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