Commit | Line | Data |
---|---|---|
5ff67f98 DF |
1 | /* |
2 | * Copyright (c) 1980 Regents of the University of California. | |
3 | * All rights reserved. The Berkeley software License Agreement | |
4 | * specifies the terms and conditions for redistribution. | |
5 | */ | |
6 | ||
ae1f9014 | 7 | #ifndef lint |
5ff67f98 DF |
8 | char copyright[] = |
9 | "@(#) Copyright (c) 1980 Regents of the University of California.\n\ | |
10 | All rights reserved.\n"; | |
0dc27808 | 11 | #endif /* not lint */ |
5ff67f98 DF |
12 | |
13 | #ifndef lint | |
1bbe0c66 | 14 | static char sccsid[] = "@(#)pstat.c 5.35 (Berkeley) %G%"; |
0dc27808 | 15 | #endif /* not lint */ |
5ff67f98 | 16 | |
ceb84881 BJ |
17 | /* |
18 | * Print system stuff | |
19 | */ | |
ceb84881 | 20 | #include <sys/param.h> |
ceb84881 BJ |
21 | #include <sys/user.h> |
22 | #include <sys/proc.h> | |
9eecf21c KM |
23 | #include <sys/time.h> |
24 | #include <sys/vnode.h> | |
ceb84881 | 25 | #include <sys/map.h> |
844d8384 | 26 | #define KERNEL |
6102031f MT |
27 | #define NFS |
28 | #include <sys/file.h> | |
29 | #include <sys/mount.h> | |
551215f4 | 30 | #include <ufs/quota.h> |
6102031f MT |
31 | #include <ufs/inode.h> |
32 | #include <sys/stat.h> | |
33 | #include <nfs/nfsv2.h> | |
34 | #include <nfs/nfs.h> | |
35 | #include <nfs/nfsnode.h> | |
88a58f27 | 36 | #include <sys/ioctl.h> |
ceb84881 | 37 | #include <sys/tty.h> |
844d8384 | 38 | #undef KERNEL |
ceb84881 | 39 | #include <sys/conf.h> |
d7985207 MK |
40 | |
41 | #ifdef SPPWAIT | |
42 | #define NEWVM | |
43 | #endif | |
44 | ||
45 | #ifndef NEWVM | |
ceb84881 | 46 | #include <sys/vm.h> |
0bc29a7d | 47 | #include <machine/pte.h> |
7e7bb114 | 48 | #include <sys/text.h> |
d7985207 | 49 | #endif |
1d47dec3 | 50 | #include <sys/kinfo.h> |
9eecf21c KM |
51 | |
52 | #include <nlist.h> | |
1d47dec3 | 53 | #include <kvm.h> |
9ed2dfb9 | 54 | #include <stdio.h> |
12f0ac74 | 55 | #include "pathnames.h" |
ceb84881 | 56 | |
f20270fc MK |
57 | #define mask(x) (x&0377) |
58 | #define clear(x) ((int)x &~ KERNBASE) | |
59 | ||
6102031f MT |
60 | char *fnlist = NULL; |
61 | char *fcore = NULL; | |
ceb84881 BJ |
62 | |
63 | struct nlist nl[] = { | |
d7985207 | 64 | #define SWAPMAP 0 |
ceb84881 | 65 | { "_swapmap" }, |
d7985207 | 66 | #define SNSWAPMAP 1 |
69d3d166 | 67 | { "_nswapmap" }, |
d7985207 | 68 | #define SDMMIN 2 |
e79dc02e | 69 | { "_dmmin" }, |
d7985207 | 70 | #define SDMMAX 3 |
e79dc02e | 71 | { "_dmmax" }, |
d7985207 | 72 | #define SNSWDEV 4 |
e79dc02e | 73 | { "_nswdev" }, |
d7985207 | 74 | #define SSWDEVT 5 |
b94a50ef | 75 | { "_swdevt" }, |
d7985207 | 76 | #ifdef NEWVM |
1bbe0c66 | 77 | #define NLMANDATORY SSWDEVT /* names up to here are mandatory */ |
d7985207 MK |
78 | #else |
79 | #define STEXT 8 | |
80 | { "_text" }, | |
81 | #define SNTEXT 9 | |
82 | { "_ntext" }, | |
83 | #define SPROC 10 | |
84 | { "_proc" }, | |
85 | #define SNPROC 11 | |
86 | { "_nproc" }, | |
87 | #define NLMANDATORY SNPROC /* names up to here are mandatory */ | |
88 | #endif | |
89 | ||
90 | #define SCONS NLMANDATORY + 1 | |
1d47dec3 | 91 | { "_cons" }, |
d7985207 | 92 | #define SPTY NLMANDATORY + 2 |
1d47dec3 | 93 | { "_pt_tty" }, |
d7985207 | 94 | #define SNPTY NLMANDATORY + 3 |
4242be26 SL |
95 | { "_npty" }, |
96 | #ifdef vax | |
97 | #define SDZ (SNPTY+1) | |
98 | { "_dz_tty" }, | |
99 | #define SNDZ (SNPTY+2) | |
100 | { "_dz_cnt" }, | |
101 | #define SDMF (SNPTY+3) | |
890571d1 | 102 | { "_dmf_tty" }, |
4242be26 | 103 | #define SNDMF (SNPTY+4) |
890571d1 | 104 | { "_ndmf" }, |
4242be26 SL |
105 | #define SDH (SNPTY+5) |
106 | { "_dh11" }, | |
107 | #define SNDH (SNPTY+6) | |
108 | { "_ndh11" }, | |
109 | #define SDHU (SNPTY+7) | |
5cf6fff2 | 110 | { "_dhu_tty" }, |
4242be26 | 111 | #define SNDHU (SNPTY+8) |
5cf6fff2 | 112 | { "_ndhu" }, |
4242be26 | 113 | #define SDMZ (SNPTY+9) |
35d0530f | 114 | { "_dmz_tty" }, |
4242be26 | 115 | #define SNDMZ (SNPTY+10) |
35d0530f | 116 | { "_ndmz" }, |
bac975ad MT |
117 | #define SQD (SNPTY+11) |
118 | { "_qd_tty" }, | |
119 | #define SNQD (SNPTY+12) | |
120 | { "_nNQD" }, | |
4242be26 | 121 | #endif |
b98ff689 | 122 | |
4242be26 SL |
123 | #ifdef tahoe |
124 | #define SVX (SNPTY+1) | |
125 | { "_vx_tty" }, | |
126 | #define SNVX (SNPTY+2) | |
127 | { "_nvx" }, | |
844d8384 | 128 | #define SMP (SNPTY+3) |
c6864ab6 | 129 | { "_mp_tty" }, |
844d8384 | 130 | #define SNMP (SNPTY+4) |
c6864ab6 | 131 | { "_nmp" }, |
4242be26 | 132 | #endif |
b98ff689 MK |
133 | |
134 | #ifdef hp300 | |
135 | #define SDCA (SNPTY+1) | |
136 | { "_dca_tty" }, | |
137 | #define SNDCA (SNPTY+2) | |
138 | { "_ndca" }, | |
139 | #define SDCM (SNPTY+3) | |
140 | { "_dcm_tty" }, | |
141 | #define SNDCM (SNPTY+4) | |
1d47dec3 | 142 | { "_ndcm" }, |
b98ff689 MK |
143 | #define SDCL (SNPTY+5) |
144 | { "_dcl_tty" }, | |
145 | #define SNDCL (SNPTY+6) | |
146 | { "_ndcl" }, | |
147 | #define SITE (SNPTY+7) | |
148 | { "_ite_tty" }, | |
149 | #define SNITE (SNPTY+8) | |
150 | { "_nite" }, | |
151 | #endif | |
b94a50ef | 152 | { "" } |
ceb84881 BJ |
153 | }; |
154 | ||
6102031f | 155 | int vnof; |
ceb84881 BJ |
156 | int txtf; |
157 | int prcf; | |
158 | int ttyf; | |
159 | int usrf; | |
8a5d2599 | 160 | int upid; |
ceb84881 BJ |
161 | int filf; |
162 | int swpf; | |
163 | int totflg; | |
164 | char partab[1]; | |
165 | struct cdevsw cdevsw[1]; | |
166 | struct bdevsw bdevsw[1]; | |
167 | int allflg; | |
6102031f | 168 | int nflg; |
dc2a22f1 | 169 | u_long getword(); |
9ed2dfb9 | 170 | off_t mkphys(); |
ceb84881 | 171 | |
6102031f MT |
172 | char *Program; |
173 | ||
1d47dec3 MT |
174 | #define V(x) (void *)(x) |
175 | ||
ceb84881 | 176 | main(argc, argv) |
0dc27808 KB |
177 | int argc; |
178 | char **argv; | |
ceb84881 | 179 | { |
0dc27808 KB |
180 | extern char *optarg; |
181 | extern int optind; | |
1d47dec3 | 182 | int ch, ret; |
ceb84881 | 183 | |
6102031f | 184 | Program = argv[0]; |
2e924960 | 185 | while ((ch = getopt(argc, argv, "TafvikptU:sxnu")) != EOF) |
b98ff689 | 186 | switch (ch) { |
ceb84881 BJ |
187 | case 'T': |
188 | totflg++; | |
189 | break; | |
ceb84881 BJ |
190 | case 'a': |
191 | allflg++; | |
0dc27808 KB |
192 | /*FALLTHROUGH*/ |
193 | case 'p': | |
194 | prcf++; | |
195 | break; | |
196 | case 'f': | |
197 | filf++; | |
ceb84881 | 198 | break; |
6102031f | 199 | case 'v': |
ceb84881 | 200 | case 'i': |
6102031f | 201 | vnof++; |
ceb84881 | 202 | break; |
ceb84881 BJ |
203 | case 't': |
204 | ttyf++; | |
205 | break; | |
2e924960 | 206 | case 'U': |
ceb84881 | 207 | usrf++; |
8a5d2599 | 208 | sscanf(optarg, "%d", &upid); |
ceb84881 BJ |
209 | break; |
210 | case 's': | |
211 | swpf++; | |
212 | break; | |
0dc27808 KB |
213 | case 'x': |
214 | txtf++; | |
215 | break; | |
6102031f MT |
216 | case 'n': |
217 | nflg++; | |
218 | break; | |
2e924960 MT |
219 | case 'u': |
220 | fprintf(stderr, "pstat: use [ -U pid ] for -u\n"); | |
221 | exit(1); | |
0dc27808 | 222 | case '?': |
ae1f9014 | 223 | default: |
2e924960 | 224 | fprintf(stderr, "usage: pstat -[Tafiptsx] [-U [pid]] [system] [core]\n"); |
ae1f9014 | 225 | exit(1); |
ceb84881 | 226 | } |
0dc27808 KB |
227 | argc -= optind; |
228 | argv += optind; | |
229 | ||
6102031f MT |
230 | if (argc > 1) |
231 | fcore = argv[1]; | |
232 | if (argc > 0) | |
233 | fnlist = argv[0]; | |
234 | if (kvm_openfiles(fnlist, fcore, NULL) == -1) { | |
1d47dec3 | 235 | error("kvm_openfiles: %s", kvm_geterr()); |
aadf0902 MK |
236 | exit(1); |
237 | } | |
1d47dec3 MT |
238 | if ((ret = kvm_nlist(nl)) != 0) { |
239 | int i, quit = 0; | |
240 | ||
241 | if (ret == -1) { | |
242 | error("kvm_nlist: %s", kvm_geterr()); | |
243 | exit(1); | |
244 | } | |
245 | for (i = 0; i <= NLMANDATORY; i++) { | |
246 | if (!nl[i].n_value) { | |
247 | quit = 1; | |
248 | error("undefined symbol: %s\n", | |
249 | nl[i].n_name); | |
250 | } | |
251 | } | |
252 | if (quit) | |
253 | exit(1); | |
ceb84881 | 254 | } |
6102031f | 255 | if (!(filf | totflg | vnof | prcf | txtf | ttyf | usrf | swpf)) { |
2e924960 | 256 | printf("pstat: one or more of -[aivxptfsU] is required\n"); |
ae1f9014 SL |
257 | exit(1); |
258 | } | |
ceb84881 | 259 | if (filf||totflg) |
69d3d166 | 260 | dofile(); |
6102031f MT |
261 | if (vnof||totflg) |
262 | dovnode(); | |
ceb84881 BJ |
263 | if (prcf||totflg) |
264 | doproc(); | |
265 | if (txtf||totflg) | |
266 | dotext(); | |
267 | if (ttyf) | |
268 | dotty(); | |
269 | if (usrf) | |
270 | dousr(); | |
271 | if (swpf||totflg) | |
272 | doswap(); | |
273 | } | |
274 | ||
551215f4 MT |
275 | struct e_vnode { |
276 | struct vnode *avnode; | |
277 | struct vnode vnode; | |
278 | }; | |
279 | ||
6102031f | 280 | dovnode() |
ceb84881 | 281 | { |
551215f4 MT |
282 | register struct e_vnode *e_vnodebase, *endvnode, *evp; |
283 | register struct vnode *vp; | |
6102031f | 284 | register struct mount *maddr = NULL, *mp; |
6102031f | 285 | int numvnodes; |
551215f4 | 286 | struct e_vnode *loadvnodes(); |
6102031f MT |
287 | struct mount *getmnt(); |
288 | ||
551215f4 | 289 | e_vnodebase = loadvnodes(&numvnodes); |
ceb84881 | 290 | if (totflg) { |
6102031f | 291 | printf("%7d vnodes\n", numvnodes); |
ceb84881 BJ |
292 | return; |
293 | } | |
551215f4 | 294 | endvnode = e_vnodebase + numvnodes; |
6102031f MT |
295 | printf("%d active vnodes\n", numvnodes); |
296 | ||
297 | ||
551215f4 MT |
298 | #define ST mp->mnt_stat |
299 | for (evp = e_vnodebase; evp < endvnode; evp++) { | |
300 | vp = &evp->vnode; | |
6102031f MT |
301 | if (vp->v_mount != maddr) { |
302 | /* | |
303 | * New filesystem | |
304 | */ | |
305 | if ((mp = getmnt(vp->v_mount)) == NULL) | |
306 | continue; | |
307 | maddr = vp->v_mount; | |
308 | mount_print(mp); | |
309 | vnode_header(); | |
310 | switch(ST.f_type) { | |
311 | case MOUNT_UFS: | |
312 | case MOUNT_MFS: | |
313 | ufs_header(); | |
314 | break; | |
315 | case MOUNT_NFS: | |
316 | nfs_header(); | |
317 | break; | |
318 | case MOUNT_NONE: | |
319 | case MOUNT_PC: | |
320 | default: | |
321 | break; | |
322 | } | |
323 | printf("\n"); | |
324 | } | |
551215f4 | 325 | vnode_print(evp->avnode, vp); |
6102031f MT |
326 | switch(ST.f_type) { |
327 | case MOUNT_UFS: | |
328 | case MOUNT_MFS: | |
329 | ufs_print(vp); | |
330 | break; | |
331 | case MOUNT_NFS: | |
332 | nfs_print(vp); | |
333 | break; | |
334 | case MOUNT_NONE: | |
335 | case MOUNT_PC: | |
336 | default: | |
337 | break; | |
338 | } | |
339 | printf("\n"); | |
6102031f | 340 | } |
551215f4 | 341 | free(e_vnodebase); |
6102031f MT |
342 | } |
343 | ||
344 | vnode_header() | |
345 | { | |
b98ff689 | 346 | printf("ADDR TYP VFLAG USE HOLD"); |
6102031f MT |
347 | } |
348 | ||
551215f4 MT |
349 | vnode_print(avnode, vp) |
350 | struct vnode *avnode; | |
6102031f MT |
351 | struct vnode *vp; |
352 | { | |
353 | char *type, flags[16]; | |
354 | char *fp = flags; | |
355 | register flag; | |
356 | ||
357 | /* | |
358 | * set type | |
359 | */ | |
360 | switch(vp->v_type) { | |
361 | case VNON: | |
362 | type = "non"; break; | |
363 | case VREG: | |
364 | type = "reg"; break; | |
365 | case VDIR: | |
366 | type = "dir"; break; | |
367 | case VBLK: | |
368 | type = "blk"; break; | |
369 | case VCHR: | |
370 | type = "chr"; break; | |
371 | case VLNK: | |
372 | type = "lnk"; break; | |
373 | case VSOCK: | |
374 | type = "soc"; break; | |
375 | case VFIFO: | |
376 | type = "fif"; break; | |
377 | case VBAD: | |
378 | type = "bad"; break; | |
379 | default: | |
380 | type = "unk"; break; | |
381 | } | |
382 | /* | |
383 | * gather flags | |
384 | */ | |
385 | flag = vp->v_flag; | |
386 | if (flag & VROOT) | |
387 | *fp++ = 'R'; | |
388 | if (flag & VTEXT) | |
389 | *fp++ = 'T'; | |
1d47dec3 MT |
390 | if (flag & VSYSTEM) |
391 | *fp++ = 'S'; | |
6102031f MT |
392 | if (flag & VXLOCK) |
393 | *fp++ = 'L'; | |
394 | if (flag & VXWANT) | |
395 | *fp++ = 'W'; | |
6102031f MT |
396 | if (flag & VBWAIT) |
397 | *fp++ = 'B'; | |
1d47dec3 MT |
398 | if (flag & VALIASED) |
399 | *fp++ = 'A'; | |
6102031f MT |
400 | if (flag == 0) |
401 | *fp++ = '-'; | |
402 | *fp = '\0'; | |
403 | /* | |
404 | * print it | |
405 | */ | |
551215f4 MT |
406 | printf("%8x %s %5s %4d %4d", |
407 | avnode, type, flags, vp->v_usecount, vp->v_holdcnt); | |
6102031f MT |
408 | } |
409 | ||
410 | ufs_header() | |
411 | { | |
551215f4 | 412 | printf(" FILEID IFLAG RDEV|SZ"); |
6102031f MT |
413 | } |
414 | ||
415 | ufs_print(vp) | |
416 | struct vnode *vp; | |
417 | { | |
418 | struct inode *ip = VTOI(vp); | |
419 | char flagbuf[16], *flags = flagbuf; | |
420 | register flag; | |
421 | char *name; | |
422 | mode_t type; | |
423 | extern char *devname(); | |
424 | ||
425 | flag = ip->i_flag; | |
426 | if (flag & ILOCKED) | |
427 | *flags++ = 'L'; | |
428 | if (flag & IWANT) | |
429 | *flags++ = 'W'; | |
430 | if (flag & IRENAME) | |
431 | *flags++ = 'R'; | |
432 | if (flag & IUPD) | |
433 | *flags++ = 'U'; | |
434 | if (flag & IACC) | |
435 | *flags++ = 'A'; | |
436 | if (flag & ICHG) | |
437 | *flags++ = 'C'; | |
438 | if (flag & IMOD) | |
439 | *flags++ = 'M'; | |
440 | if (flag & ISHLOCK) | |
441 | *flags++ = 'S'; | |
442 | if (flag & IEXLOCK) | |
443 | *flags++ = 'E'; | |
444 | if (flag & ILWAIT) | |
445 | *flags++ = 'Z'; | |
446 | if (flag == 0) | |
447 | *flags++ = '-'; | |
448 | *flags = '\0'; | |
449 | ||
551215f4 | 450 | printf(" %6d %5s", ip->i_number, flagbuf); |
6102031f MT |
451 | type = ip->i_mode & S_IFMT; |
452 | if (type == S_IFCHR || type == S_IFBLK) | |
ff337c25 | 453 | if (nflg || ((name = devname(ip->i_rdev, type)) == NULL)) |
6102031f MT |
454 | printf(" %2d,%-2d", |
455 | major(ip->i_rdev), minor(ip->i_rdev)); | |
456 | else | |
457 | printf(" %7s", name); | |
458 | else | |
459 | printf(" %7d", ip->i_size); | |
460 | } | |
461 | ||
462 | nfs_header() | |
463 | { | |
551215f4 | 464 | printf(" FILEID NFLAG RDEV|SZ"); |
6102031f MT |
465 | } |
466 | ||
467 | nfs_print(vp) | |
468 | struct vnode *vp; | |
469 | { | |
551215f4 | 470 | struct nfsnode *np = VTONFS(vp); |
6102031f MT |
471 | char flagbuf[16], *flags = flagbuf; |
472 | register flag; | |
473 | char *name; | |
474 | mode_t type; | |
475 | extern char *devname(); | |
476 | ||
477 | flag = np->n_flag; | |
478 | if (flag & NLOCKED) | |
479 | *flags++ = 'L'; | |
480 | if (flag & NWANT) | |
481 | *flags++ = 'W'; | |
482 | if (flag & NMODIFIED) | |
483 | *flags++ = 'M'; | |
6102031f MT |
484 | if (flag & NWRITEERR) |
485 | *flags++ = 'E'; | |
486 | if (flag == 0) | |
487 | *flags++ = '-'; | |
488 | *flags = '\0'; | |
489 | ||
490 | #define VT np->n_vattr | |
551215f4 | 491 | printf(" %6d %5s", VT.va_fileid, flagbuf); |
6102031f MT |
492 | type = VT.va_mode & S_IFMT; |
493 | if (type == S_IFCHR || type == S_IFBLK) | |
ff337c25 | 494 | if (nflg || ((name = devname(VT.va_rdev, type)) == NULL)) |
6102031f MT |
495 | printf(" %2d,%-2d", |
496 | major(VT.va_rdev), minor(VT.va_rdev)); | |
497 | else | |
498 | printf(" %7s", name); | |
499 | else | |
500 | printf(" %7d", np->n_size); | |
501 | } | |
502 | ||
503 | /* | |
504 | * Given a pointer to a mount structure in kernel space, | |
505 | * read it in and return a usable pointer to it. | |
506 | */ | |
507 | struct mount * | |
508 | getmnt(maddr) | |
509 | struct mount *maddr; | |
510 | { | |
511 | static struct mtab { | |
512 | struct mtab *next; | |
513 | struct mount *maddr; | |
514 | struct mount mount; | |
515 | } *mhead = NULL; | |
516 | register struct mtab *mt; | |
517 | ||
518 | for (mt = mhead; mt != NULL; mt = mt->next) | |
519 | if (maddr == mt->maddr) | |
520 | return (&mt->mount); | |
521 | if ((mt = (struct mtab *)malloc(sizeof (struct mtab))) == NULL) { | |
522 | error("out of memory"); | |
523 | exit(1); | |
524 | } | |
1d47dec3 | 525 | if (kvm_read(V(maddr), &mt->mount, sizeof(struct mount)) != |
6102031f MT |
526 | sizeof(struct mount)) { |
527 | error("can't read mount table at %x", maddr); | |
528 | return (NULL); | |
529 | } | |
530 | mt->maddr = maddr; | |
531 | mt->next = mhead; | |
532 | mhead = mt; | |
533 | return (&mt->mount); | |
534 | } | |
535 | ||
536 | mount_print(mp) | |
537 | struct mount *mp; | |
538 | { | |
539 | char *type = "unknown"; | |
540 | register flags; | |
541 | ||
551215f4 | 542 | #define ST mp->mnt_stat |
6102031f MT |
543 | printf("*** MOUNT "); |
544 | switch (ST.f_type) { | |
545 | case MOUNT_NONE: | |
546 | type = "none"; | |
547 | break; | |
548 | case MOUNT_UFS: | |
549 | type = "ufs"; | |
550 | break; | |
551 | case MOUNT_NFS: | |
552 | type = "nfs"; | |
553 | break; | |
554 | case MOUNT_MFS: | |
555 | type = "mfs"; | |
556 | break; | |
557 | case MOUNT_PC: | |
558 | type = "pc"; | |
559 | break; | |
560 | } | |
561 | printf("%s %s on %s", type, ST.f_mntfromname, ST.f_mntonname); | |
551215f4 | 562 | if (flags = mp->mnt_flag) { |
6102031f MT |
563 | char *comma = "("; |
564 | ||
565 | putchar(' '); | |
551215f4 MT |
566 | /* user visable flags */ |
567 | if (flags & MNT_RDONLY) { | |
6102031f | 568 | printf("%srdonly", comma); |
551215f4 | 569 | flags &= ~MNT_RDONLY; |
6102031f MT |
570 | comma = ","; |
571 | } | |
551215f4 | 572 | if (flags & MNT_SYNCHRONOUS) { |
6102031f | 573 | printf("%ssynchronous", comma); |
551215f4 | 574 | flags &= ~MNT_SYNCHRONOUS; |
6102031f MT |
575 | comma = ","; |
576 | } | |
551215f4 | 577 | if (flags & MNT_NOEXEC) { |
6102031f | 578 | printf("%snoexec", comma); |
551215f4 | 579 | flags &= ~MNT_NOEXEC; |
6102031f MT |
580 | comma = ","; |
581 | } | |
551215f4 | 582 | if (flags & MNT_NOSUID) { |
6102031f | 583 | printf("%snosuid", comma); |
551215f4 | 584 | flags &= ~MNT_NOSUID; |
6102031f MT |
585 | comma = ","; |
586 | } | |
551215f4 | 587 | if (flags & MNT_NODEV) { |
6102031f | 588 | printf("%snodev", comma); |
551215f4 | 589 | flags &= ~MNT_NODEV; |
6102031f MT |
590 | comma = ","; |
591 | } | |
551215f4 | 592 | if (flags & MNT_EXPORTED) { |
6102031f | 593 | printf("%sexport", comma); |
551215f4 | 594 | flags &= ~MNT_EXPORTED; |
6102031f MT |
595 | comma = ","; |
596 | } | |
551215f4 | 597 | if (flags & MNT_EXRDONLY) { |
6102031f | 598 | printf("%sexrdonly", comma); |
551215f4 MT |
599 | flags &= ~MNT_EXRDONLY; |
600 | comma = ","; | |
601 | } | |
602 | if (flags & MNT_LOCAL) { | |
603 | printf("%slocal", comma); | |
604 | flags &= ~MNT_LOCAL; | |
6102031f MT |
605 | comma = ","; |
606 | } | |
551215f4 MT |
607 | if (flags & MNT_QUOTA) { |
608 | printf("%squota", comma); | |
609 | flags &= ~MNT_QUOTA; | |
610 | comma = ","; | |
611 | } | |
612 | /* filesystem control flags */ | |
613 | if (flags & MNT_UPDATE) { | |
614 | printf("%supdate", comma); | |
615 | flags &= ~MNT_UPDATE; | |
616 | comma = ","; | |
617 | } | |
618 | if (flags & MNT_MLOCK) { | |
6102031f | 619 | printf("%slock", comma); |
551215f4 | 620 | flags &= ~MNT_MLOCK; |
6102031f MT |
621 | comma = ","; |
622 | } | |
551215f4 | 623 | if (flags & MNT_MWAIT) { |
6102031f | 624 | printf("%swait", comma); |
551215f4 MT |
625 | flags &= ~MNT_MWAIT; |
626 | comma = ","; | |
627 | } | |
628 | if (flags & MNT_MPBUSY) { | |
629 | printf("%sbusy", comma); | |
630 | flags &= ~MNT_MPBUSY; | |
631 | comma = ","; | |
632 | } | |
633 | if (flags & MNT_MPWANT) { | |
634 | printf("%swant", comma); | |
635 | flags &= ~MNT_MPWANT; | |
6102031f MT |
636 | comma = ","; |
637 | } | |
551215f4 MT |
638 | if (flags & MNT_UNMOUNT) { |
639 | printf("%sunmount", comma); | |
640 | flags &= ~MNT_UNMOUNT; | |
6102031f MT |
641 | comma = ","; |
642 | } | |
551215f4 MT |
643 | if (flags) |
644 | printf("%sunknown_flags:%x", flags); | |
6102031f MT |
645 | printf(")"); |
646 | } | |
647 | printf("\n"); | |
648 | #undef ST | |
649 | } | |
650 | ||
551215f4 | 651 | struct e_vnode * |
6102031f MT |
652 | loadvnodes(avnodes) |
653 | int *avnodes; | |
654 | { | |
caa05a92 | 655 | int ret, copysize; |
551215f4 | 656 | struct e_vnode *vnodebase; |
6102031f MT |
657 | |
658 | if (fcore != NULL) { | |
1bbe0c66 MT |
659 | /* |
660 | * add emulation of KINFO_VNODE here | |
661 | */ | |
662 | error("vnodes on dead kernel, not impl\n"); | |
6102031f MT |
663 | exit(1); |
664 | } | |
665 | if ((ret = getkerninfo(KINFO_VNODE, NULL, NULL, 0)) == -1) { | |
666 | syserror("can't get estimate for kerninfo"); | |
667 | exit(1); | |
668 | } | |
669 | copysize = ret; | |
551215f4 | 670 | if ((vnodebase = (struct e_vnode *)malloc(copysize)) |
6102031f MT |
671 | == NULL) { |
672 | error("out of memory"); | |
673 | exit(1); | |
674 | } | |
675 | if ((ret = getkerninfo(KINFO_VNODE, vnodebase, ©size, 0)) | |
676 | == -1) { | |
677 | syserror("can't get vnode list"); | |
678 | exit(1); | |
679 | } | |
551215f4 | 680 | if (copysize % sizeof (struct e_vnode)) { |
6102031f | 681 | error("vnode size mismatch"); |
1d47dec3 | 682 | exit(1); |
ceb84881 | 683 | } |
551215f4 | 684 | *avnodes = copysize / sizeof (struct e_vnode); |
6102031f MT |
685 | |
686 | return (vnodebase); | |
69d3d166 BJ |
687 | } |
688 | ||
9ed2dfb9 | 689 | u_long |
dc2a22f1 | 690 | getword(loc) |
1d47dec3 | 691 | int loc; |
69d3d166 | 692 | { |
9ed2dfb9 | 693 | u_long word; |
69d3d166 | 694 | |
1d47dec3 | 695 | kvm_read(V(loc), &word, sizeof (word)); |
69d3d166 | 696 | return (word); |
ceb84881 BJ |
697 | } |
698 | ||
699 | putf(v, n) | |
700 | { | |
701 | if (v) | |
702 | printf("%c", n); | |
703 | else | |
69d3d166 | 704 | printf(" "); |
ceb84881 BJ |
705 | } |
706 | ||
707 | dotext() | |
708 | { | |
d7985207 MK |
709 | #ifdef NEWVM |
710 | printf("no text table in this system\n"); | |
711 | #else | |
ceb84881 | 712 | register struct text *xp; |
69d3d166 BJ |
713 | int ntext; |
714 | struct text *xtext, *atext; | |
9ed2dfb9 | 715 | int ntx, ntxca; |
ceb84881 | 716 | |
9ed2dfb9 | 717 | ntx = ntxca = 0; |
dc2a22f1 | 718 | ntext = getword(nl[SNTEXT].n_value); |
69d3d166 | 719 | xtext = (struct text *)calloc(ntext, sizeof (struct text)); |
dc2a22f1 | 720 | atext = (struct text *)getword(nl[STEXT].n_value); |
9ed2dfb9 MK |
721 | if (ntext < 0 || ntext > 10000) { |
722 | fprintf(stderr, "number of texts is preposterous (%d)\n", | |
723 | ntext); | |
724 | return; | |
725 | } | |
726 | if (xtext == NULL) { | |
727 | fprintf(stderr, "can't allocate memory for text table\n"); | |
728 | return; | |
729 | } | |
6102031f | 730 | kvm_read(atext, xtext, ntext * sizeof (struct text)); |
9ed2dfb9 | 731 | for (xp = xtext; xp < &xtext[ntext]; xp++) { |
9eecf21c | 732 | if (xp->x_vptr != NULL) |
9ed2dfb9 MK |
733 | ntxca++; |
734 | if (xp->x_count != 0) | |
ceb84881 | 735 | ntx++; |
9ed2dfb9 | 736 | } |
ceb84881 | 737 | if (totflg) { |
9ed2dfb9 | 738 | printf("%3d/%3d texts active, %3d used\n", ntx, ntext, ntxca); |
ceb84881 BJ |
739 | return; |
740 | } | |
9ed2dfb9 MK |
741 | printf("%d/%d active texts, %d used\n", ntx, ntext, ntxca); |
742 | printf("\ | |
9eecf21c | 743 | LOC FLAGS DADDR CADDR RSS SIZE VPTR CNT CCNT FORW BACK\n"); |
69d3d166 | 744 | for (xp = xtext; xp < &xtext[ntext]; xp++) { |
9eecf21c | 745 | if (xp->x_vptr == NULL) |
ceb84881 | 746 | continue; |
69d3d166 | 747 | printf("%8.1x", atext + (xp - xtext)); |
ceb84881 | 748 | printf(" "); |
9eecf21c | 749 | putf(xp->x_flag&XPAGV, 'P'); |
ceb84881 BJ |
750 | putf(xp->x_flag&XTRC, 'T'); |
751 | putf(xp->x_flag&XWRIT, 'W'); | |
752 | putf(xp->x_flag&XLOAD, 'L'); | |
753 | putf(xp->x_flag&XLOCK, 'K'); | |
754 | putf(xp->x_flag&XWANT, 'w'); | |
ceb84881 | 755 | printf("%5x", xp->x_daddr[0]); |
9ed2dfb9 | 756 | printf("%10x", xp->x_caddr); |
ceb84881 BJ |
757 | printf("%5d", xp->x_rssize); |
758 | printf("%5d", xp->x_size); | |
9eecf21c | 759 | printf("%10.1x", xp->x_vptr); |
ceb84881 | 760 | printf("%5d", xp->x_count&0377); |
54298f71 | 761 | printf("%5d", xp->x_ccount); |
9ed2dfb9 MK |
762 | printf("%10x", xp->x_forw); |
763 | printf("%9x", xp->x_back); | |
ceb84881 BJ |
764 | printf("\n"); |
765 | } | |
69d3d166 | 766 | free(xtext); |
d7985207 | 767 | #endif |
ceb84881 BJ |
768 | } |
769 | ||
770 | doproc() | |
771 | { | |
d7985207 | 772 | #ifdef NEWVM |
1bbe0c66 | 773 | printf("pstat: -p no longer supported (use ps)\n"); |
d7985207 | 774 | #else |
69d3d166 BJ |
775 | struct proc *xproc, *aproc; |
776 | int nproc; | |
ceb84881 BJ |
777 | register struct proc *pp; |
778 | register loc, np; | |
caa05a92 | 779 | /* |
ceb84881 | 780 | struct pte apte; |
caa05a92 | 781 | */ |
ceb84881 | 782 | |
dc2a22f1 | 783 | nproc = getword(nl[SNPROC].n_value); |
69d3d166 | 784 | xproc = (struct proc *)calloc(nproc, sizeof (struct proc)); |
dc2a22f1 | 785 | aproc = (struct proc *)getword(nl[SPROC].n_value); |
2e924960 | 786 | if (nproc < 0 || nproc > 100000) { |
9ed2dfb9 MK |
787 | fprintf(stderr, "number of procs is preposterous (%d)\n", |
788 | nproc); | |
789 | return; | |
790 | } | |
791 | if (xproc == NULL) { | |
792 | fprintf(stderr, "can't allocate memory for proc table\n"); | |
793 | return; | |
794 | } | |
6102031f | 795 | kvm_read(aproc, xproc, nproc * sizeof (struct proc)); |
ceb84881 | 796 | np = 0; |
69d3d166 | 797 | for (pp=xproc; pp < &xproc[nproc]; pp++) |
ceb84881 BJ |
798 | if (pp->p_stat) |
799 | np++; | |
800 | if (totflg) { | |
69d3d166 | 801 | printf("%3d/%3d processes\n", np, nproc); |
ceb84881 BJ |
802 | return; |
803 | } | |
69d3d166 | 804 | printf("%d/%d processes\n", np, nproc); |
1b27d03f | 805 | printf(" LOC S F POIP PRI SIG UID SLP TIM CPU NI PID PPID ADDR RSS SRSS SIZE WCHAN LINK TEXTP\n"); |
69d3d166 | 806 | for (pp=xproc; pp<&xproc[nproc]; pp++) { |
ceb84881 BJ |
807 | if (pp->p_stat==0 && allflg==0) |
808 | continue; | |
69d3d166 | 809 | printf("%8x", aproc + (pp - xproc)); |
ceb84881 | 810 | printf(" %2d", pp->p_stat); |
1b27d03f | 811 | printf(" %8x", pp->p_flag); |
ceb84881 BJ |
812 | printf(" %4d", pp->p_poip); |
813 | printf(" %3d", pp->p_pri); | |
54298f71 | 814 | printf(" %8x", pp->p_sig); |
ceb84881 BJ |
815 | printf(" %4d", pp->p_uid); |
816 | printf(" %3d", pp->p_slptime); | |
817 | printf(" %3d", pp->p_time); | |
818 | printf(" %4d", pp->p_cpu&0377); | |
819 | printf(" %3d", pp->p_nice); | |
ceb84881 BJ |
820 | printf(" %6d", pp->p_pid); |
821 | printf(" %6d", pp->p_ppid); | |
6102031f | 822 | /* |
aadf0902 | 823 | if (pp->p_flag & SLOAD) { |
6102031f | 824 | kvm_read(pp->p_addr, &apte, sizeof(apte)); |
aadf0902 MK |
825 | printf(" %8x", apte.pg_pfnum); |
826 | } else | |
827 | printf(" %8x", pp->p_swaddr); | |
6102031f | 828 | */ |
ceb84881 BJ |
829 | printf(" %4x", pp->p_rssize); |
830 | printf(" %4x", pp->p_swrss); | |
831 | printf(" %5x", pp->p_dsize+pp->p_ssize); | |
832 | printf(" %7x", clear(pp->p_wchan)); | |
833 | printf(" %7x", clear(pp->p_link)); | |
834 | printf(" %7x", clear(pp->p_textp)); | |
ceb84881 BJ |
835 | printf("\n"); |
836 | } | |
9ed2dfb9 | 837 | free(xproc); |
d7985207 | 838 | #endif |
ceb84881 BJ |
839 | } |
840 | ||
b98ff689 | 841 | char mesg[] = " LINE RAW CAN OUT HWT LWT ADDR COL STATE SESS PGID DISC\n"; |
6102031f MT |
842 | int ttyspace = 128; |
843 | struct tty *tty; | |
5cf6fff2 | 844 | |
ceb84881 BJ |
845 | dotty() |
846 | { | |
ceb84881 | 847 | |
13562341 MK |
848 | if ((tty = (struct tty *)malloc(ttyspace * sizeof(*tty))) == 0) { |
849 | printf("pstat: out of memory\n"); | |
850 | return; | |
851 | } | |
b98ff689 | 852 | #ifndef hp300 |
ceb84881 | 853 | printf("1 cons\n"); |
1d47dec3 | 854 | kvm_read(V(nl[SCONS].n_value), tty, sizeof(*tty)); |
ceb84881 | 855 | printf(mesg); |
13562341 | 856 | ttyprt(&tty[0], 0); |
b98ff689 | 857 | #endif |
4242be26 | 858 | #ifdef vax |
bac975ad MT |
859 | if (nl[SNQD].n_type != 0) |
860 | doqdss(); | |
5cf6fff2 KM |
861 | if (nl[SNDZ].n_type != 0) |
862 | dottytype("dz", SDZ, SNDZ); | |
863 | if (nl[SNDH].n_type != 0) | |
864 | dottytype("dh", SDH, SNDH); | |
865 | if (nl[SNDMF].n_type != 0) | |
866 | dottytype("dmf", SDMF, SNDMF); | |
867 | if (nl[SNDHU].n_type != 0) | |
868 | dottytype("dhu", SDHU, SNDHU); | |
35d0530f JB |
869 | if (nl[SNDMZ].n_type != 0) |
870 | dottytype("dmz", SDMZ, SNDMZ); | |
4242be26 SL |
871 | #endif |
872 | #ifdef tahoe | |
873 | if (nl[SNVX].n_type != 0) | |
874 | dottytype("vx", SVX, SNVX); | |
c6864ab6 KB |
875 | if (nl[SNMP].n_type != 0) |
876 | dottytype("mp", SMP, SNMP); | |
b98ff689 MK |
877 | #endif |
878 | #ifdef hp300 | |
879 | if (nl[SNITE].n_type != 0) | |
880 | dottytype("ite", SITE, SNITE); | |
881 | if (nl[SNDCA].n_type != 0) | |
882 | dottytype("dca", SDCA, SNDCA); | |
883 | if (nl[SNDCM].n_type != 0) | |
884 | dottytype("dcm", SDCM, SNDCM); | |
885 | if (nl[SNDCL].n_type != 0) | |
886 | dottytype("dcl", SDCL, SNDCL); | |
4242be26 | 887 | #endif |
5cf6fff2 KM |
888 | if (nl[SNPTY].n_type != 0) |
889 | dottytype("pty", SPTY, SNPTY); | |
890 | } | |
891 | ||
bac975ad | 892 | /* |
844d8384 MT |
893 | * Special case the qdss: there are 4 ttys per qdss, |
894 | * but only the first of each is used as a tty. | |
bac975ad MT |
895 | */ |
896 | #ifdef vax | |
897 | doqdss() | |
898 | { | |
899 | int nqd; | |
900 | register struct tty *tp; | |
901 | ||
1d47dec3 | 902 | kvm_read(V(nl[SNQD].n_value), &nqd, sizeof(nqd)); |
bac975ad | 903 | printf("%d qd\n", nqd); |
1d47dec3 | 904 | kvm_read((V(nl[SQD].n_value), tty, nqd * sizeof(struct tty) * 4); |
bac975ad MT |
905 | printf(mesg); |
906 | for (tp = tty; tp < &tty[nqd * 4]; tp += 4) | |
907 | ttyprt(tp, tp - tty); | |
908 | } | |
909 | #endif | |
910 | ||
5cf6fff2 KM |
911 | dottytype(name, type, number) |
912 | char *name; | |
913 | { | |
914 | int ntty; | |
915 | register struct tty *tp; | |
916 | extern char *realloc(); | |
917 | ||
bac975ad | 918 | if (tty == (struct tty *)0) |
890571d1 | 919 | return; |
1d47dec3 | 920 | kvm_read(V(nl[number].n_value), &ntty, sizeof(ntty)); |
5cf6fff2 | 921 | printf("%d %s lines\n", ntty, name); |
13562341 MK |
922 | if (ntty > ttyspace) { |
923 | ttyspace = ntty; | |
924 | if ((tty = (struct tty *)realloc(tty, ttyspace * sizeof(*tty))) == 0) { | |
925 | printf("pstat: out of memory\n"); | |
926 | return; | |
927 | } | |
676bc34a | 928 | } |
1d47dec3 | 929 | kvm_read(V(nl[type].n_value), tty, ntty * sizeof(struct tty)); |
8faa0fee | 930 | printf(mesg); |
13562341 MK |
931 | for (tp = tty; tp < &tty[ntty]; tp++) |
932 | ttyprt(tp, tp - tty); | |
ceb84881 BJ |
933 | } |
934 | ||
844d8384 MT |
935 | struct { |
936 | int flag; | |
937 | char val; | |
938 | } ttystates[] = { | |
939 | TS_WOPEN, 'W', | |
940 | TS_ISOPEN, 'O', | |
941 | TS_CARR_ON, 'C', | |
942 | TS_TIMEOUT, 'T', | |
943 | TS_FLUSH, 'F', | |
944 | TS_BUSY, 'B', | |
945 | TS_ASLEEP, 'A', | |
946 | TS_XCLUDE, 'X', | |
947 | TS_TTSTOP, 'S', | |
844d8384 MT |
948 | TS_TBLOCK, 'K', |
949 | TS_RCOLL, 'R', | |
950 | TS_WCOLL, 'I', /* running short on letters ! */ | |
951 | TS_ASYNC, 'Y', | |
952 | TS_BKSL, 'D', | |
953 | TS_ERASE, 'E', | |
954 | TS_LNCH, 'L', | |
955 | TS_TYPEN, 'P', | |
956 | TS_CNTTB, 'N', | |
957 | 0, 0 | |
958 | }; | |
959 | ||
ceb84881 BJ |
960 | ttyprt(atp, line) |
961 | struct tty *atp; | |
962 | { | |
963 | register struct tty *tp; | |
844d8384 MT |
964 | char state[20]; |
965 | register i, j; | |
551215f4 MT |
966 | char *name; |
967 | extern char *devname(); | |
968 | pid_t pgid; | |
ceb84881 | 969 | |
ceb84881 | 970 | tp = atp; |
7e7bb114 | 971 | if (nflg || tp->t_dev == 0 || |
551215f4 MT |
972 | (name = devname(tp->t_dev, S_IFCHR)) == NULL) |
973 | printf("%7d ", line); | |
974 | else | |
975 | printf("%7s ", name); | |
976 | printf("%2d %3d ", tp->t_rawq.c_cc, tp->t_canq.c_cc); | |
b98ff689 | 977 | printf("%3d %4d %3d %8x %3d ", tp->t_outq.c_cc, |
844d8384 MT |
978 | tp->t_hiwat, tp->t_lowat, tp->t_addr, tp->t_col); |
979 | for (i = j = 0; ttystates[i].flag; i++) | |
980 | if (tp->t_state&ttystates[i].flag) | |
981 | state[j++] = ttystates[i].val; | |
b98ff689 MK |
982 | if (j == 0) |
983 | state[j++] = '-'; | |
844d8384 | 984 | state[j] = '\0'; |
b98ff689 | 985 | printf("%-4s %6x", state, (u_long)tp->t_session & ~KERNBASE); |
551215f4 MT |
986 | if (tp->t_pgrp == NULL || kvm_read(&tp->t_pgrp->pg_id, &pgid, |
987 | sizeof (pid_t)) != sizeof (pid_t)) | |
988 | pgid = 0; | |
989 | printf("%6d ", pgid); | |
ceb84881 BJ |
990 | switch (tp->t_line) { |
991 | ||
b98ff689 | 992 | case TTYDISC: |
844d8384 | 993 | printf("term\n"); |
ceb84881 BJ |
994 | break; |
995 | ||
8faa0fee | 996 | case TABLDISC: |
844d8384 | 997 | printf("tab\n"); |
8faa0fee EW |
998 | break; |
999 | ||
399e4254 | 1000 | case SLIPDISC: |
844d8384 | 1001 | printf("slip\n"); |
399e4254 KB |
1002 | break; |
1003 | ||
8faa0fee | 1004 | default: |
844d8384 | 1005 | printf("%d\n", tp->t_line); |
ceb84881 | 1006 | } |
ceb84881 BJ |
1007 | } |
1008 | ||
1d47dec3 MT |
1009 | /* |
1010 | * The user structure is going away. What's left here won't | |
1011 | * be around for long. | |
1012 | */ | |
ceb84881 BJ |
1013 | dousr() |
1014 | { | |
d7985207 MK |
1015 | #ifdef NEWVM |
1016 | printf("nothing left in user structure in this system\n"); | |
1017 | #else | |
8a5d2599 | 1018 | register struct user *up; |
ceb84881 | 1019 | register i, j, *ip; |
2e924960 | 1020 | register struct nameidata *nd; |
8a5d2599 | 1021 | struct proc *p; |
2e924960 | 1022 | int ret; |
ceb84881 | 1023 | |
2e924960 MT |
1024 | if ((ret = kvm_getprocs(KINFO_PROC_PID, upid)) != 1) { |
1025 | if (ret == -1) | |
1026 | error("kvm_getproc: %s", kvm_geterr()); | |
1027 | else | |
1028 | error("can't locate process %d", upid); | |
8a5d2599 MT |
1029 | return (1); |
1030 | } | |
2e924960 | 1031 | if ((p = kvm_nextproc()) == NULL) { |
8a5d2599 MT |
1032 | error("kvm_nextproc: %s", kvm_geterr()); |
1033 | return (1); | |
1034 | } | |
2e924960 | 1035 | if ((up = kvm_getu(p)) == NULL) { |
8a5d2599 MT |
1036 | error("kvm_getu: %s", kvm_geterr()); |
1037 | return (1); | |
1038 | } | |
2e924960 | 1039 | nd = &up->u_nd; |
ceb84881 | 1040 | printf("pcb"); |
8a5d2599 | 1041 | ip = (int *)&up->u_pcb; |
2e924960 MT |
1042 | i = 0; |
1043 | while (ip < (int *)((char *)&up->u_pcb + sizeof (struct pcb))) { | |
1044 | if (i%4 == 0) | |
1045 | putchar('\t'); | |
1046 | printf("%#10x ", *ip++); | |
1047 | if (i%4 == 3) | |
1048 | putchar('\n'); | |
1049 | i++; | |
ceb84881 | 1050 | } |
2e924960 MT |
1051 | if (i%4) |
1052 | putchar('\n'); | |
1053 | printf("procp\t%#x\n", up->u_procp); | |
1054 | printf("ar0\t%#x\n", up->u_ar0); | |
1055 | printf("sizes\ttext %d data %d stack %d\n", | |
1056 | up->u_tsize, up->u_dsize, up->u_ssize); | |
2e924960 MT |
1057 | printf("ssave"); |
1058 | for (i=0; i<sizeof(label_t)/sizeof(int); i++) { | |
ceb84881 BJ |
1059 | if (i%5==0) |
1060 | printf("\t"); | |
2e924960 | 1061 | printf("%#11x", up->u_ssave.val[i]); |
ceb84881 BJ |
1062 | if (i%5==4) |
1063 | printf("\n"); | |
1064 | } | |
1065 | if (i%5) | |
1066 | printf("\n"); | |
2e924960 MT |
1067 | printf("odsize\t%#x\n", up->u_odsize); |
1068 | printf("ossize\t%#x\n", up->u_ossize); | |
1069 | printf("outime\t%d\n", up->u_outime); | |
1070 | printf("mmap\t%#x\n", up->u_mmap); | |
1071 | printf("sigs"); | |
1072 | for (i=0; i<NSIG; i++) { | |
aadf0902 MK |
1073 | if (i % 8 == 0) |
1074 | printf("\t"); | |
2e924960 | 1075 | printf("%#x ", up->u_signal[i]); |
aadf0902 MK |
1076 | if (i % 8 == 7) |
1077 | printf("\n"); | |
1078 | } | |
1079 | if (i % 8) | |
1080 | printf("\n"); | |
2e924960 MT |
1081 | printf("sigmask"); |
1082 | for (i=0; i<NSIG; i++) { | |
aadf0902 MK |
1083 | if (i % 8 == 0) |
1084 | printf("\t"); | |
2e924960 | 1085 | printf("%#x ", up->u_sigmask[i]); |
aadf0902 MK |
1086 | if (i % 8 == 7) |
1087 | printf("\n"); | |
1088 | } | |
1089 | if (i % 8) | |
1090 | printf("\n"); | |
2e924960 MT |
1091 | printf("sigonstack\t%#x\n", up->u_sigonstack); |
1092 | printf("sigintr\t%#x\n", up->u_sigintr); | |
1093 | printf("oldmask\t%#x\n", up->u_oldmask); | |
1094 | printf("sigstack\t%#x %#x\n", | |
1095 | up->u_sigstack.ss_sp, up->u_sigstack.ss_onstack); | |
1096 | printf("sig\t%#x\n", up->u_sig); | |
1097 | printf("code\t%#x\n", up->u_code); | |
2e924960 MT |
1098 | printf("start\t%ld secs %ld usecs\n", |
1099 | up->u_start.tv_sec, up->u_start.tv_usec); | |
1100 | printf("acflag\t%#x\n", up->u_acflag); | |
1101 | printf("prof\t%#x %#x %#x %#x\n", up->u_prof.pr_base, up->u_prof.pr_size, | |
8a5d2599 | 1102 | up->u_prof.pr_off, up->u_prof.pr_scale); |
88a58f27 | 1103 | printf("ru\t"); |
8a5d2599 MT |
1104 | ip = (int *)&up->u_ru; |
1105 | for (i = 0; i < sizeof(up->u_ru)/sizeof(int); i++) | |
b9e98a4b | 1106 | printf("%ld ", ip[i]); |
ceb84881 | 1107 | printf("\n"); |
8a5d2599 | 1108 | ip = (int *)&up->u_cru; |
88a58f27 | 1109 | printf("cru\t"); |
8a5d2599 | 1110 | for (i = 0; i < sizeof(up->u_cru)/sizeof(int); i++) |
b9e98a4b | 1111 | printf("%ld ", ip[i]); |
ceb84881 | 1112 | printf("\n"); |
d7985207 | 1113 | #endif |
ceb84881 BJ |
1114 | } |
1115 | ||
1116 | oatoi(s) | |
1117 | char *s; | |
1118 | { | |
1119 | register v; | |
1120 | ||
1121 | v = 0; | |
1122 | while (*s) | |
1123 | v = (v<<3) + *s++ - '0'; | |
1124 | return(v); | |
1125 | } | |
1126 | ||
69d3d166 | 1127 | dofile() |
ceb84881 | 1128 | { |
ceb84881 | 1129 | register struct file *fp; |
1bbe0c66 MT |
1130 | struct file *addr; |
1131 | char *buf; | |
1132 | int len, maxfile, nfile; | |
1133 | struct nlist fnl[] = { | |
1134 | #define FNL_NFILE 0 | |
1135 | {"_nfiles"}, | |
1136 | #define FNL_MAXFILE 1 | |
1137 | {"_maxfiles"}, | |
1138 | {""} | |
1139 | }; | |
71c73ab0 | 1140 | static char *dtypes[] = { "???", "inode", "socket" }; |
ceb84881 | 1141 | |
1bbe0c66 MT |
1142 | if (kvm_nlist(fnl) != 0) { |
1143 | error("kvm_nlist: no _nfiles or _maxfiles: %s", | |
1144 | kvm_geterr()); | |
9ed2dfb9 MK |
1145 | return; |
1146 | } | |
1bbe0c66 MT |
1147 | kvm_read(V(fnl[FNL_MAXFILE].n_value), &maxfile, |
1148 | sizeof (maxfile)); | |
ceb84881 | 1149 | if (totflg) { |
1bbe0c66 MT |
1150 | kvm_read(V(fnl[FNL_NFILE].n_value), &nfile, sizeof (nfile)); |
1151 | printf("%3d/%3d files\n", nfile, maxfile); | |
ceb84881 BJ |
1152 | return; |
1153 | } | |
1bbe0c66 MT |
1154 | if (getfiles(&buf, &len) == -1) |
1155 | return; | |
1156 | /* | |
1157 | * getfiles returns in malloc'd buf a pointer to the first file | |
1158 | * structure, and then an array of file structs (whose | |
1159 | * addresses are derivable from the previous entry) | |
1160 | */ | |
1161 | addr = *((struct file **)buf); | |
1162 | fp = (struct file *)(buf + sizeof (struct file *)); | |
1163 | nfile = (len - sizeof (struct file *)) / sizeof (struct file); | |
1164 | ||
1165 | printf("%d/%d open files\n", nfile, maxfile); | |
192c0cf3 | 1166 | printf(" LOC TYPE FLG CNT MSG DATA OFFSET\n"); |
1bbe0c66 MT |
1167 | for (; (char *)fp < buf + len; addr = fp->f_filef, fp++) { |
1168 | printf("%x ", addr); | |
71c73ab0 | 1169 | if (fp->f_type <= DTYPE_SOCKET) |
ae1f9014 SL |
1170 | printf("%-8.8s", dtypes[fp->f_type]); |
1171 | else | |
ff8002b1 | 1172 | printf("%8d", fp->f_type); |
ceb84881 BJ |
1173 | putf(fp->f_flag&FREAD, 'R'); |
1174 | putf(fp->f_flag&FWRITE, 'W'); | |
ae1f9014 | 1175 | putf(fp->f_flag&FAPPEND, 'A'); |
38e88f54 | 1176 | #ifdef FSHLOCK /* currently gone */ |
192c0cf3 SL |
1177 | putf(fp->f_flag&FSHLOCK, 'S'); |
1178 | putf(fp->f_flag&FEXLOCK, 'X'); | |
1bbe0c66 MT |
1179 | #else |
1180 | putf(0, ' '); | |
1181 | putf(0, ' '); | |
38e88f54 | 1182 | #endif |
192c0cf3 | 1183 | putf(fp->f_flag&FASYNC, 'I'); |
1bbe0c66 MT |
1184 | printf(" %3d", fp->f_count); |
1185 | printf(" %3d", fp->f_msgcount); | |
71c73ab0 SL |
1186 | printf(" %8.1x", fp->f_data); |
1187 | if (fp->f_offset < 0) | |
1188 | printf(" %x\n", fp->f_offset); | |
676bc34a BJ |
1189 | else |
1190 | printf(" %ld\n", fp->f_offset); | |
ceb84881 | 1191 | } |
1bbe0c66 | 1192 | free(buf); |
ceb84881 BJ |
1193 | } |
1194 | ||
1bbe0c66 MT |
1195 | getfiles(abuf, alen) |
1196 | char **abuf; | |
1197 | int *alen; | |
1198 | { | |
1199 | char *buf; | |
1200 | int len; | |
1201 | ||
1202 | if (fcore != NULL) { | |
1203 | /* | |
1204 | * add emulation of KINFO_FILE here | |
1205 | */ | |
1206 | error("files on dead kernel, not impl\n"); | |
1207 | exit(1); | |
1208 | } | |
1209 | if ((len = getkerninfo(KINFO_FILE, NULL, NULL, 0)) == -1) { | |
1210 | syserror("getkerninfo estimate"); | |
1211 | return (-1); | |
1212 | } | |
1213 | if ((buf = (char *)malloc(len)) == NULL) { | |
1214 | error("out of memory"); | |
1215 | return (-1); | |
1216 | } | |
1217 | if ((len = getkerninfo(KINFO_FILE, buf, &len, 0)) == -1) { | |
1218 | syserror("getkerninfo"); | |
1219 | return (-1); | |
1220 | } | |
1221 | *abuf = buf; | |
1222 | *alen = len; | |
1223 | return (0); | |
1224 | } | |
1225 | ||
1226 | ||
d7985207 MK |
1227 | #ifdef NEWVM |
1228 | doswap() | |
1229 | { | |
1230 | printf("swap statistics not yet supported in this system\n"); | |
1231 | } | |
1232 | ||
1233 | #else /* NEWVM */ | |
e79dc02e SL |
1234 | int dmmin, dmmax, nswdev; |
1235 | ||
ceb84881 BJ |
1236 | doswap() |
1237 | { | |
69d3d166 BJ |
1238 | struct proc *proc; |
1239 | int nproc; | |
1240 | struct text *xtext; | |
1241 | int ntext; | |
1242 | struct map *swapmap; | |
1243 | int nswapmap; | |
b94a50ef | 1244 | struct swdevt *swdevt, *sw; |
ceb84881 | 1245 | register struct proc *pp; |
e79dc02e SL |
1246 | int nswap, used, tused, free, waste; |
1247 | int db, sb; | |
df3e00cc | 1248 | register struct mapent *me; |
ceb84881 | 1249 | register struct text *xp; |
e79dc02e | 1250 | int i, j; |
f85d329a | 1251 | long rmalloc(); |
ceb84881 | 1252 | |
dc2a22f1 KM |
1253 | nproc = getword(nl[SNPROC].n_value); |
1254 | ntext = getword(nl[SNTEXT].n_value); | |
9ed2dfb9 MK |
1255 | if (nproc < 0 || nproc > 10000 || ntext < 0 || ntext > 10000) { |
1256 | fprintf(stderr, "number of procs/texts is preposterous (%d, %d)\n", | |
1257 | nproc, ntext); | |
1258 | return; | |
1259 | } | |
1260 | proc = (struct proc *)calloc(nproc, sizeof (struct proc)); | |
1261 | if (proc == NULL) { | |
1262 | fprintf(stderr, "can't allocate memory for proc table\n"); | |
1263 | exit(1); | |
1264 | } | |
b94a50ef | 1265 | xtext = (struct text *)calloc(ntext, sizeof (struct text)); |
9ed2dfb9 MK |
1266 | if (xtext == NULL) { |
1267 | fprintf(stderr, "can't allocate memory for text table\n"); | |
1268 | exit(1); | |
1269 | } | |
dc2a22f1 | 1270 | nswapmap = getword(nl[SNSWAPMAP].n_value); |
69d3d166 | 1271 | swapmap = (struct map *)calloc(nswapmap, sizeof (struct map)); |
9ed2dfb9 MK |
1272 | if (swapmap == NULL) { |
1273 | fprintf(stderr, "can't allocate memory for swapmap\n"); | |
1274 | exit(1); | |
1275 | } | |
dc2a22f1 | 1276 | nswdev = getword(nl[SNSWDEV].n_value); |
b94a50ef | 1277 | swdevt = (struct swdevt *)calloc(nswdev, sizeof (struct swdevt)); |
9ed2dfb9 MK |
1278 | if (swdevt == NULL) { |
1279 | fprintf(stderr, "can't allocate memory for swdevt table\n"); | |
1280 | exit(1); | |
1281 | } | |
1d47dec3 | 1282 | kvm_read(V(nl[SSWDEVT].n_value), swdevt, |
2e924960 | 1283 | nswdev * sizeof (struct swdevt)); |
1d47dec3 | 1284 | kvm_read(V(getword(nl[SPROC].n_value)), proc, |
2e924960 | 1285 | nproc * sizeof (struct proc)); |
1d47dec3 | 1286 | kvm_read(V(getword(nl[STEXT].n_value)), xtext, |
2e924960 | 1287 | ntext * sizeof (struct text)); |
1d47dec3 | 1288 | kvm_read(V(getword(nl[SWAPMAP].n_value)), swapmap, |
2e924960 | 1289 | nswapmap * sizeof (struct map)); |
6102031f | 1290 | |
33b2e9da | 1291 | swapmap->m_name = "swap"; |
e49b41bc | 1292 | swapmap->m_limit = (struct mapent *)&swapmap[nswapmap]; |
dc2a22f1 KM |
1293 | dmmin = getword(nl[SDMMIN].n_value); |
1294 | dmmax = getword(nl[SDMMAX].n_value); | |
b94a50ef SL |
1295 | nswap = 0; |
1296 | for (sw = swdevt; sw < &swdevt[nswdev]; sw++) | |
491de191 KM |
1297 | if (sw->sw_freed) |
1298 | nswap += sw->sw_nblks; | |
ceb84881 | 1299 | free = 0; |
df3e00cc BJ |
1300 | for (me = (struct mapent *)(swapmap+1); |
1301 | me < (struct mapent *)&swapmap[nswapmap]; me++) | |
1302 | free += me->m_size; | |
ceb84881 | 1303 | tused = 0; |
69d3d166 | 1304 | for (xp = xtext; xp < &xtext[ntext]; xp++) |
9eecf21c | 1305 | if (xp->x_vptr!=NULL) { |
79877ea5 | 1306 | tused += ctod(clrnd(xp->x_size)); |
9eecf21c | 1307 | if (xp->x_flag & XPAGV) |
79877ea5 | 1308 | tused += ctod(clrnd(ctopt(xp->x_size))); |
b94a50ef | 1309 | } |
ceb84881 | 1310 | used = tused; |
e79dc02e | 1311 | waste = 0; |
69d3d166 | 1312 | for (pp = proc; pp < &proc[nproc]; pp++) { |
ceb84881 BJ |
1313 | if (pp->p_stat == 0 || pp->p_stat == SZOMB) |
1314 | continue; | |
1315 | if (pp->p_flag & SSYS) | |
1316 | continue; | |
b94a50ef SL |
1317 | db = ctod(pp->p_dsize), sb = up(db); |
1318 | used += sb; | |
1319 | waste += sb - db; | |
1320 | db = ctod(pp->p_ssize), sb = up(db); | |
1321 | used += sb; | |
1322 | waste += sb - db; | |
ceb84881 | 1323 | if ((pp->p_flag&SLOAD) == 0) |
13562341 | 1324 | used += ctod(vusize(pp)); |
ceb84881 | 1325 | } |
ceb84881 | 1326 | if (totflg) { |
b94a50ef SL |
1327 | #define btok(x) ((x) / (1024 / DEV_BSIZE)) |
1328 | printf("%3d/%3d 00k swap\n", | |
1329 | btok(used/100), btok((used+free)/100)); | |
ceb84881 BJ |
1330 | return; |
1331 | } | |
b94a50ef SL |
1332 | printf("%dk used (%dk text), %dk free, %dk wasted, %dk missing\n", |
1333 | btok(used), btok(tused), btok(free), btok(waste), | |
1334 | /* a dmmax/2 block goes to argmap */ | |
1335 | btok(nswap - dmmax/2 - (used + free))); | |
e79dc02e SL |
1336 | printf("avail: "); |
1337 | for (i = dmmax; i >= dmmin; i /= 2) { | |
1338 | j = 0; | |
1339 | while (rmalloc(swapmap, i) != 0) | |
1340 | j++; | |
b94a50ef | 1341 | if (j) printf("%d*%dk ", j, btok(i)); |
e79dc02e | 1342 | } |
b94a50ef SL |
1343 | free = 0; |
1344 | for (me = (struct mapent *)(swapmap+1); | |
1345 | me < (struct mapent *)&swapmap[nswapmap]; me++) | |
1346 | free += me->m_size; | |
1347 | printf("%d*1k\n", btok(free)); | |
ceb84881 BJ |
1348 | } |
1349 | ||
1350 | up(size) | |
1351 | register int size; | |
1352 | { | |
1353 | register int i, block; | |
1354 | ||
1355 | i = 0; | |
e79dc02e | 1356 | block = dmmin; |
ceb84881 BJ |
1357 | while (i < size) { |
1358 | i += block; | |
e79dc02e | 1359 | if (block < dmmax) |
ceb84881 BJ |
1360 | block *= 2; |
1361 | } | |
1362 | return (i); | |
1363 | } | |
1364 | ||
b94a50ef SL |
1365 | /* |
1366 | * Compute number of pages to be allocated to the u. area | |
1367 | * and data and stack area page tables, which are stored on the | |
1368 | * disk immediately after the u. area. | |
1369 | */ | |
ceb84881 | 1370 | vusize(p) |
b94a50ef | 1371 | register struct proc *p; |
ceb84881 BJ |
1372 | { |
1373 | register int tsz = p->p_tsize / NPTEPG; | |
1374 | ||
b94a50ef SL |
1375 | /* |
1376 | * We do not need page table space on the disk for page | |
1377 | * table pages wholly containing text. | |
1378 | */ | |
1379 | return (clrnd(UPAGES + | |
1380 | clrnd(ctopt(p->p_tsize+p->p_dsize+p->p_ssize+UPAGES)) - tsz)); | |
e79dc02e SL |
1381 | } |
1382 | ||
1383 | /* | |
1384 | * Allocate 'size' units from the given | |
1385 | * map. Return the base of the allocated space. | |
1386 | * In a map, the addresses are increasing and the | |
1387 | * list is terminated by a 0 size. | |
1388 | * | |
1389 | * Algorithm is first-fit. | |
1390 | * | |
1391 | * This routine knows about the interleaving of the swapmap | |
1392 | * and handles that. | |
1393 | */ | |
1394 | long | |
1395 | rmalloc(mp, size) | |
1396 | register struct map *mp; | |
1397 | long size; | |
1398 | { | |
1399 | register struct mapent *ep = (struct mapent *)(mp+1); | |
1400 | register int addr; | |
1401 | register struct mapent *bp; | |
1402 | swblk_t first, rest; | |
1403 | ||
1404 | if (size <= 0 || size > dmmax) | |
1405 | return (0); | |
1406 | /* | |
1407 | * Search for a piece of the resource map which has enough | |
1408 | * free space to accomodate the request. | |
1409 | */ | |
1410 | for (bp = ep; bp->m_size; bp++) { | |
1411 | if (bp->m_size >= size) { | |
1412 | /* | |
1413 | * If allocating from swapmap, | |
1414 | * then have to respect interleaving | |
1415 | * boundaries. | |
1416 | */ | |
1417 | if (nswdev > 1 && | |
1418 | (first = dmmax - bp->m_addr%dmmax) < bp->m_size) { | |
1419 | if (bp->m_size - first < size) | |
1420 | continue; | |
1421 | addr = bp->m_addr + first; | |
1422 | rest = bp->m_size - first - size; | |
1423 | bp->m_size = first; | |
1424 | if (rest) | |
1425 | rmfree(mp, rest, addr+size); | |
1426 | return (addr); | |
1427 | } | |
1428 | /* | |
1429 | * Allocate from the map. | |
1430 | * If there is no space left of the piece | |
1431 | * we allocated from, move the rest of | |
1432 | * the pieces to the left. | |
1433 | */ | |
1434 | addr = bp->m_addr; | |
1435 | bp->m_addr += size; | |
1436 | if ((bp->m_size -= size) == 0) { | |
1437 | do { | |
1438 | bp++; | |
1439 | (bp-1)->m_addr = bp->m_addr; | |
1440 | } while ((bp-1)->m_size = bp->m_size); | |
1441 | } | |
1442 | if (addr % CLSIZE) | |
1443 | return (0); | |
1444 | return (addr); | |
1445 | } | |
1446 | } | |
1447 | return (0); | |
1448 | } | |
1449 | ||
1450 | /* | |
1451 | * Free the previously allocated space at addr | |
1452 | * of size units into the specified map. | |
1453 | * Sort addr into map and combine on | |
1454 | * one or both ends if possible. | |
1455 | */ | |
1456 | rmfree(mp, size, addr) | |
1457 | struct map *mp; | |
1458 | long size, addr; | |
1459 | { | |
1460 | struct mapent *firstbp; | |
1461 | register struct mapent *bp; | |
1462 | register int t; | |
1463 | ||
1464 | /* | |
1465 | * Both address and size must be | |
1466 | * positive, or the protocol has broken down. | |
1467 | */ | |
1468 | if (addr <= 0 || size <= 0) | |
1469 | goto badrmfree; | |
1470 | /* | |
1471 | * Locate the piece of the map which starts after the | |
1472 | * returned space (or the end of the map). | |
1473 | */ | |
1474 | firstbp = bp = (struct mapent *)(mp + 1); | |
1475 | for (; bp->m_addr <= addr && bp->m_size != 0; bp++) | |
1476 | continue; | |
1477 | /* | |
1478 | * If the piece on the left abuts us, | |
1479 | * then we should combine with it. | |
1480 | */ | |
1481 | if (bp > firstbp && (bp-1)->m_addr+(bp-1)->m_size >= addr) { | |
1482 | /* | |
1483 | * Check no overlap (internal error). | |
1484 | */ | |
1485 | if ((bp-1)->m_addr+(bp-1)->m_size > addr) | |
1486 | goto badrmfree; | |
1487 | /* | |
1488 | * Add into piece on the left by increasing its size. | |
1489 | */ | |
1490 | (bp-1)->m_size += size; | |
1491 | /* | |
1492 | * If the combined piece abuts the piece on | |
1493 | * the right now, compress it in also, | |
1494 | * by shifting the remaining pieces of the map over. | |
1495 | */ | |
1496 | if (bp->m_addr && addr+size >= bp->m_addr) { | |
1497 | if (addr+size > bp->m_addr) | |
1498 | goto badrmfree; | |
1499 | (bp-1)->m_size += bp->m_size; | |
1500 | while (bp->m_size) { | |
1501 | bp++; | |
1502 | (bp-1)->m_addr = bp->m_addr; | |
1503 | (bp-1)->m_size = bp->m_size; | |
1504 | } | |
1505 | } | |
1506 | goto done; | |
1507 | } | |
1508 | /* | |
1509 | * Don't abut on the left, check for abutting on | |
1510 | * the right. | |
1511 | */ | |
1512 | if (addr+size >= bp->m_addr && bp->m_size) { | |
1513 | if (addr+size > bp->m_addr) | |
1514 | goto badrmfree; | |
1515 | bp->m_addr -= size; | |
1516 | bp->m_size += size; | |
1517 | goto done; | |
1518 | } | |
1519 | /* | |
1520 | * Don't abut at all. Make a new entry | |
1521 | * and check for map overflow. | |
1522 | */ | |
1523 | do { | |
1524 | t = bp->m_addr; | |
1525 | bp->m_addr = addr; | |
1526 | addr = t; | |
1527 | t = bp->m_size; | |
1528 | bp->m_size = size; | |
1529 | bp++; | |
1530 | } while (size = t); | |
1531 | /* | |
1532 | * Segment at bp is to be the delimiter; | |
1533 | * If there is not room for it | |
1534 | * then the table is too full | |
1535 | * and we must discard something. | |
1536 | */ | |
1537 | if (bp+1 > mp->m_limit) { | |
1538 | /* | |
1539 | * Back bp up to last available segment. | |
1540 | * which contains a segment already and must | |
1541 | * be made into the delimiter. | |
1542 | * Discard second to last entry, | |
1543 | * since it is presumably smaller than the last | |
1544 | * and move the last entry back one. | |
1545 | */ | |
1546 | bp--; | |
1547 | printf("%s: rmap ovflo, lost [%d,%d)\n", mp->m_name, | |
1548 | (bp-1)->m_addr, (bp-1)->m_addr+(bp-1)->m_size); | |
1549 | bp[-1] = bp[0]; | |
1550 | bp[0].m_size = bp[0].m_addr = 0; | |
1551 | } | |
1552 | done: | |
1553 | return; | |
1554 | badrmfree: | |
1555 | printf("bad rmfree\n"); | |
ceb84881 | 1556 | } |
d7985207 | 1557 | #endif /* NEWVM */ |
6102031f MT |
1558 | |
1559 | #include <varargs.h> | |
1560 | ||
1561 | error(va_alist) | |
1562 | va_dcl | |
1563 | { | |
1564 | char *fmt; | |
1565 | va_list ap; | |
1566 | extern errno; | |
1567 | ||
1568 | fprintf(stderr, "%s: ", Program); | |
1569 | va_start(ap); | |
1570 | fmt = va_arg(ap, char *); | |
1571 | (void) vfprintf(stderr, fmt, ap); | |
1572 | va_end(ap); | |
1573 | fprintf(stderr, "\n"); | |
1574 | } | |
1575 | ||
1576 | syserror(va_alist) | |
1577 | va_dcl | |
76ea98af | 1578 | { |
6102031f MT |
1579 | char *fmt; |
1580 | va_list ap; | |
1581 | extern errno; | |
1582 | ||
1583 | fprintf(stderr, "%s: ", Program); | |
1584 | va_start(ap); | |
1585 | fmt = va_arg(ap, char *); | |
1586 | (void) vfprintf(stderr, fmt, ap); | |
1587 | va_end(ap); | |
1588 | fprintf(stderr, ": %s\n", strerror(errno)); | |
76ea98af | 1589 | } |