xref: /csrg-svn/usr.bin/uudecode/uudecode.c (revision 62415)
134953Sbostic /*
2*62415Sbostic  * Copyright (c) 1983, 1993
3*62415Sbostic  *	The Regents of the University of California.  All rights reserved.
434953Sbostic  *
542781Sbostic  * %sccs.include.redist.c%
634953Sbostic  */
734953Sbostic 
813681Ssam #ifndef lint
9*62415Sbostic static char sccsid[] = "@(#)uudecode.c	8.1 (Berkeley) 06/06/93";
1034953Sbostic #endif /* not lint */
1113681Ssam 
1213681Ssam /*
1338475Sbostic  * uudecode [file ...]
1413681Ssam  *
1513681Ssam  * create the specified file, decoding as you go.
1613681Ssam  * used with uuencode.
1713681Ssam  */
1838475Sbostic #include <sys/param.h>
1937845Sbostic #include <sys/stat.h>
2038475Sbostic #include <pwd.h>
2113681Ssam #include <stdio.h>
2242049Sbostic #include <string.h>
2313681Ssam 
2438475Sbostic char *filename;
2513681Ssam 
2638475Sbostic /* ARGSUSED */
2713681Ssam main(argc, argv)
2838475Sbostic 	int argc;
2938475Sbostic 	char **argv;
3013681Ssam {
3138475Sbostic 	extern int errno;
3238475Sbostic 	int rval;
3313681Ssam 
3438475Sbostic 	if (*++argv) {
3538475Sbostic 		rval = 0;
3638475Sbostic 		do {
3738475Sbostic 			if (!freopen(filename = *argv, "r", stdin)) {
3838475Sbostic 				(void)fprintf(stderr, "uudecode: %s: %s\n",
3938475Sbostic 				    *argv, strerror(errno));
4038475Sbostic 				rval = 1;
4138475Sbostic 				continue;
4238475Sbostic 			}
4338475Sbostic 			rval |= decode();
4438475Sbostic 		} while (*++argv);
4538475Sbostic 	} else {
4638475Sbostic 		filename = "stdin";
4738475Sbostic 		rval = decode();
4813681Ssam 	}
4938475Sbostic 	exit(rval);
5038475Sbostic }
5113681Ssam 
5238475Sbostic decode()
5338475Sbostic {
5438475Sbostic 	extern int errno;
5538475Sbostic 	struct passwd *pw;
5638475Sbostic 	register int n;
5738475Sbostic 	register char ch, *p;
5838475Sbostic 	int mode, n1;
5938475Sbostic 	char buf[MAXPATHLEN];
6038475Sbostic 
6113681Ssam 	/* search for header line */
6238475Sbostic 	do {
6338475Sbostic 		if (!fgets(buf, sizeof(buf), stdin)) {
6438475Sbostic 			(void)fprintf(stderr,
6538475Sbostic 			    "uudecode: %s: no \"begin\" line\n", filename);
6638475Sbostic 			return(1);
6713681Ssam 		}
6838475Sbostic 	} while (strncmp(buf, "begin ", 6));
6938475Sbostic 	(void)sscanf(buf, "begin %o %s", &mode, buf);
7013681Ssam 
7113681Ssam 	/* handle ~user/file format */
7238475Sbostic 	if (buf[0] == '~') {
7338475Sbostic 		if (!(p = index(buf, '/'))) {
7438475Sbostic 			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
7538475Sbostic 			    filename);
7638475Sbostic 			return(1);
7713681Ssam 		}
7838475Sbostic 		*p++ = NULL;
7938475Sbostic 		if (!(pw = getpwnam(buf + 1))) {
8038475Sbostic 			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
8138475Sbostic 			    filename, buf);
8238475Sbostic 			return(1);
8313681Ssam 		}
8438475Sbostic 		n = strlen(pw->pw_dir);
8538475Sbostic 		n1 = strlen(p);
8638475Sbostic 		if (n + n1 + 2 > MAXPATHLEN) {
8738475Sbostic 			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
8838475Sbostic 			    filename);
8938475Sbostic 			return(1);
9038475Sbostic 		}
9138475Sbostic 		bcopy(p, buf + n + 1, n1 + 1);
9238475Sbostic 		bcopy(pw->pw_dir, buf, n);
9338475Sbostic 		buf[n] = '/';
9413681Ssam 	}
9513681Ssam 
9638475Sbostic 	/* create output file, set mode */
9738720Sbostic 	if (!freopen(buf, "w", stdout) ||
9838720Sbostic 	    fchmod(fileno(stdout), mode&0666)) {
9938475Sbostic 		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
10038475Sbostic 		    filename, strerror(errno));
10138475Sbostic 		return(1);
10213681Ssam 	}
10313681Ssam 
10438475Sbostic 	/* for each input line */
10513681Ssam 	for (;;) {
10638475Sbostic 		if (!fgets(p = buf, sizeof(buf), stdin)) {
10738475Sbostic 			(void)fprintf(stderr, "uudecode: %s: short file.\n",
10838475Sbostic 			    filename);
10938475Sbostic 			return(1);
11013681Ssam 		}
11138475Sbostic #define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
11238475Sbostic 		/*
11338475Sbostic 		 * `n' is used to avoid writing out all the characters
11438475Sbostic 		 * at the end of the file.
11538475Sbostic 		 */
11638475Sbostic 		if ((n = DEC(*p)) <= 0)
11713681Ssam 			break;
11838475Sbostic 		for (++p; n > 0; p += 4, n -= 3)
11938475Sbostic 			if (n >= 3) {
12038475Sbostic 				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
12138475Sbostic 				putchar(ch);
12238475Sbostic 				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
12338475Sbostic 				putchar(ch);
12438475Sbostic 				ch = DEC(p[2]) << 6 | DEC(p[3]);
12538475Sbostic 				putchar(ch);
12638475Sbostic 			}
12738475Sbostic 			else {
12838475Sbostic 				if (n >= 1) {
12938475Sbostic 					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
13038475Sbostic 					putchar(ch);
13138475Sbostic 				}
13238475Sbostic 				if (n >= 2) {
13338475Sbostic 					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
13438475Sbostic 					putchar(ch);
13538475Sbostic 				}
13638475Sbostic 				if (n >= 3) {
13738475Sbostic 					ch = DEC(p[2]) << 6 | DEC(p[3]);
13838475Sbostic 					putchar(ch);
13938475Sbostic 				}
14038475Sbostic 			}
14113681Ssam 	}
14238475Sbostic 	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
14338475Sbostic 		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
14438475Sbostic 		    filename);
14538475Sbostic 		return(1);
14638475Sbostic 	}
14738475Sbostic 	return(0);
14813681Ssam }
14913681Ssam 
15038475Sbostic usage()
15113681Ssam {
15238475Sbostic 	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
15338475Sbostic 	exit(1);
15413681Ssam }
155