124 lines
2.7 KiB
C
124 lines
2.7 KiB
C
/*
|
|
* 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);
|
|
}
|
|
|