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:
20
NEWS
20
NEWS
@@ -1,4 +1,4 @@
|
||||
GNU tar NEWS - User visible changes. 2013-01-26
|
||||
GNU tar NEWS - User visible changes. 2013-02-10
|
||||
Please send GNU tar bug reports to <bug-tar@gnu.org>
|
||||
|
||||
|
||||
@@ -50,6 +50,24 @@ Additionally, the options --xattrs-include and --xattrs-exclude allow
|
||||
you to selectively control for which files to store (or extract) the
|
||||
extended attributes.
|
||||
|
||||
* Passing command line arguments to external commands.
|
||||
|
||||
Any option taking a command name as its argument now accepts a full
|
||||
command line as well. Thus, it is now possible to pass additional
|
||||
arguments to invoked programs. The affected options are:
|
||||
|
||||
--checkpoint-action=exec
|
||||
-I, --use-compress-program
|
||||
-F, --info-script
|
||||
--to-command
|
||||
|
||||
Furthermore, if any additional information is supplied to such a
|
||||
command via environment variables, these variables can now be used in
|
||||
the command line itself. Care should be taken to escape them, to
|
||||
prevent from being expanded too early, for example:
|
||||
|
||||
tar -x -f a.tar --info-script='changevol $TAR_ARCHIVE $TAR_VOLUME'
|
||||
|
||||
* New configure option --enable-gcc-warnings, intended for debugging.
|
||||
|
||||
|
||||
|
||||
180
doc/tar.texi
180
doc/tar.texi
@@ -1800,13 +1800,14 @@ and @option{--interactive} options (@pxref{interactive}).
|
||||
* Synopsis::
|
||||
* using tar options::
|
||||
* Styles::
|
||||
* All Options::
|
||||
* help::
|
||||
* defaults::
|
||||
* verbose::
|
||||
* checkpoints::
|
||||
* warnings::
|
||||
* interactive::
|
||||
* All Options:: All @command{tar} Options.
|
||||
* help:: Where to Get Help.
|
||||
* defaults:: What are the Default Values.
|
||||
* verbose:: Checking @command{tar} progress.
|
||||
* checkpoints:: Checkpoints.
|
||||
* warnings:: Controlling Warning Messages.
|
||||
* interactive:: Asking for Confirmation During Operations.
|
||||
* external:: Running External Commands.
|
||||
@end menu
|
||||
|
||||
@node Synopsis
|
||||
@@ -2784,14 +2785,14 @@ Send verbose output to @var{file} instead of to standard output.
|
||||
|
||||
@opsummary{info-script}
|
||||
@opsummary{new-volume-script}
|
||||
@item --info-script=@var{script-file}
|
||||
@itemx --new-volume-script=@var{script-file}
|
||||
@itemx -F @var{script-file}
|
||||
@item --info-script=@var{command}
|
||||
@itemx --new-volume-script=@var{command}
|
||||
@itemx -F @var{command}
|
||||
|
||||
When @command{tar} is performing multi-tape backups, @var{script-file} is run
|
||||
at the end of each tape. If @var{script-file} exits with nonzero status,
|
||||
@command{tar} fails immediately. @xref{info-script}, for a detailed
|
||||
discussion of @var{script-file}.
|
||||
When @command{tar} is performing multi-tape backups, @var{command} is run
|
||||
at the end of each tape. If it exits with nonzero status,
|
||||
@command{tar} fails immediately. @xref{info-script}, for a detailed
|
||||
discussion of this feature.
|
||||
|
||||
@opsummary{interactive}
|
||||
@item --interactive
|
||||
@@ -4004,17 +4005,22 @@ checkpoint:
|
||||
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=sleep=30}
|
||||
@end smallexample
|
||||
|
||||
@anchor{checkpoint exec}
|
||||
@cindex @code{exec}, checkpoint action
|
||||
Finally, the @code{exec} action executes a given external program.
|
||||
Finally, the @code{exec} action executes a given external command.
|
||||
For example:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -c --checkpoint=1000 --checkpoint-action=exec=/sbin/cpoint}
|
||||
@end smallexample
|
||||
|
||||
This program is executed using @command{/bin/sh -c}, with no
|
||||
additional arguments. Its exit code is ignored. It gets a copy of
|
||||
@command{tar}'s environment plus the following variables:
|
||||
The supplied command can be any valid command invocation, with or
|
||||
without additional command line arguments. If it does contain
|
||||
arguments, don't forget to quote it to prevent it from being split by
|
||||
the shell. @xref{external, Running External Commands}, for more detail.
|
||||
|
||||
The command gets a copy of @command{tar}'s environment plus the
|
||||
following variables:
|
||||
|
||||
@table @env
|
||||
@vrindex TAR_VERSION, checkpoint script environment
|
||||
@@ -4044,6 +4050,18 @@ Format of the archive being processed. @xref{Formats}, for a complete
|
||||
list of archive format names.
|
||||
@end table
|
||||
|
||||
These environment variables can also be passed as arguments to the
|
||||
command, provided that they are properly escaped, for example:
|
||||
|
||||
@smallexample
|
||||
@kbd{tar -c -f arc.tar \
|
||||
--checkpoint-action='exec=/sbin/cpoint $TAR_FILENAME'}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
Notice single quotes to prevent variable names from being expanded by
|
||||
the shell when invoking @command{tar}.
|
||||
|
||||
Any number of actions can be defined, by supplying several
|
||||
@option{--checkpoint-action} options in the command line. For
|
||||
example, the command below displays two messages, pauses
|
||||
@@ -4258,6 +4276,42 @@ named pipe to receive the archive, and having the consumer process to
|
||||
read from that named pipe. This has the advantage of letting standard
|
||||
output free to receive verbose output, all separate from errors.
|
||||
|
||||
@node external
|
||||
@section Running External Commands
|
||||
|
||||
Certain @GNUTAR{} operations imply running external commands that you
|
||||
supply on the command line. One of such operations is checkpointing,
|
||||
described above (@pxref{checkpoint exec}). Another example of this
|
||||
feature is the @option{-I} option, which allows you to supply the
|
||||
program to use for compressing or decompressing the archive
|
||||
(@pxref{use-compress-program}).
|
||||
|
||||
Whenever such operation is requested, @command{tar} first splits the
|
||||
supplied command into words much like the shell does. It then treats
|
||||
the first word as the name of the program or the shell script to execute
|
||||
and the rest of words as its command line arguments. The program,
|
||||
unless given as an absolute file name, is searched in the shell's
|
||||
@env{PATH}.
|
||||
|
||||
Any additional information is normally supplied to external commands
|
||||
in environment variables, specific to each particular operation. For
|
||||
example, the @option{--checkpoint-action=exec} option, defines the
|
||||
@env{TAR_ARCHIVE} variable to the name of the archive being worked
|
||||
upon. You can, should the need be, use these variables in the
|
||||
command line of the external command. For example:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -x -f archive.tar \
|
||||
--checkpoint=exec='printf "%04d in %32s\r" $TAR_CHECKPOINT $TAR_ARCHIVE'}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
This command prints for each checkpoint its number and the name of the
|
||||
archive, using the same output line on the screen.
|
||||
|
||||
Notice the use of single quotes to prevent variable names from being
|
||||
expanded by the shell when invoking @command{tar}.
|
||||
|
||||
@node operations
|
||||
@chapter @GNUTAR{} Operations
|
||||
|
||||
@@ -5470,11 +5524,13 @@ file to the standard input of an external program:
|
||||
@opindex to-command
|
||||
@item --to-command=@var{command}
|
||||
Extract files and pipe their contents to the standard input of
|
||||
@var{command}. When this option is used, instead of creating the
|
||||
@var{command}. When this option is used, instead of creating the
|
||||
files specified, @command{tar} invokes @var{command} and pipes the
|
||||
contents of the files to its standard output. The @var{command} may
|
||||
contain command line arguments. The program is executed via
|
||||
@code{sh -c}. Notice, that @var{command} is executed once for each regular file
|
||||
contents of the files to its standard output. The @var{command} may
|
||||
contain command line arguments (see @ref{external, Running External Commands},
|
||||
for more detail).
|
||||
|
||||
Notice, that @var{command} is executed once for each regular file
|
||||
extracted. Non-regular files (directories, etc.) are ignored when this
|
||||
option is used.
|
||||
@end table
|
||||
@@ -5572,6 +5628,20 @@ Format of the archive being processed. @xref{Formats}, for a complete
|
||||
list of archive format names.
|
||||
@end table
|
||||
|
||||
These variables are defined prior to executing the command, so you can
|
||||
pass them as arguments, if you prefer. For example, if the command
|
||||
@var{proc} takes the member name and size as its arguments, then you
|
||||
could do:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -x -f archive.tar \
|
||||
--to-command='proc $TAR_FILENAME $TAR_SIZE'}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
Notice single quotes to prevent variable names from being expanded by
|
||||
the shell when invoking @command{tar}.
|
||||
|
||||
If @var{command} exits with a non-0 status, @command{tar} will print
|
||||
an error message similar to the following:
|
||||
|
||||
@@ -8932,9 +9002,15 @@ environment variable. For example, with @command{gzip} you can set
|
||||
@smallexample
|
||||
$ @kbd{GZIP='-9 -n' tar czf archive.tar.gz subdir}
|
||||
@end smallexample
|
||||
Another way would be to use the @option{-I} option instead (see
|
||||
below), e.g.:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar -cf archive.tar.gz -I 'gzip -9 -n' subdir}
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
The traditional way to do this is to use a pipe:
|
||||
Finally, the third, traditional, way to do this is to use a pipe:
|
||||
|
||||
@smallexample
|
||||
$ @kbd{tar cf - subdir | gzip -9 -n > archive.tar.gz}
|
||||
@@ -8977,20 +9053,29 @@ suffix. The following suffixes are recognized:
|
||||
@item @samp{.xz} @tab @command{xz}
|
||||
@end multitable
|
||||
|
||||
@anchor{use-compress-program}
|
||||
@opindex use-compress-program
|
||||
@item --use-compress-program=@var{prog}
|
||||
@itemx -I=@var{prog}
|
||||
Use external compression program @var{prog}. Use this option if you
|
||||
@item --use-compress-program=@var{command}
|
||||
@itemx -I=@var{command}
|
||||
Use external compression program @var{command}. Use this option if you
|
||||
are not happy with the compression program associated with the suffix
|
||||
at compile time or if you have a compression program that @GNUTAR{}
|
||||
does not support. The program should follow two conventions:
|
||||
does not support. The @var{command} argument is a valid command
|
||||
invocation, as you would type it at the command line prompt, with any
|
||||
additional options as needed. Enclose it in quotes if it contains
|
||||
white space (see @ref{external, Running External Commands}, for more detail).
|
||||
|
||||
First, when invoked without options, it should read data from standard
|
||||
input, compress it and output it on standard output.
|
||||
The @var{command} should follow two conventions:
|
||||
|
||||
Secondly, if invoked with the @option{-d} option, it should do exactly
|
||||
the opposite, i.e., read the compressed data from the standard input
|
||||
and produce uncompressed data on the standard output.
|
||||
First, when invoked without additional options, it should read data
|
||||
from standard input, compress it and output it on standard output.
|
||||
|
||||
Secondly, if invoked with the additional @option{-d} option, it should
|
||||
do exactly the opposite, i.e., read the compressed data from the
|
||||
standard input and produce uncompressed data on the standard output.
|
||||
|
||||
The latter requirement means that you must not use the @option{-d}
|
||||
option as a part of the @var{command} itself.
|
||||
@end table
|
||||
|
||||
@cindex gpg, using with tar
|
||||
@@ -10462,10 +10547,10 @@ maximum tape length, you might avoid the problem entirely.
|
||||
|
||||
@xopindex{info-script, short description}
|
||||
@xopindex{new-volume-script, short description}
|
||||
@item -F @var{file}
|
||||
@itemx --info-script=@var{file}
|
||||
@itemx --new-volume-script=@var{file}
|
||||
Execute @file{file} at end of each tape. This implies
|
||||
@item -F @var{command}
|
||||
@itemx --info-script=@var{command}
|
||||
@itemx --new-volume-script=@var{command}
|
||||
Execute @var{command} at end of each tape. This implies
|
||||
@option{--multi-volume} (@option{-M}). @xref{info-script}, for a detailed
|
||||
description of this option.
|
||||
@end table
|
||||
@@ -11345,19 +11430,20 @@ volume, and instruct @command{tar} to use it instead of its normal
|
||||
prompting procedure:
|
||||
|
||||
@table @option
|
||||
@item --info-script=@var{script-name}
|
||||
@itemx --new-volume-script=@var{script-name}
|
||||
@itemx -F @var{script-name}
|
||||
Specify the full name of the volume script to use. The script can be
|
||||
used to eject cassettes, or to broadcast messages such as
|
||||
@item --info-script=@var{command}
|
||||
@itemx --new-volume-script=@var{command}
|
||||
@itemx -F @var{command}
|
||||
Specify the command to invoke when switching volumes. The @var{command}
|
||||
can be used to eject cassettes, or to broadcast messages such as
|
||||
@samp{Someone please come change my tape} when performing unattended
|
||||
backups.
|
||||
@end table
|
||||
|
||||
The @var{script-name} is executed without any command line
|
||||
arguments. It inherits @command{tar}'s shell environment.
|
||||
Additional data is passed to it via the following
|
||||
environment variables:
|
||||
The @var{command} can contain additional options, if such are needed.
|
||||
@xref{external, Running External Commands}, for a detailed discussion
|
||||
of the way @GNUTAR{} runs external commands. It inherits
|
||||
@command{tar}'s shell environment. Additional data is passed to it
|
||||
via the following environment variables:
|
||||
|
||||
@table @env
|
||||
@vrindex TAR_VERSION, info script environment variable
|
||||
@@ -11392,6 +11478,10 @@ File descriptor which can be used to communicate the new volume
|
||||
name to @command{tar}.
|
||||
@end table
|
||||
|
||||
These variables can be used in the @var{command} itself, provided that
|
||||
they are properly quoted to prevent them from being expanded by the
|
||||
shell that invokes @command{tar}.
|
||||
|
||||
The volume script can instruct @command{tar} to use new archive name,
|
||||
by writing in to file descriptor @env{$TAR_FD} (see below for an example).
|
||||
|
||||
|
||||
@@ -30,7 +30,15 @@ CLEANFILES = rmt-command.h rmt-command.h-t
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/gnu -I../ -I../gnu
|
||||
AM_CFLAGS = $(GNULIB_WARN_CFLAGS) $(WERROR_CFLAGS)
|
||||
|
||||
noinst_HEADERS = system.h system-ioctl.h rmt.h paxlib.h stdopen.h xattr-at.h
|
||||
noinst_HEADERS = \
|
||||
paxlib.h\
|
||||
rmt.h\
|
||||
stdopen.h\
|
||||
system.h\
|
||||
system-ioctl.h\
|
||||
wordsplit.h\
|
||||
xattr-at.h
|
||||
|
||||
libtar_a_SOURCES = \
|
||||
paxerror.c paxexit-status.c paxlib.h paxnames.c \
|
||||
prepargs.c prepargs.h \
|
||||
@@ -38,6 +46,7 @@ libtar_a_SOURCES = \
|
||||
rmt.h \
|
||||
stdopen.c stdopen.h \
|
||||
system.h system-ioctl.h \
|
||||
wordsplit.c\
|
||||
xattr-at.c
|
||||
|
||||
if !TAR_COND_XATTR_H
|
||||
|
||||
1625
lib/wordsplit.c
Normal file
1625
lib/wordsplit.c
Normal file
File diff suppressed because it is too large
Load Diff
162
lib/wordsplit.h
Normal file
162
lib/wordsplit.h
Normal file
@@ -0,0 +1,162 @@
|
||||
/* wordsplit - a word splitter
|
||||
Copyright (C) 2009-2013 Free Software Foundation, Inc.
|
||||
|
||||
This program 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 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
This program 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Written by Sergey Poznyakoff
|
||||
*/
|
||||
|
||||
#ifndef __WORDSPLIT_H
|
||||
#define __WORDSPLIT_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct wordsplit
|
||||
{
|
||||
size_t ws_wordc;
|
||||
char **ws_wordv;
|
||||
size_t ws_offs;
|
||||
size_t ws_wordn;
|
||||
int ws_flags;
|
||||
const char *ws_delim;
|
||||
const char *ws_comment;
|
||||
const char *ws_escape;
|
||||
void (*ws_alloc_die) (struct wordsplit * wsp);
|
||||
void (*ws_error) (const char *, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
void (*ws_debug) (const char *, ...)
|
||||
__attribute__ ((__format__ (__printf__, 1, 2)));
|
||||
|
||||
const char **ws_env;
|
||||
const char *(*ws_getvar) (const char *, size_t, void *);
|
||||
void *ws_closure;
|
||||
|
||||
const char *ws_input;
|
||||
size_t ws_len;
|
||||
size_t ws_endp;
|
||||
int ws_errno;
|
||||
struct wordsplit_node *ws_head, *ws_tail;
|
||||
};
|
||||
|
||||
/* Wordsplit flags. Only 2 bits of a 32-bit word remain unused.
|
||||
It is getting crowded... */
|
||||
/* Append the words found to the array resulting from a previous
|
||||
call. */
|
||||
#define WRDSF_APPEND 0x00000001
|
||||
/* Insert we_offs initial NULLs in the array ws_wordv.
|
||||
(These are not counted in the returned ws_wordc.) */
|
||||
#define WRDSF_DOOFFS 0x00000002
|
||||
/* Don't do command substitution. Reserved for future use. */
|
||||
#define WRDSF_NOCMD 0x00000004
|
||||
/* The parameter p resulted from a previous call to
|
||||
wordsplit(), and wordsplit_free() was not called. Reuse the
|
||||
allocated storage. */
|
||||
#define WRDSF_REUSE 0x00000008
|
||||
/* Print errors */
|
||||
#define WRDSF_SHOWERR 0x00000010
|
||||
/* Consider it an error if an undefined shell variable
|
||||
is expanded. */
|
||||
#define WRDSF_UNDEF 0x00000020
|
||||
|
||||
/* Don't do variable expansion. */
|
||||
#define WRDSF_NOVAR 0x00000040
|
||||
/* Abort on ENOMEM error */
|
||||
#define WRDSF_ENOMEMABRT 0x00000080
|
||||
/* Trim off any leading and trailind whitespace */
|
||||
#define WRDSF_WS 0x00000100
|
||||
/* Handle single quotes */
|
||||
#define WRDSF_SQUOTE 0x00000200
|
||||
/* Handle double quotes */
|
||||
#define WRDSF_DQUOTE 0x00000400
|
||||
/* Handle quotes and escape directives */
|
||||
#define WRDSF_QUOTE (WRDSF_SQUOTE|WRDSF_DQUOTE)
|
||||
/* Replace each input sequence of repeated delimiters with a single
|
||||
delimiter */
|
||||
#define WRDSF_SQUEEZE_DELIMS 0x00000800
|
||||
/* Return delimiters */
|
||||
#define WRDSF_RETURN_DELIMS 0x00001000
|
||||
/* Treat sed expressions as words */
|
||||
#define WRDSF_SED_EXPR 0x00002000
|
||||
/* ws_delim field is initialized */
|
||||
#define WRDSF_DELIM 0x00004000
|
||||
/* ws_comment field is initialized */
|
||||
#define WRDSF_COMMENT 0x00008000
|
||||
/* ws_alloc_die field is initialized */
|
||||
#define WRDSF_ALLOC_DIE 0x00010000
|
||||
/* ws_error field is initialized */
|
||||
#define WRDSF_ERROR 0x00020000
|
||||
/* ws_debug field is initialized */
|
||||
#define WRDSF_DEBUG 0x00040000
|
||||
/* ws_env field is initialized */
|
||||
#define WRDSF_ENV 0x00080000
|
||||
/* ws_getvar field is initialized */
|
||||
#define WRDSF_GETVAR 0x00100000
|
||||
/* enable debugging */
|
||||
#define WRDSF_SHOWDBG 0x00200000
|
||||
/* Don't split input into words. Useful for side effects. */
|
||||
#define WRDSF_NOSPLIT 0x00400000
|
||||
/* Keep undefined variables in place, instead of expanding them to
|
||||
empty string */
|
||||
#define WRDSF_KEEPUNDEF 0x00800000
|
||||
/* Warn about undefined variables */
|
||||
#define WRDSF_WARNUNDEF 0x01000000
|
||||
/* Handle C escapes */
|
||||
#define WRDSF_CESCAPES 0x02000000
|
||||
|
||||
/* ws_closure is set */
|
||||
#define WRDSF_CLOSURE 0x04000000
|
||||
/* ws_env is a Key/Value environment, i.e. the value of a variable is
|
||||
stored in the element that follows its name. */
|
||||
#define WRDSF_ENV_KV 0x08000000
|
||||
|
||||
/* ws_escape is set */
|
||||
#define WRDSF_ESCAPE 0x10000000
|
||||
|
||||
/* Incremental mode */
|
||||
#define WRDSF_INCREMENTAL 0x20000000
|
||||
|
||||
#define WRDSF_DEFFLAGS \
|
||||
(WRDSF_NOVAR | WRDSF_NOCMD | \
|
||||
WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_CESCAPES)
|
||||
|
||||
#define WRDSE_EOF 0
|
||||
#define WRDSE_QUOTE 1
|
||||
#define WRDSE_NOSPACE 2
|
||||
#define WRDSE_NOSUPP 3
|
||||
#define WRDSE_USAGE 4
|
||||
#define WRDSE_CBRACE 5
|
||||
#define WRDSE_UNDEF 6
|
||||
#define WRDSE_NOINPUT 7
|
||||
|
||||
int wordsplit (const char *s, struct wordsplit *p, int flags);
|
||||
int wordsplit_len (const char *s, size_t len,
|
||||
struct wordsplit *p, int flags);
|
||||
void wordsplit_free (struct wordsplit *p);
|
||||
void wordsplit_free_words (struct wordsplit *ws);
|
||||
|
||||
int wordsplit_c_unquote_char (int c);
|
||||
int wordsplit_c_quote_char (int c);
|
||||
size_t wordsplit_c_quoted_length (const char *str, int quote_hex,
|
||||
int *quote);
|
||||
void wordsplit_general_unquote_copy (char *dst, const char *src, size_t n,
|
||||
const char *escapable);
|
||||
void wordsplit_sh_unquote_copy (char *dst, const char *src, size_t n);
|
||||
void wordsplit_c_unquote_copy (char *dst, const char *src, size_t n);
|
||||
void wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex);
|
||||
|
||||
void wordsplit_perror (struct wordsplit *ws);
|
||||
const char *wordsplit_strerror (struct wordsplit *ws);
|
||||
|
||||
|
||||
#endif
|
||||
70
src/system.c
70
src/system.c
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user