]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/exit-status.c
Merge pull request #695 from poettering/journal-fixes
[thirdparty/systemd.git] / src / basic / exit-status.c
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 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 switch ((int) status) {
35
36 case EXIT_SUCCESS:
37 return "SUCCESS";
38
39 case EXIT_FAILURE:
40 return "FAILURE";
41 }
42
43
44 if (level == EXIT_STATUS_SYSTEMD || level == EXIT_STATUS_LSB) {
45 switch ((int) status) {
46
47 case EXIT_CHDIR:
48 return "CHDIR";
49
50 case EXIT_NICE:
51 return "NICE";
52
53 case EXIT_FDS:
54 return "FDS";
55
56 case EXIT_EXEC:
57 return "EXEC";
58
59 case EXIT_MEMORY:
60 return "MEMORY";
61
62 case EXIT_LIMITS:
63 return "LIMITS";
64
65 case EXIT_OOM_ADJUST:
66 return "OOM_ADJUST";
67
68 case EXIT_SIGNAL_MASK:
69 return "SIGNAL_MASK";
70
71 case EXIT_STDIN:
72 return "STDIN";
73
74 case EXIT_STDOUT:
75 return "STDOUT";
76
77 case EXIT_CHROOT:
78 return "CHROOT";
79
80 case EXIT_IOPRIO:
81 return "IOPRIO";
82
83 case EXIT_TIMERSLACK:
84 return "TIMERSLACK";
85
86 case EXIT_SECUREBITS:
87 return "SECUREBITS";
88
89 case EXIT_SETSCHEDULER:
90 return "SETSCHEDULER";
91
92 case EXIT_CPUAFFINITY:
93 return "CPUAFFINITY";
94
95 case EXIT_GROUP:
96 return "GROUP";
97
98 case EXIT_USER:
99 return "USER";
100
101 case EXIT_CAPABILITIES:
102 return "CAPABILITIES";
103
104 case EXIT_CGROUP:
105 return "CGROUP";
106
107 case EXIT_SETSID:
108 return "SETSID";
109
110 case EXIT_CONFIRM:
111 return "CONFIRM";
112
113 case EXIT_STDERR:
114 return "STDERR";
115
116 case EXIT_PAM:
117 return "PAM";
118
119 case EXIT_NETWORK:
120 return "NETWORK";
121
122 case EXIT_NAMESPACE:
123 return "NAMESPACE";
124
125 case EXIT_NO_NEW_PRIVILEGES:
126 return "NO_NEW_PRIVILEGES";
127
128 case EXIT_SECCOMP:
129 return "SECCOMP";
130
131 case EXIT_SELINUX_CONTEXT:
132 return "SELINUX_CONTEXT";
133
134 case EXIT_PERSONALITY:
135 return "PERSONALITY";
136
137 case EXIT_APPARMOR_PROFILE:
138 return "APPARMOR";
139
140 case EXIT_ADDRESS_FAMILIES:
141 return "ADDRESS_FAMILIES";
142
143 case EXIT_RUNTIME_DIRECTORY:
144 return "RUNTIME_DIRECTORY";
145
146 case EXIT_CHOWN:
147 return "CHOWN";
148
149 case EXIT_MAKE_STARTER:
150 return "MAKE_STARTER";
151
152 case EXIT_BUS_ENDPOINT:
153 return "BUS_ENDPOINT";
154
155 case EXIT_SMACK_PROCESS_LABEL:
156 return "SMACK_PROCESS_LABEL";
157 }
158 }
159
160 if (level == EXIT_STATUS_LSB) {
161 switch ((int) status) {
162
163 case EXIT_INVALIDARGUMENT:
164 return "INVALIDARGUMENT";
165
166 case EXIT_NOTIMPLEMENTED:
167 return "NOTIMPLEMENTED";
168
169 case EXIT_NOPERMISSION:
170 return "NOPERMISSION";
171
172 case EXIT_NOTINSTALLED:
173 return "NOTINSTALLED";
174
175 case EXIT_NOTCONFIGURED:
176 return "NOTCONFIGURED";
177
178 case EXIT_NOTRUNNING:
179 return "NOTRUNNING";
180 }
181 }
182
183 return NULL;
184 }
185
186
187 bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
188
189 if (code == CLD_EXITED)
190 return status == 0 ||
191 (success_status &&
192 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 if (code == CLD_KILLED)
197 return
198 status == SIGHUP ||
199 status == SIGINT ||
200 status == SIGTERM ||
201 status == SIGPIPE ||
202 (success_status &&
203 set_contains(success_status->signal, INT_TO_PTR(status)));
204
205 return false;
206 }
207
208 bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
209
210 if (is_clean_exit(code, status, success_status))
211 return true;
212
213 return
214 code == CLD_EXITED &&
215 (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
216 }
217
218 void exit_status_set_free(ExitStatusSet *x) {
219 assert(x);
220
221 set_free(x->status);
222 set_free(x->signal);
223 x->status = x->signal = NULL;
224 }
225
226 bool exit_status_set_is_empty(ExitStatusSet *x) {
227 if (!x)
228 return true;
229
230 return set_isempty(x->status) && set_isempty(x->signal);
231 }
232
233 bool exit_status_set_test(ExitStatusSet *x, int code, int status) {
234
235 if (exit_status_set_is_empty(x))
236 return false;
237
238 if (code == CLD_EXITED && set_contains(x->status, INT_TO_PTR(status)))
239 return true;
240
241 if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && set_contains(x->signal, INT_TO_PTR(status)))
242 return true;
243
244 return false;
245 }