xref: /csrg-svn/usr.bin/tn3270/ctlr/api.c (revision 38210)
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*38210Sminshall static char sccsid[] = "@(#)api.c	4.2 (Berkeley) 05/30/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"
34*38210Sminshall #include "hostctlr.h"
3531871Sminshall #include "oia.h"
3631193Sminshall 
3731183Sminshall #include "../general/globals.h"
3831158Sminshall 
3931158Sminshall /*
4031193Sminshall  * General utility routines.
4131193Sminshall  */
4231193Sminshall 
4331193Sminshall #if	defined(MSDOS)
4431193Sminshall 
4531211Sminshall #if	defined(LINT_ARGS)
4631211Sminshall static void movetous(char *, int, int, int);
4731211Sminshall static void movetothem(int, int, char *, int);
4831211Sminshall #endif	/* defined(LINT_ARGS) */
4931211Sminshall 
5031507Sminshall #define	access_api(foo,length,copyin)	(foo)
5131507Sminshall #define	unaccess_api(foo,goo,length,copyout)
5231226Sminshall 
5331193Sminshall static void
5431193Sminshall movetous(parms, es, di, length)
5531193Sminshall char *parms;
5635421Sminshall int es, di;
5735421Sminshall int length;
5831193Sminshall {
5931211Sminshall     char far *farparms = parms;
6031193Sminshall 
6135421Sminshall     movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length);
6231193Sminshall }
6331193Sminshall 
6431193Sminshall static void
6531211Sminshall movetothem(es, di, parms, length)
6631211Sminshall int es, di;
6731211Sminshall char *parms;
6831211Sminshall int length;
6931193Sminshall {
7031211Sminshall     char far *farparms = parms;
7131193Sminshall 
7235421Sminshall     movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length);
7331193Sminshall }
7431193Sminshall #endif	/* defined(MSDOS) */
7531193Sminshall 
7631226Sminshall #if	defined(unix)
7735421Sminshall extern char *access_api();
7835421Sminshall extern void movetous(), movetothem(), unaccess_api();
7931226Sminshall #endif	/* defined(unix) */
8031226Sminshall 
8131470Sminshall 
8231193Sminshall /*
8331158Sminshall  * Supervisor Services.
8431158Sminshall  */
8531158Sminshall 
8631158Sminshall static void
8731193Sminshall name_resolution(regs, sregs)
8831158Sminshall union REGS *regs;
8931158Sminshall struct SREGS *sregs;
9031158Sminshall {
9131167Sminshall     NameResolveParms parms;
9231161Sminshall 
9331167Sminshall     movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
9431161Sminshall 
9531161Sminshall     regs->h.cl = 0;
9631193Sminshall     if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
9731161Sminshall 	regs->x.dx = GATE_SESSMGR;
9831193Sminshall     } else if (memcmp((char *)&parms, NAME_KEYBOARD,
9931193Sminshall 					sizeof parms.gate_name) == 0) {
10031161Sminshall 	regs->x.dx = GATE_KEYBOARD;
10131193Sminshall     } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
10231161Sminshall 	regs->x.dx = GATE_COPY;
10331193Sminshall     } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
10431161Sminshall 	regs->x.dx = GATE_OIAM;
10531161Sminshall     } else {
10631161Sminshall 	regs->h.cl = 0x2e;	/* Name not found */
10731161Sminshall     }
10831161Sminshall     regs->h.ch = 0x12;
10931161Sminshall     regs->h.bh = 7;
11031158Sminshall }
11131158Sminshall 
11231158Sminshall /*
11331158Sminshall  * Session Information Services.
11431158Sminshall  */
11531158Sminshall 
11631158Sminshall static void
11731158Sminshall query_session_id(regs, sregs)
11831158Sminshall union REGS *regs;
11931158Sminshall struct SREGS *sregs;
12031158Sminshall {
12131167Sminshall     QuerySessionIdParms parms;
12231161Sminshall 
12331167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
12431161Sminshall 
12531211Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
12631211Sminshall 	parms.rc = 0x0c;
12731211Sminshall     } else if (parms.option_code != 0x01) {
12831211Sminshall 	parms.rc = 0x0d;	/* Invalid option code */
12931167Sminshall     } else if (parms.data_code != 0x45) {
13031211Sminshall 	parms.rc = 0x0b;
13131161Sminshall     } else {
13231168Sminshall 	NameArray list;
13331167Sminshall 
13431167Sminshall 	movetous((char *)&list, FP_SEG(parms.name_array),
13535421Sminshall 		    FP_OFF(parms.name_array), sizeof list);
13631168Sminshall 	if ((list.length < 14) || (list.length > 170)) {
13731167Sminshall 	    parms.rc = 0x12;
13831161Sminshall 	} else {
13931167Sminshall 	    list.number_matching_session = 1;
14031167Sminshall 	    list.name_array_element.short_name = parms.data_code;
14131167Sminshall 	    list.name_array_element.type = TYPE_DFT;
14231167Sminshall 	    list.name_array_element.session_id = 23;
14331167Sminshall 	    memcpy(list.name_array_element.long_name, "ONLYSESS",
14431167Sminshall 			    sizeof list.name_array_element.long_name);
14531167Sminshall 	    movetothem(FP_SEG(parms.name_array),
14631193Sminshall 		FP_OFF(parms.name_array), (char *)&list, sizeof list);
14731167Sminshall 	    parms.rc = 0;
14831161Sminshall 	}
14931161Sminshall     }
15031211Sminshall     parms.function_id = 0x6b;
15131167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
15231158Sminshall }
15331158Sminshall 
15431158Sminshall static void
15531158Sminshall query_session_parameters(regs, sregs)
15631158Sminshall union REGS *regs;
15731158Sminshall struct SREGS *sregs;
15831158Sminshall {
15931167Sminshall     QuerySessionParametersParms parms;
16031167Sminshall 
16131167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
16231167Sminshall 
16331168Sminshall     if ((parms.rc !=0) || (parms.function_id != 0)) {
16431211Sminshall 	parms.rc = 0x0c;
16531211Sminshall     } else if (parms.session_id != 23) {
16631211Sminshall 	parms.rc = 0x02;
16731167Sminshall     } else {
16831211Sminshall 	parms.rc = 0;
16931167Sminshall 	parms.session_type = TYPE_DFT;
17031167Sminshall 	parms.session_characteristics = 0;	/* Neither EAB nor PSS */
17131167Sminshall 	parms.rows = MaxNumberLines;
17231167Sminshall 	parms.columns = MaxNumberColumns;
17331167Sminshall 	parms.presentation_space = 0;
17431167Sminshall     }
17531211Sminshall     parms.function_id = 0x6b;
17631168Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
17731158Sminshall }
17831158Sminshall 
17931158Sminshall static void
18031158Sminshall query_session_cursor(regs, sregs)
18131158Sminshall union REGS *regs;
18231158Sminshall struct SREGS *sregs;
18331158Sminshall {
18431167Sminshall     QuerySessionCursorParms parms;
18531167Sminshall 
18631167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
18731167Sminshall 
18831167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
18931167Sminshall 	parms.rc = 0x0c;
19031167Sminshall     } else if (parms.session_id != 23) {
19131167Sminshall 	parms.rc = 0x02;
19231167Sminshall     } else {
19331167Sminshall 	parms.rc = 0;
19431167Sminshall 	parms.cursor_type = CURSOR_BLINKING;	/* XXX what is inhibited? */
19531167Sminshall 	parms.row_address = ScreenLine(CursorAddress);
19631167Sminshall 	parms.column_address = ScreenLineOffset(CursorAddress);
19731167Sminshall     }
19831167Sminshall 
19931211Sminshall     parms.function_id = 0x6b;
20031211Sminshall     movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
20131158Sminshall }
20231158Sminshall 
20331158Sminshall /*
20431158Sminshall  * Keyboard Services.
20531158Sminshall  */
20631158Sminshall 
20731158Sminshall 
20831158Sminshall static void
20931158Sminshall connect_to_keyboard(regs, sregs)
21031158Sminshall union REGS *regs;
21131158Sminshall struct SREGS *sregs;
21231158Sminshall {
21331167Sminshall     ConnectToKeyboardParms parms;
21431167Sminshall 
21531183Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
21631167Sminshall 
21731167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
21831167Sminshall 	parms.rc = 0x0c;
21931167Sminshall     } else if (parms.session_id != 23) {
22031167Sminshall 	parms.rc = 0x02;
22131167Sminshall     } else if (parms.intercept_options != 0) {
22231167Sminshall 	parms.rc = 0x01;
22331167Sminshall     } else {
22431167Sminshall 	parms.rc = 0;
22531167Sminshall 	parms.first_connection_identifier = 0;
22631167Sminshall     }
22731167Sminshall     parms.function_id = 0x62;
22831167Sminshall 
22931167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
23031158Sminshall }
23131158Sminshall 
23231158Sminshall static void
23331167Sminshall disconnect_from_keyboard(regs, sregs)
23431158Sminshall union REGS *regs;
23531158Sminshall struct SREGS *sregs;
23631158Sminshall {
23731167Sminshall     DisconnectFromKeyboardParms parms;
23831167Sminshall 
23931167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
24031167Sminshall 
24131167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
24231167Sminshall 	parms.rc = 0x0c;
24331167Sminshall     } else if (parms.session_id != 23) {
24431167Sminshall 	parms.rc = 0x02;
24531167Sminshall     } else if (parms.connectors_task_id != 0) {
24631167Sminshall 	parms.rc = 04;			/* XXX */
24731167Sminshall     } else {
24831167Sminshall 	parms.rc = 0;
24931167Sminshall     }
25031167Sminshall     parms.function_id = 0x62;
25131167Sminshall 
25231167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
25331158Sminshall }
25431158Sminshall 
25531158Sminshall static void
25631158Sminshall write_keystroke(regs, sregs)
25731158Sminshall union REGS *regs;
25831158Sminshall struct SREGS *sregs;
25931158Sminshall {
26031198Sminshall     WriteKeystrokeParms parms;
26131198Sminshall 
26231198Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
26331198Sminshall 
26431198Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
26531198Sminshall 	parms.rc = 0x0c;
26631198Sminshall     } else if (parms.session_id != 23) {
26731198Sminshall 	parms.rc = 0x02;
26831198Sminshall     } else if (parms.connectors_task_id != 0) {
26931198Sminshall 	parms.rc = 0x04;
27031198Sminshall     } else {
27131198Sminshall 	parms.number_of_keys_sent = 0;
27231198Sminshall 	parms.rc = 0;
27331198Sminshall 	if (parms.options == OPTION_SINGLE_KEYSTROKE) {
27431198Sminshall 	    KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
27531198Sminshall 
27631198Sminshall 	    if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
27731198Sminshall 		parms.rc = 0x10;		/* XXX needs 0x12 too! */
27831198Sminshall 	    }
27931198Sminshall 	    parms.number_of_keys_sent++;
28031198Sminshall 	} else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
28131198Sminshall 	    KeystrokeList
28231198Sminshall 		list,
28331198Sminshall 		far *atlist = parms.keystroke_specifier.keystroke_list;
28431198Sminshall 	    KeystrokeEntry
28531198Sminshall 		entry[10],		/* 10 at a time */
28631198Sminshall 		*ourentry,
28731198Sminshall 		far *theirentry;
28831198Sminshall 	    int
28931198Sminshall 		todo;
29031198Sminshall 
29131198Sminshall 	    movetous((char *)&list, FP_SEG(atlist),
29235421Sminshall 			FP_OFF(atlist), sizeof *atlist);
29331198Sminshall 	    todo = list.length/2;
29431198Sminshall 	    ourentry = entry+(highestof(entry)+1);
29535421Sminshall 	    theirentry = &atlist->keystrokes;
29631198Sminshall 
29731198Sminshall 	    while (todo) {
29831198Sminshall 		if (ourentry > &entry[highestof(entry)]) {
29931198Sminshall 		    int thistime;
30031198Sminshall 
30131198Sminshall 		    thistime = todo;
30231198Sminshall 		    if (thistime > numberof(entry)) {
30331198Sminshall 			thistime = numberof(entry);
30431198Sminshall 		    }
30531198Sminshall 		    movetous((char *)entry, FP_SEG(theirentry),
30631198Sminshall 			    FP_OFF(theirentry), thistime*sizeof *theirentry);
30731198Sminshall 		    theirentry += thistime;
30831198Sminshall 		    ourentry = entry;
30931198Sminshall 		}
31031198Sminshall 		if (AcceptKeystroke(ourentry->scancode,
31131198Sminshall 						ourentry->shift_state) == 0) {
31231198Sminshall 		    parms.rc = 0x10;		/* XXX needs 0x12 too! */
31331198Sminshall 		    break;
31431198Sminshall 		}
31531198Sminshall 		parms.number_of_keys_sent++;
31631198Sminshall 		ourentry++;
31731198Sminshall 		todo--;
31831198Sminshall 	    }
31931198Sminshall 	} else {
32031198Sminshall 	    parms.rc = 0x01;
32131198Sminshall 	}
32231198Sminshall     }
32331198Sminshall     parms.function_id = 0x62;
32431198Sminshall 
32531198Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
32631167Sminshall /* XXX */
32731158Sminshall }
32831158Sminshall 
32931167Sminshall 
33031158Sminshall static void
33131167Sminshall disable_input(regs, sregs)
33231167Sminshall union REGS *regs;
33331167Sminshall struct SREGS *sregs;
33431167Sminshall {
33531167Sminshall     DisableInputParms parms;
33631167Sminshall 
33731167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
33831167Sminshall 
33931167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
34031167Sminshall 	parms.rc = 0x0c;
34131167Sminshall     } else if (parms.session_id != 23) {
34231167Sminshall 	parms.rc = 0x02;
34331167Sminshall     } else if (parms.connectors_task_id != 0) {
34431167Sminshall 	parms.rc = 0x04;
34531167Sminshall     } else {
34631211Sminshall 	SetOiaApiInhibit(&OperatorInformationArea);
34731167Sminshall 	parms.rc = 0;
34831167Sminshall     }
34931167Sminshall     parms.function_id = 0x62;
35031167Sminshall 
35131167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
35231167Sminshall }
35331167Sminshall 
35431167Sminshall static void
35531158Sminshall enable_input(regs, sregs)
35631158Sminshall union REGS *regs;
35731158Sminshall struct SREGS *sregs;
35831158Sminshall {
35931167Sminshall     EnableInputParms parms;
36031167Sminshall 
36131167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
36231167Sminshall 
36331167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
36431167Sminshall 	parms.rc = 0x0c;
36531167Sminshall     } else if (parms.session_id != 23) {
36631167Sminshall 	parms.rc = 0x02;
36731167Sminshall     } else if (parms.connectors_task_id != 0) {
36831167Sminshall 	parms.rc = 0x04;
36931167Sminshall     } else {
37031211Sminshall 	ResetOiaApiInhibit(&OperatorInformationArea);
37131167Sminshall 	parms.rc = 0;
37231167Sminshall     }
37331167Sminshall     parms.function_id = 0x62;
37431167Sminshall 
37531167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
37631158Sminshall }
37731158Sminshall 
37831158Sminshall /*
37931158Sminshall  * Copy Services.
38031158Sminshall  */
38131158Sminshall 
38231507Sminshall static
38331507Sminshall copy_subroutine(target, source, parms, what_is_user, length)
38431226Sminshall BufferDescriptor *target, *source;
38531226Sminshall CopyStringParms *parms;
38631226Sminshall int what_is_user;
38731226Sminshall #define	USER_IS_TARGET	0
38831226Sminshall #define	USER_IS_SOURCE	1
38931226Sminshall {
39031226Sminshall #define	TARGET_NO_EAB		1
39131226Sminshall #define	SOURCE_NO_EAB		2
39231226Sminshall #define	TARGET_PC		4
39331226Sminshall #define	SOURCE_PC		8
39431226Sminshall #define	NO_FIELD_ATTRIBUTES	16
39531226Sminshall     int needtodo = 0;
39631226Sminshall     int access_length;
39731226Sminshall     char far *input;
39831226Sminshall     char far *output;
39931226Sminshall     char far *access_pointer;
40031226Sminshall 
40131226Sminshall     if ((target->characteristics^source->characteristics)
40231226Sminshall 		    &CHARACTERISTIC_EAB) {
40331226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
40431226Sminshall 	    needtodo |= TARGET_NO_EAB;	/* Need to bump for EAB in target */
40531226Sminshall 	} else {
40631226Sminshall 	    needtodo |= SOURCE_NO_EAB;	/* Need to bump for EAB in source */
40731226Sminshall 	}
40831226Sminshall     }
40931226Sminshall     if (target->session_type != source->session_type) {
41031226Sminshall 	if (target->session_type == TYPE_PC) {
41131226Sminshall 	    needtodo |= TARGET_PC;	/* scan codes to PC */
41231226Sminshall 	} else {
41331226Sminshall 	    needtodo |= SOURCE_PC;	/* PC to scan codes */
41431226Sminshall 	}
41531226Sminshall     }
41631226Sminshall     if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
41731226Sminshall 	needtodo |= NO_FIELD_ATTRIBUTES;
41831226Sminshall     }
41931507Sminshall     access_length = length;
42031226Sminshall     if (what_is_user == USER_IS_TARGET) {
42131226Sminshall 	if (target->characteristics&CHARACTERISTIC_EAB) {
42231226Sminshall 	    access_length *= 2;
42331226Sminshall 	}
42431226Sminshall 	input = (char far *) &Host[source->begin];
42531226Sminshall 	access_pointer = target->buffer;
42631507Sminshall 	output = access_api(target->buffer, access_length, 0);
42731226Sminshall     } else {
42831226Sminshall 	if (source->characteristics&CHARACTERISTIC_EAB) {
42931226Sminshall 	    access_length *= 2;
43031226Sminshall 	}
43131226Sminshall 	access_pointer = source->buffer;
43231507Sminshall 	input = access_api(source->buffer, access_length, 1);
43331226Sminshall 	output = (char far *) &Host[target->begin];
43431226Sminshall     }
43531226Sminshall     while (length--) {
43631226Sminshall 	if (needtodo&TARGET_PC) {
43731226Sminshall 	    *output++ = disp_asc[*input++];
43831226Sminshall 	} else if (needtodo&SOURCE_PC) {
43931226Sminshall 	    *output++ = asc_disp[*input++];
44031226Sminshall 	} else {
44131226Sminshall 	    *output++ = *input++;
44231226Sminshall 	}
44331226Sminshall 	if (needtodo&TARGET_NO_EAB) {
44435421Sminshall 	    input++;
44531226Sminshall 	} else if (needtodo&SOURCE_NO_EAB) {
44631226Sminshall 	    *output++ = 0;		/* Should figure out good EAB? */
44731226Sminshall 	}
44831226Sminshall     }
44931226Sminshall     if (what_is_user == USER_IS_TARGET) {
45031507Sminshall 	unaccess_api(target->buffer, access_pointer, access_length, 1);
45131226Sminshall     } else {
45231507Sminshall 	unaccess_api(source->buffer, access_pointer, access_length, 0);
45331226Sminshall     }
45431226Sminshall }
45531226Sminshall 
45631226Sminshall 
45731158Sminshall static void
45831167Sminshall copy_string(regs, sregs)
45931158Sminshall union REGS *regs;
46031158Sminshall struct SREGS *sregs;
46131158Sminshall {
46231167Sminshall     CopyStringParms parms;
46331226Sminshall     BufferDescriptor *target = &parms.target, *source = &parms.source;
46431226Sminshall     int length;
46531167Sminshall 
46631167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
46731167Sminshall 
46831507Sminshall     length = 1+parms.source_end-source->begin;
46931167Sminshall     if ((parms.rc != 0) || (parms.function_id !=0)) {
47031167Sminshall 	parms.rc = 0x0c;
47131226Sminshall     } else if (target->session_id == 0) {	/* Target is buffer */
47231226Sminshall 	if (source->session_id != 23) {		/* A no-no */
47331226Sminshall 	    parms.rc = 0x2;
47431226Sminshall 	} else {
47531507Sminshall 	    if ((source->begin < 0) || (source->begin > highestof(Host))) {
47631507Sminshall 		parms.rc = 0x06;		/* invalid source definition */
47731507Sminshall 	    } else {
47831507Sminshall 		if ((source->begin+length) > highestof(Host)) {
47931507Sminshall 		    length = highestof(Host)-source->begin;
48031507Sminshall 		    parms.rc = 0x0f;	/* Truncate */
48131507Sminshall 		}
48231507Sminshall 	        if ((source->characteristics == target->characteristics) &&
48331226Sminshall 		    (source->session_type == target->session_type)) {
48431507Sminshall 		    if (source->characteristics&CHARACTERISTIC_EAB) {
48531507Sminshall 			length *= 2;
48631507Sminshall 		    }
48735421Sminshall 		    movetothem(FP_SEG(target->buffer),
48835421Sminshall 			    FP_OFF(target->buffer),
48931507Sminshall 			    (char *)&Host[source->begin], length);
49031507Sminshall 		} else {
49131507Sminshall 		    copy_subroutine(target, source, &parms,
49231507Sminshall 							USER_IS_TARGET, length);
49331226Sminshall 		}
49431226Sminshall 	    }
49531226Sminshall 	}
49631226Sminshall     } else if (source->session_id != 0) {
49731226Sminshall 	    parms.rc = 0xd;
49831226Sminshall     } else {
499*38210Sminshall 	/* Send to presentation space (3270 buffer) */
500*38210Sminshall 	if ((target->begin < 0) || (target->begin > highestof(Host))) {
501*38210Sminshall 	    parms.rc = 0x07;		/* invalid target definition */
502*38210Sminshall 	} if (!UnLocked) {
503*38210Sminshall 		parms.rc = 0x03;	/* Keyboard locked */
504*38210Sminshall 	} else if (parms.copy_mode != 0) {
505*38210Sminshall 		parms.rc = 0x0f;	/* Copy of field attr's not allowed */
506*38210Sminshall 	} else if (IsProtected(target->begin) || /* Make sure no protected */
507*38210Sminshall 		    (WhereAttrByte(target->begin) !=	/* in range */
508*38210Sminshall 			    WhereAttrByte(target->begin+length-1))) {
509*38210Sminshall 		parms.rc = 0x0e;	/* Attempt to write in protected */
51031507Sminshall 	} else {
511*38210Sminshall 	    if ((target->begin+length) > highestof(Host)) {
512*38210Sminshall 		length = highestof(Host)-target->begin;
51331507Sminshall 		parms.rc = 0x0f;	/* Truncate */
51431226Sminshall 	    }
515*38210Sminshall 	    TurnOnMdt(target->begin);	/* Things have changed */
51631507Sminshall 	    if ((source->characteristics == target->characteristics) &&
51731507Sminshall 		    (source->session_type == target->session_type)) {
51831507Sminshall 		if (source->characteristics&CHARACTERISTIC_EAB) {
51931507Sminshall 		    length *= 2;
52031507Sminshall 		}
52131507Sminshall 		movetous((char *)&Host[target->begin],
52235421Sminshall 			    FP_SEG(source->buffer),
52335421Sminshall 			    FP_OFF(source->buffer), length);
52431507Sminshall 	    } else {
52531507Sminshall 		copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
52631507Sminshall 	    }
52731226Sminshall 	}
52831167Sminshall     }
52931183Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
53031158Sminshall }
53131158Sminshall /*
53231158Sminshall  * Operator Information Area Services.
53331158Sminshall  */
53431158Sminshall 
53531158Sminshall static void
53631158Sminshall read_oia_group(regs, sregs)
53731158Sminshall union REGS *regs;
53831158Sminshall struct SREGS *sregs;
53931158Sminshall {
54031167Sminshall     ReadOiaGroupParms parms;
54131167Sminshall 
54231167Sminshall     movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
54331167Sminshall 
54431167Sminshall     if ((parms.rc != 0) || (parms.function_id != 0)) {
54531167Sminshall 	parms.rc = 0x0c;
54631167Sminshall     } else if (parms.session_id != 23) {
54731167Sminshall 	parms.rc = 0x02;
54831167Sminshall     } else {
54931167Sminshall 	int group = parms.oia_group_number;
55031193Sminshall 	char *from;
55131193Sminshall 	int size;
55231167Sminshall 
55331211Sminshall 	if ((group != API_OIA_ALL_GROUPS) &&
55431211Sminshall 		((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
55531193Sminshall 	} else {
55631193Sminshall 	    if (group == API_OIA_ALL_GROUPS) {
55731193Sminshall 		size = API_OIA_BYTES_ALL_GROUPS;
55831193Sminshall 		from = (char *)&OperatorInformationArea;
55931193Sminshall 	    } else if (group == API_OIA_INPUT_INHIBITED) {
56031193Sminshall 		size = sizeof OperatorInformationArea.input_inhibited;
56131193Sminshall 		from = (char *)&OperatorInformationArea.input_inhibited[0];
56231193Sminshall 	    } else {
56331193Sminshall 		size = 1;
56431193Sminshall 		from = ((char *)&OperatorInformationArea)+group;
56531193Sminshall 	    }
56631193Sminshall 	    movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
56731193Sminshall 			from, size);
56831168Sminshall 	}
56931167Sminshall     }
57031168Sminshall     parms.function_id = 0x6d;
57131167Sminshall     movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
57231158Sminshall }
57331158Sminshall 
57435421Sminshall /*ARGSUSED*/
57531158Sminshall static void
57631158Sminshall unknown_op(regs, sregs)
57731158Sminshall union REGS *regs;
57831158Sminshall struct SREGS *sregs;
57931158Sminshall {
58031158Sminshall     regs->h.ch = 0x12;
58131158Sminshall     regs->h.cl = 0x05;
58231158Sminshall }
58331158Sminshall 
58431158Sminshall 
58531158Sminshall handle_api(regs, sregs)
58631158Sminshall union REGS *regs;
58731158Sminshall struct SREGS *sregs;
58831158Sminshall {
58931158Sminshall     if (regs->h.ah == NAME_RESOLUTION) {
59031158Sminshall 	name_resolution(regs, sregs);
59131517Sminshall #if	defined(unix)
59231517Sminshall     } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
59331517Sminshall 	while ((oia_modified == 0) && (ps_modified == 0)) {
59431517Sminshall 	    (void) Scheduler(1);
59531517Sminshall 	}
59631517Sminshall 	oia_modified = ps_modified = 0;
59731517Sminshall #endif	/* defined(unix) */
59831168Sminshall     } else if (regs->h.ah != 0x09) {
59931168Sminshall 	regs->h.ch = 0x12;
60031168Sminshall 	regs->h.cl = 0x0f;		/* XXX Invalid environmental access */
60131168Sminshall     } else if (regs->x.bx != 0x8020) {
60231168Sminshall 	regs->h.ch = 0x12;
60331168Sminshall 	regs->h.cl = 0x08;		/* XXX Invalid wait specified */
60431168Sminshall     } else if (regs->h.ch != 0) {
60531211Sminshall 	regs->x.cx = 0x1206;		/* XXX Invalid priority */
60631158Sminshall     } else {
60731158Sminshall 	switch (regs->x.dx) {
60831158Sminshall 	case GATE_SESSMGR:
60931158Sminshall 	    switch (regs->h.al) {
61031158Sminshall 	    case QUERY_SESSION_ID:
61131168Sminshall 		if (regs->h.cl != 0) {
61231211Sminshall 		    regs->x.cx = 0x1206;
61331168Sminshall 		} else {
61431211Sminshall 		    regs->x.cx = 0x1200;
61531168Sminshall 		    query_session_id(regs, sregs);
61631168Sminshall 		}
61731158Sminshall 		break;
61831211Sminshall 	    case QUERY_SESSION_PARAMETERS:
61931168Sminshall 		if (regs->h.cl != 0) {
62031211Sminshall 		    regs->x.cx = 0x1206;
62131168Sminshall 		} else {
62231211Sminshall 		    regs->x.cx = 0x1200;
62331193Sminshall 		    query_session_parameters(regs, sregs);
62431168Sminshall 		}
62531158Sminshall 		break;
62631158Sminshall 	    case QUERY_SESSION_CURSOR:
62731168Sminshall 		if (regs->h.cl != 0xff) {
62831211Sminshall 		    regs->x.cx = 0x1206;
62931168Sminshall 		} else {
63031211Sminshall 		    regs->x.cx = 0x1200;
63131168Sminshall 		    query_session_cursor(regs, sregs);
63231168Sminshall 		}
63331158Sminshall 		break;
63431158Sminshall 	    default:
63531158Sminshall 		unknown_op(regs, sregs);
63631158Sminshall 		break;
63731158Sminshall 	    }
63831158Sminshall 	    break;
63931158Sminshall 	case GATE_KEYBOARD:
64031168Sminshall 	    if (regs->h.cl != 00) {
64131211Sminshall 		regs->x.cx = 0x1206;
64231168Sminshall 	    } else {
64331211Sminshall 		regs->x.cx = 0x1200;
64431168Sminshall 		switch (regs->h.al) {
64531168Sminshall 		case CONNECT_TO_KEYBOARD:
64631168Sminshall 		    connect_to_keyboard(regs, sregs);
64731168Sminshall 		    break;
64831168Sminshall 		case DISABLE_INPUT:
64931168Sminshall 		    disable_input(regs, sregs);
65031168Sminshall 		    break;
65131168Sminshall 		case WRITE_KEYSTROKE:
65231168Sminshall 		    write_keystroke(regs, sregs);
65331168Sminshall 		    break;
65431168Sminshall 		case ENABLE_INPUT:
65531168Sminshall 		    enable_input(regs, sregs);
65631168Sminshall 		    break;
65731168Sminshall 		case DISCONNECT_FROM_KEYBOARD:
65831168Sminshall 		    disconnect_from_keyboard(regs, sregs);
65931168Sminshall 		    break;
66031168Sminshall 		default:
66131168Sminshall 		    unknown_op(regs, sregs);
66231168Sminshall 		    break;
66331168Sminshall 		}
66431158Sminshall 	    }
66531158Sminshall 	    break;
66631158Sminshall 	case GATE_COPY:
66731168Sminshall 	    if (regs->h.cl != 0xff) {
66831211Sminshall 		regs->x.cx = 0x1206;
66931168Sminshall 	    } else {
67031211Sminshall 		regs->x.cx = 0x1200;
67131168Sminshall 		switch (regs->h.al) {
67231168Sminshall 		case COPY_STRING:
67331168Sminshall 		    copy_string(regs, sregs);
67431168Sminshall 		    break;
67531168Sminshall 		default:
67631168Sminshall 		    unknown_op(regs, sregs);
67731168Sminshall 		    break;
67831168Sminshall 		}
67931158Sminshall 	    }
68031158Sminshall 	    break;
68131158Sminshall 	case GATE_OIAM:
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 READ_OIA_GROUP:
68831168Sminshall 		    read_oia_group(regs, sregs);
68931168Sminshall 		    break;
69031168Sminshall 		default:
69131168Sminshall 		    unknown_op(regs, sregs);
69231168Sminshall 		    break;
69331168Sminshall 		}
69431158Sminshall 	    }
69531158Sminshall 	    break;
69631158Sminshall 	default:
69731168Sminshall 	    regs->h.ch = 0x12;
69831168Sminshall 	    regs->h.cl = 0x34;		/* Invalid GATE entry */
69931158Sminshall 	    break;
70031158Sminshall 	}
70131158Sminshall     }
70231158Sminshall }
703