ubase

suckless linux base utils
git clone git://git.suckless.org/ubase
Log | Files | Refs | README | LICENSE

pidof.c (2054B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <sys/types.h>
      3 
      4 #include <dirent.h>
      5 #include <libgen.h>
      6 #include <limits.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 #include <unistd.h>
     11 
     12 #include "proc.h"
     13 #include "queue.h"
     14 #include "util.h"
     15 
     16 struct pidentry {
     17 	pid_t pid;
     18 	SLIST_ENTRY(pidentry) entry;
     19 };
     20 
     21 static SLIST_HEAD(, pidentry) omitpid_head;
     22 
     23 static void
     24 usage(void)
     25 {
     26 	eprintf("usage: %s [-o pid1,pid2,...pidN] [-s] [program...]\n", argv0);
     27 }
     28 
     29 int
     30 main(int argc, char *argv[])
     31 {
     32 	DIR *dp;
     33 	struct dirent *entry;
     34 	pid_t pid;
     35 	struct procstat ps;
     36 	char cmdline[BUFSIZ], *cmd, *cmdbase = NULL, *p, *arg = NULL;
     37 	int i, found = 0;
     38 	int sflag = 0, oflag = 0;
     39 	struct pidentry *pe;
     40 
     41 	ARGBEGIN {
     42 	case 's':
     43 		sflag = 1;
     44 		break;
     45 	case 'o':
     46 		oflag = 1;
     47 		arg = EARGF(usage());
     48 		break;
     49 	default:
     50 		usage();
     51 	} ARGEND;
     52 
     53 	if (!argc)
     54 		return 1;
     55 
     56 	SLIST_INIT(&omitpid_head);
     57 
     58 	if (oflag) {
     59 		for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) {
     60 			pe = emalloc(sizeof(*pe));
     61 			if (strcmp(p, "%PPID") == 0)
     62 				pe->pid = getppid();
     63 			else
     64 				pe->pid = estrtol(p, 10);
     65 			SLIST_INSERT_HEAD(&omitpid_head, pe, entry);
     66 		}
     67 	}
     68 
     69 	if (!(dp = opendir("/proc")))
     70 		eprintf("opendir /proc:");
     71 
     72 	while ((entry = readdir(dp))) {
     73 		if (!pidfile(entry->d_name))
     74 			continue;
     75 		pid = estrtol(entry->d_name, 10);
     76 		if (oflag) {
     77 			SLIST_FOREACH(pe, &omitpid_head, entry)
     78 				if (pe->pid == pid)
     79 					break;
     80 			if (pe)
     81 				continue;
     82 		}
     83 		if (parsestat(pid, &ps) < 0)
     84 			continue;
     85 		if (parsecmdline(ps.pid, cmdline,
     86 				 sizeof(cmdline)) < 0) {
     87 			cmd = ps.comm;
     88 			cmdbase = cmd;
     89 		} else {
     90 			if ((p = strchr(cmdline, ' ')))
     91 				*p = '\0';
     92 			cmd = cmdline;
     93 			cmdbase = basename(cmdline);
     94 		}
     95 		/* Workaround for login shells */
     96 		if (cmd[0] == '-')
     97 			cmd++;
     98 		for (i = 0; i < argc; i++) {
     99 			if (strcmp(cmd, argv[i]) == 0 ||
    100 			    strcmp(cmdbase, argv[i]) == 0) {
    101 				putword(entry->d_name);
    102 				found++;
    103 				if (sflag)
    104 					goto out;
    105 			}
    106 		}
    107 	}
    108 
    109 out:
    110 	if (found)
    111 		putchar('\n');
    112 
    113 	closedir(dp);
    114 
    115 	return found ? 0 : 1;
    116 }