home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1993 #2 / Image.iso / os2 / gtak212b.zip / SOURCE.ZIP / 1.10 / buffer.c < prev    next >
C/C++ Source or Header  |  1993-01-14  |  38KB  |  1,636 lines

  1. /*****************************************************************************
  2.  * $Id: buffer.c,v 1.7 1993/01/14 21:50:21 ak Exp $
  3.  *****************************************************************************
  4.  * $Log: buffer.c,v $
  5.  * Revision 1.7  1993/01/14  21:50:21  ak
  6.  * EMX 0.8f fixes and enhancements by Kai Uwe Rommel.
  7.  *
  8.  * Revision 1.6  1992/09/29  09:55:27  ak
  9.  * K.U.R., once again :-)
  10.  * - removed a dup() in buffer.c
  11.  * - EMX opendir with hidden/system test in gnu.c (...dotdot)
  12.  *
  13.  * Revision 1.5  1992/09/26  08:32:16  ak
  14.  * *** empty log message ***
  15.  *
  16.  * Revision 1.4  1992/09/22  21:40:17  ak
  17.  * Yet another fix from K.U.R.:
  18.  *  Ich habe noch einen Bug im multi-volume handling gefunden. Die Abfrage
  19.  *  auf ENOSPC und EIO war nicht symmetrisch fuer Lesen und Schreiben.
  20.  *  Multi-Volume-Archive auf floppies konnte man zwar schreiben, aber
  21.  *  nicht lesen.
  22.  *
  23.  * Revision 1.3  1992/09/12  15:57:14  ak
  24.  * - Usenet patches for GNU TAR 1.10
  25.  * - Bugfixes and patches of Kai Uwe Rommel:
  26.  *         filename conversion for FAT
  27.  *         EMX 0.8e
  28.  *         -0..1 alias for a: b:
  29.  *         -2..7 alias for +++TAPE$x
  30.  *
  31.  * Revision 1.2  1992/09/02  20:07:46  ak
  32.  * Version AK200
  33.  * - Tape access
  34.  * - Quick file access
  35.  * - OS/2 extended attributes
  36.  * - Some OS/2 fixes
  37.  * - Some fixes of Kai Uwe Rommel
  38.  *
  39.  * Revision 1.1.1.1  1992/09/02  19:16:58  ak
  40.  * Original GNU Tar 1.10 with some filenames shortened for FAT compliance.
  41.  *
  42.  * Revision 1.1  1992/09/02  19:16:55  ak
  43.  * Initial revision
  44.  *
  45.  *****************************************************************************/
  46.  
  47. static char *rcsid = "$Id: buffer.c,v 1.7 1993/01/14 21:50:21 ak Exp $";
  48.  
  49. /*
  50.  * Modified by Andreas Kaiser July 92.
  51.  * See CHANGES.AK for info.
  52.  */
  53.  
  54. /* Buffer management for tar.
  55.    Copyright (C) 1988 Free Software Foundation
  56.  
  57. This file is part of GNU Tar.
  58.  
  59. GNU Tar is free software; you can redistribute it and/or modify
  60. it under the terms of the GNU General Public License as published by
  61. the Free Software Foundation; either version 1, or (at your option)
  62. any later version.
  63.  
  64. GNU Tar is distributed in the hope that it will be useful,
  65. but WITHOUT ANY WARRANTY; without even the implied warranty of
  66. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  67. GNU General Public License for more details.
  68.  
  69. You should have received a copy of the GNU General Public License
  70. along with GNU Tar; see the file COPYING.  If not, write to
  71. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  72.  
  73. /*
  74.  * Buffer management for tar.
  75.  *
  76.  * Written by John Gilmore, ihnp4!hoptoad!gnu, on 25 August 1985.
  77.  *
  78.  * @(#) buffer.c 1.28 11/6/87 - gnu
  79.  */
  80.  
  81. #include <stdio.h>
  82. #include <ctype.h>
  83. #include <errno.h>
  84. #include <sys/types.h>        /* For non-Berkeley systems */
  85. #include <sys/stat.h>
  86. #include <signal.h>
  87.  
  88. #ifndef MSDOS
  89. #include <sys/ioctl.h>
  90. #if !defined(USG) || defined(HAVE_MTIO)
  91. #include <sys/mtio.h>
  92. #endif
  93. #endif
  94.  
  95. #ifdef    MSDOS
  96. # include <fcntl.h>
  97. # include <process.h>
  98. #else
  99. # ifdef XENIX
  100. #  include <sys/inode.h>
  101. # endif
  102. # include <sys/file.h>
  103. #endif
  104.  
  105. extern int errno;
  106.  
  107. #ifdef OS2
  108. # define INCL_DOSPROCESS
  109. # include <os2.h>
  110. # include <process.h>
  111. # include <string.h>
  112. static int stdio;
  113. #endif
  114.  
  115. #include "tar.h"
  116. #include "port.h"
  117. #include "rmt.h"
  118. #include "regex.h"
  119.  
  120. /* Either stdout or stderr:  The thing we write messages (standard msgs, not
  121.    errors) to.  Stdout unless we're writing a pipe, in which case stderr */
  122. FILE *msg_file = stdout;
  123.  
  124. #define    STDIN    0        /* Standard input  file descriptor */
  125. #define    STDOUT    1        /* Standard output file descriptor */
  126.  
  127. #define    PREAD    0        /* Read  file descriptor from pipe() */
  128. #define    PWRITE    1        /* Write file descriptor from pipe() */
  129.  
  130. #ifdef __STDC__
  131. extern void    *malloc();
  132. extern void    *valloc();
  133. #else
  134. extern char    *malloc();
  135. extern char    *valloc();
  136. #endif
  137. extern time_t time();
  138.  
  139. extern char    *index(), *strcat();
  140. extern char    *strcpy();
  141.  
  142. /*
  143.  * V7 doesn't have a #define for this.
  144.  */
  145. #ifndef O_RDONLY
  146. #define    O_RDONLY    0
  147. #endif
  148. #ifndef O_RDWR
  149. #define O_RDWR        2
  150. #endif
  151. #ifndef O_CREAT
  152. #define O_CREAT        0
  153. #endif
  154. #ifndef O_BINARY
  155. #define O_BINARY    0
  156. #endif
  157.  
  158. #define    MAGIC_STAT    105    /* Magic status returned by child, if
  159.                    it can't exec.  We hope compress/sh
  160.                    never return this status! */
  161.  
  162. void writeerror();
  163. void readerror();
  164.  
  165. void ck_pipe();
  166. void ck_close();
  167.  
  168. extern void finish_header();
  169. extern void to_oct();
  170.  
  171. #ifndef MSDOS
  172. /* Obnoxious test to see if dimwit is trying to dump the archive */
  173. dev_t ar_dev;
  174. ino_t ar_ino;
  175. #endif
  176.  
  177. /*
  178.  * The record pointed to by save_rec should not be overlaid
  179.  * when reading in a new tape block.  Copy it to record_save_area first, and
  180.  * change the pointer in *save_rec to point to record_save_area.
  181.  * Saved_recno records the record number at the time of the save.
  182.  * This is used by annofile() to print the record number of a file's
  183.  * header record.
  184.  */
  185. static union record **save_rec;
  186.  union record record_save_area;
  187. static long        saved_recno;
  188.  
  189. /*
  190.  * PID of child program, if f_compress or remote archive access.
  191.  */
  192. static int    childpid = 0;
  193. #ifdef OS2
  194. static char *    childname;
  195. #endif
  196.  
  197. /*
  198.  * Record number of the start of this block of records
  199.  */
  200. long    baserec;
  201.  
  202. /*
  203.  * Error recovery stuff
  204.  */
  205. static int    r_error_count;
  206.  
  207. /*
  208.  * Have we hit EOF yet?
  209.  */
  210. static int    eof;
  211.  
  212. /* JF we're reading, but we just read the last record and its time to update */
  213. extern time_to_start_writing;
  214. int file_to_switch_to= -1;    /* If remote update, close archive, and use
  215.                    this descriptor to write to */
  216.  
  217. int volno = 1;            /* JF which volume of a multi-volume tape
  218.                    we're on */
  219.  
  220. char *save_name = 0;        /* Name of the file we are currently writing */
  221. long save_totsize;        /* total size of file we are writing.  Only
  222.                    valid if save_name is non_zero */
  223. long save_sizeleft;        /* Where we are in the file we are writing.
  224.                    Only valid if save_name is non-zero */
  225.  
  226. int write_archive_to_stdout;
  227.  
  228. /* Used by fl_read and fl_write to store the real info about saved names */
  229. static char real_s_name[NAMSIZ];
  230. static long real_s_totsize;
  231. static long real_s_sizeleft;
  232.  
  233. /* Reset the EOF flag (if set), and re-set ar_record, etc */
  234.  
  235. void
  236. reset_eof()
  237. {
  238.     if(eof) {
  239.         eof=0;
  240.         ar_record=ar_block;
  241.         ar_last=ar_block+blocking;
  242.         ar_reading=0;
  243.     }
  244. }
  245.  
  246. /*
  247.  * Return the location of the next available input or output record.
  248.  * Return NULL for EOF.  Once we have returned NULL, we just keep returning
  249.  * it, to avoid accidentally going on to the next file on the "tape".
  250.  */
  251. union record *
  252. findrec()
  253. {
  254.     if (ar_record == ar_last) {
  255.         if (eof)
  256.             return (union record *)NULL;    /* EOF */
  257.         flush_archive();
  258.         if (ar_record == ar_last) {
  259.             eof++;
  260.             return (union record *)NULL;    /* EOF */
  261.         }
  262.     }
  263.     return ar_record;
  264. }
  265.  
  266.  
  267. /*
  268.  * Indicate that we have used all records up thru the argument.
  269.  * (should the arg have an off-by-1? XXX FIXME)
  270.  */
  271. void
  272. userec(rec)
  273.     union record *rec;
  274. {
  275.     while(rec >= ar_record)
  276.         ar_record++;
  277.     /*
  278.      * Do NOT flush the archive here.  If we do, the same
  279.      * argument to userec() could mean the next record (if the
  280.      * input block is exactly one record long), which is not what
  281.      * is intended.
  282.      */
  283.     if (ar_record > ar_last)
  284.         abort();
  285. }
  286.  
  287.  
  288. /*
  289.  * Return a pointer to the end of the current records buffer.
  290.  * All the space between findrec() and endofrecs() is available
  291.  * for filling with data, or taking data from.
  292.  */
  293. union record *
  294. endofrecs()
  295. {
  296.     return ar_last;
  297. }
  298.  
  299.  
  300. /*
  301.  * Duplicate a file descriptor into a certain slot.
  302.  * Equivalent to BSD "dup2" with error reporting.
  303.  */
  304. void
  305. dupto(from, to, msg)
  306.     int from, to;
  307.     char *msg;
  308. {
  309.     int err;
  310.  
  311.     if (from != to) {
  312.         err=close(to);
  313.         if(err<0 && errno!=EBADF) {
  314.             msg_perror("Cannot close descriptor %d",to);
  315.             exit(EX_SYSTEM);
  316.         }
  317.         err = dup(from);
  318.         if (err != to) {
  319.             msg_perror("cannot dup %s",msg);
  320.             exit(EX_SYSTEM);
  321.         }
  322.         ck_close(from);
  323.     }
  324. }
  325.  
  326. /* return non-zero if p is the name of a directory */
  327. isfile(p)
  328. char *p;
  329. {
  330.     struct stat stbuf;
  331.  
  332.     if(stat(p,&stbuf)<0)
  333.         return 1;
  334.     if((stbuf.st_mode&S_IFMT)==S_IFREG)
  335.         return 1;
  336.     return 0;
  337. }
  338.  
  339. #ifdef MSDOS
  340. # ifdef OS2
  341.  
  342. int    buffer_size;
  343. int    rmt_fd = -1;
  344.  
  345. void
  346. child_open()
  347. {
  348.     int    save[2];
  349.     int    pipe1[2], pipe2[2];
  350.     int    fd, r, no, a, b, mode;
  351.  
  352.     if (ar_reading) {
  353.         a = 0;
  354.         b = 1;
  355.         mode = O_RDONLY|O_BINARY;
  356.     } else {
  357.         a = 1;
  358.         b = 0;
  359.         mode = O_WRONLY|O_CREAT|O_TRUNC|O_BINARY;
  360.     }
  361.  
  362.     stdio = (strcmp(ar_file, "-") == 0 || ar_file[0] == 0);
  363.  
  364.     ck_pipe(pipe1);
  365.  
  366.     noinherit(save[b] = dup(b));
  367.  
  368.     if (ar_reading && is_device)
  369.         f_reblock = 1;
  370.  
  371.     if (stdio)
  372.         save[a] = -1;
  373.     else {
  374.         noinherit(save[a] = dup(a));
  375.         close(a);
  376.  
  377.         if ((fd = rmtopen(ar_file, mode, 0666)) < 0) {
  378.             msg_perror("can't open archive %s",ar_file);
  379.             exit(EX_BADARCH);
  380.         }
  381.  
  382.         if (_isrmt(fd)) {
  383.             rmt_fd = fd;
  384.             fd -= __REM_BIAS;
  385.         }
  386.  
  387.         if (fd != a) {
  388.             msg_perror("can't dup archive %s",ar_file);
  389.             exit(EX_BADARCH);
  390.         }
  391.     }
  392.  
  393.     dupto(pipe1[b], b, "pipe");
  394.     inherit(a);
  395.     inherit(b);
  396.     noinherit(pipe1[a]);
  397.  
  398.     if (is_device || f_buffered) {
  399.         if (ar_reading)
  400.             r = spawnlp(P_NOWAIT, "buffer", "buffer", "-i90", "-o0", NULL);
  401.         else {
  402.             char bs[10];
  403.             sprintf(bs, "-b%d", blocksize);
  404.             r = spawnlp(P_NOWAIT, "buffer", "buffer", "-i0", "-o90", bs, NULL);
  405.         }
  406.         if (r < 0) {
  407.             msg_perror("can't spawn buffer");
  408.             exit(EX_SYSTEM);
  409.         }
  410.         childpid = r;
  411.         childname = "buffer";
  412.  
  413.         ck_pipe(pipe2);
  414.         dupto(pipe1[a], a, "pipe");
  415.         dupto(pipe2[b], b, "pipe");
  416.         noinherit(pipe2[a]);
  417.         inherit(a);
  418.         inherit(b);
  419.         r = spawnlp(P_NOWAIT, "compress", "compress",
  420.             ar_reading ? "-d" : NULL, NULL);
  421.         if (r < 0) {
  422.             msg_perror("can't spawn compress");
  423.             exit(EX_SYSTEM);    
  424.         }
  425.         archive = pipe2[a];
  426.     } else {
  427.         r = spawnlp(P_NOWAIT, "compress", "compress",
  428.             ar_reading ? "-d" : NULL, NULL);
  429.         if (r < 0) {
  430.             msg_perror("can't spawn compress");
  431.             exit(EX_SYSTEM);    
  432.         }
  433.         archive = pipe1[a];
  434.         childpid = r;
  435.         childname = "compress";
  436.     }
  437.  
  438.     if (stdio) {
  439.         if (ar_reading)
  440.             freopen("nul", "r", stdin);
  441.         else
  442.             freopen("nul", "w", stdout);
  443.     }
  444.  
  445.     if (save[0] >= 0)
  446.         dupto(save[0], 0, "saved to stdin");
  447.     if (save[1] >= 0)
  448.         dupto(save[1], 1, "saved to stdout");
  449.     inherit(0);
  450.     inherit(1);
  451. }
  452.  
  453. static void
  454. child_status(int childpid, char *who, int force)
  455. {
  456.     RESULTCODES st;
  457.     PID pid;
  458.  
  459.     if (DosWaitChild(0, 0, &st, &pid, childpid) == 0) {
  460.         switch (st.codeTerminate) {
  461.         case TC_EXIT:
  462.             if (st.codeResult > force)
  463.                 msg("child '%s' return code %d", who, st.codeResult);
  464.             break;
  465.         case TC_HARDERROR:
  466.             msg("child '%s' aborted with hard error", who);
  467.             break;
  468.         case TC_TRAP:
  469.             msg("child '%s' aborted by trap, who");
  470.             break;
  471.         case TC_KILLPROCESS:
  472.             msg("child '%s' killed", who);
  473.             break;
  474.         default:
  475.             msg("child '%s' terminated with unknown status %x.%x",
  476.                 who, st.codeTerminate, st.codeResult);
  477.         }
  478.     }
  479. }
  480.  
  481. void
  482. child_close(force)
  483. {
  484.     if (childpid)
  485.         child_status(childpid, childname, force);
  486. #ifdef DIRECT
  487.     if (rmt_fd >= 0)
  488.         rmtclose(rmt_fd);
  489. #endif
  490.     childpid = 0;
  491. }
  492.  
  493. #else /* MSDOS but not OS2 */
  494.  
  495. void
  496. child_open()
  497. {
  498.     fprintf(stderr,"MSDOS %s can't use compressed or remote archives\n",tar);
  499.     exit(EX_ARGSBAD);
  500. }
  501.  
  502. void
  503. child_close()
  504. {
  505. }
  506.  
  507. # endif /* MSDOS */
  508. #else /* unix */
  509.  
  510. void
  511. child_open()
  512. {
  513.     int pipe[2];
  514.     int err = 0;
  515.  
  516.     int kidpipe[2];
  517.     int kidchildpid;
  518.  
  519.     ck_pipe(pipe);
  520.  
  521.     childpid=fork();
  522.     if(childpid<0) {
  523.         msg_perror("cannot fork");
  524.         exit(EX_SYSTEM);
  525.     }
  526.     if(childpid>0) {
  527.         /* We're the parent.  Clean up and be happy */
  528.         /* This, at least, is easy */
  529.  
  530.         if(ar_reading) {
  531.             f_reblock++;
  532.             archive=pipe[PREAD];
  533.             ck_close(pipe[PWRITE]);
  534.         } else {
  535.             archive = pipe[PWRITE];
  536.             ck_close(pipe[PREAD]);
  537.         }
  538.         return;
  539.     }
  540.  
  541.     /* We're the kid */
  542.     if(ar_reading) {
  543.         dupto(pipe[PWRITE],STDOUT,"(child) pipe to stdout");
  544.         ck_close(pipe[PREAD]);
  545.     } else {
  546.         dupto(pipe[PREAD],STDIN,"(child) pipe to stdin");
  547.         ck_close(pipe[PWRITE]);
  548.     }
  549.  
  550.     /* We need a child tar only if
  551.        1: we're reading/writing stdin/out (to force reblocking)
  552.        2: the file is to be accessed by rmt (compress doesn't know how)
  553.        3: the file is not a plain file */
  554. #ifdef NO_REMOTE
  555.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && isfile(ar_file))
  556. #else
  557.     if(!(ar_file[0]=='-' && ar_file[1]=='\0') && !_remdev(ar_file) && isfile(ar_file))
  558. #endif
  559.     {
  560.         /* We don't need a child tar.  Open the archive */
  561.         if(ar_reading) {
  562.             archive=open(ar_file, O_RDONLY|O_BINARY, 0666);
  563.             if(archive<0) {
  564.                 msg_perror("can't open archive %s",ar_file);
  565.                 exit(EX_BADARCH);
  566.             }
  567.             dupto(archive,STDIN,"archive to stdin");
  568.             /* close(archive); */
  569.         } else {
  570.             archive=creat(ar_file,0666);
  571.             if(archive<0) {
  572.                 msg_perror("can't open archive %s",ar_file);
  573.                 exit(EX_BADARCH);
  574.             }
  575.             dupto(archive,STDOUT,"archive to stdout");
  576.             /* close(archive); */
  577.         }
  578.     } else {
  579.         /* We need a child tar */
  580.         ck_pipe(kidpipe);
  581.  
  582.         kidchildpid=fork();
  583.         if(kidchildpid<0) {
  584.             msg_perror("child can't fork");
  585.             exit(EX_SYSTEM);
  586.         }
  587.  
  588.         if(kidchildpid>0) {
  589.             /* About to exec compress:  set up the files */
  590.             if(ar_reading) {
  591.                 dupto(kidpipe[PREAD],STDIN,"((child)) pipe to stdin");
  592.                 ck_close(kidpipe[PWRITE]);
  593.                 /* dup2(pipe[PWRITE],STDOUT); */
  594.             } else {
  595.                 /* dup2(pipe[PREAD],STDIN); */
  596.                 dupto(kidpipe[PWRITE],STDOUT,"((child)) pipe to stdout");
  597.                 ck_close(kidpipe[PREAD]);
  598.             }
  599.             /* ck_close(pipe[PREAD]); */
  600.             /* ck_close(pipe[PWRITE]); */
  601.             /* ck_close(kidpipe[PREAD]);
  602.             ck_close(kidpipe[PWRITE]); */
  603.         } else {
  604.         /* Grandchild.  Do the right thing, namely sit here and
  605.            read/write the archive, and feed stuff back to compress */
  606.             tar="tar (child)";
  607.             if(ar_reading) {
  608.                 dupto(kidpipe[PWRITE],STDOUT,"[child] pipe to stdout");
  609.                 ck_close(kidpipe[PREAD]);
  610.             } else {
  611.                 dupto(kidpipe[PREAD],STDIN,"[child] pipe to stdin");
  612.                 ck_close(kidpipe[PWRITE]);
  613.             }
  614.  
  615.             if (ar_file[0] == '-' && ar_file[1] == '\0') {
  616.                 if (ar_reading)
  617.                     archive = STDIN;
  618.                 else
  619.                     archive = STDOUT;
  620.             } else /* This can't happen if (ar_reading==2)
  621.                 archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
  622.             else */if(ar_reading)
  623.                 archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
  624.             else
  625.                 archive = rmtcreat(ar_file, 0666);
  626.  
  627.             if (archive < 0) {
  628.                 msg_perror("can't open archive %s",ar_file);
  629.                 exit(EX_BADARCH);
  630.             }
  631.  
  632.             if(ar_reading) {
  633.                 for(;;) {
  634.                     char *ptr;
  635.                     int max,count;
  636.         
  637.                     r_error_count = 0;
  638.                 error_loop:
  639.                     err=rmtread(archive, ar_block->charptr,(int)(blocksize));
  640.                     if(err<0) {
  641.                         readerror();
  642.                         goto error_loop;
  643.                     }
  644.                     if(err==0)
  645.                         break;
  646.                     ptr = ar_block->charptr;
  647.                     max = err;
  648.                     while(max) {
  649.                         count = (max<RECORDSIZE) ? max : RECORDSIZE;
  650.                         err=write(STDOUT,ptr,count);
  651.                         if(err!=count) {
  652.                             if(err<0) {
  653.                                 msg_perror("can't write to compress");
  654.                                 exit(EX_SYSTEM);
  655.                             } else
  656.                                 msg("write to compress short %d bytes",count-err);
  657.                             count = (err<0) ? 0 : err;
  658.                         }
  659.                         ptr+=count;
  660.                         max-=count;
  661.                     }
  662.                 }
  663.             } else {
  664.                 for(;;) {
  665.                     int n;
  666.                     char *ptr;
  667.         
  668.                     n=blocksize;
  669.                     ptr = ar_block->charptr;
  670.                     while(n) {
  671.                         err=read(STDIN,ptr,(n<RECORDSIZE) ? n : RECORDSIZE);
  672.                         if(err<=0)
  673.                             break;
  674.                         n-=err;
  675.                         ptr+=err;
  676.                     }
  677.                         /* EOF */
  678.                     if(err==0) {
  679.                         if(f_compress<2)
  680.                             blocksize-=n;
  681.                         else
  682.                             bzero(ar_block->charptr+blocksize-n,n);
  683.                         err=rmtwrite(archive,ar_block->charptr,blocksize);
  684.                         if(err!=(blocksize))
  685.                             writeerror(err);
  686.                         if(f_compress<2)
  687.                             blocksize+=n;
  688.                         break;
  689.                     }
  690.                     if(n) {
  691.                         msg_perror("can't read from compress");
  692.                         exit(EX_SYSTEM);
  693.                     }
  694.                     err=rmtwrite(archive, ar_block->charptr, (int)blocksize);
  695.                     if(err!=blocksize)
  696.                         writeerror(err);
  697.                 }
  698.             }
  699.         
  700.             /* close_archive(); */
  701.             exit(0);
  702.         }
  703.     }
  704.         /* So we should exec compress (-d) */
  705.     if(ar_reading)
  706.         execlp("compress", "compress", "-d", (char *)0);
  707.     else
  708.         execlp("compress", "compress", (char *)0);
  709.     msg_perror("can't exec compress");
  710.     _exit(EX_SYSTEM);
  711. }
  712.  
  713. void
  714. child_close()
  715. {
  716.     int child, status;
  717.  
  718.     if (childpid) {
  719.         /*
  720.          * Loop waiting for the right child to die, or for
  721.          * no more kids.
  722.          */
  723.         while (((child = wait(&status)) != childpid) && child != -1)
  724.             ;
  725.  
  726.         if (child != -1) {
  727.             switch (TERM_SIGNAL(status)) {
  728.             case 0:
  729.                 /* Child voluntarily terminated  -- but why? */
  730.                 if (TERM_VALUE(status) == MAGIC_STAT) {
  731.                     exit(EX_SYSTEM);/* Child had trouble */
  732.                 }
  733.                 if (TERM_VALUE(status) == (SIGPIPE + 128)) {
  734.                     /*
  735.                      * /bin/sh returns this if its child
  736.                      * dies with SIGPIPE.  'Sok.
  737.                      */
  738.                     break;
  739.                 } else if (TERM_VALUE(status))
  740.                     msg("child returned status %d",
  741.                         TERM_VALUE(status));
  742.             case SIGPIPE:
  743.                 break;        /* This is OK. */
  744.  
  745.             default:
  746.                 msg("child died with signal %d%s",
  747.                  TERM_SIGNAL(status),
  748.                  TERM_COREDUMP(status)? " (core dumped)": "");
  749.             }
  750.         }
  751.     }
  752. }
  753. #endif
  754.  
  755. /*
  756.  * Open an archive file.  The argument specifies whether we are
  757.  * reading or writing.
  758.  */
  759. /* JF if the arg is 2, open for reading and writing. */
  760. open_archive(reading)
  761.     int reading;
  762. {
  763.     extern int map_read;
  764.  
  765. #ifdef HOST
  766.     if (f_host && reading)
  767.         host_recv(ar_file);
  768. #endif
  769.  
  770.     msg_file = f_exstdout ? stderr : stdout;
  771.  
  772.     if (blocksize == 0) {
  773.         msg("invalid value for blocksize");
  774.         exit(EX_ARGSBAD);
  775.     }
  776.  
  777.     if(ar_file==0) {
  778.         msg("No archive name given, what should I do?");
  779.         exit(EX_BADARCH);
  780.     }
  781.  
  782.     /*NOSTRICT*/
  783.     if(f_multivol) {
  784.         ar_block = (union record *) valloc((unsigned)(blocksize+(2*RECORDSIZE)));
  785.         if(ar_block)
  786.             ar_block += 2;
  787.     } else
  788.         ar_block = (union record *) valloc((unsigned)blocksize);
  789.     if (!ar_block) {
  790.         msg("could not allocate memory for blocking factor %d",
  791.             blocking);
  792.         exit(EX_ARGSBAD);
  793.     }
  794.  
  795.     ar_record = ar_block;
  796.     ar_last   = ar_block + blocking;
  797.     ar_reading = reading;
  798.  
  799.     if (f_compress) {
  800.         if(reading==2 || f_verify) {
  801.             msg("cannot update or verify compressed archives");
  802.             exit(EX_ARGSBAD);
  803.         }
  804.         child_open();
  805.         if(!reading && ar_file[0]=='-' && ar_file[1]=='\0')
  806.             msg_file = stderr;
  807.         /* child_open(rem_host, rem_file); */
  808.     } else if (ar_file[0] == '-' && ar_file[1] == '\0') {
  809.         f_reblock++;    /* Could be a pipe, be safe */
  810.         if(f_verify) {
  811.             msg("can't verify stdin/stdout archive");
  812.             exit(EX_ARGSBAD);
  813.         }
  814.         if(reading==2) {
  815.             archive=STDIN;
  816.             msg_file=stderr;
  817.             write_archive_to_stdout++;
  818.         } else if (reading)
  819.             archive = STDIN;
  820.         else {
  821.             archive = STDOUT;
  822.             msg_file = stderr;
  823.         }
  824.     } else if (reading==2 || f_verify) {
  825.         archive = rmtopen(ar_file, O_RDWR|O_CREAT|O_BINARY, 0666);
  826.     } else if(reading) {
  827.         archive = rmtopen(ar_file, O_RDONLY|O_BINARY, 0666);
  828.     } else {
  829.         archive = rmtcreat(ar_file, 0666);
  830.     }
  831. #ifndef MSDOS
  832.     if(!_isrmt(archive)) {
  833.         struct stat tmp_stat;
  834.  
  835.         fstat(archive,&tmp_stat);
  836.         if((tmp_stat.st_mode&S_IFMT)==S_IFREG) {
  837.             ar_dev=tmp_stat.st_dev;
  838.             ar_ino=tmp_stat.st_ino;
  839.         }
  840.     }
  841. #endif
  842.  
  843.     if (archive < 0) {
  844.         msg_perror("can't open %s",ar_file);
  845.         exit(EX_BADARCH);
  846.     }
  847. #ifdef    MSDOS
  848.     if (!_isrmt(archive))
  849.         setmode(archive, O_BINARY);
  850. #endif
  851.  
  852.     if (reading) {
  853.         ar_last = ar_block;        /* Set up for 1st block = # 0 */
  854.         if (f_map_file && map_read)
  855.             return;
  856.         (void) findrec();        /* Read it in, check for EOF */
  857.  
  858.         if(f_volhdr) {
  859.             union record *head;
  860. #ifndef REGEX
  861.             char *ptr;
  862.  
  863.             if(f_multivol) {
  864.                 ptr=malloc(strlen(f_volhdr)+20);
  865.                 sprintf(ptr,"%s Volume %d",f_volhdr,1);
  866.             } else
  867.                 ptr=f_volhdr;
  868. #endif
  869.             head=findrec();
  870.             if(!head) {
  871.                 msg("Archive not labelled to match %s",f_volhdr);
  872.                 exit(EX_BADVOL);
  873.             }
  874. #ifdef REGEX
  875.             if (re_match (label_pattern, head->header.name,
  876.                       strlen (head->header.name), 0, 0) < 0) {
  877.                 msg ("Volume mismatch!  %s!=%s", f_volhdr,
  878.                      head->header.name);
  879.                 exit (EX_BADVOL);
  880.             }
  881. #else
  882.             if(strcmp(ptr,head->header.name)) {
  883.                 msg("Volume mismatch!  %s!=%s",ptr,head->header.name);
  884.                 exit(EX_BADVOL);
  885.             }
  886.             if(ptr!=f_volhdr)
  887.                 free(ptr);
  888. #endif
  889.         }
  890.     } else if(f_volhdr) {
  891.         bzero((void *)ar_block,RECORDSIZE);
  892.         if(f_multivol)
  893.             sprintf(ar_block->header.name,"%s Volume 1",f_volhdr);
  894.         else
  895.             strcpy(ar_block->header.name,f_volhdr);
  896.         ar_block->header.linkflag = LF_VOLHDR;
  897.         to_oct(time(0),    1+12, ar_block->header.mtime);
  898.         finish_header(ar_block);
  899.         /* ar_record++; */
  900.     }
  901. }
  902.  
  903.  
  904. /*
  905.  * Remember a union record * as pointing to something that we
  906.  * need to keep when reading onward in the file.  Only one such
  907.  * thing can be remembered at once, and it only works when reading
  908.  * an archive.
  909.  *
  910.  * We calculate "offset" then add it because some compilers end up
  911.  * adding (baserec+ar_record), doing a 9-bit shift of baserec, then
  912.  * subtracting ar_block from that, shifting it back, losing the top 9 bits.
  913.  */
  914. saverec(pointer)
  915.     union record **pointer;
  916. {
  917.     long offset;
  918.  
  919.     save_rec = pointer;
  920.     offset = ar_record - ar_block;
  921.     saved_recno = baserec + offset;
  922. }
  923.  
  924. /*
  925.  * Perform a write to flush the buffer.
  926.  */
  927.  
  928. /*send_buffer_to_file();
  929.   if(new_volume) {
  930.       deal_with_new_volume_stuff();
  931.     send_buffer_to_file();
  932.   }
  933.  */
  934.  
  935. fl_write()
  936. {
  937.     int err;
  938.     int copy_back;
  939.     static long bytes_written = 0;
  940.  
  941.     if(tape_length && bytes_written >= tape_length * 1024) {
  942.         errno = ENOSPC;
  943.         err = 0;
  944.     } else
  945.         err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
  946.     if(err!=blocksize && !f_multivol)
  947.         writeerror(err);
  948.     else if (f_totals)
  949.             tot_written += blocksize;
  950.  
  951.     if(err>0)
  952.         bytes_written+=err;
  953.     if (err == blocksize) {
  954.         if(f_multivol) {
  955.             if(!save_name) {
  956.                 real_s_name[0]='\0';
  957.                 real_s_totsize=0;
  958.                 real_s_sizeleft = 0;
  959.                 return;
  960.             }
  961. #ifdef MSDOS
  962.             if(save_name[1]==':')
  963.                 save_name+=2;
  964. #endif
  965.             while(*save_name=='/')
  966.                 save_name++;
  967.  
  968.              /* strcpy(real_s_name,save_name); */
  969.                         strncpy(real_s_name,save_name,NAMSIZ-1);
  970.                         real_s_name[NAMSIZ]='\0';
  971.             real_s_totsize = save_totsize;
  972.             real_s_sizeleft = save_sizeleft;
  973.         }
  974.         return;
  975.     }
  976.  
  977.     /* We're multivol  Panic if we didn't get the right kind of response */
  978.     /* ENXIO is for the UNIX PC */
  979. #ifdef ENXIO
  980.     if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO && errno!=ENXIO))
  981. #else
  982.     if(err>0 || (err<0 && errno!=ENOSPC && errno!=EIO))
  983. #endif
  984.         writeerror(err);
  985.  
  986.     if(new_volume(0)<0)
  987.         return;
  988.     bytes_written=0;
  989.     if(f_volhdr && real_s_name[0]) {
  990.         copy_back=2;
  991.         ar_block-=2;
  992.     } else if(f_volhdr || real_s_name[0]) {
  993.         copy_back = 1;
  994.         ar_block--;
  995.     } else
  996.         copy_back = 0;
  997.     if(f_volhdr) {
  998.         bzero((void *)ar_block,RECORDSIZE);
  999.         sprintf(ar_block->header.name,"%s Volume %d",f_volhdr,volno);
  1000.         to_oct(time(0),    1+12, ar_block->header.mtime);
  1001.         ar_block->header.linkflag = LF_VOLHDR;
  1002.         finish_header(ar_block);
  1003.     }
  1004.     if(real_s_name[0]) {
  1005.         int tmp;
  1006.  
  1007.         if(f_volhdr)
  1008.             ar_block++;
  1009.         bzero((void *)ar_block,RECORDSIZE);
  1010.         strcpy(ar_block->header.name,real_s_name);
  1011.         ar_block->header.linkflag = LF_MULTIVOL;
  1012.         to_oct((long)real_s_sizeleft,1+12,
  1013.                ar_block->header.size);
  1014.         to_oct((long)real_s_totsize-real_s_sizeleft,
  1015.                1+12,ar_block->header.offset);
  1016.         tmp=f_verbose;
  1017.         f_verbose=0;
  1018.         finish_header(ar_block);
  1019.         f_verbose=tmp;
  1020.         if(f_volhdr)
  1021.             ar_block--;
  1022.     }
  1023.  
  1024.     err = rmtwrite(archive, ar_block->charptr,(int) blocksize);
  1025.     if(err!=blocksize)
  1026.         writeerror(err);
  1027.     else if (f_totals)
  1028.             tot_written += blocksize;
  1029.             
  1030.  
  1031.     bytes_written = blocksize;
  1032.     if(copy_back) {
  1033.         ar_block+=copy_back;
  1034.         bcopy((void *)(ar_block+blocking-copy_back),
  1035.               (void *)ar_record,
  1036.               copy_back*RECORDSIZE);
  1037.         ar_record+=copy_back;
  1038.  
  1039.         if(real_s_sizeleft>=copy_back*RECORDSIZE)
  1040.             real_s_sizeleft-=copy_back*RECORDSIZE;
  1041.         else if((real_s_sizeleft+RECORDSIZE-1)/RECORDSIZE<=copy_back)
  1042.             real_s_name[0] = '\0';
  1043.         else {
  1044. #ifdef MSDOS
  1045.             if(save_name[1]==':')
  1046.                 save_name+=2;
  1047. #endif
  1048.             while(*save_name=='/')
  1049.                 save_name++;
  1050.  
  1051.             strcpy(real_s_name,save_name);
  1052.             real_s_sizeleft = save_sizeleft;
  1053.             real_s_totsize=save_totsize;
  1054.         }
  1055.         copy_back = 0;
  1056.     }
  1057. }
  1058.  
  1059. /* Handle write errors on the archive.  Write errors are always fatal */
  1060. /* Hitting the end of a volume does not cause a write error unless the write
  1061. *  was the first block of the volume */
  1062.  
  1063. void
  1064. writeerror(err)
  1065. int err;
  1066. {
  1067.     if (err < 0) {
  1068.         msg_perror("can't write to %s",ar_file);
  1069.         exit(EX_BADARCH);
  1070.     } else {
  1071.         msg("only wrote %u of %u bytes to %s",err,blocksize,ar_file);
  1072.         exit(EX_BADARCH);
  1073.     }
  1074. }
  1075.  
  1076. /*
  1077.  * Handle read errors on the archive.
  1078.  *
  1079.  * If the read should be retried, readerror() returns to the caller.
  1080.  */
  1081. void
  1082. readerror()
  1083. {
  1084. #    define    READ_ERROR_MAX    10
  1085.  
  1086.     read_error_flag++;        /* Tell callers */
  1087.  
  1088.     msg_perror("read error on %s",ar_file);
  1089.  
  1090.     if (baserec == 0) {
  1091.         /* First block of tape.  Probably stupidity error */
  1092.         exit(EX_BADARCH);
  1093.     }
  1094.  
  1095.     /*
  1096.      * Read error in mid archive.  We retry up to READ_ERROR_MAX times
  1097.      * and then give up on reading the archive.  We set read_error_flag
  1098.      * for our callers, so they can cope if they want.
  1099.      */
  1100.     if (r_error_count++ > READ_ERROR_MAX) {
  1101.         msg("Too many errors, quitting.");
  1102.         exit(EX_BADARCH);
  1103.     }
  1104.     return;
  1105. }
  1106.  
  1107.  
  1108. /*
  1109.  * Perform a read to flush the buffer.
  1110.  */
  1111. fl_read()
  1112. {
  1113.     int err;        /* Result from system call */
  1114.     int left;        /* Bytes left */
  1115.     char *more;        /* Pointer to next byte to read */
  1116.  
  1117.     /*
  1118.      * Clear the count of errors.  This only applies to a single
  1119.      * call to fl_read.  We leave read_error_flag alone; it is
  1120.      * only turned off by higher level software.
  1121.      */
  1122.     r_error_count = 0;    /* Clear error count */
  1123.  
  1124.     /*
  1125.      * If we are about to wipe out a record that
  1126.      * somebody needs to keep, copy it out to a holding
  1127.      * area and adjust somebody's pointer to it.
  1128.      */
  1129.     if (save_rec &&
  1130.         *save_rec >= ar_record &&
  1131.         *save_rec < ar_last) {
  1132.         record_save_area = **save_rec;
  1133.         *save_rec = &record_save_area;
  1134.     }
  1135.     if(write_archive_to_stdout && baserec!=0) {
  1136.         err=rmtwrite(1, ar_block->charptr, blocksize);
  1137.         if(err!=blocksize)
  1138.             writeerror(err);
  1139.     }
  1140.     if(f_multivol) {
  1141.         if(save_name) {
  1142.             if(save_name!=real_s_name) {
  1143. #ifdef MSDOS
  1144.                 if(save_name[1]==':')
  1145.                     save_name+=2;
  1146. #endif
  1147.                 while(*save_name=='/')
  1148.                     save_name++;
  1149.  
  1150.                 strcpy(real_s_name,save_name);
  1151.                 save_name=real_s_name;
  1152.             }
  1153.             real_s_totsize = save_totsize;
  1154.             real_s_sizeleft = save_sizeleft;
  1155.                 
  1156.         } else {
  1157.             real_s_name[0]='\0';
  1158.             real_s_totsize=0;
  1159.             real_s_sizeleft = 0;
  1160.         }
  1161.     }
  1162.  
  1163. error_loop:
  1164.     err = rmtread(archive, ar_block->charptr, (int)blocksize);
  1165.     if (err == blocksize)
  1166.         return;
  1167.  
  1168.     if((err == 0 || (err<0 && (errno==ENOSPC || errno == EIO))) && 
  1169.        f_multivol) {
  1170.         union record *head;
  1171.  
  1172.     try_volume:
  1173.         if(new_volume((cmd_mode==CMD_APPEND || cmd_mode==CMD_CAT || cmd_mode==CMD_UPDATE) ? 2 : 1)<0)
  1174.             return;
  1175.     vol_error:
  1176.         err = rmtread(archive, ar_block->charptr,(int) blocksize);
  1177.         if(err < 0) {
  1178.             readerror();
  1179.             goto vol_error;
  1180.         }
  1181.         if(err!=blocksize)
  1182.             goto short_read;
  1183.  
  1184.         head=ar_block;
  1185.  
  1186.         if(head->header.linkflag==LF_VOLHDR) {
  1187.             if(f_volhdr) {
  1188. #ifndef REGEX
  1189.                 char *ptr;
  1190.  
  1191.                 ptr=(char *)malloc(strlen(f_volhdr)+20);
  1192.                 sprintf(ptr,"%s Volume %d",f_volhdr,volno);
  1193. #endif
  1194. #ifdef REGEX
  1195.                 if (re_match (label_pattern, head->header.name,
  1196.                           strlen (head->header.name),
  1197.                           0, 0) < 0) {
  1198.                     msg("Volume mismatch! %s!=%s",f_volhdr,
  1199.                         head->header.name);
  1200.                     --volno;
  1201.                     goto try_volume;
  1202.                       }
  1203. #else
  1204.                  if(strcmp(ptr,head->header.name)) {
  1205.                     msg("Volume mismatch! %s!=%s",ptr,head->header.name);
  1206.                     --volno;
  1207.                     free(ptr);
  1208.                     goto try_volume;
  1209.                 }
  1210.                 free(ptr);
  1211. #endif
  1212.             }
  1213.             if(f_verbose)
  1214.                 fprintf(msg_file,"Reading %s",head->header.name);
  1215.             head++;
  1216.         } else if(f_volhdr) {
  1217.             msg("Warning:  No volume header!");
  1218.         }
  1219.  
  1220.         if(real_s_name[0]) {
  1221.             long from_oct();
  1222.  
  1223.             if(head->header.linkflag!=LF_MULTIVOL || strcmp(head->header.name,real_s_name)) {
  1224.                 msg("%s is not continued on this volume!",real_s_name);
  1225.                 --volno;
  1226.                 goto try_volume;
  1227.             }
  1228.             if(real_s_totsize!=from_oct(1+12,head->header.size)+from_oct(1+12,head->header.offset)) {
  1229.                 msg("%s is the wrong size (%ld!=%ld+%ld)",
  1230.                        head->header.name,save_totsize,
  1231.                        from_oct(1+12,head->header.size),
  1232.                        from_oct(1+12,head->header.offset));
  1233.                 --volno;
  1234.                 goto try_volume;
  1235.             }
  1236.             if(real_s_totsize-real_s_sizeleft!=from_oct(1+12,head->header.offset)) {
  1237.                 msg("This volume is out of sequence");
  1238.                 --volno;
  1239.                 goto try_volume;
  1240.             }
  1241.             head++;
  1242.         }
  1243.         ar_record=head;
  1244.         return;
  1245.     } else if (err < 0) {
  1246.         readerror();
  1247.         goto error_loop;    /* Try again */
  1248.     }
  1249.  
  1250.  short_read:
  1251.     more = ar_block->charptr + err;
  1252.     left = blocksize - err;
  1253.  
  1254. again:
  1255.     if (0 == (((unsigned)left) % RECORDSIZE)) {
  1256.         /* FIXME, for size=0, multi vol support */
  1257.         /* On the first block, warn about the problem */
  1258.         if (!f_reblock && baserec == 0 && f_verbose && err > 0) {
  1259.         /*    msg("Blocksize = %d record%s",
  1260.                 err / RECORDSIZE, (err > RECORDSIZE)? "s": "");*/
  1261.             msg("Blocksize = %d records", err / RECORDSIZE);
  1262.         }
  1263.         ar_last = ar_block + ((unsigned)(blocksize - left))/RECORDSIZE;
  1264.         return;
  1265.     }
  1266.     if (f_reblock) {
  1267.         /*
  1268.          * User warned us about this.  Fix up.
  1269.          */
  1270.         if (left > 0) {
  1271. error2loop:
  1272.             err = rmtread(archive, more, (int)left);
  1273.             if (err < 0) {
  1274.                 readerror();
  1275.                 goto error2loop;    /* Try again */
  1276.             }
  1277.             if (err == 0) {
  1278.                 msg("archive %s EOF not on block boundary",ar_file);
  1279.                 exit(EX_BADARCH);
  1280.             }
  1281.             left -= err;
  1282.             more += err;
  1283.             goto again;
  1284.         }
  1285.     } else {
  1286.         msg("only read %d bytes from archive %s",err,ar_file);
  1287.         exit(EX_BADARCH);
  1288.     }
  1289. }
  1290.  
  1291.  
  1292. /*
  1293.  * Flush the current buffer to/from the archive.
  1294.  */
  1295. flush_archive()
  1296. {
  1297.     int c;
  1298.  
  1299.     baserec += ar_last - ar_block;    /* Keep track of block #s */
  1300.     ar_record = ar_block;        /* Restore pointer to start */
  1301.     ar_last = ar_block + blocking;    /* Restore pointer to end */
  1302.  
  1303.     if (ar_reading) {
  1304.         if(time_to_start_writing) {
  1305.             time_to_start_writing=0;
  1306.             ar_reading=0;
  1307.  
  1308.             if(file_to_switch_to>=0) {
  1309.                 if((c=rmtclose(archive))<0)
  1310.                     msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
  1311.  
  1312.                 archive=file_to_switch_to;
  1313.             } else
  1314.                  (void)backspace_output();
  1315.             fl_write();
  1316.         } else
  1317.             fl_read();
  1318.     } else {
  1319.         fl_write();
  1320.     }
  1321. }
  1322.  
  1323. /* Backspace the archive descriptor by one blocks worth.
  1324.    If its a tape, MTIOCTOP will work.  If its something else,
  1325.    we try to seek on it.  If we can't seek, we lose! */
  1326. backspace_output()
  1327. {
  1328.     long cur;
  1329.     /* int er; */
  1330.     extern char *output_start;
  1331.  
  1332. #ifdef MTIOCTOP
  1333.     struct mtop t;
  1334.  
  1335.     t.mt_op = MTBSR;
  1336.     t.mt_count = 1;
  1337.     if((rmtioctl(archive,MTIOCTOP,&t))>=0)
  1338.         return 1;
  1339.     if(errno==EIO && (rmtioctl(archive,MTIOCTOP,&t))>=0)
  1340.         return 1;
  1341. #endif
  1342.  
  1343.         cur=rmtlseek(archive,0L,1);
  1344.     cur-=blocksize;
  1345.     /* Seek back to the beginning of this block and
  1346.        start writing there. */
  1347.  
  1348.     if(rmtlseek(archive,cur,0)!=cur) {
  1349.         /* Lseek failed.  Try a different method */
  1350.         msg("Couldn't backspace archive file.  It may be unreadable without -i.");
  1351.         /* Replace the first part of the block with nulls */
  1352.         if(ar_block->charptr!=output_start)
  1353.             bzero(ar_block->charptr,output_start-ar_block->charptr);
  1354.         return 2;
  1355.     }
  1356.     return 3;
  1357. }
  1358.  
  1359.  
  1360. /*
  1361.  * Close the archive file.
  1362.  */
  1363. close_archive()
  1364. {
  1365.     int child;
  1366.     int status;
  1367.     int c;
  1368.  
  1369.     if (time_to_start_writing || !ar_reading)
  1370.         flush_archive();
  1371.     if(cmd_mode==CMD_DELETE) {
  1372.         long pos;
  1373.  
  1374.         pos = rmtlseek(archive,0L,1);
  1375. #ifndef MSDOS
  1376.         /* FIXME does ftruncate really take an INT?! */
  1377.         (void) ftruncate(archive,(int)pos);
  1378. #else
  1379.         (void)rmtwrite(archive,"",0);
  1380. #endif
  1381.     }
  1382.     if(f_verify)
  1383.         verify_volume();
  1384.  
  1385.     if((c=rmtclose(archive))<0)
  1386.         msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
  1387.  
  1388.     if (childpid)
  1389.         child_close();
  1390.  
  1391. #ifdef HOST
  1392. !!!!    if (f_host) {
  1393.         if (!ar_reading)
  1394.             host_send(ar_file);
  1395.         host_end();
  1396.     }
  1397. #endif
  1398. }
  1399.  
  1400.  
  1401. #ifdef DONTDEF
  1402. /*
  1403.  * Message management.
  1404.  *
  1405.  * anno writes a message prefix on stream (eg stdout, stderr).
  1406.  *
  1407.  * The specified prefix is normally output followed by a colon and a space.
  1408.  * However, if other command line options are set, more output can come
  1409.  * out, such as the record # within the archive.
  1410.  *
  1411.  * If the specified prefix is NULL, no output is produced unless the
  1412.  * command line option(s) are set.
  1413.  *
  1414.  * If the third argument is 1, the "saved" record # is used; if 0, the
  1415.  * "current" record # is used.
  1416.  */
  1417. void
  1418. anno(stream, prefix, savedp)
  1419.     FILE    *stream;
  1420.     char    *prefix;
  1421.     int    savedp;
  1422. {
  1423. #    define    MAXANNO    50
  1424.     char    buffer[MAXANNO];    /* Holds annorecment */
  1425. #    define    ANNOWIDTH 13
  1426.     int    space;
  1427.     long    offset;
  1428.     int    save_e;
  1429.  
  1430.     save_e=errno;
  1431.     /* Make sure previous output gets out in sequence */
  1432.     if (stream == stderr)
  1433.         fflush(stdout);
  1434.     if (f_sayblock) {
  1435.         if (prefix) {
  1436.             fputs(prefix, stream);
  1437.             putc(' ', stream);
  1438.         }
  1439.         offset = ar_record - ar_block;
  1440.         (void) sprintf(buffer, "rec %d: ",
  1441.             savedp?    saved_recno:
  1442.                 baserec + offset);
  1443.         fputs(buffer, stream);
  1444.         space = ANNOWIDTH - strlen(buffer);
  1445.         if (space > 0) {
  1446.             fprintf(stream, "%*s", space, "");
  1447.         }
  1448.     } else if (prefix) {
  1449.         fputs(prefix, stream);
  1450.         fputs(": ", stream);
  1451.     }
  1452.     errno=save_e;
  1453. }
  1454. #endif
  1455.  
  1456. /* We've hit the end of the old volume.  Close it and open the next one */
  1457. /* Values for type:  0: writing  1: reading  2: updating */
  1458. new_volume(type)
  1459. int    type;
  1460. {
  1461.     int    c;
  1462.     char    inbuf[80];
  1463.     char    *p;
  1464.     static FILE *read_file = 0;
  1465.     extern int now_verifying;
  1466.     extern char TTY_NAME[];
  1467. #ifndef ANSI
  1468.     char *getenv();
  1469. #endif
  1470.  
  1471.     if(!read_file && !f_run_script_at_end)
  1472.         read_file = (archive==0) ? fopen(TTY_NAME, "r") : stdin;
  1473.  
  1474.     if(now_verifying)
  1475.         return -1;
  1476.     if(f_verify)
  1477.         verify_volume();
  1478.     if((c=rmtclose(archive))<0)
  1479.         msg_perror("Warning: can't close %s(%d,%d)",ar_file,archive,c);
  1480.  
  1481.     if (childpid)
  1482.         child_close();
  1483. #ifdef HOST
  1484.     if (f_host && type==0)
  1485.         host_send(ar_file);
  1486. #endif
  1487.     volno++;
  1488.  tryagain:
  1489.     if (f_run_script_at_end)
  1490.         system(info_script);
  1491.     else for(;;) {
  1492.         fprintf(msg_file,"\007Prepare volume #%d and hit return: ",volno);
  1493.         fflush(msg_file);
  1494. #ifdef __EMX__
  1495.                 while (_read_kbd(0, 0, 0) != -1);
  1496.         /* not available with -Zomf -Zsys in 0.8e, but in 0.8f */
  1497. #endif
  1498.         if(fgets(inbuf,sizeof(inbuf),read_file)==0) {
  1499.              fprintf(msg_file,"EOF?  What does that mean?");
  1500.             if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
  1501.                 msg("Warning:  Archive is INCOMPLETE!");
  1502.             exit(EX_BADARCH);
  1503.         }
  1504.         if(inbuf[0]=='\n' || inbuf[0]=='y' || inbuf[0]=='Y')
  1505.             break;
  1506.  
  1507.         switch(inbuf[0]) {
  1508.         case '?':
  1509.         {
  1510.             fprintf(msg_file,"\
  1511.  n [name]   Give a new filename for the next (and subsequent) volume(s)\n\
  1512.  q          Abort tar\n\
  1513.  !          Spawn a subshell\n\
  1514.  ?          Print this list\n");
  1515.         }
  1516.             break;
  1517.  
  1518.         case 'q':    /* Quit */
  1519.             fprintf(msg_file,"No new volume; exiting.\n");
  1520.             if(cmd_mode!=CMD_EXTRACT && cmd_mode!=CMD_LIST && cmd_mode!=CMD_DIFF)
  1521.                 msg("Warning:  Archive is INCOMPLETE!");
  1522.             exit(EX_BADARCH);
  1523.  
  1524.         case 'n':    /* Get new file name */
  1525.         {
  1526.             char *q,*r;
  1527.             static char *old_name;
  1528.  
  1529.             for(q= &inbuf[1];*q==' ' || *q=='\t';q++)
  1530.                 ;
  1531.             for(r=q;*r;r++)
  1532.                 if(*r=='\n')
  1533.                     *r='\0';
  1534.             if(old_name)
  1535.                 free(old_name);
  1536.             old_name=p=(char *)malloc((unsigned)(strlen(q)+2));
  1537.             if(p==0) {
  1538.                 msg("Can't allocate memory for name");
  1539.                 exit(EX_SYSTEM);
  1540.             }
  1541.             (void) strcpy(p,q);
  1542.             ar_file=p;
  1543.         }
  1544.             break;
  1545.  
  1546.         case '!':
  1547. #ifdef MSDOS
  1548.             spawnl(P_WAIT,getenv("COMSPEC"),"-",0);
  1549. #else
  1550.                 /* JF this needs work! */
  1551.             switch(fork()) {
  1552.             case -1:
  1553.                 msg_perror("can't fork!");
  1554.                 break;
  1555.             case 0:
  1556.                 p=getenv("SHELL");
  1557.                 if(p==0) p="/bin/sh";
  1558.                 execlp(p,"-sh","-i",0);
  1559.                 msg_perror("can't exec a shell %s",p);
  1560.                 _exit(55);
  1561.             default:
  1562.                 wait(0);
  1563.                 break;
  1564.             }
  1565. #endif
  1566.             break;
  1567.         }
  1568.     }
  1569.  
  1570. #ifdef HOST
  1571.     if (f_host && type!=0)
  1572.         host_recv(ar_file);
  1573. #endif
  1574.     if(f_compress)
  1575.         child_open();
  1576.     else if(type==2 || f_verify)
  1577.         archive=rmtopen(ar_file,O_RDWR|O_CREAT|O_BINARY,0666);
  1578.     else if(type==1)
  1579.         archive=rmtopen(ar_file,O_RDONLY|O_BINARY,0666);
  1580.     else if(type==0)
  1581.         archive=rmtcreat(ar_file,0666);
  1582.     else
  1583.         archive= -1;
  1584.  
  1585.     if(archive<0) {
  1586.         msg_perror("can't open %s",ar_file);
  1587.         goto tryagain;
  1588.     }
  1589. #ifdef MSDOS
  1590.     setmode(archive,O_BINARY);
  1591. #endif
  1592.     return 0;
  1593. }
  1594.  
  1595. /* this is a useless function that takes a buffer returned by wantbytes
  1596.    and does nothing with it.  If the function called by wantbytes returns
  1597.    an error indicator (non-zero), this function is called for the rest of
  1598.    the file.
  1599.  */
  1600. int
  1601. no_op(size,data)
  1602. int size;
  1603. char *data;
  1604. {
  1605.     return 0;
  1606. }
  1607.  
  1608. /* Some other routine wants SIZE bytes in the archive.  For each chunk of
  1609.    the archive, call FUNC with the size of the chunk, and the address of
  1610.    the chunk it can work with.
  1611.  */
  1612. int
  1613. wantbytes(size,func)
  1614. long size;
  1615. int (*func)();
  1616. {
  1617.     char *data;
  1618.     long    data_size;
  1619.  
  1620.     while(size) {
  1621.         data = findrec()->charptr;
  1622.         if (data == NULL) {    /* Check it... */
  1623.             msg("Unexpected EOF on archive file");
  1624.             return -1;
  1625.         }
  1626.         data_size = endofrecs()->charptr - data;
  1627.         if(data_size>size)
  1628.             data_size=size;
  1629.         if((*func)(data_size,data))
  1630.             func=no_op;
  1631.         userec((union record *)(data + data_size - 1));
  1632.         size-=data_size;
  1633.     }
  1634.     return 0;
  1635. }
  1636.