+\f
+/* Saving and restoring the process group of Emacs's terminal. */
+
+#ifdef BSD_PGRPS
+
+/* 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 (input_fd, &me);
+ setpgrp (0, me);
+}
+
+/* Set the tty to our original foreground group. */
+widen_foreground_group ()
+{
+ if (inherited_pgroup != getpid ())
+ EMACS_SET_TTY_PGRP (input_fd, &inherited_pgroup);
+ setpgrp (0, inherited_pgroup);
+}
+
+#endif /* BSD_PGRPS */
+\f
+/* Getting and setting emacs_tty structures. */
+
+/* Set *TC to the parameters associated with the terminal FD.
+ Return zero if all's well, or -1 if we ran into an error we
+ couldn't deal with. */
+int
+emacs_get_tty (fd, settings)
+ int fd;
+ struct emacs_tty *settings;
+{
+ /* Retrieve the primary parameters - baud rate, character size, etcetera. */
+#ifdef HAVE_TCATTR
+ /* We have those nifty POSIX tcmumbleattr functions. */
+ if (tcgetattr (fd, &settings->main) < 0)
+ return -1;
+
+#else
+#ifdef HAVE_TERMIO
+ /* The SYSV-style interface? */
+ if (ioctl (fd, TCGETA, &settings->main) < 0)
+ return -1;
+
+#else
+#ifdef VMS
+ /* Vehemently Monstrous System? :-) */
+ if (! (SYS$QIOW (0, fd, IO$_SENSEMODE, settings, 0, 0,
+ &settings->main.class, 12, 0, 0, 0, 0)
+ & 1))
+ return -1;
+
+#else
+#ifndef MSDOS
+ /* I give up - I hope you have the BSD ioctls. */
+ if (ioctl (fd, TIOCGETP, &settings->main) < 0)
+ return -1;
+#endif /* not MSDOS */
+#endif
+#endif
+#endif
+
+ /* Suivant - Do we have to get struct ltchars data? */
+#ifdef HAVE_LTCHARS
+ if (ioctl (fd, TIOCGLTC, &settings->ltchars) < 0)
+ return -1;
+#endif
+
+ /* How about a struct tchars and a wordful of lmode bits? */
+#ifdef HAVE_TCHARS
+ if (ioctl (fd, TIOCGETC, &settings->tchars) < 0
+ || ioctl (fd, TIOCLGET, &settings->lmode) < 0)
+ return -1;
+#endif
+
+ /* We have survived the tempest. */
+ return 0;
+}
+
+
+/* Set the parameters of the tty on FD according to the contents of
+ *SETTINGS. If WAITP is non-zero, we wait for all queued output to
+ be written before making the change; otherwise, we forget any
+ queued input and make the change immediately.
+ Return 0 if all went well, and -1 if anything failed. */
+int
+emacs_set_tty (fd, settings, waitp)
+ int fd;
+ struct emacs_tty *settings;
+ int waitp;
+{
+ /* Set the primary parameters - baud rate, character size, etcetera. */
+#ifdef HAVE_TCATTR
+ int i;
+ /* We have those nifty POSIX tcmumbleattr functions.
+ William J. Smith <wjs@wiis.wang.com> writes:
+ "POSIX 1003.1 defines tcsetattr() to return success if it was
+ able to perform any of the requested actions, even if some
+ of the requested actions could not be performed.
+ We must read settings back to ensure tty setup properly.
+ AIX requires this to keep tty from hanging occasionally." */
+ /* This make sure that we don't loop indefinitely in here. */
+ for (i = 0 ; i < 10 ; i++)
+ if (tcsetattr (fd, waitp ? TCSAFLUSH : TCSADRAIN, &settings->main) < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ else
+ return -1;
+ }
+ else
+ {
+ struct termios new;
+
+ /* Get the current settings, and see if they're what we asked for. */
+ tcgetattr (fd, &new);
+ /* We cannot use memcmp on the whole structure here because under
+ * aix386 the termios structure has some reserved field that may
+ * not be filled in.
+ */
+ if ( new.c_iflag == settings->main.c_iflag
+ && new.c_oflag == settings->main.c_oflag
+ && new.c_cflag == settings->main.c_cflag
+ && new.c_lflag == settings->main.c_lflag
+ && memcmp(new.c_cc, settings->main.c_cc, NCCS) == 0)
+ break;
+ else
+ continue;
+ }
+
+#else
+#ifdef HAVE_TERMIO
+ /* The SYSV-style interface? */
+ if (ioctl (fd, waitp ? TCSETAW : TCSETAF, &settings->main) < 0)
+ return -1;
+
+#else
+#ifdef VMS
+ /* Vehemently Monstrous System? :-) */
+ if (! (SYS$QIOW (0, fd, IO$_SETMODE, &input_iosb, 0, 0,
+ &settings->main.class, 12, 0, 0, 0, 0)
+ & 1))
+ return -1;
+
+#else
+#ifndef MSDOS
+ /* I give up - I hope you have the BSD ioctls. */
+ if (ioctl (fd, (waitp) ? TIOCSETP : TIOCSETN, &settings->main) < 0)
+ return -1;
+#endif /* not MSDOS */
+
+#endif
+#endif
+#endif
+
+ /* Suivant - Do we have to get struct ltchars data? */
+#ifdef HAVE_LTCHARS
+ if (ioctl (fd, TIOCSLTC, &settings->ltchars) < 0)
+ return -1;
+#endif
+
+ /* How about a struct tchars and a wordful of lmode bits? */
+#ifdef HAVE_TCHARS
+ if (ioctl (fd, TIOCSETC, &settings->tchars) < 0
+ || ioctl (fd, TIOCLSET, &settings->lmode) < 0)
+ return -1;
+#endif
+
+ /* We have survived the tempest. */
+ return 0;
+}
+