: UUE utility - uuencode.c uudecode.c uuencode.1c

echo x - uudecode.c

cat >uudecode.c <<'@EOF'

#ifndef lint

static char sccsid[] = "@(#)uudecode.c	5.1 (Berkeley) 7/2/83";

#endif



/*

 * uudecode [input]

 *

 * create the specified file, decoding as you go.

 * used with uuencode.

 */

#include <stdio.h>

#include <pwd.h>

#include <sys/types.h>

#include <sys/stat.h>



/* single character decode */

#define DEC(c)	(((c) - ' ') & 077)



main(argc, argv)

char **argv;

{

	FILE *in, *out;

	struct stat sbuf;

	int mode;

	char dest[128];

	char buf[80];



	/* optional input arg */

	if (argc > 1) {

		if ((in = fopen(argv[1], "r")) == NULL) {

			perror(argv[1]);

			exit(1);

		}

		argv++; argc--;

	} else

		in = stdin;



	if (argc != 1) {

		printf("Usage: uudecode [infile]\n");

		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);



	/* handle ~user/file format */

	if (dest[0] == '~') {

		char *sl;

		struct passwd *getpwnam();

		char *index();

		struct passwd *user;

		char dnbuf[100];



		sl = index(dest, '/');

		if (sl == NULL) {

			fprintf(stderr, "Illegal ~user\n");

			exit(3);

		}

		*sl++ = 0;

		user = getpwnam(dest+1);

		if (user == NULL) {

			fprintf(stderr, "No such user as %s\n", dest);

			exit(4);

		}

		strcpy(dnbuf, user->pw_dir);

		strcat(dnbuf, "/");

		strcat(dnbuf, sl);

		strcpy(dest, dnbuf);

	}



	/* create output file */

	out = fopen(dest, "w");

	if (out == NULL) {

		perror(dest);

		exit(4);

	}

	chmod(dest, mode);



	decode(in, out);



	if (fgets(buf, sizeof buf, in) == NULL || strcmp(buf, "end\n")) {

		fprintf(stderr, "No end line\n");

		exit(5);

	}

	exit(0);

}



/*

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

 */

decode(in, out)

FILE *in;

FILE *out;

{

	char buf[80];

	char *bp;

	int n;



	for (;;) {

		/* for each input line */

		if (fgets(buf, sizeof buf, in) == NULL) {

			printf("Short file\n");

			exit(10);

		}

		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.

 */

outdec(p, f, n)

char *p;

FILE *f;

{

	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(fd, buf, cnt)

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);

}



/*

 * Return the ptr in sp at which the character c appears;

 * NULL if not found

 */



#define	NULL	0



char *

index(sp, c)

register char *sp, c;

{

	do {

		if (*sp == c)

			return(sp);

	} while (*sp++);

	return(NULL);

}

@EOF

size=`wc -c <uudecode.c`; if test $size -ne 2949 ; then

	echo ERROR: uudecode.c is $size bytes but should be 2949.

fi



chmod 644 uudecode.c



echo x - uuencode.1c

cat >uuencode.1c <<'@EOF'

.TH UUENCODE 1C "1 June 1980"

.UC 4

.SH NAME

uuencode,uudecode \- encode/decode a binary file for transmission via mail

.SH SYNOPSIS

.B uuencode

[ source ] remotedest |

.B mail

sys1!sys2!..!decode

.br

.B uudecode

[ file ]

.SH DESCRIPTION

.I Uuencode

and

.I uudecode

are used to send a binary file via uucp (or other) mail.

This combination can be used over indirect mail links

even when

.IR uusend (1C)

is not available.

.PP

.I Uuencode

takes the named source file (default standard input) and

produces an encoded version on the standard output.

The encoding uses only printing ASCII characters,

and includes the mode of the file and the

.I remotedest

for recreation on the remote system.

.PP

.I Uudecode

reads an encoded file,

strips off any leading and trailing lines added by mailers,

and recreates the original file with the specified mode and name.

.PP

The intent is that all mail to the user ``decode'' should be filtered

through the uudecode program.  This way the file is created automatically

without human intervention.

This is possible on the uucp network by either using

.I sendmail

or by making

.I rmail

be a link to

.I Mail

instead of

.I mail.

In each case, an alias must be created in a master file to get

the automatic invocation of uudecode.

.PP

If these facilities are not available, the file can be sent to a

user on the remote machine who can uudecode it manually.

.PP

The encode file has an ordinary text form and can be edited

by any text editor to change the mode or remote name.

.SH SEE\ ALSO

uuencode(5), uusend(1C), uucp(1C), uux(1C), mail(1)

.SH AUTHOR

Mark Horton

.SH BUGS

The file is expanded by 35% (3 bytes become 4 plus control information)

causing it to take longer to transmit.

.PP

The user on the remote system who is invoking

.I uudecode

(often

.I uucp)

must have write permission on the specified file.

@EOF

size=`wc -c <uuencode.1c`; if test $size -ne 1840 ; then

	echo ERROR: uuencode.1c is $size bytes but should be 1840.

fi



chmod 644 uuencode.1c



echo x - uuencode.c

cat >uuencode.c <<'@EOF'

#ifndef lint

static char sccsid[] = "@(#)uuencode.c	5.1 (Berkeley) 7/2/83";

#endif



/*

 * uuencode [input] output

 *

 * Encode a file so it can be mailed to a remote system.

 */

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>



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

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



main(argc, argv)

char **argv;

{

	FILE *in;

	struct stat sbuf;

	int mode;



	/* optional 1st argument */

	if (argc > 2) {

		if ((in = fopen(argv[1], "r")) == NULL) {

			perror(argv[1]);

			exit(1);

		}

		argv++; argc--;

	} else

		in = stdin;



	if (argc != 2) {

		printf("Usage: uuencode [infile] remotefile\n");

		exit(2);

	}



	/* figure out the input file mode */

	fstat(fileno(in), &sbuf);

	mode = sbuf.st_mode & 0777;

	printf("begin %o %s\n", mode, argv[1]);



	encode(in, stdout);



	printf("end\n");

	exit(0);

}



/*

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

 */

encode(in, out)

FILE *in;

FILE *out;

{

	char buf[80];

	int i, n;



	for (;;) {

		/* 1 (up to) 45 character line */

		n = fr(in, buf, 45);

		putc(ENC(n), out);



		for (i=0; i<n; i += 3)

			outdec(&buf[i], out);



		putc('\n', out);

		if (n <= 0)

			break;

	}

}



/*

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

 */

outdec(p, f)

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;

	putc(ENC(c1), f);

	putc(ENC(c2), f);

	putc(ENC(c3), f);

	putc(ENC(c4), f);

}



/* fr: like read but stdio */

int

fr(fd, buf, cnt)

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);

}

@EOF

size=`wc -c <uuencode.c`; if test $size -ne 1707 ; then

	echo ERROR: uuencode.c is $size bytes but should be 1707.

fi



chmod 644 uuencode.c



exit 0

