bug-gnu-utils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] ptys


From: address@hidden
Subject: [PATCH] ptys
Date: Fri, 8 Jun 2001 15:34:06 +0200

Here is the patch -- so small that I gave a try to it before reading
your answer...

No regressions from 3.1.0; here is the changelog entry.

2001-06-08  Paolo Bonzini  <address@hidden>

        * configure.in: test for termios.h and stropts.h.
        * io.c: include termios.h and stropts.h if available.
        * io.c (close_redir): close write channel for two-way pipes
        by sending an EOF.
        * io.c (two_way_open): use pty's instead of pipes to open
        two-way pipes as they are line-buffered by default --> alleviate
        deadlock problems.

Paolo Bonzini
---


diff --recursive -U3 gawk-3.1.0.orig/configure.in gawk-3.1.0/configure.in
--- gawk-3.1.0.orig/configure.in        Tue May 15 17:46:40 2001
+++ gawk-3.1.0/configure.in     Fri Jun  8 13:49:06 2001
@@ -97,7 +97,7 @@
 AC_HEADER_SYS_WAIT
 AC_CHECK_HEADERS(fcntl.h limits.h locale.h libintl.h mcheck.h \
        netdb.h netinet/in.h  signum.h stdarg.h string.h \
-       sys/param.h sys/socket.h unistd.h)
+       sys/param.h sys/socket.h unistd.h termios.h stropts.h)

 if test "$ac_cv_header_string_h" = yes
 then
@@ -129,7 +129,7 @@

 AC_CHECK_LIB(m, fmod)
 AC_CHECK_FUNCS(memset memcpy memcmp fmod setlocale strchr strerror \
-                strftime strncasecmp strtod system tzset)
+                strftime strncasecmp strtod system tzset grantpt)

 dnl check for dynamic linking
 dnl This is known to be very primitive
diff --recursive -U3 gawk-3.1.0.orig/io.c gawk-3.1.0/io.c
--- gawk-3.1.0.orig/io.c        Tue Apr 24 12:35:35 2001
+++ gawk-3.1.0/io.c     Fri Jun  8 14:07:54 2001
@@ -41,6 +41,13 @@
 #define O_ACCMODE      (O_RDONLY|O_WRONLY|O_RDWR)
 #endif

+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+
 #ifdef HAVE_SOCKETS
 #ifdef HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
@@ -762,8 +769,14 @@
                        if ((rp->flag & RED_TCP) != 0)
                                (void) shutdown(fileno(rp->fp), SHUT_WR);
 #endif /* HAVE_SOCKETS */
-                       status = fclose(rp->fp);
-                       rp->fp = NULL;
+
+                       if ((rp->flag & (RED_READ|RED_WRITE)) == 
(RED_READ|RED_WRITE)) {
+                               fwrite("\004\n", sizeof("\004\n") - 1, 1, 
rp->fp);
+                               fflush(rp->fp);
+                       } else {
+                               status = fclose(rp->fp);
+                               rp->fp = NULL;
+                       }
                }

                /* read end: */
@@ -1516,80 +1529,194 @@
 #ifndef PIPES_SIMULATED                /* real pipes */
        /* case 2: two way pipe to a child process */
     {
-       int ptoc[2], ctop[2];
-       int pid;
-       int save_errno;
-
-       if (pipe(ptoc) < 0)
-               return FALSE;   /* errno set, diagnostic from caller */
-
-       if (pipe(ctop) < 0) {
-               save_errno = errno;
-               close(ptoc[0]);
-               close(ptoc[1]);
-               errno = save_errno;
-               return FALSE;
+       static int initialized = 0;
+       static char first_pty_letter;
+#ifdef HAVE_GRANTPT
+       static int have_dev_ptmx;
+#endif
+
+       char slavenam[32];
+       char c;
+       int master;
+       int slave;
+       int save_errno;
+       pid_t pid;
+       struct stat statb;
+       struct termios st;
+
+       if (!initialized) {
+
+               initialized = 1;
+#ifdef HAVE_GRANTPT
+               have_dev_ptmx = stat ("/dev/ptmx", &statb) >= 0;
+#endif
+
+               c = 'p';
+               do {
+                       sprintf (slavenam, "/dev/pty%c0", c);
+                       if (stat (slavenam, &statb) >= 0) {
+                               first_pty_letter = c;
+                               break;
+                       }
+                       if (++c > 'z')
+                               c = 'a';
+               } while (c != 'p');
+       }
+
+#ifdef HAVE_GRANTPT
+       if (have_dev_ptmx) {
+               master = open ("/dev/ptmx", O_RDWR);
+               if (master >= 0) {
+                       char *tem;
+                       grantpt (master);
+                       unlockpt (master);
+                       tem = ptsname (master);
+                       if (tem != 0) {
+                               strcpy (slavenam, tem);
+                               goto got_the_pty;
+                       }
+                       close (master);
+               }
        }
+#endif

-       if ((pid = fork()) < 0) {
-               save_errno = errno;
-               close(ptoc[0]); close(ptoc[1]);
-               close(ctop[0]); close(ctop[1]);
-               errno = save_errno;
-               return FALSE;
+       if (first_pty_letter) {
+               /* Assume /dev/ptyXNN and /dev/ttyXN naming system.
+                  The FIRST_PTY_LETTER gives the first X to try. We try in the
+                  sequence FIRST_PTY_LETTER, .., 'z', 'a', .., 
FIRST_PTY_LETTER.
+                  Is this worthwhile, or just over-zealous? */
+               c = first_pty_letter;
+               do {
+                       int i;
+                       for (i = 0; i < 16; i++) {
+                               sprintf (slavenam, "/dev/pty%c%x", c, i);
+                               if (stat (slavenam, &statb) < 0)
+                                       return 0;
+
+                               if ((master = open (slavenam, O_RDWR)) >= 0) {
+                                       slavenam[sizeof ("/dev/") - 1] = 't';
+                                       if (access (slavenam, R_OK | W_OK) == 0)
+                                               goto got_the_pty;
+                                       close (master);
+                               }
+                       }
+                       if (++c > 'z')
+                               c = 'a';
+               } while (c != first_pty_letter);
        }
-
-       if (pid == 0) { /* child */
+
+       /* Couldn't find a pty. Signal an error. */
+       fatal(_("`|&' not supported"));
+       return 0;
+
+ got_the_pty:
+               if ((slave = open (slavenam, O_RDWR)) < 0) {
+                       fatal(_("could not open `%s', mode `%s'"),
+                                               slavenam, "r+");
+               }
+
+
+#ifdef I_PUSH
+               /* Push the necessary modules onto the slave to
+                  get terminal semantics. */
+               ioctl (slave, I_PUSH, "ptem");
+               ioctl (slave, I_PUSH, "ldterm");
+#endif
+
+
+#ifdef TIOCSCTTY
+               ioctl (slave, TIOCSCTTY, 0);
+#endif
+               tcgetattr (slave, &st);
+               st.c_iflag &= ~(ISTRIP | IGNCR | INLCR | IXOFF);
+               st.c_iflag |= (ICRNL | IGNPAR | BRKINT | IXON);
+               st.c_oflag &= ~OPOST;
+               st.c_cflag &= ~CSIZE;
+               st.c_cflag |= CREAD | CS8 | CLOCAL;
+               st.c_lflag &= ~(ECHO | ECHOE | ECHOK | NOFLSH | TOSTOP);
+               st.c_lflag |= ISIG;
+#if 0
+               st.c_cc[VMIN] = 1;
+               st.c_cc[VTIME] = 0;
+#endif
+
+               /* Set some control codes to default values */
+#ifdef VINTR
+               st.c_cc[VINTR] = '\003';        /* ^c */
+#endif
+#ifdef VQUIT
+               st.c_cc[VQUIT] = '\034';        /* ^| */
+#endif
+#ifdef VERASE
+               st.c_cc[VERASE] = '\177';       /* ^? */
+#endif
+#ifdef VKILL
+               st.c_cc[VKILL] = '\025';        /* ^u */
+#endif
+#ifdef VEOF
+               st.c_cc[VEOF] = '\004'; /* ^d */
+#endif
+               tcsetattr (slave, TCSANOW, &st);
+
+       switch (pid = fork ()) {
+       case 0: {
+               /* Child process */
+
+               if (close(master))
+                       fatal(_("close of pipe failed (%s)"), strerror(errno));
+
                if (close(1) == -1)
                        fatal(_("close of stdout in child failed (%s)"),
-                               strerror(errno));
-               if (dup(ctop[1]) != 1)
+                       strerror(errno));
+               if (dup(slave) != 1)
                        fatal(_("moving pipe to stdout in child failed (dup: 
%s)"), strerror(errno));
                if (close(0) == -1)
                        fatal(_("close of stdin in child failed (%s)"),
-                               strerror(errno));
-               if (dup(ptoc[0]) != 0)
+                       strerror(errno));
+               if (dup(slave) != 0)
                        fatal(_("moving pipe to stdin in child failed (dup: 
%s)"), strerror(errno));
-               if (   close(ptoc[0]) == -1 || close(ptoc[1]) == -1
-                   || close(ctop[0]) == -1 || close(ctop[1]) == -1)
+               if (close(slave))
                        fatal(_("close of pipe failed (%s)"), strerror(errno));
+
                /* stderr does NOT get dup'ed onto child's stdout */
+
+               signal (SIGPIPE, SIG_DFL);
+
                execl("/bin/sh", "sh", "-c", str, NULL);
                _exit(127);
        }

+       case -1:
+               save_errno = errno;
+               close(master);
+               errno = save_errno;
+               return FALSE;
+
+       }
+
+       if (close(slave))
+               fatal(_("close of pipe failed (%s)"), strerror(errno));
+
        /* parent */
        rp->pid = pid;
-       rp->iop = iop_alloc(ctop[0], str, NULL);
+       rp->iop = iop_alloc(master, str, NULL);
        if (rp->iop == NULL) {
-               (void) close(ctop[0]);
-               (void) close(ctop[1]);
-               (void) close(ptoc[0]);
-               (void) close(ptoc[1]);
+               (void) close(master);
                (void) kill(pid, SIGKILL);      /* overkill? (pardon pun) */
                return FALSE;
        }
-       rp->fp = fdopen(ptoc[1], "w");
+       rp->fp = fdopen(master, "w");
        if (rp->fp == NULL) {
                iop_close(rp->iop);
                rp->iop = NULL;
-               (void) close(ctop[0]);
-               (void) close(ctop[1]);
-               (void) close(ptoc[0]);
-               (void) close(ptoc[1]);
+               (void) close(master);
                (void) kill(pid, SIGKILL);      /* overkill? (pardon pun) */
                return FALSE;
        }
-       if (fcntl(ctop[0], F_SETFD, 1) < 0) {
+       if (fcntl(master, F_SETFD, 1) < 0) {
                warning(_("pipe from `%s': could not set close-on-exec (fcntl: 
%s)"),
                        str, strerror(errno));;
        }
-       if (fcntl(ptoc[1], F_SETFD, 1) < 0) {
-               warning(_("pipe to `%s': could not set close-on-exec (fcntl: 
%s)"),
-                       str, strerror(errno));;
-       }
-       (void) close(ptoc[0]);
-       (void) close(ctop[1]);
        return TRUE;
     }






reply via email to

[Prev in Thread] Current Thread [Next in Thread]