I'm trying to use pipes to handle a command that requires multiple inputs, but not quite sure how to do it. Here's a snippet of what I'm trying to do. I know how to handle the first input, but I'm at lost as to piping in the second input -newstdinpass
NSTask *task = [[NSTask alloc] init];
NSPipe *pipe = [NSPipe pipe];
[task setLaunchPath: @"/bin/sh"];
[task setArguments: [NSArray arrayWithObjects: @"-c", @"/usr/bin/hdiutil chpass -oldstdinpass -newstdinpass /path/to/dmg", nil]];
[task setStandardInput:pipe];
[task launch];
[[pipe fileHandleForWriting] writeData:[@"thepassword" dataUsingEncoding:NSUTF8StringEncoding]];
[[pipe fileHandleForWriting] closeFile];
[task waitUntilExit];
[task release];
So I know using hdiutil
in this manner is a bit of a hack, but in terms of pipes, am I going about it the correct way?
Thanks.
UPDATE: In case others are wondering about this, a quick solution to my problem is to pass in a null-terminated string as Ken Thomases had pointed out below. Use [[NSString stringWithFormat:@"oldpass\0newpass\0"] dataUsingEncoding:NSUTF8StringEncoding]
into the pipe. Now, still need to learn how to bridge multiple NSTasks
with pipes...
You can create multiple NSTask
s and a bunch of NSPipe
s and hook them together, or you can use the sh -c
trick to feed a shell a command, and let it parse it and set up all the IPC.
Example :
NSTask *task;
task = [[NSTask alloc] init];
[task setLaunchPath: @"/bin/sh"];
NSArray *arguments;
arguments = [NSArray arrayWithObjects: @"-c",
@"cat /usr/share/dict/words | grep -i ham | rev | tail -5", nil];
[task setArguments: arguments];
// and then do all the other jazz for running an NSTask.
Reference : http://borkware.com/quickies/one?topic=nstask
Now, as for a "proper" command execution function, here's one I'm usually using...
Code :
/*******************************************************
*
* MAIN ROUTINE
*
*******************************************************/
- (void)runCommand:(NSString *)cmd withArgs:(NSArray *)argsArray
{
//-------------------------------
// Set up Task
//-------------------------------
if (task) { [self terminate]; }
task = [[NSTask alloc] init];
[task setLaunchPath:cmd];
[task setArguments:argsArray];
[task setStandardOutput:[NSPipe pipe]];
[task setStandardError:[task standardOutput]];
//-------------------------------
// Set up Observers
//-------------------------------
[PP_NOTIFIER removeObserver:self];
[PP_NOTIFIER addObserver:self
selector:@selector(commandSentData:)
name: NSFileHandleReadCompletionNotification
object: [[task standardOutput] fileHandleForReading]];
[PP_NOTIFIER addObserver:self
selector:@selector(taskTerminated:)
name:NSTaskDidTerminateNotification
object:nil];
//-------------------------------
// Launch
//-------------------------------
[[[task standardOutput] fileHandleForReading] readInBackgroundAndNotify];
[task launch];
}
/*******************************************************
*
* OBSERVERS
*
*******************************************************/
- (void)commandSentData:(NSNotification*)n
{
NSData* d;
d = [[n userInfo] valueForKey:NSFileHandleNotificationDataItem];
if ([d length])
{
NSString* s = [[NSString alloc] initWithData:d encoding:NSUTF8StringEncoding];
NSLog(@"Received : %@",s);
}
[[n object] readInBackgroundAndNotify];
}
- (void)taskTerminated:(NSNotification*)n
{
[task release];
task = nil;
}