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