[Top][All Lists]
[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;
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] ptys,
address@hidden <=