/* Asynchronous subprocess control for GNU Emacs.
-Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2011
+Copyright (C) 1985-1988, 1993-1996, 1998-1999, 2001-2012
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include <stdio.h>
#include <errno.h>
#include <setjmp.h>
-#include <sys/types.h> /* some typedefs are used in sys/file.h */
+#include <sys/types.h> /* Some typedefs are used in sys/file.h. */
#include <sys/file.h>
#include <sys/stat.h>
#include <setjmp.h>
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
#include <unistd.h>
#include <fcntl.h>
+#include "lisp.h"
+
/* Only MS-DOS does not define `subprocesses'. */
#ifdef subprocesses
#endif
#include <sys/ioctl.h>
-#if defined(HAVE_NET_IF_H)
+#if defined (HAVE_NET_IF_H)
#include <net/if.h>
#endif /* HAVE_NET_IF_H */
+#if defined (HAVE_IFADDRS_H)
+/* Must be after net/if.h */
+#include <ifaddrs.h>
+
+/* We only use structs from this header when we use getifaddrs. */
+#if defined (HAVE_NET_IF_DL_H)
+#include <net/if_dl.h>
+#endif
+
+#endif
+
#ifdef NEED_BSDTTY
#include <bsdtty.h>
#endif
#endif /* subprocesses */
-#include "lisp.h"
#include "systime.h"
#include "systty.h"
#include "gnutls.h"
#endif
-#if defined (USE_GTK) || defined (HAVE_GCONF)
+#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
#include "xgselect.h"
-#endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+#endif
#ifdef HAVE_NS
#include "nsterm.h"
#endif
#ifdef subprocesses
Lisp_Object Qprocessp;
-Lisp_Object Qrun, Qstop, Qsignal;
-Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal, Qipv4, Qdatagram, Qseqpacket;
-Lisp_Object Qreal, Qnetwork, Qserial;
+static Lisp_Object Qrun, Qstop, Qsignal;
+static Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
+Lisp_Object Qlocal;
+static Lisp_Object Qipv4, Qdatagram, Qseqpacket;
+static Lisp_Object Qreal, Qnetwork, Qserial;
#ifdef AF_INET6
-Lisp_Object Qipv6;
+static Lisp_Object Qipv6;
#endif
-Lisp_Object QCport, QCspeed, QCprocess;
+static Lisp_Object QCport, QCprocess;
+Lisp_Object QCspeed;
Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven;
Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary;
-Lisp_Object QCbuffer, QChost, QCservice;
-Lisp_Object QClocal, QCremote, QCcoding;
-Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
-Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
-Lisp_Object Qlast_nonmenu_event;
+static Lisp_Object QCbuffer, QChost, QCservice;
+static Lisp_Object QClocal, QCremote, QCcoding;
+static Lisp_Object QCserver, QCnowait, QCnoquery, QCstop;
+static Lisp_Object QCsentinel, QClog, QCoptions, QCplist;
+static Lisp_Object Qlast_nonmenu_event;
/* QCfamily is declared and initialized in xfaces.c,
QCfilter in keyboard.c. */
extern Lisp_Object QCfamily, QCfilter;
#define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial))
#define SERIALCONN1_P(p) (EQ ((p)->type, Qserial))
-/* Define first descriptor number available for subprocesses. */
-#define FIRST_PROC_DESC 3
-
#ifndef HAVE_H_ERRNO
extern int h_errno;
#endif
-/* 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. */
-int process_tick;
+static int process_tick;
/* Number of events for which the user or sentinel has been notified. */
-int update_tick;
+static int update_tick;
/* Define NON_BLOCKING_CONNECT if we can support non-blocking connects. */
#define process_output_delay_count 0
#endif
+static Lisp_Object Fget_process (Lisp_Object);
+static void create_process (Lisp_Object, char **, Lisp_Object);
+#ifdef SIGIO
static int keyboard_bit_set (SELECT_TYPE *);
+#endif
static void deactivate_process (Lisp_Object);
static void status_notify (struct Lisp_Process *);
static int read_process_output (Lisp_Object, int);
/* If we support a window system, turn on the code to poll periodically
to detect C-g. It isn't actually used when doing interrupt input. */
-#ifdef HAVE_WINDOW_SYSTEM
+#if defined (HAVE_WINDOW_SYSTEM) && !defined (USE_ASYNC_EVENTS)
#define POLL_FOR_INPUT
#endif
/* Number of bits set in connect_wait_mask. */
static int num_pending_connects;
-
-#define IF_NON_BLOCKING_CONNECT(s) s
-#else /* NON_BLOCKING_CONNECT */
-#define IF_NON_BLOCKING_CONNECT(s)
#endif /* NON_BLOCKING_CONNECT */
/* The largest descriptor currently in use for a process object. */
static int max_input_desc;
/* Indexed by descriptor, gives the process (if any) for that descriptor */
-Lisp_Object chan_process[MAXDESC];
+static Lisp_Object chan_process[MAXDESC];
/* Alist of elements (NAME . PROCESS) */
-Lisp_Object Vprocess_alist;
+static Lisp_Object Vprocess_alist;
/* Buffered-ahead input char from process, indexed by channel.
-1 means empty (no char is buffered).
output from the process is to read at least one char.
Always -1 on systems that support FIONREAD. */
-/* Don't make static; need to access externally. */
-int proc_buffered_char[MAXDESC];
+static int proc_buffered_char[MAXDESC];
/* Table of `struct coding-system' for each process. */
static struct coding_system *proc_decode_coding_system[MAXDESC];
#ifdef DATAGRAM_SOCKETS
/* Table of `partner address' for datagram sockets. */
-struct sockaddr_and_len {
+static struct sockaddr_and_len {
struct sockaddr *sa;
int len;
} datagram_address[MAXDESC];
\f
-struct fd_callback_data
+static struct fd_callback_data
{
fd_callback func;
void *data;
{
register Lisp_Object val, tem, name1;
register struct Lisp_Process *p;
- char suffix[10];
- register int i;
+ char suffix[sizeof "<>" + INT_STRLEN_BOUND (printmax_t)];
+ printmax_t i;
p = allocate_process ();
p->gnutls_initstage = GNUTLS_STAGE_EMPTY;
p->gnutls_log_level = 0;
p->gnutls_p = 0;
+ p->gnutls_state = NULL;
+ p->gnutls_x509_cred = NULL;
+ p->gnutls_anon_cred = NULL;
#endif
/* If name is already in use, modify it until it is unused. */
{
tem = Fget_process (name1);
if (NILP (tem)) break;
- sprintf (suffix, "<%d>", i);
+ sprintf (suffix, "<%"pMd">", i);
name1 = concat2 (name, build_string (suffix));
}
name = name1;
DEFUN ("set-process-buffer", Fset_process_buffer, Sset_process_buffer,
2, 2, 0,
- doc: /* Set buffer associated with PROCESS to BUFFER (a buffer, or nil). */)
+ doc: /* Set buffer associated with PROCESS to BUFFER (a buffer, or nil).
+Return BUFFER. */)
(register Lisp_Object process, Lisp_Object buffer)
{
struct Lisp_Process *p;
}
#ifdef DATAGRAM_SOCKETS
-Lisp_Object Fprocess_datagram_address (Lisp_Object process);
+static Lisp_Object Fprocess_datagram_address (Lisp_Object);
#endif
DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
if (VECTORP (address)) /* AF_INET or AF_INET6 */
{
register struct Lisp_Vector *p = XVECTOR (address);
+ EMACS_INT size = p->header.size;
Lisp_Object args[10];
int nargs, i;
- if (p->size == 4 || (p->size == 5 && !NILP (omit_port)))
+ if (size == 4 || (size == 5 && !NILP (omit_port)))
{
args[0] = build_string ("%d.%d.%d.%d");
nargs = 4;
}
- else if (p->size == 5)
+ else if (size == 5)
{
args[0] = build_string ("%d.%d.%d.%d:%d");
nargs = 5;
}
- else if (p->size == 8 || (p->size == 9 && !NILP (omit_port)))
+ else if (size == 8 || (size == 9 && !NILP (omit_port)))
{
args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
nargs = 8;
}
- else if (p->size == 9)
+ else if (size == 9)
{
args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d");
nargs = 9;
return Qnil;
}
-\f
-static Lisp_Object
-list_processes_1 (Lisp_Object query_only)
-{
- register Lisp_Object tail;
- Lisp_Object proc, minspace;
- register struct Lisp_Process *p;
- char tembuf[300];
- int w_proc, w_buffer, w_tty;
- int exited = 0;
- Lisp_Object i_status, i_buffer, i_tty, i_command;
-
- w_proc = 4; /* Proc */
- w_buffer = 6; /* Buffer */
- w_tty = 0; /* Omit if no ttys */
-
- for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
- {
- int i;
-
- proc = Fcdr (XCAR (tail));
- p = XPROCESS (proc);
- if (NILP (p->type))
- continue;
- if (!NILP (query_only) && p->kill_without_query)
- continue;
- if (STRINGP (p->name)
- && ( i = SCHARS (p->name), (i > w_proc)))
- w_proc = i;
- if (!NILP (p->buffer))
- {
- if (NILP (BVAR (XBUFFER (p->buffer), name)))
- {
- if (w_buffer < 8)
- w_buffer = 8; /* (Killed) */
- }
- else if ((i = SCHARS (BVAR (XBUFFER (p->buffer), name)), (i > w_buffer)))
- w_buffer = i;
- }
- if (STRINGP (p->tty_name)
- && (i = SCHARS (p->tty_name), (i > w_tty)))
- w_tty = i;
- }
-
- XSETFASTINT (i_status, w_proc + 1);
- XSETFASTINT (i_buffer, XFASTINT (i_status) + 9);
- if (w_tty)
- {
- XSETFASTINT (i_tty, XFASTINT (i_buffer) + w_buffer + 1);
- XSETFASTINT (i_command, XFASTINT (i_tty) + w_tty + 1);
- }
- else
- {
- i_tty = Qnil;
- XSETFASTINT (i_command, XFASTINT (i_buffer) + w_buffer + 1);
- }
-
- XSETFASTINT (minspace, 1);
-
- set_buffer_internal (XBUFFER (Vstandard_output));
- BVAR (current_buffer, undo_list) = Qt;
-
- BVAR (current_buffer, truncate_lines) = Qt;
-
- write_string ("Proc", -1);
- Findent_to (i_status, minspace); write_string ("Status", -1);
- Findent_to (i_buffer, minspace); write_string ("Buffer", -1);
- if (!NILP (i_tty))
- {
- Findent_to (i_tty, minspace); write_string ("Tty", -1);
- }
- Findent_to (i_command, minspace); write_string ("Command", -1);
- write_string ("\n", -1);
-
- write_string ("----", -1);
- Findent_to (i_status, minspace); write_string ("------", -1);
- Findent_to (i_buffer, minspace); write_string ("------", -1);
- if (!NILP (i_tty))
- {
- Findent_to (i_tty, minspace); write_string ("---", -1);
- }
- Findent_to (i_command, minspace); write_string ("-------", -1);
- write_string ("\n", -1);
-
- for (tail = Vprocess_alist; CONSP (tail); tail = XCDR (tail))
- {
- Lisp_Object symbol;
-
- proc = Fcdr (XCAR (tail));
- p = XPROCESS (proc);
- if (NILP (p->type))
- continue;
- if (!NILP (query_only) && p->kill_without_query)
- continue;
-
- Finsert (1, &p->name);
- Findent_to (i_status, minspace);
-
- if (p->raw_status_new)
- update_status (p);
- symbol = p->status;
- if (CONSP (p->status))
- symbol = XCAR (p->status);
-
- if (EQ (symbol, Qsignal))
- {
- Lisp_Object tem;
- tem = Fcar (Fcdr (p->status));
- Fprinc (symbol, Qnil);
- }
- else if (NETCONN1_P (p) || SERIALCONN1_P (p))
- {
- if (EQ (symbol, Qexit))
- write_string ("closed", -1);
- else if (EQ (p->command, Qt))
- write_string ("stopped", -1);
- else if (EQ (symbol, Qrun))
- write_string ("open", -1);
- else
- Fprinc (symbol, Qnil);
- }
- else if (SERIALCONN1_P (p))
- {
- write_string ("running", -1);
- }
- else
- Fprinc (symbol, Qnil);
-
- if (EQ (symbol, Qexit))
- {
- Lisp_Object tem;
- tem = Fcar (Fcdr (p->status));
- if (XFASTINT (tem))
- {
- sprintf (tembuf, " %d", (int) XFASTINT (tem));
- write_string (tembuf, -1);
- }
- }
-
- if (EQ (symbol, Qsignal) || EQ (symbol, Qexit) || EQ (symbol, Qclosed))
- exited++;
-
- Findent_to (i_buffer, minspace);
- if (NILP (p->buffer))
- insert_string ("(none)");
- else if (NILP (BVAR (XBUFFER (p->buffer), name)))
- insert_string ("(Killed)");
- else
- Finsert (1, &BVAR (XBUFFER (p->buffer), name));
-
- if (!NILP (i_tty))
- {
- Findent_to (i_tty, minspace);
- if (STRINGP (p->tty_name))
- Finsert (1, &p->tty_name);
- }
-
- Findent_to (i_command, minspace);
-
- if (EQ (p->status, Qlisten))
- {
- Lisp_Object port = Fplist_get (p->childp, QCservice);
- if (INTEGERP (port))
- port = Fnumber_to_string (port);
- if (NILP (port))
- port = Fformat_network_address (Fplist_get (p->childp, QClocal), Qnil);
- sprintf (tembuf, "(network %s server on %s)\n",
- (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
- (STRINGP (port) ? SSDATA (port) : "?"));
- insert_string (tembuf);
- }
- else if (NETCONN1_P (p))
- {
- /* For a local socket, there is no host name,
- so display service instead. */
- Lisp_Object host = Fplist_get (p->childp, QChost);
- if (!STRINGP (host))
- {
- host = Fplist_get (p->childp, QCservice);
- if (INTEGERP (host))
- host = Fnumber_to_string (host);
- }
- if (NILP (host))
- host = Fformat_network_address (Fplist_get (p->childp, QCremote), Qnil);
- sprintf (tembuf, "(network %s connection to %s)\n",
- (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"),
- (STRINGP (host) ? SSDATA (host) : "?"));
- insert_string (tembuf);
- }
- else if (SERIALCONN1_P (p))
- {
- Lisp_Object port = Fplist_get (p->childp, QCport);
- Lisp_Object speed = Fplist_get (p->childp, QCspeed);
- insert_string ("(serial port ");
- if (STRINGP (port))
- insert_string (SSDATA (port));
- else
- insert_string ("?");
- if (INTEGERP (speed))
- {
- sprintf (tembuf, " at %ld b/s", (long) XINT (speed));
- insert_string (tembuf);
- }
- insert_string (")\n");
- }
- else
- {
- Lisp_Object tem = p->command;
- while (1)
- {
- Lisp_Object tem1 = Fcar (tem);
- if (NILP (tem1))
- break;
- Finsert (1, &tem1);
- tem = Fcdr (tem);
- if (NILP (tem))
- break;
- insert_string (" ");
- }
- insert_string ("\n");
- }
- }
- if (exited)
- {
- status_notify (NULL);
- redisplay_preserve_echo_area (13);
- }
- return Qnil;
-}
-
-DEFUN ("list-processes", Flist_processes, Slist_processes, 0, 1, "P",
- doc: /* Display a list of all processes.
-If optional argument QUERY-ONLY is non-nil, only processes with
-the query-on-exit flag set will be listed.
-Any process listed as exited or signaled is actually eliminated
-after the listing is made. */)
- (Lisp_Object query_only)
-{
- internal_with_output_to_temp_buffer ("*Process List*",
- list_processes_1, query_only);
- return Qnil;
-}
DEFUN ("process-list", Fprocess_list, Sprocess_list, 0, 0, 0,
doc: /* Return a list of all processes. */)
function to handle the output. BUFFER may also be nil, meaning that
this process is not associated with any buffer.
-PROGRAM is the program file name. It is searched for in PATH. If
-nil, just associate a pty with the buffer. Remaining arguments are
-strings to give program as arguments.
+PROGRAM is the program file name. It is searched for in `exec-path'
+(which see). If nil, just associate a pty with the buffer. Remaining
+arguments are strings to give program as arguments.
If you want to separate standard output from standard error, invoke
the command through a shell and redirect one of them using the shell
syntax.
usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */)
- (int nargs, register Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object buffer, name, program, proc, current_dir, tem;
register unsigned char **new_argv;
- register int i;
+ ptrdiff_t i;
int count = SPECPDL_INDEX ();
buffer = args[1];
{
if (EQ (coding_systems, Qt))
{
- args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof args2);
+ args2 = (Lisp_Object *) alloca ((nargs + 1) * sizeof *args2);
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
val = XCDR (Vdefault_process_coding_system);
}
XPROCESS (proc)->encode_coding_system = val;
- /* Note: At this momemnt, the above coding system may leave
+ /* Note: At this moment, the above coding system may leave
text-conversion or eol-conversion unspecified. They will be
decided after we read output from the process and decode it by
some coding system, or just before we actually send a text to
new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *));
new_argv[nargs - 2] = 0;
- for (i = nargs - 3; i >= 0; i--)
+ for (i = nargs - 2; i-- != 0; )
{
new_argv[i] = SDATA (XCAR (tem));
tem = XCDR (tem);
if (!PROCESSP (proc))
abort ();
- /* Was PROC started successfully? */
- if (XPROCESS (proc)->pid == -1)
+ /* Was PROC started successfully?
+ -2 is used for a pty with no process, eg for gdb. */
+ if (XPROCESS (proc)->pid <= 0 && XPROCESS (proc)->pid != -2)
remove_process (proc);
return Qnil;
}
-void
+static void
create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
{
int inchannel, outchannel;
XPROCESS (process)->pty_flag = pty_flag;
XPROCESS (process)->status = Qrun;
- setup_process_coding_systems (process);
/* Delay interrupts until we have a chance to store
the new fork's pid in its process structure */
sigaddset (&blocked, SIGHUP ); sigaction (SIGHUP , 0, &sighup_action );
#endif
#endif /* HAVE_WORKING_VFORK */
- sigprocmask (SIG_BLOCK, &blocked, &procmask);
+ pthread_sigmask (SIG_BLOCK, &blocked, &procmask);
FD_SET (inchannel, &input_wait_mask);
FD_SET (inchannel, &non_keyboard_wait_mask);
processes to get their return values scrambled. */
XPROCESS (process)->pid = -1;
+ /* This must be called after the above line because it may signal an
+ error. */
+ setup_process_coding_systems (process);
+
BLOCK_INPUT;
{
/* child_setup must clobber environ on systems with true vfork.
Protect it from permanent change. */
char **save_environ = environ;
-
- current_dir = ENCODE_FILE (current_dir);
+ volatile Lisp_Object encoded_current_dir = ENCODE_FILE (current_dir);
#ifndef WINDOWSNT
pid = vfork ();
signal (SIGPIPE, SIG_DFL);
/* Stop blocking signals in the child. */
- sigprocmask (SIG_SETMASK, &procmask, 0);
+ pthread_sigmask (SIG_SETMASK, &procmask, 0);
if (pty_flag)
child_setup_tty (xforkout);
#ifdef WINDOWSNT
pid = child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, current_dir);
+ new_argv, 1, encoded_current_dir);
#else /* not WINDOWSNT */
#ifdef FD_CLOEXEC
emacs_close (wait_child_setup[0]);
#endif
child_setup (xforkin, xforkout, xforkout,
- new_argv, 1, current_dir);
+ new_argv, 1, encoded_current_dir);
#endif /* not WINDOWSNT */
}
environ = save_environ;
#endif
#endif /* HAVE_WORKING_VFORK */
/* Stop blocking signals in the parent. */
- sigprocmask (SIG_SETMASK, &procmask, 0);
+ pthread_sigmask (SIG_SETMASK, &procmask, 0);
/* Now generate the error if vfork failed. */
if (pid < 0)
create_pty (Lisp_Object process)
{
int inchannel, outchannel;
-
- /* Use volatile to protect variables from being clobbered by longjmp. */
- volatile int forkin, forkout;
- volatile int pty_flag = 0;
+ int pty_flag = 0;
inchannel = outchannel = -1;
#ifdef O_NOCTTY
/* Don't let this terminal become our controlling terminal
(in case we don't have one). */
- forkout = forkin = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
+ int forkout = emacs_open (pty_name, O_RDWR | O_NOCTTY, 0);
#else
- forkout = forkin = emacs_open (pty_name, O_RDWR, 0);
+ int forkout = emacs_open (pty_name, O_RDWR, 0);
#endif
- if (forkin < 0)
+ if (forkout < 0)
report_file_error ("Opening pty", Qnil);
#if defined (DONT_REOPEN_PTY)
/* In the case that vfork is defined as fork, the parent process
tty options setup. So we setup tty before forking. */
child_setup_tty (forkout);
#endif /* DONT_REOPEN_PTY */
-#else
- forkin = forkout = -1;
#endif /* not USG, or USG_SUBTTY_WORKS */
pty_flag = 1;
}
if (VECTORP (address))
{
p = XVECTOR (address);
- if (p->size == 5)
+ if (p->header.size == 5)
{
*familyp = AF_INET;
return sizeof (struct sockaddr_in);
}
#ifdef AF_INET6
- else if (p->size == 9)
+ else if (p->header.size == 9)
{
*familyp = AF_INET6;
return sizeof (struct sockaddr_in6);
struct sockaddr *sa;
*familyp = XINT (XCAR (address));
p = XVECTOR (XCDR (address));
- return p->size + sizeof (sa->sa_family);
+ return p->header.size + sizeof (sa->sa_family);
}
return 0;
}
\(serial-process-configure :port "\\\\.\\COM13" :bytesize 7)
usage: (serial-process-configure &rest ARGS) */)
- (int nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
struct Lisp_Process *p;
Lisp_Object contact = Qnil;
\(make-serial-process :port "/dev/tty.BlueConsole-SPP-1" :speed nil)
usage: (make-serial-process &rest ARGS) */)
- (int nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
int fd = -1;
Lisp_Object proc, contact, port;
information, is available via the `process-contact' function.
usage: (make-network-process &rest ARGS) */)
- (int nargs, Lisp_Object *args)
+ (ptrdiff_t nargs, Lisp_Object *args)
{
Lisp_Object proc;
Lisp_Object contact;
{
/* Don't support network sockets when non-blocking mode is
not available, since a blocked Emacs is not useful. */
-#if !defined(O_NONBLOCK) && !defined(O_NDELAY)
+#if !defined (O_NONBLOCK) && !defined (O_NDELAY)
error ("Network servers not supported");
#else
is_server = 1;
tem = Fplist_get (contact, QCfamily);
if (NILP (tem))
{
-#if defined(HAVE_GETADDRINFO) && defined(AF_INET6)
+#if defined (HAVE_GETADDRINFO) && defined (AF_INET6)
family = AF_UNSPEC;
#else
family = AF_INET;
portstring = "0";
else if (INTEGERP (service))
{
- sprintf (portbuf, "%ld", (long) XINT (service));
+ sprintf (portbuf, "%"pI"d", XINT (service));
portstring = portbuf;
}
else
{
struct hostent *host_info_ptr;
- /* gethostbyname may fail with TRY_AGAIN, but we don't honour that,
+ /* gethostbyname may fail with TRY_AGAIN, but we don't honor that,
as it may `hang' Emacs for a very long time. */
immediate_quit = 1;
QUIT;
for (lres = res; lres; lres = lres->ai_next)
{
- int optn, optbits;
+ ptrdiff_t optn;
+ int optbits;
#ifdef WINDOWSNT
retry_connect:
if (EQ (service, Qt))
{
struct sockaddr_in sa1;
- int len1 = sizeof (sa1);
+ socklen_t len1 = sizeof (sa1);
if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
{
((struct sockaddr_in *)(lres->ai_addr))->sin_port = sa1.sin_port;
/* Unlike most other syscalls connect() cannot be called
again. (That would return EALREADY.) The proper way to
wait for completion is select(). */
- int sc, len;
+ int sc;
+ socklen_t len;
SELECT_TYPE fdset;
retry_select:
FD_ZERO (&fdset);
if (!is_server)
{
struct sockaddr_in sa1;
- int len1 = sizeof (sa1);
+ socklen_t len1 = sizeof (sa1);
if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
contact = Fplist_put (contact, QClocal,
conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1));
{
/* Setup coding systems for communicating with the network stream. */
- struct gcpro inner_gcpro1;
+ struct gcpro gcpro1;
/* Qt denotes we have not yet called Ffind_operation_coding_system. */
Lisp_Object coding_systems = Qt;
Lisp_Object fargs[5], val;
|| (NILP (buffer) && NILP (BVAR (&buffer_defaults, enable_multibyte_characters))))
/* We dare not decode end-of-line format by setting VAL to
Qraw_text, because the existing Emacs Lisp libraries
- assume that they receive bare code including a sequene of
+ assume that they receive bare code including a sequence of
CR LF. */
val = Qnil;
else
{
fargs[0] = Qopen_network_stream, fargs[1] = name,
fargs[2] = buffer, fargs[3] = host, fargs[4] = service;
- GCPRO1_VAR (proc, inner_gcpro);
+ GCPRO1 (proc);
coding_systems = Ffind_operation_coding_system (5, fargs);
- UNGCPRO_VAR (inner_gcpro);
+ UNGCPRO;
}
if (CONSP (coding_systems))
val = XCAR (coding_systems);
{
fargs[0] = Qopen_network_stream, fargs[1] = name,
fargs[2] = buffer, fargs[3] = host, fargs[4] = service;
- GCPRO1_VAR (proc, inner_gcpro);
+ GCPRO1 (proc);
coding_systems = Ffind_operation_coding_system (5, fargs);
- UNGCPRO_VAR (inner_gcpro);
+ UNGCPRO;
}
}
if (CONSP (coding_systems))
}
\f
-#if defined(HAVE_NET_IF_H)
+#if defined (HAVE_NET_IF_H)
#ifdef SIOCGIFCONF
DEFUN ("network-interface-list", Fnetwork_interface_list, Snetwork_interface_list, 0, 0, 0,
(void)
{
struct ifconf ifconf;
- struct ifreq *ifreqs = NULL;
- int ifaces = 0;
- int buf_size, s;
+ struct ifreq *ifreq;
+ void *buf = NULL;
+ ptrdiff_t buf_size = 512;
+ int s, i;
Lisp_Object res;
s = socket (AF_INET, SOCK_STREAM, 0);
if (s < 0)
return Qnil;
- again:
- ifaces += 25;
- buf_size = ifaces * sizeof (ifreqs[0]);
- ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size);
- if (!ifreqs)
- {
- close (s);
- return Qnil;
- }
-
- ifconf.ifc_len = buf_size;
- ifconf.ifc_req = ifreqs;
- if (ioctl (s, SIOCGIFCONF, &ifconf))
+ do
{
- close (s);
- return Qnil;
+ buf = xpalloc (buf, &buf_size, 1, INT_MAX, 1);
+ ifconf.ifc_buf = buf;
+ ifconf.ifc_len = buf_size;
+ if (ioctl (s, SIOCGIFCONF, &ifconf))
+ {
+ close (s);
+ xfree (buf);
+ return Qnil;
+ }
}
-
- if (ifconf.ifc_len == buf_size)
- goto again;
+ while (ifconf.ifc_len == buf_size);
close (s);
- ifaces = ifconf.ifc_len / sizeof (ifreqs[0]);
res = Qnil;
- while (--ifaces >= 0)
+ ifreq = ifconf.ifc_req;
+ while ((char *) ifreq < (char *) ifconf.ifc_req + ifconf.ifc_len)
{
- struct ifreq *ifq = &ifreqs[ifaces];
+ struct ifreq *ifq = ifreq;
+#ifdef HAVE_STRUCT_IFREQ_IFR_ADDR_SA_LEN
+#define SIZEOF_IFREQ(sif) \
+ ((sif)->ifr_addr.sa_len < sizeof (struct sockaddr) \
+ ? sizeof (*(sif)) : sizeof ((sif)->ifr_name) + (sif)->ifr_addr.sa_len)
+
+ int len = SIZEOF_IFREQ (ifq);
+#else
+ int len = sizeof (*ifreq);
+#endif
char namebuf[sizeof (ifq->ifr_name) + 1];
+ i += len;
+ ifreq = (struct ifreq *) ((char *) ifreq + len);
+
if (ifq->ifr_addr.sa_family != AF_INET)
continue;
+
memcpy (namebuf, ifq->ifr_name, sizeof (ifq->ifr_name));
namebuf[sizeof (ifq->ifr_name)] = 0;
res = Fcons (Fcons (build_string (namebuf),
res);
}
+ xfree (buf);
return res;
}
#endif /* SIOCGIFCONF */
-#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS)
+#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
struct ifflag_def {
int flag_bit;
{ IFF_PROMISC, "promisc" },
#endif
#ifdef IFF_NOTRAILERS
+#ifdef NS_IMPL_COCOA
+ /* Really means smart, notrailers is obsolete */
+ { IFF_NOTRAILERS, "smart" },
+#else
{ IFF_NOTRAILERS, "notrailers" },
#endif
+#endif
#ifdef IFF_ALLMULTI
{ IFF_ALLMULTI, "allmulti" },
#endif
doc: /* Return information about network interface named IFNAME.
The return value is a list (ADDR BCAST NETMASK HWADDR FLAGS),
where ADDR is the layer 3 address, BCAST is the layer 3 broadcast address,
-NETMASK is the layer 3 network mask, HWADDR is the layer 2 addres, and
+NETMASK is the layer 3 network mask, HWADDR is the layer 2 address, and
FLAGS is the current flags of the interface. */)
(Lisp_Object ifname)
{
Lisp_Object elt;
int s;
int any = 0;
+#if (! (defined SIOCGIFHWADDR && defined HAVE_STRUCT_IFREQ_IFR_HWADDR) \
+ && defined HAVE_GETIFADDRS && defined LLADDR)
+ struct ifaddrs *ifap;
+#endif
CHECK_STRING (ifname);
return Qnil;
elt = Qnil;
-#if defined(SIOCGIFFLAGS) && defined(HAVE_STRUCT_IFREQ_IFR_FLAGS)
+#if defined (SIOCGIFFLAGS) && defined (HAVE_STRUCT_IFREQ_IFR_FLAGS)
if (ioctl (s, SIOCGIFFLAGS, &rq) == 0)
{
int flags = rq.ifr_flags;
const struct ifflag_def *fp;
int fnum;
- any++;
+ /* If flags is smaller than int (i.e. short) it may have the high bit set
+ due to IFF_MULTICAST. In that case, sign extending it into
+ an int is wrong. */
+ if (flags < 0 && sizeof (rq.ifr_flags) < sizeof (flags))
+ flags = (unsigned short) rq.ifr_flags;
+
+ any = 1;
for (fp = ifflag_table; flags != 0 && fp->flag_sym; fp++)
{
if (flags & fp->flag_bit)
flags -= fp->flag_bit;
}
}
- for (fnum = 0; flags && fnum < 32; fnum++)
+ for (fnum = 0; flags && fnum < 32; flags >>= 1, fnum++)
{
- if (flags & (1 << fnum))
+ if (flags & 1)
{
elt = Fcons (make_number (fnum), elt);
}
res = Fcons (elt, res);
elt = Qnil;
-#if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_HWADDR)
+#if defined (SIOCGIFHWADDR) && defined (HAVE_STRUCT_IFREQ_IFR_HWADDR)
if (ioctl (s, SIOCGIFHWADDR, &rq) == 0)
{
Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
register struct Lisp_Vector *p = XVECTOR (hwaddr);
int n;
- any++;
+ any = 1;
for (n = 0; n < 6; n++)
p->contents[n] = make_number (((unsigned char *)&rq.ifr_hwaddr.sa_data[0])[n]);
elt = Fcons (make_number (rq.ifr_hwaddr.sa_family), hwaddr);
}
+#elif defined (HAVE_GETIFADDRS) && defined (LLADDR)
+ if (getifaddrs (&ifap) != -1)
+ {
+ Lisp_Object hwaddr = Fmake_vector (make_number (6), Qnil);
+ register struct Lisp_Vector *p = XVECTOR (hwaddr);
+ struct ifaddrs *it;
+
+ for (it = ifap; it != NULL; it = it->ifa_next)
+ {
+ struct sockaddr_dl *sdl = (struct sockaddr_dl*) it->ifa_addr;
+ unsigned char linkaddr[6];
+ int n;
+
+ if (it->ifa_addr->sa_family != AF_LINK
+ || strcmp (it->ifa_name, SSDATA (ifname)) != 0
+ || sdl->sdl_alen != 6)
+ continue;
+
+ memcpy (linkaddr, LLADDR (sdl), sdl->sdl_alen);
+ for (n = 0; n < 6; n++)
+ p->contents[n] = make_number (linkaddr[n]);
+
+ elt = Fcons (make_number (it->ifa_addr->sa_family), hwaddr);
+ break;
+ }
+ }
+#ifdef HAVE_FREEIFADDRS
+ freeifaddrs (ifap);
#endif
+
+#endif /* HAVE_GETIFADDRS && LLADDR */
+
res = Fcons (elt, res);
elt = Qnil;
-#if defined(SIOCGIFNETMASK) && (defined(HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined(HAVE_STRUCT_IFREQ_IFR_ADDR))
+#if defined (SIOCGIFNETMASK) && (defined (HAVE_STRUCT_IFREQ_IFR_NETMASK) || defined (HAVE_STRUCT_IFREQ_IFR_ADDR))
if (ioctl (s, SIOCGIFNETMASK, &rq) == 0)
{
- any++;
+ any = 1;
#ifdef HAVE_STRUCT_IFREQ_IFR_NETMASK
elt = conv_sockaddr_to_lisp (&rq.ifr_netmask, sizeof (rq.ifr_netmask));
#else
res = Fcons (elt, res);
elt = Qnil;
-#if defined(SIOCGIFBRDADDR) && defined(HAVE_STRUCT_IFREQ_IFR_BROADADDR)
+#if defined (SIOCGIFBRDADDR) && defined (HAVE_STRUCT_IFREQ_IFR_BROADADDR)
if (ioctl (s, SIOCGIFBRDADDR, &rq) == 0)
{
- any++;
+ any = 1;
elt = conv_sockaddr_to_lisp (&rq.ifr_broadaddr, sizeof (rq.ifr_broadaddr));
}
#endif
res = Fcons (elt, res);
elt = Qnil;
-#if defined(SIOCGIFADDR) && defined(HAVE_STRUCT_IFREQ_IFR_ADDR)
+#if defined (SIOCGIFADDR) && defined (HAVE_STRUCT_IFREQ_IFR_ADDR)
if (ioctl (s, SIOCGIFADDR, &rq) == 0)
{
- any++;
+ any = 1;
elt = conv_sockaddr_to_lisp (&rq.ifr_addr, sizeof (rq.ifr_addr));
}
#endif
return any ? res : Qnil;
}
#endif
-#endif /* defined(HAVE_NET_IF_H) */
+#endif /* defined (HAVE_NET_IF_H) */
/* Turn off input and output for process PROC. */
-void
+static void
deactivate_process (Lisp_Object proc)
{
register int inchannel, outchannel;
register struct Lisp_Process *p = XPROCESS (proc);
+#ifdef HAVE_GNUTLS
+ /* Delete GnuTLS structures in PROC, if any. */
+ emacs_gnutls_deinit (proc);
+#endif /* HAVE_GNUTLS */
+
inchannel = p->infd;
outchannel = p->outfd;
struct sockaddr_un un;
#endif
} saddr;
- int len = sizeof saddr;
+ socklen_t len = sizeof saddr;
s = accept (channel, &saddr.sa, &len);
impossible to step through wait_reading_process_output. */
#ifndef select
-static INLINE int
+static inline int
select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo)
{
return select (n, rfd, wfd, xfd, tmo);
struct buffer *old_buffer = current_buffer;
Lisp_Object old_window = selected_window;
- timer_delay = timer_check (1);
+ timer_delay = timer_check ();
/* If a timer has run, this might have changed buffers
an alike. Make read_key_sequence aware of that. */
set_waiting_for_input (&timeout);
}
+ /* Skip the `select' call if input is available and we're
+ waiting for keyboard input or a cell change (which can be
+ triggered by processing X events). In the latter case, set
+ nfds to 1 to avoid breaking the loop. */
no_avail = 0;
- if (read_kbd && detect_input_pending ())
+ if ((read_kbd || !NILP (wait_for_cell))
+ && detect_input_pending ())
{
- nfds = 0;
+ nfds = read_kbd ? 0 : 1;
no_avail = 1;
}
- else
+
+ if (!no_avail)
{
#ifdef ADAPTIVE_READ_BUFFERING
process_output_skip = 0;
}
#endif
-#if defined (USE_GTK) || defined (HAVE_GCONF)
+#if defined (USE_GTK) || defined (HAVE_GCONF) || defined (HAVE_GSETTINGS)
nfds = xg_select
#elif defined (HAVE_NS)
nfds = ns_select
&Available,
(check_write ? &Writeok : (SELECT_TYPE *)0),
(SELECT_TYPE *)0, &timeout);
+
+#ifdef HAVE_GNUTLS
+ /* GnuTLS buffers data internally. In lowat mode it leaves
+ some data in the TCP buffers so that select works, but
+ with custom pull/push functions we need to check if some
+ data is available in the buffers manually. */
+ if (nfds == 0)
+ {
+ if (! wait_proc)
+ {
+ /* We're not waiting on a specific process, so loop
+ through all the channels and check for data.
+ This is a workaround needed for some versions of
+ the gnutls library -- 2.12.14 has been confirmed
+ to need it. See
+ http://comments.gmane.org/gmane.emacs.devel/145074 */
+ for (channel = 0; channel < MAXDESC; ++channel)
+ if (! NILP (chan_process[channel]))
+ {
+ struct Lisp_Process *p =
+ XPROCESS (chan_process[channel]);
+ if (p && p->gnutls_p && p->infd
+ && ((emacs_gnutls_record_check_pending
+ (p->gnutls_state))
+ > 0))
+ {
+ nfds++;
+ FD_SET (p->infd, &Available);
+ }
+ }
+ }
+ else
+ {
+ /* Check this specific channel. */
+ if (wait_proc->gnutls_p /* Check for valid process. */
+ /* Do we have pending data? */
+ && ((emacs_gnutls_record_check_pending
+ (wait_proc->gnutls_state))
+ > 0))
+ {
+ nfds = 1;
+ /* Set to Available. */
+ FD_SET (wait_proc->infd, &Available);
+ }
+ }
+ }
+#endif
}
xerrno = errno;
d->func (channel, d->data, 0);
}
- /* Really FIRST_PROC_DESC should be 0 on Unix,
- but this is safer in the short run. */
for (channel = 0; channel <= max_process_desc; channel++)
{
if (FD_ISSET (channel, &Available)
It can't hurt. */
else if (nread == -1 && errno == EIO)
{
- /* Clear the descriptor now, so we only raise the
- signal once. Don't do this if `process' is only
- a pty. */
- if (XPROCESS (proc)->pid != -2)
- {
- FD_CLR (channel, &input_wait_mask);
- FD_CLR (channel, &non_keyboard_wait_mask);
+ /* Clear the descriptor now, so we only raise the signal once. */
+ FD_CLR (channel, &input_wait_mask);
+ FD_CLR (channel, &non_keyboard_wait_mask);
- kill (getpid (), SIGCHLD);
- }
+ kill (getpid (), SIGCHLD);
}
#endif /* HAVE_PTYS */
/* If we can detect process termination, don't consider the process
/* getsockopt(,,SO_ERROR,,) is said to hang on some systems.
So only use it on systems where it is known to work. */
{
- int xlen = sizeof (xerrno);
+ socklen_t xlen = sizeof (xerrno);
if (getsockopt (channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen))
xerrno = errno;
}
static int
read_process_output (Lisp_Object proc, register int channel)
{
- register int nbytes;
+ register ssize_t nbytes;
char *chars;
register Lisp_Object outstream;
register struct Lisp_Process *p = XPROCESS (proc);
/* We have a working select, so proc_buffered_char is always -1. */
if (DATAGRAM_CHAN_P (channel))
{
- int len = datagram_address[channel].len;
+ socklen_t len = datagram_address[channel].len;
nbytes = recvfrom (channel, chars + carryover, readmax,
0, datagram_address[channel].sa, &len);
}
else
#endif
- if (proc_buffered_char[channel] < 0)
{
+ int buffered = 0 <= proc_buffered_char[channel];
+ if (buffered)
+ {
+ chars[carryover] = proc_buffered_char[channel];
+ proc_buffered_char[channel] = -1;
+ }
#ifdef HAVE_GNUTLS
- if (XPROCESS (proc)->gnutls_p)
- nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
- chars + carryover, readmax);
+ if (p->gnutls_p)
+ nbytes = emacs_gnutls_read (p, chars + carryover + buffered,
+ readmax - buffered);
else
#endif
- nbytes = emacs_read (channel, chars + carryover, readmax);
+ nbytes = emacs_read (channel, chars + carryover + buffered,
+ readmax - buffered);
#ifdef ADAPTIVE_READ_BUFFERING
if (nbytes > 0 && p->adaptive_read_buffering)
{
delay += READ_OUTPUT_DELAY_INCREMENT * 2;
}
}
- else if (delay > 0 && (nbytes == readmax))
+ else if (delay > 0 && nbytes == readmax - buffered)
{
delay -= READ_OUTPUT_DELAY_INCREMENT;
if (delay == 0)
}
}
#endif
- }
- else
- {
- chars[carryover] = proc_buffered_char[channel];
- proc_buffered_char[channel] = -1;
-#ifdef HAVE_GNUTLS
- if (XPROCESS (proc)->gnutls_p)
- nbytes = emacs_gnutls_read (channel, XPROCESS (proc),
- chars + carryover + 1, readmax - 1);
- else
-#endif
- nbytes = emacs_read (channel, chars + carryover + 1, readmax - 1);
- if (nbytes < 0)
- nbytes = 1;
- else
- nbytes = nbytes + 1;
+ nbytes += buffered;
+ nbytes += buffered && nbytes <= 0;
}
p->decoding_carryover = 0;
outstream = p->filter;
if (!NILP (outstream))
{
- Lisp_Object obuffer, okeymap;
Lisp_Object text;
int outer_running_asynch_code = running_asynch_code;
int waiting = waiting_for_user_input_p;
/* 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. */
+#if 0
+ Lisp_Object obuffer, okeymap;
XSETBUFFER (obuffer, current_buffer);
okeymap = BVAR (current_buffer, keymap);
+#endif
/* We inhibit quit here instead of just catching it so that
hitting ^G when a filter happens to be running won't screw
p->decoding_carryover = coding->carryover_bytes;
}
if (SBYTES (text) > 0)
+ /* FIXME: It's wrong to wrap or not based on debug-on-error, and
+ sometimes it's simply wrong to wrap (e.g. when called from
+ accept-process-output). */
internal_condition_case_1 (read_process_output_call,
Fcons (outstream,
Fcons (proc, Fcons (text, Qnil))),
\f
/* Sending data to subprocess */
-jmp_buf send_process_frame;
-Lisp_Object process_sent_to;
+static jmp_buf send_process_frame;
+static Lisp_Object process_sent_to;
-static SIGTYPE
+#ifndef FORWARD_SIGNAL_TO_MAIN_THREAD
+static void send_process_trap (int) NO_RETURN;
+#endif
+
+static void
send_process_trap (int ignore)
{
SIGNAL_THREAD_CHECK (SIGPIPE);
{
/* Use volatile to protect variables from being clobbered by longjmp. */
struct Lisp_Process *p = XPROCESS (proc);
- EMACS_INT rv;
+ ssize_t rv;
struct coding_system *coding;
struct gcpro gcpro1;
- SIGTYPE (*volatile old_sigpipe) (int);
+ void (*volatile old_sigpipe) (int);
GCPRO1 (object);
sending a multibyte text, thus we must encode it by the
original coding system specified for the current process.
- Another reason we comming here is that the coding system
- was just complemented and new one was returned by
+ Another reason we come here is that the coding system
+ was just complemented and a new one was returned by
complement_process_encoding_system. */
setup_coding_system (p->encode_coding_system, coding);
Vlast_coding_system_used = p->encode_coding_system;
}
else
{
+ coding->src_multibyte = 0;
/* For sending a unibyte text, character code conversion should
not take place but EOL conversion should. So, setup raw-text
or one of the subsidiary if we have not yet done it. */
when returning with longjmp despite being declared volatile. */
if (!setjmp (send_process_frame))
{
+ p = XPROCESS (proc); /* Repair any setjmp clobbering. */
+
process_sent_to = proc;
while (len > 0)
{
/* Send this batch, using one or more write calls. */
while (this > 0)
{
+ EMACS_INT written = 0;
int outfd = p->outfd;
- old_sigpipe = (SIGTYPE (*) (int)) signal (SIGPIPE, send_process_trap);
+ old_sigpipe = (void (*) (int)) signal (SIGPIPE, send_process_trap);
#ifdef DATAGRAM_SOCKETS
if (DATAGRAM_CHAN_P (outfd))
{
rv = sendto (outfd, buf, this,
0, datagram_address[outfd].sa,
datagram_address[outfd].len);
- if (rv < 0 && errno == EMSGSIZE)
+ if (0 <= rv)
+ written = rv;
+ else if (errno == EMSGSIZE)
{
signal (SIGPIPE, old_sigpipe);
report_file_error ("sending datagram",
#endif
{
#ifdef HAVE_GNUTLS
- if (XPROCESS (proc)->gnutls_p)
- rv = emacs_gnutls_write (outfd,
- XPROCESS (proc),
- buf, this);
+ if (p->gnutls_p)
+ written = emacs_gnutls_write (p, buf, this);
else
#endif
- rv = emacs_write (outfd, buf, this);
+ written = emacs_write (outfd, buf, this);
+ rv = (written ? 0 : -1);
#ifdef ADAPTIVE_READ_BUFFERING
if (p->read_output_delay > 0
&& p->adaptive_read_buffering == 1)
that may allow the program
to finish doing output and read more. */
{
- int offset = 0;
+ EMACS_INT offset = 0;
#ifdef BROKEN_PTY_READ_AFTER_EAGAIN
/* A gross hack to work around a bug in FreeBSD.
offset);
else if (STRINGP (object))
buf = offset + SSDATA (object);
-
- rv = 0;
}
else
/* This is a real error. */
report_file_error ("writing to process", Fcons (proc, Qnil));
}
- buf += rv;
- len -= rv;
- this -= rv;
+ buf += written;
+ len -= written;
+ this -= written;
}
}
}
indirectly; if it does, that is a bug */
#ifdef SIGCHLD
-static SIGTYPE
+static void
sigchld_handler (int signo)
{
int old_errno = errno;
static void
exec_sentinel (Lisp_Object proc, Lisp_Object reason)
{
- Lisp_Object sentinel, obuffer, odeactivate, okeymap;
+ Lisp_Object sentinel, odeactivate;
register struct Lisp_Process *p = XPROCESS (proc);
int count = SPECPDL_INDEX ();
int outer_running_asynch_code = running_asynch_code;
/* 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;
+#if 0
+ Lisp_Object obuffer, okeymap;
XSETBUFFER (obuffer, current_buffer);
okeymap = BVAR (current_buffer, keymap);
+#endif
/* There's no good reason to let sentinels change the current
buffer, and many callers of accept-process-output, sit-for, and
\f
+# ifdef HAVE_GPM
+
void
add_gpm_wait_descriptor (int desc)
{
delete_keyboard_wait_descriptor (desc);
}
+# endif
+
+# ifdef SIGIO
+
/* Return nonzero if *MASK has a bit set
that corresponds to one of the keyboard input descriptors. */
return 0;
}
+# endif
#else /* not subprocesses */
do
{
int old_timers_run = timers_run;
- timer_delay = timer_check (1);
+ timer_delay = timer_check ();
if (timers_run != old_timers_run && do_display)
/* We must retry, since a timer may have requeued itself
and that could alter the time delay. */
#endif /* subprocesses */
}
-DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p, Swaiting_for_user_input_p,
- 0, 0, 0,
+DEFUN ("waiting-for-user-input-p", Fwaiting_for_user_input_p,
+ Swaiting_for_user_input_p, 0, 0, 0,
doc: /* Returns non-nil if Emacs is waiting for input from the user.
This is intended for use by asynchronous process output filters and sentinels. */)
(void)
#ifdef HAVE_GETSOCKNAME
ADD_SUBFEATURE (QCservice, Qt);
#endif
-#if defined(O_NONBLOCK) || defined(O_NDELAY)
+#if defined (O_NONBLOCK) || defined (O_NDELAY)
ADD_SUBFEATURE (QCserver, Qt);
#endif
processes. As such, we only change the default value. */
if (initialized)
{
- const char *release = get_operating_system_release ();
+ char const *release = (STRINGP (Voperating_system_release)
+ ? SSDATA (Voperating_system_release)
+ : 0);
if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
&& release[1] == '.')) {
Vprocess_connection_type = Qnil;
{
#ifdef subprocesses
- Qprocessp = intern_c_string ("processp");
- staticpro (&Qprocessp);
- Qrun = intern_c_string ("run");
- staticpro (&Qrun);
- Qstop = intern_c_string ("stop");
- staticpro (&Qstop);
- Qsignal = intern_c_string ("signal");
- staticpro (&Qsignal);
+ DEFSYM (Qprocessp, "processp");
+ DEFSYM (Qrun, "run");
+ DEFSYM (Qstop, "stop");
+ DEFSYM (Qsignal, "signal");
/* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
here again.
Qexit = intern_c_string ("exit");
staticpro (&Qexit); */
- Qopen = intern_c_string ("open");
- staticpro (&Qopen);
- Qclosed = intern_c_string ("closed");
- staticpro (&Qclosed);
- Qconnect = intern_c_string ("connect");
- staticpro (&Qconnect);
- Qfailed = intern_c_string ("failed");
- staticpro (&Qfailed);
- Qlisten = intern_c_string ("listen");
- staticpro (&Qlisten);
- Qlocal = intern_c_string ("local");
- staticpro (&Qlocal);
- Qipv4 = intern_c_string ("ipv4");
- staticpro (&Qipv4);
+ DEFSYM (Qopen, "open");
+ DEFSYM (Qclosed, "closed");
+ DEFSYM (Qconnect, "connect");
+ DEFSYM (Qfailed, "failed");
+ DEFSYM (Qlisten, "listen");
+ DEFSYM (Qlocal, "local");
+ DEFSYM (Qipv4, "ipv4");
#ifdef AF_INET6
- Qipv6 = intern_c_string ("ipv6");
- staticpro (&Qipv6);
-#endif
- Qdatagram = intern_c_string ("datagram");
- staticpro (&Qdatagram);
- Qseqpacket = intern_c_string ("seqpacket");
- staticpro (&Qseqpacket);
-
- QCport = intern_c_string (":port");
- staticpro (&QCport);
- QCspeed = intern_c_string (":speed");
- staticpro (&QCspeed);
- QCprocess = intern_c_string (":process");
- staticpro (&QCprocess);
-
- QCbytesize = intern_c_string (":bytesize");
- staticpro (&QCbytesize);
- QCstopbits = intern_c_string (":stopbits");
- staticpro (&QCstopbits);
- QCparity = intern_c_string (":parity");
- staticpro (&QCparity);
- Qodd = intern_c_string ("odd");
- staticpro (&Qodd);
- Qeven = intern_c_string ("even");
- staticpro (&Qeven);
- QCflowcontrol = intern_c_string (":flowcontrol");
- staticpro (&QCflowcontrol);
- Qhw = intern_c_string ("hw");
- staticpro (&Qhw);
- Qsw = intern_c_string ("sw");
- staticpro (&Qsw);
- QCsummary = intern_c_string (":summary");
- staticpro (&QCsummary);
-
- Qreal = intern_c_string ("real");
- staticpro (&Qreal);
- Qnetwork = intern_c_string ("network");
- staticpro (&Qnetwork);
- Qserial = intern_c_string ("serial");
- staticpro (&Qserial);
- QCbuffer = intern_c_string (":buffer");
- staticpro (&QCbuffer);
- QChost = intern_c_string (":host");
- staticpro (&QChost);
- QCservice = intern_c_string (":service");
- staticpro (&QCservice);
- QClocal = intern_c_string (":local");
- staticpro (&QClocal);
- QCremote = intern_c_string (":remote");
- staticpro (&QCremote);
- QCcoding = intern_c_string (":coding");
- staticpro (&QCcoding);
- QCserver = intern_c_string (":server");
- staticpro (&QCserver);
- QCnowait = intern_c_string (":nowait");
- staticpro (&QCnowait);
- QCsentinel = intern_c_string (":sentinel");
- staticpro (&QCsentinel);
- QClog = intern_c_string (":log");
- staticpro (&QClog);
- QCnoquery = intern_c_string (":noquery");
- staticpro (&QCnoquery);
- QCstop = intern_c_string (":stop");
- staticpro (&QCstop);
- QCoptions = intern_c_string (":options");
- staticpro (&QCoptions);
- QCplist = intern_c_string (":plist");
- staticpro (&QCplist);
-
- Qlast_nonmenu_event = intern_c_string ("last-nonmenu-event");
- staticpro (&Qlast_nonmenu_event);
+ DEFSYM (Qipv6, "ipv6");
+#endif
+ DEFSYM (Qdatagram, "datagram");
+ DEFSYM (Qseqpacket, "seqpacket");
+
+ DEFSYM (QCport, ":port");
+ DEFSYM (QCspeed, ":speed");
+ DEFSYM (QCprocess, ":process");
+
+ DEFSYM (QCbytesize, ":bytesize");
+ DEFSYM (QCstopbits, ":stopbits");
+ DEFSYM (QCparity, ":parity");
+ DEFSYM (Qodd, "odd");
+ DEFSYM (Qeven, "even");
+ DEFSYM (QCflowcontrol, ":flowcontrol");
+ DEFSYM (Qhw, "hw");
+ DEFSYM (Qsw, "sw");
+ DEFSYM (QCsummary, ":summary");
+
+ DEFSYM (Qreal, "real");
+ DEFSYM (Qnetwork, "network");
+ DEFSYM (Qserial, "serial");
+ DEFSYM (QCbuffer, ":buffer");
+ DEFSYM (QChost, ":host");
+ DEFSYM (QCservice, ":service");
+ DEFSYM (QClocal, ":local");
+ DEFSYM (QCremote, ":remote");
+ DEFSYM (QCcoding, ":coding");
+ DEFSYM (QCserver, ":server");
+ DEFSYM (QCnowait, ":nowait");
+ DEFSYM (QCsentinel, ":sentinel");
+ DEFSYM (QClog, ":log");
+ DEFSYM (QCnoquery, ":noquery");
+ DEFSYM (QCstop, ":stop");
+ DEFSYM (QCoptions, ":options");
+ DEFSYM (QCplist, ":plist");
+
+ DEFSYM (Qlast_nonmenu_event, "last-nonmenu-event");
staticpro (&Vprocess_alist);
#ifdef SIGCHLD
#endif /* subprocesses */
- QCname = intern_c_string (":name");
- staticpro (&QCname);
- QCtype = intern_c_string (":type");
- staticpro (&QCtype);
-
- Qeuid = intern_c_string ("euid");
- staticpro (&Qeuid);
- Qegid = intern_c_string ("egid");
- staticpro (&Qegid);
- Quser = intern_c_string ("user");
- staticpro (&Quser);
- Qgroup = intern_c_string ("group");
- staticpro (&Qgroup);
- Qcomm = intern_c_string ("comm");
- staticpro (&Qcomm);
- Qstate = intern_c_string ("state");
- staticpro (&Qstate);
- Qppid = intern_c_string ("ppid");
- staticpro (&Qppid);
- Qpgrp = intern_c_string ("pgrp");
- staticpro (&Qpgrp);
- Qsess = intern_c_string ("sess");
- staticpro (&Qsess);
- Qttname = intern_c_string ("ttname");
- staticpro (&Qttname);
- Qtpgid = intern_c_string ("tpgid");
- staticpro (&Qtpgid);
- Qminflt = intern_c_string ("minflt");
- staticpro (&Qminflt);
- Qmajflt = intern_c_string ("majflt");
- staticpro (&Qmajflt);
- Qcminflt = intern_c_string ("cminflt");
- staticpro (&Qcminflt);
- Qcmajflt = intern_c_string ("cmajflt");
- staticpro (&Qcmajflt);
- Qutime = intern_c_string ("utime");
- staticpro (&Qutime);
- Qstime = intern_c_string ("stime");
- staticpro (&Qstime);
- Qtime = intern_c_string ("time");
- staticpro (&Qtime);
- Qcutime = intern_c_string ("cutime");
- staticpro (&Qcutime);
- Qcstime = intern_c_string ("cstime");
- staticpro (&Qcstime);
- Qctime = intern_c_string ("ctime");
- staticpro (&Qctime);
- Qpri = intern_c_string ("pri");
- staticpro (&Qpri);
- Qnice = intern_c_string ("nice");
- staticpro (&Qnice);
- Qthcount = intern_c_string ("thcount");
- staticpro (&Qthcount);
- Qstart = intern_c_string ("start");
- staticpro (&Qstart);
- Qvsize = intern_c_string ("vsize");
- staticpro (&Qvsize);
- Qrss = intern_c_string ("rss");
- staticpro (&Qrss);
- Qetime = intern_c_string ("etime");
- staticpro (&Qetime);
- Qpcpu = intern_c_string ("pcpu");
- staticpro (&Qpcpu);
- Qpmem = intern_c_string ("pmem");
- staticpro (&Qpmem);
- Qargs = intern_c_string ("args");
- staticpro (&Qargs);
+ DEFSYM (QCname, ":name");
+ DEFSYM (QCtype, ":type");
+
+ DEFSYM (Qeuid, "euid");
+ DEFSYM (Qegid, "egid");
+ DEFSYM (Quser, "user");
+ DEFSYM (Qgroup, "group");
+ DEFSYM (Qcomm, "comm");
+ DEFSYM (Qstate, "state");
+ DEFSYM (Qppid, "ppid");
+ DEFSYM (Qpgrp, "pgrp");
+ DEFSYM (Qsess, "sess");
+ DEFSYM (Qttname, "ttname");
+ DEFSYM (Qtpgid, "tpgid");
+ DEFSYM (Qminflt, "minflt");
+ DEFSYM (Qmajflt, "majflt");
+ DEFSYM (Qcminflt, "cminflt");
+ DEFSYM (Qcmajflt, "cmajflt");
+ DEFSYM (Qutime, "utime");
+ DEFSYM (Qstime, "stime");
+ DEFSYM (Qtime, "time");
+ DEFSYM (Qcutime, "cutime");
+ DEFSYM (Qcstime, "cstime");
+ DEFSYM (Qctime, "ctime");
+ DEFSYM (Qpri, "pri");
+ DEFSYM (Qnice, "nice");
+ DEFSYM (Qthcount, "thcount");
+ DEFSYM (Qstart, "start");
+ DEFSYM (Qvsize, "vsize");
+ DEFSYM (Qrss, "rss");
+ DEFSYM (Qetime, "etime");
+ DEFSYM (Qpcpu, "pcpu");
+ DEFSYM (Qpmem, "pmem");
+ DEFSYM (Qargs, "args");
DEFVAR_BOOL ("delete-exited-processes", delete_exited_processes,
doc: /* *Non-nil means delete processes immediately when they exit.
defsubr (&Sprocess_contact);
defsubr (&Sprocess_plist);
defsubr (&Sset_process_plist);
- defsubr (&Slist_processes);
defsubr (&Sprocess_list);
defsubr (&Sstart_process);
defsubr (&Sserial_process_configure);
defsubr (&Sset_network_process_option);
defsubr (&Smake_network_process);
defsubr (&Sformat_network_address);
-#if defined(HAVE_NET_IF_H)
+#if defined (HAVE_NET_IF_H)
#ifdef SIOCGIFCONF
defsubr (&Snetwork_interface_list);
#endif
-#if defined(SIOCGIFADDR) || defined(SIOCGIFHWADDR) || defined(SIOCGIFFLAGS)
+#if defined (SIOCGIFADDR) || defined (SIOCGIFHWADDR) || defined (SIOCGIFFLAGS)
defsubr (&Snetwork_interface_info);
#endif
-#endif /* defined(HAVE_NET_IF_H) */
+#endif /* defined (HAVE_NET_IF_H) */
#ifdef DATAGRAM_SOCKETS
defsubr (&Sprocess_datagram_address);
defsubr (&Sset_process_datagram_address);