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