LCOV - code coverage report
Current view: top level - lib/dpkg - subproc.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 37 79 46.8 %
Date: 2022-12-03 00:40:01 Functions: 4 10 40.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 22 44 50.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * libdpkg - Debian packaging suite library routines
       3                 :            :  * subproc.c - subprocess helper routines
       4                 :            :  *
       5                 :            :  * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
       6                 :            :  * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
       7                 :            :  *
       8                 :            :  * This is free software; you can redistribute it and/or modify
       9                 :            :  * it under the terms of the GNU General Public License as published by
      10                 :            :  * the Free Software Foundation; either version 2 of the License, or
      11                 :            :  * (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :  * GNU General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU General Public License
      19                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : #include <compat.h>
      24                 :            : 
      25                 :            : #include <sys/types.h>
      26                 :            : #include <sys/wait.h>
      27                 :            : 
      28                 :            : #include <errno.h>
      29                 :            : #include <string.h>
      30                 :            : #include <signal.h>
      31                 :            : #include <unistd.h>
      32                 :            : #include <stdlib.h>
      33                 :            : #include <stdio.h>
      34                 :            : 
      35                 :            : #include <dpkg/i18n.h>
      36                 :            : #include <dpkg/dpkg.h>
      37                 :            : #include <dpkg/subproc.h>
      38                 :            : 
      39                 :            : static int signo_ignores[] = { SIGQUIT, SIGINT };
      40                 :            : static struct sigaction sa_save[array_count(signo_ignores)];
      41                 :            : 
      42                 :            : static void
      43                 :          0 : subproc_reset_signal(int sig, struct sigaction *sa_old)
      44                 :            : {
      45         [ #  # ]:          0 :         if (sigaction(sig, sa_old, NULL)) {
      46                 :          0 :                 fprintf(stderr, _("error un-catching signal %s: %s\n"),
      47                 :          0 :                         strsignal(sig), strerror(errno));
      48                 :          0 :                 onerr_abort++;
      49                 :            :         }
      50                 :          0 : }
      51                 :            : 
      52                 :            : static void
      53                 :          0 : subproc_set_signal(int sig, struct sigaction *sa, struct sigaction *sa_old,
      54                 :            :                    const char *name)
      55                 :            : {
      56         [ #  # ]:          0 :         if (sigaction(sig, sa, sa_old))
      57                 :          0 :                 ohshite(_("unable to ignore signal %s before running %.250s"),
      58                 :            :                         strsignal(sig), name);
      59                 :          0 : }
      60                 :            : 
      61                 :            : void
      62                 :          0 : subproc_signals_ignore(const char *name)
      63                 :            : {
      64                 :            :         struct sigaction sa;
      65                 :            :         size_t i;
      66                 :            : 
      67                 :          0 :         onerr_abort++;
      68                 :          0 :         memset(&sa, 0, sizeof(sa));
      69                 :          0 :         sigemptyset(&sa.sa_mask);
      70                 :          0 :         sa.sa_handler = SIG_IGN;
      71                 :          0 :         sa.sa_flags = 0;
      72                 :            : 
      73         [ #  # ]:          0 :         for (i = 0; i < array_count(signo_ignores); i++)
      74                 :          0 :                 subproc_set_signal(signo_ignores[i], &sa, &sa_save[i], name);
      75                 :            : 
      76                 :          0 :         push_cleanup(subproc_signals_cleanup, ~0, 0);
      77                 :          0 :         onerr_abort--;
      78                 :          0 : }
      79                 :            : 
      80                 :            : void
      81                 :          0 : subproc_signals_cleanup(int argc, void **argv)
      82                 :            : {
      83                 :            :         size_t i;
      84                 :            : 
      85         [ #  # ]:          0 :         for (i = 0; i < array_count(signo_ignores); i++)
      86                 :          0 :                 subproc_reset_signal(signo_ignores[i], &sa_save[i]);
      87                 :          0 : }
      88                 :            : 
      89                 :            : void
      90                 :          0 : subproc_signals_restore(void)
      91                 :            : {
      92                 :          0 :         pop_cleanup(ehflag_normaltidy);
      93                 :          0 : }
      94                 :            : 
      95                 :            : static void
      96                 :          0 : print_subproc_error(const char *emsg, const void *data)
      97                 :            : {
      98                 :          0 :         fprintf(stderr, _("%s (subprocess): %s\n"), dpkg_get_progname(), emsg);
      99                 :          0 : }
     100                 :            : 
     101                 :            : pid_t
     102                 :        145 : subproc_fork(void)
     103                 :            : {
     104                 :            :         pid_t pid;
     105                 :            : 
     106                 :        145 :         pid = fork();
     107         [ -  + ]:        286 :         if (pid == -1) {
     108                 :          0 :                 onerr_abort++;
     109                 :          0 :                 ohshite(_("fork failed"));
     110                 :            :         }
     111         [ +  + ]:        286 :         if (pid > 0)
     112                 :        145 :                 return pid;
     113                 :            : 
     114                 :            :         /* Push a new error context, so that we don't do the other cleanups,
     115                 :            :          * because they'll be done by/in the parent process. */
     116                 :        141 :         push_error_context_func(catch_fatal_error, print_subproc_error, NULL);
     117                 :            : 
     118                 :        141 :         return pid;
     119                 :            : }
     120                 :            : 
     121                 :            : static int
     122                 :        143 : subproc_check(int status, const char *desc, enum subproc_flags flags)
     123                 :            : {
     124                 :            :         void (*out)(const char *fmt, ...) DPKG_ATTR_PRINTF(1);
     125                 :            :         int n;
     126                 :            : 
     127         [ +  + ]:        143 :         if (flags & SUBPROC_WARN)
     128                 :          4 :                 out = warning;
     129                 :            :         else
     130                 :        139 :                 out = ohshit;
     131                 :            : 
     132         [ +  + ]:        143 :         if (WIFEXITED(status)) {
     133                 :        139 :                 n = WEXITSTATUS(status);
     134         [ +  + ]:        139 :                 if (!n)
     135                 :        137 :                         return 0;
     136         [ +  - ]:          2 :                 if (flags & SUBPROC_RETERROR)
     137                 :          2 :                         return n;
     138                 :            : 
     139                 :          0 :                 out(_("%s subprocess returned error exit status %d"), desc, n);
     140         [ +  - ]:          4 :         } else if (WIFSIGNALED(status)) {
     141                 :          4 :                 n = WTERMSIG(status);
     142         [ -  + ]:          4 :                 if (!n)
     143                 :          0 :                         return 0;
     144   [ +  +  +  - ]:          4 :                 if ((flags & SUBPROC_NOPIPE) && n == SIGPIPE)
     145                 :          1 :                         return 0;
     146         [ -  + ]:          3 :                 if (flags & SUBPROC_RETSIGNO)
     147                 :          0 :                         return n;
     148                 :            : 
     149         [ +  + ]:          3 :                 if (n == SIGINT)
     150                 :          1 :                         out(_("%s subprocess was interrupted"), desc);
     151                 :            :                 else
     152                 :          2 :                         out(_("%s subprocess was killed by signal (%s)%s"),
     153                 :            :                             desc, strsignal(n),
     154         [ -  + ]:          2 :                             WCOREDUMP(status) ? _(", core dumped") : "");
     155                 :            :         } else {
     156         [ #  # ]:          0 :                 if (flags & SUBPROC_RETERROR)
     157                 :          0 :                         return -1;
     158                 :            : 
     159                 :          0 :                 out(_("%s subprocess failed with wait status code %d"), desc,
     160                 :            :                     status);
     161                 :            :         }
     162                 :            : 
     163                 :          3 :         return -1;
     164                 :            : }
     165                 :            : 
     166                 :            : static int
     167                 :        143 : subproc_wait(pid_t pid, const char *desc)
     168                 :            : {
     169                 :            :         pid_t dead_pid;
     170                 :            :         int status;
     171                 :            : 
     172   [ -  +  -  - ]:        143 :         while ((dead_pid = waitpid(pid, &status, 0)) == -1 && errno == EINTR) ;
     173                 :            : 
     174         [ -  + ]:        143 :         if (dead_pid != pid) {
     175                 :          0 :                 onerr_abort++;
     176                 :          0 :                 ohshite(_("wait for %s subprocess failed"), desc);
     177                 :            :         }
     178                 :            : 
     179                 :        143 :         return status;
     180                 :            : }
     181                 :            : 
     182                 :            : int
     183                 :        143 : subproc_reap(pid_t pid, const char *desc, enum subproc_flags flags)
     184                 :            : {
     185                 :            :         int status, rc;
     186                 :            : 
     187                 :        143 :         status = subproc_wait(pid, desc);
     188                 :            : 
     189         [ -  + ]:        143 :         if (flags & SUBPROC_NOCHECK)
     190                 :          0 :                 rc = status;
     191                 :            :         else
     192                 :        143 :                 rc = subproc_check(status, desc, flags);
     193                 :            : 
     194                 :        143 :         return rc;
     195                 :            : }

Generated by: LCOV version 1.16