1204880Skib/*-
2204880Skib * Copyright (c) 2010 Konstantin Belousov
3287486Sallanjude * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
4204880Skib * All rights reserved.
5204880Skib *
6204880Skib * Redistribution and use in source and binary forms, with or without
7204880Skib * modification, are permitted provided that the following conditions
8204880Skib * are met:
9204880Skib * 1. Redistributions of source code must retain the above copyright
10204880Skib *    notice, this list of conditions and the following disclaimer.
11204880Skib * 2. Redistributions in binary form must reproduce the above copyright
12204880Skib *    notice, this list of conditions and the following disclaimer in the
13204880Skib *    documentation and/or other materials provided with the distribution.
14204880Skib *
15204880Skib * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16204880Skib * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17204880Skib * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18204880Skib * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19204880Skib * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20204880Skib * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21204880Skib * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22204880Skib * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23204880Skib * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24204880Skib * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25204880Skib * SUCH DAMAGE.
26204880Skib *
27204880Skib * $FreeBSD: releng/11.0/usr.bin/procstat/procstat_sigs.c 287486 2015-09-05 17:02:01Z allanjude $
28204880Skib */
29204880Skib
30204880Skib#include <sys/param.h>
31204880Skib#include <sys/sysctl.h>
32204880Skib#include <sys/user.h>
33204880Skib
34204880Skib#include <ctype.h>
35204880Skib#include <err.h>
36204880Skib#include <errno.h>
37204880Skib#include <signal.h>
38204880Skib#include <stdio.h>
39204880Skib#include <stdlib.h>
40204880Skib#include <string.h>
41221807Sstas#include <libprocstat.h>
42204880Skib
43204880Skib#include "procstat.h"
44204880Skib
45204880Skibstatic void
46204880Skibprocstat_print_signame(int sig)
47204880Skib{
48204880Skib	char name[12];
49204880Skib	int i;
50204880Skib
51204880Skib	if (!nflag && sig < sys_nsig) {
52204880Skib		strlcpy(name, sys_signame[sig], sizeof(name));
53204880Skib		for (i = 0; name[i] != 0; i++)
54204880Skib			name[i] = toupper(name[i]);
55287486Sallanjude		xo_emit("{d:signal/%-7s/%s} ", name);
56287486Sallanjude		xo_open_container(name);
57287486Sallanjude	} else {
58287486Sallanjude		xo_emit("{d:signal/%-7d/%d} ", sig);
59287486Sallanjude		snprintf(name, 12, "%d", sig);
60287486Sallanjude		xo_open_container(name);
61287486Sallanjude	}
62287486Sallanjude}
63287486Sallanjude
64287486Sallanjudestatic void
65287486Sallanjudeprocstat_close_signame(int sig)
66287486Sallanjude{
67287486Sallanjude	char name[12];
68287486Sallanjude	int i;
69287486Sallanjude
70287486Sallanjude	if (!nflag && sig < sys_nsig) {
71287486Sallanjude		strlcpy(name, sys_signame[sig], sizeof(name));
72287486Sallanjude		for (i = 0; name[i] != 0; i++)
73287486Sallanjude			name[i] = toupper(name[i]);
74287486Sallanjude		xo_close_container(name);
75204880Skib	} else
76287486Sallanjude		snprintf(name, 12, "%d", sig);
77287486Sallanjude		xo_close_container(name);
78204880Skib}
79204880Skib
80204880Skibstatic void
81204880Skibprocstat_print_sig(const sigset_t *set, int sig, char flag)
82204880Skib{
83287486Sallanjude	xo_emit("{d:sigmember/%c}", sigismember(set, sig) ? flag : '-');
84287486Sallanjude	switch (flag) {
85287486Sallanjude		case 'B':
86287486Sallanjude			xo_emit("{en:mask/%s}", sigismember(set, sig) ?
87287486Sallanjude			    "true" : "false");
88287486Sallanjude			break;
89287486Sallanjude		case 'C':
90287486Sallanjude			xo_emit("{en:catch/%s}", sigismember(set, sig) ?
91287486Sallanjude			    "true" : "false");
92287486Sallanjude			break;
93287486Sallanjude		case 'P':
94287486Sallanjude			xo_emit("{en:list/%s}", sigismember(set, sig) ?
95287486Sallanjude			    "true" : "false");
96287486Sallanjude			break;
97287486Sallanjude		case 'I':
98287486Sallanjude			xo_emit("{en:ignore/%s}", sigismember(set, sig) ?
99287486Sallanjude			    "true" : "false");
100287486Sallanjude			break;
101287486Sallanjude		default:
102287486Sallanjude			xo_emit("{en:unknown/%s}", sigismember(set, sig) ?
103287486Sallanjude			    "true" : "false");
104287486Sallanjude			break;
105287486Sallanjude	}
106204880Skib}
107204880Skib
108204880Skibvoid
109221807Sstasprocstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
110204880Skib{
111204880Skib	int j;
112204880Skib
113204880Skib	if (!hflag)
114287486Sallanjude		xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
115287486Sallanjude		    "FLAGS");
116204880Skib
117287486Sallanjude	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
118287486Sallanjude	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
119287486Sallanjude	xo_open_container("signals");
120204880Skib	for (j = 1; j <= _SIG_MAXSIG; j++) {
121287486Sallanjude		xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
122287486Sallanjude		xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
123204880Skib		procstat_print_signame(j);
124287486Sallanjude		xo_emit(" ");
125204880Skib		procstat_print_sig(&kipp->ki_siglist, j, 'P');
126204880Skib		procstat_print_sig(&kipp->ki_sigignore, j, 'I');
127204880Skib		procstat_print_sig(&kipp->ki_sigcatch, j, 'C');
128287486Sallanjude		procstat_close_signame(j);
129287486Sallanjude		xo_emit("\n");
130204880Skib	}
131287486Sallanjude	xo_close_container("signals");
132204880Skib}
133204880Skib
134204880Skibvoid
135249668Strocinyprocstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
136204880Skib{
137204880Skib	struct kinfo_proc *kip;
138249668Strociny	int j;
139249668Strociny	unsigned int count, i;
140287486Sallanjude	char *threadid;
141204880Skib
142204880Skib	if (!hflag)
143287486Sallanjude		xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
144204880Skib		     "SIG", "FLAGS");
145204880Skib
146249668Strociny	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
147287486Sallanjude	    kipp->ki_pid, &count);
148204880Skib	if (kip == NULL)
149204880Skib		return;
150287486Sallanjude	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
151287486Sallanjude	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
152287486Sallanjude	xo_open_container("threads");
153249668Strociny	kinfo_proc_sort(kip, count);
154249668Strociny	for (i = 0; i < count; i++) {
155204880Skib		kipp = &kip[i];
156287486Sallanjude		asprintf(&threadid, "%d", kipp->ki_tid);
157287486Sallanjude		if (threadid == NULL)
158287486Sallanjude			xo_errc(1, ENOMEM, "Failed to allocate memory in "
159287486Sallanjude			    "procstat_threads_sigs()");
160287486Sallanjude		xo_open_container(threadid);
161287486Sallanjude		xo_emit("{e:thread_id/%6d/%d}", kipp->ki_tid);
162287486Sallanjude		xo_open_container("signals");
163204880Skib		for (j = 1; j <= _SIG_MAXSIG; j++) {
164287486Sallanjude			xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
165287486Sallanjude			xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
166287486Sallanjude			xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
167204880Skib			procstat_print_signame(j);
168287486Sallanjude			xo_emit(" ");
169204880Skib			procstat_print_sig(&kipp->ki_siglist, j, 'P');
170204880Skib			procstat_print_sig(&kipp->ki_sigmask, j, 'B');
171287486Sallanjude			procstat_close_signame(j);
172287486Sallanjude			xo_emit("\n");
173204880Skib		}
174287486Sallanjude		xo_close_container("signals");
175287486Sallanjude		xo_close_container(threadid);
176287486Sallanjude		free(threadid);
177204880Skib	}
178287486Sallanjude	xo_close_container("threads");
179249668Strociny	procstat_freeprocs(procstat, kip);
180204880Skib}
181