diff options
| author | Dan Nicolaescu | 2008-12-19 19:50:35 +0000 |
|---|---|---|
| committer | Dan Nicolaescu | 2008-12-19 19:50:35 +0000 |
| commit | 06e111a6efbbe275e8f7c364ff8e5955d1ab75f0 (patch) | |
| tree | 3ed4dc7cbf6c74663a3c4bd4c35b71e40ab2e3e9 /src | |
| parent | 349b3256608412d33ddabc7c3f9b429123e7c353 (diff) | |
| download | emacs-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/ChangeLog | 32 | ||||
| -rw-r--r-- | src/process.c | 439 | ||||
| -rw-r--r-- | src/process.h | 6 | ||||
| -rw-r--r-- | src/s/gnu-linux.h | 4 | ||||
| -rw-r--r-- | src/sysdep.c | 444 | ||||
| -rw-r--r-- | src/w32.c | 4 |
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 @@ | |||
| 1 | 2008-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 | |||
| 1 | 2008-12-19 Kenichi Handa <handa@m17n.org> | 33 | 2008-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 | |||
| 7080 | static Lisp_Object | ||
| 7081 | procfs_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 | |||
| 7110 | static void | ||
| 7111 | time_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 | |||
| 7126 | static Lisp_Object | ||
| 7127 | ltime_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 | |||
| 7139 | static void | ||
| 7140 | get_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 | |||
| 7169 | static Lisp_Object | ||
| 7170 | procfs_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 | |||
| 7211 | static unsigned long | ||
| 7212 | procfs_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 | |||
| 7240 | static Lisp_Object | ||
| 7241 | procfs_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 | |||
| 7492 | DEFUN ("list-system-processes", Flist_system_processes, Slist_system_processes, | 7065 | DEFUN ("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 | |||
| 7498 | given its ID. */) | 7071 | given 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 | ||
| 7508 | DEFUN ("system-process-attributes", Fsystem_process_attributes, | 7077 | DEFUN ("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 | ||
| 7568 | void | 7133 | void |
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. */ |
| 162 | extern int inhibit_sentinels; | 162 | extern int inhibit_sentinels; |
| 163 | 163 | ||
| 164 | extern Lisp_Object w32_list_system_processes P_ ((void)); | ||
| 165 | extern Lisp_Object w32_system_process_attributes P_ ((Lisp_Object)); | ||
| 166 | |||
| 167 | extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname; | 164 | extern Lisp_Object Qeuid, Qegid, Qcomm, Qstate, Qppid, Qpgrp, Qsess, Qttname; |
| 168 | extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime; | 165 | extern Lisp_Object Qminflt, Qmajflt, Qcminflt, Qcmajflt, Qutime, Qstime; |
| 169 | extern Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs; | 166 | extern Lisp_Object Qcutime, Qpri, Qnice, Qthcount, Qstart, Qvsize, Qrss, Qargs; |
| 170 | extern Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtpgid, Qcstime; | 167 | extern Lisp_Object Quser, Qgroup, Qetime, Qpcpu, Qpmem, Qtpgid, Qcstime; |
| 171 | 168 | ||
| 169 | extern Lisp_Object list_system_processes (void); | ||
| 170 | extern 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 | |||
| 3188 | Lisp_Object | ||
| 3189 | list_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 | |||
| 3220 | Lisp_Object | ||
| 3221 | list_system_processes () | ||
| 3222 | { | ||
| 3223 | return Qnil; | ||
| 3224 | } | ||
| 3225 | #endif /* !defined (WINDOWSNT)*/ | ||
| 3226 | |||
| 3227 | #ifdef GNU_LINUX | ||
| 3228 | static void | ||
| 3229 | time_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 | |||
| 3244 | static Lisp_Object | ||
| 3245 | ltime_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 | |||
| 3257 | static void | ||
| 3258 | get_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 | |||
| 3287 | static Lisp_Object | ||
| 3288 | procfs_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 | |||
| 3329 | static unsigned long | ||
| 3330 | procfs_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 | |||
| 3358 | Lisp_Object | ||
| 3359 | system_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 | |||
| 3610 | Lisp_Object | ||
| 3611 | system_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) */ |
| @@ -3671,7 +3671,7 @@ BOOL WINAPI global_memory_status_ex ( | |||
| 3671 | } | 3671 | } |
| 3672 | 3672 | ||
| 3673 | Lisp_Object | 3673 | Lisp_Object |
| 3674 | w32_list_system_processes () | 3674 | list_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 | ||
| 3825 | Lisp_Object | 3825 | Lisp_Object |
| 3826 | w32_system_process_attributes (pid) | 3826 | system_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; |