int 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 (); if (global_pid != 0) { xclose (p[PREAD]); return p[PWRITE]; } /* Child */ xdup2 (p[PREAD], STDIN_FILENO); xclose (p[PWRITE]); 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_fatal (file_name); }
static void 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) { WARNOPT (WARN_DECOMPRESS_PROGRAM, (0, errno, _("cannot run %s"), prog)); WARNOPT (WARN_DECOMPRESS_PROGRAM, (0, 0, _("trying %s"), p)); } 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] = (char *) "-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"))); exec_fatal (prog); }
void sys_spawn_shell (void) { pid_t child; const char *shell = getenv ("SHELL"); if (! shell) shell = "/bin/sh"; child = xfork (); if (child == 0) { priv_set_restore_linkdir (); execlp (shell, "-sh", "-i", NULL); exec_fatal (shell); } else { int wait_status; while (waitpid (child, &wait_status, 0) == -1) if (errno != EINTR) { waitpid_error (shell); break; } } }
static _Noreturn 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); }
void sys_exec_checkpoint_script (const char *script_name, const char *archive_name, int checkpoint_number) { pid_t pid; char *argv[4]; char uintbuf[UINTMAX_STRSIZE_BOUND]; pid = xfork (); if (pid != 0) { /* Master */ int status; while (waitpid (pid, &status, 0) == -1) if (errno != EINTR) { waitpid_error (script_name); break; } return; } /* Child */ setenv ("TAR_VERSION", PACKAGE_VERSION, 1); setenv ("TAR_ARCHIVE", archive_name, 1); setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1); setenv ("TAR_BLOCKING_FACTOR", STRINGIFY_BIGINT (blocking_factor, uintbuf), 1); setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1); setenv ("TAR_FORMAT", archive_format_string (current_format == DEFAULT_FORMAT ? archive_format : current_format), 1); argv[0] = "/bin/sh"; argv[1] = "-c"; argv[2] = (char*) script_name; argv[3] = NULL; execv (argv[0], argv); exec_fatal (script_name); }
int sys_exec_info_script (const char **archive_name, int volume_number) { pid_t pid; char *argv[4]; char uintbuf[UINTMAX_STRSIZE_BOUND]; int p[2]; static RETSIGTYPE (*saved_handler) (int sig); xpipe (p); saved_handler = signal (SIGPIPE, SIG_IGN); pid = xfork (); if (pid != 0) { /* Master */ int rc; int status; char *buf = NULL; size_t size = 0; FILE *fp; xclose (p[PWRITE]); fp = fdopen (p[PREAD], "r"); rc = getline (&buf, &size, fp); fclose (fp); if (rc > 0 && buf[rc-1] == '\n') buf[--rc] = 0; while (waitpid (pid, &status, 0) == -1) if (errno != EINTR) { signal (SIGPIPE, saved_handler); waitpid_error (info_script_option); return -1; } signal (SIGPIPE, saved_handler); if (WIFEXITED (status)) { if (WEXITSTATUS (status) == 0 && rc > 0) *archive_name = buf; else free (buf); return WEXITSTATUS (status); } free (buf); return -1; } /* Child */ setenv ("TAR_VERSION", PACKAGE_VERSION, 1); setenv ("TAR_ARCHIVE", *archive_name, 1); setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1); setenv ("TAR_BLOCKING_FACTOR", STRINGIFY_BIGINT (blocking_factor, uintbuf), 1); setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1); setenv ("TAR_FORMAT", 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] = "/bin/sh"; argv[1] = "-c"; argv[2] = (char*) info_script_option; argv[3] = NULL; execv (argv[0], argv); exec_fatal (info_script_option); }
/* Set ARCHIVE for uncompressing, then reading an archive. */ pid_t sys_child_open_for_uncompress (void) { int parent_pipe[2]; int child_pipe[2]; pid_t grandchild_pid; pid_t child_pid; xpipe (parent_pipe); child_pid = xfork (); if (child_pid > 0) { /* The parent tar is still here! Just clean up. */ archive = parent_pipe[PREAD]; xclose (parent_pipe[PWRITE]); return child_pid; } /* The newborn child tar is here! */ set_program_name (_("tar (child)")); signal (SIGPIPE, SIG_DFL); xdup2 (parent_pipe[PWRITE], STDOUT_FILENO); xclose (parent_pipe[PREAD]); /* Check if we need a grandchild tar. This happens only if either: a) we're reading stdin: to force unblocking; b) the file is to be accessed by rmt: compressor doesn't know how; c) the file is not a plain file. */ if (strcmp (archive_name_array[0], "-") != 0 && !_remdev (archive_name_array[0]) && is_regular_file (archive_name_array[0])) { /* We don't need a grandchild tar. Open the archive and lauch the uncompressor. */ archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW); if (archive < 0) open_fatal (archive_name_array[0]); xdup2 (archive, STDIN_FILENO); execlp (use_compress_program_option, use_compress_program_option, "-d", (char *) 0); exec_fatal (use_compress_program_option); } /* We do need a grandchild tar. */ xpipe (child_pipe); grandchild_pid = xfork (); if (grandchild_pid == 0) { /* The newborn grandchild tar is here! Launch the uncompressor. */ set_program_name (_("tar (grandchild)")); xdup2 (child_pipe[PREAD], STDIN_FILENO); xclose (child_pipe[PWRITE]); execlp (use_compress_program_option, use_compress_program_option, "-d", (char *) 0); exec_fatal (use_compress_program_option); } /* The child tar is still here! */ /* Prepare for unblocking the data from the archive into the uncompressor. */ xdup2 (child_pipe[PWRITE], STDOUT_FILENO); xclose (child_pipe[PREAD]); if (strcmp (archive_name_array[0], "-") == 0) archive = STDIN_FILENO; else archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW, rsh_command_option); if (archive < 0) open_fatal (archive_name_array[0]); /* Let's read the archive and pipe it into stdout. */ while (1) { char *cursor; size_t maximum; size_t count; size_t status; clear_read_error_count (); error_loop: status = rmtread (archive, record_start->buffer, record_size); if (status == SAFE_READ_ERROR) { archive_read_error (); goto error_loop; } if (status == 0) break; cursor = record_start->buffer; maximum = status; while (maximum) { count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE; if (full_write (STDOUT_FILENO, cursor, count) != count) write_error (use_compress_program_option); cursor += count; maximum -= count; } } xclose (STDOUT_FILENO); wait_for_grandchild (grandchild_pid); }
/* Set ARCHIVE for writing, then compressing an archive. */ pid_t sys_child_open_for_compress (void) { int parent_pipe[2]; int child_pipe[2]; pid_t grandchild_pid; pid_t child_pid; xpipe (parent_pipe); child_pid = xfork (); if (child_pid > 0) { /* The parent tar is still here! Just clean up. */ archive = parent_pipe[PWRITE]; xclose (parent_pipe[PREAD]); return child_pid; } /* The new born child tar is here! */ set_program_name (_("tar (child)")); signal (SIGPIPE, SIG_DFL); xdup2 (parent_pipe[PREAD], STDIN_FILENO); xclose (parent_pipe[PWRITE]); /* Check if we need a grandchild tar. This happens only if either: a) the file is to be accessed by rmt: compressor doesn't know how; b) the file is not a plain file. */ if (!_remdev (archive_name_array[0]) && is_regular_file (archive_name_array[0])) { if (backup_option) maybe_backup_file (archive_name_array[0], 1); /* We don't need a grandchild tar. Open the archive and launch the compressor. */ if (strcmp (archive_name_array[0], "-")) { archive = creat (archive_name_array[0], MODE_RW); if (archive < 0) { int saved_errno = errno; if (backup_option) undo_last_backup (); errno = saved_errno; open_fatal (archive_name_array[0]); } xdup2 (archive, STDOUT_FILENO); } execlp (use_compress_program_option, use_compress_program_option, NULL); exec_fatal (use_compress_program_option); } /* We do need a grandchild tar. */ xpipe (child_pipe); grandchild_pid = xfork (); if (grandchild_pid == 0) { /* The newborn grandchild tar is here! Launch the compressor. */ set_program_name (_("tar (grandchild)")); xdup2 (child_pipe[PWRITE], STDOUT_FILENO); xclose (child_pipe[PREAD]); execlp (use_compress_program_option, use_compress_program_option, (char *) 0); exec_fatal (use_compress_program_option); } /* The child tar is still here! */ /* Prepare for reblocking the data from the compressor into the archive. */ xdup2 (child_pipe[PREAD], STDIN_FILENO); xclose (child_pipe[PWRITE]); if (strcmp (archive_name_array[0], "-") == 0) archive = STDOUT_FILENO; else { archive = rmtcreat (archive_name_array[0], MODE_RW, rsh_command_option); if (archive < 0) open_fatal (archive_name_array[0]); } /* Let's read out of the stdin pipe and write an archive. */ while (1) { size_t status = 0; char *cursor; size_t length; /* Assemble a record. */ for (length = 0, cursor = record_start->buffer; length < record_size; length += status, cursor += status) { size_t size = record_size - length; status = safe_read (STDIN_FILENO, cursor, size); if (status == SAFE_READ_ERROR) read_fatal (use_compress_program_option); if (status == 0) break; } /* Copy the record. */ if (status == 0) { /* We hit the end of the file. Write last record at full length, as the only role of the grandchild is doing proper reblocking. */ if (length > 0) { memset (record_start->buffer + length, 0, record_size - length); status = sys_write_archive_buffer (); if (status != record_size) archive_write_error (status); } /* There is nothing else to read, break out. */ break; } status = sys_write_archive_buffer (); if (status != record_size) archive_write_error (status); } wait_for_grandchild (grandchild_pid); }