xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 31211)
1 /*
2  * This file implements the API used in the PC version.
3  */
4 
5 #include <stdio.h>
6 
7 #include "api.h"
8 #include "../general/general.h"
9 
10 #include "../ctlr/screen.h"
11 #include "../ctlr/oia.h"
12 
13 #include "../general/globals.h"
14 
15 /*
16  * General utility routines.
17  */
18 
19 #if	defined(MSDOS)
20 
21 #if	defined(LINT_ARGS)
22 static void movetous(char *, int, int, int);
23 static void movetothem(int, int, char *, int);
24 #endif	/* defined(LINT_ARGS) */
25 
26 static void
27 movetous(parms, es, di, length)
28 char *parms;
29 int es, di, length;
30 {
31     char far *farparms = parms;
32 
33     movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length);
34 }
35 
36 static void
37 movetothem(es, di, parms, length)
38 int es, di;
39 char *parms;
40 int length;
41 {
42     char far *farparms = parms;
43 
44     movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length);
45 }
46 #endif	/* defined(MSDOS) */
47 
48 /* No Unix version yet... */
49 
50 
51 /*
52  * Supervisor Services.
53  */
54 
55 static void
56 name_resolution(regs, sregs)
57 union REGS *regs;
58 struct SREGS *sregs;
59 {
60     NameResolveParms parms;
61 
62     movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
63 
64     regs->h.cl = 0;
65     if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
66 	regs->x.dx = GATE_SESSMGR;
67     } else if (memcmp((char *)&parms, NAME_KEYBOARD,
68 					sizeof parms.gate_name) == 0) {
69 	regs->x.dx = GATE_KEYBOARD;
70     } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
71 	regs->x.dx = GATE_COPY;
72     } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
73 	regs->x.dx = GATE_OIAM;
74     } else {
75 	regs->h.cl = 0x2e;	/* Name not found */
76     }
77     regs->h.ch = 0x12;
78     regs->h.bh = 7;
79 }
80 
81 /*
82  * Session Information Services.
83  */
84 
85 static void
86 query_session_id(regs, sregs)
87 union REGS *regs;
88 struct SREGS *sregs;
89 {
90     QuerySessionIdParms parms;
91 
92     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
93 
94     if ((parms.rc != 0) || (parms.function_id != 0)) {
95 	parms.rc = 0x0c;
96     } else if (parms.option_code != 0x01) {
97 	parms.rc = 0x0d;	/* Invalid option code */
98     } else if (parms.data_code != 0x45) {
99 	parms.rc = 0x0b;
100     } else {
101 	NameArray list;
102 	NameArrayElement element;
103 
104 	movetous((char *)&list, FP_SEG(parms.name_array),
105 			    FP_OFF(parms.name_array), sizeof list);
106 	if ((list.length < 14) || (list.length > 170)) {
107 	    parms.rc = 0x12;
108 	} else {
109 	    list.number_matching_session = 1;
110 	    list.name_array_element.short_name = parms.data_code;
111 	    list.name_array_element.type = TYPE_DFT;
112 	    list.name_array_element.session_id = 23;
113 	    memcpy(list.name_array_element.long_name, "ONLYSESS",
114 			    sizeof list.name_array_element.long_name);
115 	    movetothem(FP_SEG(parms.name_array),
116 		FP_OFF(parms.name_array), (char *)&list, sizeof list);
117 	    parms.rc = 0;
118 	}
119     }
120     parms.function_id = 0x6b;
121     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
122 }
123 
124 static void
125 query_session_parameters(regs, sregs)
126 union REGS *regs;
127 struct SREGS *sregs;
128 {
129     QuerySessionParametersParms parms;
130 
131     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
132 
133     if ((parms.rc !=0) || (parms.function_id != 0)) {
134 	parms.rc = 0x0c;
135     } else if (parms.session_id != 23) {
136 	parms.rc = 0x02;
137     } else {
138 	parms.rc = 0;
139 	parms.session_type = TYPE_DFT;
140 	parms.session_characteristics = 0;	/* Neither EAB nor PSS */
141 	parms.rows = MaxNumberLines;
142 	parms.columns = MaxNumberColumns;
143 	parms.presentation_space = 0;
144     }
145     parms.function_id = 0x6b;
146     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
147 }
148 
149 static void
150 query_session_cursor(regs, sregs)
151 union REGS *regs;
152 struct SREGS *sregs;
153 {
154     QuerySessionCursorParms parms;
155 
156     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
157 
158     if ((parms.rc != 0) || (parms.function_id != 0)) {
159 	parms.rc = 0x0c;
160     } else if (parms.session_id != 23) {
161 	parms.rc = 0x02;
162     } else {
163 	parms.rc = 0;
164 	parms.cursor_type = CURSOR_BLINKING;	/* XXX what is inhibited? */
165 	parms.row_address = ScreenLine(CursorAddress);
166 	parms.column_address = ScreenLineOffset(CursorAddress);
167     }
168 
169     parms.function_id = 0x6b;
170     movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
171 }
172 
173 /*
174  * Keyboard Services.
175  */
176 
177 
178 static void
179 connect_to_keyboard(regs, sregs)
180 union REGS *regs;
181 struct SREGS *sregs;
182 {
183     ConnectToKeyboardParms parms;
184 
185     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
186 
187     if ((parms.rc != 0) || (parms.function_id != 0)) {
188 	parms.rc = 0x0c;
189     } else if (parms.session_id != 23) {
190 	parms.rc = 0x02;
191     } else if (parms.intercept_options != 0) {
192 	parms.rc = 0x01;
193     } else {
194 	parms.rc = 0;
195 	parms.first_connection_identifier = 0;
196     }
197     parms.function_id = 0x62;
198 
199     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
200 }
201 
202 static void
203 disconnect_from_keyboard(regs, sregs)
204 union REGS *regs;
205 struct SREGS *sregs;
206 {
207     DisconnectFromKeyboardParms 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 = 04;			/* XXX */
217     } else {
218 	parms.rc = 0;
219     }
220     parms.function_id = 0x62;
221 
222     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
223 }
224 
225 static void
226 write_keystroke(regs, sregs)
227 union REGS *regs;
228 struct SREGS *sregs;
229 {
230     WriteKeystrokeParms parms;
231 
232     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
233 
234     if ((parms.rc != 0) || (parms.function_id != 0)) {
235 	parms.rc = 0x0c;
236     } else if (parms.session_id != 23) {
237 	parms.rc = 0x02;
238     } else if (parms.connectors_task_id != 0) {
239 	parms.rc = 0x04;
240     } else {
241 	parms.number_of_keys_sent = 0;
242 	parms.rc = 0;
243 	if (parms.options == OPTION_SINGLE_KEYSTROKE) {
244 	    KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
245 
246 	    if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
247 		parms.rc = 0x10;		/* XXX needs 0x12 too! */
248 	    }
249 	    parms.number_of_keys_sent++;
250 	} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
251 	    KeystrokeList
252 		list,
253 		far *atlist = parms.keystroke_specifier.keystroke_list;
254 	    KeystrokeEntry
255 		entry[10],		/* 10 at a time */
256 		*ourentry,
257 		far *theirentry;
258 	    int
259 		todo;
260 
261 	    movetous((char *)&list, FP_SEG(atlist),
262 				FP_OFF(atlist), sizeof *atlist);
263 	    todo = list.length/2;
264 	    ourentry = entry+(highestof(entry)+1);
265 
266 	    while (todo) {
267 		if (ourentry > &entry[highestof(entry)]) {
268 		    int thistime;
269 
270 		    thistime = todo;
271 		    if (thistime > numberof(entry)) {
272 			thistime = numberof(entry);
273 		    }
274 		    movetous((char *)entry, FP_SEG(theirentry),
275 			    FP_OFF(theirentry), thistime*sizeof *theirentry);
276 		    theirentry += thistime;
277 		    ourentry = entry;
278 		}
279 		if (AcceptKeystroke(ourentry->scancode,
280 						ourentry->shift_state) == 0) {
281 		    parms.rc = 0x10;		/* XXX needs 0x12 too! */
282 		    break;
283 		}
284 		parms.number_of_keys_sent++;
285 		ourentry++;
286 		todo--;
287 	    }
288 	} else {
289 	    parms.rc = 0x01;
290 	}
291     }
292     parms.function_id = 0x62;
293 
294     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
295 /* XXX */
296 }
297 
298 
299 static void
300 disable_input(regs, sregs)
301 union REGS *regs;
302 struct SREGS *sregs;
303 {
304     DisableInputParms parms;
305 
306     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
307 
308     if ((parms.rc != 0) || (parms.function_id != 0)) {
309 	parms.rc = 0x0c;
310     } else if (parms.session_id != 23) {
311 	parms.rc = 0x02;
312     } else if (parms.connectors_task_id != 0) {
313 	parms.rc = 0x04;
314     } else {
315 	SetOiaApiInhibit(&OperatorInformationArea);
316 	parms.rc = 0;
317     }
318     parms.function_id = 0x62;
319 
320     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
321 }
322 
323 static void
324 enable_input(regs, sregs)
325 union REGS *regs;
326 struct SREGS *sregs;
327 {
328     EnableInputParms parms;
329 
330     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
331 
332     if ((parms.rc != 0) || (parms.function_id != 0)) {
333 	parms.rc = 0x0c;
334     } else if (parms.session_id != 23) {
335 	parms.rc = 0x02;
336     } else if (parms.connectors_task_id != 0) {
337 	parms.rc = 0x04;
338     } else {
339 	ResetOiaApiInhibit(&OperatorInformationArea);
340 	parms.rc = 0;
341     }
342     parms.function_id = 0x62;
343 
344     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
345 }
346 
347 /*
348  * Copy Services.
349  */
350 
351 static void
352 copy_string(regs, sregs)
353 union REGS *regs;
354 struct SREGS *sregs;
355 {
356     CopyStringParms parms;
357     BufferDescriptor *target, *source;
358 
359     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
360 
361     if ((parms.rc != 0) || (parms.function_id !=0)) {
362 	parms.rc = 0x0c;
363     }
364     /* XXX do something! */
365     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
366 }
367 /*
368  * Operator Information Area Services.
369  */
370 
371 static void
372 read_oia_group(regs, sregs)
373 union REGS *regs;
374 struct SREGS *sregs;
375 {
376     ReadOiaGroupParms parms;
377 
378     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
379 
380     if ((parms.rc != 0) || (parms.function_id != 0)) {
381 	parms.rc = 0x0c;
382     } else if (parms.session_id != 23) {
383 	parms.rc = 0x02;
384     } else {
385 	int group = parms.oia_group_number;
386 	char *from;
387 	int size;
388 
389 	if ((group != API_OIA_ALL_GROUPS) &&
390 		((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
391 	} else {
392 	    if (group == API_OIA_ALL_GROUPS) {
393 		size = API_OIA_BYTES_ALL_GROUPS;
394 		from = (char *)&OperatorInformationArea;
395 	    } else if (group == API_OIA_INPUT_INHIBITED) {
396 		size = sizeof OperatorInformationArea.input_inhibited;
397 		from = (char *)&OperatorInformationArea.input_inhibited[0];
398 	    } else {
399 		size = 1;
400 		from = ((char *)&OperatorInformationArea)+group;
401 	    }
402 	    movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
403 			from, size);
404 	}
405     }
406     parms.function_id = 0x6d;
407     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
408 }
409 
410 static void
411 unknown_op(regs, sregs)
412 union REGS *regs;
413 struct SREGS *sregs;
414 {
415     regs->h.ch = 0x12;
416     regs->h.cl = 0x05;
417 }
418 
419 
420 handle_api(regs, sregs)
421 union REGS *regs;
422 struct SREGS *sregs;
423 {
424     if (regs->h.ah == NAME_RESOLUTION) {
425 	name_resolution(regs, sregs);
426     } else if (regs->h.ah != 0x09) {
427 	regs->h.ch = 0x12;
428 	regs->h.cl = 0x0f;		/* XXX Invalid environmental access */
429     } else if (regs->x.bx != 0x8020) {
430 	regs->h.ch = 0x12;
431 	regs->h.cl = 0x08;		/* XXX Invalid wait specified */
432     } else if (regs->h.ch != 0) {
433 	regs->x.cx = 0x1206;		/* XXX Invalid priority */
434     } else {
435 	switch (regs->x.dx) {
436 	case GATE_SESSMGR:
437 	    switch (regs->h.al) {
438 	    case QUERY_SESSION_ID:
439 		if (regs->h.cl != 0) {
440 		    regs->x.cx = 0x1206;
441 		} else {
442 		    regs->x.cx = 0x1200;
443 		    query_session_id(regs, sregs);
444 		}
445 		break;
446 	    case QUERY_SESSION_PARAMETERS:
447 		if (regs->h.cl != 0) {
448 		    regs->x.cx = 0x1206;
449 		} else {
450 		    regs->x.cx = 0x1200;
451 		    query_session_parameters(regs, sregs);
452 		}
453 		break;
454 	    case QUERY_SESSION_CURSOR:
455 		if (regs->h.cl != 0xff) {
456 		    regs->x.cx = 0x1206;
457 		} else {
458 		    regs->x.cx = 0x1200;
459 		    query_session_cursor(regs, sregs);
460 		}
461 		break;
462 	    default:
463 		unknown_op(regs, sregs);
464 		break;
465 	    }
466 	    break;
467 	case GATE_KEYBOARD:
468 	    if (regs->h.cl != 00) {
469 		regs->x.cx = 0x1206;
470 	    } else {
471 		regs->x.cx = 0x1200;
472 		switch (regs->h.al) {
473 		case CONNECT_TO_KEYBOARD:
474 		    connect_to_keyboard(regs, sregs);
475 		    break;
476 		case DISABLE_INPUT:
477 		    disable_input(regs, sregs);
478 		    break;
479 		case WRITE_KEYSTROKE:
480 		    write_keystroke(regs, sregs);
481 		    break;
482 		case ENABLE_INPUT:
483 		    enable_input(regs, sregs);
484 		    break;
485 		case DISCONNECT_FROM_KEYBOARD:
486 		    disconnect_from_keyboard(regs, sregs);
487 		    break;
488 		default:
489 		    unknown_op(regs, sregs);
490 		    break;
491 		}
492 	    }
493 	    break;
494 	case GATE_COPY:
495 	    if (regs->h.cl != 0xff) {
496 		regs->x.cx = 0x1206;
497 	    } else {
498 		regs->x.cx = 0x1200;
499 		switch (regs->h.al) {
500 		case COPY_STRING:
501 		    copy_string(regs, sregs);
502 		    break;
503 		default:
504 		    unknown_op(regs, sregs);
505 		    break;
506 		}
507 	    }
508 	    break;
509 	case GATE_OIAM:
510 	    if (regs->h.cl != 0xff) {
511 		regs->x.cx = 0x1206;
512 	    } else {
513 		regs->x.cx = 0x1200;
514 		switch (regs->h.al) {
515 		case READ_OIA_GROUP:
516 		    read_oia_group(regs, sregs);
517 		    break;
518 		default:
519 		    unknown_op(regs, sregs);
520 		    break;
521 		}
522 	    }
523 	    break;
524 	default:
525 	    regs->h.ch = 0x12;
526 	    regs->h.cl = 0x34;		/* Invalid GATE entry */
527 	    break;
528 	}
529     }
530 }
531