chiark / gitweb /
core: add new logic for services to store file descriptors in PID 1
[elogind.git] / src / shared / 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 <sys/wait.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         }
156
157         if (level == EXIT_STATUS_LSB) {
158                 switch ((int) status) {
159
160                 case EXIT_INVALIDARGUMENT:
161                         return "INVALIDARGUMENT";
162
163                 case EXIT_NOTIMPLEMENTED:
164                         return "NOTIMPLEMENTED";
165
166                 case EXIT_NOPERMISSION:
167                         return "NOPERMISSION";
168
169                 case EXIT_NOTINSTALLED:
170                         return "NOTINSSTALLED";
171
172                 case EXIT_NOTCONFIGURED:
173                         return "NOTCONFIGURED";
174
175                 case EXIT_NOTRUNNING:
176                         return "NOTRUNNING";
177                 }
178         }
179
180         return NULL;
181 }
182
183
184 bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
185
186         if (code == CLD_EXITED)
187                 return status == 0 ||
188                        (success_status &&
189                        set_contains(success_status->status, INT_TO_PTR(status)));
190
191         /* If a daemon does not implement handlers for some of the
192          * signals that's not considered an unclean shutdown */
193         if (code == CLD_KILLED)
194                 return
195                         status == SIGHUP ||
196                         status == SIGINT ||
197                         status == SIGTERM ||
198                         status == SIGPIPE ||
199                         (success_status &&
200                         set_contains(success_status->signal, INT_TO_PTR(status)));
201
202         return false;
203 }
204
205 bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
206
207         if (is_clean_exit(code, status, success_status))
208                 return true;
209
210         return
211                 code == CLD_EXITED &&
212                 (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
213 }
214
215 void exit_status_set_free(ExitStatusSet *x) {
216         assert(x);
217
218         set_free(x->status);
219         set_free(x->signal);
220         x->status = x->signal = NULL;
221 }
222
223 bool exit_status_set_is_empty(ExitStatusSet *x) {
224         if (!x)
225                 return true;
226
227         return set_isempty(x->status) && set_isempty(x->signal);
228 }