comparison src/process-unix.c @ 853:2b6fa2618f76

[xemacs-hg @ 2002-05-28 08:44:22 by ben] merge my stderr-proc ws make-docfile.c: Fix places where we forget to check for EOF. code-init.el: Don't use CRLF conversion by default on process output. CMD.EXE and friends work both ways but Cygwin programs don't like the CRs. code-process.el, multicast.el, process.el: Removed. Improvements to call-process-internal: -- allows a buffer to be specified for input and stderr output -- use it on all systems -- implement C-g as documented -- clean up and comment call-process-region uses new call-process facilities; no temp file. remove duplicate funs in process.el. comment exactly how coding systems work and fix various problems. open-multicast-group now does similar coding-system frobbing to open-network-stream. dumped-lisp.el, faces.el, msw-faces.el: Fix some hidden errors due to code not being defined at the right time. xemacs.mak: Add -DSTRICT. ================================================================ ALLOW SEPARATION OF STDOUT AND STDERR IN PROCESSES ================================================================ Standard output and standard error can be processed separately in a process. Each can have its own buffer, its own mark in that buffer, and its filter function. You can specify a separate buffer for stderr in `start-process' to get things started, or use the new primitives: set-process-stderr-buffer process-stderr-buffer process-stderr-mark set-process-stderr-filter process-stderr-filter Also, process-send-region takes a 4th optional arg, a buffer. Currently always uses a pipe() under Unix to read the error output. (#### Would a PTY be better?) sysdep.h, sysproc.h, unexfreebsd.c, unexsunos4.c, nt.c, emacs.c, callproc.c, symsinit.h, sysdep.c, Makefile.in.in, process-unix.c: Delete callproc.c. Move child_setup() to process-unix.c. wait_for_termination() now only needed on a few really old systems. console-msw.h, event-Xt.c, event-msw.c, event-stream.c, event-tty.c, event-unixoid.c, events.h, process-nt.c, process-unix.c, process.c, process.h, procimpl.h: Rewrite the process methods to handle a separate channel for error input. Create Lstreams for reading in the error channel. Many process methods need change. In general the changes are fairly clear as they involve duplicating what's used for reading the normal stdout and changing for stderr -- although tedious, as such changes are required throughout the entire process code. Rewrote the code that reads process output to do two loops, one for stdout and one for stderr. gpmevent.c, tooltalk.c: set_process_filter takes an argument for stderr. ================================================================ NEW ERROR-TRAPPING MECHANISM ================================================================ Totally rewrite error trapping code to be unified and support more features. Basic function is call_trapping_problems(), which lets you specify, by means of flags, what sorts of problems you want trapped. these can include -- quit -- errors -- throws past the function -- creation of "display objects" (e.g. buffers) -- deletion of already-existing "display objects" (e.g. buffers) -- modification of already-existing buffers -- entering the debugger -- gc -- errors->warnings (ala suspended errors) etc. All other error funs rewritten in terms of this one. Various older mechanisms removed or rewritten. window.c, insdel.c, console.c, buffer.c, device.c, frame.c: When creating a display object, added call to note_object_created(), for use with trapping_problems mechanism. When deleting, call check_allowed_operation() and note_object deleted(). The trapping-problems code records the objects created since the call-trapping-problems began. Those objects can be deleted, but none others (i.e. previously existing ones). bytecode.c, cmdloop.c: internal_catch takes another arg. eval.c: Add long comments describing the "five lists" used to maintain state (backtrace, gcpro, specbind, etc.) in the Lisp engine. backtrace.h, eval.c: Implement trapping-problems mechanism, eliminate old mechanisms or redo in terms of new one. frame.c, gutter.c: Flush out the concept of "critical display section", defined by the in_display() var. Use an internal_bind() to get it reset, rather than just doing it at end, because there may be a non-local exit. event-msw.c, event-stream.c, console-msw.h, device.c, dialog-msw.c, frame.c, frame.h, intl.c, toolbar.c, menubar-msw.c, redisplay.c, alloc.c, menubar-x.c: Make use of new trapping-errors stuff and rewrite code based on old mechanisms. glyphs-widget.c, redisplay.h: Protect calling Lisp in redisplay. insdel.c: Protect hooks against deleting existing buffers. frame-msw.c: Use EQ, not EQUAL in hash tables whose keys are just numbers. Otherwise we run into stickiness in redisplay because internal_equal() can QUIT. ================================================================ SIGNAL, C-G CHANGES ================================================================ Here we change the way that C-g interacts with event reading. The idea is that a C-g occurring while we're reading a user event should be read as C-g, but elsewhere should be a QUIT. The former code did all sorts of bizarreness -- requiring that no QUIT occurs anywhere in event-reading code (impossible to enforce given the stuff called or Lisp code invoked), and having some weird system involving enqueue/dequeue of a C-g and interaction with Vquit_flag -- and it didn't work. Now, we simply enclose all code where we want C-g read as an event with {begin/end}_dont_check_for_quit(). This completely turns off the mechanism that checks (and may remove or alter) C-g in the read-ahead queues, so we just get the C-g normal. Signal.c documents this very carefully. cmdloop.c: Correct use of dont_check_for_quit to new scheme, remove old out-of-date comments. event-stream.c: Fix C-g handling to actually work. device-x.c: Disable quit checking when err out. signal.c: Cleanup. Add large descriptive comment. process-unix.c, process-nt.c, sysdep.c: Use QUIT instead of REALLY_QUIT. It's not necessary to use REALLY_QUIT and just confuses the issue. lisp.h: Comment quit handlers. ================================================================ CONS CHANGES ================================================================ free_cons() now takes a Lisp_Object not the result of XCONS(). car and cdr have been renamed so that they don't get used directly; go through XCAR(), XCDR() instead. alloc.c, dired.c, editfns.c, emodules.c, fns.c, glyphs-msw.c, glyphs-x.c, glyphs.c, keymap.c, minibuf.c, search.c, eval.c, lread.c, lisp.h: Correct free_cons calling convention: now takes Lisp_Object, not Lisp_Cons chartab.c: Eliminate direct use of ->car, ->cdr, should be black box. callint.c: Rewrote using EXTERNAL_LIST_LOOP to avoid use of Lisp_Cons. ================================================================ USE INTERNAL-BIND-* ================================================================ eval.c: Cleanups of these funs. alloc.c, fileio.c, undo.c, specifier.c, text.c, profile.c, lread.c, redisplay.c, menubar-x.c, macros.c: Rewrote to use internal_bind_int() and internal_bind_lisp_object() in place of whatever varied and cumbersome mechanisms were formerly there. ================================================================ SPECBIND SANITY ================================================================ backtrace.h: - Improved comments backtrace.h, bytecode.c, eval.c: Add new mechanism check_specbind_stack_sanity() for sanity checking code each time the catchlist or specbind stack change. Removed older prototype of same mechanism. ================================================================ MISC ================================================================ lisp.h, insdel.c, window.c, device.c, console.c, buffer.c: Fleshed out authorship. device-msw.c: Correct bad Unicode-ization. print.c: Be more careful when not initialized or in fatal error handling. search.c: Eliminate running_asynch_code, an FSF holdover. alloc.c: Added comments about gc-cons-threshold. dialog-x.c: Use begin_gc_forbidden() around code to build up a widget value tree, like in menubar-x.c. gui.c: Use Qunbound not Qnil as the default for gethash. lisp-disunion.h, lisp-union.h: Added warnings on use of VOID_TO_LISP(). lisp.h: Use ERROR_CHECK_STRUCTURES to turn on ERROR_CHECK_TRAPPING_PROBLEMS and ERROR_CHECK_TYPECHECK lisp.h: Add assert_with_message. lisp.h: Add macros for gcproing entire arrays. (You could do this before but it required manual twiddling the gcpro structure.) lisp.h: Add prototypes for new functions defined elsewhere.
author ben
date Tue, 28 May 2002 08:45:36 +0000
parents 6728e641994e
children 1d8fb2eee1bb
comparison
equal deleted inserted replaced
852:d83885ef293b 853:2b6fa2618f76
49 #include "sysdep.h" 49 #include "sysdep.h"
50 #include "window.h" 50 #include "window.h"
51 #include "file-coding.h" 51 #include "file-coding.h"
52 52
53 #include <setjmp.h> 53 #include <setjmp.h>
54 #include "sysdir.h"
54 #include "sysfile.h" 55 #include "sysfile.h"
55 #include "sysproc.h" 56 #include "sysproc.h"
56 #include "systime.h" 57 #include "systime.h"
57 #include "syssignal.h" /* Always include before systty.h */ 58 #include "syssignal.h" /* Always include before systty.h */
58 #include "systty.h" 59 #include "systty.h"
75 { 76 {
76 /* Non-0 if this is really a ToolTalk channel. */ 77 /* Non-0 if this is really a ToolTalk channel. */
77 int connected_via_filedesc_p; 78 int connected_via_filedesc_p;
78 /* Descriptor by which we read from this process. -1 for dead process */ 79 /* Descriptor by which we read from this process. -1 for dead process */
79 int infd; 80 int infd;
81 /* Descriptor by which we read stderr from this process. -1 for
82 dead process */
83 int errfd;
80 /* Descriptor for the tty which this process is using. 84 /* Descriptor for the tty which this process is using.
81 -1 if we didn't record it (on some systems, there's no need). */ 85 -1 if we didn't record it (on some systems, there's no need). */
82 int subtty; 86 int subtty;
83 /* Name of subprocess terminal. */ 87 /* Name of subprocess terminal. */
84 Lisp_Object tty_name; 88 Lisp_Object tty_name;
85 /* Non-false if communicating through a pty. */ 89 /* Non-false if communicating through a pty. */
86 char pty_flag; 90 char pty_flag;
87 }; 91 };
88 92
89 #define UNIX_DATA(p) ((struct unix_process_data*)((p)->process_data)) 93 #define UNIX_DATA(p) ((struct unix_process_data*) ((p)->process_data))
90 94
91 95
92 96
93 /**********************************************************************/ 97 /**********************************************************************/
94 /* Static helper routines */ 98 /* Static helper routines */
124 /* Close all descriptors currently in use for communication 128 /* Close all descriptors currently in use for communication
125 with subprocess. This is used in a newly-forked subprocess 129 with subprocess. This is used in a newly-forked subprocess
126 to get rid of irrelevant descriptors. */ 130 to get rid of irrelevant descriptors. */
127 131
128 static int 132 static int
129 close_process_descs_mapfun (const void* key, void* contents, void* arg) 133 close_process_descs_mapfun (const void *key, void *contents, void *arg)
130 { 134 {
131 Lisp_Object proc; 135 Lisp_Object proc = VOID_TO_LISP (contents);
132 proc = VOID_TO_LISP (contents); 136 USID vaffan, culo;
133 event_stream_delete_stream_pair (XPROCESS(proc)->pipe_instream, 137
134 XPROCESS(proc)->pipe_outstream); 138 event_stream_delete_io_streams (XPROCESS (proc)->pipe_instream,
139 XPROCESS (proc)->pipe_outstream,
140 XPROCESS (proc)->pipe_errstream,
141 &vaffan, &culo);
135 return 0; 142 return 0;
136 } 143 }
137 144
138 /* #### This function is currently called from child_setup
139 in callproc.c. It should become static though - kkm */
140 void 145 void
141 close_process_descs (void) 146 close_process_descs (void)
142 { 147 {
143 maphash (close_process_descs_mapfun, usid_to_process, 0); 148 maphash (close_process_descs_mapfun, usid_to_process, 0);
144 } 149 }
184 buffer = Fget_buffer_create (buffer); 189 buffer = Fget_buffer_create (buffer);
185 proc = make_process_internal (name); 190 proc = make_process_internal (name);
186 191
187 XPROCESS (proc)->pid = Fcons (infd, name); 192 XPROCESS (proc)->pid = Fcons (infd, name);
188 XPROCESS (proc)->buffer = buffer; 193 XPROCESS (proc)->buffer = buffer;
189 init_process_io_handles (XPROCESS (proc), (void*)inch, (void*)XINT (outfd), 194 init_process_io_handles (XPROCESS (proc), (void *) inch,
190 0); 195 (void *) XINT (outfd), (void *) -1, 0);
191 UNIX_DATA (XPROCESS (proc))->connected_via_filedesc_p = 1; 196 UNIX_DATA (XPROCESS (proc))->connected_via_filedesc_p = 1;
192 197
193 event_stream_select_process (XPROCESS (proc)); 198 event_stream_select_process (XPROCESS (proc), 1, 1);
194 199
195 return proc; 200 return proc;
196 } 201 }
197 202
198 static int allocate_pty_the_old_fashioned_way (void); 203 static int allocate_pty_the_old_fashioned_way (void);
510 return 1; 515 return 1;
511 } 516 }
512 #endif /* !USE_GETADDRINFO */ 517 #endif /* !USE_GETADDRINFO */
513 518
514 static void 519 static void
515 set_socket_nonblocking_maybe (int fd, int port, const char* proto) 520 set_socket_nonblocking_maybe (int fd, int port, const char *proto)
516 { 521 {
517 #ifdef PROCESS_IO_BLOCKING 522 #ifdef PROCESS_IO_BLOCKING
518 Lisp_Object tail; 523 Lisp_Object tail;
519 524
520 for (tail = network_stream_blocking_port_list; CONSP (tail); tail = XCDR (tail)) 525 for (tail = network_stream_blocking_port_list; CONSP (tail); tail = XCDR (tail))
718 723
719 static int 724 static int
720 process_signal_char (int tty_fd, int signo) 725 process_signal_char (int tty_fd, int signo)
721 { 726 {
722 /* If it's not a tty, pray that these default values work */ 727 /* If it's not a tty, pray that these default values work */
723 if (! isatty (tty_fd)) { 728 if (! isatty (tty_fd))
729 {
724 #define CNTL(ch) (037 & (ch)) 730 #define CNTL(ch) (037 & (ch))
725 switch (signo) 731 switch (signo)
726 { 732 {
727 case SIGINT: return CNTL ('C'); 733 case SIGINT: return CNTL ('C');
728 case SIGQUIT: return CNTL ('\\'); 734 case SIGQUIT: return CNTL ('\\');
729 #ifdef SIGTSTP 735 #ifdef SIGTSTP
730 case SIGTSTP: return CNTL ('Z'); 736 case SIGTSTP: return CNTL ('Z');
731 #endif 737 #endif
732 } 738 }
733 } 739 }
734 740
735 #ifdef HAVE_TERMIOS 741 #ifdef HAVE_TERMIOS
736 /* TERMIOS is the latest and bestest, and seems most likely to work. 742 /* TERMIOS is the latest and bestest, and seems most likely to work.
737 If the system has it, use it. */ 743 If the system has it, use it. */
738 { 744 {
803 { 809 {
804 p->process_data = xnew (struct unix_process_data); 810 p->process_data = xnew (struct unix_process_data);
805 811
806 UNIX_DATA(p)->connected_via_filedesc_p = 0; 812 UNIX_DATA(p)->connected_via_filedesc_p = 0;
807 UNIX_DATA(p)->infd = -1; 813 UNIX_DATA(p)->infd = -1;
814 UNIX_DATA(p)->errfd = -1;
808 UNIX_DATA(p)->subtty = -1; 815 UNIX_DATA(p)->subtty = -1;
809 UNIX_DATA(p)->tty_name = Qnil; 816 UNIX_DATA(p)->tty_name = Qnil;
810 UNIX_DATA(p)->pty_flag = 0; 817 UNIX_DATA(p)->pty_flag = 0;
811 } 818 }
812 819
841 * handles are generally represented by void* type, but are 848 * handles are generally represented by void* type, but are
842 * of type int (file descriptors) for UNIX. 849 * of type int (file descriptors) for UNIX.
843 */ 850 */
844 851
845 static void 852 static void
846 unix_init_process_io_handles (Lisp_Process *p, void* in, void* out, int flags) 853 unix_init_process_io_handles (Lisp_Process *p, void *in, void *out, void *err,
847 { 854 int flags)
848 UNIX_DATA(p)->infd = (int)in; 855 {
856 UNIX_DATA(p)->infd = (int) in;
857 UNIX_DATA(p)->errfd = (int) err;
858 }
859
860 /* Move the file descriptor FD so that its number is not less than MIN. *
861 The original file descriptor remains open. */
862 static int
863 relocate_fd (int fd, int min)
864 {
865 if (fd >= min)
866 return fd;
867 else
868 {
869 int newfd = dup (fd);
870 if (newfd == -1)
871 {
872 Intbyte *errmess;
873 GET_STRERROR (errmess, errno);
874 stderr_out ("Error while setting up child: %s\n", errmess);
875 _exit (1);
876 }
877 return relocate_fd (newfd, min);
878 }
879 }
880
881 /* This is the last thing run in a newly forked inferior process.
882 Copy descriptors IN, OUT and ERR
883 as descriptors STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO.
884 Initialize inferior's priority, pgrp, connected dir and environment.
885 then exec another program based on new_argv.
886
887 XEmacs: We've removed the SET_PGRP argument because it's already
888 done by the callers of child_setup.
889
890 CURRENT_DIR is an elisp string giving the path of the current
891 directory the subprocess should have. Since we can't really signal
892 a decent error from within the child (#### not quite correct in
893 XEmacs?), this should be verified as an executable directory by the
894 parent. */
895
896 static void
897 child_setup (int in, int out, int err, Intbyte **new_argv,
898 Lisp_Object current_dir)
899 {
900 Intbyte **env;
901 Intbyte *pwd;
902
903 #ifdef SET_EMACS_PRIORITY
904 if (emacs_priority != 0)
905 nice (- emacs_priority);
906 #endif
907
908 #if !defined (NO_SUBPROCESSES)
909 /* Close Emacs's descriptors that this process should not have. */
910 close_process_descs ();
911 #endif /* not NO_SUBPROCESSES */
912 close_load_descs ();
913
914 /* [[Note that use of alloca is always safe here. It's obvious for systems
915 that do not have true vfork or that have true (stack) alloca.
916 If using vfork and C_ALLOCA it is safe because that changes
917 the superior's static variables as if the superior had done alloca
918 and will be cleaned up in the usual way.]] -- irrelevant because
919 XEmacs does not use vfork. */
920 {
921 REGISTER Bytecount i;
922
923 i = XSTRING_LENGTH (current_dir);
924 pwd = alloca_array (Intbyte, i + 6);
925 memcpy (pwd, "PWD=", 4);
926 memcpy (pwd + 4, XSTRING_DATA (current_dir), i);
927 i += 4;
928 if (!IS_DIRECTORY_SEP (pwd[i - 1]))
929 pwd[i++] = DIRECTORY_SEP;
930 pwd[i] = 0;
931
932 /* [[We can't signal an Elisp error here; we're in a vfork. Since
933 the callers check the current directory before forking, this
934 should only return an error if the directory's permissions
935 are changed between the check and this chdir, but we should
936 at least check.]] -- irrelevant because XEmacs does not use vfork. */
937 if (qxe_chdir (pwd + 4) < 0)
938 {
939 /* Don't report the chdir error, or ange-ftp.el doesn't work. */
940 /* (FSFmacs does _exit (errno) here.) */
941 pwd = 0;
942 }
943 else
944 {
945 /* Strip trailing "/". Cretinous *[]&@$#^%@#$% Un*x */
946 /* leave "//" (from FSF) */
947 while (i > 6 && IS_DIRECTORY_SEP (pwd[i - 1]))
948 pwd[--i] = 0;
949 }
950 }
951
952 /* Set `env' to a vector of the strings in Vprocess_environment. */
953 /* + 2 to include PWD and terminating 0. */
954 env = alloca_array (Intbyte *, XINT (Flength (Vprocess_environment)) + 2);
955 {
956 REGISTER Lisp_Object tail;
957 Intbyte **new_env = env;
958
959 /* If we have a PWD envvar and we know the real current directory,
960 pass one down, but with corrected value. */
961 if (pwd && egetenv ("PWD"))
962 *new_env++ = pwd;
963
964 /* Copy the Vprocess_environment strings into new_env. */
965 for (tail = Vprocess_environment;
966 CONSP (tail) && STRINGP (XCAR (tail));
967 tail = XCDR (tail))
968 {
969 Intbyte **ep = env;
970 Intbyte *envvar = XSTRING_DATA (XCAR (tail));
971
972 /* See if envvar duplicates any string already in the env.
973 If so, don't put it in.
974 When an env var has multiple definitions,
975 we keep the definition that comes first in process-environment. */
976 for (; ep != new_env; ep++)
977 {
978 Intbyte *p = *ep, *q = envvar;
979 while (1)
980 {
981 if (*q == 0)
982 /* The string is malformed; might as well drop it. */
983 goto duplicate;
984 if (*q != *p)
985 break;
986 if (*q == '=')
987 goto duplicate;
988 p++, q++;
989 }
990 }
991 if (pwd && !qxestrncmp ((Intbyte *) "PWD=", envvar, 4))
992 {
993 *new_env++ = pwd;
994 pwd = 0;
995 }
996 else
997 *new_env++ = envvar;
998
999 duplicate: ;
1000 }
1001
1002 *new_env = 0;
1003 }
1004
1005 /* Make sure that in, out, and err are not actually already in
1006 descriptors zero, one, or two; this could happen if Emacs is
1007 started with its standard in, out, or error closed, as might
1008 happen under X. */
1009 in = relocate_fd (in, 3);
1010 out = relocate_fd (out, 3);
1011 err = relocate_fd (err, 3);
1012
1013 /* Set the standard input/output channels of the new process. */
1014 retry_close (STDIN_FILENO);
1015 retry_close (STDOUT_FILENO);
1016 retry_close (STDERR_FILENO);
1017
1018 dup2 (in, STDIN_FILENO);
1019 dup2 (out, STDOUT_FILENO);
1020 dup2 (err, STDERR_FILENO);
1021
1022 retry_close (in);
1023 retry_close (out);
1024 retry_close (err);
1025
1026 /* I can't think of any reason why child processes need any more
1027 than the standard 3 file descriptors. It would be cleaner to
1028 close just the ones that need to be, but the following brute
1029 force approach is certainly effective, and not too slow.
1030
1031 #### Who the hell added this? We already close the descriptors
1032 by using close_process_descs()!!! --ben */
1033 {
1034 int fd;
1035 for (fd = 3; fd <= 64; fd++)
1036 retry_close (fd);
1037 }
1038
1039 /* we've wrapped execve; it translates its arguments */
1040 qxe_execve (new_argv[0], new_argv, env);
1041
1042 stdout_out ("Can't exec program %s\n", new_argv[0]);
1043 _exit (1);
849 } 1044 }
850 1045
851 /* 1046 /*
852 * Fork off a subprocess. P is a pointer to a newly created subprocess 1047 * Fork off a subprocess. P is a pointer to a newly created subprocess
853 * object. If this function signals, the caller is responsible for 1048 * object. If this function signals, the caller is responsible for
859 */ 1054 */
860 1055
861 static int 1056 static int
862 unix_create_process (Lisp_Process *p, 1057 unix_create_process (Lisp_Process *p,
863 Lisp_Object *argv, int nargv, 1058 Lisp_Object *argv, int nargv,
864 Lisp_Object program, Lisp_Object cur_dir) 1059 Lisp_Object program, Lisp_Object cur_dir,
1060 int separate_err)
865 { 1061 {
866 int pid; 1062 int pid;
867 int inchannel = -1; 1063 int inchannel = -1;
868 int outchannel = -1; 1064 int outchannel = -1;
1065 int errchannel = -1;
869 /* Use volatile to protect variables from being clobbered by longjmp. */ 1066 /* Use volatile to protect variables from being clobbered by longjmp. */
870 volatile int forkin = -1; 1067 volatile int forkin = -1;
871 volatile int forkout = -1; 1068 volatile int forkout = -1;
1069 volatile int forkerr = -1;
872 volatile int pty_flag = 0; 1070 volatile int pty_flag = 0;
873 1071
874 if (!NILP (Vprocess_connection_type)) 1072 if (!NILP (Vprocess_connection_type))
875 { 1073 {
876 /* find a new pty, open the master side, return the opened 1074 /* find a new pty, open the master side, return the opened
885 On some systems, we can open it here; this allows for 1083 On some systems, we can open it here; this allows for
886 better error checking. */ 1084 better error checking. */
887 #if !defined(USG) 1085 #if !defined(USG)
888 /* On USG systems it does not work to open the pty's tty here 1086 /* On USG systems it does not work to open the pty's tty here
889 and then close and reopen it in the child. */ 1087 and then close and reopen it in the child. */
890 #ifdef O_NOCTTY 1088 # ifdef O_NOCTTY
891 /* Don't let this terminal become our controlling terminal 1089 /* Don't let this terminal become our controlling terminal
892 (in case we don't have one). */ 1090 (in case we don't have one). */
893 forkout = forkin = qxe_open (pty_name, 1091 forkout = forkin = qxe_open (pty_name,
894 O_RDWR | O_NOCTTY | OPEN_BINARY, 0); 1092 O_RDWR | O_NOCTTY | OPEN_BINARY, 0);
895 #else 1093 # else
896 forkout = forkin = qxe_open (pty_name, O_RDWR | OPEN_BINARY, 0); 1094 forkout = forkin = qxe_open (pty_name, O_RDWR | OPEN_BINARY, 0);
897 #endif 1095 # endif
898 if (forkin < 0) 1096 if (forkin < 0)
899 goto io_failure; 1097 goto io_failure;
900 #endif /* not USG */ 1098 #endif /* not USG */
901 UNIX_DATA(p)->pty_flag = pty_flag = 1; 1099 UNIX_DATA (p)->pty_flag = pty_flag = 1;
902 } 1100 }
903 else 1101 else
904 if (create_bidirectional_pipe (&inchannel, &outchannel, 1102 if (create_bidirectional_pipe (&inchannel, &outchannel,
905 &forkin, &forkout) < 0) 1103 &forkin, &forkout) < 0)
906 goto io_failure; 1104 goto io_failure;
907 1105
1106 if (separate_err)
1107 {
1108 int sv[2];
1109
1110 if (pipe (sv) < 0)
1111 goto io_failure;
1112 forkerr = sv[1];
1113 errchannel = sv[0];
1114 }
1115
908 #if 0 1116 #if 0
909 /* Replaced by close_process_descs */ 1117 /* Replaced by close_process_descs */
910 set_exclusive_use (inchannel); 1118 set_exclusive_use (inchannel);
911 set_exclusive_use (outchannel); 1119 set_exclusive_use (outchannel);
912 #endif 1120 #endif
913 1121
914 set_descriptor_non_blocking (inchannel); 1122 set_descriptor_non_blocking (inchannel);
1123 if (errchannel >= 0)
1124 set_descriptor_non_blocking (errchannel);
915 1125
916 /* Record this as an active process, with its channels. 1126 /* Record this as an active process, with its channels.
917 As a result, child_setup will close Emacs's side of the pipes. */ 1127 As a result, child_setup will close Emacs's side of the pipes. */
918 init_process_io_handles (p, (void*)inchannel, (void*)outchannel, 1128 init_process_io_handles (p, (void *) inchannel, (void *) outchannel,
1129 (void *) errchannel,
919 pty_flag ? STREAM_PTY_FLUSHING : 0); 1130 pty_flag ? STREAM_PTY_FLUSHING : 0);
920 /* Record the tty descriptor used in the subprocess. */ 1131 /* Record the tty descriptor used in the subprocess. */
921 UNIX_DATA(p)->subtty = forkin; 1132 UNIX_DATA (p)->subtty = forkin;
922 1133
923 { 1134 {
924 pid = fork (); 1135 pid = fork ();
925 if (pid == 0) 1136 if (pid == 0)
926 { 1137 {
927 /**** Now we're in the child process ****/ 1138 /**** Now we're in the child process ****/
928 int xforkin = forkin; 1139 int xforkin = forkin;
929 int xforkout = forkout; 1140 int xforkout = forkout;
1141 int xforkerr = forkerr;
930 1142
931 /* Disconnect the current controlling terminal, pursuant to 1143 /* Disconnect the current controlling terminal, pursuant to
932 making the pty be the controlling terminal of the process. 1144 making the pty be the controlling terminal of the process.
933 Also put us in our own process group. */ 1145 Also put us in our own process group. */
934 1146
965 I deleted it. So sue me. */ 1177 I deleted it. So sue me. */
966 1178
967 /* SunOS has TIOCSCTTY but the close/open method 1179 /* SunOS has TIOCSCTTY but the close/open method
968 also works. */ 1180 also works. */
969 1181
970 # if defined (USG) || !defined (TIOCSCTTY) 1182 #if defined (USG) || !defined (TIOCSCTTY)
971 /* Now close the pty (if we had it open) and reopen it. 1183 /* Now close the pty (if we had it open) and reopen it.
972 This makes the pty the controlling terminal of the 1184 This makes the pty the controlling terminal of the
973 subprocess. */ 1185 subprocess. */
974 /* I wonder if retry_close (qxe_open (pty_name, ...)) would work? */ 1186 /* I wonder if retry_close (qxe_open (pty_name, ...)) would
1187 work? */
975 if (xforkin >= 0) 1188 if (xforkin >= 0)
976 retry_close (xforkin); 1189 retry_close (xforkin);
977 xforkout = xforkin = qxe_open (pty_name, O_RDWR | OPEN_BINARY, 0); 1190 xforkout = xforkin = qxe_open (pty_name, O_RDWR | OPEN_BINARY, 0);
978 if (xforkin < 0) 1191 if (xforkin < 0)
979 { 1192 {
980 retry_write (1, "Couldn't open the pty terminal ", 31); 1193 retry_write (1, "Couldn't open the pty terminal ", 31);
981 retry_write (1, pty_name, qxestrlen (pty_name)); 1194 retry_write (1, pty_name, qxestrlen (pty_name));
982 retry_write (1, "\n", 1); 1195 retry_write (1, "\n", 1);
983 _exit (1); 1196 _exit (1);
984 } 1197 }
985 # endif /* USG or not TIOCSCTTY */ 1198 #endif /* USG or not TIOCSCTTY */
986 1199
987 /* Miscellaneous setup required for some systems. 1200 /* Miscellaneous setup required for some systems.
988 Must be done before using tc* functions on xforkin. 1201 Must be done before using tc* functions on xforkin.
989 This guarantees that isatty(xforkin) is true. */ 1202 This guarantees that isatty(xforkin) is true. */
990 1203
991 # if defined (HAVE_ISASTREAM) && defined (I_PUSH) 1204 #if defined (HAVE_ISASTREAM) && defined (I_PUSH)
992 if (isastream (xforkin)) 1205 if (isastream (xforkin))
993 { 1206 {
994 # if defined (I_FIND) 1207 # if defined (I_FIND)
995 # define stream_module_pushed(fd, module) (ioctl (fd, I_FIND, module) == 1) 1208 # define stream_module_pushed(fd, module) (ioctl (fd, I_FIND, module) == 1)
996 # else 1209 # else
997 # define stream_module_pushed(fd, module) 0 1210 # define stream_module_pushed(fd, module) 0
998 # endif 1211 # endif
999 if (! stream_module_pushed (xforkin, "ptem")) 1212 if (! stream_module_pushed (xforkin, "ptem"))
1000 ioctl (xforkin, I_PUSH, "ptem"); 1213 ioctl (xforkin, I_PUSH, "ptem");
1001 if (! stream_module_pushed (xforkin, "ldterm")) 1214 if (! stream_module_pushed (xforkin, "ldterm"))
1002 ioctl (xforkin, I_PUSH, "ldterm"); 1215 ioctl (xforkin, I_PUSH, "ldterm");
1003 if (! stream_module_pushed (xforkin, "ttcompat")) 1216 if (! stream_module_pushed (xforkin, "ttcompat"))
1004 ioctl (xforkin, I_PUSH, "ttcompat"); 1217 ioctl (xforkin, I_PUSH, "ttcompat");
1005 } 1218 }
1006 # endif /* HAVE_ISASTREAM */ 1219 #endif /* defined (HAVE_ISASTREAM) && defined (I_PUSH) */
1007 1220
1008 # ifdef TIOCSCTTY 1221 #ifdef TIOCSCTTY
1009 /* We ignore the return value 1222 /* We ignore the return value
1010 because faith@cs.unc.edu says that is necessary on Linux. */ 1223 because faith@cs.unc.edu says that is necessary on Linux. */
1011 assert (isatty (xforkin)); 1224 assert (isatty (xforkin));
1012 ioctl (xforkin, TIOCSCTTY, 0); 1225 ioctl (xforkin, TIOCSCTTY, 0);
1013 # endif /* TIOCSCTTY */ 1226 #endif /* TIOCSCTTY */
1014 1227
1015 /* Change the line discipline. */ 1228 /* Change the line discipline. */
1016 1229
1017 # if defined (HAVE_TERMIOS) && defined (LDISC1) 1230 #if defined (HAVE_TERMIOS) && defined (LDISC1)
1018 { 1231 {
1019 struct termios t; 1232 struct termios t;
1020 assert (isatty (xforkin)); 1233 assert (isatty (xforkin));
1021 tcgetattr (xforkin, &t); 1234 tcgetattr (xforkin, &t);
1022 t.c_lflag = LDISC1; 1235 t.c_lflag = LDISC1;
1023 if (tcsetattr (xforkin, TCSANOW, &t) < 0) 1236 if (tcsetattr (xforkin, TCSANOW, &t) < 0)
1024 perror ("create_process/tcsetattr LDISC1 failed\n"); 1237 perror ("create_process/tcsetattr LDISC1 failed\n");
1025 } 1238 }
1026 # elif defined (NTTYDISC) && defined (TIOCSETD) 1239 #elif defined (NTTYDISC) && defined (TIOCSETD)
1027 { 1240 {
1028 /* Use new line discipline. TIOCSETD is accepted and 1241 /* Use new line discipline. TIOCSETD is accepted and
1029 ignored on Sys5.4 systems with ttcompat. */ 1242 ignored on Sys5.4 systems with ttcompat. */
1030 int ldisc = NTTYDISC; 1243 int ldisc = NTTYDISC;
1031 assert (isatty (xforkin)); 1244 assert (isatty (xforkin));
1032 ioctl (xforkin, TIOCSETD, &ldisc); 1245 ioctl (xforkin, TIOCSETD, &ldisc);
1033 } 1246 }
1034 # endif /* TIOCSETD & NTTYDISC */ 1247 #endif /* TIOCSETD & NTTYDISC */
1035 1248
1036 /* Make our process group be the foreground group 1249 /* Make our process group be the foreground group
1037 of our new controlling terminal. */ 1250 of our new controlling terminal. */
1038 1251
1039 { 1252 {
1069 CHECK_STRING (argv[i]); 1282 CHECK_STRING (argv[i]);
1070 new_argv[i + 1] = XSTRING_DATA (argv[i]); 1283 new_argv[i + 1] = XSTRING_DATA (argv[i]);
1071 } 1284 }
1072 new_argv[i + 1] = 0; 1285 new_argv[i + 1] = 0;
1073 1286
1074 child_setup (xforkin, xforkout, xforkout, new_argv, cur_dir); 1287 child_setup (xforkin, xforkout, separate_err ? xforkerr : xforkout,
1288 new_argv, cur_dir);
1075 } 1289 }
1076 1290
1077 } /**** End of child code ****/ 1291 } /**** End of child code ****/
1078 1292
1079 /**** Back in parent process ****/ 1293 /**** Back in parent process ****/
1080 } 1294 }
1081 1295
1082 if (pid < 0) 1296 if (pid < 0)
1083 { 1297 {
1298 /* Note: The caller set up an unwind-protect to automatically delete
1299 the process if we fail. This will correctly deselect and close
1300 inchannel, outchannel, and errchannel. */
1084 int save_errno = errno; 1301 int save_errno = errno;
1085 close_descriptor_pair (forkin, forkout); 1302 close_descriptor_pair (forkin, forkout);
1303 if (separate_err)
1304 retry_close (forkerr);
1086 errno = save_errno; 1305 errno = save_errno;
1087 report_process_error ("Doing fork", Qunbound); 1306 report_process_error ("Doing fork", Qunbound);
1088 } 1307 }
1089 1308
1090 /* #### dmoore - why is this commented out, otherwise we leave 1309 /* #### dmoore - why is this commented out, otherwise we leave
1091 subtty = forkin, but then we close forkin just below. */ 1310 subtty = forkin, but then we close forkin just below. */
1092 /* UNIX_DATA(p)->subtty = -1; */ 1311 /* UNIX_DATA (p)->subtty = -1; */
1093 1312
1094 /* If the subfork execv fails, and it exits, 1313 /* If the subfork execv fails, and it exits,
1095 this close hangs. I don't know why. 1314 this close hangs. I don't know why.
1096 So have an interrupt jar it loose. */ 1315 So have an interrupt jar it loose. */
1097 if (forkin >= 0) 1316 if (forkin >= 0)
1098 close_safely (forkin); 1317 close_safely (forkin);
1099 if (forkin != forkout && forkout >= 0) 1318 if (forkin != forkout && forkout >= 0)
1100 retry_close (forkout); 1319 retry_close (forkout);
1320 if (separate_err)
1321 retry_close (forkerr);
1101 1322
1102 UNIX_DATA (p)->tty_name = pty_flag ? build_intstring (pty_name) : Qnil; 1323 UNIX_DATA (p)->tty_name = pty_flag ? build_intstring (pty_name) : Qnil;
1103 1324
1104 /* Notice that SIGCHLD was not blocked. (This is not possible on 1325 /* Notice that SIGCHLD was not blocked. (This is not possible on
1105 some systems.) No biggie if SIGCHLD occurs right around the 1326 some systems.) No biggie if SIGCHLD occurs right around the
1106 time that this call happens, because SIGCHLD() does not actually 1327 time that this call happens, because SIGCHLD() does not actually
1107 deselect the process (that doesn't occur until the next time 1328 deselect the process (that doesn't occur until the next time
1108 we're waiting for an event, when status_notify() is called). */ 1329 we're waiting for an event, when status_notify() is called). */
1109 return pid; 1330 return pid;
1110 1331
1111 io_failure: 1332 io_failure:
1112 { 1333 {
1113 int save_errno = errno; 1334 int save_errno = errno;
1114 close_descriptor_pair (forkin, forkout); 1335 close_descriptor_pair (forkin, forkout);
1115 close_descriptor_pair (inchannel, outchannel); 1336 close_descriptor_pair (inchannel, outchannel);
1337 close_descriptor_pair (forkerr, errchannel);
1116 errno = save_errno; 1338 errno = save_errno;
1117 report_process_error ("Opening pty or pipe", Qunbound); 1339 report_process_error ("Opening pty or pipe", Qunbound);
1118 RETURN_NOT_REACHED (0) 1340 RETURN_NOT_REACHED (0)
1119 } 1341 }
1120 } 1342 }
1122 /* Return nonzero if this process is a ToolTalk connection. */ 1344 /* Return nonzero if this process is a ToolTalk connection. */
1123 1345
1124 static int 1346 static int
1125 unix_tooltalk_connection_p (Lisp_Process *p) 1347 unix_tooltalk_connection_p (Lisp_Process *p)
1126 { 1348 {
1127 return UNIX_DATA(p)->connected_via_filedesc_p; 1349 return UNIX_DATA (p)->connected_via_filedesc_p;
1128 } 1350 }
1129 1351
1130 /* This is called to set process' virtual terminal size */ 1352 /* This is called to set process' virtual terminal size */
1131 1353
1132 static int 1354 static int
1133 unix_set_window_size (Lisp_Process* p, int cols, int rows) 1355 unix_set_window_size (Lisp_Process *p, int cols, int rows)
1134 { 1356 {
1135 return set_window_size (UNIX_DATA(p)->infd, cols, rows); 1357 return set_window_size (UNIX_DATA (p)->infd, cols, rows);
1136 } 1358 }
1137 1359
1138 /* 1360 /*
1139 * This method is called to update status fields of the process 1361 * This method is called to update status fields of the process
1140 * structure. If the process has not existed, this method is 1362 * structure. If the process has not existed, this method is
1143 * The method is called only for real child processes. 1365 * The method is called only for real child processes.
1144 */ 1366 */
1145 1367
1146 #ifdef HAVE_WAITPID 1368 #ifdef HAVE_WAITPID
1147 static void 1369 static void
1148 unix_update_status_if_terminated (Lisp_Process* p) 1370 unix_update_status_if_terminated (Lisp_Process *p)
1149 { 1371 {
1150 int w; 1372 int w;
1151 #ifdef SIGCHLD 1373 #ifdef SIGCHLD
1152 EMACS_BLOCK_SIGNAL (SIGCHLD); 1374 EMACS_BLOCK_SIGNAL (SIGCHLD);
1153 #endif 1375 #endif
1180 if (exited_processes_index <= 0) 1402 if (exited_processes_index <= 0)
1181 { 1403 {
1182 return; 1404 return;
1183 } 1405 }
1184 1406
1185 #ifdef EMACS_BLOCK_SIGNAL 1407 #ifdef EMACS_BLOCK_SIGNAL
1186 EMACS_BLOCK_SIGNAL (SIGCHLD); 1408 EMACS_BLOCK_SIGNAL (SIGCHLD);
1187 #endif 1409 #endif
1188 for (i = 0; i < exited_processes_index; i++) 1410 for (i = 0; i < exited_processes_index; i++)
1189 { 1411 {
1190 int pid = exited_processes[i]; 1412 int pid = exited_processes[i];
1213 update_status_from_wait_code (p, &w); 1435 update_status_from_wait_code (p, &w);
1214 1436
1215 /* If process has terminated, stop waiting for its output. */ 1437 /* If process has terminated, stop waiting for its output. */
1216 if (WIFSIGNALED (w) || WIFEXITED (w)) 1438 if (WIFSIGNALED (w) || WIFEXITED (w))
1217 { 1439 {
1218 if (!NILP(p->pipe_instream)) 1440 if (!NILP (p->pipe_instream))
1219 { 1441 {
1220 /* We can't just call event_stream->unselect_process_cb (p) 1442 /* We can't just call event_stream->unselect_process_cb (p)
1221 here, because that calls XtRemoveInput, which is not 1443 here, because that calls XtRemoveInput, which is not
1222 necessarily reentrant, so we can't call this at interrupt 1444 necessarily reentrant, so we can't call this at interrupt
1223 level. 1445 level.
1224 */ 1446 */
1225 } 1447 }
1226 } 1448 }
1227 } 1449 }
1450 #ifdef NEED_SYNC_PROCESS_CODE
1228 else 1451 else
1229 { 1452 {
1230 /* There was no asynchronous process found for that id. Check 1453 /* There was no asynchronous process found for that id. Check
1231 if we have a synchronous process. Only set sync process status 1454 if we have a synchronous process. Only set sync process status
1232 if there is one, so we work OK with the waitpid() call in 1455 if there is one, so we work OK with the waitpid() call in
1240 synch_process_retcode = WEXITSTATUS (w); 1463 synch_process_retcode = WEXITSTATUS (w);
1241 else if (WIFSIGNALED (w)) 1464 else if (WIFSIGNALED (w))
1242 synch_process_death = signal_name (WTERMSIG (w)); 1465 synch_process_death = signal_name (WTERMSIG (w));
1243 } 1466 }
1244 } 1467 }
1468 #endif /* NEED_SYNC_PROCESS_CODE */
1245 } 1469 }
1246 1470
1247 exited_processes_index = 0; 1471 exited_processes_index = 0;
1248 1472
1249 EMACS_UNBLOCK_SIGNAL (SIGCHLD); 1473 EMACS_UNBLOCK_SIGNAL (SIGCHLD);
1263 EMACS_UNBLOCK_SIGNAL (signum); 1487 EMACS_UNBLOCK_SIGNAL (signum);
1264 LONGJMP (send_process_frame, 1); 1488 LONGJMP (send_process_frame, 1);
1265 } 1489 }
1266 1490
1267 static void 1491 static void
1268 unix_send_process (Lisp_Object proc, struct lstream* lstream) 1492 unix_send_process (Lisp_Object proc, struct lstream *lstream)
1269 { 1493 {
1270 /* Use volatile to protect variables from being clobbered by longjmp. */ 1494 /* Use volatile to protect variables from being clobbered by longjmp. */
1271 SIGTYPE (*volatile old_sigpipe) (int) = 0; 1495 SIGTYPE (*volatile old_sigpipe) (int) = 0;
1272 volatile Lisp_Object vol_proc = proc; 1496 volatile Lisp_Object vol_proc = proc;
1273 Lisp_Process *volatile p = XPROCESS (proc); 1497 Lisp_Process *volatile p = XPROCESS (proc);
1379 * Called before the process is deactivated. The process object 1603 * Called before the process is deactivated. The process object
1380 * is not immediately finalized, just undergoes a transition to 1604 * is not immediately finalized, just undergoes a transition to
1381 * inactive state. 1605 * inactive state.
1382 * 1606 *
1383 * The return value is a unique stream ID, as returned by 1607 * The return value is a unique stream ID, as returned by
1384 * event_stream_delete_stream_pair 1608 * event_stream_delete_io_streams
1385 * 1609 *
1386 * In the lack of this method, only event_stream_delete_stream_pair 1610 * In the lack of this method, only event_stream_delete_io_streams
1387 * is called on both I/O streams of the process. 1611 * is called on both I/O streams of the process.
1388 * 1612 *
1389 * The UNIX version guards this by ignoring possible SIGPIPE. 1613 * The UNIX version guards this by ignoring possible SIGPIPE.
1390 */ 1614 */
1391 1615
1392 static USID 1616 static void
1393 unix_deactivate_process (Lisp_Process *p) 1617 unix_deactivate_process (Lisp_Process *p,
1618 USID *in_usid,
1619 USID *err_usid)
1394 { 1620 {
1395 SIGTYPE (*old_sigpipe) (int) = 0; 1621 SIGTYPE (*old_sigpipe) (int) = 0;
1396 USID usid;
1397 1622
1398 if (UNIX_DATA(p)->infd >= 0) 1623 if (UNIX_DATA(p)->infd >= 0)
1399 flush_pending_output (UNIX_DATA(p)->infd); 1624 flush_pending_output (UNIX_DATA(p)->infd);
1625 if (UNIX_DATA(p)->errfd >= 0)
1626 flush_pending_output (UNIX_DATA(p)->errfd);
1400 1627
1401 /* closing the outstream could result in SIGPIPE, so ignore it. */ 1628 /* closing the outstream could result in SIGPIPE, so ignore it. */
1402 old_sigpipe = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGPIPE, SIG_IGN); 1629 old_sigpipe = (SIGTYPE (*) (int)) EMACS_SIGNAL (SIGPIPE, SIG_IGN);
1403 usid = event_stream_delete_stream_pair (p->pipe_instream, p->pipe_outstream); 1630 event_stream_delete_io_streams (p->pipe_instream, p->pipe_outstream,
1631 p->pipe_errstream, in_usid, err_usid);
1404 EMACS_SIGNAL (SIGPIPE, old_sigpipe); 1632 EMACS_SIGNAL (SIGPIPE, old_sigpipe);
1405 1633
1406 UNIX_DATA(p)->infd = -1; 1634 UNIX_DATA(p)->infd = -1;
1407 1635 UNIX_DATA(p)->errfd = -1;
1408 return usid;
1409 } 1636 }
1410 1637
1411 /* If the subtty field of the process data is not filled in, do so now. */ 1638 /* If the subtty field of the process data is not filled in, do so now. */
1412 static void 1639 static void
1413 try_to_initialize_subtty (struct unix_process_data *upd) 1640 try_to_initialize_subtty (struct unix_process_data *upd)
1454 #endif /* ! defined (SIGCONT) */ 1681 #endif /* ! defined (SIGCONT) */
1455 case SIGINT: 1682 case SIGINT:
1456 case SIGQUIT: 1683 case SIGQUIT:
1457 case SIGKILL: 1684 case SIGKILL:
1458 flush_pending_output (d->infd); 1685 flush_pending_output (d->infd);
1686 flush_pending_output (d->errfd);
1459 break; 1687 break;
1460 } 1688 }
1461 1689
1462 if (! d->pty_flag) 1690 if (! d->pty_flag)
1463 current_group = 0; 1691 current_group = 0;
1502 1730
1503 #ifdef SIGNALS_VIA_CHARACTERS 1731 #ifdef SIGNALS_VIA_CHARACTERS
1504 /* If possible, send signals to the entire pgrp 1732 /* If possible, send signals to the entire pgrp
1505 by sending an input character to it. */ 1733 by sending an input character to it. */
1506 { 1734 {
1507 char sigchar = process_signal_char (d->subtty, signo); 1735 Intbyte sigchar = process_signal_char (d->subtty, signo);
1508 if (sigchar) 1736 if (sigchar)
1509 { 1737 {
1510 send_process (proc, Qnil, (Intbyte *) &sigchar, 0, 1); 1738 send_process (proc, Qnil, &sigchar, 0, 1);
1511 return; 1739 return;
1512 } 1740 }
1513 } 1741 }
1514 #endif /* SIGNALS_VIA_CHARACTERS */ 1742 #endif /* SIGNALS_VIA_CHARACTERS */
1515 1743
1783 if (QUITP) 2011 if (QUITP)
1784 { 2012 {
1785 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS 2013 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS
1786 speed_up_interrupts (); 2014 speed_up_interrupts ();
1787 #endif 2015 #endif
1788 REALLY_QUIT; 2016 QUIT;
1789 /* In case something really weird happens ... */ 2017 /* In case something really weird happens ... */
1790 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS 2018 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS
1791 slow_down_interrupts (); 2019 slow_down_interrupts ();
1792 #endif 2020 #endif
1793 } 2021 }
1918 important issue. 2146 important issue.
1919 */ 2147 */
1920 2148
1921 static void 2149 static void
1922 unix_open_multicast_group (Lisp_Object name, Lisp_Object dest, 2150 unix_open_multicast_group (Lisp_Object name, Lisp_Object dest,
1923 Lisp_Object port, Lisp_Object ttl, void** vinfd, 2151 Lisp_Object port, Lisp_Object ttl, void **vinfd,
1924 void** voutfd) 2152 void **voutfd)
1925 { 2153 {
1926 struct ip_mreq imr; 2154 struct ip_mreq imr;
1927 struct sockaddr_in sa; 2155 struct sockaddr_in sa;
1928 struct protoent *udp; 2156 struct protoent *udp;
1929 int ws, rs; 2157 int ws, rs;
2015 if (QUITP) 2243 if (QUITP)
2016 { 2244 {
2017 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS 2245 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS
2018 speed_up_interrupts (); 2246 speed_up_interrupts ();
2019 #endif 2247 #endif
2020 REALLY_QUIT; 2248 QUIT;
2021 /* In case something really weird happens ... */ 2249 /* In case something really weird happens ... */
2022 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS 2250 #ifdef CONNECT_NEEDS_SLOWED_INTERRUPTS
2023 slow_down_interrupts (); 2251 slow_down_interrupts ();
2024 #endif 2252 #endif
2025 } 2253 }