home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #20 / NN_1992_20.iso / spool / comp / sys / amiga / programm / 13133 < prev    next >
Encoding:
Text File  |  1992-09-08  |  12.6 KB  |  498 lines

  1. Path: sparky!uunet!gatech!bloom-beacon!eru.mt.luth.se!lunic!sunic!seunet!kullmar!piraya!overdose!Nikolai_Waldman
  2. From: Nikolai_Waldman@p27.f302.n901.z92.badnet.bad.se (Nikolai Waldman)
  3. Newsgroups: comp.sys.amiga.programmer
  4. Subject: UUENCODE and UUDECODE
  5. Message-ID: <OA92-901-302p27_143aeae7@piraya.bad.se>
  6. Date: 6 Sep 92 01:49:55 GMT
  7. References: <jorngh.6@dhhalden.no>
  8. Sender: BadNet@piraya.bad.se
  9. Reply-To: Nikolai_Waldman@p27.f302.n901.z92.badnet.bad.se (Nikolai Waldman)
  10. Organization: Nickname, Torsby, Sweden
  11. Lines: 484
  12. OD-Comment-To: Internet_Gateway
  13.  
  14. JORNGH@DHHALDEN.NO
  15.  
  16.  
  17. Hi JORN !
  18.  
  19. In a message of  5-Sep-92 you wrote:
  20.  
  21.  JGH> From: jorngh@dhhalden.no (JORN GUNNAR HALONEN)
  22.  
  23.  
  24.  JGH> I'm currently working on a project that needs to read/write UUDECODE
  25.  JGH> & TAR formats. Is there any documentation (or source code) available
  26.  JGH> that lets me program my own routines to support these formats ???
  27.  
  28. Here I send you the sourcecode for UUENCODE and UUDECODE
  29.  
  30. *********************
  31. *HERE COMES UUENCODE*
  32. *********************
  33.  
  34. /* #ifndef lint
  35. static char sccsid[] = "@(#)uuencode.c  5.3-1 (Berkeley) 1/22/85"; #endif */
  36.  
  37. /* Written by Mark Horton */
  38. /* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */ /*
  39. Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  40.    compatibility */
  41. /* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix a very
  42.    misleading error message on the Amiga port, enable CTRL-C for LATTICE,
  43.    and add a transparant file size trailer for later check. */
  44.  
  45. /*
  46.  * uuencode >outfile infile name
  47.  *
  48.  * Encode a file so it can be mailed to a remote system.  This version
  49.  * transparantly adds line checksums and a file size for sanity checks.
  50.  *
  51.  */
  52.  
  53. #ifdef AZTEC_C
  54. #include "no_wbparse.h"
  55. #endif
  56.  
  57. #include <stdio.h>
  58.  
  59. #ifdef AMIGA
  60. #define AMIGA_LATTICE           /* Set for Amiga Lattice C */ #define MCH_
  61. AMIGA#define MPU68000
  62. #endif
  63.  
  64. #ifdef unix
  65. #include <sys/types.h>
  66. #include <sys/stat.h>
  67. #endif
  68.  
  69. #define SUMSIZE 64  /* 6 bits */
  70. /* ENC is the basic 1 character encode function to make a char printing */ /* 
  71. Each output character represents 6 bits of input */ #define ENC(c) ((c) ? ((c) 
  72. & 077) + ' ': '`') long    totalsize=0;    /* Used to count the file size 
  73. because ftell() does
  74.                            not return sane results for pipes */
  75.  
  76. main(argc, argv)
  77. char **argv;
  78. {
  79.     FILE *in;
  80.     int mode;
  81. #ifdef unix
  82.     struct stat sbuf;
  83. #endif
  84. #ifdef AMIGA_LATTICE
  85.     extern int Enable_Abort;    /* Enable CTRL-C for Lattice */
  86.     Enable_Abort=1;
  87. #endif
  88.  
  89.         /* optional 1st argument */
  90.         if (argc > 2) {
  91.                 if ((in = fopen(argv[1], "r")) == NULL) {
  92.                         fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
  93.                         fprintf(stderr, "USAGE: uuencode >outfile infile 
  94. name\n");
  95.                         exit(10);
  96.                 }
  97.                 argv++; argc--;
  98.         } else
  99.                 in = stdin;
  100.  
  101.         if (argc != 2) {
  102.                 fprintf(stderr, "USAGE: uuencode >outfile infile name\n");
  103.                 exit(11);
  104.         }
  105.  
  106. #ifdef unix
  107.         /* figure out the input file mode */
  108.         fstat(fileno(in), &sbuf);
  109.         mode = sbuf.st_mode & 0777;
  110. #else
  111.         mode = 0644;        /* Default permissions */ #endif
  112.  
  113.         printf("\nbegin %o %s\n", mode, argv[1]);
  114.  
  115.         encode(in, stdout);
  116.  
  117.         printf("end\n");
  118.         printf("size %ld\n",totalsize);
  119.         exit(0);
  120. }
  121.  
  122. /*
  123.  * copy from in to out, encoding as you go along.
  124.  */
  125. encode(in, out)
  126. FILE *in;
  127. FILE *out;
  128. {
  129. #ifndef unix
  130. extern errno;
  131. #endif
  132.         char buf[80];
  133.         int i, n, checksum;
  134.  
  135.         for (;;) {
  136.                 /* 1 (up to) 45 character line */
  137.                 n = fr(in, buf, 45);
  138.                 putc(ENC(n), out);
  139.  
  140.                 checksum = 0;
  141.                 for (i=0; i<n; i += 3)
  142.                     checksum = (checksum+outdec(&buf[i], out)) % SUMSIZE;
  143.  
  144.                 putc(ENC(checksum), out);
  145.                 putc('\n', out);
  146.  
  147. #ifndef unix
  148.                 /* Error checking under UNIX?? You must be kidding! */
  149.                 if (errno) {
  150.                     fprintf(stderr, "ERROR: error writing to output\n");
  151.                         exit(12);
  152.                     }
  153. #endif
  154.                 if (n <= 0)
  155.                         break;
  156.         }
  157. }
  158.  
  159. /*
  160.  * output one group of 3 bytes, pointed at by p, on file f.
  161.  * return the checksum increment.
  162.  */
  163. int outdec(p, f)
  164. char *p;
  165. FILE *f;
  166. {
  167.         int c1, c2, c3, c4;
  168.  
  169.         c1 = *p >> 2;
  170.         c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
  171.         c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
  172.         c4 = p[2] & 077;
  173.         putc(ENC(c1), f);
  174.         putc(ENC(c2), f);
  175.         putc(ENC(c3), f);
  176.         putc(ENC(c4), f);
  177.  
  178.         return((p[0]+p[1]+p[2]) % SUMSIZE);
  179. }
  180.  
  181. /* fr: like read but stdio */
  182. int
  183. fr(fd, buf, cnt)
  184. FILE *fd;
  185. char *buf;
  186. int cnt;
  187. {
  188.         int c, i;
  189.  
  190.         for (i=0; i<cnt; i++) {
  191.                 c = getc(fd);
  192.                 if (c == EOF)
  193.                         return(i);
  194.                 totalsize++;
  195.                 buf[i] = c;
  196.         }
  197.         return (cnt);
  198. }
  199.  
  200. ***************************** 
  201. *AND NOW HERE COMES UUDECODE*
  202. *****************************
  203.  
  204. /* #ifndef lint
  205. static char sccsid[] = "@(#)uudecode.c  5.3-1 (Berkeley) 4/10/85"; #endif */
  206.  
  207. /* Written by Mark Horton */
  208. /* Modified by ajr (Alan J Rosenthatl,flaps@utcsri.UUCP) to use checksums */ /*
  209. Modified by fnf (Fred Fish,well!fnf) to use Keith Pyle's suggestion for
  210.    compatibility */
  211. /* Modified by bcn (Bryce Nesbitt,ucbvax!cogsci!bryce) to fix some very
  212.    misleading error messages on the Amiga port, to fix a bug that prevented
  213.    decoding certain files, to work even if trailing spaces have been
  214.    removed from a file, to check the filesize (if present), to add some
  215.    error checking, and to loop for multiple decodes from a single file.
  216.    Also kludged around a missing string function in Aztec C */
  217.  
  218. /*
  219.  * uudecode [input]
  220.  *
  221.  * Decode a file encoded with uuencode.
  222.  */
  223.  
  224. #ifdef AZTEC_C
  225. #include "no_wbparse.h"
  226. #endif
  227.  
  228. #include <stdio.h>
  229. #include <ctype.h>
  230.  
  231. #ifdef AMIGA
  232. #define AMIGA_LATTICE       /* Set for Amiga Lattice C */ #define MCH_AMIGA
  233. #define MPU68000
  234. #endif
  235.  
  236. #ifdef unix
  237. #include <pwd.h>
  238. #include <sys/types.h>
  239. #include <sys/stat.h>
  240. #endif
  241.  
  242. #define SUMSIZE 64
  243. #define DEC(c)  (((c) - ' ') & 077)    /* single character decode */
  244.  
  245. main(argc, argv)
  246. char **argv;
  247. {
  248. FILE    *in, *out;
  249. int     through_loop=0; /* Dejavu indicator */ int     mode;           /* file'
  250. s mode (from header) */ long    filesize;       /* theoretical file size (from 
  251. header) */ char    dest[128];
  252. char    buf[80];
  253.  
  254. #ifdef AMIGA_LATTICE
  255. extern  int Enable_Abort;
  256.         Enable_Abort=1;
  257. #endif
  258.  
  259.     /* A filename can be specified to be uudecoded, or nothing can
  260.     be specified, and the input will come from STDIN */
  261.  
  262.     switch (argc)
  263.         {
  264.         case 1:
  265.         in=stdin;
  266.         break;
  267.  
  268.         case 2:
  269.         if ((in = fopen(argv[1], "r")) == NULL)
  270.             {
  271.             fprintf(stderr, "ERROR: can't find %s\n", argv[1]);
  272.             fprintf(stderr, "USAGE: uudecode [infile]\n");
  273.             exit(10);
  274.             }
  275.         break;
  276.  
  277.         default:
  278.         fprintf(stderr, "USAGE: uudecode [infile]\n");
  279.         exit(11);
  280.         break;
  281.         }
  282.  
  283.     /* Loop through file, searching for headers.  Decode anything with a
  284.        header, complain if there where no headers. */
  285.  
  286. for (;;)
  287. {
  288.     /* search file for header line */
  289.     for (;;)
  290.         {
  291.         if (fgets(buf, sizeof buf, in) == NULL)
  292.             {
  293.             if (!through_loop)
  294.                 {
  295.                 fprintf(stderr, "ERROR: no `begin' line!\n");
  296.                 exit(12);
  297.                 }
  298.             else
  299.                 {
  300.                 exit(0);
  301.                 }
  302.             }
  303.         if (strncmp(buf, "begin ", 6) == 0)
  304.             break;
  305.         }
  306.     sscanf(buf, "begin %o %s", &mode, dest);
  307.  
  308. #ifdef unix
  309.     /* handle ~user/file format */
  310.     if (dest[0] == '~')
  311.         {
  312.         char *sl;
  313.         struct passwd *getpwnam();
  314.         char *index();
  315.         struct passwd *user;
  316.         char dnbuf[100];
  317.  
  318.         sl = index(dest, '/');
  319.         if (sl == NULL)
  320.             {
  321.             fprintf(stderr, "Illegal ~user\n");
  322.                 exit(13);
  323.             }
  324.         *sl++ = 0;
  325.         user = getpwnam(dest+1);
  326.         if (user == NULL)
  327.             {
  328.             fprintf(stderr, "No such user as %s\n", dest);
  329.             exit(14);
  330.             }
  331.         strcpy(dnbuf, user->pw_dir);
  332.         strcat(dnbuf, "/");
  333.         strcat(dnbuf, sl);
  334.         strcpy(dest, dnbuf);
  335.         }
  336. #endif
  337.  
  338.     /* create output file */
  339.     printf("UuDecoding to file %s\n",dest);
  340.     if ((out = fopen(dest, "w")) == NULL)
  341.         {
  342.         fprintf(stderr, "ERROR: can't open output file %s\n", dest);
  343.         exit(15);
  344.         }
  345. #ifdef unix
  346.     chmod(dest, mode);
  347. #endif
  348.  
  349.     decode(in, out, dest);
  350.  
  351.     if (fgets(buf, sizeof buf, in) == NULL || strncmp(buf,"end",3))
  352.         {              /* don't be overly picky about newline ^ */
  353.         fprintf(stderr, "ERROR: no `end' line\n");
  354.         exit(16);
  355.         }
  356.  
  357.     if (!(fgets(buf,sizeof buf,in) == NULL || strncmp(buf,"size ",3)))
  358.         {
  359.         sscanf(buf, "size %ld", &filesize);
  360.         if (ftell(out) != filesize)
  361.             {
  362.             fprintf(stderr, "ERROR: file should have been %ld bytes long but 
  363. was %ld.\n", filesize, ftell(out));
  364.             exit(17);
  365.             }
  366.         }
  367.     through_loop = 1;
  368. }   /* forever */
  369. }   /* main */
  370.  
  371. /*
  372.  * Copy from in to out, decoding as you go.
  373.  * If a return or newline is encountered too early in a line, it is
  374.  * assumed that means that some editor has truncated trailing spaces.
  375.  */
  376. decode(in, out, dest)
  377. FILE *in;
  378. FILE *out;
  379. char *dest;
  380. {
  381. char buf[80];
  382. char *bp;
  383. int nosum=0;
  384. #ifndef unix
  385. extern errno;
  386. #endif
  387. register int j;
  388. register int n;
  389. int checksum, line;
  390.  
  391.     for (line = 1; ; line++)    /* for each input line */
  392.         {
  393.         if (fgets(buf, sizeof buf, in) == NULL)
  394.             {
  395.             fprintf(stderr, "ERROR: input ended unexpectedly!\n");
  396.             exit(18);
  397.             }
  398.  
  399.         /* Pad end of lines in case some editor truncated trailing
  400.            spaces */
  401.  
  402.         for (n=0;n<79;n++)  /* search for first \r, \n or \000 */
  403.             {
  404.             if(buf[n]=='\r'||buf[n]=='\n'||buf[n]=='\000')
  405.                 break;
  406.             }
  407.         for (;n<79;n++)     /* when found, fill rest of line with space */
  408.             {
  409.             buf[n]=' ';
  410.             }
  411.         buf[79]=0;          /* terminate new string */
  412.  
  413.         checksum = 0;
  414.         n = DEC(buf[0]);
  415.         if (n <= 0)
  416.             break;      /* 0 bytes on a line??  Must be the last line */
  417.  
  418.         bp = &buf[1];
  419.  
  420.         /* FOUR input characters go into each THREE output charcters */
  421.  
  422.         while (n >= 4)
  423.             {
  424.             j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4; putc(j, out); checksum += j;
  425.             j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2; putc(j, out); checksum += j;
  426.             j = DEC(bp[2]) << 6 | DEC(bp[3]);      putc(j, out); checksum += j;
  427.             checksum = checksum % SUMSIZE;
  428.             bp += 4;
  429.             n -= 3;
  430.             }
  431.  
  432.             j = DEC(bp[0]) << 2 | DEC(bp[1]) >> 4;
  433.                 checksum += j;
  434.                 if (n >= 1)
  435.                     putc(j, out);
  436.             j = DEC(bp[1]) << 4 | DEC(bp[2]) >> 2;
  437.                 checksum += j;
  438.                 if (n >= 2)
  439.                     putc(j, out);
  440.             j = DEC(bp[2]) << 6 | DEC(bp[3]);
  441.                 checksum += j;
  442.                 if (n >= 3)
  443.                     putc(j, out);
  444.             checksum = checksum % SUMSIZE;
  445.             bp += 4;
  446.             n -= 3;
  447.  
  448. #ifndef unix
  449.          /* Error checking under UNIX??? You must be kidding... */
  450.          /* Check if an error occured while writing to that last line */
  451.         if (errno)
  452.             {
  453.             fprintf(stderr, "ERROR: error writing to %s\n",dest);
  454.             exit(19);
  455.             }
  456. #endif
  457.  
  458.         /* The line has been decoded; now check that sum */
  459.  
  460.         nosum |= !isspace(*bp);
  461.         if (nosum)                      /* Is there a checksum at all?? */
  462.             {
  463.             if (checksum != DEC(*bp))   /* Does that checksum match? */
  464.                 {
  465.                 fprintf(stderr, "ERROR: checksum mismatch decoding %s, line %d.
  466. \n",dest, line);
  467.                 }
  468.             }   /* sum */
  469.     }   /* line */
  470. }   /* function */
  471.  
  472. #ifdef unix
  473. /*
  474.  * Return the ptr in sp at which the character c appears;
  475.  * 0 if not found
  476.  */
  477. char *
  478. index(sp, c)
  479. register char *sp, c;
  480. {
  481.     do
  482.         {
  483.         if (*sp == c)
  484.             return(sp);
  485.         }
  486.     while (*sp++);
  487.  
  488.     return(0);
  489. }
  490. #endif unix
  491.  
  492. I hope this will help you!
  493.  
  494. Regards Nikolai
  495. Fido-Net: 2:203/602.27
  496. Internet: Nikolai_Waldman@p27.f302.n902.z92.badnet.bad.se
  497. ---
  498.