Run terminal command with NSTask - objective-c

I want to run a Terminal command in my program.
The command looks like this:
cd /path/to/file/; ./foo HTTPProxy 127.0.0.1
It works with system() but it doesn't work when I use NSTask.
system("cd /path/to/file/; ./foo HTTPProxy 127.0.0.1");
works fine but
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/path/to/file/./foo"];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[task setArguments:[NSArray arrayWithObjects:#"HTTPProxy 127.0.0.1", nil]];
[task launch];
NSData *data = [file readDataToEndOfFile];
NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog(string);
doesn't.
Output:
Command-line option 'HTTPProxy 127.0.0.1' with no value. Failing.
Has anybody an idea?

Now I think I have got it:
[task setArguments:[NSArray arrayWithObjects:#"HTTPProxy", #"127.0.0.1", nil]];
those are separate arguments in your invocation from the command line...
OLD ANSWER:
You could trying setting the current directory for execution:
– setCurrentDirectoryPath:
This is basically the effect of cd in the system version of your code.

Related

How to get out put from a TOP terminal command using Obj-C?

I am trying to retrieve CPU usage of system using
top -F -R -o cpu
The command is running fine in terminal however I am not able to get the output in Objective c using the code given below:
-(NSString*)runCommand:(NSString*)commandToRun;
{
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects:
#"-c" ,
[NSString stringWithFormat:#"%#", commandToRun],
nil];
NSLog(#"run command: %#",commandToRun);
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *output;
output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
return output;
}
I am getting the empty string as a result.
Please suggest what should I do. Many thanks.
I haven't tried using top before in this way, I suspect the issue is related to top updating the output every second. In that case you could try a different top command:
top -F -R -o cpu -l 1
or use a different tool to get the data you want, like ps:
ps -vaA

Launching command using NSTask returns error

I'd like to launch the following command from my application using NSTask:
sudo -u myusername launchctl load /Library/LaunchAgents/com.google.keystone.agent.plist
Here is a code I do:
NSPipe *pipe = [NSPipe pipe];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath: #"/bin/sh"];
[task setCurrentDirectoryPath:#"/"];
[task setStandardError:pipe];
NSArray *arguments = nil;
arguments = #[#"sudo",
#"-u",
#"myusername",
#"launchctl",
#"load",
#"/Library/LaunchAgents/com.google.keystone.agent.plist"];
[task setArguments: arguments];
NSFileHandle * read = [pipe fileHandleForReading];
[task launch];
[task waitUntilExit];
NSData * dataRead = [read readDataToEndOfFile];
NSString * output = [[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding];
NSLog(#"output: %#", output);
After processing I receive an error below:
/bin/sh: sudo: No such file or directory
I've found out solution:
arguments = #[#"-c",
#"sudo -u myusername launchctl load /Library/LaunchAgents/com.google.keystone.agent.plist"];

Using NSTask to launch a Ruby script (Shenzhen)

I am trying to generate an IPA with the Shenzhen script: https://github.com/nomad/shenzhen
Here is the code I currently have:
-(void)startBuildIPAForProject:(NSString*)path
{
task = [[NSTask alloc] init];
[task setLaunchPath:#"/bin/bash"];
[task setCurrentDirectoryPath:path];
[task setArguments:#[#"ipa build",#"-c",#"Release"]];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data
encoding: NSUTF8StringEncoding];
NSLog(#"task output: %#",string);
[task waitUntilExit];
}
When executing [task launch] I get the following output from the console:
/bin/bash: ipa build: No such file or directory
When I use the regular terminal ipa build is working (that is, it tells me there exists no Xcode project in the current dir)
I'm a bit lost, so any help is greatly appreciated.
The ipa script will need to be in your application's PATH environment variable (or in the same directory as your binary.) An easy fix would be to specify the full, absolute path to ipa in your arguments. i.e. change:
[task setArguments:#[#"ipa build",#"-c",#"Release"]];
to
[task setArguments:#[#"/full/path/to/ipa build",#"-c",#"Release"]];

Executing a command from Objective C

I want to execute a command from objective C (Cocoa framework). The command I am trying is as below. I tried with NSTask but it says "launch path not accessible" when I execute it.
sudo ifconfig en0 down
My code is:
- (void)testme {
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: #"sudo ifconfig en0 down"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: #"foo", #"bar.txt", nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *string;
string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"command returned:\n%#", string);
[string release];
[task release];
}
sudo ifconfig en0 down is not a sensible launch path. The correct launch path for this command would be /usr/sbin/sudo.
Once that is done, you still need to pass the correct arguments to setArguments:. foo and bar.txt look like example code that you copied without reading.
MORE IMPORTANTLY, THOUGH, running sudo from NSTask will not work. You will need to use Authorization Services to launch a privileged command.
You need to specify the full executable path and you should specify the arguments as the arguments, not along with the launch path. NSTask ain't a shell, it internally uses syscalls (execv(), I guess) to invoke the command.
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:#"/usr/bin/sudo"];
NSArray *arguments = #[#"ifconfig", #"en0", #"down"];
[task setArguments:arguments];

Call shell script with argument in Mac application

I'm having trouble calling a shell script which takes an argument from my Cocoa application for Mac.
I have created the shell script, and put it in the app's local repository. It is called SCRIPT. It takes one argument which is a URL address.
I call the script as follows but nothing happens, no errors or messages, just the script stops after doing nothing.
NSString *address = [_addressField stringValue];
NSString *resPath = [[NSBundle mainBundle] resourcePath];
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: [NSString stringWithFormat:#"%#/SCRIPT", resPath]];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: address, nil];
[task setArguments: arguments];
NSPipe *pipe;
pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
NSFileHandle *file;
file = [pipe fileHandleForReading];
[task launch];
NSData *data;
data = [file readDataToEndOfFile];
NSString *status;
status = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
NSLog (#"%#", status);
Thanks in advance everyone
The Objective-C code seams to work fine for me if i try with /bin/echo as launch path. So i guess the problem is with the script. Can you include the script in your question? note that the environment when running from a Cocoa application is probably quite different from when running in a interactive shell.
Could it be a permissions issue? Try invoking /bin/sh and setting the script path as the first argument.