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 static int 209 show_paths(uint_t type, const void *data, size_t len, void *arg __unused) 210 { 211 if (type == PR_PATHNAME) 212 (void) printf(" %.*s\n", len, data); 213 return (0); 214 } 215 216 static int 217 show_file(void *data, const prfdinfo_t *info) 218 { 219 struct ps_prochandle *Pr = data; 220 char unknown[12]; 221 char *s; 222 mode_t mode; 223 224 if (interrupt) 225 return (1); 226 227 mode = info->pr_mode; 228 229 switch (mode & S_IFMT) { 230 case S_IFCHR: s = "S_IFCHR"; break; 231 case S_IFBLK: s = "S_IFBLK"; break; 232 case S_IFIFO: s = "S_IFIFO"; break; 233 case S_IFDIR: s = "S_IFDIR"; break; 234 case S_IFREG: s = "S_IFREG"; break; 235 case S_IFLNK: s = "S_IFLNK"; break; 236 case S_IFSOCK: s = "S_IFSOCK"; break; 237 case S_IFDOOR: s = "S_IFDOOR"; break; 238 case S_IFPORT: s = "S_IFPORT"; break; 239 default: 240 s = unknown; 241 (void) sprintf(s, "0x%.4x ", (int)mode & S_IFMT); 242 break; 243 } 244 245 (void) printf("%4d: %s mode:0%.3o", info->pr_fd, s, 246 (int)mode & ~S_IFMT); 247 248 (void) printf(" dev:%u,%u", 249 (unsigned)info->pr_major, (unsigned)info->pr_minor); 250 251 if ((mode & S_IFMT) == S_IFPORT) { 252 (void) printf(" uid:%d gid:%d", 253 (int)info->pr_uid, (int)info->pr_gid); 254 (void) printf(" size:%lld\n", (longlong_t)info->pr_size); 255 return (0); 256 } 257 258 (void) printf(" ino:%llu uid:%d gid:%d", 259 (u_longlong_t)info->pr_ino, (int)info->pr_uid, (int)info->pr_gid); 260 261 if ((info->pr_rmajor == (major_t)NODEV) && 262 (info->pr_rminor == (minor_t)NODEV)) 263 (void) printf(" size:%lld\n", (longlong_t)info->pr_size); 264 else 265 (void) printf(" rdev:%u,%u\n", 266 (unsigned)info->pr_rmajor, (unsigned)info->pr_rminor); 267 268 if (!nflag) { 269 dofcntl(Pr, info, 270 (mode & (S_IFMT|S_ENFMT|S_IXGRP)) == (S_IFREG|S_ENFMT), 271 (mode & S_IFMT) == S_IFDOOR); 272 273 if (Pstate(Pr) != PS_DEAD) { 274 switch (mode & S_IFMT) { 275 case S_IFSOCK: 276 dosocket(Pr, info); 277 break; 278 case S_IFIFO: 279 dofifo(Pr, info); 280 break; 281 case S_IFCHR: 282 /* 283 * This may be a TLI endpoint. If so, it will 284 * have socket names in the fdinfo and this 285 * will print them. 286 */ 287 dosocknames(Pr, info); 288 break; 289 } 290 } 291 292 (void) proc_fdinfowalk(info, show_paths, NULL); 293 294 if (info->pr_offset != -1) { 295 (void) printf(" offset:%lld\n", 296 (long long)info->pr_offset); 297 } 298 } 299 300 return (0); 301 } 302 303 static void 304 show_files(struct ps_prochandle *Pr) 305 { 306 struct rlimit rlim; 307 308 if (pr_getrlimit(Pr, RLIMIT_NOFILE, &rlim) == 0) { 309 ulong_t nfd = rlim.rlim_cur; 310 if (nfd == RLIM_INFINITY) 311 (void) printf( 312 " Current rlimit: unlimited file descriptors\n"); 313 else 314 (void) printf( 315 " Current rlimit: %lu file descriptors\n", nfd); 316 } 317 318 (void) Pfdinfo_iter(Pr, show_file, Pr); 319 } 320 321 /* examine open file with fcntl() */ 322 static void 323 dofcntl(struct ps_prochandle *Pr, const prfdinfo_t *info, int mandatory, 324 int isdoor) 325 { 326 int fileflags; 327 int fdflags; 328 329 fileflags = info->pr_fileflags; 330 fdflags = info->pr_fdflags; 331 332 if (fileflags != -1 || fdflags != -1) { 333 (void) printf(" "); 334 if (fileflags != -1) 335 show_fileflags(fileflags); 336 if (fdflags != -1 && (fdflags & FD_CLOEXEC)) 337 (void) printf(" FD_CLOEXEC"); 338 if (isdoor && (Pstate(Pr) != PS_DEAD)) 339 show_door(Pr, info); 340 (void) fputc('\n', stdout); 341 } else if (isdoor && (Pstate(Pr) != PS_DEAD)) { 342 (void) printf(" "); 343 show_door(Pr, info); 344 (void) fputc('\n', stdout); 345 } 346 347 if (Pstate(Pr) != PS_DEAD) { 348 if (info->pr_locktype != F_UNLCK && 349 (info->pr_locksysid != -1 || info->pr_lockpid != -1)) { 350 unsigned long sysid = info->pr_locksysid; 351 352 (void) printf(" %s %s lock set", 353 mandatory ? "mandatory" : "advisory", 354 info->pr_locktype == F_RDLCK? "read" : "write"); 355 if (sysid) 356 (void) printf(" by system 0x%lX", sysid); 357 if (info->pr_lockpid != -1) 358 (void) printf(" by process %d", 359 (int)info->pr_lockpid); 360 (void) fputc('\n', stdout); 361 } 362 } 363 } 364 365 #define ALL_O_FLAGS O_ACCMODE | O_NDELAY | O_NONBLOCK | O_APPEND | \ 366 O_SYNC | O_DSYNC | O_RSYNC | O_XATTR | \ 367 O_CREAT | O_TRUNC | O_EXCL | O_NOCTTY | O_LARGEFILE 368 369 static void 370 show_fileflags(int flags) 371 { 372 char buffer[136]; 373 char *str = buffer; 374 375 switch (flags & O_ACCMODE) { 376 case O_RDONLY: 377 (void) strcpy(str, "O_RDONLY"); 378 break; 379 case O_WRONLY: 380 (void) strcpy(str, "O_WRONLY"); 381 break; 382 case O_RDWR: 383 (void) strcpy(str, "O_RDWR"); 384 break; 385 case O_SEARCH: 386 (void) strcpy(str, "O_SEARCH"); 387 break; 388 case O_EXEC: 389 (void) strcpy(str, "O_EXEC"); 390 break; 391 default: 392 (void) sprintf(str, "0x%x", flags & O_ACCMODE); 393 break; 394 } 395 396 if (flags & O_NDELAY) 397 (void) strcat(str, "|O_NDELAY"); 398 if (flags & O_NONBLOCK) 399 (void) strcat(str, "|O_NONBLOCK"); 400 if (flags & O_APPEND) 401 (void) strcat(str, "|O_APPEND"); 402 if (flags & O_SYNC) 403 (void) strcat(str, "|O_SYNC"); 404 if (flags & O_DSYNC) 405 (void) strcat(str, "|O_DSYNC"); 406 if (flags & O_RSYNC) 407 (void) strcat(str, "|O_RSYNC"); 408 if (flags & O_CREAT) 409 (void) strcat(str, "|O_CREAT"); 410 if (flags & O_TRUNC) 411 (void) strcat(str, "|O_TRUNC"); 412 if (flags & O_EXCL) 413 (void) strcat(str, "|O_EXCL"); 414 if (flags & O_NOCTTY) 415 (void) strcat(str, "|O_NOCTTY"); 416 if (flags & O_LARGEFILE) 417 (void) strcat(str, "|O_LARGEFILE"); 418 if (flags & O_XATTR) 419 (void) strcat(str, "|O_XATTR"); 420 if (flags & ~(ALL_O_FLAGS)) 421 (void) sprintf(str + strlen(str), "|0x%x", 422 flags & ~(ALL_O_FLAGS)); 423 424 (void) printf("%s", str); 425 } 426 427 /* show process on the other end of a door, socket or fifo */ 428 static void 429 show_peer_process(pid_t ppid) 430 { 431 psinfo_t psinfo; 432 433 if (proc_get_psinfo(ppid, &psinfo) == 0) 434 (void) printf(" %s[%d]", psinfo.pr_fname, (int)ppid); 435 else 436 (void) printf(" pid %d", (int)ppid); 437 } 438 439 /* show door info */ 440 static void 441 show_door(struct ps_prochandle *Pr, const prfdinfo_t *info) 442 { 443 door_info_t door_info; 444 445 if (pr_door_info(Pr, info->pr_fd, &door_info) != 0) 446 return; 447 448 (void) printf(" door to"); 449 show_peer_process(door_info.di_target); 450 } 451 452 /* 453 * Print out the socket address pointed to by `sa'. `len' is only 454 * needed for AF_UNIX sockets. 455 */ 456 static void 457 show_sockaddr(const char *str, const struct sockaddr *sa, socklen_t len) 458 { 459 struct sockaddr_in *so_in = (struct sockaddr_in *)(void *)sa; 460 struct sockaddr_in6 *so_in6 = (struct sockaddr_in6 *)(void *)sa; 461 struct sockaddr_un *so_un = (struct sockaddr_un *)sa; 462 char abuf[INET6_ADDRSTRLEN]; 463 const char *p; 464 465 if (len == 0) 466 return; 467 468 switch (sa->sa_family) { 469 default: 470 return; 471 case AF_INET: 472 (void) printf("\t%s: AF_INET %s port: %u\n", str, 473 inet_ntop(AF_INET, &so_in->sin_addr, abuf, sizeof (abuf)), 474 ntohs(so_in->sin_port)); 475 return; 476 case AF_INET6: 477 (void) printf("\t%s: AF_INET6 %s port: %u\n", str, 478 inet_ntop(AF_INET6, &so_in6->sin6_addr, 479 abuf, sizeof (abuf)), 480 ntohs(so_in->sin_port)); 481 return; 482 case AF_UNIX: 483 if (len >= sizeof (so_un->sun_family)) { 484 (void) printf("\t%s: AF_UNIX %.*s\n", 485 str, len - sizeof (so_un->sun_family), 486 so_un->sun_path); 487 } 488 return; 489 case AF_IMPLINK: p = "AF_IMPLINK"; break; 490 case AF_PUP: p = "AF_PUP"; break; 491 case AF_CHAOS: p = "AF_CHAOS"; break; 492 case AF_NS: p = "AF_NS"; break; 493 case AF_NBS: p = "AF_NBS"; break; 494 case AF_ECMA: p = "AF_ECMA"; break; 495 case AF_DATAKIT: p = "AF_DATAKIT"; break; 496 case AF_CCITT: p = "AF_CCITT"; break; 497 case AF_SNA: p = "AF_SNA"; break; 498 case AF_DECnet: p = "AF_DECnet"; break; 499 case AF_DLI: p = "AF_DLI"; break; 500 case AF_LAT: p = "AF_LAT"; break; 501 case AF_HYLINK: p = "AF_HYLINK"; break; 502 case AF_APPLETALK: p = "AF_APPLETALK"; break; 503 case AF_NIT: p = "AF_NIT"; break; 504 case AF_802: p = "AF_802"; break; 505 case AF_OSI: p = "AF_OSI"; break; 506 case AF_X25: p = "AF_X25"; break; 507 case AF_OSINET: p = "AF_OSINET"; break; 508 case AF_GOSIP: p = "AF_GOSIP"; break; 509 case AF_IPX: p = "AF_IPX"; break; 510 case AF_ROUTE: p = "AF_ROUTE"; break; 511 case AF_KEY: p = "AF_KEY"; break; 512 case AF_POLICY: p = "AF_POLICY"; break; 513 case AF_LINK: p = "AF_LINK"; break; 514 } 515 516 (void) printf("\t%s: %s\n", str, p); 517 } 518 519 /* 520 * Print out the process information for the other end of local sockets 521 * and fifos 522 */ 523 static void 524 show_ucred(const char *str, ucred_t *cred) 525 { 526 pid_t upid = ucred_getpid(cred); 527 zoneid_t uzid = ucred_getzoneid(cred); 528 char zonename[ZONENAME_MAX]; 529 530 if ((upid != -1) || (uzid != -1)) { 531 (void) printf("\t%s:", str); 532 if (upid != -1) { 533 show_peer_process(upid); 534 } 535 if (uzid != -1) { 536 if (getzonenamebyid(uzid, zonename, sizeof (zonename)) 537 != -1) { 538 (void) printf(" zone: %s[%d]", zonename, 539 (int)uzid); 540 } else { 541 (void) printf(" zoneid: %d", (int)uzid); 542 } 543 } 544 (void) printf("\n"); 545 } 546 } 547 548 static void 549 show_socktype(uint_t type) 550 { 551 static const char *types[] = { 552 NULL, "DGRAM", "STREAM", NULL, "RAW", "RDM", "SEQPACKET" 553 }; 554 555 if (type < sizeof (types) / sizeof (*types) && types[type] != NULL) 556 (void) printf("\tSOCK_%s\n", types[type]); 557 else 558 (void) printf("\tunknown socket type %u\n", type); 559 } 560 561 #define BUFSIZE 200 562 static void 563 show_sockopts(struct ps_prochandle *Pr, const prfdinfo_t *info) 564 { 565 const int *val; 566 size_t vlen; 567 char buf[BUFSIZE]; 568 char buf1[32]; 569 char ipaddr[INET_ADDRSTRLEN]; 570 int i; 571 const in_addr_t *nexthop_val; 572 const prsockopts_bool_opts_t *opts; 573 struct boolopt { 574 int opt; 575 const char *name; 576 }; 577 static struct boolopt boolopts[] = { 578 { PR_SO_DEBUG, "SO_DEBUG," }, 579 { PR_SO_REUSEADDR, "SO_REUSEADDR," }, 580 { PR_SO_KEEPALIVE, "SO_KEEPALIVE," }, 581 { PR_SO_DONTROUTE, "SO_DONTROUTE," }, 582 { PR_SO_BROADCAST, "SO_BROADCAST," }, 583 { PR_SO_OOBINLINE, "SO_OOBINLINE," }, 584 { PR_SO_DGRAM_ERRIND, "SO_DGRAM_ERRIND,"}, 585 { PR_SO_ALLZONES, "SO_ALLZONES," }, 586 { PR_SO_MAC_EXEMPT, "SO_MAC_EXEMPT," }, 587 { PR_SO_MAC_IMPLICIT, "SO_MAC_IMPLICIT," }, 588 { PR_SO_EXCLBIND, "SO_EXCLBIND," }, 589 { PR_SO_VRRP, "SO_VRRP," }, 590 { PR_UDP_NAT_T_ENDPOINT, "UDP_NAT_T_ENDPOINT," }, 591 }; 592 const struct linger *l; 593 594 opts = proc_fdinfo_misc(info, PR_SOCKOPTS_BOOL_OPTS, NULL); 595 596 buf[0] = '!'; /* sentinel value, never printed */ 597 buf[1] = '\0'; 598 599 for (i = 0; i < sizeof (boolopts) / sizeof (boolopts[0]); i++) { 600 if (opts != NULL && opts->prsock_bool_opts & boolopts[i].opt) 601 (void) strlcat(buf, boolopts[i].name, sizeof (buf)); 602 } 603 604 l = proc_fdinfo_misc(info, PR_SOCKOPT_LINGER, NULL); 605 if (l != NULL && l->l_onoff != 0) { 606 (void) snprintf(buf1, sizeof (buf1), "SO_LINGER(%d),", 607 l->l_linger); 608 (void) strlcat(buf, buf1, sizeof (buf)); 609 } 610 611 val = proc_fdinfo_misc(info, PR_SOCKOPT_SNDBUF, NULL); 612 if (val != NULL) { 613 (void) snprintf(buf1, sizeof (buf1), "SO_SNDBUF(%d),", *val); 614 (void) strlcat(buf, buf1, sizeof (buf)); 615 } 616 617 val = proc_fdinfo_misc(info, PR_SOCKOPT_RCVBUF, NULL); 618 if (val != NULL) { 619 (void) snprintf(buf1, sizeof (buf1), "SO_RCVBUF(%d),", *val); 620 (void) strlcat(buf, buf1, sizeof (buf)); 621 } 622 623 624 nexthop_val = proc_fdinfo_misc(info, PR_SOCKOPT_IP_NEXTHOP, &vlen); 625 if (nexthop_val != NULL && vlen > 0) { 626 (void) inet_ntop(AF_INET, (void *) nexthop_val, 627 ipaddr, sizeof (ipaddr)); 628 (void) snprintf(buf1, sizeof (buf1), "IP_NEXTHOP(%s),", 629 ipaddr); 630 (void) strlcat(buf, buf1, sizeof (buf)); 631 } 632 633 buf[strlen(buf) - 1] = '\0'; /* overwrites sentinel if no options */ 634 if (buf[1] != '\0') 635 (void) printf("\t%s\n", buf+1); 636 } 637 638 #define MAXNALLOC 32 639 static void 640 show_sockfilters(struct ps_prochandle *Pr, const prfdinfo_t *info) 641 { 642 struct fil_info *fi; 643 int i = 0, nalloc = 2, len = nalloc * sizeof (*fi); 644 boolean_t printhdr = B_TRUE; 645 int fd = info->pr_fd; 646 647 fi = calloc(nalloc, sizeof (*fi)); 648 if (fi == NULL) { 649 perror("calloc"); 650 return; 651 } 652 /* CONSTCOND */ 653 while (1) { 654 if (pr_getsockopt(Pr, fd, SOL_FILTER, FIL_LIST, fi, &len) != 0) 655 break; 656 /* No filters */ 657 if (len == 0) 658 break; 659 /* Make sure buffer was large enough */ 660 if (fi->fi_pos >= nalloc) { 661 struct fil_info *new; 662 663 nalloc = fi->fi_pos + 1; 664 if (nalloc > MAXNALLOC) 665 break; 666 len = nalloc * sizeof (*fi); 667 new = realloc(fi, nalloc * sizeof (*fi)); 668 if (new == NULL) { 669 perror("realloc"); 670 break; 671 } 672 fi = new; 673 continue; 674 } 675 676 for (i = 0; (i + 1) * sizeof (*fi) <= len; i++) { 677 if (fi[i].fi_flags & FILF_BYPASS) 678 continue; 679 if (printhdr) { 680 (void) printf("\tfilters: "); 681 printhdr = B_FALSE; 682 } 683 (void) printf("%s", fi[i].fi_name); 684 if (fi[i].fi_flags != 0) { 685 (void) printf("("); 686 if (fi[i].fi_flags & FILF_AUTO) 687 (void) printf("auto,"); 688 if (fi[i].fi_flags & FILF_PROG) 689 (void) printf("prog,"); 690 (void) printf("\b)"); 691 } 692 if (fi[i].fi_pos == 0) /* last one */ 693 break; 694 (void) printf(","); 695 } 696 if (!printhdr) 697 (void) printf("\n"); 698 break; 699 } 700 free(fi); 701 } 702 703 /* print peer credentials for sockets and named pipes */ 704 static void 705 dopeerucred(struct ps_prochandle *Pr, const prfdinfo_t *info) 706 { 707 ucred_t *peercred = NULL; /* allocated by getpeerucred */ 708 709 if (pr_getpeerucred(Pr, info->pr_fd, &peercred) == 0) { 710 show_ucred("peer", peercred); 711 ucred_free(peercred); 712 } 713 } 714 715 static void 716 dosocknames(struct ps_prochandle *Pr, const prfdinfo_t *info) 717 { 718 const struct sockaddr *sa; 719 size_t vlen; 720 721 sa = proc_fdinfo_misc(info, PR_SOCKETNAME, &vlen); 722 if (sa != NULL) 723 show_sockaddr("sockname", sa, vlen); 724 725 sa = proc_fdinfo_misc(info, PR_PEERSOCKNAME, &vlen); 726 if (sa != NULL) 727 show_sockaddr("peername", sa, vlen); 728 } 729 730 /* the file is a socket */ 731 static void 732 dosocket(struct ps_prochandle *Pr, const prfdinfo_t *info) 733 { 734 const int *type; 735 736 type = proc_fdinfo_misc(info, PR_SOCKOPT_TYPE, NULL); 737 if (type != NULL) 738 show_socktype((uint_t)*type); 739 740 show_sockopts(Pr, info); 741 show_sockfilters(Pr, info); 742 dosocknames(Pr, info); 743 dopeerucred(Pr, info); 744 } 745 746 /* the file is a fifo (aka "named pipe") */ 747 static void 748 dofifo(struct ps_prochandle *Pr, const prfdinfo_t *info) 749 { 750 dopeerucred(Pr, info); 751 } 752