summaryrefslogtreecommitdiff
path: root/lib-src/emacsclient.c
diff options
context:
space:
mode:
authorKaroly Lorentey <lorentey@elte.hu>2004-01-03 08:31:14 +0000
committerKaroly Lorentey <lorentey@elte.hu>2004-01-03 08:31:14 +0000
commit4d553a13abdadb4bb469bc0b59c003d48066dce5 (patch)
tree0b84a435d41801417190e60bf89ffa0305c8c4ac /lib-src/emacsclient.c
parentb28c910d1f41815fa4744756852d5f2377d28636 (diff)
downloademacs-4d553a13abdadb4bb469bc0b59c003d48066dce5.tar.gz
Portability fixes (now it compiles & runs fine on Solaris).
lib-src/emacsclient.c: Removed tty proxy kludge. Emacs should just use the same terminal as emacsclient. (ec_get_tty, ec_set_tty, master, pty_name, old_tty, tty, old_tty_valid) (tty_erase_char, quit_char, flow_control, meta_key, _sobuf, init_tty) (window_change, reset_tty, init_pty, copy_from_to) (pty_conversation): Removed. (window_change_signal): Just forward the signal to Emacs, don't do anything else. (init_signals): Don't set handlers for SIGHUP & SIGINT. (strprefix): New function. (main): Don't touch the terminal, simply tell its name to Emacs. lisp/server.el (server-frames): Changed name and semantics to server-ttys. (server-tty-live-p): New function. (server-sentinel): Delete the whole tty, not just the frame. (server-handle-delete-frame): Removed. (server-handle-delete-tty): New function. Close the client connection if the tty is deleted. (server-start): Clean up server-ttys, not server-frames. Set up delete-tty-after-functions. (server-process-filter): Set up server-ttys, not server-frames. Updated protocol for sending our pid to emacsclient. (server-buffer-done): Don't delete the client process directly, delete the tty instead, and rely on the delete-tty hook to close the connection. Otherwise the terminal could be left in a bad state. src/cm.c (cmputc): Don't abort on write errors. src/indent.c: #include <stdio.h>, for termchar.h. src/window.c: Ditto. src/xfaces.c: Ditto. src/sysdep.c (init_sigio, reset_sigio, request_sigio)[!SIGIO] (unrequest_sigio)[!SIGIO]: If SIGIO is not supported, don't do anything. (For Solaris.) (init_sys_modes): Moved tty_set_terminal_modes call back to here, disable window system check. (reset_sys_modes): Reset the terminal even if X is running. src/term.c (Vdelete_tty_after_functions): New variable. (syms_of_term): Initialize it. (Fdelete_tty): Updated docs. (delete_tty): Run delete-tty-after-functions. (term_init): Removed tty_set_terminal_modes call. git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-35
Diffstat (limited to 'lib-src/emacsclient.c')
-rw-r--r--lib-src/emacsclient.c638
1 files changed, 48 insertions, 590 deletions
diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c
index 741f5da2f1e..563a8ba9db0 100644
--- a/lib-src/emacsclient.c
+++ b/lib-src/emacsclient.c
@@ -41,54 +41,10 @@ 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
-
+#include <errno.h>
-/* 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 ();
@@ -314,532 +270,37 @@ fail (void)
}
}
-
-#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 quit_char = 'g' & 037;
-int flow_control = 0;
-int meta_key = 0;
-char _sobuf[BUFSIZ];
int emacs_pid;
-/* 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] = quit_char; /* C-g (usually) gives SIGINT */
- /* Set up C-g for both SIGQUIT and SIGINT.
- We don't know which we will get, but we handle both alike
- so which one it really gives us does not matter. */
- tty.c_cc[VQUIT] = quit_char;
- 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;
+#ifdef nec_ews_svr4
+extern char *_sobuf ;
#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);
+#if defined (USG) || defined (DGUX)
+unsigned char _sobuf[BUFSIZ+8];
#else
- setbuf (stdout, (char *) _sobuf);
+char _sobuf[BUFSIZ];
+#endif
#endif
-
- return 1;
-}
-
-void
-window_change ()
-{
- int width = 0, height = 0;
-
-#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 */
-
- if (emacs_pid && width && height)
- kill (emacs_pid, SIGWINCH);
-}
-
-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;
-}
-
-SIGTYPE
-interrupt_signal (int signalnum)
-{
- int old_errno = errno;
-
- /* Forward it to Emacs. */
if (emacs_pid)
- kill (emacs_pid, SIGINT);
+ kill (emacs_pid, SIGWINCH);
+ signal (SIGWINCH, window_change_signal);
errno = old_errno;
}
-int
-init_signals ()
+void
+init_signals (void)
{
/* Set up signal handlers. */
signal (SIGWINCH, window_change_signal);
- signal (SIGHUP, hang_up_signal);
- signal (SIGINT, interrupt_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, int sigio)
-{
- static char buf[BUFSIZ];
- int nread = read (in, &buf, BUFSIZ);
- if (nread == 0)
- return 1; /* EOF */
- else if (nread < 0 && errno != EAGAIN)
- return 0;
- else if (nread > 0)
- {
- int r = 0;
- int written = 0;
-
- do {
- r = write (out, &buf, nread);
- } while ((r < 0 && errno == EINTR)
- || (r > 0 && (written += r) && written != nread));
-
- if (r < 0)
- return 0;
-
- if (sigio && emacs_pid)
- kill (emacs_pid, SIGIO);
- }
- return 1;
-}
-
-int
-pty_conversation (FILE *in)
-{
- char *str;
- char string[BUFSIZ];
- fd_set set, rset;
- int res;
-
- FD_ZERO (&set);
- FD_SET (master, &set);
- FD_SET (1, &set);
- FD_SET (fileno (in), &set);
-
- in_conversation = 1;
-
- while (! quit_conversation) {
- rset = set;
- res = select (FD_SETSIZE, &rset, NULL, NULL, NULL);
- if (res < 0 && errno != EINTR)
- {
- reset_tty ();
- fprintf (stderr, "%s: ", progname);
- perror ("select");
- return 0; /* Error */
- }
- else if (res > 0)
- {
- if (FD_ISSET (master, &rset))
- {
- /* Copy Emacs output to stdout. */
- if (! copy_from_to (master, 0, 0))
- {
- FD_CLR (master, &set);
- }
- }
- if (FD_ISSET (1, &rset))
- {
- /* Forward user input to Emacs. */
- if (! copy_from_to (1, master, 1))
- {
- FD_CLR (master, &set);
- }
- }
- if (FD_ISSET (fileno (in), &rset))
- {
- do {
- res = read (fileno (in), string, BUFSIZ-1);
- } while (res < 0 && errno == EINTR);
- if (res < 0)
- {
- reset_tty ();
- fprintf (stderr, "%s: ", progname);
- perror ("read");
- return 0;
- }
- if (!res)
- {
- return 1;
- }
-
- string[res] = 0;
- if (string[res-1] == '\n')
- string[res-1] = 0;
-
- if (! emacs_pid)
- {
- /* Get the pid of the Emacs process.
- XXX Is there some nifty libc/kernel feature for doing this?
- */
- if (! string[0])
- {
- reset_tty ();
- fprintf (stderr, "%s: could not get Emacs process id\n"
- "Maybe this Emacs does not support multiple terminals.\n", progname);
- return 0;
- }
- emacs_pid = strtol (string, NULL, 10);
- }
-
- if (! emacs_pid) /* emacs_pid should be set above */
- {
- reset_tty ();
- fprintf (stderr, "%s: %s\n", progname, string);
- return 0;
- }
- }
- }
- }
- return 1;
}
-#endif /* HAVE_TERMIOS */
-
#if !defined (HAVE_SOCKETS) || defined (NO_SOCKETS_IN_FILE_SYSTEM)
@@ -886,6 +347,23 @@ socket_status (socket_name)
return 0;
}
+/* Returns 1 if PREFIX is a prefix of STRING. */
+static int
+strprefix (char *prefix, char *string)
+{
+ int i;
+ if (! prefix)
+ return 1;
+
+ if (!string)
+ return 0;
+
+ for (i = 0; prefix[i]; i++)
+ if (!string[i] || string[i] != prefix[i])
+ return 0;
+ return 1;
+}
+
int
main (argc, argv)
int argc;
@@ -1086,31 +564,14 @@ To start the server in Emacs, type \"M-x server-start\".\n",
if (frame)
{
- if (! init_signals ())
- {
- fprintf (stderr, "%s: ", argv[0]);
- perror ("fdopen");
- fail ();
- }
-
- if (! init_tty ())
- {
- reset_tty ();
- fprintf (stderr, "%s: ", argv[0]);
- perror ("fdopen");
- fail ();
- }
+ char *tty_name = ttyname (fileno (stdin));
+ if (! tty_name)
+ fail ();
- if (! init_pty ())
- {
- reset_tty ();
- fprintf (stderr, "%s: ", argv[0]);
- perror ("fdopen");
- fail ();
- }
+ init_signals ();
fprintf (out, "-tty ");
- quote_file_name (pty_name, out);
+ quote_file_name (tty_name, out);
fprintf (out, " ");
quote_file_name (getenv("TERM"), out);
fprintf (out, " ");
@@ -1160,22 +621,10 @@ To start the server in Emacs, type \"M-x server-start\".\n",
/* Maybe wait for an answer. */
if (nowait)
{
- reset_tty ();
return 0;
}
- if (frame)
- {
- if (! pty_conversation (out))
- {
- reset_tty ();
- fail ();
- }
- reset_tty ();
- return 0;
- }
-
- if (!eval)
+ if (!eval && !frame)
{
printf ("Waiting for Emacs...");
needlf = 2;
@@ -1185,17 +634,26 @@ To start the server in Emacs, type \"M-x server-start\".\n",
/* Now, wait for an answer and print any messages. */
while ((str = fgets (string, BUFSIZ, in)))
{
- if (needlf == 2)
- printf ("\n");
- printf ("%s", str);
- needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+ if (frame)
+ {
+ if (strprefix ("emacs-pid ", str))
+ {
+ emacs_pid = strtol (string + strlen ("emacs-pid"), NULL, 10);
+ }
+ }
+ else
+ {
+ if (needlf == 2)
+ printf ("\n");
+ printf ("%s", str);
+ needlf = str[0] == '\0' ? needlf : str[strlen (str) - 1] != '\n';
+ }
}
if (needlf)
printf ("\n");
fflush (stdout);
- reset_tty ();
return 0;
}