ubase

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

pidof.c (2017B)


      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 	for (p = strtok(arg, ","); p; p = strtok(NULL, ",")) {
     59 		pe = emalloc(sizeof(*pe));
     60 		if (strcmp(p, "%PPID") == 0)
     61 			pe->pid = getppid();
     62 		else
     63 			pe->pid = estrtol(p, 10);
     64 		SLIST_INSERT_HEAD(&omitpid_head, pe, entry);
     65 	}
     66 
     67 	if (!(dp = opendir("/proc")))
     68 		eprintf("opendir /proc:");
     69 
     70 	while ((entry = readdir(dp))) {
     71 		if (!pidfile(entry->d_name))
     72 			continue;
     73 		pid = estrtol(entry->d_name, 10);
     74 		if (oflag) {
     75 			SLIST_FOREACH(pe, &omitpid_head, entry)
     76 				if (pe->pid == pid)
     77 					break;
     78 			if (pe)
     79 				continue;
     80 		}
     81 		if (parsestat(pid, &ps) < 0)
     82 			continue;
     83 		if (parsecmdline(ps.pid, cmdline,
     84 				 sizeof(cmdline)) < 0) {
     85 			cmd = ps.comm;
     86 			cmdbase = cmd;
     87 		} else {
     88 			if ((p = strchr(cmdline, ' ')))
     89 				*p = '\0';
     90 			cmd = cmdline;
     91 			cmdbase = basename(cmdline);
     92 		}
     93 		/* Workaround for login shells */
     94 		if (cmd[0] == '-')
     95 			cmd++;
     96 		for (i = 0; i < argc; i++) {
     97 			if (strcmp(cmd, argv[i]) == 0 ||
     98 			    strcmp(cmdbase, argv[i]) == 0) {
     99 				putword(entry->d_name);
    100 				found++;
    101 				if (sflag)
    102 					goto out;
    103 			}
    104 		}
    105 	}
    106 
    107 out:
    108 	if (found)
    109 		putchar('\n');
    110 
    111 	closedir(dp);
    112 
    113 	return 0;
    114 }