xref: /original-bsd/usr.bin/uudecode/uudecode.c (revision 5e1b3b90)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)uudecode.c	5.9 (Berkeley) 05/15/90";
20 #endif /* not lint */
21 
22 /*
23  * uudecode [file ...]
24  *
25  * create the specified file, decoding as you go.
26  * used with uuencode.
27  */
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <pwd.h>
31 #include <stdio.h>
32 #include <string.h>
33 
34 char *filename;
35 
36 /* ARGSUSED */
37 main(argc, argv)
38 	int argc;
39 	char **argv;
40 {
41 	extern int errno;
42 	int rval;
43 
44 	if (*++argv) {
45 		rval = 0;
46 		do {
47 			if (!freopen(filename = *argv, "r", stdin)) {
48 				(void)fprintf(stderr, "uudecode: %s: %s\n",
49 				    *argv, strerror(errno));
50 				rval = 1;
51 				continue;
52 			}
53 			rval |= decode();
54 		} while (*++argv);
55 	} else {
56 		filename = "stdin";
57 		rval = decode();
58 	}
59 	exit(rval);
60 }
61 
62 decode()
63 {
64 	extern int errno;
65 	struct passwd *pw;
66 	register int n;
67 	register char ch, *p;
68 	int mode, n1;
69 	char buf[MAXPATHLEN];
70 
71 	/* search for header line */
72 	do {
73 		if (!fgets(buf, sizeof(buf), stdin)) {
74 			(void)fprintf(stderr,
75 			    "uudecode: %s: no \"begin\" line\n", filename);
76 			return(1);
77 		}
78 	} while (strncmp(buf, "begin ", 6));
79 	(void)sscanf(buf, "begin %o %s", &mode, buf);
80 
81 	/* handle ~user/file format */
82 	if (buf[0] == '~') {
83 		if (!(p = index(buf, '/'))) {
84 			(void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
85 			    filename);
86 			return(1);
87 		}
88 		*p++ = NULL;
89 		if (!(pw = getpwnam(buf + 1))) {
90 			(void)fprintf(stderr, "uudecode: %s: no user %s.\n",
91 			    filename, buf);
92 			return(1);
93 		}
94 		n = strlen(pw->pw_dir);
95 		n1 = strlen(p);
96 		if (n + n1 + 2 > MAXPATHLEN) {
97 			(void)fprintf(stderr, "uudecode: %s: path too long.\n",
98 			    filename);
99 			return(1);
100 		}
101 		bcopy(p, buf + n + 1, n1 + 1);
102 		bcopy(pw->pw_dir, buf, n);
103 		buf[n] = '/';
104 	}
105 
106 	/* create output file, set mode */
107 	if (!freopen(buf, "w", stdout) ||
108 	    fchmod(fileno(stdout), mode&0666)) {
109 		(void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
110 		    filename, strerror(errno));
111 		return(1);
112 	}
113 
114 	/* for each input line */
115 	for (;;) {
116 		if (!fgets(p = buf, sizeof(buf), stdin)) {
117 			(void)fprintf(stderr, "uudecode: %s: short file.\n",
118 			    filename);
119 			return(1);
120 		}
121 #define	DEC(c)	(((c) - ' ') & 077)		/* single character decode */
122 		/*
123 		 * `n' is used to avoid writing out all the characters
124 		 * at the end of the file.
125 		 */
126 		if ((n = DEC(*p)) <= 0)
127 			break;
128 		for (++p; n > 0; p += 4, n -= 3)
129 			if (n >= 3) {
130 				ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
131 				putchar(ch);
132 				ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
133 				putchar(ch);
134 				ch = DEC(p[2]) << 6 | DEC(p[3]);
135 				putchar(ch);
136 			}
137 			else {
138 				if (n >= 1) {
139 					ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
140 					putchar(ch);
141 				}
142 				if (n >= 2) {
143 					ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
144 					putchar(ch);
145 				}
146 				if (n >= 3) {
147 					ch = DEC(p[2]) << 6 | DEC(p[3]);
148 					putchar(ch);
149 				}
150 			}
151 	}
152 	if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
153 		(void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
154 		    filename);
155 		return(1);
156 	}
157 	return(0);
158 }
159 
160 usage()
161 {
162 	(void)fprintf(stderr, "usage: uudecode [file ...]\n");
163 	exit(1);
164 }
165