]> granicus.if.org Git - sudo/commitdiff
Start commands in the background when I/O logging is enabled. We
authorTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 25 Sep 2012 17:49:51 +0000 (13:49 -0400)
committerTodd C. Miller <Todd.Miller@courtesan.com>
Tue, 25 Sep 2012 17:49:51 +0000 (13:49 -0400)
can't do this on Mac OS X due to a kernel bug in tc[gs]etattr(2)
which returns EINTR on signal instead of restarting automatically.

src/exec_pty.c

index ddfd67be7924f0c4eea07fd5614a9b7373c8b995..30b4ea0442d7510e22adccfaa6e4027e6ae6b972 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009-2011 Todd C. Miller <Todd.Miller@courtesan.com>
+ * Copyright (c) 2009-2012 Todd C. Miller <Todd.Miller@courtesan.com>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
 # define winsize       ttysize
 #endif
 
+/*
+ * Mac OS X has a bug wrt tc[gs]etpgrp where it returns EINTR if interrupted
+ * by a signal (usually SIGTTOU or SIGTTIN) instead of being restarted
+ * automatically (via ERESTART in the kernel).  On other systems we can start
+ * the command in the background which prevents sudo from stealing /dev/tty
+ * input when it doesn't need to.  When the command receives SIGTTOU or SIGTTIN,
+ * sudo will continue it in the foreground (assuming sudo is in the foreground).
+ */
+#ifdef __APPLE__
+# define TCSETATTR_NO_RESTART
+#endif
+
 struct io_buffer {
     struct io_buffer *next;
     int len; /* buffer length (how much produced) */
@@ -659,6 +671,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask)
            sync_ttysize(io_fds[SFD_USERTTY], io_fds[SFD_SLAVE]);
        }
 
+#ifdef TCSETATTR_NO_RESTART
        /* Start out in raw mode if we are not part of a pipeline. */
        if (!pipeline) {
            ttymode = TERM_RAW;
@@ -668,6 +681,7 @@ fork_pty(struct command_details *details, int sv[], int *maxfd, sigset_t *omask)
            if (!n)
                error(1, _("unable to set terminal to raw mode"));
        }
+#endif
     }
 
     /*
@@ -1089,17 +1103,17 @@ exec_monitor(struct command_details *details, int backchannel)
     if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE])
        close(io_fds[SFD_STDERR]);
 
-    /*
-     * Put command in its own process group.  If we are starting the command
-     * in the foreground, assign its pgrp to the tty.
-     */
+    /* Put command in its own process group. */
     cmnd_pgrp = cmnd_pid;
     setpgid(cmnd_pid, cmnd_pgrp);
+#ifdef TCSETATTR_NO_RESTART
+    /* Make the command the foreground process for the pty slave. */
     if (foreground) {
        do {
            n = tcsetpgrp(io_fds[SFD_SLAVE], cmnd_pgrp);
        } while (n == -1 && errno == EINTR);
     }
+#endif
 
     /* Wait for errno on pipe, signal on backchannel or for SIGCHLD */
     maxfd = MAX(MAX(errpipe[0], signal_pipe[0]), backchannel);
@@ -1289,11 +1303,13 @@ exec_pty(struct command_details *details, int *errfd)
        dup2(io_fds[SFD_STDERR], STDERR_FILENO) == -1)
        error(1, "dup2");
 
+#ifdef TCSETATTR_NO_RESTART
     /* Wait for parent to grant us the tty if we are foreground. */
     if (foreground) {
        while (tcgetpgrp(io_fds[SFD_SLAVE]) != self)
            ; /* spin */
     }
+#endif
 
     /* We have guaranteed that the slave fd is > 2 */
     if (io_fds[SFD_SLAVE] != -1)