home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / uudoall.zip / uudoall.c < prev    next >
Text File  |  1993-08-30  |  11KB  |  349 lines

  1. /*uudoall.c cleans up split files checks checksums and writes by h**2 7/4/91
  2.  *  (c) 1991 by Howard Helman
  3.  */
  4.  
  5.  
  6.  
  7. /*
  8.   uudoall.c can usually handle the split files with all the intervening mail
  9.   crap.
  10.   Automatically checks for checksums on lines and automatically checks for
  11.   a `size' line at the end and verifies the size.  It also computes the sum
  12.   value for the decoded file. I could not find any convention on people using
  13.   sum so the program just computes it and prints it.
  14.  
  15.   Compile by defining DOS for msdos use or OS2 for GCC on OS/2 or UNIX for use elsewhere.
  16.  */
  17.  
  18.  
  19. /* the program is called by :
  20.         uudoall [opts] -ddir infile [...]
  21.  where opts are:
  22.                 -s+             do size check
  23.                 -s-             inhibit size check
  24.                 -c+             do line by line checksum
  25.                 -c-             inhibit checksum
  26.                 -ddir   place output files in the named directory
  27.                 infile  the file to process (all parts should be concatenated.)
  28.                 [...]   options and file names may be repeated.
  29.                                 The last option setting is in effect when a file is
  30.                                 processed.
  31.  If the program cannot open the output file, it prompts the user
  32.  for a new file name or `enter' to stop.
  33.  The trimming of trailing blanks is handled properly.  This program
  34.  has been in use continually and has only had one problem: a user
  35.  signature started in col 1 and had a `M' and over sixty characters in the
  36.  line.  This is what the program searches for to find the next part of the
  37.  encoded file.
  38. */
  39.  
  40. /*
  41.   This program is donated to the public domain provided that the source
  42.   is distributed in total and my authorship of the program is credited.
  43.  
  44.                 Howard Helman
  45.                 Box 340
  46.                 Manhattan Beach
  47.                 CA 90266
  48. */
  49.  
  50. /* v1.1, 3 Oct 91   Toad Hall Tweak
  51.  * - Slight tweaks to reduce Turbo C v2.0 warnings.
  52.  * - Threw in some prototypes.
  53.  * - Reformatted to K&R standards (via good old Mister Mangler,
  54.  *   AKA indent).
  55.  * David Kirschbaum
  56.  * Toad Hall
  57.  * kirsch@usasoc.soc.mil
  58.  */
  59.  
  60. /* Added #ifdef's for OS/2 August 29, 1993 */
  61.  
  62. #ifdef __TURBOC__
  63. #define DOS 1
  64. #endif
  65.  
  66. #ifdef DOS
  67. #include <stdlib.h>
  68. #include <alloc.h>
  69. #define ReaD "rt"
  70. #define WritE "wb"
  71. #define SlasH "\\"
  72. #endif
  73. #ifdef UNIX
  74. #define ReaD "r"
  75. #define WritE "w"
  76. #define SlasH "/"
  77. #endif
  78. #ifdef OS2
  79. #define ReaD "rt"
  80. #define WritE "wb"
  81. #define SlasH "/"
  82. #endif
  83.  
  84. #include <stdio.h>
  85. #include <string.h>
  86. #include <ctype.h>
  87.  
  88. #define Bsize 80
  89. #define SUMSIZE 64
  90. #define DEC(c)  (((x_x=(c))>=' ')?((x_x-' ')&077):(0))  /* single char decode */
  91. #define match(x) matcher(buf,x)
  92.  
  93. static int dosize = 1, docheck = 1;
  94. static char x_x, dir[80];
  95. static long nbytes;
  96. static unsigned int sum1;
  97.  
  98. #ifdef DOS
  99. static void *vbi;
  100. static unsigned bn;
  101. #endif
  102.  
  103. #ifdef __TURBOC__
  104. /* v1.1 I like prototypes */
  105. int matcher(char *a, char *b);
  106. int hget(char *buf, int bs, FILE *in);
  107. void decode(FILE *in, FILE *out, char *dest);
  108. void doopts(char *s);
  109. void decodeit(FILE *in, char buf[Bsize]);
  110.  
  111. #endif
  112. enum States {
  113.         BeginSearch, InBody, GapOrEnd, LookEnd, PutTwo, PutEnd,
  114.         Mfind
  115. } state = BeginSearch;
  116.  
  117. int matcher(a, b)
  118. char *a, *b;
  119. {
  120.         while (*b && *a == *b)
  121.                 a++, b++;
  122.         return (!*b);
  123. }
  124.  
  125. int hget(buf, bs, in)
  126. char *buf;
  127. int bs;
  128. FILE *in;
  129. {
  130.         static char s1[Bsize], s2[Bsize];
  131.  
  132.         if (state == PutEnd) {
  133.                 strcpy(buf, "end");
  134.                 state = BeginSearch;
  135.                 return 1;
  136.         }
  137.         if (state == PutTwo) {
  138.                 strcpy(buf, s2);
  139.                 state = PutEnd;
  140.                 return 1;
  141.         }
  142.         while (fgets(buf, bs, in)) {
  143.                 switch (state) {
  144.                 case BeginSearch:
  145.                         if (match("begin "))
  146.                                 state = InBody;
  147.                         return 1;
  148.                 case InBody:
  149.                         if (*buf == 'M')
  150.                                 return 1;
  151.                         else if (*buf == '`') {
  152.                                 state = BeginSearch;
  153.                                 return 1;
  154.                         } else {
  155.                                 strcpy(s1, buf);
  156.                                 state = GapOrEnd;
  157.                         }
  158.                         break;
  159.                 case GapOrEnd:
  160.                         if (match("end")) {
  161.                                 strcpy(buf, s1);
  162.                                 state = PutEnd;
  163.                                 return 1;
  164.                         } else {
  165.                                 strcpy(s2, buf);
  166.                                 state = LookEnd;
  167.                         }
  168.                         break;
  169.                 case LookEnd:
  170.                         if (match("end")) {
  171.                                 strcpy(buf, s1);
  172.                                 state = PutTwo;
  173.                                 return 1;
  174.                         } else
  175.                                 state = Mfind;
  176.                         break;
  177.                 case Mfind:
  178.                         if (*buf == 'M' && strlen(buf) > 60) {
  179.                                 state = InBody;
  180.                                 return 1;
  181.                         }
  182.                         break;
  183.                 }
  184.         }
  185.         return 0;
  186. }
  187.  
  188. void decode(in, out, dest)
  189. FILE *in, *out;
  190. char *dest;
  191. {
  192.         int j, n, checksum, altsum;
  193.         char buf[Bsize], *bp, hold[Bsize / 4 * 3], *jp;
  194.         unsigned pcline = 0, line = 0;
  195.  
  196.         sum1 = 0;
  197.         nbytes = 0;
  198.         while (memset(buf, 0, Bsize), hget(buf, Bsize, in)
  199.           &&(n = DEC(*buf)) > 0) {
  200.                 line++;
  201.                 altsum = checksum = 0;
  202.                 bp = buf + 1;
  203.                 for (jp = hold, j = n; j > 0; j -= 3, bp += 4) {
  204.                         *jp = (DEC(bp[0]) << 2) | (DEC(bp[1]) >> 4);
  205.                         checksum += *jp++;
  206.                         *jp = (DEC(bp[1]) << 4) | (DEC(bp[2]) >> 2);
  207.                         checksum += *jp++;
  208.                         *jp = (DEC(bp[2]) << 6) | (DEC(bp[3]));
  209.                         checksum += *jp++;
  210.                         altsum += bp[0] + bp[1] + bp[2] + bp[3];
  211.                 }
  212.                 for (j = 0, jp = hold; j < n; j++, jp++)
  213.                         sum1 = ((sum1 >> 1) + ((sum1 & 1) ? 0x8000 : 0)
  214.                                 + (*jp & 0xff)) & 0xffff;
  215.                 nbytes += n;
  216.                 if (fwrite(hold, 1, n, out) != n) {
  217.                         fprintf(stderr, "ERROR: error writing to %s\n", dest);
  218.                         exit(1);
  219.                 }
  220.                 if (!isspace(*bp) && docheck)
  221.                         if ((checksum & (SUMSIZE - 1)) != DEC(*bp)
  222.                           && (altsum & 077) != (DEC(*bp) & 077)) {
  223.                                 if (!pcline)
  224.                                         pcline = line;
  225.                         } else if (pcline) {
  226.                                 fprintf(stderr,
  227.                                                 "ERROR:Bad Checksum lines %u-%u\n", pcline, line);
  228.                                 pcline = 0;
  229.                         }
  230.         }
  231.         if (pcline)
  232.                 fprintf(stderr, "ERROR:Bad Checksum lines %u-%u\n", pcline, line);
  233.         if (feof(in) ||ferror(in)) {
  234.                 fprintf(stderr, "ERROR: Input ended unexpectedly!\n");
  235.                 exit(1);
  236.         }
  237. }
  238.  
  239. void decodeit(in, buf)
  240. FILE *in;
  241. char buf[Bsize];
  242. {
  243.         int mode;
  244.         long filesize, tsize;
  245.         FILE *out;
  246.         char fname[128], dest[128];
  247.  
  248.         sscanf(buf, "begin %o %s", &mode, dest);
  249.         while (strcpy(fname, dir) && strcat(fname, dest)
  250.           && !(out = fopen(fname, WritE))) {
  251.                 fprintf(stderr, "ERROR: Can't open output file %s\nTry new one:",
  252.                                 fname);
  253.                 gets(dest);
  254.                 if (!*dest)
  255.                         exit(1);
  256.         }
  257. #ifdef DOS
  258.         setvbuf(out, (char *) vbi + bn * 512, _IOFBF, bn * 512);
  259. #endif
  260.         fprintf(stderr, "Creating %s\n", fname);
  261.         decode(in, out, dest);
  262.         if (!hget(buf, Bsize, in) ||!match("end")) {
  263.                 fprintf(stderr, "ERROR: no `end' line\n");
  264.                 exit(1);
  265.         }
  266.         tsize = ftell(out);
  267.         if (dosize && hget(buf, Bsize, in) &&match("size ")) {
  268.                 sscanf(buf, "size %ld", &filesize);
  269.                 if (tsize != filesize) {
  270.                         fprintf(stderr,
  271.                         "ERROR: file should have been %ld bytes long but was %ld.\n",
  272.                                         filesize, tsize);
  273.                         exit(1);
  274.                 }
  275.         } else if (dosize)
  276.                 fprintf(stderr, "Size check not done\n");
  277.         if (tsize != nbytes) {
  278.                 fprintf(stderr, "Size Error:file=%ld data=%ld\n", tsize, nbytes);
  279.                 exit(1);
  280.         }
  281.         fprintf(stderr, "sums: %u %ld %ld\n", sum1, (nbytes + 1023) / 1024,
  282.                         nbytes);
  283.         fclose(out);
  284. }
  285.  
  286. void doopts(s)
  287. char *s;
  288. {
  289.         if (s[1] == 's')
  290.                 dosize = s[2] != '-';
  291.         else if (s[1] == 'c')
  292.                 docheck = s[2] != '-';
  293.         else if (s[1] == 'd') {
  294.                 strcpy(dir, s + 2);
  295.                 if (*dir)
  296.                         strcat(dir, SlasH);
  297.         } else {
  298.                 fprintf(stderr, "Illegal flag %s\n", s);
  299.                 exit(1);
  300.         }
  301. }
  302.  
  303. int main(argc, argv)
  304. int argc;
  305. char **argv;
  306. {
  307.         FILE *in;
  308.         int nf = 0, i;
  309.         char buf[80];
  310.  
  311.         *dir = 0;
  312.         if (argc < 2) {
  313.                 fprintf(stderr,
  314.         "UUDOALL is a UUDECODER for multiple part uuencoded files that have been placed\n");
  315.                 fprintf(stderr,
  316.         "in a single file. For example, all of the articles from a USENET newsgroup\n");
  317.                 fprintf(stderr,
  318.         "could be saved to a single file.  UUDOALL would automatically extract any\n");
  319.                 fprintf(stderr,
  320.         "complete UUENCODED files.  It will handle UNIX and OS/2 long filenames.\n\n");
  321.                 fprintf(stderr,
  322.         "USAGE: uudoall [opts] -ddir infile [...] where opts are -s+|- -c+|-\n");
  323.                 exit(1);
  324.         }
  325. #ifdef DOS
  326.         bn = coreleft() / 1024 - 2;
  327.         vbi = malloc(512 * 2 * bn);
  328. #endif
  329.         for (i = 1; i < argc; i++) {
  330.                 if (argv[i][0] == '-')
  331.                         doopts(argv[i]);
  332.                 else if (!(in = fopen(argv[i], ReaD)))
  333.                         fprintf(stderr, "ERROR: can't find %s\n", argv[i]);
  334.                 else {
  335. #ifdef DOS
  336.                         setvbuf(in, vbi, _IOFBF, bn * 512);
  337. #endif
  338.                         while (hget(buf, Bsize, in)) {
  339.                                 if (match("begin ")) {
  340.                                         nf++;
  341.                                         decodeit(in, buf);
  342.                                 }
  343.                         }
  344.                         fclose(in);
  345.                 }
  346.         }
  347.         return !nf;
  348. }
  349.