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