Annotation of src/usr.bin/uudecode/uudecode.c, Revision 1.5
1.5 ! deraadt 1: /* $OpenBSD: uudecode.c,v 1.4 1998/05/11 01:19:05 deraadt Exp $ */
1.1 deraadt 2: /* $NetBSD: uudecode.c,v 1.6 1994/11/17 07:40:43 jtc Exp $ */
3:
4: /*-
5: * Copyright (c) 1983, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: */
36:
37: char copyright[] =
38: "@(#) Copyright (c) 1983, 1993\n\
39: The Regents of the University of California. All rights reserved.\n";
40:
41: #ifndef lint
42: #if 0
43: static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94";
44: #endif
1.5 ! deraadt 45: static char rcsid[] = "$OpenBSD: uudecode.c,v 1.4 1998/05/11 01:19:05 deraadt Exp $";
1.1 deraadt 46: #endif /* not lint */
47:
48: /*
49: * uudecode [file ...]
50: *
51: * create the specified file, decoding as you go.
52: * used with uuencode.
53: */
54: #include <stdio.h>
55: #include <string.h>
56: #include <locale.h>
57: #include <errno.h>
58: #include <sys/param.h>
59: #include <sys/stat.h>
60:
61: #include <pwd.h>
62: #include <unistd.h>
63:
64: static int decode();
65: static void usage();
66: char *filename;
67:
68: int
69: main(argc, argv)
70: int argc;
71: char *argv[];
72: {
73: int rval;
74:
75: setlocale(LC_ALL, "");
76:
77: while (getopt(argc, argv, "") != -1)
78: usage();
79: argc -= optind;
80: argv += optind;
81:
82: if (*argv) {
83: rval = 0;
84: do {
85: if (!freopen(filename = *argv, "r", stdin)) {
86: (void)fprintf(stderr, "uudecode: %s: %s\n",
87: *argv, strerror(errno));
88: rval = 1;
89: continue;
90: }
91: rval |= decode();
92: } while (*++argv);
93: } else {
94: filename = "stdin";
95: rval = decode();
96: }
97: exit(rval);
98: }
99:
100: static int
101: decode()
102: {
103: extern int errno;
104: struct passwd *pw;
105: register int n;
106: register char ch, *p;
107: int mode, n1;
108: char buf[MAXPATHLEN];
109:
110: /* search for header line */
111: do {
112: if (!fgets(buf, sizeof(buf), stdin)) {
113: (void)fprintf(stderr,
114: "uudecode: %s: no \"begin\" line\n", filename);
115: return(1);
116: }
117: } while (strncmp(buf, "begin ", 6));
1.5 ! deraadt 118: (void)sscanf(buf, "begin %o %1023[^\n\r]", &mode, buf);
1.1 deraadt 119:
120: /* handle ~user/file format */
121: if (buf[0] == '~') {
1.3 millert 122: if (!(p = strchr(buf, '/'))) {
1.1 deraadt 123: (void)fprintf(stderr, "uudecode: %s: illegal ~user.\n",
124: filename);
125: return(1);
126: }
127: *p++ = NULL;
128: if (!(pw = getpwnam(buf + 1))) {
129: (void)fprintf(stderr, "uudecode: %s: no user %s.\n",
130: filename, buf);
131: return(1);
132: }
133: n = strlen(pw->pw_dir);
134: n1 = strlen(p);
135: if (n + n1 + 2 > MAXPATHLEN) {
136: (void)fprintf(stderr, "uudecode: %s: path too long.\n",
137: filename);
138: return(1);
139: }
140: bcopy(p, buf + n + 1, n1 + 1);
141: bcopy(pw->pw_dir, buf, n);
142: buf[n] = '/';
143: }
144:
145: /* create output file, set mode */
146: if (!freopen(buf, "w", stdout) ||
147: fchmod(fileno(stdout), mode&0666)) {
148: (void)fprintf(stderr, "uudecode: %s: %s: %s\n", buf,
149: filename, strerror(errno));
150: return(1);
151: }
152:
153: /* for each input line */
154: for (;;) {
155: if (!fgets(p = buf, sizeof(buf), stdin)) {
156: (void)fprintf(stderr, "uudecode: %s: short file.\n",
157: filename);
158: return(1);
159: }
160: #define DEC(c) (((c) - ' ') & 077) /* single character decode */
161: /*
162: * `n' is used to avoid writing out all the characters
163: * at the end of the file.
164: */
165: if ((n = DEC(*p)) <= 0)
166: break;
167: for (++p; n > 0; p += 4, n -= 3)
168: if (n >= 3) {
169: ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
170: putchar(ch);
171: ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
172: putchar(ch);
173: ch = DEC(p[2]) << 6 | DEC(p[3]);
174: putchar(ch);
175: }
176: else {
177: if (n >= 1) {
178: ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4;
179: putchar(ch);
180: }
181: if (n >= 2) {
182: ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2;
183: putchar(ch);
184: }
185: if (n >= 3) {
186: ch = DEC(p[2]) << 6 | DEC(p[3]);
187: putchar(ch);
188: }
189: }
190: }
191: if (!fgets(buf, sizeof(buf), stdin) || strcmp(buf, "end\n")) {
192: (void)fprintf(stderr, "uudecode: %s: no \"end\" line.\n",
193: filename);
194: return(1);
195: }
196: return(0);
197: }
198:
199: static void
200: usage()
201: {
202: (void)fprintf(stderr, "usage: uudecode [file ...]\n");
203: exit(1);
204: }