xref: /titanic_50/usr/src/cmd/bnu/uuencode.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate /*
31*7c478bd9Sstevel@tonic-gate  * Portions of this source code were derived from Berkeley 4.3 BSD
32*7c478bd9Sstevel@tonic-gate  * under license from the Regents of the University of California.
33*7c478bd9Sstevel@tonic-gate  */
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate  * uuencode [-m] [input] decode_pathname
39*7c478bd9Sstevel@tonic-gate  *
40*7c478bd9Sstevel@tonic-gate  * Encode a file so it can be mailed to a remote system.
41*7c478bd9Sstevel@tonic-gate  */
42*7c478bd9Sstevel@tonic-gate #include <unistd.h>
43*7c478bd9Sstevel@tonic-gate #include <limits.h>
44*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
45*7c478bd9Sstevel@tonic-gate #include <string.h>
46*7c478bd9Sstevel@tonic-gate #include <stdio.h>
47*7c478bd9Sstevel@tonic-gate #include <locale.h>
48*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
49*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
50*7c478bd9Sstevel@tonic-gate #include <errno.h>
51*7c478bd9Sstevel@tonic-gate #include <assert.h>
52*7c478bd9Sstevel@tonic-gate #include <signal.h>
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate /*
55*7c478bd9Sstevel@tonic-gate  * (Size of TABLE_SIZE octal is large enough to convert a basic 6-bit
56*7c478bd9Sstevel@tonic-gate  * data chunk.)
57*7c478bd9Sstevel@tonic-gate  */
58*7c478bd9Sstevel@tonic-gate #define		TABLE_SIZE	0x40
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate 
61*7c478bd9Sstevel@tonic-gate static unsigned char	base64_table_initializer[] =
62*7c478bd9Sstevel@tonic-gate 	"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
63*7c478bd9Sstevel@tonic-gate 	"abcdefghijklmnopqrstuvwxyz0123456789+/";
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate static unsigned char	encode_table[TABLE_SIZE];
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* ENC is the basic 1 character encoding function to make a char printing */
68*7c478bd9Sstevel@tonic-gate #define	ENC(c)	encode_table[(c) & 077]
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate static void	encode(FILE *, FILE *, int);
71*7c478bd9Sstevel@tonic-gate static char	*prog;
72*7c478bd9Sstevel@tonic-gate 
73*7c478bd9Sstevel@tonic-gate int
74*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
75*7c478bd9Sstevel@tonic-gate {
76*7c478bd9Sstevel@tonic-gate 	FILE *in;
77*7c478bd9Sstevel@tonic-gate 	struct stat sbuf;
78*7c478bd9Sstevel@tonic-gate 	mode_t mode = 0;
79*7c478bd9Sstevel@tonic-gate 	int	c, i;
80*7c478bd9Sstevel@tonic-gate 	int	errflag = 0;
81*7c478bd9Sstevel@tonic-gate 	int	base64flag = 0;
82*7c478bd9Sstevel@tonic-gate 	char	oline[PATH_MAX + 20];
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate 	prog = argv[0];
85*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGPIPE, SIG_DFL);
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 	/* Set locale environment variables local definitions */
88*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
89*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
90*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it wasn't */
91*7c478bd9Sstevel@tonic-gate #endif
92*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
93*7c478bd9Sstevel@tonic-gate 
94*7c478bd9Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "m")) != EOF)
95*7c478bd9Sstevel@tonic-gate 		switch (c) {
96*7c478bd9Sstevel@tonic-gate 		case 'm':
97*7c478bd9Sstevel@tonic-gate 			base64flag++;
98*7c478bd9Sstevel@tonic-gate 			break;
99*7c478bd9Sstevel@tonic-gate 		default:
100*7c478bd9Sstevel@tonic-gate 		case '?':
101*7c478bd9Sstevel@tonic-gate 			errflag++;
102*7c478bd9Sstevel@tonic-gate 		}
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	argc -= optind;
105*7c478bd9Sstevel@tonic-gate 	argv = &argv[optind];
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	/* optional 1st argument */
108*7c478bd9Sstevel@tonic-gate 	if (argc > 1) {
109*7c478bd9Sstevel@tonic-gate 		if ((in = fopen(*argv, "r")) == NULL) {
110*7c478bd9Sstevel@tonic-gate 			perror(*argv);
111*7c478bd9Sstevel@tonic-gate 			exit(1);
112*7c478bd9Sstevel@tonic-gate 		}
113*7c478bd9Sstevel@tonic-gate 		argv++; argc--;
114*7c478bd9Sstevel@tonic-gate 	} else {
115*7c478bd9Sstevel@tonic-gate 		in = stdin;
116*7c478bd9Sstevel@tonic-gate 		mode = 0777;
117*7c478bd9Sstevel@tonic-gate 	}
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate 	if ((argc != 1) || errflag) {
120*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr,
121*7c478bd9Sstevel@tonic-gate 		    gettext("Usage: %s [-m] [infile] remotefile\n"), prog);
122*7c478bd9Sstevel@tonic-gate 		exit(2);
123*7c478bd9Sstevel@tonic-gate 	}
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 	/* figure out the input file mode */
126*7c478bd9Sstevel@tonic-gate 	errno = 0;
127*7c478bd9Sstevel@tonic-gate 	if (fstat(fileno(in), &sbuf) < 0 || !S_ISREG(sbuf.st_mode)) {
128*7c478bd9Sstevel@tonic-gate 		mode = 0666 & ~umask(0666);
129*7c478bd9Sstevel@tonic-gate 	} else {
130*7c478bd9Sstevel@tonic-gate 		mode = sbuf.st_mode & 0777;
131*7c478bd9Sstevel@tonic-gate 	}
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	/*
134*7c478bd9Sstevel@tonic-gate 	 * encoding varies depending on whether we are
135*7c478bd9Sstevel@tonic-gate 	 * using base64 encoding or the historical algorithm
136*7c478bd9Sstevel@tonic-gate 	 */
137*7c478bd9Sstevel@tonic-gate 	if (base64flag) {
138*7c478bd9Sstevel@tonic-gate 		(void) memcpy(encode_table, base64_table_initializer,
139*7c478bd9Sstevel@tonic-gate 		    sizeof (base64_table_initializer));
140*7c478bd9Sstevel@tonic-gate 	} else {
141*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < TABLE_SIZE; i++)
142*7c478bd9Sstevel@tonic-gate 			encode_table[i] = (unsigned char)i + 0x20;
143*7c478bd9Sstevel@tonic-gate 	}
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	/*
146*7c478bd9Sstevel@tonic-gate 	 * here's the meat of the whole thing
147*7c478bd9Sstevel@tonic-gate 	 */
148*7c478bd9Sstevel@tonic-gate 	if (base64flag)
149*7c478bd9Sstevel@tonic-gate 		(void) snprintf(oline, sizeof (oline), "begin-base64 %lo %s\n",
150*7c478bd9Sstevel@tonic-gate 		    (long)mode, *argv);
151*7c478bd9Sstevel@tonic-gate 	else
152*7c478bd9Sstevel@tonic-gate 		(void) snprintf(oline, sizeof (oline), "begin %lo %s\n",
153*7c478bd9Sstevel@tonic-gate 		    (long)mode, *argv);
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate 	if (printf("%s", oline) < 0) {
156*7c478bd9Sstevel@tonic-gate 		perror(prog);
157*7c478bd9Sstevel@tonic-gate 		exit(6);
158*7c478bd9Sstevel@tonic-gate 	}
159*7c478bd9Sstevel@tonic-gate 
160*7c478bd9Sstevel@tonic-gate 	encode(in, stdout, base64flag);
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	if (base64flag)
163*7c478bd9Sstevel@tonic-gate 		(void) snprintf(oline, sizeof (oline), "====\n");
164*7c478bd9Sstevel@tonic-gate 	else
165*7c478bd9Sstevel@tonic-gate 		(void) snprintf(oline, sizeof (oline), "end\n");
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 	if (printf("%s", oline) < 0) {
168*7c478bd9Sstevel@tonic-gate 		perror(prog);
169*7c478bd9Sstevel@tonic-gate 		exit(6);
170*7c478bd9Sstevel@tonic-gate 	}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 	if (ferror(stdout) != 0 || fclose(stdout) != 0) {
173*7c478bd9Sstevel@tonic-gate 		perror(prog);
174*7c478bd9Sstevel@tonic-gate 		exit(6);
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	return (0);
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate /*
181*7c478bd9Sstevel@tonic-gate  * copy from in to out, encoding as you go along.
182*7c478bd9Sstevel@tonic-gate  */
183*7c478bd9Sstevel@tonic-gate static void
184*7c478bd9Sstevel@tonic-gate encode(FILE *in, FILE *out, int base64)
185*7c478bd9Sstevel@tonic-gate {
186*7c478bd9Sstevel@tonic-gate 	unsigned char in_buf[80];
187*7c478bd9Sstevel@tonic-gate 	unsigned char out_buf[112];
188*7c478bd9Sstevel@tonic-gate 	unsigned char *iptr, *optr;
189*7c478bd9Sstevel@tonic-gate 	int i;
190*7c478bd9Sstevel@tonic-gate 	size_t n, opos;
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	if (! base64) {
193*7c478bd9Sstevel@tonic-gate 		/* historical algorithm */
194*7c478bd9Sstevel@tonic-gate 
195*7c478bd9Sstevel@tonic-gate 		for (;;) {
196*7c478bd9Sstevel@tonic-gate 			iptr = in_buf;
197*7c478bd9Sstevel@tonic-gate 			optr = out_buf;
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 			/* 1 (up to) 45 character line */
200*7c478bd9Sstevel@tonic-gate 			n = fread(iptr, 1, 45, in);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 			*(optr++) = ENC(n);
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < n; i += 3) {
205*7c478bd9Sstevel@tonic-gate 				*(optr++) = ENC(*iptr >> 2);
206*7c478bd9Sstevel@tonic-gate 				*(optr++) = ENC((*iptr << 4) & 060 |
207*7c478bd9Sstevel@tonic-gate 				    (*(iptr + 1) >> 4) & 017);
208*7c478bd9Sstevel@tonic-gate 				*(optr++) = ENC((*(iptr + 1) << 2) & 074 |
209*7c478bd9Sstevel@tonic-gate 				    (*(iptr + 2) >> 6) & 03);
210*7c478bd9Sstevel@tonic-gate 				*(optr++) = ENC(*(iptr + 2) & 077);
211*7c478bd9Sstevel@tonic-gate 				iptr += 3;
212*7c478bd9Sstevel@tonic-gate 			}
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 			*(optr++) = '\n';
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 			/*LINTED*/
217*7c478bd9Sstevel@tonic-gate 			(void) fwrite(out_buf, 1, (size_t)(optr - out_buf),
218*7c478bd9Sstevel@tonic-gate 			    out);
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 			if (ferror(out)) {
221*7c478bd9Sstevel@tonic-gate 				perror(prog);
222*7c478bd9Sstevel@tonic-gate 				exit(6);
223*7c478bd9Sstevel@tonic-gate 			}
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 			if (n == 0)
226*7c478bd9Sstevel@tonic-gate 				break;
227*7c478bd9Sstevel@tonic-gate 		}
228*7c478bd9Sstevel@tonic-gate 	} else {
229*7c478bd9Sstevel@tonic-gate 		/* base64 algorithm */
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 			optr = out_buf;
232*7c478bd9Sstevel@tonic-gate 			/*
233*7c478bd9Sstevel@tonic-gate 			 * read must be a multiple of 3 bytes for
234*7c478bd9Sstevel@tonic-gate 			 * this algorithm to work, and also must
235*7c478bd9Sstevel@tonic-gate 			 * be small enough that read_size * (4/3)
236*7c478bd9Sstevel@tonic-gate 			 * will always be 76 bytes or less, since
237*7c478bd9Sstevel@tonic-gate 			 * base64 lines can be no longer than that
238*7c478bd9Sstevel@tonic-gate 			 */
239*7c478bd9Sstevel@tonic-gate 			while ((n = fread(in_buf, 1, 51, in)) > 0) {
240*7c478bd9Sstevel@tonic-gate 				opos = 0;
241*7c478bd9Sstevel@tonic-gate 				iptr = in_buf;
242*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < n / 3; i++) {
243*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC(*iptr >> 2);
244*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC((*iptr << 4) & 060 |
245*7c478bd9Sstevel@tonic-gate 					    (*(iptr + 1) >> 4) & 017);
246*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC((*(iptr + 1) << 2)
247*7c478bd9Sstevel@tonic-gate 					    & 074 | (*(iptr + 2) >> 6) & 03);
248*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC(*(iptr + 2) & 077);
249*7c478bd9Sstevel@tonic-gate 					iptr += 3;
250*7c478bd9Sstevel@tonic-gate 					opos += 3;
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 					/* need output padding ? */
253*7c478bd9Sstevel@tonic-gate 					if (n - opos < 3)
254*7c478bd9Sstevel@tonic-gate 						break;
255*7c478bd9Sstevel@tonic-gate 
256*7c478bd9Sstevel@tonic-gate 					(void) fwrite(out_buf, 1,
257*7c478bd9Sstevel@tonic-gate 					    /*LINTED*/
258*7c478bd9Sstevel@tonic-gate 					    (size_t)(optr - out_buf), out);
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 					if (ferror(out)) {
261*7c478bd9Sstevel@tonic-gate 						perror(prog);
262*7c478bd9Sstevel@tonic-gate 						exit(6);
263*7c478bd9Sstevel@tonic-gate 					}
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 					optr = out_buf;
266*7c478bd9Sstevel@tonic-gate 				}
267*7c478bd9Sstevel@tonic-gate 				/*
268*7c478bd9Sstevel@tonic-gate 				 * Take care of any output padding that is
269*7c478bd9Sstevel@tonic-gate 				 * necessary.
270*7c478bd9Sstevel@tonic-gate 				 */
271*7c478bd9Sstevel@tonic-gate 				assert(n - opos < 3);
272*7c478bd9Sstevel@tonic-gate 				switch (n - opos) {
273*7c478bd9Sstevel@tonic-gate 				case 0:
274*7c478bd9Sstevel@tonic-gate 					/* no-op  - 24 bits of data encoded */
275*7c478bd9Sstevel@tonic-gate 					*(optr++) = '\n';
276*7c478bd9Sstevel@tonic-gate 					break;
277*7c478bd9Sstevel@tonic-gate 				case 1:
278*7c478bd9Sstevel@tonic-gate 					/* 8 bits encoded - pad with 2 '=' */
279*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC((*iptr & 0xFC) >> 2);
280*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC((*iptr & 0x03) << 4);
281*7c478bd9Sstevel@tonic-gate 					*(optr++) = '=';
282*7c478bd9Sstevel@tonic-gate 					*(optr++) = '=';
283*7c478bd9Sstevel@tonic-gate 					*(optr++) = '\n';
284*7c478bd9Sstevel@tonic-gate 					break;
285*7c478bd9Sstevel@tonic-gate 				case 2:
286*7c478bd9Sstevel@tonic-gate 					/* 16 bits encoded - pad with 1 '=' */
287*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC((*iptr & 0xFC) >> 2);
288*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC(((*iptr & 0x03) << 4) |
289*7c478bd9Sstevel@tonic-gate 					    ((*(iptr + 1) & 0xF0) >> 4));
290*7c478bd9Sstevel@tonic-gate 					*(optr++) = ENC((*(iptr + 1) & 0x0F)
291*7c478bd9Sstevel@tonic-gate 					    << 2);
292*7c478bd9Sstevel@tonic-gate 					*(optr++) = '=';
293*7c478bd9Sstevel@tonic-gate 					*(optr++) = '\n';
294*7c478bd9Sstevel@tonic-gate 					break;
295*7c478bd9Sstevel@tonic-gate 				default:
296*7c478bd9Sstevel@tonic-gate 					/* impossible */
297*7c478bd9Sstevel@tonic-gate 					break;
298*7c478bd9Sstevel@tonic-gate 				}
299*7c478bd9Sstevel@tonic-gate 				(void) fwrite(out_buf, 1,
300*7c478bd9Sstevel@tonic-gate 				    /*LINTED*/
301*7c478bd9Sstevel@tonic-gate 				    (size_t)(optr - out_buf), out);
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate 				if (ferror(out)) {
304*7c478bd9Sstevel@tonic-gate 					perror(prog);
305*7c478bd9Sstevel@tonic-gate 					exit(6);
306*7c478bd9Sstevel@tonic-gate 				}
307*7c478bd9Sstevel@tonic-gate 
308*7c478bd9Sstevel@tonic-gate 				optr = out_buf;
309*7c478bd9Sstevel@tonic-gate 			}
310*7c478bd9Sstevel@tonic-gate 	}
311*7c478bd9Sstevel@tonic-gate }
312