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 */ 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. */ 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 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