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