Remove building with NOCRYPTO option
[minix.git] / minix / usr.bin / trace / service / ipc.c
blob7be2a34916eedbdf6e48c5af4032baabdfae2873
1 /* This file is concerned with the IPC server, not with kernel-level IPC. */
3 #include "inc.h"
5 #include <sys/ipc.h>
6 #include <sys/shm.h>
7 #include <sys/sem.h>
9 static void
10 put_key(struct trace_proc * proc, const char * name, key_t key)
13 if (!valuesonly && key == IPC_PRIVATE)
14 put_field(proc, name, "IPC_PRIVATE");
15 else
16 put_value(proc, name, "%ld", key);
19 static const struct flags ipcget_flags[] = {
20 FLAG(IPC_CREAT),
21 FLAG(IPC_EXCL),
24 static int
25 ipc_shmget_out(struct trace_proc * proc, const message * m_out)
28 put_key(proc, "key", m_out->m_lc_ipc_shmget.key);
29 put_value(proc, "size", "%zu", m_out->m_lc_ipc_shmget.size);
30 put_flags(proc, "shmflg", ipcget_flags, COUNT(ipcget_flags), "0%o",
31 m_out->m_lc_ipc_shmget.flag);
33 return CT_DONE;
36 static void
37 ipc_shmget_in(struct trace_proc * proc, const message * __unused m_out,
38 const message * m_in, int failed)
41 if (!failed)
42 put_value(proc, NULL, "%d", m_in->m_lc_ipc_shmget.retid);
43 else
44 put_result(proc);
47 static const struct flags shmat_flags[] = {
48 FLAG(SHM_RDONLY),
49 FLAG(SHM_RND),
52 static int
53 ipc_shmat_out(struct trace_proc * proc, const message * m_out)
56 put_value(proc, "shmid", "%d", m_out->m_lc_ipc_shmat.id);
57 put_ptr(proc, "shmaddr", (vir_bytes)m_out->m_lc_ipc_shmat.addr);
58 put_flags(proc, "shmflg", shmat_flags, COUNT(shmat_flags), "0x%x",
59 m_out->m_lc_ipc_shmat.flag);
61 return CT_DONE;
64 static void
65 ipc_shmat_in(struct trace_proc * proc, const message * __unused m_out,
66 const message * m_in, int failed)
69 if (!failed)
70 put_ptr(proc, NULL, (vir_bytes)m_in->m_lc_ipc_shmat.retaddr);
71 else
72 put_result(proc);
75 static int
76 ipc_shmdt_out(struct trace_proc * proc, const message * m_out)
79 put_ptr(proc, "shmaddr", (vir_bytes)m_out->m_lc_ipc_shmdt.addr);
81 return CT_DONE;
84 static void
85 put_shmctl_cmd(struct trace_proc * proc, const char * name, int cmd)
87 const char *text = NULL;
89 if (!valuesonly) {
90 switch (cmd) {
91 TEXT(IPC_RMID);
92 TEXT(IPC_SET);
93 TEXT(IPC_STAT);
94 TEXT(SHM_STAT);
95 TEXT(SHM_INFO);
96 TEXT(IPC_INFO);
100 if (text != NULL)
101 put_field(proc, name, text);
102 else
103 put_value(proc, name, "%d", cmd);
106 static const struct flags shm_mode_flags[] = {
107 FLAG(SHM_DEST),
108 FLAG(SHM_LOCKED),
111 static void
112 put_struct_shmid_ds(struct trace_proc * proc, const char * name, int flags,
113 vir_bytes addr)
115 struct shmid_ds buf;
116 int set;
118 if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
119 return;
121 /* Is this an IPC_SET call? Then print a small subset of fields.. */
122 set = (flags & PF_ALT);
124 put_open(proc, "shm_perm", 0, "{", ", ");
126 put_value(proc, "uid", "%u", buf.shm_perm.uid);
127 put_value(proc, "gid", "%u", buf.shm_perm.gid);
128 if (!set && verbose > 0) {
129 put_value(proc, "cuid", "%u", buf.shm_perm.cuid);
130 put_value(proc, "cgid", "%u", buf.shm_perm.cgid);
132 put_flags(proc, "mode", shm_mode_flags, COUNT(shm_mode_flags),
133 "0%03o", buf.shm_perm.mode);
135 put_close(proc, "}");
137 if (!set) {
138 put_value(proc, "shm_segsz", "%zu", buf.shm_segsz);
139 if (verbose > 0) {
140 put_value(proc, "shm_lpid", "%d", buf.shm_lpid);
141 put_value(proc, "shm_cpid", "%d", buf.shm_cpid);
142 put_time(proc, "shm_atime", buf.shm_atime);
143 put_time(proc, "shm_dtime", buf.shm_dtime);
144 put_time(proc, "shm_ctime", buf.shm_ctime);
146 put_value(proc, "shm_nattch", "%u", buf.shm_nattch);
149 put_close_struct(proc, set || verbose > 0);
152 static int
153 ipc_shmctl_out(struct trace_proc * proc, const message * m_out)
156 put_value(proc, "shmid", "%d", m_out->m_lc_ipc_shmctl.id);
157 put_shmctl_cmd(proc, "cmd", m_out->m_lc_ipc_shmctl.cmd);
159 /* TODO: add support for the IPC_INFO and SHM_INFO structures.. */
160 switch (m_out->m_lc_ipc_shmctl.cmd) {
161 case IPC_STAT:
162 case SHM_STAT:
163 return CT_NOTDONE;
165 case IPC_SET:
166 put_struct_shmid_ds(proc, "buf", PF_ALT,
167 (vir_bytes)m_out->m_lc_ipc_shmctl.buf);
169 return CT_DONE;
171 default:
172 put_ptr(proc, "buf", (vir_bytes)m_out->m_lc_ipc_shmctl.buf);
174 return CT_DONE;
178 static void
179 ipc_shmctl_in(struct trace_proc * proc, const message * m_out,
180 const message * m_in, int failed)
183 switch (m_out->m_lc_ipc_shmctl.cmd) {
184 case IPC_STAT:
185 case SHM_STAT:
186 put_struct_shmid_ds(proc, "buf", failed,
187 (vir_bytes)m_out->m_lc_ipc_shmctl.buf);
188 put_equals(proc);
190 break;
193 if (!failed) {
194 switch (m_out->m_lc_ipc_shmctl.cmd) {
195 case SHM_INFO:
196 case SHM_STAT:
197 case IPC_INFO:
198 put_value(proc, NULL, "%d", m_in->m_lc_ipc_shmctl.ret);
200 return;
204 put_result(proc);
207 static int
208 ipc_semget_out(struct trace_proc * proc, const message * m_out)
211 put_key(proc, "key", m_out->m_lc_ipc_semget.key);
212 put_value(proc, "nsems", "%d", m_out->m_lc_ipc_semget.nr);
213 put_flags(proc, "semflg", ipcget_flags, COUNT(ipcget_flags), "0%o",
214 m_out->m_lc_ipc_semget.flag);
216 return CT_DONE;
219 static void
220 ipc_semget_in(struct trace_proc * proc, const message * __unused m_out,
221 const message * m_in, int failed)
224 if (!failed)
225 put_value(proc, NULL, "%d", m_in->m_lc_ipc_semget.retid);
226 else
227 put_result(proc);
230 static void
231 put_semctl_cmd(struct trace_proc * proc, const char * name, int cmd)
233 const char *text = NULL;
235 if (!valuesonly) {
236 switch (cmd) {
237 TEXT(IPC_RMID);
238 TEXT(IPC_SET);
239 TEXT(IPC_STAT);
240 TEXT(GETNCNT);
241 TEXT(GETPID);
242 TEXT(GETVAL);
243 TEXT(GETALL);
244 TEXT(GETZCNT);
245 TEXT(SETVAL);
246 TEXT(SETALL);
247 TEXT(SEM_STAT);
248 TEXT(SEM_INFO);
249 TEXT(IPC_INFO);
253 if (text != NULL)
254 put_field(proc, name, text);
255 else
256 put_value(proc, name, "%d", cmd);
259 static void
260 put_struct_semid_ds(struct trace_proc * proc, const char * name, int flags,
261 vir_bytes addr)
263 struct semid_ds buf;
264 int set;
266 if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
267 return;
269 /* Is this an IPC_SET call? Then print a small subset of fields.. */
270 set = (flags & PF_ALT);
272 put_open(proc, "sem_perm", 0, "{", ", ");
274 put_value(proc, "uid", "%u", buf.sem_perm.uid);
275 put_value(proc, "gid", "%u", buf.sem_perm.gid);
276 if (!set && verbose > 0) {
277 put_value(proc, "cuid", "%u", buf.sem_perm.cuid);
278 put_value(proc, "cgid", "%u", buf.sem_perm.cgid);
280 put_value(proc, "mode", "0%03o", buf.sem_perm.mode);
282 put_close(proc, "}");
284 if (!set) {
285 if (verbose > 0) {
286 put_time(proc, "sem_otime", buf.sem_otime);
287 put_time(proc, "sem_ctime", buf.sem_ctime);
289 put_value(proc, "sem_nsems", "%u", buf.sem_nsems);
292 put_close_struct(proc, set || verbose > 0);
296 static int
297 ipc_semctl_out(struct trace_proc * proc, const message * m_out)
300 put_value(proc, "semid", "%d", m_out->m_lc_ipc_semctl.id);
301 put_value(proc, "semnum", "%d", m_out->m_lc_ipc_semctl.num);
302 put_semctl_cmd(proc, "cmd", m_out->m_lc_ipc_semctl.cmd);
304 /* TODO: add support for the IPC_INFO and SEM_INFO structures.. */
305 switch (m_out->m_lc_ipc_semctl.cmd) {
306 case IPC_STAT:
307 case SEM_STAT:
308 return CT_NOTDONE;
310 case IPC_SET:
311 put_struct_semid_ds(proc, "buf", PF_ALT,
312 (vir_bytes)m_out->m_lc_ipc_semctl.opt);
314 return CT_DONE;
316 case IPC_INFO:
317 case SEM_INFO:
318 put_ptr(proc, "buf", (vir_bytes)m_out->m_lc_ipc_semctl.opt);
320 return CT_DONE;
322 case GETALL:
323 case SETALL:
324 put_ptr(proc, "array", (vir_bytes)m_out->m_lc_ipc_semctl.opt);
326 return CT_DONE;
328 case SETVAL:
329 put_value(proc, "val", "%lu", m_out->m_lc_ipc_semctl.opt);
331 return CT_DONE;
333 default:
334 return CT_DONE;
338 static void
339 ipc_semctl_in(struct trace_proc * proc, const message * m_out,
340 const message * m_in, int failed)
343 switch (m_out->m_lc_ipc_semctl.cmd) {
344 case IPC_STAT:
345 case SEM_STAT:
346 put_struct_semid_ds(proc, "buf", failed,
347 (vir_bytes)m_out->m_lc_ipc_semctl.opt);
348 put_equals(proc);
350 break;
353 if (!failed) {
354 switch (m_out->m_lc_ipc_semctl.cmd) {
355 case GETNCNT:
356 case GETPID:
357 case GETVAL:
358 case GETZCNT:
359 case SEM_INFO:
360 case SEM_STAT:
361 case IPC_INFO:
362 put_value(proc, NULL, "%d", m_in->m_lc_ipc_semctl.ret);
363 return;
366 put_result(proc);
369 static const struct flags sem_flags[] = {
370 FLAG(IPC_NOWAIT),
371 FLAG(SEM_UNDO),
374 static void
375 put_struct_sembuf(struct trace_proc * proc, const char * name, int flags,
376 vir_bytes addr)
378 struct sembuf buf;
379 int all;
381 if (!put_open_struct(proc, name, flags, addr, &buf, sizeof(buf)))
382 return;
384 all = FALSE;
385 put_value(proc, "sem_num", "%u", buf.sem_num);
386 put_value(proc, "sem_op", "%d", buf.sem_op);
387 if (verbose > 0 || (buf.sem_flg & ~SEM_UNDO) != 0) {
388 put_flags(proc, "sem_flg", sem_flags, COUNT(sem_flags), "0x%x",
389 buf.sem_flg);
390 all = TRUE;
393 put_close_struct(proc, all);
396 static void
397 put_sembuf_array(struct trace_proc * proc, const char * name, vir_bytes addr,
398 size_t count)
400 struct sembuf buf[SEMOPM]; /* about 600 bytes, so OK for the stack */
401 size_t i;
403 if (valuesonly > 1 || count > SEMOPM ||
404 mem_get_data(proc->pid, addr, &buf, count * sizeof(buf[0])) != 0) {
405 put_ptr(proc, name, addr);
407 return;
410 put_open(proc, name, PF_NONAME, "[", ", ");
411 for (i = 0; i < count; i++)
412 put_struct_sembuf(proc, NULL, PF_LOCADDR, (vir_bytes)&buf[i]);
413 put_close(proc, "]");
416 static int
417 ipc_semop_out(struct trace_proc * proc, const message * m_out)
420 put_value(proc, "semid", "%d", m_out->m_lc_ipc_semop.id);
421 put_sembuf_array(proc, "sops", (vir_bytes)m_out->m_lc_ipc_semop.ops,
422 m_out->m_lc_ipc_semop.size);
423 put_value(proc, "nsops", "%u", m_out->m_lc_ipc_semop.size);
425 return CT_DONE;
428 #define IPC_CALL(c) [((IPC_ ## c) - IPC_BASE)]
430 static const struct call_handler ipc_map[] = {
431 IPC_CALL(SHMGET) = HANDLER("shmget", ipc_shmget_out, ipc_shmget_in),
432 IPC_CALL(SHMAT) = HANDLER("shmat", ipc_shmat_out, ipc_shmat_in),
433 IPC_CALL(SHMDT) = HANDLER("shmdt", ipc_shmdt_out, default_in),
434 IPC_CALL(SHMCTL) = HANDLER("shmctl", ipc_shmctl_out, ipc_shmctl_in),
435 IPC_CALL(SEMGET) = HANDLER("semget", ipc_semget_out, ipc_semget_in),
436 IPC_CALL(SEMCTL) = HANDLER("semctl", ipc_semctl_out, ipc_semctl_in),
437 IPC_CALL(SEMOP) = HANDLER("semop", ipc_semop_out, default_in),
440 const struct calls ipc_calls = {
441 .endpt = ANY,
442 .base = IPC_BASE,
443 .map = ipc_map,
444 .count = COUNT(ipc_map)