kinfo_proc.h gone, stuff moved to <sys/sysctl.h>
[unix-history] / usr / src / usr.bin / fstat / fstat.c
CommitLineData
7f9552fe
MT
1/*-
2 * Copyright (c) 1988 The Regents of the University of California.
5ebc207c
KB
3 * All rights reserved.
4 *
7f9552fe 5 * %sccs.include.redist.c%
055eee28
KB
6 */
7
8#ifndef lint
9char copyright[] =
7f9552fe 10"@(#) Copyright (c) 1988 The Regents of the University of California.\n\
055eee28 11 All rights reserved.\n";
5ebc207c 12#endif /* not lint */
055eee28
KB
13
14#ifndef lint
fa39b65c 15static char sccsid[] = "@(#)fstat.c 5.44 (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
KB
220 printf("%s",
221"USER CMD PID FD DEV INUM MODE SZ|DV");
e00a6228 222 else
40a7fa18
KB
223 printf("%s",
224"USER CMD PID FD MOUNT INUM MODE SZ|DV");
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
MT
290 if (filed.fd_rdir)
291 vtrans(filed.fd_rdir, RDIR);
e00a6228
MT
292 /*
293 * current working directory vnode
294 */
49acea14 295 vtrans(filed.fd_cdir, CDIR);
e00a6228
MT
296 /*
297 * ktrace vnode, if one
298 */
299 if (p->p_tracep)
300 vtrans(p->p_tracep, TRACE);
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)
325 vtrans((struct vnode *)file.f_data, i);
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
e00a6228
MT
339vtrans(vp, i)
340 struct vnode *vp;
829312ba 341 int i;
055eee28 342{
829312ba 343 extern char *devname();
e00a6228
MT
344 struct vnode vn;
345 struct filestat fst;
7f9552fe 346 char 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 }
e00a6228
MT
425 if (filename && !fsflg)
426 printf(" %s", filename);
427
428 putchar('\n');
429}
055eee28 430
2524719d 431int
e00a6228
MT
432ufs_filestat(vp, fsp)
433 struct vnode *vp;
434 struct filestat *fsp;
435{
2524719d
MT
436 struct inode inode;
437
438 if (!KVM_READ(VTOI(vp), &inode, sizeof (inode))) {
439 dprintf(stderr, "can't read inode at %x for pid %d\n",
440 VTOI(vp), Pid);
441 return 0;
442 }
443 fsp->fsid = inode.i_dev & 0xffff;
444 fsp->fileid = (long)inode.i_number;
445 fsp->mode = (mode_t)inode.i_mode;
446 fsp->size = (u_long)inode.i_size;
447 fsp->rdev = inode.i_rdev;
3dae3806 448
2524719d 449 return 1;
e00a6228 450}
3dae3806 451
2524719d 452int
e00a6228
MT
453nfs_filestat(vp, fsp)
454 struct vnode *vp;
455 struct filestat *fsp;
456{
2524719d 457 struct nfsnode nfsnode;
7f9552fe 458 register mode_t mode;
3dae3806 459
2524719d
MT
460 if (!KVM_READ(VTONFS(vp), &nfsnode, sizeof (nfsnode))) {
461 dprintf(stderr, "can't read nfsnode at %x for pid %d\n",
462 VTONFS(vp), Pid);
463 return 0;
464 }
465 fsp->fsid = nfsnode.n_vattr.va_fsid;
466 fsp->fileid = nfsnode.n_vattr.va_fileid;
467 fsp->size = nfsnode.n_size;
468 fsp->rdev = nfsnode.n_vattr.va_rdev;
469 mode = (mode_t)nfsnode.n_vattr.va_mode;
7f9552fe
MT
470 switch (vp->v_type) {
471 case VREG:
472 mode |= S_IFREG;
473 break;
474 case VDIR:
475 mode |= S_IFDIR;
476 break;
477 case VBLK:
478 mode |= S_IFBLK;
479 break;
480 case VCHR:
481 mode |= S_IFCHR;
482 break;
483 case VLNK:
484 mode |= S_IFLNK;
485 break;
486 case VSOCK:
487 mode |= S_IFSOCK;
488 break;
489 case VFIFO:
490 mode |= S_IFIFO;
491 break;
492 };
493 fsp->mode = mode;
2524719d
MT
494
495 return 1;
e00a6228 496}
3dae3806 497
3dae3806 498
e00a6228
MT
499char *
500getmnton(m)
501 struct mount *m;
502{
503 static struct mount mount;
504 static struct mtab {
505 struct mtab *next;
506 struct mount *m;
507 char mntonname[MNAMELEN];
508 } *mhead = NULL;
509 register struct mtab *mt;
510
511 for (mt = mhead; mt != NULL; mt = mt->next)
512 if (m == mt->m)
513 return (mt->mntonname);
829312ba 514 if (!KVM_READ(m, &mount, sizeof(struct mount))) {
e00a6228
MT
515 fprintf(stderr, "can't read mount table at %x\n", m);
516 return (NULL);
055eee28 517 }
829312ba
KB
518 if ((mt = malloc(sizeof (struct mtab))) == NULL) {
519 fprintf(stderr, "fstat: %s\n", strerror(errno));
e00a6228
MT
520 exit(1);
521 }
522 mt->m = m;
7f9552fe 523 bcopy(&mount.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
e00a6228
MT
524 mt->next = mhead;
525 mhead = mt;
526 return (mt->mntonname);
055eee28 527}
1a585c5c 528
829312ba 529void
e00a6228 530socktrans(sock, i)
1a585c5c 531 struct socket *sock;
829312ba 532 int i;
055eee28 533{
f255214c 534 static char *stypename[] = {
1a585c5c
KB
535 "unused", /* 0 */
536 "stream", /* 1 */
537 "dgram", /* 2 */
538 "raw", /* 3 */
539 "rdm", /* 4 */
540 "seqpak" /* 5 */
541 };
542#define STYPEMAX 5
543 struct socket so;
544 struct protosw proto;
545 struct domain dom;
546 struct inpcb inpcb;
547 struct unpcb unpcb;
f255214c
KB
548 int len;
549 char dname[32], *strcpy();
055eee28 550
e00a6228
MT
551 PREFIX(i);
552
055eee28 553 /* fill in socket */
49acea14 554 if (!KVM_READ(sock, &so, sizeof(struct socket))) {
e00a6228 555 dprintf(stderr, "can't read sock at %x\n", sock);
7f9552fe 556 goto bad;
055eee28
KB
557 }
558
559 /* fill in protosw entry */
49acea14 560 if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
e00a6228 561 dprintf(stderr, "can't read protosw at %x", so.so_proto);
7f9552fe 562 goto bad;
055eee28
KB
563 }
564
565 /* fill in domain */
49acea14 566 if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
e00a6228 567 dprintf(stderr, "can't read domain at %x\n", proto.pr_domain);
7f9552fe 568 goto bad;
055eee28
KB
569 }
570
f3fad419
KB
571 if ((len = kvm_read(kd, (u_long)dom.dom_name, dname,
572 sizeof(dname) - 1)) < 0) {
49acea14
MT
573 dprintf(stderr, "can't read domain name at %x\n",
574 dom.dom_name);
575 dname[0] = '\0';
1a585c5c 576 }
49acea14
MT
577 else
578 dname[len] = '\0';
055eee28 579
f255214c 580 if ((u_short)so.so_type > STYPEMAX)
7f9552fe 581 printf("* %s ?%d", dname, so.so_type);
f255214c 582 else
7f9552fe 583 printf("* %s %s", dname, stypename[so.so_type]);
055eee28
KB
584
585 /*
5ebc207c 586 * protocol specific formatting
055eee28 587 *
f255214c
KB
588 * Try to find interesting things to print. For tcp, the interesting
589 * thing is the address of the tcpcb, for udp and others, just the
590 * inpcb (socket pcb). For unix domain, its the address of the socket
591 * pcb and the address of the connected pcb (if connected). Otherwise
592 * just print the protocol number and address of the socket itself.
593 * The idea is not to duplicate netstat, but to make available enough
594 * information for further analysis.
055eee28 595 */
f255214c
KB
596 switch(dom.dom_family) {
597 case AF_INET:
598 getinetproto(proto.pr_protocol);
055eee28
KB
599 if (proto.pr_protocol == IPPROTO_TCP ) {
600 if (so.so_pcb) {
f3fad419
KB
601 if (kvm_read(kd, (u_long)so.so_pcb,
602 (char *)&inpcb, sizeof(struct inpcb))
829312ba 603 != sizeof(struct inpcb)) {
e00a6228 604 dprintf(stderr,
829312ba
KB
605 "can't read inpcb at %x\n",
606 so.so_pcb);
7f9552fe 607 goto bad;
055eee28 608 }
7f9552fe 609 printf(" %x", (int)inpcb.inp_ppcb);
055eee28 610 }
055eee28 611 }
1a585c5c 612 else if (so.so_pcb)
7f9552fe 613 printf(" %x", (int)so.so_pcb);
f255214c
KB
614 break;
615 case AF_UNIX:
055eee28
KB
616 /* print address of pcb and connected pcb */
617 if (so.so_pcb) {
7f9552fe 618 printf(" %x", (int)so.so_pcb);
f3fad419 619 if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb,
829312ba 620 sizeof(struct unpcb)) != sizeof(struct unpcb)){
e00a6228 621 dprintf(stderr, "can't read unpcb at %x\n",
829312ba 622 so.so_pcb);
7f9552fe 623 goto bad;
055eee28 624 }
5e369078 625 if (unpcb.unp_conn) {
f255214c 626 char shoconn[4], *cp;
1a585c5c 627
f255214c 628 cp = shoconn;
5e369078 629 if (!(so.so_state & SS_CANTRCVMORE))
f255214c
KB
630 *cp++ = '<';
631 *cp++ = '-';
5e369078 632 if (!(so.so_state & SS_CANTSENDMORE))
f255214c
KB
633 *cp++ = '>';
634 *cp = '\0';
7f9552fe 635 printf(" %s %x", shoconn,
cf2c7bf9 636 (int)unpcb.unp_conn);
5e369078 637 }
055eee28 638 }
f255214c
KB
639 break;
640 default:
641 /* print protocol number and socket address */
7f9552fe 642 printf(" %d %x", proto.pr_protocol, (int)sock);
f255214c 643 }
7f9552fe
MT
644 printf("\n");
645 return;
646bad:
647 printf("* error\n");
055eee28
KB
648}
649
f255214c
KB
650/*
651 * getinetproto --
652 * print name of protocol number
653 */
829312ba 654void
055eee28 655getinetproto(number)
1a585c5c 656 int number;
055eee28 657{
1a585c5c 658 char *cp;
9bd38ba8 659
055eee28 660 switch(number) {
f255214c
KB
661 case IPPROTO_IP:
662 cp = "ip"; break;
663 case IPPROTO_ICMP:
664 cp ="icmp"; break;
665 case IPPROTO_GGP:
666 cp ="ggp"; break;
667 case IPPROTO_TCP:
668 cp ="tcp"; break;
669 case IPPROTO_EGP:
670 cp ="egp"; break;
671 case IPPROTO_PUP:
672 cp ="pup"; break;
673 case IPPROTO_UDP:
674 cp ="udp"; break;
675 case IPPROTO_IDP:
676 cp ="idp"; break;
677 case IPPROTO_RAW:
678 cp ="raw"; break;
9bd38ba8 679 default:
7f9552fe 680 printf(" %d", number);
f255214c 681 return;
055eee28 682 }
7f9552fe 683 printf(" %s", cp);
055eee28
KB
684}
685
055eee28 686getfname(filename)
1a585c5c 687 char *filename;
055eee28 688{
f255214c
KB
689 struct stat statbuf;
690 DEVS *cur;
055eee28 691
1a585c5c 692 if (stat(filename, &statbuf)) {
191bf8ce 693 fprintf(stderr, "fstat: %s: %s\n", filename, strerror(errno));
6270ab99 694 return(0);
1a585c5c 695 }
829312ba
KB
696 if ((cur = malloc(sizeof(DEVS))) == NULL) {
697 fprintf(stderr, "fstat: %s\n", strerror(errno));
f255214c
KB
698 exit(1);
699 }
700 cur->next = devs;
701 devs = cur;
055eee28 702
e00a6228 703 cur->ino = statbuf.st_ino;
7f9552fe 704 cur->fsid = statbuf.st_dev & 0xffff;
d81abd9a 705 cur->name = filename;
6270ab99 706 return(1);
f255214c
KB
707}
708
829312ba 709void
f255214c
KB
710usage()
711{
cf2c7bf9 712 (void)fprintf(stderr,
7cb64bc8 713 "usage: fstat [-fnv] [-p pid] [-u user] [-N system] [-M core] [file ...]\n");
f255214c 714 exit(1);
055eee28 715}