| /* |
| * procs.c -- functions to parse the linux /proc filesystem. |
| * (c) 1994 salvatore valente <svalente@mit.edu> |
| * |
| * this program is free software. you can redistribute it and |
| * modify it under the terms of the gnu general public license. |
| * there is no warranty. |
| * |
| * faith |
| * 1.2 |
| * 1995/02/23 01:20:40 |
| * |
| */ |
| |
| #define _POSIX_SOURCE 1 |
| |
| #include <sys/types.h> |
| #include <sys/stat.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <dirent.h> |
| #include <ctype.h> |
| #include <unistd.h> |
| #include "kill.h" |
| |
| extern char *mybasename (char *); |
| static char *parse_parens (char *buf); |
| |
| int * |
| get_pids (char *process_name, int get_all) { |
| DIR *dir; |
| struct dirent *ent; |
| int status; |
| char *dname, fname[100], *cp, buf[256]; |
| struct stat st; |
| uid_t uid; |
| FILE *fp; |
| int pid, *pids, num_pids, pids_size; |
| |
| dir = opendir ("/proc"); |
| if (! dir) { |
| perror ("opendir /proc"); |
| return NULL; |
| } |
| uid = getuid (); |
| pids = NULL; |
| num_pids = pids_size = 0; |
| |
| while ((ent = readdir (dir)) != NULL) { |
| dname = ent->d_name; |
| if (! isdigit (*dname)) continue; |
| pid = atoi (dname); |
| sprintf (fname, "/proc/%d/cmdline", pid); |
| /* get the process owner */ |
| status = stat (fname, &st); |
| if (status != 0) continue; |
| if (! get_all && uid != st.st_uid) continue; |
| /* get the command line */ |
| fp = fopen (fname, "r"); |
| if (! fp) continue; |
| cp = fgets (buf, sizeof (buf), fp); |
| fclose (fp); |
| /* an empty command line means the process is swapped out */ |
| if (! cp || ! *cp) { |
| /* get the process name from the statfile */ |
| sprintf (fname, "/proc/%d/stat", pid); |
| fp = fopen (fname, "r"); |
| if (! fp) continue; |
| cp = fgets (buf, sizeof (buf), fp); |
| if (cp == NULL) continue; |
| fclose (fp); |
| cp = parse_parens (buf); |
| if (cp == NULL) continue; |
| } |
| /* ok, we got the process name. */ |
| if (strcmp (process_name, mybasename (cp))) continue; |
| while (pids_size < num_pids + 2) { |
| pids_size += 5; |
| pids = (int *) realloc (pids, sizeof (int) * pids_size); |
| } |
| pids[num_pids++] = pid; |
| pids[num_pids] = -1; |
| } |
| closedir (dir); |
| return (pids); |
| } |
| |
| /* |
| * parse_parens () -- return an index just past the first open paren in |
| * buf, and terminate the string at the matching close paren. |
| */ |
| static char *parse_parens (char *buf) |
| { |
| char *cp, *ip; |
| int depth; |
| |
| cp = strchr (buf, '('); |
| if (cp == NULL) return NULL; |
| cp++; |
| depth = 1; |
| for (ip = cp; *ip; ip++) { |
| if (*ip == '(') |
| depth++; |
| if (*ip == ')') { |
| depth--; |
| if (depth == 0) { |
| *ip = 0; |
| break; |
| } |
| } |
| } |
| return cp; |
| } |
| |
| char *mybasename (char *path) |
| { |
| char *cp; |
| |
| cp = strrchr (path, '/'); |
| return (cp ? cp + 1 : path); |
| } |
| |