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[] = "@(#)api.c 4.2 (Berkeley) 05/30/89"; 20 #endif /* not lint */ 21 22 /* 23 * This file implements the API used in the PC version. 24 */ 25 26 #include <stdio.h> 27 28 #include "api.h" 29 #include "../general/general.h" 30 31 #include "../api/disp_asc.h" 32 33 #include "screen.h" 34 #include "hostctlr.h" 35 #include "oia.h" 36 37 #include "../general/globals.h" 38 39 /* 40 * General utility routines. 41 */ 42 43 #if defined(MSDOS) 44 45 #if defined(LINT_ARGS) 46 static void movetous(char *, int, int, int); 47 static void movetothem(int, int, char *, int); 48 #endif /* defined(LINT_ARGS) */ 49 50 #define access_api(foo,length,copyin) (foo) 51 #define unaccess_api(foo,goo,length,copyout) 52 53 static void 54 movetous(parms, es, di, length) 55 char *parms; 56 int es, di; 57 int length; 58 { 59 char far *farparms = parms; 60 61 movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length); 62 } 63 64 static void 65 movetothem(es, di, parms, length) 66 int es, di; 67 char *parms; 68 int length; 69 { 70 char far *farparms = parms; 71 72 movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length); 73 } 74 #endif /* defined(MSDOS) */ 75 76 #if defined(unix) 77 extern char *access_api(); 78 extern void movetous(), movetothem(), unaccess_api(); 79 #endif /* defined(unix) */ 80 81 82 /* 83 * Supervisor Services. 84 */ 85 86 static void 87 name_resolution(regs, sregs) 88 union REGS *regs; 89 struct SREGS *sregs; 90 { 91 NameResolveParms parms; 92 93 movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms); 94 95 regs->h.cl = 0; 96 if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) { 97 regs->x.dx = GATE_SESSMGR; 98 } else if (memcmp((char *)&parms, NAME_KEYBOARD, 99 sizeof parms.gate_name) == 0) { 100 regs->x.dx = GATE_KEYBOARD; 101 } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) { 102 regs->x.dx = GATE_COPY; 103 } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) { 104 regs->x.dx = GATE_OIAM; 105 } else { 106 regs->h.cl = 0x2e; /* Name not found */ 107 } 108 regs->h.ch = 0x12; 109 regs->h.bh = 7; 110 } 111 112 /* 113 * Session Information Services. 114 */ 115 116 static void 117 query_session_id(regs, sregs) 118 union REGS *regs; 119 struct SREGS *sregs; 120 { 121 QuerySessionIdParms parms; 122 123 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 124 125 if ((parms.rc != 0) || (parms.function_id != 0)) { 126 parms.rc = 0x0c; 127 } else if (parms.option_code != 0x01) { 128 parms.rc = 0x0d; /* Invalid option code */ 129 } else if (parms.data_code != 0x45) { 130 parms.rc = 0x0b; 131 } else { 132 NameArray list; 133 134 movetous((char *)&list, FP_SEG(parms.name_array), 135 FP_OFF(parms.name_array), sizeof list); 136 if ((list.length < 14) || (list.length > 170)) { 137 parms.rc = 0x12; 138 } else { 139 list.number_matching_session = 1; 140 list.name_array_element.short_name = parms.data_code; 141 list.name_array_element.type = TYPE_DFT; 142 list.name_array_element.session_id = 23; 143 memcpy(list.name_array_element.long_name, "ONLYSESS", 144 sizeof list.name_array_element.long_name); 145 movetothem(FP_SEG(parms.name_array), 146 FP_OFF(parms.name_array), (char *)&list, sizeof list); 147 parms.rc = 0; 148 } 149 } 150 parms.function_id = 0x6b; 151 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 152 } 153 154 static void 155 query_session_parameters(regs, sregs) 156 union REGS *regs; 157 struct SREGS *sregs; 158 { 159 QuerySessionParametersParms parms; 160 161 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 162 163 if ((parms.rc !=0) || (parms.function_id != 0)) { 164 parms.rc = 0x0c; 165 } else if (parms.session_id != 23) { 166 parms.rc = 0x02; 167 } else { 168 parms.rc = 0; 169 parms.session_type = TYPE_DFT; 170 parms.session_characteristics = 0; /* Neither EAB nor PSS */ 171 parms.rows = MaxNumberLines; 172 parms.columns = MaxNumberColumns; 173 parms.presentation_space = 0; 174 } 175 parms.function_id = 0x6b; 176 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 177 } 178 179 static void 180 query_session_cursor(regs, sregs) 181 union REGS *regs; 182 struct SREGS *sregs; 183 { 184 QuerySessionCursorParms parms; 185 186 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 187 188 if ((parms.rc != 0) || (parms.function_id != 0)) { 189 parms.rc = 0x0c; 190 } else if (parms.session_id != 23) { 191 parms.rc = 0x02; 192 } else { 193 parms.rc = 0; 194 parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */ 195 parms.row_address = ScreenLine(CursorAddress); 196 parms.column_address = ScreenLineOffset(CursorAddress); 197 } 198 199 parms.function_id = 0x6b; 200 movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms); 201 } 202 203 /* 204 * Keyboard Services. 205 */ 206 207 208 static void 209 connect_to_keyboard(regs, sregs) 210 union REGS *regs; 211 struct SREGS *sregs; 212 { 213 ConnectToKeyboardParms parms; 214 215 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 216 217 if ((parms.rc != 0) || (parms.function_id != 0)) { 218 parms.rc = 0x0c; 219 } else if (parms.session_id != 23) { 220 parms.rc = 0x02; 221 } else if (parms.intercept_options != 0) { 222 parms.rc = 0x01; 223 } else { 224 parms.rc = 0; 225 parms.first_connection_identifier = 0; 226 } 227 parms.function_id = 0x62; 228 229 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 230 } 231 232 static void 233 disconnect_from_keyboard(regs, sregs) 234 union REGS *regs; 235 struct SREGS *sregs; 236 { 237 DisconnectFromKeyboardParms parms; 238 239 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 240 241 if ((parms.rc != 0) || (parms.function_id != 0)) { 242 parms.rc = 0x0c; 243 } else if (parms.session_id != 23) { 244 parms.rc = 0x02; 245 } else if (parms.connectors_task_id != 0) { 246 parms.rc = 04; /* XXX */ 247 } else { 248 parms.rc = 0; 249 } 250 parms.function_id = 0x62; 251 252 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 253 } 254 255 static void 256 write_keystroke(regs, sregs) 257 union REGS *regs; 258 struct SREGS *sregs; 259 { 260 WriteKeystrokeParms parms; 261 262 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 263 264 if ((parms.rc != 0) || (parms.function_id != 0)) { 265 parms.rc = 0x0c; 266 } else if (parms.session_id != 23) { 267 parms.rc = 0x02; 268 } else if (parms.connectors_task_id != 0) { 269 parms.rc = 0x04; 270 } else { 271 parms.number_of_keys_sent = 0; 272 parms.rc = 0; 273 if (parms.options == OPTION_SINGLE_KEYSTROKE) { 274 KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry; 275 276 if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) { 277 parms.rc = 0x10; /* XXX needs 0x12 too! */ 278 } 279 parms.number_of_keys_sent++; 280 } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) { 281 KeystrokeList 282 list, 283 far *atlist = parms.keystroke_specifier.keystroke_list; 284 KeystrokeEntry 285 entry[10], /* 10 at a time */ 286 *ourentry, 287 far *theirentry; 288 int 289 todo; 290 291 movetous((char *)&list, FP_SEG(atlist), 292 FP_OFF(atlist), sizeof *atlist); 293 todo = list.length/2; 294 ourentry = entry+(highestof(entry)+1); 295 theirentry = &atlist->keystrokes; 296 297 while (todo) { 298 if (ourentry > &entry[highestof(entry)]) { 299 int thistime; 300 301 thistime = todo; 302 if (thistime > numberof(entry)) { 303 thistime = numberof(entry); 304 } 305 movetous((char *)entry, FP_SEG(theirentry), 306 FP_OFF(theirentry), thistime*sizeof *theirentry); 307 theirentry += thistime; 308 ourentry = entry; 309 } 310 if (AcceptKeystroke(ourentry->scancode, 311 ourentry->shift_state) == 0) { 312 parms.rc = 0x10; /* XXX needs 0x12 too! */ 313 break; 314 } 315 parms.number_of_keys_sent++; 316 ourentry++; 317 todo--; 318 } 319 } else { 320 parms.rc = 0x01; 321 } 322 } 323 parms.function_id = 0x62; 324 325 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 326 /* XXX */ 327 } 328 329 330 static void 331 disable_input(regs, sregs) 332 union REGS *regs; 333 struct SREGS *sregs; 334 { 335 DisableInputParms parms; 336 337 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 338 339 if ((parms.rc != 0) || (parms.function_id != 0)) { 340 parms.rc = 0x0c; 341 } else if (parms.session_id != 23) { 342 parms.rc = 0x02; 343 } else if (parms.connectors_task_id != 0) { 344 parms.rc = 0x04; 345 } else { 346 SetOiaApiInhibit(&OperatorInformationArea); 347 parms.rc = 0; 348 } 349 parms.function_id = 0x62; 350 351 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 352 } 353 354 static void 355 enable_input(regs, sregs) 356 union REGS *regs; 357 struct SREGS *sregs; 358 { 359 EnableInputParms parms; 360 361 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 362 363 if ((parms.rc != 0) || (parms.function_id != 0)) { 364 parms.rc = 0x0c; 365 } else if (parms.session_id != 23) { 366 parms.rc = 0x02; 367 } else if (parms.connectors_task_id != 0) { 368 parms.rc = 0x04; 369 } else { 370 ResetOiaApiInhibit(&OperatorInformationArea); 371 parms.rc = 0; 372 } 373 parms.function_id = 0x62; 374 375 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 376 } 377 378 /* 379 * Copy Services. 380 */ 381 382 static 383 copy_subroutine(target, source, parms, what_is_user, length) 384 BufferDescriptor *target, *source; 385 CopyStringParms *parms; 386 int what_is_user; 387 #define USER_IS_TARGET 0 388 #define USER_IS_SOURCE 1 389 { 390 #define TARGET_NO_EAB 1 391 #define SOURCE_NO_EAB 2 392 #define TARGET_PC 4 393 #define SOURCE_PC 8 394 #define NO_FIELD_ATTRIBUTES 16 395 int needtodo = 0; 396 int access_length; 397 char far *input; 398 char far *output; 399 char far *access_pointer; 400 401 if ((target->characteristics^source->characteristics) 402 &CHARACTERISTIC_EAB) { 403 if (target->characteristics&CHARACTERISTIC_EAB) { 404 needtodo |= TARGET_NO_EAB; /* Need to bump for EAB in target */ 405 } else { 406 needtodo |= SOURCE_NO_EAB; /* Need to bump for EAB in source */ 407 } 408 } 409 if (target->session_type != source->session_type) { 410 if (target->session_type == TYPE_PC) { 411 needtodo |= TARGET_PC; /* scan codes to PC */ 412 } else { 413 needtodo |= SOURCE_PC; /* PC to scan codes */ 414 } 415 } 416 if ((parms->copy_mode©_MODE_FIELD_ATTRIBUTES) == 0) { 417 needtodo |= NO_FIELD_ATTRIBUTES; 418 } 419 access_length = length; 420 if (what_is_user == USER_IS_TARGET) { 421 if (target->characteristics&CHARACTERISTIC_EAB) { 422 access_length *= 2; 423 } 424 input = (char far *) &Host[source->begin]; 425 access_pointer = target->buffer; 426 output = access_api(target->buffer, access_length, 0); 427 } else { 428 if (source->characteristics&CHARACTERISTIC_EAB) { 429 access_length *= 2; 430 } 431 access_pointer = source->buffer; 432 input = access_api(source->buffer, access_length, 1); 433 output = (char far *) &Host[target->begin]; 434 } 435 while (length--) { 436 if (needtodo&TARGET_PC) { 437 *output++ = disp_asc[*input++]; 438 } else if (needtodo&SOURCE_PC) { 439 *output++ = asc_disp[*input++]; 440 } else { 441 *output++ = *input++; 442 } 443 if (needtodo&TARGET_NO_EAB) { 444 input++; 445 } else if (needtodo&SOURCE_NO_EAB) { 446 *output++ = 0; /* Should figure out good EAB? */ 447 } 448 } 449 if (what_is_user == USER_IS_TARGET) { 450 unaccess_api(target->buffer, access_pointer, access_length, 1); 451 } else { 452 unaccess_api(source->buffer, access_pointer, access_length, 0); 453 } 454 } 455 456 457 static void 458 copy_string(regs, sregs) 459 union REGS *regs; 460 struct SREGS *sregs; 461 { 462 CopyStringParms parms; 463 BufferDescriptor *target = &parms.target, *source = &parms.source; 464 int length; 465 466 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 467 468 length = 1+parms.source_end-source->begin; 469 if ((parms.rc != 0) || (parms.function_id !=0)) { 470 parms.rc = 0x0c; 471 } else if (target->session_id == 0) { /* Target is buffer */ 472 if (source->session_id != 23) { /* A no-no */ 473 parms.rc = 0x2; 474 } else { 475 if ((source->begin < 0) || (source->begin > highestof(Host))) { 476 parms.rc = 0x06; /* invalid source definition */ 477 } else { 478 if ((source->begin+length) > highestof(Host)) { 479 length = highestof(Host)-source->begin; 480 parms.rc = 0x0f; /* Truncate */ 481 } 482 if ((source->characteristics == target->characteristics) && 483 (source->session_type == target->session_type)) { 484 if (source->characteristics&CHARACTERISTIC_EAB) { 485 length *= 2; 486 } 487 movetothem(FP_SEG(target->buffer), 488 FP_OFF(target->buffer), 489 (char *)&Host[source->begin], length); 490 } else { 491 copy_subroutine(target, source, &parms, 492 USER_IS_TARGET, length); 493 } 494 } 495 } 496 } else if (source->session_id != 0) { 497 parms.rc = 0xd; 498 } else { 499 /* Send to presentation space (3270 buffer) */ 500 if ((target->begin < 0) || (target->begin > highestof(Host))) { 501 parms.rc = 0x07; /* invalid target definition */ 502 } if (!UnLocked) { 503 parms.rc = 0x03; /* Keyboard locked */ 504 } else if (parms.copy_mode != 0) { 505 parms.rc = 0x0f; /* Copy of field attr's not allowed */ 506 } else if (IsProtected(target->begin) || /* Make sure no protected */ 507 (WhereAttrByte(target->begin) != /* in range */ 508 WhereAttrByte(target->begin+length-1))) { 509 parms.rc = 0x0e; /* Attempt to write in protected */ 510 } else { 511 if ((target->begin+length) > highestof(Host)) { 512 length = highestof(Host)-target->begin; 513 parms.rc = 0x0f; /* Truncate */ 514 } 515 TurnOnMdt(target->begin); /* Things have changed */ 516 if ((source->characteristics == target->characteristics) && 517 (source->session_type == target->session_type)) { 518 if (source->characteristics&CHARACTERISTIC_EAB) { 519 length *= 2; 520 } 521 movetous((char *)&Host[target->begin], 522 FP_SEG(source->buffer), 523 FP_OFF(source->buffer), length); 524 } else { 525 copy_subroutine(target, source, &parms, USER_IS_SOURCE, length); 526 } 527 } 528 } 529 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 530 } 531 /* 532 * Operator Information Area Services. 533 */ 534 535 static void 536 read_oia_group(regs, sregs) 537 union REGS *regs; 538 struct SREGS *sregs; 539 { 540 ReadOiaGroupParms parms; 541 542 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 543 544 if ((parms.rc != 0) || (parms.function_id != 0)) { 545 parms.rc = 0x0c; 546 } else if (parms.session_id != 23) { 547 parms.rc = 0x02; 548 } else { 549 int group = parms.oia_group_number; 550 char *from; 551 int size; 552 553 if ((group != API_OIA_ALL_GROUPS) && 554 ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) { 555 } else { 556 if (group == API_OIA_ALL_GROUPS) { 557 size = API_OIA_BYTES_ALL_GROUPS; 558 from = (char *)&OperatorInformationArea; 559 } else if (group == API_OIA_INPUT_INHIBITED) { 560 size = sizeof OperatorInformationArea.input_inhibited; 561 from = (char *)&OperatorInformationArea.input_inhibited[0]; 562 } else { 563 size = 1; 564 from = ((char *)&OperatorInformationArea)+group; 565 } 566 movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer), 567 from, size); 568 } 569 } 570 parms.function_id = 0x6d; 571 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 572 } 573 574 /*ARGSUSED*/ 575 static void 576 unknown_op(regs, sregs) 577 union REGS *regs; 578 struct SREGS *sregs; 579 { 580 regs->h.ch = 0x12; 581 regs->h.cl = 0x05; 582 } 583 584 585 handle_api(regs, sregs) 586 union REGS *regs; 587 struct SREGS *sregs; 588 { 589 if (regs->h.ah == NAME_RESOLUTION) { 590 name_resolution(regs, sregs); 591 #if defined(unix) 592 } else if (regs->h.ah == PS_OR_OIA_MODIFIED) { 593 while ((oia_modified == 0) && (ps_modified == 0)) { 594 (void) Scheduler(1); 595 } 596 oia_modified = ps_modified = 0; 597 #endif /* defined(unix) */ 598 } else if (regs->h.ah != 0x09) { 599 regs->h.ch = 0x12; 600 regs->h.cl = 0x0f; /* XXX Invalid environmental access */ 601 } else if (regs->x.bx != 0x8020) { 602 regs->h.ch = 0x12; 603 regs->h.cl = 0x08; /* XXX Invalid wait specified */ 604 } else if (regs->h.ch != 0) { 605 regs->x.cx = 0x1206; /* XXX Invalid priority */ 606 } else { 607 switch (regs->x.dx) { 608 case GATE_SESSMGR: 609 switch (regs->h.al) { 610 case QUERY_SESSION_ID: 611 if (regs->h.cl != 0) { 612 regs->x.cx = 0x1206; 613 } else { 614 regs->x.cx = 0x1200; 615 query_session_id(regs, sregs); 616 } 617 break; 618 case QUERY_SESSION_PARAMETERS: 619 if (regs->h.cl != 0) { 620 regs->x.cx = 0x1206; 621 } else { 622 regs->x.cx = 0x1200; 623 query_session_parameters(regs, sregs); 624 } 625 break; 626 case QUERY_SESSION_CURSOR: 627 if (regs->h.cl != 0xff) { 628 regs->x.cx = 0x1206; 629 } else { 630 regs->x.cx = 0x1200; 631 query_session_cursor(regs, sregs); 632 } 633 break; 634 default: 635 unknown_op(regs, sregs); 636 break; 637 } 638 break; 639 case GATE_KEYBOARD: 640 if (regs->h.cl != 00) { 641 regs->x.cx = 0x1206; 642 } else { 643 regs->x.cx = 0x1200; 644 switch (regs->h.al) { 645 case CONNECT_TO_KEYBOARD: 646 connect_to_keyboard(regs, sregs); 647 break; 648 case DISABLE_INPUT: 649 disable_input(regs, sregs); 650 break; 651 case WRITE_KEYSTROKE: 652 write_keystroke(regs, sregs); 653 break; 654 case ENABLE_INPUT: 655 enable_input(regs, sregs); 656 break; 657 case DISCONNECT_FROM_KEYBOARD: 658 disconnect_from_keyboard(regs, sregs); 659 break; 660 default: 661 unknown_op(regs, sregs); 662 break; 663 } 664 } 665 break; 666 case GATE_COPY: 667 if (regs->h.cl != 0xff) { 668 regs->x.cx = 0x1206; 669 } else { 670 regs->x.cx = 0x1200; 671 switch (regs->h.al) { 672 case COPY_STRING: 673 copy_string(regs, sregs); 674 break; 675 default: 676 unknown_op(regs, sregs); 677 break; 678 } 679 } 680 break; 681 case GATE_OIAM: 682 if (regs->h.cl != 0xff) { 683 regs->x.cx = 0x1206; 684 } else { 685 regs->x.cx = 0x1200; 686 switch (regs->h.al) { 687 case READ_OIA_GROUP: 688 read_oia_group(regs, sregs); 689 break; 690 default: 691 unknown_op(regs, sregs); 692 break; 693 } 694 } 695 break; 696 default: 697 regs->h.ch = 0x12; 698 regs->h.cl = 0x34; /* Invalid GATE entry */ 699 break; 700 } 701 } 702 } 703