|
|
1.1 ! root 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: static char sccsid[] = "@(#)outbound.c 4.2 (Berkeley) 2/6/89"; ! 20: #endif /* not lint */ ! 21: ! 22: #include <stdio.h> ! 23: ! 24: #include "../general/general.h" ! 25: ! 26: #include "hostctlr.h" ! 27: #include "oia.h" ! 28: #include "screen.h" ! 29: #include "../api/ebc_disp.h" ! 30: ! 31: #include "../general/globals.h" ! 32: #include "externs.h" ! 33: #include "declare.h" ! 34: ! 35: #define SetHighestLowest(position) { \ ! 36: if (position < Lowest) { \ ! 37: Lowest = position; \ ! 38: } \ ! 39: if (position > Highest) { \ ! 40: Highest = position; \ ! 41: } \ ! 42: } ! 43: ! 44: ! 45: static int LastWasTerminated = 1; /* was "control" = 1 last time? */ ! 46: ! 47: /* some globals */ ! 48: ! 49: #if !defined(PURE3274) ! 50: int OutputClock; /* what time it is */ ! 51: int TransparentClock; /* time we were last in transparent */ ! 52: #endif /* !defined(PURE3274) */ ! 53: ! 54: char CIABuffer[64] = { ! 55: 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, ! 56: 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, ! 57: 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, ! 58: 0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, ! 59: 0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, ! 60: 0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, ! 61: 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, ! 62: 0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f ! 63: }; ! 64: ! 65: static struct orders_def orders_def[] = ORDERS_DEF; ! 66: ! 67: /* ! 68: * init_ctlr() ! 69: * ! 70: * Initialize all data from the 'data' portion to their startup values. ! 71: */ ! 72: ! 73: void ! 74: init_ctlr() ! 75: { ! 76: LastWasTerminated = 1; ! 77: init_inbound(); ! 78: init_oia(); ! 79: } ! 80: ! 81: ! 82: FieldInc(position) ! 83: register int position; /* Position in previous field */ ! 84: { ! 85: register ScreenImage *ptr; ! 86: ! 87: ptr = (ScreenImage *)memNSchr((char *)Host+position+1, ATTR_MASK, ! 88: HighestScreen()-position, ATTR_MASK, sizeof Host[0]); ! 89: if (ptr == 0) { ! 90: ptr = (ScreenImage *)memNSchr((char *)Host+LowestScreen(), ATTR_MASK, ! 91: position-LowestScreen(), ATTR_MASK, sizeof Host[0]); ! 92: if (ptr == 0) { ! 93: return LowestScreen(); ! 94: } ! 95: } ! 96: return ptr-Host; ! 97: } ! 98: ! 99: FieldDec(position) ! 100: int position; ! 101: { ! 102: register ScreenImage *ptr; ! 103: ! 104: ptr = (ScreenImage *)memNSchr((char *)(Host+position)-1, ATTR_MASK, ! 105: position-LowestScreen(), ATTR_MASK, -sizeof Host[0]); ! 106: if (ptr == 0) { ! 107: ptr = (ScreenImage *)memNSchr((char *)Host+HighestScreen(), ATTR_MASK, ! 108: HighestScreen()-position, ATTR_MASK, -sizeof Host[0]); ! 109: if (ptr == 0) { ! 110: return LowestScreen(); ! 111: } ! 112: } ! 113: return ptr-Host; ! 114: } ! 115: ! 116: /* Clear3270 - called to clear the screen */ ! 117: ! 118: void ! 119: Clear3270() ! 120: { ! 121: ClearArray(Host); ! 122: DeleteAllFields(); /* get rid of all fields */ ! 123: BufferAddress = SetBufferAddress(0,0); ! 124: CursorAddress = SetBufferAddress(0,0); ! 125: Lowest = LowestScreen(); ! 126: Highest = HighestScreen(); ! 127: } ! 128: ! 129: /* AddHost - called to add a character to the buffer. ! 130: * We use a macro in this module, since we call it so ! 131: * often from loops. ! 132: * ! 133: * NOTE: It is a macro, so don't go around using AddHost(p, *c++), or ! 134: * anything similar. (I don't define any temporary variables, again ! 135: * just for the speed.) ! 136: */ ! 137: void ! 138: AddHost(position, character) ! 139: int position; ! 140: char character; ! 141: { ! 142: # define AddHostA(p,c) \ ! 143: { \ ! 144: if (IsStartField(p)) { \ ! 145: DeleteField(p); \ ! 146: Highest = HighestScreen(); \ ! 147: Lowest = LowestScreen(); \ ! 148: SetHighestLowest(p); \ ! 149: } \ ! 150: SetHost(p, c); \ ! 151: } ! 152: # define AddHost(p,c) \ ! 153: { \ ! 154: if (c != GetHost(p)) { \ ! 155: SetHighestLowest(p); \ ! 156: } \ ! 157: AddHostA(p,c); \ ! 158: } /* end of macro of AddHost */ ! 159: ! 160: AddHost(position, character); ! 161: } ! 162: ! 163: /* returns the number of characters consumed */ ! 164: int ! 165: DataFromNetwork(Buffer, count, control) ! 166: char *Buffer; /* what the data is */ ! 167: register int count; /* and how much there is */ ! 168: int control; /* this buffer ended block? */ ! 169: { ! 170: int origCount; ! 171: register unsigned char *buffer = (unsigned char *)Buffer; ! 172: register int c; ! 173: register int i; ! 174: static int Command; ! 175: static int Wcc; ! 176: ! 177: origCount = count; ! 178: ! 179: /* ! 180: * If this is the start of a new data stream, then look ! 181: * for an op-code and (possibly) a WCC. ! 182: */ ! 183: if (LastWasTerminated) { ! 184: ! 185: if (count < 2) { ! 186: if (count == 0) { ! 187: ExitString("Short count received from host!\n", 1); ! 188: return(count); ! 189: } ! 190: Command = buffer[0]; ! 191: switch (Command) { /* This had better be a read command */ ! 192: case CMD_READ_MODIFIED: ! 193: case CMD_SNA_READ_MODIFIED: ! 194: case CMD_SNA_READ_MODIFIED_ALL: ! 195: SetOiaOnlineA(&OperatorInformationArea); ! 196: SetOiaModified(); ! 197: DoReadModified(Command); ! 198: break; ! 199: case CMD_READ_BUFFER: ! 200: case CMD_SNA_READ_BUFFER: ! 201: SetOiaOnlineA(&OperatorInformationArea); ! 202: SetOiaModified(); ! 203: DoReadBuffer(); ! 204: break; ! 205: default: ! 206: { ! 207: char s_buffer[100]; ! 208: ! 209: sprintf(s_buffer, ! 210: "Unexpected read command code 0x%x received.\n", ! 211: Command); ! 212: ExitString(s_buffer, 1); ! 213: break; ! 214: } ! 215: } ! 216: return(1); /* We consumed everything */ ! 217: } ! 218: Command = buffer[0]; ! 219: Wcc = buffer[1]; ! 220: if (Wcc & WCC_RESET_MDT) { ! 221: i = c = WhereAttrByte(LowestScreen()); ! 222: do { ! 223: if (HasMdt(i)) { ! 224: TurnOffMdt(i); ! 225: } ! 226: i = FieldInc(i); ! 227: } while (i != c); ! 228: } ! 229: ! 230: switch (Command) { ! 231: case CMD_ERASE_WRITE: ! 232: case CMD_ERASE_WRITE_ALTERNATE: ! 233: case CMD_SNA_ERASE_WRITE: ! 234: case CMD_SNA_ERASE_WRITE_ALTERNATE: ! 235: { ! 236: int newlines, newcolumns; ! 237: ! 238: SetOiaOnlineA(&OperatorInformationArea); ! 239: ResetOiaTWait(&OperatorInformationArea); ! 240: SetOiaModified(); ! 241: if ((Command == CMD_ERASE_WRITE) ! 242: || (Command == CMD_SNA_ERASE_WRITE)) { ! 243: newlines = 24; ! 244: newcolumns = 80; ! 245: } else { ! 246: newlines = MaxNumberLines; ! 247: newcolumns = MaxNumberColumns; ! 248: } ! 249: if ((newlines != NumberLines) ! 250: || (newcolumns != NumberColumns)) { ! 251: /* ! 252: * The LocalClearScreen() is really for when we ! 253: * are going from a larger screen to a smaller ! 254: * screen, and we need to clear off the stuff ! 255: * at the end of the lines, or the lines at ! 256: * the end of the screen. ! 257: */ ! 258: LocalClearScreen(); ! 259: NumberLines = newlines; ! 260: NumberColumns = newcolumns; ! 261: ScreenSize = NumberLines * NumberColumns; ! 262: } ! 263: Clear3270(); ! 264: #if !defined(PURE3274) ! 265: if (TransparentClock == OutputClock) { ! 266: TransStop(); ! 267: } ! 268: #endif /* !defined(PURE3274) */ ! 269: break; ! 270: } ! 271: ! 272: case CMD_ERASE_ALL_UNPROTECTED: ! 273: case CMD_SNA_ERASE_ALL_UNPROTECTED: ! 274: SetOiaOnlineA(&OperatorInformationArea); ! 275: ResetOiaTWait(&OperatorInformationArea); ! 276: SetOiaModified(); ! 277: CursorAddress = HighestScreen()+1; ! 278: for (i = LowestScreen(); i <= HighestScreen(); i = ScreenInc(i)) { ! 279: if (IsUnProtected(i)) { ! 280: if (CursorAddress > i) { ! 281: CursorAddress = i; ! 282: } ! 283: AddHost(i, '\0'); ! 284: } ! 285: if (HasMdt(i)) { ! 286: TurnOffMdt(i); ! 287: } ! 288: } ! 289: if (CursorAddress == HighestScreen()+1) { ! 290: CursorAddress = SetBufferAddress(0,0); ! 291: } ! 292: UnLocked = 1; ! 293: AidByte = 0; ! 294: ResetOiaSystemLocked(&OperatorInformationArea); ! 295: SetOiaModified(); ! 296: TerminalIn(); ! 297: break; ! 298: case CMD_WRITE: ! 299: case CMD_SNA_WRITE: ! 300: SetOiaOnlineA(&OperatorInformationArea); ! 301: ResetOiaTWait(&OperatorInformationArea); ! 302: SetOiaModified(); ! 303: break; ! 304: default: ! 305: { ! 306: char s_buffer[100]; ! 307: ! 308: sprintf(s_buffer, ! 309: "Unexpected write command code 0x%x received.\n", ! 310: Command); ! 311: ExitString(s_buffer, 1); ! 312: break; ! 313: } ! 314: } ! 315: ! 316: count -= 2; /* strip off command and wcc */ ! 317: buffer += 2; ! 318: ! 319: } else { ! 320: #if !defined(PURE3274) ! 321: if (TransparentClock == OutputClock) { ! 322: TransOut(buffer, count, -1, control); ! 323: count = 0; ! 324: } ! 325: #endif /* !defined(PURE3274) */ ! 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: if ( ! (IsStartField(BufferAddress) && ! 349: FieldAttributes(BufferAddress) == c)) { ! 350: SetHighestLowest(BufferAddress); ! 351: NewField(BufferAddress,c); ! 352: } ! 353: BufferAddress = ScreenInc(BufferAddress); ! 354: break; ! 355: case ORDER_SBA: ! 356: Ensure(2); ! 357: i = buffer[0]; ! 358: c = buffer[1]; ! 359: #if !defined(PURE3274) ! 360: /* Check for transparent write */ ! 361: if ((i == 0) && ((c == 0) || (c == 1) || (c == 5))) { ! 362: TransparentClock = OutputClock+1; ! 363: TransOut(buffer+2, count-2, c, control); ! 364: buffer += count; ! 365: count -= count; ! 366: break; ! 367: } ! 368: #endif /* !defined(PURE3274) */ ! 369: BufferAddress = Addr3270(i, c); ! 370: buffer += 2; ! 371: count -= 2; ! 372: break; ! 373: case ORDER_IC: ! 374: CursorAddress = BufferAddress; ! 375: break; ! 376: /* ! 377: * XXX - PT is supposed to null fill the screen buffer ! 378: * under certain draconian conditions. ! 379: */ ! 380: case ORDER_PT: ! 381: i = BufferAddress; ! 382: do { ! 383: if (IsStartField(i)) { ! 384: if (!IsProtected(ScreenInc(i))) { ! 385: break; ! 386: } ! 387: } ! 388: i = ScreenInc(i); ! 389: } while (i != HighestScreen()); ! 390: BufferAddress = ScreenInc(i); ! 391: break; ! 392: case ORDER_RA: ! 393: Ensure(3); ! 394: i = Addr3270(buffer[0], buffer[1]); ! 395: if ((i < 0) || (i > HighestScreen())) { ! 396: char s_buffer[200]; ! 397: ! 398: sprintf(s_buffer, "tn3270: %s%d.\n\t%s%d%s%d%s\n", ! 399: "Invalid 3270 order 'Repeat to Address' to address ", ! 400: i, ! 401: "(Screen currently set to ", ! 402: NumberLines, ! 403: " by ", ! 404: NumberColumns, ! 405: ".)"); ! 406: ExitString(s_buffer, 1); ! 407: /*NOTREACHED*/ ! 408: } ! 409: c = buffer[2]; ! 410: if (c == ORDER_GE) { ! 411: Ensure(4); ! 412: c = buffer[3]; ! 413: buffer += 4; ! 414: count -= 4; ! 415: } else { ! 416: buffer += 3; ! 417: count -= 3; ! 418: } ! 419: do { ! 420: AddHost(BufferAddress, ebc_disp[c]); ! 421: BufferAddress = ScreenInc(BufferAddress); ! 422: } while (BufferAddress != i); ! 423: break; ! 424: case ORDER_EUA: /* (from [here,there), ie: half open interval] */ ! 425: Ensure(2); ! 426: /* ! 427: * Compiler error - msc version 4.0: ! 428: * "expression too complicated". ! 429: */ ! 430: i = WhereAttrByte(BufferAddress); ! 431: c = FieldAttributes(i); ! 432: i = Addr3270(buffer[0], buffer[1]); ! 433: if ((i < 0) || (i > HighestScreen())) { ! 434: char s_buffer[200]; ! 435: ! 436: sprintf(s_buffer, "tn3270: %s%d.\n\t%s%d%s%d%s\n", ! 437: "Invalid 3270 order 'Erase Unprotected to Address' to address ", ! 438: i, ! 439: "(Screen currently set to ", ! 440: NumberLines, ! 441: " by ", ! 442: NumberColumns, ! 443: ".)"); ! 444: ExitString(s_buffer, 1); ! 445: /*NOTREACHED*/ ! 446: } ! 447: do { ! 448: if (IsStartField(BufferAddress)) { ! 449: c = FieldAttributes(BufferAddress); ! 450: } else if (!IsProtectedAttr(BufferAddress, c)) { ! 451: AddHost(BufferAddress, 0); ! 452: } ! 453: BufferAddress = ScreenInc(BufferAddress); ! 454: } while (i != BufferAddress); ! 455: buffer += 2; ! 456: count -= 2; ! 457: break; ! 458: case ORDER_GE: ! 459: Ensure(2); ! 460: /* XXX Should do SOMETHING! */ ! 461: /* XXX buffer += 0; */ ! 462: /* XXX count -= 0; *//* For now, just use this character */ ! 463: break; ! 464: case ORDER_YALE: /* special YALE defined order */ ! 465: Ensure(2); /* need at least two characters */ ! 466: if (*buffer == 0x5b) { ! 467: i = OptOrder(buffer+1, count-1, control); ! 468: if (i == 0) { ! 469: return(origCount-(count+1)); /* come here again */ ! 470: } else { ! 471: buffer += 1 + i; ! 472: count -= (1 + i); ! 473: } ! 474: } ! 475: break; ! 476: default: ! 477: { ! 478: char s_buffer[100]; ! 479: static struct orders_def unk_order ! 480: = { 0, "??", "(unknown)" }; ! 481: struct orders_def *porder = &unk_order; ! 482: int s_i; ! 483: ! 484: for (s_i = 0; s_i <= highestof(orders_def); s_i++) { ! 485: if (orders_def[s_i].code == c) { ! 486: porder = &orders_def[s_i]; ! 487: break; ! 488: } ! 489: } ! 490: sprintf(s_buffer, ! 491: "Unsupported order '%s' (%s, 0x%x) received.\n", ! 492: porder->long_name, porder->short_name, c); ! 493: ExitString(s_buffer, 1); ! 494: /*NOTREACHED*/ ! 495: } ! 496: } ! 497: if (count < 0) { ! 498: count = 0; ! 499: } ! 500: } else { ! 501: /* Data comes in large clumps - take it all */ ! 502: i = BufferAddress; ! 503: AddHostA(i, ebc_disp[c]); ! 504: SetHighestLowest(i); ! 505: i = ScreenInc(i); ! 506: c = *buffer; ! 507: while (count && !IsOrder(c)) { ! 508: AddHostA(i, ebc_disp[c]); ! 509: i = ScreenInc(i); ! 510: if (i == LowestScreen()) { ! 511: SetHighestLowest(HighestScreen()); ! 512: } ! 513: count--; ! 514: buffer++; ! 515: c = *buffer; ! 516: } ! 517: SetHighestLowest(i); ! 518: BufferAddress = i; ! 519: } ! 520: } ! 521: if (count == 0) { ! 522: if (control) { ! 523: #if !defined(PURE3274) ! 524: OutputClock++; /* time rolls on */ ! 525: #endif /* !defined(PURE3274) */ ! 526: if (Wcc & WCC_RESTORE) { ! 527: #if !defined(PURE3274) ! 528: if (TransparentClock != OutputClock) { ! 529: AidByte = 0; ! 530: } ! 531: #else /* !defined(PURE3274) */ ! 532: AidByte = 0; ! 533: #endif /* !defined(PURE3274) */ ! 534: UnLocked = 1; ! 535: ResetOiaSystemLocked(&OperatorInformationArea); ! 536: SetOiaModified(); ! 537: SetPsModified(); ! 538: TerminalIn(); ! 539: } ! 540: if (Wcc & WCC_ALARM) { ! 541: RingBell((char *)0); ! 542: } ! 543: } ! 544: LastWasTerminated = control; /* state for next time */ ! 545: return(origCount); ! 546: } else { ! 547: return(origCount-count); ! 548: } ! 549: } ! 550: ! 551: /* ! 552: * Init3270() ! 553: * ! 554: * Initialize any 3270 (controller) variables to an initial state ! 555: * in preparation for accepting a connection. ! 556: */ ! 557: ! 558: void ! 559: Init3270() ! 560: { ! 561: int i; ! 562: ! 563: OptInit(); /* initialize mappings */ ! 564: ! 565: ClearArray(Host); ! 566: ! 567: ClearArray(Orders); ! 568: for (i = 0; i <= highestof(orders_def); i++) { ! 569: Orders[orders_def[i].code] = 1; ! 570: } ! 571: ! 572: DeleteAllFields(); /* Clear screen */ ! 573: Lowest = HighestScreen()+1; ! 574: Highest = LowestScreen()-1; ! 575: CursorAddress = BufferAddress = SetBufferAddress(0,0); ! 576: UnLocked = 1; ! 577: #if !defined(PURE3274) ! 578: OutputClock = 1; ! 579: TransparentClock = -1; ! 580: #endif /* !defined(PURE3274) */ ! 581: SetOiaReady3274(&OperatorInformationArea); ! 582: } ! 583: ! 584: ! 585: void ! 586: Stop3270() ! 587: { ! 588: ResetOiaReady3274(&OperatorInformationArea); ! 589: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.