print.c revision 1.30 1 /* $NetBSD: print.c,v 1.30 1996/10/02 18:07:25 ws 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 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94";
39 #else
40 static char rcsid[] = "$NetBSD: print.c,v 1.30 1996/10/02 18:07:25 ws Exp $";
41 #endif
42 #endif /* not lint */
43
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <sys/resource.h>
47 #include <sys/proc.h>
48 #include <sys/stat.h>
49
50 #ifdef P_PPWAIT
51 #define NEWVM
52 #endif
53
54 #ifdef NEWVM
55 #include <sys/ucred.h>
56 #include <sys/sysctl.h>
57 #include <vm/vm.h>
58 #else
59 #include <machine/pte.h>
60 #include <sys/vmparam.h>
61 #include <sys/vm.h>
62 #endif
63
64 #include <err.h>
65 #include <kvm.h>
66 #include <math.h>
67 #include <nlist.h>
68 #include <pwd.h>
69 #include <stddef.h>
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <string.h>
73 #include <tzfile.h>
74 #include <unistd.h>
75
76 #include "ps.h"
77
78 extern kvm_t *kd;
79 extern int needenv, needcomm, commandonly;
80
81 static char *cmdpart __P((char *));
82
83 static char *
84 cmdpart(arg0)
85 char *arg0;
86 {
87 char *cp;
88
89 return ((cp = strrchr(arg0, '/')) != NULL ? cp + 1 : arg0);
90 }
91
92 void
93 printheader()
94 {
95 VAR *v;
96 struct varent *vent;
97
98 for (vent = vhead; vent; vent = vent->next) {
99 v = vent->var;
100 if (v->flag & LJUST) {
101 if (vent->next == NULL) /* last one */
102 (void)printf("%s", v->header);
103 else
104 (void)printf("%-*s", v->width, v->header);
105 } else
106 (void)printf("%*s", v->width, v->header);
107 if (vent->next != NULL)
108 (void)putchar(' ');
109 }
110 (void)putchar('\n');
111 }
112
113 void
114 command(ki, ve)
115 KINFO *ki;
116 VARENT *ve;
117 {
118 VAR *v;
119 int left;
120 char **argv, **p;
121
122 v = ve->var;
123 if (ve->next != NULL || termwidth != UNLIMITED) {
124 if (ve->next == NULL) {
125 left = termwidth - (totwidth - v->width);
126 if (left < 1) /* already wrapped, just use std width */
127 left = v->width;
128 } else
129 left = v->width;
130 } else
131 left = -1;
132 if (needenv) {
133 argv = kvm_getenvv(kd, ki->ki_p, termwidth);
134 if (p = argv) {
135 while (*p) {
136 fmt_puts(*p, &left);
137 p++;
138 fmt_putc(' ', &left);
139 }
140 }
141 }
142 if (needcomm) {
143 if (!commandonly) {
144 argv = kvm_getargv(kd, ki->ki_p, termwidth);
145 if (p = argv) {
146 while (*p) {
147 fmt_puts(*p, &left);
148 p++;
149 fmt_putc(' ', &left);
150 }
151 }
152 if (argv == 0 || argv[0] == 0 ||
153 strcmp(cmdpart(argv[0]), KI_PROC(ki)->p_comm)) {
154 fmt_putc('(', &left);
155 fmt_puts(KI_PROC(ki)->p_comm, &left);
156 fmt_putc(')', &left);
157 }
158 } else {
159 fmt_puts(KI_PROC(ki)->p_comm, &left);
160 }
161 }
162 if (ve->next && left > 0)
163 printf("%*s", left, "");
164 }
165
166 void
167 ucomm(k, ve)
168 KINFO *k;
169 VARENT *ve;
170 {
171 VAR *v;
172
173 v = ve->var;
174 (void)printf("%-*s", v->width, KI_PROC(k)->p_comm);
175 }
176
177 void
178 logname(k, ve)
179 KINFO *k;
180 VARENT *ve;
181 {
182 VAR *v;
183
184 v = ve->var;
185 #ifndef NEWVM
186 (void)printf("%-*s", v->width, KI_PROC(k)->p_logname);
187 #else
188 (void)printf("%-*s", v->width, KI_EPROC(k)->e_login);
189 #endif
190 }
191
192 void
193 state(k, ve)
194 KINFO *k;
195 VARENT *ve;
196 {
197 struct proc *p;
198 int flag;
199 char *cp;
200 VAR *v;
201 char buf[16];
202
203 v = ve->var;
204 p = KI_PROC(k);
205 flag = p->p_flag;
206 cp = buf;
207
208 switch (p->p_stat) {
209
210 case SSTOP:
211 *cp = 'T';
212 break;
213
214 case SSLEEP:
215 if (flag & P_SINTR) /* interuptable (long) */
216 *cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
217 else
218 *cp = 'D';
219 break;
220
221 case SRUN:
222 case SIDL:
223 *cp = 'R';
224 break;
225
226 case SZOMB:
227 *cp = 'Z';
228 break;
229
230 default:
231 *cp = '?';
232 }
233 cp++;
234 if (flag & P_INMEM) {
235 #ifndef NEWVM
236 if (p->p_rssize > p->p_maxrss)
237 *cp++ = '>';
238 #endif
239 } else
240 *cp++ = 'W';
241 if (p->p_nice < NZERO)
242 *cp++ = '<';
243 else if (p->p_nice > NZERO)
244 *cp++ = 'N';
245 #ifndef NEWVM
246 if (flag & SUANOM)
247 *cp++ = 'A';
248 else if (flag & SSEQL)
249 *cp++ = 'S';
250 #endif
251 if (flag & P_TRACED)
252 *cp++ = 'X';
253 if (flag & P_WEXIT && p->p_stat != SZOMB)
254 *cp++ = 'E';
255 #ifdef NEWVM
256 if (flag & P_PPWAIT)
257 #else
258 if (flag & SVFORK)
259 #endif
260 *cp++ = 'V';
261 #ifdef NEWVM
262 if ((flag & P_SYSTEM) || p->p_holdcnt)
263 #else
264 if (flag & (SSYS|SLOCK|SULOCK|SKEEP|SPHYSIO))
265 #endif
266 *cp++ = 'L';
267 if (KI_EPROC(k)->e_flag & EPROC_SLEADER)
268 *cp++ = 's';
269 if ((flag & P_CONTROLT) && KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid)
270 *cp++ = '+';
271 *cp = '\0';
272 (void)printf("%-*s", v->width, buf);
273 }
274
275 void
276 pnice(k, ve)
277 KINFO *k;
278 VARENT *ve;
279 {
280 VAR *v;
281
282 v = ve->var;
283 (void)printf("%*d", v->width, KI_PROC(k)->p_nice - NZERO);
284 }
285
286 void
287 pri(k, ve)
288 KINFO *k;
289 VARENT *ve;
290 {
291 VAR *v;
292
293 v = ve->var;
294 (void)printf("%*d", v->width, KI_PROC(k)->p_priority - PZERO);
295 }
296
297 void
298 uname(k, ve)
299 KINFO *k;
300 VARENT *ve;
301 {
302 VAR *v;
303
304 v = ve->var;
305 #ifndef NEWVM
306 (void)printf("%-*s",
307 (int)v->width, user_from_uid(KI_PROC(k)->p_uid, 0));
308 #else
309 (void)printf("%-*s",
310 (int)v->width, user_from_uid(KI_EPROC(k)->e_ucred.cr_uid, 0));
311 #endif
312 }
313
314 void
315 runame(k, ve)
316 KINFO *k;
317 VARENT *ve;
318 {
319 VAR *v;
320
321 v = ve->var;
322 #ifndef NEWVM
323 (void)printf("%-*s",
324 (int)v->width, user_from_uid(KI_PROC(k)->p_ruid, 0));
325 #else
326 (void)printf("%-*s",
327 (int)v->width, user_from_uid(KI_EPROC(k)->e_pcred.p_ruid, 0));
328 #endif
329 }
330
331 void
332 tdev(k, ve)
333 KINFO *k;
334 VARENT *ve;
335 {
336 VAR *v;
337 dev_t dev;
338 char buff[16];
339
340 v = ve->var;
341 dev = KI_EPROC(k)->e_tdev;
342 if (dev == NODEV)
343 (void)printf("%*s", v->width, "??");
344 else {
345 (void)snprintf(buff, sizeof(buff),
346 "%d/%d", major(dev), minor(dev));
347 (void)printf("%*s", v->width, buff);
348 }
349 }
350
351 void
352 tname(k, ve)
353 KINFO *k;
354 VARENT *ve;
355 {
356 VAR *v;
357 dev_t dev;
358 char *ttname;
359
360 v = ve->var;
361 dev = KI_EPROC(k)->e_tdev;
362 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
363 (void)printf("%-*s", v->width, "??");
364 else {
365 if (strncmp(ttname, "tty", 3) == 0)
366 ttname += 3;
367 (void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
368 KI_EPROC(k)->e_flag & EPROC_CTTY ? ' ' : '-');
369 }
370 }
371
372 void
373 longtname(k, ve)
374 KINFO *k;
375 VARENT *ve;
376 {
377 VAR *v;
378 dev_t dev;
379 char *ttname;
380
381 v = ve->var;
382 dev = KI_EPROC(k)->e_tdev;
383 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
384 (void)printf("%-*s", v->width, "??");
385 else
386 (void)printf("%-*s", v->width, ttname);
387 }
388
389 void
390 started(k, ve)
391 KINFO *k;
392 VARENT *ve;
393 {
394 VAR *v;
395 static time_t now;
396 time_t startt;
397 struct tm *tp;
398 char buf[100];
399
400 v = ve->var;
401 if (!k->ki_u.u_valid) {
402 (void)printf("%-*s", v->width, "-");
403 return;
404 }
405
406 startt = k->ki_u.u_start.tv_sec;
407 tp = localtime(&startt);
408 if (!now)
409 (void)time(&now);
410 if (now - k->ki_u.u_start.tv_sec < 24 * SECSPERHOUR) {
411 /* I *hate* SCCS... */
412 static char fmt[] = __CONCAT("%l:%", "M%p");
413 (void)strftime(buf, sizeof(buf) - 1, fmt, tp);
414 } else if (now - k->ki_u.u_start.tv_sec < 7 * SECSPERDAY) {
415 /* I *hate* SCCS... */
416 static char fmt[] = __CONCAT("%a%", "I%p");
417 (void)strftime(buf, sizeof(buf) - 1, fmt, tp);
418 } else
419 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
420 (void)printf("%-*s", v->width, buf);
421 }
422
423 void
424 lstarted(k, ve)
425 KINFO *k;
426 VARENT *ve;
427 {
428 VAR *v;
429 time_t startt;
430 char buf[100];
431
432 v = ve->var;
433 if (!k->ki_u.u_valid) {
434 (void)printf("%-*s", v->width, "-");
435 return;
436 }
437 startt = k->ki_u.u_start.tv_sec;
438 (void)strftime(buf, sizeof(buf) -1, "%C",
439 localtime(&startt));
440 (void)printf("%-*s", v->width, buf);
441 }
442
443 void
444 wchan(k, ve)
445 KINFO *k;
446 VARENT *ve;
447 {
448 VAR *v;
449
450 v = ve->var;
451 if (KI_PROC(k)->p_wchan) {
452 if (KI_PROC(k)->p_wmesg)
453 (void)printf("%-*.*s", v->width, v->width,
454 KI_EPROC(k)->e_wmesg);
455 else
456 (void)printf("%-*lx", v->width,
457 (long)KI_PROC(k)->p_wchan &~ KERNBASE);
458 } else
459 (void)printf("%-*s", v->width, "-");
460 }
461
462 #define pgtok(a) (((a)*getpagesize())/1024)
463
464 void
465 vsize(k, ve)
466 KINFO *k;
467 VARENT *ve;
468 {
469 VAR *v;
470
471 v = ve->var;
472 (void)printf("%*d", v->width,
473 #ifndef NEWVM
474 pgtok(KI_PROC(k)->p_dsize +
475 KI_PROC(k)->p_ssize + KI_EPROC(k)->e_xsize));
476 #else
477 pgtok(KI_EPROC(k)->e_vm.vm_dsize + KI_EPROC(k)->e_vm.vm_ssize +
478 KI_EPROC(k)->e_vm.vm_tsize));
479 #endif
480 }
481
482 void
483 rssize(k, ve)
484 KINFO *k;
485 VARENT *ve;
486 {
487 VAR *v;
488
489 v = ve->var;
490 #ifndef NEWVM
491 (void)printf("%*d", v->width,
492 pgtok(KI_PROC(k)->p_rssize + (KI_EPROC(k)->e_xccount ?
493 (KI_EPROC(k)->e_xrssize / KI_EPROC(k)->e_xccount) : 0)));
494 #else
495 /* XXX don't have info about shared */
496 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
497 #endif
498 }
499
500 void
501 p_rssize(k, ve) /* doesn't account for text */
502 KINFO *k;
503 VARENT *ve;
504 {
505 VAR *v;
506
507 v = ve->var;
508 #ifndef NEWVM
509 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_rssize));
510 #else
511 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_rssize));
512 #endif
513 }
514
515 void
516 cputime(k, ve)
517 KINFO *k;
518 VARENT *ve;
519 {
520 VAR *v;
521 long secs;
522 long psecs; /* "parts" of a second. first micro, then centi */
523 char obuff[128];
524
525 v = ve->var;
526 if (KI_PROC(k)->p_stat == SZOMB || !k->ki_u.u_valid) {
527 secs = 0;
528 psecs = 0;
529 } else {
530 /*
531 * This counts time spent handling interrupts. We could
532 * fix this, but it is not 100% trivial (and interrupt
533 * time fractions only work on the sparc anyway). XXX
534 */
535 secs = KI_PROC(k)->p_rtime.tv_sec;
536 psecs = KI_PROC(k)->p_rtime.tv_usec;
537 if (sumrusage) {
538 secs += k->ki_u.u_cru.ru_utime.tv_sec +
539 k->ki_u.u_cru.ru_stime.tv_sec;
540 psecs += k->ki_u.u_cru.ru_utime.tv_usec +
541 k->ki_u.u_cru.ru_stime.tv_usec;
542 }
543 /*
544 * round and scale to 100's
545 */
546 psecs = (psecs + 5000) / 10000;
547 secs += psecs / 100;
548 psecs = psecs % 100;
549 }
550 (void)snprintf(obuff, sizeof(obuff),
551 "%3ld:%02ld.%02ld", secs/60, secs%60, psecs);
552 (void)printf("%*s", v->width, obuff);
553 }
554
555 double
556 getpcpu(k)
557 KINFO *k;
558 {
559 struct proc *p;
560 static int failure;
561
562 if (!nlistread)
563 failure = donlist();
564 if (failure)
565 return (0.0);
566
567 p = KI_PROC(k);
568 #define fxtofl(fixpt) ((double)(fixpt) / fscale)
569
570 /* XXX - I don't like this */
571 if (p->p_swtime == 0 || (p->p_flag & P_INMEM) == 0
572 || p->p_stat == SZOMB)
573 return (0.0);
574 if (rawcpu)
575 return (100.0 * fxtofl(p->p_pctcpu));
576 return (100.0 * fxtofl(p->p_pctcpu) /
577 (1.0 - exp(p->p_swtime * log(fxtofl(ccpu)))));
578 }
579
580 void
581 pcpu(k, ve)
582 KINFO *k;
583 VARENT *ve;
584 {
585 VAR *v;
586
587 v = ve->var;
588 (void)printf("%*.1f", v->width, getpcpu(k));
589 }
590
591 double
592 getpmem(k)
593 KINFO *k;
594 {
595 static int failure;
596 struct proc *p;
597 struct eproc *e;
598 double fracmem;
599 int szptudot;
600
601 if (!nlistread)
602 failure = donlist();
603 if (failure)
604 return (0.0);
605
606 p = KI_PROC(k);
607 e = KI_EPROC(k);
608 if ((p->p_flag & P_INMEM) == 0)
609 return (0.0);
610 #ifndef NEWVM
611 szptudot = USPACE/getpagesize() +
612 clrnd(ctopt(p->p_dsize + p->p_ssize + e->e_xsize));
613 fracmem = ((float)p->p_rssize + szptudot)/CLSIZE/mempages;
614 if (p->p_textp && e->e_xccount)
615 fracmem += ((float)e->e_xrssize)/CLSIZE/e->e_xccount/mempages;
616 #else
617 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
618 szptudot = USPACE/getpagesize();
619 /* XXX don't have info about shared */
620 fracmem = ((float)e->e_vm.vm_rssize + szptudot)/CLSIZE/mempages;
621 #endif
622 return (100.0 * fracmem);
623 }
624
625 void
626 pmem(k, ve)
627 KINFO *k;
628 VARENT *ve;
629 {
630 VAR *v;
631
632 v = ve->var;
633 (void)printf("%*.1f", v->width, getpmem(k));
634 }
635
636 void
637 pagein(k, ve)
638 KINFO *k;
639 VARENT *ve;
640 {
641 VAR *v;
642
643 v = ve->var;
644 (void)printf("%*ld", v->width,
645 k->ki_u.u_valid ? k->ki_u.u_ru.ru_majflt : 0);
646 }
647
648 void
649 maxrss(k, ve)
650 KINFO *k;
651 VARENT *ve;
652 {
653 VAR *v;
654
655 v = ve->var;
656 #ifndef NEWVM /* not yet */
657 if (KI_PROC(k)->p_maxrss != (RLIM_INFINITY/getpagesize()))
658 (void)printf("%*d", v->width, pgtok(KI_PROC(k)->p_maxrss));
659 else
660 #endif
661 (void)printf("%*s", v->width, "-");
662 }
663
664 void
665 tsize(k, ve)
666 KINFO *k;
667 VARENT *ve;
668 {
669 VAR *v;
670
671 v = ve->var;
672 #ifndef NEWVM
673 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xsize));
674 #else
675 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_vm.vm_tsize));
676 #endif
677 }
678
679 #ifndef NEWVM
680 void
681 trss(k, ve)
682 KINFO *k;
683 VARENT *ve;
684 {
685 VAR *v;
686
687 v = ve->var;
688 (void)printf("%*d", v->width, pgtok(KI_EPROC(k)->e_xrssize));
689 }
690 #endif
691
692 /*
693 * Generic output routines. Print fields from various prototype
694 * structures.
695 */
696 static void
697 printval(bp, v)
698 char *bp;
699 VAR *v;
700 {
701 static char ofmt[32] = "%";
702 char *fcp, *cp;
703 enum type type;
704
705 cp = ofmt + 1;
706 fcp = v->fmt;
707 if (v->flag & LJUST)
708 *cp++ = '-';
709 *cp++ = '*';
710 while (*cp++ = *fcp++);
711
712 /*
713 * Note that the "INF127" check is nonsensical for types
714 * that are or can be signed.
715 */
716 #define GET(type) (*(type *)bp)
717 #define CHK_INF127(n) (((n) > 127) && (v->flag & INF127) ? 127 : (n))
718
719 switch (v->type) {
720 case INT32:
721 if (sizeof(int32_t) == sizeof(int))
722 type = INT;
723 else if (sizeof(int32_t) == sizeof(long))
724 type = LONG;
725 else
726 errx(1, "unknown conversion for type %d", v->type);
727 break;
728 case UINT32:
729 if (sizeof(u_int32_t) == sizeof(u_int))
730 type = UINT;
731 else if (sizeof(u_int32_t) == sizeof(u_long))
732 type = ULONG;
733 else
734 errx(1, "unknown conversion for type %d", v->type);
735 break;
736 default:
737 type = v->type;
738 break;
739 }
740
741 switch (type) {
742 case CHAR:
743 (void)printf(ofmt, v->width, GET(char));
744 break;
745 case UCHAR:
746 (void)printf(ofmt, v->width, CHK_INF127(GET(u_char)));
747 break;
748 case SHORT:
749 (void)printf(ofmt, v->width, GET(short));
750 break;
751 case USHORT:
752 (void)printf(ofmt, v->width, CHK_INF127(GET(u_short)));
753 break;
754 case INT:
755 (void)printf(ofmt, v->width, GET(int));
756 break;
757 case UINT:
758 (void)printf(ofmt, v->width, CHK_INF127(GET(u_int)));
759 break;
760 case LONG:
761 (void)printf(ofmt, v->width, GET(long));
762 break;
763 case ULONG:
764 (void)printf(ofmt, v->width, CHK_INF127(GET(u_long)));
765 break;
766 case KPTR:
767 (void)printf(ofmt, v->width, GET(u_long) &~ KERNBASE);
768 break;
769 default:
770 errx(1, "unknown type %d", v->type);
771 }
772 #undef GET
773 #undef CHK_INF127
774 }
775
776 void
777 pvar(k, ve)
778 KINFO *k;
779 VARENT *ve;
780 {
781 VAR *v;
782
783 v = ve->var;
784 printval((char *)KI_PROC(k) + v->off, v);
785 }
786
787 void
788 evar(k, ve)
789 KINFO *k;
790 VARENT *ve;
791 {
792 VAR *v;
793
794 v = ve->var;
795 printval((char *)KI_EPROC(k) + v->off, v);
796 }
797
798 void
799 uvar(k, ve)
800 KINFO *k;
801 VARENT *ve;
802 {
803 VAR *v;
804
805 v = ve->var;
806 if (k->ki_u.u_valid)
807 printval((char *)&k->ki_u + v->off, v);
808 else
809 (void)printf("%*s", v->width, "-");
810 }
811
812 void
813 rvar(k, ve)
814 KINFO *k;
815 VARENT *ve;
816 {
817 VAR *v;
818
819 v = ve->var;
820 if (k->ki_u.u_valid)
821 printval((char *)&k->ki_u.u_ru + v->off, v);
822 else
823 (void)printf("%*s", v->width, "-");
824 }
825