1 /* $NetBSD: fstat.c,v 1.117 2022/10/28 05:27:16 ozaki-r Exp $ */ 2 3 /*- 4 * Copyright (c) 1988, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #ifndef lint 34 __COPYRIGHT("@(#) Copyright (c) 1988, 1993\ 35 The Regents of the University of California. All rights reserved."); 36 #endif /* not lint */ 37 38 #ifndef lint 39 #if 0 40 static char sccsid[] = "@(#)fstat.c 8.3 (Berkeley) 5/2/95"; 41 #else 42 __RCSID("$NetBSD: fstat.c,v 1.117 2022/10/28 05:27:16 ozaki-r Exp $"); 43 #endif 44 #endif /* not lint */ 45 46 #include <sys/types.h> 47 #include <sys/param.h> 48 #include <sys/time.h> 49 #include <sys/proc.h> 50 #include <sys/stat.h> 51 #include <sys/vnode.h> 52 #include <sys/socket.h> 53 #include <sys/socketvar.h> 54 #include <sys/domain.h> 55 #include <sys/protosw.h> 56 #include <sys/unpcb.h> 57 #include <sys/sysctl.h> 58 #include <sys/filedesc.h> 59 #include <sys/pipe.h> 60 #define _KERNEL 61 #include <sys/mount.h> 62 #undef _KERNEL 63 #define _KERNEL 64 #include <sys/file.h> 65 #include <ufs/ufs/inode.h> 66 #include <ufs/ufs/ufsmount.h> 67 #undef _KERNEL 68 #define NFS 69 #include <nfs/nfsproto.h> 70 #include <nfs/rpcv2.h> 71 #include <nfs/nfs.h> 72 #include <nfs/nfsnode.h> 73 #undef NFS 74 #include <msdosfs/denode.h> 75 #include <msdosfs/bpb.h> 76 #define _KERNEL 77 #include <msdosfs/msdosfsmount.h> 78 #undef _KERNEL 79 #define _KERNEL 80 #include <miscfs/genfs/layer.h> 81 #undef _KERNEL 82 83 #include <net/route.h> 84 #include <netinet/in.h> 85 #include <netinet/in_systm.h> 86 #include <netinet/ip.h> 87 #include <netinet/in_pcb.h> 88 89 #ifdef INET6 90 #include <netinet/ip6.h> 91 #include <netinet6/in6.h> 92 #include <netinet6/ip6_var.h> 93 #include <netinet6/in6_pcb.h> 94 #endif 95 96 #include <netatalk/at.h> 97 #include <netatalk/ddp_var.h> 98 99 #include <netdb.h> 100 #include <arpa/inet.h> 101 102 #include <ctype.h> 103 #include <errno.h> 104 #include <kvm.h> 105 #include <limits.h> 106 #include <nlist.h> 107 #include <paths.h> 108 #include <pwd.h> 109 #include <stdio.h> 110 #include <stdlib.h> 111 #include <string.h> 112 #include <unistd.h> 113 #include <err.h> 114 #include <util.h> 115 116 #include "fstat.h" 117 118 #define TEXT -1 119 #define CDIR -2 120 #define RDIR -3 121 #define TRACE -4 122 123 typedef struct devs { 124 struct devs *next; 125 long fsid; 126 ino_t ino; 127 const char *name; 128 } DEVS; 129 static DEVS *devs; 130 131 static int fsflg, /* show files on same filesystem as file(s) argument */ 132 pflg, /* show files open by a particular pid */ 133 uflg; /* show files open by a particular (effective) user */ 134 static int checkfile; /* true if restricting to particular files or filesystems */ 135 static int nflg; /* (numerical) display f.s. and rdev as dev_t */ 136 static int Aflg; /* prefix with address of file structure */ 137 static int Oflg; /* print offset instead of size */ 138 int vflg; /* display errors in locating kernel data objects etc... */ 139 140 static fdfile_t **ofiles; /* buffer of pointers to file structures */ 141 static int fstat_maxfiles; 142 #define ALLOC_OFILES(d) \ 143 if ((d) > fstat_maxfiles) { \ 144 size_t len = (d) * sizeof(fdfile_t *); \ 145 free(ofiles); \ 146 ofiles = malloc(len); \ 147 if (ofiles == NULL) { \ 148 err(1, "malloc(%zu)", len); \ 149 } \ 150 fstat_maxfiles = (d); \ 151 } 152 153 kvm_t *kd; 154 155 static const char *const dtypes[] = { 156 DTYPE_NAMES 157 }; 158 159 static void dofiles(struct kinfo_proc2 *); 160 static int ext2fs_filestat(struct vnode *, struct filestat *); 161 static int getfname(const char *); 162 static void getinetproto(char *, size_t, int); 163 static void getatproto(char *, size_t, int); 164 static char *getmnton(struct mount *); 165 static const char *layer_filestat(struct vnode *, struct filestat *); 166 static int msdosfs_filestat(struct vnode *, struct filestat *); 167 static int nfs_filestat(struct vnode *, struct filestat *); 168 static const char *inet_addrstr(char *, size_t, const struct in_addr *, 169 uint16_t, bool); 170 #ifdef INET6 171 static const char *inet6_addrstr(char *, size_t, const struct in6_addr *, 172 uint16_t, bool); 173 #endif 174 static const char *at_addrstr(char *, size_t, const struct sockaddr_at *); 175 static void socktrans(struct file *, struct socket *, int); 176 static void misctrans(struct file *, int); 177 static int ufs_filestat(struct vnode *, struct filestat *); 178 static void usage(void) __dead; 179 static const char *vfilestat(struct vnode *, struct filestat *); 180 static void vtrans(struct file *, struct vnode *, int, int, long); 181 static void ftrans(fdfile_t *, int); 182 static void ptrans(struct file *, struct pipe *, int); 183 static void kdriver_init(void); 184 static void check_privs(void); 185 186 int 187 main(int argc, char **argv) 188 { 189 struct passwd *passwd; 190 struct kinfo_proc2 *p, *plast; 191 int arg, ch, what; 192 char *memf, *nlistf; 193 char buf[_POSIX2_LINE_MAX]; 194 int cnt; 195 gid_t egid = getegid(); 196 197 (void)setegid(getgid()); 198 arg = 0; 199 what = KERN_PROC_ALL; 200 nlistf = memf = NULL; 201 while ((ch = getopt(argc, argv, "fnAOp:u:vN:M:")) != -1) 202 switch((char)ch) { 203 case 'f': 204 fsflg = 1; 205 break; 206 case 'M': 207 memf = optarg; 208 break; 209 case 'N': 210 nlistf = optarg; 211 break; 212 case 'n': 213 nflg = 1; 214 break; 215 case 'A': 216 Aflg = 1; 217 break; 218 case 'O': 219 Oflg = 1; 220 break; 221 case 'p': 222 if (pflg++) 223 usage(); 224 if (!isdigit((unsigned char)*optarg)) { 225 warnx("-p requires a process id"); 226 usage(); 227 } 228 what = KERN_PROC_PID; 229 arg = atoi(optarg); 230 break; 231 case 'u': 232 if (uflg++) 233 usage(); 234 if (!(passwd = getpwnam(optarg))) { 235 errx(1, "%s: unknown uid", optarg); 236 } 237 what = KERN_PROC_UID; 238 arg = passwd->pw_uid; 239 break; 240 case 'v': 241 vflg = 1; 242 break; 243 case '?': 244 default: 245 usage(); 246 } 247 248 check_privs(); 249 250 kdriver_init(); 251 252 if (*(argv += optind)) { 253 for (; *argv; ++argv) { 254 if (getfname(*argv)) 255 checkfile = 1; 256 } 257 if (!checkfile) /* file(s) specified, but none accessible */ 258 exit(1); 259 } 260 261 ALLOC_OFILES(256); /* reserve space for file pointers */ 262 263 if (fsflg && !checkfile) { 264 /* -f with no files means use wd */ 265 if (getfname(".") == 0) 266 exit(1); 267 checkfile = 1; 268 } 269 270 /* 271 * Discard setgid privileges. If not the running kernel, we toss 272 * them away totally so that bad guys can't print interesting stuff 273 * from kernel memory, otherwise switch back to kmem for the 274 * duration of the kvm_openfiles() call. 275 */ 276 if (nlistf != NULL || memf != NULL) 277 (void)setgid(getgid()); 278 else 279 (void)setegid(egid); 280 281 if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf)) == NULL) 282 errx(1, "%s", buf); 283 284 /* get rid of it now anyway */ 285 if (nlistf == NULL && memf == NULL) 286 (void)setgid(getgid()); 287 288 if ((p = kvm_getproc2(kd, what, arg, sizeof *p, &cnt)) == NULL) { 289 errx(1, "%s", kvm_geterr(kd)); 290 } 291 if (Aflg) 292 (void)printf("%-*s ", 2*(int)(sizeof(void*)), "ADDR"); 293 if (nflg) 294 (void)printf( 295 "USER CMD PID FD DEV INUM MODE %s R/W", 296 Oflg ? " OFFS" : "SZ|DV" ); 297 else 298 (void)printf( 299 "USER CMD PID FD MOUNT INUM MODE %s R/W", 300 Oflg ? " OFFS" : "SZ|DV" ); 301 302 if (checkfile && fsflg == 0) 303 (void)printf(" NAME\n"); 304 else 305 (void)putchar('\n'); 306 307 for (plast = &p[cnt]; p < plast; ++p) { 308 if (p->p_stat == SZOMB) 309 continue; 310 dofiles(p); 311 } 312 return 0; 313 } 314 315 static void 316 check_privs(void) 317 { 318 int expaddr; 319 size_t expsize = sizeof(expaddr); 320 const char *expname = "kern.expose_address"; 321 322 if (geteuid() == 0) 323 return; 324 325 if (sysctlbyname(expname, &expaddr, &expsize, NULL, 0) == -1) 326 err(EXIT_FAILURE, "Can't get sysctl `%s'", expname); 327 if (expaddr == 0) 328 errx(EXIT_FAILURE, "This program does not work without " 329 "sysctl `%s' being set", expname); 330 } 331 332 static const char *Uname, *Comm; 333 pid_t Pid; 334 335 #define PREFIX(i) (void)printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \ 336 switch(i) { \ 337 case TEXT: \ 338 (void)printf(" text"); \ 339 break; \ 340 case CDIR: \ 341 (void)printf(" wd"); \ 342 break; \ 343 case RDIR: \ 344 (void)printf(" root"); \ 345 break; \ 346 case TRACE: \ 347 (void)printf(" tr"); \ 348 break; \ 349 default: \ 350 (void)printf(" %4d", i); \ 351 break; \ 352 } 353 354 static struct kinfo_drivers *kdriver; 355 static size_t kdriverlen; 356 357 static int 358 kdriver_comp(const void *a, const void *b) 359 { 360 const struct kinfo_drivers *ka = a; 361 const struct kinfo_drivers *kb = b; 362 int kac = ka->d_cmajor == -1 ? 0 : ka->d_cmajor; 363 int kbc = kb->d_cmajor == -1 ? 0 : kb->d_cmajor; 364 int kab = ka->d_bmajor == -1 ? 0 : ka->d_bmajor; 365 int kbb = kb->d_bmajor == -1 ? 0 : kb->d_bmajor; 366 int c = kac - kbc; 367 if (c == 0) 368 return kab - kbb; 369 else 370 return c; 371 } 372 373 static const char * 374 kdriver_search(int type, dev_t num) 375 { 376 struct kinfo_drivers k, *kp; 377 static char buf[64]; 378 379 if (nflg) 380 goto out; 381 382 if (type == VBLK) { 383 k.d_bmajor = num; 384 k.d_cmajor = -1; 385 } else { 386 k.d_bmajor = -1; 387 k.d_cmajor = num; 388 } 389 kp = bsearch(&k, kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); 390 if (kp) 391 return kp->d_name; 392 out: 393 snprintf(buf, sizeof(buf), "%llu", (unsigned long long)num); 394 return buf; 395 } 396 397 398 static void 399 kdriver_init(void) 400 { 401 size_t sz; 402 int error; 403 static const int name[2] = { CTL_KERN, KERN_DRIVERS }; 404 405 error = sysctl(name, __arraycount(name), NULL, &sz, NULL, 0); 406 if (error == -1) { 407 warn("sysctl kern.drivers"); 408 return; 409 } 410 411 if (sz % sizeof(*kdriver)) { 412 warnx("bad size %zu for kern.drivers", sz); 413 return; 414 } 415 416 kdriver = malloc(sz); 417 if (kdriver == NULL) { 418 warn("malloc"); 419 return; 420 } 421 422 error = sysctl(name, __arraycount(name), kdriver, &sz, NULL, 0); 423 if (error == -1) { 424 warn("sysctl kern.drivers"); 425 return; 426 } 427 428 kdriverlen = sz / sizeof(*kdriver); 429 qsort(kdriver, kdriverlen, sizeof(*kdriver), kdriver_comp); 430 #ifdef DEBUG 431 for (size_t i = 0; i < kdriverlen; i++) 432 printf("%d %d %s\n", kdriver[i].d_cmajor, kdriver[i].d_bmajor, 433 kdriver[i].d_name); 434 #endif 435 } 436 437 /* 438 * print open files attributed to this process 439 */ 440 static void 441 dofiles(struct kinfo_proc2 *p) 442 { 443 int i; 444 struct filedesc filed; 445 struct cwdinfo cwdi; 446 struct fdtab dt; 447 448 Uname = user_from_uid(p->p_uid, 0); 449 Pid = p->p_pid; 450 Comm = p->p_comm; 451 452 if (p->p_fd == 0 || p->p_cwdi == 0) 453 return; 454 if (!KVM_READ(p->p_fd, &filed, sizeof (filed))) { 455 warnx("can't read filedesc at %p for pid %d", 456 (void *)(uintptr_t)p->p_fd, Pid); 457 return; 458 } 459 if (filed.fd_lastfile == -1) 460 return; 461 if (!KVM_READ(p->p_cwdi, &cwdi, sizeof(cwdi))) { 462 warnx("can't read cwdinfo at %p for pid %d", 463 (void *)(uintptr_t)p->p_cwdi, Pid); 464 return; 465 } 466 if (!KVM_READ(filed.fd_dt, &dt, sizeof(dt))) { 467 warnx("can't read dtab at %p for pid %d", filed.fd_dt, Pid); 468 return; 469 } 470 if ((unsigned)filed.fd_lastfile >= dt.dt_nfiles || 471 filed.fd_freefile > filed.fd_lastfile + 1) { 472 dprintf("filedesc corrupted at %p for pid %d", 473 (void *)(uintptr_t)p->p_fd, Pid); 474 return; 475 } 476 /* 477 * root directory vnode, if one 478 */ 479 if (cwdi.cwdi_rdir) 480 vtrans(NULL, cwdi.cwdi_rdir, RDIR, FREAD, (long)cwdi.cwdi_rdir); 481 /* 482 * current working directory vnode 483 */ 484 vtrans(NULL, cwdi.cwdi_cdir, CDIR, FREAD, (long)cwdi.cwdi_cdir); 485 #if 0 486 /* 487 * Disable for now, since p->p_tracep appears to point to a ktr_desc * 488 * ktrace vnode, if one 489 */ 490 if (p->p_tracep) 491 ftrans(p->p_tracep, TRACE); 492 #endif 493 /* 494 * open files 495 */ 496 #define FPSIZE (sizeof (fdfile_t *)) 497 ALLOC_OFILES(filed.fd_lastfile+1); 498 if (!KVM_READ(&filed.fd_dt->dt_ff, ofiles, 499 (filed.fd_lastfile+1) * FPSIZE)) { 500 dprintf("can't read file structures at %p for pid %d", 501 &filed.fd_dt->dt_ff, Pid); 502 return; 503 } 504 for (i = 0; i <= filed.fd_lastfile; i++) { 505 if (ofiles[i] == NULL) 506 continue; 507 ftrans(ofiles[i], i); 508 } 509 } 510 511 static void 512 ftrans(fdfile_t *fp, int i) 513 { 514 struct file file; 515 fdfile_t fdfile; 516 517 if (!KVM_READ(fp, &fdfile, sizeof(fdfile))) { 518 dprintf("can't read file %d at %p for pid %d", 519 i, fp, Pid); 520 return; 521 } 522 if (fdfile.ff_file == NULL) { 523 dprintf("null ff_file for %d at %p for pid %d", 524 i, fp, Pid); 525 return; 526 } 527 if (!KVM_READ(fdfile.ff_file, &file, sizeof(file))) { 528 dprintf("can't read file %d at %p for pid %d", 529 i, fdfile.ff_file, Pid); 530 return; 531 } 532 if (Aflg && file.f_type != DTYPE_VNODE && checkfile == 0) 533 (void)printf("%*lx ", 534 2*(int)(sizeof(void*)), (long)fdfile.ff_file); 535 switch (file.f_type) { 536 case DTYPE_VNODE: 537 vtrans(&file, file.f_data, i, file.f_flag, (long)fdfile.ff_file); 538 break; 539 case DTYPE_SOCKET: 540 socktrans(&file, file.f_data, i); 541 break; 542 case DTYPE_PIPE: 543 if (checkfile == 0) 544 ptrans(&file, file.f_data, i); 545 break; 546 case DTYPE_MISC: 547 case DTYPE_KQUEUE: 548 case DTYPE_CRYPTO: 549 case DTYPE_MQUEUE: 550 case DTYPE_SEM: 551 if (checkfile == 0) 552 misctrans(&file, i); 553 break; 554 default: 555 dprintf("unknown file type %d for file %d of pid %d", 556 file.f_type, i, Pid); 557 break; 558 } 559 } 560 561 static const char dead[] = "dead"; 562 static const char *vnode_tag[] = { 563 VNODE_TAGS 564 }; 565 566 static const char * 567 vfilestat(struct vnode *vp, struct filestat *fsp) 568 { 569 const char *badtype = NULL; 570 571 if (vp->v_type == VNON) 572 badtype = "none"; 573 else if (vp->v_type == VBAD) 574 badtype = "bad"; 575 else 576 switch (vp->v_tag) { 577 case VT_NON: 578 badtype = dead; 579 break; 580 case VT_UFS: 581 case VT_LFS: 582 case VT_MFS: 583 if (!ufs_filestat(vp, fsp)) 584 badtype = "error"; 585 break; 586 case VT_MSDOSFS: 587 if (!msdosfs_filestat(vp, fsp)) 588 badtype = "error"; 589 break; 590 case VT_NFS: 591 if (!nfs_filestat(vp, fsp)) 592 badtype = "error"; 593 break; 594 case VT_EXT2FS: 595 if (!ext2fs_filestat(vp, fsp)) 596 badtype = "error"; 597 break; 598 case VT_ISOFS: 599 if (!isofs_filestat(vp, fsp)) 600 badtype = "error"; 601 break; 602 case VT_NTFS: 603 if (!ntfs_filestat(vp, fsp)) 604 badtype = "error"; 605 break; 606 case VT_PTYFS: 607 if (!ptyfs_filestat(vp, fsp)) 608 badtype = "error"; 609 break; 610 case VT_TMPFS: 611 if (!tmpfs_filestat(vp, fsp)) 612 badtype = "error"; 613 break; 614 #ifdef HAVE_ZFS 615 case VT_ZFS: 616 if (!zfs_filestat(vp, fsp)) 617 badtype = "error"; 618 break; 619 #endif 620 case VT_NULL: 621 case VT_OVERLAY: 622 case VT_UMAP: 623 badtype = layer_filestat(vp, fsp); 624 break; 625 default: { 626 static char unknown[10]; 627 (void)snprintf(unknown, sizeof unknown, "%s(%#x)", 628 (size_t)vp->v_tag < __arraycount(vnode_tag) ? 629 vnode_tag[vp->v_tag] : "?", vp->v_tag); 630 badtype = unknown; 631 break; 632 } 633 } 634 return badtype; 635 } 636 637 static int 638 checkfs(struct vnode *vp, struct vnode *vn, struct filestat *fst, 639 const char **type, const char **fname) 640 { 641 *fname = NULL; 642 if (!KVM_READ(vp, vn, sizeof(*vn))) { 643 dprintf("can't read vnode at %p for pid %d", vp, Pid); 644 return 0; 645 } 646 *type = vfilestat(vn, fst); 647 if (checkfile) { 648 int fsmatch = 0; 649 DEVS *d; 650 #if 0 651 if (*type && *type != dead) 652 return 0; 653 #endif 654 for (d = devs; d != NULL; d = d->next) { 655 if (d->fsid == fst->fsid) { 656 fsmatch = 1; 657 if (d->ino == fst->fileid) { 658 *fname = d->name; 659 break; 660 } 661 } 662 } 663 if (fsmatch == 0 || (*fname == NULL && fsflg == 0)) 664 return 0; 665 } 666 return 1; 667 } 668 669 static void 670 vprint(struct vnode *vn, struct filestat *fst) 671 { 672 switch (vn->v_type) { 673 case VBLK: 674 case VCHR: { 675 const char *name; 676 677 if (nflg || ((name = devname(fst->rdev, vn->v_type == VCHR ? 678 S_IFCHR : S_IFBLK)) == NULL)) 679 (void)printf(" %s,%-2llu", 680 kdriver_search(vn->v_type, major(fst->rdev)), 681 (unsigned long long)minor(fst->rdev)); 682 else 683 (void)printf(" %6s", name); 684 break; 685 } 686 default: 687 (void)printf(" %6lld", (long long)fst->size); 688 } 689 } 690 691 void 692 oprint(struct file *fp, const char *str) 693 { 694 if (Oflg) 695 (void)printf(" %6lld", (long long)(fp ? fp->f_offset : 0)); 696 fputs(str, stdout); 697 } 698 699 static void 700 vtrans(struct file *fp, struct vnode *vp, int i, int flag, long addr) 701 { 702 struct vnode vn; 703 char mode[15], rw[3]; 704 const char *badtype, *filename; 705 struct filestat fst; 706 707 if (!checkfs(vp, &vn, &fst, &badtype, &filename)) 708 return; 709 710 if (Aflg) 711 (void)printf("%*lx ", 2*(int)(sizeof(void*)), addr); 712 PREFIX(i); 713 if (badtype == dead) { 714 char buf[1024]; 715 (void)snprintb(buf, sizeof(buf), VNODE_FLAGBITS, 716 vn.v_iflag | vn.v_vflag | vn.v_uflag); 717 (void)printf(" flags %s\n", buf); 718 return; 719 } else if (badtype) { 720 (void)printf(" - - %10s -\n", badtype); 721 return; 722 } 723 if (nflg) 724 (void)printf(" %3llu,%-2llu", 725 (unsigned long long)major(fst.fsid), 726 (unsigned long long)minor(fst.fsid)); 727 else 728 (void)printf(" %-8s", getmnton(vn.v_mount)); 729 if (nflg) 730 (void)snprintf(mode, sizeof mode, "%6o", fst.mode); 731 else 732 strmode(fst.mode, mode); 733 (void)printf(" %8"PRIu64" %*s", fst.fileid, nflg ? 5 : 10, mode); 734 if (Oflg) { 735 oprint(fp, ""); 736 } else { 737 vprint(&vn, &fst); 738 } 739 rw[0] = '\0'; 740 if (flag & FREAD) 741 (void)strlcat(rw, "r", sizeof(rw)); 742 if (flag & FWRITE) 743 (void)strlcat(rw, "w", sizeof(rw)); 744 (void)printf(" %-2s", rw); 745 if (filename && !fsflg) 746 (void)printf(" %s", filename); 747 (void)putchar('\n'); 748 } 749 750 static int 751 ufs_filestat(struct vnode *vp, struct filestat *fsp) 752 { 753 struct inode inode; 754 struct ufsmount ufsmount; 755 union dinode { 756 struct ufs1_dinode dp1; 757 struct ufs2_dinode dp2; 758 } dip; 759 760 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 761 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); 762 return 0; 763 } 764 765 if (!KVM_READ(inode.i_ump, &ufsmount, sizeof (struct ufsmount))) { 766 dprintf("can't read ufsmount at %p for pid %d", inode.i_ump, Pid); 767 return 0; 768 } 769 770 switch (ufsmount.um_fstype) { 771 case UFS1: 772 if (!KVM_READ(inode.i_din.ffs1_din, &dip, 773 sizeof(struct ufs1_dinode))) { 774 dprintf("can't read dinode at %p for pid %d", 775 inode.i_din.ffs1_din, Pid); 776 return 0; 777 } 778 fsp->rdev = dip.dp1.di_rdev; 779 break; 780 case UFS2: 781 if (!KVM_READ(inode.i_din.ffs2_din, &dip, 782 sizeof(struct ufs2_dinode))) { 783 dprintf("can't read dinode at %p for pid %d", 784 inode.i_din.ffs2_din, Pid); 785 return 0; 786 } 787 fsp->rdev = dip.dp2.di_rdev; 788 break; 789 default: 790 dprintf("unknown ufs type %ld for pid %d", 791 ufsmount.um_fstype, Pid); 792 break; 793 } 794 fsp->fsid = inode.i_dev & 0xffff; 795 fsp->fileid = inode.i_number; 796 fsp->mode = (mode_t)inode.i_mode; 797 fsp->size = inode.i_size; 798 799 return 1; 800 } 801 802 static int 803 ext2fs_filestat(struct vnode *vp, struct filestat *fsp) 804 { 805 struct inode inode; 806 struct ext2fs_dinode dinode; 807 808 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) { 809 dprintf("can't read inode at %p for pid %d", VTOI(vp), Pid); 810 return 0; 811 } 812 fsp->fsid = inode.i_dev & 0xffff; 813 fsp->fileid = inode.i_number; 814 815 if (!KVM_READ(inode.i_din.e2fs_din, &dinode, sizeof dinode)) { 816 dprintf("can't read ext2fs_dinode at %p for pid %d", 817 inode.i_din.e2fs_din, Pid); 818 return 0; 819 } 820 fsp->mode = dinode.e2di_mode; 821 fsp->size = dinode.e2di_size; 822 fsp->rdev = dinode.e2di_rdev; 823 824 return 1; 825 } 826 827 static int 828 nfs_filestat(struct vnode *vp, struct filestat *fsp) 829 { 830 struct nfsnode nfsnode; 831 struct vattr va; 832 833 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) { 834 dprintf("can't read nfsnode at %p for pid %d", VTONFS(vp), 835 Pid); 836 return 0; 837 } 838 if (!KVM_READ(nfsnode.n_vattr, &va, sizeof(va))) { 839 dprintf("can't read vnode attributes at %p for pid %d", 840 nfsnode.n_vattr, Pid); 841 return 0; 842 } 843 fsp->fsid = va.va_fsid; 844 fsp->fileid = va.va_fileid; 845 fsp->size = nfsnode.n_size; 846 fsp->rdev = va.va_rdev; 847 fsp->mode = (mode_t)va.va_mode | getftype(vp->v_type); 848 849 return 1; 850 } 851 852 static int 853 msdosfs_filestat(struct vnode *vp, struct filestat *fsp) 854 { 855 struct denode de; 856 struct msdosfsmount mp; 857 858 if (!KVM_READ(VTONFS(vp), &de, sizeof(de))) { 859 dprintf("can't read denode at %p for pid %d", VTONFS(vp), 860 Pid); 861 return 0; 862 } 863 if (!KVM_READ(de.de_pmp, &mp, sizeof(mp))) { 864 dprintf("can't read mount struct at %p for pid %d", de.de_pmp, 865 Pid); 866 return 0; 867 } 868 869 fsp->fsid = de.de_dev & 0xffff; 870 fsp->fileid = 0; /* XXX see msdosfs_vptofh() for more info */ 871 fsp->size = de.de_FileSize; 872 fsp->rdev = 0; /* msdosfs doesn't support device files */ 873 fsp->mode = (0777 & mp.pm_mask) | getftype(vp->v_type); 874 return 1; 875 } 876 877 static const char * 878 layer_filestat(struct vnode *vp, struct filestat *fsp) 879 { 880 struct layer_node layer_node; 881 struct mount mount; 882 struct vnode vn; 883 const char *badtype; 884 885 if (!KVM_READ(VTOLAYER(vp), &layer_node, sizeof(layer_node))) { 886 dprintf("can't read layer_node at %p for pid %d", 887 VTOLAYER(vp), Pid); 888 return "error"; 889 } 890 if (!KVM_READ(vp->v_mount, &mount, sizeof(struct mount))) { 891 dprintf("can't read mount struct at %p for pid %d", 892 vp->v_mount, Pid); 893 return "error"; 894 } 895 vp = layer_node.layer_lowervp; 896 if (!KVM_READ(vp, &vn, sizeof(struct vnode))) { 897 dprintf("can't read vnode at %p for pid %d", vp, Pid); 898 return "error"; 899 } 900 if ((badtype = vfilestat(&vn, fsp)) == NULL) 901 fsp->fsid = mount.mnt_stat.f_fsidx.__fsid_val[0]; 902 return badtype; 903 } 904 905 static char * 906 getmnton(struct mount *m) 907 { 908 static struct mount mount; 909 static struct mtab { 910 struct mtab *next; 911 struct mount *m; 912 char mntonname[MNAMELEN]; 913 } *mhead = NULL; 914 struct mtab *mt; 915 916 for (mt = mhead; mt != NULL; mt = mt->next) 917 if (m == mt->m) 918 return mt->mntonname; 919 if (!KVM_READ(m, &mount, sizeof(struct mount))) { 920 warnx("can't read mount table at %p", m); 921 return NULL; 922 } 923 if ((mt = malloc(sizeof (struct mtab))) == NULL) { 924 err(1, "malloc(%u)", (unsigned int)sizeof(struct mtab)); 925 } 926 mt->m = m; 927 (void)memmove(&mt->mntonname[0], &mount.mnt_stat.f_mntonname[0], 928 MNAMELEN); 929 mt->next = mhead; 930 mhead = mt; 931 return mt->mntonname; 932 } 933 934 static const char * 935 inet_addrstr(char *buf, size_t len, const struct in_addr *a, uint16_t p, bool isdg) 936 { 937 char addr[256], serv[256]; 938 struct sockaddr_in sin; 939 const int niflags = 940 (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) | 941 (isdg ? NI_DGRAM : 0); 942 943 944 (void)memset(&sin, 0, sizeof(sin)); 945 sin.sin_family = AF_INET; 946 sin.sin_len = sizeof(sin); 947 sin.sin_addr = *a; 948 sin.sin_port = htons(p); 949 950 serv[0] = '\0'; 951 952 if (getnameinfo((struct sockaddr *)&sin, sin.sin_len, 953 addr, sizeof(addr), serv, sizeof(serv), niflags)) { 954 if (inet_ntop(AF_INET, a, addr, sizeof(addr)) == NULL) 955 strlcpy(addr, "invalid", sizeof(addr)); 956 } 957 958 if (serv[0] == '\0') 959 snprintf(serv, sizeof(serv), "%u", p); 960 961 if (a->s_addr == INADDR_ANY) { 962 if (p == 0) 963 buf[0] = '\0'; 964 else 965 snprintf(buf, len, "*:%s", serv); 966 return buf; 967 } 968 969 snprintf(buf, len, "%s:%s", addr, serv); 970 return buf; 971 } 972 973 #ifdef INET6 974 static const char * 975 inet6_addrstr(char *buf, size_t len, const struct in6_addr *a, uint16_t p, bool isdg) 976 { 977 char addr[256], serv[256]; 978 struct sockaddr_in6 sin6; 979 const int niflags = 980 (nflg ? (NI_NUMERICHOST|NI_NUMERICSERV) : 0) | 981 (isdg ? NI_DGRAM : 0); 982 983 (void)memset(&sin6, 0, sizeof(sin6)); 984 sin6.sin6_family = AF_INET6; 985 sin6.sin6_len = sizeof(sin6); 986 sin6.sin6_addr = *a; 987 sin6.sin6_port = htons(p); 988 989 inet6_getscopeid(&sin6, INET6_IS_ADDR_LINKLOCAL); 990 serv[0] = '\0'; 991 992 if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 993 addr, sizeof(addr), serv, sizeof(serv), niflags)) { 994 if (inet_ntop(AF_INET6, a, addr, sizeof(addr)) == NULL) 995 strlcpy(addr, "invalid", sizeof(addr)); 996 } 997 998 if (serv[0] == '\0') 999 snprintf(serv, sizeof(serv), "%u", p); 1000 1001 if (IN6_IS_ADDR_UNSPECIFIED(a)) { 1002 if (p == 0) 1003 buf[0] = '\0'; 1004 else 1005 snprintf(buf, len, "*:%s", serv); 1006 return buf; 1007 } 1008 1009 if (strchr(addr, ':') == NULL) 1010 snprintf(buf, len, "%s:%s", addr, serv); 1011 else 1012 snprintf(buf, len, "[%s]:%s", addr, serv); 1013 1014 return buf; 1015 } 1016 #endif 1017 1018 static const char * 1019 at_addrstr(char *buf, size_t len, const struct sockaddr_at *sat) 1020 { 1021 const struct netrange *nr = &sat->sat_range.r_netrange; 1022 const struct at_addr *at = &sat->sat_addr; 1023 char addr[64], phase[64], range[64]; 1024 1025 if (sat->sat_port || at->s_net || at->s_node) { 1026 if (at->s_net || at->s_node) 1027 snprintf(addr, sizeof(addr), "%u.%u:%u", 1028 ntohs(at->s_net), at->s_node, sat->sat_port); 1029 else 1030 snprintf(addr, sizeof(addr), "*:%u", sat->sat_port); 1031 } else 1032 addr[0] = '\0'; 1033 1034 if (nr->nr_phase) 1035 snprintf(phase, sizeof(phase), " phase %u", nr->nr_phase); 1036 else 1037 phase[0] = '\0'; 1038 1039 if (nr->nr_firstnet || nr->nr_lastnet) 1040 snprintf(range, sizeof(range), " range [%u-%u]", 1041 ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet)); 1042 else 1043 range[0] = '\0'; 1044 1045 snprintf(buf, len, "%s%s%s", addr, phase, range); 1046 return buf; 1047 } 1048 1049 static void 1050 socktrans(struct file *f, struct socket *sock, int i) 1051 { 1052 static const char *stypename[] = { 1053 "unused", /* 0 */ 1054 "stream", /* 1 */ 1055 "dgram", /* 2 */ 1056 "raw", /* 3 */ 1057 "rdm", /* 4 */ 1058 "seqpak" /* 5 */ 1059 }; 1060 #define STYPEMAX 5 1061 struct socket so; 1062 struct protosw proto; 1063 struct domain dom; 1064 struct in4pcb in4pcb; 1065 struct in6pcb in6pcb; 1066 struct unpcb unpcb; 1067 struct ddpcb ddpcb; 1068 int len; 1069 char dname[32]; 1070 char lbuf[512], fbuf[512], pbuf[24]; 1071 bool isdgram; 1072 1073 pbuf[0] = '\0'; 1074 /* fill in socket */ 1075 if (!KVM_READ(sock, &so, sizeof(struct socket))) { 1076 dprintf("can't read sock at %p", sock); 1077 goto bad; 1078 } 1079 1080 /* fill in protosw entry */ 1081 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) { 1082 dprintf("can't read protosw at %p", so.so_proto); 1083 goto bad; 1084 } 1085 1086 /* fill in domain */ 1087 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) { 1088 dprintf("can't read domain at %p", proto.pr_domain); 1089 goto bad; 1090 } 1091 1092 if (checkfile && dom.dom_family != AF_LOCAL) 1093 return; 1094 1095 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname, 1096 sizeof(dname) - 1)) != sizeof(dname) -1) { 1097 dprintf("can't read domain name at %p", dom.dom_name); 1098 dname[0] = '\0'; 1099 } 1100 else 1101 dname[len] = '\0'; 1102 1103 /* 1104 * protocol specific formatting 1105 * 1106 * Try to find interesting things to print. For TCP, the interesting 1107 * thing is the address of the tcpcb, for UDP and others, just the 1108 * inpcb (socket pcb). For UNIX domain, its the address of the socket 1109 * pcb and the address of the connected pcb (if connected). Otherwise 1110 * just print the protocol number and address of the socket itself. 1111 * The idea is not to duplicate netstat, but to make available enough 1112 * information for further analysis. 1113 */ 1114 fbuf[0] = '\0'; 1115 lbuf[0] = '\0'; 1116 isdgram = false; 1117 switch(dom.dom_family) { 1118 case AF_INET: 1119 getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol); 1120 switch (proto.pr_protocol) { 1121 case IPPROTO_UDP: 1122 isdgram = true; 1123 /* FALLTHROUGH */ 1124 case IPPROTO_TCP: 1125 if (so.so_pcb == NULL) 1126 break; 1127 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in4pcb, 1128 sizeof(in4pcb)) != sizeof(in4pcb)) { 1129 dprintf("can't read in4pcb at %p", so.so_pcb); 1130 goto bad; 1131 } 1132 struct inpcb *inp = (struct inpcb *)&in4pcb; 1133 inet_addrstr(lbuf, sizeof(lbuf), &in4p_laddr(inp), 1134 ntohs(inp->inp_lport), isdgram); 1135 inet_addrstr(fbuf, sizeof(fbuf), &in4p_faddr(inp), 1136 ntohs(inp->inp_fport), isdgram); 1137 break; 1138 default: 1139 break; 1140 } 1141 break; 1142 #ifdef INET6 1143 case AF_INET6: 1144 getinetproto(pbuf, sizeof(pbuf), proto.pr_protocol); 1145 switch (proto.pr_protocol) { 1146 case IPPROTO_UDP: 1147 isdgram = true; 1148 /* FALLTHROUGH */ 1149 case IPPROTO_TCP: 1150 if (so.so_pcb == NULL) 1151 break; 1152 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&in6pcb, 1153 sizeof(in6pcb)) != sizeof(in6pcb)) { 1154 dprintf("can't read in6pcb at %p", so.so_pcb); 1155 goto bad; 1156 } 1157 struct inpcb *inp = (struct inpcb *)&in6pcb; 1158 inet6_addrstr(lbuf, sizeof(lbuf), &in6p_laddr(inp), 1159 ntohs(inp->inp_lport), isdgram); 1160 inet6_addrstr(fbuf, sizeof(fbuf), &in6p_faddr(inp), 1161 ntohs(inp->inp_fport), isdgram); 1162 break; 1163 default: 1164 break; 1165 } 1166 break; 1167 #endif 1168 case AF_LOCAL: 1169 /* print address of pcb and connected pcb */ 1170 if (so.so_pcb) { 1171 char shoconn[4], *cp; 1172 void *pcb[2]; 1173 size_t p = 0; 1174 1175 pcb[0] = so.so_pcb; 1176 1177 cp = shoconn; 1178 if (!(so.so_state & SS_CANTRCVMORE)) 1179 *cp++ = '<'; 1180 *cp++ = '-'; 1181 if (!(so.so_state & SS_CANTSENDMORE)) 1182 *cp++ = '>'; 1183 *cp = '\0'; 1184 again: 1185 if (kvm_read(kd, (u_long)pcb[p], (char *)&unpcb, 1186 sizeof(struct unpcb)) != sizeof(struct unpcb)){ 1187 dprintf("can't read unpcb at %p", so.so_pcb); 1188 goto bad; 1189 } 1190 if (checkfile) { 1191 struct vnode vn; 1192 struct filestat fst; 1193 const char *badtype, *filename; 1194 if (unpcb.unp_vnode == NULL) 1195 return; 1196 if (!checkfs(unpcb.unp_vnode, &vn, &fst, 1197 &badtype, &filename)) 1198 return; 1199 } 1200 1201 if (unpcb.unp_addr) { 1202 struct sockaddr_un *sun = 1203 malloc(unpcb.unp_addrlen); 1204 if (sun == NULL) 1205 err(1, "malloc(%zu)", 1206 unpcb.unp_addrlen); 1207 if (kvm_read(kd, (u_long)unpcb.unp_addr, 1208 sun, unpcb.unp_addrlen) != 1209 (ssize_t)unpcb.unp_addrlen) { 1210 dprintf("can't read sun at %p", 1211 unpcb.unp_addr); 1212 free(sun); 1213 } else { 1214 snprintf(fbuf, sizeof(fbuf), " %s %s %s", 1215 shoconn, sun->sun_path, 1216 p == 0 ? "[creat]" : "[using]"); 1217 free(sun); 1218 break; 1219 } 1220 } 1221 if (unpcb.unp_conn) { 1222 if (p == 0) { 1223 pcb[++p] = unpcb.unp_conn; 1224 goto again; 1225 } else 1226 snprintf(fbuf, sizeof(fbuf), 1227 " %p %s %p", pcb[0], shoconn, 1228 pcb[1]); 1229 } 1230 } 1231 break; 1232 case AF_APPLETALK: 1233 getatproto(pbuf, sizeof(pbuf), proto.pr_protocol); 1234 if (so.so_pcb) { 1235 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&ddpcb, 1236 sizeof(ddpcb)) != sizeof(ddpcb)){ 1237 dprintf("can't read ddpcb at %p", so.so_pcb); 1238 goto bad; 1239 } 1240 at_addrstr(fbuf, sizeof(fbuf), &ddpcb.ddp_fsat); 1241 at_addrstr(lbuf, sizeof(lbuf), &ddpcb.ddp_lsat); 1242 } 1243 break; 1244 default: 1245 /* print protocol number and socket address */ 1246 snprintf(fbuf, sizeof(fbuf), " %d %jx", proto.pr_protocol, 1247 (uintmax_t)(uintptr_t)sock); 1248 break; 1249 } 1250 PREFIX(i); 1251 if ((u_short)so.so_type > STYPEMAX) 1252 (void)printf("* %s ?%d", dname, so.so_type); 1253 else 1254 (void)printf("* %s %s", dname, stypename[so.so_type]); 1255 1256 if (pbuf[0]) 1257 printf("%s", pbuf); 1258 if (fbuf[0] || lbuf[0]) 1259 printf(" %s%s%s", fbuf, (fbuf[0] && lbuf[0]) ? " <-> " : "", 1260 lbuf); 1261 else if (so.so_pcb) 1262 printf(" %jx", (uintmax_t)(uintptr_t)so.so_pcb); 1263 oprint(f, "\n"); 1264 return; 1265 bad: 1266 (void)printf("* error\n"); 1267 } 1268 1269 static void 1270 ptrans(struct file *fp, struct pipe *cpipe, int i) 1271 { 1272 struct pipe cp; 1273 1274 PREFIX(i); 1275 1276 /* fill in pipe */ 1277 if (!KVM_READ(cpipe, &cp, sizeof(struct pipe))) { 1278 dprintf("can't read pipe at %p", cpipe); 1279 goto bad; 1280 } 1281 1282 /* pipe descriptor is either read or write, never both */ 1283 (void)printf("* pipe %p %s %p %s%s%s", cpipe, 1284 (fp->f_flag & FWRITE) ? "->" : "<-", 1285 cp.pipe_peer, 1286 (fp->f_flag & FWRITE) ? "w" : "r", 1287 (fp->f_flag & FNONBLOCK) ? "n" : "", 1288 (cp.pipe_state & PIPE_ASYNC) ? "a" : ""); 1289 oprint(fp, "\n"); 1290 return; 1291 bad: 1292 (void)printf("* error\n"); 1293 } 1294 1295 static void 1296 misctrans(struct file *file, int i) 1297 { 1298 1299 PREFIX(i); 1300 pmisc(file, dtypes[file->f_type]); 1301 } 1302 1303 /* 1304 * getinetproto -- 1305 * print name of protocol number 1306 */ 1307 static void 1308 getinetproto(char *buf, size_t len, int number) 1309 { 1310 const char *cp; 1311 1312 switch (number) { 1313 case IPPROTO_IP: 1314 cp = "ip"; break; 1315 case IPPROTO_ICMP: 1316 cp ="icmp"; break; 1317 case IPPROTO_GGP: 1318 cp ="ggp"; break; 1319 case IPPROTO_TCP: 1320 cp ="tcp"; break; 1321 case IPPROTO_EGP: 1322 cp ="egp"; break; 1323 case IPPROTO_PUP: 1324 cp ="pup"; break; 1325 case IPPROTO_UDP: 1326 cp ="udp"; break; 1327 case IPPROTO_IDP: 1328 cp ="idp"; break; 1329 case IPPROTO_RAW: 1330 cp ="raw"; break; 1331 case IPPROTO_ICMPV6: 1332 cp ="icmp6"; break; 1333 default: 1334 (void)snprintf(buf, len, " %d", number); 1335 return; 1336 } 1337 (void)snprintf(buf, len, " %s", cp); 1338 } 1339 1340 /* 1341 * getatproto -- 1342 * print name of protocol number 1343 */ 1344 static void 1345 getatproto(char *buf, size_t len, int number) 1346 { 1347 const char *cp; 1348 1349 switch (number) { 1350 case ATPROTO_DDP: 1351 cp = "ddp"; break; 1352 case ATPROTO_AARP: 1353 cp ="aarp"; break; 1354 default: 1355 (void)snprintf(buf, len, " %d", number); 1356 return; 1357 } 1358 (void)snprintf(buf, len, " %s", cp); 1359 } 1360 1361 static int 1362 getfname(const char *filename) 1363 { 1364 struct stat statbuf; 1365 DEVS *cur; 1366 1367 if (stat(filename, &statbuf)) { 1368 warn("stat(%s)", filename); 1369 return 0; 1370 } 1371 if ((cur = malloc(sizeof(*cur))) == NULL) { 1372 err(1, "malloc(%zu)", sizeof(*cur)); 1373 } 1374 cur->next = devs; 1375 devs = cur; 1376 1377 cur->ino = statbuf.st_ino; 1378 cur->fsid = statbuf.st_dev & 0xffff; 1379 cur->name = filename; 1380 return 1; 1381 } 1382 1383 mode_t 1384 getftype(enum vtype v_type) 1385 { 1386 mode_t ftype; 1387 1388 switch (v_type) { 1389 case VREG: 1390 ftype = S_IFREG; 1391 break; 1392 case VDIR: 1393 ftype = S_IFDIR; 1394 break; 1395 case VBLK: 1396 ftype = S_IFBLK; 1397 break; 1398 case VCHR: 1399 ftype = S_IFCHR; 1400 break; 1401 case VLNK: 1402 ftype = S_IFLNK; 1403 break; 1404 case VSOCK: 1405 ftype = S_IFSOCK; 1406 break; 1407 case VFIFO: 1408 ftype = S_IFIFO; 1409 break; 1410 default: 1411 ftype = 0; 1412 break; 1413 }; 1414 1415 return ftype; 1416 } 1417 1418 static void 1419 usage(void) 1420 { 1421 (void)fprintf(stderr, "Usage: %s [-Afnv] [-M core] [-N system] " 1422 "[-p pid] [-u user] [file ...]\n", getprogname()); 1423 exit(1); 1424 } 1425