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