1/* 2 * proc.c - common process and file structure functions for lsof 3 */ 4 5 6/* 7 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana 8 * 47907. All rights reserved. 9 * 10 * Written by Victor A. Abell 11 * 12 * This software is not subject to any license of the American Telephone 13 * and Telegraph Company or the Regents of the University of California. 14 * 15 * Permission is granted to anyone to use this software for any purpose on 16 * any computer system, and to alter it and redistribute it freely, subject 17 * to the following restrictions: 18 * 19 * 1. Neither the authors nor Purdue University are responsible for any 20 * consequences of the use of this software. 21 * 22 * 2. The origin of this software must not be misrepresented, either by 23 * explicit claim or by omission. Credit to the authors and Purdue 24 * University must appear in documentation and sources. 25 * 26 * 3. Altered versions must be plainly marked as such, and must not be 27 * misrepresented as being the original software. 28 * 29 * 4. This notice may not be removed or altered. 30 */ 31 32#ifndef lint 33static char copyright[] = 34"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n"; 35static char *rcsid = "$Id: proc.c,v 1.47 2013/01/02 17:14:59 abe Exp $"; 36#endif 37 38 39#include "lsof.h" 40 41 42/* 43 * Local function prototypes 44 */ 45 46_PROTOTYPE(static int is_file_sel,(struct lproc *lp, struct lfile *lf)); 47 48 49/* 50 * add_nma() - add to NAME column addition 51 */ 52 53void 54add_nma(cp, len) 55 char *cp; /* string to add */ 56 int len; /* string length */ 57{ 58 int nl; 59 60 if (!cp || !len) 61 return; 62 if (Lf->nma) { 63 nl = (int)strlen(Lf->nma); 64 Lf->nma = (char *)realloc((MALLOC_P *)Lf->nma, 65 (MALLOC_S)(len + nl + 2)); 66 } else { 67 nl = 0; 68 Lf->nma = (char *)malloc((MALLOC_S)(len + 1)); 69 } 70 if (!Lf->nma) { 71 (void) fprintf(stderr, "%s: no name addition space: PID %ld, FD %s", 72 Pn, (long)Lp->pid, Lf->fd); 73 Exit(1); 74 } 75 if (nl) { 76 Lf->nma[nl] = ' '; 77 (void) strncpy(&Lf->nma[nl + 1], cp, len); 78 Lf->nma[nl + 1 + len] = '\0'; 79 } else { 80 (void) strncpy(Lf->nma, cp, len); 81 Lf->nma[len] = '\0'; 82 } 83} 84 85 86#if defined(HASFSTRUCT) 87_PROTOTYPE(static char *alloc_fflbuf,(char **bp, int *al, int lr)); 88 89 90/* 91 * alloc_fflbuf() - allocate file flags print buffer 92 */ 93 94static char * 95alloc_fflbuf(bp, al, lr) 96 char **bp; /* current buffer pointer */ 97 int *al; /* current allocated length */ 98 int lr; /* length required */ 99{ 100 int sz; 101 102 sz = (int)(lr + 1); /* allocate '\0' space */ 103 if (*bp && (sz <= *al)) 104 return(*bp); 105 if (*bp) 106 *bp = (char *)realloc((MALLOC_P *)*bp, (MALLOC_S)sz); 107 else 108 *bp = (char *)malloc((MALLOC_S)sz); 109 if (!*bp) { 110 (void) fprintf(stderr, "%s: no space (%d) for print flags\n", 111 Pn, sz); 112 Exit(1); 113 } 114 *al = sz; 115 return(*bp); 116} 117#endif /* defined(HASFSTRUCT) */ 118 119 120/* 121 * alloc_lfile() - allocate local file structure space 122 */ 123 124void 125alloc_lfile(nm, num) 126 char *nm; /* file descriptor name (may be NULL) */ 127 int num; /* file descriptor number -- -1 if 128 * none */ 129{ 130 int fds; 131 132 if (Lf) { 133/* 134 * If reusing a previously allocated structure, release any allocated 135 * space it was using. 136 */ 137 if (Lf->dev_ch) 138 (void) free((FREE_P *)Lf->dev_ch); 139 if (Lf->nm) 140 (void) free((FREE_P *)Lf->nm); 141 if (Lf->nma) 142 (void) free((FREE_P *)Lf->nma); 143 144#if defined(HASLFILEADD) && defined(CLRLFILEADD) 145 CLRLFILEADD(Lf) 146#endif /* defined(HASLFILEADD) && defined(CLRLFILEADD) */ 147 148/* 149 * Othwerise, allocate a new structure. 150 */ 151 } else if (!(Lf = (struct lfile *)malloc(sizeof(struct lfile)))) { 152 (void) fprintf(stderr, "%s: no local file space at PID %d\n", 153 Pn, Lp->pid); 154 Exit(1); 155 } 156/* 157 * Initialize the structure. 158 */ 159 Lf->access = Lf->lock = ' '; 160 Lf->dev_def = Lf->inp_ty = Lf->is_com = Lf->is_nfs = Lf->is_stream 161 = Lf->lmi_srch = Lf->nlink_def = Lf->off_def = Lf->sz_def 162 = Lf->rdev_def 163 = (unsigned char)0; 164 Lf->li[0].af = Lf->li[1].af = 0; 165 Lf->lts.type = -1; 166 Lf->nlink = 0l; 167 168#if defined(HASMNTSTAT) 169 Lf->mnt_stat = (unsigned char)0; 170#endif /* defined(HASMNTSTAT) */ 171 172#if defined(HASSOOPT) 173 Lf->lts.kai = Lf->lts.ltm = 0; 174 Lf->lts.opt = Lf->lts.qlen = Lf->lts.qlim = Lf->lts.pqlen 175 = (unsigned int)0; 176 Lf->lts.rbsz = Lf->lts.sbsz = (unsigned long)0; 177 Lf->lts.qlens = Lf->lts.qlims = Lf->lts.pqlens = Lf->lts.rbszs 178 = Lf->lts.sbszs = (unsigned char)0; 179#endif /* defined(HASSOOPT) */ 180 181#if defined(HASSOSTATE) 182 Lf->lts.ss = 0; 183#endif /* defined(HASSOSTATE) */ 184 185#if defined(HASTCPOPT) 186 Lf->lts.mss = (unsigned long)0; 187 Lf->lts.msss = (unsigned char)0; 188 Lf->lts.topt = (unsigned int)0; 189#endif /* defined(HASTCPOPT) */ 190 191#if defined(HASTCPTPIQ) 192 Lf->lts.rqs = Lf->lts.sqs = (unsigned char)0; 193#endif /* defined(HASTCPTPIQ) */ 194 195#if defined(HASTCPTPIW) 196 Lf->lts.rws = Lf->lts.wws = (unsigned char)0; 197#endif /* defined(HASTCPTPIW) */ 198 199#if defined(HASFSINO) 200 Lf->fs_ino = 0; 201#endif /* defined(HASFSINO) */ 202 203#if defined(HASVXFS) && defined(HASVXFSDNLC) 204 Lf->is_vxfs = 0; 205#endif /* defined(HASVXFS) && defined(HASVXFSDNLC) */ 206 207 Lf->inode = (INODETYPE)0; 208 Lf->off = (SZOFFTYPE)0; 209 if (Lp->pss & PS_PRI) 210 Lf->sf = Lp->sf; 211 else 212 Lf->sf = 0; 213 Lf->iproto[0] = Lf->type[0] = '\0'; 214 if (nm) { 215 (void) strncpy(Lf->fd, nm, FDLEN - 1); 216 Lf->fd[FDLEN - 1] = '\0'; 217 } else if (num >= 0) { 218 if (num < 10000) 219 (void) snpf(Lf->fd, sizeof(Lf->fd), "%4d", num); 220 else 221 (void) snpf(Lf->fd, sizeof(Lf->fd), "*%03d", num % 1000); 222 } else 223 Lf->fd[0] = '\0'; 224 Lf->dev_ch = Lf->fsdir = Lf->fsdev = Lf->nm = Lf->nma = (char *)NULL; 225 Lf->ch = -1; 226 227#if defined(HASNCACHE) && HASNCACHE<2 228 Lf->na = (KA_T)NULL; 229#endif /* defined(HASNCACHE) && HASNCACHE<2 */ 230 231 Lf->next = (struct lfile *)NULL; 232 Lf->ntype = Ntype = N_REGLR; 233 Namech[0] = '\0'; 234 235#if defined(HASFSTRUCT) 236 Lf->fct = Lf->ffg = Lf->pof = (long)0; 237 Lf->fna = (KA_T)NULL; 238 Lf->fsv = (unsigned char)0; 239#endif /* defined(HASFSTRUCT) */ 240 241#if defined(HASLFILEADD) && defined(SETLFILEADD) 242/* 243 * Do local initializations. 244 */ 245 SETLFILEADD 246#endif /* defined(HASLFILEADD) && defined(SETLFILEADD) */ 247 248/* 249 * See if the file descriptor has been selected. 250 */ 251 if (!Fdl || (!nm && num < 0)) 252 return; 253 fds = ck_fd_status(nm, num); 254 switch (FdlTy) { 255 case 0: /* inclusion list */ 256 if (fds == 2) 257 Lf->sf |= SELFD; 258 break; 259 case 1: /* exclusion list */ 260 if (fds != 1) 261 Lf->sf |= SELFD; 262 } 263} 264 265 266/* 267 * alloc_lproc() - allocate local proc structure space 268 */ 269 270void 271alloc_lproc(pid, pgid, ppid, uid, cmd, pss, sf) 272 int pid; /* Process ID */ 273 int pgid; /* process group ID */ 274 int ppid; /* parent process ID */ 275 UID_ARG uid; /* User ID */ 276 char *cmd; /* command */ 277 int pss; /* process select state */ 278 int sf; /* process select flags */ 279{ 280 static int sz = 0; 281 282 if (!Lproc) { 283 if (!(Lproc = (struct lproc *)malloc( 284 (MALLOC_S)(LPROCINCR * sizeof(struct lproc))))) 285 { 286 (void) fprintf(stderr, 287 "%s: no malloc space for %d local proc structures\n", 288 Pn, LPROCINCR); 289 Exit(1); 290 } 291 sz = LPROCINCR; 292 } else if ((Nlproc + 1) > sz) { 293 sz += LPROCINCR; 294 if (!(Lproc = (struct lproc *)realloc((MALLOC_P *)Lproc, 295 (MALLOC_S)(sz * sizeof(struct lproc))))) 296 { 297 (void) fprintf(stderr, 298 "%s: no realloc space for %d local proc structures\n", 299 Pn, sz); 300 Exit(1); 301 } 302 } 303 Lp = &Lproc[Nlproc++]; 304 Lp->pid = pid; 305 306#if defined(HASTASKS) 307 Lp->tid = 0; 308#endif /* defined(HASTASKS) */ 309 310 Lp->pgid = pgid; 311 Lp->ppid = ppid; 312 Lp->file = (struct lfile *)NULL; 313 Lp->sf = (short)sf; 314 Lp->pss = (short)pss; 315 Lp->uid = (uid_t)uid; 316/* 317 * Allocate space for the full command name and copy it there. 318 */ 319 if (!(Lp->cmd = mkstrcpy(cmd, (MALLOC_S *)NULL))) { 320 (void) fprintf(stderr, "%s: PID %d, no space for command name: ", 321 Pn, pid); 322 safestrprt(cmd, stderr, 1); 323 Exit(1); 324 } 325 326#if defined(HASZONES) 327/* 328 * Clear the zone name pointer. The dialect's own code will set it. 329 */ 330 Lp->zn = (char *)NULL; 331#endif /* defined(HASZONES) */ 332 333#if defined(HASSELINUX) 334/* 335 * Clear the security context pointer. The dialect's own code will 336 * set it. 337 */ 338 Lp->cntx = (char *)NULL; 339#endif /* defined(HASSELINUX) */ 340 341} 342 343 344/* 345 * ck_fd_status() - check FD status 346 * 347 * return: 0 == FD is neither included nor excluded 348 * 1 == FD is excluded 349 * 2 == FD is included 350 */ 351 352extern int 353ck_fd_status(nm, num) 354 char *nm; /* file descriptor name (may be NULL) */ 355 int num; /* file descriptor number -- -1 if 356 * none */ 357{ 358 char *cp; 359 struct fd_lst *fp; 360 361 if (!(fp = Fdl) || (!nm && num < 0)) 362 return(0); 363 if ((cp = nm)) { 364 while (*cp && *cp == ' ') 365 cp++; 366 } 367/* 368 * Check for an exclusion match. 369 */ 370 if (FdlTy == 1) { 371 for (; fp; fp = fp->next) { 372 if (cp) { 373 if (fp->nm && strcmp(fp->nm, cp) == 0) 374 return(1); 375 continue; 376 } 377 if (num >= fp->lo && num <= fp->hi) 378 return(1); 379 } 380 return(0); 381 } 382/* 383 * If Fdl isn't an exclusion list, check for an inclusion match. 384 */ 385 for (; fp; fp = fp->next) { 386 if (cp) { 387 if (fp->nm && strcmp(fp->nm, cp) == 0) 388 return(2); 389 continue; 390 } 391 if (num >= fp->lo && num <= fp->hi) 392 return(2); 393 } 394 return(0); 395} 396 397 398/* 399 * comppid() - compare PIDs 400 */ 401 402int 403comppid(a1, a2) 404 COMP_P *a1, *a2; 405{ 406 struct lproc **p1 = (struct lproc **)a1; 407 struct lproc **p2 = (struct lproc **)a2; 408 409 if ((*p1)->pid < (*p2)->pid) 410 return(-1); 411 if ((*p1)->pid > (*p2)->pid) 412 return(1); 413 414#if defined(HASTASKS) 415 if ((*p1)->tid < (*p2)->tid) 416 return(-1); 417 if ((*p1)->tid > (*p2)->tid) 418 return(1); 419#endif /* defined(HASTASKS) */ 420 421 return(0); 422} 423 424 425/* 426 * ent_inaddr() - enter Internet addresses 427 */ 428 429void 430ent_inaddr(la, lp, fa, fp, af) 431 unsigned char *la; /* local Internet address */ 432 int lp; /* local port */ 433 unsigned char *fa; /* foreign Internet address -- may 434 * be NULL to indicate no foreign 435 * address is known */ 436 int fp; /* foreign port */ 437 int af; /* address family -- e.g, AF_INET, 438 * AF_INET */ 439{ 440 int m; 441 442 if (la) { 443 Lf->li[0].af = af; 444 445#if defined(HASIPv6) 446 if (af == AF_INET6) 447 Lf->li[0].ia.a6 = *(struct in6_addr *)la; 448 else 449#endif /* defined(HASIPv6) */ 450 451 Lf->li[0].ia.a4 = *(struct in_addr *)la; 452 Lf->li[0].p = lp; 453 } else 454 Lf->li[0].af = 0; 455 if (fa) { 456 Lf->li[1].af = af; 457 458#if defined(HASIPv6) 459 if (af == AF_INET6) 460 Lf->li[1].ia.a6 = *(struct in6_addr *)fa; 461 else 462#endif /* defined(HASIPv6) */ 463 464 Lf->li[1].ia.a4 = *(struct in_addr *)fa; 465 Lf->li[1].p = fp; 466 } else 467 Lf->li[1].af = 0; 468/* 469 * If network address matching has been selected, check both addresses. 470 */ 471 if ((Selflags & SELNA) && Nwad) { 472 m = (fa && is_nw_addr(fa, fp, af)) ? 1 : 0; 473 m |= (la && is_nw_addr(la, lp, af)) ? 1 : 0; 474 if (m) 475 Lf->sf |= SELNA; 476 } 477} 478 479 480/* 481 * examine_lproc() - examine local process 482 * 483 * return: 1 = last process 484 */ 485 486int 487examine_lproc() 488{ 489 int sbp = 0; 490 491 if (RptTm) 492 return(0); 493/* 494 * List the process if the process is selected and: 495 * 496 * o listing is limited to a single PID selection -- this one; 497 * 498 * o listing is selected by an ANDed option set (not all options) 499 * that includes a single PID selection -- this one. 500 */ 501 if ((Lp->sf & SELPID) && !Selall) { 502 if ((Selflags == SELPID) 503 || (Fand && (Selflags & SELPID))) { 504 sbp = 1; 505 Npuns--; 506 } 507 } 508 if (Lp->pss && Npid == 1 && sbp) { 509 print_init(); 510 (void) print_proc(); 511 PrPass++; 512 if (PrPass < 2) 513 (void) print_proc(); 514 Lp->pss = 0; 515 } 516/* 517 * Deprecate an unselected (or listed) process. 518 */ 519 if ( ! Lp->pss) { 520 (void) free_lproc(Lp); 521 Nlproc--; 522 } 523/* 524 * Indicate last-process if listing is limited to PID selections, 525 * and all selected processes have been listed. 526 */ 527 return((sbp && Npuns == 0) ? 1 : 0); 528} 529 530 531/* 532 * free_lproc() - free lproc entry and its associated malloc'd space 533 */ 534 535void 536free_lproc(lp) 537 struct lproc *lp; 538{ 539 struct lfile *lf, *nf; 540 541 for (lf = lp->file; lf; lf = nf) { 542 if (lf->dev_ch) { 543 (void) free((FREE_P *)lf->dev_ch); 544 lf->dev_ch = (char *)NULL; 545 } 546 if (lf->nm) { 547 (void) free((FREE_P *)lf->nm); 548 lf->nm = (char *)NULL; 549 } 550 if (lf->nma) { 551 (void) free((FREE_P *)lf->nma); 552 lf->nma = (char *)NULL; 553 } 554 555#if defined(HASLFILEADD) && defined(CLRLFILEADD) 556 CLRLFILEADD(lf) 557#endif /* defined(HASLFILEADD) && defined(CLRLFILEADD) */ 558 559 nf = lf->next; 560 (void) free((FREE_P *)lf); 561 } 562 lp->file = (struct lfile *)NULL; 563 if (lp->cmd) { 564 (void) free((FREE_P *)lp->cmd); 565 lp->cmd = (char *)NULL; 566 } 567} 568 569 570/* 571 * is_cmd_excl() - is command excluded? 572 */ 573 574int 575is_cmd_excl(cmd, pss, sf) 576 char *cmd; /* command name */ 577 short *pss; /* process state */ 578 short *sf; /* process select flags */ 579{ 580 int i; 581 struct str_lst *sp; 582/* 583 * See if the command is excluded by a "-c^<command>" option. 584 */ 585 if (Cmdl && Cmdnx) { 586 for (sp = Cmdl; sp; sp = sp->next) { 587 if (sp->x && !strncmp(sp->str, cmd, sp->len)) 588 return(1); 589 } 590 } 591/* 592 * The command is not excluded if no command selection was requested, 593 * or if its name matches any -c <command> specification. 594 * 595 */ 596 if ((Selflags & SELCMD) == 0) 597 return(0); 598 for (sp = Cmdl; sp; sp = sp->next) { 599 if (!sp->x && !strncmp(sp->str, cmd, sp->len)) { 600 sp->f = 1; 601 *pss |= PS_PRI; 602 *sf |= SELCMD; 603 return(0); 604 } 605 } 606/* 607 * The command name doesn't match any -c <command> specification. See if it 608 * matches a -c /RE/[bix] specification. 609 */ 610 for (i = 0; i < NCmdRxU; i++) { 611 if (!regexec(&CmdRx[i].cx, cmd, 0, NULL, 0)) { 612 CmdRx[i].mc = 1; 613 *pss |= PS_PRI; 614 *sf |= SELCMD; 615 return(0); 616 } 617 } 618/* 619 * The command name matches no -c specification. 620 * 621 * It's excluded if the only selection condition is command name, 622 * or if command name selection is part of an ANDed set. 623 */ 624 if (Selflags == SELCMD) 625 return(1); 626 return (Fand ? 1 : 0); 627} 628 629 630/* 631 * is_file_sel() - is file selected? 632 */ 633 634static int 635is_file_sel(lp, lf) 636 struct lproc *lp; /* lproc structure pointer */ 637 struct lfile *lf; /* lfile structure pointer */ 638{ 639 if (!lf || !lf->sf) 640 return(0); 641 if (Lf->sf & SELEXCLF) 642 return(0); 643 644#if defined(HASSECURITY) && defined(HASNOSOCKSECURITY) 645 if (Myuid && (Myuid != lp->uid)) { 646 if (!(lf->sf & (SELNA | SELNET))) 647 return(0); 648 } 649#endif /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */ 650 651 if (Selall) 652 return(1); 653 if (Fand && ((lf->sf & Selflags) != Selflags)) 654 return(0); 655 return(1); 656} 657 658 659/* 660 * is_proc_excl() - is process excluded? 661 */ 662 663int 664 665#if defined(HASTASKS) 666is_proc_excl(pid, pgid, uid, pss, sf, tid) 667#else /* !defined(HASTASKS) */ 668is_proc_excl(pid, pgid, uid, pss, sf) 669#endif /* defined(HASTASKS) */ 670 671 int pid; /* Process ID */ 672 int pgid; /* process group ID */ 673 UID_ARG uid; /* User ID */ 674 short *pss; /* process select state for lproc */ 675 short *sf; /* select flags for lproc */ 676 677#if defined(HASTASKS) 678 int tid; /* task ID (not a task if zero) */ 679#endif /* defined(HASTASKS) */ 680 681{ 682 int i, j; 683 684 *pss = *sf = 0; 685 686#if defined(HASSECURITY) 687/* 688 * The process is excluded by virtue of the security option if it 689 * isn't owned by the owner of this lsof process, unless the 690 * HASNOSOCKSECURITY option is also specified. In that case the 691 * selected socket files of any process may be listed. 692 */ 693# if !defined(HASNOSOCKSECURITY) 694 if (Myuid && Myuid != (uid_t)uid) 695 return(1); 696# endif /* !defined(HASNOSOCKSECURITY) */ 697#endif /* defined(HASSECURITY) */ 698 699/* 700 * If the excluding of process listing by UID has been specified, see if the 701 * owner of this process is excluded. 702 */ 703 if (Nuidexcl) { 704 for (i = j = 0; (i < Nuid) && (j < Nuidexcl); i++) { 705 if (!Suid[i].excl) 706 continue; 707 if (Suid[i].uid == (uid_t)uid) 708 return(1); 709 j++; 710 } 711 } 712/* 713 * If the excluding of process listing by PGID has been specified, see if this 714 * PGID is excluded. 715 */ 716 if (Npgidx) { 717 for (i = j = 0; (i < Npgid) && (j < Npgidx); i++) { 718 if (!Spgid[i].x) 719 continue; 720 if (Spgid[i].i == pgid) 721 return(1); 722 j++; 723 } 724 } 725/* 726 * If the excluding of process listing by PID has been specified, see if this 727 * PID is excluded. 728 */ 729 if (Npidx) { 730 for (i = j = 0; (i < Npid) && (j < Npidx); i++) { 731 if (!Spid[i].x) 732 continue; 733 if (Spid[i].i == pid) 734 return(1); 735 j++; 736 } 737 } 738/* 739 * If the listing of all processes is selected, then this one is not excluded. 740 * 741 * However, if HASSECURITY and HASNOSOCKSECURITY are both specified, exclude 742 * network selections from the file flags, so that the tests in is_file_sel() 743 * work as expected. 744 */ 745 if (Selall) { 746 *pss = PS_PRI; 747 748#if defined(HASSECURITY) && defined(HASNOSOCKSECURITY) 749 *sf = SELALL & ~(SELNA | SELNET); 750#else /* !defined(HASSECURITY) || !defined(HASNOSOCKSECURITY) */ 751 *sf = SELALL; 752#endif /* defined(HASSECURITY) && defined(HASNOSOCKSECURITY) */ 753 754 return(0); 755 } 756/* 757 * If the listing of processes has been specified by process group ID, see 758 * if this one is included or excluded. 759 */ 760 if (Npgidi && (Selflags & SELPGID)) { 761 for (i = j = 0; (i < Npgid) && (j < Npgidi); i++) { 762 if (Spgid[i].x) 763 continue; 764 if (Spgid[i].i == pgid) { 765 Spgid[i].f = 1; 766 *pss = PS_PRI; 767 *sf = SELPGID; 768 if (Selflags == SELPGID) 769 return(0); 770 break; 771 } 772 j++; 773 } 774 if ((Selflags == SELPGID) && !*sf) 775 return(1); 776 } 777/* 778 * If the listing of processes has been specified by PID, see if this one is 779 * included or excluded. 780 */ 781 if (Npidi && (Selflags & SELPID)) { 782 for (i = j = 0; (i < Npid) && (j < Npidi); i++) { 783 if (Spid[i].x) 784 continue; 785 if (Spid[i].i == pid) { 786 Spid[i].f = 1; 787 *pss = PS_PRI; 788 *sf |= SELPID; 789 if (Selflags == SELPID) 790 return(0); 791 break; 792 } 793 j++; 794 } 795 if ((Selflags == SELPID) && !*sf) 796 return(1); 797 } 798/* 799 * If the listing of processes has been specified by UID, see if the owner of 800 * this process has been included. 801 */ 802 if (Nuidincl && (Selflags & SELUID)) { 803 for (i = j = 0; (i < Nuid) && (j < Nuidincl); i++) { 804 if (Suid[i].excl) 805 continue; 806 if (Suid[i].uid == (uid_t)uid) { 807 Suid[i].f = 1; 808 *pss = PS_PRI; 809 *sf |= SELUID; 810 if (Selflags == SELUID) 811 return(0); 812 break; 813 } 814 j++; 815 } 816 if (Selflags == SELUID && (*sf & SELUID) == 0) 817 return(1); 818 } 819 820#if defined(HASTASKS) 821 if ((Selflags & SELTASK) && tid) { 822 823 /* 824 * This is a task and tasks are selected. 825 */ 826 *pss = PS_PRI; 827 *sf |= SELTASK; 828 if ((Selflags == SELTASK) 829 || (Fand && ((*sf & Selflags) == Selflags))) 830 return(0); 831 } 832#endif /* defined(HASTASKS) */ 833 834/* 835 * When neither the process group ID, nor the PID, nor the task, nor the UID 836 * is selected: 837 * 838 * If list option ANDing of process group IDs, PIDs, UIDs or tasks is 839 * specified, the process is excluded; 840 * 841 * Otherwise, it's not excluded by the tests of this function. 842 */ 843 if ( ! *sf) 844 return((Fand && (Selflags & (SELPGID|SELPID|SELUID|SELTASK))) 845 ? 1 : 0); 846/* 847 * When the process group ID, PID, task or UID is selected and the process 848 * group ID, PID, task or UID list option has been specified: 849 * 850 * If list option ANDing has been specified, and the correct 851 * combination of selections are in place, reply that the process is no 852 * excluded; 853 * or 854 * If list option ANDing has not been specified, reply that the 855 * process is not excluded by the tests of this function. 856 */ 857 if (Selflags & (SELPGID|SELPID|SELUID|SELTASK)) { 858 if (Fand) 859 return(((Selflags & (SELPGID|SELPID|SELUID|SELTASK)) != *sf) 860 ? 1 : 0); 861 return(0); 862 } 863/* 864 * Finally, when neither the process group ID, nor the PID, nor the UID, nor 865 * the task is selected, and no applicable list option has been specified: 866 * 867 * If list option ANDing has been specified, this process is 868 * excluded; 869 * 870 * Otherwise, it isn't excluded by the tests of this function. 871 */ 872 return(Fand ? 1 : 0); 873} 874 875 876/* 877 * link_lfile() - link local file structures 878 */ 879 880void 881link_lfile() 882{ 883 if (Lf->sf & SELEXCLF) 884 return; 885 Lp->pss |= PS_SEC; 886 if (Plf) 887 Plf->next = Lf; 888 else 889 Lp->file = Lf; 890 Plf = Lf; 891 if (Fnet && (Lf->sf & SELNET)) 892 Fnet = 2; 893 if (Fnfs && (Lf->sf & SELNFS)) 894 Fnfs = 2; 895 if (Ftask && (Lf->sf & SELTASK)) 896 Ftask = 2; 897 Lf = (struct lfile *)NULL; 898} 899 900 901#if defined(HASFSTRUCT) 902/* 903 * print_fflags() - print interpreted f_flag[s] 904 */ 905 906char * 907print_fflags(ffg, pof) 908 long ffg; /* file structure's flags value */ 909 long pof; /* process open files flags value */ 910{ 911 int al, ct, fx; 912 static int bl = 0; 913 static char *bp = (char *)NULL; 914 char *sep; 915 int sepl; 916 struct pff_tab *tp; 917 long wf; 918 char xbuf[64]; 919/* 920 * Reduce the supplied flags according to the definitions in Pff_tab[] and 921 * Pof_tab[]. 922 */ 923 for (ct = fx = 0; fx < 2; fx++) { 924 if (fx == 0) { 925 sep = ""; 926 sepl = 0; 927 tp = Pff_tab; 928 wf = ffg; 929 } else { 930 sep = ";"; 931 sepl = 1; 932 tp = Pof_tab; 933 wf = pof; 934 } 935 for (; wf && !FsvFlagX; ct += al ) { 936 while (tp->nm) { 937 if (wf & tp->val) 938 break; 939 tp++; 940 } 941 if (!tp->nm) 942 break; 943 al = (int)strlen(tp->nm) + sepl; 944 bp = alloc_fflbuf(&bp, &bl, al + ct); 945 (void) snpf(bp + ct, al + 1, "%s%s", sep, tp->nm); 946 sep = ","; 947 sepl = 1; 948 wf &= ~(tp->val); 949 } 950 /* 951 * If flag bits remain, print them in hex. If hex output was 952 * specified with +fG, print all flag values, including zero, 953 * in hex. 954 */ 955 if (wf || FsvFlagX) { 956 (void) snpf(xbuf, sizeof(xbuf), "0x%lx", wf); 957 al = (int)strlen(xbuf) + sepl; 958 bp = alloc_fflbuf(&bp, &bl, al + ct); 959 (void) snpf(bp + ct, al + 1, "%s%s", sep, xbuf); 960 ct += al; 961 } 962 } 963/* 964 * Make sure there is at least a NUL terminated reply. 965 */ 966 if (!bp) { 967 bp = alloc_fflbuf(&bp, &bl, 0); 968 *bp = '\0'; 969 } 970 return(bp); 971} 972#endif /* defined(HASFSTRUCT) */ 973 974 975/* 976 * print_proc() - print process 977 */ 978 979int 980print_proc() 981{ 982 char buf[128], *cp; 983 int lc, len, st, ty; 984 int rv = 0; 985 unsigned long ul; 986/* 987 * If nothing in the process has been selected, skip it. 988 */ 989 if (!Lp->pss) 990 return(0); 991 if (Fterse) { 992 if (Lp->pid == LastPid) /* eliminate duplicates */ 993 return(0); 994 LastPid = Lp->pid; 995 /* 996 * The mode is terse and something in the process appears to have 997 * been selected. Make sure of that by looking for a selected file, 998 * so that the HASSECURITY and HASNOSOCKSECURITY option combination 999 * won't produce a false positive result. 1000 */ 1001 for (Lf = Lp->file; Lf; Lf = Lf->next) { 1002 if (is_file_sel(Lp, Lf)) { 1003 (void) printf("%d\n", Lp->pid); 1004 return(1); 1005 } 1006 } 1007 return(0); 1008 } 1009/* 1010 * If fields have been selected, output the process-only ones, provided 1011 * that some file has also been selected. 1012 */ 1013 if (Ffield) { 1014 for (Lf = Lp->file; Lf; Lf = Lf->next) { 1015 if (is_file_sel(Lp, Lf)) 1016 break; 1017 } 1018 if (!Lf) 1019 return(rv); 1020 rv = 1; 1021 (void) printf("%c%d%c", LSOF_FID_PID, Lp->pid, Terminator); 1022 1023#if defined(HASTASKS) 1024 if (FieldSel[LSOF_FIX_TID].st && Lp->tid) 1025 (void) printf("%c%d%c", LSOF_FID_TID, Lp->tid, Terminator); 1026#endif /* defined(HASTASKS) */ 1027 1028#if defined(HASZONES) 1029 if (FieldSel[LSOF_FIX_ZONE].st && Fzone && Lp->zn) 1030 (void) printf("%c%s%c", LSOF_FID_ZONE, Lp->zn, Terminator); 1031#endif /* defined(HASZONES) */ 1032 1033#if defined(HASSELINUX) 1034 if (FieldSel[LSOF_FIX_CNTX].st && Fcntx && Lp->cntx && CntxStatus) 1035 (void) printf("%c%s%c", LSOF_FID_CNTX, Lp->cntx, Terminator); 1036#endif /* defined(HASSELINUX) */ 1037 1038 if (FieldSel[LSOF_FIX_PGID].st && Fpgid) 1039 (void) printf("%c%d%c", LSOF_FID_PGID, Lp->pgid, Terminator); 1040 1041#if defined(HASPPID) 1042 if (FieldSel[LSOF_FIX_PPID].st && Fppid) 1043 (void) printf("%c%d%c", LSOF_FID_PPID, Lp->ppid, Terminator); 1044#endif /* defined(HASPPID) */ 1045 1046 if (FieldSel[LSOF_FIX_CMD].st) { 1047 putchar(LSOF_FID_CMD); 1048 safestrprt(Lp->cmd ? Lp->cmd : "(unknown)", stdout, 0); 1049 putchar(Terminator); 1050 } 1051 if (FieldSel[LSOF_FIX_UID].st) 1052 (void) printf("%c%d%c", LSOF_FID_UID, (int)Lp->uid, Terminator); 1053 if (FieldSel[LSOF_FIX_LOGIN].st) { 1054 cp = printuid((UID_ARG)Lp->uid, &ty); 1055 if (ty == 0) 1056 (void) printf("%c%s%c", LSOF_FID_LOGIN, cp, Terminator); 1057 } 1058 if (Terminator == '\0') 1059 putchar('\n'); 1060 } 1061/* 1062 * Print files. 1063 */ 1064 for (Lf = Lp->file; Lf; Lf = Lf->next) { 1065 if (!is_file_sel(Lp, Lf)) 1066 continue; 1067 rv = 1; 1068 /* 1069 * If no field output selected, print dialects-specific formatted 1070 * output. 1071 */ 1072 if (!Ffield) { 1073 print_file(); 1074 continue; 1075 } 1076 /* 1077 * Print selected fields. 1078 */ 1079 lc = st = 0; 1080 if (FieldSel[LSOF_FIX_FD].st) { 1081 for (cp = Lf->fd; *cp == ' '; cp++) 1082 ; 1083 if (*cp) { 1084 (void) printf("%c%s%c", LSOF_FID_FD, cp, Terminator); 1085 lc++; 1086 } 1087 } 1088 if (FieldSel[LSOF_FIX_ACCESS].st) { 1089 (void) printf("%c%c%c", 1090 LSOF_FID_ACCESS, Lf->access, Terminator); 1091 lc++; 1092 } 1093 if (FieldSel[LSOF_FIX_LOCK].st) { 1094 (void) printf("%c%c%c", LSOF_FID_LOCK, Lf->lock, Terminator); 1095 lc++; 1096 } 1097 if (FieldSel[LSOF_FIX_TYPE].st) { 1098 for (cp = Lf->type; *cp == ' '; cp++) 1099 ; 1100 if (*cp) { 1101 (void) printf("%c%s%c", LSOF_FID_TYPE, cp, Terminator); 1102 lc++; 1103 } 1104 } 1105 1106#if defined(HASFSTRUCT) 1107 if (FieldSel[LSOF_FIX_FA].st && (Fsv & FSV_FA) 1108 && (Lf->fsv & FSV_FA)) { 1109 (void) printf("%c%s%c", LSOF_FID_FA, 1110 print_kptr(Lf->fsa, (char *)NULL, 0), Terminator); 1111 lc++; 1112 } 1113 if (FieldSel[LSOF_FIX_CT].st && (Fsv & FSV_CT) 1114 && (Lf->fsv & FSV_CT)) { 1115 (void) printf("%c%ld%c", LSOF_FID_CT, Lf->fct, Terminator); 1116 lc++; 1117 } 1118 if (FieldSel[LSOF_FIX_FG].st && (Fsv & FSV_FG) 1119 && (Lf->fsv & FSV_FG) && (FsvFlagX || Lf->ffg || Lf->pof)) { 1120 (void) printf("%c%s%c", LSOF_FID_FG, 1121 print_fflags(Lf->ffg, Lf->pof), Terminator); 1122 lc++; 1123 } 1124 if (FieldSel[LSOF_FIX_NI].st && (Fsv & FSV_NI) 1125 && (Lf->fsv & FSV_NI)) { 1126 (void) printf("%c%s%c", LSOF_FID_NI, 1127 print_kptr(Lf->fna, (char *)NULL, 0), Terminator); 1128 lc++; 1129 } 1130#endif /* defined(HASFSTRUCT) */ 1131 1132 if (FieldSel[LSOF_FIX_DEVCH].st && Lf->dev_ch && Lf->dev_ch[0]) { 1133 for (cp = Lf->dev_ch; *cp == ' '; cp++) 1134 ; 1135 if (*cp) { 1136 (void) printf("%c%s%c", LSOF_FID_DEVCH, cp, Terminator); 1137 lc++; 1138 } 1139 } 1140 if (FieldSel[LSOF_FIX_DEVN].st && Lf->dev_def) { 1141 if (sizeof(unsigned long) > sizeof(dev_t)) 1142 ul = (unsigned long)((unsigned int)Lf->dev); 1143 else 1144 ul = (unsigned long)Lf->dev; 1145 (void) printf("%c0x%lx%c", LSOF_FID_DEVN, ul, Terminator); 1146 lc++; 1147 } 1148 if (FieldSel[LSOF_FIX_RDEV].st && Lf->rdev_def) { 1149 if (sizeof(unsigned long) > sizeof(dev_t)) 1150 ul = (unsigned long)((unsigned int)Lf->rdev); 1151 else 1152 ul = (unsigned long)Lf->rdev; 1153 (void) printf("%c0x%lx%c", LSOF_FID_RDEV, ul, Terminator); 1154 lc++; 1155 } 1156 if (FieldSel[LSOF_FIX_SIZE].st && Lf->sz_def) { 1157 putchar(LSOF_FID_SIZE); 1158 1159#if defined(HASPRINTSZ) 1160 cp = HASPRINTSZ(Lf); 1161#else /* !defined(HASPRINTSZ) */ 1162 (void) snpf(buf, sizeof(buf), SzOffFmt_d, Lf->sz); 1163 cp = buf; 1164#endif /* defined(HASPRINTSZ) */ 1165 1166 (void) printf("%s", cp); 1167 putchar(Terminator); 1168 lc++; 1169 } 1170 if (FieldSel[LSOF_FIX_OFFSET].st && Lf->off_def) { 1171 putchar(LSOF_FID_OFFSET); 1172 1173#if defined(HASPRINTOFF) 1174 cp = HASPRINTOFF(Lf, 0); 1175#else /* !defined(HASPRINTOFF) */ 1176 (void) snpf(buf, sizeof(buf), SzOffFmt_0t, Lf->off); 1177 cp = buf; 1178#endif /* defined(HASPRINTOFF) */ 1179 1180 len = strlen(cp); 1181 if (OffDecDig && len > (OffDecDig + 2)) { 1182 1183#if defined(HASPRINTOFF) 1184 cp = HASPRINTOFF(Lf, 1); 1185#else /* !defined(HASPRINTOFF) */ 1186 (void) snpf(buf, sizeof(buf), SzOffFmt_x, Lf->off); 1187 cp = buf; 1188#endif /* defined(HASPRINTOFF) */ 1189 1190 } 1191 (void) printf("%s", cp); 1192 putchar(Terminator); 1193 lc++; 1194 } 1195 if (FieldSel[LSOF_FIX_INODE].st && Lf->inp_ty == 1) { 1196 putchar(LSOF_FID_INODE); 1197 (void) printf(InodeFmt_d, Lf->inode); 1198 putchar(Terminator); 1199 lc++; 1200 } 1201 if (FieldSel[LSOF_FIX_NLINK].st && Lf->nlink_def) { 1202 (void) printf("%c%ld%c", LSOF_FID_NLINK, Lf->nlink, Terminator); 1203 lc++; 1204 } 1205 if (FieldSel[LSOF_FIX_PROTO].st && Lf->inp_ty == 2) { 1206 for (cp = Lf->iproto; *cp == ' '; cp++) 1207 ; 1208 if (*cp) { 1209 (void) printf("%c%s%c", LSOF_FID_PROTO, cp, Terminator); 1210 lc++; 1211 } 1212 } 1213 if (FieldSel[LSOF_FIX_STREAM].st && Lf->nm && Lf->is_stream) { 1214 if (strncmp(Lf->nm, "STR:", 4) == 0 1215 || strcmp(Lf->iproto, "STR") == 0) { 1216 putchar(LSOF_FID_STREAM); 1217 printname(0); 1218 putchar(Terminator); 1219 lc++; 1220 st++; 1221 } 1222 } 1223 if (st == 0 && FieldSel[LSOF_FIX_NAME].st) { 1224 putchar(LSOF_FID_NAME); 1225 printname(0); 1226 putchar(Terminator); 1227 lc++; 1228 } 1229 if (Lf->lts.type >= 0 && FieldSel[LSOF_FIX_TCPTPI].st) { 1230 print_tcptpi(0); 1231 lc++; 1232 } 1233 if (Terminator == '\0' && lc) 1234 putchar('\n'); 1235 } 1236 return(rv); 1237} 1238