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