1 /* 2 * Copyright (c) 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #ifndef lint 14 char copyright[] = 15 "@(#) Copyright (c) 1988 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif /* not lint */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)prt3270.c 3.3 (Berkeley) 03/28/88"; 21 #endif /* not lint */ 22 23 #if defined(unix) 24 #endif 25 #include <stdio.h> 26 #include <ctype.h> 27 28 #include "../general/general.h" 29 30 #include "../api/asc_ebc.h" 31 #include "../ctlr/hostctlr.h" 32 #include "../ctlr/screen.h" 33 #include "../ctlr/function.h" 34 #include "../api/astosc.h" 35 #include "../general/globals.h" 36 37 #include "../ctlr/kbd.out" 38 39 40 int NumberColumns = 80; 41 42 int direction; 43 44 int column = 1; 45 int indenting = 0; 46 int direction = '?'; 47 48 unsigned char printBuffer[200], *print = printBuffer; 49 50 #define ColsLeft() (79-column) /* A little room for error */ 51 52 53 void 54 putSpace() 55 { 56 extern void Column1(); 57 unsigned char *ourPrint = print; 58 59 print = printBuffer; /* For mutual calls */ 60 *ourPrint = 0; 61 if (ColsLeft() < 0) { 62 Column1(); 63 } 64 if (column != (indenting*8+1)) { 65 putchar(' '); 66 } else { 67 int i; 68 69 putchar(direction); 70 putchar(' '); 71 for (i = 0; i < indenting; i++) { 72 putchar('\t'); 73 } 74 } 75 printf("%s", printBuffer); 76 column += strlen(printBuffer); 77 } 78 79 void 80 Column1() 81 { 82 if (print != printBuffer) { 83 putSpace(); 84 } 85 if (column != (indenting*8+1)) { 86 putchar('\n'); 87 column = indenting*8+1; 88 } 89 } 90 91 void 92 Indent() 93 { 94 if ((column != (indenting*8+1)) || (print != printBuffer)) { 95 Column1(); 96 } 97 indenting++; 98 column = indenting*8+1; 99 } 100 101 void 102 Undent() 103 { 104 if ((column != (indenting*8+1)) || (print != printBuffer)) { 105 Column1(); 106 } 107 indenting--; 108 if (indenting < 0) { 109 fflush(stdout); 110 fprintf(stderr, "INTERNAL ERROR: indenting < 0.\n"); 111 fflush(stderr); 112 } else { 113 column = indenting*8+1; 114 } 115 } 116 117 void 118 putChar(character) 119 int character; 120 { 121 *print++ = character; 122 column++; 123 } 124 125 void 126 putstr(s) 127 char *s; 128 { 129 while (*s) { 130 putChar(*s++); 131 } 132 } 133 134 void 135 put2hex(i) 136 int i; 137 { 138 char place[40]; 139 140 sprintf(place, "%02x", i); 141 putstr(place); 142 } 143 144 145 void 146 putdecimal(i) 147 int i; 148 { 149 char place[40]; 150 151 sprintf(place, "%d", i); 152 putstr(place); 153 } 154 155 void 156 puthex(i) 157 int i; 158 { 159 char place[40]; 160 161 sprintf(place, "%x", i); 162 putstr(place); 163 } 164 165 void 166 putEChar(character) 167 int character; 168 { 169 putChar(ebc_asc[character]); 170 if (ColsLeft() < 10) { 171 Column1(); 172 } 173 } 174 175 void 176 PrintAid(i) 177 int i; 178 { 179 struct astosc *this; 180 181 for (this = &astosc[0]; this <= &astosc[highestof(astosc)]; this++) { 182 if (this->function == FCN_AID) { 183 int j; 184 185 switch (this->shiftstate) { 186 case 0: 187 j = 0; 188 break; 189 case SHIFT_UPSHIFT: 190 j = 1; 191 break; 192 case SHIFT_ALT: 193 j = 2; 194 break; 195 case (SHIFT_UPSHIFT|SHIFT_ALT): 196 j = 3; 197 break; 198 default: 199 fprintf(stderr, "Bad shiftstate 0x%x.\n", this->shiftstate); 200 exit(1); 201 } 202 if (hits[this->scancode].hit[j].code == i) { 203 putstr(this->name); 204 return; 205 } 206 } 207 } 208 209 putstr("Unknown AID 0x"); 210 put2hex(i); 211 } 212 213 void 214 PrintAddr(i) 215 int i; 216 { 217 if (ColsLeft() < 9) { 218 Column1(); 219 } 220 putChar('('); 221 putdecimal(ScreenLine(i)); 222 putChar(','); 223 putdecimal(ScreenLineOffset(i)); 224 putChar(')'); 225 } 226 227 228 /* returns the number of characters consumed */ 229 int 230 DataFromNetwork(buffer, count, control) 231 register unsigned char *buffer; /* what the data is */ 232 register int count; /* and how much there is */ 233 int control; /* this buffer ended block? */ 234 { 235 int origCount; 236 register int c; 237 register int i; 238 static int Command; 239 static int Wcc; 240 static int LastWasTerminated = 1; /* was "control" = 1 last time? */ 241 242 if (count == 0) { 243 Column1(); 244 return 0; 245 } 246 247 origCount = count; 248 249 if (LastWasTerminated) { 250 251 if (count < 2) { 252 if (count == 0) { 253 fflush(stdout); 254 fprintf(stderr, "Short count received from host!\n"); 255 fflush(stderr); 256 return(count); 257 } 258 Command = buffer[0]; 259 switch (Command) { /* This had better be a read command */ 260 case CMD_READ_MODIFIED: 261 putstr("read_modified command\n"); 262 break; 263 case CMD_SNA_READ_MODIFIED: 264 putstr("sna_read_modified command\n"); 265 break; 266 case CMD_SNA_READ_MODIFIED_ALL: 267 putstr("sna_read_modified_all command\n"); 268 break; 269 case CMD_READ_BUFFER: 270 putstr("read_buffer command\n"); 271 break; 272 case CMD_SNA_READ_BUFFER: 273 putstr("sna_read_buffer command\n"); 274 break; 275 default: 276 break; 277 } 278 return(1); /* We consumed everything */ 279 } 280 Command = buffer[0]; 281 Wcc = buffer[1]; 282 switch (Command) { 283 case CMD_ERASE_WRITE: 284 putstr("erase write command "); 285 break; 286 case CMD_ERASE_WRITE_ALTERNATE: 287 putstr("erase write alternate command "); 288 break; 289 case CMD_SNA_ERASE_WRITE: 290 putstr("sna erase write command "); 291 break; 292 case CMD_SNA_ERASE_WRITE_ALTERNATE: 293 putstr("erase write alternate command "); 294 break; 295 case CMD_ERASE_ALL_UNPROTECTED: 296 putstr("erase all unprotected command "); 297 break; 298 case CMD_SNA_ERASE_ALL_UNPROTECTED: 299 putstr("sna erase write command "); 300 break; 301 case CMD_WRITE: 302 putstr("write command "); 303 break; 304 case CMD_SNA_WRITE: 305 putstr("sna write command "); 306 break; 307 default: 308 putstr("Unexpected command code 0x"); 309 puthex(Command); 310 putstr(" received."); 311 Column1(); 312 break; 313 } 314 putstr("WCC is 0x"); 315 puthex(Wcc); 316 Column1(); 317 318 count -= 2; /* strip off command and wcc */ 319 buffer += 2; 320 321 } 322 LastWasTerminated = 0; /* then, reset at end... */ 323 324 while (count) { 325 count--; 326 c = *buffer++; 327 if (IsOrder(c)) { 328 /* handle an order */ 329 switch (c) { 330 # define Ensure(x) if (count < x) { \ 331 if (!control) { \ 332 return(origCount-(count+1)); \ 333 } else { \ 334 /* XXX - should not occur */ \ 335 count = 0; \ 336 break; \ 337 } \ 338 } 339 case ORDER_SF: 340 Ensure(1); 341 c = *buffer++; 342 count--; 343 putstr("SF (0x"); 344 put2hex(c); 345 putstr(") "); 346 break; 347 case ORDER_SBA: 348 Ensure(2); 349 i = buffer[0]; 350 c = buffer[1]; 351 buffer += 2; 352 count -= 2; 353 putstr("SBA to "); 354 PrintAddr(Addr3270(i,c)); 355 putSpace(); 356 break; 357 case ORDER_IC: 358 putstr("IC"); 359 putSpace(); 360 break; 361 case ORDER_PT: 362 putstr("PT"); 363 putSpace(); 364 break; 365 case ORDER_RA: 366 Ensure(3); 367 i = Addr3270(buffer[0], buffer[1]); 368 c = buffer[2]; 369 buffer += 3; 370 count -= 3; 371 putstr("RA to "); 372 PrintAddr(i); 373 putstr(" of 0x"); 374 put2hex(c); 375 putSpace(); 376 break; 377 case ORDER_EUA: /* (from [here,there), ie: half open interval] */ 378 Ensure(2); 379 putstr("EUA to "); 380 PrintAddr(Addr3270(buffer[0], buffer[1])); 381 putSpace(); 382 buffer += 2; 383 count -= 2; 384 break; 385 case ORDER_YALE: /* special YALE defined order */ 386 Ensure(2); /* need at least two characters */ 387 putstr("YALE order"); 388 putSpace(); 389 break; 390 default: 391 putstr("UNKNOWN ORDER: 0x"); 392 put2hex(c); 393 putSpace(); 394 break; 395 } 396 if (count < 0) { 397 count = 0; 398 } 399 } else { 400 /* Data comes in large clumps - take it all */ 401 putstr("DATA:"); 402 Indent(); 403 putEChar(c); 404 c = *buffer; 405 while (count && !IsOrder(c)) { 406 putEChar(c); 407 count--; 408 buffer++; 409 c = *buffer; 410 } 411 Undent(); 412 } 413 } 414 LastWasTerminated = control; 415 return origCount - count; 416 } 417 418 int 419 DataToNetwork(buffer, count, control) 420 unsigned char *buffer; 421 int count; 422 int control; 423 { 424 #define NEED_AID 0 425 #define JUST_GOT_AID 1 426 #define DATA 2 427 #define DATA_CONTINUE 3 428 static int state = NEED_AID; 429 static int aid; 430 int origCount = count; 431 432 if (count == 0) { 433 if (control) { 434 state = NEED_AID; 435 } 436 Column1(); 437 return 0; 438 } 439 440 switch (state) { 441 case NEED_AID: 442 aid = buffer[0]; 443 buffer++; 444 count--; 445 PrintAid(aid); 446 putSpace(); 447 if (aid == AID_TREQ) { 448 state = DATA; 449 } else { 450 state = JUST_GOT_AID; 451 } 452 return origCount - count + DataToNetwork(buffer, count, control); 453 case JUST_GOT_AID: 454 Ensure(2); 455 PrintAddr(Addr3270(buffer[0], buffer[1])); 456 putSpace(); 457 buffer += 2; 458 count -= 2; 459 state = DATA; 460 return origCount - count + DataToNetwork(buffer, count, control); 461 case DATA: 462 case DATA_CONTINUE: 463 while (count) { 464 if (*buffer == ORDER_SBA) { 465 if (state == DATA_CONTINUE) { 466 Undent(); 467 state = DATA; 468 } 469 putstr("SBA "); 470 PrintAddr(Addr3270(buffer[1], buffer[2])); 471 putSpace(); 472 buffer += 3; 473 count -= 3; 474 } else { 475 if (state == DATA) { 476 putstr("DATA:"); 477 Indent(); 478 state = DATA_CONTINUE; 479 } 480 putEChar(*buffer); 481 buffer++; 482 count--; 483 } 484 } 485 if (control) { 486 if (state == DATA_CONTINUE) { 487 Undent(); 488 } 489 state = NEED_AID; 490 } 491 return origCount-count; 492 } 493 } 494 495 int 496 GetXValue(c) 497 int c; 498 { 499 if (!isascii(c)) { 500 fflush(stdout); 501 fprintf(stderr, "Non-hex digit 0x%x.\n"); 502 fflush(stderr); 503 return 0; 504 } else { 505 if (islower(c)) { 506 return (c-'a')+10; 507 } else if (isupper(c)) { 508 return (c-'A')+10; 509 } else { 510 return c-'0'; 511 } 512 } 513 } 514 515 unsigned char outbound[8192], inbound[8192], 516 *outnext = outbound, *innext = inbound, *p = 0; 517 518 void 519 termblock(old, new, control) 520 int old, 521 new; /* old and new directions */ 522 { 523 int count; 524 525 if (p) { 526 if (old == '<') { 527 outnext = p; 528 count = DataFromNetwork(outbound, outnext-outbound, control); 529 if (outbound+count == outnext) { 530 outnext = outbound; 531 } else { 532 memcpy(outbound, outbound+count, outnext-(outbound+count)); 533 outnext = outbound+count; 534 } 535 } else { 536 innext = p; 537 count = DataToNetwork(inbound, innext-inbound, control); 538 if (inbound+count == innext) { 539 innext = inbound; 540 } else { 541 memcpy(inbound, inbound+count, innext-(inbound+count)); 542 innext = inbound+count; 543 } 544 } 545 } 546 if (new == '<') { 547 p = outnext; 548 } else if (new == '>') { 549 p = innext; 550 } else { 551 fprintf(stderr, "Bad direction character '%c'.\n", new); 552 exit(1); 553 } 554 } 555 556 main() 557 { 558 int location; 559 char new; 560 int c, c1; 561 562 memset(Orders, 0, sizeof Orders); 563 Orders[ORDER_SF] = Orders[ORDER_SBA] = Orders[ORDER_IC] 564 = Orders[ORDER_PT] = Orders[ORDER_RA] = Orders[ORDER_EUA] 565 = Orders[ORDER_YALE] = 1; 566 567 while (scanf("%c 0x%x\t", &new, &location) != EOF) { 568 if (new != direction) { 569 termblock(direction, new, 0); 570 direction = new; 571 } 572 while (((c = getchar()) != EOF) && (c != '\n') && (isxdigit(c))) { 573 #define NORMAL 0 574 #define GOT0XFF 0xff 575 static int state = NORMAL; 576 577 c1 = getchar(); 578 c = (GetXValue(c) << 4) + GetXValue(c1); 579 switch (state) { 580 case NORMAL: 581 if (c == 0xff) { 582 state = GOT0XFF; 583 } else { 584 *p++ = c; 585 } 586 break; 587 case GOT0XFF: 588 if (c == 0xef) { 589 termblock(direction, direction, 1); 590 } else { 591 *p++ = 0xff; 592 *p++ = c; 593 } 594 state = NORMAL; 595 } 596 } 597 } 598 return 0; 599 } 600