]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/tn3270/tools/prt3270.c
BSD 4.4 Lite Usr.bin Sources
[FreeBSD/FreeBSD.git] / usr.bin / tn3270 / tools / prt3270.c
1 /*-
2  * Copyright (c) 1988, 1993
3  *      The Regents of the University of California.  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 static char copyright[] =
36 "@(#) Copyright (c) 1988, 1993\n\
37         The Regents of the University of California.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #ifndef lint
41 static char sccsid[] = "@(#)prt3270.c   8.1 (Berkeley) 6/6/93";
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
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
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
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
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
139 putChar(character)
140 int     character;
141 {
142     *print++ = character;
143     column++;
144 }
145
146 void
147 putstr(s)
148 char *s;
149 {
150     while (*s) {
151         putChar(*s++);
152     }
153 }
154
155 void
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
167 putdecimal(i)
168 int i;
169 {
170     char place[40];
171
172     sprintf(place, "%d", i);
173     putstr(place);
174 }
175
176 void
177 puthex(i)
178 int i;
179 {
180     char place[40];
181
182     sprintf(place, "%x", i);
183     putstr(place);
184 }
185
186 void
187 putEChar(character)
188 int character;
189 {
190     putChar(ebc_asc[character]);
191     if (ColsLeft() < 10) {
192         Column1();
193     }
194 }
195
196 void
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
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
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
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
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
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
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 }