From 398b4a2fbb96894d12bf9a63b5ec49d0e75b530e Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Mon, 19 Apr 2004 15:07:30 +0000 Subject: [PATCH] Add pty support to proc_open() for systems with Unix98 ptys. # With permission from Andi --- configure.in | 6 +++ ext/standard/proc_open.c | 109 ++++++++++++++++++++++++++++++++------- 2 files changed, 97 insertions(+), 18 deletions(-) diff --git a/configure.in b/configure.in index edb768e089..5190f9d64f 100644 --- a/configure.in +++ b/configure.in @@ -351,6 +351,7 @@ stdlib.h \ string.h \ syslog.h \ sysexits.h \ +sys/ioctl.h \ sys/file.h \ sys/mman.h \ sys/mount.h \ @@ -364,6 +365,7 @@ sys/vfs.h \ sys/sysexits.h \ sys/varargs.h \ sys/wait.h \ +termios.h \ unistd.h \ unix.h \ utime.h \ @@ -479,6 +481,7 @@ getservbyport \ getrusage \ gettimeofday \ gmtime_r \ +grantpt \ inet_ntoa \ inet_ntop \ inet_pton \ @@ -494,6 +497,7 @@ mmap \ nl_langinfo \ perror \ poll \ +ptsname \ putenv \ realpath \ random \ @@ -504,6 +508,7 @@ scandir \ setitimer \ setlocale \ localeconv \ +setpgid \ setsockopt \ setvbuf \ shutdown \ @@ -524,6 +529,7 @@ strtok_r \ symlink \ tempnam \ tzset \ +unlockpt \ unsetenv \ usleep \ nanosleep \ diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 9bb4db1aa5..126f712376 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -17,8 +17,11 @@ */ /* $Id$ */ -#include +#define _XOPEN_SOURCE +#define _BSD_SOURCE + #include "php.h" +#include #include #include "php_string.h" #include "safe_mode.h" @@ -35,9 +38,6 @@ #include #endif -#if HAVE_SYS_TYPES_H -#include -#endif #if HAVE_SYS_STAT_H #include #endif @@ -52,6 +52,13 @@ * */ #ifdef PHP_CAN_SUPPORT_PROC_OPEN + +#if HAVE_PTSNAME && HAVE_GRANTPT && HAVE_UNLOCKPT && HAVE_SYS_IOCTL_H && HAVE_TERMIOS_H +# define PHP_CAN_DO_PTS 1 +# include +# include +#endif + #include "proc_open.h" static int le_proc_open; @@ -472,6 +479,10 @@ PHP_FUNCTION(proc_open) struct php_process_handle *proc; int is_persistent = 0; /* TODO: ensure that persistent procs will work */ int suppress_errors = 0; +#if PHP_CAN_DO_PTS + php_file_descriptor_t dev_ptmx = -1; /* master */ + php_file_descriptor_t slave_pty = -1; +#endif if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "saz|s!a!a!", &command, &command_len, &descriptorspec, &pipes, &cwd, &cwd_len, &environment, @@ -640,7 +651,32 @@ PHP_FUNCTION(proc_open) #else descriptors[ndesc].childend = fd; #endif + } else if (strcmp(Z_STRVAL_PP(ztype), "pty") == 0) { +#if PHP_CAN_DO_PTS + if (dev_ptmx == -1) { + /* open things up */ + dev_ptmx = open("/dev/ptmx", O_RDWR); + if (dev_ptmx == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to open /dev/ptmx, errno %d", errno); + goto exit_fail; + } + grantpt(dev_ptmx); + unlockpt(dev_ptmx); + slave_pty = open(ptsname(dev_ptmx), O_RDWR); + if (slave_pty == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to open slave pty, errno %d", errno); + goto exit_fail; + } + } + descriptors[ndesc].mode = DESC_PIPE; + descriptors[ndesc].childend = dup(slave_pty); + descriptors[ndesc].parentend = dup(dev_ptmx); + descriptors[ndesc].mode_flags = O_RDWR; +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, "pty pseudo terminal is not support on this system"); + goto exit_fail; +#endif } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a valid descriptor spec/mode", Z_STRVAL_PP(ztype)); goto exit_fail; @@ -709,6 +745,18 @@ PHP_FUNCTION(proc_open) if (child == 0) { /* this is the child process */ +#if PHP_CAN_DO_PTS + if (dev_ptmx >= 0) { + int my_pid = getpid(); + + /* detach from original tty. Might only need this if isatty(0) is true */ + ioctl(0,TIOCNOTTY,NULL); + /* become process group leader */ + setpgid(my_pid, my_pid); + tcsetpgrp(0, my_pid); + } +#endif + /* close those descriptors that we just opened for the parent stuff, * dup new descriptors into required descriptors and close the original * cruft */ @@ -723,6 +771,14 @@ PHP_FUNCTION(proc_open) if (descriptors[i].childend != descriptors[i].index) close(descriptors[i].childend); } + +#if PHP_CAN_DO_PTS + if (dev_ptmx >= 0) { + close(dev_ptmx); + close(slave_pty); + } +#endif + if (cwd) { chdir(cwd); } @@ -765,12 +821,18 @@ PHP_FUNCTION(proc_open) } array_init(pipes); +#if PHP_CAN_DO_PTS + if (dev_ptmx >= 0) { + close(dev_ptmx); + close(slave_pty); + } +#endif + /* clean up all the child ends and then open streams on the parent * ends, where appropriate */ for (i = 0; i < ndesc; i++) { - FILE *fp; char *mode_string=NULL; - php_stream *stream; + php_stream *stream = NULL; close_descriptor(descriptors[i].childend); @@ -791,24 +853,27 @@ PHP_FUNCTION(proc_open) case O_RDONLY: mode_string = "r"; break; + case O_RDWR: + mode_string = "r+"; + break; } #ifdef PHP_WIN32 - fp = _fdopen(_open_osfhandle((long)descriptors[i].parentend, - descriptors[i].mode_flags), mode_string); + stream = php_stream_fopen_from_fd(_open_osfhandle((long)descriptors[i].parentend, + descriptors[i].mode_flags), mode_string, NULL); #else - fp = fdopen(descriptors[i].parentend, mode_string); + stream = php_stream_fopen_from_fd(descriptors[i].parentend, mode_string, NULL); #endif - if (fp) { - stream = php_stream_fopen_from_file(fp, mode_string); - if (stream) { - zval *retfp; + if (stream) { + zval *retfp; - MAKE_STD_ZVAL(retfp); - php_stream_to_zval(stream, retfp); - add_index_zval(pipes, descriptors[i].index, retfp); + /* nasty hack; don't copy it */ + stream->flags |= PHP_STREAM_FLAG_NO_SEEK; + + MAKE_STD_ZVAL(retfp); + php_stream_to_zval(stream, retfp); + add_index_zval(pipes, descriptors[i].index, retfp); - proc->pipes[i] = Z_LVAL_P(retfp); - } + proc->pipes[i] = Z_LVAL_P(retfp); } break; default: @@ -822,6 +887,14 @@ PHP_FUNCTION(proc_open) exit_fail: _php_free_envp(env, is_persistent); pefree(command, is_persistent); +#if PHP_CAN_DO_PTS + if (dev_ptmx >= 0) { + close(dev_ptmx); + } + if (slave_pty >= 0) { + close(slave_pty); + } +#endif RETURN_FALSE; } -- 2.50.1