Print this page
5218 posix definition of NULL
correct unistd.h and iso/stddef_iso.h
update gate source affected
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/bnu/uudecode.c
+++ new/usr/src/cmd/bnu/uudecode.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License, Version 1.0 only
6 6 * (the "License"). You may not use this file except in compliance
7 7 * with the License.
8 8 *
9 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 10 * or http://www.opensolaris.org/os/licensing.
11 11 * See the License for the specific language governing permissions
12 12 * and limitations under the License.
13 13 *
14 14 * When distributing Covered Code, include this CDDL HEADER in each
15 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 16 * If applicable, add the following below this CDDL HEADER, with the
17 17 * fields enclosed by brackets "[]" replaced with your own identifying
18 18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 19 *
20 20 * CDDL HEADER END
21 21 */
22 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 23 /* All Rights Reserved */
24 24
25 25 /* Copyright 2004 Sun Microsystems, Inc. All rights reserved. */
26 26 /* Use is subject to license terms. */
27 27
28 28 #pragma ident "%Z%%M% %I% %E% SMI"
29 29
30 30 /*
31 31 * uudecode [-o outfile | -p] [input]
32 32 *
33 33 * create the specified file, decoding as you go.
34 34 * used with uuencode.
35 35 */
36 36 #include <unistd.h>
37 37 #include <stdio.h>
38 38 #include <stdlib.h>
39 39 #include <pwd.h>
40 40 #include <string.h>
41 41 #include <strings.h>
42 42 #include <sys/types.h>
43 43 #include <sys/stat.h>
44 44 #include <locale.h>
45 45 #include <nl_types.h>
46 46 #include <langinfo.h>
47 47 #include <iconv.h>
48 48 #include <limits.h>
49 49 #include <errno.h>
50 50 #include <ctype.h>
51 51 #include <signal.h>
52 52 #include <stdarg.h>
53 53
54 54 #define BUFSIZE 90 /* must be a multiple of 3 */
55 55
56 56 #define TABLE_SIZE 0x40
57 57
58 58 #define isvalid(octet) (octet <= 0x40)
59 59
60 60 /*
61 61 * base64 decoding table
62 62 */
63 63 /* BEGIN CSTYLED */
64 64 static char base64tab[] = {
65 65 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
66 66 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
67 67 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
68 68 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
69 69 '\377', '\377', '\377', '\377', '\377', '\377', '\377', '\377',
70 70 '\377', '\377', '\377', 62, '\377', '\377', '\377', 63,
71 71 52, 53, 54, 55, 56, 57, 58, 59,
72 72 60, 61, '\377', '\377', '\377', '\377', '\377', '\377',
73 73 '\377', 0, 1, 2, 3, 4, 5, 6,
74 74 7, 8, 9, 10, 11, 12, 13, 14,
75 75 15, 16, 17, 18, 19, 20, 21, 22,
76 76 23, 24, 25, '\377', '\377', '\377', '\377', '\377',
77 77 '\377', 26, 27, 28, 29, 30, 31, 32,
78 78 33, 34, 35, 36, 37, 38, 39, 40,
79 79 41, 42, 43, 44, 45, 46, 47, 48,
80 80 49, 50, 51, '\377', '\377', '\377', '\377', '\377'
81 81 };
82 82 /* END CSTYLED */
83 83
84 84 static char decode_table[UCHAR_MAX + 1];
85 85
86 86 /* DEC is the basic 1 character decoding function (historical algorithm) */
87 87 #define DEC(c) decode_table[c]
88 88
89 89 /* true if the character is in the base64 encoding table */
90 90 #define validbase64(c) (('A' <= (c) && (c) <= 'Z') || \
91 91 ('a' <= (c) && (c) <= 'z') || \
92 92 ('0' <= (c) && (c) <= '9') || \
93 93 (c) == '+' || (c) == '/')
94 94
95 95 static void decode(FILE *, FILE *, int);
96 96 static int outdec(unsigned char *, unsigned char *, int);
97 97 static int outdec64(unsigned char *, unsigned char *, int);
98 98
99 99 /* from usr/src/cmd/chmod/common.c */
100 100
101 101 void errmsg(int severity, int code, char *format, ...);
102 102
103 103 extern mode_t newmode(char *ms, mode_t new_mode, mode_t umsk,
104 104 char *file, char *path);
105 105
106 106 static char *prog;
107 107 static char outfile[PATH_MAX];
108 108 static int mode_err = 0; /* mode conversion error flag */
109 109
110 110 int
111 111 main(int argc, char **argv)
112 112 {
113 113 FILE *in, *out;
114 114 int pipeout = 0;
115 115 int oflag = 0;
116 116 int i;
117 117 mode_t mode, p_umask;
118 118 char dest[PATH_MAX];
119 119 char modebits[1024];
120 120 char buf[LINE_MAX];
121 121 int c, errflag = 0;
122 122 struct stat sbuf;
123 123 int base64flag = 0;
124 124
125 125 prog = argv[0];
126 126 (void) signal(SIGPIPE, SIG_DFL);
127 127 bzero(dest, sizeof (dest));
128 128 outfile[0] = '\0';
129 129
130 130 /* Set locale environment variables local definitions */
131 131 (void) setlocale(LC_ALL, "");
132 132 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
133 133 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
134 134 #endif
135 135 (void) textdomain(TEXT_DOMAIN);
136 136 p_umask = umask((mode_t)0);
137 137
138 138 while ((c = getopt(argc, argv, "o:p")) != EOF) {
139 139 switch (c) {
140 140 case 'o':
141 141 oflag++;
142 142 (void) strncpy(outfile, optarg, sizeof (outfile));
143 143 break;
144 144 case 'p':
145 145 pipeout++;
146 146 break;
147 147 default:
148 148 case '?':
149 149 errflag++;
150 150 break;
151 151 }
152 152 }
153 153 argc -= optind;
154 154 argv = &argv[optind];
155 155
156 156 /* optional input arg */
157 157 if (argc > 0) {
158 158 if ((in = fopen(*argv, "r")) == NULL) {
159 159 perror(*argv);
160 160 exit(1);
161 161 }
162 162 argv++; argc--;
163 163 } else {
164 164 in = stdin;
165 165 errno = 0;
166 166 if (fstat(fileno(in), &sbuf) < 0) {
167 167 perror("stdin");
168 168 exit(1);
169 169 }
170 170 }
171 171
172 172 if ((argc > 0) || errflag || (oflag && pipeout)) {
173 173 (void) fprintf(stderr,
174 174 gettext("Usage: %s [-o outfile | -p] [infile]\n"), prog);
175 175 exit(2);
176 176 }
177 177
178 178 /* search for header line */
179 179 for (;;) {
180 180 if (fgets(buf, sizeof (buf), in) == NULL) {
181 181 /* suppress message if we printed a mode error */
182 182 if (mode_err == 0)
183 183 (void) fprintf(stderr,
184 184 gettext("No begin line\n"));
185 185 exit(3);
186 186 }
187 187 /*
188 188 * the check for begin-base64 obviously needs to come
189 189 * first, since both algorithms' begin strings start
190 190 * with 'begin'. Also verify that there is a valid
191 191 * octal or symbolic file mode.
192 192 */
193 193 if (strncmp(buf, "begin-base64", 12) == 0) {
194 194 base64flag = 1;
195 195 mode_err = 0;
196 196 if ((sscanf(buf + 13, "%1023s %1023s",
197 197 modebits, dest) == 2) &&
198 198 ((sscanf(modebits, "%lo", &mode) == 1) ||
199 199 ((mode = newmode(modebits, 0, p_umask,
200 200 "", "")) != 0) && mode_err == 0))
201 201 break;
202 202 } else if (strncmp(buf, "begin", 5) == 0) {
203 203 base64flag = 0;
204 204 mode_err = 0;
205 205 if ((sscanf(buf + 6, "%1023s %1023s",
206 206 modebits, dest) == 2) &&
207 207 ((sscanf(modebits, "%lo", &mode) == 1) ||
208 208 ((mode = newmode(modebits, 0, p_umask,
209 209 "", "")) != 0) && mode_err == 0))
210 210 break;
211 211 }
212 212 }
213 213
214 214 /*
215 215 * Now that we know the type of encoding used, we can
216 216 * initialize the decode table.
217 217 */
218 218 if (base64flag == 0) {
219 219 (void) memset(decode_table, 0xFF, sizeof (decode_table));
220 220 for (i = 0; i <= TABLE_SIZE; i++)
221 221 decode_table[(unsigned char)i + 0x20] =
222 222 (unsigned char)i & 0x3F;
223 223 } else
224 224 (void) memcpy(decode_table, base64tab, sizeof (base64tab));
225 225
226 226 /*
227 227 * Filename specified on the command line with -o
228 228 * overrides filename in the encoded file.
229 229 */
230 230 if (outfile[0] != '\0')
231 231 (void) strncpy(dest, outfile, sizeof (dest));
232 232
233 233 if (pipeout ||
234 234 (dest[0] == '-' && dest[1] == '\0' && outfile[0] == '\0')) {
235 235 out = stdout;
236 236 bzero(outfile, sizeof (outfile));
237 237 bzero(dest, sizeof (dest));
238 238 } else {
239 239 /* handle ~user/file format */
240 240 if (dest[0] == '~') {
241 241 char *sl;
242 242 struct passwd *user;
243 243 char dnbuf[100];
244 244
245 245 sl = strchr(dest, '/');
246 246 if (sl == NULL) {
247 247 (void) fprintf(stderr,
248 248 gettext("Illegal ~user\n"));
249 249 exit(3);
250 250 }
251 251 *sl++ = 0;
252 252 user = getpwnam(dest+1);
253 253 if (user == NULL) {
254 254 (void) fprintf(stderr,
255 255 gettext("No such user as %s\n"), dest);
256 256 exit(4);
257 257 }
258 258 (void) strncpy(dnbuf, user->pw_dir, sizeof (dnbuf));
259 259 (void) strlcat(dnbuf, "/", sizeof (dnbuf));
260 260 (void) strlcat(dnbuf, sl, sizeof (dnbuf));
261 261 (void) strncpy(dest, dnbuf, sizeof (dest));
262 262 }
263 263 }
264 264 /* if not using stdout, create file */
265 265 if (dest[0] != '\0') {
266 266 if ((out = fopen(dest, "w")) == NULL) {
267 267 perror(dest);
268 268 exit(4);
269 269 }
270 270 (void) chmod(dest, mode & 0777);
271 271 }
272 272
273 273 decode(in, out, base64flag);
274 274
275 275 if (fclose(out) == EOF) {
276 276 perror(prog);
277 277 exit(6);
278 278 }
279 279
280 280 return (0);
281 281 }
282 282
283 283 /*
284 284 * copy from in to out, decoding as you go along.
285 285 */
286 286
287 287 static void
288 288 decode(FILE *in, FILE *out, int base64)
289 289 {
290 290 char inbuf[120], *ibp, *iptr;
291 291 unsigned char outbuf[BUFSIZE], *obp, *optr;
292 292 int n, octets, warned, endseen, numbase64chars;
293 293 unsigned char chr[4], curchr, ch;
294 294 longlong_t line;
295 295
296 296 if (! base64) { /* use historical algorithm */
297 297 warned = 0;
298 298 for (line = 1; ; line++) {
299 299 /* for each input line */
300 300 if (fgets(inbuf, sizeof (inbuf), in) == NULL) {
301 301 (void) fprintf(stderr,
302 302 gettext("No end line\n"));
303 303 exit(5);
304 304 }
305 305
306 306 /* Is line == 'end\n'? */
307 307 if (strcmp(inbuf, "end\n") == 0) {
308 308 break;
309 309 }
310 310
311 311 n = DEC(inbuf[0]);
312 312
313 313 if (n < 0)
314 314 continue;
315 315
316 316 /*
317 317 * Decode data lines.
318 318 *
319 319 * Note that uuencode/uudecode uses only the portable
320 320 * character set for encoded data and the portable
321 321 * character set characters must be represented in
322 322 * a single byte. We use this knowledge to reuse
323 323 * buffer space while decoding.
324 324 */
325 325 octets = n;
326 326 obp = (unsigned char *) &inbuf[0];
327 327 ibp = &inbuf[1];
328 328 while (octets > 0) {
329 329 if ((ch = outdec((unsigned char *)obp,
330 330 (unsigned char *)ibp, octets))
331 331 != 0x20) {
332 332 /* invalid characters where detected */
333 333 if (!warned) {
334 334 warned = 1;
335 335 (void) fprintf(stderr,
336 336 gettext("Invalid character"
337 337 " (0x%x) on line"
338 338 " %lld\n"), ch, line);
339 339 }
340 340 break;
341 341 }
342 342 ibp += 4;
343 343 obp += 3;
344 344 octets -= 3;
345 345 }
346 346 /*
347 347 * Only write out uncorrupted lines
348 348 */
↓ open down ↓ |
348 lines elided |
↑ open up ↑ |
349 349 if (octets <= 0) {
350 350 (void) fwrite(inbuf, n, 1, out);
351 351 }
352 352 }
353 353 } else { /* use base64 algorithm */
354 354 endseen = numbase64chars = 0;
355 355 optr = outbuf;
356 356 while ((fgets(inbuf, sizeof (inbuf), in)) != NULL) {
357 357 /* process an input line */
358 358 iptr = inbuf;
359 - while ((curchr = *(iptr++)) != NULL) {
359 + while ((curchr = *(iptr++)) != '\0') {
360 360 /* decode chars */
361 361 if (curchr == '=') /* if end */
362 362 endseen++;
363 363
364 364 if (validbase64(curchr))
365 365 chr[numbase64chars++] = curchr;
366 366 /*
367 367 * if we've gathered 4 base64 octets
368 368 * we need to decode and output them
369 369 */
370 370 if (numbase64chars == 4) {
371 371 /*LINTED*/
372 372 if (optr - outbuf > BUFSIZE - 3) {
373 373 (void) fwrite(outbuf,
374 374 /*LINTED*/
375 375 (size_t)(optr - outbuf),
376 376 1, out);
377 377 if (ferror(out)) {
378 378 perror(prog);
379 379 exit(6);
380 380 }
381 381 optr = outbuf;
382 382 }
383 383 octets = outdec64(optr, chr, 4);
384 384 optr += octets;
385 385 numbase64chars = 0;
386 386 }
387 387 }
388 388 /*
389 389 * handle any remaining base64 octets at end
390 390 */
391 391 if (endseen && numbase64chars > 0) {
392 392 octets = outdec64(optr, chr, numbase64chars);
393 393 optr += octets;
394 394 numbase64chars = 0;
395 395 }
396 396 }
397 397 /*
398 398 * if we have generated any additional output
399 399 * in the buffer, write it out
400 400 */
401 401 if (optr != outbuf) {
402 402 /*LINTED*/
403 403 (void) fwrite(outbuf, (size_t)(optr - outbuf),
404 404 1, out);
405 405 if (ferror(out)) {
406 406 perror(prog);
407 407 exit(6);
408 408 }
409 409 }
410 410
411 411 if (endseen == 0) {
412 412 (void) fprintf(stderr, gettext("No end line\n"));
413 413 exit(5);
414 414 }
415 415 }
416 416 }
417 417
418 418 /*
419 419 * historical algorithm
420 420 *
421 421 * output a group of 3 bytes (4 input characters).
422 422 * the input chars are pointed to by p, they are to
423 423 * be output to file f. n is used to tell us not to
424 424 * output all of them at the end of the file.
425 425 */
426 426
427 427 static int
428 428 outdec(unsigned char *out, unsigned char *in, int n)
429 429 {
430 430 unsigned char b0 = DEC(*(in++));
431 431 unsigned char b1 = DEC(*(in++));
432 432 unsigned char b2 = DEC(*(in++));
433 433 unsigned char b3 = DEC(*in);
434 434
435 435 if (!isvalid(b0)) {
436 436 return (*(in-3));
437 437 }
438 438 if (!isvalid(b1)) {
439 439 return (*(in-2));
440 440 }
441 441
442 442 *(out++) = (b0 << 2) | (b1 >> 4);
443 443
444 444 if (n >= 2) {
445 445 if (!isvalid(b2)) {
446 446 return (*(in - 1));
447 447 }
448 448
449 449 *(out++) = (b1 << 4) | (b2 >> 2);
450 450
451 451 if (n >= 3) {
452 452 if (!isvalid(b3)) {
453 453 return (*in);
454 454 }
455 455 *out = (b2 << 6) | b3;
456 456 }
457 457 }
458 458 return (0x20); /* a know good value */
459 459 }
460 460
461 461 /*
462 462 * base64 algorithm
463 463 *
464 464 * Takes a pointer to the current position in the output buffer,
465 465 * a pointer to the (up to) 4 byte base64 input buffer and a
466 466 * count of the number of valid input bytes.
467 467 *
468 468 * Return the number of bytes placed in the output buffer
469 469 */
470 470 static int
471 471 outdec64(unsigned char *out, unsigned char *chr, int num)
472 472 {
473 473
474 474 unsigned char char1, char2, char3, char4;
475 475 unsigned char *outptr = out;
476 476 int rc = 0;
477 477
478 478 switch (num) {
479 479 case 0:
480 480 case 1: /* these are impossible */
481 481 default:
482 482 break;
483 483 case 2: /* 2 base64 bytes == 1 decoded byte */
484 484 char1 = base64tab[chr[0]] & 0xFF;
485 485 char2 = base64tab[chr[1]] & 0xFF;
486 486 *(outptr++) = ((char1 << 2) & 0xFC) |
487 487 ((char2 >> 4) & 0x03);
488 488 rc = 1;
489 489 break;
490 490 case 3: /* 3 base64 bytes == 2 decoded bytes */
491 491 char1 = base64tab[chr[0]] & 0xFF;
492 492 char2 = base64tab[chr[1]] & 0xFF;
493 493 char3 = base64tab[chr[2]] & 0xFF;
494 494 *(outptr++) = ((char1 << 2) & 0xFC) |
495 495 ((char2 >> 4) & 0x03);
496 496 *(outptr++) = ((char2 << 4) & 0xF0) |
497 497 ((char3 >> 2) & 0x0F);
498 498 rc = 2;
499 499 break;
500 500 case 4: /* 4 base64 bytes == 3 decoded bytes */
501 501 char1 = base64tab[chr[0]] & 0xFF;
502 502 char2 = base64tab[chr[1]] & 0xFF;
503 503 char3 = base64tab[chr[2]] & 0xFF;
504 504 char4 = base64tab[chr[3]] & 0xFF;
505 505 *(outptr++) = ((char1 << 2) & 0xFC) |
506 506 ((char2 >> 4) & 0x03);
507 507 *(outptr++) = ((char2 << 4) & 0xF0) |
508 508 ((char3 >> 2) & 0x0F);
509 509 *(outptr++) = ((char3 << 6) & 0xC0) |
510 510 (char4 & 0x3F);
511 511 rc = 3;
512 512 break;
513 513 }
514 514 return (rc);
515 515 }
516 516
517 517 /*
518 518 * error message routine called by newmode.
519 519 *
520 520 * The severity and code are ignored here. If this routine gets
521 521 * called, we set a global flag (which can be tested after return
522 522 * from here) which tells us whether or not a valid mode has been
523 523 * parsed or if we printed an error message.
524 524 */
525 525
526 526 /*ARGSUSED*/
527 527 void
528 528 errmsg(int severity, int code, char *format, ...)
529 529 {
530 530 va_list ap;
531 531
532 532 va_start(ap, format);
533 533
534 534 (void) fprintf(stderr, "uudecode: ");
535 535 (void) fprintf(stderr, format, ap);
536 536
537 537 va_end(ap);
538 538
539 539 mode_err = 1;
540 540 }
↓ open down ↓ |
171 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX