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