Sepehrom
Sepehrom

Reputation: 1335

Cannot Pass Argument to /bin/sh

I'm writing a command line helper for one of my cocoa apps. This helper tool is supposed to execute an instance of shell ( /bin/sh ) using NSTask. As you all know it's possible to execute sh taking advantage of -c, you can pass one or more command as an argument to be executed.

For example running /bin/sh -c "networksetup -setwebproxystate Wi-Fi on"

executes networksetup -setwebproxystate Wi-Fi on .

Now, Here's the question :

When I set the launch path to sh ( [task setLaunchPath:@"/bin/sh"] ) , and then set Arguments as following :

cmd = "-c,\\\"networksetup\\_-setwebproxystate\\_Wi-Fi\\_on\\\"";
stringArguments = [NSMutableString stringWithFormat:@"%s", cmd.c_str()];
stringArguments = [[stringArguments stringByReplacingOccurrencesOfString:@"_" withString:@" "] mutableCopy];
arguments = [stringArguments componentsSeparatedByString:@","];        
[task setArguments:arguments];

I see that somehow -c argument is skipped, because I get the following error :

/bin/sh: "networksetup -setwebproxystate Wi-Fi on": command not found

and that's because "networksetup -setwebproxystate Wi-Fi on" is executed directly not as an argument after sh -c.

I know I couldn't explain in the clearest way possible, but hope I could deliver what I meant.

I tried almost everything came to my mind, but I'm stuck with this. Any suggestions is really appreciated.

Upvotes: 0

Views: 653

Answers (2)

CRD
CRD

Reputation: 53000

When entering a command at the shell prompt double-quotes are used to pass a string as a single argument when it would otherwise be passed as multiple arguments. When using NSTask (or function/system calls in the exec family) you pass each argument individually, the shell does not need to parse a command line, and so double quotes are not required. The following fragment:

NSTask *task = [NSTask new];

[task setLaunchPath:@"/bin/sh"];

[task setArguments:@[@"-c", @"networksetup -setwebproxystate Wi-Fi on"]];

[task launch];

will do the task you want. The two arguments are passed using a literal array expression, each argument is just a string and may contain spaces etc.

HTH

Upvotes: 0

Jeff Laing
Jeff Laing

Reputation: 923

The problem is in your amazingly convoluted way of specifying the command string. NSTask does not need quotes around the arguments. You are ending up with arguments containing this:

[0] ==> -c

[1] ==> "networksetup -setwebproxystate Wi-Fi on"

Note the double-quotes. Why not just use

 arguments = [NSArray arrayWithObjects:
    @"-c",
    @"networksetup -setwebproxystate Wi-Fi on",
    nil ];

Upvotes: 2

Related Questions