LCOV - code coverage report
Current view: top level - lib/dpkg - command.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 65 67 97.0 %
Date: 2022-12-03 00:40:01 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 14 16 87.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * libdpkg - Debian packaging suite library routines
       3                 :            :  * command.c - command execution support
       4                 :            :  *
       5                 :            :  * Copyright © 2010-2012 Guillem Jover <guillem@debian.org>
       6                 :            :  *
       7                 :            :  * This is free software; you can redistribute it and/or modify
       8                 :            :  * it under the terms of the GNU General Public License as published by
       9                 :            :  * the Free Software Foundation; either version 2 of the License, or
      10                 :            :  * (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            :  * GNU General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU General Public License
      18                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      19                 :            :  */
      20                 :            : 
      21                 :            : #include <config.h>
      22                 :            : #include <compat.h>
      23                 :            : 
      24                 :            : #include <stdarg.h>
      25                 :            : #include <stdlib.h>
      26                 :            : #include <unistd.h>
      27                 :            : 
      28                 :            : #include <dpkg/dpkg.h>
      29                 :            : #include <dpkg/i18n.h>
      30                 :            : #include <dpkg/string.h>
      31                 :            : #include <dpkg/path.h>
      32                 :            : #include <dpkg/command.h>
      33                 :            : 
      34                 :            : /**
      35                 :            :  * Initialize a command structure.
      36                 :            :  *
      37                 :            :  * If name is NULL, then the last component of the filename path will be
      38                 :            :  * used to initialize the name member.
      39                 :            :  *
      40                 :            :  * @param cmd The command structure to initialize.
      41                 :            :  * @param filename The filename of the command to execute.
      42                 :            :  * @param name The description of the command to execute.
      43                 :            :  */
      44                 :            : void
      45                 :         53 : command_init(struct command *cmd, const char *filename, const char *name)
      46                 :            : {
      47                 :         53 :         cmd->filename = filename;
      48         [ +  + ]:         53 :         if (name == NULL)
      49                 :          6 :                 cmd->name = path_basename(filename);
      50                 :            :         else
      51                 :         47 :                 cmd->name = name;
      52                 :         53 :         cmd->argc = 0;
      53                 :         53 :         cmd->argv_size = 10;
      54                 :         53 :         cmd->argv = m_malloc(cmd->argv_size * sizeof(cmd->argv[0]));
      55                 :         53 :         cmd->argv[0] = NULL;
      56                 :         53 : }
      57                 :            : 
      58                 :            : /**
      59                 :            :  * Destroy a command structure.
      60                 :            :  *
      61                 :            :  * Free the members managed by the command functions (i.e. the argv pointer
      62                 :            :  * array), and zero all members of a command structure.
      63                 :            :  *
      64                 :            :  * @param cmd The command structure to free.
      65                 :            :  */
      66                 :            : void
      67                 :          8 : command_destroy(struct command *cmd)
      68                 :            : {
      69                 :          8 :         cmd->filename = NULL;
      70                 :          8 :         cmd->name = NULL;
      71                 :          8 :         cmd->argc = 0;
      72                 :          8 :         cmd->argv_size = 0;
      73                 :          8 :         free(cmd->argv);
      74                 :          8 :         cmd->argv = NULL;
      75                 :          8 : }
      76                 :            : 
      77                 :            : static void
      78                 :        226 : command_grow_argv(struct command *cmd, int need)
      79                 :            : {
      80                 :            :         /* We need a ghost byte for the NUL character. */
      81                 :        226 :         need++;
      82                 :            : 
      83                 :            :         /* Check if we already have enough room. */
      84         [ +  + ]:        226 :         if ((cmd->argv_size - cmd->argc) >= need)
      85                 :        205 :                 return;
      86                 :            : 
      87                 :         21 :         cmd->argv_size = (cmd->argv_size + need) * 2;
      88                 :         21 :         cmd->argv = m_realloc(cmd->argv, cmd->argv_size * sizeof(cmd->argv[0]));
      89                 :            : }
      90                 :            : 
      91                 :            : /**
      92                 :            :  * Append an argument to the command's argv.
      93                 :            :  *
      94                 :            :  * @param cmd The command structure to act on.
      95                 :            :  * @param arg The argument to append to argv.
      96                 :            :  */
      97                 :            : void
      98                 :        161 : command_add_arg(struct command *cmd, const char *arg)
      99                 :            : {
     100                 :        161 :         command_grow_argv(cmd, 1);
     101                 :            : 
     102                 :        161 :         cmd->argv[cmd->argc++] = arg;
     103                 :        161 :         cmd->argv[cmd->argc] = NULL;
     104                 :        161 : }
     105                 :            : 
     106                 :            : /**
     107                 :            :  * Append an argument array to the command's argv.
     108                 :            :  *
     109                 :            :  * @param cmd The command structure to act on.
     110                 :            :  * @param argv The NULL terminated argument array to append to argv.
     111                 :            :  */
     112                 :            : void
     113                 :          1 : command_add_argl(struct command *cmd, const char **argv)
     114                 :            : {
     115                 :          1 :         int i, add_argc = 0;
     116                 :            : 
     117         [ +  + ]:          4 :         while (argv[add_argc] != NULL)
     118                 :          3 :                 add_argc++;
     119                 :            : 
     120                 :          1 :         command_grow_argv(cmd, add_argc);
     121                 :            : 
     122         [ +  + ]:          4 :         for (i = 0; i < add_argc; i++)
     123                 :          3 :                 cmd->argv[cmd->argc++] = argv[i];
     124                 :            : 
     125                 :          1 :         cmd->argv[cmd->argc] = NULL;
     126                 :          1 : }
     127                 :            : 
     128                 :            : /**
     129                 :            :  * Append a va_list of argument to the command's argv.
     130                 :            :  *
     131                 :            :  * @param cmd The command structure to act on.
     132                 :            :  * @param args The NULL terminated va_list of argument array to append to argv.
     133                 :            :  */
     134                 :            : void
     135                 :         64 : command_add_argv(struct command *cmd, va_list args)
     136                 :            : {
     137                 :            :         va_list args_copy;
     138                 :         64 :         int i, add_argc = 0;
     139                 :            : 
     140                 :         64 :         va_copy(args_copy, args);
     141         [ +  + ]:        379 :         while (va_arg(args_copy, const char *) != NULL)
     142                 :        315 :                 add_argc++;
     143                 :         64 :         va_end(args_copy);
     144                 :            : 
     145                 :         64 :         command_grow_argv(cmd, add_argc);
     146                 :            : 
     147         [ +  + ]:        379 :         for (i = 0; i < add_argc; i++)
     148                 :        315 :                 cmd->argv[cmd->argc++] = va_arg(args, const char *);
     149                 :            : 
     150                 :         64 :         cmd->argv[cmd->argc] = NULL;
     151                 :         64 : }
     152                 :            : 
     153                 :            : /**
     154                 :            :  * Append a variable list of argument to the command's argv.
     155                 :            :  *
     156                 :            :  * @param cmd The command structure to act on.
     157                 :            :  * @param ... The NULL terminated variable list of argument to append to argv.
     158                 :            :  */
     159                 :            : void
     160                 :         64 : command_add_args(struct command *cmd, ...)
     161                 :            : {
     162                 :            :         va_list args;
     163                 :            : 
     164                 :         64 :         va_start(args, cmd);
     165                 :         64 :         command_add_argv(cmd, args);
     166                 :         64 :         va_end(args);
     167                 :         64 : }
     168                 :            : 
     169                 :            : /**
     170                 :            :  * Execute the command specified.
     171                 :            :  *
     172                 :            :  * The command is executed searching the PATH if the filename does not
     173                 :            :  * contain any slashes, or using the full path if it's either a relative or
     174                 :            :  * absolute pathname. This functions does not return.
     175                 :            :  *
     176                 :            :  * @param cmd The command structure to act on.
     177                 :            :  */
     178                 :            : void
     179                 :         46 : command_exec(struct command *cmd)
     180                 :            : {
     181                 :         46 :         execvp(cmd->filename, (char * const *)cmd->argv);
     182                 :         46 :         ohshite(_("unable to execute %s (%s)"), cmd->name, cmd->filename);
     183                 :            : }
     184                 :            : 
     185                 :            : /**
     186                 :            :  * Execute a shell with a possible command.
     187                 :            :  *
     188                 :            :  * @param cmd The command string to execute, if it's NULL an interactive
     189                 :            :  *            shell will be executed instead.
     190                 :            :  * @param name The description of the command to execute.
     191                 :            :  */
     192                 :            : void
     193                 :          6 : command_shell(const char *cmd, const char *name)
     194                 :            : {
     195                 :            :         const char *shell;
     196                 :            :         const char *mode;
     197                 :            : 
     198         [ -  + ]:          6 :         if (cmd == NULL) {
     199                 :          0 :                 mode = "-i";
     200                 :          0 :                 shell = getenv("SHELL");
     201                 :            :         } else {
     202                 :          6 :                 mode = "-c";
     203                 :          6 :                 shell = NULL;
     204                 :            :         }
     205                 :            : 
     206         [ +  - ]:          6 :         if (str_is_unset(shell))
     207                 :          6 :                 shell = DEFAULTSHELL;
     208                 :            : 
     209                 :          6 :         execlp(shell, shell, mode, cmd, NULL);
     210                 :          6 :         ohshite(_("unable to execute %s (%s)"), name, cmd);
     211                 :            : }

Generated by: LCOV version 1.16