Reputation: 1216
I am trying to use NSTask to execute terminal commands using the standardInput and standardOutput. Everything works for commands like ls, pwd, etc. But When I try to run cd command, Standard output doesn't write any output. I understand that standardOutput won't write any data since cd command doesn't have any response to display. But Is there anyway to check if the command has run successfully? I need this as I am waiting for a response to update the UI. Below is my code. I am using NSFileHandleDataAvailableNotification to read the output as this helps with commands like ping
-(void)setupTask {
@autoreleasepool {
// Commands are read from standard input:
NSFileHandle *input = [NSFileHandle fileHandleWithStandardInput];
NSPipe *inPipe = [NSPipe new]; // pipe for shell input
NSPipe *outPipe = [NSPipe new]; // pipe for shell output
NSPipe *errorPipe = [NSPipe new];
task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setStandardInput:inPipe];
[task setStandardOutput:outPipe];
[task setStandardError:errorPipe];
[task launch];
// Wait for standard input ...
[input waitForDataInBackgroundAndNotify];
// ... and wait for shell output.
[[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
[[errorPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
// Wait asynchronously for standard input.
// The block is executed as soon as some data is available on standard input.
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:input queue: [NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note)
{
NSData *inData = [input availableData];
if ([inData length] == 0) {
// EOF on standard input.
[[inPipe fileHandleForWriting] closeFile];
} else {
// Read from standard input and write to shell input pipe.
[[inPipe fileHandleForWriting] writeData:inData];
// Continue waiting for standard input.
[input waitForDataInBackgroundAndNotify];
}
}];
// Wait asynchronously for shell output.
// The block is executed as soon as some data is available on the shell output pipe.
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:[outPipe fileHandleForReading] queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note)
{
// Read from shell output
NSData *outData = [[outPipe fileHandleForReading] availableData];
if ([outData length] > 0) {
NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
NSLog(@"Output: %@", outStr);
}
// Continue waiting for shell output.
[[outPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
}];
[[NSNotificationCenter defaultCenter] addObserverForName:NSFileHandleDataAvailableNotification
object:[errorPipe fileHandleForReading] queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification *note)
{
// Read from shell output
NSData *outData = [[errorPipe fileHandleForReading] availableData];
if ([outData length] > 0) {
NSString *outStr = [[NSString alloc] initWithData:outData encoding:NSUTF8StringEncoding];
NSLog(@"Error: %@", outStr);
}
// Continue waiting for shell output.
[[errorPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
}];
}
}
-(void)executeCommand:(NSString*)command {
NSData* data = [command dataUsingEncoding:NSUTF8StringEncoding];
NSError* error;
[[[task standardInput] fileHandleForWriting] writeData:data error:&error];
if (error != NULL) {
NSLog(@"%@", [error localizedDescription]);
}
NSData* newLine = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
[[[task standardInput] fileHandleForWriting] writeData:newLine error:&error];
if (error != NULL) {
NSLog(@"%@", [error localizedDescription]);
}
}
-(void)runCommand {
[self setupTask];
[self executeCommand:@"cd Users"];
}
Upvotes: 0
Views: 59