#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. */
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++)
{
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;
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;
}
{
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. */
FD_ZERO (&Available);
}
else
- nfds = select (MAXDESC, &Available, 0, 0, &timeout);
+ nfds = select (MAXDESC, &Available, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
+ &timeout);
xerrno = errno;
/* Handling the process output should not deactivate the mark. */
Vdeactivate_mark = odeactivate;
+#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))
- record_asynch_buffer_change ();
-
- if (waiting_for_user_input_p)
- prepare_menu_bars ();
+#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);
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))
restore_match_data ();
Vdeactivate_mark = odeactivate;
+#if 0
if (! EQ (Fcurrent_buffer (), obuffer)
|| ! EQ (current_buffer->keymap, okeymap))
- record_asynch_buffer_change ();
+#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);
}
register Lisp_Object proc, buffer;
Lisp_Object tail, msg;
struct gcpro gcpro1, gcpro2;
- Lisp_Object old_process_alist;
tail = Qnil;
msg = Qnil;
reference. */
GCPRO2 (tail, msg);
- do
+ /* 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))
{
- old_process_alist = Vprocess_alist;
- for (tail = Vprocess_alist; !NILP (tail); tail = Fcdr (tail))
+ Lisp_Object symbol;
+ register struct Lisp_Process *p;
+
+ proc = Fcdr (Fcar (tail));
+ p = XPROCESS (proc);
+
+ if (XINT (p->tick) != XINT (p->update_tick))
{
- Lisp_Object symbol;
- register struct Lisp_Process *p;
+ XSETINT (p->update_tick, XINT (p->tick));
- proc = Fcdr (Fcar (tail));
- p = XPROCESS (proc);
+ /* If process is still active, read any output that remains. */
+ if (XINT (p->infd) >= 0)
+ while (! EQ (p->filter, Qt)
+ && read_process_output (proc, XINT (p->infd)) > 0);
- if (XINT (p->tick) != XINT (p->update_tick))
- {
- XSETINT (p->update_tick, XINT (p->tick));
+ buffer = p->buffer;
- /* If process is still active, read any output that remains. */
- if (XINT (p->infd) >= 0)
- while (! EQ (p->filter, Qt)
- && read_process_output (proc, XINT (p->infd)) > 0);
+ /* Get the text to use for the message. */
+ if (!NILP (p->raw_status_low))
+ update_status (p);
+ msg = status_message (p->status);
- buffer = p->buffer;
+ /* If process is terminated, deactivate it or delete it. */
+ symbol = p->status;
+ if (CONSP (p->status))
+ symbol = XCONS (p->status)->car;
- /* Get the text to use for the message. */
- if (!NILP (p->raw_status_low))
- update_status (p);
- msg = status_message (p->status);
+ if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
+ || EQ (symbol, Qclosed))
+ {
+ if (delete_exited_processes)
+ remove_process (proc);
+ else
+ deactivate_process (proc);
+ }
- /* If process is terminated, deactivate it or delete it. */
- symbol = p->status;
- if (CONSP (p->status))
- symbol = XCONS (p->status)->car;
+ /* Now output the message suitably. */
+ if (!NILP (p->sentinel))
+ exec_sentinel (proc, msg);
+ /* Don't bother with a message in the buffer
+ when a process becomes runnable. */
+ else if (!EQ (symbol, Qrun) && !NILP (buffer))
+ {
+ Lisp_Object ro, tem;
+ struct buffer *old = current_buffer;
+ int opoint;
- if (EQ (symbol, Qsignal) || EQ (symbol, Qexit)
- || EQ (symbol, Qclosed))
- {
- if (delete_exited_processes)
- remove_process (proc);
- else
- deactivate_process (proc);
- }
+ ro = XBUFFER (buffer)->read_only;
- /* Now output the message suitably. */
- if (!NILP (p->sentinel))
- exec_sentinel (proc, msg);
- /* Don't bother with a message in the buffer
- when a process becomes runnable. */
- else if (!EQ (symbol, Qrun) && !NILP (buffer))
- {
- 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))
- continue;
- Fset_buffer (buffer);
- opoint = point;
- /* Insert new output into buffer
- at the current end-of-output marker,
- thus preserving logical ordering of input and output. */
- if (XMARKER (p->mark)->buffer)
- SET_PT (marker_position (p->mark));
- else
- SET_PT (ZV);
- if (point <= opoint)
- opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
-
- tem = current_buffer->read_only;
- current_buffer->read_only = Qnil;
- insert_string ("\nProcess ");
- Finsert (1, &p->name);
- insert_string (" ");
- Finsert (1, &msg);
- current_buffer->read_only = tem;
- Fset_marker (p->mark, make_number (point), p->buffer);
-
- SET_PT (opoint);
- set_buffer_internal (old);
- }
+ /* Avoid error if buffer is deleted
+ (probably that's why the process is dead, too) */
+ if (NILP (XBUFFER (buffer)->name))
+ continue;
+ Fset_buffer (buffer);
+ opoint = point;
+ /* Insert new output into buffer
+ at the current end-of-output marker,
+ thus preserving logical ordering of input and output. */
+ if (XMARKER (p->mark)->buffer)
+ SET_PT (marker_position (p->mark));
+ else
+ SET_PT (ZV);
+ if (point <= opoint)
+ opoint += XSTRING (msg)->size + XSTRING (p->name)->size + 10;
+
+ tem = current_buffer->read_only;
+ current_buffer->read_only = Qnil;
+ insert_string ("\nProcess ");
+ Finsert (1, &p->name);
+ insert_string (" ");
+ Finsert (1, &msg);
+ current_buffer->read_only = tem;
+ Fset_marker (p->mark, make_number (point), p->buffer);
+
+ SET_PT (opoint);
+ set_buffer_internal (old);
}
- } /* end for */
- } while (! EQ (old_process_alist, Vprocess_alist));
+ }
+ } /* end for */
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 ();