source: MondoRescue/branches/3.3/mindi-busybox/procps/pgrep.c@ 3865

Last change on this file since 3865 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 4.6 KB
RevLine 
[2725]1/* vi: set sw=4 ts=4: */
2/*
3 * Mini pgrep/pkill implementation for busybox
4 *
5 * Copyright (C) 2007 Loic Grenie <loic.grenie@gmail.com>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
[3232]9
10//usage:#define pgrep_trivial_usage
11//usage: "[-flnovx] [-s SID|-P PPID|PATTERN]"
12//usage:#define pgrep_full_usage "\n\n"
13//usage: "Display process(es) selected by regex PATTERN\n"
14//usage: "\n -l Show command name too"
15//usage: "\n -f Match against entire command line"
16//usage: "\n -n Show the newest process only"
17//usage: "\n -o Show the oldest process only"
18//usage: "\n -v Negate the match"
19//usage: "\n -x Match whole name (not substring)"
20//usage: "\n -s Match session ID (0 for current)"
21//usage: "\n -P Match parent process ID"
22//usage:
23//usage:#define pkill_trivial_usage
24//usage: "[-l|-SIGNAL] [-fnovx] [-s SID|-P PPID|PATTERN]"
25//usage:#define pkill_full_usage "\n\n"
26//usage: "Send a signal to process(es) selected by regex PATTERN\n"
27//usage: "\n -l List all signals"
28//usage: "\n -f Match against entire command line"
29//usage: "\n -n Signal the newest process only"
30//usage: "\n -o Signal the oldest process only"
31//usage: "\n -v Negate the match"
32//usage: "\n -x Match whole name (not substring)"
33//usage: "\n -s Match session ID (0 for current)"
34//usage: "\n -P Match parent process ID"
35
[2725]36#include "libbb.h"
37#include "xregex.h"
38
39/* Idea taken from kill.c */
40#define pgrep (ENABLE_PGREP && applet_name[1] == 'g')
41#define pkill (ENABLE_PKILL && applet_name[1] == 'k')
42
43enum {
44 /* "vlfxons:P:" */
45 OPTBIT_V = 0, /* must be first, we need OPT_INVERT = 0/1 */
46 OPTBIT_L,
47 OPTBIT_F,
48 OPTBIT_X,
49 OPTBIT_O,
50 OPTBIT_N,
51 OPTBIT_S,
52 OPTBIT_P,
53};
54
55#define OPT_INVERT (opt & (1 << OPTBIT_V))
56#define OPT_LIST (opt & (1 << OPTBIT_L))
57#define OPT_FULL (opt & (1 << OPTBIT_F))
58#define OPT_ANCHOR (opt & (1 << OPTBIT_X))
59#define OPT_FIRST (opt & (1 << OPTBIT_O))
60#define OPT_LAST (opt & (1 << OPTBIT_N))
61#define OPT_SID (opt & (1 << OPTBIT_S))
62#define OPT_PPID (opt & (1 << OPTBIT_P))
63
64static void act(unsigned pid, char *cmd, int signo)
65{
66 if (pgrep) {
67 if (option_mask32 & (1 << OPTBIT_L)) /* OPT_LIST */
[3621]68 printf("%u %s\n", pid, cmd);
[2725]69 else
[3621]70 printf("%u\n", pid);
[2725]71 } else
72 kill(pid, signo);
73}
74
75int pgrep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
76int pgrep_main(int argc UNUSED_PARAM, char **argv)
77{
78 unsigned pid;
79 int signo;
80 unsigned opt;
81 int scan_mask;
82 int matched_pid;
83 int sid2match, ppid2match;
84 char *cmd_last;
85 procps_status_t *proc;
86 /* These are initialized to 0 */
87 struct {
88 regex_t re_buffer;
89 regmatch_t re_match[1];
90 } Z;
91#define re_buffer (Z.re_buffer)
92#define re_match (Z.re_match )
93
94 memset(&Z, 0, sizeof(Z));
95
96 /* Parse -SIGNAL for pkill. Must be first option, if present */
97 signo = SIGTERM;
98 if (pkill && argv[1] && argv[1][0] == '-') {
99 int temp = get_signum(argv[1]+1);
100 if (temp != -1) {
101 signo = temp;
102 argv++;
103 }
104 }
105
106 /* Parse remaining options */
107 ppid2match = -1;
108 sid2match = -1;
109 opt_complementary = "s+:P+"; /* numeric opts */
110 opt = getopt32(argv, "vlfxons:P:", &sid2match, &ppid2match);
111 argv += optind;
112
113 if (pkill && OPT_LIST) { /* -l: print the whole signal list */
114 print_signames();
115 return 0;
116 }
117
118 pid = getpid();
119 if (sid2match == 0)
120 sid2match = getsid(pid);
121
122 scan_mask = PSSCAN_COMM | PSSCAN_ARGV0;
123 if (OPT_FULL)
124 scan_mask |= PSSCAN_ARGVN;
125
126 /* One pattern is required, if no -s and no -P */
127 if ((sid2match & ppid2match) < 0 && (!argv[0] || argv[1]))
128 bb_show_usage();
129
130 if (argv[0])
[3621]131 xregcomp(&re_buffer, argv[0], OPT_ANCHOR ? REG_EXTENDED : (REG_EXTENDED|REG_NOSUB));
[2725]132
133 matched_pid = 0;
134 cmd_last = NULL;
135 proc = NULL;
136 while ((proc = procps_scan(proc, scan_mask)) != NULL) {
137 char *cmd;
138
139 if (proc->pid == pid)
140 continue;
141
142 cmd = proc->argv0;
143 if (!cmd) {
144 cmd = proc->comm;
145 } else {
146 int i = proc->argv_len;
147 while (--i >= 0) {
148 if ((unsigned char)cmd[i] < ' ')
149 cmd[i] = ' ';
150 }
151 }
152
153 if (ppid2match >= 0 && ppid2match != proc->ppid)
154 continue;
155 if (sid2match >= 0 && sid2match != proc->sid)
156 continue;
157
158 /* NB: OPT_INVERT is always 0 or 1 */
159 if (!argv[0]
160 || (regexec(&re_buffer, cmd, 1, re_match, 0) == 0 /* match found */
161 && (!OPT_ANCHOR || (re_match[0].rm_so == 0 && re_match[0].rm_eo == (regoff_t)strlen(cmd)))
162 ) ^ OPT_INVERT
163 ) {
164 matched_pid = proc->pid;
165 if (OPT_LAST) {
166 free(cmd_last);
167 cmd_last = xstrdup(cmd);
168 continue;
169 }
170 act(proc->pid, cmd, signo);
171 if (OPT_FIRST)
172 break;
173 }
174 }
175
176 if (cmd_last) {
177 act(matched_pid, cmd_last, signo);
178 if (ENABLE_FEATURE_CLEAN_UP)
179 free(cmd_last);
180 }
181 return matched_pid == 0; /* return 1 if no processes listed/signaled */
182}
Note: See TracBrowser for help on using the repository browser.