[Exec Binding] Spaces in arguments (Workaround)

Because the Exec Binding simply uses the string as is in Runtime.getRuntime().exec spaces cannot be used in an argument (see below).

Use this workaround if you need them:
File /toArgs.java (edit for example with sudo vim /toArgs.java)

    import java.io.*;

    public class toArgs {
      public static void main(String[] args) throws java.io.IOException {
        StringBuilder cmnd = new StringBuilder();
        for (int i = 0; i < args.length; i++) {
          cmnd.append(args[i]);
          if (i != args.length - 1) {
            cmnd.append(" ");
          }
        }
        //System.out.println(cmnd.toString());
        
        String line;
        Process p = Runtime.getRuntime().exec(new String[] {"bash", "-c", cmnd.toString()});
        BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
        while ((line = in.readLine()) != null) {
          System.out.println(line);
        }
        in.close();
      }
    }

For windows users: replace “bash” with “cmd” and “-c” with “/c”
The compile using sudo javac /toArgs.java
In your command now prepend java -cp / toArgs

Explanation
When the exec function receives a string, it is parsed using the Tokenizer class. This class always splits at spaces, completely disregarding quotes.
For example the command wget --post-data "some data" http://example.com gets parsed into wget --post-data "some data" http://example.com (notice the quotes and the split argument). This is unwanted behavior, as quotes indicate one argument.
If parsed by bash, the command would result in wget --post-data some data http://example.com (some data is one argument, no quotes). This workaround accomplishes that by reconstructing the original string and then passing it to bash using the -c option.
With each block being one element in the arguments array.

Problems
Not really a problem, but this spawns two additional programs compared to a fix in the source (first the workaround and the bash).
I will open an issue on github.

Hopefully you do a PR too! executeCommand is also affected by this.

You could just use @@ as your argument separator instead of a space, at least for the executeCommand.

I don’t think this works… Programs normally don’t replace @@ with spaces inside arguments… Or could you please clarify how you would do this?

See the note here: https://www.openhab.org/docs/configuration/actions.html#exec-actions

Thanks, I did not know that. Sadly, if you take a look at the source, this is achieved by openHAB. The Exec binding does not provide this functionality, so this doesn’t help my case. Interesting anyways :blush:

Indeed. Hence why I said “at least for the executeCommand”. I have never looked into the exec binding, sorry.

Perhaps the binding can use the same approach as the Exec action?

1 Like

I think the parser in the binding and in the action need some improvements, so that they recognise things enclosed in single/double quotes as a single argument. Surely there’s already a code / library / someone out there that has solved this issue.

I’ll second the request for the PR. This is probably the root of a lot of user’s problems with Exec and executeCommandLine.

In many programming languages, the solve the issue by flexing around the issue. Instead of supplying a string to be parsed, you pass in an array of arguments. Then it doesn’t matter if there are spaces and whatnot.

2 Likes

Since you’re a foundation member, could you please kindly do the PR? I am not familiar with this (if PR means pull request, I’ve never done that before)…

Foundation member just means we’ve donated to the openHAB foundation.

See How to file an Issue

Also see Tutorial: Migrating OH 1 addon to OH 2: preparing (1/x) and https://www.openhab.org/docs/developer/.

I don’t know how where this code needs to go so I’d be a terrible person to try and file a PR on it.

@c.piber I opened this issue on git some time ago

https://github.com/openhab/openhab-addons/issues/6269