xref: /minix3/minix/usr.bin/trace/service/pm.c (revision 7c48de6cc4c6d56f2277d378dba01dbac8a8c3b9)
1 
2 #include "inc.h"
3 
4 #include <signal.h>
5 #include <sys/time.h>
6 #include <sys/wait.h>
7 #include <sys/resource.h>
8 #include <sys/utsname.h>
9 #include <sys/reboot.h>
10 #include <minix/profile.h>
11 
12 static int
13 pm_exit_out(struct trace_proc * proc, const message * m_out)
14 {
15 
16 	put_value(proc, "status", "%d", m_out->m_lc_pm_exit.status);
17 
18 	return CT_NORETURN;
19 }
20 
21 static const struct flags waitpid_options[] = {
22 	FLAG(WNOHANG),
23 	FLAG(WUNTRACED),
24 	FLAG(WALTSIG),
25 	FLAG(WALLSIG),
26 	FLAG(WNOWAIT),
27 	FLAG(WNOZOMBIE),
28 	FLAG(WOPTSCHECKED),
29 };
30 
31 static void
32 put_waitpid_status(struct trace_proc * proc, const char * name, int status)
33 {
34 	const char *signame;
35 	int sig;
36 
37 	/*
38 	 * There is no suitable set of macros to be used here, so we're going
39 	 * to invent our own: W_EXITED, W_SIGNALED, and W_STOPPED.  Hopefully
40 	 * they are sufficiently clear even though they don't actually exist.
41 	 * The code below is downright messy, but it also ensures that no bits
42 	 * are set unexpectedly in the status.
43 	 */
44 	if (!valuesonly && WIFEXITED(status) &&
45 	    status == W_EXITCODE(WEXITSTATUS(status), 0)) {
46 		put_value(proc, name, "W_EXITED(%d)",
47 		    WEXITSTATUS(status));
48 
49 		return;
50 	}
51 
52 	/* WCOREDUMP() actually returns WCOREFLAG or 0, but better safe.. */
53 	if (!valuesonly && WIFSIGNALED(status) && status == (W_EXITCODE(0,
54 	    WTERMSIG(status)) | (WCOREDUMP(status) ? WCOREFLAG : 0))) {
55 		sig = WTERMSIG(status);
56 
57 		if ((signame = get_signal_name(sig)) != NULL)
58 			put_value(proc, name, "W_SIGNALED(%s)", signame);
59 		else
60 			put_value(proc, name, "W_SIGNALED(%u)", sig);
61 
62 		if (WCOREDUMP(status))
63 			put_text(proc, "|WCOREDUMP");
64 
65 		return;
66 	}
67 
68 	if (!valuesonly && WIFSTOPPED(status) &&
69 	    status == W_STOPCODE(WSTOPSIG(status))) {
70 		sig = WSTOPSIG(status);
71 
72 		if ((signame = get_signal_name(sig)) != NULL)
73 			put_value(proc, name, "W_STOPPED(%s)", signame);
74 		else
75 			put_value(proc, name, "W_STOPPED(%u)", sig);
76 
77 		return;
78 	}
79 
80 	/*
81 	 * If we get here, either valuesonly is enabled or the resulting status
82 	 * is not one we recognize, for example because extra bits are set.
83 	 */
84 	put_value(proc, name, "0x%04x", status);
85 }
86 
87 static int
88 pm_waitpid_out(struct trace_proc * proc, const message * m_out)
89 {
90 
91 	put_value(proc, "pid", "%d", m_out->m_lc_pm_waitpid.pid);
92 
93 	return CT_NOTDONE;
94 }
95 
96 static void
97 pm_waitpid_in(struct trace_proc * proc, const message * m_out,
98 	const message * m_in, int failed)
99 {
100 
101 	/*
102 	 * If the result is zero, there is no status to show.  Also, since the
103 	 * status is returned in the result message, we cannot print the user-
104 	 * given pointer.  Instead, upon failure we show "&.." to indicate an
105 	 * unknown pointer.
106 	 */
107 	if (!failed && m_in->m_type > 0)
108 		put_waitpid_status(proc, "status",
109 		    m_in->m_pm_lc_waitpid.status);
110 	else
111 		put_field(proc, "status", "&..");
112 	put_flags(proc, "options", waitpid_options, COUNT(waitpid_options),
113 	    "0x%x", m_out->m_lc_pm_waitpid.options);
114 	put_equals(proc);
115 	put_result(proc);
116 }
117 
118 static void
119 pm_getpid_in(struct trace_proc * proc, const message * __unused m_out,
120 	const message * m_in, int failed)
121 {
122 
123 	put_result(proc);
124 	if (!failed) {
125 		put_open(proc, NULL, 0, "(", ", ");
126 		put_value(proc, "ppid", "%d", m_in->m_pm_lc_getpid.parent_pid);
127 		put_close(proc, ")");
128 	}
129 }
130 
131 /* This function is shared between setuid and seteuid. */
132 static int
133 pm_setuid_out(struct trace_proc * proc, const message * m_out)
134 {
135 
136 	put_value(proc, "uid", "%u", m_out->m_lc_pm_setuid.uid);
137 
138 	return CT_DONE;
139 }
140 
141 static void
142 pm_getuid_in(struct trace_proc * proc, const message * __unused m_out,
143 	const message * m_in, int failed)
144 {
145 
146 	put_result(proc);
147 	if (!failed) {
148 		put_open(proc, NULL, 0, "(", ", ");
149 		put_value(proc, "euid", "%u", m_in->m_pm_lc_getuid.euid);
150 		put_close(proc, ")");
151 	}
152 }
153 
154 static int
155 pm_stime_out(struct trace_proc * proc, const message * m_out)
156 {
157 
158 	put_time(proc, "time", m_out->m_lc_pm_time.sec);
159 
160 	return CT_DONE;
161 }
162 
163 static void
164 put_signal(struct trace_proc * proc, const char * name, int sig)
165 {
166 	const char *signame;
167 
168 	if (!valuesonly && (signame = get_signal_name(sig)) != NULL)
169 		put_field(proc, name, signame);
170 	else
171 		put_value(proc, name, "%d", sig);
172 }
173 
174 static void
175 put_ptrace_req(struct trace_proc * proc, const char * name, int req)
176 {
177 	const char *text = NULL;
178 
179 	if (!valuesonly) {
180 		switch (req) {
181 		TEXT(T_STOP);
182 		TEXT(T_OK);
183 		TEXT(T_ATTACH);
184 		TEXT(T_DETACH);
185 		TEXT(T_RESUME);
186 		TEXT(T_STEP);
187 		TEXT(T_SYSCALL);
188 		TEXT(T_EXIT);
189 		TEXT(T_GETINS);
190 		TEXT(T_GETDATA);
191 		TEXT(T_GETUSER);
192 		TEXT(T_SETINS);
193 		TEXT(T_SETDATA);
194 		TEXT(T_SETUSER);
195 		TEXT(T_SETOPT);
196 		TEXT(T_GETRANGE);
197 		TEXT(T_SETRANGE);
198 		TEXT(T_READB_INS);
199 		TEXT(T_WRITEB_INS);
200 		}
201 	}
202 
203 	if (text != NULL)
204 		put_field(proc, name, text);
205 	else
206 		put_value(proc, name, "%d", req);
207 }
208 
209 static void
210 put_struct_ptrace_range(struct trace_proc * proc, const char * name, int flags,
211 	vir_bytes addr)
212 {
213 	struct ptrace_range pr;
214 
215 	if (!put_open_struct(proc, name, flags, addr, &pr, sizeof(pr)))
216 		return;
217 
218 	if (!valuesonly && pr.pr_space == TS_INS)
219 		put_field(proc, "pr_space", "TS_INS");
220 	else if (!valuesonly && pr.pr_space == TS_DATA)
221 		put_field(proc, "pr_space", "TS_DATA");
222 	else
223 		put_value(proc, "pr_space", "%d", pr.pr_space);
224 	put_value(proc, "pr_addr", "0x%lx", pr.pr_addr);
225 	put_ptr(proc, "pr_ptr", (vir_bytes)pr.pr_ptr);
226 	put_value(proc, "pr_size", "%zu", pr.pr_size);
227 
228 	put_close_struct(proc, TRUE /*all*/);
229 }
230 
231 static int
232 pm_ptrace_out(struct trace_proc * proc, const message * m_out)
233 {
234 
235 	put_ptrace_req(proc, "req", m_out->m_lc_pm_ptrace.req);
236 	put_value(proc, "pid", "%d", m_out->m_lc_pm_ptrace.pid);
237 
238 	switch (m_out->m_lc_pm_ptrace.req) {
239 	case T_GETINS:
240 	case T_GETDATA:
241 	case T_GETUSER:
242 	case T_READB_INS:
243 		put_value(proc, "addr", "0x%lx", m_out->m_lc_pm_ptrace.addr);
244 		put_value(proc, "data", "%ld", m_out->m_lc_pm_ptrace.data);
245 		break;
246 	case T_SETINS:
247 	case T_SETDATA:
248 	case T_SETUSER:
249 	case T_WRITEB_INS:
250 		put_value(proc, "addr", "0x%lx", m_out->m_lc_pm_ptrace.addr);
251 		put_value(proc, "data", "0x%lx", m_out->m_lc_pm_ptrace.data);
252 		break;
253 	case T_RESUME:
254 	case T_STEP:
255 	case T_SYSCALL:
256 		put_value(proc, "addr", "%ld", m_out->m_lc_pm_ptrace.addr);
257 		put_signal(proc, "data", m_out->m_lc_pm_ptrace.data);
258 		break;
259 	case T_GETRANGE:
260 	case T_SETRANGE:
261 		put_struct_ptrace_range(proc, "addr", 0,
262 		    m_out->m_lc_pm_ptrace.addr);
263 		put_value(proc, "data", "%ld", m_out->m_lc_pm_ptrace.data);
264 		break;
265 	default:
266 		put_value(proc, "addr", "%ld", m_out->m_lc_pm_ptrace.addr);
267 		put_value(proc, "data", "%ld", m_out->m_lc_pm_ptrace.data);
268 		break;
269 	}
270 
271 	return CT_DONE;
272 }
273 
274 static void
275 pm_ptrace_in(struct trace_proc * proc, const message * m_out,
276 	const message * m_in, int failed)
277 {
278 
279 	if (!failed) {
280 		switch (m_out->m_lc_pm_ptrace.req) {
281 		case T_GETINS:
282 		case T_GETDATA:
283 		case T_GETUSER:
284 		case T_READB_INS:
285 			put_value(proc, NULL, "0x%lx",
286 			    m_in->m_pm_lc_ptrace.data);
287 			return;
288 		}
289 	}
290 
291 	put_result(proc);
292 }
293 
294 void
295 put_groups(struct trace_proc * proc, const char * name, int flags,
296 	vir_bytes addr, int count)
297 {
298 	gid_t groups[NGROUPS_MAX];
299 	int i;
300 
301 	if ((flags & PF_FAILED) || valuesonly || count < 0 ||
302 	    count > NGROUPS_MAX || (count > 0 && mem_get_data(proc->pid, addr,
303 	    groups, count * sizeof(groups[0])) < 0)) {
304 		if (flags & PF_LOCADDR)
305 			put_field(proc, name, "&..");
306 		else
307 			put_ptr(proc, name, addr);
308 
309 		return;
310 	}
311 
312 	put_open(proc, name, PF_NONAME, "[", ", ");
313 	for (i = 0; i < count; i++)
314 		put_value(proc, NULL, "%u", groups[i]);
315 	put_close(proc, "]");
316 }
317 
318 static int
319 pm_setgroups_out(struct trace_proc * proc, const message * m_out)
320 {
321 
322 	put_value(proc, "ngroups", "%d", m_out->m_lc_pm_groups.num);
323 	put_groups(proc, "grouplist", 0, m_out->m_lc_pm_groups.ptr,
324 	    m_out->m_lc_pm_groups.num);
325 
326 	return CT_DONE;
327 }
328 
329 static int
330 pm_getgroups_out(struct trace_proc * proc, const message * m_out)
331 {
332 
333 	put_value(proc, "ngroups", "%d", m_out->m_lc_pm_groups.num);
334 
335 	return CT_NOTDONE;
336 }
337 
338 static void
339 pm_getgroups_in(struct trace_proc * proc, const message * m_out,
340 	const message * m_in, int failed)
341 {
342 
343 	put_groups(proc, "grouplist", failed, m_out->m_lc_pm_groups.ptr,
344 	    m_in->m_type);
345 	put_equals(proc);
346 	put_result(proc);
347 }
348 
349 static int
350 pm_kill_out(struct trace_proc * proc, const message * m_out)
351 {
352 
353 	put_value(proc, "pid", "%d", m_out->m_lc_pm_sig.pid);
354 	put_signal(proc, "sig", m_out->m_lc_pm_sig.nr);
355 
356 	return CT_DONE;
357 }
358 
359 /* This function is shared between setgid and setegid. */
360 static int
361 pm_setgid_out(struct trace_proc * proc, const message * m_out)
362 {
363 
364 	put_value(proc, "gid", "%u", m_out->m_lc_pm_setgid.gid);
365 
366 	return CT_DONE;
367 }
368 
369 static void
370 pm_getgid_in(struct trace_proc * proc, const message * __unused m_out,
371 	const message * m_in, int failed)
372 {
373 
374 	put_result(proc);
375 	if (!failed) {
376 		put_open(proc, NULL, 0, "(", ", ");
377 		put_value(proc, "egid", "%u", m_in->m_pm_lc_getgid.egid);
378 		put_close(proc, ")");
379 	}
380 }
381 
382 static int
383 put_frame_string(struct trace_proc * proc, vir_bytes frame, size_t len,
384 	vir_bytes addr)
385 {
386 	vir_bytes stacktop, offset;
387 
388 	/*
389 	 * The addresses in the frame assume that the process has already been
390 	 * changed, and the top of the frame is now located at the new process
391 	 * stack top, which is a hardcoded system-global value.  In order to
392 	 * print the strings, we must convert back each address to its location
393 	 * within the given frame.
394 	 */
395 	stacktop = kernel_get_stacktop();
396 
397 	if (addr >= stacktop)
398 		return FALSE;
399 	offset = stacktop - addr;
400 	if (offset >= len)
401 		return FALSE;
402 	addr = frame + len - offset;
403 
404 	/*
405 	 * TODO: while using put_buf() is highly convenient, it does require at
406 	 * least one copy operation per printed string.  The strings are very
407 	 * likely to be consecutive in memory, so copying in larger chunks at
408 	 * once would be preferable.  Also, if copying from the frame fails,
409 	 * put_buf() will print the string address as we corrected it above,
410 	 * rather than the address as found in the frame.  A copy failure would
411 	 * always be a case of malice on the traced process's behalf, though.
412 	 */
413 	put_buf(proc, NULL, PF_STRING, addr, len - offset);
414 
415 	return TRUE;
416 }
417 
418 /*
419  * Print the contents of the exec frame, which includes both pointers and
420  * actual string data for the arguments and environment variables to be used.
421  * Even though we know that the entire frame is not going to exceed ARG_MAX
422  * bytes, this is too large a size for a static buffer, and we'd like to avoid
423  * allocating large dynamic buffers as well.  The situation is complicated by
424  * the fact that any string in the frame may run up to the end of the frame.
425  */
426 static void
427 put_exec_frame(struct trace_proc * proc, vir_bytes addr, size_t len)
428 {
429 	void *argv[64];
430 	size_t off, chunk;
431 	unsigned int i, count, max, argv_max, envp_max;
432 	int first, ok, nulls;
433 
434 	if (valuesonly) {
435 		put_ptr(proc, "frame", addr);
436 		put_value(proc, "framelen", "%zu", len);
437 
438 		return;
439 	}
440 
441 	if (verbose == 0) {
442 		argv_max = 16;
443 		envp_max = 0;
444 	} else if (verbose == 1)
445 		argv_max = envp_max = 64;
446 	else
447 		argv_max = envp_max = INT_MAX;
448 
449 	off = sizeof(int); /* skip 'argc' at the start of the frame */
450 	first = TRUE;
451 	ok = TRUE;
452 	nulls = 0;
453 	count = 0;
454 	max = argv_max;
455 
456 	do {
457 		chunk = sizeof(argv);
458 		if (chunk > len - off)
459 			chunk = len - off;
460 
461 		if (mem_get_data(proc->pid, addr + off, argv, chunk) != 0)
462 			break;
463 
464 		if (first) {
465 			put_open(proc, "argv", PF_NONAME, "[", ", ");
466 
467 			first = FALSE;
468 		}
469 
470 		for (i = 0; i < chunk / sizeof(void *) && ok; i++) {
471 			if (argv[i] == NULL) {
472 				if (count > max)
473 					put_tail(proc, count, max);
474 				put_close(proc, "]");
475 				if (nulls++ == 0) {
476 					put_open(proc, "envp", PF_NONAME, "[",
477 					    ", ");
478 					count = 0;
479 					max = envp_max;
480 				} else
481 					break; /* two NULL pointers: done! */
482 			} else if (count++ < max)
483 				ok = put_frame_string(proc, addr, len,
484 				    (vir_bytes)argv[i]);
485 		}
486 
487 		off += chunk;
488 	} while (nulls < 2 && ok);
489 
490 	/*
491 	 * Handle failure cases, implied by not reaching the second NULL
492 	 * in the array.  Successful completion is handled in the loop above.
493 	 * Note that 'ok' is not always cleared on failure, as it is used only
494 	 * to break out of the outer loop.
495 	 */
496 	if (first) {
497 		put_ptr(proc, "argv", addr + off);
498 		put_field(proc, "envp", "&..");
499 	} else if (nulls < 2) {
500 		put_tail(proc, 0, 0);
501 		put_close(proc, "]");
502 		if (nulls < 1) {
503 			put_open(proc, "envp", PF_NONAME, "[", ", ");
504 			put_tail(proc, 0, 0);
505 			put_close(proc, "]");
506 		}
507 	}
508 }
509 
510 static int
511 pm_exec_out(struct trace_proc * proc, const message * m_out)
512 {
513 
514 	put_buf(proc, "path", PF_PATH, m_out->m_lc_pm_exec.name,
515 	    m_out->m_lc_pm_exec.namelen);
516 	put_exec_frame(proc, m_out->m_lc_pm_exec.frame,
517 	    m_out->m_lc_pm_exec.framelen);
518 
519 	return CT_NORETURN;
520 }
521 
522 /* The idea is that this function may one day print a human-readable time. */
523 void
524 put_time(struct trace_proc * proc, const char * name, time_t time)
525 {
526 
527 	put_value(proc, name, "%"PRId64, time);
528 }
529 
530 void
531 put_struct_timeval(struct trace_proc * proc, const char * name, int flags,
532 	vir_bytes addr)
533 {
534 	struct timeval tv;
535 
536 	/* No field names; they just make things harder to read. */
537 	if (!put_open_struct(proc, name, flags | PF_NONAME, addr, &tv,
538 	    sizeof(tv)))
539 		return;
540 
541 	if (flags & PF_ALT)
542 		put_time(proc, "tv_sec", tv.tv_sec);
543 	else
544 		put_value(proc, "tv_sec", "%"PRId64, tv.tv_sec);
545 	put_value(proc, "tv_usec", "%d", tv.tv_usec);
546 
547 	put_close_struct(proc, TRUE /*all*/);
548 }
549 
550 static void
551 put_struct_itimerval(struct trace_proc * proc, const char * name, int flags,
552 	vir_bytes addr)
553 {
554 	struct itimerval it;
555 
556 	/*
557 	 * This used to pass PF_NONAME, but the layout may not be clear enough
558 	 * without names.  It does turn simple alarm(1) calls into rather
559 	 * lengthy output, though.
560 	 */
561 	if (!put_open_struct(proc, name, flags, addr, &it, sizeof(it)))
562 		return;
563 
564 	put_struct_timeval(proc, "it_interval", PF_LOCADDR,
565 	    (vir_bytes)&it.it_interval);
566 	put_struct_timeval(proc, "it_value", PF_LOCADDR,
567 	    (vir_bytes)&it.it_value);
568 
569 	put_close_struct(proc, TRUE /*all*/);
570 }
571 
572 static void
573 put_itimer_which(struct trace_proc * proc, const char * name, int which)
574 {
575 	const char *text = NULL;
576 
577 	if (!valuesonly) {
578 		switch (which) {
579 		TEXT(ITIMER_REAL);
580 		TEXT(ITIMER_VIRTUAL);
581 		TEXT(ITIMER_PROF);
582 		TEXT(ITIMER_MONOTONIC);
583 		}
584 	}
585 
586 	if (text != NULL)
587 		put_field(proc, name, text);
588 	else
589 		put_value(proc, name, "%d", which);
590 }
591 
592 static const char *
593 pm_itimer_name(const message * m_out)
594 {
595 
596 	return (m_out->m_lc_pm_itimer.value != 0) ? "setitimer" : "getitimer";
597 }
598 
599 static int
600 pm_itimer_out(struct trace_proc * proc, const message * m_out)
601 {
602 
603 	put_itimer_which(proc, "which", m_out->m_lc_pm_itimer.which);
604 	if (m_out->m_lc_pm_itimer.value != 0) {
605 		put_struct_itimerval(proc, "value", 0,
606 		    m_out->m_lc_pm_itimer.value);
607 
608 		/*
609 		 * If there will be no old values to print, finish the call
610 		 * now.  For setitimer only; getitimer may not pass NULL.
611 		 */
612 		if (m_out->m_lc_pm_itimer.ovalue == 0) {
613 			put_ptr(proc, "ovalue", 0);
614 
615 			return CT_DONE;
616 		}
617 	}
618 
619 	return CT_NOTDONE;
620 }
621 
622 static void
623 pm_itimer_in(struct trace_proc * proc, const message * m_out,
624 	const message * __unused m_in, int failed)
625 {
626 
627 	if (m_out->m_lc_pm_itimer.value == 0 ||
628 	    m_out->m_lc_pm_itimer.ovalue != 0) {
629 		put_struct_itimerval(proc,
630 		    (m_out->m_lc_pm_itimer.value != 0) ? "ovalue" : "value",
631 		    failed, m_out->m_lc_pm_itimer.ovalue);
632 		put_equals(proc);
633 	}
634 	put_result(proc);
635 }
636 
637 static void
638 put_struct_mcontext(struct trace_proc * proc, const char * name, int flags,
639 	vir_bytes addr)
640 {
641 	mcontext_t ctx;
642 
643 	if (!put_open_struct(proc, name, flags, addr, &ctx, sizeof(ctx)))
644 		return;
645 
646 	/*
647 	 * TODO: print actual fields.  Then again, the ones that are saved and
648 	 * restored (FPU state) are hardly interesting enough to print..
649 	 */
650 
651 	put_close_struct(proc, FALSE /*all*/);
652 }
653 
654 static int
655 pm_getmcontext_out(struct trace_proc * proc, const message * m_out)
656 {
657 
658 	return CT_NOTDONE;
659 }
660 
661 static void
662 pm_getmcontext_in(struct trace_proc * proc, const message * m_out,
663 	const message * m_in, int failed)
664 {
665 
666 	put_struct_mcontext(proc, "mcp", failed, m_out->m_lc_pm_mcontext.ctx);
667 	put_equals(proc);
668 	put_result(proc);
669 }
670 
671 static int
672 pm_setmcontext_out(struct trace_proc * proc, const message * m_out)
673 {
674 
675 	put_struct_mcontext(proc, "mcp", 0, m_out->m_lc_pm_mcontext.ctx);
676 
677 	return CT_DONE;
678 }
679 
680 static void
681 put_sigset(struct trace_proc * proc, const char * name, sigset_t set)
682 {
683 	const char *signame;
684 	unsigned int count, unknown;
685 	int sig, invert;
686 
687 	/*
688 	 * First decide whether we should print a normal or an inverted mask.
689 	 * Unfortunately, depending on the place, a filled set may or may not
690 	 * have bits outside the 1..NSIG range set.  Therefore, we ignore the
691 	 * bits outside this range entirely, and use simple heuristics to
692 	 * decide whether to show an inverted set.  If we know all the signal
693 	 * names for either set and not the other, show that one; otherwise,
694 	 * show an inverted mask if at least 3/4th of the bits are set.
695 	 */
696 	count = 0;
697 	unknown = 0;
698 	for (sig = 1; sig < NSIG; sig++) {
699 		if (sigismember(&set, sig))
700 			count++;
701 		if (get_signal_name(sig) == NULL)
702 			unknown |= 1 << !!sigismember(&set, sig);
703 	}
704 	if (unknown == 1 /*for unset bit*/ || unknown == 2 /*for set bit*/)
705 		invert = unknown - 1;
706 	else
707 		invert = (count >= (NSIG - 1) * 3 / 4);
708 
709 	put_open(proc, name, PF_NONAME, invert ? "~[" : "[", " ");
710 
711 	for (sig = 1; sig < NSIG; sig++) {
712 		/* Note that sigismember() may not strictly return 0 or 1.. */
713 		if (!sigismember(&set, sig) != invert)
714 			continue;
715 
716 		if ((signame = get_signal_name(sig)) != NULL) {
717 			/* Skip the "SIG" prefix for brevity. */
718 			if (!strncmp(signame, "SIG", 3))
719 				put_field(proc, NULL, &signame[3]);
720 			else
721 				put_field(proc, NULL, signame);
722 		} else
723 			put_value(proc, NULL, "%d", sig);
724 	}
725 
726 	put_close(proc, "]");
727 }
728 
729 static const struct flags sa_flags[] = {
730 	FLAG(SA_ONSTACK),
731 	FLAG(SA_RESTART),
732 	FLAG(SA_RESETHAND),
733 	FLAG(SA_NODEFER),
734 	FLAG(SA_NOCLDSTOP),
735 	FLAG(SA_NOCLDWAIT),
736 #ifdef SA_SIGINFO
737 	FLAG(SA_SIGINFO),
738 #endif
739 	FLAG(SA_NOKERNINFO)
740 };
741 
742 static void
743 put_sa_handler(struct trace_proc * proc, const char * name, vir_bytes handler)
744 {
745 	const char *text = NULL;
746 
747 	if (!valuesonly) {
748 		switch ((int)handler) {
749 		case (int)SIG_DFL: text = "SIG_DFL"; break;
750 		case (int)SIG_IGN: text = "SIG_IGN"; break;
751 		case (int)SIG_HOLD: text = "SIG_HOLD"; break;
752 		}
753 	}
754 
755 	if (text != NULL)
756 		put_field(proc, name, text);
757 	else
758 		put_ptr(proc, name, handler);
759 }
760 
761 static void
762 put_struct_sigaction(struct trace_proc * proc, const char * name, int flags,
763 	vir_bytes addr)
764 {
765 	struct sigaction sa;
766 
767 	if (!put_open_struct(proc, name, flags, addr, &sa, sizeof(sa)))
768 		return;
769 
770 	put_sa_handler(proc, "sa_handler", (vir_bytes)sa.sa_handler);
771 
772 	if (verbose > 1)
773 		put_sigset(proc, "sa_mask", sa.sa_mask);
774 
775 	/* A somewhat lame attempt to reduce noise a bit. */
776 	if ((sa.sa_flags & ~(SA_ONSTACK | SA_RESTART | SA_RESETHAND |
777 	    SA_NODEFER)) != 0 || sa.sa_handler != SIG_DFL || verbose > 0)
778 		put_flags(proc, "sa_flags", sa_flags, COUNT(sa_flags), "0x%x",
779 		    sa.sa_flags);
780 
781 	put_close_struct(proc, verbose > 1);
782 }
783 
784 static int
785 pm_sigaction_out(struct trace_proc * proc, const message * m_out)
786 {
787 
788 	put_signal(proc, "signal", m_out->m_lc_pm_sig.nr);
789 	put_struct_sigaction(proc, "act", 0, m_out->m_lc_pm_sig.act);
790 
791 	/* If there will be no old values to print, finish the call now. */
792 	if (m_out->m_lc_pm_sig.oact == 0) {
793 		put_ptr(proc, "oact", 0);
794 		return CT_DONE;
795 	} else
796 		return CT_NOTDONE;
797 }
798 
799 static void
800 pm_sigaction_in(struct trace_proc * proc, const message * m_out,
801 	const message * __unused m_in, int failed)
802 {
803 
804 	if (m_out->m_lc_pm_sig.oact != 0) {
805 		put_struct_sigaction(proc, "oact", failed,
806 		    m_out->m_lc_pm_sig.oact);
807 		put_equals(proc);
808 	}
809 	put_result(proc);
810 }
811 
812 static int
813 pm_sigsuspend_out(struct trace_proc * proc, const message * m_out)
814 {
815 
816 	put_sigset(proc, "set", m_out->m_lc_pm_sigset.set);
817 
818 	return CT_DONE;
819 }
820 
821 static int
822 pm_sigpending_out(struct trace_proc * __unused proc,
823 	const message * __unused m_out)
824 {
825 
826 	return CT_NOTDONE;
827 }
828 
829 static void
830 pm_sigpending_in(struct trace_proc * proc, const message * __unused m_out,
831 	const message * m_in, int failed)
832 {
833 
834 	if (!failed)
835 		put_sigset(proc, "set", m_in->m_pm_lc_sigset.set);
836 	else
837 		put_field(proc, "set", "&..");
838 	put_equals(proc);
839 	put_result(proc);
840 }
841 
842 static void
843 put_sigprocmask_how(struct trace_proc * proc, const char * name, int how)
844 {
845 	const char *text = NULL;
846 
847 	if (!valuesonly) {
848 		switch (how) {
849 		case SIG_INQUIRE: /* pseudocode, print something else */
850 		TEXT(SIG_BLOCK);
851 		TEXT(SIG_UNBLOCK);
852 		TEXT(SIG_SETMASK);
853 		}
854 	}
855 
856 	if (text != NULL)
857 		put_field(proc, name, text);
858 	else
859 		put_value(proc, name, "%d", how);
860 }
861 
862 static int
863 pm_sigprocmask_out(struct trace_proc * proc, const message * m_out)
864 {
865 
866 	put_sigprocmask_how(proc, "how", m_out->m_lc_pm_sigset.how);
867 	if (m_out->m_lc_pm_sigset.how == SIG_INQUIRE)
868 		put_ptr(proc, "set", 0);
869 	else
870 		put_sigset(proc, "set", m_out->m_lc_pm_sigset.set);
871 
872 	return CT_NOTDONE;
873 }
874 
875 static void
876 pm_sigprocmask_in(struct trace_proc * proc, const message * __unused m_out,
877 	const message * m_in, int failed)
878 {
879 
880 	if (!failed)
881 		put_sigset(proc, "oset", m_in->m_pm_lc_sigset.set);
882 	else
883 		put_field(proc, "oset", "&..");
884 	put_equals(proc);
885 	put_result(proc);
886 }
887 
888 static int
889 pm_sigreturn_out(struct trace_proc * proc, const message * m_out)
890 {
891 	struct sigcontext scp;
892 
893 	if (put_open_struct(proc, "scp", 0, m_out->m_lc_pm_sigset.ctx, &scp,
894 	    sizeof(scp))) {
895 		if (verbose == 1) {
896 #if defined(__i386__)
897 			put_ptr(proc, "sc_eip", scp.sc_eip);
898 			put_ptr(proc, "sc_esp", scp.sc_esp);
899 #elif defined(__arm__)
900 			put_ptr(proc, "sc_pc", scp.sc_pc);
901 			put_ptr(proc, "sc_usr_sp", scp.sc_usr_sp);
902 #endif
903 		}
904 
905 		/*
906 		 * We deliberately print the signal set from the message rather
907 		 * than from the structure, since in theory they may be
908 		 * different and PM uses the one from the message only.
909 		 */
910 		put_sigset(proc, "sc_mask", m_out->m_lc_pm_sigset.set);
911 
912 		/*
913 		 * TODO: print some other fields, although it is probably not
914 		 * useful to print all registers even with verbose > 1?
915 		 */
916 		put_close_struct(proc, FALSE /*all*/);
917 	}
918 
919 	return CT_NORETURN;
920 }
921 
922 static void
923 pm_sigreturn_in(struct trace_proc * proc, const message * __unused m_out,
924 	const message * __unused m_in, int failed)
925 {
926 
927 	if (failed) {
928 		put_equals(proc);
929 		put_result(proc);
930 	}
931 }
932 
933 static void
934 put_sysuname_field(struct trace_proc * proc, const char * name, int field)
935 {
936 	const char *text = NULL;
937 
938 	if (!valuesonly) {
939 		switch (field) {
940 		TEXT(_UTS_ARCH);
941 		TEXT(_UTS_KERNEL);
942 		TEXT(_UTS_MACHINE);
943 		TEXT(_UTS_HOSTNAME);
944 		TEXT(_UTS_NODENAME);
945 		TEXT(_UTS_RELEASE);
946 		TEXT(_UTS_VERSION);
947 		TEXT(_UTS_SYSNAME);
948 		TEXT(_UTS_BUS);
949 		}
950 	}
951 
952 	if (text != NULL)
953 		put_field(proc, name, text);
954 	else
955 		put_value(proc, name, "%d", field);
956 }
957 
958 static int
959 pm_sysuname_out(struct trace_proc * proc, const message * m_out)
960 {
961 
962 	if (!valuesonly && m_out->m_lc_pm_sysuname.req == _UTS_GET)
963 		put_field(proc, "req", "_UTS_GET");
964 	else if (!valuesonly && m_out->m_lc_pm_sysuname.req == _UTS_SET)
965 		put_field(proc, "req", "_UTS_SET");
966 	else
967 		put_value(proc, "req", "%d", m_out->m_lc_pm_sysuname.req);
968 	put_sysuname_field(proc, "field", m_out->m_lc_pm_sysuname.field);
969 
970 	if (m_out->m_lc_pm_sysuname.req == _UTS_GET)
971 		return CT_NOTDONE;
972 
973 	put_buf(proc, "value", PF_STRING, m_out->m_lc_pm_sysuname.value,
974 	    m_out->m_lc_pm_sysuname.len);
975 	put_value(proc, "len", "%zu", m_out->m_lc_pm_sysuname.len);
976 	return CT_DONE;
977 }
978 
979 static void
980 pm_sysuname_in(struct trace_proc * proc, const message * m_out,
981 	const message * m_in, int failed)
982 {
983 
984 	if (m_out->m_lc_pm_sysuname.req == _UTS_GET) {
985 		put_buf(proc, "value", failed | PF_STRING,
986 		    m_out->m_lc_pm_sysuname.value, m_in->m_type);
987 		put_value(proc, "len", "%zu", m_out->m_lc_pm_sysuname.len);
988 		put_equals(proc);
989 	}
990 	put_result(proc);
991 }
992 
993 static void
994 put_priority_which(struct trace_proc * proc, const char * name, int which)
995 {
996 	const char *text = NULL;
997 
998 	if (!valuesonly) {
999 		switch (which) {
1000 		TEXT(PRIO_PROCESS);
1001 		TEXT(PRIO_PGRP);
1002 		TEXT(PRIO_USER);
1003 		}
1004 	}
1005 
1006 	if (text != NULL)
1007 		put_field(proc, name, text);
1008 	else
1009 		put_value(proc, name, "%d", which);
1010 }
1011 
1012 static int
1013 pm_getpriority_out(struct trace_proc * proc, const message * m_out)
1014 {
1015 
1016 	put_priority_which(proc, "which", m_out->m_lc_pm_priority.which);
1017 	put_value(proc, "who", "%d", m_out->m_lc_pm_priority.who);
1018 
1019 	return CT_DONE;
1020 }
1021 
1022 static void
1023 pm_getpriority_in(struct trace_proc * proc, const message * __unused m_out,
1024 	const message * m_in, int failed)
1025 {
1026 
1027 	if (!failed)
1028 		put_value(proc, NULL, "%d", m_in->m_type + PRIO_MIN);
1029 	else
1030 		put_result(proc);
1031 }
1032 
1033 static int
1034 pm_setpriority_out(struct trace_proc * proc, const message * m_out)
1035 {
1036 
1037 	put_priority_which(proc, "which", m_out->m_lc_pm_priority.which);
1038 	put_value(proc, "who", "%d", m_out->m_lc_pm_priority.who);
1039 	put_value(proc, "prio", "%d", m_out->m_lc_pm_priority.prio);
1040 
1041 	return CT_DONE;
1042 }
1043 
1044 static int
1045 pm_gettimeofday_out(struct trace_proc * __unused proc,
1046 	const message * __unused m_out)
1047 {
1048 
1049 	return CT_NOTDONE;
1050 }
1051 
1052 static void
1053 put_timespec_as_timeval(struct trace_proc * proc, const char * name,
1054 	time_t sec, long nsec)
1055 {
1056 
1057 	/* No field names within the structure. */
1058 	put_open(proc, name, PF_NONAME, "{", ", ");
1059 
1060 	put_time(proc, "tv_sec", sec);
1061 	put_value(proc, "tv_usec", "%ld", nsec / 1000);
1062 
1063 	put_close(proc, "}");
1064 }
1065 
1066 static void
1067 pm_gettimeofday_in(struct trace_proc * proc, const message * __unused m_out,
1068 	const message * m_in, int failed)
1069 {
1070 
1071 	if (!failed) {
1072 		/*
1073 		 * The system call returns values which do not match the call
1074 		 * being made, so just like libc, we have to correct..
1075 		 */
1076 		put_timespec_as_timeval(proc, "tp", m_in->m_pm_lc_time.sec,
1077 		    m_in->m_pm_lc_time.nsec);
1078 	} else
1079 		put_field(proc, "tp", "&..");
1080 	put_ptr(proc, "tzp", 0); /* not part of the system call (yet) */
1081 
1082 	put_equals(proc);
1083 	put_result(proc);
1084 }
1085 
1086 static int
1087 pm_getsid_out(struct trace_proc * proc, const message * m_out)
1088 {
1089 
1090 	put_value(proc, "pid", "%d", m_out->m_lc_pm_getsid.pid);
1091 
1092 	return CT_DONE;
1093 }
1094 
1095 static void
1096 put_clockid(struct trace_proc * proc, const char * name, clockid_t clock_id)
1097 {
1098 	const char *text = NULL;
1099 
1100 	if (!valuesonly) {
1101 		switch (clock_id) {
1102 		TEXT(CLOCK_REALTIME);
1103 #ifdef CLOCK_VIRTUAL
1104 		TEXT(CLOCK_VIRTUAL);
1105 #endif
1106 #ifdef CLOCK_PROF
1107 		TEXT(CLOCK_PROF);
1108 #endif
1109 		TEXT(CLOCK_MONOTONIC);
1110 		}
1111 	}
1112 
1113 	if (text != NULL)
1114 		put_field(proc, name, text);
1115 	else
1116 		put_value(proc, name, "%d", clock_id);
1117 }
1118 
1119 static void
1120 put_clock_timespec(struct trace_proc * proc, const char * name, int flags,
1121 	time_t sec, long nsec)
1122 {
1123 
1124 	if (flags & PF_FAILED) {
1125 		put_field(proc, name, "&..");
1126 
1127 		return;
1128 	}
1129 
1130 	/* No field names within the structure. */
1131 	put_open(proc, name, PF_NONAME, "{", ", ");
1132 
1133 	if (flags & PF_ALT)
1134 		put_time(proc, "tv_sec", sec);
1135 	else
1136 		put_value(proc, "tv_sec", "%"PRId64, sec);
1137 	put_value(proc, "tv_nsec", "%ld", nsec);
1138 
1139 	put_close(proc, "}");
1140 }
1141 
1142 /* This function is shared between clock_getres and clock_gettime. */
1143 static int
1144 pm_clock_get_out(struct trace_proc * proc, const message * m_out)
1145 {
1146 
1147 	put_clockid(proc, "clock_id", m_out->m_lc_pm_time.clk_id);
1148 
1149 	return CT_NOTDONE;
1150 }
1151 
1152 static void
1153 pm_clock_getres_in(struct trace_proc * proc, const message * __unused m_out,
1154 	const message * m_in, int failed)
1155 {
1156 
1157 	put_clock_timespec(proc, "res", failed, m_in->m_pm_lc_time.sec,
1158 	    m_in->m_pm_lc_time.nsec);
1159 	put_equals(proc);
1160 	put_result(proc);
1161 }
1162 
1163 /*
1164  * Same as pm_clock_getres_in, but different field name and the option to print
1165  * at least some results as time strings (in the future).
1166  */
1167 static void
1168 pm_clock_gettime_in(struct trace_proc * proc, const message * m_out,
1169 	const message * m_in, int failed)
1170 {
1171 	int flags;
1172 
1173 	flags = failed;
1174 	if (m_out->m_lc_pm_time.clk_id == CLOCK_REALTIME)
1175 		flags |= PF_ALT; /* TODO: make this print a time string. */
1176 
1177 	put_clock_timespec(proc, "tp", flags, m_in->m_pm_lc_time.sec,
1178 	    m_in->m_pm_lc_time.nsec);
1179 	put_equals(proc);
1180 	put_result(proc);
1181 }
1182 
1183 static const char *
1184 pm_clock_settime_name(const message * m_out)
1185 {
1186 
1187 	if (m_out->m_lc_pm_time.now == 0)
1188 		return "adjtime";
1189 	else
1190 		return "clock_settime";
1191 }
1192 
1193 static int
1194 pm_clock_settime_out(struct trace_proc * proc, const message * m_out)
1195 {
1196 	int flags;
1197 
1198 	/* These two calls just look completely different.. */
1199 	if (m_out->m_lc_pm_time.now == 0) {
1200 		put_timespec_as_timeval(proc, "delta", m_out->m_lc_pm_time.sec,
1201 		    m_out->m_lc_pm_time.nsec);
1202 		put_ptr(proc, "odelta", 0); /* not supported on MINIX3 */
1203 	} else {
1204 		flags = 0;
1205 		if (m_out->m_lc_pm_time.clk_id == CLOCK_REALTIME)
1206 			flags |= PF_ALT;
1207 		put_clockid(proc, "clock_id", m_out->m_lc_pm_time.clk_id);
1208 		put_clock_timespec(proc, "tp", flags, m_out->m_lc_pm_time.sec,
1209 		    m_out->m_lc_pm_time.nsec);
1210 	}
1211 
1212 	return CT_DONE;
1213 }
1214 
1215 static int
1216 pm_getrusage_out(struct trace_proc * proc, const message * m_out)
1217 {
1218 
1219 	if (!valuesonly && m_out->m_lc_pm_rusage.who == RUSAGE_SELF)
1220 		put_field(proc, "who", "RUSAGE_SELF");
1221 	else if (!valuesonly && m_out->m_lc_pm_rusage.who == RUSAGE_CHILDREN)
1222 		put_field(proc, "who", "RUSAGE_CHILDREN");
1223 	else
1224 		put_value(proc, "who", "%d", m_out->m_lc_pm_rusage.who);
1225 
1226 	return CT_NOTDONE;
1227 }
1228 
1229 static void
1230 pm_getrusage_in(struct trace_proc * proc, const message * m_out,
1231 	const message * __unused m_in, int failed)
1232 {
1233 	struct rusage buf;
1234 
1235 	/* Inline; we will certainly not be reusing this anywhere else. */
1236 	if (put_open_struct(proc, "rusage", failed, m_out->m_lc_pm_rusage.addr,
1237 	    &buf, sizeof(buf))) {
1238 		put_struct_timeval(proc, "ru_utime", PF_LOCADDR,
1239 		    (vir_bytes)&buf.ru_utime);
1240 		put_struct_timeval(proc, "ru_stime", PF_LOCADDR,
1241 		    (vir_bytes)&buf.ru_stime);
1242 
1243 		if (verbose > 0)
1244 			put_value(proc, "ru_nsignals", "%ld", buf.ru_nsignals);
1245 		put_close_struct(proc, verbose > 0);
1246 	}
1247 	put_equals(proc);
1248 	put_result(proc);
1249 }
1250 
1251 static const struct flags reboot_flags[] = {
1252 	FLAG_ZERO(RB_AUTOBOOT),
1253 	FLAG(RB_ASKNAME),
1254 	FLAG(RB_DUMP),
1255 	FLAG_MASK(RB_POWERDOWN, RB_HALT),
1256 	FLAG(RB_POWERDOWN),
1257 	FLAG(RB_INITNAME),
1258 	FLAG(RB_KDB),
1259 	FLAG(RB_NOSYNC),
1260 	FLAG(RB_RDONLY),
1261 	FLAG(RB_SINGLE),
1262 	FLAG(RB_STRING),
1263 	FLAG(RB_USERCONF),
1264 };
1265 
1266 static int
1267 pm_reboot_out(struct trace_proc * proc, const message * m_out)
1268 {
1269 
1270 	put_flags(proc, "how", reboot_flags, COUNT(reboot_flags), "0x%x",
1271 	    m_out->m_lc_pm_reboot.how);
1272 	put_ptr(proc, "bootstr", 0); /* not supported on MINIX3 */
1273 
1274 	return CT_DONE;
1275 }
1276 
1277 static int
1278 pm_svrctl_out(struct trace_proc * proc, const message * m_out)
1279 {
1280 
1281 	put_ioctl_req(proc, "request", m_out->m_lc_svrctl.request,
1282 	    TRUE /*is_svrctl*/);
1283 	return put_ioctl_arg_out(proc, "arg", m_out->m_lc_svrctl.request,
1284 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1285 }
1286 
1287 static void
1288 pm_svrctl_in(struct trace_proc * proc, const message * m_out,
1289 	const message * __unused m_in, int failed)
1290 {
1291 
1292 	put_ioctl_arg_in(proc, "arg", failed, m_out->m_lc_svrctl.request,
1293 	    m_out->m_lc_svrctl.arg, TRUE /*is_svrctl*/);
1294 }
1295 
1296 static int
1297 pm_sprof_out(struct trace_proc * proc, const message * m_out)
1298 {
1299 	int freq;
1300 
1301 	if (!valuesonly && m_out->m_lc_pm_sprof.action == PROF_START)
1302 		put_field(proc, "action", "PROF_START");
1303 	else if (!valuesonly && m_out->m_lc_pm_sprof.action == PROF_STOP)
1304 		put_field(proc, "action", "PROF_STOP");
1305 	else
1306 		put_value(proc, "action", "%d", m_out->m_lc_pm_sprof.action);
1307 
1308 	put_value(proc, "size", "%zu", m_out->m_lc_pm_sprof.mem_size);
1309 
1310 	freq = m_out->m_lc_pm_sprof.freq;
1311 	if (!valuesonly && freq >= 3 && freq <= 15) /* no constants.. */
1312 		put_value(proc, "freq", "%u /*%uHz*/", freq, 1 << (16 - freq));
1313 	else
1314 		put_value(proc, "freq", "%u", freq);
1315 
1316 	if (!valuesonly && m_out->m_lc_pm_sprof.intr_type == PROF_RTC)
1317 		put_field(proc, "type", "PROF_RTC");
1318 	else if (!valuesonly && m_out->m_lc_pm_sprof.intr_type == PROF_NMI)
1319 		put_field(proc, "type", "PROF_NMI");
1320 	else
1321 		put_value(proc, "type", "%d", m_out->m_lc_pm_sprof.intr_type);
1322 
1323 	put_ptr(proc, "ctl_ptr", m_out->m_lc_pm_sprof.ctl_ptr);
1324 	put_ptr(proc, "mem_ptr", m_out->m_lc_pm_sprof.mem_ptr);
1325 
1326 	return CT_DONE;
1327 }
1328 
1329 #define PM_CALL(c) [((PM_ ## c) - PM_BASE)]
1330 
1331 static const struct call_handler pm_map[] = {
1332 	PM_CALL(EXIT) = HANDLER("exit", pm_exit_out, default_in),
1333 	PM_CALL(FORK) = HANDLER("fork", default_out, default_in),
1334 	PM_CALL(WAITPID) = HANDLER("waitpid", pm_waitpid_out, pm_waitpid_in),
1335 	PM_CALL(GETPID) = HANDLER("getpid", default_out, pm_getpid_in),
1336 	PM_CALL(SETUID) = HANDLER("setuid", pm_setuid_out, default_in),
1337 	PM_CALL(GETUID) = HANDLER("getuid", default_out, pm_getuid_in),
1338 	PM_CALL(STIME) = HANDLER("stime", pm_stime_out, default_in),
1339 	PM_CALL(PTRACE) = HANDLER("ptrace", pm_ptrace_out, pm_ptrace_in),
1340 	PM_CALL(SETGROUPS) = HANDLER("setgroups", pm_setgroups_out,
1341 	    default_in),
1342 	PM_CALL(GETGROUPS) = HANDLER("getgroups", pm_getgroups_out,
1343 	    pm_getgroups_in),
1344 	PM_CALL(KILL) = HANDLER("kill", pm_kill_out, default_in),
1345 	PM_CALL(SETGID) = HANDLER("setgid", pm_setgid_out, default_in),
1346 	PM_CALL(GETGID) = HANDLER("getgid", default_out, pm_getgid_in),
1347 	PM_CALL(EXEC) = HANDLER("execve", pm_exec_out, default_in),
1348 	PM_CALL(SETSID) = HANDLER("setsid", default_out, default_in),
1349 	PM_CALL(GETPGRP) = HANDLER("getpgrp", default_out, default_in),
1350 	PM_CALL(ITIMER) = HANDLER_NAME(pm_itimer_name, pm_itimer_out,
1351 	    pm_itimer_in),
1352 	PM_CALL(GETMCONTEXT) = HANDLER("getmcontext", pm_getmcontext_out,
1353 	    pm_getmcontext_in),
1354 	PM_CALL(SETMCONTEXT) = HANDLER("setmcontext", pm_setmcontext_out,
1355 	    default_in),
1356 	PM_CALL(SIGACTION) = HANDLER("sigaction", pm_sigaction_out,
1357 	    pm_sigaction_in),
1358 	PM_CALL(SIGSUSPEND) = HANDLER("sigsuspend", pm_sigsuspend_out,
1359 	    default_in),
1360 	PM_CALL(SIGPENDING) = HANDLER("sigpending", pm_sigpending_out,
1361 	    pm_sigpending_in),
1362 	PM_CALL(SIGPROCMASK) = HANDLER("sigprocmask", pm_sigprocmask_out,
1363 	    pm_sigprocmask_in),
1364 	PM_CALL(SIGRETURN) = HANDLER("sigreturn", pm_sigreturn_out,
1365 	    pm_sigreturn_in),
1366 	PM_CALL(SYSUNAME) = HANDLER("sysuname", pm_sysuname_out,
1367 	    pm_sysuname_in),
1368 	PM_CALL(GETPRIORITY) = HANDLER("getpriority", pm_getpriority_out,
1369 	    pm_getpriority_in),
1370 	PM_CALL(SETPRIORITY) = HANDLER("setpriority", pm_setpriority_out,
1371 	    default_in),
1372 	PM_CALL(GETTIMEOFDAY) = HANDLER("gettimeofday", pm_gettimeofday_out,
1373 	    pm_gettimeofday_in),
1374 	PM_CALL(SETEUID) = HANDLER("seteuid", pm_setuid_out, default_in),
1375 	PM_CALL(SETEGID) = HANDLER("setegid", pm_setgid_out, default_in),
1376 	PM_CALL(ISSETUGID) = HANDLER("issetugid", default_out, default_in),
1377 	PM_CALL(GETSID) = HANDLER("getsid", pm_getsid_out, default_in),
1378 	PM_CALL(CLOCK_GETRES) = HANDLER("clock_getres", pm_clock_get_out,
1379 	    pm_clock_getres_in),
1380 	PM_CALL(CLOCK_GETTIME) = HANDLER("clock_gettime", pm_clock_get_out,
1381 	    pm_clock_gettime_in),
1382 	PM_CALL(CLOCK_SETTIME) = HANDLER_NAME(pm_clock_settime_name,
1383 	    pm_clock_settime_out, default_in),
1384 	PM_CALL(GETRUSAGE) = HANDLER("pm_getrusage", pm_getrusage_out,
1385 	    pm_getrusage_in),
1386 	PM_CALL(REBOOT) = HANDLER("reboot", pm_reboot_out, default_in),
1387 	PM_CALL(SVRCTL) = HANDLER("pm_svrctl", pm_svrctl_out, pm_svrctl_in),
1388 	PM_CALL(SPROF) = HANDLER("sprofile", pm_sprof_out, default_in),
1389 };
1390 
1391 const struct calls pm_calls = {
1392 	.endpt = PM_PROC_NR,
1393 	.base = PM_BASE,
1394 	.map = pm_map,
1395 	.count = COUNT(pm_map)
1396 };
1397