Hi all,

I’ve having a bit of trouble with setting up a pseudo-TTY to communicate with 
another process. What I’m doing is setting up an incredibly basic terminal 
(NSTextView + delegate) which will be used to give commands to another process. 
It pretty much works, except that the input is echoed back along with output. 
If I disable echoing, then this does not happen, but then strangely enough 
certain aspects of the terminal stop working.

Here’s how I setup the TTY, done as a category on top of NSTask:

- (NSFileHandle *)masterSideOfPTYOrError:(NSError *__autoreleasing *)error {
        int fdMaster, fdSlave;
        int rc = openpty(&fdMaster, &fdSlave, NULL, NULL, NULL);
        if (rc != 0) {
                if (error) {
                        *error = [NSError errorWithDomain:NSPOSIXErrorDomain 
code:errno userInfo:nil];
                }
                return nil;
        }

        // Disable echoing and CR conversion
        struct termios buf = {};
        if (tcgetattr(fdMaster, &buf) < 0) {
                perror("ERROR: Cannot get terminal attributes");
                return nil;
        }

        buf.c_oflag &= ~(ONLCR);
        buf.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
        if (tcsetattr(fdMaster, TCSANOW, &buf) < 0) {
                perror("ERROR: Cannot disable terminal echo");
                return nil;
        }

        // Set the master and slave to automatically close
        fcntl(fdMaster, F_SETFD, FD_CLOEXEC);
        fcntl(fdSlave, F_SETFD, FD_CLOEXEC);
        NSFileHandle *masterHandle = [[NSFileHandle alloc] 
initWithFileDescriptor:fdMaster closeOnDealloc:YES];
        NSFileHandle *slaveHandle = [[NSFileHandle alloc] 
initWithFileDescriptor:fdSlave closeOnDealloc:YES];
        self.standardInput = slaveHandle;
        self.standardOutput = slaveHandle;
        return masterHandle;
}

This is how input is “written” to the process:

- (BOOL)textView:(NSTextView *)textView 
doCommandBySelector:(SEL)commandSelector {
        BOOL retval = NO;

        // When return is entered, record and color the newly committed text
        if (@selector(insertNewline:) == commandSelector) {
                NSUInteger textLength = [[textView string] length];
                if (textLength > committedLength) {
                        NSString *textToSubmit = [[textView string] 
substringFromIndex:committedLength];
                        [textView setSelectedRange:NSMakeRange(textLength, 0)];
                        [textView insertText:@"\n"];
                        //[textView setTextColor:[NSColor redColor] 
range:NSMakeRange(committedLength, textLength - committedLength)];
                        //[self.textView setFont:[NSFont fontWithName:@"Menlo" 
size:11]];
                        //textLength++;
                        committedLength = textLength;

                        const char *convertedInput = [textToSubmit UTF8String];
                        [self.masterHandle writeData:[NSData 
dataWithBytes:convertedInput length:strlen(convertedInput)]];
                        [self.masterHandle writeData:[NSData dataWithBytes:"\n" 
length:strlen("\n")]];
                        [self.masterHandle synchronizeFile];
                }
                retval = YES;
        }

        return retval;
}

And here’s the relevant code for reading:

text = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];

NSAttributedString *astr = [[NSAttributedString alloc] initWithString:text];
[[self.textView textStorage] appendAttributedString:astr];
[self.textView setTextColor:[NSColor whiteColor]];
[self.textView setFont:[NSFont fontWithName:@"Menlo" size:11]];

NSUInteger textLength = [[self.textView string] length];
if (textLength > committedLength) {
        if (textLength > 0) --textLength; else textLength = 0;

        textLength++;
        [self.textView setSelectedRange:NSMakeRange(textLength, 0)];
        committedLength = textLength;

        [self.textView scrollRangeToVisible:NSMakeRange([[self.textView string] 
length], 0)];
}

Here’s an example of the session when output is printed (notice the echoing):

Insane BF Interactive Console 1.0 (Dec 18 2014, 16:22:05)
Current memory size: 30000 cells, each 4 bytes
: ,
,
A
A

:
: .
.
A
:

And here’s what it shows when I disable echoing using the code above. Nothing 
else has been changed:

Insane BF Interactive Console 1.0 (Dec 18 2014, 16:22:05)
Current memory size: 30000 cells, each 4 bytes
: ,
A

:
: .


:

Any ideas?

— SevenBits

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to