xref: /minix3/usr.bin/uuencode/uuencode.c (revision 2fde3a4846bf5ff2e91c001c8718329d949fe938)
1*2fde3a48SSky Liu /*	$NetBSD: uuencode.c,v 1.16 2014/09/06 18:58:35 dholland Exp $	*/
2*2fde3a48SSky Liu 
3*2fde3a48SSky Liu /*-
4*2fde3a48SSky Liu  * Copyright (c) 1983, 1993
5*2fde3a48SSky Liu  *	The Regents of the University of California.  All rights reserved.
6*2fde3a48SSky Liu  *
7*2fde3a48SSky Liu  * Redistribution and use in source and binary forms, with or without
8*2fde3a48SSky Liu  * modification, are permitted provided that the following conditions
9*2fde3a48SSky Liu  * are met:
10*2fde3a48SSky Liu  * 1. Redistributions of source code must retain the above copyright
11*2fde3a48SSky Liu  *    notice, this list of conditions and the following disclaimer.
12*2fde3a48SSky Liu  * 2. Redistributions in binary form must reproduce the above copyright
13*2fde3a48SSky Liu  *    notice, this list of conditions and the following disclaimer in the
14*2fde3a48SSky Liu  *    documentation and/or other materials provided with the distribution.
15*2fde3a48SSky Liu  * 3. Neither the name of the University nor the names of its contributors
16*2fde3a48SSky Liu  *    may be used to endorse or promote products derived from this software
17*2fde3a48SSky Liu  *    without specific prior written permission.
18*2fde3a48SSky Liu  *
19*2fde3a48SSky Liu  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*2fde3a48SSky Liu  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*2fde3a48SSky Liu  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*2fde3a48SSky Liu  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*2fde3a48SSky Liu  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*2fde3a48SSky Liu  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*2fde3a48SSky Liu  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*2fde3a48SSky Liu  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*2fde3a48SSky Liu  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*2fde3a48SSky Liu  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*2fde3a48SSky Liu  * SUCH DAMAGE.
30*2fde3a48SSky Liu  */
31*2fde3a48SSky Liu 
32*2fde3a48SSky Liu #include <sys/cdefs.h>
33*2fde3a48SSky Liu #ifndef lint
34*2fde3a48SSky Liu __COPYRIGHT("@(#) Copyright (c) 1983, 1993\
35*2fde3a48SSky Liu  The Regents of the University of California.  All rights reserved.");
36*2fde3a48SSky Liu #endif /* not lint */
37*2fde3a48SSky Liu 
38*2fde3a48SSky Liu #ifndef lint
39*2fde3a48SSky Liu #if 0
40*2fde3a48SSky Liu static char sccsid[] = "@(#)uuencode.c	8.2 (Berkeley) 4/2/94";
41*2fde3a48SSky Liu #else
42*2fde3a48SSky Liu __RCSID("$NetBSD: uuencode.c,v 1.16 2014/09/06 18:58:35 dholland Exp $");
43*2fde3a48SSky Liu #endif
44*2fde3a48SSky Liu #endif /* not lint */
45*2fde3a48SSky Liu 
46*2fde3a48SSky Liu /*
47*2fde3a48SSky Liu  * uuencode [input] output
48*2fde3a48SSky Liu  *
49*2fde3a48SSky Liu  * Encode a file so it can be mailed to a remote system.
50*2fde3a48SSky Liu  */
51*2fde3a48SSky Liu #include <sys/types.h>
52*2fde3a48SSky Liu #include <sys/stat.h>
53*2fde3a48SSky Liu #include <netinet/in.h>
54*2fde3a48SSky Liu #include <err.h>
55*2fde3a48SSky Liu #include <errno.h>
56*2fde3a48SSky Liu #include <locale.h>
57*2fde3a48SSky Liu #include <resolv.h>
58*2fde3a48SSky Liu #include <stdio.h>
59*2fde3a48SSky Liu #include <stdlib.h>
60*2fde3a48SSky Liu #include <string.h>
61*2fde3a48SSky Liu #include <unistd.h>
62*2fde3a48SSky Liu 
63*2fde3a48SSky Liu static void encode(void);
64*2fde3a48SSky Liu static void base64_encode(void);
65*2fde3a48SSky Liu __dead static void usage(void);
66*2fde3a48SSky Liu 
67*2fde3a48SSky Liu int
main(int argc,char * argv[])68*2fde3a48SSky Liu main(int argc, char *argv[])
69*2fde3a48SSky Liu {
70*2fde3a48SSky Liu 	struct stat sb;
71*2fde3a48SSky Liu 	int base64, ch, mode;
72*2fde3a48SSky Liu 
73*2fde3a48SSky Liu 	mode = 0;
74*2fde3a48SSky Liu 	base64 = 0;
75*2fde3a48SSky Liu 	setlocale(LC_ALL, "");
76*2fde3a48SSky Liu 	setprogname(argv[0]);
77*2fde3a48SSky Liu 
78*2fde3a48SSky Liu 	while ((ch = getopt(argc, argv, "m")) != -1) {
79*2fde3a48SSky Liu 		switch(ch) {
80*2fde3a48SSky Liu 		case 'm':
81*2fde3a48SSky Liu 			base64 = 1;
82*2fde3a48SSky Liu 			break;
83*2fde3a48SSky Liu 		default:
84*2fde3a48SSky Liu 			usage();
85*2fde3a48SSky Liu 		}
86*2fde3a48SSky Liu 	}
87*2fde3a48SSky Liu 	argv += optind;
88*2fde3a48SSky Liu 	argc -= optind;
89*2fde3a48SSky Liu 
90*2fde3a48SSky Liu 	switch(argc) {
91*2fde3a48SSky Liu 	case 2:			/* optional first argument is input file */
92*2fde3a48SSky Liu 		if (!freopen(*argv, "r", stdin) || fstat(fileno(stdin), &sb))
93*2fde3a48SSky Liu 			err(1, "%s", *argv);
94*2fde3a48SSky Liu #define	RWX	(S_IRWXU|S_IRWXG|S_IRWXO)
95*2fde3a48SSky Liu 		mode = sb.st_mode & RWX;
96*2fde3a48SSky Liu 		++argv;
97*2fde3a48SSky Liu 		break;
98*2fde3a48SSky Liu 	case 1:
99*2fde3a48SSky Liu #define	RW	(S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
100*2fde3a48SSky Liu 		mode = RW & ~umask(RW);
101*2fde3a48SSky Liu 		break;
102*2fde3a48SSky Liu 	case 0:
103*2fde3a48SSky Liu 	default:
104*2fde3a48SSky Liu 		usage();
105*2fde3a48SSky Liu 	}
106*2fde3a48SSky Liu 
107*2fde3a48SSky Liu 	if (base64) {
108*2fde3a48SSky Liu 		(void)printf("begin-base64 %o %s\n", mode, *argv);
109*2fde3a48SSky Liu 		base64_encode();
110*2fde3a48SSky Liu 		(void)printf("====\n");
111*2fde3a48SSky Liu 	} else {
112*2fde3a48SSky Liu 		(void)printf("begin %o %s\n", mode, *argv);
113*2fde3a48SSky Liu 		encode();
114*2fde3a48SSky Liu 		(void)printf("end\n");
115*2fde3a48SSky Liu 	}
116*2fde3a48SSky Liu 
117*2fde3a48SSky Liu 	if (ferror(stdout))
118*2fde3a48SSky Liu 		err(1, "write error");
119*2fde3a48SSky Liu 	exit(0);
120*2fde3a48SSky Liu }
121*2fde3a48SSky Liu 
122*2fde3a48SSky Liu /* ENC is the basic 1 character encoding function to make a char printing */
123*2fde3a48SSky Liu #define	ENC(c) ((c) ? ((c) & 077) + ' ': '`')
124*2fde3a48SSky Liu 
125*2fde3a48SSky Liu /*
126*2fde3a48SSky Liu  * copy from in to out, encoding in base64 as you go along.
127*2fde3a48SSky Liu  */
128*2fde3a48SSky Liu static void
base64_encode(void)129*2fde3a48SSky Liu base64_encode(void)
130*2fde3a48SSky Liu {
131*2fde3a48SSky Liu 	/*
132*2fde3a48SSky Liu 	 * Output must fit into 80 columns, chunks come in 4, leave 1.
133*2fde3a48SSky Liu 	 */
134*2fde3a48SSky Liu #define GROUPS 	((70 / 4) - 1)
135*2fde3a48SSky Liu 	unsigned char buf[3];
136*2fde3a48SSky Liu 	char buf2[sizeof(buf) * 2 + 1];
137*2fde3a48SSky Liu 	size_t n;
138*2fde3a48SSky Liu 	int rv, sequence;
139*2fde3a48SSky Liu 
140*2fde3a48SSky Liu 	sequence = 0;
141*2fde3a48SSky Liu 
142*2fde3a48SSky Liu 	while ((n = fread(buf, 1, sizeof(buf), stdin))) {
143*2fde3a48SSky Liu 		++sequence;
144*2fde3a48SSky Liu 		rv = b64_ntop(buf, n, buf2, (sizeof(buf2) / sizeof(buf2[0])));
145*2fde3a48SSky Liu 		if (rv == -1)
146*2fde3a48SSky Liu 			errx(1, "b64_ntop: error encoding base64");
147*2fde3a48SSky Liu 		printf("%s%s", buf2, (sequence % GROUPS) ? "" : "\n");
148*2fde3a48SSky Liu 	}
149*2fde3a48SSky Liu 	if (sequence % GROUPS)
150*2fde3a48SSky Liu 		printf("\n");
151*2fde3a48SSky Liu }
152*2fde3a48SSky Liu 
153*2fde3a48SSky Liu /*
154*2fde3a48SSky Liu  * copy from in to out, encoding as you go along.
155*2fde3a48SSky Liu  */
156*2fde3a48SSky Liu static void
encode(void)157*2fde3a48SSky Liu encode(void)
158*2fde3a48SSky Liu {
159*2fde3a48SSky Liu 	int ch, n;
160*2fde3a48SSky Liu 	char *p;
161*2fde3a48SSky Liu 	char buf[80];
162*2fde3a48SSky Liu 
163*2fde3a48SSky Liu 	while ((n = fread(buf, 1, 45, stdin)) > 0) {
164*2fde3a48SSky Liu 		ch = ENC(n);
165*2fde3a48SSky Liu 		if (putchar(ch) == EOF)
166*2fde3a48SSky Liu 			break;
167*2fde3a48SSky Liu 		for (p = buf; n > 0; n -= 3, p += 3) {
168*2fde3a48SSky Liu 			ch = *p >> 2;
169*2fde3a48SSky Liu 			ch = ENC(ch);
170*2fde3a48SSky Liu 			if (putchar(ch) == EOF)
171*2fde3a48SSky Liu 				break;
172*2fde3a48SSky Liu 			ch = ((*p << 4) & 060) | ((p[1] >> 4) & 017);
173*2fde3a48SSky Liu 			ch = ENC(ch);
174*2fde3a48SSky Liu 			if (putchar(ch) == EOF)
175*2fde3a48SSky Liu 				break;
176*2fde3a48SSky Liu 			ch = ((p[1] << 2) & 074) | ((p[2] >> 6) & 03);
177*2fde3a48SSky Liu 			ch = ENC(ch);
178*2fde3a48SSky Liu 			if (putchar(ch) == EOF)
179*2fde3a48SSky Liu 				break;
180*2fde3a48SSky Liu 			ch = p[2] & 077;
181*2fde3a48SSky Liu 			ch = ENC(ch);
182*2fde3a48SSky Liu 			if (putchar(ch) == EOF)
183*2fde3a48SSky Liu 				break;
184*2fde3a48SSky Liu 		}
185*2fde3a48SSky Liu 		if (putchar('\n') == EOF)
186*2fde3a48SSky Liu 			break;
187*2fde3a48SSky Liu 	}
188*2fde3a48SSky Liu 	if (ferror(stdin))
189*2fde3a48SSky Liu 		err(1, "read error.");
190*2fde3a48SSky Liu 	ch = ENC('\0');
191*2fde3a48SSky Liu 	(void)putchar(ch);
192*2fde3a48SSky Liu 	(void)putchar('\n');
193*2fde3a48SSky Liu }
194*2fde3a48SSky Liu 
195*2fde3a48SSky Liu static void
usage(void)196*2fde3a48SSky Liu usage(void)
197*2fde3a48SSky Liu {
198*2fde3a48SSky Liu 	(void)fprintf(stderr,
199*2fde3a48SSky Liu 		      "usage: %s [-m] [inputfile] headername > encodedfile\n",
200*2fde3a48SSky Liu 		      getprogname());
201*2fde3a48SSky Liu 	exit(1);
202*2fde3a48SSky Liu }
203