X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/68c45bf06516ed4650eb7f9f617742d84750600a..cd2904bd2c06864bc02f3e454caccdeb3f0e03f2:/src/process.c diff --git a/src/process.c b/src/process.c index 144e69af7c..cb51af92af 100644 --- a/src/process.c +++ b/src/process.c @@ -20,8 +20,8 @@ the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#define _GNU_SOURCE /* to get strsignal declared with glibc 2 */ #include - #include /* This file is split into two parts by the following preprocessor @@ -44,7 +44,7 @@ Boston, MA 02111-1307, USA. */ #include #endif -#ifdef WINDOWSNT +#if defined(WINDOWSNT) || defined(UNIX98_PTYS) #include #include #endif /* not WINDOWSNT */ @@ -59,7 +59,7 @@ Boston, MA 02111-1307, USA. */ #endif /* NEED_NET_ERRNO_H */ #endif /* HAVE_SOCKETS */ -/* TERM is a poor-man's SLIP, used on Linux. */ +/* TERM is a poor-man's SLIP, used on GNU/Linux. */ #ifdef TERM #include #endif @@ -104,10 +104,12 @@ Boston, MA 02111-1307, USA. */ #include "termhooks.h" #include "termopts.h" #include "commands.h" +#include "keyboard.h" #include "frame.h" #include "blockinput.h" -#include "keyboard.h" #include "dispextern.h" +#include "composite.h" +#include "atimer.h" #define max(a, b) ((a) > (b) ? (a) : (b)) @@ -145,8 +147,9 @@ Lisp_Object Qlast_nonmenu_event; extern void set_waiting_for_input P_ ((EMACS_TIME *)); +#ifndef USE_CRT_DLL extern int errno; -extern char *strerror (); +#endif #ifdef VMS extern char *sys_errlist[]; #endif @@ -155,50 +158,6 @@ extern char *sys_errlist[]; extern int h_errno; #endif -#ifndef HAVE_STRSIGNAL -#ifndef SYS_SIGLIST_DECLARED -#ifndef VMS -#ifndef BSD4_1 -#ifndef WINDOWSNT -#ifndef LINUX -extern char *sys_siglist[]; -#endif /* not LINUX */ -#else /* BSD4_1 */ -char *sys_siglist[] = - { - "bum signal!!", - "hangup", - "interrupt", - "quit", - "illegal instruction", - "trace trap", - "iot instruction", - "emt instruction", - "floating point exception", - "kill", - "bus error", - "segmentation violation", - "bad argument to system call", - "write on a pipe with no one to read it", - "alarm clock", - "software termination signal from kill", - "status signal", - "sendable stop signal not from tty", - "stop signal from tty", - "continue a stopped process", - "child status has changed", - "background read attempted from control tty", - "background write attempted from control tty", - "input record available at control tty", - "exceeded CPU time limit", - "exceeded file size limit" - }; -#endif /* not WINDOWSNT */ -#endif -#endif /* VMS */ -#endif /* ! SYS_SIGLIST_DECLARED */ -#endif /* ! HAVE_STRSIGNAL */ - /* t means use pty, nil means use a pipe, maybe other values to come. */ static Lisp_Object Vprocess_connection_type; @@ -360,7 +319,7 @@ status_message (status) if (EQ (symbol, Qsignal) || EQ (symbol, Qstop)) { char *signame; - synchronize_messages_locale (); + synchronize_system_messages_locale (); signame = strsignal (code); if (signame == 0) signame = "unknown"; @@ -1066,7 +1025,6 @@ static Lisp_Object start_process_unwind (); DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0, "Start a program in a subprocess. Return the process object for it.\n\ -Args are NAME BUFFER PROGRAM &rest PROGRAM-ARGS\n\ NAME is name for process. It is modified if necessary to make it unique.\n\ BUFFER is the buffer or (buffer-name) to associate with the process.\n\ Process output goes at end of that buffer, unless you specify\n\ @@ -1126,63 +1084,6 @@ Remaining arguments are strings to give program as arguments.") CHECK_STRING (program, 2); -#ifdef VMS - /* Make a one member argv with all args concatenated - together separated by a blank. */ - len = STRING_BYTES (XSTRING (program)) + 2; - for (i = 3; i < nargs; i++) - { - tem = args[i]; - CHECK_STRING (tem, i); - len += STRING_BYTES (XSTRING (tem)) + 1; /* count the blank */ - } - new_argv = (unsigned char *) alloca (len); - strcpy (new_argv, XSTRING (program)->data); - for (i = 3; i < nargs; i++) - { - tem = args[i]; - CHECK_STRING (tem, i); - strcat (new_argv, " "); - strcat (new_argv, XSTRING (tem)->data); - } - /* Need to add code here to check for program existence on VMS */ - -#else /* not VMS */ - new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *)); - - /* If program file name is not absolute, search our path for it */ - if (!IS_DIRECTORY_SEP (XSTRING (program)->data[0]) - && !(XSTRING (program)->size > 1 - && IS_DEVICE_SEP (XSTRING (program)->data[1]))) - { - struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; - - tem = Qnil; - GCPRO4 (name, program, buffer, current_dir); - openp (Vexec_path, program, EXEC_SUFFIXES, &tem, 1); - UNGCPRO; - if (NILP (tem)) - report_file_error ("Searching for program", Fcons (program, Qnil)); - tem = Fexpand_file_name (tem, Qnil); - new_argv[0] = XSTRING (tem)->data; - } - else - { - if (!NILP (Ffile_directory_p (program))) - error ("Specified program for new process is a directory"); - - new_argv[0] = XSTRING (program)->data; - } - - for (i = 3; i < nargs; i++) - { - tem = args[i]; - CHECK_STRING (tem, i); - new_argv[i - 2] = XSTRING (tem)->data; - } - new_argv[i - 2] = 0; -#endif /* not VMS */ - proc = make_process (name); /* If an error occurs and we can't start the process, we want to remove it from the process list. This means that each error @@ -1211,7 +1112,7 @@ Remaining arguments are strings to give program as arguments.") /* Qt denotes we have not yet called Ffind_operation_coding_system. */ Lisp_Object coding_systems = Qt; Lisp_Object val, *args2; - struct gcpro gcpro1; + struct gcpro gcpro1, gcpro2; val = Vcoding_system_for_read; if (NILP (val)) @@ -1219,7 +1120,7 @@ Remaining arguments are strings to give program as arguments.") args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2); args2[0] = Qstart_process; for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; - GCPRO1 (proc); + GCPRO2 (proc, current_dir); coding_systems = Ffind_operation_coding_system (nargs + 1, args2); UNGCPRO; if (CONSP (coding_systems)) @@ -1237,7 +1138,7 @@ Remaining arguments are strings to give program as arguments.") args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof args2); args2[0] = Qstart_process; for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; - GCPRO1 (proc); + GCPRO2 (proc, current_dir); coding_systems = Ffind_operation_coding_system (nargs + 1, args2); UNGCPRO; } @@ -1249,6 +1150,73 @@ Remaining arguments are strings to give program as arguments.") XPROCESS (proc)->encode_coding_system = val; } +#ifdef VMS + /* Make a one member argv with all args concatenated + together separated by a blank. */ + len = STRING_BYTES (XSTRING (program)) + 2; + for (i = 3; i < nargs; i++) + { + tem = args[i]; + CHECK_STRING (tem, i); + len += STRING_BYTES (XSTRING (tem)) + 1; /* count the blank */ + } + new_argv = (unsigned char *) alloca (len); + strcpy (new_argv, XSTRING (program)->data); + for (i = 3; i < nargs; i++) + { + tem = args[i]; + CHECK_STRING (tem, i); + strcat (new_argv, " "); + strcat (new_argv, XSTRING (tem)->data); + } + /* Need to add code here to check for program existence on VMS */ + +#else /* not VMS */ + new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *)); + + /* If program file name is not absolute, search our path for it */ + if (!IS_DIRECTORY_SEP (XSTRING (program)->data[0]) + && !(XSTRING (program)->size > 1 + && IS_DEVICE_SEP (XSTRING (program)->data[1]))) + { + struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; + + tem = Qnil; + GCPRO4 (name, program, buffer, current_dir); + openp (Vexec_path, program, EXEC_SUFFIXES, &tem, 1); + UNGCPRO; + if (NILP (tem)) + report_file_error ("Searching for program", Fcons (program, Qnil)); + tem = Fexpand_file_name (tem, Qnil); + tem = ENCODE_FILE (tem); + new_argv[0] = XSTRING (tem)->data; + } + else + { + if (!NILP (Ffile_directory_p (program))) + error ("Specified program for new process is a directory"); + + tem = ENCODE_FILE (program); + new_argv[0] = XSTRING (tem)->data; + } + + /* Here we encode arguments by the coding system used for sending + data to the process. We don't support using different coding + systems for encoding arguments and for encoding data sent to the + process. */ + + for (i = 3; i < nargs; i++) + { + tem = args[i]; + CHECK_STRING (tem, i); + if (STRING_MULTIBYTE (tem)) + tem = (code_convert_string_norecord + (tem, XPROCESS (proc)->encode_coding_system, 1)); + new_argv[i - 2] = XSTRING (tem)->data; + } + new_argv[i - 2] = 0; +#endif /* not VMS */ + XPROCESS (proc)->decoding_buf = make_uninit_string (0); XPROCESS (proc)->decoding_carryover = make_number (0); XPROCESS (proc)->encoding_buf = make_uninit_string (0); @@ -1281,18 +1249,14 @@ start_process_unwind (proc) return Qnil; } - -SIGTYPE -create_process_1 (signo) - int signo; +void +create_process_1 (timer) + struct atimer *timer; { -#if defined (USG) && !defined (POSIX_SIGNALS) - /* USG systems forget handlers when they are used; - must reestablish each time */ - signal (signo, create_process_1); -#endif /* USG */ + /* Nothing to do. */ } + #if 0 /* This doesn't work; see the note before sigchld_handler. */ #ifdef USG #ifdef SIGCHLD @@ -1339,7 +1303,9 @@ create_process (process, new_argv, current_dir) /* Use volatile to protect variables from being clobbered by longjmp. */ volatile int forkin, forkout; volatile int pty_flag = 0; +#ifndef USE_CRT_DLL extern char **environ; +#endif Lisp_Object buffer = XPROCESS (process)->buffer; inchannel = outchannel = -1; @@ -1444,46 +1410,6 @@ create_process (process, new_argv, current_dir) setup_coding_system (XPROCESS (process)->encode_coding_system, proc_encode_coding_system[outchannel]); - if ((!NILP (buffer) && NILP (XBUFFER (buffer)->enable_multibyte_characters)) - || (NILP (buffer) && NILP (buffer_defaults.enable_multibyte_characters))) - { - /* In unibyte mode, character code conversion should not take - place but EOL conversion should. So, setup raw-text or one - of the subsidiary according to the information just setup. */ - if (!NILP (XPROCESS (process)->decode_coding_system)) - setup_raw_text_coding_system (proc_decode_coding_system[inchannel]); - if (!NILP (XPROCESS (process)->encode_coding_system)) - setup_raw_text_coding_system (proc_encode_coding_system[outchannel]); - } - - if (CODING_REQUIRE_ENCODING (proc_encode_coding_system[outchannel])) - { - /* Here we encode arguments by the coding system used for - sending data to the process. We don't support using - different coding systems for encoding arguments and for - encoding data sent to the process. */ - struct gcpro gcpro1; - int i = 1; - struct coding_system *coding = proc_encode_coding_system[outchannel]; - - coding->mode |= CODING_MODE_LAST_BLOCK; - GCPRO1 (process); - while (new_argv[i] != 0) - { - int len = strlen (new_argv[i]); - int size = encoding_buffer_size (coding, len); - unsigned char *buf = (unsigned char *) alloca (size); - - encode_coding (coding, (unsigned char *)new_argv[i], buf, len, size); - buf[coding->produced] = 0; - /* We don't have to free new_argv[i] because it points to a - Lisp string given as an argument to `start-process'. */ - new_argv[i++] = (char *) buf; - } - UNGCPRO; - coding->mode &= ~CODING_MODE_LAST_BLOCK; - } - /* Delay interrupts until we have a chance to store the new fork's pid in its process structure */ #ifdef POSIX_SIGNALS @@ -1729,14 +1655,22 @@ create_process (process, new_argv, current_dir) /* If the subfork execv fails, and it exits, this close hangs. I don't know why. So have an interrupt jar it loose. */ - stop_polling (); - signal (SIGALRM, create_process_1); - alarm (1); - XPROCESS (process)->subtty = Qnil; - if (forkin >= 0) - emacs_close (forkin); - alarm (0); - start_polling (); + { + struct atimer *timer; + EMACS_TIME offset; + + stop_polling (); + EMACS_SET_SECS_USECS (offset, 1, 0); + timer = start_atimer (ATIMER_RELATIVE, offset, create_process_1, 0); + + XPROCESS (process)->subtty = Qnil; + if (forkin >= 0) + emacs_close (forkin); + + cancel_atimer (timer); + start_polling (); + } + if (forkin != forkout && forkout >= 0) emacs_close (forkout); @@ -1814,18 +1748,18 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ Lisp_Object name, buffer, host, service; { Lisp_Object proc; -#ifndef HAVE_GETADDRINFO +#ifdef HAVE_GETADDRINFO + struct addrinfo hints, *res, *lres; + int ret = 0; + int xerrno = 0; + char *portstring, portbuf[128]; +#else /* HAVE_GETADDRINFO */ struct sockaddr_in address; struct servent *svc_info; struct hostent *host_info_ptr, host_info; char *(addr_list[2]); IN_ADDR numeric_addr; int port; -#else /* HAVE_GETADDRINFO */ - struct addrinfo hints, *res, *lres; - int ret = 0; - int xerrno = 0; - char *portstring, portbuf[128]; #endif /* HAVE_GETADDRINFO */ int s = -1, outch, inch; struct gcpro gcpro1, gcpro2, gcpro3, gcpro4; @@ -1843,13 +1777,11 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ CHECK_STRING (host, 0); #ifdef HAVE_GETADDRINFO - /* - * SERVICE can either be a string or int. - * Convert to a C string for later use by getaddrinfo. - */ + /* SERVICE can either be a string or int. + Convert to a C string for later use by getaddrinfo. */ if (INTEGERP (service)) { - sprintf (portbuf, "%d", XINT (service)); + sprintf (portbuf, "%ld", (long) XINT (service)); portstring = portbuf; } else @@ -1857,7 +1789,7 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ CHECK_STRING (service, 0); portstring = XSTRING (service)->data; } -#else /* ! HAVE_GETADDRINFO */ +#else /* HAVE_GETADDRINFO */ if (INTEGERP (service)) port = htons ((unsigned short) XINT (service)); else @@ -1868,44 +1800,48 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ error ("Unknown service \"%s\"", XSTRING (service)->data); port = svc_info->s_port; } -#endif /* ! HAVE_GETADDRINFO */ +#endif /* HAVE_GETADDRINFO */ /* Slow down polling to every ten seconds. Some kernels have a bug which causes retrying connect to fail after a connect. Polling can interfere with gethostbyname too. */ #ifdef POLL_FOR_INPUT + record_unwind_protect (unwind_stop_other_atimers, Qnil); bind_polling_period (10); #endif #ifndef TERM #ifdef HAVE_GETADDRINFO - { - immediate_quit = 1; - QUIT; - memset (&hints, 0, sizeof (hints)); - hints.ai_flags = 0; - hints.ai_family = AF_UNSPEC; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = 0; - ret = getaddrinfo (XSTRING (host)->data, portstring, &hints, &res); - if (ret) - { - error ("%s/%s %s", XSTRING (host)->data, portstring, - strerror (ret)); - } - immediate_quit = 0; - } + immediate_quit = 1; + QUIT; + memset (&hints, 0, sizeof (hints)); + hints.ai_flags = 0; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = 0; + ret = getaddrinfo (XSTRING (host)->data, portstring, &hints, &res); + if (ret) +#ifdef HAVE_GAI_STRERROR + error ("%s/%s %s", XSTRING (host)->data, portstring, gai_strerror(ret)); +#else + error ("%s/%s getaddrinfo error %d", XSTRING (host)->data, portstring, + ret); +#endif + immediate_quit = 0; - s = -1; + /* Do this in case we never enter the for-loop below. */ count1 = specpdl_ptr - specpdl; - record_unwind_protect (close_file_unwind, make_number (s)); + s = -1; for (lres = res; lres; lres = lres->ai_next) { s = socket (lres->ai_family, lres->ai_socktype, lres->ai_protocol); - if (s < 0) - continue; + if (s < 0) + { + xerrno = errno; + continue; + } /* Kernel bugs (on Ultrix at least) cause lossage (not just EINTR) when connect is interrupted. So let's not let it get interrupted. @@ -1916,12 +1852,50 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ if (interrupt_input) unrequest_sigio (); + /* Make us close S if quit. */ + count1 = specpdl_ptr - specpdl; + record_unwind_protect (close_file_unwind, make_number (s)); + + loop: + immediate_quit = 1; QUIT; + /* This turns off all alarm-based interrupts; the + bind_polling_period call above doesn't always turn all the + short-interval ones off, especially if interrupt_input is + set. + + It'd be nice to be able to control the connect timeout + though. Would non-blocking connect calls be portable? */ + turn_on_atimers (0); ret = connect (s, lres->ai_addr, lres->ai_addrlen); - if (ret == 0) + xerrno = errno; + turn_on_atimers (1); + + if (ret == 0 || xerrno == EISCONN) + /* The unwind-protect will be discarded afterwards. + Likewise for immediate_quit. */ break; + + immediate_quit = 0; + + if (xerrno == EINTR) + goto loop; + if (xerrno == EADDRINUSE && retry < 20) + { + /* A delay here is needed on some FreeBSD systems, + and it is harmless, since this retrying takes time anyway + and should be infrequent. */ + Fsleep_for (make_number (1), Qnil); + retry++; + goto loop; + } + + /* Discard the unwind protect closing S. */ + specpdl_ptr = specpdl + count1; + count1 = specpdl_ptr - specpdl; + emacs_close (s); s = -1; } @@ -1936,7 +1910,8 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ report_file_error ("connection failed", Fcons (host, Fcons (name, Qnil))); } -#else /* ! HAVE_GETADDRINFO */ + +#else /* not HAVE_GETADDRINFO */ while (1) { @@ -1957,6 +1932,7 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ break; Fsleep_for (make_number (1), Qnil); } + if (host_info_ptr == 0) /* Attempt to interpret host as numeric inet address */ { @@ -2038,11 +2014,12 @@ Fourth arg SERVICE is name of the service desired, or an integer\n\ report_file_error ("connection failed", Fcons (host, Fcons (name, Qnil))); } -#endif /* ! HAVE_GETADDRINFO */ + +#endif /* not HAVE_GETADDRINFO */ immediate_quit = 0; - /* Discard the unwind protect. */ + /* Discard the unwind protect, if any. */ specpdl_ptr = specpdl + count1; #ifdef POLL_FOR_INPUT @@ -2413,18 +2390,13 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) Causes "poll: interrupted system call" messages when Emacs is run in an X window Turn off periodic alarms (in case they are in use) */ - stop_polling (); + turn_on_atimers (0); #endif while (1) { int timeout_reduced_for_timers = 0; -#ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - Fx_hide_busy_cursor (Qnil); -#endif - /* If calling from keyboard input, do not quit since we want to return C-g as an input character. Otherwise, do pending quit if requested. */ @@ -2848,12 +2820,6 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) start_polling (); #endif -#ifdef HAVE_X_WINDOWS - if (display_busy_cursor_p) - if (!inhibit_busy_cursor) - Fx_show_busy_cursor (); -#endif - return got_some_input; } @@ -2874,6 +2840,7 @@ read_process_output_error_handler (error) Vinhibit_quit = Qt; update_echo_area (); Fsleep_for (make_number (2), Qnil); + return Qt; } /* Read pending output from the process channel, @@ -2894,18 +2861,11 @@ read_process_output (proc, channel) { register int nchars, nbytes; char *chars; -#ifdef VMS - int chars_allocated = 0; /* If 1, `chars' should be freed later. */ -#else - char buf[1024]; -#endif register Lisp_Object outstream; register struct buffer *old = current_buffer; register struct Lisp_Process *p = XPROCESS (proc); register int opoint; struct coding_system *coding = proc_decode_coding_system[channel]; - int chars_in_decoding_buf = 0; /* If 1, `chars' points - XSTRING (p->decoding_buf)->data. */ int carryover = XINT (p->decoding_carryover); #ifdef VMS @@ -2933,42 +2893,33 @@ read_process_output (proc, channel) /* The data carried over in the previous decoding (which are at the tail of decoding buffer) should be prepended to the new data read to decode all together. */ - char *buf = (char *) xmalloc (nbytes + carryover); - - bcopy (XSTRING (p->decoding_buf)->data - + STRING_BYTES (XSTRING (p->decoding_buf)) - carryover, - buf, carryover); - bcopy (chars, buf + carryover, nbytes); - chars = buf; - chars_allocated = 1; + chars = (char *) alloca (nbytes + carryover); + bcopy (XSTRING (p->decoding_buf)->data, buf, carryover); + bcopy (vs->inputBuffer, chars + carryover, nbytes); } #else /* not VMS */ - + chars = (char *) alloca (carryover + 1024); if (carryover) /* See the comment above. */ - bcopy (XSTRING (p->decoding_buf)->data - + STRING_BYTES (XSTRING (p->decoding_buf)) - carryover, - buf, carryover); + bcopy (XSTRING (p->decoding_buf)->data, chars, carryover); if (proc_buffered_char[channel] < 0) - nbytes = emacs_read (channel, buf + carryover, (sizeof buf) - carryover); + nbytes = emacs_read (channel, chars + carryover, 1024 - carryover); else { - buf[carryover] = proc_buffered_char[channel]; + chars[carryover] = proc_buffered_char[channel]; proc_buffered_char[channel] = -1; - nbytes = emacs_read (channel, buf + carryover + 1, - (sizeof buf) - carryover - 1); + nbytes = emacs_read (channel, chars + carryover + 1, 1023 - carryover); if (nbytes < 0) nbytes = 1; else nbytes = nbytes + 1; } - chars = buf; #endif /* not VMS */ XSETINT (p->decoding_carryover, 0); - /* At this point, NBYTES holds number of characters just received + /* At this point, NBYTES holds number of bytes just received (including the one in proc_buffered_char[channel]). */ if (nbytes <= 0) { @@ -2979,109 +2930,6 @@ read_process_output (proc, channel) /* Now set NBYTES how many bytes we must decode. */ nbytes += carryover; - nchars = nbytes; - - if (CODING_MAY_REQUIRE_DECODING (coding)) - { - int require = decoding_buffer_size (coding, nbytes); - int result; - - if (STRING_BYTES (XSTRING (p->decoding_buf)) < require) - p->decoding_buf = make_uninit_string (require); - result = decode_coding (coding, chars, XSTRING (p->decoding_buf)->data, - nbytes, STRING_BYTES (XSTRING (p->decoding_buf))); - carryover = nbytes - coding->consumed; - if (carryover > 0) - { - /* Copy the carryover bytes to the end of p->decoding_buf, to - be processed on the next read. Since decoding_buffer_size - asks for an extra amount of space beyond the maximum - expected for the output, there should always be sufficient - space for the carryover (which is by definition a sequence - of bytes that was not long enough to be decoded, and thus - has a bounded length). */ - if (STRING_BYTES (XSTRING (p->decoding_buf)) - < coding->produced + carryover) - abort (); - bcopy (chars + coding->consumed, - XSTRING (p->decoding_buf)->data - + STRING_BYTES (XSTRING (p->decoding_buf)) - carryover, - carryover); - XSETINT (p->decoding_carryover, carryover); - } - - /* A new coding system might be found by `decode_coding'. */ - if (!EQ (p->decode_coding_system, coding->symbol)) - { - p->decode_coding_system = coding->symbol; - - /* Don't call setup_coding_system for - proc_decode_coding_system[channel] here. It is done in - detect_coding called via decode_coding above. */ - - /* If a coding system for encoding is not yet decided, we set - it as the same as coding-system for decoding. - - But, before doing that we must check if - proc_encode_coding_system[p->outfd] surely points to a - valid memory because p->outfd will be changed once EOF is - sent to the process. */ - if (NILP (p->encode_coding_system) - && proc_encode_coding_system[XINT (p->outfd)]) - { - p->encode_coding_system = coding->symbol; - setup_coding_system (coding->symbol, - proc_encode_coding_system[XINT (p->outfd)]); - } - } - -#ifdef VMS - /* Now we don't need the contents of `chars'. */ - if (chars_allocated) - free (chars); -#endif - if (coding->produced == 0) - return 0; - chars = (char *) XSTRING (p->decoding_buf)->data; - nbytes = coding->produced; - nchars = (coding->fake_multibyte - ? multibyte_chars_in_text (chars, nbytes) - : coding->produced_char); - chars_in_decoding_buf = 1; - } - else - { -#ifdef VMS - if (chars_allocated) - { - /* Although we don't have to decode the received data, we - must move it to an area which we don't have to free. */ - if (! STRINGP (p->decoding_buf) - || STRING_BYTES (XSTRING (p->decoding_buf)) < nbytes) - p->decoding_buf = make_uninit_string (nbytes); - bcopy (chars, XSTRING (p->decoding_buf)->data, nbytes); - free (chars); - chars = XSTRING (p->decoding_buf)->data; - chars_in_decoding_buf = 1; - } -#endif - nchars = multibyte_chars_in_text (chars, nbytes); - } - - Vlast_coding_system_used = coding->symbol; - - /* If the caller required, let the process associated buffer - inherit the coding-system used to decode the process output. */ - if (! NILP (p->inherit_coding_system_flag) - && !NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name)) - { - struct buffer *prev_buf = current_buffer; - - Fset_buffer (p->buffer); - call1 (intern ("after-insert-file-set-buffer-file-coding-system"), - make_number (nbytes)); - set_buffer_internal (prev_buf); - } /* Read and dispose of the process output. */ outstream = p->filter; @@ -3123,14 +2971,44 @@ read_process_output (proc, channel) save the match data in a special nonrecursive fashion. */ running_asynch_code = 1; - /* The multibyteness of a string given to the filter is decided - by which coding system we used for decoding. */ - if (coding->type == coding_type_no_conversion - || coding->type == coding_type_raw_text) - text = make_unibyte_string (chars, nbytes); - else - text = make_multibyte_string (chars, nchars, nbytes); + text = decode_coding_string (make_unibyte_string (chars, nbytes), + coding, 0); + if (NILP (buffer_defaults.enable_multibyte_characters)) + /* We had better return unibyte string. */ + text = string_make_unibyte (text); + + Vlast_coding_system_used = coding->symbol; + /* A new coding system might be found. */ + if (!EQ (p->decode_coding_system, coding->symbol)) + { + p->decode_coding_system = coding->symbol; + + /* Don't call setup_coding_system for + proc_decode_coding_system[channel] here. It is done in + detect_coding called via decode_coding above. */ + + /* If a coding system for encoding is not yet decided, we set + it as the same as coding-system for decoding. + But, before doing that we must check if + proc_encode_coding_system[p->outfd] surely points to a + valid memory because p->outfd will be changed once EOF is + sent to the process. */ + if (NILP (p->encode_coding_system) + && proc_encode_coding_system[XINT (p->outfd)]) + { + p->encode_coding_system = coding->symbol; + setup_coding_system (coding->symbol, + proc_encode_coding_system[XINT (p->outfd)]); + } + } + + carryover = nbytes - coding->consumed; + bcopy (chars + coding->consumed, XSTRING (p->decoding_buf)->data, + carryover); + XSETINT (p->decoding_carryover, carryover); + nbytes = STRING_BYTES (XSTRING (text)); + nchars = XSTRING (text)->size; internal_condition_case_1 (read_process_output_call, Fcons (outstream, Fcons (proc, Fcons (text, Qnil))), @@ -3176,6 +3054,7 @@ read_process_output (proc, channel) Lisp_Object odeactivate; int before, before_byte; int opoint_byte; + Lisp_Object text; odeactivate = Vdeactivate_mark; @@ -3207,26 +3086,40 @@ read_process_output (proc, channel) if (! (BEGV <= PT && PT <= ZV)) Fwiden (); - if (NILP (current_buffer->enable_multibyte_characters)) - nchars = nbytes; - + text = decode_coding_string (make_unibyte_string (chars, nbytes), + coding, 0); + Vlast_coding_system_used = coding->symbol; + /* A new coding system might be found. See the comment in the + similar code in the previous `if' block. */ + if (!EQ (p->decode_coding_system, coding->symbol)) + { + p->decode_coding_system = coding->symbol; + if (NILP (p->encode_coding_system) + && proc_encode_coding_system[XINT (p->outfd)]) + { + p->encode_coding_system = coding->symbol; + setup_coding_system (coding->symbol, + proc_encode_coding_system[XINT (p->outfd)]); + } + } + carryover = nbytes - coding->consumed; + bcopy (chars + coding->consumed, XSTRING (p->decoding_buf)->data, + carryover); + XSETINT (p->decoding_carryover, carryover); + /* Adjust the multibyteness of TEXT to that of the buffer. */ + if (NILP (current_buffer->enable_multibyte_characters) + != ! STRING_MULTIBYTE (text)) + text = (STRING_MULTIBYTE (text) + ? Fstring_as_unibyte (text) + : Fstring_as_multibyte (text)); + nbytes = STRING_BYTES (XSTRING (text)); + nchars = XSTRING (text)->size; /* Insert before markers in case we are inserting where the buffer's mark is, and the user's next command is Meta-y. */ - if (chars_in_decoding_buf) - { - /* Since multibyteness of p->docoding_buf is corrupted, we - can't use insert_from_string_before_markers. */ - char *temp_buf; + insert_from_string_before_markers (text, 0, 0, nchars, nbytes, 0); + signal_after_change (before, 0, PT - before); + update_compositions (before, PT, CHECK_BORDER); - temp_buf = (char *) alloca (nbytes); - bcopy (XSTRING (p->decoding_buf)->data, temp_buf, nbytes); - insert_before_markers (temp_buf, nbytes); - } - else - { - insert_1_both (chars, nchars, nbytes, 0, 1, 1); - signal_after_change (opoint, 0, PT - opoint); - } set_marker_both (p->mark, p->buffer, PT, PT_BYTE); update_mode_lines++; @@ -3278,6 +3171,7 @@ This is intended for use by asynchronous process output filters and sentinels.") /* Sending data to subprocess */ jmp_buf send_process_frame; +Lisp_Object process_sent_to; SIGTYPE send_process_trap () @@ -3291,27 +3185,25 @@ send_process_trap () /* Send some data to process PROC. BUF is the beginning of the data; LEN is the number of characters. - OBJECT is the Lisp object that the data comes from. + OBJECT is the Lisp object that the data comes from. If OBJECT is + nil or t, it means that the data comes from C string. + + If OBJECT is not nil, the data is encoded by PROC's coding-system + for encoding before it is sent. - The data is encoded by PROC's coding-system for encoding before it - is sent. But if the data ends at the middle of multi-byte - representation, that incomplete sequence of bytes are sent without - being encoded. Should we store them in a buffer to prepend them to - the data send later? */ + This function can evaluate Lisp code and can garbage collect. */ void send_process (proc, buf, len, object) volatile Lisp_Object proc; - unsigned char *buf; - int len; - Lisp_Object object; + unsigned char *volatile buf; + volatile int len; + volatile Lisp_Object object; { /* Use volatile to protect variables from being clobbered by longjmp. */ int rv; - volatile unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data; struct coding_system *coding; struct gcpro gcpro1; - int carryover = XINT (XPROCESS (proc)->encoding_carryover); GCPRO1 (object); @@ -3323,64 +3215,81 @@ send_process (proc, buf, len, object) if (! NILP (XPROCESS (proc)->raw_status_low)) update_status (XPROCESS (proc)); if (! EQ (XPROCESS (proc)->status, Qrun)) - error ("Process %s not running", procname); + error ("Process %s not running", + XSTRING (XPROCESS (proc)->name)->data); if (XINT (XPROCESS (proc)->outfd) < 0) - error ("Output file descriptor of %s is closed", procname); + error ("Output file descriptor of %s is closed", + XSTRING (XPROCESS (proc)->name)->data); coding = proc_encode_coding_system[XINT (XPROCESS (proc)->outfd)]; Vlast_coding_system_used = coding->symbol; + if ((STRINGP (object) && STRING_MULTIBYTE (object)) + || (BUFFERP (object) + && !NILP (XBUFFER (object)->enable_multibyte_characters)) + || EQ (object, Qt)) + { + coding->src_multibyte = 1; + if (!EQ (coding->symbol, XPROCESS (proc)->encode_coding_system)) + /* The coding system for encoding was changed to raw-text + because we sent a unibyte text previously. Now we are + sending a multibyte text, thus we must encode it by the + original coding system specified for the current + process. */ + setup_coding_system (XPROCESS (proc)->encode_coding_system, + coding); + } + else + { + /* For sending a unibyte text, character code conversion should + not take place but EOL conversion should. So, setup raw-text + or one of the subsidiary if we have not yet done it. */ + if (coding->type != coding_type_raw_text) + { + if (CODING_REQUIRE_FLUSHING (coding)) + { + /* But, before changing the coding, we must flush out data. */ + coding->mode |= CODING_MODE_LAST_BLOCK; + send_process (proc, "", 0, Qt); + } + coding->src_multibyte = 0; + setup_raw_text_coding_system (coding); + } + } + coding->dst_multibyte = 0; + if (CODING_REQUIRE_ENCODING (coding)) { int require = encoding_buffer_size (coding, len); - int offset; + int from_byte = -1, from = -1, to = -1; unsigned char *temp_buf = NULL; - /* Remember the offset of data because a string or a buffer may - be relocated. Setting OFFSET to -1 means we don't have to - care about relocation. */ - offset = (BUFFERP (object) - ? BUF_PTR_BYTE_POS (XBUFFER (object), buf) - : (STRINGP (object) - ? buf - XSTRING (object)->data - : -1)); - - if (carryover > 0) + if (BUFFERP (object)) { - temp_buf = (unsigned char *) xmalloc (len + carryover); - - if (offset >= 0) - { - if (BUFFERP (object)) - buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset); - else if (STRINGP (object)) - buf = offset + XSTRING (object)->data; - /* Now we don't have to care about relocation. */ - offset = -1; - } - bcopy ((XSTRING (XPROCESS (proc)->encoding_buf)->data - + STRING_BYTES (XSTRING (XPROCESS (proc)->encoding_buf)) - - carryover), - temp_buf, - carryover); - bcopy (buf, temp_buf + carryover, len); - buf = temp_buf; + from_byte = BUF_PTR_BYTE_POS (XBUFFER (object), buf); + from = buf_bytepos_to_charpos (XBUFFER (object), from_byte); + to = buf_bytepos_to_charpos (XBUFFER (object), from_byte + len); } + else if (STRINGP (object)) + { + from_byte = buf - XSTRING (object)->data; + from = string_byte_to_char (object, from_byte); + to = string_byte_to_char (object, from_byte + len); + } + + if (from_byte >= 0 && coding->composing != COMPOSITION_DISABLED) + coding_save_composition (coding, from, to, object); if (STRING_BYTES (XSTRING (XPROCESS (proc)->encoding_buf)) < require) - { - XPROCESS (proc)->encoding_buf = make_uninit_string (require); + XPROCESS (proc)->encoding_buf = make_uninit_string (require); + + if (from_byte >= 0) + buf = (BUFFERP (object) + ? BUF_BYTE_ADDRESS (XBUFFER (object), from_byte) + : XSTRING (object)->data + from_byte); - if (offset >= 0) - { - if (BUFFERP (object)) - buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset); - else if (STRINGP (object)) - buf = offset + XSTRING (object)->data; - } - } object = XPROCESS (proc)->encoding_buf; - encode_coding (coding, buf, XSTRING (object)->data, + encode_coding (coding, (char *) buf, XSTRING (object)->data, len, STRING_BYTES (XSTRING (object))); len = coding->produced; buf = XSTRING (object)->data; @@ -3394,7 +3303,7 @@ send_process (proc, buf, len, object) error ("Could not find this process: %x", p->pid); else if (write_to_vms_process (vs, buf, len)) ; -#else +#else /* not VMS */ if (pty_max_bytes == 0) { @@ -3410,111 +3319,149 @@ send_process (proc, buf, len, object) pty_max_bytes--; } + /* 2000-09-21: Emacs 20.7, sparc-sun-solaris-2.6, GCC 2.95.2, + CFLAGS="-g -O": The value of the parameter `proc' is clobbered + when returning with longjmp despite being declared volatile. */ if (!setjmp (send_process_frame)) - while (len > 0) - { - int this = len; - SIGTYPE (*old_sigpipe)(); + { + process_sent_to = proc; + while (len > 0) + { + int this = len; + SIGTYPE (*old_sigpipe)(); - /* Decide how much data we can send in one batch. - Long lines need to be split into multiple batches. */ - if (!NILP (XPROCESS (proc)->pty_flag)) - { - /* Starting this at zero is always correct when not the first iteration - because the previous iteration ended by sending C-d. - It may not be correct for the first iteration - if a partial line was sent in a separate send_process call. - If that proves worth handling, we need to save linepos - in the process object. */ - int linepos = 0; - unsigned char *ptr = buf; - unsigned char *end = buf + len; - - /* Scan through this text for a line that is too long. */ - while (ptr != end && linepos < pty_max_bytes) - { - if (*ptr == '\n') - linepos = 0; - else - linepos++; - ptr++; - } - /* If we found one, break the line there - and put in a C-d to force the buffer through. */ - this = ptr - buf; - } + /* Decide how much data we can send in one batch. + Long lines need to be split into multiple batches. */ + if (!NILP (XPROCESS (proc)->pty_flag)) + { + /* Starting this at zero is always correct when not the first iteration + because the previous iteration ended by sending C-d. + It may not be correct for the first iteration + if a partial line was sent in a separate send_process call. + If that proves worth handling, we need to save linepos + in the process object. */ + int linepos = 0; + unsigned char *ptr = (unsigned char *) buf; + unsigned char *end = (unsigned char *) buf + len; + + /* Scan through this text for a line that is too long. */ + while (ptr != end && linepos < pty_max_bytes) + { + if (*ptr == '\n') + linepos = 0; + else + linepos++; + ptr++; + } + /* If we found one, break the line there + and put in a C-d to force the buffer through. */ + this = ptr - buf; + } - /* Send this batch, using one or more write calls. */ - while (this > 0) - { - old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap); - rv = emacs_write (XINT (XPROCESS (proc)->outfd), buf, this); - signal (SIGPIPE, old_sigpipe); + /* Send this batch, using one or more write calls. */ + while (this > 0) + { + old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap); + rv = emacs_write (XINT (XPROCESS (proc)->outfd), + (char *) buf, this); + signal (SIGPIPE, old_sigpipe); - if (rv < 0) - { - if (0 + if (rv < 0) + { + if (0 #ifdef EWOULDBLOCK - || errno == EWOULDBLOCK + || errno == EWOULDBLOCK #endif #ifdef EAGAIN - || errno == EAGAIN + || errno == EAGAIN #endif - ) - /* Buffer is full. Wait, accepting input; - that may allow the program - to finish doing output and read more. */ - { - Lisp_Object zero; - int offset; - - /* Running filters might relocate buffers or strings. - Arrange to relocate BUF. */ - if (BUFFERP (object)) - offset = BUF_PTR_BYTE_POS (XBUFFER (object), buf); - else if (STRINGP (object)) - offset = buf - XSTRING (object)->data; - - XSETFASTINT (zero, 0); + ) + /* Buffer is full. Wait, accepting input; + that may allow the program + to finish doing output and read more. */ + { + Lisp_Object zero; + int offset = 0; + +#ifdef BROKEN_PTY_READ_AFTER_EAGAIN + /* A gross hack to work around a bug in FreeBSD. + In the following sequence, read(2) returns + bogus data: + + write(2) 1022 bytes + write(2) 954 bytes, get EAGAIN + read(2) 1024 bytes in process_read_output + read(2) 11 bytes in process_read_output + + That is, read(2) returns more bytes than have + ever been written successfully. The 1033 bytes + read are the 1022 bytes written successfully + after processing (for example with CRs added if + the terminal is set up that way which it is + here). The same bytes will be seen again in a + later read(2), without the CRs. */ + + if (errno == EAGAIN) + { + int flags = FWRITE; + ioctl (XINT (XPROCESS (proc)->outfd), TIOCFLUSH, + &flags); + } +#endif /* BROKEN_PTY_READ_AFTER_EAGAIN */ + + /* Running filters might relocate buffers or strings. + Arrange to relocate BUF. */ + if (BUFFERP (object)) + offset = BUF_PTR_BYTE_POS (XBUFFER (object), buf); + else if (STRINGP (object)) + offset = buf - XSTRING (object)->data; + + XSETFASTINT (zero, 0); #ifdef EMACS_HAS_USECS - wait_reading_process_input (0, 20000, zero, 0); + wait_reading_process_input (0, 20000, zero, 0); #else - wait_reading_process_input (1, 0, zero, 0); + wait_reading_process_input (1, 0, zero, 0); #endif - if (BUFFERP (object)) - buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset); - else if (STRINGP (object)) - buf = offset + XSTRING (object)->data; + if (BUFFERP (object)) + buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset); + else if (STRINGP (object)) + buf = offset + XSTRING (object)->data; - rv = 0; - } - else - /* This is a real error. */ - report_file_error ("writing to process", Fcons (proc, Qnil)); - } - buf += rv; - len -= rv; - this -= rv; - } + rv = 0; + } + else + /* This is a real error. */ + report_file_error ("writing to process", Fcons (proc, Qnil)); + } + buf += rv; + len -= rv; + this -= rv; + } - /* If we sent just part of the string, put in an EOF - to force it through, before we send the rest. */ - if (len > 0) - Fprocess_send_eof (proc); - } -#endif + /* If we sent just part of the string, put in an EOF + to force it through, before we send the rest. */ + if (len > 0) + Fprocess_send_eof (proc); + } + } +#endif /* not VMS */ else { +#ifndef VMS + proc = process_sent_to; +#endif XPROCESS (proc)->raw_status_low = Qnil; XPROCESS (proc)->raw_status_high = Qnil; XPROCESS (proc)->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); XSETINT (XPROCESS (proc)->tick, ++process_tick); deactivate_process (proc); #ifdef VMS - error ("Error writing to process %s; closed it", procname); + error ("Error writing to process %s; closed it", + XSTRING (XPROCESS (proc)->name)->data); #else - error ("SIGPIPE raised on process %s; closed it", procname); + error ("SIGPIPE raised on process %s; closed it", + XSTRING (XPROCESS (proc)->name)->data); #endif } @@ -4254,7 +4201,7 @@ sigchld_handler (signo) int code = WTERMSIG (w); char *signame; - synchronize_messages_locale (); + synchronize_system_messages_locale (); signame = strsignal (code); if (signame == 0) @@ -4301,6 +4248,7 @@ exec_sentinel_error_handler (error) Vinhibit_quit = Qt; update_echo_area (); Fsleep_for (make_number (2), Qnil); + return Qt; } static void @@ -4623,11 +4571,6 @@ init_process () } bzero (proc_decode_coding_system, sizeof proc_decode_coding_system); bzero (proc_encode_coding_system, sizeof proc_encode_coding_system); - - Vdefault_process_coding_system - = (NILP (buffer_defaults.enable_multibyte_characters) - ? Fcons (Qraw_text, Qnil) - : Fcons (Qemacs_mule, Qnil)); } void @@ -4788,7 +4731,7 @@ wait_reading_process_input (time_limit, microsecs, read_kbd, do_display) /* Turn off periodic alarms (in case they are in use) because the select emulator uses alarms. */ - stop_polling (); + turn_on_atimers (0); while (1) {