home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #30 / NN_1992_30.iso / spool / comp / sources / acorn / 57 < prev    next >
Encoding:
Text File  |  1992-12-17  |  19.4 KB  |  754 lines

  1. Path: sparky!uunet!comp.vuw.ac.nz!waikato.ac.nz!aukuni.ac.nz!cs18.cs.aukuni.ac.nz!jwil1
  2. Newsgroups: comp.sources.acorn
  3. Subject: Source [C, UNIX]: CBadecode for UNIX
  4. Message-ID: <1992Dec17.015625.7604@cs.aukuni.ac.nz>
  5. From: jwil1@cs.aukuni.ac.nz (TMOTA)
  6. Date: Thu, 17 Dec 1992 01:56:25 GMT
  7. Sender: jwil1@cs.aukuni.ac.nz (TMOTA)
  8. Organization: Computer Science Dept. University of Auckland
  9. Approved: cba@acorn.co.nz
  10. Lines: 742
  11.  
  12.  
  13. /*
  14. The following is pcc and ANSI compatible C source code for a command-line
  15. version of the Archimedes !CBAdecode application.
  16.  
  17. NOTE: You do not *need* this program to decode postings to this group.
  18. Currently it is expected that all postings will be uucoded Spark
  19. Archives, and this is unlikely to change in the next year or two...
  20.  
  21. If you wish to gain all of the advantages of this autodecoder on a
  22. machine other than the Archimedes (for which you should use !CBAdecode)
  23. then simply compile the following program. On my ULTRIX box, I typed
  24. "gcc cbadecode.c" and it worked fine, so hopefully it'll be easy to
  25. compile on your system as well.
  26.  
  27. --- Cut here (or below the Help section) ---------------------------->8---
  28. */
  29. /* (This Help file is embedded into a C comment so you don't need to strip
  30.     it if you can't be bothered... )
  31.  
  32. Help for CBAdecode (UNIX source version)
  33. ========================================
  34.  
  35.  *  This source code is PUBLIC DOMAIN
  36.  *  You may copy/distribute it as much as you like so long as it is not
  37.  *  copied or distributed for profit, or as part of a commercial product.
  38.  *  Use (of application and source) is entirely at your own risk.
  39.  
  40. This application is designed specifically to make decoding
  41. comp.binaries.acorn postings easier and quicker. It will NOT work with
  42. postings to other usenet or FidoNet groups! (This is because it relies on
  43. some header data that we place when we post files, which cannot be expected
  44. in other groups)
  45.  
  46. It is supplied as a UNIX (pcc/ANSI) source file. (Please excuse the messiness,
  47. but it's a cut-back version of the !CBAdecode application on the Archimedes)
  48.  
  49. This version of the application is the command-line version of the
  50. Archimedes application. It compiles OK on my Ultrix box, so it shouldn't be
  51. too difficult to compile on any C compiler...
  52.  
  53. Run the application with the syntax:
  54.   CBAdecode [list_of_filenames]
  55.  
  56.   CBAdecode csa/95 csa/96 csa/97
  57.   CBAdecode file1 file3
  58.  
  59. Any complete and valid postings found will be decoded immediately, using the
  60. name after the "begin 777" in the first part of the posting. The output
  61. files are Spark archives, which can be decompressed using UNIX Spark, or
  62. (on an archimedes) using !Spark, SparkPlug, SparkFS, ArcFS.
  63. Output files will be placed in the current directory. The name will be
  64. extended with a ".arc" or a ".txt" extension to identify its type. (archive
  65. or text/unknown file)
  66.  
  67. If a file of the same name as the output file already exists, an extra
  68. extension (.retry1 .retry2 etc) will be added in an attempt to get a unique
  69. (safe) filename.
  70.  
  71. Operation
  72. =========
  73.  
  74. The way the program scans for parts means that you do not need to delete
  75. message headers and signatures, concatenate files, or even get them in the
  76. right order - everything is done automatically for you!
  77.  
  78. In fact, if you do strip headers, the program will FAIL, so just leave the
  79. message files you get from c.b.a alone, and pass them to this program in
  80. their RAW, unprocessed form.
  81.  
  82. The application will cope with all of the posted messages concatenated into
  83. one (or more) file(s), or a lot of seperate files.
  84.  
  85. It also handles any mixture of parts from different postings without
  86. complaint. It shouldn't cause any damage to any of the source files, or any
  87. other files in the same directory, but work from a backup just in case.
  88.  
  89. The only thing it won't currently handle is a posting with more than 32
  90. parts in it (which is a 1.6 Megabyte posting...). However, such a large
  91. posting will produce an archive file of approximately 1MB, which is a bit
  92. big for many people to handle anyway, so it is extremely unlikely that
  93. binaries larger than this will be posted on c.b.a. in one archive chunk.
  94.  
  95.  
  96. Problem shooting
  97. ================
  98.  
  99. Don't shoot problems. It's antisocial. (Bdooom-Tsh!)
  100.  
  101. What can you do wrong? Here's a list:
  102. (There are 2 types of error - warnings, which indicate possible problems,
  103. but usually don't affect the outcome of the decode, and bad errors, which
  104. will cause the application to abort its attempt to decode that particular
  105. posting. (Some very bad and unlikely errors may even cause the application
  106. to quit)
  107.  
  108. * Not all parts present
  109.   You will not be able to decode a posting until files containing all the
  110.   relevant parts have been supplied.
  111.  
  112. * One or more parts duplicated
  113.   The duplicate parts are ignored without comment.
  114.  
  115. * The quoted total number of posted parts changes from one part to another
  116.   Processing of that posting will abort, and the next posting will be
  117.   started. This shouldn't happen unless the messages get corrupted or
  118.   you happen to get 2 different postings under the same name (unlikely!)
  119.  
  120. * Too many parts in the posting
  121.   The application thinks there are supposed to be (eg) 5 parts in the
  122.   posting, and it has found a part number less than 1 or greater than 5.
  123.   This usually indicates corruption of some of the files, or possibly
  124.   that the 32 part-per-post limit of the application has been reached.
  125.  
  126. * Filing errors
  127.   If any problems occur when trying to read or write any files (most likely
  128.   because an input file wasn't found or because the disc is full - disc
  129.   is full? Hopefully not on your UNIX box!) the program will abort
  130.  
  131. * UUcode errors
  132.   These are usually fatal (uucode is either right or wrong), and are usually
  133.   caused by parts of the uucode data being corrupted or missing. There isn't
  134.   much that can be done about this - try to get a new copy of the offending
  135.   files.
  136.  
  137. If anything goes wrong, what can you do to fix it?
  138. * Check that you are giving it the correct set of files, and try again.
  139.  
  140. * If you still can't get any joy, then you will have to resort to decoding
  141.   the file by hand - strip headers and footers, concatenate all the text
  142.   together in the correct order, and use uudecode and UNIX Spark to decode
  143.   the file.
  144.  
  145. The author
  146. ==========
  147.  
  148. If you have any bug reports, suggestions, or improved code to send to the
  149. author, or if you want to offer him an extremely highly paid job and a
  150. Porsche (preference, black 930 or 944), write to:
  151.  
  152.   *  Jason Williams
  153.   *  R.D.2, Manuel Road,
  154.   *  Silverdale,
  155.   *  North Auckland,
  156.   *  NEW ZEALAND.
  157.   *
  158.   *  jwil1@cs.aukuni.ac.nz
  159.   *
  160.   *  (A moderator of the usenet group comp.binaries.acorn)
  161.  
  162. */
  163.  
  164. /*  Program:     CBAdecode.c
  165.  *  Purpose:     comp.binaries.acorn auto-post decoder
  166.  *  Author:      Jason Williams
  167.  *  Version:     21 May 1992
  168.  *
  169.  *  This source code is PUBLIC DOMAIN
  170.  *  You may copy/distribute it as much as you like so long as it is not
  171.  *  copied or distributed for profit, or as part of a commercial product.
  172.  *  Use of this program and source code is entirely at your own risk.
  173.  *
  174.  *  You can contact me at:
  175.  *    Jason Williams,          jwil1@cs.aukuni.ac.nz
  176.  *    R.D.2, Manuel road,      (until March 1993)
  177.  *    Silverdale,
  178.  *    North Auckland,
  179.  *    NEW ZEALAND.
  180.  */
  181.  
  182.  
  183. #include <stddef.h>
  184. #include <stdlib.h>
  185. #include <stdio.h>
  186. #include "string.h"
  187.  
  188. #ifndef BOOL
  189. #  define BOOL  int
  190. #  define FALSE 0
  191. #  define TRUE  1
  192. #  define ERROR   1
  193. #  define NOERROR 0
  194. #endif
  195.  
  196. #ifndef SEEK_SET
  197. #  define SEEK_SET 0
  198. #endif
  199.  
  200.  
  201. /*  Maximum number of parts per post */
  202. #define MAXPARTS    32
  203.  
  204. /* Number of the first icon in the series used for the list */
  205. #define BASEICON     1
  206.  
  207. /* Gap between left & top of window and icons */
  208.  
  209. #define NOTFOUND     0
  210. #define FOUND        1
  211. #define PROCESSED    2
  212.  
  213. /*
  214.  *  Posted archives should all have a 0x1a as their first byte
  215.  *  If this is the case we will *SetType the type to "Archive" (0xDDC)
  216.  */
  217. #define ARCIDBYTE (0x1a)
  218.  
  219.  
  220. typedef struct
  221. {
  222.   char     filename[260];                 /* Input file data can be found in */
  223.   long int filepos;                       /* Place in file the data starts   */
  224.   int      status;                        /* Not-found, Found, or processed  */
  225. } partinfo;
  226.  
  227.  
  228. typedef struct _postinfo
  229. {
  230.   struct _postinfo *next;                 /* Next postinfo in linked list    */
  231.   int      totalparts, partsfound;        /* Number of parts found & total   */
  232.   char     id[48];                        /* Post identifier name            */
  233.   char     icontext[48];                  /* Indirected text for icon        */
  234.   char     postname[32];                  /* Output leaf filename            */
  235.   int      filetype;                      /* Output file type                */
  236.   partinfo part[MAXPARTS];                /* list of part information        */
  237.   int      index;                         /* index in list (== icon index)   */
  238.   BOOL     selected;                      /* Is this item selected?          */
  239. } postinfo;
  240.  
  241.  
  242. BOOL quit = FALSE;
  243.  
  244. /* Static data for scanning source files... */
  245. static postinfo *postheader = NULL;
  246.  
  247. /* Static data for uudecoding... */
  248. static FILE *outfile = NULL;
  249. static char outfilename[256] = "\0";
  250.  
  251.  
  252.  
  253. static void FreeEntry(prev, this)
  254. postinfo *prev;
  255. postinfo *this;
  256. {
  257.   if (prev == NULL)
  258.     postheader = this->next;
  259.   else
  260.     prev->next = this->next;
  261.  
  262.     free(this);
  263. }
  264.  
  265.  
  266.  
  267. static void FreeEntryList()
  268. {
  269.   postinfo *ptr = postheader, *next;
  270.  
  271.   while (ptr != NULL)
  272.   {
  273.     next = ptr->next;
  274.     free(ptr);
  275.     ptr = next;
  276.   }
  277.  
  278.   postheader = NULL;
  279. }
  280.  
  281.  
  282.  
  283. static void InitData()
  284. /* (re)sets all data back to initial state */
  285. {
  286.   outfile   = NULL;
  287.   FreeEntryList();
  288. }
  289.  
  290.  
  291.  
  292. static BOOL ProcessError()
  293. /*
  294.  *  Tidies up after unrecoverable error
  295.  */
  296. {
  297.   if (outfile != NULL)
  298.     fclose(outfile);
  299.  
  300.   return(ERROR);
  301. }
  302.  
  303.  
  304.  
  305. static void GetFilePath(pathname, path)
  306. char *pathname;
  307. char *path;
  308. /*  Given a full-path filename, find the pathname
  309.  */
  310. {
  311.   int index, loop;
  312.  
  313.   path[0] = '\0';
  314.   if (pathname[0] == '\0') return;
  315.  
  316.   index = strlen(pathname);
  317.   while (index > 0 && pathname[index] != '/')
  318.     index--;
  319.  
  320.   if (index > 0)
  321.   {
  322.     for (loop = 0; loop <= index; loop++)
  323.       path[loop] = pathname[loop];
  324.     path[loop] = '\0';
  325.   }
  326. }
  327.  
  328.  
  329.  
  330. /*
  331.  *  UUDecode function & macro
  332.  */
  333. #define decode(ch) (((ch) - ' ') & 0x3F)
  334.  
  335. void outdec(buffer, outfile, numbytes)
  336. char *buffer;
  337. FILE *outfile;
  338. int numbytes;
  339. {
  340.   int c1, c2, c3;
  341.  
  342.   c1 = (decode(buffer[0]) << 2) | (decode( buffer[1]) >> 4);
  343.   c2 = (decode(buffer[1]) << 4) | (decode( buffer[2]) >> 2);
  344.   c3 = (decode(buffer[2]) << 6) | (decode( buffer[3]));
  345.  
  346.   /* Make sure we don't output too much at EOF */
  347.   if(numbytes >= 1)  putc(c1, outfile);
  348.   if(numbytes >= 2)  putc(c2, outfile);
  349.   if(numbytes >= 3)  putc(c3, outfile);
  350. }
  351.  
  352.  
  353.  
  354. static BOOL GetOutputName(outname, path, leafname, filetype)
  355. char *outname;
  356. char *path;
  357. char *leafname;
  358. int filetype;
  359. /*
  360.  *  Tries to open the specified filename as an output file. Ensures
  361.  *  that no existing files are overwritten by generating random
  362.  *  names until a filename is found that is unique.
  363.  *  I would use tmpnam(), but this is unhelpful in that it doesn't 
  364.  *  give you just a leafname.
  365.  */
  366. {
  367.   char leaf[64];
  368.   FILE *outfile = (FILE *) 42;
  369.   int retry = 1;
  370.  
  371.   strcpy(leaf,leafname);          /* First try is the leafname we were given */
  372.   if (filetype = 0xDDC)
  373.     strcat(leaf, ".arc");
  374.   else
  375.     strcat(leaf, ".txt");
  376.  
  377.   sprintf(outname, "%s%s", path, leaf);
  378.   while (outfile != NULL)
  379.   {
  380.     outfile = fopen(outname, "rb");
  381.     if (outfile != NULL)
  382.     {
  383.       fclose(outfile);
  384.       sprintf(outname, "%s%s.retry%d", path, leaf, retry++);
  385.       if (retry > 32)                         /* 32 retries and still no joy */
  386.       {
  387.     printf("Error: Unable to generate unique filename!\n");
  388.     return(ProcessError());
  389.       }
  390.     }
  391.   }
  392.   return(NOERROR);
  393. }
  394.  
  395.  
  396.  
  397. static BOOL UUDecodePart(post, partnum, pathname)
  398. postinfo *post;
  399. int partnum;
  400. char *pathname;
  401. /*
  402.  *  Starts/continues/completes uudecoding by processing the given part
  403.  */
  404. {
  405.   FILE *infile;
  406.   char line[260], filepath[260] = "\0";
  407.   partinfo *part = &post->part[partnum];
  408.  
  409.   if (part->status != FOUND)
  410.     return(ERROR);
  411.  
  412.   infile = fopen(part->filename, "rb");
  413.   if (infile == NULL)
  414.   {
  415.     printf("Error: Unable to read part %d from %s\n",
  416.             partnum, part->filename);
  417.     return(ProcessError());
  418.   }
  419.  
  420.   fseek(infile, part->filepos, SEEK_SET);
  421.   if (partnum == 1)
  422.   {
  423.     fgets(line, 256, infile);
  424.     if (strncmp(line, "begin", 5) != 0)
  425.     {
  426.       printf("Error: 'begin' line not found (%s, part %d)\n",
  427.               post->id, partnum);
  428.       return(ProcessError());
  429.     }
  430.  
  431.     GetFilePath(pathname, filepath);
  432.     if (GetOutputName(outfilename, filepath, post->postname, post->filetype) == ERROR)
  433.       return(ERROR);
  434.  
  435.     printf("UUDecoding post '%s' as '%s'\n", post->id, outfilename);
  436.  
  437.     if (outfile != NULL)  fclose(outfile);
  438.  
  439.     outfile = fopen(outfilename, "wb");
  440.     if (outfile == NULL)
  441.     {
  442.       printf("Error: Can't open output file, '%s'!\n", outfilename);
  443.       return(ProcessError());
  444.     }
  445.   }
  446.  
  447.  
  448.   /* Actual UUDecode pass over rest of file
  449.    * --------------------------------------
  450.    */
  451.   {
  452.     int  numbytes;
  453.     char *buffptr;
  454.  
  455.     while(TRUE)
  456.     {
  457.       if(fgets(line, sizeof(line), infile) == NULL)
  458.       {
  459.     printf("Error: Short file (%s)\n", part->filename);
  460.     return(ProcessError());
  461.       }
  462.  
  463.       if (strlen(line) >= 60 && strncmp(line, "END", 3) == 0 &&
  464.                 strncmp(&line[57], "---", 3) == 0)
  465.     break;
  466.  
  467.       numbytes = decode(*line);
  468.       if(numbytes <= 0)
  469.     break;
  470.  
  471.       buffptr = line + 1;
  472.       while (numbytes > 0)
  473.       {
  474.     outdec(buffptr, outfile, numbytes);
  475.     buffptr  += 4;
  476.     numbytes -= 3;
  477.       }
  478.     }
  479.   }
  480.  
  481.   /*  uudecode of part complete
  482.    *  -------------------------
  483.    */
  484.   part->status = PROCESSED;
  485.   fclose(infile);
  486.  
  487.   if (partnum == post->totalparts)
  488.     fclose(outfile);
  489.  
  490.   return(NOERROR);
  491. }
  492.  
  493.  
  494.  
  495. static BOOL UUDecodePost(post, pathname, icon)
  496. postinfo *post;
  497. char *pathname;
  498. int icon;
  499. /*
  500.  *  Calls UUDecodePart for each part to be processed in turn
  501.  */
  502. {
  503.   int partnum;
  504.  
  505.   post->selected = FALSE;
  506.   if (post->totalparts <= 0)
  507.     return(ERROR);
  508.  
  509.   if (post->totalparts - post->partsfound > 0)
  510.   {
  511.     printf("Error: %d parts of %s are missing\n",
  512.             post->totalparts - post->partsfound, post->id);
  513.     return(ProcessError());
  514.   }
  515.  
  516.   for (partnum = 1; partnum <= post->totalparts; partnum++)
  517.   {
  518.     if (UUDecodePart(post, partnum, pathname) == ERROR || quit)
  519.       return(ERROR);
  520.   }
  521.  
  522.   return(NOERROR);
  523. }
  524.  
  525.  
  526.  
  527. static void UUDecodeFiles(pathname)
  528. char *pathname;
  529. {
  530.   postinfo *ptr = postheader, *last = NULL;
  531.  
  532.   while (ptr != NULL)
  533.   {
  534.     if (ptr->selected)
  535.     {
  536.       UUDecodePost(ptr, pathname, ptr->index);
  537.       if (quit)
  538.     break;
  539.  
  540.       FreeEntry(last, ptr);
  541.       if (last == NULL)        /* Have deleted "ptr" item out from under us! */
  542.     ptr = (postinfo *) &postheader;
  543.       else
  544.     ptr = last;
  545.     }
  546.     last = ptr;
  547.     if (ptr != NULL)
  548.       ptr  = ptr->next;
  549.   }
  550. }
  551.  
  552.  
  553.  
  554. static postinfo *FindPost(name, create)
  555. char *name;
  556. BOOL create;
  557. /*  Looks for the given posting in the linked list. Returns a ptr to it.
  558.  *  If the entry isn't found, (and create == TRUE), a new one is created
  559.  */
  560. {
  561.   postinfo *ptr = postheader, *last = (postinfo *) &postheader;
  562.   int loop = BASEICON;
  563.  
  564.   while (ptr != NULL)
  565.   {
  566.     if (!strcmp(name, ptr->id))
  567.       break;
  568.     last = ptr;
  569.     ptr->index = loop;
  570.     ptr = ptr->next;
  571.     loop++;                       /* remember index in list (== icon number) */
  572.   }
  573.  
  574.   if (ptr == NULL && create)
  575.   {
  576.     ptr = (postinfo *) malloc(sizeof(postinfo));
  577.     if (ptr == NULL)
  578.     {
  579.       printf("Error: Out of memory!\n");
  580.       return(NULL);
  581.     }
  582.  
  583.     last->next = ptr;
  584.  
  585.     ptr->selected   = FALSE;
  586.     ptr->index      = loop;
  587.     ptr->filetype   = 0xDDC;
  588.     ptr->next       = NULL;
  589.     ptr->totalparts = 0;
  590.     ptr->partsfound = 0;
  591.     strcpy(ptr->id, name);
  592.     ptr->postname[0] = '\0';
  593.  
  594.     for (loop = 0; loop < MAXPARTS; loop++)
  595.     {
  596.       ptr->part[loop].status = NOTFOUND;
  597.       ptr->part[loop].filename[0] = '\0';
  598.       ptr->part[loop].filepos = NULL;
  599.     }
  600.   }
  601.  
  602.   return(ptr);
  603. }
  604.  
  605.  
  606.  
  607. static void AddEntry(infile, filename, line)
  608. FILE *infile;
  609. char *filename;
  610. char *line;
  611. /*
  612.  *  Adds an entry for the given post & part so that we remember where to
  613.  *  find the uucode data for the parts of the post when it is needed.
  614.  */
  615. {
  616.   int      index = 5;
  617.   int      namestart;
  618.   int      partnum, totalparts;
  619.   char     postid[64];
  620.   postinfo *post;
  621.   long int filepos = ftell(infile);   /* remember where 'begin' line started */
  622.  
  623.   while(line[index] != 0 && line[index] != '[')  index++;
  624.   namestart = index + 1;
  625.   while (line[index] != 0 && line[index] != ' ')  index++;
  626.   if (line[index] == 0) return;
  627.  
  628.   line[index++] = '\0';
  629.   strcpy(postid, &line[namestart]);
  630.   if ((post = FindPost(postid, TRUE)) == NULL) return;
  631.  
  632.   if (strncmp(&line[index], "part", 4) != 0)
  633.   {
  634.     printf("Warning: Invalid part header in file '%s' ignored", filename);
  635.     return;
  636.   }
  637.   sscanf(&line[index], "part %d of %d]", &partnum, &totalparts);
  638.  
  639.   if (partnum == 1)            /* If part 1, get postname (output file name) */
  640.   {
  641.     fgets(line, 255, infile);
  642.     sscanf(line, "begin 777 %s ", post->postname);
  643.     fgets(line, 255, infile);
  644.     if (((decode(line[1]) << 2) | (decode(line[2]) >> 4)) == ARCIDBYTE)
  645.       post->filetype = 0xDDC;
  646.     else
  647.       post->filetype = 0xFFF;
  648.   }
  649.  
  650.   if (post->totalparts == 0)         /* Get idea of how many parts to expect */
  651.     post->totalparts = totalparts;
  652.   else
  653.     if (post->totalparts != totalparts)
  654.     {
  655.       printf("Error: Number of parts in %s is inconsistent!\n", postid);
  656.       return;
  657.     }
  658.                            /* Check part number validity */
  659.   if (partnum < 1 || partnum > totalparts || partnum > MAXPARTS)
  660.   {
  661.     printf("Error: Illegal part number (%d) in %s\n", partnum, postid);
  662.     return;
  663.   }
  664.  
  665.   if (post->part[partnum].filename[0] == '\0')   /* Check if its a duplicate */
  666.   {
  667.     strcpy(post->part[partnum].filename, filename);
  668.     post->part[partnum].filepos  = filepos;
  669.     post->part[partnum].status   = FOUND;
  670.     post->partsfound++;
  671.   }
  672.   else
  673.     printf("Warning: Duplicate of %s part %d ignored\n", postid, partnum);
  674.  
  675.   if (post->totalparts == post->partsfound)
  676.     post->selected = TRUE;       /* If all parts found, select the post icon */
  677. }
  678.  
  679.  
  680.  
  681. static void ScanFile(filename)
  682. char *filename;
  683. /*
  684.  *  Scans the given file looking for post headers
  685.  */
  686. {
  687.   FILE *infile;
  688.   char line[256];
  689.  
  690.   infile = fopen(filename, "rb");
  691.   if (infile == NULL)
  692.   {
  693.     printf("Warning: Unable to process %s\n", filename);
  694.     return;
  695.   }
  696.  
  697.   printf("Scanning file %s\n", filename);
  698.   while (!feof(infile))
  699.   {
  700.     fgets(line, 255, infile);
  701.     if (!strncmp(line, "BEGIN", 5))
  702.       AddEntry(infile, filename, line);
  703.   }
  704.  
  705.   fclose(infile);
  706. }
  707.  
  708.  
  709.  
  710. static void PrintHelp()
  711. /*
  712.  *  This, ah... prints the... er... help.
  713.  */
  714. {
  715.   printf("\n");
  716.   printf("  ####  #####   ####   Autoposted binary uudecoder\n");
  717.   printf(" ##  ## ##  ## ##  ##  Syntax: CBADecode [-options] [filename(s)]\n");
  718.   printf(" ##     #####  ######  \n");
  719.   printf(" ##  ## ##  ## ##  ##  By Jason Williams - jwil1@cs.aukuni.ac.nz\n");
  720.   printf("  ####  #####  ##  ##  Version: 5 June 1992\n");
  721.   exit(1);
  722. }
  723.  
  724.  
  725.  
  726. extern int main(argc, argv)
  727. int argc;
  728. char *argv[];
  729. /*
  730.  *  If you don't know what this is for, then maybe you shouldn't be
  731.  *  mucking about with it? ;-)
  732.  */
  733. {
  734.   int count;
  735.  
  736.   if (argc < 2)           /* check if user has absolutely no idea what to do */
  737.     PrintHelp();
  738.  
  739.   InitData();                                  /* Initialise data structures */
  740.  
  741.   for(count = 1; count < argc; count++)  /* Scan files given in Command line */
  742.     ScanFile(argv[count]);
  743.  
  744.   UUDecodeFiles("\0");
  745.   return(0);
  746. }
  747.  
  748. --- CUT HERE ---
  749.  
  750. -- 
  751. _________________  "I'd like to answer this question in two ways:
  752.   /____ _ _/_ __       First in my normal voice, and then
  753.  // / //_//_ /_/       in a silly, high-pitched whine." (Monty Python)
  754.