Everhart,Glenn
From:	Shane F. Smith [SFS@alphie.healthnet.com]
Sent:	Tuesday, May 05, 1998 7:12 PM
To:	Info-VAX@Mvb.Saic.Com
Subject:	RE: File attach with MAIL

--Boundary_(ID_D8L58ay8nwyarEwl+JZR8g)
Content-type: TEXT/PLAIN

> Hello!
>
> We have a client who uses VMS and is trying to send us PKZIP files
> that were created with a VMS version of zip.
>
> What is the best way to send these zip files through internet email?
> Is there a uuencode or equivalent?  Sorry if this is a basic question
> but I have zero VMS experience and don't even know where to begin...
>
> Thanks!
> Mark Lehrer

You'll find C sources for uuencode/uudecode and base 64 encode/decode after
my mailsig. I hope you find them useful.

 #####   ---------------------------------------------------------------
#-O-O-# | shane dot smith at earthling dot net, spam to abuse@127.0.0.1 |
#  L  #  ---------------------------------------------------------------
 #===#   Don't blame HealthNet for anything I say. They're innocent.
  ###    Bob Palmer for C.E.O of Microsoft!

----------------------------snip-here--------------------------
/*
 * Uuencode -- encode a file so that it's printable ascii, short lines
 *
 * Slightly modified by SFS to eliminate compilation warnings
 * and use ANSII standard function declarations.
 */

#include "stdio.h"
#include "stdlib.h"
#include "errno.h"

void encode( FILE *in, FILE *out );
void outdec( char *p, FILE *f );
int  fr( FILE *fd, char *buf, int cnt);

char *progname = "uuencode";

#define USAGE "Usage: uuencode file [outfile]\n"

/* ENC is the basic 1 character encoding function to make a char printable */

#define ENC(c) (((c) & 077) + ' ')

int main( int argc, char *argv[] )
{
	FILE *in, *out; int mode;
	if (argc < 2)
	{
		fprintf(stderr, USAGE);
		exit(2);
	}
	in = fopen(argv[1], "r");
	if  (argc < 3)
	{
		if ((out = stdout) == NULL)
		{
			fprintf(stderr, "No output specified, no STDOUT." );
			exit(2);
		}
	}
	else
		out = fopen(argv[2], "w");

	if  (out == NULL) 
	{
	    perror("uuencode");
	    exit(1);
	}

	fprintf(out, "begin %o %s\n", 0777, argv[1]);
	encode(in, out);
	fprintf(out, "end\n");
	fclose(out);
}

/*
 * copy from in to out, encoding as you go along.
 */

void encode( FILE *in, FILE *out )
{
	char buf[80];
	int i, n;
	for (;;)
	{
		n = fr(in, buf, 45);
		fputc(ENC(n), out);
		for (i=0; i<n; i += 3)
			outdec(&buf[i], out);
		fputc('\n', out);
		if (n <= 0)
			break;
	}
}

/*
 * output one group of 3 bytes, pointed at by p, on file f.
 */

void outdec( char *p, FILE *f )
{
	int c1, c2, c3, c4;
	c1 = *p >> 2;
	c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
	c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
	c4 = p[2] & 077;
	fputc(ENC(c1), f);
	fputc(ENC(c2), f);
	fputc(ENC(c3), f);
	fputc(ENC(c4), f);
}

/*
 * fr: like read but stdio
 */

int fr( FILE *fd, char *buf, int cnt)
{
	int c, i;
	for (i = 0; i < cnt; i++)
	{
		c = fgetc(fd);
		if (c == EOF)
			return(i);
		buf[i] = c;
	}
	return (cnt);
}
----------------------------snip-here--------------------------
/*
 * Uudecode -- decode a uuencoded file back to binary form.
 *
 * Slightly modified by SFS to eliminate compilation warnings
 * and use ANSII standard function declarations.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

char *progname = "UUDECODE";

#define USAGE "Usage: UUDECODE [file]\n"

void decode( FILE *in, FILE *out );
void outdec( char *p, FILE *f, int n );
int fr( FILE *fd, char *buf, int cnt );

/* single character decode */
#define DEC(c)	(((c) - ' ') & 077)

main( int argc, char *argv[] )
{
	static  FILE *in, *out;
	int mode;
	char dest[128];
	char buf[80];
	/* optional input arg */
	if (argc > 1)
	{
		in = fopen(argv[1], "r");
		argv++; argc--;
	}
	else
		in = stdin;
	if (argc != 1)
	{
		fprintf(stderr, USAGE);
		exit(2);
	}

	/* search for header line */
	for (;;)
	{
		if (fgets(buf, sizeof buf, in) == NULL)
		{
			fprintf(stderr, "No begin line\n");
			exit(3);
		}
		if (strncmp(buf, "begin ", 6) == 0)
			break;
	}
	sscanf(buf, "begin %o %s", &mode, dest);
	out = fopen(dest, "w", "alq=300", "deq=100");  /* create output file */
	decode(in, out);
	fclose(out);
	if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n"))
	{
		fprintf(stderr, "No end line\n");
		exit(5);
	}
}

/*
 * copy from in to out, decoding as you go along.
 */

void decode( FILE *in, FILE *out )
{
	char buf[80];
	char *bp;
	int n;
	for (;;)
	{
		if (fgets(buf, sizeof buf, in) == NULL)
		{
			fprintf(stderr, "Short file\n");
			break;
		}
		n = DEC(buf[0]);
		if (n <= 0)
			break;
		bp = &buf[1];
		while (n > 0)
		{
			outdec(bp, out, n);
			bp += 4;
			n -= 3;
		}
	}
}

/*
 * output a group of 3 bytes (4 input characters).
 * the input chars are pointed to by p, they are to
 * be output to file f.  n is used to tell us not to
 * output all of them at the end of the file.
 */

void outdec( char *p, FILE *f, int n )
{
	int c1, c2, c3;
	c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
	c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
	c3 = DEC(p[2]) << 6 | DEC(p[3]);
	if (n >= 1)
		putc(c1, f);
	if (n >= 2)
		putc(c2, f);
	if (n >= 3)
		putc(c3, f);
}


/* fr: like read but stdio */

int fr( FILE *fd, char *buf, int cnt )
{
	int c, i;
	for (i = 0; i < cnt; i++)
	{
		c = getc(fd);
		if (c == EOF)
			return(i);
		buf[i] = c;
	}
	return (cnt);
}

/* If your library already has this function, use it and nuke the code below */

#ifdef noindex
/*
 * Return the ptr in sp at which the character c appears;
 * NULL if not found
 */

char *index( register char *sp, char c )
{
	do
	{
		if (*sp == c)
			return(sp);
	} while (*sp++);
	return(NULL);
}
#endif

----------------------------snip-here--------------------------
/*
 * b64_encode.c
 */

#include <stdlib.h>
#include <stdio.h>

#define	MAXLINELEN	76

static const char	b64chars[] = 
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/*   0000000000000000111111111111111122222222222222223333333333333333	*/
/*   0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF	*/

main( int argc, char *argv[] )
{
    FILE	*fin;
    FILE	*fout;
    int		octet;
    int		temp = 0;
    int		bits = 0;
    int		linelen = 0;

    if( argc < 2 ) {
	fprintf( stderr, "Usage: b64encode <infile> [outfile]\n" );
	exit( EXIT_SUCCESS );
    }

    fin = fopen( argv[1], "rb" );
    if( fin == NULL ) {
	perror( "openin" );
	exit( EXIT_FAILURE );
    }

    if( argc < 3 )
	fout = stdout;
    else {
	fout = fopen( argv[2], "w" );
	if( fout == NULL ) {
	    perror( "openout" );
	    fclose( fin );
	    exit( EXIT_FAILURE );
	}
    }

    while( (octet = fgetc( fin )) != EOF ) {
	temp <<= 8;
	temp |= 0xff & octet;
	bits += 8;
	while( bits >= 6 ) {
	    bits -= 6;
	    fputc( b64chars[ 0x3f & (temp >> bits) ], fout );
	    if( ++linelen >= MAXLINELEN ) {
		fputc( '\n', fout );
		linelen = 0;
	    }
	}
    }
    if( bits > 0 ) {
	temp <<= 6 - bits;
	fputc( b64chars[ 0x3f & temp ], fout );
	if( bits == 4 )
	    fputc( '=', fout );
	else if( bits == 2 ) {
	    fputc( '=', fout );
	    fputc( '=', fout );
	}
	fputc( '\n', fout );
    }

    fclose( fout );
    fclose( fin );
    exit( EXIT_SUCCESS );
}
----------------------------snip-here--------------------------
/*
 * b64_decode.c
 */

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>

int decode_b64char( int ch )
{
    int		sextet;

    if( ('A' <= ch) && (ch <= 'Z') )
	sextet = ch - 'A';
    else if( ('a' <= ch) && (ch <= 'z') )
	sextet = (ch - 'a') + 26;
    else if( ('0' <= ch) && (ch <= '9') )
	sextet = (ch - '0') + 52;
    else if( ch == '+' )
	sextet = 62;
    else if( ch == '/' )
	sextet = 63;
    else {
	fprintf( stderr, (isprint(ch) ? "Illegal base64 character '%c'\n" :
					"Illegal base64 character 0x%02x\n"),
		 ch );
	exit( EXIT_FAILURE );
    }

    return( sextet );
}


main( int argc, char *argv[] )
{
    FILE	*fin;
    FILE	*fout;
    int		flushing = 0;
    int		temp = 0;
    int		bits = 0;
    int		ch;

    if( argc < 2 ) {
	fprintf( stderr, "Usage: b64decode <infile> [outfile]\n" );
	exit( EXIT_SUCCESS );
    }

    fin = fopen( argv[1], "r" );
    if( fin == NULL ) {
	perror( "openin" );
	exit( EXIT_FAILURE );
    }

    if( argc < 3 )
	fout = stdout;
    else {
	fout = fopen( argv[2], "wb" );
	if( fout == NULL ) {
	    perror( "openout" );
	    fclose( fin );
	    exit( EXIT_FAILURE );
	}
    }

    while( (ch = fgetc( fin )) != EOF ) {
	if( !isspace(ch) ) {
	    if( flushing ) {
		if( ch != '=' ) {
		    fprintf( stderr, "Illegal character in EOF padding\n" );
		    exit( EXIT_FAILURE );
		}
	    }
	    else {
		if( ch == '=' )
		    flushing = 1;
		else {
		    temp <<= 6;
		    temp |= decode_b64char( ch );
		    bits += 6;
		    if( bits >= 8 ) {
			bits -= 8;
			fputc( (0xff & (temp >> bits)), fout );
		    }
		}
	    }
	}
    }

    fclose( fout );
    fclose( fin );
}
----------------------------snip-here--------------------------


--Boundary_(ID_D8L58ay8nwyarEwl+JZR8g)--