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 * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
30114594Sobrien#if 0
311590Srgrimes#ifndef lint
3228564Scharnierstatic const char copyright[] =
331590Srgrimes"@(#) Copyright (c) 1983, 1993\n\
341590Srgrimes	The Regents of the University of California.  All rights reserved.\n";
351590Srgrimes#endif /* not lint */
361590Srgrimes
371590Srgrimes#ifndef lint
381590Srgrimesstatic char sccsid[] = "@(#)uuencode.c	8.2 (Berkeley) 4/2/94";
3996438Smike#endif /* not lint */
4028564Scharnier#endif
4196438Smike#include <sys/cdefs.h>
4296438Smike__FBSDID("$FreeBSD: stable/11/usr.bin/uuencode/uuencode.c 317062 2017-04-17 18:55:54Z araujo $");
4396438Smike
441590Srgrimes/*
451590Srgrimes * uuencode [input] output
461590Srgrimes *
471590Srgrimes * Encode a file so it can be mailed to a remote system.
481590Srgrimes */
4991661Sjmallett#include <sys/param.h>
5091661Sjmallett#include <sys/socket.h>
511590Srgrimes#include <sys/stat.h>
521590Srgrimes
5391661Sjmallett#include <netinet/in.h>
5491661Sjmallett
5528564Scharnier#include <err.h>
56105519Sfanf#include <libgen.h>
5791661Sjmallett#include <resolv.h>
581590Srgrimes#include <stdio.h>
5978718Sdd#include <stdlib.h>
6091661Sjmallett#include <string.h>
6128564Scharnier#include <unistd.h>
621590Srgrimes
63227197Sedstatic void encode(void);
64227197Sedstatic void base64_encode(void);
6592922Simpstatic void usage(void);
6628564Scharnier
67227197Sedstatic FILE *output;
68227197Sedstatic int mode;
69297678Sgahrstatic char raw = 0;
70227197Sedstatic char **av;
7191661Sjmallett
721590Srgrimesint
7396386Salfredmain(int argc, char *argv[])
741590Srgrimes{
751590Srgrimes	struct stat sb;
7691661Sjmallett	int base64;
77124830Sgrehan	int ch;
7891661Sjmallett	char *outfile;
791590Srgrimes
8091661Sjmallett	base64 = 0;
8191661Sjmallett	outfile = NULL;
8291661Sjmallett
83105519Sfanf	if (strcmp(basename(argv[0]), "b64encode") == 0)
8496942Sjmallett		base64 = 1;
8596942Sjmallett
86297678Sgahr	while ((ch = getopt(argc, argv, "mo:r")) != -1) {
8791661Sjmallett		switch (ch) {
8891661Sjmallett		case 'm':
8991661Sjmallett			base64 = 1;
9091661Sjmallett			break;
9191661Sjmallett		case 'o':
9291661Sjmallett			outfile = optarg;
9391661Sjmallett			break;
94297678Sgahr		case 'r':
95297678Sgahr			raw = 1;
96297678Sgahr			break;
9791661Sjmallett		case '?':
9891661Sjmallett		default:
9991661Sjmallett			usage();
10091661Sjmallett		}
10191661Sjmallett	}
1021590Srgrimes	argv += optind;
1031590Srgrimes	argc -= optind;
1041590Srgrimes
1051590Srgrimes	switch(argc) {
1061590Srgrimes	case 2:			/* optional first argument is input file */
10728564Scharnier		if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
10828564Scharnier			err(1, "%s", *argv);
1091590Srgrimes#define	RWX	(S_IRWXU|S_IRWXG|S_IRWXO)
1101590Srgrimes		mode = sb.st_mode & RWX;
1111590Srgrimes		++argv;
1121590Srgrimes		break;
1131590Srgrimes	case 1:
1141590Srgrimes#define	RW	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
1151590Srgrimes		mode = RW & ~umask(RW);
1161590Srgrimes		break;
1171590Srgrimes	case 0:
1181590Srgrimes	default:
1191590Srgrimes		usage();
1201590Srgrimes	}
1211590Srgrimes
12291661Sjmallett	av = argv;
12391661Sjmallett
12491661Sjmallett	if (outfile != NULL) {
12591661Sjmallett		output = fopen(outfile, "w+");
12691661Sjmallett		if (output == NULL)
12791661Sjmallett			err(1, "unable to open %s for output", outfile);
12891676Smike	} else
12991676Smike		output = stdout;
13091661Sjmallett	if (base64)
13191661Sjmallett		base64_encode();
13291661Sjmallett	else
13391661Sjmallett		encode();
13491661Sjmallett	if (ferror(output))
13528564Scharnier		errx(1, "write error");
1361590Srgrimes	exit(0);
1371590Srgrimes}
1381590Srgrimes
1391590Srgrimes/* ENC is the basic 1 character encoding function to make a char printing */
1401590Srgrimes#define	ENC(c) ((c) ? ((c) & 077) + ' ': '`')
1411590Srgrimes
1421590Srgrimes/*
14391661Sjmallett * Copy from in to out, encoding in base64 as you go along.
1441590Srgrimes */
145227197Sedstatic void
14696438Smikebase64_encode(void)
14791661Sjmallett{
14896810Sjmallett	/*
14996810Sjmallett	 * Output must fit into 80 columns, chunks come in 4, leave 1.
15096810Sjmallett	 */
15196810Sjmallett#define	GROUPS	((80 / 4) - 1)
15296810Sjmallett	unsigned char buf[3];
15396810Sjmallett	char buf2[sizeof(buf) * 2 + 1];
15491661Sjmallett	size_t n;
15591661Sjmallett	int rv, sequence;
15691661Sjmallett
15791661Sjmallett	sequence = 0;
15891661Sjmallett
159297678Sgahr	if (!raw)
160297678Sgahr		fprintf(output, "begin-base64 %o %s\n", mode, *av);
16191661Sjmallett	while ((n = fread(buf, 1, sizeof(buf), stdin))) {
16291661Sjmallett		++sequence;
163317062Saraujo		rv = b64_ntop(buf, n, buf2, nitems(buf2));
16491661Sjmallett		if (rv == -1)
16591661Sjmallett			errx(1, "b64_ntop: error encoding base64");
16691661Sjmallett		fprintf(output, "%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
16791661Sjmallett	}
16891661Sjmallett	if (sequence % GROUPS)
16991661Sjmallett		fprintf(output, "\n");
170297678Sgahr	if (!raw)
171297678Sgahr		fprintf(output, "====\n");
17291661Sjmallett}
17391661Sjmallett
17491661Sjmallett/*
17591661Sjmallett * Copy from in to out, encoding as you go along.
17691661Sjmallett */
177227197Sedstatic void
17896438Smikeencode(void)
1791590Srgrimes{
1801590Srgrimes	register int ch, n;
1811590Srgrimes	register char *p;
1821590Srgrimes	char buf[80];
1831590Srgrimes
184297678Sgahr	if (!raw)
185297678Sgahr		(void)fprintf(output, "begin %o %s\n", mode, *av);
18628564Scharnier	while ((n = fread(buf, 1, 45, stdin))) {
1871590Srgrimes		ch = ENC(n);
18891661Sjmallett		if (fputc(ch, output) == EOF)
1891590Srgrimes			break;
1901590Srgrimes		for (p = buf; n > 0; n -= 3, p += 3) {
19184715Sru			/* Pad with nulls if not a multiple of 3. */
19284715Sru			if (n < 3) {
19384715Sru				p[2] = '\0';
19484715Sru				if (n < 2)
19584715Sru					p[1] = '\0';
19684715Sru			}
1971590Srgrimes			ch = *p >> 2;
1981590Srgrimes			ch = ENC(ch);
19991661Sjmallett			if (fputc(ch, output) == EOF)
2001590Srgrimes				break;
20178387Sdd			ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
2021590Srgrimes			ch = ENC(ch);
20391661Sjmallett			if (fputc(ch, output) == EOF)
2041590Srgrimes				break;
20578387Sdd			ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
2061590Srgrimes			ch = ENC(ch);
20791661Sjmallett			if (fputc(ch, output) == EOF)
2081590Srgrimes				break;
2091590Srgrimes			ch = p[2] & 077;
2101590Srgrimes			ch = ENC(ch);
21191661Sjmallett			if (fputc(ch, output) == EOF)
2121590Srgrimes				break;
2131590Srgrimes		}
21491661Sjmallett		if (fputc('\n', output) == EOF)
2151590Srgrimes			break;
2161590Srgrimes	}
21728564Scharnier	if (ferror(stdin))
21828564Scharnier		errx(1, "read error");
219297678Sgahr	if (!raw)
220297678Sgahr		(void)fprintf(output, "%c\nend\n", ENC('\0'));
2211590Srgrimes}
2221590Srgrimes
22328564Scharnierstatic void
22496438Smikeusage(void)
2251590Srgrimes{
22696943Sjmallett	(void)fprintf(stderr,
22796943Sjmallett"usage: uuencode [-m] [-o outfile] [infile] remotefile\n"
22896943Sjmallett"       b64encode [-o outfile] [infile] remotefile\n");
2291590Srgrimes	exit(1);
2301590Srgrimes}
231