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