Boston, MA 02111-1307, USA. */
+#define _GNU_SOURCE /* to get strsignal declared with glibc 2 */
#include <config.h>
-
#include <signal.h>
/* This file is split into two parts by the following preprocessor
#include <unistd.h>
#endif
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(UNIX98_PTYS)
#include <stdlib.h>
#include <fcntl.h>
#endif /* not WINDOWSNT */
#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 <client.h>
#endif
#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))
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
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;
if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
{
char *signame;
- synchronize_messages_locale ();
+ synchronize_system_messages_locale ();
signame = strsignal (code);
if (signame == 0)
signame = "unknown";
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\
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
/* 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))
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))
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;
}
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);
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
/* 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;
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
/* 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);
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;
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
CHECK_STRING (service, 0);
portstring = XSTRING (service)->data;
}
-#else /* ! HAVE_GETADDRINFO */
+#else /* HAVE_GETADDRINFO */
if (INTEGERP (service))
port = htons ((unsigned short) XINT (service));
else
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.
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;
}
report_file_error ("connection failed",
Fcons (host, Fcons (name, Qnil)));
}
-#else /* ! HAVE_GETADDRINFO */
+
+#else /* not HAVE_GETADDRINFO */
while (1)
{
break;
Fsleep_for (make_number (1), Qnil);
}
+
if (host_info_ptr == 0)
/* Attempt to interpret host as numeric inet address */
{
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
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. */
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;
}
\f
Vinhibit_quit = Qt;
update_echo_area ();
Fsleep_for (make_number (2), Qnil);
+ return Qt;
}
/* Read pending output from the process 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
/* 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)
{
/* 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;
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))),
Lisp_Object odeactivate;
int before, before_byte;
int opoint_byte;
+ Lisp_Object text;
odeactivate = Vdeactivate_mark;
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++;
/* Sending data to subprocess */
jmp_buf send_process_frame;
+Lisp_Object process_sent_to;
SIGTYPE
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);
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;
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)
{
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
}
int code = WTERMSIG (w);
char *signame;
- synchronize_messages_locale ();
+ synchronize_system_messages_locale ();
signame = strsignal (code);
if (signame == 0)
Vinhibit_quit = Qt;
update_echo_area ();
Fsleep_for (make_number (2), Qnil);
+ return Qt;
}
static void
}
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
/* Turn off periodic alarms (in case they are in use)
because the select emulator uses alarms. */
- stop_polling ();
+ turn_on_atimers (0);
while (1)
{