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