1174199Srwatson/*- 2224859Srwatson * Copyright (c) 2007-2011 Robert N. M. Watson 3174199Srwatson * All rights reserved. 4174199Srwatson * 5174199Srwatson * Redistribution and use in source and binary forms, with or without 6174199Srwatson * modification, are permitted provided that the following conditions 7174199Srwatson * are met: 8174199Srwatson * 1. Redistributions of source code must retain the above copyright 9174199Srwatson * notice, this list of conditions and the following disclaimer. 10174199Srwatson * 2. Redistributions in binary form must reproduce the above copyright 11174199Srwatson * notice, this list of conditions and the following disclaimer in the 12174199Srwatson * documentation and/or other materials provided with the distribution. 13174199Srwatson * 14174199Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15174199Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16174199Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17174199Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18174199Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19174199Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20174199Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21174199Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22174199Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23174199Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24174199Srwatson * SUCH DAMAGE. 25174199Srwatson * 26174199Srwatson * $FreeBSD$ 27174199Srwatson */ 28174199Srwatson 29186567Srwatson#include <sys/param.h> 30280250Srwatson#include <sys/capsicum.h> 31174199Srwatson#include <sys/socket.h> 32174199Srwatson#include <sys/sysctl.h> 33174199Srwatson#include <sys/un.h> 34174199Srwatson#include <sys/user.h> 35174199Srwatson 36174199Srwatson#include <netinet/in.h> 37174199Srwatson 38174199Srwatson#include <arpa/inet.h> 39174199Srwatson 40200462Sdelphij#include <err.h> 41221807Sstas#include <libprocstat.h> 42174199Srwatson#include <inttypes.h> 43174199Srwatson#include <stdio.h> 44174199Srwatson#include <stdlib.h> 45174199Srwatson#include <string.h> 46174199Srwatson 47174199Srwatson#include "procstat.h" 48174199Srwatson 49174199Srwatsonstatic const char * 50174199Srwatsonprotocol_to_string(int domain, int type, int protocol) 51174199Srwatson{ 52174199Srwatson 53174199Srwatson switch (domain) { 54174199Srwatson case AF_INET: 55174199Srwatson case AF_INET6: 56174199Srwatson switch (protocol) { 57174199Srwatson case IPPROTO_TCP: 58174199Srwatson return ("TCP"); 59174199Srwatson case IPPROTO_UDP: 60174199Srwatson return ("UDP"); 61174199Srwatson case IPPROTO_ICMP: 62174530Srwatson return ("ICM"); 63174199Srwatson case IPPROTO_RAW: 64174199Srwatson return ("RAW"); 65174199Srwatson case IPPROTO_SCTP: 66174530Srwatson return ("SCT"); 67174530Srwatson case IPPROTO_DIVERT: 68174530Srwatson return ("IPD"); 69174199Srwatson default: 70174530Srwatson return ("IP?"); 71174199Srwatson } 72174199Srwatson 73174199Srwatson case AF_LOCAL: 74174199Srwatson switch (type) { 75174199Srwatson case SOCK_STREAM: 76174530Srwatson return ("UDS"); 77174199Srwatson case SOCK_DGRAM: 78174530Srwatson return ("UDD"); 79174199Srwatson default: 80174530Srwatson return ("UD?"); 81174199Srwatson } 82174199Srwatson default: 83174530Srwatson return ("?"); 84174199Srwatson } 85174199Srwatson} 86174199Srwatson 87174199Srwatsonstatic void 88174199Srwatsonaddr_to_string(struct sockaddr_storage *ss, char *buffer, int buflen) 89174199Srwatson{ 90174199Srwatson char buffer2[INET6_ADDRSTRLEN]; 91174199Srwatson struct sockaddr_in6 *sin6; 92174199Srwatson struct sockaddr_in *sin; 93174199Srwatson struct sockaddr_un *sun; 94174199Srwatson 95174199Srwatson switch (ss->ss_family) { 96174199Srwatson case AF_LOCAL: 97174199Srwatson sun = (struct sockaddr_un *)ss; 98174199Srwatson if (strlen(sun->sun_path) == 0) 99174199Srwatson strlcpy(buffer, "-", buflen); 100174199Srwatson else 101174199Srwatson strlcpy(buffer, sun->sun_path, buflen); 102174199Srwatson break; 103174199Srwatson 104174199Srwatson case AF_INET: 105174199Srwatson sin = (struct sockaddr_in *)ss; 106174199Srwatson snprintf(buffer, buflen, "%s:%d", inet_ntoa(sin->sin_addr), 107174199Srwatson ntohs(sin->sin_port)); 108174199Srwatson break; 109174199Srwatson 110174199Srwatson case AF_INET6: 111174199Srwatson sin6 = (struct sockaddr_in6 *)ss; 112174199Srwatson if (inet_ntop(AF_INET6, &sin6->sin6_addr, buffer2, 113174199Srwatson sizeof(buffer2)) != NULL) 114174199Srwatson snprintf(buffer, buflen, "%s.%d", buffer2, 115174199Srwatson ntohs(sin6->sin6_port)); 116174199Srwatson else 117268517Sdelphij strlcpy(buffer, "-", buflen); 118174199Srwatson break; 119174199Srwatson 120174199Srwatson default: 121174199Srwatson strlcpy(buffer, "", buflen); 122174199Srwatson break; 123174199Srwatson } 124174199Srwatson} 125174199Srwatson 126174199Srwatsonstatic void 127174199Srwatsonprint_address(struct sockaddr_storage *ss) 128174199Srwatson{ 129174199Srwatson char addr[PATH_MAX]; 130174199Srwatson 131174199Srwatson addr_to_string(ss, addr, sizeof(addr)); 132174530Srwatson printf("%s", addr); 133174199Srwatson} 134174199Srwatson 135224859Srwatsonstatic struct cap_desc { 136255219Spjd uint64_t cd_right; 137224859Srwatson const char *cd_desc; 138224859Srwatson} cap_desc[] = { 139224859Srwatson /* General file I/O. */ 140224859Srwatson { CAP_READ, "rd" }, 141224859Srwatson { CAP_WRITE, "wr" }, 142247602Spjd { CAP_SEEK, "se" }, 143224859Srwatson { CAP_MMAP, "mm" }, 144247602Spjd { CAP_CREATE, "cr" }, 145224859Srwatson { CAP_FEXECVE, "fe" }, 146224859Srwatson { CAP_FSYNC, "fy" }, 147224859Srwatson { CAP_FTRUNCATE, "ft" }, 148224859Srwatson 149224859Srwatson /* VFS methods. */ 150247602Spjd { CAP_FCHDIR, "cd" }, 151224859Srwatson { CAP_FCHFLAGS, "cf" }, 152224859Srwatson { CAP_FCHMOD, "cm" }, 153224859Srwatson { CAP_FCHOWN, "cn" }, 154224859Srwatson { CAP_FCNTL, "fc" }, 155247602Spjd { CAP_FLOCK, "fl" }, 156224859Srwatson { CAP_FPATHCONF, "fp" }, 157224859Srwatson { CAP_FSCK, "fk" }, 158224859Srwatson { CAP_FSTAT, "fs" }, 159224859Srwatson { CAP_FSTATFS, "sf" }, 160224859Srwatson { CAP_FUTIMES, "fu" }, 161247602Spjd { CAP_LINKAT, "li" }, 162247602Spjd { CAP_MKDIRAT, "md" }, 163247602Spjd { CAP_MKFIFOAT, "mf" }, 164247602Spjd { CAP_MKNODAT, "mn" }, 165247602Spjd { CAP_RENAMEAT, "rn" }, 166247602Spjd { CAP_SYMLINKAT, "sl" }, 167247602Spjd { CAP_UNLINKAT, "un" }, 168224859Srwatson 169247602Spjd /* Lookups - used to constrain *at() calls. */ 170224859Srwatson { CAP_LOOKUP, "lo" }, 171224859Srwatson 172224859Srwatson /* Extended attributes. */ 173224859Srwatson { CAP_EXTATTR_GET, "eg" }, 174224859Srwatson { CAP_EXTATTR_SET, "es" }, 175224859Srwatson { CAP_EXTATTR_DELETE, "ed" }, 176224859Srwatson { CAP_EXTATTR_LIST, "el" }, 177224859Srwatson 178224859Srwatson /* Access Control Lists. */ 179224859Srwatson { CAP_ACL_GET, "ag" }, 180224859Srwatson { CAP_ACL_SET, "as" }, 181224859Srwatson { CAP_ACL_DELETE, "ad" }, 182224859Srwatson { CAP_ACL_CHECK, "ac" }, 183224859Srwatson 184224859Srwatson /* Socket operations. */ 185224859Srwatson { CAP_ACCEPT, "at" }, 186224859Srwatson { CAP_BIND, "bd" }, 187224859Srwatson { CAP_CONNECT, "co" }, 188224859Srwatson { CAP_GETPEERNAME, "pn" }, 189224859Srwatson { CAP_GETSOCKNAME, "sn" }, 190224859Srwatson { CAP_GETSOCKOPT, "gs" }, 191224859Srwatson { CAP_LISTEN, "ln" }, 192224859Srwatson { CAP_PEELOFF, "pf" }, 193224859Srwatson { CAP_SETSOCKOPT, "ss" }, 194224859Srwatson { CAP_SHUTDOWN, "sh" }, 195224859Srwatson 196224859Srwatson /* Mandatory Access Control. */ 197224859Srwatson { CAP_MAC_GET, "mg" }, 198224859Srwatson { CAP_MAC_SET, "ms" }, 199224859Srwatson 200224859Srwatson /* Methods on semaphores. */ 201224859Srwatson { CAP_SEM_GETVALUE, "sg" }, 202224859Srwatson { CAP_SEM_POST, "sp" }, 203224859Srwatson { CAP_SEM_WAIT, "sw" }, 204224859Srwatson 205224859Srwatson /* Event monitoring and posting. */ 206258324Spjd { CAP_EVENT, "ev" }, 207258324Spjd { CAP_KQUEUE_EVENT, "ke" }, 208258324Spjd { CAP_KQUEUE_CHANGE, "kc" }, 209224859Srwatson 210224859Srwatson /* Strange and powerful rights that should not be given lightly. */ 211224859Srwatson { CAP_IOCTL, "io" }, 212224859Srwatson { CAP_TTYHOOK, "ty" }, 213224859Srwatson 214246644Spjd /* Process management via process descriptors. */ 215224859Srwatson { CAP_PDGETPID, "pg" }, 216246644Spjd { CAP_PDWAIT, "pw" }, 217224859Srwatson { CAP_PDKILL, "pk" }, 218247602Spjd 219247667Spjd /* 220247667Spjd * Rights that allow to use bindat(2) and connectat(2) syscalls on a 221247667Spjd * directory descriptor. 222247667Spjd */ 223247667Spjd { CAP_BINDAT, "ba" }, 224247667Spjd { CAP_CONNECTAT, "ca" }, 225247667Spjd 226247602Spjd /* Aliases and defines that combine multiple rights. */ 227247602Spjd { CAP_PREAD, "prd" }, 228247602Spjd { CAP_PWRITE, "pwr" }, 229247602Spjd 230247602Spjd { CAP_MMAP_R, "mmr" }, 231247602Spjd { CAP_MMAP_W, "mmw" }, 232247602Spjd { CAP_MMAP_X, "mmx" }, 233247602Spjd { CAP_MMAP_RW, "mrw" }, 234247602Spjd { CAP_MMAP_RX, "mrx" }, 235247602Spjd { CAP_MMAP_WX, "mwx" }, 236247602Spjd { CAP_MMAP_RWX, "mma" }, 237247602Spjd 238247602Spjd { CAP_RECV, "re" }, 239247602Spjd { CAP_SEND, "sd" }, 240247602Spjd 241247602Spjd { CAP_SOCK_CLIENT, "scl" }, 242247602Spjd { CAP_SOCK_SERVER, "ssr" }, 243224859Srwatson}; 244224859Srwatsonstatic const u_int cap_desc_count = sizeof(cap_desc) / 245224859Srwatson sizeof(cap_desc[0]); 246224859Srwatson 247224859Srwatsonstatic u_int 248255219Spjdwidth_capability(cap_rights_t *rightsp) 249224859Srwatson{ 250224859Srwatson u_int count, i, width; 251224859Srwatson 252224859Srwatson count = 0; 253224859Srwatson width = 0; 254224859Srwatson for (i = 0; i < cap_desc_count; i++) { 255255219Spjd if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) { 256224859Srwatson width += strlen(cap_desc[i].cd_desc); 257224859Srwatson if (count) 258224859Srwatson width++; 259224859Srwatson count++; 260224859Srwatson } 261224859Srwatson } 262224859Srwatson return (width); 263224859Srwatson} 264224859Srwatson 265224859Srwatsonstatic void 266255219Spjdprint_capability(cap_rights_t *rightsp, u_int capwidth) 267224859Srwatson{ 268224859Srwatson u_int count, i, width; 269224859Srwatson 270224859Srwatson count = 0; 271224859Srwatson width = 0; 272255219Spjd for (i = width_capability(rightsp); i < capwidth; i++) { 273255219Spjd if (i != 0) 274224859Srwatson printf(" "); 275224859Srwatson else 276224859Srwatson printf("-"); 277224859Srwatson } 278224859Srwatson for (i = 0; i < cap_desc_count; i++) { 279255219Spjd if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) { 280224859Srwatson printf("%s%s", count ? "," : "", cap_desc[i].cd_desc); 281224859Srwatson width += strlen(cap_desc[i].cd_desc); 282224859Srwatson if (count) 283224859Srwatson width++; 284224859Srwatson count++; 285224859Srwatson } 286224859Srwatson } 287224859Srwatson} 288224859Srwatson 289174199Srwatsonvoid 290221807Sstasprocstat_files(struct procstat *procstat, struct kinfo_proc *kipp) 291247602Spjd{ 292221807Sstas struct sockstat sock; 293221807Sstas struct filestat_list *head; 294221807Sstas struct filestat *fst; 295174199Srwatson const char *str; 296221807Sstas struct vnstat vn; 297224859Srwatson u_int capwidth, width; 298221807Sstas int error; 299174199Srwatson 300224859Srwatson /* 301224859Srwatson * To print the header in capability mode, we need to know the width 302224859Srwatson * of the widest capability string. Even if we get no processes 303224859Srwatson * back, we will print the header, so we defer aborting due to a lack 304224859Srwatson * of processes until after the header logic. 305224859Srwatson */ 306224859Srwatson capwidth = 0; 307224859Srwatson head = procstat_getfiles(procstat, kipp, 0); 308224859Srwatson if (head != NULL && Cflag) { 309224859Srwatson STAILQ_FOREACH(fst, head, next) { 310255219Spjd width = width_capability(&fst->fs_cap_rights); 311224859Srwatson if (width > capwidth) 312224859Srwatson capwidth = width; 313224859Srwatson } 314224859Srwatson if (capwidth < strlen("CAPABILITIES")) 315224859Srwatson capwidth = strlen("CAPABILITIES"); 316224859Srwatson } 317174199Srwatson 318224859Srwatson if (!hflag) { 319224859Srwatson if (Cflag) 320224859Srwatson printf("%5s %-16s %4s %1s %-9s %-*s " 321224859Srwatson "%-3s %-12s\n", "PID", "COMM", "FD", "T", 322224859Srwatson "FLAGS", capwidth, "CAPABILITIES", "PRO", 323224859Srwatson "NAME"); 324224859Srwatson else 325224859Srwatson printf("%5s %-16s %4s %1s %1s %-9s " 326224859Srwatson "%3s %7s %-3s %-12s\n", "PID", "COMM", "FD", "T", 327224859Srwatson "V", "FLAGS", "REF", "OFFSET", "PRO", "NAME"); 328224859Srwatson } 329224859Srwatson 330221807Sstas if (head == NULL) 331186315Smarcus return; 332221807Sstas STAILQ_FOREACH(fst, head, next) { 333221807Sstas printf("%5d ", kipp->ki_pid); 334174530Srwatson printf("%-16s ", kipp->ki_comm); 335221807Sstas if (fst->fs_uflags & PS_FST_UFLAG_CTTY) 336254485Spjd printf(" ctty "); 337221807Sstas else if (fst->fs_uflags & PS_FST_UFLAG_CDIR) 338254485Spjd printf(" cwd "); 339221807Sstas else if (fst->fs_uflags & PS_FST_UFLAG_JAIL) 340254485Spjd printf(" jail "); 341221807Sstas else if (fst->fs_uflags & PS_FST_UFLAG_RDIR) 342254485Spjd printf(" root "); 343221807Sstas else if (fst->fs_uflags & PS_FST_UFLAG_TEXT) 344254485Spjd printf(" text "); 345221807Sstas else if (fst->fs_uflags & PS_FST_UFLAG_TRACE) 346221807Sstas printf("trace "); 347221807Sstas else 348254485Spjd printf("%5d ", fst->fs_fd); 349176124Smarcus 350221807Sstas switch (fst->fs_type) { 351221807Sstas case PS_FST_TYPE_VNODE: 352174199Srwatson str = "v"; 353174199Srwatson break; 354174199Srwatson 355221807Sstas case PS_FST_TYPE_SOCKET: 356174199Srwatson str = "s"; 357174199Srwatson break; 358174199Srwatson 359221807Sstas case PS_FST_TYPE_PIPE: 360174199Srwatson str = "p"; 361174199Srwatson break; 362174199Srwatson 363221807Sstas case PS_FST_TYPE_FIFO: 364174199Srwatson str = "f"; 365174199Srwatson break; 366174199Srwatson 367221807Sstas case PS_FST_TYPE_KQUEUE: 368174199Srwatson str = "k"; 369174199Srwatson break; 370174199Srwatson 371221807Sstas case PS_FST_TYPE_CRYPTO: 372174199Srwatson str = "c"; 373174199Srwatson break; 374174199Srwatson 375221807Sstas case PS_FST_TYPE_MQUEUE: 376174199Srwatson str = "m"; 377174199Srwatson break; 378174199Srwatson 379221807Sstas case PS_FST_TYPE_SHM: 380175515Srwatson str = "h"; 381175515Srwatson break; 382175515Srwatson 383221807Sstas case PS_FST_TYPE_PTS: 384181905Sed str = "t"; 385181905Sed break; 386181905Sed 387221807Sstas case PS_FST_TYPE_SEM: 388180059Sjhb str = "e"; 389180059Sjhb break; 390180059Sjhb 391221807Sstas case PS_FST_TYPE_NONE: 392221807Sstas case PS_FST_TYPE_UNKNOWN: 393174199Srwatson default: 394174199Srwatson str = "?"; 395174199Srwatson break; 396174199Srwatson } 397174199Srwatson printf("%1s ", str); 398224859Srwatson if (!Cflag) { 399224859Srwatson str = "-"; 400224859Srwatson if (fst->fs_type == PS_FST_TYPE_VNODE) { 401224859Srwatson error = procstat_get_vnode_info(procstat, fst, 402224859Srwatson &vn, NULL); 403224859Srwatson switch (vn.vn_type) { 404224859Srwatson case PS_FST_VTYPE_VREG: 405224859Srwatson str = "r"; 406224859Srwatson break; 407174199Srwatson 408224859Srwatson case PS_FST_VTYPE_VDIR: 409224859Srwatson str = "d"; 410224859Srwatson break; 411174199Srwatson 412224859Srwatson case PS_FST_VTYPE_VBLK: 413224859Srwatson str = "b"; 414224859Srwatson break; 415174199Srwatson 416224859Srwatson case PS_FST_VTYPE_VCHR: 417224859Srwatson str = "c"; 418224859Srwatson break; 419174199Srwatson 420224859Srwatson case PS_FST_VTYPE_VLNK: 421224859Srwatson str = "l"; 422224859Srwatson break; 423174199Srwatson 424224859Srwatson case PS_FST_VTYPE_VSOCK: 425224859Srwatson str = "s"; 426224859Srwatson break; 427174199Srwatson 428224859Srwatson case PS_FST_VTYPE_VFIFO: 429224859Srwatson str = "f"; 430224859Srwatson break; 431174199Srwatson 432224859Srwatson case PS_FST_VTYPE_VBAD: 433224859Srwatson str = "x"; 434224859Srwatson break; 435174199Srwatson 436224859Srwatson case PS_FST_VTYPE_VNON: 437224859Srwatson case PS_FST_VTYPE_UNKNOWN: 438224859Srwatson default: 439224859Srwatson str = "?"; 440224859Srwatson break; 441224859Srwatson } 442174199Srwatson } 443224859Srwatson printf("%1s ", str); 444174199Srwatson } 445221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_READ ? "r" : "-"); 446221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_WRITE ? "w" : "-"); 447221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_APPEND ? "a" : "-"); 448221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_ASYNC ? "s" : "-"); 449221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_SYNC ? "f" : "-"); 450221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_NONBLOCK ? "n" : "-"); 451221807Sstas printf("%s", fst->fs_fflags & PS_FST_FFLAG_DIRECT ? "d" : "-"); 452224859Srwatson printf("%s", fst->fs_fflags & PS_FST_FFLAG_HASLOCK ? "l" : "-"); 453224859Srwatson if (!Cflag) { 454224859Srwatson if (fst->fs_ref_count > -1) 455224859Srwatson printf("%3d ", fst->fs_ref_count); 456224859Srwatson else 457224859Srwatson printf("%3c ", '-'); 458224859Srwatson if (fst->fs_offset > -1) 459224859Srwatson printf("%7jd ", (intmax_t)fst->fs_offset); 460224859Srwatson else 461224859Srwatson printf("%7c ", '-'); 462224859Srwatson } 463224859Srwatson if (Cflag) { 464255219Spjd print_capability(&fst->fs_cap_rights, capwidth); 465224859Srwatson printf(" "); 466224859Srwatson } 467221807Sstas switch (fst->fs_type) { 468221807Sstas case PS_FST_TYPE_SOCKET: 469221807Sstas error = procstat_get_socket_info(procstat, fst, &sock, NULL); 470221807Sstas if (error != 0) 471221807Sstas break; 472174530Srwatson printf("%-3s ", 473221807Sstas protocol_to_string(sock.dom_family, 474221807Sstas sock.type, sock.proto)); 475174199Srwatson /* 476174199Srwatson * While generally we like to print two addresses, 477174199Srwatson * local and peer, for sockets, it turns out to be 478174199Srwatson * more useful to print the first non-nul address for 479174199Srwatson * local sockets, as typically they aren't bound and 480174199Srwatson * connected, and the path strings can get long. 481174199Srwatson */ 482221807Sstas if (sock.dom_family == AF_LOCAL) { 483174199Srwatson struct sockaddr_un *sun = 484221807Sstas (struct sockaddr_un *)&sock.sa_local; 485174199Srwatson 486174199Srwatson if (sun->sun_path[0] != 0) 487221807Sstas print_address(&sock.sa_local); 488174199Srwatson else 489221807Sstas print_address(&sock.sa_peer); 490174199Srwatson } else { 491221807Sstas print_address(&sock.sa_local); 492174199Srwatson printf(" "); 493221807Sstas print_address(&sock.sa_peer); 494174199Srwatson } 495174199Srwatson break; 496174199Srwatson 497174199Srwatson default: 498233760Sjhb printf("%-3s ", "-"); 499233760Sjhb printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-"); 500174199Srwatson } 501174199Srwatson 502174199Srwatson printf("\n"); 503174199Srwatson } 504240081Strociny procstat_freefiles(procstat, head); 505174199Srwatson} 506