1 /*
2 * bdecode [file]
3 */
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "coder.h"
8
9 /* forwards */
10 void fatal(const char *s);
11
12 const char *myname, *inputfile = "(stdin)";
13
main(argc,argv)14 main(argc, argv)
15 char **argv;
16 {
17 register long word;
18 register int c, bcount;
19 register FILE *fin = stdin, *fout = stdout; /* in regs for speed */
20 register char *map, *p;
21 register long nbytes;
22 register unsigned crc;
23 long nbytes2;
24 unsigned w, crc2;
25 char buf[512];
26
27 myname = argv[0];
28 if (sizeof(word) < 4)
29 fprintf(stderr, "%s: word size too small\n", myname), exit(1);
30 if (argc > 2)
31 fprintf(stderr, "Usage: %s [file]\n", myname), exit(1);
32 if (argc == 2) {
33 if ((fin = fopen(argv[1], "r")) == NULL) {
34 fprintf(stderr, "%s: ", myname);
35 perror(argv[1]);
36 exit(1);
37 }
38 inputfile = argv[1];
39 }
40 /* skip to beginning of encoded data */
41 do {
42 if (fgets(buf, sizeof buf, fin) == NULL)
43 fatal("Missing header");
44 /* trim trailing blanks (sigh) */
45 p = strchr(buf, '\n');
46 if (p == 0)
47 continue;
48 while (*--p == ' ')
49 ;
50 p[1] = '\n';
51 p[2] = '\0';
52 } while (strcmp(buf, header) != 0);
53
54 /* define input mapping table */
55 map = buf+1;
56 for (c = 0; c < 256; c++)
57 map[c] = 64; /* illegal */
58 for (c = 0; c < 64; c++)
59 map[ENCODE(c)] = c;
60 map[EOF] = 65; /* special cases */
61 map['/'] = 66;
62
63 word = 0;
64 bcount = 4;
65 nbytes = 0;
66 crc = 0;
67 #define PUTC(x) { c = (x) & 0xff; CRC(crc, c); putc(c, fout); nbytes++; }
68 for (;;) {
69 c = map[getc(fin)];
70 if ((unsigned)c < 64) {
71 word <<= 6;
72 word |= c;
73 if (--bcount == 0) {
74 PUTC(word >> 16);
75 PUTC(word >> 8);
76 PUTC(word);
77 word = 0;
78 bcount = 4;
79 }
80 continue;
81 }
82 switch (c) {
83
84 default:
85 /*
86 * Ignore stuff not in the code set.
87 */
88 continue;
89
90 case 65: /* EOF */
91 fatal("Unexpected EOF");
92
93 case 66: /* '/' */
94 /* trailer follows: %d%x */
95 c = getc(fin);
96 if (fscanf(fin, "%x", &w) != 1)
97 fatal("Corrupted input (trailer)");
98 switch (c) {
99 case '2': PUTC(w >> 8);
100 case '1': PUTC(w);
101 case '0': break;
102 default: fatal("Corrupted input (trailer)");
103 }
104 /*
105 * Byte count and CRC follow.
106 */
107 if (fscanf(fin, "%ld%x", &nbytes2, &crc2) != 2)
108 fatal("Corrupted input (missing byte count/CRC)");
109 if (nbytes2 != nbytes)
110 fatal("Corrupted input (byte count is wrong)");
111 if (crc2 != (crc & 0xffff))
112 fatal("Corrupted input (CRC mismatch)");
113 exit(0);
114 }
115 }
116 }
117
118 void
fatal(s)119 fatal(s)
120 const char *s;
121 {
122 fprintf(stderr, "%s: %s: %s\n", myname, inputfile, s);
123 exit(2);
124 }
125