Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

executing shell command with | (pipe) using NSTask

I'm trying to execute this comamnd ps -ef | grep test using NSTask but I can't get the | grep test to be included in the NSTask:

This is what I'm using currently to get the output of ps -ef into a string then I need to somehow get the pid of the process test

NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/ps"];

NSArray *arguments;
arguments = [NSArray arrayWithObjects: @"-ef", 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 (@"got\n%@", string);
like image 363
ed1t Avatar asked Jul 22 '11 03:07

ed1t


1 Answers

Piping is a feature provided by shells, such as /bin/sh. You may try launching your command via such a shell:

/* ... */
[task setLaunchPath: @"/bin/sh"];
/* ... */
arguments = [NSArray arrayWithObjects: @"-c", @"ps -ef | grep test", nil];

However, if you let the user supply a value (instead of hard-coding e.g. test), you are making the program susceptible to shell injection attacks, which are kind of like SQL injection. An alternative, which doesn't suffer from this problem, is to use a pipe object to connect the standard output of ps with the standard input of grep:

NSTask *psTask = [[NSTask alloc] init];
NSTask *grepTask = [[NSTask alloc] init];

[psTask setLaunchPath: @"/bin/ps"];
[grepTask setLaunchPath: @"/bin/grep"];

[psTask setArguments: [NSArray arrayWithObjects: @"-ef", nil]];
[grepTask setArguments: [NSArray arrayWithObjects: @"test", nil]];

/* ps ==> grep */
NSPipe *pipeBetween = [NSPipe pipe];
[psTask setStandardOutput: pipeBetween];
[grepTask setStandardInput: pipeBetween];

/* grep ==> me */
NSPipe *pipeToMe = [NSPipe pipe];
[grepTask setStandardOutput: pipeToMe];

NSFileHandle *grepOutput = [pipeToMe fileHandleForReading];

[psTask launch];
[grepTask launch];

NSData *data = [grepOutput readDataToEndOfFile];

/* etc. */

This uses built-in Foundation functionality to perform the same steps as the shell does when it encounters the | character.

Finally as others have pointed out, the usage of grep is overkill. Just add this to your code:

NSArray *lines = [string componentsSeparatedByString:@"\n"];
NSArray *filteredLines = [lines filteredArrayUsingPredicate: [NSPredicate predicateWithFormat: @"SELF contains[c] 'test'"]];
like image 61
RavuAlHemio Avatar answered Oct 13 '22 00:10

RavuAlHemio