uuencode.c revision 91661
11590Srgrimes/*-
21590Srgrimes * Copyright (c) 1983, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 3. All advertising materials mentioning features or use of this software
141590Srgrimes *    must display the following acknowledgement:
151590Srgrimes *	This product includes software developed by the University of
161590Srgrimes *	California, Berkeley and its contributors.
171590Srgrimes * 4. Neither the name of the University nor the names of its contributors
181590Srgrimes *    may be used to endorse or promote products derived from this software
191590Srgrimes *    without specific prior written permission.
201590Srgrimes *
211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311590Srgrimes * SUCH DAMAGE.
321590Srgrimes */
331590Srgrimes
341590Srgrimes#ifndef lint
3528564Scharnierstatic const char copyright[] =
361590Srgrimes"@(#) Copyright (c) 1983, 1993\n\
371590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
381590Srgrimes#endif /* not lint */
391590Srgrimes
401590Srgrimes#ifndef lint
4128564Scharnier#if 0
421590Srgrimesstatic char sccsid[] = "@(#)uuencode.c	8.2 (Berkeley) 4/2/94";
4328564Scharnier#endif
4428564Scharnierstatic const char rcsid[] =
4550477Speter  "$FreeBSD: head/usr.bin/uuencode/uuencode.c 91661 2002-03-05 03:27:47Z jmallett $";
461590Srgrimes#endif /* not lint */
471590Srgrimes
481590Srgrimes/*
491590Srgrimes * uuencode [input] output
501590Srgrimes *
511590Srgrimes * Encode a file so it can be mailed to a remote system.
521590Srgrimes */
5391661Sjmallett#include <sys/param.h>
5491661Sjmallett#include <sys/socket.h>
551590Srgrimes#include <sys/stat.h>
561590Srgrimes
5791661Sjmallett#include <netinet/in.h>
5891661Sjmallett
5928564Scharnier#include <err.h>
6091661Sjmallett#include <resolv.h>
611590Srgrimes#include <stdio.h>
6278718Sdd#include <stdlib.h>
6391661Sjmallett#include <string.h>
6428564Scharnier#include <unistd.h>
651590Srgrimes
6628564Scharniervoid encode __P((void));
6791661Sjmallettvoid base64_encode __P((void));
6828564Scharnierstatic void usage __P((void));
6928564Scharnier
7091661SjmallettFILE *output = stdout;
7191661Sjmallettint mode;
7291661Sjmallettchar **av;
7391661Sjmallett
741590Srgrimesint
751590Srgrimesmain(argc, argv)
761590Srgrimes	int argc;
771590Srgrimes	char *argv[];
781590Srgrimes{
791590Srgrimes	struct stat sb;
8091661Sjmallett	int base64;
8191661Sjmallett	char ch;
8291661Sjmallett	char *outfile;
831590Srgrimes
8491661Sjmallett	base64 = 0;
8591661Sjmallett	outfile = NULL;
8691661Sjmallett
8791661Sjmallett	while ((ch = getopt(argc, argv, "mo:")) != -1) {
8891661Sjmallett		switch (ch) {
8991661Sjmallett		case 'm':
9091661Sjmallett			base64 = 1;
9191661Sjmallett			break;
9291661Sjmallett		case 'o':
9391661Sjmallett			outfile = optarg;
9491661Sjmallett			break;
9591661Sjmallett		case '?':
9691661Sjmallett		default:
9791661Sjmallett			usage();
9891661Sjmallett		}
9991661Sjmallett	}
1001590Srgrimes	argv += optind;
1011590Srgrimes	argc -= optind;
1021590Srgrimes
1031590Srgrimes	switch(argc) {
1041590Srgrimes	case 2:			/* optional first argument is input file */
10528564Scharnier		if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
10628564Scharnier			err(1, "%s", *argv);
1071590Srgrimes#define	RWX	(S_IRWXU|S_IRWXG|S_IRWXO)
1081590Srgrimes		mode = sb.st_mode & RWX;
1091590Srgrimes		++argv;
1101590Srgrimes		break;
1111590Srgrimes	case 1:
1121590Srgrimes#define	RW	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
1131590Srgrimes		mode = RW & ~umask(RW);
1141590Srgrimes		break;
1151590Srgrimes	case 0:
1161590Srgrimes	default:
1171590Srgrimes		usage();
1181590Srgrimes	}
1191590Srgrimes
12091661Sjmallett	av = argv;
12191661Sjmallett
12291661Sjmallett	if (outfile != NULL) {
12391661Sjmallett		output = fopen(outfile, "w+");
12491661Sjmallett		if (output == NULL)
12591661Sjmallett			err(1, "unable to open %s for output", outfile);
12691661Sjmallett	}
12791661Sjmallett	if (base64)
12891661Sjmallett		base64_encode();
12991661Sjmallett	else
13091661Sjmallett		encode();
13191661Sjmallett	if (ferror(output))
13228564Scharnier		errx(1, "write error");
1331590Srgrimes	exit(0);
1341590Srgrimes}
1351590Srgrimes
1361590Srgrimes/* ENC is the basic 1 character encoding function to make a char printing */
1371590Srgrimes#define	ENC(c) ((c) ? ((c) & 077) + ' ': '`')
1381590Srgrimes
1391590Srgrimes/*
14091661Sjmallett * Copy from in to out, encoding in base64 as you go along.
1411590Srgrimes */
14228564Scharniervoid
14391661Sjmallettbase64_encode()
14491661Sjmallett{
14591661Sjmallett#define	GROUPS	8 /* Group output chunks */
14691661Sjmallett	unsigned char buf[6];
14791661Sjmallett	char buf2[16];
14891661Sjmallett	size_t n;
14991661Sjmallett	int rv, sequence;
15091661Sjmallett
15191661Sjmallett	sequence = 0;
15291661Sjmallett
15391661Sjmallett	fprintf(output, "begin-base64 %o %s\n", mode, *av);
15491661Sjmallett	while ((n = fread(buf, 1, sizeof(buf), stdin))) {
15591661Sjmallett		++sequence;
15691661Sjmallett		rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0])));
15791661Sjmallett		if (rv == -1)
15891661Sjmallett			errx(1, "b64_ntop: error encoding base64");
15991661Sjmallett		fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
16091661Sjmallett	}
16191661Sjmallett	if (sequence % GROUPS)
16291661Sjmallett		fprintf(output, "\n");
16391661Sjmallett	fprintf(output, "====\n");
16491661Sjmallett}
16591661Sjmallett
16691661Sjmallett/*
16791661Sjmallett * Copy from in to out, encoding as you go along.
16891661Sjmallett */
16991661Sjmallettvoid
1701590Srgrimesencode()
1711590Srgrimes{
1721590Srgrimes	register int ch, n;
1731590Srgrimes	register char *p;
1741590Srgrimes	char buf[80];
1751590Srgrimes
17691661Sjmallett	(void)fprintf(output, "begin %o %s\n", mode, *av);
17728564Scharnier	while ((n = fread(buf, 1, 45, stdin))) {
1781590Srgrimes		ch = ENC(n);
17991661Sjmallett		if (fputc(ch, output) == EOF)
1801590Srgrimes			break;
1811590Srgrimes		for (p = buf; n > 0; n -= 3, p += 3) {
18284715Sru			/* Pad with nulls if not a multiple of 3. */
18384715Sru			if (n < 3) {
18484715Sru				p[2] = '\0';
18584715Sru				if (n < 2)
18684715Sru					p[1] = '\0';
18784715Sru			}
1881590Srgrimes			ch = *p >> 2;
1891590Srgrimes			ch = ENC(ch);
19091661Sjmallett			if (fputc(ch, output) == EOF)
1911590Srgrimes				break;
19278387Sdd			ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
1931590Srgrimes			ch = ENC(ch);
19491661Sjmallett			if (fputc(ch, output) == EOF)
1951590Srgrimes				break;
19678387Sdd			ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
1971590Srgrimes			ch = ENC(ch);
19891661Sjmallett			if (fputc(ch, output) == EOF)
1991590Srgrimes				break;
2001590Srgrimes			ch = p[2] & 077;
2011590Srgrimes			ch = ENC(ch);
20291661Sjmallett			if (fputc(ch, output) == EOF)
2031590Srgrimes				break;
2041590Srgrimes		}
20591661Sjmallett		if (fputc('\n', output) == EOF)
2061590Srgrimes			break;
2071590Srgrimes	}
20828564Scharnier	if (ferror(stdin))
20928564Scharnier		errx(1, "read error");
21091661Sjmallett	(void)fprintf(output, "%c\nend\n", ENC('\0'));
2111590Srgrimes}
2121590Srgrimes
21328564Scharnierstatic void
2141590Srgrimesusage()
2151590Srgrimes{
21691661Sjmallett	(void)fprintf(stderr,"usage: uuencode [-m] [-o outfile] [infile] remotefile\n");
2171590Srgrimes	exit(1);
2181590Srgrimes}
219