busybox/procps/pidof.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * pidof implementation for busybox
   4 *
   5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
   6 *
   7 * Licensed under GPLv2, see file LICENSE in this source tree.
   8 */
   9//config:config PIDOF
  10//config:       bool "pidof (6.3 kb)"
  11//config:       default y
  12//config:       help
  13//config:       Pidof finds the process id's (pids) of the named programs. It prints
  14//config:       those id's on the standard output.
  15//config:
  16//config:config FEATURE_PIDOF_SINGLE
  17//config:       bool "Enable single shot (-s)"
  18//config:       default y
  19//config:       depends on PIDOF
  20//config:       help
  21//config:       Support '-s' for returning only the first pid found.
  22//config:
  23//config:config FEATURE_PIDOF_OMIT
  24//config:       bool "Enable omitting pids (-o PID)"
  25//config:       default y
  26//config:       depends on PIDOF
  27//config:       help
  28//config:       Support '-o PID' for omitting the given pid(s) in output.
  29//config:       The special pid %PPID can be used to name the parent process
  30//config:       of the pidof, in other words the calling shell or shell script.
  31
  32//applet:IF_PIDOF(APPLET(pidof, BB_DIR_BIN, BB_SUID_DROP))
  33/* can't be noexec: can find _itself_ under wrong name, since after fork only,
  34 * /proc/PID/cmdline and comm are wrong! Can fix comm (prctl(PR_SET_NAME)),
  35 * but cmdline?
  36 */
  37
  38//kbuild:lib-$(CONFIG_PIDOF) += pidof.o
  39
  40//usage:#if (ENABLE_FEATURE_PIDOF_SINGLE || ENABLE_FEATURE_PIDOF_OMIT)
  41//usage:#define pidof_trivial_usage
  42//usage:       "[OPTIONS] [NAME]..."
  43//usage:#define USAGE_PIDOF "\n"
  44//usage:#else
  45//usage:#define pidof_trivial_usage
  46//usage:       "[NAME]..."
  47//usage:#define USAGE_PIDOF /* none */
  48//usage:#endif
  49//usage:#define pidof_full_usage "\n\n"
  50//usage:       "List PIDs of all processes with names that match NAMEs"
  51//usage:        USAGE_PIDOF
  52//usage:        IF_FEATURE_PIDOF_SINGLE(
  53//usage:     "\n        -s      Show only one PID"
  54//usage:        )
  55//usage:        IF_FEATURE_PIDOF_OMIT(
  56//usage:     "\n        -o PID  Omit given pid"
  57//usage:     "\n                Use %PPID to omit pid of pidof's parent"
  58//usage:        )
  59//usage:
  60//usage:#define pidof_example_usage
  61//usage:       "$ pidof init\n"
  62//usage:       "1\n"
  63//usage:        IF_FEATURE_PIDOF_OMIT(
  64//usage:       "$ pidof /bin/sh\n20351 5973 5950\n")
  65//usage:        IF_FEATURE_PIDOF_OMIT(
  66//usage:       "$ pidof /bin/sh -o %PPID\n20351 5950")
  67
  68#include "libbb.h"
  69
  70enum {
  71        IF_FEATURE_PIDOF_SINGLE(OPTBIT_SINGLE,)
  72        IF_FEATURE_PIDOF_OMIT(  OPTBIT_OMIT  ,)
  73        OPT_SINGLE = IF_FEATURE_PIDOF_SINGLE((1<<OPTBIT_SINGLE)) + 0,
  74        OPT_OMIT   = IF_FEATURE_PIDOF_OMIT(  (1<<OPTBIT_OMIT  )) + 0,
  75};
  76
  77int pidof_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  78int pidof_main(int argc UNUSED_PARAM, char **argv)
  79{
  80        unsigned first = 1;
  81        unsigned opt;
  82#if ENABLE_FEATURE_PIDOF_OMIT
  83        llist_t *omits = NULL; /* list of pids to omit */
  84#endif
  85
  86        /* do unconditional option parsing */
  87        opt = getopt32(argv, ""
  88                        IF_FEATURE_PIDOF_SINGLE ("s")
  89                        IF_FEATURE_PIDOF_OMIT("o:*", &omits));
  90
  91#if ENABLE_FEATURE_PIDOF_OMIT
  92        /* fill omit list.  */
  93        {
  94                llist_t *omits_p = omits;
  95                while (1) {
  96                        omits_p = llist_find_str(omits_p, "%PPID");
  97                        if (!omits_p)
  98                                break;
  99                        /* are we asked to exclude the parent's process ID?  */
 100                        omits_p->data = utoa((unsigned)getppid());
 101                }
 102        }
 103#endif
 104        /* Looks like everything is set to go.  */
 105        argv += optind;
 106        while (*argv) {
 107                pid_t *pidList;
 108                pid_t *pl;
 109
 110                /* reverse the pidlist like GNU pidof does.  */
 111                pidList = pidlist_reverse(find_pid_by_name(*argv));
 112                for (pl = pidList; *pl; pl++) {
 113#if ENABLE_FEATURE_PIDOF_OMIT
 114                        if (opt & OPT_OMIT) {
 115                                llist_t *omits_p = omits;
 116                                while (omits_p) {
 117                                        if (xatoul(omits_p->data) == (unsigned long)(*pl)) {
 118                                                goto omitting;
 119                                        }
 120                                        omits_p = omits_p->link;
 121                                }
 122                        }
 123#endif
 124                        printf(" %u" + first, (unsigned)*pl);
 125                        first = 0;
 126                        if (ENABLE_FEATURE_PIDOF_SINGLE && (opt & OPT_SINGLE))
 127                                break;
 128#if ENABLE_FEATURE_PIDOF_OMIT
 129 omitting: ;
 130#endif
 131                }
 132                free(pidList);
 133                argv++;
 134        }
 135        if (!first)
 136                bb_putchar('\n');
 137
 138#if ENABLE_FEATURE_PIDOF_OMIT
 139        if (ENABLE_FEATURE_CLEAN_UP)
 140                llist_free(omits, NULL);
 141#endif
 142        return first; /* 1 (failure) - no processes found */
 143}
 144