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