home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / utils / djtar / djtar.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-01  |  20.0 KB  |  807 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <sys/stat.h>
  8. #include <string.h>
  9. #include <errno.h>
  10. #include <dos.h>
  11. #include <time.h>
  12. #include <io.h>
  13. #include <crt0.h>
  14.  
  15. #define NO_LFN (!_use_lfn("."))
  16.  
  17. #include "oread.h"
  18. #include "zread.h"
  19.  
  20. static void
  21. Fatal(const char *msg)
  22. {
  23.   fprintf(stderr, "Fatal! %s!\n", msg);
  24.   exit(1);
  25. }
  26.  
  27. /*------------------------------------------------------------------------*/
  28.  
  29. typedef struct CE {
  30.   struct CE *next;
  31.   char *from;
  32.   char *to;
  33. } CE;
  34.  
  35. #define HASHSIZE 2048
  36. #define HASHMASK 2047
  37. #define HASHBITS 11
  38. CE *htab[HASHSIZE];
  39.  
  40. static unsigned long
  41. hash(unsigned char *cp)
  42. {
  43.   unsigned long rv = 0;
  44.   while (*cp)
  45.     rv += *cp++;
  46.   while (rv > HASHMASK)
  47.     rv = (rv & HASHMASK) + (rv >> HASHBITS);
  48.   return rv;
  49. }
  50.  
  51. static void
  52. store_entry(char *from, char *to)
  53. {
  54.   unsigned long h = hash(from);
  55.   CE *ce = (CE *)malloc(sizeof(CE));
  56.   if (ce == 0)
  57.     Fatal("Out of memory");
  58.   ce->from = strdup(from);
  59.   ce->to = strdup(to);
  60.   ce->next = htab[h];
  61.   htab[h] = ce;
  62. }
  63.  
  64. static char *
  65. get_entry(char *from)
  66. {
  67.   CE *ce;
  68.   for (ce = htab[hash(from)]; ce; ce=ce->next)
  69.   {
  70.     if (strcmp(ce->from, from) == 0)
  71.       return ce->to;
  72.   }
  73.   return from;
  74. }
  75.  
  76. static void
  77. DoNameChanges(char *fname)
  78. {
  79.   FILE *f = fopen(fname, "r");
  80.   char from[100], to[100];
  81.   char line[250];
  82.   if (f == 0)
  83.   {
  84.     perror(fname);
  85.     exit(1);
  86.   }
  87.   while (1)
  88.   {
  89.     fgets(line, 250, f);
  90.     if (feof(f))
  91.       break;
  92.     to[0] = 0;
  93.     sscanf(line, "%s %s", from, to);
  94.     if (to[0])
  95.       store_entry(from, to);
  96.   }
  97.   fclose(f);
  98. }
  99.  
  100. /*------------------------------------------------------------------------*/
  101.  
  102. FILE *change_file;
  103.  
  104. int v_switch = 0;
  105. int dot_switch = 1;
  106. int text_unix = 0;
  107. int text_dos = 0;
  108. int z_switch = 0;
  109. int to_stdout = 0;
  110. int to_tty = 0;
  111. int ignore_csum = 0;
  112. int list_only = 1;
  113. char skipped_str[] = "[skipped]";
  114.  
  115. char *only_dir;
  116.  
  117. /*------------------------------------------------------------------------*/
  118.  
  119. typedef struct CHANGE {
  120.   struct CHANGE *next;
  121.   char *old;
  122.   char *new;
  123.   int isdir; /* 0=file, 1=dir, 2=skip */
  124. } CHANGE;
  125.  
  126. CHANGE *change_root = 0;
  127.  
  128. static void
  129. dump_changes(void)
  130. {
  131.   CHANGE *c;
  132.   for (c=change_root; c; c=c->next)
  133.     fprintf(change_file, "%s -> %s\n", c->old, c->new);
  134. }
  135.  
  136. static int
  137. change(char *fname, const char *problem, int isadir)
  138. {
  139.   CHANGE *ch;
  140.   char new[200];
  141.   char *pos;
  142.  
  143.   for (ch=change_root; ch; ch = ch->next)
  144.     if ((strncmp(fname, ch->old, strlen(ch->old)) == 0) && ch->isdir)
  145.     {
  146.       if (ch->isdir == 2)
  147.       {
  148.         fprintf(log_out, "  [ skipping %s ]\n", fname);
  149.         return 0;
  150.       }
  151. /*      fprintf(log_out, "  [ changing %s to ", fname); */
  152.       sprintf(new, "%s%s", ch->new, fname+strlen(ch->old));
  153.       strcpy(fname, new);
  154. /*      fprintf(log_out, "%s ]\n", fname); */
  155.       return 1;
  156.     }
  157.   
  158.   fprintf(log_out, "  %s %s\n  new name : ", problem, fname);
  159.   gets(new);
  160.  
  161.   if ((strcmp(new, "") == 0) && (isadir == 2))
  162.     return 0;
  163.   if (isadir) isadir=1;
  164.   ch = (CHANGE *)malloc(sizeof(CHANGE));
  165.   if (ch == 0)
  166.     Fatal("Out of memory");
  167.   ch->next = change_root;
  168.   change_root = ch;
  169.   ch->old = strdup(fname);
  170.   pos = strrchr(fname, '/');
  171.   if (pos && (strchr(new, '/') == 0))
  172.   {
  173.     if (new[0] == 0)
  174.       ch->new = skipped_str;
  175.     else
  176.     {
  177.       ch->new = (char *)malloc(strlen(new) + (pos-fname) + 2);
  178.       if (ch->new == 0)
  179.         Fatal("Out of memory");
  180.       *pos = 0;
  181.       sprintf(ch->new, "%s/%s", fname, new);
  182.     }
  183.   }
  184.   else if (new[0] == 0)
  185.     ch->new = skipped_str;
  186.   else
  187.     ch->new = strdup(new);
  188.   ch->isdir = isadir;
  189.   strcpy(fname, ch->new);
  190.   if (new[0] == 0)
  191.   {
  192.     ch->isdir = 2;
  193.     return 0;
  194.   }
  195.   return 1;
  196. }
  197.  
  198. /*------------------------------------------------------------------------*/
  199.  
  200. static int
  201. isadir(char *n)
  202. {
  203. #ifdef __DJGPP__
  204.   return (access(n, D_OK) == 0);
  205. #else
  206.   union REGS r;
  207.   struct SREGS s;
  208.   r.x.ax = 0x4300;
  209.   r.x.dx = FP_OFF(n);
  210.   s.ds = FP_SEG(n);
  211.   int86x(0x21, &r, &r, &s);
  212.   if (r.x.flags & 1)
  213.     return 0;
  214.   return r.x.cx & 0x10;
  215. #endif
  216. }
  217.  
  218. static void
  219. do_directories(char *n)
  220. {
  221.   char tmp[100];
  222.   char *sl;
  223.   int r;
  224.   sprintf(tmp, n);
  225.   n = tmp;
  226.   for (sl=n; *sl; sl++)
  227.   {
  228.     if ((*sl == '/' || *sl == '\\') && sl[-1] != ':')
  229.     {
  230.       char save = *sl;
  231.       *sl = 0;
  232.       do {
  233.     if (isadir(n))
  234.       break;
  235.     r = mkdir (n, 0777);
  236.     if (r)
  237.       r = change(n, "Unable to create directory", 1);
  238.       } while (r);
  239.       *sl = save;
  240.     }
  241.   }
  242. }
  243.  
  244. /*------------------------------------------------------------------------*/
  245.  
  246. typedef enum { DOS_BINARY, DOS_TEXT, UNIX_TEXT } File_type;
  247.  
  248. /* Guess DOS file type by looking at its contents.  */
  249. static File_type
  250. guess_file_type(char *buf, register size_t buflen)
  251. {
  252.   int crlf_seen = 0;
  253.   /* Use unsigned char, so this will work with foreign characters.  */
  254.   register unsigned char *bp = buf;
  255.  
  256.   while (buflen--)
  257.     {
  258.       /* Binary files have characters with ASCII code less then 32 decimal,
  259.          unless they are one of: BS (for man pages), TAB, LF, FF, CR, ^Z. */
  260.       if (*bp  < ' '  && !(*bp > 7 && *bp <= '\n') &&
  261.           *bp != '\f' &&   *bp != '\r' && *bp != '\32')
  262.         return DOS_BINARY;
  263.  
  264.       /* CR before LF means DOS text file (unless we later see
  265.          binary characters).  */
  266.       else if (*bp == '\r' && bp[1] == '\n')
  267.         crlf_seen++;
  268.  
  269.       bp++;
  270.     }
  271.  
  272.   return crlf_seen ? DOS_TEXT : UNIX_TEXT;
  273. }
  274.  
  275. /*------------------------------------------------------------------------*/
  276.  
  277. typedef struct {
  278.   char name[100];
  279.   char operm[8];
  280.   char ouid[8];
  281.   char ogid[8];
  282.   char osize[12];
  283.   char otime[12];
  284.   char ocsum[8];
  285.   char flags[1];
  286.   char filler[355];
  287. } TARREC;
  288.  
  289. static TARREC header;
  290. static int looking_for_header;
  291. static char *changed_name;
  292. static int first_block = 1;
  293. static File_type file_type = DOS_BINARY;
  294. static long perm, uid, gid, size;
  295. static long posn = 0;
  296. static time_t ftime;
  297. static struct ftime ftimes;
  298. static struct tm *tm;
  299. static int r;
  300. static int skipping;
  301. static char new[2048];  /* got to think about LFN's! */
  302.  
  303. int
  304. tarread(char *buf, long buf_size)
  305. {
  306.   int should_be_written;
  307.  
  308.   while (buf_size)
  309.   {
  310.     char *info;
  311.     int write_errno = 0;
  312.     int dsize = 512, wsize;
  313.  
  314.     if (skipping)
  315.     {
  316.       if (skipping <= buf_size)
  317.       {
  318.         bytes_out += skipping;
  319.         buf      += skipping;
  320.         buf_size -= skipping;
  321.         skipping  = 0;
  322.         looking_for_header = 1;
  323.         if (buf_size < sizeof header)
  324.           return 0;
  325.       }
  326.       else
  327.       {
  328.         bytes_out += buf_size;
  329.         skipping -= buf_size;
  330.         return 0;
  331.       }
  332.     }
  333.  
  334.     if (looking_for_header)
  335.     {
  336.       int head_csum = 0;
  337.       int i;
  338.  
  339.       memcpy(&header, buf, sizeof header);
  340.       if (header.name[0] == 0)
  341.       {
  342.         bytes_out += buf_size;  /* assume everything left should be counted */
  343.         return EOF;
  344.       }
  345.       buf += sizeof header;
  346.       buf_size -= sizeof header;
  347.       bytes_out += sizeof header;
  348.       first_block = 1;
  349.       file_type = DOS_BINARY;
  350.       looking_for_header = 0;
  351.  
  352.       /* ONLY_DIR says to extract only files which are siblings
  353.          of that directory.  */
  354.       should_be_written = list_only == 0;
  355.       if (should_be_written &&
  356.           only_dir && strncmp(only_dir, header.name, strlen(only_dir)))
  357.         should_be_written = 0;
  358.       sscanf(header.operm, " %lo", &perm);
  359.       sscanf(header.ouid, " %lo", &uid);
  360.       sscanf(header.ogid, " %lo", &gid);
  361.       sscanf(header.osize, " %lo", &size);
  362.       sscanf(header.otime, " %o", &ftime);
  363.       sscanf(header.ocsum, " %o", &head_csum);
  364.       for (i = 0; i < sizeof header; i++)
  365.       {
  366.         /* Checksum on header, but with the checksum field blanked out.  */
  367.         int j = (i > 147 && i < 156) ? ' ' : *((unsigned char *)&header + i);
  368.  
  369.         head_csum -= j;
  370.       }
  371.       if (head_csum && !ignore_csum)
  372.       {
  373.         /* Probably corrupted archive.  Bail out.  */
  374.         fprintf(log_out, "--- !!Directory checksum error!! ---\n");
  375.         bytes_out += buf_size;
  376.         return EOF;
  377.       }
  378.  
  379.       changed_name = get_entry(header.name);
  380.       if (should_be_written && !to_stdout && NO_LFN)
  381.       {
  382.         info = strstr(changed_name, ".info-");
  383.         if (info)
  384.         {
  385.           strcpy(new, changed_name);
  386.           info = strstr(new, ".info-");
  387.           strcpy(info+2, info+6);
  388.           fprintf(log_out, "[ changing %s to %s ]\n", changed_name, new);
  389.         }
  390.         else
  391.         {
  392.           char *tgz = strstr(changed_name, ".tar.gz");
  393.           if (tgz)
  394.           {
  395.             strcpy(new, changed_name);
  396.             tgz = strstr(new, ".tar.gz");
  397.             strcpy(tgz, ".tgz");
  398.             strcat(tgz, tgz+7);
  399.             fprintf(log_out, "[ changing %s to %s ]\n", changed_name, new);
  400.           }
  401.           else
  402.           {
  403.             char *plus = strstr(changed_name, "++"), *plus2;
  404.             if (plus)
  405.             {
  406.               strcpy(new, changed_name);
  407.               plus2 = strstr(new, "++");
  408.               strcpy(plus2, "plus");
  409.               strcpy(plus2+4, plus+2);
  410.               fprintf(log_out, "[ changing %s to %s ]\n", changed_name, new);
  411.             }
  412.             else
  413.             {
  414.               strcpy(new, changed_name);
  415.             }
  416.           }
  417.         }
  418.         changed_name = new;
  419.  
  420.         if (dot_switch)
  421.         {
  422.           char *p = changed_name, *name_start = changed_name;
  423.           int state = 0;
  424.           /* 0 = start of item
  425.              1 = before dot (not counting initial dot), but not first char
  426.              2 = after first dot */
  427.  
  428.           /* ".gdbinit" -> "_gdbinit"
  429.              "emacs-19.28.90/ChangeLog" -> "emacs-19.28-90/ChangeLog"
  430.              "./dir/file" -> "./dir/file"
  431.              "sh.lex.c" -> "sh_lex.c"
  432.            */
  433.           while (*p)
  434.           {
  435.             switch (*p++)
  436.             {
  437.               case '/':
  438.               case '\\':
  439.                   state = 0;
  440.                   name_start = p;
  441.                   break;
  442.               case '.':
  443.                   /* Don't waste our limited 8-char real estate in the
  444.                      name part too early, unless the name is really short. */
  445.                   if (state == 1 && p - name_start < 5)
  446.                   {
  447.                     size_t namelen    = strlen(p);
  448.                     char *next_slash  = memchr(p, '/', namelen);
  449.                     char *next_bslash = memchr(p, '\\', namelen);
  450.                     char *next_dot    = memchr(p, '.', namelen);
  451.  
  452.                     /* Find where this name ends.  */
  453.                     if (next_slash == (char *)0)
  454.                     {
  455.                       if (next_bslash)
  456.                         next_slash = next_bslash;
  457.                       else
  458.                         next_slash = p + namelen;
  459.                     }
  460.  
  461.                     else if (next_bslash && next_bslash < next_slash)
  462.                       next_slash = next_bslash;
  463.  
  464.                     /* If name has more dots, convert this one to `_'. */
  465.                     if (next_dot && next_dot < next_slash)
  466.                     {
  467.                       p[-1] = '_';
  468.                       break;      /* don't bump `state' */
  469.                     }
  470.                   }
  471.  
  472.                   /* Leave "./", "../", "/." etc. alone.  */
  473.                   if (state != 0 ||
  474.                       (*p && *p != '/' && *p != '\\' && *p != '.'))
  475.                     p[-1] = "_.-"[state];
  476.                   if (state < 2) state++;
  477.                   break;
  478.               default:
  479.                   if (state == 0) state = 1;
  480.             }
  481.           }
  482.         }
  483.       }
  484.  
  485.       if (v_switch)
  486.         fprintf(log_out, "%08lx %6lo ", posn, perm);
  487.       else
  488.         fprintf(log_out, "%c%c%c%c ",
  489.                S_ISDIR(perm)  ? 'd' : '-',
  490.                perm & S_IRUSR ? 'r' : '-',
  491.                perm & S_IWUSR ? 'w' : '-',
  492.                perm & S_IXUSR ? 'x' : '-');
  493.       fprintf(log_out, "%.20s %9ld %s", ctime(&ftime)+4, size, changed_name);
  494. #if 0
  495.       fprintf(log_out, "(out: %ld)", bytes_out);
  496. #endif
  497.       if (header.flags[1] == 0x32)
  498.         fprintf(log_out, " -> %s", header.filler);
  499.       fprintf(log_out, "%s\n",
  500.               !should_be_written && !list_only ? "\t[ skipped ]" : "");
  501.       posn += 512 + ((size+511) & ~511);
  502. #if 0
  503.       fprintf(log_out, "%6lo %02x %12ld %s\n",perm,header.flags[0],size,changed_name);
  504. #endif
  505.       if (should_be_written == 0)
  506.       {
  507.         skipping = (size+511) & ~511;
  508.         continue;
  509.       }
  510.       else if (changed_name[strlen(changed_name)-1] == '/' && !to_stdout)
  511.       {
  512.         changed_name[strlen(changed_name)-1] = 0;
  513.         do {
  514.           if (strcmp(changed_name, ".") == 0)
  515.             r = 0;        /* current dir always exists */
  516.           else if (strcmp(changed_name, "..") == 0)
  517.             r = !isadir(changed_name); /* root has no parent */
  518.           else
  519.             r = mkdir(changed_name
  520. #ifdef __GO32__
  521.                       ,0
  522. #endif
  523.                       );
  524.           if (r && (errno==EACCES))
  525.           {
  526.             change(changed_name, "Duplicate directory name", 2);
  527.             continue;
  528.           }
  529.           if (r)
  530.             r = change(changed_name, "Unable to create directory", 1);
  531.           else
  532.             fprintf(log_out, "Making directory %s\n", changed_name);
  533.         } while (r);
  534.         looking_for_header = 1;
  535.         continue;
  536.       }
  537.       else
  538.       {
  539. open_file:
  540.         if (!to_stdout)
  541.         {
  542.           do_directories(changed_name);
  543.           r = open(changed_name,
  544.                    O_WRONLY | O_BINARY | O_CREAT | O_EXCL, S_IWRITE | S_IREAD);
  545.           if (r < 0)
  546.             if (change(changed_name, "Cannot exclusively open file", 0))
  547.               goto open_file;
  548.             else
  549.             {
  550.               skipping = (size+511) & ~511;
  551.               continue;
  552.             }
  553.         }
  554.         else
  555.         {
  556.           r = fileno(stdout);
  557.           if (!to_tty)
  558.             setmode(r, O_BINARY);
  559.         }
  560.       }
  561.     }
  562.  
  563.     while (size)
  564.     {
  565.       char tbuf[512];
  566.       char *wbuf = buf;
  567.  
  568.       if (buf_size <= 0)    /* this buffer exhausted */
  569.         return 0;
  570.       if (size < 512)
  571.         dsize = size;
  572.       else if (buf_size < 512)
  573.         dsize = buf_size;
  574.       else
  575.         dsize = 512;
  576.       if (first_block && (text_dos || text_unix || to_tty))
  577.       {
  578.         file_type = guess_file_type(buf, dsize);
  579.         first_block = 0;
  580.         if (file_type == UNIX_TEXT && text_dos)
  581.           setmode(r, O_TEXT);   /* will add CR chars to each line */
  582.       }
  583.       if ((text_unix || to_tty) && file_type == DOS_TEXT)
  584.       {
  585.         /* If they asked for text files to be written Unix style, or
  586.            we are writing to console, remove the CR and ^Z characters
  587.            from DOS text files.
  588.            Note that we don't alter the original uncompressed data so
  589.            as not to screw up the CRC computations.  */
  590.         char *s=buf, *d=tbuf;
  591.         while (s-buf < dsize)
  592.         {
  593.           if (*s != '\r' && *s != 26)
  594.             *d++ = *s;
  595.           s++;
  596.         }
  597.         wsize = d - tbuf;
  598.         wbuf = tbuf;
  599.       }
  600.       else
  601.       {
  602.         wbuf = buf;
  603.         wsize = dsize;
  604.       }
  605.       errno = 0;
  606.       if (write(r, wbuf, wsize) < wsize)
  607.       {
  608.         if (errno == 0)
  609.           errno = ENOSPC;
  610.         fprintf(log_out, "%s: %s\n", changed_name, strerror(errno));
  611.         write_errno = errno;
  612.         break;
  613.       }
  614.       size     -= dsize;
  615.       buf_size -= dsize;
  616.       buf      += dsize;
  617.       bytes_out += dsize;
  618.     }
  619.  
  620.     if (!to_stdout)
  621.     {
  622.       close(r);
  623.       r = open(changed_name, O_RDONLY);
  624.       tm = localtime(&ftime);
  625.       ftimes.ft_tsec = tm->tm_sec / 2;
  626.       ftimes.ft_min = tm->tm_min;
  627.       ftimes.ft_hour = tm->tm_hour;
  628.       ftimes.ft_day = tm->tm_mday;
  629.       ftimes.ft_month = tm->tm_mon+1;
  630.       ftimes.ft_year = tm->tm_year - 80;
  631.       setftime(r, &ftimes);
  632.       close(r);
  633.       chmod(changed_name, perm);
  634.     }
  635.     looking_for_header = 1;
  636.     if (write_errno == ENOSPC)  /* target disk full: quit early */
  637.     {
  638.       bytes_out += buf_size;
  639.       return EOF;
  640.     }
  641.     else if (write_errno)       /* other error: skip this file, try next */
  642.       skipping = (size - dsize + 511) & ~511;
  643.     else    /* skip the slack garbage to the next 512-byte boundary */
  644.       skipping = 512 - dsize;
  645.   }
  646.   return 0;
  647. }
  648.  
  649. /*------------------------------------------------------------------------*/
  650.  
  651. int part_nb;
  652. static const char *zip_description[] = {
  653.   "uncompressed",
  654.   "COMPRESS'ed",
  655.   "PACK'ed",
  656.   "LZH'ed",
  657.   "compressed by unknown method (4)",
  658.   "compressed by unknown method (5)",
  659.   "compressed by unknown method (6)",
  660.   "compressed by unknown method (7)",
  661.   "deflated by "
  662. };
  663.  
  664. static void
  665. tar_gz_read(char *fname)
  666. {
  667.   void *f;
  668.  
  669.   errno = 0;
  670.   f = oread_open(fname);
  671.   if (errno)
  672.   {
  673.     fprintf(log_out, "%s: %s\n", fname, strerror(errno));
  674.     return;
  675.   }
  676.   ifname = fname;
  677.   header_bytes = 0;
  678.   clear_bufs(); /* clear input and output buffers */
  679.   part_nb = 0;  /* FIXME!! handle multi-part gzip's */
  680.   method = get_method(f);
  681.   if (method < 0)
  682.   {
  683.     oread_close(f);
  684.     return;     /* error message already emitted */
  685.   }
  686.   if (v_switch)
  687.     fprintf(log_out, "-- `%s\' is %s%s --\n\n",
  688.             fname,
  689.             method > MAX_METHODS ? "corrupted (?)" : zip_description[method],
  690.             method == DEFLATED ? (pkzip ? "PKZip" : "GZip") : "");
  691.  
  692.   bytes_out = 0;
  693.   looking_for_header = 1;
  694.   posn = 0;
  695.  
  696.   if ((*decompressor)(f) != OK)
  697.   {
  698.     fprintf(log_out,
  699.             "\n%s: corrupted file; I might have written garbage\n", fname);
  700.     fflush(log_out);
  701.   }
  702.   oread_close(f);
  703.   method = -1;
  704. }
  705.  
  706. /*------------------------------------------------------------------------*/
  707.  
  708. FILE * log_out = stdout;
  709. static char djtarx[] = "djtarx.exe";
  710. static char djtart[] = "djtart.exe";
  711.  
  712. int
  713. main(int argc, char **argv)
  714. {
  715.   int i = 1;
  716.   char *tp;
  717.   char *xp;
  718.  
  719.   progname = strlwr(strdup(argv[0]));
  720.  
  721.   if (argc < 2)
  722.   {
  723.     fprintf(stderr, "Usage: %s [-n changeFile] [-p] [-i] [-t|x] [-o dir] [-v] [-u|d|b] [-[!].] tarfile...\n", progname);
  724.     exit(1);
  725.   }
  726.  
  727.   /* DJTARX -> ``djtar -x'', DJTART -> ``djtar -t''.  */
  728.   tp = strstr(progname, djtart);
  729.   xp = strstr(progname, djtarx);
  730.   /* Check both with and without .exe, just in case.  */
  731.   if (tp && (tp[sizeof(djtart)-1] == '\0' || tp[sizeof(djtart)-5] == '\0'))
  732.     list_only = 1;
  733.   else if (xp && (xp[sizeof(djtarx)-1] == '\0' || xp[sizeof(djtarx)-5] == '\0'))
  734.     list_only = 0;
  735.   while ((argc > i) && (argv[i][0] == '-') && argv[i][1])
  736.   {
  737.     switch (argv[i][1])
  738.     {
  739.       case 'n':
  740.         DoNameChanges(argv[i+1]);
  741.         i++;
  742.         break;
  743.       case 'v':
  744.         v_switch = 1;
  745.         break;
  746.       case 'u':
  747.     text_unix = 1;
  748.     text_dos = 0;
  749.     break;
  750.       case 'd':
  751.     text_dos = 1;
  752.     text_unix = 0;
  753.     break;
  754.       case 'b':
  755.     text_dos = 0;
  756.     text_unix = 0;
  757.     break;
  758.       case '.':
  759.     dot_switch = 1;
  760.     break;
  761.       case '!':
  762.     if (argv[i][2] == '.')
  763.       dot_switch = 0;
  764.     break;
  765.       case 'o':
  766.         only_dir = strdup(argv[++i]);
  767.         break;
  768.       case 'p':
  769.         to_stdout = 1;
  770.         to_tty = isatty(fileno(stdout));
  771.         log_out = stderr;
  772.         text_dos = 1;
  773.         break;
  774.       case 't':
  775.         list_only = 1;
  776.         break;
  777.       case 'i':
  778.         ignore_csum = 1;
  779.         break;
  780.       case 'x':
  781.         list_only = 0;
  782.     }
  783.     i++;
  784.   }
  785.  
  786.   for (; i < argc; i++)
  787.     tar_gz_read(argv[i]);
  788.  
  789.   if (to_stdout)
  790.   {
  791.     setmode(fileno(stdout), O_TEXT);
  792.     return 0;
  793.   }
  794.   else
  795.   {
  796.     change_file = fopen("/tarchange.lst", "w");
  797.     if (change_file != (FILE *)0)
  798.     {
  799.       dump_changes();
  800.       fclose(change_file);
  801.       return 0;
  802.     }
  803.     else
  804.       return 1;
  805.   }
  806. }
  807.