xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 31168)
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