xref: /freebsd/usr.bin/procstat/procstat_sigs.c (revision 5e3934b1)
1f4646706SKonstantin Belousov /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4f4646706SKonstantin Belousov  * Copyright (c) 2010 Konstantin Belousov
5474b62b8SAllan Jude  * Copyright (c) 2015 Allan Jude <allanjude@freebsd.org>
6f4646706SKonstantin Belousov  * All rights reserved.
7f4646706SKonstantin Belousov  *
8f4646706SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
9f4646706SKonstantin Belousov  * modification, are permitted provided that the following conditions
10f4646706SKonstantin Belousov  * are met:
11f4646706SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
12f4646706SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
13f4646706SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
14f4646706SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
15f4646706SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
16f4646706SKonstantin Belousov  *
17f4646706SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18f4646706SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19f4646706SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20f4646706SKonstantin Belousov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21f4646706SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22f4646706SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23f4646706SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24f4646706SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25f4646706SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26f4646706SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27f4646706SKonstantin Belousov  * SUCH DAMAGE.
28f4646706SKonstantin Belousov  */
29f4646706SKonstantin Belousov 
30f4646706SKonstantin Belousov #include <sys/param.h>
31f4646706SKonstantin Belousov #include <sys/sysctl.h>
32f4646706SKonstantin Belousov #include <sys/user.h>
33f4646706SKonstantin Belousov 
34f4646706SKonstantin Belousov #include <ctype.h>
35f4646706SKonstantin Belousov #include <err.h>
36f4646706SKonstantin Belousov #include <errno.h>
37f4646706SKonstantin Belousov #include <signal.h>
3824d57fa8SKonstantin Belousov #include <stdbool.h>
3924d57fa8SKonstantin Belousov #include <stdint.h>
40f4646706SKonstantin Belousov #include <stdio.h>
41f4646706SKonstantin Belousov #include <stdlib.h>
42f4646706SKonstantin Belousov #include <string.h>
430daf62d9SStanislav Sedov #include <libprocstat.h>
44f4646706SKonstantin Belousov 
45f4646706SKonstantin Belousov #include "procstat.h"
46f4646706SKonstantin Belousov 
47f4646706SKonstantin Belousov static void
procstat_print_signame(int sig)48f4646706SKonstantin Belousov procstat_print_signame(int sig)
49f4646706SKonstantin Belousov {
50f4646706SKonstantin Belousov 	char name[12];
51f4646706SKonstantin Belousov 	int i;
52f4646706SKonstantin Belousov 
532a243b95SBrooks Davis 	if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
54f4646706SKonstantin Belousov 		strlcpy(name, sys_signame[sig], sizeof(name));
55f4646706SKonstantin Belousov 		for (i = 0; name[i] != 0; i++)
56f4646706SKonstantin Belousov 			name[i] = toupper(name[i]);
57474b62b8SAllan Jude 		xo_emit("{d:signal/%-7s/%s} ", name);
58474b62b8SAllan Jude 		xo_open_container(name);
59474b62b8SAllan Jude 	} else {
60474b62b8SAllan Jude 		xo_emit("{d:signal/%-7d/%d} ", sig);
61474b62b8SAllan Jude 		snprintf(name, 12, "%d", sig);
62474b62b8SAllan Jude 		xo_open_container(name);
63474b62b8SAllan Jude 	}
64474b62b8SAllan Jude }
65474b62b8SAllan Jude 
66474b62b8SAllan Jude static void
procstat_close_signame(int sig)67474b62b8SAllan Jude procstat_close_signame(int sig)
68474b62b8SAllan Jude {
69474b62b8SAllan Jude 	char name[12];
70474b62b8SAllan Jude 	int i;
71474b62b8SAllan Jude 
722a243b95SBrooks Davis 	if ((procstat_opts & PS_OPT_SIGNUM) == 0 && sig < sys_nsig) {
73474b62b8SAllan Jude 		strlcpy(name, sys_signame[sig], sizeof(name));
74474b62b8SAllan Jude 		for (i = 0; name[i] != 0; i++)
75474b62b8SAllan Jude 			name[i] = toupper(name[i]);
76474b62b8SAllan Jude 		xo_close_container(name);
777bf1ff65SDimitry Andric 	} else {
78474b62b8SAllan Jude 		snprintf(name, 12, "%d", sig);
79474b62b8SAllan Jude 		xo_close_container(name);
80f4646706SKonstantin Belousov 	}
817bf1ff65SDimitry Andric }
82f4646706SKonstantin Belousov 
83f4646706SKonstantin Belousov static void
procstat_print_sig(const sigset_t * set,int sig,char flag)84f4646706SKonstantin Belousov procstat_print_sig(const sigset_t *set, int sig, char flag)
85f4646706SKonstantin Belousov {
86474b62b8SAllan Jude 	xo_emit("{d:sigmember/%c}", sigismember(set, sig) ? flag : '-');
87474b62b8SAllan Jude 	switch (flag) {
88474b62b8SAllan Jude 		case 'B':
89474b62b8SAllan Jude 			xo_emit("{en:mask/%s}", sigismember(set, sig) ?
90474b62b8SAllan Jude 			    "true" : "false");
91474b62b8SAllan Jude 			break;
92474b62b8SAllan Jude 		case 'C':
93474b62b8SAllan Jude 			xo_emit("{en:catch/%s}", sigismember(set, sig) ?
94474b62b8SAllan Jude 			    "true" : "false");
95474b62b8SAllan Jude 			break;
96474b62b8SAllan Jude 		case 'P':
97474b62b8SAllan Jude 			xo_emit("{en:list/%s}", sigismember(set, sig) ?
98474b62b8SAllan Jude 			    "true" : "false");
99474b62b8SAllan Jude 			break;
100474b62b8SAllan Jude 		case 'I':
101474b62b8SAllan Jude 			xo_emit("{en:ignore/%s}", sigismember(set, sig) ?
102474b62b8SAllan Jude 			    "true" : "false");
103474b62b8SAllan Jude 			break;
104474b62b8SAllan Jude 		default:
105474b62b8SAllan Jude 			xo_emit("{en:unknown/%s}", sigismember(set, sig) ?
106474b62b8SAllan Jude 			    "true" : "false");
107474b62b8SAllan Jude 			break;
108474b62b8SAllan Jude 	}
109f4646706SKonstantin Belousov }
110f4646706SKonstantin Belousov 
111f4646706SKonstantin Belousov void
procstat_sigs(struct procstat * prstat __unused,struct kinfo_proc * kipp)1120daf62d9SStanislav Sedov procstat_sigs(struct procstat *prstat __unused, struct kinfo_proc *kipp)
113f4646706SKonstantin Belousov {
114f4646706SKonstantin Belousov 	int j;
115f4646706SKonstantin Belousov 
1162a243b95SBrooks Davis 	if ((procstat_opts & PS_OPT_NOHEADER) == 0)
117474b62b8SAllan Jude 		xo_emit("{T:/%5s %-16s %-7s %4s}\n", "PID", "COMM", "SIG",
118474b62b8SAllan Jude 		    "FLAGS");
119f4646706SKonstantin Belousov 
120474b62b8SAllan Jude 	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
121474b62b8SAllan Jude 	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
122474b62b8SAllan Jude 	xo_open_container("signals");
123f4646706SKonstantin Belousov 	for (j = 1; j <= _SIG_MAXSIG; j++) {
124474b62b8SAllan Jude 		xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
125474b62b8SAllan Jude 		xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
126f4646706SKonstantin Belousov 		procstat_print_signame(j);
127474b62b8SAllan Jude 		xo_emit(" ");
128f4646706SKonstantin Belousov 		procstat_print_sig(&kipp->ki_siglist, j, 'P');
129f4646706SKonstantin Belousov 		procstat_print_sig(&kipp->ki_sigignore, j, 'I');
130f4646706SKonstantin Belousov 		procstat_print_sig(&kipp->ki_sigcatch, j, 'C');
131474b62b8SAllan Jude 		procstat_close_signame(j);
132474b62b8SAllan Jude 		xo_emit("\n");
133f4646706SKonstantin Belousov 	}
134474b62b8SAllan Jude 	xo_close_container("signals");
135f4646706SKonstantin Belousov }
136f4646706SKonstantin Belousov 
137f4646706SKonstantin Belousov void
procstat_threads_sigs(struct procstat * procstat,struct kinfo_proc * kipp)138efade150SMikolaj Golub procstat_threads_sigs(struct procstat *procstat, struct kinfo_proc *kipp)
139f4646706SKonstantin Belousov {
140f4646706SKonstantin Belousov 	struct kinfo_proc *kip;
141efade150SMikolaj Golub 	int j;
142efade150SMikolaj Golub 	unsigned int count, i;
143474b62b8SAllan Jude 	char *threadid;
144f4646706SKonstantin Belousov 
1452a243b95SBrooks Davis 	if ((procstat_opts & PS_OPT_NOHEADER) == 0)
146474b62b8SAllan Jude 		xo_emit("{T:/%5s %6s %-16s %-7s %4s}\n", "PID", "TID", "COMM",
147f4646706SKonstantin Belousov 		     "SIG", "FLAGS");
148f4646706SKonstantin Belousov 
149efade150SMikolaj Golub 	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
150474b62b8SAllan Jude 	    kipp->ki_pid, &count);
151f4646706SKonstantin Belousov 	if (kip == NULL)
152f4646706SKonstantin Belousov 		return;
153474b62b8SAllan Jude 	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
154474b62b8SAllan Jude 	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
155474b62b8SAllan Jude 	xo_open_container("threads");
156efade150SMikolaj Golub 	kinfo_proc_sort(kip, count);
157efade150SMikolaj Golub 	for (i = 0; i < count; i++) {
158f4646706SKonstantin Belousov 		kipp = &kip[i];
159474b62b8SAllan Jude 		asprintf(&threadid, "%d", kipp->ki_tid);
160474b62b8SAllan Jude 		if (threadid == NULL)
161474b62b8SAllan Jude 			xo_errc(1, ENOMEM, "Failed to allocate memory in "
162474b62b8SAllan Jude 			    "procstat_threads_sigs()");
163474b62b8SAllan Jude 		xo_open_container(threadid);
164474b62b8SAllan Jude 		xo_emit("{e:thread_id/%6d/%d}", kipp->ki_tid);
165474b62b8SAllan Jude 		xo_open_container("signals");
16624d57fa8SKonstantin Belousov 
167f4646706SKonstantin Belousov 		for (j = 1; j <= _SIG_MAXSIG; j++) {
168474b62b8SAllan Jude 			xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
169474b62b8SAllan Jude 			xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
170474b62b8SAllan Jude 			xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
171f4646706SKonstantin Belousov 			procstat_print_signame(j);
172474b62b8SAllan Jude 			xo_emit(" ");
173f4646706SKonstantin Belousov 			procstat_print_sig(&kipp->ki_siglist, j, 'P');
174f4646706SKonstantin Belousov 			procstat_print_sig(&kipp->ki_sigmask, j, 'B');
175474b62b8SAllan Jude 			procstat_close_signame(j);
176474b62b8SAllan Jude 			xo_emit("\n");
177f4646706SKonstantin Belousov 		}
178474b62b8SAllan Jude 		xo_close_container("signals");
179474b62b8SAllan Jude 		xo_close_container(threadid);
180474b62b8SAllan Jude 		free(threadid);
181f4646706SKonstantin Belousov 	}
182474b62b8SAllan Jude 	xo_close_container("threads");
183efade150SMikolaj Golub 	procstat_freeprocs(procstat, kip);
184f4646706SKonstantin Belousov }
18524d57fa8SKonstantin Belousov 
18624d57fa8SKonstantin Belousov void
procstat_sigfastblock(struct procstat * procstat,struct kinfo_proc * kipp)18724d57fa8SKonstantin Belousov procstat_sigfastblock(struct procstat *procstat, struct kinfo_proc *kipp)
18824d57fa8SKonstantin Belousov {
18924d57fa8SKonstantin Belousov 	struct kinfo_proc *kip;
19024d57fa8SKonstantin Belousov 	char *threadid;
19124d57fa8SKonstantin Belousov 	uintptr_t sigfastblk_addr;
19224d57fa8SKonstantin Belousov 	int error, name[4];
19324d57fa8SKonstantin Belousov 	unsigned int count, i;
19424d57fa8SKonstantin Belousov 	size_t len;
19524d57fa8SKonstantin Belousov 	bool has_sigfastblk_addr;
19624d57fa8SKonstantin Belousov 
19724d57fa8SKonstantin Belousov 	if ((procstat_opts & PS_OPT_NOHEADER) == 0)
19824d57fa8SKonstantin Belousov 		xo_emit("{T:/%5s %6s %-16s %-16s}\n", "PID", "TID",
19924d57fa8SKonstantin Belousov 		     "COMM", "SIGFBLK");
20024d57fa8SKonstantin Belousov 
20124d57fa8SKonstantin Belousov 	kip = procstat_getprocs(procstat, KERN_PROC_PID | KERN_PROC_INC_THREAD,
20224d57fa8SKonstantin Belousov 	    kipp->ki_pid, &count);
20324d57fa8SKonstantin Belousov 	if (kip == NULL)
20424d57fa8SKonstantin Belousov 		return;
20524d57fa8SKonstantin Belousov 	xo_emit("{ek:process_id/%5d/%d}", kipp->ki_pid);
20624d57fa8SKonstantin Belousov 	xo_emit("{e:command/%-16s/%s}", kipp->ki_comm);
20724d57fa8SKonstantin Belousov 	xo_open_container("threads");
20824d57fa8SKonstantin Belousov 	kinfo_proc_sort(kip, count);
20924d57fa8SKonstantin Belousov 	for (i = 0; i < count; i++) {
21024d57fa8SKonstantin Belousov 		kipp = &kip[i];
21124d57fa8SKonstantin Belousov 		len = sizeof(sigfastblk_addr);
21224d57fa8SKonstantin Belousov 		name[0] = CTL_KERN;
21324d57fa8SKonstantin Belousov 		name[1] = KERN_PROC;
21424d57fa8SKonstantin Belousov 		name[2] = KERN_PROC_SIGFASTBLK;
21524d57fa8SKonstantin Belousov 		name[3] = kipp->ki_tid;
21624d57fa8SKonstantin Belousov 		error = sysctl(name, 4, &sigfastblk_addr, &len, NULL, 0);
21724d57fa8SKonstantin Belousov 		if (error < 0) {
21824d57fa8SKonstantin Belousov 			if (errno != ESRCH && errno != ENOTTY) {
21924d57fa8SKonstantin Belousov 				warn("sysctl: kern.proc.fastsigblk: %d",
22024d57fa8SKonstantin Belousov 				    kipp->ki_tid);
22124d57fa8SKonstantin Belousov 			}
22224d57fa8SKonstantin Belousov 			has_sigfastblk_addr = false;
22324d57fa8SKonstantin Belousov 		} else
22424d57fa8SKonstantin Belousov 			has_sigfastblk_addr = true;
22524d57fa8SKonstantin Belousov 
22624d57fa8SKonstantin Belousov 		asprintf(&threadid, "%d", kipp->ki_tid);
22724d57fa8SKonstantin Belousov 		if (threadid == NULL)
22824d57fa8SKonstantin Belousov 			xo_errc(1, ENOMEM, "Failed to allocate memory in "
22924d57fa8SKonstantin Belousov 			    "procstat_sigfastblock()");
23024d57fa8SKonstantin Belousov 		xo_open_container(threadid);
23124d57fa8SKonstantin Belousov 		xo_emit("{dk:process_id/%5d/%d} ", kipp->ki_pid);
23224d57fa8SKonstantin Belousov 		xo_emit("{d:thread_id/%6d/%d} ", kipp->ki_tid);
23324d57fa8SKonstantin Belousov 		xo_emit("{d:command/%-16s/%s} ", kipp->ki_comm);
23424d57fa8SKonstantin Belousov 		xo_emit("{e:sigfastblock/%#-16jx/%#jx}", has_sigfastblk_addr ?
23524d57fa8SKonstantin Belousov 		    (uintmax_t)sigfastblk_addr : (uintmax_t)-1);
23624d57fa8SKonstantin Belousov 		xo_emit("{d:sigfastblock/%#-16jx/%#jx}", has_sigfastblk_addr ?
23724d57fa8SKonstantin Belousov 		    (uintmax_t)sigfastblk_addr : (uintmax_t)-1);
23824d57fa8SKonstantin Belousov 		xo_emit("\n");
23924d57fa8SKonstantin Belousov 		xo_close_container(threadid);
24024d57fa8SKonstantin Belousov 		free(threadid);
24124d57fa8SKonstantin Belousov 	}
24224d57fa8SKonstantin Belousov 	xo_close_container("threads");
24324d57fa8SKonstantin Belousov 	procstat_freeprocs(procstat, kip);
24424d57fa8SKonstantin Belousov }
245