/* 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, 2010 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#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
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif /* HAVE_SOCKETS */
-#if defined(BSD_SYSTEM)
+#if defined(HAVE_SYS_IOCTL_H)
#include <sys/ioctl.h>
#if !defined (O_NDELAY) && defined (HAVE_PTYS) && !defined(USG5)
#include <fcntl.h>
#endif /* HAVE_PTYS and no O_NDELAY */
-#endif /* BSD_SYSTEM */
+#endif /* HAVE_SYS_IOCTL_H */
#ifdef NEED_BSDTTY
#include <bsdtty.h>
#include "composite.h"
#include "atimer.h"
+#if defined (USE_GTK) || defined (HAVE_GCONF)
+#include "xgselect.h"
+#endif /* defined (USE_GTK) || defined (HAVE_GCONF) */
+
Lisp_Object Qprocessp;
Lisp_Object Qrun, Qstop, Qsignal;
Lisp_Object Qopen, Qclosed, Qconnect, Qfailed, Qlisten;
-Lisp_Object Qlocal, Qipv4, Qdatagram;
+Lisp_Object Qlocal, Qipv4, Qdatagram, Qseqpacket;
Lisp_Object Qreal, Qnetwork, Qserial;
#ifdef AF_INET6
Lisp_Object Qipv6;
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;
+Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtime, Qctime;
#ifdef HAVE_SOCKETS
#define NETCONN_P(p) (EQ (XPROCESS (p)->type, Qnetwork))
#include "syswait.h"
-extern char *get_operating_system_release ();
+extern char *get_operating_system_release (void);
/* Serial processes require termios or Windows. */
#if defined (HAVE_TERMIOS) || defined (WINDOWSNT)
extern void serial_configure (struct Lisp_Process *p, Lisp_Object contact);
#endif
-#ifndef USE_CRT_DLL
-extern int errno;
-#endif
-
#ifndef HAVE_H_ERRNO
extern int h_errno;
#endif
#endif /* DATAGRAM_SOCKETS */
#endif /* BROKEN_DATAGRAM_SOCKETS */
+#if defined HAVE_LOCAL_SOCKETS && defined DATAGRAM_SOCKETS
+# define HAVE_SEQPACKET
+#endif
+
#if !defined (ADAPTIVE_READ_BUFFERING) && !defined (NO_ADAPTIVE_READ_BUFFERING)
#ifdef EMACS_HAS_USECS
#define ADAPTIVE_READ_BUFFERING
#include "sysselect.h"
-static int keyboard_bit_set P_ ((SELECT_TYPE *));
-static void deactivate_process P_ ((Lisp_Object));
-static void status_notify P_ ((struct Lisp_Process *));
-static int read_process_output P_ ((Lisp_Object, int));
+static int keyboard_bit_set (SELECT_TYPE *);
+static void deactivate_process (Lisp_Object);
+static void status_notify (struct Lisp_Process *);
+static int read_process_output (Lisp_Object, 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. */
#define POLL_FOR_INPUT
#endif
-static Lisp_Object get_process ();
-static void exec_sentinel ();
+static Lisp_Object get_process (register Lisp_Object name);
+static void exec_sentinel (Lisp_Object proc, Lisp_Object reason);
-extern EMACS_TIME timer_check ();
extern int timers_run;
\f
/* Mask of bits indicating the descriptors that we wait for input on. */
static SELECT_TYPE input_wait_mask;
+/* Non-zero if keyboard input is on hold, zero otherwise. */
+
+static int kbd_is_on_hold;
+
/* Mask that excludes keyboard input descriptor(s). */
static SELECT_TYPE non_keyboard_wait_mask;
static Lisp_Object status_convert (int);
static void
-update_status (p)
- struct Lisp_Process *p;
+update_status (struct Lisp_Process *p)
{
eassert (p->raw_status_new);
p->status = status_convert (p->raw_status);
and store them individually through the three pointers. */
static void
-decode_status (l, symbol, code, coredump)
- Lisp_Object l;
- Lisp_Object *symbol;
- int *code;
- int *coredump;
+decode_status (Lisp_Object l, Lisp_Object *symbol, int *code, int *coredump)
{
Lisp_Object tem;
/* Return a string describing a process status list. */
static Lisp_Object
-status_message (p)
- struct Lisp_Process *p;
+status_message (struct Lisp_Process *p)
{
Lisp_Object status = p->status;
Lisp_Object symbol;
synchronize_system_messages_locale ();
signame = strsignal (code);
if (signame == 0)
- signame = "unknown";
- string = build_string (signame);
+ string = build_string ("unknown");
+ else
+ {
+ int c1, c2;
+
+ string = make_unibyte_string (signame, strlen (signame));
+ if (! NILP (Vlocale_coding_system))
+ string = (code_convert_string_norecord
+ (string, Vlocale_coding_system, 0));
+ c1 = STRING_CHAR ((char *) SDATA (string));
+ c2 = DOWNCASE (c1);
+ if (c1 != c2)
+ Faset (string, make_number (0), make_number (c2));
+ }
string2 = build_string (coredump ? " (core dumped)\n" : "\n");
- SSET (string, 0, DOWNCASE (SREF (string, 0)));
return concat2 (string, string2);
}
else if (EQ (symbol, Qexit))
is left in the variable pty_name. */
static int
-allocate_pty ()
+allocate_pty (void)
{
register int c, i;
int fd;
#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)
{
#endif /* HAVE_PTYS */
\f
static Lisp_Object
-make_process (name)
- Lisp_Object name;
+make_process (Lisp_Object name)
{
register Lisp_Object val, tem, name1;
register struct Lisp_Process *p;
}
static void
-remove_process (proc)
- register Lisp_Object proc;
+remove_process (register Lisp_Object proc)
{
register Lisp_Object pair;
/* Setup coding systems of PROCESS. */
void
-setup_process_coding_systems (process)
- Lisp_Object process;
+setup_process_coding_systems (Lisp_Object process)
{
struct Lisp_Process *p = XPROCESS (process);
int inch = p->infd;
current buffer. */
static Lisp_Object
-get_process (name)
- register Lisp_Object name;
+get_process (register Lisp_Object name)
{
register Lisp_Object proc, obj;
if (STRINGP (name))
p->status = Fcons (Qexit, Fcons (make_number (0), Qnil));
p->tick = ++process_tick;
status_notify (p);
+ redisplay_preserve_echo_area (13);
}
else if (p->infd >= 0)
{
= Fcons (Qsignal, Fcons (make_number (SIGKILL), Qnil));
p->tick = ++process_tick;
status_notify (p);
+ redisplay_preserve_echo_area (13);
}
}
remove_process (process);
2, 2, 0,
doc: /* Specify if query is needed for PROCESS when Emacs is exited.
If the second argument FLAG is non-nil, Emacs will query the user before
-exiting if PROCESS is running. */)
+exiting or killing a buffer if PROCESS is running. */)
(process, flag)
register Lisp_Object process, flag;
{
}
#ifdef DATAGRAM_SOCKETS
-Lisp_Object Fprocess_datagram_address ();
+Lisp_Object Fprocess_datagram_address (Lisp_Object process);
#endif
DEFUN ("process-contact", Fprocess_contact, Sprocess_contact,
#endif
\f
static Lisp_Object
-list_processes_1 (query_only)
- Lisp_Object query_only;
+list_processes_1 (Lisp_Object query_only)
{
register Lisp_Object tail, tem;
Lisp_Object proc, minspace, tem1;
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);
(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);
insert_string ("?");
if (INTEGERP (speed))
{
- sprintf (tembuf, " at %d b/s", XINT (speed));
+ sprintf (tembuf, " at %ld b/s", (long) XINT (speed));
insert_string (tembuf);
}
insert_string (")\n");
while (1)
{
tem1 = Fcar (tem);
+ if (NILP (tem1))
+ break;
Finsert (1, &tem1);
tem = Fcdr (tem);
if (NILP (tem))
}
}
if (exited)
- status_notify (NULL);
+ {
+ status_notify (NULL);
+ redisplay_preserve_echo_area (13);
+ }
return Qnil;
}
\f
/* Starting asynchronous inferior processes. */
-static Lisp_Object start_process_unwind ();
+static Lisp_Object start_process_unwind (Lisp_Object proc);
DEFUN ("start-process", Fstart_process, Sstart_process, 3, MANY, 0,
doc: /* Start a program in a subprocess. Return the process object for it.
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.
-Remaining arguments are strings to give program as arguments.
+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.
If you want to separate standard output from standard error, invoke
the command through a shell and redirect one of them using the shell
program = args[2];
- CHECK_STRING (program);
+ if (!NILP (program))
+ CHECK_STRING (program);
proc = make_process (name);
/* If an error occurs and we can't start the process, we want to
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
- coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+ if (!NILP (program))
+ coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
UNGCPRO;
if (CONSP (coding_systems))
val = XCAR (coding_systems);
args2[0] = Qstart_process;
for (i = 0; i < nargs; i++) args2[i + 1] = args[i];
GCPRO2 (proc, current_dir);
- coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
+ if (!NILP (program))
+ coding_systems = Ffind_operation_coding_system (nargs + 1, args2);
UNGCPRO;
}
if (CONSP (coding_systems))
XPROCESS (proc)->encode_coding_system = val;
}
- 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))
- && !(SCHARS (program) > 1
- && IS_DEVICE_SEP (SREF (program, 1))))
- {
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+ XPROCESS (proc)->decoding_buf = make_uninit_string (0);
+ XPROCESS (proc)->decoding_carryover = 0;
+ XPROCESS (proc)->encoding_buf = make_uninit_string (0);
- tem = Qnil;
- GCPRO4 (name, program, buffer, current_dir);
- openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
- UNGCPRO;
- if (NILP (tem))
- report_file_error ("Searching for program", Fcons (program, Qnil));
- tem = Fexpand_file_name (tem, Qnil);
- }
- else
+ XPROCESS (proc)->inherit_coding_system_flag
+ = !(NILP (buffer) || !inherit_process_coding_system);
+
+ if (!NILP (program))
{
- if (!NILP (Ffile_directory_p (program)))
- error ("Specified program for new process is a directory");
- tem = program;
- }
+ /* 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))
+ && !(SCHARS (program) > 1
+ && IS_DEVICE_SEP (SREF (program, 1))))
+ {
+ struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
+
+ tem = Qnil;
+ GCPRO4 (name, program, buffer, current_dir);
+ openp (Vexec_path, program, Vexec_suffixes, &tem, make_number (X_OK));
+ UNGCPRO;
+ if (NILP (tem))
+ report_file_error ("Searching for program", Fcons (program, Qnil));
+ tem = Fexpand_file_name (tem, Qnil);
+ }
+ else
+ {
+ if (!NILP (Ffile_directory_p (program)))
+ error ("Specified program for new process is a directory");
+ 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);
+ /* 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);
- /* 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);
- /* 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. */
+ /* 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);
- for (i = 3; i < nargs; 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 - 2] = 0;
+ /* 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. */
- XPROCESS (proc)->decoding_buf = make_uninit_string (0);
- XPROCESS (proc)->decoding_carryover = 0;
- XPROCESS (proc)->encoding_buf = make_uninit_string (0);
+ 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));
+ }
- XPROCESS (proc)->inherit_coding_system_flag
- = !(NILP (buffer) || !inherit_process_coding_system);
+ UNGCPRO;
+ }
- create_process (proc, (char **) new_argv, current_dir);
+ /* 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 = nargs - 3; i >= 0; i--)
+ {
+ new_argv[i] = SDATA (XCAR (tem));
+ tem = XCDR (tem);
+ }
+
+ create_process (proc, (char **) new_argv, current_dir);
+ }
+ else
+ create_pty (proc);
return unbind_to (count, proc);
}
an error and the process wasn't started successfully, so we should
remove it from the process list. */
static Lisp_Object
-start_process_unwind (proc)
- Lisp_Object proc;
+start_process_unwind (Lisp_Object proc)
{
if (!PROCESSP (proc))
abort ();
/* Was PROC started successfully? */
- if (XPROCESS (proc)->pid <= 0)
+ if (XPROCESS (proc)->pid == -1)
remove_process (proc);
return Qnil;
}
static void
-create_process_1 (timer)
- struct atimer *timer;
+create_process_1 (struct atimer *timer)
{
/* Nothing to do. */
}
#endif
void
-create_process (process, new_argv, current_dir)
- Lisp_Object process;
- char **new_argv;
- Lisp_Object current_dir;
+create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
{
int inchannel, outchannel;
pid_t pid;
#if !defined (WINDOWSNT) && defined (FD_CLOEXEC)
int wait_child_setup[2];
#endif
-#ifdef POSIX_SIGNALS
sigset_t procmask;
sigset_t blocked;
struct sigaction sigint_action;
#ifdef AIX
struct sigaction sighup_action;
#endif
-#else /* !POSIX_SIGNALS */
-#if 0
-#ifdef SIGCHLD
- SIGTYPE (*sigchld)();
-#endif
-#endif /* 0 */
-#endif /* !POSIX_SIGNALS */
/* Use volatile to protect variables from being clobbered by longjmp. */
volatile int forkin, forkout;
volatile int pty_flag = 0;
#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 */
/* Delay interrupts until we have a chance to store
the new fork's pid in its process structure */
-#ifdef POSIX_SIGNALS
sigemptyset (&blocked);
#ifdef SIGCHLD
sigaddset (&blocked, SIGCHLD);
#endif
#endif /* HAVE_WORKING_VFORK */
sigprocmask (SIG_BLOCK, &blocked, &procmask);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#if defined (BSD_SYSTEM) || defined (HPUX)
- sigsetmask (sigmask (SIGCHLD));
-#else /* ordinary USG */
-#if 0
- sigchld_deferred = 0;
- sigchld = signal (SIGCHLD, create_process_sigchld);
-#endif
-#endif /* ordinary USG */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
FD_SET (inchannel, &input_wait_mask);
FD_SET (inchannel, &non_keyboard_wait_mask);
process_set_signal to fail on SGI when using a pipe. */
setsid ();
/* Make the pty's terminal the controlling terminal. */
- if (pty_flag)
+ if (pty_flag && xforkin >= 0)
{
#ifdef TIOCSCTTY
/* We ignore the return value
/* I wonder: would just ioctl (0, TIOCNOTTY, 0) work here?
I can't test it since I don't have 4.3. */
int j = emacs_open ("/dev/tty", O_RDWR, 0);
- ioctl (j, TIOCNOTTY, 0);
- emacs_close (j);
+ if (j >= 0)
+ {
+ ioctl (j, TIOCNOTTY, 0);
+ emacs_close (j);
+ }
#ifndef USG
/* In order to get a controlling terminal on some versions
of BSD, it is necessary to put the process in pgrp 0
signal (SIGQUIT, SIG_DFL);
/* Stop blocking signals in the child. */
-#ifdef POSIX_SIGNALS
sigprocmask (SIG_SETMASK, &procmask, 0);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#if defined (BSD_SYSTEM) || defined (HPUX)
- sigsetmask (SIGEMPTYMASK);
-#else /* ordinary USG */
-#if 0
- signal (SIGCHLD, sigchld);
-#endif
-#endif /* ordinary USG */
-#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);
/* Restore the signal state whether vfork succeeded or not.
(We will signal an error, below, if it failed.) */
-#ifdef POSIX_SIGNALS
#ifdef HAVE_WORKING_VFORK
/* Restore the parent's signal handlers. */
sigaction (SIGINT, &sigint_action, 0);
#endif /* HAVE_WORKING_VFORK */
/* Stop blocking signals in the parent. */
sigprocmask (SIG_SETMASK, &procmask, 0);
-#else /* !POSIX_SIGNALS */
-#ifdef SIGCHLD
-#if defined (BSD_SYSTEM) || defined (HPUX)
- sigsetmask (SIGEMPTYMASK);
-#else /* ordinary USG */
-#if 0
- signal (SIGCHLD, sigchld);
- /* Now really handle any of these signals
- that came in during this function. */
- if (sigchld_deferred)
- kill (getpid (), SIGCHLD);
-#endif
-#endif /* ordinary USG */
-#endif /* SIGCHLD */
-#endif /* !POSIX_SIGNALS */
/* Now generate the error if vfork failed. */
if (pid < 0)
report_file_error ("Doing vfork", Qnil);
}
+void
+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;
+
+ inchannel = outchannel = -1;
+
+#ifdef HAVE_PTYS
+ if (!NILP (Vprocess_connection_type))
+ outchannel = inchannel = allocate_pty ();
+
+ if (inchannel >= 0)
+ {
+#if ! defined (USG) || defined (USG_SUBTTY_WORKS)
+ /* On most USG systems it does not work to open the pty's tty here,
+ then close it and reopen it in the child. */
+#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);
+#else
+ forkout = forkin = emacs_open (pty_name, O_RDWR, 0);
+#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 */
+ pty_flag = 1;
+ }
+#endif /* HAVE_PTYS */
+
+#ifdef O_NONBLOCK
+ fcntl (inchannel, F_SETFL, O_NONBLOCK);
+ fcntl (outchannel, F_SETFL, O_NONBLOCK);
+#else
+#ifdef O_NDELAY
+ fcntl (inchannel, F_SETFL, O_NDELAY);
+ fcntl (outchannel, F_SETFL, O_NDELAY);
+#endif
+#endif
+
+ /* Record this as an active process, with its channels.
+ As a result, child_setup will close Emacs's side of the pipes. */
+ chan_process[inchannel] = process;
+ XPROCESS (process)->infd = inchannel;
+ XPROCESS (process)->outfd = outchannel;
+
+ /* Previously we recorded the tty descriptor used in the subprocess.
+ It was only used for getting the foreground tty process, so now
+ we just reopen the device (see emacs_get_tty_pgrp) as this is
+ more portable (see USG_SUBTTY_WORKS above). */
+
+ XPROCESS (process)->pty_flag = pty_flag;
+ XPROCESS (process)->status = Qrun;
+ setup_process_coding_systems (process);
+
+ FD_SET (inchannel, &input_wait_mask);
+ FD_SET (inchannel, &non_keyboard_wait_mask);
+ if (inchannel > max_process_desc)
+ max_process_desc = inchannel;
+
+ XPROCESS (process)->pid = -2;
+#ifdef HAVE_PTYS
+ if (pty_flag)
+ XPROCESS (process)->tty_name = build_string (pty_name);
+ else
+#endif
+ XPROCESS (process)->tty_name = Qnil;
+}
+
\f
#ifdef HAVE_SOCKETS
The address family of sa is not included in the result. */
static Lisp_Object
-conv_sockaddr_to_lisp (sa, len)
- struct sockaddr *sa;
- int len;
+conv_sockaddr_to_lisp (struct sockaddr *sa, int len)
{
Lisp_Object address;
int i;
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:
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);
}
#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;
}
/* Get family and required size for sockaddr structure to hold ADDRESS. */
static int
-get_lisp_to_sockaddr_size (address, familyp)
- Lisp_Object address;
- int *familyp;
+get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
{
register struct Lisp_Vector *p;
we return after zeroing *SA. */
static void
-conv_lisp_to_sockaddr (family, address, sa, len)
- int family;
- Lisp_Object address;
- struct sockaddr *sa;
- int len;
+conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int len)
{
register struct Lisp_Vector *p;
register unsigned char *cp = NULL;
register int i;
- bzero (sa, len);
+ memset (sa, 0, len);
if (VECTORP (address))
{
ip6[i] = ntohs (j);
}
sa->sa_family = family;
+ return;
}
#endif
- return;
+ else
+ return;
}
else if (STRINGP (address))
{
#endif
\f
-static struct socket_options {
+static const struct socket_options {
/* The name of this option. Should be lowercase version of option
name without SO_ prefix. */
char *name;
*/
static int
-set_socket_option (s, opt, val)
- int s;
- Lisp_Object opt, val;
+set_socket_option (int s, Lisp_Object opt, Lisp_Object val)
{
char *name;
- struct socket_options *sopt;
+ const struct socket_options *sopt;
int ret = 0;
CHECK_SYMBOL (opt);
/* This is broken, at least in the Linux 2.4 kernel.
To unbind, the arg must be a zero integer, not the empty string.
This should work on all systems. KFS. 2003-09-23. */
- bzero (devname, sizeof devname);
+ memset (devname, 0, sizeof devname);
if (STRINGP (val))
{
char *arg = (char *) SDATA (val);
int len = min (strlen (arg), IFNAMSIZ);
- bcopy (arg, devname, len);
+ memcpy (devname, arg, len);
}
else if (!NILP (val))
error ("Bad option value for %s", name);
p->inherit_coding_system_flag
= !(!NILP (tem) || NILP (buffer) || !inherit_process_coding_system);
- Fserial_process_configure(nargs, args);
+ Fserial_process_configure (nargs, args);
specpdl_ptr = specpdl + specpdl_count;
string, e.g. "80", as well as an integer. This is not portable.)
:type TYPE -- TYPE is the type of connection. The default (nil) is a
-stream type connection, `datagram' creates a datagram type connection.
+stream type connection, `datagram' creates a datagram type connection,
+`seqpacket' creates a reliable datagram connection.
:family FAMILY -- FAMILY is the address (and protocol) family for the
service specified by HOST and SERVICE. The default (nil) is to use
#ifdef DATAGRAM_SOCKETS
else if (EQ (tem, Qdatagram))
socktype = SOCK_DGRAM;
+#endif
+#ifdef HAVE_SEQPACKET
+ else if (EQ (tem, Qseqpacket))
+ socktype = SOCK_SEQPACKET;
#endif
else
error ("Unsupported connection type");
QCaddress = is_server ? QClocal : QCremote;
/* :nowait BOOL */
- if (!is_server && socktype == SOCK_STREAM
+ if (!is_server && socktype != SOCK_DGRAM
&& (tem = Fplist_get (contact, QCnowait), !NILP (tem)))
{
#ifndef NON_BLOCKING_CONNECT
/* :service SERVICE -- string, integer (port number), or t (random port). */
service = Fplist_get (contact, QCservice);
+ /* :host HOST -- hostname, ip address, or 'local for localhost. */
+ host = Fplist_get (contact, QChost);
+ if (!NILP (host))
+ {
+ if (EQ (host, Qlocal))
+ host = build_string ("localhost");
+ CHECK_STRING (host);
+ }
+
#ifdef HAVE_LOCAL_SOCKETS
if (family == AF_LOCAL)
{
- /* Host is not used. */
- host = Qnil;
+ if (!NILP (host))
+ {
+ message (":family local ignores the :host \"%s\" property",
+ SDATA (host));
+ contact = Fplist_put (contact, QChost, Qnil);
+ host = Qnil;
+ }
CHECK_STRING (service);
- bzero (&address_un, sizeof address_un);
+ memset (&address_un, 0, sizeof address_un);
address_un.sun_family = AF_LOCAL;
strncpy (address_un.sun_path, SDATA (service), sizeof address_un.sun_path);
ai.ai_addr = (struct sockaddr *) &address_un;
}
#endif
- /* :host HOST -- hostname, ip address, or 'local for localhost. */
- host = Fplist_get (contact, QChost);
- if (!NILP (host))
- {
- if (EQ (host, Qlocal))
- host = build_string ("localhost");
- CHECK_STRING (host);
- }
-
/* Slow down polling to every ten seconds.
Some kernels have a bug which causes retrying connect to fail
after a connect. Polling can interfere with gethostbyname too. */
#ifdef POLL_FOR_INPUT
- if (socktype == SOCK_STREAM)
+ if (socktype != SOCK_DGRAM)
{
record_unwind_protect (unwind_stop_other_atimers, Qnil);
bind_polling_period (10);
ret = getaddrinfo (SDATA (host), portstring, &hints, &res);
if (ret)
#ifdef HAVE_GAI_STRERROR
- error ("%s/%s %s", SDATA (host), portstring, gai_strerror(ret));
+ 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;
port = svc_info->s_port;
}
- bzero (&address_in, sizeof address_in);
+ memset (&address_in, 0, sizeof address_in);
address_in.sin_family = family;
address_in.sin_addr.s_addr = INADDR_ANY;
address_in.sin_port = port;
if (host_info_ptr)
{
- bcopy (host_info_ptr->h_addr, (char *) &address_in.sin_addr,
- host_info_ptr->h_length);
+ memcpy (&address_in.sin_addr, host_info_ptr->h_addr,
+ host_info_ptr->h_length);
family = host_info_ptr->h_addrtype;
address_in.sin_family = family;
}
if (numeric_addr == -1)
error ("Unknown host \"%s\"", SDATA (host));
- bcopy ((char *)&numeric_addr, (char *) &address_in.sin_addr,
- sizeof (address_in.sin_addr));
+ memcpy (&address_in.sin_addr, &numeric_addr,
+ sizeof (address_in.sin_addr));
}
}
/* 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]);
}
#endif
- if (socktype == SOCK_STREAM && listen (s, backlog))
+ if (socktype != SOCK_DGRAM && listen (s, backlog))
report_file_error ("Cannot listen on server socket", Qnil);
break;
immediate_quit = 1;
QUIT;
- /* This turns off all alarm-based interrupts; the
- bind_polling_period call above doesn't always turn all the
- short-interval ones off, especially if interrupt_input is
- set.
-
- It'd be nice to be able to control the connect timeout
- though. Would non-blocking connect calls be portable?
-
- This used to be conditioned by HAVE_GETADDRINFO. Why? */
-
- turn_on_atimers (0);
-
ret = connect (s, lres->ai_addr, lres->ai_addrlen);
xerrno = errno;
- turn_on_atimers (1);
-
if (ret == 0 || xerrno == EISCONN)
{
/* The unwind-protect will be discarded afterwards.
#endif
#endif
+#ifndef WINDOWSNT
+ if (xerrno == EINTR)
+ {
+ /* 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;
+ SELECT_TYPE fdset;
+ retry_select:
+ FD_ZERO (&fdset);
+ FD_SET (s, &fdset);
+ QUIT;
+ sc = select (s + 1, (SELECT_TYPE *)0, &fdset, (SELECT_TYPE *)0,
+ (EMACS_TIME *)0);
+ if (sc == -1)
+ {
+ if (errno == EINTR)
+ goto retry_select;
+ else
+ report_file_error ("select failed", Qnil);
+ }
+ eassert (sc > 0);
+
+ len = sizeof xerrno;
+ eassert (FD_ISSET (s, &fdset));
+ if (getsockopt (s, SOL_SOCKET, SO_ERROR, &xerrno, &len) == -1)
+ report_file_error ("getsockopt failed", Qnil);
+ if (xerrno)
+ errno = xerrno, report_file_error ("error during connect", Qnil);
+ else
+ break;
+ }
+#endif /* !WINDOWSNT */
+
immediate_quit = 0;
/* Discard the unwind protect closing S. */
emacs_close (s);
s = -1;
+#ifdef WINDOWSNT
if (xerrno == EINTR)
goto retry_connect;
+#endif
}
if (s >= 0)
if (is_server)
{
Lisp_Object remote;
- bzero (datagram_address[s].sa, lres->ai_addrlen);
+ memset (datagram_address[s].sa, 0, lres->ai_addrlen);
if (remote = Fplist_get (contact, QCremote), !NILP (remote))
{
int rfamily, rlen;
}
}
else
- bcopy (lres->ai_addr, datagram_address[s].sa, lres->ai_addrlen);
+ memcpy (datagram_address[s].sa, lres->ai_addr, lres->ai_addrlen);
}
#endif
contact = Fplist_put (contact, QCaddress,
int len1 = sizeof (sa1);
if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0)
contact = Fplist_put (contact, QClocal,
- conv_sockaddr_to_lisp (&sa1, len1));
+ conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1));
}
#endif
}
p->pid = 0;
p->infd = inch;
p->outfd = outch;
- if (is_server && socktype == SOCK_STREAM)
+ if (is_server && socktype != SOCK_DGRAM)
p->status = Qlisten;
/* Make the process marker point into the process buffer (if any). */
again:
ifaces += 25;
- buf_size = ifaces * sizeof(ifreqs[0]);
+ buf_size = ifaces * sizeof (ifreqs[0]);
ifreqs = (struct ifreq *)xrealloc(ifreqs, buf_size);
if (!ifreqs)
{
char namebuf[sizeof (ifq->ifr_name) + 1];
if (ifq->ifr_addr.sa_family != AF_INET)
continue;
- bcopy (ifq->ifr_name, namebuf, sizeof (ifq->ifr_name));
+ memcpy (namebuf, ifq->ifr_name, sizeof (ifq->ifr_name));
namebuf[sizeof (ifq->ifr_name)] = 0;
res = Fcons (Fcons (build_string (namebuf),
conv_sockaddr_to_lisp (&ifq->ifr_addr,
struct ifflag_def {
int flag_bit;
- char *flag_sym;
+ const char *flag_sym;
};
-static struct ifflag_def ifflag_table[] = {
+static const struct ifflag_def ifflag_table[] = {
#ifdef IFF_UP
{ IFF_UP, "up" },
#endif
CHECK_STRING (ifname);
- bzero (rq.ifr_name, sizeof rq.ifr_name);
+ memset (rq.ifr_name, 0, sizeof rq.ifr_name);
strncpy (rq.ifr_name, SDATA (ifname), sizeof (rq.ifr_name));
s = socket (AF_INET, SOCK_STREAM, 0);
if (ioctl (s, SIOCGIFFLAGS, &rq) == 0)
{
int flags = rq.ifr_flags;
- struct ifflag_def *fp;
+ const struct ifflag_def *fp;
int fnum;
any++;
/* Turn off input and output for process PROC. */
void
-deactivate_process (proc)
- Lisp_Object proc;
+deactivate_process (Lisp_Object proc)
{
register int inchannel, outchannel;
register struct Lisp_Process *p = XPROCESS (proc);
to get rid of irrelevant descriptors. */
void
-close_process_descs ()
+close_process_descs (void)
{
#ifndef WINDOWSNT
int i;
static int connect_counter = 0;
static void
-server_accept_connection (server, channel)
- Lisp_Object server;
- int channel;
+server_accept_connection (Lisp_Object server, int channel)
{
Lisp_Object proc, caller, name, buffer;
Lisp_Object contact, host, service;
int i;
args[0] = build_string ("%x:%x:%x:%x:%x:%x:%x:%x");
for (i = 0; i < 8; i++)
- args[i+1] = make_number (ntohs(ip6[i]));
+ args[i+1] = make_number (ntohs (ip6[i]));
host = Fformat (9, args);
service = make_number (ntohs (saddr.in.sin_port));
static int waiting_for_user_input_p;
static Lisp_Object
-wait_reading_process_output_unwind (data)
- Lisp_Object data;
+wait_reading_process_output_unwind (Lisp_Object data)
{
waiting_for_user_input_p = XINT (data);
return Qnil;
/* This is here so breakpoints can be put on it. */
static void
-wait_reading_process_output_1 ()
+wait_reading_process_output_1 (void)
{
}
/* Use a wrapper around select to work around a bug in gdb 5.3.
- Normally, the wrapper is optimzed away by inlining.
+ Normally, the wrapper is optimized away by inlining.
If emacs is stopped inside select, the gdb backtrace doesn't
show the function which called select, so it is practically
#ifndef select
static INLINE int
-select_wrapper (n, rfd, wfd, xfd, tmo)
- int n;
- SELECT_TYPE *rfd, *wfd, *xfd;
- EMACS_TIME *tmo;
+select_wrapper (int n, fd_set *rfd, fd_set *wfd, fd_set *xfd, struct timeval *tmo)
{
return select (n, rfd, wfd, xfd, tmo);
}
FD_ZERO (&Connecting);
#endif
+ if (time_limit == 0 && wait_proc && !NILP (Vinhibit_quit)
+ && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
+ message ("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;
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. */
/* If status of something has changed, and no input is
available, notify the user of the change right away. After
this explicit check, we'll let the SIGCHLD handler zap
- timeout to get our attention. When Emacs is run
- interactively, only do this with a nonzero DO_DISPLAY
- argument, because status_notify triggers redisplay. */
- if (update_tick != process_tick
- && (do_display || noninteractive))
+ timeout to get our attention. */
+ if (update_tick != process_tick)
{
SELECT_TYPE Atemp;
#ifdef NON_BLOCKING_CONNECT
SELECT_TYPE Ctemp;
#endif
- Atemp = input_wait_mask;
+ if (kbd_on_hold_p ())
+ FD_ZERO (&Atemp);
+ else
+ Atemp = input_wait_mask;
IF_NON_BLOCKING_CONNECT (Ctemp = connect_wait_mask);
EMACS_SET_SECS_USECS (timeout, 0, 0);
the loop, since timeout has already been zeroed out. */
clear_waiting_for_input ();
status_notify (NULL);
+ if (do_display) redisplay_preserve_echo_area (13);
}
}
/* 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
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)
process_output_skip = 0;
}
#endif
-#ifdef HAVE_NS
- nfds = ns_select
+#if defined (USE_GTK) || defined (HAVE_GCONF)
+ nfds = xg_select
+#elif defined (HAVE_NS)
+ 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
It can't hurt. */
else if (nread == -1 && errno == EIO)
{
- /* Clear the descriptor now, so we only raise the signal once. */
- FD_CLR (channel, &input_wait_mask);
- FD_CLR (channel, &non_keyboard_wait_mask);
+ /* 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);
- kill (getpid (), SIGCHLD);
+ kill (getpid (), SIGCHLD);
+ }
}
#endif /* HAVE_PTYS */
/* If we can detect process termination, don't consider the process
#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))
+ int xlen = sizeof (xerrno);
+ if (getsockopt (channel, SOL_SOCKET, SO_ERROR, &xerrno, &xlen))
xerrno = errno;
}
#else
{
struct sockaddr pname;
- int pnamelen = sizeof(pname);
+ int pnamelen = sizeof (pname);
/* If connection failed, getpeername will fail. */
xerrno = 0;
- if (getpeername(channel, &pname, &pnamelen) < 0)
+ if (getpeername (channel, &pname, &pnamelen) < 0)
{
/* Obtain connect failure code through error slippage. */
char dummy;
xerrno = errno;
- if (errno == ENOTCONN && read(channel, &dummy, 1) < 0)
+ if (errno == ENOTCONN && read (channel, &dummy, 1) < 0)
xerrno = errno;
}
}
/* Given a list (FUNCTION ARGS...), apply FUNCTION to the ARGS. */
static Lisp_Object
-read_process_output_call (fun_and_args)
- Lisp_Object fun_and_args;
+read_process_output_call (Lisp_Object fun_and_args)
{
return apply1 (XCAR (fun_and_args), XCDR (fun_and_args));
}
static Lisp_Object
-read_process_output_error_handler (error)
- Lisp_Object error;
+read_process_output_error_handler (Lisp_Object error)
{
cmd_error_internal (error, "error in process filter: ");
Vinhibit_quit = Qt;
for decoding. */
static int
-read_process_output (proc, channel)
- Lisp_Object proc;
- register int channel;
+read_process_output (Lisp_Object proc, register int 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;
+ int count = SPECPDL_INDEX ();
+ Lisp_Object odeactivate;
chars = (char *) alloca (carryover + readmax);
if (carryover)
/* See the comment above. */
- bcopy (SDATA (p->decoding_buf), chars, carryover);
+ memcpy (chars, SDATA (p->decoding_buf), carryover);
#ifdef DATAGRAM_SOCKETS
/* We have a working select, so proc_buffered_char is always -1. */
/* Now set NBYTES how many bytes we must decode. */
nbytes += carryover;
+ odeactivate = Vdeactivate_mark;
+ /* There's no good reason to let process filters change the current
+ buffer, and many callers of accept-process-output, sit-for, and
+ friends don't expect current-buffer to be changed from under them. */
+ record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
+
/* Read and dispose of the process output. */
outstream = p->filter;
if (!NILP (outstream))
{
- /* We inhibit quit here instead of just catching it so that
- hitting ^G when a filter happens to be running won't screw
- it up. */
- int count = SPECPDL_INDEX ();
- Lisp_Object odeactivate;
Lisp_Object obuffer, okeymap;
Lisp_Object text;
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;
XSETBUFFER (obuffer, current_buffer);
okeymap = current_buffer->keymap;
+ /* We inhibit quit here instead of just catching it so that
+ hitting ^G when a filter happens to be running won't screw
+ it up. */
specbind (Qinhibit_quit, Qt);
specbind (Qlast_nonmenu_event, Qt);
{
if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
p->decoding_buf = make_uninit_string (coding->carryover_bytes);
- bcopy (coding->carryover, SDATA (p->decoding_buf),
- coding->carryover_bytes);
+ memcpy (SDATA (p->decoding_buf), coding->carryover,
+ coding->carryover_bytes);
p->decoding_carryover = coding->carryover_bytes;
}
if (SBYTES (text) > 0)
restore_search_regs ();
running_asynch_code = outer_running_asynch_code;
- /* Handling the process output should not deactivate the mark. */
- Vdeactivate_mark = odeactivate;
-
/* Restore waiting_for_user_input_p as it was
when we were called, in case the filter clobbered it. */
waiting_for_user_input_p = waiting;
cause trouble (for example it would make sit_for return). */
if (waiting_for_user_input_p == -1)
record_asynch_buffer_change ();
-
- unbind_to (count, Qnil);
- return nbytes;
}
/* If no filter, write into buffer if it isn't dead. */
- if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
+ else if (!NILP (p->buffer) && !NILP (XBUFFER (p->buffer)->name))
{
Lisp_Object old_read_only;
int old_begv, old_zv;
int old_begv_byte, old_zv_byte;
- Lisp_Object odeactivate;
int before, before_byte;
int opoint_byte;
Lisp_Object text;
struct buffer *b;
- odeactivate = Vdeactivate_mark;
-
Fset_buffer (p->buffer);
opoint = PT;
opoint_byte = PT_BYTE;
{
if (SCHARS (p->decoding_buf) < coding->carryover_bytes)
p->decoding_buf = make_uninit_string (coding->carryover_bytes);
- bcopy (coding->carryover, SDATA (p->decoding_buf),
- coding->carryover_bytes);
+ memcpy (SDATA (p->decoding_buf), coding->carryover,
+ coding->carryover_bytes);
p->decoding_carryover = coding->carryover_bytes;
}
/* Adjust the multibyteness of TEXT to that of the buffer. */
if (old_begv != BEGV || old_zv != ZV)
Fnarrow_to_region (make_number (old_begv), make_number (old_zv));
- /* Handling the process output should not deactivate the mark. */
- Vdeactivate_mark = odeactivate;
current_buffer->read_only = old_read_only;
SET_PT_BOTH (opoint, opoint_byte);
- set_buffer_internal (old);
}
+ /* Handling the process output should not deactivate the mark. */
+ Vdeactivate_mark = odeactivate;
+
+ unbind_to (count, Qnil);
return nbytes;
}
Lisp_Object process_sent_to;
SIGTYPE
-send_process_trap ()
+send_process_trap (int ignore)
{
SIGNAL_THREAD_CHECK (SIGPIPE);
sigunblock (sigmask (SIGPIPE));
This function can evaluate Lisp code and can garbage collect. */
static void
-send_process (proc, buf, len, object)
- volatile Lisp_Object proc;
- unsigned char *volatile buf;
- volatile int len;
- volatile Lisp_Object object;
+send_process (volatile Lisp_Object proc, unsigned char *volatile buf,
+ volatile int len, volatile Lisp_Object object)
{
/* Use volatile to protect variables from being clobbered by longjmp. */
struct Lisp_Process *p = XPROCESS (proc);
int rv;
struct coding_system *coding;
struct gcpro gcpro1;
- SIGTYPE (*volatile old_sigpipe) ();
+ SIGTYPE (*volatile old_sigpipe) (int);
GCPRO1 (object);
}
else if (STRINGP (object))
{
- encode_coding_string (coding, object, 1);
+ encode_coding_object (coding, object, 0, 0, SCHARS (object),
+ SBYTES (object), Qt);
}
else
{
}
len = coding->produced;
- buf = SDATA (coding->dst_object);
+ object = coding->dst_object;
+ buf = SDATA (object);
}
if (pty_max_bytes == 0)
{
int this = len;
- /* Decide how much data we can send in one batch.
- Long lines need to be split into multiple batches. */
- 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.
- 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
- in the process object. */
- int linepos = 0;
- unsigned char *ptr = (unsigned char *) buf;
- unsigned char *end = (unsigned char *) buf + len;
-
- /* Scan through this text for a line that is too long. */
- while (ptr != end && linepos < pty_max_bytes)
- {
- if (*ptr == '\n')
- linepos = 0;
- else
- linepos++;
- ptr++;
- }
- /* If we found one, break the line there
- and put in a C-d to force the buffer through. */
- this = ptr - buf;
- }
-
/* Send this batch, using one or more write calls. */
while (this > 0)
{
int outfd = p->outfd;
- old_sigpipe = (SIGTYPE (*) ()) signal (SIGPIPE, send_process_trap);
+ old_sigpipe = (SIGTYPE (*) (int)) signal (SIGPIPE, send_process_trap);
#ifdef DATAGRAM_SOCKETS
if (DATAGRAM_CHAN_P (outfd))
{
len -= rv;
this -= rv;
}
-
- /* If we sent just part of the string, put in an EOF (C-d)
- to force it through, before we send the rest. */
- if (len > 0)
- Fprocess_send_eof (proc);
}
}
else
/* Return the foreground process group for the tty/pty that
the process P uses. */
static int
-emacs_get_tty_pgrp (p)
- struct Lisp_Process *p;
+emacs_get_tty_pgrp (struct Lisp_Process *p)
{
int gid = -1;
their uid, for which killpg would return an EPERM error. */
static void
-process_send_signal (process, signo, current_group, nomsg)
- Lisp_Object process;
- int signo;
- Lisp_Object current_group;
- int nomsg;
+process_send_signal (Lisp_Object process, int signo, Lisp_Object current_group,
+ int nomsg)
{
Lisp_Object proc;
register struct Lisp_Process *p;
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;
p->status = Qrun;
p->tick = ++process_tick;
if (!nomsg)
- status_notify (NULL);
+ {
+ status_notify (NULL);
+ redisplay_preserve_echo_area (13);
+ }
break;
#endif /* ! defined (SIGCONT) */
case SIGINT:
CHECK_SYMBOL (sigcode);
name = SDATA (SYMBOL_NAME (sigcode));
- if (!strncmp(name, "SIG", 3) || !strncmp(name, "sig", 3))
+ if (!strncmp (name, "SIG", 3) || !strncmp (name, "sig", 3))
name += 3;
if (0)
if (!proc_encode_coding_system[new_outfd])
proc_encode_coding_system[new_outfd]
= (struct coding_system *) xmalloc (sizeof (struct coding_system));
- bcopy (proc_encode_coding_system[old_outfd],
- proc_encode_coding_system[new_outfd],
- sizeof (struct coding_system));
- bzero (proc_encode_coding_system[old_outfd],
- sizeof (struct coding_system));
+ memcpy (proc_encode_coding_system[new_outfd],
+ proc_encode_coding_system[old_outfd],
+ sizeof (struct coding_system));
+ memset (proc_encode_coding_system[old_outfd], 0,
+ sizeof (struct coding_system));
XPROCESS (proc)->outfd = new_outfd;
}
If `buffer' is nil, kill all processes */
void
-kill_buffer_processes (buffer)
- Lisp_Object buffer;
+kill_buffer_processes (Lisp_Object buffer)
{
Lisp_Object tail, proc;
#ifdef SIGCHLD
SIGTYPE
-sigchld_handler (signo)
- int signo;
+sigchld_handler (int signo)
{
int old_errno = errno;
Lisp_Object proc;
#endif /* no WUNTRACED */
/* Keep trying to get a status until we get a definitive result. */
do
- {
+ {
errno = 0;
pid = wait3 (&w, WNOHANG | WUNTRACED, 0);
}
/* PID == 0 means no processes found, PID == -1 means a real
failure. We have done all our job, so return. */
- /* USG systems forget handlers when they are used;
- must reestablish each time */
-#if defined (USG) && !defined (POSIX_SIGNALS)
- signal (signo, sigchld_handler); /* WARNING - must come after wait3() */
-#endif
errno = old_errno;
return;
}
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. */
to use up all the processes that have something to tell us. */
#if (defined WINDOWSNT \
|| (defined USG && !defined GNU_LINUX \
- && !(defined HPUX && defined WNOHANG)))
-#if defined (USG) && ! defined (POSIX_SIGNALS)
- signal (signo, sigchld_handler);
-#endif
+ && !(defined HPUX && defined WNOHANG)))
errno = old_errno;
return;
#endif /* USG, but not HPUX with WNOHANG */
\f
static Lisp_Object
-exec_sentinel_unwind (data)
- Lisp_Object data;
+exec_sentinel_unwind (Lisp_Object data)
{
XPROCESS (XCAR (data))->sentinel = XCDR (data);
return Qnil;
}
static Lisp_Object
-exec_sentinel_error_handler (error)
- Lisp_Object error;
+exec_sentinel_error_handler (Lisp_Object error)
{
cmd_error_internal (error, "error in process sentinel: ");
Vinhibit_quit = Qt;
}
static void
-exec_sentinel (proc, reason)
- Lisp_Object proc, reason;
+exec_sentinel (Lisp_Object proc, Lisp_Object reason)
{
Lisp_Object sentinel, obuffer, odeactivate, okeymap;
register struct Lisp_Process *p = XPROCESS (proc);
XSETBUFFER (obuffer, current_buffer);
okeymap = current_buffer->keymap;
+ /* There's no good reason to let sentinels change the current
+ buffer, and many callers of accept-process-output, sit-for, and
+ friends don't expect current-buffer to be changed from under them. */
+ record_unwind_protect (set_buffer_if_live, Fcurrent_buffer ());
+
sentinel = p->sentinel;
if (NILP (sentinel))
return;
record_unwind_protect (exec_sentinel_unwind, Fcons (proc, sentinel));
/* Inhibit quit so that random quits don't screw up a running filter. */
specbind (Qinhibit_quit, Qt);
- specbind (Qlast_nonmenu_event, Qt);
+ specbind (Qlast_nonmenu_event, Qt); /* Why? --Stef */
/* In case we get recursively called,
and we already saved the match data nonrecursively,
but can be done at other times. */
static void
-status_notify (deleting_process)
- struct Lisp_Process *deleting_process;
+status_notify (struct Lisp_Process *deleting_process)
{
register Lisp_Object proc, buffer;
Lisp_Object tail, msg;
when a process becomes runnable. */
else if (!EQ (symbol, Qrun) && !NILP (buffer))
{
- Lisp_Object ro, tem;
+ Lisp_Object tem;
struct buffer *old = current_buffer;
int opoint, opoint_byte;
int before, before_byte;
- ro = XBUFFER (buffer)->read_only;
-
/* Avoid error if buffer is deleted
(probably that's why the process is dead, too) */
if (NILP (XBUFFER (buffer)->name))
} /* end for */
update_mode_lines++; /* in case buffers use %s in mode-line-format */
- redisplay_preserve_echo_area (13);
-
UNGCPRO;
}
\f
+/* Stop reading input from keyboard sources. */
+
+void
+hold_keyboard_input (void)
+{
+ kbd_is_on_hold = 1;
+}
+
+/* Resume reading input from keyboard sources. */
+
+void
+unhold_keyboard_input (void)
+{
+ kbd_is_on_hold = 0;
+}
+
+/* Return non-zero if keyboard input is on hold, zero otherwise. */
+
+int
+kbd_on_hold_p (void)
+{
+ return kbd_is_on_hold;
+}
+
/* Add DESC to the set of keyboard input descriptors. */
void
-add_keyboard_wait_descriptor (desc)
- int desc;
+add_keyboard_wait_descriptor (int desc)
{
FD_SET (desc, &input_wait_mask);
FD_SET (desc, &non_process_wait_mask);
static int add_gpm_wait_descriptor_called_flag;
void
-add_gpm_wait_descriptor (desc)
- int desc;
+add_gpm_wait_descriptor (int desc)
{
if (! add_gpm_wait_descriptor_called_flag)
FD_CLR (0, &input_wait_mask);
/* From now on, do not expect DESC to give keyboard input. */
void
-delete_keyboard_wait_descriptor (desc)
- int desc;
+delete_keyboard_wait_descriptor (int desc)
{
int fd;
int lim = max_keyboard_desc;
}
void
-delete_gpm_wait_descriptor (desc)
- int desc;
+delete_gpm_wait_descriptor (int desc)
{
int fd;
int lim = max_gpm_desc;
that corresponds to one of the keyboard input descriptors. */
static int
-keyboard_bit_set (mask)
- SELECT_TYPE *mask;
+keyboard_bit_set (fd_set *mask)
{
int fd;
doc: /* Return a list of numerical process IDs of all running processes.
If this functionality is unsupported, return nil.
-See `system-process-attributes' for getting attributes of a process
-given its ID. */)
+See `process-attributes' for getting attributes of a process given its ID. */)
()
{
return list_system_processes ();
}
-DEFUN ("system-process-attributes", Fsystem_process_attributes,
- Ssystem_process_attributes, 1, 1, 0,
+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
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)
}
\f
void
-init_process ()
+init_process (void)
{
register int i;
chan_process[i] = Qnil;
proc_buffered_char[i] = -1;
}
- bzero (proc_decode_coding_system, sizeof proc_decode_coding_system);
- bzero (proc_encode_coding_system, sizeof proc_encode_coding_system);
+ memset (proc_decode_coding_system, 0, sizeof proc_decode_coding_system);
+ memset (proc_encode_coding_system, 0, sizeof proc_encode_coding_system);
#ifdef DATAGRAM_SOCKETS
- bzero (datagram_address, sizeof datagram_address);
+ memset (datagram_address, 0, sizeof datagram_address);
#endif
#ifdef HAVE_SOCKETS
{
Lisp_Object subfeatures = Qnil;
- struct socket_options *sopt;
+ const struct socket_options *sopt;
#define ADD_SUBFEATURE(key, val) \
- subfeatures = Fcons (Fcons (key, Fcons (val, Qnil)), subfeatures)
+ subfeatures = pure_cons (pure_cons (key, pure_cons (val, Qnil)), subfeatures)
#ifdef NON_BLOCKING_CONNECT
ADD_SUBFEATURE (QCnowait, Qt);
#ifdef DATAGRAM_SOCKETS
ADD_SUBFEATURE (QCtype, Qdatagram);
#endif
+#ifdef HAVE_SEQPACKET
+ ADD_SUBFEATURE (QCtype, Qseqpacket);
+#endif
#ifdef HAVE_LOCAL_SOCKETS
ADD_SUBFEATURE (QCfamily, Qlocal);
#endif
#endif
for (sopt = socket_options; sopt->name; sopt++)
- subfeatures = Fcons (intern (sopt->name), subfeatures);
+ subfeatures = pure_cons (intern_c_string (sopt->name), subfeatures);
- Fprovide (intern ("make-network-process"), subfeatures);
+ Fprovide (intern_c_string ("make-network-process"), subfeatures);
}
#endif /* HAVE_SOCKETS */
processes. As such, we only change the default value. */
if (initialized)
{
- char *release = get_operating_system_release();
+ char *release = get_operating_system_release ();
if (!release || !release[0] || (release[0] < MIN_PTY_KERNEL_VERSION
&& release[1] == '.')) {
Vprocess_connection_type = Qnil;
}
void
-syms_of_process ()
+syms_of_process (void)
{
- Qprocessp = intern ("processp");
+ Qprocessp = intern_c_string ("processp");
staticpro (&Qprocessp);
- Qrun = intern ("run");
+ Qrun = intern_c_string ("run");
staticpro (&Qrun);
- Qstop = intern ("stop");
+ Qstop = intern_c_string ("stop");
staticpro (&Qstop);
- Qsignal = intern ("signal");
+ Qsignal = intern_c_string ("signal");
staticpro (&Qsignal);
/* Qexit is already staticpro'd by syms_of_eval; don't staticpro it
here again.
- Qexit = intern ("exit");
+ Qexit = intern_c_string ("exit");
staticpro (&Qexit); */
- Qopen = intern ("open");
+ Qopen = intern_c_string ("open");
staticpro (&Qopen);
- Qclosed = intern ("closed");
+ Qclosed = intern_c_string ("closed");
staticpro (&Qclosed);
- Qconnect = intern ("connect");
+ Qconnect = intern_c_string ("connect");
staticpro (&Qconnect);
- Qfailed = intern ("failed");
+ Qfailed = intern_c_string ("failed");
staticpro (&Qfailed);
- Qlisten = intern ("listen");
+ Qlisten = intern_c_string ("listen");
staticpro (&Qlisten);
- Qlocal = intern ("local");
+ Qlocal = intern_c_string ("local");
staticpro (&Qlocal);
- Qipv4 = intern ("ipv4");
+ Qipv4 = intern_c_string ("ipv4");
staticpro (&Qipv4);
#ifdef AF_INET6
- Qipv6 = intern ("ipv6");
+ Qipv6 = intern_c_string ("ipv6");
staticpro (&Qipv6);
#endif
- Qdatagram = intern ("datagram");
+ Qdatagram = intern_c_string ("datagram");
staticpro (&Qdatagram);
+ Qseqpacket = intern_c_string ("seqpacket");
+ staticpro (&Qseqpacket);
- QCport = intern (":port");
+ QCport = intern_c_string (":port");
staticpro (&QCport);
- QCspeed = intern (":speed");
+ QCspeed = intern_c_string (":speed");
staticpro (&QCspeed);
- QCprocess = intern (":process");
+ QCprocess = intern_c_string (":process");
staticpro (&QCprocess);
- QCbytesize = intern (":bytesize");
+ QCbytesize = intern_c_string (":bytesize");
staticpro (&QCbytesize);
- QCstopbits = intern (":stopbits");
+ QCstopbits = intern_c_string (":stopbits");
staticpro (&QCstopbits);
- QCparity = intern (":parity");
+ QCparity = intern_c_string (":parity");
staticpro (&QCparity);
- Qodd = intern ("odd");
+ Qodd = intern_c_string ("odd");
staticpro (&Qodd);
- Qeven = intern ("even");
+ Qeven = intern_c_string ("even");
staticpro (&Qeven);
- QCflowcontrol = intern (":flowcontrol");
+ QCflowcontrol = intern_c_string (":flowcontrol");
staticpro (&QCflowcontrol);
- Qhw = intern ("hw");
+ Qhw = intern_c_string ("hw");
staticpro (&Qhw);
- Qsw = intern ("sw");
+ Qsw = intern_c_string ("sw");
staticpro (&Qsw);
- QCsummary = intern (":summary");
+ QCsummary = intern_c_string (":summary");
staticpro (&QCsummary);
- Qreal = intern ("real");
+ Qreal = intern_c_string ("real");
staticpro (&Qreal);
- Qnetwork = intern ("network");
+ Qnetwork = intern_c_string ("network");
staticpro (&Qnetwork);
- Qserial = intern ("serial");
+ Qserial = intern_c_string ("serial");
staticpro (&Qserial);
- QCname = intern (":name");
+ QCname = intern_c_string (":name");
staticpro (&QCname);
- QCbuffer = intern (":buffer");
+ QCbuffer = intern_c_string (":buffer");
staticpro (&QCbuffer);
- QChost = intern (":host");
+ QChost = intern_c_string (":host");
staticpro (&QChost);
- QCservice = intern (":service");
+ QCservice = intern_c_string (":service");
staticpro (&QCservice);
- QCtype = intern (":type");
+ QCtype = intern_c_string (":type");
staticpro (&QCtype);
- QClocal = intern (":local");
+ QClocal = intern_c_string (":local");
staticpro (&QClocal);
- QCremote = intern (":remote");
+ QCremote = intern_c_string (":remote");
staticpro (&QCremote);
- QCcoding = intern (":coding");
+ QCcoding = intern_c_string (":coding");
staticpro (&QCcoding);
- QCserver = intern (":server");
+ QCserver = intern_c_string (":server");
staticpro (&QCserver);
- QCnowait = intern (":nowait");
+ QCnowait = intern_c_string (":nowait");
staticpro (&QCnowait);
- QCsentinel = intern (":sentinel");
+ QCsentinel = intern_c_string (":sentinel");
staticpro (&QCsentinel);
- QClog = intern (":log");
+ QClog = intern_c_string (":log");
staticpro (&QClog);
- QCnoquery = intern (":noquery");
+ QCnoquery = intern_c_string (":noquery");
staticpro (&QCnoquery);
- QCstop = intern (":stop");
+ QCstop = intern_c_string (":stop");
staticpro (&QCstop);
- QCoptions = intern (":options");
+ QCoptions = intern_c_string (":options");
staticpro (&QCoptions);
- QCplist = intern (":plist");
+ QCplist = intern_c_string (":plist");
staticpro (&QCplist);
- Qlast_nonmenu_event = intern ("last-nonmenu-event");
+ Qlast_nonmenu_event = intern_c_string ("last-nonmenu-event");
staticpro (&Qlast_nonmenu_event);
staticpro (&Vprocess_alist);
staticpro (&deleted_pid_list);
#endif
- Qeuid = intern ("euid");
+ Qeuid = intern_c_string ("euid");
staticpro (&Qeuid);
- Qegid = intern ("egid");
+ Qegid = intern_c_string ("egid");
staticpro (&Qegid);
- Quser = intern ("user");
+ Quser = intern_c_string ("user");
staticpro (&Quser);
- Qgroup = intern ("group");
+ Qgroup = intern_c_string ("group");
staticpro (&Qgroup);
- Qcomm = intern ("comm");
+ Qcomm = intern_c_string ("comm");
staticpro (&Qcomm);
- Qstate = intern ("state");
+ Qstate = intern_c_string ("state");
staticpro (&Qstate);
- Qppid = intern ("ppid");
+ Qppid = intern_c_string ("ppid");
staticpro (&Qppid);
- Qpgrp = intern ("pgrp");
+ Qpgrp = intern_c_string ("pgrp");
staticpro (&Qpgrp);
- Qsess = intern ("sess");
+ Qsess = intern_c_string ("sess");
staticpro (&Qsess);
- Qttname = intern ("ttname");
+ Qttname = intern_c_string ("ttname");
staticpro (&Qttname);
- Qtpgid = intern ("tpgid");
+ Qtpgid = intern_c_string ("tpgid");
staticpro (&Qtpgid);
- Qminflt = intern ("minflt");
+ Qminflt = intern_c_string ("minflt");
staticpro (&Qminflt);
- Qmajflt = intern ("majflt");
+ Qmajflt = intern_c_string ("majflt");
staticpro (&Qmajflt);
- Qcminflt = intern ("cminflt");
+ Qcminflt = intern_c_string ("cminflt");
staticpro (&Qcminflt);
- Qcmajflt = intern ("cmajflt");
+ Qcmajflt = intern_c_string ("cmajflt");
staticpro (&Qcmajflt);
- Qutime = intern ("utime");
+ Qutime = intern_c_string ("utime");
staticpro (&Qutime);
- Qstime = intern ("stime");
+ Qstime = intern_c_string ("stime");
staticpro (&Qstime);
- Qcutime = intern ("cutime");
+ Qtime = intern_c_string ("time");
+ staticpro (&Qtime);
+ Qcutime = intern_c_string ("cutime");
staticpro (&Qcutime);
- Qcstime = intern ("cstime");
+ Qcstime = intern_c_string ("cstime");
staticpro (&Qcstime);
- Qpri = intern ("pri");
+ Qctime = intern_c_string ("ctime");
+ staticpro (&Qctime);
+ Qpri = intern_c_string ("pri");
staticpro (&Qpri);
- Qnice = intern ("nice");
+ Qnice = intern_c_string ("nice");
staticpro (&Qnice);
- Qthcount = intern ("thcount");
+ Qthcount = intern_c_string ("thcount");
staticpro (&Qthcount);
- Qstart = intern ("start");
+ Qstart = intern_c_string ("start");
staticpro (&Qstart);
- Qvsize = intern ("vsize");
+ Qvsize = intern_c_string ("vsize");
staticpro (&Qvsize);
- Qrss = intern ("rss");
+ Qrss = intern_c_string ("rss");
staticpro (&Qrss);
- Qetime = intern ("etime");
+ Qetime = intern_c_string ("etime");
staticpro (&Qetime);
- Qpcpu = intern ("pcpu");
+ Qpcpu = intern_c_string ("pcpu");
staticpro (&Qpcpu);
- Qpmem = intern ("pmem");
+ Qpmem = intern_c_string ("pmem");
staticpro (&Qpmem);
- Qargs = intern ("args");
+ Qargs = intern_c_string ("args");
staticpro (&Qargs);
DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,
defsubr (&Sset_process_filter_multibyte);
defsubr (&Sprocess_filter_multibyte_p);
defsubr (&Slist_system_processes);
- defsubr (&Ssystem_process_attributes);
+ defsubr (&Sprocess_attributes);
}
\f
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
+#include <setjmp.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
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:
Wait for timeout to elapse and/or keyboard input to be available.
doc: /* Return a list of numerical process IDs of all running processes.
If this functionality is unsupported, return nil.
-See `system-process-attributes' for getting attributes of a process
-given its ID. */)
+See `process-attributes' for getting attributes of a process given its ID. */)
()
{
return list_system_processes ();
}
-DEFUN ("system-process-attributes", Fsystem_process_attributes,
- Ssystem_process_attributes, 1, 1, 0,
+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
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)
void
init_process ()
{
+ kbd_is_on_hold = 0;
}
void
syms_of_process ()
{
- QCtype = intern (":type");
+ QCtype = intern_c_string (":type");
+ staticpro (&QCtype);
+ QCname = intern_c_string (":name");
+ staticpro (&QCname);
+ QCtype = intern_c_string (":type");
staticpro (&QCtype);
- QCname = intern (":name");
+ QCname = intern_c_string (":name");
staticpro (&QCname);
+ 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);
defsubr (&Sget_buffer_process);
defsubr (&Sprocess_inherit_coding_system_flag);
defsubr (&Slist_system_processes);
- defsubr (&Ssystem_process_attributes);
+ defsubr (&Sprocess_attributes);
}
\f