• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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