xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 33816)
131158Sminshall /*
2*33816Sbostic  * Copyright (c) 1988 Regents of the University of California.
3*33816Sbostic  * All rights reserved.
431892Sminshall  *
5*33816Sbostic  * Redistribution and use in source and binary forms are permitted
6*33816Sbostic  * provided that this notice is preserved and that due credit is given
7*33816Sbostic  * to the University of California at Berkeley. The name of the University
8*33816Sbostic  * may not be used to endorse or promote products derived from this
9*33816Sbostic  * software without specific prior written permission. This software
10*33816Sbostic  * is provided ``as is'' without express or implied warranty.
1131892Sminshall  */
1231892Sminshall 
1331892Sminshall #ifndef lint
14*33816Sbostic static char sccsid[] = "@(#)api.c	3.2 (Berkeley) 03/28/88";
15*33816Sbostic #endif /* not lint */
1631892Sminshall 
1731892Sminshall /*
1831158Sminshall  * This file implements the API used in the PC version.
1931158Sminshall  */
2031158Sminshall 
2131158Sminshall #include <stdio.h>
2231158Sminshall 
2331158Sminshall #include "api.h"
2431183Sminshall #include "../general/general.h"
2531158Sminshall 
2631871Sminshall #include "../api/disp_asc.h"
2731226Sminshall 
2831871Sminshall #include "screen.h"
2931871Sminshall #include "oia.h"
3031193Sminshall 
3131183Sminshall #include "../general/globals.h"
3231158Sminshall 
3331158Sminshall /*
3431193Sminshall  * General utility routines.
3531193Sminshall  */
3631193Sminshall 
3731193Sminshall #if	defined(MSDOS)
3831193Sminshall 
3931211Sminshall #if	defined(LINT_ARGS)
4031211Sminshall static void movetous(char *, int, int, int);
4131211Sminshall static void movetothem(int, int, char *, int);
4231211Sminshall #endif	/* defined(LINT_ARGS) */
4331211Sminshall 
4431507Sminshall #define	access_api(foo,length,copyin)	(foo)
4531507Sminshall #define	unaccess_api(foo,goo,length,copyout)
4631226Sminshall 
4731193Sminshall static void
4831193Sminshall movetous(parms, es, di, length)
4931193Sminshall char *parms;
5031211Sminshall int es, di, length;
5131193Sminshall {
5231211Sminshall     char far *farparms = parms;
5331193Sminshall 
5431211Sminshall     movedata(es, di, (int) FP_SEG(farparms), (int) FP_OFF(farparms), length);
5531193Sminshall }
5631193Sminshall 
5731193Sminshall static void
5831211Sminshall movetothem(es, di, parms, length)
5931211Sminshall int es, di;
6031211Sminshall char *parms;
6131211Sminshall int length;
6231193Sminshall {
6331211Sminshall     char far *farparms = parms;
6431193Sminshall 
6531211Sminshall     movedata((int) FP_SEG(farparms), (int) FP_OFF(farparms), es, di, length);
6631193Sminshall }
6731193Sminshall #endif	/* defined(MSDOS) */
6831193Sminshall 
6931226Sminshall #if	defined(unix)
7031470Sminshall extern char *access_api(), *unaccess_api();
7131226Sminshall #endif	/* defined(unix) */
7231226Sminshall 
7331470Sminshall 
7431193Sminshall /*
7531158Sminshall  * Supervisor Services.
7631158Sminshall  */
7731158Sminshall 
7831158Sminshall static void
7931193Sminshall name_resolution(regs, sregs)
8031158Sminshall union REGS *regs;
8131158Sminshall struct SREGS *sregs;
8231158Sminshall {
8331167Sminshall     NameResolveParms parms;
8431161Sminshall 
8531167Sminshall     movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
8631161Sminshall 
8731161Sminshall     regs->h.cl = 0;
8831193Sminshall     if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
8931161Sminshall 	regs->x.dx = GATE_SESSMGR;
9031193Sminshall     } else if (memcmp((char *)&parms, NAME_KEYBOARD,
9131193Sminshall 					sizeof parms.gate_name) == 0) {
9231161Sminshall 	regs->x.dx = GATE_KEYBOARD;
9331193Sminshall     } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
9431161Sminshall 	regs->x.dx = GATE_COPY;
9531193Sminshall     } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
9631161Sminshall 	regs->x.dx = GATE_OIAM;
9731161Sminshall     } else {
9831161Sminshall 	regs->h.cl = 0x2e;	/* Name not found */
9931161Sminshall     }
10031161Sminshall     regs->h.ch = 0x12;
10131161Sminshall     regs->h.bh = 7;
10231158Sminshall }
10331158Sminshall 
10431158Sminshall /*
10531158Sminshall  * Session Information Services.
10631158Sminshall  */
10731158Sminshall 
10831158Sminshall static void
10931158Sminshall query_session_id(regs, sregs)
11031158Sminshall union REGS *regs;
11131158Sminshall struct SREGS *sregs;
11231158Sminshall {
11331167Sminshall     QuerySessionIdParms parms;
11431161Sminshall 
11531167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
11631161Sminshall 
11731211Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
11831211Sminshall 	parms.rc = 0x0c;
11931211Sminshall     } else if (parms.option_code != 0x01) {
12031211Sminshall 	parms.rc = 0x0d;	/* Invalid option code */
12131167Sminshall     } else if (parms.data_code != 0x45) {
12231211Sminshall 	parms.rc = 0x0b;
12331161Sminshall     } else {
12431168Sminshall 	NameArray list;
12531167Sminshall 	NameArrayElement element;
12631167Sminshall 
12731167Sminshall 	movetous((char *)&list, FP_SEG(parms.name_array),
12831193Sminshall 			    FP_OFF(parms.name_array), sizeof list);
12931168Sminshall 	if ((list.length < 14) || (list.length > 170)) {
13031167Sminshall 	    parms.rc = 0x12;
13131161Sminshall 	} else {
13231167Sminshall 	    list.number_matching_session = 1;
13331167Sminshall 	    list.name_array_element.short_name = parms.data_code;
13431167Sminshall 	    list.name_array_element.type = TYPE_DFT;
13531167Sminshall 	    list.name_array_element.session_id = 23;
13631167Sminshall 	    memcpy(list.name_array_element.long_name, "ONLYSESS",
13731167Sminshall 			    sizeof list.name_array_element.long_name);
13831167Sminshall 	    movetothem(FP_SEG(parms.name_array),
13931193Sminshall 		FP_OFF(parms.name_array), (char *)&list, sizeof list);
14031167Sminshall 	    parms.rc = 0;
14131161Sminshall 	}
14231161Sminshall     }
14331211Sminshall     parms.function_id = 0x6b;
14431167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
14531158Sminshall }
14631158Sminshall 
14731158Sminshall static void
14831158Sminshall query_session_parameters(regs, sregs)
14931158Sminshall union REGS *regs;
15031158Sminshall struct SREGS *sregs;
15131158Sminshall {
15231167Sminshall     QuerySessionParametersParms parms;
15331167Sminshall 
15431167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
15531167Sminshall 
15631168Sminshall     if ((parms.rc !=0) || (parms.function_id != 0)) {
15731211Sminshall 	parms.rc = 0x0c;
15831211Sminshall     } else if (parms.session_id != 23) {
15931211Sminshall 	parms.rc = 0x02;
16031167Sminshall     } else {
16131211Sminshall 	parms.rc = 0;
16231167Sminshall 	parms.session_type = TYPE_DFT;
16331167Sminshall 	parms.session_characteristics = 0;	/* Neither EAB nor PSS */
16431167Sminshall 	parms.rows = MaxNumberLines;
16531167Sminshall 	parms.columns = MaxNumberColumns;
16631167Sminshall 	parms.presentation_space = 0;
16731167Sminshall     }
16831211Sminshall     parms.function_id = 0x6b;
16931168Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
17031158Sminshall }
17131158Sminshall 
17231158Sminshall static void
17331158Sminshall query_session_cursor(regs, sregs)
17431158Sminshall union REGS *regs;
17531158Sminshall struct SREGS *sregs;
17631158Sminshall {
17731167Sminshall     QuerySessionCursorParms parms;
17831167Sminshall 
17931167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
18031167Sminshall 
18131167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
18231167Sminshall 	parms.rc = 0x0c;
18331167Sminshall     } else if (parms.session_id != 23) {
18431167Sminshall 	parms.rc = 0x02;
18531167Sminshall     } else {
18631167Sminshall 	parms.rc = 0;
18731167Sminshall 	parms.cursor_type = CURSOR_BLINKING;	/* XXX what is inhibited? */
18831167Sminshall 	parms.row_address = ScreenLine(CursorAddress);
18931167Sminshall 	parms.column_address = ScreenLineOffset(CursorAddress);
19031167Sminshall     }
19131167Sminshall 
19231211Sminshall     parms.function_id = 0x6b;
19331211Sminshall     movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
19431158Sminshall }
19531158Sminshall 
19631158Sminshall /*
19731158Sminshall  * Keyboard Services.
19831158Sminshall  */
19931158Sminshall 
20031158Sminshall 
20131158Sminshall static void
20231158Sminshall connect_to_keyboard(regs, sregs)
20331158Sminshall union REGS *regs;
20431158Sminshall struct SREGS *sregs;
20531158Sminshall {
20631167Sminshall     ConnectToKeyboardParms parms;
20731167Sminshall 
20831183Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
20931167Sminshall 
21031167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
21131167Sminshall 	parms.rc = 0x0c;
21231167Sminshall     } else if (parms.session_id != 23) {
21331167Sminshall 	parms.rc = 0x02;
21431167Sminshall     } else if (parms.intercept_options != 0) {
21531167Sminshall 	parms.rc = 0x01;
21631167Sminshall     } else {
21731167Sminshall 	parms.rc = 0;
21831167Sminshall 	parms.first_connection_identifier = 0;
21931167Sminshall     }
22031167Sminshall     parms.function_id = 0x62;
22131167Sminshall 
22231167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
22331158Sminshall }
22431158Sminshall 
22531158Sminshall static void
22631167Sminshall disconnect_from_keyboard(regs, sregs)
22731158Sminshall union REGS *regs;
22831158Sminshall struct SREGS *sregs;
22931158Sminshall {
23031167Sminshall     DisconnectFromKeyboardParms parms;
23131167Sminshall 
23231167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
23331167Sminshall 
23431167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
23531167Sminshall 	parms.rc = 0x0c;
23631167Sminshall     } else if (parms.session_id != 23) {
23731167Sminshall 	parms.rc = 0x02;
23831167Sminshall     } else if (parms.connectors_task_id != 0) {
23931167Sminshall 	parms.rc = 04;			/* XXX */
24031167Sminshall     } else {
24131167Sminshall 	parms.rc = 0;
24231167Sminshall     }
24331167Sminshall     parms.function_id = 0x62;
24431167Sminshall 
24531167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
24631158Sminshall }
24731158Sminshall 
24831158Sminshall static void
24931158Sminshall write_keystroke(regs, sregs)
25031158Sminshall union REGS *regs;
25131158Sminshall struct SREGS *sregs;
25231158Sminshall {
25331198Sminshall     WriteKeystrokeParms parms;
25431198Sminshall 
25531198Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
25631198Sminshall 
25731198Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
25831198Sminshall 	parms.rc = 0x0c;
25931198Sminshall     } else if (parms.session_id != 23) {
26031198Sminshall 	parms.rc = 0x02;
26131198Sminshall     } else if (parms.connectors_task_id != 0) {
26231198Sminshall 	parms.rc = 0x04;
26331198Sminshall     } else {
26431198Sminshall 	parms.number_of_keys_sent = 0;
26531198Sminshall 	parms.rc = 0;
26631198Sminshall 	if (parms.options == OPTION_SINGLE_KEYSTROKE) {
26731198Sminshall 	    KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
26831198Sminshall 
26931198Sminshall 	    if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
27031198Sminshall 		parms.rc = 0x10;		/* XXX needs 0x12 too! */
27131198Sminshall 	    }
27231198Sminshall 	    parms.number_of_keys_sent++;
27331198Sminshall 	} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
27431198Sminshall 	    KeystrokeList
27531198Sminshall 		list,
27631198Sminshall 		far *atlist = parms.keystroke_specifier.keystroke_list;
27731198Sminshall 	    KeystrokeEntry
27831198Sminshall 		entry[10],		/* 10 at a time */
27931198Sminshall 		*ourentry,
28031198Sminshall 		far *theirentry;
28131198Sminshall 	    int
28231198Sminshall 		todo;
28331198Sminshall 
28431198Sminshall 	    movetous((char *)&list, FP_SEG(atlist),
28531198Sminshall 				FP_OFF(atlist), sizeof *atlist);
28631198Sminshall 	    todo = list.length/2;
28731198Sminshall 	    ourentry = entry+(highestof(entry)+1);
28831198Sminshall 
28931198Sminshall 	    while (todo) {
29031198Sminshall 		if (ourentry > &entry[highestof(entry)]) {
29131198Sminshall 		    int thistime;
29231198Sminshall 
29331198Sminshall 		    thistime = todo;
29431198Sminshall 		    if (thistime > numberof(entry)) {
29531198Sminshall 			thistime = numberof(entry);
29631198Sminshall 		    }
29731198Sminshall 		    movetous((char *)entry, FP_SEG(theirentry),
29831198Sminshall 			    FP_OFF(theirentry), thistime*sizeof *theirentry);
29931198Sminshall 		    theirentry += thistime;
30031198Sminshall 		    ourentry = entry;
30131198Sminshall 		}
30231198Sminshall 		if (AcceptKeystroke(ourentry->scancode,
30331198Sminshall 						ourentry->shift_state) == 0) {
30431198Sminshall 		    parms.rc = 0x10;		/* XXX needs 0x12 too! */
30531198Sminshall 		    break;
30631198Sminshall 		}
30731198Sminshall 		parms.number_of_keys_sent++;
30831198Sminshall 		ourentry++;
30931198Sminshall 		todo--;
31031198Sminshall 	    }
31131198Sminshall 	} else {
31231198Sminshall 	    parms.rc = 0x01;
31331198Sminshall 	}
31431198Sminshall     }
31531198Sminshall     parms.function_id = 0x62;
31631198Sminshall 
31731198Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
31831167Sminshall /* XXX */
31931158Sminshall }
32031158Sminshall 
32131167Sminshall 
32231158Sminshall static void
32331167Sminshall disable_input(regs, sregs)
32431167Sminshall union REGS *regs;
32531167Sminshall struct SREGS *sregs;
32631167Sminshall {
32731167Sminshall     DisableInputParms parms;
32831167Sminshall 
32931167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
33031167Sminshall 
33131167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
33231167Sminshall 	parms.rc = 0x0c;
33331167Sminshall     } else if (parms.session_id != 23) {
33431167Sminshall 	parms.rc = 0x02;
33531167Sminshall     } else if (parms.connectors_task_id != 0) {
33631167Sminshall 	parms.rc = 0x04;
33731167Sminshall     } else {
33831211Sminshall 	SetOiaApiInhibit(&OperatorInformationArea);
33931167Sminshall 	parms.rc = 0;
34031167Sminshall     }
34131167Sminshall     parms.function_id = 0x62;
34231167Sminshall 
34331167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
34431167Sminshall }
34531167Sminshall 
34631167Sminshall static void
34731158Sminshall enable_input(regs, sregs)
34831158Sminshall union REGS *regs;
34931158Sminshall struct SREGS *sregs;
35031158Sminshall {
35131167Sminshall     EnableInputParms parms;
35231167Sminshall 
35331167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
35431167Sminshall 
35531167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
35631167Sminshall 	parms.rc = 0x0c;
35731167Sminshall     } else if (parms.session_id != 23) {
35831167Sminshall 	parms.rc = 0x02;
35931167Sminshall     } else if (parms.connectors_task_id != 0) {
36031167Sminshall 	parms.rc = 0x04;
36131167Sminshall     } else {
36231211Sminshall 	ResetOiaApiInhibit(&OperatorInformationArea);
36331167Sminshall 	parms.rc = 0;
36431167Sminshall     }
36531167Sminshall     parms.function_id = 0x62;
36631167Sminshall 
36731167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
36831158Sminshall }
36931158Sminshall 
37031158Sminshall /*
37131158Sminshall  * Copy Services.
37231158Sminshall  */
37331158Sminshall 
37431507Sminshall static
37531507Sminshall copy_subroutine(target, source, parms, what_is_user, length)
37631226Sminshall BufferDescriptor *target, *source;
37731226Sminshall CopyStringParms *parms;
37831226Sminshall int what_is_user;
37931226Sminshall #define	USER_IS_TARGET	0
38031226Sminshall #define	USER_IS_SOURCE	1
38131226Sminshall {
38231226Sminshall #define	TARGET_NO_EAB		1
38331226Sminshall #define	SOURCE_NO_EAB		2
38431226Sminshall #define	TARGET_PC		4
38531226Sminshall #define	SOURCE_PC		8
38631226Sminshall #define	NO_FIELD_ATTRIBUTES	16
38731226Sminshall     int needtodo = 0;
38831226Sminshall     int access_length;
38931226Sminshall     char far *input;
39031226Sminshall     char far *output;
39131226Sminshall     char far *access_pointer;
39231226Sminshall 
39331226Sminshall     if ((target->characteristics^source->characteristics)
39431226Sminshall 		    &CHARACTERISTIC_EAB) {
39531226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
39631226Sminshall 	    needtodo |= TARGET_NO_EAB;	/* Need to bump for EAB in target */
39731226Sminshall 	} else {
39831226Sminshall 	    needtodo |= SOURCE_NO_EAB;	/* Need to bump for EAB in source */
39931226Sminshall 	}
40031226Sminshall     }
40131226Sminshall     if (target->session_type != source->session_type) {
40231226Sminshall 	if (target->session_type == TYPE_PC) {
40331226Sminshall 	    needtodo |= TARGET_PC;	/* scan codes to PC */
40431226Sminshall 	} else {
40531226Sminshall 	    needtodo |= SOURCE_PC;	/* PC to scan codes */
40631226Sminshall 	}
40731226Sminshall     }
40831226Sminshall     if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
40931226Sminshall 	needtodo |= NO_FIELD_ATTRIBUTES;
41031226Sminshall     }
41131507Sminshall     access_length = length;
41231226Sminshall     if (what_is_user == USER_IS_TARGET) {
41331226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
41431226Sminshall 	    access_length *= 2;
41531226Sminshall 	}
41631226Sminshall 	input = (char far *) &Host[source->begin];
41731226Sminshall 	access_pointer = target->buffer;
41831507Sminshall 	output = access_api(target->buffer, access_length, 0);
41931226Sminshall     } else {
42031226Sminshall 	if (source->characteristics&CHARACTERISTIC_EAB) {
42131226Sminshall 	    access_length *= 2;
42231226Sminshall 	}
42331226Sminshall 	access_pointer = source->buffer;
42431507Sminshall 	input = access_api(source->buffer, access_length, 1);
42531226Sminshall 	output = (char far *) &Host[target->begin];
42631226Sminshall     }
42731226Sminshall     while (length--) {
42831226Sminshall 	if (needtodo&TARGET_PC) {
42931226Sminshall 	    *output++ = disp_asc[*input++];
43031226Sminshall 	} else if (needtodo&SOURCE_PC) {
43131226Sminshall 	    *output++ = asc_disp[*input++];
43231226Sminshall 	} else {
43331226Sminshall 	    *output++ = *input++;
43431226Sminshall 	}
43531226Sminshall 	if (needtodo&TARGET_NO_EAB) {
43631226Sminshall 	    *input++;
43731226Sminshall 	} else if (needtodo&SOURCE_NO_EAB) {
43831226Sminshall 	    *output++ = 0;		/* Should figure out good EAB? */
43931226Sminshall 	}
44031226Sminshall     }
44131226Sminshall     if (what_is_user == USER_IS_TARGET) {
44231507Sminshall 	unaccess_api(target->buffer, access_pointer, access_length, 1);
44331226Sminshall     } else {
44431507Sminshall 	unaccess_api(source->buffer, access_pointer, access_length, 0);
44531226Sminshall     }
44631226Sminshall }
44731226Sminshall 
44831226Sminshall 
44931158Sminshall static void
45031167Sminshall copy_string(regs, sregs)
45131158Sminshall union REGS *regs;
45231158Sminshall struct SREGS *sregs;
45331158Sminshall {
45431167Sminshall     CopyStringParms parms;
45531226Sminshall     BufferDescriptor *target = &parms.target, *source = &parms.source;
45631226Sminshall     int length;
45731167Sminshall 
45831167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
45931167Sminshall 
46031507Sminshall     length = 1+parms.source_end-source->begin;
46131167Sminshall     if ((parms.rc != 0) || (parms.function_id !=0)) {
46231167Sminshall 	parms.rc = 0x0c;
46331226Sminshall     } else if (target->session_id == 0) {	/* Target is buffer */
46431226Sminshall 	if (source->session_id != 23) {		/* A no-no */
46531226Sminshall 	    parms.rc = 0x2;
46631226Sminshall 	} else {
46731507Sminshall 	    if ((source->begin < 0) || (source->begin > highestof(Host))) {
46831507Sminshall 		parms.rc = 0x06;		/* invalid source definition */
46931507Sminshall 	    } else {
47031507Sminshall 		if ((source->begin+length) > highestof(Host)) {
47131507Sminshall 		    length = highestof(Host)-source->begin;
47231507Sminshall 		    parms.rc = 0x0f;	/* Truncate */
47331507Sminshall 		}
47431507Sminshall 	        if ((source->characteristics == target->characteristics) &&
47531226Sminshall 		    (source->session_type == target->session_type)) {
47631507Sminshall 		    if (source->characteristics&CHARACTERISTIC_EAB) {
47731507Sminshall 			length *= 2;
47831507Sminshall 		    }
47931507Sminshall 		    movetothem( (int) FP_SEG(target->buffer),
48031507Sminshall 			    (int) FP_OFF(target->buffer),
48131507Sminshall 			    (char *)&Host[source->begin], length);
48231507Sminshall 		} else {
48331507Sminshall 		    copy_subroutine(target, source, &parms,
48431507Sminshall 							USER_IS_TARGET, length);
48531226Sminshall 		}
48631226Sminshall 	    }
48731226Sminshall 	}
48831226Sminshall     } else if (source->session_id != 0) {
48931226Sminshall 	    parms.rc = 0xd;
49031226Sminshall     } else {
49131507Sminshall 	if ((target->begin < 0) || (source->begin > highestof(Host))) {
49231507Sminshall 	    parms.rc = 0x07;		/* invalid source definition */
49331507Sminshall 	} else {
49431507Sminshall 	    if ((source->begin+length) > highestof(Host)) {
49531507Sminshall 		length = highestof(Host)-source->begin;
49631507Sminshall 		parms.rc = 0x0f;	/* Truncate */
49731226Sminshall 	    }
49831507Sminshall 	    if ((source->characteristics == target->characteristics) &&
49931507Sminshall 		    (source->session_type == target->session_type)) {
50031507Sminshall 		if (source->characteristics&CHARACTERISTIC_EAB) {
50131507Sminshall 		    length *= 2;
50231507Sminshall 		}
50331507Sminshall 		movetous((char *)&Host[target->begin],
50431507Sminshall 			    (int) FP_SEG(source->buffer),
50531507Sminshall 			    (int) FP_OFF(source->buffer), length);
50631507Sminshall 	    } else {
50731507Sminshall 		copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
50831507Sminshall 	    }
50931226Sminshall 	}
51031167Sminshall     }
51131183Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
51231158Sminshall }
51331158Sminshall /*
51431158Sminshall  * Operator Information Area Services.
51531158Sminshall  */
51631158Sminshall 
51731158Sminshall static void
51831158Sminshall read_oia_group(regs, sregs)
51931158Sminshall union REGS *regs;
52031158Sminshall struct SREGS *sregs;
52131158Sminshall {
52231167Sminshall     ReadOiaGroupParms parms;
52331167Sminshall 
52431167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
52531167Sminshall 
52631167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
52731167Sminshall 	parms.rc = 0x0c;
52831167Sminshall     } else if (parms.session_id != 23) {
52931167Sminshall 	parms.rc = 0x02;
53031167Sminshall     } else {
53131167Sminshall 	int group = parms.oia_group_number;
53231193Sminshall 	char *from;
53331193Sminshall 	int size;
53431167Sminshall 
53531211Sminshall 	if ((group != API_OIA_ALL_GROUPS) &&
53631211Sminshall 		((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
53731193Sminshall 	} else {
53831193Sminshall 	    if (group == API_OIA_ALL_GROUPS) {
53931193Sminshall 		size = API_OIA_BYTES_ALL_GROUPS;
54031193Sminshall 		from = (char *)&OperatorInformationArea;
54131193Sminshall 	    } else if (group == API_OIA_INPUT_INHIBITED) {
54231193Sminshall 		size = sizeof OperatorInformationArea.input_inhibited;
54331193Sminshall 		from = (char *)&OperatorInformationArea.input_inhibited[0];
54431193Sminshall 	    } else {
54531193Sminshall 		size = 1;
54631193Sminshall 		from = ((char *)&OperatorInformationArea)+group;
54731193Sminshall 	    }
54831193Sminshall 	    movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
54931193Sminshall 			from, size);
55031168Sminshall 	}
55131167Sminshall     }
55231168Sminshall     parms.function_id = 0x6d;
55331167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
55431158Sminshall }
55531158Sminshall 
55631158Sminshall static void
55731158Sminshall unknown_op(regs, sregs)
55831158Sminshall union REGS *regs;
55931158Sminshall struct SREGS *sregs;
56031158Sminshall {
56131158Sminshall     regs->h.ch = 0x12;
56231158Sminshall     regs->h.cl = 0x05;
56331158Sminshall }
56431158Sminshall 
56531158Sminshall 
56631158Sminshall handle_api(regs, sregs)
56731158Sminshall union REGS *regs;
56831158Sminshall struct SREGS *sregs;
56931158Sminshall {
57031158Sminshall     if (regs->h.ah == NAME_RESOLUTION) {
57131158Sminshall 	name_resolution(regs, sregs);
57231517Sminshall #if	defined(unix)
57331517Sminshall     } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
57431517Sminshall 	while ((oia_modified == 0) && (ps_modified == 0)) {
57531517Sminshall 	    (void) Scheduler(1);
57631517Sminshall 	}
57731517Sminshall 	oia_modified = ps_modified = 0;
57831517Sminshall #endif	/* defined(unix) */
57931168Sminshall     } else if (regs->h.ah != 0x09) {
58031168Sminshall 	regs->h.ch = 0x12;
58131168Sminshall 	regs->h.cl = 0x0f;		/* XXX Invalid environmental access */
58231168Sminshall     } else if (regs->x.bx != 0x8020) {
58331168Sminshall 	regs->h.ch = 0x12;
58431168Sminshall 	regs->h.cl = 0x08;		/* XXX Invalid wait specified */
58531168Sminshall     } else if (regs->h.ch != 0) {
58631211Sminshall 	regs->x.cx = 0x1206;		/* XXX Invalid priority */
58731158Sminshall     } else {
58831158Sminshall 	switch (regs->x.dx) {
58931158Sminshall 	case GATE_SESSMGR:
59031158Sminshall 	    switch (regs->h.al) {
59131158Sminshall 	    case QUERY_SESSION_ID:
59231168Sminshall 		if (regs->h.cl != 0) {
59331211Sminshall 		    regs->x.cx = 0x1206;
59431168Sminshall 		} else {
59531211Sminshall 		    regs->x.cx = 0x1200;
59631168Sminshall 		    query_session_id(regs, sregs);
59731168Sminshall 		}
59831158Sminshall 		break;
59931211Sminshall 	    case QUERY_SESSION_PARAMETERS:
60031168Sminshall 		if (regs->h.cl != 0) {
60131211Sminshall 		    regs->x.cx = 0x1206;
60231168Sminshall 		} else {
60331211Sminshall 		    regs->x.cx = 0x1200;
60431193Sminshall 		    query_session_parameters(regs, sregs);
60531168Sminshall 		}
60631158Sminshall 		break;
60731158Sminshall 	    case QUERY_SESSION_CURSOR:
60831168Sminshall 		if (regs->h.cl != 0xff) {
60931211Sminshall 		    regs->x.cx = 0x1206;
61031168Sminshall 		} else {
61131211Sminshall 		    regs->x.cx = 0x1200;
61231168Sminshall 		    query_session_cursor(regs, sregs);
61331168Sminshall 		}
61431158Sminshall 		break;
61531158Sminshall 	    default:
61631158Sminshall 		unknown_op(regs, sregs);
61731158Sminshall 		break;
61831158Sminshall 	    }
61931158Sminshall 	    break;
62031158Sminshall 	case GATE_KEYBOARD:
62131168Sminshall 	    if (regs->h.cl != 00) {
62231211Sminshall 		regs->x.cx = 0x1206;
62331168Sminshall 	    } else {
62431211Sminshall 		regs->x.cx = 0x1200;
62531168Sminshall 		switch (regs->h.al) {
62631168Sminshall 		case CONNECT_TO_KEYBOARD:
62731168Sminshall 		    connect_to_keyboard(regs, sregs);
62831168Sminshall 		    break;
62931168Sminshall 		case DISABLE_INPUT:
63031168Sminshall 		    disable_input(regs, sregs);
63131168Sminshall 		    break;
63231168Sminshall 		case WRITE_KEYSTROKE:
63331168Sminshall 		    write_keystroke(regs, sregs);
63431168Sminshall 		    break;
63531168Sminshall 		case ENABLE_INPUT:
63631168Sminshall 		    enable_input(regs, sregs);
63731168Sminshall 		    break;
63831168Sminshall 		case DISCONNECT_FROM_KEYBOARD:
63931168Sminshall 		    disconnect_from_keyboard(regs, sregs);
64031168Sminshall 		    break;
64131168Sminshall 		default:
64231168Sminshall 		    unknown_op(regs, sregs);
64331168Sminshall 		    break;
64431168Sminshall 		}
64531158Sminshall 	    }
64631158Sminshall 	    break;
64731158Sminshall 	case GATE_COPY:
64831168Sminshall 	    if (regs->h.cl != 0xff) {
64931211Sminshall 		regs->x.cx = 0x1206;
65031168Sminshall 	    } else {
65131211Sminshall 		regs->x.cx = 0x1200;
65231168Sminshall 		switch (regs->h.al) {
65331168Sminshall 		case COPY_STRING:
65431168Sminshall 		    copy_string(regs, sregs);
65531168Sminshall 		    break;
65631168Sminshall 		default:
65731168Sminshall 		    unknown_op(regs, sregs);
65831168Sminshall 		    break;
65931168Sminshall 		}
66031158Sminshall 	    }
66131158Sminshall 	    break;
66231158Sminshall 	case GATE_OIAM:
66331168Sminshall 	    if (regs->h.cl != 0xff) {
66431211Sminshall 		regs->x.cx = 0x1206;
66531168Sminshall 	    } else {
66631211Sminshall 		regs->x.cx = 0x1200;
66731168Sminshall 		switch (regs->h.al) {
66831168Sminshall 		case READ_OIA_GROUP:
66931168Sminshall 		    read_oia_group(regs, sregs);
67031168Sminshall 		    break;
67131168Sminshall 		default:
67231168Sminshall 		    unknown_op(regs, sregs);
67331168Sminshall 		    break;
67431168Sminshall 		}
67531158Sminshall 	    }
67631158Sminshall 	    break;
67731158Sminshall 	default:
67831168Sminshall 	    regs->h.ch = 0x12;
67931168Sminshall 	    regs->h.cl = 0x34;		/* Invalid GATE entry */
68031158Sminshall 	    break;
68131158Sminshall 	}
68231158Sminshall     }
68331158Sminshall }
684