(sys_exec_command,sys_wait_command): New functions

This commit is contained in:
Sergey Poznyakoff
2005-02-05 10:34:46 +00:00
parent 75a16f75a9
commit 0b939d7dbc

View File

@@ -626,5 +626,170 @@ sys_child_open_for_uncompress (void)
exit (exit_status);
}
static void
dec_to_env (char *envar, uintmax_t num)
{
char buf[UINTMAX_STRSIZE_BOUND];
char *numstr;
numstr = STRINGIFY_BIGINT (num, buf);
setenv (envar, numstr, 1);
}
static void
oct_to_env (char *envar, unsigned long num)
{
char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
snprintf (buf, sizeof buf, "0%lo", num);
setenv (envar, buf, 1);
}
static void
str_to_env (char *envar, char const *str)
{
if (str)
setenv (envar, str, 1);
else
unsetenv (envar);
}
static void
chr_to_env (char *envar, char c)
{
char buf[2];
buf[0] = c;
buf[1] = 0;
setenv (envar, buf, 1);
}
static void
stat_to_env (char *name, char type, struct tar_stat_info *st)
{
chr_to_env ("TAR_FILETYPE", type);
oct_to_env ("TAR_MODE", st->stat.st_mode);
str_to_env ("TAR_FILENAME", name);
str_to_env ("TAR_REALNAME", st->file_name);
str_to_env ("TAR_UNAME", st->uname);
str_to_env ("TAR_GNAME", st->gname);
dec_to_env ("TAR_MTIME", st->stat.st_mtime);
dec_to_env ("TAR_ATIME", st->stat.st_atime);
dec_to_env ("TAR_CTIME", st->stat.st_ctime);
dec_to_env ("TAR_SIZE", st->stat.st_size);
dec_to_env ("TAR_UID", st->stat.st_uid);
dec_to_env ("TAR_GID", st->stat.st_gid);
switch (type)
{
case 'b':
case 'c':
dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev));
dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev));
unsetenv ("TAR_LINKNAME");
break;
case 'l':
case 'h':
unsetenv ("TAR_MINOR");
unsetenv ("TAR_MAJOR");
str_to_env ("TAR_LINKNAME", st->link_name);
break;
default:
unsetenv ("TAR_MINOR");
unsetenv ("TAR_MAJOR");
unsetenv ("TAR_LINKNAME");
break;
}
}
static pid_t pid;
static RETSIGTYPE (*pipe_handler) (int sig);
int
sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
{
int p[2];
char *argv[4];
if (pipe (p))
{
pipe_error (file_name);
return -1;
}
pipe_handler = signal (SIGPIPE, SIG_IGN);
pid = fork ();
if (pid < 0)
{
fork_error (file_name);
close (p[1]);
close (p[0]);
signal (SIGPIPE, pipe_handler);
return -1;
}
if (pid != 0)
{
close (p[0]);
return p[1];
}
/* Child */
close (0);
dup (p[0]);
close (p[1]);
stat_to_env (file_name, typechar, st);
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = to_command_option;
argv[3] = NULL;
execv ("/bin/sh", argv);
exec_error (file_name);
_exit (127);
}
void
sys_wait_command (void)
{
int status;
if (pid < 0)
return;
signal (SIGPIPE, pipe_handler);
while (waitpid (pid, &status, 0) == -1)
if (errno != EINTR)
{
pid = -1;
waitpid_error (to_command_option);
return;
}
if (WIFEXITED (status))
{
if (!ignore_command_error_option && WEXITSTATUS (status))
ERROR ((0, 0, _("%lu: Child returned status %d"),
(unsigned long) pid, WEXITSTATUS (status)));
}
else if (WIFSIGNALED (status))
{
WARN ((0, 0, _("%lu: Child terminated on signal %d"),
(unsigned long) pid, WTERMSIG (status)));
}
else
ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
(unsigned long) pid, WTERMSIG (status)));
pid = -1;
}
#endif /* not MSDOS */