print.c revision 1.51.2.1 1 /* $NetBSD: print.c,v 1.51.2.1 2000/06/22 15:03:44 minoura Exp $ */
2
3 /*
4 * Copyright (c) 2000 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Simon Burge.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright (c) 1990, 1993, 1994
41 * The Regents of the University of California. All rights reserved.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 */
71
72 #include <sys/cdefs.h>
73 #ifndef lint
74 #if 0
75 static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94";
76 #else
77 __RCSID("$NetBSD: print.c,v 1.51.2.1 2000/06/22 15:03:44 minoura Exp $");
78 #endif
79 #endif /* not lint */
80
81 #include <sys/param.h>
82 #include <sys/time.h>
83 #include <sys/resource.h>
84 #include <sys/proc.h>
85 #include <sys/stat.h>
86 #include <sys/ucred.h>
87 #include <sys/sysctl.h>
88
89 #include <vm/vm.h>
90
91 #include <err.h>
92 #include <kvm.h>
93 #include <math.h>
94 #include <nlist.h>
95 #include <pwd.h>
96 #include <stddef.h>
97 #include <stdio.h>
98 #include <stdlib.h>
99 #include <string.h>
100 #include <time.h>
101 #include <tzfile.h>
102 #include <unistd.h>
103
104 #include "ps.h"
105
106 static char *cmdpart __P((char *));
107 static void printval __P((void *, VAR *, int));
108 static int titlecmp __P((char *, char **));
109
110 static void doubleprintorsetwidth __P((VAR *, double, int, int));
111 static void intprintorsetwidth __P((VAR *, int, int));
112 static void strprintorsetwidth __P((VAR *, const char *, int));
113
114 #define min(a,b) ((a) <= (b) ? (a) : (b))
115 #define max(a,b) ((a) >= (b) ? (a) : (b))
116
117 static char *
118 cmdpart(arg0)
119 char *arg0;
120 {
121 char *cp;
122
123 return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0);
124 }
125
126 void
127 printheader()
128 {
129 int len;
130 VAR *v;
131 struct varent *vent;
132 static int firsttime = 1;
133
134 for (vent = vhead; vent; vent = vent->next) {
135 v = vent->var;
136 if (firsttime) {
137 len = strlen(v->header);
138 if (len > v->width)
139 v->width = len;
140 totwidth += v->width + 1; /* +1 for space */
141 }
142 if (v->flag & LJUST) {
143 if (vent->next == NULL) /* last one */
144 (void)printf("%s", v->header);
145 else
146 (void)printf("%-*s", v->width,
147 v->header);
148 } else
149 (void)printf("%*s", v->width, v->header);
150 if (vent->next != NULL)
151 (void)putchar(' ');
152 }
153 (void)putchar('\n');
154 if (firsttime) {
155 firsttime = 0;
156 totwidth--; /* take off last space */
157 }
158 }
159
160 static int
161 titlecmp(name, argv)
162 char *name;
163 char **argv;
164 {
165 char *title;
166 int namelen;
167
168 if (argv == 0 || argv[0] == 0)
169 return (1);
170
171 title = cmdpart(argv[0]);
172
173 if (!strcmp(name, title))
174 return (0);
175
176 if (title[0] == '-' && !strcmp(name, title+1))
177 return (0);
178
179 namelen = strlen(name);
180
181 if (argv[1] == 0 &&
182 !strncmp(name, title, namelen) &&
183 title[namelen + 0] == ':' &&
184 title[namelen + 1] == ' ')
185 return (0);
186
187 return (1);
188 }
189
190 static void
191 doubleprintorsetwidth(v, val, prec, mode)
192 VAR *v;
193 double val;
194 int prec;
195 int mode;
196 {
197 int fmtlen;
198
199 if (mode == WIDTHMODE) {
200 if (val < 0.0 && val < v->longestnd) {
201 fmtlen = (int)log10(-val) + prec + 2;
202 v->longestnd = val;
203 if (fmtlen > v->width)
204 v->width = fmtlen;
205 } else if (val > 0.0 && val > v->longestpd) {
206 fmtlen = (int)log10(val) + prec + 1;
207 v->longestpd = val;
208 if (fmtlen > v->width)
209 v->width = fmtlen;
210 }
211 } else {
212 printf("%*.*f", v->width, prec, val);
213 }
214 }
215
216 static void
217 intprintorsetwidth(v, val, mode)
218 VAR *v;
219 int val;
220 int mode;
221 {
222 int fmtlen;
223
224 if (mode == WIDTHMODE) {
225 if (val < 0 && val < v->longestn) {
226 fmtlen = (int)log10((double)-val) + 2;
227 v->longestn = val;
228 if (fmtlen > v->width)
229 v->width = fmtlen;
230 } else if (val > 0 && val > v->longestp) {
231 fmtlen = (int)log10((double)val) + 1;
232 v->longestp = val;
233 if (fmtlen > v->width)
234 v->width = fmtlen;
235 }
236 } else
237 printf("%*d", v->width, val);
238 }
239
240 static void
241 strprintorsetwidth(v, str, mode)
242 VAR *v;
243 const char *str;
244 {
245 int len;
246
247 if (mode == WIDTHMODE) {
248 len = strlen(str);
249 if (len > v->width)
250 v->width = len;
251 } else {
252 if (v->flag & LJUST)
253 printf("%-*.*s", v->width, v->width, str);
254 else
255 printf("%*.*s", v->width, v->width, str);
256 }
257 }
258
259 void
260 command(ki, ve, mode)
261 struct kinfo_proc2 *ki;
262 VARENT *ve;
263 int mode;
264 {
265 VAR *v;
266 int left;
267 char **argv, **p, *name;
268
269 if (mode == WIDTHMODE)
270 return;
271
272 v = ve->var;
273 if (ve->next != NULL || termwidth != UNLIMITED) {
274 if (ve->next == NULL) {
275 left = termwidth - (totwidth - v->width);
276 if (left < 1) /* already wrapped, just use std width */
277 left = v->width;
278 } else
279 left = v->width;
280 } else
281 left = -1;
282 if (needenv && kd) {
283 argv = kvm_getenvv2(kd, ki, termwidth);
284 if ((p = argv) != NULL) {
285 while (*p) {
286 fmt_puts(*p, &left);
287 p++;
288 fmt_putc(' ', &left);
289 }
290 }
291 }
292 if (needcomm) {
293 name = ki->p_comm;
294 if (!commandonly) {
295 argv = NULL;
296 if (!use_procfs)
297 argv = kvm_getargv2(kd, ki, termwidth);
298 else
299 argv = procfs_getargv(ki, termwidth);
300 if ((p = argv) != NULL) {
301 while (*p) {
302 fmt_puts(*p, &left);
303 p++;
304 fmt_putc(' ', &left);
305 }
306 }
307 if (titlecmp(name, argv)) {
308 fmt_putc('(', &left);
309 fmt_puts(name, &left);
310 fmt_putc(')', &left);
311 }
312 if (use_procfs && argv) {
313 free(argv[0]);
314 free(argv);
315 }
316 } else {
317 fmt_puts(name, &left);
318 }
319 }
320 if (ve->next && left > 0)
321 printf("%*s", left, "");
322 }
323
324 void
325 ucomm(k, ve, mode)
326 struct kinfo_proc2 *k;
327 VARENT *ve;
328 int mode;
329 {
330 VAR *v;
331
332 v = ve->var;
333 strprintorsetwidth(v, k->p_comm, mode);
334 }
335
336 void
337 logname(k, ve, mode)
338 struct kinfo_proc2 *k;
339 VARENT *ve;
340 int mode;
341 {
342 VAR *v;
343
344 v = ve->var;
345 strprintorsetwidth(v, k->p_login, mode);
346 }
347
348 void
349 state(k, ve, mode)
350 struct kinfo_proc2 *k;
351 VARENT *ve;
352 int mode;
353 {
354 int flag, is_zombie;
355 char *cp;
356 VAR *v;
357 char buf[16];
358
359 is_zombie = 0;
360 v = ve->var;
361 flag = k->p_flag;
362 cp = buf;
363
364 switch (k->p_stat) {
365
366 case SSTOP:
367 *cp = 'T';
368 break;
369
370 case SSLEEP:
371 if (flag & P_SINTR) /* interuptable (long) */
372 *cp = k->p_slptime >= MAXSLP ? 'I' : 'S';
373 else
374 *cp = 'D';
375 break;
376
377 case SRUN:
378 case SIDL:
379 case SONPROC:
380 *cp = 'R';
381 break;
382
383 case SZOMB:
384 case SDEAD:
385 *cp = 'Z';
386 is_zombie = 1;
387 break;
388
389 default:
390 *cp = '?';
391 }
392 cp++;
393 if (flag & P_INMEM) {
394 } else
395 *cp++ = 'W';
396 if (k->p_nice < NZERO)
397 *cp++ = '<';
398 else if (k->p_nice > NZERO)
399 *cp++ = 'N';
400 if (flag & P_TRACED)
401 *cp++ = 'X';
402 if (flag & P_WEXIT && !is_zombie)
403 *cp++ = 'E';
404 if (flag & P_PPWAIT)
405 *cp++ = 'V';
406 if ((flag & P_SYSTEM) || k->p_holdcnt)
407 *cp++ = 'L';
408 if (k->p_eflag & EPROC_SLEADER)
409 *cp++ = 's';
410 if ((flag & P_CONTROLT) && k->p__pgid == k->p_tpgid)
411 *cp++ = '+';
412 *cp = '\0';
413 strprintorsetwidth(v, buf, mode);
414 }
415
416 void
417 pnice(k, ve, mode)
418 struct kinfo_proc2 *k;
419 VARENT *ve;
420 int mode;
421 {
422 VAR *v;
423
424 v = ve->var;
425 intprintorsetwidth(v, k->p_nice - NZERO, mode);
426 }
427
428 void
429 pri(k, ve, mode)
430 struct kinfo_proc2 *k;
431 VARENT *ve;
432 int mode;
433 {
434 VAR *v;
435
436 v = ve->var;
437 intprintorsetwidth(v, k->p_priority - PZERO, mode);
438 }
439
440 void
441 uname(k, ve, mode)
442 struct kinfo_proc2 *k;
443 VARENT *ve;
444 int mode;
445 {
446 VAR *v;
447
448 v = ve->var;
449 strprintorsetwidth(v, user_from_uid(k->p_uid, 0), mode);
450 }
451
452 void
453 runame(k, ve, mode)
454 struct kinfo_proc2 *k;
455 VARENT *ve;
456 int mode;
457 {
458 VAR *v;
459
460 v = ve->var;
461 strprintorsetwidth(v, user_from_uid(k->p_ruid, 0), mode);
462 }
463
464 void
465 tdev(k, ve, mode)
466 struct kinfo_proc2 *k;
467 VARENT *ve;
468 int mode;
469 {
470 VAR *v;
471 dev_t dev;
472 char buff[16];
473
474 v = ve->var;
475 dev = k->p_tdev;
476 if (dev == NODEV) {
477 /*
478 * Minimum width is width of header - we don't
479 * need to check it every time.
480 */
481 if (mode == PRINTMODE)
482 (void)printf("%*s", v->width, "??");
483 } else {
484 (void)snprintf(buff, sizeof(buff),
485 "%d/%d", major(dev), minor(dev));
486 strprintorsetwidth(v, buff, mode);
487 }
488 }
489
490 void
491 tname(k, ve, mode)
492 struct kinfo_proc2 *k;
493 VARENT *ve;
494 int mode;
495 {
496 VAR *v;
497 dev_t dev;
498 const char *ttname;
499 int noctty;
500
501 v = ve->var;
502 dev = k->p_tdev;
503 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) {
504 /*
505 * Minimum width is width of header - we don't
506 * need to check it every time.
507 */
508 if (mode == PRINTMODE)
509 (void)printf("%-*s", v->width, "??");
510 } else {
511 if (strncmp(ttname, "tty", 3) == 0 ||
512 strncmp(ttname, "dty", 3) == 0)
513 ttname += 3;
514 noctty = !(k->p_eflag & EPROC_CTTY) ? 1 : 0;
515 if (mode == WIDTHMODE) {
516 int fmtlen;
517
518 fmtlen = strlen(ttname) + noctty;
519 if (v->width < fmtlen)
520 v->width = fmtlen;
521 } else {
522 if (noctty)
523 printf("%-*s-", v->width - 1, ttname);
524 else
525 printf("%-*s", v->width, ttname);
526 }
527 }
528 }
529
530 void
531 longtname(k, ve, mode)
532 struct kinfo_proc2 *k;
533 VARENT *ve;
534 int mode;
535 {
536 VAR *v;
537 dev_t dev;
538 const char *ttname;
539
540 v = ve->var;
541 dev = k->p_tdev;
542 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL) {
543 /*
544 * Minimum width is width of header - we don't
545 * need to check it every time.
546 */
547 if (mode == PRINTMODE)
548 (void)printf("%-*s", v->width, "??");
549 }
550 else {
551 strprintorsetwidth(v, ttname, mode);
552 }
553 }
554
555 void
556 started(k, ve, mode)
557 struct kinfo_proc2 *k;
558 VARENT *ve;
559 int mode;
560 {
561 VAR *v;
562 static time_t now;
563 time_t startt;
564 struct tm *tp;
565 char buf[100], *cp;
566
567 /*
568 * XXX: The maximum width of this field is the same as the header
569 * "STARTED" for locales that have 3 letter abbreviated month
570 * names and 2 letter am/pm descriptions.
571 */
572 if (mode == WIDTHMODE)
573 return;
574
575 v = ve->var;
576 if (!k->p_uvalid) {
577 if (mode == PRINTMODE)
578 (void)printf("%*s", v->width, "-");
579 return;
580 }
581
582 startt = k->p_ustart_sec;
583 tp = localtime(&startt);
584 if (!now)
585 (void)time(&now);
586 if (now - k->p_ustart_sec < SECSPERDAY)
587 /* I *hate* SCCS... */
588 (void)strftime(buf, sizeof(buf) - 1, "%l:%" "M%p", tp);
589 else if (now - k->p_ustart_sec < DAYSPERWEEK * SECSPERDAY)
590 /* I *hate* SCCS... */
591 (void)strftime(buf, sizeof(buf) - 1, "%a%" "I%p", tp);
592 else
593 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
594 /* %e and %l can start with a space. */
595 cp = buf;
596 if (*cp == ' ')
597 cp++;
598 strprintorsetwidth(v, cp, mode);
599 }
600
601 void
602 lstarted(k, ve, mode)
603 struct kinfo_proc2 *k;
604 VARENT *ve;
605 int mode;
606 {
607 VAR *v;
608 time_t startt;
609 char buf[100];
610
611 v = ve->var;
612 if (!k->p_uvalid) {
613 /*
614 * Minimum width is less than header - we don't
615 * need to check it every time.
616 */
617 if (mode == PRINTMODE)
618 (void)printf("%*s", v->width, "-");
619 return;
620 }
621 startt = k->p_ustart_sec;
622
623 /* assume all times are the same length */
624 if (mode != WIDTHMODE || v->width == 0) {
625 (void)strftime(buf, sizeof(buf) -1, "%c",
626 localtime(&startt));
627 strprintorsetwidth(v, buf, mode);
628 }
629 }
630
631 void
632 wchan(k, ve, mode)
633 struct kinfo_proc2 *k;
634 VARENT *ve;
635 int mode;
636 {
637 VAR *v;
638 char *buf;
639
640 v = ve->var;
641 if (k->p_wchan) {
642 if (k->p_wmesg) {
643 strprintorsetwidth(v, k->p_wmesg, mode);
644 v->width = min(v->width, WMESGLEN);
645 } else {
646 (void)asprintf(&buf, "%-*llx", v->width,
647 (long long)k->p_wchan);
648 if (buf == NULL)
649 err(1, "%s", "");
650 strprintorsetwidth(v, buf, mode);
651 v->width = min(v->width, WMESGLEN);
652 free(buf);
653 }
654 } else {
655 if (mode == PRINTMODE)
656 (void)printf("%-*s", v->width, "-");
657 }
658 }
659
660 #define pgtok(a) (((a)*getpagesize())/1024)
661
662 void
663 vsize(k, ve, mode)
664 struct kinfo_proc2 *k;
665 VARENT *ve;
666 int mode;
667 {
668 VAR *v;
669
670 v = ve->var;
671 intprintorsetwidth(v,
672 pgtok(k->p_vm_dsize + k->p_vm_ssize + k->p_vm_tsize), mode);
673 }
674
675 void
676 rssize(k, ve, mode)
677 struct kinfo_proc2 *k;
678 VARENT *ve;
679 int mode;
680 {
681 VAR *v;
682
683 v = ve->var;
684 /* XXX don't have info about shared */
685 intprintorsetwidth(v, pgtok(k->p_vm_rssize), mode);
686 }
687
688 void
689 p_rssize(k, ve, mode) /* doesn't account for text */
690 struct kinfo_proc2 *k;
691 VARENT *ve;
692 int mode;
693 {
694 VAR *v;
695
696 v = ve->var;
697 intprintorsetwidth(v, pgtok(k->p_vm_rssize), mode);
698 }
699
700 void
701 cputime(k, ve, mode)
702 struct kinfo_proc2 *k;
703 VARENT *ve;
704 int mode;
705 {
706 VAR *v;
707 long secs;
708 long psecs; /* "parts" of a second. first micro, then centi */
709 int fmtlen;
710
711 v = ve->var;
712 if (P_ZOMBIE(k) || k->p_uvalid == 0) {
713 secs = 0;
714 psecs = 0;
715 } else {
716 /*
717 * This counts time spent handling interrupts. We could
718 * fix this, but it is not 100% trivial (and interrupt
719 * time fractions only work on the sparc anyway). XXX
720 */
721 secs = k->p_rtime_sec;
722 psecs = k->p_rtime_usec;
723 if (sumrusage) {
724 secs += k->p_uctime_sec;
725 psecs += k->p_uctime_usec;
726 }
727 /*
728 * round and scale to 100's
729 */
730 psecs = (psecs + 5000) / 10000;
731 secs += psecs / 100;
732 psecs = psecs % 100;
733 }
734 if (mode == WIDTHMODE) {
735 /*
736 * Ugg, this is the only field where a value of 0 longer
737 * than the column title, and log10(0) isn't good enough.
738 * Use SECSPERMIN, because secs is divided by that when
739 * passed to log10().
740 */
741 if (secs == 0 && v->longestp == 0)
742 secs = SECSPERMIN;
743 if (secs > v->longestp) {
744 /* "+6" for the "%02ld.%02ld" in the printf() below */
745 fmtlen = (int)log10((double)secs / SECSPERMIN) + 1 + 6;
746 v->longestp = secs;
747 if (fmtlen > v->width)
748 v->width = fmtlen;
749 }
750 } else {
751 printf("%*ld:%02ld.%02ld", v->width - 6, secs / SECSPERMIN,
752 secs % SECSPERMIN, psecs);
753 }
754 }
755
756 double
757 getpcpu(k)
758 struct kinfo_proc2 *k;
759 {
760 static int failure;
761
762 if (!nlistread)
763 failure = (kd) ? donlist() : 1;
764 if (failure)
765 return (0.0);
766
767 #define fxtofl(fixpt) ((double)(fixpt) / fscale)
768
769 /* XXX - I don't like this */
770 if (k->p_swtime == 0 || (k->p_flag & P_INMEM) == 0 ||
771 k->p_stat == SZOMB || k->p_stat == SDEAD)
772 return (0.0);
773 if (rawcpu)
774 return (100.0 * fxtofl(k->p_pctcpu));
775 return (100.0 * fxtofl(k->p_pctcpu) /
776 (1.0 - exp(k->p_swtime * log(ccpu))));
777 }
778
779 void
780 pcpu(k, ve, mode)
781 struct kinfo_proc2 *k;
782 VARENT *ve;
783 int mode;
784 {
785 VAR *v;
786
787 v = ve->var;
788 doubleprintorsetwidth(v, getpcpu(k), 1, mode);
789 }
790
791 double
792 getpmem(k)
793 struct kinfo_proc2 *k;
794 {
795 static int failure;
796 double fracmem;
797 int szptudot;
798
799 if (!nlistread)
800 failure = (kd) ? donlist() : 1;
801 if (failure)
802 return (0.0);
803
804 if ((k->p_flag & P_INMEM) == 0)
805 return (0.0);
806 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
807 szptudot = USPACE/getpagesize();
808 /* XXX don't have info about shared */
809 fracmem = ((float)k->p_vm_rssize + szptudot)/mempages;
810 return (100.0 * fracmem);
811 }
812
813 void
814 pmem(k, ve, mode)
815 struct kinfo_proc2 *k;
816 VARENT *ve;
817 int mode;
818 {
819 VAR *v;
820
821 v = ve->var;
822 doubleprintorsetwidth(v, getpmem(k), 1, mode);
823 }
824
825 void
826 pagein(k, ve, mode)
827 struct kinfo_proc2 *k;
828 VARENT *ve;
829 int mode;
830 {
831 VAR *v;
832
833 v = ve->var;
834 intprintorsetwidth(v, k->p_uvalid ? k->p_uru_majflt : 0, mode);
835 }
836
837 void
838 maxrss(k, ve, mode)
839 struct kinfo_proc2 *k;
840 VARENT *ve;
841 int mode;
842 {
843 VAR *v;
844
845 v = ve->var;
846 /* No need to check width! */
847 if (mode == PRINTMODE)
848 (void)printf("%*s", v->width, "-");
849 }
850
851 void
852 tsize(k, ve, mode)
853 struct kinfo_proc2 *k;
854 VARENT *ve;
855 int mode;
856 {
857 VAR *v;
858
859 v = ve->var;
860 intprintorsetwidth(v, pgtok(k->p_vm_tsize), mode);
861 }
862
863 /*
864 * Generic output routines. Print fields from various prototype
865 * structures.
866 */
867 static void
868 printval(bp, v, mode)
869 void *bp;
870 VAR *v;
871 int mode;
872 {
873 static char ofmt[32] = "%";
874 int width, vok, fmtlen;
875 char *fcp, *cp, *obuf;
876 enum type type;
877 long long val;
878 unsigned long long uval;
879
880 /*
881 * Note that the "INF127" check is nonsensical for types
882 * that are or can be signed.
883 */
884 #define GET(type) (*(type *)bp)
885 #define CHK_INF127(n) (((n) > 127) && (v->flag & INF127) ? 127 : (n))
886
887 #define VSIGN 1
888 #define VUNSIGN 2
889 #define VPTR 3
890
891 if (mode == WIDTHMODE) {
892 vok = 0;
893 switch (v->type) {
894 case CHAR:
895 val = GET(char);
896 vok = VSIGN;
897 break;
898 case UCHAR:
899 uval = CHK_INF127(GET(u_char));
900 vok = VUNSIGN;
901 break;
902 case SHORT:
903 val = GET(short);
904 vok = VSIGN;
905 break;
906 case USHORT:
907 uval = CHK_INF127(GET(u_short));
908 vok = VUNSIGN;
909 break;
910 case INT32:
911 val = GET(int32_t);
912 vok = VSIGN;
913 break;
914 case INT:
915 val = GET(int);
916 vok = VSIGN;
917 break;
918 case UINT:
919 case UINT32:
920 uval = CHK_INF127(GET(u_int));
921 vok = VUNSIGN;
922 break;
923 case LONG:
924 val = GET(long);
925 vok = VSIGN;
926 break;
927 case ULONG:
928 uval = CHK_INF127(GET(u_long));
929 vok = VUNSIGN;
930 break;
931 case KPTR:
932 uval = GET(u_long);
933 vok = VPTR;
934 break;
935 case KPTR24:
936 uval = GET(u_long) & 0xffffff;
937 vok = VPTR;
938 break;
939 default:
940 /* nothing... */;
941 }
942 switch (vok) {
943 case VSIGN:
944 if (val < 0 && val < v->longestn) {
945 fmtlen = (int)log10((double)-val) + 2;
946 v->longestn = val;
947 if (fmtlen > v->width)
948 v->width = fmtlen;
949 } else if (val > 0 && val > v->longestp) {
950 fmtlen = (int)log10((double)val) + 1;
951 v->longestp = val;
952 if (fmtlen > v->width)
953 v->width = fmtlen;
954 }
955 return;
956 case VUNSIGN:
957 if (uval > v->longestu) {
958 fmtlen = (int)log10((double)uval) + 1;
959 v->longestu = uval;
960 v->width = fmtlen;
961 }
962 return;
963 case VPTR:
964 fmtlen = 0;
965 while (uval > 0) {
966 uval >>= 4;
967 fmtlen++;
968 }
969 if (fmtlen > v->width)
970 v->width = fmtlen;
971 return;
972 }
973 }
974
975 width = v->width;
976 cp = ofmt + 1;
977 fcp = v->fmt;
978 if (v->flag & LJUST)
979 *cp++ = '-';
980 *cp++ = '*';
981 while ((*cp++ = *fcp++) != '\0')
982 continue;
983
984 switch (v->type) {
985 case INT32:
986 if (sizeof(int32_t) == sizeof(int))
987 type = INT;
988 else if (sizeof(int32_t) == sizeof(long))
989 type = LONG;
990 else
991 errx(1, "unknown conversion for type %d", v->type);
992 break;
993 case UINT32:
994 if (sizeof(u_int32_t) == sizeof(u_int))
995 type = UINT;
996 else if (sizeof(u_int32_t) == sizeof(u_long))
997 type = ULONG;
998 else
999 errx(1, "unknown conversion for type %d", v->type);
1000 break;
1001 default:
1002 type = v->type;
1003 break;
1004 }
1005
1006 switch (type) {
1007 case CHAR:
1008 (void)printf(ofmt, width, GET(char));
1009 return;
1010 case UCHAR:
1011 (void)printf(ofmt, width, CHK_INF127(GET(u_char)));
1012 return;
1013 case SHORT:
1014 (void)printf(ofmt, width, GET(short));
1015 return;
1016 case USHORT:
1017 (void)printf(ofmt, width, CHK_INF127(GET(u_short)));
1018 return;
1019 case INT:
1020 (void)printf(ofmt, width, GET(int));
1021 return;
1022 case UINT:
1023 (void)printf(ofmt, width, CHK_INF127(GET(u_int)));
1024 return;
1025 case LONG:
1026 (void)printf(ofmt, width, GET(long));
1027 return;
1028 case ULONG:
1029 (void)printf(ofmt, width, CHK_INF127(GET(u_long)));
1030 return;
1031 case KPTR:
1032 (void)printf(ofmt, width, GET(u_long));
1033 return;
1034 case KPTR24:
1035 (void)printf(ofmt, width, GET(u_long) & 0xffffff);
1036 return;
1037 case SIGLIST:
1038 {
1039 sigset_t *s = (sigset_t *)(void *)bp;
1040 size_t i;
1041 #define SIGSETSIZE (sizeof(s->__bits) / sizeof(s->__bits[0]))
1042 char buf[SIGSETSIZE * 8 + 1];
1043
1044 for (i = 0; i < SIGSETSIZE; i++)
1045 (void)snprintf(&buf[i * 8], 9, "%.8x",
1046 s->__bits[(SIGSETSIZE - 1) - i]);
1047
1048 /* Skip leading zeroes */
1049 for (i = 0; buf[i]; i++)
1050 if (buf[i] != '0')
1051 break;
1052
1053 if (buf[i] == '\0')
1054 i--;
1055 (void)asprintf(&obuf, ofmt, width, &buf[i]);
1056 }
1057 break;
1058 default:
1059 errx(1, "unknown type %d", v->type);
1060 }
1061 if (obuf == NULL)
1062 err(1, "%s", "");
1063 if (mode == WIDTHMODE) {
1064 /* Skip leading spaces. */
1065 cp = strrchr(obuf, ' ');
1066 if (cp == NULL)
1067 cp = obuf;
1068 else
1069 cp++; /* skip last space */
1070 }
1071 else
1072 cp = obuf;
1073 strprintorsetwidth(v, cp, mode);
1074 free(obuf);
1075 #undef GET
1076 #undef CHK_INF127
1077 }
1078
1079 void
1080 pvar(k, ve, mode)
1081 struct kinfo_proc2 *k;
1082 VARENT *ve;
1083 int mode;
1084 {
1085 VAR *v;
1086
1087 v = ve->var;
1088 printval((char *)k + v->off, v, mode);
1089 }
1090