# HG changeset patch # User Karoly Lorentey # Date 1073118674 0 # Node ID 039bd6989d29f0e42aac8e557b78184eec8525d8 # Parent 44ffe551079c9e6ac0e6549778946053aef190e1 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 , 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 diff -r 44ffe551079c -r 039bd6989d29 README.multi-tty --- a/README.multi-tty Fri Jan 02 13:03:12 2004 +0000 +++ b/README.multi-tty Sat Jan 03 08:31:14 2004 +0000 @@ -130,7 +130,9 @@ ** Something with (maybe) multi-keyboard support broke function keys and arrows on ttys during X+tty combo sessions. Debug this. -** Fix faces on tty frames during X-tty combo sessions. +** Fix faces on tty frames during X-tty combo sessions. There is an + init_frame_faces call in init_sys_modes, see if there is a problem + with it. ** During an X-tty combo session, a (message "Hello") from a tty frame goes to the X frame. Fix this. @@ -186,7 +188,8 @@ select(9, [0 3 5 6], NULL, NULL, {0, 0}) = 2 (in [5 6], left {0, 0}) gettimeofday({1072842297, 748245}, NULL) = 0 - I have not been able to reproduce this. + I have seen something similar with a single X frame, but have not + been able to reproduce it for debugging. ** Define a output_initial value for output_method for the initial frame that is dumped with Emacs. Checking for this frame (e.g. in @@ -196,6 +199,12 @@ about face problems. This can even lock up Emacs (if the recursive frame sets single_kboard). +** Clean up the source of emacsclient. It is a mess. + +** C-x 5 2, C-x 5 o, C-x 5 0 on an emacsclient frame unexpectedly + exits emacsclient. This is a result of trying to be clever with + delete-frame-functions. + DIARY OF CHANGES ---------------- diff -r 44ffe551079c -r 039bd6989d29 lib-src/emacsclient.c --- a/lib-src/emacsclient.c Fri Jan 02 13:03:12 2004 +0000 +++ b/lib-src/emacsclient.c Sat Jan 03 08:31:14 2004 +0000 @@ -41,54 +41,10 @@ # include #endif /* not VMS */ - -/****************************************/ - +#include #include -#include - -#ifndef INCLUDED_FCNTL -#define INCLUDED_FCNTL -#include -#endif - -#ifdef HAVE_TERMIOS -#ifndef NO_TERMIO -#include -#endif -#include -#endif /* not HAVE_TERMIOS */ - -#ifdef __GNU_LIBRARY__ -#include -#include -#endif - -#if (defined (POSIX) || defined (NEED_UNISTD_H)) && defined (HAVE_UNISTD_H) -#include -#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 (); @@ -314,532 +270,37 @@ } } - -#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 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); +#if defined (USG) || defined (DGUX) +unsigned char _sobuf[BUFSIZ+8]; +#else +char _sobuf[BUFSIZ]; #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 = 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; + if (emacs_pid) + kill (emacs_pid, SIGWINCH); - 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); - - 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 @@ 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 @@ 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 @@ /* 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 @@ /* 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; } diff -r 44ffe551079c -r 039bd6989d29 lisp/server.el --- a/lisp/server.el Fri Jan 02 13:03:12 2004 +0000 +++ b/lisp/server.el Sat Jan 03 08:31:14 2004 +0000 @@ -106,10 +106,11 @@ that can be given to the server process to identify a client. When a buffer is marked as \"done\", it is removed from this list.") -(defvar server-frames nil - "List of current server frames. -Each element is (CLIENTID FRAME) where CLIENTID is a string +(defvar server-ttys nil + "List of current terminal devices used by the server. +Each element is (CLIENTID TTY) where CLIENTID is a string that can be given to the server process to identify a client. +TTY is the name of the tty device. When all the buffers of the client are marked as \"done\", the frame is deleted.") @@ -180,6 +181,14 @@ string) (or (bolp) (newline))))) +(defun server-tty-live-p (tty) + "Return non-nil if the tty device named TTY has a live frame." + (let (result) + (dolist (frame (frame-list) result) + (when (and (eq (frame-live-p frame) t) + (equal (frame-tty-name frame) tty)) + (setq result t))))) + (defun server-sentinel (proc msg) (let ((client (assq proc server-clients))) ;; Remove PROC from the list of clients. @@ -195,22 +204,21 @@ (not server-existing-buffer)) (server-temp-file-p))) (kill-buffer (current-buffer))))) - (let ((frame (assq (car client) server-frames))) - (when frame - (setq server-frames (delq frame server-frames)) - (when (frame-live-p (cadr frame)) (delete-frame (cadr frame) 'force)))))) + (let ((tty (assq (car client) server-ttys))) + (when tty + (setq server-ttys (delq tty server-ttys)) + (when (server-tty-live-p (cadr tty)) + (delete-tty (cadr tty))))))) (server-log (format "Status changed to %s" (process-status proc)) proc)) -(defun server-handle-delete-frame (frame) - (dolist (entry server-frames) +(defun server-handle-delete-tty (tty) + (dolist (entry server-ttys) (let ((proc (nth 0 entry)) - (f (nth 1 entry))) - (when (eq f frame) + (term (nth 1 entry))) + (when (equal term tty) (let ((client (assq proc server-clients))) - (if (and (cdr client) (not (yes-or-no-p "Frame has pending buffers; close anyway? "))) - (error "Frame deletion cancelled") - (setq server-frames (delq entry server-frames)) - (delete-process (car client)))))))) + (setq server-ttys (delq entry server-ttys)) + (delete-process (car client))))))) (defun server-select-display (display) ;; If the current frame is on `display' we're all set. @@ -280,15 +288,15 @@ (let ((buffer (nth 1 (car server-clients)))) (server-buffer-done buffer))) ;; Delete any remaining opened frames of the previous server. - (while server-frames - (let ((frame (cadar server-frames))) - (setq server-frames (cdr server-frames)) - (when (frame-live-p frame) (delete-frame frame 'force)))) + (while server-ttys + (let ((tty (cadar server-ttys))) + (setq server-ttys (cdr server-ttys)) + (when (server-tty-live-p tty) (delete-tty tty)))) (unless leave-dead (if server-process (server-log (message "Restarting server"))) (letf (((default-file-modes) ?\700)) - (add-to-list 'delete-frame-functions 'server-handle-delete-frame) + (add-to-list 'delete-tty-after-functions 'server-handle-delete-tty) (setq server-process (make-network-process :name "server" :family 'local :server t :noquery t @@ -354,9 +362,9 @@ (setq request (substring request (match-end 0))) (condition-case err (let ((frame (make-frame-on-tty tty type))) - (setq server-frames (cons (list (car client) frame) server-frames)) + (setq server-ttys (cons (list (car client) (frame-tty-name frame)) server-ttys)) (sit-for 0) - (process-send-string proc (concat (number-to-string (emacs-pid)) "\n")) + (process-send-string proc (concat "emacs-pid " (number-to-string (emacs-pid)) "\n")) (select-frame frame) (setq newframe t)) (error (ignore-errors (process-send-string proc (concat (nth 1 err) "\n"))) @@ -488,9 +496,15 @@ ;; If client now has no pending buffers, ;; tell it that it is done, and forget it entirely. (unless (cdr client) - (delete-process (car client)) - (server-log "Close" (car client)) - (setq server-clients (delq client server-clients)))) + (let ((tty (assq (car client) server-ttys))) + (if tty + ;; Be careful, if we delete the process before the + ;; tty, then the terminal modes will not be restored + ;; correctly. + (delete-tty (cadr tty)) + (delete-process (car client)) + (server-log "Close" (car client)) + (setq server-clients (delq client server-clients)))))) (setq old-clients (cdr old-clients))) (if (and (bufferp buffer) (buffer-name buffer)) ;; We may or may not kill this buffer; diff -r 44ffe551079c -r 039bd6989d29 src/Makefile.in --- a/src/Makefile.in Fri Jan 02 13:03:12 2004 +0000 +++ b/src/Makefile.in Sat Jan 03 08:31:14 2004 +0000 @@ -1142,7 +1142,7 @@ msdos.h composite.h fontset.h blockinput.h atimer.h systime.h keymap.h xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ window.h charset.h msdos.h dosfns.h composite.h atimer.h systime.h \ - systty.h termchar.h $(config_h) + termchar.h $(config_h) xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \ charset.h gtkutil.h systty.h termchar.h $(config_h) diff -r 44ffe551079c -r 039bd6989d29 src/cm.c --- a/src/cm.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/cm.c Sat Jan 03 08:31:14 2004 +0000 @@ -70,8 +70,7 @@ { if (TTY_TERMSCRIPT (current_tty)) putc (c & 0177, TTY_TERMSCRIPT (current_tty)); - if (putc (c & 0177, TTY_OUTPUT (current_tty)) == EOF) - abort (); /* XXX For testing only! */ + putc (c & 0177, TTY_OUTPUT (current_tty)); return c; } diff -r 44ffe551079c -r 039bd6989d29 src/dispnew.c --- a/src/dispnew.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/dispnew.c Sat Jan 03 08:31:14 2004 +0000 @@ -5925,7 +5925,7 @@ int old_errno = errno; struct tty_display_info *tty; - + /* The frame size change obviously applies to a single termcap-controlled terminal, but we can't decide which. Therefore, we resize the frames corresponding to each tty. @@ -5934,22 +5934,18 @@ if (! tty->term_initted) continue; - + get_tty_size (fileno (TTY_INPUT (tty)), &width, &height); { Lisp_Object tail, frame; FOR_EACH_FRAME (tail, frame) - { - if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty) - { - /* Record the new sizes, but don't reallocate the data structures - now. Let that be done later outside of the signal handler. */ - change_frame_size (XFRAME (frame), height, width, 0, 1, 0); - break; - } - } + if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty) + /* Record the new sizes, but don't reallocate the data + structures now. Let that be done later outside of the + signal handler. */ + change_frame_size (XFRAME (frame), height, width, 0, 1, 0); } } diff -r 44ffe551079c -r 039bd6989d29 src/indent.c --- a/src/indent.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/indent.c Sat Jan 03 08:31:14 2004 +0000 @@ -20,6 +20,8 @@ Boston, MA 02111-1307, USA. */ #include +#include + #include "lisp.h" #include "buffer.h" #include "charset.h" diff -r 44ffe551079c -r 039bd6989d29 src/sysdep.c --- a/src/sysdep.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/sysdep.c Sat Jan 03 08:31:14 2004 +0000 @@ -913,6 +913,29 @@ } } +#ifndef SIGIO +/* If SIGIO is broken, don't do anything. */ +void +init_sigio (int fd) +{ +} + +void +reset_sigio (int fd) +{ +} + +void +request_sigio (void) +{ +} + +void +unrequest_sigio (void) +{ +} + +#else #ifdef F_SETFL int old_fcntl_flags[MAXDESC]; @@ -932,10 +955,13 @@ reset_sigio (fd) int fd; { +#ifdef FASYNC fcntl (fd, F_SETFL, old_fcntl_flags[fd]); +#endif } #ifdef FASYNC /* F_SETFL does not imply existence of FASYNC */ +/* XXX Uhm, this FASYNC is not used anymore here. */ void request_sigio () @@ -1053,6 +1079,7 @@ #endif /* STRIDE */ #endif /* FASYNC */ #endif /* F_SETFL */ +#endif /* SIGIO */ /* Saving and restoring the process group of Emacs's terminal. */ @@ -1368,6 +1395,7 @@ #ifdef HAVE_WINDOW_SYSTEM /* Emacs' window system on MSDOG uses the `internal terminal' and therefore needs the initialization code below. */ + /* XXX This need to be revised for X+tty session support. */ if (tty_out->input != stdin || (!read_socket_hook && EQ (Vwindow_system, Qnil))) #endif { @@ -1641,6 +1669,8 @@ #else setbuf (TTY_OUTPUT (tty_out), (char *) _sobuf); #endif + +#if 0 /* We always need this with multi-tty support. */ #ifdef HAVE_WINDOW_SYSTEM /* Emacs' window system on MSDOG uses the `internal terminal' and therefore needs the initialization code below. */ @@ -1652,6 +1682,8 @@ #endif ) #endif +#endif + tty_set_terminal_modes (tty_out); if (!tty_out->term_initted) { @@ -1750,7 +1782,6 @@ *widthp = 0; *heightp = 0; #endif - #endif /* not VMS */ #endif /* not SunOS-style */ #endif /* not BSD-style */ @@ -1815,6 +1846,7 @@ } if (!tty_out->term_initted) return; +#if 0 /* We always need to do this with multi-tty support. */ #ifdef HAVE_WINDOW_SYSTEM /* Emacs' window system on MSDOG uses the `internal terminal' and therefore needs the clean-up code below. */ @@ -1828,7 +1860,8 @@ )) return; #endif - +#endif + cmgoto (tty_out, FrameRows (tty_out) - 1, 0); tty_clear_end_of_line (tty_out, FrameCols (tty_out)); cmgoto (tty_out, FrameRows (tty_out) - 1, 0); diff -r 44ffe551079c -r 039bd6989d29 src/syssignal.h --- a/src/syssignal.h Fri Jan 02 13:03:12 2004 +0000 +++ b/src/syssignal.h Sat Jan 03 08:31:14 2004 +0000 @@ -25,6 +25,7 @@ indicate that SIGIO doesn't work by #undef-ing SIGIO. If this file #includes , then that will re-#define SIGIO and confuse things. */ +/* XXX This is not correct anymore, there is a BROKEN_SIGIO macro. */ #define SIGMASKTYPE sigset_t diff -r 44ffe551079c -r 039bd6989d29 src/term.c --- a/src/term.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/term.c Sat Jan 03 08:31:14 2004 +0000 @@ -100,6 +100,9 @@ Lisp_Object Vring_bell_function; +/* Functions to call after a tty was deleted. */ +Lisp_Object Vdelete_tty_after_functions; + /* Terminal characteristics that higher levels want to look at. */ struct tty_display_info *tty_list; @@ -2751,8 +2754,6 @@ /* Init system terminal modes (RAW or CBREAK, etc.). */ init_sys_modes (tty); - tty_set_terminal_modes (tty); - return tty; #endif /* not WINDOWSNT */ } @@ -2772,7 +2773,11 @@ DEFUN ("delete-tty", Fdelete_tty, Sdelete_tty, 0, 1, 0, - doc: /* Delete all frames on the terminal named TTY, and close the device. */) + doc: /* Delete all frames on the terminal named TTY, and close the device. +If omitted, TTY defaults to the controlling terminal. + +This function runs `delete-tty-after-functions' after closing the +tty. The functions are run with one arg, the frame to be deleted. */) (tty) Lisp_Object tty; { @@ -2802,7 +2807,8 @@ delete_tty (struct tty_display_info *tty) { Lisp_Object tail, frame; - + char *tty_name; + if (deleting_tty) /* We get a recursive call when we delete the last frame on this tty. */ @@ -2838,8 +2844,7 @@ reset_sys_modes (tty); - if (tty->name) - xfree (tty->name); + tty_name = tty->name; if (tty->type) xfree (tty->type); @@ -2873,6 +2878,21 @@ bzero (tty, sizeof (struct tty_display_info)); xfree (tty); deleting_tty = 0; + + /* Run `delete-tty-after-functions'. */ + if (!NILP (Vrun_hooks)) + { + Lisp_Object args[2]; + args[0] = intern ("delete-tty-after-functions"); + if (tty_name) + { + args[1] = build_string (tty_name); + xfree (tty_name); + } + else + args[1] = Qnil; + Frun_hook_with_args (2, args); + } } @@ -2911,6 +2931,12 @@ The function should accept no arguments. */); Vring_bell_function = Qnil; + DEFVAR_LISP ("delete-tty-after-functions", &Vdelete_tty_after_functions, + doc: /* Functions to be run after deleting a tty. +The functions are run with one argument, the name of the tty to be deleted. +See `delete-tty'. */); + Vdelete_tty_after_functions = Qnil; + Qframe_tty_name = intern ("frame-tty-name"); staticpro (&Qframe_tty_name); diff -r 44ffe551079c -r 039bd6989d29 src/window.c --- a/src/window.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/window.c Sat Jan 03 08:31:14 2004 +0000 @@ -21,6 +21,8 @@ Boston, MA 02111-1307, USA. */ #include +#include + #include "lisp.h" #include "buffer.h" #include "keyboard.h" diff -r 44ffe551079c -r 039bd6989d29 src/xfaces.c --- a/src/xfaces.c Fri Jan 02 13:03:12 2004 +0000 +++ b/src/xfaces.c Sat Jan 03 08:31:14 2004 +0000 @@ -194,6 +194,7 @@ #include #include #include +#include /* This needs to be before termchar.h */ #include "lisp.h" #include "charset.h" @@ -241,7 +242,6 @@ #include "blockinput.h" #include "window.h" #include "intervals.h" -#include "systty.h" /* For emacs_tty in termchar.h */ #include "termchar.h" #ifdef HAVE_X_WINDOWS @@ -263,7 +263,6 @@ #endif /* HAVE_X_WINDOWS */ -#include #include #define abs(X) ((X) < 0 ? -(X) : (X))