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
main(argc,argv)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
decode()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
usage()157 usage()
158 {
159 (void)fprintf(stderr, "usage: uudecode [file ...]\n");
160 exit(1);
161 }
162