uuencode.c revision 105519
1132744Skan/*-
290285Sobrien * Copyright (c) 1983, 1993
3169706Skan *	The Regents of the University of California.  All rights reserved.
418334Speter *
5132744Skan * Redistribution and use in source and binary forms, with or without
618334Speter * modification, are permitted provided that the following conditions
7132744Skan * are met:
818334Speter * 1. Redistributions of source code must retain the above copyright
918334Speter *    notice, this list of conditions and the following disclaimer.
1018334Speter * 2. Redistributions in binary form must reproduce the above copyright
1118334Speter *    notice, this list of conditions and the following disclaimer in the
12132744Skan *    documentation and/or other materials provided with the distribution.
1318334Speter * 3. All advertising materials mentioning features or use of this software
1418334Speter *    must display the following acknowledgement:
1518334Speter *	This product includes software developed by the University of
1618334Speter *	California, Berkeley and its contributors.
1718334Speter * 4. Neither the name of the University nor the names of its contributors
18132744Skan *    may be used to endorse or promote products derived from this software
19169706Skan *    without specific prior written permission.
20169706Skan *
2118334Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2218334Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2318334Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2418334Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2518334Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2618334Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2718334Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2818334Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2918334Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3018334Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3118334Speter * SUCH DAMAGE.
3218334Speter */
3390285Sobrien
3490285Sobrien#ifndef lint
3590285Sobrienstatic const char copyright[] =
3618334Speter"@(#) Copyright (c) 1983, 1993\n\
3750654Sobrien	The Regents of the University of California.  All rights reserved.\n";
3850654Sobrien#endif /* not lint */
3950654Sobrien
4090285Sobrien#if 0
4190285Sobrien#ifndef lint
4290285Sobrienstatic char sccsid[] = "@(#)uuencode.c	8.2 (Berkeley) 4/2/94";
4390285Sobrien#endif /* not lint */
44169706Skan#endif
45132744Skan
4690285Sobrien#include <sys/cdefs.h>
47169706Skan__FBSDID("$FreeBSD: head/usr.bin/uuencode/uuencode.c 105519 2002-10-20 14:18:25Z fanf $");
48132744Skan
4990285Sobrien/*
5090285Sobrien * uuencode [input] output
5190285Sobrien *
5290285Sobrien * Encode a file so it can be mailed to a remote system.
5390285Sobrien */
5490285Sobrien#include <sys/param.h>
5590285Sobrien#include <sys/socket.h>
5690285Sobrien#include <sys/stat.h>
5790285Sobrien
5890285Sobrien#include <netinet/in.h>
5990285Sobrien
6090285Sobrien#include <err.h>
6190285Sobrien#include <libgen.h>
6290285Sobrien#include <resolv.h>
6390285Sobrien#include <stdio.h>
6490285Sobrien#include <stdlib.h>
6590285Sobrien#include <string.h>
6690285Sobrien#include <unistd.h>
6790285Sobrien
6890285Sobrienvoid encode(void);
6990285Sobrienvoid base64_encode(void);
7090285Sobrienstatic void usage(void);
7190285Sobrien
7290285SobrienFILE *output;
7390285Sobrienint mode;
7490285Sobrienchar **av;
7590285Sobrien
7690285Sobrienint
7790285Sobrienmain(int argc, char *argv[])
7890285Sobrien{
7990285Sobrien	struct stat sb;
80132744Skan	int base64;
81117407Skan	char ch;
82117407Skan	char *outfile;
83117407Skan
84117407Skan	base64 = 0;
85117407Skan	outfile = NULL;
86117407Skan
8750654Sobrien	if (strcmp(basename(argv[0]), "b64encode") == 0)
8850654Sobrien		base64 = 1;
8990285Sobrien
9050654Sobrien	while ((ch = getopt(argc, argv, "mo:")) != -1) {
9118334Speter		switch (ch) {
9218334Speter		case 'm':
9318334Speter			base64 = 1;
9490285Sobrien			break;
9518334Speter		case 'o':
96169706Skan			outfile = optarg;
9718334Speter			break;
98169706Skan		case '?':
99169706Skan		default:
100169706Skan			usage();
101169706Skan		}
102132744Skan	}
10318334Speter	argv += optind;
104169706Skan	argc -= optind;
105117407Skan
106117407Skan	switch(argc) {
107117407Skan	case 2:			/* optional first argument is input file */
108117407Skan		if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
109169706Skan			err(1, "%s", *argv);
110117407Skan#define	RWX	(S_IRWXU|S_IRWXG|S_IRWXO)
111117407Skan		mode = sb.st_mode & RWX;
112117407Skan		++argv;
113117407Skan		break;
114117407Skan	case 1:
115117407Skan#define	RW	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
116169706Skan		mode = RW & ~umask(RW);
117169706Skan		break;
118117407Skan	case 0:
11990285Sobrien	default:
12090285Sobrien		usage();
12190285Sobrien	}
12290285Sobrien
12390285Sobrien	av = argv;
124117407Skan
12518334Speter	if (outfile != NULL) {
126169706Skan		output = fopen(outfile, "w+");
127169706Skan		if (output == NULL)
12852295Sobrien			err(1, "unable to open %s for output", outfile);
129132744Skan	} else
130132744Skan		output = stdout;
131132744Skan	if (base64)
132132744Skan		base64_encode();
133219374Smm	else
134132744Skan		encode();
135132744Skan	if (ferror(output))
136132744Skan		errx(1, "write error");
137132744Skan	exit(0);
138132744Skan}
139169706Skan
140219374Smm/* ENC is the basic 1 character encoding function to make a char printing */
141169706Skan#define	ENC(c) ((c) ? ((c) & 077) + ' ': '`')
142169706Skan
143169706Skan/*
144252080Spfg * Copy from in to out, encoding in base64 as you go along.
145132744Skan */
146132744Skanvoid
14752295Sobrienbase64_encode(void)
14852295Sobrien{
14990285Sobrien	/*
15090285Sobrien	 * Output must fit into 80 columns, chunks come in 4, leave 1.
151169706Skan	 */
152169706Skan#define	GROUPS	((80 / 4) - 1)
15390285Sobrien	unsigned char buf[3];
154117407Skan	char buf2[sizeof(buf) * 2 + 1];
15590285Sobrien	size_t n;
15690285Sobrien	int rv, sequence;
15790285Sobrien
15890285Sobrien	sequence = 0;
15990285Sobrien
16090285Sobrien	fprintf(output, "begin-base64 %o %s\n", mode, *av);
161117407Skan	while ((n = fread(buf, 1, sizeof(buf), stdin))) {
162169706Skan		++sequence;
163252080Spfg		rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0])));
164132744Skan		if (rv == -1)
165169706Skan			errx(1, "b64_ntop: error encoding base64");
166169706Skan		fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
167169706Skan	}
168252080Spfg	if (sequence % GROUPS)
169169706Skan		fprintf(output, "\n");
170169706Skan	fprintf(output, "====\n");
171169706Skan}
172252080Spfg
17352295Sobrien/*
174132744Skan * Copy from in to out, encoding as you go along.
175132744Skan */
176132744Skanvoid
177132744Skanencode(void)
178132744Skan{
17990285Sobrien	register int ch, n;
18090285Sobrien	register char *p;
18190285Sobrien	char buf[80];
182169706Skan
183132744Skan	(void)fprintf(output, "begin %o %s\n", mode, *av);
184132744Skan	while ((n = fread(buf, 1, 45, stdin))) {
185132744Skan		ch = ENC(n);
186132744Skan		if (fputc(ch, output) == EOF)
187132744Skan			break;
188132744Skan		for (p = buf; n > 0; n -= 3, p += 3) {
189169706Skan			/* Pad with nulls if not a multiple of 3. */
190169706Skan			if (n < 3) {
191169706Skan				p[2] = '\0';
192132744Skan				if (n < 2)
193132744Skan					p[1] = '\0';
194132744Skan			}
195132744Skan			ch = *p >> 2;
196132744Skan			ch = ENC(ch);
197132744Skan			if (fputc(ch, output) == EOF)
198132744Skan				break;
199132744Skan			ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
200132744Skan			ch = ENC(ch);
201132744Skan			if (fputc(ch, output) == EOF)
202132744Skan				break;
203132744Skan			ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
204132744Skan			ch = ENC(ch);
205132744Skan			if (fputc(ch, output) == EOF)
206132744Skan				break;
207132744Skan			ch = p[2] & 077;
208132744Skan			ch = ENC(ch);
209132744Skan			if (fputc(ch, output) == EOF)
210132744Skan				break;
211132744Skan		}
212252080Spfg		if (fputc('\n', output) == EOF)
213252080Spfg			break;
214169706Skan	}
215132744Skan	if (ferror(stdin))
216132744Skan		errx(1, "read error");
217132744Skan	(void)fprintf(output, "%c\nend\n", ENC('\0'));
218132744Skan}
219132744Skan
22090285Sobrienstatic void
221132744Skanusage(void)
222132744Skan{
223132744Skan	(void)fprintf(stderr,
224132744Skan"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"
225169706Skan"       b64encode [-o outfile] [infile] remotefile\n");
226169706Skan	exit(1);
227169706Skan}
228169706Skan