xref: /original-bsd/usr.bin/tn3270/tools/prt3270.c (revision f1324ba5)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1988 Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)prt3270.c	3.4 (Berkeley) 06/29/88";
26 #endif /* not lint */
27 
28 #if defined(unix)
29 #endif
30 #include <stdio.h>
31 #include <ctype.h>
32 
33 #include "../general/general.h"
34 
35 #include "../api/asc_ebc.h"
36 #include "../ctlr/hostctlr.h"
37 #include "../ctlr/screen.h"
38 #include "../ctlr/function.h"
39 #include "../api/astosc.h"
40 #include "../general/globals.h"
41 
42 #include "../ctlr/kbd.out"
43 
44 
45 int NumberColumns = 80;
46 
47 int direction;
48 
49 int column = 1;
50 int indenting = 0;
51 int direction = '?';
52 
53 unsigned char printBuffer[200], *print = printBuffer;
54 
55 #define	ColsLeft()	(79-column)	/* A little room for error */
56 
57 
58 void
59 putSpace()
60 {
61     extern void Column1();
62     unsigned char *ourPrint = print;
63 
64     print = printBuffer;		/* For mutual calls */
65     *ourPrint = 0;
66     if (ColsLeft() < 0) {
67 	Column1();
68     }
69     if (column != (indenting*8+1)) {
70 	putchar(' ');
71     } else {
72 	int i;
73 
74 	putchar(direction);
75 	putchar(' ');
76 	for (i = 0; i < indenting; i++) {
77 	    putchar('\t');
78 	}
79     }
80     printf("%s", printBuffer);
81     column += strlen(printBuffer);
82 }
83 
84 void
85 Column1()
86 {
87     if (print != printBuffer) {
88 	putSpace();
89     }
90     if (column != (indenting*8+1)) {
91 	putchar('\n');
92 	column = indenting*8+1;
93     }
94 }
95 
96 void
97 Indent()
98 {
99     if ((column != (indenting*8+1)) || (print != printBuffer)) {
100 	Column1();
101     }
102     indenting++;
103     column = indenting*8+1;
104 }
105 
106 void
107 Undent()
108 {
109     if ((column != (indenting*8+1)) || (print != printBuffer)) {
110 	Column1();
111     }
112     indenting--;
113     if (indenting < 0) {
114 	fflush(stdout);
115 	fprintf(stderr, "INTERNAL ERROR: indenting < 0.\n");
116 	fflush(stderr);
117     } else {
118 	column = indenting*8+1;
119     }
120 }
121 
122 void
123 putChar(character)
124 int	character;
125 {
126     *print++ = character;
127     column++;
128 }
129 
130 void
131 putstr(s)
132 char *s;
133 {
134     while (*s) {
135 	putChar(*s++);
136     }
137 }
138 
139 void
140 put2hex(i)
141 int i;
142 {
143     char place[40];
144 
145     sprintf(place, "%02x", i);
146     putstr(place);
147 }
148 
149 
150 void
151 putdecimal(i)
152 int i;
153 {
154     char place[40];
155 
156     sprintf(place, "%d", i);
157     putstr(place);
158 }
159 
160 void
161 puthex(i)
162 int i;
163 {
164     char place[40];
165 
166     sprintf(place, "%x", i);
167     putstr(place);
168 }
169 
170 void
171 putEChar(character)
172 int character;
173 {
174     putChar(ebc_asc[character]);
175     if (ColsLeft() < 10) {
176 	Column1();
177     }
178 }
179 
180 void
181 PrintAid(i)
182 int	i;
183 {
184     struct astosc *this;
185 
186     for (this = &astosc[0]; this <= &astosc[highestof(astosc)]; this++) {
187 	if (this->function == FCN_AID) {
188 	    int j;
189 
190 	    switch (this->shiftstate) {
191 	    case 0:
192 		j = 0;
193 		break;
194 	    case SHIFT_UPSHIFT:
195 		j = 1;
196 		break;
197 	    case SHIFT_ALT:
198 		j = 2;
199 		break;
200 	    case (SHIFT_UPSHIFT|SHIFT_ALT):
201 		j = 3;
202 		break;
203 	    default:
204 		fprintf(stderr, "Bad shiftstate 0x%x.\n", this->shiftstate);
205 		exit(1);
206 	    }
207 	    if (hits[this->scancode].hit[j].code == i) {
208 		putstr(this->name);
209 		return;
210 	    }
211 	}
212     }
213 
214     putstr("Unknown AID 0x");
215     put2hex(i);
216 }
217 
218 void
219 PrintAddr(i)
220 int	i;
221 {
222     if (ColsLeft() < 9) {
223 	Column1();
224     }
225     putChar('(');
226     putdecimal(ScreenLine(i));
227     putChar(',');
228     putdecimal(ScreenLineOffset(i));
229     putChar(')');
230 }
231 
232 
233 /* returns the number of characters consumed */
234 int
235 DataFromNetwork(buffer, count, control)
236 register unsigned char	*buffer;		/* what the data is */
237 register int	count;				/* and how much there is */
238 int	control;				/* this buffer ended block? */
239 {
240     int origCount;
241     register int c;
242     register int i;
243     static int Command;
244     static int Wcc;
245     static int	LastWasTerminated = 1;	/* was "control" = 1 last time? */
246 
247     if (count == 0) {
248 	Column1();
249 	return 0;
250     }
251 
252     origCount = count;
253 
254     if (LastWasTerminated) {
255 
256 	if (count < 2) {
257 	    if (count == 0) {
258 		fflush(stdout);
259 		fprintf(stderr, "Short count received from host!\n");
260 		fflush(stderr);
261 		return(count);
262 	    }
263 	    Command = buffer[0];
264 	    switch (Command) {		/* This had better be a read command */
265 	    case CMD_READ_MODIFIED:
266 		putstr("read_modified command\n");
267 		break;
268 	    case CMD_SNA_READ_MODIFIED:
269 		putstr("sna_read_modified command\n");
270 		break;
271 	    case CMD_SNA_READ_MODIFIED_ALL:
272 		putstr("sna_read_modified_all command\n");
273 		break;
274 	    case CMD_READ_BUFFER:
275 		putstr("read_buffer command\n");
276 		break;
277 	    case CMD_SNA_READ_BUFFER:
278 		putstr("sna_read_buffer command\n");
279 		break;
280 	    default:
281 		break;
282 	    }
283 	    return(1);			/* We consumed everything */
284 	}
285 	Command = buffer[0];
286 	Wcc = buffer[1];
287 	switch (Command) {
288 	case CMD_ERASE_WRITE:
289 	    putstr("erase write command ");
290 	    break;
291 	case CMD_ERASE_WRITE_ALTERNATE:
292 	    putstr("erase write alternate command ");
293 	    break;
294 	case CMD_SNA_ERASE_WRITE:
295 	    putstr("sna erase write command ");
296 	    break;
297 	case CMD_SNA_ERASE_WRITE_ALTERNATE:
298 	    putstr("erase write alternate command ");
299 	    break;
300 	case CMD_ERASE_ALL_UNPROTECTED:
301 	    putstr("erase all unprotected command ");
302 	    break;
303 	case CMD_SNA_ERASE_ALL_UNPROTECTED:
304 	    putstr("sna erase write command ");
305 	    break;
306 	case CMD_WRITE:
307 	    putstr("write command ");
308 	    break;
309 	case CMD_SNA_WRITE:
310 	    putstr("sna write command ");
311 	    break;
312 	default:
313 	    putstr("Unexpected command code 0x");
314 	    puthex(Command);
315 	    putstr(" received.");
316 	    Column1();
317 	    break;
318 	}
319 	putstr("WCC is 0x");
320 	puthex(Wcc);
321 	Column1();
322 
323 	count -= 2;			/* strip off command and wcc */
324 	buffer += 2;
325 
326     }
327     LastWasTerminated = 0;		/* then, reset at end... */
328 
329     while (count) {
330 	count--;
331 	c = *buffer++;
332 	if (IsOrder(c)) {
333 	    /* handle an order */
334 	    switch (c) {
335 #		define Ensure(x)	if (count < x) { \
336 					    if (!control) { \
337 						return(origCount-(count+1)); \
338 					    } else { \
339 						/* XXX - should not occur */ \
340 						count = 0; \
341 						break; \
342 					    } \
343 					}
344 	    case ORDER_SF:
345 		Ensure(1);
346 		c = *buffer++;
347 		count--;
348 		putstr("SF (0x");
349 		put2hex(c);
350 		putstr(") ");
351 		break;
352 	    case ORDER_SBA:
353 		Ensure(2);
354 		i = buffer[0];
355 		c = buffer[1];
356 		buffer += 2;
357 		count -= 2;
358 		putstr("SBA to ");
359 		PrintAddr(Addr3270(i,c));
360 		putSpace();
361 		break;
362 	    case ORDER_IC:
363 		putstr("IC");
364 		putSpace();
365 		break;
366 	    case ORDER_PT:
367 		putstr("PT");
368 		putSpace();
369 		break;
370 	    case ORDER_RA:
371 		Ensure(3);
372 		i = Addr3270(buffer[0], buffer[1]);
373 		c = buffer[2];
374 		buffer += 3;
375 		count -= 3;
376 		putstr("RA to ");
377 		PrintAddr(i);
378 		putstr(" of 0x");
379 		put2hex(c);
380 		putSpace();
381 		break;
382 	    case ORDER_EUA:    /* (from [here,there), ie: half open interval] */
383 		Ensure(2);
384 		putstr("EUA to ");
385 		PrintAddr(Addr3270(buffer[0], buffer[1]));
386 		putSpace();
387 		buffer += 2;
388 		count -= 2;
389 		break;
390 	    case ORDER_YALE:		/* special YALE defined order */
391 		Ensure(2);	/* need at least two characters */
392 		putstr("YALE order");
393 		putSpace();
394 		break;
395 	    default:
396 		putstr("UNKNOWN ORDER: 0x");
397 		put2hex(c);
398 		putSpace();
399 		break;
400 	    }
401 	    if (count < 0) {
402 		count = 0;
403 	    }
404 	} else {
405 	    /* Data comes in large clumps - take it all */
406 	    putstr("DATA:");
407 	    Indent();
408 	    putEChar(c);
409 	    c = *buffer;
410 	    while (count && !IsOrder(c)) {
411 		putEChar(c);
412 		count--;
413 		buffer++;
414 		c = *buffer;
415 	    }
416 	    Undent();
417 	}
418     }
419     LastWasTerminated = control;
420     return origCount - count;
421 }
422 
423 int
424 DataToNetwork(buffer, count, control)
425 unsigned char *buffer;
426 int count;
427 int control;
428 {
429 #define	NEED_AID	0
430 #define	JUST_GOT_AID	1
431 #define	DATA		2
432 #define	DATA_CONTINUE	3
433     static int state = NEED_AID;
434     static int aid;
435     int origCount = count;
436 
437     if (count == 0) {
438 	if (control) {
439 	    state = NEED_AID;
440 	}
441 	Column1();
442 	return 0;
443     }
444 
445     switch (state) {
446     case NEED_AID:
447 	aid = buffer[0];
448 	buffer++;
449 	count--;
450 	PrintAid(aid);
451 	putSpace();
452 	if (aid == AID_TREQ) {
453 	    state = DATA;
454 	} else {
455 	    state = JUST_GOT_AID;
456 	}
457 	return origCount - count + DataToNetwork(buffer, count, control);
458     case JUST_GOT_AID:
459 	Ensure(2);
460 	PrintAddr(Addr3270(buffer[0], buffer[1]));
461 	putSpace();
462 	buffer += 2;
463 	count -= 2;
464 	state = DATA;
465 	return origCount - count + DataToNetwork(buffer, count, control);
466     case DATA:
467     case DATA_CONTINUE:
468 	while (count) {
469 	    if (*buffer == ORDER_SBA) {
470 		if (state == DATA_CONTINUE) {
471 		    Undent();
472 		    state = DATA;
473 		}
474 		putstr("SBA ");
475 		PrintAddr(Addr3270(buffer[1], buffer[2]));
476 		putSpace();
477 		buffer += 3;
478 		count -= 3;
479 	    } else {
480 		if (state == DATA) {
481 		    putstr("DATA:");
482 		    Indent();
483 		    state = DATA_CONTINUE;
484 		}
485 		putEChar(*buffer);
486 		buffer++;
487 		count--;
488 	    }
489 	}
490 	if (control) {
491 	    if (state == DATA_CONTINUE) {
492 		Undent();
493 	    }
494 	    state = NEED_AID;
495 	}
496 	return origCount-count;
497     }
498 }
499 
500 int
501 GetXValue(c)
502 int	c;
503 {
504     if (!isascii(c)) {
505 	fflush(stdout);
506 	fprintf(stderr, "Non-hex digit 0x%x.\n");
507 	fflush(stderr);
508 	return 0;
509     } else {
510 	if (islower(c)) {
511 	    return (c-'a')+10;
512 	} else if (isupper(c)) {
513 	    return (c-'A')+10;
514 	} else {
515 	    return c-'0';
516 	}
517     }
518 }
519 
520 unsigned char outbound[8192], inbound[8192],
521 	*outnext = outbound, *innext = inbound, *p = 0;
522 
523 void
524 termblock(old, new, control)
525 int old,
526 	new;		/* old and new directions */
527 {
528     int count;
529 
530     if (p) {
531 	if (old == '<') {
532 	    outnext = p;
533 	    count = DataFromNetwork(outbound, outnext-outbound, control);
534 	    if (outbound+count == outnext) {
535 		outnext = outbound;
536 	    } else {
537 		memcpy(outbound, outbound+count, outnext-(outbound+count));
538 		outnext = outbound+count;
539 	    }
540 	} else {
541 	    innext = p;
542 	    count = DataToNetwork(inbound, innext-inbound, control);
543 	    if (inbound+count == innext) {
544 		innext = inbound;
545 	    } else {
546 		memcpy(inbound, inbound+count, innext-(inbound+count));
547 		innext = inbound+count;
548 	    }
549 	}
550     }
551     if (new == '<') {
552 	p = outnext;
553     } else if (new == '>') {
554 	p = innext;
555     } else {
556 	fprintf(stderr, "Bad direction character '%c'.\n", new);
557 	exit(1);
558     }
559 }
560 
561 main()
562 {
563     int location;
564     char new;
565     int c, c1;
566 
567     memset(Orders, 0, sizeof Orders);
568     Orders[ORDER_SF] = Orders[ORDER_SBA] = Orders[ORDER_IC]
569 	    = Orders[ORDER_PT] = Orders[ORDER_RA] = Orders[ORDER_EUA]
570 	    = Orders[ORDER_YALE] = 1;
571 
572     while (scanf("%c 0x%x\t", &new, &location) != EOF) {
573 	if (new != direction) {
574 	    termblock(direction, new, 0);
575 	    direction = new;
576 	}
577 	while (((c = getchar()) != EOF) && (c != '\n') && (isxdigit(c))) {
578 #define	NORMAL	0
579 #define	GOT0XFF	0xff
580 	    static int state = NORMAL;
581 
582 	    c1 = getchar();
583 	    c = (GetXValue(c) << 4) + GetXValue(c1);
584 	    switch (state) {
585 	    case NORMAL:
586 		if (c == 0xff) {
587 		    state = GOT0XFF;
588 		} else {
589 		    *p++ = c;
590 		}
591 		break;
592 	    case GOT0XFF:
593 		if (c == 0xef) {
594 		    termblock(direction, direction, 1);
595 		} else {
596 		    *p++ = 0xff;
597 		    *p++ = c;
598 		}
599 		state = NORMAL;
600 	    }
601 	}
602     }
603     return 0;
604 }
605