1/* 2 * main.c - common main function for lsof 3 * 4 * V. Abell, Purdue University 5 */ 6 7 8/* 9 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana 10 * 47907. All rights reserved. 11 * 12 * Written by Victor A. Abell 13 * 14 * This software is not subject to any license of the American Telephone 15 * and Telegraph Company or the Regents of the University of California. 16 * 17 * Permission is granted to anyone to use this software for any purpose on 18 * any computer system, and to alter it and redistribute it freely, subject 19 * to the following restrictions: 20 * 21 * 1. Neither the authors nor Purdue University are responsible for any 22 * consequences of the use of this software. 23 * 24 * 2. The origin of this software must not be misrepresented, either by 25 * explicit claim or by omission. Credit to the authors and Purdue 26 * University must appear in documentation and sources. 27 * 28 * 3. Altered versions must be plainly marked as such, and must not be 29 * misrepresented as being the original software. 30 * 31 * 4. This notice may not be removed or altered. 32 */ 33 34#ifndef lint 35static char copyright[] = 36"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; 37static char *rcsid = "$Id: main.c,v 1.55 2011/09/07 19:13:49 abe Exp $"; 38#endif 39 40 41#include "lsof.h" 42 43 44/* 45 * Local definitions 46 */ 47 48static int GObk[] = { 1, 1 }; /* option backspace values */ 49static char GOp; /* option prefix -- '+' or '-' */ 50static char *GOv = (char *)NULL; /* option `:' value pointer */ 51static int GOx1 = 1; /* first opt[][] index */ 52static int GOx2 = 0; /* second opt[][] index */ 53 54 55_PROTOTYPE(static int GetOpt,(int ct, char *opt[], char *rules, int *err)); 56_PROTOTYPE(static char *sv_fmt_str,(char *f)); 57 58 59/* 60 * main() - main function for lsof 61 */ 62 63int 64main(argc, argv) 65 int argc; 66 char *argv[]; 67{ 68 int ad, c, i, n, rv, se1, se2, ss; 69 char *cp; 70 int err = 0; 71 int ev = 0; 72 int fh = 0; 73 char *fmtr = (char *)NULL; 74 long l; 75 MALLOC_S len; 76 struct lfile *lf; 77 struct nwad *np, *npn; 78 char options[128]; 79 int rc = 0; 80 struct stat sb; 81 struct sfile *sfp; 82 struct lproc **slp = (struct lproc **)NULL; 83 int sp = 0; 84 struct str_lst *str, *strt; 85 int version = 0; 86 int xover = 0; 87 88#if defined(HAS_STRFTIME) 89 char *fmt = (char *)NULL; 90 size_t fmtl; 91#endif /* defined(HAS_STRFTIME) */ 92 93#if defined(HASZONES) 94 znhash_t *zp; 95#endif /* defined(HASZONES) */ 96 97#if defined(HASSELINUX) 98/* 99 * This stanza must be immediately before the "Save progam name." code, since 100 * it contains code itself. 101 */ 102 cntxlist_t *cntxp; 103 104 CntxStatus = is_selinux_enabled() ? 1 : 0; 105#endif /* defined(HASSELINUX) */ 106 107/* 108 * Save program name. 109 */ 110 if ((Pn = strrchr(argv[0], '/'))) 111 Pn++; 112 else 113 Pn = argv[0]; 114/* 115 * Close all file descriptors above 2. 116 * 117 * Make sure stderr, stdout, and stdin are open descriptors. Open /dev/null 118 * for ones that aren't. Be terse. 119 * 120 * Make sure umask allows lsof to define its own file permissions. 121 */ 122 for (i = 3, n = GET_MAX_FD(); i < n; i++) 123 (void) close(i); 124 while (((i = open("/dev/null", O_RDWR, 0)) >= 0) && (i < 2)) 125 ; 126 if (i < 0) 127 Exit(1); 128 if (i > 2) 129 (void) close(i); 130 (void) umask(0); 131 132#if defined(HASSETLOCALE) 133/* 134 * Set locale to environment's definition. 135 */ 136 (void) setlocale(LC_CTYPE, ""); 137#endif /* defined(HASSETLOCALE) */ 138 139/* 140 * Common initialization. 141 */ 142 Mypid = getpid(); 143 if ((Mygid = (gid_t)getgid()) != getegid()) 144 Setgid = 1; 145 Euid = geteuid(); 146 if ((Myuid = (uid_t)getuid()) && !Euid) 147 Setuidroot = 1; 148 if (!(Namech = (char *)malloc(MAXPATHLEN + 1))) { 149 (void) fprintf(stderr, "%s: no space for name buffer\n", Pn); 150 Exit(1); 151 } 152 Namechl = (size_t)(MAXPATHLEN + 1); 153/* 154 * Create option mask. 155 */ 156 (void) snpf(options, sizeof(options), 157 "?a%sbc:%sD:d:%sf:F:g:hi:%s%slL:%s%snNo:Op:Pr:%ss:S:tT:u:UvVwx:%s%s%s", 158 159#if defined(HAS_AFS) && defined(HASAOPT) 160 "A:", 161#else /* !defined(HAS_AFS) || !defined(HASAOPT) */ 162 "", 163#endif /* defined(HAS_AFS) && defined(HASAOPT) */ 164 165#if defined(HASNCACHE) 166 "C", 167#else /* !defined(HASNCACHE) */ 168 "", 169#endif /* defined(HASNCACHE) */ 170 171#if defined(HASEOPT) 172 "e:", 173#else /* !defined(HASEOPT) */ 174 "", 175#endif /* defined(HASEOPT) */ 176 177#if defined(HASKOPT) 178 "k:", 179#else /* !defined(HASKOPT) */ 180 "", 181#endif /* defined(HASKOPT) */ 182 183#if defined(HASTASKS) 184 "K", 185#else /* !defined(HASTASKS) */ 186 "", 187#endif /* defined(HASTASKS) */ 188 189#if defined(HASMOPT) || defined(HASMNTSUP) 190 "m:", 191#else /* !defined(HASMOPT) && !defined(HASMNTSUP) */ 192 "", 193#endif /* defined(HASMOPT) || defined(HASMNTSUP) */ 194 195#if defined(HASNORPC_H) 196 "", 197#else /* !defined(HASNORPC_H) */ 198 "M", 199#endif /* defined(HASNORPC_H) */ 200 201#if defined(HASPPID) 202 "R", 203#else /* !defined(HASPPID) */ 204 "", 205#endif /* defined(HASPPID) */ 206 207#if defined(HASXOPT) 208# if defined(HASXOPT_ROOT) 209 (Myuid == 0) ? "X" : "", 210# else /* !defined(HASXOPT_ROOT) */ 211 "X", 212# endif /* defined(HASXOPT_ROOT) */ 213#else /* !defined(HASXOPT) */ 214 "", 215#endif /* defined(HASXOPT) */ 216 217#if defined(HASZONES) 218 "z:", 219#else /* !defined(HASZONES) */ 220 "", 221#endif /* defined(HASZONES) */ 222 223#if defined(HASSELINUX) 224 "Z:" 225#else /* !defined(HASSELINUX) */ 226 "" 227#endif /* defined(HASSELINUX) */ 228 229 ); 230/* 231 * Loop through options. 232 */ 233 while ((c = GetOpt(argc, argv, options, &rv)) != EOF) { 234 if (rv) { 235 err = 1; 236 continue; 237 } 238 switch (c) { 239 case 'a': 240 Fand = 1; 241 break; 242 243#if defined(HAS_AFS) && defined(HASAOPT) 244 case 'A': 245 if (!GOv || *GOv == '-' || *GOv == '+') { 246 (void) fprintf(stderr, "%s: -A not followed by path\n", Pn); 247 err = 1; 248 if (GOv) { 249 GOx1 = GObk[0]; 250 GOx2 = GObk[1]; 251 } 252 } else 253 AFSApath = GOv; 254 break; 255#endif /* defined(HAS_AFS) && defined(HASAOPT) */ 256 257 case 'b': 258 Fblock = 1; 259 break; 260 case 'c': 261 if (GOp == '+') { 262 if (!GOv || (*GOv == '-') || (*GOv == '+') 263 || !isdigit((int)*GOv)) 264 { 265 (void) fprintf(stderr, 266 "%s: +c not followed by width number\n", Pn); 267 err = 1; 268 if (GOv) { 269 GOx1 = GObk[0]; 270 GOx2 = GObk[1]; 271 } 272 } else { 273 CmdLim = atoi(GOv); 274 275#if defined(MAXSYSCMDL) 276 if (CmdLim > MAXSYSCMDL) { 277 (void) fprintf(stderr, 278 "%s: +c %d > what system provides (%d)\n", 279 Pn, CmdLim, MAXSYSCMDL); 280 err = 1; 281 } 282#endif /* defined(MAXSYSCMDL) */ 283 284 } 285 break; 286 } 287 if (GOv && (*GOv == '/')) { 288 if (enter_cmd_rx(GOv)) 289 err = 1; 290 } else { 291 if (enter_str_lst("-c", GOv, &Cmdl, &Cmdni, &Cmdnx)) 292 err = 1; 293 294#if defined(MAXSYSCMDL) 295 else if (Cmdl->len > MAXSYSCMDL) { 296 (void) fprintf(stderr, "%s: \"-c ", Pn); 297 (void) safestrprt(Cmdl->str, stderr, 2); 298 (void) fprintf(stderr, "\" length (%d) > what system", 299 Cmdl->len); 300 (void) fprintf(stderr, " provides (%d)\n", 301 MAXSYSCMDL); 302 Cmdl->len = 0; /* (to avoid later error report) */ 303 err = 1; 304 } 305#endif /* defined(MAXSYSCMDL) */ 306 307 } 308 break; 309 310#if defined(HASNCACHE) 311 case 'C': 312 Fncache = (GOp == '-') ? 0 : 1; 313 break; 314#endif /* defined(HASNCACHE) */ 315 316#if defined(HASEOPT) 317 case 'e': 318 if (enter_efsys(GOv, ((GOp == '+') ? 1 : 0))) 319 err = 1; 320 break; 321#endif /* defined(HASEOPT) */ 322 323 case 'd': 324 if (GOp == '+') { 325 if (enter_dir(GOv, 0)) 326 err = 1; 327 else { 328 Selflags |= SELNM; 329 xover = 1; 330 } 331 } else { 332 if (enter_fd(GOv)) 333 err = 1; 334 } 335 break; 336 case 'D': 337 if (GOp == '+') { 338 if (enter_dir(GOv, 1)) 339 err = 1; 340 else { 341 Selflags |= SELNM; 342 xover = 1; 343 } 344 } else { 345 346#if defined(HASDCACHE) 347 if (ctrl_dcache(GOv)) 348 err = 1; 349#else /* !defined(HASDCACHE) */ 350 (void) fprintf(stderr, "%s: unsupported option: -D\n", Pn); 351 err = 1; 352#endif /* defined(HASDCACHE) */ 353 354 } 355 break; 356 case 'f': 357 if (!GOv || *GOv == '-' || *GOv == '+') { 358 Ffilesys = (GOp == '+') ? 2 : 1; 359 if (GOv) { 360 GOx1 = GObk[0]; 361 GOx2 = GObk[1]; 362 } 363 break; 364 } 365 366#if defined(HASFSTRUCT) 367 for (; *GOv; GOv++) { 368 switch (*GOv) { 369 370# if !defined(HASNOFSCOUNT) 371 case 'c': 372 case 'C': 373 if (GOp == '+') { 374 Fsv |= FSV_CT; 375 FsvByf = 1; 376 } else 377 Fsv &= (unsigned char)~FSV_CT; 378 break; 379# endif /* !defined(HASNOFSCOUNT) */ 380 381# if !defined(HASNOFSADDR) 382 case 'f': 383 case 'F': 384 if (GOp == '+') { 385 Fsv |= FSV_FA; 386 FsvByf = 1; 387 } else 388 Fsv &= (unsigned char)~FSV_FA; 389 break; 390# endif /* !defined(HASNOFSADDR) */ 391 392# if !defined(HASNOFSFLAGS) 393 case 'g': 394 case 'G': 395 if (GOp == '+') { 396 Fsv |= FSV_FG; 397 FsvByf = 1; 398 } else 399 Fsv &= (unsigned char)~FSV_FG; 400 FsvFlagX = (*GOv == 'G') ? 1 : 0; 401 break; 402# endif /* !defined(HASNOFSFLAGS) */ 403 404# if !defined(HASNOFSNADDR) 405 case 'n': 406 case 'N': 407 if (GOp == '+') { 408 Fsv |= FSV_NI; 409 FsvByf = 1; 410 } else 411 Fsv &= (unsigned char)~FSV_NI; 412 break; 413# endif /* !defined(HASNOFSNADDR */ 414 415 default: 416 (void) fprintf(stderr, 417 "%s: unknown file struct option: %c\n", Pn, *GOv); 418 err++; 419 } 420 } 421#else /* !defined(HASFSTRUCT) */ 422 (void) fprintf(stderr, 423 "%s: unknown string for %cf: %s\n", Pn, GOp, GOv); 424 err++; 425#endif /* defined(HASFSTRUCT) */ 426 427 break; 428 case 'F': 429 if (!GOv || *GOv == '-' || *GOv == '+' 430 || strcmp(GOv, "0") == 0) { 431 if (GOv) { 432 if (*GOv == '-' || *GOv == '+') { 433 GOx1 = GObk[0]; 434 GOx2 = GObk[1]; 435 } else if (*GOv == '0') 436 Terminator = '\0'; 437 } 438 for (i = 0; FieldSel[i].nm; i++) { 439 440#if !defined(HASPPID) 441 if (FieldSel[i].id == LSOF_FID_PPID) 442 continue; 443#endif /* !defined(HASPPID) */ 444 445#if !defined(HASFSTRUCT) 446 if (FieldSel[i].id == LSOF_FID_CT 447 || FieldSel[i].id == LSOF_FID_FA 448 || FieldSel[i].id == LSOF_FID_FG 449 || FieldSel[i].id == LSOF_FID_NI) 450 continue; 451#endif /* !defined(HASFSTRUCT) */ 452 453#if defined(HASSELINUX) 454 if ((FieldSel[i].id == LSOF_FID_CNTX) && !CntxStatus) 455 continue; 456#else /* !defined(HASSELINUX) */ 457 if (FieldSel[i].id == LSOF_FID_CNTX) 458 continue; 459#endif /* !defined(HASSELINUX) */ 460 461 if (FieldSel[i].id == LSOF_FID_RDEV) 462 continue; /* for compatibility */ 463 464#if !defined(HASTASKS) 465 if (FieldSel[i].id == LSOF_FID_TID) 466 continue; 467#endif /* !defined(HASTASKS) */ 468 469#if !defined(HASZONES) 470 if (FieldSel[i].id == LSOF_FID_ZONE) 471 continue; 472#endif /* !defined(HASZONES) */ 473 474 FieldSel[i].st = 1; 475 if (FieldSel[i].opt && FieldSel[i].ov) 476 *(FieldSel[i].opt) |= FieldSel[i].ov; 477 } 478 479#if defined(HASFSTRUCT) 480 Ffield = FsvFlagX = 1; 481#else /* !defined(HASFSTRUCT) */ 482 Ffield = 1; 483#endif /* defined(HASFSTRUCT) */ 484 485 break; 486 } 487 if (strcmp(GOv, "?") == 0) { 488 fh = 1; 489 break; 490 } 491 for (; *GOv; GOv++) { 492 for (i = 0; FieldSel[i].nm; i++) { 493 494#if !defined(HASPPID) 495 if (FieldSel[i].id == LSOF_FID_PPID) 496 continue; 497#endif /* !defined(HASPPID) */ 498 499#if !defined(HASFSTRUCT) 500 if (FieldSel[i].id == LSOF_FID_CT 501 || FieldSel[i].id == LSOF_FID_FA 502 || FieldSel[i].id == LSOF_FID_FG 503 || FieldSel[i].id == LSOF_FID_NI) 504 continue; 505#endif /* !defined(HASFSTRUCT) */ 506 507#if !defined(HASTASKS) 508 if (FieldSel[i].id == LSOF_FID_TID) 509 continue; 510#endif /* !defined(HASTASKS) */ 511 512 if (FieldSel[i].id == *GOv) { 513 FieldSel[i].st = 1; 514 if (FieldSel[i].opt && FieldSel[i].ov) 515 *(FieldSel[i].opt) |= FieldSel[i].ov; 516 517#if defined(HASFSTRUCT) 518 if (i == LSOF_FIX_FG) 519 FsvFlagX = 1; 520#endif /* defined(HASFSTRUCT) */ 521 522 if (i == LSOF_FIX_TERM) 523 Terminator = '\0'; 524 break; 525 } 526 } 527 if ( ! FieldSel[i].nm) { 528 (void) fprintf(stderr, 529 "%s: unknown field: %c\n", Pn, *GOv); 530 err++; 531 } 532 } 533 Ffield = 1; 534 break; 535 case 'g': 536 if (GOv) { 537 if (*GOv == '-' || *GOv == '+') { 538 GOx1 = GObk[0]; 539 GOx2 = GObk[1]; 540 } else if (enter_id(PGID, GOv)) 541 err = 1; 542 } 543 Fpgid = 1; 544 break; 545 case 'h': 546 case '?': 547 Fhelp = 1; 548 break; 549 case 'i': 550 if (!GOv || *GOv == '-' || *GOv == '+') { 551 Fnet = 1; 552 FnetTy = 0; 553 if (GOv) { 554 GOx1 = GObk[0]; 555 GOx2 = GObk[1]; 556 } 557 break; 558 } 559 if (enter_network_address(GOv)) 560 err = 1; 561 break; 562 563#if defined(HASKOPT) 564 case 'k': 565 if (!GOv || *GOv == '-' || *GOv == '+') { 566 (void) fprintf(stderr, "%s: -k not followed by path\n", Pn); 567 err = 1; 568 if (GOv) { 569 GOx1 = GObk[0]; 570 GOx2 = GObk[1]; 571 } 572 } else 573 Nmlst = GOv; 574 break; 575#endif /* defined(HASKOPT) */ 576 577#if defined(HASTASKS) 578 case 'K': 579 Ftask = 1; 580 Selflags |= SELTASK; 581 break; 582#endif /* defined(HASTASKS) */ 583 584 case 'l': 585 Futol = 0; 586 break; 587 case 'L': 588 Fnlink = (GOp == '+') ? 1 : 0; 589 if (!GOv || *GOv == '-' || *GOv == '+') { 590 Nlink = 0l; 591 if (GOv) { 592 GOx1 = GObk[0]; 593 GOx2 = GObk[1]; 594 } 595 break; 596 } 597 for (cp = GOv, l = 0l, n = 0; *cp; cp++) { 598 if (!isdigit((unsigned char)*cp)) 599 break; 600 l = (l * 10l) + ((long)*cp - (long)'0'); 601 n++; 602 } 603 if (n) { 604 if (GOp != '+') { 605 (void) fprintf(stderr, 606 "%s: no number may follow -L\n", Pn); 607 err = 1; 608 } else { 609 Nlink = l; 610 Selflags |= SELNLINK; 611 } 612 } else 613 Nlink = 0l; 614 if (*cp) { 615 GOx1 = GObk[0]; 616 GOx2 = GObk[1] + n; 617 } 618 break; 619 620#if defined(HASMOPT) || defined(HASMNTSUP) 621 case 'm': 622 if (GOp == '-') { 623 624# if defined(HASMOPT) 625 if (!GOv || *GOv == '-' || *GOv == '+') { 626 (void) fprintf(stderr, 627 "%s: -m not followed by path\n", Pn); 628 err = 1; 629 if (GOv) { 630 GOx1 = GObk[0]; 631 GOx2 = GObk[1]; 632 } 633 } else 634 Memory = GOv; 635# else /* !defined(HASMOPT) */ 636 (void) fprintf(stderr, "%s: -m not supported\n", Pn); 637 err = 1; 638# endif /* defined(HASMOPT) */ 639 640 } else if (GOp == '+') { 641 642# if defined(HASMNTSUP) 643 if (!GOv || *GOv == '-' || *GOv == '+') { 644 MntSup = 1; 645 if (GOv) { 646 GOx1 = GObk[0]; 647 GOx2 = GObk[1]; 648 } 649 } else { 650 MntSup = 2; 651 MntSupP = GOv; 652 } 653# else /* !defined(HASMNTSUP) */ 654 (void) fprintf(stderr, "%s: +m not supported\n", Pn); 655 err = 1; 656# endif /* defined(HASMNTSUP) */ 657 658 } else { 659 (void) fprintf(stderr, "%s: %cm not supported\n", Pn, GOp); 660 err = 1; 661 } 662 break; 663#endif /* defined(HASMOPT) || defined(HASMNTSUP) */ 664 665#if !defined(HASNORPC_H) 666 case 'M': 667 FportMap = (GOp == '+') ? 1 : 0; 668 break; 669#endif /* !defined(HASNORPC_H) */ 670 671 case 'n': 672 Fhost = (GOp == '-') ? 0 : 1; 673 break; 674 case 'N': 675 Fnfs = 1; 676 break; 677 case 'o': 678 if (!GOv || *GOv == '-' || *GOv == '+') { 679 Foffset = 1; 680 if (GOv) { 681 GOx1 = GObk[0]; 682 GOx2 = GObk[1]; 683 } 684 break; 685 } 686 for (cp = GOv, i = n = 0; *cp; cp++) { 687 if (!isdigit((unsigned char)*cp)) 688 break; 689 i = (i * 10) + ((int)*cp - '0'); 690 n++; 691 } 692 if (n) 693 OffDecDig = i; 694 else 695 Foffset = 1; 696 if (*cp) { 697 GOx1 = GObk[0]; 698 GOx2 = GObk[1] + n; 699 } 700 break; 701 case 'O': 702 Fovhd = (GOp == '-') ? 1 : 0; 703 break; 704 case 'p': 705 if (enter_id(PID, GOv)) 706 err = 1; 707 break; 708 case 'P': 709 Fport = (GOp == '-') ? 0 : 1; 710 break; 711 case 'r': 712 if (GOp == '+') 713 ev = rc = 1; 714 if (!GOv || *GOv == '-' || *GOv == '+') { 715 RptTm = RPTTM; 716 if (GOv) { 717 GOx1 = GObk[0]; 718 GOx2 = GObk[1]; 719 } 720 break; 721 } 722 for (cp = GOv, i = n = 0; *cp; cp++) { 723 if (!isdigit((unsigned char)*cp)) 724 break; 725 i = (i * 10) + ((int)*cp - '0'); 726 n++; 727 } 728 if (n) 729 RptTm = i; 730 else 731 RptTm = RPTTM; 732 if (!*cp) 733 break; 734 while(*cp && (*cp == ' ')) 735 cp++; 736 if (*cp != LSOF_FID_MARK) { 737 GOx1 = GObk[0]; 738 GOx2 = GObk[1] + n; 739 break; 740 } 741 742#if defined(HAS_STRFTIME) 743 744 /* 745 * Collect the strftime(3) format and test it. 746 */ 747 cp++; 748 if ((fmtl = strlen(cp) + 1) < 1) { 749 (void) fprintf(stderr, "%s: <fmt> too short: \"%s\"\n", 750 Pn, cp); 751 err = 1; 752 } else { 753 fmt = cp; 754 fmtl = (fmtl * 8) + 1; 755 if (!(fmtr = (char *)malloc((MALLOC_S)fmtl))) { 756 (void) fprintf(stderr, 757 "%s: no space (%d) for <fmt> result: \"%s\"\n", 758 Pn, (int)fmtl, cp); 759 Exit(1); 760 } 761 if (util_strftime(fmtr, fmtl - 1, fmt) < 1) { 762 (void) fprintf(stderr, "%s: illegal <fmt>: \"%s\"\n", 763 Pn, fmt); 764 err = 1; 765 } 766 } 767 768#else /* !defined(HAS_STRFTIME) */ 769 (void) fprintf(stderr, "%s: m<fmt> not supported: \"%s\"\n", 770 Pn, cp); 771 err = 1; 772#endif /* defined(HAS_STRFTIME) */ 773 774 break; 775 776#if defined(HASPPID) 777 case 'R': 778 Fppid = 1; 779 break; 780#endif /* defined(HASPPID) */ 781 782 case 's': 783 784#if defined(HASTCPUDPSTATE) 785 if (!GOv || *GOv == '-' || *GOv == '+') { 786 Fsize = 1; 787 if (GOv) { 788 GOx1 = GObk[0]; 789 GOx2 = GObk[1]; 790 } 791 } else { 792 if (enter_state_spec(GOv)) 793 err = 1; 794 } 795#else /* !defined(HASTCPUDPSTATE) */ 796 Fsize = 1; 797#endif /* defined(HASTCPUDPSTATE) */ 798 799 break; 800 case 'S': 801 if (!GOv || *GOv == '-' || *GOv == '+') { 802 TmLimit = TMLIMIT; 803 if (GOv) { 804 GOx1 = GObk[0]; 805 GOx2 = GObk[1]; 806 } 807 break; 808 } 809 for (cp = GOv, i = n = 0; *cp; cp++) { 810 if (!isdigit((unsigned char)*cp)) 811 break; 812 i = (i * 10) + ((int)*cp - '0'); 813 n++; 814 } 815 if (n) 816 TmLimit = i; 817 else 818 TmLimit = TMLIMIT; 819 if (*cp) { 820 GOx1 = GObk[0]; 821 GOx2 = GObk[1] + n; 822 } 823 if (TmLimit < TMLIMMIN) { 824 (void) fprintf(stderr, 825 "%s: WARNING: -S time (%d) changed to %d\n", 826 Pn, TmLimit, TMLIMMIN); 827 TmLimit = TMLIMMIN; 828 } 829 break; 830 case 't': 831 Fterse = Fwarn = 1; 832 break; 833 case 'T': 834 if (!GOv || *GOv == '-' || *GOv == '+') { 835 Ftcptpi = (GOp == '-') ? 0 : TCPTPI_STATE; 836 if (GOv) { 837 GOx1 = GObk[0]; 838 GOx2 = GObk[1]; 839 } 840 break; 841 } 842 for (Ftcptpi = 0; *GOv; GOv++) { 843 switch (*GOv) { 844 845#if defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT) 846 case 'f': 847 Ftcptpi |= TCPTPI_FLAGS; 848 break; 849#endif /* defined(HASSOOPT) || defined(HASSOSTATE) || defined(HASTCPOPT) */ 850 851#if defined(HASTCPTPIQ) 852 case 'q': 853 Ftcptpi |= TCPTPI_QUEUES; 854 break; 855#endif /* defined(HASTCPTPIQ) */ 856 857 case 's': 858 Ftcptpi |= TCPTPI_STATE; 859 break; 860 861#if defined(HASTCPTPIW) 862 case 'w': 863 Ftcptpi |= TCPTPI_WINDOWS; 864 break; 865#endif /* defined(HASTCPTPIW) */ 866 867 default: 868 (void) fprintf(stderr, 869 "%s: unsupported TCP/TPI info selection: %c\n", 870 Pn, *GOv); 871 err = 1; 872 } 873 } 874 break; 875 case 'u': 876 if (enter_uid(GOv)) 877 err = 1; 878 break; 879 case 'U': 880 Funix = 1; 881 break; 882 case 'v': 883 version = 1; 884 break; 885 case 'V': 886 Fverbose = 1; 887 break; 888 case 'w': 889 Fwarn = (GOp == '+') ? 0 : 1; 890 break; 891 case 'x': 892 if (!GOv || *GOv == '-' || *GOv == '+') { 893 Fxover = XO_ALL; 894 if (GOv) { 895 GOx1 = GObk[0]; 896 GOx2 = GObk[1]; 897 } 898 break; 899 } else { 900 for (; *GOv; GOv++) { 901 switch (*GOv) { 902 case 'f': 903 Fxover |= XO_FILESYS; 904 break; 905 case 'l': 906 Fxover |= XO_SYMLINK; 907 break; 908 default: 909 (void) fprintf(stderr, 910 "%s: unknown cross-over option: %c\n", 911 Pn, *GOv); 912 err++; 913 } 914 } 915 } 916 break; 917 918#if defined(HASXOPT) 919 case 'X': 920 Fxopt = Fxopt ? 0 : 1; 921 break; 922#endif /* defined(HASXOPT) */ 923 924#if defined(HASZONES) 925 case 'z': 926 Fzone = 1; 927 if (GOv && (*GOv != '-') && (*GOv != '+')) { 928 929 /* 930 * Add to the zone name argument hash. 931 */ 932 if (enter_zone_arg(GOv)) 933 err = 1; 934 } else if (GOv) { 935 GOx1 = GObk[0]; 936 GOx2 = GObk[1]; 937 } 938 break; 939#endif /* defined(HASZONES) */ 940 941#if defined(HASSELINUX) 942 case 'Z': 943 if (!CntxStatus) { 944 (void) fprintf(stderr, "%s: -Z limited to SELinux\n", Pn); 945 err = 1; 946 } else { 947 Fcntx = 1; 948 if (GOv && (*GOv != '-') && (*GOv != '+')) { 949 950 /* 951 * Add to the context name argument hash. 952 */ 953 if (enter_cntx_arg(GOv)) 954 err = 1; 955 } else if (GOv) { 956 GOx1 = GObk[0]; 957 GOx2 = GObk[1]; 958 } 959 } 960 break; 961#endif /* defined(HASSELINUX) */ 962 963 default: 964 (void) fprintf(stderr, "%s: unknown option (%c)\n", Pn, c); 965 err = 1; 966 } 967 } 968/* 969 * Check for argument consistency. 970 */ 971 if (Cmdnx && Cmdni) { 972 973 /* 974 * Check for command inclusion/exclusion conflicts. 975 */ 976 for (str = Cmdl; str; str = str->next) { 977 if (str->x) { 978 for (strt = Cmdl; strt; strt = strt->next) { 979 if (!strt->x) { 980 if (!strcmp(str->str, strt->str)) { 981 (void) fprintf(stderr, 982 "%s: -c^%s and -c%s conflict.\n", 983 Pn, str->str, strt->str); 984 err++; 985 } 986 } 987 } 988 } 989 } 990 } 991 992#if defined(HASTCPUDPSTATE) 993 if (TcpStXn && TcpStIn) { 994 995 /* 996 * Check for excluded and included TCP states. 997 */ 998 for (i = 0; i < TcpNstates; i++) { 999 if (TcpStX[i] && TcpStI[i]) { 1000 (void) fprintf(stderr, 1001 "%s: can't include and exclude TCP state: %s\n", 1002 Pn, TcpSt[i]); 1003 err = 1; 1004 } 1005 } 1006 } 1007 if (UdpStXn && UdpStIn) { 1008 1009 /* 1010 * Check for excluded and included UDP states. 1011 */ 1012 for (i = 0; i < UdpNstates; i++) { 1013 if (UdpStX[i] && UdpStI[i]) { 1014 (void) fprintf(stderr, 1015 "%s: can't include and exclude UDP state: %s\n", 1016 Pn, UdpSt[i]); 1017 err = 1; 1018 } 1019 } 1020 } 1021#endif /* defined(HASTCPUDPSTATE) */ 1022 1023 if (Fsize && Foffset) { 1024 (void) fprintf(stderr, "%s: -o and -s are mutually exclusive\n", 1025 Pn); 1026 err++; 1027 } 1028 if (Ffield) { 1029 if (Fterse) { 1030 (void) fprintf(stderr, 1031 "%s: -F and -t are mutually exclusive\n", Pn); 1032 err++; 1033 } 1034 FieldSel[LSOF_FIX_PID].st = 1; 1035 1036#if defined(HAS_STRFTIME) 1037 if (fmtr) { 1038 1039 /* 1040 * The field output marker format can't contain "%n" new line 1041 * requests. 1042 */ 1043 for (cp = strchr(fmt, '%'); cp; cp = strchr(cp, '%')) { 1044 if (*++cp == 'n') { 1045 (void) fprintf(stderr, 1046 "%s: %%n illegal in -r m<fmt> when -F has", Pn); 1047 (void) fprintf(stderr, 1048 " been specified: \"%s\"\n", fmt); 1049 err++; 1050 break; 1051 } else if (*cp == '%') 1052 cp++; 1053 } 1054 } 1055#endif /* defined(HAS_STRFTIME) */ 1056 1057 } 1058 if (Fxover && !xover) { 1059 (void) fprintf(stderr, "%s: -x must accompany +d or +D\n", Pn); 1060 err++; 1061 } 1062 1063#if defined(HASEOPT) 1064 if (Efsysl) { 1065 1066 /* 1067 * If there are file systems specified by -e options, check them. 1068 */ 1069 efsys_list_t *ep; /* Efsysl pointer */ 1070 struct mounts *mp, *mpw; /* local mount table pointers */ 1071 1072 if ((mp = readmnt())) { 1073 for (ep = Efsysl; ep; ep = ep->next) { 1074 for (mpw = mp; mpw; mpw = mpw->next) { 1075 if (!strcmp(mpw->dir, ep->path)) { 1076 ep->mp = mpw; 1077 break; 1078 } 1079 } 1080 if (!ep->mp) { 1081 (void) fprintf(stderr, 1082 "%s: \"-e %s\" is not a mounted file system.\n", 1083 Pn, ep->path); 1084 err++; 1085 } 1086 } 1087 } 1088 } 1089#endif /* defined(HASEOPT) */ 1090 1091 if (DChelp || err || Fhelp || fh || version) 1092 usage(err ? 1 : 0, fh, version); 1093/* 1094 * Reduce the size of Suid[], if necessary. 1095 */ 1096 if (Suid && Nuid && Nuid < Mxuid) { 1097 if (!(Suid = (struct seluid *)realloc((MALLOC_P *)Suid, 1098 (MALLOC_S)(sizeof(struct seluid) * Nuid)))) 1099 { 1100 (void) fprintf(stderr, "%s: can't realloc UID table\n", Pn); 1101 Exit(1); 1102 } 1103 Mxuid = Nuid; 1104 } 1105/* 1106 * Compute the selection flags. 1107 */ 1108 if ((Cmdl && Cmdni) || CmdRx) 1109 Selflags |= SELCMD; 1110 1111#if defined(HASSELINUX) 1112 if (CntxArg) 1113 Selflags |= SELCNTX; 1114#endif /* defined(HASSELINUX) */ 1115 1116 if (Fdl) 1117 Selflags |= SELFD; 1118 if (Fnet) 1119 Selflags |= SELNET; 1120 if (Fnfs) 1121 Selflags |= SELNFS; 1122 if (Funix) 1123 Selflags |= SELUNX; 1124 if (Npgid && Npgidi) 1125 Selflags |= SELPGID; 1126 if (Npid && Npidi) 1127 Selflags |= SELPID; 1128 if (Nuid && Nuidincl) 1129 Selflags |= SELUID; 1130 if (Nwad) 1131 Selflags |= SELNA; 1132 1133#if defined(HASZONES) 1134 if (ZoneArg) 1135 Selflags |= SELZONE; 1136#endif /* defined(HASZONES) */ 1137 1138 if (GOx1 < argc) 1139 Selflags |= SELNM; 1140 if (Selflags == 0) { 1141 if (Fand) { 1142 (void) fprintf(stderr, 1143 "%s: no select options to AND via -a\n", Pn); 1144 usage(1, 0, 0); 1145 } 1146 Selflags = SELALL; 1147 } else { 1148 if (GOx1 >= argc && (Selflags & (SELNA|SELNET)) != 0 1149 && (Selflags & ~(SELNA|SELNET)) == 0) 1150 Selinet = 1; 1151 Selall = 0; 1152 } 1153/* 1154 * Get the device for DEVDEV_PATH. 1155 */ 1156 if (stat(DEVDEV_PATH, &sb)) { 1157 se1 = errno; 1158 if ((ad = strcmp(DEVDEV_PATH, "/dev"))) { 1159 if ((ss = stat("/dev", &sb))) 1160 se2 = errno; 1161 else 1162 se2 = 0; 1163 } else { 1164 se2 = 0; 1165 ss = 1; 1166 } 1167 if (ss) { 1168 (void) fprintf(stderr, "%s: can't stat(%s): %s\n", Pn, 1169 DEVDEV_PATH, strerror(se1)); 1170 if (ad) { 1171 (void) fprintf(stderr, "%s: can't stat(/dev): %s\n", Pn, 1172 strerror(se2)); 1173 } 1174 Exit(1); 1175 } 1176 } 1177 DevDev = sb.st_dev; 1178/* 1179 * Process the file arguments. 1180 */ 1181 if (GOx1 < argc) { 1182 if (ck_file_arg(GOx1, argc, argv, Ffilesys, 0, (struct stat *)NULL)) 1183 usage(1, 0, 0); 1184 } 1185/* 1186 * Do dialect-specific initialization. 1187 */ 1188 initialize(); 1189 if (Sfile) 1190 (void) hashSfile(); 1191 1192#if defined(WILLDROPGID) 1193/* 1194 * If this process isn't setuid(root), but it is setgid(not_real_gid), 1195 * relinquish the setgid power. (If it hasn't already been done.) 1196 */ 1197 (void) dropgid(); 1198#endif /* defined(WILLDROPGID) */ 1199 1200 1201#if defined(HASDCACHE) 1202/* 1203 * If there is a device cache, prepare the device table. 1204 */ 1205 if (DCstate) 1206 readdev(0); 1207#endif /* defined(HASDCACHE) */ 1208 1209/* 1210 * Define the size and offset print formats. 1211 */ 1212 (void) snpf(options, sizeof(options), "%%%su", INODEPSPEC); 1213 InodeFmt_d = sv_fmt_str(options); 1214 (void) snpf(options, sizeof(options), "%%#%sx", INODEPSPEC); 1215 InodeFmt_x = sv_fmt_str(options); 1216 (void) snpf(options, sizeof(options), "0t%%%su", SZOFFPSPEC); 1217 SzOffFmt_0t = sv_fmt_str(options); 1218 (void) snpf(options, sizeof(options), "%%%su", SZOFFPSPEC); 1219 SzOffFmt_d = sv_fmt_str(options); 1220 (void) snpf(options, sizeof(options), "%%*%su", SZOFFPSPEC); 1221 SzOffFmt_dv = sv_fmt_str(options); 1222 (void) snpf(options, sizeof(options), "%%#%sx", SZOFFPSPEC); 1223 SzOffFmt_x = sv_fmt_str(options); 1224 1225#if defined(HASMNTSUP) 1226/* 1227 * Report mount supplement information, as requested. 1228 */ 1229 if (MntSup == 1) { 1230 (void) readmnt(); 1231 Exit(0); 1232 } 1233#endif /* defined(HASMNTSUP) */ 1234 1235/* 1236 * Gather and report process information every RptTm seconds. 1237 */ 1238 if (RptTm) 1239 CkPasswd = 1; 1240 do { 1241 1242 /* 1243 * Gather information about processes. 1244 */ 1245 gather_proc_info(); 1246 /* 1247 * If the local process table has more than one entry, sort it by PID. 1248 */ 1249 if (Nlproc > 1) { 1250 if (Nlproc > sp) { 1251 len = (MALLOC_S)(Nlproc * sizeof(struct lproc *)); 1252 sp = Nlproc; 1253 if (!slp) 1254 slp = (struct lproc **)malloc(len); 1255 else 1256 slp = (struct lproc **)realloc((MALLOC_P *)slp, len); 1257 if (!slp) { 1258 (void) fprintf(stderr, 1259 "%s: no space for %d sort pointers\n", Pn, Nlproc); 1260 Exit(1); 1261 } 1262 } 1263 for (i = 0; i < Nlproc; i++) { 1264 slp[i] = &Lproc[i]; 1265 } 1266 (void) qsort((QSORT_P *)slp, (size_t)Nlproc, 1267 (size_t)sizeof(struct lproc *), comppid); 1268 } 1269 if ((n = Nlproc)) { 1270 1271#if defined(HASNCACHE) 1272 /* 1273 * If using the kernel name cache, force its reloading. 1274 */ 1275 NcacheReload = 1; 1276#endif /* defined(HASNCACHE) */ 1277 1278 /* 1279 * Print the selected processes and count them. 1280 * 1281 * Lf contents must be preserved, since they may point to a 1282 * malloc()'d area, and since Lf is used throughout the print 1283 * process. 1284 */ 1285 for (lf = Lf, print_init(); PrPass < 2; PrPass++) { 1286 for (i = n = 0; i < Nlproc; i++) { 1287 Lp = (Nlproc > 1) ? slp[i] : &Lproc[i]; 1288 if (Lp->pss) { 1289 if (print_proc()) 1290 n++; 1291 } 1292 if (RptTm && PrPass) 1293 (void) free_lproc(Lp); 1294 } 1295 } 1296 Lf = lf; 1297 } 1298 /* 1299 * If a repeat time is set, sleep for the specified time. 1300 * 1301 * If conditional repeat mode is in effect, see if it's time to exit. 1302 */ 1303 if (RptTm) { 1304 if (rc) { 1305 if (!n) 1306 break; 1307 else 1308 ev = 0; 1309 } 1310 1311#if defined(HAS_STRFTIME) 1312 if (fmt && fmtr) { 1313 1314 /* 1315 * Format the marker line. 1316 */ 1317 (void) util_strftime(fmtr, fmtl - 1, fmt); 1318 fmtr[fmtl - 1] = '\0'; 1319 } 1320#endif /* defined(HAS_STRFTIME) */ 1321 1322 if (Ffield) { 1323 putchar(LSOF_FID_MARK); 1324 1325#if defined(HAS_STRFTIME) 1326 if (fmtr) 1327 (void) printf("%s", fmtr); 1328#endif /* defined(HAS_STRFTIME) */ 1329 1330 putchar(Terminator); 1331 if (Terminator != '\n') 1332 putchar('\n'); 1333 } else { 1334 1335#if defined(HAS_STRFTIME) 1336 if (fmtr) 1337 cp = fmtr; 1338 else 1339#endif /* defined(HAS_STRFTIME) */ 1340 1341 cp = "======="; 1342 puts(cp); 1343 } 1344 (void) fflush(stdout); 1345 (void) childx(); 1346 (void) sleep(RptTm); 1347 Hdr = Nlproc = 0; 1348 CkPasswd = 1; 1349 } 1350 } while (RptTm); 1351/* 1352 * See if all requested information was displayed. Return zero if it 1353 * was; one, if not. If -V was specified, report what was not displayed. 1354 */ 1355 (void) childx(); 1356 rv = 0; 1357 for (str = Cmdl; str; str = str->next) { 1358 1359 /* 1360 * Check command specifications. 1361 */ 1362 if (str->f) 1363 continue; 1364 rv = 1; 1365 if (Fverbose) { 1366 (void) printf("%s: command not located: ", Pn); 1367 safestrprt(str->str, stdout, 1); 1368 } 1369 } 1370 for (i = 0; i < NCmdRxU; i++) { 1371 1372 /* 1373 * Check command regular expressions. 1374 */ 1375 if (CmdRx[i].mc) 1376 continue; 1377 rv = 1; 1378 if (Fverbose) { 1379 (void) printf("%s: no command found for regex: ", Pn); 1380 safestrprt(CmdRx[i].exp, stdout, 1); 1381 } 1382 } 1383 for (sfp = Sfile; sfp; sfp = sfp->next) { 1384 1385 /* 1386 * Check file specifications. 1387 */ 1388 if (sfp->f) 1389 continue; 1390 rv = 1; 1391 if (Fverbose) { 1392 (void) printf("%s: no file%s use located: ", Pn, 1393 sfp->type ? "" : " system"); 1394 safestrprt(sfp->aname, stdout, 1); 1395 } 1396 } 1397 1398#if defined(HASPROCFS) 1399 /* 1400 * Report on proc file system search results. 1401 */ 1402 if (Procsrch && !Procfind) { 1403 rv = 1; 1404 if (Fverbose) { 1405 (void) printf("%s: no file system use located: ", Pn); 1406 safestrprt(Mtprocfs ? Mtprocfs->dir : HASPROCFS, stdout, 1); 1407 } 1408 } 1409 { 1410 struct procfsid *pfi; 1411 1412 for (pfi = Procfsid; pfi; pfi = pfi->next) { 1413 if (!pfi->f) { 1414 rv = 1; 1415 if (Fverbose) { 1416 (void) printf("%s: no file use located: ", Pn); 1417 safestrprt(pfi->nm, stdout, 1); 1418 } 1419 } 1420 } 1421 } 1422#endif /* defined(HASPROCFS) */ 1423 1424 if ((np = Nwad)) { 1425 1426 /* 1427 * Check Internet address specifications. 1428 * 1429 * If any Internet address derived from the same argument was found, 1430 * consider all derivations found. If no derivation from the same 1431 * argument was found, report only the first failure. 1432 * 1433 */ 1434 for (; np; np = np->next) { 1435 if (!(cp = np->arg)) 1436 continue; 1437 for (npn = np->next; npn; npn = npn->next) { 1438 if (!npn->arg) 1439 continue; 1440 if (!strcmp(cp, npn->arg)) { 1441 1442 /* 1443 * If either of the duplicate specifications was found, 1444 * mark them both found. If neither was found, mark all 1445 * but the first one found. 1446 */ 1447 if (np->f) 1448 npn->f = np->f; 1449 else if (npn->f) 1450 np->f = npn->f; 1451 else 1452 npn->f = 1; 1453 } 1454 } 1455 } 1456 for (np = Nwad; np; np = np->next) { 1457 if (!np->f && (cp = np->arg)) { 1458 rv = 1; 1459 if (Fverbose) { 1460 (void) printf("%s: Internet address not located: ", Pn); 1461 safestrprt(cp ? cp : "(unknown)", stdout, 1); 1462 } 1463 } 1464 } 1465 } 1466 if (Fnet && Fnet < 2) { 1467 1468 /* 1469 * Report no Internet files located. 1470 */ 1471 rv = 1; 1472 if (Fverbose) 1473 (void) printf("%s: no Internet files located\n", Pn); 1474 } 1475 1476#if defined(HASTCPUDPSTATE) 1477 if (TcpStIn) { 1478 1479 /* 1480 * Check for included TCP states not located. 1481 */ 1482 for (i = 0; i < TcpNstates; i++) { 1483 if (TcpStI[i] == 1) { 1484 rv = 1; 1485 if (Fverbose) 1486 (void) printf("%s: TCP state not located: %s\n", 1487 Pn, TcpSt[i]); 1488 } 1489 } 1490 } 1491 if (UdpStIn) { 1492 1493 /* 1494 * Check for included UDP states not located. 1495 */ 1496 for (i = 0; i < UdpNstates; i++) { 1497 if (UdpStI[i] == 1) { 1498 rv = 1; 1499 if (Fverbose) 1500 (void) printf("%s: UDP state not located: %s\n", 1501 Pn, UdpSt[i]); 1502 } 1503 } 1504 } 1505#endif /* defined(HASTCPUDPSTATE) */ 1506 1507 if (Fnfs && Fnfs < 2) { 1508 1509 /* 1510 * Report no NFS files located. 1511 */ 1512 rv = 1; 1513 if (Fverbose) 1514 (void) printf("%s: no NFS files located\n", Pn); 1515 } 1516 for (i = 0; i < Npid; i++) { 1517 1518 /* 1519 * Check inclusionary process ID specifications. 1520 */ 1521 if (Spid[i].f || Spid[i].x) 1522 continue; 1523 rv = 1; 1524 if (Fverbose) 1525 (void) printf("%s: process ID not located: %d\n", 1526 Pn, Spid[i].i); 1527 } 1528 1529#if defined(HASTASKS) 1530 if (Ftask && Ftask < 2) { 1531 1532 /* 1533 * Report no tasks located. 1534 */ 1535 rv = 1; 1536 if (Fverbose) 1537 (void) printf("%s: no tasks located\n", Pn); 1538 } 1539#endif /* defined(HASTASKS) */ 1540 1541#if defined(HASZONES) 1542 if (ZoneArg) { 1543 1544 /* 1545 * Check zone argument results. 1546 */ 1547 for (i = 0; i < HASHZONE; i++) { 1548 for (zp = ZoneArg[i]; zp; zp = zp->next) { 1549 if (!zp->f) { 1550 rv = 1; 1551 if (Fverbose) { 1552 (void) printf("%s: zone not located: ", Pn); 1553 safestrprt(zp->zn, stdout, 1); 1554 } 1555 } 1556 } 1557 } 1558 } 1559#endif /* defined(HASZONES) */ 1560 1561#if defined(HASSELINUX) 1562 if (CntxArg) { 1563 1564 /* 1565 * Check context argument results. 1566 */ 1567 for (cntxp = CntxArg; cntxp; cntxp = cntxp->next) { 1568 if (!cntxp->f) { 1569 rv = 1; 1570 if (Fverbose) { 1571 (void) printf("%s: context not located: ", Pn); 1572 safestrprt(cntxp->cntx, stdout, 1); 1573 } 1574 } 1575 } 1576 } 1577#endif /* defined(HASSELINUX) */ 1578 1579 for (i = 0; i < Npgid; i++) { 1580 1581 /* 1582 * Check inclusionary process group ID specifications. 1583 */ 1584 if (Spgid[i].f || Spgid[i].x) 1585 continue; 1586 rv = 1; 1587 if (Fverbose) 1588 (void) printf("%s: process group ID not located: %d\n", 1589 Pn, Spgid[i].i); 1590 } 1591 for (i = 0; i < Nuid; i++) { 1592 1593 /* 1594 * Check inclusionary user ID specifications. 1595 */ 1596 if (Suid[i].excl || Suid[i].f) 1597 continue; 1598 rv = 1; 1599 if (Fverbose) { 1600 if (Suid[i].lnm) { 1601 (void) printf("%s: login name (UID %lu) not located: ", 1602 Pn, (unsigned long)Suid[i].uid); 1603 safestrprt(Suid[i].lnm, stdout, 1); 1604 } else 1605 (void) printf("%s: user ID not located: %lu\n", Pn, 1606 (unsigned long)Suid[i].uid); 1607 } 1608 } 1609 if (!rv && rc) 1610 rv = ev; 1611 if (!rv && ErrStat) 1612 rv = 1; 1613 Exit(rv); 1614 return(rv); /* to make code analyzers happy */ 1615} 1616 1617 1618/* 1619 * GetOpt() -- Local get option 1620 * 1621 * Liberally adapted from the public domain AT&T getopt() source, 1622 * distributed at the 1985 UNIFORM conference in Dallas 1623 * 1624 * The modifications allow `?' to be an option character and allow 1625 * the caller to decide that an option that may be followed by a 1626 * value doesn't have one -- e.g., has a default instead. 1627 */ 1628 1629static int 1630GetOpt(ct, opt, rules, err) 1631 int ct; /* option count */ 1632 char *opt[]; /* options */ 1633 char *rules; /* option rules */ 1634 int *err; /* error return */ 1635{ 1636 register int c; 1637 register char *cp = (char *)NULL; 1638 1639 if (GOx2 == 0) { 1640 1641 /* 1642 * Move to a new entry of the option array. 1643 * 1644 * EOF if: 1645 * 1646 * Option list has been exhausted; 1647 * Next option doesn't start with `-' or `+'; 1648 * Next option has nothing but `-' or `+'; 1649 * Next option is ``--'' or ``++''. 1650 */ 1651 if (GOx1 >= ct 1652 || (opt[GOx1][0] != '-' && opt[GOx1][0] != '+') 1653 || !opt[GOx1][1]) 1654 return(EOF); 1655 if (strcmp(opt[GOx1], "--") == 0 || strcmp(opt[GOx1], "++") == 0) { 1656 GOx1++; 1657 return(EOF); 1658 } 1659 GOp = opt[GOx1][0]; 1660 GOx2 = 1; 1661 } 1662/* 1663 * Flag `:' option character as an error. 1664 * 1665 * Check for a rule on this option character. 1666 */ 1667 *err = 0; 1668 if ((c = opt[GOx1][GOx2]) == ':') { 1669 (void) fprintf(stderr, 1670 "%s: colon is an illegal option character.\n", Pn); 1671 *err = 1; 1672 } else if (!(cp = strchr(rules, c))) { 1673 (void) fprintf(stderr, "%s: illegal option character: %c\n", Pn, c); 1674 *err = 2; 1675 } 1676 if (*err) { 1677 1678 /* 1679 * An error was detected. 1680 * 1681 * Advance to the next option character. 1682 * 1683 * Return the character causing the error. 1684 */ 1685 if (opt[GOx1][++GOx2] == '\0') { 1686 GOx1++; 1687 GOx2 = 0; 1688 } 1689 return(c); 1690 } 1691 if (*(cp + 1) == ':') { 1692 1693 /* 1694 * The option may have a following value. The caller decides 1695 * if it does. 1696 * 1697 * Save the position of the possible value in case the caller 1698 * decides it does not belong to the option and wants it 1699 * reconsidered as an option character. The caller does that 1700 * with: 1701 * GOx1 = GObk[0]; GOx2 = GObk[1]; 1702 * 1703 * Don't indicate that an option of ``--'' is a possible value. 1704 * 1705 * Finally, on the assumption that the caller will decide that 1706 * the possible value belongs to the option, position to the 1707 * option following the possible value, so that the next call 1708 * to GetOpt() will find it. 1709 */ 1710 if(opt[GOx1][GOx2 + 1] != '\0') { 1711 GObk[0] = GOx1; 1712 GObk[1] = ++GOx2; 1713 GOv = &opt[GOx1++][GOx2]; 1714 } else if (++GOx1 >= ct) 1715 GOv = (char *)NULL; 1716 else { 1717 GObk[0] = GOx1; 1718 GObk[1] = 0; 1719 GOv = opt[GOx1]; 1720 if (strcmp(GOv, "--") == 0) 1721 GOv = (char *)NULL; 1722 else 1723 GOx1++; 1724 } 1725 GOx2 = 0; 1726 } else { 1727 1728 /* 1729 * The option character stands alone with no following value. 1730 * 1731 * Advance to the next option character. 1732 */ 1733 if (opt[GOx1][++GOx2] == '\0') { 1734 GOx2 = 0; 1735 GOx1++; 1736 } 1737 GOv = (char *)NULL; 1738 } 1739/* 1740 * Return the option character. 1741 */ 1742 return(c); 1743} 1744 1745 1746/* 1747 * sv_fmt_str() - save format string 1748 */ 1749 1750static char * 1751sv_fmt_str(f) 1752 char *f; /* format string */ 1753{ 1754 char *cp; 1755 MALLOC_S l; 1756 1757 l = (MALLOC_S)(strlen(f) + 1); 1758 if (!(cp = (char *)malloc(l))) { 1759 (void) fprintf(stderr, 1760 "%s: can't allocate %d bytes for format: %s\n", Pn, (int)l, f); 1761 Exit(1); 1762 } 1763 (void) snpf(cp, l, "%s", f); 1764 return(cp); 1765} 1766