/bin/pkill/pkill.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 805 lines · 658 code · 74 blank · 73 comment · 252 complexity · 46c1810f2b21dd8f93201c929c2b2ea6 MD5 · raw file

  1. /* $NetBSD: pkill.c,v 1.16 2005/10/10 22:13:20 kleink Exp $ */
  2. /*-
  3. * Copyright (c) 2002 The NetBSD Foundation, Inc.
  4. * Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
  5. * All rights reserved.
  6. *
  7. * This code is derived from software contributed to The NetBSD Foundation
  8. * by Andrew Doran.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  20. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  21. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  22. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  23. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  24. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  25. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  26. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  27. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  28. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  29. * POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include <sys/cdefs.h>
  32. __FBSDID("$FreeBSD$");
  33. #include <sys/types.h>
  34. #include <sys/param.h>
  35. #include <sys/sysctl.h>
  36. #include <sys/proc.h>
  37. #include <sys/queue.h>
  38. #include <sys/stat.h>
  39. #include <sys/time.h>
  40. #include <sys/user.h>
  41. #include <assert.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <limits.h>
  45. #include <paths.h>
  46. #include <string.h>
  47. #include <unistd.h>
  48. #include <signal.h>
  49. #include <regex.h>
  50. #include <ctype.h>
  51. #include <fcntl.h>
  52. #include <kvm.h>
  53. #include <err.h>
  54. #include <pwd.h>
  55. #include <grp.h>
  56. #include <errno.h>
  57. #include <locale.h>
  58. #define STATUS_MATCH 0
  59. #define STATUS_NOMATCH 1
  60. #define STATUS_BADUSAGE 2
  61. #define STATUS_ERROR 3
  62. #define MIN_PID 5
  63. #define MAX_PID 99999
  64. /* Ignore system-processes (if '-S' flag is not specified) and myself. */
  65. #define PSKIP(kp) ((kp)->ki_pid == mypid || \
  66. (!kthreads && ((kp)->ki_flag & P_KTHREAD) != 0))
  67. enum listtype {
  68. LT_GENERIC,
  69. LT_USER,
  70. LT_GROUP,
  71. LT_TTY,
  72. LT_PGRP,
  73. LT_JID,
  74. LT_SID
  75. };
  76. struct list {
  77. SLIST_ENTRY(list) li_chain;
  78. long li_number;
  79. };
  80. SLIST_HEAD(listhead, list);
  81. static struct kinfo_proc *plist;
  82. static char *selected;
  83. static const char *delim = "\n";
  84. static int nproc;
  85. static int pgrep;
  86. static int signum = SIGTERM;
  87. static int newest;
  88. static int oldest;
  89. static int interactive;
  90. static int inverse;
  91. static int longfmt;
  92. static int matchargs;
  93. static int fullmatch;
  94. static int kthreads;
  95. static int cflags = REG_EXTENDED;
  96. static int quiet;
  97. static kvm_t *kd;
  98. static pid_t mypid;
  99. static struct listhead euidlist = SLIST_HEAD_INITIALIZER(euidlist);
  100. static struct listhead ruidlist = SLIST_HEAD_INITIALIZER(ruidlist);
  101. static struct listhead rgidlist = SLIST_HEAD_INITIALIZER(rgidlist);
  102. static struct listhead pgrplist = SLIST_HEAD_INITIALIZER(pgrplist);
  103. static struct listhead ppidlist = SLIST_HEAD_INITIALIZER(ppidlist);
  104. static struct listhead tdevlist = SLIST_HEAD_INITIALIZER(tdevlist);
  105. static struct listhead sidlist = SLIST_HEAD_INITIALIZER(sidlist);
  106. static struct listhead jidlist = SLIST_HEAD_INITIALIZER(jidlist);
  107. static void usage(void) __attribute__((__noreturn__));
  108. static int killact(const struct kinfo_proc *);
  109. static int grepact(const struct kinfo_proc *);
  110. static void makelist(struct listhead *, enum listtype, char *);
  111. static int takepid(const char *, int);
  112. int
  113. main(int argc, char **argv)
  114. {
  115. char buf[_POSIX2_LINE_MAX], *mstr, **pargv, *p, *q, *pidfile;
  116. const char *execf, *coref;
  117. int ancestors, debug_opt, did_action;
  118. int i, ch, bestidx, rv, criteria, pidfromfile, pidfilelock;
  119. size_t jsz;
  120. int (*action)(const struct kinfo_proc *);
  121. struct kinfo_proc *kp;
  122. struct list *li;
  123. struct timeval best_tval;
  124. regex_t reg;
  125. regmatch_t regmatch;
  126. pid_t pid;
  127. setlocale(LC_ALL, "");
  128. if (strcmp(getprogname(), "pgrep") == 0) {
  129. action = grepact;
  130. pgrep = 1;
  131. } else {
  132. action = killact;
  133. p = argv[1];
  134. if (argc > 1 && p[0] == '-') {
  135. p++;
  136. i = (int)strtol(p, &q, 10);
  137. if (*q == '\0') {
  138. signum = i;
  139. argv++;
  140. argc--;
  141. } else {
  142. if (strncasecmp(p, "SIG", 3) == 0)
  143. p += 3;
  144. for (i = 1; i < NSIG; i++)
  145. if (strcasecmp(sys_signame[i], p) == 0)
  146. break;
  147. if (i != NSIG) {
  148. signum = i;
  149. argv++;
  150. argc--;
  151. }
  152. }
  153. }
  154. }
  155. ancestors = 0;
  156. criteria = 0;
  157. debug_opt = 0;
  158. pidfile = NULL;
  159. pidfilelock = 0;
  160. quiet = 0;
  161. execf = NULL;
  162. coref = _PATH_DEVNULL;
  163. while ((ch = getopt(argc, argv, "DF:G:ILM:N:P:SU:ad:fg:ij:lnoqs:t:u:vx")) != -1)
  164. switch (ch) {
  165. case 'D':
  166. debug_opt++;
  167. break;
  168. case 'F':
  169. pidfile = optarg;
  170. criteria = 1;
  171. break;
  172. case 'G':
  173. makelist(&rgidlist, LT_GROUP, optarg);
  174. criteria = 1;
  175. break;
  176. case 'I':
  177. if (pgrep)
  178. usage();
  179. interactive = 1;
  180. break;
  181. case 'L':
  182. pidfilelock = 1;
  183. break;
  184. case 'M':
  185. coref = optarg;
  186. break;
  187. case 'N':
  188. execf = optarg;
  189. break;
  190. case 'P':
  191. makelist(&ppidlist, LT_GENERIC, optarg);
  192. criteria = 1;
  193. break;
  194. case 'S':
  195. if (!pgrep)
  196. usage();
  197. kthreads = 1;
  198. break;
  199. case 'U':
  200. makelist(&ruidlist, LT_USER, optarg);
  201. criteria = 1;
  202. break;
  203. case 'a':
  204. ancestors++;
  205. break;
  206. case 'd':
  207. if (!pgrep)
  208. usage();
  209. delim = optarg;
  210. break;
  211. case 'f':
  212. matchargs = 1;
  213. break;
  214. case 'g':
  215. makelist(&pgrplist, LT_PGRP, optarg);
  216. criteria = 1;
  217. break;
  218. case 'i':
  219. cflags |= REG_ICASE;
  220. break;
  221. case 'j':
  222. makelist(&jidlist, LT_JID, optarg);
  223. criteria = 1;
  224. break;
  225. case 'l':
  226. longfmt = 1;
  227. break;
  228. case 'n':
  229. newest = 1;
  230. criteria = 1;
  231. break;
  232. case 'o':
  233. oldest = 1;
  234. criteria = 1;
  235. break;
  236. case 'q':
  237. if (!pgrep)
  238. usage();
  239. quiet = 1;
  240. break;
  241. case 's':
  242. makelist(&sidlist, LT_SID, optarg);
  243. criteria = 1;
  244. break;
  245. case 't':
  246. makelist(&tdevlist, LT_TTY, optarg);
  247. criteria = 1;
  248. break;
  249. case 'u':
  250. makelist(&euidlist, LT_USER, optarg);
  251. criteria = 1;
  252. break;
  253. case 'v':
  254. inverse = 1;
  255. break;
  256. case 'x':
  257. fullmatch = 1;
  258. break;
  259. default:
  260. usage();
  261. /* NOTREACHED */
  262. }
  263. argc -= optind;
  264. argv += optind;
  265. if (argc != 0)
  266. criteria = 1;
  267. if (!criteria)
  268. usage();
  269. if (newest && oldest)
  270. errx(STATUS_ERROR, "Options -n and -o are mutually exclusive");
  271. if (pidfile != NULL)
  272. pidfromfile = takepid(pidfile, pidfilelock);
  273. else {
  274. if (pidfilelock) {
  275. errx(STATUS_ERROR,
  276. "Option -L doesn't make sense without -F");
  277. }
  278. pidfromfile = -1;
  279. }
  280. mypid = getpid();
  281. /*
  282. * Retrieve the list of running processes from the kernel.
  283. */
  284. kd = kvm_openfiles(execf, coref, NULL, O_RDONLY, buf);
  285. if (kd == NULL)
  286. errx(STATUS_ERROR, "Cannot open kernel files (%s)", buf);
  287. /*
  288. * Use KERN_PROC_PROC instead of KERN_PROC_ALL, since we
  289. * just want processes and not individual kernel threads.
  290. */
  291. plist = kvm_getprocs(kd, KERN_PROC_PROC, 0, &nproc);
  292. if (plist == NULL) {
  293. errx(STATUS_ERROR, "Cannot get process list (%s)",
  294. kvm_geterr(kd));
  295. }
  296. /*
  297. * Allocate memory which will be used to keep track of the
  298. * selection.
  299. */
  300. if ((selected = malloc(nproc)) == NULL) {
  301. err(STATUS_ERROR, "Cannot allocate memory for %d processes",
  302. nproc);
  303. }
  304. memset(selected, 0, nproc);
  305. /*
  306. * Refine the selection.
  307. */
  308. for (; *argv != NULL; argv++) {
  309. if ((rv = regcomp(&reg, *argv, cflags)) != 0) {
  310. regerror(rv, &reg, buf, sizeof(buf));
  311. errx(STATUS_BADUSAGE,
  312. "Cannot compile regular expression `%s' (%s)",
  313. *argv, buf);
  314. }
  315. for (i = 0, kp = plist; i < nproc; i++, kp++) {
  316. if (PSKIP(kp)) {
  317. if (debug_opt > 0)
  318. fprintf(stderr, "* Skipped %5d %3d %s\n",
  319. kp->ki_pid, kp->ki_uid, kp->ki_comm);
  320. continue;
  321. }
  322. if (matchargs &&
  323. (pargv = kvm_getargv(kd, kp, 0)) != NULL) {
  324. jsz = 0;
  325. while (jsz < sizeof(buf) && *pargv != NULL) {
  326. jsz += snprintf(buf + jsz,
  327. sizeof(buf) - jsz,
  328. pargv[1] != NULL ? "%s " : "%s",
  329. pargv[0]);
  330. pargv++;
  331. }
  332. mstr = buf;
  333. } else
  334. mstr = kp->ki_comm;
  335. rv = regexec(&reg, mstr, 1, &regmatch, 0);
  336. if (rv == 0) {
  337. if (fullmatch) {
  338. if (regmatch.rm_so == 0 &&
  339. regmatch.rm_eo ==
  340. (off_t)strlen(mstr))
  341. selected[i] = 1;
  342. } else
  343. selected[i] = 1;
  344. } else if (rv != REG_NOMATCH) {
  345. regerror(rv, &reg, buf, sizeof(buf));
  346. errx(STATUS_ERROR,
  347. "Regular expression evaluation error (%s)",
  348. buf);
  349. }
  350. if (debug_opt > 1) {
  351. const char *rv_res = "NoMatch";
  352. if (selected[i])
  353. rv_res = "Matched";
  354. fprintf(stderr, "* %s %5d %3d %s\n", rv_res,
  355. kp->ki_pid, kp->ki_uid, mstr);
  356. }
  357. }
  358. regfree(&reg);
  359. }
  360. for (i = 0, kp = plist; i < nproc; i++, kp++) {
  361. if (PSKIP(kp))
  362. continue;
  363. if (pidfromfile >= 0 && kp->ki_pid != pidfromfile) {
  364. selected[i] = 0;
  365. continue;
  366. }
  367. SLIST_FOREACH(li, &ruidlist, li_chain)
  368. if (kp->ki_ruid == (uid_t)li->li_number)
  369. break;
  370. if (SLIST_FIRST(&ruidlist) != NULL && li == NULL) {
  371. selected[i] = 0;
  372. continue;
  373. }
  374. SLIST_FOREACH(li, &rgidlist, li_chain)
  375. if (kp->ki_rgid == (gid_t)li->li_number)
  376. break;
  377. if (SLIST_FIRST(&rgidlist) != NULL && li == NULL) {
  378. selected[i] = 0;
  379. continue;
  380. }
  381. SLIST_FOREACH(li, &euidlist, li_chain)
  382. if (kp->ki_uid == (uid_t)li->li_number)
  383. break;
  384. if (SLIST_FIRST(&euidlist) != NULL && li == NULL) {
  385. selected[i] = 0;
  386. continue;
  387. }
  388. SLIST_FOREACH(li, &ppidlist, li_chain)
  389. if (kp->ki_ppid == (pid_t)li->li_number)
  390. break;
  391. if (SLIST_FIRST(&ppidlist) != NULL && li == NULL) {
  392. selected[i] = 0;
  393. continue;
  394. }
  395. SLIST_FOREACH(li, &pgrplist, li_chain)
  396. if (kp->ki_pgid == (pid_t)li->li_number)
  397. break;
  398. if (SLIST_FIRST(&pgrplist) != NULL && li == NULL) {
  399. selected[i] = 0;
  400. continue;
  401. }
  402. SLIST_FOREACH(li, &tdevlist, li_chain) {
  403. if (li->li_number == -1 &&
  404. (kp->ki_flag & P_CONTROLT) == 0)
  405. break;
  406. if (kp->ki_tdev == (dev_t)li->li_number)
  407. break;
  408. }
  409. if (SLIST_FIRST(&tdevlist) != NULL && li == NULL) {
  410. selected[i] = 0;
  411. continue;
  412. }
  413. SLIST_FOREACH(li, &sidlist, li_chain)
  414. if (kp->ki_sid == (pid_t)li->li_number)
  415. break;
  416. if (SLIST_FIRST(&sidlist) != NULL && li == NULL) {
  417. selected[i] = 0;
  418. continue;
  419. }
  420. SLIST_FOREACH(li, &jidlist, li_chain) {
  421. /* A particular jail ID, including 0 (not in jail) */
  422. if (kp->ki_jid == (int)li->li_number)
  423. break;
  424. /* Any jail */
  425. if (kp->ki_jid > 0 && li->li_number == -1)
  426. break;
  427. }
  428. if (SLIST_FIRST(&jidlist) != NULL && li == NULL) {
  429. selected[i] = 0;
  430. continue;
  431. }
  432. if (argc == 0)
  433. selected[i] = 1;
  434. }
  435. if (!ancestors) {
  436. pid = mypid;
  437. while (pid) {
  438. for (i = 0, kp = plist; i < nproc; i++, kp++) {
  439. if (PSKIP(kp))
  440. continue;
  441. if (kp->ki_pid == pid) {
  442. selected[i] = 0;
  443. pid = kp->ki_ppid;
  444. break;
  445. }
  446. }
  447. if (i == nproc) {
  448. if (pid == mypid)
  449. pid = getppid();
  450. else
  451. break; /* Maybe we're in a jail ? */
  452. }
  453. }
  454. }
  455. if (newest || oldest) {
  456. best_tval.tv_sec = 0;
  457. best_tval.tv_usec = 0;
  458. bestidx = -1;
  459. for (i = 0, kp = plist; i < nproc; i++, kp++) {
  460. if (!selected[i])
  461. continue;
  462. if (bestidx == -1) {
  463. /* The first entry of the list which matched. */
  464. ;
  465. } else if (timercmp(&kp->ki_start, &best_tval, >)) {
  466. /* This entry is newer than previous "best". */
  467. if (oldest) /* but we want the oldest */
  468. continue;
  469. } else {
  470. /* This entry is older than previous "best". */
  471. if (newest) /* but we want the newest */
  472. continue;
  473. }
  474. /* This entry is better than previous "best" entry. */
  475. best_tval.tv_sec = kp->ki_start.tv_sec;
  476. best_tval.tv_usec = kp->ki_start.tv_usec;
  477. bestidx = i;
  478. }
  479. memset(selected, 0, nproc);
  480. if (bestidx != -1)
  481. selected[bestidx] = 1;
  482. }
  483. /*
  484. * Take the appropriate action for each matched process, if any.
  485. */
  486. did_action = 0;
  487. for (i = 0, rv = 0, kp = plist; i < nproc; i++, kp++) {
  488. if (PSKIP(kp))
  489. continue;
  490. if (selected[i]) {
  491. if (longfmt && !pgrep) {
  492. did_action = 1;
  493. printf("kill -%d %d\n", signum, kp->ki_pid);
  494. }
  495. if (inverse)
  496. continue;
  497. } else if (!inverse)
  498. continue;
  499. rv |= (*action)(kp);
  500. }
  501. if (!did_action && !pgrep && longfmt)
  502. fprintf(stderr,
  503. "No matching processes belonging to you were found\n");
  504. exit(rv ? STATUS_MATCH : STATUS_NOMATCH);
  505. }
  506. static void
  507. usage(void)
  508. {
  509. const char *ustr;
  510. if (pgrep)
  511. ustr = "[-LSfilnoqvx] [-d delim]";
  512. else
  513. ustr = "[-signal] [-ILfilnovx]";
  514. fprintf(stderr,
  515. "usage: %s %s [-F pidfile] [-G gid] [-M core] [-N system]\n"
  516. " [-P ppid] [-U uid] [-g pgrp] [-j jid] [-s sid]\n"
  517. " [-t tty] [-u euid] pattern ...\n", getprogname(),
  518. ustr);
  519. exit(STATUS_BADUSAGE);
  520. }
  521. static void
  522. show_process(const struct kinfo_proc *kp)
  523. {
  524. char **argv;
  525. if (quiet) {
  526. assert(pgrep);
  527. return;
  528. }
  529. if ((longfmt || !pgrep) && matchargs &&
  530. (argv = kvm_getargv(kd, kp, 0)) != NULL) {
  531. printf("%d ", (int)kp->ki_pid);
  532. for (; *argv != NULL; argv++) {
  533. printf("%s", *argv);
  534. if (argv[1] != NULL)
  535. putchar(' ');
  536. }
  537. } else if (longfmt || !pgrep)
  538. printf("%d %s", (int)kp->ki_pid, kp->ki_comm);
  539. else
  540. printf("%d", (int)kp->ki_pid);
  541. }
  542. static int
  543. killact(const struct kinfo_proc *kp)
  544. {
  545. int ch, first;
  546. if (interactive) {
  547. /*
  548. * Be careful, ask before killing.
  549. */
  550. printf("kill ");
  551. show_process(kp);
  552. printf("? ");
  553. fflush(stdout);
  554. first = ch = getchar();
  555. while (ch != '\n' && ch != EOF)
  556. ch = getchar();
  557. if (first != 'y' && first != 'Y')
  558. return (1);
  559. }
  560. if (kill(kp->ki_pid, signum) == -1) {
  561. /*
  562. * Check for ESRCH, which indicates that the process
  563. * disappeared between us matching it and us
  564. * signalling it; don't issue a warning about it.
  565. */
  566. if (errno != ESRCH)
  567. warn("signalling pid %d", (int)kp->ki_pid);
  568. /*
  569. * Return 0 to indicate that the process should not be
  570. * considered a match, since we didn't actually get to
  571. * signal it.
  572. */
  573. return (0);
  574. }
  575. return (1);
  576. }
  577. static int
  578. grepact(const struct kinfo_proc *kp)
  579. {
  580. show_process(kp);
  581. if (!quiet)
  582. printf("%s", delim);
  583. return (1);
  584. }
  585. static void
  586. makelist(struct listhead *head, enum listtype type, char *src)
  587. {
  588. struct list *li;
  589. struct passwd *pw;
  590. struct group *gr;
  591. struct stat st;
  592. const char *cp;
  593. char *sp, *ep, buf[MAXPATHLEN];
  594. int empty;
  595. empty = 1;
  596. while ((sp = strsep(&src, ",")) != NULL) {
  597. if (*sp == '\0')
  598. usage();
  599. if ((li = malloc(sizeof(*li))) == NULL) {
  600. err(STATUS_ERROR, "Cannot allocate %zu bytes",
  601. sizeof(*li));
  602. }
  603. SLIST_INSERT_HEAD(head, li, li_chain);
  604. empty = 0;
  605. li->li_number = (uid_t)strtol(sp, &ep, 0);
  606. if (*ep == '\0') {
  607. switch (type) {
  608. case LT_PGRP:
  609. if (li->li_number == 0)
  610. li->li_number = getpgrp();
  611. break;
  612. case LT_SID:
  613. if (li->li_number == 0)
  614. li->li_number = getsid(mypid);
  615. break;
  616. case LT_JID:
  617. if (li->li_number < 0)
  618. errx(STATUS_BADUSAGE,
  619. "Negative jail ID `%s'", sp);
  620. /* For compatibility with old -j */
  621. if (li->li_number == 0)
  622. li->li_number = -1; /* any jail */
  623. break;
  624. case LT_TTY:
  625. if (li->li_number < 0)
  626. errx(STATUS_BADUSAGE,
  627. "Negative /dev/pts tty `%s'", sp);
  628. snprintf(buf, sizeof(buf), _PATH_DEV "pts/%s",
  629. sp);
  630. if (stat(buf, &st) != -1)
  631. goto foundtty;
  632. if (errno == ENOENT)
  633. errx(STATUS_BADUSAGE, "No such tty: `"
  634. _PATH_DEV "pts/%s'", sp);
  635. err(STATUS_ERROR, "Cannot access `"
  636. _PATH_DEV "pts/%s'", sp);
  637. break;
  638. default:
  639. break;
  640. }
  641. continue;
  642. }
  643. switch (type) {
  644. case LT_USER:
  645. if ((pw = getpwnam(sp)) == NULL)
  646. errx(STATUS_BADUSAGE, "Unknown user `%s'", sp);
  647. li->li_number = pw->pw_uid;
  648. break;
  649. case LT_GROUP:
  650. if ((gr = getgrnam(sp)) == NULL)
  651. errx(STATUS_BADUSAGE, "Unknown group `%s'", sp);
  652. li->li_number = gr->gr_gid;
  653. break;
  654. case LT_TTY:
  655. if (strcmp(sp, "-") == 0) {
  656. li->li_number = -1;
  657. break;
  658. } else if (strcmp(sp, "co") == 0) {
  659. cp = "console";
  660. } else {
  661. cp = sp;
  662. }
  663. snprintf(buf, sizeof(buf), _PATH_DEV "%s", cp);
  664. if (stat(buf, &st) != -1)
  665. goto foundtty;
  666. snprintf(buf, sizeof(buf), _PATH_DEV "tty%s", cp);
  667. if (stat(buf, &st) != -1)
  668. goto foundtty;
  669. if (errno == ENOENT)
  670. errx(STATUS_BADUSAGE, "No such tty: `%s'", sp);
  671. err(STATUS_ERROR, "Cannot access `%s'", sp);
  672. foundtty: if ((st.st_mode & S_IFCHR) == 0)
  673. errx(STATUS_BADUSAGE, "Not a tty: `%s'", sp);
  674. li->li_number = st.st_rdev;
  675. break;
  676. case LT_JID:
  677. if (strcmp(sp, "none") == 0)
  678. li->li_number = 0;
  679. else if (strcmp(sp, "any") == 0)
  680. li->li_number = -1;
  681. else if (*ep != '\0')
  682. errx(STATUS_BADUSAGE,
  683. "Invalid jail ID `%s'", sp);
  684. break;
  685. default:
  686. usage();
  687. }
  688. }
  689. if (empty)
  690. usage();
  691. }
  692. static int
  693. takepid(const char *pidfile, int pidfilelock)
  694. {
  695. char *endp, line[BUFSIZ];
  696. FILE *fh;
  697. long rval;
  698. fh = fopen(pidfile, "r");
  699. if (fh == NULL)
  700. err(STATUS_ERROR, "Cannot open pidfile `%s'", pidfile);
  701. if (pidfilelock) {
  702. /*
  703. * If we can lock pidfile, this means that daemon is not
  704. * running, so would be better not to kill some random process.
  705. */
  706. if (flock(fileno(fh), LOCK_EX | LOCK_NB) == 0) {
  707. (void)fclose(fh);
  708. errx(STATUS_ERROR, "File '%s' can be locked", pidfile);
  709. } else {
  710. if (errno != EWOULDBLOCK) {
  711. errx(STATUS_ERROR,
  712. "Error while locking file '%s'", pidfile);
  713. }
  714. }
  715. }
  716. if (fgets(line, sizeof(line), fh) == NULL) {
  717. if (feof(fh)) {
  718. (void)fclose(fh);
  719. errx(STATUS_ERROR, "Pidfile `%s' is empty", pidfile);
  720. }
  721. (void)fclose(fh);
  722. err(STATUS_ERROR, "Cannot read from pid file `%s'", pidfile);
  723. }
  724. (void)fclose(fh);
  725. rval = strtol(line, &endp, 10);
  726. if (*endp != '\0' && !isspace((unsigned char)*endp))
  727. errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
  728. else if (rval < MIN_PID || rval > MAX_PID)
  729. errx(STATUS_ERROR, "Invalid pid in file `%s'", pidfile);
  730. return (rval);
  731. }