/* Asynchronous subprocess control for GNU Emacs.
- Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
+ Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <sys/types.h> /* some typedefs are used in sys/file.h */
#include <sys/file.h>
#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
#include <sys/socket.h>
#include "syswait.h"
-extern errno;
-extern sys_nerr;
+extern int errno;
+extern char *strerror ();
+#ifdef VMS
extern char *sys_errlist[];
+#endif
+#ifndef SYS_SIGLIST_DECLARED
#ifndef VMS
#ifndef BSD4_1
#ifndef LINUX
};
#endif
#endif /* VMS */
+#endif /* ! SYS_SIGLIST_DECLARED */
/* t means use pty, nil means use a pipe,
maybe other values to come. */
static int delete_exited_processes;
/* Indexed by descriptor, gives the process (if any) for that descriptor */
-static Lisp_Object chan_process[MAXDESC];
+Lisp_Object chan_process[MAXDESC];
/* Alist of elements (NAME . PROCESS) */
-static Lisp_Object Vprocess_alist;
+Lisp_Object Vprocess_alist;
/* Buffered-ahead input char from process, indexed by channel.
-1 means empty (no char is buffered).
static int proc_buffered_char[MAXDESC];
static Lisp_Object get_process ();
+
+/* Maximum number of bytes to send to a pty without an eof. */
+static int pty_max_bytes;
\f
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
{
+ char *signame = 0;
+ if (code < NSIG)
+ {
#ifndef VMS
- string = build_string (code < NSIG ? sys_siglist[code] : "unknown");
+ signame = sys_siglist[code];
#else
- string = build_string (code < NSIG ? sys_errlist[code] : "unknown");
+ signame = sys_errlist[code];
#endif
+ }
+ if (signame == 0)
+ signame = "unknown";
+ string = build_string (signame);
string2 = build_string (coredump ? " (core dumped)\n" : "\n");
XSTRING (string)->data[0] = DOWNCASE (XSTRING (string)->data[0]);
return concat2 (string, string2);
get_process (name)
register Lisp_Object name;
{
- register Lisp_Object proc;
- if (NILP (name))
- proc = Fget_buffer_process (Fcurrent_buffer ());
+ register Lisp_Object proc, obj;
+ if (STRINGP (name))
+ {
+ obj = Fget_process (name);
+ if (NILP (obj))
+ obj = Fget_buffer (name);
+ if (NILP (obj))
+ error ("Process %s does not exist", XSTRING (name)->data);
+ }
+ else if (NILP (name))
+ obj = Fcurrent_buffer ();
else
+ obj = name;
+
+ /* Now obj should be either a buffer object or a process object.
+ */
+ if (BUFFERP (obj))
{
- proc = Fget_process (name);
+ proc = Fget_buffer_process (obj);
if (NILP (proc))
- proc = Fget_buffer_process (Fget_buffer (name));
+ error ("Buffer %s has no process", XSTRING (XBUFFER (obj)->name)->data);
}
-
- if (!NILP (proc))
- return proc;
-
- if (NILP (name))
- error ("Current buffer has no process");
else
- error ("Process %s does not exist", XSTRING (name)->data);
- /* NOTREACHED */
+ {
+ CHECK_PROCESS (obj, 0);
+ proc = obj;
+ }
+ return proc;
}
DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
DEFUN ("process-kill-without-query", Fprocess_kill_without_query,
Sprocess_kill_without_query, 1, 2, 0,
"Say no query needed if PROCESS is running when Emacs is exited.\n\
-Optional second argument if non-nill says to require a query.\n\
+Optional second argument if non-nil says to require a query.\n\
Value is t if a query was formerly required.")
(proc, value)
register Lisp_Object proc, value;
#else /* not VMS */
new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
- 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;
- new_argv[0] = XSTRING (program)->data;
-
/* If program file name is not absolute, search our path for it */
- if (new_argv[0][0] != '/')
+ if (XSTRING (program)->data[0] != '/')
{
+ 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));
new_argv[0] = XSTRING (tem)->data;
}
+ else
+ 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);
#endif /* USG */
#endif /* not HAVE_SETSID */
#ifdef NTTYDISC
- {
- /* Use new line discipline. */
- int ldisc = NTTYDISC;
- if (ioctl (xforkin, TIOCSETD, &ldisc) < 0)
- write (1, "create_process/TIOCSETD failed\n", 31);
- }
+ if (pty_flag && xforkin >= 0)
+ {
+ /* Use new line discipline. */
+ int ldisc = NTTYDISC;
+ if (ioctl (xforkin, TIOCSETD, &ldisc) < 0)
+ write (1, "create_process/TIOCSETD failed\n", 31);
+ }
#endif
#ifdef TIOCNOTTY
/* In 4.3BSD, the TIOCSPGRP bug has been fixed, and now you
condition here; if a SIGIO arrives between now and the select
and indicates that a frame is trashed, the select may block
displaying a trashed screen. */
- if (frame_garbaged)
+ if (frame_garbaged && do_display)
redisplay_preserve_echo_area ();
if (XINT (read_kbd) && detect_input_pending ())
#endif
}
else
- error("select error: %s", sys_errlist[xerrno]);
+ error("select error: %s", strerror (xerrno));
}
#if defined(sun) && !defined(USG5_4)
else if (nfds > 0 && FD_ISSET (keyboard_descriptor, &Available)
#ifdef VMS
start_vms_process_read (vs);
#endif
- unbind_to (count);
+ unbind_to (count, Qnil);
return nchars;
}
{
int this = len;
SIGTYPE (*old_sigpipe)();
+ int flush_pty = 0;
+
+ if (pty_max_bytes == 0)
+ {
+#if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON)
+ pty_max_bytes = fpathconf (XFASTINT (XPROCESS (proc)->outfd),
+ _PC_MAX_CANON);
+#else
+ pty_max_bytes = 250;
+#endif
+ }
+
+ /* Don't send more than pty_max_bytes bytes at a time. */
+ /* Subtract 1 to leave room for the EOF. */
+ if (this >= pty_max_bytes && XPROCESS (proc)->pty_flag != 0)
+ this = pty_max_bytes - 1;
- /* Don't send more than 500 bytes at a time. */
- if (this > 500)
- this = 500;
old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
rv = write (XINT (XPROCESS (proc)->outfd), buf, this);
+
+ /* If we sent just part of the string, put in an EOF
+ to force it through, before we send the rest. */
+ if (this < len)
+ Fprocess_send_eof (proc);
+
signal (SIGPIPE, old_sigpipe);
if (rv < 0)
{
if (WIFEXITED (w))
synch_process_retcode = WRETCODE (w);
else if (WIFSIGNALED (w))
+ {
+ int code = WTERMSIG (w);
+ char *signame = 0;
+
+ if (code < NSIG)
+ {
#ifndef VMS
- synch_process_death = (char *) sys_siglist[WTERMSIG (w)];
+ signame = sys_siglist[code];
#else
- synch_process_death = sys_errlist[WTERMSIG (w)];
+ signame = sys_errlist[code];
#endif
+ }
+ if (signame == 0)
+ signame = "unknown";
+
+ synch_process_death = signame;
+ }
/* Tell wait_reading_process_input that it needs to wake up and
look around. */
/* Inhibit quit so that random quits don't screw up a running filter. */
specbind (Qinhibit_quit, Qt);
call2 (sentinel, proc, reason);
- unbind_to (count);
+ unbind_to (count, Qnil);
}
/* Report all recent events of a change in process status
status_notify ()
{
register Lisp_Object proc, buffer;
- Lisp_Object tail = Qnil;
- Lisp_Object msg = Qnil;
+ Lisp_Object tail, msg;
struct gcpro gcpro1, gcpro2;
+ tail = Qnil;
+ msg = Qnil;
/* We need to gcpro tail; if read_process_output calls a filter
which deletes a process and removes the cons to which tail points
from Vprocess_alist, and then causes a GC, tail is an unprotected
when a process becomes runnable. */
else if (!EQ (symbol, Qrun) && !NILP (buffer))
{
- Lisp_Object ro = XBUFFER (buffer)->read_only;
- Lisp_Object tem;
+ Lisp_Object ro, tem;
struct buffer *old = current_buffer;
int opoint;
+ ro = XBUFFER (buffer)->read_only;
+
/* Avoid error if buffer is deleted
(probably that's why the process is dead, too) */
if (NILP (XBUFFER (buffer)->name))
`subprocesses' isn't defined.
do_display != 0 means redisplay should be done to show subprocess
- output that arrives. This version of the function ignores it.
+ output that arrives.
Return true iff we received input from any process. */
/* If a frame has been newly mapped and needs updating,
reprocess its display stuff. */
- if (frame_garbaged)
+ if (frame_garbaged && do_display)
redisplay_preserve_echo_area ();
if (XINT (read_kbd) && detect_input_pending ())
DEFUN ("get-buffer-process", Fget_buffer_process, Sget_buffer_process, 1, 1, 0,
- /* Don't confused make-docfile by having two doc strings for this function.
+ /* Don't confuse make-docfile by having two doc strings for this function.
make-docfile does not pay attention to #if, for good reason! */
0)
(name)