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