home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 551.lha / Lister_v1.01 / lister.c < prev    next >
C/C++ Source or Header  |  1991-09-08  |  19KB  |  816 lines

  1. /*
  2.   Lister v1.01 Source Code
  3.   Copyright 1991 Baf! Technologies
  4.   Started : 5/24/91 at 11:24:10 pm
  5.  
  6.   Written by:  Geoffrey Faivre-Malloy   & Kerry Cianos
  7.                jjm7609csci@apsu.bitnet    ktc0440csci@apsu.bitnet
  8.                Bix - mduck
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <string.h>
  13. #include <errno.h>
  14. #include <time.h>
  15.  
  16. /* our defines */
  17. #define FALSE 0
  18. #define TRUE 1
  19. #define OFF 0
  20. #define ON 1
  21.  
  22. /* declare a data type */
  23. #define ULONG unsigned long
  24. #define PTR unsigned long int
  25. #define UCHAR unsigned char
  26.  
  27. /* file type defines */
  28. #define ARC    12
  29. #define LHARC    13
  30. #define ZIP    14
  31. #define ZOO    15
  32. #define SIT    16
  33. #define CPIO    17
  34. #define TAR    18
  35. #define ADD_EXT 19
  36.  
  37. /* error code defines */
  38. #define FILE_ERROR 101
  39. #define MEMORY_ERROR 102
  40. #define NOT_FOUND 103
  41. #define WRONG_ARCHIVE 104
  42.  
  43. /* archive types */
  44. struct { char arc,
  45.           lharc,
  46.           zip,
  47.           zoo,
  48.           sit,
  49.           cpio,
  50.           tar;
  51.     } types;
  52.  
  53. /* Structure used for Tar Lister */
  54. struct {
  55.   char name[100],
  56.        mode[8],
  57.        uid[8],
  58.        gid[8],
  59.        size[12],
  60.        mtime[12],
  61.        chksum[8],
  62.        linkflag[1],
  63.        linkname[100],
  64.        rdev[6];
  65.    } tar;
  66.  
  67. /* the months of the year */
  68. char *months[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  69.              "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
  70.  
  71. /* totals variables for the archive stats */
  72. long int tcomp, tuncomp;
  73. float tcf;
  74. int tfiles;
  75.  
  76. /* global vars */
  77. struct EX_STRUCT { char infile[25], time_str[25], ext[4],
  78.             line[132], filename[30];
  79.            int file_num, error, add, line_num, type, length, line_len;
  80.            FILE *fp_in;
  81.          } ex;
  82.  
  83. /* Buffer used for Listing Routines, 132 + '\n' */
  84. unsigned char b[133];
  85.  
  86. /* Functions */
  87.  
  88. void usage(), msdog(), init_list(), print_list(), move(), end_stats(),
  89.      error(), check_error();
  90. int list_arc(), list_zip(), list_sit(), list_cpio(), convert8();
  91. ULONG get_long(int);
  92.  
  93. /* main module */
  94.  
  95. main (argc, argv)
  96. int argc;
  97. char *argv[];
  98. {
  99.   int i;
  100.  
  101.   /* check to make sure we have the minimum number of arguments */
  102.   if (argc == 2) {
  103.     strcpy(ex.infile, argv[1]);
  104.  
  105.     /* auto-detecter */
  106.     i = detect();
  107.  
  108.     if (i == ADD_EXT) ex.add = TRUE;
  109.      else ex.add = FALSE;
  110.  
  111.     if ((i == TRUE) || (i == ADD_EXT)) {
  112.       if (types.arc)   check_error (list_arc());
  113.       if (types.cpio)  check_error (list_cpio());
  114.       if (types.lharc) check_error (list_lharc());
  115.       if (types.sit)   check_error (list_sit());
  116.       if (types.tar)   check_error (list_tar());
  117.       if (types.zip)   check_error (list_zip());
  118.       if (types.zoo)   check_error (list_zoo());
  119.       }
  120.  
  121.      /* manual search */
  122.      else {
  123.       i = list_arc();
  124.       if (! i) i = list_cpio();
  125.       if (! i) i = list_lharc();
  126.       if (! i) i = list_sit();
  127.       if (! i) i = list_tar();
  128.       if (! i) i = list_zip();
  129.       if (! i) i = list_zoo();
  130.       }
  131.  
  132.     check_error(i);
  133.     }
  134.    else usage(0);
  135.   return (0);
  136. }
  137.  
  138. /* prints an error messages, checks for Quiet mode */
  139. void error(str)
  140. char *str;
  141. {
  142.   printf("\nError : %s\n\n", str);
  143.   exit(0);
  144. }
  145.  
  146. void check_error(num)
  147. int num;
  148. {
  149.   switch (num)
  150.    {
  151.      case FILE_ERROR    : error("File or Disk Error.");
  152.      case FALSE         : error("Archive file not found.");
  153.      case WRONG_ARCHIVE : error("Archive header is invalid.");
  154.    }
  155. }
  156.  
  157. /*  print header for listing archives and reset stat values */
  158. void init_list()
  159. {
  160.   printf("\n");
  161.   switch (ex.type) {
  162.     case ARC    : printf("Arc");
  163.           break;
  164.     case CPIO    : printf("Cpio");
  165.           break;
  166.     case LHARC    : printf("Lharc");
  167.           break;
  168.     case SIT    : printf("Sit");
  169.           break;
  170.     case ZIP    : printf("Zip");
  171.           break;
  172.     case TAR    : printf("Tar");
  173.                   break;
  174.     case ZOO    : printf("Zoo");
  175.           break;
  176.     }
  177.   printf(" Archive: %s\n",ex.infile);
  178.   printf("\n---------------------------------------------------------------------------\n");
  179.   printf("  Original  Compress  Ratio       Date      Time    Filename\n");
  180.   printf("---------------------------------------------------------------------------\n");
  181.   tcomp = tuncomp = tfiles = 0;
  182. }
  183.  
  184. /*  print entry in archive listing and update stats */
  185. void print_list(n, u, c)
  186. char *n;
  187. long int u, c;
  188. {
  189.   float f;
  190.  
  191.   if ( (c==0) || (u==0) ) f = 0;
  192.    else f = (float) c / (float) u * 100.0;
  193.   tfiles ++;
  194.   tcomp += c;
  195.   tuncomp += u;
  196.   printf("  %-10ld%-10ld%-5.1f%%  %-22s%s\n", u, c, f, ex.time_str, n);
  197. }
  198.  
  199. /* prints the total statistics on the archive */
  200. void end_stats()
  201. {
  202.   float cf;
  203.   char temp[6];
  204.  
  205.   if (tfiles == 1) strcpy(temp, "file");
  206.    else strcpy(temp, "files");
  207.   if (tuncomp == 0) cf = 0;
  208.    else cf = (float) tcomp / (float) tuncomp * 100.0;
  209.   printf("---------------------------------------------------------------------------\n");
  210.   printf("  %-10ld%-10ld%-5.1f%%         %d %s processed.\n\n", tuncomp, tcomp, cf, tfiles, temp);
  211. }
  212.  
  213. /*  Converts from MS-DOG time and date to english format
  214.     and places the string into the global ex.time_str */
  215. void msdog(time, date)
  216. int time, date;
  217. {
  218.   int i, yr, mo, day, hr, min, sec;
  219.   char day_str[3];
  220.  
  221.   ex.error = FALSE;
  222.   yr = (date >> 9 & 0x7f) + 1980;
  223.   mo = date >> 5 & 0x0f;
  224.   day = date & 0x1f;
  225.   hr = time >> 11 & 0x1f;
  226.   min = time >> 5 & 0x3f;
  227.   sec = (time & 0x1f) * 2;
  228.  
  229.   if ( (mo < 1) || (mo > 12) || (day < 1) || (day > 31) || (hr < 0) ||
  230.     (hr > 23) || (min < 0) || (min > 59) || (sec < 0) || (sec > 59) ) {
  231.     error("Corrupted archive!");
  232.     ex.error = TRUE;
  233.     return;
  234.     }
  235.  
  236.   sprintf(ex.time_str, "%2d-%s-%d %02d:%02d:%02d", day, months[mo-1], yr, hr,
  237.     min, sec);
  238. }
  239.  
  240. /* prints out the usage message and exits with the status number passed */
  241. void usage(number)
  242. int number;
  243. {
  244.   printf("\nLister v1.01  -  Copyright 1991 Baf! Technologies\n\n");
  245.   printf("Usage : Lister <filename>\n");
  246.   printf("\n");
  247.   exit(number);
  248. }
  249.  
  250. /* lists an Arc file's contents */
  251. int list_arc()
  252. {
  253.   int ct, time, date, done;
  254.   ULONG uncomp, comp;
  255.  
  256.   get_filename(".arc");
  257.   if ( (ex.fp_in = fopen(ex.filename, "rb")) == NULL) return(FILE_ERROR);
  258.   ct = read_buf(29);
  259.  
  260.   /* check ARC signature */
  261.   if ( (b[0] != 0x1A) || (ct != 1)) {
  262.     fclose(ex.fp_in);
  263.     return(FALSE);
  264.     }
  265.  
  266.   /* start listing */
  267.   ex.type = ARC;
  268.   init_list();
  269.  
  270.   /* parse each header block until ARC signature check fails or EOF */
  271.   done= FALSE;
  272.   while ( ! done) {
  273.     comp = get_long(18);
  274.     uncomp = get_long(28);
  275.     date = b[20] * 256 + b[19];
  276.     time = b[22] * 256 + b[21];
  277.     msdog(time,date);
  278.     if (ex.error) break;
  279.     print_list(b+2, uncomp, comp);
  280.  
  281.     fseek (ex.fp_in,comp,SEEK_CUR);
  282.  
  283.     /* get next block and check */
  284.     ct = fread(b, 29, 1, ex.fp_in);
  285.     if ( (b[0] != 0x1A) || (ct != 1) || (b[1] == 0)) done = TRUE;
  286.     }
  287.  
  288.   fclose(ex.fp_in);
  289.   end_stats();
  290.   return(TRUE);
  291. }
  292.  
  293. /* lists a CPIO file's contents */
  294. int list_cpio()
  295. {
  296.   int ct, done, i;
  297.   ULONG uncomp, comp = 0, time;
  298.   struct tm *tm;
  299.  
  300.   get_filename(".cpio");
  301.   in_open();
  302.   ct = fread(b, 76, 1, ex.fp_in);
  303.  
  304.   /* check CPIO signature */
  305.   if ( (b[0] != 0x30) || (b[1] != 0x37) ||
  306.        (b[2] != 0x30) || (b[3] != 0x37) ||
  307.        (b[4] != 0x30) || (b[5] != 0x37) || (ct != 1)) {
  308.     fclose(ex.fp_in);
  309.     return(FALSE);
  310.     }
  311.  
  312.   /* start listing */
  313.   ex.type = CPIO;
  314.   init_list();
  315.  
  316.   /* parse each header block until CPIO signature check fails or EOF */
  317.   done = FALSE;
  318.   while ( ! done) {
  319.     comp = uncomp = convert8(b+70);
  320.  
  321.     /* get Un*x stored time */
  322.     sscanf (b+48,"%11o",&time);
  323.     tm = localtime (&time);
  324.     sprintf (ex.time_str,"%02d-%s-19%d %02d:%02d:%02d",
  325.       tm->tm_mday,months[tm->tm_mon],tm->tm_year,tm->tm_hour,
  326.       tm->tm_min,tm->tm_sec);
  327.  
  328.     /* get filename */
  329.     i = convert8(b+59);
  330.     ct = fread(b, (long) i, 1, ex.fp_in);
  331.     print_list(b, uncomp, comp);
  332.  
  333.     fseek(ex.fp_in,uncomp,SEEK_CUR);
  334.  
  335.     /* get next block and check */
  336.     ct = fread(b, 76, 1, ex.fp_in);
  337.     i = convert8(b+70);
  338.     if ( (b[0] != 0x30) || (b[1] != 0x37) ||
  339.        (b[2] != 0x30) || (b[3] != 0x37) ||
  340.        (b[4] != 0x30) || (b[5] != 0x37) || (ct != 1) || (i == 0) )
  341.      done = TRUE;
  342.     }
  343.  
  344.   fclose(ex.fp_in);
  345.   end_stats();
  346.   return(TRUE);
  347. }
  348.  
  349. /* lists an StuffIt file's contents */
  350. int list_sit()
  351. {
  352.   int ct, time, date, done, counter, max;
  353.   ULONG uncomp, comp, i;
  354.  
  355.   get_filename(".sit");
  356.   in_open();
  357.   ct = fread(b, 22, 1, ex.fp_in);
  358.  
  359.   /* check SIT signature and fread status */
  360.   if ( (b[0] != 0x53) || (b[1] != 0x49) || (b[2] != 0x54)
  361.     || (b[3] != 0x21) || (ct != 1)) {
  362.  
  363.     /* skip that part and read next section in case of MacBinary header */
  364.     ct = fread(b, 106, 1, ex.fp_in);
  365.     ct = fread(b, 22, 1, ex.fp_in);
  366.     if ( (b[0] != 0x53) || (b[1] != 0x49) || (b[2] != 0x54)
  367.       || (b[3] != 0x21) || (ct != 1)) {
  368.       fclose(ex.fp_in);
  369.       return (FALSE);
  370.       }
  371.     }
  372.  
  373.   /* read first header */
  374.   max = b[4] * 256 + b[5];
  375.   ct = fread(b, 122, 1, ex.fp_in);
  376.   counter = 1;
  377.  
  378.   /* start listing */
  379.   ex.type = SIT;
  380.   init_list();
  381.  
  382.   /* parse each header block until done */
  383.   done= FALSE;
  384.   while ( counter <= max) {
  385.     /* Get Long not used here due to different storage format of long int */
  386.     comp = b[92] * 16777216 + b[93] * 65536 + b[94] * 256 +                   
  387.     b[95] + b[96] * 167216 + b[97] * 6536 + b[98] * 256 + b[9];                                                      
  388.  
  389.     uncomp = b[84] * 167216 + b[85] * 6536 + b[86] * 256 +          
  390.     b[87] + b[8] * 167216 + b[89] * 6536 + b[90] * 256 + b[91];
  391.  
  392.     /* print and get next record */
  393.     b[b[2] + 3] = '\0';
  394.     print_list(b + 3, uncomp, comp);
  395.     fseek(ex.fp_in, (comp-10), SEEK_CUR);
  396.     ct = fread(b, 122, 1, ex.fp_in);
  397.     if ( (ex.error) || (ct < 1) ) break;
  398.     counter ++;
  399.     }
  400.  
  401.   fclose(ex.fp_in);
  402.   end_stats();
  403.   return(TRUE);
  404. }
  405.  
  406. /* lists a Zip file's contents */
  407. int list_zip()
  408. {
  409.   int ct, time, date, done, extra;
  410.   long int uncomp, comp, i;
  411.  
  412.   get_filename(".zip");
  413.   in_open();
  414.   ct = fread(b, 30, 1, ex.fp_in);
  415.  
  416.   /* check ZIP signature and fread status */
  417.   if ( (b[0] != 0x50) || (b[1] != 0x4b) || (b[2] != 0x03)
  418.     || (b[3] != 0x04) || (ct != 1)) {
  419.     fclose(ex.fp_in);
  420.     return (FALSE);
  421.     }
  422.  
  423.   /* start listing */
  424.   ex.type = ZIP;
  425.   init_list();
  426.  
  427.   /* parse each header block until done */
  428.   done= FALSE;
  429.   while ( ! done) {
  430.     comp = get_long(21);
  431.     uncomp = get_long(25);
  432.     date = b[13] * 256 + b[12];
  433.     time = b[11] * 256 + b[10];
  434.     msdog(time,date);
  435.     if (ex.error) break;
  436.     i = (long) ( b[26] + b[27] * 256);
  437.     extra = (long) ( b[28] + b[29] * 256);
  438.  
  439.     /* get variable length filename */
  440.     fread(b, i, 1, ex.fp_in);
  441.     b[(int) i] = '\0';
  442.     print_list(b, uncomp, comp);
  443.  
  444.     /* get variable length 'extra' bytes */
  445.     if (extra != 0) fread(b, extra, 1, ex.fp_in);
  446.     fseek(ex.fp_in, comp, SEEK_CUR);
  447.     ct = fread(b, 30, 1, ex.fp_in);
  448.  
  449.     /* check ZIP signature */
  450.     if ( (b[0] != 0x50) || (b[1] != 0x4b) || (b[2] != 0x03)
  451.       || (b[3] != 0x04) || (ct != 1)) done = TRUE;
  452.     }
  453.  
  454.   fclose(ex.fp_in);
  455.   end_stats();
  456.   return(TRUE);
  457. }
  458.  
  459. /* routine to convert octal stored ascii into numerical form */
  460. int convert8(str)
  461. char *str;
  462. {
  463.   int x = 0;
  464.  
  465.   x = (str[5] - 48) + (str[4] - 48) * 8 + (str[3] - 48) * 64 +
  466.       (str[2] - 48) * 512 + (str[1] - 48) * 4096 + (str[0] - 48) * 32768;
  467.   return (x);
  468. }
  469.  
  470. /* Open filename with proper extension.  will use 01 for 1 and 1 for 1 */
  471. /* returns TRUE if opened ok.  FALSE otherwise.                */
  472.  
  473. int detect()
  474. {
  475.   char temp[40];
  476.   int i;
  477.  
  478.   /* Convert those four characters to lower case for comparisons */
  479.   for (i=0; i < strlen(ex.infile); ex.infile[i] = tolower(ex.infile[i]), i++);
  480.   strcpy (temp,ex.infile);
  481.  
  482.   /* Check the file extension - return appropriate value if filetype */
  483.   /* Recognized.                             */
  484.   if (strstr (temp,".arc") != 0)
  485.     {
  486.       types.arc = TRUE;
  487.       return (TRUE);
  488.     }
  489.   if (strstr (temp,".lzh") != 0)
  490.     {
  491.       types.lharc = TRUE;
  492.       return (TRUE);
  493.     }
  494.   if (strstr (temp,".zip") != 0)
  495.     {
  496.       types.zip = TRUE;
  497.       return (TRUE);
  498.     }
  499.   if (strstr (temp,".zoo") != 0)
  500.     {
  501.       types.zoo = TRUE;
  502.       return (TRUE);
  503.     }
  504.   if (strstr (temp,".sit") != 0)
  505.     {
  506.       types.sit = TRUE;
  507.       return (TRUE);
  508.     }
  509.   if (strstr (temp,".cpio") != 0)
  510.     {
  511.       types.cpio = TRUE;
  512.       return (TRUE);
  513.     }
  514.   if (strstr (temp,".tar") != 0)
  515.     {
  516.       types.tar = TRUE;
  517.       return (TRUE);
  518.     }
  519.  
  520.   /* See if file with .ARC extension can be opened.             */
  521.   /* ARC_TYPE if it can be opened.                     */
  522.   sprintf(temp,"%s.arc",ex.infile);
  523.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  524.     {
  525.       fclose (ex.fp_in);
  526.       types.arc = TRUE;
  527.     }
  528.  
  529.   /* See if file with .CPIO extension can be opened.              */
  530.   /* CPIO_TYPE if it can be opened.                      */
  531.   sprintf(temp,"%s.cpio",ex.infile);
  532.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  533.     {
  534.       fclose (ex.fp_in);
  535.       types.cpio = TRUE;
  536.     }
  537.  
  538.   /* See if file with .LZH extension can be opened.             */
  539.   /* LZH_TYPE if it can be opened.                     */
  540.   sprintf(temp,"%s.lzh",ex.infile);
  541.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  542.     {
  543.       fclose (ex.fp_in);
  544.       types.lharc = TRUE;
  545.     }
  546.  
  547.   /* See if file with .SIT extension can be opened.             */
  548.   /* SIT_TYPE if it can be opened                     */
  549.   sprintf(temp,"%s.sit",ex.infile);
  550.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  551.     {
  552.       fclose (ex.fp_in);
  553.       types.sit = TRUE;
  554.     }
  555.  
  556.   /* See if file with .TAR extension can be opened.             */
  557.   /* TAR_TYPE if it can be opened.                     */
  558.   sprintf(temp,"%s.tar",ex.infile);
  559.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  560.     {
  561.       fclose (ex.fp_in);
  562.       types.tar = TRUE;
  563.     }
  564.  
  565.   /* See if file with .ZIP extension can be opened.             */
  566.   /* ZIP_TYPE if it can be opened                     */
  567.   sprintf(temp,"%s.zip",ex.infile);
  568.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  569.     {
  570.       fclose (ex.fp_in);
  571.       types.zip = TRUE;
  572.     }
  573.  
  574.   /* See if file with .ZOO extension can be opened.  Return FALSE if */
  575.   /* it can't be opened.  ZOO_TYPE otherwise.                        */
  576.   sprintf(temp,"%s.zoo",ex.infile);
  577.   if ((ex.fp_in = fopen (temp,"r")) != NULL)
  578.     {
  579.       fclose (ex.fp_in);
  580.       types.zoo = TRUE;
  581.     }
  582.  
  583.   if (types.arc || types.lharc || types.zoo || types.sit || types.cpio ||
  584.       types.tar || types.zip)
  585.     return (ADD_EXT);
  586.   else return (FALSE);
  587. }
  588.  
  589. /* Used to put the filename to be opened in ex.filename */
  590.  
  591. int get_filename(type)
  592. char *type;
  593. {
  594.   if (! ex.add) strcpy (ex.filename,ex.infile);
  595.     else sprintf (ex.filename,"%s%s",ex.infile,type);
  596. }
  597.  
  598. /* This will return an unsigned long integer calculated from the global */
  599. /* buffer used for storage.  Pass the high byte to this routine.    */
  600.  
  601. ULONG get_long (temp)
  602. int temp;
  603. {
  604.   return ((ULONG) (b[temp] << 24) + (ULONG) (b[temp-1] << 16) +
  605.       (ULONG) (b[temp-2] << 8) + (ULONG) b[temp-3]);
  606. }
  607.  
  608. /* Open the input file */
  609. in_open ()
  610. {
  611.   if ((ex.fp_in = fopen(ex.filename,"rb")) == NULL)
  612.     exit (1);
  613. }
  614.  
  615. /* Read x bytes from ex.infile - Do error checking here too */
  616. int read_buf (x)
  617. int x;
  618. {
  619.   int count;
  620.   count = fread(b,x,1,ex.fp_in);
  621.   if (count == 0)
  622.     exit (1);
  623.   else return (count);
  624. }
  625.  
  626. /* List an Lharc file's contents */
  627. int list_lharc(bool)
  628. int bool;
  629. {
  630.   int ct, time, date, done;
  631.   long int uncomp, comp;
  632.   unsigned char name[80];
  633.  
  634.   get_filename (".lzh");
  635.  
  636.   /* Open the file - Abort if Error occurs. */
  637.   in_open();
  638.  
  639.   /* Read in my bytes */
  640.   ct = read_buf (22);
  641.  
  642.   /* Determine if it is an Lharc file */
  643.   if ((strncmp(b+(sizeof (char) *2),"-l",2) != 0))
  644.     {
  645.       fclose (ex.fp_in);
  646.       return (WRONG_ARCHIVE);
  647.     }
  648.  
  649.   /* Get file name stored in archive */
  650.   ct = fread(name,b[21]+2,1,ex.fp_in);
  651.   name[b[21]] = 0;
  652.  
  653.   /* Print out header info to standard output */
  654.   ex.type = LHARC;
  655.   init_list();
  656.  
  657.   done = FALSE;
  658.   while (!done)
  659.    {
  660.      /* Calculate Compressed, Uncompressed, Date,Time, and print it out */
  661.      comp = get_long(10);
  662.      uncomp = get_long(14);
  663.      date = b[18] * 256 + b[17];
  664.      time = b [16] * 256 + b[15];
  665.      msdog (time,date);
  666.      if (ex.error) break;
  667.      print_list(name,uncomp,comp);
  668.  
  669.      /* Read in more bytes */
  670.      fseek(ex.fp_in,comp,SEEK_CUR);
  671.      ct = fread(b,22,1,ex.fp_in);
  672.  
  673.      if ((strncmp(b+(sizeof (char) *2),"-l",2) != 0) || (ct < 1))
  674.        done = TRUE;
  675.  
  676.      /* Read in file name again */
  677.      ct = fread(name,b[21]+2,1,ex.fp_in);
  678.      name[b[21]] = 0;
  679.    }
  680.  
  681.   fclose (ex.fp_in);
  682.   /* Print ending stats */
  683.   end_stats();
  684.   return (TRUE);
  685. }
  686.  
  687. /* List a Tar archive */
  688. int list_tar()
  689. {
  690.   long time,size;
  691.   int ct, date, done, i;
  692.   ULONG uncomp, comp;
  693.  
  694.   struct tm *tm;
  695.  
  696.   /* Get the filename with extension */
  697.   get_filename (".tar");
  698.  
  699.   /* Open the file up.    Abort if file not found or error occurs */
  700.   in_open();
  701.  
  702.   /* Initialize the start of the list */
  703.   ex.type = TAR;
  704.   init_list();
  705.  
  706.   /* Loop until there is a Zero in the first byte of the name */
  707.   while (get_header())
  708.     {
  709.       /* Read in the uncompressed size */
  710.       sscanf (tar.size,"%8o\n",&uncomp);
  711.  
  712.       /* Read in date of stored file and put it in string */
  713.       sscanf (tar.mtime,"%12o",&time);
  714.       tm = localtime (&time);
  715.  
  716.       sprintf (ex.time_str,"%02d-%s-19%d %02d:%02d:%02d",
  717.     tm->tm_mday,months[tm->tm_mon],tm->tm_year,tm->tm_hour,
  718.     tm->tm_min,tm->tm_sec);
  719.  
  720.       /* Print out statistics read in */
  721.       print_list (tar.name,uncomp,uncomp);
  722.  
  723.       /* Seek to next header in list */
  724.       fseek (ex.fp_in,512 - (sizeof tar),SEEK_CUR);
  725.       fseek (ex.fp_in,uncomp,SEEK_CUR);
  726.       if ( (uncomp != 0) && ((uncomp % 512) != 0) )
  727.        {
  728.      uncomp = 512 - uncomp % 512;
  729.      fseek (ex.fp_in,uncomp,SEEK_CUR);
  730.        }
  731.     }
  732.  
  733.    /* Close the file and print the ending statistics. */
  734.    fclose (ex.fp_in);
  735.    end_stats();
  736.    return (TRUE);
  737. }
  738.  
  739. /* Function to read the tar header structure into memory */
  740. int get_header()
  741. {
  742.   fread (tar.name,1,100,ex.fp_in);
  743.   if (tar.name[0] == 0)
  744.     return (FALSE);
  745.   fread (tar.mode,1,8,ex.fp_in);
  746.   fread (tar.uid,1,8,ex.fp_in);
  747.   fread (tar.gid,1,8,ex.fp_in);
  748.   fread (tar.size,1,12,ex.fp_in);
  749.   fread (tar.mtime,1,12,ex.fp_in);
  750.   fread (tar.chksum,1,8,ex.fp_in);
  751.   fread (tar.linkflag,1,1,ex.fp_in);
  752.   fread (tar.linkname,1,100,ex.fp_in);
  753.   fread (tar.rdev,1,6,ex.fp_in);
  754.   return (TRUE);
  755. }
  756.  
  757. /* List a zoo archive */
  758.  
  759. int list_zoo()
  760. {
  761.   int ct, time, date, done, i;
  762.   unsigned long int uncomp, comp, pntr, pntr2, temp;
  763.  
  764.   get_filename (".zoo");
  765.  
  766.   /* Open the file - Abort if Error occurs. */
  767.   in_open();
  768.  
  769.   ct = read_buf (35);
  770.  
  771.   temp = get_long(23);
  772.   /* Determine if it is a Zoo file */
  773.   if (temp != 0xFDC4A7DC)
  774.     {
  775.       fclose (ex.fp_in);
  776.       return (WRONG_ARCHIVE);
  777.     }
  778.  
  779.   /* Pointer to next header */
  780.   pntr = get_long (27);
  781.  
  782.   /* Read in the File Info */
  783.   fseek(ex.fp_in,pntr,SEEK_SET);
  784.  
  785.   ct = read_buf(51);
  786.  
  787.   /* Print out header info to standard output */
  788.   ex.type = ZOO;
  789.   init_list();
  790.  
  791.   done = FALSE;
  792.   pntr = get_long (9);
  793.   while (!done)
  794.    {
  795.      /* Calculate Compressed, Uncompressed, Date,Time, and print it out */
  796.      comp = get_long(27);
  797.      uncomp = get_long(23);
  798.      date = b[15] * 256 + b[14];
  799.      time = b [17] * 256 + b[16];
  800.      msdog (time,date);
  801.      if (ex.error) break;
  802.      print_list(b+38,uncomp,comp);
  803.  
  804.      fseek (ex.fp_in,pntr,SEEK_SET);
  805.  
  806.      ct = read_buf (51);
  807.      pntr = get_long(9);
  808.      if (pntr == 0) break;
  809.    }
  810.  
  811.   fclose (ex.fp_in);
  812.   /* Print ending stats */
  813.   end_stats();
  814.   return (TRUE);
  815. }
  816.