1/*- 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1983, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#if 0 41#ifndef lint 42static char sccsid[] = "@(#)uudecode.c 8.2 (Berkeley) 4/2/94"; 43#endif /* not lint */ 44#endif 45 46#include <sys/cdefs.h>
|
47__FBSDID("$FreeBSD: head/usr.bin/uudecode/uudecode.c 103201 2002-09-10 20:53:46Z fanf $");
|
47__FBSDID("$FreeBSD: head/usr.bin/uudecode/uudecode.c 103203 2002-09-10 21:10:33Z fanf $"); |
48 49/* 50 * uudecode [file ...] 51 * 52 * create the specified file, decoding as you go. 53 * used with uuencode. 54 */ 55#include <sys/param.h> 56#include <sys/socket.h> 57#include <sys/stat.h> 58 59#include <netinet/in.h> 60 61#include <err.h> 62#include <pwd.h> 63#include <resolv.h> 64#include <stdio.h> 65#include <stdlib.h> 66#include <string.h> 67#include <unistd.h> 68 69const char *filename; 70char *outfile; 71int cflag, iflag, oflag, pflag, sflag; 72 73static void usage(void); 74int decode(void); 75int decode2(void);
|
76void base64_decode(const char *);
|
76int base64_decode(const char *); |
77 78int 79main(int argc, char *argv[]) 80{ 81 int rval, ch; 82 83 while ((ch = getopt(argc, argv, "cio:ps")) != -1) { 84 switch(ch) { 85 case 'c': 86 if (oflag) 87 usage(); 88 cflag = 1; /* multiple uudecode'd files */ 89 break; 90 case 'i': 91 iflag = 1; /* ask before override files */ 92 break; 93 case 'o': 94 if (cflag || pflag || sflag) 95 usage(); 96 oflag = 1; /* output to the specified file */ 97 sflag = 1; /* do not strip pathnames for output */ 98 outfile = optarg; /* set the output filename */ 99 break; 100 case 'p': 101 if (oflag) 102 usage(); 103 pflag = 1; /* print output to stdout */ 104 break; 105 case 's': 106 if (oflag) 107 usage(); 108 sflag = 1; /* do not strip pathnames for output */ 109 break; 110 default: 111 usage(); 112 } 113 } 114 argc -= optind; 115 argv += optind; 116 117 if (*argv) { 118 rval = 0; 119 do { 120 if (freopen(filename = *argv, "r", stdin) == NULL) { 121 warn("%s", *argv); 122 rval = 1; 123 continue; 124 } 125 rval |= decode(); 126 } while (*++argv); 127 } else { 128 filename = "stdin"; 129 rval = decode(); 130 } 131 exit(rval); 132} 133 134int 135decode(void) 136{ 137 int r, v; 138 139 v = decode2(); 140 if (v == EOF) { 141 warnx("%s: missing or bad \"begin\" line", filename); 142 return (1); 143 } 144 for (r = v; cflag; r |= v) { 145 v = decode2(); 146 if (v == EOF) 147 break; 148 } 149 return (r); 150} 151 152int 153decode2(void) 154{ 155 int base64; 156 int n; 157 char ch, *p, *q; 158 void *mode; 159 struct passwd *pw; 160 struct stat st; 161 char buf[MAXPATHLEN+1]; 162 char buffn[MAXPATHLEN+1]; /* file name buffer */ 163 164 base64 = 0; 165 /* search for header line */ 166 for (;;) { 167 if (fgets(buf, sizeof(buf), stdin) == NULL) 168 return (EOF); 169 p = buf; 170 if (strncmp(p, "begin-base64 ", 13) == 0) { 171 base64 = 1; 172 p += 13; 173 } else if (strncmp(p, "begin ", 6) == 0) 174 p += 6; 175 else 176 continue; 177 /* p points to mode */ 178 q = strchr(p, ' '); 179 if (q == NULL) 180 continue; 181 *q++ = '\0'; 182 /* q points to filename */ 183 n = strlen(q); 184 while (n > 0 && (q[n-1] == '\n' || q[n-1] == '\r')) 185 q[--n] = '\0'; 186 /* found valid header? */ 187 if (n > 0) 188 break; 189 } 190 191 mode = setmode(p); 192 if (mode == NULL) { 193 warnx("%s: unable to parse file mode", filename); 194 return (1); 195 } 196 197 if (oflag) { 198 /* use command-line filename */ 199 n = strlcpy(buffn, outfile, sizeof(buffn)); 200 } else if (sflag) { 201 /* don't strip, so try ~user/file expansion */ 202 p = NULL; 203 pw = NULL; 204 if (*q == '~') 205 p = strchr(q, '/'); 206 if (p != NULL) { 207 *p = '\0'; 208 pw = getpwnam(q + 1); 209 *p = '/'; 210 } 211 if (pw != NULL) { 212 strlcpy(buffn, pw->pw_dir, sizeof(buffn)); 213 n = strlcat(buffn, p, sizeof(buffn)); 214 } else { 215 n = strlcpy(buffn, q, sizeof(buffn)); 216 } 217 } else { 218 /* strip down to leaf name */ 219 p = strrchr(q, '/'); 220 if (p != NULL) 221 n = strlcpy(buffn, p+1, sizeof(buffn)); 222 else 223 n = strlcpy(buffn, q, sizeof(buffn)); 224 } 225 if (n >= sizeof(buffn) || *buffn == '\0') { 226 warnx("%s: bad output filename", filename); 227 return (1); 228 } 229 230 if (!pflag) { 231 if (iflag && !access(buffn, F_OK)) { 232 warnx("not overwritten: %s", buffn); 233 return (0); 234 } 235 if (freopen(buffn, "w", stdout) == NULL || 236 stat(buffn, &st) < 0 || (S_ISREG(st.st_mode) && 237 fchmod(fileno(stdout), getmode(mode, 0) & 0666) < 0)) { 238 warn("%s: %s", filename, buffn); 239 return (1); 240 } 241 } 242 free(mode); 243
|
244 if (base64) 245 return (base64_decode(buffn)); 246 |
247 /* for each input line */ 248 for (;;) { 249 if (fgets(p = buf, sizeof(buf), stdin) == NULL) { 250 warnx("%s: short file", filename); 251 return (1); 252 }
|
250 if (base64) {
251 if (strncmp(buf, "====", 4) == 0)
252 return (0);
253 base64_decode(buf);
254 continue;
255 }
|
253 |
254#define DEC(c) (((c) - ' ') & 077) /* single character decode */ 255#define IS_DEC(c) ( (((c) - ' ') >= 0) && (((c) - ' ') <= 077 + 1) ) 256/* #define IS_DEC(c) (1) */ 257 258#define OUT_OF_RANGE \ 259{ \ 260 warnx( \ 261"\n\tinput file: %s\n\tencoded file: %s\n\tcharacter out of range: [%d-%d]", \ 262 filename, buffn, 1 + ' ', 077 + ' ' + 1); \ 263 return (1); \ 264} 265 266 /* 267 * `n' is used to avoid writing out all the characters 268 * at the end of the file. 269 */ 270 if ((n = DEC(*p)) <= 0) 271 break; 272 for (++p; n > 0; p += 4, n -= 3) 273 if (n >= 3) { 274 if (!(IS_DEC(*p) && IS_DEC(*(p + 1)) && 275 IS_DEC(*(p + 2)) && IS_DEC(*(p + 3)))) 276 OUT_OF_RANGE 277 278 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 279 putchar(ch); 280 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 281 putchar(ch); 282 ch = DEC(p[2]) << 6 | DEC(p[3]); 283 putchar(ch); 284 } 285 else { 286 if (n >= 1) { 287 if (!(IS_DEC(*p) && IS_DEC(*(p + 1)))) 288 OUT_OF_RANGE 289 ch = DEC(p[0]) << 2 | DEC(p[1]) >> 4; 290 putchar(ch); 291 } 292 if (n >= 2) { 293 if (!(IS_DEC(*(p + 1)) && 294 IS_DEC(*(p + 2)))) 295 OUT_OF_RANGE 296 297 ch = DEC(p[1]) << 4 | DEC(p[2]) >> 2; 298 putchar(ch); 299 } 300 if (n >= 3) { 301 if (!(IS_DEC(*(p + 2)) && 302 IS_DEC(*(p + 3)))) 303 OUT_OF_RANGE 304 ch = DEC(p[2]) << 6 | DEC(p[3]); 305 putchar(ch); 306 } 307 } 308 } 309 if (fgets(buf, sizeof(buf), stdin) == NULL || 310 (strcmp(buf, "end") && strcmp(buf, "end\n") && 311 strcmp(buf, "end\r\n"))) { 312 warnx("%s: no \"end\" line", filename); 313 return (1); 314 } 315 return (0); 316} 317
|
320void
321base64_decode(const char *stream)
|
318int 319base64_decode(const char *outname) |
320{
|
321 int n; 322 char buf[MAXPATHLEN+1]; |
323 unsigned char out[MAXPATHLEN * 4];
|
324 int rv;
|
324
|
326 if (index(stream, '\r') != NULL)
327 *index(stream, '\r') = '\0';
328 if (index(stream, '\n') != NULL)
329 *index(stream, '\n') = '\0';
330 rv = b64_pton(stream, out, (sizeof(out) / sizeof(out[0])));
331 if (rv == -1)
332 errx(1, "b64_pton: error decoding base64 input stream");
333 fwrite(out, 1, rv, stdout);
|
325 for (;;) { 326 if (fgets(buf, sizeof(buf), stdin) == NULL) { 327 warnx("%s: short file", filename); 328 return (1); 329 } 330 if (strcmp(buf, "====") == 0 || 331 strcmp(buf, "====\n") == 0 || 332 strcmp(buf, "====\r\n") == 0) 333 return (0); 334 n = strlen(buf); 335 while (n > 0 && (buf[n-1] == '\n' || buf[n-1] == '\r')) 336 buf[--n] = '\0'; 337 n = b64_pton(buf, out, sizeof(out)); 338 if (n < 0) { 339 warnx("%s: %s: error decoding base64 input stream", filename, outname); 340 return (1); 341 } 342 fwrite(out, 1, n, stdout); 343 } |
344} 345 346static void 347usage(void) 348{ 349 (void)fprintf(stderr, 350"usage: uudecode [-cips] [file ...]\n" 351" uudecode [-i] -o output_file [file]\n" 352" b64decode [-cips] [file ...]\n" 353" b64decode [-i] -o output_file [file]\n"); 354 exit(1); 355}
|