file:///d:/³ÌÐò×ÊÁÏ/format2/uuencode.txt

uuencode

uuencode is a utility designed to enable arbitrary binary files to be
transmitted using text-only media such as email. it does this by
encoding the files in such a way that the encoded file contains only
printable characters.
(important note: this file is the result of an afternoon's hacking by
myself. i make no guarantees as to its completeness and accuracy. i have
coded my own uuencode and uudecode programs which haven't let me down
yet)
the uuencode algorithm hinges around a 3-byte-to-4-byte  (8-bit to 6-bit
data) encoding to convert all data to printable characters. to perform
this encoding read in 3 bytes from the file to be encoded whose binary
representation is
  a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0 c7c6c5c4c3c2c1c0
and convert them into 4 bytes with values in the range 0-63 as follows:
  0 0 a7a6a5a4a3a2 0 0 a1a0b7b6b5b4 0 0 b3b2b1b0c7c6 0 0 c5c4c3c2c1c0
then convert these bytes to printable characters by adding 0x20 (32).
exception: if you end up with a zero byte it should be converted to 0x60
(back-quote '`') rather than 0x20 (space ' ').
so if you read 3 bytes from the file as follows: 14 0f a8 (hex) i.e.
  00010100 00001111 10101000
your 4 bytes output should be 25 60 5e 48 ("%`^h"). the intermediate 4
bytes in this case were
  00000101 00000000 00111110 00101000
note that the zero byte has been translated to 0x60 instead of 0x20. the
body of a uuencoded file therefore only contains the characters 0x21 '!'
to 0x60 '`', which are all printable and capable of being transmitted by
email.
(note: this of course means that uuencoded files are slightly more than
33% longer than the originals. uuencoding text-only files is redundant
and a silly thing to do. standard and sensible practice is to compress
the files first using a standard compression utility and then to
uuencode them).
in addition, the start of the encoding is marked by the line "start
<mode> <filename>", where
<mode> consists of 3 octal digits which are the unix mode of the file,
and
<filename> is the original filename of the file encoded.
the end of the encoding is marked by the line "end".
the first character of each line contains the line length in bytes *in
the original file*, encoded in the same way as an ordinary byte i.e.
line length 0->0x60, all other lengths add 0x20 to convert to printable
characters. line lengths vary from 0 to 45 (which encodes to 'm'; this
is why lines in a uuencoded file all start with an m), which is a line
length of 61 characters (including the length character) in the encoded
file. this is a nice safe length to transmit via email.
lines in the encoded file are always a multiple of 4 + 1 characters
long; this sometimes means that 1 or 2 bytes are thrown away at the end
of the decoding.
(note: i can't see any reason why lines shouldn't be an arbitrary
length, and don't know whether the proper definition disallows this.
i've never seen a uuencoded file where any line apart from the last one
wasn't 'm' followed by 60 characters, though)
to decode, simply perform the inverse of the encoding algorithm.
===== sample code =====
i include here the c source code to a small uuencode and uudecode
utility i coded myself. it isn't very sophisticated and probably not
very complete, but it does its job, and is very useful for my pc where i
don't have access to the standard unix stuff. it took me about half an
hour to write, and another hour or so to iron out the obvious bugs. it
works quite happily under dos (uuencoding needs practically no internal
storage). it isn't a great masterpiece of software design and coding,
but might be worth a look. feel free to do whatever you want to it, up
to and including throwing it in the bin.
===== uuencode.c =====
/*
* uuencode.c -
*  simple uuencode utility
*  jim cameron, 1997
*/
#include "stdio.h"
#include "stdlib.h"
#define max_linelen 45
#define encode_byte(b) (((b) == 0) ? 0x60 : ((b) + 0x20))
typedef unsigned char byte;
int main (int argc, char *argv [])
{
  file *infile	= null;
file *outfile = null;
int	linelen;
int linecnt;
byte inbuf [max_linelen];
byte *inbytep;
char outbuf [5];
  if (argc != 3)
{
fprintf (stderr, "syntax: uuencode <infile> <outfile>\n");
exit (1);
}
  /* try and open the input file (binary) */
  infile = fopen (argv [1], "rb");
if (infile == null)
{
fprintf (stderr, "uuencode: couldn't open input file %s\n", argv
[1]);
exit (1);
}
  /* try and open the output file (text) */
  outfile = fopen (argv [2], "wt");
if (outfile == null)
{
fprintf (stderr, "uuencode: couldn't open output file %s\n", argv
[2]);
exit (1);
}
  /* write the 'begin' line, giving it a mode of 0600 */
  fprintf (outfile, "begin 600 %s\n", argv [1]);
  do
{
    /* read a line from input file */
    linelen = fread (inbuf, 1, max_linelen, infile);
    /* write the line length byte */
    fputc (encode_byte (linelen), outfile);
    /* encode the line */
    for (linecnt = linelen, inbytep = inbuf;
linecnt > 0;
linecnt -= 3, inbytep += 3)
{
      /* encode 3 bytes from the input buffer */
      outbuf [0] = encode_byte ((inbytep [0] & 0xfc) >> 2);
outbuf [1] = encode_byte (((inbytep [0] & 0x03) << 4) +
((inbytep [1] & 0xf0) >> 4));
outbuf [2] = encode_byte (((inbytep [1] & 0x0f) << 2) +
((inbytep [2] & 0xc0) >> 6));
outbuf [3] = encode_byte (inbytep [2] & 0x3f);
outbuf [4] = '\0';
      /* write the 4 encoded bytes to the file */
      fprintf (outfile, "%s", outbuf);
    }
    fprintf (outfile, "\n");
  } while (linelen != 0);
  /* write the 'end' marker */
  fprintf (outfile, "end\n");
  /* tidy up and return */
  fclose (infile);
fclose (outfile);
  return 0;
}
===== uudecode.c =====
/*
* uudecode.c -
*  simple uudecode utility
*  jim cameron, 1997
*/
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* we all hate magic numbers! */
#define line_buf_size 256
/* decode a byte */
#define decode_byte(b) ((b == 0x60) ? 0 : b - 0x20)
typedef unsigned char byte;
int main (int argc, char *argv [])
{
  file *infile	= null;
file *outfile = null;
char linebuf [line_buf_size];
char *linep	= null;
char *tempcp	= null;
int   linelen	= 0;
int   linecnt	= 0;
char outfname [line_buf_size];
byte outbyte	[3];
  /* check that we have the right number of arguments */
  if (argc != 2)
{
fprintf (stderr, "syntax: uudecode <filename>\n");
exit (1);
}
  /* open the input file */
  infile = fopen (argv [1], "rt");
if (infile == null)
{
fprintf (stderr, "uudecode: couldn't open file %s\n", argv [1]);
exit (1);
}
  /* uu-encoded files always have a 'begin' marker, so go and look for
this */
  for (;;)
{
    /* read a line */
    if (fgets (linebuf, line_buf_size, infile) == null)
{
fprintf (stderr, "uudecode: not a valid uu-encoded file\n");
exit (1);
}
    /* see if it is the 'begin' marker */
    if ((strncmp (linebuf, "begin", 5) == 0) && isspace (linebuf [5]))
{
break;
}
  }
  /* if we have reached this point, we have found a begin marker */
  linep = linebuf + 5;
  /* next comes the mode, which we ignore */
  while (isspace (*linep))
{
linep++;
}
if (*linep == '\0')
{
fprintf (stderr, "uudecode: not a valid uu-encoded file\n");
exit (1);
}
  while (isdigit (*linep))
{
linep++;
}
while (isspace (*linep))
{
linep++;
}
if (*linep == '\0')
{
fprintf (stderr, "uudecode: not a valid uu-encoded file/n");
exit (1);
}
  /* the rest of the begin line is the output file name */
  strcpy (outfname, linep);
tempcp = outfname;
while (!isspace (*tempcp) && (*tempcp != '\0'))
{
tempcp++;
}
*tempcp = '\0';
  /* now open the output file */
  outfile = fopen (outfname, "wb");
if (outfile == null)
{
fprintf (stderr, "uudecode: couldn't open output file %s\n",
outfname);
exit (1);
}
  /* now for the uu-decode proper */
  do
{
    if (fgets (linebuf, line_buf_size, infile) == null)
{
fprintf (stderr, "uudecode: read error\n");
exit (1);
}
    /* the first byte of the line represents the length of the decoded
line */
    linelen = decode_byte (linebuf [0]);
linep = linebuf + 1;
for (linecnt = linelen; linecnt > 0; linecnt -= 3, linep += 4)
{
      /* check for premature end-of-line */
      if ((linep [0] == '\0') || (linep [1] == '\0') ||
(linep [2] == '\0') || (linep [3] == '\0'))
{
fprintf (stderr, "uudecode: error in encoded block\n");
exit (1);
}
      /* decode the 4-byte block */
      outbyte [0] = decode_byte (linep [0]);
outbyte [1] = decode_byte (linep [1]);
outbyte [0] <<= 2;
outbyte [0] |= (outbyte [1] >> 4) & 0x03;
outbyte [1] <<= 4;
outbyte [2] = decode_byte (linep [2]);
outbyte [1] |= (outbyte [2] >> 2) & 0x0f;
outbyte [2] <<= 6;
outbyte [2] |= decode_byte (linep [3]) & 0x3f;
      /* write the decoded bytes to the output file */
      if (linecnt > 3)
{
if (fwrite (outbyte, 1, 3, outfile) != 3)
{
fprintf (stderr, "uudecode: error writing to output file\n");
exit (1);
}
}
else
{
if (fwrite (outbyte, 1, linecnt, outfile) != linecnt)
{
fprintf (stderr, "uudecode: error writing to output file\n");
exit (1);
}
linecnt = 3;
}
    }
  } while (linelen != 0);
  /* all is ok, tidy up and exit */
  fclose (infile);
fclose (outfile);
  return 0;
}

jim
--
[email protected]

·µ»Ø