Sync usage with man page.
[netbsd-mini2440.git] / usr.bin / tn3270 / tools / prt3270 / prt3270.c
blobec837916921c830ec5dff7007523bfc70ba5e216
1 /* $NetBSD: prt3270.c,v 1.10 2006/11/09 20:59:23 christos Exp $ */
3 /*-
4 * Copyright (c) 1988 The Regents of the University of California.
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
32 #ifndef HOST_TOOL
33 #include <sys/cdefs.h>
34 #if defined(__COPYRIGHT) && !defined(lint)
35 __COPYRIGHT("@(#) Copyright (c) 1988\
36 The Regents of the University of California. All rights reserved.");
37 #endif /* not lint */
38 #endif
40 #if defined(__RCSID) && !defined(lint)
41 #if 0
42 static char sccsid[] = "@(#)prt3270.c 4.2 (Berkeley) 4/26/91";
43 #else
44 __RCSID("$NetBSD: prt3270.c,v 1.10 2006/11/09 20:59:23 christos Exp $");
45 #endif
46 #endif /* not lint */
48 #include <stdio.h>
49 #include <ctype.h>
50 #include <stdlib.h>
52 #define DEFINING_INSTANCES
53 #include "../general/general.h"
55 #include "../api/asc_ebc.h"
56 #include "../ctlr/hostctlr.h"
57 #include "../ctlr/screen.h"
58 #include "../ctlr/function.h"
59 #include "../api/astosc.h"
60 #include "../general/globals.h"
62 #include "kbd.out"
65 int NumberColumns = 80;
67 int direction;
69 int column = 1;
70 int indenting = 0;
71 int direction = '?';
73 unsigned char printBuffer[200], *print = printBuffer;
75 #define ColsLeft() (79-column) /* A little room for error */
78 /* prt3270.c */
79 void putSpace(void);
80 void Column1(void);
81 void Indent(void);
82 void Undent(void);
83 void putChar(int);
84 void putstr(char *);
85 void put2hex(int);
86 void putdecimal(int);
87 void puthex(int);
88 void putEChar(int);
89 void PrintAid(int);
90 void PrintAddr(int);
91 int DataFromNetwork(unsigned char *, int, int);
92 int DataToNetwork(unsigned char *, int, int);
93 int GetXValue(int);
94 void termblock(int, int , int);
95 int main(int, char *[]);
97 void
98 putSpace()
100 unsigned char *ourPrint = print;
102 print = printBuffer; /* For mutual calls */
103 *ourPrint = 0;
104 if (ColsLeft() < 0) {
105 Column1();
107 if (column != (indenting*8+1)) {
108 putchar(' ');
109 } else {
110 int i;
112 putchar(direction);
113 putchar(' ');
114 for (i = 0; i < indenting; i++) {
115 putchar('\t');
118 printf("%s", printBuffer);
119 column += strlen(printBuffer);
122 void
123 Column1()
125 if (print != printBuffer) {
126 putSpace();
128 if (column != (indenting*8+1)) {
129 putchar('\n');
130 column = indenting*8+1;
134 void
135 Indent()
137 if ((column != (indenting*8+1)) || (print != printBuffer)) {
138 Column1();
140 indenting++;
141 column = indenting*8+1;
144 void
145 Undent()
147 if ((column != (indenting*8+1)) || (print != printBuffer)) {
148 Column1();
150 indenting--;
151 if (indenting < 0) {
152 fflush(stdout);
153 fprintf(stderr, "INTERNAL ERROR: indenting < 0.\n");
154 fflush(stderr);
155 } else {
156 column = indenting*8+1;
160 void
161 putChar(character)
162 int character;
164 *print++ = character;
165 column++;
168 void
169 putstr(s)
170 char *s;
172 while (*s) {
173 putChar(*s++);
177 void
178 put2hex(i)
179 int i;
181 char place[40];
183 sprintf(place, "%02x", i);
184 putstr(place);
188 void
189 putdecimal(i)
190 int i;
192 char place[40];
194 sprintf(place, "%d", i);
195 putstr(place);
198 void
199 puthex(i)
200 int i;
202 char place[40];
204 sprintf(place, "%x", i);
205 putstr(place);
208 void
209 putEChar(character)
210 int character;
212 putChar(ebc_asc[character]);
213 if (ColsLeft() < 10) {
214 Column1();
218 void
219 PrintAid(i)
220 int i;
222 struct astosc *this;
224 for (this = &astosc[0]; this <= &astosc[highestof(astosc)]; this++) {
225 if (this->function == FCN_AID) {
226 int j;
228 switch (this->shiftstate) {
229 case 0:
230 j = 0;
231 break;
232 case SHIFT_UPSHIFT:
233 j = 1;
234 break;
235 case SHIFT_ALT:
236 j = 2;
237 break;
238 case (SHIFT_UPSHIFT|SHIFT_ALT):
239 j = 3;
240 break;
241 default:
242 fprintf(stderr, "Bad shiftstate 0x%x.\n", this->shiftstate);
243 exit(1);
245 if (hits[this->scancode].hit[j].code == i) {
246 putstr(this->name);
247 return;
252 putstr("Unknown AID 0x");
253 put2hex(i);
256 void
257 PrintAddr(i)
258 int i;
260 if (ColsLeft() < 9) {
261 Column1();
263 putChar('(');
264 putdecimal(ScreenLine(i));
265 putChar(',');
266 putdecimal(ScreenLineOffset(i));
267 putChar(')');
271 /* returns the number of characters consumed */
273 DataFromNetwork(buffer, count, control)
274 unsigned char *buffer; /* what the data is */
275 int count; /* and how much there is */
276 int control; /* this buffer ended block? */
278 int origCount;
279 int c;
280 int i;
281 static int Command;
282 static int Wcc;
283 static int LastWasTerminated = 1; /* was "control" = 1 last time? */
285 if (count == 0) {
286 Column1();
287 return 0;
290 origCount = count;
292 if (LastWasTerminated) {
294 if (count < 2) {
295 if (count == 0) {
296 fflush(stdout);
297 fprintf(stderr, "Short count received from host!\n");
298 fflush(stderr);
299 return(count);
301 Command = buffer[0];
302 switch (Command) { /* This had better be a read command */
303 case CMD_READ_MODIFIED:
304 putstr("read_modified command\n");
305 break;
306 case CMD_SNA_READ_MODIFIED:
307 putstr("sna_read_modified command\n");
308 break;
309 case CMD_SNA_READ_MODIFIED_ALL:
310 putstr("sna_read_modified_all command\n");
311 break;
312 case CMD_READ_BUFFER:
313 putstr("read_buffer command\n");
314 break;
315 case CMD_SNA_READ_BUFFER:
316 putstr("sna_read_buffer command\n");
317 break;
318 default:
319 break;
321 return(1); /* We consumed everything */
323 Command = buffer[0];
324 Wcc = buffer[1];
325 switch (Command) {
326 case CMD_ERASE_WRITE:
327 putstr("erase write command ");
328 break;
329 case CMD_ERASE_WRITE_ALTERNATE:
330 putstr("erase write alternate command ");
331 break;
332 case CMD_SNA_ERASE_WRITE:
333 putstr("sna erase write command ");
334 break;
335 case CMD_SNA_ERASE_WRITE_ALTERNATE:
336 putstr("erase write alternate command ");
337 break;
338 case CMD_ERASE_ALL_UNPROTECTED:
339 putstr("erase all unprotected command ");
340 break;
341 case CMD_SNA_ERASE_ALL_UNPROTECTED:
342 putstr("sna erase write command ");
343 break;
344 case CMD_WRITE:
345 putstr("write command ");
346 break;
347 case CMD_SNA_WRITE:
348 putstr("sna write command ");
349 break;
350 default:
351 putstr("Unexpected command code 0x");
352 puthex(Command);
353 putstr(" received.");
354 Column1();
355 break;
357 putstr("WCC is 0x");
358 puthex(Wcc);
359 Column1();
361 count -= 2; /* strip off command and wcc */
362 buffer += 2;
365 LastWasTerminated = 0; /* then, reset at end... */
367 while (count) {
368 count--;
369 c = *buffer++;
370 if (IsOrder(c)) {
371 /* handle an order */
372 switch (c) {
373 # define Ensure(x) if (count < x) { \
374 if (!control) { \
375 return(origCount-(count+1)); \
376 } else { \
377 /* XXX - should not occur */ \
378 count = 0; \
379 break; \
382 case ORDER_SF:
383 Ensure(1);
384 c = *buffer++;
385 count--;
386 putstr("SF (0x");
387 put2hex(c);
388 putstr(") ");
389 break;
390 case ORDER_SBA:
391 Ensure(2);
392 i = buffer[0];
393 c = buffer[1];
394 buffer += 2;
395 count -= 2;
396 putstr("SBA to ");
397 PrintAddr(Addr3270(i,c));
398 putSpace();
399 break;
400 case ORDER_IC:
401 putstr("IC");
402 putSpace();
403 break;
404 case ORDER_PT:
405 putstr("PT");
406 putSpace();
407 break;
408 case ORDER_RA:
409 Ensure(3);
410 i = Addr3270(buffer[0], buffer[1]);
411 c = buffer[2];
412 buffer += 3;
413 count -= 3;
414 putstr("RA to ");
415 PrintAddr(i);
416 putstr(" of 0x");
417 put2hex(c);
418 putSpace();
419 break;
420 case ORDER_EUA: /* (from [here,there), ie: half open interval] */
421 Ensure(2);
422 putstr("EUA to ");
423 PrintAddr(Addr3270(buffer[0], buffer[1]));
424 putSpace();
425 buffer += 2;
426 count -= 2;
427 break;
428 case ORDER_YALE: /* special YALE defined order */
429 Ensure(2); /* need at least two characters */
430 putstr("YALE order");
431 putSpace();
432 break;
433 default:
434 putstr("UNKNOWN ORDER: 0x");
435 put2hex(c);
436 putSpace();
437 break;
439 if (count < 0) {
440 count = 0;
442 } else {
443 /* Data comes in large clumps - take it all */
444 putstr("DATA:");
445 Indent();
446 putEChar(c);
447 c = *buffer;
448 while (count && !IsOrder(c)) {
449 putEChar(c);
450 count--;
451 buffer++;
452 c = *buffer;
454 Undent();
457 LastWasTerminated = control;
458 return origCount - count;
462 DataToNetwork(buffer, count, control)
463 unsigned char *buffer;
464 int count;
465 int control;
467 #define NEED_AID 0
468 #define JUST_GOT_AID 1
469 #define DATA 2
470 #define DATA_CONTINUE 3
471 static int state = NEED_AID;
472 static int aid;
473 int origCount = count;
475 if (count == 0) {
476 if (control) {
477 state = NEED_AID;
479 Column1();
480 return 0;
483 switch (state) {
484 case NEED_AID:
485 aid = buffer[0];
486 buffer++;
487 count--;
488 PrintAid(aid);
489 putSpace();
490 if (aid == AID_TREQ) {
491 state = DATA;
492 } else {
493 state = JUST_GOT_AID;
495 return origCount - count + DataToNetwork(buffer, count, control);
496 case JUST_GOT_AID:
497 Ensure(2);
498 PrintAddr(Addr3270(buffer[0], buffer[1]));
499 putSpace();
500 buffer += 2;
501 count -= 2;
502 state = DATA;
503 return origCount - count + DataToNetwork(buffer, count, control);
504 case DATA:
505 case DATA_CONTINUE:
506 while (count) {
507 if (*buffer == ORDER_SBA) {
508 if (state == DATA_CONTINUE) {
509 Undent();
510 state = DATA;
512 putstr("SBA ");
513 PrintAddr(Addr3270(buffer[1], buffer[2]));
514 putSpace();
515 buffer += 3;
516 count -= 3;
517 } else {
518 if (state == DATA) {
519 putstr("DATA:");
520 Indent();
521 state = DATA_CONTINUE;
523 putEChar(*buffer);
524 buffer++;
525 count--;
528 if (control) {
529 if (state == DATA_CONTINUE) {
530 Undent();
532 state = NEED_AID;
534 return origCount-count;
536 return 0;
540 GetXValue(c)
541 int c;
543 if (!isascii(c)) {
544 fflush(stdout);
545 fprintf(stderr, "Non-hex digit 0x%x.\n", c);
546 fflush(stderr);
547 return 0;
548 } else {
549 if (islower(c)) {
550 return (c-'a')+10;
551 } else if (isupper(c)) {
552 return (c-'A')+10;
553 } else {
554 return c-'0';
559 unsigned char outbound[8192], inbound[8192],
560 *outnext = outbound, *innext = inbound, *p = 0;
562 void
563 termblock(old, new, control)
564 int old,
565 new; /* old and new directions */
567 int count;
569 if (p) {
570 if (old == '<') {
571 outnext = p;
572 count = DataFromNetwork(outbound, outnext-outbound, control);
573 if (outbound+count == outnext) {
574 outnext = outbound;
575 } else {
576 memcpy(outbound, outbound+count, outnext-(outbound+count));
577 outnext = outbound+count;
579 } else {
580 innext = p;
581 count = DataToNetwork(inbound, innext-inbound, control);
582 if (inbound+count == innext) {
583 innext = inbound;
584 } else {
585 memcpy(inbound, inbound+count, innext-(inbound+count));
586 innext = inbound+count;
590 if (new == '<') {
591 p = outnext;
592 } else if (new == '>') {
593 p = innext;
594 } else {
595 fprintf(stderr, "Bad direction character '%c'.\n", new);
596 exit(1);
601 main(argc, argv)
602 int argc;
603 char *argv[];
605 int location;
606 char new;
607 int c, c1;
609 memset(Orders, 0, sizeof Orders);
610 Orders[ORDER_SF] = Orders[ORDER_SBA] = Orders[ORDER_IC]
611 = Orders[ORDER_PT] = Orders[ORDER_RA] = Orders[ORDER_EUA]
612 = Orders[ORDER_YALE] = 1;
614 while (scanf("%c 0x%x\t", &new, &location) != EOF) {
615 if (new != direction) {
616 termblock(direction, new, 0);
617 direction = new;
619 while (((c = getchar()) != EOF) && (c != '\n') && (isxdigit(c))) {
620 #define NORMAL 0
621 #define GOT0XFF 0xff
622 static int state = NORMAL;
624 c1 = getchar();
625 c = (GetXValue(c) << 4) + GetXValue(c1);
626 switch (state) {
627 case NORMAL:
628 if (c == 0xff) {
629 state = GOT0XFF;
630 } else {
631 *p++ = c;
633 break;
634 case GOT0XFF:
635 if (c == 0xef) {
636 termblock(direction, direction, 1);
637 } else {
638 *p++ = 0xff;
639 *p++ = c;
641 state = NORMAL;
645 return 0;