Release 4.1
[unix-history] / usr / src / usr.bin / tn3270 / tools / prt3270.c
CommitLineData
992de934 1/*
0de390c0
KB
2 * Copyright (c) 1988 Regents of the University of California.
3 * All rights reserved.
992de934 4 *
0de390c0 5 * Redistribution and use in source and binary forms are permitted
b36fc510
KB
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.
992de934 16 */
71ac803b 17
992de934 18#ifndef lint
0de390c0
KB
19char 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
d43d1075 25static char sccsid[] = "@(#)prt3270.c 4.1 (Berkeley) %G%";
0de390c0 26#endif /* not lint */
71ac803b
GM
27
28#if defined(unix)
29#endif
30#include <stdio.h>
71ac803b
GM
31#include <ctype.h>
32
03bae598 33#include "../general/general.h"
e56fc5cb 34
4718d085 35#include "../api/asc_ebc.h"
71ac803b
GM
36#include "../ctlr/hostctlr.h"
37#include "../ctlr/screen.h"
906419f0 38#include "../ctlr/function.h"
4718d085 39#include "../api/astosc.h"
03bae598 40#include "../general/globals.h"
71ac803b 41
906419f0
GM
42#include "../ctlr/kbd.out"
43
71ac803b
GM
44
45int NumberColumns = 80;
46
47int direction;
48
49int column = 1;
50int indenting = 0;
51int direction = '?';
52
53unsigned char printBuffer[200], *print = printBuffer;
54
55#define ColsLeft() (79-column) /* A little room for error */
56
57
58void
59putSpace()
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
84void
85Column1()
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
96void
97Indent()
98{
99 if ((column != (indenting*8+1)) || (print != printBuffer)) {
100 Column1();
101 }
102 indenting++;
103 column = indenting*8+1;
104}
105
106void
107Undent()
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
122void
123putChar(character)
124int character;
125{
126 *print++ = character;
e993a7ea 127 column++;
71ac803b
GM
128}
129
130void
131putstr(s)
132char *s;
133{
134 while (*s) {
135 putChar(*s++);
136 }
137}
138
139void
140put2hex(i)
141int i;
142{
143 char place[40];
144
145 sprintf(place, "%02x", i);
146 putstr(place);
147}
148
149
150void
151putdecimal(i)
152int i;
153{
154 char place[40];
155
156 sprintf(place, "%d", i);
157 putstr(place);
158}
159
160void
161puthex(i)
162int i;
163{
164 char place[40];
165
166 sprintf(place, "%x", i);
167 putstr(place);
168}
169
170void
171putEChar(character)
172int character;
173{
138011c0 174 putChar(ebc_asc[character]);
71ac803b
GM
175 if (ColsLeft() < 10) {
176 Column1();
177 }
178}
179
180void
181PrintAid(i)
182int i;
183{
906419f0
GM
184 struct astosc *this;
185
186 for (this = &astosc[0]; this <= &astosc[highestof(astosc)]; this++) {
187 if (this->function == FCN_AID) {
188 int j;
71ac803b 189
906419f0
GM
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 }
71ac803b
GM
211 }
212 }
213
214 putstr("Unknown AID 0x");
215 put2hex(i);
216}
217
218void
219PrintAddr(i)
220int 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 */
234int
235DataFromNetwork(buffer, count, control)
236register unsigned char *buffer; /* what the data is */
237register int count; /* and how much there is */
238int 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:
5cc553b7 269 putstr("sna_read_modified command\n");
71ac803b
GM
270 break;
271 case CMD_SNA_READ_MODIFIED_ALL:
5cc553b7 272 putstr("sna_read_modified_all command\n");
71ac803b
GM
273 break;
274 case CMD_READ_BUFFER:
5cc553b7 275 putstr("read_buffer command\n");
71ac803b
GM
276 break;
277 case CMD_SNA_READ_BUFFER:
5cc553b7 278 putstr("sna_read_buffer command\n");
71ac803b
GM
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
423int
424DataToNetwork(buffer, count, control)
425unsigned char *buffer;
426int count;
427int 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();
906419f0 452 if (aid == AID_TREQ) {
71ac803b
GM
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
500int
501GetXValue(c)
502int 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
520unsigned char outbound[8192], inbound[8192],
521 *outnext = outbound, *innext = inbound, *p = 0;
522
523void
524termblock(old, new, control)
525int 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 {
e56fc5cb 537 memcpy(outbound, outbound+count, outnext-(outbound+count));
71ac803b
GM
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 {
e56fc5cb 546 memcpy(inbound, inbound+count, innext-(inbound+count));
71ac803b
GM
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
561main()
562{
563 int location;
5cc553b7 564 char new;
71ac803b
GM
565 int c, c1;
566
e56fc5cb 567 memset(Orders, 0, sizeof Orders);
71ac803b
GM
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}