Commit | Line | Data |
---|---|---|
055eee28 KB |
1 | /* |
2 | * Copyright (c) 1987 Regents of the University of California. | |
5ebc207c KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
b8c620d6 KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
055eee28 KB |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
20 | "@(#) Copyright (c) 1987 Regents of the University of California.\n\ | |
21 | All rights reserved.\n"; | |
5ebc207c | 22 | #endif /* not lint */ |
055eee28 KB |
23 | |
24 | #ifndef lint | |
435e8dff | 25 | static char sccsid[] = "@(#)fstat.c 5.18 (Berkeley) %G%"; |
5ebc207c | 26 | #endif /* not lint */ |
055eee28 KB |
27 | |
28 | /* | |
29 | * fstat | |
30 | */ | |
f255214c | 31 | #include <machine/pte.h> |
1a585c5c | 32 | |
055eee28 | 33 | #include <sys/param.h> |
055eee28 KB |
34 | #include <sys/dir.h> |
35 | #include <sys/user.h> | |
36 | #include <sys/proc.h> | |
055eee28 KB |
37 | #include <sys/text.h> |
38 | #include <sys/stat.h> | |
055eee28 KB |
39 | #include <sys/inode.h> |
40 | #include <sys/socket.h> | |
41 | #include <sys/socketvar.h> | |
42 | #include <sys/domain.h> | |
43 | #include <sys/protosw.h> | |
055eee28 | 44 | #include <sys/unpcb.h> |
f255214c KB |
45 | #include <sys/vmmac.h> |
46 | #define KERNEL | |
055eee28 | 47 | #include <sys/file.h> |
f255214c | 48 | #undef KERNEL |
1a585c5c KB |
49 | #include <net/route.h> |
50 | #include <netinet/in.h> | |
51 | #include <netinet/in_pcb.h> | |
52 | #include <stdio.h> | |
7168b138 | 53 | #include <ctype.h> |
1a585c5c KB |
54 | #include <nlist.h> |
55 | #include <pwd.h> | |
cf2c7bf9 | 56 | #include <strings.h> |
435e8dff | 57 | #include <paths.h> |
055eee28 | 58 | |
1a585c5c KB |
59 | #ifdef ULTRIX |
60 | /* UFS -> GFS */ | |
055eee28 KB |
61 | # define inode gnode |
62 | # define x_iptr x_gptr | |
63 | # define i_dev g_dev | |
64 | # define i_number g_number | |
65 | # define i_mode g_mode | |
66 | # define i_size g_size | |
f255214c KB |
67 | #endif |
68 | ||
1a585c5c KB |
69 | #define TEXT -2 |
70 | #define WD -1 | |
f255214c | 71 | |
cf2c7bf9 KB |
72 | #define VP if (vflg) (void)printf |
73 | ||
f255214c | 74 | typedef struct devs { |
4575617f KB |
75 | struct devs *next; |
76 | dev_t dev; | |
77 | int inum; | |
78 | char *name; | |
f255214c | 79 | } DEVS; |
4575617f | 80 | DEVS *devs; |
5e369078 | 81 | |
f255214c | 82 | static struct nlist nl[] = { |
055eee28 KB |
83 | { "_proc" }, |
84 | #define X_PROC 0 | |
85 | { "_Usrptmap" }, | |
86 | #define X_USRPTMA 1 | |
055eee28 | 87 | { "_nproc" }, |
f255214c KB |
88 | #define X_NPROC 2 |
89 | { "_usrpt" }, | |
90 | #define X_USRPT 3 | |
055eee28 KB |
91 | { "" }, |
92 | }; | |
93 | ||
4575617f KB |
94 | struct proc *mproc; |
95 | struct pte *Usrptma, *usrpt; | |
f255214c | 96 | |
055eee28 | 97 | union { |
4575617f KB |
98 | struct user user; |
99 | char upages[UPAGES][NBPG]; | |
055eee28 | 100 | } user; |
055eee28 | 101 | |
4575617f KB |
102 | extern int errno; |
103 | static int fflg, vflg; | |
104 | static int kmem, mem, nproc, swap; | |
105 | static char *uname; | |
1a585c5c | 106 | |
4575617f | 107 | off_t lseek(); |
055eee28 KB |
108 | |
109 | main(argc, argv) | |
4575617f KB |
110 | int argc; |
111 | char **argv; | |
055eee28 | 112 | { |
f255214c KB |
113 | extern char *optarg; |
114 | extern int optind; | |
115 | register struct passwd *passwd; | |
116 | register int pflg, pid, uflg, uid; | |
117 | int ch, size; | |
118 | struct passwd *getpwnam(), *getpwuid(); | |
119 | long lgetw(); | |
120 | char *malloc(); | |
121 | ||
122 | pflg = uflg = 0; | |
1a585c5c KB |
123 | while ((ch = getopt(argc, argv, "p:u:v")) != EOF) |
124 | switch((char)ch) { | |
125 | case 'p': | |
7168b138 MT |
126 | if (pflg++) |
127 | usage(); | |
128 | if (!isdigit(*optarg)) { | |
129 | fputs("fstat: -p option requires a process id.\n", stderr); | |
055eee28 | 130 | usage(); |
055eee28 | 131 | } |
f255214c | 132 | pid = atoi(optarg); |
1a585c5c KB |
133 | break; |
134 | case 'u': | |
135 | if (uflg++) | |
055eee28 | 136 | usage(); |
f255214c | 137 | if (!(passwd = getpwnam(optarg))) { |
cf2c7bf9 KB |
138 | (void)fprintf(stderr, "%s: unknown uid\n", |
139 | optarg); | |
055eee28 KB |
140 | exit(1); |
141 | } | |
f255214c KB |
142 | uid = passwd->pw_uid; |
143 | uname = passwd->pw_name; | |
1a585c5c | 144 | break; |
5ebc207c | 145 | case 'v': /* undocumented: print read error messages */ |
1a585c5c KB |
146 | vflg++; |
147 | break; | |
148 | case '?': | |
149 | default: | |
150 | usage(); | |
055eee28 | 151 | } |
055eee28 | 152 | |
5ebc207c | 153 | if (*(argv += optind)) { |
193d3a86 | 154 | for (; *argv; ++argv) { |
5ebc207c KB |
155 | if (getfname(*argv)) |
156 | fflg = 1; | |
157 | } | |
158 | if (!fflg) /* file(s) specified, but none accessable */ | |
159 | exit(1); | |
055eee28 | 160 | } |
d81abd9a | 161 | |
055eee28 | 162 | openfiles(); |
055eee28 | 163 | |
0ea8b445 | 164 | if (nlist(_PATH_UNIX, nl) == -1 || !nl[0].n_type) { |
cf2c7bf9 | 165 | (void)fprintf(stderr, "%s: no namelist\n", _PATH_UNIX); |
055eee28 KB |
166 | exit(1); |
167 | } | |
1a585c5c | 168 | Usrptma = (struct pte *)nl[X_USRPTMA].n_value; |
f255214c | 169 | usrpt = (struct pte *) nl[X_USRPT].n_value; |
f255214c KB |
170 | nproc = (int)lgetw((off_t)nl[X_NPROC].n_value); |
171 | ||
5ebc207c | 172 | (void)lseek(kmem, lgetw((off_t)nl[X_PROC].n_value), L_SET); |
f255214c KB |
173 | size = nproc * sizeof(struct proc); |
174 | if ((mproc = (struct proc *)malloc((u_int)size)) == NULL) { | |
cf2c7bf9 | 175 | (void)fprintf(stderr, "fstat: out of space.\n"); |
055eee28 KB |
176 | exit(1); |
177 | } | |
f255214c | 178 | if (read(kmem, (char *)mproc, size) != size) |
0ea8b445 | 179 | rerr1("proc table", _PATH_KMEM); |
5ebc207c | 180 | |
cf2c7bf9 | 181 | (void)printf("USER\t CMD\t PID FD\tDEVICE\tINODE\t SIZE TYPE%s\n", |
5ebc207c | 182 | fflg ? " NAME" : ""); |
f255214c KB |
183 | for (; nproc--; ++mproc) { |
184 | if (mproc->p_stat == 0) | |
185 | continue; | |
186 | if (pflg && mproc->p_pid != pid) | |
187 | continue; | |
188 | if (uflg) { | |
189 | if (mproc->p_uid != uid) | |
190 | continue; | |
191 | } | |
192 | else | |
193 | uname = (passwd = getpwuid(mproc->p_uid)) ? | |
194 | passwd->pw_name : "unknown"; | |
195 | if (mproc->p_stat != SZOMB && getu() == 0) | |
196 | continue; | |
197 | dotext(); | |
198 | readf(); | |
199 | } | |
200 | exit(0); | |
055eee28 KB |
201 | } |
202 | ||
1a585c5c | 203 | static |
055eee28 KB |
204 | getu() |
205 | { | |
206 | struct pte *pteaddr, apte; | |
207 | struct pte arguutl[UPAGES+CLSIZE]; | |
208 | register int i; | |
f255214c | 209 | int ncl; |
055eee28 | 210 | |
055eee28 KB |
211 | if ((mproc->p_flag & SLOAD) == 0) { |
212 | if (swap < 0) | |
f255214c | 213 | return(0); |
1a585c5c | 214 | (void)lseek(swap, (off_t)dtob(mproc->p_swaddr), L_SET); |
f255214c KB |
215 | if (read(swap, (char *)&user.user, sizeof(struct user)) |
216 | != sizeof(struct user)) { | |
cf2c7bf9 | 217 | VP("fstat: can't read u for pid %d from %s\n", |
435e8dff | 218 | mproc->p_pid, _PATH_DRUM); |
1a585c5c | 219 | return(0); |
055eee28 | 220 | } |
1a585c5c | 221 | return(1); |
055eee28 KB |
222 | } |
223 | pteaddr = &Usrptma[btokmx(mproc->p_p0br) + mproc->p_szpt - 1]; | |
1a585c5c | 224 | (void)lseek(kmem, (off_t)pteaddr, L_SET); |
055eee28 | 225 | if (read(kmem, (char *)&apte, sizeof(apte)) != sizeof(apte)) { |
cf2c7bf9 | 226 | VP("fstat: can't read indir pte to get u for pid %d from %s\n", |
435e8dff | 227 | mproc->p_pid, _PATH_DRUM); |
1a585c5c | 228 | return(0); |
055eee28 | 229 | } |
1a585c5c KB |
230 | (void)lseek(mem, (off_t)ctob(apte.pg_pfnum+1) - (UPAGES+CLSIZE) |
231 | * sizeof(struct pte), L_SET); | |
055eee28 | 232 | if (read(mem, (char *)arguutl, sizeof(arguutl)) != sizeof(arguutl)) { |
cf2c7bf9 KB |
233 | VP("fstat: can't read page table for u of pid %d from %s\n", |
234 | mproc->p_pid, _PATH_KMEM); | |
1a585c5c | 235 | return(0); |
055eee28 | 236 | } |
f255214c | 237 | ncl = (sizeof(struct user) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE); |
055eee28 KB |
238 | while (--ncl >= 0) { |
239 | i = ncl * CLSIZE; | |
1a585c5c | 240 | (void)lseek(mem, (off_t)ctob(arguutl[CLSIZE+i].pg_pfnum), L_SET); |
055eee28 | 241 | if (read(mem, user.upages[i], CLSIZE*NBPG) != CLSIZE*NBPG) { |
cf2c7bf9 KB |
242 | VP("fstat: can't read page %u of u of pid %d from %s\n", |
243 | arguutl[CLSIZE+i].pg_pfnum, mproc->p_pid, | |
244 | _PATH_MEM); | |
055eee28 KB |
245 | return(0); |
246 | } | |
247 | } | |
1a585c5c | 248 | return(1); |
055eee28 KB |
249 | } |
250 | ||
1a585c5c | 251 | static |
055eee28 KB |
252 | dotext() |
253 | { | |
4575617f | 254 | struct text text; |
055eee28 | 255 | |
1a585c5c | 256 | (void)lseek(kmem, (off_t)mproc->p_textp, L_SET); |
055eee28 | 257 | if (read(kmem, (char *) &text, sizeof(text)) != sizeof(text)) { |
0ea8b445 | 258 | rerr1("text table", _PATH_KMEM); |
055eee28 KB |
259 | return; |
260 | } | |
f255214c KB |
261 | if (text.x_flag) |
262 | itrans(DTYPE_INODE, text.x_iptr, TEXT); | |
055eee28 KB |
263 | } |
264 | ||
1a585c5c | 265 | static |
055eee28 | 266 | itrans(ftype, g, fno) |
1a585c5c | 267 | int ftype, fno; |
4575617f | 268 | struct inode *g; /* if ftype is inode */ |
055eee28 | 269 | { |
f255214c KB |
270 | struct inode inode; |
271 | dev_t idev; | |
272 | char *comm, *itype(); | |
d81abd9a | 273 | char *name = (char *)NULL; /* set by devmatch() on a match */ |
1a585c5c KB |
274 | |
275 | if (g || fflg) { | |
276 | (void)lseek(kmem, (off_t)g, L_SET); | |
277 | if (read(kmem, (char *)&inode, sizeof(inode)) != sizeof(inode)) { | |
cf2c7bf9 | 278 | rerr2((int)g, "inode"); |
1a585c5c KB |
279 | return; |
280 | } | |
281 | idev = inode.i_dev; | |
d81abd9a | 282 | if (fflg && !devmatch(idev, inode.i_number, &name)) |
1a585c5c | 283 | return; |
055eee28 | 284 | } |
055eee28 KB |
285 | if (mproc->p_pid == 0) |
286 | comm = "swapper"; | |
287 | else if (mproc->p_pid == 2) | |
288 | comm = "pagedaemon"; | |
289 | else | |
1a585c5c | 290 | comm = user.user.u_comm; |
cf2c7bf9 | 291 | (void)printf("%-8.8s %-10.10s %5d ", uname, comm, mproc->p_pid); |
f255214c KB |
292 | |
293 | switch(fno) { | |
294 | case WD: | |
cf2c7bf9 | 295 | (void)printf(" wd"); break; |
f255214c | 296 | case TEXT: |
cf2c7bf9 | 297 | (void)printf("text"); break; |
f255214c | 298 | default: |
cf2c7bf9 | 299 | (void)printf("%4d", fno); |
f255214c | 300 | } |
055eee28 KB |
301 | |
302 | if (g == 0) { | |
cf2c7bf9 | 303 | (void)printf("* (deallocated)\n"); |
055eee28 KB |
304 | return; |
305 | } | |
306 | ||
1a585c5c KB |
307 | switch(ftype) { |
308 | case DTYPE_INODE: | |
cf2c7bf9 KB |
309 | (void)printf("\t%2d, %2d\t%5lu\t", major(inode.i_dev), |
310 | minor(inode.i_dev), inode.i_number); | |
56af3334 | 311 | switch(inode.i_mode & IFMT) { |
cf2c7bf9 KB |
312 | case IFSOCK: |
313 | (void)printf(" 0\t"); | |
56af3334 | 314 | break; |
cf2c7bf9 KB |
315 | case IFCHR: |
316 | (void)printf("%2d, %2d\t", major(inode.i_rdev), | |
317 | minor(inode.i_rdev)); | |
56af3334 KF |
318 | break; |
319 | default: | |
cf2c7bf9 | 320 | (void)printf("%6ld\t", inode.i_size); |
56af3334 | 321 | } |
cf2c7bf9 | 322 | (void)printf("%3s %s\n", itype(inode.i_mode), name ? name : ""); |
1a585c5c KB |
323 | break; |
324 | case DTYPE_SOCKET: | |
055eee28 | 325 | socktrans((struct socket *)g); |
1a585c5c | 326 | break; |
055eee28 | 327 | #ifdef DTYPE_PORT |
1a585c5c | 328 | case DTYPE_PORT: |
cf2c7bf9 | 329 | (void)printf("* (fifo / named pipe)\n"); |
1a585c5c KB |
330 | break; |
331 | #endif | |
332 | default: | |
cf2c7bf9 | 333 | (void)printf("* (unknown file type)\n"); |
055eee28 KB |
334 | } |
335 | } | |
1a585c5c | 336 | |
f255214c KB |
337 | static char * |
338 | itype(mode) | |
339 | u_short mode; | |
5e369078 | 340 | { |
f255214c KB |
341 | switch(mode & IFMT) { |
342 | case IFCHR: | |
343 | return("chr"); | |
344 | case IFDIR: | |
345 | return("dir"); | |
346 | case IFBLK: | |
347 | return("blk"); | |
348 | case IFREG: | |
349 | return("reg"); | |
350 | case IFLNK: | |
351 | return("lnk"); | |
352 | case IFSOCK: | |
353 | return("soc"); | |
354 | default: | |
355 | return("unk"); | |
356 | } | |
357 | /*NOTREACHED*/ | |
5e369078 | 358 | } |
055eee28 | 359 | |
1a585c5c | 360 | static |
055eee28 | 361 | socktrans(sock) |
1a585c5c | 362 | struct socket *sock; |
055eee28 | 363 | { |
f255214c | 364 | static char *stypename[] = { |
1a585c5c KB |
365 | "unused", /* 0 */ |
366 | "stream", /* 1 */ | |
367 | "dgram", /* 2 */ | |
368 | "raw", /* 3 */ | |
369 | "rdm", /* 4 */ | |
370 | "seqpak" /* 5 */ | |
371 | }; | |
372 | #define STYPEMAX 5 | |
373 | struct socket so; | |
374 | struct protosw proto; | |
375 | struct domain dom; | |
376 | struct inpcb inpcb; | |
377 | struct unpcb unpcb; | |
f255214c KB |
378 | int len; |
379 | char dname[32], *strcpy(); | |
055eee28 KB |
380 | |
381 | /* fill in socket */ | |
1a585c5c KB |
382 | (void)lseek(kmem, (off_t)sock, L_SET); |
383 | if (read(kmem, (char *)&so, sizeof(struct socket)) | |
384 | != sizeof(struct socket)) { | |
cf2c7bf9 | 385 | rerr2((int)sock, "socket"); |
055eee28 KB |
386 | return; |
387 | } | |
388 | ||
389 | /* fill in protosw entry */ | |
1a585c5c KB |
390 | (void)lseek(kmem, (off_t)so.so_proto, L_SET); |
391 | if (read(kmem, (char *)&proto, sizeof(struct protosw)) | |
392 | != sizeof(struct protosw)) { | |
cf2c7bf9 | 393 | rerr2((int)so.so_proto, "protosw"); |
055eee28 KB |
394 | return; |
395 | } | |
396 | ||
397 | /* fill in domain */ | |
1a585c5c KB |
398 | (void)lseek(kmem, (off_t)proto.pr_domain, L_SET); |
399 | if (read(kmem, (char *)&dom, sizeof(struct domain)) | |
400 | != sizeof(struct domain)) { | |
cf2c7bf9 | 401 | rerr2((int)proto.pr_domain, "domain"); |
055eee28 KB |
402 | return; |
403 | } | |
404 | ||
f255214c KB |
405 | /* |
406 | * grab domain name | |
407 | * kludge "internet" --> "inet" for brevity | |
408 | */ | |
1a585c5c KB |
409 | if (dom.dom_family == AF_INET) |
410 | (void)strcpy(dname, "inet"); | |
f255214c KB |
411 | else { |
412 | (void)lseek(kmem, (off_t)dom.dom_name, L_SET); | |
413 | if ((len = read(kmem, dname, sizeof(dname) - 1)) < 0) { | |
cf2c7bf9 | 414 | rerr2((int)dom.dom_name, "char"); |
f255214c KB |
415 | dname[0] = '\0'; |
416 | } | |
417 | else | |
418 | dname[len] = '\0'; | |
1a585c5c | 419 | } |
055eee28 | 420 | |
f255214c | 421 | if ((u_short)so.so_type > STYPEMAX) |
cf2c7bf9 | 422 | (void)printf("* (%s unk%d %x", dname, so.so_type, so.so_state); |
f255214c | 423 | else |
cf2c7bf9 | 424 | (void)printf("* (%s %s %x", dname, stypename[so.so_type], |
f255214c | 425 | so.so_state); |
055eee28 KB |
426 | |
427 | /* | |
5ebc207c | 428 | * protocol specific formatting |
055eee28 | 429 | * |
f255214c KB |
430 | * Try to find interesting things to print. For tcp, the interesting |
431 | * thing is the address of the tcpcb, for udp and others, just the | |
432 | * inpcb (socket pcb). For unix domain, its the address of the socket | |
433 | * pcb and the address of the connected pcb (if connected). Otherwise | |
434 | * just print the protocol number and address of the socket itself. | |
435 | * The idea is not to duplicate netstat, but to make available enough | |
436 | * information for further analysis. | |
055eee28 | 437 | */ |
f255214c KB |
438 | switch(dom.dom_family) { |
439 | case AF_INET: | |
440 | getinetproto(proto.pr_protocol); | |
055eee28 KB |
441 | if (proto.pr_protocol == IPPROTO_TCP ) { |
442 | if (so.so_pcb) { | |
1a585c5c KB |
443 | (void)lseek(kmem, (off_t)so.so_pcb, L_SET); |
444 | if (read(kmem, (char *)&inpcb, sizeof(struct inpcb)) | |
055eee28 | 445 | != sizeof(struct inpcb)){ |
cf2c7bf9 | 446 | rerr2((int)so.so_pcb, "inpcb"); |
055eee28 KB |
447 | return; |
448 | } | |
cf2c7bf9 | 449 | (void)printf(" %x", (int)inpcb.inp_ppcb); |
055eee28 | 450 | } |
055eee28 | 451 | } |
1a585c5c | 452 | else if (so.so_pcb) |
cf2c7bf9 | 453 | (void)printf(" %x", (int)so.so_pcb); |
f255214c KB |
454 | break; |
455 | case AF_UNIX: | |
055eee28 KB |
456 | /* print address of pcb and connected pcb */ |
457 | if (so.so_pcb) { | |
cf2c7bf9 | 458 | (void)printf(" %x", (int)so.so_pcb); |
1a585c5c KB |
459 | (void)lseek(kmem, (off_t)so.so_pcb, L_SET); |
460 | if (read(kmem, (char *)&unpcb, sizeof(struct unpcb)) | |
055eee28 | 461 | != sizeof(struct unpcb)){ |
cf2c7bf9 | 462 | rerr2((int)so.so_pcb, "unpcb"); |
055eee28 KB |
463 | return; |
464 | } | |
5e369078 | 465 | if (unpcb.unp_conn) { |
f255214c | 466 | char shoconn[4], *cp; |
1a585c5c | 467 | |
f255214c | 468 | cp = shoconn; |
5e369078 | 469 | if (!(so.so_state & SS_CANTRCVMORE)) |
f255214c KB |
470 | *cp++ = '<'; |
471 | *cp++ = '-'; | |
5e369078 | 472 | if (!(so.so_state & SS_CANTSENDMORE)) |
f255214c KB |
473 | *cp++ = '>'; |
474 | *cp = '\0'; | |
cf2c7bf9 KB |
475 | (void)printf(" %s %x", shoconn, |
476 | (int)unpcb.unp_conn); | |
5e369078 | 477 | } |
055eee28 | 478 | } |
f255214c KB |
479 | break; |
480 | default: | |
481 | /* print protocol number and socket address */ | |
cf2c7bf9 | 482 | (void)printf(" %d %x", proto.pr_protocol, (int)sock); |
f255214c | 483 | } |
cf2c7bf9 | 484 | (void)printf(")\n"); |
055eee28 KB |
485 | } |
486 | ||
f255214c KB |
487 | /* |
488 | * getinetproto -- | |
489 | * print name of protocol number | |
490 | */ | |
491 | static | |
055eee28 | 492 | getinetproto(number) |
1a585c5c | 493 | int number; |
055eee28 | 494 | { |
1a585c5c | 495 | char *cp; |
9bd38ba8 | 496 | |
055eee28 | 497 | switch(number) { |
f255214c KB |
498 | case IPPROTO_IP: |
499 | cp = "ip"; break; | |
500 | case IPPROTO_ICMP: | |
501 | cp ="icmp"; break; | |
502 | case IPPROTO_GGP: | |
503 | cp ="ggp"; break; | |
504 | case IPPROTO_TCP: | |
505 | cp ="tcp"; break; | |
506 | case IPPROTO_EGP: | |
507 | cp ="egp"; break; | |
508 | case IPPROTO_PUP: | |
509 | cp ="pup"; break; | |
510 | case IPPROTO_UDP: | |
511 | cp ="udp"; break; | |
512 | case IPPROTO_IDP: | |
513 | cp ="idp"; break; | |
514 | case IPPROTO_RAW: | |
515 | cp ="raw"; break; | |
9bd38ba8 | 516 | default: |
cf2c7bf9 | 517 | (void)printf(" %d", number); |
f255214c | 518 | return; |
055eee28 | 519 | } |
cf2c7bf9 | 520 | (void)printf(" %s", cp); |
055eee28 KB |
521 | } |
522 | ||
f255214c KB |
523 | static |
524 | readf() | |
055eee28 | 525 | { |
1a585c5c | 526 | struct file lfile; |
f255214c | 527 | int i; |
055eee28 | 528 | |
1a585c5c | 529 | itrans(DTYPE_INODE, user.user.u_cdir, WD); |
055eee28 | 530 | for (i = 0; i < NOFILE; i++) { |
1a585c5c | 531 | if (user.user.u_ofile[i] == 0) |
055eee28 | 532 | continue; |
1a585c5c KB |
533 | (void)lseek(kmem, (off_t)user.user.u_ofile[i], L_SET); |
534 | if (read(kmem, (char *)&lfile, sizeof(lfile)) | |
535 | != sizeof(lfile)) { | |
0ea8b445 | 536 | rerr1("file", _PATH_KMEM); |
055eee28 KB |
537 | continue; |
538 | } | |
1a585c5c | 539 | itrans(lfile.f_type, (struct inode *)lfile.f_data, i); |
055eee28 KB |
540 | } |
541 | } | |
542 | ||
1a585c5c | 543 | static |
d81abd9a | 544 | devmatch(idev, inum, name) |
f255214c KB |
545 | dev_t idev; |
546 | ino_t inum; | |
d81abd9a | 547 | char **name; |
055eee28 | 548 | { |
f255214c | 549 | register DEVS *d; |
1a585c5c | 550 | |
f255214c | 551 | for (d = devs; d; d = d->next) |
d81abd9a MT |
552 | if (d->dev == idev && (d->inum == 0 || d->inum == inum)) { |
553 | *name = d->name; | |
f255214c | 554 | return(1); |
d81abd9a | 555 | } |
f255214c | 556 | return(0); |
055eee28 KB |
557 | } |
558 | ||
1a585c5c | 559 | static |
055eee28 | 560 | getfname(filename) |
1a585c5c | 561 | char *filename; |
055eee28 | 562 | { |
f255214c KB |
563 | struct stat statbuf; |
564 | DEVS *cur; | |
565 | char *malloc(); | |
055eee28 | 566 | |
1a585c5c | 567 | if (stat(filename, &statbuf)) { |
cf2c7bf9 KB |
568 | (void)fprintf(stderr, "fstat: %s: %s\n", strerror(errno), |
569 | filename); | |
6270ab99 | 570 | return(0); |
1a585c5c | 571 | } |
f255214c | 572 | if ((cur = (DEVS *)malloc(sizeof(DEVS))) == NULL) { |
cf2c7bf9 | 573 | (void)fprintf(stderr, "fstat: out of space.\n"); |
f255214c KB |
574 | exit(1); |
575 | } | |
576 | cur->next = devs; | |
577 | devs = cur; | |
055eee28 | 578 | |
f255214c | 579 | /* if file is block special, look for open files on it */ |
055eee28 | 580 | if ((statbuf.st_mode & S_IFMT) != S_IFBLK) { |
f255214c KB |
581 | cur->inum = statbuf.st_ino; |
582 | cur->dev = statbuf.st_dev; | |
1a585c5c KB |
583 | } |
584 | else { | |
f255214c KB |
585 | cur->inum = 0; |
586 | cur->dev = statbuf.st_rdev; | |
055eee28 | 587 | } |
d81abd9a | 588 | cur->name = filename; |
6270ab99 | 589 | return(1); |
f255214c KB |
590 | } |
591 | ||
592 | static | |
593 | openfiles() | |
594 | { | |
0ea8b445 KB |
595 | if ((kmem = open(_PATH_KMEM, O_RDONLY, 0)) < 0) { |
596 | (void)fprintf(stderr, "fstat: %s: %s\n", | |
597 | strerror(errno), _PATH_KMEM); | |
f255214c KB |
598 | exit(1); |
599 | } | |
0ea8b445 KB |
600 | if ((mem = open(_PATH_MEM, O_RDONLY, 0)) < 0) { |
601 | (void)fprintf(stderr, "fstat: %s: %s\n", | |
602 | strerror(errno), _PATH_MEM); | |
f255214c KB |
603 | exit(1); |
604 | } | |
435e8dff | 605 | if ((swap = open(_PATH_DRUM, O_RDONLY, 0)) < 0) { |
0ea8b445 | 606 | (void)fprintf(stderr, "fstat: %s: %s\n", |
435e8dff | 607 | strerror(errno), _PATH_DRUM); |
f255214c KB |
608 | exit(1); |
609 | } | |
610 | } | |
611 | ||
612 | static | |
5ebc207c | 613 | rerr1(what, fromwhat) |
f255214c KB |
614 | char *what, *fromwhat; |
615 | { | |
cf2c7bf9 | 616 | VP("error reading %s from %s", what, fromwhat); |
5ebc207c KB |
617 | } |
618 | ||
619 | static | |
cf2c7bf9 KB |
620 | rerr2(address, what) |
621 | int address; | |
5ebc207c KB |
622 | char *what; |
623 | { | |
cf2c7bf9 KB |
624 | VP("error %d reading %s at %x from %s\n", errno, what, address, |
625 | _PATH_KMEM); | |
f255214c KB |
626 | } |
627 | ||
628 | static long | |
629 | lgetw(loc) | |
630 | off_t loc; | |
631 | { | |
632 | long word; | |
633 | ||
634 | (void)lseek(kmem, (off_t)loc, L_SET); | |
5ebc207c | 635 | if (read(kmem, (char *)&word, sizeof(word)) != sizeof(word)) |
cf2c7bf9 | 636 | rerr2((int)loc, "word"); |
f255214c KB |
637 | return(word); |
638 | } | |
639 | ||
640 | static | |
641 | usage() | |
642 | { | |
cf2c7bf9 KB |
643 | (void)fprintf(stderr, |
644 | "usage: fstat [-u user] [-p pid] [filename ...]\n"); | |
f255214c | 645 | exit(1); |
055eee28 | 646 | } |