chiark / gitweb /
Fix completion checking in Killer Solo.
[sgt-puzzles.git] / obfusc.c
1 /*
2  * Stand-alone tool to access the Puzzles obfuscation algorithm.
3  * 
4  * To deobfuscate, use "obfusc -d":
5  * 
6  *   obfusc -d                 reads binary data from stdin, writes to stdout
7  *   obfusc -d <hex string>    works on the given hex string instead of stdin
8  *   obfusc -d -h              writes a hex string instead of binary to stdout
9  *
10  * To obfuscate, "obfusc -e":
11  * 
12  *   obfusc -e                 reads binary from stdin, writes hex to stdout
13  *   obfusc -e <hex string>    works on the given hex string instead of stdin
14  *   obfusc -e -b              writes binary instead of text to stdout
15  *
16  * The default output format is hex for -e and binary for -d
17  * because that's the way obfuscation is generally used in
18  * Puzzles. Either of -b and -h can always be specified to set it
19  * explicitly.
20  *
21  * Data read from standard input is assumed always to be binary;
22  * data provided on the command line is taken to be hex.
23  */
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <errno.h>
30
31 #include "puzzles.h"
32
33 int main(int argc, char **argv)
34 {
35     enum { BINARY, DEFAULT, HEX } outputmode = DEFAULT;
36     char *inhex = NULL;
37     unsigned char *data;
38     int datalen;
39     int decode = -1;
40     int doing_opts = TRUE;
41
42     while (--argc > 0) {
43         char *p = *++argv;
44
45         if (doing_opts && *p == '-') {
46             if (!strcmp(p, "--")) {
47                 doing_opts = 0;
48                 continue;
49             }
50             p++;
51             while (*p) {
52                 switch (*p) {
53                   case 'e':
54                     decode = 0;
55                     break;
56                   case 'd':
57                     decode = 1;
58                     break;
59                   case 'b':
60                     outputmode = BINARY;
61                     break;
62                   case 'h':
63                     outputmode = HEX;
64                     break;
65                   default:
66                     fprintf(stderr, "obfusc: unrecognised option '-%c'\n",
67                             *p);
68                     return 1;
69                 }
70                 p++;
71             }
72         } else {
73             if (!inhex) {
74                 inhex = p;
75             } else {
76                 fprintf(stderr, "obfusc: expected at most one argument\n");
77                 return 1;
78             }
79         }
80     }
81
82     if (decode < 0) {
83         fprintf(stderr, "usage: obfusc < -e | -d > [ -b | -h ] [hex data]\n");
84         return 0;
85     }
86
87     if (outputmode == DEFAULT)
88         outputmode = (decode ? BINARY : HEX);
89
90     if (inhex) {
91         datalen = strlen(inhex) / 2;
92         data = hex2bin(inhex, datalen);
93     } else {
94         int datasize = 4096;
95         datalen = 0;
96         data = snewn(datasize, unsigned char);
97         while (1) {
98             int ret = fread(data + datalen, 1, datasize - datalen, stdin);
99             if (ret < 0) {
100                 fprintf(stderr, "obfusc: read: %s\n", strerror(errno));
101                 return 1;
102             } else if (ret == 0) {
103                 break;
104             } else {
105                 datalen += ret;
106                 if (datasize - datalen < 4096) {
107                     datasize = datalen * 5 / 4 + 4096;
108                     data = sresize(data, datasize, unsigned char);
109                 }
110             }
111         }
112     }
113
114     obfuscate_bitmap(data, datalen * 8, decode);
115
116     if (outputmode == BINARY) {
117         int ret = fwrite(data, 1, datalen, stdout);
118         if (ret < 0) {
119             fprintf(stderr, "obfusc: write: %s\n", strerror(errno));
120             return 1;
121         }
122     } else {
123         int i;
124         for (i = 0; i < datalen; i++)
125             printf("%02x", data[i]);
126         printf("\n");
127     }
128
129     return 0;
130 }