Interact properly with shells lacking job control (sh, rc, es...)
[bpt/emacs.git] / src / sysdep.c
index 4974443..247b9b2 100644 (file)
@@ -756,6 +756,54 @@ unrequest_sigio ()
 #endif /* FASYNC */
 #endif /* F_SETFL */
 \f
+/* Saving and restoring the process group of Emacs's terminal.  */
+
+#ifdef BSD
+
+/* The process group of which Emacs was a member when it initially
+   started.
+
+   If Emacs was in its own process group (i.e. inherited_pgroup ==
+   getpid ()), then we know we're running under a shell with job
+   control (Emacs would never be run as part of a pipeline).
+   Everything is fine.
+
+   If Emacs was not in its own process group, then we know we're
+   running under a shell (or a caller) that doesn't know how to
+   separate itself from Emacs (like sh).  Emacs must be in its own
+   process group in order to receive SIGIO correctly.  In this
+   situation, we put ourselves in our own pgroup, forcibly set the
+   tty's pgroup to our pgroup, and make sure to restore and reinstate
+   the tty's pgroup just like any other terminal setting.  If
+   inherited_group was not the tty's pgroup, then we'll get a
+   SIGTTmumble when we try to change the tty's pgroup, and a CONT if
+   it goes foreground in the future, which is what should happen.  */
+int inherited_pgroup;
+
+/* Split off the foreground process group to Emacs alone.
+   When we are in the foreground, but not started in our own process
+   group, redirect the TTY to point to our own process group.  We need
+   to be in our own process group to receive SIGIO properly.  */
+narrow_foreground_group ()
+{
+  int me = getpid ();
+
+  setpgrp (0, inherited_pgroup);
+  if (inherited_pgroup != me)
+    EMACS_SET_TTY_PGRP (0, &me);
+  setpgrp (0, me);
+}
+
+/* Set the tty to our original foreground group.  */
+widen_foreground_group ()
+{
+  if (inherited_pgroup != getpid ())
+    EMACS_SET_TTY_PGRP (0, &inherited_pgroup);
+  setpgrp (0, inherited_pgroup);
+}
+
+#endif
+\f
 /* Getting and setting emacs_tty structures.  */
 
 /* Set *TC to the parameters associated with the terminal FD.
@@ -982,6 +1030,11 @@ init_sys_modes ()
 #endif
 #endif /* not VMS */
 
+#ifdef BSD
+  if (! read_socket_hook && EQ (Vwindow_system, Qnil))
+    narrow_foreground_group ();
+#endif
+
   EMACS_GET_TTY (input_fd, &old_tty);
 
   if (!read_socket_hook && EQ (Vwindow_system, Qnil))
@@ -1334,6 +1387,10 @@ reset_sys_modes ()
 #ifdef AIX
   hft_reset ();
 #endif
+
+#ifdef BSD
+  widen_foreground_group ();
+#endif
 }
 \f
 #ifdef HAVE_PTYS