xref: /csrg-svn/usr.bin/uudecode/uudecode.c (revision 38475)
134953Sbostic /*
234953Sbostic  * Copyright (c) 1983 Regents of the University of California.
334953Sbostic  * All rights reserved.
434953Sbostic  *
534953Sbostic  * Redistribution and use in source and binary forms are permitted
634953Sbostic  * provided that the above copyright notice and this paragraph are
734953Sbostic  * duplicated in all such forms and that any documentation,
834953Sbostic  * advertising materials, and other materials related to such
934953Sbostic  * distribution and use acknowledge that the software was developed
1034953Sbostic  * by the University of California, Berkeley.  The name of the
1134953Sbostic  * University may not be used to endorse or promote products derived
1234953Sbostic  * from this software without specific prior written permission.
1334953Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1434953Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1534953Sbostic  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1634953Sbostic  */
1734953Sbostic 
1813681Ssam #ifndef lint
19*38475Sbostic static char sccsid[] = "@(#)uudecode.c	5.7 (Berkeley) 07/19/89";
2034953Sbostic #endif /* not lint */
2113681Ssam 
2213681Ssam /*
23*38475Sbostic  * uudecode [file ...]
2413681Ssam  *
2513681Ssam  * create the specified file, decoding as you go.
2613681Ssam  * used with uuencode.
2713681Ssam  */
28*38475Sbostic #include <sys/param.h>
2937845Sbostic #include <sys/stat.h>
30*38475Sbostic #include <pwd.h>
3113681Ssam #include <stdio.h>
32*38475Sbostic #include <strings.h>
3313681Ssam 
34*38475Sbostic char *filename;
3513681Ssam 
36*38475Sbostic /* ARGSUSED */
3713681Ssam main(argc, argv)
38*38475Sbostic 	int argc;
39*38475Sbostic 	char **argv;
4013681Ssam {
41*38475Sbostic 	extern int errno;
42*38475Sbostic 	int rval;
4313681Ssam 
44*38475Sbostic 	if (*++argv) {
45*38475Sbostic 		rval = 0;
46*38475Sbostic 		do {
47*38475Sbostic 			if (!freopen(filename = *argv, "r", stdin)) {
48*38475Sbostic 				(void)fprintf(stderr, "uudecode: %s: %s\n",
49*38475Sbostic 				    *argv, strerror(errno));
50*38475Sbostic 				rval = 1;
51*38475Sbostic 				continue;
52*38475Sbostic 			}
53*38475Sbostic 			rval |= decode();
54*38475Sbostic 		} while (*++argv);
55*38475Sbostic 	} else {
56*38475Sbostic 		filename = "stdin";
57*38475Sbostic 		rval = decode();
5813681Ssam 	}
59*38475Sbostic 	exit(rval);
60*38475Sbostic }
6113681Ssam 
62*38475Sbostic decode()
63*38475Sbostic {
64*38475Sbostic 	extern int errno;
65*38475Sbostic 	struct passwd *pw;
66*38475Sbostic 	register int n;
67*38475Sbostic 	register char ch, *p;
68*38475Sbostic 	int mode, n1;
69*38475Sbostic 	char buf[MAXPATHLEN];
70*38475Sbostic 
7113681Ssam 	/* search for header line */
72*38475Sbostic 	do {
73*38475Sbostic 		if (!fgets(buf, sizeof(buf), stdin)) {
74*38475Sbostic 			(void)fprintf(stderr,
75*38475Sbostic 			    "uudecode: %s: no \"begin\" line\n", filename);
76*38475Sbostic 			return(1);
7713681Ssam 		}
78*38475Sbostic 	} while (strncmp(buf, "begin ", 6));
79*38475Sbostic 	(void)sscanf(buf, "begin %o %s", &mode, buf);
8013681Ssam 
8113681Ssam 	/* handle ~user/file format */
82*38475Sbostic 	if (buf[0] == '~') {
83*38475Sbostic 		if (!(p = index(buf, '/'))) {
84*38475Sbostic 			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
85*38475Sbostic 			    filename);
86*38475Sbostic 			return(1);
8713681Ssam 		}
88*38475Sbostic 		*p++ = NULL;
89*38475Sbostic 		if (!(pw = getpwnam(buf + 1))) {
90*38475Sbostic 			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
91*38475Sbostic 			    filename, buf);
92*38475Sbostic 			return(1);
9313681Ssam 		}
94*38475Sbostic 		n = strlen(pw->pw_dir);
95*38475Sbostic 		n1 = strlen(p);
96*38475Sbostic 		if (n + n1 + 2 > MAXPATHLEN) {
97*38475Sbostic 			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
98*38475Sbostic 			    filename);
99*38475Sbostic 			return(1);
100*38475Sbostic 		}
101*38475Sbostic 		bcopy(p, buf + n + 1, n1 + 1);
102*38475Sbostic 		bcopy(pw->pw_dir, buf, n);
103*38475Sbostic 		buf[n] = '/';
10413681Ssam 	}
10513681Ssam 
106*38475Sbostic 	/* create output file, set mode */
107*38475Sbostic 	if (!freopen(buf, "w", stdout) || fchmod(fileno(stdout), mode)) {
108*38475Sbostic 		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
109*38475Sbostic 		    filename, strerror(errno));
110*38475Sbostic 		return(1);
11113681Ssam 	}
11213681Ssam 
113*38475Sbostic 	/* for each input line */
11413681Ssam 	for (;;) {
115*38475Sbostic 		if (!fgets(p = buf, sizeof(buf), stdin)) {
116*38475Sbostic 			(void)fprintf(stderr, "uudecode: %s: short file.\n",
117*38475Sbostic 			    filename);
118*38475Sbostic 			return(1);
11913681Ssam 		}
120*38475Sbostic #define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
121*38475Sbostic 		/*
122*38475Sbostic 		 * `n' is used to avoid writing out all the characters
123*38475Sbostic 		 * at the end of the file.
124*38475Sbostic 		 */
125*38475Sbostic 		if ((n = DEC(*p)) <= 0)
12613681Ssam 			break;
127*38475Sbostic 		for (++p; n > 0; p += 4, n -= 3)
128*38475Sbostic 			if (n >= 3) {
129*38475Sbostic 				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
130*38475Sbostic 				putchar(ch);
131*38475Sbostic 				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
132*38475Sbostic 				putchar(ch);
133*38475Sbostic 				ch = DEC(p[2]) << 6 | DEC(p[3]);
134*38475Sbostic 				putchar(ch);
135*38475Sbostic 			}
136*38475Sbostic 			else {
137*38475Sbostic 				if (n >= 1) {
138*38475Sbostic 					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
139*38475Sbostic 					putchar(ch);
140*38475Sbostic 				}
141*38475Sbostic 				if (n >= 2) {
142*38475Sbostic 					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
143*38475Sbostic 					putchar(ch);
144*38475Sbostic 				}
145*38475Sbostic 				if (n >= 3) {
146*38475Sbostic 					ch = DEC(p[2]) << 6 | DEC(p[3]);
147*38475Sbostic 					putchar(ch);
148*38475Sbostic 				}
149*38475Sbostic 			}
15013681Ssam 	}
151*38475Sbostic 	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
152*38475Sbostic 		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
153*38475Sbostic 		    filename);
154*38475Sbostic 		return(1);
155*38475Sbostic 	}
156*38475Sbostic 	return(0);
15713681Ssam }
15813681Ssam 
159*38475Sbostic usage()
16013681Ssam {
161*38475Sbostic 	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
162*38475Sbostic 	exit(1);
16313681Ssam }
164