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 : : }