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