xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 39468)
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*39468Sminshall static char sccsid[] = "@(#)api.c	4.4 (Berkeley) 10/31/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*39468Sminshall int apitrace = 0;
4038924Sminshall 
4131158Sminshall /*
42*39468Sminshall  * Some defines for things we use internally.
43*39468Sminshall  */
44*39468Sminshall 
45*39468Sminshall #define	PS_SESSION_ID	23
46*39468Sminshall #define	BUF_SESSION_ID	0
47*39468Sminshall 
48*39468Sminshall /*
4931193Sminshall  * General utility routines.
5031193Sminshall  */
5131193Sminshall 
5231193Sminshall #if	defined(MSDOS)
5331193Sminshall 
5431211Sminshall #if	defined(LINT_ARGS)
5531211Sminshall static void movetous(char *, int, int, int);
5631211Sminshall static void movetothem(int, int, char *, int);
5731211Sminshall #endif	/* defined(LINT_ARGS) */
5831211Sminshall 
5931507Sminshall #define	access_api(foo,length,copyin)	(foo)
6031507Sminshall #define	unaccess_api(foo,goo,length,copyout)
6131226Sminshall 
6231193Sminshall static void
6331193Sminshall movetous(parms, es, di, length)
6431193Sminshall char *parms;
6535421Sminshall int es, di;
6635421Sminshall int length;
6731193Sminshall {
6831211Sminshall     char far *farparms = parms;
6931193Sminshall 
7035421Sminshall     movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length);
7138924Sminshall     if (apitrace) {
7238924Sminshall 	Dump('(', parms, length);
7338924Sminshall     }
7431193Sminshall }
7531193Sminshall 
7631193Sminshall static void
7731211Sminshall movetothem(es, di, parms, length)
7831211Sminshall int es, di;
7931211Sminshall char *parms;
8031211Sminshall int length;
8131193Sminshall {
8231211Sminshall     char far *farparms = parms;
8331193Sminshall 
8435421Sminshall     movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length);
8538924Sminshall     if (apitrace) {
8638924Sminshall 	Dump(')', parms, length);
8738924Sminshall     }
8831193Sminshall }
8931193Sminshall #endif	/* defined(MSDOS) */
9031193Sminshall 
9131226Sminshall #if	defined(unix)
9235421Sminshall extern char *access_api();
9335421Sminshall extern void movetous(), movetothem(), unaccess_api();
9431226Sminshall #endif	/* defined(unix) */
9531226Sminshall 
9631470Sminshall 
9731193Sminshall /*
9831158Sminshall  * Supervisor Services.
9931158Sminshall  */
10031158Sminshall 
10131158Sminshall static void
10231193Sminshall name_resolution(regs, sregs)
10331158Sminshall union REGS *regs;
10431158Sminshall struct SREGS *sregs;
10531158Sminshall {
10631167Sminshall     NameResolveParms parms;
10731161Sminshall 
10831167Sminshall     movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
10931161Sminshall 
11031161Sminshall     regs->h.cl = 0;
11131193Sminshall     if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
11231161Sminshall 	regs->x.dx = GATE_SESSMGR;
11331193Sminshall     } else if (memcmp((char *)&parms, NAME_KEYBOARD,
11431193Sminshall 					sizeof parms.gate_name) == 0) {
11531161Sminshall 	regs->x.dx = GATE_KEYBOARD;
11631193Sminshall     } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
11731161Sminshall 	regs->x.dx = GATE_COPY;
11831193Sminshall     } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
11931161Sminshall 	regs->x.dx = GATE_OIAM;
12031161Sminshall     } else {
12131161Sminshall 	regs->h.cl = 0x2e;	/* Name not found */
12231161Sminshall     }
12331161Sminshall     regs->h.ch = 0x12;
12431161Sminshall     regs->h.bh = 7;
12531158Sminshall }
12631158Sminshall 
12731158Sminshall /*
12831158Sminshall  * Session Information Services.
12931158Sminshall  */
13031158Sminshall 
13131158Sminshall static void
13231158Sminshall query_session_id(regs, sregs)
13331158Sminshall union REGS *regs;
13431158Sminshall struct SREGS *sregs;
13531158Sminshall {
13631167Sminshall     QuerySessionIdParms parms;
13731161Sminshall 
13831167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
13931161Sminshall 
14031211Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
14131211Sminshall 	parms.rc = 0x0c;
14231211Sminshall     } else if (parms.option_code != 0x01) {
14331211Sminshall 	parms.rc = 0x0d;	/* Invalid option code */
144*39468Sminshall #ifdef	NOTOBS
145*39468Sminshall     } else if ((parms.data_code != 0x45) && (parms.data_code != 0x00/*OBS*/)) {
14631211Sminshall 	parms.rc = 0x0b;
147*39468Sminshall #endif	/* NOTOBS */
14831161Sminshall     } else {
14931168Sminshall 	NameArray list;
15031167Sminshall 
15131167Sminshall 	movetous((char *)&list, FP_SEG(parms.name_array),
15235421Sminshall 		    FP_OFF(parms.name_array), sizeof list);
15331168Sminshall 	if ((list.length < 14) || (list.length > 170)) {
15431167Sminshall 	    parms.rc = 0x12;
15531161Sminshall 	} else {
15631167Sminshall 	    list.number_matching_session = 1;
15731167Sminshall 	    list.name_array_element.short_name = parms.data_code;
15831167Sminshall 	    list.name_array_element.type = TYPE_DFT;
159*39468Sminshall 	    list.name_array_element.session_id = PS_SESSION_ID;
16031167Sminshall 	    memcpy(list.name_array_element.long_name, "ONLYSESS",
16131167Sminshall 			    sizeof list.name_array_element.long_name);
16231167Sminshall 	    movetothem(FP_SEG(parms.name_array),
16331193Sminshall 		FP_OFF(parms.name_array), (char *)&list, sizeof list);
16431167Sminshall 	    parms.rc = 0;
16531161Sminshall 	}
16631161Sminshall     }
16731211Sminshall     parms.function_id = 0x6b;
16831167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
16931158Sminshall }
17031158Sminshall 
17131158Sminshall static void
17231158Sminshall query_session_parameters(regs, sregs)
17331158Sminshall union REGS *regs;
17431158Sminshall struct SREGS *sregs;
17531158Sminshall {
17631167Sminshall     QuerySessionParametersParms parms;
17731167Sminshall 
17831167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
17931167Sminshall 
18031168Sminshall     if ((parms.rc !=0) || (parms.function_id != 0)) {
18131211Sminshall 	parms.rc = 0x0c;
182*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
18331211Sminshall 	parms.rc = 0x02;
18431167Sminshall     } else {
18531211Sminshall 	parms.rc = 0;
18631167Sminshall 	parms.session_type = TYPE_DFT;
18731167Sminshall 	parms.session_characteristics = 0;	/* Neither EAB nor PSS */
18831167Sminshall 	parms.rows = MaxNumberLines;
18931167Sminshall 	parms.columns = MaxNumberColumns;
19031167Sminshall 	parms.presentation_space = 0;
19131167Sminshall     }
19231211Sminshall     parms.function_id = 0x6b;
19331168Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
19431158Sminshall }
19531158Sminshall 
19631158Sminshall static void
19731158Sminshall query_session_cursor(regs, sregs)
19831158Sminshall union REGS *regs;
19931158Sminshall struct SREGS *sregs;
20031158Sminshall {
20131167Sminshall     QuerySessionCursorParms parms;
20231167Sminshall 
20331167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
20431167Sminshall 
20531167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
20631167Sminshall 	parms.rc = 0x0c;
207*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
20831167Sminshall 	parms.rc = 0x02;
20931167Sminshall     } else {
21031167Sminshall 	parms.rc = 0;
21131167Sminshall 	parms.cursor_type = CURSOR_BLINKING;	/* XXX what is inhibited? */
21231167Sminshall 	parms.row_address = ScreenLine(CursorAddress);
21331167Sminshall 	parms.column_address = ScreenLineOffset(CursorAddress);
21431167Sminshall     }
21531167Sminshall 
21631211Sminshall     parms.function_id = 0x6b;
21731211Sminshall     movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
21831158Sminshall }
21931158Sminshall 
22031158Sminshall /*
22131158Sminshall  * Keyboard Services.
22231158Sminshall  */
22331158Sminshall 
22431158Sminshall 
22531158Sminshall static void
22631158Sminshall connect_to_keyboard(regs, sregs)
22731158Sminshall union REGS *regs;
22831158Sminshall struct SREGS *sregs;
22931158Sminshall {
23031167Sminshall     ConnectToKeyboardParms parms;
23131167Sminshall 
23231183Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
23331167Sminshall 
23431167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
23531167Sminshall 	parms.rc = 0x0c;
236*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
23731167Sminshall 	parms.rc = 0x02;
23831167Sminshall     } else if (parms.intercept_options != 0) {
23931167Sminshall 	parms.rc = 0x01;
24031167Sminshall     } else {
24131167Sminshall 	parms.rc = 0;
24231167Sminshall 	parms.first_connection_identifier = 0;
24331167Sminshall     }
24431167Sminshall     parms.function_id = 0x62;
24531167Sminshall 
24631167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
24731158Sminshall }
24831158Sminshall 
24931158Sminshall static void
25031167Sminshall disconnect_from_keyboard(regs, sregs)
25131158Sminshall union REGS *regs;
25231158Sminshall struct SREGS *sregs;
25331158Sminshall {
25431167Sminshall     DisconnectFromKeyboardParms parms;
25531167Sminshall 
25631167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
25731167Sminshall 
25831167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
25931167Sminshall 	parms.rc = 0x0c;
260*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
26131167Sminshall 	parms.rc = 0x02;
26231167Sminshall     } else if (parms.connectors_task_id != 0) {
26331167Sminshall 	parms.rc = 04;			/* XXX */
26431167Sminshall     } else {
26531167Sminshall 	parms.rc = 0;
26631167Sminshall     }
26731167Sminshall     parms.function_id = 0x62;
26831167Sminshall 
26931167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
27031158Sminshall }
27131158Sminshall 
27231158Sminshall static void
27331158Sminshall write_keystroke(regs, sregs)
27431158Sminshall union REGS *regs;
27531158Sminshall struct SREGS *sregs;
27631158Sminshall {
27731198Sminshall     WriteKeystrokeParms parms;
27831198Sminshall 
27931198Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
28031198Sminshall 
28131198Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
28231198Sminshall 	parms.rc = 0x0c;
283*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
28431198Sminshall 	parms.rc = 0x02;
28531198Sminshall     } else if (parms.connectors_task_id != 0) {
28631198Sminshall 	parms.rc = 0x04;
28731198Sminshall     } else {
28831198Sminshall 	parms.number_of_keys_sent = 0;
28931198Sminshall 	parms.rc = 0;
29031198Sminshall 	if (parms.options == OPTION_SINGLE_KEYSTROKE) {
29131198Sminshall 	    KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
29231198Sminshall 
29331198Sminshall 	    if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
29431198Sminshall 		parms.rc = 0x10;		/* XXX needs 0x12 too! */
29531198Sminshall 	    }
29631198Sminshall 	    parms.number_of_keys_sent++;
29731198Sminshall 	} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
29831198Sminshall 	    KeystrokeList
29931198Sminshall 		list,
30031198Sminshall 		far *atlist = parms.keystroke_specifier.keystroke_list;
30131198Sminshall 	    KeystrokeEntry
30231198Sminshall 		entry[10],		/* 10 at a time */
30331198Sminshall 		*ourentry,
30431198Sminshall 		far *theirentry;
30531198Sminshall 	    int
30631198Sminshall 		todo;
30731198Sminshall 
30831198Sminshall 	    movetous((char *)&list, FP_SEG(atlist),
30935421Sminshall 			FP_OFF(atlist), sizeof *atlist);
31031198Sminshall 	    todo = list.length/2;
31131198Sminshall 	    ourentry = entry+(highestof(entry)+1);
31235421Sminshall 	    theirentry = &atlist->keystrokes;
31331198Sminshall 
31431198Sminshall 	    while (todo) {
31531198Sminshall 		if (ourentry > &entry[highestof(entry)]) {
31631198Sminshall 		    int thistime;
31731198Sminshall 
31831198Sminshall 		    thistime = todo;
31931198Sminshall 		    if (thistime > numberof(entry)) {
32031198Sminshall 			thistime = numberof(entry);
32131198Sminshall 		    }
32231198Sminshall 		    movetous((char *)entry, FP_SEG(theirentry),
32331198Sminshall 			    FP_OFF(theirentry), thistime*sizeof *theirentry);
32431198Sminshall 		    theirentry += thistime;
32531198Sminshall 		    ourentry = entry;
32631198Sminshall 		}
32731198Sminshall 		if (AcceptKeystroke(ourentry->scancode,
32831198Sminshall 						ourentry->shift_state) == 0) {
32931198Sminshall 		    parms.rc = 0x10;		/* XXX needs 0x12 too! */
33031198Sminshall 		    break;
33131198Sminshall 		}
33231198Sminshall 		parms.number_of_keys_sent++;
33331198Sminshall 		ourentry++;
33431198Sminshall 		todo--;
33531198Sminshall 	    }
33631198Sminshall 	} else {
33731198Sminshall 	    parms.rc = 0x01;
33831198Sminshall 	}
33931198Sminshall     }
34031198Sminshall     parms.function_id = 0x62;
34131198Sminshall 
34231198Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
34331167Sminshall /* XXX */
34431158Sminshall }
34531158Sminshall 
34631167Sminshall 
34731158Sminshall static void
34831167Sminshall disable_input(regs, sregs)
34931167Sminshall union REGS *regs;
35031167Sminshall struct SREGS *sregs;
35131167Sminshall {
35231167Sminshall     DisableInputParms parms;
35331167Sminshall 
35431167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
35531167Sminshall 
35631167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
35731167Sminshall 	parms.rc = 0x0c;
358*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
35931167Sminshall 	parms.rc = 0x02;
36031167Sminshall     } else if (parms.connectors_task_id != 0) {
36131167Sminshall 	parms.rc = 0x04;
36231167Sminshall     } else {
36331211Sminshall 	SetOiaApiInhibit(&OperatorInformationArea);
36431167Sminshall 	parms.rc = 0;
36531167Sminshall     }
36631167Sminshall     parms.function_id = 0x62;
36731167Sminshall 
36831167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
36931167Sminshall }
37031167Sminshall 
37131167Sminshall static void
37231158Sminshall enable_input(regs, sregs)
37331158Sminshall union REGS *regs;
37431158Sminshall struct SREGS *sregs;
37531158Sminshall {
37631167Sminshall     EnableInputParms parms;
37731167Sminshall 
37831167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
37931167Sminshall 
38031167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
38131167Sminshall 	parms.rc = 0x0c;
382*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
38331167Sminshall 	parms.rc = 0x02;
38431167Sminshall     } else if (parms.connectors_task_id != 0) {
38531167Sminshall 	parms.rc = 0x04;
38631167Sminshall     } else {
38731211Sminshall 	ResetOiaApiInhibit(&OperatorInformationArea);
38831167Sminshall 	parms.rc = 0;
38931167Sminshall     }
39031167Sminshall     parms.function_id = 0x62;
39131167Sminshall 
39231167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
39331158Sminshall }
39431158Sminshall 
39531158Sminshall /*
39631158Sminshall  * Copy Services.
39731158Sminshall  */
39831158Sminshall 
39931507Sminshall static
40031507Sminshall copy_subroutine(target, source, parms, what_is_user, length)
40131226Sminshall BufferDescriptor *target, *source;
40231226Sminshall CopyStringParms *parms;
40331226Sminshall int what_is_user;
40431226Sminshall #define	USER_IS_TARGET	0
40531226Sminshall #define	USER_IS_SOURCE	1
40631226Sminshall {
40731226Sminshall #define	TARGET_NO_EAB		1
40831226Sminshall #define	SOURCE_NO_EAB		2
40931226Sminshall #define	TARGET_PC		4
41031226Sminshall #define	SOURCE_PC		8
41131226Sminshall #define	NO_FIELD_ATTRIBUTES	16
41231226Sminshall     int needtodo = 0;
41331226Sminshall     int access_length;
41431226Sminshall     char far *input;
41531226Sminshall     char far *output;
41631226Sminshall     char far *access_pointer;
41731226Sminshall 
41831226Sminshall     if ((target->characteristics^source->characteristics)
41931226Sminshall 		    &CHARACTERISTIC_EAB) {
42031226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
42131226Sminshall 	    needtodo |= TARGET_NO_EAB;	/* Need to bump for EAB in target */
42231226Sminshall 	} else {
42331226Sminshall 	    needtodo |= SOURCE_NO_EAB;	/* Need to bump for EAB in source */
42431226Sminshall 	}
42531226Sminshall     }
42631226Sminshall     if (target->session_type != source->session_type) {
42731226Sminshall 	if (target->session_type == TYPE_PC) {
42831226Sminshall 	    needtodo |= TARGET_PC;	/* scan codes to PC */
42931226Sminshall 	} else {
43031226Sminshall 	    needtodo |= SOURCE_PC;	/* PC to scan codes */
43131226Sminshall 	}
43231226Sminshall     }
43331226Sminshall     if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
43431226Sminshall 	needtodo |= NO_FIELD_ATTRIBUTES;
43531226Sminshall     }
43631507Sminshall     access_length = length;
43731226Sminshall     if (what_is_user == USER_IS_TARGET) {
43831226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
43931226Sminshall 	    access_length *= 2;
44031226Sminshall 	}
44131226Sminshall 	input = (char far *) &Host[source->begin];
44231226Sminshall 	access_pointer = target->buffer;
44331507Sminshall 	output = access_api(target->buffer, access_length, 0);
44431226Sminshall     } else {
44531226Sminshall 	if (source->characteristics&CHARACTERISTIC_EAB) {
44631226Sminshall 	    access_length *= 2;
44731226Sminshall 	}
44831226Sminshall 	access_pointer = source->buffer;
44931507Sminshall 	input = access_api(source->buffer, access_length, 1);
45031226Sminshall 	output = (char far *) &Host[target->begin];
45131226Sminshall     }
45231226Sminshall     while (length--) {
45331226Sminshall 	if (needtodo&TARGET_PC) {
45431226Sminshall 	    *output++ = disp_asc[*input++];
45531226Sminshall 	} else if (needtodo&SOURCE_PC) {
45631226Sminshall 	    *output++ = asc_disp[*input++];
45731226Sminshall 	} else {
45831226Sminshall 	    *output++ = *input++;
45931226Sminshall 	}
46031226Sminshall 	if (needtodo&TARGET_NO_EAB) {
46135421Sminshall 	    input++;
46231226Sminshall 	} else if (needtodo&SOURCE_NO_EAB) {
46331226Sminshall 	    *output++ = 0;		/* Should figure out good EAB? */
46431226Sminshall 	}
46531226Sminshall     }
46631226Sminshall     if (what_is_user == USER_IS_TARGET) {
46731507Sminshall 	unaccess_api(target->buffer, access_pointer, access_length, 1);
46831226Sminshall     } else {
46931507Sminshall 	unaccess_api(source->buffer, access_pointer, access_length, 0);
47031226Sminshall     }
47131226Sminshall }
47231226Sminshall 
47331226Sminshall 
47431158Sminshall static void
47531167Sminshall copy_string(regs, sregs)
47631158Sminshall union REGS *regs;
47731158Sminshall struct SREGS *sregs;
47831158Sminshall {
47931167Sminshall     CopyStringParms parms;
48031226Sminshall     BufferDescriptor *target = &parms.target, *source = &parms.source;
48131226Sminshall     int length;
48231167Sminshall 
48331167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
48431167Sminshall 
48531507Sminshall     length = 1+parms.source_end-source->begin;
48631167Sminshall     if ((parms.rc != 0) || (parms.function_id !=0)) {
48731167Sminshall 	parms.rc = 0x0c;
488*39468Sminshall     } else if (target->session_id == BUF_SESSION_ID) {	/* Target is buffer */
489*39468Sminshall 	if (source->session_id != PS_SESSION_ID) {		/* A no-no */
49031226Sminshall 	    parms.rc = 0x2;
49131226Sminshall 	} else {
49231507Sminshall 	    if ((source->begin < 0) || (source->begin > highestof(Host))) {
49331507Sminshall 		parms.rc = 0x06;		/* invalid source definition */
49431507Sminshall 	    } else {
49531507Sminshall 		if ((source->begin+length) > highestof(Host)) {
49631507Sminshall 		    length = highestof(Host)-source->begin;
49731507Sminshall 		    parms.rc = 0x0f;	/* Truncate */
49831507Sminshall 		}
49931507Sminshall 	        if ((source->characteristics == target->characteristics) &&
50031226Sminshall 		    (source->session_type == target->session_type)) {
50131507Sminshall 		    if (source->characteristics&CHARACTERISTIC_EAB) {
50231507Sminshall 			length *= 2;
50331507Sminshall 		    }
50435421Sminshall 		    movetothem(FP_SEG(target->buffer),
50535421Sminshall 			    FP_OFF(target->buffer),
50631507Sminshall 			    (char *)&Host[source->begin], length);
50731507Sminshall 		} else {
50831507Sminshall 		    copy_subroutine(target, source, &parms,
50931507Sminshall 							USER_IS_TARGET, length);
51031226Sminshall 		}
51131226Sminshall 	    }
51231226Sminshall 	}
513*39468Sminshall     } else if (source->session_id != BUF_SESSION_ID) {
51431226Sminshall 	    parms.rc = 0xd;
51531226Sminshall     } else {
51638210Sminshall 	/* Send to presentation space (3270 buffer) */
51738210Sminshall 	if ((target->begin < 0) || (target->begin > highestof(Host))) {
51838210Sminshall 	    parms.rc = 0x07;		/* invalid target definition */
51938210Sminshall 	} if (!UnLocked) {
52038210Sminshall 		parms.rc = 0x03;	/* Keyboard locked */
52138210Sminshall 	} else if (parms.copy_mode != 0) {
52238210Sminshall 		parms.rc = 0x0f;	/* Copy of field attr's not allowed */
52338210Sminshall 	} else if (IsProtected(target->begin) || /* Make sure no protected */
52438210Sminshall 		    (WhereAttrByte(target->begin) !=	/* in range */
52538210Sminshall 			    WhereAttrByte(target->begin+length-1))) {
52638210Sminshall 		parms.rc = 0x0e;	/* Attempt to write in protected */
52731507Sminshall 	} else {
52838210Sminshall 	    if ((target->begin+length) > highestof(Host)) {
52938210Sminshall 		length = highestof(Host)-target->begin;
53031507Sminshall 		parms.rc = 0x0f;	/* Truncate */
53131226Sminshall 	    }
53238210Sminshall 	    TurnOnMdt(target->begin);	/* Things have changed */
53331507Sminshall 	    if ((source->characteristics == target->characteristics) &&
53431507Sminshall 		    (source->session_type == target->session_type)) {
53531507Sminshall 		if (source->characteristics&CHARACTERISTIC_EAB) {
53631507Sminshall 		    length *= 2;
53731507Sminshall 		}
53831507Sminshall 		movetous((char *)&Host[target->begin],
53935421Sminshall 			    FP_SEG(source->buffer),
54035421Sminshall 			    FP_OFF(source->buffer), length);
54131507Sminshall 	    } else {
54231507Sminshall 		copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
54331507Sminshall 	    }
54431226Sminshall 	}
54531167Sminshall     }
546*39468Sminshall     parms.function_id = 0x64;
54731183Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
54831158Sminshall }
549*39468Sminshall 
550*39468Sminshall 
55131158Sminshall /*
55231158Sminshall  * Operator Information Area Services.
55331158Sminshall  */
55431158Sminshall 
55531158Sminshall static void
55631158Sminshall read_oia_group(regs, sregs)
55731158Sminshall union REGS *regs;
55831158Sminshall struct SREGS *sregs;
55931158Sminshall {
56031167Sminshall     ReadOiaGroupParms parms;
56131167Sminshall 
56231167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
56331167Sminshall 
56431167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
56531167Sminshall 	parms.rc = 0x0c;
566*39468Sminshall     } else if (parms.session_id != PS_SESSION_ID) {
56731167Sminshall 	parms.rc = 0x02;
56831167Sminshall     } else {
56931167Sminshall 	int group = parms.oia_group_number;
57031193Sminshall 	char *from;
57131193Sminshall 	int size;
57231167Sminshall 
57331211Sminshall 	if ((group != API_OIA_ALL_GROUPS) &&
57431211Sminshall 		((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
57531193Sminshall 	} else {
57631193Sminshall 	    if (group == API_OIA_ALL_GROUPS) {
57731193Sminshall 		size = API_OIA_BYTES_ALL_GROUPS;
57831193Sminshall 		from = (char *)&OperatorInformationArea;
57931193Sminshall 	    } else if (group == API_OIA_INPUT_INHIBITED) {
58031193Sminshall 		size = sizeof OperatorInformationArea.input_inhibited;
58131193Sminshall 		from = (char *)&OperatorInformationArea.input_inhibited[0];
58231193Sminshall 	    } else {
58331193Sminshall 		size = 1;
58431193Sminshall 		from = ((char *)&OperatorInformationArea)+group;
58531193Sminshall 	    }
58631193Sminshall 	    movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
58731193Sminshall 			from, size);
58831168Sminshall 	}
58931167Sminshall     }
59031168Sminshall     parms.function_id = 0x6d;
59131167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
59231158Sminshall }
59331158Sminshall 
59435421Sminshall /*ARGSUSED*/
59531158Sminshall static void
59631158Sminshall unknown_op(regs, sregs)
59731158Sminshall union REGS *regs;
59831158Sminshall struct SREGS *sregs;
59931158Sminshall {
60031158Sminshall     regs->h.ch = 0x12;
60131158Sminshall     regs->h.cl = 0x05;
60231158Sminshall }
60331158Sminshall 
60431158Sminshall 
60531158Sminshall handle_api(regs, sregs)
60631158Sminshall union REGS *regs;
60731158Sminshall struct SREGS *sregs;
60831158Sminshall {
60938924Sminshall /*
61038924Sminshall  * Do we need to log this transaction?
61138924Sminshall  */
61238924Sminshall     if (apitrace) {
61338924Sminshall 	Dump('<', (char *)regs, sizeof *regs);
61438924Sminshall 	Dump('<', (char *)sregs, sizeof *sregs);
61538924Sminshall     }
61631158Sminshall     if (regs->h.ah == NAME_RESOLUTION) {
61731158Sminshall 	name_resolution(regs, sregs);
61831517Sminshall #if	defined(unix)
61931517Sminshall     } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
62031517Sminshall 	while ((oia_modified == 0) && (ps_modified == 0)) {
62131517Sminshall 	    (void) Scheduler(1);
62231517Sminshall 	}
62331517Sminshall 	oia_modified = ps_modified = 0;
62431517Sminshall #endif	/* defined(unix) */
62531168Sminshall     } else if (regs->h.ah != 0x09) {
62631168Sminshall 	regs->h.ch = 0x12;
62731168Sminshall 	regs->h.cl = 0x0f;		/* XXX Invalid environmental access */
62831168Sminshall     } else if (regs->x.bx != 0x8020) {
62931168Sminshall 	regs->h.ch = 0x12;
63031168Sminshall 	regs->h.cl = 0x08;		/* XXX Invalid wait specified */
63131168Sminshall     } else if (regs->h.ch != 0) {
63231211Sminshall 	regs->x.cx = 0x1206;		/* XXX Invalid priority */
63331158Sminshall     } else {
63431158Sminshall 	switch (regs->x.dx) {
63531158Sminshall 	case GATE_SESSMGR:
63631158Sminshall 	    switch (regs->h.al) {
63731158Sminshall 	    case QUERY_SESSION_ID:
63831168Sminshall 		if (regs->h.cl != 0) {
63931211Sminshall 		    regs->x.cx = 0x1206;
64031168Sminshall 		} else {
64131211Sminshall 		    regs->x.cx = 0x1200;
64231168Sminshall 		    query_session_id(regs, sregs);
64331168Sminshall 		}
64431158Sminshall 		break;
64531211Sminshall 	    case QUERY_SESSION_PARAMETERS:
64631168Sminshall 		if (regs->h.cl != 0) {
64731211Sminshall 		    regs->x.cx = 0x1206;
64831168Sminshall 		} else {
64931211Sminshall 		    regs->x.cx = 0x1200;
65031193Sminshall 		    query_session_parameters(regs, sregs);
65131168Sminshall 		}
65231158Sminshall 		break;
65331158Sminshall 	    case QUERY_SESSION_CURSOR:
654*39468Sminshall 		if ((regs->h.cl != 0xff) && (regs->h.cl != 0x00/*OBS*/)) {
65531211Sminshall 		    regs->x.cx = 0x1206;
65631168Sminshall 		} else {
65731211Sminshall 		    regs->x.cx = 0x1200;
65831168Sminshall 		    query_session_cursor(regs, sregs);
65931168Sminshall 		}
66031158Sminshall 		break;
66131158Sminshall 	    default:
66231158Sminshall 		unknown_op(regs, sregs);
66331158Sminshall 		break;
66431158Sminshall 	    }
66531158Sminshall 	    break;
66631158Sminshall 	case GATE_KEYBOARD:
66731168Sminshall 	    if (regs->h.cl != 00) {
66831211Sminshall 		regs->x.cx = 0x1206;
66931168Sminshall 	    } else {
67031211Sminshall 		regs->x.cx = 0x1200;
67131168Sminshall 		switch (regs->h.al) {
67231168Sminshall 		case CONNECT_TO_KEYBOARD:
67331168Sminshall 		    connect_to_keyboard(regs, sregs);
67431168Sminshall 		    break;
67531168Sminshall 		case DISABLE_INPUT:
67631168Sminshall 		    disable_input(regs, sregs);
67731168Sminshall 		    break;
67831168Sminshall 		case WRITE_KEYSTROKE:
67931168Sminshall 		    write_keystroke(regs, sregs);
68031168Sminshall 		    break;
68131168Sminshall 		case ENABLE_INPUT:
68231168Sminshall 		    enable_input(regs, sregs);
68331168Sminshall 		    break;
68431168Sminshall 		case DISCONNECT_FROM_KEYBOARD:
68531168Sminshall 		    disconnect_from_keyboard(regs, sregs);
68631168Sminshall 		    break;
68731168Sminshall 		default:
68831168Sminshall 		    unknown_op(regs, sregs);
68931168Sminshall 		    break;
69031168Sminshall 		}
69131158Sminshall 	    }
69231158Sminshall 	    break;
69331158Sminshall 	case GATE_COPY:
69431168Sminshall 	    if (regs->h.cl != 0xff) {
69531211Sminshall 		regs->x.cx = 0x1206;
69631168Sminshall 	    } else {
69731211Sminshall 		regs->x.cx = 0x1200;
69831168Sminshall 		switch (regs->h.al) {
69931168Sminshall 		case COPY_STRING:
70031168Sminshall 		    copy_string(regs, sregs);
70131168Sminshall 		    break;
70231168Sminshall 		default:
70331168Sminshall 		    unknown_op(regs, sregs);
70431168Sminshall 		    break;
70531168Sminshall 		}
70631158Sminshall 	    }
70731158Sminshall 	    break;
70831158Sminshall 	case GATE_OIAM:
70931168Sminshall 	    if (regs->h.cl != 0xff) {
71031211Sminshall 		regs->x.cx = 0x1206;
71131168Sminshall 	    } else {
71231211Sminshall 		regs->x.cx = 0x1200;
71331168Sminshall 		switch (regs->h.al) {
71431168Sminshall 		case READ_OIA_GROUP:
71531168Sminshall 		    read_oia_group(regs, sregs);
71631168Sminshall 		    break;
71731168Sminshall 		default:
71831168Sminshall 		    unknown_op(regs, sregs);
71931168Sminshall 		    break;
72031168Sminshall 		}
72131158Sminshall 	    }
72231158Sminshall 	    break;
72331158Sminshall 	default:
72431168Sminshall 	    regs->h.ch = 0x12;
72531168Sminshall 	    regs->h.cl = 0x34;		/* Invalid GATE entry */
72631158Sminshall 	    break;
72731158Sminshall 	}
72831158Sminshall     }
72938924Sminshall /*
73038924Sminshall  * Do we need to log this transaction?
73138924Sminshall  */
73238924Sminshall     if (apitrace) {
73338924Sminshall 	Dump('>', (char *)regs, sizeof *regs);
73438924Sminshall 	Dump('>', (char *)sregs, sizeof *sregs);
735*39468Sminshall #ifdef	MSDOS
736*39468Sminshall 	{ char buf[10];  gets(buf); }
737*39468Sminshall #endif	/* MSDOS */
73838924Sminshall     }
73931158Sminshall }
740