1/*
2 * Copyright 2023, Trung Nguyen, trungnt282910@gmail.com.
3 * Distributed under the terms of the MIT License.
4 */
5
6
7#include <stdio.h>
8
9#include <string>
10
11#include "signals.h"
12
13
14// signal names
15static const char *kSignalName[] = {
16	/*  0 */ "SIG0",
17	/*  1 */ "SIGHUP",
18	/*  2 */ "SIGINT",
19	/*  3 */ "SIGQUIT",
20	/*  4 */ "SIGILL",
21	/*  5 */ "SIGCHLD",
22	/*  6 */ "SIGABRT",
23	/*  7 */ "SIGPIPE",
24	/*  8 */ "SIGFPE",
25	/*  9 */ "SIGKILL",
26	/* 10 */ "SIGSTOP",
27	/* 11 */ "SIGSEGV",
28	/* 12 */ "SIGCONT",
29	/* 13 */ "SIGTSTP",
30	/* 14 */ "SIGALRM",
31	/* 15 */ "SIGTERM",
32	/* 16 */ "SIGTTIN",
33	/* 17 */ "SIGTTOU",
34	/* 18 */ "SIGUSR1",
35	/* 19 */ "SIGUSR2",
36	/* 20 */ "SIGWINCH",
37	/* 21 */ "SIGKILLTHR",
38	/* 22 */ "SIGTRAP",
39	/* 23 */ "SIGPOLL",
40	/* 24 */ "SIGPROF",
41	/* 25 */ "SIGSYS",
42	/* 26 */ "SIGURG",
43	/* 27 */ "SIGVTALRM",
44	/* 28 */ "SIGXCPU",
45	/* 29 */ "SIGXFSZ",
46	/* 30 */ "SIGBUS",
47	/* 31 */ "SIGRESERVED1",
48	/* 32 */ "SIGRESERVED2",
49};
50
51
52std::string
53signal_name(int signal)
54{
55	if (signal >= 0 && signal <= SIGRESERVED2)
56		return kSignalName[signal];
57
58	static char buffer[32];
59	sprintf(buffer, "%d", signal);
60	return buffer;
61}
62
63
64static const char *
65signal_code(int signal, int code)
66{
67#define CASE(X) case X: return #X;
68	switch (code) {
69		CASE(SI_USER)
70		CASE(SI_QUEUE)
71		CASE(SI_TIMER)
72		CASE(SI_ASYNCIO)
73		CASE(SI_MESGQ)
74	}
75
76	switch (signal) {
77		case SIGILL:
78			switch (code) {
79				CASE(ILL_ILLOPC)
80				CASE(ILL_ILLOPN)
81				CASE(ILL_ILLADR)
82				CASE(ILL_ILLTRP)
83				CASE(ILL_PRVOPC)
84				CASE(ILL_PRVREG)
85				CASE(ILL_COPROC)
86				CASE(ILL_BADSTK)
87			}
88			break;
89		case SIGFPE:
90			switch (code) {
91				CASE(FPE_INTDIV)
92				CASE(FPE_INTOVF)
93				CASE(FPE_FLTDIV)
94				CASE(FPE_FLTOVF)
95				CASE(FPE_FLTUND)
96				CASE(FPE_FLTRES)
97				CASE(FPE_FLTINV)
98				CASE(FPE_FLTSUB)
99			}
100			break;
101		case SIGSEGV:
102			switch (code) {
103				CASE(SEGV_MAPERR)
104				CASE(SEGV_ACCERR)
105			}
106			break;
107		case SIGBUS:
108			switch (code) {
109				CASE(BUS_ADRALN)
110				CASE(BUS_ADRERR)
111				CASE(BUS_OBJERR)
112			}
113			break;
114		case SIGTRAP:
115			switch (code) {
116				CASE(TRAP_BRKPT)
117				CASE(TRAP_TRACE)
118			}
119			break;
120		case SIGCHLD:
121			switch (code) {
122				CASE(CLD_EXITED)
123				CASE(CLD_KILLED)
124				CASE(CLD_DUMPED)
125				CASE(CLD_TRAPPED)
126				CASE(CLD_STOPPED)
127				CASE(CLD_CONTINUED)
128			}
129			break;
130		case SIGPOLL:
131			switch (code) {
132				CASE(POLL_IN)
133				CASE(POLL_OUT)
134				CASE(POLL_MSG)
135				CASE(POLL_ERR)
136				CASE(POLL_PRI)
137				CASE(POLL_HUP)
138			}
139			break;
140	}
141#undef CASE
142
143	static char buffer[32];
144	sprintf(buffer, "%d", code);
145	return buffer;
146}
147
148
149std::string
150signal_info(siginfo_t& info)
151{
152	static char buffer[32];
153	std::string string;
154
155	string.reserve(256);
156
157	string += "{";
158	string += "si_signo=";
159	string += signal_name(info.si_signo);
160	string += ", si_code=";
161	string += signal_code(info.si_signo, info.si_code);
162
163	if (info.si_errno != 0) {
164		string += ", si_errno=0x";
165		sprintf(buffer, "%x", info.si_errno);
166		string += buffer;
167	}
168
169	string += ", si_pid=";
170	sprintf(buffer, "%d", (int)info.si_pid);
171	string += buffer;
172	string += ", si_uid=";
173	sprintf(buffer, "%d", (int)info.si_uid);
174	string += buffer;
175
176	if (info.si_signo == SIGILL || info.si_signo == SIGFPE || info.si_signo == SIGSEGV
177		|| info.si_signo == SIGBUS || info.si_signo == SIGTRAP) {
178		string += ", si_addr=";
179		sprintf(buffer, "%p", info.si_addr);
180		string += buffer;
181	}
182
183	if (info.si_signo == SIGCHLD) {
184		string += ", si_status=";
185		sprintf(buffer, "%d", info.si_status);
186		string += buffer;
187	}
188
189	if (info.si_signo == SIGPOLL) {
190		string += ", si_band=";
191		sprintf(buffer, "%ld", info.si_band);
192		string += buffer;
193	}
194
195	string += ", si_value=";
196	sprintf(buffer, "%p", info.si_value.sival_ptr);
197	string += buffer;
198	string += "}";
199
200	return string;
201}
202