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