xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 38924)
131158Sminshall /*
233816Sbostic  * Copyright (c) 1988 Regents of the University of California.
333816Sbostic  * All rights reserved.
431892Sminshall  *
533816Sbostic  * Redistribution and use in source and binary forms are permitted
635421Sminshall  * provided that the above copyright notice and this paragraph are
735421Sminshall  * duplicated in all such forms and that any documentation,
835421Sminshall  * advertising materials, and other materials related to such
935421Sminshall  * distribution and use acknowledge that the software was developed
1035421Sminshall  * by the University of California, Berkeley.  The name of the
1135421Sminshall  * University may not be used to endorse or promote products derived
1235421Sminshall  * from this software without specific prior written permission.
1335421Sminshall  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1435421Sminshall  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1535421Sminshall  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1631892Sminshall  */
1731892Sminshall 
1831892Sminshall #ifndef lint
19*38924Sminshall static char sccsid[] = "@(#)api.c	4.3 (Berkeley) 09/02/89";
2033816Sbostic #endif /* not lint */
2131892Sminshall 
2231892Sminshall /*
2331158Sminshall  * This file implements the API used in the PC version.
2431158Sminshall  */
2531158Sminshall 
2631158Sminshall #include <stdio.h>
2731158Sminshall 
2831158Sminshall #include "api.h"
2931183Sminshall #include "../general/general.h"
3031158Sminshall 
3131871Sminshall #include "../api/disp_asc.h"
3231226Sminshall 
3331871Sminshall #include "screen.h"
3438210Sminshall #include "hostctlr.h"
3531871Sminshall #include "oia.h"
3631193Sminshall 
3731183Sminshall #include "../general/globals.h"
3831158Sminshall 
39*38924Sminshall int apitrace = 0;		/* Should we trace API interactions */
40*38924Sminshall 
4131158Sminshall /*
4231193Sminshall  * General utility routines.
4331193Sminshall  */
4431193Sminshall 
4531193Sminshall #if	defined(MSDOS)
4631193Sminshall 
4731211Sminshall #if	defined(LINT_ARGS)
4831211Sminshall static void movetous(char *, int, int, int);
4931211Sminshall static void movetothem(int, int, char *, int);
5031211Sminshall #endif	/* defined(LINT_ARGS) */
5131211Sminshall 
5231507Sminshall #define	access_api(foo,length,copyin)	(foo)
5331507Sminshall #define	unaccess_api(foo,goo,length,copyout)
5431226Sminshall 
5531193Sminshall static void
5631193Sminshall movetous(parms, es, di, length)
5731193Sminshall char *parms;
5835421Sminshall int es, di;
5935421Sminshall int length;
6031193Sminshall {
6131211Sminshall     char far *farparms = parms;
6231193Sminshall 
6335421Sminshall     movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length);
64*38924Sminshall     if (apitrace) {
65*38924Sminshall 	Dump('(', parms, length);
66*38924Sminshall     }
6731193Sminshall }
6831193Sminshall 
6931193Sminshall static void
7031211Sminshall movetothem(es, di, parms, length)
7131211Sminshall int es, di;
7231211Sminshall char *parms;
7331211Sminshall int length;
7431193Sminshall {
7531211Sminshall     char far *farparms = parms;
7631193Sminshall 
7735421Sminshall     movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length);
78*38924Sminshall     if (apitrace) {
79*38924Sminshall 	Dump(')', parms, length);
80*38924Sminshall     }
8131193Sminshall }
8231193Sminshall #endif	/* defined(MSDOS) */
8331193Sminshall 
8431226Sminshall #if	defined(unix)
8535421Sminshall extern char *access_api();
8635421Sminshall extern void movetous(), movetothem(), unaccess_api();
8731226Sminshall #endif	/* defined(unix) */
8831226Sminshall 
8931470Sminshall 
9031193Sminshall /*
9131158Sminshall  * Supervisor Services.
9231158Sminshall  */
9331158Sminshall 
9431158Sminshall static void
9531193Sminshall name_resolution(regs, sregs)
9631158Sminshall union REGS *regs;
9731158Sminshall struct SREGS *sregs;
9831158Sminshall {
9931167Sminshall     NameResolveParms parms;
10031161Sminshall 
10131167Sminshall     movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
10231161Sminshall 
10331161Sminshall     regs->h.cl = 0;
10431193Sminshall     if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
10531161Sminshall 	regs->x.dx = GATE_SESSMGR;
10631193Sminshall     } else if (memcmp((char *)&parms, NAME_KEYBOARD,
10731193Sminshall 					sizeof parms.gate_name) == 0) {
10831161Sminshall 	regs->x.dx = GATE_KEYBOARD;
10931193Sminshall     } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
11031161Sminshall 	regs->x.dx = GATE_COPY;
11131193Sminshall     } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
11231161Sminshall 	regs->x.dx = GATE_OIAM;
11331161Sminshall     } else {
11431161Sminshall 	regs->h.cl = 0x2e;	/* Name not found */
11531161Sminshall     }
11631161Sminshall     regs->h.ch = 0x12;
11731161Sminshall     regs->h.bh = 7;
11831158Sminshall }
11931158Sminshall 
12031158Sminshall /*
12131158Sminshall  * Session Information Services.
12231158Sminshall  */
12331158Sminshall 
12431158Sminshall static void
12531158Sminshall query_session_id(regs, sregs)
12631158Sminshall union REGS *regs;
12731158Sminshall struct SREGS *sregs;
12831158Sminshall {
12931167Sminshall     QuerySessionIdParms parms;
13031161Sminshall 
13131167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
13231161Sminshall 
13331211Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
13431211Sminshall 	parms.rc = 0x0c;
13531211Sminshall     } else if (parms.option_code != 0x01) {
13631211Sminshall 	parms.rc = 0x0d;	/* Invalid option code */
13731167Sminshall     } else if (parms.data_code != 0x45) {
13831211Sminshall 	parms.rc = 0x0b;
13931161Sminshall     } else {
14031168Sminshall 	NameArray list;
14131167Sminshall 
14231167Sminshall 	movetous((char *)&list, FP_SEG(parms.name_array),
14335421Sminshall 		    FP_OFF(parms.name_array), sizeof list);
14431168Sminshall 	if ((list.length < 14) || (list.length > 170)) {
14531167Sminshall 	    parms.rc = 0x12;
14631161Sminshall 	} else {
14731167Sminshall 	    list.number_matching_session = 1;
14831167Sminshall 	    list.name_array_element.short_name = parms.data_code;
14931167Sminshall 	    list.name_array_element.type = TYPE_DFT;
15031167Sminshall 	    list.name_array_element.session_id = 23;
15131167Sminshall 	    memcpy(list.name_array_element.long_name, "ONLYSESS",
15231167Sminshall 			    sizeof list.name_array_element.long_name);
15331167Sminshall 	    movetothem(FP_SEG(parms.name_array),
15431193Sminshall 		FP_OFF(parms.name_array), (char *)&list, sizeof list);
15531167Sminshall 	    parms.rc = 0;
15631161Sminshall 	}
15731161Sminshall     }
15831211Sminshall     parms.function_id = 0x6b;
15931167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
16031158Sminshall }
16131158Sminshall 
16231158Sminshall static void
16331158Sminshall query_session_parameters(regs, sregs)
16431158Sminshall union REGS *regs;
16531158Sminshall struct SREGS *sregs;
16631158Sminshall {
16731167Sminshall     QuerySessionParametersParms parms;
16831167Sminshall 
16931167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
17031167Sminshall 
17131168Sminshall     if ((parms.rc !=0) || (parms.function_id != 0)) {
17231211Sminshall 	parms.rc = 0x0c;
17331211Sminshall     } else if (parms.session_id != 23) {
17431211Sminshall 	parms.rc = 0x02;
17531167Sminshall     } else {
17631211Sminshall 	parms.rc = 0;
17731167Sminshall 	parms.session_type = TYPE_DFT;
17831167Sminshall 	parms.session_characteristics = 0;	/* Neither EAB nor PSS */
17931167Sminshall 	parms.rows = MaxNumberLines;
18031167Sminshall 	parms.columns = MaxNumberColumns;
18131167Sminshall 	parms.presentation_space = 0;
18231167Sminshall     }
18331211Sminshall     parms.function_id = 0x6b;
18431168Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
18531158Sminshall }
18631158Sminshall 
18731158Sminshall static void
18831158Sminshall query_session_cursor(regs, sregs)
18931158Sminshall union REGS *regs;
19031158Sminshall struct SREGS *sregs;
19131158Sminshall {
19231167Sminshall     QuerySessionCursorParms parms;
19331167Sminshall 
19431167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
19531167Sminshall 
19631167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
19731167Sminshall 	parms.rc = 0x0c;
19831167Sminshall     } else if (parms.session_id != 23) {
19931167Sminshall 	parms.rc = 0x02;
20031167Sminshall     } else {
20131167Sminshall 	parms.rc = 0;
20231167Sminshall 	parms.cursor_type = CURSOR_BLINKING;	/* XXX what is inhibited? */
20331167Sminshall 	parms.row_address = ScreenLine(CursorAddress);
20431167Sminshall 	parms.column_address = ScreenLineOffset(CursorAddress);
20531167Sminshall     }
20631167Sminshall 
20731211Sminshall     parms.function_id = 0x6b;
20831211Sminshall     movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
20931158Sminshall }
21031158Sminshall 
21131158Sminshall /*
21231158Sminshall  * Keyboard Services.
21331158Sminshall  */
21431158Sminshall 
21531158Sminshall 
21631158Sminshall static void
21731158Sminshall connect_to_keyboard(regs, sregs)
21831158Sminshall union REGS *regs;
21931158Sminshall struct SREGS *sregs;
22031158Sminshall {
22131167Sminshall     ConnectToKeyboardParms parms;
22231167Sminshall 
22331183Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
22431167Sminshall 
22531167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
22631167Sminshall 	parms.rc = 0x0c;
22731167Sminshall     } else if (parms.session_id != 23) {
22831167Sminshall 	parms.rc = 0x02;
22931167Sminshall     } else if (parms.intercept_options != 0) {
23031167Sminshall 	parms.rc = 0x01;
23131167Sminshall     } else {
23231167Sminshall 	parms.rc = 0;
23331167Sminshall 	parms.first_connection_identifier = 0;
23431167Sminshall     }
23531167Sminshall     parms.function_id = 0x62;
23631167Sminshall 
23731167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
23831158Sminshall }
23931158Sminshall 
24031158Sminshall static void
24131167Sminshall disconnect_from_keyboard(regs, sregs)
24231158Sminshall union REGS *regs;
24331158Sminshall struct SREGS *sregs;
24431158Sminshall {
24531167Sminshall     DisconnectFromKeyboardParms parms;
24631167Sminshall 
24731167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
24831167Sminshall 
24931167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
25031167Sminshall 	parms.rc = 0x0c;
25131167Sminshall     } else if (parms.session_id != 23) {
25231167Sminshall 	parms.rc = 0x02;
25331167Sminshall     } else if (parms.connectors_task_id != 0) {
25431167Sminshall 	parms.rc = 04;			/* XXX */
25531167Sminshall     } else {
25631167Sminshall 	parms.rc = 0;
25731167Sminshall     }
25831167Sminshall     parms.function_id = 0x62;
25931167Sminshall 
26031167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
26131158Sminshall }
26231158Sminshall 
26331158Sminshall static void
26431158Sminshall write_keystroke(regs, sregs)
26531158Sminshall union REGS *regs;
26631158Sminshall struct SREGS *sregs;
26731158Sminshall {
26831198Sminshall     WriteKeystrokeParms parms;
26931198Sminshall 
27031198Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
27131198Sminshall 
27231198Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
27331198Sminshall 	parms.rc = 0x0c;
27431198Sminshall     } else if (parms.session_id != 23) {
27531198Sminshall 	parms.rc = 0x02;
27631198Sminshall     } else if (parms.connectors_task_id != 0) {
27731198Sminshall 	parms.rc = 0x04;
27831198Sminshall     } else {
27931198Sminshall 	parms.number_of_keys_sent = 0;
28031198Sminshall 	parms.rc = 0;
28131198Sminshall 	if (parms.options == OPTION_SINGLE_KEYSTROKE) {
28231198Sminshall 	    KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
28331198Sminshall 
28431198Sminshall 	    if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
28531198Sminshall 		parms.rc = 0x10;		/* XXX needs 0x12 too! */
28631198Sminshall 	    }
28731198Sminshall 	    parms.number_of_keys_sent++;
28831198Sminshall 	} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
28931198Sminshall 	    KeystrokeList
29031198Sminshall 		list,
29131198Sminshall 		far *atlist = parms.keystroke_specifier.keystroke_list;
29231198Sminshall 	    KeystrokeEntry
29331198Sminshall 		entry[10],		/* 10 at a time */
29431198Sminshall 		*ourentry,
29531198Sminshall 		far *theirentry;
29631198Sminshall 	    int
29731198Sminshall 		todo;
29831198Sminshall 
29931198Sminshall 	    movetous((char *)&list, FP_SEG(atlist),
30035421Sminshall 			FP_OFF(atlist), sizeof *atlist);
30131198Sminshall 	    todo = list.length/2;
30231198Sminshall 	    ourentry = entry+(highestof(entry)+1);
30335421Sminshall 	    theirentry = &atlist->keystrokes;
30431198Sminshall 
30531198Sminshall 	    while (todo) {
30631198Sminshall 		if (ourentry > &entry[highestof(entry)]) {
30731198Sminshall 		    int thistime;
30831198Sminshall 
30931198Sminshall 		    thistime = todo;
31031198Sminshall 		    if (thistime > numberof(entry)) {
31131198Sminshall 			thistime = numberof(entry);
31231198Sminshall 		    }
31331198Sminshall 		    movetous((char *)entry, FP_SEG(theirentry),
31431198Sminshall 			    FP_OFF(theirentry), thistime*sizeof *theirentry);
31531198Sminshall 		    theirentry += thistime;
31631198Sminshall 		    ourentry = entry;
31731198Sminshall 		}
31831198Sminshall 		if (AcceptKeystroke(ourentry->scancode,
31931198Sminshall 						ourentry->shift_state) == 0) {
32031198Sminshall 		    parms.rc = 0x10;		/* XXX needs 0x12 too! */
32131198Sminshall 		    break;
32231198Sminshall 		}
32331198Sminshall 		parms.number_of_keys_sent++;
32431198Sminshall 		ourentry++;
32531198Sminshall 		todo--;
32631198Sminshall 	    }
32731198Sminshall 	} else {
32831198Sminshall 	    parms.rc = 0x01;
32931198Sminshall 	}
33031198Sminshall     }
33131198Sminshall     parms.function_id = 0x62;
33231198Sminshall 
33331198Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
33431167Sminshall /* XXX */
33531158Sminshall }
33631158Sminshall 
33731167Sminshall 
33831158Sminshall static void
33931167Sminshall disable_input(regs, sregs)
34031167Sminshall union REGS *regs;
34131167Sminshall struct SREGS *sregs;
34231167Sminshall {
34331167Sminshall     DisableInputParms parms;
34431167Sminshall 
34531167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
34631167Sminshall 
34731167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
34831167Sminshall 	parms.rc = 0x0c;
34931167Sminshall     } else if (parms.session_id != 23) {
35031167Sminshall 	parms.rc = 0x02;
35131167Sminshall     } else if (parms.connectors_task_id != 0) {
35231167Sminshall 	parms.rc = 0x04;
35331167Sminshall     } else {
35431211Sminshall 	SetOiaApiInhibit(&OperatorInformationArea);
35531167Sminshall 	parms.rc = 0;
35631167Sminshall     }
35731167Sminshall     parms.function_id = 0x62;
35831167Sminshall 
35931167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
36031167Sminshall }
36131167Sminshall 
36231167Sminshall static void
36331158Sminshall enable_input(regs, sregs)
36431158Sminshall union REGS *regs;
36531158Sminshall struct SREGS *sregs;
36631158Sminshall {
36731167Sminshall     EnableInputParms parms;
36831167Sminshall 
36931167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
37031167Sminshall 
37131167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
37231167Sminshall 	parms.rc = 0x0c;
37331167Sminshall     } else if (parms.session_id != 23) {
37431167Sminshall 	parms.rc = 0x02;
37531167Sminshall     } else if (parms.connectors_task_id != 0) {
37631167Sminshall 	parms.rc = 0x04;
37731167Sminshall     } else {
37831211Sminshall 	ResetOiaApiInhibit(&OperatorInformationArea);
37931167Sminshall 	parms.rc = 0;
38031167Sminshall     }
38131167Sminshall     parms.function_id = 0x62;
38231167Sminshall 
38331167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
38431158Sminshall }
38531158Sminshall 
38631158Sminshall /*
38731158Sminshall  * Copy Services.
38831158Sminshall  */
38931158Sminshall 
39031507Sminshall static
39131507Sminshall copy_subroutine(target, source, parms, what_is_user, length)
39231226Sminshall BufferDescriptor *target, *source;
39331226Sminshall CopyStringParms *parms;
39431226Sminshall int what_is_user;
39531226Sminshall #define	USER_IS_TARGET	0
39631226Sminshall #define	USER_IS_SOURCE	1
39731226Sminshall {
39831226Sminshall #define	TARGET_NO_EAB		1
39931226Sminshall #define	SOURCE_NO_EAB		2
40031226Sminshall #define	TARGET_PC		4
40131226Sminshall #define	SOURCE_PC		8
40231226Sminshall #define	NO_FIELD_ATTRIBUTES	16
40331226Sminshall     int needtodo = 0;
40431226Sminshall     int access_length;
40531226Sminshall     char far *input;
40631226Sminshall     char far *output;
40731226Sminshall     char far *access_pointer;
40831226Sminshall 
40931226Sminshall     if ((target->characteristics^source->characteristics)
41031226Sminshall 		    &CHARACTERISTIC_EAB) {
41131226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
41231226Sminshall 	    needtodo |= TARGET_NO_EAB;	/* Need to bump for EAB in target */
41331226Sminshall 	} else {
41431226Sminshall 	    needtodo |= SOURCE_NO_EAB;	/* Need to bump for EAB in source */
41531226Sminshall 	}
41631226Sminshall     }
41731226Sminshall     if (target->session_type != source->session_type) {
41831226Sminshall 	if (target->session_type == TYPE_PC) {
41931226Sminshall 	    needtodo |= TARGET_PC;	/* scan codes to PC */
42031226Sminshall 	} else {
42131226Sminshall 	    needtodo |= SOURCE_PC;	/* PC to scan codes */
42231226Sminshall 	}
42331226Sminshall     }
42431226Sminshall     if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
42531226Sminshall 	needtodo |= NO_FIELD_ATTRIBUTES;
42631226Sminshall     }
42731507Sminshall     access_length = length;
42831226Sminshall     if (what_is_user == USER_IS_TARGET) {
42931226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
43031226Sminshall 	    access_length *= 2;
43131226Sminshall 	}
43231226Sminshall 	input = (char far *) &Host[source->begin];
43331226Sminshall 	access_pointer = target->buffer;
43431507Sminshall 	output = access_api(target->buffer, access_length, 0);
43531226Sminshall     } else {
43631226Sminshall 	if (source->characteristics&CHARACTERISTIC_EAB) {
43731226Sminshall 	    access_length *= 2;
43831226Sminshall 	}
43931226Sminshall 	access_pointer = source->buffer;
44031507Sminshall 	input = access_api(source->buffer, access_length, 1);
44131226Sminshall 	output = (char far *) &Host[target->begin];
44231226Sminshall     }
44331226Sminshall     while (length--) {
44431226Sminshall 	if (needtodo&TARGET_PC) {
44531226Sminshall 	    *output++ = disp_asc[*input++];
44631226Sminshall 	} else if (needtodo&SOURCE_PC) {
44731226Sminshall 	    *output++ = asc_disp[*input++];
44831226Sminshall 	} else {
44931226Sminshall 	    *output++ = *input++;
45031226Sminshall 	}
45131226Sminshall 	if (needtodo&TARGET_NO_EAB) {
45235421Sminshall 	    input++;
45331226Sminshall 	} else if (needtodo&SOURCE_NO_EAB) {
45431226Sminshall 	    *output++ = 0;		/* Should figure out good EAB? */
45531226Sminshall 	}
45631226Sminshall     }
45731226Sminshall     if (what_is_user == USER_IS_TARGET) {
45831507Sminshall 	unaccess_api(target->buffer, access_pointer, access_length, 1);
45931226Sminshall     } else {
46031507Sminshall 	unaccess_api(source->buffer, access_pointer, access_length, 0);
46131226Sminshall     }
46231226Sminshall }
46331226Sminshall 
46431226Sminshall 
46531158Sminshall static void
46631167Sminshall copy_string(regs, sregs)
46731158Sminshall union REGS *regs;
46831158Sminshall struct SREGS *sregs;
46931158Sminshall {
47031167Sminshall     CopyStringParms parms;
47131226Sminshall     BufferDescriptor *target = &parms.target, *source = &parms.source;
47231226Sminshall     int length;
47331167Sminshall 
47431167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
47531167Sminshall 
47631507Sminshall     length = 1+parms.source_end-source->begin;
47731167Sminshall     if ((parms.rc != 0) || (parms.function_id !=0)) {
47831167Sminshall 	parms.rc = 0x0c;
47931226Sminshall     } else if (target->session_id == 0) {	/* Target is buffer */
48031226Sminshall 	if (source->session_id != 23) {		/* A no-no */
48131226Sminshall 	    parms.rc = 0x2;
48231226Sminshall 	} else {
48331507Sminshall 	    if ((source->begin < 0) || (source->begin > highestof(Host))) {
48431507Sminshall 		parms.rc = 0x06;		/* invalid source definition */
48531507Sminshall 	    } else {
48631507Sminshall 		if ((source->begin+length) > highestof(Host)) {
48731507Sminshall 		    length = highestof(Host)-source->begin;
48831507Sminshall 		    parms.rc = 0x0f;	/* Truncate */
48931507Sminshall 		}
49031507Sminshall 	        if ((source->characteristics == target->characteristics) &&
49131226Sminshall 		    (source->session_type == target->session_type)) {
49231507Sminshall 		    if (source->characteristics&CHARACTERISTIC_EAB) {
49331507Sminshall 			length *= 2;
49431507Sminshall 		    }
49535421Sminshall 		    movetothem(FP_SEG(target->buffer),
49635421Sminshall 			    FP_OFF(target->buffer),
49731507Sminshall 			    (char *)&Host[source->begin], length);
49831507Sminshall 		} else {
49931507Sminshall 		    copy_subroutine(target, source, &parms,
50031507Sminshall 							USER_IS_TARGET, length);
50131226Sminshall 		}
50231226Sminshall 	    }
50331226Sminshall 	}
50431226Sminshall     } else if (source->session_id != 0) {
50531226Sminshall 	    parms.rc = 0xd;
50631226Sminshall     } else {
50738210Sminshall 	/* Send to presentation space (3270 buffer) */
50838210Sminshall 	if ((target->begin < 0) || (target->begin > highestof(Host))) {
50938210Sminshall 	    parms.rc = 0x07;		/* invalid target definition */
51038210Sminshall 	} if (!UnLocked) {
51138210Sminshall 		parms.rc = 0x03;	/* Keyboard locked */
51238210Sminshall 	} else if (parms.copy_mode != 0) {
51338210Sminshall 		parms.rc = 0x0f;	/* Copy of field attr's not allowed */
51438210Sminshall 	} else if (IsProtected(target->begin) || /* Make sure no protected */
51538210Sminshall 		    (WhereAttrByte(target->begin) !=	/* in range */
51638210Sminshall 			    WhereAttrByte(target->begin+length-1))) {
51738210Sminshall 		parms.rc = 0x0e;	/* Attempt to write in protected */
51831507Sminshall 	} else {
51938210Sminshall 	    if ((target->begin+length) > highestof(Host)) {
52038210Sminshall 		length = highestof(Host)-target->begin;
52131507Sminshall 		parms.rc = 0x0f;	/* Truncate */
52231226Sminshall 	    }
52338210Sminshall 	    TurnOnMdt(target->begin);	/* Things have changed */
52431507Sminshall 	    if ((source->characteristics == target->characteristics) &&
52531507Sminshall 		    (source->session_type == target->session_type)) {
52631507Sminshall 		if (source->characteristics&CHARACTERISTIC_EAB) {
52731507Sminshall 		    length *= 2;
52831507Sminshall 		}
52931507Sminshall 		movetous((char *)&Host[target->begin],
53035421Sminshall 			    FP_SEG(source->buffer),
53135421Sminshall 			    FP_OFF(source->buffer), length);
53231507Sminshall 	    } else {
53331507Sminshall 		copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
53431507Sminshall 	    }
53531226Sminshall 	}
53631167Sminshall     }
53731183Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
53831158Sminshall }
53931158Sminshall /*
54031158Sminshall  * Operator Information Area Services.
54131158Sminshall  */
54231158Sminshall 
54331158Sminshall static void
54431158Sminshall read_oia_group(regs, sregs)
54531158Sminshall union REGS *regs;
54631158Sminshall struct SREGS *sregs;
54731158Sminshall {
54831167Sminshall     ReadOiaGroupParms parms;
54931167Sminshall 
55031167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
55131167Sminshall 
55231167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
55331167Sminshall 	parms.rc = 0x0c;
55431167Sminshall     } else if (parms.session_id != 23) {
55531167Sminshall 	parms.rc = 0x02;
55631167Sminshall     } else {
55731167Sminshall 	int group = parms.oia_group_number;
55831193Sminshall 	char *from;
55931193Sminshall 	int size;
56031167Sminshall 
56131211Sminshall 	if ((group != API_OIA_ALL_GROUPS) &&
56231211Sminshall 		((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
56331193Sminshall 	} else {
56431193Sminshall 	    if (group == API_OIA_ALL_GROUPS) {
56531193Sminshall 		size = API_OIA_BYTES_ALL_GROUPS;
56631193Sminshall 		from = (char *)&OperatorInformationArea;
56731193Sminshall 	    } else if (group == API_OIA_INPUT_INHIBITED) {
56831193Sminshall 		size = sizeof OperatorInformationArea.input_inhibited;
56931193Sminshall 		from = (char *)&OperatorInformationArea.input_inhibited[0];
57031193Sminshall 	    } else {
57131193Sminshall 		size = 1;
57231193Sminshall 		from = ((char *)&OperatorInformationArea)+group;
57331193Sminshall 	    }
57431193Sminshall 	    movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
57531193Sminshall 			from, size);
57631168Sminshall 	}
57731167Sminshall     }
57831168Sminshall     parms.function_id = 0x6d;
57931167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
58031158Sminshall }
58131158Sminshall 
58235421Sminshall /*ARGSUSED*/
58331158Sminshall static void
58431158Sminshall unknown_op(regs, sregs)
58531158Sminshall union REGS *regs;
58631158Sminshall struct SREGS *sregs;
58731158Sminshall {
58831158Sminshall     regs->h.ch = 0x12;
58931158Sminshall     regs->h.cl = 0x05;
59031158Sminshall }
59131158Sminshall 
59231158Sminshall 
59331158Sminshall handle_api(regs, sregs)
59431158Sminshall union REGS *regs;
59531158Sminshall struct SREGS *sregs;
59631158Sminshall {
597*38924Sminshall /*
598*38924Sminshall  * Do we need to log this transaction?
599*38924Sminshall  */
600*38924Sminshall     if (apitrace) {
601*38924Sminshall 	Dump('<', (char *)regs, sizeof *regs);
602*38924Sminshall 	Dump('<', (char *)sregs, sizeof *sregs);
603*38924Sminshall     }
60431158Sminshall     if (regs->h.ah == NAME_RESOLUTION) {
60531158Sminshall 	name_resolution(regs, sregs);
60631517Sminshall #if	defined(unix)
60731517Sminshall     } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
60831517Sminshall 	while ((oia_modified == 0) && (ps_modified == 0)) {
60931517Sminshall 	    (void) Scheduler(1);
61031517Sminshall 	}
61131517Sminshall 	oia_modified = ps_modified = 0;
61231517Sminshall #endif	/* defined(unix) */
61331168Sminshall     } else if (regs->h.ah != 0x09) {
61431168Sminshall 	regs->h.ch = 0x12;
61531168Sminshall 	regs->h.cl = 0x0f;		/* XXX Invalid environmental access */
61631168Sminshall     } else if (regs->x.bx != 0x8020) {
61731168Sminshall 	regs->h.ch = 0x12;
61831168Sminshall 	regs->h.cl = 0x08;		/* XXX Invalid wait specified */
61931168Sminshall     } else if (regs->h.ch != 0) {
62031211Sminshall 	regs->x.cx = 0x1206;		/* XXX Invalid priority */
62131158Sminshall     } else {
62231158Sminshall 	switch (regs->x.dx) {
62331158Sminshall 	case GATE_SESSMGR:
62431158Sminshall 	    switch (regs->h.al) {
62531158Sminshall 	    case QUERY_SESSION_ID:
62631168Sminshall 		if (regs->h.cl != 0) {
62731211Sminshall 		    regs->x.cx = 0x1206;
62831168Sminshall 		} else {
62931211Sminshall 		    regs->x.cx = 0x1200;
63031168Sminshall 		    query_session_id(regs, sregs);
63131168Sminshall 		}
63231158Sminshall 		break;
63331211Sminshall 	    case QUERY_SESSION_PARAMETERS:
63431168Sminshall 		if (regs->h.cl != 0) {
63531211Sminshall 		    regs->x.cx = 0x1206;
63631168Sminshall 		} else {
63731211Sminshall 		    regs->x.cx = 0x1200;
63831193Sminshall 		    query_session_parameters(regs, sregs);
63931168Sminshall 		}
64031158Sminshall 		break;
64131158Sminshall 	    case QUERY_SESSION_CURSOR:
64231168Sminshall 		if (regs->h.cl != 0xff) {
64331211Sminshall 		    regs->x.cx = 0x1206;
64431168Sminshall 		} else {
64531211Sminshall 		    regs->x.cx = 0x1200;
64631168Sminshall 		    query_session_cursor(regs, sregs);
64731168Sminshall 		}
64831158Sminshall 		break;
64931158Sminshall 	    default:
65031158Sminshall 		unknown_op(regs, sregs);
65131158Sminshall 		break;
65231158Sminshall 	    }
65331158Sminshall 	    break;
65431158Sminshall 	case GATE_KEYBOARD:
65531168Sminshall 	    if (regs->h.cl != 00) {
65631211Sminshall 		regs->x.cx = 0x1206;
65731168Sminshall 	    } else {
65831211Sminshall 		regs->x.cx = 0x1200;
65931168Sminshall 		switch (regs->h.al) {
66031168Sminshall 		case CONNECT_TO_KEYBOARD:
66131168Sminshall 		    connect_to_keyboard(regs, sregs);
66231168Sminshall 		    break;
66331168Sminshall 		case DISABLE_INPUT:
66431168Sminshall 		    disable_input(regs, sregs);
66531168Sminshall 		    break;
66631168Sminshall 		case WRITE_KEYSTROKE:
66731168Sminshall 		    write_keystroke(regs, sregs);
66831168Sminshall 		    break;
66931168Sminshall 		case ENABLE_INPUT:
67031168Sminshall 		    enable_input(regs, sregs);
67131168Sminshall 		    break;
67231168Sminshall 		case DISCONNECT_FROM_KEYBOARD:
67331168Sminshall 		    disconnect_from_keyboard(regs, sregs);
67431168Sminshall 		    break;
67531168Sminshall 		default:
67631168Sminshall 		    unknown_op(regs, sregs);
67731168Sminshall 		    break;
67831168Sminshall 		}
67931158Sminshall 	    }
68031158Sminshall 	    break;
68131158Sminshall 	case GATE_COPY:
68231168Sminshall 	    if (regs->h.cl != 0xff) {
68331211Sminshall 		regs->x.cx = 0x1206;
68431168Sminshall 	    } else {
68531211Sminshall 		regs->x.cx = 0x1200;
68631168Sminshall 		switch (regs->h.al) {
68731168Sminshall 		case COPY_STRING:
68831168Sminshall 		    copy_string(regs, sregs);
68931168Sminshall 		    break;
69031168Sminshall 		default:
69131168Sminshall 		    unknown_op(regs, sregs);
69231168Sminshall 		    break;
69331168Sminshall 		}
69431158Sminshall 	    }
69531158Sminshall 	    break;
69631158Sminshall 	case GATE_OIAM:
69731168Sminshall 	    if (regs->h.cl != 0xff) {
69831211Sminshall 		regs->x.cx = 0x1206;
69931168Sminshall 	    } else {
70031211Sminshall 		regs->x.cx = 0x1200;
70131168Sminshall 		switch (regs->h.al) {
70231168Sminshall 		case READ_OIA_GROUP:
70331168Sminshall 		    read_oia_group(regs, sregs);
70431168Sminshall 		    break;
70531168Sminshall 		default:
70631168Sminshall 		    unknown_op(regs, sregs);
70731168Sminshall 		    break;
70831168Sminshall 		}
70931158Sminshall 	    }
71031158Sminshall 	    break;
71131158Sminshall 	default:
71231168Sminshall 	    regs->h.ch = 0x12;
71331168Sminshall 	    regs->h.cl = 0x34;		/* Invalid GATE entry */
71431158Sminshall 	    break;
71531158Sminshall 	}
71631158Sminshall     }
717*38924Sminshall /*
718*38924Sminshall  * Do we need to log this transaction?
719*38924Sminshall  */
720*38924Sminshall     if (apitrace) {
721*38924Sminshall 	Dump('>', (char *)regs, sizeof *regs);
722*38924Sminshall 	Dump('>', (char *)sregs, sizeof *sregs);
723*38924Sminshall     }
72431158Sminshall }
725