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