PageRenderTime 27ms CodeModel.GetById 41ms RepoModel.GetById 0ms app.codeStats 0ms

/user/procps/procps-2.0.7/pgrep.c

https://bitbucket.org/thelearninglabs/uclinux-distro-tll-public
C | 605 lines | 518 code | 70 blank | 17 comment | 164 complexity | af75b2d32c800c819c79b90cd24f87e3 MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-3.0, Unlicense, GPL-2.0, GPL-3.0, CC-BY-SA-3.0, AGPL-1.0, ISC, MIT, 0BSD, LGPL-2.0
  1. /* emacs settings: -*- c-basic-offset: 8 tab-width: 8 -*-
  2. *
  3. * pgrep/pkill -- utilities to filter the process table
  4. *
  5. * Copyright 2000 Kjetil Torgrim Homme <kjetilho@ifi.uio.no>
  6. *
  7. * May be distributed under the conditions of the
  8. * GNU General Public License; a copy is in COPYING
  9. */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include <ctype.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include <signal.h>
  17. #include <pwd.h>
  18. #include <grp.h>
  19. #include <regex.h>
  20. #include <errno.h>
  21. #include "proc/readproc.h"
  22. #include "proc/signals.h"
  23. #include "proc/devname.h"
  24. #include "proc/sysinfo.h"
  25. static int i_am_pkill = 0;
  26. char *progname = "pgrep";
  27. union el {
  28. long num;
  29. char * str;
  30. };
  31. /* User supplied arguments */
  32. static int opt_full = 0;
  33. static int opt_long = 0;
  34. static int opt_newest = 0;
  35. static int opt_negate = 0;
  36. static int opt_exact = 0;
  37. static int opt_signal = SIGTERM;
  38. static char *opt_delim = "\n";
  39. static union el *opt_pgrp = NULL;
  40. static union el *opt_gid = NULL;
  41. static union el *opt_ppid = NULL;
  42. static union el *opt_sid = NULL;
  43. static union el *opt_term = NULL;
  44. static union el *opt_euid = NULL;
  45. static union el *opt_uid = NULL;
  46. static char *opt_pattern = NULL;
  47. /* Prototypes */
  48. static union el *split_list (const char *, char, int (*)(const char *, union el *));
  49. static int conv_uid (const char *, union el *);
  50. static int conv_gid (const char *, union el *);
  51. static int conv_sid (const char *, union el *);
  52. static int conv_pgrp (const char *, union el *);
  53. static int conv_num (const char *, union el *);
  54. static int conv_str (const char *, union el *);
  55. static int match_numlist (long, const union el *);
  56. static int match_strlist (const char *, const union el *);
  57. static int
  58. usage (int opt)
  59. {
  60. if (i_am_pkill)
  61. fprintf (stderr, "Usage: pkill [-flnvx] [-d DELIM] ");
  62. else
  63. fprintf (stderr, "Usage: pgrep [-SIGNAL] [-fnvx] ");
  64. fprintf (stderr, "[-P PPIDLIST] [-g PGRPLIST] [-s SIDLIST]\n"
  65. "\t[-u EUIDLIST] [-U UIDLIST] [-G GIDLIST] [-t TERMLIST] "
  66. "[PATTERN]\n");
  67. exit (opt == '?' ? 0 : 2);
  68. }
  69. static void
  70. parse_opts (int argc, char **argv)
  71. {
  72. char opts[32] = "";
  73. int opt;
  74. int criteria_count = 0;
  75. if (strstr (argv[0], "pkill")) {
  76. i_am_pkill = 1;
  77. progname = "pkill";
  78. /* Look for a signal name or number as first argument */
  79. if (argc > 1 && argv[1][0] == '-') {
  80. int sig;
  81. sig = get_signal2 (argv[1] + 1);
  82. if (sig == -1 && isdigit (argv[1][1]))
  83. sig = atoi (argv[1] + 1);
  84. if (sig != -1) {
  85. int i;
  86. for (i = 2; i < argc; i++)
  87. argv[i-1] = argv[i];
  88. --argc;
  89. opt_signal = sig;
  90. }
  91. }
  92. } else {
  93. /* These options are for pgrep only */
  94. strcat (opts, "ld:");
  95. }
  96. strcat (opts, "fnvxP:g:s:u:U:G:t:?");
  97. while ((opt = getopt (argc, argv, opts)) != -1) {
  98. switch (opt) {
  99. case 'f':
  100. opt_full = 1;
  101. break;
  102. case 'l':
  103. opt_long = 1;
  104. break;
  105. case 'n':
  106. opt_newest = 1;
  107. ++criteria_count;
  108. break;
  109. case 'v':
  110. opt_negate = 1;
  111. break;
  112. case 'x':
  113. opt_exact = 1;
  114. break;
  115. case 'd':
  116. opt_delim = strdup (optarg);
  117. break;
  118. case 'P':
  119. opt_ppid = split_list (optarg, ',', conv_num);
  120. if (opt_ppid == NULL)
  121. usage (opt);
  122. ++criteria_count;
  123. break;
  124. case 'g':
  125. opt_pgrp = split_list (optarg, ',', conv_pgrp);
  126. if (opt_pgrp == NULL)
  127. usage (opt);
  128. break;
  129. case 's':
  130. opt_sid = split_list (optarg, ',', conv_sid);
  131. if (opt_sid == NULL)
  132. usage (opt);
  133. ++criteria_count;
  134. break;
  135. case 'u':
  136. opt_euid = split_list (optarg, ',', conv_uid);
  137. if (opt_euid == NULL)
  138. usage (opt);
  139. ++criteria_count;
  140. break;
  141. case 'U':
  142. opt_uid = split_list (optarg, ',', conv_uid);
  143. if (opt_uid == NULL)
  144. usage (opt);
  145. ++criteria_count;
  146. break;
  147. case 'G':
  148. opt_gid = split_list (optarg, ',', conv_gid);
  149. if (opt_gid == NULL)
  150. usage (opt);
  151. ++criteria_count;
  152. break;
  153. case 't':
  154. opt_term = split_list (optarg, ',', conv_str);
  155. if (opt_term == NULL)
  156. usage (opt);
  157. ++criteria_count;
  158. break;
  159. case '?':
  160. usage (opt);
  161. break;
  162. }
  163. }
  164. if (argc - optind == 1)
  165. opt_pattern = argv[optind];
  166. else if (argc - optind > 1)
  167. usage (0);
  168. else if (criteria_count == 0) {
  169. fprintf (stderr, "%s: No matching criteria specified\n",
  170. progname);
  171. usage (0);
  172. }
  173. }
  174. static union el *
  175. split_list (const char *str, char sep, int (*convert)(const char *, union el *))
  176. {
  177. char *copy = strdup (str);
  178. char *ptr = copy;
  179. char *sep_pos;
  180. int i = 1, size = 32;
  181. union el *list;
  182. list = malloc (size * sizeof (union el));
  183. if (list == NULL)
  184. exit (3);
  185. do {
  186. sep_pos = strchr (ptr, sep);
  187. if (sep_pos)
  188. *sep_pos = 0;
  189. if (convert (ptr, &list[i]))
  190. ++i;
  191. else
  192. exit (2);
  193. if (i == size) {
  194. size *= 2;
  195. list = realloc (list, size * sizeof (union el));
  196. if (list == NULL)
  197. exit (3);
  198. }
  199. if (sep_pos)
  200. ptr = sep_pos + 1;
  201. } while (sep_pos);
  202. free (copy);
  203. if (i == 1) {
  204. free (list);
  205. list = NULL;
  206. } else {
  207. list[0].num = i - 1;
  208. }
  209. return (list);
  210. }
  211. /* strict_atol returns a Boolean: TRUE if the input string contains a
  212. plain number, FALSE if there are any non-digits. */
  213. static int
  214. strict_atol (const char *str, long *value)
  215. {
  216. int res = 0;
  217. int sign = 1;
  218. if (*str == '+')
  219. ++str;
  220. else if (*str == '-') {
  221. ++str;
  222. sign = -1;
  223. }
  224. for ( ; *str; ++str) {
  225. if (! isdigit (*str))
  226. return (0);
  227. res *= 10;
  228. res += *str - '0';
  229. }
  230. *value = sign * res;
  231. return (1);
  232. }
  233. static int
  234. conv_uid (const char *name, union el *e)
  235. {
  236. struct passwd *pwd;
  237. if (strict_atol (name, &e->num))
  238. return (1);
  239. pwd = getpwnam (name);
  240. if (pwd == NULL) {
  241. fprintf (stderr, "%s: invalid user name: %s\n",
  242. progname, name);
  243. return (0);
  244. }
  245. e->num = pwd->pw_uid;
  246. return (1);
  247. }
  248. static int
  249. conv_gid (const char *name, union el *e)
  250. {
  251. struct group *grp;
  252. if (strict_atol (name, &e->num))
  253. return (1);
  254. grp = getgrnam (name);
  255. if (grp == NULL) {
  256. fprintf (stderr, "%s: invalid group name: %s\n",
  257. progname, name);
  258. return (0);
  259. }
  260. e->num = grp->gr_gid;
  261. return (1);
  262. }
  263. static int
  264. conv_pgrp (const char *name, union el *e)
  265. {
  266. if (! strict_atol (name, &e->num)) {
  267. fprintf (stderr, "%s: invalid process group: %s\n",
  268. progname, name);
  269. return (0);
  270. }
  271. if (e->num == 0)
  272. e->num = getpgrp ();
  273. return (1);
  274. }
  275. static int
  276. conv_sid (const char *name, union el *e)
  277. {
  278. if (! strict_atol (name, &e->num)) {
  279. fprintf (stderr, "%s: invalid session id: %s\n",
  280. progname, name);
  281. return (0);
  282. }
  283. if (e->num == 0)
  284. e->num = getsid (0);
  285. return (1);
  286. }
  287. static int
  288. conv_num (const char *name, union el *e)
  289. {
  290. if (! strict_atol (name, &e->num)) {
  291. fprintf (stderr, "%s: not a number: %s\n",
  292. progname, name);
  293. return (0);
  294. }
  295. return (1);
  296. }
  297. static int
  298. conv_str (const char *name, union el *e)
  299. {
  300. e->str = strdup (name);
  301. return (1);
  302. }
  303. static int
  304. match_numlist (long value, const union el *list)
  305. {
  306. int found = 0;
  307. if (list == NULL)
  308. found = 0;
  309. else {
  310. int i;
  311. for (i = list[0].num; i > 0; i--) {
  312. if (list[i].num == value)
  313. found = 1;
  314. }
  315. }
  316. return (found);
  317. }
  318. static int
  319. match_strlist (const char *value, const union el *list)
  320. {
  321. int found = 0;
  322. if (list == NULL)
  323. found = 0;
  324. else {
  325. int i;
  326. for (i = list[0].num; i > 0; i--) {
  327. if (! strcmp (list[i].str, value))
  328. found = 1;
  329. }
  330. }
  331. return (found);
  332. }
  333. static void
  334. output_numlist (const union el *list)
  335. {
  336. int i;
  337. for (i = 1; i < list[0].num; i++)
  338. printf ("%ld%s", list[i].num, opt_delim);
  339. if (list[0].num)
  340. printf ("%ld\n", list[i].num);
  341. }
  342. static void
  343. output_strlist (const union el *list)
  344. {
  345. int i;
  346. for (i = 1; i < list[0].num; i++)
  347. printf ("%s%s", list[i].str, opt_delim);
  348. if (list[0].num)
  349. printf ("%s\n", list[i].str);
  350. }
  351. static PROCTAB *
  352. do_openproc ()
  353. {
  354. PROCTAB *ptp;
  355. int flags = PROC_FILLANY;
  356. if (opt_pattern || opt_full)
  357. flags |= PROC_FILLCMD;
  358. if (opt_uid)
  359. flags |= PROC_FILLSTATUS;
  360. if (opt_euid && !opt_negate) {
  361. int num = opt_euid[0].num;
  362. int i = num;
  363. uid_t *uids = malloc (num * sizeof (uid_t));
  364. if (uids == NULL)
  365. exit (3);
  366. while (i-- > 0) {
  367. uids[i] = opt_euid[i+1].num;
  368. }
  369. flags |= PROC_UID;
  370. ptp = openproc (flags, uids, num);
  371. } else {
  372. ptp = openproc (flags);
  373. }
  374. return (ptp);
  375. }
  376. static regex_t *
  377. do_regcomp ()
  378. {
  379. regex_t *preg = NULL;
  380. if (opt_pattern) {
  381. char *re;
  382. char errbuf[256];
  383. int re_err;
  384. preg = malloc (sizeof (regex_t));
  385. if (preg == NULL)
  386. exit (3);
  387. if (opt_exact) {
  388. re = malloc (strlen (opt_pattern) + 5);
  389. if (re == NULL)
  390. exit (3);
  391. sprintf (re, "^(%s)$", opt_pattern);
  392. } else {
  393. re = opt_pattern;
  394. }
  395. re_err = regcomp (preg, re, REG_EXTENDED | REG_NOSUB);
  396. if (re_err) {
  397. regerror (re_err, preg, errbuf, sizeof(errbuf));
  398. fprintf (stderr, errbuf);
  399. exit (2);
  400. }
  401. }
  402. return preg;
  403. }
  404. #ifdef NOT_USED
  405. static time_t
  406. jiffies_to_time_t (long jiffies)
  407. {
  408. static time_t time_of_boot = 0;
  409. if (time_of_boot == 0) {
  410. time_of_boot = time (NULL) - uptime (0, 0);
  411. }
  412. return (time_of_boot + jiffies / Hertz);
  413. }
  414. #endif
  415. static union el *
  416. select_procs ()
  417. {
  418. PROCTAB *ptp;
  419. proc_t task;
  420. long newest_start_time = 0;
  421. pid_t newest_pid = 0;
  422. int matches = 0;
  423. int size = 32;
  424. regex_t *preg;
  425. pid_t myself = getpid();
  426. union el *list;
  427. char cmd[4096];
  428. list = malloc (size * sizeof (union el));
  429. if (list == NULL)
  430. exit (3);
  431. ptp = do_openproc ();
  432. preg = do_regcomp ();
  433. memset (&task, 0, sizeof (task));
  434. while (readproc (ptp, &task)) {
  435. int match = 1;
  436. if (task.pid == myself)
  437. continue;
  438. else if (opt_newest && task.start_time < newest_start_time)
  439. match = 0;
  440. else if (opt_ppid && ! match_numlist (task.ppid, opt_ppid))
  441. match = 0;
  442. else if (opt_pgrp && ! match_numlist (task.pgrp, opt_pgrp))
  443. match = 0;
  444. else if (opt_euid && ! match_numlist (task.euid, opt_euid))
  445. match = 0;
  446. else if (opt_uid && ! match_numlist (task.ruid, opt_uid))
  447. match = 0;
  448. else if (opt_gid && ! match_numlist (task.rgid, opt_gid))
  449. match = 0;
  450. else if (opt_sid && ! match_numlist (task.session, opt_sid))
  451. match = 0;
  452. else if (opt_term) {
  453. if (task.tty == -1) {
  454. match = 0;
  455. } else {
  456. char tty[256];
  457. dev_to_tty (tty, sizeof(tty) - 1,
  458. task.tty, task.pid, ABBREV_DEV);
  459. match = match_strlist (tty, opt_term);
  460. }
  461. }
  462. if (opt_long || (match && opt_pattern)) {
  463. if (opt_full && task.cmdline) {
  464. int i = 0;
  465. int bytes = sizeof (cmd) - 1;
  466. /* make sure it is always NUL-terminated */
  467. cmd[bytes] = 0;
  468. /* make room for SPC in loop below */
  469. --bytes;
  470. strncpy (cmd, task.cmdline[i], bytes);
  471. bytes -= strlen (task.cmdline[i++]);
  472. while (task.cmdline[i] && bytes > 0) {
  473. strncat (cmd, " ", bytes);
  474. strncat (cmd, task.cmdline[i], bytes);
  475. bytes -= strlen (task.cmdline[i++]) + 1;
  476. }
  477. } else {
  478. strcpy (cmd, task.cmd);
  479. }
  480. }
  481. if (match && opt_pattern) {
  482. if (regexec (preg, cmd, 0, NULL, 0) != 0)
  483. match = 0;
  484. }
  485. if (match ^ opt_negate) { /* Exclusive OR is neat */
  486. if (opt_newest) {
  487. if (newest_start_time == task.start_time &&
  488. newest_pid > task.pid)
  489. continue;
  490. newest_start_time = task.start_time;
  491. newest_pid = task.pid;
  492. matches = 0;
  493. }
  494. if (opt_long) {
  495. char buff[4096];
  496. sprintf (buff, "%d %s", task.pid, cmd);
  497. list[++matches].str = strdup (buff);
  498. } else {
  499. list[++matches].num = task.pid;
  500. }
  501. if (matches == size) {
  502. size *= 2;
  503. list = realloc (list,
  504. size * sizeof (union el));
  505. if (list == NULL)
  506. exit (3);
  507. }
  508. }
  509. memset (&task, 0, sizeof (task));
  510. }
  511. closeproc (ptp);
  512. list[0].num = matches;
  513. return (list);
  514. }
  515. int
  516. main (int argc, char **argv)
  517. {
  518. union el *procs;
  519. parse_opts (argc, argv);
  520. procs = select_procs ();
  521. if (i_am_pkill) {
  522. int i;
  523. for (i = 1; i <= procs[0].num; i++) {
  524. if (kill (procs[i].num, opt_signal) == -1)
  525. fprintf (stderr, "pkill: %ld - %s\n",
  526. procs[i].num, strerror (errno));
  527. }
  528. } else {
  529. if (opt_long)
  530. output_strlist (procs);
  531. else
  532. output_numlist (procs);
  533. }
  534. return ((procs[0].num) == 0 ? 1 : 0);
  535. }