diff -crN --exclude=CVS src/Lib/pty.py src-openpty/Lib/pty.py *** src/Lib/pty.py Fri Feb 4 16:10:34 2000 --- src-openpty/Lib/pty.py Mon Jun 26 21:02:08 2000 *************** *** 16,24 **** CHILD = 0 def master_open(): """Open pty master and return (master_fd, tty_name). ! SGI and Linux/BSD version.""" try: import sgi except ImportError: --- 16,52 ---- CHILD = 0 + def openpty(): + """openpty() -> (master_fd, slave_fd) + Open a pty master/slave pair, using os.openpty() if possible.""" + + try: + return os.openpty() + except (AttributeError, OSError): + pass + master_fd, slave_name = _open_terminal() + slave_fd = _slave_open(slave_name) + return master_fd, slave_fd + def master_open(): + """master_open() -> (master_fd, slave_name) + Open a pty master and return the fd, and the filename of the slave end. + Deprecated, use openpty() instead.""" + + try: + master_fd, slave_fd = os.openpty() + except (AttributeError, OSError): + pass + else: + slave_name = os.ttyname(slave_fd) + os.close(slave_fd) + return master_fd, slave_name + + return _open_terminal() + + def _open_terminal(): """Open pty master and return (master_fd, tty_name). ! SGI and generic BSD version, for when openpty() fails.""" try: import sgi except ImportError: *************** *** 40,61 **** raise os.error, 'out of pty devices' def slave_open(tty_name): ! """Open the pty slave and acquire the controlling terminal. ! Return the file descriptor. Linux version.""" ! # (Should be universal? --Guido) return os.open(tty_name, FCNTL.O_RDWR) def fork(): ! """Fork and make the child a session leader with a controlling terminal. ! Return (pid, master_fd).""" ! master_fd, tty_name = master_open() pid = os.fork() if pid == CHILD: # Establish a new session. os.setsid() - - # Acquire controlling terminal. - slave_fd = slave_open(tty_name) os.close(master_fd) # Slave becomes stdin/stdout/stderr of child. --- 68,102 ---- raise os.error, 'out of pty devices' def slave_open(tty_name): ! """slave_open(tty_name) -> slave_fd ! Open the pty slave and acquire the controlling terminal, returning ! opened filedescriptor. ! Deprecated, use openpty() instead.""" ! return os.open(tty_name, FCNTL.O_RDWR) def fork(): ! """fork() -> (pid, master_fd) ! Fork and make the child a session leader with a controlling terminal.""" ! ! try: ! pid, fd = os.forkpty() ! except (AttributeError, OSError): ! pass ! else: ! if pid == CHILD: ! try: ! os.setsid() ! except OSError: ! # os.forkpty() already set us session leader ! pass ! return pid, fd ! ! master_fd, slave_fd = openpty() pid = os.fork() if pid == CHILD: # Establish a new session. os.setsid() os.close(master_fd) # Slave becomes stdin/stdout/stderr of child. *************** *** 68,84 **** # Parent and child process. return pid, master_fd ! def writen(fd, data): """Write all the data to a descriptor.""" while data != '': n = os.write(fd, data) data = data[n:] ! def read(fd): """Default read function.""" return os.read(fd, 1024) ! def copy(master_fd, master_read=read, stdin_read=read): """Parent copy loop. Copies pty master -> standard output (master_read) --- 109,125 ---- # Parent and child process. return pid, master_fd ! def _writen(fd, data): """Write all the data to a descriptor.""" while data != '': n = os.write(fd, data) data = data[n:] ! def _read(fd): """Default read function.""" return os.read(fd, 1024) ! def _copy(master_fd, master_read=_read, stdin_read=_read): """Parent copy loop. Copies pty master -> standard output (master_read) *************** *** 91,99 **** os.write(STDOUT_FILENO, data) if STDIN_FILENO in rfds: data = stdin_read(STDIN_FILENO) ! writen(master_fd, data) ! def spawn(argv, master_read=read, stdin_read=read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv,) --- 132,140 ---- os.write(STDOUT_FILENO, data) if STDIN_FILENO in rfds: data = stdin_read(STDIN_FILENO) ! _writen(master_fd, data) ! def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv,) *************** *** 103,108 **** mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) try: ! copy(master_fd, master_read, stdin_read) except: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) --- 144,149 ---- mode = tty.tcgetattr(STDIN_FILENO) tty.setraw(STDIN_FILENO) try: ! _copy(master_fd, master_read, stdin_read) except: tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode) diff -crN --exclude=CVS src/Modules/posixmodule.c src-openpty/Modules/posixmodule.c *** src/Modules/posixmodule.c Tue Jun 6 22:52:17 2000 --- src-openpty/Modules/posixmodule.c Mon Jun 26 21:02:09 2000 *************** *** 1731,1736 **** --- 1731,1794 ---- } #endif + #if defined(HAVE_OPENPTY) || defined(HAVE_FORKPTY) + #ifdef HAVE_PTY_H + #include + #else + #ifdef HAVE_LIBUTIL_H + #include + #else + /* BSDI does not supply a prototype for the 'openpty' and 'forkpty' + functions, eventhough they are included in libutil. */ + #include + extern int openpty(int *, int *, char *, struct termios *, struct winsize *); + extern int forkpty(int *, char *, struct termios *, struct winsize *); + #endif /* HAVE_LIBUTIL_H */ + #endif /* HAVE_PTY_H */ + #endif /* defined(HAVE_OPENPTY) or defined(HAVE_FORKPTY) */ + + #ifdef HAVE_OPENPTY + static char posix_openpty__doc__[] = + "openpty() -> (master_fd, slave_fd)\n\ + Open a pseudo-terminal, returning open fd's for both master and slave end.\n"; + + static PyObject * + posix_openpty(self, args) + PyObject *self; + PyObject *args; + { + int master_fd, slave_fd; + if (!PyArg_ParseTuple(args, ":openpty")) + return NULL; + if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL) != 0) + return posix_error(); + return Py_BuildValue("(ii)", master_fd, slave_fd); + } + #endif + + #ifdef HAVE_FORKPTY + static char posix_forkpty__doc__[] = + "forkpty() -> (pid, master_fd)\n\ + Fork a new process with a new pseudo-terminal as controlling tty.\n\n\ + Like fork(), return 0 as pid to child process, and PID of child to parent.\n\ + To both, return fd of newly opened pseudo-terminal.\n"; + + static PyObject * + posix_forkpty(self, args) + PyObject *self; + PyObject *args; + { + int master_fd, pid; + + if (!PyArg_ParseTuple(args, ":forkpty")) + return NULL; + pid = forkpty(&master_fd, NULL, NULL, NULL); + if (pid == -1) + return posix_error(); + PyOS_AfterFork(); + return Py_BuildValue("(ii)", pid, master_fd); + } + #endif #ifdef HAVE_GETEGID static char posix_getegid__doc__[] = *************** *** 4514,4519 **** --- 4572,4583 ---- #ifdef HAVE_FORK {"fork", posix_fork, METH_VARARGS, posix_fork__doc__}, #endif /* HAVE_FORK */ + #ifdef HAVE_OPENPTY + {"openpty", posix_openpty, METH_VARARGS, posix_openpty__doc__}, + #endif /* HAVE_OPENPTY */ + #ifdef HAVE_FORKPTY + {"forkpty", posix_forkpty, METH_VARARGS, posix_forkpty__doc__}, + #endif /* HAVE_FORKPTY */ #ifdef HAVE_GETEGID {"getegid", posix_getegid, METH_VARARGS, posix_getegid__doc__}, #endif /* HAVE_GETEGID */ diff -crN --exclude=CVS src/configure.in src-openpty/configure.in *** src/configure.in Sun Jun 18 16:54:13 2000 --- src-openpty/configure.in Mon Jun 26 21:01:52 2000 *************** *** 357,363 **** signal.h stdarg.h stddef.h stdlib.h thread.h unistd.h utime.h \ sys/audioio.h sys/file.h sys/lock.h \ sys/param.h sys/select.h sys/socket.h sys/time.h sys/times.h \ ! sys/un.h sys/utsname.h sys/wait.h) AC_HEADER_DIRENT # checks for typedefs --- 357,363 ---- signal.h stdarg.h stddef.h stdlib.h thread.h unistd.h utime.h \ sys/audioio.h sys/file.h sys/lock.h \ sys/param.h sys/select.h sys/socket.h sys/time.h sys/times.h \ ! sys/un.h sys/utsname.h sys/wait.h pty.h libutil.h) AC_HEADER_DIRENT # checks for typedefs *************** *** 770,775 **** --- 770,780 ---- sigaction siginterrupt sigrelse strftime strptime symlink sysconf \ tcgetpgrp tcsetpgrp tempnam timegm times tmpfile tmpnam tmpnam_r \ truncate uname waitpid) + + # check for openpty and forkpty + + AC_CHECK_FUNCS(openpty,, AC_CHECK_LIB(util,openpty, [AC_DEFINE(HAVE_OPENPTY)] [LIBS="$LIBS -lutil"])) + AC_CHECK_FUNCS(forkpty,, AC_CHECK_LIB(util,forkpty, [AC_DEFINE(HAVE_FORKPTY)] [LIBS="$LIBS -lutil"])) # check for long file support functions AC_CHECK_FUNCS(fseek64 fseeko fstatvfs ftell64 ftello statvfs)