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