#include <unistd.h>
#endif
+#ifdef WINDOWSNT
+#include <stdlib.h>
+#include <fcntl.h>
+#endif /* not WINDOWSNT */
+
#ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */
#include <sys/socket.h>
#include <netdb.h>
#ifdef HAVE_SOCKETS
static Lisp_Object stream_process;
-#define NETCONN_P(p) (XGCTYPE (XPROCESS (p)->childp) == Lisp_String)
+#define NETCONN_P(p) (GC_STRINGP (XPROCESS (p)->childp))
#else
#define NETCONN_P(p) 0
#endif /* HAVE_SOCKETS */
#ifndef SYS_SIGLIST_DECLARED
#ifndef VMS
#ifndef BSD4_1
+#ifndef WINDOWSNT
#ifndef LINUX
extern char *sys_siglist[];
#endif /* not LINUX */
"exceeded CPU time limit",
"exceeded file size limit"
};
+#endif /* not WINDOWSNT */
#endif
#endif /* VMS */
#endif /* ! SYS_SIGLIST_DECLARED */
#define POLL_FOR_INPUT
#endif
-/* Mask of bits indicating the descriptors that we wait for input on */
+/* Mask of bits indicating the descriptors that we wait for input on. */
static SELECT_TYPE input_wait_mask;
+/* Mask that excludes keyboard input descriptor (s). */
+
+static SELECT_TYPE non_keyboard_wait_mask;
+
/* The largest descriptor currently in use for a process object. */
static int max_process_desc;
-/* Descriptor to use for keyboard input. */
-static int keyboard_descriptor;
+/* The largest descriptor currently in use for keyboard input. */
+static int max_keyboard_desc;
/* Nonzero means delete a process right away if it exits. */
static int delete_exited_processes;
output from the process is to read at least one char.
Always -1 on systems that support FIONREAD. */
-static int proc_buffered_char[MAXDESC];
+/* Don't make static; need to access externally. */
+int proc_buffered_char[MAXDESC];
static Lisp_Object get_process ();
if (code < NSIG)
{
#ifndef VMS
- signame = sys_siglist[code];
+ /* Cast to suppress warning if the table has const char *. */
+ signame = (char *) sys_siglist[code];
#else
signame = sys_errlist[code];
#endif
make_process (name)
Lisp_Object name;
{
+ struct Lisp_Vector *vec;
register Lisp_Object val, tem, name1;
register struct Lisp_Process *p;
char suffix[10];
register int i;
- /* size of process structure includes the vector header,
- so deduct for that. But struct Lisp_Vector includes the first
- element, thus deducts too much, so add it back. */
- val = Fmake_vector (make_number ((sizeof (struct Lisp_Process)
- - sizeof (struct Lisp_Vector)
- + sizeof (Lisp_Object))
- / sizeof (Lisp_Object)),
- Qnil);
- XSETTYPE (val, Lisp_Process);
-
- p = XPROCESS (val);
+ vec = allocate_vectorlike ((EMACS_INT) VECSIZE (struct Lisp_Process));
+ for (i = 0; i < VECSIZE (struct Lisp_Process); i++)
+ vec->contents[i] = Qnil;
+ vec->size = VECSIZE (struct Lisp_Process);
+ p = (struct Lisp_Process *)vec;
+
XSETINT (p->infd, -1);
XSETINT (p->outfd, -1);
- XFASTINT (p->pid) = 0;
- XFASTINT (p->tick) = 0;
- XFASTINT (p->update_tick) = 0;
+ XSETFASTINT (p->pid, 0);
+ XSETFASTINT (p->tick, 0);
+ XSETFASTINT (p->update_tick, 0);
p->raw_status_low = Qnil;
p->raw_status_high = Qnil;
p->status = Qrun;
}
name = name1;
p->name = name;
+ XSETPROCESS (val, p);
Vprocess_alist = Fcons (Fcons (name, val), Vprocess_alist);
return val;
}
{
CHECK_PROCESS (proc, 0);
if (EQ (filter, Qt))
- FD_CLR (XINT (XPROCESS (proc)->infd), &input_wait_mask);
+ {
+ FD_CLR (XINT (XPROCESS (proc)->infd), &input_wait_mask);
+ FD_CLR (XINT (XPROCESS (proc)->infd), &non_keyboard_wait_mask);
+ }
else if (EQ (XPROCESS (proc)->filter, Qt))
- FD_SET (XINT (XPROCESS (proc)->infd), &input_wait_mask);
+ {
+ FD_SET (XINT (XPROCESS (proc)->infd), &input_wait_mask);
+ FD_SET (XINT (XPROCESS (proc)->infd), &non_keyboard_wait_mask);
+ }
XPROCESS (proc)->filter = filter;
return filter;
}
register int state;
char tembuf[80];
- XFASTINT (minspace) = 1;
+ XSETFASTINT (minspace, 1);
set_buffer_internal (XBUFFER (Vstandard_output));
Fbuffer_disable_undo (Vstandard_output);
current_buffer->truncate_lines = Qt;
write_string ("\
-Proc Status Buffer Command\n\
----- ------ ------ -------\n", -1);
+Proc Status Buffer Tty Command\n\
+---- ------ ------ --- -------\n", -1);
for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
{
Findent_to (make_number (37), minspace);
+ if (STRINGP (p->tty_name))
+ Finsert (1, &p->tty_name);
+ else
+ insert_string ("(none)");
+
+ Findent_to (make_number (49), minspace);
+
if (NETCONN_P (proc))
{
sprintf (tembuf, "(network stream connection to %s)\n",
new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
/* If program file name is not absolute, search our path for it */
- if (XSTRING (program)->data[0] != '/')
+ 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;
}
#else /* not SKTPAIR */
{
+#ifdef WINDOWSNT
+ pipe_with_inherited_out (sv);
+ inchannel = sv[0];
+ forkout = sv[1];
+
+ pipe_with_inherited_in (sv);
+ forkin = sv[0];
+ outchannel = sv[1];
+#else /* not WINDOWSNT */
pipe (sv);
inchannel = sv[0];
forkout = sv[1];
pipe (sv);
outchannel = sv[1];
forkin = sv[0];
+#endif /* not WINDOWSNT */
}
#endif /* not SKTPAIR */
if (forkin < 0)
XPROCESS (process)->subtty = Qnil;
else
- XFASTINT (XPROCESS (process)->subtty) = forkin;
+ XSETFASTINT (XPROCESS (process)->subtty, forkin);
XPROCESS (process)->pty_flag = (pty_flag ? Qt : Qnil);
XPROCESS (process)->status = Qrun;
#endif /* SIGCHLD */
FD_SET (inchannel, &input_wait_mask);
+ FD_SET (inchannel, &non_keyboard_wait_mask);
if (inchannel > max_process_desc)
max_process_desc = inchannel;
Protect it from permanent change. */
char **save_environ = environ;
+#ifndef WINDOWSNT
pid = vfork ();
if (pid == 0)
+#endif /* not WINDOWSNT */
{
int xforkin = forkin;
int xforkout = forkout;
/* In order to get a controlling terminal on some versions
of BSD, it is necessary to put the process in pgrp 0
before it opens the terminal. */
+#ifdef OSF1
+ setpgid (0, 0);
+#else
setpgrp (0, 0);
+#endif
#endif
}
#endif /* TIOCNOTTY */
if (pty_flag)
child_setup_tty (xforkout);
+#ifdef WINDOWSNT
+ pid = child_setup (xforkin, xforkout, xforkout,
+ new_argv, 1, current_dir);
+#else /* not WINDOWSNT */
child_setup (xforkin, xforkout, xforkout,
new_argv, 1, current_dir);
+#endif /* not WINDOWSNT */
}
environ = save_environ;
}
report_file_error ("Doing vfork", Qnil);
}
- XFASTINT (XPROCESS (process)->pid) = pid;
+ XSETFASTINT (XPROCESS (process)->pid, pid);
+
+#ifdef WINDOWSNT
+ register_child (pid, inchannel);
+#endif /* WINDOWSNT */
/* If the subfork execv fails, and it exits,
this close hangs. I don't know why.
XSETINT (XPROCESS (proc)->outfd, outch);
XPROCESS (proc)->status = Qrun;
FD_SET (inch, &input_wait_mask);
+ FD_SET (inch, &non_keyboard_wait_mask);
if (inch > max_process_desc)
max_process_desc = inch;
XSETINT (p->outfd, -1);
chan_process[inchannel] = Qnil;
FD_CLR (inchannel, &input_wait_mask);
+ FD_CLR (inchannel, &non_keyboard_wait_mask);
if (inchannel == max_process_desc)
{
int i;
close_process_descs ()
{
+#ifndef WINDOWSNT
int i;
for (i = 0; i < MAXDESC; i++)
{
close (out);
}
}
+#endif
}
\f
DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output,
}
if (NILP (proc))
- XFASTINT (proc) = 0;
+ XSETFASTINT (proc, 0);
return
(wait_reading_process_input (seconds, useconds, proc, 0)
{
wait_proc = XPROCESS (read_kbd);
wait_channel = XINT (wait_proc->infd);
- XFASTINT (read_kbd) = 0;
+ XSETFASTINT (read_kbd, 0);
}
/* If waiting for non-nil in a cell, record where. */
if (CONSP (read_kbd))
{
wait_for_cell = &XCONS (read_kbd)->car;
- XFASTINT (read_kbd) = 0;
+ XSETFASTINT (read_kbd, 0);
}
waiting_for_user_input_p = XINT (read_kbd);
/* Wait till there is something to do */
- Available = input_wait_mask;
if (! XINT (read_kbd) && wait_for_cell == 0)
- FD_CLR (keyboard_descriptor, &Available);
+ Available = non_keyboard_wait_mask;
+ else
+ Available = input_wait_mask;
/* If frame size has changed or the window is newly mapped,
redisplay now, before we start to wait. There is a race
error("select error: %s", strerror (xerrno));
}
#if defined(sun) && !defined(USG5_4)
- else if (nfds > 0 && FD_ISSET (keyboard_descriptor, &Available)
+ else if (nfds > 0 && keyboard_bit_set (&Available)
&& interrupt_input)
/* System sometimes fails to deliver SIGIO.
but select says there is input. */
if (XINT (read_kbd) && interrupt_input
- && (FD_ISSET (keyboard_descriptor, &Available)))
+ && (keyboard_bit_set (&Available)))
kill (0, SIGIO);
#endif
/* Check for data from a process. */
/* Really FIRST_PROC_DESC should be 0 on Unix,
but this is safer in the short run. */
- for (channel = keyboard_descriptor == 0 ? FIRST_PROC_DESC : 0;
- channel <= max_process_desc; channel++)
+ for (channel = 0; channel <= max_process_desc; channel++)
{
- if (FD_ISSET (channel, &Available))
+ if (FD_ISSET (channel, &Available)
+ && FD_ISSET (channel, &non_keyboard_wait_mask))
{
int nread;
#else /* not VMS */
if (proc_buffered_char[channel] < 0)
+#ifdef WINDOWSNT
+ nchars = read_child_output (channel, chars, sizeof (chars));
+#else
nchars = read (channel, chars, sizeof chars);
+#endif
else
{
chars[0] = proc_buffered_char[channel];
proc_buffered_char[channel] = -1;
+#ifdef WINDOWSNT
+ nchars = read_child_output (channel, chars + 1, sizeof (chars) - 1);
+#else
nchars = read (channel, chars + 1, sizeof chars - 1);
+#endif
if (nchars < 0)
nchars = 1;
else
specbind (Qinhibit_quit, Qt);
specbind (Qlast_nonmenu_event, Qt);
+ running_asynch_code = 1;
internal_condition_case_1 (read_process_output_call,
Fcons (outstream,
Fcons (proc,
- Fcons (make_string (chars, nchars),
+ Fcons (make_string (chars,
+ nchars),
Qnil))),
!NILP (Vdebug_on_error) ? Qnil : Qerror,
read_process_output_error_handler);
+ running_asynch_code = 0;
+ restore_match_data ();
/* Handling the process output should not deactivate the mark. */
Vdeactivate_mark = odeactivate;
Fset_buffer (p->buffer);
opoint = point;
old_read_only = current_buffer->read_only;
- XFASTINT (old_begv) = BEGV;
- XFASTINT (old_zv) = ZV;
+ XSETFASTINT (old_begv, BEGV);
+ XSETFASTINT (old_zv, ZV);
current_buffer->read_only = Qnil;
/* Insert after old_begv, but before old_zv. */
if (point < XFASTINT (old_begv))
- XFASTINT (old_begv) += nchars;
+ XSETFASTINT (old_begv, XFASTINT (old_begv) + nchars);
if (point <= XFASTINT (old_zv))
- XFASTINT (old_zv) += nchars;
+ XSETFASTINT (old_zv, XFASTINT (old_zv) + nchars);
/* Insert before markers in case we are inserting where
the buffer's mark is, and the user's next command is Meta-y. */
else if (STRINGP (object))
offset = buf - (char *) XSTRING (object)->data;
- XFASTINT (zero) = 0;
+ XSETFASTINT (zero, 0);
wait_reading_process_input (1, 0, zero, 0);
if (BUFFERP (object))
{
CHECK_NUMBER (pid, 0);
CHECK_NUMBER (sig, 1);
+#ifdef WINDOWSNT
+ /* Only works for kill-type signals */
+ return make_number (win32_kill_process (XINT (pid), XINT (sig)));
+#else
return make_number (kill (XINT (pid), XINT (sig)));
+#endif
}
DEFUN ("process-send-eof", Fprocess_send_eof, Sprocess_send_eof, 0, 1, 0,
{
Lisp_Object tail, proc;
- for (tail = Vprocess_alist; XGCTYPE (tail) == Lisp_Cons;
- tail = XCONS (tail)->cdr)
+ for (tail = Vprocess_alist; GC_CONSP (tail); tail = XCONS (tail)->cdr)
{
proc = XCONS (XCONS (tail)->car)->cdr;
- if (XGCTYPE (proc) == Lisp_Process
+ if (GC_PROCESSP (proc)
&& (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer)))
{
if (NETCONN_P (proc))
if (p != 0)
{
union { int i; WAITTYPE wt; } u;
+ int clear_desc_flag = 0;
XSETINT (p->tick, ++process_tick);
u.wt = w;
- XFASTINT (p->raw_status_low) = u.i & 0xffff;
- XFASTINT (p->raw_status_high) = u.i >> 16;
+ XSETFASTINT (p->raw_status_low, u.i & 0xffff);
+ XSETFASTINT (p->raw_status_high, u.i >> 16);
/* If process has terminated, stop waiting for its output. */
- if (WIFSIGNALED (w) || WIFEXITED (w))
- if (XINT (p->infd) >= 0)
+ if ((WIFSIGNALED (w) || WIFEXITED (w))
+ && XINT (p->infd) >= 0)
+ clear_desc_flag = 1;
+
+ /* We use clear_desc_flag to avoid a compiler bug in Microsoft C. */
+ if (clear_desc_flag)
+ {
FD_CLR (XINT (p->infd), &input_wait_mask);
+ FD_CLR (XINT (p->infd), &non_keyboard_wait_mask);
+ }
/* Tell wait_reading_process_input that it needs to wake up and
look around. */
if (code < NSIG)
{
#ifndef VMS
- signame = sys_siglist[code];
+ /* Suppress warning if the table has const char *. */
+ signame = (char *) sys_siglist[code];
#else
signame = sys_errlist[code];
#endif
get another signal.
Otherwise (on systems that have WNOHANG), loop around
to use up all the processes that have something to tell us. */
-#if defined (USG) && ! (defined (HPUX) && defined (WNOHANG))
+#if defined (USG) && ! (defined (HPUX) && defined (WNOHANG)) || defined (WINDOWSNT)
#ifdef USG
signal (signo, sigchld_handler);
#endif
specbind (Qinhibit_quit, Qt);
specbind (Qlast_nonmenu_event, Qt);
+ running_asynch_code = 1;
internal_condition_case_1 (read_process_output_call,
Fcons (sentinel,
Fcons (proc, Fcons (reason, Qnil))),
!NILP (Vdebug_on_error) ? Qnil : Qerror,
exec_sentinel_error_handler);
+ running_asynch_code = 0;
+ restore_match_data ();
Vdeactivate_mark = odeactivate;
if (! EQ (Fcurrent_buffer (), obuffer))
UNGCPRO;
}
\f
+/* The first time this is called, assume keyboard input comes from DESC
+ instead of from where we used to expect it.
+ Subsequent calls mean assume input keyboard can come from DESC
+ in addition to other places. */
+
+static int add_keyboard_wait_descriptor_called_flag;
+
+void
+add_keyboard_wait_descriptor (desc)
+ int desc;
+{
+ if (! add_keyboard_wait_descriptor_called_flag)
+ FD_CLR (0, &input_wait_mask);
+ add_keyboard_wait_descriptor_called_flag = 1;
+ FD_SET (desc, &input_wait_mask);
+ if (desc > max_keyboard_desc)
+ max_keyboard_desc = desc;
+}
+
+/* From now on, do not expect DESC to give keyboard input. */
+
+void
+delete_keyboard_wait_descriptor (desc)
+ int desc;
+{
+ int fd;
+ int lim = max_keyboard_desc;
+
+ FD_CLR (desc, &input_wait_mask);
+
+ if (desc == max_keyboard_desc)
+ for (fd = 0; fd < lim; fd++)
+ if (FD_ISSET (fd, &input_wait_mask)
+ && !FD_ISSET (fd, &non_keyboard_wait_mask))
+ max_keyboard_desc = fd;
+}
+
+/* Return nonzero if *MASK has a bit set
+ that corresponds to one of the keyboard input descriptors. */
+
+int
+keyboard_bit_set (mask)
+ SELECT_TYPE *mask;
+{
+ int 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;
+
+ return 0;
+}
+\f
init_process ()
{
register int i;
#endif
FD_ZERO (&input_wait_mask);
+ FD_ZERO (&non_keyboard_wait_mask);
max_process_desc = 0;
- keyboard_descriptor = 0;
- FD_SET (keyboard_descriptor, &input_wait_mask);
+ FD_SET (0, &input_wait_mask);
Vprocess_alist = Qnil;
for (i = 0; i < MAXDESC; i++)
}
}
-/* From now on, assume keyboard input comes from descriptor DESC. */
-
-void
-change_keyboard_wait_descriptor (desc)
- int desc;
-{
- FD_CLR (keyboard_descriptor, &input_wait_mask);
- keyboard_descriptor = desc;
- FD_SET (keyboard_descriptor, &input_wait_mask);
-}
-
syms_of_process ()
{
#ifdef HAVE_SOCKETS