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