home *** CD-ROM | disk | FTP | other *** search
/ The Best of Mecomp Multimedia 1 / Mecomp-CD.iso / amiga / librarys / xprascii.library / source / uue.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-09  |  7.4 KB  |  350 lines

  1. /* Written by Mark Horton */
  2. /* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */
  3. /* Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  4.    compatibility */
  5. /* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a very
  6.    misleading error message on the Amiga port, enable CTRL-C for LATTICE,
  7.    and add a transparant file size trailer for later check. */
  8. /* Modified by Ueli Kaufmann (Ueli_Kaufmann@augs1.adsp.sub.org) for use
  9.    in xprascii.library */
  10.  
  11. #include <exec/types.h>
  12.  
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <ctype.h>
  16.  
  17. #include "xproto.h"
  18. #include "xprascii.h"
  19.  
  20. LONG AtoL(UBYTE *);
  21.  
  22.  
  23. #define SUMSIZE 64  /* 6 bits */
  24. /* ENC is the basic 1 character encode function to make a char printing */
  25. /* Each output character represents 6 bits of input */
  26. #define ENC(c) ((c) ? ((c) & '\077') + ' ': '`')
  27.  
  28. #define DEC(c)    (((c) - ' ') & '\077')    /* single character decode */
  29.  
  30. VOID __stdargs upderr(struct XPR_IO *io, UBYTE *err, ...);
  31.  
  32.  
  33.  
  34. VOID uuencode_header(UBYTE *name, UBYTE *buf)
  35. {
  36.     sprintf(buf, "\nbegin 644 %s\n", name);
  37. }
  38.  
  39.  
  40. VOID uuencode_footer(UBYTE *buf, ULONG size)
  41. {
  42.     sprintf(buf, "end\nsize %ld\n", size);
  43. }
  44.  
  45.  
  46. STATIC UBYTE outdec(UBYTE *buf_source, UBYTE *buf_dest)
  47. {
  48.     buf_dest[0] = ENC( (buf_source[0] >> 2));
  49.     buf_dest[1] = ENC(((buf_source[0] << 4) & '\060' | (buf_source[1] >> 4) & '\017'));
  50.     buf_dest[2] = ENC(((buf_source[1] << 2) & '\074' | (buf_source[2] >> 6) & '\003'));
  51.     buf_dest[3] = ENC(( buf_source[2] & '\077'));
  52.  
  53.     return((UBYTE)((buf_source[0] + buf_source[1] + buf_source[2]) % SUMSIZE));
  54. }
  55.  
  56.  
  57. VOID uuencode(UBYTE *buf_source, UBYTE *buf_dest, UBYTE *temp, UBYTE len)
  58. {
  59.     UBYTE checksum, i, j;
  60.  
  61.     checksum = 0;
  62.     for(i=0, j=0; i<len; i+=3, j+=4)
  63.         checksum = (checksum + outdec(&buf_source[i], &temp[j])) % SUMSIZE;
  64.     temp[j] = '\0';
  65.  
  66.     sprintf(buf_dest, "%lc%s%lc\n", ENC(len), temp, ENC(checksum));
  67. }
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78. struct my_fgets_data {
  79.     ULONG inbuf;
  80.     ULONG bufpos;
  81. };
  82.  
  83.  
  84.  
  85.  
  86. STATIC UBYTE *my_fgets(struct XPR_IO *io, UBYTE *buf_dest, ULONG maxlen, UBYTE *buf_source, VOID *fp_source, struct my_fgets_data *myfgd)
  87. {
  88.     ULONG len, limit;
  89.     UBYTE *ptr;
  90.  
  91.     VOID kprintf(UBYTE *, ...);
  92.  
  93.  
  94.     if(myfgd->inbuf < maxlen)
  95.     {
  96.         if(myfgd->inbuf)
  97.             movmem(buf_source + myfgd->bufpos, buf_source, 1024 - myfgd->bufpos);
  98.  
  99.         myfgd->inbuf += io->xpr_fread(buf_source + myfgd->inbuf, 1, 1024 - myfgd->inbuf, fp_source);
  100.  
  101.         myfgd->bufpos = 0;
  102.  
  103.         buf_source[myfgd->inbuf] = '\0';
  104.     }
  105.  
  106.     if(myfgd->inbuf == 0)
  107.         return(NULL);
  108.  
  109.     ptr = buf_source + myfgd->bufpos;
  110.     len = 0;
  111.     for(;;)
  112.     {
  113.         len++;
  114.         if(ptr[0] == '\n'  ||  ptr[0] == '\r'  ||  ptr[0] == '\0')
  115.         {
  116.             if(ptr[1] == '\n'  ||  ptr[1] == '\r')
  117.                 len++;
  118.  
  119.             break;
  120.         }
  121.  
  122.         ptr++;
  123.     }
  124.  
  125.  
  126.     if(len == 0)
  127.         return(NULL);
  128.  
  129.     limit = (myfgd->inbuf > maxlen) ? maxlen : myfgd->inbuf;
  130.  
  131.     if(len > limit)
  132.         len = limit;
  133.  
  134.     memcpy(buf_dest, buf_source + myfgd->bufpos, len);
  135.  
  136.     buf_dest[len] = '\0';
  137.     myfgd->inbuf  -= len;
  138.     myfgd->bufpos += len;
  139.  
  140.     return(buf_dest);
  141. }
  142.  
  143.  
  144. STATIC VOID uudecode(struct XPR_IO *io, UBYTE *fileName, UBYTE *buf_source, UBYTE *buf_dest, VOID *fp_source, VOID *fp_dest, struct my_fgets_data *myfgd)
  145. {
  146.     ULONG line;
  147.     LONG n;
  148.     BOOL nosum=FALSE;
  149.     UBYTE *buf_destptr, *bp, c, checksum;
  150.  
  151.     for(line=0; ; line++)    /* for each input line */
  152.     {
  153.         if((buf_destptr = my_fgets(io, buf_dest, 80, buf_source, fp_source, myfgd)) == NULL)
  154.         {
  155.             upderr(io, "Input ended unexpectedly!");
  156.             return;
  157.         }
  158.  
  159.         for(n=0; n<79; n++)    /* search for first \r, \n or \0 */
  160.         {
  161.             if(buf_destptr[n]=='\r' || buf_destptr[n]=='\n' || buf_destptr[n]=='\0')
  162.                 break;
  163.         }
  164.  
  165.         for(; n<79; n++)        /* when found, fill rest of line with space */
  166.             buf_destptr[n] = ' ';
  167.  
  168.         buf_destptr[79] = '\0';        /* terminate new string */
  169.  
  170.         checksum = 0;
  171.         n = DEC(buf_destptr[0]);
  172.  
  173.         if(n <= 0)
  174.             break;                /* 0 bytes on a line??    Must be the last line */
  175.  
  176.         bp = &buf_destptr[1];
  177.  
  178.  
  179.         /* FOUR input characters go into each THREE output charcters */
  180.  
  181.         while(n >= 4)
  182.         {
  183.             c = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  184.             checksum += c;
  185.             *buf_destptr++ = c;
  186.  
  187.             c = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  188.             checksum += c;
  189.             *buf_destptr++ = c;
  190.  
  191.             c = DEC(bp[2]) << 6 | DEC(bp[3]);
  192.             checksum += c;
  193.             *buf_destptr++ = c;
  194.  
  195.             checksum = checksum % SUMSIZE;
  196.             bp += 4;
  197.             n -= 3;
  198.         }
  199.  
  200.         c = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  201.         checksum += c;
  202.         if(n >= 1)
  203.             *buf_destptr++ = c;
  204.  
  205.         c = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  206.         checksum += c;
  207.         if(n >= 2)
  208.             *buf_destptr++ = c;
  209.  
  210.         c = DEC(bp[2]) << 6 | DEC(bp[3]);
  211.         checksum += c;
  212.         if(n >= 3)
  213.             *buf_destptr++ = c;
  214.  
  215.         checksum = checksum % SUMSIZE;
  216.         bp += 4;
  217.         n -= 3;
  218.  
  219.       io->xpr_fwrite(buf_dest, 1, buf_destptr - buf_dest, fp_dest);
  220.  
  221.     /* The line has been decoded; now check that sum */
  222.  
  223.         nosum |= !isspace(*bp);
  224.         if(nosum)                    /* Is there a checksum at all?? */
  225.         {
  226.             if(checksum != DEC(*bp))    /* Does that checksum match? */
  227.                 upderr(io, "checksum mismatch decoding %s, line %ld.", fileName, line);
  228.         }
  229.     }
  230. }
  231.  
  232.  
  233. BOOL ProcessUUeFile(struct XPR_IO *io, UBYTE *buf_source, UBYTE *buf_dest, VOID *fp_source)
  234. {
  235.     struct XPR_UPDATE xpru;
  236.     struct my_fgets_data myfgd;
  237.     VOID *fp_dest=0;
  238.     LONG fileMode;        /* ignored.. */
  239.     BOOL thruLoop=FALSE;    /* Dejavu indicator */
  240.     BOOL success;
  241.     UBYTE *buf_destptr, fileName[34], msgBuf[80];
  242.  
  243.     success = TRUE;
  244.  
  245.     myfgd.inbuf = 0;
  246.     myfgd.bufpos= 0;
  247.  
  248.     /* Loop through file, searching for headers.  Decode anything with a
  249.        header, complain if there where no headers. */
  250.  
  251.  
  252.     for(;;)
  253.     {
  254.         xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  255.         xpru.xpru_msg        = "";
  256.         xpru.xpru_filename   = "";
  257.         io->xpr_update(&xpru);
  258.  
  259.  
  260.         for(;;)        /* search file for header line */
  261.         {
  262.             if((buf_destptr = my_fgets(io, buf_dest, 80, buf_source, fp_source, &myfgd)) == NULL)
  263.             {
  264.                 if(thruLoop == FALSE)
  265.                     upderr(io, "No `begin' line!");
  266.                 return(FALSE);
  267.             }
  268.  
  269.             if(strncmp(buf_destptr, "begin ", 6) == 0)
  270.                 break;
  271.         }
  272.  
  273.         sscanf(buf_destptr, "begin %o %s", &fileMode, fileName);
  274.  
  275. #if 0
  276.  
  277.         UBYTE *tmpptr;
  278.  
  279.     /*    sscanf()-replacement    */
  280.  
  281.         tmpptr = buf_destptr;        /* search file for file name */
  282.         while(iscntrl(tmpptr[1]) == FALSE)
  283.             tmpptr++;
  284.         tmpptr[1] = '\0';
  285.  
  286.         while(isspace(tmpptr[-1]) == FALSE)
  287.             tmpptr--;
  288.  
  289.         strcpy(fileName, tmpptr);
  290.  
  291. #endif
  292.         if((fp_dest = (void *)io->xpr_fopen(fileName, "w")) == NULL)        /* create output file */
  293.         {
  294.             upderr(io, "Cannot open output file `%s'", fileName);
  295.             success = FALSE;
  296.             break;
  297.         }
  298.  
  299.  
  300.         xpru.xpru_updatemask = XPRU_MSG | XPRU_FILENAME;
  301.         sprintf(msgBuf, "Starting uudecode %s", io->xpr_filename);
  302.         xpru.xpru_msg        = msgBuf;
  303.         xpru.xpru_filename   = fileName;
  304.         io->xpr_update(&xpru);
  305.  
  306.         uudecode(io, fileName, buf_source, buf_dest, fp_source, fp_dest, &myfgd);
  307.  
  308.         io->xpr_fclose(fp_dest);
  309.         fp_dest = NULL;
  310.  
  311.         if((buf_destptr = my_fgets(io, buf_dest, 80, buf_source, fp_source, &myfgd)) == NULL  ||
  312.                                 strncmp(buf_destptr, "end", 3))
  313.         {
  314.             success = FALSE;
  315.             upderr(io, "No `end' line");    /* don't be overly picky about newline ^ */
  316.             break;
  317.         }
  318.  
  319.         if(!((buf_destptr = my_fgets(io, buf_dest, 80, buf_source, fp_source, &myfgd)) == NULL  ||
  320.                                     strncmp(buf_destptr, "size ", 3)))
  321.         {
  322.             ULONG total, fileSize;
  323.  
  324.             total = io->xpr_finfo(fileName, 1);
  325.  
  326. /*
  327. **            sscanf()-replacement
  328. **            filesize = AtoL(&buf_destptr[5]);
  329. */
  330.  
  331.             sscanf(buf_destptr, "size %ld", &fileSize);
  332.             if(total != fileSize)
  333.             {
  334.                 success = FALSE;
  335.                 upderr(io, "Filesize error (should=%ld  is=%ld)", fileSize, total);
  336.                 break;
  337.             }
  338.         }
  339.         thruLoop = TRUE;
  340.     }
  341.  
  342.     if(fp_dest != NULL)
  343.         io->xpr_fclose(fp_dest);
  344.  
  345.     return(success);
  346. }
  347.  
  348.  
  349. /* end of source-code */
  350.