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