*
* unix - Compiles in unix specific stuff.
*
- * msdos - Compiles in msdos specific stuff.
+ * MSDOS - Compiles in MSDOS specific stuff.
*
*/
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
#include <netinet/in.h>
+#if defined(unix)
+/* By the way, we need to include curses.h before telnet.h since,
+ * among other things, telnet.h #defines 'DO', which is a variable
+ * declared in curses.h.
+ */
#include <curses.h>
+#endif /* defined(unix) */
#define TELOPTS
#include <arpa/telnet.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
-#include <signal.h>
#include <setjmp.h>
#include <netdb.h>
+
+#if defined(unix)
#include <strings.h>
+#else /* defined(unix) */
+#include <string.h>
+#endif /* defined(unix) */
#if defined(TN3270)
#include "ctlr/screen.h"
#include "ctlr/options.ext"
#include "ctlr/outbound.ext"
#include "keyboard/termin.ext"
-#include "general.h"
#endif /* defined(TN3270) */
+#include "general.h"
autosynch, /* send interrupt characters with SYNCH? */
localchars, /* we recognize interrupt/quit */
donelclchars, /* the user has set "localchars" */
- dontlecho; /* do we suppress local echoing right now? */
+ dontlecho, /* do we suppress local echoing right now? */
+ globalmode;
/* The following are some tn3270 specific flags */
#if defined(TN3270)
static int
Sent3270TerminalType; /* Have we said we are a 3270? */
+/* Some real, live, globals. */
+int
+ tout, /* Output file descriptor */
+ tin; /* Input file descriptor */
+
+#else /* defined(TN3270) */
+static int tin, tout; /* file descriptors */
+#endif /* defined(TN3270) */
+
+
/*
* Telnet receiver states for fsm
*/
#define TS_SE 8 /* looking for sub-option end */
static int telrcv_state = TS_DATA;
-/* Some real, live, globals. */
-int
-#if defined(unix)
- HaveInput, /* There is input available to scan */
-#endif /* defined(unix) */
- tout, /* Output file descriptor */
- tin; /* Input file descriptor */
-#if defined(unix)
-char *transcom = 0; /* transparent mode command (default: none) */
-#endif /* defined(unix) */
-
-#else /* defined(TN3270) */
-static int tin, tout; /* file descriptors */
-#endif /* defined(TN3270) */
static char line[200];
-#if defined(TN3270) && defined(unix)
-static char tline[200];
-#endif /* defined(TN3270) && defined(unix) */
static int margc;
static char *margv[20];
-static jmp_buf toplevel = 0;
+static jmp_buf toplevel = { 0 };
static jmp_buf peerdied;
extern int errno;
static struct servent *sp = 0;
+static int flushline;
+
+static char *hostname;
+static char hnamebuf[32];
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+static struct {
+ int
+ system, /* what the current time is */
+ echotoggle, /* last time user entered echo character */
+ modenegotiated, /* last time operating mode negotiated */
+ didnetreceive, /* last time we read data from network */
+ gotDM; /* when did we last see a data mark */
+} clocks;
+
+#define settimer(x) clocks.x = clocks.system++
+\f
+/* Various modes */
+#define MODE_LINE(m) (modelist[m].modetype & LINE)
+#define MODE_LOCAL_CHARS(m) (modelist[m].modetype & LOCAL_CHARS)
+#define MODE_LOCAL_ECHO(m) (modelist[m].modetype & LOCAL_ECHO)
+#define MODE_COMMAND_LINE(m) (modelist[m].modetype & COMMAND_LINE)
+
+#define LOCAL_CHARS 0x01 /* Characters processed locally */
+#define LINE 0x02 /* Line-by-line mode of operation */
+#define LOCAL_ECHO 0x04 /* Echoing locally */
+#define COMMAND_LINE 0x08 /* Command line mode */
+
+static struct {
+ char *modedescriptions;
+ char modetype;
+} modelist[] = {
+ { "telnet command mode", COMMAND_LINE },
+ { "character-at-a-time mode", 0 },
+ { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
+ { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
+ { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
+ { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
+ { "3270 mode", 0 },
+};
+
+\f
+/*
+ * The following routines try to encapsulate what is system dependent
+ * (at least between 4.x and dos) which is used in telnet.c.
+ */
+
+#if defined(unix)
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <signal.h>
+
+int
+ HaveInput; /* There is input available to scan */
+
+#if defined(TN3270)
+static char tline[200];
+char *transcom = 0; /* transparent mode command (default: none) */
+#endif /* defined(TN3270) */
+
static struct tchars otc = { 0 }, ntc = { 0 };
static struct ltchars oltc = { 0 }, nltc = { 0 };
static struct sgttyb ottyb = { 0 }, nttyb = { 0 };
-static int flushline;
-static char *hostname;
-static char hnamebuf[32];
-/*
- * The following are some clocks used to decide how to interpret
- * the relationship between various variables.
- */
+#define TerminalWrite(fd,buf,n) write(fd,buf,n)
+#define TerminalRead(fd,buf,n) read(fd,buf,n)
+
+/*
+ *
+ */
+
+static int
+TerminalAutoFlush() /* unix */
+{
+#if defined(LNOFLSH)
+ ioctl(0, TIOCLGET, (char *)&autoflush);
+ return !(autoflush&LNOFLSH); /* if LNOFLSH, no autoflush */
+#else /* LNOFLSH */
+ return 1;
+#endif /* LNOFLSH */
+}
+
+/*
+ * TerminalSpecialChars()
+ *
+ * Look at an input character to see if it is a special character
+ * and decide what to do.
+ *
+ * Output:
+ *
+ * 0 Don't add this character.
+ * 1 Do add this character
+ */
+
+int
+TerminalSpecialChars(c) /* unix */
+int c;
+{
+ void doflush(), intp(), sendbrk();
+
+ if (c == ntc.t_intrc) {
+ intp();
+ return 0;
+ } else if (c == ntc.t_quitc) {
+ sendbrk();
+ return 0;
+ } else if (c == nltc.t_flushc) {
+ NET2ADD(IAC, AO);
+ if (autoflush) {
+ doflush();
+ }
+ return 0;
+ } else if (!MODE_LOCAL_CHARS(globalmode)) {
+ if (c == nttyb.sg_kill) {
+ NET2ADD(IAC, EL);
+ return 0;
+ } else if (c == nttyb.sg_erase) {
+ NET2ADD(IAC, EC);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+
+static void
+TerminalFlushOutput() /* unix */
+{
+ (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
+}
+
+static void
+TerminalSaveState() /* unix */
+{
+ ioctl(0, TIOCGETP, (char *)&ottyb);
+ ioctl(0, TIOCGETC, (char *)&otc);
+ ioctl(0, TIOCGLTC, (char *)&oltc);
+
+ ntc = otc;
+ nltc = oltc;
+ nttyb = ottyb;
+}
+
+static void
+TerminalRestoreState() /* unix */
+{
+}
+
+/*
+ * TerminalNewMode - set up terminal to a specific mode.
+ */
+
+
+static void
+TerminalNewMode(f) /* unix */
+register int f;
+{
+ static int prevmode = 0;
+ struct tchars *tc;
+ struct tchars tc3;
+ struct ltchars *ltc;
+ struct sgttyb sb;
+ int onoff;
+ int old;
+ struct tchars notc2;
+ struct ltchars noltc2;
+ static struct tchars notc = { -1, -1, -1, -1, -1, -1 };
+ static struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
+
+ globalmode = f;
+ if (prevmode == f)
+ return;
+ old = prevmode;
+ prevmode = f;
+ sb = nttyb;
+
+ switch (f) {
+
+ case 0:
+ onoff = 0;
+ tc = &otc;
+ ltc = &oltc;
+ break;
+
+ case 1: /* remote character processing, remote echo */
+ case 2: /* remote character processing, local echo */
+ case 6: /* 3270 mode - like 1, but with xon/xoff local */
+ /* (might be nice to have "6" in telnet also...) */
+ sb.sg_flags |= CBREAK;
+ if ((f == 1) || (f == 6)) {
+ sb.sg_flags &= ~(ECHO|CRMOD);
+ } else {
+ sb.sg_flags |= ECHO|CRMOD;
+ }
+ sb.sg_erase = sb.sg_kill = -1;
+ if (f == 6) {
+ tc = &tc3;
+ tc3 = notc;
+ /* get XON, XOFF characters */
+ tc3.t_startc = otc.t_startc;
+ tc3.t_stopc = otc.t_stopc;
+ } else {
+ /*
+ * If user hasn't specified one way or the other,
+ * then default to not trapping signals.
+ */
+ if (!donelclchars) {
+ localchars = 0;
+ }
+ if (localchars) {
+ notc2 = notc;
+ notc2.t_intrc = ntc.t_intrc;
+ notc2.t_quitc = ntc.t_quitc;
+ tc = ¬c2;
+ } else {
+ tc = ¬c;
+ }
+ }
+ ltc = &noltc;
+ onoff = 1;
+ break;
+ case 3: /* local character processing, remote echo */
+ case 4: /* local character processing, local echo */
+ case 5: /* local character processing, no echo */
+ sb.sg_flags &= ~CBREAK;
+ sb.sg_flags |= CRMOD;
+ if (f == 4)
+ sb.sg_flags |= ECHO;
+ else
+ sb.sg_flags &= ~ECHO;
+ notc2 = ntc;
+ tc = ¬c2;
+ noltc2 = oltc;
+ ltc = &noltc2;
+ /*
+ * If user hasn't specified one way or the other,
+ * then default to trapping signals.
+ */
+ if (!donelclchars) {
+ localchars = 1;
+ }
+ if (localchars) {
+ notc2.t_brkc = nltc.t_flushc;
+ noltc2.t_flushc = -1;
+ } else {
+ notc2.t_intrc = notc2.t_quitc = -1;
+ }
+ noltc2.t_suspc = escape;
+ noltc2.t_dsuspc = -1;
+ onoff = 1;
+ break;
+
+ default:
+ return;
+ }
+ ioctl(tin, TIOCSLTC, (char *)ltc);
+ ioctl(tin, TIOCSETC, (char *)tc);
+ ioctl(tin, TIOCSETP, (char *)&sb);
+#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
+ ioctl(tin, FIONBIO, (char *)&onoff);
+ ioctl(tout, FIONBIO, (char *)&onoff);
+#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
+#if defined(TN3270) && !defined(DEBUG)
+ ioctl(tin, FIOASYNC, (char *)&onoff);
+#endif /* defined(TN3270) && !defined(DEBUG) */
+
+ if (MODE_LINE(f)) {
+ void doescape();
+
+ signal(SIGTSTP, doescape);
+ } else if (MODE_LINE(old)) {
+ signal(SIGTSTP, SIG_DFL);
+ sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
+ }
+}
+
+
+int
+NetClose(net)
+int net;
+{
+ return close(net);
+}
+
+
+static void
+NetNonblockingIO(fd, onoff) /* unix */
+int
+ fd,
+ onoff;
+{
+ ioctl(net, FIONBIO, (char *)&onoff);
+}
+
+static void
+NetSigIO(fd, onoff) /* unix */
+int
+ fd,
+ onoff;
+{
+ ioctl(net, FIOASYNC, (char *)&onoff); /* hear about input */
+}
+
+static void
+NetSetPgrp(fd) /* unix */
+int fd;
+{
+ int myPid;
+
+ myPid = getpid();
+#if defined(NOT43)
+ myPid = -myPid;
+#endif /* defined(NOT43) */
+ ioctl(net, SIOCSPGRP, (char *)&myPid); /* set my pid */
+}
+
+
+#endif /* defined(unix) */
+\f
+#if defined(MSDOS)
+#include <time.h>
+#include <signal.h>
+#include <process.h>
+
+#if !defined(SO_OOBINLINE)
+#define SO_OOBINLINE
+#endif /* !defined(SO_OOBINLINE) */
+
+
+static char
+ termEofChar,
+ termEraseChar,
+ termFlushChar,
+ termIntChar,
+ termKillChar,
+ termLiteralNextChar,
+ termQuitChar;
+
+\f
+/*
+ * MSDOS doesn't have anyway of deciding whether a full-edited line
+ * is ready to be read in, so we need to do character-by-character
+ * reads, and then do the editing in the program (in the case where
+ * we are supporting line-by-line mode).
+ *
+ * The following routines, which are internal to the MSDOS-specific
+ * code, accomplish this miracle.
+ */
+
+#define Hex(c) HEX[(c)&0xff]
+
+static survivorSetup = 0; /* Do we have ^C hooks in? */
+
+static int
+ lineend = 0, /* There is a line terminator */
+ ctrlCCount = 0;
+
+static char linein[200], /* Where input line is assembled */
+ *nextin = linein, /* Next input character */
+ *nextout = linein; /* Next character to be consumed */
+
+#define consumechar() \
+ if ((++nextout) >= nextin) { \
+ nextout = nextin = linein; \
+ lineend = 0; \
+ }
+
+#define characteratatime() (!MODE_LINE(globalmode)) /* one by one */
+
+
+/*
+ * killone()
+ *
+ * Erase the last character on the line.
+ */
+
+static void
+killone()
+{
+ if (lineend) {
+ return; /* ??? XXX */
+ }
+ if (nextin == linein) {
+ return; /* Nothing to do */
+ }
+ nextin--;
+ if (!(isspace(*nextin) || isprint(*nextin))) {
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+ }
+ putchar('\b');
+ putchar(' ');
+ putchar('\b');
+}
+
+
+/*
+ * setlineend()
+ *
+ * Decide if it's time to send the current line up to the user
+ * process.
+ */
+
+static void
+setlineend()
+{
+ if (nextin == nextout) {
+ return;
+ }
+ if (characteratatime()) {
+ lineend = 1;
+ } else if (nextin >= (linein+sizeof linein)) {
+ lineend = 1;
+ } else {
+ int c = *(nextin-1);
+ if ((c == termIntChar)
+ || (c == termQuitChar)
+ || (c == termEofChar)) {
+ lineend = 1;
+ } else if (c == termFlushChar) {
+ lineend = 1;
+ } else if ((c == '\n') || (c == '\r')) {
+ lineend = 1;
+ }
+ }
+ /* Otherwise, leave it alone (reset by 'consumechar') */
+}
+
+/*
+ * OK, what we do here is:
+ *
+ * o If we are echoing, then
+ * o Look for character erase, line kill characters
+ * o Echo the character (using '^' if a control character)
+ * o Put the character in the input buffer
+ * o Set 'lineend' as necessary
+ */
+
+static void
+DoNextChar(c)
+int c; /* Character to process */
+{
+ static char literalnextcharacter = 0;
+
+ if (nextin >= (linein+sizeof linein)) {
+ putchar('\7'); /* Ring bell */
+ setlineend();
+ return;
+ }
+ if (MODE_LOCAL_CHARS(globalmode)) {
+ /* Look for some special character */
+ if (!literalnextcharacter) {
+ if (c == termEraseChar) {
+ killone();
+ setlineend();
+ return;
+ } else if (c == termKillChar) {
+ while (nextin != linein) {
+ killone();
+ }
+ setlineend();
+ return;
+ } else if (c == termLiteralNextChar) {
+ literalnextcharacter = 1;
+ return;
+ }
+ }
+
+ if (MODE_LOCAL_ECHO(globalmode)) {
+ if ((literalnextcharacter == 0) && ((c == '\r') || (c == '\n'))) {
+ putchar('\r');
+ putchar('\n');
+ c = '\n';
+ } else if (!isprint(c) && !isspace(c)) {
+ putchar('^');
+ putchar(c^0x40);
+ } else {
+ putchar(c);
+ }
+ }
+ literalnextcharacter = 0;
+ }
+ *nextin++ = c;
+ setlineend();
+}
+
+static int
+inputExists()
+{
+ int input;
+ static state = 0;
+
+ while (ctrlCCount) {
+ DoNextChar(0x03);
+ ctrlCCount--;
+ }
+ if (lineend) {
+ return 1;
+ }
+#if 1 /* For BIOS variety of calls */
+ if (kbhit() == 0) {
+ return lineend;
+ }
+ input = getch(); /* MSC - get console character */
+ if ((input&0xff) == 0) {
+ DoNextChar(0x01); /* ^A */
+ } else {
+ DoNextChar(input&0xff);
+ }
+#else /* 0 */
+ if ((input = dirconio()) == -1) {
+ return lineend;
+ }
+ if ((input&0xff) == 0) {
+ if ((input&0xff00) == 0x0300) { /* Null */
+ DoNextChar(0);
+ } else {
+ DoNextChar(0x01);
+ if (input&0x8000) {
+ DoNextChar(0x01);
+ DoNextChar((input>>8)&0x7f);
+ } else {
+ DoNextChar((input>>8)&0xff);
+ }
+ }
+ } else {
+ DoNextChar(input&0xff);
+ }
+#endif /* 0 */
+ return lineend;
+}
+
+
+void
+CtrlCInterrupt()
+{
+ if (!MODE_COMMAND_LINE(globalmode)) {
+ ctrlCCount++; /* XXX */
+ signal(SIGINT, CtrlCInterrupt);
+ } else {
+ closeallsockets();
+ exit(1);
+ }
+}
+\f
+/*
+ * The MSDOS routines, called from elsewhere.
+ */
+
+
+static int
+TerminalAutoFlush() /* MSDOS */
+{
+ return 1;
+}
+
+static int
+TerminalCanRead()
+{
+ return inputExists();
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+
+static void
+TerminalFlushOutput() /* MSDOS */
+{
+}
+
+
+static void
+TerminalNewMode(f) /* MSDOS */
+register int f;
+{
+ globalmode = f;
+ signal(SIGINT, CtrlCInterrupt);
+}
+
+
+int
+TerminalRead(fd, buffer, count)
+int fd;
+char *buffer;
+int count;
+{
+ int done = 0;
+
+ for (;;) {
+ while (inputExists() && (done < count)) {
+ *buffer++ = *nextout;
+ consumechar();
+ done++;
+ }
+ if (done) {
+ return(done);
+ } else {
+ return 0;
+ }
+ }
+}
+
+
+static void
+TerminalSaveState() /* MSDOS */
+{
+}
+
+int
+TerminalSpecialChars(c) /* MSDOS */
+{
+ return 1;
+}
+
+
+static void
+TerminalRestoreState() /* MSDOS */
+{
+}
+
+
+static int
+TerminalWrite(fd, buffer, count) /* MSDOS */
+int fd;
+char *buffer;
+int count;
+{
+ return fwrite(buffer, sizeof (char), count, stdout);
+}
+
+
+static int
+NetClose(fd)
+{
+ return closesocket(fd);
+}
+
+static void
+NetNonblockingIO(fd, onoff) /* MSDOS */
+int
+ fd,
+ onoff;
+{
+ if (SetSockOpt(net, SOL_SOCKET, SO_NONBLOCKING, onoff)) {
+ perror("setsockop (SO_NONBLOCKING) ");
+ ExitString(stderr, "exiting\n", 1);
+ }
+}
+
+static void
+NetSigIO(fd) /* MSDOS */
+int fd;
+{
+}
+
+static void
+NetSetPgrp(fd) /* MSDOS */
+int fd;
+{
+}
-static struct {
- int
- system, /* what the current time is */
- echotoggle, /* last time user entered echo character */
- modenegotiated, /* last time operating mode negotiated */
- didnetreceive, /* last time we read data from network */
- gotDM; /* when did we last see a data mark */
-} clocks;
-#define settimer(x) clocks.x = clocks.system++
+#endif /* defined(MSDOS) */
\f
/*
* Initialize variables.
static void
tninit()
{
+#if defined(TN3270)
+ Sent3270TerminalType = 0;
Ifrontp = Ibackp = Ibuf;
+#endif /* defined(TN3270) */
+
tfrontp = tbackp = ttyobuf;
nfrontp = nbackp = netobuf;
connected = net = scc = tcc = In3270 = ISend = 0;
telnetport = 0;
-
- SYNCHing = 0;
- Sent3270TerminalType = 0;
-
#if defined(unix)
HaveInput = 0;
#endif /* defined(unix) */
+
+ SYNCHing = 0;
+
errno = 0;
flushline = 0;
argument++;
}
}
+
+/*
+ * SetSockOpt()
+ *
+ * Compensate for differences in 4.2 and 4.3 systems.
+ */
+
+static int
+SetSockOpt(fd, level, option, yesno)
+int
+ fd,
+ level,
+ option,
+ yesno;
+{
+#ifndef NOT43
+ return setsockopt(fd, level, option,
+ (char *)&yesno, sizeof yesno);
+#else /* NOT43 */
+ if (yesno == 0) { /* Can't do that in 4.2! */
+ fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
+ option);
+ return -1;
+ }
+ return setsockopt(fd, level, option, 0, 0);
+#endif /* NOT43 */
+}
\f
/*
* The following are routines used to print out debugging information.
char tmpbuf[sizeof subbuffer];
int minlen = min(length, sizeof tmpbuf);
- bcopy(pointer+2, tmpbuf, minlen);
+ memcpy(tmpbuf, pointer+2, minlen);
tmpbuf[minlen-1] = 0;
fprintf(NetTrace, "is %s.\n", tmpbuf);
}
if ((n = nfrontp - nbackp) > 0) {
if (!neturg) {
- n = write(net, nbackp, n); /* normal write */
+ n = send(net, nbackp, n, 0); /* normal write */
} else {
n = neturg - nbackp;
/*
if (errno != ENOBUFS && errno != EWOULDBLOCK) {
setcommandmode();
perror(hostname);
- close(net);
+ NetClose(net);
neturg = 0;
longjmp(peerdied, -1);
/*NOTREACHED*/
next = nextitem(next);
} while (wewant(next) && (nfrontp > next));
length = next-thisitem;
- bcopy(thisitem, good, length);
+ memcpy(good, thisitem, length);
good += length;
thisitem = next;
} else {
if ((n = tfrontp - tbackp) > 0) {
if (!(SYNCHing||flushout)) {
- n = write(tout, tbackp, n);
+ n = TerminalWrite(tout, tbackp, n);
} else {
- ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
+ TerminalFlushOutput();
/* we leave 'n' alone! */
}
}
}
#endif /* defined(unix) */
\f
-static int globalmode = 0;
-/* Various modes */
-#define MODE_LINE(m) (modelist[m].modetype & LINE)
-#define MODE_LOCAL_CHARS(m) (modelist[m].modetype & LOCAL_CHARS)
-
-#define LOCAL_CHARS 0x01 /* Characters processed locally */
-#define LINE 0x02 /* Line-by-line mode of operation */
-
-static struct {
- char *modedescriptions;
- char modetype;
-} modelist[] = {
- { "telnet command mode", 0 },
- { "character-at-a-time mode", 0 },
- { "character-at-a-time mode (local echo)", LOCAL_CHARS },
- { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
- { "line-by-line mode", LINE | LOCAL_CHARS },
- { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
- { "3270 mode", 0 },
-};
-/*
- * Mode - set up terminal to a specific mode.
- */
-
-
-static void
-mode(f)
- register int f;
-{
- static int prevmode = 0;
- struct tchars *tc;
- struct tchars tc3;
- struct ltchars *ltc;
- struct sgttyb sb;
- int onoff;
-#if defined(unix)
- int old;
-#endif /* defined(unix) */
- struct tchars notc2;
- struct ltchars noltc2;
- static struct tchars notc = { -1, -1, -1, -1, -1, -1 };
- static struct ltchars noltc = { -1, -1, -1, -1, -1, -1 };
-
- globalmode = f;
- if (prevmode == f)
- return;
-#if defined(unix)
- old = prevmode;
-#endif /* defined(unix) */
- prevmode = f;
- sb = nttyb;
-
- switch (f) {
-
- case 0:
- onoff = 0;
- tc = &otc;
- ltc = &oltc;
- break;
-
- case 1: /* remote character processing, remote echo */
- case 2: /* remote character processing, local echo */
- case 6: /* 3270 mode - like 1, but with xon/xoff local */
- /* (might be nice to have "6" in telnet also...) */
- sb.sg_flags |= CBREAK;
- if ((f == 1) || (f == 6)) {
- sb.sg_flags &= ~(ECHO|CRMOD);
- } else {
- sb.sg_flags |= ECHO|CRMOD;
- }
- sb.sg_erase = sb.sg_kill = -1;
- if (f == 6) {
- tc = &tc3;
- tc3 = notc;
- /* get XON, XOFF characters */
- tc3.t_startc = otc.t_startc;
- tc3.t_stopc = otc.t_stopc;
- } else {
- /*
- * If user hasn't specified one way or the other,
- * then default to not trapping signals.
- */
- if (!donelclchars) {
- localchars = 0;
- }
- if (localchars) {
- notc2 = notc;
- notc2.t_intrc = ntc.t_intrc;
- notc2.t_quitc = ntc.t_quitc;
- tc = ¬c2;
- } else {
- tc = ¬c;
- }
- }
- ltc = &noltc;
- onoff = 1;
- break;
- case 3: /* local character processing, remote echo */
- case 4: /* local character processing, local echo */
- case 5: /* local character processing, no echo */
- sb.sg_flags &= ~CBREAK;
- sb.sg_flags |= CRMOD;
- if (f == 4)
- sb.sg_flags |= ECHO;
- else
- sb.sg_flags &= ~ECHO;
- notc2 = ntc;
- tc = ¬c2;
- noltc2 = oltc;
- ltc = &noltc2;
-#if defined(unix)
- /*
- * If user hasn't specified one way or the other,
- * then default to trapping signals.
- */
- if (!donelclchars) {
- localchars = 1;
- }
- if (localchars) {
- notc2.t_brkc = nltc.t_flushc;
- noltc2.t_flushc = -1;
- } else {
- notc2.t_intrc = notc2.t_quitc = -1;
- }
-#else /* defined(unix) */
- notc2.t_intrc = -1;
-#endif /* defined(unix) */
- noltc2.t_suspc = escape;
- noltc2.t_dsuspc = -1;
- onoff = 1;
- break;
-
- default:
- return;
- }
- ioctl(tin, TIOCSLTC, (char *)ltc);
- ioctl(tin, TIOCSETC, (char *)tc);
- ioctl(tin, TIOCSETP, (char *)&sb);
-#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
- ioctl(tin, FIONBIO, (char *)&onoff);
- ioctl(tout, FIONBIO, (char *)&onoff);
-#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
-#if defined(TN3270) && !defined(DEBUG)
- ioctl(tin, FIOASYNC, (char *)&onoff);
-#endif /* defined(TN3270) && !defined(DEBUG) */
-
-#if defined(unix)
- if (MODE_LINE(f)) {
- signal(SIGTSTP, doescape);
- } else if (MODE_LINE(old)) {
- signal(SIGTSTP, SIG_DFL);
- sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
- }
-#endif /* defined(unix) */
-}
-\f
/*
* These routines decides on what the mode should be (based on the values
* of various global variables).
void
setconnmode()
{
- mode(getconnmode());
+ TerminalNewMode(getconnmode());
}
void
setcommandmode()
{
- mode(0);
+ TerminalNewMode(0);
}
\f
static void
* on the format of our screen, and (in the future) color
* capaiblities.
*/
- if ((initscr() != ERR) && /* Initialize curses to get line size */
- (LINES >= 24) && (COLS >= 80)) {
+#if defined(unix)
+ if (initscr() != ERR) { /* Initialize curses to get line size */
+ MaxNumberLines = LINES;
+ MaxNumberColumns = COLS;
+ }
+#else /* defined(unix) */
+ InitTerminal();
+#endif /* defined(unix) */
+ if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
Sent3270TerminalType = 1;
- if ((LINES >= 27) && (COLS >= 132)) {
+ if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
MaxNumberLines = 27;
MaxNumberColumns = 132;
sb_terminal[SBTERMMODEL] = '5';
- } else if (LINES >= 43) {
+ } else if (MaxNumberLines >= 43) {
MaxNumberLines = 43;
MaxNumberColumns = 80;
sb_terminal[SBTERMMODEL] = '4';
- } else if (LINES >= 32) {
+ } else if (MaxNumberLines >= 32) {
MaxNumberLines = 32;
MaxNumberColumns = 80;
sb_terminal[SBTERMMODEL] = '3';
"Programming error: MAXSCREENSIZE too small.\n", 1);
/*NOTREACHED*/
}
- bcopy(sb_terminal, nfrontp, sizeof sb_terminal);
+ memcpy(nfrontp, sb_terminal, sizeof sb_terminal);
printsub(">", nfrontp+2, sizeof sb_terminal-2);
nfrontp += sizeof sb_terminal;
return;
register int count; /* how much to send */
{
int origCount;
+#if defined(unix)
fd_set o;
- origCount = count;
FD_ZERO(&o);
+#endif /* defined(unix) */
+ origCount = count;
while (count) {
if (tfrontp >= ttyobuf+sizeof ttyobuf) {
ttyflush();
while (tfrontp >= ttyobuf+sizeof ttyobuf) {
+#if defined(unix)
FD_SET(tout, &o);
(void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
(struct timeval *) 0);
+#endif /* defined(unix) */
ttyflush();
}
}
void
EmptyTerminal()
{
+#if defined(unix)
fd_set o;
FD_ZERO(&o);
+#endif /* defined(unix) */
if (tfrontp == tbackp) {
+#if defined(unix)
FD_SET(tout, &o);
(void) select(tout+1, (int *) 0, &o, (int *) 0,
(struct timeval *) 0); /* wait for TTLOWAT */
+#endif /* defined(unix) */
} else {
while (tfrontp != tbackp) {
ttyflush();
+#if defined(unix)
FD_SET(tout, &o);
(void) select(tout+1, (int *) 0, &o, (int *) 0,
(struct timeval *) 0); /* wait for TTLOWAT */
+#endif /* defined(unix) */
}
}
}
if (scc) {
if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
if (Ibackp != Ibuf) {
- bcopy(Ibackp, Ibuf, Ifrontp-Ibackp);
+ memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
Ifrontp -= (Ibackp-Ibuf);
Ibackp = Ibuf;
}
if ((!MODE_LINE(globalmode) || flushline) && NETBYTES()) {
FD_SET(net, &obits);
}
+#if !defined(MSDOS)
if (TTYBYTES()) {
FD_SET(tout, &obits);
}
if ((tcc == 0) && NETROOM()) {
FD_SET(tin, &ibits);
}
+#endif /* !defined(MSDOS) */
# if !defined(TN3270)
if (TTYROOM()) {
FD_SET(net, &ibits);
}
#endif /* defined(TN3270) && defined(unix) */
if ((c = select(16, &ibits, &obits, &xbits,
- block? (struct timeval *)0 : &TimeValue)) < 1) {
+ block? (struct timeval *)0 : &TimeValue)) < 0) {
if (c == -1) {
/*
* we can get EINTR if we are in line mode,
if (atmark) {
c = recv(net, sbp+scc, canread, MSG_OOB);
if ((c == -1) && (errno == EINVAL)) {
- c = read(net, sbp+scc, canread);
+ c = recv(net, sbp+scc, canread, 0);
if (clocks.didnetreceive < clocks.gotDM) {
SYNCHing = stilloob(net);
}
}
} else {
- c = read(net, sbp+scc, canread);
+ c = recv(net, sbp+scc, canread, 0);
}
} else {
- c = read(net, sbp+scc, canread);
+ c = recv(net, sbp+scc, canread, 0);
}
settimer(didnetreceive);
#else /* !defined(SO_OOBINLINE) */
- c = read(net, sbp+scc, canread);
+ c = recv(net, sbp+scc, canread, 0);
#endif /* !defined(SO_OOBINLINE) */
if (c < 0 && errno == EWOULDBLOCK) {
c = 0;
/*
* Something to read from the tty...
*/
- if (FD_ISSET(tin, &ibits)) {
+#if defined(MSDOS)
+ if ((tcc == 0) && NETROOM() && TerminalCanRead())
+#else /* defined(MSDOS) */
+ if (FD_ISSET(tin, &ibits))
+#endif /* defined(MSDOS) */
+ {
FD_CLR(tin, &ibits);
if (tcc == 0) {
tbp = tibuf; /* nothing left, reset */
}
- c = read(tin, tbp, tibuf+sizeof tibuf - tbp);
+ c = TerminalRead(tin, tbp, tibuf+sizeof tibuf - tbp);
if (c < 0 && errno == EWOULDBLOCK) {
c = 0;
} else {
+#if defined(unix)
/* EOF detection for line mode!!!! */
if (c == 0 && MODE_LOCAL_CHARS(globalmode)) {
/* must be an EOF... */
*tbp = ntc.t_eofc;
c = 1;
}
+#endif /* defined(unix) */
if (c <= 0) {
tcc = c;
return -1;
}
}
if (localchars) {
- if (sc == ntc.t_intrc) {
- intp();
- break;
- } else if (sc == ntc.t_quitc) {
- sendbrk();
- break;
- } else if (sc == nltc.t_flushc) {
- NET2ADD(IAC, AO);
- if (autoflush) {
- doflush();
- }
- break;
- } else if (MODE_LOCAL_CHARS(globalmode)) {
- ;
- } else if (sc == nttyb.sg_kill) {
- NET2ADD(IAC, EL);
- break;
- } else if (sc == nttyb.sg_erase) {
- NET2ADD(IAC, EC);
+ if (TerminalSpecialChars(sc) == 0) {
break;
}
}
returnValue = Push3270();
# endif /* !defined(TN3270) */
}
- if (FD_ISSET(tout, &obits) && (TTYBYTES() > 0)) {
+#if defined(MSDOS)
+ if (TTYBYTES())
+#else /* defined(MSDOS) */
+ if (FD_ISSET(tout, &obits) && (TTYBYTES() > 0))
+#endif /* defined(MSDOS) */
+ {
FD_CLR(tout, &obits);
returnValue = ttyflush();
}
static void
telnet()
{
- int on = 1;
+#if defined(MSDOS)
+#define SCHED_BLOCK 0 /* Don't block in MSDOS */
+#else /* defined(MSDOS) */
+#define SCHED_BLOCK 1
+#endif /* defined(MSDOS) */
+
#if defined(TN3270) && defined(unix)
int myPid;
#endif /* defined(TN3270) */
FD_ZERO(&obits);
FD_ZERO(&xbits);
- ioctl(net, FIONBIO, (char *)&on);
+ NetNonblockingIO(net, 1);
#if defined(TN3270)
#if !defined(DEBUG) /* DBX can't handle! */
- ioctl(net, FIOASYNC, (char *)&on); /* hear about input */
+ NetSigIO(net, 1);
#endif /* !defined(DEBUG) */
-#if defined(unix)
- myPid = getpid();
-#if defined(NOT43)
- myPid = -myPid;
-#endif /* defined(NOT43) */
- ioctl(net, SIOCSPGRP, (char *)&myPid); /* set my pid */
-#endif /* defined(unix) */
-
+ NetSetPgrp(net);
#endif /* defined(TN3270) */
-#if defined(SO_OOBINLINE)
- setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
-#endif /* defined(SO_OOBINLINE) */
+
+#if defined(SO_OOBINLINE) && !defined(MSDOS)
+ SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1);
+#endif /* defined(SO_OOBINLINE) && !defined(MSDOS) */
# if !defined(TN3270)
if (telnetport) {
# if !defined(TN3270)
for (;;) {
- if (Scheduler(1) == -1) {
+ if (Scheduler(SCHED_BLOCK) == -1) {
setcommandmode();
return;
}
int schedValue;
while (!In3270) {
- if (Scheduler(1) == -1) {
+ if (Scheduler(SCHED_BLOCK) == -1) {
setcommandmode();
return;
}
schedValue = DoTerminalOutput();
}
if (schedValue) {
- if (Scheduler(1) == -1) {
+ if (Scheduler(SCHED_BLOCK) == -1) {
setcommandmode();
return;
}
{
#ifndef NOT43
if (net > 0 &&
- setsockopt(net, SOL_SOCKET, SO_DEBUG, (char *)&debug, sizeof(debug))
- < 0) {
+ (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
perror("setsockopt (SO_DEBUG)");
}
#else /* NOT43 */
if (debug) {
- if (net > 0 && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+ if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
perror("setsockopt (SO_DEBUG)");
} else
printf("Cannot turn off socket debugging\n");
{ "escape", "character to escape back to telnet command mode", &escape },
{ " ", "" },
{ " ", "The following need 'localchars' to be toggled true", 0 },
+#if defined(unix)
{ "erase", "character to cause an Erase Character", &nttyb.sg_erase },
{ "flushoutput", "character to cause an Abort Oubput", &nltc.t_flushc },
{ "interrupt", "character to cause an Interrupt Process", &ntc.t_intrc },
{ "kill", "character to cause an Erase Line", &nttyb.sg_kill },
{ "quit", "character to cause a Break", &ntc.t_quitc },
{ "eof", "character to cause an EOF ", &ntc.t_eofc },
+#endif /* defined(unix) */
+#if defined(MSDOS)
+ { "erase", "character to cause an Erase Character", &termEraseChar },
+ { "flushoutput", "character to cause an Abort Oubput", &termFlushChar },
+ { "interrupt", "character to cause an Interrupt Process", &termIntChar },
+ { "kill", "character to cause an Erase Line", &termKillChar },
+ { "quit", "character to cause a Break", &termQuitChar },
+ { "eof", "character to cause an EOF ", &termEofChar },
+#endif /* defined(MSDOS) */
{ 0 }
};
setcommandmode();
#if defined(unix)
kill(0, SIGTSTP);
-#endif /* defined(unix) */
/* reget parameters in case they were changed */
- ioctl(0, TIOCGETP, (char *)&ottyb);
- ioctl(0, TIOCGETC, (char *)&otc);
- ioctl(0, TIOCGLTC, (char *)&oltc);
+ TerminalSaveState();
+#endif /* defined(unix) */
return 1;
}
if (connected) {
shutdown(net, 2);
printf("Connection closed.\n");
- close(net);
+ NetClose(net);
connected = 0;
/* reset options */
tninit();
#endif /* defined(TN3270) && defined(unix) */
+
static
tn(argc, argv)
int argc;
char *argv[];
{
register struct hostent *host = 0;
-#if defined(msdos)
+#if defined(MSDOS)
char *cp;
-#endif /* defined(msdos) */
+#endif /* defined(MSDOS) */
if (connected) {
printf("?Already connected to %s\n", hostname);
printf("usage: %s host-name [port]\n", argv[0]);
return 0;
}
-#if defined(msdos)
+#if defined(MSDOS)
for (cp = argv[1]; *cp; cp++) {
if (isupper(*cp)) {
*cp = tolower(*cp);
}
}
-#endif /* defined(msdos) */
+#endif /* defined(MSDOS) */
sin.sin_addr.s_addr = inet_addr(argv[1]);
if (sin.sin_addr.s_addr != -1) {
sin.sin_family = AF_INET;
if (host) {
sin.sin_family = host->h_addrtype;
#if defined(h_addr) /* In 4.3, this is a #define */
- bcopy(host->h_addr_list[0], (caddr_t)&sin.sin_addr, host->h_length);
+ memcpy((caddr_t)&sin.sin_addr,
+ host->h_addr_list[0], host->h_length);
#else /* defined(h_addr) */
- bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length);
+ memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
#endif /* defined(h_addr) */
hostname = host->h_name;
} else {
perror("telnet: socket");
return 0;
}
-#ifndef NOT43
- if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG,
- (char *)&debug, sizeof(debug)) < 0)
-#else /* NOT43 */
- if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
-#endif /* NOT43 */
+ if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
perror("setsockopt (SO_DEBUG)");
+ }
if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
#if defined(h_addr) /* In 4.3, this is a #define */
errno = oerrno;
perror((char *)0);
host->h_addr_list++;
- bcopy(host->h_addr_list[0],
- (caddr_t)&sin.sin_addr, host->h_length);
+ memcpy((caddr_t)&sin.sin_addr,
+ host->h_addr_list[0], host->h_length);
fprintf(stderr, "Trying %s...\n",
inet_ntoa(sin.sin_addr));
- (void) close(net);
+ (void) NetClose(net);
continue;
}
#endif /* defined(h_addr) */
call(status, "status", "notmuch", 0);
if (setjmp(peerdied) == 0)
telnet();
+ NetClose(net);
ExitString(stderr, "Connection closed by foreign host.\n",1);
/*NOTREACHED*/
}
openhelp[] = "connect to a site",
closehelp[] = "close current connection",
quithelp[] = "exit telnet",
- zhelp[] = "suspend telnet",
statushelp[] = "print status information",
helphelp[] = "print help information",
sendhelp[] = "transmit special characters ('send ?' for more)",
#if defined(TN3270) && defined(unix)
transcomhelp[] = "specify Unix command for transparent mode pipe",
#endif /* defined(TN3270) && defined(unix) */
+#if defined(unix)
+ zhelp[] = "suspend telnet",
+#endif /* defined(unix */
+#if defined(MSDOS)
+ shellhelp[] = "invoke a subshell",
+#endif /* defined(MSDOS) */
modehelp[] = "try to enter line-by-line or character-at-a-time mode";
-extern int help();
+extern int help(), shell();
static struct cmd cmdtab[] = {
{ "close", closehelp, bye, 1, 1 },
#if defined(TN3270) && defined(unix)
{ "transcom", transcomhelp, settranscom, 1, 0 },
#endif /* defined(TN3270) && defined(unix) */
+#if defined(unix)
{ "z", zhelp, suspend, 1, 0 },
+#endif /* defined(unix) */
+#if defined(MSDOS)
+ { "!", shellhelp, shell, 1, 0 },
+#endif /* defined(MSDOS) */
{ "?", helphelp, help, 1, 0 },
0
};
tninit(); /* Clear out things */
NetTrace = stdout;
- ioctl(0, TIOCGETP, (char *)&ottyb);
- ioctl(0, TIOCGETC, (char *)&otc);
- ioctl(0, TIOCGLTC, (char *)&oltc);
-#if defined(LNOFLSH)
- ioctl(0, TIOCLGET, (char *)&autoflush);
- autoflush = !(autoflush&LNOFLSH); /* if LNOFLSH, no autoflush */
-#else /* LNOFLSH */
- autoflush = 1;
-#endif /* LNOFLSH */
- ntc = otc;
- nltc = oltc;
- nttyb = ottyb;
- setbuf(stdin, (char *)0);
- setbuf(stdout, (char *)0);
+ TerminalSaveState();
+ autoflush = TerminalAutoFlush();
+
prompt = argv[0];
if (argc > 1 && !strcmp(argv[1], "-d")) {
debug = 1;