Pseudo terminal support added

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@8977 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2001-02-05 09:28:19 +00:00
parent 86fc747a2c
commit 02ebb24e52
8 changed files with 752 additions and 512 deletions

View file

@ -1,3 +1,8 @@
2001-02-04 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSTask.m: Added gnustep specific feature to run task in
pseudo terminal.
2001-02-02 Richard Frith-Macdonald <rfm@gnu.org>
Integrated patch for unicode support for ([-initWithFormat:]) by

View file

@ -85,6 +85,10 @@
- (void) launch;
- (void) terminate;
- (void) waitUntilExit;
#ifndef NO_GNUSTEP
- (BOOL) usePseudoTerminal;
#endif
@end
GS_EXPORT NSString* NSTaskDidTerminateNotification;

View file

@ -236,3 +236,34 @@
/* Define if you have the iconv library (-liconv). */
#undef HAVE_LIBICONV
/* Define if you have sysv style pseudo-terminals. */
#undef HAVE_GRANTPT
/* Define if you need sysv stream modules. */
#undef HAVE_PTS_STREAM_MODULES
/* Define if you have the setsid function. */
#undef HAVE_SETSID
/* Define if you have the waitpid function. */
#undef HAVE_WAITPID
/* Define if you have the <signal.h> header file. */
#undef HAVE_SIGNAL_H
/* Define if you have the <sys/file.h> header file. */
#undef HAVE_SYS_FILE_H
/* Define if you have the <sys/fcntl.h> header file. */
#undef HAVE_SYS_FCNTL_H
/* Define if you have the <sys/ioctl.h> header file. */
#undef HAVE_SYS_IOCTL_H
/* Define if you have the <sys/wait.h> header file. */
#undef HAVE_SYS_WAIT_H
/* Define if you have the <sys/stropts.h> header file. */
#undef HAVE_SYS_STROPTS_H

View file

@ -2169,8 +2169,19 @@ transmute(ivars self, NSString *aString)
NSRange aRange;
NSString *t;
t = (NSString*)NSAllocateObject(NSStringClass, 0, NSDefaultMallocZone());
/*
* Get the abstract class to give us the default placeholder string.
*/
t = (NSString*)[NSStringClass allocWithZone: NSDefaultMallocZone()];
/*
* Now initialise with the format information ... the placeholder
* can decide whether to create a concrete C string or unicode string.
*/
t = [t initWithFormat: format arguments: ap];
/*
* Now append the created string to this one ... the appending
* method will make this string wide if necessary.
*/
aRange.location = _count;
aRange.length = 0;
[self replaceCharactersInRange: aRange withString: t];

View file

@ -81,9 +81,122 @@ static void handleSignal(int sig)
#else
@interface NSConcreteUnixTask : NSTask
{
char slave_name[32];
BOOL usePseudoTerminal;
}
@end
#define NSConcreteTask NSConcreteUnixTask
#if HAVE_SIGNAL_H
#include <signal.h>
#endif
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#if HAVE_SYS_FCNTL_H
#include <sys/fcntl.h>
#endif
#if HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
/*
* If we are on a streams based system, we need to include stropts.h
* for definitions needed to set up slave pseudo-terminal stream.
*/
#if HAVE_SYS_STROPTS_H
#include <sys/stropts.h>
#endif
#ifndef MAX_OPEN
#define MAX_OPEN 64
#endif
static int
pty_master(char* name, int len)
{
int master;
/*
* If we have grantpt(), assume we are using sysv-style pseudo-terminals,
* otherwise assume bsd style.
*/
#if HAVE_GRANTPT
master = open("/dev/ptmx", O_RDWR);
if (master >= 0)
{
const char *slave;
grantpt(master); /* Change permission of slave. */
unlockpt(master); /* Unlock slave. */
slave = (const char*)ptsname(master);
if (slave == 0 || strlen(slave) >= len)
{
close(master);
master = -1;
}
else
{
strcpy(name, (char*)slave);
}
}
else
#endif
{
const char *groups = "pqrstuvwxyzPQRSTUVWXYZ";
master = -1;
if (len > 10)
{
strcpy(name, "/dev/ptyXX");
while (master < 0 && *groups != '\0')
{
int i;
name[8] = *groups++;
for (i = 0; i < 16; i++)
{
name[9] = "0123456789abcdef"[i];
master = open(name, O_RDWR);
if (master >= 0)
{
name[5] = 't';
break;
}
}
}
}
}
return master;
}
static int
pty_slave(const char* name)
{
int slave;
slave = open(name, O_RDWR);
#if HAVE_SYS_STROPTS_H
#if HAVE_PTS_STREAM_MODULES
if (slave >= 0 && isastream(slave))
{
if (ioctl(slave, I_PUSH, "ptem") < 0)
{
perror("unable to push 'ptem' streams module");
}
else if (ioctl(slave, I_PUSH, "ldterm") < 0)
{
perror("unable to push 'ldterm' streams module");
}
}
#endif
#endif
return slave;
}
#endif
@interface NSTask (Private)
@ -388,6 +501,11 @@ static void handleSignal(int sig)
#endif
}
- (BOOL) usePseudoTerminal
{
return NO;
}
- (void) waitUntilExit
{
while ([self isRunning])
@ -561,13 +679,13 @@ GSCheckTasks()
- (void) launch
{
STARTUPINFO start_info;
STARTUPINFO start_info;
NSString *lpath;
NSString *arg;
NSEnumerator *arg_enum;
NSMutableString *args;
char *c_args;
int result;
char *c_args;
int result;
if (_hasLaunched)
{
@ -627,8 +745,8 @@ GSCheckTasks()
- (int) terminationStatus
{
DWORD exit_code;
int result;
DWORD exit_code;
int result;
[super terminationStatus];
result = GetExitCodeProcess(proc_info.hProcess, &exit_code);
@ -815,24 +933,69 @@ GSCheckTasks()
#endif
#endif
/*
* Set up stdin, stdout and stderr by duplicating descriptors as
* necessary and closing the originals (to ensure we won't have a
* pipe left with two write descriptors etc).
*/
if (idesc != 0)
if (usePseudoTerminal == YES)
{
dup2(idesc, 0);
int s;
s = pty_slave(slave_name);
if (s < 0)
{
exit(1); /* Failed to open slave! */
}
#if HAVE_SETSID
i = setsid();
#endif
#if TIOCNOTTY
i = open("/dev/tty", O_RDWR);
if (i >= 0)
{
(void)ioctl(i, TIOCNOTTY, 0);
(void)close(i);
}
#endif
/*
* Set up stdin, stdout and stderr by duplicating descriptors as
* necessary and closing the originals (to ensure we won't have a
* pipe left with two write descriptors etc).
*/
if (s != 0)
{
dup2(s, 0);
}
if (s != 1)
{
dup2(s, 1);
}
if (s != 2)
{
dup2(s, 2);
}
}
if (odesc != 1)
else
{
dup2(odesc, 1);
}
if (edesc != 2)
{
dup2(edesc, 2);
/*
* Set up stdin, stdout and stderr by duplicating descriptors as
* necessary and closing the originals (to ensure we won't have a
* pipe left with two write descriptors etc).
*/
if (idesc != 0)
{
dup2(idesc, 0);
}
if (odesc != 1)
{
dup2(odesc, 1);
}
if (edesc != 2)
{
dup2(edesc, 2);
}
}
/*
* Close any extra descriptors.
*/
for (i = 3; i < NOFILE; i++)
{
(void) close(i);
@ -902,5 +1065,37 @@ GSCheckTasks()
}
}
- (BOOL) usePseudoTerminal
{
int master;
NSFileHandle *fh;
if (usePseudoTerminal == YES)
{
return YES;
}
master = pty_master(slave_name, sizeof(slave_name));
if (master < 0)
{
return NO;
}
fh = [[NSFileHandle alloc] initWithFileDescriptor: master
closeOnDealloc: YES];
[self setStandardInput: fh];
RELEASE(fh);
master = dup(master);
fh = [[NSFileHandle alloc] initWithFileDescriptor: master
closeOnDealloc: YES];
[self setStandardOutput: fh];
RELEASE(fh);
master = dup(master);
fh = [[NSFileHandle alloc] initWithFileDescriptor: master
closeOnDealloc: YES];
[self setStandardError: fh];
RELEASE(fh);
usePseudoTerminal = YES;
return YES;
}
@end
#endif /* !MINGW */

View file

@ -8,6 +8,7 @@ main()
id pool;
NSDictionary *env;
NSTask *task;
NSData *d;
pool = [[NSAutoreleasePool alloc] init];
@ -29,7 +30,12 @@ main()
[task setEnvironment: env];
[task setLaunchPath: @"/bin/sh"];
[task setArguments: [NSArray arrayWithObjects: @"-c", @"echo $PATH", nil]];
if ([task usePseudoTerminal] == NO)
printf("Argh - unable to use pseudo terminal\n");
[task launch];
d = [[task standardOutput] availableData];
NSLog(@"Got PATH of '%*s'", [d length], [d bytes]);
[task waitUntilExit];
[task release];
[pool release];

963
configure vendored

File diff suppressed because it is too large Load diff

View file

@ -578,6 +578,17 @@ AC_CHECK_FUNCS(inet_aton)
AC_CHECK_FUNCS(killpg setpgrp setpgid)
AC_FUNC_SETPGRP
HAVE_PTS_STREAM_MODULES=0
case "${target}" in
*-sysv-*)
HAVE_PTS_STREAM_MODULES=1
;;
esac
AC_DEFINE_UNQUOTED(HAVE_PTS_STREAM_MODULES, $HAVE_PTS_STREAM_MODULES)
AC_SUBST(HAVE_PTS_STREAM_MODULES)
AC_CHECK_HEADERS(libc.h limits.h malloc.h memory.h string.h signal.h sys/file.h sys/fcntl.h sys/ioctl.h sys/stropts.h unistd.h utime.h libguile.h)
#--------------------------------------------------------------------
# This function needed by NSThread.m
#--------------------------------------------------------------------