#if defined(BSD) || defined(STRIDE)
#include <sys/ioctl.h>
-#if !defined (O_NDELAY) && defined (HAVE_PTYS)
+#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
#include <fcntl.h>
#endif /* HAVE_PTYS and no O_NDELAY */
#endif /* BSD or STRIDE */
-#ifdef USG
-#ifdef HAVE_TERMIOS
-#include <termios.h>
-#else
-#include <termio.h>
-#endif
-#include <fcntl.h>
-#endif /* USG */
#ifdef NEED_BSDTTY
#include <bsdtty.h>
#endif
-#ifdef HPUX
-#undef TIOCGPGRP
-#endif
-
#ifdef IRIS
#include <sys/sysmacros.h> /* for "minor" */
#endif /* not IRIS */
#include "systime.h"
-
-#if defined (HPUX) && defined (HAVE_PTYS)
-#include <sys/ptyio.h>
-#endif
-
-#ifdef AIX
-#include <sys/pty.h>
-#include <unistd.h>
-#endif
-
-#ifdef SYSV_PTYS
-#include <sys/tty.h>
-#ifdef titan
-#include <sys/ttyhw.h>
-#include <sys/stream.h>
-#endif
-#include <sys/pty.h>
-#endif
-
-#ifdef XENIX
-#undef TIOCGETC /* Avoid confusing some conditionals that test this. */
-#endif
-
-#ifdef BROKEN_TIOCGETC
-#undef TIOCGETC
-#endif
+#include "systty.h"
#include "lisp.h"
#include "window.h"
#ifndef VMS
#ifndef WAITTYPE
#if !defined (BSD) && !defined (UNIPLUS) && !defined (STRIDE) && !(defined (HPUX) && !defined (NOMULTIPLEJOBS)) && !defined (HAVE_WAIT_HEADER)
-mis;tak-+;;:
#define WAITTYPE int
#define WIFSTOPPED(w) ((w&0377) == 0177)
#define WIFSIGNALED(w) ((w&0377) != 0177 && (w&~0377) == 0)
#define WIFEXITED(w) ((w&0377) == 0)
#define WRETCODE(w) (w >> 8)
#define WSTOPSIG(w) (w >> 8)
-#define WCOREDUMP(w) ((w&0200) != 0)
#define WTERMSIG(w) (w & 0377)
+#ifndef WCOREDUMP
+#define WCOREDUMP(w) ((w&0200) != 0)
+#endif
#else
#ifdef BSD4_1
#include <wait.h>
/* Compute the Lisp form of the process status, p->status, from
the numeric status that was returned by `wait'. */
+Lisp_Object status_convert ();
+
update_status (p)
struct Lisp_Process *p;
{
*symbol = XCONS (l)->car;
tem = XCONS (l)->cdr;
*code = XFASTINT (XCONS (tem)->car);
- tem = XFASTINT (XCONS (tem)->cdr);
+ tem = XCONS (tem)->cdr;
*coredump = !NILP (tem);
}
}
}
\f
#ifdef HAVE_PTYS
-static int pty_process;
/* Open an available pty, returning a file descriptor.
Return -1 on failure.
{
#ifdef PTY_NAME_SPRINTF
PTY_NAME_SPRINTF
-#else
-#ifdef HPUX
- sprintf (pty_name, "/dev/ptym/pty%c%x", c, i);
-#else
-#ifdef RTU
- sprintf (pty_name, "/dev/pty%x", i);
#else
sprintf (pty_name, "/dev/pty%c%x", c, i);
-#endif /* not RTU */
-#endif /* not HPUX */
#endif /* no PTY_NAME_SPRINTF */
+#ifdef PTY_OPEN
+ PTY_OPEN;
+#else /* no PTY_OPEN */
#ifdef IRIS
/* Unusual IRIS code */
*ptyv = open ("/dev/ptc", O_RDWR | O_NDELAY, 0);
return -1;
if (fstat (fd, &stb) < 0)
return -1;
-#else
+#else /* not IRIS */
if (stat (pty_name, &stb) < 0)
{
failed_count++;
#else
fd = open (pty_name, O_RDWR | O_NDELAY, 0);
#endif
-#endif /* IRIS */
+#endif /* not IRIS */
+#endif /* no PTY_OPEN */
if (fd >= 0)
{
this avoids a nasty yet stupid bug in rlogins */
#ifdef PTY_TTY_NAME_SPRINTF
PTY_TTY_NAME_SPRINTF
-#else
- /* TODO: In version 19, make these special cases use the macro above. */
-#ifdef HPUX
- sprintf (pty_name, "/dev/pty/tty%c%x", c, i);
-#else
-#ifdef RTU
- sprintf (pty_name, "/dev/ttyp%x", i);
-#else
-#ifdef IRIS
- sprintf (pty_name, "/dev/ttyq%d", minor (stb.st_rdev));
#else
sprintf (pty_name, "/dev/tty%c%x", c, i);
-#endif /* not IRIS */
-#endif /* not RTU */
-#endif /* not HPUX */
#endif /* no PTY_TTY_NAME_SPRINTF */
#ifndef UNIPLUS
if (access (pty_name, 6) != 0)
return Qnil;
}
-/* This is how commands for the user decode process arguments */
+/* This is how commands for the user decode process arguments. It
+ accepts a process, a process name, a buffer, a buffer name, or nil.
+ Buffers denote the first process in the buffer, and nil denotes the
+ current buffer. */
Lisp_Object
get_process (name)
DEFUN ("delete-process", Fdelete_process, Sdelete_process, 1, 1, 0,
"Delete PROCESS: kill it and forget about it immediately.\n\
-PROCESS may be a process or the name of one, or a buffer name.")
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
(proc)
register Lisp_Object proc;
{
signal -- for a process that has got a fatal signal.\n\
open -- for a network stream connection that is open.\n\
closed -- for a network stream connection that is closed.\n\
-nil -- if arg is a process name and no such process exists.")
+nil -- if arg is a process name and no such process exists.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
/* command -- for a command channel opened to Emacs by another process.\n\
external -- for an i/o channel opened to Emacs by another process.\n\ */
(proc)
{
register struct Lisp_Process *p;
register Lisp_Object status;
- proc = Fget_process (proc);
+ proc = get_process (proc);
if (NILP (proc))
return proc;
p = XPROCESS (proc);
#endif
int pty_flag = 0;
Lisp_Object current_dir;
- char **env;
extern char **environ;
- env = environ;
-
inchannel = outchannel = -1;
#ifdef HAVE_PTYS
/* First, disconnect its current controlling terminal. */
#ifdef HAVE_SETSID
setsid ();
+#ifdef TIOCSCTTY
+ /* Make the pty's terminal the controlling terminal. */
+ if (pty_flag && (ioctl (xforkin, TIOCSCTTY, 0) < 0))
+ abort ();
+#endif
#else /* not HAVE_SETSID */
#ifdef USG
/* It's very important to call setpgrp() here and no time
#if defined (BSD) || defined (UNIPLUS) || defined (HPUX)
sigsetmask (SIGEMPTYMASK);
#else /* ordinary USG */
+#if 0
signal (SIGCHLD, sigchld);
+#endif
#endif /* ordinary USG */
#endif /* not BSD4_1 */
#endif /* SIGCHLD */
child_setup_tty (xforkout);
child_setup (xforkin, xforkout, xforkout,
- new_argv, env, 1, current_dir);
+ new_argv, 1, current_dir);
}
environ = save_environ;
}
}
}
}
+ else
+ useconds = 0;
if (! NILP (timeout))
{
seconds = 0;
}
+ if (NILP (proc))
+ XFASTINT (proc) = 0;
+
return
- (wait_reading_process_input (seconds, useconds,
- (NILP (proc)
- ? XPROCESS (get_process (proc)) : 0), 0)
+ (wait_reading_process_input (seconds, useconds, proc, 0)
? Qt : Qnil);
}
zero for no limit, or
-1 means gobble data immediately available but don't wait for any.
- read_kbd is:
+ read_kbd is a lisp value:
0 to ignore keyboard input, or
1 to return when input is available, or
-1 means caller will actually read the input, so don't throw to
the quit handler, or
- a pointer to a struct Lisp_Process, meaning wait until something
- arrives from that process. The return value is true iff we read
- some input from that process.
+ a process object, meaning wait until something arrives from that
+ process. The return value is true iff we read some input from
+ that process.
do_display != 0 means redisplay should be done to show subprocess
output that arrives.
Otherwise, return true iff we recieved input from any process. */
wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
- int time_limit, microsecs, read_kbd, do_display;
+ int time_limit, microsecs;
+ Lisp_Object read_kbd;
+ int do_display;
{
register int channel, nfds, m;
static SELECT_TYPE Available;
FD_ZERO (&Available);
- /* Detect when read_kbd is really the address of a Lisp_Process. */
- if (read_kbd > 10 || read_kbd < -1)
+ /* If read_kbd is a process to watch, set wait_proc and wait_channel
+ accordingly. */
+ if (XTYPE (read_kbd) == Lisp_Process)
{
- wait_proc = (struct Lisp_Process *) read_kbd;
+ wait_proc = XPROCESS (read_kbd);
wait_channel = XFASTINT (wait_proc->infd);
- read_kbd = 0;
+ XFASTINT (read_kbd) = 0;
}
- waiting_for_user_input_p = read_kbd;
+ waiting_for_user_input_p = XINT (read_kbd);
/* Since we may need to wait several times,
compute the absolute time to return at. */
EMACS_ADD_TIME (end_time, end_time, timeout);
}
- /* Turn off periodic alarms (in case they are in use)
- because the select emulator uses alarms. */
- stop_polling ();
-
while (1)
{
/* 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. */
- if (read_kbd >= 0)
+ if (XINT (read_kbd) >= 0)
QUIT;
/* If status of something has changed, and no input is available,
/* Cause C-g and alarm signals to take immediate action,
and cause input available signals to zero out timeout */
- if (read_kbd < 0)
+ if (XINT (read_kbd) < 0)
set_waiting_for_input (&timeout);
/* Wait till there is something to do */
Available = input_wait_mask;
- if (!read_kbd)
+ if (! XINT (read_kbd))
FD_CLR (0, &Available);
- if (read_kbd && detect_input_pending ())
+ /* If frame size has changed or the window is newly mapped,
+ redisplay now, before we start to wait. There is a race
+ condition here; if a SIGIO arrives between now and the select
+ and indicates that a frame is trashed, we lose. */
+ if (frame_garbaged)
+ redisplay_preserve_echo_area ();
+
+ if (XINT (read_kbd) && detect_input_pending ())
nfds = 0;
else
nfds = select (MAXDESC, &Available, 0, 0, &timeout);
/* If we woke up due to SIGWINCH, actually change size now. */
do_pending_window_change ();
- if (time_limit && nfds == 0) /* timeout elapsed */
+ if (time_limit && nfds == 0) /* timeout elapsed */
break;
if (nfds < 0)
{
if (xerrno == EINTR)
FD_ZERO (&Available);
+#ifdef __ultrix__
+ /* Ultrix select seems to return ENOMEM when it is interrupted.
+ Treat it just like EINTR. Bleah. -JimB */
+ else if (xerrno == ENOMEM)
+ FD_ZERO (&Available);
+#endif
#ifdef ALLIANT
/* This happens for no known reason on ALLIANT.
I am guessing that this is the right response. -- RMS. */
So, SIGHUP is ignored (see def of PTY_TTY_NAME_SPRINTF
in m-ibmrt-aix.h), and here we just ignore the select error.
Cleanup occurs c/o status_notify after SIGCLD. */
- FD_ZERO (&Available); /* Cannot depend on values returned */
+ FD_ZERO (&Available); /* Cannot depend on values returned */
#else
abort ();
#endif
/* If there is any, return immediately
to give it higher priority than subprocesses */
- if (read_kbd && detect_input_pending ())
+ if (XINT (read_kbd) && detect_input_pending ())
break;
#ifdef SIGIO
but select says there is input. */
/*
- if (read_kbd && interrupt_input && (Available & fileno (stdin)))
- */
- if (read_kbd && interrupt_input && (FD_ISSET (fileno (stdin), &Available)))
+ if (XINT (read_kbd) && interrupt_input && (Available & fileno (stdin)))
+ */
+ if (XINT (read_kbd) && interrupt_input && (FD_ISSET (fileno (stdin), &Available)))
kill (0, SIGIO);
#endif
Available &= ~(ChannelMask (comm_server));
create_commchan ();
}
-#endif vipc
+#endif /* vipc */
if (! wait_proc)
got_some_input |= nfds > 0;
/* If checking input just got us a size-change event from X,
obey it now if we should. */
- if (read_kbd)
+ if (XINT (read_kbd))
do_pending_window_change ();
- /* If screen size has changed, redisplay now
- for either sit-for or keyboard input. */
- if (read_kbd && screen_garbaged)
- redisplay_preserve_echo_area ();
-
/* Check for data from a process or a command channel */
for (channel = FIRST_PROC_DESC; channel < MAXDESC; channel++)
{
}
continue;
}
-#endif /* vipc */
+#endif /* vipc */
/* Read data from the process, starting with our
buffered-ahead character if we have one. */
subprocess termination and SIGCHLD. */
else if (nread == 0 && !NETCONN_P (proc))
;
-#endif /* O_NDELAY */
-#endif /* O_NONBLOCK */
-#endif /* EWOULDBLOCK */
+#endif /* O_NDELAY */
+#endif /* O_NONBLOCK */
+#endif /* EWOULDBLOCK */
#ifdef HAVE_PTYS
/* On some OSs with ptys, when the process on one end of
a pty exits, the other end gets an error reading with
get a SIGCHLD). */
else if (nread == -1 && errno == EIO)
;
-#endif /* HAVE_PTYS */
-/* If we can detect process termination, don't consider the process
- gone just because its pipe is closed. */
+#endif /* HAVE_PTYS */
+ /* If we can detect process termination, don't consider the process
+ gone just because its pipe is closed. */
#ifdef SIGCHLD
else if (nread == 0 && !NETCONN_P (proc))
;
= Fcons (Qexit, Fcons (make_number (256), Qnil));
}
}
- } /* end for each file descriptor */
- } /* end while exit conditions not met */
+ } /* end for each file descriptor */
+ } /* end while exit conditions not met */
- /* Resume periodic signals to poll for input, if necessary. */
- start_polling ();
+ /* 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. */
+ if (XINT (read_kbd) >= 0)
+ {
+ /* Prevent input_pending from remaining set if we quit. */
+ clear_input_pending ();
+ QUIT;
+ }
return got_some_input;
}
/* Don't send more than 500 bytes at a time. */
if (this > 500)
this = 500;
- old_sigpipe = signal (SIGPIPE, send_process_trap);
+ old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
rv = write (XFASTINT (XPROCESS (proc)->outfd), buf, this);
signal (SIGPIPE, old_sigpipe);
if (rv < 0)
/* Allow input from processes between bursts of sending.
Otherwise things may get stopped up. */
if (len > 0)
- wait_reading_process_input (-1, 0, 0, 0);
+ {
+ Lisp_Object zero;
+
+ XFASTINT (zero) = 0;
+ wait_reading_process_input (-1, 0, zero, 0);
+ }
}
#endif
else
DEFUN ("process-send-region", Fprocess_send_region, Sprocess_send_region,
3, 3, 0,
"Send current contents of region as input to PROCESS.\n\
-PROCESS may be a process name or an actual process.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
Called from program, takes three arguments, PROCESS, START and END.\n\
If the region is more than 500 characters long,\n\
it is sent in several bunches. This may happen even for shorter regions.\n\
DEFUN ("process-send-string", Fprocess_send_string, Sprocess_send_string,
2, 2, 0,
"Send PROCESS the contents of STRING as input.\n\
-PROCESS may be a process name or an actual process.\n\
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.\n\
If STRING is more than 500 characters long,\n\
it is sent in several bunches. This may happen even for shorter strings.\n\
Output from processes can arrive in between bunches.")
If NOMSG is zero, insert signal-announcements into process's buffers
right away. */
+static void
process_send_signal (process, signo, current_group, nomsg)
Lisp_Object process;
int signo;
if (NILP (p->pty_flag))
current_group = Qnil;
-#ifdef TIOCGPGRP /* Not sure about this! (fnf) */
/* If we are using pgrps, get a pgrp number and make it negative. */
if (!NILP (current_group))
{
case SIGINT:
ioctl (XFASTINT (p->infd), TIOCGETC, &c);
send_process (proc, &c.t_intrc, 1);
- return Qnil;
+ return;
case SIGQUIT:
ioctl (XFASTINT (p->infd), TIOCGETC, &c);
send_process (proc, &c.t_quitc, 1);
- return Qnil;
+ return;
+#ifdef SIGTSTP
case SIGTSTP:
ioctl (XFASTINT (p->infd), TIOCGLTC, &lc);
send_process (proc, &lc.t_suspc, 1);
- return Qnil;
+ return;
+#endif /* SIGTSTP */
}
-#endif /* have TIOCGLTC and have TIOCGETC */
+#endif /* ! defined (TIOCGLTC) && defined (TIOCGETC) */
/* It is possible that the following code would work
on other kinds of USG systems, not just on the IRIS.
This should be tried in Emacs 19. */
-#if defined (IRIS) && defined (HAVE_SETSID) /* Check for Irix, not older
- systems. */
+#if defined (USG)
struct termio t;
switch (signo)
{
case SIGINT:
ioctl (XFASTINT (p->infd), TCGETA, &t);
send_process (proc, &t.c_cc[VINTR], 1);
- return Qnil;
+ return;
case SIGQUIT:
ioctl (XFASTINT (p->infd), TCGETA, &t);
send_process (proc, &t.c_cc[VQUIT], 1);
- return Qnil;
+ return;
+#ifdef SIGTSTP
case SIGTSTP:
ioctl (XFASTINT (p->infd), TCGETA, &t);
send_process (proc, &t.c_cc[VSWTCH], 1);
- return Qnil;
+ return;
+#endif
}
-#endif /* IRIS and HAVE_SETSID */
+#endif /* ! defined (USG) */
+#ifdef TIOCGPGRP
/* Get the pgrp using the tty itself, if we have that.
Otherwise, use the pty to get the pgrp.
On pfa systems, saka@pfu.fujitsu.co.JP writes:
"TICGPGRP symbol defined in sys/ioctl.h at E50.
- But, TIOCGPGRP donot work on E50 ;-P work fine on E60"
+ But, TIOCGPGRP does not work on E50 ;-P works fine on E60"
His patch indicates that if TIOCGPGRP returns an error, then
we should just assume that p->pid is also the process group id. */
{
#ifdef pfa
if (err == -1)
gid = - XFASTINT (p->pid);
-#endif
+#endif /* ! defined (pfa) */
}
if (gid == -1)
no_pgrp = 1;
else
gid = - gid;
+#else /* ! defined (TIOCGPGRP ) */
+ /* Can't select pgrps on this system, so we know that
+ the child itself heads the pgrp. */
+ gid = - XFASTINT (p->pid);
+#endif /* ! defined (TIOCGPGRP ) */
}
else
gid = - XFASTINT (p->pid);
-#else /* not using pgrps */
- /* Can't select pgrps on this system, so we know that
- the child itself heads the pgrp. */
- gid = - XFASTINT (p->pid);
-#endif /* not using pgrps */
switch (signo)
{
if (!nomsg)
status_notify ();
break;
-#endif
+#endif /* ! defined (SIGCONT) */
case SIGINT:
#ifdef VMS
send_process (proc, "\003", 1); /* ^C */
gid = - XFASTINT (p->pid);
kill (gid, signo);
}
-#else /* no TIOCSIGSEND */
+#else /* ! defined (TIOCSIGSEND) */
EMACS_KILLPG (-gid, signo);
-#endif
+#endif /* ! defined (TIOCSIGSEND) */
}
DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0,
"Interrupt process PROCESS. May be process or name of one.\n\
+PROCESS may be a process, a buffer, or the name of a process or buffer.\n\
Nil or no arg means current buffer's process.\n\
Second arg CURRENT-GROUP non-nil means send signal to\n\
the current process-group of the process's controlling terminal\n\
DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
"Make PROCESS see end-of-file in its input.\n\
Eof comes after any text already sent to it.\n\
-nil or no arg means current buffer's process.")
+PROCESS may be a process, a buffer, the name of a process or buffer, or\n\
+nil, indicating the current buffer's process.")
(process)
Lisp_Object process;
{
/* If process has terminated, stop waiting for its output. */
if (WIFSIGNALED (w) || WIFEXITED (w))
- if (p->infd)
- FD_CLR (p->infd, &input_wait_mask);
+ if (XFASTINT (p->infd))
+ FD_CLR (XFASTINT (p->infd), &input_wait_mask);
}
/* There was no asynchronous process found for that id. Check
#endif
syms_of_process ()
{
-#ifdef HAVE_PTYS
- pty_process = intern ("pty");
-#endif
#ifdef HAVE_SOCKETS
stream_process = intern ("stream");
#endif
#include "systime.h"
#include "termopts.h"
-extern int screen_garbaged;
+extern int frame_garbaged;
/* As described above, except assuming that there are no subprocesses:
zero for no limit, or
-1 means gobble data immediately available but don't wait for any.
- read_kbd is:
+ read_kbd is a Lisp_Object:
0 to ignore keyboard input, or
1 to return when input is available, or
-1 means caller will actually read the input, so don't throw to
do_display != 0 means redisplay should be done to show subprocess
output that arrives. This version of the function ignores it.
- If read_kbd is a pointer to a struct Lisp_Process, then the
- function returns true iff we received input from that process
- before the timeout elapsed.
- Otherwise, return true iff we recieved input from any process. */
+ Return true iff we recieved input from any process. */
int
wait_reading_process_input (time_limit, microsecs, read_kbd, do_display)
- int time_limit, microsecs, read_kbd, do_display;
+ int time_limit, microsecs;
+ Lisp_Object read_kbd;
+ int do_display;
{
EMACS_TIME end_time, timeout, *timeout_p;
int waitchannels;
{
int nfds;
- waitchannels = read_kbd ? 1 : 0;
+ waitchannels = XINT (read_kbd) ? 1 : 0;
/* 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. */
- if (read_kbd >= 0)
+ if (XINT (read_kbd) >= 0)
QUIT;
if (timeout_p)
/* Cause C-g and alarm signals to take immediate action,
and cause input available signals to zero out timeout. */
- if (read_kbd < 0)
+ if (XINT (read_kbd) < 0)
set_waiting_for_input (&timeout);
- /* If a screen has been newly mapped and needs updating,
+ /* If a frame has been newly mapped and needs updating,
reprocess its display stuff. */
- if (screen_garbaged)
+ if (frame_garbaged)
redisplay_preserve_echo_area ();
- if (read_kbd && detect_input_pending ())
+ if (XINT (read_kbd) && detect_input_pending ())
nfds = 0;
else
nfds = select (1, &waitchannels, 0, 0, timeout_p);
/* System sometimes fails to deliver SIGIO. */
kill (getpid (), SIGIO);
#endif
- if (read_kbd && interrupt_input && (waitchannels & 1))
+ if (XINT (read_kbd) && interrupt_input && (waitchannels & 1))
kill (0, SIGIO);
/* If we have timed out (nfds == 0) or found some input (nfds > 0),