aboutsummaryrefslogtreecommitdiffstats
path: root/io.c
diff options
context:
space:
mode:
Diffstat (limited to 'io.c')
-rw-r--r--io.c86
1 files changed, 49 insertions, 37 deletions
diff --git a/io.c b/io.c
index f6b50314..2249a2d8 100644
--- a/io.c
+++ b/io.c
@@ -1879,56 +1879,75 @@ two_way_open(const char *str, struct redirect *rp)
goto use_pipes;
got_the_pty:
- if ((slave = open(slavenam, O_RDWR)) < 0) {
- close(master);
- fatal(_("could not open `%s', mode `%s'"),
- slavenam, "r+");
- }
-#ifdef I_PUSH
/*
- * Push the necessary modules onto the slave to
- * get terminal semantics.
+ * We specifically open the slave only in the child. This allows
+ * certain, er, "limited" systems to work. The open is specifically
+ * without O_NOCTTY in order to make the slave become the controlling
+ * terminal.
*/
- ioctl(slave, I_PUSH, "ptem");
- ioctl(slave, I_PUSH, "ldterm");
+
+ switch (pid = fork()) {
+ case 0:
+ /* Child process */
+ setsid();
+
+ if ((slave = open(slavenam, O_RDWR)) < 0) {
+ close(master);
+ fatal(_("could not open `%s', mode `%s'"),
+ slavenam, "r+");
+ }
+
+#ifdef I_PUSH
+ /*
+ * Push the necessary modules onto the slave to
+ * get terminal semantics. Check that they aren't
+ * already there to avoid hangs on said "limited" systems.
+ */
+#ifdef I_FIND
+ if (ioctl(slave, I_FIND, "ptem") == 0)
#endif
+ ioctl(slave, I_PUSH, "ptem");
+#ifdef I_FIND
+ if (ioctl(slave, I_FIND, "ldterm") == 0)
+#endif
+ ioctl(slave, I_PUSH, "ldterm");
+#endif
+ tcgetattr(slave, & st);
- 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;
+ 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;
- /* Set some control codes to default values */
+ /* Set some control codes to default values */
#ifdef VINTR
- st.c_cc[VINTR] = '\003'; /* ^c */
+ st.c_cc[VINTR] = '\003'; /* ^c */
#endif
#ifdef VQUIT
- st.c_cc[VQUIT] = '\034'; /* ^| */
+ st.c_cc[VQUIT] = '\034'; /* ^| */
#endif
#ifdef VERASE
- st.c_cc[VERASE] = '\177'; /* ^? */
+ st.c_cc[VERASE] = '\177'; /* ^? */
#endif
#ifdef VKILL
- st.c_cc[VKILL] = '\025'; /* ^u */
+ st.c_cc[VKILL] = '\025'; /* ^u */
#endif
#ifdef VEOF
- st.c_cc[VEOF] = '\004'; /* ^d */
+ st.c_cc[VEOF] = '\004'; /* ^d */
#endif
- tcsetattr(slave, TCSANOW, & st);
-
- switch (pid = fork()) {
- case 0:
- /* Child process */
- setsid();
#ifdef TIOCSCTTY
+ /*
+ * This may not necessary anymore given that we
+ * open the slave in the child, but it doesn't hurt.
+ */
ioctl(slave, TIOCSCTTY, 0);
#endif
+ tcsetattr(slave, TCSANOW, & st);
if (close(master) == -1)
fatal(_("close of master pty failed (%s)"), strerror(errno));
@@ -1961,13 +1980,6 @@ two_way_open(const char *str, struct redirect *rp)
}
- /* parent */
- if (close(slave) != 0) {
- close(master);
- (void) kill(pid, SIGKILL);
- fatal(_("close of slave pty failed (%s)"), strerror(errno));
- }
-
rp->pid = pid;
rp->iop = iop_alloc(master, str, 0);
find_input_parser(rp->iop);