home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / star / star.c < prev    next >
C/C++ Source or Header  |  2001-04-30  |  33KB  |  1,327 lines

  1. /* %Z%%M%    %I% %E% Copyright 1985, 88-90, 92-96, 98, 99, 2000-2001 J. Schilling */
  2. #ifndef lint
  3. static    char sccsid[] =
  4.     "%Z%%M%    %I% %E% Copyright 1985, 88-90, 92-96, 98, 99, 2000-2001 J. Schilling";
  5. #endif
  6. /*
  7.  *    Copyright (c) 1985, 88-90, 92-96, 98, 99, 2000-2001 J. Schilling
  8.  */
  9. /*
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2, or (at your option)
  13.  * any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; see the file COPYING.  If not, write to
  22.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  */
  24.  
  25. #include <mconfig.h>
  26. #include <stdio.h>
  27. #include <sys/types.h>
  28. #include <signal.h>
  29. #include <stdxlib.h>
  30. #include <unixstd.h>
  31. #include <strdefs.h>
  32. #include "star.h"
  33. #include "diff.h"
  34. #include <waitdefs.h>
  35. #include <standard.h>
  36. #include <patmatch.h>
  37. #define    __XDEV__    /* Needed to activate _dev_init() */
  38. #include <device.h>
  39. #include <getargs.h>
  40. #include <schily.h>
  41. #include "starsubs.h"
  42. #include "fifo.h"
  43.  
  44. EXPORT    int    main        __PR((int ac, char** av));
  45. LOCAL    void    getdir        __PR((int *acp, char *const **avp,
  46.                         const char **dirp));
  47. LOCAL    char    *dogetwdir    __PR((void));
  48. LOCAL    BOOL    dochdir        __PR((const char *dir, BOOL doexit));
  49. LOCAL    void    openlist    __PR((void));
  50. LOCAL    void    usage        __PR((int ret));
  51. LOCAL    void    xusage        __PR((int ret));
  52. LOCAL    void    dusage        __PR((int ret));
  53. LOCAL    void    husage        __PR((int ret));
  54. LOCAL    void    gargs        __PR((int ac, char *const* av));
  55. LOCAL    long    number        __PR((char* arg, int* retp));
  56. LOCAL    int    getnum        __PR((char* arg, long* valp));
  57. EXPORT    const char *filename    __PR((const char *name));
  58. LOCAL    BOOL    nameprefix    __PR((const char *patp, const char *name));
  59. LOCAL    int    namefound    __PR((const char* name));
  60. EXPORT    BOOL    match        __PR((const char* name));
  61. LOCAL    int    addpattern    __PR((const char* pattern));
  62. LOCAL    int    addarg        __PR((const char* pattern));
  63. LOCAL    void    closepattern    __PR((void));
  64. LOCAL    void    printpattern    __PR((void));
  65. LOCAL    int    add_diffopt    __PR((char* optstr, long* flagp));
  66. LOCAL    int    gethdr        __PR((char* optstr, long* typep));
  67. #ifdef    USED
  68. LOCAL    int    addfile        __PR((char* optstr, long* dummy));
  69. #endif
  70. LOCAL    void    exsig        __PR((int sig));
  71. LOCAL    void    sighup        __PR((int sig));
  72. LOCAL    void    sigintr        __PR((int sig));
  73. LOCAL    void    sigquit        __PR((int sig));
  74. LOCAL    void    getstamp    __PR((void));
  75. EXPORT    void    *__malloc    __PR((unsigned int size));
  76. EXPORT    char    *__savestr    __PR((char *s));
  77. LOCAL    void    docompat    __PR((int *pac, char *const **pav));
  78.  
  79. #if    defined(SIGDEFER) || defined(SVR4)
  80. #define    signal    sigset
  81. #endif
  82.  
  83. #define    QIC_24_TSIZE    122880        /*  61440 kBytes */
  84. #define    QIC_120_TSIZE    256000        /* 128000 kBytes */
  85. #define    QIC_150_TSIZE    307200        /* 153600 kBytes */
  86. #define    QIC_250_TSIZE    512000        /* 256000 kBytes (XXX not verified)*/
  87. #define    TSIZE(s)    ((s)*TBLOCK)
  88.  
  89. #define    SECOND        (1)
  90. #define    MINUTE        (60 * SECOND)
  91. #define    HOUR        (60 * MINUTE)
  92. #define DAY        (24 * HOUR)
  93. #define YEAR        (365 * DAY)
  94. #define LEAPYEAR    (366 * DAY)
  95.  
  96. char    strvers[] = "1.3.1";
  97.  
  98. struct star_stats    xstats;
  99.  
  100. #define    NPAT    100
  101.  
  102. EXPORT    BOOL        havepat = FALSE;
  103. LOCAL    int        npat    = 0;
  104. LOCAL    int        narg    = 0;
  105. LOCAL    int        maxplen    = 0;
  106. LOCAL    int        *aux[NPAT];
  107. LOCAL    int        alt[NPAT];
  108. LOCAL    int        *state;
  109. const    unsigned char    *pat[NPAT];
  110. const        char    *dirs[NPAT];
  111.  
  112. FILE    *tarf;
  113. FILE    *listf;
  114. FILE    *tty;
  115. FILE    *vpr;
  116. char    *tarfile;
  117. char    *listfile;
  118. char    *stampfile;
  119. const    char    *wdir;
  120. const    char    *currdir;
  121. const    char    *dir_flags = NULL;
  122. char    *volhdr;
  123. long    tape_dev;
  124. long    tape_ino;
  125. #ifdef    FIFO
  126. BOOL    use_fifo = TRUE;
  127. #else
  128. BOOL    use_fifo = FALSE;
  129. #endif
  130. BOOL    shmflag    = FALSE;
  131. long    fs;
  132. long    bs;
  133. int    nblocks = 20;
  134. int    uid;
  135. Ulong    curfs;
  136. long    hdrtype    = H_XSTAR;    /* default header format */
  137. long    chdrtype= H_UNDEF;    /* command line hdrtype     */
  138. int    version    = 0;
  139. int    swapflg    = -1;
  140. BOOL    debug    = FALSE;
  141. BOOL    showtime= FALSE;
  142. BOOL    no_stats= FALSE;
  143. BOOL    do_fifostats= FALSE;
  144. BOOL    numeric    = FALSE;
  145. BOOL    verbose = FALSE;
  146. BOOL    tpath    = FALSE;
  147. BOOL    cflag    = FALSE;
  148. BOOL    uflag    = FALSE;
  149. BOOL    rflag    = FALSE;
  150. BOOL    xflag    = FALSE;
  151. BOOL    tflag    = FALSE;
  152. BOOL    nflag    = FALSE;
  153. BOOL    diff_flag = FALSE;
  154. BOOL    zflag    = FALSE;
  155. BOOL    bzflag    = FALSE;
  156. BOOL    multblk    = FALSE;
  157. BOOL    ignoreerr = FALSE;
  158. BOOL    nodir    = FALSE;
  159. BOOL    nomtime    = FALSE;
  160. BOOL    nochown    = FALSE;
  161. BOOL    acctime    = FALSE;
  162. BOOL    dirmode    = FALSE;
  163. BOOL    nolinkerr = FALSE;
  164. BOOL    follow    = FALSE;
  165. BOOL    nodesc    = FALSE;
  166. BOOL    nomount    = FALSE;
  167. BOOL    interactive = FALSE;
  168. BOOL    signedcksum = FALSE;
  169. BOOL    partial    = FALSE;
  170. BOOL    nospec    = FALSE;
  171. int    Fflag    = 0;
  172. BOOL    uncond    = FALSE;
  173. BOOL    xdir    = FALSE;
  174. BOOL    keep_old= FALSE;
  175. BOOL    refresh_old= FALSE;
  176. BOOL    abs_path= FALSE;
  177. BOOL    notpat    = FALSE;
  178. BOOL    force_hole = FALSE;
  179. BOOL    sparse    = FALSE;
  180. BOOL    to_stdout = FALSE;
  181. BOOL    wready = FALSE;
  182. BOOL    force_remove = FALSE;
  183. BOOL    ask_remove = FALSE;
  184. BOOL    remove_first = FALSE;
  185. BOOL    remove_recursive = FALSE;
  186. BOOL    nullout = FALSE;
  187.  
  188. Ulong    maxsize    = 0L;
  189. Ulong    Newer    = 0L;
  190. Ulong    tsize    = 0L;
  191. long    diffopts= 0L;
  192. BOOL    nowarn    = FALSE;
  193. BOOL    Ctime    = FALSE;
  194.  
  195. BOOL    listnew    = FALSE;
  196. BOOL    listnewf= FALSE;
  197. BOOL    hpdev    = FALSE;
  198. BOOL    modebits= FALSE;
  199. BOOL    copylinks= FALSE;
  200.  
  201. BOOL    fcompat    = FALSE;
  202.  
  203. int    intr    = 0;
  204.  
  205. char    *opts = "C*,help,xhelp,version,debug,time,no_statistics,no-statistics,fifostats,numeric,v,tpath,c,u,r,x,t,n,diff,diffopts&,H&,force_hole,force-hole,sparse,to_stdout,to-stdout,wready,force_remove,force-remove,ask_remove,ask-remove,remove_first,remove-first,remove_recursive,remove-recursive,nullout,onull,fifo,no_fifo,no-fifo,shm,fs&,VOLHDR*,list*,file*,f*,T,bs&,blocks#,b#,z,bz,B,pattern&,pat&,i,d,m,nochown,a,atime,p,l,L,D,dodesc,M,I,w,O,signed_checksum,signed-checksum,P,S,F+,U,xdir,k,keep_old_files,keep-old-files,refresh_old_files,refresh-old-files,refresh,/,not,V,maxsize#L,newer*,ctime,tsize#L,qic24,qic120,qic150,qic250,nowarn,newest_file,newest-file,newest,hpdev,modebits,copylinks";
  206.  
  207. EXPORT int
  208. main(ac, av)
  209.     int    ac;
  210.     char    **av;
  211. {
  212.     int        cac  = ac;
  213.     char *const    *cav = av;
  214.  
  215.     save_args(ac, av);
  216.  
  217.     if (ac > 1 && av[1][0] != '-')
  218.         docompat(&cac, &cav);
  219.  
  220.     gargs(cac, cav);
  221.     --cac,cav++;
  222.  
  223.     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
  224.         (void) signal(SIGHUP, sighup);
  225.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  226.         (void) signal(SIGINT, sigintr);
  227.     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
  228.         (void) signal(SIGQUIT, sigquit);
  229.  
  230.     file_raise((FILE *)NULL, FALSE);
  231.  
  232.     initbuf(nblocks);
  233.  
  234.     (void)openremote();        /* This needs super user privilleges */
  235.  
  236.     if (geteuid() != getuid()) {    /* AIX does not like to do this */
  237.                     /* If we are not root        */
  238. #ifdef    HAVE_SETREUID
  239.         if (setreuid(-1, getuid()) < 0)
  240. #else
  241. #ifdef    HAVE_SETEUID
  242.         if (seteuid(getuid()) < 0)
  243. #else
  244.         if (setuid(getuid()) < 0)
  245. #endif
  246. #endif
  247.             comerr("Panic cannot set back efective uid.\n");
  248.     }
  249.  
  250.     opentape();
  251.  
  252.     uid = geteuid();
  253.  
  254.     if (stampfile)
  255.         getstamp();
  256.  
  257.     setprops(chdrtype);    /* Set up properties for archive format */
  258.     dev_init(debug);    /* Init device macro handling */
  259.  
  260. #ifdef    FIFO
  261.     if (use_fifo)
  262.         runfifo();
  263. #endif
  264.  
  265.     if (dir_flags)
  266.         wdir = dogetwdir();
  267.  
  268.     if (xflag || tflag || diff_flag) {
  269.         if (listfile) {
  270.             openlist();
  271.             hash_build(listf, 1000);
  272.             if((currdir = dir_flags) != NULL)
  273.                 dochdir(currdir, TRUE);
  274.         } else {
  275.             for (;;--cac,cav++) {
  276.                 if (dir_flags)
  277.                     getdir(&cac, &cav, &currdir);
  278.                 if (getfiles(&cac, &cav, opts) == 0)
  279.                     break;
  280.                 addarg(cav[0]);
  281.             }
  282.             closepattern();
  283.         }
  284.         if (tflag) {
  285.             list();
  286.         } else {
  287.             /*
  288.              * xflag || diff_flag
  289.              * First change dir to the one or last -C arg
  290.              * in case there is no pattern in list.
  291.              */
  292.             if((currdir = dir_flags) != NULL)
  293.                 dochdir(currdir, TRUE);
  294.             if (xflag)
  295.                 extract(volhdr);
  296.             else
  297.                 diff();
  298.         }
  299.     }
  300.     closepattern();
  301.     if (uflag || rflag) {
  302.         skipall();
  303.         syncbuf();
  304.         backtape();
  305.     }
  306.     if (cflag) {
  307.         put_volhdr(volhdr);
  308.         if (listfile) {
  309.             openlist();
  310.             if((currdir = dir_flags) != NULL)
  311.                 dochdir(currdir, TRUE);
  312.             createlist();
  313.         } else {
  314.             const char    *cdir = NULL;
  315.  
  316.             for (;;--cac,cav++) {
  317.                 if (dir_flags)
  318.                     getdir(&cac, &cav, &currdir);
  319.                 if (currdir && cdir != currdir) {
  320.                     if (!(dochdir(wdir, FALSE) &&
  321.                           dochdir(currdir, FALSE)))
  322.                         break;
  323.                     cdir = currdir;
  324.                 }
  325.  
  326.                 if (getfiles(&cac, &cav, opts) == 0)
  327.                     break;
  328.                 if (intr)
  329.                     break;
  330.                 curfs = -1L;
  331.                 create(cav[0]);
  332.             }
  333.         }
  334.         weof();
  335.         buf_drain();
  336.     }
  337.  
  338.     if (!nolinkerr)
  339.         checklinks();
  340.     if (!use_fifo)
  341.         closetape();
  342.  
  343.     while (wait(0) >= 0)
  344.         ;
  345.     prstats();
  346.     if (checkerrs()) {
  347.         if (!nowarn && !no_stats) {
  348.             errmsgno(EX_BAD,
  349.             "Processed all possible files, despite earlier errors.\n");
  350.         }
  351.         exit(-2);
  352.     }
  353.     exit(0);
  354.     /* NOTREACHED */
  355.     return(0);    /* keep lint happy */
  356. }
  357.  
  358. LOCAL void
  359. getdir(acp, avp, dirp)
  360.     int        *acp;
  361.     char *const    **avp;
  362.     const char    **dirp;
  363. {
  364.     /*
  365.      * Skip all other flags.
  366.      */
  367.     getfiles(acp, avp, &opts[3]);
  368.  
  369.     if (debug) /* temporary */
  370.         errmsgno(EX_BAD, "Flag/File: '%s'.\n", *avp[0]);
  371.  
  372.     if (getargs(acp, avp, "C*", dirp) < 0) {
  373.         /*
  374.          * Skip all other flags.
  375.          */
  376.         if (getfiles(acp, avp, &opts[3]) < 0) {
  377.             errmsgno(EX_BAD, "Badly placed Option: %s.\n", *avp[0]);
  378.             usage(EX_BAD);
  379.         }
  380.     }
  381.     if (debug) /* temporary */
  382.         errmsgno(EX_BAD, "Dir: '%s'.\n", *dirp);
  383. }
  384.  
  385. #include <dirdefs.h>
  386. #include <maxpath.h>
  387. #include <getcwd.h>
  388.  
  389. LOCAL char *
  390. dogetwdir()
  391. {
  392.     char    dir[PATH_MAX+1];
  393.     char    *ndir;
  394.  
  395. /* XXX MAXPATHNAME vs. PATH_MAX ??? */
  396.  
  397.     if (getcwd(dir, PATH_MAX) == NULL)
  398.         comerr("Cannot get working directory\n");
  399.     ndir = malloc(strlen(dir)+1);
  400.     if (ndir == NULL)
  401.         comerr("Cannot alloc space for working dir.\n");
  402.     strcpy(ndir, dir);
  403.     return (ndir);
  404. }
  405.  
  406. LOCAL BOOL
  407. dochdir(dir, doexit)
  408.     const char    *dir;
  409.     BOOL        doexit;
  410. {
  411.     if (debug) /* temporary */
  412.         error("dochdir(%s) = ", dir);
  413.  
  414.     if (chdir(dir) < 0) {
  415.         int    ex = geterrno();
  416.  
  417.         if (debug) /* temporary */
  418.             error("%d\n", ex);
  419.  
  420.         errmsg("Cannot change directory to '%s'.\n", dir);
  421.         if (doexit)
  422.             exit(ex);
  423.         return (FALSE);
  424.     }
  425.     if (debug) /* temporary */
  426.         error("%d\n", 0);
  427.  
  428.     return (TRUE);
  429. }
  430.  
  431. LOCAL void
  432. openlist()
  433. {
  434.     if (streql(listfile, "-")) {
  435.         listf = stdin;
  436.         listfile = "stdin";
  437.     } else if ((listf = fileopen(listfile, "r")) == (FILE *)NULL)
  438.         comerr("Cannot open '%s'.\n", listfile);
  439. }
  440.  
  441. LOCAL void
  442. usage(ret)
  443.     int    ret;
  444. {
  445.     error("Usage:\tstar cmd [options] file1 ... filen\n");
  446.     error("Cmd:\n");
  447.     error("\t-c/-u/-r\tcreate/update/replace named files to tape\n");
  448.     error("\t-x/-t/-n\textract/list/trace named files from tape\n");
  449.     error("\t-diff\t\tdiff archive against file system (see -xhelp)\n");
  450.     error("Options:\n");
  451.     error("\t-help\t\tprint this help\n");
  452.     error("\t-xhelp\t\tprint extended help\n");
  453.     error("\tblocks=#,b=#\tset blocking factor to #x512 Bytes (default 20)\n"); 
  454.     error("\tfile=nm,f=nm\tuse 'nm' as tape instead of stdin/stdout\n");
  455.     error("\t-T\t\tuse $TAPE as tape instead of stdin/stdout\n");
  456. #ifdef    FIFO
  457.     error("\t-fifo/-no-fifo\tuse/don't use a fifo to optimize data flow from/to tape\n");
  458. #if defined(USE_MMAP) && defined(USE_USGSHM)
  459.     error("\t-shm\t\tuse SysV shared memory for fifo\n");
  460. #endif
  461. #endif
  462.     error("\t-v\t\tbe verbose\n");
  463.     error("\t-tpath\t\tuse with -t to list path names only\n");
  464.     error("\tH=header\tgenerate 'header' type archive (see H=help)\n");
  465.     error("\tC=dir\t\tperform a chdir to 'dir' before storing next file\n");
  466.     error("\t-z\t\tpipe input/output through gzip, does not work on tapes\n");
  467.     error("\t-bz\t\tpipe input/output through bzip2, does not work on tapes\n");
  468.     error("\t-B\t\tperform multiple reads (needed on pipes)\n");
  469.     error("\t-i\t\tignore checksum errors\n");
  470.     error("\t-d\t\tdo not store/create directories\n");
  471.     error("\t-m\t\tdo not restore access and modification time\n");
  472.     error("\t-nochown\tdo not restore owner and group\n");
  473.     error("\t-a,-atime\treset access time after storing file\n");
  474.     error("\t-p\t\trestore filemodes of directories\n");
  475.     error("\t-l\t\tdo not print a message if not all links are dumped\n");
  476.     error("\t-L\t\tfollow symbolic links as if they were files\n");
  477.     error("\t-D\t\tdo not descend directories\n");
  478.     error("\t-M\t\tdo not descend mounting points\n");
  479.     error("\t-I,-w\t\tdo interactive creation/extraction/renaming\n");
  480.     error("\t-O\t\tbe compatible to old tar (except for checksum bug)\n");
  481.     error("\t-P\t\tlast record may be partial (useful on cartridge tapes)\n");
  482.     error("\t-S\t\tdo not store/create special files\n");
  483.     error("\t-F,-FF,-FFF,...\tdo not store/create SCCS/RCS, core and object files\n");
  484.     error("\t-U\t\trestore files unconditionally\n");
  485.     exit(ret);
  486.     /* NOTREACHED */
  487. }
  488.  
  489. LOCAL void
  490. xusage(ret)
  491.     int    ret;
  492. {
  493.     error("Usage:\tstar cmd [options] file1 ... filen\n");
  494.     error("Extended options:\n");
  495.     error("\tdiffopts=optlst\tcomma separated list of diffopts (see diffopts=help)\n");
  496.     error("\t-not,-V\t\tuse those files which do not match pattern\n");
  497.     error("\tVOLHDR=name\tuse name to generate a volume header\n");
  498.     error("\t-xdir\t\textract dir even if the current is never\n");
  499.     error("\t-keep-old-files,-k\tkeep existing files\n");
  500.     error("\t-refresh-old-files\trefresh existing files, don't create new files\n");
  501.     error("\t-/\t\tdon't strip leading '/'s from file names\n");
  502.     error("\tlist=name\tread filenames from named file\n");
  503.     error("\t-dodesc\t\tdo descend directories found in a list= file\n");
  504.     error("\tpattern=p,pat=p\tset matching pattern\n");
  505.     error("\tmaxsize=#\tdo not store file if it is bigger than # kBytes\n");
  506.     error("\tnewer=name\tstore only files which are newer than 'name'\n");
  507.     error("\t-ctime\t\tuse ctime for newer= option\n");
  508.     error("\tbs=#\t\tset (output) block size to #\n");
  509. #ifdef    FIFO
  510.     error("\tfs=#\t\tset fifo size to #\n");
  511. #endif
  512.     error("\ttsize=#\t\tset tape volume size to # 512 byte blocks\n");
  513.     error("\t-qic24\t\tset tape volume size to %d kBytes\n",
  514.                         TSIZE(QIC_24_TSIZE)/1024);
  515.     error("\t-qic120\t\tset tape volume size to %d kBytes\n",
  516.                         TSIZE(QIC_120_TSIZE)/1024);
  517.     error("\t-qic150\t\tset tape volume size to %d kBytes\n",
  518.                         TSIZE(QIC_150_TSIZE)/1024);
  519.     error("\t-qic250\t\tset tape volume size to %d kBytes\n",
  520.                         TSIZE(QIC_250_TSIZE)/1024);
  521.     error("\t-nowarn\t\tdo not print warning messages\n");
  522.     error("\t-time\t\tprint timing info\n");
  523.     error("\t-no-statistics\tdo not print statistics\n");
  524. #ifdef    FIFO
  525.     error("\t-fifostats\tprint fifo statistics\n");
  526. #endif
  527.     error("\t-numeric\tdon't use user/group name from tape\n");
  528.     error("\t-newest\t\tfind newest file on tape\n");
  529.     error("\t-newest-file\tfind newest regular file on tape\n");
  530.     error("\t-hpdev\t\tuse HP's non POSIX compliant method to store dev numbers\n");
  531.     error("\t-modebits\tinclude all 16 bits from stat.st_mode, this violates POSIX-1003.1\n");
  532.     error("\t-copylinks\tCopy hard and symlinks rather than linking\n");
  533.     error("\t-signed-checksum\tuse signed chars to calculate checksum\n");
  534.     error("\t-sparse\t\thandle file with holes effectively on store/create\n");
  535.     error("\t-force-hole\ttry to extract all files with holes\n");
  536.     error("\t-to-stdout\textract files to stdout\n");
  537.     error("\t-wready\t\twait for tape drive to become ready\n");
  538.     error("\t-force-remove\tforce to remove non writable files on extraction\n");
  539.     error("\t-ask-remove\task to remove non writable files on extraction\n");
  540.     error("\t-remove-first\tremove files before extraction\n");
  541.     error("\t-remove-recursive\tremove files recursive\n");
  542.     error("\t-onull,-nullout\tsimulate creating an achive to compute the size\n");
  543.     exit(ret);
  544.     /* NOTREACHED */
  545. }
  546.  
  547. LOCAL void
  548. dusage(ret)
  549.     int    ret;
  550. {
  551.     error("Diff options:\n");
  552.     error("\tnot\t\tif this option is present, exclude listed options\n");
  553.     error("\tperm\t\tcompare file permissions\n");
  554.     error("\tmode\t\tcompare file permissions\n");
  555.     error("\ttype\t\tcompare file type\n");
  556.     error("\tnlink\t\tcompare linkcount (not supported)\n");
  557.     error("\tuid\t\tcompare owner of file\n");
  558.     error("\tgid\t\tcompare group of file\n");
  559.     error("\tuname\t\tcompare name of owner of file\n");
  560.     error("\tgname\t\tcompare name of group of file\n");
  561.     error("\tid\t\tcompare owner, group, ownername and groupname of file\n");
  562.     error("\tsize\t\tcompare file size\n");
  563.     error("\tdata\t\tcompare content of file\n");
  564.     error("\tcont\t\tcompare content of file\n");
  565.     error("\trdev\t\tcompare rdev of device node\n");
  566.     error("\thardlink\tcompare target of hardlink\n");
  567.     error("\tsymlink\t\tcompare target of symlink\n");
  568.     error("\tatime\t\tcompare access time of file (only star)\n");
  569.     error("\tmtime\t\tcompare modification time of file\n");
  570.     error("\tctime\t\tcompare creation time of file (only star)\n");
  571.     error("\ttimes\t\tcompare all times of file\n");
  572.     exit(ret);
  573.     /* NOTREACHED */
  574. }
  575.  
  576. LOCAL void
  577. husage(ret)
  578.     int    ret;
  579. {
  580.     error("Header types:\n");
  581.     error("\ttar\t\told tar format\n");
  582.     error("\tstar\t\tstar format\n");
  583.     error("\tgnutar\t\tgnu tar format\n");
  584.     error("\tustar\t\tstandard tar (ieee 1003.1) format\n");
  585.     error("\txstar\t\textended standard tar format\n");
  586.     error("\txustar\t\textended standard tar format without tar signature\n");
  587.     exit(ret);
  588.     /* NOTREACHED */
  589. }
  590.  
  591. LOCAL void
  592. gargs(ac, av)
  593.     int        ac;
  594.     char    *const *av;
  595. {
  596.     BOOL    help    = FALSE;
  597.     BOOL    xhelp    = FALSE;
  598.     BOOL    prvers    = FALSE;
  599.     BOOL    oldtar    = FALSE;
  600.     BOOL    no_fifo    = FALSE;
  601.     BOOL    usetape    = FALSE;
  602.     BOOL    dodesc    = FALSE;
  603.     BOOL    qic24    = FALSE;
  604.     BOOL    qic120    = FALSE;
  605.     BOOL    qic150    = FALSE;
  606.     BOOL    qic250    = FALSE;
  607.     const    char    *p;
  608.  
  609. /*char    *opts = "C*,help,xhelp,version,debug,time,no_statistics,no-statistics,fifostats,numeric,v,tpath,c,u,r,x,t,n,diff,diffopts&,H&,force_hole,force-hole,sparse,to_stdout,to-stdout,wready,force_remove,force-remove,ask_remove,ask-remove,remove_first,remove-first,remove_recursive,remove-recursive,nullout,onull,fifo,no_fifo,no-fifo,shm,fs&,VOLHDR*,list*,file*,f*,T,bs&,blocks#,b#,z,bz,B,pattern&,pat&,i,d,m,nochown,a,atime,p,l,L,D,dodesc,M,I,w,O,signed_checksum,signed-checksum,P,S,F+,U,xdir,k,keep_old_files,keep-old-files,refresh_old_files,refresh-old-files,refresh,/,not,V,maxsize#L,newer*,ctime,tsize#L,qic24,qic120,qic150,qic250,nowarn,newest_file,newest-file,newest,hpdev,modebits,copylinks";*/
  610.  
  611.     p = filename(av[0]);
  612.     if (streql(p, "ustar")) {
  613.         hdrtype = H_USTAR;
  614.     }
  615.     --ac,++av;
  616.     if (getallargs(&ac, &av, opts,
  617.                 &dir_flags,
  618.                 &help, &xhelp, &prvers, &debug,
  619.                 &showtime, &no_stats, &no_stats, &do_fifostats,
  620.                 &numeric, &verbose, &tpath,
  621. #ifndef    lint
  622.                 &cflag,
  623.                 &uflag,
  624.                 &rflag,
  625.                 &xflag,
  626.                 &tflag,
  627.                 &nflag,
  628.                 &diff_flag, add_diffopt, &diffopts,
  629.                 gethdr, &chdrtype,
  630.                 &force_hole, &force_hole, &sparse, &to_stdout, &to_stdout, &wready,
  631.                 &force_remove, &force_remove, &ask_remove, &ask_remove,
  632.                 &remove_first, &remove_first, &remove_recursive, &remove_recursive,
  633.                 &nullout, &nullout,
  634.                 &use_fifo, &no_fifo, &no_fifo, &shmflag,
  635.                 getnum, &fs,
  636.                 &volhdr,
  637.                 &listfile,
  638.                 &tarfile, &tarfile,
  639.                 &usetape,
  640.                 getnum, &bs,
  641.                 &nblocks, &nblocks,
  642.                 &zflag, &bzflag, &multblk,
  643.                 addpattern, NULL,
  644.                 addpattern, NULL,
  645.                 &ignoreerr,
  646.                 &nodir,
  647.                 &nomtime, &nochown,
  648.                 &acctime, &acctime,
  649.                 &dirmode,
  650.                 &nolinkerr,
  651.                 &follow,
  652.                 &nodesc,
  653.                 &dodesc,
  654.                 &nomount,
  655.                 &interactive, &interactive,
  656.                 &oldtar, &signedcksum, &signedcksum,
  657.                 &partial,
  658.                 &nospec, &Fflag,
  659.                 &uncond, &xdir,
  660.                 &keep_old, &keep_old, &keep_old,
  661.                 &refresh_old, &refresh_old, &refresh_old,
  662.                 &abs_path,
  663.                 ¬pat, ¬pat,
  664.                 &maxsize,
  665.                 &stampfile,
  666.                 &Ctime,
  667.                 &tsize,
  668.                 &qic24,
  669.                 &qic120,
  670.                 &qic150,
  671.                 &qic250,
  672.                 &nowarn,
  673. #endif /* lint */
  674.                 &listnewf, &listnewf,
  675.                 &listnew,
  676.                 &hpdev, &modebits, ©links) < 0){
  677.         errmsgno(EX_BAD, "Bad Option: %s.\n", av[0]);
  678.         usage(EX_BAD);
  679.     }
  680.     if (help)
  681.         usage(0);
  682.     if (xhelp)
  683.         xusage(0);
  684.     if (prvers) {
  685.         printf("star %s (%s-%s-%s)\n\n", strvers, HOST_CPU, HOST_VENDOR, HOST_OS);
  686.         printf("Copyright (C) 1985, 88-90, 92-96, 98, 99, 2000-2001 J÷rg Schilling\n");
  687.         printf("This is free software; see the source for copying conditions.  There is NO\n");
  688.         printf("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
  689.         exit(0);
  690.     }
  691.  
  692.     if ((xflag + cflag + uflag + rflag + tflag + nflag + diff_flag) > 1) {
  693.         errmsgno(EX_BAD, "Only one of -x -c -u -r -t or -n.\n");
  694.         usage(EX_BAD);
  695.     }
  696.     if (!(xflag | cflag | uflag | rflag | tflag | nflag | diff_flag)) {
  697.         errmsgno(EX_BAD, "Must specify -x -c -u -r -t -n -diff.\n");
  698.         usage(EX_BAD);
  699.     }
  700.     if (uflag || rflag) {
  701.         cflag = TRUE;
  702.         no_fifo = TRUE;    /* Until we are able to reverse the FIFO */
  703.     }
  704.     if (nullout && !cflag) {
  705.         errmsgno(EX_BAD, "-nullout only make sense in create mode.\n");
  706.         usage(EX_BAD);
  707.     }
  708.     if (no_fifo || nullout)
  709.         use_fifo = FALSE;
  710. #ifndef    FIFO
  711.     if (use_fifo) {
  712.         errmsgno(EX_BAD, "Fifo not configured in.\n");
  713.         usage(EX_BAD);
  714.     }
  715. #endif
  716.     if (oldtar)
  717.         chdrtype = H_OTAR;
  718.     if (chdrtype != H_UNDEF) {
  719.         if (H_TYPE(chdrtype) == H_OTAR)
  720.             oldtar = TRUE;    /* XXX hack */
  721.     }
  722.     if (cflag) {
  723.         if (chdrtype != H_UNDEF)
  724.             hdrtype = chdrtype;
  725.         chdrtype = hdrtype;    /* wegen setprops in main() */
  726.  
  727.         /*
  728.          * hdrtype und chdrtype
  729.          * bei uflag, rflag sowie xflag, tflag, nflag, diff_flag
  730.          * in get_tcb vergleichen !
  731.          */
  732.     }
  733.     if (diff_flag) {
  734.         if (diffopts == 0)
  735.             diffopts = D_DEFLT;
  736.     } else if (diffopts != 0) {
  737.         errmsgno(EX_BAD, "diffopts= only makes sense with -diff\n");
  738.         usage(EX_BAD);
  739.     }
  740.     if (fs == 0L) {
  741.         char    *ep = getenv("STAR_FIFO_SIZE");
  742.  
  743.         if (ep) {
  744.             if (getnum(ep, &fs) != 1)
  745.                 comerr("Bad fifo size environment '%s'.\n",
  746.                                     ep);
  747.         }
  748.     }
  749.     if (bs % TBLOCK) {
  750.         errmsgno(EX_BAD, "Invalid blocksize %ld.\n", bs);
  751.         usage(EX_BAD);
  752.     }
  753.     if (bs)
  754.         nblocks = bs / TBLOCK;
  755.     if (nblocks <= 0) {
  756.         errmsgno(EX_BAD, "Invalid blocksize %d blocks.\n", nblocks);
  757.         usage(EX_BAD);
  758.     }
  759.     bs = nblocks * TBLOCK;
  760.     if (tsize > 0 && tsize < 3) {
  761.         errmsgno(EX_BAD, "Tape size must be at least 3 blocks.\n");
  762.         usage(EX_BAD);
  763.     }
  764.     if (tsize == 0) {
  765.         if (qic24)  tsize = QIC_24_TSIZE;
  766.         if (qic120) tsize = QIC_120_TSIZE;
  767.         if (qic150) tsize = QIC_150_TSIZE;
  768.         if (qic250) tsize = QIC_250_TSIZE;
  769.     }
  770.     if (listfile != NULL && !dodesc)
  771.         nodesc = TRUE;
  772.     if (oldtar)
  773.         nospec = TRUE;
  774.     if (!tarfile) {
  775.         if (usetape) {
  776.             tarfile = getenv("TAPE");
  777.         }
  778.         if (!tarfile)
  779.             tarfile = "-";
  780.     }
  781.     if (interactive || ask_remove || tsize > 0) {
  782. #ifdef    JOS
  783.         tty = stderr;
  784. #else
  785.         if ((tty = fileopen("/dev/tty", "r")) == (FILE *)NULL)
  786.             comerr("Cannot open '/dev/tty'.\n");
  787. #endif
  788.     }
  789.     if (nflag) {
  790.         xflag = TRUE;
  791.         interactive = TRUE;
  792.         verbose = TRUE;
  793.     }
  794.     if (to_stdout) {
  795.         force_hole = FALSE;
  796.     }
  797.     if (remove_recursive)
  798.         comerrno(EX_BAD, "-remove_recursive not implemented\n");
  799.     if (keep_old && refresh_old)
  800.         comerrno(EX_BAD, "Cannot use -keep_old_files and -refresh_old_files together.\n");
  801. }
  802.  
  803. LOCAL long
  804. number(arg, retp)
  805.     register char    *arg;
  806.         int    *retp;
  807. {
  808.     long    val    = 0;
  809.  
  810.     if (*retp != 1)
  811.         return (val);
  812.     if (*arg == '\0')
  813.         *retp = -1;
  814.     else if (*(arg = astol(arg, &val))) {
  815.         if (*arg == 'm' || *arg == 'M') {
  816.             val *= (1024*1024);
  817.             arg++;
  818.         }
  819.         else if (*arg == 'k' || *arg == 'K') {
  820.             val *= 1024;
  821.             arg++;
  822.         }
  823.         else if (*arg == 'b' || *arg == 'B') {
  824.             val *= TBLOCK;
  825.             arg++;
  826.         }
  827.         else if (*arg == 'w' || *arg == 'W') {
  828.             val *= 2;
  829.             arg++;
  830.         }
  831.         if (*arg == '*' || *arg == 'x')
  832.             val *= number(++arg, retp);
  833.         else if (*arg != '\0')
  834.             *retp = -1;
  835.     }
  836.     return (val);
  837. }
  838.  
  839. LOCAL int
  840. getnum(arg, valp)
  841.     char    *arg;
  842.     long    *valp;
  843. {
  844.     int    ret = 1;
  845.  
  846.     *valp = number(arg, &ret);
  847.     return (ret);
  848. }
  849.  
  850. EXPORT const char *
  851. filename(name)
  852.     const char    *name;
  853. {
  854.     char    *p;
  855.  
  856.     if ((p = strrchr(name, '/')) == NULL)
  857.         return (name);
  858.     return (++p);
  859. }
  860.  
  861. LOCAL BOOL
  862. nameprefix(patp, name)
  863.     register const char    *patp;
  864.     register const char    *name;
  865. {
  866.     while (*patp) {
  867.         if (*patp++ != *name++)
  868.             return (FALSE);
  869.     }
  870.     if (*name) {
  871.         return (*name == '/');    /* Directory tree match    */
  872.     }
  873.     return (TRUE);            /* Names are equal    */
  874. }
  875.  
  876. LOCAL int
  877. namefound(name)
  878.     const    char    *name;
  879. {
  880.     register int    i;
  881.  
  882.     for (i=npat; i < narg; i++) {
  883.         if (nameprefix((const char *)pat[i], name)) {
  884.             return (i);
  885.         }
  886.     }
  887.     return (-1);
  888. }
  889.  
  890. EXPORT BOOL
  891. match(name)
  892.     const    char    *name;
  893. {
  894.     register int    i;
  895.         char    *ret = NULL;
  896.  
  897.     if (!cflag && narg > 0) {
  898.         if ((i = namefound(name)) < 0)
  899.             return (FALSE);
  900.         if (npat == 0)
  901.             goto found;
  902.     }
  903.  
  904.     for (i=0; i < npat; i++) {
  905.         ret = (char *)patmatch(pat[i], aux[i],
  906.                     (const unsigned char *)name, 0,
  907.                     strlen(name), alt[i], state);
  908.         if (ret != NULL && *ret == '\0')
  909.             break;
  910.     }
  911.     if (notpat ^ (ret != NULL && *ret == '\0')) {
  912. found:
  913.         if (!(xflag || diff_flag))    /* Chdir only on -x or -diff */
  914.             return (TRUE);
  915.         if (dirs[i] != NULL && currdir != dirs[i]) {
  916.             currdir = dirs[i];
  917.             dochdir(wdir, TRUE);
  918.             dochdir(currdir, TRUE);
  919.         }
  920.         return TRUE;
  921.     }
  922.     return FALSE;
  923. }
  924.  
  925. LOCAL int
  926. addpattern(pattern)
  927.     const char    *pattern;
  928. {
  929.     int    plen;
  930.  
  931. /*    if (debug)*/
  932. /*        error("Add pattern '%s'.\n", pattern);*/
  933.  
  934.     if (npat >= NPAT)
  935.         comerrno(EX_BAD, "Too many patterns (max is %d).\n", NPAT);
  936.     plen = strlen(pattern);
  937.     pat[npat] = (const unsigned char *)pattern;
  938.  
  939.     if (plen > maxplen)
  940.         maxplen = plen;
  941.  
  942.     if ((aux[npat] = malloc(plen*sizeof(int))) == NULL)
  943.         comerr("Cannot alloc space for compiled pattern.\n");
  944.     if ((alt[npat] = patcompile((const unsigned char *)pattern,
  945.                             plen, aux[npat])) == 0)
  946.         comerrno(EX_BAD, "Bad pattern: '%s'.\n", pattern);
  947.     dirs[npat] = currdir;
  948.     npat++;
  949.     return (TRUE);
  950. }
  951.  
  952. LOCAL int
  953. addarg(pattern)
  954.     const char    *pattern;
  955. {
  956.     if (narg == 0)
  957.         narg = npat;
  958.  
  959. /*    if (debug)*/
  960. /*        error("Add arg '%s'.\n", pattern);*/
  961.  
  962.     if (narg >= NPAT)
  963.         comerrno(EX_BAD, "Too many patterns (max is %d).\n", NPAT);
  964.  
  965.     pat[narg] = (const unsigned char *)pattern;
  966.     dirs[narg] = currdir;
  967.     narg++;
  968.     return (TRUE);
  969. }
  970.  
  971. /*
  972.  * Close pattern list: insert useful default directories.
  973.  */
  974. LOCAL void
  975. closepattern()
  976. {
  977.     register int    i;
  978.  
  979.     if (debug) /* temporary */
  980.         printpattern();
  981.  
  982.     for (i=0; i < npat; i++) {
  983.         if (dirs[i] != NULL)
  984.             break;
  985.     }
  986.     while (--i >= 0)
  987.         dirs[i] = wdir;
  988.  
  989.     if (debug) /* temporary */
  990.         printpattern();
  991.  
  992.     if (npat > 0 || narg > 0)
  993.         havepat = TRUE;
  994.  
  995.     if (npat > 0) {
  996.         if ((state = malloc((maxplen+1)*sizeof(int))) == NULL)
  997.             comerr("Cannot alloc space for pattern state.\n");
  998.     }
  999. }
  1000.  
  1001. LOCAL void
  1002. printpattern()
  1003. {
  1004.     register int    i;
  1005.  
  1006.     error("npat: %d narg: %d\n", npat, narg);
  1007.     for (i=0; i < npat; i++) {
  1008.         error("pat %s dir %s\n", pat[i], dirs[i]);
  1009.     }
  1010.     for (i=npat; i < narg; i++) {
  1011.         error("arg %s dir %s\n", pat[i], dirs[i]);
  1012.     }
  1013. }
  1014.  
  1015. LOCAL int
  1016. add_diffopt(optstr, flagp)
  1017.     char    *optstr;
  1018.     long    *flagp;
  1019. {
  1020.     char    *ep;
  1021.     char    *np;
  1022.     int    optlen;
  1023.     long    optflags = 0;
  1024.     BOOL    not = FALSE;
  1025.  
  1026.     while (*optstr) {
  1027.         if ((ep = strchr(optstr, ',')) != NULL) {
  1028.             optlen = ep - optstr;
  1029.             np = &ep[1];
  1030.         } else {
  1031.             optlen = strlen(optstr);
  1032.             np = &optstr[optlen];
  1033.         }
  1034.         if (optstr[0] == '!') {
  1035.             optstr++;
  1036.             optlen--;
  1037.             not = TRUE;
  1038.         }
  1039.         if (strncmp(optstr, "not", optlen) == 0 ||
  1040.                 strncmp(optstr, "!", optlen) == 0) {
  1041.             not = TRUE;
  1042.         } else if (strncmp(optstr, "all", optlen) == 0) {
  1043.             optflags |= D_ALL;
  1044.         } else if (strncmp(optstr, "perm", optlen) == 0) {
  1045.             optflags |= D_PERM;
  1046.         } else if (strncmp(optstr, "mode", optlen) == 0) {
  1047.             optflags |= D_PERM;
  1048.         } else if (strncmp(optstr, "type", optlen) == 0) {
  1049.             optflags |= D_TYPE;
  1050.         } else if (strncmp(optstr, "nlink", optlen) == 0) {
  1051.             optflags |= D_NLINK;
  1052.             errmsgno(EX_BAD, "nlink not supported\n");
  1053.             dusage(EX_BAD);
  1054.         } else if (strncmp(optstr, "uid", optlen) == 0) {
  1055.             optflags |= D_UID;
  1056.         } else if (strncmp(optstr, "gid", optlen) == 0) {
  1057.             optflags |= D_GID;
  1058.         } else if (strncmp(optstr, "uname", optlen) == 0) {
  1059.             optflags |= D_UNAME;
  1060.         } else if (strncmp(optstr, "gname", optlen) == 0) {
  1061.             optflags |= D_GNAME;
  1062.         } else if (strncmp(optstr, "id", optlen) == 0) {
  1063.             optflags |= D_ID;
  1064.         } else if (strncmp(optstr, "size", optlen) == 0) {
  1065.             optflags |= D_SIZE;
  1066.         } else if (strncmp(optstr, "data", optlen) == 0) {
  1067.             optflags |= D_DATA;
  1068.         } else if (strncmp(optstr, "cont", optlen) == 0) {
  1069.             optflags |= D_DATA;
  1070.         } else if (strncmp(optstr, "rdev", optlen) == 0) {
  1071.             optflags |= D_RDEV;
  1072.         } else if (strncmp(optstr, "hardlink", optlen) == 0) {
  1073.             optflags |= D_HLINK;
  1074.         } else if (strncmp(optstr, "symlink", optlen) == 0) {
  1075.             optflags |= D_SLINK;
  1076.         } else if (strncmp(optstr, "sparse", optlen) == 0) {
  1077.             optflags |= D_SPARS;
  1078.         } else if (strncmp(optstr, "atime", optlen) == 0) {
  1079.             optflags |= D_ATIME;
  1080.         } else if (strncmp(optstr, "mtime", optlen) == 0) {
  1081.             optflags |= D_MTIME;
  1082.         } else if (strncmp(optstr, "ctime", optlen) == 0) {
  1083.             optflags |= D_CTIME;
  1084.         } else if (strncmp(optstr, "times", optlen) == 0) {
  1085.             optflags |= D_TIMES;
  1086.         } else if (strncmp(optstr, "help", optlen) == 0) {
  1087.             dusage(0);
  1088.         } else {
  1089.             error("Illegal diffopt.\n");
  1090.             dusage(EX_BAD);
  1091.             return (-1);
  1092.         }
  1093.         optstr = np;
  1094.     }
  1095.     if (not) {
  1096.         *flagp = ~optflags;
  1097.     } else {
  1098.         *flagp = optflags;
  1099.     }
  1100.     return (TRUE);
  1101. }
  1102.  
  1103. LOCAL int
  1104. gethdr(optstr, typep)
  1105.     char    *optstr;
  1106.     long    *typep;
  1107. {
  1108.     BOOL    swapped = FALSE;
  1109.     long    type    = H_UNDEF;
  1110.  
  1111.     if (*optstr == 'S') {
  1112.         swapped = TRUE;
  1113.         optstr++;
  1114.     }
  1115.     if (streql(optstr, "tar")) {
  1116.         type = H_OTAR;
  1117.     } else if (streql(optstr, "star")) {
  1118.         type = H_STAR;
  1119.     } else if (streql(optstr, "gnutar")) {
  1120.         type = H_GNUTAR;
  1121.     } else if (streql(optstr, "ustar")) {
  1122.         type = H_USTAR;
  1123.     } else if (streql(optstr, "xstar")) {
  1124.         type = H_XSTAR;
  1125.     } else if (streql(optstr, "xustar")) {
  1126.         type = H_XUSTAR;
  1127.     } else if (streql(optstr, "help")) {
  1128.         husage(0);
  1129.     } else {
  1130.         error("Illegal header type '%s'.\n", optstr);
  1131.         husage(EX_BAD);
  1132.         return (-1);
  1133.     }
  1134.     if (swapped)
  1135.         *typep = H_SWAPPED(type);
  1136.     else
  1137.         *typep = type;
  1138.     return (TRUE);
  1139. }
  1140.  
  1141. #ifdef    USED
  1142. /*
  1143.  * Add archive file.
  1144.  * May currently not be activated:
  1145.  *    If the option string ends with ",&", the -C option will not work
  1146.  *    anymore.
  1147.  */
  1148. LOCAL int
  1149. addfile(optstr, dummy)
  1150.     char    *optstr;
  1151.     long    *dummy;
  1152. {
  1153.     char    *p;
  1154.  
  1155. /*    error("got_it: %s\n", optstr);*/
  1156.  
  1157.     if (!strchr("01234567", optstr[0]))
  1158.         return (NOTAFILE);/* Tell getargs that this may be a flag */
  1159.  
  1160.     for (p = &optstr[1]; *p; p++) {
  1161.         if (*p != 'l' && *p != 'm' && *p != 'h')
  1162.             return (BADFLAG);
  1163.     }
  1164. /*    error("is_tape: %s\n", optstr);*/
  1165.  
  1166.     comerrno(EX_BAD, "Options [0-7][lmh] currently not supported.\n");
  1167.     /*
  1168.      * The tape device should be determined from the defaults file
  1169.      * in the near future.
  1170.      * Search for /etc/opt/schily/star, /etc/default/star, /etc/default/tar
  1171.      */
  1172.  
  1173.     return (1);        /* Success */
  1174. }
  1175. #endif
  1176.  
  1177. LOCAL void
  1178. exsig(sig)
  1179.     int    sig;
  1180. {
  1181.     signal(sig, SIG_DFL);
  1182.     kill(getpid(), sig);
  1183. }
  1184.  
  1185. /* ARGSUSED */
  1186. LOCAL void
  1187. sighup(sig)
  1188.     int    sig;
  1189. {
  1190.     signal(SIGHUP, sighup);
  1191.     prstats();
  1192.     intr++;
  1193.     if (!cflag)
  1194.         exsig(sig);
  1195. }
  1196.  
  1197. /* ARGSUSED */
  1198. LOCAL void
  1199. sigintr(sig)
  1200.     int    sig;
  1201. {
  1202.     signal(SIGINT, sigintr);
  1203.     prstats();
  1204.     intr++;
  1205.     if (!cflag)
  1206.         exsig(sig);
  1207. }
  1208.  
  1209. /* ARGSUSED */
  1210. LOCAL void
  1211. sigquit(sig)
  1212.     int    sig;
  1213. {
  1214.     signal(SIGQUIT, sigquit);
  1215.     prstats();
  1216. }
  1217.  
  1218. LOCAL void
  1219. getstamp()
  1220. {
  1221.     FINFO    finfo;
  1222.     BOOL    ofollow = follow;
  1223.  
  1224.     follow = TRUE;
  1225.     if (!getinfo(stampfile, &finfo))
  1226.         comerr("Cannot stat '%s'.\n", stampfile);
  1227.     follow = ofollow;
  1228.  
  1229.     Newer = finfo.f_mtime;
  1230. }
  1231.  
  1232. EXPORT void *
  1233. __malloc(size)
  1234.     unsigned int size;
  1235. {
  1236.     void    *ret;
  1237.  
  1238.     ret = malloc(size);
  1239.     if (ret == NULL) {
  1240.         comerr("No memory.\n");
  1241.         /* NOTREACHED */
  1242.     }
  1243.     return (ret);
  1244. }
  1245.  
  1246. EXPORT char *
  1247. __savestr(s)
  1248.     char    *s;
  1249. {
  1250.     char    *ret = __malloc(strlen(s)+1);
  1251.  
  1252.     strcpy(ret, s);
  1253.     return (ret);
  1254. }
  1255.  
  1256. /*
  1257.  * Convert old tar type syntax into the new UNIX option syntax.
  1258.  * Allow only a limited subset of the single character options to avoid
  1259.  * collisions between interpretation of options in different
  1260.  * tar implementations. The old syntax has a risk to damage files
  1261.  * which is avoided with the 'fcompat' flag (see opentape()).
  1262.  *
  1263.  * Problems:
  1264.  *    The 'e' and 'X' option are currently not implemented.
  1265.  *    The 'h' option can only be implemented if the -help 
  1266.  *    shortcut in star is removed.
  1267.  *    There is a collision between the BSD -I (include) and
  1268.  *    star's -I (interactive) which may be solved by using -w instead.
  1269.  */
  1270. LOCAL void
  1271. docompat(pac, pav)
  1272.     int    *pac;
  1273.     char    *const **pav;
  1274. {
  1275.     int    ac    = *pac;
  1276.     char    *const *av    = *pav;
  1277.     int    nac;
  1278.     char    **nav;
  1279.     char    nopt[3];
  1280.     char    *copt = "crtuxbfXBFTLdeiklmnopvwz01234567";
  1281.     char    *p;
  1282.     char    c;
  1283.     char    *const *oa;
  1284.     char    **na;
  1285.  
  1286.     if (strchr(av[1], '=') != NULL)        /* Do not try to convert bs= */
  1287.         return;
  1288.  
  1289.     nac = ac + strlen(av[1]);
  1290.     nav = __malloc(nac-- * sizeof(char *));    /* keep space for NULL ptr */
  1291.     oa = av;
  1292.     na = nav;
  1293.     *na++ = *oa++;
  1294.     oa++;                    /* Skip over av[1] */
  1295.  
  1296.     nopt[0] = '-';
  1297.     nopt[2] = '\0';
  1298.  
  1299.     for (p=av[1]; (c = *p) != '\0'; p++) {
  1300.         if (strchr(copt, c) == NULL) {
  1301.             errmsgno(EX_BAD, "Illegal option '%c' for compat mode.\n", c);
  1302.             usage(EX_BAD);
  1303.         }
  1304.         nopt[1] = c;
  1305.         *na++ = __savestr(nopt);
  1306.         if (c == 'f' || c == 'b' || c == 'X') {
  1307.             *na++ = *oa++;
  1308.             /*
  1309.              * The old syntax has a high risk of corrupting
  1310.              * files if the user disorders the args.
  1311.              */
  1312.             if (c == 'f')
  1313.                 fcompat = TRUE;
  1314.         }
  1315.     }
  1316.  
  1317.     /*
  1318.      * Now copy over the rest...
  1319.      */
  1320.     while ((av + ac) > oa)
  1321.         *na++ = *oa++;
  1322.     *na = NULL;
  1323.  
  1324.     *pac = nac;
  1325.     *pav = nav;
  1326. }
  1327.