]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/exit-status.c
Add SPDX license identifiers to source files under the LGPL
[thirdparty/systemd.git] / src / basic / exit-status.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <signal.h>
22 #include <stdlib.h>
23
24 #include "exit-status.h"
25 #include "macro.h"
26 #include "set.h"
27
28 const char* exit_status_to_string(int status, ExitStatusLevel level) {
29
30 /* We cast to int here, so that -Wenum doesn't complain that
31 * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
32
33 switch (status) {
34
35 case EXIT_SUCCESS:
36 return "SUCCESS";
37
38 case EXIT_FAILURE:
39 return "FAILURE";
40 }
41
42 if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB)) {
43 switch (status) {
44
45 case EXIT_CHDIR:
46 return "CHDIR";
47
48 case EXIT_NICE:
49 return "NICE";
50
51 case EXIT_FDS:
52 return "FDS";
53
54 case EXIT_EXEC:
55 return "EXEC";
56
57 case EXIT_MEMORY:
58 return "MEMORY";
59
60 case EXIT_LIMITS:
61 return "LIMITS";
62
63 case EXIT_OOM_ADJUST:
64 return "OOM_ADJUST";
65
66 case EXIT_SIGNAL_MASK:
67 return "SIGNAL_MASK";
68
69 case EXIT_STDIN:
70 return "STDIN";
71
72 case EXIT_STDOUT:
73 return "STDOUT";
74
75 case EXIT_CHROOT:
76 return "CHROOT";
77
78 case EXIT_IOPRIO:
79 return "IOPRIO";
80
81 case EXIT_TIMERSLACK:
82 return "TIMERSLACK";
83
84 case EXIT_SECUREBITS:
85 return "SECUREBITS";
86
87 case EXIT_SETSCHEDULER:
88 return "SETSCHEDULER";
89
90 case EXIT_CPUAFFINITY:
91 return "CPUAFFINITY";
92
93 case EXIT_GROUP:
94 return "GROUP";
95
96 case EXIT_USER:
97 return "USER";
98
99 case EXIT_CAPABILITIES:
100 return "CAPABILITIES";
101
102 case EXIT_CGROUP:
103 return "CGROUP";
104
105 case EXIT_SETSID:
106 return "SETSID";
107
108 case EXIT_CONFIRM:
109 return "CONFIRM";
110
111 case EXIT_STDERR:
112 return "STDERR";
113
114 case EXIT_PAM:
115 return "PAM";
116
117 case EXIT_NETWORK:
118 return "NETWORK";
119
120 case EXIT_NAMESPACE:
121 return "NAMESPACE";
122
123 case EXIT_NO_NEW_PRIVILEGES:
124 return "NO_NEW_PRIVILEGES";
125
126 case EXIT_SECCOMP:
127 return "SECCOMP";
128
129 case EXIT_SELINUX_CONTEXT:
130 return "SELINUX_CONTEXT";
131
132 case EXIT_PERSONALITY:
133 return "PERSONALITY";
134
135 case EXIT_APPARMOR_PROFILE:
136 return "APPARMOR";
137
138 case EXIT_ADDRESS_FAMILIES:
139 return "ADDRESS_FAMILIES";
140
141 case EXIT_RUNTIME_DIRECTORY:
142 return "RUNTIME_DIRECTORY";
143
144 case EXIT_CHOWN:
145 return "CHOWN";
146
147 case EXIT_SMACK_PROCESS_LABEL:
148 return "SMACK_PROCESS_LABEL";
149
150 case EXIT_KEYRING:
151 return "KEYRING";
152
153 case EXIT_STATE_DIRECTORY:
154 return "STATE_DIRECTORY";
155
156 case EXIT_CACHE_DIRECTORY:
157 return "CACHE_DIRECTORY";
158
159 case EXIT_LOGS_DIRECTORY:
160 return "LOGS_DIRECTORY";
161
162 case EXIT_CONFIGURATION_DIRECTORY:
163 return "CONFIGURATION_DIRECTORY";
164 }
165 }
166
167 if (level == EXIT_STATUS_LSB) {
168 switch (status) {
169
170 case EXIT_INVALIDARGUMENT:
171 return "INVALIDARGUMENT";
172
173 case EXIT_NOTIMPLEMENTED:
174 return "NOTIMPLEMENTED";
175
176 case EXIT_NOPERMISSION:
177 return "NOPERMISSION";
178
179 case EXIT_NOTINSTALLED:
180 return "NOTINSTALLED";
181
182 case EXIT_NOTCONFIGURED:
183 return "NOTCONFIGURED";
184
185 case EXIT_NOTRUNNING:
186 return "NOTRUNNING";
187 }
188 }
189
190 return NULL;
191 }
192
193 bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
194
195 if (code == CLD_EXITED)
196 return status == 0 ||
197 (success_status &&
198 set_contains(success_status->status, INT_TO_PTR(status)));
199
200 /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
201 if (code == CLD_KILLED)
202 return
203 (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
204 (success_status &&
205 set_contains(success_status->signal, INT_TO_PTR(status)));
206
207 return false;
208 }
209
210 void exit_status_set_free(ExitStatusSet *x) {
211 assert(x);
212
213 x->status = set_free(x->status);
214 x->signal = set_free(x->signal);
215 }
216
217 bool exit_status_set_is_empty(ExitStatusSet *x) {
218 if (!x)
219 return true;
220
221 return set_isempty(x->status) && set_isempty(x->signal);
222 }
223
224 bool exit_status_set_test(ExitStatusSet *x, int code, int status) {
225
226 if (exit_status_set_is_empty(x))
227 return false;
228
229 if (code == CLD_EXITED && set_contains(x->status, INT_TO_PTR(status)))
230 return true;
231
232 if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && set_contains(x->signal, INT_TO_PTR(status)))
233 return true;
234
235 return false;
236 }