1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 25 */ 26 /* 27 * Copyright (c) 2017 Joyent, Inc. All Rights reserved. 28 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. 29 */ 30 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <fcntl.h> 35 #include <ctype.h> 36 #include <string.h> 37 #include <signal.h> 38 #include <dirent.h> 39 #include <limits.h> 40 #include <door.h> 41 #include <sys/types.h> 42 #include <sys/socket.h> 43 #include <sys/stat.h> 44 #include <sys/mkdev.h> 45 #include <sys/stropts.h> 46 #include <sys/timod.h> 47 #include <sys/un.h> 48 #include <libproc.h> 49 #include <netinet/in.h> 50 #include <netinet/udp.h> 51 #include <arpa/inet.h> 52 #include <ucred.h> 53 #include <zone.h> 54 55 static char *command; 56 static volatile int interrupt; 57 static int Fflag; 58 static boolean_t nflag = B_FALSE; 59 60 static void intr(int); 61 static void dofcntl(struct ps_prochandle *, const prfdinfo_t *, int, int); 62 static void dosocket(struct ps_prochandle *, const prfdinfo_t *); 63 static void dosocknames(struct ps_prochandle *, const prfdinfo_t *); 64 static void dofifo(struct ps_prochandle *, const prfdinfo_t *); 65 static void show_files(struct ps_prochandle *); 66 static void show_fileflags(int); 67 static void show_door(struct ps_prochandle *, const prfdinfo_t *); 68 69 int 70 main(int argc, char **argv) 71 { 72 int retc = 0; 73 int opt; 74 int errflg = 0; 75 struct ps_prochandle *Pr; 76 77 if ((command = strrchr(argv[0], '/')) != NULL) 78 command++; 79 else 80 command = argv[0]; 81 82 /* options */ 83 while ((opt = getopt(argc, argv, "Fn")) != EOF) { 84 switch (opt) { 85 case 'F': /* force grabbing (no O_EXCL) */ 86 Fflag = PGRAB_FORCE; 87 break; 88 case 'n': 89 nflag = B_TRUE; 90 break; 91 default: 92 errflg = 1; 93 break; 94 } 95 } 96 97 argc -= optind; 98 argv += optind; 99 100 if (errflg || argc <= 0) { 101 (void) fprintf(stderr, "usage:\t%s [-F] { pid | core } ...\n", 102 command); 103 (void) fprintf(stderr, 104 " (report open files of each process)\n"); 105 (void) fprintf(stderr, 106 " -F: force grabbing of the target process\n"); 107 exit(2); 108 } 109 110 /* catch signals from terminal */ 111 if (sigset(SIGHUP, SIG_IGN) == SIG_DFL) 112 (void) sigset(SIGHUP, intr); 113 if (sigset(SIGINT, SIG_IGN) == SIG_DFL) 114 (void) sigset(SIGINT, intr); 115 if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL) 116 (void) sigset(SIGQUIT, intr); 117 (void) sigset(SIGPIPE, intr); 118 (void) sigset(SIGTERM, intr); 119 120 (void) proc_initstdio(); 121 122 123 while (--argc >= 0 && !interrupt) { 124 char *arg; 125 psinfo_t psinfo; 126 pid_t pid; 127 int gret; 128 129 (void) proc_flushstdio(); 130 131 arg = *argv++; 132 133 /* get the specified pid and the psinfo struct */ 134 if ((pid = proc_arg_psinfo(arg, PR_ARG_PIDS, 135 &psinfo, &gret)) == -1) { 136 137 if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_CORES, 138 Fflag, &gret, NULL)) == NULL) { 139 (void) fprintf(stderr, 140 "%s: cannot examine %s: %s\n", 141 command, arg, Pgrab_error(gret)); 142 retc++; 143 continue; 144 } 145 if (proc_arg_psinfo(arg, PR_ARG_ANY, &psinfo, 146 &gret) < 0) { 147 (void) fprintf(stderr, 148 "%s: cannot examine %s: %s\n", 149 command, arg, Pgrab_error(gret)); 150 retc++; 151 Prelease(Pr, 0); 152 continue; 153 } 154 (void) printf("core '%s' of %d:\t%.70s\n", 155 arg, (int)psinfo.pr_pid, psinfo.pr_psargs); 156 157 show_files(Pr); 158 Prelease(Pr, 0); 159 160 } else if ((Pr = Pgrab(pid, Fflag, &gret)) != NULL) { 161 if (Pcreate_agent(Pr) == 0) { 162 proc_unctrl_psinfo(&psinfo); 163 (void) printf("%d:\t%.70s\n", 164 (int)pid, psinfo.pr_psargs); 165 show_files(Pr); 166 Pdestroy_agent(Pr); 167 } else { 168 (void) fprintf(stderr, 169 "%s: cannot control process %d\n", 170 command, (int)pid); 171 retc++; 172 } 173 Prelease(Pr, 0); 174 Pr = NULL; 175 } else { 176 switch (gret) { 177 case G_SYS: 178 proc_unctrl_psinfo(&psinfo); 179 (void) printf("%d:\t%.70s\n", (int)pid, 180 psinfo.pr_psargs); 181 (void) printf(" [system process]\n"); 182 break; 183 default: 184 (void) fprintf(stderr, "%s: %s: %d\n", 185 command, Pgrab_error(gret), (int)pid); 186 retc++; 187 break; 188 } 189 } 190 } 191 192 (void) proc_finistdio(); 193 194 if (interrupt && retc == 0) 195 retc++; 196 return (retc); 197 } 198 199 /* ARGSUSED */ 200 static void 201 intr(int sig) 202 { 203 interrupt = 1; 204 } 205 206 /* ------ begin specific code ------ */ 207 208 209 static int 210 show_file(void *data, const prfdinfo_t *info) 211 { 212 struct ps_prochandle *Pr = data; 213 char unknown[12]; 214 const char *path; 215 char *s; 216 mode_t mode; 217 218 if (interrupt) 219 return (1); 220 221 mode = info->pr_mode; 222 223 switch (mode & S_IFMT) { 224 case S_IFCHR: s = "S_IFCHR"; break; 225 case S_IFBLK: s = "S_IFBLK"; break; 226 case S_IFIFO: s = "S_IFIFO"; break; 227 case S_IFDIR: s = "S_IFDIR"; break; 228 case S_IFREG: s = "S_IFREG"; break; 229 case S_IFLNK: s = "S_IFLNK"; break; 230 case S_IFSOCK: s = "S_IFSOCK"; break; 231 case S_IFDOOR: s = "S_IFDOOR"; break; 232 case S_IFPORT: s = "S_IFPORT"; break; 233 default: 234 s = unknown; 235 (void) sprintf(s, "0x%.4x ", (int)mode & S_IFMT); 236 break; 237 } 238 239 (void) printf("%4d: %s mode:0%.3o", info->pr_fd, s, 240 (int)mode & ~S_IFMT); 241 242 (void) printf(" dev:%u,%u", 243 (unsigned)info->pr_major, (unsigned)info->pr_minor); 244 245 if ((mode & S_IFMT) == S_IFPORT) { 246 (void) printf(" uid:%d gid:%d", 247 (int)info->pr_uid, (int)info->pr_gid); 248 (void) printf(" size:%lld\n", (longlong_t)info->pr_size); 249 return (0); 250 } 251 252 (void) printf(" ino:%llu uid:%d gid:%d", 253 (u_longlong_t)info->pr_ino, (int)info->pr_uid, (int)info->pr_gid); 254 255 if ((info->pr_rmajor == (major_t)NODEV) && 256 (info->pr_rminor == (minor_t)NODEV)) 257 (void) printf(" size:%lld\n", (longlong_t)info->pr_size); 258 else 259 (void) printf(" rdev:%u,%u\n", 260 (unsigned)info->pr_rmajor, (unsigned)info->pr_rminor); 261 262 path = proc_fdinfo_misc(info, PR_PATHNAME, NULL); 263 264 if (!nflag) { 265 dofcntl(Pr, info, 266 (mode & (S_IFMT|S_ENFMT|S_IXGRP)) == (S_IFREG|S_ENFMT), 267 (mode & S_IFMT) == S_IFDOOR); 268 269 if (Pstate(Pr) != PS_DEAD) { 270 switch (mode & S_IFMT) { 271 case S_IFSOCK: 272 dosocket(Pr, info); 273 break; 274 case S_IFIFO: 275 dofifo(Pr, info); 276 break; 277 case S_IFCHR: 278 /* 279 * This may be a TLI endpoint. If so, it will 280 * have socket names in the fdinfo and this 281 * will print them. 282 */ 283 dosocknames(Pr, info); 284 break; 285 } 286 } 287 288 if (path != NULL) 289 (void) printf(" %s\n", path); 290 291 if (info->pr_offset != -1) { 292 (void) printf(" offset:%lld\n", 293 (long long)info->pr_offset); 294 } 295 } 296 297 return (0); 298 } 299 300 static void 301 show_files(struct ps_prochandle *Pr) 302 { 303 struct rlimit rlim; 304 305 if (pr_getrlimit(Pr, RLIMIT_NOFILE, &rlim) == 0) { 306 ulong_t nfd = rlim.rlim_cur; 307 if (nfd == RLIM_INFINITY) 308 (void) printf( 309 " Current rlimit: unlimited file descriptors\n"); 310 else 311 (void) printf( 312 " Current rlimit: %lu file descriptors\n", nfd); 313 } 314 315 (void) Pfdinfo_iter(Pr, show_file, Pr); 316 } 317 318 /* examine open file with fcntl() */ 319 static void 320 dofcntl(struct ps_prochandle *Pr, const prfdinfo_t *info, int mandatory, 321 int isdoor) 322 { 323 int fileflags; 324 int fdflags; 325 326 fileflags = info->pr_fileflags; 327 fdflags = info->pr_fdflags; 328 329 if (fileflags != -1 || fdflags != -1) { 330 (void) printf(" "); 331 if (fileflags != -1) 332 show_fileflags(fileflags); 333 if (fdflags != -1 && (fdflags & FD_CLOEXEC)) 334 (void) printf(" FD_CLOEXEC"); 335 if (isdoor && (Pstate(Pr) != PS_DEAD)) 336 show_door(Pr, info); 337 (void) fputc('\n', stdout); 338 } else if (isdoor && (Pstate(Pr) != PS_DEAD)) { 339 (void) printf(" "); 340 show_door(Pr, info); 341 (void) fputc('\n', stdout); 342 } 343 344 if (Pstate(Pr) != PS_DEAD) { 345 if (info->pr_locktype != F_UNLCK && 346 (info->pr_locksysid != -1 || info->pr_lockpid != -1)) { 347 unsigned long sysid = info->pr_locksysid; 348 349 (void) printf(" %s %s lock set", 350 mandatory ? "mandatory" : "advisory", 351 info->pr_locktype == F_RDLCK? "read" : "write"); 352 if (sysid) 353 (void) printf(" by system 0x%lX", sysid); 354 if (info->pr_lockpid != -1) 355 (void) printf(" by process %d", 356 (int)info->pr_lockpid); 357 (void) fputc('\n', stdout); 358 } 359 } 360 } 361 362 #define ALL_O_FLAGS O_ACCMODE | O_NDELAY | O_NONBLOCK | O_APPEND | \ 363 O_SYNC | O_DSYNC | O_RSYNC | O_XATTR | \ 364 O_CREAT | O_TRUNC | O_EXCL | O_NOCTTY | O_LARGEFILE 365 366 static void 367 show_fileflags(int flags) 368 { 369 char buffer[136]; 370 char *str = buffer; 371 372 switch (flags & O_ACCMODE) { 373 case O_RDONLY: 374 (void) strcpy(str, "O_RDONLY"); 375 break; 376 case O_WRONLY: 377 (void) strcpy(str, "O_WRONLY"); 378 break; 379 case O_RDWR: 380 (void) strcpy(str, "O_RDWR"); 381 break; 382 case O_SEARCH: 383 (void) strcpy(str, "O_SEARCH"); 384 break; 385 case O_EXEC: 386 (void) strcpy(str, "O_EXEC"); 387 break; 388 default: 389 (void) sprintf(str, "0x%x", flags & O_ACCMODE); 390 break; 391 } 392 393 if (flags & O_NDELAY) 394 (void) strcat(str, "|O_NDELAY"); 395 if (flags & O_NONBLOCK) 396 (void) strcat(str, "|O_NONBLOCK"); 397 if (flags & O_APPEND) 398 (void) strcat(str, "|O_APPEND"); 399 if (flags & O_SYNC) 400 (void) strcat(str, "|O_SYNC"); 401 if (flags & O_DSYNC) 402 (void) strcat(str, "|O_DSYNC"); 403 if (flags & O_RSYNC) 404 (void) strcat(str, "|O_RSYNC"); 405 if (flags & O_CREAT) 406 (void) strcat(str, "|O_CREAT"); 407 if (flags & O_TRUNC) 408 (void) strcat(str, "|O_TRUNC"); 409 if (flags & O_EXCL) 410 (void) strcat(str, "|O_EXCL"); 411 if (flags & O_NOCTTY) 412 (void) strcat(str, "|O_NOCTTY"); 413 if (flags & O_LARGEFILE) 414 (void) strcat(str, "|O_LARGEFILE"); 415 if (flags & O_XATTR) 416 (void) strcat(str, "|O_XATTR"); 417 if (flags & ~(ALL_O_FLAGS)) 418 (void) sprintf(str + strlen(str), "|0x%x", 419 flags & ~(ALL_O_FLAGS)); 420 421 (void) printf("%s", str); 422 } 423 424 /* show process on the other end of a door, socket or fifo */ 425 static void 426 show_peer_process(pid_t ppid) 427 { 428 psinfo_t psinfo; 429 430 if (proc_get_psinfo(ppid, &psinfo) == 0) 431 (void) printf(" %s[%d]", psinfo.pr_fname, (int)ppid); 432 else 433 (void) printf(" pid %d", (int)ppid); 434 } 435 436 /* show door info */ 437 static void 438 show_door(struct ps_prochandle *Pr, const prfdinfo_t *info) 439 { 440 door_info_t door_info; 441 442 if (pr_door_info(Pr, info->pr_fd, &door_info) != 0) 443 return; 444 445 (void) printf(" door to"); 446 show_peer_process(door_info.di_target); 447 } 448 449 /* 450 * Print out the socket address pointed to by `sa'. `len' is only 451 * needed for AF_UNIX sockets. 452 */ 453 static void 454 show_sockaddr(const char *str, const struct sockaddr *sa, socklen_t len) 455 { 456 struct sockaddr_in *so_in = (struct sockaddr_in *)(void *)sa; 457 struct sockaddr_in6 *so_in6 = (struct sockaddr_in6 *)(void *)sa; 458 struct sockaddr_un *so_un = (struct sockaddr_un *)sa; 459 char abuf[INET6_ADDRSTRLEN]; 460 const char *p; 461 462 if (len == 0) 463 return; 464 465 switch (sa->sa_family) { 466 default: 467 return; 468 case AF_INET: 469 (void) printf("\t%s: AF_INET %s port: %u\n", str, 470 inet_ntop(AF_INET, &so_in->sin_addr, abuf, sizeof (abuf)), 471 ntohs(so_in->sin_port)); 472 return; 473 case AF_INET6: 474 (void) printf("\t%s: AF_INET6 %s port: %u\n", str, 475 inet_ntop(AF_INET6, &so_in6->sin6_addr, 476 abuf, sizeof (abuf)), 477 ntohs(so_in->sin_port)); 478 return; 479 case AF_UNIX: 480 if (len >= sizeof (so_un->sun_family)) { 481 (void) printf("\t%s: AF_UNIX %.*s\n", 482 str, len - sizeof (so_un->sun_family), 483 so_un->sun_path); 484 } 485 return; 486 case AF_IMPLINK: p = "AF_IMPLINK"; break; 487 case AF_PUP: p = "AF_PUP"; break; 488 case AF_CHAOS: p = "AF_CHAOS"; break; 489 case AF_NS: p = "AF_NS"; break; 490 case AF_NBS: p = "AF_NBS"; break; 491 case AF_ECMA: p = "AF_ECMA"; break; 492 case AF_DATAKIT: p = "AF_DATAKIT"; break; 493 case AF_CCITT: p = "AF_CCITT"; break; 494 case AF_SNA: p = "AF_SNA"; break; 495 case AF_DECnet: p = "AF_DECnet"; break; 496 case AF_DLI: p = "AF_DLI"; break; 497 case AF_LAT: p = "AF_LAT"; break; 498 case AF_HYLINK: p = "AF_HYLINK"; break; 499 case AF_APPLETALK: p = "AF_APPLETALK"; break; 500 case AF_NIT: p = "AF_NIT"; break; 501 case AF_802: p = "AF_802"; break; 502 case AF_OSI: p = "AF_OSI"; break; 503 case AF_X25: p = "AF_X25"; break; 504 case AF_OSINET: p = "AF_OSINET"; break; 505 case AF_GOSIP: p = "AF_GOSIP"; break; 506 case AF_IPX: p = "AF_IPX"; break; 507 case AF_ROUTE: p = "AF_ROUTE"; break; 508 case AF_KEY: p = "AF_KEY"; break; 509 case AF_POLICY: p = "AF_POLICY"; break; 510 case AF_LINK: p = "AF_LINK"; break; 511 } 512 513 (void) printf("\t%s: %s\n", str, p); 514 } 515 516 /* 517 * Print out the process information for the other end of local sockets 518 * and fifos 519 */ 520 static void 521 show_ucred(const char *str, ucred_t *cred) 522 { 523 pid_t upid = ucred_getpid(cred); 524 zoneid_t uzid = ucred_getzoneid(cred); 525 char zonename[ZONENAME_MAX]; 526 527 if ((upid != -1) || (uzid != -1)) { 528 (void) printf("\t%s:", str); 529 if (upid != -1) { 530 show_peer_process(upid); 531 } 532 if (uzid != -1) { 533 if (getzonenamebyid(uzid, zonename, sizeof (zonename)) 534 != -1) { 535 (void) printf(" zone: %s[%d]", zonename, 536 (int)uzid); 537 } else { 538 (void) printf(" zoneid: %d", (int)uzid); 539 } 540 } 541 (void) printf("\n"); 542 } 543 } 544 545 static void 546 show_socktype(uint_t type) 547 { 548 static const char *types[] = { 549 NULL, "DGRAM", "STREAM", NULL, "RAW", "RDM", "SEQPACKET" 550 }; 551 552 if (type < sizeof (types) / sizeof (*types) && types[type] != NULL) 553 (void) printf("\tSOCK_%s\n", types[type]); 554 else 555 (void) printf("\tunknown socket type %u\n", type); 556 } 557 558 #define BUFSIZE 200 559 static void 560 show_sockopts(struct ps_prochandle *Pr, const prfdinfo_t *info) 561 { 562 const int *val; 563 size_t vlen; 564 char buf[BUFSIZE]; 565 char buf1[32]; 566 char ipaddr[INET_ADDRSTRLEN]; 567 int i; 568 const in_addr_t *nexthop_val; 569 const prsockopts_bool_opts_t *opts; 570 struct boolopt { 571 int opt; 572 const char *name; 573 }; 574 static struct boolopt boolopts[] = { 575 { PR_SO_DEBUG, "SO_DEBUG," }, 576 { PR_SO_REUSEADDR, "SO_REUSEADDR," }, 577 { PR_SO_KEEPALIVE, "SO_KEEPALIVE," }, 578 { PR_SO_DONTROUTE, "SO_DONTROUTE," }, 579 { PR_SO_BROADCAST, "SO_BROADCAST," }, 580 { PR_SO_OOBINLINE, "SO_OOBINLINE," }, 581 { PR_SO_DGRAM_ERRIND, "SO_DGRAM_ERRIND,"}, 582 { PR_SO_ALLZONES, "SO_ALLZONES," }, 583 { PR_SO_MAC_EXEMPT, "SO_MAC_EXEMPT," }, 584 { PR_SO_MAC_IMPLICIT, "SO_MAC_IMPLICIT," }, 585 { PR_SO_EXCLBIND, "SO_EXCLBIND," }, 586 { PR_SO_VRRP, "SO_VRRP," }, 587 { PR_UDP_NAT_T_ENDPOINT, "UDP_NAT_T_ENDPOINT," }, 588 }; 589 const struct linger *l; 590 591 opts = proc_fdinfo_misc(info, PR_SOCKOPTS_BOOL_OPTS, NULL); 592 593 buf[0] = '!'; /* sentinel value, never printed */ 594 buf[1] = '\0'; 595 596 for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]); i++) { 597 if (opts != NULL && opts->prsock_bool_opts & boolopts[i].opt) 598 (void) strlcat(buf, boolopts[i].name, sizeof (buf)); 599 } 600 601 l = proc_fdinfo_misc(info, PR_SOCKOPT_LINGER, NULL); 602 if (l != NULL && l->l_onoff != 0) { 603 (void) snprintf(buf1, sizeof (buf1), "SO_LINGER(%d),", 604 l->l_linger); 605 (void) strlcat(buf, buf1, sizeof (buf)); 606 } 607 608 val = proc_fdinfo_misc(info, PR_SOCKOPT_SNDBUF, NULL); 609 if (val != NULL) { 610 (void) snprintf(buf1, sizeof (buf1), "SO_SNDBUF(%d),", *val); 611 (void) strlcat(buf, buf1, sizeof (buf)); 612 } 613 614 val = proc_fdinfo_misc(info, PR_SOCKOPT_RCVBUF, NULL); 615 if (val != NULL) { 616 (void) snprintf(buf1, sizeof (buf1), "SO_RCVBUF(%d),", *val); 617 (void) strlcat(buf, buf1, sizeof (buf)); 618 } 619 620 621 nexthop_val = proc_fdinfo_misc(info, PR_SOCKOPT_IP_NEXTHOP, &vlen); 622 if (nexthop_val != NULL && vlen > 0) { 623 (void) inet_ntop(AF_INET, (void *) nexthop_val, 624 ipaddr, sizeof (ipaddr)); 625 (void) snprintf(buf1, sizeof (buf1), "IP_NEXTHOP(%s),", 626 ipaddr); 627 (void) strlcat(buf, buf1, sizeof (buf)); 628 } 629 630 buf[strlen(buf) - 1] = '\0'; /* overwrites sentinel if no options */ 631 if (buf[1] != '\0') 632 (void) printf("\t%s\n", buf+1); 633 } 634 635 #define MAXNALLOC 32 636 static void 637 show_sockfilters(struct ps_prochandle *Pr, const prfdinfo_t *info) 638 { 639 struct fil_info *fi; 640 int i = 0, nalloc = 2, len = nalloc * sizeof (*fi); 641 boolean_t printhdr = B_TRUE; 642 int fd = info->pr_fd; 643 644 fi = calloc(nalloc, sizeof (*fi)); 645 if (fi == NULL) { 646 perror("calloc"); 647 return; 648 } 649 /* CONSTCOND */ 650 while (1) { 651 if (pr_getsockopt(Pr, fd, SOL_FILTER, FIL_LIST, fi, &len) != 0) 652 break; 653 /* No filters */ 654 if (len == 0) 655 break; 656 /* Make sure buffer was large enough */ 657 if (fi->fi_pos >= nalloc) { 658 struct fil_info *new; 659 660 nalloc = fi->fi_pos + 1; 661 if (nalloc > MAXNALLOC) 662 break; 663 len = nalloc * sizeof (*fi); 664 new = realloc(fi, nalloc * sizeof (*fi)); 665 if (new == NULL) { 666 perror("realloc"); 667 break; 668 } 669 fi = new; 670 continue; 671 } 672 673 for (i = 0; (i + 1) * sizeof (*fi) <= len; i++) { 674 if (fi[i].fi_flags & FILF_BYPASS) 675 continue; 676 if (printhdr) { 677 (void) printf("\tfilters: "); 678 printhdr = B_FALSE; 679 } 680 (void) printf("%s", fi[i].fi_name); 681 if (fi[i].fi_flags != 0) { 682 (void) printf("("); 683 if (fi[i].fi_flags & FILF_AUTO) 684 (void) printf("auto,"); 685 if (fi[i].fi_flags & FILF_PROG) 686 (void) printf("prog,"); 687 (void) printf("\b)"); 688 } 689 if (fi[i].fi_pos == 0) /* last one */ 690 break; 691 (void) printf(","); 692 } 693 if (!printhdr) 694 (void) printf("\n"); 695 break; 696 } 697 free(fi); 698 } 699 700 /* print peer credentials for sockets and named pipes */ 701 static void 702 dopeerucred(struct ps_prochandle *Pr, const prfdinfo_t *info) 703 { 704 ucred_t *peercred = NULL; /* allocated by getpeerucred */ 705 706 if (pr_getpeerucred(Pr, info->pr_fd, &peercred) == 0) { 707 show_ucred("peer", peercred); 708 ucred_free(peercred); 709 } 710 } 711 712 static void 713 dosocknames(struct ps_prochandle *Pr, const prfdinfo_t *info) 714 { 715 const struct sockaddr *sa; 716 size_t vlen; 717 718 sa = proc_fdinfo_misc(info, PR_SOCKETNAME, &vlen); 719 if (sa != NULL) 720 show_sockaddr("sockname", sa, vlen); 721 722 sa = proc_fdinfo_misc(info, PR_PEERSOCKNAME, &vlen); 723 if (sa != NULL) 724 show_sockaddr("peername", sa, vlen); 725 } 726 727 /* the file is a socket */ 728 static void 729 dosocket(struct ps_prochandle *Pr, const prfdinfo_t *info) 730 { 731 const int *type; 732 733 type = proc_fdinfo_misc(info, PR_SOCKOPT_TYPE, NULL); 734 if (type != NULL) 735 show_socktype((uint_t)*type); 736 737 show_sockopts(Pr, info); 738 show_sockfilters(Pr, info); 739 dosocknames(Pr, info); 740 dopeerucred(Pr, info); 741 } 742 743 /* the file is a fifo (aka "named pipe") */ 744 static void 745 dofifo(struct ps_prochandle *Pr, const prfdinfo_t *info) 746 { 747 dopeerucred(Pr, info); 748 } 749