1 /* primitive arbitrary-data frontend for netcat. 0.9 960226
2 only handles one value per ascii line, but at least parses 0xNN too
3 an input line containing "%r" during "-g" generates a random byte
4
5 todo:
6 make work on msloss jus' for kicks [workin' on it...]
7
8 syntax: data -X [limit]
9 where X is one of
10 d: dump raw bytes to ascii format
11 g: generate raw bytes from ascii input
12 c: generate ??? of value -- NOTYET
13 r: generate all random bytes
14 and limit is how many bytes to generate or dump [unspecified = infinite]
15
16 *Hobbit*, started 951004 or so and randomly screwed around with since */
17
18 #include <stdio.h>
19
20 #ifdef MSDOS /* for MSC only at the moment... */
21 #include <fcntl.h>
22 #else /* MSDOS */
23 #include <sys/file.h>
24 #define HAVE_RANDOM /* XXX: might have to change */
25 #endif /* MSDOS */
26
27 static char buf_in [128];
28 static char buf_raw [8192];
29 static char surveysez[] = "survey sez... XXX\n";
30
31 /* fgetss :
32 wrapper for fgets, that yanks trailing newlines. Doing the work ourselves
33 instead of calling strchr/strlen/whatever */
fgetss(buf,len,from)34 char * fgetss (buf, len, from)
35 char * buf;
36 size_t len;
37 FILE * from;
38 {
39 register int x;
40 register char * p, * q;
41 p = fgets (buf, len, from); /* returns ptr to buf */
42 if (! p)
43 return (NULL);
44 q = p;
45 for (x = 0; x < len; x++) {
46 *p = (*p & 0x7f); /* rip parity, just in case */
47 switch (*p) {
48 case '\n':
49 case '\r':
50 case '\0':
51 *p = '\0';
52 return (q);
53 } /* switch */
54 p++;
55 } /* for */
56 } /* fgetss */
57
58 /* randint:
59 swiped from rndb.c. Generates an INT, you have to mask down to char. */
randint()60 int randint()
61 {
62 register int q;
63 register int x;
64
65 #ifndef HAVE_RANDOM
66 q = rand();
67 #else
68 q = random();
69 #endif
70 x = ((q >> 8) & 0xff); /* perturb low byte using some higher bits */
71 x = q ^ x;
72 return (x);
73 }
74
main(argc,argv)75 main (argc, argv)
76 int argc;
77 char ** argv;
78 {
79 register unsigned char * p;
80 register char * q;
81 register int x;
82 int bc = 0;
83 int limit = 0; /* num to gen, or 0 = infinite */
84 register int xlimit; /* running limit */
85 FILE * txt; /* line-by-line ascii file */
86 int raw; /* raw bytes fd */
87 int dumping = 0; /* cmd flags ... */
88 int genning = 0;
89 int randing = 0;
90
91 memset (buf_in, 0, sizeof (buf_in));
92 memset (buf_raw, 0, sizeof (buf_raw));
93
94 xlimit = 1; /* doubles as "exit flag" */
95 bc = 1; /* preload, assuming "dump" */
96 x = getpid() + 687319;
97 /* if your library doesnt have srandom/random, use srand/rand. [from rnd.c] */
98 #ifndef HAVE_RANDOM
99 srand (time(0) + x);
100 #else
101 srandom (time(0) + x);
102 #endif
103
104 #ifdef O_BINARY
105 /* DOS stupidity */
106 /* Aha: *here's* where that setmode() lib call conflict in ?BSD came from */
107 x = setmode (0, O_BINARY); /* make stdin raw */
108 if (x < 0) {
109 fprintf (stderr, "stdin binary setmode oops: %d\n", x);
110 exit (1);
111 }
112 x = setmode (1, O_BINARY); /* make stdout raw */
113 if (x < 0) {
114 fprintf (stderr, "stdout binary setmode oops: %d\n", x);
115 exit (1);
116 }
117 #endif /* O_BINARY */
118
119 if (argv[1]) {
120 p = argv[1]; /* shit-simple single arg parser... */
121 if (*p == '-') /* dash is optional, we'll deal */
122 p++;
123 if (*p == 'd')
124 dumping++;
125 if (*p == 'g')
126 genning++;
127 if (*p == 'r')
128 randing++;
129 } /* if argv 1 */
130
131 /* optional second argument: limit # of bytes shoveled either way */
132 if (argv[2]) {
133 x = atoi (argv[2]);
134 if (x)
135 limit = x;
136 else
137 goto wrong;
138 xlimit = limit;
139 }
140
141 /* Since this prog would likely best be written in assmbler, I'm gonna
142 write it *like* assembler. So there. */
143
144 if (randing)
145 goto do_rand;
146
147 nextbuf: /* loop sleaze */
148
149 if (dumping) { /* switch off to wherever */
150 if (genning)
151 goto wrong;
152 goto do_dump;
153 }
154 if (genning)
155 goto do_gen;
156 wrong:
157 fprintf (stderr, surveysez); /* if both or neither */
158 exit (1);
159
160 do_gen:
161 /* here if genning -- original functionality */
162 q = buf_raw;
163 bc = 0;
164 /* suck up lines until eof or buf_raw is full */
165 while (1) {
166 p = fgetss (buf_in, 120, stdin);
167 if (! p)
168 break; /* EOF */
169 /* super-primitive version first: one thingie per line */
170 if (*p == '#') /* comment */
171 continue;
172 if (*p == '\0') /* blank line */
173 continue;
174 if (*p == '%') { /* escape char? */
175 p++;
176 if (*p == 'r') { /* random byte */
177 x = randint();
178 goto stuff;
179 } /* %r */
180 } /* if "%" escape */
181 if (*p == '0')
182 if (*(p+1) == 'x') /* 0x?? */
183 goto hex;
184 x = atoi (p); /* reg'lar decimal number */
185 goto stuff;
186
187 hex:
188 /* A 65 a 97 */
189 /* xxx: use a conversion table for this or something. Since we ripped the
190 parity bit, we only need a preset array of 128 with downconversion factors
191 loaded in *once*. maybe look at scanf... */
192 p++; p++; /* point at hex-chars */
193 x = 0;
194 if ((*p > 96) && (*p < 123)) /* a-z */
195 *p = (*p - 32); /* this is massively clumsy */
196 if ((*p > 64) && (*p < 71)) /* A-F */
197 x = (*p - 55);
198 if ((*p > 47) && (*p < 58)) /* digits */
199 x = (*p - 48);
200 p++;
201 if (*p) /* another digit? */
202 x = (x << 4); /* shift to hi half */
203 if ((*p > 96) && (*p < 123)) /* a-z */
204 *p = (*p - 32);
205 if ((*p > 64) && (*p < 71)) /* A-F */
206 x = (x | (*p - 55)); /* lo half */
207 if ((*p > 47) && (*p < 58)) /* digits */
208 x = (x | (*p - 48));
209
210 /* fall thru */
211 stuff: /* cvt to byte and add to buffer */
212 *q = (x & 0xff);
213 q++;
214 bc++;
215 if (limit) {
216 xlimit--;
217 if (xlimit == 0) /* max num reached */
218 break;
219 } /* limit */
220 if (bc >= sizeof (buf_raw)) /* buffer full */
221 break;
222 } /* while 1 */
223
224 /* now in theory we have our buffer formed; shovel it out */
225 x = write (1, buf_raw, bc);
226 if (x <= 0) {
227 fprintf (stderr, "write oops: %d\n", x);
228 exit (1);
229 }
230 if (xlimit && p)
231 goto nextbuf; /* go get some more */
232 exit (0);
233
234 do_dump:
235 /* here if dumping raw stuff into an ascii file */
236 /* gad, this is *so* much simpler! can we say "don't rewrite printf"? */
237 x = read (0, buf_raw, 8192);
238 if (x <= 0)
239 exit (0);
240 q = buf_raw;
241 for ( ; x > 0; x--) {
242 p = q;
243 printf ("%-3.3d # 0x%-2.2x # ", *p, *p);
244 if ((*p > 31) && (*p < 127))
245 printf ("%c %d\n", *p, bc);
246 else
247 printf (". %d\n", bc);
248 q++;
249 bc++;
250 if (limit) {
251 xlimit--;
252 if (xlimit == 0) {
253 fflush (stdout);
254 exit (0);
255 }
256 } /* limit */
257 } /* for */
258 goto nextbuf;
259
260 do_rand:
261 /* here if generating all-random bytes. Stays in this loop */
262 p = buf_raw;
263 while (1) {
264 *p = (randint() & 0xff);
265 write (1, p, 1); /* makes very slow! */
266 if (limit) {
267 xlimit--;
268 if (xlimit == 0)
269 break;
270 }
271 } /* while */
272 exit (0);
273
274 } /* main */
275