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
command_init(struct command * cmd,const char * filename,const char * name)45 command_init(struct command *cmd, const char *filename, const char *name)
46 {
47 cmd->filename = filename;
48 if (name == NULL)
49 cmd->name = path_basename(filename);
50 else
51 cmd->name = name;
52 cmd->argc = 0;
53 cmd->argv_size = 10;
54 cmd->argv = m_malloc(cmd->argv_size * sizeof(const char *));
55 cmd->argv[0] = NULL;
56 }
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
command_destroy(struct command * cmd)67 command_destroy(struct command *cmd)
68 {
69 cmd->filename = NULL;
70 cmd->name = NULL;
71 cmd->argc = 0;
72 cmd->argv_size = 0;
73 free(cmd->argv);
74 cmd->argv = NULL;
75 }
76
77 static void
command_grow_argv(struct command * cmd,int need)78 command_grow_argv(struct command *cmd, int need)
79 {
80 /* We need a ghost byte for the NUL character. */
81 need++;
82
83 /* Check if we already have enough room. */
84 if ((cmd->argv_size - cmd->argc) >= need)
85 return;
86
87 cmd->argv_size = (cmd->argv_size + need) * 2;
88 cmd->argv = m_realloc(cmd->argv, cmd->argv_size * sizeof(const char *));
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
command_add_arg(struct command * cmd,const char * arg)98 command_add_arg(struct command *cmd, const char *arg)
99 {
100 command_grow_argv(cmd, 1);
101
102 cmd->argv[cmd->argc++] = arg;
103 cmd->argv[cmd->argc] = NULL;
104 }
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
command_add_argl(struct command * cmd,const char ** argv)113 command_add_argl(struct command *cmd, const char **argv)
114 {
115 int i, add_argc = 0;
116
117 while (argv[add_argc] != NULL)
118 add_argc++;
119
120 command_grow_argv(cmd, add_argc);
121
122 for (i = 0; i < add_argc; i++)
123 cmd->argv[cmd->argc++] = argv[i];
124
125 cmd->argv[cmd->argc] = NULL;
126 }
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
command_add_argv(struct command * cmd,va_list args)135 command_add_argv(struct command *cmd, va_list args)
136 {
137 va_list args_copy;
138 int i, add_argc = 0;
139
140 va_copy(args_copy, args);
141 while (va_arg(args_copy, const char *) != NULL)
142 add_argc++;
143 va_end(args_copy);
144
145 command_grow_argv(cmd, add_argc);
146
147 for (i = 0; i < add_argc; i++)
148 cmd->argv[cmd->argc++] = va_arg(args, const char *);
149
150 cmd->argv[cmd->argc] = NULL;
151 }
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
command_add_args(struct command * cmd,...)160 command_add_args(struct command *cmd, ...)
161 {
162 va_list args;
163
164 va_start(args, cmd);
165 command_add_argv(cmd, args);
166 va_end(args);
167 }
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
command_exec(struct command * cmd)179 command_exec(struct command *cmd)
180 {
181 execvp(cmd->filename, (char * const *)cmd->argv);
182 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
command_shell(const char * cmd,const char * name)193 command_shell(const char *cmd, const char *name)
194 {
195 const char *shell;
196 const char *mode;
197
198 if (cmd == NULL) {
199 mode = "-i";
200 shell = getenv("SHELL");
201 } else {
202 mode = "-c";
203 shell = NULL;
204 }
205
206 if (str_is_unset(shell))
207 shell = DEFAULTSHELL;
208
209 execlp(shell, shell, mode, cmd, NULL);
210 ohshite(_("unable to execute %s (%s)"), name, cmd);
211 }
212