home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1995 November / PCWK1195.iso / inne / podstawy / dos / archive / tar320c-.exe / SOURCES.ZIP / TAR.C < prev    next >
Encoding:
Text File  |  1995-04-17  |  28.8 KB  |  876 lines

  1. /* tar.c - Tape ARchive utility program (main function)
  2.  * Author: T.V.Shaporev
  3.  * Creation date: 14 Dec 1990
  4.  *
  5.  * The program works in a same fashion under UNIX (most clones) and MS-DOS.
  6.  * The main idear was to develop a tool for file transferring via diskette
  7.  * between different operating systems - such as all UNIX clones, MS-DOS,
  8.  * RSX, VAX/VMS - and all others which support tar format on a diskette.
  9.  *
  10.  * First step on this way (made in 1989) lies in adapting common UNIX tar
  11.  * program to MS-DOS.
  12.  *
  13.  * On the second step
  14.  *  - some bugs were fixed (especially in DOS-applied codes) and some
  15.  *    optimization were done;
  16.  *  - nonstandard (under DOS) diskette formats were added (i.e.
  17.  *    DEC Rainbow and 80 tracks & 9 sectors format)
  18.  *  - the possibility for compress encoding were included
  19.  *    (this compressor has the best ratio among all others which
  20.  *    I know, but don't ask me about its speed). Compressed-file
  21.  *    format is compatible with the common versions of tar, so You
  22.  *    can extract the compressed image from the archive by the
  23.  *    common program, but I doubt You could uncompress them at last.
  24.  *
  25.  * On the fird step the program was totally (newly) overwritten to bypass
  26.  * any copyright exclamations. In fact, it must be considered new program
  27.  * but I prefer to continue version enumeration (I hope, nobody cares).
  28.  *
  29.  * I think, this program must be called Tar (with capital first letter)
  30.  * to distinguish it from regular UNIX tar.
  31.  *
  32.  * The program's behaviour is analogous to usual tar, and I hope, its
  33.  * internal help will be enough to understand the differences.
  34.  *
  35.  * The program doesn't perform any text file conversion - it passes
  36.  * strict binary image of each file. If You has a problems with reading
  37.  * DOS text files under UNIX (or UNIX files under DOS) please use my
  38.  * dostext program.
  39.  *
  40.  * The program must be compiled by Turbo C 2.0 compiler (in a compact
  41.  * model) under MS-DOS. Please don't replace dynamic arrays back to
  42.  * static and automatic - MS-DOS compilers dislike them.
  43.  *
  44.  *            tim    tim@ecsc.mipt.su    14 Dec 1990
  45.  */
  46. /* Version 3.01
  47.  * Handling of the 'l' option corrected
  48.  */
  49. /* Version 3.02                                       31 Dec 1990
  50.  *  - great deal of minor corrections
  51.  *  - u<pdate> option expanded to extracting
  52.  *  - j<ournal> option added (comment storying files)
  53.  *  - wildcards * and ? are now processed in archive; this may be
  54.  *    suppressed by s<trict> option
  55.  *  - d<elete> option added to replace previous occurencies of files
  56.  *    in archive on storying, or deleting files from archive when
  57.  *    whithout a<dd> parameter - this is for file archives only!
  58.  */
  59. /* Version 3.03                                       22 Feb 1991
  60.  *  - an error corrected in mismatch() (file extract.c)
  61.  *  - decreased stack requirements for tree processing
  62.  *    (see store() in store.c and putfiles() in tar.c)
  63.  *  - added codes to prevent archive file self-storying
  64.  *    (not quite reliable for MS-DOS)
  65.  *  - bincall() invocations changed by calls to rmdir() and mkdir()
  66.  *    this is done automatically for 386/ix and may be switched by
  67.  *    RMKDIR macro
  68.  */
  69. /* Version 3.04                                       29 Jul 1991
  70.  *  - a direct intialization of static global variables inserted into
  71.  *    lzencode() and lzdecode() - see file lzpack.c
  72.  */
  73. /* Version 3.04b                                      03 Oct 1991
  74.  *  - a minor correction of bincall()
  75.  *  - added default block number = sectors on track (MS-DOS)
  76.  */
  77. /* Version 3.05                                       11 Nov 1991
  78.  *  - block factor for diskette writing is set to 1 for most BIOS
  79.  *    compatibility
  80.  *  - scantape() is slightly optimized
  81.  */
  82. /* Version 3.06                                       17 Dec 1991
  83.  *  - n<onest> option applied to all actions (see inarg() in extract.c)
  84.  *  - command-line-extension-file option (responce file) added
  85.  *    for vak (vak@kiae.su) request (see append() in tar.c)
  86.  *  - p<ermission> option added to save directories permissions (UNIX)
  87.  */
  88. /* Version 3.06b                                      22 Dec 1991
  89.  *   - UNIX to DOS renaming algorithm (dot elimination) slightly
  90.  *     changed (see extract.c)
  91.  *   - most of output redirected to stdout (vs stderr)
  92.  */
  93. /* Version 3.07                                       28 Dec 1992
  94.  *   - all unary apostrofs in string constants preserved by backslashes
  95.  *   - reading file list from stdin allowed (see append() in tar.c)
  96.  *   - input redirected to /dev/tty under UNIX
  97.  *   - support for traditional UNIX compression algorithm
  98.  *   - few changes in converting UNIX names for DOS
  99.  */
  100. /* Version 3.07b                                      20 Jan 1993
  101.  *   - gethead() does not return FALSE while errors,
  102.  *     scantape() looks for tape reading errors
  103.  */
  104. /* Version 3.08                                       22 Feb 1993
  105.  *   - method-dependent comression indicator masks (see percent.c)
  106.  *   - 'z' option applied to catalog printing (see catalog())
  107.  *   - compatibility corrections in directory structure checking
  108.  *   - st.st_size == codesize - means file unpacked! (see extract.c)
  109.  */
  110. /* Version 3.09                                       14 Mar 1993
  111.  *   - a bug fixed wich prevents archiving unpacked files at all
  112.  *     (ha-ha!) - see store.c
  113.  *   - changed header description to support new features
  114.  *     see define.h
  115.  *   - support for P1003 and GNU file types - 't' option only! -
  116.  *     see extract.c
  117.  *   - small changes in #ifdef-s to distinguish SCO UNIXes from
  118.  *     XENIXes - see store.c
  119.  *   - regular file processing extracted into separate source
  120.  *     files (see savefile.c & restore.c)
  121.  *   - support for devices and FIFOs added
  122.  *   - 'l' option added for DOS (copy linked files)
  123.  *   - support for System V extents - see extract.c and restore.c
  124.  *     to read archives only, extents may not be unpacked on the
  125.  *     fly - alas, that's all for now
  126.  *   - an error corrected in roll.c
  127.  */
  128. /* Version 3.10                                       28 Jun 1993
  129.  *   - a bug fixed in old compression code (see lzpack.c)
  130.  *   - added possibility to run through compress (',' comma option)
  131.  *     see tar.c, tape.c and compress.c
  132.  *   - comments will not be printed unless 'j' is given (extract.c)
  133.  *   - separated compress-related codes
  134.  */
  135. /* Version 3.11                                       14 Jul 1993
  136.  *   - support for QIC-02 streamers (first version!)
  137.  *     devices supported: fastape, everex
  138.  */
  139. /* Version 3.12                                       29 Sen 1993
  140.  *   - slack area in archive is filled by nulls to improve compression
  141.  *   - added support for Wangtek (QIC-02) device
  142.  *   - a bug fixed in memory release ('pk_out' variable - see _done())
  143.  *   - program support for QIC-02 drive number and tape format
  144.  *     selection
  145.  *   - experimental (!) support for appending QIC-02 tapes
  146.  *     (see qback() in qicface.c)
  147.  *   - LZW support splitted into compressor and extractor and
  148.  *     the letter included in official release (see unlzw.c etc.)
  149.  *   - get default file name from TAPE environment variable
  150.  *   - 'o' flag for DOS means prevent file overwriting
  151.  */
  152. /* Version 3.12b                                      10 Nov 1993
  153.  *   - an error corrected in QIC device selection (see qicface.c)
  154.  *   - eliminated idle rewindings around QIC tape initialisation
  155.  */
  156. /* Version 3.13                                       26 Dec 1993
  157.  *   - online inflatter (unzip) and corresponding '.' (dot) option
  158.  */
  159. /* Version 3.14                                       19 Feb 1994
  160.  *   - online deflatter (zip); compilation model changed to large
  161.  */
  162. /* Version 3.15 - general bugfix                      03 Apr 1994
  163.  *   - strerror() missed in some UNIXes, so psyserr() function added
  164.  *     into tape.c
  165.  *   - extended local header signature inserted in deflated output and
  166.  *     unzclose() changed to uderstand both formats
  167.  *     (see zipdefs.h, zippipe.c and diszip.c)
  168.  *   - pkflush() output is aligned to pksize boundary if output is not
  169.  *     regular file or DOS floppy to avoid block device alignment error
  170.  *     (see tape.c)
  171.  *   - "total blocks" number is reported accordingly to real archive
  172.  *     size (see tape.c, extract.c, tar.c)
  173.  */
  174. /* Version 3.15b - bugfix                             15 Jun 1994
  175.  *   - uname() (see restore.c) bug fixed;
  176.  *   - bi_reverse() cleaned (__emit__ed code cause BC 3.1 error)
  177.  *     moved to trees.c and renamed;
  178.  *   - getlg() changed to look for NEEDBITS buffer;
  179.  *   - diszip.c cleaned a bit.
  180.  */
  181. /* Version 3.16                                       ?? Jul 1994
  182.  *   - got rid of __emit__() - completely;
  183.  *   - got rid of "#pragma pack()" - see define.h;
  184.  *   - error corrected in ct_free() (see trees.c);
  185.  *   - default (-e) compression changed to deflation,
  186.  *     keep support for old-style decompression;
  187.  *   - exclude file(s) specification ('#' option) - up to 16 patterns
  188.  *     (see fmatch.c, store.c, extract.c);
  189.  *   - autodetection of compressed or (g)zipped archives
  190.  *     (pktest() from extract.c etc.)
  191.  */
  192. /* Version 3.17                                       04 Nov 1994
  193.  *   - changed foloppy calibrating logic (see disk.c), added diskspec()
  194.  *     function (see pclevel.asm) and support for 2.88M floppies (?);
  195.  *   - corrected missing IBEGIN updating into diszip.c;
  196.  *   - added 'drop online' op. into streamer() and qend();
  197.  *   - restored handling of ':' option in savefile();
  198.  *   - restored "idle rewindings" while starting tape since
  199.  *     they arrear to improve reliability;
  200.  *   - use conditional XOFF flag in ct_iobyte() (see streamer.c);
  201.  *   - added explicit call to tzset() in tar.c;
  202.  *   - implemented 'add' and 'skip' device parameters;
  203.  *   - unzipping stored file (see diszip.c),
  204.  *     gmtime() changed to localtime() in zippipe.c;
  205.  *   - GNU-like command line syntax, environment configuration;
  206.  *   - cascade EOI changed to specific in cthandle.asm.
  207.  */
  208. /* Version 3.18                                       24 Dec 1994
  209.      - ASPI support (first version!);
  210.      - bug fixed in blocksize reading (see readblk() in readopt.c);
  211.      - bug fixed in pattern comparing (see mismatch() in fmatch.c)
  212.  */
  213. #include "sysup.h"
  214. #include "modern.h"
  215. #include "zippipe.h"
  216. #include "lzwbits.h"
  217. #include "lzwhead.h"
  218. #include "compress.h"
  219.  
  220. static char note[] = "\n\
  221.    Tape ARchive utility        v3.20c%c        (C) 1990-94 Tim V.Shaporev\n";
  222.  
  223. #ifdef USE_COMPRESS
  224. #    define SIGN_VERSION '+'
  225. #else
  226. #    define SIGN_VERSION '-'
  227. #endif
  228.  
  229. #ifdef UNIX
  230. static char help[] = "\n\
  231.    Usage: tar -<options> [tapefile] [blocksize] [disksize] file ...\n\n\
  232.    Options are:                       s - no wildcards for archive\n\
  233.      c - put files to new archive     i - ignore read errors\n\
  234.      a,r - add files to archive       m - forget files origin date/time\n\
  235.      y - move files to archive        o - forget files owner\n\
  236.      x - extract files from archive   l - type missed links\n\
  237.      t - show archive catalog         p - save directories & permissions\n\
  238.      d - delete files in archive      n - no proceed with dir nesting\n\
  239.      u - update files                 / - omit left \'/\' in file names\n\
  240.      v - verbose                      0...7 - number of tape device\n\
  241.      w - acknowledge operations       j - comment storying files\n\
  242.      e - compress encode files        f - next arg is an archive file\n\
  243.      z - old-fashion compression      b - next arg is a blocking factor\n\
  244.      , - run through compressor       @ - next arg is a responce file\n\
  245.      . - run through (g)zip           # - exclude file(s) specification\n\
  246. ";
  247. #endif
  248.  
  249. #ifdef MSDOS
  250. static char help[] = "\n\
  251.    Usage: tar -<options> [tapefile] [blocksize] [disksize] file ...\n\n\
  252.    Options are:\n\
  253.      c - put files to new archive     s - no wildcards for archive\n\
  254.      a,r - add files to archive       m - forget files date/time\n\
  255.      y - move files to archive        n - no proceed with dir nesting\n\
  256.      x - extract files from archive   l - copy linked files\n\
  257.      t - show archive catalog         o - prevent files overwriting\n\
  258.      d - delete files in archive      \\ - omit left \'\\\' in file names\n\
  259.      u - update files                 : - omit DOS drive name\n\
  260.      v - verbose                      0...3 - number of storage device\n\
  261.      w - acknowledge operations       j - comment storying files\n\
  262.      i - ignore read errors           f - next arg is an archive file\n\
  263.      e - compress encode files        b - next arg is a blocking factor\n\
  264.      z - old-fashion compression      k - next arg is K diskette size\n\
  265.      , - run through compressor       @ - next arg is a responce file\n\
  266.      . - run through (g)zip           # - exclude file(s) specification\n\
  267. \n\
  268.    Most of options may be combined. Wildcards * and ? are o\'k\n\
  269. ";
  270. static char devlist[] = "\n\
  271.    The following \"file names\" will be treated as diskette format/size:\n\
  272. \tfd048ss8  - 160K\tfd048ds8  - 320K\tfd135ds9  - 720K\n\
  273. \tfd048ss9  - 180K\tfd048ds9  - 360K\tfd135ds18 - 1.4M\n\
  274. \tfd096ds9  - 720K\tfd096ds15 - 1.2M\trainbow\n\
  275. \n\
  276.    Streamer \"file name\" syntax (full form) is:\n\
  277. \t<device>:base:=<base address>h,dma:=<DRQ>[,irq:=<IRQ>][,norewind]\n\
  278.    Streamer device clones supported are:\n\
  279. \tarchive,\teverex,\t\twangtek\n\
  280. \n\
  281.    The following \"file names\" are aliases for ASPI driven SCSI streamer:\n\
  282. \taspitape,\taspimgr$,\taspi\n\
  283.    Full form is:\n\
  284. \taspi[:target:=<n>[,lun:=<n>][,adapter:=<n>][,density:=<x>]]\n\
  285. ";
  286. #endif
  287.  
  288. #include <signal.h>
  289. #include <stdio.h>
  290. #ifdef MSDOS
  291. #    include <string.h>
  292. #    include <stdlib.h>
  293. #    include <time.h>
  294. #    include <dos.h>
  295. #    include <dir.h>
  296. #    include <io.h>
  297. #else
  298.     char *strcpy(), *strcat(), *strncpy();
  299.         char *getenv(), *malloc(), *realloc();
  300.     int  open(), read(), close(), link(), unlink(), isatty();
  301.     int  strlen(), strncmp(), atoi();
  302.         void exit(), free();
  303.     long lseek();
  304. #endif
  305.  
  306. #define __ALLOCEXT__
  307. #include "define.h"
  308.  
  309. #include "lzpack.h"
  310. #include "roll.h"
  311.  
  312. #ifdef UNIX
  313. #    ifdef MAXNAMSIZ
  314. #        define MAXPATH MAXNAMSIZ+1
  315. #    else
  316. #        define MAXPATH 512+1
  317. #    endif
  318. #endif
  319.  
  320. #ifdef UNIX
  321. #    ifndef RMKDIR
  322. int bincall(name, args)
  323. char *name, *args;
  324. {
  325.    extern int fork(), execl(), wait();
  326.    int i; register k;
  327.    char b[24];
  328.  
  329.    if (fork() == 0) {
  330.       (void)execl(strcat(strcpy(b, "/bin/"),     name), name, args, 0);
  331.       (void)execl(strcat(strcpy(b, "/usr/bin/"), name), name, args, 0);
  332.       k = -1;
  333.    } else {
  334.       (void)wait(&i); k = i>>8;
  335.    }
  336.    return k;
  337. }
  338. #    endif
  339. #endif
  340.  
  341. #ifdef MSDOS
  342. void takename(dst, src)
  343. register char *dst, *src;
  344. {
  345.    do {
  346.       *(dst++) = *src >= 'A' && *src <= 'Z' ? *src + ('z'-'Z') :
  347.                  *src == '\\' ? '/' : *src;
  348.    } while (*(src++));
  349. }
  350. #endif
  351.  
  352. short headsum(h)
  353. header *h;
  354. {
  355.    register short i, j;
  356.  
  357.    for (i=0, j=0; i<BLKSIZE; i++) {
  358.       j += i >= MAXTNAME+3*8+2*12 && i < MAXTNAME+3*8+2*12+8 ?
  359.            ' ' : *((unsigned char *)h + i);
  360.    }
  361. #if ~0 != 0177777
  362.    return j & 0177777;
  363. #else
  364.    return j;
  365. #endif
  366. }
  367.  
  368. node *finditem(fname, prev, head)
  369. char *fname; node **prev, *head;
  370. {
  371.    register node *this;
  372.    register i;
  373.  
  374.    *prev = this = head; i = 1;
  375.    while (this && i>0) {
  376.       if ((i = strcmp(fname, this->name)) > 0) {
  377.          *prev = this; this = this->next;
  378.       }
  379.    }
  380.    return i ? NONE : this;
  381. }
  382.  
  383. node *additem(fname, prev, head)
  384. char *fname; node *prev, **head;
  385. {
  386.    register node *this;
  387.    register i;
  388.  
  389.    i = sizeof(node) - (MINTNAME-1) + strlen(fname);
  390.    if ((this = (node *)malloc(i)) == NULL) return NONE;
  391.    (void)strcpy(this->name, fname);
  392.    this->prev = prev;
  393.    if (prev != NONE) {
  394.       if ((this->next = prev->next) != NONE) this->next->prev = this;
  395.       prev->next = this;
  396.    } else {/* initialise the list */
  397.       this->next = NONE;
  398.       (*head) = this;
  399.    }
  400.    return this;
  401. }
  402.  
  403. void delitem(this, head)
  404. node *this, **head;
  405. {
  406.    if (this == *head) {/* head of the list */
  407.       if (this->next != NONE) {
  408.          this->next->prev = this->prev != this ? this->prev : this->next;
  409.       }
  410.       this = this->next;
  411.       free(*head);
  412.       *head = this;
  413.    } else {
  414.       if (this->next != NONE) this->next->prev = this->prev;
  415.       this->prev->next = this->next;
  416.       free(this);
  417.    }
  418. }
  419.  
  420. static void _done __ARGS__(( void ))
  421. {
  422.    register node *p, *q;
  423. #ifdef MSDOS
  424.    extern void qend __ARGS__((void)), aspiend __ARGS__((void));
  425.  
  426.    if      (devtype == DEV_QIC2) qend();
  427.    else if (devtype == DEV_ASPI) aspiend();
  428.    if (archname) free(archname);
  429. #endif
  430.    if (responce)  free(responce);
  431.    if (argvector) free((char*)argvector);
  432.    if (tarcmd)    free(tarcmd);
  433.    p = timehead; while (p) { q = p->next; free(p); p = q; }
  434. #ifdef UNIX
  435.    p = linkhead; while (p) { q = p->next; free(p); p = q; }
  436. #endif
  437.    if (hwrite >= 0 && hwrite != handle) {
  438.       (void)close(hwrite); (void)unlink(scratch);
  439.    }
  440.    if (io_2nd && io_2nd!=io_buf) free(io_2nd);
  441.    if (io_buf) free(io_buf);
  442.    if (pk_out && pk_out!=pk_inp) free(pk_out);
  443.    if (pk_inp) free(pk_inp);
  444.    zipfree();
  445.    unzfree();
  446. #ifdef USE_COMPRESS
  447.    z_reltab();
  448. #endif
  449.    z_relmem();
  450.    delroll();
  451. }
  452.  
  453. void done(n)
  454. int n;
  455. {
  456.    _done(); exit(n);
  457. }
  458.  
  459. void outmem(f)
  460. FILE *f;
  461. {
  462.    (void)fprintf(f, "Tar: not enough memory\n");
  463.    done(ESMALL);
  464. }
  465.  
  466. char *salloc(n)
  467. int n;
  468. {
  469.    register char *p;
  470.  
  471.    if ((p = malloc(n)) == NULL) outmem(stderr);
  472.    return p;
  473. }
  474.  
  475. int yes_no(d)
  476. char d;
  477. {
  478.    register int c;
  479. #ifdef MSDOS
  480.    extern int getkey __ARGS__((void));
  481.  
  482.    do {
  483.       c = getkey();
  484.    } while (c!='y' && c!='Y' && c!='n' && c!='N' && c!='q' && c!='Q' &&
  485.             c!='\r' && c!='\n' && c!=27 && c!=3);
  486.    if (c == 3) {
  487.       cbreak = TRUE;
  488.    } else if (c >= ' ') {
  489.       (void)fprintf(stderr, "%c", c);
  490.    } else if (d) {
  491.       (void)fprintf(stderr, "%c", d);
  492.    }
  493.    (void)fprintf(stderr, "\n");
  494. #else
  495.    if ((c = getc(myinp)) == '\n') {
  496.       c = d;
  497.    } else {
  498.       while (getc(myinp) != '\n') ;
  499.    }
  500. #endif
  501.    if (c == 'q' || c == 'Q') done(EXIT);
  502.    return c == 'y' || c == 'Y';
  503. }
  504.  
  505. void prmode(c, m)
  506. char c; int m;
  507. {
  508.    (void)fprintf(myout, "%c%c%c%c%c%c%c%c%c%c", c,
  509.       (m & S_IREAD ? 'r' : '-'), (m & S_IWRITE? 'w' : '-'),
  510.       (m & S_ISUID ? 's' : m & S_IEXEC ? 'x' : '-'),
  511.       (m & 00040   ? 'r' : '-'), (m & 00020   ? 'w' : '-'),
  512.       (m & S_ISGID ? 's' : m & 00010   ? 'x' : '-'),
  513.       (m & 00004   ? 'r' : '-'), (m & 00002   ? 'w' : '-'),
  514.       (m & S_ISVTX ? 't' : m & 00001   ? 'x' : '-'));
  515. }
  516.  
  517. int okwork(c, p, s, n)
  518. char c, p, *n;
  519. struct stat *s;
  520. {
  521.    register m;
  522.  
  523.    (void)fprintf(stderr, "%c ", c);
  524.    if (v_flag) {
  525.       if (p == ' ' && (m = s->st_mode & S_IFMT) != 0) {
  526.          switch (m) {
  527.             case S_IFREG: break;
  528.             case S_IFDIR: p = 'd'; break;
  529.             case S_IFIFO: p = 'p'; break;
  530.             case S_IFCHR: p = 'c'; break;
  531.             case S_IFBLK: p = 'b'; break;
  532. #ifdef S_IFLNK
  533.             case S_IFLNK: p = 'l'; break;
  534. #endif
  535.             default:      p = '?';
  536.          }
  537.       }
  538.       prmode(p, (int)(s->st_mode));
  539.       (void)fprintf(stderr," %3d/%1d %7ld ",s->st_uid,s->st_gid,s->st_size);
  540.    }
  541.    (void)fprintf(stderr, "%s : ", n);
  542.    return YES_NO();
  543. }
  544.  
  545. void onintr() { (void)signal(SIGINT,  SIG_IGN); cbreak = TRUE; }
  546. #ifdef UNIX
  547. void onquit() { (void)signal(SIGQUIT, SIG_IGN); cbreak = TRUE; }
  548. void onhup()  { (void)signal(SIGHUP,  SIG_IGN); cbreak = TRUE; }
  549. #endif
  550.  
  551. static void set_sig __ARGS__(( void ))
  552. {
  553.    if (signal(SIGINT, SIG_IGN) != SIG_IGN) (void)signal(SIGINT, onintr);
  554. #ifdef UNIX
  555.    if (signal(SIGHUP, SIG_IGN) != SIG_IGN) (void)signal(SIGHUP, onhup );
  556.    if (signal(SIGQUIT,SIG_IGN) != SIG_IGN) (void)signal(SIGQUIT,onquit);
  557. #endif
  558. }
  559.  
  560. static void delfile __ARGS__(( void ))
  561. {
  562.    if (v_flag)
  563.       (void)fprintf(myout, "d %s, %ld bytes, %ld tape blocks\n",
  564.          hblock->m.name, st.st_size, (st.st_size + (BLKSIZE-1))/BLKSIZE);
  565.    if (usize()) skipfile();
  566. }
  567.  
  568. static void putfiles __ARGS__(( int, char ** ));
  569.  
  570. static void putfiles(argc, argv)
  571. int argc; char *argv[];
  572. {
  573.    register i;
  574.    char fnmbuf[MAXPATH];
  575.  
  576.    for (i=0; i<argc; i++) {
  577.       if (strlen(argv[i]) > MAXTNAME) {
  578.          (void)fprintf(myout, "Tar: \'%s\' name too long\n", argv[i]);
  579.          continue;
  580.       }
  581.       takename(fnmbuf, argv[i]);
  582.       store(fnmbuf);
  583.    }
  584. }
  585.  
  586. static void stdhelp __ARGS__((void))
  587. {
  588.    (void)fprintf(stdout, note, SIGN_VERSION);
  589.    (void)fprintf(stdout, help);
  590.    (void)fflush (stdout);
  591. #ifdef MSDOS
  592.    if (ioctl(fileno(stdout),0) & 0x80) {/* not a disk file */
  593.       (void)fprintf(stderr,"\nDo you want to see device list? ");
  594.       (void)fflush (stderr);
  595.       if (!YES_NO()) return;
  596.    }
  597.    (void)fprintf(stdout, devlist);
  598. #endif
  599. }
  600.  
  601. int pkalloc()
  602. {
  603.    register k;
  604.  
  605.    if (pktype == PKpLZW || pktype == PKZIP) {/* Pipe compression */
  606.       pksize = BLKSIZE;
  607.       k = (d_flag || x_flag || t_flag) && (pk_inp=malloc(pksize))==NULL ||
  608.           (d_flag || a_flag)           && (pk_out=malloc(pksize))==NULL;
  609.    } else {/* Individual file(s) compression */
  610.       pksize = PKSIZE;
  611.       k = (d_flag || x_flag || (t_flag && pktype == PKfLZW)) &&
  612.                                 (pk_out=malloc(pksize))==NULL ||
  613.           (d_flag || a_flag) && (pk_inp=malloc(pksize))==NULL;
  614.    }
  615.    return k;
  616. }
  617.  
  618. int main(argc, argv)
  619. int argc; char *argv[];
  620. {
  621.    register i, k;
  622.    register char *p;
  623.    int cenv; char **earg;
  624.  
  625.    if (argc < 2) {
  626.       stdhelp(); return ERRARG;
  627.    }
  628. #ifdef MSDOS
  629.    setdrive = FALSE;
  630.    filemask = FA_SYSTEM+FA_HIDDEN+FA_RDONLY+FA_DIREC+FA_ARCH;
  631. #endif
  632.    pktype = PKNONE;
  633.    pklock = FALSE;
  634.    cblock = 0;
  635.    tapename = NULL;
  636.    myout = stdout;
  637.    xcnt = 0;
  638.    lzwbits = BITS; ziplevel = 6;
  639.  
  640.    /* Skip the program name */ --argc; ++argv;
  641.    appname = NULL;
  642.    if ((cenv = envbuild(0, &earg)) > 0) {
  643.       i = readopt(&cenv, &earg, OPTFLAG);
  644.       if (i < cenv) {
  645.          revector(argc, &argv, cenv-i);
  646.          /* append new arguments */
  647.          while(i<cenv) argv[argc++] = earg[i++];
  648.       }
  649.       if (appname) argc = argfile(argc, &argv, appname, &responce);
  650.    }
  651.    i = readopt(&argc, &argv, 0);
  652.    pktype &= OPTMASK;
  653. #ifdef MSDOS
  654.    if (nonest) filemask = FA_SYSTEM+FA_HIDDEN+FA_RDONLY+FA_ARCH;
  655. #endif
  656.    if (
  657. #ifdef MSDOS
  658.        !k_flag &&
  659. #endif
  660.                   !tapename) tapename = getenv("TAPE");
  661.    if (!a_flag && !x_flag && !t_flag && !d_flag) {
  662.       (void)fprintf(stderr, "Tar: nothing to do\n"); return ERRARG;
  663.    }
  664.    if (a_flag || d_flag) {
  665.       if (i >= argc) {
  666.          (void)fprintf(stderr, "Tar: no files specified\n");
  667.          return ERRARG;
  668.       }
  669. #ifndef USE_COMPRESS
  670.       if (pktype == PKfLZW || pktype == PKpLZW) {
  671.          (void)fprintf(stderr,
  672.          "Tar: this restricted version does not support LZW compression\n");
  673.          return ERRARG;
  674.       }
  675. #endif
  676.    }
  677.    if ((k = initape(tapename)) != CORRECT) done(k);
  678.    if ((io_buf=getbuf(cblock ? cblock*BLKSIZE : MAXBLOCK*BLKSIZE)) == NULL)
  679.       done(ESMALL);
  680.    io_2nd = io_buf;
  681.    if (pktype != PKNONE) {
  682.       if (pkalloc()) {/* Memory lack */
  683.          if (!w_flag) {
  684.             outmem(stderr);
  685.          } else {
  686.             (void)fprintf(stderr,
  687.                "No memory for [de]compression. Continue? ");
  688.             k = YES_NO();
  689.             (void)fprintf(stderr, "\n");
  690.             if (!k) done(ESMALL);
  691.             if (pk_inp) { free(pk_inp); pk_inp = NULL; }
  692.             pktype = PKNONE;
  693.          }
  694.       }
  695.    }
  696.    cbreak = FALSE;
  697.  
  698.    if ((k = runtape()) != CORRECT) done(k);
  699. #ifdef UNIX
  700.    myinp = stdin;
  701.    if (!isatty(/* stdin */ 0) && (myinp = fopen("/dev/tty", "r")) == NULL) {
  702.       (void)fprintf(myout,
  703.          "Tar: warning: can\'t open terminal device, may be problems\n");
  704.       myinp = stdin;
  705.    }
  706. #endif
  707.  
  708. #ifdef MSDOS
  709.    if (a_flag && isfile) {
  710.       p = tapename;
  711.       if ((p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z') && p[1]==':') {
  712.          k = p[0] < 'a' ? p[0] - ('A'-1) : p[0] - ('a'-1); p += 2;
  713.       } else {
  714.          k = 0;
  715.       }
  716.       if (p[0] == '/' || p[0] == '\\') {
  717.          takename((archname = salloc(strlen(p) + 1)), p);
  718.       } else {
  719.          archname = salloc(strlen(p) + MAXPATH);
  720.          *(int *)archname = '/';
  721.          getcurdir(k, archname+1); takename(archname, archname);
  722.          k = strlen(archname);
  723.          archname[k++] = '/';
  724.          takename(archname+k, p);
  725.       }
  726.    }
  727.    /* Turbo C 2.0 stat() does not call tzset(), so
  728.       invoke it explicitly (for non-file archives) */
  729.    tzset();
  730. #endif
  731.    argc -= i; argv += i;
  732.  
  733.    if (d_flag) {
  734.       register header *h; register long l; register m;
  735.  
  736.       if (d_flag && !isfile) {
  737.          (void)fprintf(stderr,
  738.                        "Tar: delete option is for file archives only\n");
  739.          return ERRARG;
  740.       }
  741.       duptape(tapename);
  742.  
  743.       m = FALSE;
  744.       do {
  745.          if ((k = gethead()) == ERROR) done(ERREAD);
  746.          if (!k) continue;
  747.  
  748.          if        (a_flag) {
  749.             struct stat s;
  750.  
  751.              if (inargs(argc, argv, hblock->m.name)) {
  752.                 if (u_flag) uplist();
  753.                 if (stat(hblock->m.name, &s)!=0) {
  754.                    if (v_flag) {
  755.                       (void)fprintf(myout, "Tar: can\'t access \'%s\'\n",
  756.                                             hblock->m.name);
  757.                    }
  758.                 } else if (!u_flag || s.st_mtime > st.st_mtime) {
  759.                    delfile(); continue;
  760.                 }
  761.              }
  762.          } else {/* pure delete */
  763.             if (inargs(argc, argv, hblock->m.name) ||
  764.                ((hblock->m.filetype==TF_LNK || hblock->m.filetype==TF_SYM) &&
  765.                 inargs(argc, argv, hblock->m.linkname))) {
  766.                m = TRUE; delfile(); continue;
  767.             }
  768.          }
  769.  
  770.          /* move file to output archive */
  771.          for (h=steptape(), i=0; i<BLKSIZE/sizeof(int); i++) {
  772.             ((int *)h)[i] = ((int *)hblock)[i];
  773.          }
  774.          if (usize()) {
  775.             l = (st.st_size + (BLKSIZE-1)) / BLKSIZE;
  776.             while (l-- > 0) {
  777.                if ((hblock = readtape()) == NULL) done(ERREAD);
  778.                for (h=steptape(), i=0; i<BLKSIZE/sizeof(int); i++) {
  779.                   ((int *)h)[i] = ((int *)hblock)[i];
  780.                }
  781.             }
  782.          }
  783.       } while (k);
  784.  
  785.       if (a_flag) {
  786.          l = lseek(hwrite, 0L, 1);
  787.          putfiles(argc, argv);
  788.          m = lseek(hwrite, 0L, 1) > l;
  789.       }
  790.  
  791.       if (m) {/* archive was modified */
  792.          endtape();
  793.          if (unlink(tapename)) {
  794.             (void)fprintf(myout, "Tar: can\'t delete \'%s\'\n", tapename);
  795.             done(EWRITE);
  796.          }
  797. #ifdef UNIX
  798.          if (link(scratch, tapename)) {
  799.             (void)fprintf(myout,
  800.                "Tar: can\'t link \'%s\' - data stay in \'%s\'\n",
  801.                tapename, scratch);
  802.             done(EWRITE);
  803.          }
  804.          if (unlink(scratch)) {
  805.             (void)fprintf(myout, "Tar: can\'t delete scratch file\n");
  806.          }
  807. #endif
  808.  
  809. #ifdef MSDOS
  810.          if (rename(scratch, tapename)) {
  811.             (void)fprintf(myout, "Tar: can\'t rename \'%s\' to \'%s\'\n",
  812.                                   scratch, tapename);
  813.             done(EWRITE);
  814.          }
  815. #endif
  816.  
  817. #ifdef UNIX
  818.          if (a_flag && l_flag) {
  819.             register node *this;
  820.  
  821.             for (this=linkhead; this; this=this->next) {
  822.                (void)fprintf(myout, "Tar: missed %d link(s) to \'%s\'\n",
  823.                              this->info.data.count, this->name);
  824.             }
  825.          }
  826. #endif
  827.       } else {
  828.          if (v_flag) (void)fprintf(myout, "Tar: archive unchanged\n");
  829.          (void)close(hwrite);
  830.          if (unlink(scratch)) {
  831.             (void)fprintf(myout, "Tar: can\'t delete scratch file\n");
  832.             done(EWRITE);
  833.          }
  834.       }
  835.    } else if (a_flag) {
  836. #ifdef MSDOS
  837.       if (w_flag && c_flag && devtype == DEV_FLOP) {
  838.          fprintf(stderr,
  839.                  "\007Data on drive %c: would be destroyed. Continue ? ",
  840.                  ndrive + 'A');
  841.          if (!YES_NO()) done(ERRARG);
  842.       }
  843. #endif
  844.       if (a_flag && !c_flag) {
  845.          scantape(argc, argv, acctime); backtape();
  846.       }
  847.       set_sig();
  848.       putfiles(argc, argv);
  849.       endtape();
  850. #ifdef UNIX
  851.       if (l_flag) {
  852.          register node *this;
  853.  
  854.          for (this=linkhead; this; this=this->next) {
  855.             (void)fprintf(myout, "Tar: missed %d link(s) to \'%s\'\n",
  856.                           this->info.data.count, this->name);
  857.          }
  858.       }
  859. #endif
  860.    } else if (x_flag) {
  861. #ifdef UNIX
  862.       (void)umask(0);
  863. #endif
  864.       scantape(argc, argv, extract);
  865.    } else {/* if (t_flag) */
  866.       allbytes = 0; allfiles = 0;
  867.       scantape(argc, argv, catalog);
  868.       if (v_flag) {
  869.          (void)fprintf(myout,
  870.             "\tTotal %u file(s) for %lu bytes in %lu tape blocks\n",
  871.             allfiles, allbytes, allblock);
  872.       }
  873.    }
  874.    _done(); return 0;
  875. }
  876.