133685Sbostic /* 233685Sbostic * Copyright (c) 1988 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 533685Sbostic * Redistribution and use in source and binary forms are permitted 634898Sbostic * provided that the above copyright notice and this paragraph are 734898Sbostic * duplicated in all such forms and that any documentation, 834898Sbostic * advertising materials, and other materials related to such 934898Sbostic * distribution and use acknowledge that the software was developed 1034898Sbostic * by the University of California, Berkeley. The name of the 1134898Sbostic * University may not be used to endorse or promote products derived 1234898Sbostic * from this software without specific prior written permission. 1334898Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434898Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534898Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633685Sbostic */ 1733685Sbostic 1833685Sbostic #ifndef lint 19*38810Sborman static char sccsid[] = "@(#)commands.c 1.20 (Berkeley) 08/28/89"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2232144Sminshall #include <sys/types.h> 2336274Sminshall #if defined(unix) 2436274Sminshall #include <sys/file.h> 2536274Sminshall #endif /* defined(unix) */ 2632144Sminshall #include <sys/socket.h> 2732144Sminshall #include <netinet/in.h> 2838689Sborman #ifdef CRAY 2938689Sborman #include <sys/fcntl.h> 30*38810Sborman #endif /* CRAY */ 3132144Sminshall 3232144Sminshall #include <signal.h> 3332144Sminshall #include <netdb.h> 3432144Sminshall #include <ctype.h> 3535298Sminshall #include <varargs.h> 3632144Sminshall 3732144Sminshall #include <arpa/telnet.h> 3832144Sminshall 3934305Sminshall #include "general.h" 4034305Sminshall 4132381Sminshall #include "ring.h" 4232381Sminshall 4332144Sminshall #include "externs.h" 4432144Sminshall #include "defines.h" 4532144Sminshall #include "types.h" 4632144Sminshall 4738689Sborman #ifdef SRCRT 48*38810Sborman # ifndef CRAY 49*38810Sborman # include <netinet/in_systm.h> 50*38810Sborman # ifndef sun 51*38810Sborman # include <machine/endian.h> 52*38810Sborman # endif /* sun */ 53*38810Sborman # endif /* CRAY */ 5438689Sborman #include <netinet/ip.h> 55*38810Sborman #endif /* SRCRT */ 5638689Sborman 5738689Sborman 5832144Sminshall char *hostname; 5938689Sborman extern char *getenv(); 6032144Sminshall 6136180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 6232144Sminshall static char *ambiguous; /* special return value for command routines */ 6332144Sminshall 6432144Sminshall typedef struct { 6532144Sminshall char *name; /* command name */ 6638689Sborman char *help; /* help string (NULL for no help) */ 6732144Sminshall int (*handler)(); /* routine which executes command */ 6832144Sminshall int needconnect; /* Do we need to be connected to execute? */ 6932144Sminshall } Command; 7032144Sminshall 7138689Sborman static char line[256]; 7238689Sborman static char saveline[256]; 7332144Sminshall static int margc; 7432144Sminshall static char *margv[20]; 7532144Sminshall 7632144Sminshall /* 7732144Sminshall * Various utility routines. 7832144Sminshall */ 7932144Sminshall 8036180Sminshall #if !defined(BSD) || (BSD <= 43) 8136180Sminshall 8236180Sminshall char *h_errlist[] = { 8336180Sminshall "Error 0", 8436180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 8536180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 8636180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 8736180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 8836180Sminshall }; 8936180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 9036180Sminshall 9136274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 9236180Sminshall 9336180Sminshall /* 9436180Sminshall * herror -- 9536180Sminshall * print the error indicated by the h_errno value. 9636180Sminshall */ 9736180Sminshall herror(s) 9836180Sminshall char *s; 9936180Sminshall { 10036180Sminshall if (s && *s) { 10136180Sminshall fprintf(stderr, "%s: ", s); 10236180Sminshall } 10336180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 10436180Sminshall fprintf(stderr, "Unknown error\n"); 10536274Sminshall } else if (h_errno == 0) { 10636274Sminshall #if defined(sun) 10736274Sminshall fprintf(stderr, "Host unknown\n"); 10836274Sminshall #endif /* defined(sun) */ 10936180Sminshall } else { 11036180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 11136180Sminshall } 11236180Sminshall } 11336180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 11436180Sminshall 11532144Sminshall static void 11632144Sminshall makeargv() 11732144Sminshall { 11832144Sminshall register char *cp; 11932144Sminshall register char **argp = margv; 12032144Sminshall 12132144Sminshall margc = 0; 12232144Sminshall cp = line; 12332144Sminshall if (*cp == '!') { /* Special case shell escape */ 12438689Sborman strcpy(saveline, line); /* save for shell command */ 12532144Sminshall *argp++ = "!"; /* No room in string to get this */ 12632144Sminshall margc++; 12732144Sminshall cp++; 12832144Sminshall } 12932144Sminshall while (*cp) { 13032144Sminshall while (isspace(*cp)) 13132144Sminshall cp++; 13232144Sminshall if (*cp == '\0') 13332144Sminshall break; 13432144Sminshall *argp++ = cp; 13532144Sminshall margc += 1; 13632144Sminshall while (*cp != '\0' && !isspace(*cp)) 13732144Sminshall cp++; 13832144Sminshall if (*cp == '\0') 13932144Sminshall break; 14032144Sminshall *cp++ = '\0'; 14132144Sminshall } 14232144Sminshall *argp++ = 0; 14332144Sminshall } 14432144Sminshall 14532144Sminshall 14632144Sminshall static char ** 14732144Sminshall genget(name, table, next) 14832144Sminshall char *name; /* name to match */ 14932144Sminshall char **table; /* name entry in table */ 15032144Sminshall char **(*next)(); /* routine to return next entry in table */ 15132144Sminshall { 15232144Sminshall register char *p, *q; 15332144Sminshall register char **c, **found; 15432144Sminshall register int nmatches, longest; 15532144Sminshall 15632144Sminshall if (name == 0) { 15732144Sminshall return 0; 15832144Sminshall } 15932144Sminshall longest = 0; 16032144Sminshall nmatches = 0; 16132144Sminshall found = 0; 16232144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 16332144Sminshall for (q = name; 16432144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 16532144Sminshall if (*q == 0) /* exact match? */ 16632144Sminshall return (c); 16732144Sminshall if (!*q) { /* the name was a prefix */ 16832144Sminshall if (q - name > longest) { 16932144Sminshall longest = q - name; 17032144Sminshall nmatches = 1; 17132144Sminshall found = c; 17232144Sminshall } else if (q - name == longest) 17332144Sminshall nmatches++; 17432144Sminshall } 17532144Sminshall } 17632144Sminshall if (nmatches > 1) 17736180Sminshall return &ambiguous; 17832144Sminshall return (found); 17932144Sminshall } 18032144Sminshall 18132144Sminshall /* 18232144Sminshall * Make a character string into a number. 18332144Sminshall * 18432144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 18532144Sminshall */ 18632144Sminshall 18732144Sminshall static 18832144Sminshall special(s) 18932144Sminshall register char *s; 19032144Sminshall { 19132144Sminshall register char c; 19232144Sminshall char b; 19332144Sminshall 19432144Sminshall switch (*s) { 19532144Sminshall case '^': 19632144Sminshall b = *++s; 19732144Sminshall if (b == '?') { 19832144Sminshall c = b | 0x40; /* DEL */ 19932144Sminshall } else { 20032144Sminshall c = b & 0x1f; 20132144Sminshall } 20232144Sminshall break; 20332144Sminshall default: 20432144Sminshall c = *s; 20532144Sminshall break; 20632144Sminshall } 20732144Sminshall return c; 20832144Sminshall } 20932144Sminshall 21032144Sminshall /* 21132144Sminshall * Construct a control character sequence 21232144Sminshall * for a special character. 21332144Sminshall */ 21432144Sminshall static char * 21532144Sminshall control(c) 21632144Sminshall register int c; 21732144Sminshall { 21832144Sminshall static char buf[3]; 21932144Sminshall 22032144Sminshall if (c == 0x7f) 22132144Sminshall return ("^?"); 22232144Sminshall if (c == '\377') { 22332144Sminshall return "off"; 22432144Sminshall } 22532144Sminshall if (c >= 0x20) { 22632144Sminshall buf[0] = c; 22732144Sminshall buf[1] = 0; 22832144Sminshall } else { 22932144Sminshall buf[0] = '^'; 23032144Sminshall buf[1] = '@'+c; 23132144Sminshall buf[2] = 0; 23232144Sminshall } 23332144Sminshall return (buf); 23432144Sminshall } 23532144Sminshall 23632144Sminshall 23732144Sminshall 23832144Sminshall /* 23932144Sminshall * The following are data structures and routines for 24032144Sminshall * the "send" command. 24132144Sminshall * 24232144Sminshall */ 24332144Sminshall 24432144Sminshall struct sendlist { 24532144Sminshall char *name; /* How user refers to it (case independent) */ 24632144Sminshall char *help; /* Help information (0 ==> no help) */ 24732144Sminshall #if defined(NOT43) 24838689Sborman int (*handler)(); /* Routine to perform (for special ops) */ 24932144Sminshall #else /* defined(NOT43) */ 25038689Sborman void (*handler)(); /* Routine to perform (for special ops) */ 25132144Sminshall #endif /* defined(NOT43) */ 25238689Sborman int what; /* Character to be sent (<0 ==> special) */ 25332144Sminshall }; 25432144Sminshall 25532144Sminshall #define SENDQUESTION -1 25632144Sminshall #define SENDESCAPE -3 25732144Sminshall 25832144Sminshall static struct sendlist Sendlist[] = { 25938689Sborman { "ao", "Send Telnet Abort output", 0, AO }, 26038689Sborman { "ayt", "Send Telnet 'Are You There'", 0, AYT }, 26138689Sborman { "brk", "Send Telnet Break", 0, BREAK }, 26238689Sborman { "ec", "Send Telnet Erase Character", 0, EC }, 26338689Sborman { "el", "Send Telnet Erase Line", 0, EL }, 26438689Sborman { "escape", "Send current escape character", 0, SENDESCAPE }, 26538689Sborman { "ga", "Send Telnet 'Go Ahead' sequence", 0, GA }, 26638689Sborman { "ip", "Send Telnet Interrupt Process", 0, IP }, 26738689Sborman { "nop", "Send Telnet 'No operation'", 0, NOP }, 26838689Sborman { "eor", "Send Telnet 'End of Record'", 0, EOR }, 26938689Sborman { "abort", "Send Telnet 'Abort Process'", 0, ABORT }, 27038689Sborman { "susp", "Send Telnet 'Suspend Process'", 0, SUSP }, 27138689Sborman { "eof", "Send Telnet End of File Character", 0, xEOF }, 27238689Sborman { "synch", "Perform Telnet 'Synch operation'", dosynch, SYNCH }, 27338689Sborman { "?", "Display send options", 0, SENDQUESTION }, 27432144Sminshall { 0 } 27532144Sminshall }; 27632144Sminshall 27732144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 27838689Sborman { "break", 0, 0, BREAK }, 27932144Sminshall 28038689Sborman { "intp", 0, 0, IP }, 28138689Sborman { "interrupt", 0, 0, IP }, 28238689Sborman { "intr", 0, 0, IP }, 28332144Sminshall 28438689Sborman { "help", 0, 0, SENDQUESTION }, 28532144Sminshall 28638689Sborman { 0 } 28732144Sminshall }; 28832144Sminshall 28932144Sminshall static char ** 29032144Sminshall getnextsend(name) 29132144Sminshall char *name; 29232144Sminshall { 29332144Sminshall struct sendlist *c = (struct sendlist *) name; 29432144Sminshall 29532144Sminshall return (char **) (c+1); 29632144Sminshall } 29732144Sminshall 29832144Sminshall static struct sendlist * 29932144Sminshall getsend(name) 30032144Sminshall char *name; 30132144Sminshall { 30232144Sminshall struct sendlist *sl; 30332144Sminshall 30432144Sminshall if ((sl = (struct sendlist *) 30532144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 30632144Sminshall return sl; 30732144Sminshall } else { 30832144Sminshall return (struct sendlist *) 30932144Sminshall genget(name, (char **) Sendlist2, getnextsend); 31032144Sminshall } 31132144Sminshall } 31232144Sminshall 31332144Sminshall static 31432144Sminshall sendcmd(argc, argv) 31532144Sminshall int argc; 31632144Sminshall char **argv; 31732144Sminshall { 31832144Sminshall int what; /* what we are sending this time */ 31932144Sminshall int count; /* how many bytes we are going to need to send */ 32032144Sminshall int i; 32132144Sminshall int question = 0; /* was at least one argument a question */ 32232144Sminshall struct sendlist *s; /* pointer to current command */ 32332144Sminshall 32432144Sminshall if (argc < 2) { 32532144Sminshall printf("need at least one argument for 'send' command\n"); 32632144Sminshall printf("'send ?' for help\n"); 32732144Sminshall return 0; 32832144Sminshall } 32932144Sminshall /* 33032144Sminshall * First, validate all the send arguments. 33132144Sminshall * In addition, we see how much space we are going to need, and 33232144Sminshall * whether or not we will be doing a "SYNCH" operation (which 33332144Sminshall * flushes the network queue). 33432144Sminshall */ 33532144Sminshall count = 0; 33632144Sminshall for (i = 1; i < argc; i++) { 33732144Sminshall s = getsend(argv[i]); 33832144Sminshall if (s == 0) { 33932144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 34032144Sminshall argv[i]); 34132144Sminshall return 0; 34232144Sminshall } else if (Ambiguous(s)) { 34332144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 34432144Sminshall argv[i]); 34532144Sminshall return 0; 34632144Sminshall } 34732144Sminshall switch (s->what) { 34832144Sminshall case SENDQUESTION: 34938689Sborman question = 1; 35032144Sminshall break; 35132144Sminshall case SENDESCAPE: 35232144Sminshall count += 1; 35332144Sminshall break; 35432144Sminshall case SYNCH: 35532144Sminshall count += 2; 35632144Sminshall break; 35732144Sminshall default: 35832144Sminshall count += 2; 35932144Sminshall break; 36032144Sminshall } 36132144Sminshall } 36238689Sborman if (!connected) { 36338689Sborman if (count) 36438689Sborman printf("?Need to be connected first.\n"); 36538689Sborman if (question) { 36638689Sborman for (s = Sendlist; s->name; s++) 36738689Sborman if (s->help) 36838689Sborman printf("%-15s %s\n", s->name, s->help); 36938689Sborman } else 37038689Sborman printf("'send ?' for help\n"); 37138689Sborman return !question; 37238689Sborman } 37332144Sminshall /* Now, do we have enough room? */ 37432144Sminshall if (NETROOM() < count) { 37532144Sminshall printf("There is not enough room in the buffer TO the network\n"); 37632144Sminshall printf("to process your request. Nothing will be done.\n"); 37732144Sminshall printf("('send synch' will throw away most data in the network\n"); 37832144Sminshall printf("buffer, if this might help.)\n"); 37932144Sminshall return 0; 38032144Sminshall } 38132144Sminshall /* OK, they are all OK, now go through again and actually send */ 38232144Sminshall for (i = 1; i < argc; i++) { 38332144Sminshall if ((s = getsend(argv[i])) == 0) { 38432144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 38532144Sminshall quit(); 38632144Sminshall /*NOTREACHED*/ 38732144Sminshall } 38838689Sborman if (s->handler) { 38938689Sborman (*s->handler)(s); 39032144Sminshall } else { 39132144Sminshall switch (what = s->what) { 39232144Sminshall case SYNCH: 39332144Sminshall dosynch(); 39432144Sminshall break; 39532144Sminshall case SENDQUESTION: 39632144Sminshall for (s = Sendlist; s->name; s++) { 39738689Sborman if (s->help) 39838689Sborman printf("%-15s %s\n", s->name, s->help); 39932144Sminshall } 40032144Sminshall question = 1; 40132144Sminshall break; 40232144Sminshall case SENDESCAPE: 40332144Sminshall NETADD(escape); 40432144Sminshall break; 40532144Sminshall default: 40632144Sminshall NET2ADD(IAC, what); 40732144Sminshall break; 40832144Sminshall } 40932144Sminshall } 41032144Sminshall } 41132144Sminshall return !question; 41232144Sminshall } 41332144Sminshall 41432144Sminshall /* 41532144Sminshall * The following are the routines and data structures referred 41632144Sminshall * to by the arguments to the "toggle" command. 41732144Sminshall */ 41832144Sminshall 41932144Sminshall static 42032144Sminshall lclchars() 42132144Sminshall { 42232144Sminshall donelclchars = 1; 42332144Sminshall return 1; 42432144Sminshall } 42532144Sminshall 42632144Sminshall static 42732144Sminshall togdebug() 42832144Sminshall { 42932144Sminshall #ifndef NOT43 43032144Sminshall if (net > 0 && 43132144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 43232144Sminshall perror("setsockopt (SO_DEBUG)"); 43332144Sminshall } 43432144Sminshall #else /* NOT43 */ 43532144Sminshall if (debug) { 43632144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 43732144Sminshall perror("setsockopt (SO_DEBUG)"); 43832144Sminshall } else 43932144Sminshall printf("Cannot turn off socket debugging\n"); 44032144Sminshall #endif /* NOT43 */ 44132144Sminshall return 1; 44232144Sminshall } 44332144Sminshall 44432144Sminshall 44532144Sminshall static int 44632144Sminshall togcrlf() 44732144Sminshall { 44832144Sminshall if (crlf) { 44932144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 45032144Sminshall } else { 45132144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 45232144Sminshall } 45332144Sminshall return 1; 45432144Sminshall } 45532144Sminshall 45632144Sminshall 45732144Sminshall static int 45838689Sborman togbinary(val) 45938689Sborman int val; 46032144Sminshall { 46132144Sminshall donebinarytoggle = 1; 46232144Sminshall 46338689Sborman if (my_want_state_is_will(TELOPT_BINARY) || 46438689Sborman my_want_state_is_do(TELOPT_BINARY)) { 46538689Sborman if (val == 1) 46638689Sborman printf("Already operating in binary mode with remote host.\n"); 46738689Sborman else { 46838689Sborman /* leave binary mode */ 46938689Sborman printf("Negotiating network ascii mode with remote host.\n"); 47038689Sborman tel_leave_binary(); 47138689Sborman } 47237226Sminshall } else { /* Turn off binary mode */ 47338689Sborman if (val == 0) 47438689Sborman printf("Already in network ascii mode with remote host.\n"); 47538689Sborman else { 47638689Sborman printf("Negotiating binary mode with remote host.\n"); 47738689Sborman tel_enter_binary(); 47838689Sborman } 47932144Sminshall } 48032144Sminshall return 1; 48132144Sminshall } 48232144Sminshall 48332144Sminshall 48432144Sminshall 48532144Sminshall extern int togglehelp(); 48638689Sborman extern int slc_check(); 48732144Sminshall 48832144Sminshall struct togglelist { 48932144Sminshall char *name; /* name of toggle */ 49032144Sminshall char *help; /* help message */ 49132144Sminshall int (*handler)(); /* routine to do actual setting */ 49232144Sminshall int *variable; 49332144Sminshall char *actionexplanation; 49432144Sminshall }; 49532144Sminshall 49632144Sminshall static struct togglelist Togglelist[] = { 49732144Sminshall { "autoflush", 49838689Sborman "flushing of output when sending interrupt characters", 49932144Sminshall 0, 50038689Sborman &autoflush, 50138689Sborman "flush output when sending interrupt characters" }, 50232144Sminshall { "autosynch", 50338689Sborman "automatic sending of interrupt characters in urgent mode", 50432144Sminshall 0, 50538689Sborman &autosynch, 50638689Sborman "send interrupt characters in urgent mode" }, 50732144Sminshall { "binary", 50838689Sborman "sending and receiving of binary data", 50932144Sminshall togbinary, 51038689Sborman 0, 51138689Sborman 0 }, 51232144Sminshall { "crlf", 51338689Sborman "sending carriage returns as telnet <CR><LF>", 51432144Sminshall togcrlf, 51538689Sborman &crlf, 51638689Sborman 0 }, 51732144Sminshall { "crmod", 51838689Sborman "mapping of received carriage returns", 51932144Sminshall 0, 52038689Sborman &crmod, 52138689Sborman "map carriage return on output" }, 52232144Sminshall { "localchars", 52338689Sborman "local recognition of certain control characters", 52432144Sminshall lclchars, 52538689Sborman &localchars, 52638689Sborman "recognize certain control characters" }, 52738689Sborman { " ", "", 0 }, /* empty line */ 52838208Sminshall #if defined(unix) && defined(TN3270) 52938208Sminshall { "cursesdata", 53038208Sminshall "(debugging) toggle printing of hexadecimal curses data", 53138208Sminshall 0, 53238689Sborman &cursesdata, 53338689Sborman "print hexadecimal representation of curses data" }, 53438208Sminshall #endif /* defined(unix) && defined(TN3270) */ 53532144Sminshall { "debug", 53638689Sborman "debugging", 53732144Sminshall togdebug, 53838689Sborman &debug, 53938689Sborman "turn on socket level debugging" }, 54032144Sminshall { "netdata", 54138689Sborman "printing of hexadecimal network data (debugging)", 54232144Sminshall 0, 54338689Sborman &netdata, 54438689Sborman "print hexadecimal representation of network traffic" }, 54538689Sborman { "prettydump", 54638689Sborman "output of \"netdata\" to user readable format (debugging)", 54738689Sborman 0, 54838689Sborman &prettydump, 54938689Sborman "print user readable output for \"netdata\"" }, 55032144Sminshall { "options", 55138689Sborman "viewing of options processing (debugging)", 55232144Sminshall 0, 55338689Sborman &showoptions, 55438689Sborman "show option processing" }, 55538208Sminshall #if defined(unix) 55638208Sminshall { "termdata", 55738208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 55838208Sminshall 0, 55938689Sborman &termdata, 56038689Sborman "print hexadecimal representation of terminal traffic" }, 56138208Sminshall #endif /* defined(unix) */ 56232144Sminshall { "?", 56338689Sborman 0, 56438689Sborman togglehelp }, 56532144Sminshall { "help", 56638689Sborman 0, 56738689Sborman togglehelp }, 56832144Sminshall { 0 } 56932144Sminshall }; 57032144Sminshall 57132144Sminshall static 57232144Sminshall togglehelp() 57332144Sminshall { 57432144Sminshall struct togglelist *c; 57532144Sminshall 57632144Sminshall for (c = Togglelist; c->name; c++) { 57738689Sborman if (c->help) { 57838689Sborman if (*c->help) 57938689Sborman printf("%-15s toggle %s\n", c->name, c->help); 58038689Sborman else 58138689Sborman printf("\n"); 58232144Sminshall } 58332144Sminshall } 58438689Sborman printf("\n"); 58538689Sborman printf("%-15s %s\n", "?", "display help information"); 58632144Sminshall return 0; 58732144Sminshall } 58832144Sminshall 58938689Sborman static 59038689Sborman settogglehelp(set) 59138689Sborman int set; 59238689Sborman { 59338689Sborman struct togglelist *c; 59438689Sborman 59538689Sborman for (c = Togglelist; c->name; c++) { 59638689Sborman if (c->help) { 59738689Sborman if (*c->help) 59838689Sborman printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 59938689Sborman c->help); 60038689Sborman else 60138689Sborman printf("\n"); 60238689Sborman } 60338689Sborman } 60438689Sborman } 60538689Sborman 60632144Sminshall static char ** 60732144Sminshall getnexttoggle(name) 60832144Sminshall char *name; 60932144Sminshall { 61032144Sminshall struct togglelist *c = (struct togglelist *) name; 61132144Sminshall 61232144Sminshall return (char **) (c+1); 61332144Sminshall } 61432144Sminshall 61532144Sminshall static struct togglelist * 61632144Sminshall gettoggle(name) 61732144Sminshall char *name; 61832144Sminshall { 61932144Sminshall return (struct togglelist *) 62032144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 62132144Sminshall } 62232144Sminshall 62332144Sminshall static 62432144Sminshall toggle(argc, argv) 62532144Sminshall int argc; 62632144Sminshall char *argv[]; 62732144Sminshall { 62832144Sminshall int retval = 1; 62932144Sminshall char *name; 63032144Sminshall struct togglelist *c; 63132144Sminshall 63232144Sminshall if (argc < 2) { 63332144Sminshall fprintf(stderr, 63432144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 63532144Sminshall return 0; 63632144Sminshall } 63732144Sminshall argc--; 63832144Sminshall argv++; 63932144Sminshall while (argc--) { 64032144Sminshall name = *argv++; 64132144Sminshall c = gettoggle(name); 64232144Sminshall if (Ambiguous(c)) { 64332144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 64432144Sminshall name); 64532144Sminshall return 0; 64632144Sminshall } else if (c == 0) { 64732144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 64832144Sminshall name); 64932144Sminshall return 0; 65032144Sminshall } else { 65132144Sminshall if (c->variable) { 65232144Sminshall *c->variable = !*c->variable; /* invert it */ 65332144Sminshall if (c->actionexplanation) { 65432144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 65532144Sminshall c->actionexplanation); 65632144Sminshall } 65732144Sminshall } 65832144Sminshall if (c->handler) { 65938689Sborman retval &= (*c->handler)(-1); 66032144Sminshall } 66132144Sminshall } 66232144Sminshall } 66332144Sminshall return retval; 66432144Sminshall } 66532144Sminshall 66632144Sminshall /* 66732144Sminshall * The following perform the "set" command. 66832144Sminshall */ 66932144Sminshall 67038689Sborman #ifdef USE_TERMIO 67138689Sborman struct termio new_tc = { 0 }; 67238689Sborman #endif 67338689Sborman 67432144Sminshall struct setlist { 67532144Sminshall char *name; /* name */ 67632144Sminshall char *help; /* help information */ 67738689Sborman void (*handler)(); 67832144Sminshall char *charp; /* where it is located at */ 67932144Sminshall }; 68032144Sminshall 68132144Sminshall static struct setlist Setlist[] = { 68238689Sborman { "echo", "character to toggle local echoing on/off", 0, &echoc }, 68338689Sborman { "escape", "character to escape back to telnet command mode", 0, &escape }, 68438689Sborman { "tracefile", "file to write trace intormation to", SetNetTrace, NetTraceFile}, 68532144Sminshall { " ", "" }, 68638689Sborman { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 68738689Sborman #ifndef CRAY 68838689Sborman { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp }, 68938689Sborman #endif 69038689Sborman { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 69138689Sborman { "quit", "character to cause an Abort process", 0, termQuitCharp }, 69238689Sborman { "eof", "character to cause an EOF ", 0, termEofCharp }, 69338689Sborman { " ", "" }, 69438689Sborman { " ", "The following are for local editing in linemode", 0, 0 }, 69538689Sborman { "erase", "character to use to erase a character", 0, termEraseCharp }, 69638689Sborman { "kill", "character to use to erase a line", 0, termKillCharp }, 69738689Sborman #ifndef CRAY 69838689Sborman { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 69938689Sborman { "susp", "character to cuase a Suspend Process", 0, termSuspCharp }, 70038689Sborman { "reprint", "character to use for line reprint", 0, termRprntCharp }, 70138689Sborman { "worderase", "character to use to erase a word", 0, termWerasCharp }, 70238689Sborman { "start", "character to use for XON", 0, termStartCharp }, 70338689Sborman { "stop", "character to sue for XOFF", 0, termStopCharp }, 70438689Sborman #endif 70532144Sminshall { 0 } 70632144Sminshall }; 70732144Sminshall 70838689Sborman #ifdef CRAY 70938689Sborman /* Work around compiler bug */ 71038689Sborman _setlist_init() 71138689Sborman { 71238689Sborman Setlist[6].charp = &termIntChar; 71338689Sborman Setlist[7].charp = &termQuitChar; 71438689Sborman Setlist[8].charp = &termEofChar; 71538689Sborman Setlist[11].charp = &termEraseChar; 71638689Sborman Setlist[12].charp = &termKillChar; 71738689Sborman } 718*38810Sborman #endif /* CRAY */ 71938689Sborman 72032144Sminshall static char ** 72132144Sminshall getnextset(name) 72232144Sminshall char *name; 72332144Sminshall { 72432144Sminshall struct setlist *c = (struct setlist *)name; 72532144Sminshall 72632144Sminshall return (char **) (c+1); 72732144Sminshall } 72832144Sminshall 72932144Sminshall static struct setlist * 73032144Sminshall getset(name) 73132144Sminshall char *name; 73232144Sminshall { 73332144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 73432144Sminshall } 73532144Sminshall 73632144Sminshall static 73732144Sminshall setcmd(argc, argv) 73832144Sminshall int argc; 73932144Sminshall char *argv[]; 74032144Sminshall { 74132144Sminshall int value; 74232144Sminshall struct setlist *ct; 74338689Sborman struct togglelist *c; 74432144Sminshall 74538689Sborman if (argc < 2 || argc > 3) { 74638689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 74732144Sminshall return 0; 74832144Sminshall } 74938689Sborman if ((argc == 2) && 75038689Sborman ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 75138689Sborman for (ct = Setlist; ct->name; ct++) 75238689Sborman printf("%-15s %s\n", ct->name, ct->help); 75338689Sborman printf("\n"); 75438689Sborman settogglehelp(1); 75538689Sborman printf("%-15s %s\n", "?", "display help information"); 75638689Sborman return 0; 75738689Sborman } 75832144Sminshall 75932144Sminshall ct = getset(argv[1]); 76032144Sminshall if (ct == 0) { 76138689Sborman c = gettoggle(argv[1]); 76238689Sborman if (c == 0) { 76338689Sborman fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 76432144Sminshall argv[1]); 76538689Sborman return 0; 76638689Sborman } else if (Ambiguous(c)) { 76738689Sborman fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 76838689Sborman argv[1]); 76938689Sborman return 0; 77038689Sborman } 77138689Sborman if (c->variable) { 77238689Sborman if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 77338689Sborman *c->variable = 1; 77438689Sborman else if (strcmp("off", argv[2]) == 0) 77538689Sborman *c->variable = 0; 77638689Sborman else { 77738689Sborman printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 77838689Sborman return 0; 77938689Sborman } 78038689Sborman if (c->actionexplanation) { 78138689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 78238689Sborman c->actionexplanation); 78338689Sborman } 78438689Sborman } 78538689Sborman if (c->handler) 78638689Sborman (*c->handler)(1); 78738689Sborman } else if (argc != 3) { 78838689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 78932144Sminshall return 0; 79032144Sminshall } else if (Ambiguous(ct)) { 79132144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 79232144Sminshall argv[1]); 79332144Sminshall return 0; 79438689Sborman } else if (ct->handler) { 79538689Sborman (*ct->handler)(argv[2]); 79638689Sborman printf("%s set to \"%s\".\n", ct->name, ct->charp); 79732144Sminshall } else { 79832144Sminshall if (strcmp("off", argv[2])) { 79932144Sminshall value = special(argv[2]); 80032144Sminshall } else { 80132144Sminshall value = -1; 80232144Sminshall } 80332144Sminshall *(ct->charp) = value; 80432144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 80532144Sminshall } 80638689Sborman slc_check(); 80732144Sminshall return 1; 80832144Sminshall } 80938689Sborman 81038689Sborman static 81138689Sborman unsetcmd(argc, argv) 81238689Sborman int argc; 81338689Sborman char *argv[]; 81438689Sborman { 81538689Sborman int value; 81638689Sborman struct setlist *ct; 81738689Sborman struct togglelist *c; 81838689Sborman register char *name; 81938689Sborman 82038689Sborman if (argc < 2) { 82138689Sborman fprintf(stderr, 82238689Sborman "Need an argument to 'unset' command. 'unset ?' for help.\n"); 82338689Sborman return 0; 82438689Sborman } 82538689Sborman if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) { 82638689Sborman for (ct = Setlist; ct->name; ct++) 82738689Sborman printf("%-15s %s\n", ct->name, ct->help); 82838689Sborman printf("\n"); 82938689Sborman settogglehelp(0); 83038689Sborman printf("%-15s %s\n", "?", "display help information"); 83138689Sborman return 0; 83238689Sborman } 83338689Sborman 83438689Sborman argc--; 83538689Sborman argv++; 83638689Sborman while (argc--) { 83738689Sborman name = *argv++; 83838689Sborman ct = getset(name); 83938689Sborman if (ct == 0) { 84038689Sborman c = gettoggle(name); 84138689Sborman if (c == 0) { 84238689Sborman fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 84338689Sborman name); 84438689Sborman return 0; 84538689Sborman } else if (Ambiguous(c)) { 84638689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 84738689Sborman name); 84838689Sborman return 0; 84938689Sborman } 85038689Sborman if (c->variable) { 85138689Sborman *c->variable = 0; 85238689Sborman if (c->actionexplanation) { 85338689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 85438689Sborman c->actionexplanation); 85538689Sborman } 85638689Sborman } 85738689Sborman if (c->handler) 85838689Sborman (*c->handler)(0); 85938689Sborman } else if (Ambiguous(ct)) { 86038689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 86138689Sborman name); 86238689Sborman return 0; 86338689Sborman } else if (ct->handler) { 86438689Sborman (*ct->handler)(0); 86538689Sborman printf("%s reset to \"%s\".\n", ct->name, ct->charp); 86638689Sborman } else { 86738689Sborman value = -1; 86838689Sborman *(ct->charp) = -1; 86938689Sborman printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 87038689Sborman } 87138689Sborman } 87238689Sborman return 1; 87338689Sborman } 87432144Sminshall 87532144Sminshall /* 87632144Sminshall * The following are the data structures and routines for the 87732144Sminshall * 'mode' command. 87832144Sminshall */ 87938689Sborman #ifdef KLUDGELINEMODE 88038689Sborman extern int kludgelinemode; 88138689Sborman #endif 88232144Sminshall 88332144Sminshall static 88432144Sminshall dolinemode() 88532144Sminshall { 88638689Sborman #ifdef KLUDGELINEMODE 88738689Sborman if (kludgelinemode) 88838689Sborman send_dont(TELOPT_SGA, 1); 88938689Sborman #endif 89038689Sborman send_will(TELOPT_LINEMODE, 1); 89138689Sborman send_dont(TELOPT_ECHO, 1); 89232144Sminshall return 1; 89332144Sminshall } 89432144Sminshall 89532144Sminshall static 89632144Sminshall docharmode() 89732144Sminshall { 89838689Sborman #ifdef KLUDGELINEMODE 89938689Sborman if (kludgelinemode) 90038689Sborman send_do(TELOPT_SGA, 1); 90138689Sborman else 90238689Sborman #endif 90338689Sborman send_wont(TELOPT_LINEMODE, 1); 90438689Sborman send_do(TELOPT_ECHO, 1); 90538689Sborman return 1; 90638689Sborman } 90738689Sborman 90838689Sborman setmode(bit) 90938689Sborman { 91038689Sborman return dolmmode(bit, 1); 91138689Sborman } 91238689Sborman 91338689Sborman clearmode(bit) 91438689Sborman { 91538689Sborman return dolmmode(bit, 0); 91638689Sborman } 91738689Sborman 91838689Sborman dolmmode(bit, on) 91938689Sborman int bit, on; 92038689Sborman { 92138689Sborman char c; 92238689Sborman extern int linemode; 92338689Sborman 92438689Sborman if (my_want_state_is_wont(TELOPT_LINEMODE)) { 92538689Sborman printf("?Need to have LINEMODE option enabled first.\n"); 92638689Sborman printf("'mode ?' for help.\n"); 92738689Sborman return 0; 92832144Sminshall } 92938689Sborman 93038689Sborman if (on) 93138689Sborman c = (linemode | bit); 93238689Sborman else 93338689Sborman c = (linemode & ~bit); 93438689Sborman lm_mode(&c, 1, 1); 93532144Sminshall return 1; 93632144Sminshall } 93732144Sminshall 93838689Sborman struct modelist { 93938689Sborman char *name; /* command name */ 94038689Sborman char *help; /* help string */ 94138689Sborman int (*handler)(); /* routine which executes command */ 94238689Sborman int needconnect; /* Do we need to be connected to execute? */ 94338689Sborman int arg1; 94438689Sborman }; 94538689Sborman 94638689Sborman extern int modehelp(); 94738689Sborman 94838689Sborman static struct modelist ModeList[] = { 94938689Sborman { "character", "Disable LINEMODE option", docharmode, 1 }, 95038689Sborman #ifdef KLUDEGLINEMODE 95138689Sborman { "", "(or disable obsolete line-by-line mode)", 0 }; 95238689Sborman #endif 95338689Sborman { "line", "Enable LINEMODE option", dolinemode, 1 }, 95438689Sborman #ifdef KLUDEGLINEMODE 95538689Sborman { "", "(or enable obsolete line-by-line mode)", 0 }; 95638689Sborman #endif 95738689Sborman { "", "", 0 }, 95838689Sborman { "", "These require the LINEMODE option to be enabled", 0 }, 95938689Sborman { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 96038689Sborman { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 96138689Sborman { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 96238689Sborman { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 96338689Sborman { "+edit", 0, setmode, 1, MODE_EDIT }, 96438689Sborman { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 96538689Sborman { "help", 0, modehelp, 0 }, 96638689Sborman { "?", "Print help information", modehelp, 0 }, 96732144Sminshall { 0 }, 96832144Sminshall }; 96932144Sminshall 97032144Sminshall static char ** 97132144Sminshall getnextmode(name) 97232144Sminshall char *name; 97332144Sminshall { 97438689Sborman return (char **) (((struct modelist *)name)+1); 97532144Sminshall } 97632144Sminshall 97738689Sborman static struct modelist * 97832144Sminshall getmodecmd(name) 97932144Sminshall char *name; 98032144Sminshall { 98138689Sborman return (struct modelist *) genget(name, (char **) ModeList, getnextmode); 98232144Sminshall } 98332144Sminshall 98438689Sborman modehelp() 98538689Sborman { 98638689Sborman struct modelist *mt; 98738689Sborman 98838689Sborman printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 98938689Sborman for (mt = ModeList; mt->name; mt++) { 99038689Sborman if (mt->help) { 99138689Sborman if (*mt->help) 99238689Sborman printf("%-15s %s\n", mt->name, mt->help); 99338689Sborman else 99438689Sborman printf("\n"); 99538689Sborman } 99638689Sborman } 99738689Sborman return 0; 99838689Sborman } 99938689Sborman 100032144Sminshall static 100132144Sminshall modecmd(argc, argv) 100232144Sminshall int argc; 100332144Sminshall char *argv[]; 100432144Sminshall { 100538689Sborman struct modelist *mt; 100632144Sminshall 100738689Sborman if (argc != 2) { 100838689Sborman printf("'mode' command requires an argument\n"); 100938689Sborman printf("'mode ?' for help.\n"); 101038689Sborman } else if ((mt = getmodecmd(argv[1])) == 0) { 101132144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 101232144Sminshall } else if (Ambiguous(mt)) { 101332144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 101438689Sborman } else if (mt->needconnect && !connected) { 101538689Sborman printf("?Need to be connected first.\n"); 101638689Sborman printf("'mode ?' for help.\n"); 101738689Sborman } else if (mt->handler) { 101838689Sborman return (*mt->handler)(mt->arg1); 101932144Sminshall } 102038689Sborman return 0; 102132144Sminshall } 102232144Sminshall 102332144Sminshall /* 102432144Sminshall * The following data structures and routines implement the 102532144Sminshall * "display" command. 102632144Sminshall */ 102732144Sminshall 102832144Sminshall static 102932144Sminshall display(argc, argv) 103032144Sminshall int argc; 103132144Sminshall char *argv[]; 103232144Sminshall { 103332144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 103432144Sminshall if (*tl->variable) { \ 103532144Sminshall printf("will"); \ 103632144Sminshall } else { \ 103732144Sminshall printf("won't"); \ 103832144Sminshall } \ 103932144Sminshall printf(" %s.\n", tl->actionexplanation); \ 104032144Sminshall } 104132144Sminshall 104232144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 104338689Sborman if (sl->handler == 0) \ 104438689Sborman printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 104538689Sborman else \ 104638689Sborman printf("%-15s \"%s\"\n", sl->name, sl->charp); \ 104732144Sminshall } 104832144Sminshall 104932144Sminshall struct togglelist *tl; 105032144Sminshall struct setlist *sl; 105132144Sminshall 105232144Sminshall if (argc == 1) { 105332144Sminshall for (tl = Togglelist; tl->name; tl++) { 105432144Sminshall dotog(tl); 105532144Sminshall } 105632144Sminshall printf("\n"); 105732144Sminshall for (sl = Setlist; sl->name; sl++) { 105832144Sminshall doset(sl); 105932144Sminshall } 106032144Sminshall } else { 106132144Sminshall int i; 106232144Sminshall 106332144Sminshall for (i = 1; i < argc; i++) { 106432144Sminshall sl = getset(argv[i]); 106532144Sminshall tl = gettoggle(argv[i]); 106632144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 106732144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 106832144Sminshall return 0; 106932144Sminshall } else if (!sl && !tl) { 107032144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 107132144Sminshall return 0; 107232144Sminshall } else { 107332144Sminshall if (tl) { 107432144Sminshall dotog(tl); 107532144Sminshall } 107632144Sminshall if (sl) { 107732144Sminshall doset(sl); 107832144Sminshall } 107932144Sminshall } 108032144Sminshall } 108132144Sminshall } 108238689Sborman /*@*/optionstatus(); 108332144Sminshall return 1; 108432144Sminshall #undef doset 108532144Sminshall #undef dotog 108632144Sminshall } 108732144Sminshall 108832144Sminshall /* 108932144Sminshall * The following are the data structures, and many of the routines, 109032144Sminshall * relating to command processing. 109132144Sminshall */ 109232144Sminshall 109332144Sminshall /* 109432144Sminshall * Set the escape character. 109532144Sminshall */ 109632144Sminshall static 109732144Sminshall setescape(argc, argv) 109832144Sminshall int argc; 109932144Sminshall char *argv[]; 110032144Sminshall { 110132144Sminshall register char *arg; 110232144Sminshall char buf[50]; 110332144Sminshall 110432144Sminshall printf( 110532144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 110632144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 110732144Sminshall if (argc > 2) 110832144Sminshall arg = argv[1]; 110932144Sminshall else { 111032144Sminshall printf("new escape character: "); 111134849Sminshall (void) gets(buf); 111232144Sminshall arg = buf; 111332144Sminshall } 111432144Sminshall if (arg[0] != '\0') 111532144Sminshall escape = arg[0]; 111632144Sminshall if (!In3270) { 111732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 111832144Sminshall } 111934849Sminshall (void) fflush(stdout); 112032144Sminshall return 1; 112132144Sminshall } 112232144Sminshall 112332144Sminshall /*VARARGS*/ 112432144Sminshall static 112532144Sminshall togcrmod() 112632144Sminshall { 112732144Sminshall crmod = !crmod; 112832144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 112932144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 113034849Sminshall (void) fflush(stdout); 113132144Sminshall return 1; 113232144Sminshall } 113332144Sminshall 113432144Sminshall /*VARARGS*/ 113532144Sminshall suspend() 113632144Sminshall { 113738689Sborman #ifdef SIGTSTP 113837219Sminshall setcommandmode(); 113937219Sminshall { 114037219Sminshall long oldrows, oldcols, newrows, newcols; 114137219Sminshall 114237219Sminshall TerminalWindowSize(&oldrows, &oldcols); 114334849Sminshall (void) kill(0, SIGTSTP); 114437219Sminshall TerminalWindowSize(&newrows, &newcols); 114537219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 114637219Sminshall if (connected) { 114737219Sminshall sendnaws(); 114837219Sminshall } 114937219Sminshall } 115037219Sminshall } 115137219Sminshall /* reget parameters in case they were changed */ 115237219Sminshall TerminalSaveState(); 115338689Sborman setconnmode(0); 115438689Sborman #else 115538689Sborman printf("Suspend is not supported. Try the '!' command instead\n"); 115638689Sborman #endif 115737219Sminshall return 1; 115832144Sminshall } 115932144Sminshall 116038689Sborman #if !defined(TN3270) 116138689Sborman #ifdef CRAY 116238689Sborman #define vfork fork 116338689Sborman #endif 116438689Sborman shell(argc, argv) 116538689Sborman int argc; 116638689Sborman char *argv[]; 116738689Sborman { 116838689Sborman extern char *rindex(); 116938689Sborman char cmdbuf[256]; 117038689Sborman 117138689Sborman setcommandmode(); 117238689Sborman switch(vfork()) { 117338689Sborman case -1: 117438689Sborman perror("Fork failed\n"); 117538689Sborman break; 117638689Sborman 117738689Sborman case 0: 117838689Sborman { 117938689Sborman /* 118038689Sborman * Fire up the shell in the child. 118138689Sborman */ 118238689Sborman register char *shell, *shellname; 118338689Sborman 118438689Sborman shell = getenv("SHELL"); 118538689Sborman if (shell == NULL) 118638689Sborman shell = "/bin/sh"; 118738689Sborman if ((shellname = rindex(shell, '/')) == 0) 118838689Sborman shellname = shell; 118938689Sborman else 119038689Sborman shellname++; 119138689Sborman if (argc > 1) 119238689Sborman execl(shell, shellname, "-c", &saveline[1], 0); 119338689Sborman else 119438689Sborman execl(shell, shellname, 0); 119538689Sborman perror("Execl"); 119638689Sborman _exit(1); 119738689Sborman } 119838689Sborman default: 119938689Sborman wait((int *)0); /* Wait for the shell to complete */ 120038689Sborman } 120138689Sborman } 120238689Sborman #endif /* !defined(TN3270) */ 120338689Sborman 120432144Sminshall /*VARARGS*/ 120532144Sminshall static 120632144Sminshall bye(argc, argv) 120732144Sminshall int argc; /* Number of arguments */ 120832144Sminshall char *argv[]; /* arguments */ 120932144Sminshall { 121032144Sminshall if (connected) { 121134849Sminshall (void) shutdown(net, 2); 121232144Sminshall printf("Connection closed.\n"); 121334849Sminshall (void) NetClose(net); 121432144Sminshall connected = 0; 121532144Sminshall /* reset options */ 121632144Sminshall tninit(); 121732144Sminshall #if defined(TN3270) 121832144Sminshall SetIn3270(); /* Get out of 3270 mode */ 121932144Sminshall #endif /* defined(TN3270) */ 122032144Sminshall } 122132144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 122232144Sminshall longjmp(toplevel, 1); 122332144Sminshall /* NOTREACHED */ 122432144Sminshall } 122532144Sminshall return 1; /* Keep lint, etc., happy */ 122632144Sminshall } 122732144Sminshall 122832144Sminshall /*VARARGS*/ 122932144Sminshall quit() 123032144Sminshall { 123132144Sminshall (void) call(bye, "bye", "fromquit", 0); 123232144Sminshall Exit(0); 123332144Sminshall return 1; /* just to keep lint happy */ 123432144Sminshall } 123538689Sborman 123638689Sborman /* 123738689Sborman * The SLC command. 123838689Sborman */ 123932144Sminshall 124038689Sborman struct slclist { 124138689Sborman char *name; 124238689Sborman char *help; 124338689Sborman int (*handler)(); 124438689Sborman int arg; 124538689Sborman }; 124638689Sborman 124738689Sborman extern int slc_help(); 124838689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate(); 124938689Sborman 125038689Sborman struct slclist SlcList[] = { 125138689Sborman { "export", "Use local special character definitions", 125238689Sborman slc_mode_export, 0 }, 125338689Sborman { "import", "Use remote special character definitions", 125438689Sborman slc_mode_import, 1 }, 125538689Sborman { "check", "Verify remote special character definitions", 125638689Sborman slc_mode_import, 0 }, 125738689Sborman { "help", 0, slc_help, 0 }, 125838689Sborman { "?", "Print help information", slc_help, 0 }, 125938689Sborman { 0 }, 126038689Sborman }; 126138689Sborman 126238689Sborman static 126338689Sborman slc_help() 126438689Sborman { 126538689Sborman struct slclist *c; 126638689Sborman 126738689Sborman for (c = SlcList; c->name; c++) { 126838689Sborman if (c->help) { 126938689Sborman if (*c->help) 127038689Sborman printf("%-15s %s\n", c->name, c->help); 127138689Sborman else 127238689Sborman printf("\n"); 127338689Sborman } 127438689Sborman } 127538689Sborman } 127638689Sborman 127738689Sborman static char ** 127838689Sborman getnextslc(name) 127938689Sborman char *name; 128038689Sborman { 128138689Sborman return (char **)(((struct slclist *)name)+1); 128238689Sborman } 128338689Sborman 128438689Sborman static struct slclist * 128538689Sborman getslc(name) 128638689Sborman char *name; 128738689Sborman { 128838689Sborman return (struct slclist *)genget(name, (char **) SlcList, getnextslc); 128938689Sborman } 129038689Sborman 129138689Sborman static 129238689Sborman slccmd(argc, argv) 129338689Sborman int argc; 129438689Sborman char *argv[]; 129538689Sborman { 129638689Sborman struct slclist *c; 129738689Sborman 129838689Sborman if (argc != 2) { 129938689Sborman fprintf(stderr, 130038689Sborman "Need an argument to 'slc' command. 'slc ?' for help.\n"); 130138689Sborman return 0; 130238689Sborman } 130338689Sborman c = getslc(argv[1]); 130438689Sborman if (c == 0) { 130538689Sborman fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 130638689Sborman argv[1]); 130738689Sborman return 0; 130838689Sborman } 130938689Sborman if (Ambiguous(c)) { 131038689Sborman fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 131138689Sborman argv[1]); 131238689Sborman return 0; 131338689Sborman } 131438689Sborman (*c->handler)(c->arg); 131538689Sborman slcstate(); 131638689Sborman return 1; 131738689Sborman } 131838689Sborman 131936274Sminshall #if defined(unix) 132032144Sminshall /* 132136274Sminshall * Some information about our file descriptors. 132236274Sminshall */ 132336274Sminshall 132436274Sminshall char * 132536274Sminshall decodeflags(mask) 132636274Sminshall int mask; 132736274Sminshall { 132836274Sminshall static char buffer[100]; 132936274Sminshall #define do(m,s) \ 133036274Sminshall if (mask&(m)) { \ 133136274Sminshall strcat(buffer, (s)); \ 133236274Sminshall } 133336274Sminshall 133436274Sminshall buffer[0] = 0; /* Terminate it */ 133536274Sminshall 133636274Sminshall #ifdef FREAD 133736274Sminshall do(FREAD, " FREAD"); 133836274Sminshall #endif 133936274Sminshall #ifdef FWRITE 134036274Sminshall do(FWRITE, " FWRITE"); 134136274Sminshall #endif 134236274Sminshall #ifdef F_DUPFP 134336274Sminshall do(F_DUPFD, " F_DUPFD"); 134436274Sminshall #endif 134536274Sminshall #ifdef FNDELAY 134636274Sminshall do(FNDELAY, " FNDELAY"); 134736274Sminshall #endif 134836274Sminshall #ifdef FAPPEND 134936274Sminshall do(FAPPEND, " FAPPEND"); 135036274Sminshall #endif 135136274Sminshall #ifdef FMARK 135236274Sminshall do(FMARK, " FMARK"); 135336274Sminshall #endif 135436274Sminshall #ifdef FDEFER 135536274Sminshall do(FDEFER, " FDEFER"); 135636274Sminshall #endif 135736274Sminshall #ifdef FASYNC 135836274Sminshall do(FASYNC, " FASYNC"); 135936274Sminshall #endif 136036274Sminshall #ifdef FSHLOCK 136136274Sminshall do(FSHLOCK, " FSHLOCK"); 136236274Sminshall #endif 136336274Sminshall #ifdef FEXLOCK 136436274Sminshall do(FEXLOCK, " FEXLOCK"); 136536274Sminshall #endif 136636274Sminshall #ifdef FCREAT 136736274Sminshall do(FCREAT, " FCREAT"); 136836274Sminshall #endif 136936274Sminshall #ifdef FTRUNC 137036274Sminshall do(FTRUNC, " FTRUNC"); 137136274Sminshall #endif 137236274Sminshall #ifdef FEXCL 137336274Sminshall do(FEXCL, " FEXCL"); 137436274Sminshall #endif 137536274Sminshall 137636274Sminshall return buffer; 137736274Sminshall } 137836274Sminshall #undef do 137936274Sminshall 138036274Sminshall static void 138136274Sminshall filestuff(fd) 138236274Sminshall int fd; 138336274Sminshall { 138436274Sminshall int res; 138536274Sminshall 138638689Sborman #ifdef F_GETOWN 138738689Sborman setconnmode(0); 138836274Sminshall res = fcntl(fd, F_GETOWN, 0); 138936274Sminshall setcommandmode(); 139036274Sminshall 139136274Sminshall if (res == -1) { 139236274Sminshall perror("fcntl"); 139336274Sminshall return; 139436274Sminshall } 139536274Sminshall printf("\tOwner is %d.\n", res); 139638689Sborman #endif 139736274Sminshall 139838689Sborman setconnmode(0); 139936274Sminshall res = fcntl(fd, F_GETFL, 0); 140036274Sminshall setcommandmode(); 140136274Sminshall 140236274Sminshall if (res == -1) { 140336274Sminshall perror("fcntl"); 140436274Sminshall return; 140536274Sminshall } 140636274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 140736274Sminshall } 140836274Sminshall 140936274Sminshall 141036274Sminshall #endif /* defined(unix) */ 141136274Sminshall 141236274Sminshall /* 141332144Sminshall * Print status about the connection. 141432144Sminshall */ 141534849Sminshall /*ARGSUSED*/ 141632144Sminshall static 141732144Sminshall status(argc, argv) 141832144Sminshall int argc; 141932144Sminshall char *argv[]; 142032144Sminshall { 142132144Sminshall if (connected) { 142232144Sminshall printf("Connected to %s.\n", hostname); 142336242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 142438689Sborman int mode = getconnmode(); 142538689Sborman 142638689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 142738689Sborman printf("Operating with LINEMODE option\n"); 142838689Sborman printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 142938689Sborman printf("%s catching of signals\n", 143038689Sborman (mode&MODE_TRAPSIG) ? "Local" : "No"); 143138689Sborman slcstate(); 143238689Sborman #ifdef KLUDGELINEMODE 143338689Sborman } else if (kludgelinemode && my_want_state_is_wont(TELOPT_SGA)) { 143438689Sborman printf("Operating in obsolete linemode\n"); 143538689Sborman #endif 143638689Sborman } else { 143738689Sborman printf("Operating in single character mode\n"); 143838689Sborman if (localchars) 143938689Sborman printf("Catching signals locally\n"); 144032144Sminshall } 144138689Sborman printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 144238689Sborman if (my_want_state_is_will(TELOPT_LFLOW)) 144338689Sborman printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 144432144Sminshall } 144532144Sminshall } else { 144632144Sminshall printf("No connection.\n"); 144732144Sminshall } 144832144Sminshall # if !defined(TN3270) 144932144Sminshall printf("Escape character is '%s'.\n", control(escape)); 145034849Sminshall (void) fflush(stdout); 145132144Sminshall # else /* !defined(TN3270) */ 145232144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 145332144Sminshall printf("Escape character is '%s'.\n", control(escape)); 145432144Sminshall } 145532144Sminshall # if defined(unix) 145636242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 145736242Sminshall printf("SIGIO received %d time%s.\n", 145836242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 145936274Sminshall if (In3270) { 146036274Sminshall printf("Process ID %d, process group %d.\n", 146136274Sminshall getpid(), getpgrp(getpid())); 146236274Sminshall printf("Terminal input:\n"); 146336274Sminshall filestuff(tin); 146436274Sminshall printf("Terminal output:\n"); 146536274Sminshall filestuff(tout); 146636274Sminshall printf("Network socket:\n"); 146736274Sminshall filestuff(net); 146836274Sminshall } 146936242Sminshall } 147032144Sminshall if (In3270 && transcom) { 147132144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 147232144Sminshall } 147332144Sminshall # endif /* defined(unix) */ 147434849Sminshall (void) fflush(stdout); 147532144Sminshall if (In3270) { 147632144Sminshall return 0; 147732144Sminshall } 147832144Sminshall # endif /* defined(TN3270) */ 147932144Sminshall return 1; 148032144Sminshall } 148132144Sminshall 148232144Sminshall 148332144Sminshall 148432144Sminshall int 148532144Sminshall tn(argc, argv) 148632144Sminshall int argc; 148732144Sminshall char *argv[]; 148832144Sminshall { 148932144Sminshall register struct hostent *host = 0; 149032144Sminshall struct sockaddr_in sin; 149132144Sminshall struct servent *sp = 0; 149232144Sminshall static char hnamebuf[32]; 149338689Sborman unsigned long temp, inet_addr(); 149437219Sminshall extern char *inet_ntoa(); 149538689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 149638689Sborman char *srp = 0, *strrchr(); 149738689Sborman unsigned long sourceroute(), srlen; 149838689Sborman #endif 149932144Sminshall 150032144Sminshall 150132144Sminshall #if defined(MSDOS) 150232144Sminshall char *cp; 150332144Sminshall #endif /* defined(MSDOS) */ 150432144Sminshall 150532144Sminshall if (connected) { 150632144Sminshall printf("?Already connected to %s\n", hostname); 150732144Sminshall return 0; 150832144Sminshall } 150932144Sminshall if (argc < 2) { 151032144Sminshall (void) strcpy(line, "Connect "); 151132144Sminshall printf("(to) "); 151234849Sminshall (void) gets(&line[strlen(line)]); 151332144Sminshall makeargv(); 151432144Sminshall argc = margc; 151532144Sminshall argv = margv; 151632144Sminshall } 151732144Sminshall if ((argc < 2) || (argc > 3)) { 151832144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 151932144Sminshall return 0; 152032144Sminshall } 152132144Sminshall #if defined(MSDOS) 152232144Sminshall for (cp = argv[1]; *cp; cp++) { 152332144Sminshall if (isupper(*cp)) { 152432144Sminshall *cp = tolower(*cp); 152532144Sminshall } 152632144Sminshall } 152732144Sminshall #endif /* defined(MSDOS) */ 152838689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 152938689Sborman if (argv[1][0] == '@' || argv[1][0] == '!') { 153038689Sborman if ((hostname = strrchr(argv[1], ':')) == NULL) 153138689Sborman hostname = strrchr(argv[1], '@'); 153238689Sborman hostname++; 153338689Sborman srp = 0; 153438689Sborman temp = sourceroute(argv[1], &srp, &srlen); 153538689Sborman if (temp == 0) { 153638689Sborman herror(srp); 153738689Sborman return 0; 153838689Sborman } else if (temp == -1) { 153938689Sborman printf("Bad source route option: %s\n", argv[1]); 154038689Sborman return 0; 154138689Sborman } else { 154238689Sborman sin.sin_addr.s_addr = temp; 154338689Sborman sin.sin_family = AF_INET; 154438689Sborman } 154532144Sminshall } else { 154638689Sborman #endif 154738689Sborman temp = inet_addr(argv[1]); 154838689Sborman if (temp != (unsigned long) -1) { 154938689Sborman sin.sin_addr.s_addr = temp; 155038689Sborman sin.sin_family = AF_INET; 155138689Sborman (void) strcpy(hnamebuf, argv[1]); 155238689Sborman hostname = hnamebuf; 155338689Sborman } else { 155438689Sborman host = gethostbyname(argv[1]); 155538689Sborman if (host) { 155638689Sborman sin.sin_family = host->h_addrtype; 155732144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 155838689Sborman memcpy((caddr_t)&sin.sin_addr, 155932144Sminshall host->h_addr_list[0], host->h_length); 156032144Sminshall #else /* defined(h_addr) */ 156138689Sborman memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 156232144Sminshall #endif /* defined(h_addr) */ 156338689Sborman hostname = host->h_name; 156438689Sborman } else { 156538689Sborman herror(argv[1]); 156638689Sborman return 0; 156738689Sborman } 156832144Sminshall } 156938689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 157032144Sminshall } 157138689Sborman #endif 157232144Sminshall if (argc == 3) { 157338689Sborman int tmp; 157438689Sborman 157538689Sborman if (*argv[2] == '-') { 157638689Sborman argv[2]++; 157738689Sborman telnetport = 1; 157838689Sborman } else 157938689Sborman telnetport = 0; 158032144Sminshall sin.sin_port = atoi(argv[2]); 158132144Sminshall if (sin.sin_port == 0) { 158232144Sminshall sp = getservbyname(argv[2], "tcp"); 158332144Sminshall if (sp) 158432144Sminshall sin.sin_port = sp->s_port; 158532144Sminshall else { 158632144Sminshall printf("%s: bad port number\n", argv[2]); 158732144Sminshall return 0; 158832144Sminshall } 158932144Sminshall } else { 159034849Sminshall #if !defined(htons) 159134849Sminshall u_short htons(); 159234849Sminshall #endif /* !defined(htons) */ 159332144Sminshall sin.sin_port = htons(sin.sin_port); 159432144Sminshall } 159532144Sminshall } else { 159632144Sminshall if (sp == 0) { 159732144Sminshall sp = getservbyname("telnet", "tcp"); 159832144Sminshall if (sp == 0) { 159934849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 160032144Sminshall return 0; 160132144Sminshall } 160232144Sminshall sin.sin_port = sp->s_port; 160332144Sminshall } 160432144Sminshall telnetport = 1; 160532144Sminshall } 160637219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 160732144Sminshall do { 160832144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 160932144Sminshall if (net < 0) { 161032144Sminshall perror("telnet: socket"); 161132144Sminshall return 0; 161232144Sminshall } 161338689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 161438689Sborman if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) 161538689Sborman perror("setsockopt (IP_OPTIONS)"); 161638689Sborman #endif 161732144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 161832144Sminshall perror("setsockopt (SO_DEBUG)"); 161932144Sminshall } 162032144Sminshall 162132144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 162232144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 162332144Sminshall if (host && host->h_addr_list[1]) { 162432144Sminshall int oerrno = errno; 162532144Sminshall 162632144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 162732144Sminshall inet_ntoa(sin.sin_addr)); 162832144Sminshall errno = oerrno; 162932144Sminshall perror((char *)0); 163032144Sminshall host->h_addr_list++; 163132144Sminshall memcpy((caddr_t)&sin.sin_addr, 163232144Sminshall host->h_addr_list[0], host->h_length); 163332144Sminshall (void) NetClose(net); 163432144Sminshall continue; 163532144Sminshall } 163632144Sminshall #endif /* defined(h_addr) */ 163732144Sminshall perror("telnet: Unable to connect to remote host"); 163832144Sminshall return 0; 163937219Sminshall } 164032144Sminshall connected++; 164132144Sminshall } while (connected == 0); 164238689Sborman cmdrc(argv[1], hostname); 164334849Sminshall (void) call(status, "status", "notmuch", 0); 164432144Sminshall if (setjmp(peerdied) == 0) 164532144Sminshall telnet(); 164634849Sminshall (void) NetClose(net); 164732381Sminshall ExitString("Connection closed by foreign host.\n",1); 164832144Sminshall /*NOTREACHED*/ 164932144Sminshall } 165032144Sminshall 165132144Sminshall 165232144Sminshall #define HELPINDENT (sizeof ("connect")) 165332144Sminshall 165432144Sminshall static char 165532144Sminshall openhelp[] = "connect to a site", 165632144Sminshall closehelp[] = "close current connection", 165732144Sminshall quithelp[] = "exit telnet", 165832144Sminshall statushelp[] = "print status information", 165932144Sminshall helphelp[] = "print help information", 166032144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 166132144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 166238689Sborman unsethelp[] = "unset operating parameters ('unset ?' for more)", 166332144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 166438689Sborman slchelp[] = "change state of special charaters ('slc ?' for more)", 166532144Sminshall displayhelp[] = "display operating parameters", 166632144Sminshall #if defined(TN3270) && defined(unix) 166732144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 166832144Sminshall #endif /* defined(TN3270) && defined(unix) */ 166932144Sminshall #if defined(unix) 167032144Sminshall zhelp[] = "suspend telnet", 167132144Sminshall #endif /* defined(unix */ 167232144Sminshall shellhelp[] = "invoke a subshell", 167338689Sborman modestring[] = "try to enter line-by-line or character-at-a-time mode"; 167432144Sminshall 167532144Sminshall extern int help(), shell(); 167632144Sminshall 167732144Sminshall static Command cmdtab[] = { 167838689Sborman { "close", closehelp, bye, 1 }, 167938689Sborman { "display", displayhelp, display, 0 }, 168038689Sborman { "mode", modestring, modecmd, 0 }, 168138689Sborman { "open", openhelp, tn, 0 }, 168238689Sborman { "quit", quithelp, quit, 0 }, 168338689Sborman { "send", sendhelp, sendcmd, 0 }, 168438689Sborman { "set", sethelp, setcmd, 0 }, 168538689Sborman { "unset", unsethelp, unsetcmd, 0 }, 168638689Sborman { "status", statushelp, status, 0 }, 168738689Sborman { "toggle", togglestring, toggle, 0 }, 168838689Sborman { "slc", slchelp, slccmd, 0 }, 168932144Sminshall #if defined(TN3270) && defined(unix) 169038689Sborman { "transcom", transcomhelp, settranscom, 0 }, 169132144Sminshall #endif /* defined(TN3270) && defined(unix) */ 169232144Sminshall #if defined(unix) 169338689Sborman { "z", zhelp, suspend, 0 }, 169432144Sminshall #endif /* defined(unix) */ 169532144Sminshall #if defined(TN3270) 169638689Sborman { "!", shellhelp, shell, 1 }, 169738689Sborman #else 169838689Sborman { "!", shellhelp, shell, 0 }, 169938689Sborman #endif 170038689Sborman { "?", helphelp, help, 0 }, 170132144Sminshall 0 170232144Sminshall }; 170332144Sminshall 170432144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 170532144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 170632144Sminshall 170732144Sminshall static Command cmdtab2[] = { 170838689Sborman { "help", 0, help, 0 }, 170938689Sborman { "escape", escapehelp, setescape, 0 }, 171038689Sborman { "crmod", crmodhelp, togcrmod, 0 }, 171132144Sminshall 0 171232144Sminshall }; 171332144Sminshall 171435298Sminshall 171532144Sminshall /* 171632144Sminshall * Call routine with argc, argv set from args (terminated by 0). 171732144Sminshall */ 171835298Sminshall 171935417Sminshall /*VARARGS1*/ 172032144Sminshall static 172135298Sminshall call(va_alist) 172235298Sminshall va_dcl 172332144Sminshall { 172435298Sminshall va_list ap; 172535298Sminshall typedef int (*intrtn_t)(); 172635298Sminshall intrtn_t routine; 172735298Sminshall char *args[100]; 172835298Sminshall int argno = 0; 172935298Sminshall 173035298Sminshall va_start(ap); 173135298Sminshall routine = (va_arg(ap, intrtn_t)); 173235495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 173335298Sminshall ; 173435495Sminshall } 173535298Sminshall va_end(ap); 173635495Sminshall return (*routine)(argno-1, args); 173732144Sminshall } 173832144Sminshall 173935298Sminshall 174032144Sminshall static char ** 174132144Sminshall getnextcmd(name) 174232144Sminshall char *name; 174332144Sminshall { 174432144Sminshall Command *c = (Command *) name; 174532144Sminshall 174632144Sminshall return (char **) (c+1); 174732144Sminshall } 174832144Sminshall 174932144Sminshall static Command * 175032144Sminshall getcmd(name) 175132144Sminshall char *name; 175232144Sminshall { 175332144Sminshall Command *cm; 175432144Sminshall 175532144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 175632144Sminshall return cm; 175732144Sminshall } else { 175832144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 175932144Sminshall } 176032144Sminshall } 176132144Sminshall 176232144Sminshall void 176338689Sborman command(top, tbuf, cnt) 176432144Sminshall int top; 176538689Sborman char *tbuf; 176638689Sborman int cnt; 176732144Sminshall { 176832144Sminshall register Command *c; 176932144Sminshall 177032144Sminshall setcommandmode(); 177132144Sminshall if (!top) { 177232144Sminshall putchar('\n'); 177337219Sminshall #if defined(unix) 177432144Sminshall } else { 177532144Sminshall signal(SIGINT, SIG_DFL); 177632144Sminshall signal(SIGQUIT, SIG_DFL); 177732144Sminshall #endif /* defined(unix) */ 177832144Sminshall } 177932144Sminshall for (;;) { 178032144Sminshall printf("%s> ", prompt); 178138689Sborman if (tbuf) { 178238689Sborman register char *cp; 178338689Sborman cp = line; 178438689Sborman while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 178538689Sborman cnt--; 178638689Sborman tbuf = 0; 178738689Sborman if (cp == line || *--cp != '\n' || cp == line) 178838689Sborman goto getline; 178938689Sborman *cp = '\0'; 179038689Sborman printf("%s\n", line); 179138689Sborman } else { 179238689Sborman getline: 179338689Sborman if (gets(line) == NULL) { 179438689Sborman if (feof(stdin) || ferror(stdin)) 179538689Sborman quit(); 179638689Sborman break; 179738689Sborman } 179832144Sminshall } 179932144Sminshall if (line[0] == 0) 180032144Sminshall break; 180132144Sminshall makeargv(); 180237219Sminshall if (margv[0] == 0) { 180337219Sminshall break; 180437219Sminshall } 180532144Sminshall c = getcmd(margv[0]); 180632144Sminshall if (Ambiguous(c)) { 180732144Sminshall printf("?Ambiguous command\n"); 180832144Sminshall continue; 180932144Sminshall } 181032144Sminshall if (c == 0) { 181132144Sminshall printf("?Invalid command\n"); 181232144Sminshall continue; 181332144Sminshall } 181432144Sminshall if (c->needconnect && !connected) { 181532144Sminshall printf("?Need to be connected first.\n"); 181632144Sminshall continue; 181732144Sminshall } 181832144Sminshall if ((*c->handler)(margc, margv)) { 181932144Sminshall break; 182032144Sminshall } 182132144Sminshall } 182232144Sminshall if (!top) { 182332144Sminshall if (!connected) { 182432144Sminshall longjmp(toplevel, 1); 182532144Sminshall /*NOTREACHED*/ 182632144Sminshall } 182732144Sminshall #if defined(TN3270) 182832144Sminshall if (shell_active == 0) { 182938689Sborman setconnmode(0); 183032144Sminshall } 183132144Sminshall #else /* defined(TN3270) */ 183238689Sborman setconnmode(0); 183332144Sminshall #endif /* defined(TN3270) */ 183432144Sminshall } 183532144Sminshall } 183632144Sminshall 183732144Sminshall /* 183832144Sminshall * Help command. 183932144Sminshall */ 184032144Sminshall static 184132144Sminshall help(argc, argv) 184232144Sminshall int argc; 184332144Sminshall char *argv[]; 184432144Sminshall { 184532144Sminshall register Command *c; 184632144Sminshall 184732144Sminshall if (argc == 1) { 184832144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 184932144Sminshall for (c = cmdtab; c->name; c++) 185038689Sborman if (c->help) { 185132144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 185232144Sminshall c->help); 185332144Sminshall } 185432144Sminshall return 0; 185532144Sminshall } 185632144Sminshall while (--argc > 0) { 185732144Sminshall register char *arg; 185832144Sminshall arg = *++argv; 185932144Sminshall c = getcmd(arg); 186032144Sminshall if (Ambiguous(c)) 186132144Sminshall printf("?Ambiguous help command %s\n", arg); 186232144Sminshall else if (c == (Command *)0) 186332144Sminshall printf("?Invalid help command %s\n", arg); 186432144Sminshall else 186532144Sminshall printf("%s\n", c->help); 186632144Sminshall } 186732144Sminshall return 0; 186832144Sminshall } 186938689Sborman 187038689Sborman static char *rcname = 0; 187138689Sborman static char rcbuf[128]; 187238689Sborman 187338689Sborman cmdrc(m1, m2) 187438689Sborman char *m1, *m2; 187538689Sborman { 187638689Sborman register Command *c; 187738689Sborman FILE *rcfile; 187838689Sborman int gotmachine = 0; 187938689Sborman int l1 = strlen(m1); 188038689Sborman int l2 = strlen(m2); 188138689Sborman char m1save[64]; 188238689Sborman 188338689Sborman strcpy(m1save, m1); 188438689Sborman m1 = m1save; 188538689Sborman 188638689Sborman if (rcname == 0) { 188738689Sborman rcname = getenv("HOME"); 188838689Sborman if (rcname) 188938689Sborman strcpy(rcbuf, rcname); 189038689Sborman else 189138689Sborman rcbuf[0] = '\0'; 189238689Sborman strcat(rcbuf, "/.telnetrc"); 189338689Sborman rcname = rcbuf; 189438689Sborman } 189538689Sborman 189638689Sborman if ((rcfile = fopen(rcname, "r")) == 0) { 189738689Sborman return; 189838689Sborman } 189938689Sborman 190038689Sborman for (;;) { 190138689Sborman if (fgets(line, sizeof(line), rcfile) == NULL) 190238689Sborman break; 190338689Sborman if (line[0] == 0) 190438689Sborman break; 190538689Sborman if (line[0] == '#') 190638689Sborman continue; 190738689Sborman if (gotmachine == 0) { 190838689Sborman if (isspace(line[0])) 190938689Sborman continue; 191038689Sborman if (strncasecmp(line, m1, l1) == 0) 191138689Sborman strncpy(line, &line[l1], sizeof(line) - l1); 191238689Sborman else if (strncasecmp(line, m2, l2) == 0) 191338689Sborman strncpy(line, &line[l2], sizeof(line) - l2); 191438689Sborman else 191538689Sborman continue; 191638689Sborman gotmachine = 1; 191738689Sborman } else { 191838689Sborman if (!isspace(line[0])) { 191938689Sborman gotmachine = 0; 192038689Sborman continue; 192138689Sborman } 192238689Sborman } 192338689Sborman makeargv(); 192438689Sborman if (margv[0] == 0) 192538689Sborman continue; 192638689Sborman c = getcmd(margv[0]); 192738689Sborman if (Ambiguous(c)) { 192838689Sborman printf("?Ambiguous command: %s\n", margv[0]); 192938689Sborman continue; 193038689Sborman } 193138689Sborman if (c == 0) { 193238689Sborman printf("?Invalid command: %s\n", margv[0]); 193338689Sborman continue; 193438689Sborman } 193538689Sborman /* 193638689Sborman * This should never happen... 193738689Sborman */ 193838689Sborman if (c->needconnect && !connected) { 193938689Sborman printf("?Need to be connected first for %s.\n", margv[0]); 194038689Sborman continue; 194138689Sborman } 194238689Sborman (*c->handler)(margc, margv); 194338689Sborman } 194438689Sborman fclose(rcfile); 194538689Sborman } 194638689Sborman 194738689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 194838689Sborman 194938689Sborman /* 195038689Sborman * Source route is handed in as 195138689Sborman * [!]@hop1@hop2...[@|:]dst 195238689Sborman * If the leading ! is present, it is a 195338689Sborman * strict source route, otherwise it is 195438689Sborman * assmed to be a loose source route. 195538689Sborman * 195638689Sborman * We fill in the source route option as 195738689Sborman * hop1,hop2,hop3...dest 195838689Sborman * and return a pointer to hop1, which will 195938689Sborman * be the address to connect() to. 196038689Sborman * 196138689Sborman * Arguments: 196238689Sborman * arg: pointer to route list to decipher 196338689Sborman * 196438689Sborman * cpp: If *cpp is not equal to NULL, this is a 196538689Sborman * pointer to a pointer to a character array 196638689Sborman * that should be filled in with the option. 196738689Sborman * 196838689Sborman * lenp: pointer to an integer that contains the 196938689Sborman * length of *cpp if *cpp != NULL. 197038689Sborman * 197138689Sborman * Return values: 197238689Sborman * 197338689Sborman * Returns the address of the host to connect to. If the 197438689Sborman * return value is -1, there was a syntax error in the 197538689Sborman * option, either unknown characters, or too many hosts. 197638689Sborman * If the return value is 0, one of the hostnames in the 197738689Sborman * path is unknown, and *cpp is set to point to the bad 197838689Sborman * hostname. 197938689Sborman * 198038689Sborman * *cpp: If *cpp was equal to NULL, it will be filled 198138689Sborman * in with a pointer to our static area that has 198238689Sborman * the option filled in. This will be 32bit aligned. 198338689Sborman * 198438689Sborman * *lenp: This will be filled in with how long the option 198538689Sborman * pointed to by *cpp is. 198638689Sborman * 198738689Sborman */ 198838689Sborman unsigned long 198938689Sborman sourceroute(arg, cpp, lenp) 199038689Sborman char *arg; 199138689Sborman char **cpp; 199238689Sborman int *lenp; 199338689Sborman { 199438689Sborman static char lsr[44]; 199538689Sborman char *cp, *cp2, *lsrp, *lsrep, *index(); 199638689Sborman register int tmp; 199738689Sborman struct in_addr sin_addr; 199838689Sborman register struct hostent *host = 0; 199938689Sborman register char c; 200038689Sborman 200138689Sborman /* 200238689Sborman * Verify the arguments, and make sure we have 200338689Sborman * at least 7 bytes for the option. 200438689Sborman */ 200538689Sborman if (cpp == NULL || lenp == NULL) 200638689Sborman return((unsigned long)-1); 200738689Sborman if (*cpp != NULL && *lenp < 7) 200838689Sborman return((unsigned long)-1); 200938689Sborman /* 201038689Sborman * Decide whether we have a buffer passed to us, 201138689Sborman * or if we need to use our own static buffer. 201238689Sborman */ 201338689Sborman if (*cpp) { 201438689Sborman lsrp = *cpp; 201538689Sborman lsrep = lsrp + *lenp; 201638689Sborman } else { 201738689Sborman *cpp = lsrp = lsr; 201838689Sborman lsrep = lsrp + 44; 201938689Sborman } 202038689Sborman 202138689Sborman cp = arg; 202238689Sborman 202338689Sborman /* 202438689Sborman * Next, decide whether we have a loose source 202538689Sborman * route or a strict source route, and fill in 202638689Sborman * the begining of the option. 202738689Sborman */ 202838689Sborman if (*cp == '!') { 202938689Sborman cp++; 203038689Sborman *lsrp++ = IPOPT_SSRR; 203138689Sborman } else 203238689Sborman *lsrp++ = IPOPT_LSRR; 203338689Sborman 203438689Sborman if (*cp != '@') 203538689Sborman return((unsigned long)-1); 203638689Sborman 203738689Sborman lsrp++; /* skip over length, we'll fill it in later */ 203838689Sborman *lsrp++ = 4; 203938689Sborman 204038689Sborman cp++; 204138689Sborman 204238689Sborman sin_addr.s_addr = 0; 204338689Sborman 204438689Sborman for (c = 0;;) { 204538689Sborman if (c == ':') 204638689Sborman cp2 = 0; 204738689Sborman else for (cp2 = cp; c = *cp2; cp2++) { 204838689Sborman if (c == ',') { 204938689Sborman *cp2++ = '\0'; 205038689Sborman if (*cp2 == '@') 205138689Sborman cp2++; 205238689Sborman } else if (c == '@') { 205338689Sborman *cp2++ = '\0'; 205438689Sborman } else if (c == ':') { 205538689Sborman *cp2++ = '\0'; 205638689Sborman } else 205738689Sborman continue; 205838689Sborman break; 205938689Sborman } 206038689Sborman if (!c) 206138689Sborman cp2 = 0; 206238689Sborman 206338689Sborman if ((tmp = inet_addr(cp)) != -1) { 206438689Sborman sin_addr.s_addr = tmp; 206538689Sborman } else if (host = gethostbyname(cp)) { 206638689Sborman #if defined(h_addr) 206738689Sborman memcpy((caddr_t)&sin_addr, 206838689Sborman host->h_addr_list[0], host->h_length); 206938689Sborman #else 207038689Sborman memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); 207138689Sborman #endif 207238689Sborman } else { 207338689Sborman *cpp = cp; 207438689Sborman return(0); 207538689Sborman } 207638689Sborman memcpy(lsrp, (char *)&sin_addr, 4); 207738689Sborman lsrp += 4; 207838689Sborman if (cp2) 207938689Sborman cp = cp2; 208038689Sborman else 208138689Sborman break; 208238689Sborman /* 208338689Sborman * Check to make sure there is space for next address 208438689Sborman */ 208538689Sborman if (lsrp + 4 > lsrep) 208638689Sborman return((unsigned long)-1); 208738689Sborman } 208838689Sborman if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 208938689Sborman *cpp = 0; 209038689Sborman *lenp = 0; 209138689Sborman return((unsigned long)-1); 209238689Sborman } 209338689Sborman *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 209438689Sborman *lenp = lsrp - *cpp; 209538689Sborman return(sin_addr.s_addr); 209638689Sborman } 209738689Sborman #endif 209838689Sborman 209938689Sborman #if defined(sun) 210038689Sborman strncasecmp(p1, p2, len) 210138689Sborman register char *p1, *p2; 210238689Sborman int len; 210338689Sborman { 210438689Sborman while (len--) { 210538689Sborman if (tolower(*p1) != tolower(*p2)) 210638689Sborman return(tolower(*p1) - tolower(*p2)); 210738689Sborman if (*p1 == '\0') 210838689Sborman return(0); 210938689Sborman p1++, p2++; 211038689Sborman } 211138689Sborman return(0); 211238689Sborman } 211338689Sborman #endif 2114