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