diff options
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, ®s, &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, ®s, &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, ®s, &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(®s, ®s, &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©_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; +} |