From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 16-AUG-1989 15:43
To:	MRGATE::"ARISIA::EVERHART"
Subj:	UUENCODE/UUDECODE for VMS

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Wed, 16 AUG 89 11:44:43 PDT
Received: from asd.wpafb.af.mil (UAP2.CDS.WPAFB.AF.MIL) by KL.SRI.COM with TCP; Wed, 16 Aug 89 11:12:25 PDT
Message-Id: <143326.8908161810@asd.wpafb.af.mil>
Received:  by asd.wpafb.af.mil (5.61/UK-1.4a)
	ASD Central Datacomm System
	id AA143326; Wed, 16 Aug 89 14:10:47 -0400
Date: Wed Aug 16 14:10:37 1989
From: akeef@asd.wpafb.af.mil ( Earle Ake)
Subject: UUENCODE/UUDECODE for VMS
To: info-vax@kl.sri.com
Status:  N 

	A lot of people have asked me for the sources to UUENCODE/UUDECODE
that run under VMS.  Here it is.

Earle Ake
akeef@asd.wpafb.af.mil

$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.1-004  3-AUG-1989
$!   On 16-AUG-1989 14:00:21.12   By user FAC2 (Earle Ake - SAIC)
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. UUDECODE.C;1
$!       2. UUENCODE.C;1
$!       3. UUENCDEC.DOC;1
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ if f$getsyi("version") .ges. "V4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete/nolog 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete/nolog 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");
buff:=CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(buff))
;LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(buff));g:=0;LOOP EXITIF MARK(NONE)=END_OF(buff);x:=
ERASE_CHARACTER(1);IF g = 0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x=
"V" THEN APPEND_LINE;MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;
IF x="+" THEN g:=1;ERASE_LINE;ENDIF;ELSE IF x="-" THEN g:=0;ENDIF;ERASE_LINE;
ENDIF;ENDLOOP;p:="`";POSITION(BEGINNING_OF(buff));LOOP r:=SEARCH(p,FORWARD);
EXITIF r=0;POSITION(r);ERASE(r);COPY_TEXT(ASCII(INT(ERASE_CHARACTER(3))));
ENDLOOP;o:=GET_INFO(COMMAND_LINE,"output_file");WRITE_FILE(buff,o);
ENDPROCEDURE;Unpacker;EXIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create/nolog 'f'
X/*
X * uudecode `091input`093
X *
X * if input not specified, get input from stdin
X *
X * Create the specified file, decoding as you go.
X * Used with uuencode.
X *
X * Modified for use with Microsoft C and VAX/VMS. `032
X * Define CI86 symbol to use with CI86.
X */
X#ifndef VMS
X#include <stdio.h>
X#ifndef MSDOS
X#include <pwd.h>
X#endif`009`009/* ifndef MSDOS */
X#ifndef CI86
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X#else`009`009/* ifndef VMS */
X#include stdio
X#include types
X#include stat
X#endif`009`009/* ifndef VMS */
X
X/* single character decode */
X#define DEC(c)`009(((c) - ' ') & 077)
X
Xmain(argc, argv)
Xchar **argv;
X`123
X`009FILE *in, *out;
X#ifndef`009CI86
X`009struct stat sbuf;
X#endif
X`009int mode;
X`009char dest`091128`093;
X`009char buf`09180`093;
X
X`009/* optional input arg */
X`009if (argc > 1) `123
X`009`009if ((in = fopen(argv`0911`093, "r")) == NULL) `123
X`009`009`009perror(argv`0911`093);
X`009`009`009exit(1);
X`009`009`125
X`009`009argv++; argc--;
X`009`125 else
X`009`009in = stdin;
X
X`009if (argc != 1) `123
X`009`009fprintf(stderr, "Usage: uudecode `091infile`093\n");
X`009`009exit(2);
X`009`125
X
X`009/* search for header line */
X`009for (;;) `123
X`009`009if (fgets(buf, sizeof buf, in) == NULL) `123
X`009`009`009fprintf(stderr, "No begin line\n");
X`009`009`009exit(3);
X`009`009`125
X`009`009if (strncmp(buf, "begin ", 6) == 0)
X`009`009`009break;
X`009`125
X`009sscanf(buf, "begin %o %s", &mode, dest);
X
X`009/* handle `126user/file format */
X#ifndef MSDOS
X#ifndef VMS
X`009if (dest`0910`093 == '`126') `123
X`009`009char *sl;
X`009`009struct passwd *getpwnam();
X`009`009char *index();
X`009`009struct passwd *user;
X`009`009char dnbuf`091100`093;
X
X`009`009sl = index(dest, '/');
X`009`009if (sl == NULL) `123
X`009`009`009fprintf(stderr, "Illegal `126user\n");
X`009`009`009exit(3);
X`009`009`125
X`009`009*sl++ = 0;
X`009`009user = getpwnam(dest+1);
X`009`009if (user == NULL) `123
X`009`009`009fprintf(stderr, "No such user as %s\n", dest);
X`009`009`009exit(4);
X`009`009`125
X`009`009strcpy(dnbuf, user->pw_dir);
X`009`009strcat(dnbuf, "/");
X`009`009strcat(dnbuf, sl);
X`009`009strcpy(dest, dnbuf);
X`009`125
X#endif`009/* ifndef VMS */
X#endif`009/* ifndef MSDOS */
X
X`009/* create output file */
X#ifdef MSDOS
X`009/* binary output file */
X`009out = fopen(dest, "wb");
X#else
X#ifdef VMS
X`009out = fopen(dest, "w", "rfm=var");
X#else
X`009out = fopen(dest, "w");
X#endif`009/* ifdef VMS */
X#endif`009/* ifdef MSDOS */
X`009if (out == NULL) `123
X`009`009perror(dest);
X`009`009exit(4);
X`009`125
X#ifndef`009CI86
X`009chmod(dest, mode);
X#endif
X
X`009decode(in, out);
X
X`009if (fgets(buf, sizeof buf, in) == NULL `124`124 strcmp(buf, "end\n")) `1
V23
X`009`009fprintf(stderr, "No end line\n");
X`009`009exit(5);
X`009`125
X#ifndef VMS
X`009exit(0);
X#else
X`009exit(1);`009/* VMS successful */
X#endif
X`125
X
X/*
X * copy from in to out, decoding as you go along.
X */
Xdecode(in, out)
XFILE *in;
XFILE *out;
X`123
X`009char buf`09180`093;
X`009char *bp;
X`009int n;
X
X`009for (;;) `123
X`009`009/* for each input line */
X`009`009if (fgets(buf, sizeof buf, in) == NULL) `123
X`009`009`009fprintf(stderr, "Short file\n");
X`009`009`009exit(10);
X`009`009`125
X`009`009n = DEC(buf`0910`093);
X`009`009if (n <= 0)
X`009`009`009break;
X
X`009`009bp = &buf`0911`093;
X`009`009while (n > 0) `123
X`009`009`009outdec(bp, out, n);
X`009`009`009bp += 4;
X`009`009`009n -= 3;
X`009`009`125
X`009`125
X`125
X
X/*
X * output a group of 3 bytes (4 input characters).
X * the input chars are pointed to by p, they are to
X * be output to file f.  n is used to tell us not to
X * output all of them at the end of the file.
X */
Xoutdec(p, f, n)
Xchar *p;
XFILE *f;
X`123
X`009int c1, c2, c3;
X
X`009c1 = DEC(*p) << 2 `124 DEC(p`0911`093) >> 4;
X`009c2 = DEC(p`0911`093) << 4 `124 DEC(p`0912`093) >> 2;
X`009c3 = DEC(p`0912`093) << 6 `124 DEC(p`0913`093);
X`009if (n >= 1)
X`009`009putc(c1, f);
X`009if (n >= 2)
X`009`009putc(c2, f);
X`009if (n >= 3)
X`009`009putc(c3, f);
X`125
X
X
X/* fr: like read but stdio */
Xint
Xfr(fd, buf, cnt)
XFILE *fd;
Xchar *buf;
Xint cnt;
X`123
X`009int c, i;
X
X`009for (i=0; i<cnt; i++) `123
X`009`009c = getc(fd);
X`009`009if (c == EOF)
X`009`009`009return(i);
X`009`009buf`091i`093 = c;
X`009`125
X`009return (cnt);
X`125
X
X/*
X * Return the ptr in sp at which the character c appears;
X * NULL if not found
X */
X
X#define`009NULL`0090
X
Xchar *
Xindex(sp, c)
Xregister char *sp, c;
X`123
X`009do `123
X`009`009if (*sp == c)
X`009`009`009return(sp);
X`009`125 while (*sp++);
X`009return(NULL);
X`125
$ CALL UNPACK UUDECODE.C;1 845387361
$ create/nolog 'f'
X/*
X * uuencode `091input `091output`093 `093
X *
X * if output not specified, output to stdout
X * if input not specified, input from stdin
X *
X * Encode a file so it can be mailed to a remote system.
X *
X * Modified for use with Microsoft C and VAX/VMS. `032
X * Define CI86 symbol to use with CI86.
X */
X#ifndef VMS
X#include <stdio.h>
X#ifndef`009CI86
X#include <sys/types.h>
X#include <sys/stat.h>
X#endif
X#else`009/* ifndef VMS */
X#include stdio
X#include types
X#include stat
X#endif`009/* ifndef VMS */
X
X/* ENC is the basic 1 character encoding function to make a char printing */
X#define ENC(c) (((c) & 077) + ' ')
X
Xmain(argc, argv)
Xchar **argv;
X`123
X`009FILE *in, *out;
X#ifndef`009CI86
X`009struct stat sbuf;
X#endif
X`009int mode;
X
X`009/* if 3 arguments, then output file specified */
X`009if (argc > 2) `123
X`009`009if ((out = fopen(argv`0912`093, "w")) == NULL) `123
X`009    `009`009perror(argv`0912`093);
X`009`009`009exit(3);
X`009`009`125
X`009`009argc--;
X`009`125
X`009else
X`009`009out = stdout;
X`009if (argc > 1) `123
X#ifdef`009MSDOS
X`009`009/* Use binary mode */
X`009`009if ((in = fopen(argv`0911`093, "rb")) == NULL) `123
X#else
X`009`009if ((in = fopen(argv`0911`093, "r")) == NULL) `123
X#endif
X`009`009`009perror(argv`0911`093);
X`009`009`009exit(1);
X`009`009`125
X`009`009argc--;
X`009`125 else
X`009`009in = stdin;
X
X`009if (argc != 1) `123
X`009`009fprintf(stderr,"Usage: uuencode `091infile `091outfile`093 `093\n");
X`009`009exit(2);
X`009`125
X
X#ifndef`009CI86
X`009/* figure out the input file mode */
X`009fstat(fileno(in), &sbuf);
X`009mode = sbuf.st_mode & 0777;
X#else
X`009mode = 0;  /* default to normal mode */
X#endif
X`009fprintf(out,"begin %o %s\n", mode, argv`0911`093);
X
X`009encode(in, out);
X
X`009fprintf(out,"end\n");
X#ifndef VMS
X`009exit(0);
X#else
X`009exit(1);`009/* VMS successful */
X#endif
X`125
X
X/*
X * copy from in to out, encoding as you go along.
X */
Xencode(in, out)
XFILE *in;
XFILE *out;
X`123
X`009char buf`09180`093;
X`009int i, n;
X
X`009for (;;) `123
X`009`009/* 1 (up to) 45 character line */
X`009`009n = fr(in, buf, 45);
X`009`009putc(ENC(n), out);
X
X`009`009for (i=0; i<n; i += 3)
X`009`009`009outdec(&buf`091i`093, out);
X
X`009`009putc('\n', out);
X`009`009if (n <= 0)
X`009`009`009break;
X`009`125
X`125
X
X/*
X * output one group of 3 bytes, pointed at by p, on file f.
X */
Xoutdec(p, f)
Xchar *p;
XFILE *f;
X`123
X`009int c1, c2, c3, c4;
X
X`009c1 = *p >> 2;
X`009c2 = (*p << 4) & 060 `124 (p`0911`093 >> 4) & 017;
X`009c3 = (p`0911`093 << 2) & 074 `124 (p`0912`093 >> 6) & 03;
X`009c4 = p`0912`093 & 077;
X`009putc(ENC(c1), f);
X`009putc(ENC(c2), f);
X`009putc(ENC(c3), f);
X`009putc(ENC(c4), f);
X`125
X
X/* fr: like read but stdio */
Xint
Xfr(fd, buf, cnt)
XFILE *fd;
Xchar *buf;
Xint cnt;
X`123
X`009int c, i;
X
X`009for (i=0; i<cnt; i++) `123
X`009`009c = getc(fd);
X`009`009if (c == EOF)
X`009`009`009return(i);
X`009`009buf`091i`093 = c;
X`009`125
X`009return (cnt);
X`125
$ CALL UNPACK UUENCODE.C;1 1379740328
$ create/nolog 'f'
XModified once more to compile with Microsoft C V3.00, and VAX/VMS.
XThe CI86 code is still there, surrounded with #ifdef CI86...#endif
X
XUsage is:
X`009uuencode `091input `091output`093 `093
X`009`009if output not specified, write to stdout
X`009`009if input not specified, get input from stdin
X`009uudecode `091input`093
X`009`009if input not specified, get input from stdin
X
XWARNING: Current restriction on VAX/VMS:  ASCII text files get
Xall CR/LF combinations converted to LF only during UUENCODE.
XThis should not be a major problem, as ASCII text files should
Xnot need to be "encoded".
X
XAlso note that the return status is not consistent with VAX/VMS
Xusage, although the error messages should be OK.
X
XGary Stebbins, DEC, 8/31/86
X============================================================================
V==
XThe files described in the following paragraphs have been modified
Xfor and compiled under Computer Innovations C86.  Note that when
Xuuencoding a binary file, you must not feed the file to uuencode
Xthrough stdin--for some reason, this causes the file to only be
Xpartially encoded (I suspect that this happens when uuencode runs
Xinto a `094Z in the input--I have played around with putting stdin into
X'raw' mode, which failed to successfully correct the problem).  So
Xwhen uuencoding binary files, use the full two-argument form.  Note
Xthat uudecode is unaffected.
X
XBrant Cheikes
XDepartment of Computer and Information Science
XUniversity of Pennsylvania
XARPA:  brant@linc.cis.upenn.edu
XCSNET: brant%upenn-linc@upenn.csnet
X============================================================================
V==
X
Xuudecode and uuencode are easily implemented under MSDOS as well.  Here
Xare the sources for Microsoft C v3.0, but if you have another kind of C
Xcompiler, there should be perhaps only 1 change -- the output file of
Xuudecode and the input file of uuencode must be in binary format.
X(ie.  binary files, like .EXE files may have byte patterns that are the
Xsame as `094Z, which signals end-of-file in non-binary (text) mode).
X
XIf you need more info, write back.  Note that the included files are
X*not* in "shar" format -- you will have to use an editor to cut the
Xfiles out.
X
X`009Don Kneller
XUUCP:`009...ucbvax!ucsfcgl!kneller
XARPA:`009kneller@ucsf-cgl.ARPA
XBITNET:`009kneller@ucsfcgl.BITNET
$ CALL UNPACK UUENCDEC.DOC;1 473845489
$ v=f$verify(v)
$ EXIT

