home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1992 / TheOrigSharewareV1.cdr / 25 / arj200.exe / arj / AV.C < prev    next >
C/C++ Source or Header  |  1991-04-10  |  18KB  |  759 lines

  1. /* AV.C, ARJ, R JUNG, 03/13/91
  2. /* Display the contents of an ARJ archive
  3. /* Copyright (c) 1990 by Robert K Jung.  All rights reserved.
  4. /*
  5. /* License policy:
  6. /*   You are free to use this code for any purpose as long as you make
  7. /*   mention of its original author.
  8. /*
  9. /* Description:
  10. /*   This program can be compiled under Turbo C 2.0, Turbo C++ 1.0 and
  11. /*   QuickC 2.5.  Use option -DUNIX for UNIX SysV R3.2.
  12. /*
  13. /* Modification history:
  14. /* Date      Programmer  Description of modification.
  15. /* 03/13/91  R. Jung     Added empty directory support.
  16. /* 03/07/91  R. Jung     Improved find_header() to quickly discern non-ARJ
  17. /*                       archives.
  18. /* 02/28/91  R. Jung     Added display of internal archive date-time.
  19. /*                       Removed special case of zero files.
  20. /* 02/21/91  R. Jung     Fixed UCHAR_MAX define.  Fixed get_date_str() for
  21. /*                       years over 1999.  Modification of initialization
  22. /*                       in list_arc().
  23. /* 01/28/91  R. Jung     Fixed ANSI version of strncopy() by testing *from.
  24. /* 01/26/91  A. Dunkel   Changes for AT&T UNIX.
  25. /* 01/10/91  R. Jung     Fixed description of header.
  26. /* 01/03/91  R. Jung     Fixed description of time stamp.
  27. /* 12/09/90  R. Jung     Increased comment size to 2048.  Added length check
  28. /*                       to comment processing.  Corrected copyright display.
  29. /*                       Added more string length checking.
  30. /* 11/15/90  R. Jung     Initial coding.
  31. /*
  32. */
  33.  
  34. #include <stdio.h>
  35. #include <limits.h>
  36.  
  37. #ifdef UNIX
  38. #ifndef UCHAR_MAX
  39. #define UCHAR_MAX       CHAR_MAX
  40. #endif
  41. #define EXIT_FAILURE    (1)
  42. #define EXIT_SUCCESS    (0)
  43. #include <unistd.h>
  44. #include <varargs.h>
  45. #else
  46. #include <stdlib.h>
  47. #include <stdarg.h>
  48. #endif
  49.  
  50. #include <ctype.h>
  51. #include <string.h>
  52.  
  53. typedef unsigned char  uchar;   /*  8 bits or more */
  54. typedef unsigned int   uint;    /* 16 - 32 bits or more */
  55. typedef unsigned short ushort;  /* 16 bits or more */
  56. typedef unsigned long  ulong;   /* 32 bits or more */
  57.  
  58. typedef ulong UCRC;
  59.  
  60. #define FA_RDONLY    0x01        /* Read only attribute */
  61. #define FA_HIDDEN    0x02        /* Hidden file */
  62. #define FA_SYSTEM    0x04        /* System file */
  63. #define FA_LABEL    0x08        /* Volume label */
  64. #define FA_DIREC    0x10        /* Directory */
  65. #define FA_ARCH        0x20        /* Archive */
  66.  
  67. /* ********************************************************* */
  68. /*
  69. /* Structure of archive block (low order byte first):
  70. /*
  71. /*  2  header id (comment and local file) = 0xEA60 or 60000U
  72. /*  2  basic header size (from 'first_hdr_size' thru 'comment' below)
  73. /*         = first_hdr_size + strlen(filename) + 1 + strlen(comment) + 1
  74. /*         = 0 if end of archive
  75. /*
  76. /*  1  first_hdr_size (size up to 'extra data')
  77. /*  1  archiver version number
  78. /*  1  minimum archiver version to extract
  79. /*  1  host OS     (0 = MSDOS, 1 = PRIMOS, 2 = UNIX, 3 = AMIGA, 4 = MACDOS)
  80. /*  1  arj flags (0x01 = GARBLED_FLAG) indicates passworded file
  81. /*               (0x02 = RESERVED)
  82. /*               (0x04 = VOLUME_FLAG)  indicates continued file to next volume
  83. /*               (0x08 = EXTFILE_FLAG) indicates file starting position field
  84. /*               (0x10 = PATHSYM_FLAG) indicates path translated
  85. /*  1  method    (0 = stored, 1 = compressed most ... 4 compressed fastest)
  86. /*  1  file type (0 = binary, 1 = text, 2 = comment header)
  87. /*  1  reserved
  88. /*  4  date time stamp modified
  89. /*  4  compressed size
  90. /*  4  original size
  91. /*  4  original file's CRC
  92. /*  2  entryname position in filename
  93. /*  2  file access mode
  94. /*  2  host data (currently not used)
  95. /*  ?  extra data
  96. /*     4 bytes for extended file position when used
  97. /*     (this is present when EXTFILE_FLAG is set)
  98. /*
  99. /*  ?  filename (null-terminated)
  100. /*  ?  comment    (null-terminated)
  101. /*
  102. /*  4  basic header CRC
  103. /*
  104. /*  2  1st extended header size (0 if none)
  105. /*  ?  1st extended header (currently not used)
  106. /*  4  1st extended header's CRC
  107. /*  ...
  108. /*  ?  compressed file
  109. /*
  110. /* ********************************************************* */
  111.  
  112. /* ********************************************************* */
  113. /*                                 */
  114. /*     Time stamp format:                     */
  115. /*                                 */
  116. /*    31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16      */
  117. /*     |<---- year-1980 --->|<- month ->|<--- day ---->|     */
  118. /*                                 */
  119. /*    15 14 13 12 11 10  9  8  7  6  5  4  3    2  1  0      */
  120. /*     |<--- hour --->|<---- minute --->|<- second/2 ->|     */
  121. /*                                 */
  122. /* ********************************************************* */
  123.  
  124. #define NULL_CHAR       '\0'
  125. #define PATH_CHAR       '\\'
  126. #define FNAME_MAX       512
  127. #define MAXSFX        25000
  128. #define OS                0
  129. #define HOST_OS_NAMES  { "MS-DOS","PRIMOS","UNIX","AMIGA","MAC-OS",NULL }
  130.  
  131. #ifdef UNIX
  132. #define HEADER_ID      60000
  133. #else
  134. #define HEADER_ID      60000U
  135. #endif
  136. #define FIRST_HDR_SIZE    30
  137. #define COMMENT_MAX     2048
  138. #define HEADERSIZE_MAX   (FIRST_HDR_SIZE + 10 + FNAME_MAX + COMMENT_MAX)
  139. #define BINARY_TYPE        0 /* This must line up with binary/text strings */
  140. #define TEXT_TYPE          1
  141. #define COMMENT_TYPE       2
  142. #define DIR_TYPE           3
  143. #define GARBLE_FLAG     0x01
  144. #define VOLUME_FLAG     0x04
  145. #define EXTFILE_FLAG    0x08
  146. #define PATHSYM_FLAG    0x10
  147.  
  148. #ifdef UNIX
  149. #define CRC_MASK        0xFFFFFFFFL
  150. #else
  151. #define CRC_MASK        0xFFFFFFFFUL
  152. #endif
  153. #define ASCII_MASK      0x7F
  154. #define ARJ_PATH_CHAR   '/'
  155. #ifdef UNIX
  156. #define CRCPOLY         0xEDB88320L
  157. #else
  158. #define CRCPOLY         0xEDB88320UL
  159. #endif
  160.  
  161. #define UPDATE_CRC(crc, c)  \
  162.         crc = crctable[(uchar)crc ^ (uchar)(c)] ^ (crc >> CHAR_BIT)
  163. #define FIX_PARITY(c)   c &= ASCII_MASK
  164. #define get_tstamp(yy, mm, dd, hr, mn, sc) \
  165.     ( (((ulong)(yy - 1980)) << 25) + ((ulong)mm << 21) + ((ulong)dd << 16) + \
  166.     ((ulong)hr << 11) + (mn << 5) + (sc / 2) )
  167.  
  168. #define ts_year(ts)  ((uint)((ts >> 25) & 0x7f) + 1980)
  169. #define ts_month(ts) ((uint)(ts >> 21) & 0x0f)      /* 1..12 means Jan..Dec */
  170. #define ts_day(ts)   ((uint)(ts >> 16) & 0x1f)      /* 1..31 means 1st..31st */
  171. #define ts_hour(ts)  ((uint)(ts >> 11) & 0x1f)
  172. #define ts_min(ts)   ((uint)(ts >> 5) & 0x3f)
  173. #define ts_sec(ts)   ((uint)((ts & 0x1f) * 2))
  174.  
  175. #define get_crc()       get_longword()
  176. #define fget_crc(f)     fget_longword(f)
  177.  
  178. #define setup_get(PTR)  (get_ptr = (PTR))
  179. #define get_byte()      ((uchar)(*get_ptr++ & 0xff))
  180. #define setup_put(PTR)  (put_ptr = (PTR))
  181.  
  182. static UCRC   crc;
  183. static FILE   *arcfile;
  184. static long   compsize;
  185. static long   origsize;
  186. static uchar  header[HEADERSIZE_MAX];
  187. static char   arc_name[FNAME_MAX];
  188. static char   filename[FNAME_MAX];
  189. static char   comment[COMMENT_MAX];
  190. static char   *hdr_filename;
  191. static char   *hdr_comment;
  192. static ushort headersize;
  193. static uchar  first_hdr_size;
  194. static uchar  arj_nbr;
  195. static uchar  arj_x_nbr;
  196. static uchar  host_os;
  197. static uchar  arj_flags;
  198. static short  method;
  199. static short  file_type;
  200. static ushort file_mode;
  201. static ulong  time_stamp;
  202. static ulong  arj_time_stamp;
  203. static short  entry_pos;
  204. static ushort host_data;
  205. static uchar  *get_ptr;
  206. static UCRC   file_crc;
  207. static UCRC   header_crc;
  208. static long   torigsize;
  209. static long   tcompsize;
  210.  
  211. static UCRC   crctable[UCHAR_MAX + 1];
  212.  
  213. #ifdef UNIX
  214. void error(va_alist)
  215. va_dcl
  216. {
  217.     va_list ap;
  218.     char    *fmt, *s;
  219.  
  220.     va_start(ap);
  221.     fmt = (char *) va_arg(ap, char *);
  222.     s = (char *) va_arg(ap, char *);
  223.  
  224.     fputc('\n', stdout);
  225.     fprintf(stdout, fmt, s);
  226.     fputc('\n', stdout);
  227.     va_end(ap);
  228.     exit(EXIT_FAILURE);
  229. }
  230. #else
  231. void
  232. error(char *fmt,...)
  233. {
  234.     va_list args;
  235.  
  236.     va_start(args, fmt);
  237.     fputc('\n', stdout);
  238.     vfprintf(stdout, fmt, args);
  239.     fputc('\n', stdout);
  240.     va_end(args);
  241.     exit(EXIT_FAILURE);
  242. }
  243. #endif
  244.  
  245. #ifdef UNIX
  246. void
  247. make_crctable()
  248. #else
  249. void
  250. make_crctable(void)
  251. #endif
  252. {
  253.     uint i, j;
  254.     UCRC r;
  255.  
  256.     for (i = 0; i <= UCHAR_MAX; i++)
  257.     {
  258.         r = i;
  259.         for (j = 0; j < CHAR_BIT; j++)
  260.         {
  261.             if (r & 1)
  262.                 r = (r >> 1) ^ (CRCPOLY);
  263.             else
  264.                 r >>= 1;
  265.         }
  266.         crctable[i] = r;
  267.     }
  268. }
  269.  
  270. #ifdef UNIX
  271. void
  272. crc_buf(str, len)
  273. char   *str;
  274. uint   len;
  275. #else
  276. void
  277. crc_buf(char *str, uint len)
  278. #endif
  279. {
  280.     while (len--)
  281.         UPDATE_CRC(crc, *str++);
  282. }
  283.  
  284. #ifdef UNIX
  285. void
  286. strparity(p)
  287. uchar   *p;
  288. #else
  289. void
  290. strparity(uchar *p)
  291. #endif
  292. {
  293.     while (*p)
  294.     {
  295.         FIX_PARITY(*p);
  296.         p++;
  297.     }
  298. }
  299.  
  300. #ifdef UNIX
  301. void
  302. get_date_str(str, tstamp)
  303. char   *str;
  304. ulong  tstamp;
  305. #else
  306. void
  307. get_date_str(char *str, ulong tstamp)
  308. #endif
  309. {
  310.     sprintf(str, "%02u-%02u-%02u %02u:%02u:%02u",
  311.            ts_year(tstamp) % 100, ts_month(tstamp), ts_day(tstamp),
  312.            ts_hour(tstamp), ts_min(tstamp), ts_sec(tstamp));
  313. }
  314.  
  315. #ifdef UNIX
  316. int
  317. parse_path(pathname)
  318. char   *pathname;
  319. #else
  320. int
  321. parse_path(char *pathname)
  322. #endif
  323. {
  324.     char *cptr, *ptr, *fptr;
  325.     short pos;
  326.  
  327.     fptr = NULL;
  328.     for (cptr = ":\\"; *cptr; cptr++)
  329.     {
  330.         if ((ptr = strrchr(pathname, *cptr)) != NULL &&
  331.                 (fptr == NULL || ptr > fptr))
  332.             fptr = ptr;
  333.     }
  334.     if (fptr == NULL)
  335.         pos = 0;
  336.     else
  337.         pos = fptr + 1 - pathname;
  338.     return pos;
  339. }
  340.  
  341. #ifdef UNIX
  342. int
  343. decode_path(name)
  344. char    *name;
  345. #else
  346. int
  347. decode_path(char *name)
  348. #endif
  349. {
  350.     for ( ; *name; name++)
  351.     {
  352.         if (*name == ARJ_PATH_CHAR)
  353.             *name = PATH_CHAR;
  354.     }
  355.     return 1;
  356. }
  357.  
  358. #ifdef UNIX
  359. int
  360. fget_byte(f)
  361. FILE    *f;
  362. #else
  363. int
  364. fget_byte(FILE *f)
  365. #endif
  366. {
  367.     int c;
  368.  
  369.     if ((c = fgetc(f)) == EOF)
  370.         error("Can't read file or unexpected end of file");
  371.     return c & 0xFF;
  372. }
  373.  
  374. #ifdef UNIX
  375. uint
  376. fget_word(f)
  377. FILE   *f;
  378. #else
  379. uint
  380. fget_word(FILE *f)
  381. #endif
  382. {
  383.     uint b0, b1;
  384.  
  385.     b0 = fget_byte(f);
  386.     b1 = fget_byte(f);
  387.     return (b1 << 8) + b0;
  388. }
  389.  
  390. #ifdef UNIX
  391. ulong
  392. fget_longword(f)
  393. FILE  *f;
  394. #else
  395. ulong
  396. fget_longword(FILE *f)
  397. #endif
  398. {
  399.     ulong b0, b1, b2, b3;
  400.  
  401.     b0 = fget_byte(f);
  402.     b1 = fget_byte(f);
  403.     b2 = fget_byte(f);
  404.     b3 = fget_byte(f);
  405.     return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  406. }
  407.  
  408. #ifdef UNIX
  409. uint
  410. fread_crc(p, n, f)
  411. uchar   *p;
  412. uint    n;
  413. FILE    *f;
  414. #else
  415. uint
  416. fread_crc(uchar *p, uint n, FILE *f)
  417. #endif
  418. {
  419.     n = fread(p, 1, n, f);
  420.     origsize += n;
  421.     crc_buf((char *)p, n);
  422.     return n;
  423. }
  424.  
  425. #ifdef UNIX
  426. void
  427. get_mode_str(str, mode)
  428. char    *str;
  429. ushort    mode;
  430. #else
  431. void
  432. get_mode_str(char *str, ushort mode)
  433. #endif
  434. {
  435.     strcpy(str, "---W");
  436.     if (mode & FA_ARCH)
  437.         str[0] = 'A';
  438.     if (mode & FA_SYSTEM)
  439.         str[1] = 'S';
  440.     if (mode & FA_HIDDEN)
  441.         str[2] = 'H';
  442.     if (mode & FA_RDONLY)
  443.         str[3] = 'R';
  444. }
  445.  
  446. #ifdef UNIX
  447. static uint
  448. get_word()
  449. #else
  450. static uint
  451. get_word(void)
  452. #endif
  453. {
  454.     uint b0, b1;
  455.  
  456.     b0 = get_byte();
  457.     b1 = get_byte();
  458.     return (b1 << 8) + b0;
  459. }
  460.  
  461. #ifdef UNIX
  462. static ulong
  463. get_longword()
  464. #else
  465. static ulong
  466. get_longword(void)
  467. #endif
  468. {
  469.     ulong b0, b1, b2, b3;
  470.  
  471.     b0 = get_byte();
  472.     b1 = get_byte();
  473.     b2 = get_byte();
  474.     b3 = get_byte();
  475.     return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
  476. }
  477.  
  478. #ifdef UNIX
  479. static void
  480. strncopy(to, from, len)
  481. char    *to, *from;
  482. int    len;
  483. #else
  484. static void
  485. strncopy(char *to, char *from, int len)
  486. #endif
  487. {
  488.     int i;
  489.  
  490.     for (i = 1; i < len && *from; i++)
  491.         *to++ = *from++;
  492.     *to = NULL_CHAR;
  493. }
  494.  
  495. #ifdef UNIX
  496. static long
  497. find_header()
  498. #else
  499. static long
  500. find_header(void)
  501. #endif
  502. {
  503.     long arcpos;
  504.     uchar c;
  505.  
  506.     for (arcpos = 0; arcpos < MAXSFX; arcpos++)
  507.     {
  508.         fseek(arcfile, arcpos, SEEK_SET);
  509.         c = (uchar)fget_byte(arcfile);
  510.         while (arcpos < MAXSFX)
  511.         {
  512.             if (c != (uchar)HEADER_ID)      /* low order byte first */
  513.                 c = (uchar)fget_byte(arcfile);
  514.             else if ((c = (uchar)fget_byte(arcfile)) == ((ushort)HEADER_ID >> 8))
  515.                 break;
  516.             arcpos++;
  517.         }
  518.         if ((headersize = fget_word(arcfile)) > 0 && headersize <= HEADERSIZE_MAX)
  519.         {
  520.             crc = CRC_MASK;
  521.             fread_crc(header, headersize, arcfile);
  522.             if ((crc ^ CRC_MASK) == fget_crc(arcfile))
  523.             {
  524.                 fseek(arcfile, arcpos, SEEK_SET);
  525.                 break;
  526.             }
  527.         }
  528.     }
  529.     return arcpos;
  530. }
  531.  
  532. #ifdef UNIX
  533. static int
  534. read_header()
  535. #else
  536. static int
  537. read_header(void)
  538. #endif
  539. {
  540.     ushort extheadersize;
  541.  
  542.     if (fget_word(arcfile) != HEADER_ID)
  543.         error("Bad header");
  544.  
  545.     if ((headersize = fget_word(arcfile)) == 0)
  546.         return 0;               /* end of archive */
  547.     if (headersize > HEADERSIZE_MAX)
  548.         error("Bad header");
  549.  
  550.     crc = CRC_MASK;
  551.     fread_crc(header, headersize, arcfile);
  552.     header_crc = fget_crc(arcfile);
  553.     if ((crc ^ CRC_MASK) != header_crc)
  554.         error("Header CRC error");
  555.  
  556.     setup_get(header);
  557.     first_hdr_size = get_byte();
  558.     arj_nbr = get_byte();
  559.     arj_x_nbr = get_byte();
  560.     host_os = get_byte();
  561.     arj_flags = get_byte();
  562.     method = get_byte();
  563.     file_type = get_byte();
  564.     (void) get_byte();
  565.     time_stamp = get_longword();
  566.     compsize = get_longword();
  567.     origsize = get_longword();
  568.     file_crc = get_crc();
  569.     entry_pos = get_word();
  570.     file_mode = get_word();
  571.     host_data = get_word();
  572.  
  573.     hdr_filename = (char *)&header[first_hdr_size];
  574.     strncopy(filename, hdr_filename, FNAME_MAX);
  575.     if (host_os != OS)
  576.         strparity((uchar *)filename);
  577.     if ((arj_flags & PATHSYM_FLAG) != 0)
  578.         decode_path(filename);
  579.  
  580.     hdr_comment = (char *)&header[first_hdr_size + strlen(hdr_filename) + 1];
  581.     strncopy(comment, hdr_comment, sizeof(comment));
  582.     if (host_os != OS)
  583.         strparity((uchar *)comment);
  584.  
  585.     while ((extheadersize = fget_word(arcfile)) != 0)
  586.         fseek(arcfile, extheadersize + 2, SEEK_CUR);
  587.  
  588.     return 1;                   /* success */
  589. }
  590.  
  591. #ifdef UNIX
  592. static void
  593. skip()
  594. #else
  595. static void
  596. skip(void)
  597. #endif
  598. {
  599.     fseek(arcfile, compsize, SEEK_CUR);
  600. }
  601.  
  602. #ifdef UNIX
  603. uint
  604. ratio(a, b)         /* [(1000a + [b/2]) / b] */
  605. long   a, b;
  606. #else
  607. uint
  608. ratio(long a, long b)         /* [(1000a + [b/2]) / b] */
  609. #endif
  610. {
  611.    int i;
  612.  
  613.    for (i = 0; i < 3; i++)
  614.        if (a <= LONG_MAX / 10)
  615.            a *= 10;
  616.        else
  617.            b /= 10;
  618.    if ((long) (a + (b >> 1)) < a)
  619.    {
  620.        a >>= 1;
  621.        b >>= 1;
  622.    }
  623.    if (b == 0)
  624.        return 0;
  625.    return (uint) ((a + (b >> 1)) / b);
  626. }
  627.  
  628. #ifdef UNIX
  629. static void
  630. list_start()
  631. #else
  632. static void
  633. list_start(void)
  634. #endif
  635. {
  636.     printf("Filename     ");
  637.     printf("  Original Compressed Ratio DateTime modified CRC-32   Attr TPMGVX\n");
  638.     printf("------------ ---------- ---------- ----- ----------------- -------- ---- ------\n");
  639. }
  640.  
  641. #ifdef UNIX
  642. static void
  643. list_arc(count)
  644. int  count;
  645. #else
  646. static void
  647. list_arc(int count)
  648. #endif
  649. {
  650.     uint r;
  651.     int garble_mode, path_mode, volume_mode, extfil_mode, ftype;
  652.     char date_str[20], fmode_str[10];
  653.     static char mode[4] = { 'B', 'T', '?', 'D' };
  654.     static char pthf[2] = { ' ', '+' };
  655.     static char pwdf[2] = { ' ', 'G' };  /* plain, encrypted */
  656.     static char volf[2] = { ' ', 'V' };
  657.     static char extf[2] = { ' ', 'X' };
  658.  
  659.     if (count == 0)
  660.         list_start();
  661.  
  662.     garble_mode = ((arj_flags & GARBLE_FLAG) != 0);
  663.     path_mode = (entry_pos > 0);
  664.     volume_mode = ((arj_flags & VOLUME_FLAG) != 0);
  665.     extfil_mode = ((arj_flags & EXTFILE_FLAG) != 0);
  666.     r = ratio(compsize, origsize);
  667.     torigsize += origsize;
  668.     tcompsize += compsize;
  669.     ftype = file_type;
  670.     if (ftype != BINARY_TYPE && ftype != TEXT_TYPE && ftype != DIR_TYPE)
  671.         ftype = 3;
  672.     get_date_str(date_str, time_stamp);
  673.     strcpy(fmode_str, "    ");
  674.     if (host_os == OS)
  675.         get_mode_str(fmode_str, file_mode);
  676.     if (strlen(&filename[entry_pos]) > 12)
  677.         printf("%-12s\n             ", &filename[entry_pos]);
  678.     else
  679.         printf("%-12s ", &filename[entry_pos]);
  680.     printf("%10ld %10ld %u.%03u %s %08lX %4s %c%c%u%c\n",
  681.         origsize, compsize, r / 1000, r % 1000, date_str, file_crc,
  682.         fmode_str, mode[ftype], pthf[path_mode], method, pwdf[garble_mode],
  683.         volf[volume_mode], extf[extfil_mode]);
  684. }
  685.  
  686. #ifdef UNIX
  687. void
  688. execute_cmd()
  689. #else
  690. void
  691. execute_cmd(void)
  692. #endif
  693. {
  694.     int count;
  695.     uint r;
  696.     char date_str[22];
  697.  
  698.     torigsize = 0;
  699.     tcompsize = 0;
  700.  
  701.     if ((arcfile = fopen(arc_name, "rb")) == NULL)
  702.         error("Can't open: %s", arc_name);
  703.  
  704.     find_header();
  705.     if (!read_header())
  706.         error("Bad archive header");
  707.     arj_time_stamp = time_stamp;
  708.  
  709.     count = 0;
  710.     while (read_header())
  711.     {
  712.         list_arc(count);
  713.         ++count;
  714.         skip();
  715.     }
  716.  
  717.     get_date_str(date_str, arj_time_stamp);
  718.     printf("------------ ---------- ---------- ----- -----------------\n");
  719.     r = ratio(tcompsize, torigsize);
  720.     printf(" %5d files %10ld %10ld %u.%03u %s\n",
  721.         count, torigsize, tcompsize, r / 1000, r % 1000, date_str);
  722.     fclose(arcfile);
  723. }
  724.  
  725. #ifdef UNIX
  726. int
  727. main(argc, argv)
  728. int  argc;
  729. char *argv[];
  730. #else
  731. int
  732. main(int argc, char *argv[])
  733. #endif
  734. {
  735.     int i, j, lastc;
  736.  
  737.     printf("AV - ARJ file viewer - Rev 1.3, Copyright (c) 1990,91 Robert K Jung\n");
  738.  
  739.     if (argc != 2)
  740.         error("Usage:  AV archive_name[.ARJ]");
  741.  
  742.     make_crctable();
  743.  
  744.     strncopy(arc_name, argv[1], FNAME_MAX);
  745.     i = strlen(arc_name);
  746.     j = parse_path(arc_name);
  747.     lastc = arc_name[i - 1];
  748.     if (lastc == '.')
  749.         arc_name[i - 1] = NULL_CHAR;
  750.     else if (strrchr(&arc_name[j], '.') == NULL)
  751.         strcat(arc_name, ".ARJ");
  752.  
  753.     execute_cmd();
  754.  
  755.     return EXIT_SUCCESS;
  756. }
  757.  
  758. /* end AV.C */
  759.