xref: /original-bsd/usr.bin/uudecode/uudecode.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1983, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char sccsid[] = "@(#)uudecode.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 /*
13  * uudecode [file ...]
14  *
15  * create the specified file, decoding as you go.
16  * used with uuencode.
17  */
18 #include <sys/param.h>
19 #include <sys/stat.h>
20 #include <pwd.h>
21 #include <stdio.h>
22 #include <string.h>
23 
24 char *filename;
25 
26 /* ARGSUSED */
27 main(argc, argv)
28 	int argc;
29 	char **argv;
30 {
31 	extern int errno;
32 	int rval;
33 
34 	if (*++argv) {
35 		rval = 0;
36 		do {
37 			if (!freopen(filename = *argv, "r", stdin)) {
38 				(void)fprintf(stderr, "uudecode: %s: %s\n",
39 				    *argv, strerror(errno));
40 				rval = 1;
41 				continue;
42 			}
43 			rval |= decode();
44 		} while (*++argv);
45 	} else {
46 		filename = "stdin";
47 		rval = decode();
48 	}
49 	exit(rval);
50 }
51 
52 decode()
53 {
54 	extern int errno;
55 	struct passwd *pw;
56 	register int n;
57 	register char ch, *p;
58 	int mode, n1;
59 	char buf[MAXPATHLEN];
60 
61 	/* search for header line */
62 	do {
63 		if (!fgets(buf, sizeof(buf), stdin)) {
64 			(void)fprintf(stderr,
65 			    "uudecode: %s: no \"begin\" line\n", filename);
66 			return(1);
67 		}
68 	} while (strncmp(buf, "begin ", 6));
69 	(void)sscanf(buf, "begin %o %s", &mode, buf);
70 
71 	/* handle ~user/file format */
72 	if (buf[0] == '~') {
73 		if (!(p = index(buf, '/'))) {
74 			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
75 			    filename);
76 			return(1);
77 		}
78 		*p++ = NULL;
79 		if (!(pw = getpwnam(buf + 1))) {
80 			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
81 			    filename, buf);
82 			return(1);
83 		}
84 		n = strlen(pw->pw_dir);
85 		n1 = strlen(p);
86 		if (n + n1 + 2 > MAXPATHLEN) {
87 			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
88 			    filename);
89 			return(1);
90 		}
91 		bcopy(p, buf + n + 1, n1 + 1);
92 		bcopy(pw->pw_dir, buf, n);
93 		buf[n] = '/';
94 	}
95 
96 	/* create output file, set mode */
97 	if (!freopen(buf, "w", stdout) ||
98 	    fchmod(fileno(stdout), mode&0666)) {
99 		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
100 		    filename, strerror(errno));
101 		return(1);
102 	}
103 
104 	/* for each input line */
105 	for (;;) {
106 		if (!fgets(p = buf, sizeof(buf), stdin)) {
107 			(void)fprintf(stderr, "uudecode: %s: short file.\n",
108 			    filename);
109 			return(1);
110 		}
111 #define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
112 		/*
113 		 * `n' is used to avoid writing out all the characters
114 		 * at the end of the file.
115 		 */
116 		if ((n = DEC(*p)) <= 0)
117 			break;
118 		for (++p; n > 0; p += 4, n -= 3)
119 			if (n >= 3) {
120 				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
121 				putchar(ch);
122 				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
123 				putchar(ch);
124 				ch = DEC(p[2]) << 6 | DEC(p[3]);
125 				putchar(ch);
126 			}
127 			else {
128 				if (n >= 1) {
129 					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
130 					putchar(ch);
131 				}
132 				if (n >= 2) {
133 					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
134 					putchar(ch);
135 				}
136 				if (n >= 3) {
137 					ch = DEC(p[2]) << 6 | DEC(p[3]);
138 					putchar(ch);
139 				}
140 			}
141 	}
142 	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
143 		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
144 		    filename);
145 		return(1);
146 	}
147 	return(0);
148 }
149 
150 usage()
151 {
152 	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
153 	exit(1);
154 }
155