aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDan Nicolaescu2008-12-19 19:50:35 +0000
committerDan Nicolaescu2008-12-19 19:50:35 +0000
commit06e111a6efbbe275e8f7c364ff8e5955d1ab75f0 (patch)
tree3ed4dc7cbf6c74663a3c4bd4c35b71e40ab2e3e9 /src
parent349b3256608412d33ddabc7c3f9b429123e7c353 (diff)
downloademacs-06e111a6efbbe275e8f7c364ff8e5955d1ab75f0.tar.gz
emacs-06e111a6efbbe275e8f7c364ff8e5955d1ab75f0.zip
Reorganize implementation of Flist_system_processes and
Fsystem_process_attributes. No functional changes. * process.c: Don't #include pwd.h, grp.h and limits.h. (Flist_system_processes): Just call list_system_processes. (Fsystem_process_attributes): Just call system_process_attributes. (procfs_list_system_processes, time_from_jiffies) (ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR) (procfs_get_total_memory, procfs_system_process_attributes): Move ... * sysdep.c: ... here. Include pwd.h, grp.h and limits.h. (list_system_processes): Rename from procfs_list_system_processes. Enclose in #ifdef HAVE_PROCFS. Provide a do nothing implementation. (system_process_attributes): Rename from procfs_list_system_processes. (ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR) (procfs_get_total_memory): Enclose in #ifdef GNU_LINUX. * w32.c (list_system_processes): Rename from w32_list_system_processes. (system_process_attributes): Rename from w32_system_process_attributes. * s/gnu-linux.h (LISTPROC, PROCATTR): Remove. * process.h (w32_list_system_processes) (w32_system_process_attributes): Remove. (list_system_processes, system_process_attributes): New prototypes. * config.nt (LISTPROC, PROCATTR): Remove.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog32
-rw-r--r--src/process.c439
-rw-r--r--src/process.h6
-rw-r--r--src/s/gnu-linux.h4
-rw-r--r--src/sysdep.c444
-rw-r--r--src/w32.c4
6 files changed, 484 insertions, 445 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 53654f413f5..4bc6d54c1a0 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,35 @@
12008-12-19 Dan Nicolaescu <dann@ics.uci.edu>
2
3 Reorganize implementation of Flist_system_processes and
4 Fsystem_process_attributes. No functional changes.
5 * process.c: Don't #include pwd.h, grp.h and limits.h.
6 (Flist_system_processes): Just call list_system_processes.
7 (Fsystem_process_attributes): Just call system_process_attributes.
8 (procfs_list_system_processes, time_from_jiffies)
9 (ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR)
10 (procfs_get_total_memory, procfs_system_process_attributes): Move ...
11
12 * sysdep.c: ... here. Include pwd.h, grp.h and limits.h.
13 (list_system_processes): Rename from
14 procfs_list_system_processes. Enclose in #ifdef HAVE_PROCFS.
15 Provide a do nothing implementation.
16 (system_process_attributes): Rename from
17 procfs_list_system_processes.
18 (ltime_from_jiffies, get_up_time, procfs_ttyname, MAJOR, MINOR)
19 (procfs_get_total_memory): Enclose in #ifdef GNU_LINUX.
20
21 * w32.c (list_system_processes): Rename from
22 w32_list_system_processes.
23 (system_process_attributes): Rename from
24 w32_system_process_attributes.
25
26 * s/gnu-linux.h (LISTPROC, PROCATTR): Remove.
27
28 * process.h (w32_list_system_processes)
29 (w32_system_process_attributes): Remove.
30 (list_system_processes, system_process_attributes): New
31 prototypes.
32
12008-12-19 Kenichi Handa <handa@m17n.org> 332008-12-19 Kenichi Handa <handa@m17n.org>
2 34
3 * xfont.c (xfont_decode_coding_xlfd): New function. 35 * xfont.c (xfont_decode_coding_xlfd): New function.
diff --git a/src/process.c b/src/process.c
index 0f3373b5db0..4172ffe1f50 100644
--- a/src/process.c
+++ b/src/process.c
@@ -33,8 +33,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33#ifdef subprocesses 33#ifdef subprocesses
34 34
35#include <stdio.h> 35#include <stdio.h>
36#include <stdlib.h>
37#include <ctype.h>
38#include <errno.h> 36#include <errno.h>
39#include <setjmp.h> 37#include <setjmp.h>
40#include <sys/types.h> /* some typedefs are used in sys/file.h */ 38#include <sys/types.h> /* some typedefs are used in sys/file.h */
@@ -44,11 +42,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
44#include <inttypes.h> 42#include <inttypes.h>
45#endif 43#endif
46 44
47#ifdef HAVE_PWD_H
48#include <pwd.h>
49#include <grp.h>
50#endif
51
52#ifdef HAVE_UNISTD_H 45#ifdef HAVE_UNISTD_H
53#include <unistd.h> 46#include <unistd.h>
54#endif 47#endif
@@ -104,10 +97,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
104#include <resolv.h> 97#include <resolv.h>
105#endif 98#endif
106 99
107#ifdef HAVE_LIMITS_H
108#include <limits.h>
109#endif /* HAVE_LIMITS_H */
110
111#include "lisp.h" 100#include "lisp.h"
112#include "systime.h" 101#include "systime.h"
113#include "systty.h" 102#include "systty.h"
@@ -7073,422 +7062,6 @@ keyboard_bit_set (mask)
7073 7062
7074/* Enumeration of and access to system processes a-la ps(1). */ 7063/* Enumeration of and access to system processes a-la ps(1). */
7075 7064
7076#if HAVE_PROCFS
7077
7078/* Process enumeration and access via /proc. */
7079
7080static Lisp_Object
7081procfs_list_system_processes ()
7082{
7083 Lisp_Object procdir, match, proclist, next;
7084 struct gcpro gcpro1, gcpro2;
7085 register Lisp_Object tail;
7086
7087 GCPRO2 (procdir, match);
7088 /* For every process on the system, there's a directory in the
7089 "/proc" pseudo-directory whose name is the numeric ID of that
7090 process. */
7091 procdir = build_string ("/proc");
7092 match = build_string ("[0-9]+");
7093 proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
7094
7095 /* `proclist' gives process IDs as strings. Destructively convert
7096 each string into a number. */
7097 for (tail = proclist; CONSP (tail); tail = next)
7098 {
7099 next = XCDR (tail);
7100 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
7101 }
7102 UNGCPRO;
7103
7104 /* directory_files_internal returns the files in reverse order; undo
7105 that. */
7106 proclist = Fnreverse (proclist);
7107 return proclist;
7108}
7109
7110static void
7111time_from_jiffies (unsigned long long tval, long hz,
7112 time_t *sec, unsigned *usec)
7113{
7114 unsigned long long ullsec;
7115
7116 *sec = tval / hz;
7117 ullsec = *sec;
7118 tval -= ullsec * hz;
7119 /* Careful: if HZ > 1 million, then integer division by it yields zero. */
7120 if (hz <= 1000000)
7121 *usec = tval * 1000000 / hz;
7122 else
7123 *usec = tval / (hz / 1000000);
7124}
7125
7126static Lisp_Object
7127ltime_from_jiffies (unsigned long long tval, long hz)
7128{
7129 time_t sec;
7130 unsigned usec;
7131
7132 time_from_jiffies (tval, hz, &sec, &usec);
7133
7134 return list3 (make_number ((sec >> 16) & 0xffff),
7135 make_number (sec & 0xffff),
7136 make_number (usec));
7137}
7138
7139static void
7140get_up_time (time_t *sec, unsigned *usec)
7141{
7142 FILE *fup;
7143
7144 *sec = *usec = 0;
7145
7146 BLOCK_INPUT;
7147 fup = fopen ("/proc/uptime", "r");
7148
7149 if (fup)
7150 {
7151 double uptime, idletime;
7152
7153 /* The numbers in /proc/uptime use C-locale decimal point, but
7154 we already set ourselves to the C locale (see `fixup_locale'
7155 in emacs.c). */
7156 if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
7157 {
7158 *sec = uptime;
7159 *usec = (uptime - *sec) * 1000000;
7160 }
7161 fclose (fup);
7162 }
7163 UNBLOCK_INPUT;
7164}
7165
7166#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
7167#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
7168
7169static Lisp_Object
7170procfs_ttyname (rdev)
7171{
7172 FILE *fdev = NULL;
7173 char name[PATH_MAX];
7174
7175 BLOCK_INPUT;
7176 fdev = fopen ("/proc/tty/drivers", "r");
7177
7178 if (fdev)
7179 {
7180 unsigned major;
7181 unsigned long minor_beg, minor_end;
7182 char minor[25]; /* 2 32-bit numbers + dash */
7183 char *endp;
7184
7185 while (!feof (fdev) && !ferror (fdev))
7186 {
7187 if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
7188 && major == MAJOR (rdev))
7189 {
7190 minor_beg = strtoul (minor, &endp, 0);
7191 if (*endp == '\0')
7192 minor_end = minor_beg;
7193 else if (*endp == '-')
7194 minor_end = strtoul (endp + 1, &endp, 0);
7195 else
7196 continue;
7197
7198 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
7199 {
7200 sprintf (name + strlen (name), "%lu", MINOR (rdev));
7201 break;
7202 }
7203 }
7204 }
7205 fclose (fdev);
7206 }
7207 UNBLOCK_INPUT;
7208 return build_string (name);
7209}
7210
7211static unsigned long
7212procfs_get_total_memory (void)
7213{
7214 FILE *fmem = NULL;
7215 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
7216
7217 BLOCK_INPUT;
7218 fmem = fopen ("/proc/meminfo", "r");
7219
7220 if (fmem)
7221 {
7222 unsigned long entry_value;
7223 char entry_name[20]; /* the longest I saw is 13+1 */
7224
7225 while (!feof (fmem) && !ferror (fmem))
7226 {
7227 if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
7228 && strcmp (entry_name, "MemTotal:") == 0)
7229 {
7230 retval = entry_value;
7231 break;
7232 }
7233 }
7234 fclose (fmem);
7235 }
7236 UNBLOCK_INPUT;
7237 return retval;
7238}
7239
7240static Lisp_Object
7241procfs_system_process_attributes (pid)
7242 Lisp_Object pid;
7243{
7244 char procfn[PATH_MAX], fn[PATH_MAX];
7245 struct stat st;
7246 struct passwd *pw;
7247 struct group *gr;
7248 long clocks_per_sec;
7249 char *procfn_end;
7250 char procbuf[1025], *p, *q;
7251 int fd;
7252 ssize_t nread;
7253 const char *cmd = NULL;
7254 char *cmdline = NULL;
7255 size_t cmdsize = 0, cmdline_size;
7256 unsigned char c;
7257 int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
7258 unsigned long long utime, stime, cutime, cstime, start;
7259 long priority, nice, rss;
7260 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
7261 time_t sec;
7262 unsigned usec;
7263 EMACS_TIME tnow, tstart, tboot, telapsed,ttotal;
7264 double pcpu, pmem;
7265 Lisp_Object attrs = Qnil;
7266 Lisp_Object cmd_str, decoded_cmd, tem;
7267 struct gcpro gcpro1, gcpro2;
7268 EMACS_INT uid_eint, gid_eint;
7269
7270 CHECK_NUMBER_OR_FLOAT (pid);
7271 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
7272 sprintf (procfn, "/proc/%lu", proc_id);
7273 if (stat (procfn, &st) < 0)
7274 return attrs;
7275
7276 GCPRO2 (attrs, decoded_cmd);
7277
7278 /* euid egid */
7279 uid = st.st_uid;
7280 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
7281 uid_eint = uid;
7282 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
7283 BLOCK_INPUT;
7284 pw = getpwuid (uid);
7285 UNBLOCK_INPUT;
7286 if (pw)
7287 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
7288
7289 gid = st.st_gid;
7290 gid_eint = gid;
7291 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
7292 BLOCK_INPUT;
7293 gr = getgrgid (gid);
7294 UNBLOCK_INPUT;
7295 if (gr)
7296 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
7297
7298 strcpy (fn, procfn);
7299 procfn_end = fn + strlen (fn);
7300 strcpy (procfn_end, "/stat");
7301 fd = emacs_open (fn, O_RDONLY, 0);
7302 if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof(procbuf) - 1)) > 0)
7303 {
7304 procbuf[nread] = '\0';
7305 p = procbuf;
7306
7307 p = strchr (p, '(');
7308 if (p != NULL)
7309 {
7310 q = strrchr (p + 1, ')');
7311 /* comm */
7312 if (q != NULL)
7313 {
7314 cmd = p + 1;
7315 cmdsize = q - cmd;
7316 }
7317 }
7318 else
7319 q = NULL;
7320 if (cmd == NULL)
7321 {
7322 cmd = "???";
7323 cmdsize = 3;
7324 }
7325 /* Command name is encoded in locale-coding-system; decode it. */
7326 cmd_str = make_unibyte_string (cmd, cmdsize);
7327 decoded_cmd = code_convert_string_norecord (cmd_str,
7328 Vlocale_coding_system, 0);
7329 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
7330
7331 if (q)
7332 {
7333 EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
7334 p = q + 2;
7335 /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
7336 sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
7337 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
7338 &minflt, &cminflt, &majflt, &cmajflt,
7339 &utime, &stime, &cutime, &cstime,
7340 &priority, &nice, &thcount, &start, &vsize, &rss);
7341 {
7342 char state_str[2];
7343
7344 state_str[0] = c;
7345 state_str[1] = '\0';
7346 tem = build_string (state_str);
7347 attrs = Fcons (Fcons (Qstate, tem), attrs);
7348 }
7349 /* Stops GCC whining about limited range of data type. */
7350 ppid_eint = ppid;
7351 pgrp_eint = pgrp;
7352 sess_eint = sess;
7353 tpgid_eint = tpgid;
7354 thcount_eint = thcount;
7355 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
7356 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
7357 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
7358 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
7359 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
7360 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
7361 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
7362 attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
7363 attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
7364 clocks_per_sec = sysconf (_SC_CLK_TCK);
7365 if (clocks_per_sec < 0)
7366 clocks_per_sec = 100;
7367 attrs = Fcons (Fcons (Qutime,
7368 ltime_from_jiffies (utime, clocks_per_sec)),
7369 attrs);
7370 attrs = Fcons (Fcons (Qstime,
7371 ltime_from_jiffies (stime, clocks_per_sec)),
7372 attrs);
7373 attrs = Fcons (Fcons (Qcutime,
7374 ltime_from_jiffies (cutime, clocks_per_sec)),
7375 attrs);
7376 attrs = Fcons (Fcons (Qcstime,
7377 ltime_from_jiffies (cstime, clocks_per_sec)),
7378 attrs);
7379 attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
7380 attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
7381 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
7382 EMACS_GET_TIME (tnow);
7383 get_up_time (&sec, &usec);
7384 EMACS_SET_SECS (telapsed, sec);
7385 EMACS_SET_USECS (telapsed, usec);
7386 EMACS_SUB_TIME (tboot, tnow, telapsed);
7387 time_from_jiffies (start, clocks_per_sec, &sec, &usec);
7388 EMACS_SET_SECS (tstart, sec);
7389 EMACS_SET_USECS (tstart, usec);
7390 EMACS_ADD_TIME (tstart, tboot, tstart);
7391 attrs = Fcons (Fcons (Qstart,
7392 list3 (make_number
7393 ((EMACS_SECS (tstart) >> 16) & 0xffff),
7394 make_number
7395 (EMACS_SECS (tstart) & 0xffff),
7396 make_number
7397 (EMACS_USECS (tstart)))),
7398 attrs);
7399 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
7400 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
7401 EMACS_SUB_TIME (telapsed, tnow, tstart);
7402 attrs = Fcons (Fcons (Qetime,
7403 list3 (make_number
7404 ((EMACS_SECS (telapsed) >> 16) & 0xffff),
7405 make_number
7406 (EMACS_SECS (telapsed) & 0xffff),
7407 make_number
7408 (EMACS_USECS (telapsed)))),
7409 attrs);
7410 time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
7411 pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
7412 if (pcpu > 1.0)
7413 pcpu = 1.0;
7414 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
7415 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
7416 if (pmem > 100)
7417 pmem = 100;
7418 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
7419 }
7420 }
7421 if (fd >= 0)
7422 emacs_close (fd);
7423
7424 /* args */
7425 strcpy (procfn_end, "/cmdline");
7426 fd = emacs_open (fn, O_RDONLY, 0);
7427 if (fd >= 0)
7428 {
7429 for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
7430 {
7431 if (isspace (c) || c == '\\')
7432 cmdline_size++; /* for later quoting, see below */
7433 }
7434 if (cmdline_size)
7435 {
7436 cmdline = xmalloc (cmdline_size + 1);
7437 lseek (fd, 0L, SEEK_SET);
7438 cmdline[0] = '\0';
7439 if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
7440 cmdline[nread++] = '\0';
7441 else
7442 {
7443 /* Assigning zero to `nread' makes us skip the following
7444 two loops, assign zero to cmdline_size, and enter the
7445 following `if' clause that handles unknown command
7446 lines. */
7447 nread = 0;
7448 }
7449 /* We don't want trailing null characters. */
7450 for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
7451 nread--;
7452 for (p = cmdline; p < cmdline + nread; p++)
7453 {
7454 /* Escape-quote whitespace and backslashes. */
7455 if (isspace (*p) || *p == '\\')
7456 {
7457 memmove (p + 1, p, nread - (p - cmdline));
7458 nread++;
7459 *p++ = '\\';
7460 }
7461 else if (*p == '\0')
7462 *p = ' ';
7463 }
7464 cmdline_size = nread;
7465 }
7466 if (!cmdline_size)
7467 {
7468 if (!cmd)
7469 cmd = "???";
7470 if (!cmdsize)
7471 cmdsize = strlen (cmd);
7472 cmdline_size = cmdsize + 2;
7473 cmdline = xmalloc (cmdline_size + 1);
7474 strcpy (cmdline, "[");
7475 strcat (strncat (cmdline, cmd, cmdsize), "]");
7476 }
7477 emacs_close (fd);
7478 /* Command line is encoded in locale-coding-system; decode it. */
7479 cmd_str = make_unibyte_string (cmdline, cmdline_size);
7480 decoded_cmd = code_convert_string_norecord (cmd_str,
7481 Vlocale_coding_system, 0);
7482 xfree (cmdline);
7483 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
7484 }
7485
7486 UNGCPRO;
7487 return attrs;
7488}
7489
7490#endif /* !HAVE_PROCFS */
7491
7492DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes, 7065DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes,
7493 0, 0, 0, 7066 0, 0, 0,
7494 doc: /* Return a list of numerical process IDs of all running processes. 7067 doc: /* Return a list of numerical process IDs of all running processes.
@@ -7498,11 +7071,7 @@ See `system-process-attributes' for getting attributes of a process
7498given its ID. */) 7071given its ID. */)
7499 () 7072 ()
7500{ 7073{
7501#ifdef LISTPROC 7074 return list_system_processes ();
7502 return LISTPROC ();
7503#else
7504 return Qnil;
7505#endif
7506} 7075}
7507 7076
7508DEFUN ("system-process-attributes", Fsystem_process_attributes, 7077DEFUN ("system-process-attributes", Fsystem_process_attributes,
@@ -7558,11 +7127,7 @@ integer or floating point values.
7558 7127
7559 Lisp_Object pid; 7128 Lisp_Object pid;
7560{ 7129{
7561#ifdef PROCATTR 7130 return system_process_attributes (pid);
7562 return PROCATTR (pid);
7563#else
7564 return Qnil;
7565#endif
7566} 7131}
7567 7132
7568void 7133void
diff --git a/src/process.h b/src/process.h
index 9606f5da9d6..73674b7358e 100644
--- a/src/process.h
+++ b/src/process.h
@@ -161,13 +161,13 @@ extern int synch_process_retcode;
161 when exiting. */ 161 when exiting. */
162extern int inhibit_sentinels; 162extern int inhibit_sentinels;
163 163
164extern Lisp_Object w32_list_system_processes P_ ((void));
165extern Lisp_Object w32_system_process_attributes P_ ((Lisp_Object));
166
167extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname; 164extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname;
168extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime; 165extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime;
169extern Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs; 166extern Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs;
170extern Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtpgid, Qcstime; 167extern Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtpgid, Qcstime;
171 168
169extern Lisp_Object list_system_processes (void);
170extern Lisp_Object system_process_attributes (Lisp_Object);
171
172/* arch-tag: dffedfc4-d7bc-4b58-a26f-c16155449c72 172/* arch-tag: dffedfc4-d7bc-4b58-a26f-c16155449c72
173 (do not change this comment) */ 173 (do not change this comment) */
diff --git a/src/s/gnu-linux.h b/src/s/gnu-linux.h
index 2e28b81f7d0..7437db5d8eb 100644
--- a/src/s/gnu-linux.h
+++ b/src/s/gnu-linux.h
@@ -105,10 +105,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
105 105
106#define BSTRING 106#define BSTRING
107 107
108/* These are used in Flist_system_processes and Fsystem_process_attributes. */ 108/* This is used in list_system_processes. */
109#define HAVE_PROCFS 1 109#define HAVE_PROCFS 1
110#define LISTPROC procfs_list_system_processes
111#define PROCATTR procfs_system_process_attributes
112 110
113/* define MAIL_USE_FLOCK if the mailer uses flock 111/* define MAIL_USE_FLOCK if the mailer uses flock
114 to interlock access to /usr/spool/mail/$USER. 112 to interlock access to /usr/spool/mail/$USER.
diff --git a/src/sysdep.c b/src/sysdep.c
index 0a2e2ed1614..7f53ea2f788 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -25,6 +25,13 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
25#include <signal.h> 25#include <signal.h>
26#include <stdio.h> 26#include <stdio.h>
27#include <setjmp.h> 27#include <setjmp.h>
28#ifdef HAVE_PWD_H
29#include <pwd.h>
30#include <grp.h>
31#endif /* HAVE_PWD_H */
32#ifdef HAVE_LIMITS_H
33#include <limits.h>
34#endif /* HAVE_LIMITS_H */
28#ifdef HAVE_UNISTD_H 35#ifdef HAVE_UNISTD_H
29#include <unistd.h> 36#include <unistd.h>
30#endif 37#endif
@@ -3171,6 +3178,443 @@ serial_configure (struct Lisp_Process *p,
3171 3178
3172} 3179}
3173#endif /* TERMIOS */ 3180#endif /* TERMIOS */
3181
3182/* System depended enumeration of and access to system processes a-la ps(1). */
3183
3184#ifdef HAVE_PROCFS
3185
3186/* Process enumeration and access via /proc. */
3187
3188Lisp_Object
3189list_system_processes ()
3190{
3191 Lisp_Object procdir, match, proclist, next;
3192 struct gcpro gcpro1, gcpro2;
3193 register Lisp_Object tail;
3194
3195 GCPRO2 (procdir, match);
3196 /* For every process on the system, there's a directory in the
3197 "/proc" pseudo-directory whose name is the numeric ID of that
3198 process. */
3199 procdir = build_string ("/proc");
3200 match = build_string ("[0-9]+");
3201 proclist = directory_files_internal (procdir, Qnil, match, Qt, 0, Qnil);
3202
3203 /* `proclist' gives process IDs as strings. Destructively convert
3204 each string into a number. */
3205 for (tail = proclist; CONSP (tail); tail = next)
3206 {
3207 next = XCDR (tail);
3208 XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
3209 }
3210 UNGCPRO;
3211
3212 /* directory_files_internal returns the files in reverse order; undo
3213 that. */
3214 proclist = Fnreverse (proclist);
3215 return proclist;
3216}
3217
3218#elif !defined (WINDOWSNT)
3219
3220Lisp_Object
3221list_system_processes ()
3222{
3223 return Qnil;
3224}
3225#endif /* !defined (WINDOWSNT)*/
3226
3227#ifdef GNU_LINUX
3228static void
3229time_from_jiffies (unsigned long long tval, long hz,
3230 time_t *sec, unsigned *usec)
3231{
3232 unsigned long long ullsec;
3233
3234 *sec = tval / hz;
3235 ullsec = *sec;
3236 tval -= ullsec * hz;
3237 /* Careful: if HZ > 1 million, then integer division by it yields zero. */
3238 if (hz <= 1000000)
3239 *usec = tval * 1000000 / hz;
3240 else
3241 *usec = tval / (hz / 1000000);
3242}
3243
3244static Lisp_Object
3245ltime_from_jiffies (unsigned long long tval, long hz)
3246{
3247 time_t sec;
3248 unsigned usec;
3249
3250 time_from_jiffies (tval, hz, &sec, &usec);
3251
3252 return list3 (make_number ((sec >> 16) & 0xffff),
3253 make_number (sec & 0xffff),
3254 make_number (usec));
3255}
3256
3257static void
3258get_up_time (time_t *sec, unsigned *usec)
3259{
3260 FILE *fup;
3261
3262 *sec = *usec = 0;
3263
3264 BLOCK_INPUT;
3265 fup = fopen ("/proc/uptime", "r");
3266
3267 if (fup)
3268 {
3269 double uptime, idletime;
3270
3271 /* The numbers in /proc/uptime use C-locale decimal point, but
3272 we already set ourselves to the C locale (see `fixup_locale'
3273 in emacs.c). */
3274 if (2 <= fscanf (fup, "%lf %lf", &uptime, &idletime))
3275 {
3276 *sec = uptime;
3277 *usec = (uptime - *sec) * 1000000;
3278 }
3279 fclose (fup);
3280 }
3281 UNBLOCK_INPUT;
3282}
3283
3284#define MAJOR(d) (((unsigned)(d) >> 8) & 0xfff)
3285#define MINOR(d) (((unsigned)(d) & 0xff) | (((unsigned)(d) & 0xfff00000) >> 12))
3286
3287static Lisp_Object
3288procfs_ttyname (rdev)
3289{
3290 FILE *fdev = NULL;
3291 char name[PATH_MAX];
3292
3293 BLOCK_INPUT;
3294 fdev = fopen ("/proc/tty/drivers", "r");
3295
3296 if (fdev)
3297 {
3298 unsigned major;
3299 unsigned long minor_beg, minor_end;
3300 char minor[25]; /* 2 32-bit numbers + dash */
3301 char *endp;
3302
3303 while (!feof (fdev) && !ferror (fdev))
3304 {
3305 if (3 <= fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor)
3306 && major == MAJOR (rdev))
3307 {
3308 minor_beg = strtoul (minor, &endp, 0);
3309 if (*endp == '\0')
3310 minor_end = minor_beg;
3311 else if (*endp == '-')
3312 minor_end = strtoul (endp + 1, &endp, 0);
3313 else
3314 continue;
3315
3316 if (MINOR (rdev) >= minor_beg && MINOR (rdev) <= minor_end)
3317 {
3318 sprintf (name + strlen (name), "%lu", MINOR (rdev));
3319 break;
3320 }
3321 }
3322 }
3323 fclose (fdev);
3324 }
3325 UNBLOCK_INPUT;
3326 return build_string (name);
3327}
3328
3329static unsigned long
3330procfs_get_total_memory (void)
3331{
3332 FILE *fmem = NULL;
3333 unsigned long retval = 2 * 1024 * 1024; /* default: 2GB */
3334
3335 BLOCK_INPUT;
3336 fmem = fopen ("/proc/meminfo", "r");
3337
3338 if (fmem)
3339 {
3340 unsigned long entry_value;
3341 char entry_name[20]; /* the longest I saw is 13+1 */
3342
3343 while (!feof (fmem) && !ferror (fmem))
3344 {
3345 if (2 <= fscanf (fmem, "%s %lu kB\n", entry_name, &entry_value)
3346 && strcmp (entry_name, "MemTotal:") == 0)
3347 {
3348 retval = entry_value;
3349 break;
3350 }
3351 }
3352 fclose (fmem);
3353 }
3354 UNBLOCK_INPUT;
3355 return retval;
3356}
3357
3358Lisp_Object
3359system_process_attributes (pid)
3360 Lisp_Object pid;
3361{
3362 char procfn[PATH_MAX], fn[PATH_MAX];
3363 struct stat st;
3364 struct passwd *pw;
3365 struct group *gr;
3366 long clocks_per_sec;
3367 char *procfn_end;
3368 char procbuf[1025], *p, *q;
3369 int fd;
3370 ssize_t nread;
3371 const char *cmd = NULL;
3372 char *cmdline = NULL;
3373 size_t cmdsize = 0, cmdline_size;
3374 unsigned char c;
3375 int proc_id, ppid, uid, gid, pgrp, sess, tty, tpgid, thcount;
3376 unsigned long long utime, stime, cutime, cstime, start;
3377 long priority, nice, rss;
3378 unsigned long minflt, majflt, cminflt, cmajflt, vsize;
3379 time_t sec;
3380 unsigned usec;
3381 EMACS_TIME tnow, tstart, tboot, telapsed,ttotal;
3382 double pcpu, pmem;
3383 Lisp_Object attrs = Qnil;
3384 Lisp_Object cmd_str, decoded_cmd, tem;
3385 struct gcpro gcpro1, gcpro2;
3386 EMACS_INT uid_eint, gid_eint;
3387
3388 CHECK_NUMBER_OR_FLOAT (pid);
3389 proc_id = FLOATP (pid) ? XFLOAT_DATA (pid) : XINT (pid);
3390 sprintf (procfn, "/proc/%lu", proc_id);
3391 if (stat (procfn, &st) < 0)
3392 return attrs;
3393
3394 GCPRO2 (attrs, decoded_cmd);
3395
3396 /* euid egid */
3397 uid = st.st_uid;
3398 /* Use of EMACS_INT stops GCC whining about limited range of data type. */
3399 uid_eint = uid;
3400 attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid_eint)), attrs);
3401 BLOCK_INPUT;
3402 pw = getpwuid (uid);
3403 UNBLOCK_INPUT;
3404 if (pw)
3405 attrs = Fcons (Fcons (Quser, build_string (pw->pw_name)), attrs);
3406
3407 gid = st.st_gid;
3408 gid_eint = gid;
3409 attrs = Fcons (Fcons (Qegid, make_fixnum_or_float (gid_eint)), attrs);
3410 BLOCK_INPUT;
3411 gr = getgrgid (gid);
3412 UNBLOCK_INPUT;
3413 if (gr)
3414 attrs = Fcons (Fcons (Qgroup, build_string (gr->gr_name)), attrs);
3415
3416 strcpy (fn, procfn);
3417 procfn_end = fn + strlen (fn);
3418 strcpy (procfn_end, "/stat");
3419 fd = emacs_open (fn, O_RDONLY, 0);
3420 if (fd >= 0 && (nread = emacs_read (fd, procbuf, sizeof(procbuf) - 1)) > 0)
3421 {
3422 procbuf[nread] = '\0';
3423 p = procbuf;
3424
3425 p = strchr (p, '(');
3426 if (p != NULL)
3427 {
3428 q = strrchr (p + 1, ')');
3429 /* comm */
3430 if (q != NULL)
3431 {
3432 cmd = p + 1;
3433 cmdsize = q - cmd;
3434 }
3435 }
3436 else
3437 q = NULL;
3438 if (cmd == NULL)
3439 {
3440 cmd = "???";
3441 cmdsize = 3;
3442 }
3443 /* Command name is encoded in locale-coding-system; decode it. */
3444 cmd_str = make_unibyte_string (cmd, cmdsize);
3445 decoded_cmd = code_convert_string_norecord (cmd_str,
3446 Vlocale_coding_system, 0);
3447 attrs = Fcons (Fcons (Qcomm, decoded_cmd), attrs);
3448
3449 if (q)
3450 {
3451 EMACS_INT ppid_eint, pgrp_eint, sess_eint, tpgid_eint, thcount_eint;
3452 p = q + 2;
3453 /* state ppid pgrp sess tty tpgid . minflt cminflt majflt cmajflt utime stime cutime cstime priority nice thcount . start vsize rss */
3454 sscanf (p, "%c %d %d %d %d %d %*u %lu %lu %lu %lu %Lu %Lu %Lu %Lu %ld %ld %d %*d %Lu %lu %ld",
3455 &c, &ppid, &pgrp, &sess, &tty, &tpgid,
3456 &minflt, &cminflt, &majflt, &cmajflt,
3457 &utime, &stime, &cutime, &cstime,
3458 &priority, &nice, &thcount, &start, &vsize, &rss);
3459 {
3460 char state_str[2];
3461
3462 state_str[0] = c;
3463 state_str[1] = '\0';
3464 tem = build_string (state_str);
3465 attrs = Fcons (Fcons (Qstate, tem), attrs);
3466 }
3467 /* Stops GCC whining about limited range of data type. */
3468 ppid_eint = ppid;
3469 pgrp_eint = pgrp;
3470 sess_eint = sess;
3471 tpgid_eint = tpgid;
3472 thcount_eint = thcount;
3473 attrs = Fcons (Fcons (Qppid, make_fixnum_or_float (ppid_eint)), attrs);
3474 attrs = Fcons (Fcons (Qpgrp, make_fixnum_or_float (pgrp_eint)), attrs);
3475 attrs = Fcons (Fcons (Qsess, make_fixnum_or_float (sess_eint)), attrs);
3476 attrs = Fcons (Fcons (Qttname, procfs_ttyname (tty)), attrs);
3477 attrs = Fcons (Fcons (Qtpgid, make_fixnum_or_float (tpgid_eint)), attrs);
3478 attrs = Fcons (Fcons (Qminflt, make_fixnum_or_float (minflt)), attrs);
3479 attrs = Fcons (Fcons (Qmajflt, make_fixnum_or_float (majflt)), attrs);
3480 attrs = Fcons (Fcons (Qcminflt, make_fixnum_or_float (cminflt)), attrs);
3481 attrs = Fcons (Fcons (Qcmajflt, make_fixnum_or_float (cmajflt)), attrs);
3482 clocks_per_sec = sysconf (_SC_CLK_TCK);
3483 if (clocks_per_sec < 0)
3484 clocks_per_sec = 100;
3485 attrs = Fcons (Fcons (Qutime,
3486 ltime_from_jiffies (utime, clocks_per_sec)),
3487 attrs);
3488 attrs = Fcons (Fcons (Qstime,
3489 ltime_from_jiffies (stime, clocks_per_sec)),
3490 attrs);
3491 attrs = Fcons (Fcons (Qcutime,
3492 ltime_from_jiffies (cutime, clocks_per_sec)),
3493 attrs);
3494 attrs = Fcons (Fcons (Qcstime,
3495 ltime_from_jiffies (cstime, clocks_per_sec)),
3496 attrs);
3497 attrs = Fcons (Fcons (Qpri, make_number (priority)), attrs);
3498 attrs = Fcons (Fcons (Qnice, make_number (nice)), attrs);
3499 attrs = Fcons (Fcons (Qthcount, make_fixnum_or_float (thcount_eint)), attrs);
3500 EMACS_GET_TIME (tnow);
3501 get_up_time (&sec, &usec);
3502 EMACS_SET_SECS (telapsed, sec);
3503 EMACS_SET_USECS (telapsed, usec);
3504 EMACS_SUB_TIME (tboot, tnow, telapsed);
3505 time_from_jiffies (start, clocks_per_sec, &sec, &usec);
3506 EMACS_SET_SECS (tstart, sec);
3507 EMACS_SET_USECS (tstart, usec);
3508 EMACS_ADD_TIME (tstart, tboot, tstart);
3509 attrs = Fcons (Fcons (Qstart,
3510 list3 (make_number
3511 ((EMACS_SECS (tstart) >> 16) & 0xffff),
3512 make_number
3513 (EMACS_SECS (tstart) & 0xffff),
3514 make_number
3515 (EMACS_USECS (tstart)))),
3516 attrs);
3517 attrs = Fcons (Fcons (Qvsize, make_fixnum_or_float (vsize/1024)), attrs);
3518 attrs = Fcons (Fcons (Qrss, make_fixnum_or_float (4*rss)), attrs);
3519 EMACS_SUB_TIME (telapsed, tnow, tstart);
3520 attrs = Fcons (Fcons (Qetime,
3521 list3 (make_number
3522 ((EMACS_SECS (telapsed) >> 16) & 0xffff),
3523 make_number
3524 (EMACS_SECS (telapsed) & 0xffff),
3525 make_number
3526 (EMACS_USECS (telapsed)))),
3527 attrs);
3528 time_from_jiffies (utime + stime, clocks_per_sec, &sec, &usec);
3529 pcpu = (sec + usec / 1000000.0) / (EMACS_SECS (telapsed) + EMACS_USECS (telapsed) / 1000000.0);
3530 if (pcpu > 1.0)
3531 pcpu = 1.0;
3532 attrs = Fcons (Fcons (Qpcpu, make_float (100 * pcpu)), attrs);
3533 pmem = 4.0 * 100 * rss / procfs_get_total_memory ();
3534 if (pmem > 100)
3535 pmem = 100;
3536 attrs = Fcons (Fcons (Qpmem, make_float (pmem)), attrs);
3537 }
3538 }
3539 if (fd >= 0)
3540 emacs_close (fd);
3541
3542 /* args */
3543 strcpy (procfn_end, "/cmdline");
3544 fd = emacs_open (fn, O_RDONLY, 0);
3545 if (fd >= 0)
3546 {
3547 for (cmdline_size = 0; emacs_read (fd, &c, 1) == 1; cmdline_size++)
3548 {
3549 if (isspace (c) || c == '\\')
3550 cmdline_size++; /* for later quoting, see below */
3551 }
3552 if (cmdline_size)
3553 {
3554 cmdline = xmalloc (cmdline_size + 1);
3555 lseek (fd, 0L, SEEK_SET);
3556 cmdline[0] = '\0';
3557 if ((nread = read (fd, cmdline, cmdline_size)) >= 0)
3558 cmdline[nread++] = '\0';
3559 else
3560 {
3561 /* Assigning zero to `nread' makes us skip the following
3562 two loops, assign zero to cmdline_size, and enter the
3563 following `if' clause that handles unknown command
3564 lines. */
3565 nread = 0;
3566 }
3567 /* We don't want trailing null characters. */
3568 for (p = cmdline + nread - 1; p > cmdline && !*p; p--)
3569 nread--;
3570 for (p = cmdline; p < cmdline + nread; p++)
3571 {
3572 /* Escape-quote whitespace and backslashes. */
3573 if (isspace (*p) || *p == '\\')
3574 {
3575 memmove (p + 1, p, nread - (p - cmdline));
3576 nread++;
3577 *p++ = '\\';
3578 }
3579 else if (*p == '\0')
3580 *p = ' ';
3581 }
3582 cmdline_size = nread;
3583 }
3584 if (!cmdline_size)
3585 {
3586 if (!cmd)
3587 cmd = "???";
3588 if (!cmdsize)
3589 cmdsize = strlen (cmd);
3590 cmdline_size = cmdsize + 2;
3591 cmdline = xmalloc (cmdline_size + 1);
3592 strcpy (cmdline, "[");
3593 strcat (strncat (cmdline, cmd, cmdsize), "]");
3594 }
3595 emacs_close (fd);
3596 /* Command line is encoded in locale-coding-system; decode it. */
3597 cmd_str = make_unibyte_string (cmdline, cmdline_size);
3598 decoded_cmd = code_convert_string_norecord (cmd_str,
3599 Vlocale_coding_system, 0);
3600 xfree (cmdline);
3601 attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
3602 }
3603
3604 UNGCPRO;
3605 return attrs;
3606}
3607
3608#elif !defined (WINDOWSNT)
3609
3610Lisp_Object
3611system_process_attributes (Lisp_Object pid)
3612{
3613 return Qnil
3614}
3615
3616#endif /* !defined (WINDOWSNT) */
3617
3174 3618
3175/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf 3619/* arch-tag: edb43589-4e09-4544-b325-978b5b121dcf
3176 (do not change this comment) */ 3620 (do not change this comment) */
diff --git a/src/w32.c b/src/w32.c
index c6660c0d3d6..5d70cbc48c3 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -3671,7 +3671,7 @@ BOOL WINAPI global_memory_status_ex (
3671} 3671}
3672 3672
3673Lisp_Object 3673Lisp_Object
3674w32_list_system_processes () 3674list_system_processes ()
3675{ 3675{
3676 struct gcpro gcpro1; 3676 struct gcpro gcpro1;
3677 Lisp_Object proclist = Qnil; 3677 Lisp_Object proclist = Qnil;
@@ -3823,7 +3823,7 @@ process_times (h_proc, ctime, etime, stime, utime, pcpu)
3823} 3823}
3824 3824
3825Lisp_Object 3825Lisp_Object
3826w32_system_process_attributes (pid) 3826system_process_attributes (pid)
3827 Lisp_Object pid; 3827 Lisp_Object pid;
3828{ 3828{
3829 struct gcpro gcpro1, gcpro2, gcpro3; 3829 struct gcpro gcpro1, gcpro2, gcpro3;