I want to use NSTask to simulate the Terminal to run commands. The codes as follows. It can get input in loop and return the process output.
int main(int argc, const char * argv[])
{
@autoreleasepool {
while (1) {
char str[80] = {0};
scanf("%s", str);
NSString *cmdstr = [NSString stringWithUTF8String:str];
NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObjects:@"-c", cmdstr, nil]];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
NSData *data = [[pipe fileHandleForReading] readDataToEndOfFile];
[task waitUntilExit];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", string);
}
}
My question is: when a loop is end, the running environment restore to the initialization state. For example, the default running path is /Users/apple
, and I run cd /
to change the path to /
, and then run pwd
, it return the /Users/apple
rather than the /
.
So how can I use NSTask
to simulate the Terminal completely ?
cd
andpwd
are shell built-in commands. If you execute the taskthere is no way of getting the changed working directory back to the calling process. The same problem exists if you want to set variables
MYVAR=myvalue
.You could try to parse these lines separately and update the environment. But what about multi-line commands like
You cannot emulate that by sending each line to separate
NSTask
processes.The only thing you could do is to start a single
/bin/sh
process withNSTask
, and feed all the input lines to the standard input of that process. But then you can not usereadDataToEndOfFile
to read the output, but you have to read asynchronously (using[[pipe fileHandleForReading] waitForDataInBackgroundAndNotify]
).So in short: you can simulate the Terminal only by running a (single) shell.
ADDED: Perhaps you can use the following as a starting point for your app. (I have omitted all error checking.)