Pass command line arguments to external commands.

Any option taking a command name as its argument accepts
additional arguments as well.

* lib/wordsplit.c: New file.
* lib/wordsplit.h: New file.
* lib/Makefile.am: Add new files.
* src/system.c (xexec): New function.
(run_decompress_program): Use wordsplit.
(sys_child_open_for_compress,sys_exec_command)
(sys_exec_info_script)
(sys_exec_checkpoint_script): Use xexec to invoke external
command.

* NEWS: Update.
* doc/tar.texi: Update.
This commit is contained in:
Sergey Poznyakoff
2013-02-10 14:43:43 +02:00
parent 20dcc4d122
commit 7b5e803963
6 changed files with 1990 additions and 78 deletions
+39 -31
View File
@@ -21,6 +21,20 @@
#include <priv-set.h>
#include <rmt.h>
#include <signal.h>
#include <wordsplit.h>
static void
xexec (const char *cmd)
{
struct wordsplit ws;
ws.ws_env = (const char **) environ;
if (wordsplit (cmd, &ws, (WRDSF_DEFFLAGS | WRDSF_ENV) & ~WRDSF_NOVAR))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
cmd, wordsplit_strerror (&ws)));
execvp (ws.ws_wordv[0], ws.ws_wordv);
exec_fatal (cmd);
}
#if MSDOS
@@ -192,7 +206,7 @@ sys_spawn_shell (void)
if (child == 0)
{
priv_set_restore_linkdir ();
execlp (shell, "-sh", "-i", (char *) 0);
execlp (shell, "-sh", "-i", NULL);
exec_fatal (shell);
}
else
@@ -315,7 +329,7 @@ sys_child_open_for_compress (void)
int child_pipe[2];
pid_t grandchild_pid;
pid_t child_pid;
xpipe (parent_pipe);
child_pid = xfork ();
@@ -363,8 +377,7 @@ sys_child_open_for_compress (void)
xdup2 (archive, STDOUT_FILENO);
}
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option, NULL);
exec_fatal (use_compress_program_option);
xexec (use_compress_program_option);
}
/* We do need a grandchild tar. */
@@ -381,9 +394,7 @@ sys_child_open_for_compress (void)
xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
xclose (child_pipe[PREAD]);
priv_set_restore_linkdir ();
execlp (use_compress_program_option, use_compress_program_option,
(char *) 0);
exec_fatal (use_compress_program_option);
xexec (use_compress_program_option);
}
/* The child tar is still here! */
@@ -458,7 +469,12 @@ run_decompress_program (void)
{
int i;
const char *p, *prog = NULL;
struct wordsplit ws;
int wsflags = (WRDSF_DEFFLAGS | WRDSF_ENV | WRDSF_DOOFFS) & ~WRDSF_NOVAR;
ws.ws_env = (const char **) environ;
ws.ws_offs = 1;
for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
{
if (prog)
@@ -468,8 +484,16 @@ run_decompress_program (void)
WARNOPT (WARN_DECOMPRESS_PROGRAM,
(0, 0, _("trying %s"), p));
}
prog = p;
execlp (p, p, "-d", NULL);
if (wordsplit (p, &ws, wsflags))
FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
p, wordsplit_strerror (&ws)));
wsflags |= WRDSF_REUSE;
memmove(ws.ws_wordv, ws.ws_wordv + ws.ws_offs,
sizeof(ws.ws_wordv[0])*ws.ws_wordc);
ws.ws_wordv[ws.ws_wordc] = "-d";
prog = p;
execvp (ws.ws_wordv[0], ws.ws_wordv);
ws.ws_wordv[ws.ws_wordc] = NULL;
}
if (!prog)
FATAL_ERROR ((0, 0, _("unable to run decompression program")));
@@ -703,7 +727,7 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
{
int p[2];
char *argv[4];
xpipe (p);
pipe_handler = signal (SIGPIPE, SIG_IGN);
global_pid = xfork ();
@@ -720,15 +744,8 @@ sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
stat_to_env (file_name, typechar, st);
argv[0] = (char *) "/bin/sh";
argv[1] = (char *) "-c";
argv[2] = to_command_option;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv ("/bin/sh", argv);
exec_fatal (file_name);
xexec (to_command_option);
}
void
@@ -832,18 +849,11 @@ sys_exec_info_script (const char **archive_name, int volume_number)
archive_format_string (current_format == DEFAULT_FORMAT ?
archive_format : current_format), 1);
setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
xclose (p[PREAD]);
argv[0] = (char *) "/bin/sh";
argv[1] = (char *) "-c";
argv[2] = (char *) info_script_option;
argv[3] = NULL;
priv_set_restore_linkdir ();
execv (argv[0], argv);
exec_fatal (info_script_option);
xexec (info_script_option);
}
void
@@ -854,7 +864,7 @@ sys_exec_checkpoint_script (const char *script_name,
pid_t pid;
char *argv[4];
char uintbuf[UINTMAX_STRSIZE_BOUND];
pid = xfork ();
if (pid != 0)
@@ -889,9 +899,7 @@ sys_exec_checkpoint_script (const char *script_name,
argv[3] = NULL;
priv_set_restore_linkdir ();
execv (argv[0], argv);
exec_fatal (script_name);
xexec (script_name);
}
#endif /* not MSDOS */