pgrep.c (37451B)
1 /* 2 * pgrep, pkill - find or signal processes by name and other attributes 3 * 4 * Gunnar Ritter, Freiburg i. Br., Germany, March 2003. 5 */ 6 /* 7 * Copyright (c) 2003 Gunnar Ritter 8 * 9 * This software is provided 'as-is', without any express or implied 10 * warranty. In no event will the authors be held liable for any damages 11 * arising from the use of this software. 12 * 13 * Permission is granted to anyone to use this software for any purpose, 14 * including commercial applications, and to alter it and redistribute 15 * it freely, subject to the following restrictions: 16 * 17 * 1. The origin of this software must not be misrepresented; you must not 18 * claim that you wrote the original software. If you use this software 19 * in a product, an acknowledgment in the product documentation would be 20 * appreciated but is not required. 21 * 22 * 2. Altered source versions must be plainly marked as such, and must not be 23 * misrepresented as being the original software. 24 * 25 * 3. This notice may not be removed or altered from any source distribution. 26 */ 27 28 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4 29 #define USED __attribute__ ((used)) 30 #elif defined __GNUC__ 31 #define USED __attribute__ ((unused)) 32 #else 33 #define USED 34 #endif 35 static const char sccsid[] USED = "@(#)pgrep.sl 1.25 (gritter) 12/16/07"; 36 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <fcntl.h> 40 #include <unistd.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <stdlib.h> 44 #include <errno.h> 45 #include <libgen.h> 46 #include <alloca.h> 47 #include <dirent.h> 48 #include <limits.h> 49 #include <pwd.h> 50 #include <signal.h> 51 #include <grp.h> 52 #include <locale.h> 53 #include <ctype.h> 54 #include <regex.h> 55 56 #if !defined (__linux__) && !defined (__NetBSD__) && !defined (__OpenBSD__) \ 57 && !defined (__APPLE__) 58 #if defined (__hpux) 59 #include <sys/param.h> 60 #include <sys/pstat.h> 61 #elif defined (_AIX) 62 #include <procinfo.h> 63 #define proc process 64 #else /* !__hpux, !_AIX */ 65 #ifdef sun 66 #define _STRUCTURED_PROC 1 67 #endif /* sun */ 68 #include <sys/procfs.h> 69 #endif /* !__hpux, !_AIX */ 70 #endif /* !__linux__, !__NetBSD__, !__OpenBSD__ */ 71 72 #if defined (__NetBSD__) || defined (__OpenBSD__) || defined (__APPLE__) 73 #ifndef __APPLE__ 74 #include <kvm.h> 75 #endif 76 #include <sys/param.h> 77 #include <sys/sysctl.h> 78 #if defined (__APPLE__) 79 #include <mach/mach_types.h> 80 #include <mach/task_info.h> 81 #endif /* __APPLE__ */ 82 #define proc process 83 #undef p_pgid 84 #define p_pgid p__pgid 85 #endif /* __NetBSD__, __OpenBSD__, __APPLE__ */ 86 87 #ifndef PRNODEV 88 #define PRNODEV 0 89 #endif 90 91 #include <blank.h> 92 93 #define PROCDIR "/proc" 94 #define eq(a, b) (strcmp(a, b) == 0) 95 96 enum okay { 97 OKAY, 98 STOP 99 }; 100 101 enum valtype { 102 VT_CHAR, 103 VT_INT, 104 VT_UINT, 105 VT_LONG, 106 VT_ULONG 107 }; 108 109 union value { 110 char v_char; 111 int v_int; 112 unsigned int v_uint; 113 long v_long; 114 unsigned long v_ulong; 115 }; 116 117 struct proc { 118 struct proc *p_nxt; /* next proc structure */ 119 pid_t p_pid; /* process id */ 120 char p_fname[19]; /* executable name */ 121 pid_t p_ppid; /* parent process id */ 122 pid_t p_pgid; /* process group id */ 123 pid_t p_sid; /* session id */ 124 int p_ttydev; /* controlling terminal */ 125 char p_psargs[80]; /* process arguments */ 126 uid_t p_uid; /* real user id */ 127 uid_t p_euid; /* effective user id */ 128 gid_t p_gid; /* real group id */ 129 gid_t p_egid; /* effective group id */ 130 unsigned long p_start; /* start time (in jiffies except BSD) */ 131 unsigned long p_size; /* size in kilobytes */ 132 int p_match; /* matched this process */ 133 }; 134 135 enum attype { 136 ATT_PPID, /* parent process id */ 137 ATT_PGRP, /* process group id */ 138 ATT_SID, /* sessiond id */ 139 ATT_EUID, /* effective user id */ 140 ATT_UID, /* real user id */ 141 ATT_GID, /* real group id */ 142 ATT_TTY, /* controlling terminal */ 143 ATT_ALL 144 }; 145 146 struct attrib { 147 struct attrib *a_nxt; /* next element of list */ 148 enum attype a_type; /* type of attribute */ 149 long a_val; /* value of attribute */ 150 }; 151 152 struct attlist { 153 struct attlist *al_nxt; /* next element of list */ 154 struct attrib *al_att; /* this attribute */ 155 }; 156 157 static const char *progname; 158 static pid_t mypid; /* this instance's pid */ 159 static unsigned errcnt; /* error count */ 160 static int matched; /* a process matched */ 161 static int pkill; /* this is the pkill command */ 162 static int fflag; /* match against full command line */ 163 static int lflag; /* long output format */ 164 static int nflag; /* match newest process only */ 165 static int oflag; /* match oldest process only */ 166 static int vflag; /* reverse matching */ 167 static int xflag; /* match exact string */ 168 static int signo = SIGTERM; /* signal to send */ 169 static int need_euid_egid; /* need euid or egid */ 170 static struct attlist *attributes; /* required attributes */ 171 static struct proc *processes; /* collected processes */ 172 static regex_t *expression; /* regular expression to match */ 173 static const char *delimiter; /* delimiter string */ 174 static int prdelim; /* print a delimiter (not first proc) */ 175 176 static int str_2_sig(const char *, int *); 177 178 static void * 179 srealloc(void *vp, size_t nbytes) 180 { 181 void *p; 182 183 if ((p = realloc(vp, nbytes)) == NULL) { 184 write(2, "no memory\n", 10); 185 exit(3); 186 } 187 return p; 188 } 189 190 static void * 191 smalloc(size_t nbytes) 192 { 193 return srealloc(NULL, nbytes); 194 } 195 196 static void * 197 scalloc(size_t nmemb, size_t size) 198 { 199 void *p; 200 201 if ((p = (void *)calloc(nmemb, size)) == NULL) { 202 write(2, "no memory\n", 10); 203 exit(3); 204 } 205 return p; 206 } 207 208 #if !defined (__hpux) && !defined (_AIX) && !defined (__NetBSD__) \ 209 && !defined (__OpenBSD__) && !defined (__APPLE__) 210 static void 211 chdir_to_proc(void) 212 { 213 static int fd = -1; 214 215 if (fd == -1 && (fd = open(PROCDIR, O_RDONLY)) < 0) { 216 fprintf(stderr, "%s: cannot open %s\n", progname, PROCDIR); 217 exit(3); 218 } 219 if (fchdir(fd) < 0) { 220 fprintf(stderr, "%s: cannot chdir to %s\n", progname, PROCDIR); 221 exit(3); 222 } 223 } 224 225 static union value * 226 getval(char **listp, enum valtype type, int separator, int sep2) 227 { 228 char *buf; 229 static union value v; 230 const char *cp, *op; 231 char *cq, *x; 232 233 if (**listp == '\0') 234 return NULL; 235 op = *listp; 236 while (**listp != '\0') { 237 if ((separator==' ' ? isspace(**listp) : **listp == separator) 238 || **listp == sep2) 239 break; 240 (*listp)++; 241 } 242 buf = alloca(*listp - op + 1); 243 for (cp = op, cq = buf; cp < *listp; cp++, cq++) 244 *cq = *cp; 245 *cq = '\0'; 246 if (**listp) { 247 while ((separator == ' ' ? 248 isspace(**listp) : **listp == separator) || 249 **listp == sep2) 250 (*listp)++; 251 } 252 switch (type) { 253 case VT_CHAR: 254 if (buf[1] != '\0') 255 return NULL; 256 v.v_char = buf[0]; 257 break; 258 case VT_INT: 259 v.v_int = strtol(buf, &x, 10); 260 if (*x != '\0') 261 return NULL; 262 break; 263 case VT_UINT: 264 v.v_uint = strtoul(buf, &x, 10); 265 if (*x != '\0') 266 return NULL; 267 break; 268 case VT_LONG: 269 v.v_long = strtol(buf, &x, 10); 270 if (*x != '\0') 271 return NULL; 272 break; 273 case VT_ULONG: 274 v.v_ulong = strtoul(buf, &x, 10); 275 if (*x != '\0') 276 return NULL; 277 break; 278 } 279 return &v; 280 } 281 #endif /* !__hpux, !_AIX, !__NetBSD__, !__OpenBSD__, !__APPLE__ */ 282 283 static const char * 284 element(const char **listp, int override) 285 { 286 static char *buf; 287 static size_t buflen; 288 const char *cp, *op; 289 char *cq; 290 size_t sz; 291 int stop = ','; 292 293 if (**listp == '\0') 294 return NULL; 295 op = *listp; 296 while (**listp != '\0') { 297 if (**listp == override) 298 stop = '\0'; 299 if (stop != '\0' && (**listp == stop || isblank(**listp))) 300 break; 301 (*listp)++; 302 } 303 if (**listp == '\0') 304 return op; 305 if ((sz = *listp - op + 1) > buflen) { 306 buflen = sz; 307 buf = srealloc(buf, buflen); 308 } 309 for (cp = op, cq = buf; cp < *listp; cp++, cq++) 310 *cq = *cp; 311 *cq = '\0'; 312 if (**listp) { 313 while (**listp == stop || isblank(**listp)) 314 (*listp)++; 315 } 316 return buf; 317 } 318 319 #if !defined (__hpux) && !defined (_AIX) && !defined (__NetBSD__) && \ 320 !defined (__OpenBSD__) && !defined (__APPLE__) 321 322 #if defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__) 323 324 #define GETVAL_REQ(a) if ((v = getval(&cp, (a), ' ', 0)) == NULL) \ 325 return STOP 326 327 #define GETVAL_OPT(a) if ((v = getval(&cp, (a), ' ', 0)) == NULL) \ 328 goto complete 329 330 #define GETVAL_COMMA(a) if ((v = getval(&cp, (a), ' ', ',')) == NULL) \ 331 return STOP 332 333 #endif /* __linux__ || __FreeBSD__ || __DragonFly__ */ 334 335 336 #if defined (__linux__) 337 static enum okay 338 getproc_stat(struct proc *p, pid_t expected_pid) 339 { 340 static char *buf; 341 static size_t buflen; 342 union value *v; 343 FILE *fp; 344 char *cp, *cq, *ce; 345 size_t sz, sc; 346 347 if ((fp = fopen("stat", "r")) == NULL) 348 return STOP; 349 for (cp = buf; ;) { 350 const unsigned chunk = 32; 351 352 if (buflen < (sz = cp - buf + chunk)) { 353 sc = cp - buf; 354 buf = srealloc(buf, buflen = sz); 355 cp = &buf[sc]; 356 } 357 if ((sz = fread(cp, 1, chunk, fp)) < chunk) { 358 ce = &cp[sz - 1]; 359 break; 360 } 361 cp += chunk; 362 } 363 fclose(fp); 364 if (*ce != '\n') 365 return STOP; 366 *ce-- = '\0'; 367 cp = buf; 368 GETVAL_REQ(VT_INT); 369 if ((p->p_pid = v->v_int) != expected_pid) 370 return STOP; 371 if (*cp++ != '(') 372 return STOP; 373 for (cq = ce; cq >= cp && *cq != ')'; cq--); 374 if (cq < cp) 375 return STOP; 376 *cq = '\0'; 377 strncpy(p->p_fname, cp, sizeof p->p_fname); 378 p->p_fname[sizeof p->p_fname - 1] = '\0'; 379 cp = &cq[1]; 380 while (isspace(*cp)) 381 cp++; 382 GETVAL_REQ(VT_CHAR); 383 if (v->v_char == 'Z') 384 return STOP; 385 GETVAL_REQ(VT_INT); 386 p->p_ppid = v->v_int; 387 GETVAL_REQ(VT_INT); 388 p->p_pgid = v->v_int; 389 GETVAL_REQ(VT_INT); 390 p->p_sid = v->v_int; 391 GETVAL_REQ(VT_INT); 392 p->p_ttydev = v->v_int; 393 GETVAL_REQ(VT_INT); 394 /* tty_pgrp not used */ 395 GETVAL_REQ(VT_ULONG); 396 /* flag not used */ 397 GETVAL_REQ(VT_ULONG); 398 /* min_flt */ 399 GETVAL_REQ(VT_ULONG); 400 /* cmin_flt */ 401 GETVAL_REQ(VT_ULONG); 402 /* maj_flt */ 403 GETVAL_REQ(VT_ULONG); 404 /* cmaj_flt */ 405 GETVAL_REQ(VT_ULONG); 406 /* time */ 407 GETVAL_REQ(VT_ULONG); 408 /* stime */ 409 GETVAL_REQ(VT_LONG); 410 /* ctime */ 411 GETVAL_REQ(VT_LONG); 412 /* cstime */ 413 GETVAL_REQ(VT_LONG); 414 /* priority */ 415 GETVAL_REQ(VT_LONG); 416 /* nice */ 417 GETVAL_REQ(VT_LONG); 418 /* timeout not used */ 419 GETVAL_REQ(VT_LONG); 420 /* it_real_value not used */ 421 GETVAL_REQ(VT_ULONG); 422 p->p_start = v->v_ulong; 423 GETVAL_REQ(VT_ULONG); 424 p->p_size = (v->v_ulong >> 10); 425 return OKAY; 426 } 427 428 static enum okay 429 getproc_cmdline(struct proc *p) 430 { 431 FILE *fp; 432 char *cp, *ce; 433 int hadzero = 0, c; 434 435 if ((fp = fopen("cmdline", "r")) != NULL) { 436 cp = p->p_psargs; 437 ce = cp + sizeof p->p_psargs - 1; 438 while (cp < ce && (c = getc(fp)) != EOF) { 439 if (c != '\0') { 440 if (hadzero) { 441 *cp++ = ' '; 442 if (cp == ce) 443 break; 444 hadzero = 0; 445 } 446 *cp++ = c; 447 } else { 448 hadzero = 1; 449 } 450 } 451 *cp = '\0'; 452 fclose(fp); 453 } 454 if (*p->p_psargs == '\0' && p->p_size == 0) 455 strcpy(p->p_psargs, p->p_fname); 456 return OKAY; 457 } 458 459 static enum okay 460 getproc_status(struct proc *p) 461 { 462 char line[LINE_MAX]; 463 union value *v; 464 FILE *fp; 465 char *cp; 466 int scanr; 467 468 if ((fp = fopen("status", "r")) == NULL) 469 return STOP; 470 scanr = 0; 471 while (fgets(line, sizeof line, fp) != NULL) { 472 if (strncmp(line, "Uid:", 4) == 0) { 473 cp = &line[4]; 474 while (isspace(*cp)) 475 cp++; 476 if ((v = getval(&cp, VT_INT, ' ', 0)) == NULL) { 477 fclose(fp); 478 return STOP; 479 } 480 p->p_uid = v->v_int; 481 if ((v = getval(&cp, VT_INT, ' ', 0)) == NULL) { 482 fclose(fp); 483 return STOP; 484 } 485 p->p_euid = v->v_int; 486 scanr++; 487 } else if (strncmp(line, "Gid:", 4) == 0) { 488 cp = &line[4]; 489 while (isspace(*cp)) 490 cp++; 491 if ((v = getval(&cp, VT_INT, ' ', 0)) == NULL) { 492 fclose(fp); 493 return STOP; 494 } 495 p->p_gid = v->v_int; 496 if ((v = getval(&cp, VT_INT, ' ', 0)) == NULL) { 497 fclose(fp); 498 return STOP; 499 } 500 p->p_egid = v->v_int; 501 scanr++; 502 } 503 } 504 fclose(fp); 505 if (scanr != 2) 506 return STOP; 507 return OKAY; 508 } 509 510 static struct proc * 511 getproc(const char *dir, pid_t expected_pid) 512 { 513 struct proc *p; 514 enum okay result; 515 516 p = scalloc(1, sizeof *p); 517 if (chdir(dir) == 0) { 518 if ((result = getproc_stat(p, expected_pid)) == OKAY) 519 if ((result = getproc_cmdline(p)) == OKAY) 520 result = getproc_status(p); 521 chdir_to_proc(); 522 } else 523 result = STOP; 524 if (result == STOP) { 525 free(p); 526 return NULL; 527 } 528 return p; 529 } 530 531 #elif defined (__FreeBSD__) || defined (__DragonFly__) 532 533 static enum okay 534 getproc_status(struct proc *p, pid_t expected_pid) 535 { 536 static char *buf; 537 static size_t buflen; 538 union value *v; 539 FILE *fp; 540 char *cp, *ce, *cq; 541 size_t sz, sc; 542 int mj, mi; 543 544 if ((fp = fopen("status", "r")) == NULL) 545 return STOP; 546 for (cp = buf; ;) { 547 const unsigned chunk = 32; 548 549 if (buflen < (sz = cp - buf + chunk)) { 550 sc = cp - buf; 551 buf = srealloc(buf, buflen = sz); 552 cp = &buf[sc]; 553 } 554 if ((sz = fread(cp, 1, chunk, fp)) < chunk) { 555 ce = &cp[sz - 1]; 556 break; 557 } 558 cp += chunk; 559 } 560 fclose(fp); 561 if (*ce != '\n') 562 return STOP; 563 *ce-- = '\0'; 564 cp = buf; 565 while (*cp != ' ') { 566 if (cp - buf < sizeof p->p_fname - 2) 567 p->p_fname[cp-buf] = *cp; 568 cp++; 569 } 570 if (cp - buf < sizeof p->p_fname - 1) 571 p->p_fname[cp-buf] = '\0'; 572 else 573 p->p_fname[sizeof p->p_fname - 1] = '\0'; 574 while (*cp == ' ') 575 cp++; 576 GETVAL_REQ(VT_INT); 577 p->p_pid = v->v_int; 578 GETVAL_REQ(VT_INT); 579 p->p_ppid = v->v_int; 580 GETVAL_REQ(VT_INT); 581 p->p_pgid = v->v_int; 582 GETVAL_REQ(VT_INT); 583 p->p_sid = v->v_int; 584 if (isdigit(*cp)) { 585 GETVAL_COMMA(VT_INT); 586 mj = v->v_int; 587 GETVAL_REQ(VT_INT); 588 mi = v->v_int; 589 if (mj != -1 || mi != -1) 590 p->p_ttydev = makedev(mj, mi); 591 } else { 592 struct stat st; 593 char *dev; 594 cq = cp; 595 while (*cp != ' ') cp++; 596 *cp = '\0'; 597 dev = smalloc(cp - cq + 8); 598 strcpy(dev, "/dev/"); 599 strcpy(&dev[5], cq); 600 if (stat(dev, &st) < 0) 601 p->p_ttydev = PRNODEV; 602 else 603 p->p_ttydev = st.st_rdev; 604 free(dev); 605 *cp = ' '; 606 while (*cp == ' ') cp++; 607 } 608 while (*cp != ' ') cp++; while (*cp == ' ') cp++; 609 /* skip flags */ 610 GETVAL_COMMA(VT_LONG); 611 p->p_start = v->v_long; 612 GETVAL_REQ(VT_LONG); 613 /* skip microseconds */ 614 while (*cp != ' ') cp++; while (*cp == ' ') cp++; 615 /* skip user time */ 616 while (*cp != ' ') cp++; while (*cp == ' ') cp++; 617 /* skip system time */ 618 while (*cp != ' ') cp++; while (*cp == ' ') cp++; 619 /* skip wchan message */ 620 GETVAL_REQ(VT_INT); 621 p->p_euid = v->v_int; 622 GETVAL_REQ(VT_INT); 623 p->p_uid = v->v_int; 624 GETVAL_COMMA(VT_INT); 625 p->p_gid = v->v_int; 626 GETVAL_COMMA(VT_INT); 627 p->p_egid = v->v_int; 628 return OKAY; 629 } 630 631 static enum okay 632 getproc_cmdline(struct proc *p) 633 { 634 FILE *fp; 635 char *cp, *ce; 636 int hadzero = 0, c; 637 638 if ((fp = fopen("cmdline", "r")) != NULL) { 639 cp = p->p_psargs; 640 ce = cp + sizeof p->p_psargs - 1; 641 while (cp < ce && (c = getc(fp)) != EOF) { 642 if (c != '\0') { 643 if (hadzero) { 644 *cp++ = ' '; 645 if (cp == ce) 646 break; 647 hadzero = 0; 648 } 649 *cp++ = c; 650 } else { 651 hadzero = 1; 652 } 653 } 654 *cp = '\0'; 655 fclose(fp); 656 } 657 if (*p->p_psargs == '\0' && p->p_size == 0) 658 strcpy(p->p_psargs, p->p_fname); 659 return OKAY; 660 } 661 662 static struct proc * 663 getproc(const char *dir, pid_t expected_pid) 664 { 665 struct proc *p; 666 enum okay result; 667 668 p = scalloc(1, sizeof *p); 669 if (chdir(dir) == 0) { 670 if ((result = getproc_status(p, expected_pid)) == OKAY) 671 result = getproc_cmdline(p); 672 chdir_to_proc(); 673 } else 674 result = STOP; 675 if (result == STOP) { 676 free(p); 677 return NULL; 678 } 679 return p; 680 } 681 682 #else /* !__linux__, !__FreeBSD__, !__DragonFly__ */ 683 684 static const char * 685 concat(const char *dir, const char *base) 686 { 687 static char *name; 688 static long size; 689 long length; 690 char *np; 691 const char *cp; 692 693 if ((length = strlen(dir) + strlen(base) + 2) > size) 694 name = srealloc(name, size = length); 695 np = name; 696 for (cp = dir; *cp; cp++) 697 *np++ = *cp; 698 *np++ = '/'; 699 for (cp = base; *cp; cp++) 700 *np++ = *cp; 701 *np = '\0'; 702 return name; 703 } 704 705 static enum okay 706 getproc_psinfo(const char *dir, struct proc *p, pid_t expected_pid) 707 { 708 FILE *fp; 709 struct psinfo pi; 710 711 if ((fp = fopen(concat(dir, "psinfo"), "r")) == NULL) 712 return STOP; 713 if (fread(&pi, 1, sizeof pi, fp) != sizeof pi || 714 pi.pr_pid != expected_pid) { 715 fclose(fp); 716 return STOP; 717 } 718 fclose(fp); 719 p->p_pid = pi.pr_pid; 720 strncpy(p->p_fname, pi.pr_fname, sizeof p->p_fname); 721 p->p_fname[sizeof p->p_fname - 1] = '\0'; 722 p->p_ppid = pi.pr_ppid; 723 p->p_pgid = pi.pr_pgid; 724 p->p_sid = pi.pr_sid; 725 p->p_ttydev = pi.pr_ttydev; 726 strncpy(p->p_psargs, pi.pr_psargs, sizeof p->p_psargs); 727 p->p_psargs[sizeof p->p_psargs - 1] = '\0'; 728 p->p_uid = pi.pr_uid; 729 p->p_gid = pi.pr_gid; 730 #ifdef __sun 731 p->p_euid = pi.pr_euid; 732 p->p_egid = pi.pr_egid; 733 #endif /* __sun */ 734 p->p_start = pi.pr_start.tv_sec; 735 p->p_size = pi.pr_size; 736 return OKAY; 737 } 738 739 #ifndef __sun 740 static enum okay 741 getproc_cred(const char *dir, struct proc *p) 742 { 743 FILE *fp; 744 struct prcred pc; 745 746 if ((fp = fopen(concat(dir, "cred"), "r")) == NULL) 747 return need_euid_egid ? STOP : OKAY; 748 if (fread(&pc, 1, sizeof pc, fp) != sizeof pc) { 749 fclose(fp); 750 return STOP; 751 } 752 fclose(fp); 753 p->p_euid = pc.pr_euid; 754 p->p_egid = pc.pr_egid; 755 return OKAY; 756 } 757 #endif /* !__sun */ 758 759 static struct proc * 760 getproc(const char *dir, pid_t expected_pid) 761 { 762 struct proc *p; 763 enum okay result; 764 765 p = scalloc(1, sizeof *p); 766 result = getproc_psinfo(dir, p, expected_pid); 767 #ifndef __sun 768 if (result == OKAY) 769 result = getproc_cred(dir, p); 770 #endif /* !__sun */ 771 if (result == STOP) { 772 free(p); 773 return NULL; 774 } 775 return p; 776 } 777 #endif /* !__linux__ */ 778 779 static void 780 collectprocs(void) 781 { 782 struct proc *p, *pq = NULL; 783 DIR *Dp; 784 struct dirent *dp; 785 unsigned long val; 786 char *x; 787 788 if ((Dp = opendir(".")) != NULL) { 789 while ((dp = readdir(Dp)) != NULL) { 790 if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || 791 (dp->d_name[1] == '.' && 792 dp->d_name[2] == '\0'))) 793 continue; 794 val = strtoul(dp->d_name, &x, 10); 795 if (*x != 0) 796 continue; 797 if ((p = getproc(dp->d_name, val)) != NULL) { 798 if (pq) 799 pq->p_nxt = p; 800 else 801 processes = p; 802 pq = p; 803 } 804 } 805 closedir(Dp); 806 } 807 } 808 809 #elif defined (__hpux) 810 static void 811 collectprocs(void) 812 { 813 #define burst ((size_t)10) 814 struct proc *p, *pq = NULL; 815 struct pst_status pst[burst]; 816 int i, count; 817 int idx = 0; 818 819 while ((count = pstat_getproc(pst, sizeof *pst, burst, idx)) > 0) { 820 for (i = 0; i < count; i++) { 821 p = scalloc(sizeof *p, 1); 822 if (pq) 823 pq->p_nxt = p; 824 else 825 processes = p; 826 pq = p; 827 p->p_pid = pst[i].pst_pid; 828 strncpy(p->p_fname, pst[i].pst_ucomm, 829 sizeof p->p_fname); 830 p->p_fname[sizeof p->p_fname - 1] = '\0'; 831 p->p_ppid = pst[i].pst_ppid; 832 p->p_pgid = pst[i].pst_pgrp; 833 p->p_sid = pst[i].pst_sid; 834 if (pst[i].pst_term.psd_major != -1 || 835 pst[i].pst_term.psd_minor != -1) 836 p->p_ttydev = makedev(pst[i].pst_term.psd_major, 837 pst[i].pst_term.psd_minor); 838 strncpy(p->p_psargs, pst[i].pst_cmd, 839 sizeof p->p_psargs); 840 p->p_psargs[sizeof p->p_psargs - 1] = '\0'; 841 p->p_uid = pst[i].pst_uid; 842 p->p_euid = pst[i].pst_euid; 843 p->p_gid = pst[i].pst_gid; 844 p->p_egid = pst[i].pst_egid; 845 p->p_start = pst[i].pst_start; 846 p->p_size = pst[i].pst_dsize + pst[i].pst_tsize + 847 pst[i].pst_ssize; 848 } 849 idx = pst[count-1].pst_idx + 1; 850 } 851 } 852 #elif defined (_AIX) 853 static void 854 oneproc(struct proc *p, struct procentry64 *pi) 855 { 856 char args[100], *ap, *cp; 857 858 p->p_pid = pi->pi_pid; 859 strncpy(p->p_fname, pi->pi_comm, sizeof p->p_fname); 860 p->p_fname[sizeof p->p_fname - 1] = '\0'; 861 p->p_ppid = pi->pi_ppid; 862 p->p_pgid = pi->pi_pgrp; 863 p->p_sid = pi->pi_sid; 864 p->p_ttydev = pi->pi_ttyp ? pi->pi_ttyd : PRNODEV; 865 p->p_uid = pi->pi_uid; 866 p->p_euid = pi->pi_cred.crx_uid; 867 p->p_gid = pi->pi_cred.crx_rgid; 868 p->p_egid = pi->pi_cred.crx_gid; 869 p->p_start = pi->pi_start; 870 p->p_size = pi->pi_size; 871 if (getargs(pi, sizeof *pi, args, sizeof args) == 0) { 872 ap = args; 873 cp = p->p_psargs; 874 while (cp < &p->p_psargs[sizeof p->p_psargs - 1]) { 875 if (ap[0] == '\0') { 876 if (ap[1] == '\0') 877 break; 878 *cp++ = ' '; 879 } else 880 *cp++ = *ap; 881 ap++; 882 } 883 *cp = '\0'; 884 } 885 } 886 887 static void 888 collectprocs(void) 889 { 890 #define burst ((size_t)10) 891 struct proc *p, *pq = NULL; 892 struct procentry64 pi[burst]; 893 pid_t idx = 0; 894 int i, count; 895 896 while ((count = getprocs64(pi, sizeof *pi, NULL, 0, &idx, burst)) > 0) { 897 for (i = 0; i < count; i++) { 898 p = scalloc(sizeof *p, 1); 899 if (pq) 900 pq->p_nxt = p; 901 else 902 processes = p; 903 pq = p; 904 oneproc(p, &pi[i]); 905 } 906 if (count < burst) 907 break; 908 } 909 } 910 #elif defined (__OpenBSD__) 911 #include <uvm/uvm_extern.h> 912 static void 913 oneproc(struct proc *p, struct kinfo_proc *kp) 914 { 915 p->p_pid = kp->kp_proc.p_pid; 916 strncpy(p->p_fname, kp->kp_proc.p_comm, sizeof p->p_fname); 917 p->p_fname[sizeof p->p_fname - 1] = '\0'; 918 p->p_ppid = kp->kp_eproc.e_ppid; 919 p->p_pgid = kp->kp_eproc.e_pgid; 920 p->p_sid = kp->kp_eproc.e_tpgid; /* ? */ 921 p->p_ttydev = kp->kp_eproc.e_tdev; 922 p->p_uid = kp->kp_eproc.e_pcred.p_ruid; 923 p->p_euid = kp->kp_eproc.e_ucred.cr_uid; 924 p->p_gid = kp->kp_eproc.e_pcred.p_rgid; 925 p->p_egid = kp->kp_eproc.e_ucred.cr_gid; 926 p->p_start = kp->kp_eproc.e_pstats.p_start.tv_sec; 927 p->p_size = kp->kp_eproc.e_vm.vm_tsize + 928 kp->kp_eproc.e_vm.vm_dsize + 929 kp->kp_eproc.e_vm.vm_ssize; 930 } 931 static void 932 argproc(struct proc *p, struct kinfo_proc *kp, kvm_t *kt) 933 { 934 char **args; 935 char *ap, *pp; 936 937 if ((args = kvm_getargv(kt, kp, sizeof p->p_psargs)) == NULL) 938 return; 939 ap = args[0]; 940 for (pp = p->p_psargs; pp < &p->p_psargs[sizeof p->p_psargs-1]; pp++) { 941 if (*ap == '\0') { 942 *pp = ' '; 943 ap = *++args; 944 if (ap == NULL) 945 break; 946 } else 947 *pp = *ap++; 948 } 949 } 950 951 static void 952 collectprocs(void) 953 { 954 struct proc *p, *pq = NULL; 955 kvm_t *kt; 956 struct kinfo_proc *kp; 957 int i, cnt; 958 959 if ((kt = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open")) == NULL) 960 exit(1); 961 kp = kvm_getprocs(kt, KERN_PROC_ALL, 0, &cnt); 962 for (i = 0; i < cnt; i++) { 963 p = scalloc(sizeof *p, 1); 964 if (pq) 965 pq->p_nxt = p; 966 else 967 processes = p; 968 pq = p; 969 oneproc(p, &kp[i]); 970 argproc(p, &kp[i], kt); 971 } 972 kvm_close(kt); 973 } 974 #elif defined (__NetBSD__) 975 static void 976 oneproc(struct proc *p, struct kinfo_proc2 *kp) 977 { 978 p->p_pid = kp->p_pid; 979 strncpy(p->p_fname, kp->p_comm, sizeof p->p_fname); 980 p->p_fname[sizeof p->p_fname - 1] = '\0'; 981 p->p_ppid = kp->p_ppid; 982 p->p_pgid = kp->p__pgid; 983 p->p_sid = kp->p_sid; 984 p->p_ttydev = kp->p_tdev; 985 p->p_uid = kp->p_ruid; 986 p->p_euid = kp->p_uid; 987 p->p_gid = kp->p_rgid; 988 p->p_egid = kp->p_gid; 989 p->p_start = kp->p_ustart_sec; 990 p->p_size = kp->p_vm_tsize + kp->p_vm_dsize + kp->p_vm_ssize; 991 } 992 993 static void 994 argproc(struct proc *p, struct kinfo_proc2 *kp, kvm_t *kt) 995 { 996 char **args; 997 char *ap, *pp; 998 999 if ((args = kvm_getargv2(kt, kp, sizeof p->p_psargs)) == NULL) 1000 return; 1001 ap = args[0]; 1002 for (pp = p->p_psargs; pp < &p->p_psargs[sizeof p->p_psargs-1]; pp++) { 1003 if (*ap == '\0') { 1004 *pp = ' '; 1005 ap = *++args; 1006 if (ap == NULL) 1007 break; 1008 } else 1009 *pp = *ap++; 1010 } 1011 } 1012 1013 static void 1014 collectprocs(void) 1015 { 1016 struct proc *p, *pq = NULL; 1017 kvm_t *kt; 1018 struct kinfo_proc2 *kp; 1019 int i, cnt; 1020 1021 if ((kt = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, "kvm_open")) == NULL) 1022 exit(1); 1023 kp = kvm_getproc2(kt, KERN_PROC_ALL, 0, sizeof *kp, &cnt); 1024 for (i = 0; i < cnt; i++) { 1025 p = scalloc(sizeof *p, 1); 1026 if (pq) 1027 pq->p_nxt = p; 1028 else 1029 processes = p; 1030 pq = p; 1031 oneproc(p, &kp[i]); 1032 argproc(p, &kp[i], kt); 1033 } 1034 kvm_close(kt); 1035 } 1036 #elif defined (__APPLE__) 1037 1038 static int 1039 GetBSDProcessList(pid_t thepid, struct kinfo_proc **procList, size_t *procCount) 1040 /* derived from http://developer.apple.com/qa/qa2001/qa1123.html */ 1041 /* Returns a list of all BSD processes on the system. This routine 1042 allocates the list and puts it in *procList and a count of the 1043 number of entries in *procCount. You are responsible for freeing 1044 this list (use "free" from System framework). 1045 all classic apps run in one process 1046 On success, the function returns 0. 1047 On error, the function returns a BSD errno value. 1048 Preconditions: 1049 assert( procList != NULL); 1050 assert(*procList == NULL); 1051 assert(procCount != NULL); 1052 Postconditions: 1053 assert( (err == 0) == (*procList != NULL) ); 1054 */ 1055 { 1056 int err; 1057 struct kinfo_proc *result; 1058 int mib[4]; 1059 size_t length; 1060 1061 mib[0] = CTL_KERN; 1062 mib[1] = KERN_PROC; 1063 if (thepid == 0) { 1064 mib[2] = KERN_PROC_ALL; 1065 mib[3] = 0; 1066 } else { 1067 mib[2] = KERN_PROC_PID; 1068 mib[3] = thepid; 1069 } 1070 /* We start by calling sysctl with result == NULL and length == 0. 1071 That will succeed, and set length to the appropriate length. 1072 We then allocate a buffer of that size and call sysctl again 1073 with that buffer. 1074 */ 1075 length = 0; 1076 err = sysctl(mib, 4, NULL, &length, NULL, 0); 1077 if (err == -1) 1078 err = errno; 1079 if (err == 0) { 1080 result = smalloc(length); 1081 err = sysctl(mib, 4, result, &length, NULL, 0); 1082 if (err == -1) 1083 err = errno; 1084 if (err == ENOMEM) { 1085 free(result); /* clean up */ 1086 result = NULL; 1087 } 1088 } 1089 *procList = result; 1090 *procCount = err == 0 ? length / sizeof **procList : 0; 1091 return err; 1092 } 1093 1094 extern kern_return_t task_for_pid(task_port_t task, pid_t pid, task_port_t *target); 1095 1096 static void 1097 oneproc(struct proc *p, struct kinfo_proc *kp) 1098 { 1099 task_port_t task; 1100 kern_return_t error; 1101 struct task_basic_info task_binfo; 1102 unsigned int info_count = TASK_BASIC_INFO_COUNT; 1103 1104 p->p_pid = kp->kp_proc.p_pid; 1105 strncpy(p->p_fname, kp->kp_proc.p_comm, sizeof p->p_fname); 1106 p->p_fname[sizeof p->p_fname - 1] = '\0'; 1107 p->p_ppid = kp->kp_eproc.e_ppid; 1108 p->p_pgid = kp->kp_eproc.e_pgid; 1109 p->p_sid = kp->kp_eproc.e_tpgid; 1110 p->p_ttydev = kp->kp_eproc.e_tdev == -1 ? PRNODEV : kp->kp_eproc.e_tdev;; 1111 p->p_uid = kp->kp_eproc.e_pcred.p_ruid; 1112 p->p_euid = kp->kp_eproc.e_ucred.cr_uid; 1113 p->p_gid = kp->kp_eproc.e_pcred.p_rgid; 1114 p->p_egid = kp->kp_eproc.e_ucred.cr_gid; 1115 p->p_start = kp->kp_proc.p_starttime.tv_sec + 1116 (kp->kp_proc.p_starttime.tv_usec >= 500000); 1117 1118 error = task_for_pid(mach_task_self(), p->p_pid, &task); 1119 if (error != KERN_SUCCESS) { 1120 return; /* no process, nothing to show/kill */ 1121 } 1122 1123 info_count = TASK_BASIC_INFO_COUNT; 1124 error = task_info(task, TASK_BASIC_INFO, &task_binfo, &info_count); 1125 if (error != KERN_SUCCESS) { 1126 fprintf(stderr, "Error calling task_info():%d\n", error); 1127 exit(3); 1128 } 1129 1130 p->p_size = task_binfo.virtual_size / 1024; /* in kilobytes */ 1131 } 1132 1133 static void 1134 argproc(struct proc *p, struct kinfo_proc *kp) 1135 { 1136 size_t size, argsz; 1137 char *argbuf; 1138 int mib[3]; 1139 long nargs; 1140 char *ap, *pp; 1141 1142 /* allocate a procargs space per process */ 1143 mib[0] = CTL_KERN; 1144 mib[1] = KERN_ARGMAX; 1145 size = sizeof argsz; 1146 if (sysctl(mib, 2, &argsz, &size, NULL, 0) == -1) { 1147 fprintf(stderr, "error in sysctl(): %s\n", strerror(errno)); 1148 exit(3); 1149 } 1150 argbuf = (char *)smalloc(argsz); 1151 1152 /* fetch the process arguments */ 1153 mib[0] = CTL_KERN; 1154 mib[1] = KERN_PROCARGS2; 1155 mib[2] = kp->kp_proc.p_pid; 1156 if (sysctl(mib, 3, argbuf, &argsz, NULL, 0) == -1) 1157 goto DONE; /* process has no args or already left the system */ 1158 1159 /* the number of args is at offset 0, this works for 32 and 64bit */ 1160 memcpy(&nargs, argbuf, sizeof nargs); 1161 ap = argbuf + sizeof nargs; 1162 1163 /* skip the exec_path */ 1164 while (ap < &argbuf[argsz] && *ap != '\0') 1165 ap++; 1166 if (ap == &argbuf[argsz]) 1167 goto DONE; /* no args to show */ 1168 /* skip trailing '\0' chars */ 1169 while (ap < &argbuf[argsz] && *ap == '\0') 1170 ap++; 1171 if (ap == &argbuf[argsz]) 1172 goto DONE; /* no args to show */ 1173 1174 /* now concat copy the arguments */ 1175 for (pp = p->p_psargs; pp < &p->p_psargs[sizeof p->p_psargs-1]; pp++) { 1176 if (*ap == '\0') { 1177 if (--nargs == 0) 1178 break; 1179 *pp = ' '; 1180 ++ap; 1181 } else 1182 *pp = *ap++; 1183 } 1184 *pp = '\0'; 1185 1186 DONE: free(argbuf); 1187 return; 1188 } 1189 1190 static void 1191 collectprocs(void) 1192 { 1193 int mib[2]; 1194 struct proc *p, *pq = NULL; 1195 struct kinfo_proc *kp = NULL; 1196 size_t i, cnt; 1197 int err; 1198 1199 if ((err = GetBSDProcessList(0, &kp, &cnt)) != 0) { 1200 fprintf(stderr, "error getting proc list: %s\n", strerror(err)); 1201 exit(3); 1202 } 1203 for (i = 0; i < cnt; i++) { 1204 p = smalloc(sizeof *p); 1205 if (pq) 1206 pq->p_nxt = p; 1207 else 1208 processes = p; 1209 pq = p; 1210 oneproc(p, &kp[i]); 1211 argproc(p, &kp[i]); 1212 } 1213 /* free the memory allocated by GetBSDProcessList */ 1214 free(kp); 1215 } 1216 #endif /* all */ 1217 1218 static enum okay 1219 hasattr(struct proc *p, struct attrib *a) 1220 { 1221 long val = 0; 1222 1223 switch (a->a_type) { 1224 case ATT_ALL: 1225 return OKAY; 1226 case ATT_PPID: 1227 val = p->p_ppid; 1228 break; 1229 case ATT_PGRP: 1230 val = p->p_pgid; 1231 break; 1232 case ATT_SID: 1233 val = p->p_sid; 1234 break; 1235 case ATT_EUID: 1236 val = p->p_euid; 1237 break; 1238 case ATT_UID: 1239 val = p->p_uid; 1240 break; 1241 case ATT_GID: 1242 val = p->p_gid; 1243 break; 1244 case ATT_TTY: 1245 /* 1246 * Never matches processes without controlling tty. 1247 */ 1248 if (p->p_ttydev == PRNODEV) 1249 return STOP; 1250 val = p->p_ttydev; 1251 break; 1252 } 1253 return val == a->a_val ? OKAY : STOP; 1254 } 1255 1256 static void 1257 tryproc(struct proc *p) 1258 { 1259 struct attlist *alp; 1260 struct attrib *ap; 1261 const char *line; 1262 regmatch_t where; 1263 1264 for (alp = attributes; alp; alp = alp->al_nxt) { 1265 for (ap = alp->al_att; ap; ap = ap->a_nxt) 1266 if (hasattr(p, ap) == OKAY) 1267 break; 1268 if (ap == NULL) 1269 return; 1270 } 1271 if (expression) { 1272 line = fflag ? p->p_psargs : p->p_fname; 1273 if (regexec(expression, line, 1, &where, 0) != 0) 1274 return; 1275 if (xflag && (where.rm_so != 0 || where.rm_eo == -1 || 1276 line[where.rm_eo] != '\0')) 1277 return; 1278 } 1279 p->p_match = 1; 1280 } 1281 1282 static void 1283 selectprocs(void) 1284 { 1285 struct proc *p; 1286 1287 for (p = processes; p; p = p->p_nxt) 1288 tryproc(p); 1289 } 1290 1291 static void 1292 outproc(struct proc *p) 1293 { 1294 if (pkill) { 1295 if (kill(p->p_pid, signo) < 0) 1296 fprintf(stderr, 1297 "%s: Failed to signal pid %ld: %s\n", 1298 progname, (long)p->p_pid, strerror(errno)); 1299 } else { 1300 if (delimiter && prdelim++) 1301 printf("%s", delimiter); 1302 if (lflag) 1303 printf("%5ld %s", (long)p->p_pid, 1304 fflag ? p->p_psargs : p->p_fname); 1305 else 1306 printf("%ld", (long)p->p_pid); 1307 if (delimiter == NULL) 1308 printf("\n"); 1309 } 1310 } 1311 1312 static void 1313 handleprocs(void) 1314 { 1315 struct proc *p, *selected = NULL; 1316 1317 for (p = processes; p; p = p->p_nxt) { 1318 if (p->p_pid != mypid && p->p_match ^ vflag) { 1319 matched = 1; 1320 if (nflag) { 1321 if (selected == NULL || 1322 p->p_start >= selected->p_start) 1323 selected = p; 1324 } else if (oflag) { 1325 if (selected == NULL || 1326 p->p_start < selected->p_start) 1327 selected = p; 1328 } else 1329 outproc(p); 1330 } 1331 } 1332 if ((nflag || oflag) && selected) 1333 outproc(selected); 1334 if (prdelim && delimiter) 1335 printf("\n"); 1336 } 1337 1338 static long 1339 getrdev(const char *device) 1340 { 1341 struct stat st; 1342 long id = 0; 1343 char *file; 1344 1345 file = alloca(strlen(device) + 9); 1346 strcpy(file, "/dev/"); 1347 strcpy(&file[5], device); 1348 if (stat(file, &st) < 0) { 1349 strcpy(file, "/dev/tty/"); 1350 strcpy(&file[8], device); 1351 if (stat(file, &st) == 0) 1352 id = st.st_rdev; 1353 else { 1354 fprintf(stderr, "%s: unknown terminal name -- %s\n", 1355 progname, device); 1356 exit(2); 1357 } 1358 } else 1359 id = st.st_rdev; 1360 return id; 1361 } 1362 1363 static struct attrib * 1364 makatt(enum attype at, const char *string, int optc, struct attrib *aq) 1365 { 1366 struct attrib *ap; 1367 struct passwd *pwd; 1368 struct group *grp; 1369 char *x; 1370 long val = 0; 1371 1372 if (*string == '\0') 1373 at = ATT_ALL; 1374 else switch (at) { 1375 case ATT_PPID: 1376 case ATT_PGRP: 1377 case ATT_SID: 1378 val = strtol(string, &x, 10); 1379 if (*x != '\0' || *string == '+' || *string == '-') { 1380 fprintf(stderr, 1381 "%s: invalid argument for option '%c' -- %s\n", 1382 progname, optc, string); 1383 exit(2); 1384 } 1385 if (val == 0) switch (at) { 1386 case ATT_PGRP: 1387 val = getpgid(0); 1388 break; 1389 case ATT_SID: 1390 val = getsid(0); 1391 break; 1392 } 1393 break; 1394 case ATT_EUID: 1395 need_euid_egid = 1; 1396 /*FALLTHRU*/ 1397 case ATT_UID: 1398 if ((pwd = getpwnam(string)) != NULL) 1399 val = pwd->pw_uid; 1400 else { 1401 val = strtol(string, &x, 10); 1402 if (*x != '\0' || *string == '+' || *string == '-') { 1403 fprintf(stderr, 1404 "%s: invalid user name -- %s\n", 1405 progname, string); 1406 exit(2); 1407 } 1408 } 1409 break; 1410 case ATT_GID: 1411 if ((grp = getgrnam(string)) != NULL) 1412 val = grp->gr_gid; 1413 else { 1414 val = strtol(string, &x, 10); 1415 if (*x != '\0' || *string == '+' || *string == '-') { 1416 fprintf(stderr, 1417 "%s: invalid group name -- %s\n", 1418 progname, string); 1419 exit(2); 1420 } 1421 } 1422 break; 1423 case ATT_TTY: 1424 val = getrdev(string); 1425 break; 1426 } 1427 ap = scalloc(1, sizeof *ap); 1428 ap->a_type = at; 1429 ap->a_val = val; 1430 ap->a_nxt = aq; 1431 return ap; 1432 } 1433 1434 static void 1435 addattribs(enum attype at, const char *list, int optc) 1436 { 1437 struct attlist *al = NULL; 1438 const char *cp; 1439 1440 for (al = attributes; al; al = al->al_nxt) 1441 if (al->al_att && al->al_att->a_type == at) 1442 break; 1443 if (al == NULL) { 1444 al = scalloc(1, sizeof *al); 1445 al->al_nxt = attributes; 1446 attributes = al; 1447 } 1448 while (*list == ',' || isblank(*list&0377)) 1449 list++; 1450 if (*list) 1451 while ((cp = element(&list, '\0')) != NULL) 1452 al->al_att = makatt(at, cp, optc, al->al_att); 1453 else 1454 al->al_att = makatt(at, "", optc, al->al_att); 1455 } 1456 1457 static enum okay 1458 getsig(const char *str) 1459 { 1460 char *x; 1461 int val; 1462 1463 if ((val = strtol(str, &x, 10)) >= 0 && *x == '\0' && 1464 *str != '-' && *str != '+') { 1465 signo = val; 1466 return OKAY; 1467 } 1468 if (str_2_sig(str, &val) == OKAY) { 1469 signo = val; 1470 return OKAY; 1471 } 1472 return STOP; 1473 } 1474 1475 static void 1476 usage(void) 1477 { 1478 if (pkill) 1479 fprintf(stderr, "\ 1480 Usage: %s [-signal] [-fnovx] [-P ppidlist] [-g pgrplist] [-s sidlist]\n\ 1481 \t[-u euidlist] [-U uidlist] [-G gidlist] [-t termlist] [pattern]\n", 1482 progname); 1483 else 1484 fprintf(stderr, "\ 1485 Usage: %s [-flnovx] [-d delim] [-P ppidlist] [-g pgrplist] [-s sidlist]\n\ 1486 \t[-u euidlist] [-U uidlist] [-G gidlist] [-t termlist] [pattern]\n", 1487 progname); 1488 exit(2); 1489 } 1490 1491 int 1492 main(int argc, char **argv) 1493 { 1494 int i, flags; 1495 1496 progname = basename(argv[0]); 1497 if (strncmp(progname, "pkill", 5) == 0) 1498 pkill = 1; 1499 setlocale(LC_COLLATE, ""); 1500 setlocale(LC_CTYPE, ""); 1501 if (pkill && argc > 1 && argv[1][0] == '-' && 1502 getsig(&argv[1][1]) == OKAY) 1503 optind = 2; 1504 while ((i = getopt(argc, argv, pkill ? "fnovxP:g:s:u:U:G:t:" : 1505 "flnovxd:P:g:s:u:U:G:t:")) != EOF) { 1506 switch (i) { 1507 case 'f': 1508 fflag = 1; 1509 break; 1510 case 'l': 1511 lflag = 1; 1512 break; 1513 case 'n': 1514 nflag = 1; 1515 break; 1516 case 'o': 1517 oflag = 1; 1518 break; 1519 case 'v': 1520 vflag = 1; 1521 break; 1522 case 'x': 1523 xflag = 1; 1524 break; 1525 case 'd': 1526 delimiter = optarg; 1527 break; 1528 case 'P': 1529 addattribs(ATT_PPID, optarg, i); 1530 break; 1531 case 'g': 1532 addattribs(ATT_PGRP, optarg, i); 1533 break; 1534 case 's': 1535 addattribs(ATT_SID, optarg, i); 1536 break; 1537 case 'u': 1538 addattribs(ATT_EUID, optarg, i); 1539 break; 1540 case 'U': 1541 addattribs(ATT_UID, optarg, i); 1542 break; 1543 case 'G': 1544 addattribs(ATT_GID, optarg, i); 1545 break; 1546 case 't': 1547 addattribs(ATT_TTY, optarg, i); 1548 break; 1549 default: 1550 usage(); 1551 } 1552 } 1553 if (nflag && oflag) { 1554 fprintf(stderr, "%s: -n and -o are mutually exclusive\n", 1555 progname); 1556 usage(); 1557 } 1558 if (argv[optind]) { 1559 if (argv[optind+1]) { 1560 fprintf(stderr, "%s: illegal argument -- %s\n", 1561 progname, argv[optind + 1]); 1562 usage(); 1563 } 1564 flags = REG_EXTENDED; 1565 #ifdef REG_MTPARENBAD 1566 flags |= REG_MTPARENBAD; 1567 #endif 1568 if (!xflag) 1569 flags |= REG_NOSUB; 1570 #ifdef REG_ONESUB 1571 else 1572 flags |= REG_ONESUB; 1573 #endif 1574 expression = scalloc(1, sizeof *expression); 1575 if ((i = regcomp(expression, argv[optind], flags)) != 0) { 1576 char *errst; 1577 size_t errsz; 1578 1579 errsz = regerror(i, expression, NULL, 0) + 1; 1580 errst = smalloc(errsz); 1581 regerror(i, expression, errst, errsz); 1582 fprintf(stderr, "%s: %s\n", progname, errst); 1583 exit(2); 1584 } 1585 } else if (attributes == NULL) { 1586 fprintf(stderr, "%s: No matching criteria specified\n", 1587 progname); 1588 usage(); 1589 } 1590 mypid = getpid(); 1591 #if !defined (__hpux) && !defined (_AIX) && !defined (__NetBSD__) && \ 1592 !defined (__OpenBSD__) && !defined (__APPLE__) 1593 chdir_to_proc(); 1594 #endif /* !__hpux, !_AIX, !__NetBSD__, !__OpenBSD__, !__APPLE__ */ 1595 collectprocs(); 1596 selectprocs(); 1597 handleprocs(); 1598 return errcnt ? errcnt : matched == 0; 1599 } 1600 1601 struct sig_strlist 1602 { 1603 const int sig_num; 1604 const char *sig_str; 1605 }; 1606 1607 static const struct sig_strlist sig_strs[] = { 1608 { 0, "EXIT" }, 1609 { SIGHUP, "HUP" }, 1610 { SIGINT, "INT" }, 1611 { SIGQUIT, "QUIT" }, 1612 { SIGILL, "ILL" }, 1613 { SIGTRAP, "TRAP" }, 1614 { SIGABRT, "ABRT" }, 1615 #ifdef SIGIOT 1616 { SIGIOT, "IOT" }, 1617 #endif 1618 #ifdef SIGEMT 1619 { SIGEMT, "EMT" }, 1620 #endif 1621 #ifdef SIGFPE 1622 { SIGFPE, "FPE" }, 1623 #endif 1624 #ifdef SIGKILL 1625 { SIGKILL, "KILL" }, 1626 #endif 1627 #ifdef SIGBUS 1628 { SIGBUS, "BUS" }, 1629 #endif 1630 #ifdef SIGSEGV 1631 { SIGSEGV, "SEGV" }, 1632 #endif 1633 #ifdef SIGSYS 1634 { SIGSYS, "SYS" }, 1635 #endif 1636 #ifdef SIGPIPE 1637 { SIGPIPE, "PIPE" }, 1638 #endif 1639 #ifdef SIGALRM 1640 { SIGALRM, "ALRM" }, 1641 #endif 1642 #ifdef SIGTERM 1643 { SIGTERM, "TERM" }, 1644 #endif 1645 #ifdef SIGUSR1 1646 { SIGUSR1, "USR1" }, 1647 #endif 1648 #ifdef SIGUSR2 1649 { SIGUSR2, "USR2" }, 1650 #endif 1651 #ifdef SIGCLD 1652 { SIGCLD, "CLD" }, 1653 #endif 1654 #ifdef SIGCHLD 1655 { SIGCHLD, "CHLD" }, 1656 #endif 1657 #ifdef SIGPWR 1658 { SIGPWR, "PWR" }, 1659 #endif 1660 #ifdef SIGWINCH 1661 { SIGWINCH, "WINCH" }, 1662 #endif 1663 #ifdef SIGURG 1664 { SIGURG, "URG" }, 1665 #endif 1666 #ifdef SIGPOLL 1667 { SIGPOLL, "POLL" }, 1668 #endif 1669 #ifdef SIGIO 1670 { SIGIO, "IO" }, 1671 #endif 1672 #ifdef SIGSTOP 1673 { SIGSTOP, "STOP" }, 1674 #endif 1675 #ifdef SIGTSTP 1676 { SIGTSTP, "TSTP" }, 1677 #endif 1678 #ifdef SIGCONT 1679 { SIGCONT, "CONT" }, 1680 #endif 1681 #ifdef SIGTTIN 1682 { SIGTTIN, "TTIN" }, 1683 #endif 1684 #ifdef SIGTTOU 1685 { SIGTTOU, "TTOU" }, 1686 #endif 1687 #ifdef SIGVTALRM 1688 { SIGVTALRM, "VTALRM" }, 1689 #endif 1690 #ifdef SIGPROF 1691 { SIGPROF, "PROF" }, 1692 #endif 1693 #ifdef SIGXCPU 1694 { SIGXCPU, "XCPU" }, 1695 #endif 1696 #ifdef SIGXFSZ 1697 { SIGXFSZ, "XFSZ" }, 1698 #endif 1699 #ifdef SIGWAITING 1700 { SIGWAITING, "WAITING" }, 1701 #endif 1702 #ifdef SIGLWP 1703 { SIGLWP, "LWP" }, 1704 #endif 1705 #ifdef SIGFREEZE 1706 { SIGFREEZE, "FREEZE" }, 1707 #endif 1708 #ifdef SIGTHAW 1709 { SIGTHAW, "THAW" }, 1710 #endif 1711 #ifdef SIGCANCEL 1712 { SIGCANCEL, "CANCEL" }, 1713 #endif 1714 #ifdef SIGLOST 1715 { SIGLOST, "LOST" }, 1716 #endif 1717 #ifdef SIGSTKFLT 1718 { SIGSTKFLT, "STKFLT" }, 1719 #endif 1720 #ifdef SIGINFO 1721 { SIGINFO, "INFO" }, 1722 #endif 1723 #ifdef SIG_2_STR_WITH_RT_SIGNALS 1724 { SIGRTMIN, "RTMIN" }, 1725 { SIGRTMIN+1, "RTMIN+1" }, 1726 { SIGRTMIN+2, "RTMIN+2" }, 1727 { SIGRTMIN+3, "RTMIN+3" }, 1728 { SIGRTMAX-3, "RTMAX-3" }, 1729 { SIGRTMAX-2, "RTMAX-2" }, 1730 { SIGRTMAX-1, "RTMAX-1" }, 1731 { SIGRTMAX, "RTMAX" }, 1732 #endif /* SIG_2_STR_WITH_RT_SIGNALS */ 1733 { -1, NULL } 1734 }; 1735 1736 static int 1737 str_2_sig(const char *str, int *signum) 1738 { 1739 int i; 1740 1741 for (i = 0; sig_strs[i].sig_str; i++) 1742 if (eq(str, sig_strs[i].sig_str)) 1743 break; 1744 if (sig_strs[i].sig_str == NULL) 1745 return STOP; 1746 *signum = sig_strs[i].sig_num; 1747 return OKAY; 1748 }