1 /* 2 * This file implements the API used in the PC version. 3 */ 4 5 #include <stdio.h> 6 #include <dos.h> 7 #include <stdlib.h> 8 9 #include "spint.h" 10 #include "api.h" 11 #include "../general.h" 12 13 #include "../ctlr/screen.h" 14 #include "../system/globals.h" 15 16 int ApiDisableInput = 0; 17 18 /* 19 * Supervisor Services. 20 */ 21 22 static void 23 name_resolve(regs, sregs) 24 union REGS *regs; 25 struct SREGS *sregs; 26 { 27 NameResolveParms parms; 28 29 movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms); 30 31 regs->h.cl = 0; 32 if (strcmp((char *)&parms, NAME_SESSMGR) == 0) { 33 regs->x.dx = GATE_SESSMGR; 34 } else if (strcmp((char *)&parms, NAME_KEYBOARD) == 0) { 35 regs->x.dx = GATE_KEYBOARD; 36 } else if (strcmp((char *)&parms, NAME_COPY) == 0) { 37 regs->x.dx = GATE_COPY; 38 } else if (strcmp((char *)&parms, NAME_OIAM) == 0) { 39 regs->x.dx = GATE_OIAM; 40 } else { 41 regs->h.cl = 0x2e; /* Name not found */ 42 } 43 regs->h.ch = 0x12; 44 regs->h.bh = 7; 45 } 46 47 /* 48 * Session Information Services. 49 */ 50 51 static void 52 query_session_id(regs, sregs) 53 union REGS *regs; 54 struct SREGS *sregs; 55 { 56 QuerySessionIdParms parms; 57 58 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 59 60 if (parms.rc != 0) { 61 regs->h.cl = 0x0c; 62 return; 63 } 64 if (parms.option_code != 0x01) { 65 regs->h.cl = 0x0d; /* Invalid option code */ 66 } else if (parms.data_code != 0x45) { 67 regs->h.cl = 0x0b; 68 } else { 69 NameArray list; 70 NameArrayElement element; 71 72 movetous((char *)&list, FP_SEG(parms.name_array), 73 FP_OFFSET(parms.name_array), sizeof list); 74 if ((list.length < 14) || (list.length > 170)) { 75 parms.rc = 0x12; 76 regs->h.cl = 0x12; 77 } else { 78 list.number_matching_session = 1; 79 list.name_array_element.short_name = parms.data_code; 80 list.name_array_element.type = TYPE_DFT; 81 list.name_array_element.session_id = 23; 82 memcpy(list.name_array_element.long_name, "ONLYSESS", 83 sizeof list.name_array_element.long_name); 84 movetothem(FP_SEG(parms.name_array), 85 FP_OFFSET(parms.name_array), (char *)&list, sizeof list); 86 parms.rc = 0; 87 regs->h.cl = 0; 88 } 89 } 90 parms.function_id = 0x6d; 91 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 92 } 93 94 static void 95 query_session_parameters(regs, sregs) 96 union REGS *regs; 97 struct SREGS *sregs; 98 { 99 QuerySessionParametersParms parms; 100 101 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 102 103 if ((parms.rc !=0) || (parms.function_id != 0)) { 104 regs->h.cl = 0x0c; 105 return; 106 } 107 if (parms.session_id != 23) { 108 regs->h.cl = parms.rc = 0x02; 109 } else { 110 regs->h.cl = parms.rc = 0; 111 parms.function_id = 0x6b; 112 parms.session_type = TYPE_DFT; 113 parms.session_characteristics = 0; /* Neither EAB nor PSS */ 114 parms.rows = MaxNumberLines; 115 parms.columns = MaxNumberColumns; 116 parms.presentation_space = 0; 117 } 118 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 119 } 120 121 static void 122 query_session_cursor(regs, sregs) 123 union REGS *regs; 124 struct SREGS *sregs; 125 { 126 QuerySessionCursorParms parms; 127 128 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 129 130 if ((parms.rc != 0) || (parms.function_id != 0)) { 131 parms.rc = 0x0c; 132 } else if (parms.session_id != 23) { 133 parms.rc = 0x02; 134 } else { 135 parms.rc = 0; 136 parms.function_id = 0x6b; 137 parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */ 138 parms.row_address = ScreenLine(CursorAddress); 139 parms.column_address = ScreenLineOffset(CursorAddress); 140 } 141 142 movetothem(sregs->es, regs->x.di, sizeof parms); 143 } 144 145 /* 146 * Keyboard Services. 147 */ 148 149 150 static void 151 connect_to_keyboard(regs, sregs) 152 union REGS *regs; 153 struct SREGS *sregs; 154 { 155 ConnectToKeyboardParms parms; 156 157 movetous((char *)parms, sregs->es, regs->x.di, sizeof parms); 158 159 if ((parms.rc != 0) || (parms.function_id != 0)) { 160 parms.rc = 0x0c; 161 } else if (parms.session_id != 23) { 162 parms.rc = 0x02; 163 } else if (parms.intercept_options != 0) { 164 parms.rc = 0x01; 165 } else { 166 parms.rc = 0; 167 parms.first_connection_identifier = 0; 168 } 169 parms.function_id = 0x62; 170 171 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 172 } 173 174 static void 175 disconnect_from_keyboard(regs, sregs) 176 union REGS *regs; 177 struct SREGS *sregs; 178 { 179 DisconnectFromKeyboardParms parms; 180 181 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 182 183 if ((parms.rc != 0) || (parms.function_id != 0)) { 184 parms.rc = 0x0c; 185 } else if (parms.session_id != 23) { 186 parms.rc = 0x02; 187 } else if (parms.connectors_task_id != 0) { 188 parms.rc = 04; /* XXX */ 189 } else { 190 parms.rc = 0; 191 } 192 parms.function_id = 0x62; 193 194 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 195 } 196 197 static void 198 write_keystroke(regs, sregs) 199 union REGS *regs; 200 struct SREGS *sregs; 201 { 202 /* XXX */ 203 } 204 205 206 static void 207 disable_input(regs, sregs) 208 union REGS *regs; 209 struct SREGS *sregs; 210 { 211 DisableInputParms parms; 212 213 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 214 215 if ((parms.rc != 0) || (parms.function_id != 0)) { 216 parms.rc = 0x0c; 217 } else if (parms.session_id != 23) { 218 parms.rc = 0x02; 219 } else if (parms.connectors_task_id != 0) { 220 parms.rc = 0x04; 221 } else { 222 ApiDisableInput = 1; 223 parms.rc = 0; 224 } 225 parms.function_id = 0x62; 226 227 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 228 } 229 230 static void 231 enable_input(regs, sregs) 232 union REGS *regs; 233 struct SREGS *sregs; 234 { 235 EnableInputParms parms; 236 237 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 238 239 if ((parms.rc != 0) || (parms.function_id != 0)) { 240 parms.rc = 0x0c; 241 } else if (parms.session_id != 23) { 242 parms.rc = 0x02; 243 } else if (parms.connectors_task_id != 0) { 244 parms.rc = 0x04; 245 } else { 246 ApiDisableInput = 0; 247 parms.rc = 0; 248 } 249 parms.function_id = 0x62; 250 251 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 252 } 253 254 /* 255 * Copy Services. 256 */ 257 258 static void 259 copy_string(regs, sregs) 260 union REGS *regs; 261 struct SREGS *sregs; 262 { 263 CopyStringParms parms; 264 BufferDescriptor *target, *source; 265 266 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 267 268 if ((parms.rc != 0) || (parms.function_id !=0)) { 269 parms.rc = 0x0c; 270 } 271 /* XXX do something! */ 272 movetothem(sregs->es, regs->x.di, (char *)parms, sizeof parms); 273 } 274 /* 275 * Operator Information Area Services. 276 */ 277 278 static void 279 read_oia_group(regs, sregs) 280 union REGS *regs; 281 struct SREGS *sregs; 282 { 283 ReadOiaGroupParms parms; 284 285 movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms); 286 287 if ((parms.rc != 0) || (parms.function_id != 0)) { 288 parms.rc = 0x0c; 289 } else if (parms.session_id != 23) { 290 parms.rc = 0x02; 291 } else { 292 int group = parms.oia_group_number; 293 char far *where = parms.oia_buffer; 294 295 switch (group) { 296 case OIA_ALL_GROUPS: 297 case OIA_ONLINE_OWNERSHIP: 298 if (group != OIA_ALL_GROUPS) { 299 break; 300 } /* else, fall through */ 301 case OIA_CHARACTER_SELECTION: 302 if (group != OIA_ALL_GROUPS) { 303 break; 304 } /* else, fall through */ 305 case OIA_SHIFT_STATE: 306 if (group != OIA_ALL_GROUPS) { 307 break; 308 } /* else, fall through */ 309 case OIA_PSS_GROUP_1: 310 if (group != OIA_ALL_GROUPS) { 311 break; 312 } /* else, fall through */ 313 case OIA_HIGHLIGHT_GROUP_1: 314 if (group != OIA_ALL_GROUPS) { 315 break; 316 } /* else, fall through */ 317 case OIA_COLOR_GROUP_1: 318 if (group != OIA_ALL_GROUPS) { 319 break; 320 } /* else, fall through */ 321 case OIA_INSERT: 322 if (group != OIA_ALL_GROUPS) { 323 break; 324 } /* else, fall through */ 325 case OIA_INPUT_INHIBITED: 326 if (group != OIA_ALL_GROUPS) { 327 break; 328 } /* else, fall through */ 329 case OIA_PSS_GROUP_2: 330 if (group != OIA_ALL_GROUPS) { 331 break; 332 } /* else, fall through */ 333 case OIA_HIGHLIGHT_GROUP_2: 334 if (group != OIA_ALL_GROUPS) { 335 break; 336 } /* else, fall through */ 337 case OIA_COLOR_GROUP_2: 338 if (group != OIA_ALL_GROUPS) { 339 break; 340 } /* else, fall through */ 341 case OIA_COMMUNICATION_ERROR_REMINDER: 342 if (group != OIA_ALL_GROUPS) { 343 break; 344 } /* else, fall through */ 345 case OIA_PRINTER_STATUS: 346 if (group != OIA_ALL_GROUPS) { 347 break; 348 } /* else, fall through */ 349 case OIA_AUTOKEY_PLAY_RECORD_STATUS: 350 if (group != OIA_ALL_GROUPS) { 351 break; 352 } /* else, fall through */ 353 case OIA_AUTOKEY_ABORT_PAUSE_STATUS: 354 if (group != OIA_ALL_GROUPS) { 355 break; 356 } /* else, fall through */ 357 case OIA_ENLARGE_STATE: 358 if (group != OIA_ALL_GROUPS) { 359 break; 360 } /* else, fall through */ 361 362 /* oops, we are done! */ 363 break; 364 default: 365 break; 366 } 367 } 368 parms.function_id = 0x6d; 369 movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms); 370 } 371 372 static void 373 unknown_op(regs, sregs) 374 union REGS *regs; 375 struct SREGS *sregs; 376 { 377 regs->h.ch = 0x12; 378 regs->h.cl = 0x05; 379 } 380 381 382 handle_api(regs, sregs) 383 union REGS *regs; 384 struct SREGS *sregs; 385 { 386 if (regs->h.ah == NAME_RESOLUTION) { 387 name_resolution(regs, sregs); 388 } else if (regs->h.ah != 0x09) { 389 regs->h.ch = 0x12; 390 regs->h.cl = 0x0f; /* XXX Invalid environmental access */ 391 } else if (regs->x.bx != 0x8020) { 392 regs->h.ch = 0x12; 393 regs->h.cl = 0x08; /* XXX Invalid wait specified */ 394 } else if (regs->h.ch != 0) { 395 regs->h.ch = 0x12; 396 regs->h.cl = 0x07; /* XXX Invalid reply specified */ 397 } else { 398 switch (regs->x.dx) { 399 case GATE_SESSMGR: 400 switch (regs->h.al) { 401 case QUERY_SESSION_ID: 402 if (regs->h.cl != 0) { 403 } else { 404 query_session_id(regs, sregs); 405 } 406 break; 407 case QUERY_SESSION_PARMS: 408 if (regs->h.cl != 0) { 409 } else { 410 query_session_parms(regs, sregs); 411 } 412 break; 413 case QUERY_SESSION_CURSOR: 414 if (regs->h.cl != 0xff) { 415 } else { 416 query_session_cursor(regs, sregs); 417 } 418 break; 419 default: 420 unknown_op(regs, sregs); 421 break; 422 } 423 break; 424 case GATE_KEYBOARD: 425 if (regs->h.cl != 00) { 426 } else { 427 switch (regs->h.al) { 428 case CONNECT_TO_KEYBOARD: 429 connect_to_keyboard(regs, sregs); 430 break; 431 case DISABLE_INPUT: 432 disable_input(regs, sregs); 433 break; 434 case WRITE_KEYSTROKE: 435 write_keystroke(regs, sregs); 436 break; 437 case ENABLE_INPUT: 438 enable_input(regs, sregs); 439 break; 440 case DISCONNECT_FROM_KEYBOARD: 441 disconnect_from_keyboard(regs, sregs); 442 break; 443 default: 444 unknown_op(regs, sregs); 445 break; 446 } 447 } 448 break; 449 case GATE_COPY: 450 if (regs->h.cl != 0xff) { 451 } else { 452 switch (regs->h.al) { 453 case COPY_STRING: 454 copy_string(regs, sregs); 455 break; 456 default: 457 unknown_op(regs, sregs); 458 break; 459 } 460 } 461 break; 462 case GATE_OIAM: 463 if (regs->h.cl != 0xff) { 464 } else { 465 switch (regs->h.al) { 466 case READ_OIA_GROUP: 467 read_oia_group(regs, sregs); 468 break; 469 default: 470 unknown_op(regs, sregs); 471 break; 472 } 473 } 474 break; 475 default: 476 regs->h.ch = 0x12; 477 regs->h.cl = 0x34; /* Invalid GATE entry */ 478 break; 479 } 480 } 481 } 482 483 484 /* 485 * Called from telnet.c to fork a lower command.com. We 486 * use the spint... routines so that we can pick up 487 * interrupts generated by application programs. 488 */ 489 490 491 int 492 shell(argc,argv) 493 int argc; 494 char *argv[]; 495 { 496 Spint spinted; 497 char command[256]; 498 499 ClearElement(spinted); 500 spinted.int_no = API_INTERRUPT_NUMBER; 501 if (argc == 1) { 502 command[0] = 0; 503 } else { 504 char *cmdptr; 505 int length; 506 507 argc--; 508 argv++; 509 strcpy(command, " /c"); 510 cmdptr = command+strlen(command); 511 while (argc) { 512 if ((cmdptr+strlen(*argv)) >= (command+sizeof command)) { 513 fprintf(stderr, "Argument list too long at argument *%s*.\n", 514 *argv); 515 return 0; 516 } 517 *cmdptr++ = ' '; /* Blank separators */ 518 strcpy(cmdptr, *argv); 519 cmdptr += strlen(cmdptr); 520 argc--; 521 argv++; 522 } 523 length = strlen(command)-1; 524 if (length < 0) { 525 length = 0; 526 } 527 command[0] = length; 528 } 529 530 /* 531 * spint_start() returns when either the command has finished, or when 532 * the required interrupt comes in. In the latter case, the appropriate 533 * thing to do is to process the interrupt, and then return to 534 * the interrupt issuer by calling spint_continue(). 535 */ 536 spint_start(command, &spinted); 537 while (spinted.done == 0) { 538 /* Process request */ 539 handle_api(&spinted.regs, &spinted.sregs); 540 spint_continue(&spinted); 541 } 542 if (spinted.rc != 0) { 543 fprintf(stderr, "Process generated a return code of 0x%x.\n", 544 spinted.rc); 545 } 546 return 0; 547 } 548