4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / usr.bin / fstat / fstat.c
CommitLineData
7f9552fe 1/*-
84181c2c
KB
2 * Copyright (c) 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5ebc207c 4 *
7f9552fe 5 * %sccs.include.redist.c%
055eee28
KB
6 */
7
8#ifndef lint
84181c2c
KB
9static char copyright[] =
10"@(#) Copyright (c) 1988, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
5ebc207c 12#endif /* not lint */
055eee28
KB
13
14#ifndef lint
84181c2c 15static char sccsid[] = "@(#)fstat.c 8.1 (Berkeley) %G%";
5ebc207c 16#endif /* not lint */
055eee28 17
055eee28 18#include <sys/param.h>
49acea14 19#include <sys/time.h>
055eee28 20#include <sys/proc.h>
e1155dd7 21#include <sys/user.h>
055eee28 22#include <sys/stat.h>
3dae3806 23#include <sys/vnode.h>
055eee28
KB
24#include <sys/socket.h>
25#include <sys/socketvar.h>
26#include <sys/domain.h>
27#include <sys/protosw.h>
055eee28 28#include <sys/unpcb.h>
dc602bdf 29#include <sys/sysctl.h>
49acea14 30#include <sys/filedesc.h>
f255214c 31#define KERNEL
055eee28 32#include <sys/file.h>
b66366ba
KB
33#include <ufs/ufs/quota.h>
34#include <ufs/ufs/inode.h>
3433c8ac
KB
35#undef KERNEL
36#define NFS
37#include <sys/mount.h>
e00a6228 38#include <nfs/nfsv2.h>
68e0dca3 39#include <nfs/rpcv2.h>
e00a6228
MT
40#include <nfs/nfs.h>
41#include <nfs/nfsnode.h>
3433c8ac 42#undef NFS
e00a6228 43
1a585c5c
KB
44#include <net/route.h>
45#include <netinet/in.h>
e00a6228
MT
46#include <netinet/in_systm.h>
47#include <netinet/ip.h>
1a585c5c 48#include <netinet/in_pcb.h>
e00a6228 49
fa39b65c 50#include <ctype.h>
40a7fa18 51#include <errno.h>
829312ba 52#include <kvm.h>
fa39b65c
KB
53#include <nlist.h>
54#include <paths.h>
1a585c5c 55#include <pwd.h>
e00a6228 56#include <stdio.h>
829312ba 57#include <stdlib.h>
40a7fa18 58#include <string.h>
e1155dd7 59
e00a6228
MT
60#define TEXT -1
61#define CDIR -2
62#define RDIR -3
63#define TRACE -4
cf2c7bf9 64
f255214c 65typedef struct devs {
e00a6228 66 struct devs *next;
7f9552fe 67 long fsid;
e00a6228
MT
68 ino_t ino;
69 char *name;
f255214c 70} DEVS;
4575617f 71DEVS *devs;
5e369078 72
e00a6228
MT
73struct filestat {
74 long fsid;
75 long fileid;
7f9552fe 76 mode_t mode;
e00a6228
MT
77 u_long size;
78 dev_t rdev;
79};
80
7f9552fe 81#ifdef notdef
e00a6228 82struct nlist nl[] = {
055eee28
KB
83 { "" },
84};
7f9552fe 85#endif
055eee28 86
e00a6228
MT
87int fsflg, /* show files on same filesystem as file(s) argument */
88 pflg, /* show files open by a particular pid */
89 uflg; /* show files open by a particular (effective) user */
90int checkfile; /* true if restricting to particular files or filesystems */
91int nflg; /* (numerical) display f.s. and rdev as dev_t */
92int vflg; /* display errors in locating kernel data objects etc... */
f255214c 93
e00a6228 94#define dprintf if (vflg) fprintf
055eee28 95
49acea14
MT
96struct file **ofiles; /* buffer of pointers to file structures */
97int maxfiles;
98#define ALLOC_OFILES(d) \
99 if ((d) > maxfiles) { \
100 free(ofiles); \
40a7fa18 101 ofiles = malloc((d) * sizeof(struct file *)); \
49acea14 102 if (ofiles == NULL) { \
40a7fa18 103 fprintf(stderr, "fstat: %s\n", strerror(errno)); \
49acea14
MT
104 exit(1); \
105 } \
106 maxfiles = (d); \
107 }
108
109/*
110 * a kvm_read that returns true if everything is read
111 */
f3fad419
KB
112#define KVM_READ(kaddr, paddr, len) \
113 (kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (len))
114
115kvm_t *kd;
49acea14 116
2524719d
MT
117int ufs_filestat(), nfs_filestat();
118void dofiles(), getinetproto(), socktrans();
829312ba
KB
119void usage(), vtrans();
120
055eee28 121main(argc, argv)
4575617f
KB
122 int argc;
123 char **argv;
055eee28 124{
f255214c
KB
125 extern char *optarg;
126 extern int optind;
40a7fa18 127 register struct passwd *passwd;
f3fad419 128 struct kinfo_proc *p, *plast;
40a7fa18 129 int arg, ch, what;
ad07e3a9 130 char *memf, *nlistf;
f3fad419 131 int cnt;
e00a6228 132
40a7fa18 133 arg = 0;
dc602bdf 134 what = KERN_PROC_ALL;
ad07e3a9 135 nlistf = memf = NULL;
7cb64bc8 136 while ((ch = getopt(argc, argv, "fnp:u:vNM")) != EOF)
1a585c5c 137 switch((char)ch) {
40a7fa18
KB
138 case 'f':
139 fsflg = 1;
140 break;
ad07e3a9
KB
141 case 'M':
142 memf = optarg;
143 break;
144 case 'N':
145 nlistf = optarg;
146 break;
40a7fa18
KB
147 case 'n':
148 nflg = 1;
149 break;
1a585c5c 150 case 'p':
7168b138
MT
151 if (pflg++)
152 usage();
153 if (!isdigit(*optarg)) {
40a7fa18
KB
154 fprintf(stderr,
155 "fstat: -p requires a process id\n");
055eee28 156 usage();
055eee28 157 }
dc602bdf 158 what = KERN_PROC_PID;
e00a6228 159 arg = atoi(optarg);
1a585c5c
KB
160 break;
161 case 'u':
162 if (uflg++)
055eee28 163 usage();
f255214c 164 if (!(passwd = getpwnam(optarg))) {
7f9552fe 165 fprintf(stderr, "%s: unknown uid\n",
cf2c7bf9 166 optarg);
055eee28
KB
167 exit(1);
168 }
dc602bdf 169 what = KERN_PROC_UID;
e00a6228 170 arg = passwd->pw_uid;
1a585c5c 171 break;
e00a6228 172 case 'v':
40a7fa18 173 vflg = 1;
1a585c5c
KB
174 break;
175 case '?':
176 default:
177 usage();
055eee28 178 }
055eee28 179
5ebc207c 180 if (*(argv += optind)) {
193d3a86 181 for (; *argv; ++argv) {
5ebc207c 182 if (getfname(*argv))
e00a6228 183 checkfile = 1;
5ebc207c 184 }
e00a6228 185 if (!checkfile) /* file(s) specified, but none accessable */
5ebc207c 186 exit(1);
055eee28 187 }
49acea14 188
40a7fa18 189 ALLOC_OFILES(256); /* reserve space for file pointers */
49acea14 190
e00a6228
MT
191 if (fsflg && !checkfile) {
192 /* -f with no files means use wd */
193 if (getfname(".") == 0)
194 exit(1);
195 checkfile = 1;
196 }
d81abd9a 197
ad07e3a9
KB
198 /*
199 * Discard setgid privileges if not the running kernel so that bad
200 * guys can't print interesting stuff from kernel memory.
201 */
202 if (nlistf != NULL || memf != NULL)
203 setgid(getgid());
204
f3fad419
KB
205 if ((kd = kvm_open(nlistf, memf, NULL, O_RDONLY, NULL)) == NULL) {
206 fprintf(stderr, "fstat: %s\n", kvm_geterr(kd));
055eee28
KB
207 exit(1);
208 }
7f9552fe 209#ifdef notdef
f3fad419
KB
210 if (kvm_nlist(kd, nl) != 0) {
211 fprintf(stderr, "fstat: no namelist: %s\n", kvm_geterr(kd));
e00a6228
MT
212 exit(1);
213 }
7f9552fe 214#endif
f3fad419
KB
215 if ((p = kvm_getprocs(kd, what, arg, &cnt)) == NULL) {
216 fprintf(stderr, "fstat: %s\n", kvm_geterr(kd));
055eee28
KB
217 exit(1);
218 }
e00a6228 219 if (nflg)
40a7fa18 220 printf("%s",
2340eb0f 221"USER CMD PID FD DEV INUM MODE SZ|DV R/W");
e00a6228 222 else
40a7fa18 223 printf("%s",
2340eb0f 224"USER CMD PID FD MOUNT INUM MODE SZ|DV R/W");
e00a6228 225 if (checkfile && fsflg == 0)
40a7fa18 226 printf(" NAME\n");
e00a6228
MT
227 else
228 putchar('\n');
5ebc207c 229
f3fad419
KB
230 for (plast = &p[cnt]; p < plast; ++p) {
231 if (p->kp_proc.p_stat == SZOMB)
f255214c 232 continue;
e00a6228 233 dofiles(p);
f255214c
KB
234 }
235 exit(0);
055eee28
KB
236}
237
e00a6228
MT
238char *Uname, *Comm;
239int Pid;
240
e1155dd7 241#define PREFIX(i) printf("%-8.8s %-10s %5d", Uname, Comm, Pid); \
e00a6228
MT
242 switch(i) { \
243 case TEXT: \
40a7fa18 244 printf(" text"); \
e00a6228
MT
245 break; \
246 case CDIR: \
40a7fa18 247 printf(" wd"); \
e00a6228
MT
248 break; \
249 case RDIR: \
40a7fa18 250 printf(" root"); \
e00a6228
MT
251 break; \
252 case TRACE: \
40a7fa18 253 printf(" tr"); \
e00a6228
MT
254 break; \
255 default: \
256 printf(" %4d", i); \
257 break; \
055eee28 258 }
e00a6228
MT
259
260/*
261 * print open files attributed to this process
262 */
829312ba 263void
f3fad419
KB
264dofiles(kp)
265 struct kinfo_proc *kp;
e00a6228 266{
49acea14 267 int i, last;
e00a6228 268 struct file file;
e1155dd7
MT
269 struct filedesc0 filed0;
270#define filed filed0.fd_fd
f3fad419
KB
271 struct proc *p = &kp->kp_proc;
272 struct eproc *ep = &kp->kp_eproc;
49acea14 273
7f9552fe 274 extern char *user_from_uid();
e00a6228 275
e1155dd7 276 Uname = user_from_uid(ep->e_ucred.cr_uid, 0);
e00a6228
MT
277 Pid = p->p_pid;
278 Comm = p->p_comm;
279
49acea14
MT
280 if (p->p_fd == NULL)
281 return;
e1155dd7
MT
282 if (!KVM_READ(p->p_fd, &filed0, sizeof (filed0))) {
283 dprintf(stderr, "can't read filedesc at %x for pid %d\n",
284 p->p_fd, Pid);
285 return;
286 }
e00a6228
MT
287 /*
288 * root directory vnode, if one
289 */
49acea14 290 if (filed.fd_rdir)
2340eb0f 291 vtrans(filed.fd_rdir, RDIR, FREAD);
e00a6228
MT
292 /*
293 * current working directory vnode
294 */
2340eb0f 295 vtrans(filed.fd_cdir, CDIR, FREAD);
e00a6228
MT
296 /*
297 * ktrace vnode, if one
298 */
299 if (p->p_tracep)
2340eb0f 300 vtrans(p->p_tracep, TRACE, FREAD|FWRITE);
e00a6228
MT
301 /*
302 * open files
303 */
49acea14 304#define FPSIZE (sizeof (struct file *))
0ac13c53 305 ALLOC_OFILES(filed.fd_lastfile+1);
e1155dd7
MT
306 if (filed.fd_nfiles > NDFILE) {
307 if (!KVM_READ(filed.fd_ofiles, ofiles,
0ac13c53 308 (filed.fd_lastfile+1) * FPSIZE)) {
e1155dd7
MT
309 dprintf(stderr,
310 "can't read file structures at %x for pid %d\n",
311 filed.fd_ofiles, Pid);
312 return;
313 }
314 } else
0ac13c53 315 bcopy(filed0.fd_dfiles, ofiles, (filed.fd_lastfile+1) * FPSIZE);
0ac13c53 316 for (i = 0; i <= filed.fd_lastfile; i++) {
49acea14 317 if (ofiles[i] == NULL)
e00a6228 318 continue;
49acea14
MT
319 if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) {
320 dprintf(stderr, "can't read file %d at %x for pid %d\n",
321 i, ofiles[i], Pid);
e00a6228
MT
322 continue;
323 }
324 if (file.f_type == DTYPE_VNODE)
2340eb0f 325 vtrans((struct vnode *)file.f_data, i, file.f_flag);
7e7eb7a2
MT
326 else if (file.f_type == DTYPE_SOCKET) {
327 if (checkfile == 0)
328 socktrans((struct socket *)file.f_data, i);
329 }
e00a6228
MT
330 else {
331 dprintf(stderr,
332 "unknown file type %d for file %d of pid %d\n",
333 file.f_type, i, Pid);
055eee28
KB
334 }
335 }
055eee28
KB
336}
337
829312ba 338void
2340eb0f 339vtrans(vp, i, flag)
e00a6228 340 struct vnode *vp;
829312ba 341 int i;
2340eb0f 342 int flag;
055eee28 343{
e00a6228
MT
344 struct vnode vn;
345 struct filestat fst;
2340eb0f 346 char rw[3], mode[15];
7e7eb7a2 347 char *badtype = NULL, *filename, *getmnton();
e00a6228 348
829312ba
KB
349 filename = badtype = NULL;
350 if (!KVM_READ(vp, &vn, sizeof (struct vnode))) {
e00a6228
MT
351 dprintf(stderr, "can't read vnode at %x for pid %d\n",
352 vp, Pid);
055eee28
KB
353 return;
354 }
7f9552fe
MT
355 if (vn.v_type == VNON || vn.v_tag == VT_NON)
356 badtype = "none";
357 else if (vn.v_type == VBAD)
358 badtype = "bad";
359 else
360 switch (vn.v_tag) {
361 case VT_UFS:
2524719d
MT
362 if (!ufs_filestat(&vn, &fst))
363 badtype = "error";
7f9552fe
MT
364 break;
365 case VT_MFS:
2524719d
MT
366 if (!ufs_filestat(&vn, &fst))
367 badtype = "error";
7f9552fe
MT
368 break;
369 case VT_NFS:
2524719d
MT
370 if (!nfs_filestat(&vn, &fst))
371 badtype = "error";
7f9552fe
MT
372 break;
373 default: {
374 static char unknown[10];
375 sprintf(badtype = unknown, "?(%x)", vn.v_tag);
376 break;;
377 }
e00a6228
MT
378 }
379 if (checkfile) {
380 int fsmatch = 0;
381 register DEVS *d;
055eee28 382
7f9552fe 383 if (badtype)
1a585c5c 384 return;
e00a6228 385 for (d = devs; d != NULL; d = d->next)
7f9552fe 386 if (d->fsid == fst.fsid) {
e00a6228
MT
387 fsmatch = 1;
388 if (d->ino == fst.fileid) {
389 filename = d->name;
390 break;
391 }
3dae3806 392 }
e00a6228
MT
393 if (fsmatch == 0 || (filename == NULL && fsflg == 0))
394 return;
395 }
396 PREFIX(i);
7f9552fe
MT
397 if (badtype) {
398 (void)printf(" - - %10s -\n", badtype);
e00a6228 399 return;
055eee28 400 }
e00a6228 401 if (nflg)
7f9552fe 402 (void)printf(" %2d,%-2d", major(fst.fsid), minor(fst.fsid));
055eee28 403 else
7f9552fe
MT
404 (void)printf(" %-8s", getmnton(vn.v_mount));
405 if (nflg)
406 (void)sprintf(mode, "%o", fst.mode);
407 else
408 strmode(fst.mode, mode);
409 (void)printf(" %6d %10s", fst.fileid, mode);
e00a6228
MT
410 switch (vn.v_type) {
411 case VBLK:
7179a0b6
MT
412 case VCHR: {
413 char *name;
414
415 if (nflg || ((name = devname(fst.rdev, vn.v_type == VCHR ?
416 S_IFCHR : S_IFBLK)) == NULL))
e00a6228
MT
417 printf(" %2d,%-2d", major(fst.rdev), minor(fst.rdev));
418 else
7179a0b6 419 printf(" %6s", name);
e00a6228 420 break;
7179a0b6 421 }
f255214c 422 default:
e00a6228 423 printf(" %6d", fst.size);
055eee28 424 }
2340eb0f
KM
425 rw[0] = '\0';
426 if (flag & FREAD)
427 strcat(rw, "r");
428 if (flag & FWRITE)
429 strcat(rw, "w");
430 printf(" %2s", rw);
e00a6228 431 if (filename && !fsflg)
2340eb0f 432 printf(" %s", filename);
e00a6228
MT
433 putchar('\n');
434}
055eee28 435
2524719d 436int
e00a6228
MT
437ufs_filestat(vp, fsp)
438 struct vnode *vp;
439 struct filestat *fsp;
440{
2524719d
MT
441 struct inode inode;
442
443 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
444 dprintf(stderr, "can't read inode at %x for pid %d\n",
445 VTOI(vp), Pid);
446 return 0;
447 }
448 fsp->fsid = inode.i_dev & 0xffff;
449 fsp->fileid = (long)inode.i_number;
450 fsp->mode = (mode_t)inode.i_mode;
451 fsp->size = (u_long)inode.i_size;
452 fsp->rdev = inode.i_rdev;
3dae3806 453
2524719d 454 return 1;
e00a6228 455}
3dae3806 456
2524719d 457int
e00a6228
MT
458nfs_filestat(vp, fsp)
459 struct vnode *vp;
460 struct filestat *fsp;
461{
2524719d 462 struct nfsnode nfsnode;
7f9552fe 463 register mode_t mode;
3dae3806 464
2524719d
MT
465 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
466 dprintf(stderr, "can't read nfsnode at %x for pid %d\n",
467 VTONFS(vp), Pid);
468 return 0;
469 }
470 fsp->fsid = nfsnode.n_vattr.va_fsid;
471 fsp->fileid = nfsnode.n_vattr.va_fileid;
472 fsp->size = nfsnode.n_size;
473 fsp->rdev = nfsnode.n_vattr.va_rdev;
474 mode = (mode_t)nfsnode.n_vattr.va_mode;
7f9552fe
MT
475 switch (vp->v_type) {
476 case VREG:
477 mode |= S_IFREG;
478 break;
479 case VDIR:
480 mode |= S_IFDIR;
481 break;
482 case VBLK:
483 mode |= S_IFBLK;
484 break;
485 case VCHR:
486 mode |= S_IFCHR;
487 break;
488 case VLNK:
489 mode |= S_IFLNK;
490 break;
491 case VSOCK:
492 mode |= S_IFSOCK;
493 break;
494 case VFIFO:
495 mode |= S_IFIFO;
496 break;
497 };
498 fsp->mode = mode;
2524719d
MT
499
500 return 1;
e00a6228 501}
3dae3806 502
3dae3806 503
e00a6228
MT
504char *
505getmnton(m)
506 struct mount *m;
507{
508 static struct mount mount;
509 static struct mtab {
510 struct mtab *next;
511 struct mount *m;
512 char mntonname[MNAMELEN];
513 } *mhead = NULL;
514 register struct mtab *mt;
515
516 for (mt = mhead; mt != NULL; mt = mt->next)
517 if (m == mt->m)
518 return (mt->mntonname);
829312ba 519 if (!KVM_READ(m, &mount, sizeof(struct mount))) {
e00a6228
MT
520 fprintf(stderr, "can't read mount table at %x\n", m);
521 return (NULL);
055eee28 522 }
829312ba
KB
523 if ((mt = malloc(sizeof (struct mtab))) == NULL) {
524 fprintf(stderr, "fstat: %s\n", strerror(errno));
e00a6228
MT
525 exit(1);
526 }
527 mt->m = m;
7f9552fe 528 bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
e00a6228
MT
529 mt->next = mhead;
530 mhead = mt;
531 return (mt->mntonname);
055eee28 532}
1a585c5c 533
829312ba 534void
e00a6228 535socktrans(sock, i)
1a585c5c 536 struct socket *sock;
829312ba 537 int i;
055eee28 538{
f255214c 539 static char *stypename[] = {
1a585c5c
KB
540 "unused", /* 0 */
541 "stream", /* 1 */
542 "dgram", /* 2 */
543 "raw", /* 3 */
544 "rdm", /* 4 */
545 "seqpak" /* 5 */
546 };
547#define STYPEMAX 5
548 struct socket so;
549 struct protosw proto;
550 struct domain dom;
551 struct inpcb inpcb;
552 struct unpcb unpcb;
f255214c
KB
553 int len;
554 char dname[32], *strcpy();
055eee28 555
e00a6228
MT
556 PREFIX(i);
557
055eee28 558 /* fill in socket */
49acea14 559 if (!KVM_READ(sock, &so, sizeof(struct socket))) {
e00a6228 560 dprintf(stderr, "can't read sock at %x\n", sock);
7f9552fe 561 goto bad;
055eee28
KB
562 }
563
564 /* fill in protosw entry */
49acea14 565 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
e00a6228 566 dprintf(stderr, "can't read protosw at %x", so.so_proto);
7f9552fe 567 goto bad;
055eee28
KB
568 }
569
570 /* fill in domain */
49acea14 571 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
e00a6228 572 dprintf(stderr, "can't read domain at %x\n", proto.pr_domain);
7f9552fe 573 goto bad;
055eee28
KB
574 }
575
f3fad419
KB
576 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname,
577 sizeof(dname) - 1)) < 0) {
49acea14
MT
578 dprintf(stderr, "can't read domain name at %x\n",
579 dom.dom_name);
580 dname[0] = '\0';
1a585c5c 581 }
49acea14
MT
582 else
583 dname[len] = '\0';
055eee28 584
f255214c 585 if ((u_short)so.so_type > STYPEMAX)
7f9552fe 586 printf("* %s ?%d", dname, so.so_type);
f255214c 587 else
7f9552fe 588 printf("* %s %s", dname, stypename[so.so_type]);
055eee28
KB
589
590 /*
5ebc207c 591 * protocol specific formatting
055eee28 592 *
f255214c
KB
593 * Try to find interesting things to print. For tcp, the interesting
594 * thing is the address of the tcpcb, for udp and others, just the
595 * inpcb (socket pcb). For unix domain, its the address of the socket
596 * pcb and the address of the connected pcb (if connected). Otherwise
597 * just print the protocol number and address of the socket itself.
598 * The idea is not to duplicate netstat, but to make available enough
599 * information for further analysis.
055eee28 600 */
f255214c
KB
601 switch(dom.dom_family) {
602 case AF_INET:
603 getinetproto(proto.pr_protocol);
055eee28
KB
604 if (proto.pr_protocol == IPPROTO_TCP ) {
605 if (so.so_pcb) {
f3fad419
KB
606 if (kvm_read(kd, (u_long)so.so_pcb,
607 (char *)&inpcb, sizeof(struct inpcb))
829312ba 608 != sizeof(struct inpcb)) {
e00a6228 609 dprintf(stderr,
829312ba
KB
610 "can't read inpcb at %x\n",
611 so.so_pcb);
7f9552fe 612 goto bad;
055eee28 613 }
7f9552fe 614 printf(" %x", (int)inpcb.inp_ppcb);
055eee28 615 }
055eee28 616 }
1a585c5c 617 else if (so.so_pcb)
7f9552fe 618 printf(" %x", (int)so.so_pcb);
f255214c
KB
619 break;
620 case AF_UNIX:
055eee28
KB
621 /* print address of pcb and connected pcb */
622 if (so.so_pcb) {
7f9552fe 623 printf(" %x", (int)so.so_pcb);
f3fad419 624 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb,
829312ba 625 sizeof(struct unpcb)) != sizeof(struct unpcb)){
e00a6228 626 dprintf(stderr, "can't read unpcb at %x\n",
829312ba 627 so.so_pcb);
7f9552fe 628 goto bad;
055eee28 629 }
5e369078 630 if (unpcb.unp_conn) {
f255214c 631 char shoconn[4], *cp;
1a585c5c 632
f255214c 633 cp = shoconn;
5e369078 634 if (!(so.so_state & SS_CANTRCVMORE))
f255214c
KB
635 *cp++ = '<';
636 *cp++ = '-';
5e369078 637 if (!(so.so_state & SS_CANTSENDMORE))
f255214c
KB
638 *cp++ = '>';
639 *cp = '\0';
7f9552fe 640 printf(" %s %x", shoconn,
cf2c7bf9 641 (int)unpcb.unp_conn);
5e369078 642 }
055eee28 643 }
f255214c
KB
644 break;
645 default:
646 /* print protocol number and socket address */
7f9552fe 647 printf(" %d %x", proto.pr_protocol, (int)sock);
f255214c 648 }
7f9552fe
MT
649 printf("\n");
650 return;
651bad:
652 printf("* error\n");
055eee28
KB
653}
654
f255214c
KB
655/*
656 * getinetproto --
657 * print name of protocol number
658 */
829312ba 659void
055eee28 660getinetproto(number)
1a585c5c 661 int number;
055eee28 662{
1a585c5c 663 char *cp;
9bd38ba8 664
055eee28 665 switch(number) {
f255214c
KB
666 case IPPROTO_IP:
667 cp = "ip"; break;
668 case IPPROTO_ICMP:
669 cp ="icmp"; break;
670 case IPPROTO_GGP:
671 cp ="ggp"; break;
672 case IPPROTO_TCP:
673 cp ="tcp"; break;
674 case IPPROTO_EGP:
675 cp ="egp"; break;
676 case IPPROTO_PUP:
677 cp ="pup"; break;
678 case IPPROTO_UDP:
679 cp ="udp"; break;
680 case IPPROTO_IDP:
681 cp ="idp"; break;
682 case IPPROTO_RAW:
683 cp ="raw"; break;
9bd38ba8 684 default:
7f9552fe 685 printf(" %d", number);
f255214c 686 return;
055eee28 687 }
7f9552fe 688 printf(" %s", cp);
055eee28
KB
689}
690
055eee28 691getfname(filename)
1a585c5c 692 char *filename;
055eee28 693{
f255214c
KB
694 struct stat statbuf;
695 DEVS *cur;
055eee28 696
1a585c5c 697 if (stat(filename, &statbuf)) {
191bf8ce 698 fprintf(stderr, "fstat: %s: %s\n", filename, strerror(errno));
6270ab99 699 return(0);
1a585c5c 700 }
829312ba
KB
701 if ((cur = malloc(sizeof(DEVS))) == NULL) {
702 fprintf(stderr, "fstat: %s\n", strerror(errno));
f255214c
KB
703 exit(1);
704 }
705 cur->next = devs;
706 devs = cur;
055eee28 707
e00a6228 708 cur->ino = statbuf.st_ino;
7f9552fe 709 cur->fsid = statbuf.st_dev & 0xffff;
d81abd9a 710 cur->name = filename;
6270ab99 711 return(1);
f255214c
KB
712}
713
829312ba 714void
f255214c
KB
715usage()
716{
cf2c7bf9 717 (void)fprintf(stderr,
7cb64bc8 718 "usage: fstat [-fnv] [-p pid] [-u user] [-N system] [-M core] [file ...]\n");
f255214c 719 exit(1);
055eee28 720}