(root)/
tar-1.35/
src/
system.c
       1  /* System-dependent calls for tar.
       2  
       3     Copyright 2003-2023 Free Software Foundation, Inc.
       4  
       5     This program is free software; you can redistribute it and/or modify it
       6     under the terms of the GNU General Public License as published by the
       7     Free Software Foundation; either version 3, or (at your option) any later
       8     version.
       9  
      10     This program is distributed in the hope that it will be useful, but
      11     WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
      13     Public License for more details.
      14  
      15     You should have received a copy of the GNU General Public License along
      16     with this program.  If not, see <http://www.gnu.org/licenses/>.  */
      17  
      18  #include <system.h>
      19  #include <system-ioctl.h>
      20  
      21  #include "common.h"
      22  #include <priv-set.h>
      23  #include <rmt.h>
      24  #include <signal.h>
      25  #include <wordsplit.h>
      26  
      27  static _Noreturn void
      28  xexec (const char *cmd)
      29  {
      30    char *argv[4];
      31  
      32    argv[0] = (char *) "/bin/sh";
      33    argv[1] = (char *) "-c";
      34    argv[2] = (char *) cmd;
      35    argv[3] = NULL;
      36  
      37    execv ("/bin/sh", argv);
      38    exec_fatal (cmd);
      39  }
      40  
      41  /* True if the archive is seekable via ioctl and MTIOCTOP,
      42     or if it is not known whether it is seekable.
      43     False if it is known to be not seekable.  */
      44  static bool mtioseekable_archive;
      45  
      46  bool
      47  mtioseek (bool count_files, off_t count)
      48  {
      49    if (mtioseekable_archive)
      50      {
      51  #ifdef MTIOCTOP
      52        struct mtop operation;
      53        operation.mt_op = (count_files
      54  			 ? (count < 0 ? MTBSF : MTFSF)
      55  			 : (count < 0 ? MTBSR : MTFSR));
      56        if (! (count < 0
      57  	     ? INT_SUBTRACT_WRAPV (0, count, &operation.mt_count)
      58  	     : INT_ADD_WRAPV (count, 0, &operation.mt_count))
      59  	  && (0 <= rmtioctl (archive, MTIOCTOP, &operation)
      60  	      || (errno == EIO
      61  		  && 0 <= rmtioctl (archive, MTIOCTOP, &operation))))
      62  	return true;
      63  #endif
      64  
      65        mtioseekable_archive = false;
      66      }
      67    return false;
      68  }
      69  
      70  #if MSDOS
      71  
      72  bool
      73  sys_get_archive_stat (void)
      74  {
      75    return 0;
      76  }
      77  
      78  bool
      79  sys_file_is_archive (struct tar_stat_info *p)
      80  {
      81    return false;
      82  }
      83  
      84  void
      85  sys_detect_dev_null_output (void)
      86  {
      87    static char const dev_null[] = "nul";
      88  
      89    dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
      90  		     || (! _isrmt (archive)));
      91  }
      92  
      93  void
      94  sys_wait_for_child (pid_t child_pid, bool eof)
      95  {
      96  }
      97  
      98  void
      99  sys_spawn_shell (void)
     100  {
     101    spawnl (P_WAIT, getenv ("COMSPEC"), "-", 0);
     102  }
     103  
     104  /* stat() in djgpp's C library gives a constant number of 42 as the
     105     uid and gid of a file.  So, comparing an FTP'ed archive just after
     106     unpack would fail on MSDOS.  */
     107  
     108  bool
     109  sys_compare_uid (struct stat *a, struct stat *b)
     110  {
     111    return true;
     112  }
     113  
     114  bool
     115  sys_compare_gid (struct stat *a, struct stat *b)
     116  {
     117    return true;
     118  }
     119  
     120  void
     121  sys_compare_links (struct stat *link_data, struct stat *stat_data)
     122  {
     123    return true;
     124  }
     125  
     126  int
     127  sys_truncate (int fd)
     128  {
     129    return write (fd, "", 0);
     130  }
     131  
     132  size_t
     133  sys_write_archive_buffer (void)
     134  {
     135    return full_write (archive, record_start->buffer, record_size);
     136  }
     137  
     138  /* Set ARCHIVE for writing, then compressing an archive.  */
     139  void
     140  sys_child_open_for_compress (void)
     141  {
     142    FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
     143  }
     144  
     145  /* Set ARCHIVE for uncompressing, then reading an archive.  */
     146  void
     147  sys_child_open_for_uncompress (void)
     148  {
     149    FATAL_ERROR ((0, 0, _("Cannot use compressed or remote archives")));
     150  }
     151  
     152  #else
     153  
     154  extern union block *record_start; /* FIXME */
     155  
     156  bool
     157  sys_get_archive_stat (void)
     158  {
     159    bool remote = _isrmt (archive);
     160    mtioseekable_archive = true;
     161    if (!remote && 0 <= archive && fstat (archive, &archive_stat) == 0)
     162      {
     163        if (!S_ISCHR (archive_stat.st_mode))
     164  	mtioseekable_archive = false;
     165        return true;
     166      }
     167    else
     168      {
     169        /* FIXME: This memset should not be needed.  It is present only
     170  	 because other parts of tar may incorrectly access
     171  	 archive_stat even if it's not the archive status.  */
     172        memset (&archive_stat, 0, sizeof archive_stat);
     173  
     174        return remote;
     175      }
     176  }
     177  
     178  bool
     179  sys_file_is_archive (struct tar_stat_info *p)
     180  {
     181    return (!dev_null_output && !_isrmt (archive)
     182  	  && p->stat.st_dev == archive_stat.st_dev
     183  	  && p->stat.st_ino == archive_stat.st_ino);
     184  }
     185  
     186  /* Detect if outputting to "/dev/null".  */
     187  void
     188  sys_detect_dev_null_output (void)
     189  {
     190    static char const dev_null[] = "/dev/null";
     191    static struct stat dev_null_stat;
     192  
     193    dev_null_output = (strcmp (archive_name_array[0], dev_null) == 0
     194  		     || (! _isrmt (archive)
     195  			 && S_ISCHR (archive_stat.st_mode)
     196  			 && (dev_null_stat.st_ino != 0
     197  			     || stat (dev_null, &dev_null_stat) == 0)
     198  			 && archive_stat.st_ino == dev_null_stat.st_ino
     199  			 && archive_stat.st_dev == dev_null_stat.st_dev));
     200  }
     201  
     202  void
     203  sys_wait_for_child (pid_t child_pid, bool eof)
     204  {
     205    if (child_pid)
     206      {
     207        int wait_status;
     208  
     209        while (waitpid (child_pid, &wait_status, 0) == -1)
     210  	if (errno != EINTR)
     211  	  {
     212  	    waitpid_error (use_compress_program_option);
     213  	    break;
     214  	  }
     215  
     216        if (WIFSIGNALED (wait_status))
     217  	{
     218  	  int sig = WTERMSIG (wait_status);
     219  	  if (!(!eof && sig == SIGPIPE))
     220  	    FATAL_ERROR ((0, 0, _("Child died with signal %d"), sig));
     221  	}
     222        else if (WEXITSTATUS (wait_status) != 0)
     223  	FATAL_ERROR ((0, 0, _("Child returned status %d"),
     224  		      WEXITSTATUS (wait_status)));
     225      }
     226  }
     227  
     228  void
     229  sys_spawn_shell (void)
     230  {
     231    pid_t child;
     232    const char *shell = getenv ("SHELL");
     233    if (! shell)
     234      shell = "/bin/sh";
     235    child = xfork ();
     236    if (child == 0)
     237      {
     238        priv_set_restore_linkdir ();
     239        execlp (shell, "-sh", "-i", NULL);
     240        exec_fatal (shell);
     241      }
     242    else
     243      {
     244        int wait_status;
     245        while (waitpid (child, &wait_status, 0) == -1)
     246  	if (errno != EINTR)
     247  	  {
     248  	    waitpid_error (shell);
     249  	    break;
     250  	  }
     251      }
     252  }
     253  
     254  bool
     255  sys_compare_uid (struct stat *a, struct stat *b)
     256  {
     257    return a->st_uid == b->st_uid;
     258  }
     259  
     260  bool
     261  sys_compare_gid (struct stat *a, struct stat *b)
     262  {
     263    return a->st_gid == b->st_gid;
     264  }
     265  
     266  bool
     267  sys_compare_links (struct stat *link_data, struct stat *stat_data)
     268  {
     269    return stat_data->st_dev == link_data->st_dev
     270           && stat_data->st_ino == link_data->st_ino;
     271  }
     272  
     273  int
     274  sys_truncate (int fd)
     275  {
     276    off_t pos = lseek (fd, (off_t) 0, SEEK_CUR);
     277    return pos < 0 ? -1 : ftruncate (fd, pos);
     278  }
     279  
     280  /* Return nonzero if NAME is the name of a regular file, or if the file
     281     does not exist (so it would be created as a regular file).  */
     282  static int
     283  is_regular_file (const char *name)
     284  {
     285    struct stat stbuf;
     286  
     287    if (stat (name, &stbuf) == 0)
     288      return S_ISREG (stbuf.st_mode);
     289    else
     290      return errno == ENOENT;
     291  }
     292  
     293  size_t
     294  sys_write_archive_buffer (void)
     295  {
     296    return rmtwrite (archive, record_start->buffer, record_size);
     297  }
     298  
     299  #define	PREAD 0			/* read file descriptor from pipe() */
     300  #define	PWRITE 1		/* write file descriptor from pipe() */
     301  
     302  /* Work around GCC bug 109839.  */
     303  #if 13 <= __GNUC__
     304  # pragma GCC diagnostic ignored "-Wanalyzer-fd-leak"
     305  #endif
     306  
     307  /* Duplicate file descriptor FROM into becoming INTO.
     308     INTO is closed first and has to be the next available slot.  */
     309  static void
     310  xdup2 (int from, int into)
     311  {
     312    if (from != into)
     313      {
     314        if (dup2 (from, into) < 0)
     315  	{
     316  	  int e = errno;
     317  	  FATAL_ERROR ((0, e, _("Cannot dup2")));
     318  	}
     319        xclose (from);
     320      }
     321  }
     322  
     323  /* Propagate any failure of the grandchild back to the parent.  */
     324  static _Noreturn void
     325  wait_for_grandchild (pid_t pid)
     326  {
     327    int wait_status;
     328    int exit_code = 0;
     329  
     330    while (waitpid (pid, &wait_status, 0) == -1)
     331      if (errno != EINTR)
     332        {
     333  	waitpid_error (use_compress_program_option);
     334  	break;
     335        }
     336  
     337    if (WIFSIGNALED (wait_status))
     338      raise (WTERMSIG (wait_status));
     339    else if (WEXITSTATUS (wait_status) != 0)
     340      exit_code = WEXITSTATUS (wait_status);
     341  
     342    exit (exit_code);
     343  }
     344  
     345  /* Set ARCHIVE for writing, then compressing an archive.  */
     346  pid_t
     347  sys_child_open_for_compress (void)
     348  {
     349    int parent_pipe[2];
     350    int child_pipe[2];
     351    pid_t grandchild_pid;
     352    pid_t child_pid;
     353  
     354    signal (SIGPIPE, SIG_IGN);
     355    xpipe (parent_pipe);
     356    child_pid = xfork ();
     357  
     358    if (child_pid > 0)
     359      {
     360        /* The parent tar is still here!  Just clean up.  */
     361  
     362        archive = parent_pipe[PWRITE];
     363        xclose (parent_pipe[PREAD]);
     364        return child_pid;
     365      }
     366  
     367    /* The new born child tar is here!  */
     368  
     369    set_program_name (_("tar (child)"));
     370    signal (SIGPIPE, SIG_DFL);
     371  
     372    xdup2 (parent_pipe[PREAD], STDIN_FILENO);
     373    xclose (parent_pipe[PWRITE]);
     374  
     375    /* Check if we need a grandchild tar.  This happens only if either:
     376       a) the file is to be accessed by rmt: compressor doesn't know how;
     377       b) the file is not a plain file.  */
     378  
     379    if (!_remdev (archive_name_array[0])
     380        && is_regular_file (archive_name_array[0]))
     381      {
     382        if (backup_option)
     383  	maybe_backup_file (archive_name_array[0], 1);
     384  
     385        /* We don't need a grandchild tar.  Open the archive and launch the
     386  	 compressor.  */
     387        if (strcmp (archive_name_array[0], "-"))
     388  	{
     389  	  archive = creat (archive_name_array[0], MODE_RW);
     390  	  if (archive < 0)
     391  	    {
     392  	      int saved_errno = errno;
     393  
     394  	      if (backup_option)
     395  		undo_last_backup ();
     396  	      errno = saved_errno;
     397  	      open_fatal (archive_name_array[0]);
     398  	    }
     399  	  xdup2 (archive, STDOUT_FILENO);
     400  	}
     401        priv_set_restore_linkdir ();
     402        xexec (use_compress_program_option);
     403      }
     404  
     405    /* We do need a grandchild tar.  */
     406  
     407    xpipe (child_pipe);
     408    grandchild_pid = xfork ();
     409  
     410    if (grandchild_pid == 0)
     411      {
     412        /* The newborn grandchild tar is here!  Launch the compressor.  */
     413  
     414        set_program_name (_("tar (grandchild)"));
     415  
     416        xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
     417        xclose (child_pipe[PREAD]);
     418        priv_set_restore_linkdir ();
     419        xexec (use_compress_program_option);
     420      }
     421  
     422    /* The child tar is still here!  */
     423  
     424    /* Prepare for reblocking the data from the compressor into the archive.  */
     425  
     426    xdup2 (child_pipe[PREAD], STDIN_FILENO);
     427    xclose (child_pipe[PWRITE]);
     428  
     429    if (strcmp (archive_name_array[0], "-") == 0)
     430      archive = STDOUT_FILENO;
     431    else
     432      {
     433        archive = rmtcreat (archive_name_array[0], MODE_RW, rsh_command_option);
     434        if (archive < 0)
     435  	open_fatal (archive_name_array[0]);
     436      }
     437  
     438    /* Let's read out of the stdin pipe and write an archive.  */
     439  
     440    while (1)
     441      {
     442        size_t status = 0;
     443        char *cursor;
     444        size_t length;
     445  
     446        /* Assemble a record.  */
     447  
     448        for (length = 0, cursor = record_start->buffer;
     449  	   length < record_size;
     450  	   length += status, cursor += status)
     451  	{
     452  	  size_t size = record_size - length;
     453  
     454  	  status = safe_read (STDIN_FILENO, cursor, size);
     455  	  if (status == SAFE_READ_ERROR)
     456  	    read_fatal (use_compress_program_option);
     457  	  if (status == 0)
     458  	    break;
     459  	}
     460  
     461        /* Copy the record.  */
     462  
     463        if (status == 0)
     464  	{
     465  	  /* We hit the end of the file.  Write last record at
     466  	     full length, as the only role of the grandchild is
     467  	     doing proper reblocking.  */
     468  
     469  	  if (length > 0)
     470  	    {
     471  	      memset (record_start->buffer + length, 0, record_size - length);
     472  	      status = sys_write_archive_buffer ();
     473  	      if (status != record_size)
     474  		archive_write_error (status);
     475  	    }
     476  
     477  	  /* There is nothing else to read, break out.  */
     478  	  break;
     479  	}
     480  
     481        status = sys_write_archive_buffer ();
     482        if (status != record_size)
     483  	archive_write_error (status);
     484      }
     485  
     486    wait_for_grandchild (grandchild_pid);
     487  }
     488  
     489  static void
     490  run_decompress_program (void)
     491  {
     492    int i;
     493    const char *p, *prog = NULL;
     494    struct wordsplit ws;
     495    int wsflags = (WRDSF_DEFFLAGS | WRDSF_ENV | WRDSF_DOOFFS) & ~WRDSF_NOVAR;
     496  
     497    ws.ws_env = (const char **) environ;
     498    ws.ws_offs = 1;
     499  
     500    for (p = first_decompress_program (&i); p; p = next_decompress_program (&i))
     501      {
     502        if (prog)
     503  	{
     504  	  WARNOPT (WARN_DECOMPRESS_PROGRAM,
     505  		   (0, errno, _("cannot run %s"), prog));
     506  	  WARNOPT (WARN_DECOMPRESS_PROGRAM,
     507  		   (0, 0, _("trying %s"), p));
     508  	}
     509        if (wordsplit (p, &ws, wsflags))
     510  	FATAL_ERROR ((0, 0, _("cannot split string '%s': %s"),
     511  		      p, wordsplit_strerror (&ws)));
     512        wsflags |= WRDSF_REUSE;
     513        memmove(ws.ws_wordv, ws.ws_wordv + ws.ws_offs,
     514  	      sizeof(ws.ws_wordv[0])*ws.ws_wordc);
     515        ws.ws_wordv[ws.ws_wordc] = (char *) "-d";
     516        prog = p;
     517        execvp (ws.ws_wordv[0], ws.ws_wordv);
     518        ws.ws_wordv[ws.ws_wordc] = NULL;
     519      }
     520    if (!prog)
     521      FATAL_ERROR ((0, 0, _("unable to run decompression program")));
     522    exec_fatal (prog);
     523  }
     524  
     525  /* Set ARCHIVE for uncompressing, then reading an archive.  */
     526  pid_t
     527  sys_child_open_for_uncompress (void)
     528  {
     529    int parent_pipe[2];
     530    int child_pipe[2];
     531    pid_t grandchild_pid;
     532    pid_t child_pid;
     533  
     534    xpipe (parent_pipe);
     535    child_pid = xfork ();
     536  
     537    if (child_pid > 0)
     538      {
     539        /* The parent tar is still here!  Just clean up.  */
     540  
     541        archive = parent_pipe[PREAD];
     542        xclose (parent_pipe[PWRITE]);
     543        return child_pid;
     544      }
     545  
     546    /* The newborn child tar is here!  */
     547  
     548    set_program_name (_("tar (child)"));
     549    signal (SIGPIPE, SIG_DFL);
     550  
     551    xdup2 (parent_pipe[PWRITE], STDOUT_FILENO);
     552    xclose (parent_pipe[PREAD]);
     553  
     554    /* Check if we need a grandchild tar.  This happens only if either:
     555       a) we're reading stdin: to force unblocking;
     556       b) the file is to be accessed by rmt: compressor doesn't know how;
     557       c) the file is not a plain file.  */
     558  
     559    if (strcmp (archive_name_array[0], "-") != 0
     560        && !_remdev (archive_name_array[0])
     561        && is_regular_file (archive_name_array[0]))
     562      {
     563        /* We don't need a grandchild tar.  Open the archive and launch the
     564  	 uncompressor.  */
     565  
     566        archive = open (archive_name_array[0], O_RDONLY | O_BINARY, MODE_RW);
     567        if (archive < 0)
     568  	open_fatal (archive_name_array[0]);
     569        xdup2 (archive, STDIN_FILENO);
     570        priv_set_restore_linkdir ();
     571        run_decompress_program ();
     572      }
     573  
     574    /* We do need a grandchild tar.  */
     575  
     576    xpipe (child_pipe);
     577    grandchild_pid = xfork ();
     578  
     579    if (grandchild_pid == 0)
     580      {
     581        /* The newborn grandchild tar is here!  Launch the uncompressor.  */
     582  
     583        set_program_name (_("tar (grandchild)"));
     584  
     585        xdup2 (child_pipe[PREAD], STDIN_FILENO);
     586        xclose (child_pipe[PWRITE]);
     587        priv_set_restore_linkdir ();
     588        run_decompress_program ();
     589      }
     590  
     591    /* The child tar is still here!  */
     592  
     593    /* Prepare for unblocking the data from the archive into the
     594       uncompressor.  */
     595  
     596    xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
     597    xclose (child_pipe[PREAD]);
     598  
     599    if (strcmp (archive_name_array[0], "-") == 0)
     600      archive = STDIN_FILENO;
     601    else
     602      archive = rmtopen (archive_name_array[0], O_RDONLY | O_BINARY,
     603  		       MODE_RW, rsh_command_option);
     604    if (archive < 0)
     605      open_fatal (archive_name_array[0]);
     606  
     607    /* Let's read the archive and pipe it into stdout.  */
     608  
     609    while (1)
     610      {
     611        char *cursor;
     612        size_t maximum;
     613        size_t count;
     614        size_t status;
     615  
     616        clear_read_error_count ();
     617  
     618      error_loop:
     619        status = rmtread (archive, record_start->buffer, record_size);
     620        if (status == SAFE_READ_ERROR)
     621  	{
     622  	  archive_read_error ();
     623  	  goto error_loop;
     624  	}
     625        if (status == 0)
     626  	break;
     627        cursor = record_start->buffer;
     628        maximum = status;
     629        while (maximum)
     630  	{
     631  	  count = maximum < BLOCKSIZE ? maximum : BLOCKSIZE;
     632  	  if (full_write (STDOUT_FILENO, cursor, count) != count)
     633  	    write_error (use_compress_program_option);
     634  	  cursor += count;
     635  	  maximum -= count;
     636  	}
     637      }
     638  
     639    xclose (STDOUT_FILENO);
     640  
     641    wait_for_grandchild (grandchild_pid);
     642  }
     643  
     644  
     645  
     646  static void
     647  dec_to_env (char const *envar, uintmax_t num)
     648  {
     649    char buf[UINTMAX_STRSIZE_BOUND];
     650    char *numstr;
     651  
     652    numstr = STRINGIFY_BIGINT (num, buf);
     653    if (setenv (envar, numstr, 1) != 0)
     654      xalloc_die ();
     655  }
     656  
     657  static void
     658  time_to_env (char const *envar, struct timespec t)
     659  {
     660    char buf[TIMESPEC_STRSIZE_BOUND];
     661    if (setenv (envar, code_timespec (t, buf), 1) != 0)
     662      xalloc_die ();
     663  }
     664  
     665  static void
     666  oct_to_env (char const *envar, unsigned long num)
     667  {
     668    char buf[1+1+(sizeof(unsigned long)*CHAR_BIT+2)/3];
     669  
     670    snprintf (buf, sizeof buf, "0%lo", num);
     671    if (setenv (envar, buf, 1) != 0)
     672      xalloc_die ();
     673  }
     674  
     675  static void
     676  str_to_env (char const *envar, char const *str)
     677  {
     678    if (str)
     679      {
     680        if (setenv (envar, str, 1) != 0)
     681  	xalloc_die ();
     682      }
     683    else
     684      unsetenv (envar);
     685  }
     686  
     687  static void
     688  chr_to_env (char const *envar, char c)
     689  {
     690    char buf[2];
     691    buf[0] = c;
     692    buf[1] = 0;
     693    if (setenv (envar, buf, 1) != 0)
     694      xalloc_die ();
     695  }
     696  
     697  static void
     698  stat_to_env (char *name, char type, struct tar_stat_info *st)
     699  {
     700    str_to_env ("TAR_VERSION", PACKAGE_VERSION);
     701    str_to_env ("TAR_ARCHIVE", *archive_name_cursor);
     702    dec_to_env ("TAR_VOLUME", archive_name_cursor - archive_name_array + 1);
     703    dec_to_env ("TAR_BLOCKING_FACTOR", blocking_factor);
     704    str_to_env ("TAR_FORMAT",
     705  	      archive_format_string (current_format == DEFAULT_FORMAT ?
     706  				     archive_format : current_format));
     707    chr_to_env ("TAR_FILETYPE", type);
     708    oct_to_env ("TAR_MODE", st->stat.st_mode);
     709    str_to_env ("TAR_FILENAME", name);
     710    str_to_env ("TAR_REALNAME", st->file_name);
     711    str_to_env ("TAR_UNAME", st->uname);
     712    str_to_env ("TAR_GNAME", st->gname);
     713    time_to_env ("TAR_ATIME", st->atime);
     714    time_to_env ("TAR_MTIME", st->mtime);
     715    time_to_env ("TAR_CTIME", st->ctime);
     716    dec_to_env ("TAR_SIZE", st->stat.st_size);
     717    dec_to_env ("TAR_UID", st->stat.st_uid);
     718    dec_to_env ("TAR_GID", st->stat.st_gid);
     719  
     720    switch (type)
     721      {
     722      case 'b':
     723      case 'c':
     724        dec_to_env ("TAR_MINOR", minor (st->stat.st_rdev));
     725        dec_to_env ("TAR_MAJOR", major (st->stat.st_rdev));
     726        unsetenv ("TAR_LINKNAME");
     727        break;
     728  
     729      case 'l':
     730      case 'h':
     731        unsetenv ("TAR_MINOR");
     732        unsetenv ("TAR_MAJOR");
     733        str_to_env ("TAR_LINKNAME", st->link_name);
     734        break;
     735  
     736      default:
     737        unsetenv ("TAR_MINOR");
     738        unsetenv ("TAR_MAJOR");
     739        unsetenv ("TAR_LINKNAME");
     740        break;
     741      }
     742  }
     743  
     744  static pid_t global_pid;
     745  static void (*pipe_handler) (int sig);
     746  
     747  int
     748  sys_exec_command (char *file_name, int typechar, struct tar_stat_info *st)
     749  {
     750    int p[2];
     751  
     752    xpipe (p);
     753    pipe_handler = signal (SIGPIPE, SIG_IGN);
     754    global_pid = xfork ();
     755  
     756    if (global_pid != 0)
     757      {
     758        xclose (p[PREAD]);
     759        return p[PWRITE];
     760      }
     761  
     762    /* Child */
     763    xdup2 (p[PREAD], STDIN_FILENO);
     764    xclose (p[PWRITE]);
     765  
     766    stat_to_env (file_name, typechar, st);
     767  
     768    priv_set_restore_linkdir ();
     769    xexec (to_command_option);
     770  }
     771  
     772  void
     773  sys_wait_command (void)
     774  {
     775    int status;
     776  
     777    if (global_pid < 0)
     778      return;
     779  
     780    signal (SIGPIPE, pipe_handler);
     781    while (waitpid (global_pid, &status, 0) == -1)
     782      if (errno != EINTR)
     783        {
     784          global_pid = -1;
     785          waitpid_error (to_command_option);
     786          return;
     787        }
     788  
     789    if (WIFEXITED (status))
     790      {
     791        if (!ignore_command_error_option && WEXITSTATUS (status))
     792  	ERROR ((0, 0, _("%lu: Child returned status %d"),
     793  		(unsigned long) global_pid, WEXITSTATUS (status)));
     794      }
     795    else if (WIFSIGNALED (status))
     796      {
     797        WARN ((0, 0, _("%lu: Child terminated on signal %d"),
     798  	     (unsigned long) global_pid, WTERMSIG (status)));
     799      }
     800    else
     801      ERROR ((0, 0, _("%lu: Child terminated on unknown reason"),
     802  	    (unsigned long) global_pid));
     803  
     804    global_pid = -1;
     805  }
     806  
     807  int
     808  sys_exec_info_script (const char **archive_name, int volume_number)
     809  {
     810    pid_t pid;
     811    char uintbuf[UINTMAX_STRSIZE_BOUND];
     812    int p[2];
     813    static void (*saved_handler) (int sig);
     814  
     815    xpipe (p);
     816    saved_handler = signal (SIGPIPE, SIG_IGN);
     817  
     818    pid = xfork ();
     819  
     820    if (pid != 0)
     821      {
     822        /* Master */
     823  
     824        int rc;
     825        int status;
     826        char *buf = NULL;
     827        size_t size = 0;
     828        FILE *fp;
     829  
     830        xclose (p[PWRITE]);
     831        fp = fdopen (p[PREAD], "r");
     832        rc = getline (&buf, &size, fp);
     833        fclose (fp);
     834  
     835        if (rc > 0 && buf[rc-1] == '\n')
     836  	buf[--rc] = 0;
     837  
     838        while (waitpid (pid, &status, 0) == -1)
     839  	if (errno != EINTR)
     840  	  {
     841  	    signal (SIGPIPE, saved_handler);
     842  	    waitpid_error (info_script_option);
     843  	    return -1;
     844  	  }
     845  
     846        signal (SIGPIPE, saved_handler);
     847  
     848        if (WIFEXITED (status))
     849  	{
     850  	  if (WEXITSTATUS (status) == 0 && rc > 0)
     851  	    *archive_name = buf;
     852  	  else
     853  	    free (buf);
     854  	  return WEXITSTATUS (status);
     855  	}
     856  
     857        free (buf);
     858        return -1;
     859      }
     860  
     861    /* Child */
     862    setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
     863    setenv ("TAR_ARCHIVE", *archive_name, 1);
     864    setenv ("TAR_VOLUME", STRINGIFY_BIGINT (volume_number, uintbuf), 1);
     865    setenv ("TAR_BLOCKING_FACTOR",
     866  	  STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
     867    setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
     868    setenv ("TAR_FORMAT",
     869  	  archive_format_string (current_format == DEFAULT_FORMAT ?
     870  				 archive_format : current_format), 1);
     871    setenv ("TAR_FD", STRINGIFY_BIGINT (p[PWRITE], uintbuf), 1);
     872  
     873    xclose (p[PREAD]);
     874  
     875    priv_set_restore_linkdir ();
     876    xexec (info_script_option);
     877  }
     878  
     879  void
     880  sys_exec_checkpoint_script (const char *script_name,
     881  			    const char *archive_name,
     882  			    int checkpoint_number)
     883  {
     884    pid_t pid;
     885    char uintbuf[UINTMAX_STRSIZE_BOUND];
     886  
     887    pid = xfork ();
     888  
     889    if (pid != 0)
     890      {
     891        /* Master */
     892  
     893        int status;
     894  
     895        while (waitpid (pid, &status, 0) == -1)
     896  	if (errno != EINTR)
     897  	  {
     898  	    waitpid_error (script_name);
     899  	    break;
     900  	  }
     901  
     902        return;
     903      }
     904  
     905    /* Child */
     906    setenv ("TAR_VERSION", PACKAGE_VERSION, 1);
     907    setenv ("TAR_ARCHIVE", archive_name, 1);
     908    setenv ("TAR_CHECKPOINT", STRINGIFY_BIGINT (checkpoint_number, uintbuf), 1);
     909    setenv ("TAR_BLOCKING_FACTOR",
     910  	  STRINGIFY_BIGINT (blocking_factor, uintbuf), 1);
     911    setenv ("TAR_SUBCOMMAND", subcommand_string (subcommand_option), 1);
     912    setenv ("TAR_FORMAT",
     913  	  archive_format_string (current_format == DEFAULT_FORMAT ?
     914  				 archive_format : current_format), 1);
     915    priv_set_restore_linkdir ();
     916    xexec (script_name);
     917  }
     918  
     919  #endif /* not MSDOS */