diff options
Diffstat (limited to 'usr.bin/tn3270')
96 files changed, 18687 insertions, 0 deletions
diff --git a/usr.bin/tn3270/Makefile b/usr.bin/tn3270/Makefile new file mode 100644 index 0000000..009e31f --- /dev/null +++ b/usr.bin/tn3270/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +SUBDIR= tn3270 mset + +.if !make(install) +SUBDIR+=tools +.endif + +.include <bsd.subdir.mk> diff --git a/usr.bin/tn3270/Makefile.inc b/usr.bin/tn3270/Makefile.inc new file mode 100644 index 0000000..bd2446e --- /dev/null +++ b/usr.bin/tn3270/Makefile.inc @@ -0,0 +1,4 @@ +# @(#)Makefile.inc 8.1 (Berkeley) 6/6/93 + +KBD= unix.kbd +CFLAGS+=-DTERMCAP -DSRCRT -DKLUDGELINEMODE -DUSE_TERMIO -DTN3270 diff --git a/usr.bin/tn3270/api/api_bsd.c b/usr.bin/tn3270/api/api_bsd.c new file mode 100644 index 0000000..46db372 --- /dev/null +++ b/usr.bin/tn3270/api/api_bsd.c @@ -0,0 +1,281 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)api_bsd.c 8.2 (Berkeley) 1/7/94"; +#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 "../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; + extern char *getenv(); + 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:%s", 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; + } + bcopy(hp->h_addr, (char *)&server.sin_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, "%s\n", inkey) != 1) { + perror("fscanf"); + return -1; + } + sd.length = strlen(inkey)+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, inkey) == -1) { + return -1; + } + while ((i = api_exch_nextcommand()) != EXCH_CMD_ASSOCIATED) { + int passwd_length; + char *passwd, *getpass(); + char buffer[200]; + + switch (i) { + case EXCH_CMD_REJECTED: + if (api_exch_intype(EXCH_TYPE_STORE_DESC, + sizeof sd, (char *)&sd) == -1) { + return -1; + } + if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { + return -1; + } + buffer[sd.length] = 0; + fprintf(stderr, "%s\n", buffer); + if (api_exch_outcommand(EXCH_CMD_ASSOCIATE) == -1) { + return -1; + } + break; + case EXCH_CMD_SEND_AUTH: + if (api_exch_intype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { + return -1; + } + if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { + return -1; + } + 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) { + return -1; + } + if (api_exch_intype(EXCH_TYPE_BYTES, sd.length, buffer) == -1) { + return -1; + } + 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) { + return -1; + } + if (api_exch_outtype(EXCH_TYPE_STORE_DESC, sizeof sd, (char *)&sd) == -1) { + return -1; + } + if (api_exch_outtype(EXCH_TYPE_BYTES, passwd_length, passwd) == -1) { + return -1; + } + break; + case -1: + return -1; + default: + fprintf(stderr, + "Waiting for connection indicator, received 0x%x.\n", i); + break; + } + } + /* YEAH */ + return 0; /* Happiness! */ +} + + +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/usr.bin/tn3270/api/api_exch.c b/usr.bin/tn3270/api/api_exch.c new file mode 100644 index 0000000..a4626b9 --- /dev/null +++ b/usr.bin/tn3270/api/api_exch.c @@ -0,0 +1,429 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)api_exch.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.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() +{ + 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; + } + 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; + } + } + 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; +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; +{ + extern char *strcpy(); + + 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/usr.bin/tn3270/api/api_exch.h b/usr.bin/tn3270/api/api_exch.h new file mode 100644 index 0000000..24e6691 --- /dev/null +++ b/usr.bin/tn3270/api/api_exch.h @@ -0,0 +1,161 @@ +/*- + * 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. 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. + * + * @(#)api_exch.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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 */ +}; diff --git a/usr.bin/tn3270/api/apilib.c b/usr.bin/tn3270/api/apilib.c new file mode 100644 index 0000000..3146170 --- /dev/null +++ b/usr.bin/tn3270/api/apilib.c @@ -0,0 +1,411 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)apilib.c 8.1 (Berkeley) 6/6/93"; +#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; + +/* + * 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 + */ + +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; + } +} + + +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; + } +} + +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 + */ + +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; + } +} + + +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; + } +} + + +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; + } +} + + +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; + } +} + +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 + */ + +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 + */ + +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. + */ + +api_finish() +{ +#if defined(unix) + if (api_close_api() == -1) { + return -1; + } else { + return 0; + } +#endif /* defined(unix) */ +} + + +/* + * The initialization routine. Be sure to call this first. + */ + +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/usr.bin/tn3270/api/apilib.h b/usr.bin/tn3270/api/apilib.h new file mode 100644 index 0000000..3253e39 --- /dev/null +++ b/usr.bin/tn3270/api/apilib.h @@ -0,0 +1,44 @@ +/*- + * 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. 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. + * + * @(#)apilib.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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.) */ diff --git a/usr.bin/tn3270/api/asc_ebc.c b/usr.bin/tn3270/api/asc_ebc.c new file mode 100644 index 0000000..14061f0 --- /dev/null +++ b/usr.bin/tn3270/api/asc_ebc.c @@ -0,0 +1,110 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)asc_ebc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * 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/usr.bin/tn3270/api/asc_ebc.h b/usr.bin/tn3270/api/asc_ebc.h new file mode 100644 index 0000000..17c0488 --- /dev/null +++ b/usr.bin/tn3270/api/asc_ebc.h @@ -0,0 +1,51 @@ +/*- + * 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. 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. + * + * @(#)asc_ebc.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/api/astosc.c b/usr.bin/tn3270/api/astosc.c new file mode 100644 index 0000000..ff641d6 --- /dev/null +++ b/usr.bin/tn3270/api/astosc.c @@ -0,0 +1,98 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)astosc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#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 +ustrcmp(string1, string2) +register char *string1; +register char *string2; +{ + register 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) +register char *string; +{ + register 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/usr.bin/tn3270/api/astosc.h b/usr.bin/tn3270/api/astosc.h new file mode 100644 index 0000000..bbafd5f --- /dev/null +++ b/usr.bin/tn3270/api/astosc.h @@ -0,0 +1,58 @@ +/*- + * 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. 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. + * + * @(#)astosc.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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(); /* Function to feed InitControl() */ + +extern struct astosc astosc[256]; diff --git a/usr.bin/tn3270/api/dctype.c b/usr.bin/tn3270/api/dctype.c new file mode 100644 index 0000000..1fd8a90 --- /dev/null +++ b/usr.bin/tn3270/api/dctype.c @@ -0,0 +1,245 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)dctype.c 8.1 (Berkeley) 6/6/93"; +#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/usr.bin/tn3270/api/dctype.h b/usr.bin/tn3270/api/dctype.h new file mode 100644 index 0000000..2b0c068 --- /dev/null +++ b/usr.bin/tn3270/api/dctype.h @@ -0,0 +1,54 @@ +/*- + * 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. 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. + * + * @(#)dctype.h 8.1 (Berkeley) 6/6/93 + */ + +#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/usr.bin/tn3270/api/disp_asc.c b/usr.bin/tn3270/api/disp_asc.c new file mode 100644 index 0000000..85ba106 --- /dev/null +++ b/usr.bin/tn3270/api/disp_asc.c @@ -0,0 +1,45 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)disp_asc.c 8.1 (Berkeley) 6/6/93"; +#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/usr.bin/tn3270/api/disp_asc.h b/usr.bin/tn3270/api/disp_asc.h new file mode 100644 index 0000000..5abe92b --- /dev/null +++ b/usr.bin/tn3270/api/disp_asc.h @@ -0,0 +1,43 @@ +/*- + * 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. 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. + * + * @(#)disp_asc.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/api/ebc_disp.c b/usr.bin/tn3270/api/ebc_disp.c new file mode 100644 index 0000000..a601099 --- /dev/null +++ b/usr.bin/tn3270/api/ebc_disp.c @@ -0,0 +1,106 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)ebc_disp.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * 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/usr.bin/tn3270/api/ebc_disp.h b/usr.bin/tn3270/api/ebc_disp.h new file mode 100644 index 0000000..201c39d --- /dev/null +++ b/usr.bin/tn3270/api/ebc_disp.h @@ -0,0 +1,38 @@ +/*- + * 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. 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. + * + * @(#)ebc_disp.h 8.1 (Berkeley) 6/6/93 + */ + +extern unsigned char + ebc_disp[256], + disp_ebc[192]; diff --git a/usr.bin/tn3270/ascii/default.map b/usr.bin/tn3270/ascii/default.map new file mode 100644 index 0000000..a4cf6e1 --- /dev/null +++ b/usr.bin/tn3270/ascii/default.map @@ -0,0 +1,79 @@ +/*- + * 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. 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. + * + * @(#)default.map 8.1 (Berkeley) 6/6/93 + */ + +/* 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 /etc/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/usr.bin/tn3270/ascii/map3270.c b/usr.bin/tn3270/ascii/map3270.c new file mode 100644 index 0000000..0295509 --- /dev/null +++ b/usr.bin/tn3270/ascii/map3270.c @@ -0,0 +1,934 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)map3270.c 8.1 (Berkeley) 6/6/93"; +#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 <stdio.h> +#include <ctype.h> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ + +#define IsPrint(c) ((isprint(c) && !isspace(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 dependancy... */ +#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); 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 avaliable. + */ + +#ifdef DEBUG +static int debug = 0; /* debug flag (for debuggin tables) */ +#endif /* DEBUG */ + +static int (*GetTc)(); +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] = { 0 }; /* character stack for parser */ +static int rp = 0, /* read pointer into lifo */ + wp = 0; /* write pointer into lifo */ + +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]; + extern char *getenv(); + + (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() +{ + static lexicon c; + register lexicon *pC = &c; + register 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) + register 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 */ + +ustrcmp(string1, string2) +register char *string1; +register char *string2; +{ + register 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, *lp; + 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; + } + lp = &lex; + if ((lp->type == LEX_CHAR) && !IsPrint(lp->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 +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 +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, *lp; + static stringWithLength output = { 0 }; + char *pointer = output.array; +# define IsAlnum(c) (isalnum(c) || (c == '_') \ + || (c == '-') || (c == '.')) + + lex = Get(); + lp = &lex; + + if ((lp->type != LEX_CHAR) || !IsAlnum(lp->value)) { + UnGet(lex); + return(0); + } + + while ((lp->type == LEX_CHAR) && IsAlnum(lp->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, *lp; + + lex = Get(); + lp = &lex; + + while ((lp->type == LEX_CHAR) && + (isspace(lp->value) || (lp->value == '#'))) { + if (lex.value == '#') { + lex = EatToNL(); + } else { + lex = Get(); + } + } + UnGet(lex); +} + +static void +FreeState(pState) +state *pState; +{ + extern int free(); + + free((char *)pState); +} + + +static state * +GetState() +{ + state *pState; + extern char *malloc(); + + 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 +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 +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 +GetDefinitions() +{ + if (!GetDefinition()) { + return(0); + } else { + while (GetDefinition()) { + ; + } + } + return(1); +} + +static +GetBegin() +{ + GetWS(); + if (!GetCharacter('{')) { + return(0); + } + return(1); +} + +static +GetEnd() +{ + GetWS(); + if (!GetCharacter('}')) { + return(0); + } + return(1); +} + +static +GetName() +{ + if (!GetAlphaMericString()) { + return(0); + } + GetWS(); + while (GetAlphaMericString()) { + GetWS(); + } + return(1); +} + +static +GetNames() +{ + GetWS(); + if (!GetName()) { + return(0); + } else { + GetWS(); + while (GetCharacter('|')) { + GetWS(); + if (!GetName()) { + return(0); + } + } + } + return(1); +} + +static +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 +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 + */ + +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; + extern char *malloc(); + + 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)(); /* Translates ascii string to integer */ +{ + extern char *getenv(); + 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 (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("/etc/map3270", keybdPointer); + } + } + if (!GotIt) { + if (environPointer) { + GotIt = Position(environPointer, "unknown"); + } + if (!GotIt) { + GotIt = Position("/etc/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(); + return(firstentry.address); +} diff --git a/usr.bin/tn3270/ascii/map3270.h b/usr.bin/tn3270/ascii/map3270.h new file mode 100644 index 0000000..f8d6e5c --- /dev/null +++ b/usr.bin/tn3270/ascii/map3270.h @@ -0,0 +1,41 @@ +/*- + * 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. 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.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Declaration for map3270.c. + */ + +extern state + *InitControl(); diff --git a/usr.bin/tn3270/ascii/mset.c b/usr.bin/tn3270/ascii/mset.c new file mode 100644 index 0000000..508fe66 --- /dev/null +++ b/usr.bin/tn3270/ascii/mset.c @@ -0,0 +1,410 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mset.c 8.1 (Berkeley) 6/6/93"; +#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> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ +#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(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) +register struct regstate *regptr; +{ + static struct regstate *pivot = regstates; + register 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) +register char *string; +char *begin, *tc_name; +{ + register char *st1, *st2; + register int pchar; + static char suffix = 'A'; + int new = strcmp(savename, tc_name); + char delim = new ? ';' : '|'; + char *uncontrol(); + + 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; +} + + +main(argc, argv) +int argc; +char *argv[]; +{ + state *head; + char *keybdPointer = (char *) 0; + char *commandName = argv[0]; + extern char *getenv(); + 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/usr.bin/tn3270/ascii/state.h b/usr.bin/tn3270/ascii/state.h new file mode 100644 index 0000000..562522a --- /dev/null +++ b/usr.bin/tn3270/ascii/state.h @@ -0,0 +1,50 @@ +/*- + * 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. 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. + * + * @(#)state.h 8.1 (Berkeley) 6/6/93 + */ + +#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 */ +}; diff --git a/usr.bin/tn3270/ascii/termin.c b/usr.bin/tn3270/ascii/termin.c new file mode 100644 index 0000000..a783189 --- /dev/null +++ b/usr.bin/tn3270/ascii/termin.c @@ -0,0 +1,281 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)termin.c 8.1 (Berkeley) 6/6/93"; +#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/externs.h" +#include "../ctlr/declare.h" + +#include "../api/astosc.h" +#include "state.h" + +#include "../general/globals.h" + +#define IsControl(c) (!isprint(c) || (isspace(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) + + +/* + * init_keyboard() + * + * Initialize the keyboard variables. + */ + +void +init_keyboard() +{ + ourPHead = ourPTail = ourBuffer; + InControl = 0; + WaitingForSynch = 0; +} + + +/* + * Initialize the keyboard mapping file. + */ + +void +InitMapping() +{ + extern state *InitControl(); + register struct astosc *ptr; + + if (!headOfControl) { + /* need to initialize */ + headOfControl = InitControl((char *)0, 0, ascii_to_index); + if (!headOfControl) { /* should not occur */ + quit(); + } + 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; + register 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) +register char *buffer; /* the data read in */ +register int count; /* how many bytes in this buffer */ +{ + register state *regControlPointer; + register char c; + register 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) { + void BellOff(); + + BellOff(); + } + + origCount = count; + + while (count) { + c = *buffer++&0x7f; + count--; + + 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 { + void RingBell(); + + 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/usr.bin/tn3270/ctlr/3180.kbd b/usr.bin/tn3270/ctlr/3180.kbd new file mode 100644 index 0000000..1fc7204 --- /dev/null +++ b/usr.bin/tn3270/ctlr/3180.kbd @@ -0,0 +1,182 @@ +/*- + * 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. 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. + * + * @(#)3180.kbd 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/ctlr/3270pc.kbd b/usr.bin/tn3270/ctlr/3270pc.kbd new file mode 100644 index 0000000..df75046 --- /dev/null +++ b/usr.bin/tn3270/ctlr/3270pc.kbd @@ -0,0 +1,182 @@ +/*- + * 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. 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. + * + * @(#)3270pc.kbd 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/ctlr/api.c b/usr.bin/tn3270/ctlr/api.c new file mode 100644 index 0000000..1113295 --- /dev/null +++ b/usr.bin/tn3270/ctlr/api.c @@ -0,0 +1,755 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)api.c 8.1 (Berkeley) 6/6/93"; +#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 "../general/globals.h" + +int apitrace = 0; + +/* + * Some defines for things we use internally. + */ + +#define PS_SESSION_ID 23 +#define BUF_SESSION_ID 0 + +/* + * General utility routines. + */ + +#if defined(MSDOS) + +#if defined(LINT_ARGS) +static void movetous(char *, int, int, int); +static void movetothem(int, int, char *, int); +#endif /* defined(LINT_ARGS) */ + +#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) */ + +#if defined(unix) +extern char *access_api(); +extern void movetous(), movetothem(), unaccess_api(); +#endif /* defined(unix) */ + + +/* + * 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 +copy_subroutine(target, source, parms, what_is_user, length) +BufferDescriptor *target, *source; +CopyStringParms *parms; +int what_is_user; +#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; + 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 = (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 = 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) { + 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; +} + + +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/usr.bin/tn3270/ctlr/api.h b/usr.bin/tn3270/ctlr/api.h new file mode 100644 index 0000000..8004f34 --- /dev/null +++ b/usr.bin/tn3270/ctlr/api.h @@ -0,0 +1,403 @@ +/*- + * 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. 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. + * + * @(#)api.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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 preceeding. + */ + +#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) */ diff --git a/usr.bin/tn3270/ctlr/declare.h b/usr.bin/tn3270/ctlr/declare.h new file mode 100644 index 0000000..0400b33 --- /dev/null +++ b/usr.bin/tn3270/ctlr/declare.h @@ -0,0 +1,53 @@ +/*- + * 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. 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. + * + * @(#)declare.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Declarations of routines from the controller. + */ + +extern void + AddHost(), + DoReadModified(), + DoReadBuffer(), + OptInit(), + SendToIBM(), + SendTransparent(); + +extern int + DataFrom3270(), + DataFromNetwork(), + OptOrder(), + OutputClock, + TransparentClock; diff --git a/usr.bin/tn3270/ctlr/externs.h b/usr.bin/tn3270/ctlr/externs.h new file mode 100644 index 0000000..11c983c --- /dev/null +++ b/usr.bin/tn3270/ctlr/externs.h @@ -0,0 +1,66 @@ +/*- + * 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. 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. + * + * @(#)externs.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * External references from the controller. + */ + +#if !defined(MSDOS) +extern char *access_api(); +extern void movetous(), movetothem(), unaccess_api(); +#endif /* !defined(MSDOS) */ + +extern unsigned char + *memNSchr(); /* Search for a character ANDED, increment by stride */ + +extern int + DataToNetwork(), + OutputClock, + suspend(), + TransparentClock, + UnLocked; /* keyboard is UnLocked? */ + +extern void + command(), + ConnectScreen(), + ExitString(), + init_inbound(), + LocalClearScreen(), + RefreshScreen(), + RingBell(), + setconnmode(), + StopScreen(), + TransOut(), + TransStop(); diff --git a/usr.bin/tn3270/ctlr/function.c b/usr.bin/tn3270/ctlr/function.c new file mode 100644 index 0000000..1844860 --- /dev/null +++ b/usr.bin/tn3270/ctlr/function.c @@ -0,0 +1,47 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)function.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * 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/usr.bin/tn3270/ctlr/function.h b/usr.bin/tn3270/ctlr/function.h new file mode 100644 index 0000000..a62018d --- /dev/null +++ b/usr.bin/tn3270/ctlr/function.h @@ -0,0 +1,166 @@ +/*- + * 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. 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. + * + * @(#)function.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/ctlr/hostctlr.h b/usr.bin/tn3270/ctlr/hostctlr.h new file mode 100644 index 0000000..086d7ee --- /dev/null +++ b/usr.bin/tn3270/ctlr/hostctlr.h @@ -0,0 +1,222 @@ +/*- + * 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. 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. + * + * @(#)hostctlr.h 8.1 (Berkeley) 6/6/93 + */ + +#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/usr.bin/tn3270/ctlr/inbound.c b/usr.bin/tn3270/ctlr/inbound.c new file mode 100644 index 0000000..fe8d142 --- /dev/null +++ b/usr.bin/tn3270/ctlr/inbound.c @@ -0,0 +1,1194 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)inbound.c 8.1 (Berkeley) 6/6/93"; +#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 "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? */ + + +/* + * 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() +{ + register 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() +{ + register 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). + */ + +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() +{ + register 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) +register int where, /* Where to start deleting from */ + from; /* Where to pull back from */ +{ + register 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() +{ + register 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() +{ + register 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() +{ + register int i; + register 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 +LastOfField(i) +register int i; /* position to start from */ +{ + register int j; + register 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() +{ + register int i, j; + register int Nulls; + register 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 +SendField(i, cmd) +register int i; /* where we saw MDT bit */ +int cmd; /* The command code (type of read) */ +{ + register int j; + register int k; + register int Nulls; + register 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 */ +{ + register 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() +{ + register 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? */ +{ + register 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 */ +{ + register int c; + register int i; + register 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); + 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); + if (shell_active == 0) { + ConnectScreen(); + } + break; + + case FCN_DISC: + StopScreen(1); + suspend(); + setconnmode(); + 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/usr.bin/tn3270/ctlr/oia.c b/usr.bin/tn3270/ctlr/oia.c new file mode 100644 index 0000000..1f80359 --- /dev/null +++ b/usr.bin/tn3270/ctlr/oia.c @@ -0,0 +1,51 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)oia.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * Routines to maintain the Operator Information Area. + */ + +#include "../general/general.h" + +#include "oia.h" +#include "../general/globals.h" + + +init_oia() +{ + ClearElement(OperatorInformationArea); +} diff --git a/usr.bin/tn3270/ctlr/oia.h b/usr.bin/tn3270/ctlr/oia.h new file mode 100644 index 0000000..a1414ca --- /dev/null +++ b/usr.bin/tn3270/ctlr/oia.h @@ -0,0 +1,190 @@ +/*- + * 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. 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. + * + * @(#)oia.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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 diff --git a/usr.bin/tn3270/ctlr/options.c b/usr.bin/tn3270/ctlr/options.c new file mode 100644 index 0000000..38a2d43 --- /dev/null +++ b/usr.bin/tn3270/ctlr/options.c @@ -0,0 +1,181 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)options.c 8.1 (Berkeley) 6/6/93"; +#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() +{ + register 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; +} + +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/usr.bin/tn3270/ctlr/options.h b/usr.bin/tn3270/ctlr/options.h new file mode 100644 index 0000000..fbf5b10 --- /dev/null +++ b/usr.bin/tn3270/ctlr/options.h @@ -0,0 +1,41 @@ +/*- + * 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. 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. + * + * @(#)options.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * the various options that run our life. Very few of these are implemented + * as yet. + */ + +#define INCLUDED_OPTIONS diff --git a/usr.bin/tn3270/ctlr/outbound.c b/usr.bin/tn3270/ctlr/outbound.c new file mode 100644 index 0000000..72432f2 --- /dev/null +++ b/usr.bin/tn3270/ctlr/outbound.c @@ -0,0 +1,605 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)outbound.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> + +#include "../general/general.h" + +#include "hostctlr.h" +#include "oia.h" +#include "screen.h" +#include "../api/ebc_disp.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(); +} + + +FieldInc(position) +register int position; /* Position in previous field */ +{ + register 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; +} + +FieldDec(position) +int position; +{ + register 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 */ +register int count; /* and how much there is */ +int control; /* this buffer ended block? */ +{ + int origCount; + register unsigned char *buffer = (unsigned char *)Buffer; + register int c; + register 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 (count == 0) { + 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); + } else { + return(origCount-count); + } +} + +/* + * 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/usr.bin/tn3270/ctlr/screen.h b/usr.bin/tn3270/ctlr/screen.h new file mode 100644 index 0000000..9dd8595 --- /dev/null +++ b/usr.bin/tn3270/ctlr/screen.h @@ -0,0 +1,145 @@ +/*- + * 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. 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. + * + * @(#)screen.h 8.1 (Berkeley) 6/6/93 + */ + +#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 int + FieldFind(); + +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/usr.bin/tn3270/ctlr/scrnctlr.h b/usr.bin/tn3270/ctlr/scrnctlr.h new file mode 100644 index 0000000..8c140c6 --- /dev/null +++ b/usr.bin/tn3270/ctlr/scrnctlr.h @@ -0,0 +1,48 @@ +/*- + * 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. 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. + * + * @(#)scrnctlr.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/ctlr/unix.kbd b/usr.bin/tn3270/ctlr/unix.kbd new file mode 100644 index 0000000..ad41eec --- /dev/null +++ b/usr.bin/tn3270/ctlr/unix.kbd @@ -0,0 +1,184 @@ +/*- + * 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. 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. + * + * @(#)unix.kbd 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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/usr.bin/tn3270/distribution/README b/usr.bin/tn3270/distribution/README new file mode 100644 index 0000000..29afc73 --- /dev/null +++ b/usr.bin/tn3270/distribution/README @@ -0,0 +1,99 @@ +Welcome to the new tn3270 - version 4.1.1. + +This version consists entirely of bug fixes to the August 1987 beta release +of tn3270. This version will now deal with CICS and VM/XA on the IBM +side, and with SunOS 4.0 on Sun 3's and Sun 4's. + +This version has been tested on various versions of BSD Unix, including +4.2 and 4.3 (but there are never vanilla versions) and the post-4.3 systems +running at Berkeley. It has been tested on CCI's, Vaxen, Sun 3's and Sun 4's. +However, it doesn't necessarily work on all systems (nor has the testing +been as intensive as one might like). + +This version should build on any Berkeley-derived system. + +There are two alternate make files: ./makefile_4.2 and telnet/Makefile_ultrix. + +**** Try ./makefile_4.2 if you get compile-time errors, or get + "multiply defined" messages for "_putchar" from the loader. + +**** Try telnet/Makefile_ultrix if your make(1) utility doesn't + support VPATH. Also try this makefile if your ld(1) doesn't + support the -r flag correctly. + +The bad news is that I've had to drop MS-DOS support. The good news here is +that there are various versions available for MS-DOS (from FTP Software in +Cambridge, Mass.; from IBM; from Excelan; and probably from others). The +hooks are still there, as well as some code to update the screen. However, +I just haven't had the time to produce a fully integrated version that would +"just make". I suspect that a future release may have MS-DOS support back +in it. + +There is no Mac support. Contact Peter DiCamillo at Brown University if +you need a Mac tn3270. + +The main code change in this version is to what used to be called "telnet.c". +This is now replaced with a version of telnet (substantially what appeared +in the "4.3tahoe" release from CSRG) which is broken into separate files. + +Here is an overview of the directory structure: + + api/ General library of function needed by API + (and, to some extent, by the rest of tn3270). + + arpa/ Location of "telnet.h" (for non-4.3 systems). + + ascii/ Routines necessary to handle the case of running + from an ASCII-oriented system (ie: unix). + + ctlr/ The main part of the emulator. Handles 3270 scan + codes, 3270 data stream, 3270 display codes, + and EBCDIC. Also, the internal API function + lives here. + + general/ Some general subroutines and data structures of + interest to the emulator only. + + sys_curses/ System-dependent code for a curses-based environment. + + sys_dos/ System-dependent code for an MS-DOS-base environment. + Remember that this is included for your developmental + needs (ie: it doesn't work). + + telnet/ Where the telnet portion of tn3720 is built. + + tools/ Various tools. Most of these are used during the + build process. One (prt3270) is a debugging tool. + One (mkmake.y) is quite horrible, and attempts to + transform Unix makefiles into PC makefiles. + + utilities/ The source for tnrecv, which receives files + (fairly slowly) from an IBM host. We don't + include the IBM side, because we really aren't + happy with very much of it (except that it does, + sometimes, work). Hopefully, when we get past + the beta stage we will have more robust (and + complete) code to share. + +The fact that system dependancies are isolated should make it easy +to port to other systems. I would like to hear about problems porting +to new areas. + +In the August, 1987 README file, the following appeared: + +> WHAT IS NOT IN THIS VERSION (sigh): + +> 1) We don't have a native X version yet. I am waiting for X version 11 +> (though this is mostly an excuse; I could have done version 10, +> but I haven't had the time). + +> 2) We don't process structured fields. + +> 3) We don't do 3270-style graphics (ala 3193, say). + +> The above three items WILL be in the next version, which should come +> along "any day now" (say 6 months) (but, they WON'T be in the production +> release of this version). + +The next piece of bad news is that none of the above have happened yet, +and I don't know when they might occur. diff --git a/usr.bin/tn3270/distribution/arpa/makefile b/usr.bin/tn3270/distribution/arpa/makefile new file mode 100644 index 0000000..2cf3bc0 --- /dev/null +++ b/usr.bin/tn3270/distribution/arpa/makefile @@ -0,0 +1,67 @@ +# @(#)makefile 8.1 (Berkeley) 6/6/93 + +# msdos versus unix defines +O = .o +#PC_O = .obj + +X = +#PC_X = .exe + +L = +#PC_L = -link + +CC = cc +#PC_CC = cl + +MV = mv +#PC_MV = rename + +RM = rm -f +#PC_RM= erase + +LINT_ARGS = +#PC_LINT_ARGS = -DLINT_ARGS + +DEBUG_FLAGS = -g +#PC_DEBUG_FLAGS = -Zi -Od + +AR = ar +AR1 = cr +AR2 = +AR3 = +#PC_AR = lib +#PC_AR1 = +#PC_AR2 = + +#PC_AR3 = ";" + +RANLIB = ranlib +#PC_RANLIB = echo "Done with " + +PRINT = lpr -p + +ALLC = +ALLH = telnet.h + +ALLPRINT = ${ALLH} ${ALLC} + +ALLSOURCE = ${ALLPRINT} makefile makefile.mak + +clean: + +sccsclean: + -sccs clean + -sccs get makefile + +action: + ${ACTION} + +print: + ${PRINT} ${ALLPRINT} + + +sourcelist: ${ALLSOURCE} + @for i in ${ALLSOURCE}; \ + do (echo ${DIRPATH}$$i); done + +.DEFAULT: + sccs get $< diff --git a/usr.bin/tn3270/distribution/arpa/telnet.h b/usr.bin/tn3270/distribution/arpa/telnet.h new file mode 100644 index 0000000..eeb72c2 --- /dev/null +++ b/usr.bin/tn3270/distribution/arpa/telnet.h @@ -0,0 +1,191 @@ +/*- + * Copyright (c) 1983, 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. + * + * @(#)telnet.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Definitions for the TELNET protocol. + */ +#define IAC 255 /* interpret as command: */ +#define DONT 254 /* you are not to use option */ +#define DO 253 /* please, you use option */ +#define WONT 252 /* I won't use option */ +#define WILL 251 /* I will use option */ +#define SB 250 /* interpret as subnegotiation */ +#define GA 249 /* you may reverse the line */ +#define EL 248 /* erase the current line */ +#define EC 247 /* erase the current character */ +#define AYT 246 /* are you there */ +#define AO 245 /* abort output--but let prog finish */ +#define IP 244 /* interrupt process--permanently */ +#define BREAK 243 /* break */ +#define DM 242 /* data mark--for connect. cleaning */ +#define NOP 241 /* nop */ +#define SE 240 /* end sub negotiation */ +#define EOR 239 /* end of record (transparent mode) */ +#define ABORT 238 /* Abort process */ +#define SUSP 237 /* Suspend process */ +#define xEOF 236 /* End of file: EOF is already used... */ + +#define SYNCH 242 /* for telfunc calls */ + +#ifdef TELCMDS +char *telcmds[] = { + "EOF", "SUSP", "ABORT", "EOR", + "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", + "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", +}; +#define TELCMD_FIRST xEOF +#define TELCMD_LAST IAC +#define TELCMD_OK(x) ((x) <= TELCMD_LAST && (x) >= TELCMD_FIRST) +#define TELCMD(x) telcmds[(x)-TELCMD_FIRST] +#endif + +/* telnet options */ +#define TELOPT_BINARY 0 /* 8-bit data path */ +#define TELOPT_ECHO 1 /* echo */ +#define TELOPT_RCP 2 /* prepare to reconnect */ +#define TELOPT_SGA 3 /* suppress go ahead */ +#define TELOPT_NAMS 4 /* approximate message size */ +#define TELOPT_STATUS 5 /* give status */ +#define TELOPT_TM 6 /* timing mark */ +#define TELOPT_RCTE 7 /* remote controlled transmission and echo */ +#define TELOPT_NAOL 8 /* negotiate about output line width */ +#define TELOPT_NAOP 9 /* negotiate about output page size */ +#define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ +#define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ +#define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ +#define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ +#define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ +#define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ +#define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ +#define TELOPT_XASCII 17 /* extended ascic character set */ +#define TELOPT_LOGOUT 18 /* force logout */ +#define TELOPT_BM 19 /* byte macro */ +#define TELOPT_DET 20 /* data entry terminal */ +#define TELOPT_SUPDUP 21 /* supdup protocol */ +#define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ +#define TELOPT_SNDLOC 23 /* send location */ +#define TELOPT_TTYPE 24 /* terminal type */ +#define TELOPT_EOR 25 /* end or record */ +#define TELOPT_TUID 26 /* TACACS user identification */ +#define TELOPT_OUTMRK 27 /* output marking */ +#define TELOPT_TTYLOC 28 /* terminal location number */ +#define TELOPT_3270REGIME 29 /* 3270 regime */ +#define TELOPT_X3PAD 30 /* X.3 PAD */ +#define TELOPT_NAWS 31 /* window size */ +#define TELOPT_TSPEED 32 /* terminal speed */ +#define TELOPT_LFLOW 33 /* remote flow control */ +#define TELOPT_LINEMODE 34 /* Linemode option */ +#define TELOPT_EXOPL 255 /* extended-options-list */ + +#define NTELOPTS (1+TELOPT_LINEMODE) +#ifdef TELOPTS +char *telopts[NTELOPTS] = { + "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", + "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", + "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", + "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", + "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", + "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", + "TACACS UID", "OUTPUT MARKING", "TTYLOC", + "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", + "LINEMODE", +}; +#define TELOPT_FIRST TELOPT_BINARY +#define TELOPT_LAST TELOPT_LINEMODE +#define TELOPT_OK(x) ((x) <= TELOPT_LAST && (x) >= TELOPT_FIRST) +#define TELOPT(x) telopts[(x)-TELOPT_FIRST] +#endif + +/* sub-option qualifiers */ +#define TELQUAL_IS 0 /* option is... */ +#define TELQUAL_SEND 1 /* send option */ + +/* + * LINEMODE suboptions + */ + +#define LM_MODE 1 +#define LM_FORWARDMASK 2 +#define LM_SLC 3 + +#define MODE_EDIT 0x01 +#define MODE_TRAPSIG 0x02 +#define MODE_ACK 0x04 + +#define MODE_MASK (MODE_EDIT|MODE_TRAPSIG|MODE_ACK) + +/* Not part of protocol, but needed to simplify things... */ +#define MODE_FLOW 0x40 +#define MODE_ECHO 0x80 +#define MODE_FORCE 0x20 + +#define SLC_SYNCH 1 +#define SLC_BRK 2 +#define SLC_IP 3 +#define SLC_AO 4 +#define SLC_AYT 5 +#define SLC_EOR 6 +#define SLC_ABORT 7 +#define SLC_EOF 8 +#define SLC_SUSP 9 +#define SLC_EC 10 +#define SLC_EL 11 +#define SLC_EW 12 +#define SLC_RP 13 +#define SLC_LNEXT 14 +#define SLC_XON 15 +#define SLC_XOFF 16 +#define SLC_FORW1 17 +#define SLC_FORW2 18 + +#define NSLC 18 + +#define SLC_NAMES "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ + "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ + "LNEXT", "XON", "XOFF", "FORW1", "FORW2" + +#define SLC_NOSUPPORT 0 +#define SLC_CANTCHANGE 1 +#define SLC_VARIABLE 2 +#define SLC_DEFAULT 3 +#define SLC_LEVELBITS 0x03 + +#define SLC_FUNC 0 +#define SLC_FLAGS 1 +#define SLC_VALUE 2 + +#define SLC_ACK 0x80 +#define SLC_FLUSHIN 0x40 +#define SLC_FLUSHOUT 0x20 diff --git a/usr.bin/tn3270/distribution/makefile_4.2 b/usr.bin/tn3270/distribution/makefile_4.2 new file mode 100644 index 0000000..b8e5eb8e --- /dev/null +++ b/usr.bin/tn3270/distribution/makefile_4.2 @@ -0,0 +1,268 @@ +# @(#)makefile 3.5 (Berkeley) 5/15/88 + +# This makefile will make tn3270 on Vax 4.2 systems. Notice, however, +# that on an ultrix system you will need to use the Makefile_ultrix in +# telnet/ rather than the Makefile already in that directory. + +# Makefile for tn3270 and friends... +# +# This is the makefile for tn3270. Note that we use the 4.3+ telnet +# (compiled with special options; see below) to provide the telnet +# support we need. +# +# The following are the defines that may be passed (via the cc +# -D option) to the compiler. +# +# TN3270 - This is to be linked with tn3270. Necessary +# for creating tn3270. Only for compiling +# telnet. +# +# NOT43 - Allows the program to compile and run on +# a 4.2BSD system. +# +# PUTCHAR - Within tn3270, on a NOT43 system, +# allows the use of the 4.3 curses +# (greater speed updating the screen). +# You need the 4.3 curses for this to work. +# +# FD_SETSIZE - On whichever system, if this isn't defined, +# we patch over the FD_SET, etc., macros with +# some homebrewed ones. +# +# SO_OOBINLINE - This is a socket option which we would like +# to set to allow TCP urgent data to come +# to us "inline". This is NECESSARY for +# CORRECT operation, and desireable for +# simpler operation. +# +# LNOFLSH - Detects the presence of the LNOFLSH bit +# in the tty structure. +# +# +# Here are some which are used throughout the system: +# +# unix - Compiles in unix specific stuff. +# +# msdos - Compiles in msdos specific stuff. +# + +# msdos versus unix defines +O = .o +#PC_O = .obj + +X = +#PC_X = .exe + +L = +#PC_L = -link + +CC = cc +#PC_CC = cl + +MV = mv +#PC_MV = rename + +RM = rm -f +#PC_RM= erase + +LINT_ARGS = +#PC_LINT_ARGS = -DLINT_ARGS + +DEBUG_FLAGS = -g +#PC_DEBUG_FLAGS = -Zi -Od + +AR = ar +AR1 = cr +AR2 = +AR3 = +#PC_AR = lib +#PC_AR1 = +#PC_AR2 = + +#PC_AR3 = ";" + +RANLIB = ranlib +#PC_RANLIB = echo "Done with " + + +PRINT = print +ACTION = @sccs tell + +DEFINES = -DNOT43 ${LINT_ARGS} + +INCLUDES = -I. -I.. + +OPTIMIZE = -O +OPTIMIZE = ${DEBUG_FLAGS} + +CFLAGS = $(OPTIMIZE) $(INCLUDES) $(DEFINES) + +# Lint flags +LINTFLAGS = -hbxaz +# How to install the bloody thing... + +DESTDIR= + +BINDIR = $(DESTDIR)/usr/ucb + +# Names for the terminal libraries... +LIBCURSES = -lcurses +LIBTERM = -ltermlib + +#PC_LIBCURSES = +#PC_LIBTERM = + +# The source files... +ALLH = telnet.ext + +MSMAIN = ascii/mset.c + +ALLC = + +ALLO = mset$O + +ALLHC= ${ALLH} ${ALLC} +ALLPRINT = ${ALLHC} + +ALLSOURCE = ${ALLPRINT} makefile makefile.mak makefile_4.2 README + +SYS = sys_curses +#PC_SYS = sys_dos + +# The places where the various components live... + +SUBDIR = api ascii ctlr general ${SYS} telnet + +# The following are directories we don't do regular make's in, but +# we do make everywhere, print, and sourcelist in. + +EXTRADIR = arpa sys_dos tools utilities + +# The libraries we use. The order here is important. +# syslib.a and ctlrlib.a should come first, then the rest. +SUBLIB = ${SYS}/syslib.a ctlr/ctlrlib.a \ + ascii/asciilib.a general/generallib.a + +.s.o: + /lib/cpp -E $< | as -o $@ + +.c.obj: + ${CC} ${CFLAGS} -c $< + +all: FRC tn3270$X mset$X + +FRC: + for i in ${SUBDIR}; \ + do (cd $$i; make ${MFLAGS} "CFLAGS=${CFLAGS}"); done + +tn3270$X: telnet/telprog.o ${SUBLIB} api/apilib.a + ${CC} ${CFLAGS} -o tn3270 telnet/telprog.o \ + $L ${SUBLIB} api/apilib.a $(LIBCURSES) $(LIBTERM) + +#PC_tn3270$X: +#PC_ link <@< +#PC_ telnet +#PC_ tn3270 +#PC_ nul +#PC_ ${SUBLIB} api/apilib.a+ +#PC_ \lib\ublib\ubtcp +#PC_ _PC_< + +mset$X: mset$O ascii/map3270$O + ${CC} ${CFLAGS} -o mset mset$O ascii/map3270$O $L api/apilib.a + +mset$O: $(MSMAIN) + $(CC) $(CFLAGS) -c $(MSMAIN) + +install: tn3270$X mset$X + install -m 755 -o bin -g bin -s tn3270 $(BINDIR) + install -m 755 -o bin -g bin -s mset $(BINDIR) + +action: + ${ACTION} + +clist: ${ALLHC} + @for i in ${SUBDIR}; \ + do (cd $$i; make ${MFLAGS} "DIRPATH=${DIRPATH}$$i/" \ + clist); done + +hclist: ${ALLHC} + @for i in ${SUBDIR}; \ + do (cd $$i; make ${MFLAGS} "DIRPATH=${DIRPATH}$$i/" \ + hclist); done + +everywhere: action + for i in ${SUBDIR} ${EXTRADIR}; \ + do (echo "[$$i]"; cd $$i; make ${MFLAGS} action \ + "ACTION=${ACTION}"); done + +clean: + for i in $(ALLO) mset tn3270 errs makefile.bak; \ + do (${RM} $$i); done + for i in ${SUBDIR} ${EXTRADIR}; \ + do (cd $$i; make ${MFLAGS} clean); done + +sccsclean: + -sccs clean + -sccs get makefile + for i in ${SUBDIR} ${EXTRADIR}; \ + do (cd $$i; make ${MFLAGS} sccsclean); done + +print: + ${PRINT} ${ALLPRINT} + for i in ${SUBDIR} ${EXTRADIR}; \ + do (cd $$i; make ${MFLAGS} "PRINT=${PRINT}" print); done + +tags: ${ALLC} ${ALLH} + ctags -t `make ${MFLAGS} hclist` + +sourcelist: ${ALLSOURCE} + @for i in ${ALLSOURCE}; \ + do (echo ${DIRPATH}$$i); done + @for i in ${SUBDIR} ${EXTRADIR}; \ + do (cd $$i; make ${MFLAGS} "DIRPATH=${DIRPATH}$$i/" \ + sourcelist); done + +lint: + lint ${LINTFLAGS} ${INCLUDES} ${DEFINES} -DTN3270 \ + `make clist` -lcurses + +lintmset: + lint ${LINTFLAGS} ${INCLUDES} ${DEFINES} ${MSMAIN} \ + ascii/map3270.c -lcurses + +makefiles.pc: tools/mkmake + for i in . ${SUBDIR} ${EXTRADIR}; \ + do (sed -e "s/lib\.a/.lib/g" -e "s/^#PC_//" < $$i/makefile | \ + ./tools/mkmake | \ + sed -e "sx/x\\\\xg" -e "s/[ ]*_PC_//" > $$i/makefile.mak); \ + done + +tools/mkmake: + (cd tools; make mkmake) + +.DEFAULT: + sccs get $< + +depend: thisdepend + for i in ${SUBDIR}; do (cd $$i; make ${MFLAGS} depend); done + +thisdepend: + echo > eddep.c + grep '^#include' ${ALLC} eddep.c | grep -v '<' | \ + sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' \ + -e 's/\.c/$$O/' | \ + awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ + else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ + else rec = rec " " $$2 } } \ + END { print rec } ' > makedep + echo '$$r makedep' >>eddep + echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + -rm -f makefile.bak + cp makefile makefile.bak + ed - makefile < eddep + rm eddep makedep eddep.c + +# DO NOT DELETE THIS LINE + diff --git a/usr.bin/tn3270/distribution/sys_dos/makefile b/usr.bin/tn3270/distribution/sys_dos/makefile new file mode 100644 index 0000000..4188f9f --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/makefile @@ -0,0 +1,127 @@ +# @(#)makefile 8.1 (Berkeley) 6/6/93 + +# msdos versus unix defines +O = .o +#PC_O = .obj + +X = +#PC_X = .exe + +L = +#PC_L = -link + +CC = cc +#PC_CC = cl + +MV = mv +#PC_MV = rename + +RM = rm -f +#PC_RM= erase + +LINT_ARGS = +#PC_LINT_ARGS = -DLINT_ARGS + +DEBUG_FLAGS = -g +#PC_DEBUG_FLAGS = -Zi -Od + +AR = ar +AR1 = cr +AR2 = +AR3 = +#PC_AR = lib +#PC_AR1 = +#PC_AR2 = + +#PC_AR3 = ";" + +RANLIB = ranlib +#PC_RANLIB = echo "Done with " + +PRINT = print + +DEFINES = ${LINT_ARGS} + +INCLUDES = -I. + +OPTIMIZE = -O +OPTIMIZE = ${DEBUG_FLAGS} + +CFLAGS = $(OPTIMIZE) $(INCLUDES) $(DEFINES) + +# Lint flags +LINTFLAGS = -hbxaz + +ALLH = spint.h video.h + +ALLC = spintc.c system.c termout.c + +ALLASM = spintasm.asm support.asm + +ALLO = spintasm$O spintc$O support$O system$O termout$O + +ALLPRINT = ${ALLH} ${ALLASM} ${ALLC} + +ALLSOURCE = ${ALLPRINT} makefile makefile.mak + +.c.obj: + ${CC} ${CFLAGS} -c $< + +syslib.a: $(ALLO) + ${RM} $@ + for i in ${ALLO}; do (${AR} ${AR1} $@ ${AR2} $$i${AR3}); done + ${RANLIB} $@ + +clean: + for i in $(ALLO) errs makefile.bak syslib.a; \ + do (${RM} $$i); done + +sccsclean: + -sccs clean + -sccs get makefile + +sourcelist: ${ALLSOURCE} + @for i in ${ALLSOURCE}; \ + do (echo ${DIRPATH}$$i); done + +print: + ${PRINT} ${ALLPRINT} + +tags: ${ALLC} ${ALLH} + ctags -t ${ALLC} ${ALLH} + +action: + ${ACTION} + +lint: + lint ${LINTFLAGS} ${INCLUDES} ${DEFINES} -DTN3270 \ + ${TNMAIN} ${MOSTC} -lcurses + lint ${LINTFLAGS} ${INCLUDES} ${DEFINES} ${MSMAIN} map3270.c -lcurses + +.DEFAULT: + sccs get $< + +depend: + grep '^#include' ${ALLC} ${ALLH} | grep -v '<' | \ + sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' \ + -e 's/\.c/$$O/' | \ + awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ + else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ + else rec = rec " " $$2 } } \ + END { print rec } ' > makedep + echo '$$r makedep' >>eddep + echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + -rm -f makefile.bak + cp makefile makefile.bak + ed - makefile < eddep + rm eddep makedep + +# DO NOT DELETE THIS LINE + +spintc$O: ../general/general.h spint.h +system$O: ../general/general.h ../ctlr/api.h spint.h ../general/globals.h +termout$O: ../general/general.h ../api/disp_asc.h +termout$O: ../ctlr/hostctlr.h +termout$O: ../ctlr/oia.h +termout$O: ../ctlr/screen.h ../general/globals.h video.h diff --git a/usr.bin/tn3270/distribution/sys_dos/spint.h b/usr.bin/tn3270/distribution/sys_dos/spint.h new file mode 100644 index 0000000..023ee52 --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/spint.h @@ -0,0 +1,49 @@ +/*- + * 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. 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. + * + * @(#)spint.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * The 'spint' (spawn and interrupt) routines use this structure. + * + * Note that spint_asm.asm contains an Assembly language version of + * the following, so keep changes in synch! + */ + +typedef struct { + union REGS regs; + struct SREGS sregs; + int int_no; /* Which interrupt to wait on */ + int done; /* Are we done, or just took an interrupt? */ + int rc; /* return code */ +} Spint; diff --git a/usr.bin/tn3270/distribution/sys_dos/spintasm.asm b/usr.bin/tn3270/distribution/sys_dos/spintasm.asm new file mode 100644 index 0000000..72efdec --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/spintasm.asm @@ -0,0 +1,252 @@ +; 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. 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. +; +; @(#)spintasm.asm 8.1 (Berkeley) 6/6/93 +; + +; The code in this file complete the spint calls + +spint struc +; union REGS +spint_ax dw 1 +spint_bx dw 1 +spint_cx dw 1 +spint_dx dw 1 +spint_si dw 1 +spint_di dw 1 +spint_cflag dw 1 +; struct SREGS +spint_es dw 1 +spint_cs dw 1 +spint_ss dw 1 +spint_ds dw 1 +; int intno +spint_intno dw 1 +; int done +spint_done dw 1 +; int rc +spint_rc dw 1 +; +spint ends + + +ENTER MACRO + ; Begin enter + push bp + mov bp,sp + + push ax + push bx + push cx + push dx + push bp + push di + push si + push ds + push es + pushf + + mov cs:start_sp, sp + mov cs:start_ss, ss + ; End enter + ENDM + +LEAVE MACRO + ; Begin leave + cli + mov sp, cs:start_sp + mov ss, cs:start_ss + sti + + popf + pop es + pop ds + pop si + pop di + pop bp + pop dx + pop cx + pop bx + pop ax + + mov sp,bp + pop bp + ret + ; End leave + ENDM + +GETREGS MACRO wherefrom + mov si, wherefrom + mov spint_segment, ds + mov spint_offset, si + + mov ax, spint_ax[si] + mov bx, spint_bx[si] + mov cx, spint_cx[si] + mov dx, spint_dx[si] + ; XXX mov si, spint_si[si] + mov di, spint_di[si] + mov es, spint_es[si] + ; Now, need to do DS, SI + push spint_ds[si] + mov si, spint_si[si] + pop ds + ENDM + + +SETREGS MACRO + mov cs:old_si, si + mov cs:old_ds, ds + + mov ds, cs:spint_segment + mov si, cs:spint_offset + + mov spint_ax[si], ax + mov spint_bx[si], bx + mov spint_cx[si], cx + mov spint_dx[si], dx + + mov spint_si[si], si + mov spint_di[si], di + + mov spint_cs[si], cs + mov spint_ds[si], ds + mov spint_es[si], es + mov spint_ss[si], ss + ; now, need to do SI, DS + mov ax, old_si + mov spint_si[si], ax + mov ax, old_ds + mov spint_ds[si], ax + ENDM + + +_TEXT segment byte public 'CODE' +_TEXT ends + +_DATA segment word public 'DATA' +_DATA ends + +CONST segment word public 'CONST' +CONST ends + +_BSS segment word public 'BSS' +_BSS ends + +DGROUP group CONST, _BSS, _DATA + + assume cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP + +_TEXT segment + +start_sp dw 1 dup (?) ; For use in our 'longjmp' +start_ss dw 1 dup (?) ; For use in our 'longjmp' + +spint_segment dw 1 dup (?) ; Segment of spawn control block +spint_offset dw 1 dup (?) ; Offset of spawn control block + +old_si dw 1 dup (?) ; SI of interrupt issuer (temporary) +old_ds dw 1 dup (?) ; DS of interrupt issuer (temporary) + +issuer_ss dw 1 dup (?) ; ss of person who called us (permanent) +issuer_sp dw 1 dup (?) ; sp of person who called us (permanent) + +int21_stack db 100 dup (?) ; Stack for int21. + +; +; _spint_int gets control on an interrupt. It switches the stack +; and does a 'return' from _spint_start. +; + public __spint_int + +__spint_int proc near + mov cs:issuer_sp, sp + mov cs:issuer_ss, ss + sti + + SETREGS + + LEAVE +__spint_int endp + +; +; _spint_start issues the dos interrupt after setting up the passed +; registers. When control returns to it, it sets spint->done to non-zero. +; + public __spint_start + +__spint_start proc near + ENTER + + GETREGS 4[bp] + + ; Now, switch to a different (short) stack. This is so + ; that our games won't mess up the stack int 21 (hardware and, + ; possibly, software) stores things on. + + cli + mov cs:int21_stack, cs + mov ss, cs:int21_stack + mov sp, offset int21_stack + add sp, (length int21_stack) - 4 + sti + + int 21H ; Issue DOS interrupt + + SETREGS + + mov ds, cs:spint_segment + mov si, cs:spint_offset + mov spint_done[si], 1 ; We are done + + LEAVE +__spint_start endp + +; +; After _spint_int has faked a return from start_spawn, we come here to +; return to the interrupt issuer. +; + public __spint_continue + +__spint_continue proc near + ENTER + + GETREGS 4[bp] + + mov sp, cs:issuer_sp ; Restore SP + mov ss, cs:issuer_ss ; Restore SS + + iret +__spint_continue endp + +_TEXT ends + + end diff --git a/usr.bin/tn3270/distribution/sys_dos/spintc.c b/usr.bin/tn3270/distribution/sys_dos/spintc.c new file mode 100644 index 0000000..aa16405 --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/spintc.c @@ -0,0 +1,186 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)spintc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> +#include <dos.h> +#include <stdlib.h> + +#include "../general/general.h" +#include "spint.h" + +#define PSP_ENVIRONMENT 0x2c +#define PSP_FCB1 0x5c +#define PSP_FCB2 0x6c + +typedef struct { + int + environment, /* Segment address of environment */ + cmd_ptr_offset, /* Offset of command to execute */ + cmd_ptr_segment, /* Segment where command lives */ + fcb1_ptr_offset, /* Offset of FCB 1 */ + fcb1_ptr_segment, /* Segment of FCB 1 */ + fcb2_ptr_offset, /* Offset of FCB 2 */ + fcb2_ptr_segment; /* Segment of FCB 2 */ +} ExecList; + + +static int int_offset, int_segment; + + +void +spint_finish(spint) +Spint *spint; +{ + union REGS regs; + struct SREGS sregs; + + if (spint->done == 0) { + return; /* Not done yet */ + } + + /* + * Restore old interrupt handler. + */ + + regs.h.ah = 0x25; + regs.h.al = spint->int_no; + regs.x.dx = int_offset; + sregs.ds = int_segment; + intdosx(®s, ®s, &sregs); + + if (spint->regs.x.cflag) { + fprintf(stderr, "0x%x return code from EXEC.\n", spint->regs.x.ax); + spint->done = 1; + spint->rc = 99; + return; + } + + regs.h.ah = 0x4d; /* Get return code */ + + intdos(®s, ®s); + + spint->rc = regs.x.ax; +} + +void +spint_continue(spint) +Spint *spint; +{ + _spint_continue(spint); /* Return to caller */ + spint_finish(spint); +} + + +void +spint_start(command, spint) +char *command; +Spint *spint; +{ + ExecList mylist; + char *comspec; + void _spint_int(); + union REGS regs; + struct SREGS sregs; + + /* + * Get comspec. + */ + comspec = getenv("COMSPEC"); + if (comspec == 0) { /* Can't find where command.com is */ + fprintf(stderr, "Unable to find COMSPEC in the environment."); + spint->done = 1; + spint->rc = 99; /* XXX */ + return; + } + + /* + * Now, hook up our interrupt routine. + */ + + regs.h.ah = 0x35; + regs.h.al = spint->int_no; + intdosx(®s, ®s, &sregs); + + /* Save old routine */ + int_offset = regs.x.bx; + int_segment = sregs.es; + + regs.h.ah = 0x25; + regs.h.al = spint->int_no; + regs.x.dx = (int) _spint_int; + segread(&sregs); + sregs.ds = sregs.cs; + intdosx(®s, ®s, &sregs); + + /* + * Read in segment registers. + */ + + segread(&spint->sregs); + + /* + * Set up registers for the EXEC call. + */ + + spint->regs.h.ah = 0x4b; + spint->regs.h.al = 0; + spint->regs.x.dx = (int) comspec; + spint->sregs.es = spint->sregs.ds; /* Superfluous, probably */ + spint->regs.x.bx = (int) &mylist; + + /* + * Set up EXEC parameter list. + */ + + ClearElement(mylist); + mylist.cmd_ptr_offset = (int) command; + mylist.cmd_ptr_segment = spint->sregs.ds; + mylist.fcb1_ptr_offset = PSP_FCB1; + mylist.fcb1_ptr_segment = _psp; + mylist.fcb2_ptr_offset = PSP_FCB2; + mylist.fcb2_ptr_segment = _psp; + mylist.environment = *((int far *)(((long)_psp<<16)|PSP_ENVIRONMENT)); + + /* + * Call to assembly language routine to actually set up for + * the spint. + */ + + _spint_start(spint); + + spint_finish(spint); +} diff --git a/usr.bin/tn3270/distribution/sys_dos/support.asm b/usr.bin/tn3270/distribution/sys_dos/support.asm new file mode 100644 index 0000000..a51c41d --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/support.asm @@ -0,0 +1,60 @@ +; 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. 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. +; +; @(#)support.asm 8.1 (Berkeley) 6/6/93 +; + +_TEXT segment byte public 'CODE' +_TEXT ends + +_DATA segment word public 'DATA' +_DATA ends + +CONST segment word public 'CONST' +CONST ends + +_BSS segment word public 'BSS' +_BSS ends + +DGROUP group CONST, _BSS, _DATA + + assume cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP + +_TEXT segment + public _iret_subr + +_iret_subr proc far + iret +_iret_subr endp + +_TEXT ends + + end diff --git a/usr.bin/tn3270/distribution/sys_dos/system.c b/usr.bin/tn3270/distribution/sys_dos/system.c new file mode 100644 index 0000000..864926b --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/system.c @@ -0,0 +1,140 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> + +#include "../general/general.h" +#include "../ctlr/api.h" +#include "spint.h" + +#include "../general/globals.h" + + +static Spint spinted; +static char command[256]; +static int need_to_start = 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() +{ + /* + * spint_start() returns when either the command has finished, or when + * the required interrupt comes in. In the latter case, the appropriate + * thing to do is to process the interrupt, and then return to + * the interrupt issuer by calling spint_continue(). + */ + if (need_to_start) { + need_to_start = 0; + spint_start(command, &spinted); + } + + if (spinted.done == 0) { + /* Process request */ + handle_api(&spinted.regs, &spinted.sregs); + spint_continue(&spinted); + } else { + char inputbuffer[100]; + + if (spinted.rc != 0) { + fprintf(stderr, "Process generated a return code of 0x%x.\n", + spinted.rc); + } + printf("[Hit return to continue]"); + fflush(stdout); + (void) gets(inputbuffer); + shell_active = 0; + setconnmode(); + ConnectScreen(); + } + return shell_active; +} + + +/* + * Called from telnet.c to fork a lower command.com. We + * use the spint... routines so that we can pick up + * interrupts generated by application programs. + */ + + +int +shell(argc,argv) +int argc; +char *argv[]; +{ + + ClearElement(spinted); + spinted.int_no = API_INTERRUPT_NUMBER; + if (argc == 1) { + command[0] = 0; + } else { + char *cmdptr; + int length; + + argc--; + argv++; + strcpy(command, " /c"); + cmdptr = command+strlen(command); + while (argc) { + if ((cmdptr+strlen(*argv)) >= (command+sizeof command)) { + fprintf(stderr, "Argument list too long at argument *%s*.\n", + *argv); + return 0; + } + *cmdptr++ = ' '; /* Blank separators */ + strcpy(cmdptr, *argv); + cmdptr += strlen(cmdptr); + argc--; + argv++; + } + length = strlen(command)-1; + if (length < 0) { + length = 0; + } + command[0] = length; + } + need_to_start = 1; + shell_active = 1; + return 1; /* Go back to main loop */ +} diff --git a/usr.bin/tn3270/distribution/sys_dos/termout.c b/usr.bin/tn3270/distribution/sys_dos/termout.c new file mode 100644 index 0000000..0339072 --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/termout.c @@ -0,0 +1,514 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)termout.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> +#include <dos.h> +#include "../general/general.h" + +#include "../telnet.ext" + +#include "../api/disp_asc.h" +#include "../ascii/map3270.ext" + +#include "../ctlr/hostctlr.h" +#include "../ctlr/externs.h" +#include "../ctlr/declare.h" +#include "../ctlr/oia.h" +#include "../ctlr/screen.h" + +#include "../general/globals.h" + +#include "video.h" + +extern void EmptyTerminal(); + +#define CorrectTerminalCursor() ((TransparentClock == OutputClock)? \ + terminalCursorAddress: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 needToRing; /* need to ring terinal bell */ + +typedef struct { + char + data, /* The data for this position */ + attr; /* The attributes for this position */ +} ScreenBuffer; + +ScreenBuffer Screen[MAXNUMBERLINES*MAXNUMBERCOLUMNS]; +ScreenBuffer saveScreen[sizeof Screen/sizeof Screen[0]]; + +/* OurExitString - designed to keep us from going through infinite recursion */ + +static void +OurExitString(file, string, value) +FILE *file; +char *string; +int value; +{ + static int recursion = 0; + + if (!recursion) { + recursion = 1; + ExitString(file, string, value); + } +} + + +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(stderr, foo, 1); + /* NOTREACHED */ +} + +/* + * Routines to deal with the screen. These routines are lifted + * from mskermit. + */ + +#define CRT_STATUS 0x3da /* Color card */ +#define DISPLAY_ENABLE 0x08 /* Enable */ +#define scrseg() ((crt_mode == 7)? 0xb000 : 0xb800) +#define scrwait() if (crt_mode != 7) { \ + while ((inp(CRT_STATUS)&DISPLAY_ENABLE) == 0) { \ + ; \ + } \ + } +static int + crt_mode, + crt_cols, + crt_lins, + curpage; + +/* + * Set the cursor position to where it belongs. + */ + +static void +setcursor(row, column, page) +int + row, + column, + page; +{ + union REGS inregs, outregs; + + inregs.h.dh = row; + inregs.h.dl = column; + inregs.h.bh = page; + inregs.h.ah = SetCursorPosition; + + int86(BIOS_VIDEO, &inregs, &outregs); +} +/* + * Read the state of the video system. Put the cursor somewhere + * reasonable. + */ + +static void +scrini() +{ + union REGS inregs, outregs; + + inregs.h.ah = CurrentVideoState; + int86(BIOS_VIDEO, &inregs, &outregs); + + crt_mode = outregs.h.al; + crt_cols = outregs.h.ah; + crt_lins = 25; + curpage = outregs.h.bh; + + inregs.h.ah = ReadCursorPosition; + inregs.h.bh = curpage; + + int86(BIOS_VIDEO, &inregs, &outregs); + + if (outregs.h.dh > crt_lins) { + outregs.h.dh = crt_lins; + } + if (outregs.h.dl > crt_cols) { + outregs.h.dl = crt_cols; + } + inregs.h.dh = outregs.h.dh; + inregs.h.dl = outregs.h.dl; + inregs.h.bh = curpage; + + inregs.h.ah = SetCursorPosition; + int86(BIOS_VIDEO, &inregs, &outregs); +} + + +static void +scrwrite(source, length, offset) +ScreenBuffer *source; +int + length, + offset; +{ + struct SREGS segregs; + + segread(&segregs); /* read the current segment register */ + + scrwait(); + movedata(segregs.ds, source, scrseg(), sizeof *source*offset, + sizeof *source*length); +} + +static void +scrsave(buffer) +ScreenBuffer *buffer; +{ + struct SREGS segregs; + + segread(&segregs); /* read the current segment register */ + + scrwait(); + movedata(scrseg(), 0, segregs.ds, buffer, crt_cols*crt_lins*2); +} + +static void +scrrest(buffer) +ScreenBuffer *buffer; +{ + scrwrite(buffer, crt_cols*crt_lins, 0); +} + +static void +TryToSend() +{ +#define STANDOUT 0x0a /* Highlighted mode */ +#define NORMAL 0x02 /* Normal mode */ +#define NONDISPLAY 0x00 /* Don't display */ + +#define DoAttribute(a) \ + if (screenIsFormatted) { \ + if (IsNonDisplayAttr(a)) { \ + a = NONDISPLAY; /* don't display */ \ + } else if (IsHighlightedAttr(a)) { \ + a = STANDOUT; \ + } else { \ + a = NORMAL; \ + } \ + } else { \ + a = NORMAL; /* do display on unformatted */\ + } + ScreenImage *p, *upper; + ScreenBuffer *sp; + int fieldattr; /* spends most of its time == 0 or 1 */ + int screenIsFormatted = FormattedScreen(); + +/* 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())) { + sp = &Screen[Lowest]; + p = &Host[Lowest]; + upper = &Host[Highest]; + fieldattr = FieldAttributes(Lowest); + DoAttribute(fieldattr); /* Set standout, non-display status */ + + while (p <= upper) { + if (IsStartFieldPointer(p)) { /* New field? */ + Highest = HighestScreen(); + Lowest = LowestScreen(); + TryToSend(); /* Recurse */ + return; + } else if (fieldattr) { /* Should we display? */ + /* Display translated data */ + sp->data = disp_asc[GetHostPointer(p)]; + } else { + sp->data = ' '; + } + sp->attr = fieldattr; + p++; + sp++; + } + } else { /* Going from Lowest to Highest */ + ScreenImage *End = &Host[ScreenSize]-1; + + sp = Screen; + p = Host; + fieldattr = FieldAttributes(LowestScreen()); + DoAttribute(fieldattr); /* Set standout, non-display status */ + + while (p <= End) { + if (IsStartFieldPointer(p)) { /* New field? */ + fieldattr = FieldAttributesPointer(p); /* Get attributes */ + DoAttribute(fieldattr); /* Set standout, non-display */ + } + if (fieldattr) { /* Should we display? */ + /* Display translated data */ + sp->data = disp_asc[GetHostPointer(p)]; + } else { + sp->data = ' '; + } + sp->attr = fieldattr; + p++; + sp++; + } + } + terminalCursorAddress = CorrectTerminalCursor(); + /* + * We might be here just to update the cursor address. + */ + if (Highest >= Lowest) { + scrwrite(Screen+Lowest, (1+Highest-Lowest), Lowest); + } + setcursor(ScreenLine(terminalCursorAddress), + ScreenLineOffset(terminalCursorAddress), 0); + Lowest = HighestScreen()+1; + Highest = LowestScreen()-1; + if (needToRing) { + DataToTerminal("\7", 1); + needToRing = 0; + } + return; +} + +/* InitTerminal - called to initialize the screen, etc. */ + +void +InitTerminal() +{ + InitMapping(); /* Go do mapping file (MAP3270) first */ + if (!screenInitd) { /* not initialized */ + MaxNumberLines = 24; /* XXX */ + MaxNumberColumns = 80; /* XXX */ + scrini(); + scrsave(saveScreen); /* Save the screen buffer away */ + ClearArray(Screen); + terminalCursorAddress = SetBufferAddress(0,0); + screenInitd = 1; + screenStopped = 0; /* Not stopped */ + } +} + + +/* StopScreen - called when we are going away... */ + +void +StopScreen(doNewLine) +int doNewLine; +{ + if (screenInitd && !screenStopped) { + scrrest(saveScreen); + setcursor(NumberLines-1, 1, 0); + if (doNewLine) { + StringToTerminal("\r\n"); + } + EmptyTerminal(); + screenStopped = 1; + } +} + + +/* RefreshScreen - called to cause the screen to be refreshed */ + +void +RefreshScreen() +{ + Highest = HighestScreen(); + Lowest = LowestScreen(); + TryToSend(); +} + + +/* ConnectScreen - called to reconnect to the screen */ + +void +ConnectScreen() +{ + if (screenInitd) { + RefreshScreen(); + screenStopped = 0; + } +} + +/* LocalClearScreen() - clear the whole ball of wax, cheaply */ + +void +LocalClearScreen() +{ + Clear3270(); + Lowest = LowestScreen(); /* everything in sync... */ + Highest = HighestScreen(); + TryToSend(); +} + +/* + * Implement the bell/error message function. + */ + +int + bellwinup = 0; /* If != 0, length of bell message */ +static int + bell_len = 0; /* Length of error message */ + + +void +BellOff() +{ + ScreenBuffer a[100]; + int i; + + if (bellwinup) { + unsigned char blank = ' '; + + for (i = 0; i < bell_len; i++) { + a[i].attr = NORMAL; + a[i].data = ' '; + } + } + scrwrite(a, bell_len, 24*80); /* XXX */ +} + + +void +RingBell(s) +char *s; +{ + needToRing = 1; + if (s) { + int i; + ScreenBuffer bellstring[100]; + + bell_len = strlen(s); + bellwinup = 1; + if (bell_len > sizeof bellstring-1) { + OurExitString(stderr, "Bell string too long.", 1); + } + for (i = 0; i < bell_len; i++) { + bellstring[i].attr = STANDOUT; + bellstring[i].data = s[i]; + } + scrwrite(bellstring, bell_len, 24*80); /* XXX */ + } +} + +/* + * Update the OIA area. + */ + +void +ScreenOIA(oia) +OIA *oia; +{ +} + + +/* 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() +{ + 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 */ +{ + char *ptr; + + while (DoTerminalOutput() == 0) { + ; + } + for (ptr = buffer; ptr < buffer+count; ptr++) { + *ptr &= 0x7f; /* Turn off parity bit */ + } + (void) DataToTerminal(buffer, count); + if (control && (kind == 0)) { /* Send in AID byte */ + SendToIBM(); + } else { + TransInput(1, kind); /* Go get some data */ + } +} + +/* + * init_screen() + * + * Initialize variables used by screen. + */ + +void +init_screen() +{ + bellwinup = 0; +} + + diff --git a/usr.bin/tn3270/distribution/sys_dos/termout.ext b/usr.bin/tn3270/distribution/sys_dos/termout.ext new file mode 100644 index 0000000..d3c8fb4 --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/termout.ext @@ -0,0 +1,47 @@ +/*- + * 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. 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. + * + * @(#)termout.ext 8.1 (Berkeley) 6/6/93 + */ + +extern void + StartScreen(), + StopScreen(), + ConnectScreen(), + ClearScreen(), + LocalClearScreen(), + RefreshScreen(), + RingBell(), + AddHost(); + +extern int + DoTerminalOutput(); diff --git a/usr.bin/tn3270/distribution/sys_dos/video.h b/usr.bin/tn3270/distribution/sys_dos/video.h new file mode 100644 index 0000000..8fffe6c --- /dev/null +++ b/usr.bin/tn3270/distribution/sys_dos/video.h @@ -0,0 +1,75 @@ +/*- + * 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. 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. + * + * @(#)video.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * This is a header file describing the interface via int 10H to the + * video subsystem. + */ + +#define BIOS_VIDEO 0x10 + +typedef enum { + SetMode = 0, + SetCursorType, + SetCursorPosition, + ReadCursorPosition, + ReadLightPenPosition, + SelectActiveDisplayPage, + ScrollActivePageUp, + ScrollActivePageDown, + ReadAttribute_Character, + WriteAttribute_Character, + WriteCharacterOnly, + SetColorPalette, + WriteDot, + ReadDot, + WriteTeletypeToActivePage, + CurrentVideoState, + Reserved16, + Reserved17, + Reserved18, + WriteString +} VideoOperationsType; + +typedef enum { + bw_40x25 = 0, + color_40x25, + bw_80x25, + color_80x25, + color_320x200, + bw_320x200, + bw_640x200, + internal_bw_80x25 +} VideoModeType; diff --git a/usr.bin/tn3270/distribution/telnet/Makefile_ultrix b/usr.bin/tn3270/distribution/telnet/Makefile_ultrix new file mode 100644 index 0000000..dbb93ea --- /dev/null +++ b/usr.bin/tn3270/distribution/telnet/Makefile_ultrix @@ -0,0 +1,179 @@ +# @(#)Makefile 1.4 (Berkeley) 5/15/88 + +# This is the makefile for an Ultrix system. The current Ultrix make(1) doesn't +# support VPATH, so we expand everything out. + +# The following is the telnet makefile for tn3270, using the shared telnet +# sources. + +# +# TERMCAP Define this if your system is termcap based, +# otherwise a terminfo based system is assumed. +# +# SRCRT Includes code to allow you to specify source routes. +# Format is: +# [!]@hop1@hop2...[@|:]dst +# Leading ! means strict source route. +# +# NOSTRNCASECMP Define this if you do not have strncasecmp() in +# your C libarary. +# +# USE_TERMIO Define this if you have System V termio structures. +# What is here is how things are on Cray computers. +# +# KLUDGELINEMODE Define this to get the kludged up version of linemode +# that was in 4.3BSD. This is a good thing to have +# around for talking to older systems. +# + +DEFINES= -DTERMCAP -DSRCRT -DKLUDGELINEMODE + + +VPATH = ../../telnet/Source +XINCLUDES= -I../../telnet/Source +INCLUDES= -I. +XDEFINES = -DTN3270 +OPTIMIZE= -O +CFLAGS = ${OPTIMIZE} ${INCLUDES} ${DEFINES} +XCFLAGS= ${XINCLUDES} ${XDEFINES} +LD = ld +LDFLAGS = -r +PRINT = print +ACTION = sccs tell +LIBC= /lib/libc.a +SD= ../../telnet/Source/ +ALLH= ${SD}defines.h ${SD}externs.h ${SD}fdset.h ${SD}general.h ${SD}ring.h ${SD}types.h +SRCS= ${SD}commands.c ${SD}main.c ${SD}network.c ${SD}ring.c \ + ${SD}sys_bsd.c ${SD}sys_dos.c ${SD}telnet.c ${SD}terminal.c \ + ${SD}tn3270.c ${SD}utilities.c +ALLHC= ${ALLH} ${SRCS} +ALLPRINT = ${ALLHC} +ALLSOURCE= ${ALLHC} Makefile Makefile_ultrix +OBJS= commands.o main.o network.o ring.o sys_bsd.o sys_dos.o \ + telnet.o terminal.o tn3270.o utilities.o + +.c.o: + ${CC} -c ${CFLAGS} ${XCFLAGS} $< + +telprog.o: ${OBJS} ${LIBC} + ${LD} ${LDFLAGS} -o $@ ${OBJS} + +clean: FRC + rm -f ${OBJS} core telnet + +depend: FRC ${SRCS} + mkdep ${CFLAGS} ${SRCS} + +lint: FRC ${SRCS} + lint ${CFLAGS} ${SRCS} + +tags: FRC ${ALLHC} + ctags ${ALLHC} + +print: FRC ${ALLPRINT} + ${PRINT} ${ALLPRINT} + +commands.o: ${SD}commands.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}commands.c + +main.o: ${SD}main.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}main.c + +network.o: ${SD}network.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}network.c + +ring.o: ${SD}ring.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}ring.c + +sys_bsd.o: ${SD}sys_bsd.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}sys_bsd.c + +sys_dos.o: ${SD}sys_dos.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}sys_dos.c + +telnet.o: ${SD}telnet.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}telnet.c + +terminal.o: ${SD}terminal.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}terminal.c + +tn3270.o: ${SD}tn3270.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}tn3270.c + +utilities.o: ${SD}utilities.c + ${CC} -c ${CFLAGS} ${XCFLAGS} ${SD}utilities.c + + +action: FRC + ${ACTION} + +clist: FRC ${SRCS} + @for i in ${SRCS} ; \ + do (echo ${DIRPATH}$$i); done + +hclist: FRC ${ALLHC} + @for i in ${ALLHC} ; \ + do (echo ${DIRPATH}$$i); done + +sourcelist: FRC ${ALLSOURCE} + @for i in ${ALLSOURCE} ../../telnet/Makefile ; \ + do (echo ${DIRPATH}$$i); done + +FRC: + +# DO NOT DELETE THIS LINE -- mkdep uses it. +# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. + +commands.o: ../../telnet/Source/commands.c /usr/include/sys/types.h +commands.o: /usr/include/sys/socket.h /usr/include/netinet/in.h +commands.o: /usr/include/signal.h /usr/include/machine/trap.h +commands.o: /usr/include/netdb.h /usr/include/ctype.h +commands.o: /usr/include/arpa/telnet.h ../../telnet/Source/ring.h +commands.o: ../../telnet/Source/externs.h /usr/include/stdio.h +commands.o: /usr/include/setjmp.h ../../telnet/Source/defines.h +commands.o: ../../telnet/Source/types.h +main.o: ../../telnet/Source/main.c /usr/include/sys/types.h +main.o: ../../telnet/Source/ring.h ../../telnet/Source/externs.h +main.o: /usr/include/stdio.h /usr/include/setjmp.h +main.o: ../../telnet/Source/defines.h +network.o: ../../telnet/Source/network.c /usr/include/sys/types.h +network.o: /usr/include/sys/socket.h /usr/include/sys/time.h +network.o: /usr/include/time.h /usr/include/errno.h /usr/include/arpa/telnet.h +network.o: ../../telnet/Source/ring.h ../../telnet/Source/defines.h +network.o: ../../telnet/Source/externs.h /usr/include/stdio.h +network.o: /usr/include/setjmp.h ../../telnet/Source/fdset.h +ring.o: ../../telnet/Source/ring.c /usr/include/stdio.h /usr/include/errno.h +ring.o: /usr/include/sys/types.h /usr/include/sys/ioctl.h +ring.o: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h +ring.o: /usr/include/sys/socket.h ../../telnet/Source/ring.h +ring.o: ../../telnet/Source/general.h +sys_bsd.o: ../../telnet/Source/sys_bsd.c /usr/include/sys/ioctl.h +sys_bsd.o: /usr/include/sys/ttychars.h /usr/include/sys/ttydev.h +sys_bsd.o: /usr/include/sys/types.h /usr/include/sys/time.h /usr/include/time.h +sys_bsd.o: /usr/include/sys/socket.h /usr/include/signal.h +sys_bsd.o: /usr/include/machine/trap.h /usr/include/errno.h +sys_bsd.o: ../../telnet/Source/ring.h ../../telnet/Source/fdset.h +sys_bsd.o: ../../telnet/Source/defines.h ../../telnet/Source/externs.h +sys_bsd.o: /usr/include/stdio.h /usr/include/setjmp.h +sys_bsd.o: ../../telnet/Source/types.h +sys_dos.o: ../../telnet/Source/sys_dos.c +telnet.o: ../../telnet/Source/telnet.c /usr/include/sys/types.h +telnet.o: /usr/include/curses.h /usr/include/stdio.h /usr/include/sgtty.h +telnet.o: /usr/include/sys/ioctl.h /usr/include/sys/ttychars.h +telnet.o: /usr/include/sys/ttydev.h /usr/include/arpa/telnet.h +telnet.o: /usr/include/strings.h ../../telnet/Source/ring.h +telnet.o: ../../telnet/Source/defines.h ../../telnet/Source/externs.h +telnet.o: /usr/include/stdio.h /usr/include/setjmp.h +telnet.o: ../../telnet/Source/types.h ../../telnet/Source/general.h +telnet.o: /usr/include/varargs.h +terminal.o: ../../telnet/Source/terminal.c /usr/include/arpa/telnet.h +terminal.o: /usr/include/sys/types.h ../../telnet/Source/ring.h +terminal.o: ../../telnet/Source/externs.h /usr/include/stdio.h +terminal.o: /usr/include/setjmp.h ../../telnet/Source/types.h +tn3270.o: ../../telnet/Source/tn3270.c ../../telnet/Source/fdset.h +utilities.o: ../../telnet/Source/utilities.c /usr/include/arpa/telnet.h +utilities.o: /usr/include/sys/types.h /usr/include/ctype.h +utilities.o: ../../telnet/Source/ring.h ../../telnet/Source/externs.h +utilities.o: /usr/include/stdio.h /usr/include/setjmp.h + +# IF YOU PUT ANYTHING HERE IT WILL GO AWAY diff --git a/usr.bin/tn3270/distribution/ultrix.curses b/usr.bin/tn3270/distribution/ultrix.curses new file mode 100644 index 0000000..f5fcd94 --- /dev/null +++ b/usr.bin/tn3270/distribution/ultrix.curses @@ -0,0 +1,46 @@ +Return-Path: mtxinu!kinetics!minshall@ucbvax.Berkeley.EDU +Received: from ucbvax.berkeley.edu + by violet.berkeley.edu (5.54 (CFC 4.22.3)/1.16.17l) + id AA23846; Wed, 30 Mar 88 19:54:24 PST +Received: by ucbvax.berkeley.edu (5.59/1.26) + id AA09851; Tue, 29 Mar 88 23:25:19 PST +Received: by mtxinu.UUCP (5.51/4.7) + id AA05135; Tue, 29 Mar 88 17:32:01 PST +Message-Id: <8803300132.AA05135@mtxinu.UUCP> +Date: Thu, 17 Mar 88 11:06:10 pst +From: mtxinu!kinetics!minshall@ucbvax.Berkeley.EDU (Greg Minshall) +To: mtxinu!minshall + +Path: kinetics!zehntel!varian!ptsfa!pacbell!ames!ll-xn!husc6!panda!teddy!jpn +From: jpn@teddy.UUCP (John P. Nelson) +Newsgroups: comp.bugs.4bsd +Subject: Re: Ultrix curses problem +Keywords: curses ultrix bug fix +Message-ID: <4668@teddy.UUCP> +Date: 14 Mar 88 19:43:39 GMT +References: <535@hscfvax.harvard.edu> +Reply-To: jpn@teddy.UUCP (John P. Nelson) +Organization: GenRad, Inc., Concord, Mass. +Lines: 21 + +>I have found the bug, fixable as above, in both Ultrix 1.2 and 2.0. Feedback +>from those brave souls who have brought up 2.2 would be most welcome. + +Yup, the bug exists in Ultrix 2.2 as well. I have reported this bug to +DEC support every time we get a new release. I assume that my bug reports +are getting filed (in the circular file). + +It is clear that whoever made this "fix" at DEC had no understanding +of curses whatsoever. As in the earlier posting, the bug can be fixed +by replacing the definitions of the nl() and nonl() macros in curses.h with: + +#define nl() (_tty.sg_flags |= CRMOD,_pfast = _rawmode,stty(_tty_ch, &_tty)) +#define nonl() (_tty.sg_flags &= ~CRMOD, _pfast = TRUE, stty(_tty_ch, &_tty)) + +- john nelson. + +P.S. I did reach someone at DEC who would listen (Thanks Chet!) My + understanding is that they have no plans to fix this bug, as curses + is now "owned" by some group in England, who is working on a port of the + terminfo curses for Ultrix 2.4. I'm just pissed that my bug reports + submitted for Ultrix 1.2 and 2.0 were ignored. diff --git a/usr.bin/tn3270/distribution/utilities/adm3a.keys b/usr.bin/tn3270/distribution/utilities/adm3a.keys new file mode 100644 index 0000000..4e65374 --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/adm3a.keys @@ -0,0 +1,78 @@ +1LSI ADM 3A Key Definitions for IBM 3277 Terminal Emulation 06/18/81 ++LSI ADM 3A Key Definitions for IBM 3277 Terminal Emulation 06/18/81 + + 3277 Key ADM Key(s) | 3277 Key LSI ADM 3A Key(s) + ======== ========== | ======== ==================== + | + Cursor Movement Keys | Command Keys ++______ ________ ____ _______ ____ + | + New Line Ctrl-N -or- | Enter Return + Home | Clear Ctrl-Z + Tab Ctrl-I | + Back Tab Ctrl-B | Program Function Keys ++ _______ ________ ____ + Cursor Left Ctrl-H | + Cursor Right Ctrl-L | PF1 Esc 1 + Cursor Up Ctrl-K | PF2 Esc 2 + Cursor Down Ctrl-J -or- | PF3 Esc 3 + Line Feed | PF4 Esc 4 + Home Ctrl-@ | PF5 Esc 5 + | PF6 Esc 6 + | PF7 Esc 7 + Edit Control Keys | PF8 Esc 8 ++____ _______ ____ + | PF9 Esc 9 + Delete Char Ctrl-D -OR- Rub | PF10 Esc 0 + Erase EOF Ctrl-E | PF11 Esc Colon + Erase Input Ctrl-W | PF12 Esc Minus + Insert Mode Esc Space | PF13 Ctrl-F 1 3 + End Insert Esc Space | PF14 Ctrl-F 1 4 + Dup Ctrl-U | PF15 Ctrl-F 1 5 + Field Mark Ctrl-Y | PF16 Ctrl-F 1 6 + | PF17 Ctrl-F 1 7 + Series-1 Control Keys | PF18 Ctrl-F 1 8 ++________ _______ ____ + | PF19 Ctrl-F 1 9 + Reset After Error Ctrl-R | PF20 Ctrl-F 2 0 + Keyboard Unlock Ctrl-T | PF21 Ctrl-F 2 1 + Purge Input Buffer Ctrl-X | PF22 Ctrl-F 2 2 + Stop Output Ctrl-S | PF23 Ctrl-F 2 3 + Start Output Ctrl-Q | PF24 Ctrl-F 2 4 + Re-Display Screen Ctrl-V | + | Program Attention Keys ++ _______ _________ ____ + Miscellaneous 3277 Keys | ++_____________ ____ ____ + | PA1 Ctrl-P 1 + Cursor Select Esc Period | PA2 Ctrl-P 2 + Test Request (not supported) | PA3 Ctrl-P 3 + + Series 1 Local Editing Keys ++______ _ _____ _______ ____ + + Set Tab Stop Esc Semicolon + Clear (all) Tab Stops Esc Plus + Set Left Margin (New Line) Esc LeftParen + Set Home (Home) Esc Exclamation + Tab to Next Local Tab Stop Esc i (or Esc I) + Tab to Previous Local Tab Stop Esc b (or Esc B) + Indent (to Next Local Tab Stop - New Line) Esc l (or Esc L) + Undent (to Previous Local Tab Stop - New Line) Esc h (or Esc H) + + + Note: If the terminal hangs up, enter "Ctrl-H" and see if the + cursor moves. If it does, you are trying to enter data + into a protected field, trying to insert a character when + the last character of the field is non-blank, or trying to + communicate to a virtual process which is not accepting data. + If the cursor did not move, a transmission error or terminal + lock has occurred. Enter the following sequence to unhang + the terminal: "Ctrl-R Ctrl-T Ctrl-X Ctrl-Q Ctrl-V". + + ********** DRAFT ONLY - SPECIFICATION SUBJECT TO CHANGE ********** ++********** DRAFT ONLY - SPECIFICATION SUBJECT TO CHANGE ********** ++********** DRAFT ONLY - SPECIFICATION SUBJECT TO CHANGE ********** ++********** DRAFT ONLY - SPECIFICATION SUBJECT TO CHANGE ********** + + diff --git a/usr.bin/tn3270/distribution/utilities/cross.c b/usr.bin/tn3270/distribution/utilities/cross.c new file mode 100644 index 0000000..191aac0 --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/cross.c @@ -0,0 +1,55 @@ +/* + This program is, essentially, a cross product generator. It takes + an input file which is said to consist of a number of lines, and + expands each line. A line like + (a,b)(c,d) + will be expanded to lines like + ac + ad + bc + bd + (without regard for the ORDER of the output; ie: the lines can appear + in any order). + + Parenthesis can be nested, so + (a,b)(c(d,e),f) + will produce + acd + ace + af + bcd + bce + bf + */ + + +#include <stdio.h> + +char leftParen, /* The left parenthesis character */ + rightParen; /* The right parenthesis character */ + + +/* Finds next occurrence of 'character' at this level of nesting. + Returns 0 if no such character found. + */ + +char * +ThisLevel(string, character) +char *string, character; +{ + int level; /* Level 0 is OUR level */ + + level = 0; + + while (*string != '\0') { + if (*string == leftParen) + level++; + else if (*string == rightParen) { + level--; + if (level < 0) + return(0); + } + if ((level == 0) && (*string == character)) + return(string); + string++; + } diff --git a/usr.bin/tn3270/distribution/utilities/makefile b/usr.bin/tn3270/distribution/utilities/makefile new file mode 100644 index 0000000..0cb5b3e --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/makefile @@ -0,0 +1,121 @@ +# +# Copyright (c) 1988 Regents of the University of California. +# All rights reserved. +# +# Redistribution and use in source and binary forms are permitted +# provided that the above copyright notice and this paragraph are +# duplicated in all such forms and that any documentation, +# advertising materials, and other materials related to such +# distribution and use acknowledge that the software was developed +# by the University of California, Berkeley. The name of the +# University may not be used to endorse or promote products derived +# from this software without specific prior written permission. +# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +# WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. +# +# @(#)makefile 8.1 (Berkeley) 6/6/93 +# +# msdos versus unix defines +O = .o +#PC_O = .obj + +X = +#PC_X = .exe + +L = +#PC_L = -link + +CC = cc +#PC_CC = cl + +MV = mv +#PC_MV = rename + +RM = rm -f +#PC_RM= erase + +LINT_ARGS = +#PC_LINT_ARGS = -DLINT_ARGS + +DEBUG_FLAGS = -g +#PC_DEBUG_FLAGS = -Zi -Od + +AR = ar +AR1 = cr +AR2 = +AR3 = +#PC_AR = lib +#PC_AR1 = +#PC_AR2 = + +#PC_AR3 = ";" + +RANLIB = ranlib +#PC_RANLIB = echo "Done with " + +DEFINES = ${LINT_ARGS} + +CFLAGS = ${DEBUG_FLAGS} -I.. + +PRINT = lpr -p + +ALLC = tnrecv.c +ALLH = tncomp.h + +ALLPRINT = ${ALLH} ${ALLC} + +ALLSOURCE = ${ALLPRINT} makefile makefile.mak + +ALLO = tnrecv$O + +.c.obj: + ${CC} ${CFLAGS} -c $< + +all: tnrecv$X + +tnrecv$X: tnrecv$O + ${CC} ${CFLAGS} -o $@ tnrecv$O $L ../api/apilib.a + +clean: + for i in makefile.bak ${ALLO} errs tnrecv$X; \ + do (${RM} $$i); done + +.DEFAULT: + sccs get $< + +sccsclean: + -sccs clean + -sccs get makefile + +action: + ${ACTION} + +print: + ${PRINT} ${ALLPRINT} + +sourcelist: ${ALLSOURCE} tarread.exe + @for i in ${ALLSOURCE} tarread.exe; \ + do (echo ${DIRPATH}$$i); done + +depend: + grep '^#include' ${ALLC} | grep -v '<' | \ + sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' \ + -e 's/\.c/$$O/' | \ + awk ' { if ($$1 != prev) { print rec; rec = $$0; prev = $$1; } \ + else { if (length(rec $$2) > 78) { print rec; rec = $$0; } \ + else rec = rec " " $$2 } } \ + END { print rec } ' > makedep + echo '$$r makedep' >>eddep + echo '/^# DO NOT DELETE THIS LINE/+1,$$d' >eddep + echo '$$r makedep' >>eddep + echo 'w' >>eddep + -rm -f makefile.bak + cp makefile makefile.bak + ed - makefile < eddep + rm eddep makedep + +# DO NOT DELETE THIS LINE + +#include "tncomp.h" "../api/api.h" "../ctlr/function.h" "../ctlr/hostctlr.h" +#include "../ctlr/oia.h" "../ctlr/screen.h" "../apilib/disp_asc.h" +#include "../apilib/astosc.h" "../general/general.h" diff --git a/usr.bin/tn3270/distribution/utilities/srccmd/tar/makefile b/usr.bin/tn3270/distribution/utilities/srccmd/tar/makefile new file mode 100644 index 0000000..f4618af --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/srccmd/tar/makefile @@ -0,0 +1,8 @@ +tarread.obj: tarread.c + cl /c /Zd tarread.c + +tarread.exe: tarread.obj + link tarread,,tarread/map/lin; + +tarread.sym: tarread.map + mapsym /l tarread diff --git a/usr.bin/tn3270/distribution/utilities/srccmd/tar/tar.h b/usr.bin/tn3270/distribution/utilities/srccmd/tar/tar.h new file mode 100644 index 0000000..0345756 --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/srccmd/tar/tar.h @@ -0,0 +1,19 @@ +/* tar.h */ + +#define TBLOCK 512 +#define NAMSIZ 100 + +union hblock { + char dummy[TBLOCK]; + struct header { + char name[NAMSIZ]; + char mode[8]; + char gid[8]; + char uid[8]; + char size[12]; + char mtime[12]; + char chksum[8]; + char linkflag; + char linkname[NAMSIZ]; + } dbuf; +}; diff --git a/usr.bin/tn3270/distribution/utilities/srccmd/tar/tarread.c b/usr.bin/tn3270/distribution/utilities/srccmd/tar/tarread.c new file mode 100644 index 0000000..fedeb69 --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/srccmd/tar/tarread.c @@ -0,0 +1,208 @@ +/* tarread.c */ +/* Copyright (c) 1985, by Carnegie-Mellon University */ + +#include <stdio.h> +#include <v2tov3.h> +#include <sys\types.h> +#include <sys\stat.h> +#include "tar.h" + +char usage[] = "tarread: usage: tarread tx[vwz] tarfile\n"; +union hblock hbuf; + +int verbose = 0; +int confirm = 0; +int binary = 0; +char cmd; + +main(argc, argv) +int argc; +char *argv[]; +{ + FILE *fp; + char *cp; + + if (argc != 3) { + fprintf(stderr, usage); + exit(1); + } + + for (cp = argv[1]; *cp; cp++) + switch (*cp) { + case 't': + case 'x': + cmd = *cp; + break; + + case 'v': + verbose++; + break; + case 'z': + binary++; + break; + case 'w': + confirm++; + break; + default: + fprintf(stderr, "tarread: unknown switch %c\n", *cp); + fprintf(stderr, usage); + exit(1); + } + + if ((fp = fopen(argv[2], "rb")) == NULL) { + fprintf(stderr, "tarrread: cannot open %s\n", argv[2]); + exit(1); + } + + for (;;) { + if (fread(&hbuf, sizeof(hbuf), 1, fp) != 1) { + perror("fread"); + exit(1); + } + if (!proc_file(fp)) + break; + } +} + + +int proc_file(fp) +FILE *fp; +{ + char name[NAMSIZ]; + unsigned short mode; + short uid, gid; + long size, mtime; + char c; + int confrmd; + long skip; + + if (hbuf.dbuf.name[0] == '\0') + return (NULL); + + strcpy(name, hbuf.dbuf.name); + if (sscanf(hbuf.dbuf.mode, "%o", &mode) != 1) + fprintf("Couldn't read mode\n"); + if (sscanf(hbuf.dbuf.uid, "%o", &uid) != 1) + fprintf("Couldn't read uid\n"); + if (sscanf(hbuf.dbuf.gid, "%o", &gid) != 1) + fprintf("Couldn't read gid\n"); + if (sscanf(hbuf.dbuf.size, "%12lo %12lo", &size, &mtime) != 2) + fprintf("Couldn't read size or mtime\n"); + + skip = (size + TBLOCK - 1) / TBLOCK * TBLOCK; + + switch (cmd) { + case 't': + if (verbose) + printf("%8o %d/%d\t %6ld %.24s %s\n", mode, + uid, gid, size, ctime(&mtime), name); + else + printf("%s\n", name); + + break; + + case 'x': + if (verbose) + printf("x %s: ", name); + confrmd = 1; + + if (confirm) { + confrmd = 0; + if ((c = getchar()) == 'y') + confrmd++; + while (c != '\n') + c = getchar(); + if(!confrmd) + break; + } + + if(extract(name, size, mode, mtime, fp)) + skip = 0; + + if (verbose) + printf("\n"); + break; + } + if (fseek(fp, skip, 1)) { + perror("fseek"); + exit(1); + } + return (1); +} + + +int extract(fname, size, mode, mtime, ifp) +char *fname; +long size; +unsigned short mode; +long mtime; +FILE *ifp; +{ + FILE *ofp; + char fbuf[TBLOCK]; + long copied, left; + char *s, *np, *strchr(); + struct stat sbuf; + + for(np = fname; s = strchr(np, '/'); np = s+1) { + *s = '\0'; + if(stat(fname, &sbuf)) { + if(mkdir(fname)) + perror("mkdir"); + } else if(!(sbuf.st_mode & S_IFDIR)) { + fprintf(stderr, "\n%s: Not a directory", fname); + *s = '/'; + fprintf(stderr, "\ntar: %s - cannot create", fname); + return (0); + } + *s = '/'; + } + if(!*np) + return (0); + + if (binary) { + if ((ofp = fopen(fname, "wb")) == NULL) { + perror("extract:"); + return (0); + } + } else { + if ((ofp = fopen(fname, "w")) == NULL) { + perror("extract:"); + return (0); + } + } + + for(copied = 0; copied < size; copied += TBLOCK) { + if(fread(fbuf, TBLOCK, 1, ifp) != 1) { + perror("fread"); + exit(1); + } + left = size - copied; + if(fwrite(fbuf, (int)min(left, TBLOCK), 1, ofp) != 1) { + perror("fwrite"); + exit(1); + } + } + + if(fclose(ofp)) { + perror("fclose"); + exit(1); + } + + /* + * Now, set modification time. + */ + { +#include <sys\utime.h> + struct utimbuf utim; + + utim.modtime = mtime; + + if (utime(fname, &utim) == -1) { + perror("utime"); + exit(1); + } + } + + return (1); +} diff --git a/usr.bin/tn3270/distribution/utilities/tncomp.h b/usr.bin/tn3270/distribution/utilities/tncomp.h new file mode 100644 index 0000000..c726297 --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/tncomp.h @@ -0,0 +1,51 @@ +/*- + * 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. 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. + * + * @(#)tncomp.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Where the fields fall on the formatted screen used by tncomp, tnrecv, + * and tnsend. + */ + +#define SEND_SEQUENCE 1 +#define SEND_SEQUENCE_LENGTH 23 + +#define ACK_SEQUENCE (SEND_SEQUENCE+SEND_SEQUENCE_LENGTH+1) +#define ACK_SEQUENCE_LENGTH 22 + +#define CHECKSUM (ACK_SEQUENCE+ACK_SEQUENCE_LENGTH+1) +#define CHECKSUM_LENGTH 32 + +#define DATA (CHECKSUM+CHECKSUM_LENGTH+1) +#define DATA_LENGTH ((80*22)+79) diff --git a/usr.bin/tn3270/distribution/utilities/tnrecv.c b/usr.bin/tn3270/distribution/utilities/tnrecv.c new file mode 100644 index 0000000..4474691 --- /dev/null +++ b/usr.bin/tn3270/distribution/utilities/tnrecv.c @@ -0,0 +1,674 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tnrecv.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> + +#include <api/apilib.h> + +#include "tncomp.h" + + +#include "../ctlr/api.h" +#include "../ctlr/function.h" +#include "../ctlr/hostctlr.h" +#include "../ctlr/oia.h" +#include "../ctlr/screen.h" + +#include "../api/disp_asc.h" +#include "../api/astosc.h" + +#include "../general/general.h" + +ScreenImage Host[MAXSCREENSIZE]; + +static char + a_send_sequence[SEND_SEQUENCE_LENGTH+1], + a_ack_sequence[ACK_SEQUENCE_LENGTH+1], + a_checksum[CHECKSUM_LENGTH+1], + data_array[DATA_LENGTH+1]; + +static int + verbose, + blocks, + enter_index, + clear_index, + ScreenSize, + session_id; + +static unsigned int + send_sequence, + ack_sequence = -1, + checksum; + +api_perror(string) +char *string; +{ + fprintf(stderr, "Error: [0x%x/0x%x:0x%x/0x%x] from %s.\n", + api_sup_fcn_id, api_sup_errno, + api_fcn_fcn_id, api_fcn_errno, string); +} + + +char * +session_type(type) +int type; +{ + switch (type) { + case TYPE_WSCTL: + return "work station control"; + case TYPE_DFT: + return "distributed function terminal"; + case TYPE_CUT: + return "control unit terminal"; + case TYPE_NOTEPAD: + return "notepad"; + case TYPE_PC: + return "personal computer"; + default: + return "(UNKNOWN)"; + } +} + +static int +wait_for_ps_or_oia() +{ +#if defined(unix) + return api_ps_or_oia_modified(); +#endif /* defined(unix) */ +} + + +static int +wait_for_unlock() +{ + OIA oia; + ReadOiaGroupParms re; + static char zeroes[sizeof oia.input_inhibited] = { 0 }; + + do { + re.rc = re.function_id = 0; + re.session_id = session_id; + re.oia_buffer = (char far *) &oia; + re.oia_group_number = API_OIA_ALL_GROUPS; + if (api_read_oia_group(&re) == -1) { + api_perror("api_read_oia_group"); + return -1; + } else if (verbose) { + if (IsOiaReady3274(&oia)) { + printf("3274 ready, "); + } + if (IsOiaMyJob(&oia)) { + printf("my job, "); + } + if (IsOiaInsert(&oia)) { + printf("insert mode, "); + } + if (IsOiaSystemLocked(&oia)) { + printf("system locked, "); + } + if (IsOiaTWait(&oia)) { + printf("terminal wait, "); + } + printf("are some bits from the OIA.\n"); + } + /* We turned this on, so turn it off now */ + ResetOiaApiInhibit(&oia); + if (memcmp(zeroes, oia.input_inhibited, sizeof oia.input_inhibited)) { + if (wait_for_ps_or_oia() == -1) { + return -1; + } + } + } while (memcmp(zeroes, oia.input_inhibited, sizeof oia.input_inhibited)); + return 0; +} + +static int +initialize() +{ + QuerySessionIdParms id; + QuerySessionParametersParms pa; + QuerySessionCursorParms cu; + ConnectToKeyboardParms conn; + DisableInputParms disable; + NameArray namearray; + + if (api_init() == 0) { + fprintf(stderr, "API function not available.\n"); + return -1; + } + + id.rc = 0; + id.function_id = 0; + id.option_code = ID_OPTION_BY_NAME; + id.data_code = 'E'; + id.name_array = &namearray; + namearray.length = sizeof namearray; + if (api_query_session_id(&id)) { + api_perror("api_query_session_id"); + } else if (namearray.number_matching_session == 0) { + fprintf(stderr, "query_session_id: No matching sessions!\n"); + return -1; + } else if (verbose) { + printf("Session short name 0x%x, type is ", + namearray.name_array_element.short_name); + printf("%s", session_type(namearray.name_array_element.type)); + printf(", session ID is: 0x%x\n", + namearray.name_array_element.session_id); + } + session_id = namearray.name_array_element.session_id; + + pa.rc = pa.function_id = 0; + pa.session_id = session_id; + if (api_query_session_parameters(&pa) == -1) { + api_perror("api_query_session_parameters"); + return -1; + } else if (verbose) { + printf("Session type %s, ", session_type(pa.session_type)); + if (pa.session_characteristics&CHARACTERISTIC_EAB) { + printf(" has EAB, "); + } + if (pa.session_characteristics&CHARACTERISTIC_PSS) { + printf(" has PSS, "); + } + printf("%d rows, %d columns ", pa.rows, pa.columns); + if (pa.presentation_space) { + printf("presentation space at 0x%x:0x%x.\n", + FP_SEG(pa.presentation_space), FP_OFF(pa.presentation_space)); + } else { + printf("(no direct presentation space access).\n"); + } + } + ScreenSize = pa.rows*pa.columns; + if (pa.session_characteristics&CHARACTERISTIC_EAB) { + fprintf(stderr, + "tncomp utilities not designed to work with extended attribute buffers.\n"); + return -1; + } + + if (verbose) { + cu.rc = cu.function_id = 0; + cu.session_id = session_id; + if (api_query_session_cursor(&cu) == -1) { + api_perror("api_query_session_cursor"); + } else { + printf("cursor"); + if (cu.cursor_type&CURSOR_INHIBITED_AUTOSCROLL) { + printf(" inhibited autoscroll"); + } + if (cu.cursor_type&CURSOR_INHIBITED) { + printf(" inhibited"); + } + if (cu.cursor_type&CURSOR_BLINKING) { + printf(" blinking"); + } else { + printf(" not blinking"); + } + if (cu.cursor_type&CURSOR_BOX) { + printf(" box "); + } else { + printf(" not box "); + } + printf("at row %d, column %d.\n", + cu.row_address, cu.column_address); + } + } + + conn.rc = conn.function_id = 0; + conn.session_id = session_id; + conn.event_queue_id = conn.input_queue_id = 0; + conn.intercept_options = 0; + if (api_connect_to_keyboard(&conn) == -1) { + api_perror("api_connect_to_keyboard"); + } else if (verbose) { + if (conn.first_connection_identifier) { + printf("First keyboard connection.\n"); + } else { + printf("Not first keyboard connection.\n"); + } + } + + disable.rc = disable.function_id = 0; + disable.session_id = session_id; + disable.connectors_task_id = 0; + if (api_disable_input(&disable) == -1) { + api_perror("api_disable_input"); + return -1; + } else if (verbose) { + printf("Disabled.\n"); + } + + if ((enter_index = ascii_to_index("ENTER")) == -1) { + return -1; + } + if ((clear_index = ascii_to_index("CLEAR")) == -1) { + return -1; + } + + return 0; /* all ok */ +} + +static int +send_key(index) +int index; +{ + WriteKeystrokeParms wr; + extern struct astosc astosc[]; + + wait_for_unlock(); + + wr.rc = wr.function_id = 0; + wr.session_id = session_id; + wr.connectors_task_id = 0; + wr.options = OPTION_SINGLE_KEYSTROKE; + wr.number_of_keys_sent = 0; + wr.keystroke_specifier.keystroke_entry.scancode = astosc[index].scancode; + wr.keystroke_specifier.keystroke_entry.shift_state + = astosc[index].shiftstate; + if (api_write_keystroke(&wr) == -1) { + api_perror("api_write_keystroke"); + return -1; + } else if (wr.number_of_keys_sent != 1) { + fprintf(stderr, "write_keystroke claims to have sent %d keystrokes.\n", + wr.number_of_keys_sent); + return -1; + } else if (verbose) { + printf("Keystroke sent.\n"); + } + if (wait_for_ps_or_oia() == -1) { + return -1; + } + return 0; +} + +static int +terminate() +{ + EnableInputParms enable; + DisconnectFromKeyboardParms disc; + + enable.rc = enable.function_id = 0; + enable.session_id = session_id; + enable.connectors_task_id = 0; + if (api_enable_input(&enable) == -1) { + api_perror("api_enable"); + return -1; + } else if (verbose) { + printf("Enabled.\n"); + } + + disc.rc = disc.function_id = 0; + disc.session_id = session_id; + disc.connectors_task_id = 0; + if (api_disconnect_from_keyboard(&disc) == -1) { + api_perror("api_disconnect_from_keyboard"); + return -1; + } else if (verbose) { + printf("Disconnected from keyboard.\n"); + } + + (void) api_finish(); + + return 0; +} + + +static int +get_screen() +{ + CopyStringParms copy; + /* Time copy services */ + + wait_for_unlock(); + + copy.copy_mode = 0; + copy.rc = copy.function_id = 0; + copy.source.session_id = session_id; + copy.source.buffer = 0; + copy.source.characteristics = 0; + copy.source.session_type = TYPE_DFT; + copy.source.begin = 0; + + copy.source_end = ScreenSize; + + copy.target.session_id = 0; + copy.target.buffer = (char *) &Host[0]; + copy.target.characteristics = 0; + copy.target.session_type = TYPE_DFT; + + if (api_copy_string(©) == -1) { + api_perror("api_copy_string"); + return -1; + } + return 0; +} + + +put_at(offset, from, length, attribute) +int offset; +char *from; +int length; +{ + CopyStringParms copy; + + wait_for_unlock(); + + copy.copy_mode = 0; + copy.rc = copy.function_id = 0; + copy.source.session_id = 0; + copy.source.buffer = from; + copy.source.characteristics = 0; + copy.source.session_type = TYPE_DFT; + copy.source.begin = 0; + + copy.source_end = length-1; + + copy.target.session_id = session_id; + copy.target.buffer = 0; + copy.target.characteristics = 0; + copy.target.session_type = TYPE_DFT; + copy.target.begin = offset; + + if (api_copy_string(©) == -1) { + api_perror("api_copy_string"); + return -1; + } + return 0; +} + +static void +translate(input, output, table, length) +char *input, *output, table[]; +int length; +{ + unsigned char *indices = (unsigned char *) input; + + while (length--) { + *output++ = table[*indices++]; + } +} + +static int +find_input_area(from) +int from; +{ +#define FieldDec(p) (0) /* We don't really use this */ + register int i, attr; + + for (i = from; i < MAXSCREENSIZE; ) { + if (IsStartField(i)) { + attr = FieldAttributes(i); + i++; + if (!IsProtectedAttr(i, attr)) { + return i; + } + } else { + i++; + } + } + return -1; +} + + +static void +getascii(offset, to, length) +int offset; /* Where in screen */ +char *to; /* Where it goes to */ +int length; /* Where to put it */ +{ + translate(Host+offset, to, disp_asc, length); +} + +static int +putascii(offset, from, length, before) +int offset; /* Where in screen */ +char *from; /* Where it comes from */ +int length; /* Where to put it */ +int before; /* How much else should go */ +{ + translate(from, Host+offset, asc_disp, length); + if (put_at(offset-before, + (char *) Host+offset-before, length+before) == -1) { + return -1; + } + return 0; +} + +static int +ack() +{ + static char ack_blanks[sizeof a_ack_sequence] = {0}; + + if (ack_blanks[0] == 0) { + int i; + + for (i = 0; i < sizeof ack_blanks; i++) { + ack_blanks[i] = ' '; + } + } + + memcpy(a_ack_sequence, ack_blanks, sizeof a_ack_sequence); + sprintf(a_ack_sequence, "%d", ack_sequence); + a_ack_sequence[strlen(a_ack_sequence)] = ' '; + if (putascii(ACK_SEQUENCE, a_ack_sequence, ACK_SEQUENCE_LENGTH, 0) == -1) { + return -1; + } + return 0; +} + +static int +formatted_correct() +{ + if ((find_input_area(SEND_SEQUENCE-1) != SEND_SEQUENCE) || + (find_input_area(SEND_SEQUENCE) != ACK_SEQUENCE) || + (find_input_area(ACK_SEQUENCE) != CHECKSUM) || + (find_input_area(CHECKSUM) != DATA)) { + return -1; + } else { + return 0; + } +} + + +main(argc, argv) +int argc; +char *argv[]; +{ + register int i; + int data_length, input_length; + char ascii[8]; /* Lots of room */ + FILE *outfile; + char *data; + char *argv0 = argv[0]; + + argc--; + argv++; + /* Process any flags */ + while (argc && (argv[0][0] == '-')) { + switch (argv[0][1]) { + case 'v': + verbose = 1; + break; + case 'b': + blocks = 1; + break; + } + argc--; + argv++; + } + + if ((argc) < 2) { + fprintf(stderr, + "usage: %s [-b] [-v] local.file remote.file [remote.options]\n", + argv0); + exit(1); + } + + /* Open the local file */ + if ((outfile = fopen(argv[0], "w")) == NULL) { + perror("fopen"); + exit(2); + } + argc--; + argv++; + + if (initialize() == -1) { + return -1; + } + + /* build the command line */ + data = data_array; + strcpy(data, "TNCOMP SEND"); + data += strlen(data); + while (argc--) { + *data++ = ' '; + strcpy(data, argv[0]); + data += strlen(argv[0]); + argv++; + } + if (verbose) { + printf("%s\n", data_array); + } + if (get_screen() == -1) { + return -1; + } + data_length = strlen(data_array); + if ((i = find_input_area(0)) == -1) { /* Get an input area */ + if (send_key(clear_index) == -1) { + return -1; + } + if ((i = find_input_area(0)) == -1) { /* Try again */ + fprintf(stderr, "Unable to enter command line.\n"); + return -1; + } + } + if (putascii(i, data_array, data_length, 0) == -1) { + return -1; + } + if (send_key(enter_index) == -1) { + return -1; + } + do { + if (get_screen() == -1) { + return -1; + } + } while (formatted_correct() == -1); + + do { + if (get_screen() == -1) { + return -1; + } + /* For each screen */ + if (formatted_correct() == -1) { + fprintf(stderr, "Bad screen written by host.\n"); + return -1; + } + /* If MDT isn't reset in the sequence number, go around again */ + if (Host[ACK_SEQUENCE-1]&ATTR_MDT) { + if (wait_for_ps_or_oia() == -1) { + return -1; + } + continue; + } + getascii(SEND_SEQUENCE, a_send_sequence, SEND_SEQUENCE_LENGTH); + send_sequence = atoi(a_send_sequence); + getascii(CHECKSUM, a_checksum, CHECKSUM_LENGTH); + checksum = atoi(a_checksum); + getascii(DATA, data_array, DATA_LENGTH); + data = data_array; + if (send_sequence != (ack_sequence+1)) { + if (ack() == -1) { + return -1; + } + data = "1234"; /* Keep loop from failing */ + if (send_key(enter_index) == -1) { + return -1; + } + if (get_screen() == -1) { + return -1; + } + continue; + } + + data_length = DATA_LENGTH; + while (data_length && memcmp(data, " EOF", 4) + && memcmp(data, " ", 4)) { + memcpy(ascii, data, 4); + data += 4; + data_length -= 4; + ascii[4] = 0; + input_length = atoi(ascii); + /* CMS can't live with zero length records */ + if ((input_length > 1) || + ((input_length == 1) && (data[0] != ' '))) { + if (fwrite(data, sizeof (char), + input_length, outfile) == 0) { + perror("fwrite"); + exit(9); + } + } + fprintf(outfile, "\n"); + data += input_length; + data_length -= input_length; + } + + ack_sequence = send_sequence; + if (blocks) { + printf("#"); + fflush(stdout); + } + if (ack() == -1) { + return -1; + } + if (send_key(enter_index) == -1) { + return -1; + } + } while (memcmp(data, " EOF", 4)); + + if (blocks) { + printf("\n"); + } + if (terminate() == -1) { + return -1; + } + return 0; +} diff --git a/usr.bin/tn3270/general/genbsubs.c b/usr.bin/tn3270/general/genbsubs.c new file mode 100644 index 0000000..b5377a6 --- /dev/null +++ b/usr.bin/tn3270/general/genbsubs.c @@ -0,0 +1,125 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)genbsubs.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* 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) +register char *s1, *s2; +register n; +{ + register 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) +register char *s1; +register int n; +register int b; +{ + register 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; +int stride; +{ + register 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/usr.bin/tn3270/general/general.h b/usr.bin/tn3270/general/general.h new file mode 100644 index 0000000..8fee245 --- /dev/null +++ b/usr.bin/tn3270/general/general.h @@ -0,0 +1,65 @@ +/*- + * 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. 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. + * + * @(#)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) + +#if defined(unix) +#define ClearElement(x) bzero((char *)&x, sizeof x) +#define ClearArray(x) bzero((char *)x, sizeof x) +#else /* defined(unix) */ +#define ClearElement(x) memset((char *)&x, 0, sizeof x) +#define ClearArray(x) memset((char *)x, 0, sizeof x) +#endif /* defined(unix) */ + +#if defined(unix) /* Define BSD equivalent mem* functions */ +#define memcpy(dest,src,n) bcopy(src,dest,n) +#define memmove(dest,src,n) bcopy(src,dest,n) +#define memset(s,c,n) if (c == 0) { \ + bzero(s,n); \ + } else { \ + register char *src = s; \ + register int count = n; \ + \ + while (count--) { \ + *src++ = c; \ + } \ + } +#define memcmp(s1,s2,n) bcmp(s1,s2,n) +#endif /* defined(unix) */ diff --git a/usr.bin/tn3270/general/globals.c b/usr.bin/tn3270/general/globals.c new file mode 100644 index 0000000..11e565f --- /dev/null +++ b/usr.bin/tn3270/general/globals.c @@ -0,0 +1,74 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)globals.c 8.1 (Berkeley) 6/6/93"; +#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/usr.bin/tn3270/general/globals.h b/usr.bin/tn3270/general/globals.h new file mode 100644 index 0000000..4fb365c --- /dev/null +++ b/usr.bin/tn3270/general/globals.h @@ -0,0 +1,130 @@ +/*- + * 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. 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. + * + * @(#)globals.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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 + +#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/usr.bin/tn3270/general/vaxbsubs.s b/usr.bin/tn3270/general/vaxbsubs.s new file mode 100644 index 0000000..096f532 --- /dev/null +++ b/usr.bin/tn3270/general/vaxbsubs.s @@ -0,0 +1,101 @@ +/*- + * 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. 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. + * + * @(#)vaxbsubs.s 8.1 (Berkeley) 6/6/93 + */ + +/* 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/usr.bin/tn3270/mset/Makefile b/usr.bin/tn3270/mset/Makefile new file mode 100644 index 0000000..0094fc8 --- /dev/null +++ b/usr.bin/tn3270/mset/Makefile @@ -0,0 +1,34 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= mset +CFLAGS+=-I${.CURDIR} -I. +SRCS+= astosc.c map3270.c mset.c +MAN1= mset.0 +MAN5= map3270.0 +.PATH: ${.CURDIR}/../api ${.CURDIR}/../ascii + +CLEANFILES+= astosc.OUT astosc.out + +# This and the dependency hacks below to make 'depend' target +# work right... + +DEPSRCS+= astosc.OUT map3270.c mset.c + +astosc.o: astosc.OUT +astosc.OUT: ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h +astosc.OUT: ${.CURDIR}/../ctlr/${KBD} ${.CURDIR}/../tools/mkastosc/obj/mkastosc + ${.CURDIR}/../tools/mkastosc/obj/mkastosc \ + ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h \ + < ${.CURDIR}/../ctlr/${KBD} > ${.TARGET} + rm -f astosc.out; ln -s astosc.OUT astosc.out + +# astosc.out +${.CURDIR}/../tools/mkastosc/obj/mkastosc: + cd ${.CURDIR}/../tools/mkastosc; make + +depend: .depend +.depend:${DEPSRCS} + mkdep ${MKDEP} ${CFLAGS:M-[ID]*} ${.ALLSRC:M*.c} + +.include <../../Makefile.inc> +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/mset/map3270.5 b/usr.bin/tn3270/mset/map3270.5 new file mode 100644 index 0000000..3904f3a --- /dev/null +++ b/usr.bin/tn3270/mset/map3270.5 @@ -0,0 +1,341 @@ +.\" Copyright (c) 1986, 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.5 8.3 (Berkeley) 4/19/94 +.\" +.TH MAP3270 5 "April 19, 1994" +.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 /etc/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 alternate 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 /etc/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&'; pfk20 = '\eE*'; + pfk21 = '\eE('; pfk22 = '\eE)'; pfk23 = '\eE_'; pfk24 = '\eE+'; + } +.fi +.SH "IBM 3270 KEY DEFINITONS 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 +/etc/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/usr.bin/tn3270/mset/mset.1 b/usr.bin/tn3270/mset/mset.1 new file mode 100644 index 0000000..a806eaa --- /dev/null +++ b/usr.bin/tn3270/mset/mset.1 @@ -0,0 +1,188 @@ +.\" Copyright (c) 1986, 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. 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. +.\" +.\" @(#)mset.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt MSET 1 +.Os BSD 4.3 +.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 Mset +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 +.Xr tn3270 +command (see +.Xr tn3270 1 ) . +.Pp +The default +.Nm mset +output can be used to store the mapping information in the process environment +in order to avoid scanning +.Nm map3270 +each time +.Nm 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 mset +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 mset +uses the user's terminal type from the environment variable +.Ev TERM +as the keyboard name. +Normally, +.Nm mset +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 alternate 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 alternate 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 mset +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 mset +normally will not complain about entries for unknown functions (like +.Dq PFX1 ; +the +.Fl picky +argument causes +.Nm mset +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 mset +output cannot be used to store the mapping information in the process +environment to avoid scanning +.Pa map3270 +each time +.Nm tn3270 +is invoked. +The +.Fl shell +argument causes +.Nm mset +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 > tmp ; source tmp ; /bin/rm tmp +.Ed +.It Ar keyboardname +When searching for the +.Pa map3270 +entry that matches the user's keyboard, +.Nm mset +will use +.Ar keyboardname +instead of determining the keyboard name from the +.Ev KEYBD +or +.Ev TERM +environmental variables. +.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 mset +command appeared in +.Bx 4.3 . diff --git a/usr.bin/tn3270/sys_curses/system.c b/usr.bin/tn3270/sys_curses/system.c new file mode 100644 index 0000000..14a99bd --- /dev/null +++ b/usr.bin/tn3270/sys_curses/system.c @@ -0,0 +1,753 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/6/93"; +#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/file.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/wait.h> + +#include <errno.h> +extern int errno; + +#include <netdb.h> +#include <signal.h> +#include <stdio.h> +#include <string.h> +#include <pwd.h> + +#include "../general/general.h" +#include "../ctlr/api.h" +#include "../api/api_exch.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() +{ + 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; + extern char *crypt(); + + 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("(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 (!defined(sun)) || defined(BSD) && (BSD >= 43) + extern uid_t geteuid(); +#endif /* (!defined(sun)) || defined(BSD) && (BSD >= 43) */ + + 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)) { + 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(); + } + 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(); + } + 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(); + } 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(); + } 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(); + } 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(); + } + 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() +{ + fd_set fdset; + int i; + + sock = -1; + FD_ZERO(&fdset); + while (shell_active && (sock == -1)) { + FD_SET(serversock, &fdset); + if ((i = select(serversock+1, &fdset, + (fd_set *)0, (fd_set *)0, (struct timeval *)0)) < 0) { + if (errno = EINTR) { + continue; + } else { + perror("in select waiting for API connection"); + return -1; + } + } else { + i = accept(serversock, (struct sockaddr *)0, (int *)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)) { + extern void setcommandmode(); + + (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) +{ + union wait status; + register int pid; + + while ((pid = wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) { + if (pid == shell_pid) { + char inputbuffer[100]; + extern void setconnmode(); + extern void ConnectScreen(); + + shell_active = 0; + if (sock != -1) { + (void) close(sock); + sock = -1; + } + printf("[Hit return to continue]"); + fflush(stdout); + (void) gets(inputbuffer); + setconnmode(); + 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 spint... routines so that we can pick up + * interrupts generated by application programs. + */ + + +int +shell(argc,argv) +int argc; +char *argv[]; +{ + int length; + struct sockaddr_in server; + char sockNAME[100]; + static char **whereAPI = 0; + int fd; + struct timeval tv; + long ikey; + extern long random(); + extern char *mktemp(); + extern char *strcpy(); + + /* First, create verification file. */ + do { + keyname = mktemp(strdup("/tmp/apiXXXXXX")); + fd = open(keyname, O_RDWR|O_CREAT|O_EXCL, IREAD|IWRITE); + } while ((fd == -1) && (errno == EEXIST)); + + 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)); + 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(); /* Start up signal handler */ + shell_active = 1; /* We are running down below */ + if (shell_pid = vfork()) { + if (shell_pid == -1) { + perror("vfork"); + (void) close(serversock); + } else { + state = UNCONNECTED; + } + } else { /* New process */ + register int i; + + for (i = 3; i < 30; i++) { + (void) close(i); + } + if (argc == 1) { /* Just get a shell */ + char *cmdname; + extern char *getenv(); + + cmdname = getenv("SHELL"); + execlp(cmdname, cmdname, 0); + perror("Exec'ing new shell...\n"); + exit(1); + } else { + execvp(argv[1], &argv[1]); + perror("Exec'ing command.\n"); + exit(1); + } + /*NOTREACHED*/ + } + return shell_active; /* Go back to main loop */ +} diff --git a/usr.bin/tn3270/sys_curses/telextrn.h b/usr.bin/tn3270/sys_curses/telextrn.h new file mode 100644 index 0000000..becf82a2 --- /dev/null +++ b/usr.bin/tn3270/sys_curses/telextrn.h @@ -0,0 +1,71 @@ +/*- + * 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. 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. + * + * @(#)telextrn.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * 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; + +extern int + netflush(), + quit(), + TtyChars(), + DataToTerminal(); + +extern void + outputPurge(), + EmptyTerminal(), + StringToTerminal(), + ExitPerror(), + setcommandmode(); + +/* + * Pieces exported from other random locations. + */ + +extern char + *strsave(); diff --git a/usr.bin/tn3270/sys_curses/terminal.h b/usr.bin/tn3270/sys_curses/terminal.h new file mode 100644 index 0000000..d7041b7 --- /dev/null +++ b/usr.bin/tn3270/sys_curses/terminal.h @@ -0,0 +1,81 @@ +/*- + * 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. 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. + * + * @(#)terminal.h 8.1 (Berkeley) 6/6/93 + */ + +#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/usr.bin/tn3270/sys_curses/termout.c b/usr.bin/tn3270/sys_curses/termout.c new file mode 100644 index 0000000..5dbe311 --- /dev/null +++ b/usr.bin/tn3270/sys_curses/termout.c @@ -0,0 +1,957 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)termout.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#if defined(unix) +#include <signal.h> +#include <sgtty.h> +#endif +#include <stdio.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/externs.h" +#include "../ctlr/declare.h" +#include "../ctlr/oia.h" +#include "../ctlr/screen.h" +#include "../ctlr/scrnctlr.h" + +#include "../general/globals.h" + +#include "telextrn.h" + +#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 = "\07"; /* bell sequence (may be replaced by + * VB during initialization) + */ +static WINDOW *bellwin = 0; /* The window the bell message is in */ +int bellwinup = 0; /* Are we up with it or not */ + +#if defined(unix) +static char *myKS, *myKE; +#endif /* defined(unix) */ + + +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 */ +#endif /* defined(unix) */ + + +/* + * 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) +register int p; +{ + register 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() +{ + register int is, shouldbe, isattr, shouldattr; + register int pointer; + register int fieldattr, termattr; + register 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())) { + register 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; + register 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)() = FastScreen; + +/*ARGSUSED*/ +void +ScreenOIA(oia) +OIA *oia; +{ +} + + +/* InitTerminal - called to initialize the screen, etc. */ + +void +InitTerminal() +{ +#if defined(unix) + struct sgttyb ourttyb; + static int speeds[] = { 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, + 2400, 4800, 9600 }; +#endif + extern void InitMapping(); + + InitMapping(); /* Go do mapping file (MAP3270) first */ + if (!screenInitd) { /* not initialized */ +#if defined(unix) + char KSEbuffer[2050]; + char *lotsofspace = KSEbuffer; + extern void abort(); + extern char *tgetstr(); +#endif /* defined(unix) */ + + if (initscr() == ERR) { /* 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, abort); +#endif + + TryToSend = FastScreen; +#if defined(unix) + ioctl(1, TIOCGETP, (char *) &ourttyb); + if ((ourttyb.sg_ospeed < 0) || (ourttyb.sg_ospeed > B9600)) { + max_changes_before_poll = 1920; + } else { + max_changes_before_poll = speeds[ourttyb.sg_ospeed]/10; + if (max_changes_before_poll < 40) { + max_changes_before_poll = 40; + } + TryToSend = SlowScreen; + HaveInput = 1; /* get signals going */ + } +#endif /* defined(unix) */ + setcommandmode(); + /* + * By now, initscr() (in curses) has been called (from telnet.c), + * and the screen has been initialized. + */ +#if defined(unix) + nonl(); + /* the problem is that curses catches SIGTSTP to + * be nice, but it messes us up. + */ + signal(SIGTSTP, SIG_DFL); + if ((myKS = tgetstr("ks", &lotsofspace)) != 0) { + myKS = strsave(myKS); + StringToTerminal(myKS); + } + if ((myKE = tgetstr("ke", &lotsofspace)) != 0) { + myKE = strsave(myKE); + } + if (tgetstr("md", &lotsofspace) && tgetstr("me", &lotsofspace)) { + SO = strsave(tgetstr("md", &lotsofspace)); + SE = strsave(tgetstr("me", &lotsofspace)); + } +#endif + DoARefresh(); + setconnmode(); + if (VB && *VB) { + bellSequence = VB; /* use visual bell */ + } + 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(); + setcommandmode(); + endwin(); + setconnmode(); +#if defined(unix) + if (myKE) { + StringToTerminal(myKE); + } +#endif /* defined(unix) */ + 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) { +#if defined(unix) + if (myKS) { + StringToTerminal(myKS); + } +#endif /* defined(unix) */ + RefreshScreen(); + (*TryToSend)(); + screenStopped = 0; + } +} + +/* LocalClearScreen() - clear the whole ball of wax, cheaply */ + +void +LocalClearScreen() +{ + extern void Clear3270(); + + 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(); + 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]; + static void aborttc(); +#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(); + 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 { + extern void TransInput(); + + TransInput(1, kind); /* Go get some data */ + } +} + + +#if defined(unix) +static void +aborttc(signo) + int signo; +{ + setcommandmode(); + (void) close(tin); + (void) close(tout); + tin = savefd[0]; + tout = savefd[1]; + setconnmode(); + tcflag = 0; +} +#endif /* defined(unix) */ diff --git a/usr.bin/tn3270/telnet/Makefile b/usr.bin/tn3270/telnet/Makefile new file mode 100644 index 0000000..b4095e2 --- /dev/null +++ b/usr.bin/tn3270/telnet/Makefile @@ -0,0 +1,87 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +# The following is the telnet makefile for tn3270, using the shared telnet +# sources. + +# +# TERMCAP Define this if your system is termcap based, +# otherwise a terminfo based system is assumed. +# +# SRCRT Includes code to allow you to specify source routes. +# Format is: +# [!]@hop1@hop2...[@|:]dst +# Leading ! means strict source route. +# +# NOSTRNCASECMP Define this if you do not have strncasecmp() in +# your C libarary. +# +# USE_TERMIO Define this if you have System V termio structures. +# What is here is how things are on Cray computers. +# +# KLUDGELINEMODE Define this to get the kludged up version of linemode +# that was in 4.3BSD. This is a good thing to have +# around for talking to older systems. +# + +DEFINES= -DTERMCAP -DSRCRT -DKLUDGELINEMODE -DUSE_TERMIO + + +VPATH = ${.CURDIR}/../../telnet +XINCLUDES= -I${.CURDIR}/../../telnet -I${.CURDIR} +INCLUDES= +XDEFINES = -DTN3270 +OPTIMIZE= -O +CFLAGS = ${OPTIMIZE} ${INCLUDES} ${DEFINES} +XCFLAGS= ${XINCLUDES} ${XDEFINES} +LD = ld +LDFLAGS = -r +PRINT = print +ACTION = sccs tell +LIBC= /usr/lib/libc.a +ALLH= defines.h externs.h fdset.h general.h ring.h types.h +SRCS= commands.c main.c network.c ring.c \ + sys_bsd.c telnet.c terminal.c \ + tn3270.c utilities.c +ALLHC= ${ALLH} ${SRCS} +ALLPRINT = ${ALLHC} +ALLSOURCE= ${ALLHC} Makefile Makefile_ultrix +OBJS= commands.o main.o network.o ring.o sys_bsd.o \ + telnet.o terminal.o tn3270.o utilities.o + +.c.o: + ${CC} -c ${CFLAGS} ${XCFLAGS} $< + +telprog.o: ${OBJS} ${LIBC} + ${LD} ${LDFLAGS} -o $@ ${OBJS} + +clean: FRC + rm -f telprog.o ${OBJS} core telnet + +depend: FRC ${SRCS} + mkdep ${CFLAGS} ${SRCS} + +lint: FRC ${SRCS} + lint ${CFLAGS} ${SRCS} + +tags: FRC ${ALLHC} + ctags ${ALLHC} + +print: FRC ${ALLPRINT} + ${PRINT} ${ALLPRINT} + +action: FRC + ${ACTION} + +clist: FRC ${SRCS} + @for i in ${SRCS} ; \ + do (echo ${DIRPATH}$$i); done + +hclist: FRC ${ALLHC} + @for i in ${ALLHC} ; \ + do (echo ${DIRPATH}$$i); done + +sourcelist: FRC ${ALLSOURCE} + @for i in ${ALLSOURCE} ../../telnet/Makefile ; \ + do (echo ${DIRPATH}$$i); done + +FRC: diff --git a/usr.bin/tn3270/tn3270/Makefile b/usr.bin/tn3270/tn3270/Makefile new file mode 100644 index 0000000..a9f1641 --- /dev/null +++ b/usr.bin/tn3270/tn3270/Makefile @@ -0,0 +1,80 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= tn3270 +CFLAGS+=-I${.CURDIR} -I. +LDADD+= -lcurses -ltermcap -ltelnet +DPADD+= ${LIBCURSES} /usr/lib/libtermcap.a /usr/lib/libtelnet.a +CLEANFILES+= asc_disp.OUT asc_disp.out disp_asc.OUT disp_asc.out TMPfunc.out +.PATH: ${.CURDIR}/../api ${.CURDIR}/../ascii ${.CURDIR}/../ctlr +.PATH: ${.CURDIR}/../general ${.CURDIR}/../sys_curses ${.CURDIR}/../../telnet + +MAN1= tn3270.0 + +SRCS+= apilib.c api_bsd.c api_exch.c asc_ebc.c astosc.c dctype.c +SRCS+= disp_asc.c ebc_disp.c +SRCS+= map3270.c termin.c +SRCS+= api.c function.c inbound.c oia.c options.c outbound.c +SRCS+= genbsubs.c globals.c system.c termout.c +SRCS+= commands.c main.c network.c ring.c sys_bsd.c telnet.c terminal.c +SRCS+= tn3270.c utilities.c + +# This and the dependency hacks below to make 'depend' target +# work right... + +DEPSRCS+= astosc.OUT asc_disp.OUT disp_asc.OUT kbd.OUT +DEPSRCS+= apilib.c api_bsd.c api_exch.c asc_ebc.c dctype.c +DEPSRCS+= ebc_disp.c +DEPSRCS+= map3270.c termin.c +DEPSRCS+= api.c function.c inbound.c oia.c options.c outbound.c +DEPSRCS+= genbsubs.c globals.c system.c termout.c +DEPSRCS+= commands.c main.c network.c ring.c sys_bsd.c telnet.c terminal.c +DEPSRCS+= tn3270.c utilities.c + +astosc.o: astosc.OUT +CLEANFILES+= astosc.OUT astosc.out +astosc.OUT: ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/function.h +astosc.OUT: ${.CURDIR}/../ctlr/${KBD} ${.CURDIR}/../tools/mkastosc/obj/mkastosc + ${.CURDIR}/../tools/mkastosc/obj/mkastosc \ + ${.CURDIR}/../ctlr/hostctlr.h \ + ${.CURDIR}/../ctlr/function.h < ${.CURDIR}/../ctlr/${KBD} \ + > ${.TARGET} + rm -f astosc.out; ln -s astosc.OUT astosc.out + +disp_asc.o: asc_disp.OUT disp_asc.OUT +asc_disp.OUT: ${.CURDIR}/../tools/mkastods/obj/mkastods + ${.CURDIR}/../tools/mkastods/obj/mkastods > ${.TARGET} + rm -f asc_disp.out; ln -s asc_disp.OUT asc_disp.out + +disp_asc.OUT: ${.CURDIR}/../tools/mkdstoas/obj/mkdstoas + ${.CURDIR}/../tools/mkdstoas/obj/mkdstoas > ${.TARGET} + rm -f disp_asc.out; ln -s disp_asc.OUT disp_asc.out + +inbound.o: kbd.OUT +CLEANFILES += kbd.OUT kbd.out +kbd.OUT: ${.CURDIR}/../ctlr/hostctlr.h ${.CURDIR}/../ctlr/${KBD} +kbd.OUT: ${.CURDIR}/../tools/mkhits/obj/mkhits + ${CC} ${CFLAGS} -E ${.CURDIR}/../ctlr/function.c > TMPfunc.out + ${.CURDIR}/../tools/mkhits/obj/mkhits ${.CURDIR}/../ctlr/hostctlr.h \ + TMPfunc.out < ${.CURDIR}/../ctlr/${KBD} > ${.TARGET} + rm -f kbd.out; ln -s kbd.OUT kbd.out + +# astosc.out +# asc_disp.out disp_asc.out +# default.map +# kbd.out + +${.CURDIR}/../tools/mkastosc/obj/mkastosc: + cd ${.CURDIR}/../tools/mkastosc; make +${.CURDIR}/../tools/mkastods/obj/mkastods: + cd ${.CURDIR}/../tools/mkastods; make +${.CURDIR}/../tools/mkdstoas/obj/mkdstoas: + cd ${.CURDIR}/../tools/mkdstoas; make +${.CURDIR}/../tools/mkhits/obj/mkhits: + cd ${.CURDIR}/../tools/mkhits; make + +depend: .depend +.depend: ${DEPSRCS} + mkdep ${MKDEP} ${CFLAGS:M-[ID]*} ${.ALLSRC:M*.c} + +.include <../../Makefile.inc> +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/tn3270/tn3270.1 b/usr.bin/tn3270/tn3270/tn3270.1 new file mode 100644 index 0000000..778302e --- /dev/null +++ b/usr.bin/tn3270/tn3270/tn3270.1 @@ -0,0 +1,339 @@ +.\" Copyright (c) 1986, 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. 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. +.\" +.\" @(#)tn3270.1 8.2 (Berkeley) 4/18/94 +.\" +.Dd April 18, 1994 +.Dt TN3270 1 +.Os BSD 4.3 +.Sh NAME +.Nm tn3270 +.Nd full-screen remote login to +.Tn IBM VM/CMS +.Sh SYNOPSIS +.Nm tn3270 +.Op Fl d +.Op Fl n Ar filename +.Op Fl t Ar commandname +.Op Ar sysname Op port +.Sh DESCRIPTION +.Nm Tn3270 +permits a full-screen, full-duplex connection +from a +.Tn UNIX +machine +to an +.Tn IBM +(or compatible) machine. +.Nm Tn3270 +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 Tn3270 +looks to the user in many respects +like the Yale +.Tn ASCII +Terminal Communication System II. +.Nm Tn3270 +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 tn3270 +are as follows: +.Bl -tag -width Fl +.It Fl d +Turn on socket-level tracing (for super-user only) +.Fl n Ns 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. +.Fl t Ns Ar commandname +Specify a +.Tn UNIX +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 tn3270 +attempts to connect to the +standard +.Tn TELNET +port (port +23) on the remote machine. +.El +.Pp +When +.Nm tn3270 +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 tn3270 +emulates a 3278 terminal. +To decide which specific model, +.Nm tn3270 +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 tn3270 +is running, on multiple +window systems) must have at least 80 columns and 24 lines, or +.Nm tn3270 +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 +.Tn UNIX +process. +This emulation involves mapping +3270-style commands from the host +into appropriate sequences to control the user's terminal screen. +.Nm Tn3270 +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 tn3270 +looks for an entry for the terminal type +.Em unknown . +If this is not found, +.Nm tn3270 +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 tn3270 +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 tn3270 +is invoked without specifying a remote host system name, +it enters local command mode, +indicated by the prompt +.Dq Li tn3270>\ . +In this mode, +.Nm tn3270 +accepts and executes +all the commands of +.Xr telnet 1 , +plus one additional command: +.Pp +.Bl -tag -width Ar +.It Ic transcom +Specify +.Tn UNIX +command for +.Tn IBM +4994 style transparent mode processing. +.El +.Pp +.Nm Tn3270 +command mode may also be entered, after connecting to a host, by typing +a special escape sequence. +If +.Nm tn3270 +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 tn3270 +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 Tn3270 +checks the following environment variables: +.Ev TERM , +.Ev MAP3270 , +.Ev MAP3270[A...] . +Information on these can be found in +.Xr mset 1 . +.Nm Tn3270 +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 termcap 5 , +.Xr map3270 5 , +.Rs +.%T "Yale ASCII Terminal Communication" +.%B "System II Program Description/Operator's Manual" +.%R IBM SB30-1911 +.Re +.Sh HISTORY +The +.Nm tn3270 +command appeared in +.Bx 4.3 . +.Sh BUGS +Tn3270 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/usr.bin/tn3270/tools/Makefile b/usr.bin/tn3270/tools/Makefile new file mode 100644 index 0000000..0b64f8f --- /dev/null +++ b/usr.bin/tn3270/tools/Makefile @@ -0,0 +1,5 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +SUBDIR= mkhits mkastosc mkastods mkdstoas mkdctype + +.include <bsd.subdir.mk> diff --git a/usr.bin/tn3270/tools/mkastods/Makefile b/usr.bin/tn3270/tools/mkastods/Makefile new file mode 100644 index 0000000..a2d36a1 --- /dev/null +++ b/usr.bin/tn3270/tools/mkastods/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= mkastods +SRCS= mkastods.c asc_ebc.c ebc_disp.c +CFLAGS+=-I${.CURDIR}/.. -I. +NOMAN= noman +.PATH: ${.CURDIR}/../../api + +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/tools/mkastods/mkastods.c b/usr.bin/tn3270/tools/mkastods/mkastods.c new file mode 100644 index 0000000..6a9f72e --- /dev/null +++ b/usr.bin/tn3270/tools/mkastods/mkastods.c @@ -0,0 +1,77 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkastods.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ +#include <ctype.h> +#include "../api/asc_ebc.h" +#include "../api/ebc_disp.h" + +int +main() +{ + 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/usr.bin/tn3270/tools/mkastosc/Makefile b/usr.bin/tn3270/tools/mkastosc/Makefile new file mode 100644 index 0000000..a6268f5 --- /dev/null +++ b/usr.bin/tn3270/tools/mkastosc/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= mkastosc +SRCS= mkastosc.c dohits.c asc_ebc.c ebc_disp.c +CFLAGS+=-I${.CURDIR}/../mkhits -I${.CURDIR}/.. -I. +NOMAN= noman +.PATH: ${.CURDIR}/../mkhits ${.CURDIR}/../../api + +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/tools/mkastosc/mkastosc.c b/usr.bin/tn3270/tools/mkastosc/mkastosc.c new file mode 100644 index 0000000..697122d --- /dev/null +++ b/usr.bin/tn3270/tools/mkastosc/mkastosc.c @@ -0,0 +1,166 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkastosc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ +#include <ctype.h> + +#include "../general/general.h" +#include "../ctlr/function.h" + +#include "dohits.h" + +static struct tbl { + unsigned char + scancode, + used; + char + *shiftstate; +} tbl[128]; + +int +main(argc, argv) +int argc; +char *argv[]; +{ + int scancode; + int asciicode; + int empty; + int i; + int c; + int found; + struct hits *ph; + struct Hits *Ph; + struct thing *this; + struct thing **attable; + struct tbl *Pt; + static 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, "Unable to produce scancode sequence for"); + fprintf(stderr, " ASCII character [%c]!\n", 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%02x, %s, ", + 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/usr.bin/tn3270/tools/mkdctype/Makefile b/usr.bin/tn3270/tools/mkdctype/Makefile new file mode 100644 index 0000000..818bb52 --- /dev/null +++ b/usr.bin/tn3270/tools/mkdctype/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= mkdctype +SRCS= mkdctype.c ebc_disp.c ectype.c +CFLAGS+=-I${.CURDIR}/.. -I. +NOMAN= noman +.PATH: ${.CURDIR}/../../api + +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/tools/mkdctype/ectype.c b/usr.bin/tn3270/tools/mkdctype/ectype.c new file mode 100644 index 0000000..ebdca0b --- /dev/null +++ b/usr.bin/tn3270/tools/mkdctype/ectype.c @@ -0,0 +1,313 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)ectype.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include "ectype.h" + +char ectype[] = { +/* 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/usr.bin/tn3270/tools/mkdctype/ectype.h b/usr.bin/tn3270/tools/mkdctype/ectype.h new file mode 100644 index 0000000..15dfb86 --- /dev/null +++ b/usr.bin/tn3270/tools/mkdctype/ectype.h @@ -0,0 +1,52 @@ +/*- + * 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. 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. + * + * @(#)ectype.h 8.1 (Berkeley) 6/6/93 + */ + +#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) diff --git a/usr.bin/tn3270/tools/mkdctype/mkdctype.c b/usr.bin/tn3270/tools/mkdctype/mkdctype.c new file mode 100644 index 0000000..24ee095 --- /dev/null +++ b/usr.bin/tn3270/tools/mkdctype/mkdctype.c @@ -0,0 +1,99 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkdctype.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include "../api/ebc_disp.h" +#include "ectype.h" + + +extern unsigned char ectype[256]; + + +void +main() +{ + 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"); + } +} diff --git a/usr.bin/tn3270/tools/mkdstoas/Makefile b/usr.bin/tn3270/tools/mkdstoas/Makefile new file mode 100644 index 0000000..b2abeb3 --- /dev/null +++ b/usr.bin/tn3270/tools/mkdstoas/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= mkdstoas +SRCS= mkdstoas.c asc_ebc.c ebc_disp.c +CFLAGS+=-I${.CURDIR}/.. -I. +NOMAN= noman +.PATH: ${.CURDIR}/../../api + +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/tools/mkdstoas/mkdstoas.c b/usr.bin/tn3270/tools/mkdstoas/mkdstoas.c new file mode 100644 index 0000000..befd3c6 --- /dev/null +++ b/usr.bin/tn3270/tools/mkdstoas/mkdstoas.c @@ -0,0 +1,78 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkdstoas.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ +#include <ctype.h> +#include "../api/asc_ebc.h" +#include "../api/ebc_disp.h" + + +int +main() +{ + 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/usr.bin/tn3270/tools/mkhits/Makefile b/usr.bin/tn3270/tools/mkhits/Makefile new file mode 100644 index 0000000..c7c8802 --- /dev/null +++ b/usr.bin/tn3270/tools/mkhits/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= mkhits +SRCS= mkhits.c dohits.c asc_ebc.c ebc_disp.c +CFLAGS+=-I${.CURDIR}/.. -I. +NOMAN= noman +.PATH: ${.CURDIR}/../../api + +.include <bsd.prog.mk> diff --git a/usr.bin/tn3270/tools/mkhits/dohits.c b/usr.bin/tn3270/tools/mkhits/dohits.c new file mode 100644 index 0000000..d2d576e --- /dev/null +++ b/usr.bin/tn3270/tools/mkhits/dohits.c @@ -0,0 +1,295 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)dohits.c 8.1 (Berkeley) 6/6/93"; +#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 <stdio.h> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ +#include <ctype.h> +#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]; + +extern char *malloc(); + +unsigned int +dohash(seed, string) +unsigned int seed; +char *string; +{ + register unsigned int i = seed; + register unsigned char c; + + while (c = *string++) { + if (c >= 0x60) { + c -= (0x60+0x20); + } else { + c -= 0x20; + } + i = (i>>26) + (i<<6) + (c&0x3f); + } + return i; +} + +void +add(first, second, value) +char *first, *second; +int value; +{ + struct thing **item, *this; + + item = &firstentry(second); + this = (struct thing *) malloc(sizeof *this); + this->next = *item; + *item = this; + this->value = value; + strcpy(this->name, first); + strcpy(this->name+strlen(this->name), second); +} + +void +scanwhite(file, prefix) +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], value[100]; + char line[200]; + + sprintf(compare, " %s%%[^,\t \n]", prefix); + if ((ourfile = fopen(file, "r")) == NULL) { + perror("fopen"); + 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)) { + perror("fgets"); + } + break; + } + } while (line[strlen(line)-1] != '\n'); + } +} + +void +scandefine(file, prefix) +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; + + sprintf(compare, "#define %s%%s %%s", prefix); + if ((ourfile = fopen(file, "r")) == NULL) { + perror("fopen"); + 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)) { + perror("fgets"); + } + break; + } + } while (line[strlen(line)-1] != '\n'); + } +} + +char *savechr(c) +unsigned char c; +{ + char *foo; + + foo = malloc(sizeof c); + if (foo == 0) { + fprintf(stderr, "No room for ascii characters!\n"); + exit(1); + } + *foo = c; + return foo; +} + +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, "Error: Unknown type %s.\n", type); + return 0; + } +} + + +void +dohits(aidfile, fcnfile) +char *aidfile, *fcnfile; +{ + unsigned char plain[100], shifted[100], alted[100], shiftalted[100]; + unsigned char line[200]; + int keynumber, scancode; + int empty; + int i; + struct hit *hit; + struct hits *ph; + struct Hits *Ph; + + 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 (gets(line) != NULL) { + 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, + "Error: scancode 0x%02x for keynumber %d\n", scancode, + keynumber); + break; + } + if (Hits[scancode].hits.hit[0].ctlrfcn != undefined) { + fprintf(stderr, + "Error: 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/usr.bin/tn3270/tools/mkhits/dohits.h b/usr.bin/tn3270/tools/mkhits/dohits.h new file mode 100644 index 0000000..9c26eca --- /dev/null +++ b/usr.bin/tn3270/tools/mkhits/dohits.h @@ -0,0 +1,56 @@ +/*- + * 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. 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. + * + * @(#)dohits.h 8.1 (Berkeley) 6/6/93 + */ + +#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]; + +extern unsigned int dohash(); diff --git a/usr.bin/tn3270/tools/mkhits/mkhits.c b/usr.bin/tn3270/tools/mkhits/mkhits.c new file mode 100644 index 0000000..0fafb8f --- /dev/null +++ b/usr.bin/tn3270/tools/mkhits/mkhits.c @@ -0,0 +1,147 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)mkhits.c 8.1 (Berkeley) 6/6/93"; +#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 <stdio.h> +#if defined(unix) +#include <strings.h> +#else /* defined(unix) */ +#include <string.h> +#endif /* defined(unix) */ +#include <ctype.h> +#include "../ctlr/function.h" + +#include "dohits.h" + + +int +main(argc, argv) +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/usr.bin/tn3270/tools/mkmake.y b/usr.bin/tn3270/tools/mkmake.y new file mode 100644 index 0000000..e9c2c6b --- /dev/null +++ b/usr.bin/tn3270/tools/mkmake.y @@ -0,0 +1,1097 @@ +%{ + +/*- + * 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. 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. + */ + +#ifndef lint +static char sccsid[] = "@(#)mkmake.y 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +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 dependancy. + */ + +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 <ctype.h> + +static int last_char, last_saved = 0; +static int column = 0, lineno = 1; + + +static string_t + *strings = 0; + +static same_t + *shell_variables = 0, + *shell_special = 0, + *variables = 0, + *targets = 0, + *actions = 0; + +static same_t + *null, + *blank, + *cwd_line, + *newline; + +extern char *malloc(); + +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--) + +yyerror(s) +char *s; +{ + fprintf(stderr, "line %d, character %d: %s\n", lineno, column, s); + do_dump(); +} + +int +visitcheck(same) +same_t *same; +{ + if (same->string == 0) { + yyerror("BUG - freed 'same' in use..."); + exit(1); + } + return 0; +} + +int +string_hashof(string, length) +char *string; +int length; +{ + register int i = 0; + + while (length--) { + i = (i<<3) + *string ^ ((i>>28)&0x7); + } + return i; +} + +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; + } +} + +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)) + +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; +} + +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; + } +} + +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; +} + +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; +} + + +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); + } +} + + +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); +} + +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; +} + +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; +} + + +same_t * +same_char(ch) +char ch; +{ + char buffer[2]; + + buffer[0] = ch; + buffer[1] = 0; + + return same_item(string_lookup(buffer)); +} + + +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); + } +} + + +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; +} + +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); +} + +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); + } +} + + +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; +} + + +same_t * +ws_merge(list) +same_t *list; +{ + same_t *newlist = 0, *item; + 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); +} + + +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("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; +} + + +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("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; +} + +same_t * +for_statement(special, variable, list) +same_t + *special, + *variable, + *list; +{ + variable->shell_item = special; + variable->value_list = list; + return variable; +} + +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)); +} + + +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; + } +} + + +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; +} + + +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(c) if (yydebug) { \ + printf("[%d]", c); \ + fflush(stdout); \ + } \ + yyval.intval = c; \ + return c; +#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); +} + +main() +{ +#define YYDEBUG + extern int yydebug; + + 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 defined(YYDEBUG) +dump_same(same) +same_t *same; +{ + same_t *same2; + + for (visit(same, same2); !visited(same2); visit_next(same2)) { + printf(same2->string->string); + } + visit_end(); +} +#endif /* YYDEBUG */ + +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(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(same2->string->string); + } + visit_end(); + printf("\n\t"); + for (visit(same->action_list, same2); !visited(same2); + visit_next(same2)) { + printf(same2->string->string); + if (same2->string->string[0] == '\n') { + printf("\t"); + } + } + visit_end(); + printf("\n"); + } + visit_end(); +} diff --git a/usr.bin/tn3270/tools/prt3270.c b/usr.bin/tn3270/tools/prt3270.c new file mode 100644 index 0000000..55d72d5 --- /dev/null +++ b/usr.bin/tn3270/tools/prt3270.c @@ -0,0 +1,620 @@ +/*- + * 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. 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. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)prt3270.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#if defined(unix) +#endif +#include <stdio.h> +#include <ctype.h> + +#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 "../ctlr/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 */ + + +void +putSpace() +{ + extern void Column1(); + 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) +register unsigned char *buffer; /* what the data is */ +register int count; /* and how much there is */ +int control; /* this buffer ended block? */ +{ + int origCount; + register int c; + register 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; + } +} + +int +GetXValue(c) +int c; +{ + if (!isascii(c)) { + fflush(stdout); + fprintf(stderr, "Non-hex digit 0x%x.\n"); + 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); + } +} + +main() +{ + 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; +} |