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