diff options
Diffstat (limited to 'src/process.c')
-rw-r--r-- | src/process.c | 582 |
1 files changed, 295 insertions, 287 deletions
diff --git a/src/process.c b/src/process.c index 5b16af02908..1d935ba8a3e 100644 --- a/src/process.c +++ b/src/process.c @@ -140,12 +140,6 @@ extern int sys_select (int, fd_set *, fd_set *, fd_set *, #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) # pragma GCC diagnostic ignored "-Wstrict-overflow" #endif - -Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname, Qtpgid; -Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime, Qcstime; -Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs; -Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime; -Lisp_Object QCname, QCtype; /* True if keyboard input is on hold, zero otherwise. */ @@ -191,27 +185,6 @@ process_socket (int domain, int type, int protocol) # define socket(domain, type, protocol) process_socket (domain, type, protocol) #endif -Lisp_Object Qprocessp; -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 -static Lisp_Object Qipv6; -#endif -static Lisp_Object QCport, QCprocess; -Lisp_Object QCspeed; -Lisp_Object QCbytesize, QCstopbits, QCparity, Qodd, Qeven; -Lisp_Object QCflowcontrol, Qhw, Qsw, QCsummary; -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; -static Lisp_Object Qinternal_default_process_sentinel; -static Lisp_Object Qinternal_default_process_filter; - #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork)) #define NETCONN1_P(p) (EQ (p->type, Qnetwork)) #define SERIALCONN_P(p) (EQ (XPROCESS (p)->type, Qserial)) @@ -227,8 +200,9 @@ static EMACS_INT update_tick; /* Only W32 has this, it really means that select can't take write mask. */ #ifdef BROKEN_NON_BLOCKING_CONNECT #undef NON_BLOCKING_CONNECT -#define SELECT_CANT_DO_WRITE_MASK +enum { SELECT_CAN_DO_WRITE_MASK = false }; #else +enum { SELECT_CAN_DO_WRITE_MASK = true }; #ifndef NON_BLOCKING_CONNECT #ifdef HAVE_SELECT #if defined (HAVE_GETPEERNAME) || defined (GNU_LINUX) @@ -284,17 +258,11 @@ static void create_process (Lisp_Object, char **, Lisp_Object); static bool keyboard_bit_set (fd_set *); #endif static void deactivate_process (Lisp_Object); -static void status_notify (struct Lisp_Process *); +static int status_notify (struct Lisp_Process *, struct Lisp_Process *); static int read_process_output (Lisp_Object, int); static void handle_child_signal (int); static void create_pty (Lisp_Object); -/* 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 -#define POLL_FOR_INPUT -#endif - static Lisp_Object get_process (register Lisp_Object name); static void exec_sentinel (Lisp_Object proc, Lisp_Object reason); @@ -331,10 +299,10 @@ static int max_process_desc; /* The largest descriptor currently in use for input; -1 if none. */ static int max_input_desc; -/* Indexed by descriptor, gives the process (if any) for that descriptor */ +/* Indexed by descriptor, gives the process (if any) for that descriptor. */ static Lisp_Object chan_process[FD_SETSIZE]; -/* Alist of elements (NAME . PROCESS) */ +/* Alist of elements (NAME . PROCESS). */ static Lisp_Object Vprocess_alist; /* Buffered-ahead input char from process, indexed by channel. @@ -454,6 +422,11 @@ pset_write_queue (struct Lisp_Process *p, Lisp_Object val) } +static Lisp_Object +make_lisp_proc (struct Lisp_Process *p) +{ + return make_lisp_ptr (p, Lisp_Vectorlike); +} static struct fd_callback_data { @@ -461,7 +434,7 @@ static struct fd_callback_data void *data; #define FOR_READ 1 #define FOR_WRITE 2 - int condition; /* mask of the defines above. */ + int condition; /* Mask of the defines above. */ } fd_callback_info[FD_SETSIZE]; @@ -471,7 +444,6 @@ static struct fd_callback_data void add_read_fd (int fd, fd_callback func, void *data) { - eassert (fd < FD_SETSIZE); add_keyboard_wait_descriptor (fd); fd_callback_info[fd].func = func; @@ -484,7 +456,6 @@ add_read_fd (int fd, fd_callback func, void *data) void delete_read_fd (int fd) { - eassert (fd < FD_SETSIZE); delete_keyboard_wait_descriptor (fd); fd_callback_info[fd].condition &= ~FOR_READ; @@ -501,7 +472,6 @@ delete_read_fd (int fd) void add_write_fd (int fd, fd_callback func, void *data) { - eassert (fd < FD_SETSIZE); FD_SET (fd, &write_mask); if (fd > max_input_desc) max_input_desc = fd; @@ -532,7 +502,6 @@ delete_input_desc (int fd) void delete_write_fd (int fd) { - eassert (fd < FD_SETSIZE); FD_CLR (fd, &write_mask); fd_callback_info[fd].condition &= ~FOR_WRITE; if (fd_callback_info[fd].condition == 0) @@ -608,7 +577,7 @@ status_message (struct Lisp_Process *p) Lisp_Object symbol; int code; bool coredump; - Lisp_Object string, string2; + Lisp_Object string; decode_status (status, &symbol, &code, &coredump); @@ -632,8 +601,8 @@ status_message (struct Lisp_Process *p) if (c1 != c2) Faset (string, make_number (0), make_number (c2)); } - string2 = build_string (coredump ? " (core dumped)\n" : "\n"); - return concat2 (string, string2); + AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n"); + return concat2 (string, suffix); } else if (EQ (symbol, Qexit)) { @@ -641,17 +610,17 @@ status_message (struct Lisp_Process *p) return build_string (code == 0 ? "deleted\n" : "connection broken by remote peer\n"); if (code == 0) return build_string ("finished\n"); + AUTO_STRING (prefix, "exited abnormally with code "); string = Fnumber_to_string (make_number (code)); - string2 = build_string (coredump ? " (core dumped)\n" : "\n"); - return concat3 (build_string ("exited abnormally with code "), - string, string2); + AUTO_STRING (suffix, coredump ? " (core dumped)\n" : "\n"); + return concat3 (prefix, string, suffix); } else if (EQ (symbol, Qfailed)) { + AUTO_STRING (prefix, "failed with code "); string = Fnumber_to_string (make_number (code)); - string2 = build_string ("\n"); - return concat3 (build_string ("failed with code "), - string, string2); + AUTO_STRING (suffix, "\n"); + return concat3 (prefix, string, suffix); } else return Fcopy_sequence (Fsymbol_name (symbol)); @@ -700,8 +669,8 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) have a race condition between the PTY_OPEN and here. */ fcntl (fd, F_SETFD, FD_CLOEXEC); #endif - /* check to make certain that both sides are available - this avoids a nasty yet stupid bug in rlogins */ + /* Check to make certain that both sides are available + this avoids a nasty yet stupid bug in rlogins. */ #ifdef PTY_TTY_NAME_SPRINTF PTY_TTY_NAME_SPRINTF #else @@ -723,7 +692,15 @@ allocate_pty (char pty_name[PTY_NAME_SIZE]) #endif /* HAVE_PTYS */ return -1; } - + +/* Allocate basically initialized process. */ + +static struct Lisp_Process * +allocate_process (void) +{ + return ALLOCATE_ZEROED_PSEUDOVECTOR (struct Lisp_Process, pid, PVEC_PROCESS); +} + static Lisp_Object make_process (Lisp_Object name) { @@ -873,7 +850,7 @@ nil, indicating the current buffer's process. */) { pset_status (p, list2 (Qexit, make_number (0))); p->tick = ++process_tick; - status_notify (p); + status_notify (p, NULL); redisplay_preserve_echo_area (13); } else @@ -893,7 +870,7 @@ nil, indicating the current buffer's process. */) pset_status (p, list2 (Qsignal, make_number (SIGKILL))); p->tick = ++process_tick; - status_notify (p); + status_notify (p, NULL); redisplay_preserve_echo_area (13); } } @@ -1314,30 +1291,34 @@ Returns nil if format of ADDRESS is invalid. */) ptrdiff_t size = p->header.size; Lisp_Object args[10]; int nargs, i; + char const *format; if (size == 4 || (size == 5 && !NILP (omit_port))) { - args[0] = build_string ("%d.%d.%d.%d"); + format = "%d.%d.%d.%d"; nargs = 4; } else if (size == 5) { - args[0] = build_string ("%d.%d.%d.%d:%d"); + format = "%d.%d.%d.%d:%d"; nargs = 5; } else if (size == 8 || (size == 9 && !NILP (omit_port))) { - args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); + format = "%x:%x:%x:%x:%x:%x:%x:%x"; nargs = 8; } else if (size == 9) { - args[0] = build_string ("[%x:%x:%x:%x:%x:%x:%x:%x]:%d"); + format = "[%x:%x:%x:%x:%x:%x:%x:%x]:%d"; nargs = 9; } else return Qnil; + AUTO_STRING (format_obj, format); + args[0] = format_obj; + for (i = 0; i < nargs; i++) { if (! RANGED_INTEGERP (0, p->contents[i], 65535)) @@ -1348,18 +1329,16 @@ Returns nil if format of ADDRESS is invalid. */) && XINT (p->contents[i]) > 255) return Qnil; - args[i+1] = p->contents[i]; + args[i + 1] = p->contents[i]; } - return Fformat (nargs+1, args); + return Fformat (nargs + 1, args); } if (CONSP (address)) { - Lisp_Object args[2]; - args[0] = build_string ("<Family %d>"); - args[1] = Fcar (address); - return Fformat (2, args); + AUTO_STRING (format, "<Family %d>"); + return CALLN (Fformat, format, Fcar (address)); } return Qnil; @@ -1398,9 +1377,10 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) (ptrdiff_t nargs, Lisp_Object *args) { Lisp_Object buffer, name, program, proc, current_dir, tem; - register unsigned char **new_argv; + unsigned char **new_argv; ptrdiff_t i; ptrdiff_t count = SPECPDL_INDEX (); + USE_SAFE_ALLOCA; buffer = args[1]; if (!NILP (buffer)) @@ -1476,7 +1456,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) val = Vcoding_system_for_read; if (NILP (val)) { - args2 = alloca ((nargs + 1) * sizeof *args2); + SAFE_ALLOCA_LISP (args2, nargs + 1); args2[0] = Qstart_process; for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; GCPRO2 (proc, current_dir); @@ -1495,7 +1475,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) { if (EQ (coding_systems, Qt)) { - args2 = alloca ((nargs + 1) * sizeof *args2); + SAFE_ALLOCA_LISP (args2, nargs + 1); args2[0] = Qstart_process; for (i = 0; i < nargs; i++) args2[i + 1] = args[i]; GCPRO2 (proc, current_dir); @@ -1550,11 +1530,8 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) tem = program; } - /* If program file name starts with /: for quoting a magic name, - discard that. */ - if (SBYTES (tem) > 2 && SREF (tem, 0) == '/' - && SREF (tem, 1) == ':') - tem = Fsubstring (tem, make_number (2), Qnil); + /* Remove "/:" from TEM. */ + tem = remove_slash_colon (tem); { Lisp_Object arg_encoding = Qnil; @@ -1590,7 +1567,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) /* Now that everything is encoded we can collect the strings into NEW_ARGV. */ - new_argv = alloca ((nargs - 1) * sizeof *new_argv); + SAFE_NALLOCA (new_argv, 1, nargs - 1); new_argv[nargs - 2] = 0; for (i = nargs - 2; i-- != 0; ) @@ -1604,6 +1581,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) else create_pty (proc); + SAFE_FREE (); return unbind_to (count, proc); } @@ -1666,6 +1644,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) bool pty_flag = 0; char pty_name[PTY_NAME_SIZE]; Lisp_Object lisp_pty_name = Qnil; + sigset_t oldset; inchannel = outchannel = -1; @@ -1727,11 +1706,11 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) if (inchannel > max_process_desc) max_process_desc = inchannel; - /* This may signal an error. */ + /* This may signal an error. */ setup_process_coding_systems (process); block_input (); - block_child_signal (); + block_child_signal (&oldset); #ifndef WINDOWSNT /* vfork, and prevent local vars from being clobbered by the vfork. */ @@ -1855,7 +1834,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) signal (SIGPIPE, SIG_DFL); /* Stop blocking SIGCHLD in the child. */ - unblock_child_signal (); + unblock_child_signal (&oldset); if (pty_flag) child_setup_tty (xforkout); @@ -1874,7 +1853,7 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir) p->alive = 1; /* Stop blocking in the parent. */ - unblock_child_signal (); + unblock_child_signal (&oldset); unblock_input (); if (pid < 0) @@ -1969,9 +1948,6 @@ create_pty (Lisp_Object process) /* Convert an internal struct sockaddr to a lisp object (vector or string). The address family of sa is not included in the result. */ -#ifndef WINDOWSNT -static -#endif Lisp_Object conv_sockaddr_to_lisp (struct sockaddr *sa, int len) { @@ -2003,7 +1979,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr; - len = sizeof (sin6->sin6_addr)/2 + 1; + len = sizeof (sin6->sin6_addr) / 2 + 1; address = Fmake_vector (make_number (len), Qnil); p = XVECTOR (address); p->contents[--len] = make_number (ntohs (sin6->sin6_port)); @@ -2024,11 +2000,11 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, int len) terminator, however. */ if (name_length > 0 && sockun->sun_path[0] != '\0') { - const char* terminator = - memchr (sockun->sun_path, '\0', name_length); + const char *terminator + = memchr (sockun->sun_path, '\0', name_length); if (terminator) - name_length = terminator - (const char*) sockun->sun_path; + name_length = terminator - (const char *) sockun->sun_path; } return make_unibyte_string (sockun->sun_path, name_length); @@ -2085,8 +2061,10 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp) && VECTORP (XCDR (address))) { struct sockaddr *sa; - *familyp = XINT (XCAR (address)); p = XVECTOR (XCDR (address)); + if (MAX_ALLOCA - sizeof sa->sa_family < p->header.size) + return 0; + *familyp = XINT (XCAR (address)); return p->header.size + sizeof (sa->sa_family); } return 0; @@ -2212,14 +2190,14 @@ Returns nil upon error setting address, ADDRESS otherwise. */) static const struct socket_options { /* The name of this option. Should be lowercase version of option - name without SO_ prefix. */ + name without SO_ prefix. */ const char *name; - /* Option level SOL_... */ + /* Option level SOL_... */ int optlevel; - /* Option number SO_... */ + /* Option number SO_... */ int optnum; enum { SOPT_UNKNOWN, SOPT_BOOL, SOPT_INT, SOPT_IFNAME, SOPT_LINGER } opttype; - enum { OPIX_NONE=0, OPIX_MISC=1, OPIX_REUSEADDR=2 } optbit; + enum { OPIX_NONE = 0, OPIX_MISC = 1, OPIX_REUSEADDR = 2 } optbit; } socket_options[] = { #ifdef SO_BINDTODEVICE @@ -2295,7 +2273,7 @@ set_socket_option (int s, Lisp_Object opt, Lisp_Object val) #ifdef SO_BINDTODEVICE case SOPT_IFNAME: { - char devname[IFNAMSIZ+1]; + char devname[IFNAMSIZ + 1]; /* This is broken, at least in the Linux 2.4 kernel. To unbind, the arg must be a zero integer, not the empty string. @@ -2672,7 +2650,7 @@ usage: (make-serial-process &rest ARGS) */) exactly like a normal process when reading and writing. Primary differences are in status display and process deletion. A network connection has no PID; you cannot signal it. All you can do is - stop/continue it and deactivate/close it via delete-process */ + stop/continue it and deactivate/close it via delete-process. */ DEFUN ("make-network-process", Fmake_network_process, Smake_network_process, 0, MANY, 0, @@ -2858,7 +2836,7 @@ usage: (make-network-process &rest ARGS) */) struct gcpro gcpro1; ptrdiff_t count = SPECPDL_INDEX (); ptrdiff_t count1; - Lisp_Object QCaddress; /* one of QClocal or QCremote */ + Lisp_Object colon_address; /* Either QClocal or QCremote. */ Lisp_Object tem; Lisp_Object name, buffer, host, service, address; Lisp_Object filter, sentinel; @@ -2876,7 +2854,7 @@ usage: (make-network-process &rest ARGS) */) GCPRO1 (contact); #ifdef WINDOWSNT - /* Ensure socket support is loaded if available. */ + /* Ensure socket support is loaded if available. */ init_winsock (TRUE); #endif @@ -2906,8 +2884,8 @@ usage: (make-network-process &rest ARGS) */) backlog = XINT (tem); } - /* Make QCaddress an alias for :local (server) or :remote (client). */ - QCaddress = is_server ? QClocal : QCremote; + /* Make colon_address an alias for :local (server) or :remote (client). */ + colon_address = is_server ? QClocal : QCremote; /* :nowait BOOL */ if (!is_server && socktype != SOCK_DGRAM @@ -2934,7 +2912,7 @@ usage: (make-network-process &rest ARGS) */) res = &ai; /* :local ADDRESS or :remote ADDRESS */ - address = Fplist_get (contact, QCaddress); + address = Fplist_get (contact, colon_address); if (!NILP (address)) { host = service = Qnil; @@ -2983,7 +2961,7 @@ usage: (make-network-process &rest ARGS) */) { if (EQ (host, Qlocal)) /* Depending on setup, "localhost" may map to different IPv4 and/or - IPv6 addresses, so it's better to be explicit. (Bug#6781) */ + IPv6 addresses, so it's better to be explicit (Bug#6781). */ host = build_string ("127.0.0.1"); CHECK_STRING (host); } @@ -3003,7 +2981,7 @@ usage: (make-network-process &rest ARGS) */) address_un.sun_family = AF_LOCAL; if (sizeof address_un.sun_path <= SBYTES (service)) error ("Service name too long"); - strcpy (address_un.sun_path, SSDATA (service)); + lispstpcpy (address_un.sun_path, service); ai.ai_addr = (struct sockaddr *) &address_un; ai.ai_addrlen = sizeof address_un; goto open_socket; @@ -3115,7 +3093,7 @@ usage: (make-network-process &rest ARGS) */) address_in.sin_family = family; } else - /* Attempt to interpret host as numeric inet address */ + /* Attempt to interpret host as numeric inet address. */ { unsigned long numeric_addr; numeric_addr = inet_addr (SSDATA (host)); @@ -3181,8 +3159,8 @@ usage: (make-network-process &rest ARGS) */) /* Parse network options in the arg list. We simply ignore anything which isn't a known option (including other keywords). An error is signaled if setting a known option fails. */ - for (optn = optbits = 0; optn < nargs-1; optn += 2) - optbits |= set_socket_option (s, args[optn], args[optn+1]); + for (optn = optbits = 0; optn < nargs - 1; optn += 2) + optbits |= set_socket_option (s, args[optn], args[optn + 1]); if (is_server) { @@ -3253,7 +3231,7 @@ usage: (make-network-process &rest ARGS) */) { /* Unlike most other syscalls connect() cannot be called again. (That would return EALREADY.) The proper way to - wait for completion is pselect(). */ + wait for completion is pselect(). */ int sc; socklen_t len; fd_set fdset; @@ -3321,7 +3299,7 @@ usage: (make-network-process &rest ARGS) */) memcpy (datagram_address[s].sa, lres->ai_addr, lres->ai_addrlen); } #endif - contact = Fplist_put (contact, QCaddress, + contact = Fplist_put (contact, colon_address, conv_sockaddr_to_lisp (lres->ai_addr, lres->ai_addrlen)); #ifdef HAVE_GETSOCKNAME if (!is_server) @@ -3444,7 +3422,7 @@ usage: (make-network-process &rest ARGS) */) struct gcpro gcpro1; /* Qt denotes we have not yet called Ffind_operation_coding_system. */ Lisp_Object coding_systems = Qt; - Lisp_Object fargs[5], val; + Lisp_Object val; if (!NILP (tem)) { @@ -3467,10 +3445,10 @@ usage: (make-network-process &rest ARGS) */) coding_systems = Qnil; else { - fargs[0] = Qopen_network_stream, fargs[1] = name, - fargs[2] = buffer, fargs[3] = host, fargs[4] = service; GCPRO1 (proc); - coding_systems = Ffind_operation_coding_system (5, fargs); + coding_systems = CALLN (Ffind_operation_coding_system, + Qopen_network_stream, name, buffer, + host, service); UNGCPRO; } if (CONSP (coding_systems)) @@ -3500,10 +3478,10 @@ usage: (make-network-process &rest ARGS) */) coding_systems = Qnil; else { - fargs[0] = Qopen_network_stream, fargs[1] = name, - fargs[2] = buffer, fargs[3] = host, fargs[4] = service; GCPRO1 (proc); - coding_systems = Ffind_operation_coding_system (5, fargs); + coding_systems = CALLN (Ffind_operation_coding_system, + Qopen_network_stream, name, buffer, + host, service); UNGCPRO; } } @@ -3631,7 +3609,7 @@ static const struct ifflag_def ifflag_table[] = { #endif #ifdef IFF_NOTRAILERS #ifdef NS_IMPL_COCOA - /* Really means smart, notrailers is obsolete */ + /* Really means smart, notrailers is obsolete. */ { IFF_NOTRAILERS, "smart" }, #else { IFF_NOTRAILERS, "notrailers" }, @@ -3659,19 +3637,19 @@ static const struct ifflag_def ifflag_table[] = { { IFF_DYNAMIC, "dynamic" }, #endif #ifdef IFF_OACTIVE - { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress */ + { IFF_OACTIVE, "oactive" }, /* OpenBSD: transmission in progress. */ #endif #ifdef IFF_SIMPLEX - { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions */ + { IFF_SIMPLEX, "simplex" }, /* OpenBSD: can't hear own transmissions. */ #endif #ifdef IFF_LINK0 - { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit */ + { IFF_LINK0, "link0" }, /* OpenBSD: per link layer defined bit. */ #endif #ifdef IFF_LINK1 - { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit */ + { IFF_LINK1, "link1" }, /* OpenBSD: per link layer defined bit. */ #endif #ifdef IFF_LINK2 - { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit */ + { IFF_LINK2, "link2" }, /* OpenBSD: per link layer defined bit. */ #endif { 0, 0 } }; @@ -3694,7 +3672,7 @@ network_interface_info (Lisp_Object ifname) if (sizeof rq.ifr_name <= SBYTES (ifname)) error ("interface name too long"); - strcpy (rq.ifr_name, SSDATA (ifname)); + lispstpcpy (rq.ifr_name, ifname); s = socket (AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (s < 0) @@ -3862,6 +3840,18 @@ Data that is unavailable is returned as nil. */) #endif } +/* If program file NAME starts with /: for quoting a magic + name, remove that, preserving the multibyteness of NAME. */ + +Lisp_Object +remove_slash_colon (Lisp_Object name) +{ + return + ((SBYTES (name) > 2 && SREF (name, 0) == '/' && SREF (name, 1) == ':') + ? make_specified_string (SSDATA (name) + 2, SCHARS (name) - 2, + SBYTES (name) - 2, STRING_MULTIBYTE (name)) + : name); +} /* Turn off input and output for process PROC. */ @@ -3887,7 +3877,7 @@ deactivate_process (Lisp_Object proc) } #endif - /* Beware SIGCHLD hereabouts. */ + /* Beware SIGCHLD hereabouts. */ for (i = 0; i < PROCESS_OPEN_FDS; i++) close_process_fd (&p->open_fd[i]); @@ -3936,19 +3926,20 @@ DEFUN ("accept-process-output", Faccept_process_output, Saccept_process_output, 0, 4, 0, doc: /* Allow any pending output from subprocesses to be read by Emacs. It is given to their filter functions. -Non-nil arg PROCESS means do not return until some output has been received -from PROCESS. +Optional argument PROCESS means do not return until output has been +received from PROCESS. -Non-nil second arg SECONDS and third arg MILLISEC are number of seconds -and milliseconds to wait; return after that much time whether or not -there is any subprocess output. If SECONDS is a floating point number, +Optional second argument SECONDS and third argument MILLISEC +specify a timeout; return after that much time even if there is +no subprocess output. If SECONDS is a floating point number, it specifies a fractional number of seconds to wait. The MILLISEC argument is obsolete and should be avoided. -If optional fourth arg JUST-THIS-ONE is non-nil, only accept output -from PROCESS, suspending reading output from other processes. +If optional fourth argument JUST-THIS-ONE is non-nil, accept output +from PROCESS only, suspending reading output from other processes. If JUST-THIS-ONE is an integer, don't run any timers either. -Return non-nil if we received any output before the timeout expired. */) +Return non-nil if we received any output from PROCESS (or, if PROCESS +is nil, from any process) before the timeout expired. */) (register Lisp_Object process, Lisp_Object seconds, Lisp_Object millisec, Lisp_Object just_this_one) { intmax_t secs; @@ -4000,12 +3991,13 @@ Return non-nil if we received any output before the timeout expired. */) nsecs = 0; return - (wait_reading_process_output (secs, nsecs, 0, 0, - Qnil, - !NILP (process) ? XPROCESS (process) : NULL, - NILP (just_this_one) ? 0 : - !INTEGERP (just_this_one) ? 1 : -1) - ? Qt : Qnil); + ((wait_reading_process_output (secs, nsecs, 0, 0, + Qnil, + !NILP (process) ? XPROCESS (process) : NULL, + (NILP (just_this_one) ? 0 + : !INTEGERP (just_this_one) ? 1 : -1)) + <= 0) + ? Qnil : Qt); } /* Accept a connection for server process SERVER on CHANNEL. */ @@ -4017,7 +4009,7 @@ server_accept_connection (Lisp_Object server, int channel) { Lisp_Object proc, caller, name, buffer; Lisp_Object contact, host, service; - struct Lisp_Process *ps= XPROCESS (server); + struct Lisp_Process *ps = XPROCESS (server); struct Lisp_Process *p; int s; union u_sockaddr { @@ -4069,20 +4061,15 @@ server_accept_connection (Lisp_Object server, int channel) { case AF_INET: { - Lisp_Object args[5]; unsigned char *ip = (unsigned char *)&saddr.in.sin_addr.s_addr; - args[0] = build_string ("%d.%d.%d.%d"); - args[1] = make_number (*ip++); - args[2] = make_number (*ip++); - args[3] = make_number (*ip++); - args[4] = make_number (*ip++); - host = Fformat (5, args); - service = make_number (ntohs (saddr.in.sin_port)); - args[0] = build_string (" <%s:%d>"); - args[1] = host; - args[2] = service; - caller = Fformat (3, args); + AUTO_STRING (ipv4_format, "%d.%d.%d.%d"); + host = CALLN (Fformat, ipv4_format, + make_number (ip[0]), make_number (ip[1]), + make_number (ip[2]), make_number (ip[3])); + service = make_number (ntohs (saddr.in.sin_port)); + AUTO_STRING (caller_format, " <%s:%d>"); + caller = CALLN (Fformat, caller_format, host, service); } break; @@ -4092,16 +4079,15 @@ server_accept_connection (Lisp_Object server, int channel) Lisp_Object args[9]; uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr; int i; - args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x"); + + AUTO_STRING (ipv6_format, "%x:%x:%x:%x:%x:%x:%x:%x"); + args[0] = ipv6_format; for (i = 0; i < 8; i++) - args[i+1] = make_number (ntohs (ip6[i])); - host = Fformat (9, args); + args[i + 1] = make_number (ntohs (ip6[i])); + host = CALLMANY (Fformat, args); service = make_number (ntohs (saddr.in.sin_port)); - - args[0] = build_string (" <[%s]:%d>"); - args[1] = host; - args[2] = service; - caller = Fformat (3, args); + AUTO_STRING (caller_format, " <[%s]:%d>"); + caller = CALLN (Fformat, caller_format, host, service); } break; #endif @@ -4111,7 +4097,9 @@ server_accept_connection (Lisp_Object server, int channel) #endif default: caller = Fnumber_to_string (make_number (connect_counter)); - caller = concat3 (build_string (" <"), caller, build_string (">")); + AUTO_STRING (space_less_than, " <"); + AUTO_STRING (greater_than, ">"); + caller = concat3 (space_less_than, caller, greater_than); break; } @@ -4208,16 +4196,18 @@ server_accept_connection (Lisp_Object server, int channel) p->inherit_coding_system_flag = (NILP (buffer) ? 0 : ps->inherit_coding_system_flag); + AUTO_STRING (dash, "-"); + AUTO_STRING (nl, "\n"); + Lisp_Object host_string = STRINGP (host) ? host : dash; + if (!NILP (ps->log)) - call3 (ps->log, server, proc, - concat3 (build_string ("accept from "), - (STRINGP (host) ? host : build_string ("-")), - build_string ("\n"))); + { + AUTO_STRING (accept_from, "accept from "); + call3 (ps->log, server, proc, concat3 (accept_from, host_string, nl)); + } - exec_sentinel (proc, - concat3 (build_string ("open from "), - (STRINGP (host) ? host : build_string ("-")), - build_string ("\n"))); + AUTO_STRING (open_from, "open from "); + exec_sentinel (proc, concat3 (open_from, host_string, nl)); } /* This variable is different from waiting_for_input in keyboard.c. @@ -4270,18 +4260,17 @@ wait_reading_process_output_1 (void) (and gobble terminal input into the buffer if any arrives). If WAIT_PROC is specified, wait until something arrives from that - process. The return value is true if we read some input from - that process. + process. If JUST_WAIT_PROC is nonzero, handle only output from WAIT_PROC (suspending output from other processes). A negative value means don't run any timers either. - If WAIT_PROC is specified, then the function returns true if we - received input from that process before the timeout elapsed. - Otherwise, return true if we received input from any process. */ + Return positive if we received input from WAIT_PROC (or from any + process if WAIT_PROC is null), zero if we attempted to receive + input but got none, and negative if we didn't even try. */ -bool +int wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -4296,8 +4285,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, int xerrno; Lisp_Object proc; struct timespec timeout, end_time; - int wait_channel = -1; - bool got_some_input = 0; + int got_some_input = -1; ptrdiff_t count = SPECPDL_INDEX (); FD_ZERO (&Available); @@ -4308,10 +4296,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, && EQ (XCAR (wait_proc->status), Qexit))) message1 ("Blocking call to accept-process-output with quit inhibited!!"); - /* If wait_proc is a process to watch, set wait_channel accordingly. */ - if (wait_proc != NULL) - wait_channel = wait_proc->infd; - record_unwind_protect_int (wait_reading_process_output_unwind, waiting_for_user_input_p); waiting_for_user_input_p = read_kbd; @@ -4334,7 +4318,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { - bool timeout_reduced_for_timers = 0; + bool timeout_reduced_for_timers = false; /* If calling from keyboard input, do not quit since we want to return C-g as an input character. @@ -4348,13 +4332,17 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell))) break; + /* After reading input, vacuum up any leftovers without waiting. */ + if (0 <= got_some_input) + nsecs = -1; + /* Compute time from now till when time limit is up. */ /* Exit if already run out. */ if (nsecs < 0) { /* A negative timeout means gobble output available now - but don't wait at all. */ + but don't wait at all. */ timeout = make_timespec (0, 0); } @@ -4417,7 +4405,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (timespec_cmp (timer_delay, timeout) < 0) { timeout = timer_delay; - timeout_reduced_for_timers = 1; + timeout_reduced_for_timers = true; } } else @@ -4466,7 +4454,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* It's okay for us to do this and then continue with the loop, since timeout has already been zeroed out. */ clear_waiting_for_input (); - status_notify (NULL); + got_some_input = status_notify (NULL, wait_proc); if (do_display) redisplay_preserve_echo_area (13); } } @@ -4476,30 +4464,36 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (wait_proc && wait_proc->raw_status_new) update_status (wait_proc); if (wait_proc + && wait_proc->infd >= 0 && ! EQ (wait_proc->status, Qrun) && ! EQ (wait_proc->status, Qconnect)) { - bool read_some_bytes = 0; + bool read_some_bytes = false; clear_waiting_for_input (); XSETPROCESS (proc, wait_proc); /* Read data from the process, until we exhaust it. */ - while (wait_proc->infd >= 0) + while (true) { int nread = read_process_output (proc, wait_proc->infd); - - if (nread == 0) - break; - - if (nread > 0) - got_some_input = read_some_bytes = 1; - else if (nread == -1 && (errno == EIO || errno == EAGAIN)) - break; + if (nread < 0) + { + if (errno == EIO || errno == EAGAIN) + break; #ifdef EWOULDBLOCK - else if (nread == -1 && EWOULDBLOCK == errno) - break; + if (errno == EWOULDBLOCK) + break; #endif + } + else + { + if (got_some_input < nread) + got_some_input = nread; + if (nread == 0) + break; + read_some_bytes = true; + } } if (read_some_bytes && do_display) redisplay_preserve_echo_area (10); @@ -4507,11 +4501,11 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, break; } - /* Wait till there is something to do */ + /* Wait till there is something to do. */ if (wait_proc && just_wait_proc) { - if (wait_proc->infd < 0) /* Terminated */ + if (wait_proc->infd < 0) /* Terminated. */ break; FD_SET (wait_proc->infd, &Available); check_delay = 0; @@ -4530,12 +4524,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, else Available = input_wait_mask; Writeok = write_mask; -#ifdef SELECT_CANT_DO_WRITE_MASK - check_write = 0; -#else - check_write = 1; -#endif - check_delay = wait_channel >= 0 ? 0 : process_output_delay_count; + check_delay = wait_proc ? 0 : process_output_delay_count; + check_write = SELECT_CAN_DO_WRITE_MASK; } /* If frame size has changed or the window is newly mapped, @@ -4561,6 +4551,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { nfds = read_kbd ? 0 : 1; no_avail = 1; + FD_ZERO (&Available); } if (!no_avail) @@ -4570,7 +4561,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* Set the timeout for adaptive read buffering if any process has non-zero read_output_skip and non-zero read_output_delay, and we are not reading output for a - specific wait_channel. It is not executed if + specific process. It is not executed if Vprocess_adaptive_read_buffering is nil. */ if (process_output_skip && check_delay > 0) { @@ -4632,19 +4623,20 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, { struct Lisp_Process *p = XPROCESS (chan_process[channel]); - if (p && p->gnutls_p && p->gnutls_state && p->infd + if (p && p->gnutls_p && p->gnutls_state && ((emacs_gnutls_record_check_pending (p->gnutls_state)) > 0)) { nfds++; + eassert (p->infd == channel); FD_SET (p->infd, &Available); } } } else { - /* Check this specific channel. */ + /* Check this specific channel. */ if (wait_proc->gnutls_p /* Check for valid process. */ && wait_proc->gnutls_state /* Do we have pending data? */ @@ -4653,6 +4645,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, > 0)) { nfds = 1; + eassert (0 <= wait_proc->infd); /* Set to Available. */ FD_SET (wait_proc->infd, &Available); } @@ -4663,7 +4656,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, xerrno = errno; - /* Make C-g and alarm signals set flags again */ + /* Make C-g and alarm signals set flags again. */ clear_waiting_for_input (); /* If we woke up due to SIGWINCH, actually change size now. */ @@ -4682,28 +4675,22 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, report_file_errno ("Failed select", Qnil, xerrno); } - if (no_avail) - { - FD_ZERO (&Available); - check_write = 0; - } - - /* Check for keyboard input */ + /* Check for keyboard input. */ /* If there is any, return immediately - to give it higher priority than subprocesses */ + to give it higher priority than subprocesses. */ if (read_kbd != 0) { unsigned old_timers_run = timers_run; struct buffer *old_buffer = current_buffer; Lisp_Object old_window = selected_window; - bool leave = 0; + bool leave = false; if (detect_input_pending_run_timers (do_display)) { swallow_events (do_display); if (detect_input_pending_run_timers (do_display)) - leave = 1; + leave = true; } /* If a timer has run, this might have changed buffers @@ -4754,9 +4741,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, handle_input_available_signal (SIGIO); #endif - 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 || ! NILP (wait_for_cell)) @@ -4788,12 +4772,6 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* If waiting for this channel, arrange to return as soon as no more input to be processed. No more waiting. */ - if (wait_channel == channel) - { - wait_channel = -1; - nsecs = -1; - got_some_input = 1; - } proc = chan_process[channel]; if (NILP (proc)) continue; @@ -4809,6 +4787,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, buffered-ahead character if we have one. */ nread = read_process_output (proc, channel); + if ((!wait_proc || wait_proc == XPROCESS (proc)) && got_some_input < nread) + got_some_input = nread; if (nread > 0) { /* Since read_process_output can run a filter, @@ -4933,7 +4913,8 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, status_notify to do it later, it will read input from the process before calling the sentinel. */ exec_sentinel (proc, build_string ("open\n")); - if (!EQ (p->filter, Qt) && !EQ (p->command, Qt)) + if (0 <= p->infd && !EQ (p->filter, Qt) + && !EQ (p->command, Qt)) { FD_SET (p->infd, &input_wait_mask); FD_SET (p->infd, &non_keyboard_wait_mask); @@ -4994,18 +4975,17 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, for decoding. */ static int -read_process_output (Lisp_Object proc, register int channel) +read_process_output (Lisp_Object proc, int channel) { - register ssize_t nbytes; - char *chars; - register struct Lisp_Process *p = XPROCESS (proc); + ssize_t nbytes; + struct Lisp_Process *p = XPROCESS (proc); struct coding_system *coding = proc_decode_coding_system[channel]; int carryover = p->decoding_carryover; - int readmax = 4096; + enum { readmax = 4096 }; ptrdiff_t count = SPECPDL_INDEX (); Lisp_Object odeactivate; + char chars[sizeof coding->carryover + readmax]; - chars = alloca (carryover + readmax); if (carryover) /* See the comment above. */ memcpy (chars, SDATA (p->decoding_buf), carryover); @@ -5155,7 +5135,7 @@ read_and_dispose_of_process_output (struct Lisp_Process *p, char *chars, proc_encode_coding_system[p->outfd] surely points to a valid memory because p->outfd will be changed once EOF is sent to the process. */ - if (NILP (p->encode_coding_system) + if (NILP (p->encode_coding_system) && p->outfd >= 0 && proc_encode_coding_system[p->outfd]) { pset_encode_coding_system @@ -5706,7 +5686,7 @@ return t unconditionally. */) return Qt; } -/* send a signal number SIGNO to PROCESS. +/* Send a signal number SIGNO to PROCESS. If CURRENT_GROUP is t, that means send to the process group that currently owns the terminal being used to communicate with PROCESS. This is used for various commands in shell mode. @@ -5809,11 +5789,11 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, Or perhaps this is vestigial. */ if (gid == -1) no_pgrp = 1; -#else /* ! defined (TIOCGPGRP ) */ +#else /* ! defined (TIOCGPGRP) */ /* Can't select pgrps on this system, so we know that the child itself heads the pgrp. */ gid = p->pid; -#endif /* ! defined (TIOCGPGRP ) */ +#endif /* ! defined (TIOCGPGRP) */ /* If current_group is lambda, and the shell owns the terminal, don't send any signal. */ @@ -5829,36 +5809,31 @@ process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group, p->tick = ++process_tick; if (!nomsg) { - status_notify (NULL); + status_notify (NULL, NULL); redisplay_preserve_echo_area (13); } } #endif +#ifdef TIOCSIGSEND + /* Work around a HP-UX 7.0 bug that mishandles signals to subjobs. + We don't know whether the bug is fixed in later HP-UX versions. */ + if (! NILP (current_group) && ioctl (p->infd, TIOCSIGSEND, signo) != -1) + return; +#endif + /* If we don't have process groups, send the signal to the immediate subprocess. That isn't really right, but it's better than any obvious alternative. */ - if (no_pgrp) - { - kill (p->pid, signo); - return; - } + pid_t pid = no_pgrp ? gid : - gid; - /* gid may be a pid, or minus a pgrp's number */ -#ifdef TIOCSIGSEND - if (!NILP (current_group)) - { - if (ioctl (p->infd, TIOCSIGSEND, signo) == -1) - kill (-gid, signo); - } - else - { - gid = - p->pid; - kill (gid, signo); - } -#else /* ! defined (TIOCSIGSEND) */ - kill (-gid, signo); -#endif /* ! defined (TIOCSIGSEND) */ + /* Do not kill an already-reaped process, as that could kill an + innocent bystander that happens to have the same process ID. */ + sigset_t oldset; + block_child_signal (&oldset); + if (p->alive) + kill (pid, signo); + unblock_child_signal (&oldset); } DEFUN ("interrupt-process", Finterrupt_process, Sinterrupt_process, 0, 2, 0, @@ -6000,8 +5975,8 @@ SIGCODE may be an integer, or a symbol whose name is a signal name. */) Lisp_Object tem = Fget_process (process); if (NILP (tem)) { - Lisp_Object process_number = - string_to_number (SSDATA (process), 10, 1); + Lisp_Object process_number + = string_to_number (SSDATA (process), 10, 1); if (INTEGERP (process_number) || FLOATP (process_number)) tem = process_number; } @@ -6100,8 +6075,8 @@ process has been transmitted to the serial port. */) for communication with the subprocess, call shutdown to cause EOF. (In some old system, shutdown to socketpair doesn't work. Then we just can't win.) */ - if (EQ (p->type, Qnetwork) - || p->infd == old_outfd) + if (0 <= old_outfd + && (EQ (p->type, Qnetwork) || p->infd == old_outfd)) shutdown (old_outfd, 1); #endif close_process_fd (&p->open_fd[WRITE_TO_SUBPROCESS]); @@ -6184,7 +6159,7 @@ static signal_handler_t volatile lib_child_handler; Inc. ** Malloc WARNING: This should never call malloc either directly or - indirectly; if it does, that is a bug */ + indirectly; if it does, that is a bug. */ static void handle_child_signal (int sig) @@ -6257,7 +6232,7 @@ handle_child_signal (int sig) #ifdef NS_IMPL_GNUSTEP /* NSTask in GNUstep sets its child handler each time it is called. So we must re-set ours. */ - catch_child_signal(); + catch_child_signal (); #endif } @@ -6357,14 +6332,20 @@ exec_sentinel (Lisp_Object proc, Lisp_Object reason) /* Report all recent events of a change in process status (either run the sentinel or output a message). This is usually done while Emacs is waiting for keyboard input - but can be done at other times. */ + but can be done at other times. -static void -status_notify (struct Lisp_Process *deleting_process) + Return positive if any input was received from WAIT_PROC (or from + any process if WAIT_PROC is null), zero if input was attempted but + none received, and negative if we didn't even try. */ + +static int +status_notify (struct Lisp_Process *deleting_process, + struct Lisp_Process *wait_proc) { - register Lisp_Object proc; + Lisp_Object proc; Lisp_Object tail, msg; struct gcpro gcpro1, gcpro2; + int got_some_input = -1; tail = Qnil; msg = Qnil; @@ -6394,8 +6375,14 @@ status_notify (struct Lisp_Process *deleting_process) /* Network or serial process not stopped: */ && ! EQ (p->command, Qt) && p->infd >= 0 - && p != deleting_process - && read_process_output (proc, p->infd) > 0); + && p != deleting_process) + { + int nread = read_process_output (proc, p->infd); + if (got_some_input < nread) + got_some_input = nread; + if (nread <= 0) + break; + } /* Get the text to use for the message. */ if (p->raw_status_new) @@ -6427,6 +6414,7 @@ status_notify (struct Lisp_Process *deleting_process) update_mode_lines = 24; /* In case buffers use %s in mode-line-format. */ UNGCPRO; + return got_some_input; } DEFUN ("internal-default-process-sentinel", Finternal_default_process_sentinel, @@ -6562,6 +6550,8 @@ DEFUN ("process-filter-multibyte-p", Fprocess_filter_multibyte_p, CHECK_PROCESS (process); p = XPROCESS (process); + if (p->infd < 0) + return Qnil; coding = proc_decode_coding_system[p->infd]; return (CODING_FOR_UNIBYTE (coding) ? Qnil : Qt); } @@ -6606,7 +6596,7 @@ keyboard_bit_set (fd_set *mask) #else /* not subprocesses */ -/* Defined on msdos.c. */ +/* Defined in msdos.c. */ extern int sys_select (int, fd_set *, fd_set *, fd_set *, struct timespec *, void *); @@ -6638,9 +6628,11 @@ extern int sys_select (int, fd_set *, fd_set *, fd_set *, DO_DISPLAY means redisplay should be done to show subprocess output that arrives. - Return true if we received input from any process. */ + Return positive if we received input from WAIT_PROC (or from any + process if WAIT_PROC is null), zero if we attempted to receive + input but got none, and negative if we didn't even try. */ -bool +int wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, bool do_display, Lisp_Object wait_for_cell, @@ -6672,7 +6664,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, while (1) { - bool timeout_reduced_for_timers = 0; + bool timeout_reduced_for_timers = false; fd_set waitchannels; int xerrno; @@ -6739,7 +6731,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, if (timespec_cmp (timer_delay, timeout) < 0) { timeout = timer_delay; - timeout_reduced_for_timers = 1; + timeout_reduced_for_timers = true; } } } @@ -6772,7 +6764,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, xerrno = errno; - /* Make C-g and alarm signals set flags again */ + /* Make C-g and alarm signals set flags again. */ clear_waiting_for_input (); /* If we woke up due to SIGWINCH, actually change size now. */ @@ -6792,7 +6784,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, report_file_errno ("Failed select", Qnil, xerrno); } - /* Check for keyboard input */ + /* Check for keyboard input. */ if (read_kbd && detect_input_pending_run_timers (do_display)) @@ -6828,7 +6820,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, start_polling (); - return 0; + return -1; } #endif /* not subprocesses */ @@ -6836,12 +6828,32 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd, /* The following functions are needed even if async subprocesses are not supported. Some of them are no-op stubs in that case. */ +#ifdef HAVE_TIMERFD + +/* Add FD, which is a descriptor returned by timerfd_create, + to the set of non-keyboard input descriptors. */ + +void +add_timer_wait_descriptor (int fd) +{ + FD_SET (fd, &input_wait_mask); + FD_SET (fd, &non_keyboard_wait_mask); + FD_SET (fd, &non_process_wait_mask); + fd_callback_info[fd].func = timerfd_callback; + fd_callback_info[fd].data = NULL; + fd_callback_info[fd].condition |= FOR_READ; + if (fd > max_input_desc) + max_input_desc = fd; +} + +#endif /* HAVE_TIMERFD */ + /* Add DESC to the set of keyboard input descriptors. */ void add_keyboard_wait_descriptor (int desc) { -#ifdef subprocesses /* actually means "not MSDOS" */ +#ifdef subprocesses /* Actually means "not MSDOS". */ FD_SET (desc, &input_wait_mask); FD_SET (desc, &non_process_wait_mask); if (desc > max_input_desc) @@ -6932,7 +6944,7 @@ the process output. */) } /* Kill all processes associated with `buffer'. - If `buffer' is nil, kill all processes */ + If `buffer' is nil, kill all processes. */ void kill_buffer_processes (Lisp_Object buffer) @@ -7067,24 +7079,23 @@ integer or floating point values. futz with the SIGCHLD handler, but before Emacs forks any children. This function's caller should block SIGCHLD. */ -#ifndef NS_IMPL_GNUSTEP -static -#endif void catch_child_signal (void) { struct sigaction action, old_action; + sigset_t oldset; emacs_sigaction_init (&action, deliver_child_signal); - block_child_signal (); + block_child_signal (&oldset); sigaction (SIGCHLD, &action, &old_action); - eassert (! (old_action.sa_flags & SA_SIGINFO)); + eassert (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN + || ! (old_action.sa_flags & SA_SIGINFO)); if (old_action.sa_handler != deliver_child_signal) lib_child_handler = (old_action.sa_handler == SIG_DFL || old_action.sa_handler == SIG_IGN ? dummy_handler : old_action.sa_handler); - unblock_child_signal (); + unblock_child_signal (&oldset); } #endif /* subprocesses */ @@ -7212,10 +7223,7 @@ syms_of_process (void) 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); */ + here again. */ DEFSYM (Qopen, "open"); DEFSYM (Qclosed, "closed"); |