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
putSpace()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
Column1()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
Indent()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
Undent()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
putChar(character)113 putChar(character)
114 int character;
115 {
116 *print++ = character;
117 column++;
118 }
119
120 void
putstr(s)121 putstr(s)
122 char *s;
123 {
124 while (*s) {
125 putChar(*s++);
126 }
127 }
128
129 void
put2hex(i)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
putdecimal(i)141 putdecimal(i)
142 int i;
143 {
144 char place[40];
145
146 sprintf(place, "%d", i);
147 putstr(place);
148 }
149
150 void
puthex(i)151 puthex(i)
152 int i;
153 {
154 char place[40];
155
156 sprintf(place, "%x", i);
157 putstr(place);
158 }
159
160 void
putEChar(character)161 putEChar(character)
162 int character;
163 {
164 putChar(ebc_asc[character]);
165 if (ColsLeft() < 10) {
166 Column1();
167 }
168 }
169
170 void
PrintAid(i)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
PrintAddr(i)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
DataFromNetwork(buffer,count,control)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
DataToNetwork(buffer,count,control)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
GetXValue(c)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
termblock(old,new,control)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
main()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