/* Asynchronous subprocess control for GNU Emacs.
- Copyright (C) 1985, 86, 87, 88, 93, 94 Free Software Foundation, Inc.
+ Copyright (C) 1985, 86, 87, 88, 93, 94, 95 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#ifdef NEED_NET_ERRNO_H
+#include <net/errno.h>
+#endif /* NEED_NET_ERRNO_H */
#endif /* HAVE_SOCKETS */
/* TERM is a poor-man's SLIP, used on Linux. */
#endif
#endif /* SKTPAIR */
+/* These next two vars are non-static since sysdep.c uses them in the
+ emulation of `select'. */
/* Number of events of change of status of a process. */
-static int process_tick;
-
+int process_tick;
/* Number of events for which the user or sentinel has been notified. */
-static int update_tick;
+int update_tick;
#include "sysselect.h"
/* Maximum number of bytes to send to a pty without an eof. */
static int pty_max_bytes;
-/* Open an available pty, returning a file descriptor.
- Return -1 on failure.
- The file name of the terminal corresponding to the pty
- is left in the variable pty_name. */
+#ifdef HAVE_PTYS
+/* The file name of the pty opened by allocate_pty. */
static char pty_name[24];
+#endif
\f
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
\f
#ifdef HAVE_PTYS
+/* Open an available pty, returning a file descriptor.
+ Return -1 on failure.
+ The file name of the terminal corresponding to the pty
+ is left in the variable pty_name. */
+
int
allocate_pty ()
{
tem = Fcar (Fcdr (p->status));
if (XFASTINT (tem))
{
- sprintf (tembuf, " %d", XFASTINT (tem));
+ sprintf (tembuf, " %d", (int) XFASTINT (tem));
write_string (tembuf, -1);
}
}
GCPRO2 (buffer, current_dir);
- current_dir =
- expand_and_dir_to_file
- (Funhandled_file_name_directory (current_dir), Qnil);
+ current_dir
+ = expand_and_dir_to_file (Funhandled_file_name_directory (current_dir),
+ Qnil);
if (NILP (Ffile_accessible_directory_p (current_dir)))
report_file_error ("Setting current directory",
Fcons (current_buffer->directory, Qnil));
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
- new_argv[0] = XSTRING (program)->data;
+ {
+ 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++)
{
XPROCESS (proc)->filter = Qnil;
XPROCESS (proc)->command = Flist (nargs - 2, args + 2);
+ /* Make the process marker point into the process buffer (if any). */
+ if (!NILP (buffer))
+ Fset_marker (XPROCESS (proc)->mark,
+ make_number (BUF_ZV (XBUFFER (buffer))), buffer);
+
create_process (proc, new_argv, current_dir);
return unbind_to (count, proc);
char **new_argv;
Lisp_Object current_dir;
{
- int pid, inchannel, outchannel, forkin, forkout;
+ int pid, inchannel, outchannel;
int sv[2];
#ifdef SIGCHLD
SIGTYPE (*sigchld)();
#endif
- int pty_flag = 0;
+ /* Use volatile to protect variables from being clobbered by longjmp. */
+ volatile int forkin, forkout;
+ volatile int pty_flag = 0;
extern char **environ;
inchannel = outchannel = -1;
close (xforkin);
xforkout = xforkin = open (pty_name, O_RDWR, 0);
+ if (xforkin < 0)
+ {
+ write (1, "Couldn't open the pty terminal ", 31);
+ write (1, pty_name, strlen (pty_name));
+ write (1, "\n", 1);
+ _exit (1);
+ }
+
#ifdef SET_CHILD_PTY_PGRP
ioctl (xforkin, TIOCSPGRP, &pgrp);
ioctl (xforkout, TIOCSPGRP, &pgrp);
#endif
-
- if (xforkin < 0)
- abort ();
}
#endif /* not UNIPLUS and not RTU */
#ifdef SETUP_SLAVE_PTY
if (forkin != forkout && forkout >= 0)
close (forkout);
- XPROCESS (process)->tty_name = build_string (pty_name);
+#ifdef HAVE_PTYS
+ if (pty_flag)
+ XPROCESS (process)->tty_name = build_string (pty_name);
+ else
+#endif
+ XPROCESS (process)->tty_name = Qnil;
#ifdef SIGCHLD
#ifdef BSD4_1
goto loop;
if (errno == 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;
}
EMACS_ADD_TIME (end_time, end_time, timeout);
}
- /* It would not be safe to call this below,
- where we call redisplay_preserve_echo_area. */
- if (do_display && frame_garbaged)
- prepare_menu_bars ();
-
while (1)
{
/* If calling from keyboard input, do not quit
{
Atemp = input_wait_mask;
EMACS_SET_SECS_USECS (timeout, 0, 0);
- if (select (MAXDESC, &Atemp, 0, 0, &timeout) <= 0)
+ if ((select (MAXDESC, &Atemp, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+ &timeout)
+ <= 0))
{
/* It's okay for us to do this and then continue with
the loop, since timeout has already been zeroed out. */
and indicates that a frame is trashed, the select may block
displaying a trashed screen. */
if (frame_garbaged && do_display)
- redisplay_preserve_echo_area ();
+ {
+ clear_waiting_for_input ();
+ redisplay_preserve_echo_area ();
+ if (XINT (read_kbd) < 0)
+ set_waiting_for_input (&timeout);
+ }
if (XINT (read_kbd) && detect_input_pending ())
{
FD_ZERO (&Available);
}
else
- nfds = select (MAXDESC, &Available, 0, 0, &timeout);
+ nfds = select (MAXDESC, &Available, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+ &timeout);
xerrno = errno;
cmd_error_internal (error, "error in process filter: ");
Vinhibit_quit = Qt;
update_echo_area ();
- Fsleep_for (make_number (2));
+ Fsleep_for (make_number (2), Qnil);
}
/* Read pending output from the process channel,
it up. */
int count = specpdl_ptr - specpdl;
Lisp_Object odeactivate;
- Lisp_Object obuffer;
+ Lisp_Object obuffer, okeymap;
+ /* No need to gcpro these, because all we do with them later
+ is test them for EQness, and none of them should be a string. */
odeactivate = Vdeactivate_mark;
- obuffer = Fcurrent_buffer ();
+ XSETBUFFER (obuffer, current_buffer);
+ okeymap = current_buffer->keymap;
specbind (Qinhibit_quit, Qt);
specbind (Qlast_nonmenu_event, Qt);
/* Handling the process output should not deactivate the mark. */
Vdeactivate_mark = odeactivate;
- if (! EQ (Fcurrent_buffer (), obuffer))
- record_asynch_buffer_change ();
-
- if (waiting_for_user_input_p)
- prepare_menu_bars ();
+#if 0 /* Call record_asynch_buffer_change unconditionally,
+ because we might have changed minor modes or other things
+ that affect key bindings. */
+ if (! EQ (Fcurrent_buffer (), obuffer)
+ || ! EQ (current_buffer->keymap, okeymap))
+#endif
+ /* But do it only if the caller is actually going to read events.
+ Otherwise there's no need to make him wake up, and it could
+ cause trouble (for example it would make Fsit_for return). */
+ if (waiting_for_user_input_p == -1)
+ record_asynch_buffer_change ();
#ifdef VMS
start_vms_process_read (vs);
OBJECT is the Lisp object that the data comes from. */
send_process (proc, buf, len, object)
- Lisp_Object proc;
+ volatile Lisp_Object proc;
char *buf;
int len;
Lisp_Object object;
{
- /* Don't use register vars; longjmp can lose them. */
+ /* Use volatile to protect variables from being clobbered by longjmp. */
int rv;
- unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
+ volatile unsigned char *procname = XSTRING (XPROCESS (proc)->name)->data;
#ifdef VMS
struct Lisp_Process *p = XPROCESS (proc);
DEFUN ("signal-process", Fsignal_process, Ssignal_process,
2, 2, "nProcess number: \nnSignal code: ",
- "Send the process with number PID the signal with code CODE.\n\
-Both PID and CODE are integers.")
- (pid, sig)
- Lisp_Object pid, sig;
+ "Send the process with process id PID the signal with code SIGCODE.\n\
+PID must be an integer. The process need not be a child of this Emacs.\n\
+SIGCODE may be an integer, or a symbol whose name is a signal name.")
+ (pid, sigcode)
+ Lisp_Object pid, sigcode;
{
CHECK_NUMBER (pid, 0);
- CHECK_NUMBER (sig, 1);
+
+#define handle_signal(NAME, VALUE) \
+ else if (!strcmp (name, NAME)) \
+ XSETINT (sigcode, VALUE)
+
+ if (INTEGERP (sigcode))
+ ;
+ else
+ {
+ unsigned char *name;
+
+ CHECK_SYMBOL (sigcode, 1);
+ name = XSYMBOL (sigcode)->name->data;
+
+ if (0)
+ ;
+#ifdef SIGHUP
+ handle_signal ("SIGHUP", SIGHUP);
+#endif
+#ifdef SIGINT
+ handle_signal ("SIGINT", SIGINT);
+#endif
+#ifdef SIGQUIT
+ handle_signal ("SIGQUIT", SIGQUIT);
+#endif
+#ifdef SIGILL
+ handle_signal ("SIGILL", SIGILL);
+#endif
+#ifdef SIGABRT
+ handle_signal ("SIGABRT", SIGABRT);
+#endif
+#ifdef SIGEMT
+ handle_signal ("SIGEMT", SIGEMT);
+#endif
+#ifdef SIGKILL
+ handle_signal ("SIGKILL", SIGKILL);
+#endif
+#ifdef SIGFPE
+ handle_signal ("SIGFPE", SIGFPE);
+#endif
+#ifdef SIGBUS
+ handle_signal ("SIGBUS", SIGBUS);
+#endif
+#ifdef SIGSEGV
+ handle_signal ("SIGSEGV", SIGSEGV);
+#endif
+#ifdef SIGSYS
+ handle_signal ("SIGSYS", SIGSYS);
+#endif
+#ifdef SIGPIPE
+ handle_signal ("SIGPIPE", SIGPIPE);
+#endif
+#ifdef SIGALRM
+ handle_signal ("SIGALRM", SIGALRM);
+#endif
+#ifdef SIGTERM
+ handle_signal ("SIGTERM", SIGTERM);
+#endif
+#ifdef SIGURG
+ handle_signal ("SIGURG", SIGURG);
+#endif
+#ifdef SIGSTOP
+ handle_signal ("SIGSTOP", SIGSTOP);
+#endif
+#ifdef SIGTSTP
+ handle_signal ("SIGTSTP", SIGTSTP);
+#endif
+#ifdef SIGCONT
+ handle_signal ("SIGCONT", SIGCONT);
+#endif
+#ifdef SIGCHLD
+ handle_signal ("SIGCHLD", SIGCHLD);
+#endif
+#ifdef SIGTTIN
+ handle_signal ("SIGTTIN", SIGTTIN);
+#endif
+#ifdef SIGTTOU
+ handle_signal ("SIGTTOU", SIGTTOU);
+#endif
+#ifdef SIGIO
+ handle_signal ("SIGIO", SIGIO);
+#endif
+#ifdef SIGXCPU
+ handle_signal ("SIGXCPU", SIGXCPU);
+#endif
+#ifdef SIGXFSZ
+ handle_signal ("SIGXFSZ", SIGXFSZ);
+#endif
+#ifdef SIGVTALRM
+ handle_signal ("SIGVTALRM", SIGVTALRM);
+#endif
+#ifdef SIGPROF
+ handle_signal ("SIGPROF", SIGPROF);
+#endif
+#ifdef SIGWINCH
+ handle_signal ("SIGWINCH", SIGWINCH);
+#endif
+#ifdef SIGINFO
+ handle_signal ("SIGINFO", SIGINFO);
+#endif
+#ifdef SIGUSR1
+ handle_signal ("SIGUSR1", SIGUSR1);
+#endif
+#ifdef SIGUSR2
+ handle_signal ("SIGUSR2", SIGUSR2);
+#endif
+ else
+ error ("Undefined signal name %s", name);
+ }
+
+#undef handle_signal
+
#ifdef WINDOWSNT
/* Only works for kill-type signals */
- return make_number (win32_kill_process (XINT (pid), XINT (sig)));
+ return make_number (win32_kill_process (XINT (pid), XINT (sigcode)));
#else
- return make_number (kill (XINT (pid), XINT (sig)));
+ return make_number (kill (XINT (pid), XINT (sigcode)));
#endif
}
XSETINT (p->tick, ++process_tick);
u.wt = w;
- XSETFASTINT (p->raw_status_low, u.i & 0xffff);
- XSETFASTINT (p->raw_status_high, u.i >> 16);
+ XSETINT (p->raw_status_low, u.i & 0xffff);
+ XSETINT (p->raw_status_high, u.i >> 16);
/* If process has terminated, stop waiting for its output. */
if ((WIFSIGNALED (w) || WIFEXITED (w))
cmd_error_internal (error, "error in process sentinel: ");
Vinhibit_quit = Qt;
update_echo_area ();
- Fsleep_for (make_number (2));
+ Fsleep_for (make_number (2), Qnil);
}
static void
exec_sentinel (proc, reason)
Lisp_Object proc, reason;
{
- Lisp_Object sentinel, obuffer, odeactivate;
+ Lisp_Object sentinel, obuffer, odeactivate, okeymap;
register struct Lisp_Process *p = XPROCESS (proc);
int count = specpdl_ptr - specpdl;
+ /* No need to gcpro these, because all we do with them later
+ is test them for EQness, and none of them should be a string. */
odeactivate = Vdeactivate_mark;
- obuffer = Fcurrent_buffer ();
+ XSETBUFFER (obuffer, current_buffer);
+ okeymap = current_buffer->keymap;
+
sentinel = p->sentinel;
if (NILP (sentinel))
return;
restore_match_data ();
Vdeactivate_mark = odeactivate;
- if (! EQ (Fcurrent_buffer (), obuffer))
- record_asynch_buffer_change ();
+#if 0
+ if (! EQ (Fcurrent_buffer (), obuffer)
+ || ! EQ (current_buffer->keymap, okeymap))
+#endif
+ /* But do it only if the caller is actually going to read events.
+ Otherwise there's no need to make him wake up, and it could
+ cause trouble (for example it would make Fsit_for return). */
+ if (waiting_for_user_input_p == -1)
+ record_asynch_buffer_change ();
- if (waiting_for_user_input_p)
- prepare_menu_bars ();
unbind_to (count, Qnil);
}
reference. */
GCPRO2 (tail, msg);
+ /* Set this now, so that if new processes are created by sentinels
+ that we run, we get called again to handle their status changes. */
+ update_tick = process_tick;
+
for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
{
Lisp_Object symbol;
update_mode_lines++; /* in case buffers use %s in mode-line-format */
redisplay_preserve_echo_area ();
- update_tick = process_tick;
-
UNGCPRO;
}
\f
{
int fd;
- for (fd = 0; fd < max_keyboard_desc; fd++)
+ for (fd = 0; fd <= max_keyboard_desc; fd++)
if (FD_ISSET (fd, mask) && FD_ISSET (fd, &input_wait_mask)
&& !FD_ISSET (fd, &non_keyboard_wait_mask))
return 1;
#include "lisp.h"
#include "systime.h"
#include "termopts.h"
+#include "sysselect.h"
extern int frame_garbaged;
/* It's infinite. */
timeout_p = 0;
- /* This must come before stop_polling. */
- prepare_menu_bars ();
-
/* Turn off periodic alarms (in case they are in use)
because the select emulator uses alarms. */
stop_polling ();
if (XINT (read_kbd) && detect_input_pending ())
nfds = 0;
else
- nfds = select (1, &waitchannels, 0, 0, timeout_p);
+ nfds = select (1, &waitchannels, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+ timeout_p);
/* Make C-g and alarm signals set flags again */
clear_waiting_for_input ();