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