xref: /csrg-svn/usr.bin/uudecode/uudecode.c (revision 66660)
1*66660Sbostic /*-
262415Sbostic  * Copyright (c) 1983, 1993
362415Sbostic  *	The Regents of the University of California.  All rights reserved.
434953Sbostic  *
542781Sbostic  * %sccs.include.redist.c%
634953Sbostic  */
734953Sbostic 
813681Ssam #ifndef lint
9*66660Sbostic char copyright[] =
10*66660Sbostic "@(#) Copyright (c) 1983, 1993\n\
11*66660Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1234953Sbostic #endif /* not lint */
1313681Ssam 
14*66660Sbostic #ifndef lint
15*66660Sbostic static char sccsid[] = "@(#)uudecode.c	8.2 (Berkeley) 04/02/94";
16*66660Sbostic #endif /* not lint */
17*66660Sbostic 
1813681Ssam /*
1938475Sbostic  * uudecode [file ...]
2013681Ssam  *
2113681Ssam  * create the specified file, decoding as you go.
2213681Ssam  * used with uuencode.
2313681Ssam  */
2438475Sbostic #include <sys/param.h>
2537845Sbostic #include <sys/stat.h>
26*66660Sbostic 
2738475Sbostic #include <pwd.h>
2813681Ssam #include <stdio.h>
2942049Sbostic #include <string.h>
3013681Ssam 
3138475Sbostic char *filename;
3213681Ssam 
33*66660Sbostic int
main(argc,argv)3413681Ssam main(argc, argv)
3538475Sbostic 	int argc;
36*66660Sbostic 	char *argv[];
3713681Ssam {
3838475Sbostic 	extern int errno;
3938475Sbostic 	int rval;
4013681Ssam 
4138475Sbostic 	if (*++argv) {
4238475Sbostic 		rval = 0;
4338475Sbostic 		do {
4438475Sbostic 			if (!freopen(filename = *argv, "r", stdin)) {
4538475Sbostic 				(void)fprintf(stderr, "uudecode: %s: %s\n",
4638475Sbostic 				    *argv, strerror(errno));
4738475Sbostic 				rval = 1;
4838475Sbostic 				continue;
4938475Sbostic 			}
5038475Sbostic 			rval |= decode();
5138475Sbostic 		} while (*++argv);
5238475Sbostic 	} else {
5338475Sbostic 		filename = "stdin";
5438475Sbostic 		rval = decode();
5513681Ssam 	}
5638475Sbostic 	exit(rval);
5738475Sbostic }
5813681Ssam 
decode()5938475Sbostic decode()
6038475Sbostic {
6138475Sbostic 	extern int errno;
6238475Sbostic 	struct passwd *pw;
6338475Sbostic 	register int n;
6438475Sbostic 	register char ch, *p;
6538475Sbostic 	int mode, n1;
6638475Sbostic 	char buf[MAXPATHLEN];
6738475Sbostic 
6813681Ssam 	/* search for header line */
6938475Sbostic 	do {
7038475Sbostic 		if (!fgets(buf, sizeof(buf), stdin)) {
7138475Sbostic 			(void)fprintf(stderr,
7238475Sbostic 			    "uudecode: %s: no \"begin\" line\n", filename);
7338475Sbostic 			return(1);
7413681Ssam 		}
7538475Sbostic 	} while (strncmp(buf, "begin ", 6));
7638475Sbostic 	(void)sscanf(buf, "begin %o %s", &mode, buf);
7713681Ssam 
7813681Ssam 	/* handle ~user/file format */
7938475Sbostic 	if (buf[0] == '~') {
8038475Sbostic 		if (!(p = index(buf, '/'))) {
8138475Sbostic 			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
8238475Sbostic 			    filename);
8338475Sbostic 			return(1);
8413681Ssam 		}
8538475Sbostic 		*p++ = NULL;
8638475Sbostic 		if (!(pw = getpwnam(buf + 1))) {
8738475Sbostic 			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
8838475Sbostic 			    filename, buf);
8938475Sbostic 			return(1);
9013681Ssam 		}
9138475Sbostic 		n = strlen(pw->pw_dir);
9238475Sbostic 		n1 = strlen(p);
9338475Sbostic 		if (n + n1 + 2 > MAXPATHLEN) {
9438475Sbostic 			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
9538475Sbostic 			    filename);
9638475Sbostic 			return(1);
9738475Sbostic 		}
9838475Sbostic 		bcopy(p, buf + n + 1, n1 + 1);
9938475Sbostic 		bcopy(pw->pw_dir, buf, n);
10038475Sbostic 		buf[n] = '/';
10113681Ssam 	}
10213681Ssam 
10338475Sbostic 	/* create output file, set mode */
10438720Sbostic 	if (!freopen(buf, "w", stdout) ||
10538720Sbostic 	    fchmod(fileno(stdout), mode&0666)) {
10638475Sbostic 		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
10738475Sbostic 		    filename, strerror(errno));
10838475Sbostic 		return(1);
10913681Ssam 	}
11013681Ssam 
11138475Sbostic 	/* for each input line */
11213681Ssam 	for (;;) {
11338475Sbostic 		if (!fgets(p = buf, sizeof(buf), stdin)) {
11438475Sbostic 			(void)fprintf(stderr, "uudecode: %s: short file.\n",
11538475Sbostic 			    filename);
11638475Sbostic 			return(1);
11713681Ssam 		}
11838475Sbostic #define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
11938475Sbostic 		/*
12038475Sbostic 		 * `n' is used to avoid writing out all the characters
12138475Sbostic 		 * at the end of the file.
12238475Sbostic 		 */
12338475Sbostic 		if ((n = DEC(*p)) <= 0)
12413681Ssam 			break;
12538475Sbostic 		for (++p; n > 0; p += 4, n -= 3)
12638475Sbostic 			if (n >= 3) {
12738475Sbostic 				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
12838475Sbostic 				putchar(ch);
12938475Sbostic 				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
13038475Sbostic 				putchar(ch);
13138475Sbostic 				ch = DEC(p[2]) << 6 | DEC(p[3]);
13238475Sbostic 				putchar(ch);
13338475Sbostic 			}
13438475Sbostic 			else {
13538475Sbostic 				if (n >= 1) {
13638475Sbostic 					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
13738475Sbostic 					putchar(ch);
13838475Sbostic 				}
13938475Sbostic 				if (n >= 2) {
14038475Sbostic 					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
14138475Sbostic 					putchar(ch);
14238475Sbostic 				}
14338475Sbostic 				if (n >= 3) {
14438475Sbostic 					ch = DEC(p[2]) << 6 | DEC(p[3]);
14538475Sbostic 					putchar(ch);
14638475Sbostic 				}
14738475Sbostic 			}
14813681Ssam 	}
14938475Sbostic 	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
15038475Sbostic 		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
15138475Sbostic 		    filename);
15238475Sbostic 		return(1);
15338475Sbostic 	}
15438475Sbostic 	return(0);
15513681Ssam }
15613681Ssam 
usage()15738475Sbostic usage()
15813681Ssam {
15938475Sbostic 	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
16038475Sbostic 	exit(1);
16113681Ssam }
162