[comp.binaries.ibm.pc] uuencode-uudecode for Unix

W8SDZ@SIMTEL20.ARPA (Keith Petersen) (03/10/88)

If you plan to post binaries to this newsgroup from a Unix host,
please make sure your host has the latest uuencode that substitutes
the accent grave (`) for the space character.  This gets around the
problem of some mailers that strip trailing spaces.

From the archives at SIMTEL20 comes uuencoded/uudecode, a PD version
of Berkeley, in the shar below.  Please pass it along to your systems
folks.  This may solve some of the problems we've been having with
truncated postings in comp.binaries.ibm.pc.

Keith Petersen
Maintainer of the MSDOS archives at SIMTEL20

---cut here---
# This is a shell archive.  Save this into a file, edit it
# and delete all lines above this comment.  Then give this
# file to sh by executing the command "sh file".  The files
# will be extracted into the current directory owned by
# you with default permissions.
#
# The files contained herein are:
#      uudecode.c     uuencode.c    uuencode.1c
#
echo 'x - uudecode.c'
sed 's/^X//' <<'________This_Is_The_END________' >>uudecode.c
X#ifndef lint
Xstatic char sccsid[] = "@(#)uudecode.c	5.3 (Berkeley) 4/10/85";
X#endif
X
X/*
X * uudecode [input]
X *
X * create the specified file, decoding as you go.
X * used with uuencode.
X */
X#include <stdio.h>
X#include <pwd.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X/* single character decode */
X#define DEC(c)	(((c) - ' ') & 077)
X
Xmain(argc, argv)
Xchar **argv;
X{
X	FILE *in, *out;
X	int mode;
X	char dest[128];
X	char buf[80];
X
X	/* optional input arg */
X	if (argc > 1) {
X		if ((in = fopen(argv[1], "r")) == NULL) {
X			perror(argv[1]);
X			exit(1);
X		}
X		argv++; argc--;
X	} else
X		in = stdin;
X
X	if (argc != 1) {
X		printf("Usage: uudecode [infile]\n");
X		exit(2);
X	}
X
X	/* search for header line */
X	for (;;) {
X		if (fgets(buf, sizeof buf, in) == NULL) {
X			fprintf(stderr, "No begin line\n");
X			exit(3);
X		}
X		if (strncmp(buf, "begin ", 6) == 0)
X			break;
X	}
X	sscanf(buf, "begin %o %s", &mode, dest);
X
X	/* handle ~user/file format */
X	if (dest[0] == '~') {
X		char *sl;
X		struct passwd *getpwnam();
X		char *index();
X		struct passwd *user;
X		char dnbuf[100];
X
X		sl = index(dest, '/');
X		if (sl == NULL) {
X			fprintf(stderr, "Illegal ~user\n");
X			exit(3);
X		}
X		*sl++ = 0;
X		user = getpwnam(dest+1);
X		if (user == NULL) {
X			fprintf(stderr, "No such user as %s\n", dest);
X			exit(4);
X		}
X		strcpy(dnbuf, user->pw_dir);
X		strcat(dnbuf, "/");
X		strcat(dnbuf, sl);
X		strcpy(dest, dnbuf);
X	}
X
X	/* create output file */
X	out = fopen(dest, "w");
X	if (out == NULL) {
X		perror(dest);
X		exit(4);
X	}
X	chmod(dest, mode);
X
X	decode(in, out);
X
X	if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {
X		fprintf(stderr, "No end line\n");
X		exit(5);
X	}
X	exit(0);
X}
X
X/*
X * copy from in to out, decoding as you go along.
X */
Xdecode(in, out)
XFILE *in;
XFILE *out;
X{
X	char buf[80];
X	char *bp;
X	int n;
X
X	for (;;) {
X		/* for each input line */
X		if (fgets(buf, sizeof buf, in) == NULL) {
X			printf("Short file\n");
X			exit(10);
X		}
X		n = DEC(buf[0]);
X		if (n <= 0)
X			break;
X
X		bp = &buf[1];
X		while (n > 0) {
X			outdec(bp, out, n);
X			bp += 4;
X			n -= 3;
X		}
X	}
X}
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{
X	int c1, c2, c3;
X
X	c1 = DEC(*p) << 2 | DEC(p[1]) >> 4;
X	c2 = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
X	c3 = DEC(p[2]) << 6 | DEC(p[3]);
X	if (n >= 1)
X		putc(c1, f);
X	if (n >= 2)
X		putc(c2, f);
X	if (n >= 3)
X		putc(c3, f);
X}
X
X
X/* fr: like read but stdio */
Xint
Xfr(fd, buf, cnt)
XFILE *fd;
Xchar *buf;
Xint cnt;
X{
X	int c, i;
X
X	for (i=0; i<cnt; i++) {
X		c = getc(fd);
X		if (c == EOF)
X			return(i);
X		buf[i] = c;
X	}
X	return (cnt);
X}
X
X/*
X * Return the ptr in sp at which the character c appears;
X * NULL if not found
X */
X
X#define	NULL	0
X
Xchar *
Xindex(sp, c)
Xregister char *sp, c;
X{
X	do {
X		if (*sp == c)
X			return(sp);
X	} while (*sp++);
X	return(NULL);
X}
________This_Is_The_END________
echo 'x - uuencode.c'
sed 's/^X//' <<'________This_Is_The_END________' >>uuencode.c
X#ifndef lint
Xstatic char sccsid[] = "@(#)uuencode.c	5.3 (Berkeley) 1/22/85";
X#endif
X
X/*
X * uuencode [input] output
X *
X * Encode a file so it can be mailed to a remote system.
X */
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X/* ENC is the basic 1 character encoding function to make a char printing */
X#define ENC(c) ((c) ? ((c) & 077) + ' ': '`')
X
Xmain(argc, argv)
Xchar **argv;
X{
X	FILE *in;
X	struct stat sbuf;
X	int mode;
X
X	/* optional 1st argument */
X	if (argc > 2) {
X		if ((in = fopen(argv[1], "r")) == NULL) {
X			perror(argv[1]);
X			exit(1);
X		}
X		argv++; argc--;
X	} else
X		in = stdin;
X
X	if (argc != 2) {
X		printf("Usage: uuencode [infile] remotefile\n");
X		exit(2);
X	}
X
X	/* figure out the input file mode */
X	fstat(fileno(in), &sbuf);
X	mode = sbuf.st_mode & 0777;
X	printf("begin %o %s\n", mode, argv[1]);
X
X	encode(in, stdout);
X
X	printf("end\n");
X	exit(0);
X}
X
X/*
X * copy from in to out, encoding as you go along.
X */
Xencode(in, out)
XFILE *in;
XFILE *out;
X{
X	char buf[80];
X	int i, n;
X
X	for (;;) {
X		/* 1 (up to) 45 character line */
X		n = fr(in, buf, 45);
X		putc(ENC(n), out);
X
X		for (i=0; i<n; i += 3)
X			outdec(&buf[i], out);
X
X		putc('\n', out);
X		if (n <= 0)
X			break;
X	}
X}
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{
X	int c1, c2, c3, c4;
X
X	c1 = *p >> 2;
X	c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
X	c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
X	c4 = p[2] & 077;
X	putc(ENC(c1), f);
X	putc(ENC(c2), f);
X	putc(ENC(c3), f);
X	putc(ENC(c4), f);
X}
X
X/* fr: like read but stdio */
Xint
Xfr(fd, buf, cnt)
XFILE *fd;
Xchar *buf;
Xint cnt;
X{
X	int c, i;
X
X	for (i=0; i<cnt; i++) {
X		c = getc(fd);
X		if (c == EOF)
X			return(i);
X		buf[i] = c;
X	}
X	return (cnt);
X}
________This_Is_The_END________
echo 'x - uuencode.1c'
sed 's/^X//' <<'________This_Is_The_END________' >>uuencode.1c
X.\" Copyright (c) 1980 Regents of the University of California.
X.\" All rights reserved.  The Berkeley software License Agreement
X.\" specifies the terms and conditions for redistribution.
X.\"
X.\"	@(#)uuencode.1c	6.2 (Berkeley) 4/24/86
X.\"
X.TH UUENCODE 1C "April 24, 1986"
X.UC 4
X.SH NAME
Xuuencode, uudecode \- encode/decode a binary file for transmission via mail
X.SH SYNOPSIS
X.B uuencode
X[ source ] remotedest |
X.B mail
Xsys1!sys2!..!decode
X.br
X.B uudecode
X[ file ]
X.SH DESCRIPTION
X.I Uuencode
Xand
X.I uudecode
Xare used to send a binary file via uucp (or other) mail.
XThis combination can be used over indirect mail links
Xeven when
X.IR uusend (1C)
Xis not available.
X.PP
X.I Uuencode
Xtakes the named source file (default standard input) and
Xproduces an encoded version on the standard output.
XThe encoding uses only printing ASCII characters,
Xand includes the mode of the file and the
X.I remotedest
Xfor recreation on the remote system.
X.PP
X.I Uudecode
Xreads an encoded file,
Xstrips off any leading and trailing lines added by mailers,
Xand recreates the original file with the specified mode and name.
X.PP
XThe intent is that all mail to the user ``decode'' should be filtered
Xthrough the
X.I uudecode
Xprogram.  This way the file is created automatically
Xwithout human intervention.
XThis is possible on the uucp network by either using
X.I sendmail
Xor by making
X.I rmail
Xbe a link to
X.I Mail
Xinstead of
X.IR mail .
XIn each case, an alias must be created in a master file to get
Xthe automatic invocation of
X.IR uudecode .
X.PP
XIf these facilities are not available, the file can be sent to a
Xuser on the remote machine who can uudecode it manually.
X.PP
XThe encode file has an ordinary text form and can be edited
Xby any text editor to change the mode or remote name.
X.SH SEE ALSO
Xatob(n), uusend(1C), uucp(1C), uux(1C), mail(1), uuencode(5)
X.SH BUGS
XThe file is expanded by 35% (3 bytes become 4 plus control information)
Xcausing it to take longer to transmit.
X.PP
XThe user on the remote system who is invoking
X.I uudecode
X(often
X.IR uucp )
Xmust have write permission on the specified file.
________This_Is_The_END________
exit