xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 31507)
131158Sminshall /*
231158Sminshall  * This file implements the API used in the PC version.
331158Sminshall  */
431158Sminshall 
531158Sminshall #include <stdio.h>
631158Sminshall 
731158Sminshall #include "api.h"
831183Sminshall #include "../general/general.h"
931158Sminshall 
1031226Sminshall #include "../ascii/disp_asc.h"
1131226Sminshall 
1231168Sminshall #include "../ctlr/screen.h"
1331193Sminshall #include "../ctlr/oia.h"
1431193Sminshall 
1531183Sminshall #include "../general/globals.h"
1631158Sminshall 
1731158Sminshall /*
1831193Sminshall  * General utility routines.
1931193Sminshall  */
2031193Sminshall 
2131193Sminshall #if	defined(MSDOS)
2231193Sminshall 
2331211Sminshall #if	defined(LINT_ARGS)
2431211Sminshall static void movetous(char *, int, int, int);
2531211Sminshall static void movetothem(int, int, char *, int);
2631211Sminshall #endif	/* defined(LINT_ARGS) */
2731211Sminshall 
28*31507Sminshall #define	access_api(foo,length,copyin)	(foo)
29*31507Sminshall #define	unaccess_api(foo,goo,length,copyout)
3031226Sminshall 
3131193Sminshall static void
3231193Sminshall movetous(parms, es, di, length)
3331193Sminshall char *parms;
3431211Sminshall int es, di, length;
3531193Sminshall {
3631211Sminshall     char far *farparms = parms;
3731193Sminshall 
3831211Sminshall     movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length);
3931193Sminshall }
4031193Sminshall 
4131193Sminshall static void
4231211Sminshall movetothem(es, di, parms, length)
4331211Sminshall int es, di;
4431211Sminshall char *parms;
4531211Sminshall int length;
4631193Sminshall {
4731211Sminshall     char far *farparms = parms;
4831193Sminshall 
4931211Sminshall     movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length);
5031193Sminshall }
5131193Sminshall #endif	/* defined(MSDOS) */
5231193Sminshall 
5331226Sminshall #if	defined(unix)
5431470Sminshall extern char *access_api(), *unaccess_api();
5531226Sminshall #endif	/* defined(unix) */
5631226Sminshall 
5731470Sminshall 
5831193Sminshall /*
5931158Sminshall  * Supervisor Services.
6031158Sminshall  */
6131158Sminshall 
6231158Sminshall static void
6331193Sminshall name_resolution(regs, sregs)
6431158Sminshall union REGS *regs;
6531158Sminshall struct SREGS *sregs;
6631158Sminshall {
6731167Sminshall     NameResolveParms parms;
6831161Sminshall 
6931167Sminshall     movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
7031161Sminshall 
7131161Sminshall     regs->h.cl = 0;
7231193Sminshall     if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
7331161Sminshall 	regs->x.dx = GATE_SESSMGR;
7431193Sminshall     } else if (memcmp((char *)&parms, NAME_KEYBOARD,
7531193Sminshall 					sizeof parms.gate_name) == 0) {
7631161Sminshall 	regs->x.dx = GATE_KEYBOARD;
7731193Sminshall     } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
7831161Sminshall 	regs->x.dx = GATE_COPY;
7931193Sminshall     } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
8031161Sminshall 	regs->x.dx = GATE_OIAM;
8131161Sminshall     } else {
8231161Sminshall 	regs->h.cl = 0x2e;	/* Name not found */
8331161Sminshall     }
8431161Sminshall     regs->h.ch = 0x12;
8531161Sminshall     regs->h.bh = 7;
8631158Sminshall }
8731158Sminshall 
8831158Sminshall /*
8931158Sminshall  * Session Information Services.
9031158Sminshall  */
9131158Sminshall 
9231158Sminshall static void
9331158Sminshall query_session_id(regs, sregs)
9431158Sminshall union REGS *regs;
9531158Sminshall struct SREGS *sregs;
9631158Sminshall {
9731167Sminshall     QuerySessionIdParms parms;
9831161Sminshall 
9931167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
10031161Sminshall 
10131211Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
10231211Sminshall 	parms.rc = 0x0c;
10331211Sminshall     } else if (parms.option_code != 0x01) {
10431211Sminshall 	parms.rc = 0x0d;	/* Invalid option code */
10531167Sminshall     } else if (parms.data_code != 0x45) {
10631211Sminshall 	parms.rc = 0x0b;
10731161Sminshall     } else {
10831168Sminshall 	NameArray list;
10931167Sminshall 	NameArrayElement element;
11031167Sminshall 
11131167Sminshall 	movetous((char *)&list, FP_SEG(parms.name_array),
11231193Sminshall 			    FP_OFF(parms.name_array), sizeof list);
11331168Sminshall 	if ((list.length < 14) || (list.length > 170)) {
11431167Sminshall 	    parms.rc = 0x12;
11531161Sminshall 	} else {
11631167Sminshall 	    list.number_matching_session = 1;
11731167Sminshall 	    list.name_array_element.short_name = parms.data_code;
11831167Sminshall 	    list.name_array_element.type = TYPE_DFT;
11931167Sminshall 	    list.name_array_element.session_id = 23;
12031167Sminshall 	    memcpy(list.name_array_element.long_name, "ONLYSESS",
12131167Sminshall 			    sizeof list.name_array_element.long_name);
12231167Sminshall 	    movetothem(FP_SEG(parms.name_array),
12331193Sminshall 		FP_OFF(parms.name_array), (char *)&list, sizeof list);
12431167Sminshall 	    parms.rc = 0;
12531161Sminshall 	}
12631161Sminshall     }
12731211Sminshall     parms.function_id = 0x6b;
12831167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
12931158Sminshall }
13031158Sminshall 
13131158Sminshall static void
13231158Sminshall query_session_parameters(regs, sregs)
13331158Sminshall union REGS *regs;
13431158Sminshall struct SREGS *sregs;
13531158Sminshall {
13631167Sminshall     QuerySessionParametersParms parms;
13731167Sminshall 
13831167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
13931167Sminshall 
14031168Sminshall     if ((parms.rc !=0) || (parms.function_id != 0)) {
14131211Sminshall 	parms.rc = 0x0c;
14231211Sminshall     } else if (parms.session_id != 23) {
14331211Sminshall 	parms.rc = 0x02;
14431167Sminshall     } else {
14531211Sminshall 	parms.rc = 0;
14631167Sminshall 	parms.session_type = TYPE_DFT;
14731167Sminshall 	parms.session_characteristics = 0;	/* Neither EAB nor PSS */
14831167Sminshall 	parms.rows = MaxNumberLines;
14931167Sminshall 	parms.columns = MaxNumberColumns;
15031167Sminshall 	parms.presentation_space = 0;
15131167Sminshall     }
15231211Sminshall     parms.function_id = 0x6b;
15331168Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
15431158Sminshall }
15531158Sminshall 
15631158Sminshall static void
15731158Sminshall query_session_cursor(regs, sregs)
15831158Sminshall union REGS *regs;
15931158Sminshall struct SREGS *sregs;
16031158Sminshall {
16131167Sminshall     QuerySessionCursorParms parms;
16231167Sminshall 
16331167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
16431167Sminshall 
16531167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
16631167Sminshall 	parms.rc = 0x0c;
16731167Sminshall     } else if (parms.session_id != 23) {
16831167Sminshall 	parms.rc = 0x02;
16931167Sminshall     } else {
17031167Sminshall 	parms.rc = 0;
17131167Sminshall 	parms.cursor_type = CURSOR_BLINKING;	/* XXX what is inhibited? */
17231167Sminshall 	parms.row_address = ScreenLine(CursorAddress);
17331167Sminshall 	parms.column_address = ScreenLineOffset(CursorAddress);
17431167Sminshall     }
17531167Sminshall 
17631211Sminshall     parms.function_id = 0x6b;
17731211Sminshall     movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
17831158Sminshall }
17931158Sminshall 
18031158Sminshall /*
18131158Sminshall  * Keyboard Services.
18231158Sminshall  */
18331158Sminshall 
18431158Sminshall 
18531158Sminshall static void
18631158Sminshall connect_to_keyboard(regs, sregs)
18731158Sminshall union REGS *regs;
18831158Sminshall struct SREGS *sregs;
18931158Sminshall {
19031167Sminshall     ConnectToKeyboardParms parms;
19131167Sminshall 
19231183Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
19331167Sminshall 
19431167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
19531167Sminshall 	parms.rc = 0x0c;
19631167Sminshall     } else if (parms.session_id != 23) {
19731167Sminshall 	parms.rc = 0x02;
19831167Sminshall     } else if (parms.intercept_options != 0) {
19931167Sminshall 	parms.rc = 0x01;
20031167Sminshall     } else {
20131167Sminshall 	parms.rc = 0;
20231167Sminshall 	parms.first_connection_identifier = 0;
20331167Sminshall     }
20431167Sminshall     parms.function_id = 0x62;
20531167Sminshall 
20631167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
20731158Sminshall }
20831158Sminshall 
20931158Sminshall static void
21031167Sminshall disconnect_from_keyboard(regs, sregs)
21131158Sminshall union REGS *regs;
21231158Sminshall struct SREGS *sregs;
21331158Sminshall {
21431167Sminshall     DisconnectFromKeyboardParms parms;
21531167Sminshall 
21631167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
21731167Sminshall 
21831167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
21931167Sminshall 	parms.rc = 0x0c;
22031167Sminshall     } else if (parms.session_id != 23) {
22131167Sminshall 	parms.rc = 0x02;
22231167Sminshall     } else if (parms.connectors_task_id != 0) {
22331167Sminshall 	parms.rc = 04;			/* XXX */
22431167Sminshall     } else {
22531167Sminshall 	parms.rc = 0;
22631167Sminshall     }
22731167Sminshall     parms.function_id = 0x62;
22831167Sminshall 
22931167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
23031158Sminshall }
23131158Sminshall 
23231158Sminshall static void
23331158Sminshall write_keystroke(regs, sregs)
23431158Sminshall union REGS *regs;
23531158Sminshall struct SREGS *sregs;
23631158Sminshall {
23731198Sminshall     WriteKeystrokeParms parms;
23831198Sminshall 
23931198Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
24031198Sminshall 
24131198Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
24231198Sminshall 	parms.rc = 0x0c;
24331198Sminshall     } else if (parms.session_id != 23) {
24431198Sminshall 	parms.rc = 0x02;
24531198Sminshall     } else if (parms.connectors_task_id != 0) {
24631198Sminshall 	parms.rc = 0x04;
24731198Sminshall     } else {
24831198Sminshall 	parms.number_of_keys_sent = 0;
24931198Sminshall 	parms.rc = 0;
25031198Sminshall 	if (parms.options == OPTION_SINGLE_KEYSTROKE) {
25131198Sminshall 	    KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
25231198Sminshall 
25331198Sminshall 	    if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
25431198Sminshall 		parms.rc = 0x10;		/* XXX needs 0x12 too! */
25531198Sminshall 	    }
25631198Sminshall 	    parms.number_of_keys_sent++;
25731198Sminshall 	} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
25831198Sminshall 	    KeystrokeList
25931198Sminshall 		list,
26031198Sminshall 		far *atlist = parms.keystroke_specifier.keystroke_list;
26131198Sminshall 	    KeystrokeEntry
26231198Sminshall 		entry[10],		/* 10 at a time */
26331198Sminshall 		*ourentry,
26431198Sminshall 		far *theirentry;
26531198Sminshall 	    int
26631198Sminshall 		todo;
26731198Sminshall 
26831198Sminshall 	    movetous((char *)&list, FP_SEG(atlist),
26931198Sminshall 				FP_OFF(atlist), sizeof *atlist);
27031198Sminshall 	    todo = list.length/2;
27131198Sminshall 	    ourentry = entry+(highestof(entry)+1);
27231198Sminshall 
27331198Sminshall 	    while (todo) {
27431198Sminshall 		if (ourentry > &entry[highestof(entry)]) {
27531198Sminshall 		    int thistime;
27631198Sminshall 
27731198Sminshall 		    thistime = todo;
27831198Sminshall 		    if (thistime > numberof(entry)) {
27931198Sminshall 			thistime = numberof(entry);
28031198Sminshall 		    }
28131198Sminshall 		    movetous((char *)entry, FP_SEG(theirentry),
28231198Sminshall 			    FP_OFF(theirentry), thistime*sizeof *theirentry);
28331198Sminshall 		    theirentry += thistime;
28431198Sminshall 		    ourentry = entry;
28531198Sminshall 		}
28631198Sminshall 		if (AcceptKeystroke(ourentry->scancode,
28731198Sminshall 						ourentry->shift_state) == 0) {
28831198Sminshall 		    parms.rc = 0x10;		/* XXX needs 0x12 too! */
28931198Sminshall 		    break;
29031198Sminshall 		}
29131198Sminshall 		parms.number_of_keys_sent++;
29231198Sminshall 		ourentry++;
29331198Sminshall 		todo--;
29431198Sminshall 	    }
29531198Sminshall 	} else {
29631198Sminshall 	    parms.rc = 0x01;
29731198Sminshall 	}
29831198Sminshall     }
29931198Sminshall     parms.function_id = 0x62;
30031198Sminshall 
30131198Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
30231167Sminshall /* XXX */
30331158Sminshall }
30431158Sminshall 
30531167Sminshall 
30631158Sminshall static void
30731167Sminshall disable_input(regs, sregs)
30831167Sminshall union REGS *regs;
30931167Sminshall struct SREGS *sregs;
31031167Sminshall {
31131167Sminshall     DisableInputParms parms;
31231167Sminshall 
31331167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
31431167Sminshall 
31531167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
31631167Sminshall 	parms.rc = 0x0c;
31731167Sminshall     } else if (parms.session_id != 23) {
31831167Sminshall 	parms.rc = 0x02;
31931167Sminshall     } else if (parms.connectors_task_id != 0) {
32031167Sminshall 	parms.rc = 0x04;
32131167Sminshall     } else {
32231211Sminshall 	SetOiaApiInhibit(&OperatorInformationArea);
32331167Sminshall 	parms.rc = 0;
32431167Sminshall     }
32531167Sminshall     parms.function_id = 0x62;
32631167Sminshall 
32731167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
32831167Sminshall }
32931167Sminshall 
33031167Sminshall static void
33131158Sminshall enable_input(regs, sregs)
33231158Sminshall union REGS *regs;
33331158Sminshall struct SREGS *sregs;
33431158Sminshall {
33531167Sminshall     EnableInputParms parms;
33631167Sminshall 
33731167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
33831167Sminshall 
33931167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
34031167Sminshall 	parms.rc = 0x0c;
34131167Sminshall     } else if (parms.session_id != 23) {
34231167Sminshall 	parms.rc = 0x02;
34331167Sminshall     } else if (parms.connectors_task_id != 0) {
34431167Sminshall 	parms.rc = 0x04;
34531167Sminshall     } else {
34631211Sminshall 	ResetOiaApiInhibit(&OperatorInformationArea);
34731167Sminshall 	parms.rc = 0;
34831167Sminshall     }
34931167Sminshall     parms.function_id = 0x62;
35031167Sminshall 
35131167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
35231158Sminshall }
35331158Sminshall 
35431158Sminshall /*
35531158Sminshall  * Copy Services.
35631158Sminshall  */
35731158Sminshall 
358*31507Sminshall static
359*31507Sminshall copy_subroutine(target, source, parms, what_is_user, length)
36031226Sminshall BufferDescriptor *target, *source;
36131226Sminshall CopyStringParms *parms;
36231226Sminshall int what_is_user;
36331226Sminshall #define	USER_IS_TARGET	0
36431226Sminshall #define	USER_IS_SOURCE	1
36531226Sminshall {
36631226Sminshall #define	TARGET_NO_EAB		1
36731226Sminshall #define	SOURCE_NO_EAB		2
36831226Sminshall #define	TARGET_PC		4
36931226Sminshall #define	SOURCE_PC		8
37031226Sminshall #define	NO_FIELD_ATTRIBUTES	16
37131226Sminshall     int needtodo = 0;
37231226Sminshall     int access_length;
37331226Sminshall     char far *input;
37431226Sminshall     char far *output;
37531226Sminshall     char far *access_pointer;
37631226Sminshall 
37731226Sminshall     if ((target->characteristics^source->characteristics)
37831226Sminshall 		    &CHARACTERISTIC_EAB) {
37931226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
38031226Sminshall 	    needtodo |= TARGET_NO_EAB;	/* Need to bump for EAB in target */
38131226Sminshall 	} else {
38231226Sminshall 	    needtodo |= SOURCE_NO_EAB;	/* Need to bump for EAB in source */
38331226Sminshall 	}
38431226Sminshall     }
38531226Sminshall     if (target->session_type != source->session_type) {
38631226Sminshall 	if (target->session_type == TYPE_PC) {
38731226Sminshall 	    needtodo |= TARGET_PC;	/* scan codes to PC */
38831226Sminshall 	} else {
38931226Sminshall 	    needtodo |= SOURCE_PC;	/* PC to scan codes */
39031226Sminshall 	}
39131226Sminshall     }
39231226Sminshall     if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
39331226Sminshall 	needtodo |= NO_FIELD_ATTRIBUTES;
39431226Sminshall     }
395*31507Sminshall     access_length = length;
39631226Sminshall     if (what_is_user == USER_IS_TARGET) {
39731226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
39831226Sminshall 	    access_length *= 2;
39931226Sminshall 	}
40031226Sminshall 	input = (char far *) &Host[source->begin];
40131226Sminshall 	access_pointer = target->buffer;
402*31507Sminshall 	output = access_api(target->buffer, access_length, 0);
40331226Sminshall     } else {
40431226Sminshall 	if (source->characteristics&CHARACTERISTIC_EAB) {
40531226Sminshall 	    access_length *= 2;
40631226Sminshall 	}
40731226Sminshall 	access_pointer = source->buffer;
408*31507Sminshall 	input = access_api(source->buffer, access_length, 1);
40931226Sminshall 	output = (char far *) &Host[target->begin];
41031226Sminshall     }
41131226Sminshall     while (length--) {
41231226Sminshall 	if (needtodo&TARGET_PC) {
41331226Sminshall 	    *output++ = disp_asc[*input++];
41431226Sminshall 	} else if (needtodo&SOURCE_PC) {
41531226Sminshall 	    *output++ = asc_disp[*input++];
41631226Sminshall 	} else {
41731226Sminshall 	    *output++ = *input++;
41831226Sminshall 	}
41931226Sminshall 	if (needtodo&TARGET_NO_EAB) {
42031226Sminshall 	    *input++;
42131226Sminshall 	} else if (needtodo&SOURCE_NO_EAB) {
42231226Sminshall 	    *output++ = 0;		/* Should figure out good EAB? */
42331226Sminshall 	}
42431226Sminshall     }
42531226Sminshall     if (what_is_user == USER_IS_TARGET) {
426*31507Sminshall 	unaccess_api(target->buffer, access_pointer, access_length, 1);
42731226Sminshall     } else {
428*31507Sminshall 	unaccess_api(source->buffer, access_pointer, access_length, 0);
42931226Sminshall     }
43031226Sminshall }
43131226Sminshall 
43231226Sminshall 
43331158Sminshall static void
43431167Sminshall copy_string(regs, sregs)
43531158Sminshall union REGS *regs;
43631158Sminshall struct SREGS *sregs;
43731158Sminshall {
43831167Sminshall     CopyStringParms parms;
43931226Sminshall     BufferDescriptor *target = &parms.target, *source = &parms.source;
44031226Sminshall     int length;
44131167Sminshall 
44231167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
44331167Sminshall 
444*31507Sminshall     length = 1+parms.source_end-source->begin;
44531167Sminshall     if ((parms.rc != 0) || (parms.function_id !=0)) {
44631167Sminshall 	parms.rc = 0x0c;
44731226Sminshall     } else if (target->session_id == 0) {	/* Target is buffer */
44831226Sminshall 	if (source->session_id != 23) {		/* A no-no */
44931226Sminshall 	    parms.rc = 0x2;
45031226Sminshall 	} else {
451*31507Sminshall 	    if ((source->begin < 0) || (source->begin > highestof(Host))) {
452*31507Sminshall 		parms.rc = 0x06;		/* invalid source definition */
453*31507Sminshall 	    } else {
454*31507Sminshall 		if ((source->begin+length) > highestof(Host)) {
455*31507Sminshall 		    length = highestof(Host)-source->begin;
456*31507Sminshall 		    parms.rc = 0x0f;	/* Truncate */
457*31507Sminshall 		}
458*31507Sminshall 	        if ((source->characteristics == target->characteristics) &&
45931226Sminshall 		    (source->session_type == target->session_type)) {
460*31507Sminshall 		    if (source->characteristics&CHARACTERISTIC_EAB) {
461*31507Sminshall 			length *= 2;
462*31507Sminshall 		    }
463*31507Sminshall 		    movetothem( (int) FP_SEG(target->buffer),
464*31507Sminshall 			    (int) FP_OFF(target->buffer),
465*31507Sminshall 			    (char *)&Host[source->begin], length);
466*31507Sminshall 		} else {
467*31507Sminshall 		    copy_subroutine(target, source, &parms,
468*31507Sminshall 							USER_IS_TARGET, length);
46931226Sminshall 		}
47031226Sminshall 	    }
47131226Sminshall 	}
47231226Sminshall     } else if (source->session_id != 0) {
47331226Sminshall 	    parms.rc = 0xd;
47431226Sminshall     } else {
475*31507Sminshall 	if ((target->begin < 0) || (source->begin > highestof(Host))) {
476*31507Sminshall 	    parms.rc = 0x07;		/* invalid source definition */
477*31507Sminshall 	} else {
478*31507Sminshall 	    if ((source->begin+length) > highestof(Host)) {
479*31507Sminshall 		length = highestof(Host)-source->begin;
480*31507Sminshall 		parms.rc = 0x0f;	/* Truncate */
48131226Sminshall 	    }
482*31507Sminshall 	    if ((source->characteristics == target->characteristics) &&
483*31507Sminshall 		    (source->session_type == target->session_type)) {
484*31507Sminshall 		if (source->characteristics&CHARACTERISTIC_EAB) {
485*31507Sminshall 		    length *= 2;
486*31507Sminshall 		}
487*31507Sminshall 		movetous((char *)&Host[target->begin],
488*31507Sminshall 			    (int) FP_SEG(source->buffer),
489*31507Sminshall 			    (int) FP_OFF(source->buffer), length);
490*31507Sminshall 	    } else {
491*31507Sminshall 		copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
492*31507Sminshall 	    }
49331226Sminshall 	}
49431167Sminshall     }
49531183Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
49631158Sminshall }
49731158Sminshall /*
49831158Sminshall  * Operator Information Area Services.
49931158Sminshall  */
50031158Sminshall 
50131158Sminshall static void
50231158Sminshall read_oia_group(regs, sregs)
50331158Sminshall union REGS *regs;
50431158Sminshall struct SREGS *sregs;
50531158Sminshall {
50631167Sminshall     ReadOiaGroupParms parms;
50731167Sminshall 
50831167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
50931167Sminshall 
51031167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
51131167Sminshall 	parms.rc = 0x0c;
51231167Sminshall     } else if (parms.session_id != 23) {
51331167Sminshall 	parms.rc = 0x02;
51431167Sminshall     } else {
51531167Sminshall 	int group = parms.oia_group_number;
51631193Sminshall 	char *from;
51731193Sminshall 	int size;
51831167Sminshall 
51931211Sminshall 	if ((group != API_OIA_ALL_GROUPS) &&
52031211Sminshall 		((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
52131193Sminshall 	} else {
52231193Sminshall 	    if (group == API_OIA_ALL_GROUPS) {
52331193Sminshall 		size = API_OIA_BYTES_ALL_GROUPS;
52431193Sminshall 		from = (char *)&OperatorInformationArea;
52531193Sminshall 	    } else if (group == API_OIA_INPUT_INHIBITED) {
52631193Sminshall 		size = sizeof OperatorInformationArea.input_inhibited;
52731193Sminshall 		from = (char *)&OperatorInformationArea.input_inhibited[0];
52831193Sminshall 	    } else {
52931193Sminshall 		size = 1;
53031193Sminshall 		from = ((char *)&OperatorInformationArea)+group;
53131193Sminshall 	    }
53231193Sminshall 	    movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
53331193Sminshall 			from, size);
53431168Sminshall 	}
53531167Sminshall     }
53631168Sminshall     parms.function_id = 0x6d;
53731167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
53831158Sminshall }
53931158Sminshall 
54031158Sminshall static void
54131158Sminshall unknown_op(regs, sregs)
54231158Sminshall union REGS *regs;
54331158Sminshall struct SREGS *sregs;
54431158Sminshall {
54531158Sminshall     regs->h.ch = 0x12;
54631158Sminshall     regs->h.cl = 0x05;
54731158Sminshall }
54831158Sminshall 
54931158Sminshall 
55031158Sminshall handle_api(regs, sregs)
55131158Sminshall union REGS *regs;
55231158Sminshall struct SREGS *sregs;
55331158Sminshall {
55431158Sminshall     if (regs->h.ah == NAME_RESOLUTION) {
55531158Sminshall 	name_resolution(regs, sregs);
55631168Sminshall     } else if (regs->h.ah != 0x09) {
55731168Sminshall 	regs->h.ch = 0x12;
55831168Sminshall 	regs->h.cl = 0x0f;		/* XXX Invalid environmental access */
55931168Sminshall     } else if (regs->x.bx != 0x8020) {
56031168Sminshall 	regs->h.ch = 0x12;
56131168Sminshall 	regs->h.cl = 0x08;		/* XXX Invalid wait specified */
56231168Sminshall     } else if (regs->h.ch != 0) {
56331211Sminshall 	regs->x.cx = 0x1206;		/* XXX Invalid priority */
56431158Sminshall     } else {
56531158Sminshall 	switch (regs->x.dx) {
56631158Sminshall 	case GATE_SESSMGR:
56731158Sminshall 	    switch (regs->h.al) {
56831158Sminshall 	    case QUERY_SESSION_ID:
56931168Sminshall 		if (regs->h.cl != 0) {
57031211Sminshall 		    regs->x.cx = 0x1206;
57131168Sminshall 		} else {
57231211Sminshall 		    regs->x.cx = 0x1200;
57331168Sminshall 		    query_session_id(regs, sregs);
57431168Sminshall 		}
57531158Sminshall 		break;
57631211Sminshall 	    case QUERY_SESSION_PARAMETERS:
57731168Sminshall 		if (regs->h.cl != 0) {
57831211Sminshall 		    regs->x.cx = 0x1206;
57931168Sminshall 		} else {
58031211Sminshall 		    regs->x.cx = 0x1200;
58131193Sminshall 		    query_session_parameters(regs, sregs);
58231168Sminshall 		}
58331158Sminshall 		break;
58431158Sminshall 	    case QUERY_SESSION_CURSOR:
58531168Sminshall 		if (regs->h.cl != 0xff) {
58631211Sminshall 		    regs->x.cx = 0x1206;
58731168Sminshall 		} else {
58831211Sminshall 		    regs->x.cx = 0x1200;
58931168Sminshall 		    query_session_cursor(regs, sregs);
59031168Sminshall 		}
59131158Sminshall 		break;
59231158Sminshall 	    default:
59331158Sminshall 		unknown_op(regs, sregs);
59431158Sminshall 		break;
59531158Sminshall 	    }
59631158Sminshall 	    break;
59731158Sminshall 	case GATE_KEYBOARD:
59831168Sminshall 	    if (regs->h.cl != 00) {
59931211Sminshall 		regs->x.cx = 0x1206;
60031168Sminshall 	    } else {
60131211Sminshall 		regs->x.cx = 0x1200;
60231168Sminshall 		switch (regs->h.al) {
60331168Sminshall 		case CONNECT_TO_KEYBOARD:
60431168Sminshall 		    connect_to_keyboard(regs, sregs);
60531168Sminshall 		    break;
60631168Sminshall 		case DISABLE_INPUT:
60731168Sminshall 		    disable_input(regs, sregs);
60831168Sminshall 		    break;
60931168Sminshall 		case WRITE_KEYSTROKE:
61031168Sminshall 		    write_keystroke(regs, sregs);
61131168Sminshall 		    break;
61231168Sminshall 		case ENABLE_INPUT:
61331168Sminshall 		    enable_input(regs, sregs);
61431168Sminshall 		    break;
61531168Sminshall 		case DISCONNECT_FROM_KEYBOARD:
61631168Sminshall 		    disconnect_from_keyboard(regs, sregs);
61731168Sminshall 		    break;
61831168Sminshall 		default:
61931168Sminshall 		    unknown_op(regs, sregs);
62031168Sminshall 		    break;
62131168Sminshall 		}
62231158Sminshall 	    }
62331158Sminshall 	    break;
62431158Sminshall 	case GATE_COPY:
62531168Sminshall 	    if (regs->h.cl != 0xff) {
62631211Sminshall 		regs->x.cx = 0x1206;
62731168Sminshall 	    } else {
62831211Sminshall 		regs->x.cx = 0x1200;
62931168Sminshall 		switch (regs->h.al) {
63031168Sminshall 		case COPY_STRING:
63131168Sminshall 		    copy_string(regs, sregs);
63231168Sminshall 		    break;
63331168Sminshall 		default:
63431168Sminshall 		    unknown_op(regs, sregs);
63531168Sminshall 		    break;
63631168Sminshall 		}
63731158Sminshall 	    }
63831158Sminshall 	    break;
63931158Sminshall 	case GATE_OIAM:
64031168Sminshall 	    if (regs->h.cl != 0xff) {
64131211Sminshall 		regs->x.cx = 0x1206;
64231168Sminshall 	    } else {
64331211Sminshall 		regs->x.cx = 0x1200;
64431168Sminshall 		switch (regs->h.al) {
64531168Sminshall 		case READ_OIA_GROUP:
64631168Sminshall 		    read_oia_group(regs, sregs);
64731168Sminshall 		    break;
64831168Sminshall 		default:
64931168Sminshall 		    unknown_op(regs, sregs);
65031168Sminshall 		    break;
65131168Sminshall 		}
65231158Sminshall 	    }
65331158Sminshall 	    break;
65431158Sminshall 	default:
65531168Sminshall 	    regs->h.ch = 0x12;
65631168Sminshall 	    regs->h.cl = 0x34;		/* Invalid GATE entry */
65731158Sminshall 	    break;
65831158Sminshall 	}
65931158Sminshall     }
66031158Sminshall }
661