LCOV - code coverage report
Current view: top level - shared - exit-status.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 33 50 66.0 %
Date: 2019-08-23 13:36:53 Functions: 5 7 71.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 25 59 42.4 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <signal.h>
       4                 :            : #include <stdlib.h>
       5                 :            : #include <sysexits.h>
       6                 :            : 
       7                 :            : #include "exit-status.h"
       8                 :            : #include "macro.h"
       9                 :            : #include "parse-util.h"
      10                 :            : #include "set.h"
      11                 :            : #include "string-util.h"
      12                 :            : 
      13                 :            : const ExitStatusMapping exit_status_mappings[256] = {
      14                 :            :         /* Exit status ranges:
      15                 :            :          *
      16                 :            :          *   0…1   │ ISO C, EXIT_SUCCESS + EXIT_FAILURE
      17                 :            :          *   2…7   │ LSB exit codes for init scripts
      18                 :            :          *   8…63  │ (Currently unmapped)
      19                 :            :          *  64…78  │ BSD defined exit codes
      20                 :            :          *  79…199 │ (Currently unmapped)
      21                 :            :          * 200…242 │ systemd's private error codes (might be extended to 254 in future development)
      22                 :            :          * 243…254 │ (Currently unmapped, but see above)
      23                 :            :          *
      24                 :            :          *   255   │ EXIT_EXCEPTION (We use this to propagate exit-by-signal events. It's frequently used by others apps (like bash)
      25                 :            :          *         │ to indicate exit reason that cannot really be expressed in a single exit status value — such as a propagated
      26                 :            :          *         │ signal or such, and we follow that logic here.)
      27                 :            :          */
      28                 :            : 
      29                 :            :         [EXIT_SUCCESS] =                 { "SUCCESS",                 EXIT_STATUS_LIBC },
      30                 :            :         [EXIT_FAILURE] =                 { "FAILURE",                 EXIT_STATUS_LIBC },
      31                 :            : 
      32                 :            :         [EXIT_CHDIR] =                   { "CHDIR",                   EXIT_STATUS_SYSTEMD },
      33                 :            :         [EXIT_NICE] =                    { "NICE",                    EXIT_STATUS_SYSTEMD },
      34                 :            :         [EXIT_FDS] =                     { "FDS",                     EXIT_STATUS_SYSTEMD },
      35                 :            :         [EXIT_EXEC] =                    { "EXEC",                    EXIT_STATUS_SYSTEMD },
      36                 :            :         [EXIT_MEMORY] =                  { "MEMORY",                  EXIT_STATUS_SYSTEMD },
      37                 :            :         [EXIT_LIMITS] =                  { "LIMITS",                  EXIT_STATUS_SYSTEMD },
      38                 :            :         [EXIT_OOM_ADJUST] =              { "OOM_ADJUST",              EXIT_STATUS_SYSTEMD },
      39                 :            :         [EXIT_SIGNAL_MASK] =             { "SIGNAL_MASK",             EXIT_STATUS_SYSTEMD },
      40                 :            :         [EXIT_STDIN] =                   { "STDIN",                   EXIT_STATUS_SYSTEMD },
      41                 :            :         [EXIT_STDOUT] =                  { "STDOUT",                  EXIT_STATUS_SYSTEMD },
      42                 :            :         [EXIT_CHROOT] =                  { "CHROOT",                  EXIT_STATUS_SYSTEMD },
      43                 :            :         [EXIT_IOPRIO] =                  { "IOPRIO",                  EXIT_STATUS_SYSTEMD },
      44                 :            :         [EXIT_TIMERSLACK] =              { "TIMERSLACK",              EXIT_STATUS_SYSTEMD },
      45                 :            :         [EXIT_SECUREBITS] =              { "SECUREBITS",              EXIT_STATUS_SYSTEMD },
      46                 :            :         [EXIT_SETSCHEDULER] =            { "SETSCHEDULER",            EXIT_STATUS_SYSTEMD },
      47                 :            :         [EXIT_CPUAFFINITY] =             { "CPUAFFINITY",             EXIT_STATUS_SYSTEMD },
      48                 :            :         [EXIT_GROUP] =                   { "GROUP",                   EXIT_STATUS_SYSTEMD },
      49                 :            :         [EXIT_USER] =                    { "USER",                    EXIT_STATUS_SYSTEMD },
      50                 :            :         [EXIT_CAPABILITIES] =            { "CAPABILITIES",            EXIT_STATUS_SYSTEMD },
      51                 :            :         [EXIT_CGROUP] =                  { "CGROUP",                  EXIT_STATUS_SYSTEMD },
      52                 :            :         [EXIT_SETSID] =                  { "SETSID",                  EXIT_STATUS_SYSTEMD },
      53                 :            :         [EXIT_CONFIRM] =                 { "CONFIRM",                 EXIT_STATUS_SYSTEMD },
      54                 :            :         [EXIT_STDERR] =                  { "STDERR",                  EXIT_STATUS_SYSTEMD },
      55                 :            :         [EXIT_PAM] =                     { "PAM",                     EXIT_STATUS_SYSTEMD },
      56                 :            :         [EXIT_NETWORK] =                 { "NETWORK",                 EXIT_STATUS_SYSTEMD },
      57                 :            :         [EXIT_NAMESPACE] =               { "NAMESPACE",               EXIT_STATUS_SYSTEMD },
      58                 :            :         [EXIT_NO_NEW_PRIVILEGES] =       { "NO_NEW_PRIVILEGES",       EXIT_STATUS_SYSTEMD },
      59                 :            :         [EXIT_SECCOMP] =                 { "SECCOMP",                 EXIT_STATUS_SYSTEMD },
      60                 :            :         [EXIT_SELINUX_CONTEXT] =         { "SELINUX_CONTEXT",         EXIT_STATUS_SYSTEMD },
      61                 :            :         [EXIT_PERSONALITY] =             { "PERSONALITY",             EXIT_STATUS_SYSTEMD },
      62                 :            :         [EXIT_APPARMOR_PROFILE] =        { "APPARMOR",                EXIT_STATUS_SYSTEMD },
      63                 :            :         [EXIT_ADDRESS_FAMILIES] =        { "ADDRESS_FAMILIES",        EXIT_STATUS_SYSTEMD },
      64                 :            :         [EXIT_RUNTIME_DIRECTORY] =       { "RUNTIME_DIRECTORY",       EXIT_STATUS_SYSTEMD },
      65                 :            :         [EXIT_CHOWN] =                   { "CHOWN",                   EXIT_STATUS_SYSTEMD },
      66                 :            :         [EXIT_SMACK_PROCESS_LABEL] =     { "SMACK_PROCESS_LABEL",     EXIT_STATUS_SYSTEMD },
      67                 :            :         [EXIT_KEYRING] =                 { "KEYRING",                 EXIT_STATUS_SYSTEMD },
      68                 :            :         [EXIT_STATE_DIRECTORY] =         { "STATE_DIRECTORY",         EXIT_STATUS_SYSTEMD },
      69                 :            :         [EXIT_CACHE_DIRECTORY] =         { "CACHE_DIRECTORY",         EXIT_STATUS_SYSTEMD },
      70                 :            :         [EXIT_LOGS_DIRECTORY] =          { "LOGS_DIRECTORY",          EXIT_STATUS_SYSTEMD },
      71                 :            :         [EXIT_CONFIGURATION_DIRECTORY] = { "CONFIGURATION_DIRECTORY", EXIT_STATUS_SYSTEMD },
      72                 :            :         [EXIT_NUMA_POLICY] =             { "NUMA_POLICY",             EXIT_STATUS_SYSTEMD },
      73                 :            :         [EXIT_EXCEPTION] =               { "EXCEPTION",               EXIT_STATUS_SYSTEMD },
      74                 :            : 
      75                 :            :         [EXIT_INVALIDARGUMENT] =         { "INVALIDARGUMENT",         EXIT_STATUS_LSB },
      76                 :            :         [EXIT_NOTIMPLEMENTED] =          { "NOTIMPLEMENTED",          EXIT_STATUS_LSB },
      77                 :            :         [EXIT_NOPERMISSION] =            { "NOPERMISSION",            EXIT_STATUS_LSB },
      78                 :            :         [EXIT_NOTINSTALLED] =            { "NOTINSTALLED",            EXIT_STATUS_LSB },
      79                 :            :         [EXIT_NOTCONFIGURED] =           { "NOTCONFIGURED",           EXIT_STATUS_LSB },
      80                 :            :         [EXIT_NOTRUNNING] =              { "NOTRUNNING",              EXIT_STATUS_LSB },
      81                 :            : 
      82                 :            :         [EX_USAGE] =                     { "USAGE",                   EXIT_STATUS_BSD },
      83                 :            :         [EX_DATAERR] =                   { "DATAERR",                 EXIT_STATUS_BSD },
      84                 :            :         [EX_NOINPUT] =                   { "NOINPUT",                 EXIT_STATUS_BSD },
      85                 :            :         [EX_NOUSER] =                    { "NOUSER",                  EXIT_STATUS_BSD },
      86                 :            :         [EX_NOHOST] =                    { "NOHOST",                  EXIT_STATUS_BSD },
      87                 :            :         [EX_UNAVAILABLE] =               { "UNAVAILABLE",             EXIT_STATUS_BSD },
      88                 :            :         [EX_SOFTWARE] =                  { "SOFTWARE",                EXIT_STATUS_BSD },
      89                 :            :         [EX_OSERR] =                     { "OSERR",                   EXIT_STATUS_BSD },
      90                 :            :         [EX_OSFILE] =                    { "OSFILE",                  EXIT_STATUS_BSD },
      91                 :            :         [EX_CANTCREAT] =                 { "CANTCREAT",               EXIT_STATUS_BSD },
      92                 :            :         [EX_IOERR] =                     { "IOERR",                   EXIT_STATUS_BSD },
      93                 :            :         [EX_TEMPFAIL] =                  { "TEMPFAIL",                EXIT_STATUS_BSD },
      94                 :            :         [EX_PROTOCOL] =                  { "PROTOCOL",                EXIT_STATUS_BSD },
      95                 :            :         [EX_NOPERM] =                    { "NOPERM",                  EXIT_STATUS_BSD },
      96                 :            :         [EX_CONFIG] =                    { "CONFIG",                  EXIT_STATUS_BSD },
      97                 :            : };
      98                 :            : 
      99                 :       1048 : const char* exit_status_to_string(int code, ExitStatusClass class) {
     100   [ +  +  +  + ]:       1048 :         if (code < 0 || (size_t) code >= ELEMENTSOF(exit_status_mappings))
     101                 :          8 :                 return NULL;
     102         [ +  + ]:       1040 :         return class & exit_status_mappings[code].class ? exit_status_mappings[code].name : NULL;
     103                 :            : }
     104                 :            : 
     105                 :       1032 : const char* exit_status_class(int code) {
     106   [ +  +  +  + ]:       1032 :         if (code < 0 || (size_t) code >= ELEMENTSOF(exit_status_mappings))
     107                 :          8 :                 return NULL;
     108                 :            : 
     109   [ +  +  +  +  :       1024 :         switch (exit_status_mappings[code].class) {
                      + ]
     110                 :          8 :         case EXIT_STATUS_LIBC:
     111                 :          8 :                 return "libc";
     112                 :        168 :         case EXIT_STATUS_SYSTEMD:
     113                 :        168 :                 return "systemd";
     114                 :         24 :         case EXIT_STATUS_LSB:
     115                 :         24 :                 return "LSB";
     116                 :         60 :         case EXIT_STATUS_BSD:
     117                 :         60 :                 return "BSD";
     118                 :        764 :         default: return NULL;
     119                 :            :         }
     120                 :            : }
     121                 :            : 
     122                 :        284 : int exit_status_from_string(const char *s) {
     123                 :            :         uint8_t val;
     124                 :            :         int r;
     125                 :            : 
     126         [ +  + ]:      45960 :         for (size_t i = 0; i < ELEMENTSOF(exit_status_mappings); i++)
     127         [ +  + ]:      45944 :                 if (streq_ptr(s, exit_status_mappings[i].name))
     128                 :        268 :                         return i;
     129                 :            : 
     130                 :         16 :         r = safe_atou8(s, &val);
     131         [ +  + ]:         16 :         if (r < 0)
     132                 :         12 :                 return r;
     133                 :            : 
     134                 :          4 :         return val;
     135                 :            : }
     136                 :            : 
     137                 :          0 : bool is_clean_exit(int code, int status, ExitClean clean, const ExitStatusSet *success_status) {
     138         [ #  # ]:          0 :         if (code == CLD_EXITED)
     139   [ #  #  #  # ]:          0 :                 return status == 0 ||
     140         [ #  # ]:          0 :                        (success_status &&
     141                 :          0 :                         bitmap_isset(&success_status->status, status));
     142                 :            : 
     143                 :            :         /* If a daemon does not implement handlers for some of the signals, we do not consider this an
     144                 :            :            unclean shutdown */
     145         [ #  # ]:          0 :         if (code == CLD_KILLED)
     146                 :            :                 return
     147   [ #  #  #  #  :          0 :                         (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) ||
             #  #  #  # ]
     148         [ #  # ]:          0 :                         (success_status &&
     149                 :          0 :                          bitmap_isset(&success_status->signal, status));
     150                 :            : 
     151                 :          0 :         return false;
     152                 :            : }
     153                 :            : 
     154                 :        552 : void exit_status_set_free(ExitStatusSet *x) {
     155         [ -  + ]:        552 :         assert(x);
     156                 :            : 
     157                 :        552 :         bitmap_clear(&x->status);
     158                 :        552 :         bitmap_clear(&x->signal);
     159                 :        552 : }
     160                 :            : 
     161                 :         68 : bool exit_status_set_is_empty(const ExitStatusSet *x) {
     162         [ -  + ]:         68 :         if (!x)
     163                 :          0 :                 return true;
     164                 :            : 
     165   [ +  -  +  - ]:         68 :         return bitmap_isclear(&x->status) && bitmap_isclear(&x->signal);
     166                 :            : }
     167                 :            : 
     168                 :          0 : bool exit_status_set_test(const ExitStatusSet *x, int code, int status) {
     169   [ #  #  #  # ]:          0 :         if (code == CLD_EXITED && bitmap_isset(&x->status, status))
     170                 :          0 :                 return true;
     171                 :            : 
     172   [ #  #  #  #  :          0 :         if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && bitmap_isset(&x->signal, status))
                   #  # ]
     173                 :          0 :                 return true;
     174                 :            : 
     175                 :          0 :         return false;
     176                 :            : }

Generated by: LCOV version 1.14