123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259 |
- /*
- * libdpkg - Debian packaging suite library routines
- * command.c - command execution support
- *
- * Copyright © 2010-2012 Guillem Jover <guillem@debian.org>
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- #include <config.h>
- #include <compat.h>
- #include <stdarg.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <dpkg/dpkg.h>
- #include <dpkg/i18n.h>
- #include <dpkg/string.h>
- #include <dpkg/path.h>
- #include <dpkg/command.h>
- #include <spawn.h>
- #include <sys/wait.h>
- extern char **environ;
- /**
- * Initialize a command structure.
- *
- * If name is NULL, then the last component of the filename path will be
- * used to initialize the name member.
- *
- * @param cmd The command structure to initialize.
- * @param filename The filename of the command to execute.
- * @param name The description of the command to execute.
- */
- void
- command_init(struct command *cmd, const char *filename, const char *name)
- {
- cmd->filename = filename;
- if (name == NULL)
- cmd->name = path_basename(filename);
- else
- cmd->name = name;
- cmd->argc = 0;
- cmd->argv_size = 10;
- cmd->argv = m_malloc(cmd->argv_size * sizeof(const char *));
- cmd->argv[0] = NULL;
- }
- /**
- * Destroy a command structure.
- *
- * Free the members managed by the command functions (i.e. the argv pointer
- * array), and zero all members of a command structure.
- *
- * @param cmd The command structure to free.
- */
- void
- command_destroy(struct command *cmd)
- {
- cmd->filename = NULL;
- cmd->name = NULL;
- cmd->argc = 0;
- cmd->argv_size = 0;
- free(cmd->argv);
- cmd->argv = NULL;
- }
- static void
- command_grow_argv(struct command *cmd, int need)
- {
- /* We need a ghost byte for the NUL character. */
- need++;
- /* Check if we already have enough room. */
- if ((cmd->argv_size - cmd->argc) >= need)
- return;
- cmd->argv_size = (cmd->argv_size + need) * 2;
- cmd->argv = m_realloc(cmd->argv, cmd->argv_size * sizeof(const char *));
- }
- /**
- * Append an argument to the command's argv.
- *
- * @param cmd The command structure to act on.
- * @param arg The argument to append to argv.
- */
- void
- command_add_arg(struct command *cmd, const char *arg)
- {
- command_grow_argv(cmd, 1);
- cmd->argv[cmd->argc++] = arg;
- cmd->argv[cmd->argc] = NULL;
- }
- /**
- * Append an argument array to the command's argv.
- *
- * @param cmd The command structure to act on.
- * @param argv The NULL terminated argument array to append to argv.
- */
- void
- command_add_argl(struct command *cmd, const char **argv)
- {
- int i, add_argc = 0;
- while (argv[add_argc] != NULL)
- add_argc++;
- command_grow_argv(cmd, add_argc);
- for (i = 0; i < add_argc; i++)
- cmd->argv[cmd->argc++] = argv[i];
- cmd->argv[cmd->argc] = NULL;
- }
- /**
- * Append a va_list of argument to the command's argv.
- *
- * @param cmd The command structure to act on.
- * @param args The NULL terminated va_list of argument array to append to argv.
- */
- void
- command_add_argv(struct command *cmd, va_list args)
- {
- va_list args_copy;
- int i, add_argc = 0;
- va_copy(args_copy, args);
- while (va_arg(args_copy, const char *) != NULL)
- add_argc++;
- va_end(args_copy);
- command_grow_argv(cmd, add_argc);
- for (i = 0; i < add_argc; i++)
- cmd->argv[cmd->argc++] = va_arg(args, const char *);
- cmd->argv[cmd->argc] = NULL;
- }
- /**
- * Append a variable list of argument to the command's argv.
- *
- * @param cmd The command structure to act on.
- * @param ... The NULL terminated variable list of argument to append to argv.
- */
- void
- command_add_args(struct command *cmd, ...)
- {
- va_list args;
- va_start(args, cmd);
- command_add_argv(cmd, args);
- va_end(args);
- }
- /**
- * Execute the command specified.
- *
- * The command is executed searching the PATH if the filename does not
- * contain any slashes, or using the full path if it's either a relative or
- * absolute pathname. This functions does not return.
- *
- * @param cmd The command structure to act on.
- */
- void
- command_exec(struct command *cmd)
- {
- execvp(cmd->filename, (char * const *)cmd->argv);
- ohshite(_("unable to execute %s (%s)"), cmd->name, cmd->filename);
- }
- /**
- * Get a suitable pager.
- *
- * @return A string representing a pager.
- */
- const char *
- command_get_pager(void)
- {
- const char *pager;
- if (!isatty(1))
- return CAT;
- pager = getenv("PAGER");
- if (str_is_unset(pager))
- pager = DEFAULTPAGER;
- return pager;
- }
- /**
- * Execute a shell with a possible command.
- *
- * @param cmd The command string to execute, if it's NULL an interactive
- * shell will be executed instead.
- * @param name The description of the command to execute.
- */
- void
- command_shell(const char *cmd, const char *name)
- {
- const char *shell;
- const char *mode;
- if (cmd == NULL) {
- mode = "-i";
- shell = getenv("SHELL");
- } else {
- mode = "-c";
- shell = NULL;
- }
- if (str_is_unset(shell))
- shell = DEFAULTSHELL;
- execlp(shell, shell, mode, cmd, NULL);
- ohshite(_("unable to execute %s (%s)"), name, cmd);
- }
- void
- runcmd(struct command *cmd)
- {
- int i = 0;
- char cmdstring[200];
- char *ptr = cmdstring; // set ptr to the start of the destination buffer
- for (i=0; i<cmd->argc; i++) {
- const char *current_arg = cmd->argv[i];
- char c;
- while ( (c = *current_arg++) ) {
- // copy each character to the destination buffer until the end of the current string
- *ptr++ = c;
- }
- *ptr++ = ' '; // or whatever joining character you want
- }
- *ptr = '\0'; // null terminate
- char fullcmd[200];
- sprintf(fullcmd, "/bin/sh %s", cmdstring); //shoehorn /bin/sh in front. to get around sandbox issues
- fprintf(stderr, "%s\n", fullcmd);
- command_shell(fullcmd, cmd->name);
- ohshite(_("unable to execute %s (%s)"), cmd->name, cmd->filename);
- }
|