xref: /csrg-svn/usr.bin/uudecode/uudecode.c (revision 42049)
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*42049Sbostic static char sccsid[] = "@(#)uudecode.c	5.9 (Berkeley) 05/15/90";
2034953Sbostic #endif /* not lint */
2113681Ssam 
2213681Ssam /*
2338475Sbostic  * uudecode [file ...]
2413681Ssam  *
2513681Ssam  * create the specified file, decoding as you go.
2613681Ssam  * used with uuencode.
2713681Ssam  */
2838475Sbostic #include <sys/param.h>
2937845Sbostic #include <sys/stat.h>
3038475Sbostic #include <pwd.h>
3113681Ssam #include <stdio.h>
32*42049Sbostic #include <string.h>
3313681Ssam 
3438475Sbostic char *filename;
3513681Ssam 
3638475Sbostic /* ARGSUSED */
3713681Ssam main(argc, argv)
3838475Sbostic 	int argc;
3938475Sbostic 	char **argv;
4013681Ssam {
4138475Sbostic 	extern int errno;
4238475Sbostic 	int rval;
4313681Ssam 
4438475Sbostic 	if (*++argv) {
4538475Sbostic 		rval = 0;
4638475Sbostic 		do {
4738475Sbostic 			if (!freopen(filename = *argv, "r", stdin)) {
4838475Sbostic 				(void)fprintf(stderr, "uudecode: %s: %s\n",
4938475Sbostic 				    *argv, strerror(errno));
5038475Sbostic 				rval = 1;
5138475Sbostic 				continue;
5238475Sbostic 			}
5338475Sbostic 			rval |= decode();
5438475Sbostic 		} while (*++argv);
5538475Sbostic 	} else {
5638475Sbostic 		filename = "stdin";
5738475Sbostic 		rval = decode();
5813681Ssam 	}
5938475Sbostic 	exit(rval);
6038475Sbostic }
6113681Ssam 
6238475Sbostic decode()
6338475Sbostic {
6438475Sbostic 	extern int errno;
6538475Sbostic 	struct passwd *pw;
6638475Sbostic 	register int n;
6738475Sbostic 	register char ch, *p;
6838475Sbostic 	int mode, n1;
6938475Sbostic 	char buf[MAXPATHLEN];
7038475Sbostic 
7113681Ssam 	/* search for header line */
7238475Sbostic 	do {
7338475Sbostic 		if (!fgets(buf, sizeof(buf), stdin)) {
7438475Sbostic 			(void)fprintf(stderr,
7538475Sbostic 			    "uudecode: %s: no \"begin\" line\n", filename);
7638475Sbostic 			return(1);
7713681Ssam 		}
7838475Sbostic 	} while (strncmp(buf, "begin ", 6));
7938475Sbostic 	(void)sscanf(buf, "begin %o %s", &mode, buf);
8013681Ssam 
8113681Ssam 	/* handle ~user/file format */
8238475Sbostic 	if (buf[0] == '~') {
8338475Sbostic 		if (!(p = index(buf, '/'))) {
8438475Sbostic 			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
8538475Sbostic 			    filename);
8638475Sbostic 			return(1);
8713681Ssam 		}
8838475Sbostic 		*p++ = NULL;
8938475Sbostic 		if (!(pw = getpwnam(buf + 1))) {
9038475Sbostic 			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
9138475Sbostic 			    filename, buf);
9238475Sbostic 			return(1);
9313681Ssam 		}
9438475Sbostic 		n = strlen(pw->pw_dir);
9538475Sbostic 		n1 = strlen(p);
9638475Sbostic 		if (n + n1 + 2 > MAXPATHLEN) {
9738475Sbostic 			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
9838475Sbostic 			    filename);
9938475Sbostic 			return(1);
10038475Sbostic 		}
10138475Sbostic 		bcopy(p, buf + n + 1, n1 + 1);
10238475Sbostic 		bcopy(pw->pw_dir, buf, n);
10338475Sbostic 		buf[n] = '/';
10413681Ssam 	}
10513681Ssam 
10638475Sbostic 	/* create output file, set mode */
10738720Sbostic 	if (!freopen(buf, "w", stdout) ||
10838720Sbostic 	    fchmod(fileno(stdout), mode&0666)) {
10938475Sbostic 		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
11038475Sbostic 		    filename, strerror(errno));
11138475Sbostic 		return(1);
11213681Ssam 	}
11313681Ssam 
11438475Sbostic 	/* for each input line */
11513681Ssam 	for (;;) {
11638475Sbostic 		if (!fgets(p = buf, sizeof(buf), stdin)) {
11738475Sbostic 			(void)fprintf(stderr, "uudecode: %s: short file.\n",
11838475Sbostic 			    filename);
11938475Sbostic 			return(1);
12013681Ssam 		}
12138475Sbostic #define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
12238475Sbostic 		/*
12338475Sbostic 		 * `n' is used to avoid writing out all the characters
12438475Sbostic 		 * at the end of the file.
12538475Sbostic 		 */
12638475Sbostic 		if ((n = DEC(*p)) <= 0)
12713681Ssam 			break;
12838475Sbostic 		for (++p; n > 0; p += 4, n -= 3)
12938475Sbostic 			if (n >= 3) {
13038475Sbostic 				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
13138475Sbostic 				putchar(ch);
13238475Sbostic 				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
13338475Sbostic 				putchar(ch);
13438475Sbostic 				ch = DEC(p[2]) << 6 | DEC(p[3]);
13538475Sbostic 				putchar(ch);
13638475Sbostic 			}
13738475Sbostic 			else {
13838475Sbostic 				if (n >= 1) {
13938475Sbostic 					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
14038475Sbostic 					putchar(ch);
14138475Sbostic 				}
14238475Sbostic 				if (n >= 2) {
14338475Sbostic 					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
14438475Sbostic 					putchar(ch);
14538475Sbostic 				}
14638475Sbostic 				if (n >= 3) {
14738475Sbostic 					ch = DEC(p[2]) << 6 | DEC(p[3]);
14838475Sbostic 					putchar(ch);
14938475Sbostic 				}
15038475Sbostic 			}
15113681Ssam 	}
15238475Sbostic 	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
15338475Sbostic 		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
15438475Sbostic 		    filename);
15538475Sbostic 		return(1);
15638475Sbostic 	}
15738475Sbostic 	return(0);
15813681Ssam }
15913681Ssam 
16038475Sbostic usage()
16113681Ssam {
16238475Sbostic 	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
16338475Sbostic 	exit(1);
16413681Ssam }
165