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