Blob


2 static int
3 copy_str(const char *field, size_t max, char *buf, size_t size, off_t off)
4 {
5 const size_t n = strnlen(field, max);
6 if ((size_t)off < n) {
7 if ((n - off) < size)
8 size = n - off;
9 memcpy(buf, field + off, size);
10 return n - off;
11 } else if ((size_t)off > n) {
12 return 0;
13 } else {
14 buf[0] = '\n';
15 return 1;
16 }
17 }
19 static int
20 copy_str2(const char *field, char *buf, size_t size, off_t off)
21 {
22 const size_t n = strlen(field);
23 if ((size_t)off < n) {
24 if ((n - off) < size)
25 size = n - off;
26 memcpy(buf, field + off, size);
27 return n - off;
28 } else {
29 return 0;
30 }
31 }
33 static int
34 copy_uint(unsigned int field, char *buf, size_t size, off_t off)
35 {
36 char buffer[32];
37 int n;
39 n = snprintf(buffer, sizeof (buffer), "%u\n", field);
40 if (n >= (int)sizeof (buffer)) {
41 warnx("copy_uint(%u): Failed to format field.", field);
42 return -EIO;
43 }
45 return copy_str2(buffer, buf, size, off);
46 }
48 static int
49 copy_int(int field, char *buf, size_t size, off_t off)
50 {
51 char buffer[32];
52 int n;
54 n = snprintf(buffer, sizeof (buffer), "%d\n", field);
55 if (n >= (int)sizeof (buffer)) {
56 warnx("copy_int(%u): Failed to format field.", field);
57 return -EIO;
58 }
60 return copy_str2(buffer, buf, size, off);
61 }
63 #define def_uint(arg, name, value) \
64 static int \
65 name(arg, char *buf, size_t size, off_t off) \
66 { \
67 return copy_uint((value), buf, size, off); \
68 }
70 #define def_int(arg, name, value) \
71 static int \
72 name(arg, char *buf, size_t size, off_t off) \
73 { \
74 return copy_int((value), buf, size, off); \
75 }
77 #define def_str(arg, name, value, max) \
78 static int \
79 name(arg, char *buf, size_t size, off_t off) \
80 { \
81 return copy_str((value), max, buf, size, off); \
82 }
84 def_uint(struct kinfo_proc *kp, read_pid, kp->p_pid);
85 def_str(struct kinfo_proc *kp, read_comm, kp->p_comm, KI_MAXCOMLEN);
86 def_str(struct kinfo_proc *kp, read_name, kp->p_name, KI_MAXCOMLEN);
87 def_str(struct kinfo_proc *kp, read_emul, kp->p_emul, KI_EMULNAMELEN);
88 def_str(struct kinfo_proc *kp, read_wmesg, kp->p_wmesg, KI_WMESGLEN);
89 def_str(struct kinfo_proc *kp, read_login, kp->p_login, KI_MAXLOGNAME);
90 def_uint(struct kinfo_proc *kp, read_uid, kp->p_uid);
91 def_uint(struct kinfo_proc *kp, read_ruid, kp->p_ruid);
92 def_uint(struct kinfo_proc *kp, read_gid, kp->p_gid);
93 def_uint(struct kinfo_proc *kp, read_rgid, kp->p_rgid);
94 def_uint(struct kinfo_proc *kp, read_priority, kp->p_priority);
95 def_int(struct kinfo_proc *kp, read_nice, kp->p_nice - 20);
96 def_int(struct kinfo_proc *kp, read_vm_rssize, kp->p_vm_rssize);
97 def_int(struct kinfo_proc *kp, read_vm_tsize, kp->p_vm_tsize);
98 def_int(struct kinfo_proc *kp, read_vm_dsize, kp->p_vm_dsize);
99 def_int(struct kinfo_proc *kp, read_vm_ssize, kp->p_vm_ssize);
101 static int
102 read_flag(struct kinfo_proc *kp, char *buf, size_t size, off_t off)
104 struct flag {
105 const char *name;
106 uint32_t mask;
107 };
108 static struct flag flags[] = {
109 { .name = "inktr", .mask = P_INKTR, },
110 { .name = "profpend", .mask = P_PROFPEND, },
111 { .name = "alrmpend", .mask = P_ALRMPEND, },
112 { .name = "sigsuspend", .mask = P_SIGSUSPEND, },
113 { .name = "cantsleep", .mask = P_CANTSLEEP, },
114 { .name = "wsleep", .mask = P_WSLEEP, },
115 { .name = "sintr", .mask = P_SINTR, },
116 { .name = "system", .mask = P_SYSTEM, },
117 { .name = "timeout", .mask = P_TIMEOUT, },
118 { .name = "wexit", .mask = P_WEXIT, },
119 { .name = "oweupc", .mask = P_OWEUPC, },
120 { .name = "suspsingle", .mask = P_SUSPSINGLE, },
121 { .name = "continued", .mask = P_CONTINUED, },
122 { .name = "thread", .mask = P_THREAD, },
123 { .name = "suspsig", .mask = P_SUSPSIG, },
124 { .name = "softdep", .mask = P_SOFTDEP, },
125 { .name = "cpupeg", .mask = P_CPUPEG, },
126 { .name = NULL, .mask = 0, },
127 };
128 static char buffer[200];
130 buffer[0] = '\0';
131 for (const struct flag *f = flags; f->name != NULL; ++f) {
132 if ((kp->p_flag & f->mask) == f->mask) {
133 strlcat(buffer, f->name, sizeof (buffer));
134 strlcat(buffer, "\n", sizeof (buffer));
137 return copy_str2(buffer, buf, size, off);
140 static int
141 read_groups(struct kinfo_proc *kp, char *buf, size_t size, off_t off)
143 static char buffer[KI_NGROUPS * 32];
145 buffer[0] = '\0';
147 for (int i = 0; i < kp->p_ngroups; ++i) {
148 char tmp[32];
149 snprintf(tmp, sizeof (tmp), "%u\n", kp->p_groups[i]);
150 strlcat(buffer, tmp, sizeof (buffer));
152 return copy_str2(buffer, buf, size, off);
155 static int
156 read_status(struct kinfo_proc *kp, char *buf, size_t size, off_t off)
158 const char *s;
159 switch (kp->p_stat) {
160 case SIDL: s = "idle"; break;
161 case SRUN: s = "runnable"; break;
162 case SSLEEP: s = "sleeping"; break;
163 case SSTOP: s = "stopped"; break;
164 case SZOMB: s = "zomb"; break; // unused
165 case SDEAD: s = "zombie"; break;
166 case SONPROC: s = "running"; break;
167 default: s = "unknown"; break;
169 return copy_str2(s, buf, size, off);
172 static int
173 read_pledge(struct kinfo_proc *kp, char *buf, size_t size, off_t off)
175 static char buffer[sizeof (pledgenames) / sizeof (*pledgenames) * 16];
177 buffer[0] = '\0';
179 for (int i = 0; pledgenames[i].bits != 0; ++i) {
180 const uint64_t mask = pledgenames[i].bits;
181 if ((kp->p_pledge & mask) == mask) {
182 strlcat(buffer, pledgenames[i].name, sizeof (buffer));
183 strlcat(buffer, "\n", sizeof (buffer));
187 return copy_str2(buffer, buf, size, off);
190 // TODO: argv, envv, fd
192 static struct myfile files[] = {
193 { .name = "/pid", .read = read_pid, },
194 { .name = "/comm", .read = read_comm, },
195 { .name = "/name", .read = read_name, },
196 { .name = "/emul", .read = read_emul, },
197 { .name = "/wmesg", .read = read_wmesg, },
198 { .name = "/login", .read = read_login, },
199 { .name = "/uid", .read = read_uid, },
200 { .name = "/ruid", .read = read_ruid, },
201 { .name = "/gid", .read = read_gid, },
202 { .name = "/rgid", .read = read_rgid, },
203 { .name = "/priority", .read = read_priority, },
204 { .name = "/nice", .read = read_nice, },
205 { .name = "/vm_rssize", .read = read_vm_rssize, },
206 { .name = "/vm_tsize", .read = read_vm_tsize, },
207 { .name = "/vm_dsize", .read = read_vm_dsize, },
208 { .name = "/vm_ssize", .read = read_vm_ssize, },
209 { .name = "/flag", .read = read_flag, },
210 { .name = "/groups", .read = read_groups, },
211 { .name = "/status", .read = read_status, },
212 { .name = "/pledge", .read = read_pledge, },
213 { .name = NULL, .read = NULL, },
214 };
216 static int
217 read_fd_type(struct kinfo_file *f, char *buf, size_t size, off_t off)
219 const char *s;
220 switch (f->f_type) {
221 case DTYPE_VNODE: s = "vnode\n"; break;
222 case DTYPE_SOCKET: s = "socket\n"; break;
223 case DTYPE_PIPE: s = "pipe\n"; break;
224 case DTYPE_KQUEUE: s = "kqueue\n"; break;
225 case DTYPE_DMABUF: s = "dmabuf\n"; break;
226 case DTYPE_SYNC: s = "sync\n"; break;
228 return copy_str2(s, buf, size, off);
230 def_uint(struct kinfo_file *f, read_fd_fd, f->fd_fd);
231 def_uint(struct kinfo_file *f, read_fd_pid, f->p_pid);
232 def_uint(struct kinfo_file *f, read_fd_uid, f->f_uid);
233 def_uint(struct kinfo_file *f, read_fd_gid, f->f_gid);
234 def_str(struct kinfo_file *f, read_fd_comm, f->p_comm, KI_MAXCOMLEN);
236 static struct myfdfile fd_files[] = {
237 { .name = "/type", .read = read_fd_type, },
238 { .name = "/fd", .read = read_fd_fd, },
239 { .name = "/pid", .read = read_fd_pid, },
240 { .name = "/uid", .read = read_fd_uid, },
241 { .name = "/gid", .read = read_fd_gid, },
242 { .name = "/comm", .read = read_fd_comm, },
243 { .name = NULL, .read = NULL, },
244 };