Re: NSTask troubles
Re: NSTask troubles
- Subject: Re: NSTask troubles
- From: Chris Suter <email@hidden>
- Date: Fri, 13 Jul 2007 13:35:06 +1000
OK, I've nailed it, but what a pain in the ass! forkpty isn't
documented well anywhere that I could find (on the web at least).
I presume you looked at the man page for forkpty.
And in its default state, the pseudo-TTY has all sorts of
undesirable behaviors like echoing, and \n becoming \r\n.
I was in the process of responding to your earlier post. I was going
to say that I think you've got confused about what slave FD and
master FD means. You should have set both stdin and stdout for the
task to the slave FD and then handled input and output to the task
via the master FD. To turn off the echo, passing in a zeroed termios
structure would probably suffice.
The following appears to work:
#include <Cocoa/Cocoa.h>
#include <stdlib.h>
#include <util.h>
#include <stdio.h>
#include <string.h>
#include <sys/errno.h>
#include <unistd.h>
@interface NSTask (PseudoTTY)
- (int)usePseudoTTY;
@end
@implementation NSTask (PseudoTTY)
- (int)usePseudoTTY
{
int masterFD, slaveFD;
struct termios t;
bzero (&t, sizeof (t));
if (openpty (&masterFD, &slaveFD, NULL, &t, NULL)) {
fprintf (stderr, "openpty failed %d: %s\n", errno, strerror
(errno));
return -1;
}
[self setStandardOutput:[[[NSFileHandle alloc]
initWithFileDescriptor:slaveFD] autorelease]];
[self setStandardInput:[[[NSFileHandle alloc]
initWithFileDescriptor:slaveFD] autorelease]];
return masterFD;
}
@end
int main (int argc __attribute__ ((__unused__)),
char *argv[] __attribute__ ((__unused__)))
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSTask *atosTask = [[NSTask alloc] init];
[atosTask setLaunchPath:@"/usr/bin/atos"];
[atosTask setArguments:[NSArray arrayWithObjects:
@"-o",
@"test-term",
NULL]];
int masterFD = [atosTask usePseudoTTY];
[atosTask launch];
assert (write (masterFD, "1234567890\n", 11) == 11);
char buffer[1024];
for (;;) {
ssize_t amount_read = read (masterFD, buffer, sizeof (buffer));
if (amount_read < 0) {
fprintf (stderr, "error %d %s", errno, strerror (errno));
return -1;
}
if (!amount_read)
return 0;
write (STDOUT_FILENO, buffer, amount_read);
}
[pool release];
// fail gracefully
return 0;
}
One thing you could do is create a pipe for input into your task thus
bypassing the terminal and avoiding any issues with echo. I'm no
expert on any of this so I might be wrong.
- Chris
Attachment:
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden