19b50d902SRodney W. Grimes /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 40daf62d9SStanislav Sedov * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org> 59b50d902SRodney W. Grimes * Copyright (c) 1988, 1993 69b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 79b50d902SRodney W. Grimes * 89b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 99b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 109b50d902SRodney W. Grimes * are met: 119b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 129b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 139b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 149b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 159b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 16fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 179b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 189b50d902SRodney W. Grimes * without specific prior written permission. 199b50d902SRodney W. Grimes * 209b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 219b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 229b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 239b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 249b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 259b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 269b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 279b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 289b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 299b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 309b50d902SRodney W. Grimes * SUCH DAMAGE. 319b50d902SRodney W. Grimes */ 329b50d902SRodney W. Grimes 33e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 34e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 359b50d902SRodney W. Grimes 369b50d902SRodney W. Grimes #include <sys/param.h> 379b50d902SRodney W. Grimes #include <sys/user.h> 389b50d902SRodney W. Grimes #include <sys/stat.h> 399b50d902SRodney W. Grimes #include <sys/socket.h> 409b50d902SRodney W. Grimes #include <sys/socketvar.h> 419b50d902SRodney W. Grimes #include <sys/sysctl.h> 42d2bccb9fSDavid Greenman #include <sys/queue.h> 43*91ad311bSJeremie Le Hen #include <sys/un.h> 449b50d902SRodney W. Grimes 459b50d902SRodney W. Grimes #include <netinet/in.h> 469b50d902SRodney W. Grimes 47*91ad311bSJeremie Le Hen #include <arpa/inet.h> 48*91ad311bSJeremie Le Hen 490daf62d9SStanislav Sedov #include <assert.h> 509b50d902SRodney W. Grimes #include <ctype.h> 51c1e65942SPhilippe Charnier #include <err.h> 520daf62d9SStanislav Sedov #include <libprocstat.h> 53df3f5d9dSPeter Wemm #include <limits.h> 549b50d902SRodney W. Grimes #include <pwd.h> 5576db9ccfSWarner Losh #include <stdint.h> 569b50d902SRodney W. Grimes #include <stdio.h> 579b50d902SRodney W. Grimes #include <stdlib.h> 5805427aafSKonstantin Belousov #include <stddef.h> 599b50d902SRodney W. Grimes #include <string.h> 60df3f5d9dSPeter Wemm #include <unistd.h> 610b7a57ddSRuslan Ermilov #include <netdb.h> 629b50d902SRodney W. Grimes 630daf62d9SStanislav Sedov #include "functions.h" 649b50d902SRodney W. Grimes 65357050fcSEd Schouten static int fsflg, /* show files on same filesystem as file(s) argument */ 669b50d902SRodney W. Grimes pflg, /* show files open by a particular pid */ 67*91ad311bSJeremie Le Hen sflg, /* show socket details */ 689b50d902SRodney W. Grimes uflg; /* show files open by a particular (effective) user */ 69357050fcSEd Schouten static int checkfile; /* restrict to particular files or filesystems */ 70357050fcSEd Schouten static int nflg; /* (numerical) display f.s. and rdev as dev_t */ 71357050fcSEd Schouten static int mflg; /* include memory-mapped files */ 72357050fcSEd Schouten static int vflg; /* be verbose */ 739b50d902SRodney W. Grimes 740daf62d9SStanislav Sedov typedef struct devs { 750daf62d9SStanislav Sedov struct devs *next; 7640ea8d27SAndriy Gapon uint64_t fsid; 770daf62d9SStanislav Sedov uint64_t ino; 780daf62d9SStanislav Sedov const char *name; 790daf62d9SStanislav Sedov } DEVS; 809b50d902SRodney W. Grimes 81357050fcSEd Schouten static DEVS *devs; 82357050fcSEd Schouten static char *memf, *nlistf; 839b50d902SRodney W. Grimes 840daf62d9SStanislav Sedov static int getfname(const char *filename); 850daf62d9SStanislav Sedov static void dofiles(struct procstat *procstat, struct kinfo_proc *p); 860daf62d9SStanislav Sedov static void print_access_flags(int flags); 870daf62d9SStanislav Sedov static void print_file_info(struct procstat *procstat, 880daf62d9SStanislav Sedov struct filestat *fst, const char *uname, const char *cmd, int pid); 890daf62d9SStanislav Sedov static void print_pipe_info(struct procstat *procstat, 900daf62d9SStanislav Sedov struct filestat *fst); 910daf62d9SStanislav Sedov static void print_pts_info(struct procstat *procstat, 920daf62d9SStanislav Sedov struct filestat *fst); 93958aa575SJohn Baldwin static void print_sem_info(struct procstat *procstat, 94958aa575SJohn Baldwin struct filestat *fst); 95e506e182SJohn Baldwin static void print_shm_info(struct procstat *procstat, 96e506e182SJohn Baldwin struct filestat *fst); 970daf62d9SStanislav Sedov static void print_socket_info(struct procstat *procstat, 980daf62d9SStanislav Sedov struct filestat *fst); 990daf62d9SStanislav Sedov static void print_vnode_info(struct procstat *procstat, 1000daf62d9SStanislav Sedov struct filestat *fst); 1010daf62d9SStanislav Sedov static void usage(void) __dead2; 1021c17fc99SPeter Wemm 1031c17fc99SPeter Wemm int 1040daf62d9SStanislav Sedov do_fstat(int argc, char **argv) 1059b50d902SRodney W. Grimes { 1060daf62d9SStanislav Sedov struct kinfo_proc *p; 10727d57ea9SDavid Malone struct passwd *passwd; 1080daf62d9SStanislav Sedov struct procstat *procstat; 1099b50d902SRodney W. Grimes int arg, ch, what; 1100daf62d9SStanislav Sedov int cnt, i; 1119b50d902SRodney W. Grimes 1129b50d902SRodney W. Grimes arg = 0; 113f9feee17SEd Maste what = KERN_PROC_PROC; 1149b50d902SRodney W. Grimes nlistf = memf = NULL; 115*91ad311bSJeremie Le Hen while ((ch = getopt(argc, argv, "fmnp:su:vN:M:")) != -1) 1169b50d902SRodney W. Grimes switch((char)ch) { 1179b50d902SRodney W. Grimes case 'f': 1189b50d902SRodney W. Grimes fsflg = 1; 1199b50d902SRodney W. Grimes break; 1209b50d902SRodney W. Grimes case 'M': 1219b50d902SRodney W. Grimes memf = optarg; 1229b50d902SRodney W. Grimes break; 1239b50d902SRodney W. Grimes case 'N': 1249b50d902SRodney W. Grimes nlistf = optarg; 1259b50d902SRodney W. Grimes break; 126d0482be8SBrian Feldman case 'm': 127d0482be8SBrian Feldman mflg = 1; 128d0482be8SBrian Feldman break; 1299b50d902SRodney W. Grimes case 'n': 1309b50d902SRodney W. Grimes nflg = 1; 1319b50d902SRodney W. Grimes break; 1329b50d902SRodney W. Grimes case 'p': 1339b50d902SRodney W. Grimes if (pflg++) 1349b50d902SRodney W. Grimes usage(); 1359b50d902SRodney W. Grimes if (!isdigit(*optarg)) { 136c1e65942SPhilippe Charnier warnx("-p requires a process id"); 1379b50d902SRodney W. Grimes usage(); 1389b50d902SRodney W. Grimes } 1399b50d902SRodney W. Grimes what = KERN_PROC_PID; 1409b50d902SRodney W. Grimes arg = atoi(optarg); 1419b50d902SRodney W. Grimes break; 142*91ad311bSJeremie Le Hen case 's': 143*91ad311bSJeremie Le Hen sflg = 1; 144*91ad311bSJeremie Le Hen break; 1459b50d902SRodney W. Grimes case 'u': 1469b50d902SRodney W. Grimes if (uflg++) 1479b50d902SRodney W. Grimes usage(); 148c1e65942SPhilippe Charnier if (!(passwd = getpwnam(optarg))) 149c1e65942SPhilippe Charnier errx(1, "%s: unknown uid", optarg); 1509b50d902SRodney W. Grimes what = KERN_PROC_UID; 1519b50d902SRodney W. Grimes arg = passwd->pw_uid; 1529b50d902SRodney W. Grimes break; 1539b50d902SRodney W. Grimes case 'v': 1549b50d902SRodney W. Grimes vflg = 1; 1559b50d902SRodney W. Grimes break; 1569b50d902SRodney W. Grimes case '?': 1579b50d902SRodney W. Grimes default: 1589b50d902SRodney W. Grimes usage(); 1599b50d902SRodney W. Grimes } 1609b50d902SRodney W. Grimes 1619b50d902SRodney W. Grimes if (*(argv += optind)) { 1629b50d902SRodney W. Grimes for (; *argv; ++argv) { 1639b50d902SRodney W. Grimes if (getfname(*argv)) 1649b50d902SRodney W. Grimes checkfile = 1; 1659b50d902SRodney W. Grimes } 166487ac9acSUlrich Spörlein if (!checkfile) /* file(s) specified, but none accessible */ 1679b50d902SRodney W. Grimes exit(1); 1689b50d902SRodney W. Grimes } 1699b50d902SRodney W. Grimes 1709b50d902SRodney W. Grimes if (fsflg && !checkfile) { 1719b50d902SRodney W. Grimes /* -f with no files means use wd */ 1729b50d902SRodney W. Grimes if (getfname(".") == 0) 1739b50d902SRodney W. Grimes exit(1); 1749b50d902SRodney W. Grimes checkfile = 1; 1759b50d902SRodney W. Grimes } 1769b50d902SRodney W. Grimes 1771f910d6cSDag-Erling Smørgrav if (memf != NULL) 1780daf62d9SStanislav Sedov procstat = procstat_open_kvm(nlistf, memf); 1791f910d6cSDag-Erling Smørgrav else 1800daf62d9SStanislav Sedov procstat = procstat_open_sysctl(); 1810daf62d9SStanislav Sedov if (procstat == NULL) 1820daf62d9SStanislav Sedov errx(1, "procstat_open()"); 1830daf62d9SStanislav Sedov p = procstat_getprocs(procstat, what, arg, &cnt); 1840daf62d9SStanislav Sedov if (p == NULL) 1850daf62d9SStanislav Sedov errx(1, "procstat_getprocs()"); 1861f910d6cSDag-Erling Smørgrav 1870daf62d9SStanislav Sedov /* 1880daf62d9SStanislav Sedov * Print header. 1890daf62d9SStanislav Sedov */ 1901f910d6cSDag-Erling Smørgrav if (nflg) 1911f910d6cSDag-Erling Smørgrav printf("%s", 1921f910d6cSDag-Erling Smørgrav "USER CMD PID FD DEV INUM MODE SZ|DV R/W"); 1931f910d6cSDag-Erling Smørgrav else 1941f910d6cSDag-Erling Smørgrav printf("%s", 1951f910d6cSDag-Erling Smørgrav "USER CMD PID FD MOUNT INUM MODE SZ|DV R/W"); 1961f910d6cSDag-Erling Smørgrav if (checkfile && fsflg == 0) 1971f910d6cSDag-Erling Smørgrav printf(" NAME\n"); 1981f910d6cSDag-Erling Smørgrav else 1991f910d6cSDag-Erling Smørgrav putchar('\n'); 2000daf62d9SStanislav Sedov 2010daf62d9SStanislav Sedov /* 2020daf62d9SStanislav Sedov * Go through the process list. 2030daf62d9SStanislav Sedov */ 2040daf62d9SStanislav Sedov for (i = 0; i < cnt; i++) { 2050daf62d9SStanislav Sedov if (p[i].ki_stat == SZOMB) 2060daf62d9SStanislav Sedov continue; 2070daf62d9SStanislav Sedov dofiles(procstat, &p[i]); 2080daf62d9SStanislav Sedov } 2090daf62d9SStanislav Sedov procstat_freeprocs(procstat, p); 2100daf62d9SStanislav Sedov procstat_close(procstat); 2110daf62d9SStanislav Sedov return (0); 2121f910d6cSDag-Erling Smørgrav } 2131f910d6cSDag-Erling Smørgrav 2141f910d6cSDag-Erling Smørgrav static void 2150daf62d9SStanislav Sedov dofiles(struct procstat *procstat, struct kinfo_proc *kp) 2161f910d6cSDag-Erling Smørgrav { 2170daf62d9SStanislav Sedov const char *cmd; 2180daf62d9SStanislav Sedov const char *uname; 2190daf62d9SStanislav Sedov struct filestat *fst; 2200daf62d9SStanislav Sedov struct filestat_list *head; 2210daf62d9SStanislav Sedov int pid; 2221f910d6cSDag-Erling Smørgrav 2230daf62d9SStanislav Sedov uname = user_from_uid(kp->ki_uid, 0); 2240daf62d9SStanislav Sedov pid = kp->ki_pid; 2250daf62d9SStanislav Sedov cmd = kp->ki_comm; 2261f910d6cSDag-Erling Smørgrav 2270daf62d9SStanislav Sedov head = procstat_getfiles(procstat, kp, mflg); 2280daf62d9SStanislav Sedov if (head == NULL) 2290daf62d9SStanislav Sedov return; 2300daf62d9SStanislav Sedov STAILQ_FOREACH(fst, head, next) 2310daf62d9SStanislav Sedov print_file_info(procstat, fst, uname, cmd, pid); 2320daf62d9SStanislav Sedov procstat_freefiles(procstat, head); 2339b50d902SRodney W. Grimes } 2340daf62d9SStanislav Sedov 2351f910d6cSDag-Erling Smørgrav 2361f910d6cSDag-Erling Smørgrav static void 2370daf62d9SStanislav Sedov print_file_info(struct procstat *procstat, struct filestat *fst, 2380daf62d9SStanislav Sedov const char *uname, const char *cmd, int pid) 2391f910d6cSDag-Erling Smørgrav { 2400daf62d9SStanislav Sedov struct vnstat vn; 24127d57ea9SDavid Malone DEVS *d; 2420daf62d9SStanislav Sedov const char *filename; 2430daf62d9SStanislav Sedov int error, fsmatch = 0; 2440daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 2459b50d902SRodney W. Grimes 2460daf62d9SStanislav Sedov filename = NULL; 2470daf62d9SStanislav Sedov if (checkfile != 0) { 248b4fe201cSSergey Kandaurov if (fst->fs_type != PS_FST_TYPE_VNODE && 249b4fe201cSSergey Kandaurov fst->fs_type != PS_FST_TYPE_FIFO) 250e22c40faSSergey Kandaurov return; 251b4fe201cSSergey Kandaurov error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); 2520daf62d9SStanislav Sedov if (error != 0) 2530daf62d9SStanislav Sedov return; 2540daf62d9SStanislav Sedov 2559b50d902SRodney W. Grimes for (d = devs; d != NULL; d = d->next) 2560daf62d9SStanislav Sedov if (d->fsid == vn.vn_fsid) { 2579b50d902SRodney W. Grimes fsmatch = 1; 258e458cb77SGleb Kurtsou if (d->ino == vn.vn_fileid) { 2599b50d902SRodney W. Grimes filename = d->name; 2609b50d902SRodney W. Grimes break; 2619b50d902SRodney W. Grimes } 2629b50d902SRodney W. Grimes } 2639b50d902SRodney W. Grimes if (fsmatch == 0 || (filename == NULL && fsflg == 0)) 2649b50d902SRodney W. Grimes return; 2659b50d902SRodney W. Grimes } 2669b50d902SRodney W. Grimes 2670daf62d9SStanislav Sedov /* 2680daf62d9SStanislav Sedov * Print entry prefix. 2690daf62d9SStanislav Sedov */ 2700daf62d9SStanislav Sedov printf("%-8.8s %-10s %5d", uname, cmd, pid); 2710daf62d9SStanislav Sedov if (fst->fs_uflags & PS_FST_UFLAG_TEXT) 2720daf62d9SStanislav Sedov printf(" text"); 2730daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_CDIR) 2740daf62d9SStanislav Sedov printf(" wd"); 2750daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_RDIR) 2760daf62d9SStanislav Sedov printf(" root"); 2770daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_TRACE) 2780daf62d9SStanislav Sedov printf(" tr"); 2790daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_MMAP) 2800daf62d9SStanislav Sedov printf(" mmap"); 2810daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_JAIL) 2820daf62d9SStanislav Sedov printf(" jail"); 2830daf62d9SStanislav Sedov else if (fst->fs_uflags & PS_FST_UFLAG_CTTY) 2840daf62d9SStanislav Sedov printf(" ctty"); 2850daf62d9SStanislav Sedov else 2860daf62d9SStanislav Sedov printf(" %4d", fst->fs_fd); 2870daf62d9SStanislav Sedov 2880daf62d9SStanislav Sedov /* 2890daf62d9SStanislav Sedov * Print type-specific data. 2900daf62d9SStanislav Sedov */ 2910daf62d9SStanislav Sedov switch (fst->fs_type) { 2920daf62d9SStanislav Sedov case PS_FST_TYPE_FIFO: 2930daf62d9SStanislav Sedov case PS_FST_TYPE_VNODE: 2940daf62d9SStanislav Sedov print_vnode_info(procstat, fst); 2959b50d902SRodney W. Grimes break; 2960daf62d9SStanislav Sedov case PS_FST_TYPE_SOCKET: 2970daf62d9SStanislav Sedov print_socket_info(procstat, fst); 2980daf62d9SStanislav Sedov break; 2990daf62d9SStanislav Sedov case PS_FST_TYPE_PIPE: 3000daf62d9SStanislav Sedov print_pipe_info(procstat, fst); 3010daf62d9SStanislav Sedov break; 3020daf62d9SStanislav Sedov case PS_FST_TYPE_PTS: 3030daf62d9SStanislav Sedov print_pts_info(procstat, fst); 3040daf62d9SStanislav Sedov break; 305e506e182SJohn Baldwin case PS_FST_TYPE_SHM: 306e506e182SJohn Baldwin print_shm_info(procstat, fst); 307e506e182SJohn Baldwin break; 308958aa575SJohn Baldwin case PS_FST_TYPE_SEM: 309958aa575SJohn Baldwin print_sem_info(procstat, fst); 310958aa575SJohn Baldwin break; 311a66732deSKonstantin Belousov case PS_FST_TYPE_DEV: 312a66732deSKonstantin Belousov break; 3139b50d902SRodney W. Grimes default: 3140daf62d9SStanislav Sedov if (vflg) 3150daf62d9SStanislav Sedov fprintf(stderr, 3160daf62d9SStanislav Sedov "unknown file type %d for file %d of pid %d\n", 3170daf62d9SStanislav Sedov fst->fs_type, fst->fs_fd, pid); 3189b50d902SRodney W. Grimes } 3199b50d902SRodney W. Grimes if (filename && !fsflg) 3209b50d902SRodney W. Grimes printf(" %s", filename); 3219b50d902SRodney W. Grimes putchar('\n'); 3229b50d902SRodney W. Grimes } 3239b50d902SRodney W. Grimes 324*91ad311bSJeremie Le Hen static char * 325*91ad311bSJeremie Le Hen addr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen) 326*91ad311bSJeremie Le Hen { 327*91ad311bSJeremie Le Hen char buffer2[INET6_ADDRSTRLEN]; 328*91ad311bSJeremie Le Hen struct sockaddr_in6 *sin6; 329*91ad311bSJeremie Le Hen struct sockaddr_in *sin; 330*91ad311bSJeremie Le Hen struct sockaddr_un *sun; 331*91ad311bSJeremie Le Hen 332*91ad311bSJeremie Le Hen switch (ss->ss_family) { 333*91ad311bSJeremie Le Hen case AF_LOCAL: 334*91ad311bSJeremie Le Hen sun = (struct sockaddr_un *)ss; 335*91ad311bSJeremie Le Hen if (strlen(sun->sun_path) == 0) 336*91ad311bSJeremie Le Hen strlcpy(buffer, "-", buflen); 337*91ad311bSJeremie Le Hen else 338*91ad311bSJeremie Le Hen strlcpy(buffer, sun->sun_path, buflen); 339*91ad311bSJeremie Le Hen break; 340*91ad311bSJeremie Le Hen 341*91ad311bSJeremie Le Hen case AF_INET: 342*91ad311bSJeremie Le Hen sin = (struct sockaddr_in *)ss; 343*91ad311bSJeremie Le Hen if (sin->sin_addr.s_addr == INADDR_ANY) 344*91ad311bSJeremie Le Hen snprintf(buffer, buflen, "%s:%d", "*", 345*91ad311bSJeremie Le Hen ntohs(sin->sin_port)); 346*91ad311bSJeremie Le Hen else if (inet_ntop(AF_INET, &sin->sin_addr, buffer2, 347*91ad311bSJeremie Le Hen sizeof(buffer2)) != NULL) 348*91ad311bSJeremie Le Hen snprintf(buffer, buflen, "%s:%d", buffer2, 349*91ad311bSJeremie Le Hen ntohs(sin->sin_port)); 350*91ad311bSJeremie Le Hen break; 351*91ad311bSJeremie Le Hen 352*91ad311bSJeremie Le Hen case AF_INET6: 353*91ad311bSJeremie Le Hen sin6 = (struct sockaddr_in6 *)ss; 354*91ad311bSJeremie Le Hen if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) 355*91ad311bSJeremie Le Hen snprintf(buffer, buflen, "%s.%d", "*", 356*91ad311bSJeremie Le Hen ntohs(sin6->sin6_port)); 357*91ad311bSJeremie Le Hen else if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2, 358*91ad311bSJeremie Le Hen sizeof(buffer2)) != NULL) 359*91ad311bSJeremie Le Hen snprintf(buffer, buflen, "%s.%d", buffer2, 360*91ad311bSJeremie Le Hen ntohs(sin6->sin6_port)); 361*91ad311bSJeremie Le Hen else 362*91ad311bSJeremie Le Hen strlcpy(buffer, "-", buflen); 363*91ad311bSJeremie Le Hen break; 364*91ad311bSJeremie Le Hen 365*91ad311bSJeremie Le Hen default: 366*91ad311bSJeremie Le Hen strlcpy(buffer, "", buflen); 367*91ad311bSJeremie Le Hen break; 368*91ad311bSJeremie Le Hen } 369*91ad311bSJeremie Le Hen return buffer; 370*91ad311bSJeremie Le Hen } 371*91ad311bSJeremie Le Hen 372*91ad311bSJeremie Le Hen 3730daf62d9SStanislav Sedov static void 3740daf62d9SStanislav Sedov print_socket_info(struct procstat *procstat, struct filestat *fst) 3759b50d902SRodney W. Grimes { 37627d57ea9SDavid Malone static const char *stypename[] = { 3779b50d902SRodney W. Grimes "unused", /* 0 */ 3789b50d902SRodney W. Grimes "stream", /* 1 */ 3799b50d902SRodney W. Grimes "dgram", /* 2 */ 3809b50d902SRodney W. Grimes "raw", /* 3 */ 3819b50d902SRodney W. Grimes "rdm", /* 4 */ 3829b50d902SRodney W. Grimes "seqpak" /* 5 */ 3839b50d902SRodney W. Grimes }; 3849b50d902SRodney W. Grimes #define STYPEMAX 5 3850daf62d9SStanislav Sedov struct sockstat sock; 3860daf62d9SStanislav Sedov struct protoent *pe; 3870daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 388*91ad311bSJeremie Le Hen char src_addr[PATH_MAX], dst_addr[PATH_MAX]; 389*91ad311bSJeremie Le Hen struct sockaddr_un *sun; 3900daf62d9SStanislav Sedov int error; 3910daf62d9SStanislav Sedov static int isopen; 3929b50d902SRodney W. Grimes 3930daf62d9SStanislav Sedov error = procstat_get_socket_info(procstat, fst, &sock, errbuf); 3940daf62d9SStanislav Sedov if (error != 0) { 3950daf62d9SStanislav Sedov printf("* error"); 3960daf62d9SStanislav Sedov return; 3979b50d902SRodney W. Grimes } 3980daf62d9SStanislav Sedov if (sock.type > STYPEMAX) 3990daf62d9SStanislav Sedov printf("* %s ?%d", sock.dname, sock.type); 4009b50d902SRodney W. Grimes else 4010daf62d9SStanislav Sedov printf("* %s %s", sock.dname, stypename[sock.type]); 4029b50d902SRodney W. Grimes 4039b50d902SRodney W. Grimes /* 4049b50d902SRodney W. Grimes * protocol specific formatting 4059b50d902SRodney W. Grimes * 4069b50d902SRodney W. Grimes * Try to find interesting things to print. For tcp, the interesting 4079b50d902SRodney W. Grimes * thing is the address of the tcpcb, for udp and others, just the 4089b50d902SRodney W. Grimes * inpcb (socket pcb). For unix domain, its the address of the socket 4099b50d902SRodney W. Grimes * pcb and the address of the connected pcb (if connected). Otherwise 4109b50d902SRodney W. Grimes * just print the protocol number and address of the socket itself. 4119b50d902SRodney W. Grimes * The idea is not to duplicate netstat, but to make available enough 4129b50d902SRodney W. Grimes * information for further analysis. 4139b50d902SRodney W. Grimes */ 4140daf62d9SStanislav Sedov switch (sock.dom_family) { 4159b50d902SRodney W. Grimes case AF_INET: 416677e00c0SYoshinobu Inoue case AF_INET6: 4170daf62d9SStanislav Sedov if (!isopen) 4180daf62d9SStanislav Sedov setprotoent(++isopen); 4190daf62d9SStanislav Sedov if ((pe = getprotobynumber(sock.proto)) != NULL) 4200daf62d9SStanislav Sedov printf(" %s", pe->p_name); 4210daf62d9SStanislav Sedov else 4220daf62d9SStanislav Sedov printf(" %d", sock.proto); 4230daf62d9SStanislav Sedov if (sock.proto == IPPROTO_TCP ) { 4240daf62d9SStanislav Sedov if (sock.inp_ppcb != 0) 4250daf62d9SStanislav Sedov printf(" %lx", (u_long)sock.inp_ppcb); 4269b50d902SRodney W. Grimes } 4270daf62d9SStanislav Sedov else if (sock.so_pcb != 0) 4280daf62d9SStanislav Sedov printf(" %lx", (u_long)sock.so_pcb); 429*91ad311bSJeremie Le Hen if (!sflg) 430*91ad311bSJeremie Le Hen break; 431*91ad311bSJeremie Le Hen printf(" %s <-> %s", 432*91ad311bSJeremie Le Hen addr_to_string(&sock.sa_local, src_addr, sizeof(src_addr)), 433*91ad311bSJeremie Le Hen addr_to_string(&sock.sa_peer, dst_addr, sizeof(dst_addr))); 4349b50d902SRodney W. Grimes break; 4359b50d902SRodney W. Grimes case AF_UNIX: 4369b50d902SRodney W. Grimes /* print address of pcb and connected pcb */ 4370daf62d9SStanislav Sedov if (sock.so_pcb != 0) { 4380daf62d9SStanislav Sedov printf(" %lx", (u_long)sock.so_pcb); 4390daf62d9SStanislav Sedov if (sock.unp_conn) { 4409b50d902SRodney W. Grimes char shoconn[4], *cp; 4419b50d902SRodney W. Grimes 4429b50d902SRodney W. Grimes cp = shoconn; 4430daf62d9SStanislav Sedov if (!(sock.so_rcv_sb_state & SBS_CANTRCVMORE)) 4449b50d902SRodney W. Grimes *cp++ = '<'; 4459b50d902SRodney W. Grimes *cp++ = '-'; 4460daf62d9SStanislav Sedov if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE)) 4479b50d902SRodney W. Grimes *cp++ = '>'; 4489b50d902SRodney W. Grimes *cp = '\0'; 449df94d4d2SMatt Jacob printf(" %s %lx", shoconn, 4500daf62d9SStanislav Sedov (u_long)sock.unp_conn); 4519b50d902SRodney W. Grimes } 4529b50d902SRodney W. Grimes } 453*91ad311bSJeremie Le Hen if (!sflg) 454*91ad311bSJeremie Le Hen break; 455*91ad311bSJeremie Le Hen sun = (struct sockaddr_un *)&sock.sa_local; 456*91ad311bSJeremie Le Hen /* 457*91ad311bSJeremie Le Hen * While generally we like to print two addresses, 458*91ad311bSJeremie Le Hen * local and peer, for sockets, it turns out to be 459*91ad311bSJeremie Le Hen * more useful to print the first non-null address for 460*91ad311bSJeremie Le Hen * local sockets, as typically they aren't bound and 461*91ad311bSJeremie Le Hen * connected, and the path strings can get long. 462*91ad311bSJeremie Le Hen */ 463*91ad311bSJeremie Le Hen if (sun->sun_path[0] != 0) 464*91ad311bSJeremie Le Hen addr_to_string(&sock.sa_local, 465*91ad311bSJeremie Le Hen src_addr, sizeof(src_addr)); 466*91ad311bSJeremie Le Hen else 467*91ad311bSJeremie Le Hen addr_to_string(&sock.sa_peer, 468*91ad311bSJeremie Le Hen src_addr, sizeof(src_addr)); 469*91ad311bSJeremie Le Hen printf(" %s", src_addr); 4709b50d902SRodney W. Grimes break; 4719b50d902SRodney W. Grimes default: 4729b50d902SRodney W. Grimes /* print protocol number and socket address */ 4730daf62d9SStanislav Sedov printf(" %d %lx", sock.proto, (u_long)sock.so_addr); 4749b50d902SRodney W. Grimes } 4759b50d902SRodney W. Grimes } 4769b50d902SRodney W. Grimes 4770daf62d9SStanislav Sedov static void 4780daf62d9SStanislav Sedov print_pipe_info(struct procstat *procstat, struct filestat *fst) 479bc093719SEd Schouten { 4800daf62d9SStanislav Sedov struct pipestat ps; 4810daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 4820daf62d9SStanislav Sedov int error; 4830daf62d9SStanislav Sedov 4840daf62d9SStanislav Sedov error = procstat_get_pipe_info(procstat, fst, &ps, errbuf); 4850daf62d9SStanislav Sedov if (error != 0) { 4860daf62d9SStanislav Sedov printf("* error"); 4870daf62d9SStanislav Sedov return; 4880daf62d9SStanislav Sedov } 4890daf62d9SStanislav Sedov printf("* pipe %8lx <-> %8lx", (u_long)ps.addr, (u_long)ps.peer); 4900daf62d9SStanislav Sedov printf(" %6zd", ps.buffer_cnt); 4910daf62d9SStanislav Sedov print_access_flags(fst->fs_fflags); 4920daf62d9SStanislav Sedov } 4930daf62d9SStanislav Sedov 4940daf62d9SStanislav Sedov static void 4950daf62d9SStanislav Sedov print_pts_info(struct procstat *procstat, struct filestat *fst) 4960daf62d9SStanislav Sedov { 4970daf62d9SStanislav Sedov struct ptsstat pts; 4980daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 4990daf62d9SStanislav Sedov int error; 5000daf62d9SStanislav Sedov 5010daf62d9SStanislav Sedov error = procstat_get_pts_info(procstat, fst, &pts, errbuf); 5020daf62d9SStanislav Sedov if (error != 0) { 5030daf62d9SStanislav Sedov printf("* error"); 5040daf62d9SStanislav Sedov return; 5050daf62d9SStanislav Sedov } 5060daf62d9SStanislav Sedov printf("* pseudo-terminal master "); 5070daf62d9SStanislav Sedov if (nflg || !*pts.devname) { 5089f365aa1SEd Schouten printf("%#10jx", (uintmax_t)pts.dev); 5090daf62d9SStanislav Sedov } else { 5100daf62d9SStanislav Sedov printf("%10s", pts.devname); 5110daf62d9SStanislav Sedov } 5120daf62d9SStanislav Sedov print_access_flags(fst->fs_fflags); 5130daf62d9SStanislav Sedov } 5140daf62d9SStanislav Sedov 5150daf62d9SStanislav Sedov static void 516958aa575SJohn Baldwin print_sem_info(struct procstat *procstat, struct filestat *fst) 517958aa575SJohn Baldwin { 518958aa575SJohn Baldwin struct semstat sem; 519958aa575SJohn Baldwin char errbuf[_POSIX2_LINE_MAX]; 520958aa575SJohn Baldwin char mode[15]; 521958aa575SJohn Baldwin int error; 522958aa575SJohn Baldwin 523958aa575SJohn Baldwin error = procstat_get_sem_info(procstat, fst, &sem, errbuf); 524958aa575SJohn Baldwin if (error != 0) { 525958aa575SJohn Baldwin printf("* error"); 526958aa575SJohn Baldwin return; 527958aa575SJohn Baldwin } 528958aa575SJohn Baldwin if (nflg) { 529958aa575SJohn Baldwin printf(" "); 530958aa575SJohn Baldwin (void)snprintf(mode, sizeof(mode), "%o", sem.mode); 531958aa575SJohn Baldwin } else { 532958aa575SJohn Baldwin printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-"); 533958aa575SJohn Baldwin strmode(sem.mode, mode); 534958aa575SJohn Baldwin } 535958aa575SJohn Baldwin printf(" %10s %6u", mode, sem.value); 536958aa575SJohn Baldwin print_access_flags(fst->fs_fflags); 537958aa575SJohn Baldwin } 538958aa575SJohn Baldwin 539958aa575SJohn Baldwin static void 540e506e182SJohn Baldwin print_shm_info(struct procstat *procstat, struct filestat *fst) 541e506e182SJohn Baldwin { 542e506e182SJohn Baldwin struct shmstat shm; 543e506e182SJohn Baldwin char errbuf[_POSIX2_LINE_MAX]; 544e506e182SJohn Baldwin char mode[15]; 545e506e182SJohn Baldwin int error; 546e506e182SJohn Baldwin 547e506e182SJohn Baldwin error = procstat_get_shm_info(procstat, fst, &shm, errbuf); 548e506e182SJohn Baldwin if (error != 0) { 549e506e182SJohn Baldwin printf("* error"); 550e506e182SJohn Baldwin return; 551e506e182SJohn Baldwin } 552e506e182SJohn Baldwin if (nflg) { 553e506e182SJohn Baldwin printf(" "); 554e506e182SJohn Baldwin (void)snprintf(mode, sizeof(mode), "%o", shm.mode); 555e506e182SJohn Baldwin } else { 556e506e182SJohn Baldwin printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-"); 557e506e182SJohn Baldwin strmode(shm.mode, mode); 558e506e182SJohn Baldwin } 559e506e182SJohn Baldwin printf(" %10s %6ju", mode, shm.size); 560e506e182SJohn Baldwin print_access_flags(fst->fs_fflags); 561e506e182SJohn Baldwin } 562e506e182SJohn Baldwin 563e506e182SJohn Baldwin static void 5640daf62d9SStanislav Sedov print_vnode_info(struct procstat *procstat, struct filestat *fst) 5650daf62d9SStanislav Sedov { 5660daf62d9SStanislav Sedov struct vnstat vn; 5670daf62d9SStanislav Sedov char errbuf[_POSIX2_LINE_MAX]; 5680daf62d9SStanislav Sedov char mode[15]; 5690daf62d9SStanislav Sedov const char *badtype; 5700daf62d9SStanislav Sedov int error; 5710daf62d9SStanislav Sedov 5720daf62d9SStanislav Sedov badtype = NULL; 5730daf62d9SStanislav Sedov error = procstat_get_vnode_info(procstat, fst, &vn, errbuf); 5740daf62d9SStanislav Sedov if (error != 0) 5750daf62d9SStanislav Sedov badtype = errbuf; 5760daf62d9SStanislav Sedov else if (vn.vn_type == PS_FST_VTYPE_VBAD) 5770daf62d9SStanislav Sedov badtype = "bad"; 5780daf62d9SStanislav Sedov else if (vn.vn_type == PS_FST_VTYPE_VNON) 5790daf62d9SStanislav Sedov badtype = "none"; 5800daf62d9SStanislav Sedov if (badtype != NULL) { 5810daf62d9SStanislav Sedov printf(" - - %10s -", badtype); 5820daf62d9SStanislav Sedov return; 5830daf62d9SStanislav Sedov } 5840daf62d9SStanislav Sedov 5850daf62d9SStanislav Sedov if (nflg) 58605806a06SEd Schouten printf(" %#5jx", (uintmax_t)vn.vn_fsid); 5870daf62d9SStanislav Sedov else if (vn.vn_mntdir != NULL) 5880daf62d9SStanislav Sedov (void)printf(" %-8s", vn.vn_mntdir); 5890daf62d9SStanislav Sedov 5900daf62d9SStanislav Sedov /* 5910daf62d9SStanislav Sedov * Print access mode. 5920daf62d9SStanislav Sedov */ 5930daf62d9SStanislav Sedov if (nflg) 5940daf62d9SStanislav Sedov (void)snprintf(mode, sizeof(mode), "%o", vn.vn_mode); 5950daf62d9SStanislav Sedov else { 5960daf62d9SStanislav Sedov strmode(vn.vn_mode, mode); 5970daf62d9SStanislav Sedov } 59876db9ccfSWarner Losh (void)printf(" %6jd %10s", (intmax_t)vn.vn_fileid, mode); 5990daf62d9SStanislav Sedov 6000daf62d9SStanislav Sedov if (vn.vn_type == PS_FST_VTYPE_VBLK || vn.vn_type == PS_FST_VTYPE_VCHR) { 6010daf62d9SStanislav Sedov if (nflg || !*vn.vn_devname) 6029f365aa1SEd Schouten printf(" %#6jx", (uintmax_t)vn.vn_dev); 6030daf62d9SStanislav Sedov else { 6040daf62d9SStanislav Sedov printf(" %6s", vn.vn_devname); 6050daf62d9SStanislav Sedov } 6060daf62d9SStanislav Sedov } else 6078d917b4bSWarner Losh printf(" %6ju", (uintmax_t)vn.vn_size); 6080daf62d9SStanislav Sedov print_access_flags(fst->fs_fflags); 6090daf62d9SStanislav Sedov } 6100daf62d9SStanislav Sedov 6110daf62d9SStanislav Sedov static void 6120daf62d9SStanislav Sedov print_access_flags(int flags) 6130daf62d9SStanislav Sedov { 614bc093719SEd Schouten char rw[3]; 615bc093719SEd Schouten 616bc093719SEd Schouten rw[0] = '\0'; 6170daf62d9SStanislav Sedov if (flags & PS_FST_FFLAG_READ) 618bc093719SEd Schouten strcat(rw, "r"); 6190daf62d9SStanislav Sedov if (flags & PS_FST_FFLAG_WRITE) 620bc093719SEd Schouten strcat(rw, "w"); 6210daf62d9SStanislav Sedov printf(" %2s", rw); 6229b50d902SRodney W. Grimes } 6239b50d902SRodney W. Grimes 6241c17fc99SPeter Wemm int 6251e925017SDavid Malone getfname(const char *filename) 6269b50d902SRodney W. Grimes { 6279b50d902SRodney W. Grimes struct stat statbuf; 6289b50d902SRodney W. Grimes DEVS *cur; 6299b50d902SRodney W. Grimes 6309b50d902SRodney W. Grimes if (stat(filename, &statbuf)) { 631c1e65942SPhilippe Charnier warn("%s", filename); 6329b50d902SRodney W. Grimes return (0); 6339b50d902SRodney W. Grimes } 634c1e65942SPhilippe Charnier if ((cur = malloc(sizeof(DEVS))) == NULL) 635c1e65942SPhilippe Charnier err(1, NULL); 6369b50d902SRodney W. Grimes cur->next = devs; 6379b50d902SRodney W. Grimes devs = cur; 6389b50d902SRodney W. Grimes 6399b50d902SRodney W. Grimes cur->ino = statbuf.st_ino; 640b628b0dcSDavid Malone cur->fsid = statbuf.st_dev; 6419b50d902SRodney W. Grimes cur->name = filename; 6429b50d902SRodney W. Grimes return (1); 6439b50d902SRodney W. Grimes } 6449b50d902SRodney W. Grimes 6450daf62d9SStanislav Sedov static void 6461e925017SDavid Malone usage(void) 6479b50d902SRodney W. Grimes { 6489b50d902SRodney W. Grimes (void)fprintf(stderr, 649f682f10cSRuslan Ermilov "usage: fstat [-fmnv] [-M core] [-N system] [-p pid] [-u user] [file ...]\n"); 6509b50d902SRodney W. Grimes exit(1); 6519b50d902SRodney W. Grimes } 652