275 lines
6.6 KiB
C
275 lines
6.6 KiB
C
|
/* primitive arbitrary-data frontend for netcat. 0.9 960226
|
||
|
only handles one value per ascii line, but at least parses 0xNN too
|
||
|
an input line containing "%r" during "-g" generates a random byte
|
||
|
|
||
|
todo:
|
||
|
make work on msloss jus' for kicks [workin' on it...]
|
||
|
|
||
|
syntax: data -X [limit]
|
||
|
where X is one of
|
||
|
d: dump raw bytes to ascii format
|
||
|
g: generate raw bytes from ascii input
|
||
|
c: generate ??? of value -- NOTYET
|
||
|
r: generate all random bytes
|
||
|
and limit is how many bytes to generate or dump [unspecified = infinite]
|
||
|
|
||
|
*Hobbit*, started 951004 or so and randomly screwed around with since */
|
||
|
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#ifdef MSDOS /* for MSC only at the moment... */
|
||
|
#include <fcntl.h>
|
||
|
#else /* MSDOS */
|
||
|
#include <sys/file.h>
|
||
|
#define HAVE_RANDOM /* XXX: might have to change */
|
||
|
#endif /* MSDOS */
|
||
|
|
||
|
static char buf_in [128];
|
||
|
static char buf_raw [8192];
|
||
|
static char surveysez[] = "survey sez... XXX\n";
|
||
|
|
||
|
/* fgetss :
|
||
|
wrapper for fgets, that yanks trailing newlines. Doing the work ourselves
|
||
|
instead of calling strchr/strlen/whatever */
|
||
|
char * fgetss (buf, len, from)
|
||
|
char * buf;
|
||
|
size_t len;
|
||
|
FILE * from;
|
||
|
{
|
||
|
register int x;
|
||
|
register char * p, * q;
|
||
|
p = fgets (buf, len, from); /* returns ptr to buf */
|
||
|
if (! p)
|
||
|
return (NULL);
|
||
|
q = p;
|
||
|
for (x = 0; x < len; x++) {
|
||
|
*p = (*p & 0x7f); /* rip parity, just in case */
|
||
|
switch (*p) {
|
||
|
case '\n':
|
||
|
case '\r':
|
||
|
case '\0':
|
||
|
*p = '\0';
|
||
|
return (q);
|
||
|
} /* switch */
|
||
|
p++;
|
||
|
} /* for */
|
||
|
} /* fgetss */
|
||
|
|
||
|
/* randint:
|
||
|
swiped from rndb.c. Generates an INT, you have to mask down to char. */
|
||
|
int randint()
|
||
|
{
|
||
|
register int q;
|
||
|
register int x;
|
||
|
|
||
|
#ifndef HAVE_RANDOM
|
||
|
q = rand();
|
||
|
#else
|
||
|
q = random();
|
||
|
#endif
|
||
|
x = ((q >> 8) & 0xff); /* perturb low byte using some higher bits */
|
||
|
x = q ^ x;
|
||
|
return (x);
|
||
|
}
|
||
|
|
||
|
main (argc, argv)
|
||
|
int argc;
|
||
|
char ** argv;
|
||
|
{
|
||
|
register unsigned char * p;
|
||
|
register char * q;
|
||
|
register int x;
|
||
|
int bc = 0;
|
||
|
int limit = 0; /* num to gen, or 0 = infinite */
|
||
|
register int xlimit; /* running limit */
|
||
|
FILE * txt; /* line-by-line ascii file */
|
||
|
int raw; /* raw bytes fd */
|
||
|
int dumping = 0; /* cmd flags ... */
|
||
|
int genning = 0;
|
||
|
int randing = 0;
|
||
|
|
||
|
memset (buf_in, 0, sizeof (buf_in));
|
||
|
memset (buf_raw, 0, sizeof (buf_raw));
|
||
|
|
||
|
xlimit = 1; /* doubles as "exit flag" */
|
||
|
bc = 1; /* preload, assuming "dump" */
|
||
|
x = getpid() + 687319;
|
||
|
/* if your library doesnt have srandom/random, use srand/rand. [from rnd.c] */
|
||
|
#ifndef HAVE_RANDOM
|
||
|
srand (time(0) + x);
|
||
|
#else
|
||
|
srandom (time(0) + x);
|
||
|
#endif
|
||
|
|
||
|
#ifdef O_BINARY
|
||
|
/* DOS stupidity */
|
||
|
/* Aha: *here's* where that setmode() lib call conflict in ?BSD came from */
|
||
|
x = setmode (0, O_BINARY); /* make stdin raw */
|
||
|
if (x < 0) {
|
||
|
fprintf (stderr, "stdin binary setmode oops: %d\n", x);
|
||
|
exit (1);
|
||
|
}
|
||
|
x = setmode (1, O_BINARY); /* make stdout raw */
|
||
|
if (x < 0) {
|
||
|
fprintf (stderr, "stdout binary setmode oops: %d\n", x);
|
||
|
exit (1);
|
||
|
}
|
||
|
#endif /* O_BINARY */
|
||
|
|
||
|
if (argv[1]) {
|
||
|
p = argv[1]; /* shit-simple single arg parser... */
|
||
|
if (*p == '-') /* dash is optional, we'll deal */
|
||
|
p++;
|
||
|
if (*p == 'd')
|
||
|
dumping++;
|
||
|
if (*p == 'g')
|
||
|
genning++;
|
||
|
if (*p == 'r')
|
||
|
randing++;
|
||
|
} /* if argv 1 */
|
||
|
|
||
|
/* optional second argument: limit # of bytes shoveled either way */
|
||
|
if (argv[2]) {
|
||
|
x = atoi (argv[2]);
|
||
|
if (x)
|
||
|
limit = x;
|
||
|
else
|
||
|
goto wrong;
|
||
|
xlimit = limit;
|
||
|
}
|
||
|
|
||
|
/* Since this prog would likely best be written in assmbler, I'm gonna
|
||
|
write it *like* assembler. So there. */
|
||
|
|
||
|
if (randing)
|
||
|
goto do_rand;
|
||
|
|
||
|
nextbuf: /* loop sleaze */
|
||
|
|
||
|
if (dumping) { /* switch off to wherever */
|
||
|
if (genning)
|
||
|
goto wrong;
|
||
|
goto do_dump;
|
||
|
}
|
||
|
if (genning)
|
||
|
goto do_gen;
|
||
|
wrong:
|
||
|
fprintf (stderr, surveysez); /* if both or neither */
|
||
|
exit (1);
|
||
|
|
||
|
do_gen:
|
||
|
/* here if genning -- original functionality */
|
||
|
q = buf_raw;
|
||
|
bc = 0;
|
||
|
/* suck up lines until eof or buf_raw is full */
|
||
|
while (1) {
|
||
|
p = fgetss (buf_in, 120, stdin);
|
||
|
if (! p)
|
||
|
break; /* EOF */
|
||
|
/* super-primitive version first: one thingie per line */
|
||
|
if (*p == '#') /* comment */
|
||
|
continue;
|
||
|
if (*p == '\0') /* blank line */
|
||
|
continue;
|
||
|
if (*p == '%') { /* escape char? */
|
||
|
p++;
|
||
|
if (*p == 'r') { /* random byte */
|
||
|
x = randint();
|
||
|
goto stuff;
|
||
|
} /* %r */
|
||
|
} /* if "%" escape */
|
||
|
if (*p == '0')
|
||
|
if (*(p+1) == 'x') /* 0x?? */
|
||
|
goto hex;
|
||
|
x = atoi (p); /* reg'lar decimal number */
|
||
|
goto stuff;
|
||
|
|
||
|
hex:
|
||
|
/* A 65 a 97 */
|
||
|
/* xxx: use a conversion table for this or something. Since we ripped the
|
||
|
parity bit, we only need a preset array of 128 with downconversion factors
|
||
|
loaded in *once*. maybe look at scanf... */
|
||
|
p++; p++; /* point at hex-chars */
|
||
|
x = 0;
|
||
|
if ((*p > 96) && (*p < 123)) /* a-z */
|
||
|
*p = (*p - 32); /* this is massively clumsy */
|
||
|
if ((*p > 64) && (*p < 71)) /* A-F */
|
||
|
x = (*p - 55);
|
||
|
if ((*p > 47) && (*p < 58)) /* digits */
|
||
|
x = (*p - 48);
|
||
|
p++;
|
||
|
if (*p) /* another digit? */
|
||
|
x = (x << 4); /* shift to hi half */
|
||
|
if ((*p > 96) && (*p < 123)) /* a-z */
|
||
|
*p = (*p - 32);
|
||
|
if ((*p > 64) && (*p < 71)) /* A-F */
|
||
|
x = (x | (*p - 55)); /* lo half */
|
||
|
if ((*p > 47) && (*p < 58)) /* digits */
|
||
|
x = (x | (*p - 48));
|
||
|
|
||
|
/* fall thru */
|
||
|
stuff: /* cvt to byte and add to buffer */
|
||
|
*q = (x & 0xff);
|
||
|
q++;
|
||
|
bc++;
|
||
|
if (limit) {
|
||
|
xlimit--;
|
||
|
if (xlimit == 0) /* max num reached */
|
||
|
break;
|
||
|
} /* limit */
|
||
|
if (bc >= sizeof (buf_raw)) /* buffer full */
|
||
|
break;
|
||
|
} /* while 1 */
|
||
|
|
||
|
/* now in theory we have our buffer formed; shovel it out */
|
||
|
x = write (1, buf_raw, bc);
|
||
|
if (x <= 0) {
|
||
|
fprintf (stderr, "write oops: %d\n", x);
|
||
|
exit (1);
|
||
|
}
|
||
|
if (xlimit && p)
|
||
|
goto nextbuf; /* go get some more */
|
||
|
exit (0);
|
||
|
|
||
|
do_dump:
|
||
|
/* here if dumping raw stuff into an ascii file */
|
||
|
/* gad, this is *so* much simpler! can we say "don't rewrite printf"? */
|
||
|
x = read (0, buf_raw, 8192);
|
||
|
if (x <= 0)
|
||
|
exit (0);
|
||
|
q = buf_raw;
|
||
|
for ( ; x > 0; x--) {
|
||
|
p = q;
|
||
|
printf ("%-3.3d # 0x%-2.2x # ", *p, *p);
|
||
|
if ((*p > 31) && (*p < 127))
|
||
|
printf ("%c %d\n", *p, bc);
|
||
|
else
|
||
|
printf (". %d\n", bc);
|
||
|
q++;
|
||
|
bc++;
|
||
|
if (limit) {
|
||
|
xlimit--;
|
||
|
if (xlimit == 0) {
|
||
|
fflush (stdout);
|
||
|
exit (0);
|
||
|
}
|
||
|
} /* limit */
|
||
|
} /* for */
|
||
|
goto nextbuf;
|
||
|
|
||
|
do_rand:
|
||
|
/* here if generating all-random bytes. Stays in this loop */
|
||
|
p = buf_raw;
|
||
|
while (1) {
|
||
|
*p = (randint() & 0xff);
|
||
|
write (1, p, 1); /* makes very slow! */
|
||
|
if (limit) {
|
||
|
xlimit--;
|
||
|
if (xlimit == 0)
|
||
|
break;
|
||
|
}
|
||
|
} /* while */
|
||
|
exit (0);
|
||
|
|
||
|
} /* main */
|