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