]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/basic/exit-status.c
util: introduce memcmp_safe()
[thirdparty/systemd.git] / src / basic / exit-status.c
index fcff753ada3a6592117cf74e625d42b8a8ffbf86..21af8c4c7194ec5881f5e71f5995b0369c366fc9 100644 (file)
@@ -1,37 +1,30 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
+/* SPDX-License-Identifier: LGPL-2.1+ */
 
-/***
-  This file is part of systemd.
-
-  Copyright 2010 Lennart Poettering
-
-  systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU Lesser General Public License as published by
-  the Free Software Foundation; either version 2.1 of the License, or
-  (at your option) any later version.
-
-  systemd is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  Lesser General Public License for more details.
-
-  You should have received a copy of the GNU Lesser General Public License
-  along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <stdlib.h>
 #include <signal.h>
+#include <stdlib.h>
+#include <sysexits.h>
 
 #include "exit-status.h"
-#include "set.h"
 #include "macro.h"
+#include "set.h"
 
-const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
+const char* exit_status_to_string(int status, ExitStatusLevel level) {
 
-        /* We cast to int here, so that -Wenum doesn't complain that
-         * EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
+        /* Exit status ranges:
+         *
+         *   0…1   │ ISO C, EXIT_SUCCESS + EXIT_FAILURE
+         *   2…7   │ LSB exit codes for init scripts
+         *   8…63  │ (Currently unmapped)
+         *  64…78  │ BSD defined exit codes
+         *  79…199 │ (Currently unmapped)
+         * 200…241 │ systemd's private error codes (might be extended to 254 in future development)
+         * 242…254 │ (Currently unmapped, but see above)
+         *   255   │ (We should probably stay away from that one, it's frequently used by applications to indicate an
+         *         │ exit reason that cannot really be expressed in a single exit status value — such as a propagated
+         *         │ signal or such)
+         */
 
-        switch ((int) status) {
+        switch (status) {  /* We always cover the ISO C ones */
 
         case EXIT_SUCCESS:
                 return "SUCCESS";
@@ -40,9 +33,8 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
                 return "FAILURE";
         }
 
-
-        if (level == EXIT_STATUS_SYSTEMD || level == EXIT_STATUS_LSB) {
-                switch ((int) status) {
+        if (IN_SET(level, EXIT_STATUS_SYSTEMD, EXIT_STATUS_LSB, EXIT_STATUS_FULL)) {
+                switch (status) { /* Optionally we cover our own ones */
 
                 case EXIT_CHDIR:
                         return "CHDIR";
@@ -146,19 +138,28 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
                 case EXIT_CHOWN:
                         return "CHOWN";
 
-                case EXIT_MAKE_STARTER:
-                        return "MAKE_STARTER";
-
-                case EXIT_BUS_ENDPOINT:
-                        return "BUS_ENDPOINT";
-
                 case EXIT_SMACK_PROCESS_LABEL:
                         return "SMACK_PROCESS_LABEL";
+
+                case EXIT_KEYRING:
+                        return "KEYRING";
+
+                case EXIT_STATE_DIRECTORY:
+                        return "STATE_DIRECTORY";
+
+                case EXIT_CACHE_DIRECTORY:
+                        return "CACHE_DIRECTORY";
+
+                case EXIT_LOGS_DIRECTORY:
+                        return "LOGS_DIRECTORY";
+
+                case EXIT_CONFIGURATION_DIRECTORY:
+                        return "CONFIGURATION_DIRECTORY";
                 }
         }
 
-        if (level == EXIT_STATUS_LSB) {
-                switch ((int) status) {
+        if (IN_SET(level, EXIT_STATUS_LSB, EXIT_STATUS_FULL)) {
+                switch (status) { /* Optionally we support LSB ones */
 
                 case EXIT_INVALIDARGUMENT:
                         return "INVALIDARGUMENT";
@@ -180,47 +181,81 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) {
                 }
         }
 
+        if (level == EXIT_STATUS_FULL) {
+                switch (status) { /* Optionally, we support BSD exit statusses */
+
+                case EX_USAGE:
+                        return "USAGE";
+
+                case EX_DATAERR:
+                        return "DATAERR";
+
+                case EX_NOINPUT:
+                        return "NOINPUT";
+
+                case EX_NOUSER:
+                        return "NOUSER";
+
+                case EX_NOHOST:
+                        return "NOHOST";
+
+                case EX_UNAVAILABLE:
+                        return "UNAVAILABLE";
+
+                case EX_SOFTWARE:
+                        return "SOFTWARE";
+
+                case EX_OSERR:
+                        return "OSERR";
+
+                case EX_OSFILE:
+                        return "OSFILE";
+
+                case EX_CANTCREAT:
+                        return "CANTCREAT";
+
+                case EX_IOERR:
+                        return "IOERR";
+
+                case EX_TEMPFAIL:
+                        return "TEMPFAIL";
+
+                case EX_PROTOCOL:
+                        return "PROTOCOL";
+
+                case EX_NOPERM:
+                        return "NOPERM";
+
+                case EX_CONFIG:
+                        return "CONFIG";
+                }
+        }
+
         return NULL;
 }
 
-
-bool is_clean_exit(int code, int status, ExitStatusSet *success_status) {
+bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) {
 
         if (code == CLD_EXITED)
                 return status == 0 ||
                        (success_status &&
-                       set_contains(success_status->status, INT_TO_PTR(status)));
+                        set_contains(success_status->status, INT_TO_PTR(status)));
 
-        /* If a daemon does not implement handlers for some of the
-         * signals that's not considered an unclean shutdown */
+        /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */
         if (code == CLD_KILLED)
                 return
-                        status == SIGHUP ||
-                        status == SIGINT ||
-                        status == SIGTERM ||
-                        status == SIGPIPE ||
+                        (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
                         (success_status &&
-                        set_contains(success_status->signal, INT_TO_PTR(status)));
+                         set_contains(success_status->signal, INT_TO_PTR(status)));
 
         return false;
 }
 
-bool is_clean_exit_lsb(int code, int status, ExitStatusSet *success_status) {
-
-        if (is_clean_exit(code, status, success_status))
-                return true;
-
-        return
-                code == CLD_EXITED &&
-                (status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
-}
-
 void exit_status_set_free(ExitStatusSet *x) {
         assert(x);
 
-        set_free(x->status);
-        set_free(x->signal);
-        x->status = x->signal = NULL;
+        x->status = set_free(x->status);
+        x->signal = set_free(x->signal);
 }
 
 bool exit_status_set_is_empty(ExitStatusSet *x) {