Deleted Added
full compact
print.c (97971) print.c (99110)
1/*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
1/*-
2 * Copyright (c) 1990, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35
36__FBSDID("$FreeBSD: head/bin/ps/print.c 97971 2002-06-07 00:00:29Z jmallett $");
37
38#if 0
39#ifndef lint
40static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94";
41#endif /* not lint */
42#endif
34#if 0
35#ifndef lint
36static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94";
37#endif /* not lint */
38#endif
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: head/bin/ps/print.c 99110 2002-06-30 05:15:05Z obrien $");
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#include <sys/user.h>
51#include <sys/sysctl.h>
52
53#include <err.h>
54#include <grp.h>
55#include <langinfo.h>
56#include <locale.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 <unistd.h>
65#include <vis.h>
66
67#include "lomac.h"
68#include "ps.h"
69
70static void printval(char *, VAR *);
71
72void
73printheader(void)
74{
75 VAR *v;
76 struct varent *vent;
77
78 for (vent = vhead; vent; vent = vent->next) {
79 v = vent->var;
80 if (v->flag & LJUST) {
81 if (vent->next == NULL) /* last one */
82 (void)printf("%s", v->header);
83 else
84 (void)printf("%-*s", v->width, v->header);
85 } else
86 (void)printf("%*s", v->width, v->header);
87 if (vent->next != NULL)
88 (void)putchar(' ');
89 }
90 (void)putchar('\n');
91}
92
93void
94arguments(KINFO *k, VARENT *ve)
95{
96 VAR *v;
97 int left;
98 char *cp, *vis_args;
99
100 v = ve->var;
101
102 if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
103 errx(1, "malloc failed");
104 strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
105
106 if (ve->next == NULL) {
107 /* last field */
108 if (termwidth == UNLIMITED) {
109 (void)printf("%s", vis_args);
110 } else {
111 left = termwidth - (totwidth - v->width);
112 if (left < 1) /* already wrapped, just use std width */
113 left = v->width;
114 for (cp = vis_args; --left >= 0 && *cp != '\0';)
115 (void)putchar(*cp++);
116 }
117 } else {
118 (void)printf("%-*.*s", v->width, v->width, vis_args);
119 }
120 free(vis_args);
121}
122
123void
124command(KINFO *k, VARENT *ve)
125{
126 VAR *v;
127 int left;
128 char *cp, *vis_env, *vis_args;
129
130 v = ve->var;
131
132 if (cflag) {
133 if (ve->next == NULL) /* last field, don't pad */
134 (void)printf("%s", k->ki_p->ki_comm);
135 else
136 (void)printf("%-*s", v->width, k->ki_p->ki_comm);
137 return;
138 }
139
140 if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
141 errx(1, "malloc failed");
142 strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
143 if (k->ki_env) {
144 if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1)) == NULL)
145 errx(1, "malloc failed");
146 strvis(vis_env, k->ki_env, VIS_TAB | VIS_NL | VIS_NOSLASH);
147 } else
148 vis_env = NULL;
149
150 if (ve->next == NULL) {
151 /* last field */
152 if (termwidth == UNLIMITED) {
153 if (vis_env)
154 (void)printf("%s ", vis_env);
155 (void)printf("%s", vis_args);
156 } else {
157 left = termwidth - (totwidth - v->width);
158 if (left < 1) /* already wrapped, just use std width */
159 left = v->width;
160 if ((cp = vis_env) != NULL) {
161 while (--left >= 0 && *cp)
162 (void)putchar(*cp++);
163 if (--left >= 0)
164 putchar(' ');
165 }
166 for (cp = vis_args; --left >= 0 && *cp != '\0';)
167 (void)putchar(*cp++);
168 }
169 } else
170 /* XXX env? */
171 (void)printf("%-*.*s", v->width, v->width, vis_args);
172 free(vis_args);
173 if (vis_env != NULL)
174 free(vis_env);
175}
176
177void
178ucomm(KINFO *k, VARENT *ve)
179{
180 VAR *v;
181
182 v = ve->var;
183 (void)printf("%-*s", v->width, k->ki_p->ki_comm);
184}
185
186void
187logname(KINFO *k, VARENT *ve)
188{
189 VAR *v;
190 char *s;
191
192 v = ve->var;
193 (void)printf("%-*s", v->width, (s = k->ki_p->ki_login, *s) ? s : "-");
194}
195
196void
197state(KINFO *k, VARENT *ve)
198{
199 int flag, sflag, tdflags;
200 char *cp;
201 VAR *v;
202 char buf[16];
203
204 v = ve->var;
205 flag = k->ki_p->ki_flag;
206 sflag = k->ki_p->ki_sflag;
207 tdflags = k->ki_p->ki_tdflags; /* XXXKSE */
208 cp = buf;
209
210 switch (k->ki_p->ki_stat) {
211
212 case SSTOP:
213 *cp = 'T';
214 break;
215
216 case SSLEEP:
217 if (tdflags & TDF_SINTR) /* interruptable (long) */
218 *cp = k->ki_p->ki_slptime >= MAXSLP ? 'I' : 'S';
219 else
220 *cp = 'D';
221 break;
222
223 case SRUN:
224 case SIDL:
225 *cp = 'R';
226 break;
227
228 case SWAIT:
229 *cp = 'W';
230 break;
231
232 case SMTX:
233 *cp = 'M';
234 break;
235
236 case SZOMB:
237 *cp = 'Z';
238 break;
239
240 default:
241 *cp = '?';
242 }
243 cp++;
244 if (!(sflag & PS_INMEM))
245 *cp++ = 'W';
246 if (k->ki_p->ki_nice < NZERO)
247 *cp++ = '<';
248 else if (k->ki_p->ki_nice > NZERO)
249 *cp++ = 'N';
250 if (flag & P_TRACED)
251 *cp++ = 'X';
252 if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
253 *cp++ = 'E';
254 if (flag & P_PPWAIT)
255 *cp++ = 'V';
256 if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
257 *cp++ = 'L';
258 if (k->ki_p->ki_kiflag & KI_SLEADER)
259 *cp++ = 's';
260 if ((flag & P_CONTROLT) && k->ki_p->ki_pgid == k->ki_p->ki_tpgid)
261 *cp++ = '+';
262 if (flag & P_JAILED)
263 *cp++ = 'J';
264 *cp = '\0';
265 (void)printf("%-*s", v->width, buf);
266}
267
268void
269pri(KINFO *k, VARENT *ve)
270{
271 VAR *v;
272
273 v = ve->var;
274 (void)printf("%*d", v->width, k->ki_p->ki_pri.pri_level - PZERO);
275}
276
277void
278uname(KINFO *k, VARENT *ve)
279{
280 VAR *v;
281
282 v = ve->var;
283 (void)printf("%-*s", v->width, user_from_uid(k->ki_p->ki_uid, 0));
284}
285
286int
287s_uname(KINFO *k)
288{
289 return (strlen(user_from_uid(k->ki_p->ki_uid, 0)));
290}
291
292void
293rgroupname(KINFO *k, VARENT *ve)
294{
295 VAR *v;
296
297 v = ve->var;
298 (void)printf("%-*s", v->width, group_from_gid(k->ki_p->ki_rgid, 0));
299}
300
301int
302s_rgroupname(KINFO *k)
303{
304 return (strlen(group_from_gid(k->ki_p->ki_rgid, 0)));
305}
306
307void
308runame(KINFO *k, VARENT *ve)
309{
310 VAR *v;
311
312 v = ve->var;
313 (void)printf("%-*s", v->width, user_from_uid(k->ki_p->ki_ruid, 0));
314}
315
316int
317s_runame(KINFO *k)
318{
319 return (strlen(user_from_uid(k->ki_p->ki_ruid, 0)));
320}
321
322void
323tdev(KINFO *k, VARENT *ve)
324{
325 VAR *v;
326 dev_t dev;
327 char buff[16];
328
329 v = ve->var;
330 dev = k->ki_p->ki_tdev;
331 if (dev == NODEV)
332 (void)printf("%*s", v->width, "??");
333 else {
334 (void)snprintf(buff, sizeof(buff),
335 "%d/%d", major(dev), minor(dev));
336 (void)printf("%*s", v->width, buff);
337 }
338}
339
340void
341tname(KINFO *k, VARENT *ve)
342{
343 VAR *v;
344 dev_t dev;
345 char *ttname;
346
347 v = ve->var;
348 dev = k->ki_p->ki_tdev;
349 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
350 (void)printf("%*s ", v->width-1, "??");
351 else {
352 if (strncmp(ttname, "tty", 3) == 0 ||
353 strncmp(ttname, "cua", 3) == 0)
354 ttname += 3;
355 (void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
356 k->ki_p->ki_kiflag & KI_CTTY ? ' ' : '-');
357 }
358}
359
360void
361longtname(KINFO *k, VARENT *ve)
362{
363 VAR *v;
364 dev_t dev;
365 char *ttname;
366
367 v = ve->var;
368 dev = k->ki_p->ki_tdev;
369 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
370 (void)printf("%-*s", v->width, "??");
371 else
372 (void)printf("%-*s", v->width, ttname);
373}
374
375void
376started(KINFO *k, VARENT *ve)
377{
378 VAR *v;
379 time_t then;
380 struct tm *tp;
381 char buf[100];
382 static int use_ampm = -1;
383
384 v = ve->var;
385 if (!k->ki_valid) {
386 (void)printf("%-*s", v->width, "-");
387 return;
388 }
389
390 if (use_ampm < 0)
391 use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
392
393 then = k->ki_p->ki_start.tv_sec;
394 tp = localtime(&then);
395 if (now - k->ki_p->ki_start.tv_sec < 24 * 3600) {
396 (void)strftime(buf, sizeof(buf) - 1,
397 use_ampm ? "%l:%M%p" : "%k:%M ", tp);
398 } else if (now - k->ki_p->ki_start.tv_sec < 7 * 86400) {
399 (void)strftime(buf, sizeof(buf) - 1,
400 use_ampm ? "%a%I%p" : "%a%H ", tp);
401 } else
402 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
403 (void)printf("%-*s", v->width, buf);
404}
405
406void
407lstarted(KINFO *k, VARENT *ve)
408{
409 VAR *v;
410 time_t then;
411 char buf[100];
412
413 v = ve->var;
414 if (!k->ki_valid) {
415 (void)printf("%-*s", v->width, "-");
416 return;
417 }
418 then = k->ki_p->ki_start.tv_sec;
419 (void)strftime(buf, sizeof(buf) -1, "%c", localtime(&then));
420 (void)printf("%-*s", v->width, buf);
421}
422
423void
424mtxname(KINFO *k, VARENT *ve)
425{
426 VAR *v;
427
428 v = ve->var;
429 if (k->ki_p->ki_kiflag & KI_MTXBLOCK) {
430 if (k->ki_p->ki_mtxname[0] != 0)
431 (void)printf("%-*.*s", v->width, v->width,
432 k->ki_p->ki_mtxname);
433 else
434 (void)printf("%-*s", v->width, "???");
435 } else
436 (void)printf("%-*s", v->width, "-");
437}
438
439void
440wchan(KINFO *k, VARENT *ve)
441{
442 VAR *v;
443
444 v = ve->var;
445 if (k->ki_p->ki_wchan) {
446 if (k->ki_p->ki_wmesg[0] != 0)
447 (void)printf("%-*.*s", v->width, v->width,
448 k->ki_p->ki_wmesg);
449 else
450 (void)printf("%-*lx", v->width,
451 (long)k->ki_p->ki_wchan);
452 } else {
453 (void)printf("%-*s", v->width, "-");
454 }
455}
456
457void
458mwchan(KINFO *k, VARENT *ve)
459{
460 VAR *v;
461
462 v = ve->var;
463 if (k->ki_p->ki_wchan) {
464 if (k->ki_p->ki_wmesg[0] != 0)
465 (void)printf("%-*.*s", v->width, v->width,
466 k->ki_p->ki_wmesg);
467 else
468 (void)printf("%-*lx", v->width,
469 (long)k->ki_p->ki_wchan);
470 } else if (k->ki_p->ki_kiflag & KI_MTXBLOCK) {
471 if (k->ki_p->ki_mtxname[0]) {
472 (void)printf("%-*.*s", v->width, v->width,
473 k->ki_p->ki_mtxname);
474 } else {
475 (void)printf("%-*s", v->width, "???");
476 }
477 } else {
478 (void)printf("%-*s", v->width, "-");
479 }
480}
481
482#ifndef pgtok
483#define pgtok(a) (((a)*getpagesize())/1024)
484#endif
485
486void
487vsize(KINFO *k, VARENT *ve)
488{
489 VAR *v;
490
491 v = ve->var;
492 (void)printf("%*d", v->width,
493 (k->ki_p->ki_size/1024));
494}
495
496void
497cputime(KINFO *k, VARENT *ve)
498{
499 VAR *v;
500 long secs;
501 long psecs; /* "parts" of a second. first micro, then centi */
502 char obuff[128];
503 static char decimal_point = 0;
504
505 if (!decimal_point)
506 decimal_point = localeconv()->decimal_point[0];
507 v = ve->var;
508 if (k->ki_p->ki_stat == SZOMB || !k->ki_valid) {
509 secs = 0;
510 psecs = 0;
511 } else {
512 /*
513 * This counts time spent handling interrupts. We could
514 * fix this, but it is not 100% trivial (and interrupt
515 * time fractions only work on the sparc anyway). XXX
516 */
517 secs = k->ki_p->ki_runtime / 1000000;
518 psecs = k->ki_p->ki_runtime % 1000000;
519 if (sumrusage) {
520 secs += k->ki_p->ki_childtime.tv_sec;
521 psecs += k->ki_p->ki_childtime.tv_usec;
522 }
523 /*
524 * round and scale to 100's
525 */
526 psecs = (psecs + 5000) / 10000;
527 secs += psecs / 100;
528 psecs = psecs % 100;
529 }
530 (void)snprintf(obuff, sizeof(obuff),
531 "%3ld:%02ld%c%02ld", secs/60, secs%60, decimal_point, psecs);
532 (void)printf("%*s", v->width, obuff);
533}
534
535void
536elapsed(KINFO *k, VARENT *ve)
537{
538 VAR *v;
539 time_t secs;
540 char obuff[128];
541
542 v = ve->var;
543
544 secs = now - k->ki_p->ki_start.tv_sec;
545 (void)snprintf(obuff, sizeof(obuff), "%3ld:%02ld", (long)secs/60,
546 (long)secs%60);
547 (void)printf("%*s", v->width, obuff);
548}
549
550double
551getpcpu(const KINFO *k)
552{
553 static int failure;
554
555 if (!nlistread)
556 failure = donlist();
557 if (failure)
558 return (0.0);
559
560#define fxtofl(fixpt) ((double)(fixpt) / fscale)
561
562 /* XXX - I don't like this */
563 if (k->ki_p->ki_swtime == 0 || (k->ki_p->ki_sflag & PS_INMEM) == 0)
564 return (0.0);
565 if (rawcpu)
566 return (100.0 * fxtofl(k->ki_p->ki_pctcpu));
567 return (100.0 * fxtofl(k->ki_p->ki_pctcpu) /
568 (1.0 - exp(k->ki_p->ki_swtime * log(fxtofl(ccpu)))));
569}
570
571void
572pcpu(KINFO *k, VARENT *ve)
573{
574 VAR *v;
575
576 v = ve->var;
577 (void)printf("%*.1f", v->width, getpcpu(k));
578}
579
580static double
581getpmem(KINFO *k)
582{
583 static int failure;
584 double fracmem;
585
586 if (!nlistread)
587 failure = donlist();
588 if (failure)
589 return (0.0);
590
591 if ((k->ki_p->ki_sflag & PS_INMEM) == 0)
592 return (0.0);
593 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
594 /* XXX don't have info about shared */
595 fracmem = ((float)k->ki_p->ki_rssize)/mempages;
596 return (100.0 * fracmem);
597}
598
599void
600pmem(KINFO *k, VARENT *ve)
601{
602 VAR *v;
603
604 v = ve->var;
605 (void)printf("%*.1f", v->width, getpmem(k));
606}
607
608void
609pagein(KINFO *k, VARENT *ve)
610{
611 VAR *v;
612
613 v = ve->var;
614 (void)printf("%*ld", v->width,
615 k->ki_valid ? k->ki_p->ki_rusage.ru_majflt : 0);
616}
617
618/* ARGSUSED */
619void
620maxrss(KINFO *k __unused, VARENT *ve)
621{
622 VAR *v;
623
624 v = ve->var;
625 /* XXX not yet */
626 (void)printf("%*s", v->width, "-");
627}
628
629void
630tsize(KINFO *k, VARENT *ve)
631{
632 VAR *v;
633
634 v = ve->var;
635 (void)printf("%*ld", v->width, (long)pgtok(k->ki_p->ki_tsize));
636}
637
638void
639priorityr(KINFO *k, VARENT *ve)
640{
641 VAR *v;
642 struct priority *lpri;
643 char str[8];
644 unsigned class, level;
645
646 v = ve->var;
647 lpri = (struct priority *) ((char *)k + v->off);
648 class = lpri->pri_class;
649 level = lpri->pri_level;
650 switch (class) {
651 case PRI_REALTIME:
652 snprintf(str, sizeof(str), "real:%u", level);
653 break;
654 case PRI_TIMESHARE:
655 strncpy(str, "normal", sizeof(str));
656 break;
657 case PRI_IDLE:
658 snprintf(str, sizeof(str), "idle:%u", level);
659 break;
660 default:
661 snprintf(str, sizeof(str), "%u:%u", class, level);
662 break;
663 }
664 str[sizeof(str) - 1] = '\0';
665 (void)printf("%*s", v->width, str);
666}
667
668/*
669 * Generic output routines. Print fields from various prototype
670 * structures.
671 */
672static void
673printval(char *bp, VAR *v)
674{
675 static char ofmt[32] = "%";
676 const char *fcp;
677 char *cp;
678
679 cp = ofmt + 1;
680 fcp = v->fmt;
681 if (v->flag & LJUST)
682 *cp++ = '-';
683 *cp++ = '*';
684 while ((*cp++ = *fcp++));
685
686 switch (v->type) {
687 case CHAR:
688 (void)printf(ofmt, v->width, *(char *)bp);
689 break;
690 case UCHAR:
691 (void)printf(ofmt, v->width, *(u_char *)bp);
692 break;
693 case SHORT:
694 (void)printf(ofmt, v->width, *(short *)bp);
695 break;
696 case USHORT:
697 (void)printf(ofmt, v->width, *(u_short *)bp);
698 break;
699 case INT:
700 (void)printf(ofmt, v->width, *(int *)bp);
701 break;
702 case UINT:
703 (void)printf(ofmt, v->width, *(u_int *)bp);
704 break;
705 case LONG:
706 (void)printf(ofmt, v->width, *(long *)bp);
707 break;
708 case ULONG:
709 (void)printf(ofmt, v->width, *(u_long *)bp);
710 break;
711 case KPTR:
712 (void)printf(ofmt, v->width, *(u_long *)bp);
713 break;
714 default:
715 errx(1, "unknown type %d", v->type);
716 }
717}
718
719void
720kvar(KINFO *k, VARENT *ve)
721{
722 VAR *v;
723
724 v = ve->var;
725 printval((char *)((char *)k->ki_p + v->off), v);
726}
727
728void
729rvar(KINFO *k, VARENT *ve)
730{
731 VAR *v;
732
733 v = ve->var;
734 if (k->ki_valid)
735 printval((char *)((char *)(&k->ki_p->ki_rusage) + v->off), v);
736 else
737 (void)printf("%*s", v->width, "-");
738}
739
740void
741lattr(KINFO *k, VARENT *ve)
742{
743 VAR *v;
744
745 v = ve->var;
746 (void)printf("%-*d", v->width, get_lattr(k->ki_p->ki_pid));
747}
41
42#include <sys/param.h>
43#include <sys/time.h>
44#include <sys/resource.h>
45#include <sys/proc.h>
46#include <sys/stat.h>
47
48#include <sys/user.h>
49#include <sys/sysctl.h>
50
51#include <err.h>
52#include <grp.h>
53#include <langinfo.h>
54#include <locale.h>
55#include <math.h>
56#include <nlist.h>
57#include <pwd.h>
58#include <stddef.h>
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62#include <unistd.h>
63#include <vis.h>
64
65#include "lomac.h"
66#include "ps.h"
67
68static void printval(char *, VAR *);
69
70void
71printheader(void)
72{
73 VAR *v;
74 struct varent *vent;
75
76 for (vent = vhead; vent; vent = vent->next) {
77 v = vent->var;
78 if (v->flag & LJUST) {
79 if (vent->next == NULL) /* last one */
80 (void)printf("%s", v->header);
81 else
82 (void)printf("%-*s", v->width, v->header);
83 } else
84 (void)printf("%*s", v->width, v->header);
85 if (vent->next != NULL)
86 (void)putchar(' ');
87 }
88 (void)putchar('\n');
89}
90
91void
92arguments(KINFO *k, VARENT *ve)
93{
94 VAR *v;
95 int left;
96 char *cp, *vis_args;
97
98 v = ve->var;
99
100 if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
101 errx(1, "malloc failed");
102 strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
103
104 if (ve->next == NULL) {
105 /* last field */
106 if (termwidth == UNLIMITED) {
107 (void)printf("%s", vis_args);
108 } else {
109 left = termwidth - (totwidth - v->width);
110 if (left < 1) /* already wrapped, just use std width */
111 left = v->width;
112 for (cp = vis_args; --left >= 0 && *cp != '\0';)
113 (void)putchar(*cp++);
114 }
115 } else {
116 (void)printf("%-*.*s", v->width, v->width, vis_args);
117 }
118 free(vis_args);
119}
120
121void
122command(KINFO *k, VARENT *ve)
123{
124 VAR *v;
125 int left;
126 char *cp, *vis_env, *vis_args;
127
128 v = ve->var;
129
130 if (cflag) {
131 if (ve->next == NULL) /* last field, don't pad */
132 (void)printf("%s", k->ki_p->ki_comm);
133 else
134 (void)printf("%-*s", v->width, k->ki_p->ki_comm);
135 return;
136 }
137
138 if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
139 errx(1, "malloc failed");
140 strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
141 if (k->ki_env) {
142 if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1)) == NULL)
143 errx(1, "malloc failed");
144 strvis(vis_env, k->ki_env, VIS_TAB | VIS_NL | VIS_NOSLASH);
145 } else
146 vis_env = NULL;
147
148 if (ve->next == NULL) {
149 /* last field */
150 if (termwidth == UNLIMITED) {
151 if (vis_env)
152 (void)printf("%s ", vis_env);
153 (void)printf("%s", vis_args);
154 } else {
155 left = termwidth - (totwidth - v->width);
156 if (left < 1) /* already wrapped, just use std width */
157 left = v->width;
158 if ((cp = vis_env) != NULL) {
159 while (--left >= 0 && *cp)
160 (void)putchar(*cp++);
161 if (--left >= 0)
162 putchar(' ');
163 }
164 for (cp = vis_args; --left >= 0 && *cp != '\0';)
165 (void)putchar(*cp++);
166 }
167 } else
168 /* XXX env? */
169 (void)printf("%-*.*s", v->width, v->width, vis_args);
170 free(vis_args);
171 if (vis_env != NULL)
172 free(vis_env);
173}
174
175void
176ucomm(KINFO *k, VARENT *ve)
177{
178 VAR *v;
179
180 v = ve->var;
181 (void)printf("%-*s", v->width, k->ki_p->ki_comm);
182}
183
184void
185logname(KINFO *k, VARENT *ve)
186{
187 VAR *v;
188 char *s;
189
190 v = ve->var;
191 (void)printf("%-*s", v->width, (s = k->ki_p->ki_login, *s) ? s : "-");
192}
193
194void
195state(KINFO *k, VARENT *ve)
196{
197 int flag, sflag, tdflags;
198 char *cp;
199 VAR *v;
200 char buf[16];
201
202 v = ve->var;
203 flag = k->ki_p->ki_flag;
204 sflag = k->ki_p->ki_sflag;
205 tdflags = k->ki_p->ki_tdflags; /* XXXKSE */
206 cp = buf;
207
208 switch (k->ki_p->ki_stat) {
209
210 case SSTOP:
211 *cp = 'T';
212 break;
213
214 case SSLEEP:
215 if (tdflags & TDF_SINTR) /* interruptable (long) */
216 *cp = k->ki_p->ki_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 SWAIT:
227 *cp = 'W';
228 break;
229
230 case SMTX:
231 *cp = 'M';
232 break;
233
234 case SZOMB:
235 *cp = 'Z';
236 break;
237
238 default:
239 *cp = '?';
240 }
241 cp++;
242 if (!(sflag & PS_INMEM))
243 *cp++ = 'W';
244 if (k->ki_p->ki_nice < NZERO)
245 *cp++ = '<';
246 else if (k->ki_p->ki_nice > NZERO)
247 *cp++ = 'N';
248 if (flag & P_TRACED)
249 *cp++ = 'X';
250 if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
251 *cp++ = 'E';
252 if (flag & P_PPWAIT)
253 *cp++ = 'V';
254 if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
255 *cp++ = 'L';
256 if (k->ki_p->ki_kiflag & KI_SLEADER)
257 *cp++ = 's';
258 if ((flag & P_CONTROLT) && k->ki_p->ki_pgid == k->ki_p->ki_tpgid)
259 *cp++ = '+';
260 if (flag & P_JAILED)
261 *cp++ = 'J';
262 *cp = '\0';
263 (void)printf("%-*s", v->width, buf);
264}
265
266void
267pri(KINFO *k, VARENT *ve)
268{
269 VAR *v;
270
271 v = ve->var;
272 (void)printf("%*d", v->width, k->ki_p->ki_pri.pri_level - PZERO);
273}
274
275void
276uname(KINFO *k, VARENT *ve)
277{
278 VAR *v;
279
280 v = ve->var;
281 (void)printf("%-*s", v->width, user_from_uid(k->ki_p->ki_uid, 0));
282}
283
284int
285s_uname(KINFO *k)
286{
287 return (strlen(user_from_uid(k->ki_p->ki_uid, 0)));
288}
289
290void
291rgroupname(KINFO *k, VARENT *ve)
292{
293 VAR *v;
294
295 v = ve->var;
296 (void)printf("%-*s", v->width, group_from_gid(k->ki_p->ki_rgid, 0));
297}
298
299int
300s_rgroupname(KINFO *k)
301{
302 return (strlen(group_from_gid(k->ki_p->ki_rgid, 0)));
303}
304
305void
306runame(KINFO *k, VARENT *ve)
307{
308 VAR *v;
309
310 v = ve->var;
311 (void)printf("%-*s", v->width, user_from_uid(k->ki_p->ki_ruid, 0));
312}
313
314int
315s_runame(KINFO *k)
316{
317 return (strlen(user_from_uid(k->ki_p->ki_ruid, 0)));
318}
319
320void
321tdev(KINFO *k, VARENT *ve)
322{
323 VAR *v;
324 dev_t dev;
325 char buff[16];
326
327 v = ve->var;
328 dev = k->ki_p->ki_tdev;
329 if (dev == NODEV)
330 (void)printf("%*s", v->width, "??");
331 else {
332 (void)snprintf(buff, sizeof(buff),
333 "%d/%d", major(dev), minor(dev));
334 (void)printf("%*s", v->width, buff);
335 }
336}
337
338void
339tname(KINFO *k, VARENT *ve)
340{
341 VAR *v;
342 dev_t dev;
343 char *ttname;
344
345 v = ve->var;
346 dev = k->ki_p->ki_tdev;
347 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
348 (void)printf("%*s ", v->width-1, "??");
349 else {
350 if (strncmp(ttname, "tty", 3) == 0 ||
351 strncmp(ttname, "cua", 3) == 0)
352 ttname += 3;
353 (void)printf("%*.*s%c", v->width-1, v->width-1, ttname,
354 k->ki_p->ki_kiflag & KI_CTTY ? ' ' : '-');
355 }
356}
357
358void
359longtname(KINFO *k, VARENT *ve)
360{
361 VAR *v;
362 dev_t dev;
363 char *ttname;
364
365 v = ve->var;
366 dev = k->ki_p->ki_tdev;
367 if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
368 (void)printf("%-*s", v->width, "??");
369 else
370 (void)printf("%-*s", v->width, ttname);
371}
372
373void
374started(KINFO *k, VARENT *ve)
375{
376 VAR *v;
377 time_t then;
378 struct tm *tp;
379 char buf[100];
380 static int use_ampm = -1;
381
382 v = ve->var;
383 if (!k->ki_valid) {
384 (void)printf("%-*s", v->width, "-");
385 return;
386 }
387
388 if (use_ampm < 0)
389 use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
390
391 then = k->ki_p->ki_start.tv_sec;
392 tp = localtime(&then);
393 if (now - k->ki_p->ki_start.tv_sec < 24 * 3600) {
394 (void)strftime(buf, sizeof(buf) - 1,
395 use_ampm ? "%l:%M%p" : "%k:%M ", tp);
396 } else if (now - k->ki_p->ki_start.tv_sec < 7 * 86400) {
397 (void)strftime(buf, sizeof(buf) - 1,
398 use_ampm ? "%a%I%p" : "%a%H ", tp);
399 } else
400 (void)strftime(buf, sizeof(buf) - 1, "%e%b%y", tp);
401 (void)printf("%-*s", v->width, buf);
402}
403
404void
405lstarted(KINFO *k, VARENT *ve)
406{
407 VAR *v;
408 time_t then;
409 char buf[100];
410
411 v = ve->var;
412 if (!k->ki_valid) {
413 (void)printf("%-*s", v->width, "-");
414 return;
415 }
416 then = k->ki_p->ki_start.tv_sec;
417 (void)strftime(buf, sizeof(buf) -1, "%c", localtime(&then));
418 (void)printf("%-*s", v->width, buf);
419}
420
421void
422mtxname(KINFO *k, VARENT *ve)
423{
424 VAR *v;
425
426 v = ve->var;
427 if (k->ki_p->ki_kiflag & KI_MTXBLOCK) {
428 if (k->ki_p->ki_mtxname[0] != 0)
429 (void)printf("%-*.*s", v->width, v->width,
430 k->ki_p->ki_mtxname);
431 else
432 (void)printf("%-*s", v->width, "???");
433 } else
434 (void)printf("%-*s", v->width, "-");
435}
436
437void
438wchan(KINFO *k, VARENT *ve)
439{
440 VAR *v;
441
442 v = ve->var;
443 if (k->ki_p->ki_wchan) {
444 if (k->ki_p->ki_wmesg[0] != 0)
445 (void)printf("%-*.*s", v->width, v->width,
446 k->ki_p->ki_wmesg);
447 else
448 (void)printf("%-*lx", v->width,
449 (long)k->ki_p->ki_wchan);
450 } else {
451 (void)printf("%-*s", v->width, "-");
452 }
453}
454
455void
456mwchan(KINFO *k, VARENT *ve)
457{
458 VAR *v;
459
460 v = ve->var;
461 if (k->ki_p->ki_wchan) {
462 if (k->ki_p->ki_wmesg[0] != 0)
463 (void)printf("%-*.*s", v->width, v->width,
464 k->ki_p->ki_wmesg);
465 else
466 (void)printf("%-*lx", v->width,
467 (long)k->ki_p->ki_wchan);
468 } else if (k->ki_p->ki_kiflag & KI_MTXBLOCK) {
469 if (k->ki_p->ki_mtxname[0]) {
470 (void)printf("%-*.*s", v->width, v->width,
471 k->ki_p->ki_mtxname);
472 } else {
473 (void)printf("%-*s", v->width, "???");
474 }
475 } else {
476 (void)printf("%-*s", v->width, "-");
477 }
478}
479
480#ifndef pgtok
481#define pgtok(a) (((a)*getpagesize())/1024)
482#endif
483
484void
485vsize(KINFO *k, VARENT *ve)
486{
487 VAR *v;
488
489 v = ve->var;
490 (void)printf("%*d", v->width,
491 (k->ki_p->ki_size/1024));
492}
493
494void
495cputime(KINFO *k, VARENT *ve)
496{
497 VAR *v;
498 long secs;
499 long psecs; /* "parts" of a second. first micro, then centi */
500 char obuff[128];
501 static char decimal_point = 0;
502
503 if (!decimal_point)
504 decimal_point = localeconv()->decimal_point[0];
505 v = ve->var;
506 if (k->ki_p->ki_stat == SZOMB || !k->ki_valid) {
507 secs = 0;
508 psecs = 0;
509 } else {
510 /*
511 * This counts time spent handling interrupts. We could
512 * fix this, but it is not 100% trivial (and interrupt
513 * time fractions only work on the sparc anyway). XXX
514 */
515 secs = k->ki_p->ki_runtime / 1000000;
516 psecs = k->ki_p->ki_runtime % 1000000;
517 if (sumrusage) {
518 secs += k->ki_p->ki_childtime.tv_sec;
519 psecs += k->ki_p->ki_childtime.tv_usec;
520 }
521 /*
522 * round and scale to 100's
523 */
524 psecs = (psecs + 5000) / 10000;
525 secs += psecs / 100;
526 psecs = psecs % 100;
527 }
528 (void)snprintf(obuff, sizeof(obuff),
529 "%3ld:%02ld%c%02ld", secs/60, secs%60, decimal_point, psecs);
530 (void)printf("%*s", v->width, obuff);
531}
532
533void
534elapsed(KINFO *k, VARENT *ve)
535{
536 VAR *v;
537 time_t secs;
538 char obuff[128];
539
540 v = ve->var;
541
542 secs = now - k->ki_p->ki_start.tv_sec;
543 (void)snprintf(obuff, sizeof(obuff), "%3ld:%02ld", (long)secs/60,
544 (long)secs%60);
545 (void)printf("%*s", v->width, obuff);
546}
547
548double
549getpcpu(const KINFO *k)
550{
551 static int failure;
552
553 if (!nlistread)
554 failure = donlist();
555 if (failure)
556 return (0.0);
557
558#define fxtofl(fixpt) ((double)(fixpt) / fscale)
559
560 /* XXX - I don't like this */
561 if (k->ki_p->ki_swtime == 0 || (k->ki_p->ki_sflag & PS_INMEM) == 0)
562 return (0.0);
563 if (rawcpu)
564 return (100.0 * fxtofl(k->ki_p->ki_pctcpu));
565 return (100.0 * fxtofl(k->ki_p->ki_pctcpu) /
566 (1.0 - exp(k->ki_p->ki_swtime * log(fxtofl(ccpu)))));
567}
568
569void
570pcpu(KINFO *k, VARENT *ve)
571{
572 VAR *v;
573
574 v = ve->var;
575 (void)printf("%*.1f", v->width, getpcpu(k));
576}
577
578static double
579getpmem(KINFO *k)
580{
581 static int failure;
582 double fracmem;
583
584 if (!nlistread)
585 failure = donlist();
586 if (failure)
587 return (0.0);
588
589 if ((k->ki_p->ki_sflag & PS_INMEM) == 0)
590 return (0.0);
591 /* XXX want pmap ptpages, segtab, etc. (per architecture) */
592 /* XXX don't have info about shared */
593 fracmem = ((float)k->ki_p->ki_rssize)/mempages;
594 return (100.0 * fracmem);
595}
596
597void
598pmem(KINFO *k, VARENT *ve)
599{
600 VAR *v;
601
602 v = ve->var;
603 (void)printf("%*.1f", v->width, getpmem(k));
604}
605
606void
607pagein(KINFO *k, VARENT *ve)
608{
609 VAR *v;
610
611 v = ve->var;
612 (void)printf("%*ld", v->width,
613 k->ki_valid ? k->ki_p->ki_rusage.ru_majflt : 0);
614}
615
616/* ARGSUSED */
617void
618maxrss(KINFO *k __unused, VARENT *ve)
619{
620 VAR *v;
621
622 v = ve->var;
623 /* XXX not yet */
624 (void)printf("%*s", v->width, "-");
625}
626
627void
628tsize(KINFO *k, VARENT *ve)
629{
630 VAR *v;
631
632 v = ve->var;
633 (void)printf("%*ld", v->width, (long)pgtok(k->ki_p->ki_tsize));
634}
635
636void
637priorityr(KINFO *k, VARENT *ve)
638{
639 VAR *v;
640 struct priority *lpri;
641 char str[8];
642 unsigned class, level;
643
644 v = ve->var;
645 lpri = (struct priority *) ((char *)k + v->off);
646 class = lpri->pri_class;
647 level = lpri->pri_level;
648 switch (class) {
649 case PRI_REALTIME:
650 snprintf(str, sizeof(str), "real:%u", level);
651 break;
652 case PRI_TIMESHARE:
653 strncpy(str, "normal", sizeof(str));
654 break;
655 case PRI_IDLE:
656 snprintf(str, sizeof(str), "idle:%u", level);
657 break;
658 default:
659 snprintf(str, sizeof(str), "%u:%u", class, level);
660 break;
661 }
662 str[sizeof(str) - 1] = '\0';
663 (void)printf("%*s", v->width, str);
664}
665
666/*
667 * Generic output routines. Print fields from various prototype
668 * structures.
669 */
670static void
671printval(char *bp, VAR *v)
672{
673 static char ofmt[32] = "%";
674 const char *fcp;
675 char *cp;
676
677 cp = ofmt + 1;
678 fcp = v->fmt;
679 if (v->flag & LJUST)
680 *cp++ = '-';
681 *cp++ = '*';
682 while ((*cp++ = *fcp++));
683
684 switch (v->type) {
685 case CHAR:
686 (void)printf(ofmt, v->width, *(char *)bp);
687 break;
688 case UCHAR:
689 (void)printf(ofmt, v->width, *(u_char *)bp);
690 break;
691 case SHORT:
692 (void)printf(ofmt, v->width, *(short *)bp);
693 break;
694 case USHORT:
695 (void)printf(ofmt, v->width, *(u_short *)bp);
696 break;
697 case INT:
698 (void)printf(ofmt, v->width, *(int *)bp);
699 break;
700 case UINT:
701 (void)printf(ofmt, v->width, *(u_int *)bp);
702 break;
703 case LONG:
704 (void)printf(ofmt, v->width, *(long *)bp);
705 break;
706 case ULONG:
707 (void)printf(ofmt, v->width, *(u_long *)bp);
708 break;
709 case KPTR:
710 (void)printf(ofmt, v->width, *(u_long *)bp);
711 break;
712 default:
713 errx(1, "unknown type %d", v->type);
714 }
715}
716
717void
718kvar(KINFO *k, VARENT *ve)
719{
720 VAR *v;
721
722 v = ve->var;
723 printval((char *)((char *)k->ki_p + v->off), v);
724}
725
726void
727rvar(KINFO *k, VARENT *ve)
728{
729 VAR *v;
730
731 v = ve->var;
732 if (k->ki_valid)
733 printval((char *)((char *)(&k->ki_p->ki_rusage) + v->off), v);
734 else
735 (void)printf("%*s", v->width, "-");
736}
737
738void
739lattr(KINFO *k, VARENT *ve)
740{
741 VAR *v;
742
743 v = ve->var;
744 (void)printf("%-*d", v->width, get_lattr(k->ki_p->ki_pid));
745}