Home | History | Annotate | Download | only in data
      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