X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/edfda78355c5528eee489fa8a7f9c73bf8e734f2..59c4c60fb1b371be5566e44b3fa6cb377001f958:/src/process.c diff --git a/src/process.c b/src/process.c index 87772f34f7..5fb3662532 100644 --- a/src/process.c +++ b/src/process.c @@ -1,7 +1,7 @@ /* Asynchronous subprocess control for GNU Emacs. Copyright (C) 1985, 1986, 1987, 1988, 1993, 1994, 1995, - 1996, 1998, 1999, 2001, 2002, 2003, 2004, - 2005, 2006, 2007, 2008 Free Software Foundation, Inc. + 1996, 1998, 1999, 2001, 2002, 2003, 2004, + 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -41,14 +41,14 @@ along with GNU Emacs. If not, see . */ #ifdef HAVE_INTTYPES_H #include #endif +#ifdef STDC_HEADERS +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif - -#if defined(WINDOWSNT) || defined(UNIX98_PTYS) -#include #include -#endif /* not WINDOWSNT */ #ifdef HAVE_SOCKETS /* TCP connection support, if kernel can do it */ #include @@ -68,11 +68,6 @@ along with GNU Emacs. If not, see . */ #endif #endif /* HAVE_SOCKETS */ -/* TERM is a poor-man's SLIP, used on GNU/Linux. */ -#ifdef TERM -#include -#endif - #if defined(BSD_SYSTEM) #include #if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5) @@ -95,10 +90,6 @@ along with GNU Emacs. If not, see . */ #endif #endif -#ifdef IRIS -#include /* for "minor" */ -#endif /* not IRIS */ - #ifdef HAVE_SYS_WAIT #include #endif @@ -155,6 +146,11 @@ extern Lisp_Object QCfamily; /* QCfilter is defined in keyboard.c. */ extern Lisp_Object QCfilter; +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; + #ifdef HAVE_SOCKETS #define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork)) #define NETCONN1_P(p) (EQ ((p)->type, Qnetwork)) @@ -168,11 +164,7 @@ extern Lisp_Object QCfilter; #endif /* HAVE_SOCKETS */ /* Define first descriptor number available for subprocesses. */ -#ifdef VMS -#define FIRST_PROC_DESC 1 -#else /* Not VMS */ #define FIRST_PROC_DESC 3 -#endif /* Define SIGCHLD as an alias for SIGCLD. There are many conditionals testing SIGCHLD. */ @@ -201,9 +193,6 @@ extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact); #ifndef USE_CRT_DLL extern int errno; #endif -#ifdef VMS -extern char *sys_errlist[]; -#endif #ifndef HAVE_H_ERRNO extern int h_errno; @@ -259,11 +248,6 @@ int update_tick; #endif /* DATAGRAM_SOCKETS */ #endif /* BROKEN_DATAGRAM_SOCKETS */ -#ifdef TERM -#undef NON_BLOCKING_CONNECT -#undef DATAGRAM_SOCKETS -#endif - #if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING) #ifdef EMACS_HAS_USECS #define ADAPTIVE_READ_BUFFERING @@ -542,14 +526,6 @@ allocate_pty () PTY_OPEN; #else /* no PTY_OPEN */ { -# ifdef IRIS - /* Unusual IRIS code */ - *ptyv = emacs_open ("/dev/ptc", O_RDWR | O_NDELAY, 0); - if (fd < 0) - return -1; - if (fstat (fd, &stb) < 0) - return -1; -# else /* not IRIS */ { /* Some systems name their pseudoterminals so that there are gaps in the usual sequence - for example, on HP9000/S700 systems, there are no pseudoterminals with names ending in 'f'. So we wait for @@ -571,7 +547,6 @@ allocate_pty () # else fd = emacs_open (pty_name, O_RDWR | O_NDELAY, 0); # endif -# endif /* not IRIS */ } #endif /* no PTY_OPEN */ @@ -582,16 +557,16 @@ allocate_pty () #ifdef PTY_TTY_NAME_SPRINTF PTY_TTY_NAME_SPRINTF #else - sprintf (pty_name, "/dev/tty%c%x", c, i); + sprintf (pty_name, "/dev/tty%c%x", c, i); #endif /* no PTY_TTY_NAME_SPRINTF */ if (access (pty_name, 6) != 0) { emacs_close (fd); -# if !defined(IRIS) && !defined(__sgi) +# ifndef __sgi continue; # else return -1; -# endif /* IRIS */ +# endif /* __sgi */ } setup_pty (fd); return fd; @@ -621,6 +596,7 @@ make_process (name) p->raw_status_new = 0; p->status = Qrun; p->mark = Fmake_marker (); + p->kill_without_query = 0; #ifdef ADAPTIVE_READ_BUFFERING p->adaptive_read_buffering = 0; @@ -1241,7 +1217,7 @@ a socket connection. */) return XPROCESS (process)->type; } #endif - + DEFUN ("process-type", Fprocess_type, Sprocess_type, 1, 1, 0, doc: /* Return the connection type of PROCESS. The value is either the symbol `real', `network', or `serial'. @@ -1440,12 +1416,7 @@ list_processes_1 (query_only) { Lisp_Object tem; tem = Fcar (Fcdr (p->status)); -#ifdef VMS - if (XINT (tem) < NSIG) - write_string (sys_errlist [XINT (tem)], -1); - else -#endif - Fprinc (symbol, Qnil); + Fprinc (symbol, Qnil); } else if (NETCONN1_P (p) || SERIALCONN1_P (p)) { @@ -1509,7 +1480,7 @@ list_processes_1 (query_only) 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); @@ -1525,7 +1496,7 @@ list_processes_1 (query_only) (DATAGRAM_CHAN_P (p->infd) ? "datagram" : "stream"), (STRINGP (host) ? (char *)SDATA (host) : "?")); insert_string (tembuf); - } + } else if (SERIALCONN1_P (p)) { Lisp_Object port = Fplist_get (p->childp, QCport); @@ -1610,12 +1581,7 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) register Lisp_Object *args; { Lisp_Object buffer, name, program, proc, current_dir, tem; -#ifdef VMS - register unsigned char *new_argv; - int len; -#else register unsigned char **new_argv; -#endif register int i; int count = SPECPDL_INDEX (); @@ -1732,30 +1698,6 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) XPROCESS (proc)->encode_coding_system = val; } -#ifdef VMS - /* Make a one member argv with all args concatenated - together separated by a blank. */ - len = SBYTES (program) + 2; - for (i = 3; i < nargs; i++) - { - tem = args[i]; - CHECK_STRING (tem); - len += SBYTES (tem) + 1; /* count the blank */ - } - new_argv = (unsigned char *) alloca (len); - strcpy (new_argv, SDATA (program)); - for (i = 3; i < nargs; i++) - { - tem = args[i]; - CHECK_STRING (tem); - strcat (new_argv, " "); - strcat (new_argv, SDATA (tem)); - } - /* Need to add code here to check for program existence on VMS */ - -#else /* not VMS */ - new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *)); - /* If program file name is not absolute, search our path for it. Put the name we will really use in TEM. */ if (!IS_DIRECTORY_SEP (SREF (program, 0)) @@ -1785,27 +1727,42 @@ usage: (start-process NAME BUFFER PROGRAM &rest PROGRAM-ARGS) */) && SREF (tem, 1) == ':') tem = Fsubstring (tem, make_number (2), Qnil); - /* Encode the file name and put it in NEW_ARGV. - That's where the child will use it to execute the program. */ - tem = ENCODE_FILE (tem); - new_argv[0] = SDATA (tem); + { + struct gcpro gcpro1; + GCPRO1 (tem); + + /* Encode the file name and put it in NEW_ARGV. + That's where the child will use it to execute the program. */ + tem = Fcons (ENCODE_FILE (tem), Qnil); + + /* Here we encode arguments by the coding system used for sending + data to the process. We don't support using different coding + systems for encoding arguments and for encoding data sent to the + process. */ + + for (i = 3; i < nargs; i++) + { + tem = Fcons (args[i], tem); + CHECK_STRING (XCAR (tem)); + if (STRING_MULTIBYTE (XCAR (tem))) + XSETCAR (tem, + code_convert_string_norecord + (XCAR (tem), XPROCESS (proc)->encode_coding_system, 1)); + } + + UNGCPRO; + } - /* Here we encode arguments by the coding system used for sending - data to the process. We don't support using different coding - systems for encoding arguments and for encoding data sent to the - process. */ + /* Now that everything is encoded we can collect the strings into + NEW_ARGV. */ + new_argv = (unsigned char **) alloca ((nargs - 1) * sizeof (char *)); + new_argv[nargs - 2] = 0; - for (i = 3; i < nargs; i++) + for (i = nargs - 3; i >= 0; i--) { - tem = args[i]; - CHECK_STRING (tem); - if (STRING_MULTIBYTE (tem)) - tem = (code_convert_string_norecord - (tem, XPROCESS (proc)->encode_coding_system, 1)); - new_argv[i - 2] = SDATA (tem); + new_argv[i] = SDATA (XCAR (tem)); + tem = XCDR (tem); } - new_argv[i - 2] = 0; -#endif /* not VMS */ XPROCESS (proc)->decoding_buf = make_uninit_string (0); XPROCESS (proc)->decoding_carryover = 0; @@ -1864,7 +1821,6 @@ create_process_sigchld () #endif #endif -#ifndef VMS /* VMS version of this function is in vmsproc.c. */ void create_process (process, new_argv, current_dir) Lisp_Object process; @@ -1874,6 +1830,9 @@ create_process (process, new_argv, current_dir) int inchannel, outchannel; pid_t pid; int sv[2]; +#if !defined (WINDOWSNT) && defined (FD_CLOEXEC) + int wait_child_setup[2]; +#endif #ifdef POSIX_SIGNALS sigset_t procmask; sigset_t blocked; @@ -1916,12 +1875,6 @@ create_process (process, new_argv, current_dir) #endif if (forkin < 0) report_file_error ("Opening pty", Qnil); -#if defined (DONT_REOPEN_PTY) - /* In the case that vfork is defined as fork, the parent process - (Emacs) may send some data before the child process completes - 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 */ @@ -1947,6 +1900,25 @@ create_process (process, new_argv, current_dir) forkin = sv[0]; } +#if !defined (WINDOWSNT) && defined (FD_CLOEXEC) + { + int tem; + + tem = pipe (wait_child_setup); + if (tem < 0) + report_file_error ("Creating pipe", Qnil); + tem = fcntl (wait_child_setup[1], F_GETFD, 0); + if (tem >= 0) + tem = fcntl (wait_child_setup[1], F_SETFD, tem | FD_CLOEXEC); + if (tem < 0) + { + emacs_close (wait_child_setup[0]); + emacs_close (wait_child_setup[1]); + report_file_error ("Setting file descriptor flags", Qnil); + } + } +#endif + #if 0 /* Replaced by close_process_descs */ set_exclusive_use (inchannel); @@ -2173,14 +2145,15 @@ create_process (process, new_argv, current_dir) #endif /* SIGCHLD */ #endif /* !POSIX_SIGNALS */ -#if !defined (DONT_REOPEN_PTY) if (pty_flag) child_setup_tty (xforkout); -#endif /* not DONT_REOPEN_PTY */ #ifdef WINDOWSNT pid = child_setup (xforkin, xforkout, xforkout, new_argv, 1, 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); #endif /* not WINDOWSNT */ @@ -2234,6 +2207,20 @@ create_process (process, new_argv, current_dir) else #endif XPROCESS (process)->tty_name = Qnil; + +#if !defined (WINDOWSNT) && defined (FD_CLOEXEC) + /* Wait for child_setup to complete in case that vfork is + actually defined as fork. The descriptor wait_child_setup[1] + of a pipe is closed at the child side either by close-on-exec + on successful execvp or the _exit call in child_setup. */ + { + char dummy; + + emacs_close (wait_child_setup[1]); + emacs_read (wait_child_setup[0], &dummy, 1); + emacs_close (wait_child_setup[0]); + } +#endif } /* Restore the signal state whether vfork succeeded or not. @@ -2269,7 +2256,6 @@ create_process (process, new_argv, current_dir) if (pid < 0) report_file_error ("Doing vfork", Qnil); } -#endif /* not VMS */ #ifdef HAVE_SOCKETS @@ -2287,6 +2273,12 @@ conv_sockaddr_to_lisp (sa, len) unsigned char *cp; register struct Lisp_Vector *p; + /* Workaround for a bug in getsockname on BSD: Names bound to + sockets in the UNIX domain are inaccessible; getsockname returns + a zero length name. */ + if (len < OFFSETOF (struct sockaddr, sa_family) + sizeof (sa->sa_family)) + return empty_unibyte_string; + switch (sa->sa_family) { case AF_INET: @@ -2296,14 +2288,14 @@ conv_sockaddr_to_lisp (sa, len) address = Fmake_vector (make_number (len), Qnil); p = XVECTOR (address); p->contents[--len] = make_number (ntohs (sin->sin_port)); - cp = (unsigned char *)&sin->sin_addr; + cp = (unsigned char *) &sin->sin_addr; break; } #ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; - uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; + uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr; len = sizeof (sin6->sin6_addr)/2 + 1; address = Fmake_vector (make_number (len), Qnil); p = XVECTOR (address); @@ -2324,11 +2316,11 @@ conv_sockaddr_to_lisp (sa, len) } #endif default: - len -= sizeof (sa->sa_family); + len -= OFFSETOF (struct sockaddr, sa_family) + sizeof (sa->sa_family); address = Fcons (make_number (sa->sa_family), Fmake_vector (make_number (len), Qnil)); p = XVECTOR (XCDR (address)); - cp = (unsigned char *) sa + sizeof (sa->sa_family); + cp = (unsigned char *) &sa->sa_family + sizeof (sa->sa_family); break; } @@ -2769,9 +2761,7 @@ usage: (serial-process-configure &rest ARGS) */) UNGCPRO; return Qnil; } -#endif /* HAVE_SERIAL */ -#ifdef HAVE_SERIAL /* Used by make-serial-process to recover from errors. */ Lisp_Object make_serial_process_unwind (Lisp_Object proc) { @@ -2780,9 +2770,7 @@ Lisp_Object make_serial_process_unwind (Lisp_Object proc) remove_process (proc); return Qnil; } -#endif /* HAVE_SERIAL */ -#ifdef HAVE_SERIAL DEFUN ("make-serial-process", Fmake_serial_process, Smake_serial_process, 0, MANY, 0, doc: /* Create and return a serial port process. @@ -3208,7 +3196,7 @@ usage: (make-network-process &rest ARGS) */) { /* Don't support network sockets when non-blocking mode is not available, since a blocked Emacs is not useful. */ -#if defined(TERM) || (!defined(O_NONBLOCK) && !defined(O_NDELAY)) +#if !defined(O_NONBLOCK) && !defined(O_NDELAY) error ("Network servers not supported"); #else is_server = 1; @@ -3238,32 +3226,6 @@ usage: (make-network-process &rest ARGS) */) CHECK_STRING (name); -#ifdef TERM - /* Let's handle TERM before things get complicated ... */ - host = Fplist_get (contact, QChost); - CHECK_STRING (host); - - service = Fplist_get (contact, QCservice); - if (INTEGERP (service)) - port = htons ((unsigned short) XINT (service)); - else - { - struct servent *svc_info; - CHECK_STRING (service); - svc_info = getservbyname (SDATA (service), "tcp"); - if (svc_info == 0) - error ("Unknown service: %s", SDATA (service)); - port = svc_info->s_port; - } - - s = connect_server (0); - if (s < 0) - report_file_error ("error creating socket", Fcons (name, Qnil)); - send_command (s, C_PORT, 0, "%s:%d", SDATA (host), ntohs (port)); - send_command (s, C_DUMB, 1, 0); - -#else /* not TERM */ - /* Initialize addrinfo structure in case we don't use getaddrinfo. */ ai.ai_socktype = socktype; ai.ai_protocol = 0; @@ -3387,7 +3349,7 @@ usage: (make-network-process &rest ARGS) */) #ifdef HAVE_GAI_STRERROR error ("%s/%s %s", SDATA (host), portstring, gai_strerror(ret)); #else - error ("%s/%s getaddrinfo error %d", SDATA (host), portstring, ret); + error ("%s/%s getaddrinfo error %d", SDATA (host), portstring, ret); #endif immediate_quit = 0; @@ -3508,7 +3470,7 @@ 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. */ + 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]); @@ -3674,8 +3636,6 @@ usage: (make-network-process &rest ARGS) */) report_file_error ("make client process failed", contact); } -#endif /* not TERM */ - inch = s; outch = s; @@ -4114,19 +4074,9 @@ deactivate_process (proc) { /* Beware SIGCHLD hereabouts. */ flush_pending_output (inchannel); -#ifdef VMS - { - VMS_PROC_STUFF *get_vms_process_pointer (), *vs; - sys$dassgn (outchannel); - vs = get_vms_process_pointer (p->pid); - if (vs) - give_back_vms_process_stuff (vs); - } -#else emacs_close (inchannel); if (outchannel >= 0 && outchannel != inchannel) emacs_close (outchannel); -#endif p->infd = -1; p->outfd = -1; @@ -4195,9 +4145,9 @@ It is read into the process' buffers or given to their filter functions. Non-nil arg PROCESS means do not return until some 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 input. If SECONDS is a floating point number, +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, it specifies a fractional number of seconds to wait. The MILLISEC argument is obsolete and should be avoided. @@ -4602,12 +4552,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, QUIT; #ifdef SYNC_INPUT else - { - if (interrupt_input_pending) - handle_async_input (); - if (pending_atimers) - do_pending_atimers (); - } + process_pending_signals (); #endif /* Exit now if the cell we're waiting for became non-nil. */ @@ -4717,15 +4662,6 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, #endif Atemp = input_wait_mask; -#if 0 - /* On Mac OS X 10.0, the SELECT system call always says input is - present (for reading) at stdin, even when none is. This - causes the call to SELECT below to return 1 and - status_notify not to be called. As a result output of - subprocesses are incorrectly discarded. - */ - FD_CLR (0, &Atemp); -#endif IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask); EMACS_SET_SECS_USECS (timeout, 0, 0); @@ -4748,7 +4684,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, } /* Don't wait for output from a non-running process. Just - read whatever data has already been received. */ + read whatever data has already been received. */ if (wait_proc && wait_proc->raw_status_new) update_status (wait_proc); if (wait_proc @@ -4768,22 +4704,22 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, if (nread == 0) break; - if (0 < nread) - { + if (0 < nread) + { total_nread += nread; got_some_input = 1; } #ifdef EIO else if (nread == -1 && EIO == errno) - break; + break; #endif #ifdef EAGAIN else if (nread == -1 && EAGAIN == errno) - break; + break; #endif #ifdef EWOULDBLOCK else if (nread == -1 && EWOULDBLOCK == errno) - break; + break; #endif } if (total_nread > 0 && do_display) @@ -4878,11 +4814,11 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, } #endif #ifdef HAVE_NS - nfds = ns_select + nfds = ns_select #else - nfds = select + nfds = select #endif - (max (max (max_process_desc, max_keyboard_desc), + (max (max (max_process_desc, max_keyboard_desc), max_gpm_desc) + 1, &Available, #ifdef NON_BLOCKING_CONNECT @@ -4933,19 +4869,6 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, IF_NON_BLOCKING_CONNECT (check_connect = 0); } -#if defined(sun) && !defined(USG5_4) - if (nfds > 0 && keyboard_bit_set (&Available) - && interrupt_input) - /* System sometimes fails to deliver SIGIO. - - David J. Mackenzie says that Emacs doesn't compile under - Solaris if this code is enabled, thus the USG5_4 in the CPP - conditional. "I haven't noticed any ill effects so far. - If you find a Solaris expert somewhere, they might know - better." */ - kill (getpid (), SIGIO); -#endif - #if 0 /* When polling is used, interrupt_input is 0, so get_input_pending should read the input. So this should not be needed. */ @@ -5161,7 +5084,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, #ifdef GNU_LINUX /* getsockopt(,,SO_ERROR,,) is said to hang on some systems. - So only use it on systems where it is known to work. */ + So only use it on systems where it is known to work. */ { int xlen = sizeof(xerrno); if (getsockopt(channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen)) @@ -5262,44 +5185,12 @@ read_process_output (proc, channel) register int nbytes; char *chars; register Lisp_Object outstream; - register struct buffer *old = current_buffer; register struct Lisp_Process *p = XPROCESS (proc); register int opoint; struct coding_system *coding = proc_decode_coding_system[channel]; int carryover = p->decoding_carryover; int readmax = 4096; -#ifdef VMS - VMS_PROC_STUFF *vs, *get_vms_process_pointer(); - - vs = get_vms_process_pointer (p->pid); - if (vs) - { - if (!vs->iosb[0]) - return (0); /* Really weird if it does this */ - if (!(vs->iosb[0] & 1)) - return -1; /* I/O error */ - } - else - error ("Could not get VMS process pointer"); - chars = vs->inputBuffer; - nbytes = clean_vms_buffer (chars, vs->iosb[1]); - if (nbytes <= 0) - { - start_vms_process_read (vs); /* Crank up the next read on the process */ - return 1; /* Nothing worth printing, say we got 1 */ - } - if (carryover > 0) - { - /* The data carried over in the previous decoding (which are at - the tail of decoding buffer) should be prepended to the new - data read to decode all together. */ - chars = (char *) alloca (nbytes + carryover); - bcopy (SDATA (p->decoding_buf), buf, carryover); - bcopy (vs->inputBuffer, chars + carryover, nbytes); - } -#else /* not VMS */ - chars = (char *) alloca (carryover + readmax); if (carryover) /* See the comment above. */ @@ -5356,7 +5247,6 @@ read_process_output (proc, channel) else nbytes = nbytes + 1; } -#endif /* not VMS */ p->decoding_carryover = 0; @@ -5479,9 +5369,6 @@ read_process_output (proc, channel) if (waiting_for_user_input_p == -1) record_asynch_buffer_change (); -#ifdef VMS - start_vms_process_read (vs); -#endif unbind_to (count, Qnil); return nbytes; } @@ -5497,9 +5384,11 @@ read_process_output (proc, channel) int opoint_byte; Lisp_Object text; struct buffer *b; + int count = SPECPDL_INDEX (); odeactivate = Vdeactivate_mark; + record_unwind_protect (Fset_buffer, Fcurrent_buffer ()); Fset_buffer (p->buffer); opoint = PT; opoint_byte = PT_BYTE; @@ -5602,11 +5491,8 @@ read_process_output (proc, channel) current_buffer->read_only = old_read_only; SET_PT_BOTH (opoint, opoint_byte); - set_buffer_internal (old); + unbind_to (count, Qnil); } -#ifdef VMS - start_vms_process_read (vs); -#endif return nbytes; } @@ -5658,10 +5544,6 @@ send_process (proc, buf, len, object) GCPRO1 (object); -#ifdef VMS - VMS_PROC_STUFF *vs, *get_vms_process_pointer(); -#endif /* VMS */ - if (p->raw_status_new) update_status (p); if (! EQ (p->status, Qrun)) @@ -5742,14 +5624,6 @@ send_process (proc, buf, len, object) buf = SDATA (coding->dst_object); } -#ifdef VMS - vs = get_vms_process_pointer (p->pid); - if (vs == 0) - error ("Could not find this process: %x", p->pid); - else if (write_to_vms_process (vs, buf, len)) - ; -#else /* not VMS */ - if (pty_max_bytes == 0) { #if defined (HAVE_FPATHCONF) && defined (_PC_MAX_CANON) @@ -5778,7 +5652,7 @@ send_process (proc, buf, len, object) if (p->pty_flag) { /* Starting this at zero is always correct when not the first - iteration because the previous iteration ended by sending C-d. + iteration because the previous iteration ended by sending C-d. It may not be correct for the first iteration if a partial line was sent in a separate send_process call. If that proves worth handling, we need to save linepos @@ -5878,7 +5752,9 @@ send_process (proc, buf, len, object) /* Running filters might relocate buffers or strings. Arrange to relocate BUF. */ - if (BUFFERP (object)) + if (CODING_REQUIRE_ENCODING (coding)) + offset = buf - SDATA (coding->dst_object); + else if (BUFFERP (object)) offset = BUF_PTR_BYTE_POS (XBUFFER (object), buf); else if (STRINGP (object)) offset = buf - SDATA (object); @@ -5889,7 +5765,9 @@ send_process (proc, buf, len, object) wait_reading_process_output (1, 0, 0, 0, Qnil, NULL, 0); #endif - if (BUFFERP (object)) + if (CODING_REQUIRE_ENCODING (coding)) + buf = offset + SDATA (coding->dst_object); + else if (BUFFERP (object)) buf = BUF_BYTE_ADDRESS (XBUFFER (object), offset); else if (STRINGP (object)) buf = offset + SDATA (object); @@ -5911,23 +5789,16 @@ send_process (proc, buf, len, object) Fprocess_send_eof (proc); } } -#endif /* not VMS */ else { signal (SIGPIPE, old_sigpipe); -#ifndef VMS proc = process_sent_to; p = XPROCESS (proc); -#endif p->raw_status_new = 0; p->status = Fcons (Qexit, Fcons (make_number (256), Qnil)); p->tick = ++process_tick; deactivate_process (proc); -#ifdef VMS - error ("Error writing to process %s; closed it", SDATA (p->name)); -#else error ("SIGPIPE raised on process %s; closed it", SDATA (p->name)); -#endif } UNGCPRO; @@ -6089,7 +5960,7 @@ process_send_signal (process, signo, current_group, nomsg) by sending an input character to it. */ /* TERMIOS is the latest and bestest, and seems most likely to - work. If the system has it, use it. */ + work. If the system has it, use it. */ #ifdef HAVE_TERMIOS struct termios t; cc_t *sig_char = NULL; @@ -6231,20 +6102,8 @@ process_send_signal (process, signo, current_group, nomsg) break; #endif /* ! defined (SIGCONT) */ case SIGINT: -#ifdef VMS - send_process (proc, "\003", 1, Qnil); /* ^C */ - goto whoosh; -#endif case SIGQUIT: -#ifdef VMS - send_process (proc, "\031", 1, Qnil); /* ^Y */ - goto whoosh; -#endif case SIGKILL: -#ifdef VMS - sys$forcex (&(p->pid), 0, 1); - whoosh: -#endif flush_pending_output (p->infd); break; } @@ -6585,9 +6444,6 @@ process has been transmitted to the serial port. */) send_process (proc, "", 0, Qnil); } -#ifdef VMS - send_process (proc, "\032", 1, Qnil); /* ^z */ -#else if (XPROCESS (proc)->pty_flag) send_process (proc, "\004", 1, Qnil); else if (EQ (XPROCESS (proc)->type, Qserial)) @@ -6632,7 +6488,6 @@ process has been transmitted to the serial port. */) XPROCESS (proc)->outfd = new_outfd; } -#endif /* VMS */ return process; } @@ -6708,7 +6563,7 @@ sigchld_handler (signo) #endif /* no WUNTRACED */ /* Keep trying to get a status until we get a definitive result. */ do - { + { errno = 0; pid = wait3 (&w, WNOHANG | WUNTRACED, 0); } @@ -6805,7 +6660,7 @@ sigchld_handler (signo) if (WIFEXITED (w)) synch_process_retcode = WRETCODE (w); else if (WIFSIGNALED (w)) - synch_process_termsig = WTERMSIG (w); + synch_process_termsig = WTERMSIG (w); /* Tell wait_reading_process_output that it needs to wake up and look around. */ @@ -6823,7 +6678,7 @@ sigchld_handler (signo) to use up all the processes that have something to tell us. */ #if (defined WINDOWSNT \ || (defined USG && !defined GNU_LINUX \ - && !(defined HPUX && defined WNOHANG))) + && !(defined HPUX && defined WNOHANG))) #if defined (USG) && ! defined (POSIX_SIGNALS) signal (signo, sigchld_handler); #endif @@ -7220,6 +7075,77 @@ keyboard_bit_set (mask) return 0; } +/* Enumeration of and access to system processes a-la ps(1). */ + +DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes, + 0, 0, 0, + doc: /* Return a list of numerical process IDs of all running processes. +If this functionality is unsupported, return nil. + +See `process-attributes' for getting attributes of a process given its ID. */) + () +{ + return list_system_processes (); +} + +DEFUN ("process-attributes", Fprocess_attributes, + Sprocess_attributes, 1, 1, 0, + doc: /* Return attributes of the process given by its PID, a number. + +Value is an alist where each element is a cons cell of the form + + \(KEY . VALUE) + +If this functionality is unsupported, the value is nil. + +See `list-system-processes' for getting a list of all process IDs. + +The KEYs of the attributes that this function may return are listed +below, together with the type of the associated VALUE (in parentheses). +Not all platforms support all of these attributes; unsupported +attributes will not appear in the returned alist. +Unless explicitly indicated otherwise, numbers can have either +integer or floating point values. + + euid -- Effective user User ID of the process (number) + user -- User name corresponding to euid (string) + egid -- Effective user Group ID of the process (number) + group -- Group name corresponding to egid (string) + comm -- Command name (executable name only) (string) + state -- Process state code, such as "S", "R", or "T" (string) + ppid -- Parent process ID (number) + pgrp -- Process group ID (number) + sess -- Session ID, i.e. process ID of session leader (number) + ttname -- Controlling tty name (string) + tpgid -- ID of foreground process group on the process's tty (number) + minflt -- number of minor page faults (number) + majflt -- number of major page faults (number) + cminflt -- cumulative number of minor page faults (number) + cmajflt -- cumulative number of major page faults (number) + utime -- user time used by the process, in the (HIGH LOW USEC) format + stime -- system time used by the process, in the (HIGH LOW USEC) format + time -- sum of utime and stime, in the (HIGH LOW USEC) format + cutime -- user time used by the process and its children, (HIGH LOW USEC) + cstime -- system time used by the process and its children, (HIGH LOW USEC) + ctime -- sum of cutime and cstime, in the (HIGH LOW USEC) format + pri -- priority of the process (number) + nice -- nice value of the process (number) + thcount -- process thread count (number) + start -- time the process started, in the (HIGH LOW USEC) format + vsize -- virtual memory size of the process in KB's (number) + rss -- resident set size of the process in KB's (number) + etime -- elapsed time the process is running, in (HIGH LOW USEC) format + pcpu -- percents of CPU time used by the process (floating-point number) + pmem -- percents of total physical memory used by process's resident set + (floating-point number) + args -- command line which invoked the process (string). */) + (pid) + + Lisp_Object pid; +{ + return system_process_attributes (pid); +} + void init_process () { @@ -7295,7 +7221,7 @@ init_process () #ifdef HAVE_GETSOCKNAME ADD_SUBFEATURE (QCservice, Qt); #endif -#if !defined(TERM) && (defined(O_NONBLOCK) || defined(O_NDELAY)) +#if defined(O_NONBLOCK) || defined(O_NDELAY) ADD_SUBFEATURE (QCserver, Qt); #endif @@ -7306,7 +7232,7 @@ init_process () } #endif /* HAVE_SOCKETS */ -#if defined (DARWIN) || defined (MAC_OSX) +#if defined (DARWIN_OS) /* PTYs are broken on Darwin < 6, but are sometimes useful for interactive processes. As such, we only change the default value. */ if (initialized) @@ -7433,6 +7359,69 @@ syms_of_process () staticpro (&deleted_pid_list); #endif + Qeuid = intern ("euid"); + staticpro (&Qeuid); + Qegid = intern ("egid"); + staticpro (&Qegid); + Quser = intern ("user"); + staticpro (&Quser); + Qgroup = intern ("group"); + staticpro (&Qgroup); + Qcomm = intern ("comm"); + staticpro (&Qcomm); + Qstate = intern ("state"); + staticpro (&Qstate); + Qppid = intern ("ppid"); + staticpro (&Qppid); + Qpgrp = intern ("pgrp"); + staticpro (&Qpgrp); + Qsess = intern ("sess"); + staticpro (&Qsess); + Qttname = intern ("ttname"); + staticpro (&Qttname); + Qtpgid = intern ("tpgid"); + staticpro (&Qtpgid); + Qminflt = intern ("minflt"); + staticpro (&Qminflt); + Qmajflt = intern ("majflt"); + staticpro (&Qmajflt); + Qcminflt = intern ("cminflt"); + staticpro (&Qcminflt); + Qcmajflt = intern ("cmajflt"); + staticpro (&Qcmajflt); + Qutime = intern ("utime"); + staticpro (&Qutime); + Qstime = intern ("stime"); + staticpro (&Qstime); + Qtime = intern ("time"); + staticpro (&Qtime); + Qcutime = intern ("cutime"); + staticpro (&Qcutime); + Qcstime = intern ("cstime"); + staticpro (&Qcstime); + Qctime = intern ("ctime"); + staticpro (&Qctime); + Qpri = intern ("pri"); + staticpro (&Qpri); + Qnice = intern ("nice"); + staticpro (&Qnice); + Qthcount = intern ("thcount"); + staticpro (&Qthcount); + Qstart = intern ("start"); + staticpro (&Qstart); + Qvsize = intern ("vsize"); + staticpro (&Qvsize); + Qrss = intern ("rss"); + staticpro (&Qrss); + Qetime = intern ("etime"); + staticpro (&Qetime); + Qpcpu = intern ("pcpu"); + staticpro (&Qpcpu); + Qpmem = intern ("pmem"); + staticpro (&Qpmem); + Qargs = intern ("args"); + staticpro (&Qargs); + DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes, doc: /* *Non-nil means delete processes immediately when they exit. A value of nil means don't delete them until `list-processes' is run. */); @@ -7527,6 +7516,8 @@ The variable takes effect when `start-process' is called. */); defsubr (&Sprocess_coding_system); defsubr (&Sset_process_filter_multibyte); defsubr (&Sprocess_filter_multibyte_p); + defsubr (&Slist_system_processes); + defsubr (&Sprocess_attributes); } @@ -7534,6 +7525,12 @@ The variable takes effect when `start-process' is called. */); #include #include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif #include "lisp.h" #include "systime.h" @@ -7547,7 +7544,12 @@ extern int frame_garbaged; extern EMACS_TIME timer_check (); extern int timers_run; -Lisp_Object QCtype; +Lisp_Object QCtype, QCname; + +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; /* As described above, except assuming that there are no subprocesses: @@ -7725,7 +7727,7 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display, else error ("select error: %s", emacs_strerror (xerrno)); } -#ifdef sun +#ifdef SOLARIS2 else if (nfds > 0 && (waitchannels & 1) && interrupt_input) /* System sometimes fails to deliver SIGIO. */ kill (getpid (), SIGIO); @@ -7809,6 +7811,75 @@ kill_buffer_processes (buffer) { } +DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes, + 0, 0, 0, + doc: /* Return a list of numerical process IDs of all running processes. +If this functionality is unsupported, return nil. + +See `process-attributes' for getting attributes of a process given its ID. */) + () +{ + return list_system_processes (); +} + +DEFUN ("process-attributes", Fprocess_attributes, + Sprocess_attributes, 1, 1, 0, + doc: /* Return attributes of the process given by its PID, a number. + +Value is an alist where each element is a cons cell of the form + + \(KEY . VALUE) + +If this functionality is unsupported, the value is nil. + +See `list-system-processes' for getting a list of all process IDs. + +The KEYs of the attributes that this function may return are listed +below, together with the type of the associated VALUE (in parentheses). +Not all platforms support all of these attributes; unsupported +attributes will not appear in the returned alist. +Unless explicitly indicated otherwise, numbers can have either +integer or floating point values. + + euid -- Effective user User ID of the process (number) + user -- User name corresponding to euid (string) + egid -- Effective user Group ID of the process (number) + group -- Group name corresponding to egid (string) + comm -- Command name (executable name only) (string) + state -- Process state code, such as "S", "R", or "T" (string) + ppid -- Parent process ID (number) + pgrp -- Process group ID (number) + sess -- Session ID, i.e. process ID of session leader (number) + ttname -- Controlling tty name (string) + tpgid -- ID of foreground process group on the process's tty (number) + minflt -- number of minor page faults (number) + majflt -- number of major page faults (number) + cminflt -- cumulative number of minor page faults (number) + cmajflt -- cumulative number of major page faults (number) + utime -- user time used by the process, in the (HIGH LOW USEC) format + stime -- system time used by the process, in the (HIGH LOW USEC) format + time -- sum of utime and stime, in the (HIGH LOW USEC) format + cutime -- user time used by the process and its children, (HIGH LOW USEC) + cstime -- system time used by the process and its children, (HIGH LOW USEC) + ctime -- sum of cutime and cstime, in the (HIGH LOW USEC) format + pri -- priority of the process (number) + nice -- nice value of the process (number) + thcount -- process thread count (number) + start -- time the process started, in the (HIGH LOW USEC) format + vsize -- virtual memory size of the process in KB's (number) + rss -- resident set size of the process in KB's (number) + etime -- elapsed time the process is running, in (HIGH LOW USEC) format + pcpu -- percents of CPU time used by the process (floating-point number) + pmem -- percents of total physical memory used by process's resident set + (floating-point number) + args -- command line which invoked the process (string). */) + (pid) + + Lisp_Object pid; +{ + return system_process_attributes (pid); +} + void init_process () { @@ -7819,9 +7890,79 @@ syms_of_process () { QCtype = intern (":type"); staticpro (&QCtype); + QCname = intern (":name"); + staticpro (&QCname); + QCtype = intern (":type"); + staticpro (&QCtype); + QCname = intern (":name"); + staticpro (&QCname); + Qeuid = intern ("euid"); + staticpro (&Qeuid); + Qegid = intern ("egid"); + staticpro (&Qegid); + Quser = intern ("user"); + staticpro (&Quser); + Qgroup = intern ("group"); + staticpro (&Qgroup); + Qcomm = intern ("comm"); + staticpro (&Qcomm); + Qstate = intern ("state"); + staticpro (&Qstate); + Qppid = intern ("ppid"); + staticpro (&Qppid); + Qpgrp = intern ("pgrp"); + staticpro (&Qpgrp); + Qsess = intern ("sess"); + staticpro (&Qsess); + Qttname = intern ("ttname"); + staticpro (&Qttname); + Qtpgid = intern ("tpgid"); + staticpro (&Qtpgid); + Qminflt = intern ("minflt"); + staticpro (&Qminflt); + Qmajflt = intern ("majflt"); + staticpro (&Qmajflt); + Qcminflt = intern ("cminflt"); + staticpro (&Qcminflt); + Qcmajflt = intern ("cmajflt"); + staticpro (&Qcmajflt); + Qutime = intern ("utime"); + staticpro (&Qutime); + Qstime = intern ("stime"); + staticpro (&Qstime); + Qtime = intern ("time"); + staticpro (&Qtime); + Qcutime = intern ("cutime"); + staticpro (&Qcutime); + Qcstime = intern ("cstime"); + staticpro (&Qcstime); + Qctime = intern ("ctime"); + staticpro (&Qctime); + Qpri = intern ("pri"); + staticpro (&Qpri); + Qnice = intern ("nice"); + staticpro (&Qnice); + Qthcount = intern ("thcount"); + staticpro (&Qthcount); + Qstart = intern ("start"); + staticpro (&Qstart); + Qvsize = intern ("vsize"); + staticpro (&Qvsize); + Qrss = intern ("rss"); + staticpro (&Qrss); + Qetime = intern ("etime"); + staticpro (&Qetime); + Qpcpu = intern ("pcpu"); + staticpro (&Qpcpu); + Qpmem = intern ("pmem"); + staticpro (&Qpmem); + Qargs = intern ("args"); + staticpro (&Qargs); defsubr (&Sget_buffer_process); defsubr (&Sprocess_inherit_coding_system_flag); + defsubr (&Slist_system_processes); + defsubr (&Sprocess_attributes); }