1 /*
2 * Copyright (c) 2006, William Yodlowsky <bsd@openbsd.rutgers.edu>
3 * This file is free software; it can be modified and/or
4 * redistributed under the same terms as Perl itself
5 */
6
7 #include <sys/types.h>
8 #include <sys/param.h>
9 #include <sys/mount.h>
10 #include <sys/proc.h>
11 #include <sys/stat.h>
12 #include <sys/sysctl.h>
13 #include <sys/syslimits.h>
14 #include <sys/user.h>
15
16 #include <ctype.h>
17 #include <fcntl.h>
18 #include <kvm.h>
19 #include <limits.h>
20 #include <math.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <time.h>
25 #include <unistd.h>
26
27 void ppt_croak(const char *pat, ...);
28
29 /* No need for the procstat structure since we don't use /proc */
30
31 /* We need to pass in a cap for ignore, lower for store on object */
32 /* We can just lc these! */
33 static char Defaultformat[] = "liiiiiiiiiiiillssss";
34
35 /* Mapping of field to type */
36 static char* Fields[] = {
37 "ttynum",
38 "uid",
39 "gid",
40 "euid",
41 "egid",
42 "pid",
43 "ppid",
44 "pgrp",
45 "sess",
46 "time",
47 "utime",
48 "stime",
49 "start",
50 "size",
51 "rss",
52 "fname",
53 "state",
54 "ttydev",
55 "cmndline"
56 };
57 #define F_LASTFIELD 18
58
59 /* Set up simple bounds checking */
60 #define STRLCPY(num,targ,src) if (strlcpy(targ,src,sizeof(targ)) >= sizeof(targ)) \
61 ppt_croak("call:%d source string is too big to copy into buffer", num);
62
63 #define STRLCAT(num,targ,src) if (strlcat(targ,src,sizeof(targ)) >= sizeof(targ)) \
64 ppt_croak("call:%d source string is too big to append to buffer", num);
65
66 extern void bless_into_proc(char* format, char** fields, ...);
67
OS_initialize()68 char* OS_initialize() {
69 return(NULL);
70 }
71
OS_get_table()72 void OS_get_table() {
73 kvm_t *kd;
74 char errbuf[_POSIX2_LINE_MAX];
75 struct kinfo_proc *procs;
76 int count;
77 int i, argcount;
78 int ttynum;
79 long start;
80 unsigned long vsize;
81 unsigned long rss;
82 char *ttydev;
83 char cmndline[ARG_MAX+1];
84 char **pargv;
85
86 /* for bless_into_proc */
87 static char format[F_LASTFIELD + 2];
88 char state[20];
89
90 /* open the kvm interface */
91 if ((kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL) {
92 ppt_croak("kvm_open: %s", errbuf);
93 }
94
95 /* get processes */
96 if ((procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(*procs), &count)) == NULL) {
97 kvm_close(kd);
98 ppt_croak("kvm_getprocs: %s", kvm_geterr(kd));
99 }
100
101 /* bless_into_proc each process's information */
102 for (i=0; i < count; i++) {
103 STRLCPY(1,format,Defaultformat);
104
105 /* get ttydev */
106 ttynum=procs[i].p_tdev;
107 ttydev=devname(ttynum, S_IFCHR);
108 if (ttydev == NULL) ttydev = "??";
109
110 /* process state */
111 switch (procs[i].p_stat) {
112 case SIDL:
113 STRLCPY(2,state,"IDLE");
114 break;
115 case SRUN:
116 STRLCPY(3,state,"RUN");
117 break;
118 case SSLEEP:
119 STRLCPY(4,state,"SLEEP");
120 break;
121 case SSTOP:
122 STRLCPY(5,state,"STOP");
123 break;
124 case SZOMB:
125 STRLCPY(6,state,"ZOMBIE");
126 break;
127 default:
128 STRLCPY(7,state,"UNKNOWN");
129 break;
130 }
131
132 vsize = getpagesize() * (procs[i].p_vm_dsize + procs[i].p_vm_ssize + procs[i].p_vm_tsize);
133 rss = getpagesize() * procs[i].p_vm_rssize;
134
135 /* arguments */
136 cmndline[0] = '\0';
137 pargv = kvm_getargv(kd, (const struct kinfo_proc *) &(procs[i]), 0);
138 if (pargv) {
139 argcount = 0;
140 while (pargv[argcount] && strlen(cmndline)+strlen(pargv[argcount])+1 <= ARG_MAX) {
141 STRLCAT(1,cmndline,pargv[argcount]);
142 if (pargv[argcount+1]) {
143 STRLCAT(2,cmndline," ");
144 }
145 argcount++;
146 }
147 }
148
149 /* everything else is straightforward, bless the lot */
150 bless_into_proc( format,
151 Fields,
152 ttynum,
153 procs[i].p_ruid,
154 procs[i].p_rgid,
155 procs[i].p_uid,
156 procs[i].p_gid,
157 procs[i].p_pid,
158 procs[i].p_ppid,
159 procs[i].p__pgid,
160 procs[i].p_sid,
161 procs[i].p_rtime_sec,
162 procs[i].p_uutime_sec,
163 procs[i].p_ustime_sec,
164 procs[i].p_ustart_sec,
165 vsize,
166 rss,
167 procs[i].p_comm,
168 state,
169 ttydev,
170 cmndline
171 );
172 }
173 if (kd) {
174 kvm_close(kd);
175 }
176 }
177