summaryrefslogtreecommitdiff
path: root/comms/tn3270/files
diff options
context:
space:
mode:
Diffstat (limited to 'comms/tn3270/files')
-rw-r--r--comms/tn3270/files/Makefile6
-rw-r--r--comms/tn3270/files/Makefile.inc14
-rw-r--r--comms/tn3270/files/api/api.order8
-rw-r--r--comms/tn3270/files/api/api_bsd.c295
-rw-r--r--comms/tn3270/files/api/api_exch.c446
-rw-r--r--comms/tn3270/files/api/api_exch.h168
-rw-r--r--comms/tn3270/files/api/apilib.c435
-rw-r--r--comms/tn3270/files/api/apilib.h58
-rw-r--r--comms/tn3270/files/api/asc_ebc.c116
-rw-r--r--comms/tn3270/files/api/asc_ebc.h50
-rw-r--r--comms/tn3270/files/api/astosc.c106
-rw-r--r--comms/tn3270/files/api/astosc.h57
-rw-r--r--comms/tn3270/files/api/dctype.c249
-rw-r--r--comms/tn3270/files/api/dctype.h53
-rw-r--r--comms/tn3270/files/api/disp_asc.c49
-rw-r--r--comms/tn3270/files/api/disp_asc.h42
-rw-r--r--comms/tn3270/files/api/ebc_disp.c112
-rw-r--r--comms/tn3270/files/api/ebc_disp.h37
-rw-r--r--comms/tn3270/files/ascii/ascii.order2
-rw-r--r--comms/tn3270/files/ascii/default.map75
-rw-r--r--comms/tn3270/files/ascii/map3270.c957
-rw-r--r--comms/tn3270/files/ascii/map3270.h44
-rw-r--r--comms/tn3270/files/ascii/mset.c419
-rw-r--r--comms/tn3270/files/ascii/state.h56
-rw-r--r--comms/tn3270/files/ascii/termin.c299
-rw-r--r--comms/tn3270/files/ctlr/3180.kbd178
-rw-r--r--comms/tn3270/files/ctlr/3270pc.kbd178
-rw-r--r--comms/tn3270/files/ctlr/api.c778
-rw-r--r--comms/tn3270/files/ctlr/api.h410
-rw-r--r--comms/tn3270/files/ctlr/ctlr.order5
-rw-r--r--comms/tn3270/files/ctlr/declare.h58
-rw-r--r--comms/tn3270/files/ctlr/function.c53
-rw-r--r--comms/tn3270/files/ctlr/function.h165
-rw-r--r--comms/tn3270/files/ctlr/hostctlr.h221
-rw-r--r--comms/tn3270/files/ctlr/inbound.c1214
-rw-r--r--comms/tn3270/files/ctlr/oia.c56
-rw-r--r--comms/tn3270/files/ctlr/oia.h192
-rw-r--r--comms/tn3270/files/ctlr/options.c186
-rw-r--r--comms/tn3270/files/ctlr/options.h43
-rw-r--r--comms/tn3270/files/ctlr/outbound.c618
-rw-r--r--comms/tn3270/files/ctlr/screen.h141
-rw-r--r--comms/tn3270/files/ctlr/scrnctlr.h47
-rw-r--r--comms/tn3270/files/ctlr/unix.kbd180
-rw-r--r--comms/tn3270/files/general/genbsubs.c131
-rw-r--r--comms/tn3270/files/general/general.h52
-rw-r--r--comms/tn3270/files/general/general.order2
-rw-r--r--comms/tn3270/files/general/globals.c78
-rw-r--r--comms/tn3270/files/general/globals.h131
-rw-r--r--comms/tn3270/files/general/vaxbsubs.s101
-rw-r--r--comms/tn3270/files/mset/Makefile30
-rw-r--r--comms/tn3270/files/mset/map32701028
-rw-r--r--comms/tn3270/files/mset/map3270.5341
-rw-r--r--comms/tn3270/files/mset/mset.1189
-rw-r--r--comms/tn3270/files/sys_curses/system.c763
-rw-r--r--comms/tn3270/files/sys_curses/telextrn.h72
-rw-r--r--comms/tn3270/files/sys_curses/terminal.h80
-rw-r--r--comms/tn3270/files/sys_curses/termout.c948
-rw-r--r--comms/tn3270/files/telnet/commands.c2906
-rw-r--r--comms/tn3270/files/telnet/defines.h60
-rw-r--r--comms/tn3270/files/telnet/externs.h414
-rw-r--r--comms/tn3270/files/telnet/general.h44
-rw-r--r--comms/tn3270/files/telnet/libtelnet/genget.c109
-rw-r--r--comms/tn3270/files/telnet/libtelnet/misc-proto.h73
-rw-r--r--comms/tn3270/files/telnet/libtelnet/misc.h47
-rw-r--r--comms/tn3270/files/telnet/main.c361
-rw-r--r--comms/tn3270/files/telnet/network.c180
-rw-r--r--comms/tn3270/files/telnet/ring.c340
-rw-r--r--comms/tn3270/files/telnet/ring.h105
-rw-r--r--comms/tn3270/files/telnet/sys_bsd.c740
-rw-r--r--comms/tn3270/files/telnet/telnet.c2651
-rw-r--r--comms/tn3270/files/telnet/terminal.c221
-rw-r--r--comms/tn3270/files/telnet/tn3270.c395
-rw-r--r--comms/tn3270/files/telnet/types.h51
-rw-r--r--comms/tn3270/files/telnet/utilities.c925
-rw-r--r--comms/tn3270/files/tn3270/Makefile87
-rw-r--r--comms/tn3270/files/tn3270/tn3270.1340
-rw-r--r--comms/tn3270/files/tools/Makefile6
-rw-r--r--comms/tn3270/files/tools/Makefile.inc13
-rw-r--r--comms/tn3270/files/tools/mkastods/Makefile8
-rw-r--r--comms/tn3270/files/tools/mkastods/mkastods.c77
-rw-r--r--comms/tn3270/files/tools/mkastosc/Makefile12
-rw-r--r--comms/tn3270/files/tools/mkastosc/mkastosc.c165
-rw-r--r--comms/tn3270/files/tools/mkdctype/Makefile8
-rw-r--r--comms/tn3270/files/tools/mkdctype/ectype.c319
-rw-r--r--comms/tn3270/files/tools/mkdctype/ectype.h54
-rw-r--r--comms/tn3270/files/tools/mkdctype/mkdctype.c105
-rw-r--r--comms/tn3270/files/tools/mkdstoas/Makefile8
-rw-r--r--comms/tn3270/files/tools/mkdstoas/mkdstoas.c77
-rw-r--r--comms/tn3270/files/tools/mkhits/Makefile8
-rw-r--r--comms/tn3270/files/tools/mkhits/dohits.c300
-rw-r--r--comms/tn3270/files/tools/mkhits/dohits.h56
-rw-r--r--comms/tn3270/files/tools/mkhits/mkhits.c144
-rw-r--r--comms/tn3270/files/tools/mkmake/Makefile10
-rw-r--r--comms/tn3270/files/tools/mkmake/mkmake.y1138
-rw-r--r--comms/tn3270/files/tools/prt3270/Makefile47
-rw-r--r--comms/tn3270/files/tools/prt3270/prt3270.c647
96 files changed, 26073 insertions, 0 deletions
diff --git a/comms/tn3270/files/Makefile b/comms/tn3270/files/Makefile
new file mode 100644
index 00000000000..2c66f71bbb7
--- /dev/null
+++ b/comms/tn3270/files/Makefile
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:16 dholland Exp $
+# From NetBSD: Makefile,v 1.8 2005/09/17 16:52:02 chs Exp
+
+SUBDIR = tools .WAIT tn3270 mset
+
+.include <bsd.subdir.mk>
diff --git a/comms/tn3270/files/Makefile.inc b/comms/tn3270/files/Makefile.inc
new file mode 100644
index 00000000000..8396c4b89b9
--- /dev/null
+++ b/comms/tn3270/files/Makefile.inc
@@ -0,0 +1,14 @@
+# $NetBSD: Makefile.inc,v 1.1.1.1 2010/01/17 01:33:16 dholland Exp $
+# From NetBSD: Makefile.inc,v 1.12 2009/04/14 22:15:27 lukem Exp
+
+WARNS?= 1 # XXX -Wcast-qual -Wshadow issues
+
+USE_FORT?= yes # network client
+
+CPPFLAGS+=-DTERMCAP -DSRCRT -DKLUDGELINEMODE -DUSE_TERMIO -DTN3270 -Dunix
+CPPFLAGS+=-I${.CURDIR} -I.
+KBD= unix.kbd
+
+.if exists(${.CURDIR}/../../Makefile.inc)
+.include "${.CURDIR}/../../Makefile.inc"
+.endif
diff --git a/comms/tn3270/files/api/api.order b/comms/tn3270/files/api/api.order
new file mode 100644
index 00000000000..cdbcd8ca460
--- /dev/null
+++ b/comms/tn3270/files/api/api.order
@@ -0,0 +1,8 @@
+ebc_disp.o
+disp_asc.o
+dctype.o
+astosc.o
+asc_ebc.o
+apilib.o
+api_bsd.o
+api_exch.o
diff --git a/comms/tn3270/files/api/api_bsd.c b/comms/tn3270/files/api/api_bsd.c
new file mode 100644
index 00000000000..243e57f5288
--- /dev/null
+++ b/comms/tn3270/files/api/api_bsd.c
@@ -0,0 +1,295 @@
+/* $NetBSD: api_bsd.c,v 1.1.1.1 2010/01/17 01:33:16 dholland Exp $ */
+/* From NetBSD: api_bsd.c,v 1.13 2006/05/24 16:57:12 christos Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)api_bsd.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: api_bsd.c,v 1.1.1.1 2010/01/17 01:33:16 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#if defined(unix)
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../ctlr/api.h"
+#include "api_exch.h"
+
+
+int
+api_close_api()
+{
+ if (api_exch_outcommand(EXCH_CMD_DISASSOCIATE) == -1) {
+ return -1;
+ } else if (api_exch_flush() == -1) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+int
+api_open_api(string)
+char *string; /* if non-zero, where to connect to */
+{
+ struct sockaddr_in server;
+ struct hostent *hp;
+ struct storage_descriptor sd;
+ char thehostname[100];
+ char keyname[100];
+ char inkey[100];
+ FILE *keyfile;
+ int sock;
+ unsigned int port;
+ int i;
+
+ if (string == 0) {
+ string = getenv("API3270"); /* Get API */
+ if (string == 0) {
+ fprintf(stderr,
+ "API3270 environmental variable not set - no API.\n");
+ return -1; /* Nothing */
+ }
+ }
+
+ if (sscanf(string, "%[^:]:%d:%99s", thehostname,
+ (int *)&port, keyname) != 3) {
+ fprintf(stderr, "API3270 environmental variable has bad format.\n");
+ return -1;
+ }
+ /* Now, try to connect */
+ sock = socket(AF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ perror("opening API socket");
+ return -1;
+ }
+ server.sin_family = AF_INET;
+ hp = gethostbyname(thehostname);
+ if (hp == 0) {
+ fprintf(stderr, "%s specifies bad host name.\n", string);
+ return -1;
+ }
+ if (sizeof(server.sin_addr.s_addr) < hp->h_length)
+ hp->h_length = sizeof(server.sin_addr.s_addr);
+ (void)memcpy(&server.sin_addr.s_addr, hp->h_addr, hp->h_length);
+ server.sin_port = htons(port);
+
+ if (connect(sock, (struct sockaddr *)&server, sizeof server) < 0) {
+ perror("connecting to API server");
+ return -1;
+ }
+ /* Now, try application level connection */
+ if (api_exch_init(sock, "client") == -1) {
+ return -1;
+ }
+ if (api_exch_outcommand(EXCH_CMD_ASSOCIATE) == -1) {
+ return -1;
+ }
+ keyfile = fopen(keyname, "r");
+ if (keyfile == 0) {
+ perror("fopen");
+ return -1;
+ }
+ if (fscanf(keyfile, "%99s\n", inkey) != 1) {
+ perror("fscanf");
+ goto out;
+ }
+ sd.length = strlen(inkey)+1;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ goto out;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, sd.length, inkey) == -1) {
+ goto out;
+ }
+ while ((i = api_exch_nextcommand()) != EXCH_CMD_ASSOCIATED) {
+ int passwd_length;
+ char *passwd;
+ char buffer[200];
+
+ switch (i) {
+ case EXCH_CMD_REJECTED:
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC,
+ sizeof sd, (char *)&sd) == -1) {
+ goto out;
+ }
+ if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
+ goto out;
+ }
+ buffer[sd.length] = 0;
+ fprintf(stderr, "%s\n", buffer);
+ if (api_exch_outcommand(EXCH_CMD_ASSOCIATE) == -1) {
+ goto out;
+ }
+ break;
+ case EXCH_CMD_SEND_AUTH:
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ goto out;
+ }
+ if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
+ goto out;
+ }
+ buffer[sd.length] = 0;
+ passwd = getpass(buffer); /* Go to terminal */
+ passwd_length = strlen(passwd);
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ goto out;
+ }
+ if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
+ goto out;
+ }
+ buffer[sd.length] = 0;
+ if (sd.length) {
+ char *ptr;
+
+ ptr = passwd;
+ i = 0;
+ while (*ptr) {
+ *ptr++ ^= buffer[i++];
+ if (i >= sd.length) {
+ i = 0;
+ }
+ }
+ }
+ sd.length = passwd_length;
+ if (api_exch_outcommand(EXCH_CMD_AUTH) == -1) {
+ goto out;
+ }
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ goto out;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, passwd_length, passwd) == -1) {
+ goto out;
+ }
+ break;
+ case -1:
+ goto out;
+ default:
+ fprintf(stderr,
+ "Waiting for connection indicator, received 0x%x.\n", i);
+ break;
+ }
+ }
+ /* YEAH */
+ fclose(keyfile);
+ return 0; /* Happiness! */
+ /* NOPE */
+out:
+ fclose(keyfile);
+ return -1;
+}
+
+
+int
+api_exch_api(regs, sregs, parms, length)
+union REGS *regs;
+struct SREGS *sregs;
+char *parms;
+int length;
+{
+ struct storage_descriptor sd;
+ int i;
+
+ if (api_exch_outcommand(EXCH_CMD_REQUEST) == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_REGS, sizeof *regs, (char *)regs) == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof *sregs, (char *)sregs) == -1) {
+ return -1;
+ }
+ sd.length = length;
+ sd.location = (long) parms;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, length, parms) == -1) {
+ return -1;
+ }
+ while ((i = api_exch_nextcommand()) != EXCH_CMD_REPLY) {
+ switch (i) {
+ case EXCH_CMD_GIMME:
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
+ == -1) {
+ return -1;
+ }
+ /*XXX validity check GIMME? */
+ if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
+ == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, sd.length,
+ (char *)sd.location) == -1) {
+ return -1;
+ }
+ break;
+ case EXCH_CMD_HEREIS:
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
+ == -1) {
+ return -1;
+ }
+ /* XXX Validty check HEREIS? */
+ if (api_exch_intype(EXCH_TYPE_BYTES, sd.length,
+ (char *)sd.location) == -1) {
+ return -1;
+ }
+ break;
+ default:
+ fprintf(stderr, "Waiting for reply command, we got command %d.\n",
+ i);
+ return -1;
+ }
+ }
+ if (api_exch_intype(EXCH_TYPE_REGS, sizeof *regs, (char *)regs) == -1) {
+ return -1;
+ }
+ if (api_exch_intype(EXCH_TYPE_SREGS, sizeof *sregs, (char *)sregs) == -1) {
+ return -1;
+ }
+ /* YEAH */
+ return 0; /* Happiness! */
+}
+
+#endif /* unix */
diff --git a/comms/tn3270/files/api/api_exch.c b/comms/tn3270/files/api/api_exch.c
new file mode 100644
index 00000000000..410ee3b98ea
--- /dev/null
+++ b/comms/tn3270/files/api/api_exch.c
@@ -0,0 +1,446 @@
+/* $NetBSD: api_exch.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: api_exch.c,v 1.8 2003/08/07 11:16:24 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)api_exch.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: api_exch.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../general/general.h"
+
+#include "api_exch.h"
+
+static int sock; /* Socket number */
+
+static char whoarewe[40] = "";
+#define WHO_ARE_WE() fprintf(stderr, "(API %s) ", whoarewe);
+
+static enum {CONTENTION, SEND, RECEIVE } conversation;
+
+static struct exch_exch exch_state;
+
+static unsigned int
+ my_sequence,
+ your_sequence;
+
+static char ibuffer[4000], *ibuf_next, *ibuf_last;
+#define IBUFADDED(i) ibuf_last += (i)
+#define IBUFAVAILABLE() (ibuf_last-ibuf_next)
+#define IBUFFER() ibuffer
+#define IBUFFREE() (ibuffer+sizeof ibuffer-ibuf_last-1)
+#define IBUFGETBYTES(w,l) { memcpy(w, ibuf_next, l); ibuf_next += l; }
+#define IBUFRESET() (ibuf_next = ibuf_last = ibuffer)
+
+char obuffer[4000], *obuf_next;
+#define OBUFADDBYTES(w,l) { memcpy(obuf_next, w, l); obuf_next += l; }
+#define OBUFAVAILABLE() (obuf_next - obuffer)
+#define OBUFFER() obuffer
+#define OBUFRESET() obuf_next = obuffer
+#define OBUFROOM() (obuffer+sizeof obuffer-obuf_next)
+
+
+static int outflush(void);
+static int iget(char *, int);
+static char *exch_to_ascii(int);
+static int send_state(void);
+static int receive_state(void);
+static int enter_receive(void);
+static int enter_send(void);
+
+static int
+outflush()
+{
+ int length = OBUFAVAILABLE();
+
+ if (length != 0) {
+ if (write(sock, OBUFFER(), length) != length) {
+ WHO_ARE_WE();
+ perror("write");
+ return -1;
+ }
+ OBUFRESET();
+ }
+ return 0; /* All OK */
+}
+
+
+static int
+iget(location, length)
+char *location;
+int length;
+{
+ int count;
+
+ if (OBUFAVAILABLE()) {
+ if (outflush() == -1) {
+ return -1;
+ }
+ }
+ if ((count = IBUFAVAILABLE()) != 0) {
+ if (count > length) {
+ count = length;
+ }
+ IBUFGETBYTES(location, count);
+ length -= count;
+ location += count;
+ }
+ while (length) {
+ if (ibuf_next == ibuf_last) {
+ IBUFRESET();
+ }
+ if ((count = read(sock, IBUFFER(), IBUFFREE())) < 0) {
+ WHO_ARE_WE();
+ perror("read");
+ return -1;
+ }
+ if (count == 0) {
+ /* Reading past end-of-file */
+ WHO_ARE_WE();
+ fprintf(stderr, "End of file read\r\n");
+ return -1;
+ }
+ IBUFADDED(count);
+ if (count > length) {
+ count = length;
+ }
+ IBUFGETBYTES(location, count);
+ length -= count;
+ location += count;
+ }
+ return 0;
+}
+
+static char *
+exch_to_ascii(exch)
+int exch; /* opcode to decode */
+{
+ switch (exch) {
+ case EXCH_EXCH_COMMAND:
+ return "Command";
+ case EXCH_EXCH_TYPE:
+ return "Type";
+ case EXCH_EXCH_TURNAROUND:
+ return "Turnaround";
+ case EXCH_EXCH_RTS:
+ return "Request to Send";
+ default:
+ {
+ static char unknown[40];
+
+ sprintf(unknown, "(Unknown exchange 0x%02x)", exch&0xff);
+ return unknown;
+ }
+ }
+}
+
+/*
+ * Send the exch structure, updating the sequnce number field.
+ */
+
+static int
+send_state()
+{
+ if (OBUFROOM() < sizeof exch_state) {
+ if (outflush() == -1) {
+ return -1;
+ }
+ }
+ my_sequence = (my_sequence+1)&0xff;
+ exch_state.my_sequence = my_sequence;
+ exch_state.your_sequence = your_sequence;
+ OBUFADDBYTES((char *)&exch_state, sizeof exch_state);
+ return 0;
+}
+
+/*
+ * Receive the exch structure from the other side, checking
+ * sequence numbering.
+ */
+
+static int
+receive_state()
+{
+ if (iget((char *)&exch_state, sizeof exch_state) == -1) {
+ return -1;
+ }
+ if (conversation != CONTENTION) {
+ if (exch_state.your_sequence != my_sequence) {
+ WHO_ARE_WE();
+ fprintf(stderr, "Send sequence number mismatch.\n");
+ return -1;
+ }
+ if (exch_state.my_sequence != ((++your_sequence)&0xff)) {
+ WHO_ARE_WE();
+ fprintf(stderr, "Receive sequence number mismatch.\n");
+ return -1;
+ }
+ }
+ your_sequence = exch_state.my_sequence;
+ return 0;
+}
+
+static int
+enter_receive()
+{
+ switch (conversation) {
+ case CONTENTION:
+ exch_state.opcode = EXCH_EXCH_TURNAROUND;
+ if (send_state() == -1) {
+ return -1;
+ }
+ if (receive_state() == -1) {
+ return -1;
+ }
+ if (exch_state.opcode != EXCH_EXCH_RTS) {
+ WHO_ARE_WE();
+ fprintf(stderr, "In CONTENTION state: ");
+ if (exch_state.opcode == EXCH_EXCH_TURNAROUND) {
+ fprintf(stderr,
+ "Both sides tried to enter RECEIVE state.\n");
+ } else {
+ fprintf(stderr,
+ "Protocol error trying to enter RECEIVE state.\n");
+ }
+ return -1;
+ }
+ break;
+ case SEND:
+ exch_state.opcode = EXCH_EXCH_TURNAROUND;
+ if (send_state() == -1) {
+ return -1;
+ }
+ break;
+ case RECEIVE:
+ abort(); /* Unhandled case; remove abort if we die here */
+ }
+ conversation = RECEIVE;
+ return 0;
+}
+
+static int
+enter_send()
+{
+ switch (conversation) {
+ case CONTENTION:
+ exch_state.opcode = EXCH_EXCH_RTS;
+ if (send_state() == -1) {
+ return -1;
+ }
+ /* fall through */
+ case RECEIVE:
+ if (receive_state() == -1) {
+ return -1;
+ }
+ if (exch_state.opcode != EXCH_EXCH_TURNAROUND) {
+ WHO_ARE_WE();
+ fprintf(stderr, "Conversation error - both sides in SEND state.\n");
+ return -1;
+ }
+ case SEND:
+ abort(); /* Unhandled case; remove abort if we die here */
+ }
+ conversation = SEND;
+ return 0;
+}
+
+int
+api_exch_nextcommand()
+{
+ if (conversation != RECEIVE) {
+ if (enter_receive() == -1) {
+ return -1;
+ }
+ }
+ if (receive_state() == -1) {
+ return -1;
+ }
+ if (exch_state.opcode != EXCH_EXCH_COMMAND) {
+ WHO_ARE_WE();
+ fprintf(stderr, "Expected a %s exchange, received a %s exchange.\n",
+ exch_to_ascii(EXCH_EXCH_COMMAND), exch_to_ascii(exch_state.opcode));
+ return -1;
+ }
+ return exch_state.command_or_type;
+}
+
+
+int
+api_exch_incommand(command)
+int command;
+{
+ int i;
+
+ if ((i = api_exch_nextcommand()) == -1) {
+ return -1;
+ }
+ if (i != command) {
+ WHO_ARE_WE();
+ fprintf(stderr, "Expected API command 0x%x, got API command 0x%x.\n",
+ command, i);
+ return -1;
+ }
+ return 0;
+}
+
+
+int
+api_exch_outcommand(command)
+int command;
+{
+ if (conversation != SEND) {
+ if (enter_send() == -1) {
+ return -1;
+ }
+ }
+ exch_state.command_or_type = command;
+ exch_state.opcode = EXCH_EXCH_COMMAND;
+ if (send_state() == -1) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+int
+api_exch_outtype(type, length, location)
+int
+ type,
+ length;
+const char
+ *location;
+{
+ int netleng = length;
+
+ if (conversation != SEND) {
+ if (enter_send() == -1) {
+ return -1;
+ }
+ }
+ exch_state.opcode = EXCH_EXCH_TYPE;
+ exch_state.command_or_type = type;
+ exch_state.length = netleng;
+ if (send_state() == -1) {
+ return -1;
+ }
+ if (length) {
+ if (OBUFROOM() > length) {
+ OBUFADDBYTES(location, length);
+ } else {
+ if (outflush() == -1) {
+ return -1;
+ }
+ if (write(sock, location, length) != length) {
+ WHO_ARE_WE();
+ perror("write");
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+
+int
+api_exch_intype(type, length, location)
+int
+ type,
+ length;
+char
+ *location;
+{
+ int netleng = length;
+
+ if (conversation != RECEIVE) {
+ if (enter_receive() == -1) {
+ return -1;
+ }
+ }
+ if (receive_state() == -1) {
+ return -1;
+ }
+ if (exch_state.opcode != EXCH_EXCH_TYPE) {
+ WHO_ARE_WE();
+ fprintf(stderr,
+ "Expected to receive a %s exchange, received a %s exchange.\n",
+ exch_to_ascii(EXCH_EXCH_TYPE), exch_to_ascii(exch_state.opcode));
+ return -1;
+ }
+ if (exch_state.command_or_type != type) {
+ WHO_ARE_WE();
+ fprintf(stderr, "Expected type 0x%x, got type 0x%x.\n",
+ type, exch_state.command_or_type);
+ return -1;
+ }
+ if (exch_state.length != netleng) {
+ fprintf(stderr, "Type 0x%x - expected length %d, received length %u.\n",
+ type, length, exch_state.length);
+ return -1;
+ }
+ if (iget(location, length) == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+int
+api_exch_flush()
+{
+ return outflush();
+}
+
+int
+api_exch_init(sock_number, ourname)
+int sock_number;
+char *ourname;
+{
+ sock = sock_number;
+ (void) strcpy(whoarewe, ourname); /* For error messages */
+
+ my_sequence = your_sequence = 0;
+
+ conversation = CONTENTION; /* We don't know which direction */
+
+ IBUFRESET();
+ OBUFRESET();
+
+ return 0;
+}
diff --git a/comms/tn3270/files/api/api_exch.h b/comms/tn3270/files/api/api_exch.h
new file mode 100644
index 00000000000..ae5b0de207e
--- /dev/null
+++ b/comms/tn3270/files/api/api_exch.h
@@ -0,0 +1,168 @@
+/* $NetBSD: api_exch.h,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: api_exch.h,v 1.7 2003/08/07 11:16:24 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)api_exch.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * This file describes the structures passed back and forth
+ * between the API client and API server on a Unix-based
+ * tn3270 implementation.
+ */
+
+/*
+ * The following are the low-level opcodes exchanged between the
+ * two sides. These are designed to allow for type, sequence number,
+ * and direction checking.
+ *
+ * We enforce conversation flow. There are three states: CONTENTION,
+ * SEND, and RECEIVE. Both sides start in CONTENTION.
+ * We never leave RECEIVE state without first reading a TURNAROUND
+ * opcode. We never leave SEND state without first writing a TURNAROUND
+ * opcode. This scheme ensures that we always have conversation flowing
+ * in a synchronized direction (or detect an application error), and that
+ * we never hang with both sides trying to read from the "wire".
+ *
+ * State event action
+ *
+ * CONTENTION read request send TURNAROUND
+ * read RTS
+ * enter RECEIVE
+ * CONTENTION write request send RTS
+ * read TURNAROUND
+ * enter SEND
+ *
+ * RECEIVE read request read whatever
+ * RECEIVE write request read TURNAROUND
+ *
+ * SEND read request send TURNAROUND
+ * SEND write write whatever
+ */
+
+#define EXCH_EXCH_COMMAND 0 /* The following is a command */
+#define EXCH_EXCH_TURNAROUND 1 /* Your turn to send */
+#define EXCH_EXCH_RTS 2 /* Request to send */
+#define EXCH_EXCH_TYPE 3 /* The following is a type */
+
+struct exch_exch {
+ char
+ opcode; /* COMMAND, TURNAROUND, or TYPE */
+ unsigned char
+ my_sequence, /* 0-ff, initially zero */
+ your_sequence, /* 0-ff, initially zero */
+ command_or_type; /* Application level command or type */
+ unsigned short
+ length; /* The length of any following data */
+};
+
+/*
+ * The following are the command codes which the higher level protocols
+ * send and receive.
+ */
+
+#define EXCH_CMD_ASSOCIATE 0 /* Connect [client->server] */
+ /*
+ * struct storage_desc
+ * char key[]
+ */
+#define EXCH_CMD_DISASSOCIATE 1 /* Disconnect [client->server] */
+#define EXCH_CMD_SEND_AUTH 2 /* Send password [server->client] */
+ /*
+ * struct storage_desc
+ * char prompt[]
+ * struct storage_desc
+ * char seed[]
+ */
+#define EXCH_CMD_AUTH 3 /* Authorization [client->server] */
+ /*
+ * struct storage_desc
+ * char authenticator[]
+ */
+#define EXCH_CMD_ASSOCIATED 4 /* Connected [server->client] */
+#define EXCH_CMD_REJECTED 5 /* Too bad [server->client] */
+ /*
+ * struct storage_desc
+ * char message[]
+ */
+
+#define EXCH_CMD_REQUEST 6 /* A request [client->server] */
+ /* struct regs,
+ * struct sregs,
+ * struct storage_desc
+ * char bytes[]
+ */
+#define EXCH_CMD_GIMME 7 /* Send storage [server->client] */
+ /*
+ * struct storage_desc
+ */
+#define EXCH_CMD_HEREIS 8 /* Here is storage [BOTH WAYS] */
+ /*
+ * struct storage_desc
+ * char bytes[]
+ */
+#define EXCH_CMD_REPLY 9 /* End of discussion */
+ /*
+ * struct regs,
+ * struct sregs,
+ */
+
+/*
+ * The following are typed parameters sent across the wire.
+ *
+ * This should be done much more generally, with some form of
+ * XDR or mapped conversation ability.
+ */
+
+#define EXCH_TYPE_REGS 0
+#define EXCH_TYPE_SREGS 1
+#define EXCH_TYPE_STORE_DESC 2
+#define EXCH_TYPE_BYTES 3
+
+/*
+ * each parameter that comes over looks like:
+ *
+ * char type of following
+ * short (2 bytes) length of following (network byte order)
+ * following
+ */
+
+struct storage_descriptor {
+ long location; /* In network byte order */
+ short length; /* In network byte order */
+};
+
+int api_exch_nextcommand(void);
+int api_exch_incommand(int);
+int api_exch_outcommand(int);
+int api_exch_outtype(int, int , const char *);
+int api_exch_intype(int, int , char *);
+int api_exch_flush(void);
+int api_exch_init(int, char *);
diff --git a/comms/tn3270/files/api/apilib.c b/comms/tn3270/files/api/apilib.c
new file mode 100644
index 00000000000..4e5b4e50d7b
--- /dev/null
+++ b/comms/tn3270/files/api/apilib.c
@@ -0,0 +1,435 @@
+/* $NetBSD: apilib.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: apilib.c,v 1.7 2003/08/07 11:16:24 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)apilib.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: apilib.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "../ctlr/api.h"
+
+#include "apilib.h"
+
+int
+ api_sup_errno = 0, /* Supervisor error number */
+ api_sup_fcn_id = 0, /* Supervisor function id (0x12) */
+ api_fcn_errno = 0, /* Function error number */
+ api_fcn_fcn_id = 0; /* Function ID (0x6b, etc.) */
+
+static int
+ gate_sessmgr = 0,
+ gate_keyboard = 0,
+ gate_copy = 0,
+ gate_oiam = 0;
+
+
+/* apilib.c */
+static int api_issue_regs(int, int , int , int , int , int , char *, int,
+ union REGS *, struct SREGS *);
+static int api_issue(int, int , int , int , int , int , char *, int);
+
+/*
+ * Issue an API request, with reg structures supplied by the caller.
+ *
+ * Only certain routines need this (supervisor services come to mind).
+ */
+
+static int
+api_issue_regs(ah, al, bh, bl, cx, dx, parms, length, regs, sregs)
+int ah, al, bh, bl, cx, dx;
+char *parms;
+int length;
+union REGS *regs;
+struct SREGS *sregs;
+{
+ char far *ourseg = parms;
+
+ regs->h.ah = ah;
+ regs->h.al = al;
+ regs->h.bh = bh;
+ regs->h.bl = bl;
+ regs->x.cx = cx;
+ regs->x.dx = dx;
+ sregs->es = FP_SEG(ourseg);
+ regs->x.di = FP_OFF(ourseg);
+
+#if defined(MSDOS)
+ int86x(API_INTERRUPT_NUMBER, regs, regs, sregs);
+#endif /* defined(MSDOS) */
+#if defined(unix)
+ api_exch_api(regs, sregs, parms, length);
+#endif /* defined(unix) */
+
+ if (regs->h.cl != 0) {
+ api_sup_errno = regs->h.cl;
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * Issue an API request without requiring caller to supply
+ * registers. Most routines use this.
+ */
+
+static int
+api_issue(ah, al, bh, bl, cx, dx, parms, length)
+int
+ ah,
+ al,
+ bh,
+ bl,
+ cx,
+ dx;
+char *parms;
+int length; /* Length of parms */
+{
+ union REGS regs;
+ struct SREGS sregs;
+
+ return api_issue_regs(ah, al, bh, bl, cx, dx, parms, length, &regs, &sregs);
+}
+
+/*
+ * Supervisor Services
+ */
+
+int
+api_name_resolve(name)
+char *name;
+{
+ NameResolveParms parms;
+ int i;
+ union REGS regs;
+ struct SREGS sregs;
+
+ for (i = 0; i < sizeof parms.gate_name; i++) {
+ if (*name) {
+ parms.gate_name[i] = *name++;
+ } else {
+ parms.gate_name[i] = ' ';
+ }
+ }
+
+ if (api_issue_regs(NAME_RESOLUTION, 0, 0, 0, 0, 0, (char *) &parms,
+ sizeof parms, &regs, &sregs) == -1) {
+ return -1;
+ } else {
+ return regs.x.dx;
+ }
+}
+
+#if defined(unix)
+/*
+ * Block until the oia or ps is modified.
+ */
+
+int
+api_ps_or_oia_modified()
+{
+ union REGS regs;
+ struct SREGS sregs;
+
+ if (api_issue_regs(PS_OR_OIA_MODIFIED, 0, 0, 0, 0, 0, (char *) 0,
+ 0, &regs, &sregs) == -1) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+#endif /* defined(unix) */
+
+/*
+ * Session Information Services
+ */
+
+int
+api_query_session_id(parms)
+QuerySessionIdParms *parms;
+{
+ if (api_issue(0x09, QUERY_SESSION_ID, 0x80, 0x20, 0,
+ gate_sessmgr, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+
+int
+api_query_session_parameters(parms)
+QuerySessionParametersParms *parms;
+{
+ if (api_issue(0x09, QUERY_SESSION_PARAMETERS, 0x80, 0x20, 0,
+ gate_sessmgr, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+int
+api_query_session_cursor(parms)
+QuerySessionCursorParms *parms;
+{
+ if (api_issue(0x09, QUERY_SESSION_CURSOR, 0x80, 0x20, 0xff,
+ gate_sessmgr, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+/*
+ * Keyboard Services
+ */
+
+int
+api_connect_to_keyboard(parms)
+ConnectToKeyboardParms *parms;
+{
+ if (api_issue(0x09, CONNECT_TO_KEYBOARD, 0x80, 0x20, 0,
+ gate_keyboard, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+
+int
+api_disconnect_from_keyboard(parms)
+DisconnectFromKeyboardParms *parms;
+{
+ if (api_issue(0x09, DISCONNECT_FROM_KEYBOARD, 0x80, 0x20, 0,
+ gate_keyboard, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+
+int
+api_write_keystroke(parms)
+WriteKeystrokeParms *parms;
+{
+ if (api_issue(0x09, WRITE_KEYSTROKE, 0x80, 0x20, 0,
+ gate_keyboard, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+
+int
+api_disable_input(parms)
+DisableInputParms *parms;
+{
+ if (api_issue(0x09, DISABLE_INPUT, 0x80, 0x20, 0,
+ gate_keyboard, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+int
+api_enable_input(parms)
+EnableInputParms *parms;
+{
+ if (api_issue(0x09, ENABLE_INPUT, 0x80, 0x20, 0,
+ gate_keyboard, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+/*
+ * Copy Services
+ */
+
+int
+api_copy_string(parms)
+CopyStringParms *parms;
+{
+ if (api_issue(0x09, COPY_STRING, 0x80, 0x20, 0xff,
+ gate_copy, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+/*
+ * Operator Information Area Services
+ */
+
+int
+api_read_oia_group(parms)
+ReadOiaGroupParms *parms;
+{
+ if (api_issue(0x09, READ_OIA_GROUP, 0x80, 0x20, 0xff,
+ gate_oiam, (char *)parms, sizeof *parms) == -1) {
+ api_fcn_errno = 0;
+ api_fcn_fcn_id = 0;
+ return -1;
+ } else if (parms->rc == 0) {
+ return 0;
+ } else {
+ api_fcn_errno = parms->rc;
+ api_fcn_fcn_id = parms->function_id;
+ return -1;
+ }
+}
+
+/*
+ * The "we are done" routine. This gets called last.
+ */
+
+int
+api_finish()
+{
+#if defined(unix)
+ if (api_close_api() == -1) {
+ return -1;
+ } else {
+ return 0;
+ }
+#else
+ return 0;
+#endif /* defined(unix) */
+}
+
+
+/*
+ * The initialization routine. Be sure to call this first.
+ */
+
+int
+api_init()
+{
+#if defined(MSDOS)
+ union REGS regs;
+ struct SREGS sregs;
+
+ regs.h.ah = 0x35;
+ regs.h.al = API_INTERRUPT_NUMBER;
+ intdosx(&regs, &regs, &sregs);
+
+ if ((regs.x.bx == 0) && (sregs.es == 0)) {
+ return 0; /* Interrupt not being handled */
+ }
+#endif /* defined(MSDOS) */
+#if defined(unix)
+ if (api_open_api((char *)0) == -1) {
+ return 0;
+ }
+#endif /* defined(unix) */
+
+ gate_sessmgr = api_name_resolve("SESSMGR");
+ gate_keyboard = api_name_resolve("KEYBOARD");
+ gate_copy = api_name_resolve("COPY");
+ gate_oiam = api_name_resolve("OIAM");
+
+ if ((gate_sessmgr == gate_keyboard) ||
+ (gate_sessmgr == gate_copy) ||
+ (gate_sessmgr == gate_oiam) ||
+ (gate_keyboard == gate_copy) ||
+ (gate_keyboard == gate_oiam) ||
+ (gate_copy == gate_oiam)) {
+ return 0; /* Interrupt doesn't seem correct */
+ }
+ return 1;
+}
diff --git a/comms/tn3270/files/api/apilib.h b/comms/tn3270/files/api/apilib.h
new file mode 100644
index 00000000000..716d73ae512
--- /dev/null
+++ b/comms/tn3270/files/api/apilib.h
@@ -0,0 +1,58 @@
+/* $NetBSD: apilib.h,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: apilib.h,v 1.6 2003/08/07 11:16:24 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)apilib.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * What one needs to specify
+ */
+
+extern int
+ api_sup_errno, /* Supervisor error number */
+ api_sup_fcn_id, /* Supervisor function id (0x12) */
+ api_fcn_errno, /* Function error number */
+ api_fcn_fcn_id; /* Function ID (0x6b, etc.) */
+
+int api_name_resolve(char *);
+int api_ps_or_oia_modified(void);
+int api_query_session_id(QuerySessionIdParms *);
+int api_query_session_parameters(QuerySessionParametersParms *);
+int api_query_session_cursor(QuerySessionCursorParms *);
+int api_connect_to_keyboard(ConnectToKeyboardParms *);
+int api_disconnect_from_keyboard(DisconnectFromKeyboardParms *);
+int api_write_keystroke(WriteKeystrokeParms *);
+int api_disable_input(DisableInputParms *);
+int api_enable_input(EnableInputParms *);
+int api_copy_string(CopyStringParms *);
+int api_read_oia_group(ReadOiaGroupParms *);
+int api_finish(void);
+int api_init(void);
diff --git a/comms/tn3270/files/api/asc_ebc.c b/comms/tn3270/files/api/asc_ebc.c
new file mode 100644
index 00000000000..4f6115b5ce7
--- /dev/null
+++ b/comms/tn3270/files/api/asc_ebc.c
@@ -0,0 +1,116 @@
+/* $NetBSD: asc_ebc.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: asc_ebc.c,v 1.7 2003/08/07 11:16:25 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)asc_ebc.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: asc_ebc.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $");
+#endif
+#endif /* not lint */
+#endif /* ! HOST_TOOL */
+
+/*
+ * Ascii<->Ebcdic translation tables.
+ */
+
+#include "asc_ebc.h"
+
+unsigned char asc_ebc[NASCII] = {
+
+/* 00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 08 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 18 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/* 20 */ 0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+/* 28 */ 0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+/* 30 */ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+/* 38 */ 0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+/* 40 */ 0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+/* 48 */ 0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+/* 50 */ 0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+/* 58 */ 0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
+/* 60 */ 0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+/* 68 */ 0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+/* 70 */ 0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+/* 78 */ 0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x00,
+
+};
+
+/*
+ * ebcdic to ascii translation tables
+ */
+
+unsigned char ebc_asc[NEBC] = {
+/* 00 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 08 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 10 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 18 */ ' ', ' ', ' ', ' ', '*', ' ', ';', ' ',
+/* 20 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 28 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 30 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 38 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 40 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+
+/* 48 */ ' ', ' ',
+#if !defined(MSDOS)
+ /* 4A */ '\\',
+#else /* !defined(MSDOS) */
+ /* 4A */ '\233', /* PC cent sign */
+#endif /* !defined(MSDOS) */
+ /* 4B */ '.', '<', '(', '+', '|',
+
+/* 50 */ '&', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 58 */ ' ', ' ', '!', '$', '*', ')', ';', '^',
+/* 60 */ '-', '/', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 68 */ ' ', ' ', '|', ',', '%', '_', '>', '?',
+/* 70 */ ' ', '^', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 78 */ ' ', '`', ':', '#', '@', '\'', '=', '"',
+/* 80 */ ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+/* 88 */ 'h', 'i', ' ', ' ', ' ', ' ', ' ', ' ',
+/* 90 */ ' ', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+/* 98 */ 'q', 'r', ' ', ' ', ' ', ' ', ' ', ' ',
+/* A0 */ ' ', '~', 's', 't', 'u', 'v', 'w', 'x',
+/* A8 */ 'y', 'z', ' ', ' ', ' ', '[', ' ', ' ',
+/* B0 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
+/* B8 */ ' ', ' ', ' ', ' ', ' ', ']', ' ', ' ',
+/* C0 */ '{', 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+/* C8 */ 'H', 'I', ' ', ' ', ' ', ' ', ' ', ' ',
+/* D0 */ '}', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
+/* D8 */ 'Q', 'R', ' ', ' ', ' ', ' ', ' ', ' ',
+/* E0 */ '\\', ' ', 'S', 'T', 'U', 'V', 'W', 'X',
+/* E8 */ 'Y', 'Z', ' ', ' ', ' ', ' ', ' ', ' ',
+/* F0 */ '0', '1', '2', '3', '4', '5', '6', '7',
+/* F8 */ '8', '9', ' ', ' ', ' ', ' ', ' ', ' ',
+};
diff --git a/comms/tn3270/files/api/asc_ebc.h b/comms/tn3270/files/api/asc_ebc.h
new file mode 100644
index 00000000000..9f0db5a8864
--- /dev/null
+++ b/comms/tn3270/files/api/asc_ebc.h
@@ -0,0 +1,50 @@
+/* $NetBSD: asc_ebc.h,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: asc_ebc.h,v 1.5 2003/08/07 11:16:25 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)asc_ebc.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Definitions of translate tables used for ascii<->ebcdic translation.
+ */
+
+#define INCLUDED_ASCEBC
+
+/*
+ * ascii/ebcdic translation information
+ */
+
+#define NASCII 128 /* number of ascii characters */
+
+#define NEBC 256 /* number of ebcdic characters */
+
+extern unsigned char
+ asc_ebc[NASCII], ebc_asc[NEBC];
diff --git a/comms/tn3270/files/api/astosc.c b/comms/tn3270/files/api/astosc.c
new file mode 100644
index 00000000000..0c20737d13e
--- /dev/null
+++ b/comms/tn3270/files/api/astosc.c
@@ -0,0 +1,106 @@
+/* $NetBSD: astosc.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $ */
+/* From NetBSD: astosc.c,v 1.8 2006/03/20 01:34:49 gdamore Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)astosc.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: astosc.c,v 1.1.1.1 2010/01/17 01:33:17 dholland Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include <ctype.h>
+
+#include "../general/general.h"
+
+#include "../ctlr/function.h"
+
+#include "astosc.h"
+
+struct astosc astosc[256] = {
+#include "astosc.out"
+};
+
+/* compare two strings, ignoring case */
+
+static int ustrcmp(char *, char *);
+
+static int
+ustrcmp(string1, string2)
+char *string1;
+char *string2;
+{
+ int c1, c2;
+
+ while ((c1 = (unsigned char) *string1++) != 0) {
+ if (isupper(c1)) {
+ c1 = tolower(c1);
+ }
+ if (isupper(c2 = (unsigned char) *string2++)) {
+ c2 = tolower(c2);
+ }
+ if (c1 < c2) {
+ return(-1);
+ } else if (c1 > c2) {
+ return(1);
+ }
+ }
+ if (*string2) {
+ return(-1);
+ } else {
+ return(0);
+ }
+}
+
+
+/*
+ * This routine takes a string and returns an integer. It may return
+ * -1 if there is no other integer which corresponds to the
+ * string. -1 implies an error.
+ */
+
+int
+ascii_to_index(string)
+char *string;
+{
+ struct astosc *this;
+
+ for (this = astosc; this <= &astosc[highestof(astosc)]; this++) {
+ if ((this->name != 0) && (ustrcmp(this->name, string) == 0)) {
+ return this-astosc;
+ }
+ }
+ return -1;
+}
diff --git a/comms/tn3270/files/api/astosc.h b/comms/tn3270/files/api/astosc.h
new file mode 100644
index 00000000000..19d1ad9b1ae
--- /dev/null
+++ b/comms/tn3270/files/api/astosc.h
@@ -0,0 +1,57 @@
+/* $NetBSD: astosc.h,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: astosc.h,v 1.6 2003/08/07 11:16:25 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)astosc.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * This defines the structure used to translate:
+ *
+ * ascii name ==> (scancode, shiftstate)
+ *
+ * (Actually, map3270 does "ascii name ==> index", and
+ * termin does "index ==> (scancode, shiftstate)". Both
+ * mappings use this structure.)
+ */
+
+#define INCLUDED_ASTOSC
+
+struct astosc {
+ unsigned char
+ scancode, /* Scan code for this function */
+ shiftstate; /* Shift state for this function */
+ enum ctlrfcn function; /* Internal function identifier */
+ char *name; /* Name of this function */
+};
+
+int ascii_to_index(char *); /* Function to feed InitControl() */
+
+extern struct astosc astosc[256];
diff --git a/comms/tn3270/files/api/dctype.c b/comms/tn3270/files/api/dctype.c
new file mode 100644
index 00000000000..2da7d1bf5b0
--- /dev/null
+++ b/comms/tn3270/files/api/dctype.c
@@ -0,0 +1,249 @@
+/* $NetBSD: dctype.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: dctype.c,v 1.6 2003/08/07 11:16:25 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)dctype.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: dctype.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "dctype.h"
+
+unsigned char dctype[192] = {
+/*00*/
+ D_SPACE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+/*10*/
+ D_SPACE,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ 0,
+ 0,
+ 0,
+ 0,
+/*20*/
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ D_DIGIT|D_PRINT,
+ 0,
+ 0,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+/*30*/
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+ 0,
+ 0,
+ 0,
+ 0,
+ D_PUNCT|D_PRINT,
+ 0,
+ D_PUNCT|D_PRINT,
+ 0,
+ 0,
+/*40*/
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*50*/
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*60*/
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*70*/
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*80*/
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+/*90*/
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ D_LOWER|D_PRINT,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+/*A0*/
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+/*B0*/
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ D_UPPER|D_PRINT,
+ 0,
+ 0,
+ 0,
+ 0,
+ D_PUNCT|D_PRINT,
+ D_PUNCT|D_PRINT,
+};
diff --git a/comms/tn3270/files/api/dctype.h b/comms/tn3270/files/api/dctype.h
new file mode 100644
index 00000000000..6b4c096f0ea
--- /dev/null
+++ b/comms/tn3270/files/api/dctype.h
@@ -0,0 +1,53 @@
+/* $NetBSD: dctype.h,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: dctype.h,v 1.5 2003/08/07 11:16:26 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)dctype.h 4.2 (Berkeley) 4/26/91
+ */
+
+#define INCLUDED_ECTYPE
+
+#define D_UPPER 0x01
+#define D_LOWER 0x02
+#define D_DIGIT 0x04
+#define D_SPACE 0x08
+#define D_PUNCT 0x10
+#define D_PRINT 0x20
+
+#define Disalpha(c) (dctype[(c)]&(D_UPPER|D_LOWER))
+#define Disupper(c) (dctype[(c)]&D_UPPER)
+#define Dislower(c) (dctype[(c)]&D_LOWER)
+#define Disdigit(c) (dctype[(c)]&D_DIGIT)
+#define Disalnum(c) (dctype[(c)]&(D_UPPER|D_LOWER|D_DIGIT))
+#define Disspace(c) (dctype[(c)]&D_SPACE) /* blank or null */
+#define Dispunct(c) (dctype[(c)]&D_PUNCT)
+#define Disprint(c) (dctype[(c)]&D_PRINT)
+
+extern unsigned char dctype[192];
diff --git a/comms/tn3270/files/api/disp_asc.c b/comms/tn3270/files/api/disp_asc.c
new file mode 100644
index 00000000000..39d25a12726
--- /dev/null
+++ b/comms/tn3270/files/api/disp_asc.c
@@ -0,0 +1,49 @@
+/* $NetBSD: disp_asc.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: disp_asc.c,v 1.6 2003/08/07 11:16:26 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)disp_asc.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: disp_asc.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * There isn't much excuse for this file, but here it is.
+ */
+
+#include "disp_asc.h"
+
+#include "asc_disp.out"
+#include "disp_asc.out"
diff --git a/comms/tn3270/files/api/disp_asc.h b/comms/tn3270/files/api/disp_asc.h
new file mode 100644
index 00000000000..f466186805e
--- /dev/null
+++ b/comms/tn3270/files/api/disp_asc.h
@@ -0,0 +1,42 @@
+/* $NetBSD: disp_asc.h,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: disp_asc.h,v 1.5 2003/08/07 11:16:26 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)disp_asc.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Define the translate tables used to go between 3270 display code
+ * and ascii
+ */
+
+extern unsigned char
+ disp_asc[256], /* Goes between display code and ascii */
+ asc_disp[256]; /* Goes between ascii and display code */
diff --git a/comms/tn3270/files/api/ebc_disp.c b/comms/tn3270/files/api/ebc_disp.c
new file mode 100644
index 00000000000..0b6ae04e539
--- /dev/null
+++ b/comms/tn3270/files/api/ebc_disp.c
@@ -0,0 +1,112 @@
+/* $NetBSD: ebc_disp.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: ebc_disp.c,v 1.7 2003/08/07 11:16:26 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)ebc_disp.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: ebc_disp.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $");
+#endif
+#endif /* not lint */
+#endif /* ! HOST_TOOL */
+
+/*
+ * Translate table to map EBCDIC into 3270 display codes.
+ */
+
+unsigned char ebc_disp[256] = {
+/*00*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*08*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*10*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*18*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*20*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*28*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*30*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*38*/ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+/*40*/ 0x10, 0x0a, 0x0b, 0x1c, 0x1d, 0x1e, 0x1f, 0x2a,
+/*48*/ 0x2b, 0x37, 0x1b, 0x32, 0x09, 0x0d, 0x35, 0x16,
+/*50*/ 0x30, 0x38, 0x39, 0x3a, 0x3c, 0x3e, 0x3f, 0x40,
+/*58*/ 0x41, 0x42, 0x19, 0x1a, 0xbf, 0x0c, 0xbe, 0x36,
+/*60*/ 0x31, 0x14, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+/*68*/ 0x49, 0x4a, 0x17, 0x33, 0x2e, 0x2f, 0x08, 0x18,
+/*70*/ 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
+/*78*/ 0x53, 0x3d, 0x34, 0x2c, 0x2d, 0x12, 0x11, 0x13,
+/*80*/ 0x54, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86,
+/*88*/ 0x87, 0x88, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a,
+/*90*/ 0x5b, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+/*98*/ 0x90, 0x91, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,
+/*A0*/ 0x62, 0x3b, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+/*A8*/ 0x98, 0x99, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+/*B0*/ 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
+/*B8*/ 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+/*C0*/ 0x0f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6,
+/*C8*/ 0xa7, 0xa8, 0x79, 0x7a, 0x7b, 0x7c, 0x01, 0x02,
+/*D0*/ 0x0e, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+/*D8*/ 0xb0, 0xb1, 0x7d, 0x7e, 0x7f, 0x03, 0x04, 0x05,
+/*E0*/ 0x15, 0x9a, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+/*E8*/ 0xb8, 0xb9, 0x9b, 0x9c, 0x9d, 0x06, 0x07, 0x9e,
+/*F0*/ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+/*F8*/ 0x28, 0x29, 0xba, 0xbb, 0xbc, 0xbd, 0x9f, 0x00,
+};
+
+/*
+ * Translate table to map 3270 display codes to EBCDIC.
+ */
+
+unsigned char disp_ebc[192] = {
+/*00*/ 0x00, 0xce, 0xcf, 0xdd, 0xde, 0xdf, 0xed, 0xee,
+/*08*/ 0x6e, 0x4c, 0x41, 0x42, 0x5d, 0x4d, 0xd0, 0xc0,
+/*10*/ 0x40, 0x7e, 0x7d, 0x7f, 0x61, 0xe0, 0x4f, 0x6a,
+/*18*/ 0x6f, 0x5a, 0x5b, 0x4a, 0x43, 0x44, 0x45, 0x46,
+/*20*/ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+/*28*/ 0xf8, 0xf9, 0x47, 0x48, 0x7b, 0x7c, 0x6c, 0x6d,
+/*30*/ 0x50, 0x60, 0x4b, 0x6b, 0x7a, 0x4e, 0x5f, 0x49,
+/*38*/ 0x51, 0x52, 0x53, 0xa1, 0x54, 0x79, 0x55, 0x56,
+/*40*/ 0x57, 0x58, 0x59, 0x62, 0x63, 0x64, 0x65, 0x66,
+/*48*/ 0x67, 0x68, 0x69, 0x70, 0x71, 0x72, 0x73, 0x74,
+/*50*/ 0x75, 0x76, 0x77, 0x78, 0x80, 0x8a, 0x8b, 0x8c,
+/*58*/ 0x8d, 0x8e, 0x8f, 0x90, 0x9a, 0x9b, 0x9c, 0x9d,
+/*60*/ 0x9e, 0x9f, 0xa0, 0xaa, 0xab, 0xac, 0xad, 0xae,
+/*68*/ 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+/*70*/ 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe,
+/*78*/ 0xbf, 0xca, 0xcb, 0xcc, 0xcd, 0xda, 0xdb, 0xdc,
+/*80*/ 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
+/*88*/ 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+/*90*/ 0x98, 0x99, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+/*98*/ 0xa8, 0xa9, 0xe1, 0xea, 0xeb, 0xec, 0xef, 0xfe,
+/*A0*/ 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8,
+/*A8*/ 0xc9, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+/*B0*/ 0xd8, 0xd9, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+/*B8*/ 0xe8, 0xe9, 0xfa, 0xfb, 0xfc, 0xfd, 0x5e, 0x5c,
+};
diff --git a/comms/tn3270/files/api/ebc_disp.h b/comms/tn3270/files/api/ebc_disp.h
new file mode 100644
index 00000000000..6a50c7ad4d3
--- /dev/null
+++ b/comms/tn3270/files/api/ebc_disp.h
@@ -0,0 +1,37 @@
+/* $NetBSD: ebc_disp.h,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: ebc_disp.h,v 1.5 2003/08/07 11:16:26 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ebc_disp.h 4.2 (Berkeley) 4/26/91
+ */
+
+extern unsigned char
+ ebc_disp[256],
+ disp_ebc[192];
diff --git a/comms/tn3270/files/ascii/ascii.order b/comms/tn3270/files/ascii/ascii.order
new file mode 100644
index 00000000000..01df31d955a
--- /dev/null
+++ b/comms/tn3270/files/ascii/ascii.order
@@ -0,0 +1,2 @@
+map3270.o
+termin.o
diff --git a/comms/tn3270/files/ascii/default.map b/comms/tn3270/files/ascii/default.map
new file mode 100644
index 00000000000..57d8611badb
--- /dev/null
+++ b/comms/tn3270/files/ascii/default.map
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)default.map 4.2 (Berkeley) 4/26/91
+ */
+
+/* default.map3270: This file is the system default for the key sequence
+ * if neither the user's TERM nor "unknown" are found in either of
+ * MAP3270 or /usr/share/misc/map3270.
+ *
+ *
+ */
+#if defined(MSDOS)
+"tn3270pc{",
+" ENTER='^M';CLEAR='^Z'|'^Aw';NL='^N'|'^AO';TAB='^I';DP='^U';FM='^Y';",
+" BTAB='^B'|'^[^I'|'^A^O';LEFT='^H'|'^AK';RIGHT='^L'|'^AM';UP='^K'|'^AH';",
+" DOWN='^J'|'^AP';HOME='^^'|'^AG';DELETE='^AS'|'^D';EINP='^W';FLINP='^X';",
+" EEOF='^E'|'^Au';WERASE='^As';FERASE='^At';INSRT='^[ '|'^AR';CURSEL='^[.';",
+" PFK1='^A;'|'^F01'|'^[1'|'^Ax';PFK2='^A<'|'^F02'|'^[2'|'^Ay';SETTAB='^[;';",
+" PFK3='^A='|'^F03'|'^[3'|'^Az';CLRTAB='^[+'|'^[:';SETMRG='^[(';",
+" PFK4='^A>'|'^F04'|'^[4'|'^A{';PFK5='^A?'|'^F05'|'^[5'|'^A|';",
+" PFK6='^A@'|'^F06'|'^[6'|'^A}';PFK7='^AA'|'^AI'|'^F07'|'^[7'|'^A~';",
+" PFK8='^AB'|'^AQ'|'^F08'|'^[8'|'^A^?';PFK9='^AC'|'^F09'|'^[9'|'^A^A^@';",
+" PFK10='^AD'|'^F10'|'^[0'|'^A^A^A';SETHOM='^[!';COLTAB='^[i'|'^[I';",
+" COLBAK='^[b'|'^[B';INDENT='^[l'|'^[L';UNDENT='^[h'|'^[H';",
+" PFK11='^AT'|'^F11'|'^[-'|'^A^A^B';PFK12='^AU'|'^F12'|'^A^A^C'|'^[=';",
+" PFK13='^AV'|'^F13';PFK14='^AW'|'^F14';PFK15='^AX'|'^F15';",
+" PFK16='^AY'|'^F16';",
+" PFK17='^AZ'|'^F17';PFK18='^A['|'^F18';PFK19='^A\\\\'|'^F19';",
+" PFK20='^A]'|'^F20';PFK21='^A\\^'|'^F21';PFK22='^A_'|'^F22';PA3='^Aj'|'^P3';",
+" PFK23='^A`'|'^F23';PFK24='^Aa'|'^F24';PA1='^Ah'|'^P1';PA2='^Ai'|'^P2';",
+" RESET='^T'|'^R'; ",
+" MASTER_RESET='^G';RESHOW='^V';DELTAB='^[\\\'';ESCAPE='^C';",
+"}",
+#else /* defined(MSDOS) */
+"generic { clear = '^z'; flinp = '^x'; enter = '^m'; delete = '^d' | '^?';",
+" synch = '^r'; reshow = '^v'; eeof = '^e'; tab = '^i';",
+" btab = '^b'; nl = '^n'; left = '^h'; right = '^l';",
+" up = '^k'; down = '^j'; einp = '^w'; reset = '^t';",
+" xoff = '^s'; xon = '^q'; escape = '^c'; ferase = '^u';",
+" insrt = '\\E ';",
+" pa1 = '^p1'; pa2 = '^p2'; pa3 = '^p3';",
+" pfk1 = '\\E1'; pfk2 = '\\E2'; pfk3 = '\\E3'; pfk4 = '\\E4';",
+" pfk5 = '\\E5'; pfk6 = '\\E6'; pfk7 = '\\E7'; pfk8 = '\\E8';",
+" pfk9 = '\\E9'; pfk10 = '\\E0'; pfk11 = '\\E-'; pfk12 = '\\E=';",
+" pfk13 = '\\E!'; pfk14 = '\\E@'; pfk15 = '\\E#'; pfk16 = '\\E$';",
+" pfk17 = '\\E%'; pfk18 = '\\E\\^'; pfk19 = '\\E&'; pfk20 = '\\E*';",
+" pfk21 = '\\E('; pfk22 = '\\E)'; pfk23 = '\\E_'; pfk24 = '\\E+';",
+"}",
+#endif /* defined(MSDOS) */
diff --git a/comms/tn3270/files/ascii/map3270.c b/comms/tn3270/files/ascii/map3270.c
new file mode 100644
index 00000000000..b5c666b550a
--- /dev/null
+++ b/comms/tn3270/files/ascii/map3270.c
@@ -0,0 +1,957 @@
+/* $NetBSD: map3270.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: map3270.c,v 1.15 2006/04/30 23:49:34 christos Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)map3270.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: map3270.c,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/* This program reads a description file, somewhat like /etc/termcap,
+ that describes the mapping between the current terminal's keyboard and
+ a 3270 keyboard.
+ */
+#ifdef DOCUMENTATION_ONLY
+/* here is a sample (very small) entry...
+
+ # this table is sensitive to position on a line. In particular,
+ # a terminal definition for a terminal is terminated whenever a
+ # (non-comment) line beginning in column one is found.
+ #
+ # this is an entry to map tvi924 to 3270 keys...
+ v8|tvi924|924|televideo model 924 {
+ pfk1 = '\E1';
+ pfk2 = '\E2';
+ clear = '^z'; # clear the screen
+ }
+ */
+#endif /* DOCUMENTATION_ONLY */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define IsPrint(c) ((isprint((unsigned char)c) && !isspace((unsigned char)c)) || ((c) == ' '))
+
+#include "state.h"
+#include "map3270.h"
+
+#include "../general/globals.h"
+
+/* this is the list of types returned by the lex processor */
+#define LEX_CHAR 400 /* plain unadorned character */
+#define LEX_ESCAPED LEX_CHAR+1 /* escaped with \ */
+#define LEX_CARETED LEX_ESCAPED+1 /* escaped with ^ */
+#define LEX_END_OF_FILE LEX_CARETED+1 /* end of file encountered */
+#define LEX_ILLEGAL LEX_END_OF_FILE+1 /* trailing escape character */
+
+/* the following is part of our character set dependency... */
+#define ESCAPE 0x1b
+#define TAB 0x09
+#define NEWLINE 0x0a
+#define CARRIAGE_RETURN 0x0d
+
+typedef struct {
+ int type; /* LEX_* - type of character */
+ int value; /* character this was */
+} lexicon;
+
+typedef struct {
+ int length; /* length of character string */
+ char array[500]; /* character string */
+} stringWithLength;
+
+#define panic(s) { fprintf(stderr, "%s", s); exit(1); }
+
+static state firstentry = { 0, STATE_NULL, 0, 0 };
+static state *headOfQueue = &firstentry;
+
+/* the following is a primitive adm3a table, to be used when nothing
+ * else seems to be available.
+ */
+
+#ifdef DEBUG
+static int debug = 0; /* debug flag (for debuggin tables) */
+#endif /* DEBUG */
+
+static int (*GetTc)(char *);
+static int doPaste = 1; /* should we have side effects */
+static int picky = 0; /* do we complain of unknown functions? */
+static char usePointer = 0; /* use pointer, or file */
+static FILE *ourFile= 0;
+static char *environPointer = 0;/* if non-zero, point to input
+ * string in core.
+ */
+static char **whichkey = 0;
+static char *keysgeneric[] = {
+#include "default.map" /* Define the default default */
+
+ 0, /* Terminate list of entries */
+};
+ ;
+
+static int Empty = 1, /* is the unget lifo empty? */
+ Full = 0; /* is the unget lifo full? */
+static lexicon lifo[200]; /* character stack for parser */
+static int rp = 0, /* read pointer into lifo */
+ wp = 0; /* write pointer into lifo */
+
+static int GetC(void);
+static lexicon Get(void);
+static void UnGet(lexicon);
+static stringWithLength *GetQuotedString(void);
+#ifdef NOTUSED
+static stringWithLength *GetCharString(void);
+#endif
+static int GetCharacter(int);
+#ifdef NOTUSED
+static int GetString(char *);
+#endif
+static stringWithLength *GetAlphaMericString(void);
+static lexicon EatToNL(void);
+static void GetWS(void);
+static void FreeState(state *);
+static state *GetState(void);
+static state *FindMatchAtThisLevel(state *, int);
+static state *PasteEntry(state *, char *, int, char *);
+static int GetInput(int, char *);
+static int GetDefinition(void);
+static int GetDefinitions(void);
+static int GetBegin(void);
+static int GetEnd(void);
+static int GetName(void);
+static int GetNames(void);
+static int GetEntry0(void);
+static int GetEntry(void);
+
+static int
+GetC()
+{
+ int character;
+
+ if (usePointer) {
+ if ((*environPointer) == 0) {
+ /*
+ * If we have reached the end of this string, go on to
+ * the next (if there is a next).
+ */
+ if (whichkey == 0) {
+ static char suffix = 'A'; /* From environment */
+ char envname[9];
+
+ (void) sprintf(envname, "MAP3270%c", suffix++);
+ environPointer = getenv(envname);
+ } else {
+ whichkey++; /* default map */
+ environPointer = *whichkey;
+ }
+ }
+ if (*environPointer) {
+ character = 0xff&*environPointer++;
+ } else {
+ character = EOF;
+ }
+ } else {
+ character = getc(ourFile);
+ }
+ return(character);
+}
+
+static lexicon
+Get()
+{
+ lexicon c;
+ lexicon *pC = &c;
+ int character;
+
+ if (!Empty) {
+ *pC = lifo[rp];
+ rp++;
+ if (rp == sizeof lifo/sizeof (lexicon)) {
+ rp = 0;
+ }
+ if (rp == wp) {
+ Empty = 1;
+ }
+ Full = 0;
+ } else {
+ character = GetC();
+ switch (character) {
+ case EOF:
+ pC->type = LEX_END_OF_FILE;
+ break;
+ case '^':
+ character = GetC();
+ if (!IsPrint(character)) {
+ pC->type = LEX_ILLEGAL;
+ } else {
+ pC->type = LEX_CARETED;
+ if (character == '?') {
+ character |= 0x40; /* rubout */
+ } else {
+ character &= 0x1f;
+ }
+ }
+ break;
+ case '\\':
+ character = GetC();
+ if (!IsPrint(character)) {
+ pC->type = LEX_ILLEGAL;
+ } else {
+ pC->type = LEX_ESCAPED;
+ switch (character) {
+ case 'E': case 'e':
+ character = ESCAPE;
+ break;
+ case 't':
+ character = TAB;
+ break;
+ case 'n':
+ character = NEWLINE;
+ break;
+ case 'r':
+ character = CARRIAGE_RETURN;
+ break;
+ default:
+ pC->type = LEX_ILLEGAL;
+ break;
+ }
+ }
+ break;
+ default:
+ if ((IsPrint(character)) || isspace(character)) {
+ pC->type = LEX_CHAR;
+ } else {
+ pC->type = LEX_ILLEGAL;
+ }
+ break;
+ }
+ pC->value = character;
+ }
+ return(*pC);
+}
+
+static void
+UnGet(c)
+lexicon c; /* character to unget */
+{
+ if (Full) {
+ fprintf(stderr, "attempt to put too many characters in lifo\n");
+ panic("map3270");
+ /* NOTREACHED */
+ } else {
+ lifo[wp] = c;
+ wp++;
+ if (wp == sizeof lifo/sizeof (lexicon)) {
+ wp = 0;
+ }
+ if (wp == rp) {
+ Full = 1;
+ }
+ Empty = 0;
+ }
+}
+
+/*
+ * Construct a control character sequence
+ * for a special character.
+ */
+char *
+uncontrol(c)
+ int c;
+{
+ static char buf[3];
+
+ if (c == 0x7f)
+ return ("^?");
+ if (c == '\377') {
+ return "-1";
+ }
+ if (c >= 0x20) {
+ buf[0] = c;
+ buf[1] = 0;
+ } else {
+ buf[0] = '^';
+ buf[1] = '@'+c;
+ buf[2] = 0;
+ }
+ return (buf);
+}
+
+/* compare two strings, ignoring case */
+
+int
+ustrcmp(string1, string2)
+char *string1;
+char *string2;
+{
+ int c1, c2;
+
+ while ((c1 = (unsigned char) *string1++) != 0) {
+ if (isupper(c1)) {
+ c1 = tolower(c1);
+ }
+ if (isupper(c2 = (unsigned char) *string2++)) {
+ c2 = tolower(c2);
+ }
+ if (c1 < c2) {
+ return(-1);
+ } else if (c1 > c2) {
+ return(1);
+ }
+ }
+ if (*string2) {
+ return(-1);
+ } else {
+ return(0);
+ }
+}
+
+
+static stringWithLength *
+GetQuotedString()
+{
+ lexicon lex;
+ static stringWithLength output = { 0 }; /* where return value is held */
+ char *pointer = output.array;
+
+ lex = Get();
+ if ((lex.type != LEX_CHAR) || (lex.value != '\'')) {
+ UnGet(lex);
+ return(0);
+ }
+ while (1) {
+ lex = Get();
+ if ((lex.type == LEX_CHAR) && (lex.value == '\'')) {
+ break;
+ }
+ if ((lex.type == LEX_CHAR) && !IsPrint(lex.value)) {
+ UnGet(lex);
+ return(0); /* illegal character in quoted string */
+ }
+ if (pointer >= output.array+sizeof output.array) {
+ return(0); /* too long */
+ }
+ *pointer++ = lex.value;
+ }
+ output.length = pointer-output.array;
+ return(&output);
+}
+
+#ifdef NOTUSED
+static stringWithLength *
+GetCharString()
+{
+ lexicon lex;
+ static stringWithLength output;
+ char *pointer = output.array;
+
+ lex = Get();
+
+ while ((lex.type == LEX_CHAR) &&
+ !isspace(lex.value) && (lex.value != '=')) {
+ *pointer++ = lex.value;
+ lex = Get();
+ if (pointer >= output.array + sizeof output.array) {
+ return(0); /* too long */
+ }
+ }
+ UnGet(lex);
+ output.length = pointer-output.array;
+ return(&output);
+}
+#endif /* NOTUSED */
+
+static int
+GetCharacter(character)
+int character; /* desired character */
+{
+ lexicon lex;
+
+ lex = Get();
+
+ if ((lex.type != LEX_CHAR) || (lex.value != character)) {
+ UnGet(lex);
+ return(0);
+ }
+ return(1);
+}
+
+#ifdef NOTUSED
+static int
+GetString(string)
+char *string; /* string to get */
+{
+ lexicon lex;
+
+ while (*string) {
+ lex = Get();
+ if ((lex.type != LEX_CHAR) || (lex.value != *string&0xff)) {
+ UnGet(lex);
+ return(0); /* XXX restore to state on entry */
+ }
+ string++;
+ }
+ return(1);
+}
+#endif /* NOTUSED */
+
+
+static stringWithLength *
+GetAlphaMericString()
+{
+ lexicon lex;
+ static stringWithLength output = { 0 };
+ char *pointer = output.array;
+# define IsAlnum(c) (isalnum(c) || (c == '_') \
+ || (c == '-') || (c == '.'))
+
+ lex = Get();
+
+ if ((lex.type != LEX_CHAR) || !IsAlnum(lex.value)) {
+ UnGet(lex);
+ return(0);
+ }
+
+ while ((lex.type == LEX_CHAR) && IsAlnum(lex.value)) {
+ *pointer++ = lex.value;
+ lex = Get();
+ }
+ UnGet(lex);
+ *pointer = 0;
+ output.length = pointer-output.array;
+ return(&output);
+}
+
+
+/* eat up characters until a new line, or end of file. returns terminating
+ character.
+ */
+
+static lexicon
+EatToNL()
+{
+ lexicon lex;
+
+ lex = Get();
+
+ while (!((lex.type != LEX_ESCAPED) && (lex.type != LEX_CARETED) &&
+ (lex.value == '\n')) && (!(lex.type == LEX_END_OF_FILE))) {
+ lex = Get();
+ }
+ if (lex.type != LEX_END_OF_FILE) {
+ return(Get());
+ } else {
+ return(lex);
+ }
+}
+
+
+static void
+GetWS()
+{
+ lexicon lex;
+
+ lex = Get();
+
+ while ((lex.type == LEX_CHAR) &&
+ (isspace(lex.value) || (lex.value == '#'))) {
+ if (lex.value == '#') {
+ lex = EatToNL();
+ } else {
+ lex = Get();
+ }
+ }
+ UnGet(lex);
+}
+
+static void
+FreeState(pState)
+state *pState;
+{
+ free((char *)pState);
+}
+
+
+static state *
+GetState()
+{
+ state *pState;
+
+ pState = (state *) malloc(sizeof (state));
+
+ pState->result = STATE_NULL;
+ pState->next = 0;
+
+ return(pState);
+}
+
+
+static state *
+FindMatchAtThisLevel(pState, character)
+state *pState;
+int character;
+{
+ while (pState) {
+ if (pState->match == character) {
+ return(pState);
+ }
+ pState = pState->next;
+ }
+ return(0);
+}
+
+
+static state *
+PasteEntry(head, string, count, identifier)
+state *head; /* points to who should point here... */
+char *string; /* which characters to paste */
+int count; /* number of character to do */
+char *identifier; /* for error messages */
+{
+ state *pState, *other;
+
+ if (!doPaste) { /* flag to not have any side effects */
+ return((state *)1);
+ }
+ if (!count) {
+ return(head); /* return pointer to the parent */
+ }
+ if ((head->result != STATE_NULL) && (head->result != STATE_GOTO)) {
+ /* this means that a previously defined sequence is an initial
+ * part of this one.
+ */
+ fprintf(stderr, "Conflicting entries found when scanning %s\n",
+ identifier);
+ return(0);
+ }
+# ifdef DEBUG
+ if (debug) {
+ fprintf(stderr, "%s", uncontrol(*string));
+ }
+# endif /* DEBUG */
+ pState = GetState();
+ pState->match = *string;
+ if (head->result == STATE_NULL) {
+ head->result = STATE_GOTO;
+ head->address = pState;
+ other = pState;
+ } else { /* search for same character */
+ if ((other = FindMatchAtThisLevel(head->address, *string)) != 0) {
+ FreeState(pState);
+ } else {
+ pState->next = head->address;
+ head->address = pState;
+ other = pState;
+ }
+ }
+ return(PasteEntry(other, string+1, count-1, identifier));
+}
+
+static int
+GetInput(tc, identifier)
+int tc;
+char *identifier; /* entry being parsed (for error messages) */
+{
+ stringWithLength *outputString;
+ state *head;
+ state fakeQueue;
+
+ if (doPaste) {
+ head = headOfQueue; /* always points to level above this one */
+ } else {
+ head = &fakeQueue; /* don't have any side effects... */
+ }
+
+ if ((outputString = GetQuotedString()) == 0) {
+ return(0);
+ } else if (IsPrint(outputString->array[0])) {
+ fprintf(stderr,
+ "first character of sequence for %s is not a control type character\n",
+ identifier);
+ return(0);
+ } else {
+ if ((head = PasteEntry(head, outputString->array,
+ outputString->length, identifier)) == 0) {
+ return(0);
+ }
+ GetWS();
+ while ((outputString = GetQuotedString()) != 0) {
+ if ((head = PasteEntry(head, outputString->array,
+ outputString->length, identifier)) == 0) {
+ return(0);
+ }
+ GetWS();
+ }
+ }
+ if (!doPaste) {
+ return(1);
+ }
+ if ((head->result != STATE_NULL) && (head->result != tc)) {
+ /* this means that this sequence is an initial part
+ * of a previously defined one.
+ */
+ fprintf(stderr, "Conflicting entries found when scanning %s\n",
+ identifier);
+ return(0);
+ } else {
+ head->result = tc;
+ return(1); /* done */
+ }
+}
+
+static int
+GetDefinition()
+{
+ stringWithLength *string;
+ int Tc;
+
+ GetWS();
+ if ((string = GetAlphaMericString()) == 0) {
+ return(0);
+ }
+ string->array[string->length] = 0;
+ if (doPaste) {
+ if ((Tc = (*GetTc)(string->array)) == -1) {
+ if (picky) {
+ fprintf(stderr, "%s: unknown 3270 key identifier\n",
+ string->array);
+ }
+ Tc = STATE_NULL;
+ }
+ } else {
+ Tc = STATE_NULL; /* XXX ? */
+ }
+ GetWS();
+ if (!GetCharacter('=')) {
+ fprintf(stderr,
+ "Required equal sign after 3270 key identifier %s missing\n",
+ string->array);
+ return(0);
+ }
+ GetWS();
+ if (!GetInput(Tc, string->array)) {
+ fprintf(stderr, "Missing definition part for 3270 key %s\n",
+ string->array);
+ return(0);
+ } else {
+ GetWS();
+ while (GetCharacter('|')) {
+# ifdef DEBUG
+ if (debug) {
+ fprintf(stderr, " or ");
+ }
+# endif /* DEBUG */
+ GetWS();
+ if (!GetInput(Tc, string->array)) {
+ fprintf(stderr, "Missing definition part for 3270 key %s\n",
+ string->array);
+ return(0);
+ }
+ GetWS();
+ }
+ }
+ GetWS();
+ if (!GetCharacter(';')) {
+ fprintf(stderr, "Missing semi-colon for 3270 key %s\n", string->array);
+ return(0);
+ }
+# ifdef DEBUG
+ if (debug) {
+ fprintf(stderr, ";\n");
+ }
+# endif /* DEBUG */
+ return(1);
+}
+
+
+static int
+GetDefinitions()
+{
+ if (!GetDefinition()) {
+ return(0);
+ } else {
+ while (GetDefinition()) {
+ ;
+ }
+ }
+ return(1);
+}
+
+static int
+GetBegin()
+{
+ GetWS();
+ if (!GetCharacter('{')) {
+ return(0);
+ }
+ return(1);
+}
+
+static int
+GetEnd()
+{
+ GetWS();
+ if (!GetCharacter('}')) {
+ return(0);
+ }
+ return(1);
+}
+
+static int
+GetName()
+{
+ if (!GetAlphaMericString()) {
+ return(0);
+ }
+ GetWS();
+ while (GetAlphaMericString()) {
+ GetWS();
+ }
+ return(1);
+}
+
+static int
+GetNames()
+{
+ GetWS();
+ if (!GetName()) {
+ return(0);
+ } else {
+ GetWS();
+ while (GetCharacter('|')) {
+ GetWS();
+ if (!GetName()) {
+ return(0);
+ }
+ }
+ }
+ return(1);
+}
+
+static int
+GetEntry0()
+{
+ if (!GetBegin()) {
+ fprintf(stderr, "no '{'\n");
+ return(0);
+ } else if (!GetDefinitions()) {
+ fprintf(stderr, "unable to parse the definitions\n");
+ return(0);
+ } else if (!GetEnd()) {
+ fprintf(stderr, "No '}' or scanning stopped early due to error.\n");
+ return(0);
+ } else {
+ /* done */
+ return(1);
+ }
+}
+
+
+static int
+GetEntry()
+{
+ if (!GetNames()) {
+ fprintf(stderr, "Invalid name field in entry.\n");
+ return(0);
+ } else {
+ return(GetEntry0());
+ }
+}
+
+/* position ourselves within a given filename to the entry for the current
+ * KEYBD (or TERM) variable
+ */
+
+int
+Position(filename, keybdPointer)
+char *filename;
+char *keybdPointer;
+{
+ lexicon lex;
+ stringWithLength *name = 0;
+ stringWithLength *oldName;
+# define Return(x) {doPaste = 1; return(x);}
+
+ doPaste = 0;
+
+ if ((ourFile = fopen(filename, "r")) == NULL) {
+# if !defined(MSDOS)
+ fprintf(stderr, "Unable to open file %s\n", filename);
+# endif /* !defined(MSDOS) */
+ Return(0);
+ }
+ lex = Get();
+ while (lex.type != LEX_END_OF_FILE) {
+ UnGet(lex);
+ /* now, find an entry that is our type. */
+ GetWS();
+ oldName = name;
+ if ((name = GetAlphaMericString()) != 0) {
+ if (!ustrcmp(name->array, keybdPointer)) {
+ /* need to make sure there is a name here... */
+ lex.type = LEX_CHAR;
+ lex.value = 'a';
+ UnGet(lex);
+ Return(1);
+ }
+ } else if (GetCharacter('|')) {
+ ; /* more names coming */
+ } else {
+ lex = Get();
+ UnGet(lex);
+ if (lex.type != LEX_END_OF_FILE) {
+ if (!GetEntry0()) { /* start of an entry */
+ fprintf(stderr,
+ "error was in entry for %s in file %s\n",
+ (oldName)? oldName->array:"(unknown)", filename);
+ Return(0);
+ }
+ }
+ }
+ lex = Get();
+ }
+#if !defined(MSDOS)
+ fprintf(stderr, "Unable to find entry for %s in file %s\n", keybdPointer,
+ filename);
+#endif /* !defined(MSDOS) */
+ Return(0);
+}
+
+char *
+strsave(string)
+char *string;
+{
+ char *p;
+
+ p = malloc((unsigned int)strlen(string)+1);
+ if (p != 0) {
+ strcpy(p, string);
+ }
+ return(p);
+}
+
+
+/*
+ * InitControl - our interface to the outside. What we should
+ * do is figure out keyboard (or terminal) type, set up file pointer
+ * (or string pointer), etc.
+ */
+
+state *
+InitControl(keybdPointer, pickyarg, translator)
+char *keybdPointer;
+int pickyarg; /* Should we be picky? */
+int (*translator)(char *); /* Translates ascii string to integer */
+{
+ int GotIt;
+
+ picky = pickyarg;
+ GetTc = translator;
+
+ if (keybdPointer == 0) {
+ keybdPointer = getenv("KEYBD");
+ }
+ if (keybdPointer == 0) {
+ keybdPointer = getenv("TERM");
+ }
+
+ /*
+ * Some environments have getenv() return
+ * out of a static area. So, save the keyboard name.
+ */
+ if (keybdPointer) {
+ keybdPointer = strsave(keybdPointer);
+ }
+ environPointer = getenv("MAP3270");
+ if (keybdPointer && environPointer
+ && (environPointer[0] != '/')
+#if defined(MSDOS)
+ && (environPointer[0] != '\\')
+#endif /* defined(MSDOS) */
+ && (strncmp(keybdPointer, environPointer,
+ strlen(keybdPointer) != 0)
+ || (environPointer[strlen(keybdPointer)] != '{'))) /* } */
+ {
+ environPointer = 0;
+ }
+
+ if ((!environPointer)
+#if defined(MSDOS)
+ || (*environPointer == '\\')
+#endif /* defined(MSDOS) */
+ || (*environPointer == '/')) {
+ usePointer = 0;
+ GotIt = 0;
+ if (!keybdPointer) {
+#if !defined(MSDOS)
+ fprintf(stderr, "%s%s%s%s",
+ "Neither the KEYBD environment variable nor the TERM ",
+ "environment variable\n(one of which is needed to determine ",
+ "the type of keyboard you are using)\n",
+ "is set. To set it, say 'setenv KEYBD <type>'\n");
+#endif /* !defined(MSDOS) */
+ } else {
+ if (environPointer) {
+ GotIt = Position(environPointer, keybdPointer);
+ }
+ if (!GotIt) {
+ GotIt = Position("/usr/share/misc/map3270", keybdPointer);
+ }
+ }
+ if (!GotIt) {
+ if (environPointer) {
+ GotIt = Position(environPointer, "unknown");
+ }
+ if (!GotIt && keybdPointer) {
+ GotIt = Position("/usr/share/misc/map3270", keybdPointer);
+ }
+ }
+ if (!GotIt) {
+#if !defined(MSDOS)
+ fprintf(stderr, "Using default key mappings.\n");
+#endif /* !defined(MSDOS) */
+ usePointer = 1; /* flag use of non-file */
+ whichkey = keysgeneric;
+ environPointer = *whichkey; /* use default table */
+ }
+ } else {
+ usePointer = 1;
+ }
+ (void) GetEntry();
+ free(keybdPointer);
+ return(firstentry.address);
+}
diff --git a/comms/tn3270/files/ascii/map3270.h b/comms/tn3270/files/ascii/map3270.h
new file mode 100644
index 00000000000..16f3480f9d4
--- /dev/null
+++ b/comms/tn3270/files/ascii/map3270.h
@@ -0,0 +1,44 @@
+/* $NetBSD: map3270.h,v 1.1.1.1 2010/01/17 01:33:18 dholland Exp $ */
+/* From NetBSD: map3270.h,v 1.6 2003/08/07 11:16:28 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)map3270.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Declaration for map3270.c.
+ */
+
+/* map3270.c */
+char *uncontrol(int);
+int ustrcmp(char *, char *);
+int Position(char *, char *);
+char *strsave(char *);
+state *InitControl(char *, int, int (*)(char *));
diff --git a/comms/tn3270/files/ascii/mset.c b/comms/tn3270/files/ascii/mset.c
new file mode 100644
index 00000000000..47fbb3dcd58
--- /dev/null
+++ b/comms/tn3270/files/ascii/mset.c
@@ -0,0 +1,419 @@
+/* $NetBSD: mset.c,v 1.1.1.1 2010/01/17 01:33:19 dholland Exp $ */
+/* From NetBSD: mset.c,v 1.8 2008/07/21 14:19:26 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)mset.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mset.c,v 1.1.1.1 2010/01/17 01:33:19 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * this program outputs the user's 3270 mapping table in a form suitable
+ * for inclusion in the environment. Typically, this might be used
+ * by:
+ * setenv MAP3270 "`mset`"
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../ctlr/function.h"
+
+#include "state.h"
+#include "map3270.h"
+
+#include "../api/astosc.h"
+
+#include "../general/globals.h"
+
+struct regstate {
+ char *result;
+ char *match_start;
+ char *match_end; /* start of NEXT state's match string */
+ struct regstate *forward;
+ struct regstate *backward;
+};
+
+static struct regstate regstates[500], *rptr= 0; /* for sorting states */
+static char array[5000]; /* lot's of room */
+static int toshell = 0; /* export to shell */
+static int numbchars = 0; /* number of chars in envir. var */
+
+static int MyStrcmp(char *, char *);
+static void forwRegister(struct regstate *, struct regstate *);
+static void backRegister(struct regstate *, struct regstate *);
+static struct regstate *doRegister(struct regstate *);
+static char *addString(int, int);
+static void printString(char *, char *, char *);
+static void recurse(int, state *);
+
+int main(int, char *[]);
+
+static int
+MyStrcmp(str1, str2)
+char *str1, *str2;
+{
+ if (strncmp(str1, "PFK", 3) == 0 && strncmp(str2, "PFK", 3) == 0
+ && strlen(str1) != strlen(str2)) {
+ return(strlen(str1) - strlen(str2));
+ }
+ return(strcmp(str1, str2));
+}
+
+static void
+forwRegister(regptr, sptr)
+struct regstate *regptr, *sptr;
+{
+
+ regptr->forward = sptr->forward;
+ regptr->backward = sptr;
+ (sptr->forward)->backward = regptr;
+ sptr->forward = regptr;
+}
+
+static void
+backRegister(regptr, sptr)
+struct regstate *regptr, *sptr;
+{
+
+ regptr->forward = sptr;
+ regptr->backward = sptr->backward;
+ (sptr->backward)->forward = regptr;
+ sptr->backward = regptr;
+}
+
+static struct regstate *
+doRegister(regptr)
+struct regstate *regptr;
+{
+ static struct regstate *pivot = regstates;
+ struct regstate *sptr = pivot;
+ int check;
+
+ if (pivot == regstates) { /* first time called */
+ pivot->forward = regptr;
+ regptr->backward = pivot++;
+ pivot->backward = regptr;
+ regptr->forward = pivot++;
+ return(++regptr);
+ }
+ if ((check = MyStrcmp(regptr->result, pivot->result)) < 0) {
+ while (check < 0) {
+ if (sptr->backward == regstates) {
+ backRegister(regptr, sptr);
+ pivot = pivot->backward;
+ return(++regptr);
+ }
+ sptr = sptr->backward;
+ check = MyStrcmp(regptr->result, sptr->result);
+ }
+ forwRegister(regptr, sptr);
+ pivot = pivot->backward;
+ return(++regptr);
+ }
+ while (check > 0) {
+ if ((sptr->forward)->result == 0) {
+ forwRegister(regptr, sptr);
+ pivot = pivot->forward;
+ return(++regptr);
+ }
+ sptr = sptr->forward;
+ check = MyStrcmp(regptr->result, sptr->result);
+ }
+ backRegister(regptr, sptr);
+ if (pivot->forward->result) {
+ pivot = pivot->forward;
+ }
+ return(++regptr);
+}
+
+static char *
+addString(strcount, character)
+int strcount;
+char character;
+{
+ static char *string = array;
+ int i;
+
+ if (rptr->match_start == 0) {
+ rptr->match_start = string;
+ for (i=0; i < strcount; i++) {
+ *string++ = *((rptr-1)->match_start+i);
+ }
+ }
+ *string++ = character;
+ return(string);
+}
+
+static char savename[20] = " "; /* for deciding if name is new */
+
+static void
+printString(string, begin, tc_name)
+char *string;
+char *begin, *tc_name;
+{
+ char *st1, *st2;
+ int pchar;
+ static char suffix = 'A';
+ int new = strcmp(savename, tc_name);
+ char delim = new ? ';' : '|';
+
+ st1 = begin;
+
+ numbchars += 5 + (new ? strlen(tc_name) : -1);
+ if (toshell && numbchars > 1011) {
+ new = 1;
+ delim = ';';
+ numbchars = 5 + strlen(tc_name);
+ printf(";\nsetenv MAP3270%c ", suffix++);
+ }
+ if (strcmp(" ", savename)) {
+ if (toshell) {
+ printf("%c%c", '\\', delim);
+ }
+ else {
+ printf("%c", delim);
+ }
+ }
+ else {
+ numbchars -= 2;
+ }
+ if (toshell && new) {
+ printf("%s=%c'", tc_name,'\\');
+ }
+ else if (new) {
+ printf("%s='", tc_name);
+ }
+ else if (toshell) {
+ printf("%c'", '\\');
+ }
+ else {
+ printf("'");
+ }
+ (void) strcpy(savename, tc_name);
+ while (st1 != string) {
+ if (toshell && numbchars >= 1016) { /* leave room for ctrl and delim */
+ numbchars = 0;
+ printf(";\nsetenv MAP3270%c ", suffix++);
+ }
+ pchar = 0xff&(*st1++);
+ switch (pchar) {
+ case '"':
+ case '!':
+ case '$':
+ case '(':
+ case ')':
+ case ' ':
+ case ';':
+ case '&':
+ case '|':
+ case '>':
+ case '<':
+ case '`':
+ case '#':
+ numbchars += 2;
+ if (toshell) {
+ printf("%c%c", '\\', pchar);
+ }
+ else {
+ printf("%c", pchar);
+ }
+ break;
+ case '\\':
+ case '\'':
+ numbchars += 4;
+ if (toshell) {
+ printf("%c%c%c%c", '\\', '\\', '\\', pchar);
+ }
+ else {
+ printf("%c%c", '\\', pchar);
+ }
+ break;
+ case '^':
+ numbchars += 3;
+ if (toshell) {
+ printf("%c%c%c", '\\', '\\', pchar);
+ }
+ else {
+ printf("%c%c", '\\', pchar);
+ }
+ break;
+ default:
+ st2 = uncontrol(pchar);
+ while ((pchar = *st2++) != 0) {
+ switch (pchar) {
+ case '"':
+ case '!':
+ case '$':
+ case '(':
+ case ')':
+ case ' ':
+ case ';':
+ case '&':
+ case '|':
+ case '>':
+ case '<':
+ case '`':
+ case '#':
+ case '\\':
+ case '\'':
+ if (toshell) {
+ numbchars += 2;
+ printf("%c%c", '\\', pchar);
+ }
+ else {
+ printf("%c", pchar);
+ }
+ break;
+ default:
+ numbchars++;
+ printf("%c", pchar);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ numbchars += 2;
+ if (toshell) {
+ printf("%c'", '\\');
+ }
+ else {
+ printf("'");
+ }
+}
+
+static void
+recurse(strcount, head)
+state *head;
+int strcount;
+{
+ /* if there is a left,
+ * recurse on left,
+ * if there is no down,
+ * print the string to here
+ * else,
+ * add the current match to the string,
+ * recurse.
+ * exit.
+ */
+
+ if (head->next) {
+ recurse(strcount, head->next);
+ }
+ if (head->result != STATE_GOTO) {
+ rptr->match_end = addString(strcount, head->match);
+ rptr->result = astosc[head->result].name;
+ rptr = doRegister(rptr);
+ } else {
+ (void) addString(strcount, head->match);
+ recurse(strcount+1, head->address);
+ strcount--;
+ }
+ return;
+}
+
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ state *head;
+ char *keybdPointer = (char *) 0;
+ char *commandName = argv[0];
+ int picky = 0;
+
+ while ((argc > 1) && (argv[1][0] == '-')) {
+ if (!strcmp(argv[1], "-picky")) {
+ picky++;
+ } else if (!strcmp(argv[1], "-shell")) {
+ toshell++;
+ } else {
+ fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
+ commandName);
+ exit(1);
+ /*NOTREACHED*/
+ }
+ argv++;
+ argc--;
+ }
+ if (argc == 2) {
+ keybdPointer = argv[1];
+ } else if (argc > 2) {
+ fprintf(stderr, "usage: %s [-picky] [-shell] [keyboardname]\n",
+ commandName);
+ exit(1);
+ /*NOTREACHED*/
+ }
+ head = InitControl(keybdPointer, picky, ascii_to_index);
+ if (!head) {
+ return(1);
+ }
+ if (keybdPointer == 0) {
+ keybdPointer = getenv("KEYBD");
+ }
+ if (keybdPointer == 0) {
+ keybdPointer = getenv("TERM");
+ }
+ if (keybdPointer == 0) {
+ keybdPointer = "3a"; /* use 3a as the terminal */
+ }
+ if (toshell) {
+ printf("set noglob;\nsetenv MAP3270 ");
+ }
+ printf("%s{", keybdPointer);
+ numbchars = 2 + strlen(keybdPointer);
+ /* now, run through the table registering entries */
+ rptr = regstates + 2;
+ recurse(0, head);
+ /* now print them out */
+ for (rptr = regstates[0].forward; rptr->result != 0;
+ rptr = rptr->forward) {
+ printString(rptr->match_end, rptr->match_start, rptr->result);
+ }
+ if (toshell) {
+ printf("%c;};\nunset noglob;\n", '\\');
+ }
+ else {
+ printf(";}\n");
+ }
+ return(0);
+}
diff --git a/comms/tn3270/files/ascii/state.h b/comms/tn3270/files/ascii/state.h
new file mode 100644
index 00000000000..f241b3413cd
--- /dev/null
+++ b/comms/tn3270/files/ascii/state.h
@@ -0,0 +1,56 @@
+/* $NetBSD: state.h,v 1.1.1.1 2010/01/17 01:33:19 dholland Exp $ */
+/* From NetBSD: state.h,v 1.6 2003/08/07 11:16:28 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)state.h 4.2 (Berkeley) 4/26/91
+ */
+
+#define INCLUDED_STATE
+
+/* this defines the state structure used by the key mapping routines */
+
+
+#define STATE_NULL -1 /* Falls off edge */
+#define STATE_GOTO -2 /* GOTO internal state */
+
+#define state struct State
+struct State {
+ int match; /* character to match */
+ int result; /* 3270 control code */
+ state *next; /* next entry in this same state */
+ state *address; /* if goto, where is next state */
+};
+
+/* termin.c */
+void init_keyboard(void);
+void InitMapping(void);
+void TransInput(int, int);
+int TerminalIn(void);
+int DataFromTerminal(char *, int);
diff --git a/comms/tn3270/files/ascii/termin.c b/comms/tn3270/files/ascii/termin.c
new file mode 100644
index 00000000000..7f34501f80e
--- /dev/null
+++ b/comms/tn3270/files/ascii/termin.c
@@ -0,0 +1,299 @@
+/* $NetBSD: termin.c,v 1.1.1.1 2010/01/17 01:33:19 dholland Exp $ */
+/* From NetBSD: termin.c,v 1.8 2003/08/07 11:16:28 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)termin.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: termin.c,v 1.1.1.1 2010/01/17 01:33:19 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/* this takes characters from the keyboard, and produces 3270 keystroke
+ codes
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "../general/general.h"
+#include "../ctlr/function.h"
+#include "../ctlr/declare.h"
+#include "../sys_curses/telextrn.h"
+
+#include "../api/astosc.h"
+#include "state.h"
+#include "externs.h"
+#include "map3270.h"
+
+#include "../general/globals.h"
+
+extern cc_t escape; /* Escape to command mode */
+
+#define IsControl(c) (!isprint((unsigned char)c) || (isspace((unsigned char)c) && ((c) != ' ')))
+
+#define NextState(x) (x->next)
+
+/* XXX temporary - hard code in the state table */
+
+#define MATCH_ANY 0xff /* actually, match any character */
+
+
+static unsigned char
+ ourBuffer[100], /* where we store stuff */
+ *ourPHead = ourBuffer, /* first character in buffer */
+ *ourPTail = ourBuffer, /* where next character goes */
+ *TransPointer = 0; /* For transparent mode data */
+
+static int InControl;
+static int WaitingForSynch;
+
+static struct astosc
+ *spacePTR = 0; /* Space is hard to enter */
+
+static state
+ *headOfControl = 0; /* where we enter code state table */
+
+#define FullChar ((ourPTail+5) >= ourBuffer+sizeof ourBuffer)
+#define EmptyChar (ourPTail == ourPHead)
+
+
+static void AddChar(int);
+static void FlushChar(void);
+
+
+/*
+ * init_keyboard()
+ *
+ * Initialize the keyboard variables.
+ */
+
+void
+init_keyboard()
+{
+ ourPHead = ourPTail = ourBuffer;
+ InControl = 0;
+ WaitingForSynch = 0;
+}
+
+
+/*
+ * Initialize the keyboard mapping file.
+ */
+
+void
+InitMapping()
+{
+ struct astosc *ptr;
+
+ if (!headOfControl) {
+ /* need to initialize */
+ headOfControl = InitControl((char *)0, 0, ascii_to_index);
+ if (!headOfControl) { /* should not occur */
+ quit(0, NULL);
+ }
+ for (ptr = &astosc[0]; ptr <= &astosc[highestof(astosc)]; ptr++) {
+ if (ptr->function == FCN_SPACE) {
+ spacePTR = ptr;
+ }
+ }
+ }
+}
+
+
+/* AddChar - put a function index in our buffer */
+
+static void
+AddChar(c)
+int c;
+{
+ if (!FullChar) {
+ *ourPTail++ = c;
+ } else {
+ RingBell("Typeahead buffer full");
+ }
+}
+
+/* FlushChar - put everything where it belongs */
+
+static void
+FlushChar()
+{
+ ourPTail = ourBuffer;
+ ourPHead = ourBuffer;
+}
+
+/*ARGSUSED*/
+void
+TransInput(onoff, mode)
+int mode; /* Which KIND of transparent input */
+int onoff; /* Going in, or coming out */
+{
+ if (onoff) {
+ /* Flush pending input */
+ FlushChar();
+ TransPointer = ourBuffer;
+ } else {
+ }
+}
+
+int
+TerminalIn()
+{
+ /* send data from us to next link in stream */
+ int work = 0;
+ struct astosc *ptr;
+
+ while (!EmptyChar) { /* send up the link */
+ if (*ourPHead == ' ') {
+ ptr = spacePTR;
+ } else {
+ ptr = &astosc[*ourPHead];
+ }
+ if (AcceptKeystroke(ptr->scancode, ptr->shiftstate) == 1) {
+ ourPHead++;
+ work = 1;
+ } else {
+ break;
+ }
+ }
+
+ if (EmptyChar) {
+ FlushChar();
+ }
+ /* return value answers question: "did we do anything useful?" */
+ return work;
+}
+
+int
+DataFromTerminal(buffer, count)
+char *buffer; /* the data read in */
+int count; /* how many bytes in this buffer */
+{
+ state *regControlPointer;
+ int c;
+ int result;
+ int origCount;
+ extern int bellwinup;
+ static state *controlPointer;
+
+ if (TransPointer) {
+ int i;
+
+ if ((count+TransPointer) >= (ourBuffer+sizeof ourBuffer)) {
+ i = ourBuffer+sizeof ourBuffer-TransPointer;
+ } else {
+ i = count;
+ }
+ while (i--) {
+ c = (*buffer++)&0x7f;
+ *TransPointer++ = c|0x80;
+ if (c == '\r') {
+ SendTransparent((char *)ourBuffer, TransPointer-ourBuffer);
+ TransPointer = 0; /* Done */
+ break;
+ }
+ }
+ return count;
+ }
+
+ if (bellwinup) {
+ BellOff();
+ }
+
+ origCount = count;
+
+ while (count) {
+ c = *buffer++&0x7f;
+ count--;
+
+ if (c == escape) {
+ if (count && (*buffer&0x7f) == escape) {
+ buffer++;
+ count--;
+ } else {
+ command(0, (char *)0, 0);
+ RefreshScreen();
+ continue;
+ }
+ }
+
+ if (!InControl && !IsControl(c)) {
+ AddChar(c); /* add ascii character */
+ } else {
+ if (!InControl) { /* first character of sequence */
+ InControl = 1;
+ controlPointer = headOfControl;
+ }
+ /* control pointer points to current position in state table */
+ for (regControlPointer = controlPointer; ;
+ regControlPointer = NextState(regControlPointer)) {
+ if (!regControlPointer) { /* ran off end */
+ RingBell("Invalid control sequence");
+ regControlPointer = headOfControl;
+ InControl = 0;
+ count = 0; /* Flush current input */
+ break;
+ }
+ if ((regControlPointer->match == c) /* hit this character */
+ || (regControlPointer->match == MATCH_ANY)) {
+ result = regControlPointer->result;
+ if (result == STATE_GOTO) {
+ regControlPointer = regControlPointer->address;
+ break; /* go to next character */
+ }
+ if (WaitingForSynch) {
+ if (astosc[result].function == FCN_SYNCH) {
+ WaitingForSynch = 0;
+ } else {
+ RingBell("Need to type synch character");
+ }
+ }
+ else if (astosc[result].function == FCN_FLINP) {
+ FlushChar(); /* Don't add FLINP */
+ } else {
+ if (astosc[result].function == FCN_MASTER_RESET) {
+ FlushChar();
+ }
+ AddChar(result); /* add this code */
+ }
+ InControl = 0; /* out of control now */
+ break;
+ }
+ }
+ controlPointer = regControlPointer; /* save state */
+ }
+ }
+ (void) TerminalIn(); /* try to send data */
+ return(origCount-count);
+}
diff --git a/comms/tn3270/files/ctlr/3180.kbd b/comms/tn3270/files/ctlr/3180.kbd
new file mode 100644
index 00000000000..635fb9ac0f5
--- /dev/null
+++ b/comms/tn3270/files/ctlr/3180.kbd
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)3180.kbd 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * keynumber [ scancode [ unshifted [ shifted [ alted [ shiftalted ] ] ] ] ]
+ *
+ * keynumber is in decimal, and starts in column 1.
+ * scancode is hexadecimal.
+ * unshifted, etc. - these are either a single ascii character,
+ * or the name of a function or an AID-generating key.
+ *
+ * all fields are separated by a single space.
+ */
+1 0e ` ~
+2 16 1 VERTICAL_BAR
+3 1e 2 @
+4 26 3 #
+5 25 4 $
+6 2e 5 %
+7 36 6 ^
+8 3d 7 &
+9 3e 8 *
+10 46 9 (
+11 45 0 )
+12 4e - _
+13 55 = +
+14 5d
+15 66 LEFT
+16 0d TAB
+17 15 q Q
+18 1d w W
+19 24 e E
+20 2d r R
+21 2c t T
+22 35 y Y
+23 3c u U
+24 43 i I
+25 44 o O
+26 4d p P
+27 54 CENTSIGN !
+28 5b \ |
+29 5c
+30 14 CAPS_LOCK
+31 1c a A
+32 1b s S
+33 23 d D
+34 2b f F
+35 34 g G
+36 33 h H
+37 3b j J
+38 42 k K
+39 4b l L
+40 4c ; :
+41 52 ' "
+42 53 { }
+43 5a NL
+44 12 MAKE_SHIFT MAKE_SHIFT MAKE_SHIFT
+45 13 < >
+46 1a z Z
+47 22 x X
+48 21 c C
+49 2a v V
+50 32 b B
+51 31 n N
+52 3a m M
+53 41 , ,
+54 49 . .
+55 4a / ?
+56 51
+57 59 MAKE_SHIFT MAKE_SHIFT MAKE_SHIFT
+58 11 RESET NULL DVCNL
+59
+60 19 MAKE_ALT MAKE_ALT MAKE_ALT
+61 29 SPACE SPACE
+62 39 MAKE_ALT MAKE_ALT MAKE_ALT
+63
+64 58 ENTER
+65 06 CLEAR
+66 0c NULL NULL EINP
+67 0b EEOF
+68 0a
+69 09
+70 05 ATTN NULL TREQ
+71 04
+72 03
+73 83
+74 01
+75 67 PA1 DP
+76 64 BTAB
+77
+78 61 LEFT NULL LEFT2
+79
+80 6e PA2 FM
+81 65 INSRT
+82 63 UP
+83 62 NULL NULL HOME
+84 60 DOWN
+85 6f
+86 6d DELETE
+87
+88 6a RIGHT NULL RIGHT2
+89
+90 76
+91 6c 7
+92 6b 4
+93 69 1
+94 68
+95 77
+96 75 8
+97 73 5
+98 72 2
+99 70 0
+100 7e ,
+101 7d 9
+102 74 6
+103 7a 3
+104 71 .
+105 84 SPACE
+106 7c TAB
+107 7b -
+108 79 ENTER
+109 78
+110 07 PF1
+111 0f PF2
+112 17 PF3
+113 1f PF4
+114 27 PF5
+115 2f PF6
+116 37 PF7
+117 3f PF8 NULL MONOCASE
+118 47 PF9
+119 4f PF10
+120 56 PF11
+121 5e PF12
+122 08 PF13
+123 10 PF14
+124 18 PF15
+125 20 PF16
+126 28 PF17
+127 30 PF18
+128 38 PF19
+129 40 PF20
+130 48 PF21
+131 50 PF22
+132 57 PF23
+133 5f PF24
+134 92 BREAK_SHIFT BREAK_SHIFT BREAK_SHIFT
+135 D9 BREAK_SHIFT BREAK_SHIFT BREAK_SHIFT
+136 99 BREAK_ALT BREAK_ALT BREAK_ALT
+137 B9 BREAK_ALT BREAK_ALT BREAK_ALT
diff --git a/comms/tn3270/files/ctlr/3270pc.kbd b/comms/tn3270/files/ctlr/3270pc.kbd
new file mode 100644
index 00000000000..d84fa3597ad
--- /dev/null
+++ b/comms/tn3270/files/ctlr/3270pc.kbd
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)3270pc.kbd 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * keynumber [ scancode [ unshifted [ shifted [ alted [ shiftalted ] ] ] ] ]
+ *
+ * keynumber is in decimal, and starts in column 1.
+ * scancode is hexadecimal.
+ * unshifted, etc. - these are either a single ascii character,
+ * or the name of a function or an AID-generating key.
+ *
+ * all fields are separated by a single space.
+ */
+1 0e ` ~
+2 16 1 !
+3 1e 2 @
+4 26 3 #
+5 25 4 $
+6 2e 5 %
+7 36 6 ^
+8 3d 7 &
+9 3e 8 *
+10 46 9 (
+11 45 0 )
+12 4e - _
+13 55 = +
+14 5d
+15 66 LEFT
+16 0d TAB BTAB
+17 15 q Q
+18 1d w W
+19 24 e E
+20 2d r R
+21 2c t T
+22 35 y Y
+23 3c u U
+24 43 i I
+25 44 o O
+26 4d p P
+27 54 [ {
+28 5b \ |
+29 5c
+30 14 CAPS_LOCK
+31 1c a A
+32 1b s S
+33 23 d D
+34 2b f F
+35 34 g G
+36 33 h H
+37 3b j J
+38 42 k K
+39 4b l L
+40 4c ; :
+41 52 ' "
+42 53 ] }
+43 5a NL
+44 12 MAKE_SHIFT MAKE_SHIFT MAKE_SHIFT
+45 13 < >
+46 1a z Z
+47 22 x X
+48 21 c C
+49 2a v V
+50 32 b B
+51 31 n N
+52 3a m M
+53 41 , <
+54 49 . >
+55 4a / ?
+56 51
+57 59 MAKE_SHIFT MAKE_SHIFT MAKE_SHIFT
+58 11 RESET NULL DVCNL
+59
+60 19 MAKE_ALT MAKE_ALT MAKE_ALT
+61 29 SPACE SPACE
+62 39 MAKE_ALT MAKE_ALT MAKE_ALT
+63
+64 58 ENTER
+65 06 CLEAR NULL TEST
+66 0c NULL NULL ATTN
+67 0b EEOF NULL EINP
+68 0a
+69 09 MAKE_CTRL
+70 05 ATTN NULL TREQ
+71 04
+72 03
+73 83
+74 01
+75 67 PA1 DP
+76 64 BTAB
+77
+78 61 LEFT NULL LEFT2
+79
+80 6e PA2 FM
+81 65 INSRT
+82 63 UP
+83 62 NULL NULL HOME
+84 60 DOWN
+85 6f PA3
+86 6d DELETE
+87
+88 6a RIGHT NULL RIGHT2
+89
+90 76
+91 6c 7
+92 6b 4
+93 69 1
+94 68
+95 77
+96 75 8
+97 73 5
+98 72 2
+99 70 0
+100 7e ,
+101 7d 9
+102 74 6
+103 7a 3
+104 71 .
+105 84 SPACE
+106 7c TAB
+107 7b -
+108 79 ENTER
+109 78
+110 07 PF1
+111 0f PF2
+112 17 PF3
+113 1f PF4
+114 27 PF5
+115 2f PF6
+116 37 PF7
+117 3f PF8 NULL MONOCASE
+118 47 PF9
+119 4f PF10
+120 56 PF11
+121 5e PF12
+122 08 PF13
+123 10 PF14
+124 18 PF15
+125 20 PF16
+126 28 PF17
+127 30 PF18
+128 38 PF19
+129 40 PF20
+130 48 PF21
+131 50 PF22
+132 57 PF23
+133 5f PF24
+134 92 BREAK_SHIFT BREAK_SHIFT BREAK_SHIFT
+135 D9 BREAK_SHIFT BREAK_SHIFT BREAK_SHIFT
+136 99 BREAK_ALT BREAK_ALT BREAK_ALT
+137 B9 BREAK_ALT BREAK_ALT BREAK_ALT
diff --git a/comms/tn3270/files/ctlr/api.c b/comms/tn3270/files/ctlr/api.c
new file mode 100644
index 00000000000..cecdef4b102
--- /dev/null
+++ b/comms/tn3270/files/ctlr/api.c
@@ -0,0 +1,778 @@
+/* $NetBSD: api.c,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $ */
+/* From NetBSD: api.c,v 1.7 2003/08/07 11:16:29 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)api.c 4.5 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: api.c,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * This file implements the API used in the PC version.
+ */
+
+#include <stdio.h>
+
+#include "api.h"
+#include "../general/general.h"
+
+#include "../api/disp_asc.h"
+
+#include "screen.h"
+#include "hostctlr.h"
+#include "oia.h"
+#include "declare.h"
+
+#include "externs.h"
+
+#include "../general/globals.h"
+
+int apitrace = 0;
+
+/*
+ * Some defines for things we use internally.
+ */
+
+#define PS_SESSION_ID 23
+#define BUF_SESSION_ID 0
+
+
+/* api.c */
+#if defined(MSDOS)
+static void movetous(char *, int, int , int);
+static void movetothem(int, int , char *, int);
+#else
+#include "../sys_curses/telextrn.h"
+#endif
+static void name_resolution(union REGS *, struct SREGS *);
+static void query_session_id(union REGS *, struct SREGS *);
+static void query_session_parameters(union REGS *, struct SREGS *);
+static void query_session_cursor(union REGS *, struct SREGS *);
+static void connect_to_keyboard(union REGS *, struct SREGS *);
+static void disconnect_from_keyboard(union REGS *, struct SREGS *);
+static void write_keystroke(union REGS *, struct SREGS *);
+static void disable_input(union REGS *, struct SREGS *);
+static void enable_input(union REGS *, struct SREGS *);
+static void copy_subroutine(BufferDescriptor *, BufferDescriptor *,
+ CopyStringParms *, int, int);
+static void copy_string(union REGS *, struct SREGS *);
+static void read_oia_group(union REGS *, struct SREGS *);
+static void unknown_op(union REGS *, struct SREGS *);
+
+/*
+ * General utility routines.
+ */
+
+#if defined(MSDOS)
+
+#define access_api(foo,length,copyin) (foo)
+#define unaccess_api(foo,goo,length,copyout)
+
+static void
+movetous(parms, es, di, length)
+char *parms;
+int es, di;
+int length;
+{
+ char far *farparms = parms;
+
+ movedata(es, di, FP_SEG(farparms), FP_OFF(farparms), length);
+ if (apitrace) {
+ Dump('(', parms, length);
+ }
+}
+
+static void
+movetothem(es, di, parms, length)
+int es, di;
+char *parms;
+int length;
+{
+ char far *farparms = parms;
+
+ movedata(FP_SEG(farparms), FP_OFF(farparms), es, di, length);
+ if (apitrace) {
+ Dump(')', parms, length);
+ }
+}
+#endif /* defined(MSDOS) */
+
+/*
+ * Supervisor Services.
+ */
+
+static void
+name_resolution(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ NameResolveParms parms;
+
+ movetous((char *) &parms, sregs->es, regs->x.di, sizeof parms);
+
+ regs->h.cl = 0;
+ if (memcmp((char *)&parms, NAME_SESSMGR, sizeof parms.gate_name) == 0) {
+ regs->x.dx = GATE_SESSMGR;
+ } else if (memcmp((char *)&parms, NAME_KEYBOARD,
+ sizeof parms.gate_name) == 0) {
+ regs->x.dx = GATE_KEYBOARD;
+ } else if (memcmp((char *)&parms, NAME_COPY, sizeof parms.gate_name) == 0) {
+ regs->x.dx = GATE_COPY;
+ } else if (memcmp((char *)&parms, NAME_OIAM, sizeof parms.gate_name) == 0) {
+ regs->x.dx = GATE_OIAM;
+ } else {
+ regs->h.cl = 0x2e; /* Name not found */
+ }
+ regs->h.ch = 0x12;
+ regs->h.bh = 7;
+}
+
+/*
+ * Session Information Services.
+ */
+
+static void
+query_session_id(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ QuerySessionIdParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.option_code != 0x01) {
+ parms.rc = 0x0d; /* Invalid option code */
+#ifdef NOTOBS
+ } else if ((parms.data_code != 0x45) && (parms.data_code != 0x00/*OBS*/)) {
+ parms.rc = 0x0b;
+#endif /* NOTOBS */
+ } else {
+ NameArray list;
+
+ movetous((char *)&list, FP_SEG(parms.name_array),
+ FP_OFF(parms.name_array), sizeof list);
+ if ((list.length < 14) || (list.length > 170)) {
+ parms.rc = 0x12;
+ } else {
+ list.number_matching_session = 1;
+ list.name_array_element.short_name = parms.data_code;
+ list.name_array_element.type = TYPE_DFT;
+ list.name_array_element.session_id = PS_SESSION_ID;
+ memcpy(list.name_array_element.long_name, "ONLYSESS",
+ sizeof list.name_array_element.long_name);
+ movetothem(FP_SEG(parms.name_array),
+ FP_OFF(parms.name_array), (char *)&list, sizeof list);
+ parms.rc = 0;
+ }
+ }
+ parms.function_id = 0x6b;
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+static void
+query_session_parameters(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ QuerySessionParametersParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc !=0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else {
+ parms.rc = 0;
+ parms.session_type = TYPE_DFT;
+ parms.session_characteristics = 0; /* Neither EAB nor PSS */
+ parms.rows = MaxNumberLines;
+ parms.columns = MaxNumberColumns;
+ parms.presentation_space = 0;
+ }
+ parms.function_id = 0x6b;
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+static void
+query_session_cursor(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ QuerySessionCursorParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else {
+ parms.rc = 0;
+ parms.cursor_type = CURSOR_BLINKING; /* XXX what is inhibited? */
+ parms.row_address = ScreenLine(CursorAddress);
+ parms.column_address = ScreenLineOffset(CursorAddress);
+ }
+
+ parms.function_id = 0x6b;
+ movetothem(sregs->es, regs->x.di, (char *) &parms, sizeof parms);
+}
+
+/*
+ * Keyboard Services.
+ */
+
+
+static void
+connect_to_keyboard(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ ConnectToKeyboardParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else if (parms.intercept_options != 0) {
+ parms.rc = 0x01;
+ } else {
+ parms.rc = 0;
+ parms.first_connection_identifier = 0;
+ }
+ parms.function_id = 0x62;
+
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+static void
+disconnect_from_keyboard(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ DisconnectFromKeyboardParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else if (parms.connectors_task_id != 0) {
+ parms.rc = 04; /* XXX */
+ } else {
+ parms.rc = 0;
+ }
+ parms.function_id = 0x62;
+
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+static void
+write_keystroke(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ WriteKeystrokeParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else if (parms.connectors_task_id != 0) {
+ parms.rc = 0x04;
+ } else {
+ parms.number_of_keys_sent = 0;
+ parms.rc = 0;
+ if (parms.options == OPTION_SINGLE_KEYSTROKE) {
+ KeystrokeEntry *entry = &parms.keystroke_specifier.keystroke_entry;
+
+ if (AcceptKeystroke(entry->scancode, entry->shift_state) == 0) {
+ parms.rc = 0x10; /* XXX needs 0x12 too! */
+ }
+ parms.number_of_keys_sent++;
+ } else if (parms.options == OPTION_MULTIPLE_KEYSTROKES) {
+ KeystrokeList
+ list,
+ far *atlist = parms.keystroke_specifier.keystroke_list;
+ KeystrokeEntry
+ entry[10], /* 10 at a time */
+ *ourentry,
+ far *theirentry;
+ int
+ todo;
+
+ movetous((char *)&list, FP_SEG(atlist),
+ FP_OFF(atlist), sizeof *atlist);
+ todo = list.length/2;
+ ourentry = entry+(highestof(entry)+1);
+ theirentry = &atlist->keystrokes;
+
+ while (todo) {
+ if (ourentry > &entry[highestof(entry)]) {
+ int thistime;
+
+ thistime = todo;
+ if (thistime > numberof(entry)) {
+ thistime = numberof(entry);
+ }
+ movetous((char *)entry, FP_SEG(theirentry),
+ FP_OFF(theirentry), thistime*sizeof *theirentry);
+ theirentry += thistime;
+ ourentry = entry;
+ }
+ if (AcceptKeystroke(ourentry->scancode,
+ ourentry->shift_state) == 0) {
+ parms.rc = 0x10; /* XXX needs 0x12 too! */
+ break;
+ }
+ parms.number_of_keys_sent++;
+ ourentry++;
+ todo--;
+ }
+ } else {
+ parms.rc = 0x01;
+ }
+ }
+ parms.function_id = 0x62;
+
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+/* XXX */
+}
+
+
+static void
+disable_input(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ DisableInputParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else if (parms.connectors_task_id != 0) {
+ parms.rc = 0x04;
+ } else {
+ SetOiaApiInhibit(&OperatorInformationArea);
+ parms.rc = 0;
+ }
+ parms.function_id = 0x62;
+
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+static void
+enable_input(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ EnableInputParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else if (parms.connectors_task_id != 0) {
+ parms.rc = 0x04;
+ } else {
+ ResetOiaApiInhibit(&OperatorInformationArea);
+ parms.rc = 0;
+ }
+ parms.function_id = 0x62;
+
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+/*
+ * Copy Services.
+ */
+
+static void
+copy_subroutine(target, source, parms, what_is_user, length)
+BufferDescriptor *target, *source;
+CopyStringParms *parms;
+int what_is_user;
+int length;
+#define USER_IS_TARGET 0
+#define USER_IS_SOURCE 1
+{
+#define TARGET_NO_EAB 1
+#define SOURCE_NO_EAB 2
+#define TARGET_PC 4
+#define SOURCE_PC 8
+#define NO_FIELD_ATTRIBUTES 16
+ int needtodo = 0;
+ int access_length;
+ unsigned char far *input;
+ char far *output;
+ char far *access_pointer;
+
+ if ((target->characteristics^source->characteristics)
+ &CHARACTERISTIC_EAB) {
+ if (target->characteristics&CHARACTERISTIC_EAB) {
+ needtodo |= TARGET_NO_EAB; /* Need to bump for EAB in target */
+ } else {
+ needtodo |= SOURCE_NO_EAB; /* Need to bump for EAB in source */
+ }
+ }
+ if (target->session_type != source->session_type) {
+ if (target->session_type == TYPE_PC) {
+ needtodo |= TARGET_PC; /* scan codes to PC */
+ } else {
+ needtodo |= SOURCE_PC; /* PC to scan codes */
+ }
+ }
+ if ((parms->copy_mode&COPY_MODE_FIELD_ATTRIBUTES) == 0) {
+ needtodo |= NO_FIELD_ATTRIBUTES;
+ }
+ access_length = length;
+ if (what_is_user == USER_IS_TARGET) {
+ if (target->characteristics&CHARACTERISTIC_EAB) {
+ access_length *= 2;
+ }
+ input = (unsigned char far *) &Host[source->begin];
+ access_pointer = target->buffer;
+ output = access_api(target->buffer, access_length, 0);
+ } else {
+ if (source->characteristics&CHARACTERISTIC_EAB) {
+ access_length *= 2;
+ }
+ access_pointer = source->buffer;
+ input = (unsigned char far *)
+ access_api(source->buffer, access_length, 1);
+ output = (char far *) &Host[target->begin];
+ }
+ while (length--) {
+ if (needtodo&TARGET_PC) {
+ *output++ = disp_asc[*input++];
+ } else if (needtodo&SOURCE_PC) {
+ *output++ = asc_disp[*input++];
+ } else {
+ *output++ = *input++;
+ }
+ if (needtodo&TARGET_NO_EAB) {
+ /* XXX: So why are we doing this? (bug) */
+ input++;
+ } else if (needtodo&SOURCE_NO_EAB) {
+ *output++ = 0; /* Should figure out good EAB? */
+ }
+ }
+ if (what_is_user == USER_IS_TARGET) {
+ unaccess_api(target->buffer, access_pointer, access_length, 1);
+ } else {
+ unaccess_api(source->buffer, access_pointer, access_length, 0);
+ }
+}
+
+
+static void
+copy_string(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ CopyStringParms parms;
+ BufferDescriptor *target = &parms.target, *source = &parms.source;
+ int length;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ length = 1+parms.source_end-source->begin;
+ if ((parms.rc != 0) || (parms.function_id !=0)) {
+ parms.rc = 0x0c;
+ } else if (target->session_id == BUF_SESSION_ID) { /* Target is buffer */
+ if (source->session_id != PS_SESSION_ID) { /* A no-no */
+ parms.rc = 0x2;
+ } else {
+ if ((source->begin < 0) || (source->begin > highestof(Host))) {
+ parms.rc = 0x06; /* invalid source definition */
+ } else {
+ if ((source->begin+length) > highestof(Host)) {
+ length = highestof(Host)-source->begin;
+ parms.rc = 0x0f; /* Truncate */
+ }
+ if ((source->characteristics == target->characteristics) &&
+ (source->session_type == target->session_type)) {
+ if (source->characteristics&CHARACTERISTIC_EAB) {
+ length *= 2;
+ }
+ movetothem(FP_SEG(target->buffer),
+ FP_OFF(target->buffer),
+ (char *)&Host[source->begin], length);
+ } else {
+ copy_subroutine(target, source, &parms,
+ USER_IS_TARGET, length);
+ }
+ }
+ }
+ } else if (source->session_id != BUF_SESSION_ID) {
+ parms.rc = 0xd;
+ } else {
+ /* Send to presentation space (3270 buffer) */
+ if ((target->begin < 0) || (target->begin > highestof(Host))) {
+ parms.rc = 0x07; /* invalid target definition */
+ } if (!UnLocked) {
+ parms.rc = 0x03; /* Keyboard locked */
+ } else if (parms.copy_mode != 0) {
+ parms.rc = 0x0f; /* Copy of field attr's not allowed */
+ } else if (IsProtected(target->begin) || /* Make sure no protected */
+ (WhereAttrByte(target->begin) != /* in range */
+ WhereAttrByte(target->begin+length-1))) {
+ parms.rc = 0x0e; /* Attempt to write in protected */
+ } else {
+ if ((target->begin+length) > highestof(Host)) {
+ length = highestof(Host)-target->begin;
+ parms.rc = 0x0f; /* Truncate */
+ }
+ TurnOnMdt(target->begin); /* Things have changed */
+ if ((source->characteristics == target->characteristics) &&
+ (source->session_type == target->session_type)) {
+ if (source->characteristics&CHARACTERISTIC_EAB) {
+ length *= 2;
+ }
+ movetous((char *)&Host[target->begin],
+ FP_SEG(source->buffer),
+ FP_OFF(source->buffer), length);
+ } else {
+ copy_subroutine(target, source, &parms, USER_IS_SOURCE, length);
+ }
+ }
+ }
+ parms.function_id = 0x64;
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+
+/*
+ * Operator Information Area Services.
+ */
+
+static void
+read_oia_group(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ ReadOiaGroupParms parms;
+
+ movetous((char *)&parms, sregs->es, regs->x.di, sizeof parms);
+
+ if ((parms.rc != 0) || (parms.function_id != 0)) {
+ parms.rc = 0x0c;
+ } else if (parms.session_id != PS_SESSION_ID) {
+ parms.rc = 0x02;
+ } else {
+ int group = parms.oia_group_number;
+ char *from;
+ int size;
+
+ if ((group != API_OIA_ALL_GROUPS) &&
+ ((group > API_OIA_LAST_LEGAL_GROUP) || (group < 0))) {
+ } else {
+ if (group == API_OIA_ALL_GROUPS) {
+ size = API_OIA_BYTES_ALL_GROUPS;
+ from = (char *)&OperatorInformationArea;
+ } else if (group == API_OIA_INPUT_INHIBITED) {
+ size = sizeof OperatorInformationArea.input_inhibited;
+ from = (char *)&OperatorInformationArea.input_inhibited[0];
+ } else {
+ size = 1;
+ from = ((char *)&OperatorInformationArea)+group;
+ }
+ movetothem(FP_SEG(parms.oia_buffer), FP_OFF(parms.oia_buffer),
+ from, size);
+ }
+ }
+ parms.function_id = 0x6d;
+ movetothem(sregs->es, regs->x.di, (char *)&parms, sizeof parms);
+}
+
+/*ARGSUSED*/
+static void
+unknown_op(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+ regs->h.ch = 0x12;
+ regs->h.cl = 0x05;
+}
+
+
+void
+handle_api(regs, sregs)
+union REGS *regs;
+struct SREGS *sregs;
+{
+/*
+ * Do we need to log this transaction?
+ */
+ if (apitrace) {
+ Dump('<', (char *)regs, sizeof *regs);
+ Dump('<', (char *)sregs, sizeof *sregs);
+ }
+ if (regs->h.ah == NAME_RESOLUTION) {
+ name_resolution(regs, sregs);
+#if defined(unix)
+ } else if (regs->h.ah == PS_OR_OIA_MODIFIED) {
+ while ((oia_modified == 0) && (ps_modified == 0)) {
+ (void) Scheduler(1);
+ }
+ oia_modified = ps_modified = 0;
+#endif /* defined(unix) */
+ } else if (regs->h.ah != 0x09) {
+ regs->h.ch = 0x12;
+ regs->h.cl = 0x0f; /* XXX Invalid environmental access */
+ } else if (regs->x.bx != 0x8020) {
+ regs->h.ch = 0x12;
+ regs->h.cl = 0x08; /* XXX Invalid wait specified */
+ } else if (regs->h.ch != 0) {
+ regs->x.cx = 0x1206; /* XXX Invalid priority */
+ } else {
+ switch (regs->x.dx) {
+ case GATE_SESSMGR:
+ switch (regs->h.al) {
+ case QUERY_SESSION_ID:
+ if (regs->h.cl != 0) {
+ regs->x.cx = 0x1206;
+ } else {
+ regs->x.cx = 0x1200;
+ query_session_id(regs, sregs);
+ }
+ break;
+ case QUERY_SESSION_PARAMETERS:
+ if (regs->h.cl != 0) {
+ regs->x.cx = 0x1206;
+ } else {
+ regs->x.cx = 0x1200;
+ query_session_parameters(regs, sregs);
+ }
+ break;
+ case QUERY_SESSION_CURSOR:
+ if ((regs->h.cl != 0xff) && (regs->h.cl != 0x00/*OBS*/)) {
+ regs->x.cx = 0x1206;
+ } else {
+ regs->x.cx = 0x1200;
+ query_session_cursor(regs, sregs);
+ }
+ break;
+ default:
+ unknown_op(regs, sregs);
+ break;
+ }
+ break;
+ case GATE_KEYBOARD:
+ if (regs->h.cl != 00) {
+ regs->x.cx = 0x1206;
+ } else {
+ regs->x.cx = 0x1200;
+ switch (regs->h.al) {
+ case CONNECT_TO_KEYBOARD:
+ connect_to_keyboard(regs, sregs);
+ break;
+ case DISABLE_INPUT:
+ disable_input(regs, sregs);
+ break;
+ case WRITE_KEYSTROKE:
+ write_keystroke(regs, sregs);
+ break;
+ case ENABLE_INPUT:
+ enable_input(regs, sregs);
+ break;
+ case DISCONNECT_FROM_KEYBOARD:
+ disconnect_from_keyboard(regs, sregs);
+ break;
+ default:
+ unknown_op(regs, sregs);
+ break;
+ }
+ }
+ break;
+ case GATE_COPY:
+ if (regs->h.cl != 0xff) {
+ regs->x.cx = 0x1206;
+ } else {
+ regs->x.cx = 0x1200;
+ switch (regs->h.al) {
+ case COPY_STRING:
+ copy_string(regs, sregs);
+ break;
+ default:
+ unknown_op(regs, sregs);
+ break;
+ }
+ }
+ break;
+ case GATE_OIAM:
+ if (regs->h.cl != 0xff) {
+ regs->x.cx = 0x1206;
+ } else {
+ regs->x.cx = 0x1200;
+ switch (regs->h.al) {
+ case READ_OIA_GROUP:
+ read_oia_group(regs, sregs);
+ break;
+ default:
+ unknown_op(regs, sregs);
+ break;
+ }
+ }
+ break;
+ default:
+ regs->h.ch = 0x12;
+ regs->h.cl = 0x34; /* Invalid GATE entry */
+ break;
+ }
+ }
+/*
+ * Do we need to log this transaction?
+ */
+ if (apitrace) {
+ Dump('>', (char *)regs, sizeof *regs);
+ Dump('>', (char *)sregs, sizeof *sregs);
+#ifdef MSDOS
+ { char buf[10]; gets(buf); }
+#endif /* MSDOS */
+ }
+}
diff --git a/comms/tn3270/files/ctlr/api.h b/comms/tn3270/files/ctlr/api.h
new file mode 100644
index 00000000000..37401440160
--- /dev/null
+++ b/comms/tn3270/files/ctlr/api.h
@@ -0,0 +1,410 @@
+/* $NetBSD: api.h,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $ */
+/* From NetBSD: api.h,v 1.7 2003/08/07 11:16:30 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)api.h 4.4 (Berkeley) 4/26/91
+ */
+
+/*
+ * This file contains header information used by the PC API routines.
+ */
+
+#if !defined(MSDOS)
+#define far /* For 'far *' checks */
+#endif /* !defined(MSDOS) */
+
+#define API_INTERRUPT_NUMBER 0x7A /* API Interrupt Number */
+
+/*
+ * Define the gate numbers. These are returned via the Name Resolution
+ * service.
+ */
+
+#define GATE_SESSMGR 1234
+#define GATE_KEYBOARD 5678
+#define GATE_COPY 9101
+#define GATE_OIAM 1121
+
+/*
+ * The names which correspond to the above gate numbers.
+ */
+
+#define NAME_SESSMGR "SESSMGR "
+#define NAME_KEYBOARD "KEYBOARD"
+#define NAME_COPY "COPY "
+#define NAME_OIAM "OIAM "
+
+
+/*
+ * Name Resolution is specified in AH.
+ */
+
+#define NAME_RESOLUTION 0x81
+
+#if defined(unix)
+/*
+ * In unix, we offer a service to allow the application to keep from
+ * having to poll us constantly.
+ */
+#define PS_OR_OIA_MODIFIED 0x99
+
+#endif /* defined(unix) */
+
+/*
+ * Codes specified in AL for various services.
+ */
+
+#define QUERY_SESSION_ID 0x01
+#define QUERY_SESSION_PARAMETERS 0x02
+#define QUERY_SESSION_CURSOR 0x0b
+
+#define CONNECT_TO_KEYBOARD 0x01
+#define DISCONNECT_FROM_KEYBOARD 0x02
+#define WRITE_KEYSTROKE 0x04
+#define DISABLE_INPUT 0x05
+#define ENABLE_INPUT 0x06
+
+#define COPY_STRING 0x01
+
+#define READ_OIA_GROUP 0x02
+
+/*
+ * For each service, we define the assoicated parameter blocks.
+ */
+
+/*
+ * Supervisor Services
+ */
+
+typedef struct {
+ char gate_name[8];
+} NameResolveParms;
+
+
+/*
+ * Session Information Services
+ */
+
+typedef struct {
+ char
+ short_name,
+ type,
+ session_id,
+ reserved,
+ long_name[8];
+} NameArrayElement;
+
+typedef struct {
+ unsigned char
+ length,
+ number_matching_session;
+ NameArrayElement
+ name_array_element; /* Variable number */
+} NameArray;
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ option_code,
+ data_code;
+ NameArray far
+ *name_array;
+ char
+ long_name[8];
+} QuerySessionIdParms;
+
+#define ID_OPTION_BY_NAME 0x01 /* By short (or long) name */
+#define ID_OPTION_ALL 0x00 /* All (of specified type */
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ reserved,
+ session_type,
+ session_characteristics,
+ rows,
+ columns;
+ char far
+ *presentation_space;
+} QuerySessionParametersParms;
+
+#define TYPE_WSCTL 0x01 /* Work Station Control */
+#define TYPE_DFT 0x02 /* DFT Host Session */
+#define TYPE_CUT 0x03 /* CUT Host Session */
+#define TYPE_NOTEPAD 0x04 /* Notepad Session */
+#define TYPE_PC 0x05 /* Personal Computer Session */
+
+#define CHARACTERISTIC_EAB 0x80 /* Extended Attribute Buffer */
+#define CHARACTERISTIC_PSS 0x40 /* Program Symbols Supported */
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ cursor_type,
+ row_address, /* from 0 */
+ column_address; /* from 0 */
+} QuerySessionCursorParms;
+
+#define CURSOR_INHIBITED_AUTOSCROLL 0x10
+#define CURSOR_INHIBITED 0x04
+#define CURSOR_BLINKING 0x02
+#define CURSOR_BOX 0x01
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ reserved;
+ short
+ event_queue_id,
+ input_queue_id;
+ char
+ intercept_options,
+ first_connection_identifier;
+} ConnectToKeyboardParms;
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ reserved;
+ short
+ connectors_task_id;
+} DisconnectFromKeyboardParms;
+
+typedef struct {
+ unsigned char
+ scancode,
+ shift_state;
+} KeystrokeEntry;
+
+typedef struct {
+ short
+ length; /* Length (in bytes) of list */
+ KeystrokeEntry keystrokes; /* Variable size */
+} KeystrokeList;
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ reserved;
+ short
+ connectors_task_id;
+ char
+ options,
+ number_of_keys_sent;
+ union {
+ KeystrokeEntry
+ keystroke_entry;
+ KeystrokeList far
+ *keystroke_list;
+ } keystroke_specifier;
+} WriteKeystrokeParms;
+
+#define OPTION_SINGLE_KEYSTROKE 0x20
+#define OPTION_MULTIPLE_KEYSTROKES 0x30
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ reserved;
+ short
+ connectors_task_id;
+} DisableInputParms;
+
+typedef DisableInputParms EnableInputParms;
+
+typedef struct {
+ char
+ session_id,
+ reserved;
+ char far
+ *buffer;
+ char
+ characteristics,
+ session_type;
+ short
+ begin; /* Offset within buffer */
+} BufferDescriptor;
+
+typedef struct {
+ char
+ rc,
+ function_id;
+ BufferDescriptor
+ source;
+ short
+ source_end; /* Offset within source buffer */
+ BufferDescriptor
+ target;
+ char
+ copy_mode,
+ reserved;
+} CopyStringParms;
+
+#define COPY_MODE_7_COLOR 0x80 /* Else 4 color mode */
+#define COPY_MODE_FIELD_ATTRIBUTES 0x40 /* Else don't copy attributes */
+
+typedef struct {
+ char
+ rc,
+ function_id,
+ session_id,
+ reserved;
+ char far
+ *oia_buffer;
+ char
+ oia_group_number;
+} ReadOiaGroupParms;
+
+/* If the user wants all groups, we return API_OIA_BYTES_ALL_GROUPS bytes */
+#define API_OIA_ALL_GROUPS '\377'
+#define API_OIA_BYTES_ALL_GROUPS 22 /* 22 bytes of data */
+
+/* API_OIA_INPUT_INHIBITED is special. It returns more than on byte of data */
+#define API_OIA_INPUT_INHIBITED 8
+
+#define API_OIA_LAST_LEGAL_GROUP 18 /* Highest legal number */
+
+
+
+#if defined(MSDOS)
+
+#if !defined(FP_SEG)
+#include <dos.h>
+#endif /* !defined(FP_SEG) */
+
+#else /* defined(MSDOS) */
+
+/*
+ * These definitions are here to provide the descriptions of
+ * some registers which are, normally, defined in <dos.h> on
+ * a dos system.
+ */
+
+#define FP_SEG(x) ((unsigned int)(((unsigned long)(x))>>16))
+#define FP_OFF(y) ((unsigned int)(((unsigned long)(y))&0xFFFF))
+
+/*
+ * Undo the preceding.
+ */
+
+#define SEG_OFF_BACK(x,y) (((x)<<16)|(y))
+
+/*
+ * Now, it is somewhat of a pain, but we need to keep
+ * 8086 conventions about which of the "highlow"'s map
+ * into which of the "words".
+ */
+
+#include <sys/param.h> /* Get ENDIAN from machine/endian.h */
+
+/* Determine endian'ess (if necessary) */
+
+#if !(defined(BYTE_ORDER) && defined(BIG_ENDIAN))
+#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax) */
+#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */
+
+#if defined(vax) || defined(ns32000) || defined(i386) || (defined(mips)&&defined(MIPSEL))
+#define BYTE_ORDER LITTLE_ENDIAN
+#endif /* defined(vax) || defined(ns32000) */
+
+#if defined(sun) || defined(tahoe) || defined(ibm032) || defined(pyr) || defined(gould) || (defined(mips)&&defined(MIPSEB))
+#define BYTE_ORDER BIG_ENDIAN
+#endif /* defined(sun) || defined(tahoe) || defined(ibm032) || defined(pyr) || defined(gould) */
+
+#endif /* !(defined(BYTE_ORDER) && defined(BIG_ENDIAN)) */
+
+struct highlow {
+ unsigned char
+#if BYTE_ORDER == LITTLE_ENDIAN
+ al,
+ ah,
+ bl,
+ bh,
+ cl,
+ ch,
+ dl,
+ dh;
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+#if BYTE_ORDER == BIG_ENDIAN
+ ah,
+ al,
+ bh,
+ bl,
+ ch,
+ cl,
+ dh,
+ dl;
+#endif /* BYTE_ORDER == BIG_ENDIAN */
+};
+
+struct words {
+ unsigned short
+ ax,
+ bx,
+ cx,
+ dx;
+ unsigned short
+ si,
+ di;
+};
+
+union REGS {
+ struct highlow h;
+ struct words x;
+};
+
+struct SREGS {
+ unsigned short
+ cs,
+ ds,
+ es,
+ ss;
+};
+#endif /* defined(MSDOS) (else section) */
+
+/* Interface */
+int api_close_api(void);
+int api_open_api(char *);
+int api_exch_api(union REGS *, struct SREGS *, char *, int);
+
+/* api.c */
+void handle_api(union REGS *, struct SREGS *);
diff --git a/comms/tn3270/files/ctlr/ctlr.order b/comms/tn3270/files/ctlr/ctlr.order
new file mode 100644
index 00000000000..90fba838932
--- /dev/null
+++ b/comms/tn3270/files/ctlr/ctlr.order
@@ -0,0 +1,5 @@
+api.o
+inbound.o
+oia.o
+options.o
+outbound.o
diff --git a/comms/tn3270/files/ctlr/declare.h b/comms/tn3270/files/ctlr/declare.h
new file mode 100644
index 00000000000..329b975f670
--- /dev/null
+++ b/comms/tn3270/files/ctlr/declare.h
@@ -0,0 +1,58 @@
+/* $NetBSD: declare.h,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $ */
+/* From NetBSD: declare.h,v 1.6 2003/08/07 11:16:30 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)declare.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Declarations of routines from the controller.
+ */
+
+
+/* outbound.c */
+void init_ctlr(void);
+int FieldInc(int);
+int FieldDec(int);
+void Clear3270(void);
+void AddHost(int, int);
+int DataFromNetwork(char *, int, int);
+void Init3270(void);
+void Stop3270(void);
+
+/* inbound.c */
+void init_inbound(void);
+void ModifyMdt(int, int);
+void DoReadModified(int);
+void DoReadBuffer(void);
+void SendTransparent(char *, int);
+void SendToIBM(void);
+int AcceptKeystroke(unsigned int, unsigned int );
+int DataFrom3270(unsigned char *, int);
diff --git a/comms/tn3270/files/ctlr/function.c b/comms/tn3270/files/ctlr/function.c
new file mode 100644
index 00000000000..fa73d464fb5
--- /dev/null
+++ b/comms/tn3270/files/ctlr/function.c
@@ -0,0 +1,53 @@
+/* $NetBSD: function.c,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $ */
+/* From NetBSD: function.c,v 1.6 2006/03/20 01:34:49 gdamore Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)function.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: function.c,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+/*
+ * This file, which never produces a function.o, is used solely to
+ * be run through the preprocessor.
+ *
+ * On a 4.3 system (or even msdos), "cc -E function.h" would produce
+ * the correct output. Unfortunately, 4.2 compilers aren't quite that
+ * useful.
+ */
+
+#include "function.h"
diff --git a/comms/tn3270/files/ctlr/function.h b/comms/tn3270/files/ctlr/function.h
new file mode 100644
index 00000000000..e83c1742871
--- /dev/null
+++ b/comms/tn3270/files/ctlr/function.h
@@ -0,0 +1,165 @@
+/* $NetBSD: function.h,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $ */
+/* From NetBSD: function.h,v 1.5 2003/08/07 11:16:30 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)function.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * The following are the various functions which the keyboard can ask
+ * the controller to perform.
+ *
+ * Note that this file (the following entries) are scanned by mkhit.c,
+ * and that the format must remain more-or-less consistent
+ * [ \t]*TOKEN
+ */
+
+enum ctlrfcn {
+
+ undefined = 0, /* Not yet touched */
+
+ FCN_NULL, /* Illegal sequence */
+
+ FCN_RESET, /* unlock keyboard */
+ FCN_MAKE_SHIFT_LOCK,
+ FCN_BREAK_SHIFT_LOCK,
+
+ FCN_MAKE_SHIFT, /* shift key pressed DOWN */
+ FCN_BREAK_SHIFT, /* shift key released */
+
+ FCN_MAKE_ALT, /* alt key pressed DOWN */
+ FCN_BREAK_ALT, /* alt key released */
+
+ FCN_MAKE_CTRL,
+
+ FCN_CAPS_LOCK,
+
+ FCN_MONOCASE, /* DISPLAY in upper case */
+ FCN_DVCNL,
+
+ FCN_CHARACTER, /* Not one of the following, but ... */
+ FCN_VERTICAL_BAR, /* EBCDIC solid vertical bar */
+ FCN_CENTSIGN, /* EBCDIC cent sign */
+ FCN_SPACE, /* EBCDIC space */
+ FCN_DP, /* EBCDIC dup character */
+ FCN_FM, /* EBCDIC field mark */
+
+ FCN_AID, /* Some AID key */
+ FCN_ATTN,
+ FCN_CURSEL, /* Cursor select function (and aid) */
+ FCN_TEST, /* Test function */
+
+ FCN_EINP, /* erase input (dangerous) */
+ FCN_EEOF,
+ FCN_DELETE,
+ FCN_INSRT,
+ FCN_TAB,
+ FCN_BTAB,
+ FCN_NL,
+ FCN_HOME,
+ FCN_UP,
+ FCN_DOWN,
+ FCN_RIGHT,
+ FCN_LEFT,
+ FCN_LEFT2,
+ FCN_RIGHT2,
+
+#if !defined(PURE3274)
+ /*
+ * Local editing functions
+ */
+ FCN_SETTAB, /* set a column tab */
+ FCN_DELTAB,
+ FCN_COLTAB,
+ FCN_COLBAK,
+ FCN_INDENT, /* more margin over one col tab */
+ FCN_UNDENT,
+ FCN_SETMRG,
+ FCN_SETHOM,
+ FCN_CLRTAB,
+ FCN_ERASE, /* erase last character */
+ FCN_WERASE,
+ FCN_FERASE,
+ FCN_WORDTAB, /* tab to start of next word */
+ FCN_WORDBACKTAB,
+ FCN_WORDEND, /* find next end of word */
+ FCN_FIELDEND, /* find next end of field */
+
+ /*
+ * APL functions
+ */
+ FCN_APLON, /* start using apl character set */
+ FCN_APLOFF,
+ FCN_APLEND,
+
+ FCN_PCON,
+ FCN_PCOFF,
+ FCN_INIT, /* re-init screen */
+ FCN_SYNCH, /* synch up after line/control error */
+ FCN_FLINP, /* flush input buffer */
+ FCN_RESHOW, /* redraw screen */
+ FCN_MASTER_RESET, /* FLINP, RESET, RESHOW, + more */
+
+ FCN_DISC, /* suspend application */
+ FCN_ESCAPE, /* enter command mode */
+
+ FCN_ALTK, /* Dvorak keyboard */
+
+ FCN_XOFF, /* suspend output to screen */
+ FCN_XON, /* resume output to screen */
+
+ FCN_LPRT /* print screen on printer */
+#endif /* !defined(PURE3274) */
+};
+/*
+ * The following is the structure which defines what a 3270 keystroke
+ * can do.
+ */
+
+struct hits {
+ unsigned char keynumber;
+ struct hit {
+ enum ctlrfcn ctlrfcn;
+ unsigned char code; /* AID value or 3270 display code */
+ } hit[4]; /* plain, shifted, alted, shiftalted */
+};
+
+extern struct hits hits[];
+
+/*
+ * Definitions of the shift state (and the left/right shift key position).
+ */
+
+#define SHIFT_RIGHT 0x20 /* Right shift key is down */
+#define SHIFT_LEFT 0x10 /* Left shift key is down */
+#define SHIFT_CONTROL 0x08 /* Control shift state (unused) */
+#define SHIFT_ALT 0x04 /* ALT shift state */
+#define SHIFT_CAPS 0x02 /* Caps lock state */
+#define SHIFT_UPSHIFT 0x01 /* Upshift state */
diff --git a/comms/tn3270/files/ctlr/hostctlr.h b/comms/tn3270/files/ctlr/hostctlr.h
new file mode 100644
index 00000000000..51e63155b14
--- /dev/null
+++ b/comms/tn3270/files/ctlr/hostctlr.h
@@ -0,0 +1,221 @@
+/* $NetBSD: hostctlr.h,v 1.1.1.1 2010/01/17 01:33:20 dholland Exp $ */
+/* From NetBSD: hostctlr.h,v 1.5 2003/08/07 11:16:31 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)hostctlr.h 4.2 (Berkeley) 4/26/91
+ */
+
+#define INCLUDED_HOST3270
+
+/* define orders given to 3270's */
+
+#define ORDER_SF 0x1d /* Start Field */
+#define ORDER_SFE 0x29 /* Start Field Extended */
+#define ORDER_SBA 0x11 /* Set Buffer Address (for output) */
+#define ORDER_SA 0x28 /* Set Attribute */
+#define ORDER_MF 0x2c /* Modify field */
+#define ORDER_IC 0x13 /* Insert Cursor (at buffer address) */
+#define ORDER_PT 0x05 /* Program Tab (absurdly complicated) */
+#define ORDER_RA 0x3c /* Repeat next character to some addr */
+#define ORDER_EUA 0x12 /* Null out every unprotected field
+ * to some address.
+ */
+#define ORDER_GE 0x08 /* Graphics Escape */
+#define ORDER_YALE 0x2b /* This is a special YALE order, which
+ * introduces YALE extended orders
+ * (like setting tabs, etc.).
+ */
+
+/* The following is defined for initialization and error messages. */
+
+struct orders_def {
+ int
+ code; /* As in 3270 data stream */
+ char
+ *short_name, /* Short name */
+ *long_name; /* Long name */
+};
+
+#define ORDERS_DEF { \
+ { ORDER_SF, "SF", "Start Field" }, \
+ { ORDER_SFE, "SFE", "Start Field Extended" }, \
+ { ORDER_SBA, "SBA", "Set Buffer Address" }, \
+ { ORDER_SA, "SA", "Set Attribute" }, \
+ { ORDER_MF, "MF", "Modify Field" }, \
+ { ORDER_IC, "IC", "Insert Cursor" }, \
+ { ORDER_PT, "PT", "Program Tab" }, \
+ { ORDER_RA, "RA", "Repeat to Address" }, \
+ { ORDER_EUA, "EUA", "Erase Unprotected to Address" }, \
+ { ORDER_GE, "GE", "Graphics Escape" }, \
+ { ORDER_YALE, "YALE", "Yale Order" } \
+}
+
+
+#define ATTR_RESET 0x00 /* SA only - reset to default */
+# define ATTR_DEFAULT 0x00 /* reset to default */
+ /* Also for 0x41-43 below */
+#define ATTR_FIELD 0xC0 /* Field attributes */
+# define ATTR_MASK 0xc0 /* control bits */
+# define ATTR_PROT 0x20 /* protected bit */
+# define ATTR_NUMERIC 0x10 /* numeric field */
+# define ATTR_AUTO_SKIP_MASK 0x30 /* mask to check auto skip */
+# define ATTR_AUTO_SKIP_VALUE 0x30 /* value to have auto skip */
+# define ATTR_DSPD_MASK 0x0c /* highlighting, etc. */
+# define ATTR_DSPD_DNSPD 0x00 /* display, no select */
+# define ATTR_DSPD_DSPD 0x04 /* display, select */
+# define ATTR_DSPD_HIGH 0x08 /* highlighted, select */
+# define ATTR_DSPD_NONDISPLAY 0x0c /* non-display, no select */
+# define ATTR_MDT 0x01 /* modified data tag */
+
+#define ATTR_EXTENDED_HIGHLIGHT 0x41 /* Extended highlighting */
+# define ATTR_BLINK 0xf1 /* Blinking */
+# define ATTR_REVERSE_VIDEO 0xf2 /* Reverse video */
+# define ATTR_UNDERSCORE 0xf3 /* Underline */
+#define ATTR_COLOR 0x42 /* Color */
+# define ATTR_BLUE 0xf1
+# define ATTR_RED 0xf2
+# define ATTR_PINK 0xf3
+# define ATTR_GREEN 0xf4
+# define ATTR_TURQUOISE 0xf5
+# define ATTR_YELLOW 0xf6
+# define ATTR_WHITE 0xf7 /* for 3279; black for 3287; */
+ /* multicolor for triple */
+ /* plane symbol */
+#define ATTR_PROGRAMMED_SYMBOLS 0x43 /* Programmed Symbols */
+# define ATTR_SYMBOL_SET_LOW 0x40 /* Lowest loadable set ID */
+# define ATTR_SYMBOL_SET_HIGH 0xef /* Highest loadable set ID */
+# define ATTR_SYMBOL_SET_APLTEXT 0xf1
+
+/* Non-SNA control unit commands */
+
+#define CMD_ERASE_ALL_UNPROTECTED 0x0f
+#define CMD_ERASE_WRITE 0x05
+#define CMD_ERASE_WRITE_ALTERNATE 0x0d
+#define CMD_READ_BUFFER 0x02
+#define CMD_READ_MODIFIED 0x06
+#define CMD_WRITE 0x01
+#define CMD_WRITE_STRUCTURED_FIELD 0x11
+
+/* SNA control unit commands */
+
+#define CMD_SNA_COPY 0xf7
+#define CMD_SNA_ERASE_ALL_UNPROTECTED 0x6f
+#define CMD_SNA_ERASE_WRITE 0xf5
+#define CMD_SNA_ERASE_WRITE_ALTERNATE 0x7e
+#define CMD_SNA_READ_BUFFER 0xf2
+#define CMD_SNA_READ_MODIFIED 0xf6
+#define CMD_SNA_READ_MODIFIED_ALL 0x6e
+#define CMD_SNA_WRITE 0xf1
+#define CMD_SNA_WRITE_STRUCTURED_FIELD 0xf3
+
+
+#define WCC_RESET 0x40
+#define WCC_ALARM 0x04
+#define WCC_RESTORE 0x02
+#define WCC_RESET_MDT 0x01
+
+
+/* Special EBCDIC characters unique to a 3270 */
+
+#define EBCDIC_BLANK 0x40 /* Space */
+#define EBCDIC_CENTSIGN 0x4a /* Cent sign */
+#define EBCDIC_DUP 0x1c /* DUP character */
+#define EBCDIC_FM 0x1e /* Field mark character */
+#define EBCDIC_PERCENT 0x6c /* Percent sign */
+#define EBCDIC_SLASH 0x61 /* Slash */
+#define EBCDIC_SOH 0x01 /* Start of Heading */
+#define EBCDIC_STX 0x02 /* Start of Text */
+
+/* Structured field types */
+#define SF_3270DS 0x40 /* For write operations */
+#define SF_LPS 0x06 /* Load Programmed Symbols */
+#define SF_SRM 0x09 /* Set Reply Mode */
+#define SF_SWO 0x0b /* Set Window Origin */
+#define SF_READ_PARTITION 0x01 /* Read Partition (Query) */
+#define SF_ERASE_RESET 0x03 /* Erase (and/or Reset) */
+#define SF_SCS_DATA 0x41 /* SCS Data */
+#define SF_CREATE_PARTITION 0x0c /* Create a partition */
+
+/* AID characters sent to host.
+ *
+ * Note that this file (the following entries) are scanned by mkhit.c,
+ * and that the format must remain more-or-less consistent
+ * (#define\tAID_name\t[\t]*TOKEN)
+ */
+
+#define AID_NONE 0x60 /* No AID (display) */
+#define AID_NONE_PRINTER 0xe8 /* No AID (printer) */
+
+#define AID_PA1 0x6c
+#define AID_PA2 0x6e
+#define AID_PA3 0x6b
+#define AID_CLEAR 0x6d
+#define AID_TREQ 0xf0
+#define AID_ENTER 0x7d
+#define AID_SELPEN 0x7e /*
+ * Really, only SELPEN with DESIGNATOR
+ * = space or null
+ */
+#define AID_PF1 0xf1
+#define AID_PF2 0xf2
+#define AID_PF3 0xf3
+#define AID_PF4 0xf4
+#define AID_PF5 0xf5
+#define AID_PF6 0xf6
+#define AID_PF7 0xf7
+#define AID_PF8 0xf8
+#define AID_PF9 0xf9
+#define AID_PF10 0x7a
+#define AID_PF11 0x7b
+#define AID_PF12 0x7c
+#define AID_PF13 0xc1
+#define AID_PF14 0xc2
+#define AID_PF15 0xc3
+#define AID_PF16 0xc4
+#define AID_PF17 0xc5
+#define AID_PF18 0xc6
+#define AID_PF19 0xc7
+#define AID_PF20 0xc8
+#define AID_PF21 0xc9
+#define AID_PF22 0x4a
+#define AID_PF23 0x4b
+#define AID_PF24 0x4c
+#define AID_PF25 0xd1
+#define AID_PF26 0xd2
+#define AID_PF27 0xd3
+#define AID_PF28 0xd4
+#define AID_PF29 0xd5
+#define AID_PF30 0xd6
+#define AID_PF31 0xd7
+#define AID_PF32 0xd8
+#define AID_PF33 0xd9
+#define AID_PF34 0x5a
+#define AID_PF35 0x5b
+#define AID_PF36 0x5c
diff --git a/comms/tn3270/files/ctlr/inbound.c b/comms/tn3270/files/ctlr/inbound.c
new file mode 100644
index 00000000000..ba4742ce9fd
--- /dev/null
+++ b/comms/tn3270/files/ctlr/inbound.c
@@ -0,0 +1,1214 @@
+/* $NetBSD: inbound.c,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $ */
+/* From NetBSD: inbound.c,v 1.7 2003/08/07 11:16:31 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)inbound.c 4.3 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: inbound.c,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+
+#include "../general/general.h"
+#include "function.h"
+#include "hostctlr.h"
+#include "oia.h"
+#include "scrnctlr.h"
+#include "screen.h"
+#include "options.h"
+#include "../api/dctype.h"
+#include "../api/ebc_disp.h"
+
+#include "../general/globals.h"
+#include "../sys_curses/telextrn.h"
+#include "externs.h"
+#include "declare.h"
+
+#define EmptyChar() (ourPTail == ourPHead)
+#define FullChar() (ourPHead == ourBuffer+sizeof ourBuffer)
+
+
+/*
+ * We define something to allow us to to IsProtected() quickly
+ * on unformatted screens (with the current algorithm for fields,
+ * unprotected takes exponential time...).
+ *
+ * The idea is to call SetXIsProtected() BEFORE the
+ * loop, then use XIsProtected().
+ */
+
+#define SetXIsProtected() (XWasSF = 1)
+#define XIsProtected(p) (IsStartField(p) ? \
+ (XWasSF = 1) : \
+ (XWasSF ? \
+ (XWasSF = 0, XProtected = IsProtected(p)) : \
+ XProtected))
+
+static char ourBuffer[400];
+
+static char *ourPHead = ourBuffer,
+ *ourPTail = ourBuffer;
+
+static int HadAid; /* Had an AID haven't sent */
+
+static int InsertMode; /* is the terminal in insert mode? */
+
+static unsigned int
+ rememberedshiftstate; /* Shift (alt) state of terminal */
+
+# define HITNUM(s) ((((s)&(SHIFT_CAPS|SHIFT_UPSHIFT))? 1:0) \
+ + ((((s)&SHIFT_ALT)? 1:0)<<1))
+
+static int XWasSF, XProtected; /* For optimizations */
+#if !defined(PURE3274)
+extern int TransparentClock, OutputClock;
+#endif /* !defined(PURE3274) */
+
+#include "kbd.out" /* Get keyboard mapping function */
+
+/* the following are global variables */
+
+extern int UnLocked; /* keyboard is UnLocked? */
+
+
+static void Tab(void);
+static void BackTab(void);
+static void EraseEndOfField(void);
+static void Delete(int, int );
+static void ColBak(void);
+static void ColTab(void);
+static void Home(void);
+static int LastOfField(int);
+static void FlushChar(void);
+static void AddChar(int);
+static void SendUnformatted(void);
+static int SendField(int, int);
+static void OneCharacter(int, int);
+
+/*
+ * init_inbound :
+ *
+ * Reset variables to initial state.
+ */
+
+void
+init_inbound()
+{
+ ourPHead = ourPTail = ourBuffer;
+ HadAid = 0;
+ rememberedshiftstate = 0;
+ InsertMode = 0;
+}
+
+
+/* Tab() - sets cursor to the start of the next unprotected field */
+static void
+Tab()
+{
+ int i, j;
+
+ i = CursorAddress;
+ j = WhereAttrByte(CursorAddress);
+ do {
+ if (IsStartField(i) && IsUnProtected(ScreenInc(i))) {
+ break;
+ }
+ i = FieldInc(i);
+ } while (i != j);
+ if (IsStartField(i) && IsUnProtected(ScreenInc(i))) {
+ CursorAddress = ScreenInc(i);
+ } else {
+ CursorAddress = SetBufferAddress(0,0);
+ }
+}
+
+
+/* BackTab() - sets cursor to the start of the most recent field */
+
+static void
+BackTab()
+{
+ int i;
+
+ i = ScreenDec(CursorAddress);
+ for (;;) {
+ if (IsStartField(ScreenDec(i)) && IsUnProtected(i)) {
+ CursorAddress = i;
+ break;
+ }
+ if (i == CursorAddress) {
+ CursorAddress = SetBufferAddress(0,0);
+ break;
+ }
+ i = ScreenDec(i);
+ }
+}
+
+/*
+ * ModifyMdt() - Turn a modified data tag bit on or off (watch
+ * out for unformatted screens).
+ */
+
+void
+ModifyMdt(x,on)
+int x;
+int on;
+{
+ int i = x;
+
+ if (IsStartField(i)) { /* If we are at a start field position... */
+ if (on) {
+ ModifyHost(i, |= ATTR_MDT); /* Turn it on */
+ } else {
+ ModifyHost(i, &= ~ATTR_MDT); /* Turn it off */
+ }
+ } else {
+ i = WhereAttrByte(i); /* Find beginning of field */
+ if (IsStartField(i)) { /* Is there one? */
+ if (on) {
+ ModifyHost(i, |= ATTR_MDT); /* Turn it on */
+ } else {
+ ModifyHost(i, &= ~ATTR_MDT); /* Turn it off */
+ }
+ } /* else, don't modify - this is an unformatted screen */
+ }
+}
+
+
+/* EraseEndOfField - erase all characters to the end of a field */
+
+static void
+EraseEndOfField()
+{
+ int i;
+
+ if (IsProtected(CursorAddress)) {
+ RingBell("Protected Field");
+ } else {
+ TurnOnMdt(CursorAddress);
+ if (FormattedScreen()) {
+ i = CursorAddress;
+ do {
+ AddHost(i, 0);
+ i = ScreenInc(i);
+ } while ((i != CursorAddress) && !IsStartField(i));
+ } else { /* Screen is Unformatted */
+ i = CursorAddress;
+ do {
+ AddHost(i, 0);
+ i = ScreenInc(i);
+ } while (i != HighestScreen());
+ }
+ }
+}
+
+/* Delete() - deletes a character from the screen
+ *
+ * What we want to do is delete the section
+ * [where, from-1] from the screen,
+ * filling in with what comes at from.
+ *
+ * The deleting continues to the end of the field (or
+ * until the cursor wraps).
+ *
+ * From can be a start of a field. We
+ * check for that. However, there can't be any
+ * fields that start between where and from.
+ * We don't check for that.
+ *
+ * Also, we assume that the protection status of
+ * everything has been checked by the caller.
+ *
+ */
+
+static void
+Delete(where, from)
+int where, /* Where to start deleting from */
+ from; /* Where to pull back from */
+{
+ int i;
+
+ TurnOnMdt(where); /* Only do this once in this field */
+ i = where;
+ do {
+ if (IsStartField(from)) {
+ AddHost(i, 0); /* Stick the edge at the start field */
+ } else {
+ AddHost(i, (char)GetHost(from));
+ from = ScreenInc(from); /* Move the edge */
+ }
+ i = ScreenInc(i);
+ } while ((!IsStartField(i)) && (i != where));
+}
+
+static void
+ColBak()
+{
+ int i;
+
+ i = ScreenLineOffset(CursorAddress);
+ for (i = i-1; i >= 0; i--) {
+ if (OptColTabs[i]) {
+ break;
+ }
+ }
+ if (i < 0) {
+ i = 0;
+ }
+ CursorAddress = SetBufferAddress(ScreenLine(CursorAddress), i);
+}
+
+static void
+ColTab()
+{
+ int i;
+
+ i = ScreenLineOffset(CursorAddress);
+ for (i = i+1; i < NumberColumns; i++) {
+ if (OptColTabs[i]) {
+ break;
+ }
+ }
+ if (i >= NumberColumns) {
+ i = NumberColumns-1;
+ }
+ CursorAddress = SetBufferAddress(ScreenLine(CursorAddress), i);
+}
+
+static void
+Home()
+{
+ int i;
+ int j;
+
+ i = SetBufferAddress(OptHome, 0);
+ j = WhereLowByte(i);
+ /*
+ * If the initial value of i points to the field attribute of
+ * an unprotected field, we need to return the address of the
+ * first data byte in the field (assuming there are any!).
+ */
+ if (IsStartField(i) && IsUnProtected(j)) {
+ CursorAddress = j;
+ return;
+ }
+ do {
+ if (IsUnProtected(i)) {
+ CursorAddress = i;
+ return;
+ }
+ /* the following could be a problem if we got here with an
+ * unformatted screen. However, this is "impossible", since
+ * with an unformatted screen, the IsUnProtected(i) above
+ * should be true.
+ */
+ i = ScreenInc(FieldInc(i));
+ } while (i != j);
+ CursorAddress = LowestScreen();
+}
+
+static int
+LastOfField(i)
+int i; /* position to start from */
+{
+ int j;
+ int k;
+
+ k = j = i;
+ SetXIsProtected();
+ while (XIsProtected(i) || Disspace(GetHost(i))) {
+ i = ScreenInc(i);
+ if (i == j) {
+ break;
+ }
+ }
+ /* We are now IN a word IN an unprotected field (or wrapped) */
+ while (!XIsProtected(i)) {
+ if (!Disspace(GetHost(i))) {
+ k = i;
+ }
+ i = ScreenInc(i);
+ if (i == j) {
+ break;
+ }
+ }
+ return(k);
+}
+
+
+static void
+FlushChar()
+{
+ ourPTail = ourPHead = ourBuffer;
+}
+
+
+/*
+ * Add one EBCDIC (NOT display code) character to the buffer.
+ */
+
+static void
+AddChar(character)
+char character;
+{
+ if (FullChar()) {
+ ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 0);
+ if (EmptyChar()) {
+ FlushChar();
+ } else {
+ char buffer[100];
+
+ sprintf(buffer, "File %s, line %d: No room in network buffer!\n",
+ __FILE__, __LINE__);
+ ExitString(buffer, 1);
+ /*NOTREACHED*/
+ }
+ }
+ *ourPHead++ = character;
+}
+
+
+static void
+SendUnformatted()
+{
+ int i, j;
+ int Nulls;
+ int c;
+
+ /* look for start of field */
+ Nulls = 0;
+ i = j = LowestScreen();
+ do {
+ c = GetHost(i);
+ if (c == 0) {
+ Nulls++;
+ } else {
+ while (Nulls) {
+ Nulls--;
+ AddChar(EBCDIC_BLANK); /* put in blanks */
+ }
+ AddChar((char)disp_ebc[c]);
+ }
+ i = ScreenInc(i);
+ } while (i != j);
+}
+
+static int
+SendField(i, cmd)
+int i; /* where we saw MDT bit */
+int cmd; /* The command code (type of read) */
+{
+ int j;
+ int k;
+ int Nulls;
+ int c;
+
+ /* look for start of field */
+ i = j = WhereLowByte(i);
+
+ /* On a test_request_read, don't send sba and address */
+ if ((AidByte != AID_TREQ)
+ || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
+ AddChar(ORDER_SBA); /* set start field */
+ AddChar(BufferTo3270_0(j)); /* set address of this field */
+ AddChar(BufferTo3270_1(j));
+ }
+ /*
+ * Only on read_modified_all do we return the contents
+ * of the field when the attention was caused by a
+ * selector pen.
+ */
+ if ((AidByte != AID_SELPEN)
+ || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
+ if (!IsStartField(j)) {
+ Nulls = 0;
+ k = ScreenInc(WhereHighByte(j));
+ do {
+ c = GetHost(j);
+ if (c == 0) {
+ Nulls++;
+ } else {
+ while (Nulls) {
+ Nulls--;
+ AddChar(EBCDIC_BLANK); /* put in blanks */
+ }
+ AddChar((char)disp_ebc[c]);
+ }
+ j = ScreenInc(j);
+ } while ((j != k) && (j != i));
+ }
+ } else {
+ j = FieldInc(j);
+ }
+ return(j);
+}
+
+/* Various types of reads... */
+void
+DoReadModified(cmd)
+int cmd; /* The command sent */
+{
+ int i, j;
+
+ if (AidByte) {
+ if (AidByte != AID_TREQ) {
+ AddChar(AidByte);
+ } else {
+ /* Test Request Read header */
+ AddChar(EBCDIC_SOH);
+ AddChar(EBCDIC_PERCENT);
+ AddChar(EBCDIC_SLASH);
+ AddChar(EBCDIC_STX);
+ }
+ } else {
+ AddChar(AID_NONE);
+ }
+ if (((AidByte != AID_PA1) && (AidByte != AID_PA2)
+ && (AidByte != AID_PA3) && (AidByte != AID_CLEAR))
+ || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
+ if ((AidByte != AID_TREQ)
+ || (cmd == CMD_SNA_READ_MODIFIED_ALL)) {
+ /* Test request read_modified doesn't give cursor address */
+ AddChar(BufferTo3270_0(CursorAddress));
+ AddChar(BufferTo3270_1(CursorAddress));
+ }
+ i = j = WhereAttrByte(LowestScreen());
+ /* Is this an unformatted screen? */
+ if (!IsStartField(i)) { /* yes, handle separate */
+ SendUnformatted();
+ } else {
+ do {
+ if (HasMdt(i)) {
+ i = SendField(i, cmd);
+ } else {
+ i = FieldInc(i);
+ }
+ } while (i != j);
+ }
+ }
+ ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
+ if (EmptyChar()) {
+ FlushChar();
+ HadAid = 0; /* killed that buffer */
+ }
+}
+
+/* A read buffer operation... */
+
+void
+DoReadBuffer()
+{
+ int i, j;
+
+ if (AidByte) {
+ AddChar(AidByte);
+ } else {
+ AddChar(AID_NONE);
+ }
+ AddChar(BufferTo3270_0(CursorAddress));
+ AddChar(BufferTo3270_1(CursorAddress));
+ i = j = LowestScreen();
+ do {
+ if (IsStartField(i)) {
+ AddChar(ORDER_SF);
+ AddChar(BufferTo3270_1(FieldAttributes(i)));
+ } else {
+ AddChar((char)disp_ebc[GetHost(i)]);
+ }
+ i = ScreenInc(i);
+ } while (i != j);
+ ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
+ if (EmptyChar()) {
+ FlushChar();
+ HadAid = 0; /* killed that buffer */
+ }
+}
+
+/* Send some transparent data to the host */
+
+void
+SendTransparent(buffer, count)
+char *buffer;
+int count;
+{
+ char stuff[3];
+
+ stuff[0] = AID_NONE_PRINTER;
+ stuff[1] = BufferTo3270_0(count);
+ stuff[2] = BufferTo3270_1(count);
+ DataToNetwork(stuff, sizeof stuff, 0);
+ DataToNetwork(buffer, count, 1);
+}
+
+
+/* Try to send some data to host */
+
+void
+SendToIBM()
+{
+#if !defined(PURE3274)
+ if (TransparentClock >= OutputClock) {
+ if (HadAid) {
+ AddChar(AidByte);
+ HadAid = 0;
+ } else {
+ AddChar(AID_NONE_PRINTER);
+ }
+ do {
+ ourPTail += DataToNetwork(ourPTail, ourPHead-ourPTail, 1);
+ } while (!EmptyChar());
+ FlushChar();
+ } else if (HadAid) {
+ DoReadModified(CMD_READ_MODIFIED);
+ }
+#else /* !defined(PURE3274) */
+ if (HadAid) {
+ DoReadModified(CMD_READ_MODIFIED);
+ }
+#endif /* !defined(PURE3274) */
+}
+
+/* This takes in one character from the keyboard and places it on the
+ * screen.
+ */
+
+static void
+OneCharacter(c, insert)
+int c; /* character (Ebcdic) to be shoved in */
+int insert; /* are we in insert mode? */
+{
+ int i, j;
+
+ if (IsProtected(CursorAddress)) {
+ RingBell("Protected Field");
+ return;
+ }
+ if (insert) {
+ /* is the last character in the field a blank or null? */
+ i = ScreenDec(FieldInc(CursorAddress));
+ j = GetHost(i);
+ if (!Disspace(j)) {
+ RingBell("No more room for insert");
+ return;
+ } else {
+ for (j = ScreenDec(i); i != CursorAddress;
+ j = ScreenDec(j), i = ScreenDec(i)) {
+ AddHost(i, (char)GetHost(j));
+ }
+ }
+ }
+ AddHost(CursorAddress, c);
+ TurnOnMdt(CursorAddress);
+ CursorAddress = ScreenInc(CursorAddress);
+ if (IsStartField(CursorAddress) &&
+ ((FieldAttributes(CursorAddress)&ATTR_AUTO_SKIP_MASK) ==
+ ATTR_AUTO_SKIP_VALUE)) {
+ Tab();
+ }
+}
+
+/*
+ * AcceptKeystroke()
+ *
+ * Processes one keystroke.
+ *
+ * Returns:
+ *
+ * 0 if this keystroke was NOT processed.
+ * 1 if everything went OK.
+ */
+
+int
+AcceptKeystroke(scancode, shiftstate)
+unsigned int
+ scancode, /* 3270 scancode */
+ shiftstate; /* The shift state */
+{
+ int c;
+ int i;
+ int j;
+ enum ctlrfcn ctlrfcn;
+
+ if (scancode >= numberof(hits)) {
+ ExitString(
+ "Unknown scancode encountered in AcceptKeystroke.\n", 1);
+ /*NOTREACHED*/
+ }
+ ctlrfcn = hits[scancode].hit[HITNUM(shiftstate)].ctlrfcn;
+ c = hits[scancode].hit[HITNUM(shiftstate)].code;
+
+ if (!UnLocked || HadAid) {
+ if (HadAid) {
+ SendToIBM();
+ if (!EmptyChar()) {
+ return 0; /* nothing to do */
+ }
+ }
+#if !defined(PURE3274)
+ if (!HadAid && EmptyChar()) {
+ if ((ctlrfcn == FCN_RESET) || (ctlrfcn == FCN_MASTER_RESET)) {
+ UnLocked = 1;
+ }
+ }
+#endif /* !defined(PURE3274) */
+ if (!UnLocked) {
+ return 0;
+ }
+ }
+
+ /* now, either empty, or haven't seen aid yet */
+
+#if !defined(PURE3274)
+ /*
+ * If we are in transparent (output) mode, do something special
+ * with keystrokes.
+ */
+ if (TransparentClock == OutputClock) {
+ if (ctlrfcn == FCN_AID) {
+ UnLocked = 0;
+ InsertMode = 0;
+ AidByte = (c);
+ HadAid = 1;
+ } else {
+ switch (ctlrfcn) {
+ case FCN_ESCAPE:
+ StopScreen(1);
+ command(0, NULL, 0);
+ if (shell_active == 0) {
+ ConnectScreen();
+ }
+ break;
+
+ case FCN_RESET:
+ case FCN_MASTER_RESET:
+ UnLocked = 1;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ }
+#endif /* !defined(PURE3274) */
+
+ if (ctlrfcn == FCN_CHARACTER) {
+ /* Add the character to the buffer */
+ OneCharacter(c, InsertMode);
+ } else if (ctlrfcn == FCN_AID) { /* got Aid */
+ if (c == AID_CLEAR) {
+ LocalClearScreen(); /* Side effect is to clear 3270 */
+ }
+ ResetOiaOnlineA(&OperatorInformationArea);
+ SetOiaTWait(&OperatorInformationArea);
+ ResetOiaInsert(&OperatorInformationArea);
+ InsertMode = 0; /* just like a 3278 */
+ SetOiaSystemLocked(&OperatorInformationArea);
+ SetOiaModified();
+ UnLocked = 0;
+ AidByte = c;
+ HadAid = 1;
+ SendToIBM();
+ } else {
+ switch (ctlrfcn) {
+
+ case FCN_CURSEL:
+ c = FieldAttributes(CursorAddress)&ATTR_DSPD_MASK;
+ if (!FormattedScreen()
+ || ((c != ATTR_DSPD_DSPD) && (c != ATTR_DSPD_HIGH))) {
+ RingBell("Cursor not in selectable field");
+ } else {
+ i = ScreenInc(WhereAttrByte(CursorAddress));
+ c = GetHost(i);
+ if (c == DISP_QUESTION) {
+ AddHost(i, DISP_GREATER_THAN);
+ TurnOnMdt(i);
+ } else if (c == DISP_GREATER_THAN) {
+ AddHost(i, DISP_QUESTION);
+ TurnOffMdt(i);
+ } else if (c == DISP_BLANK || c == DISP_NULL
+ || c == DISP_AMPERSAND) {
+ UnLocked = 0;
+ InsertMode = 0;
+ ResetOiaOnlineA(&OperatorInformationArea);
+ SetOiaTWait(&OperatorInformationArea);
+ SetOiaSystemLocked(&OperatorInformationArea);
+ ResetOiaInsert(&OperatorInformationArea);
+ SetOiaModified();
+ if (c == DISP_AMPERSAND) {
+ TurnOnMdt(i); /* Only for & type */
+ AidByte = AID_ENTER;
+ } else {
+ AidByte = AID_SELPEN;
+ }
+ HadAid = 1;
+ SendToIBM();
+ } else {
+ RingBell(
+ "Cursor not in a selectable field (designator)");
+ }
+ }
+ break;
+
+#if !defined(PURE3274)
+ case FCN_ERASE:
+ if (IsProtected(ScreenDec(CursorAddress))) {
+ RingBell("Protected Field");
+ } else {
+ CursorAddress = ScreenDec(CursorAddress);
+ Delete(CursorAddress, ScreenInc(CursorAddress));
+ }
+ break;
+ case FCN_WERASE:
+ j = CursorAddress;
+ i = ScreenDec(j);
+ if (IsProtected(i)) {
+ RingBell("Protected Field");
+ } else {
+ SetXIsProtected();
+ while ((!XIsProtected(i) && Disspace(GetHost(i)))
+ && (i != j)) {
+ i = ScreenDec(i);
+ }
+ /* we are pointing at a character in a word, or
+ * at a protected position
+ */
+ while ((!XIsProtected(i) && !Disspace(GetHost(i)))
+ && (i != j)) {
+ i = ScreenDec(i);
+ }
+ /* we are pointing at a space, or at a protected
+ * position
+ */
+ CursorAddress = ScreenInc(i);
+ Delete(CursorAddress, j);
+ }
+ break;
+
+ case FCN_FERASE:
+ if (IsProtected(CursorAddress)) {
+ RingBell("Protected Field");
+ } else {
+ CursorAddress = ScreenInc(CursorAddress); /* for btab */
+ BackTab();
+ EraseEndOfField();
+ }
+ break;
+
+ case FCN_RESET:
+ if (InsertMode) {
+ InsertMode = 0;
+ ResetOiaInsert(&OperatorInformationArea);
+ SetOiaModified();
+ }
+ break;
+ case FCN_MASTER_RESET:
+ if (InsertMode) {
+ InsertMode = 0;
+ ResetOiaInsert(&OperatorInformationArea);
+ SetOiaModified();
+ }
+ RefreshScreen();
+ break;
+#endif /* !defined(PURE3274) */
+
+ case FCN_UP:
+ CursorAddress = ScreenUp(CursorAddress);
+ break;
+
+ case FCN_LEFT:
+ CursorAddress = ScreenDec(CursorAddress);
+ break;
+
+ case FCN_RIGHT:
+ CursorAddress = ScreenInc(CursorAddress);
+ break;
+
+ case FCN_DOWN:
+ CursorAddress = ScreenDown(CursorAddress);
+ break;
+
+ case FCN_DELETE:
+ if (IsProtected(CursorAddress)) {
+ RingBell("Protected Field");
+ } else {
+ Delete(CursorAddress, ScreenInc(CursorAddress));
+ }
+ break;
+
+ case FCN_INSRT:
+ InsertMode = !InsertMode;
+ if (InsertMode) {
+ SetOiaInsert(&OperatorInformationArea);
+ } else {
+ ResetOiaInsert(&OperatorInformationArea);
+ }
+ SetOiaModified();
+ break;
+
+ case FCN_HOME:
+ Home();
+ break;
+
+ case FCN_NL:
+ /* The algorithm is to look for the first unprotected
+ * column after column 0 of the following line. Having
+ * found that unprotected column, we check whether the
+ * cursor-address-at-entry is at or to the right of the
+ * LeftMargin AND the LeftMargin column of the found line
+ * is unprotected. If this conjunction is true, then
+ * we set the found pointer to the address of the LeftMargin
+ * column in the found line.
+ * Then, we set the cursor address to the found address.
+ */
+ i = SetBufferAddress(ScreenLine(ScreenDown(CursorAddress)), 0);
+ j = ScreenInc(WhereAttrByte(CursorAddress));
+ do {
+ if (IsUnProtected(i)) {
+ break;
+ }
+ /* Again (see comment in Home()), this COULD be a problem
+ * with an unformatted screen.
+ */
+ /* If there was a field with only an attribute byte,
+ * we may be pointing to the attribute byte of the NEXT
+ * field, so just look at the next byte.
+ */
+ if (IsStartField(i)) {
+ i = ScreenInc(i);
+ } else {
+ i = ScreenInc(FieldInc(i));
+ }
+ } while (i != j);
+ if (!IsUnProtected(i)) { /* couldn't find unprotected */
+ i = SetBufferAddress(0,0);
+ }
+ if (OptLeftMargin <= ScreenLineOffset(CursorAddress)) {
+ if (IsUnProtected(SetBufferAddress(ScreenLine(i),
+ OptLeftMargin))) {
+ i = SetBufferAddress(ScreenLine(i), OptLeftMargin);
+ }
+ }
+ CursorAddress = i;
+ break;
+
+ case FCN_EINP:
+ if (!FormattedScreen()) {
+ i = CursorAddress;
+ TurnOffMdt(i);
+ do {
+ AddHost(i, 0);
+ i = ScreenInc(i);
+ } while (i != CursorAddress);
+ } else {
+ /*
+ * The algorithm is: go through each unprotected
+ * field on the screen, clearing it out. When
+ * we are at the start of a field, skip that field
+ * if its contents are protected.
+ */
+ i = j = FieldInc(CursorAddress);
+ do {
+ if (IsUnProtected(ScreenInc(i))) {
+ i = ScreenInc(i);
+ TurnOffMdt(i);
+ do {
+ AddHost(i, 0);
+ i = ScreenInc(i);
+ } while (!IsStartField(i));
+ } else {
+ i = FieldInc(i);
+ }
+ } while (i != j);
+ }
+ Home();
+ break;
+
+ case FCN_EEOF:
+ EraseEndOfField();
+ break;
+
+ case FCN_SPACE:
+ OneCharacter(DISP_BLANK, InsertMode); /* Add cent */
+ break;
+
+ case FCN_CENTSIGN:
+ OneCharacter(DISP_CENTSIGN, InsertMode); /* Add cent */
+ break;
+
+ case FCN_FM:
+ OneCharacter(DISP_FM, InsertMode); /* Add field mark */
+ break;
+
+ case FCN_DP:
+ if (IsProtected(CursorAddress)) {
+ RingBell("Protected Field");
+ } else {
+ OneCharacter(DISP_DUP, InsertMode);/* Add dup character */
+ Tab();
+ }
+ break;
+
+ case FCN_TAB:
+ Tab();
+ break;
+
+ case FCN_BTAB:
+ BackTab();
+ break;
+
+#ifdef NOTUSED /* Actually, this is superseded by unix flow
+ * control.
+ */
+ case FCN_XOFF:
+ Flow = 0; /* stop output */
+ break;
+
+ case FCN_XON:
+ if (!Flow) {
+ Flow = 1; /* turn it back on */
+ DoTerminalOutput();
+ }
+ break;
+#endif /* NOTUSED */
+
+#if !defined(PURE3274)
+ case FCN_ESCAPE:
+ /* FlushChar(); do we want to flush characters from before? */
+ StopScreen(1);
+ command(0, NULL, 0);
+ if (shell_active == 0) {
+ ConnectScreen();
+ }
+ break;
+
+ case FCN_DISC:
+ StopScreen(1);
+ suspend(0, NULL);
+ setconnmode(0);
+ ConnectScreen();
+ break;
+
+ case FCN_RESHOW:
+ RefreshScreen();
+ break;
+
+ case FCN_SETTAB:
+ OptColTabs[ScreenLineOffset(CursorAddress)] = 1;
+ break;
+
+ case FCN_DELTAB:
+ OptColTabs[ScreenLineOffset(CursorAddress)] = 0;
+ break;
+
+ /*
+ * Clear all tabs, home line, and left margin.
+ */
+ case FCN_CLRTAB:
+ for (i = 0; i < sizeof OptColTabs; i++) {
+ OptColTabs[i] = 0;
+ }
+ OptHome = 0;
+ OptLeftMargin = 0;
+ break;
+
+ case FCN_COLTAB:
+ ColTab();
+ break;
+
+ case FCN_COLBAK:
+ ColBak();
+ break;
+
+ case FCN_INDENT:
+ ColTab();
+ OptLeftMargin = ScreenLineOffset(CursorAddress);
+ break;
+
+ case FCN_UNDENT:
+ ColBak();
+ OptLeftMargin = ScreenLineOffset(CursorAddress);
+ break;
+
+ case FCN_SETMRG:
+ OptLeftMargin = ScreenLineOffset(CursorAddress);
+ break;
+
+ case FCN_SETHOM:
+ OptHome = ScreenLine(CursorAddress);
+ break;
+
+ /*
+ * Point to first character of next unprotected word on
+ * screen.
+ */
+ case FCN_WORDTAB:
+ i = CursorAddress;
+ SetXIsProtected();
+ while (!XIsProtected(i) && !Disspace(GetHost(i))) {
+ i = ScreenInc(i);
+ if (i == CursorAddress) {
+ break;
+ }
+ }
+ /* i is either protected, a space (blank or null),
+ * or wrapped
+ */
+ while (XIsProtected(i) || Disspace(GetHost(i))) {
+ i = ScreenInc(i);
+ if (i == CursorAddress) {
+ break;
+ }
+ }
+ CursorAddress = i;
+ break;
+
+ case FCN_WORDBACKTAB:
+ i = ScreenDec(CursorAddress);
+ SetXIsProtected();
+ while (XIsProtected(i) || Disspace(GetHost(i))) {
+ i = ScreenDec(i);
+ if (i == CursorAddress) {
+ break;
+ }
+ }
+ /* i is pointing to a character IN an unprotected word
+ * (or i wrapped)
+ */
+ while (!Disspace(GetHost(i))) {
+ i = ScreenDec(i);
+ if (i == CursorAddress) {
+ break;
+ }
+ }
+ CursorAddress = ScreenInc(i);
+ break;
+
+ /* Point to last non-blank character of this/next
+ * unprotected word.
+ */
+ case FCN_WORDEND:
+ i = ScreenInc(CursorAddress);
+ SetXIsProtected();
+ while (XIsProtected(i) || Disspace(GetHost(i))) {
+ i = ScreenInc(i);
+ if (i == CursorAddress) {
+ break;
+ }
+ }
+ /* we are pointing at a character IN an
+ * unprotected word (or we wrapped)
+ */
+ while (!Disspace(GetHost(i))) {
+ i = ScreenInc(i);
+ if (i == CursorAddress) {
+ break;
+ }
+ }
+ CursorAddress = ScreenDec(i);
+ break;
+
+ /* Get to last non-blank of this/next unprotected
+ * field.
+ */
+ case FCN_FIELDEND:
+ i = LastOfField(CursorAddress);
+ if (i != CursorAddress) {
+ CursorAddress = i; /* We moved; take this */
+ } else {
+ j = FieldInc(CursorAddress); /* Move to next field */
+ i = LastOfField(j);
+ if (i != j) {
+ CursorAddress = i; /* We moved; take this */
+ }
+ /* else - nowhere else on screen to be; stay here */
+ }
+ break;
+#endif /* !defined(PURE3274) */
+
+ default:
+ /* We don't handle this yet */
+ RingBell("Function not implemented");
+ }
+ }
+ return 1; /* We did something! */
+}
+
+
+/*
+ * We get data from the terminal. We keep track of the shift state
+ * (including ALT, CONTROL), and then call AcceptKeystroke to actually
+ * process any non-shift keys.
+ */
+
+int
+DataFrom3270(buffer, count)
+unsigned char *buffer; /* where the data is */
+int count; /* how much data there is */
+{
+ int origCount;
+
+ origCount = count;
+
+ while (count) {
+ if (*buffer >= numberof(hits)) {
+ ExitString("Unknown scancode encountered in DataFrom3270.\n", 1);
+ /*NOTREACHED*/
+ }
+
+ switch (hits[*buffer].hit[HITNUM(rememberedshiftstate)].ctlrfcn) {
+
+ case FCN_MAKE_SHIFT:
+ rememberedshiftstate |= (SHIFT_RIGHT|SHIFT_UPSHIFT);
+ break;
+ case FCN_BREAK_SHIFT:
+ rememberedshiftstate &= ~(SHIFT_RIGHT|SHIFT_UPSHIFT);
+ break;
+ case FCN_MAKE_ALT:
+ rememberedshiftstate |= SHIFT_ALT;
+ break;
+ case FCN_BREAK_ALT:
+ rememberedshiftstate &= ~SHIFT_ALT;
+ break;
+ default:
+ if (AcceptKeystroke(*buffer, rememberedshiftstate) == 0) {
+ return(origCount-count);
+ }
+ break;
+ }
+ buffer++;
+ count--;
+ }
+ return(origCount-count);
+}
diff --git a/comms/tn3270/files/ctlr/oia.c b/comms/tn3270/files/ctlr/oia.c
new file mode 100644
index 00000000000..d87717ac83f
--- /dev/null
+++ b/comms/tn3270/files/ctlr/oia.c
@@ -0,0 +1,56 @@
+/* $NetBSD: oia.c,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $ */
+/* From NetBSD: oia.c,v 1.5 2003/08/07 11:16:31 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)oia.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: oia.c,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Routines to maintain the Operator Information Area.
+ */
+
+#include "../general/general.h"
+
+#include "oia.h"
+#include "../general/globals.h"
+
+
+void
+init_oia()
+{
+ ClearElement(OperatorInformationArea);
+}
diff --git a/comms/tn3270/files/ctlr/oia.h b/comms/tn3270/files/ctlr/oia.h
new file mode 100644
index 00000000000..2df9d997ec0
--- /dev/null
+++ b/comms/tn3270/files/ctlr/oia.h
@@ -0,0 +1,192 @@
+/* $NetBSD: oia.h,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $ */
+/* From NetBSD: oia.h,v 1.6 2003/08/07 11:16:32 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)oia.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * This file describes the Operator Information Area in the 3270.
+ *
+ * Our OIA looks like that used by the 3270 PC and PC 3270 products.
+ */
+
+#define INCLUDED_OIA
+
+typedef struct {
+ char
+ online_ownership,
+ character_selection,
+ shift_state,
+ pss_group_1,
+ highlight_group_1,
+ color_group_1,
+ insert,
+ input_inhibited[5],
+ pss_group_2,
+ highlight_group_2,
+ color_group_2,
+ comm_error_reminder,
+ printer_status,
+ reserved_group_14,
+ reserved_group_15,
+ autokey_play_record_status,
+ autokey_abort_pause_status,
+ enlarge_state;
+} OIA;
+
+/* Bits in online_ownership */
+#define OIA_SETUP 0x80
+#define OIA_TEST 0x40
+#define OIA_SSCP_LU 0x20
+#define OIA_LU_LU 0x10
+#define OIA_UNOWNED 0x08
+#define OIA_SUBSYSTEM_READY 0x04
+
+/* Bit in character_selection */
+#define OIA_EXTENDED_SELECT 0x80
+#define OIA_APL 0x40
+#define OIA_KANA 0x20
+#define OIA_ALPHA 0x10
+#define OIA_TEXT 0x08
+
+/* Bits in shift_state */
+#define OIA_NUMERIC 0x80
+#define OIA_UPPER_SHIFT 0x40
+
+/* Bits in pss_group_1, highlight_group_1, and color_group_1 */
+#define OIA_SELECTABLE 0x80
+#define OIA_FIELD_INHERIT 0x40
+
+/* Bits in insert */
+#define OIA_INSERT_MODE 0x80
+
+/* We define this to be a 'long' followed by a 'char' (5 bytes) */
+
+#define OIA_NON_RESETTABLE 0x80
+#define OIA_SECURITY_KEY 0x40
+#define OIA_MACHINE_CHECK 0x20
+#define OIA_COMM_CHECK 0x10
+#define OIA_PROGRAM_CHECK 0x08
+#define OIA_RETRY 0x04
+#define OIA_DEVICE_NOT_WORKING 0x02
+#define OIA_DEVICE_VERY_BUSY 0x01
+
+#define OIA_DEVICE_BUSY 0x80
+#define OIA_TERMINAL_WAIT 0x40
+#define OIA_MINUS_SYMBOL 0x20
+#define OIA_MINUS_FUNCTION 0x10
+#define OIA_TOO_MUCH_ENTERED 0x08
+#define OIA_NOT_ENOUGH_ENTERED 0x04
+#define OIA_WRONG_NUMBER 0x02
+#define OIA_NUMERIC_FIELD 0x01
+
+#define OIA_OP_UNAUTHORIZED 0x80
+#define OIA_OP_UNAUTHORIZED_MIN 0x40
+#define OIA_INVALID_DEAD_KEY_COMBO 0x20
+#define OIA_WRONG_PLACE 0x10
+
+#define OIA_MESSAGE_PENDING 0x80
+#define OIA_PARTITION_WAIT 0x40
+#define OIA_SYSTEM_WAIT 0x20
+#define OIA_HARDWARE_MISMATCH 0x10
+#define OIA_LOGICAL_TERM_NOT_CONF 0x08
+
+
+#define OIA_AUTOKEY_INHIBIT 0x80
+#define OIA_API_INHIBIT 0x40
+
+/* Bits in pss_group_2 */
+#define OIA_PS_SELECTED 0x80
+#define OIA_PC_DISPLAY_DISABLE 0x40
+
+/* Bits in highlight_group_2 and color_group_2 */
+#define OIA_SELECTED 0x80
+
+/* Bits in comm_error_reminder */
+#define OIA_COMM_ERROR 0x80
+#define OIA_RTM 0x40
+
+/* Bits in printer_status */
+#define OIA_PRINT_NOT_CUSTOM 0x80
+#define OIA_PRINTER_MALFUNCTION 0x40
+#define OIA_PRINTER_PRINTING 0x20
+#define OIA_ASSIGN_PRINTER 0x10
+#define OIA_WHAT_PRINTER 0x08
+#define OIA_PRINTER_ASSIGNMENT 0x04
+
+/* Bits in autokey_play_record_status */
+#define OIA_PLAY 0x80
+#define OIA_RECORD 0x40
+
+/* Bits in autokey_abort_pause_status */
+#define OIA_RECORDING_OVERFLOW 0x80
+#define OIA_PAUSE 0x40
+
+/* Bits in enlarge_state */
+#define OIA_WINDOW_IS_ENLARGED 0x80
+
+/* Define functions to set and read the oia */
+
+#define SetOiaOnlineA(oia) SetOiaMyJob((oia)) /* Side-effect */
+#define ResetOiaOnlineA(oia) \
+ /* Nothing defined for this */
+
+#define IsOiaReady3274(oia) ((oia)->online_ownership&OIA_SUBSYSTEM_READY)
+#define ResetOiaReady3274(oia) (oia)->online_ownership &= ~OIA_SUBSYSTEM_READY
+#define SetOiaReady3274(oia) (oia)->online_ownership |= OIA_SUBSYSTEM_READY
+
+#define IsOiaMyJob(oia) ((oia)->online_ownership&OIA_LU_LU)
+#define ResetOiaMyJob(oia) (oia)->online_ownership &= ~OIA_LU_LU
+#define SetOiaMyJob(oia) (oia)->online_ownership |= OIA_LU_LU
+
+#define IsOiaInsert(oia) ((oia)->online_ownership&OIA_INSERT_MODE)
+#define ResetOiaInsert(oia) (oia)->online_ownership &= ~OIA_INSERT_MODE
+#define SetOiaInsert(oia) (oia)->online_ownership |= OIA_INSERT_MODE
+
+#define IsOiaSystemLocked(oia) ((oia)->input_inhibited[3]&OIA_SYSTEM_WAIT)
+#define ResetOiaSystemLocked(oia) \
+ (oia)->input_inhibited[3] &= ~OIA_SYSTEM_WAIT
+#define SetOiaSystemLocked(oia) (oia)->input_inhibited[3] |= OIA_SYSTEM_WAIT
+
+#define IsOiaTWait(oia) ((oia)->input_inhibited[1]&OIA_TERMINAL_WAIT)
+#define ResetOiaTWait(oia) (oia)->input_inhibited[1] &= ~OIA_TERMINAL_WAIT
+#define SetOiaTWait(oia) (oia)->input_inhibited[1] |= OIA_TERMINAL_WAIT
+
+#define IsOiaApiInhibit(oia) ((oia)->input_inhibited[4] & OIA_API_INHIBIT)
+#define ResetOiaApiInhibit(oia) ((oia)->input_inhibited[4] &= ~OIA_API_INHIBIT)
+#define SetOiaApiInhibit(oia) ((oia)->input_inhibited[4] |= OIA_API_INHIBIT)
+
+/* A macro to let the world know that someone has modified the OIA. */
+#define SetOiaModified() oia_modified = 1
+#define SetPsModified() ps_modified = 1
+
+/* oia.c */
+void init_oia(void);
diff --git a/comms/tn3270/files/ctlr/options.c b/comms/tn3270/files/ctlr/options.c
new file mode 100644
index 00000000000..62c67d8288f
--- /dev/null
+++ b/comms/tn3270/files/ctlr/options.c
@@ -0,0 +1,186 @@
+/* $NetBSD: options.c,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $ */
+/* From NetBSD: options.c,v 1.6 2005/02/11 06:21:22 simonb Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)options.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: options.c,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * this file contains the definitions, initialization, and processing of
+ * commands to handle the various local options (APL ON, etc.)
+ */
+
+#include "options.h"
+
+#include "../general/globals.h"
+#include "declare.h"
+
+void
+OptInit()
+{
+ int i;
+
+ OptAPLmode = 0;
+ OptNullProcessing = 1; /* improved null processing */
+ OptZonesMode = 0; /* zones mode off */
+ OptEnterNL = 0; /* regular enter/new line keys */
+ OptColFieldTab = 0; /* regular column/field tab keys */
+ OptPacing = 1; /* do pacing */
+ OptAlphaInNumeric = 0; /* allow alpha in numeric fields */
+ for (i = 0; i < sizeof OptColTabs; i++) {
+ OptColTabs[i] = ((i%8) == 0); /* every 8 columns */
+ }
+ OptHome = 0;
+ OptLeftMargin = 0;
+ OptWordWrap = 0;
+}
+
+int
+OptOrder(pointer, count, control)
+unsigned char *pointer;
+int count;
+int control;
+{
+ int i, j, character, origCount;
+
+ origCount = count;
+
+ if (count == 0) {
+ return(0);
+ }
+ character = *pointer&0xff;
+ pointer++;
+ count--;
+ switch (character) {
+ case 0xa0:
+ OptAPLmode = 1;
+ break;
+ case 0x61:
+ OptAPLmode = 0;
+ break;
+ case 0x95:
+ OptNullProcessing = 0;
+ break;
+ case 0xd5:
+ OptNullProcessing = 1;
+ break;
+ case 0xa9:
+ OptZonesMode = 1;
+ break;
+ case 0xe9:
+ OptZonesMode = 0;
+ break;
+ case 0x85:
+ OptEnterNL = 1;
+ break;
+ case 0xc5:
+ OptEnterNL = 0;
+ break;
+ case 0x83:
+ OptColFieldTab = 1;
+ break;
+ case 0xc3:
+ OptColFieldTab = 0;
+ break;
+ case 0x97:
+ OptPacing = 0;
+ break;
+ case 0xd7:
+ OptPacing = 1;
+ break;
+ case 0xa5:
+ OptAlphaInNumeric = 1;
+ break;
+ case 0xe5:
+ OptAlphaInNumeric = 0;
+ break;
+ case 0xe3:
+ if (!control && count < 30) {
+ return(0); /* want more! */
+ }
+ for (i = 0; i < sizeof OptColTabs; i++) {
+ OptColTabs[i] = 0;
+ }
+ if (!count) {
+ break;
+ }
+ j = (*pointer&0xff)-0x40;
+ count--;
+ pointer++;
+ if (j < 0 || j >= 24) {
+ break;
+ }
+ OptHome = j;
+ if (!count) {
+ break;
+ }
+ j = (*pointer&0xff)-0x40;
+ count--;
+ pointer++;
+ if (j < 0 || j >= 80) {
+ break;
+ }
+ OptLeftMargin = j;
+ if (!count) {
+ break;
+ }
+ i = count;
+ if (i > 28) {
+ i = 28;
+ }
+ while (i) {
+ j = (*pointer&0xff)-0x40;
+ if (j < 0 || j >= sizeof OptColTabs) {
+ break;
+ }
+ OptColTabs[j] = 1;
+ i--;
+ pointer++;
+ count--;
+ }
+ break;
+ case 0xa6:
+ OptWordWrap = 1;
+ break;
+ case 0xe6:
+ OptWordWrap = 0;
+ break;
+ default:
+ break;
+ }
+ return(origCount - count);
+}
diff --git a/comms/tn3270/files/ctlr/options.h b/comms/tn3270/files/ctlr/options.h
new file mode 100644
index 00000000000..40c137b9aae
--- /dev/null
+++ b/comms/tn3270/files/ctlr/options.h
@@ -0,0 +1,43 @@
+/* $NetBSD: options.h,v 1.1.1.1 2010/01/17 01:33:21 dholland Exp $ */
+/* From NetBSD: options.h,v 1.6 2003/08/07 11:16:32 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)options.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * the various options that run our life. Very few of these are implemented
+ * as yet.
+ */
+
+#define INCLUDED_OPTIONS
+
+void OptInit(void);
+int OptOrder(unsigned char *, int, int);
diff --git a/comms/tn3270/files/ctlr/outbound.c b/comms/tn3270/files/ctlr/outbound.c
new file mode 100644
index 00000000000..33e38aa7a8e
--- /dev/null
+++ b/comms/tn3270/files/ctlr/outbound.c
@@ -0,0 +1,618 @@
+/* $NetBSD: outbound.c,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: outbound.c,v 1.6 2006/04/30 23:38:34 christos Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)outbound.c 4.3 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: outbound.c,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+
+#include "../general/general.h"
+
+#include "hostctlr.h"
+#include "oia.h"
+#include "screen.h"
+#include "options.h"
+#include "../api/ebc_disp.h"
+#include "../ascii/state.h"
+#include "../sys_curses/telextrn.h"
+
+#include "../general/globals.h"
+#include "externs.h"
+#include "declare.h"
+
+#define SetHighestLowest(position) { \
+ if (position < Lowest) { \
+ Lowest = position; \
+ } \
+ if (position > Highest) { \
+ Highest = position; \
+ } \
+ }
+
+
+static int LastWasTerminated = 1; /* was "control" = 1 last time? */
+
+/* some globals */
+
+#if !defined(PURE3274)
+int OutputClock; /* what time it is */
+int TransparentClock; /* time we were last in transparent */
+#endif /* !defined(PURE3274) */
+
+char CIABuffer[64] = {
+ 0x40, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+ 0x50, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 0x61, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
+};
+
+static struct orders_def orders_def[] = ORDERS_DEF;
+
+/*
+ * init_ctlr()
+ *
+ * Initialize all data from the 'data' portion to their startup values.
+ */
+
+void
+init_ctlr()
+{
+ LastWasTerminated = 1;
+ init_inbound();
+ init_oia();
+}
+
+
+int
+FieldInc(position)
+int position; /* Position in previous field */
+{
+ ScreenImage *ptr;
+
+ ptr = (ScreenImage *)memNSchr((char *)Host+position+1, ATTR_MASK,
+ HighestScreen()-position, ATTR_MASK, sizeof Host[0]);
+ if (ptr == 0) {
+ ptr = (ScreenImage *)memNSchr((char *)Host+LowestScreen(), ATTR_MASK,
+ position-LowestScreen(), ATTR_MASK, sizeof Host[0]);
+ if (ptr == 0) {
+ return LowestScreen();
+ }
+ }
+ return ptr-Host;
+}
+
+int
+FieldDec(position)
+int position;
+{
+ ScreenImage *ptr;
+
+ ptr = (ScreenImage *)memNSchr((char *)(Host+position)-1, ATTR_MASK,
+ position-LowestScreen(), ATTR_MASK, -sizeof Host[0]);
+ if (ptr == 0) {
+ ptr = (ScreenImage *)memNSchr((char *)Host+HighestScreen(), ATTR_MASK,
+ HighestScreen()-position, ATTR_MASK, -sizeof Host[0]);
+ if (ptr == 0) {
+ return LowestScreen();
+ }
+ }
+ return ptr-Host;
+}
+
+/* Clear3270 - called to clear the screen */
+
+void
+Clear3270()
+{
+ ClearArray(Host);
+ DeleteAllFields(); /* get rid of all fields */
+ BufferAddress = SetBufferAddress(0,0);
+ CursorAddress = SetBufferAddress(0,0);
+ Lowest = LowestScreen();
+ Highest = HighestScreen();
+}
+
+/* AddHost - called to add a character to the buffer.
+ * We use a macro in this module, since we call it so
+ * often from loops.
+ *
+ * NOTE: It is a macro, so don't go around using AddHost(p, *c++), or
+ * anything similar. (I don't define any temporary variables, again
+ * just for the speed.)
+ */
+void
+AddHost(position, character)
+int position;
+char character;
+{
+# define AddHostA(p,c) \
+ { \
+ if (IsStartField(p)) { \
+ DeleteField(p); \
+ Highest = HighestScreen(); \
+ Lowest = LowestScreen(); \
+ SetHighestLowest(p); \
+ } \
+ SetHost(p, c); \
+ }
+# define AddHost(p,c) \
+ { \
+ if (c != GetHost(p)) { \
+ SetHighestLowest(p); \
+ } \
+ AddHostA(p,c); \
+ } /* end of macro of AddHost */
+
+ AddHost(position, character);
+}
+
+/* returns the number of characters consumed */
+int
+DataFromNetwork(Buffer, count, control)
+char *Buffer; /* what the data is */
+int count; /* and how much there is */
+int control; /* this buffer ended block? */
+{
+ int origCount;
+ unsigned char *buffer = (unsigned char *)Buffer;
+ int c;
+ int i;
+ static int Command;
+ static int Wcc;
+
+ origCount = count;
+
+ /*
+ * If this is the start of a new data stream, then look
+ * for an op-code and (possibly) a WCC.
+ */
+ if (LastWasTerminated) {
+
+ if (count < 2) {
+ if (count == 0) {
+ ExitString("Short count received from host!\n", 1);
+ return(count);
+ }
+ Command = buffer[0];
+ switch (Command) { /* This had better be a read command */
+ case CMD_READ_MODIFIED:
+ case CMD_SNA_READ_MODIFIED:
+ case CMD_SNA_READ_MODIFIED_ALL:
+ SetOiaOnlineA(&OperatorInformationArea);
+ SetOiaModified();
+ DoReadModified(Command);
+ break;
+ case CMD_READ_BUFFER:
+ case CMD_SNA_READ_BUFFER:
+ SetOiaOnlineA(&OperatorInformationArea);
+ SetOiaModified();
+ DoReadBuffer();
+ break;
+ default:
+ {
+ char s_buffer[100];
+
+ sprintf(s_buffer,
+ "Unexpected read command code 0x%x received.\n",
+ Command);
+ ExitString(s_buffer, 1);
+ break;
+ }
+ }
+ return(1); /* We consumed everything */
+ }
+ Command = buffer[0];
+ Wcc = buffer[1];
+ if (Wcc & WCC_RESET_MDT) {
+ i = c = WhereAttrByte(LowestScreen());
+ do {
+ if (HasMdt(i)) {
+ TurnOffMdt(i);
+ }
+ i = FieldInc(i);
+ } while (i != c);
+ }
+
+ switch (Command) {
+ case CMD_ERASE_WRITE:
+ case CMD_ERASE_WRITE_ALTERNATE:
+ case CMD_SNA_ERASE_WRITE:
+ case CMD_SNA_ERASE_WRITE_ALTERNATE:
+ {
+ int newlines, newcolumns;
+
+ SetOiaOnlineA(&OperatorInformationArea);
+ ResetOiaTWait(&OperatorInformationArea);
+ SetOiaModified();
+ if ((Command == CMD_ERASE_WRITE)
+ || (Command == CMD_SNA_ERASE_WRITE)) {
+ newlines = 24;
+ newcolumns = 80;
+ } else {
+ newlines = MaxNumberLines;
+ newcolumns = MaxNumberColumns;
+ }
+ if ((newlines != NumberLines)
+ || (newcolumns != NumberColumns)) {
+ /*
+ * The LocalClearScreen() is really for when we
+ * are going from a larger screen to a smaller
+ * screen, and we need to clear off the stuff
+ * at the end of the lines, or the lines at
+ * the end of the screen.
+ */
+ LocalClearScreen();
+ NumberLines = newlines;
+ NumberColumns = newcolumns;
+ ScreenSize = NumberLines * NumberColumns;
+ }
+ Clear3270();
+#if !defined(PURE3274)
+ if (TransparentClock == OutputClock) {
+ TransStop();
+ }
+#endif /* !defined(PURE3274) */
+ break;
+ }
+
+ case CMD_ERASE_ALL_UNPROTECTED:
+ case CMD_SNA_ERASE_ALL_UNPROTECTED:
+ SetOiaOnlineA(&OperatorInformationArea);
+ ResetOiaTWait(&OperatorInformationArea);
+ SetOiaModified();
+ CursorAddress = HighestScreen()+1;
+ for (i = LowestScreen(); i <= HighestScreen(); i = ScreenInc(i)) {
+ if (IsUnProtected(i)) {
+ if (CursorAddress > i) {
+ CursorAddress = i;
+ }
+ AddHost(i, '\0');
+ }
+ if (HasMdt(i)) {
+ TurnOffMdt(i);
+ }
+ }
+ if (CursorAddress == HighestScreen()+1) {
+ CursorAddress = SetBufferAddress(0,0);
+ }
+ UnLocked = 1;
+ AidByte = 0;
+ ResetOiaSystemLocked(&OperatorInformationArea);
+ SetOiaModified();
+ TerminalIn();
+ break;
+ case CMD_WRITE:
+ case CMD_SNA_WRITE:
+ SetOiaOnlineA(&OperatorInformationArea);
+ ResetOiaTWait(&OperatorInformationArea);
+ SetOiaModified();
+ break;
+ default:
+ {
+ char s_buffer[100];
+
+ sprintf(s_buffer,
+ "Unexpected write command code 0x%x received.\n",
+ Command);
+ ExitString(s_buffer, 1);
+ break;
+ }
+ }
+
+ count -= 2; /* strip off command and wcc */
+ buffer += 2;
+
+ } else {
+#if !defined(PURE3274)
+ if (TransparentClock == OutputClock) {
+ TransOut(buffer, count, -1, control);
+ count = 0;
+ }
+#endif /* !defined(PURE3274) */
+ }
+ LastWasTerminated = 0; /* then, reset at end... */
+
+ while (count) {
+ count--;
+ c = *buffer++;
+ if (IsOrder(c)) {
+ /* handle an order */
+ switch (c) {
+# define Ensure(x) if (count < x) { \
+ if (!control) { \
+ return(origCount-(count+1)); \
+ } else { \
+ /* XXX - should not occur */ \
+ count = 0; \
+ break; \
+ } \
+ }
+ case ORDER_SF:
+ Ensure(1);
+ c = *buffer++;
+ count--;
+ if ( ! (IsStartField(BufferAddress) &&
+ FieldAttributes(BufferAddress) == c)) {
+ SetHighestLowest(BufferAddress);
+ NewField(BufferAddress,c);
+ }
+ BufferAddress = ScreenInc(BufferAddress);
+ break;
+ case ORDER_SBA:
+ Ensure(2);
+ i = buffer[0];
+ c = buffer[1];
+#if !defined(PURE3274)
+ /* Check for transparent write */
+ if ((i == 0) && ((c == 0) || (c == 1) || (c == 5))) {
+ TransparentClock = OutputClock+1;
+ TransOut(buffer+2, count-2, c, control);
+ buffer += count;
+ count -= count;
+ break;
+ }
+#endif /* !defined(PURE3274) */
+ BufferAddress = Addr3270(i, c);
+ buffer += 2;
+ count -= 2;
+ break;
+ case ORDER_IC:
+ CursorAddress = BufferAddress;
+ break;
+ /*
+ * XXX - PT is supposed to null fill the screen buffer
+ * under certain draconian conditions.
+ */
+ case ORDER_PT:
+ i = BufferAddress;
+ do {
+ if (IsStartField(i)) {
+ if (!IsProtected(ScreenInc(i))) {
+ break;
+ }
+ }
+ i = ScreenInc(i);
+ } while (i != HighestScreen());
+ BufferAddress = ScreenInc(i);
+ break;
+ case ORDER_RA:
+ Ensure(3);
+ i = Addr3270(buffer[0], buffer[1]);
+ if ((i < 0) || (i > HighestScreen())) {
+ char s_buffer[200];
+
+ sprintf(s_buffer, "tn3270: %s%d.\n\t%s%d%s%d%s\n",
+ "Invalid 3270 order 'Repeat to Address' to address ",
+ i,
+ "(Screen currently set to ",
+ NumberLines,
+ " by ",
+ NumberColumns,
+ ".)");
+ ExitString(s_buffer, 1);
+ /*NOTREACHED*/
+ }
+ c = buffer[2];
+ if (c == ORDER_GE) {
+ Ensure(4);
+ c = buffer[3];
+ buffer += 4;
+ count -= 4;
+ } else {
+ buffer += 3;
+ count -= 3;
+ }
+ do {
+ AddHost(BufferAddress, ebc_disp[c]);
+ BufferAddress = ScreenInc(BufferAddress);
+ } while (BufferAddress != i);
+ break;
+ case ORDER_EUA: /* (from [here,there), ie: half open interval] */
+ Ensure(2);
+ /*
+ * Compiler error - msc version 4.0:
+ * "expression too complicated".
+ */
+ i = WhereAttrByte(BufferAddress);
+ c = FieldAttributes(i);
+ i = Addr3270(buffer[0], buffer[1]);
+ if ((i < 0) || (i > HighestScreen())) {
+ char s_buffer[200];
+
+ sprintf(s_buffer, "tn3270: %s%d.\n\t%s%d%s%d%s\n",
+ "Invalid 3270 order 'Erase Unprotected to Address' to address ",
+ i,
+ "(Screen currently set to ",
+ NumberLines,
+ " by ",
+ NumberColumns,
+ ".)");
+ ExitString(s_buffer, 1);
+ /*NOTREACHED*/
+ }
+ do {
+ if (IsStartField(BufferAddress)) {
+ c = FieldAttributes(BufferAddress);
+ } else if (!IsProtectedAttr(BufferAddress, c)) {
+ AddHost(BufferAddress, 0);
+ }
+ BufferAddress = ScreenInc(BufferAddress);
+ } while (i != BufferAddress);
+ buffer += 2;
+ count -= 2;
+ break;
+ case ORDER_GE:
+ Ensure(2);
+ /* XXX Should do SOMETHING! */
+ /* XXX buffer += 0; */
+ /* XXX count -= 0; *//* For now, just use this character */
+ break;
+ case ORDER_YALE: /* special YALE defined order */
+ Ensure(2); /* need at least two characters */
+ if (*buffer == 0x5b) {
+ i = OptOrder(buffer+1, count-1, control);
+ if (i == 0) {
+ return(origCount-(count+1)); /* come here again */
+ } else {
+ buffer += 1 + i;
+ count -= (1 + i);
+ }
+ }
+ break;
+ default:
+ {
+ char s_buffer[100];
+ static struct orders_def unk_order
+ = { 0, "??", "(unknown)" };
+ struct orders_def *porder = &unk_order;
+ int s_i;
+
+ for (s_i = 0; s_i <= highestof(orders_def); s_i++) {
+ if (orders_def[s_i].code == c) {
+ porder = &orders_def[s_i];
+ break;
+ }
+ }
+ sprintf(s_buffer,
+ "Unsupported order '%s' (%s, 0x%x) received.\n",
+ porder->long_name, porder->short_name, c);
+ ExitString(s_buffer, 1);
+ /*NOTREACHED*/
+ }
+ }
+ if (count < 0) {
+ count = 0;
+ }
+ } else {
+ /* Data comes in large clumps - take it all */
+ i = BufferAddress;
+ AddHostA(i, ebc_disp[c]);
+ SetHighestLowest(i);
+ i = ScreenInc(i);
+ c = *buffer;
+ while (count && !IsOrder(c)) {
+ AddHostA(i, ebc_disp[c]);
+ i = ScreenInc(i);
+ if (i == LowestScreen()) {
+ SetHighestLowest(HighestScreen());
+ }
+ count--;
+ buffer++;
+ c = *buffer;
+ }
+ SetHighestLowest(i);
+ BufferAddress = i;
+ }
+ }
+#if 0
+ if (count == 0) {
+#endif
+ if (control) {
+#if !defined(PURE3274)
+ OutputClock++; /* time rolls on */
+#endif /* !defined(PURE3274) */
+ if (Wcc & WCC_RESTORE) {
+#if !defined(PURE3274)
+ if (TransparentClock != OutputClock) {
+ AidByte = 0;
+ }
+#else /* !defined(PURE3274) */
+ AidByte = 0;
+#endif /* !defined(PURE3274) */
+ UnLocked = 1;
+ ResetOiaSystemLocked(&OperatorInformationArea);
+ SetOiaModified();
+ SetPsModified();
+ TerminalIn();
+ }
+ if (Wcc & WCC_ALARM) {
+ RingBell((char *)0);
+ }
+ }
+ LastWasTerminated = control; /* state for next time */
+ return(origCount);
+#if 0
+ } else {
+ return(origCount-count);
+ }
+#endif
+}
+
+/*
+ * Init3270()
+ *
+ * Initialize any 3270 (controller) variables to an initial state
+ * in preparation for accepting a connection.
+ */
+
+void
+Init3270()
+{
+ int i;
+
+ OptInit(); /* initialize mappings */
+
+ ClearArray(Host);
+
+ ClearArray(Orders);
+ for (i = 0; i <= highestof(orders_def); i++) {
+ Orders[orders_def[i].code] = 1;
+ }
+
+ DeleteAllFields(); /* Clear screen */
+ Lowest = HighestScreen()+1;
+ Highest = LowestScreen()-1;
+ CursorAddress = BufferAddress = SetBufferAddress(0,0);
+ UnLocked = 1;
+#if !defined(PURE3274)
+ OutputClock = 1;
+ TransparentClock = -1;
+#endif /* !defined(PURE3274) */
+ SetOiaReady3274(&OperatorInformationArea);
+}
+
+
+void
+Stop3270()
+{
+ ResetOiaReady3274(&OperatorInformationArea);
+}
diff --git a/comms/tn3270/files/ctlr/screen.h b/comms/tn3270/files/ctlr/screen.h
new file mode 100644
index 00000000000..935185c303a
--- /dev/null
+++ b/comms/tn3270/files/ctlr/screen.h
@@ -0,0 +1,141 @@
+/* $NetBSD: screen.h,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: screen.h,v 1.5 2003/08/07 11:16:32 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)screen.h 4.3 (Berkeley) 4/26/91
+ */
+
+#define INCLUDED_SCREEN
+
+/* defines and defines to describe how to deal with the screen */
+
+#if !defined(MSDOS)
+#define MAXNUMBERLINES 43 /* 3278-4 */
+#define MAXNUMBERCOLUMNS 132 /* 3278-5 */
+#define MAXSCREENSIZE 3564 /* (27*132) 3278-5 */
+#else /* !defined(MSDOS) */ /* MSDOS has memory constraints */
+#define MAXNUMBERLINES 25 /* XXX */
+#define MAXNUMBERCOLUMNS 80
+#define MAXSCREENSIZE (MAXNUMBERLINES*MAXNUMBERCOLUMNS)
+#endif /* !defined(MSDOS) */ /* MSDOS has memory constraints */
+#define LowestScreen() 0
+#define HighestScreen() (ScreenSize-1)
+
+#define ScreenLineOffset(x) ((x)%NumberColumns)
+#define ScreenLine(x) ((int)((x)/NumberColumns))
+#define ScreenInc(x) (((x)==HighestScreen())? LowestScreen():x+1)
+#define ScreenDec(x) (((x)==LowestScreen())? HighestScreen():x-1)
+#define ScreenUp(x) (((x)+(ScreenSize-NumberColumns))%ScreenSize)
+#define ScreenDown(x) (((x)+NumberColumns)%ScreenSize)
+#define IsOrder(x) (Orders[x])
+#define BAIC(x) ((x)&0x3f)
+#define CIAB(x) (CIABuffer[(x)&0x3f])
+#define BufferTo3270_0(x) (CIABuffer[(int)((x)/0x40)])
+#define BufferTo3270_1(x) (CIABuffer[(x)&0x3f])
+#define Addr3270(x,y) (BAIC(x)*64+BAIC(y))
+#define SetBufferAddress(x,y) ((x)*NumberColumns+(y))
+
+/* These know how fields are implemented... */
+
+#define WhereAttrByte(p) (IsStartField(p)? p: FieldDec(p))
+#define WhereHighByte(p) ScreenDec(FieldInc(p))
+#define WhereLowByte(p) ScreenInc(WhereAttrByte(p))
+#define FieldAttributes(x) (IsStartField(x)? GetHost(x) : \
+ GetHost(WhereAttrByte(x)))
+#define FieldAttributesPointer(p) (IsStartFieldPointer(p)? \
+ GetHostPointer(p): \
+ GetHost(WhereAttrByte((p)-&Host[0])))
+
+/*
+ * The MDT functions need to protect against the case where the screen
+ * is unformatted (sigh).
+ */
+
+/* Turn off the Modified Data Tag */
+#define TurnOffMdt(x) \
+ if (HasMdt(WhereAttrByte(x))) { \
+ ModifyMdt(x, 0); \
+ }
+
+/* Turn on the Modified Data Tag */
+#define TurnOnMdt(x) \
+ if (!HasMdt(WhereAttrByte(x))) { \
+ ModifyMdt(x, 1); \
+ }
+
+/* If this location has the MDT bit turned on (implies start of field) ... */
+#define HasMdt(x) \
+ ((GetHost(x)&(ATTR_MDT|ATTR_MASK)) == (ATTR_MDT|ATTR_MASK))
+
+ /*
+ * Is the screen formatted? Some algorithms change depending
+ * on whether there are any attribute bytes lying around.
+ */
+#define FormattedScreen() \
+ ((WhereAttrByte(0) != 0) || ((GetHost(0)&ATTR_MASK) == ATTR_MASK))
+
+ /* field starts here */
+#define IsStartField(x) ((GetHost(x)&ATTR_MASK) == ATTR_MASK)
+#define IsStartFieldPointer(p) ((GetHostPointer(p)&ATTR_MASK) == ATTR_MASK)
+
+#define NewField(p,a) SetHost(p, (a)|ATTR_MASK)
+#define DeleteField(p) SetHost(p, 0)
+#define DeleteAllFields()
+
+/* The following are independent of the implementation of fields */
+#define IsProtectedAttr(p,a) (IsStartField(p) || ((a)&ATTR_PROT))
+#define IsProtected(p) IsProtectedAttr(p,FieldAttributes(p))
+
+#define IsUnProtected(x) (!IsProtected(x))
+
+#define IsAutoSkip(x) (FieldAttributes(x)&ATTR_AUTO_SKIP)
+
+#define IsNonDisplayAttr(c) (((c)&ATTR_DSPD_MASK) == ATTR_DSPD_NONDISPLAY)
+#define IsNonDisplay(p) IsNonDisplayAttr(FieldAttributes(p))
+
+#define IsHighlightedAttr(c) \
+ (((c)&ATTR_DSPD_MASK) == ATTR_DSPD_HIGH)
+#define IsHighlighted(p) \
+ (IsHighlightedAttr(FieldAttributes(p)) && !IsStartField(p))
+
+typedef unsigned char ScreenImage;
+
+extern char
+ CIABuffer[];
+
+#define GetGeneric(i,h) (h)[i]
+#define GetGenericPointer(p) (*(p))
+#define SetGeneric(i,c,h) ((h)[i] = (c))
+#define ModifyGeneric(i,what,h) {(h)[i] what;}
+
+#define GetHost(i) GetGeneric(i,Host)
+#define GetHostPointer(p) GetGenericPointer(p)
+#define SetHost(i,c) SetGeneric(i,c,Host)
+#define ModifyHost(i,what) ModifyGeneric(i,what,Host)
diff --git a/comms/tn3270/files/ctlr/scrnctlr.h b/comms/tn3270/files/ctlr/scrnctlr.h
new file mode 100644
index 00000000000..c32f635c133
--- /dev/null
+++ b/comms/tn3270/files/ctlr/scrnctlr.h
@@ -0,0 +1,47 @@
+/* $NetBSD: scrnctlr.h,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: scrnctlr.h,v 1.5 2003/08/07 11:16:33 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)scrnctlr.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * definitions that have to do with the interface between the
+ * controller and the screen.
+ */
+
+#define DISP_AMPERSAND 0x30
+#define DISP_BLANK 0x10
+#define DISP_CENTSIGN 0x1b
+#define DISP_DUP 0x9f
+#define DISP_FM 0x9e
+#define DISP_GREATER_THAN 0x08
+#define DISP_NULL 0x00
+#define DISP_QUESTION 0x18
diff --git a/comms/tn3270/files/ctlr/unix.kbd b/comms/tn3270/files/ctlr/unix.kbd
new file mode 100644
index 00000000000..5d532ee26c6
--- /dev/null
+++ b/comms/tn3270/files/ctlr/unix.kbd
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)unix.kbd 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * keynumber [ scancode [ unshifted [ shifted [ alted [ shiftalted ] ] ] ] ]
+ *
+ * keynumber is in decimal, and starts in column 1.
+ * scancode is hexadecimal.
+ * unshifted, etc. - these are either a single ascii character,
+ * or the name of a function or an AID-generating key.
+ *
+ * all fields are separated by a single space.
+ */
+
+extern struct hits hits[];
+1 0e ` ~ LPRT
+2 16 1 ! XON
+3 1e 2 @ XOFF
+4 26 3 # ALTK
+5 25 4 $ ESCAPE
+6 2e 5 % DISC
+7 36 6 ^ MASTER_RESET
+8 3d 7 & RESHOW
+9 3e 8 * FLINP
+10 46 9 ( SYNCH
+11 45 0 ) INIT
+12 4e - _ PCOFF
+13 55 = + PCON
+14 5d APLON APLOFF APLEND
+15 66 LEFT
+16 0d TAB BTAB
+17 15 q Q FIELDEND
+18 1d w W WORDEND
+19 24 e E WORDBACKTAB
+20 2d r R FERASE
+21 2c t T WERASE
+22 35 y Y ERASE
+23 3c u U CLRTAB
+24 43 i I SETHOM
+25 44 o O SETMRG
+26 4d p P UNDENT
+27 54 [ { INDENT
+28 5b \ | SETTAB
+29 5c DELTAB COLTAB COLBAK
+30 14 CAPS_LOCK
+31 1c a A WORDTAB
+32 1b s S CURSEL
+33 23 d D VERTICAL_BAR
+34 2b f F CENTSIGN
+35 34 g G PF25
+36 33 h H PF26
+37 3b j J PF27
+38 42 k K PF28
+39 4b l L PF29
+40 4c ; : PF30
+41 52 ' " PF31
+42 53 ] } PF32
+43 5a NL
+44 12 MAKE_SHIFT MAKE_SHIFT MAKE_SHIFT
+45 13 < > PF33
+46 1a z Z PF34
+47 22 x X PF35
+48 21 c C PF36
+49 2a v V
+50 32 b B
+51 31 n N
+52 3a m M
+53 41 , <
+54 49 . >
+55 4a / ?
+56 51
+57 59 MAKE_SHIFT MAKE_SHIFT MAKE_SHIFT
+58 11 RESET NULL DVCNL
+59
+60 19 MAKE_ALT MAKE_ALT MAKE_ALT
+61 29 SPACE SPACE
+62 39 MAKE_ALT MAKE_ALT MAKE_ALT
+63
+64 58 ENTER
+65 06 CLEAR NULL TEST
+66 0c NULL NULL ATTN
+67 0b EEOF NULL EINP
+68 0a
+69 09 MAKE_CTRL
+70 05 ATTN NULL TREQ
+71 04
+72 03
+73 83
+74 01
+75 67 PA1 DP
+76 64 BTAB
+77
+78 61 LEFT NULL LEFT2
+79
+80 6e PA2 FM
+81 65 INSRT
+82 63 UP
+83 62 NULL NULL HOME
+84 60 DOWN
+85 6f PA3
+86 6d DELETE
+87
+88 6a RIGHT NULL RIGHT2
+89
+90 76
+91 6c 7
+92 6b 4
+93 69 1
+94 68
+95 77
+96 75 8
+97 73 5
+98 72 2
+99 70 0
+100 7e ,
+101 7d 9
+102 74 6
+103 7a 3
+104 71 .
+105 84 SPACE
+106 7c TAB
+107 7b -
+108 79 ENTER
+109 78
+110 07 PF1
+111 0f PF2
+112 17 PF3
+113 1f PF4
+114 27 PF5
+115 2f PF6
+116 37 PF7
+117 3f PF8 NULL MONOCASE
+118 47 PF9
+119 4f PF10
+120 56 PF11
+121 5e PF12
+122 08 PF13
+123 10 PF14
+124 18 PF15
+125 20 PF16
+126 28 PF17
+127 30 PF18
+128 38 PF19
+129 40 PF20
+130 48 PF21
+131 50 PF22
+132 57 PF23
+133 5f PF24
+134 92 BREAK_SHIFT BREAK_SHIFT BREAK_SHIFT
+135 D9 BREAK_SHIFT BREAK_SHIFT BREAK_SHIFT
+136 99 BREAK_ALT BREAK_ALT BREAK_ALT
+137 B9 BREAK_ALT BREAK_ALT BREAK_ALT
diff --git a/comms/tn3270/files/general/genbsubs.c b/comms/tn3270/files/general/genbsubs.c
new file mode 100644
index 00000000000..3aad3c0edcd
--- /dev/null
+++ b/comms/tn3270/files/general/genbsubs.c
@@ -0,0 +1,131 @@
+/* $NetBSD: genbsubs.c,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: genbsubs.c,v 1.6 2003/08/07 11:16:33 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)genbsubs.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: genbsubs.c,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "general.h"
+
+/* The output of bunequal is the offset of the byte which didn't match;
+ * if all the bytes match, then we return n.
+ * bunequal(s1, s2, n) */
+
+int
+bunequal(s1, s2, n)
+char *s1, *s2;
+int n;
+{
+ int i = 0;
+
+ while (i++ < n) {
+ if (*s1++ != *s2++) {
+ break;
+ }
+ }
+ return(i-1);
+}
+
+/* bskip(s1, n, b) : finds the first occurrence of any byte != 'b' in the 'n'
+ * bytes beginning at 's1'.
+ */
+
+int
+bskip(s1, n, b)
+char *s1;
+int n;
+int b;
+{
+ int i = 0;
+
+ while (i++ < n) {
+ if (*s1++ != b) {
+ break;
+ }
+ }
+ return(i-1);
+}
+
+/*
+ * memNSchr(const void *s, int c, size_t n, int and)
+ *
+ * Like memchr, but the comparison is '((*s)&and) == c',
+ * and we increment our way through s by "stride" ('s += stride').
+ *
+ * We optimize for the most used strides of +1 and -1.
+ */
+
+unsigned char *
+memNSchr(s, c, n, and, stride)
+char *s;
+int c;
+unsigned int n;
+int and;
+ssize_t stride;
+{
+ unsigned char _c, *_s, _and;
+
+ _and = and;
+ _c = (c&_and);
+ _s = (unsigned char *)s;
+ switch (stride) {
+ case 1:
+ while (n--) {
+ if (((*_s)&_and) == _c) {
+ return _s;
+ }
+ _s++;
+ }
+ break;
+ case -1:
+ while (n--) {
+ if (((*_s)&_and) == _c) {
+ return _s;
+ }
+ _s--;
+ }
+ break;
+ default:
+ while (n--) {
+ if (((*_s)&_and) == _c) {
+ return _s;
+ }
+ _s += stride;
+ }
+ }
+ return 0;
+}
diff --git a/comms/tn3270/files/general/general.h b/comms/tn3270/files/general/general.h
new file mode 100644
index 00000000000..5961b9ff6ef
--- /dev/null
+++ b/comms/tn3270/files/general/general.h
@@ -0,0 +1,52 @@
+/* $NetBSD: general.h,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: general.h,v 1.10 2003/08/07 11:16:34 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)general.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Some general definitions.
+ */
+
+#include <sys/types.h>
+
+#define numberof(x) (sizeof x/sizeof x[0])
+#define highestof(x) (numberof(x)-1)
+
+#define ClearElement(x) memset((char *)&x, 0, sizeof x)
+#define ClearArray(x) memset((char *)x, 0, sizeof x)
+
+#include <string.h>
+
+/* genbsubs.c */
+int bunequal(char *, char *, int);
+int bskip(char *, int, int);
+unsigned char *memNSchr(char *, int, unsigned int, int, ssize_t);
diff --git a/comms/tn3270/files/general/general.order b/comms/tn3270/files/general/general.order
new file mode 100644
index 00000000000..6f4d233b010
--- /dev/null
+++ b/comms/tn3270/files/general/general.order
@@ -0,0 +1,2 @@
+globals.o
+genbsubs.o
diff --git a/comms/tn3270/files/general/globals.c b/comms/tn3270/files/general/globals.c
new file mode 100644
index 00000000000..4346a92ca97
--- /dev/null
+++ b/comms/tn3270/files/general/globals.c
@@ -0,0 +1,78 @@
+/* $NetBSD: globals.c,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: globals.c,v 1.5 2003/08/07 11:16:34 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)globals.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: globals.c,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * Do the defining instances for the globals of tn3270.
+ */
+
+#include "../ctlr/hostctlr.h"
+#include "../ctlr/oia.h"
+#include "../ctlr/options.h"
+#include "../ctlr/screen.h"
+
+
+#define DEFINING_INSTANCES
+
+#include "globals.h"
+
+#include "../general/general.h"
+
+/*
+ * init_system()
+ *
+ * Initialize the global values in case of a restart.
+ */
+
+void
+init_system()
+{
+ OptHome = OptLeftMargin = OptAPLmode = OptNullProcessing = 0;
+ OptZonesMode = OptEnterNL = OptColFieldTab = OptPacing = 0;
+ OptAlphaInNumeric = OptHome = OptLeftMargin = OptWordWrap = 0;
+
+ ClearArray(Host);
+ CursorAddress = BufferAddress = 0;
+
+ Lowest = Highest = 0;
+
+ UnLocked = AidByte = 0;
+
+}
diff --git a/comms/tn3270/files/general/globals.h b/comms/tn3270/files/general/globals.h
new file mode 100644
index 00000000000..4b17fdda8b8
--- /dev/null
+++ b/comms/tn3270/files/general/globals.h
@@ -0,0 +1,131 @@
+/* $NetBSD: globals.h,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: globals.h,v 1.6 2003/08/07 11:16:34 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)globals.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * This file contains all the globals used by tn3270.
+ *
+ * Since various files may want to reference this file,
+ * and since they may only want subsets of the globals,
+ * we assume they have #include'd all the other .h files
+ * first, and we only give those globals relevant to
+ * the #include'd .h files.
+ *
+ */
+
+#if defined(DEFINING_INSTANCES)
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+
+EXTERN int
+ /*
+ * shell_active ==>
+ * 1. Don't do input.
+ * 2. Don't do output.
+ * 3. Don't block in select.
+ * 4. When nothing to do, call shell_continue()
+ */
+ shell_active;
+
+
+#if defined(INCLUDED_OPTIONS)
+EXTERN int OptHome; /* where home should send us */
+
+EXTERN int OptLeftMargin; /* where new line should send us */
+
+EXTERN char OptColTabs[80]; /* local tab stops */
+
+EXTERN int OptAPLmode;
+
+EXTERN int OptNullProcessing; /* improved null processing */
+
+EXTERN int OptZonesMode; /* zones mode off */
+
+EXTERN int OptEnterNL; /* regular enter/new line keys */
+
+EXTERN int OptColFieldTab; /* regular column/field tab keys */
+
+EXTERN int OptPacing; /* do pacing */
+
+EXTERN int OptAlphaInNumeric; /* allow alpha in numeric fields */
+
+EXTERN int OptHome;
+
+EXTERN int OptLeftMargin;
+
+EXTERN int OptWordWrap;
+#endif
+
+#if defined(INCLUDED_SCREEN)
+EXTERN ScreenImage
+ Host[MAXSCREENSIZE]; /* host view of screen */
+
+EXTERN char Orders[256]; /* Non-zero for orders */
+
+ /* Run-time screen geometry */
+EXTERN int
+ MaxNumberLines, /* How many rows the 3270 COULD have */
+ MaxNumberColumns, /* How many columns the 3270 COULD have */
+ NumberLines, /* How many lines the 3270 screen contains */
+ NumberColumns, /* How many columns the 3270 screen contains */
+ ScreenSize;
+
+EXTERN int CursorAddress; /* where cursor is */
+EXTERN int BufferAddress; /* where writes are going */
+
+EXTERN int Lowest, Highest;
+
+extern char CIABuffer[];
+
+EXTERN int UnLocked; /* is the keyboard unlocked */
+EXTERN int AidByte;
+
+#endif
+
+#if defined(INCLUDED_STATE)
+#endif
+
+void init_system(void);
+
+#if defined(INCLUDED_OIA)
+
+EXTERN OIA OperatorInformationArea;
+
+EXTERN int
+ oia_modified, /* Has the oia been modified */
+ ps_modified; /* Has the presentation space been modified */
+
+#endif /* defined(INCLUDED_OIA) */
diff --git a/comms/tn3270/files/general/vaxbsubs.s b/comms/tn3270/files/general/vaxbsubs.s
new file mode 100644
index 00000000000..f71a49e04d6
--- /dev/null
+++ b/comms/tn3270/files/general/vaxbsubs.s
@@ -0,0 +1,101 @@
+/* $NetBSD: vaxbsubs.s,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $ */
+/* From NetBSD: vaxbsubs.s,v 1.4 2003/08/07 11:16:34 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)vaxbsubs.s 4.2 (Berkeley) 4/26/91
+ * $NetBSD: vaxbsubs.s,v 1.1.1.1 2010/01/17 01:33:22 dholland Exp $
+ */
+
+/* This is taken from bcmp.s from 4.2.
+ * The output of bunequal is the offset of the byte which didn't match;
+ * if all the bytes match, then we return n.
+ *
+ * BUGNOTE: This has no chance of working for lengths greater than 64K.
+ * (so, if you use this somewhere else, you may need to
+ * fix it...)
+ */
+
+/* bunequal(s1, s2, n) */
+
+#include "defs.h"
+
+ENTRY(bunequal)
+ movl 4(ap),r1
+ movl 8(ap),r3
+ movl 12(ap),r4
+1:
+ movzwl $65535,r0
+ cmpl r4,r0
+ jleq 2f
+ subl2 r0,r4
+ cmpc3 r0,(r1),(r3)
+ jeql 1b
+ addl2 r4,r0
+ /* changes... */
+ subl3 r0,12(ap),r0
+ /* end of changes for bunequal... */
+ ret
+2:
+ cmpc3 r4,(r1),(r3)
+ /* changes... */
+ subl3 r0,12(ap),r0
+ /* end of changes for bunequal... */
+ ret
+
+
+
+
+/* brand new code, using the above as base... */
+/* bskip(s1, n, b) : finds the first occurrence of any byte != 'b' in the 'n'
+ * bytes beginning at 's1'.
+ *
+ * BUGNOTE: This has no chance of working for lengths greater than 64K.
+ * (so, if you use this somewhere else, you may need to
+ * fix it...)
+ */
+
+ENTRY(bskip)
+ movl 4(ap),r1
+ movl 8(ap),r3
+ movl 12(ap),r4
+1:
+ movzwl $65535,r0
+ cmpl r3,r0
+ jleq 2f
+ subl2 r0,r3
+ skpc r4,r0,(r1)
+ jeql 1b
+ addl2 r3,r0
+ subl3 r0,8(ap),r0
+ ret
+2:
+ skpc r4,r3,(r1)
+ subl3 r0,8(ap),r0
+ ret
diff --git a/comms/tn3270/files/mset/Makefile b/comms/tn3270/files/mset/Makefile
new file mode 100644
index 00000000000..8982674eb58
--- /dev/null
+++ b/comms/tn3270/files/mset/Makefile
@@ -0,0 +1,30 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:23 dholland Exp $
+# From NetBSD: Makefile,v 1.26 2003/10/21 10:01:22 lukem Exp
+
+.include <bsd.own.mk>
+
+PROG= mset
+MAN= mset.1 map3270.5
+SRCS= astosc.c map3270.c mset.c
+DPSRCS= astosc.out
+
+MKASTOSCDIR!=cd $(.CURDIR)/../tools/mkastosc && ${PRINTOBJDIR}
+MKASTOSC=${MKASTOSCDIR}/mkastosc
+
+${MKASTOSC}:
+ @cd ${.CURDIR}/../tools/mkastosc && ${MAKE}
+
+CLEANFILES+= astosc.out
+astosc.out: ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h \
+ ${.CURDIR}/../ctlr/${KBD} ${MKASTOSC}
+ ${_MKTARGET_CREATE}
+ ${MKASTOSC} \
+ ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h \
+ < ${.CURDIR}/../ctlr/${KBD} > tmp
+ mv -f tmp ${.TARGET}
+
+.include <bsd.prog.mk>
+
+.PATH: ${.CURDIR}/../api ${.CURDIR}/../ascii
+
+astosc.o: astosc.out
diff --git a/comms/tn3270/files/mset/map3270 b/comms/tn3270/files/mset/map3270
new file mode 100644
index 00000000000..0263798792d
--- /dev/null
+++ b/comms/tn3270/files/mset/map3270
@@ -0,0 +1,1028 @@
+# $NetBSD: map3270,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $
+# From NetBSD: map3270,v 1.4 1999/09/06 20:28:20 perry Exp
+#
+# Copyright (c) 1989, 1993
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by the University of
+# California, Berkeley and its contributors.
+# 4. Neither the name of the University nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# @(#)map3270 8.2 (Berkeley) 4/1/94
+#
+
+# This file contains mappings between characters entered from the keyboard,
+# and 3270 keys, for use by programs (like tn3270) doing 3270 emulation
+# from unix.
+#
+# Inside the single quotes, a caret ("^") introduces a control character
+# sequence (rub out = ^?, by the way). Also inside the single quotes,
+# a backslash ('\') introduces an escaped character. Also, \n, \r, \t,
+# are all as in C, and \E is another way of representing escape.
+#
+# NOTE that while we are defining lots of function, much of that
+# function (ie: local editing keys) may not yet be available from tn3270.
+#
+# Please e-mail changes to termcap@berkeley.edu or uunet!ucbvax!termcap.
+#
+
+3a | adm3a {
+ enter = '^m';
+ clear = '^z';
+
+ nl = '^n';
+ tab = '^i';
+ btab = '^b' | '\E^i';
+ left = '^h';
+ right = '^l';
+ up = '^k';
+ down = '^j';
+ home = '^@';
+
+ delete = '^d' | '^?'; # rubout
+ eeof = '^e';
+ einp = '^w';
+ insrt = '\E ';
+ dp = '^u';
+ fm = '^y';
+
+ # pf keys
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4';
+ pfk5 = '\E5'; pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8';
+ pfk9 = '\E9'; pfk10 = '\E0'; pfk11 = '\E:'; pfk12 = '\E-';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+ # program attention keys
+ pa1 = '^p1';
+ pa2 = '^p2';
+ pa3 = '^p3';
+
+ # other keys
+ cursel = '\E.';
+ centsign = '^\';
+
+ # local control keys
+
+ reset = '^t'; # well, there is a little confusion here...
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^v'; # redisplay screen
+ escape = '^c'; # escape to telnet command mode
+
+ # local editing keys
+ settab = '\E;';
+ deltab = '\E\'';
+ clrtab = '\E+';
+ setmrg = '\E(';
+ sethom = '\E!';
+ coltab = '\Ei';
+ colbak = '\Eb';
+ indent = '\El';
+ undent = '\Eh';
+
+} # end of adm3a
+
+920c | tvi920c | 920b { # tvi920c definitions...
+
+ # command keys
+ enter = '^m';
+ clear = '^z';
+
+ # cursor movement keys
+ nl = '^^' | '^n'; # home
+ tab = '^i';
+ btab = '^b' | '\E^i';
+ left = '^h';
+ right = '^l';
+ up = '^k';
+ down = '^j';
+ home = '^@';
+
+ # edit control keys
+ delete = '^?' | '^d'; # delete
+ eeof = '^e';
+ einp = '^w';
+ insrt = '\E ';
+ dp = '^u';
+ fm = '^y';
+
+ # program function keys
+
+ # F1 to F11
+ pfk1 = '^a@^m'; pfk2 = '^aA^m'; pfk3 = '^aB^m'; pfk4 = '^aC^m';
+ pfk5 = '^aD^m'; pfk6 = '^aE^m'; pfk7 = '^aF^m'; pfk8 = '^aG^m';
+ pfk9 = '^aH^m'; pfk10 = '^aI^m'; pfk11 = '^aJ^m';
+
+ # SHIFT-F11
+ pfk12 = '^aj^m';
+
+ # ESC F1 to ESC F11
+ pfk11 = '\E^a@^m'; pfk12 = '\E^aA^m';
+ pfk13 = '\E^aB^m'; pfk14 = '\E^aC^m'; pfk15 = '\E^aD^m'; pfk16 = '\E^aE^m';
+ pfk17 = '\E^aF^m'; pfk18 = '\E^aG^m'; pfk19 = '\E^aH^m'; pfk20 = '\E^aI^m';
+ pfk21 = '\E^a`^m';
+
+ # ESC SHIFT-F1 to ESC SHIFT-F4
+ pfk21 = '\E^a`^m'; pfk22 = '\E^aa^m'; pfk23 = '\E^ab^m'; pfk24 = '\E^ac^m';
+
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4';
+ pfk5 = '\E5'; pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8';
+ pfk9 = '\E9'; pfk10 = '\E0'; pfk11 = '\E-'; pfk12 = '\E=';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+ # program attention keys
+
+ pa1 = '^a`^m' | '^p1';
+ pa2 = '^aa^m' | '^p2';
+ pa3 = '^ab^m' | '^p3';
+
+ # miscellaneous 3270 keys
+
+ cursel = '\E.';
+ centsign = '^\';
+
+ # local control keys
+
+ reset = '^t'; # there is some confusion here...
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^v';
+ escape = '^c'; # escape to telnet command mode
+
+ # local editing keys
+
+ settab = '\E;';
+ deltab = '\E\'';
+ clrtab = '\E:';
+ setmrg = '\E*';
+ sethom = '\E!';
+ coltab = '\Ei' | '\EI';
+ colbak = '\Eb' | '\EB';
+ indent = '\El' | '\EL';
+ undent = '\Eh' | '\EH';
+} # end of tvi920c table...
+
+925 | tvi925 | 925vb | tvi925vb | televideo 925 {
+
+ # command keys
+
+ enter = '^m';
+ clear = '^z';
+
+ # cursor movement keys
+
+ nl = '^j' | '^n';
+ tab = '^i';
+ btab = '\EI';
+ left = '^h';
+ right = '^l';
+ up = '^k';
+ down = '^v';
+ home = '^^';
+
+ # edit control keys
+
+ delete = '^?'; # that's rubout...
+ eeof = '^e';
+ einp = '^w';
+ insrt = '\E ' | '\EW';
+
+ # program function keys
+
+ pfk1 = '^a@^m';
+ pfk2 = '^aA^m';
+ pfk3 = '^aB^m';
+ pfk4 = '^aC^m';
+ pfk5 = '^aD^m';
+ pfk6 = '^aE^m';
+ pfk7 = '^aF^m';
+ pfk8 = '^aG^m';
+ pfk9 = '^aH^m';
+ pfk10 = '^aI^m';
+ pfk11 = '^aJ^m';
+ pfk12 = '\EQ';
+ pfk13 = '\E^a@^m';
+ pfk14 = '\E^aA^m';
+ pfk15 = '\E^aB^m';
+ pfk16 = '\E^aC^m';
+ pfk17 = '\E^aD^m';
+ pfk18 = '\E^aE^m';
+ pfk19 = '\E^aF^m';
+ pfk20 = '\E^aG^m';
+ pfk21 = '\E^aH^m';
+ pfk22 = '\E^aI^m';
+ pfk23 = '\E^aJ^m';
+ pfk24 = '\E\EQ';
+
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4';
+ pfk5 = '\E5'; pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8';
+ pfk9 = '\E9'; pfk10 = '\E0'; pfk11 = '\E-'; pfk12 = '\E=';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+ # program attention keys
+
+ pa1 = '^a`^m';
+ pa2 = '^aa^m';
+ pa3 = '^ab^m';
+
+ # other keys
+ centsign = '^\';
+
+ # local control keys
+
+ reset = '^t'; # again, there is some confusion here...
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^b';
+ escape = '^c'; # escape to telnet command mode
+
+# local editing keys
+
+ settab = '\EY';
+ deltab = '\Ey';
+ clrtab = '\E:';
+ setmrg = '\ET';
+ sethom = '\Et';
+ coltab = '^p';
+ colbak = '^o';
+ indent = '\ER';
+ undent = '\EE';
+}
+
+
+924 | tvi924 {
+
+ # command keys
+
+ enter = '^m';
+ clear = '^z';
+
+ # cursor movement keys
+
+ nl = '^j';
+ tab = '^i';
+ btab = '\EI';
+ left = '^h';
+ right = '^l';
+ up = '^k';
+ down = '^v';
+ home = '^^';
+
+ # edit control keys
+
+ delete = '^?'; # that's rubout...
+ eeof = '^e';
+ einp = '^w';
+ insrt = '\E ' | '\EW';
+ dp = '^u';
+ fm = '^y';
+
+ # program function keys
+
+ pfk1 = '^a@^m';
+ pfk2 = '^aA^m';
+ pfk3 = '^aB^m';
+ pfk4 = '^aC^m';
+ pfk5 = '^aD^m';
+ pfk6 = '^aE^m';
+ pfk7 = '^aF^m';
+ pfk8 = '^aG^m';
+ pfk9 = '^aH^m';
+ pfk10 = '^aI^m';
+ pfk11 = '^aJ^m';
+ pfk12 = '^aK^m';
+ pfk13 = '^aL^m';
+ pfk14 = '^aM^m';
+ pfk15 = '^aN^m';
+ pfk16 = '^aO^m';
+ pfk17 = '^af^m';
+ pfk18 = '^ag^m';
+ pfk19 = '^ah^m';
+ pfk20 = '^ai^m';
+ pfk21 = '^aj^m';
+ pfk22 = '^ak^m';
+ pfk23 = '^al^m';
+ pfk24 = '^am^m';
+
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4';
+ pfk5 = '\E5'; pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8';
+ pfk9 = '\E9'; pfk10 = '\E0'; pfk11 = '\E-'; pfk12 = '\E=';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+ # program attention keys
+
+ pa1 = '^a`^m';
+ pa2 = '^aa^m';
+ pa3 = '^ab^m';
+
+ # other keys
+ centsign = '^\';
+
+ # local control keys
+
+ reset = '^t'; # again, there is some confusion here...
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^b';
+ escape = '^c'; # escape to telnet command mode
+
+ # local editing keys
+
+ settab = '\EY';
+ deltab = '\Ey';
+ clrtab = '\E:';
+ setmrg = '\ET';
+ sethom = '\Et';
+ coltab = '^p';
+ colbak = '^o';
+ indent = '\ER';
+ undent = '\EE';
+}
+
+h19 | heath | h19b | heathkit | heath-19 | z19 | zenith {
+enter = '^m';
+clear = '^z';
+
+nl = '^n' | '^?';
+tab = '^i';
+btab = '^b';
+left = '^h';
+right = '^l';
+up = '^k';
+down = '^j';
+home = '^@';
+
+delete = '^d';
+eeof = '^e';
+einp = '^w';
+insrt = '\E ';
+
+# pf keys
+pfk1 = '\E?p\E?q'; pfk2 = '\E?p\E?r'; pfk3 = '\E?p\E?s'; pfk4 = '\E?p\E?t';
+pfk5 = '\E?p\E?u'; pfk6 = '\E?p\E?v'; pfk7 = '\E?p\E?w'; pfk8 = '\E?p\E?x';
+pfk9 = '\E?p\E?y'; pfk10 = '\E?q\E?p'; pfk11 = '\E?q\E?q'; pfk12 = '\E?q\E?r';
+pfk13 = '\E?q\E?s'; pfk14 = '\E?q\E?t'; pfk15 = '\E?q\E?u'; pfk16 = '\E?q\E?v';
+pfk17 = '\E?q\E?w'; pfk18 = '\E?q\E?x'; pfk19 = '\E?q\E?y'; pfk20 = '\E?r\E?p';
+pfk21 = '\E?r\E?q'; pfk22 = '\E?r\E?r'; pfk23 = '\E?r\E?s'; pfk24 = '\E?r\E?t';
+
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4';
+ pfk5 = '\E5'; pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8';
+ pfk9 = '\E9'; pfk10 = '\E0'; pfk11 = '\E-'; pfk12 = '\E=';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+# program attention keys
+pa1 = '\EP';
+pa2 = '\EQ';
+pa3 = '\ER';
+
+# other keys
+
+ centsign = '^\';
+# cursel = '\E.'; # find out what this does
+master_reset = '^g';
+
+# local control keys
+
+reset = '^t'; # well, there is a little confusion here...
+flinp = '^x';
+reshow = '^v'; # redisplay screen
+escape = '^c'; # escape to telnet command mode
+
+# local editing keys
+settab = '\E;';
+clrtab = '\E:';
+setmrg = '\E\'';
+sethom = '\E!';
+coltab = '\Ei';
+colbak = '\Eb';
+indent = '\El';
+undent = '\Eh';
+
+} # end of h19
+
+
+co | c100 | concept | c100-4p | concept100 {
+enter = '^m';
+clear = '^z' | '^\2';
+
+nl = '^n';
+tab = '^i';
+btab = '^b';
+left = '^h' | '\E>';
+right = '^l' | '\E=';
+up = '^k' | '\E;';
+down = '^j' | '\E<';
+home = '\E?';
+
+delete = '^d' | '^?' | '^\1';
+eeof = '^e' | '^\3';
+einp = '^w';
+insrt = '^\0';
+
+# pf keys
+pfk1 = '\E\E1' | '^\5'; pfk2 = '\E\E2' | '^\6'; pfk3 = '\E\E3' | '^\7';
+pfk4 = '\E\E4' | '^\8'; pfk5 = '\E\E5' | '^\9'; pfk6 = '\E\E6' | '^\:';
+pfk7 = '\E\E7' | '^\;'; pfk8 = '\E\E8' | '^\<'; pfk9 = '\E\E9' | '^\=';
+pfk10 = '\E\E0' | '^\>'; pfk11 = '\E\E-' | '^\?'; pfk12 = '^\@';
+pfk13 = '^\A'; pfk14 = '^\B'; pfk15 = '^\)'; pfk16 = '^\*';
+pfk17 = '^\+'; pfk18 = '^\,'; pfk19 = '^\-'; pfk20 = '^\.';
+pfk21 = '^\/'; pfk22 = '^\C'; pfk23 = '^\D'; pfk24 = '^\E';
+
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4';
+ pfk5 = '\E5'; pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8';
+ pfk9 = '\E9'; pfk10 = '\E0'; pfk11 = '\E-'; pfk12 = '^f12';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+# program attention keys
+pa1 = '^\%';
+pa2 = '^\&' | '\E+';
+pa3 = '^\\'';
+
+# other keys
+cursel = '\E.';
+aplon = '\E{';
+aplend = '\E}';
+aploff = '\E_';
+master_reset = '^g';
+centsign = '\E\\';
+
+# local control keys
+
+reset = '^t'; # well, there is a little confusion here...
+flinp = '^x';
+reshow = '^v'; # redisplay screen
+escape = '^c'; # escape to telnet command mode
+
+# local editing keys
+settab = '\E\E;';
+clrtab = '\E\E:';
+setmrg = '\E\E*';
+sethom = '\E\E!';
+coltab = '\E\Ei';
+colbak = '\E\Eb';
+indent = '\E\El';
+undent = '\E\Eh';
+
+} # end of concept
+avt | avt-8p-s | avt-4p-s | avt-rv {
+enter = '^m';
+clear = '^z' | '\EOM';
+
+nl = '^?';
+tab = '^i';
+btab = '^b';
+left = '^h' | '\E[D';
+right = '^l' | '\E[C';
+up = '^k' | '\E[A';
+down = '^j' | '\E[B';
+home = '\EOn';
+
+delete = '^d';
+eeof = '^e';
+einp = '^w';
+insrt = '^ ' | '\E ';
+
+# pf keys
+pfk1 = '\EOq' | '\E1'; pfk2 = '\EOr' | '\E2'; pfk3 = '\EOs' | '\E3';
+pfk4 = '\EOt' | '\E4'; pfk5 = '\EOu' | '\E5'; pfk6 = '\EOv' | '\E6';
+pfk7 = '\EOw' | '\E7'; pfk8 = '\EOx' | '\E8'; pfk9 = '\EOy' | '\E9';
+pfk10 = '\EOP\EOp' | '\E0'; pfk11 = '\EOP\EOq' | '\E-';
+pfk12 = '\EOP\EOr' | '\E='; pfk13 = '\EOP\EOs' | '^f13';
+pfk14 = '\EOP\EOt' | '^f14'; pfk15 = '\EOP\EOu' | '^f15';
+pfk16 = '\EOP\EOv' | '^f16'; pfk17 = '\EOP\EOw' | '^f17';
+pfk18 = '\EOP\EOx' | '^f18'; pfk19 = '\EOP\EOy' | '^f19';
+pfk20 = '\EOQ\EOp' | '^f20'; pfk21 = '\EOQ\EOq' | '^f21';
+
+ pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+# program attention keys
+pa1 = '\E\EOP' | '^p1';
+pa2 = '\E\EOQ' | '^p2';
+
+# local control keys
+
+escape = '^c'; # escape to telnet command mode
+master_reset = '^g';
+ centsign = '^\';
+
+# local editing keys
+settab = '\E;';
+deltab = '\E\'';
+clrtab = '\E:';
+setmrg = '\E,';
+sethom = '\E.';
+coltab = '\E\E[B';
+colbak = '\E\E[A';
+indent = '\E\E[C';
+undent = '\E\E[D';
+} # end of avt, etc.
+
+tvipt | vp | televideopt {
+ enter = '^m';
+ clear = '^z';
+
+ nl = '^n';
+ tab = '^i';
+ btab = '^b';
+ left = '^h';
+ right = '^l';
+ up = '^k';
+ down = '^j';
+ home = '^^';
+
+ delete = '^?';
+ eeof = '^e';
+ einp = '^w';
+ insrt = '\E ';
+
+ # pf keys
+ pfk1 = '\E1' | '^A@^m';
+ pfk2 = '\E2' | '^AA^m';
+ pfk3 = '\E3' | '^AB^m';
+ pfk4 = '\E4' | '^AC^m';
+ pfk5 = '\E5' | '^AD^m';
+ pfk6 = '\E6' | '^AE^m';
+ pfk7 = '\E7' | '^AF^m';
+ pfk8 = '\E8';
+ pfk9 = '\E9';
+ pfk10 = '\E0';
+ pfk11 = '\E!' | '\E^A@^m';
+ pfk12 = '\E@' | '\E^AA^m';
+ pfk13 = '\E#' | '\E^AB^m';
+ pfk14 = '\E$' | '\E^AC^m';
+ pfk15 = '\E%' | '\E^AD^m';
+ pfk16 = '\E^AE^m' | '\E\^';
+ pfk17 = '\E&' | '\E^AF^m';
+ pfk18 = '\E*';
+ pfk19 = '\E(';
+ pfk20 = '\E)';
+
+ # program attention keys
+ pa1 = '^AG^m';
+ pa2 = '^AH^m';
+ pa3 = '^AI^m';
+
+ # other keys
+# # cursel = '\E.';
+ centsign = '^\';
+
+ # local control keys
+
+ reset = '^t'; # well, there is a little confusion here...
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^v'; # redisplay screen
+ escape = '^c'; # escape to telnet command mode
+
+ # local editing keys
+ settab = '\E;';
+ clrtab = '\E:';
+ setmrg = '\E[';
+ sethom = '\E+';
+ coltab = '\Ei' | '\EI';
+ colbak = '\Eb' | '\EB';
+ indent = '\El' | '\EL';
+ undent = '\Eh' | '\EH';
+} # end of tvipt
+vt100 | vt100nam | pt100 | vt125 | vt102 | direct831 | tek4125 | pcplot | microvax | vt220 | vt320 | xterm{
+enter = '^m';
+clear = '^z' | '\EOM';
+
+nl = '^j';
+tab = '^i';
+btab = '^b';
+left = '^h' | '\E[D' | '\EOD';
+right = '^l' | '\E[C' | '\EOC';
+up = '^k' | '\E[A' | '\EOA';
+down = '\E[B' | '\EOB';
+home = '\EOn';
+
+delete = '^d' | '^?';
+eeof = '^e';
+einp = '^w';
+insrt = '^ ' | '\E ';
+
+# pf keys
+pfk1 = '\EOq' | '\E1'; pfk2 = '\EOr' | '\E2'; pfk3 = '\EOs' | '\E3';
+pfk4 = '\EOt' | '\E4'; pfk5 = '\EOu' | '\E5'; pfk6 = '\EOv' | '\E6';
+pfk7 = '\EOw' | '\E7'; pfk8 = '\EOx' | '\E8'; pfk9 = '\EOy' | '\E9';
+pfk10 = '\EOP\EOp' | '\E0'; pfk11 = '\EOP\EOq' | '\E-';
+pfk12 = '\EOP\EOr' | '\E='; pfk13 = '\EOP\EOs' | '^f13';
+pfk14 = '\EOP\EOt' | '^f14'; pfk15 = '\EOP\EOu' | '^f15';
+pfk16 = '\EOP\EOv' | '^f16'; pfk17 = '\EOP\EOw' | '^f17';
+pfk18 = '\EOP\EOx' | '^f18'; pfk19 = '\EOP\EOy' | '^f19';
+pfk20 = '\EOQ\EOp' | '^f20'; pfk21 = '\EOQ\EOq' | '^f21';
+
+# program attention keys
+pa1 = '\E\EOP' | '^p1';
+pa2 = '\E\EOQ' | '^p2';
+
+# local control keys
+
+escape = '^c'; # escape to telnet command mode
+master_reset = '^g';
+ centsign = '^\';
+
+# local editing keys
+settab = '\E;';
+deltab = '\E\'';
+clrtab = '\E:';
+setmrg = '\E,';
+sethom = '\E.';
+coltab = '\E\E[B';
+colbak = '\E\E[A';
+indent = '\E\E[C';
+undent = '\E\E[D';
+} # end of vt100, etc.
+
+sun {
+ enter = '^m';
+ clear = '^z' | '\E[222z';
+
+ nl = '^j';
+ tab = '^i';
+ btab = '^b' | '\E[195z' | '\E[216z';
+ left = '^h' | '\E[D' | '\EOD';
+ right = '^l' | '\E[C' | '\EOC';
+ up = '^k' | '\E[A' | '\EOA';
+ down = '\E[B' | '\EOB';
+ home = '\E[218z';
+
+ delete = '^d' | '^?';
+ eeof = '^e' | '\E[214z';
+ einp = '^w' | '\E[213z';
+ insrt = '\E ' | '\E[220z';
+ dp = '^u';
+ fm = '^y';
+
+ # pf keys
+ pfk1 = '\E[224z' | '\E1'; pfk2 = '\E[225z' | '\E2';
+ pfk3 = '\E[226z' | '\E3'; pfk4 = '\E[227z' | '\E4';
+ pfk5 = '\E[228z' | '\E5'; pfk6 = '\E[229z' | '\E6';
+ pfk7 = '\E[230z' | '\E7'; pfk8 = '\E[231z' | '\E8';
+ pfk9 = '\E[232z' | '\E9'; pfk10 = '\E[208z' | '\E0';
+ pfk11 = '\E[209z' | '\E-'; pfk12 = '\E[210z' | '\E=';
+ pfk13 = '^f13'; pfk14 = '^f14'; pfk15 = '^f15'; pfk16 = '^f16';
+ pfk17 = '^f17'; pfk18 = '^f18'; pfk19 = '^f19'; pfk20 = '^f20';
+ pfk21 = '^f21'; pfk22 = '^f22'; pfk23 = '^f23'; pfk24 = '^f24';
+
+ # program attention keys
+ pa1 = '^p1' | '\E[211z';
+ pa2 = '^p2' | '\E[212z';
+ pa3 = '^p3';
+
+ # other keys
+ cursel = '\E.';
+ centsign = '^\';
+
+ # local control keys
+
+ reset = '^t'; # well, there is a little confusion here...
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^v'; # redisplay screen
+ escape = '^c'; # escape to telnet command mode
+
+ # local editing keys
+ settab = '\E;';
+ clrtab = '\E+';
+ setmrg = '\E(';
+ sethom = '\E!';
+ coltab = '\Ei';
+ colbak = '\Eb';
+ indent = '\El';
+ undent = '\Eh';
+} # end of sun
+#
+# Works with /usr/ucb/tn3270 except tn3270pc which requires /usr/new/tn3270.
+#
+msk22714 | mskermit22714 | msk227 | mskermit227 {
+#
+# 9-5-86 gts
+# MS-Kermit UCB 227.14 to Unix then tn3270 to CMS.
+# Includes underlying ADM3A keystrokes for full S/1 compatibiliy.
+# Attempts to work for both "do unix" and "do cms" keyboards. Differences are
+# marked with (C) for CMS only or (U) for Unix only. Incidental effects are
+# enclosed in square brackets [].
+# New functions WERASE Ctrl-\ and FERASE Ctrl-_.
+
+ enter = '^m'; # <--'
+ clear = '^z'; # keypad + (C)
+
+ nl = '^n'; # keypad End (C)
+ tab = '^i'; # --->|
+ btab = '^b' | '\E^I'; # |<--- (C|U)
+ left = '^h'; # keypad Left
+ right = '^l'; # keypad Right
+ up = '^k'; # keypad Up
+ down = '^j' | '\EB'; # keypad Down (U|C)
+ # [ keypad End (U) ]
+ home = '^^' | '^@'; # keypad Home (U|C)
+ dp = '^u' | '^a'; # [ keypad PgUp (U) ]
+ fm = '^y';
+
+ delete = '^d' | '^?'; # keypad Del
+ # [ keypad PgDn (U) ]
+ eeof = '^e';
+ einp = '^w'; # keypad - (C)
+ insrt = '\E ' | '\Ei'; # keypad Ins (C|U)
+
+ # pf keys IBM PC/XT/AT and ADM3A Esc d
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4'; pfk5 = '\E5';
+ pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8'; pfk9 = '\E9'; pfk10= '\E0';
+ # pf keys IBM PC/XT/AT Shift and ADM3A Ctrl-F nn
+ pfk11='^f11'; pfk12='^f12'; pfk13='^f13'; pfk14='^f14'; pfk15='^f15';
+ pfk16='^f16'; pfk17='^f17'; pfk18='^f18'; pfk19='^f19'; pfk20='^f20';
+ # pf keys IBM PC/XT/AT Ctrl- and ADM3A Ctrl-F nn
+ pfk21='^f21'; pfk22='^f22'; pfk23='^f23'; pfk24='^f24'; pfk25='^f25';
+ pfk26='^f26'; pfk27='^f27'; pfk28='^f28'; pfk29='^f29'; pfk30='^f30';
+ # pf keys IBM PC/XT/AT Ctrl-Shift- and ADM3A Ctrl-F nn
+ pfk31='^f31'; pfk32='^f32'; pfk33='^f33'; pfk34='^f34'; pfk35='^f35';
+ pfk36='^f36';
+ # pf keys IBM PC/XT/AT Alt-1 to Alt-= (generated as, Esc d, ^F 11, ^F 12)
+ # pf keys ADM3A Esc d (d = 1 to 0 interpreted as above)
+ pfk11 = '\E-'; pfk12 = '\E=';
+
+ # program attention keys (same as ADM3A)
+ pa1 = '^p1'; # Alt-F1
+ pa2 = '^p2'; # Alt-F2
+ pa3 = '^p3'; # Alt-F3
+ #pa4 = '^p4'; # Alt-F3
+ #testreq = '^pr' | '^pR'; # Alt-F5
+
+ # other keys
+ cursel = '\E.';
+ werase = '^\';
+ ferase = '^_';
+
+ # local control keys
+ master_reset = '^g';
+ reset = '^r' | '^t';
+ flinp = '^x';
+ reshow = '^v';
+ escape = '^c'; # escape to telnet
+
+ # local editing keys
+ settab = '\E;';
+ deltab = '\E\'';
+ clrtab = '\E:' | '\E+';
+ setmrg = '\E(';
+ sethom = '\E!';
+ coltab = '\EI';
+ #coltab = '\Ei' | '\EI'; # cannot use Esc i
+ colbak = '\Eb'; # on S/1 \EB is down
+ #colbak = '\Eb' | '\EB'; # cannot use Esc B
+ indent = '\El' | '\EL';
+ undent = '\Eh' | '\EH'; # on S/1 \EH is Home
+
+} # end of msk22714
+#
+ansisys | ansisysk | nansisys | nansisysk {
+#
+# 9-5-86 gts
+# IBM PC/XT/AT using the ansi.sys | ansi.sysk | nansi.sys | nansi.sysk termcaps.
+#
+# PROBLEM: cannot use periods in termcap name until mset fixed (gts 9-5-86).
+#
+# PROBLEM: cannot use eval `mset ...` until Unix csh changed to allow more
+# than 1024 characters in an environment string or until mset changed to
+# return only the filename if the resulting string is longer than 1024.
+#
+# PROBLEM when NUL (^@) immediately follows a Return: Unix telent apparently
+# ignores the NUL! (Can tn3270 negotiate a different newline?)
+#
+# Nearly identical to the map3270 for the IBM PC TN3270, which itself is nearly
+# identical to the MS-Kermit UCB 227.14 keyboard which in turn was a modest
+# improvement of the BIJOU Yterm keyboard. See HELP TN3270PC on CMS.
+# Includes the underlying ADM3A keystrokes for full S/1 compatibility.
+# Adds some Ctrl-keypad keys to compensate for TN3270 ROMBIOS dependency
+# which prevents separate use of the keypad plus and minus keys.
+# Adds new functions WERASE and FERASE.
+#
+
+ enter = '^m'; # <--'
+ clear = '^z' | '^@w'; # Ctrl-Home
+
+ nl = '^n' | '^@O'; # keypad End
+ tab = '^i'; # --->|
+ btab = '^b' | '^@^O'; # |<---
+ left = '^h' | '^@K'; # keypad Left
+ right = '^l' | '^@M'; # keypad Right
+ up = '^k' | '^@H'; # keypad Up
+ down = '^j' | '^@P'; # keypad Down
+ home = '^^' | '^@G'; # keypad Home
+ # (cannot use Ctrl-@)
+ dp = '^u';
+ fm = '^y';
+
+ delete = '^d' | '^?' | '^@S'; # keypad Del
+ eeof = '^e' | '^@u'; # keypad Ctrl-End
+ einp = '^w';
+ insrt = '\E ' | '^@R' | '\E\Ei'; # keypad Ins
+
+ # pf keys IBM PC/XT/AT
+ pfk1 = '^@;'; pfk2 = '^@<'; pfk3 = '^@='; pfk4 = '^@>'; pfk5 = '^@?';
+ pfk6 = '^@@'; pfk7 = '^@A'; pfk8 = '^@B'; pfk9 = '^@C'; pfk10= '^@D';
+ # pf keys IBM PC/XT/AT Shift
+ pfk11 = '^@T'; pfk12 = '^@U'; pfk13 = '^@V'; pfk14 = '^@W'; pfk15 = '^@X';
+ pfk16 = '^@Y'; pfk17 = '^@Z'; pfk18 = '^@['; pfk19 = '^@\\'; pfk20 = '^@]';
+ # pf keys IBM PC/XT/AT Ctrl-
+ pfk21 = '^@\^';pfk22 = '^@_'; pfk23 = '^@`'; pfk24 = '^@a'; pfk25 = '^@b';
+ pfk26 = '^@c'; pfk27 = '^@d'; pfk28 = '^@e'; pfk29 = '^@\f'; pfk30 = '^@g';
+ # pf keys IBM PC/XT/AT Ctrl-Shift- (cannot be done yet with PC tn3270)
+ # pf keys IBM PC/XT/AT Alt-d
+ pfk1 = '^@x'; pfk2 = '^@y'; pfk3 = '^@z'; pfk4 = '^@{'; pfk5 = '^@|';
+ pfk6 = '^@}'; pfk7 = '^@~'; pfk8 = '^@^?';pfk9 = '^@^@';pfk10= '^@^A';
+ pfk11='^@^B'; pfk12= '^@^C';
+
+ # pf keys ADM3A Esc d
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4'; pfk5 = '\E5';
+ pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8'; pfk9 = '\E9'; pfk10= '\E0';
+ pfk11 = '\E-'; pfk12 = '\E=';
+ # pf keys ADM3A Ctrl-F n n
+ pfk1 = '^f01'; pfk2 = '^f02'; pfk3 = '^f03'; pfk4 = '^f04'; pfk5= '^f05';
+ pfk6 = '^f06'; pfk7 = '^f07'; pfk8 = '^f08'; pfk9 = '^f09'; pfk10= '^f10';
+ pfk11= '^f11'; pfk12= '^f12'; pfk13= '^f13'; pfk14= '^f14'; pfk15= '^f15';
+ pfk16= '^f16'; pfk17= '^f17'; pfk18= '^f18'; pfk19= '^f19'; pfk20= '^f20';
+ pfk21= '^f21'; pfk22= '^f22'; pfk23= '^f23'; pfk24= '^f24'; pfk25= '^f25';
+ pfk26= '^f26'; pfk27= '^f27'; pfk28= '^f28'; pfk29= '^f29'; pfk30= '^f30';
+ pfk31= '^f31'; pfk32= '^f32'; pfk33= '^f33'; pfk34= '^f34'; pfk35= '^f35';
+ pfk36= '^f36';
+
+ # program attention keys
+ pa1 = '^p1' | '^@h'; # Alt-F1
+ pa2 = '^p2' | '^@i'; # Alt-F2
+ pa3 = '^p3' | '^@j'; # Alt-F3
+ #pa4 = '^p4' | '^@k'; # Alt-F4
+ #testreq = '^pr' | '^pR' | '^@l' # Alt-F5
+
+ # other keys
+ cursel = '\E.';
+ werase = '^\';
+ ferase = '^_';
+ pfk7 = '^@I' | '\E^U'; # keypad PgUp
+ pfk8 = '^@Q' | '\E^D'; # keypad PgDn
+
+ # local control keys
+ reset = '^r' | '^t';
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^v';
+ escape = '^c'; # escape to TN3270 command prompt
+
+ # local editing keys
+ settab = '\E;';
+ deltab = '\E\'';
+ clrtab = '\E:' | '\E+';
+ setmrg = '\E(';
+ sethom = '\E!';
+ coltab = '\Ei' | '\EI';
+ colbak = '\Eb' | '\EB'; # on S/1 \EB is down
+ indent = '\El' | '\EL';
+ undent = '\Eh' | '\EH'; # on S/1 \EH is Home
+
+} # end of ansi.sys
+#
+tn3270pc | ibm-3278-2 {
+#
+# 2-14-87 gts
+#
+# MAP3270 for the IBM PC logged into Unix with PC TN3270 with TERM=nansisys,
+# nansisysk, ansisys or ansisysk, hence requires KETBD=tn3270pc.
+#
+# MAP3270 for the IBM PC
+# Nearly identical to the MS-Kermit UCB 227.14 keyboard which in turn was
+# an modest improvement of the BIJOU Yterm keyboard.
+# Includes underlying ADM3A keystrokes for full S/1 compatibiliy.
+# Adds some Ctrl-keypad keys to compensate for TN3270 ROMBIOS dependency
+# which prevents separate use of the keypad plus and minus keys, and adds
+# new functions WERASE, FERASE, WORDTAB, WORDBACKTAB, WORDEND and FIELDEND.
+# Where possible these extensions are compatible with IBM PC keystroke usage
+# (see XT technical reference manual Keyboard Usage Guidelines).
+# Includes F11 and F12 keys from the new IBM PC/XT/AT keyboard.
+#
+
+ centsign = '\Ec' | '\EC'; # CentSign for input
+ enter = '^m'; # <--'
+ clear = '^z' | '^Aw'; # Ctrl-Home
+
+ nl = '^n' | '^AO'; # keypad End
+ tab = '^i'; # --->|
+ btab = '^b' | '\E^I' | '^A^O'; # |<---
+ left = '^h' | '^AK'; # keypad Left
+ right = '^l' | '^AM'; # keypad Right
+ up = '^k' | '^AH'; # keypad Up
+ down = '^j' | '^AP'; # keypad Down
+ home = '^^' | '^AG' | '^@'; # keypad Home
+ dp = '^u';
+ fm = '^y';
+
+ delete = '^d' | '^AS'; # keypad Del
+ eeof = '^e' | '^Au'; # keypad End
+ einp = '^w';
+ insrt = '\E ' | '^AR'; # keypad Ins
+
+ # pf keys IBM PC/XT/AT
+ pfk1 = '^A;'; pfk2 = '^A<'; pfk3 = '^A='; pfk4 = '^A>'; pfk5 = '^A?';
+ pfk6 = '^A@'; pfk7 = '^AA'; pfk8 = '^AB'; pfk9 = '^AC'; pfk10= '^AD';
+ # pf keys IBM PC/XT/AT Shift
+ pfk11 = '^AT'; pfk12 = '^AU'; pfk13 = '^AV'; pfk14 = '^AW'; pfk15 = '^AX';
+ pfk16 = '^AY'; pfk17 = '^AZ'; pfk18 = '^A['; pfk19 = '^A\\'; pfk20 = '^A]';
+ # pf keys IBM PC/XT/AT Ctrl-
+ pfk21 = '^A\^';pfk22 = '^A_'; pfk23 = '^A`'; pfk24 = '^Aa'; pfk25 = '^Ab';
+ pfk26 = '^Ac'; pfk27 = '^Ad'; pfk28 = '^Ae'; pfk29 = '^Af'; pfk30 = '^Ag';
+ # pf keys IBM PC/XT/AT Alt-d
+ pfk1 = '^Ax'; pfk2 = '^Ay'; pfk3 = '^Az'; pfk4 = '^A{'; pfk5 = '^A|';
+ pfk6 = '^A}'; pfk7 = '^A~'; pfk8 = '^A^?';pfk9 = '^A^A^@';pfk10= '^A^A^A';
+ pfk11='^A^A^b'; pfk12= '^A^A^c';
+ # pf keys NEW IBM PC/XT/AT Keyboard
+ pfk11='^A^A^e'; pfk12= '^A^A^f';
+
+ # pf keys ADM3A Esc d
+ pfk1 = '\E1'; pfk2 = '\E2'; pfk3 = '\E3'; pfk4 = '\E4'; pfk5 = '\E5';
+ pfk6 = '\E6'; pfk7 = '\E7'; pfk8 = '\E8'; pfk9 = '\E9'; pfk10= '\E0';
+ pfk11 = '\E-'; pfk12 = '\E=';
+ # pf keys ADM3A Ctrl-F n n
+ pfk1 = '^f01'; pfk2 = '^f02'; pfk3 = '^f03'; pfk4 = '^f04'; pfk5= '^f05';
+ pfk6 = '^f06'; pfk7 = '^f07'; pfk8 = '^f08'; pfk9 = '^f09'; pfk10= '^f10';
+ pfk11= '^f11'; pfk12= '^f12'; pfk13= '^f13'; pfk14= '^f14'; pfk15= '^f15';
+ pfk16= '^f16'; pfk17= '^f17'; pfk18= '^f18'; pfk19= '^f19'; pfk20= '^f20';
+ pfk21= '^f21'; pfk22= '^f22'; pfk23= '^f23'; pfk24= '^f24'; pfk25= '^f25';
+ pfk26= '^f26'; pfk27= '^f27'; pfk28= '^f28'; pfk29= '^f29'; pfk30= '^f30';
+ pfk31= '^f31'; pfk32= '^f32'; pfk33= '^f33'; pfk34= '^f34'; pfk35= '^f35';
+ pfk36= '^f36';
+
+ # program attention keys
+ pa1 = '^p1' | '^Ah'; # Alt-F1
+ pa2 = '^p2' | '^Ai'; # Alt-F2
+ pa3 = '^p3' | '^Aj'; # Alt-F3
+ treq = '^pr' | '^pR' | '^Al'; # Alt-F5
+
+ # other keys
+ cursel = '\E.';
+ werase = '^\';
+ ferase = '^_';
+ wordtab = '^At'; # Ctrl-Right
+ wordbacktab = '^As'; # Ctrl-Left
+ wordend = '^A^A^d'; # Ctrl-PgUp
+ fieldend = '^Av'; # Ctrl-PgDn
+ pfk7 = '^AI'; # keypad PgUp
+ pfk8 = '^AQ'; # keypad PgDn
+
+ # local control keys
+ reset = '^r' | '^t';
+ master_reset = '^g';
+ flinp = '^x';
+ reshow = '^v';
+ escape = '^c'; # to command prompt
+ disc = '^pS1D'; # disconnect (suspend)?
+ sync = '^pS1S'; # in sync with user?
+
+ # local editing keys
+ settab = '\E;';
+ deltab = '\E\'';
+ clrtab = '\E:' | '\E+';
+ setmrg = '\E(';
+ sethom = '\E!';
+ coltab = '\Ei' | '\EI';
+ colbak = '\Eb' | '\EB'; # on S/1 \EB is down
+ indent = '\El' | '\EL';
+ undent = '\Eh' | '\EH'; # on S/1 \EH is Home
+
+} # end of tn3270pc
diff --git a/comms/tn3270/files/mset/map3270.5 b/comms/tn3270/files/mset/map3270.5
new file mode 100644
index 00000000000..9f4114e9a13
--- /dev/null
+++ b/comms/tn3270/files/mset/map3270.5
@@ -0,0 +1,341 @@
+.\" $NetBSD: map3270.5,v 1.1.1.1 2010/01/17 01:33:23 dholland Exp $
+.\" From NetBSD: map3270.5,v 1.12 2003/08/07 11:16:35 agc Exp
+.\"
+.\" Copyright (c) 1986 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)map3270.5 4.5 (Berkeley) 7/31/91
+.\" $NetBSD: map3270.5,v 1.1.1.1 2010/01/17 01:33:23 dholland Exp $
+.\"
+.TH MAP3270 5 "July 31, 1991"
+.UC 6
+.SH NAME
+map3270 \- database for mapping ascii keystrokes into IBM 3270 keys
+.SH SYNOPSIS
+.B map3270
+.SH DESCRIPTION
+When emulating IBM-style 3270 terminals under \s-1UNIX\s0 (see \fItn3270\fR(1)),
+a mapping must be performed between sequences of keys hit on
+a user's (ascii) keyboard, and the keys that are
+available on a 3270. For example, a 3270 has a key labeled
+.B EEOF
+which erases the contents of the current field from the
+location of the cursor to the end.
+In order to accomplish this function,
+the terminal user and a program emulating a 3270 must
+agree on what keys will be typed
+to invoke the
+.B EEOF
+function.
+.PP
+The requirements for these sequences are:
+.nf
+.ta 4n 9n
+.sp
+ 1) that the first character of the sequence be outside of the
+ standard ascii printable characters;
+.sp
+ 2) that no sequence \fIbe\fR an initial part of another (although
+ sequences may \fIshare\fR initial parts).
+.sp
+.fi
+.SH FORMAT
+The file consists of entries for various keyboards. The first part
+of an entry lists the names of the keyboards which use that entry.
+These names will often be the same as in
+.I /usr/share/misc/termcap
+(see
+.IR termcap (5));
+however, note that often the terminals from various termcap entries will all
+use the same
+.I map3270
+entry; for example, both 925 and 925vb (for
+925 with visual bells) would probably use the same
+.I map3270
+entry.
+Additionally, there are occasions when the terminal type defines
+a window manager, and it will then be necessary to specify a
+keyboard name (via the
+.B KEYBD
+environment variable) as the name of the entry.
+After the names, separated by vertical bars (`|'), comes a left
+brace (`{'); the definitions; and, finally, a right brace
+(`}').
+.PP
+Each definition consists of a reserved keyword (see list below) which
+identifies the 3270 function (extended as defined below), followed
+by an equal sign (`='), followed by the various ways to generate
+this particular function, followed by a semi-colon (`;').
+Each way is a sequence of strings of
+.I printable
+ascii characters enclosed inside single quotes (`\(aa');
+various ways (alternatives) are separated by vertical bars (`|').
+.PP
+Inside the single quotes, a few characters are special.
+A caret
+(`^') specifies that the next character is
+the ``control'' character of whatever the character is.
+So, `^a'
+represents control-a, ie: hexadecimal 1
+(note that `^A' would generate the same code).
+To generate
+.B rubout
+(DEL),
+one enters `^?'.
+To represent a control character inside a file
+requires using the caret to represent a control sequence;
+simply typing control-A will not work.
+Note: the ctrl-caret sequence
+(to generate a hexadecimal 1E)
+is represented as `^^' (not `^\e^').
+.PP
+In addition to the caret, a letter may be preceded by a backslash (`\e').
+Since this has little effect for most characters,
+its use is usually not recommended.
+For the case of a single quote (`\(aa'), the backslash
+prevents that single quote from terminating the string.
+For the case of a caret (`^'), the backslash prevents
+the caret from having its special meaning.
+To have the backslash be part of the string, it is necessary to
+place two backslashes ('\e\e') in the file.
+.PP
+In addition, the following characters are special:
+.sp
+.nf
+.in +0.5i
+`\eE' means an escape character;
+`\en' means newline;
+`\et' means tab;
+`\er' means carriage return.
+.in -0.5i
+.fi
+.sp
+It is not necessary for each character in a string
+to be enclosed within single quotes.
+`\eE\eE\eE' means three escape characters.
+.PP
+Comments, which may appear anywhere on a line,
+begin with a hash mark (`#'), and terminate
+at the end of that line.
+However, comments cannot begin inside a quoted string;
+a hash mark inside a quoted string has no special meaning.
+.PP
+.SH 3270 KEYS SUPPORTED
+The following is the list of 3270 key names that are supported in this file.
+Note that some of the keys don't really exist on a 3270.
+In particular, the developers of this file have relied
+extensively on the work at the Yale University Computer Center with
+their 3270 emulator which runs in an IBM Series/1 front end.
+The following list corresponds closely to the functions
+that the developers of the Yale code offer in their product.
+.sp
+.B In the following list, the
+.B starred ("*")
+.B functions are not supported by
+.IR tn3270 (1).
+An unsupported function will cause
+.IR tn3270(1)
+to send a (possibly visual) bell sequence to the user's terminal.
+.sp
+.nf
+ 3270 Key Name Functional description
+
+ (*)LPRT local print
+ DP dup character
+ FM field mark character
+ CURSEL cursor select
+ CENTSIGN EBCDIC cent sign
+ RESHOW redisplay the screen
+ EINP erase input
+ EEOF erase end of field
+ DELETE delete character
+ INSRT toggle insert mode
+ TAB field tab
+ BTAB field back tab
+ COLTAB column tab
+ COLBAK column back tab
+ INDENT indent one tab stop
+ UNDENT undent one tab stop
+ NL new line
+ HOME home the cursor
+ UP up cursor
+ DOWN down cursor
+ RIGHT right cursor
+ LEFT left cursor
+ SETTAB set a column tab
+ DELTAB delete a columntab
+ SETMRG set left margin
+ SETHOM set home position
+ CLRTAB clear all column tabs
+ (*)APLON apl on
+ (*)APLOFF apl off
+ (*)APLEND treat input as ascii
+ (*)PCON xon/xoff on
+ (*)PCOFF xon/xoff off
+ DISC disconnect (suspend)
+ (*)INIT new terminal type
+ (*)ALTK alternative keyboard dvorak
+ FLINP flush input
+ ERASE erase last character
+ WERASE erase last word
+ FERASE erase field
+ SYNCH we are in synch with the user
+ RESET reset key-unlock keyboard
+ MASTER_RESET reset, unlock and redisplay
+ (*)XOFF please hold output
+ (*)XON please give me output
+ ESCAPE enter telnet command mode
+ WORDTAB tab to beginning of next word
+ WORDBACKTAB tab to beginning of current/last word
+ WORDEND tab to end of current/next word
+ FIELDEND tab to last non-blank of current/next
+ unprotected (writable) field.
+
+ PA1 program attention 1
+ PA2 program attention 2
+ PA3 program attention 3
+
+ CLEAR local clear of the 3270 screen
+ TREQ test request
+ ENTER enter key
+
+ PFK1 program function key 1
+ PFK2 program function key 2
+ etc. etc.
+ PFK36 program function key 36
+.SH A SAMPLE ENTRY
+The following entry is used by
+tn3270(1) when unable to locate a reasonable version in the
+user's environment and in /usr/share/misc/map3270:
+.sp
+.nf
+ name { # actual name comes from TERM variable
+ clear = '^z';
+ flinp = '^x';
+ enter = '^m';
+ delete = '^d' | '^?'; # note that '^?' is delete (rubout)
+ synch = '^r';
+ reshow = '^v';
+ eeof = '^e';
+ tab = '^i';
+ btab = '^b';
+ nl = '^n';
+ left = '^h';
+ right = '^l';
+ up = '^k';
+ down = '^j';
+ einp = '^w';
+ reset = '^t';
+ xoff = '^s';
+ xon = '^q';
+ escape = '^c';
+ ferase = '^u';
+ insrt = '\E ';
+ # program attention keys
+ pa1 = '^p1'; pa2 = '^p2'; pa3 = '^p3';
+ # program function keys
+ pfk1 = '\eE1'; pfk2 = '\eE2'; pfk3 = '\eE3'; pfk4 = '\eE4';
+ pfk5 = '\eE5'; pfk6 = '\eE6'; pfk7 = '\eE7'; pfk8 = '\eE8';
+ pfk9 = '\eE9'; pfk10 = '\eE0'; pfk11 = '\eE-'; pfk12 = '\eE=';
+ pfk13 = '\eE!'; pfk14 = '\eE@'; pfk15 = '\eE#'; pfk16 = '\eE$';
+ pfk17 = '\eE%'; pfk18 = '\eE'; pfk19 = '\eE\*[Am]'; pfk20 = '\eE*';
+ pfk21 = '\eE('; pfk22 = '\eE)'; pfk23 = '\eE_'; pfk24 = '\eE+';
+ }
+.fi
+.SH "IBM 3270 KEY DEFINITIONS FOR AN ABOVE DEFINITION"
+The charts below show the proper keys to emulate
+each 3270 function when using the default key mapping supplied
+with
+.IR tn3270 (1)
+and
+.IR mset (1).
+.sp
+.nf
+ Command Keys IBM 3270 Key Default Key(s)
+ Enter RETURN
+ Clear control-z
+ Cursor Movement Keys
+ New Line control-n or
+ Home
+ Tab control-i
+ Back Tab control-b
+ Cursor Left control-h
+ Cursor Right control-l
+ Cursor Up control-k
+ Cursor Down control-j or
+ LINE FEED
+ Edit Control Keys
+ Delete Char control-d or
+ RUB
+ Erase EOF control-e
+ Erase Input control-w
+ Insert Mode ESC Space
+ End Insert ESC Space
+ Program Function Keys
+ PF1 ESC 1
+ PF2 ESC 2
+ ... ...
+ PF10 ESC 0
+ PF11 ESC -
+ PF12 ESC =
+ PF13 ESC !
+ PF14 ESC @
+ ... ...
+ PF24 ESC +
+ Program Attention Keys
+ PA1 control-p 1
+ PA2 control-p 2
+ PA3 control-p 3
+ Local Control Keys
+ Reset After Error control-r
+ Purge Input Buffer control-x
+ Keyboard Unlock control-t
+ Redisplay Screen control-v
+ Other Keys
+ Erase current field control-u
+.fi
+.SH FILES
+/usr/share/misc/map3270
+.SH SEE ALSO
+tn3270(1), mset(1), \fIYale ASCII Terminal Communication
+System II Program Description/Operator's Manual\fR
+(IBM SB30-1911)
+.SH AUTHOR
+Greg Minshall
+.SH BUGS
+.I Tn3270
+doesn't yet understand how to process all the functions
+available in
+.I map3270;
+when such a function is requested
+.I tn3270
+will beep at you.
+.PP
+The definition of "word" (for "word erase", "word tab") should be a run-time
+option. Currently it is defined as the kernel tty driver defines it (strings
+of non-whitespace); more than one person would rather use the "vi" definition
+(strings of specials, strings of alphanumeric).
diff --git a/comms/tn3270/files/mset/mset.1 b/comms/tn3270/files/mset/mset.1
new file mode 100644
index 00000000000..a2ede605eda
--- /dev/null
+++ b/comms/tn3270/files/mset/mset.1
@@ -0,0 +1,189 @@
+.\" $NetBSD: mset.1,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $
+.\" From NetBSD: mset.1,v 1.11 2003/08/07 11:16:36 agc Exp
+.\"
+.\" Copyright (c) 1986, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)mset.1 4.6 (Berkeley) 7/27/91
+.\" $NetBSD: mset.1,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $
+.\"
+.Dd July 27, 1991
+.Dt MSET 1
+.Os
+.Sh NAME
+.Nm mset
+.Nd retrieve
+.Tn ASCII
+to
+.Tn IBM
+3270 keyboard map
+.Sh SYNOPSIS
+.Nm mset
+.Op Fl picky
+.Op Fl shell
+.Op Ar keyboardname
+.Sh DESCRIPTION
+.Nm
+retrieves mapping information
+for the
+.Tn ASCII
+keyboard to
+.Tn IBM
+3270 terminal
+special functions.
+Normally, these mappings are found
+in
+.Pa /usr/share/misc/map3270
+(see
+.Xr map3270 5 ) .
+This information is used by the
+.Ic tn3270
+command (see
+.Xr tn3270 1 ) .
+.Pp
+The default
+.Nm
+output can be used to store the mapping information in the process environment
+in order to avoid scanning
+.Pa map3270
+each time
+.Ic tn3270
+is invoked.
+To do this, place the following command in your
+.Pa .login
+file:
+.Bd -literal -offset indent
+set noglob; setenv MAP3270 "\(gamset\(ga"; unset noglob
+.Ed
+.Pp
+If the
+.Ar keyboardname
+argument is not supplied,
+.Nm
+attempts to determine the name of the keyboard the user is using,
+by checking the
+.Ev KEYBD
+environment variable.
+If the
+.Ev KEYBD
+environment variable is not set, then
+.Nm
+uses the user's terminal type from the environment variable
+.Ev TERM
+as the keyboard name.
+Normally,
+.Nm
+then uses the file
+.Xr map3270 5
+to find the keyboard mapping for that terminal.
+However, if the environment variable
+.Ev MAP3270
+exists and contains the entry for the specified keyboard, then that
+definition is used.
+If the value of
+.Ev MAP3270
+begins with a slash (`/') then it is assumed to be the full pathname
+of an alternative mapping file and that file is searched first.
+In any case, if the mapping for the keyboard is not found in
+the environment, nor in an alternative map file, nor in the standard map file,
+then the same search is performed for an entry for a keyboard with the name
+.Ar unknown .
+If that search also fails,
+then a default mapping
+is used.
+.Pp
+The arguments to
+.Nm
+are:
+.Pp
+.Bl -tag -width Fl
+.It Fl picky
+When processing the various
+.Pa map3270
+entries (for the user's keyboard,
+and all those encountered before the one for the user's keyboard),
+.Nm
+normally will not complain about entries for unknown functions (like
+.Dq PFX1 ) ;
+the
+.Fl picky
+argument causes
+.Nm
+to issue warning messages about these unknown entries.
+.It Fl shell
+If the
+.Pa map3270
+entry is longer than the shell's 1024 environmental variable
+length limit, the default
+.Nm
+output cannot be used to store the mapping information in the process
+environment to avoid scanning
+.Pa map3270
+each time
+.Ic tn3270
+is invoked.
+The
+.Fl shell
+argument causes
+.Nm
+to generate shell commands to set the environmental variables
+.Ev MAP3270 ,
+.Ev MAP3270A ,
+and so on, breaking up the entry to fit within the shell environmental
+variable length limit.
+To set these variables, place the following command in your
+.Pa .login
+file:
+.Bd -literal -offset indent
+mset -shell \*[Gt] tmp ; source tmp ; /bin/rm tmp
+.Ed
+.It Ar keyboardname
+When searching for the
+.Pa map3270
+entry that matches the user's keyboard,
+.Nm
+will use
+.Ar keyboardname
+instead of determining the keyboard name from the
+.Ev KEYBD
+or
+.Ev TERM
+environmental variables.
+.El
+.Sh FILES
+.Bl -tag -width /usr/share/misc/map3270 -compact
+.It Pa /usr/share/misc/map3270
+keyboard mapping for known keyboards
+.El
+.Sh SEE ALSO
+.Xr tn3270 1 ,
+.Xr map3270 5
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
diff --git a/comms/tn3270/files/sys_curses/system.c b/comms/tn3270/files/sys_curses/system.c
new file mode 100644
index 00000000000..a4e37ead69f
--- /dev/null
+++ b/comms/tn3270/files/sys_curses/system.c
@@ -0,0 +1,763 @@
+/* $NetBSD: system.c,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $ */
+/* From NetBSD: system.c,v 1.21 2006/10/07 17:27:57 elad Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)system.c 4.5 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: system.c,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+
+#if defined(pyr)
+#define fd_set fdset_t
+#endif /* defined(pyr) */
+
+/*
+ * Wouldn't it be nice if these REALLY were in <sys/inode.h>? Or,
+ * equivalently, if <sys/inode.h> REALLY existed?
+ */
+#define IREAD 00400
+#define IWRITE 00200
+
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../general/general.h"
+#include "../ctlr/api.h"
+#include "../api/api_exch.h"
+#include "telextrn.h"
+#include "externs.h"
+
+#include "../general/globals.h"
+
+#ifndef FD_SETSIZE
+/*
+ * The following is defined just in case someone should want to run
+ * this telnet on a 4.2 system.
+ *
+ */
+
+#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n)))
+#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n)))
+#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n)))
+#define FD_ZERO(p) ((p)->fds_bits[0] = 0)
+
+#endif
+
+static int shell_pid = 0;
+static char key[50]; /* Actual key */
+static char *keyname; /* Name of file with key in it */
+
+static char *ourENVlist[200]; /* Lots of room */
+
+static int
+ sock = -1, /* Connected socket */
+ serversock; /* Server (listening) socket */
+
+static enum { DEAD, UNCONNECTED, CONNECTED } state;
+
+static long
+ storage_location; /* Address we have */
+static short
+ storage_length = 0; /* Length we have */
+static int
+ storage_must_send = 0, /* Storage belongs on other side of wire */
+ storage_accessed = 0; /* The storage is accessed (so leave alone)! */
+
+static long storage[1000];
+
+static union REGS inputRegs;
+static struct SREGS inputSregs;
+
+extern int apitrace;
+
+static void kill_connection(void);
+static int nextstore(void);
+static int doreject(char *);
+static int doassociate(void);
+static int getstorage(long, int, int);
+static int doconnect(void);
+static void child_died(int);
+
+static void
+kill_connection()
+{
+ state = UNCONNECTED;
+ if (sock != -1) {
+ (void) close(sock);
+ sock = -1;
+ }
+}
+
+
+static int
+nextstore()
+{
+ struct storage_descriptor sd;
+
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ storage_length = 0;
+ return -1;
+ }
+ storage_length = sd.length;
+ storage_location = sd.location;
+ if (storage_length > sizeof storage) {
+ fprintf(stderr, "API client tried to send too much storage (%d).\n",
+ storage_length);
+ storage_length = 0;
+ return -1;
+ }
+ if (api_exch_intype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
+ == -1) {
+ storage_length = 0;
+ return -1;
+ }
+ return 0;
+}
+
+
+static int
+doreject(message)
+char *message;
+{
+ struct storage_descriptor sd;
+ int length = strlen(message);
+
+ if (api_exch_outcommand(EXCH_CMD_REJECTED) == -1) {
+ return -1;
+ }
+ sd.length = length;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, length, message) == -1) {
+ return -1;
+ }
+ return 0;
+}
+
+
+/*
+ * doassociate()
+ *
+ * Negotiate with the other side and try to do something.
+ *
+ * Returns:
+ *
+ * -1: Error in processing
+ * 0: Invalid password entered
+ * 1: Association OK
+ */
+
+static int
+doassociate()
+{
+ struct passwd *pwent;
+ char
+ promptbuf[100],
+ buffer[200];
+ struct storage_descriptor sd;
+
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ return -1;
+ }
+ if (sd.length >= sizeof buffer) {
+ doreject("(internal error) Authentication key too long");
+ return -1;
+ }
+ if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
+ return -1;
+ }
+ buffer[sd.length] = 0;
+
+ if (strcmp(buffer, key) != 0) {
+ if ((pwent = getpwuid((int)geteuid())) == 0) {
+ return -1;
+ }
+ sprintf(promptbuf, "Enter password for user %s:", pwent->pw_name);
+ if (api_exch_outcommand(EXCH_CMD_SEND_AUTH) == -1) {
+ return -1;
+ }
+ sd.length = strlen(promptbuf);
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
+ == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, strlen(promptbuf), promptbuf)
+ == -1) {
+ return -1;
+ }
+ sd.length = strlen(pwent->pw_name);
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
+ == -1) {
+ return -1;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES,
+ strlen(pwent->pw_name), pwent->pw_name) == -1) {
+ return -1;
+ }
+ if (api_exch_incommand(EXCH_CMD_AUTH) == -1) {
+ return -1;
+ }
+ if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd)
+ == -1) {
+ return -1;
+ }
+ sd.length = sd.length;
+ if (sd.length > sizeof buffer) {
+ doreject("Password entered was too long");
+ return -1;
+ }
+ if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) {
+ return -1;
+ }
+ buffer[sd.length] = 0;
+
+ /* Is this the correct password? */
+ if (strlen(pwent->pw_name)) {
+ const char *ptr;
+ int i;
+
+ ptr = pwent->pw_name;
+ i = 0;
+ while (i < sd.length) {
+ buffer[i++] ^= *ptr++;
+ if (*ptr == 0) {
+ ptr = pwent->pw_name;
+ }
+ }
+ }
+ if (strcmp(crypt(buffer, pwent->pw_passwd), pwent->pw_passwd) != 0) {
+ doreject("Invalid password");
+ sleep(10); /* Don't let us do too many of these */
+ return 0;
+ }
+ }
+ if (api_exch_outcommand(EXCH_CMD_ASSOCIATED) == -1) {
+ return -1;
+ } else {
+ return 1;
+ }
+}
+
+
+void
+freestorage()
+{
+ struct storage_descriptor sd;
+
+ if (storage_accessed) {
+ fprintf(stderr, "Internal error - attempt to free accessed storage.\n");
+ fprintf(stderr, "(Encountered in file %s at line %d.)\n",
+ __FILE__, __LINE__);
+ quit(0, NULL);
+ }
+ if (storage_must_send == 0) {
+ return;
+ }
+ storage_must_send = 0;
+ if (api_exch_outcommand(EXCH_CMD_HEREIS) == -1) {
+ kill_connection();
+ return;
+ }
+ sd.length = storage_length;
+ sd.location = storage_location;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) {
+ kill_connection();
+ return;
+ }
+ if (api_exch_outtype(EXCH_TYPE_BYTES, storage_length, (char *)storage)
+ == -1) {
+ kill_connection();
+ return;
+ }
+}
+
+
+static int
+getstorage(address, length, copyin)
+long
+ address;
+int
+ length,
+ copyin;
+{
+ struct storage_descriptor sd;
+
+ freestorage();
+ if (storage_accessed) {
+ fprintf(stderr,
+ "Internal error - attempt to get while storage accessed.\n");
+ fprintf(stderr, "(Encountered in file %s at line %d.)\n",
+ __FILE__, __LINE__);
+ quit(0, NULL);
+ }
+ storage_must_send = 0;
+ if (api_exch_outcommand(EXCH_CMD_GIMME) == -1) {
+ kill_connection();
+ return -1;
+ }
+ storage_location = address;
+ storage_length = length;
+ if (copyin) {
+ sd.location = (long)storage_location;
+ sd.length = storage_length;
+ if (api_exch_outtype(EXCH_TYPE_STORE_DESC,
+ sizeof sd, (char *)&sd) == -1) {
+ kill_connection();
+ return -1;
+ }
+ if (api_exch_incommand(EXCH_CMD_HEREIS) == -1) {
+ fprintf(stderr, "Bad data from other side.\n");
+ fprintf(stderr, "(Encountered at %s, %d.)\n", __FILE__, __LINE__);
+ return -1;
+ }
+ if (nextstore() == -1) {
+ kill_connection();
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*ARGSUSED*/
+void
+movetous(local, es, di, length)
+char
+ *local;
+unsigned int
+ es,
+ di;
+int
+ length;
+{
+ long where = SEG_OFF_BACK(es, di);
+
+ if (length > sizeof storage) {
+ fprintf(stderr, "Internal API error - movetous() length too long.\n");
+ fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
+ quit(0, NULL);
+ } else if (length == 0) {
+ return;
+ }
+ getstorage(where, length, 1);
+ memcpy(local, (char *)(storage+((where-storage_location))), length);
+ if (apitrace) {
+ Dump('(', local, length);
+ }
+}
+
+/*ARGSUSED*/
+void
+movetothem(es, di, local, length)
+unsigned int
+ es,
+ di;
+char
+ *local;
+int
+ length;
+{
+ long where = SEG_OFF_BACK(es, di);
+
+ if (length > sizeof storage) {
+ fprintf(stderr, "Internal API error - movetothem() length too long.\n");
+ fprintf(stderr, "(detected in file %s, line %d)\n", __FILE__, __LINE__);
+ quit(0, NULL);
+ } else if (length == 0) {
+ return;
+ }
+ freestorage();
+ memcpy((char *)storage, local, length);
+ if (apitrace) {
+ Dump(')', local, length);
+ }
+ storage_length = length;
+ storage_location = where;
+ storage_must_send = 1;
+}
+
+
+char *
+access_api(location, length, copyin)
+char *
+ location;
+int
+ length,
+ copyin; /* Do we need to copy in initially? */
+{
+ if (storage_accessed) {
+ fprintf(stderr, "Internal error - storage accessed twice\n");
+ fprintf(stderr, "(Encountered in file %s, line %d.)\n",
+ __FILE__, __LINE__);
+ quit(0, NULL);
+ } else if (length != 0) {
+ freestorage();
+ getstorage((long)location, length, copyin);
+ storage_accessed = 1;
+ }
+ return (char *) storage;
+}
+
+/*ARGSUSED*/
+void
+unaccess_api(location, local, length, copyout)
+char *location;
+char *local;
+int length;
+int copyout;
+{
+ if (storage_accessed == 0) {
+ fprintf(stderr, "Internal error - unnecessary unaccess_api call.\n");
+ fprintf(stderr, "(Encountered in file %s, line %d.)\n",
+ __FILE__, __LINE__);
+ quit(0, NULL);
+ }
+ storage_accessed = 0;
+ storage_must_send = copyout; /* if needs to go back */
+}
+
+/*
+ * Accept a connection from an API client, aborting if the child dies.
+ */
+
+static int
+doconnect()
+{
+ struct pollfd set[1];
+ int i;
+
+ sock = -1;
+ set[0].fd = serversock;
+ set[0].events = POLLIN;
+ while (shell_active && (sock == -1)) {
+ if ((i = poll(set, 1, INFTIM)) < 0) {
+ if (errno == EINTR) {
+ continue;
+ } else {
+ perror("in poll waiting for API connection");
+ return -1;
+ }
+ } else {
+ i = accept(serversock, (struct sockaddr *)0, (socklen_t *)0);
+ if (i == -1) {
+ perror("accepting API connection");
+ return -1;
+ }
+ sock = i;
+ }
+ }
+ /* If the process has already exited, we may need to close */
+ if ((shell_active == 0) && (sock != -1)) {
+
+ (void) close(sock);
+ sock = -1;
+ setcommandmode(); /* In case child_died sneaked in */
+ }
+ return 0;
+}
+
+/*
+ * shell_continue() actually runs the command, and looks for API
+ * requests coming back in.
+ *
+ * We are called from the main loop in telnet.c.
+ */
+
+int
+shell_continue()
+{
+ int i;
+
+ switch (state) {
+ case DEAD:
+ pause(); /* Nothing to do */
+ break;
+ case UNCONNECTED:
+ if (doconnect() == -1) {
+ kill_connection();
+ return -1;
+ }
+ /* At this point, it is possible that we've gone away */
+ if (shell_active == 0) {
+ kill_connection();
+ return -1;
+ }
+ if (api_exch_init(sock, "server") == -1) {
+ return -1;
+ }
+ while (state == UNCONNECTED) {
+ if (api_exch_incommand(EXCH_CMD_ASSOCIATE) == -1) {
+ kill_connection();
+ return -1;
+ } else {
+ switch (doassociate()) {
+ case -1:
+ kill_connection();
+ return -1;
+ case 0:
+ break;
+ case 1:
+ state = CONNECTED;
+ }
+ }
+ }
+ break;
+ case CONNECTED:
+ switch (i = api_exch_nextcommand()) {
+ case EXCH_CMD_REQUEST:
+ if (api_exch_intype(EXCH_TYPE_REGS, sizeof inputRegs,
+ (char *)&inputRegs) == -1) {
+ kill_connection();
+ } else if (api_exch_intype(EXCH_TYPE_SREGS, sizeof inputSregs,
+ (char *)&inputSregs) == -1) {
+ kill_connection();
+ } else if (nextstore() == -1) {
+ kill_connection();
+ } else {
+ handle_api(&inputRegs, &inputSregs);
+ freestorage(); /* Send any storage back */
+ if (api_exch_outcommand(EXCH_CMD_REPLY) == -1) {
+ kill_connection();
+ } else if (api_exch_outtype(EXCH_TYPE_REGS, sizeof inputRegs,
+ (char *)&inputRegs) == -1) {
+ kill_connection();
+ } else if (api_exch_outtype(EXCH_TYPE_SREGS, sizeof inputSregs,
+ (char *)&inputSregs) == -1) {
+ kill_connection();
+ }
+ /* Done, and it all worked! */
+ }
+ break;
+ case EXCH_CMD_DISASSOCIATE:
+ kill_connection();
+ break;
+ default:
+ if (i != -1) {
+ fprintf(stderr,
+ "Looking for a REQUEST or DISASSOCIATE command\n");
+ fprintf(stderr, "\treceived 0x%02x.\n", i);
+ }
+ kill_connection();
+ break;
+ }
+ }
+ return shell_active;
+}
+
+
+static void
+child_died(code)
+ int code;
+{
+ int pid, status;
+
+ while ((pid = waitpid((pid_t) -1, &status, WNOHANG)) > 0) {
+ if (pid == shell_pid) {
+ char inputbuffer[100];
+
+ shell_active = 0;
+ if (sock != -1) {
+ (void) close(sock);
+ sock = -1;
+ }
+ printf("[Hit return to continue]");
+ fflush(stdout);
+ (void) fgets(inputbuffer, sizeof(inputbuffer), stdin);
+ setconnmode(0);
+ ConnectScreen(); /* Turn screen on (if need be) */
+ (void) close(serversock);
+ (void) unlink(keyname);
+ }
+ }
+ signal(SIGCHLD, child_died);
+}
+
+
+/*
+ * Called from telnet.c to fork a lower command.com. We
+ * use the sprint... routines so that we can pick up
+ * interrupts generated by application programs.
+ */
+
+
+int
+shell(argc,argv)
+int argc;
+char *argv[];
+{
+ socklen_t length;
+ struct sockaddr_in server;
+ char sockNAME[128];
+ static char **whereAPI = 0;
+ int fd;
+ struct timeval tv;
+ long ikey;
+
+ /* First, create verification file. */
+#if defined(BSD4_4)
+ if (keyname != NULL)
+ free(keyname);
+ keyname = strdup("/tmp/apiXXXXXX");
+ fd = mkstemp(keyname);
+#else
+ do {
+ if (keyname != NULL)
+ free(keyname);
+ keyname = mktemp(strdup("/tmp/apiXXXXXX")); /* NetBSD: NOT USED */
+ fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE);
+ } while ((fd == -1) && (errno == EEXIST));
+#endif /* defined(BSD4_4) */
+
+ if (fd == -1) {
+ perror("open");
+ return 0;
+ }
+
+ /* Now, get seed for random */
+
+ if (gettimeofday(&tv, (struct timezone *)0) == -1) {
+ perror("gettimeofday");
+ return 0;
+ }
+ srandom(tv.tv_usec); /* seed random number generator */
+ do {
+ ikey = random();
+ } while (ikey == 0);
+ sprintf(key, "%lu\n", (unsigned long) ikey);
+ if (write(fd, key, strlen(key)) != strlen(key)) {
+ perror("write");
+ return 0;
+ }
+ key[strlen(key)-1] = 0; /* Get rid of newline */
+
+ if (close(fd) == -1) {
+ perror("close");
+ return 0;
+ }
+
+ /* Next, create the socket which will be connected to */
+ serversock = socket(AF_INET, SOCK_STREAM, 0);
+ if (serversock < 0) {
+ perror("opening API socket");
+ return 0;
+ }
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+ server.sin_port = 0;
+ if (bind(serversock, (struct sockaddr *)&server, sizeof server) < 0) {
+ perror("binding API socket");
+ return 0;
+ }
+ length = sizeof server;
+ if (getsockname(serversock, (struct sockaddr *)&server, &length) < 0) {
+ perror("getting API socket name");
+ (void) close(serversock);
+ }
+ listen(serversock, 1);
+ /* Get name to advertise in address list */
+ strcpy(sockNAME, "API3270=");
+ gethostname(sockNAME+strlen(sockNAME), sizeof sockNAME-strlen(sockNAME));
+ sockNAME[sizeof(sockNAME) - 1] = '\0';
+ if (strlen(sockNAME) > (sizeof sockNAME-(10+strlen(keyname)))) {
+ fprintf(stderr, "Local hostname too large; using 'localhost'.\n");
+ strcpy(sockNAME, "localhost");
+ }
+ sprintf(sockNAME+strlen(sockNAME), ":%u", ntohs(server.sin_port));
+ sprintf(sockNAME+strlen(sockNAME), ":%s", keyname);
+
+ if (whereAPI == 0) {
+ char **ptr, **nextenv;
+ extern char **environ;
+
+ ptr = environ;
+ nextenv = ourENVlist;
+ while (*ptr) {
+ if (nextenv >= &ourENVlist[highestof(ourENVlist)-1]) {
+ fprintf(stderr, "Too many environmental variables\n");
+ break;
+ }
+ *nextenv++ = *ptr++;
+ }
+ whereAPI = nextenv++;
+ *nextenv++ = 0;
+ environ = ourENVlist; /* New environment */
+ }
+ *whereAPI = sockNAME;
+
+ child_died(0); /* Start up signal handler */
+ shell_active = 1; /* We are running down below */
+ if ((shell_pid = vfork()) != 0) {
+ if (shell_pid == -1) {
+ perror("vfork");
+ (void) close(serversock);
+ } else {
+ state = UNCONNECTED;
+ }
+ } else { /* New process */
+ int i;
+
+ for (i = 3; i < 30; i++) {
+ (void) close(i);
+ }
+ if (argc == 1) { /* Just get a shell */
+ char *cmdname;
+
+ cmdname = getenv("SHELL");
+ execlp(cmdname, cmdname, NULL);
+ perror("Exec'ing new shell");
+ _exit(1);
+ } else {
+ execvp(argv[1], &argv[1]);
+ perror("Exec'ing command");
+ _exit(1);
+ }
+ /*NOTREACHED*/
+ }
+ return shell_active; /* Go back to main loop */
+}
diff --git a/comms/tn3270/files/sys_curses/telextrn.h b/comms/tn3270/files/sys_curses/telextrn.h
new file mode 100644
index 00000000000..31a88c8970a
--- /dev/null
+++ b/comms/tn3270/files/sys_curses/telextrn.h
@@ -0,0 +1,72 @@
+/* $NetBSD: telextrn.h,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $ */
+/* From NetBSD: telextrn.h,v 1.7 2003/08/07 11:16:37 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)telextrn.h 4.2 (Berkeley) 4/26/91
+ */
+
+/*
+ * Definitions of external routines and variables for tn3270
+ */
+
+/*
+ * Pieces exported from the telnet susbsection.
+ */
+
+extern int
+#if defined(unix)
+ HaveInput,
+#endif /* defined(unix) */
+ tout,
+ tin;
+
+extern char *transcom;
+
+/* system.c */
+void freestorage(void);
+void movetous(char *, unsigned int, unsigned int , int);
+void movetothem(unsigned int, unsigned int , char *, int);
+char *access_api(char *, int, int );
+void unaccess_api(char *, char *, int, int);
+int shell_continue(void);
+int shell(int, char *[]);
+
+/* termout.c */
+void init_screen(void);
+void InitTerminal(void);
+void StopScreen(int);
+void RefreshScreen(void);
+void ConnectScreen(void);
+void LocalClearScreen(void);
+void BellOff(void);
+void RingBell(char *);
+int DoTerminalOutput(void);
+void TransStop(void);
+void TransOut(unsigned char *, int, int, int);
diff --git a/comms/tn3270/files/sys_curses/terminal.h b/comms/tn3270/files/sys_curses/terminal.h
new file mode 100644
index 00000000000..e7482fbee4b
--- /dev/null
+++ b/comms/tn3270/files/sys_curses/terminal.h
@@ -0,0 +1,80 @@
+/* $NetBSD: terminal.h,v 1.1.1.1 2010/01/17 01:33:24 dholland Exp $ */
+/* From NetBSD: terminal.h,v 1.5 2003/08/07 11:16:37 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)terminal.h 4.3 (Berkeley) 4/26/91
+ */
+
+#define INCLUDED_TERMINAL
+
+/*
+ * In the situation where we have a copy of the terminal screen in front
+ * of us, here are some macros to deal with them.
+ */
+
+#define TermAttributes(x) (TermIsStartField(x)? GetTerminal(x)&0xff : \
+ GetTerminal(WhereTermAttrByte(x))&0xff)
+#define TermIsStartField(x) ((GetTerminal(x)&ATTR_MASK) == ATTR_MASK)
+#define TermNewField(p,a) SetTerminal(p, (a)|ATTR_MASK)
+#define TermDeleteField(p) SetTerminal(p, 0)
+#define TermIsNonDisplay(x) \
+ ((TermAttributes(x)&ATTR_DSPD_MASK) == ATTR_DSPD_NONDISPLAY)
+#define TermIsHighlighted(x) \
+ (((TermAttributes(x)&ATTR_DSPD_MASK) == ATTR_DSPD_HIGH) \
+ && !TermIsStartField(x))
+
+#define TerminalCharacterAttr(c,p,a) (IsNonDisplayAttr(a) ? ' ':c)
+#define TerminalCharacter(c,p) TerminalCharacterAttr(c,p,FieldAttributes(p))
+
+ /*
+ * Is the screen formatted? Some algorithms change depending
+ * on whether there are any attribute bytes lying around.
+ */
+#define TerminalFormattedScreen() \
+ ((WhereTermAttrByte(0) != 0) || ((GetTerminal(0)&ATTR_MASK) == ATTR_MASK))
+
+#define NeedToRedisplayFields(p) ((TermIsNonDisplay(p) != IsNonDisplay(p)) || \
+ (TermIsHighlighted(p) != IsHighlighted(p)))
+#define NeedToRedisplayFieldsAttr(p,c) ( \
+ (TermIsNonDisplay(p) != IsNonDisplayAttr(c)) || \
+ (TermIsHighlighted(p) != IsHighlightedAttr(c)))
+
+#define NotVisuallyCompatibleAttributes(p,c,d) ( \
+ (IsNonDisplayAttr(c) != IsNonDisplayAttr(d)) || \
+ (IsHighlightedAttr(c) != IsHighlightedAttr(d)))
+
+#define NeedToRedisplayAttr(c,p,a) \
+ ((c != GetTerminal(p)) || NeedToRedisplayFieldsAttr(p,a))
+#define NeedToRedisplay(c,p) NeedToRedisplayAttr(c,p,FieldAttributes(p))
+
+
+#define GetTerminal(i) GetGeneric(i, Terminal)
+#define GetTerminalPointer(p) GetGenericPointer(p)
+#define SetTerminal(i,c) SetGeneric(i,c,Terminal)
diff --git a/comms/tn3270/files/sys_curses/termout.c b/comms/tn3270/files/sys_curses/termout.c
new file mode 100644
index 00000000000..9fd3a7ff315
--- /dev/null
+++ b/comms/tn3270/files/sys_curses/termout.c
@@ -0,0 +1,948 @@
+/* $NetBSD: termout.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $ */
+/* From NetBSD: termout.c,v 1.15 2007/01/17 00:21:44 hubertf Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)termout.c 4.3 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: termout.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#if defined(unix)
+#include <signal.h>
+#include <termios.h>
+#include <unistd.h>
+#ifdef __NetBSD__
+#include <termcap.h>
+#else
+extern char *tgetstr(char *, char **);
+#endif
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <curses.h>
+#if defined(ultrix)
+/* Some version of this OS has a bad definition for nonl() */
+#undef nl
+#undef nonl
+
+#define nl() (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty))
+#define nonl() (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty))
+#endif /* defined(ultrix) */
+
+#include "../general/general.h"
+
+#include "terminal.h"
+
+#include "../api/disp_asc.h"
+
+#include "../ctlr/hostctlr.h"
+#include "../ctlr/declare.h"
+#include "../ctlr/oia.h"
+#include "../ctlr/screen.h"
+#include "../ctlr/scrnctlr.h"
+
+#include "../ascii/state.h"
+#include "../ascii/map3270.h"
+
+#include "../general/globals.h"
+
+#include "telextrn.h"
+#include "externs.h"
+
+extern int TransparentClock, OutputClock;
+
+#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \
+ CursorAddress:UnLocked? CursorAddress: HighestScreen())
+
+
+static int terminalCursorAddress; /* where the cursor is on term */
+static int screenInitd; /* the screen has been initialized */
+static int screenStopped; /* the screen has been stopped */
+static int max_changes_before_poll; /* how many characters before looking */
+ /* at terminal and net again */
+
+static int needToRing; /* need to ring terinal bell */
+static char bellSequence[1024]; /* bell sequence */
+static WINDOW *bellwin = 0; /* The window the bell message is in */
+int bellwinup = 0; /* Are we up with it or not */
+
+
+static int inHighlightMode = 0;
+ScreenImage Terminal[MAXSCREENSIZE];
+
+/* Variables for transparent mode */
+#if defined(unix)
+static int tcflag = -1; /* transparent mode command flag */
+static int savefd[2]; /* for storing fds during transcom */
+extern int tin, tout; /* file descriptors */
+
+static void aborttc(int);
+#endif /* defined(unix) */
+
+static void OurExitString(char *, int);
+static void DoARefresh(void);
+static void GoAway(char *, int);
+static int WhereTermAttrByte(int);
+static void SlowScreen(void);
+static void FastScreen(void);
+#if 0
+static void ScreenOIA(OIA *);
+#endif
+
+
+/*
+ * init_screen()
+ *
+ * Initialize variables used by screen.
+ */
+
+void
+init_screen()
+{
+ bellwinup = 0;
+ inHighlightMode = 0;
+ ClearArray(Terminal);
+}
+
+
+/* OurExitString - designed to keep us from going through infinite recursion */
+
+static void
+OurExitString(string, value)
+char *string;
+int value;
+{
+ static int recursion = 0;
+
+ if (!recursion) {
+ recursion = 1;
+ ExitString(string, value);
+ }
+}
+
+
+/* DoARefresh */
+
+static void
+DoARefresh()
+{
+ if (ERR == refresh()) {
+ OurExitString("ERR from refresh\n", 1);
+ }
+}
+
+static void
+GoAway(from, where)
+char *from; /* routine that gave error */
+int where; /* cursor address */
+{
+ char foo[100];
+
+ sprintf(foo, "ERR from %s at %d (%d, %d)\n",
+ from, where, ScreenLine(where), ScreenLineOffset(where));
+ OurExitString(foo, 1);
+ /* NOTREACHED */
+}
+
+/* What is the screen address of the attribute byte for the terminal */
+
+static int
+WhereTermAttrByte(p)
+int p;
+{
+ int i;
+
+ i = p;
+
+ do {
+ if (TermIsStartField(i)) {
+ return(i);
+ }
+ i = ScreenDec(i);
+ } while (i != p);
+
+ return(LowestScreen()); /* unformatted screen... */
+}
+
+/*
+ * There are two algorithms for updating the screen.
+ * The first, SlowScreen() optimizes the line between the
+ * computer and the screen (say a 9600 baud line). To do
+ * this, we break out of the loop every so often to look
+ * at any pending input from the network (so that successive
+ * screens will only partially print until the final screen,
+ * the one the user possibly wants to see, is displayed
+ * in its entirety).
+ *
+ * The second algorithm tries to optimize CPU time (by
+ * being simpler) at the cost of the bandwidth to the
+ * screen.
+ *
+ * Of course, curses(3X) gets in here also.
+ */
+
+
+#if defined(NOT43)
+static int
+#else /* defined(NOT43) */
+static void
+#endif /* defined(NOT43) */
+SlowScreen()
+{
+ int is, shouldbe, isattr, shouldattr;
+ int pointer;
+ int fieldattr, termattr;
+ int columnsleft;
+
+#define NORMAL 0
+#define HIGHLIGHT 1 /* Mask bits */
+#define NONDISPLAY 4 /* Mask bits */
+#define UNDETERMINED 8 /* Mask bits */
+
+#define DoAttributes(x) \
+ switch (x&ATTR_DSPD_MASK) { \
+ case ATTR_DSPD_NONDISPLAY: \
+ x = NONDISPLAY; \
+ break; \
+ case ATTR_DSPD_HIGH: \
+ x = HIGHLIGHT; \
+ break; \
+ default: \
+ x = 0; \
+ break; \
+ }
+
+# define SetHighlightMode(x) \
+ { \
+ if ((x)&HIGHLIGHT) { \
+ if (!inHighlightMode) { \
+ inHighlightMode = HIGHLIGHT; \
+ standout(); \
+ } \
+ } else { \
+ if (inHighlightMode) { \
+ inHighlightMode = 0; \
+ standend(); \
+ } \
+ } \
+ }
+
+# define DoCharacterAt(c,p) { \
+ if (p != HighestScreen()) { \
+ c = disp_asc[c&0xff]; \
+ if (terminalCursorAddress != p) { \
+ if (ERR == mvaddch(ScreenLine(p), \
+ ScreenLineOffset(p), c)) {\
+ GoAway("mvaddch", p); \
+ } \
+ } else { \
+ if (ERR == addch(c)) {\
+ GoAway("addch", p); \
+ } \
+ } \
+ terminalCursorAddress = ScreenInc(p); \
+ } \
+ }
+
+
+ /* run through screen, printing out non-null lines */
+
+ /* There are two separate reasons for wanting to terminate this
+ * loop early. One is to respond to new input (either from
+ * the terminal or from the network [host]). For this reason,
+ * we expect to see 'HaveInput' come true when new input comes in.
+ *
+ * The second reason is a bit more difficult (for me) to understand.
+ * Basically, we don't want to get too far ahead of the characters that
+ * appear on the screen. Ideally, we would type out a few characters,
+ * wait until they appeared on the screen, then type out a few more.
+ * The reason for this is that the user, on seeing some characters
+ * appear on the screen may then start to type something. We would
+ * like to look at what the user types at about the same 'time'
+ * (measured by characters being sent to the terminal) that the
+ * user types them. For this reason, what we would like to do
+ * is update a bit, then call curses to do a refresh, flush the
+ * output to the terminal, then wait until the terminal data
+ * has been sent.
+ *
+ * Note that curses is useful for, among other things, deciding whether
+ * or not to send :ce: (clear to end of line), so we should call curses
+ * at end of lines (beginning of next lines).
+ *
+ * The problems here are the following: If we do lots of write(2)s,
+ * we will be doing lots of context switches, thus lots of overhead
+ * (which we have already). Second, if we do a select to wait for
+ * the output to drain, we have to contend with the fact that NOW
+ * we are scheduled to run, but who knows what the scheduler will
+ * decide when the output has caught up.
+ */
+
+ if (Highest >= HighestScreen()) { /* Could be > if screen shrunk... */
+ Highest = ScreenDec(Highest); /* else, while loop will never end */
+ }
+ if (Lowest < LowestScreen()) {
+ Lowest = LowestScreen(); /* could be -1 in some cases with
+ * unformatted screens.
+ */
+ }
+ if (Highest >= (pointer = Lowest)) {
+ /* if there is anything to do, do it. We won't terminate
+ * the loop until we've gone at least to Highest.
+ */
+ while ((pointer <= Highest) && !HaveInput) {
+
+ /* point at the next place of disagreement */
+ pointer += (bunequal(Host+pointer, Terminal+pointer,
+ (Highest-pointer+1)*sizeof Host[0])/sizeof Host[0]);
+
+ /*
+ * How many characters to change until the end of the
+ * current line
+ */
+ columnsleft = NumberColumns - ScreenLineOffset(pointer);
+ /*
+ * Make sure we are where we think we are.
+ */
+ move(ScreenLine(pointer), ScreenLineOffset(pointer));
+
+ /* what is the field attribute of the current position */
+ if (FormattedScreen()) {
+ fieldattr = FieldAttributes(pointer);
+ DoAttributes(fieldattr);
+ } else {
+ fieldattr = NORMAL;
+ }
+ if (TerminalFormattedScreen()) {
+ termattr = TermAttributes(pointer);
+ DoAttributes(termattr);
+ } else {
+ termattr = NORMAL;
+ }
+
+ SetHighlightMode(fieldattr);
+ /*
+ * The following will terminate at least when we get back
+ * to the original 'pointer' location (since we force
+ * things to be equal).
+ */
+ for (;;) {
+ if (IsStartField(pointer)) {
+ shouldbe = DISP_BLANK;
+ shouldattr = 0;
+ fieldattr = GetHost(pointer);
+ DoAttributes(fieldattr);
+ } else {
+ if (fieldattr&NONDISPLAY) {
+ shouldbe = DISP_BLANK;
+ } else {
+ shouldbe = GetHost(pointer);
+ }
+ shouldattr = fieldattr;
+ }
+ if (TermIsStartField(pointer)) {
+ is = DISP_BLANK;
+ isattr = 0;
+ termattr = UNDETERMINED; /* Need to find out AFTER update */
+ } else {
+ if (termattr&NONDISPLAY) {
+ is = DISP_BLANK;
+ } else {
+ is = GetTerminal(pointer);
+ }
+ isattr = termattr;
+ }
+ if ((shouldbe == is) && (shouldattr == isattr)
+ && (GetHost(pointer) == GetTerminal(pointer))
+ && (GetHost(ScreenInc(pointer))
+ == GetTerminal(ScreenInc(pointer)))) {
+ break;
+ }
+
+ if (shouldattr^inHighlightMode) {
+ SetHighlightMode(shouldattr);
+ }
+
+ DoCharacterAt(shouldbe, pointer);
+ if (IsStartField(pointer)) {
+ TermNewField(pointer, FieldAttributes(pointer));
+ termattr = GetTerminal(pointer);
+ DoAttributes(termattr);
+ } else {
+ SetTerminal(pointer, GetHost(pointer));
+ /*
+ * If this USED to be a start field location,
+ * recompute the terminal attributes.
+ */
+ if (termattr == UNDETERMINED) {
+ termattr = WhereTermAttrByte(pointer);
+ if ((termattr != 0) || TermIsStartField(0)) {
+ termattr = GetTerminal(termattr);
+ DoAttributes(termattr);
+ } else { /* Unformatted screen */
+ termattr = NORMAL;
+ }
+ }
+ }
+ pointer = ScreenInc(pointer);
+ if (!(--columnsleft)) {
+ DoARefresh();
+ EmptyTerminal();
+ if (HaveInput) { /* if input came in, take it */
+ int c, j;
+
+ /*
+ * We need to start a new terminal field
+ * at this location iff the terminal attributes
+ * of this location are not what we have had
+ * them as (ie: we've overwritten the terminal
+ * start field, a the previous field had different
+ * display characteristics).
+ */
+
+ isattr = TermAttributes(pointer);
+ DoAttributes(isattr);
+ if ((!TermIsStartField(pointer)) &&
+ (isattr != termattr)) {
+ /*
+ * Since we are going to leave a new field
+ * at this terminal position, we
+ * need to make sure that we get an actual
+ * non-highlighted blank on the screen.
+ */
+ if ((is != DISP_BLANK) || (termattr&HIGHLIGHT)) {
+ SetHighlightMode(0); /* Turn off highlight */
+ c = ScreenInc(pointer);
+ j = DISP_BLANK;
+ DoCharacterAt(j, c);
+ }
+ if (termattr&HIGHLIGHT) {
+ termattr = ATTR_DSPD_HIGH;
+ } else if (termattr&NONDISPLAY) {
+ termattr = ATTR_DSPD_NONDISPLAY;
+ } else {
+ termattr = 0;
+ }
+ TermNewField(pointer, termattr);
+ }
+ break;
+ }
+ move(ScreenLine(pointer), 0);
+ columnsleft = NumberColumns;
+ }
+ } /* end of for (;;) */
+ } /* end of while (...) */
+ }
+ DoARefresh();
+ Lowest = pointer;
+ if (Lowest > Highest) { /* if we finished input... */
+ Lowest = HighestScreen()+1;
+ Highest = LowestScreen()-1;
+ terminalCursorAddress = CorrectTerminalCursor();
+ if (ERR == move(ScreenLine(terminalCursorAddress),
+ ScreenLineOffset(terminalCursorAddress))) {
+ GoAway("move", terminalCursorAddress);
+ }
+ DoARefresh();
+ if (needToRing) {
+ StringToTerminal(bellSequence);
+ needToRing = 0;
+ }
+ }
+ EmptyTerminal(); /* move data along */
+ return;
+}
+
+#if defined(NOT43)
+static int
+#else /* defined(NOT43) */
+static void
+#endif /* defined(NOT43) */
+FastScreen()
+{
+#if defined(MSDOS)
+#define SaveCorner 0
+#else /* defined(MSDOS) */
+#define SaveCorner 1
+#endif /* defined(MSDOS) */
+
+#define DoAttribute(a) if (IsHighlightedAttr(a)) { \
+ standout(); \
+ } else { \
+ standend(); \
+ } \
+ if (IsNonDisplayAttr(a)) { \
+ a = 0; /* zero == don't display */ \
+ } \
+ if (!FormattedScreen()) { \
+ a = 1; /* one ==> do display on unformatted */\
+ }
+ ScreenImage *p, *upper;
+ int fieldattr; /* spends most of its time == 0 or 1 */
+
+/* OK. We want to do this a quickly as possible. So, we assume we
+ * only need to go from Lowest to Highest. However, if we find a
+ * field in the middle, we do the whole screen.
+ *
+ * In particular, we separate out the two cases from the beginning.
+ */
+ if ((Highest != HighestScreen()) || (Lowest != LowestScreen())) {
+ int columnsleft;
+
+ move(ScreenLine(Lowest), ScreenLineOffset(Lowest));
+ p = &Host[Lowest];
+#if !defined(MSDOS)
+ if (Highest == HighestScreen()) {
+ Highest = ScreenDec(Highest);
+ }
+#endif /* !defined(MSDOS) */
+ upper = &Host[Highest];
+ fieldattr = FieldAttributes(Lowest);
+ DoAttribute(fieldattr); /* Set standout, non-display status */
+ columnsleft = NumberColumns-ScreenLineOffset(p-Host);
+
+ while (p <= upper) {
+ if (IsStartFieldPointer(p)) { /* New field? */
+ Highest = HighestScreen();
+ Lowest = LowestScreen();
+ FastScreen(); /* Recurse */
+ return;
+ } else if (fieldattr) { /* Should we display? */
+ /* Display translated data */
+ addch((char)disp_asc[GetTerminalPointer(p)]);
+ } else {
+ addch(' '); /* Display a blank */
+ }
+ /* If the physical screen is larger than what we
+ * are using, we need to make sure that each line
+ * starts at the beginning of the line. Otherwise,
+ * we will just string all the lines together.
+ */
+ p++;
+ if (--columnsleft == 0) {
+ int i = p-Host;
+
+ move(ScreenLine(i), 0);
+ columnsleft = NumberColumns;
+ }
+ }
+ } else { /* Going from Lowest to Highest */
+ unsigned char tmpbuf[MAXNUMBERCOLUMNS+1];
+ ScreenImage *End = &Host[ScreenSize]-1-SaveCorner;
+ unsigned char *tmp = tmpbuf, *tmpend = tmpbuf+NumberColumns;
+
+ *tmpend = 0; /* terminate from the beginning */
+ move(0,0);
+ p = Host;
+ fieldattr = FieldAttributes(LowestScreen());
+ DoAttribute(fieldattr); /* Set standout, non-display status */
+
+ while (p <= End) {
+ if (IsStartFieldPointer(p)) { /* New field? */
+ if (tmp != tmpbuf) {
+ *tmp++ = 0; /* close out */
+ addstr((char *)tmpbuf);
+ tmp = tmpbuf;
+ tmpend = tmpbuf+NumberColumns-ScreenLineOffset(p-Host)-1;
+ }
+ standend();
+ addch(' ');
+ fieldattr = FieldAttributesPointer(p); /* Get attributes */
+ DoAttribute(fieldattr); /* Set standout, non-display */
+ } else {
+ if (fieldattr) { /* Should we display? */
+ /* Display translated data */
+ *tmp++ = disp_asc[GetTerminalPointer(p)];
+ } else {
+ *tmp++ = ' ';
+ }
+ }
+ /* If the physical screen is larger than what we
+ * are using, we need to make sure that each line
+ * starts at the beginning of the line. Otherwise,
+ * we will just string all the lines together.
+ */
+ p++;
+ if (tmp == tmpend) {
+ int i = p-Host; /* Be sure the "p++" happened first! */
+
+ *tmp++ = 0;
+ addstr((char *)tmpbuf);
+ tmp = tmpbuf;
+ move(ScreenLine(i), 0);
+ tmpend = tmpbuf + NumberColumns;
+ }
+ }
+ if (tmp != tmpbuf) {
+ *tmp++ = 0;
+ addstr((char *)tmpbuf);
+ tmp = tmpbuf;
+ }
+ }
+ Lowest = HighestScreen()+1;
+ Highest = LowestScreen()-1;
+ terminalCursorAddress = CorrectTerminalCursor();
+ if (ERR == move(ScreenLine(terminalCursorAddress),
+ ScreenLineOffset(terminalCursorAddress))) {
+ GoAway("move", terminalCursorAddress);
+ }
+ DoARefresh();
+ if (needToRing) {
+ StringToTerminal(bellSequence);
+ needToRing = 0;
+ }
+ EmptyTerminal(); /* move data along */
+ return;
+}
+
+
+/* TryToSend - send data out to user's terminal */
+
+#if defined(NOT43)
+int
+#else /* defined(NOT43) */
+void
+#endif /* defined(NOT43) */
+ (*TryToSend)(void) = FastScreen;
+
+#if 0
+/*ARGSUSED*/
+static void
+ScreenOIA(oia)
+OIA *oia;
+{
+}
+#endif
+
+
+/* InitTerminal - called to initialize the screen, etc. */
+
+void
+InitTerminal()
+{
+#if defined(unix)
+ struct termios term;
+ speed_t speed;
+#endif
+ char termbuf[1024];
+ char *bsp;
+
+ InitMapping(); /* Go do mapping file (MAP3270) first */
+ if (!screenInitd) { /* not initialized */
+ if (initscr() == NULL) { /* Initialize curses to get line size */
+ ExitString("InitTerminal: Error initializing curses", 1);
+ /*NOTREACHED*/
+ }
+ MaxNumberLines = LINES;
+ MaxNumberColumns = COLS;
+ ClearArray(Terminal);
+ terminalCursorAddress = SetBufferAddress(0,0);
+#if defined(unix)
+ signal(SIGHUP, (void (*)(int))abort);
+#endif
+
+ TryToSend = FastScreen;
+#if defined(unix)
+ tcgetattr(1, &term);
+ speed = cfgetospeed(&term);
+ if ((speed < 0) || (speed > 9600)) {
+ max_changes_before_poll = 1920;
+ } else {
+ max_changes_before_poll = speed/10;
+ if (max_changes_before_poll < 40) {
+ max_changes_before_poll = 40;
+ }
+ TryToSend = SlowScreen;
+ HaveInput = 1; /* get signals going */
+ }
+#endif /* defined(unix) */
+ setcommandmode();
+#if defined(unix)
+ nonl();
+#endif
+ DoARefresh();
+ setconnmode(0);
+ if (tgetent(termbuf, getenv("TERM")) == 1) {
+ bsp = bellSequence;
+ if ((bsp = tgetstr("vb", &bsp)) == NULL) { /* use visual bell */
+ bsp = bellSequence;
+ if ((bsp = tgetstr("bl", &bsp)) == NULL) {
+ strcpy (bellSequence, "\07");
+ }
+ }
+ }
+ screenInitd = 1;
+ screenStopped = 0; /* Not stopped */
+ }
+}
+
+
+/* StopScreen - called when we are going away... */
+
+void
+StopScreen(doNewLine)
+int doNewLine;
+{
+ if (screenInitd && !screenStopped) {
+ move(NumberLines-1, 1);
+ standend();
+ inHighlightMode = 0;
+ DoARefresh();
+ endwin();
+ setcommandmode();
+ setconnmode(0);
+ if (doNewLine) {
+ StringToTerminal("\r\n");
+ }
+ EmptyTerminal();
+ screenStopped = 1; /* This is stopped */
+ }
+}
+
+
+/* RefreshScreen - called to cause the screen to be refreshed */
+
+void
+RefreshScreen()
+{
+ clearok(curscr, TRUE);
+ (*TryToSend)();
+}
+
+
+/* ConnectScreen - called to reconnect to the screen */
+
+void
+ConnectScreen()
+{
+ if (screenInitd) {
+ RefreshScreen();
+ (*TryToSend)();
+ screenStopped = 0;
+ }
+}
+
+/* LocalClearScreen() - clear the whole ball of wax, cheaply */
+
+void
+LocalClearScreen()
+{
+ outputPurge(); /* flush all data to terminal */
+ clear(); /* clear in curses */
+ ClearArray(Terminal);
+ Clear3270();
+ Lowest = HighestScreen()+1; /* everything in sync... */
+ Highest = LowestScreen()+1;
+}
+
+
+void
+BellOff()
+{
+ if (bellwinup) {
+ delwin(bellwin);
+ bellwin = 0;
+ bellwinup = 0;
+ touchwin(stdscr);
+ DoARefresh();
+ }
+}
+
+
+void
+RingBell(s)
+char *s;
+{
+ needToRing = 1;
+ if (s) {
+ int len = strlen(s);
+
+ if (len > COLS-2) {
+ len = COLS-2;
+ }
+ if ((bellwin = newwin(3, len+2, LINES/2, 0)) == NULL) {
+ OurExitString("Error from newwin in RingBell", 1);
+ }
+ werase(bellwin);
+ wstandout(bellwin);
+ box(bellwin, '|', '-');
+ if (wmove(bellwin, 1, 1) == ERR) {
+ OurExitString("Error from wmove in RingBell", 1);
+ }
+ while (len--) {
+ if (waddch(bellwin, *s++) == ERR) {
+ OurExitString("Error from waddch in RingBell", 1);
+ }
+ }
+ wstandend(bellwin);
+ if (wrefresh(bellwin) == ERR) {
+ OurExitString("Error from wrefresh in RingBell", 1);
+ }
+ bellwinup = 1;
+ }
+}
+
+
+/* returns a 1 if no more output available (so, go ahead and block),
+ or a 0 if there is more output available (so, just poll the other
+ sources/destinations, don't block).
+ */
+
+int
+DoTerminalOutput()
+{
+ /* called just before a select to conserve IO to terminal */
+ if (!(screenInitd||screenStopped)) {
+ return 1; /* No output if not initialized */
+ }
+ if ((Lowest <= Highest) || needToRing ||
+ (terminalCursorAddress != CorrectTerminalCursor())) {
+ (*TryToSend)();
+ }
+ if (Lowest > Highest) {
+ return 1; /* no more output now */
+ } else {
+ return 0; /* more output for future */
+ }
+}
+
+/*
+ * The following are defined to handle transparent data.
+ */
+
+void
+TransStop()
+{
+#if defined(unix)
+ if (tcflag == 0) {
+ tcflag = -1;
+ (void) signal(SIGCHLD, SIG_DFL);
+ } else if (tcflag > 0) {
+ setcommandmode();
+ (void) close(tin);
+ (void) close(tout);
+ tin = savefd[0];
+ tout = savefd[1];
+ setconnmode(0);
+ tcflag = -1;
+ (void) signal(SIGCHLD, SIG_DFL);
+ }
+#endif /* defined(unix) */
+ RefreshScreen();
+}
+
+void
+TransOut(buffer, count, kind, control)
+unsigned char *buffer;
+int count;
+int kind; /* 0 or 5 */
+int control; /* To see if we are done */
+{
+#if defined(unix)
+ extern char *transcom;
+ int inpipefd[2], outpipefd[2];
+#endif /* defined(unix) */
+
+ while (DoTerminalOutput() == 0) {
+#if defined(unix)
+ HaveInput = 0;
+#endif /* defined(unix) */
+ }
+#if defined(unix)
+ if (transcom && tcflag == -1) {
+ while (1) { /* go thru once */
+ if (pipe(outpipefd) < 0) {
+ break;
+ }
+ if (pipe(inpipefd) < 0) {
+ break;
+ }
+ if ((tcflag = fork()) == 0) {
+ (void) close(outpipefd[1]);
+ (void) close(0);
+ if (dup(outpipefd[0]) < 0) {
+ exit(1);
+ }
+ (void) close(outpipefd[0]);
+ (void) close(inpipefd[0]);
+ (void) close(1);
+ if (dup(inpipefd[1]) < 0) {
+ exit(1);
+ }
+ (void) close(inpipefd[1]);
+ if (execl("/bin/csh", "csh", "-c", transcom, (char *) 0)) {
+ exit(1);
+ }
+ }
+ (void) close(inpipefd[1]);
+ (void) close(outpipefd[0]);
+ savefd[0] = tin;
+ savefd[1] = tout;
+ setcommandmode();
+ tin = inpipefd[0];
+ tout = outpipefd[1];
+ (void) signal(SIGCHLD, aborttc);
+ setconnmode(0);
+ tcflag = 1;
+ break;
+ }
+ if (tcflag < 1) {
+ tcflag = 0;
+ }
+ }
+#endif /* defined(unix) */
+ (void) DataToTerminal((char *)buffer, count);
+ if (control && (kind == 0)) { /* Send in AID byte */
+ SendToIBM();
+ } else {
+ TransInput(1, kind); /* Go get some data */
+ }
+}
+
+
+#if defined(unix)
+static void
+aborttc(n)
+ int n;
+{
+ setcommandmode();
+ (void) close(tin);
+ (void) close(tout);
+ tin = savefd[0];
+ tout = savefd[1];
+ setconnmode(0);
+ tcflag = 0;
+}
+#endif /* defined(unix) */
diff --git a/comms/tn3270/files/telnet/commands.c b/comms/tn3270/files/telnet/commands.c
new file mode 100644
index 00000000000..b83e860a973
--- /dev/null
+++ b/comms/tn3270/files/telnet/commands.c
@@ -0,0 +1,2906 @@
+/* $NetBSD: commands.c,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $ */
+/* From NetBSD: commands.c,v 1.67 2006/12/18 14:18:40 christos Exp */
+
+/*
+ * Copyright (C) 1997 and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: commands.c,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+#include <arpa/telnet.h>
+
+#include "general.h"
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+#include "types.h"
+#include <libtelnet/misc.h>
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#endif
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+
+#if defined(IPPROTO_IP) && defined(IP_TOS)
+int tos = -1;
+#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+char *hostname;
+static char _hostname[MAXHOSTNAMELEN];
+
+typedef struct {
+ char *name; /* command name */
+ char *help; /* help string (NULL for no help) */
+ int (*handler) /* routine which executes command */
+ (int, char *[]);
+ int needconnect; /* Do we need to be connected to execute? */
+} Command;
+
+static char line[256];
+static char saveline[256];
+static int margc;
+static char *margv[20];
+
+static void makeargv(void);
+static int special(char *);
+static char *control(cc_t);
+static int sendcmd(int, char **);
+static int send_esc(char *);
+static int send_docmd(char *);
+static int send_dontcmd(char *);
+static int send_willcmd(char *);
+static int send_wontcmd(char *);
+static int send_help(char *);
+static int lclchars(int);
+static int togdebug(int);
+static int togcrlf(int);
+static int togbinary(int);
+static int togrbinary(int);
+static int togxbinary(int);
+static int togglehelp(int);
+static void settogglehelp(int);
+static int toggle(int, char *[]);
+static struct setlist *getset(char *);
+static int setcmd(int, char *[]);
+static int unsetcmd(int, char *[]);
+static int dokludgemode(int);
+static int dolinemode(int);
+static int docharmode(int);
+static int dolmmode(int, int );
+static int modecmd(int, char *[]);
+static int display(int, char *[]);
+static int setescape(int, char *[]);
+static int togcrmod(int, char *[]);
+static int bye(int, char *[]);
+static void slc_help(int);
+static struct slclist *getslc(char *);
+static int slccmd(int, char *[]);
+static struct env_lst *env_help(unsigned char *, unsigned char *);
+static struct envlist *getenvcmd(char *);
+#ifdef AUTHENTICATION
+static int auth_help(char *);
+#endif
+#ifdef TN3270
+static void filestuff(int);
+#endif
+static int status(int, char *[]);
+static const char *sockaddr_ntop (struct sockaddr *);
+typedef int (*intrtn_t)(int, char **);
+static int call(intrtn_t, ...);
+static Command *getcmd(char *);
+static int help(int, char *[]);
+
+static void
+makeargv(void)
+{
+ char *cp, *cp2, c;
+ char **argp = margv;
+
+ margc = 0;
+ cp = line;
+ if (*cp == '!') { /* Special case shell escape */
+ strlcpy(saveline, line, sizeof(saveline)); /* save for shell command */
+ *argp++ = "!"; /* No room in string to get this */
+ margc++;
+ cp++;
+ }
+ while ((c = *cp) != '\0') {
+ int inquote = 0;
+ while (isspace((unsigned char)c))
+ c = *++cp;
+ if (c == '\0')
+ break;
+ *argp++ = cp;
+ margc += 1;
+ for (cp2 = cp; c != '\0'; c = *++cp) {
+ if (inquote) {
+ if (c == inquote) {
+ inquote = 0;
+ continue;
+ }
+ } else {
+ if (c == '\\') {
+ if ((c = *++cp) == '\0')
+ break;
+ } else if (c == '"') {
+ inquote = '"';
+ continue;
+ } else if (c == '\'') {
+ inquote = '\'';
+ continue;
+ } else if (isspace((unsigned char)c))
+ break;
+ }
+ *cp2++ = c;
+ }
+ *cp2 = '\0';
+ if (c == '\0')
+ break;
+ cp++;
+ }
+ *argp++ = 0;
+}
+
+/*
+ * Make a character string into a number.
+ *
+ * Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
+ */
+
+static int
+special(char *s)
+{
+ char c;
+ char b;
+
+ switch (*s) {
+ case '^':
+ b = *++s;
+ if (b == '?') {
+ c = b | 0x40; /* DEL */
+ } else {
+ c = b & 0x1f;
+ }
+ break;
+ default:
+ c = *s;
+ break;
+ }
+ return c;
+}
+
+/*
+ * Construct a control character sequence
+ * for a special character.
+ */
+static char *
+control(cc_t c)
+{
+ static char buf[5];
+ /*
+ * The only way I could get the Sun 3.5 compiler
+ * to shut up about
+ * if ((unsigned int)c >= 0x80)
+ * was to assign "c" to an unsigned int variable...
+ * Arggg....
+ */
+ unsigned int uic = (unsigned int)c;
+
+ if (uic == 0x7f)
+ return ("^?");
+ if (c == (cc_t)_POSIX_VDISABLE) {
+ return "off";
+ }
+ if (uic >= 0x80) {
+ buf[0] = '\\';
+ buf[1] = ((c>>6)&07) + '0';
+ buf[2] = ((c>>3)&07) + '0';
+ buf[3] = (c&07) + '0';
+ buf[4] = 0;
+ } else if (uic >= 0x20) {
+ buf[0] = c;
+ buf[1] = 0;
+ } else {
+ buf[0] = '^';
+ buf[1] = '@'+c;
+ buf[2] = 0;
+ }
+ return (buf);
+}
+
+
+
+/*
+ * The following are data structures and routines for
+ * the "send" command.
+ *
+ */
+
+struct sendlist {
+ char *name; /* How user refers to it (case independent) */
+ char *help; /* Help information (0 ==> no help) */
+ int needconnect; /* Need to be connected */
+ int narg; /* Number of arguments */
+ int (*handler) /* Routine to perform (for special ops) */
+ (char *);
+ int nbyte; /* Number of bytes to send this command */
+ int what; /* Character to be sent (<0 ==> special) */
+};
+
+
+static struct sendlist Sendlist[] = {
+ { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO },
+ { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT },
+ { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK },
+ { "break", 0, 1, 0, 0, 2, BREAK },
+ { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC },
+ { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL },
+ { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 },
+ { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA },
+ { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP },
+ { "intp", 0, 1, 0, 0, 2, IP },
+ { "interrupt", 0, 1, 0, 0, 2, IP },
+ { "intr", 0, 1, 0, 0, 2, IP },
+ { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP },
+ { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR },
+ { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT },
+ { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP },
+ { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF },
+ { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 },
+ { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 },
+ { "?", "Display send options", 0, 0, send_help, 0, 0 },
+ { "help", 0, 0, 0, send_help, 0, 0 },
+ { "do", 0, 0, 1, send_docmd, 3, 0 },
+ { "dont", 0, 0, 1, send_dontcmd, 3, 0 },
+ { "will", 0, 0, 1, send_willcmd, 3, 0 },
+ { "wont", 0, 0, 1, send_wontcmd, 3, 0 },
+ { 0 }
+};
+
+#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
+ sizeof(struct sendlist)))
+
+static int
+sendcmd(int argc, char **argv)
+{
+ int count; /* how many bytes we are going to need to send */
+ int i;
+ struct sendlist *s; /* pointer to current command */
+ int success = 0;
+ int needconnect = 0;
+
+ if (argc < 2) {
+ printf("need at least one argument for 'send' command\n");
+ printf("'send ?' for help\n");
+ return 0;
+ }
+ /*
+ * First, validate all the send arguments.
+ * In addition, we see how much space we are going to need, and
+ * whether or not we will be doing a "SYNCH" operation (which
+ * flushes the network queue).
+ */
+ count = 0;
+ for (i = 1; i < argc; i++) {
+ s = GETSEND(argv[i]);
+ if (s == 0) {
+ printf("Unknown send argument '%s'\n'send ?' for help.\n",
+ argv[i]);
+ return 0;
+ } else if (Ambiguous(s)) {
+ printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
+ argv[i]);
+ return 0;
+ }
+ if (i + s->narg >= argc) {
+ fprintf(stderr,
+ "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n",
+ s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
+ return 0;
+ }
+ count += s->nbyte;
+ if (s->handler == send_help) {
+ send_help(NULL);
+ return 0;
+ }
+
+ i += s->narg;
+ needconnect += s->needconnect;
+ }
+ if (!connected && needconnect) {
+ printf("?Need to be connected first.\n");
+ printf("'send ?' for help\n");
+ return 0;
+ }
+ /* Now, do we have enough room? */
+ if (NETROOM() < count) {
+ printf("There is not enough room in the buffer TO the network\n");
+ printf("to process your request. Nothing will be done.\n");
+ printf("('send synch' will throw away most data in the network\n");
+ printf("buffer, if this might help.)\n");
+ return 0;
+ }
+ /* OK, they are all OK, now go through again and actually send */
+ count = 0;
+ for (i = 1; i < argc; i++) {
+ if ((s = GETSEND(argv[i])) == 0) {
+ fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
+ (void) quit(0, NULL);
+ /*NOTREACHED*/
+ }
+ if (s->handler) {
+ count++;
+ success += (*s->handler)(argv[i+1]);
+ i += s->narg;
+ } else {
+ NET2ADD(IAC, s->what);
+ printoption("SENT", IAC, s->what);
+ }
+ }
+ return (count == success);
+}
+
+static int
+send_esc(char *s)
+{
+ NETADD(escape);
+ return 1;
+}
+
+static int
+send_docmd(char *name)
+{
+ return(send_tncmd(send_do, "do", name));
+}
+
+static int
+send_dontcmd(char *name)
+{
+ return(send_tncmd(send_dont, "dont", name));
+}
+static int
+send_willcmd(char *name)
+{
+ return(send_tncmd(send_will, "will", name));
+}
+static int
+send_wontcmd(char *name)
+{
+ return(send_tncmd(send_wont, "wont", name));
+}
+
+int
+send_tncmd(void (*func)(int, int), char *cmd, char *name)
+{
+ const char **cpp;
+ int val = 0;
+
+ if (isprefix(name, "?")) {
+ int col, len;
+
+ printf("usage: send %s <value|option>\n", cmd);
+ printf("\"value\" must be from 0 to 255\n");
+ printf("Valid options are:\n\t");
+
+ col = 8;
+ for (cpp = telopts; *cpp; cpp++) {
+ len = strlen(*cpp) + 3;
+ if (col + len > 65) {
+ printf("\n\t");
+ col = 8;
+ }
+ printf(" \"%s\"", *cpp);
+ col += len;
+ }
+ printf("\n");
+ return 0;
+ }
+ cpp = (const char **)genget(name, (char **)telopts, sizeof(char *));
+ if (Ambiguous(cpp)) {
+ fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
+ name, cmd);
+ return 0;
+ }
+ if (cpp) {
+ val = cpp - telopts;
+ } else {
+ char *cp = name;
+
+ while (*cp >= '0' && *cp <= '9') {
+ val *= 10;
+ val += *cp - '0';
+ cp++;
+ }
+ if (*cp != 0) {
+ fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
+ name, cmd);
+ return 0;
+ } else if (val < 0 || val > 255) {
+ fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
+ name, cmd);
+ return 0;
+ }
+ }
+ if (!connected) {
+ printf("?Need to be connected first.\n");
+ return 0;
+ }
+ (*func)(val, 1);
+ return 1;
+}
+
+static int
+send_help(char *n)
+{
+ struct sendlist *s; /* pointer to current command */
+ for (s = Sendlist; s->name; s++) {
+ if (s->help)
+ printf("%-15s %s\n", s->name, s->help);
+ }
+ return(0);
+}
+
+/*
+ * The following are the routines and data structures referred
+ * to by the arguments to the "toggle" command.
+ */
+
+static int
+lclchars(int n)
+{
+ donelclchars = 1;
+ return 1;
+}
+
+static int
+togdebug(int n)
+{
+ if (net > 0 &&
+ (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, telnet_debug)) < 0) {
+ perror("setsockopt (SO_DEBUG)");
+ }
+ return 1;
+}
+
+static int
+togcrlf(int n)
+{
+ if (crlf) {
+ printf("Will send carriage returns as telnet <CR><LF>.\n");
+ } else {
+ printf("Will send carriage returns as telnet <CR><NUL>.\n");
+ }
+ return 1;
+}
+
+int binmode;
+
+static int
+togbinary(int val)
+{
+ donebinarytoggle = 1;
+
+ if (val >= 0) {
+ binmode = val;
+ } else {
+ if (my_want_state_is_will(TELOPT_BINARY) &&
+ my_want_state_is_do(TELOPT_BINARY)) {
+ binmode = 1;
+ } else if (my_want_state_is_wont(TELOPT_BINARY) &&
+ my_want_state_is_dont(TELOPT_BINARY)) {
+ binmode = 0;
+ }
+ val = binmode ? 0 : 1;
+ }
+
+ if (val == 1) {
+ if (my_want_state_is_will(TELOPT_BINARY) &&
+ my_want_state_is_do(TELOPT_BINARY)) {
+ printf("Already operating in binary mode with remote host.\n");
+ } else {
+ printf("Negotiating binary mode with remote host.\n");
+ tel_enter_binary(3);
+ }
+ } else {
+ if (my_want_state_is_wont(TELOPT_BINARY) &&
+ my_want_state_is_dont(TELOPT_BINARY)) {
+ printf("Already in network ascii mode with remote host.\n");
+ } else {
+ printf("Negotiating network ascii mode with remote host.\n");
+ tel_leave_binary(3);
+ }
+ }
+ return 1;
+}
+
+static int
+togrbinary(int val)
+{
+ donebinarytoggle = 1;
+
+ if (val == -1)
+ val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
+
+ if (val == 1) {
+ if (my_want_state_is_do(TELOPT_BINARY)) {
+ printf("Already receiving in binary mode.\n");
+ } else {
+ printf("Negotiating binary mode on input.\n");
+ tel_enter_binary(1);
+ }
+ } else {
+ if (my_want_state_is_dont(TELOPT_BINARY)) {
+ printf("Already receiving in network ascii mode.\n");
+ } else {
+ printf("Negotiating network ascii mode on input.\n");
+ tel_leave_binary(1);
+ }
+ }
+ return 1;
+}
+
+static int
+togxbinary(int val)
+{
+ donebinarytoggle = 1;
+
+ if (val == -1)
+ val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
+
+ if (val == 1) {
+ if (my_want_state_is_will(TELOPT_BINARY)) {
+ printf("Already transmitting in binary mode.\n");
+ } else {
+ printf("Negotiating binary mode on output.\n");
+ tel_enter_binary(2);
+ }
+ } else {
+ if (my_want_state_is_wont(TELOPT_BINARY)) {
+ printf("Already transmitting in network ascii mode.\n");
+ } else {
+ printf("Negotiating network ascii mode on output.\n");
+ tel_leave_binary(2);
+ }
+ }
+ return 1;
+}
+
+#ifdef ENCRYPTION
+extern int EncryptAutoEnc(int);
+extern int EncryptAutoDec(int);
+extern int EncryptDebug(int);
+extern int EncryptVerbose(int);
+#endif /* ENCRYPTION */
+
+struct togglelist {
+ char *name; /* name of toggle */
+ char *help; /* help message */
+ int (*handler) /* routine to do actual setting */
+ (int);
+ int *variable;
+ char *actionexplanation;
+};
+
+static struct togglelist Togglelist[] = {
+ { "autoflush",
+ "flushing of output when sending interrupt characters",
+ 0,
+ &autoflush,
+ "flush output when sending interrupt characters" },
+ { "autosynch",
+ "automatic sending of interrupt characters in urgent mode",
+ 0,
+ &autosynch,
+ "send interrupt characters in urgent mode" },
+#ifdef AUTHENTICATION
+ { "autologin",
+ "automatic sending of login and/or authentication info",
+ 0,
+ &autologin,
+ "send login name and/or authentication information" },
+ { "authdebug",
+ "Toggle authentication debugging",
+ auth_togdebug,
+ 0,
+ "print authentication debugging information" },
+#endif
+#ifdef ENCRYPTION
+ { "autoencrypt",
+ "automatic encryption of data stream",
+ EncryptAutoEnc,
+ 0,
+ "automatically encrypt output" },
+ { "autodecrypt",
+ "automatic decryption of data stream",
+ EncryptAutoDec,
+ 0,
+ "automatically decrypt input" },
+ { "verbose_encrypt",
+ "Toggle verbose encryption output",
+ EncryptVerbose,
+ 0,
+ "print verbose encryption output" },
+ { "encdebug",
+ "Toggle encryption debugging",
+ EncryptDebug,
+ 0,
+ "print encryption debugging information" },
+#endif /* ENCRYPTION */
+ { "skiprc",
+ "don't read ~/.telnetrc file",
+ 0,
+ &skiprc,
+ "skip reading of ~/.telnetrc file" },
+ { "binary",
+ "sending and receiving of binary data",
+ togbinary,
+ 0,
+ 0 },
+ { "inbinary",
+ "receiving of binary data",
+ togrbinary,
+ 0,
+ 0 },
+ { "outbinary",
+ "sending of binary data",
+ togxbinary,
+ 0,
+ 0 },
+ { "crlf",
+ "sending carriage returns as telnet <CR><LF>",
+ togcrlf,
+ &crlf,
+ 0 },
+ { "crmod",
+ "mapping of received carriage returns",
+ 0,
+ &crmod,
+ "map carriage return on output" },
+ { "localchars",
+ "local recognition of certain control characters",
+ lclchars,
+ &localchars,
+ "recognize certain control characters" },
+ { " ", "", 0 }, /* empty line */
+#ifdef TN3270
+ { "apitrace",
+ "(debugging) toggle tracing of API transactions",
+ 0,
+ &apitrace,
+ "trace API transactions" },
+ { "cursesdata",
+ "(debugging) toggle printing of hexadecimal curses data",
+ 0,
+ &cursesdata,
+ "print hexadecimal representation of curses data" },
+#endif /* defined(TN3270) */
+ { "debug",
+ "debugging",
+ togdebug,
+ &telnet_debug,
+ "turn on socket level debugging" },
+ { "netdata",
+ "printing of hexadecimal network data (debugging)",
+ 0,
+ &netdata,
+ "print hexadecimal representation of network traffic" },
+ { "prettydump",
+ "output of \"netdata\" to user readable format (debugging)",
+ 0,
+ &prettydump,
+ "print user readable output for \"netdata\"" },
+ { "options",
+ "viewing of options processing (debugging)",
+ 0,
+ &showoptions,
+ "show option processing" },
+ { "termdata",
+ "(debugging) toggle printing of hexadecimal terminal data",
+ 0,
+ &termdata,
+ "print hexadecimal representation of terminal traffic" },
+ { "?",
+ 0,
+ togglehelp },
+ { "help",
+ 0,
+ togglehelp },
+ { 0 }
+};
+
+static int
+togglehelp(int n)
+{
+ struct togglelist *c;
+
+ for (c = Togglelist; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s toggle %s\n", c->name, c->help);
+ else
+ printf("\n");
+ }
+ }
+ printf("\n");
+ printf("%-15s %s\n", "?", "display help information");
+ return 0;
+}
+
+static void
+settogglehelp(int set)
+{
+ struct togglelist *c;
+
+ for (c = Togglelist; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
+ c->help);
+ else
+ printf("\n");
+ }
+ }
+}
+
+#define GETTOGGLE(name) (struct togglelist *) \
+ genget(name, (char **) Togglelist, sizeof(struct togglelist))
+
+static int
+toggle(int argc, char *argv[])
+{
+ int retval = 1;
+ char *name;
+ struct togglelist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'toggle' command. 'toggle ?' for help.\n");
+ return 0;
+ }
+ argc--;
+ argv++;
+ while (argc--) {
+ name = *argv++;
+ c = GETTOGGLE(name);
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
+ name);
+ return 0;
+ } else if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
+ name);
+ return 0;
+ } else {
+ if (c->variable) {
+ *c->variable = !*c->variable; /* invert it */
+ if (c->actionexplanation) {
+ printf("%s %s.\n", *c->variable? "Will" : "Won't",
+ c->actionexplanation);
+ }
+ }
+ if (c->handler) {
+ retval &= (*c->handler)(-1);
+ }
+ }
+ }
+ return retval;
+}
+
+/*
+ * The following perform the "set" command.
+ */
+
+struct termios new_tc = { 0 };
+
+struct setlist {
+ char *name; /* name */
+ char *help; /* help information */
+ void (*handler)(char *);
+ cc_t *charp; /* where it is located at */
+};
+
+static struct setlist Setlist[] = {
+#ifdef KLUDGELINEMODE
+ { "echo", "character to toggle local echoing on/off", 0, &echoc },
+#endif
+ { "escape", "character to escape back to telnet command mode", 0, &escape },
+ { "rlogin", "rlogin escape character", 0, &rlogin },
+ { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
+ { " ", "" },
+ { " ", "The following need 'localchars' to be toggled true", 0, 0 },
+ { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
+ { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
+ { "quit", "character to cause an Abort process", 0, termQuitCharp },
+ { "eof", "character to cause an EOF ", 0, termEofCharp },
+ { " ", "" },
+ { " ", "The following are for local editing in linemode", 0, 0 },
+ { "erase", "character to use to erase a character", 0, termEraseCharp },
+ { "kill", "character to use to erase a line", 0, termKillCharp },
+ { "lnext", "character to use for literal next", 0, termLiteralNextCharp },
+ { "susp", "character to cause a Suspend Process", 0, termSuspCharp },
+ { "reprint", "character to use for line reprint", 0, termRprntCharp },
+ { "worderase", "character to use to erase a word", 0, termWerasCharp },
+ { "start", "character to use for XON", 0, termStartCharp },
+ { "stop", "character to use for XOFF", 0, termStopCharp },
+ { "forw1", "alternate end of line character", 0, termForw1Charp },
+ { "forw2", "alternate end of line character", 0, termForw2Charp },
+ { "ayt", "alternate AYT character", 0, termAytCharp },
+ { 0 }
+};
+
+static struct setlist *
+getset(char *name)
+{
+ return (struct setlist *)
+ genget(name, (char **) Setlist, sizeof(struct setlist));
+}
+
+void
+set_escape_char(char *s)
+{
+ if (rlogin != _POSIX_VDISABLE) {
+ rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
+ printf("Telnet rlogin escape character is '%s'.\n",
+ control(rlogin));
+ } else {
+ escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
+ printf("Telnet escape character is '%s'.\n", control(escape));
+ }
+}
+
+static int
+setcmd(int argc, char *argv[])
+{
+ int value;
+ struct setlist *ct;
+ struct togglelist *c;
+
+ if (argc < 2 || argc > 3) {
+ printf("Format is 'set Name Value'\n'set ?' for help.\n");
+ return 0;
+ }
+ if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
+ for (ct = Setlist; ct->name; ct++)
+ printf("%-15s %s\n", ct->name, ct->help);
+ printf("\n");
+ settogglehelp(1);
+ printf("%-15s %s\n", "?", "display help information");
+ return 0;
+ }
+
+ ct = getset(argv[1]);
+ if (ct == 0) {
+ c = GETTOGGLE(argv[1]);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
+ argv[1]);
+ return 0;
+ } else if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ if (c->variable) {
+ if ((argc == 2) || (strcmp("on", argv[2]) == 0))
+ *c->variable = 1;
+ else if (strcmp("off", argv[2]) == 0)
+ *c->variable = 0;
+ else {
+ printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
+ return 0;
+ }
+ if (c->actionexplanation) {
+ printf("%s %s.\n", *c->variable? "Will" : "Won't",
+ c->actionexplanation);
+ }
+ }
+ if (c->handler)
+ (*c->handler)(1);
+ } else if (argc != 3) {
+ printf("Format is 'set Name Value'\n'set ?' for help.\n");
+ return 0;
+ } else if (Ambiguous(ct)) {
+ fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
+ argv[1]);
+ return 0;
+ } else if (ct->handler) {
+ (*ct->handler)(argv[2]);
+ printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
+ } else {
+ if (strcmp("off", argv[2])) {
+ value = special(argv[2]);
+ } else {
+ value = _POSIX_VDISABLE;
+ }
+ *(ct->charp) = (cc_t)value;
+ printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
+ }
+ slc_check();
+ return 1;
+}
+
+static int
+unsetcmd(int argc, char *argv[])
+{
+ struct setlist *ct;
+ struct togglelist *c;
+ char *name;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'unset' command. 'unset ?' for help.\n");
+ return 0;
+ }
+ if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
+ for (ct = Setlist; ct->name; ct++)
+ printf("%-15s %s\n", ct->name, ct->help);
+ printf("\n");
+ settogglehelp(0);
+ printf("%-15s %s\n", "?", "display help information");
+ return 0;
+ }
+
+ argc--;
+ argv++;
+ while (argc--) {
+ name = *argv++;
+ ct = getset(name);
+ if (ct == 0) {
+ c = GETTOGGLE(name);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
+ name);
+ return 0;
+ } else if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
+ name);
+ return 0;
+ }
+ if (c->variable) {
+ *c->variable = 0;
+ if (c->actionexplanation) {
+ printf("%s %s.\n", *c->variable? "Will" : "Won't",
+ c->actionexplanation);
+ }
+ }
+ if (c->handler)
+ (*c->handler)(0);
+ } else if (Ambiguous(ct)) {
+ fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
+ name);
+ return 0;
+ } else if (ct->handler) {
+ (*ct->handler)(0);
+ printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
+ } else {
+ *(ct->charp) = _POSIX_VDISABLE;
+ printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
+ }
+ }
+ return 1;
+}
+
+/*
+ * The following are the data structures and routines for the
+ * 'mode' command.
+ */
+#ifdef KLUDGELINEMODE
+extern int kludgelinemode;
+
+static int
+dokludgemode(int n)
+{
+ kludgelinemode = 1;
+ send_wont(TELOPT_LINEMODE, 1);
+ send_dont(TELOPT_SGA, 1);
+ send_dont(TELOPT_ECHO, 1);
+ return 1;
+}
+#endif
+
+static int
+dolinemode(int n)
+{
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode)
+ send_dont(TELOPT_SGA, 1);
+#endif
+ send_will(TELOPT_LINEMODE, 1);
+ send_dont(TELOPT_ECHO, 1);
+ return 1;
+}
+
+static int
+docharmode(int n)
+{
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode)
+ send_do(TELOPT_SGA, 1);
+ else
+#endif
+ send_wont(TELOPT_LINEMODE, 1);
+ send_do(TELOPT_ECHO, 1);
+ return 1;
+}
+
+static int
+dolmmode(int bit, int on)
+{
+ unsigned char c;
+ extern int linemode;
+
+ if (my_want_state_is_wont(TELOPT_LINEMODE)) {
+ printf("?Need to have LINEMODE option enabled first.\n");
+ printf("'mode ?' for help.\n");
+ return 0;
+ }
+
+ if (on)
+ c = (linemode | bit);
+ else
+ c = (linemode & ~bit);
+ lm_mode(&c, 1, 1);
+ return 1;
+}
+
+int
+set_mode(int bit)
+{
+ return dolmmode(bit, 1);
+}
+
+int
+clear_mode(int bit)
+{
+ return dolmmode(bit, 0);
+}
+
+struct modelist {
+ char *name; /* command name */
+ char *help; /* help string */
+ int (*handler) /* routine which executes command */
+ (int);
+ int needconnect; /* Do we need to be connected to execute? */
+ int arg1;
+};
+
+static struct modelist ModeList[] = {
+ { "character", "Disable LINEMODE option", docharmode, 1 },
+#ifdef KLUDGELINEMODE
+ { "", "(or disable obsolete line-by-line mode)", 0 },
+#endif
+ { "line", "Enable LINEMODE option", dolinemode, 1 },
+#ifdef KLUDGELINEMODE
+ { "", "(or enable obsolete line-by-line mode)", 0 },
+#endif
+ { "", "", 0 },
+ { "", "These require the LINEMODE option to be enabled", 0 },
+ { "isig", "Enable signal trapping", set_mode, 1, MODE_TRAPSIG },
+ { "+isig", 0, set_mode, 1, MODE_TRAPSIG },
+ { "-isig", "Disable signal trapping", clear_mode, 1, MODE_TRAPSIG },
+ { "edit", "Enable character editing", set_mode, 1, MODE_EDIT },
+ { "+edit", 0, set_mode, 1, MODE_EDIT },
+ { "-edit", "Disable character editing", clear_mode, 1, MODE_EDIT },
+ { "softtabs", "Enable tab expansion", set_mode, 1, MODE_SOFT_TAB },
+ { "+softtabs", 0, set_mode, 1, MODE_SOFT_TAB },
+ { "-softtabs", "Disable character editing", clear_mode, 1, MODE_SOFT_TAB },
+ { "litecho", "Enable literal character echo", set_mode, 1, MODE_LIT_ECHO },
+ { "+litecho", 0, set_mode, 1, MODE_LIT_ECHO },
+ { "-litecho", "Disable literal character echo", clear_mode, 1, MODE_LIT_ECHO },
+ { "help", 0, modehelp, 0 },
+#ifdef KLUDGELINEMODE
+ { "kludgeline", 0, dokludgemode, 1 },
+#endif
+ { "", "", 0 },
+ { "?", "Print help information", modehelp, 0 },
+ { 0 },
+};
+
+
+int
+modehelp(int n)
+{
+ struct modelist *mt;
+
+ printf("format is: 'mode Mode', where 'Mode' is one of:\n\n");
+ for (mt = ModeList; mt->name; mt++) {
+ if (mt->help) {
+ if (*mt->help)
+ printf("%-15s %s\n", mt->name, mt->help);
+ else
+ printf("\n");
+ }
+ }
+ return 0;
+}
+
+#define GETMODECMD(name) (struct modelist *) \
+ genget(name, (char **) ModeList, sizeof(struct modelist))
+
+static int
+modecmd(int argc, char *argv[])
+{
+ struct modelist *mt;
+
+ if (argc != 2) {
+ printf("'mode' command requires an argument\n");
+ printf("'mode ?' for help.\n");
+ } else if ((mt = GETMODECMD(argv[1])) == 0) {
+ fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
+ } else if (Ambiguous(mt)) {
+ fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
+ } else if (mt->needconnect && !connected) {
+ printf("?Need to be connected first.\n");
+ printf("'mode ?' for help.\n");
+ } else if (mt->handler) {
+ return (*mt->handler)(mt->arg1);
+ }
+ return 0;
+}
+
+/*
+ * The following data structures and routines implement the
+ * "display" command.
+ */
+
+static int
+display(int argc, char *argv[])
+{
+ struct togglelist *tl;
+ struct setlist *sl;
+
+#define dotog(tl) if (tl->variable && tl->actionexplanation) { \
+ if (*tl->variable) { \
+ printf("will"); \
+ } else { \
+ printf("won't"); \
+ } \
+ printf(" %s.\n", tl->actionexplanation); \
+ }
+
+#define doset(sl) if (sl->name && *sl->name != ' ') { \
+ if (sl->handler == 0) \
+ printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
+ else \
+ printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
+ }
+
+ if (argc == 1) {
+ for (tl = Togglelist; tl->name; tl++) {
+ dotog(tl);
+ }
+ printf("\n");
+ for (sl = Setlist; sl->name; sl++) {
+ doset(sl);
+ }
+ } else {
+ int i;
+
+ for (i = 1; i < argc; i++) {
+ sl = getset(argv[i]);
+ tl = GETTOGGLE(argv[i]);
+ if (Ambiguous(sl) || Ambiguous(tl)) {
+ printf("?Ambiguous argument '%s'.\n", argv[i]);
+ return 0;
+ } else if (!sl && !tl) {
+ printf("?Unknown argument '%s'.\n", argv[i]);
+ return 0;
+ } else {
+ if (tl) {
+ dotog(tl);
+ }
+ if (sl) {
+ doset(sl);
+ }
+ }
+ }
+ }
+/*@*/optionstatus();
+#ifdef ENCRYPTION
+ EncryptStatus();
+#endif /* ENCRYPTION */
+ return 1;
+#undef doset
+#undef dotog
+}
+
+/*
+ * The following are the data structures, and many of the routines,
+ * relating to command processing.
+ */
+
+/*
+ * Set the escape character.
+ */
+static int
+setescape(int argc, char *argv[])
+{
+ char *arg;
+ char buf[50];
+
+ printf(
+ "Deprecated usage - please use 'set escape%s%s' in the future.\n",
+ (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
+ if (argc > 2)
+ arg = argv[1];
+ else {
+ printf("new escape character: ");
+ (void) fgets(buf, sizeof(buf), stdin);
+ arg = buf;
+ }
+ if (arg[0] != '\0')
+ escape = arg[0];
+ if (!In3270) {
+ printf("Escape character is '%s'.\n", control(escape));
+ }
+ (void) fflush(stdout);
+ return 1;
+}
+
+/*VARARGS*/
+static int
+togcrmod(int argc, char *argv[])
+{
+ crmod = !crmod;
+ printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
+ printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
+ (void) fflush(stdout);
+ return 1;
+}
+
+/*VARARGS*/
+int
+suspend(int argc, char *argv[])
+{
+ setcommandmode();
+ {
+ long oldrows, oldcols, newrows, newcols, err;
+
+ err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+ (void) kill(0, SIGTSTP);
+ /*
+ * If we didn't get the window size before the SUSPEND, but we
+ * can get them now (?), then send the NAWS to make sure that
+ * we are set up for the right window size.
+ */
+ if (TerminalWindowSize(&newrows, &newcols) && connected &&
+ (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+ sendnaws();
+ }
+ }
+ /* reget parameters in case they were changed */
+ TerminalSaveState();
+ setconnmode(0);
+ return 1;
+}
+
+#ifndef TN3270
+/*ARGSUSED*/
+int
+shell(int argc, char *argv[])
+{
+ long oldrows, oldcols, newrows, newcols;
+ long volatile err; /* Avoid vfork clobbering */
+
+ setcommandmode();
+
+ err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
+ switch(vfork()) {
+ case -1:
+ perror("Fork failed");
+ break;
+
+ case 0:
+ {
+ /*
+ * Fire up the shell in the child.
+ */
+ char *shellp, *shellname;
+
+ shellp = getenv("SHELL");
+ if (shellp == NULL)
+ shellp = "/bin/sh";
+ if ((shellname = strrchr(shellp, '/')) == 0)
+ shellname = shellp;
+ else
+ shellname++;
+ if (argc > 1)
+ execl(shellp, shellname, "-c", &saveline[1], NULL);
+ else
+ execl(shellp, shellname, NULL);
+ perror("execl");
+ _exit(1);
+ }
+ default:
+ (void)wait((int *)0); /* Wait for the shell to complete */
+
+ if (TerminalWindowSize(&newrows, &newcols) && connected &&
+ (err || ((oldrows != newrows) || (oldcols != newcols)))) {
+ sendnaws();
+ }
+ break;
+ }
+ return 1;
+}
+#endif /* !defined(TN3270) */
+
+/*VARARGS*/
+static int
+bye(int argc, char *argv[])
+{
+ extern int resettermname;
+
+ if (connected) {
+ (void) shutdown(net, 2);
+ printf("Connection closed.\n");
+ (void) NetClose(net);
+ connected = 0;
+ resettermname = 1;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) */
+ /* reset options */
+ tninit();
+#ifdef TN3270
+ SetIn3270(); /* Get out of 3270 mode */
+#endif /* defined(TN3270) */
+ }
+ if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
+ longjmp(toplevel, 1);
+ /* NOTREACHED */
+ }
+ return 1; /* Keep lint, etc., happy */
+}
+
+/*VARARGS*/
+int
+quit(int argc, char *argv[])
+{
+ (void) call(bye, "bye", "fromquit", 0);
+ Exit(0);
+ /*NOTREACHED*/
+}
+
+/*VARARGS*/
+int
+logout(int argc, char *argv[])
+{
+ send_do(TELOPT_LOGOUT, 1);
+ (void) netflush();
+ return 1;
+}
+
+
+/*
+ * The SLC command.
+ */
+
+struct slclist {
+ char *name;
+ char *help;
+ void (*handler)(int);
+ int arg;
+};
+
+struct slclist SlcList[] = {
+ { "export", "Use local special character definitions",
+ slc_mode_export, 0 },
+ { "import", "Use remote special character definitions",
+ slc_mode_import, 1 },
+ { "check", "Verify remote special character definitions",
+ slc_mode_import, 0 },
+ { "help", 0, slc_help, 0 },
+ { "?", "Print help information", slc_help, 0 },
+ { 0 },
+};
+
+static void
+slc_help(int n)
+{
+ struct slclist *c;
+
+ for (c = SlcList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\n", c->name, c->help);
+ else
+ printf("\n");
+ }
+ }
+}
+
+static struct slclist *
+getslc(char *name)
+{
+ return (struct slclist *)
+ genget(name, (char **) SlcList, sizeof(struct slclist));
+}
+
+static int
+slccmd(int argc, char *argv[])
+{
+ struct slclist *c;
+
+ if (argc != 2) {
+ fprintf(stderr,
+ "Need an argument to 'slc' command. 'slc ?' for help.\n");
+ return 0;
+ }
+ c = getslc(argv[1]);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ (*c->handler)(c->arg);
+ slcstate();
+ return 1;
+}
+
+/*
+ * The ENVIRON command.
+ */
+
+struct envlist {
+ char *name;
+ char *help;
+ struct env_lst *(*handler)(unsigned char *, unsigned char *);
+ int narg;
+};
+
+struct envlist EnvList[] = {
+ { "define", "Define an environment variable",
+ env_define, 2 },
+ { "undefine", "Undefine an environment variable",
+ env_undefine, 1 },
+ { "export", "Mark an environment variable for automatic export",
+ env_export, 1 },
+ { "unexport", "Don't mark an environment variable for automatic export",
+ env_unexport, 1 },
+ { "send", "Send an environment variable", env_send, 1 },
+ { "list", "List the current environment variables",
+ env_list, 0 },
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+ { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
+ env_varval, 1 },
+#endif
+ { "help", 0, env_help, 0 },
+ { "?", "Print help information", env_help, 0 },
+ { 0 },
+};
+
+static struct env_lst *
+env_help( unsigned char *us1, unsigned char *us2)
+{
+ struct envlist *c;
+
+ for (c = EnvList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\n", c->name, c->help);
+ else
+ printf("\n");
+ }
+ }
+ return NULL;
+}
+
+static struct envlist *
+getenvcmd(char *name)
+{
+ return (struct envlist *)
+ genget(name, (char **) EnvList, sizeof(struct envlist));
+}
+
+int
+env_cmd(int argc, char *argv[])
+{
+ struct envlist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'environ' command. 'environ ?' for help.\n");
+ return 0;
+ }
+ c = getenvcmd(argv[1]);
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ if (c->narg + 2 != argc) {
+ fprintf(stderr,
+ "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n",
+ c->narg < argc + 2 ? "only " : "",
+ c->narg, c->narg == 1 ? "" : "s", c->name);
+ return 0;
+ }
+ (*c->handler)(argv[2], argv[3]);
+ return 1;
+}
+
+struct env_lst {
+ struct env_lst *next; /* pointer to next structure */
+ struct env_lst *prev; /* pointer to previous structure */
+ unsigned char *var; /* pointer to variable name */
+ unsigned char *value; /* pointer to variable value */
+ int export; /* 1 -> export with default list of variables */
+ int welldefined; /* A well defined variable */
+};
+
+struct env_lst envlisthead;
+
+struct env_lst *
+env_find(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ for (ep = envlisthead.next; ep; ep = ep->next) {
+ if (strcmp((char *)ep->var, (char *)var) == 0)
+ return(ep);
+ }
+ return(NULL);
+}
+
+void
+env_init(void)
+{
+ extern char **environ;
+ char **epp, *cp;
+ struct env_lst *ep;
+
+ for (epp = environ; *epp; epp++) {
+ if ((cp = strchr(*epp, '=')) != NULL) {
+ *cp = '\0';
+ ep = env_define((unsigned char *)*epp,
+ (unsigned char *)cp+1);
+ ep->export = 0;
+ *cp = '=';
+ }
+ }
+ /*
+ * Special case for DISPLAY variable. If it is ":0.0" or
+ * "unix:0.0", we have to get rid of "unix" and insert our
+ * hostname.
+ */
+ if ((ep = env_find("DISPLAY"))
+ && ((*ep->value == ':')
+ || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
+ char hbuf[MAXHOSTNAMELEN + 1];
+ char *cp2 = strchr((char *)ep->value, ':');
+
+ gethostname(hbuf, sizeof hbuf);
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
+ sprintf((char *)cp, "%s%s", hbuf, cp2);
+ free(ep->value);
+ ep->value = (unsigned char *)cp;
+ }
+ /*
+ * If USER is not defined, but LOGNAME is, then add
+ * USER with the value from LOGNAME. By default, we
+ * don't export the USER variable.
+ */
+ if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
+ env_define((unsigned char *)"USER", ep->value);
+ env_unexport((unsigned char *)"USER", NULL);
+ }
+ env_export((unsigned char *)"DISPLAY", NULL);
+ env_export((unsigned char *)"PRINTER", NULL);
+}
+
+struct env_lst *
+env_define(unsigned char *var, unsigned char *value)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)) != NULL) {
+ if (ep->var)
+ free(ep->var);
+ if (ep->value)
+ free(ep->value);
+ } else {
+ ep = (struct env_lst *)malloc(sizeof(struct env_lst));
+ ep->next = envlisthead.next;
+ envlisthead.next = ep;
+ ep->prev = &envlisthead;
+ if (ep->next)
+ ep->next->prev = ep;
+ }
+ ep->welldefined = opt_welldefined(var);
+ ep->export = 1;
+ ep->var = (unsigned char *)strdup((char *)var);
+ ep->value = (unsigned char *)strdup((char *)value);
+ return(ep);
+}
+
+struct env_lst *
+env_undefine(unsigned char *var, unsigned char *d)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)) != NULL) {
+ ep->prev->next = ep->next;
+ if (ep->next)
+ ep->next->prev = ep->prev;
+ if (ep->var)
+ free(ep->var);
+ if (ep->value)
+ free(ep->value);
+ free(ep);
+ }
+ return NULL;
+}
+
+struct env_lst *
+env_export(unsigned char *var, unsigned char *d)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)) != NULL)
+ ep->export = 1;
+ return NULL;
+}
+
+struct env_lst *
+env_unexport(unsigned char *var, unsigned char *d)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)) != NULL)
+ ep->export = 0;
+ return NULL;
+}
+
+struct env_lst *
+env_send(unsigned char *var, unsigned char *d)
+{
+ struct env_lst *ep;
+
+ if (my_state_is_wont(TELOPT_NEW_ENVIRON)
+#ifdef OLD_ENVIRON
+ && my_state_is_wont(TELOPT_OLD_ENVIRON)
+#endif
+ ) {
+ fprintf(stderr,
+ "Cannot send '%s': Telnet ENVIRON option not enabled\n",
+ var);
+ return NULL;
+ }
+ ep = env_find(var);
+ if (ep == 0) {
+ fprintf(stderr, "Cannot send '%s': variable not defined\n",
+ var);
+ return NULL;
+ }
+ env_opt_start_info();
+ env_opt_add(ep->var);
+ env_opt_end(0);
+ return NULL;
+}
+
+struct env_lst *
+env_list(unsigned char *d1, unsigned char *d2)
+{
+ struct env_lst *ep;
+
+ for (ep = envlisthead.next; ep; ep = ep->next) {
+ printf("%c %-20s %s\n", ep->export ? '*' : ' ',
+ ep->var, ep->value);
+ }
+ return NULL;
+}
+
+unsigned char *
+env_default(int init, int welldefined)
+{
+ static struct env_lst *nep = NULL;
+
+ if (init) {
+ nep = &envlisthead;
+ return NULL;
+ }
+ if (nep) {
+ while ((nep = nep->next) != NULL) {
+ if (nep->export && (nep->welldefined == welldefined))
+ return(nep->var);
+ }
+ }
+ return(NULL);
+}
+
+unsigned char *
+env_getvalue(unsigned char *var)
+{
+ struct env_lst *ep;
+
+ if ((ep = env_find(var)) != NULL)
+ return(ep->value);
+ return(NULL);
+}
+
+#if defined(OLD_ENVIRON) && defined(ENV_HACK)
+void
+env_varval(unsigned char *what)
+{
+ extern int old_env_var, old_env_value, env_auto;
+ int len = strlen((char *)what);
+
+ if (len == 0)
+ goto unknown;
+
+ if (strncasecmp((char *)what, "status", len) == 0) {
+ if (env_auto)
+ printf("%s%s", "VAR and VALUE are/will be ",
+ "determined automatically\n");
+ if (old_env_var == OLD_ENV_VAR)
+ printf("VAR and VALUE set to correct definitions\n");
+ else
+ printf("VAR and VALUE definitions are reversed\n");
+ } else if (strncasecmp((char *)what, "auto", len) == 0) {
+ env_auto = 1;
+ old_env_var = OLD_ENV_VALUE;
+ old_env_value = OLD_ENV_VAR;
+ } else if (strncasecmp((char *)what, "right", len) == 0) {
+ env_auto = 0;
+ old_env_var = OLD_ENV_VAR;
+ old_env_value = OLD_ENV_VALUE;
+ } else if (strncasecmp((char *)what, "wrong", len) == 0) {
+ env_auto = 0;
+ old_env_var = OLD_ENV_VALUE;
+ old_env_value = OLD_ENV_VAR;
+ } else {
+unknown:
+ printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
+ }
+}
+#endif
+
+#ifdef AUTHENTICATION
+/*
+ * The AUTHENTICATE command.
+ */
+
+struct authlist {
+ char *name;
+ char *help;
+ int (*handler)(char *);
+ int narg;
+};
+
+struct authlist AuthList[] = {
+ { "status", "Display current status of authentication information",
+ auth_status, 0 },
+ { "disable", "Disable an authentication type ('auth disable ?' for more)",
+ auth_disable, 1 },
+ { "enable", "Enable an authentication type ('auth enable ?' for more)",
+ auth_enable, 1 },
+ { "help", 0, auth_help, 0 },
+ { "?", "Print help information", auth_help, 0 },
+ { 0 },
+};
+
+static int
+auth_help(char *s)
+{
+ struct authlist *c;
+
+ for (c = AuthList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\n", c->name, c->help);
+ else
+ printf("\n");
+ }
+ }
+ return 0;
+}
+
+int
+auth_cmd(int argc, char *argv[])
+{
+ struct authlist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'auth' command. 'auth ?' for help.\n");
+ return 0;
+ }
+
+ c = (struct authlist *)
+ genget(argv[1], (char **) AuthList, sizeof(struct authlist));
+ if (c == 0) {
+ fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
+ argv[1]);
+ return 0;
+ }
+ if (c->narg + 2 != argc) {
+ fprintf(stderr,
+ "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n",
+ c->narg < argc + 2 ? "only " : "",
+ c->narg, c->narg == 1 ? "" : "s", c->name);
+ return 0;
+ }
+ return((*c->handler)(argv[2]));
+}
+#endif
+
+#ifdef ENCRYPTION
+/*
+ * The ENCRYPT command.
+ */
+
+struct encryptlist {
+ char *name;
+ char *help;
+ int (*handler)(char *, char *);
+ int needconnect;
+ int minarg;
+ int maxarg;
+};
+
+static int
+ EncryptHelp(char *, char *);
+typedef int (*encrypthandler)(char *, char *);
+
+struct encryptlist EncryptList[] = {
+ { "enable", "Enable encryption. ('encrypt enable ?' for more)",
+ EncryptEnable, 1, 1, 2 },
+ { "disable", "Disable encryption. ('encrypt enable ?' for more)",
+ EncryptDisable, 0, 1, 2 },
+ { "type", "Set encryption type. ('encrypt type ?' for more)",
+ EncryptType, 0, 1, 1 },
+ { "start", "Start encryption. ('encrypt start ?' for more)",
+ (encrypthandler) EncryptStart, 1, 0, 1 },
+ { "stop", "Stop encryption. ('encrypt stop ?' for more)",
+ (encrypthandler) EncryptStop, 1, 0, 1 },
+ { "input", "Start encrypting the input stream",
+ (encrypthandler) EncryptStartInput, 1, 0, 0 },
+ { "-input", "Stop encrypting the input stream",
+ (encrypthandler) EncryptStopInput, 1, 0, 0 },
+ { "output", "Start encrypting the output stream",
+ (encrypthandler) EncryptStartOutput, 1, 0, 0 },
+ { "-output", "Stop encrypting the output stream",
+ (encrypthandler) EncryptStopOutput, 1, 0, 0 },
+
+ { "status", "Display current status of authentication information",
+ (encrypthandler) EncryptStatus, 0, 0, 0 },
+ { "help", 0, EncryptHelp, 0, 0, 0 },
+ { "?", "Print help information", EncryptHelp, 0, 0, 0 },
+ { 0 },
+};
+
+static int
+EncryptHelp(char *s1, char *s2)
+{
+ struct encryptlist *c;
+
+ for (c = EncryptList; c->name; c++) {
+ if (c->help) {
+ if (*c->help)
+ printf("%-15s %s\n", c->name, c->help);
+ else
+ printf("\n");
+ }
+ }
+ return (0);
+}
+
+int
+encrypt_cmd(int argc, char *argv[])
+{
+ struct encryptlist *c;
+
+ if (argc < 2) {
+ fprintf(stderr,
+ "Need an argument to 'encrypt' command. "
+ "'encrypt ?' for help.\n");
+ return (0);
+ }
+
+ c = (struct encryptlist *)
+ genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
+ if (c == NULL) {
+ fprintf(stderr,
+ "'%s': unknown argument ('encrypt ?' for help).\n",
+ argv[1]);
+ return (0);
+ }
+ if (Ambiguous(c)) {
+ fprintf(stderr,
+ "'%s': ambiguous argument ('encrypt ?' for help).\n",
+ argv[1]);
+ return (0);
+ }
+ argc -= 2;
+ if (argc < c->minarg || argc > c->maxarg) {
+ if (c->minarg == c->maxarg) {
+ fprintf(stderr, "Need %s%d argument%s ",
+ c->minarg < argc ? "only " : "", c->minarg,
+ c->minarg == 1 ? "" : "s");
+ } else {
+ fprintf(stderr, "Need %s%d-%d arguments ",
+ c->maxarg < argc ? "only " : "", c->minarg,
+ c->maxarg);
+ }
+ fprintf(stderr,
+ "to 'encrypt %s' command. 'encrypt ?' for help.\n",
+ c->name);
+ return (0);
+ }
+ if (c->needconnect && !connected) {
+ if (!(argc && (isprefix(argv[2], "help") ||
+ isprefix(argv[2], "?")))) {
+ printf("?Need to be connected first.\n");
+ return (0);
+ }
+ }
+ return ((*c->handler)(argv[2], argv[3]));
+}
+#endif /* ENCRYPTION */
+
+#ifdef TN3270
+static void
+filestuff(int fd)
+{
+ int res;
+
+ setconnmode(0);
+ res = fcntl(fd, F_GETOWN, 0);
+ setcommandmode();
+
+ if (res == -1) {
+ perror("fcntl");
+ return;
+ }
+ printf("\tOwner is %d.\n", res);
+
+ setconnmode(0);
+ res = fcntl(fd, F_GETFL, 0);
+ setcommandmode();
+
+ if (res == -1) {
+ perror("fcntl");
+ return;
+ }
+#ifdef notdef
+ printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
+#endif
+}
+#endif /* defined(TN3270) */
+
+/*
+ * Print status about the connection.
+ */
+/*ARGSUSED*/
+static int
+status(int argc, char *argv[])
+{
+ if (connected) {
+ printf("Connected to %s.\n", hostname);
+ if ((argc < 2) || strcmp(argv[1], "notmuch")) {
+ int mode = getconnmode();
+
+ if (my_want_state_is_will(TELOPT_LINEMODE)) {
+ printf("Operating with LINEMODE option\n");
+ printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
+ printf("%s catching of signals\n",
+ (mode&MODE_TRAPSIG) ? "Local" : "No");
+ slcstate();
+#ifdef KLUDGELINEMODE
+ } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
+ printf("Operating in obsolete linemode\n");
+#endif
+ } else {
+ printf("Operating in single character mode\n");
+ if (localchars)
+ printf("Catching signals locally\n");
+ }
+ printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
+ if (my_want_state_is_will(TELOPT_LFLOW))
+ printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
+#ifdef ENCRYPTION
+ encrypt_display();
+#endif /* ENCRYPTION */
+ }
+ } else {
+ printf("No connection.\n");
+ }
+# ifndef TN3270
+ printf("Escape character is '%s'.\n", control(escape));
+ (void) fflush(stdout);
+# else /* !defined(TN3270) */
+ if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
+ printf("Escape character is '%s'.\n", control(escape));
+ }
+ if ((argc >= 2) && !strcmp(argv[1], "everything")) {
+ printf("SIGIO received %d time%s.\n",
+ sigiocount, (sigiocount == 1)? "":"s");
+ if (In3270) {
+ printf("Process ID %d, process group %d.\n",
+ getpid(), getpgrp());
+ printf("Terminal input:\n");
+ filestuff(tin);
+ printf("Terminal output:\n");
+ filestuff(tout);
+ printf("Network socket:\n");
+ filestuff(net);
+ }
+ }
+ if (In3270 && transcom) {
+ printf("Transparent mode command is '%s'.\n", transcom);
+ }
+ (void) fflush(stdout);
+ if (In3270) {
+ return 0;
+ }
+# endif /* defined(TN3270) */
+ return 1;
+}
+
+/*
+ * Function that gets called when SIGINFO is received.
+ */
+int
+ayt_status(void)
+{
+ return call(status, "status", "notmuch", 0);
+}
+
+static const char *
+sockaddr_ntop(struct sockaddr *sa)
+{
+ static char addrbuf[NI_MAXHOST];
+ const int niflags = NI_NUMERICHOST;
+
+ if (getnameinfo(sa, sa->sa_len, addrbuf, sizeof(addrbuf),
+ NULL, 0, niflags) == 0)
+ return addrbuf;
+ else
+ return NULL;
+}
+
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+static int setpolicy (int, struct addrinfo *, char *);
+
+static int
+setpolicy(int net, struct addrinfo *res, char *policy)
+{
+ char *buf;
+ int level;
+ int optname;
+
+ if (policy == NULL)
+ return 0;
+
+ buf = ipsec_set_policy(policy, strlen(policy));
+ if (buf == NULL) {
+ printf("%s\n", ipsec_strerror());
+ return -1;
+ }
+ level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
+ optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
+ if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){
+ perror("setsockopt");
+ return -1;
+ }
+
+ free(buf);
+ return 0;
+}
+#endif
+
+int
+tn(int argc, char *argv[])
+{
+ struct addrinfo hints, *res, *res0;
+ char *cause = "telnet: unknown";
+ int error;
+#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
+ char *srp = 0;
+ unsigned long srlen;
+ int proto, opt;
+#endif
+ char *cmd, *hostp = 0, *portp = 0;
+ const char *user = 0;
+
+ if (connected) {
+ printf("?Already connected to %s\n", hostname);
+ return 0;
+ }
+ if (argc < 2) {
+ (void) strlcpy(line, "open ", sizeof(line));
+ printf("(to) ");
+ (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
+ makeargv();
+ argc = margc;
+ argv = margv;
+ }
+ cmd = *argv;
+ --argc; ++argv;
+ while (argc) {
+ if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
+ goto usage;
+ if (strcmp(*argv, "-l") == 0) {
+ --argc; ++argv;
+ if (argc == 0)
+ goto usage;
+ user = *argv++;
+ --argc;
+ continue;
+ }
+ if (strcmp(*argv, "-a") == 0) {
+ --argc; ++argv;
+ autologin = 1;
+ continue;
+ }
+ if (hostp == 0) {
+ hostp = *argv++;
+ --argc;
+ continue;
+ }
+ if (portp == 0) {
+ portp = *argv++;
+ --argc;
+ continue;
+ }
+ usage:
+ printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
+ return 0;
+ }
+ if (hostp == 0)
+ goto usage;
+
+ (void) strlcpy(_hostname, hostp, sizeof(_hostname));
+ if (hostp[0] == '@' || hostp[0] == '!') {
+ char *p;
+ hostname = NULL;
+ for (p = hostp + 1; *p; p++) {
+ if (*p == ',' || *p == '@')
+ hostname = p;
+ }
+ if (hostname == NULL) {
+ fprintf(stderr, "%s: bad source route specification\n", hostp);
+ return 0;
+ }
+ *hostname++ = '\0';
+ } else
+ hostname = hostp;
+
+ if (!portp) {
+ telnetport = 1;
+ portp = "telnet";
+ } else if (portp[0] == '-') {
+ /* use telnet negotiation if port number/name preceded by minus sign */
+ telnetport = 1;
+ portp++;
+ } else
+ telnetport = 0;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ hints.ai_flags = AI_NUMERICHOST; /* avoid forward lookup */
+ error = getaddrinfo(hostname, portp, &hints, &res0);
+ if (!error) {
+ /* numeric */
+ if (doaddrlookup &&
+ getnameinfo(res0->ai_addr, res0->ai_addrlen,
+ _hostname, sizeof(_hostname), NULL, 0, NI_NAMEREQD) == 0)
+ ; /* okay */
+ else
+ strlcpy(_hostname, hostname, sizeof(_hostname));
+ } else {
+ /* FQDN - try again with forward DNS lookup */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ hints.ai_flags = AI_CANONNAME;
+ error = getaddrinfo(hostname, portp, &hints, &res0);
+ if (error == EAI_SERVICE) {
+ fprintf(stderr, "tcp/%s: unknown service\n", portp);
+ return 0;
+ } else if (error) {
+ fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error));
+ return 0;
+ }
+ if (res0->ai_canonname)
+ (void)strlcpy(_hostname, res0->ai_canonname, sizeof(_hostname));
+ else
+ (void)strlcpy(_hostname, hostname, sizeof(_hostname));
+ }
+ hostname = _hostname;
+
+ net = -1;
+ for (res = res0; res; res = res->ai_next) {
+ printf("Trying %s...\n", sockaddr_ntop(res->ai_addr));
+ net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (net < 0) {
+ cause = "telnet: socket";
+ continue;
+ }
+
+ if (telnet_debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
+ perror("setsockopt (SO_DEBUG)");
+ }
+ if (hostp[0] == '@' || hostp[0] == '!') {
+ if ((srlen = sourceroute(res, hostp, &srp, &proto, &opt)) < 0) {
+ (void) NetClose(net);
+ net = -1;
+ continue;
+ }
+ if (srp && setsockopt(net, proto, opt, srp, srlen) < 0)
+ perror("setsockopt (source route)");
+ }
+
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ if (setpolicy(net, res, ipsec_policy_in) < 0) {
+ (void) NetClose(net);
+ net = -1;
+ continue;
+ }
+ if (setpolicy(net, res, ipsec_policy_out) < 0) {
+ (void) NetClose(net);
+ net = -1;
+ continue;
+ }
+#endif
+
+ if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
+ if (res->ai_next) {
+ int oerrno = errno;
+
+ fprintf(stderr, "telnet: connect to address %s: ",
+ sockaddr_ntop(res->ai_addr));
+ errno = oerrno;
+ perror((char *)0);
+ }
+ cause = "telnet: Unable to connect to remote host";
+ (void) NetClose(net);
+ net = -1;
+ continue;
+ }
+
+ connected++;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+ break;
+ }
+ freeaddrinfo(res0);
+ if (net < 0 || connected == 0) {
+ perror(cause);
+ return 0;
+ }
+
+ cmdrc(hostp, hostname);
+ if (autologin && user == NULL) {
+ struct passwd *pw;
+
+ user = getenv("USER");
+ if (user == NULL ||
+ ((pw = getpwnam(user)) && pw->pw_uid != getuid())) {
+ if ((pw = getpwuid(getuid())) != NULL)
+ user = pw->pw_name;
+ else
+ user = NULL;
+ }
+ }
+ if (user) {
+ env_define((unsigned char *)"USER", (unsigned char *)user);
+ env_export((unsigned char *)"USER", NULL);
+ }
+ (void) call(status, "status", "notmuch", 0);
+ telnet(user);
+ (void) NetClose(net);
+ ExitString("Connection closed by foreign host.\n",1);
+ /*NOTREACHED*/
+}
+
+#define HELPINDENT ((int)sizeof ("connect"))
+
+static char
+ openhelp[] = "connect to a site",
+ closehelp[] = "close current connection",
+ logouthelp[] = "forcibly logout remote user and close the connection",
+ quithelp[] = "exit telnet",
+ statushelp[] = "print status information",
+ helphelp[] = "print help information",
+ sendhelp[] = "transmit special characters ('send ?' for more)",
+ sethelp[] = "set operating parameters ('set ?' for more)",
+ unsethelp[] = "unset operating parameters ('unset ?' for more)",
+ togglestring[] ="toggle operating parameters ('toggle ?' for more)",
+ slchelp[] = "change state of special characters ('slc ?' for more)",
+ displayhelp[] = "display operating parameters",
+#ifdef TN3270
+ transcomhelp[] = "specify Unix command for transparent mode pipe",
+#endif /* defined(TN3270) */
+#ifdef AUTHENTICATION
+ authhelp[] = "turn on (off) authentication ('auth ?' for more)",
+#endif
+#ifdef ENCRYPTION
+ encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)",
+#endif /* ENCRYPTION */
+ zhelp[] = "suspend telnet",
+ shellhelp[] = "invoke a subshell",
+ envhelp[] = "change environment variables ('environ ?' for more)",
+ modestring[] = "try to enter line or character mode ('mode ?' for more)";
+
+static Command cmdtab[] = {
+ { "close", closehelp, bye, 1 },
+ { "logout", logouthelp, logout, 1 },
+ { "display", displayhelp, display, 0 },
+ { "mode", modestring, modecmd, 0 },
+ { "open", openhelp, tn, 0 },
+ { "quit", quithelp, quit, 0 },
+ { "send", sendhelp, sendcmd, 0 },
+ { "set", sethelp, setcmd, 0 },
+ { "unset", unsethelp, unsetcmd, 0 },
+ { "status", statushelp, status, 0 },
+ { "toggle", togglestring, toggle, 0 },
+ { "slc", slchelp, slccmd, 0 },
+#ifdef TN3270
+ { "transcom", transcomhelp, settranscom, 0 },
+#endif /* defined(TN3270) */
+#ifdef AUTHENTICATION
+ { "auth", authhelp, auth_cmd, 0 },
+#endif
+#ifdef ENCRYPTION
+ { "encrypt", encrypthelp, encrypt_cmd, 0 },
+#endif
+ { "z", zhelp, suspend, 0 },
+#ifdef TN3270
+ { "!", shellhelp, shell, 1 },
+#else
+ { "!", shellhelp, shell, 0 },
+#endif
+ { "environ", envhelp, env_cmd, 0 },
+ { "?", helphelp, help, 0 },
+ { NULL, NULL, NULL, 0 }
+};
+
+static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead";
+static char escapehelp[] = "deprecated command -- use 'set escape' instead";
+
+static Command cmdtab2[] = {
+ { "help", 0, help, 0 },
+ { "escape", escapehelp, setescape, 0 },
+ { "crmod", crmodhelp, togcrmod, 0 },
+ { NULL, NULL, NULL, 0 }
+};
+
+
+/*
+ * Call routine with argc, argv set from args (terminated by 0).
+ */
+
+/*VARARGS1*/
+static int
+call(intrtn_t routine, ...)
+{
+ va_list ap;
+ char *args[100];
+ int argno = 0;
+
+ va_start(ap, routine);
+ while ((args[argno++] = va_arg(ap, char *)) != 0) {
+ ;
+ }
+ va_end(ap);
+ return (*routine)(argno-1, args);
+}
+
+
+static Command *
+getcmd(char *name)
+{
+ Command *cm;
+
+ if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command))) != NULL)
+ return cm;
+ return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
+}
+
+void
+command(int top, char *tbuf, int cnt)
+{
+ Command *c;
+
+ setcommandmode();
+ if (!top) {
+ putchar('\n');
+ } else {
+ (void) signal(SIGINT, SIG_DFL);
+ (void) signal(SIGQUIT, SIG_DFL);
+ }
+ for (;;) {
+ if (rlogin == _POSIX_VDISABLE)
+ printf("%s> ", prompt);
+ if (tbuf) {
+ char *cp;
+ cp = line;
+ while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
+ cnt--;
+ tbuf = 0;
+ if (cp == line || *--cp != '\n' || cp == line)
+ goto getline;
+ *cp = '\0';
+ if (rlogin == _POSIX_VDISABLE)
+ printf("%s\n", line);
+ } else {
+ getline:
+ if (rlogin != _POSIX_VDISABLE)
+ printf("%s> ", prompt);
+#ifdef TN3270
+ fflush(stdout);
+#endif
+ if (fgets(line, sizeof(line), stdin) == NULL) {
+ if (feof(stdin) || ferror(stdin)) {
+ (void) quit(0, NULL);
+ /*NOTREACHED*/
+ }
+ break;
+ }
+ }
+ if (line[0] == 0)
+ break;
+ makeargv();
+ if (margv[0] == 0) {
+ break;
+ }
+ c = getcmd(margv[0]);
+ if (Ambiguous(c)) {
+ printf("?Ambiguous command\n");
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command\n");
+ continue;
+ }
+ if (c->needconnect && !connected) {
+ printf("?Need to be connected first.\n");
+ continue;
+ }
+ if ((*c->handler)(margc, margv)) {
+ break;
+ }
+ }
+ if (!top) {
+ if (!connected) {
+ longjmp(toplevel, 1);
+ /*NOTREACHED*/
+ }
+#ifdef TN3270
+ if (shell_active == 0) {
+ setconnmode(0);
+ }
+#else /* defined(TN3270) */
+ setconnmode(0);
+#endif /* defined(TN3270) */
+ }
+}
+
+/*
+ * Help command.
+ */
+static int
+help(int argc, char *argv[])
+{
+ Command *c;
+
+ if (argc == 1) {
+ printf("Commands may be abbreviated. Commands are:\n\n");
+ for (c = cmdtab; c->name; c++)
+ if (c->help) {
+ printf("%-*s\t%s\n", HELPINDENT, c->name,
+ c->help);
+ }
+ return 0;
+ }
+ while (--argc > 0) {
+ char *arg;
+ arg = *++argv;
+ c = getcmd(arg);
+ if (Ambiguous(c))
+ printf("?Ambiguous help command %s\n", arg);
+ else if (c == (Command *)0)
+ printf("?Invalid help command %s\n", arg);
+ else
+ printf("%s\n", c->help);
+ }
+ return 0;
+}
+
+static char *rcname = 0;
+static char rcbuf[128];
+
+void
+cmdrc(const char *m1, const char *m2)
+{
+ Command *c;
+ FILE *rcfile;
+ int gotmachine = 0;
+ int l1 = strlen(m1);
+ int l2 = strlen(m2);
+ char m1save[MAXHOSTNAMELEN + 1];
+
+ if (skiprc)
+ return;
+
+ strlcpy(m1save, m1, sizeof(m1save));
+ m1 = m1save;
+
+ if (rcname == 0) {
+ rcname = getenv("HOME");
+ if (rcname)
+ strlcpy(rcbuf, rcname, sizeof(rcbuf));
+ else
+ rcbuf[0] = '\0';
+ strlcat(rcbuf, "/.telnetrc", sizeof(rcbuf));
+ rcname = rcbuf;
+ }
+
+ if ((rcfile = fopen(rcname, "r")) == 0) {
+ return;
+ }
+
+ for (;;) {
+ if (fgets(line, sizeof(line), rcfile) == NULL)
+ break;
+ if (line[0] == 0)
+ break;
+ if (line[0] == '#')
+ continue;
+ if (gotmachine) {
+ if (!isspace((unsigned char)line[0]))
+ gotmachine = 0;
+ }
+ if (gotmachine == 0) {
+ if (isspace((unsigned char)line[0]))
+ continue;
+ if (strncasecmp(line, m1, l1) == 0)
+ strncpy(line, &line[l1], sizeof(line) - l1);
+ else if (strncasecmp(line, m2, l2) == 0)
+ strncpy(line, &line[l2], sizeof(line) - l2);
+ else if (strncasecmp(line, "DEFAULT", 7) == 0)
+ strncpy(line, &line[7], sizeof(line) - 7);
+ else
+ continue;
+ if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
+ continue;
+ gotmachine = 1;
+ }
+ makeargv();
+ if (margv[0] == 0)
+ continue;
+ c = getcmd(margv[0]);
+ if (Ambiguous(c)) {
+ printf("?Ambiguous command: %s\n", margv[0]);
+ continue;
+ }
+ if (c == 0) {
+ printf("?Invalid command: %s\n", margv[0]);
+ continue;
+ }
+ /*
+ * This should never happen...
+ */
+ if (c->needconnect && !connected) {
+ printf("?Need to be connected first for %s.\n", margv[0]);
+ continue;
+ }
+ (*c->handler)(margc, margv);
+ }
+ fclose(rcfile);
+}
+
+/*
+ * Source route is handed in as
+ * [!]@hop1@hop2...@dst
+ *
+ * If the leading ! is present, it is a strict source route, otherwise it is
+ * assmed to be a loose source route. Note that leading ! is effective
+ * only for IPv4 case.
+ *
+ * We fill in the source route option as
+ * hop1,hop2,hop3...dest
+ * and return a pointer to hop1, which will
+ * be the address to connect() to.
+ *
+ * Arguments:
+ * ai: The address (by struct addrinfo) for the final destination.
+ *
+ * arg: Pointer to route list to decipher
+ *
+ * cpp: Pointer to a pointer, so that sourceroute() can return
+ * the address of result buffer (statically alloc'ed).
+ *
+ * protop/optp:
+ * Pointer to an integer. The pointed variable
+ * lenp: pointer to an integer that contains the
+ * length of *cpp if *cpp != NULL.
+ *
+ * Return values:
+ *
+ * Returns the length of the option pointed to by *cpp. If the
+ * return value is -1, there was a syntax error in the
+ * option, either arg contained unknown characters or too many hosts,
+ * or hostname cannot be resolved.
+ *
+ * The caller needs to pass return value (len), *cpp, *protop and *optp
+ * to setsockopt(2).
+ *
+ * *cpp: Points to the result buffer. The region is statically
+ * allocated by the function.
+ *
+ * *protop:
+ * protocol # to be passed to setsockopt(2).
+ *
+ * *optp: option # to be passed to setsockopt(2).
+ *
+ */
+int
+sourceroute(struct addrinfo *ai, char *arg, char **cpp, int *protop, int *optp)
+{
+ char *cp, *cp2, *lsrp, *lsrep;
+ struct addrinfo hints, *res;
+ int len, error;
+ struct sockaddr_in *sin;
+ char c;
+ static char lsr[44];
+#ifdef INET6
+ struct cmsghdr *cmsg;
+ struct sockaddr_in6 *sin6;
+ static char rhbuf[1024];
+#endif
+
+ /*
+ * Verify the arguments.
+ */
+ if (cpp == NULL)
+ return -1;
+
+ cp = arg;
+
+ *cpp = NULL;
+
+ /* init these just in case.... */
+ lsrp = NULL;
+ lsrep = NULL;
+#ifdef INET6
+ cmsg = NULL;
+#endif
+
+ switch (ai->ai_family) {
+ case AF_INET:
+ lsrp = lsr;
+ lsrep = lsrp + sizeof(lsr);
+
+ /*
+ * Next, decide whether we have a loose source
+ * route or a strict source route, and fill in
+ * the begining of the option.
+ */
+ if (*cp == '!') {
+ cp++;
+ *lsrp++ = IPOPT_SSRR;
+ } else
+ *lsrp++ = IPOPT_LSRR;
+ if (*cp != '@')
+ return -1;
+ lsrp++; /* skip over length, we'll fill it in later */
+ *lsrp++ = 4;
+ cp++;
+ *protop = IPPROTO_IP;
+ *optp = IP_OPTIONS;
+ break;
+#ifdef INET6
+ case AF_INET6:
+#ifdef IPV6_PKTOPTIONS
+ /* RFC2292 */
+ cmsg = inet6_rthdr_init(rhbuf, IPV6_RTHDR_TYPE_0);
+ if (*cp != '@')
+ return -1;
+ cp++;
+ *protop = IPPROTO_IPV6;
+ *optp = IPV6_PKTOPTIONS;
+ break;
+#else
+ /* no RFC2292 */
+ return -1;
+#endif
+#endif
+ default:
+ return -1;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = ai->ai_family;
+ hints.ai_socktype = SOCK_STREAM;
+
+ for (c = 0;;) {
+ if (c == ':')
+ cp2 = 0;
+ else for (cp2 = cp; (c = *cp2) != '\0'; cp2++) {
+ if (c == ',') {
+ *cp2++ = '\0';
+ if (*cp2 == '@')
+ cp2++;
+ } else if (c == '@') {
+ *cp2++ = '\0';
+ }
+#if 0 /*colon conflicts with IPv6 address*/
+ else if (c == ':') {
+ *cp2++ = '\0';
+ }
+#endif
+ else
+ continue;
+ break;
+ }
+ if (!c)
+ cp2 = 0;
+
+ error = getaddrinfo(cp, NULL, &hints, &res);
+ if (error) {
+ fprintf(stderr, "%s: %s\n", cp, gai_strerror(error));
+ return -1;
+ }
+ if (ai->ai_family != res->ai_family) {
+ freeaddrinfo(res);
+ return -1;
+ }
+ if (ai->ai_family == AF_INET) {
+ /*
+ * Check to make sure there is space for address
+ */
+ if (lsrp + 4 > lsrep) {
+ freeaddrinfo(res);
+ return -1;
+ }
+ sin = (struct sockaddr_in *)res->ai_addr;
+ memcpy(lsrp, &sin->sin_addr, sizeof(struct in_addr));
+ lsrp += sizeof(struct in_addr);
+ }
+#ifdef INET6
+ else if (ai->ai_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)res->ai_addr;
+ inet6_rthdr_add(cmsg, &sin6->sin6_addr,
+ IPV6_RTHDR_LOOSE);
+ }
+#endif
+ else {
+ freeaddrinfo(res);
+ return -1;
+ }
+ freeaddrinfo(res);
+ if (cp2)
+ cp = cp2;
+ else
+ break;
+ }
+ switch (ai->ai_family) {
+ case AF_INET:
+ /* record the last hop */
+ if (lsrp + 4 > lsrep)
+ return -1;
+ sin = (struct sockaddr_in *)ai->ai_addr;
+ memcpy(lsrp, &sin->sin_addr, sizeof(struct in_addr));
+ lsrp += sizeof(struct in_addr);
+ lsr[IPOPT_OLEN] = lsrp - lsr;
+ if (lsr[IPOPT_OLEN] <= 7 || lsr[IPOPT_OLEN] > 40)
+ return -1;
+ *lsrp++ = IPOPT_NOP; /*32bit word align*/
+ len = lsrp - lsr;
+ *cpp = lsr;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
+ len = cmsg->cmsg_len;
+ *cpp = rhbuf;
+ break;
+#endif
+ default:
+ return -1;
+ }
+ return len;
+}
diff --git a/comms/tn3270/files/telnet/defines.h b/comms/tn3270/files/telnet/defines.h
new file mode 100644
index 00000000000..c2e70e86d3e
--- /dev/null
+++ b/comms/tn3270/files/telnet/defines.h
@@ -0,0 +1,60 @@
+/* $NetBSD: defines.h,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $ */
+/* From NetBSD: defines.h,v 1.8 2003/08/07 11:16:09 agc Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)defines.h 8.1 (Berkeley) 6/6/93
+ */
+
+#define settimer(x) clocks.x = clocks.system++
+
+#ifndef TN3270
+
+#define SetIn3270()
+
+#endif /* !defined(TN3270) */
+
+#define NETADD(c) { *netoring.supply = (c); ring_supplied(&netoring, 1); }
+#define NET2ADD(c1,c2) { NETADD((c1)); NETADD((c2)); }
+#define NETBYTES() (ring_full_count(&netoring))
+#define NETROOM() (ring_empty_count(&netoring))
+
+#define TTYADD(c) if (!(SYNCHing||flushout)) { \
+ *ttyoring.supply = c; \
+ ring_supplied(&ttyoring, 1); \
+ }
+#define TTYBYTES() (ring_full_count(&ttyoring))
+#define TTYROOM() (ring_empty_count(&ttyoring))
+
+/* Various modes */
+#define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG))
+#define MODE_LOCAL_ECHO(m) ((m)&MODE_ECHO)
+#define MODE_COMMAND_LINE(m) ((m)==-1)
+
+#define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */
diff --git a/comms/tn3270/files/telnet/externs.h b/comms/tn3270/files/telnet/externs.h
new file mode 100644
index 00000000000..d99762053d4
--- /dev/null
+++ b/comms/tn3270/files/telnet/externs.h
@@ -0,0 +1,414 @@
+/* $NetBSD: externs.h,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $ */
+/* From NetBSD: externs.h,v 1.34 2006/02/02 19:33:12 he Exp */
+
+/*
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)externs.h 8.3 (Berkeley) 5/30/95
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <setjmp.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <sys/termios.h>
+
+#include <string.h>
+
+#if defined(IPSEC)
+#include <netinet6/ipsec.h>
+#if defined(IPSEC_POLICY_IPSEC)
+extern char *ipsec_policy_in;
+extern char *ipsec_policy_out;
+#endif
+#endif
+
+#ifndef _POSIX_VDISABLE
+# ifdef sun
+# include <sys/param.h> /* pick up VDISABLE definition, mayby */
+# endif
+# ifdef VDISABLE
+# define _POSIX_VDISABLE VDISABLE
+# else
+# define _POSIX_VDISABLE ((cc_t)'\377')
+# endif
+#endif
+
+#define SUBBUFSIZE 256
+
+#include <sys/cdefs.h>
+
+extern int
+ autologin, /* Autologin enabled */
+ skiprc, /* Don't process the ~/.telnetrc file */
+ eight, /* use eight bit mode (binary in and/or out */
+ family, /* address family of peer */
+ flushout, /* flush output */
+ connected, /* Are we connected to the other side? */
+ globalmode, /* Mode tty should be in */
+ In3270, /* Are we in 3270 mode? */
+ telnetport, /* Are we connected to the telnet port? */
+ localflow, /* Flow control handled locally */
+ restartany, /* If flow control, restart output on any character */
+ localchars, /* we recognize interrupt/quit */
+ donelclchars, /* the user has set "localchars" */
+ showoptions,
+ net, /* Network file descriptor */
+ tin, /* Terminal input file descriptor */
+ tout, /* Terminal output file descriptor */
+ crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+ autoflush, /* flush output when interrupting? */
+ autosynch, /* send interrupt characters with SYNCH? */
+ SYNCHing, /* Is the stream in telnet SYNCH mode? */
+ donebinarytoggle, /* the user has put us in binary */
+ dontlecho, /* do we suppress local echoing right now? */
+ crmod,
+ netdata, /* Print out network data flow */
+ prettydump, /* Print "netdata" output in user readable format */
+#ifdef TN3270
+ cursesdata, /* Print out curses data flow */
+ apitrace, /* Trace API transactions */
+#endif /* defined(TN3270) */
+ termdata, /* Print out terminal data flow */
+ telnet_debug, /* Debug level */
+ doaddrlookup, /* do a reverse address lookup? */
+ clienteof; /* Client received EOF */
+
+extern cc_t escape; /* Escape to command mode */
+extern cc_t rlogin; /* Rlogin mode escape character */
+#ifdef KLUDGELINEMODE
+extern cc_t echoc; /* Toggle local echoing */
+#endif
+
+extern char
+ *prompt; /* Prompt for command. */
+
+extern char
+ doopt[],
+ dont[],
+ will[],
+ wont[],
+ options[], /* All the little options */
+ *hostname; /* Who are we connected to? */
+
+#ifdef ENCRYPTION
+extern void (*encrypt_output)(unsigned char *, int);
+extern int (*decrypt_input)(int);
+#endif /* ENCRYPTION */
+
+/*
+ * We keep track of each side of the option negotiation.
+ */
+
+#define MY_STATE_WILL 0x01
+#define MY_WANT_STATE_WILL 0x02
+#define MY_STATE_DO 0x04
+#define MY_WANT_STATE_DO 0x08
+
+/*
+ * Macros to check the current state of things
+ */
+
+#define my_state_is_do(opt) (options[opt]&MY_STATE_DO)
+#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL)
+#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO)
+#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL)
+
+#define my_state_is_dont(opt) (!my_state_is_do(opt))
+#define my_state_is_wont(opt) (!my_state_is_will(opt))
+#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt))
+#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt))
+
+#define set_my_state_do(opt) {options[opt] |= MY_STATE_DO;}
+#define set_my_state_will(opt) {options[opt] |= MY_STATE_WILL;}
+#define set_my_want_state_do(opt) {options[opt] |= MY_WANT_STATE_DO;}
+#define set_my_want_state_will(opt) {options[opt] |= MY_WANT_STATE_WILL;}
+
+#define set_my_state_dont(opt) {options[opt] &= ~MY_STATE_DO;}
+#define set_my_state_wont(opt) {options[opt] &= ~MY_STATE_WILL;}
+#define set_my_want_state_dont(opt) {options[opt] &= ~MY_WANT_STATE_DO;}
+#define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;}
+
+/*
+ * Make everything symmetrical
+ */
+
+#define HIS_STATE_WILL MY_STATE_DO
+#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO
+#define HIS_STATE_DO MY_STATE_WILL
+#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL
+
+#define his_state_is_do my_state_is_will
+#define his_state_is_will my_state_is_do
+#define his_want_state_is_do my_want_state_is_will
+#define his_want_state_is_will my_want_state_is_do
+
+#define his_state_is_dont my_state_is_wont
+#define his_state_is_wont my_state_is_dont
+#define his_want_state_is_dont my_want_state_is_wont
+#define his_want_state_is_wont my_want_state_is_dont
+
+#define set_his_state_do set_my_state_will
+#define set_his_state_will set_my_state_do
+#define set_his_want_state_do set_my_want_state_will
+#define set_his_want_state_will set_my_want_state_do
+
+#define set_his_state_dont set_my_state_wont
+#define set_his_state_wont set_my_state_dont
+#define set_his_want_state_dont set_my_want_state_wont
+#define set_his_want_state_wont set_my_want_state_dont
+
+
+extern FILE
+ *NetTrace; /* Where debugging output goes */
+extern char
+ NetTraceFile[]; /* Name of file where debugging output goes */
+
+extern jmp_buf
+ toplevel; /* For error conditions. */
+
+
+/* authenc.c */
+int telnet_net_write(unsigned char *, int);
+void net_encrypt(void);
+int telnet_spin(void);
+char *telnet_getenv(char *);
+char *telnet_gets(char *, char *, int, int);
+
+/* commands.c */
+int send_tncmd(void (*)(int, int), char *, char *);
+void _setlist_init(void);
+void set_escape_char(char *);
+int set_mode(int);
+int clear_mode(int);
+int modehelp(int);
+int suspend(int, char *[]);
+int shell(int, char *[]);
+int quit(int, char *[]);
+int logout(int, char *[]);
+int env_cmd(int, char *[]);
+struct env_lst *env_find(unsigned char *);
+void env_init(void);
+struct env_lst *env_define(unsigned char *, unsigned char *);
+struct env_lst *env_undefine(unsigned char *, unsigned char *);
+struct env_lst *env_export(unsigned char *, unsigned char *);
+struct env_lst *env_unexport(unsigned char *, unsigned char *);
+struct env_lst *env_send(unsigned char *, unsigned char *);
+struct env_lst *env_list(unsigned char *, unsigned char *);
+unsigned char *env_default(int, int );
+unsigned char *env_getvalue(unsigned char *);
+void env_varval(unsigned char *);
+int auth_cmd(int, char *[]);
+int ayt_status(void);
+int encrypt_cmd(int, char *[]);
+int tn(int, char *[]);
+void command(int, char *, int);
+void cmdrc(const char *, const char *);
+struct addrinfo;
+int sourceroute(struct addrinfo *, char *, char **, int *, int*);
+
+/* main.c */
+void tninit(void);
+void usage(void);
+
+/* network.c */
+void init_network(void);
+int stilloob(void);
+void setneturg(void);
+int netflush(void);
+
+/* sys_bsd.c */
+void init_sys(void);
+int TerminalWrite(char *, int);
+int TerminalRead(unsigned char *, int);
+int TerminalAutoFlush(void);
+int TerminalSpecialChars(int);
+void TerminalFlushOutput(void);
+void TerminalSaveState(void);
+cc_t *tcval(int);
+void TerminalDefaultChars(void);
+void TerminalRestoreState(void);
+void TerminalNewMode(int);
+void TerminalSpeeds(long *, long *);
+int TerminalWindowSize(long *, long *);
+int NetClose(int);
+void NetNonblockingIO(int, int);
+void NetSigIO(int, int);
+void NetSetPgrp(int);
+void sys_telnet_init(void);
+int process_rings(int , int , int , int , int , int);
+
+/* telnet.c */
+void init_telnet(void);
+void send_do(int, int );
+void send_dont(int, int );
+void send_will(int, int );
+void send_wont(int, int );
+void willoption(int);
+void wontoption(int);
+char **mklist(char *, char *);
+int is_unique(char *, char **, char **);
+int setup_term(char *, int, int *);
+char *gettermname(void);
+void lm_will(unsigned char *, int);
+void lm_wont(unsigned char *, int);
+void lm_do(unsigned char *, int);
+void lm_dont(unsigned char *, int);
+void lm_mode(unsigned char *, int, int );
+void slc_init(void);
+void slcstate(void);
+void slc_mode_export(int);
+void slc_mode_import(int);
+void slc_import(int);
+void slc_export(void);
+void slc(unsigned char *, int);
+void slc_check(void);
+void slc_start_reply(void);
+void slc_add_reply(unsigned int, unsigned int, cc_t);
+void slc_end_reply(void);
+int slc_update(void);
+void env_opt(unsigned char *, int);
+void env_opt_start(void);
+void env_opt_start_info(void);
+void env_opt_add(unsigned char *);
+int opt_welldefined(char *);
+void env_opt_end(int);
+int telrcv(void);
+int rlogin_susp(void);
+int Scheduler(int);
+void telnet(const char *);
+void xmitAO(void);
+void xmitEL(void);
+void xmitEC(void);
+int dosynch(char *);
+int get_status(char *);
+void intp(void);
+void sendbrk(void);
+void sendabort(void);
+void sendsusp(void);
+void sendeof(void);
+void sendayt(void);
+void sendnaws(void);
+void tel_enter_binary(int);
+void tel_leave_binary(int);
+
+/* terminal.c */
+void init_terminal(void);
+int ttyflush(int);
+int getconnmode(void);
+void setconnmode(int);
+void setcommandmode(void);
+
+/* utilities.c */
+void upcase(char *);
+int SetSockOpt(int, int, int, int);
+void SetNetTrace(char *);
+void Dump(int, unsigned char *, int);
+void printoption(char *, int, int );
+void optionstatus(void);
+void printsub(int, unsigned char *, int);
+void EmptyTerminal(void);
+void SetForExit(void);
+void Exit(int) __attribute__((__noreturn__));
+void ExitString(char *, int) __attribute__((__noreturn__));
+
+
+extern struct termios new_tc;
+
+# define termEofChar new_tc.c_cc[VEOF]
+# define termEraseChar new_tc.c_cc[VERASE]
+# define termIntChar new_tc.c_cc[VINTR]
+# define termKillChar new_tc.c_cc[VKILL]
+# define termQuitChar new_tc.c_cc[VQUIT]
+
+# define termSuspChar new_tc.c_cc[VSUSP]
+# define termFlushChar new_tc.c_cc[VDISCARD]
+# define termWerasChar new_tc.c_cc[VWERASE]
+# define termRprntChar new_tc.c_cc[VREPRINT]
+# define termLiteralNextChar new_tc.c_cc[VLNEXT]
+# define termStartChar new_tc.c_cc[VSTART]
+# define termStopChar new_tc.c_cc[VSTOP]
+# define termForw1Char new_tc.c_cc[VEOL]
+# define termForw2Char new_tc.c_cc[VEOL]
+# define termAytChar new_tc.c_cc[VSTATUS]
+
+# define termEofCharp &termEofChar
+# define termEraseCharp &termEraseChar
+# define termIntCharp &termIntChar
+# define termKillCharp &termKillChar
+# define termQuitCharp &termQuitChar
+# define termSuspCharp &termSuspChar
+# define termFlushCharp &termFlushChar
+# define termWerasCharp &termWerasChar
+# define termRprntCharp &termRprntChar
+# define termLiteralNextCharp &termLiteralNextChar
+# define termStartCharp &termStartChar
+# define termStopCharp &termStopChar
+# define termForw1Charp &termForw1Char
+# define termForw2Charp &termForw2Char
+# define termAytCharp &termAytChar
+
+
+/* Tn3270 section */
+#if defined(TN3270)
+
+extern int
+ HaveInput, /* Whether an asynchronous I/O indication came in */
+ noasynchtty, /* Don't do signals on I/O (SIGURG, SIGIO) */
+ noasynchnet, /* Don't do signals on I/O (SIGURG, SIGIO) */
+ sigiocount, /* Count of SIGIO receptions */
+ shell_active; /* Subshell is active */
+
+extern char
+ *Ibackp, /* Oldest byte of 3270 data */
+ Ibuf[], /* 3270 buffer */
+ *Ifrontp, /* Where next 3270 byte goes */
+ tline[200],
+ *transcom; /* Transparent command */
+
+/* tn3270.c */
+void init_3270(void);
+int DataToNetwork(char *, int, int);
+void inputAvailable(int);
+void outputPurge(void);
+int DataToTerminal(char *, int);
+int Push3270(void);
+void Finish3270(void);
+void StringToTerminal(char *);
+int _putchar(int);
+void SetIn3270(void);
+int tn3270_ttype(void);
+int settranscom(int, char *[]);
+int shell_continue(void);
+int DataFromTerminal(char *, int);
+int DataFromNetwork(char *, int, int);
+void ConnectScreen(void);
+int DoTerminalOutput(void);
+
+#endif /* defined(TN3270) */
diff --git a/comms/tn3270/files/telnet/general.h b/comms/tn3270/files/telnet/general.h
new file mode 100644
index 00000000000..35eb517e42f
--- /dev/null
+++ b/comms/tn3270/files/telnet/general.h
@@ -0,0 +1,44 @@
+/* $NetBSD: general.h,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $ */
+/* From NetBSD: general.h,v 1.6 2003/08/07 11:16:09 agc Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)general.h 8.1 (Berkeley) 6/6/93
+ */
+
+/*
+ * Some general definitions.
+ */
+
+
+#define numberof(x) (sizeof x/sizeof x[0])
+#define highestof(x) (numberof(x)-1)
+
+#define ClearElement(x) memset((char *)&x, 0, sizeof x)
+#define ClearArray(x) memset((char *)x, 0, sizeof x)
diff --git a/comms/tn3270/files/telnet/libtelnet/genget.c b/comms/tn3270/files/telnet/libtelnet/genget.c
new file mode 100644
index 00000000000..0b392e9e40e
--- /dev/null
+++ b/comms/tn3270/files/telnet/libtelnet/genget.c
@@ -0,0 +1,109 @@
+/* $NetBSD: genget.c,v 1.1.1.1 2010/01/17 01:33:33 dholland Exp $ */
+/* From NetBSD: genget.c,v 1.11 2004/10/28 21:14:52 dsl Exp */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)genget.c 8.2 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: genget.c,v 1.1.1.1 2010/01/17 01:33:33 dholland Exp $");
+#endif
+#endif /* not lint */
+
+
+#include <ctype.h>
+#include "misc.h"
+
+#define LOWER(x) (isupper((unsigned char)x) ? tolower((unsigned char)x) : (x))
+/*
+ * The prefix function returns 0 if *s1 is not a prefix
+ * of *s2. If *s1 exactly matches *s2, the negative of
+ * the length is returned. If *s1 is a prefix of *s2,
+ * the length of *s1 is returned.
+ */
+ int
+isprefix(s1, s2)
+ register char *s1, *s2;
+{
+ char *os1;
+ register char c1, c2;
+
+ if (*s1 == '\0')
+ return(-1);
+ os1 = s1;
+ c1 = *s1;
+ c2 = *s2;
+ while (LOWER(c1) == LOWER(c2)) {
+ if (c1 == '\0')
+ break;
+ c1 = *++s1;
+ c2 = *++s2;
+ }
+ return(*s1 ? 0 : (*s2 ? (s1 - os1) : (os1 - s1)));
+}
+
+static char *ambiguous; /* special return value for command routines */
+
+ char **
+genget(name, table, stlen)
+ char *name; /* name to match */
+ char **table; /* name entry in table */
+ int stlen;
+{
+ register char **c, **found;
+ register int n;
+
+ if (name == 0)
+ return 0;
+
+ found = 0;
+ for (c = table; *c != 0; c = (char **)((char *)c + stlen)) {
+ if ((n = isprefix(name, *c)) == 0)
+ continue;
+ if (n < 0) /* exact match */
+ return(c);
+ if (found)
+ return(&ambiguous);
+ found = c;
+ }
+ return(found);
+}
+
+/*
+ * Function call version of Ambiguous()
+ */
+ int
+Ambiguous(s)
+ void *s;
+{
+ return(s == &ambiguous);
+}
diff --git a/comms/tn3270/files/telnet/libtelnet/misc-proto.h b/comms/tn3270/files/telnet/libtelnet/misc-proto.h
new file mode 100644
index 00000000000..8c572e84858
--- /dev/null
+++ b/comms/tn3270/files/telnet/libtelnet/misc-proto.h
@@ -0,0 +1,73 @@
+/* $NetBSD: misc-proto.h,v 1.1.1.1 2010/01/17 01:33:33 dholland Exp $ */
+/* From NetBSD: misc-proto.h,v 1.10 2005/02/06 05:53:07 perry Exp */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)misc-proto.h 8.1 (Berkeley) 6/4/93
+ */
+
+/*
+ * Copyright (C) 1990 by the Massachusetts Institute of Technology
+ *
+ * Export of this software from the United States of America is assumed
+ * to require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ */
+
+#ifndef __MISC_PROTO__
+#define __MISC_PROTO__
+
+#include <sys/cdefs.h>
+
+void auth_encrypt_init(const char *, const char *, const char *, int);
+void auth_encrypt_user(const char *);
+void auth_encrypt_connect(int);
+void printd(const unsigned char *, int);
+
+/*
+ * These functions are imported from the application
+ */
+int telnet_net_write(unsigned char *, int);
+void net_encrypt(void);
+int telnet_spin(void);
+char *telnet_getenv(char *);
+char *telnet_gets(char *, char *, int, int);
+#endif
diff --git a/comms/tn3270/files/telnet/libtelnet/misc.h b/comms/tn3270/files/telnet/libtelnet/misc.h
new file mode 100644
index 00000000000..81ee339804b
--- /dev/null
+++ b/comms/tn3270/files/telnet/libtelnet/misc.h
@@ -0,0 +1,47 @@
+/* $NetBSD: misc.h,v 1.1.1.1 2010/01/17 01:33:33 dholland Exp $ */
+/* From NetBSD: misc.h,v 1.8 2005/02/06 05:53:07 perry Exp */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)misc.h 8.1 (Berkeley) 6/4/93
+ */
+
+__BEGIN_DECLS
+extern char *UserNameRequested;
+extern const char *LocalHostName;
+extern const char *RemoteHostName;
+extern int ConnectedCount;
+extern int ReservedPort;
+
+int isprefix(char *, char *);
+char **genget(char *, char **, int);
+int Ambiguous(void *);
+__END_DECLS
+
+#include "misc-proto.h"
diff --git a/comms/tn3270/files/telnet/main.c b/comms/tn3270/files/telnet/main.c
new file mode 100644
index 00000000000..c3b25b74e13
--- /dev/null
+++ b/comms/tn3270/files/telnet/main.c
@@ -0,0 +1,361 @@
+/* $NetBSD: main.c,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $ */
+/* From NetBSD: main.c,v 1.27 2008/07/21 14:19:26 lukem Exp */
+
+/*
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__COPYRIGHT("@(#) Copyright (c) 1988, 1990, 1993\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: main.c,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <unistd.h>
+
+#include "ring.h"
+#include "externs.h"
+#include "defines.h"
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#endif
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+/* These values need to be the same as defined in libtelnet/kerberos5.c */
+/* Either define them in both places, or put in some common header file. */
+#define OPTS_FORWARD_CREDS 0x00000002
+#define OPTS_FORWARDABLE_CREDS 0x00000001
+
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+char *ipsec_policy_in = NULL;
+char *ipsec_policy_out = NULL;
+#endif
+
+int family = AF_UNSPEC;
+
+int main(int, char *[]);
+
+/*
+ * Initialize variables.
+ */
+void
+tninit(void)
+{
+ init_terminal();
+
+ init_network();
+
+ init_telnet();
+
+ init_sys();
+
+#ifdef TN3270
+ init_3270();
+#endif
+}
+
+ void
+usage()
+{
+ fprintf(stderr, "usage: %s %s%s%s%s\n",
+ prompt,
+#ifdef AUTHENTICATION
+ "[-4] [-6] [-8] [-E] [-K] [-L] [-N] [-S tos] [-X atype] [-a] [-c]",
+ "\n\t[-d] [-e char] [-k realm] [-l user] [-f/-F] [-n tracefile] ",
+#else
+ "[-4] [-6] [-8] [-E] [-L] [-N] [-S tos] [-a] [-c] [-d] [-e char]",
+ "\n\t[-l user] [-n tracefile] ",
+#endif
+#ifdef TN3270
+# ifdef AUTHENTICATION
+ "[-noasynch] [-noasynctty]\n\t[-noasyncnet] [-r] [-t transcom] ",
+# else
+ "[-noasynch] [-noasynctty] [-noasyncnet] [-r]\n\t[-t transcom]",
+# endif
+#else
+ "[-r] ",
+#endif
+#ifdef ENCRYPTION
+ "[-x] "
+#endif
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ "\n\t[-P policy] [host-name [port]]"
+#else
+ "\n\t[host-name [port]]"
+#endif
+ );
+ exit(1);
+}
+
+/*
+ * main. Parse arguments, invoke the protocol or command parser.
+ */
+
+
+int
+main(int argc, char *argv[])
+{
+ extern char *optarg;
+ extern int optind;
+ int ch;
+ char *user;
+#ifdef FORWARD
+ extern int forward_flags;
+#endif /* FORWARD */
+
+ tninit(); /* Clear out things */
+
+ TerminalSaveState();
+
+ if ((prompt = strrchr(argv[0], '/')) != NULL)
+ ++prompt;
+ else
+ prompt = argv[0];
+
+ user = NULL;
+
+ rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
+ autologin = -1;
+
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+#define IPSECOPT "P:"
+#else
+#define IPSECOPT
+#endif
+ while ((ch = getopt(argc, argv, "468EKLNS:X:acde:fFk:l:n:rt:x"
+ IPSECOPT)) != -1) {
+#undef IPSECOPT
+ switch(ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case '8':
+ eight = 3; /* binary output and input */
+ break;
+ case 'E':
+ rlogin = escape = _POSIX_VDISABLE;
+ break;
+ case 'K':
+#ifdef AUTHENTICATION
+ autologin = 0;
+#endif
+ break;
+ case 'L':
+ eight |= 2; /* binary output only */
+ break;
+ case 'N':
+ doaddrlookup = 0;
+ break;
+ case 'S':
+ {
+ fprintf(stderr,
+ "%s: Warning: -S ignored, no parsetos() support.\n",
+ prompt);
+ }
+ break;
+ case 'X':
+#ifdef AUTHENTICATION
+ auth_disable_name(optarg);
+#endif
+ break;
+ case 'a':
+ autologin = 1;
+ break;
+ case 'c':
+ skiprc = 1;
+ break;
+ case 'd':
+ telnet_debug = 1;
+ break;
+ case 'e':
+ set_escape_char(optarg);
+ break;
+ case 'f':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+ if (forward_flags & OPTS_FORWARD_CREDS) {
+ fprintf(stderr,
+ "%s: Only one of -f and -F allowed.\n",
+ prompt);
+ usage();
+ }
+ forward_flags |= OPTS_FORWARD_CREDS;
+#else
+ fprintf(stderr,
+ "%s: Warning: -f ignored, no Kerberos V5 support.\n",
+ prompt);
+#endif
+ break;
+ case 'F':
+#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD)
+ if (forward_flags & OPTS_FORWARD_CREDS) {
+ fprintf(stderr,
+ "%s: Only one of -f and -F allowed.\n",
+ prompt);
+ usage();
+ }
+ forward_flags |= OPTS_FORWARD_CREDS;
+ forward_flags |= OPTS_FORWARDABLE_CREDS;
+#else
+ fprintf(stderr,
+ "%s: Warning: -F ignored, no Kerberos V5 support.\n",
+ prompt);
+#endif
+ break;
+ case 'k':
+ fprintf(stderr,
+ "%s: Warning: -k ignored, no Kerberos V4 support.\n",
+ prompt);
+ break;
+ case 'l':
+ if(autologin == 0) {
+ autologin = -1;
+ }
+ user = optarg;
+ break;
+ case 'n':
+#ifdef TN3270
+ /* distinguish between "-n oasynch" and "-noasynch" */
+ if (argv[optind - 1][0] == '-' && argv[optind - 1][1]
+ == 'n' && argv[optind - 1][2] == 'o') {
+ if (!strcmp(optarg, "oasynch")) {
+ noasynchtty = 1;
+ noasynchnet = 1;
+ } else if (!strcmp(optarg, "oasynchtty"))
+ noasynchtty = 1;
+ else if (!strcmp(optarg, "oasynchnet"))
+ noasynchnet = 1;
+ } else
+#endif /* defined(TN3270) */
+ SetNetTrace(optarg);
+ break;
+ case 'r':
+ rlogin = '~';
+ break;
+ case 't':
+#ifdef TN3270
+ (void)strlcpy(tline, optarg, sizeof(tline));
+ transcom = tline;
+#else
+ fprintf(stderr,
+ "%s: Warning: -t ignored, no TN3270 support.\n",
+ prompt);
+#endif
+ break;
+ case 'x':
+#ifdef ENCRYPTION
+ encrypt_auto(1);
+ decrypt_auto(1);
+#else /* ENCRYPTION */
+ fprintf(stderr,
+ "%s: Warning: -x ignored, no ENCRYPT support.\n",
+ prompt);
+#endif /* ENCRYPTION */
+ break;
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ case 'P':
+ if (!strncmp("in", optarg, 2))
+ ipsec_policy_in = strdup(optarg);
+ else if (!strncmp("out", optarg, 3))
+ ipsec_policy_out = strdup(optarg);
+ else
+ usage();
+ break;
+#endif
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (autologin == -1) { /* esc@magic.fi; force */
+#if defined(AUTHENTICATION)
+ autologin = 1;
+#endif
+#if defined(ENCRYPTION)
+ encrypt_auto(1);
+ decrypt_auto(1);
+#endif
+ }
+
+ if (autologin == -1)
+ autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1;
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc) {
+ char *args[7];
+ char ** volatile argp; /* avoid longjmp clobbering */
+
+ argp = args;
+ if (argc > 2)
+ usage();
+ *argp++ = prompt;
+ if (user) {
+ *argp++ = "-l";
+ *argp++ = user;
+ }
+ *argp++ = argv[0]; /* host */
+ if (argc > 1)
+ *argp++ = argv[1]; /* port */
+ *argp = 0;
+
+ if (setjmp(toplevel) != 0)
+ Exit(0);
+ if (tn(argp - args, args) == 1)
+ return (0);
+ else
+ return (1);
+ }
+ (void)setjmp(toplevel);
+ for (;;) {
+#ifdef TN3270
+ if (shell_active)
+ shell_continue();
+ else
+#endif
+ command(1, 0, 0);
+ }
+}
diff --git a/comms/tn3270/files/telnet/network.c b/comms/tn3270/files/telnet/network.c
new file mode 100644
index 00000000000..f2aefd91159
--- /dev/null
+++ b/comms/tn3270/files/telnet/network.c
@@ -0,0 +1,180 @@
+/* $NetBSD: network.c,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $ */
+/* From NetBSD: network.c,v 1.17 2004/03/20 23:26:05 heas Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)network.c 8.2 (Berkeley) 12/15/93";
+#else
+__RCSID("$NetBSD: network.c,v 1.1.1.1 2010/01/17 01:33:29 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <arpa/telnet.h>
+
+#include "ring.h"
+#include "defines.h"
+#include "externs.h"
+
+Ring netoring, netiring;
+unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ];
+
+/*
+ * Initialize internal network data structures.
+ */
+
+void
+init_network(void)
+{
+ if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) {
+ exit(1);
+ }
+ if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) {
+ exit(1);
+ }
+ NetTrace = stdout;
+}
+
+
+/*
+ * Check to see if any out-of-band data exists on a socket (for
+ * Telnet "synch" processing).
+ */
+
+int
+stilloob(void)
+{
+ struct pollfd set[1];
+ int value;
+
+ set[0].fd = net;
+ set[0].events = POLLPRI;
+ do {
+ value = poll(set, 1, 0);
+ } while ((value == -1) && (errno == EINTR));
+
+ if (value < 0) {
+ perror("poll");
+ (void) quit(0, NULL);
+ /* NOTREACHED */
+ }
+ if (set[0].revents & POLLPRI) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+/*
+ * setneturg()
+ *
+ * Sets "neturg" to the current location.
+ */
+
+void
+setneturg(void)
+{
+ ring_mark(&netoring);
+}
+
+
+/*
+ * netflush
+ * Send as much data as possible to the network,
+ * handling requests for urgent data.
+ *
+ * The return value indicates whether we did any
+ * useful work.
+ */
+
+
+int
+netflush(void)
+{
+ int n, n1;
+
+#ifdef ENCRYPTION
+ if (encrypt_output)
+ ring_encrypt(&netoring, encrypt_output);
+#endif /* ENCRYPTION */
+ if ((n1 = n = ring_full_consecutive(&netoring)) > 0) {
+ if (!ring_at_mark(&netoring)) {
+ n = send(net, (char *)netoring.consume, n, 0); /* normal write */
+ } else {
+ /*
+ * In 4.2 (and 4.3) systems, there is some question about
+ * what byte in a sendOOB operation is the "OOB" data.
+ * To make ourselves compatible, we only send ONE byte
+ * out of band, the one WE THINK should be OOB (though
+ * we really have more the TCP philosophy of urgent data
+ * rather than the Unix philosophy of OOB data).
+ */
+ n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */
+ }
+ }
+ if (n < 0) {
+ if (errno != ENOBUFS && errno != EWOULDBLOCK) {
+ setcommandmode();
+ perror(hostname);
+ (void)NetClose(net);
+ ring_clear_mark(&netoring);
+ ExitString("Connection closed by foreign host.\n", 1);
+ /*NOTREACHED*/
+ }
+ n = 0;
+ }
+ if (netdata && n) {
+ Dump('>', netoring.consume, n);
+ }
+ if (n) {
+ ring_consumed(&netoring, n);
+ /*
+ * If we sent all, and more to send, then recurse to pick
+ * up the other half.
+ */
+ if ((n1 == n) && ring_full_consecutive(&netoring)) {
+ (void) netflush();
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
diff --git a/comms/tn3270/files/telnet/ring.c b/comms/tn3270/files/telnet/ring.c
new file mode 100644
index 00000000000..a9cc5a155bf
--- /dev/null
+++ b/comms/tn3270/files/telnet/ring.c
@@ -0,0 +1,340 @@
+/* $NetBSD: ring.c,v 1.1.1.1 2010/01/17 01:33:30 dholland Exp $ */
+/* From NetBSD: ring.c,v 1.13 2003/08/07 11:16:10 agc Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: ring.c,v 1.1.1.1 2010/01/17 01:33:30 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * This defines a structure for a ring buffer.
+ *
+ * The circular buffer has two parts:
+ *(((
+ * full: [consume, supply)
+ * empty: [supply, consume)
+ *]]]
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include "ring.h"
+#include "general.h"
+
+/* Internal macros */
+
+#if !defined(MIN)
+#define MIN(a,b) (((a)<(b))? (a):(b))
+#endif /* !defined(MIN) */
+
+#define ring_subtract(d,a,b) (((a)-(b) >= 0)? \
+ (a)-(b): (((a)-(b))+(d)->size))
+
+#define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \
+ (a)+(c) : (((a)+(c))-(d)->size))
+
+#define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \
+ (a)-(c) : (((a)-(c))-(d)->size))
+
+
+/*
+ * The following is a clock, used to determine full, empty, etc.
+ *
+ * There is some trickiness here. Since the ring buffers are initialized
+ * to ZERO on allocation, we need to make sure, when interpreting the
+ * clock, that when the times are EQUAL, then the buffer is FULL.
+ */
+static u_long ring_clock = 0;
+
+
+#define ring_empty(d) (((d)->consume == (d)->supply) && \
+ ((d)->consumetime >= (d)->supplytime))
+#define ring_full(d) (((d)->supply == (d)->consume) && \
+ ((d)->supplytime > (d)->consumetime))
+
+
+
+
+
+/* Buffer state transition routines */
+
+int
+ring_init(Ring *ring, unsigned char *buffer, int count)
+{
+ memset((char *)ring, 0, sizeof *ring);
+
+ ring->size = count;
+
+ ring->supply = ring->consume = ring->bottom = buffer;
+
+ ring->top = ring->bottom+ring->size;
+
+#ifdef ENCRYPTION
+ ring->clearto = 0;
+#endif /* ENCRYPTION */
+
+ return 1;
+}
+
+/* Mark routines */
+
+/*
+ * Mark the most recently supplied byte.
+ */
+
+void
+ring_mark(Ring *ring)
+{
+ ring->mark = ring_decrement(ring, ring->supply, 1);
+}
+
+/*
+ * Is the ring pointing to the mark?
+ */
+
+int
+ring_at_mark(Ring *ring)
+{
+ if (ring->mark == ring->consume) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * Clear any mark set on the ring.
+ */
+
+void
+ring_clear_mark(Ring *ring)
+{
+ ring->mark = 0;
+}
+
+/*
+ * Add characters from current segment to ring buffer.
+ */
+void
+ring_supplied(Ring *ring, int count)
+{
+ ring->supply = ring_increment(ring, ring->supply, count);
+ ring->supplytime = ++ring_clock;
+}
+
+/*
+ * We have just consumed "c" bytes.
+ */
+void
+ring_consumed(Ring *ring, int count)
+{
+ if (count == 0) /* don't update anything */
+ return;
+
+ if (ring->mark &&
+ (ring_subtract(ring, ring->mark, ring->consume) < count)) {
+ ring->mark = 0;
+ }
+#ifdef ENCRYPTION
+ if (ring->consume < ring->clearto &&
+ ring->clearto <= ring->consume + count)
+ ring->clearto = 0;
+ else if (ring->consume + count > ring->top &&
+ ring->bottom <= ring->clearto &&
+ ring->bottom + ((ring->consume + count) - ring->top))
+ ring->clearto = 0;
+#endif /* ENCRYPTION */
+ ring->consume = ring_increment(ring, ring->consume, count);
+ ring->consumetime = ++ring_clock;
+ /*
+ * Try to encourage "ring_empty_consecutive()" to be large.
+ */
+ if (ring_empty(ring)) {
+ ring->consume = ring->supply = ring->bottom;
+ }
+}
+
+
+
+/* Buffer state query routines */
+
+
+/* Number of bytes that may be supplied */
+int
+ring_empty_count(Ring *ring)
+{
+ if (ring_empty(ring)) { /* if empty */
+ return ring->size;
+ } else {
+ return ring_subtract(ring, ring->consume, ring->supply);
+ }
+}
+
+/* number of CONSECUTIVE bytes that may be supplied */
+int
+ring_empty_consecutive(Ring *ring)
+{
+ if ((ring->consume < ring->supply) || ring_empty(ring)) {
+ /*
+ * if consume is "below" supply, or empty, then
+ * return distance to the top
+ */
+ return ring_subtract(ring, ring->top, ring->supply);
+ } else {
+ /*
+ * else, return what we may.
+ */
+ return ring_subtract(ring, ring->consume, ring->supply);
+ }
+}
+
+/* Return the number of bytes that are available for consuming
+ * (but don't give more than enough to get to cross over set mark)
+ */
+
+int
+ring_full_count(Ring *ring)
+{
+ if ((ring->mark == 0) || (ring->mark == ring->consume)) {
+ if (ring_full(ring)) {
+ return ring->size; /* nothing consumed, but full */
+ } else {
+ return ring_subtract(ring, ring->supply, ring->consume);
+ }
+ } else {
+ return ring_subtract(ring, ring->mark, ring->consume);
+ }
+}
+
+/*
+ * Return the number of CONSECUTIVE bytes available for consuming.
+ * However, don't return more than enough to cross over set mark.
+ */
+int
+ring_full_consecutive(Ring *ring)
+{
+ if ((ring->mark == 0) || (ring->mark == ring->consume)) {
+ if ((ring->supply < ring->consume) || ring_full(ring)) {
+ return ring_subtract(ring, ring->top, ring->consume);
+ } else {
+ return ring_subtract(ring, ring->supply, ring->consume);
+ }
+ } else {
+ if (ring->mark < ring->consume) {
+ return ring_subtract(ring, ring->top, ring->consume);
+ } else { /* Else, distance to mark */
+ return ring_subtract(ring, ring->mark, ring->consume);
+ }
+ }
+}
+
+/*
+ * Move data into the "supply" portion of of the ring buffer.
+ */
+void
+ring_supply_data(Ring *ring, unsigned char *buffer, int count)
+{
+ int i;
+
+ while (count) {
+ i = MIN(count, ring_empty_consecutive(ring));
+ memmove(ring->supply, buffer, i);
+ ring_supplied(ring, i);
+ count -= i;
+ buffer += i;
+ }
+}
+
+#ifdef notdef
+
+/*
+ * Move data from the "consume" portion of the ring buffer
+ */
+void
+ring_consume_data(Ring *ring, unsigned char *buffer, int count)
+{
+ int i;
+
+ while (count) {
+ i = MIN(count, ring_full_consecutive(ring));
+ memmove(buffer, ring->consume, i);
+ ring_consumed(ring, i);
+ count -= i;
+ buffer += i;
+ }
+}
+#endif
+
+#ifdef ENCRYPTION
+void
+ring_encrypt(Ring *ring, void (*encryptor)(unsigned char *, int))
+{
+ unsigned char *s, *c;
+
+ if (ring_empty(ring) || ring->clearto == ring->supply)
+ return;
+
+ if (!(c = ring->clearto))
+ c = ring->consume;
+
+ s = ring->supply;
+
+ if (s <= c) {
+ (*encryptor)(c, ring->top - c);
+ (*encryptor)(ring->bottom, s - ring->bottom);
+ } else
+ (*encryptor)(c, s - c);
+
+ ring->clearto = ring->supply;
+}
+
+void
+ring_clearto(Ring *ring)
+{
+
+ if (!ring_empty(ring))
+ ring->clearto = ring->supply;
+ else
+ ring->clearto = 0;
+}
+#endif /* ENCRYPTION */
diff --git a/comms/tn3270/files/telnet/ring.h b/comms/tn3270/files/telnet/ring.h
new file mode 100644
index 00000000000..071b3e978e0
--- /dev/null
+++ b/comms/tn3270/files/telnet/ring.h
@@ -0,0 +1,105 @@
+/* $NetBSD: ring.h,v 1.1.1.1 2010/01/17 01:33:30 dholland Exp $ */
+/* From NetBSD: ring.h,v 1.10 2003/08/07 11:16:10 agc Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ring.h 8.1 (Berkeley) 6/6/93
+ */
+
+#include <sys/cdefs.h>
+
+/*
+ * This defines a structure for a ring buffer.
+ *
+ * The circular buffer has two parts:
+ *(((
+ * full: [consume, supply)
+ * empty: [supply, consume)
+ *]]]
+ *
+ */
+typedef struct {
+ unsigned char *consume, /* where data comes out of */
+ *supply, /* where data comes in to */
+ *bottom, /* lowest address in buffer */
+ *top, /* highest address+1 in buffer */
+ *mark; /* marker (user defined) */
+#ifdef ENCRYPTION
+ unsigned char *clearto; /* Data to this point is clear text */
+ unsigned char *encryyptedto; /* Data is encrypted to here */
+#endif /* ENCRYPTION */
+ int size; /* size in bytes of buffer */
+ u_long consumetime, /* help us keep straight full, empty, etc. */
+ supplytime;
+} Ring;
+
+/* Ring buffer structures which are shared */
+
+extern Ring
+ netoring,
+ netiring,
+ ttyoring,
+ ttyiring;
+
+/* Here are some functions and macros to deal with the ring buffer */
+
+/* Initialization routine */
+extern int
+ ring_init(Ring *ring, unsigned char *buffer, int count);
+
+/* Data movement routines */
+extern void
+ ring_supply_data(Ring *ring, unsigned char *buffer, int count);
+#ifdef notdef
+extern void
+ ring_consume_data(Ring *ring, unsigned char *buffer, int count);
+#endif
+
+/* Buffer state transition routines */
+extern void
+ ring_supplied(Ring *ring, int count),
+ ring_consumed(Ring *ring, int count);
+
+/* Buffer state query routines */
+extern int
+ ring_empty_count(Ring *ring),
+ ring_empty_consecutive(Ring *ring),
+ ring_full_count(Ring *ring),
+ ring_full_consecutive(Ring *ring),
+ ring_at_mark(Ring *ring);
+
+#ifdef ENCRYPTION
+extern void
+ ring_encrypt(Ring *ring, void (*func)(unsigned char *, int)),
+ ring_clearto(Ring *ring);
+#endif /* ENCRYPTION */
+
+extern void
+ ring_clear_mark(Ring *ring),
+ ring_mark(Ring *ring);
diff --git a/comms/tn3270/files/telnet/sys_bsd.c b/comms/tn3270/files/telnet/sys_bsd.c
new file mode 100644
index 00000000000..fc0d340a509
--- /dev/null
+++ b/comms/tn3270/files/telnet/sys_bsd.c
@@ -0,0 +1,740 @@
+/* $NetBSD: sys_bsd.c,v 1.1.1.1 2010/01/17 01:33:30 dholland Exp $ */
+/* From NetBSD: sys_bsd.c,v 1.32 2004/11/10 20:26:43 christos Exp */
+
+/*
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+from: static char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: sys_bsd.c,v 1.1.1.1 2010/01/17 01:33:30 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * The following routines try to encapsulate what is system dependent
+ * (at least between 4.x and dos) which is used in telnet.c.
+ */
+
+
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <poll.h>
+#include <arpa/telnet.h>
+
+#include "ring.h"
+#include "defines.h"
+#include "externs.h"
+#include "types.h"
+
+#define SIG_FUNC_RET void
+
+SIG_FUNC_RET susp(int);
+SIG_FUNC_RET ayt(int);
+
+SIG_FUNC_RET intr(int);
+SIG_FUNC_RET intr2(int);
+SIG_FUNC_RET sendwin(int);
+
+
+int
+ tout, /* Output file descriptor */
+ tin, /* Input file descriptor */
+ net;
+
+struct termios old_tc = { 0 };
+extern struct termios new_tc;
+
+# ifndef TCSANOW
+# ifdef TCSETS
+# define TCSANOW TCSETS
+# define TCSADRAIN TCSETSW
+# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
+# else
+# ifdef TCSETA
+# define TCSANOW TCSETA
+# define TCSADRAIN TCSETAW
+# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
+# else
+# define TCSANOW TIOCSETA
+# define TCSADRAIN TIOCSETAW
+# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
+# endif
+# endif
+# define tcsetattr(f, a, t) ioctl(f, a, (char *)t)
+# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD)
+# ifdef CIBAUD
+# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
+# else
+# define cfgetispeed(ptr) cfgetospeed(ptr)
+# endif
+# endif /* TCSANOW */
+
+
+void
+init_sys(void)
+{
+ tout = fileno(stdout);
+ tin = fileno(stdin);
+
+ errno = 0;
+}
+
+
+int
+TerminalWrite(char *buf, int n)
+{
+ return write(tout, buf, n);
+}
+
+int
+TerminalRead(unsigned char *buf, int n)
+{
+ return read(tin, buf, n);
+}
+
+/*
+ *
+ */
+
+int
+TerminalAutoFlush(void)
+{
+ return 1;
+}
+
+#ifdef KLUDGELINEMODE
+extern int kludgelinemode;
+#endif
+/*
+ * TerminalSpecialChars()
+ *
+ * Look at an input character to see if it is a special character
+ * and decide what to do.
+ *
+ * Output:
+ *
+ * 0 Don't add this character.
+ * 1 Do add this character
+ */
+
+int
+TerminalSpecialChars(int c)
+{
+ if (c == termIntChar) {
+ intp();
+ return 0;
+ } else if (c == termQuitChar) {
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode)
+ sendbrk();
+ else
+#endif
+ sendabort();
+ return 0;
+ } else if (c == termEofChar) {
+ if (my_want_state_is_will(TELOPT_LINEMODE)) {
+ sendeof();
+ return 0;
+ }
+ return 1;
+ } else if (c == termSuspChar) {
+ sendsusp();
+ return(0);
+ } else if (c == termFlushChar) {
+ xmitAO(); /* Transmit Abort Output */
+ return 0;
+ } else if (!MODE_LOCAL_CHARS(globalmode)) {
+ if (c == termKillChar) {
+ xmitEL();
+ return 0;
+ } else if (c == termEraseChar) {
+ xmitEC(); /* Transmit Erase Character */
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+
+void
+TerminalFlushOutput(void)
+{
+ int com = 0;
+ (void) ioctl(fileno(stdout), TIOCFLUSH, &com);
+}
+
+void
+TerminalSaveState(void)
+{
+ tcgetattr(0, &old_tc);
+
+ new_tc = old_tc;
+}
+
+cc_t *
+tcval(int func)
+{
+ switch(func) {
+ case SLC_IP: return(&termIntChar);
+ case SLC_ABORT: return(&termQuitChar);
+ case SLC_EOF: return(&termEofChar);
+ case SLC_EC: return(&termEraseChar);
+ case SLC_EL: return(&termKillChar);
+ case SLC_XON: return(&termStartChar);
+ case SLC_XOFF: return(&termStopChar);
+ case SLC_FORW1: return(&termForw1Char);
+ case SLC_FORW2: return(&termForw2Char);
+ case SLC_AO: return(&termFlushChar);
+ case SLC_SUSP: return(&termSuspChar);
+ case SLC_EW: return(&termWerasChar);
+ case SLC_RP: return(&termRprntChar);
+ case SLC_LNEXT: return(&termLiteralNextChar);
+ case SLC_AYT: return(&termAytChar);
+
+ case SLC_SYNCH:
+ case SLC_BRK:
+ case SLC_EOR:
+ default:
+ return((cc_t *)0);
+ }
+}
+
+void
+TerminalDefaultChars(void)
+{
+ memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
+}
+
+#ifdef notdef
+void
+TerminalRestoreState(void)
+{
+}
+#endif
+
+/*
+ * TerminalNewMode - set up terminal to a specific mode.
+ * MODE_ECHO: do local terminal echo
+ * MODE_FLOW: do local flow control
+ * MODE_TRAPSIG: do local mapping to TELNET IAC sequences
+ * MODE_EDIT: do local line editing
+ *
+ * Command mode:
+ * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
+ * local echo
+ * local editing
+ * local xon/xoff
+ * local signal mapping
+ *
+ * Linemode:
+ * local/no editing
+ * Both Linemode and Single Character mode:
+ * local/remote echo
+ * local/no xon/xoff
+ * local/no signal mapping
+ */
+
+
+void
+TerminalNewMode(int f)
+{
+ static int prevmode = 0;
+ struct termios tmp_tc;
+ int onoff;
+ int old;
+ cc_t esc;
+
+ globalmode = f&~MODE_FORCE;
+ if (prevmode == f)
+ return;
+
+ /*
+ * Write any outstanding data before switching modes
+ * ttyflush() returns 0 only when there is no more data
+ * left to write out, it returns -1 if it couldn't do
+ * anything at all, otherwise it returns 1 + the number
+ * of characters left to write.
+#ifndef USE_TERMIO
+ * We would really like to ask the kernel to wait for the output
+ * to drain, like we can do with the TCSADRAIN, but we don't have
+ * that option. The only ioctl that waits for the output to
+ * drain, TIOCSETP, also flushes the input queue, which is NOT
+ * what we want (TIOCSETP is like TCSADFLUSH).
+#endif
+ */
+ old = ttyflush(SYNCHing|flushout);
+ if (old < 0 || old > 1) {
+ tcgetattr(tin, &tmp_tc);
+ do {
+ /*
+ * Wait for data to drain, then flush again.
+ */
+ tcsetattr(tin, TCSADRAIN, &tmp_tc);
+ old = ttyflush(SYNCHing|flushout);
+ } while (old < 0 || old > 1);
+ }
+
+ old = prevmode;
+ prevmode = f&~MODE_FORCE;
+ tmp_tc = new_tc;
+
+ if (f&MODE_ECHO) {
+ tmp_tc.c_lflag |= ECHO;
+ tmp_tc.c_oflag |= ONLCR;
+ if (crlf)
+ tmp_tc.c_iflag |= ICRNL;
+ } else {
+ tmp_tc.c_lflag &= ~ECHO;
+ tmp_tc.c_oflag &= ~ONLCR;
+# ifdef notdef
+ if (crlf)
+ tmp_tc.c_iflag &= ~ICRNL;
+# endif
+ }
+
+ if ((f&MODE_FLOW) == 0) {
+ tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */
+ } else {
+ if (restartany < 0) {
+ tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */
+ } else if (restartany > 0) {
+ tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
+ } else {
+ tmp_tc.c_iflag |= IXOFF|IXON;
+ tmp_tc.c_iflag &= ~IXANY;
+ }
+ }
+
+ if ((f&MODE_TRAPSIG) == 0) {
+ tmp_tc.c_lflag &= ~ISIG;
+ localchars = 0;
+ } else {
+ tmp_tc.c_lflag |= ISIG;
+ localchars = 1;
+ }
+
+ if (f&MODE_EDIT) {
+ tmp_tc.c_lflag |= ICANON;
+ } else {
+ tmp_tc.c_lflag &= ~ICANON;
+ tmp_tc.c_iflag &= ~ICRNL;
+ tmp_tc.c_cc[VMIN] = 1;
+ tmp_tc.c_cc[VTIME] = 0;
+ }
+
+ if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
+ tmp_tc.c_lflag &= ~IEXTEN;
+ }
+
+ if (f&MODE_SOFT_TAB) {
+# ifdef OXTABS
+ tmp_tc.c_oflag |= OXTABS;
+# endif
+# ifdef TABDLY
+ tmp_tc.c_oflag &= ~TABDLY;
+ tmp_tc.c_oflag |= TAB3;
+# endif
+ } else {
+# ifdef OXTABS
+ tmp_tc.c_oflag &= ~OXTABS;
+# endif
+# ifdef TABDLY
+ tmp_tc.c_oflag &= ~TABDLY;
+# endif
+ }
+
+ if (f&MODE_LIT_ECHO) {
+# ifdef ECHOCTL
+ tmp_tc.c_lflag &= ~ECHOCTL;
+# endif
+ } else {
+# ifdef ECHOCTL
+ tmp_tc.c_lflag |= ECHOCTL;
+# endif
+ }
+
+ if (f == -1) {
+ onoff = 0;
+ } else {
+ if (f & MODE_INBIN)
+ tmp_tc.c_iflag &= ~ISTRIP;
+ else
+ tmp_tc.c_iflag |= ISTRIP;
+ if (f & MODE_OUTBIN) {
+ tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+ tmp_tc.c_cflag |= CS8;
+ tmp_tc.c_oflag &= ~OPOST;
+ } else {
+ tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+ tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
+ tmp_tc.c_oflag |= OPOST;
+ }
+ onoff = 1;
+ }
+
+ if (f != -1) {
+ (void) signal(SIGTSTP, susp);
+ (void) signal(SIGINFO, ayt);
+#if defined(USE_TERMIO) && defined(NOKERNINFO)
+ tmp_tc.c_lflag |= NOKERNINFO;
+#endif
+ /*
+ * We don't want to process ^Y here. It's just another
+ * character that we'll pass on to the back end. It has
+ * to process it because it will be processed when the
+ * user attempts to read it, not when we send it.
+ */
+# ifdef VDSUSP
+ tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
+# endif
+ /*
+ * If the VEOL character is already set, then use VEOL2,
+ * otherwise use VEOL.
+ */
+ esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
+ if ((tmp_tc.c_cc[VEOL] != esc)
+# ifdef VEOL2
+ && (tmp_tc.c_cc[VEOL2] != esc)
+# endif
+ ) {
+ if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
+ tmp_tc.c_cc[VEOL] = esc;
+# ifdef VEOL2
+ else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
+ tmp_tc.c_cc[VEOL2] = esc;
+# endif
+ }
+ } else {
+ (void) signal(SIGINFO, (void (*)(int)) ayt_status);
+ (void) signal(SIGTSTP, SIG_DFL);
+ (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
+ tmp_tc = old_tc;
+ }
+ if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
+ tcsetattr(tin, TCSANOW, &tmp_tc);
+
+ ioctl(tin, FIONBIO, (char *)&onoff);
+ ioctl(tout, FIONBIO, (char *)&onoff);
+#if defined(TN3270)
+ if (noasynchtty == 0) {
+ ioctl(tin, FIOASYNC, (char *)&onoff);
+ }
+#endif /* defined(TN3270) */
+
+}
+
+void
+TerminalSpeeds(long *ispeed, long *ospeed)
+{
+ long in, out;
+
+ out = cfgetospeed(&old_tc);
+ in = cfgetispeed(&old_tc);
+ if (in == 0)
+ in = out;
+
+ *ispeed = in;
+ *ospeed = out;
+}
+
+int
+TerminalWindowSize(long *rows, long *cols)
+{
+ struct winsize ws;
+
+ if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
+ *rows = ws.ws_row;
+ *cols = ws.ws_col;
+ return 1;
+ }
+ return 0;
+}
+
+int
+NetClose(int fd)
+{
+ return close(fd);
+}
+
+
+void
+NetNonblockingIO(int fd, int onoff)
+{
+ ioctl(fd, FIONBIO, (char *)&onoff);
+}
+
+#ifdef TN3270
+void
+NetSigIO(int fd, int onoff)
+{
+ ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */
+}
+
+void
+NetSetPgrp(int fd)
+{
+ int myPid;
+
+ myPid = getpid();
+ fcntl(fd, F_SETOWN, myPid);
+}
+#endif /*defined(TN3270)*/
+
+/*
+ * Various signal handling routines.
+ */
+
+/* ARGSUSED */
+SIG_FUNC_RET
+intr(int sig)
+{
+ if (localchars) {
+ intp();
+ return;
+ }
+ setcommandmode();
+ longjmp(toplevel, -1);
+}
+
+/* ARGSUSED */
+SIG_FUNC_RET
+intr2(int sig)
+{
+ if (localchars) {
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode)
+ sendbrk();
+ else
+#endif
+ sendabort();
+ return;
+ }
+}
+
+/* ARGSUSED */
+SIG_FUNC_RET
+susp(int sig)
+{
+ if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
+ return;
+ if (localchars)
+ sendsusp();
+}
+
+/* ARGSUSED */
+SIG_FUNC_RET
+sendwin(int sig)
+{
+ if (connected) {
+ sendnaws();
+ }
+}
+
+/* ARGSUSED */
+SIG_FUNC_RET
+ayt(int sig)
+{
+ if (connected)
+ sendayt();
+ else
+ ayt_status();
+}
+
+
+void
+sys_telnet_init(void)
+{
+ (void) signal(SIGINT, intr);
+ (void) signal(SIGQUIT, intr2);
+ (void) signal(SIGPIPE, SIG_IGN);
+ (void) signal(SIGWINCH, sendwin);
+ (void) signal(SIGTSTP, susp);
+ (void) signal(SIGINFO, ayt);
+
+ setconnmode(0);
+
+ NetNonblockingIO(net, 1);
+
+#ifdef TN3270
+ if (noasynchnet == 0) { /* DBX can't handle! */
+ NetSigIO(net, 1);
+ NetSetPgrp(net);
+ }
+#endif /* defined(TN3270) */
+
+ if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
+ perror("SetSockOpt");
+ }
+}
+
+/*
+ * Process rings -
+ *
+ * This routine tries to fill up/empty our various rings.
+ *
+ * The parameter specifies whether this is a poll operation,
+ * or a block-until-something-happens operation.
+ *
+ * The return value is 1 if something happened, 0 if not, < 0 if an
+ * error occurred.
+ */
+
+int
+process_rings(int netin, int netout, int netex, int ttyin, int ttyout,
+ int dopoll) /* If 0, then block until something to do */
+{
+ struct pollfd set[3];
+ int c;
+ /* One wants to be a bit careful about setting returnValue
+ * to one, since a one implies we did some useful work,
+ * and therefore probably won't be called to block next
+ * time (TN3270 mode only).
+ */
+ int returnValue = 0;
+
+ set[0].fd = net;
+ set[0].events = (netout ? POLLOUT : 0) | (netin ? POLLIN : 0) |
+ (netex ? POLLPRI : 0);
+ set[1].fd = tout;
+ set[1].events = ttyout ? POLLOUT : 0;
+ set[2].fd = tin;
+ set[2].events = ttyin ? POLLIN : 0;
+
+ if ((c = poll(set, 3, dopoll ? 0 : INFTIM)) < 0) {
+ if (c == -1) {
+ /*
+ * we can get EINTR if we are in line mode,
+ * and the user does an escape (TSTP), or
+ * some other signal generator.
+ */
+ if (errno == EINTR) {
+ return 0;
+ }
+#ifdef TN3270
+ /*
+ * we can get EBADF if we were in transparent
+ * mode, and the transcom process died.
+ */
+ if (errno == EBADF)
+ return 0;
+#endif /* defined(TN3270) */
+ /* I don't like this, does it ever happen? */
+ printf("sleep(5) from telnet, after poll\r\n");
+ sleep(5);
+ }
+ return 0;
+ }
+
+ /*
+ * Any urgent data?
+ */
+ if (set[0].revents & POLLPRI) {
+ SYNCHing = 1;
+ (void) ttyflush(1); /* flush already enqueued data */
+ }
+
+ /*
+ * Something to read from the network...
+ */
+ if (set[0].revents & POLLIN) {
+ int canread;
+
+ canread = ring_empty_consecutive(&netiring);
+ c = recv(net, (char *)netiring.supply, canread, 0);
+ if (c < 0 && errno == EWOULDBLOCK) {
+ c = 0;
+ } else if (c <= 0) {
+ return -1;
+ }
+ if (netdata) {
+ Dump('<', netiring.supply, c);
+ }
+ if (c)
+ ring_supplied(&netiring, c);
+ returnValue = 1;
+ }
+
+ /*
+ * Something to read from the tty...
+ */
+ if (set[2].revents & POLLIN) {
+ c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
+ if (c < 0 && errno == EIO)
+ c = 0;
+ if (c < 0 && errno == EWOULDBLOCK) {
+ c = 0;
+ } else {
+ if (c < 0) {
+ return -1;
+ }
+ if (c == 0) {
+ /* must be an EOF... */
+ if (MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
+ *ttyiring.supply = termEofChar;
+ c = 1;
+ } else {
+ clienteof = 1;
+ shutdown(net, 1);
+ return 0;
+ }
+ }
+ if (termdata) {
+ Dump('<', ttyiring.supply, c);
+ }
+ ring_supplied(&ttyiring, c);
+ }
+ returnValue = 1; /* did something useful */
+ }
+
+ if (set[0].revents & POLLOUT) {
+ returnValue |= netflush();
+ }
+
+ if (set[1].revents & (POLLHUP|POLLNVAL))
+ return(-1);
+
+ if (set[1].revents & POLLOUT) {
+ returnValue |= (ttyflush(SYNCHing|flushout) > 0);
+ }
+
+ return returnValue;
+}
diff --git a/comms/tn3270/files/telnet/telnet.c b/comms/tn3270/files/telnet/telnet.c
new file mode 100644
index 00000000000..a4058086543
--- /dev/null
+++ b/comms/tn3270/files/telnet/telnet.c
@@ -0,0 +1,2651 @@
+/* $NetBSD: telnet.c,v 1.1.1.1 2010/01/17 01:33:31 dholland Exp $ */
+/* From NetBSD: telnet.c,v 1.31 2006/02/02 19:33:12 he Exp */
+
+/*
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: telnet.c,v 1.1.1.1 2010/01/17 01:33:31 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <signal.h>
+#include <termcap.h>
+#include <unistd.h>
+/* By the way, we need to include curses.h before telnet.h since,
+ * among other things, telnet.h #defines 'DO', which is a variable
+ * declared in curses.h.
+ */
+
+#include <arpa/telnet.h>
+
+#include <ctype.h>
+
+#include "ring.h"
+#include "defines.h"
+#include "externs.h"
+#include "types.h"
+#include "general.h"
+
+#include <libtelnet/misc.h>
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#endif
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+
+#define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
+
+static unsigned char subbuffer[SUBBUFSIZE],
+ *subpointer, *subend; /* buffer for sub-options */
+#define SB_CLEAR() subpointer = subbuffer;
+#define SB_TERM() { subend = subpointer; SB_CLEAR(); }
+#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
+ *subpointer++ = (c); \
+ }
+
+#define SB_GET() ((*subpointer++)&0xff)
+#define SB_PEEK() ((*subpointer)&0xff)
+#define SB_EOF() (subpointer >= subend)
+#define SB_LEN() (subend - subpointer)
+
+char options[256]; /* The combined options */
+char do_dont_resp[256];
+char will_wont_resp[256];
+
+int
+ eight = 0,
+ autologin = 0, /* Autologin anyone? */
+ skiprc = 0,
+ connected,
+ showoptions,
+ In3270, /* Are we in 3270 mode? */
+ ISend, /* trying to send network data in */
+ telnet_debug = 0,
+ crmod,
+ netdata, /* Print out network data flow */
+ crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
+#ifdef TN3270
+ noasynchtty = 0,/* User specified "-noasynch" on command line */
+ noasynchnet = 0,/* User specified "-noasynch" on command line */
+ askedSGA = 0, /* We have talked about suppress go ahead */
+#endif /* defined(TN3270) */
+ telnetport,
+ SYNCHing, /* we are in TELNET SYNCH mode */
+ flushout, /* flush output */
+ autoflush = 0, /* flush output when interrupting? */
+ autosynch, /* send interrupt characters with SYNCH? */
+ localflow, /* we handle flow control locally */
+ restartany, /* if flow control enabled, restart on any character */
+ localchars, /* we recognize interrupt/quit */
+ donelclchars, /* the user has set "localchars" */
+ donebinarytoggle, /* the user has put us in binary */
+ dontlecho, /* do we suppress local echoing right now? */
+ globalmode,
+ doaddrlookup = 1, /* do a reverse address lookup? */
+ clienteof = 0;
+
+char *prompt = 0;
+
+cc_t escape;
+cc_t rlogin;
+#ifdef KLUDGELINEMODE
+cc_t echoc;
+#endif
+
+/*
+ * Telnet receiver states for fsm
+ */
+#define TS_DATA 0
+#define TS_IAC 1
+#define TS_WILL 2
+#define TS_WONT 3
+#define TS_DO 4
+#define TS_DONT 5
+#define TS_CR 6
+#define TS_SB 7 /* sub-option collection */
+#define TS_SE 8 /* looking for sub-option end */
+
+static int telrcv_state;
+#ifdef OLD_ENVIRON
+unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
+#else
+# define telopt_environ TELOPT_NEW_ENVIRON
+#endif
+
+jmp_buf toplevel = { 0 };
+
+int flushline;
+int linemode;
+
+#ifdef KLUDGELINEMODE
+int kludgelinemode = 1;
+#endif
+
+static void dooption(int);
+static void dontoption(int);
+static void suboption(void);
+static int telsnd(void);
+static void netclear(void);
+static void doflush(void);
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+Clocks clocks;
+
+#ifdef notdef
+Modelist modelist[] = {
+ { "telnet command mode", COMMAND_LINE },
+ { "character-at-a-time mode", 0 },
+ { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
+ { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
+ { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
+ { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
+ { "3270 mode", 0 },
+};
+#endif
+
+
+/*
+ * Initialize telnet environment.
+ */
+
+void
+init_telnet(void)
+{
+ env_init();
+
+ SB_CLEAR();
+ ClearArray(options);
+
+ connected = In3270 = ISend = localflow = donebinarytoggle = 0;
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ auth_encrypt_connect(connected);
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+ restartany = -1;
+
+ SYNCHing = 0;
+
+ /* Don't change NetTrace */
+
+ escape = CONTROL(']');
+ rlogin = _POSIX_VDISABLE;
+#ifdef KLUDGELINEMODE
+ echoc = CONTROL('E');
+#endif
+
+ flushline = 1;
+ telrcv_state = TS_DATA;
+}
+
+
+#ifdef notdef
+#include <stdarg.h>
+
+/*VARARGS*/
+static void
+printring(Ring *ring, char *format, ...)
+ va_dcl
+{
+ va_list ap;
+ char buffer[100]; /* where things go */
+ char *ptr;
+ char *string;
+ int i;
+
+ va_start(ap, format);
+
+ ptr = buffer;
+
+ while ((i = *format++) != 0) {
+ if (i == '%') {
+ i = *format++;
+ switch (i) {
+ case 'c':
+ *ptr++ = va_arg(ap, int);
+ break;
+ case 's':
+ string = va_arg(ap, char *);
+ ring_supply_data(ring, buffer, ptr-buffer);
+ ring_supply_data(ring, string, strlen(string));
+ ptr = buffer;
+ break;
+ case 0:
+ ExitString("printring: trailing %%.\n", 1);
+ /*NOTREACHED*/
+ default:
+ ExitString("printring: unknown format character.\n", 1);
+ /*NOTREACHED*/
+ }
+ } else {
+ *ptr++ = i;
+ }
+ }
+ va_end(ap);
+ ring_supply_data(ring, buffer, ptr-buffer);
+}
+#endif
+
+/*
+ * These routines are in charge of sending option negotiations
+ * to the other side.
+ *
+ * The basic idea is that we send the negotiation if either side
+ * is in disagreement as to what the current state should be.
+ */
+
+void
+send_do(int c, int init)
+{
+ if (init) {
+ if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
+ my_want_state_is_do(c))
+ return;
+ set_my_want_state_do(c);
+ do_dont_resp[c]++;
+ }
+ NET2ADD(IAC, DO);
+ NETADD(c);
+ printoption("SENT", DO, c);
+}
+
+void
+send_dont(int c, int init)
+{
+ if (init) {
+ if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
+ my_want_state_is_dont(c))
+ return;
+ set_my_want_state_dont(c);
+ do_dont_resp[c]++;
+ }
+ NET2ADD(IAC, DONT);
+ NETADD(c);
+ printoption("SENT", DONT, c);
+}
+
+void
+send_will(int c, int init)
+{
+ if (init) {
+ if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
+ my_want_state_is_will(c))
+ return;
+ set_my_want_state_will(c);
+ will_wont_resp[c]++;
+ }
+ NET2ADD(IAC, WILL);
+ NETADD(c);
+ printoption("SENT", WILL, c);
+}
+
+void
+send_wont(int c, int init)
+{
+ if (init) {
+ if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
+ my_want_state_is_wont(c))
+ return;
+ set_my_want_state_wont(c);
+ will_wont_resp[c]++;
+ }
+ NET2ADD(IAC, WONT);
+ NETADD(c);
+ printoption("SENT", WONT, c);
+}
+
+
+void
+willoption(int option)
+{
+ int new_state_ok = 0;
+
+ if (do_dont_resp[option]) {
+ --do_dont_resp[option];
+ if (do_dont_resp[option] && my_state_is_do(option))
+ --do_dont_resp[option];
+ }
+
+ if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
+
+ switch (option) {
+
+ case TELOPT_ECHO:
+# if defined(TN3270)
+ /*
+ * The following is a pain in the rear-end.
+ * Various IBM servers (some versions of Wiscnet,
+ * possibly Fibronics/Spartacus, and who knows who
+ * else) will NOT allow us to send "DO SGA" too early
+ * in the setup proceedings. On the other hand,
+ * 4.2 servers (telnetd) won't set SGA correctly.
+ * So, we are stuck. Empirically (but, based on
+ * a VERY small sample), the IBM servers don't send
+ * out anything about ECHO, so we postpone our sending
+ * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
+ * DO send).
+ */
+ {
+ if (askedSGA == 0) {
+ askedSGA = 1;
+ if (my_want_state_is_dont(TELOPT_SGA))
+ send_do(TELOPT_SGA, 1);
+ }
+ }
+ /* Fall through */
+ case TELOPT_EOR:
+#endif /* defined(TN3270) */
+ case TELOPT_BINARY:
+ case TELOPT_SGA:
+ settimer(modenegotiated);
+ /* FALL THROUGH */
+ case TELOPT_STATUS:
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+#endif /* ENCRYPTION */
+#endif
+ new_state_ok = 1;
+ break;
+
+ case TELOPT_TM:
+ if (flushout)
+ flushout = 0;
+ /*
+ * Special case for TM. If we get back a WILL,
+ * pretend we got back a WONT.
+ */
+ set_my_want_state_dont(option);
+ set_my_state_dont(option);
+ return; /* Never reply to TM will's/wont's */
+
+ case TELOPT_LINEMODE:
+ default:
+ break;
+ }
+
+ if (new_state_ok) {
+ set_my_want_state_do(option);
+ send_do(option, 0);
+ setconnmode(0); /* possibly set new tty mode */
+ } else {
+ do_dont_resp[option]++;
+ send_dont(option, 0);
+ }
+ }
+ set_my_state_do(option);
+#ifdef ENCRYPTION
+ if (option == TELOPT_ENCRYPT)
+ encrypt_send_support();
+#endif /* ENCRYPTION */
+}
+
+void
+wontoption(int option)
+{
+ if (do_dont_resp[option]) {
+ --do_dont_resp[option];
+ if (do_dont_resp[option] && my_state_is_dont(option))
+ --do_dont_resp[option];
+ }
+
+ if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
+
+ switch (option) {
+
+#ifdef KLUDGELINEMODE
+ case TELOPT_SGA:
+ if (!kludgelinemode)
+ break;
+ /* FALL THROUGH */
+#endif
+ case TELOPT_ECHO:
+ settimer(modenegotiated);
+ break;
+
+ case TELOPT_TM:
+ if (flushout)
+ flushout = 0;
+ set_my_want_state_dont(option);
+ set_my_state_dont(option);
+ return; /* Never reply to TM will's/wont's */
+
+ default:
+ break;
+ }
+ set_my_want_state_dont(option);
+ if (my_state_is_do(option))
+ send_dont(option, 0);
+ setconnmode(0); /* Set new tty mode */
+ } else if (option == TELOPT_TM) {
+ /*
+ * Special case for TM.
+ */
+ if (flushout)
+ flushout = 0;
+ set_my_want_state_dont(option);
+ }
+ set_my_state_dont(option);
+}
+
+static void
+dooption(int option)
+{
+ int new_state_ok = 0;
+
+ if (will_wont_resp[option]) {
+ --will_wont_resp[option];
+ if (will_wont_resp[option] && my_state_is_will(option))
+ --will_wont_resp[option];
+ }
+
+ if (will_wont_resp[option] == 0) {
+ if (my_want_state_is_wont(option)) {
+
+ switch (option) {
+
+ case TELOPT_TM:
+ /*
+ * Special case for TM. We send a WILL, but pretend
+ * we sent WONT.
+ */
+ send_will(option, 0);
+ set_my_want_state_wont(TELOPT_TM);
+ set_my_state_wont(TELOPT_TM);
+ return;
+
+# if defined(TN3270)
+ case TELOPT_EOR: /* end of record */
+# endif /* defined(TN3270) */
+ case TELOPT_BINARY: /* binary mode */
+ case TELOPT_NAWS: /* window size */
+ case TELOPT_TSPEED: /* terminal speed */
+ case TELOPT_LFLOW: /* local flow control */
+ case TELOPT_TTYPE: /* terminal type option */
+ case TELOPT_SGA: /* no big deal */
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT: /* encryption variable option */
+#endif /* ENCRYPTION */
+ new_state_ok = 1;
+ break;
+
+ case TELOPT_NEW_ENVIRON: /* New environment variable option */
+#ifdef OLD_ENVIRON
+ if (my_state_is_will(TELOPT_OLD_ENVIRON))
+ send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
+ goto env_common;
+ case TELOPT_OLD_ENVIRON: /* Old environment variable option */
+ if (my_state_is_will(TELOPT_NEW_ENVIRON))
+ break; /* Don't enable if new one is in use! */
+ env_common:
+ telopt_environ = option;
+#endif
+ new_state_ok = 1;
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ if (autologin)
+ new_state_ok = 1;
+ break;
+#endif
+
+ case TELOPT_XDISPLOC: /* X Display location */
+ if (env_getvalue((unsigned char *)"DISPLAY"))
+ new_state_ok = 1;
+ break;
+
+ case TELOPT_LINEMODE:
+#ifdef KLUDGELINEMODE
+ kludgelinemode = 0;
+ send_do(TELOPT_SGA, 1);
+#endif
+ set_my_want_state_will(TELOPT_LINEMODE);
+ send_will(option, 0);
+ set_my_state_will(TELOPT_LINEMODE);
+ slc_init();
+ return;
+
+ case TELOPT_ECHO: /* We're never going to echo... */
+ default:
+ break;
+ }
+
+ if (new_state_ok) {
+ set_my_want_state_will(option);
+ send_will(option, 0);
+ setconnmode(0); /* Set new tty mode */
+ } else {
+ will_wont_resp[option]++;
+ send_wont(option, 0);
+ }
+ } else {
+ /*
+ * Handle options that need more things done after the
+ * other side has acknowledged the option.
+ */
+ switch (option) {
+ case TELOPT_LINEMODE:
+#ifdef KLUDGELINEMODE
+ kludgelinemode = 0;
+ send_do(TELOPT_SGA, 1);
+#endif
+ set_my_state_will(option);
+ slc_init();
+ send_do(TELOPT_SGA, 0);
+ return;
+ }
+ }
+ }
+ set_my_state_will(option);
+}
+
+static void
+dontoption(int option)
+{
+
+ if (will_wont_resp[option]) {
+ --will_wont_resp[option];
+ if (will_wont_resp[option] && my_state_is_wont(option))
+ --will_wont_resp[option];
+ }
+
+ if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
+ switch (option) {
+ case TELOPT_LINEMODE:
+ linemode = 0; /* put us back to the default state */
+ break;
+#ifdef OLD_ENVIRON
+ case TELOPT_NEW_ENVIRON:
+ /*
+ * The new environ option wasn't recognized, try
+ * the old one.
+ */
+ send_will(TELOPT_OLD_ENVIRON, 1);
+ telopt_environ = TELOPT_OLD_ENVIRON;
+ break;
+#endif
+ }
+ /* we always accept a DONT */
+ set_my_want_state_wont(option);
+ if (my_state_is_will(option))
+ send_wont(option, 0);
+ setconnmode(0); /* Set new tty mode */
+ }
+ set_my_state_wont(option);
+}
+
+/*
+ * Given a buffer returned by tgetent(), this routine will turn
+ * the pipe separated list of names in the buffer into an array
+ * of pointers to null terminated names. We toss out any bad,
+ * duplicate, or verbose names (names with spaces).
+ */
+
+static char *name_unknown = "UNKNOWN";
+static char *unknown[] = { 0, 0 };
+
+char **
+mklist(char *buf, char *name)
+{
+ int n;
+ char c, *cp, **argvp, *cp2, **argv, **avt;
+
+ if (name) {
+ if ((int)strlen(name) > 40) {
+ name = 0;
+ unknown[0] = name_unknown;
+ } else {
+ unknown[0] = name;
+ upcase(name);
+ }
+ } else
+ unknown[0] = name_unknown;
+ /*
+ * Count up the number of names.
+ */
+ for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
+ if (*cp == '|')
+ n++;
+ }
+ /*
+ * Allocate an array to put the name pointers into
+ */
+ argv = (char **)malloc((n+3)*sizeof(char *));
+ if (argv == 0)
+ return(unknown);
+
+ /*
+ * Fill up the array of pointers to names.
+ */
+ *argv = 0;
+ argvp = argv+1;
+ n = 0;
+ for (cp = cp2 = buf; (c = *cp); cp++) {
+ if (c == '|' || c == ':') {
+ *cp++ = '\0';
+ /*
+ * Skip entries that have spaces or are over 40
+ * characters long. If this is our environment
+ * name, then put it up front. Otherwise, as
+ * long as this is not a duplicate name (case
+ * insensitive) add it to the list.
+ */
+ if (n || (cp - cp2 > 41))
+ ;
+ else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
+ *argv = cp2;
+ else if (is_unique(cp2, argv+1, argvp))
+ *argvp++ = cp2;
+ if (c == ':')
+ break;
+ /*
+ * Skip multiple delimiters. Reset cp2 to
+ * the beginning of the next name. Reset n,
+ * the flag for names with spaces.
+ */
+ while ((c = *cp) == '|')
+ cp++;
+ cp2 = cp;
+ n = 0;
+ }
+ /*
+ * Skip entries with spaces or non-ascii values.
+ * Convert lower case letters to upper case.
+ */
+ if ((c == ' ') || !isascii(c))
+ n = 1;
+ else if (islower((unsigned char)c))
+ *cp = toupper((unsigned char)c);
+ }
+
+ /*
+ * Check for an old V6 2 character name. If the second
+ * name points to the beginning of the buffer, and is
+ * only 2 characters long, move it to the end of the array.
+ */
+ if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
+ --argvp;
+ for (avt = &argv[1]; avt < argvp; avt++)
+ *avt = *(avt+1);
+ *argvp++ = buf;
+ }
+
+ /*
+ * Duplicate last name, for TTYPE option, and null
+ * terminate the array. If we didn't find a match on
+ * our terminal name, put that name at the beginning.
+ */
+ cp = *(argvp-1);
+ *argvp++ = cp;
+ *argvp = 0;
+
+ if (*argv == 0) {
+ if (name)
+ *argv = name;
+ else {
+ --argvp;
+ for (avt = argv; avt < argvp; avt++)
+ *avt = *(avt+1);
+ }
+ }
+ if (*argv)
+ return(argv);
+ else
+ return(unknown);
+}
+
+int
+is_unique(char *name, char **as, char **ae)
+{
+ char **ap;
+ int n;
+
+ n = strlen(name) + 1;
+ for (ap = as; ap < ae; ap++)
+ if (strncasecmp(*ap, name, n) == 0)
+ return(0);
+ return (1);
+}
+
+#ifdef TERMCAP
+char *termbuf;
+
+/*ARGSUSED*/
+int
+setup_term(char *tname, int fd, int *errp)
+{
+ char zz[1024], *zz_ptr;
+ char *ext_tc, *newptr;
+
+ if ((termbuf = (char *) malloc(1024)) == NULL)
+ goto error;
+
+ if (tgetent(termbuf, tname) == 1) {
+ /* check for ZZ capability, which indicates termcap truncated */
+ zz_ptr = zz;
+ if (tgetstr("ZZ", &zz_ptr) != NULL) {
+ /* it was, fish back the full termcap */
+ sscanf(zz, "%p", &ext_tc);
+ if ((newptr = (char *) realloc(termbuf,
+ strlen(ext_tc) + 1))
+ == NULL) {
+ goto error;
+ }
+
+ strlcpy(newptr, ext_tc, strlen(ext_tc) + 1);
+ termbuf = newptr;
+ }
+
+ if (errp)
+ *errp = 1;
+ return(0);
+ }
+ error:
+ if (errp)
+ *errp = 0;
+ return(-1);
+}
+#else
+#define termbuf ttytype
+extern char ttytype[];
+#endif
+
+int resettermname = 1;
+
+char *
+gettermname(void)
+{
+ char *tname;
+ static char **tnamep = 0;
+ static char **next;
+ int err;
+
+ if (resettermname) {
+ resettermname = 0;
+ if (tnamep && tnamep != unknown)
+ free(tnamep);
+ if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
+ (setup_term(tname, 1, &err) == 0)) {
+ tnamep = mklist(termbuf, tname);
+ } else {
+ if (tname && ((int)strlen(tname) <= 40)) {
+ unknown[0] = tname;
+ upcase(tname);
+ } else
+ unknown[0] = name_unknown;
+ tnamep = unknown;
+ }
+ next = tnamep;
+ }
+ if (*next == 0)
+ next = tnamep;
+ return(*next++);
+}
+/*
+ * suboption()
+ *
+ * Look at the sub-option buffer, and try to be helpful to the other
+ * side.
+ *
+ * Currently we recognize:
+ *
+ * Terminal type, send request.
+ * Terminal speed (send request).
+ * Local flow control (is request).
+ * Linemode
+ */
+
+static void
+suboption(void)
+{
+ unsigned char subchar;
+
+ printsub('<', subbuffer, SB_LEN()+2);
+ switch (subchar = SB_GET()) {
+ case TELOPT_TTYPE:
+ if (my_want_state_is_wont(TELOPT_TTYPE))
+ return;
+ if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
+ return;
+ } else {
+ char *name;
+ unsigned char temp[50];
+ int len;
+
+#ifdef TN3270
+ if (tn3270_ttype()) {
+ return;
+ }
+#endif /* defined(TN3270) */
+ name = gettermname();
+ len = strlen(name) + 4 + 2;
+ if (len < NETROOM()) {
+ sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+ TELQUAL_IS, name, IAC, SE);
+ ring_supply_data(&netoring, temp, len);
+ printsub('>', &temp[2], len-2);
+ } else {
+ ExitString("No room in buffer for terminal type.\n", 1);
+ /*NOTREACHED*/
+ }
+ }
+ break;
+ case TELOPT_TSPEED:
+ if (my_want_state_is_wont(TELOPT_TSPEED))
+ return;
+ if (SB_EOF())
+ return;
+ if (SB_GET() == TELQUAL_SEND) {
+ long ospeed, ispeed;
+ unsigned char temp[50];
+ int len;
+
+ TerminalSpeeds(&ispeed, &ospeed);
+
+ sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
+ TELQUAL_IS, (long)ospeed, (long)ispeed, IAC, SE);
+ len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
+
+ if (len < NETROOM()) {
+ ring_supply_data(&netoring, temp, len);
+ printsub('>', temp+2, len - 2);
+ }
+/*@*/ else printf("lm_will: not enough room in buffer\n");
+ }
+ break;
+ case TELOPT_LFLOW:
+ if (my_want_state_is_wont(TELOPT_LFLOW))
+ return;
+ if (SB_EOF())
+ return;
+ switch(SB_GET()) {
+ case LFLOW_RESTART_ANY:
+ restartany = 1;
+ break;
+ case LFLOW_RESTART_XON:
+ restartany = 0;
+ break;
+ case LFLOW_ON:
+ localflow = 1;
+ break;
+ case LFLOW_OFF:
+ localflow = 0;
+ break;
+ default:
+ return;
+ }
+ setcommandmode();
+ setconnmode(0);
+ break;
+
+ case TELOPT_LINEMODE:
+ if (my_want_state_is_wont(TELOPT_LINEMODE))
+ return;
+ if (SB_EOF())
+ return;
+ switch (SB_GET()) {
+ case WILL:
+ lm_will(subpointer, SB_LEN());
+ break;
+ case WONT:
+ lm_wont(subpointer, SB_LEN());
+ break;
+ case DO:
+ lm_do(subpointer, SB_LEN());
+ break;
+ case DONT:
+ lm_dont(subpointer, SB_LEN());
+ break;
+ case LM_SLC:
+ slc(subpointer, SB_LEN());
+ break;
+ case LM_MODE:
+ lm_mode(subpointer, SB_LEN(), 0);
+ break;
+ default:
+ break;
+ }
+ break;
+
+#ifdef OLD_ENVIRON
+ case TELOPT_OLD_ENVIRON:
+#endif
+ case TELOPT_NEW_ENVIRON:
+ if (SB_EOF())
+ return;
+ switch(SB_PEEK()) {
+ case TELQUAL_IS:
+ case TELQUAL_INFO:
+ if (my_want_state_is_dont(subchar))
+ return;
+ break;
+ case TELQUAL_SEND:
+ if (my_want_state_is_wont(subchar)) {
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+ env_opt(subpointer, SB_LEN());
+ break;
+
+ case TELOPT_XDISPLOC:
+ if (my_want_state_is_wont(TELOPT_XDISPLOC))
+ return;
+ if (SB_EOF())
+ return;
+ if (SB_GET() == TELQUAL_SEND) {
+ unsigned char temp[50], *dp;
+ int len;
+
+ if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
+ /*
+ * Something happened, we no longer have a DISPLAY
+ * variable. So, turn off the option.
+ */
+ send_wont(TELOPT_XDISPLOC, 1);
+ break;
+ }
+ sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+ TELQUAL_IS, dp, IAC, SE);
+ len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
+
+ if (len < NETROOM()) {
+ ring_supply_data(&netoring, temp, len);
+ printsub('>', temp+2, len - 2);
+ }
+/*@*/ else printf("lm_will: not enough room in buffer\n");
+ }
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION: {
+ if (!autologin)
+ break;
+ if (SB_EOF())
+ return;
+ switch(SB_GET()) {
+ case TELQUAL_IS:
+ if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+ return;
+ auth_is(subpointer, SB_LEN());
+ break;
+ case TELQUAL_SEND:
+ if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+ return;
+ auth_send(subpointer, SB_LEN());
+ break;
+ case TELQUAL_REPLY:
+ if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
+ return;
+ auth_reply(subpointer, SB_LEN());
+ break;
+ case TELQUAL_NAME:
+ if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
+ return;
+ auth_name(subpointer, SB_LEN());
+ break;
+ }
+ }
+ break;
+#endif
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ if (SB_EOF())
+ return;
+ switch(SB_GET()) {
+ case ENCRYPT_START:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_start(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_END:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_end();
+ break;
+ case ENCRYPT_SUPPORT:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_support(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REQSTART:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_request_start(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REQEND:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ /*
+ * We can always send an REQEND so that we cannot
+ * get stuck encrypting. We should only get this
+ * if we have been able to get in the correct mode
+ * anyhow.
+ */
+ encrypt_request_end();
+ break;
+ case ENCRYPT_IS:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_is(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_REPLY:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_reply(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_ENC_KEYID:
+ if (my_want_state_is_dont(TELOPT_ENCRYPT))
+ return;
+ encrypt_enc_keyid(subpointer, SB_LEN());
+ break;
+ case ENCRYPT_DEC_KEYID:
+ if (my_want_state_is_wont(TELOPT_ENCRYPT))
+ return;
+ encrypt_dec_keyid(subpointer, SB_LEN());
+ break;
+ default:
+ break;
+ }
+ break;
+#endif /* ENCRYPTION */
+ default:
+ break;
+ }
+}
+
+static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
+
+void
+lm_will(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK: /* We shouldn't ever get this... */
+ default:
+ str_lm[3] = DONT;
+ str_lm[4] = cmd[0];
+ if (NETROOM() > sizeof(str_lm)) {
+ ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+ printsub('>', &str_lm[2], sizeof(str_lm)-2);
+ }
+/*@*/ else printf("lm_will: not enough room in buffer\n");
+ break;
+ }
+}
+
+void
+lm_wont(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK: /* We shouldn't ever get this... */
+ default:
+ /* We are always DONT, so don't respond */
+ return;
+ }
+}
+
+void
+lm_do(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK:
+ default:
+ str_lm[3] = WONT;
+ str_lm[4] = cmd[0];
+ if (NETROOM() > sizeof(str_lm)) {
+ ring_supply_data(&netoring, str_lm, sizeof(str_lm));
+ printsub('>', &str_lm[2], sizeof(str_lm)-2);
+ }
+/*@*/ else printf("lm_do: not enough room in buffer\n");
+ break;
+ }
+}
+
+void
+lm_dont(unsigned char *cmd, int len)
+{
+ if (len < 1) {
+/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+ switch(cmd[0]) {
+ case LM_FORWARDMASK:
+ default:
+ /* we are always WONT, so don't respond */
+ break;
+ }
+}
+
+static unsigned char str_lm_mode[] = {
+ IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
+};
+
+void
+lm_mode(unsigned char *cmd, int len, int init)
+{
+ if (len != 1)
+ return;
+ if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
+ return;
+ if (*cmd&MODE_ACK)
+ return;
+ linemode = *cmd&(MODE_MASK&~MODE_ACK);
+ str_lm_mode[4] = linemode;
+ if (!init)
+ str_lm_mode[4] |= MODE_ACK;
+ if (NETROOM() > sizeof(str_lm_mode)) {
+ ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
+ printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
+ }
+/*@*/ else printf("lm_mode: not enough room in buffer\n");
+ setconnmode(0); /* set changed mode */
+}
+
+
+
+/*
+ * slc()
+ * Handle special character suboption of LINEMODE.
+ */
+
+struct spc {
+ cc_t val;
+ cc_t *valp;
+ char flags; /* Current flags & level */
+ char mylevel; /* Maximum level & flags */
+} spc_data[NSLC+1];
+
+#define SLC_IMPORT 0
+#define SLC_EXPORT 1
+#define SLC_RVALUE 2
+static int slc_mode = SLC_EXPORT;
+
+void
+slc_init(void)
+{
+ struct spc *spcp;
+
+ localchars = 1;
+ for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
+ spcp->val = 0;
+ spcp->valp = 0;
+ spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
+ }
+
+#define initfunc(func, flags) { \
+ spcp = &spc_data[func]; \
+ if ((spcp->valp = tcval(func)) != NULL){ \
+ spcp->val = *spcp->valp; \
+ spcp->mylevel = SLC_VARIABLE|flags; \
+ } else { \
+ spcp->val = 0; \
+ spcp->mylevel = SLC_DEFAULT; \
+ } \
+ }
+
+ initfunc(SLC_SYNCH, 0);
+ /* No BRK */
+ initfunc(SLC_AO, 0);
+ initfunc(SLC_AYT, 0);
+ /* No EOR */
+ initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
+ initfunc(SLC_EOF, 0);
+ initfunc(SLC_SUSP, SLC_FLUSHIN);
+ initfunc(SLC_EC, 0);
+ initfunc(SLC_EL, 0);
+ initfunc(SLC_EW, 0);
+ initfunc(SLC_RP, 0);
+ initfunc(SLC_LNEXT, 0);
+ initfunc(SLC_XON, 0);
+ initfunc(SLC_XOFF, 0);
+ initfunc(SLC_FORW1, 0);
+ initfunc(SLC_FORW2, 0);
+ /* No FORW2 */
+
+ initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
+#undef initfunc
+
+ if (slc_mode == SLC_EXPORT)
+ slc_export();
+ else
+ slc_import(1);
+
+}
+
+void
+slcstate(void)
+{
+ printf("Special characters are %s values\n",
+ slc_mode == SLC_IMPORT ? "remote default" :
+ slc_mode == SLC_EXPORT ? "local" :
+ "remote");
+}
+
+void
+slc_mode_export(int n)
+{
+ slc_mode = SLC_EXPORT;
+ if (my_state_is_will(TELOPT_LINEMODE))
+ slc_export();
+}
+
+void
+slc_mode_import(int def)
+{
+ slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
+ if (my_state_is_will(TELOPT_LINEMODE))
+ slc_import(def);
+}
+
+unsigned char slc_import_val[] = {
+ IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
+};
+unsigned char slc_import_def[] = {
+ IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
+};
+
+void
+slc_import(int def)
+{
+ if (NETROOM() > sizeof(slc_import_val)) {
+ if (def) {
+ ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
+ printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
+ } else {
+ ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
+ printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
+ }
+ }
+/*@*/ else printf("slc_import: not enough room\n");
+}
+
+void
+slc_export(void)
+{
+ struct spc *spcp;
+
+ TerminalDefaultChars();
+
+ slc_start_reply();
+ for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+ if (spcp->mylevel != SLC_NOSUPPORT) {
+ if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+ spcp->flags = SLC_NOSUPPORT;
+ else
+ spcp->flags = spcp->mylevel;
+ if (spcp->valp)
+ spcp->val = *spcp->valp;
+ slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+ }
+ }
+ slc_end_reply();
+ (void)slc_update();
+ setconnmode(1); /* Make sure the character values are set */
+}
+
+void
+slc(unsigned char *cp, int len)
+{
+ struct spc *spcp;
+ int func,level;
+
+ slc_start_reply();
+
+ for (; len >= 3; len -=3, cp +=3) {
+
+ func = cp[SLC_FUNC];
+
+ if (func == 0) {
+ /*
+ * Client side: always ignore 0 function.
+ */
+ continue;
+ }
+ if (func > NSLC) {
+ if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
+ slc_add_reply(func, SLC_NOSUPPORT, 0);
+ continue;
+ }
+
+ spcp = &spc_data[func];
+
+ level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
+
+ if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
+ ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
+ continue;
+ }
+
+ if (level == (SLC_DEFAULT|SLC_ACK)) {
+ /*
+ * This is an error condition, the SLC_ACK
+ * bit should never be set for the SLC_DEFAULT
+ * level. Our best guess to recover is to
+ * ignore the SLC_ACK bit.
+ */
+ cp[SLC_FLAGS] &= ~SLC_ACK;
+ }
+
+ if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
+ spcp->val = (cc_t)cp[SLC_VALUE];
+ spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
+ continue;
+ }
+
+ level &= ~SLC_ACK;
+
+ if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
+ spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
+ spcp->val = (cc_t)cp[SLC_VALUE];
+ }
+ if (level == SLC_DEFAULT) {
+ if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
+ spcp->flags = spcp->mylevel;
+ else
+ spcp->flags = SLC_NOSUPPORT;
+ }
+ slc_add_reply(func, spcp->flags, spcp->val);
+ }
+ slc_end_reply();
+ if (slc_update())
+ setconnmode(1); /* set the new character values */
+}
+
+void
+slc_check(void)
+{
+ struct spc *spcp;
+
+ slc_start_reply();
+ for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+ if (spcp->valp && spcp->val != *spcp->valp) {
+ spcp->val = *spcp->valp;
+ if (spcp->val == (cc_t)(_POSIX_VDISABLE))
+ spcp->flags = SLC_NOSUPPORT;
+ else
+ spcp->flags = spcp->mylevel;
+ slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
+ }
+ }
+ slc_end_reply();
+ setconnmode(1);
+}
+
+
+unsigned char slc_reply[128];
+unsigned char *slc_replyp;
+
+void
+slc_start_reply(void)
+{
+ slc_replyp = slc_reply;
+ *slc_replyp++ = IAC;
+ *slc_replyp++ = SB;
+ *slc_replyp++ = TELOPT_LINEMODE;
+ *slc_replyp++ = LM_SLC;
+}
+
+void
+slc_add_reply(unsigned int func, unsigned int flags, cc_t value)
+{
+ if ((slc_replyp - slc_reply) + 6 > sizeof(slc_reply))
+ return;
+ if ((*slc_replyp++ = func) == IAC)
+ *slc_replyp++ = IAC;
+ if ((*slc_replyp++ = flags) == IAC)
+ *slc_replyp++ = IAC;
+ if ((*slc_replyp++ = (unsigned char)value) == IAC)
+ *slc_replyp++ = IAC;
+}
+
+void
+slc_end_reply(void)
+{
+ int len;
+
+ len = slc_replyp - slc_reply;
+ if (len <= 4 || (len + 2 > sizeof(slc_reply)))
+ return;
+ *slc_replyp++ = IAC;
+ *slc_replyp++ = SE;
+ len += 2;
+ if (NETROOM() > len) {
+ ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
+ printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
+ }
+/*@*/else printf("slc_end_reply: not enough room\n");
+}
+
+int
+slc_update(void)
+{
+ struct spc *spcp;
+ int need_update = 0;
+
+ for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
+ if (!(spcp->flags&SLC_ACK))
+ continue;
+ spcp->flags &= ~SLC_ACK;
+ if (spcp->valp && (*spcp->valp != spcp->val)) {
+ *spcp->valp = spcp->val;
+ need_update = 1;
+ }
+ }
+ return(need_update);
+}
+
+#ifdef OLD_ENVIRON
+# ifdef ENV_HACK
+/*
+ * Earlier version of telnet/telnetd from the BSD code had
+ * the definitions of VALUE and VAR reversed. To ensure
+ * maximum interoperability, we assume that the server is
+ * an older BSD server, until proven otherwise. The newer
+ * BSD servers should be able to handle either definition,
+ * so it is better to use the wrong values if we don't
+ * know what type of server it is.
+ */
+int env_auto = 1;
+int old_env_var = OLD_ENV_VAR;
+int old_env_value = OLD_ENV_VALUE;
+# else
+# define old_env_var OLD_ENV_VAR
+# define old_env_value OLD_ENV_VALUE
+# endif
+#endif
+
+void
+env_opt(unsigned char *buf, int len)
+{
+ unsigned char *ep = 0, *epc = 0;
+ int i;
+
+ switch(buf[0]&0xff) {
+ case TELQUAL_SEND:
+ env_opt_start();
+ if (len == 1) {
+ env_opt_add(NULL);
+ } else for (i = 1; i < len; i++) {
+ switch (buf[i]&0xff) {
+#ifdef OLD_ENVIRON
+ case OLD_ENV_VAR:
+# ifdef ENV_HACK
+ if (telopt_environ == TELOPT_OLD_ENVIRON
+ && env_auto) {
+ /* Server has the same definitions */
+ old_env_var = OLD_ENV_VAR;
+ old_env_value = OLD_ENV_VALUE;
+ }
+ /* FALL THROUGH */
+# endif
+ case OLD_ENV_VALUE:
+ /*
+ * Although OLD_ENV_VALUE is not legal, we will
+ * still recognize it, just in case it is an
+ * old server that has VAR & VALUE mixed up...
+ */
+ /* FALL THROUGH */
+#else
+ case NEW_ENV_VAR:
+#endif
+ case ENV_USERVAR:
+ if (ep) {
+ *epc = 0;
+ env_opt_add(ep);
+ }
+ ep = epc = &buf[i+1];
+ break;
+ case ENV_ESC:
+ i++;
+ /*FALL THROUGH*/
+ default:
+ if (epc)
+ *epc++ = buf[i];
+ break;
+ }
+ }
+ if (ep) {
+ *epc = 0;
+ env_opt_add(ep);
+ }
+ env_opt_end(1);
+ break;
+
+ case TELQUAL_IS:
+ case TELQUAL_INFO:
+ /* Ignore for now. We shouldn't get it anyway. */
+ break;
+
+ default:
+ break;
+ }
+}
+
+#define OPT_REPLY_SIZE 256
+unsigned char *opt_reply;
+unsigned char *opt_replyp;
+unsigned char *opt_replyend;
+
+void
+env_opt_start(void)
+{
+ unsigned char *p;
+
+ if (opt_reply) {
+ p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
+ if (p == NULL)
+ free(opt_reply);
+ } else
+ p = (unsigned char *)malloc(OPT_REPLY_SIZE);
+ opt_reply = p;
+ if (opt_reply == NULL) {
+/*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
+ opt_reply = opt_replyp = opt_replyend = NULL;
+ return;
+ }
+ opt_replyp = opt_reply;
+ opt_replyend = opt_reply + OPT_REPLY_SIZE;
+ *opt_replyp++ = IAC;
+ *opt_replyp++ = SB;
+ *opt_replyp++ = telopt_environ;
+ *opt_replyp++ = TELQUAL_IS;
+}
+
+void
+env_opt_start_info(void)
+{
+ env_opt_start();
+ if (opt_replyp)
+ opt_replyp[-1] = TELQUAL_INFO;
+}
+
+void
+env_opt_add(unsigned char *ep)
+{
+ unsigned char *vp, c;
+ unsigned int len, olen, elen;
+
+ if (opt_reply == NULL) /*XXX*/
+ return; /*XXX*/
+
+ if (ep == NULL || *ep == '\0') {
+ /* Send user defined variables first. */
+ env_default(1, 0);
+ while ((ep = env_default(0, 0)) != NULL)
+ env_opt_add(ep);
+
+ /* Now add the list of well know variables. */
+ env_default(1, 1);
+ while ((ep = env_default(0, 1)) != NULL)
+ env_opt_add(ep);
+ return;
+ }
+ vp = env_getvalue(ep);
+ elen = 2 * (vp ? strlen((char *)vp) : 0) +
+ 2 * strlen((char *)ep) + 6;
+ if ((opt_replyend - opt_replyp) < elen)
+ {
+ unsigned char *p;
+ len = opt_replyend - opt_reply + elen;
+ olen = opt_replyp - opt_reply;
+ p = (unsigned char *)realloc(opt_reply, len);
+ if (p == NULL)
+ free(opt_reply);
+ opt_reply = p;
+ if (opt_reply == NULL) {
+/*@*/ printf("env_opt_add: realloc() failed!!!\n");
+ opt_reply = opt_replyp = opt_replyend = NULL;
+ return;
+ }
+ opt_replyp = opt_reply + olen;
+ opt_replyend = opt_reply + len;
+ }
+ if (opt_welldefined(ep))
+#ifdef OLD_ENVIRON
+ if (telopt_environ == TELOPT_OLD_ENVIRON)
+ *opt_replyp++ = old_env_var;
+ else
+#endif
+ *opt_replyp++ = NEW_ENV_VAR;
+ else
+ *opt_replyp++ = ENV_USERVAR;
+ for (;;) {
+ while ((c = *ep++) != '\0') {
+ switch(c&0xff) {
+ case IAC:
+ *opt_replyp++ = IAC;
+ break;
+ case NEW_ENV_VAR:
+ case NEW_ENV_VALUE:
+ case ENV_ESC:
+ case ENV_USERVAR:
+ *opt_replyp++ = ENV_ESC;
+ break;
+ }
+ *opt_replyp++ = c;
+ }
+ if ((ep = vp) != NULL) {
+#ifdef OLD_ENVIRON
+ if (telopt_environ == TELOPT_OLD_ENVIRON)
+ *opt_replyp++ = old_env_value;
+ else
+#endif
+ *opt_replyp++ = NEW_ENV_VALUE;
+ vp = NULL;
+ } else
+ break;
+ }
+}
+
+int
+opt_welldefined(char *ep)
+{
+ if ((strcmp(ep, "USER") == 0) ||
+ (strcmp(ep, "DISPLAY") == 0) ||
+ (strcmp(ep, "PRINTER") == 0) ||
+ (strcmp(ep, "SYSTEMTYPE") == 0) ||
+ (strcmp(ep, "JOB") == 0) ||
+ (strcmp(ep, "ACCT") == 0))
+ return(1);
+ return(0);
+}
+void
+env_opt_end(int emptyok)
+{
+ int len;
+
+ len = opt_replyp - opt_reply + 2;
+ if (emptyok || len > 6) {
+ *opt_replyp++ = IAC;
+ *opt_replyp++ = SE;
+ if (NETROOM() > len) {
+ ring_supply_data(&netoring, opt_reply, len);
+ printsub('>', &opt_reply[2], len - 2);
+ }
+/*@*/ else printf("slc_end_reply: not enough room\n");
+ }
+ if (opt_reply) {
+ free(opt_reply);
+ opt_reply = opt_replyp = opt_replyend = NULL;
+ }
+}
+
+
+
+int
+telrcv(void)
+{
+ int c;
+ int scc;
+ unsigned char *sbp = NULL;
+ int count;
+ int returnValue = 0;
+
+ scc = 0;
+ count = 0;
+ while (TTYROOM() > 2) {
+ if (scc == 0) {
+ if (count) {
+ ring_consumed(&netiring, count);
+ returnValue = 1;
+ count = 0;
+ }
+ sbp = netiring.consume;
+ scc = ring_full_consecutive(&netiring);
+ if (scc == 0) {
+ /* No more data coming in */
+ break;
+ }
+ }
+
+ c = *sbp++ & 0xff, scc--; count++;
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+
+ switch (telrcv_state) {
+
+ case TS_CR:
+ telrcv_state = TS_DATA;
+ if (c == '\0') {
+ break; /* Ignore \0 after CR */
+ }
+ else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
+ TTYADD(c);
+ break;
+ }
+ /* Else, fall through */
+
+ case TS_DATA:
+ if (c == IAC) {
+ telrcv_state = TS_IAC;
+ break;
+ }
+# if defined(TN3270)
+ if (In3270) {
+ *Ifrontp++ = c;
+ while (scc > 0) {
+ c = *sbp++ & 0377, scc--; count++;
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+ if (c == IAC) {
+ telrcv_state = TS_IAC;
+ break;
+ }
+ *Ifrontp++ = c;
+ }
+ } else
+# endif /* defined(TN3270) */
+ /*
+ * The 'crmod' hack (see following) is needed
+ * since we can't * set CRMOD on output only.
+ * Machines like MULTICS like to send \r without
+ * \n; since we must turn off CRMOD to get proper
+ * input, the mapping is done here (sigh).
+ */
+ if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
+ if (scc > 0) {
+ c = *sbp&0xff;
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ c = (*decrypt_input)(c);
+#endif /* ENCRYPTION */
+ if (c == 0) {
+ sbp++, scc--; count++;
+ /* a "true" CR */
+ TTYADD('\r');
+ } else if (my_want_state_is_dont(TELOPT_ECHO) &&
+ (c == '\n')) {
+ sbp++, scc--; count++;
+ TTYADD('\n');
+ } else {
+#ifdef ENCRYPTION
+ if (decrypt_input)
+ (*decrypt_input)(-1);
+#endif /* ENCRYPTION */
+
+ TTYADD('\r');
+ if (crmod) {
+ TTYADD('\n');
+ }
+ }
+ } else {
+ telrcv_state = TS_CR;
+ TTYADD('\r');
+ if (crmod) {
+ TTYADD('\n');
+ }
+ }
+ } else {
+ TTYADD(c);
+ }
+ continue;
+
+ case TS_IAC:
+process_iac:
+ switch (c) {
+
+ case WILL:
+ telrcv_state = TS_WILL;
+ continue;
+
+ case WONT:
+ telrcv_state = TS_WONT;
+ continue;
+
+ case DO:
+ telrcv_state = TS_DO;
+ continue;
+
+ case DONT:
+ telrcv_state = TS_DONT;
+ continue;
+
+ case DM:
+ /*
+ * We may have missed an urgent notification,
+ * so make sure we flush whatever is in the
+ * buffer currently.
+ */
+ printoption("RCVD", IAC, DM);
+ SYNCHing = 1;
+ (void) ttyflush(1);
+ SYNCHing = stilloob();
+ settimer(gotDM);
+ break;
+
+ case SB:
+ SB_CLEAR();
+ telrcv_state = TS_SB;
+ continue;
+
+# if defined(TN3270)
+ case EOR:
+ if (In3270) {
+ if (Ibackp == Ifrontp) {
+ Ibackp = Ifrontp = Ibuf;
+ ISend = 0; /* should have been! */
+ } else {
+ Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
+ ISend = 1;
+ }
+ }
+ printoption("RCVD", IAC, EOR);
+ break;
+# endif /* defined(TN3270) */
+
+ case IAC:
+# if !defined(TN3270)
+ TTYADD(IAC);
+# else /* !defined(TN3270) */
+ if (In3270) {
+ *Ifrontp++ = IAC;
+ } else {
+ TTYADD(IAC);
+ }
+# endif /* !defined(TN3270) */
+ break;
+
+ case NOP:
+ case GA:
+ default:
+ printoption("RCVD", IAC, c);
+ break;
+ }
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_WILL:
+ printoption("RCVD", WILL, c);
+ willoption(c);
+ SetIn3270();
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_WONT:
+ printoption("RCVD", WONT, c);
+ wontoption(c);
+ SetIn3270();
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_DO:
+ printoption("RCVD", DO, c);
+ dooption(c);
+ SetIn3270();
+ if (c == TELOPT_NAWS) {
+ sendnaws();
+ } else if (c == TELOPT_LFLOW) {
+ localflow = 1;
+ setcommandmode();
+ setconnmode(0);
+ }
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_DONT:
+ printoption("RCVD", DONT, c);
+ dontoption(c);
+ flushline = 1;
+ setconnmode(0); /* set new tty mode (maybe) */
+ SetIn3270();
+ telrcv_state = TS_DATA;
+ continue;
+
+ case TS_SB:
+ if (c == IAC) {
+ telrcv_state = TS_SE;
+ } else {
+ SB_ACCUM(c);
+ }
+ continue;
+
+ case TS_SE:
+ if (c != SE) {
+ if (c != IAC) {
+ /*
+ * This is an error. We only expect to get
+ * "IAC IAC" or "IAC SE". Several things may
+ * have happened. An IAC was not doubled, the
+ * IAC SE was left off, or another option got
+ * inserted into the suboption are all possibilities.
+ * If we assume that the IAC was not doubled,
+ * and really the IAC SE was left off, we could
+ * get into an infinite loop here. So, instead,
+ * we terminate the suboption, and process the
+ * partial suboption if we can.
+ */
+ SB_ACCUM(IAC);
+ SB_ACCUM(c);
+ subpointer -= 2;
+ SB_TERM();
+
+ printoption("In SUBOPTION processing, RCVD", IAC, c);
+ suboption(); /* handle sub-option */
+ SetIn3270();
+ telrcv_state = TS_IAC;
+ goto process_iac;
+ }
+ SB_ACCUM(c);
+ telrcv_state = TS_SB;
+ } else {
+ SB_ACCUM(IAC);
+ SB_ACCUM(SE);
+ subpointer -= 2;
+ SB_TERM();
+ suboption(); /* handle sub-option */
+ SetIn3270();
+ telrcv_state = TS_DATA;
+ }
+ }
+ }
+ if (count)
+ ring_consumed(&netiring, count);
+ return returnValue||count;
+}
+
+static int bol = 1, local = 0;
+
+int
+rlogin_susp(void)
+{
+ if (local) {
+ local = 0;
+ bol = 1;
+ command(0, "z\n", 2);
+ return(1);
+ }
+ return(0);
+}
+
+static int
+telsnd(void)
+{
+ int tcc;
+ int count;
+ int returnValue = 0;
+ unsigned char *tbp = NULL;
+
+ tcc = 0;
+ count = 0;
+ while (NETROOM() > 2) {
+ int sc;
+ int c;
+
+ if (tcc == 0) {
+ if (count) {
+ ring_consumed(&ttyiring, count);
+ returnValue = 1;
+ count = 0;
+ }
+ tbp = ttyiring.consume;
+ tcc = ring_full_consecutive(&ttyiring);
+ if (tcc == 0) {
+ break;
+ }
+ }
+ c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
+ if (rlogin != _POSIX_VDISABLE) {
+ if (bol) {
+ bol = 0;
+ if (sc == rlogin) {
+ local = 1;
+ continue;
+ }
+ } else if (local) {
+ local = 0;
+ if (sc == '.' || c == termEofChar) {
+ bol = 1;
+ command(0, "close\n", 6);
+ continue;
+ }
+ if (sc == termSuspChar) {
+ bol = 1;
+ command(0, "z\n", 2);
+ continue;
+ }
+ if (sc == escape) {
+ command(0, (char *)tbp, tcc);
+ bol = 1;
+ count += tcc;
+ tcc = 0;
+ flushline = 1;
+ break;
+ }
+ if (sc != rlogin) {
+ ++tcc;
+ --tbp;
+ --count;
+ c = sc = rlogin;
+ }
+ }
+ if ((sc == '\n') || (sc == '\r'))
+ bol = 1;
+ } else if (sc == escape && escape != _POSIX_VDISABLE) {
+ /*
+ * Double escape is a pass through of a single escape character.
+ */
+ if (tcc && strip(*tbp) == escape) {
+ tbp++;
+ tcc--;
+ count++;
+ bol = 0;
+ } else {
+ command(0, (char *)tbp, tcc);
+ bol = 1;
+ count += tcc;
+ tcc = 0;
+ flushline = 1;
+ break;
+ }
+ } else
+ bol = 0;
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
+ if (tcc > 0 && strip(*tbp) == echoc) {
+ tcc--; tbp++; count++;
+ } else {
+ dontlecho = !dontlecho;
+ settimer(echotoggle);
+ setconnmode(0);
+ flushline = 1;
+ break;
+ }
+ }
+#endif
+ if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
+ if (TerminalSpecialChars(sc) == 0) {
+ bol = 1;
+ break;
+ }
+ }
+ if (my_want_state_is_wont(TELOPT_BINARY)) {
+ switch (c) {
+ case '\n':
+ /*
+ * If we are in CRMOD mode (\r ==> \n)
+ * on our local machine, then probably
+ * a newline (unix) is CRLF (TELNET).
+ */
+ if (MODE_LOCAL_CHARS(globalmode)) {
+ NETADD('\r');
+ }
+ NETADD('\n');
+ bol = flushline = 1;
+ break;
+ case '\r':
+ if (!crlf) {
+ NET2ADD('\r', '\0');
+ } else {
+ NET2ADD('\r', '\n');
+ }
+ bol = flushline = 1;
+ break;
+ case IAC:
+ NET2ADD(IAC, IAC);
+ break;
+ default:
+ NETADD(c);
+ break;
+ }
+ } else if (c == IAC) {
+ NET2ADD(IAC, IAC);
+ } else {
+ NETADD(c);
+ }
+ }
+ if (count)
+ ring_consumed(&ttyiring, count);
+ return returnValue||count; /* Non-zero if we did anything */
+}
+
+/*
+ * Scheduler()
+ *
+ * Try to do something.
+ *
+ * If we do something useful, return 1; else return 0.
+ *
+ */
+
+
+int
+Scheduler(int block) /* should we block in the select ? */
+{
+ /* One wants to be a bit careful about setting returnValue
+ * to one, since a one implies we did some useful work,
+ * and therefore probably won't be called to block next
+ * time (TN3270 mode only).
+ */
+ int returnValue;
+ int netin, netout, netex, ttyin, ttyout;
+
+ /* Decide which rings should be processed */
+
+ netout = ring_full_count(&netoring) &&
+ (flushline ||
+ (my_want_state_is_wont(TELOPT_LINEMODE)
+#ifdef KLUDGELINEMODE
+ && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
+#endif
+ ) ||
+ my_want_state_is_will(TELOPT_BINARY));
+ ttyout = ring_full_count(&ttyoring);
+
+#ifdef TN3270
+ ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
+#else /* defined(TN3270) */
+ ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
+#endif /* defined(TN3270) */
+
+#ifdef TN3270
+ netin = ring_empty_count(&netiring);
+# else /* !defined(TN3270) */
+ netin = !ISend && ring_empty_count(&netiring);
+# endif /* !defined(TN3270) */
+
+ netex = !SYNCHing;
+
+ /* If we have seen a signal recently, reset things */
+# ifdef TN3270
+ if (HaveInput) {
+ HaveInput = 0;
+ (void) signal(SIGIO, inputAvailable);
+ }
+#endif /* defined(TN3270) */
+
+ /* Call to system code to process rings */
+
+ returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
+
+ /* Now, look at the input rings, looking for work to do. */
+
+ if (ring_full_count(&ttyiring)) {
+# if defined(TN3270)
+ if (In3270) {
+ int c;
+
+ c = DataFromTerminal(ttyiring.consume,
+ ring_full_consecutive(&ttyiring));
+ if (c) {
+ returnValue = 1;
+ ring_consumed(&ttyiring, c);
+ }
+ } else {
+# endif /* defined(TN3270) */
+ returnValue |= telsnd();
+# if defined(TN3270)
+ }
+# endif /* defined(TN3270) */
+ }
+
+ if (ring_full_count(&netiring)) {
+# if !defined(TN3270)
+ returnValue |= telrcv();
+# else /* !defined(TN3270) */
+ returnValue = Push3270();
+# endif /* !defined(TN3270) */
+ }
+ return returnValue;
+}
+
+/*
+ * Select from tty and network...
+ */
+void
+telnet(const char *user)
+{
+ sys_telnet_init();
+
+#if defined(AUTHENTICATION) || defined(ENCRYPTION)
+ {
+ static char local_host[MAXHOSTNAMELEN + 1] = { 0 };
+
+ if (!local_host[0]) {
+ gethostname(local_host, sizeof(local_host));
+ local_host[sizeof(local_host)-1] = 0;
+ }
+ auth_encrypt_init(local_host, hostname, "TELNET", 0);
+ auth_encrypt_user(user);
+ }
+#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
+# if !defined(TN3270)
+ if (telnetport) {
+#ifdef AUTHENTICATION
+ if (autologin)
+ send_will(TELOPT_AUTHENTICATION, 1);
+#endif
+#ifdef ENCRYPTION
+ send_do(TELOPT_ENCRYPT, 1);
+ send_will(TELOPT_ENCRYPT, 1);
+#endif /* ENCRYPTION */
+ send_do(TELOPT_SGA, 1);
+ send_will(TELOPT_TTYPE, 1);
+ send_will(TELOPT_NAWS, 1);
+ send_will(TELOPT_TSPEED, 1);
+ send_will(TELOPT_LFLOW, 1);
+ send_will(TELOPT_LINEMODE, 1);
+ send_will(TELOPT_NEW_ENVIRON, 1);
+ send_do(TELOPT_STATUS, 1);
+ if (env_getvalue((unsigned char *)"DISPLAY"))
+ send_will(TELOPT_XDISPLOC, 1);
+ if (eight)
+ tel_enter_binary(eight);
+ }
+# endif /* !defined(TN3270) */
+
+# if !defined(TN3270)
+ for (;;) {
+ int schedValue;
+
+ while ((schedValue = Scheduler(0)) != 0) {
+ if (schedValue == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+
+ if (Scheduler(1) == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+# else /* !defined(TN3270) */
+ for (;;) {
+ int schedValue;
+
+ while (!In3270 && !shell_active) {
+ if (Scheduler(1) == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+
+ while ((schedValue = Scheduler(0)) != 0) {
+ if (schedValue == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+ /* If there is data waiting to go out to terminal, don't
+ * schedule any more data for the terminal.
+ */
+ if (ring_full_count(&ttyoring)) {
+ schedValue = 1;
+ } else {
+ if (shell_active) {
+ if (shell_continue() == 0) {
+ ConnectScreen();
+ }
+ } else if (In3270) {
+ schedValue = DoTerminalOutput();
+ }
+ }
+ if (schedValue && (shell_active == 0)) {
+ if (Scheduler(1) == -1) {
+ setcommandmode();
+ return;
+ }
+ }
+ }
+# endif /* !defined(TN3270) */
+}
+
+#if 0 /* XXX - this not being in is a bug */
+/*
+ * nextitem()
+ *
+ * Return the address of the next "item" in the TELNET data
+ * stream. This will be the address of the next character if
+ * the current address is a user data character, or it will
+ * be the address of the character following the TELNET command
+ * if the current address is a TELNET IAC ("I Am a Command")
+ * character.
+ */
+
+static char *
+nextitem(char *current)
+{
+ if ((*current&0xff) != IAC) {
+ return current+1;
+ }
+ switch (*(current+1)&0xff) {
+ case DO:
+ case DONT:
+ case WILL:
+ case WONT:
+ return current+3;
+ case SB: /* loop forever looking for the SE */
+ {
+ char *look = current+2;
+
+ for (;;) {
+ if ((*look++&0xff) == IAC) {
+ if ((*look++&0xff) == SE) {
+ return look;
+ }
+ }
+ }
+ }
+ default:
+ return current+2;
+ }
+}
+#endif /* 0 */
+
+/*
+ * netclear()
+ *
+ * We are about to do a TELNET SYNCH operation. Clear
+ * the path to the network.
+ *
+ * Things are a bit tricky since we may have sent the first
+ * byte or so of a previous TELNET command into the network.
+ * So, we have to scan the network buffer from the beginning
+ * until we are up to where we want to be.
+ *
+ * A side effect of what we do, just to keep things
+ * simple, is to clear the urgent data pointer. The principal
+ * caller should be setting the urgent data pointer AFTER calling
+ * us in any case.
+ */
+
+static void
+netclear(void)
+{
+#if 0 /* XXX */
+ char *thisitem, *next;
+ char *good;
+#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
+ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
+
+ thisitem = netobuf;
+
+ while ((next = nextitem(thisitem)) <= netobuf.send) {
+ thisitem = next;
+ }
+
+ /* Now, thisitem is first before/at boundary. */
+
+ good = netobuf; /* where the good bytes go */
+
+ while (netoring.add > thisitem) {
+ if (wewant(thisitem)) {
+ int length;
+
+ next = thisitem;
+ do {
+ next = nextitem(next);
+ } while (wewant(next) && (nfrontp > next));
+ length = next-thisitem;
+ memmove(good, thisitem, length);
+ good += length;
+ thisitem = next;
+ } else {
+ thisitem = nextitem(thisitem);
+ }
+ }
+
+#endif /* 0 */
+}
+
+/*
+ * These routines add various telnet commands to the data stream.
+ */
+
+static void
+doflush(void)
+{
+ NET2ADD(IAC, DO);
+ NETADD(TELOPT_TM);
+ flushline = 1;
+ flushout = 1;
+ (void) ttyflush(1); /* Flush/drop output */
+ /* do printoption AFTER flush, otherwise the output gets tossed... */
+ printoption("SENT", DO, TELOPT_TM);
+}
+
+void
+xmitAO(void)
+{
+ NET2ADD(IAC, AO);
+ printoption("SENT", IAC, AO);
+ if (autoflush) {
+ doflush();
+ }
+}
+
+
+void
+xmitEL(void)
+{
+ NET2ADD(IAC, EL);
+ printoption("SENT", IAC, EL);
+}
+
+void
+xmitEC(void)
+{
+ NET2ADD(IAC, EC);
+ printoption("SENT", IAC, EC);
+}
+
+
+int
+dosynch(char *s)
+{
+ netclear(); /* clear the path to the network */
+ NETADD(IAC);
+ setneturg();
+ NETADD(DM);
+ printoption("SENT", IAC, DM);
+ return 1;
+}
+
+int want_status_response = 0;
+
+int
+get_status(char *s)
+{
+ unsigned char tmp[16];
+ unsigned char *cp;
+
+ if (my_want_state_is_dont(TELOPT_STATUS)) {
+ printf("Remote side does not support STATUS option\n");
+ return 0;
+ }
+ cp = tmp;
+
+ *cp++ = IAC;
+ *cp++ = SB;
+ *cp++ = TELOPT_STATUS;
+ *cp++ = TELQUAL_SEND;
+ *cp++ = IAC;
+ *cp++ = SE;
+ if (NETROOM() >= cp - tmp) {
+ ring_supply_data(&netoring, tmp, cp-tmp);
+ printsub('>', tmp+2, cp - tmp - 2);
+ }
+ ++want_status_response;
+ return 1;
+}
+
+void
+intp(void)
+{
+ NET2ADD(IAC, IP);
+ printoption("SENT", IAC, IP);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch(NULL);
+ }
+}
+
+void
+sendbrk(void)
+{
+ NET2ADD(IAC, BREAK);
+ printoption("SENT", IAC, BREAK);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch(NULL);
+ }
+}
+
+void
+sendabort(void)
+{
+ NET2ADD(IAC, ABORT);
+ printoption("SENT", IAC, ABORT);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch(NULL);
+ }
+}
+
+void
+sendsusp(void)
+{
+ NET2ADD(IAC, SUSP);
+ printoption("SENT", IAC, SUSP);
+ flushline = 1;
+ if (autoflush) {
+ doflush();
+ }
+ if (autosynch) {
+ dosynch(NULL);
+ }
+}
+
+void
+sendeof(void)
+{
+ NET2ADD(IAC, xEOF);
+ printoption("SENT", IAC, xEOF);
+}
+
+void
+sendayt(void)
+{
+ NET2ADD(IAC, AYT);
+ printoption("SENT", IAC, AYT);
+}
+
+/*
+ * Send a window size update to the remote system.
+ */
+
+void
+sendnaws(void)
+{
+ long rows, cols;
+ unsigned char tmp[16];
+ unsigned char *cp;
+
+ if (my_state_is_wont(TELOPT_NAWS))
+ return;
+
+#define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
+ if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
+
+ if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
+ return;
+ }
+
+ cp = tmp;
+
+ *cp++ = IAC;
+ *cp++ = SB;
+ *cp++ = TELOPT_NAWS;
+ PUTSHORT(cp, cols);
+ PUTSHORT(cp, rows);
+ *cp++ = IAC;
+ *cp++ = SE;
+ if (NETROOM() >= cp - tmp) {
+ ring_supply_data(&netoring, tmp, cp-tmp);
+ printsub('>', tmp+2, cp - tmp - 2);
+ }
+}
+
+void
+tel_enter_binary(int rw)
+{
+ if (rw&1)
+ send_do(TELOPT_BINARY, 1);
+ if (rw&2)
+ send_will(TELOPT_BINARY, 1);
+}
+
+void
+tel_leave_binary(int rw)
+{
+ if (rw&1)
+ send_dont(TELOPT_BINARY, 1);
+ if (rw&2)
+ send_wont(TELOPT_BINARY, 1);
+}
diff --git a/comms/tn3270/files/telnet/terminal.c b/comms/tn3270/files/telnet/terminal.c
new file mode 100644
index 00000000000..22869ccfee8
--- /dev/null
+++ b/comms/tn3270/files/telnet/terminal.c
@@ -0,0 +1,221 @@
+/* $NetBSD: terminal.c,v 1.1.1.1 2010/01/17 01:33:32 dholland Exp $ */
+/* From NetBSD: terminal.c,v 1.15 2005/02/19 23:28:41 christos Exp */
+
+/*
+ * Copyright (c) 1988, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)terminal.c 8.2 (Berkeley) 2/16/95";
+#else
+__RCSID("$NetBSD: terminal.c,v 1.1.1.1 2010/01/17 01:33:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <arpa/telnet.h>
+#include <sys/types.h>
+
+#include "ring.h"
+
+#include "externs.h"
+#include "types.h"
+
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+Ring ttyoring, ttyiring;
+unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ];
+char line[] = { '\0' };
+
+int termdata; /* Debugging flag */
+
+/*
+ * initialize the terminal data structures.
+ */
+
+void
+init_terminal(void)
+{
+ if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) {
+ exit(1);
+ }
+ if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) {
+ exit(1);
+ }
+ autoflush = TerminalAutoFlush();
+}
+
+
+/*
+ * Send as much data as possible to the terminal, else exits if
+ * it encounters a permanent failure when writing to the tty.
+ *
+ * Return value:
+ * -1: No useful work done, data waiting to go out.
+ * 0: No data was waiting, so nothing was done.
+ * 1: All waiting data was written out.
+ * n: All data - n was written out.
+ */
+
+
+int
+ttyflush(int drop)
+{
+ int n, n0, n1;
+
+ n0 = ring_full_count(&ttyoring);
+ if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) {
+ if (drop) {
+ TerminalFlushOutput();
+ /* we leave 'n' alone! */
+ } else {
+ n = TerminalWrite(ttyoring.consume, n);
+ }
+ }
+ if (n > 0) {
+ if (termdata && n) {
+ Dump('>', ttyoring.consume, n);
+ }
+ /*
+ * If we wrote everything, and the full count is
+ * larger than what we wrote, then write the
+ * rest of the buffer.
+ */
+ if (n1 == n && n0 > n) {
+ n1 = n0 - n;
+ if (!drop)
+ n1 = TerminalWrite(ttyoring.bottom, n1);
+ if (n1 > 0)
+ n += n1;
+ }
+ ring_consumed(&ttyoring, n);
+ }
+ if (n < 0) {
+ if (errno == EAGAIN || errno == EINTR) {
+ return -1;
+ } else {
+ ring_consumed(&ttyoring, ring_full_count(&ttyoring));
+ setconnmode(0);
+ setcommandmode();
+ NetClose(net);
+ fprintf(stderr, "Connection closed by foreign host.\n");
+ exit(1);
+ }
+ }
+ if (n == n0) {
+ if (n0)
+ return -1;
+ return 0;
+ }
+ return n0 - n + 1;
+}
+
+
+/*
+ * These routines decides on what the mode should be (based on the values
+ * of various global variables).
+ */
+
+
+int
+getconnmode(void)
+{
+ extern int linemode;
+ int mode = 0;
+#ifdef KLUDGELINEMODE
+ extern int kludgelinemode;
+#endif
+
+ if (In3270)
+ return(MODE_FLOW);
+
+ if (my_want_state_is_dont(TELOPT_ECHO))
+ mode |= MODE_ECHO;
+
+ if (localflow)
+ mode |= MODE_FLOW;
+
+ if (my_want_state_is_will(TELOPT_BINARY))
+ mode |= MODE_INBIN;
+
+ if (his_want_state_is_will(TELOPT_BINARY))
+ mode |= MODE_OUTBIN;
+
+#ifdef KLUDGELINEMODE
+ if (kludgelinemode) {
+ if (my_want_state_is_dont(TELOPT_SGA)) {
+ mode |= (MODE_TRAPSIG|MODE_EDIT);
+ if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) {
+ mode &= ~MODE_ECHO;
+ }
+ }
+ return(mode);
+ }
+#endif
+ if (my_want_state_is_will(TELOPT_LINEMODE))
+ mode |= linemode;
+ return(mode);
+}
+
+void
+setconnmode(int force)
+{
+#ifdef ENCRYPTION
+ static int enc_passwd = 0;
+#endif
+ int newmode;
+
+ newmode = getconnmode()|(force?MODE_FORCE:0);
+
+ TerminalNewMode(newmode);
+
+#ifdef ENCRYPTION
+ if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) {
+ if (my_want_state_is_will(TELOPT_ENCRYPT)
+ && (enc_passwd == 0) && !encrypt_output) {
+ encrypt_request_start(0, 0);
+ enc_passwd = 1;
+ }
+ } else {
+ if (enc_passwd) {
+ encrypt_request_end();
+ enc_passwd = 0;
+ }
+ }
+#endif /* ENCRYPTION */
+}
+
+
+void
+setcommandmode(void)
+{
+ TerminalNewMode(-1);
+}
diff --git a/comms/tn3270/files/telnet/tn3270.c b/comms/tn3270/files/telnet/tn3270.c
new file mode 100644
index 00000000000..b50a51c0c75
--- /dev/null
+++ b/comms/tn3270/files/telnet/tn3270.c
@@ -0,0 +1,395 @@
+/* $NetBSD: tn3270.c,v 1.1.1.1 2010/01/17 01:33:32 dholland Exp $ */
+/* From NetBSD: tn3270.c,v 1.22 2006/10/07 17:27:57 elad Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: tn3270.c,v 1.1.1.1 2010/01/17 01:33:32 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <arpa/telnet.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include "general.h"
+#include "defines.h"
+#include "ring.h"
+#include "externs.h"
+
+#ifdef TN3270
+
+#include "../ctlr/screen.h"
+#include "../ctlr/declare.h"
+
+#include "../ascii/state.h"
+
+#include "../general/globals.h"
+
+#include "../sys_curses/telextrn.h"
+
+int
+ HaveInput, /* There is input available to scan */
+ cursesdata, /* Do we dump curses data? */
+ sigiocount; /* Number of times we got a SIGIO */
+
+char tline[200];
+char *transcom = 0; /* transparent mode command (default: none) */
+
+char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
+
+static char sb_terminal[] = { IAC, SB,
+ TELOPT_TTYPE, TELQUAL_IS,
+ 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
+ IAC, SE };
+#define SBTERMMODEL 13
+
+static int
+ Sent3270TerminalType; /* Have we said we are a 3270? */
+
+#endif /* defined(TN3270) */
+
+
+#ifdef TN3270
+void
+init_3270(void)
+{
+ HaveInput = 0;
+ sigiocount = 0;
+ Sent3270TerminalType = 0;
+ Ifrontp = Ibackp = Ibuf;
+ init_ctlr(); /* Initialize some things */
+ init_keyboard();
+ init_screen();
+ init_system();
+}
+#endif /* defined(TN3270) */
+
+
+#ifdef TN3270
+
+/*
+ * DataToNetwork - queue up some data to go to network. If "done" is set,
+ * then when last byte is queued, we add on an IAC EOR sequence (so,
+ * don't call us with "done" until you want that done...)
+ *
+ * We actually do send all the data to the network buffer, since our
+ * only client needs for us to do that.
+ */
+
+int
+DataToNetwork(char *buffer, /* where the data is */
+ int count, /* how much to send */
+ int done) /* is this the last of a logical block */
+{
+ int loop, c;
+ int origCount;
+
+ origCount = count;
+
+ while (count) {
+ /* If not enough room for EORs, IACs, etc., wait */
+ if (NETROOM() < 6) {
+ struct pollfd set[1];
+
+ set[0].fd = net;
+ set[0].events = POLLOUT;
+ netflush();
+ while (NETROOM() < 6) {
+ (void) poll(set, 1, INFTIM);
+ netflush();
+ }
+ }
+ c = ring_empty_count(&netoring);
+ if (c > count) {
+ c = count;
+ }
+ loop = c;
+ while (loop) {
+ if (((unsigned char)*buffer) == IAC) {
+ break;
+ }
+ buffer++;
+ loop--;
+ }
+ if ((c = c-loop)) {
+ ring_supply_data(&netoring, buffer-c, c);
+ count -= c;
+ }
+ if (loop) {
+ NET2ADD(IAC, IAC);
+ count--;
+ buffer++;
+ }
+ }
+
+ if (done) {
+ NET2ADD(IAC, EOR);
+ netflush(); /* try to move along as quickly as ... */
+ }
+ return(origCount - count);
+}
+
+
+void
+inputAvailable(int signo)
+{
+ HaveInput = 1;
+ sigiocount++;
+}
+
+void
+outputPurge(void)
+{
+ (void) ttyflush(1);
+}
+
+
+/*
+ * The following routines are places where the various tn3270
+ * routines make calls into telnet.c.
+ */
+
+/*
+ * DataToTerminal - queue up some data to go to terminal.
+ *
+ * Note: there are people who call us and depend on our processing
+ * *all* the data at one time (thus the poll).
+ */
+
+int
+DataToTerminal(
+ char *buffer, /* where the data is */
+ int count) /* how much to send */
+{
+ int c;
+ int origCount;
+
+ origCount = count;
+
+ while (count) {
+ if (TTYROOM() == 0) {
+ struct pollfd set[1];
+
+ set[0].fd = tout;
+ set[0].events = POLLOUT;
+ (void) ttyflush(0);
+ while (TTYROOM() == 0) {
+ (void) poll(set, 1, INFTIM);
+ (void) ttyflush(0);
+ }
+ }
+ c = TTYROOM();
+ if (c > count) {
+ c = count;
+ }
+ ring_supply_data(&ttyoring, buffer, c);
+ count -= c;
+ buffer += c;
+ }
+ return(origCount);
+}
+
+
+/*
+ * Push3270 - Try to send data along the 3270 output (to screen) direction.
+ */
+
+int
+Push3270(void)
+{
+ int save = ring_full_count(&netiring);
+
+ if (save) {
+ if (Ifrontp+save > Ibuf+sizeof Ibuf) {
+ if (Ibackp != Ibuf) {
+ memmove(Ibuf, Ibackp, Ifrontp-Ibackp);
+ Ifrontp -= (Ibackp-Ibuf);
+ Ibackp = Ibuf;
+ }
+ }
+ if (Ifrontp+save < Ibuf+sizeof Ibuf) {
+ (void)telrcv();
+ }
+ }
+ return save != ring_full_count(&netiring);
+}
+
+
+/*
+ * Finish3270 - get the last dregs of 3270 data out to the terminal
+ * before quitting.
+ */
+
+void
+Finish3270(void)
+{
+ while (Push3270() || !DoTerminalOutput()) {
+ HaveInput = 0;
+ ;
+ }
+}
+
+
+/* StringToTerminal - output a null terminated string to the terminal */
+
+void
+StringToTerminal(char *s)
+{
+ int count;
+
+ count = strlen(s);
+ if (count) {
+ (void) DataToTerminal(s, count); /* we know it always goes... */
+ }
+}
+
+
+/* _putchar - output a single character to the terminal. This name is so that
+ * curses(3x) can call us to send out data.
+ */
+
+int
+_putchar(int cc)
+{
+ char c = (char)cc;
+ if (cursesdata) {
+ Dump('>', &c, 1);
+ }
+ if (!TTYROOM()) {
+ (void) DataToTerminal(&c, 1);
+ } else {
+ TTYADD(c);
+ }
+
+ return (0);
+}
+
+void
+SetIn3270(void)
+{
+ if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
+ && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
+ if (!In3270) {
+ In3270 = 1;
+ Init3270(); /* Initialize 3270 functions */
+ /* initialize terminal key mapping */
+ InitTerminal(); /* Start terminal going */
+ setconnmode(0);
+ }
+ } else {
+ if (In3270) {
+ StopScreen(1);
+ In3270 = 0;
+ Stop3270(); /* Tell 3270 we aren't here anymore */
+ setconnmode(0);
+ }
+ }
+}
+
+/*
+ * tn3270_ttype()
+ *
+ * Send a response to a terminal type negotiation.
+ *
+ * Return '0' if no more responses to send; '1' if a response sent.
+ */
+
+int
+tn3270_ttype(void)
+{
+ /*
+ * Try to send a 3270 type terminal name. Decide which one based
+ * on the format of our screen, and (in the future) color
+ * capaiblities.
+ */
+ InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */
+ if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
+ Sent3270TerminalType = 1;
+ if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
+ MaxNumberLines = 27;
+ MaxNumberColumns = 132;
+ sb_terminal[SBTERMMODEL] = '5';
+ } else if (MaxNumberLines >= 43) {
+ MaxNumberLines = 43;
+ MaxNumberColumns = 80;
+ sb_terminal[SBTERMMODEL] = '4';
+ } else if (MaxNumberLines >= 32) {
+ MaxNumberLines = 32;
+ MaxNumberColumns = 80;
+ sb_terminal[SBTERMMODEL] = '3';
+ } else {
+ MaxNumberLines = 24;
+ MaxNumberColumns = 80;
+ sb_terminal[SBTERMMODEL] = '2';
+ }
+ NumberLines = 24; /* before we start out... */
+ NumberColumns = 80;
+ ScreenSize = NumberLines*NumberColumns;
+ if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
+ ExitString("Programming error: MAXSCREENSIZE too small.\n",
+ 1);
+ /*NOTREACHED*/
+ }
+ printsub('>', sb_terminal+2, sizeof sb_terminal-2);
+ ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int
+settranscom(int argc, char *argv[])
+{
+ int i;
+
+ if (argc == 1 && transcom) {
+ transcom = 0;
+ }
+ if (argc == 1) {
+ return 1;
+ }
+ transcom = tline;
+ (void) strlcpy(tline, argv[1], sizeof(tline));
+ for (i = 2; i < argc; ++i) {
+ (void) strlcat(tline, " ", sizeof(tline));
+ (void) strlcat(tline, argv[i], sizeof(tline));
+ }
+ return 1;
+}
+
+#endif /* defined(TN3270) */
diff --git a/comms/tn3270/files/telnet/types.h b/comms/tn3270/files/telnet/types.h
new file mode 100644
index 00000000000..96386440b74
--- /dev/null
+++ b/comms/tn3270/files/telnet/types.h
@@ -0,0 +1,51 @@
+/* $NetBSD: types.h,v 1.1.1.1 2010/01/17 01:33:32 dholland Exp $ */
+/* From NetBSD: types.h,v 1.6 2003/08/07 11:16:12 agc Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)types.h 8.1 (Berkeley) 6/6/93
+ */
+
+typedef struct {
+ char *modedescriptions;
+ char modetype;
+} Modelist;
+
+extern Modelist modelist[];
+
+typedef struct {
+ int
+ system, /* what the current time is */
+ echotoggle, /* last time user entered echo character */
+ modenegotiated, /* last time operating mode negotiated */
+ didnetreceive, /* last time we read data from network */
+ gotDM; /* when did we last see a data mark */
+} Clocks;
+
+extern Clocks clocks;
diff --git a/comms/tn3270/files/telnet/utilities.c b/comms/tn3270/files/telnet/utilities.c
new file mode 100644
index 00000000000..2f8734abf81
--- /dev/null
+++ b/comms/tn3270/files/telnet/utilities.c
@@ -0,0 +1,925 @@
+/* $NetBSD: utilities.c,v 1.1.1.1 2010/01/17 01:33:33 dholland Exp $ */
+/* From NetBSD: utilities.c,v 1.22 2006/10/07 17:27:57 elad Exp */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95";
+#else
+__RCSID("$NetBSD: utilities.c,v 1.1.1.1 2010/01/17 01:33:33 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#define TELOPTS
+#define TELCMDS
+#define SLC_NAMES
+#include <arpa/telnet.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <ctype.h>
+
+#include "general.h"
+#include "ring.h"
+#include "defines.h"
+#include "externs.h"
+
+#ifdef TN3270
+#include "../sys_curses/telextrn.h"
+#endif
+
+#ifdef AUTHENTICATION
+#include <libtelnet/auth.h>
+#endif
+#ifdef ENCRYPTION
+#include <libtelnet/encrypt.h>
+#endif
+
+FILE *NetTrace = 0; /* Not in bss, since needs to stay */
+int prettydump;
+
+/*
+ * upcase()
+ *
+ * Upcase (in place) the argument.
+ */
+
+void
+upcase(char *argument)
+{
+ int c;
+
+ while ((c = *argument) != 0) {
+ if (islower(c)) {
+ *argument = toupper(c);
+ }
+ argument++;
+ }
+}
+
+/*
+ * SetSockOpt()
+ *
+ * Compensate for differences in 4.2 and 4.3 systems.
+ */
+
+int
+SetSockOpt(int fd, int level, int option, int yesno)
+{
+ return setsockopt(fd, level, option, (char *)&yesno, sizeof yesno);
+}
+
+/*
+ * The following are routines used to print out debugging information.
+ */
+
+char NetTraceFile[256] = "(standard output)";
+
+void
+SetNetTrace(char *file)
+{
+ if (NetTrace && NetTrace != stdout)
+ fclose(NetTrace);
+ if (file && (strcmp(file, "-") != 0)) {
+ NetTrace = fopen(file, "w");
+ if (NetTrace) {
+ strlcpy(NetTraceFile, file, sizeof(NetTraceFile));
+ return;
+ }
+ fprintf(stderr, "Cannot open %s.\n", file);
+ }
+ NetTrace = stdout;
+ strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile));
+}
+
+void
+Dump(int direction, unsigned char *buffer, int length)
+{
+# define BYTES_PER_LINE 32
+# define min(x,y) ((x<y)? x:y)
+ unsigned char *pThis;
+ int offset;
+
+ offset = 0;
+
+ while (length) {
+ /* print one line */
+ fprintf(NetTrace, "%c 0x%x\t", direction, offset);
+ pThis = buffer;
+ if (prettydump) {
+ buffer = buffer + min(length, BYTES_PER_LINE/2);
+ while (pThis < buffer) {
+ fprintf(NetTrace, "%c%.2x",
+ (((*pThis)&0xff) == 0xff) ? '*' : ' ',
+ (*pThis)&0xff);
+ pThis++;
+ }
+ length -= BYTES_PER_LINE/2;
+ offset += BYTES_PER_LINE/2;
+ } else {
+ buffer = buffer + min(length, BYTES_PER_LINE);
+ while (pThis < buffer) {
+ fprintf(NetTrace, "%.2x", (*pThis)&0xff);
+ pThis++;
+ }
+ length -= BYTES_PER_LINE;
+ offset += BYTES_PER_LINE;
+ }
+ if (NetTrace == stdout) {
+ fprintf(NetTrace, "\r\n");
+ } else {
+ fprintf(NetTrace, "\n");
+ }
+ if (length < 0) {
+ fflush(NetTrace);
+ return;
+ }
+ /* find next unique line */
+ }
+ fflush(NetTrace);
+}
+
+
+void
+printoption(char *direction, int cmd, int option)
+{
+ if (!showoptions)
+ return;
+ if (cmd == IAC) {
+ if (TELCMD_OK(option))
+ fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
+ else
+ fprintf(NetTrace, "%s IAC %d", direction, option);
+ } else {
+ char *fmt;
+ fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
+ (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
+ if (fmt) {
+ fprintf(NetTrace, "%s %s ", direction, fmt);
+ if (TELOPT_OK(option))
+ fprintf(NetTrace, "%s", TELOPT(option));
+ else if (option == TELOPT_EXOPL)
+ fprintf(NetTrace, "EXOPL");
+ else
+ fprintf(NetTrace, "%d", option);
+ } else
+ fprintf(NetTrace, "%s %d %d", direction, cmd, option);
+ }
+ if (NetTrace == stdout) {
+ fprintf(NetTrace, "\r\n");
+ fflush(NetTrace);
+ } else {
+ fprintf(NetTrace, "\n");
+ }
+ return;
+}
+
+void
+optionstatus(void)
+{
+ int i;
+ extern char will_wont_resp[], do_dont_resp[];
+
+ for (i = 0; i < 256; i++) {
+ if (do_dont_resp[i]) {
+ if (TELOPT_OK(i))
+ printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
+ else if (TELCMD_OK(i))
+ printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
+ else
+ printf("resp DO_DONT %d: %d\n", i,
+ do_dont_resp[i]);
+ if (my_want_state_is_do(i)) {
+ if (TELOPT_OK(i))
+ printf("want DO %s\n", TELOPT(i));
+ else if (TELCMD_OK(i))
+ printf("want DO %s\n", TELCMD(i));
+ else
+ printf("want DO %d\n", i);
+ } else {
+ if (TELOPT_OK(i))
+ printf("want DONT %s\n", TELOPT(i));
+ else if (TELCMD_OK(i))
+ printf("want DONT %s\n", TELCMD(i));
+ else
+ printf("want DONT %d\n", i);
+ }
+ } else {
+ if (my_state_is_do(i)) {
+ if (TELOPT_OK(i))
+ printf(" DO %s\n", TELOPT(i));
+ else if (TELCMD_OK(i))
+ printf(" DO %s\n", TELCMD(i));
+ else
+ printf(" DO %d\n", i);
+ }
+ }
+ if (will_wont_resp[i]) {
+ if (TELOPT_OK(i))
+ printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
+ else if (TELCMD_OK(i))
+ printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
+ else
+ printf("resp WILL_WONT %d: %d\n",
+ i, will_wont_resp[i]);
+ if (my_want_state_is_will(i)) {
+ if (TELOPT_OK(i))
+ printf("want WILL %s\n", TELOPT(i));
+ else if (TELCMD_OK(i))
+ printf("want WILL %s\n", TELCMD(i));
+ else
+ printf("want WILL %d\n", i);
+ } else {
+ if (TELOPT_OK(i))
+ printf("want WONT %s\n", TELOPT(i));
+ else if (TELCMD_OK(i))
+ printf("want WONT %s\n", TELCMD(i));
+ else
+ printf("want WONT %d\n", i);
+ }
+ } else {
+ if (my_state_is_will(i)) {
+ if (TELOPT_OK(i))
+ printf(" WILL %s\n", TELOPT(i));
+ else if (TELCMD_OK(i))
+ printf(" WILL %s\n", TELCMD(i));
+ else
+ printf(" WILL %d\n", i);
+ }
+ }
+ }
+
+}
+
+void
+printsub(
+ int direction, /* '<' or '>' */
+ unsigned char *pointer, /* where suboption data sits */
+ int length) /* length of suboption data */
+{
+ int i;
+#ifdef ENCRYPTION
+ char buf[512];
+#endif /* ENCRYPTION */
+ extern int want_status_response;
+
+ if (showoptions || direction == 0 ||
+ (want_status_response && (pointer[0] == TELOPT_STATUS))) {
+ if (direction) {
+ fprintf(NetTrace, "%s IAC SB ",
+ (direction == '<')? "RCVD":"SENT");
+ if (length >= 3) {
+ int j;
+
+ i = pointer[length-2];
+ j = pointer[length-1];
+
+ if (i != IAC || j != SE) {
+ fprintf(NetTrace, "(terminated by ");
+ if (TELOPT_OK(i))
+ fprintf(NetTrace, "%s ", TELOPT(i));
+ else if (TELCMD_OK(i))
+ fprintf(NetTrace, "%s ", TELCMD(i));
+ else
+ fprintf(NetTrace, "%d ", i);
+ if (TELOPT_OK(j))
+ fprintf(NetTrace, "%s", TELOPT(j));
+ else if (TELCMD_OK(j))
+ fprintf(NetTrace, "%s", TELCMD(j));
+ else
+ fprintf(NetTrace, "%d", j);
+ fprintf(NetTrace, ", not IAC SE!) ");
+ }
+ }
+ length -= 2;
+ }
+ if (length < 1) {
+ fprintf(NetTrace, "(Empty suboption??\?)");
+ if (NetTrace == stdout)
+ fflush(NetTrace);
+ return;
+ }
+ switch (pointer[0]) {
+ case TELOPT_TTYPE:
+ fprintf(NetTrace, "TERMINAL-TYPE ");
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ break;
+ case TELQUAL_SEND:
+ fprintf(NetTrace, "SEND");
+ break;
+ default:
+ fprintf(NetTrace,
+ "- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
+ }
+ break;
+ case TELOPT_TSPEED:
+ fprintf(NetTrace, "TERMINAL-SPEED");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ fprintf(NetTrace, " IS ");
+ fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
+ break;
+ default:
+ if (pointer[1] == 1)
+ fprintf(NetTrace, " SEND");
+ else
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+ }
+ break;
+
+ case TELOPT_LFLOW:
+ fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case LFLOW_OFF:
+ fprintf(NetTrace, " OFF"); break;
+ case LFLOW_ON:
+ fprintf(NetTrace, " ON"); break;
+ case LFLOW_RESTART_ANY:
+ fprintf(NetTrace, " RESTART-ANY"); break;
+ case LFLOW_RESTART_XON:
+ fprintf(NetTrace, " RESTART-XON"); break;
+ default:
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ }
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+
+ case TELOPT_NAWS:
+ fprintf(NetTrace, "NAWS");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ if (length == 2) {
+ fprintf(NetTrace, " ?%d?", pointer[1]);
+ break;
+ }
+ fprintf(NetTrace, " %d %d (%d)",
+ pointer[1], pointer[2],
+ (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
+ if (length == 4) {
+ fprintf(NetTrace, " ?%d?", pointer[3]);
+ break;
+ }
+ fprintf(NetTrace, " %d %d (%d)",
+ pointer[3], pointer[4],
+ (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
+ for (i = 5; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+
+#ifdef AUTHENTICATION
+ case TELOPT_AUTHENTICATION:
+ fprintf(NetTrace, "AUTHENTICATION");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case TELQUAL_REPLY:
+ case TELQUAL_IS:
+ fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
+ "IS" : "REPLY");
+ if (AUTHTYPE_NAME_OK(pointer[2]))
+ fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
+ else
+ fprintf(NetTrace, "%d ", pointer[2]);
+ if (length < 3) {
+ fprintf(NetTrace, "(partial suboption??\?)");
+ break;
+ }
+ fprintf(NetTrace, "%s|%s",
+ ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+ "CLIENT" : "SERVER",
+ ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+ "MUTUAL" : "ONE-WAY");
+
+ auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
+ fprintf(NetTrace, "%s", buf);
+ break;
+
+ case TELQUAL_SEND:
+ i = 2;
+ fprintf(NetTrace, " SEND ");
+ while (i < length) {
+ if (AUTHTYPE_NAME_OK(pointer[i]))
+ fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
+ else
+ fprintf(NetTrace, "%d ", pointer[i]);
+ if (++i >= length) {
+ fprintf(NetTrace, "(partial suboption??\?)");
+ break;
+ }
+ fprintf(NetTrace, "%s|%s ",
+ ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
+ "CLIENT" : "SERVER",
+ ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
+ "MUTUAL" : "ONE-WAY");
+ ++i;
+ }
+ break;
+
+ case TELQUAL_NAME:
+ i = 2;
+ fprintf(NetTrace, " NAME \"");
+ while (i < length)
+ putc(pointer[i++], NetTrace);
+ putc('"', NetTrace);
+ break;
+
+ default:
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+ }
+ break;
+#endif
+
+#ifdef ENCRYPTION
+ case TELOPT_ENCRYPT:
+ fprintf(NetTrace, "ENCRYPT");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case ENCRYPT_START:
+ fprintf(NetTrace, " START");
+ break;
+
+ case ENCRYPT_END:
+ fprintf(NetTrace, " END");
+ break;
+
+ case ENCRYPT_REQSTART:
+ fprintf(NetTrace, " REQUEST-START");
+ break;
+
+ case ENCRYPT_REQEND:
+ fprintf(NetTrace, " REQUEST-END");
+ break;
+
+ case ENCRYPT_IS:
+ case ENCRYPT_REPLY:
+ fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
+ "IS" : "REPLY");
+ if (length < 3) {
+ fprintf(NetTrace, " (partial suboption??\?)");
+ break;
+ }
+ if (ENCTYPE_NAME_OK(pointer[2]))
+ fprintf(NetTrace, "%s ",
+ ENCTYPE_NAME(pointer[2]));
+ else
+ fprintf(NetTrace, " %d (unknown)", pointer[2]);
+
+ encrypt_printsub(&pointer[1], length - 1, buf,
+ sizeof(buf));
+ fprintf(NetTrace, "%s", buf);
+ break;
+
+ case ENCRYPT_SUPPORT:
+ i = 2;
+ fprintf(NetTrace, " SUPPORT ");
+ while (i < length) {
+ if (ENCTYPE_NAME_OK(pointer[i]))
+ fprintf(NetTrace, "%s ",
+ ENCTYPE_NAME(pointer[i]));
+ else
+ fprintf(NetTrace, "%d ", pointer[i]);
+ i++;
+ }
+ break;
+
+ case ENCRYPT_ENC_KEYID:
+ fprintf(NetTrace, " ENC_KEYID ");
+ goto encommon;
+
+ case ENCRYPT_DEC_KEYID:
+ fprintf(NetTrace, " DEC_KEYID ");
+ goto encommon;
+
+ default:
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ encommon:
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " %d", pointer[i]);
+ break;
+ }
+ break;
+#endif /* ENCRYPTION */
+
+ case TELOPT_LINEMODE:
+ fprintf(NetTrace, "LINEMODE ");
+ if (length < 2) {
+ fprintf(NetTrace, " (empty suboption??\?)");
+ break;
+ }
+ switch (pointer[1]) {
+ case WILL:
+ fprintf(NetTrace, "WILL ");
+ goto common;
+ case WONT:
+ fprintf(NetTrace, "WONT ");
+ goto common;
+ case DO:
+ fprintf(NetTrace, "DO ");
+ goto common;
+ case DONT:
+ fprintf(NetTrace, "DONT ");
+ common:
+ if (length < 3) {
+ fprintf(NetTrace, "(no option??\?)");
+ break;
+ }
+ switch (pointer[2]) {
+ case LM_FORWARDMASK:
+ fprintf(NetTrace, "Forward Mask");
+ for (i = 3; i < length; i++)
+ fprintf(NetTrace, " %x", pointer[i]);
+ break;
+ default:
+ fprintf(NetTrace, "%d (unknown)", pointer[2]);
+ for (i = 3; i < length; i++)
+ fprintf(NetTrace, " %d", pointer[i]);
+ break;
+ }
+ break;
+
+ case LM_SLC:
+ fprintf(NetTrace, "SLC");
+ for (i = 2; i < length - 2; i += 3) {
+ if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
+ fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
+ else
+ fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
+ switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
+ case SLC_NOSUPPORT:
+ fprintf(NetTrace, " NOSUPPORT"); break;
+ case SLC_CANTCHANGE:
+ fprintf(NetTrace, " CANTCHANGE"); break;
+ case SLC_VARIABLE:
+ fprintf(NetTrace, " VARIABLE"); break;
+ case SLC_DEFAULT:
+ fprintf(NetTrace, " DEFAULT"); break;
+ }
+ fprintf(NetTrace, "%s%s%s",
+ pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
+ pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
+ pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
+ if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
+ SLC_FLUSHOUT| SLC_LEVELBITS))
+ fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
+ fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
+ if ((pointer[i+SLC_VALUE] == IAC) &&
+ (pointer[i+SLC_VALUE+1] == IAC))
+ i++;
+ }
+ for (; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+
+ case LM_MODE:
+ fprintf(NetTrace, "MODE ");
+ if (length < 3) {
+ fprintf(NetTrace, "(no mode??\?)");
+ break;
+ }
+ {
+ char tbuf[64];
+ sprintf(tbuf, "%s%s%s%s%s",
+ pointer[2]&MODE_EDIT ? "|EDIT" : "",
+ pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
+ pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
+ pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
+ pointer[2]&MODE_ACK ? "|ACK" : "");
+ fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
+ }
+ if (pointer[2]&~(MODE_MASK))
+ fprintf(NetTrace, " (0x%x)", pointer[2]);
+ for (i = 3; i < length; i++)
+ fprintf(NetTrace, " ?0x%x?", pointer[i]);
+ break;
+ default:
+ fprintf(NetTrace, "%d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " %d", pointer[i]);
+ }
+ break;
+
+ case TELOPT_STATUS: {
+ char *cp;
+ int j, k;
+
+ fprintf(NetTrace, "STATUS");
+
+ switch (pointer[1]) {
+ default:
+ if (pointer[1] == TELQUAL_SEND)
+ fprintf(NetTrace, " SEND");
+ else
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ for (i = 2; i < length; i++)
+ fprintf(NetTrace, " ?%d?", pointer[i]);
+ break;
+ case TELQUAL_IS:
+ if (--want_status_response < 0)
+ want_status_response = 0;
+ if (NetTrace == stdout)
+ fprintf(NetTrace, " IS\r\n");
+ else
+ fprintf(NetTrace, " IS\n");
+
+ for (i = 2; i < length; i++) {
+ switch(pointer[i]) {
+ case DO: cp = "DO"; goto common2;
+ case DONT: cp = "DONT"; goto common2;
+ case WILL: cp = "WILL"; goto common2;
+ case WONT: cp = "WONT"; goto common2;
+ common2:
+ i++;
+ if (TELOPT_OK((int)pointer[i]))
+ fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
+ else
+ fprintf(NetTrace, " %s %d", cp, pointer[i]);
+
+ if (NetTrace == stdout)
+ fprintf(NetTrace, "\r\n");
+ else
+ fprintf(NetTrace, "\n");
+ break;
+
+ case SB:
+ fprintf(NetTrace, " SB ");
+ i++;
+ j = k = i;
+ while (j < length) {
+ if (pointer[j] == SE) {
+ if (j+1 == length)
+ break;
+ if (pointer[j+1] == SE)
+ j++;
+ else
+ break;
+ }
+ pointer[k++] = pointer[j++];
+ }
+ printsub(0, &pointer[i], k - i);
+ if (i < length) {
+ fprintf(NetTrace, " SE");
+ i = j;
+ } else
+ i = j - 1;
+
+ if (NetTrace == stdout)
+ fprintf(NetTrace, "\r\n");
+ else
+ fprintf(NetTrace, "\n");
+
+ break;
+
+ default:
+ fprintf(NetTrace, " %d", pointer[i]);
+ break;
+ }
+ }
+ break;
+ }
+ break;
+ }
+
+ case TELOPT_XDISPLOC:
+ fprintf(NetTrace, "X-DISPLAY-LOCATION ");
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
+ break;
+ case TELQUAL_SEND:
+ fprintf(NetTrace, "SEND");
+ break;
+ default:
+ fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
+ pointer[1], pointer[1]);
+ }
+ break;
+
+ case TELOPT_NEW_ENVIRON:
+ fprintf(NetTrace, "NEW-ENVIRON ");
+#ifdef OLD_ENVIRON
+ goto env_common1;
+ case TELOPT_OLD_ENVIRON:
+ fprintf(NetTrace, "OLD-ENVIRON");
+ env_common1:
+#endif
+ switch (pointer[1]) {
+ case TELQUAL_IS:
+ fprintf(NetTrace, "IS ");
+ goto env_common;
+ case TELQUAL_SEND:
+ fprintf(NetTrace, "SEND ");
+ goto env_common;
+ case TELQUAL_INFO:
+ fprintf(NetTrace, "INFO ");
+ env_common:
+ {
+ int noquote = 2;
+#if defined(ENV_HACK) && defined(OLD_ENVIRON)
+ extern int old_env_var, old_env_value;
+#endif
+ for (i = 2; i < length; i++ ) {
+ switch (pointer[i]) {
+ case NEW_ENV_VALUE:
+#ifdef OLD_ENVIRON
+ /* case NEW_ENV_OVAR: */
+ if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef ENV_HACK
+ if (old_env_var == OLD_ENV_VALUE)
+ fprintf(NetTrace, "\" (VALUE) " + noquote);
+ else
+# endif
+ fprintf(NetTrace, "\" VAR " + noquote);
+ } else
+#endif /* OLD_ENVIRON */
+ fprintf(NetTrace, "\" VALUE " + noquote);
+ noquote = 2;
+ break;
+
+ case NEW_ENV_VAR:
+#ifdef OLD_ENVIRON
+ /* case OLD_ENV_VALUE: */
+ if (pointer[0] == TELOPT_OLD_ENVIRON) {
+# ifdef ENV_HACK
+ if (old_env_value == OLD_ENV_VAR)
+ fprintf(NetTrace, "\" (VAR) " + noquote);
+ else
+# endif
+ fprintf(NetTrace, "\" VALUE " + noquote);
+ } else
+#endif /* OLD_ENVIRON */
+ fprintf(NetTrace, "\" VAR " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_ESC:
+ fprintf(NetTrace, "\" ESC " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_USERVAR:
+ fprintf(NetTrace, "\" USERVAR " + noquote);
+ noquote = 2;
+ break;
+
+ default:
+ if (isprint(pointer[i]) && pointer[i] != '"') {
+ if (noquote) {
+ putc('"', NetTrace);
+ noquote = 0;
+ }
+ putc(pointer[i], NetTrace);
+ } else {
+ fprintf(NetTrace, "\" %03o " + noquote,
+ pointer[i]);
+ noquote = 2;
+ }
+ break;
+ }
+ }
+ if (!noquote)
+ putc('"', NetTrace);
+ break;
+ }
+ }
+ break;
+
+ default:
+ if (TELOPT_OK(pointer[0]))
+ fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
+ else
+ fprintf(NetTrace, "%d (unknown)", pointer[0]);
+ for (i = 1; i < length; i++)
+ fprintf(NetTrace, " %d", pointer[i]);
+ break;
+ }
+ if (direction) {
+ if (NetTrace == stdout)
+ fprintf(NetTrace, "\r\n");
+ else
+ fprintf(NetTrace, "\n");
+ }
+ if (NetTrace == stdout)
+ fflush(NetTrace);
+ }
+}
+
+/* EmptyTerminal - called to make sure that the terminal buffer is empty.
+ * Note that we consider the buffer to run all the
+ * way to the kernel (thus the poll).
+ */
+
+void
+EmptyTerminal(void)
+{
+ struct pollfd set[1];
+
+ set[0].fd = tout;
+ set[0].events = POLLOUT;
+
+ if (TTYBYTES() == 0) {
+ (void) poll(set, 1, INFTIM);
+ } else {
+ while (TTYBYTES()) {
+ (void) ttyflush(0);
+ (void) poll(set, 1, INFTIM);
+ }
+ }
+}
+
+void
+SetForExit(void)
+{
+ setconnmode(0);
+#ifdef TN3270
+ if (In3270) {
+ Finish3270();
+ }
+#else /* defined(TN3270) */
+ do {
+ (void)telrcv(); /* Process any incoming data */
+ EmptyTerminal();
+ } while (ring_full_count(&netiring)); /* While there is any */
+#endif /* defined(TN3270) */
+ setcommandmode();
+ fflush(stdout);
+ fflush(stderr);
+#ifdef TN3270
+ if (In3270) {
+ StopScreen(1);
+ }
+#endif /* defined(TN3270) */
+ setconnmode(0);
+ EmptyTerminal(); /* Flush the path to the tty */
+ setcommandmode();
+}
+
+void
+Exit(int returnCode)
+{
+ SetForExit();
+ exit(returnCode);
+}
+
+void
+ExitString(char *string, int returnCode)
+{
+ SetForExit();
+ fwrite(string, 1, strlen(string), stderr);
+ exit(returnCode);
+}
diff --git a/comms/tn3270/files/tn3270/Makefile b/comms/tn3270/files/tn3270/Makefile
new file mode 100644
index 00000000000..b3f2860c9df
--- /dev/null
+++ b/comms/tn3270/files/tn3270/Makefile
@@ -0,0 +1,87 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+# From NetBSD: Makefile,v 1.38 2008/08/29 00:02:24 gmcgarry Exp
+
+.include <bsd.own.mk>
+
+CPPFLAGS+=-I${NETBSDSRCDIR}/lib -I${NETBSDSRCDIR}/usr.bin/telnet
+LDADD+= -lcurses -lcrypt
+DPADD+= ${LIBCURSES} ${LIBCRYPT}
+
+PROG= tn3270
+SRCS= api.c api_bsd.c api_exch.c apilib.c asc_ebc.c astosc.c commands.c \
+ dctype.c disp_asc.c ebc_disp.c function.c genbsubs.c genget.c \
+ globals.c inbound.c main.c map3270.c network.c oia.c options.c \
+ outbound.c ring.c sys_bsd.c system.c telnet.c termin.c terminal.c \
+ termout.c tn3270.c utilities.c
+DPSRCS= asc_disp.out astosc.out disp_asc.out kbd.out
+
+MKASTOSCDIR !=cd $(.CURDIR)/../tools/mkastosc && ${PRINTOBJDIR}
+MKASTOSC= ${MKASTOSCDIR}/mkastosc
+
+${MKASTOSC}:
+ @cd ${.CURDIR}/../tools/mkastosc && ${MAKE}
+
+MKASTODSDIR!=cd $(.CURDIR)/../tools/mkastods && ${PRINTOBJDIR}
+MKASTODS= ${MKASTODSDIR}/mkastods
+
+${MKASTODS}:
+ @cd ${.CURDIR}/../tools/mkastods && ${MAKE}
+
+MKDSTOASDIR!=cd $(.CURDIR)/../tools/mkdstoas && ${PRINTOBJDIR}
+MKDSTOAS= ${MKDSTOASDIR}/mkdstoas
+
+${MKDSTOAS}:
+ @cd ${.CURDIR}/../tools/mkdstoas && ${MAKE}
+
+MKHITSDIR!=cd $(.CURDIR)/../tools/mkhits && ${PRINTOBJDIR}
+MKHITS= ${MKHITSDIR}/mkhits
+
+${MKHITS}:
+ @cd ${.CURDIR}/../tools/mkhits && ${MAKE}
+
+astosc.out: ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h \
+ ${.CURDIR}/../ctlr/${KBD} ${MKASTOSC}
+ ${_MKTARGET_CREATE}
+ ${MKASTOSC} \
+ ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h \
+ < ${.CURDIR}/../ctlr/${KBD} > astosc.tmp
+ mv -f astosc.tmp ${.TARGET}
+CLEANFILES+= astosc.tmp astosc.out
+
+asc_disp.out: ${MKASTODS}
+ ${_MKTARGET_CREATE}
+ ${MKASTODS} > asc_disp.tmp
+ mv -f asc_disp.tmp ${.TARGET}
+CLEANFILES+= asc_disp.tmp asc_disp.out
+
+disp_asc.out: ${MKDSTOAS}
+ ${_MKTARGET_CREATE}
+ ${MKDSTOAS} > disp_asc.tmp
+ mv -f disp_asc.tmp ${.TARGET}
+CLEANFILES+= disp_asc.tmp disp_asc.out
+
+kbd.out: ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/${KBD} ${MKHITS}
+ ${_MKTARGET_CREATE}
+ ${CC} ${CPPFLAGS} -E ${.CURDIR}/../ctlr/function.c > TMPfunc.out
+ ${MKHITS} \
+ ${.CURDIR}/../ctlr/hostctlr.h TMPfunc.out \
+ < ${.CURDIR}/../ctlr/${KBD} > kbd.tmp
+ rm -f TMPFunc.out
+ mv -f kbd.tmp ${.TARGET}
+CLEANFILES+= TMPfunc.out kbd.tmp kbd.out
+
+.include <bsd.prog.mk>
+
+.if (defined(HAVE_GCC) && ${HAVE_GCC} == 4) || defined(HAVE_PCC)
+.for f in api commands system telnet terminal termout tn3270 utilities
+COPTS.${f}.c+= -Wno-pointer-sign
+.endfor
+.endif
+
+.PATH: ${.CURDIR}/../api ${.CURDIR}/../ascii ${.CURDIR}/../ctlr
+.PATH: ${.CURDIR}/../general ${.CURDIR}/../sys_curses ${.CURDIR}/../../telnet
+.PATH: ${NETBSDSRCDIR}/lib/libtelnet
+
+astosc.o: astosc.out
+disp_asc.o: asc_disp.out disp_asc.out
+inbound.o: kbd.out
diff --git a/comms/tn3270/files/tn3270/tn3270.1 b/comms/tn3270/files/tn3270/tn3270.1
new file mode 100644
index 00000000000..7c5c5c5bcf8
--- /dev/null
+++ b/comms/tn3270/files/tn3270/tn3270.1
@@ -0,0 +1,340 @@
+.\" $NetBSD: tn3270.1,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+.\" From NetBSD: tn3270.1,v 1.14 2006/06/17 02:11:29 reed Exp
+.\"
+.\" Copyright (c) 1986, 1990 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)tn3270.1 4.6 (Berkeley) 7/27/91
+.\" $NetBSD: tn3270.1,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+.\"
+.Dd July 27, 1991
+.Dt TN3270 1
+.Os
+.Sh NAME
+.Nm tn3270
+.Nd full-screen remote login to
+.Tn IBM VM/CMS
+.Sh SYNOPSIS
+.Nm
+.Op Fl d
+.Op Fl n Ar filename
+.Op Fl t Ar commandname
+.Op Ar sysname Op port
+.Sh DESCRIPTION
+.Nm
+permits a full-screen, full-duplex connection
+from a
+.Ux
+machine
+to an
+.Tn IBM
+(or compatible) machine.
+.Nm
+gives the appearance of being logged in
+to the remote machine
+from an
+.Tn IBM
+3270 terminal.
+Of course, you must have an account on the machine
+to which you connect in order to log in.
+.Nm
+looks to the user in many respects
+like the Yale
+.Tn ASCII
+Terminal Communication System II.
+.Nm
+is actually a modification of the ARPANET
+.Tn TELNET
+user interface (see
+.Xr telnet 1 )
+which will, in certain circumstances, interpret and generate
+raw 3270 control streams.
+.Pp
+The flags to
+.Nm
+are as follows:
+.Bl -tag -width indent
+.It Fl d
+Turn on socket-level tracing (for super-user only)
+.It Fl n Ar filename
+Specify a file to receive network trace data
+output (from commands "toggle netdata" and
+"toggle options", see
+.Xr telnet 1 ) ;
+the default is for output
+to be directed to the standard error file.
+.It Fl t Ar commandname
+Specify a
+.Ux
+command to process
+.Tn IBM
+4994 style transparent mode
+data received from the remote
+.Tn IBM
+machine.
+.It Ar sysname
+The name of the remote system. If the remote name
+is NOT specified, the user will be prompted for a
+command (see below).
+.It Ar port
+The port to connect to on the remote system.
+Normally,
+.Nm
+attempts to connect to the
+standard
+.Tn TELNET
+port (port
+23) on the remote machine.
+.El
+.Pp
+When
+.Nm
+first connects to the remote system, it will negotiate to go into
+3270 mode.
+Part of this negotiation involves telling the remote system what model
+3270 it is emulating.
+In all cases,
+.Nm
+emulates a 3278 terminal.
+To decide which specific model,
+.Nm
+looks at the number of lines and columns on the actual terminal (as
+defined in the
+.Ev TERM
+environment variable; see
+.Xr termcap 5 ) .
+The terminal (or window in which
+.Nm
+is running, on multiple
+window systems) must have at least 80 columns and 24 lines, or
+.Nm
+will not go into emulation mode.
+If the terminal does have at least 80 columns and at least 24 lines,
+the following table describes the emulation:
+.Pp
+.ne 7v
+.Bd -filled -offset center
+.Bl -column (rows*columns)
+.It minimum_size emulated
+.It (rows*columns) terminal
+.It -------------- ------------
+.It 27*132 3278 model 5
+.It 43*80 3278 model 4
+.It 32*80 3278 model 3
+.It 24*80 3278 model 2.
+.El
+.Ed
+.Pp
+Emulation of the 3270 terminal is done in the
+.Ux
+process.
+This emulation involves mapping
+3270-style commands from the host
+into appropriate sequences to control the user's terminal screen.
+.Nm
+uses
+.Xr curses 3
+and the
+.Pa /usr/share/misc/termcap
+file to do this.
+The emulation also involves simulating the special 3270 keyboard keys
+(program function keys, etc.)
+by mapping sequences of keystrokes
+from the
+.Tn ASCII
+keyboard into appropriate 3270 control strings.
+This mapping is terminal dependent and is specified
+in a description file,
+.Pa /usr/share/misc/map3270 ,
+(see
+.Xr map3270 5 )
+or in an environment variable
+.Ev MAP3270
+(and, if necessary,
+.Ev MAP3270A ,
+.Ev MAP3270B ,
+and so on - see
+.Xr mset 1 ) .
+Any special function keys on the
+.Tn ASCII
+keyboard are used whenever possible.
+If an entry for the user's terminal
+is not found,
+.Nm
+looks for an entry for the terminal type
+.Em unknown .
+If this is not found,
+.Nm
+uses a default keyboard mapping
+(see
+.Xr map3270 5 ) .
+.Pp
+The first character of each special keyboard mapping sequence
+is either an
+.Tn ASCII
+escape
+.Pq Tn ESC ,
+a control character, or an
+.Tn ASCII
+delete
+.Pq Tn DEL .
+If the user types an unrecognized function key sequence,
+.Nm
+sends an
+.Tn ASCII
+bell
+.Pq Tn BEL ,
+or a visual bell if
+defined in the user's termcap entry, to the user's terminal
+and nothing is sent to the
+.Tn IBM
+host.
+.Pp
+If
+.Nm
+is invoked without specifying a remote host system name,
+it enters local command mode,
+indicated by the prompt
+.Dq Li tn3270\*[Gt]\ .
+In this mode,
+.Nm
+accepts and executes
+all the commands of
+.Xr telnet 1 ,
+plus one additional command:
+.Pp
+.Bl -tag -width Ar
+.It Ic transcom
+Specify
+.Ux
+command for
+.Tn IBM
+4994 style transparent mode processing.
+.El
+.Pp
+.Nm
+command mode may also be entered, after connecting to a host, by typing
+a special escape sequence.
+If
+.Nm
+has succeeded in negotiating 3270 mode with the remote host, the
+escape sequence will be as defined by the map3270 (see
+.Xr map3270 5 )
+entry for the user's terminal type
+(typically control-C);
+otherwise the escape sequence will initially be set to the
+single character
+.Sq Li \&^]
+(control right square bracket).
+.Pp
+While in command mode, any host login session is still alive
+but temporarily suspended.
+The host login session may be resumed by entering an empty line
+(press the
+.Tn RETURN
+key)
+in response to the command prompt.
+A session may be terminated by logging off the foreign host,
+or by typing ``quit'' or ``close'' while in local command mode.
+.Sh FILES
+.Bl -tag -width /usr/share/misc/termcap -compact
+.It Pa /usr/share/misc/termcap
+.It Pa /usr/share/misc/map3270
+.El
+.\" .Sh AUTHOR
+.\" Greg Minshall
+.Sh NOTES
+The
+.Tn IBM
+4994 style transparent mode command is invoked when
+.Nm
+receives
+.Tn IBM
+4994 style transparent output from the remote host.
+Output and input pipes are created for communication between the two
+processes.
+The pipes are closed when a 3270 clear command is received from the remote
+hosts, signaling the end of transparent mode output.
+Transparent mode is necessary for sending
+.Tn ASCII
+control characters over the
+3270 terminal connection;
+.Tn ASCII
+graphics terminal support is accomplished this
+way.
+Developers of
+.Ic transcom
+commands should note that the
+.Ic transcom
+stdin pipe end will be in
+.Dv CBREAK
+mode, with
+.Dv ECHO
+and
+.Dv CRMOD
+turned off.
+.Sh ENVIRONMENT
+.Nm
+checks the following environment variables:
+.Ev TERM ,
+.Ev MAP3270 ,
+.Ev MAP3270[A...] .
+Information on these can be found in
+.Xr mset 1 .
+.Nm
+also checks
+.Ev SHELL ,
+.Ev KEYBD
+and
+.Ev API3270 .
+.Sh SEE ALSO
+.Xr mset 1 ,
+.Xr telnet 1 ,
+.Xr curses 3 ,
+.Xr termcap 3 ,
+.Xr map3270 5 ,
+.Xr termcap 5
+.Rs
+.%T "Yale ASCII Terminal Communication"
+.%B "System II Program Description/Operator's Manual"
+.%R IBM SB30-1911
+.Re
+.Sh HISTORY
+The
+.Nm
+command appeared in
+.Bx 4.3 .
+.Sh BUGS
+.Nm
+is slow and uses system resources prodigiously.
+.Pp
+Not all 3270 functions are supported,
+nor all Yale enhancements.
+.Pp
+Error conditions (attempting to enter data in a protected field, for
+example) should cause a message to be sent to the user's terminal
+instead of just ringing a bell.
diff --git a/comms/tn3270/files/tools/Makefile b/comms/tn3270/files/tools/Makefile
new file mode 100644
index 00000000000..99794b98fcc
--- /dev/null
+++ b/comms/tn3270/files/tools/Makefile
@@ -0,0 +1,6 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+# From NetBSD: Makefile,v 1.6 2005/09/17 16:52:02 chs Exp
+
+SUBDIR = mkhits mkastosc mkastods mkdstoas mkdctype mkmake .WAIT prt3270
+
+.include <bsd.subdir.mk>
diff --git a/comms/tn3270/files/tools/Makefile.inc b/comms/tn3270/files/tools/Makefile.inc
new file mode 100644
index 00000000000..64e4f5cba1c
--- /dev/null
+++ b/comms/tn3270/files/tools/Makefile.inc
@@ -0,0 +1,13 @@
+# $NetBSD: Makefile.inc,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+# From NetBSD: Makefile.inc,v 1.8 2002/09/18 14:00:42 lukem Exp
+
+NOMAN= # defined
+
+HOST_CPPFLAGS+=-I${.CURDIR}/../../api
+KBD= unix.kbd
+
+.PATH: ${.CURDIR}/../../api
+
+.if exists(${.CURDIR}/../../../Makefile.inc)
+.include "${.CURDIR}/../../../Makefile.inc"
+.endif
diff --git a/comms/tn3270/files/tools/mkastods/Makefile b/comms/tn3270/files/tools/mkastods/Makefile
new file mode 100644
index 00000000000..d3c70cb77cc
--- /dev/null
+++ b/comms/tn3270/files/tools/mkastods/Makefile
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+# From NetBSD: Makefile,v 1.10 2002/09/15 01:27:45 thorpej Exp
+
+HOSTPROG= mkastods
+HOST_CPPFLAGS+= -DHOST_TOOL
+SRCS= mkastods.c asc_ebc.c ebc_disp.c
+
+.include <bsd.hostprog.mk>
diff --git a/comms/tn3270/files/tools/mkastods/mkastods.c b/comms/tn3270/files/tools/mkastods/mkastods.c
new file mode 100644
index 00000000000..9e5b191afc4
--- /dev/null
+++ b/comms/tn3270/files/tools/mkastods/mkastods.c
@@ -0,0 +1,77 @@
+/* $NetBSD: mkastods.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $ */
+/* From NetBSD: mkastods.c,v 1.11 2008/07/21 14:19:26 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)mkastods.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mkastods.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "../api/asc_ebc.h"
+#include "../api/ebc_disp.h"
+
+int main(int, char *[]);
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ /* For each ascii code, find the display code that matches */
+
+ printf("unsigned char asc_disp[256] = {");
+ for (i = 0; i < NASCII; i++) {
+ if ((i%8) == 0) {
+ printf("\n");
+ }
+ printf("\t0x%02x,", ebc_disp[asc_ebc[i]]);
+ }
+ for (i = sizeof disp_ebc; i < 256; i++) {
+ if ((i%8) == 0) {
+ printf("\n");
+ }
+ printf("\t0x%02x,", 0);
+ }
+ printf("\n};\n");
+
+ return 0;
+}
diff --git a/comms/tn3270/files/tools/mkastosc/Makefile b/comms/tn3270/files/tools/mkastosc/Makefile
new file mode 100644
index 00000000000..e9a0bad8ec7
--- /dev/null
+++ b/comms/tn3270/files/tools/mkastosc/Makefile
@@ -0,0 +1,12 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+# From NetBSD: Makefile,v 1.10 2002/09/15 01:27:46 thorpej Exp
+
+HOSTPROG= mkastosc
+HOST_CPPFLAGS+= -DHOST_TOOL
+SRCS= mkastosc.c dohits.c asc_ebc.c ebc_disp.c
+
+HOST_CPPFLAGS+=-I${.CURDIR}/../mkhits
+.PATH: ${.CURDIR}/../mkhits
+
+.include <bsd.hostprog.mk>
+
diff --git a/comms/tn3270/files/tools/mkastosc/mkastosc.c b/comms/tn3270/files/tools/mkastosc/mkastosc.c
new file mode 100644
index 00000000000..886fcde300b
--- /dev/null
+++ b/comms/tn3270/files/tools/mkastosc/mkastosc.c
@@ -0,0 +1,165 @@
+/* $NetBSD: mkastosc.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $ */
+/* From NetBSD: mkastosc.c,v 1.12 2008/07/21 14:19:26 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)mkastosc.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mkastosc.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "../general/general.h"
+#include "../ctlr/function.h"
+
+#include "dohits.h"
+
+static struct tbl {
+ unsigned char
+ scancode,
+ used;
+ const char
+ *shiftstate;
+} tbl[128];
+
+
+int main(int, char *[]);
+
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ int scancode;
+ int asciicode;
+ int i;
+ int c;
+ struct hits *ph;
+ struct Hits *Ph;
+ struct thing *this;
+ struct thing **attable;
+ struct tbl *Pt;
+ static const char *shiftof[] =
+ { "0", "SHIFT_UPSHIFT", "SHIFT_ALT", "SHIFT_ALT|SHIFT_UPSHIFT" };
+ char *aidfile = 0, *fcnfile = 0;
+
+ if (argc > 1) {
+ if (argv[1][0] != '-') {
+ aidfile = argv[1];
+ }
+ }
+ if (argc > 2) {
+ if (argv[2][0] != '-') {
+ fcnfile = argv[2];
+ }
+ }
+
+ dohits(aidfile, fcnfile); /* Set up "Hits" */
+
+ printf("/*\n");
+ printf(" * Ascii to scancode conversion table. First\n");
+ printf(" * 128 bytes (0-127) correspond with actual Ascii\n");
+ printf(" * characters; the rest are functions from ctrl/function.h\n");
+ printf(" */\n");
+ /* Build the ascii part of the table. */
+ for (Ph = Hits, scancode = 0; Ph <= Hits+highestof(Hits);
+ Ph++, scancode++) {
+ ph = &Ph->hits;
+ for (i = 0; i < 4; i++) {
+ if (ph->hit[i].ctlrfcn == FCN_CHARACTER) {
+ c = Ph->name[i][0]; /* "name" of this one */
+ if (tbl[c].used == 0) {
+ tbl[c].used = 1;
+ tbl[c].shiftstate = shiftof[i];
+ tbl[c].scancode = scancode;
+ }
+ }
+ }
+ }
+ /* Now, output the table */
+ for (Pt = tbl, asciicode = 0; Pt <= tbl+highestof(tbl); Pt++, asciicode++) {
+ if (Pt->used == 0) {
+ if (isprint(asciicode) && (asciicode != ' ')) {
+ fprintf(stderr, "mkastosc: Unable to produce scancode sequence"
+ " for ASCII character [%c]!", asciicode);
+ }
+ printf("\t{ 0, 0, undefined, 0 },\t");
+ } else {
+ printf("\t{ 0x%02x, %s, FCN_CHARACTER, 0 },",
+ Pt->scancode, Pt->shiftstate);
+ }
+ printf("\t/* 0x%x", asciicode);
+ if (isprint(asciicode)) {
+ printf(" [%c]", asciicode);
+ }
+ printf(" */\n");
+ }
+
+
+ for (attable = &table[0]; attable <= &table[highestof(table)]; attable++) {
+ for (this = *attable; this; this = this->next) {
+ Ph = this->hits;
+ if (Ph == 0) {
+ continue;
+ }
+ for (i = 0; i < 4; i++) {
+ if ((Ph->name[i] != 0) &&
+ (Ph->name[i][0] == this->name[0]) &&
+ (strcmp(Ph->name[i], this->name) == 0)) {
+ printf("\t{ 0x%02lx, %s, ",
+ (u_long)(Ph-Hits), shiftof[i]);
+ if (memcmp("AID_", this->name, 4) == 0) { /* AID key */
+ printf("FCN_AID, ");
+ } else {
+ printf("%s, ", Ph->name[i]);
+ }
+ if (memcmp("PF", this->name+4, 2) == 0) {
+ printf("\"PFK%s\" },\n", Ph->name[i]+4+2);
+ } else {
+ printf("\"%s\" },\n", Ph->name[i]+4);
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/comms/tn3270/files/tools/mkdctype/Makefile b/comms/tn3270/files/tools/mkdctype/Makefile
new file mode 100644
index 00000000000..5cd8ac35dc8
--- /dev/null
+++ b/comms/tn3270/files/tools/mkdctype/Makefile
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $
+# From NetBSD: Makefile,v 1.11 2002/09/15 01:27:46 thorpej Exp
+
+HOSTPROG= mkdctype
+HOST_CPPFLAGS+= -DHOST_TOOL
+SRCS= mkdctype.c asc_ebc.c ebc_disp.c ectype.c
+
+.include <bsd.hostprog.mk>
diff --git a/comms/tn3270/files/tools/mkdctype/ectype.c b/comms/tn3270/files/tools/mkdctype/ectype.c
new file mode 100644
index 00000000000..9e7444bf720
--- /dev/null
+++ b/comms/tn3270/files/tools/mkdctype/ectype.c
@@ -0,0 +1,319 @@
+/* $NetBSD: ectype.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $ */
+/* From NetBSD: ectype.c,v 1.7 2006/03/20 01:34:49 gdamore Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "from: @(#)ectype.c 4.2 (Berkeley) 4/26/91";*/
+#else
+__RCSID("$NetBSD: ectype.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+#include "ectype.h"
+
+unsigned char ectype[ECMAXCHAR] = {
+/* 0x00 */
+ E_SPACE,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0x10 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0x20 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0x30 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0x40 */
+ E_SPACE,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+/* 0x50 */
+ E_PRINT|E_PUNCT,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+/* 0x60 */
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+/* 0x70 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_PUNCT,
+/* 0x80 */
+ 0x00,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0x90 */
+ 0x00,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0xA0 */
+ 0x00,
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ E_PRINT|E_LOWER,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0xB0 */
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0xC0 */
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0xD0 */
+ E_PRINT|E_PUNCT,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0xE0 */
+ E_PRINT|E_PUNCT,
+ 0x00,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ E_PRINT|E_UPPER,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+/* 0xF0 */
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ E_PRINT|E_DIGIT,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00,
+ 0x00
+};
diff --git a/comms/tn3270/files/tools/mkdctype/ectype.h b/comms/tn3270/files/tools/mkdctype/ectype.h
new file mode 100644
index 00000000000..0e8376e0d7b
--- /dev/null
+++ b/comms/tn3270/files/tools/mkdctype/ectype.h
@@ -0,0 +1,54 @@
+/* $NetBSD: ectype.h,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $ */
+/* From NetBSD: ectype.h,v 1.5 2003/08/07 11:16:40 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ectype.h 4.2 (Berkeley) 4/26/91
+ */
+
+#define INCLUDED_ECTYPE
+
+#define E_UPPER 0x01
+#define E_LOWER 0x02
+#define E_DIGIT 0x04
+#define E_SPACE 0x08
+#define E_PUNCT 0x10
+#define E_PRINT 0x20
+
+#define Eisalpha(c) (ectype[(c)&0xff]&(E_UPPER|E_LOWER))
+#define Eisupper(c) (ectype[(c)&0xff]&E_UPPER)
+#define Eislower(c) (ectype[(c)&0xff]&E_LOWER)
+#define Eisdigit(c) (ectype[(c)&0xff]&E_DIGIT)
+#define Eisalnum(c) (ectype[(c)&0xff]&(E_UPPER|E_LOWER|E_DIGIT))
+#define Eisspace(c) (ectype[(c)&0xff]&E_SPACE) /* blank or null */
+#define Eispunct(c) (ectype[(c)&0xff]&E_PUNCT)
+#define Eisprint(c) (ectype[(c)&0xff]&E_PRINT)
+
+#define ECMAXCHAR 256
+extern unsigned char ectype[ECMAXCHAR];
diff --git a/comms/tn3270/files/tools/mkdctype/mkdctype.c b/comms/tn3270/files/tools/mkdctype/mkdctype.c
new file mode 100644
index 00000000000..71527a8384f
--- /dev/null
+++ b/comms/tn3270/files/tools/mkdctype/mkdctype.c
@@ -0,0 +1,105 @@
+/* $NetBSD: mkdctype.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $ */
+/* From NetBSD: mkdctype.c,v 1.10 2008/07/21 14:19:26 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)mkdctype.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mkdctype.c,v 1.1.1.1 2010/01/17 01:33:25 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include "../api/ebc_disp.h"
+#include "ectype.h"
+
+
+int main(int, char *[]);
+
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ static unsigned char dctype[192] = { 0 };
+ int i;
+ char *orbar;
+ int type;
+
+ for (i = 0; i < sizeof ectype; i++) {
+ dctype[ebc_disp[i]] = ectype[i];
+ }
+
+ for (i = 0; i < sizeof dctype; i++) {
+ if ((i%16) == 0) {
+ printf("/*%02x*/\n", i);
+ }
+ printf("\t");
+ type = dctype[i];
+ orbar = "";
+ if (type & E_UPPER) {
+ printf("E_UPPER");
+ orbar = "|";
+ }
+ if (type & E_LOWER) {
+ printf("%sD_LOWER", orbar);
+ orbar = "|";
+ }
+ if (type & E_DIGIT) {
+ printf("%sD_DIGIT", orbar);
+ orbar = "|";
+ }
+ if (type & E_SPACE) {
+ printf("%sD_SPACE", orbar);
+ orbar = "|";
+ }
+ if (type & E_PUNCT) {
+ printf("%sD_PUNCT", orbar);
+ orbar = "|";
+ }
+ if (type & E_PRINT) {
+ printf("%sD_PRINT", orbar);
+ orbar = "|";
+ }
+ if (orbar[0] == 0) {
+ printf("0");
+ }
+ printf(",\n");
+ }
+ return 0;
+}
diff --git a/comms/tn3270/files/tools/mkdstoas/Makefile b/comms/tn3270/files/tools/mkdstoas/Makefile
new file mode 100644
index 00000000000..e3a1a9c7b1d
--- /dev/null
+++ b/comms/tn3270/files/tools/mkdstoas/Makefile
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $
+# From NetBSD: Makefile,v 1.10 2002/09/15 01:27:47 thorpej Exp
+
+HOSTPROG= mkdstoas
+HOST_CPPFLAGS+= -DHOST_TOOL
+SRCS= mkdstoas.c asc_ebc.c ebc_disp.c
+
+.include <bsd.hostprog.mk>
diff --git a/comms/tn3270/files/tools/mkdstoas/mkdstoas.c b/comms/tn3270/files/tools/mkdstoas/mkdstoas.c
new file mode 100644
index 00000000000..8a32c5e22d3
--- /dev/null
+++ b/comms/tn3270/files/tools/mkdstoas/mkdstoas.c
@@ -0,0 +1,77 @@
+/* $NetBSD: mkdstoas.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $ */
+/* From NetBSD: mkdstoas.c,v 1.11 2008/07/21 14:19:26 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)mkdstoas.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mkdstoas.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include "../api/asc_ebc.h"
+#include "../api/ebc_disp.h"
+
+int main(int, char *[]);
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ /* For each display code, find the ascii code that matches */
+
+ printf("unsigned char disp_asc[256] = {");
+ for (i = 0; i < sizeof disp_ebc; i++) {
+ if ((i%8) == 0) {
+ printf("\n");
+ }
+ printf("\t0x%02x,", ebc_asc[disp_ebc[i]]);
+ }
+ for (i = sizeof disp_ebc; i < 256; i++) {
+ if ((i%8) == 0) {
+ printf("\n");
+ }
+ printf("\t0x%02x,", ' ');
+ }
+ printf("\n};\n");
+
+ return 0;
+}
diff --git a/comms/tn3270/files/tools/mkhits/Makefile b/comms/tn3270/files/tools/mkhits/Makefile
new file mode 100644
index 00000000000..6dbfcc791eb
--- /dev/null
+++ b/comms/tn3270/files/tools/mkhits/Makefile
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $
+# From NetBSD: Makefile,v 1.10 2002/09/15 01:27:47 thorpej Exp
+
+HOSTPROG= mkhits
+HOST_CPPFLAGS+= -DHOST_TOOL
+SRCS= mkhits.c dohits.c asc_ebc.c ebc_disp.c
+
+.include <bsd.hostprog.mk>
diff --git a/comms/tn3270/files/tools/mkhits/dohits.c b/comms/tn3270/files/tools/mkhits/dohits.c
new file mode 100644
index 00000000000..df7eeba146d
--- /dev/null
+++ b/comms/tn3270/files/tools/mkhits/dohits.c
@@ -0,0 +1,300 @@
+/* $NetBSD: dohits.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $ */
+/* From NetBSD: dohits.c,v 1.14 2006/04/22 18:02:26 christos Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)dohits.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: dohits.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * This program scans a file which describes a keyboard. The output
+ * of the program is a series of 'C' declarations which describe a
+ * mapping between (scancode, shiftstate, altstate) and 3270 functions,
+ * characters, and AIDs.
+ *
+ * The format of the input file is as follows:
+ *
+ * keynumber [ scancode [ unshifted [ shifted [ alted [ shiftalted ] ] ] ] ]
+ *
+ * keynumber is in decimal, and starts in column 1.
+ * scancode is hexadecimal.
+ * unshifted, etc. - these are either a single ascii character,
+ * or the name of a function or an AID-generating key.
+ *
+ * all fields are separated by a single space.
+ */
+
+#include "../general/general.h"
+#include "../api/asc_ebc.h"
+#include "../api/ebc_disp.h"
+#include "../ctlr/function.h"
+
+#include "dohits.h"
+
+struct Hits Hits[256]; /* one for each of 0x00-0xff */
+
+struct thing *table[100];
+
+static void add(const char *, const char *, int);
+static void scanwhite(const char *, const char *);
+static void scandefine(const char *, const char *);
+static char *savechr(unsigned int);
+static char *doit(struct hit *, unsigned char *, struct Hits *);
+
+unsigned int
+dohash(seed, string)
+unsigned int seed;
+const char *string;
+{
+ unsigned int i = seed;
+ unsigned char c;
+
+ while ((c = *string++) != '\0') {
+ if (c >= 0x60) {
+ c -= (0x60+0x20);
+ } else {
+ c -= 0x20;
+ }
+ i = (i>>26) + (i<<6) + (c&0x3f);
+ }
+ return i;
+}
+
+static void
+add(first, second, value)
+const char *first, *second;
+int value;
+{
+ struct thing **item, *this;
+
+ item = &firstentry(second);
+ this = (struct thing *) malloc(sizeof *this);
+ this->hits = 0;
+ this->next = *item;
+ *item = this;
+ this->value = value;
+ strcpy(this->name, first);
+ strcpy(this->name+strlen(this->name), second);
+}
+
+static void
+scanwhite(file, prefix)
+const char *file, /* Name of file to scan for whitespace prefix */
+ *prefix; /* prefix of what should be picked up */
+{
+ FILE *ourfile;
+ char compare[100];
+ char what[100];
+ char line[200];
+
+ (void) snprintf(compare, sizeof(compare), " %s%%[^,\t \n]", prefix);
+ if ((ourfile = fopen(file, "r")) == NULL) {
+ fprintf(stderr, "Cannot open `%s': %s\n", file, strerror(errno));
+ exit(1);
+ }
+ while (!feof(ourfile)) {
+ if (fscanf(ourfile, compare, what) == 1) {
+ add(prefix, what, 0);
+ }
+ do {
+ if (fgets(line, sizeof line, ourfile) == NULL) {
+ if (!feof(ourfile)) {
+ fprintf(stderr, "fgets failed: %s\n", strerror(errno));
+ }
+ break;
+ }
+ } while (line[strlen(line)-1] != '\n');
+ }
+ (void)fclose(ourfile);
+}
+
+static void
+scandefine(file, prefix)
+const char *file, /* Name of file to scan for #define prefix */
+ *prefix; /* prefix of what should be picked up */
+{
+ FILE *ourfile;
+ char compare[100];
+ char what[100], value[100];
+ char line[200];
+ int whatitis;
+
+ snprintf(compare, sizeof(compare), "#define %s%%s %%s", prefix);
+ if ((ourfile = fopen(file, "r")) == NULL) {
+ fprintf(stderr, "Cannot open `%s': %s\n", file, strerror(errno));
+ exit(1);
+ }
+
+ while (!feof(ourfile)) {
+ if (fscanf(ourfile, compare, what, value) == 2) {
+ if (value[0] == '0') {
+ if ((value[1] == 'x') || (value[1] == 'X')) {
+ sscanf(value, "0x%x", &whatitis);
+ } else {
+ sscanf(value, "0%o", &whatitis);
+ }
+ } else {
+ sscanf(value, "%d", &whatitis);
+ }
+ add(prefix, what, whatitis);
+ }
+ do {
+ if (fgets(line, sizeof line, ourfile) == NULL) {
+ if (!feof(ourfile)) {
+ fprintf(stderr, "End of file with error: %s\n",
+ strerror(errno));
+ }
+ break;
+ }
+ } while (line[strlen(line)-1] != '\n');
+ }
+ (void)fclose(ourfile);
+}
+
+static char *savechr(c)
+unsigned int c;
+{
+ char *foo = malloc(sizeof(unsigned char));
+ if (foo == NULL) {
+ fprintf(stderr, "No room for ascii characters\n");
+ exit(1);
+ }
+ *foo = c;
+ return foo;
+}
+
+static char *
+doit(hit, type, hits)
+struct hit *hit;
+unsigned char *type;
+struct Hits *hits;
+{
+ struct thing *this;
+
+ hit->ctlrfcn = FCN_NULL;
+ if (type[0] == 0) {
+ return 0;
+ }
+ if (type[1] == 0) { /* character */
+ hit->ctlrfcn = FCN_CHARACTER;
+ hit->code = ebc_disp[asc_ebc[type[0]]];
+ return savechr(*type); /* The character is the name */
+ } else {
+ for (this = firstentry(type); this; this = this->next) {
+ if ((type[0] == this->name[4])
+ && (strcmp(type, this->name+4) == 0)) {
+ this->hits = hits;
+ if (this->name[0] == 'F') {
+ hit->ctlrfcn = FCN_NULL; /* XXX */
+ } else {
+ hit->ctlrfcn = FCN_AID;
+ }
+ return this->name;
+ }
+ }
+ fprintf(stderr, "Unknown type %s.\n", type);
+ return 0;
+ }
+}
+
+
+void
+dohits(aidfile, fcnfile)
+const char *aidfile, *fcnfile;
+{
+ unsigned char plain[100], shifted[100], alted[100], shiftalted[100];
+ unsigned char line[200];
+ int keynumber, scancode;
+ struct hit *hit;
+
+ memset((char *)Hits, 0, sizeof Hits);
+
+ /*
+ * First, we read "host3270.h" to find the names/values of
+ * various AID; then we read kbd3270.h to find the names/values
+ * of various FCNs.
+ */
+
+ if (aidfile == 0) {
+ aidfile = "../ctlr/hostctlr.h";
+ }
+ scandefine(aidfile, "AID_");
+ if (fcnfile == 0) {
+ fcnfile = "../ctlr/function.h";
+ }
+ scanwhite(fcnfile, "FCN_");
+
+ while (fgets(line, sizeof(line), stdin) != NULL) {
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = '\0';
+ if (!isdigit(line[0])) {
+ continue;
+ }
+ plain[0] = shifted[0] = alted[0] = shiftalted[0] = 0;
+ keynumber = -1;
+ scancode = -1;
+ (void) sscanf(line, "%d %x %s %s %s %s", &keynumber,
+ &scancode, plain, shifted, alted, shiftalted);
+ if ((keynumber == -1) || (scancode == -1)
+ || ((plain[0] == 0)
+ && (shifted[0] == 0)
+ && (alted[0] == 0)
+ && (shiftalted[0] == 0))) {
+ continue;
+ }
+ if (scancode >= 256) {
+ fprintf(stderr, "Scancode 0x%02x for keynumber %d\n", scancode,
+ keynumber);
+ break;
+ }
+ if (Hits[scancode].hits.hit[0].ctlrfcn != undefined) {
+ fprintf(stderr, "Duplicate scancode 0x%02x for keynumber %d\n",
+ scancode, keynumber);
+ break;
+ }
+ hit = Hits[scancode].hits.hit;
+ Hits[scancode].hits.keynumber = keynumber;
+ Hits[scancode].name[0] = doit(hit, plain, &Hits[scancode]);
+ Hits[scancode].name[1] = doit(hit+1, shifted, &Hits[scancode]);
+ Hits[scancode].name[2] = doit(hit+2, alted, &Hits[scancode]);
+ Hits[scancode].name[3] = doit(hit+3, shiftalted, &Hits[scancode]);
+ }
+}
diff --git a/comms/tn3270/files/tools/mkhits/dohits.h b/comms/tn3270/files/tools/mkhits/dohits.h
new file mode 100644
index 00000000000..df6fa43daad
--- /dev/null
+++ b/comms/tn3270/files/tools/mkhits/dohits.h
@@ -0,0 +1,56 @@
+/* $NetBSD: dohits.h,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $ */
+/* From NetBSD: dohits.h,v 1.7 2003/08/07 11:16:42 agc Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)dohits.h 4.2 (Berkeley) 4/26/91
+ */
+
+#define numberof(x) (sizeof x/sizeof x[0])
+#define highestof(x) (numberof(x)-1)
+
+#define firstentry(x) (table[dohash(0, (x))%highestof(table)])
+
+struct Hits {
+ struct hits hits;
+ char *name[4];
+};
+
+struct thing {
+ struct thing *next;
+ struct Hits *hits;
+ unsigned char value;
+ char name[100];
+};
+
+extern struct Hits Hits[256]; /* one for each of 0x00-0xff */
+extern struct thing *table[100];
+
+void dohits(const char *, const char *);
+unsigned int dohash(unsigned int, const char *);
diff --git a/comms/tn3270/files/tools/mkhits/mkhits.c b/comms/tn3270/files/tools/mkhits/mkhits.c
new file mode 100644
index 00000000000..2b6e9e578e1
--- /dev/null
+++ b/comms/tn3270/files/tools/mkhits/mkhits.c
@@ -0,0 +1,144 @@
+/* $NetBSD: mkhits.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $ */
+/* From NetBSD: mkhits.c,v 1.11 2008/07/21 14:19:27 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)mkhits.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mkhits.c,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $");
+#endif
+#endif /* not lint */
+
+/*
+ * This program scans a file which describes a keyboard. The output
+ * of the program is a series of 'C' declarations which describe a
+ * mapping between (scancode, shiftstate, altstate) and 3270 functions,
+ * characters, and AIDs.
+ *
+ * The format of the input file is as follows:
+ *
+ * keynumber [ scancode [ unshifted [ shifted [ alted [ shiftalted ] ] ] ] ]
+ *
+ * keynumber is in decimal, and starts in column 1.
+ * scancode is hexadecimal.
+ * unshifted, etc. - these are either a single ascii character,
+ * or the name of a function or an AID-generating key.
+ *
+ * all fields are separated by a single space.
+ */
+
+#include "../ctlr/function.h"
+
+#include "dohits.h"
+
+int main(int, char *[]);
+
+int
+main(int argc, char *argv[])
+{
+ int scancode;
+ int empty;
+ int i;
+ struct hits *ph;
+ struct Hits *Ph;
+ char *aidfile = 0, *fcnfile = 0;
+
+ if (argc > 1) {
+ if (argv[1][0] != '-') {
+ aidfile = argv[1];
+ }
+ }
+ if (argc > 2) {
+ if (argv[2][0] != '-') {
+ fcnfile = argv[2];
+ }
+ }
+
+ dohits(aidfile, fcnfile); /* Set up "Hits" */
+
+ printf("struct hits hits[] = {\n");
+ empty = 0;
+ scancode = -1;
+ for (Ph = Hits; Ph < Hits+(sizeof Hits/sizeof Hits[0]); Ph++) {
+ ph = &Ph->hits;
+ scancode++;
+ if ((ph->hit[0].ctlrfcn == undefined)
+ && (ph->hit[1].ctlrfcn == undefined)
+ && (ph->hit[2].ctlrfcn == undefined)
+ && (ph->hit[3].ctlrfcn == undefined)) {
+ empty++;
+ continue;
+ } else {
+ while (empty) {
+ printf("\t{ 0, { {undefined}, {undefined}");
+ printf(", {undefined}, {undefined} } },\n");
+ empty--;
+ }
+ }
+ printf("\t{ %d, {\t/* 0x%02x */\n\t", ph->keynumber, scancode);
+ for (i = 0; i < 4; i++) {
+ printf("\t{ ");
+ switch (ph->hit[i].ctlrfcn) {
+ case undefined:
+ printf("undefined");
+ break;
+ case FCN_CHARACTER:
+ printf("FCN_CHARACTER, 0x%02x", ph->hit[i].code);
+ break;
+ case FCN_AID:
+ printf("FCN_AID, %s", Ph->name[i]);
+ break;
+ case FCN_NULL:
+ default:
+ if ((Ph->name[i] != 0)
+ && (strcmp(Ph->name[i], "FCN_NULL") != 0)) {
+ printf("%s", Ph->name[i]);
+ } else {
+ printf("undefined");
+ }
+ break;
+ }
+ printf(" },\n\t");
+ }
+ printf("} },\n");
+ }
+ printf("};\n");
+ return 0;
+}
diff --git a/comms/tn3270/files/tools/mkmake/Makefile b/comms/tn3270/files/tools/mkmake/Makefile
new file mode 100644
index 00000000000..dbe17f47e3a
--- /dev/null
+++ b/comms/tn3270/files/tools/mkmake/Makefile
@@ -0,0 +1,10 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:26 dholland Exp $
+# From NetBSD: Makefile,v 1.4 2006/03/20 01:34:49 gdamore Exp
+
+HOSTPROG= mkmake
+HOST_CPPFLAGS+= -DHOST_TOOL
+SRCS= mkmake.y
+
+.include <bsd.hostprog.mk>
+
+.PATH: ${.CURDIR}/../../api ${.CURDIR}/../../ascii
diff --git a/comms/tn3270/files/tools/mkmake/mkmake.y b/comms/tn3270/files/tools/mkmake/mkmake.y
new file mode 100644
index 00000000000..8a20263fe36
--- /dev/null
+++ b/comms/tn3270/files/tools/mkmake/mkmake.y
@@ -0,0 +1,1138 @@
+%{
+/* $NetBSD: mkmake.y,v 1.1.1.1 2010/01/17 01:33:27 dholland Exp $ */
+/* From NetBSD: mkmake.y,v 1.14 2009/10/30 15:09:24 uebayasi Exp */
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)mkmake.y 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: mkmake.y,v 1.1.1.1 2010/01/17 01:33:27 dholland Exp $");
+#endif
+#endif /* not lint */
+#endif
+
+typedef struct string {
+ int
+ hashval,
+ length;
+ char
+ *string;
+ struct string
+ *next;
+} string_t;
+
+/*
+ * The deal with these is that they exist on various lists.
+ *
+ * First off, they are on a temporary list during the time they
+ * are in the active focus of the parser.
+ *
+ * Secondly, they live on one of three queues:
+ * 1. Variables
+ * 2. Targets
+ * 3. Actions
+ * (and, we restrict any given one to live on one and only one such list)
+ *
+ * Also, they may live on the list of values for someone else's variable,
+ * or as someone's dependency.
+ */
+
+typedef struct same {
+ string_t
+ *string; /* My name */
+ struct same
+ *nexttoken, /* Next pointer */
+ *lasttoken, /* Back pointer */
+ *depend_list, /* If target, dependancies */
+ *action_list, /* If target, actions */
+ *value_list, /* If variable, value list */
+ *shell_item; /* If a shell variable, current value */
+} same_t;
+
+
+%}
+
+%union {
+ string_t *string;
+ same_t *same;
+ int intval;
+ }
+
+%start makefile
+%token <string> TOKEN QUOTED_STRING
+%token <intval> FOR IN DO DONE
+%token <intval> MACRO_CHAR NL WHITE_SPACE
+%token <intval> ':' '=' '$' '{' '}' ';' '-' '@' '(' ')' ' ' '\t'
+%type <same> target target1 assignment assign1 actions action
+%type <same> command_list list list_element
+%type <same> for_statement maybe_at_minus tokens token
+%type <same> maybe_white_space
+%type <intval> white_space macro_char
+%%
+
+makefile : lines;
+
+lines : line
+ | lines line
+ ;
+
+line : NL
+ | assignment
+ | target_action
+ ;
+
+assignment : assign1 tokens NL
+ {
+ assign($1, $2);
+ }
+ | assign1 NL
+ {
+ assign($1, same_copy(null));
+ }
+ ;
+
+assign1: token maybe_white_space '=' maybe_white_space
+ ;
+
+target_action: target actions
+ {
+ add_targets_actions($1, $2);
+ }
+ | target
+ {
+ add_targets_actions($1, 0);
+ }
+ ;
+
+target : target1 tokens NL
+ {
+ $$ = add_depends($1, $2);
+ }
+ | target1 NL
+ {
+ $$ = add_depends($1, same_copy(null));
+ }
+ ;
+
+target1: tokens maybe_white_space ':' maybe_white_space
+ {
+ $$ = ws_merge($1);
+ }
+ ;
+
+actions: action
+ | actions action
+ {
+ $$ = same_cat(same_cat($1, same_copy(newline)), $2);
+ }
+ ;
+
+action: white_space command_list NL
+ {
+ $$ = $2;
+ }
+ | white_space for_statement do command_list semi_colon done NL
+ {
+ $$ = do_command($2, $4);
+ }
+ ;
+
+for_statement: maybe_at_minus FOR white_space token
+ in tokens semi_colon
+ {
+ $$ = for_statement($1, $4, ws_merge(expand_variables($6, 0)));
+ }
+ ;
+
+in: white_space IN white_space
+do: white_space DO white_space
+ ;
+
+done: white_space DONE
+ ;
+
+semi_colon: ';'
+ ;
+
+command_list: list
+ | '(' list maybe_white_space ')'
+ {
+ $$ = same_cat($2, same_copy(cwd_line));
+ }
+ ;
+
+list: token
+ | list list_element
+ {
+ $$ = same_cat($1, $2);
+ }
+ | list white_space list_element
+ {
+ $$ = same_cat($1, same_cat(same_copy(blank), $3));
+ }
+ ;
+
+list_element: token
+ | semi_colon
+ {
+ $$ = same_copy(newline);
+ }
+ ;
+
+maybe_at_minus: /* empty */
+ {
+ $$ = same_copy(null);
+ }
+ | '@'
+ {
+ char buffer[2];
+
+ buffer[0] = $1;
+ buffer[1] = 0;
+ $$ = same_item(string_lookup(buffer));
+ }
+ | '-'
+ {
+ char buffer[2];
+
+ buffer[0] = $1;
+ buffer[1] = 0;
+ $$ = same_item(string_lookup(buffer));
+ }
+ ;
+
+tokens : token
+ | tokens maybe_white_space token
+ {
+ $$ = same_cat($1, same_cat($2, $3));
+ }
+ ;
+
+token: TOKEN
+ {
+ $$ = same_item($1);
+ }
+ | QUOTED_STRING
+ {
+ $$ = same_item($1);
+ }
+ | '$' macro_char
+ {
+ char buffer[3];
+
+ buffer[0] = '$';
+ buffer[1] = $2;
+ buffer[2] = 0;
+
+ $$ = same_item(string_lookup(buffer));
+ }
+ | '$' '$' TOKEN
+ {
+ $$ = shell_variable(same_item($3));
+ }
+ | MACRO_CHAR
+ {
+ $$ = same_char($1);
+ }
+ | '$' '{' TOKEN '}'
+ {
+ $$ = variable(same_item($3));
+ }
+ | '$' '(' TOKEN ')'
+ {
+ $$ = variable(same_item($3));
+ }
+ | '$' TOKEN
+ {
+ $$ = variable(same_item($2));
+ }
+ | '-'
+ {
+ $$ = same_char('-');
+ }
+ | '@'
+ {
+ $$ = same_char('@');
+ }
+ ;
+
+macro_char: MACRO_CHAR
+ | '@'
+ ;
+
+maybe_white_space:
+ {
+ $$ = same_copy(null);
+ }
+ | white_space
+ {
+ $$ = same_char($1);
+ }
+ ;
+
+white_space : WHITE_SPACE
+ | white_space WHITE_SPACE
+ ;
+%%
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+/* mkmake.y */
+void yyerror(char *);
+void assign(same_t *, same_t *);
+int yylex(void);
+extern int yyparse(void);
+int main(int, char *[]);
+
+static int visitcheck(same_t *);
+static int string_hashof(char *, int);
+static int string_same(string_t *, string_t *);
+static string_t *string_lookup(char *);
+static same_t *same_search(same_t *, same_t *);
+static same_t *same_cat(same_t *, same_t *);
+static same_t *same_item(string_t *);
+static same_t *same_copy(same_t *);
+static same_t *same_merge(same_t *, same_t *);
+static void same_free(same_t *);
+static same_t *same_unlink(same_t *);
+static void same_replace(same_t *, same_t *);
+static same_t *same_char(int);
+static void add_target(same_t *, same_t *);
+static same_t *add_targets_actions(same_t *, same_t *);
+static same_t *add_depends(same_t *, same_t *);
+static same_t *value_of(same_t *);
+static same_t *expand_variables(same_t *, int);
+static same_t *ws_merge(same_t *);
+static same_t *variable(same_t *);
+static same_t *shell_variable(same_t *);
+static same_t *for_statement(same_t *, same_t *, same_t *);
+static same_t *do_command(same_t *, same_t *);
+static int Getchar(void);
+static int token_type(char *);
+#if 0
+static void dump_same(same_t *);
+#endif
+static void do_dump(void);
+static int last_char, last_saved = 0;
+static int column = 0, lineno = 1;
+
+
+static string_t
+ *strings = 0;
+
+static same_t
+ *variables = 0,
+ *targets = 0;
+
+static same_t
+ *null,
+ *blank,
+ *cwd_line,
+ *newline;
+
+static unsigned int
+ clock = -1;
+
+struct {
+ same_t *first;
+ int next;
+} visit_stack[20]; /* 20 maximum */
+
+#define visit(what,via) \
+ (visit_stack[++clock].next = 0, visit_stack[clock].first = via = what)
+#define visited(via) (visitcheck(via) || ((via) == 0) \
+ || (visit_stack[clock].next && (via == visit_stack[clock].first)))
+#define visit_next(via) (visit_stack[clock].next = 1, (via) = (via)->nexttoken)
+#define visit_end() (clock--)
+
+void
+yyerror(s)
+char *s;
+{
+ fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s);
+ do_dump();
+}
+
+static int
+visitcheck(same)
+same_t *same;
+{
+ if (same->string == 0) {
+ yyerror("BUG - freed 'same' in use...");
+ exit(1);
+ }
+ return 0;
+}
+
+static int
+string_hashof(string, length)
+char *string;
+int length;
+{
+ register int i = 0;
+
+ while (length--) {
+ i = ((i<<3) + *string) ^ ((i>>28)&0x7);
+ }
+ return i;
+}
+
+static int
+string_same(s1, s2)
+string_t
+ *s1, *s2;
+{
+ if ((s1->hashval == s2->hashval) && (s1->length == s2->length)
+ && (memcmp(s1->string, s2->string, s1->length) == 0)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static string_t *
+string_lookup(string)
+char *string;
+{
+ string_t ours;
+ string_t *ptr;
+
+ ours.length = strlen(string);
+ ours.hashval = string_hashof(string, ours.length);
+ ours.string = string;
+
+ for (ptr = strings; ptr; ptr = ptr->next) {
+ if (string_same(&ours, ptr)) {
+ return ptr;
+ }
+ }
+ if ((ptr = (string_t *)malloc(sizeof *ptr)) == 0) {
+ fprintf(stderr, "No space to add string *%s*!\n", string);
+ exit(1);
+ }
+ ptr->hashval = ours.hashval;
+ ptr->length = ours.length;
+ if ((ptr->string = malloc(ours.length+1)) == 0) {
+ fprintf(stderr, "No space to add literal *%s*!\n", string);
+ exit(1);
+ }
+ memcpy(ptr->string, string, ours.length+1);
+ ptr->next = strings;
+ strings = ptr;
+ return ptr;
+}
+
+#define same_singleton(s) ((s)->nexttoken == (s))
+
+static same_t *
+same_search(list, token)
+same_t
+ *list,
+ *token;
+{
+ same_t *ptr;
+
+ ptr = list;
+ for (visit(list, ptr); !visited(ptr); visit_next(ptr)) {
+ string_t *string;
+
+ string = ptr->string;
+ if (string_same(string, token->string)) {
+ visit_end();
+ return ptr;
+ }
+ }
+ visit_end();
+ return 0;
+}
+
+static same_t *
+same_cat(list, tokens)
+same_t
+ *list,
+ *tokens;
+{
+ same_t *last;
+
+ if (tokens == 0) {
+ return list;
+ }
+ if (list) {
+ last = tokens->lasttoken;
+ tokens->lasttoken = list->lasttoken;
+ list->lasttoken = last;
+ tokens->lasttoken->nexttoken = tokens;
+ last->nexttoken = list;
+ return list;
+ } else {
+ return tokens;
+ }
+}
+
+static same_t *
+same_item(string)
+string_t *string;
+{
+ same_t *ptr;
+
+ if ((ptr = (same_t *)malloc(sizeof *ptr)) == 0) {
+ fprintf(stderr, "No more space for tokens!\n");
+ exit(1);
+ }
+ memset((char *)ptr, 0, sizeof *ptr);
+ ptr->nexttoken = ptr->lasttoken = ptr;
+ ptr->string = string;
+ return ptr;
+}
+
+static same_t *
+same_copy(same)
+same_t *same;
+{
+ same_t *head, *copy;
+
+ head = 0;
+ for (visit(same, copy); !visited(copy); visit_next(copy)) {
+ same_t *ptr;
+
+ ptr = same_item(copy->string);
+ head = same_cat(head, ptr);
+ }
+ visit_end();
+ return head;
+}
+
+
+static same_t *
+same_merge(t1, t2)
+same_t
+ *t1,
+ *t2;
+{
+ if (same_singleton(t1) && same_singleton(t2)) {
+ int length = strlen(t1->string->string)+strlen(t2->string->string);
+ char *buffer = malloc(length+1);
+ same_t *value;
+
+ if (buffer == 0) {
+ yyerror("No space to merge strings in same_merge!");
+ exit(1);
+ }
+ strcpy(buffer, t1->string->string);
+ strcat(buffer, t2->string->string);
+ value = same_item(string_lookup(buffer));
+ free(buffer);
+ return value;
+ } else {
+ yyerror("Internal error - same_merge with non-singletons");
+ exit(1);
+ }
+}
+
+
+static void
+same_free(list)
+same_t *list;
+{
+ same_t *token, *ptr;
+
+ if (list == 0) {
+ return;
+ }
+
+ token = list;
+ do {
+ ptr = token->nexttoken;
+ token->string = 0;
+ (void) free((char *)token);
+ token = ptr;
+ } while (token != list);
+}
+
+static same_t *
+same_unlink(token)
+same_t
+ *token;
+{
+ same_t *tmp;
+
+ if (token == 0) {
+ return 0;
+ }
+ if ((tmp = token->nexttoken) == token) {
+ tmp = 0;
+ }
+ token->lasttoken->nexttoken = token->nexttoken;
+ token->nexttoken->lasttoken = token->lasttoken;
+ token->nexttoken = token->lasttoken = token;
+ return tmp;
+}
+
+static void
+same_replace(old, new)
+same_t
+ *old,
+ *new;
+{
+ new->lasttoken->nexttoken = old->nexttoken;
+ old->nexttoken->lasttoken = new->lasttoken;
+ new->lasttoken = old->lasttoken;
+ /* rather than
+ * old->lasttoken->nexttoken = new
+ * we update in place (for the case where there isn't anything else)
+ */
+ *old = *new;
+}
+
+
+static same_t *
+same_char(ch)
+char ch;
+{
+ char buffer[2];
+
+ buffer[0] = ch;
+ buffer[1] = 0;
+
+ return same_item(string_lookup(buffer));
+}
+
+
+static void
+add_target(target, actions)
+same_t
+ *target,
+ *actions;
+{
+ same_t *ptr;
+
+ if ((ptr = same_search(targets, target)) == 0) {
+ targets = same_cat(targets, target);
+ ptr = target;
+ } else {
+ ptr->depend_list = same_cat(ptr->depend_list, target->depend_list);
+ }
+ if (actions) {
+ if (ptr->action_list) {
+ same_free(ptr->action_list);
+ }
+ ptr->action_list = same_copy(actions);
+ }
+}
+
+
+static same_t *
+add_targets_actions(target, actions)
+same_t
+ *target,
+ *actions;
+{
+ same_t *ptr;
+
+ if (target == 0) {
+ return 0;
+ }
+ do {
+ ptr = same_unlink(target);
+ add_target(target, actions);
+ target = ptr;
+ } while (target);
+
+ same_free(actions);
+ return 0;
+}
+
+static same_t *
+add_depends(target, depends)
+same_t
+ *target,
+ *depends;
+{
+ same_t *original = target;
+
+ depends = same_cat(depends, same_copy(blank)); /* Separator */
+
+ for (visit(original, target); !visited(target); visit_next(target)) {
+ target->depend_list = same_cat(target->depend_list, same_copy(depends));
+ }
+ visit_end();
+ same_free(depends);
+
+ return original;
+}
+
+
+/*
+ * We know that variable is a singleton
+ */
+
+void
+assign(variable, value)
+same_t
+ *variable,
+ *value;
+{
+ same_t *ptr;
+
+ if ((ptr = same_search(variables, variable)) != 0) {
+ same_free(ptr->value_list);
+ variables = same_unlink(ptr);
+ same_free(ptr);
+ }
+ variable->value_list = value;
+ variables = same_cat(variables, variable);
+}
+
+static same_t *
+value_of(variable)
+same_t *variable;
+{
+ same_t *ptr = same_search(variables, variable);
+
+ if (ptr == 0) {
+ return same_copy(null);
+ } else {
+ return same_copy(ptr->value_list);
+ }
+}
+
+
+static same_t *
+expand_variables(token, free)
+same_t *token;
+int free;
+{
+ same_t *head = 0;
+
+ if (!free) {
+ token = same_copy(token); /* Get our private copy */
+ }
+
+ while (token) {
+ char *string = token->string->string;
+ same_t *tmp = same_unlink(token);
+
+ if ((string[0] == '$') && (string[1] == '{')) { /* Expand time */
+ int len = strlen(string);
+
+ string[len-1] = 0;
+ head = same_cat(head, expand_variables(
+ value_of(same_item(string_lookup(string+2))), 1));
+ string[len-1] = '}';
+ } else {
+ head = same_cat(head, token);
+ }
+ token = tmp;
+ }
+ return head;
+}
+
+
+static same_t *
+ws_merge(list)
+same_t *list;
+{
+ same_t *newlist = 0, *item = NULL;
+ int what = 0;
+
+ while (list) {
+ switch (what) {
+ case 0:
+ if (isspace(list->string->string[0])) {
+ ;
+ } else {
+ item = same_item(list->string);
+ what = 1;
+ }
+ break;
+ case 1:
+ if (isspace(list->string->string[0])) {
+ newlist = same_cat(newlist, item);
+ item = 0;
+ what = 0;
+ } else {
+ item = same_merge(item, same_item(list->string));
+ what = 1;
+ }
+ break;
+ }
+ list = same_unlink(list);
+ }
+ return same_cat(newlist, item);
+}
+
+
+static same_t *
+variable(var_name)
+same_t *var_name;
+{
+ int length = strlen(var_name->string->string);
+ same_t *resolved;
+ char *newname;
+
+ if ((newname = malloc(length+1+3)) == 0) {
+ fprintf(stderr, "Out of space for a variable name.\n");
+ exit(1);
+ }
+ newname[0] = '$';
+ newname[1] = '{';
+ strcpy(newname+2, var_name->string->string);
+ strcat(newname, "}");
+ resolved = same_item(string_lookup(newname));
+ free(newname);
+
+ return resolved;
+}
+
+
+static same_t *
+shell_variable(var_name)
+same_t *var_name;
+{
+ int length = strlen(var_name->string->string);
+ same_t *resolved;
+ char *newname;
+
+ if ((newname = malloc(length+1+2)) == 0) {
+ fprintf(stderr, "Out of space for a variable name.\n");
+ exit(1);
+ }
+ newname[0] = '$';
+ newname[1] = '$';
+ strcpy(newname+2, var_name->string->string);
+ resolved = same_item(string_lookup(newname));
+ free(newname);
+
+ return resolved;
+}
+
+static same_t *
+for_statement(special, variable, list)
+same_t
+ *special,
+ *variable,
+ *list;
+{
+ variable->shell_item = special;
+ variable->value_list = list;
+ return variable;
+}
+
+static same_t *
+do_command(forlist, commands)
+same_t
+ *forlist,
+ *commands;
+{
+ same_t
+ *special,
+ *command_list = 0,
+ *new_commands,
+ *tmp,
+ *shell_item,
+ *value_list = forlist->value_list;
+ char
+ *tmpstr,
+ *variable_name = forlist->string->string;
+
+ special = forlist->shell_item;
+ if (same_unlink(forlist->shell_item) != 0) {
+ yyerror("Unexpected second item in special part of do_command");
+ exit(1);
+ }
+
+ while ((shell_item = value_list) != 0) {
+ value_list = same_unlink(shell_item);
+ /* Visit each item in commands. For each shell variable which
+ * matches ours, replace it with ours.
+ */
+ new_commands = same_copy(commands);
+ for (visit(new_commands, tmp); !visited(tmp); visit_next(tmp)) {
+ tmpstr = tmp->string->string;
+ if ((tmpstr[0] == '$') && (tmpstr[1] == '$')) {
+ if (strcmp(tmpstr+2, variable_name) == 0) {
+ same_replace(tmp, same_copy(shell_item));
+ }
+ }
+ }
+ visit_end();
+ command_list = same_cat(command_list, new_commands);
+ }
+ return same_cat(command_list, same_copy(newline));
+}
+
+
+static int
+Getchar()
+{
+ if (last_saved) {
+ last_saved = 0;
+ return last_char;
+ } else {
+ int c;
+ c = getchar();
+ switch (c) {
+ case '\n':
+ lineno++;
+ column = 0;
+ break;
+ default:
+ column++;
+ }
+ return c;
+ }
+}
+
+
+static int
+token_type(string)
+char *string;
+{
+ switch (string[0]) {
+ case 'f':
+ if (strcmp(string, "for") == 0) {
+ return FOR;
+ }
+ break;
+ case 'd':
+ if (string[1] == 'o') {
+ if (strcmp(string, "do") == 0) {
+ return DO;
+ } else if (strcmp(string, "done") == 0) {
+ return DONE;
+ }
+ }
+ break;
+ case 'i':
+ if (strcmp(string, "in") == 0) {
+ return IN;
+ }
+ break;
+ default:
+ break;
+ }
+ return TOKEN;
+}
+
+
+int
+yylex()
+{
+#define ret_token(c) if (bufptr != buffer) { \
+ save(c); \
+ *bufptr = 0; \
+ bufptr = buffer; \
+ yylval.string = string_lookup(buffer); \
+ return token_type(buffer); \
+ }
+#define save(c) { last_char = c; last_saved = 1; }
+#if defined(YYDEBUG)
+#define Return(y,c) if (yydebug) { \
+ printf("[%d]", c); \
+ fflush(stdout); \
+ } \
+ yylval.intval = c; \
+ return y;
+#else /* defined(YYDEBUG) */
+#define Return(y,c) { yylval.intval = c; return y; }
+#endif /* defined(YYDEBUG) */
+
+
+ static char buffer[500], *bufptr = buffer;
+ static int eof_found = 0;
+ int c;
+
+ if (eof_found != 0) {
+ eof_found++;
+ if (eof_found > 2) {
+ fprintf(stderr, "End of file ignored.\n");
+ exit(1);
+ }
+ Return(EOF,0);
+ }
+ while ((c = Getchar()) != EOF) {
+ switch (c) {
+ case '#':
+ ret_token(c);
+ while (((c = Getchar()) != EOF) && (c != '\n')) {
+ ;
+ }
+ save(c);
+ break;
+ case '<':
+ case '?':
+ ret_token(c);
+ Return(MACRO_CHAR, c);
+ case '\t':
+ case ' ':
+ ret_token(c);
+ Return(WHITE_SPACE, c);
+ case '-':
+ case '@':
+ case ':':
+ case ';':
+ case '=':
+ case '$':
+ case '{':
+ case '}':
+ case '(':
+ case ')':
+ ret_token(c);
+ Return(c,c);
+ case '\'':
+ case '"':
+ if (bufptr != buffer) {
+ if (bufptr[-1] == '\\') {
+ bufptr[-1] = c;
+ }
+ break;
+ } else {
+ int newc;
+
+ ret_token(c);
+ *bufptr++ = c;
+ while (((newc = Getchar()) != EOF) && (newc != c)) {
+ *bufptr++ = newc;
+ }
+ *bufptr++ = c;
+ *bufptr = 0;
+ bufptr = buffer;
+ yylval.string = string_lookup(buffer);
+ return QUOTED_STRING;
+ }
+ case '\n':
+ if (bufptr != buffer) {
+ if (bufptr[-1] == '\\') {
+ bufptr--;
+ if ((c = Getchar()) != '\t') {
+ yyerror("continuation line doesn't begin with a tab");
+ save(c);
+ }
+ ret_token(c);
+ Return(WHITE_SPACE, c);
+ }
+ }
+ ret_token(c);
+ Return(NL, 0);
+ default:
+ *bufptr++ = c;
+ break;
+ }
+ }
+
+ eof_found = 1;
+
+ ret_token(' ');
+ Return(EOF, 0);
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ null = same_item(string_lookup(""));
+ newline = same_item(string_lookup("\n"));
+ blank = same_item(string_lookup(" "));
+ cwd_line = same_cat(same_copy(newline),
+ same_cat(same_item(string_lookup("cd ${CWD}")),
+ same_copy(newline)));
+
+ yyparse();
+
+ do_dump();
+
+ return 0;
+}
+
+#if 0
+static void
+dump_same(same)
+same_t *same;
+{
+ same_t *same2;
+
+ for (visit(same, same2); !visited(same2); visit_next(same2)) {
+ printf("%s", same2->string->string);
+ }
+ visit_end();
+}
+#endif
+
+static void
+do_dump()
+{
+ string_t *string;
+ same_t *same, *same2;
+
+ if (yydebug > 1) {
+ printf("strings...\n");
+ for (string = strings; string; string = string->next) {
+ printf("\t%s\n", string->string);
+ }
+ }
+
+ printf("# variables...\n");
+ for (visit(variables, same); !visited(same); visit_next(same)) {
+ printf("%s =\t", same->string->string);
+ for (visit(same->value_list, same2); !visited(same2);
+ visit_next(same2)) {
+ printf("%s", same2->string->string);
+ }
+ visit_end();
+ printf("\n");
+ }
+ visit_end();
+
+ printf("\n\n#targets...\n");
+ for (visit(targets, same); !visited(same); visit_next(same)) {
+ printf("\n%s:\t", same->string->string);
+ for (visit(same->depend_list, same2); !visited(same2);
+ visit_next(same2)) {
+ printf("%s", same2->string->string);
+ }
+ visit_end();
+ printf("\n\t");
+ for (visit(same->action_list, same2); !visited(same2);
+ visit_next(same2)) {
+ printf("%s", same2->string->string);
+ if (same2->string->string[0] == '\n') {
+ printf("\t");
+ }
+ }
+ visit_end();
+ printf("\n");
+ }
+ visit_end();
+}
diff --git a/comms/tn3270/files/tools/prt3270/Makefile b/comms/tn3270/files/tools/prt3270/Makefile
new file mode 100644
index 00000000000..800a5c59724
--- /dev/null
+++ b/comms/tn3270/files/tools/prt3270/Makefile
@@ -0,0 +1,47 @@
+# $NetBSD: Makefile,v 1.1.1.1 2010/01/17 01:33:27 dholland Exp $
+# From NetBSD: Makefile,v 1.11 2006/03/20 01:34:49 gdamore Exp
+
+NOMAN= # defined
+
+.include <bsd.own.mk>
+
+HOSTPROG= prt3270
+SRCS= prt3270.c asc_ebc.c ebc_disp.c astosc.c
+DPSRCS= kbd.out astosc.out
+HOST_CPPFLAGS+=-I. -DHOST_TOOL
+
+MKHITSDIR!=cd $(.CURDIR)/../mkhits && ${PRINTOBJDIR}
+MKHITS=${MKHITSDIR}/mkhits
+
+${MKHITS}:
+ cd ${.CURDIR}/../mkhits; ${MAKE}
+
+kbd.out: ${.CURDIR}/../../ctlr/hostctlr.h ${.CURDIR}/../../ctlr/${KBD} ${MKHITS}
+ ${HOST_CC} ${HOST_CPPFLAGS} -E ${.CURDIR}/../../ctlr/function.c > TMPfunc.out
+ ${MKHITS} \
+ ${.CURDIR}/../../ctlr/hostctlr.h TMPfunc.out \
+ < ${.CURDIR}/../../ctlr/${KBD} > kbd.tmp
+ rm -f TMPfunc.out
+ mv -f kbd.tmp ${.TARGET}
+CLEANFILES+= TMPfunc.out kbd.tmp kbd.out
+
+MKASTOSCDIR!=cd ${.CURDIR}/../mkastosc && ${PRINTOBJDIR}
+MKASTOSC= ${MKASTOSCDIR}/mkastosc
+
+${MKASTOSC}:
+ cd ${.CURDIR}/../mkastosc; ${MAKE}
+
+astosc.out: ${.CURDIR}/../../ctlr/hostctlr.h ${.CURDIR}/../../ctlr/function.h \
+ ${.CURDIR}/../../ctlr/${KBD} ${MKASTOSC}
+ ${MKASTOSC} \
+ ${.CURDIR}/../../ctlr/hostctlr.h ${.CURDIR}/../../ctlr/function.h \
+ < ${.CURDIR}/../../ctlr/${KBD} > astosc.tmp
+ mv -f astosc.tmp ${.TARGET}
+CLEANFILES+= astosc.tmp astosc.out
+
+.include <bsd.hostprog.mk>
+
+.PATH: ${.CURDIR}/../../api ${.CURDIR}/../../ascii
+
+astosc.o: astosc.out
+prt3270.o: kbd.out
diff --git a/comms/tn3270/files/tools/prt3270/prt3270.c b/comms/tn3270/files/tools/prt3270/prt3270.c
new file mode 100644
index 00000000000..1cdb349232e
--- /dev/null
+++ b/comms/tn3270/files/tools/prt3270/prt3270.c
@@ -0,0 +1,647 @@
+/* $NetBSD: prt3270.c,v 1.1.1.1 2010/01/17 01:33:27 dholland Exp $ */
+/* From NetBSD: prt3270.c,v 1.11 2008/07/21 14:19:27 lukem Exp */
+
+/*-
+ * Copyright (c) 1988 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef HOST_TOOL
+#include <sys/cdefs.h>
+#if defined(__COPYRIGHT) && !defined(lint)
+__COPYRIGHT("@(#) Copyright (c) 1988\
+ The Regents of the University of California. All rights reserved.");
+#endif /* not lint */
+#endif
+
+#if defined(__RCSID) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)prt3270.c 4.2 (Berkeley) 4/26/91";
+#else
+__RCSID("$NetBSD: prt3270.c,v 1.1.1.1 2010/01/17 01:33:27 dholland Exp $");
+#endif
+#endif /* not lint */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+#define DEFINING_INSTANCES
+#include "../general/general.h"
+
+#include "../api/asc_ebc.h"
+#include "../ctlr/hostctlr.h"
+#include "../ctlr/screen.h"
+#include "../ctlr/function.h"
+#include "../api/astosc.h"
+#include "../general/globals.h"
+
+#include "kbd.out"
+
+
+int NumberColumns = 80;
+
+int direction;
+
+int column = 1;
+int indenting = 0;
+int direction = '?';
+
+unsigned char printBuffer[200], *print = printBuffer;
+
+#define ColsLeft() (79-column) /* A little room for error */
+
+
+/* prt3270.c */
+void putSpace(void);
+void Column1(void);
+void Indent(void);
+void Undent(void);
+void putChar(int);
+void putstr(char *);
+void put2hex(int);
+void putdecimal(int);
+void puthex(int);
+void putEChar(int);
+void PrintAid(int);
+void PrintAddr(int);
+int DataFromNetwork(unsigned char *, int, int);
+int DataToNetwork(unsigned char *, int, int);
+int GetXValue(int);
+void termblock(int, int , int);
+int main(int, char *[]);
+
+void
+putSpace()
+{
+ unsigned char *ourPrint = print;
+
+ print = printBuffer; /* For mutual calls */
+ *ourPrint = 0;
+ if (ColsLeft() < 0) {
+ Column1();
+ }
+ if (column != (indenting*8+1)) {
+ putchar(' ');
+ } else {
+ int i;
+
+ putchar(direction);
+ putchar(' ');
+ for (i = 0; i < indenting; i++) {
+ putchar('\t');
+ }
+ }
+ printf("%s", printBuffer);
+ column += strlen(printBuffer);
+}
+
+void
+Column1()
+{
+ if (print != printBuffer) {
+ putSpace();
+ }
+ if (column != (indenting*8+1)) {
+ putchar('\n');
+ column = indenting*8+1;
+ }
+}
+
+void
+Indent()
+{
+ if ((column != (indenting*8+1)) || (print != printBuffer)) {
+ Column1();
+ }
+ indenting++;
+ column = indenting*8+1;
+}
+
+void
+Undent()
+{
+ if ((column != (indenting*8+1)) || (print != printBuffer)) {
+ Column1();
+ }
+ indenting--;
+ if (indenting < 0) {
+ fflush(stdout);
+ fprintf(stderr, "INTERNAL ERROR: indenting < 0.\n");
+ fflush(stderr);
+ } else {
+ column = indenting*8+1;
+ }
+}
+
+void
+putChar(character)
+int character;
+{
+ *print++ = character;
+ column++;
+}
+
+void
+putstr(s)
+char *s;
+{
+ while (*s) {
+ putChar(*s++);
+ }
+}
+
+void
+put2hex(i)
+int i;
+{
+ char place[40];
+
+ sprintf(place, "%02x", i);
+ putstr(place);
+}
+
+
+void
+putdecimal(i)
+int i;
+{
+ char place[40];
+
+ sprintf(place, "%d", i);
+ putstr(place);
+}
+
+void
+puthex(i)
+int i;
+{
+ char place[40];
+
+ sprintf(place, "%x", i);
+ putstr(place);
+}
+
+void
+putEChar(character)
+int character;
+{
+ putChar(ebc_asc[character]);
+ if (ColsLeft() < 10) {
+ Column1();
+ }
+}
+
+void
+PrintAid(i)
+int i;
+{
+ struct astosc *this;
+
+ for (this = &astosc[0]; this <= &astosc[highestof(astosc)]; this++) {
+ if (this->function == FCN_AID) {
+ int j;
+
+ switch (this->shiftstate) {
+ case 0:
+ j = 0;
+ break;
+ case SHIFT_UPSHIFT:
+ j = 1;
+ break;
+ case SHIFT_ALT:
+ j = 2;
+ break;
+ case (SHIFT_UPSHIFT|SHIFT_ALT):
+ j = 3;
+ break;
+ default:
+ fprintf(stderr, "Bad shiftstate 0x%x.\n", this->shiftstate);
+ exit(1);
+ }
+ if (hits[this->scancode].hit[j].code == i) {
+ putstr(this->name);
+ return;
+ }
+ }
+ }
+
+ putstr("Unknown AID 0x");
+ put2hex(i);
+}
+
+void
+PrintAddr(i)
+int i;
+{
+ if (ColsLeft() < 9) {
+ Column1();
+ }
+ putChar('(');
+ putdecimal(ScreenLine(i));
+ putChar(',');
+ putdecimal(ScreenLineOffset(i));
+ putChar(')');
+}
+
+
+/* returns the number of characters consumed */
+int
+DataFromNetwork(buffer, count, control)
+unsigned char *buffer; /* what the data is */
+int count; /* and how much there is */
+int control; /* this buffer ended block? */
+{
+ int origCount;
+ int c;
+ int i;
+ static int Command;
+ static int Wcc;
+ static int LastWasTerminated = 1; /* was "control" = 1 last time? */
+
+ if (count == 0) {
+ Column1();
+ return 0;
+ }
+
+ origCount = count;
+
+ if (LastWasTerminated) {
+
+ if (count < 2) {
+ if (count == 0) {
+ fflush(stdout);
+ fprintf(stderr, "Short count received from host!\n");
+ fflush(stderr);
+ return(count);
+ }
+ Command = buffer[0];
+ switch (Command) { /* This had better be a read command */
+ case CMD_READ_MODIFIED:
+ putstr("read_modified command\n");
+ break;
+ case CMD_SNA_READ_MODIFIED:
+ putstr("sna_read_modified command\n");
+ break;
+ case CMD_SNA_READ_MODIFIED_ALL:
+ putstr("sna_read_modified_all command\n");
+ break;
+ case CMD_READ_BUFFER:
+ putstr("read_buffer command\n");
+ break;
+ case CMD_SNA_READ_BUFFER:
+ putstr("sna_read_buffer command\n");
+ break;
+ default:
+ break;
+ }
+ return(1); /* We consumed everything */
+ }
+ Command = buffer[0];
+ Wcc = buffer[1];
+ switch (Command) {
+ case CMD_ERASE_WRITE:
+ putstr("erase write command ");
+ break;
+ case CMD_ERASE_WRITE_ALTERNATE:
+ putstr("erase write alternate command ");
+ break;
+ case CMD_SNA_ERASE_WRITE:
+ putstr("sna erase write command ");
+ break;
+ case CMD_SNA_ERASE_WRITE_ALTERNATE:
+ putstr("erase write alternate command ");
+ break;
+ case CMD_ERASE_ALL_UNPROTECTED:
+ putstr("erase all unprotected command ");
+ break;
+ case CMD_SNA_ERASE_ALL_UNPROTECTED:
+ putstr("sna erase write command ");
+ break;
+ case CMD_WRITE:
+ putstr("write command ");
+ break;
+ case CMD_SNA_WRITE:
+ putstr("sna write command ");
+ break;
+ default:
+ putstr("Unexpected command code 0x");
+ puthex(Command);
+ putstr(" received.");
+ Column1();
+ break;
+ }
+ putstr("WCC is 0x");
+ puthex(Wcc);
+ Column1();
+
+ count -= 2; /* strip off command and wcc */
+ buffer += 2;
+
+ }
+ LastWasTerminated = 0; /* then, reset at end... */
+
+ while (count) {
+ count--;
+ c = *buffer++;
+ if (IsOrder(c)) {
+ /* handle an order */
+ switch (c) {
+# define Ensure(x) if (count < x) { \
+ if (!control) { \
+ return(origCount-(count+1)); \
+ } else { \
+ /* XXX - should not occur */ \
+ count = 0; \
+ break; \
+ } \
+ }
+ case ORDER_SF:
+ Ensure(1);
+ c = *buffer++;
+ count--;
+ putstr("SF (0x");
+ put2hex(c);
+ putstr(") ");
+ break;
+ case ORDER_SBA:
+ Ensure(2);
+ i = buffer[0];
+ c = buffer[1];
+ buffer += 2;
+ count -= 2;
+ putstr("SBA to ");
+ PrintAddr(Addr3270(i,c));
+ putSpace();
+ break;
+ case ORDER_IC:
+ putstr("IC");
+ putSpace();
+ break;
+ case ORDER_PT:
+ putstr("PT");
+ putSpace();
+ break;
+ case ORDER_RA:
+ Ensure(3);
+ i = Addr3270(buffer[0], buffer[1]);
+ c = buffer[2];
+ buffer += 3;
+ count -= 3;
+ putstr("RA to ");
+ PrintAddr(i);
+ putstr(" of 0x");
+ put2hex(c);
+ putSpace();
+ break;
+ case ORDER_EUA: /* (from [here,there), ie: half open interval] */
+ Ensure(2);
+ putstr("EUA to ");
+ PrintAddr(Addr3270(buffer[0], buffer[1]));
+ putSpace();
+ buffer += 2;
+ count -= 2;
+ break;
+ case ORDER_YALE: /* special YALE defined order */
+ Ensure(2); /* need at least two characters */
+ putstr("YALE order");
+ putSpace();
+ break;
+ default:
+ putstr("UNKNOWN ORDER: 0x");
+ put2hex(c);
+ putSpace();
+ break;
+ }
+ if (count < 0) {
+ count = 0;
+ }
+ } else {
+ /* Data comes in large clumps - take it all */
+ putstr("DATA:");
+ Indent();
+ putEChar(c);
+ c = *buffer;
+ while (count && !IsOrder(c)) {
+ putEChar(c);
+ count--;
+ buffer++;
+ c = *buffer;
+ }
+ Undent();
+ }
+ }
+ LastWasTerminated = control;
+ return origCount - count;
+}
+
+int
+DataToNetwork(buffer, count, control)
+unsigned char *buffer;
+int count;
+int control;
+{
+#define NEED_AID 0
+#define JUST_GOT_AID 1
+#define DATA 2
+#define DATA_CONTINUE 3
+ static int state = NEED_AID;
+ static int aid;
+ int origCount = count;
+
+ if (count == 0) {
+ if (control) {
+ state = NEED_AID;
+ }
+ Column1();
+ return 0;
+ }
+
+ switch (state) {
+ case NEED_AID:
+ aid = buffer[0];
+ buffer++;
+ count--;
+ PrintAid(aid);
+ putSpace();
+ if (aid == AID_TREQ) {
+ state = DATA;
+ } else {
+ state = JUST_GOT_AID;
+ }
+ return origCount - count + DataToNetwork(buffer, count, control);
+ case JUST_GOT_AID:
+ Ensure(2);
+ PrintAddr(Addr3270(buffer[0], buffer[1]));
+ putSpace();
+ buffer += 2;
+ count -= 2;
+ state = DATA;
+ return origCount - count + DataToNetwork(buffer, count, control);
+ case DATA:
+ case DATA_CONTINUE:
+ while (count) {
+ if (*buffer == ORDER_SBA) {
+ if (state == DATA_CONTINUE) {
+ Undent();
+ state = DATA;
+ }
+ putstr("SBA ");
+ PrintAddr(Addr3270(buffer[1], buffer[2]));
+ putSpace();
+ buffer += 3;
+ count -= 3;
+ } else {
+ if (state == DATA) {
+ putstr("DATA:");
+ Indent();
+ state = DATA_CONTINUE;
+ }
+ putEChar(*buffer);
+ buffer++;
+ count--;
+ }
+ }
+ if (control) {
+ if (state == DATA_CONTINUE) {
+ Undent();
+ }
+ state = NEED_AID;
+ }
+ return origCount-count;
+ }
+ return 0;
+}
+
+int
+GetXValue(c)
+int c;
+{
+ if (!isascii(c)) {
+ fflush(stdout);
+ fprintf(stderr, "Non-hex digit 0x%x.\n", c);
+ fflush(stderr);
+ return 0;
+ } else {
+ if (islower(c)) {
+ return (c-'a')+10;
+ } else if (isupper(c)) {
+ return (c-'A')+10;
+ } else {
+ return c-'0';
+ }
+ }
+}
+
+unsigned char outbound[8192], inbound[8192],
+ *outnext = outbound, *innext = inbound, *p = 0;
+
+void
+termblock(old, new, control)
+int old,
+ new; /* old and new directions */
+{
+ int count;
+
+ if (p) {
+ if (old == '<') {
+ outnext = p;
+ count = DataFromNetwork(outbound, outnext-outbound, control);
+ if (outbound+count == outnext) {
+ outnext = outbound;
+ } else {
+ memcpy(outbound, outbound+count, outnext-(outbound+count));
+ outnext = outbound+count;
+ }
+ } else {
+ innext = p;
+ count = DataToNetwork(inbound, innext-inbound, control);
+ if (inbound+count == innext) {
+ innext = inbound;
+ } else {
+ memcpy(inbound, inbound+count, innext-(inbound+count));
+ innext = inbound+count;
+ }
+ }
+ }
+ if (new == '<') {
+ p = outnext;
+ } else if (new == '>') {
+ p = innext;
+ } else {
+ fprintf(stderr, "Bad direction character '%c'.\n", new);
+ exit(1);
+ }
+}
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int location;
+ char new;
+ int c, c1;
+
+ memset(Orders, 0, sizeof Orders);
+ Orders[ORDER_SF] = Orders[ORDER_SBA] = Orders[ORDER_IC]
+ = Orders[ORDER_PT] = Orders[ORDER_RA] = Orders[ORDER_EUA]
+ = Orders[ORDER_YALE] = 1;
+
+ while (scanf("%c 0x%x\t", &new, &location) != EOF) {
+ if (new != direction) {
+ termblock(direction, new, 0);
+ direction = new;
+ }
+ while (((c = getchar()) != EOF) && (c != '\n') && (isxdigit(c))) {
+#define NORMAL 0
+#define GOT0XFF 0xff
+ static int state = NORMAL;
+
+ c1 = getchar();
+ c = (GetXValue(c) << 4) + GetXValue(c1);
+ switch (state) {
+ case NORMAL:
+ if (c == 0xff) {
+ state = GOT0XFF;
+ } else {
+ *p++ = c;
+ }
+ break;
+ case GOT0XFF:
+ if (c == 0xef) {
+ termblock(direction, direction, 1);
+ } else {
+ *p++ = 0xff;
+ *p++ = c;
+ }
+ state = NORMAL;
+ }
+ }
+ }
+ return 0;
+}