diff options
Diffstat (limited to 'lib-src')
-rw-r--r-- | lib-src/emacsclient.c | 581 | ||||
-rw-r--r-- | lib-src/pty.c | 20 | ||||
-rw-r--r-- | lib-src/pty.h | 224 |
3 files changed, 817 insertions, 8 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index aafc531ac5b..2f0f45e1f59 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -41,6 +41,54 @@ Boston, MA 02111-1307, USA. */ # include <pwd.h> #endif /* not VMS */ + +/****************************************/ + +#include <errno.h> +#include <signal.h> + +#ifndef INCLUDED_FCNTL +#define INCLUDED_FCNTL +#include <fcntl.h> +#endif + +#ifdef HAVE_TERMIOS +#ifndef NO_TERMIO +#include <termio.h> +#endif +#include <termios.h> +#endif /* not HAVE_TERMIOS */ + +#ifdef __GNU_LIBRARY__ +#include <sys/ioctl.h> +#include <termios.h> +#endif + +#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H) +#include <unistd.h> +#endif + + + +/* Try to establish the correct character to disable terminal functions + in a system-independent manner. Note that USG (at least) define + _POSIX_VDISABLE as 0! */ + +#ifdef _POSIX_VDISABLE +#define CDISABLE _POSIX_VDISABLE +#else /* not _POSIX_VDISABLE */ +#ifdef CDEL +#undef CDISABLE +#define CDISABLE CDEL +#else /* not CDEL */ +#define CDISABLE 255 +#endif /* not CDEL */ +#endif /* not _POSIX_VDISABLE */ + + + +/****************************************/ + char *getenv (), *getwd (); char *getcwd (); @@ -63,6 +111,9 @@ int eval = 0; /* The display on which Emacs should work. --display. */ char *display = NULL; +/* Nonzero means open a new Emacs frame on the current terminal. */ +int here = 0; + /* If non-NULL, the name of an editor to fallback to if the server is not running. --alternate-editor. */ const char * alternate_editor = NULL; @@ -78,6 +129,7 @@ struct option longopts[] = { "eval", no_argument, NULL, 'e' }, { "help", no_argument, NULL, 'H' }, { "version", no_argument, NULL, 'V' }, + { "here", no_argument, NULL, 'h' }, { "alternate-editor", required_argument, NULL, 'a' }, { "socket-name", required_argument, NULL, 's' }, { "display", required_argument, NULL, 'd' }, @@ -95,7 +147,7 @@ decode_options (argc, argv) while (1) { int opt = getopt_long (argc, argv, - "VHnea:s:d:", longopts, 0); + "VHnea:s:d:h", longopts, 0); if (opt == EOF) break; @@ -134,6 +186,10 @@ decode_options (argc, argv) exit (0); break; + case 'h': + here = 1; + break; + case 'H': print_help_and_exit (); break; @@ -144,6 +200,12 @@ decode_options (argc, argv) break; } } + + if (here) { + nowait = 0; + display = 0; + } + } void @@ -157,6 +219,7 @@ Every FILE can be either just a FILENAME or [+LINE[:COLUMN]] FILENAME.\n\ The following OPTIONS are accepted:\n\ -V, --version Just print a version info and return\n\ -H, --help Print this usage information message\n\ +-h, --here Open a new Emacs frame on the current terminal\n\ -n, --no-wait Don't wait for the server to return\n\ -e, --eval Evaluate the FILE arguments as ELisp expressions\n\ -d, --display=DISPLAY Visit the file in the given display\n\ @@ -247,6 +310,455 @@ fail (argc, argv) } } + +#ifdef HAVE_TERMIOS + +/* Adapted from emacs_get_tty() in sysdep.c. */ +int +ec_get_tty (int fd, struct termios *settings) +{ + bzero (settings, sizeof (struct termios)); + if (tcgetattr (fd, settings) < 0) + return -1; + return 0; +} + +/* Adapted from emacs_set_tty() in sysdep.c. */ +int +ec_set_tty (int fd, struct termios *settings, int flushp) +{ + /* Set the primary parameters - baud rate, character size, etcetera. */ + + 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, flushp ? TCSAFLUSH : TCSADRAIN, settings) < 0) + { + if (errno == EINTR) + continue; + else + return -1; + } + else + { + struct termios new; + + bzero (&new, sizeof (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->c_iflag + && new.c_oflag == settings->c_oflag + && new.c_cflag == settings->c_cflag + && new.c_lflag == settings->c_lflag + && memcmp (new.c_cc, settings->c_cc, NCCS) == 0) + break; + else + continue; + } + return 0; +} + +int master; +char *pty_name; + +struct termios old_tty; +struct termios tty; +int old_tty_valid; + +int tty_erase_char; +int flow_control = 0; +int meta_key = 0; +char _sobuf[BUFSIZ]; + +/* Adapted from init_sys_modes() in sysdep.c. */ +int +init_tty () +{ + if (! isatty (0)) + { + fprintf (stderr, "%s: Input is not a terminal", "init_tty"); + return 0; + } + + ec_get_tty (0, &old_tty); + old_tty_valid = 1; + tty = old_tty; + + tty_erase_char = old_tty.c_cc[VERASE]; + + tty.c_iflag |= (IGNBRK); /* Ignore break condition */ + tty.c_iflag &= ~ICRNL; /* Disable map of CR to NL on input */ +#ifdef INLCR + tty.c_iflag &= ~INLCR; /* Disable map of NL to CR on input */ +#endif +#ifdef ISTRIP + tty.c_iflag &= ~ISTRIP; /* don't strip 8th bit on input */ +#endif + tty.c_lflag &= ~ECHO; /* Disable echo */ + tty.c_lflag &= ~ICANON; /* Disable erase/kill processing */ +#ifdef IEXTEN + tty.c_lflag &= ~IEXTEN; /* Disable other editing characters. */ +#endif + tty.c_lflag |= ISIG; /* Enable signals */ + if (flow_control) + { + tty.c_iflag |= IXON; /* Enable start/stop output control */ +#ifdef IXANY + tty.c_iflag &= ~IXANY; +#endif /* IXANY */ + } + else + tty.c_iflag &= ~IXON; /* Disable start/stop output control */ + tty.c_oflag &= ~ONLCR; /* Disable map of NL to CR-NL + on output */ + tty.c_oflag &= ~TAB3; /* Disable tab expansion */ +#ifdef CS8 + if (meta_key) + { + tty.c_cflag |= CS8; /* allow 8th bit on input */ + tty.c_cflag &= ~PARENB; /* Don't check parity */ + } +#endif + tty.c_cc[VINTR] = CDISABLE; + tty.c_cc[VQUIT] = CDISABLE; + tty.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ + tty.c_cc[VTIME] = 0; /* no matter how long that takes. */ +#ifdef VSWTCH + tty.c_cc[VSWTCH] = CDISABLE; /* Turn off shell layering use of C-z */ +#endif + +#ifdef VSUSP + tty.c_cc[VSUSP] = CDISABLE; /* Turn off mips handling of C-z. */ +#endif /* VSUSP */ +#ifdef V_DSUSP + tty.c_cc[V_DSUSP] = CDISABLE; /* Turn off mips handling of C-y. */ +#endif /* V_DSUSP */ +#ifdef VDSUSP /* Some systems have VDSUSP, some have V_DSUSP. */ + tty.c_cc[VDSUSP] = CDISABLE; +#endif /* VDSUSP */ +#ifdef VLNEXT + tty.c_cc[VLNEXT] = CDISABLE; +#endif /* VLNEXT */ +#ifdef VREPRINT + tty.c_cc[VREPRINT] = CDISABLE; +#endif /* VREPRINT */ +#ifdef VWERASE + tty.c_cc[VWERASE] = CDISABLE; +#endif /* VWERASE */ +#ifdef VDISCARD + tty.c_cc[VDISCARD] = CDISABLE; +#endif /* VDISCARD */ + + if (flow_control) + { +#ifdef VSTART + tty.c_cc[VSTART] = '\021'; +#endif /* VSTART */ +#ifdef VSTOP + tty.c_cc[VSTOP] = '\023'; +#endif /* VSTOP */ + } + else + { +#ifdef VSTART + tty.c_cc[VSTART] = CDISABLE; +#endif /* VSTART */ +#ifdef VSTOP + tty.c_cc[VSTOP] = CDISABLE; +#endif /* VSTOP */ + } + +#ifdef SET_LINE_DISCIPLINE + /* Need to explicitly request TERMIODISC line discipline or + Ultrix's termios does not work correctly. */ + tty.c_line = SET_LINE_DISCIPLINE; +#endif + +#ifdef AIX +#ifndef IBMR2AIX + /* AIX enhanced edit loses NULs, so disable it. */ + tty.c_line = 0; + tty.c_iflag &= ~ASCEDIT; +#else + tty.c_cc[VSTRT] = 255; + tty.c_cc[VSTOP] = 255; + tty.c_cc[VSUSP] = 255; + tty.c_cc[VDSUSP] = 255; +#endif /* IBMR2AIX */ + if (flow_control) + { +#ifdef VSTART + tty.c_cc[VSTART] = '\021'; +#endif /* VSTART */ +#ifdef VSTOP + tty.c_cc[VSTOP] = '\023'; +#endif /* VSTOP */ + } + /* Also, PTY overloads NUL and BREAK. + don't ignore break, but don't signal either, so it looks like NUL. + This really serves a purpose only if running in an XTERM window + or via TELNET or the like, but does no harm elsewhere. */ + tty.c_iflag &= ~IGNBRK; + tty.c_iflag &= ~BRKINT; +#endif /* AIX */ + + ec_set_tty (0, &tty, 0); + + /* This code added to insure that, if flow-control is not to be used, + we have an unlocked terminal at the start. */ + +#ifdef TCXONC + if (!flow_control) ioctl (0, TCXONC, 1); +#endif +#ifndef APOLLO +#ifdef TIOCSTART + if (!flow_control) ioctl (0, TIOCSTART, 0); +#endif +#endif + +#if defined (HAVE_TERMIOS) || defined (HPUX9) +#ifdef TCOON + if (!flow_control) tcflow (0, TCOON); +#endif +#endif + +#ifdef _IOFBF + /* This symbol is defined on recent USG systems. + Someone says without this call USG won't really buffer the file + even with a call to setbuf. */ + setvbuf (stdout, (char *) _sobuf, _IOFBF, sizeof _sobuf); +#else + setbuf (stdout, (char *) _sobuf); +#endif + + return 1; +} + +void +window_change () +{ + int width, height; + +#ifdef TIOCGWINSZ + { + /* BSD-style. */ + struct winsize size; + + if (ioctl (0, TIOCGWINSZ, &size) == -1) + width = height = 0; + else + { + width = size.ws_col; + height = size.ws_row; + } + } +#else +#ifdef TIOCGSIZE + { + /* SunOS - style. */ + struct ttysize size; + + if (ioctl (0, TIOCGSIZE, &size) == -1) + width = height = 0; + else + { + width = size.ts_cols; + height = size.ts_lines; + } + } +#endif /* not SunOS-style */ +#endif /* not BSD-style */ + +#ifdef TIOCSWINSZ + { + /* BSD-style. */ + struct winsize size; + size.ws_row = height; + size.ws_col = width; + + ioctl (master, TIOCSWINSZ, &size); + } +#else +#ifdef TIOCSSIZE + { + /* SunOS - style. */ + struct ttysize size; + size.ts_lines = height; + size.ts_cols = width; + + ioctl (master, TIOCGSIZE, &size); + } +#endif /* not SunOS-style */ +#endif /* not BSD-style */ +} + +int in_conversation = 0; +int quit_conversation = 0; + +SIGTYPE +hang_up_signal (int signalnum) +{ + int old_errno = errno; + + if (! in_conversation) + return; + + quit_conversation = 1; + + errno = old_errno; +} + +SIGTYPE +window_change_signal (int signalnum) +{ + int old_errno = errno; + + if (! in_conversation) + goto end; + + window_change(); + + end: + signal (SIGWINCH, window_change_signal); + errno = old_errno; +} + +int +init_signals () +{ + /* Set up signal handlers. */ + signal (SIGWINCH, window_change_signal); + signal (SIGHUP, hang_up_signal); + + return 1; +} + + + +/* Adapted from reset_sys_modes in sysdep.c. */ +int +reset_tty () +{ + fflush (stdout); +#ifdef BSD_SYSTEM +#ifndef BSD4_1 + /* Avoid possible loss of output when changing terminal modes. */ + fsync (fileno (stdout)); +#endif +#endif + +#ifdef F_SETFL +#ifdef O_NDELAY + fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NDELAY); +#endif +#endif /* F_SETFL */ + + if (old_tty_valid) + while (ec_set_tty (0, &old_tty, 0) < 0 && errno == EINTR) + ; + + return 1; +} + + +int +init_pty () +{ + master = getpt (); + if (master < 0) + return 0; + + if (grantpt (master) < 0 || unlockpt (master) < 0) + goto close_master; + pty_name = strdup (ptsname (master)); + if (! pty_name) + goto close_master; + + /* Propagate window size. */ + window_change (); + + return 1; + + close_master: + close (master); + return 0; +} + +int +copy_from_to (int in, int out) +{ + static char buf[BUFSIZ]; + int nread = read (in, &buf, BUFSIZ); + if (nread == 0) + return 1; /* EOF */ + else if (nread < 0 && errno != EAGAIN) + return 0; /* Error */ + else if (nread > 0) + { + int r = 0; + int written = 0; + + do { + r = write (out, &buf, nread); + } while ((r < 0 && errno == EAGAIN) + || (r > 0 && (written += r) && written != nread)); + + if (r < 0) + return 0; /* Error */ + } + return 1; +} + +int +pty_conversation () +{ + fd_set set; + + in_conversation = 1; + + while (! quit_conversation) { + int res; + + FD_ZERO (&set); + FD_SET (master, &set); + FD_SET (1, &set); + res = select (FD_SETSIZE, &set, NULL, NULL, NULL); + if (res < 0) + { + if (errno != EINTR) + return 0; + } + else if (res > 0) + { + if (FD_ISSET (master, &set)) + { + /* Copy Emacs output to stdout. */ + if (! copy_from_to (master, 0)) + return 1; + } + if (FD_ISSET (1, &set)) + { + /* Forward user input to Emacs. */ + if (! copy_from_to (1, master)) + return 1; + } + } + } + return 1; +} + +#endif /* HAVE_TERMIOS */ #if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM) @@ -312,7 +824,7 @@ main (argc, argv) /* Process options. */ decode_options (argc, argv); - if ((argc - optind < 1) && !eval) + if ((argc - optind < 1) && !eval && !here) { fprintf (stderr, "%s: file name or argument required\n", progname); fprintf (stderr, "Try `%s --help' for more information\n", progname); @@ -484,6 +996,38 @@ To start the server in Emacs, type \"M-x server-start\".\n", fprintf (out, " "); } + if (here) + { + if (! init_signals ()) + { + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + + if (! init_tty ()) + { + reset_tty (); + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + + if (! init_pty ()) + { + reset_tty (); + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + + fprintf (out, "-pty "); + quote_file_name (pty_name, out); + fprintf (out, " "); + quote_file_name (getenv("TERM"), out); + fprintf (out, " "); + } + if ((argc - optind > 0)) { for (i = optind; i < argc; i++) @@ -512,11 +1056,14 @@ To start the server in Emacs, type \"M-x server-start\".\n", } else { - while ((str = fgets (string, BUFSIZ, stdin))) - { - quote_file_name (str, out); - } - fprintf (out, " "); + if (!here) + { + while ((str = fgets (string, BUFSIZ, stdin))) + { + quote_file_name (str, out); + } + fprintf (out, " "); + } } fprintf (out, "\n"); @@ -524,8 +1071,25 @@ To start the server in Emacs, type \"M-x server-start\".\n", /* Maybe wait for an answer. */ if (nowait) - return 0; + { + reset_tty (); + return 0; + } + if (here) + { + if (! pty_conversation ()) + { + reset_tty (); + fprintf (stderr, "%s: ", argv[0]); + perror ("fdopen"); + fail (argc, argv); + } + close (master); + reset_tty (); + return 0; + } + if (!eval) { printf ("Waiting for Emacs..."); @@ -546,6 +1110,7 @@ To start the server in Emacs, type \"M-x server-start\".\n", printf ("\n"); fflush (stdout); + reset_tty (); return 0; } diff --git a/lib-src/pty.c b/lib-src/pty.c new file mode 100644 index 00000000000..05c54c63ff5 --- /dev/null +++ b/lib-src/pty.c @@ -0,0 +1,20 @@ +/* Terminal initialization for emacsclient. + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + diff --git a/lib-src/pty.h b/lib-src/pty.h new file mode 100644 index 00000000000..d8f6318176a --- /dev/null +++ b/lib-src/pty.h @@ -0,0 +1,224 @@ +/* Terminal initialization for emacsclient. + Copyright (C) 2003 Free Software Foundation, Inc. + +This file is part of GNU Emacs. + +GNU Emacs is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Emacs is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Emacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Adapted from systty.h */ + + +#ifdef HAVE_TERMIOS +#define HAVE_TCATTR +#endif + + +/* Include the proper files. */ +#ifdef HAVE_TERMIO +#ifdef __DGUX +#include <sys/ioctl.h> +#endif +#ifndef NO_TERMIO +#include <termio.h> +#endif /* not NO_TERMIO */ +#ifndef INCLUDED_FCNTL +#define INCLUDED_FCNTL +#include <fcntl.h> +#endif +#else /* not HAVE_TERMIO */ +#ifdef HAVE_TERMIOS +#if defined(_AIX) && defined(_I386) +#include <termios.h> /* termios.h needs to be before termio.h */ +#include <termio.h> +#else /* not (_AIX && _I386) */ +#ifndef NO_TERMIO +#include <termio.h> +#endif +#include <termios.h> +#endif /* not (_AIX && _I386) */ +#define INCLUDED_FCNTL +#include <fcntl.h> +#else /* neither HAVE_TERMIO nor HAVE_TERMIOS */ +#ifndef VMS +#ifndef DOS_NT +#include <sgtty.h> +#endif /* not DOS_NT */ +#else /* VMS */ +#include <descrip.h> +static struct iosb +{ + short status; + short offset; + short termlen; + short term; +} input_iosb; + +extern int waiting_for_ast; +extern int stop_input; +extern int input_ef; +extern int timer_ef; +extern int process_ef; +extern int input_eflist; +extern int timer_eflist; + +static $DESCRIPTOR (input_dsc, "TT"); +static int terminator_mask[2] = { 0, 0 }; + +static struct sensemode { + short status; + unsigned char xmit_baud; + unsigned char rcv_baud; + unsigned char crfill; + unsigned char lffill; + unsigned char parity; + unsigned char unused; + char class; + char type; + short scr_wid; + unsigned long tt_char : 24, scr_len : 8; + unsigned long tt2_char; +} sensemode_iosb; +#endif /* VMS */ +#endif /* not HAVE_TERMIOS */ +#endif /* not HAVE_TERMIO */ + +#ifdef __GNU_LIBRARY__ +#include <sys/ioctl.h> +#include <termios.h> +#endif + +#ifdef AIXHFT +/* Get files for keyboard remapping */ +#define HFNKEYS 2 +#include <sys/hft.h> +#include <sys/devinfo.h> +#endif + +/* Get rid of LLITOUT in 4.1, since it is said to stimulate kernel bugs. */ +#ifdef BSD4_1 +#undef LLITOUT +#define LLITOUT 0 +#endif /* 4.1 */ + +#ifdef NEED_BSDTTY +#include <sys/bsdtty.h> +#endif + +#if defined (HPUX) && defined (HAVE_PTYS) +#include <sys/ptyio.h> +#endif + +#ifdef AIX +#include <sys/pty.h> +#endif /* AIX */ + +#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H) +#include <unistd.h> +#endif + +#ifdef SYSV_PTYS +#include <sys/types.h> +#include <sys/tty.h> +#ifdef titan +#include <sys/ttyhw.h> +#include <sys/stream.h> +#endif +#ifndef NO_PTY_H +#include <sys/pty.h> +#endif +#endif + +/* saka@pfu.fujitsu.co.JP writes: + FASYNC defined in this file. But, FASYNC don't working. + so no problem, because unrequest_sigio only need. */ +#if defined (pfa) +#include <sys/file.h> +#endif + + +/* Special cases - inhibiting the use of certain features. */ + +#ifdef APOLLO +#undef TIOCSTART +#endif + +#ifdef XENIX +#undef TIOCGETC /* Avoid confusing some conditionals that test this. */ +#endif + +#ifdef BROKEN_TIOCGETC +#undef TIOCGETC /* Avoid confusing some conditionals that test this. */ +#endif + +/* UNIPLUS systems may have FIONREAD. */ +#ifdef UNIPLUS +#include <sys.ioctl.h> +#endif + +/* Allow m- file to inhibit use of FIONREAD. */ +#ifdef BROKEN_FIONREAD +#undef FIONREAD +#undef ASYNC +#endif + +/* Interrupt input is not used if there is no FIONREAD. */ +#ifndef FIONREAD +#undef SIGIO +#endif + +/* On TERMIOS systems, the tcmumbleattr calls take care of these + parameters, and it's a bad idea to use them (on AIX, it makes the + tty hang for a long time). */ +#if defined (TIOCGLTC) && !defined (HAVE_TERMIOS) +#define HAVE_LTCHARS +#endif + +#if defined (TIOCGETC) && !defined (HAVE_TERMIOS) +#define HAVE_TCHARS +#endif + + +/* Try to establish the correct character to disable terminal functions + in a system-independent manner. Note that USG (at least) define + _POSIX_VDISABLE as 0! */ + +#ifdef _POSIX_VDISABLE +#define CDISABLE _POSIX_VDISABLE +#else /* not _POSIX_VDISABLE */ +#ifdef CDEL +#undef CDISABLE +#define CDISABLE CDEL +#else /* not CDEL */ +#define CDISABLE 255 +#endif /* not CDEL */ +#endif /* not _POSIX_VDISABLE */ + +/* Get the number of characters queued for output. */ + +/* EMACS_OUTQSIZE(FD, int *SIZE) stores the number of characters + queued for output to the terminal FD in *SIZE, if FD is a tty. + Returns -1 if there was an error (i.e. FD is not a tty), 0 + otherwise. */ +#ifdef TIOCOUTQ +#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TIOCOUTQ, (size))) +#endif + +#ifdef HAVE_TERMIO +#ifdef TCOUTQ +#undef EMACS_OUTQSIZE +#define EMACS_OUTQSIZE(fd, size) (ioctl ((fd), TCOUTQ, (size))) +#endif +#endif |