133685Sbostic /* 2*45233Sborman * Copyright (c) 1988, 1990 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 542770Sbostic * %sccs.include.redist.c% 633685Sbostic */ 733685Sbostic 833685Sbostic #ifndef lint 9*45233Sborman static char sccsid[] = "@(#)commands.c 5.1 (Berkeley) 09/14/90"; 1033685Sbostic #endif /* not lint */ 1133685Sbostic 1244361Sborman #include <sys/types.h> 1336274Sminshall #if defined(unix) 1436274Sminshall #include <sys/file.h> 1536274Sminshall #endif /* defined(unix) */ 1632144Sminshall #include <sys/socket.h> 1732144Sminshall #include <netinet/in.h> 1838689Sborman #ifdef CRAY 1938689Sborman #include <sys/fcntl.h> 2038810Sborman #endif /* CRAY */ 2132144Sminshall 2232144Sminshall #include <signal.h> 2332144Sminshall #include <netdb.h> 2432144Sminshall #include <ctype.h> 2545008Skarels #include <pwd.h> 2635298Sminshall #include <varargs.h> 2732144Sminshall 2832144Sminshall #include <arpa/telnet.h> 2932144Sminshall 3034305Sminshall #include "general.h" 3134305Sminshall 3232381Sminshall #include "ring.h" 3332381Sminshall 3432144Sminshall #include "externs.h" 3532144Sminshall #include "defines.h" 3632144Sminshall #include "types.h" 3732144Sminshall 3844361Sborman #ifdef SRCRT 3944361Sborman # ifndef CRAY 4044361Sborman # include <netinet/in_systm.h> 4144361Sborman # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) 4244361Sborman # include <machine/endian.h> 4344361Sborman # endif /* vax */ 4444361Sborman # endif /* CRAY */ 4544361Sborman #include <netinet/ip.h> 4644361Sborman #endif /* SRCRT */ 4738689Sborman 4840248Sborman #if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS) 4944361Sborman # define HAS_IP_TOS 5040248Sborman #endif 5138689Sborman 5240248Sborman 5332144Sminshall char *hostname; 5438689Sborman extern char *getenv(); 5532144Sminshall 5636180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 5732144Sminshall static char *ambiguous; /* special return value for command routines */ 5844361Sborman static call(); 5932144Sminshall 6032144Sminshall typedef struct { 6132144Sminshall char *name; /* command name */ 6238689Sborman char *help; /* help string (NULL for no help) */ 6332144Sminshall int (*handler)(); /* routine which executes command */ 6432144Sminshall int needconnect; /* Do we need to be connected to execute? */ 6532144Sminshall } Command; 6632144Sminshall 6738689Sborman static char line[256]; 6838689Sborman static char saveline[256]; 6932144Sminshall static int margc; 7032144Sminshall static char *margv[20]; 7132144Sminshall 7232144Sminshall /* 7332144Sminshall * Various utility routines. 7432144Sminshall */ 7532144Sminshall 7636180Sminshall #if !defined(BSD) || (BSD <= 43) 7736180Sminshall 7836180Sminshall char *h_errlist[] = { 7936180Sminshall "Error 0", 8036180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 8136180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 8236180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 8336180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 8436180Sminshall }; 8536180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 8636180Sminshall 8736274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 8836180Sminshall 8936180Sminshall /* 9036180Sminshall * herror -- 9136180Sminshall * print the error indicated by the h_errno value. 9236180Sminshall */ 9336180Sminshall herror(s) 9436180Sminshall char *s; 9536180Sminshall { 9636180Sminshall if (s && *s) { 9736180Sminshall fprintf(stderr, "%s: ", s); 9836180Sminshall } 9936180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 10036180Sminshall fprintf(stderr, "Unknown error\n"); 10136274Sminshall } else if (h_errno == 0) { 10236274Sminshall #if defined(sun) 10336274Sminshall fprintf(stderr, "Host unknown\n"); 10436274Sminshall #endif /* defined(sun) */ 10536180Sminshall } else { 10636180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 10736180Sminshall } 10836180Sminshall } 10936180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 11036180Sminshall 11132144Sminshall static void 11232144Sminshall makeargv() 11332144Sminshall { 11444361Sborman register char *cp, *cp2, c; 11532144Sminshall register char **argp = margv; 11632144Sminshall 11732144Sminshall margc = 0; 11832144Sminshall cp = line; 11932144Sminshall if (*cp == '!') { /* Special case shell escape */ 12038689Sborman strcpy(saveline, line); /* save for shell command */ 12132144Sminshall *argp++ = "!"; /* No room in string to get this */ 12232144Sminshall margc++; 12332144Sminshall cp++; 12432144Sminshall } 12544361Sborman while (c = *cp) { 12644361Sborman register int inquote = 0; 12744361Sborman while (isspace(c)) 12844361Sborman c = *++cp; 12944361Sborman if (c == '\0') 13032144Sminshall break; 13132144Sminshall *argp++ = cp; 13232144Sminshall margc += 1; 13344361Sborman for (cp2 = cp; c != '\0'; c = *++cp) { 13444361Sborman if (inquote) { 13544361Sborman if (c == inquote) { 13644361Sborman inquote = 0; 13744361Sborman continue; 13844361Sborman } 13944361Sborman } else { 14044361Sborman if (c == '\\') { 14144361Sborman if ((c = *++cp) == '\0') 14244361Sborman break; 14344361Sborman } else if (c == '"') { 14444361Sborman inquote = '"'; 14544361Sborman continue; 14644361Sborman } else if (c == '\'') { 14744361Sborman inquote = '\''; 14844361Sborman continue; 14944361Sborman } else if (isspace(c)) 15044361Sborman break; 15144361Sborman } 15244361Sborman *cp2++ = c; 15344361Sborman } 15444361Sborman *cp2 = '\0'; 15544361Sborman if (c == '\0') 15632144Sminshall break; 15744361Sborman cp++; 15832144Sminshall } 15932144Sminshall *argp++ = 0; 16032144Sminshall } 16132144Sminshall 16232144Sminshall 16332144Sminshall static char ** 16432144Sminshall genget(name, table, next) 16532144Sminshall char *name; /* name to match */ 16632144Sminshall char **table; /* name entry in table */ 16732144Sminshall char **(*next)(); /* routine to return next entry in table */ 16832144Sminshall { 16932144Sminshall register char *p, *q; 17032144Sminshall register char **c, **found; 17132144Sminshall register int nmatches, longest; 17232144Sminshall 17332144Sminshall if (name == 0) { 17432144Sminshall return 0; 17532144Sminshall } 17632144Sminshall longest = 0; 17732144Sminshall nmatches = 0; 17832144Sminshall found = 0; 17932144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 18032144Sminshall for (q = name; 18132144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 18232144Sminshall if (*q == 0) /* exact match? */ 18332144Sminshall return (c); 18432144Sminshall if (!*q) { /* the name was a prefix */ 18532144Sminshall if (q - name > longest) { 18632144Sminshall longest = q - name; 18732144Sminshall nmatches = 1; 18832144Sminshall found = c; 18932144Sminshall } else if (q - name == longest) 19032144Sminshall nmatches++; 19132144Sminshall } 19232144Sminshall } 19332144Sminshall if (nmatches > 1) 19436180Sminshall return &ambiguous; 19532144Sminshall return (found); 19632144Sminshall } 19732144Sminshall 19832144Sminshall /* 19932144Sminshall * Make a character string into a number. 20032144Sminshall * 20132144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 20232144Sminshall */ 20332144Sminshall 20432144Sminshall static 20532144Sminshall special(s) 20632144Sminshall register char *s; 20732144Sminshall { 20832144Sminshall register char c; 20932144Sminshall char b; 21032144Sminshall 21132144Sminshall switch (*s) { 21232144Sminshall case '^': 21332144Sminshall b = *++s; 21432144Sminshall if (b == '?') { 21532144Sminshall c = b | 0x40; /* DEL */ 21632144Sminshall } else { 21732144Sminshall c = b & 0x1f; 21832144Sminshall } 21932144Sminshall break; 22032144Sminshall default: 22132144Sminshall c = *s; 22232144Sminshall break; 22332144Sminshall } 22432144Sminshall return c; 22532144Sminshall } 22632144Sminshall 22732144Sminshall /* 22832144Sminshall * Construct a control character sequence 22932144Sminshall * for a special character. 23032144Sminshall */ 23132144Sminshall static char * 23232144Sminshall control(c) 23340245Sborman register cc_t c; 23432144Sminshall { 23544361Sborman static char buf[5]; 23632144Sminshall 23732144Sminshall if (c == 0x7f) 23832144Sminshall return ("^?"); 239*45233Sborman if (c == (cc_t)_POSIX_VDISABLE) { 24032144Sminshall return "off"; 24132144Sminshall } 242*45233Sborman if ((unsigned int)c >= 0x80) { 24344361Sborman buf[0] = '\\'; 24444361Sborman buf[1] = ((c>>6)&07) + '0'; 24544361Sborman buf[2] = ((c>>3)&07) + '0'; 24644361Sborman buf[3] = (c&07) + '0'; 24744361Sborman buf[4] = 0; 248*45233Sborman } else if ((unsigned int)c >= 0x20) { 24932144Sminshall buf[0] = c; 25032144Sminshall buf[1] = 0; 25132144Sminshall } else { 25232144Sminshall buf[0] = '^'; 25332144Sminshall buf[1] = '@'+c; 25432144Sminshall buf[2] = 0; 25532144Sminshall } 25632144Sminshall return (buf); 25732144Sminshall } 25832144Sminshall 25932144Sminshall 26032144Sminshall 26132144Sminshall /* 26232144Sminshall * The following are data structures and routines for 26332144Sminshall * the "send" command. 26432144Sminshall * 26532144Sminshall */ 26632144Sminshall 26732144Sminshall struct sendlist { 26832144Sminshall char *name; /* How user refers to it (case independent) */ 26932144Sminshall char *help; /* Help information (0 ==> no help) */ 27032144Sminshall #if defined(NOT43) 27138689Sborman int (*handler)(); /* Routine to perform (for special ops) */ 27232144Sminshall #else /* defined(NOT43) */ 27338689Sborman void (*handler)(); /* Routine to perform (for special ops) */ 27432144Sminshall #endif /* defined(NOT43) */ 27538689Sborman int what; /* Character to be sent (<0 ==> special) */ 27632144Sminshall }; 27732144Sminshall 27832144Sminshall #define SENDQUESTION -1 27932144Sminshall #define SENDESCAPE -3 28032144Sminshall 28132144Sminshall static struct sendlist Sendlist[] = { 28238689Sborman { "ao", "Send Telnet Abort output", 0, AO }, 28338689Sborman { "ayt", "Send Telnet 'Are You There'", 0, AYT }, 28438689Sborman { "brk", "Send Telnet Break", 0, BREAK }, 28538689Sborman { "ec", "Send Telnet Erase Character", 0, EC }, 28638689Sborman { "el", "Send Telnet Erase Line", 0, EL }, 28738689Sborman { "escape", "Send current escape character", 0, SENDESCAPE }, 28838689Sborman { "ga", "Send Telnet 'Go Ahead' sequence", 0, GA }, 28938689Sborman { "ip", "Send Telnet Interrupt Process", 0, IP }, 29038689Sborman { "nop", "Send Telnet 'No operation'", 0, NOP }, 29138689Sborman { "eor", "Send Telnet 'End of Record'", 0, EOR }, 29238689Sborman { "abort", "Send Telnet 'Abort Process'", 0, ABORT }, 29338689Sborman { "susp", "Send Telnet 'Suspend Process'", 0, SUSP }, 29438689Sborman { "eof", "Send Telnet End of File Character", 0, xEOF }, 29538689Sborman { "synch", "Perform Telnet 'Synch operation'", dosynch, SYNCH }, 29638909Sborman { "getstatus", "Send request for STATUS", get_status, 0 }, 29738689Sborman { "?", "Display send options", 0, SENDQUESTION }, 29832144Sminshall { 0 } 29932144Sminshall }; 30032144Sminshall 30132144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 30238689Sborman { "break", 0, 0, BREAK }, 30332144Sminshall 30438689Sborman { "intp", 0, 0, IP }, 30538689Sborman { "interrupt", 0, 0, IP }, 30638689Sborman { "intr", 0, 0, IP }, 30732144Sminshall 30838689Sborman { "help", 0, 0, SENDQUESTION }, 30932144Sminshall 31038689Sborman { 0 } 31132144Sminshall }; 31232144Sminshall 31332144Sminshall static char ** 31432144Sminshall getnextsend(name) 31532144Sminshall char *name; 31632144Sminshall { 31732144Sminshall struct sendlist *c = (struct sendlist *) name; 31832144Sminshall 31932144Sminshall return (char **) (c+1); 32032144Sminshall } 32132144Sminshall 32232144Sminshall static struct sendlist * 32332144Sminshall getsend(name) 32432144Sminshall char *name; 32532144Sminshall { 32632144Sminshall struct sendlist *sl; 32732144Sminshall 32832144Sminshall if ((sl = (struct sendlist *) 32932144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 33032144Sminshall return sl; 33132144Sminshall } else { 33232144Sminshall return (struct sendlist *) 33332144Sminshall genget(name, (char **) Sendlist2, getnextsend); 33432144Sminshall } 33532144Sminshall } 33632144Sminshall 33732144Sminshall static 33832144Sminshall sendcmd(argc, argv) 33932144Sminshall int argc; 34032144Sminshall char **argv; 34132144Sminshall { 34232144Sminshall int what; /* what we are sending this time */ 34332144Sminshall int count; /* how many bytes we are going to need to send */ 34432144Sminshall int i; 34532144Sminshall int question = 0; /* was at least one argument a question */ 34632144Sminshall struct sendlist *s; /* pointer to current command */ 34732144Sminshall 34832144Sminshall if (argc < 2) { 34932144Sminshall printf("need at least one argument for 'send' command\n"); 35032144Sminshall printf("'send ?' for help\n"); 35132144Sminshall return 0; 35232144Sminshall } 35332144Sminshall /* 35432144Sminshall * First, validate all the send arguments. 35532144Sminshall * In addition, we see how much space we are going to need, and 35632144Sminshall * whether or not we will be doing a "SYNCH" operation (which 35732144Sminshall * flushes the network queue). 35832144Sminshall */ 35932144Sminshall count = 0; 36032144Sminshall for (i = 1; i < argc; i++) { 36132144Sminshall s = getsend(argv[i]); 36232144Sminshall if (s == 0) { 36332144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 36432144Sminshall argv[i]); 36532144Sminshall return 0; 36632144Sminshall } else if (Ambiguous(s)) { 36732144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 36832144Sminshall argv[i]); 36932144Sminshall return 0; 37032144Sminshall } 37132144Sminshall switch (s->what) { 37232144Sminshall case SENDQUESTION: 37338689Sborman question = 1; 37432144Sminshall break; 37532144Sminshall case SENDESCAPE: 37632144Sminshall count += 1; 37732144Sminshall break; 37832144Sminshall case SYNCH: 37932144Sminshall count += 2; 38032144Sminshall break; 38132144Sminshall default: 38232144Sminshall count += 2; 38332144Sminshall break; 38432144Sminshall } 38532144Sminshall } 38638689Sborman if (!connected) { 38738689Sborman if (count) 38838689Sborman printf("?Need to be connected first.\n"); 38938689Sborman if (question) { 39038689Sborman for (s = Sendlist; s->name; s++) 39138689Sborman if (s->help) 39238689Sborman printf("%-15s %s\n", s->name, s->help); 39338689Sborman } else 39438689Sborman printf("'send ?' for help\n"); 39538689Sborman return !question; 39638689Sborman } 39732144Sminshall /* Now, do we have enough room? */ 39832144Sminshall if (NETROOM() < count) { 39932144Sminshall printf("There is not enough room in the buffer TO the network\n"); 40032144Sminshall printf("to process your request. Nothing will be done.\n"); 40132144Sminshall printf("('send synch' will throw away most data in the network\n"); 40232144Sminshall printf("buffer, if this might help.)\n"); 40332144Sminshall return 0; 40432144Sminshall } 40532144Sminshall /* OK, they are all OK, now go through again and actually send */ 40632144Sminshall for (i = 1; i < argc; i++) { 40732144Sminshall if ((s = getsend(argv[i])) == 0) { 40832144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 40944361Sborman (void) quit(); 41032144Sminshall /*NOTREACHED*/ 41132144Sminshall } 41238689Sborman if (s->handler) { 41338689Sborman (*s->handler)(s); 41432144Sminshall } else { 41532144Sminshall switch (what = s->what) { 41632144Sminshall case SYNCH: 41732144Sminshall dosynch(); 41832144Sminshall break; 41932144Sminshall case SENDQUESTION: 42032144Sminshall for (s = Sendlist; s->name; s++) { 42138689Sborman if (s->help) 42238689Sborman printf("%-15s %s\n", s->name, s->help); 42332144Sminshall } 42432144Sminshall question = 1; 42532144Sminshall break; 42632144Sminshall case SENDESCAPE: 42732144Sminshall NETADD(escape); 42832144Sminshall break; 42932144Sminshall default: 43032144Sminshall NET2ADD(IAC, what); 431*45233Sborman printoption("SENT", "IAC", what); 43232144Sminshall break; 43332144Sminshall } 43432144Sminshall } 43532144Sminshall } 43632144Sminshall return !question; 43732144Sminshall } 43832144Sminshall 43932144Sminshall /* 44032144Sminshall * The following are the routines and data structures referred 44132144Sminshall * to by the arguments to the "toggle" command. 44232144Sminshall */ 44332144Sminshall 44432144Sminshall static 44532144Sminshall lclchars() 44632144Sminshall { 44732144Sminshall donelclchars = 1; 44832144Sminshall return 1; 44932144Sminshall } 45032144Sminshall 45132144Sminshall static 45232144Sminshall togdebug() 45332144Sminshall { 45432144Sminshall #ifndef NOT43 45532144Sminshall if (net > 0 && 45632144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 45732144Sminshall perror("setsockopt (SO_DEBUG)"); 45832144Sminshall } 45932144Sminshall #else /* NOT43 */ 46032144Sminshall if (debug) { 46132144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 46232144Sminshall perror("setsockopt (SO_DEBUG)"); 46332144Sminshall } else 46432144Sminshall printf("Cannot turn off socket debugging\n"); 46532144Sminshall #endif /* NOT43 */ 46632144Sminshall return 1; 46732144Sminshall } 46832144Sminshall 46932144Sminshall 47032144Sminshall static int 47132144Sminshall togcrlf() 47232144Sminshall { 47332144Sminshall if (crlf) { 47432144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 47532144Sminshall } else { 47632144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 47732144Sminshall } 47832144Sminshall return 1; 47932144Sminshall } 48032144Sminshall 48138909Sborman int binmode; 48232144Sminshall 48332144Sminshall static int 48438689Sborman togbinary(val) 48538689Sborman int val; 48632144Sminshall { 48732144Sminshall donebinarytoggle = 1; 48832144Sminshall 48938909Sborman if (val >= 0) { 49038909Sborman binmode = val; 49138909Sborman } else { 49238909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 49338909Sborman my_want_state_is_do(TELOPT_BINARY)) { 49438909Sborman binmode = 1; 49538909Sborman } else if (my_want_state_is_wont(TELOPT_BINARY) && 49638909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 49738909Sborman binmode = 0; 49838909Sborman } 49938909Sborman val = binmode ? 0 : 1; 50038909Sborman } 50138909Sborman 50238909Sborman if (val == 1) { 50338909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 50438909Sborman my_want_state_is_do(TELOPT_BINARY)) { 50538689Sborman printf("Already operating in binary mode with remote host.\n"); 50638909Sborman } else { 50738909Sborman printf("Negotiating binary mode with remote host.\n"); 50838909Sborman tel_enter_binary(3); 50938689Sborman } 51038909Sborman } else { 51138909Sborman if (my_want_state_is_wont(TELOPT_BINARY) && 51238909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 51338689Sborman printf("Already in network ascii mode with remote host.\n"); 51438909Sborman } else { 51538909Sborman printf("Negotiating network ascii mode with remote host.\n"); 51638909Sborman tel_leave_binary(3); 51738689Sborman } 51832144Sminshall } 51932144Sminshall return 1; 52032144Sminshall } 52132144Sminshall 52238909Sborman static int 52338909Sborman togrbinary(val) 52438909Sborman int val; 52538909Sborman { 52638909Sborman donebinarytoggle = 1; 52732144Sminshall 52838909Sborman if (val == -1) 52938909Sborman val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 53032144Sminshall 53138909Sborman if (val == 1) { 53238909Sborman if (my_want_state_is_do(TELOPT_BINARY)) { 53338909Sborman printf("Already receiving in binary mode.\n"); 53438909Sborman } else { 53538909Sborman printf("Negotiating binary mode on input.\n"); 53638909Sborman tel_enter_binary(1); 53738909Sborman } 53838909Sborman } else { 53938909Sborman if (my_want_state_is_dont(TELOPT_BINARY)) { 54038909Sborman printf("Already receiving in network ascii mode.\n"); 54138909Sborman } else { 54238909Sborman printf("Negotiating network ascii mode on input.\n"); 54338909Sborman tel_leave_binary(1); 54438909Sborman } 54538909Sborman } 54638909Sborman return 1; 54738909Sborman } 54838909Sborman 54938909Sborman static int 55038909Sborman togxbinary(val) 55138909Sborman int val; 55238909Sborman { 55338909Sborman donebinarytoggle = 1; 55438909Sborman 55538909Sborman if (val == -1) 55638909Sborman val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 55738909Sborman 55838909Sborman if (val == 1) { 55938909Sborman if (my_want_state_is_will(TELOPT_BINARY)) { 56038909Sborman printf("Already transmitting in binary mode.\n"); 56138909Sborman } else { 56238909Sborman printf("Negotiating binary mode on output.\n"); 56338909Sborman tel_enter_binary(2); 56438909Sborman } 56538909Sborman } else { 56638909Sborman if (my_want_state_is_wont(TELOPT_BINARY)) { 56738909Sborman printf("Already transmitting in network ascii mode.\n"); 56838909Sborman } else { 56938909Sborman printf("Negotiating network ascii mode on output.\n"); 57038909Sborman tel_leave_binary(2); 57138909Sborman } 57238909Sborman } 57338909Sborman return 1; 57438909Sborman } 57538909Sborman 57638909Sborman 57732144Sminshall extern int togglehelp(); 57838689Sborman extern int slc_check(); 57932144Sminshall 58032144Sminshall struct togglelist { 58132144Sminshall char *name; /* name of toggle */ 58232144Sminshall char *help; /* help message */ 58332144Sminshall int (*handler)(); /* routine to do actual setting */ 58432144Sminshall int *variable; 58532144Sminshall char *actionexplanation; 58632144Sminshall }; 58732144Sminshall 58832144Sminshall static struct togglelist Togglelist[] = { 58932144Sminshall { "autoflush", 59038689Sborman "flushing of output when sending interrupt characters", 59132144Sminshall 0, 59238689Sborman &autoflush, 59338689Sborman "flush output when sending interrupt characters" }, 59432144Sminshall { "autosynch", 59538689Sborman "automatic sending of interrupt characters in urgent mode", 59632144Sminshall 0, 59738689Sborman &autosynch, 59838689Sborman "send interrupt characters in urgent mode" }, 59932144Sminshall { "binary", 60038689Sborman "sending and receiving of binary data", 60132144Sminshall togbinary, 60238689Sborman 0, 60338689Sborman 0 }, 60438909Sborman { "inbinary", 60538909Sborman "receiving of binary data", 60638909Sborman togrbinary, 60738909Sborman 0, 60838909Sborman 0 }, 60938909Sborman { "outbinary", 61038909Sborman "sending of binary data", 61138909Sborman togxbinary, 61238909Sborman 0, 61338909Sborman 0 }, 61432144Sminshall { "crlf", 61538689Sborman "sending carriage returns as telnet <CR><LF>", 61632144Sminshall togcrlf, 61738689Sborman &crlf, 61838689Sborman 0 }, 61932144Sminshall { "crmod", 62038689Sborman "mapping of received carriage returns", 62132144Sminshall 0, 62238689Sborman &crmod, 62338689Sborman "map carriage return on output" }, 62432144Sminshall { "localchars", 62538689Sborman "local recognition of certain control characters", 62632144Sminshall lclchars, 62738689Sborman &localchars, 62838689Sborman "recognize certain control characters" }, 62943317Skfall #ifdef KERBEROS 63043317Skfall { "kerberos", 63143317Skfall "toggle use of Kerberos authentication", 63243317Skfall 0, 63343317Skfall &kerberized, 63443317Skfall "use Kerberos authentication" }, 63543317Skfall #endif 63638689Sborman { " ", "", 0 }, /* empty line */ 63738208Sminshall #if defined(unix) && defined(TN3270) 63838920Sminshall { "apitrace", 63938920Sminshall "(debugging) toggle tracing of API transactions", 64038920Sminshall 0, 64138920Sminshall &apitrace, 64238920Sminshall "trace API transactions" }, 64338208Sminshall { "cursesdata", 64438208Sminshall "(debugging) toggle printing of hexadecimal curses data", 64538208Sminshall 0, 64638689Sborman &cursesdata, 64738689Sborman "print hexadecimal representation of curses data" }, 64838208Sminshall #endif /* defined(unix) && defined(TN3270) */ 64932144Sminshall { "debug", 65038689Sborman "debugging", 65132144Sminshall togdebug, 65238689Sborman &debug, 65338689Sborman "turn on socket level debugging" }, 65432144Sminshall { "netdata", 65538689Sborman "printing of hexadecimal network data (debugging)", 65632144Sminshall 0, 65738689Sborman &netdata, 65838689Sborman "print hexadecimal representation of network traffic" }, 65938689Sborman { "prettydump", 66038689Sborman "output of \"netdata\" to user readable format (debugging)", 66138689Sborman 0, 66238689Sborman &prettydump, 66338689Sborman "print user readable output for \"netdata\"" }, 66432144Sminshall { "options", 66538689Sborman "viewing of options processing (debugging)", 66632144Sminshall 0, 66738689Sborman &showoptions, 66838689Sborman "show option processing" }, 66938208Sminshall #if defined(unix) 67038208Sminshall { "termdata", 67138208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 67238208Sminshall 0, 67338689Sborman &termdata, 67438689Sborman "print hexadecimal representation of terminal traffic" }, 67538208Sminshall #endif /* defined(unix) */ 67632144Sminshall { "?", 67738689Sborman 0, 67838689Sborman togglehelp }, 67932144Sminshall { "help", 68038689Sborman 0, 68138689Sborman togglehelp }, 68232144Sminshall { 0 } 68332144Sminshall }; 68432144Sminshall 68532144Sminshall static 68632144Sminshall togglehelp() 68732144Sminshall { 68832144Sminshall struct togglelist *c; 68932144Sminshall 69032144Sminshall for (c = Togglelist; c->name; c++) { 69138689Sborman if (c->help) { 69238689Sborman if (*c->help) 69338689Sborman printf("%-15s toggle %s\n", c->name, c->help); 69438689Sborman else 69538689Sborman printf("\n"); 69632144Sminshall } 69732144Sminshall } 69838689Sborman printf("\n"); 69938689Sborman printf("%-15s %s\n", "?", "display help information"); 70032144Sminshall return 0; 70132144Sminshall } 70232144Sminshall 70338689Sborman static 70438689Sborman settogglehelp(set) 70538689Sborman int set; 70638689Sborman { 70738689Sborman struct togglelist *c; 70838689Sborman 70938689Sborman for (c = Togglelist; c->name; c++) { 71038689Sborman if (c->help) { 71138689Sborman if (*c->help) 71238689Sborman printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 71338689Sborman c->help); 71438689Sborman else 71538689Sborman printf("\n"); 71638689Sborman } 71738689Sborman } 71838689Sborman } 71938689Sborman 72032144Sminshall static char ** 72132144Sminshall getnexttoggle(name) 72232144Sminshall char *name; 72332144Sminshall { 72432144Sminshall struct togglelist *c = (struct togglelist *) name; 72532144Sminshall 72632144Sminshall return (char **) (c+1); 72732144Sminshall } 72832144Sminshall 72932144Sminshall static struct togglelist * 73032144Sminshall gettoggle(name) 73132144Sminshall char *name; 73232144Sminshall { 73332144Sminshall return (struct togglelist *) 73432144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 73532144Sminshall } 73632144Sminshall 73732144Sminshall static 73832144Sminshall toggle(argc, argv) 73932144Sminshall int argc; 74032144Sminshall char *argv[]; 74132144Sminshall { 74232144Sminshall int retval = 1; 74332144Sminshall char *name; 74432144Sminshall struct togglelist *c; 74532144Sminshall 74632144Sminshall if (argc < 2) { 74732144Sminshall fprintf(stderr, 74832144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 74932144Sminshall return 0; 75032144Sminshall } 75132144Sminshall argc--; 75232144Sminshall argv++; 75332144Sminshall while (argc--) { 75432144Sminshall name = *argv++; 75532144Sminshall c = gettoggle(name); 75632144Sminshall if (Ambiguous(c)) { 75732144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 75832144Sminshall name); 75932144Sminshall return 0; 76032144Sminshall } else if (c == 0) { 76132144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 76232144Sminshall name); 76332144Sminshall return 0; 76432144Sminshall } else { 76532144Sminshall if (c->variable) { 76632144Sminshall *c->variable = !*c->variable; /* invert it */ 76732144Sminshall if (c->actionexplanation) { 76832144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 76932144Sminshall c->actionexplanation); 77032144Sminshall } 77132144Sminshall } 77232144Sminshall if (c->handler) { 77338689Sborman retval &= (*c->handler)(-1); 77432144Sminshall } 77532144Sminshall } 77632144Sminshall } 77732144Sminshall return retval; 77832144Sminshall } 77932144Sminshall 78032144Sminshall /* 78132144Sminshall * The following perform the "set" command. 78232144Sminshall */ 78332144Sminshall 78438689Sborman #ifdef USE_TERMIO 78538689Sborman struct termio new_tc = { 0 }; 78638689Sborman #endif 78738689Sborman 78832144Sminshall struct setlist { 78932144Sminshall char *name; /* name */ 79032144Sminshall char *help; /* help information */ 79138689Sborman void (*handler)(); 79240245Sborman cc_t *charp; /* where it is located at */ 79332144Sminshall }; 79432144Sminshall 79532144Sminshall static struct setlist Setlist[] = { 79644361Sborman #ifdef KLUDGELINEMODE 79738689Sborman { "echo", "character to toggle local echoing on/off", 0, &echoc }, 79844361Sborman #endif 79938689Sborman { "escape", "character to escape back to telnet command mode", 0, &escape }, 800*45233Sborman { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, 80132144Sminshall { " ", "" }, 80238689Sborman { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 803*45233Sborman { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, 80438689Sborman { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 80538689Sborman { "quit", "character to cause an Abort process", 0, termQuitCharp }, 80638689Sborman { "eof", "character to cause an EOF ", 0, termEofCharp }, 80738689Sborman { " ", "" }, 80838689Sborman { " ", "The following are for local editing in linemode", 0, 0 }, 80938689Sborman { "erase", "character to use to erase a character", 0, termEraseCharp }, 81038689Sborman { "kill", "character to use to erase a line", 0, termKillCharp }, 81138689Sborman { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 81244361Sborman { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, 81338689Sborman { "reprint", "character to use for line reprint", 0, termRprntCharp }, 81438689Sborman { "worderase", "character to use to erase a word", 0, termWerasCharp }, 81538689Sborman { "start", "character to use for XON", 0, termStartCharp }, 81644361Sborman { "stop", "character to use for XOFF", 0, termStopCharp }, 81744361Sborman { "forw1", "alternate end of line character", 0, termForw1Charp }, 81844361Sborman { "forw2", "alternate end of line character", 0, termForw2Charp }, 819*45233Sborman { "ayt", "alternate AYT character", 0, termAytCharp }, 82032144Sminshall { 0 } 82132144Sminshall }; 82232144Sminshall 823*45233Sborman #if defined(CRAY) && !defined(__STDC__) 824*45233Sborman /* Work around compiler bug in pcc 4.1.5 */ 82538689Sborman _setlist_init() 82638689Sborman { 82744361Sborman #ifndef KLUDGELINEMODE 82844361Sborman #define N 4 82944361Sborman #else 83044361Sborman #define N 5 83144361Sborman #endif 83244361Sborman Setlist[N+0].charp = &termFlushChar; 83344361Sborman Setlist[N+1].charp = &termIntChar; 83444361Sborman Setlist[N+2].charp = &termQuitChar; 83544361Sborman Setlist[N+3].charp = &termEofChar; 83644361Sborman Setlist[N+6].charp = &termEraseChar; 83744361Sborman Setlist[N+7].charp = &termKillChar; 83844361Sborman Setlist[N+8].charp = &termLiteralNextChar; 83944361Sborman Setlist[N+9].charp = &termSuspChar; 84044361Sborman Setlist[N+10].charp = &termRprntChar; 84144361Sborman Setlist[N+11].charp = &termWerasChar; 84244361Sborman Setlist[N+12].charp = &termStartChar; 84344361Sborman Setlist[N+13].charp = &termStopChar; 84444361Sborman Setlist[N+14].charp = &termForw1Char; 84544361Sborman Setlist[N+15].charp = &termForw2Char; 846*45233Sborman Setlist[N+16].charp = &termAytChar; 84744361Sborman #undef N 84838689Sborman } 849*45233Sborman #endif /* defined(CRAY) && !defined(__STDC__) */ 85038689Sborman 85132144Sminshall static char ** 85232144Sminshall getnextset(name) 85332144Sminshall char *name; 85432144Sminshall { 85532144Sminshall struct setlist *c = (struct setlist *)name; 85632144Sminshall 85732144Sminshall return (char **) (c+1); 85832144Sminshall } 85932144Sminshall 86032144Sminshall static struct setlist * 86132144Sminshall getset(name) 86232144Sminshall char *name; 86332144Sminshall { 86432144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 86532144Sminshall } 86632144Sminshall 86744361Sborman set_escape_char(s) 86844361Sborman char *s; 86944361Sborman { 870*45233Sborman escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 87144361Sborman printf("escape character is '%s'.\n", control(escape)); 87244361Sborman } 87344361Sborman 87432144Sminshall static 87532144Sminshall setcmd(argc, argv) 87632144Sminshall int argc; 87732144Sminshall char *argv[]; 87832144Sminshall { 87932144Sminshall int value; 88032144Sminshall struct setlist *ct; 88138689Sborman struct togglelist *c; 88232144Sminshall 88338689Sborman if (argc < 2 || argc > 3) { 88438689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 88532144Sminshall return 0; 88632144Sminshall } 88738689Sborman if ((argc == 2) && 88838689Sborman ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 88938689Sborman for (ct = Setlist; ct->name; ct++) 89038689Sborman printf("%-15s %s\n", ct->name, ct->help); 89138689Sborman printf("\n"); 89238689Sborman settogglehelp(1); 89338689Sborman printf("%-15s %s\n", "?", "display help information"); 89438689Sborman return 0; 89538689Sborman } 89632144Sminshall 89732144Sminshall ct = getset(argv[1]); 89832144Sminshall if (ct == 0) { 89938689Sborman c = gettoggle(argv[1]); 90038689Sborman if (c == 0) { 90138689Sborman fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 90232144Sminshall argv[1]); 90338689Sborman return 0; 90438689Sborman } else if (Ambiguous(c)) { 90538689Sborman fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 90638689Sborman argv[1]); 90738689Sborman return 0; 90838689Sborman } 90938689Sborman if (c->variable) { 91038689Sborman if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 91138689Sborman *c->variable = 1; 91238689Sborman else if (strcmp("off", argv[2]) == 0) 91338689Sborman *c->variable = 0; 91438689Sborman else { 91538689Sborman printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 91638689Sborman return 0; 91738689Sborman } 91838689Sborman if (c->actionexplanation) { 91938689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 92038689Sborman c->actionexplanation); 92138689Sborman } 92238689Sborman } 92338689Sborman if (c->handler) 92438689Sborman (*c->handler)(1); 92538689Sborman } else if (argc != 3) { 92638689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 92732144Sminshall return 0; 92832144Sminshall } else if (Ambiguous(ct)) { 92932144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 93032144Sminshall argv[1]); 93132144Sminshall return 0; 93238689Sborman } else if (ct->handler) { 93338689Sborman (*ct->handler)(argv[2]); 93444361Sborman printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 93532144Sminshall } else { 93632144Sminshall if (strcmp("off", argv[2])) { 93732144Sminshall value = special(argv[2]); 93832144Sminshall } else { 939*45233Sborman value = _POSIX_VDISABLE; 94032144Sminshall } 94140245Sborman *(ct->charp) = (cc_t)value; 94232144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 94332144Sminshall } 94438689Sborman slc_check(); 94532144Sminshall return 1; 94632144Sminshall } 94738689Sborman 94838689Sborman static 94938689Sborman unsetcmd(argc, argv) 95038689Sborman int argc; 95138689Sborman char *argv[]; 95238689Sborman { 95338689Sborman struct setlist *ct; 95438689Sborman struct togglelist *c; 95538689Sborman register char *name; 95638689Sborman 95738689Sborman if (argc < 2) { 95838689Sborman fprintf(stderr, 95938689Sborman "Need an argument to 'unset' command. 'unset ?' for help.\n"); 96038689Sborman return 0; 96138689Sborman } 96238689Sborman if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) { 96338689Sborman for (ct = Setlist; ct->name; ct++) 96438689Sborman printf("%-15s %s\n", ct->name, ct->help); 96538689Sborman printf("\n"); 96638689Sborman settogglehelp(0); 96738689Sborman printf("%-15s %s\n", "?", "display help information"); 96838689Sborman return 0; 96938689Sborman } 97038689Sborman 97138689Sborman argc--; 97238689Sborman argv++; 97338689Sborman while (argc--) { 97438689Sborman name = *argv++; 97538689Sborman ct = getset(name); 97638689Sborman if (ct == 0) { 97738689Sborman c = gettoggle(name); 97838689Sborman if (c == 0) { 97938689Sborman fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 98038689Sborman name); 98138689Sborman return 0; 98238689Sborman } else if (Ambiguous(c)) { 98338689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 98438689Sborman name); 98538689Sborman return 0; 98638689Sborman } 98738689Sborman if (c->variable) { 98838689Sborman *c->variable = 0; 98938689Sborman if (c->actionexplanation) { 99038689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 99138689Sborman c->actionexplanation); 99238689Sborman } 99338689Sborman } 99438689Sborman if (c->handler) 99538689Sborman (*c->handler)(0); 99638689Sborman } else if (Ambiguous(ct)) { 99738689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 99838689Sborman name); 99938689Sborman return 0; 100038689Sborman } else if (ct->handler) { 100138689Sborman (*ct->handler)(0); 100244361Sborman printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 100338689Sborman } else { 1004*45233Sborman *(ct->charp) = _POSIX_VDISABLE; 100538689Sborman printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 100638689Sborman } 100738689Sborman } 100838689Sborman return 1; 100938689Sborman } 101032144Sminshall 101132144Sminshall /* 101232144Sminshall * The following are the data structures and routines for the 101332144Sminshall * 'mode' command. 101432144Sminshall */ 101538689Sborman #ifdef KLUDGELINEMODE 101638689Sborman extern int kludgelinemode; 101744361Sborman 101844361Sborman dokludgemode() 101944361Sborman { 102044361Sborman kludgelinemode = 1; 102144361Sborman send_wont(TELOPT_LINEMODE, 1); 102244361Sborman send_dont(TELOPT_SGA, 1); 102344361Sborman send_dont(TELOPT_ECHO, 1); 102444361Sborman } 102538689Sborman #endif 102632144Sminshall 102732144Sminshall static 102832144Sminshall dolinemode() 102932144Sminshall { 103038689Sborman #ifdef KLUDGELINEMODE 103138689Sborman if (kludgelinemode) 103238689Sborman send_dont(TELOPT_SGA, 1); 103338689Sborman #endif 103438689Sborman send_will(TELOPT_LINEMODE, 1); 103538689Sborman send_dont(TELOPT_ECHO, 1); 103632144Sminshall return 1; 103732144Sminshall } 103832144Sminshall 103932144Sminshall static 104032144Sminshall docharmode() 104132144Sminshall { 104238689Sborman #ifdef KLUDGELINEMODE 104338689Sborman if (kludgelinemode) 104438689Sborman send_do(TELOPT_SGA, 1); 104538689Sborman else 104638689Sborman #endif 104738689Sborman send_wont(TELOPT_LINEMODE, 1); 104838689Sborman send_do(TELOPT_ECHO, 1); 104938689Sborman return 1; 105038689Sborman } 105138689Sborman 105238689Sborman setmode(bit) 105338689Sborman { 105438689Sborman return dolmmode(bit, 1); 105538689Sborman } 105638689Sborman 105738689Sborman clearmode(bit) 105838689Sborman { 105938689Sborman return dolmmode(bit, 0); 106038689Sborman } 106138689Sborman 106238689Sborman dolmmode(bit, on) 106338689Sborman int bit, on; 106438689Sborman { 106538689Sborman char c; 106638689Sborman extern int linemode; 106738689Sborman 106838689Sborman if (my_want_state_is_wont(TELOPT_LINEMODE)) { 106938689Sborman printf("?Need to have LINEMODE option enabled first.\n"); 107038689Sborman printf("'mode ?' for help.\n"); 107138689Sborman return 0; 107232144Sminshall } 107338689Sborman 107438689Sborman if (on) 107538689Sborman c = (linemode | bit); 107638689Sborman else 107738689Sborman c = (linemode & ~bit); 107838689Sborman lm_mode(&c, 1, 1); 107932144Sminshall return 1; 108032144Sminshall } 108132144Sminshall 108238689Sborman struct modelist { 108338689Sborman char *name; /* command name */ 108438689Sborman char *help; /* help string */ 108538689Sborman int (*handler)(); /* routine which executes command */ 108638689Sborman int needconnect; /* Do we need to be connected to execute? */ 108738689Sborman int arg1; 108838689Sborman }; 108938689Sborman 109038689Sborman extern int modehelp(); 109138689Sborman 109238689Sborman static struct modelist ModeList[] = { 109338689Sborman { "character", "Disable LINEMODE option", docharmode, 1 }, 109439529Sborman #ifdef KLUDGELINEMODE 109539529Sborman { "", "(or disable obsolete line-by-line mode)", 0 }, 109638689Sborman #endif 109738689Sborman { "line", "Enable LINEMODE option", dolinemode, 1 }, 109839529Sborman #ifdef KLUDGELINEMODE 109939529Sborman { "", "(or enable obsolete line-by-line mode)", 0 }, 110038689Sborman #endif 110138689Sborman { "", "", 0 }, 110238689Sborman { "", "These require the LINEMODE option to be enabled", 0 }, 110338689Sborman { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 110438689Sborman { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 110538689Sborman { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 110638689Sborman { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 110738689Sborman { "+edit", 0, setmode, 1, MODE_EDIT }, 110838689Sborman { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 110944361Sborman { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB }, 111044361Sborman { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB }, 111144361Sborman { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 111244361Sborman { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO }, 111344361Sborman { "+litecho", 0, setmode, 1, MODE_LIT_ECHO }, 111444361Sborman { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 111538689Sborman { "help", 0, modehelp, 0 }, 111644361Sborman #ifdef KLUDGELINEMODE 111744361Sborman { "kludgeline", 0, dokludgemode, 1 }, 111844361Sborman #endif 111944361Sborman { "", "", 0 }, 112038689Sborman { "?", "Print help information", modehelp, 0 }, 112132144Sminshall { 0 }, 112232144Sminshall }; 112332144Sminshall 112432144Sminshall static char ** 112532144Sminshall getnextmode(name) 112632144Sminshall char *name; 112732144Sminshall { 112838689Sborman return (char **) (((struct modelist *)name)+1); 112932144Sminshall } 113032144Sminshall 113138689Sborman static struct modelist * 113232144Sminshall getmodecmd(name) 113332144Sminshall char *name; 113432144Sminshall { 113538689Sborman return (struct modelist *) genget(name, (char **) ModeList, getnextmode); 113632144Sminshall } 113732144Sminshall 113838689Sborman modehelp() 113938689Sborman { 114038689Sborman struct modelist *mt; 114138689Sborman 114238689Sborman printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 114338689Sborman for (mt = ModeList; mt->name; mt++) { 114438689Sborman if (mt->help) { 114538689Sborman if (*mt->help) 114638689Sborman printf("%-15s %s\n", mt->name, mt->help); 114738689Sborman else 114838689Sborman printf("\n"); 114938689Sborman } 115038689Sborman } 115138689Sborman return 0; 115238689Sborman } 115338689Sborman 115432144Sminshall static 115532144Sminshall modecmd(argc, argv) 115632144Sminshall int argc; 115732144Sminshall char *argv[]; 115832144Sminshall { 115938689Sborman struct modelist *mt; 116032144Sminshall 116138689Sborman if (argc != 2) { 116238689Sborman printf("'mode' command requires an argument\n"); 116338689Sborman printf("'mode ?' for help.\n"); 116438689Sborman } else if ((mt = getmodecmd(argv[1])) == 0) { 116532144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 116632144Sminshall } else if (Ambiguous(mt)) { 116732144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 116838689Sborman } else if (mt->needconnect && !connected) { 116938689Sborman printf("?Need to be connected first.\n"); 117038689Sborman printf("'mode ?' for help.\n"); 117138689Sborman } else if (mt->handler) { 117238689Sborman return (*mt->handler)(mt->arg1); 117332144Sminshall } 117438689Sborman return 0; 117532144Sminshall } 117632144Sminshall 117732144Sminshall /* 117832144Sminshall * The following data structures and routines implement the 117932144Sminshall * "display" command. 118032144Sminshall */ 118132144Sminshall 118232144Sminshall static 118332144Sminshall display(argc, argv) 118432144Sminshall int argc; 118532144Sminshall char *argv[]; 118632144Sminshall { 118732144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 118832144Sminshall if (*tl->variable) { \ 118932144Sminshall printf("will"); \ 119032144Sminshall } else { \ 119132144Sminshall printf("won't"); \ 119232144Sminshall } \ 119332144Sminshall printf(" %s.\n", tl->actionexplanation); \ 119432144Sminshall } 119532144Sminshall 119632144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 119738689Sborman if (sl->handler == 0) \ 119838689Sborman printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 119938689Sborman else \ 120044361Sborman printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 120132144Sminshall } 120232144Sminshall 120332144Sminshall struct togglelist *tl; 120432144Sminshall struct setlist *sl; 120532144Sminshall 120632144Sminshall if (argc == 1) { 120732144Sminshall for (tl = Togglelist; tl->name; tl++) { 120832144Sminshall dotog(tl); 120932144Sminshall } 121032144Sminshall printf("\n"); 121132144Sminshall for (sl = Setlist; sl->name; sl++) { 121232144Sminshall doset(sl); 121332144Sminshall } 121432144Sminshall } else { 121532144Sminshall int i; 121632144Sminshall 121732144Sminshall for (i = 1; i < argc; i++) { 121832144Sminshall sl = getset(argv[i]); 121932144Sminshall tl = gettoggle(argv[i]); 122032144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 122132144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 122232144Sminshall return 0; 122332144Sminshall } else if (!sl && !tl) { 122432144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 122532144Sminshall return 0; 122632144Sminshall } else { 122732144Sminshall if (tl) { 122832144Sminshall dotog(tl); 122932144Sminshall } 123032144Sminshall if (sl) { 123132144Sminshall doset(sl); 123232144Sminshall } 123332144Sminshall } 123432144Sminshall } 123532144Sminshall } 123638689Sborman /*@*/optionstatus(); 123732144Sminshall return 1; 123832144Sminshall #undef doset 123932144Sminshall #undef dotog 124032144Sminshall } 124132144Sminshall 124232144Sminshall /* 124332144Sminshall * The following are the data structures, and many of the routines, 124432144Sminshall * relating to command processing. 124532144Sminshall */ 124632144Sminshall 124732144Sminshall /* 124832144Sminshall * Set the escape character. 124932144Sminshall */ 125032144Sminshall static 125132144Sminshall setescape(argc, argv) 125232144Sminshall int argc; 125332144Sminshall char *argv[]; 125432144Sminshall { 125532144Sminshall register char *arg; 125632144Sminshall char buf[50]; 125732144Sminshall 125832144Sminshall printf( 125932144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 126032144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 126132144Sminshall if (argc > 2) 126232144Sminshall arg = argv[1]; 126332144Sminshall else { 126432144Sminshall printf("new escape character: "); 126534849Sminshall (void) gets(buf); 126632144Sminshall arg = buf; 126732144Sminshall } 126832144Sminshall if (arg[0] != '\0') 126932144Sminshall escape = arg[0]; 127032144Sminshall if (!In3270) { 127132144Sminshall printf("Escape character is '%s'.\n", control(escape)); 127232144Sminshall } 127334849Sminshall (void) fflush(stdout); 127432144Sminshall return 1; 127532144Sminshall } 127632144Sminshall 127732144Sminshall /*VARARGS*/ 127832144Sminshall static 127932144Sminshall togcrmod() 128032144Sminshall { 128132144Sminshall crmod = !crmod; 128232144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 128332144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 128434849Sminshall (void) fflush(stdout); 128532144Sminshall return 1; 128632144Sminshall } 128732144Sminshall 128832144Sminshall /*VARARGS*/ 128932144Sminshall suspend() 129032144Sminshall { 129138689Sborman #ifdef SIGTSTP 129237219Sminshall setcommandmode(); 129337219Sminshall { 129444361Sborman long oldrows, oldcols, newrows, newcols, err; 129537219Sminshall 129644361Sborman err = TerminalWindowSize(&oldrows, &oldcols); 129734849Sminshall (void) kill(0, SIGTSTP); 129844361Sborman err += TerminalWindowSize(&newrows, &newcols); 129944361Sborman if (connected && !err && 130044361Sborman ((oldrows != newrows) || (oldcols != newcols))) { 130137219Sminshall sendnaws(); 130237219Sminshall } 130337219Sminshall } 130437219Sminshall /* reget parameters in case they were changed */ 130537219Sminshall TerminalSaveState(); 130638689Sborman setconnmode(0); 130738689Sborman #else 130838689Sborman printf("Suspend is not supported. Try the '!' command instead\n"); 130938689Sborman #endif 131037219Sminshall return 1; 131132144Sminshall } 131232144Sminshall 131338689Sborman #if !defined(TN3270) 131444361Sborman /*ARGSUSED*/ 131538689Sborman shell(argc, argv) 131638689Sborman int argc; 131738689Sborman char *argv[]; 131838689Sborman { 131938689Sborman extern char *rindex(); 132038689Sborman 132138689Sborman setcommandmode(); 132238689Sborman switch(vfork()) { 132338689Sborman case -1: 132438689Sborman perror("Fork failed\n"); 132538689Sborman break; 132638689Sborman 132738689Sborman case 0: 132838689Sborman { 132938689Sborman /* 133038689Sborman * Fire up the shell in the child. 133138689Sborman */ 133238689Sborman register char *shell, *shellname; 133338689Sborman 133438689Sborman shell = getenv("SHELL"); 133538689Sborman if (shell == NULL) 133638689Sborman shell = "/bin/sh"; 133738689Sborman if ((shellname = rindex(shell, '/')) == 0) 133838689Sborman shellname = shell; 133938689Sborman else 134038689Sborman shellname++; 134138689Sborman if (argc > 1) 134238689Sborman execl(shell, shellname, "-c", &saveline[1], 0); 134338689Sborman else 134438689Sborman execl(shell, shellname, 0); 134538689Sborman perror("Execl"); 134638689Sborman _exit(1); 134738689Sborman } 134838689Sborman default: 134944361Sborman (void)wait((int *)0); /* Wait for the shell to complete */ 135038689Sborman } 135138689Sborman } 135238689Sborman #endif /* !defined(TN3270) */ 135338689Sborman 135432144Sminshall /*VARARGS*/ 135532144Sminshall static 135632144Sminshall bye(argc, argv) 135732144Sminshall int argc; /* Number of arguments */ 135832144Sminshall char *argv[]; /* arguments */ 135932144Sminshall { 136032144Sminshall if (connected) { 136134849Sminshall (void) shutdown(net, 2); 136232144Sminshall printf("Connection closed.\n"); 136334849Sminshall (void) NetClose(net); 136432144Sminshall connected = 0; 136532144Sminshall /* reset options */ 136632144Sminshall tninit(); 136732144Sminshall #if defined(TN3270) 136832144Sminshall SetIn3270(); /* Get out of 3270 mode */ 136932144Sminshall #endif /* defined(TN3270) */ 137032144Sminshall } 137132144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 137232144Sminshall longjmp(toplevel, 1); 137332144Sminshall /* NOTREACHED */ 137432144Sminshall } 137532144Sminshall return 1; /* Keep lint, etc., happy */ 137632144Sminshall } 137732144Sminshall 137832144Sminshall /*VARARGS*/ 137932144Sminshall quit() 138032144Sminshall { 138132144Sminshall (void) call(bye, "bye", "fromquit", 0); 138232144Sminshall Exit(0); 138344361Sborman /*NOTREACHED*/ 138432144Sminshall } 138538689Sborman 138638689Sborman /* 138738689Sborman * The SLC command. 138838689Sborman */ 138932144Sminshall 139038689Sborman struct slclist { 139138689Sborman char *name; 139238689Sborman char *help; 139338689Sborman int (*handler)(); 139438689Sborman int arg; 139538689Sborman }; 139638689Sborman 139738689Sborman extern int slc_help(); 139838689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate(); 139938689Sborman 140038689Sborman struct slclist SlcList[] = { 140138689Sborman { "export", "Use local special character definitions", 140238689Sborman slc_mode_export, 0 }, 140338689Sborman { "import", "Use remote special character definitions", 140438689Sborman slc_mode_import, 1 }, 140538689Sborman { "check", "Verify remote special character definitions", 140638689Sborman slc_mode_import, 0 }, 140738689Sborman { "help", 0, slc_help, 0 }, 140838689Sborman { "?", "Print help information", slc_help, 0 }, 140938689Sborman { 0 }, 141038689Sborman }; 141138689Sborman 141238689Sborman static 141338689Sborman slc_help() 141438689Sborman { 141538689Sborman struct slclist *c; 141638689Sborman 141738689Sborman for (c = SlcList; c->name; c++) { 141838689Sborman if (c->help) { 141938689Sborman if (*c->help) 142038689Sborman printf("%-15s %s\n", c->name, c->help); 142138689Sborman else 142238689Sborman printf("\n"); 142338689Sborman } 142438689Sborman } 142538689Sborman } 142638689Sborman 142738689Sborman static char ** 142838689Sborman getnextslc(name) 142938689Sborman char *name; 143038689Sborman { 143138689Sborman return (char **)(((struct slclist *)name)+1); 143238689Sborman } 143338689Sborman 143438689Sborman static struct slclist * 143538689Sborman getslc(name) 143638689Sborman char *name; 143738689Sborman { 143838689Sborman return (struct slclist *)genget(name, (char **) SlcList, getnextslc); 143938689Sborman } 144038689Sborman 144138689Sborman static 144238689Sborman slccmd(argc, argv) 144338689Sborman int argc; 144438689Sborman char *argv[]; 144538689Sborman { 144638689Sborman struct slclist *c; 144738689Sborman 144838689Sborman if (argc != 2) { 144938689Sborman fprintf(stderr, 145038689Sborman "Need an argument to 'slc' command. 'slc ?' for help.\n"); 145138689Sborman return 0; 145238689Sborman } 145338689Sborman c = getslc(argv[1]); 145438689Sborman if (c == 0) { 145538689Sborman fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 145638689Sborman argv[1]); 145738689Sborman return 0; 145838689Sborman } 145938689Sborman if (Ambiguous(c)) { 146038689Sborman fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 146138689Sborman argv[1]); 146238689Sborman return 0; 146338689Sborman } 146438689Sborman (*c->handler)(c->arg); 146538689Sborman slcstate(); 146638689Sborman return 1; 146738689Sborman } 146844361Sborman 146944361Sborman /* 147044361Sborman * The ENVIRON command. 147144361Sborman */ 147238689Sborman 147344361Sborman struct envlist { 147444361Sborman char *name; 147544361Sborman char *help; 147644361Sborman int (*handler)(); 147744361Sborman int narg; 147844361Sborman }; 147944361Sborman 148044361Sborman extern struct env_lst *env_define(); 148144361Sborman extern int env_undefine(); 148244361Sborman extern int env_export(), env_unexport(); 1483*45233Sborman extern int env_send(), env_list(), env_help(); 148444361Sborman 148544361Sborman struct envlist EnvList[] = { 148644361Sborman { "define", "Define an environment variable", 148744361Sborman (int (*)())env_define, 2 }, 148844361Sborman { "undefine", "Undefine an environment variable", 148944361Sborman env_undefine, 1 }, 149044361Sborman { "export", "Mark an environment variable for automatic export", 149144361Sborman env_export, 1 }, 149244361Sborman { "unexport", "Dont mark an environment variable for automatic export", 149344361Sborman env_unexport, 1 }, 1494*45233Sborman { "send", "Send an environment variable", env_send, 1 }, 149544361Sborman { "list", "List the current environment variables", 149644361Sborman env_list, 0 }, 149744361Sborman { "help", 0, env_help, 0 }, 149844361Sborman { "?", "Print help information", env_help, 0 }, 149944361Sborman { 0 }, 150044361Sborman }; 150144361Sborman 150244361Sborman static 150344361Sborman env_help() 150444361Sborman { 150544361Sborman struct envlist *c; 150644361Sborman 150744361Sborman for (c = EnvList; c->name; c++) { 150844361Sborman if (c->help) { 150944361Sborman if (*c->help) 151044361Sborman printf("%-15s %s\n", c->name, c->help); 151144361Sborman else 151244361Sborman printf("\n"); 151344361Sborman } 151444361Sborman } 151544361Sborman } 151644361Sborman 151744361Sborman static char ** 151844361Sborman getnextenv(name) 151944361Sborman char *name; 152044361Sborman { 152144361Sborman return (char **)(((struct envlist *)name)+1); 152244361Sborman } 152344361Sborman 152444361Sborman static struct envlist * 152544361Sborman getenvcmd(name) 152644361Sborman char *name; 152744361Sborman { 152844361Sborman return (struct envlist *)genget(name, (char **) EnvList, getnextenv); 152944361Sborman } 153044361Sborman 153144361Sborman env_cmd(argc, argv) 153244361Sborman int argc; 153344361Sborman char *argv[]; 153444361Sborman { 153544361Sborman struct envlist *c; 153644361Sborman 153744361Sborman if (argc < 2) { 153844361Sborman fprintf(stderr, 153944361Sborman "Need an argument to 'environ' command. 'environ ?' for help.\n"); 154044361Sborman return 0; 154144361Sborman } 154244361Sborman c = getenvcmd(argv[1]); 154344361Sborman if (c == 0) { 154444361Sborman fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 154544361Sborman argv[1]); 154644361Sborman return 0; 154744361Sborman } 154844361Sborman if (Ambiguous(c)) { 154944361Sborman fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 155044361Sborman argv[1]); 155144361Sborman return 0; 155244361Sborman } 155344361Sborman if (c->narg + 2 != argc) { 155444361Sborman fprintf(stderr, 155544361Sborman "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 155644361Sborman c->narg < argc + 2 ? "only " : "", 155744361Sborman c->narg, c->narg == 1 ? "" : "s", c->name); 155844361Sborman return 0; 155944361Sborman } 156044361Sborman (void)(*c->handler)(argv[2], argv[3]); 156144361Sborman return 1; 156244361Sborman } 156344361Sborman 156444361Sborman struct env_lst { 156544361Sborman struct env_lst *next; /* pointer to next structure */ 156644361Sborman struct env_lst *prev; /* pointer to next structure */ 156744361Sborman char *var; /* pointer to variable name */ 156844361Sborman char *value; /* pointer to varialbe value */ 156944361Sborman int export; /* 1 -> export with default list of variables */ 157044361Sborman }; 157144361Sborman 157244361Sborman struct env_lst envlisthead; 157344361Sborman 157444361Sborman struct env_lst * 157544361Sborman env_find(var) 1576*45233Sborman char *var; 157744361Sborman { 157844361Sborman register struct env_lst *ep; 157944361Sborman 158044361Sborman for (ep = envlisthead.next; ep; ep = ep->next) { 158144361Sborman if (strcmp(ep->var, var) == 0) 158244361Sborman return(ep); 158344361Sborman } 158444361Sborman return(NULL); 158544361Sborman } 158644361Sborman 158744361Sborman env_init() 158844361Sborman { 158944361Sborman extern char **environ, *index(); 159044361Sborman register char **epp, *cp; 159144361Sborman register struct env_lst *ep; 159244361Sborman 159344361Sborman for (epp = environ; *epp; epp++) { 159444361Sborman if (cp = index(*epp, '=')) { 159544361Sborman *cp = '\0'; 159644361Sborman ep = env_define(*epp, cp+1); 159744361Sborman ep->export = 0; 159844361Sborman *cp = '='; 159944361Sborman } 160044361Sborman } 160144361Sborman /* 160244361Sborman * Special case for DISPLAY variable. If it is ":0.0" or 160344361Sborman * "unix:0.0", we have to get rid of "unix" and insert our 160444361Sborman * hostname. 160544361Sborman */ 160644361Sborman if ((ep = env_find("DISPLAY")) && 160744361Sborman ((*ep->value == ':') || (strncmp(ep->value, "unix:", 5) == 0))) { 160844361Sborman char hbuf[256+1]; 160944361Sborman char *cp2 = index(ep->value, ':'); 161044361Sborman 161144361Sborman gethostname(hbuf, 256); 161244361Sborman hbuf[256] = '\0'; 161344361Sborman cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); 161444361Sborman sprintf(cp, "%s%s", hbuf, cp2); 161544361Sborman free(ep->value); 161644361Sborman ep->value = cp; 161744361Sborman } 161844361Sborman /* 161944361Sborman * If USER is not defined, but LOGNAME is, then add 1620*45233Sborman * USER with the value from LOGNAME. By default, we 1621*45233Sborman * don't export the USER variable. 162244361Sborman */ 1623*45233Sborman if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { 162444361Sborman env_define("USER", ep->value); 1625*45233Sborman env_unexport("USER"); 1626*45233Sborman } 162744361Sborman env_export("DISPLAY"); 162844361Sborman env_export("PRINTER"); 162944361Sborman } 163044361Sborman 163144361Sborman struct env_lst * 163244361Sborman env_define(var, value) 163344361Sborman char *var, *value; 163444361Sborman { 163544361Sborman register struct env_lst *ep; 1636*45233Sborman extern char *strdup(); 163744361Sborman 163844361Sborman if (ep = env_find(var)) { 163944361Sborman if (ep->var) 164044361Sborman free(ep->var); 164144361Sborman if (ep->value) 164244361Sborman free(ep->value); 164344361Sborman } else { 164444361Sborman ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 164544361Sborman ep->next = envlisthead.next; 164644361Sborman envlisthead.next = ep; 164744361Sborman ep->prev = &envlisthead; 164844361Sborman if (ep->next) 164944361Sborman ep->next->prev = ep; 165044361Sborman } 165145009Skarels ep->export = 1; 1652*45233Sborman ep->var = strdup(var); 1653*45233Sborman ep->value = strdup(value); 165444361Sborman return(ep); 165544361Sborman } 165644361Sborman 165744361Sborman env_undefine(var) 165844361Sborman char *var; 165944361Sborman { 166044361Sborman register struct env_lst *ep; 166144361Sborman 166244361Sborman if (ep = env_find(var)) { 166344361Sborman ep->prev->next = ep->next; 1664*45233Sborman if (ep->next) 1665*45233Sborman ep->next->prev = ep->prev; 166644361Sborman if (ep->var) 166744361Sborman free(ep->var); 166844361Sborman if (ep->value) 166944361Sborman free(ep->value); 167044361Sborman free(ep); 167144361Sborman } 167244361Sborman } 167344361Sborman 167444361Sborman env_export(var) 167544361Sborman char *var; 167644361Sborman { 167744361Sborman register struct env_lst *ep; 167844361Sborman 167944361Sborman if (ep = env_find(var)) 168044361Sborman ep->export = 1; 168144361Sborman } 168244361Sborman 168344361Sborman env_unexport(var) 168444361Sborman char *var; 168544361Sborman { 168644361Sborman register struct env_lst *ep; 168744361Sborman 168844361Sborman if (ep = env_find(var)) 168944361Sborman ep->export = 0; 169044361Sborman } 169144361Sborman 1692*45233Sborman env_send(var) 1693*45233Sborman char *var; 1694*45233Sborman { 1695*45233Sborman register struct env_lst *ep; 1696*45233Sborman 1697*45233Sborman if (my_state_is_wont(TELOPT_ENVIRON)) { 1698*45233Sborman fprintf(stderr, 1699*45233Sborman "Cannot send '%s': Telnet ENVIRON option not enabled\n", 1700*45233Sborman var); 1701*45233Sborman return; 1702*45233Sborman } 1703*45233Sborman ep = env_find(var); 1704*45233Sborman if (ep == 0) { 1705*45233Sborman fprintf(stderr, "Cannot send '%s': variable not defined\n", 1706*45233Sborman var); 1707*45233Sborman return; 1708*45233Sborman } 1709*45233Sborman env_opt_start_info(); 1710*45233Sborman env_opt_add(ep->var); 1711*45233Sborman env_opt_end(0); 1712*45233Sborman } 1713*45233Sborman 171444361Sborman env_list() 171544361Sborman { 171644361Sborman register struct env_lst *ep; 171744361Sborman 171844361Sborman for (ep = envlisthead.next; ep; ep = ep->next) { 171944361Sborman printf("%c %-20s %s\n", ep->export ? '*' : ' ', 172044361Sborman ep->var, ep->value); 172144361Sborman } 172244361Sborman } 172344361Sborman 172444361Sborman char * 172544361Sborman env_default(init) 172644361Sborman { 172744361Sborman static struct env_lst *nep = NULL; 172844361Sborman 172944361Sborman if (init) { 173044361Sborman nep = &envlisthead; 173144361Sborman return; 173244361Sborman } 173344361Sborman if (nep) { 173444361Sborman while (nep = nep->next) { 173544361Sborman if (nep->export) 173644361Sborman return(nep->var); 173744361Sborman } 173844361Sborman } 173944361Sborman return(NULL); 174044361Sborman } 174144361Sborman 174244361Sborman char * 174344361Sborman env_getvalue(var) 174444361Sborman char *var; 174544361Sborman { 174644361Sborman register struct env_lst *ep; 174744361Sborman 174844361Sborman if (ep = env_find(var)) 174944361Sborman return(ep->value); 175044361Sborman return(NULL); 175144361Sborman } 175244361Sborman 1753*45233Sborman #ifdef NO_STRDUP 175444361Sborman char * 1755*45233Sborman strdup(s) 175644361Sborman register char *s; 175744361Sborman { 175844361Sborman register char *ret; 175944361Sborman if (ret = (char *)malloc(strlen(s)+1)) 176044361Sborman strcpy(ret, s); 176144361Sborman return(ret); 176244361Sborman } 1763*45233Sborman #endif 176444361Sborman 176536274Sminshall #if defined(unix) 176644361Sborman #ifdef notdef 176732144Sminshall /* 176836274Sminshall * Some information about our file descriptors. 176936274Sminshall */ 177036274Sminshall 177136274Sminshall char * 177236274Sminshall decodeflags(mask) 177336274Sminshall int mask; 177436274Sminshall { 177536274Sminshall static char buffer[100]; 177636274Sminshall #define do(m,s) \ 177736274Sminshall if (mask&(m)) { \ 177836274Sminshall strcat(buffer, (s)); \ 177936274Sminshall } 178036274Sminshall 178136274Sminshall buffer[0] = 0; /* Terminate it */ 178236274Sminshall 178336274Sminshall #ifdef FREAD 178436274Sminshall do(FREAD, " FREAD"); 178536274Sminshall #endif 178636274Sminshall #ifdef FWRITE 178736274Sminshall do(FWRITE, " FWRITE"); 178836274Sminshall #endif 178936274Sminshall #ifdef F_DUPFP 179036274Sminshall do(F_DUPFD, " F_DUPFD"); 179136274Sminshall #endif 179236274Sminshall #ifdef FNDELAY 179336274Sminshall do(FNDELAY, " FNDELAY"); 179436274Sminshall #endif 179536274Sminshall #ifdef FAPPEND 179636274Sminshall do(FAPPEND, " FAPPEND"); 179736274Sminshall #endif 179836274Sminshall #ifdef FMARK 179936274Sminshall do(FMARK, " FMARK"); 180036274Sminshall #endif 180136274Sminshall #ifdef FDEFER 180236274Sminshall do(FDEFER, " FDEFER"); 180336274Sminshall #endif 180436274Sminshall #ifdef FASYNC 180536274Sminshall do(FASYNC, " FASYNC"); 180636274Sminshall #endif 180736274Sminshall #ifdef FSHLOCK 180836274Sminshall do(FSHLOCK, " FSHLOCK"); 180936274Sminshall #endif 181036274Sminshall #ifdef FEXLOCK 181136274Sminshall do(FEXLOCK, " FEXLOCK"); 181236274Sminshall #endif 181336274Sminshall #ifdef FCREAT 181436274Sminshall do(FCREAT, " FCREAT"); 181536274Sminshall #endif 181636274Sminshall #ifdef FTRUNC 181736274Sminshall do(FTRUNC, " FTRUNC"); 181836274Sminshall #endif 181936274Sminshall #ifdef FEXCL 182036274Sminshall do(FEXCL, " FEXCL"); 182136274Sminshall #endif 182236274Sminshall 182336274Sminshall return buffer; 182436274Sminshall } 182536274Sminshall #undef do 182644361Sborman #endif /* notdef */ 182736274Sminshall 182844361Sborman #if defined(TN3270) 182936274Sminshall static void 183036274Sminshall filestuff(fd) 183136274Sminshall int fd; 183236274Sminshall { 183336274Sminshall int res; 183436274Sminshall 183538689Sborman #ifdef F_GETOWN 183638689Sborman setconnmode(0); 183736274Sminshall res = fcntl(fd, F_GETOWN, 0); 183836274Sminshall setcommandmode(); 183936274Sminshall 184036274Sminshall if (res == -1) { 184136274Sminshall perror("fcntl"); 184236274Sminshall return; 184336274Sminshall } 184436274Sminshall printf("\tOwner is %d.\n", res); 184538689Sborman #endif 184636274Sminshall 184738689Sborman setconnmode(0); 184836274Sminshall res = fcntl(fd, F_GETFL, 0); 184936274Sminshall setcommandmode(); 185036274Sminshall 185136274Sminshall if (res == -1) { 185236274Sminshall perror("fcntl"); 185336274Sminshall return; 185436274Sminshall } 185536274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 185636274Sminshall } 185744361Sborman #endif /* defined(TN3270) */ 185836274Sminshall 185936274Sminshall 186036274Sminshall #endif /* defined(unix) */ 186136274Sminshall 186236274Sminshall /* 186332144Sminshall * Print status about the connection. 186432144Sminshall */ 186534849Sminshall /*ARGSUSED*/ 186632144Sminshall static 186732144Sminshall status(argc, argv) 186832144Sminshall int argc; 186932144Sminshall char *argv[]; 187032144Sminshall { 187132144Sminshall if (connected) { 187232144Sminshall printf("Connected to %s.\n", hostname); 187336242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 187438689Sborman int mode = getconnmode(); 187538689Sborman 187638689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 187738689Sborman printf("Operating with LINEMODE option\n"); 187838689Sborman printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 187938689Sborman printf("%s catching of signals\n", 188038689Sborman (mode&MODE_TRAPSIG) ? "Local" : "No"); 188138689Sborman slcstate(); 188238689Sborman #ifdef KLUDGELINEMODE 188339529Sborman } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 188438689Sborman printf("Operating in obsolete linemode\n"); 188538689Sborman #endif 188638689Sborman } else { 188738689Sborman printf("Operating in single character mode\n"); 188838689Sborman if (localchars) 188938689Sborman printf("Catching signals locally\n"); 189032144Sminshall } 189138689Sborman printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 189238689Sborman if (my_want_state_is_will(TELOPT_LFLOW)) 189338689Sborman printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 189432144Sminshall } 189532144Sminshall } else { 189632144Sminshall printf("No connection.\n"); 189732144Sminshall } 189832144Sminshall # if !defined(TN3270) 189932144Sminshall printf("Escape character is '%s'.\n", control(escape)); 190034849Sminshall (void) fflush(stdout); 190132144Sminshall # else /* !defined(TN3270) */ 190232144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 190332144Sminshall printf("Escape character is '%s'.\n", control(escape)); 190432144Sminshall } 190532144Sminshall # if defined(unix) 190636242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 190736242Sminshall printf("SIGIO received %d time%s.\n", 190836242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 190936274Sminshall if (In3270) { 191036274Sminshall printf("Process ID %d, process group %d.\n", 191136274Sminshall getpid(), getpgrp(getpid())); 191236274Sminshall printf("Terminal input:\n"); 191336274Sminshall filestuff(tin); 191436274Sminshall printf("Terminal output:\n"); 191536274Sminshall filestuff(tout); 191636274Sminshall printf("Network socket:\n"); 191736274Sminshall filestuff(net); 191836274Sminshall } 191936242Sminshall } 192032144Sminshall if (In3270 && transcom) { 192132144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 192232144Sminshall } 192332144Sminshall # endif /* defined(unix) */ 192434849Sminshall (void) fflush(stdout); 192532144Sminshall if (In3270) { 192632144Sminshall return 0; 192732144Sminshall } 192832144Sminshall # endif /* defined(TN3270) */ 192932144Sminshall return 1; 193032144Sminshall } 193132144Sminshall 1932*45233Sborman #ifdef SIGINFO 1933*45233Sborman /* 1934*45233Sborman * Function that gets called when SIGINFO is received. 1935*45233Sborman */ 1936*45233Sborman ayt_status() 1937*45233Sborman { 1938*45233Sborman (void) call(status, "status", "notmuch", 0); 1939*45233Sborman } 1940*45233Sborman #endif 194132144Sminshall 194244361Sborman #if defined(NEED_GETTOS) 194344361Sborman struct tosent { 194444361Sborman char *t_name; /* name */ 194544361Sborman char **t_aliases; /* alias list */ 194644361Sborman char *t_proto; /* protocol */ 194744361Sborman int t_tos; /* Type Of Service bits */ 194844361Sborman }; 194944361Sborman 195044361Sborman struct tosent * 195144361Sborman gettosbyname(name, proto) 195244361Sborman char *name, *proto; 195344361Sborman { 195444361Sborman static struct tosent te; 195544361Sborman static char *aliasp = 0; 195644361Sborman 195744361Sborman te.t_name = name; 195844361Sborman te.t_aliases = &aliasp; 195944361Sborman te.t_proto = proto; 196044361Sborman te.t_tos = 020; /* Low Delay bit */ 196144361Sborman return(&te); 196244361Sborman } 196344361Sborman #endif 196444361Sborman 196545008Skarels extern int autologin; 196645008Skarels 196732144Sminshall int 196832144Sminshall tn(argc, argv) 196932144Sminshall int argc; 197032144Sminshall char *argv[]; 197132144Sminshall { 197232144Sminshall register struct hostent *host = 0; 197332144Sminshall struct sockaddr_in sin; 197432144Sminshall struct servent *sp = 0; 197532144Sminshall static char hnamebuf[32]; 197638689Sborman unsigned long temp, inet_addr(); 197737219Sminshall extern char *inet_ntoa(); 197838689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 197938689Sborman char *srp = 0, *strrchr(); 198038689Sborman unsigned long sourceroute(), srlen; 198138689Sborman #endif 198244361Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS) 198340245Sborman struct tosent *tp; 198444361Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */ 198544361Sborman char *cmd, *hostp = 0, *portp = 0, *user = 0; 198632144Sminshall 1987*45233Sborman /* clear the socket address prior to use */ 1988*45233Sborman bzero((char *)&sin, sizeof(sin)); 198932144Sminshall 199032144Sminshall if (connected) { 199132144Sminshall printf("?Already connected to %s\n", hostname); 199232144Sminshall return 0; 199332144Sminshall } 199432144Sminshall if (argc < 2) { 199532144Sminshall (void) strcpy(line, "Connect "); 199632144Sminshall printf("(to) "); 199734849Sminshall (void) gets(&line[strlen(line)]); 199832144Sminshall makeargv(); 199932144Sminshall argc = margc; 200032144Sminshall argv = margv; 200132144Sminshall } 200244361Sborman cmd = *argv; 200344361Sborman --argc; ++argv; 200444361Sborman while (argc) { 200544361Sborman if (strcmp(*argv, "-l") == 0) { 200644361Sborman --argc; ++argv; 200744361Sborman if (argc == 0) 200844361Sborman goto usage; 200944361Sborman user = *argv++; 201044361Sborman --argc; 201144361Sborman continue; 201244361Sborman } 2013*45233Sborman if (strcmp(*argv, "-a") == 0) { 2014*45233Sborman --argc; ++argv; 2015*45233Sborman autologin = 1; 2016*45233Sborman continue; 2017*45233Sborman } 201844361Sborman if (hostp == 0) { 201944361Sborman hostp = *argv++; 202044361Sborman --argc; 202144361Sborman continue; 202244361Sborman } 202344361Sborman if (portp == 0) { 202444361Sborman portp = *argv++; 202544361Sborman --argc; 202644361Sborman continue; 202744361Sborman } 202844361Sborman usage: 2029*45233Sborman printf("usage: %s [-l user] [-a] host-name [port]\n", cmd); 203032144Sminshall return 0; 203132144Sminshall } 203238689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 203344361Sborman if (hostp[0] == '@' || hostp[0] == '!') { 203444361Sborman if ((hostname = strrchr(hostp, ':')) == NULL) 203544361Sborman hostname = strrchr(hostp, '@'); 203638689Sborman hostname++; 203738689Sborman srp = 0; 203844361Sborman temp = sourceroute(hostp, &srp, &srlen); 203938689Sborman if (temp == 0) { 204038689Sborman herror(srp); 204138689Sborman return 0; 204238689Sborman } else if (temp == -1) { 204344361Sborman printf("Bad source route option: %s\n", hostp); 204438689Sborman return 0; 204538689Sborman } else { 204638689Sborman sin.sin_addr.s_addr = temp; 204738689Sborman sin.sin_family = AF_INET; 204838689Sborman } 204932144Sminshall } else { 205038689Sborman #endif 205144361Sborman temp = inet_addr(hostp); 205238689Sborman if (temp != (unsigned long) -1) { 205338689Sborman sin.sin_addr.s_addr = temp; 205438689Sborman sin.sin_family = AF_INET; 205544361Sborman (void) strcpy(hnamebuf, hostp); 205638689Sborman hostname = hnamebuf; 205738689Sborman } else { 205844361Sborman host = gethostbyname(hostp); 205938689Sborman if (host) { 206038689Sborman sin.sin_family = host->h_addrtype; 206132144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 206238689Sborman memcpy((caddr_t)&sin.sin_addr, 206332144Sminshall host->h_addr_list[0], host->h_length); 206432144Sminshall #else /* defined(h_addr) */ 206538689Sborman memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 206632144Sminshall #endif /* defined(h_addr) */ 206738689Sborman hostname = host->h_name; 206838689Sborman } else { 206944361Sborman herror(hostp); 207038689Sborman return 0; 207138689Sborman } 207232144Sminshall } 207338689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 207432144Sminshall } 207538689Sborman #endif 207644361Sborman if (portp) { 207744361Sborman if (*portp == '-') { 207844361Sborman portp++; 207938689Sborman telnetport = 1; 208038689Sborman } else 208138689Sborman telnetport = 0; 208244361Sborman sin.sin_port = atoi(portp); 208332144Sminshall if (sin.sin_port == 0) { 208444361Sborman sp = getservbyname(portp, "tcp"); 208532144Sminshall if (sp) 208632144Sminshall sin.sin_port = sp->s_port; 208732144Sminshall else { 208844361Sborman printf("%s: bad port number\n", portp); 208932144Sminshall return 0; 209032144Sminshall } 209132144Sminshall } else { 209234849Sminshall #if !defined(htons) 209334849Sminshall u_short htons(); 209434849Sminshall #endif /* !defined(htons) */ 209532144Sminshall sin.sin_port = htons(sin.sin_port); 209632144Sminshall } 209732144Sminshall } else { 209832144Sminshall if (sp == 0) { 209932144Sminshall sp = getservbyname("telnet", "tcp"); 210032144Sminshall if (sp == 0) { 210134849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 210232144Sminshall return 0; 210332144Sminshall } 210432144Sminshall sin.sin_port = sp->s_port; 210532144Sminshall } 210632144Sminshall telnetport = 1; 210732144Sminshall } 210837219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 210932144Sminshall do { 211032144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 211132144Sminshall if (net < 0) { 211232144Sminshall perror("telnet: socket"); 211332144Sminshall return 0; 211432144Sminshall } 211538689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 211638689Sborman if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) 211738689Sborman perror("setsockopt (IP_OPTIONS)"); 211838689Sborman #endif 211944361Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS) 212044361Sborman if ((tp = gettosbyname("telnet", "tcp")) && 212144361Sborman (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0)) 212240245Sborman perror("telnet: setsockopt TOS (ignored)"); 212344361Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */ 212440245Sborman 212532144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 212632144Sminshall perror("setsockopt (SO_DEBUG)"); 212732144Sminshall } 212832144Sminshall 212932144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 213032144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 213132144Sminshall if (host && host->h_addr_list[1]) { 213232144Sminshall int oerrno = errno; 213332144Sminshall 213432144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 213532144Sminshall inet_ntoa(sin.sin_addr)); 213632144Sminshall errno = oerrno; 213732144Sminshall perror((char *)0); 213832144Sminshall host->h_addr_list++; 213932144Sminshall memcpy((caddr_t)&sin.sin_addr, 214032144Sminshall host->h_addr_list[0], host->h_length); 214132144Sminshall (void) NetClose(net); 214232144Sminshall continue; 214332144Sminshall } 214432144Sminshall #endif /* defined(h_addr) */ 214532144Sminshall perror("telnet: Unable to connect to remote host"); 214632144Sminshall return 0; 214737219Sminshall } 214832144Sminshall connected++; 214932144Sminshall } while (connected == 0); 215044361Sborman cmdrc(hostp, hostname); 215145008Skarels if (autologin && user == NULL) { 215245008Skarels struct passwd *pw; 215345008Skarels 2154*45233Sborman user = getenv("USER"); 215545008Skarels if (user == NULL || 2156*45233Sborman (pw = getpwnam(user)) && pw->pw_uid != getuid()) { 2157*45233Sborman if (pw = getpwuid(getuid())) 215845008Skarels user = pw->pw_name; 215945008Skarels else 216045008Skarels user = NULL; 2161*45233Sborman } 216245008Skarels } 216345008Skarels if (user) { 216444361Sborman env_define("USER", user); 216545008Skarels env_export("USER"); 216645008Skarels } 216734849Sminshall (void) call(status, "status", "notmuch", 0); 216832144Sminshall if (setjmp(peerdied) == 0) 216932144Sminshall telnet(); 217034849Sminshall (void) NetClose(net); 217132381Sminshall ExitString("Connection closed by foreign host.\n",1); 217232144Sminshall /*NOTREACHED*/ 217332144Sminshall } 217432144Sminshall 217532144Sminshall 217632144Sminshall #define HELPINDENT (sizeof ("connect")) 217732144Sminshall 217832144Sminshall static char 217932144Sminshall openhelp[] = "connect to a site", 218032144Sminshall closehelp[] = "close current connection", 218132144Sminshall quithelp[] = "exit telnet", 218232144Sminshall statushelp[] = "print status information", 218332144Sminshall helphelp[] = "print help information", 218432144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 218532144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 218638689Sborman unsethelp[] = "unset operating parameters ('unset ?' for more)", 218732144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 218838689Sborman slchelp[] = "change state of special charaters ('slc ?' for more)", 218932144Sminshall displayhelp[] = "display operating parameters", 219032144Sminshall #if defined(TN3270) && defined(unix) 219132144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 219232144Sminshall #endif /* defined(TN3270) && defined(unix) */ 219332144Sminshall #if defined(unix) 219432144Sminshall zhelp[] = "suspend telnet", 219543317Skfall #endif /* defined(unix) */ 219632144Sminshall shellhelp[] = "invoke a subshell", 219744361Sborman envhelp[] = "change environment variables ('environ ?' for more)", 219844361Sborman modestring[] = "try to enter line or character mode ('mode ?' for more)"; 219932144Sminshall 220032144Sminshall extern int help(), shell(); 220132144Sminshall 220232144Sminshall static Command cmdtab[] = { 220338689Sborman { "close", closehelp, bye, 1 }, 220438689Sborman { "display", displayhelp, display, 0 }, 220538689Sborman { "mode", modestring, modecmd, 0 }, 220638689Sborman { "open", openhelp, tn, 0 }, 220738689Sborman { "quit", quithelp, quit, 0 }, 220838689Sborman { "send", sendhelp, sendcmd, 0 }, 220938689Sborman { "set", sethelp, setcmd, 0 }, 221038689Sborman { "unset", unsethelp, unsetcmd, 0 }, 221138689Sborman { "status", statushelp, status, 0 }, 221238689Sborman { "toggle", togglestring, toggle, 0 }, 221338689Sborman { "slc", slchelp, slccmd, 0 }, 221432144Sminshall #if defined(TN3270) && defined(unix) 221538689Sborman { "transcom", transcomhelp, settranscom, 0 }, 221632144Sminshall #endif /* defined(TN3270) && defined(unix) */ 221732144Sminshall #if defined(unix) 221838689Sborman { "z", zhelp, suspend, 0 }, 221932144Sminshall #endif /* defined(unix) */ 222032144Sminshall #if defined(TN3270) 222138689Sborman { "!", shellhelp, shell, 1 }, 222238689Sborman #else 222338689Sborman { "!", shellhelp, shell, 0 }, 222438689Sborman #endif 222544361Sborman { "environ", envhelp, env_cmd, 0 }, 222638689Sborman { "?", helphelp, help, 0 }, 222732144Sminshall 0 222832144Sminshall }; 222932144Sminshall 223032144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 223132144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 223232144Sminshall 223332144Sminshall static Command cmdtab2[] = { 223438689Sborman { "help", 0, help, 0 }, 223538689Sborman { "escape", escapehelp, setescape, 0 }, 223638689Sborman { "crmod", crmodhelp, togcrmod, 0 }, 223732144Sminshall 0 223832144Sminshall }; 223932144Sminshall 224035298Sminshall 224132144Sminshall /* 224232144Sminshall * Call routine with argc, argv set from args (terminated by 0). 224332144Sminshall */ 224435298Sminshall 224535417Sminshall /*VARARGS1*/ 224632144Sminshall static 224735298Sminshall call(va_alist) 224835298Sminshall va_dcl 224932144Sminshall { 225035298Sminshall va_list ap; 225135298Sminshall typedef int (*intrtn_t)(); 225235298Sminshall intrtn_t routine; 225335298Sminshall char *args[100]; 225435298Sminshall int argno = 0; 225535298Sminshall 225635298Sminshall va_start(ap); 225735298Sminshall routine = (va_arg(ap, intrtn_t)); 225835495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 225935298Sminshall ; 226035495Sminshall } 226135298Sminshall va_end(ap); 226235495Sminshall return (*routine)(argno-1, args); 226332144Sminshall } 226432144Sminshall 226535298Sminshall 226632144Sminshall static char ** 226732144Sminshall getnextcmd(name) 226832144Sminshall char *name; 226932144Sminshall { 227032144Sminshall Command *c = (Command *) name; 227132144Sminshall 227232144Sminshall return (char **) (c+1); 227332144Sminshall } 227432144Sminshall 227532144Sminshall static Command * 227632144Sminshall getcmd(name) 227732144Sminshall char *name; 227832144Sminshall { 227932144Sminshall Command *cm; 228032144Sminshall 228132144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 228232144Sminshall return cm; 228332144Sminshall } else { 228432144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 228532144Sminshall } 228632144Sminshall } 228732144Sminshall 228832144Sminshall void 228938689Sborman command(top, tbuf, cnt) 229032144Sminshall int top; 229138689Sborman char *tbuf; 229238689Sborman int cnt; 229332144Sminshall { 229432144Sminshall register Command *c; 229532144Sminshall 229632144Sminshall setcommandmode(); 229732144Sminshall if (!top) { 229832144Sminshall putchar('\n'); 229937219Sminshall #if defined(unix) 230032144Sminshall } else { 230144361Sborman (void) signal(SIGINT, SIG_DFL); 230244361Sborman (void) signal(SIGQUIT, SIG_DFL); 230332144Sminshall #endif /* defined(unix) */ 230432144Sminshall } 230532144Sminshall for (;;) { 230632144Sminshall printf("%s> ", prompt); 230738689Sborman if (tbuf) { 230838689Sborman register char *cp; 230938689Sborman cp = line; 231038689Sborman while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 231138689Sborman cnt--; 231238689Sborman tbuf = 0; 231338689Sborman if (cp == line || *--cp != '\n' || cp == line) 231438689Sborman goto getline; 231538689Sborman *cp = '\0'; 231638689Sborman printf("%s\n", line); 231738689Sborman } else { 231838689Sborman getline: 231938689Sborman if (gets(line) == NULL) { 232044361Sborman if (feof(stdin) || ferror(stdin)) { 232144361Sborman (void) quit(); 232244361Sborman /*NOTREACHED*/ 232344361Sborman } 232438689Sborman break; 232538689Sborman } 232632144Sminshall } 232732144Sminshall if (line[0] == 0) 232832144Sminshall break; 232932144Sminshall makeargv(); 233037219Sminshall if (margv[0] == 0) { 233137219Sminshall break; 233237219Sminshall } 233332144Sminshall c = getcmd(margv[0]); 233432144Sminshall if (Ambiguous(c)) { 233532144Sminshall printf("?Ambiguous command\n"); 233632144Sminshall continue; 233732144Sminshall } 233832144Sminshall if (c == 0) { 233932144Sminshall printf("?Invalid command\n"); 234032144Sminshall continue; 234132144Sminshall } 234232144Sminshall if (c->needconnect && !connected) { 234332144Sminshall printf("?Need to be connected first.\n"); 234432144Sminshall continue; 234532144Sminshall } 234632144Sminshall if ((*c->handler)(margc, margv)) { 234732144Sminshall break; 234832144Sminshall } 234932144Sminshall } 235032144Sminshall if (!top) { 235132144Sminshall if (!connected) { 235232144Sminshall longjmp(toplevel, 1); 235332144Sminshall /*NOTREACHED*/ 235432144Sminshall } 235532144Sminshall #if defined(TN3270) 235632144Sminshall if (shell_active == 0) { 235738689Sborman setconnmode(0); 235832144Sminshall } 235932144Sminshall #else /* defined(TN3270) */ 236038689Sborman setconnmode(0); 236132144Sminshall #endif /* defined(TN3270) */ 236232144Sminshall } 236332144Sminshall } 236432144Sminshall 236532144Sminshall /* 236632144Sminshall * Help command. 236732144Sminshall */ 236832144Sminshall static 236932144Sminshall help(argc, argv) 237032144Sminshall int argc; 237132144Sminshall char *argv[]; 237232144Sminshall { 237332144Sminshall register Command *c; 237432144Sminshall 237532144Sminshall if (argc == 1) { 237632144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 237732144Sminshall for (c = cmdtab; c->name; c++) 237838689Sborman if (c->help) { 237932144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 238032144Sminshall c->help); 238132144Sminshall } 238232144Sminshall return 0; 238332144Sminshall } 238432144Sminshall while (--argc > 0) { 238532144Sminshall register char *arg; 238632144Sminshall arg = *++argv; 238732144Sminshall c = getcmd(arg); 238832144Sminshall if (Ambiguous(c)) 238932144Sminshall printf("?Ambiguous help command %s\n", arg); 239032144Sminshall else if (c == (Command *)0) 239132144Sminshall printf("?Invalid help command %s\n", arg); 239232144Sminshall else 239332144Sminshall printf("%s\n", c->help); 239432144Sminshall } 239532144Sminshall return 0; 239632144Sminshall } 239738689Sborman 239838689Sborman static char *rcname = 0; 239938689Sborman static char rcbuf[128]; 240038689Sborman 240138689Sborman cmdrc(m1, m2) 240238689Sborman char *m1, *m2; 240338689Sborman { 240438689Sborman register Command *c; 240538689Sborman FILE *rcfile; 240638689Sborman int gotmachine = 0; 240738689Sborman int l1 = strlen(m1); 240838689Sborman int l2 = strlen(m2); 240938689Sborman char m1save[64]; 241038689Sborman 241138689Sborman strcpy(m1save, m1); 241238689Sborman m1 = m1save; 241338689Sborman 241438689Sborman if (rcname == 0) { 241538689Sborman rcname = getenv("HOME"); 241638689Sborman if (rcname) 241738689Sborman strcpy(rcbuf, rcname); 241838689Sborman else 241938689Sborman rcbuf[0] = '\0'; 242038689Sborman strcat(rcbuf, "/.telnetrc"); 242138689Sborman rcname = rcbuf; 242238689Sborman } 242338689Sborman 242438689Sborman if ((rcfile = fopen(rcname, "r")) == 0) { 242538689Sborman return; 242638689Sborman } 242738689Sborman 242838689Sborman for (;;) { 242938689Sborman if (fgets(line, sizeof(line), rcfile) == NULL) 243038689Sborman break; 243138689Sborman if (line[0] == 0) 243238689Sborman break; 243338689Sborman if (line[0] == '#') 243438689Sborman continue; 243538689Sborman if (gotmachine == 0) { 243638689Sborman if (isspace(line[0])) 243738689Sborman continue; 243838689Sborman if (strncasecmp(line, m1, l1) == 0) 243938689Sborman strncpy(line, &line[l1], sizeof(line) - l1); 244038689Sborman else if (strncasecmp(line, m2, l2) == 0) 244138689Sborman strncpy(line, &line[l2], sizeof(line) - l2); 244238689Sborman else 244338689Sborman continue; 244438689Sborman gotmachine = 1; 244538689Sborman } else { 244638689Sborman if (!isspace(line[0])) { 244738689Sborman gotmachine = 0; 244838689Sborman continue; 244938689Sborman } 245038689Sborman } 245138689Sborman makeargv(); 245238689Sborman if (margv[0] == 0) 245338689Sborman continue; 245438689Sborman c = getcmd(margv[0]); 245538689Sborman if (Ambiguous(c)) { 245638689Sborman printf("?Ambiguous command: %s\n", margv[0]); 245738689Sborman continue; 245838689Sborman } 245938689Sborman if (c == 0) { 246038689Sborman printf("?Invalid command: %s\n", margv[0]); 246138689Sborman continue; 246238689Sborman } 246338689Sborman /* 246438689Sborman * This should never happen... 246538689Sborman */ 246638689Sborman if (c->needconnect && !connected) { 246738689Sborman printf("?Need to be connected first for %s.\n", margv[0]); 246838689Sborman continue; 246938689Sborman } 247038689Sborman (*c->handler)(margc, margv); 247138689Sborman } 247238689Sborman fclose(rcfile); 247338689Sborman } 247438689Sborman 247538689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 247638689Sborman 247738689Sborman /* 247838689Sborman * Source route is handed in as 247938689Sborman * [!]@hop1@hop2...[@|:]dst 248038689Sborman * If the leading ! is present, it is a 248138689Sborman * strict source route, otherwise it is 248238689Sborman * assmed to be a loose source route. 248338689Sborman * 248438689Sborman * We fill in the source route option as 248538689Sborman * hop1,hop2,hop3...dest 248638689Sborman * and return a pointer to hop1, which will 248738689Sborman * be the address to connect() to. 248838689Sborman * 248938689Sborman * Arguments: 249038689Sborman * arg: pointer to route list to decipher 249138689Sborman * 249238689Sborman * cpp: If *cpp is not equal to NULL, this is a 249338689Sborman * pointer to a pointer to a character array 249438689Sborman * that should be filled in with the option. 249538689Sborman * 249638689Sborman * lenp: pointer to an integer that contains the 249738689Sborman * length of *cpp if *cpp != NULL. 249838689Sborman * 249938689Sborman * Return values: 250038689Sborman * 250138689Sborman * Returns the address of the host to connect to. If the 250238689Sborman * return value is -1, there was a syntax error in the 250338689Sborman * option, either unknown characters, or too many hosts. 250438689Sborman * If the return value is 0, one of the hostnames in the 250538689Sborman * path is unknown, and *cpp is set to point to the bad 250638689Sborman * hostname. 250738689Sborman * 250838689Sborman * *cpp: If *cpp was equal to NULL, it will be filled 250938689Sborman * in with a pointer to our static area that has 251038689Sborman * the option filled in. This will be 32bit aligned. 251138689Sborman * 251238689Sborman * *lenp: This will be filled in with how long the option 251338689Sborman * pointed to by *cpp is. 251438689Sborman * 251538689Sborman */ 251638689Sborman unsigned long 251738689Sborman sourceroute(arg, cpp, lenp) 251838689Sborman char *arg; 251938689Sborman char **cpp; 252038689Sborman int *lenp; 252138689Sborman { 252238689Sborman static char lsr[44]; 252338689Sborman char *cp, *cp2, *lsrp, *lsrep, *index(); 252438689Sborman register int tmp; 252538689Sborman struct in_addr sin_addr; 252638689Sborman register struct hostent *host = 0; 252738689Sborman register char c; 252838689Sborman 252938689Sborman /* 253038689Sborman * Verify the arguments, and make sure we have 253138689Sborman * at least 7 bytes for the option. 253238689Sborman */ 253338689Sborman if (cpp == NULL || lenp == NULL) 253438689Sborman return((unsigned long)-1); 253538689Sborman if (*cpp != NULL && *lenp < 7) 253638689Sborman return((unsigned long)-1); 253738689Sborman /* 253838689Sborman * Decide whether we have a buffer passed to us, 253938689Sborman * or if we need to use our own static buffer. 254038689Sborman */ 254138689Sborman if (*cpp) { 254238689Sborman lsrp = *cpp; 254338689Sborman lsrep = lsrp + *lenp; 254438689Sborman } else { 254538689Sborman *cpp = lsrp = lsr; 254638689Sborman lsrep = lsrp + 44; 254738689Sborman } 254838689Sborman 254938689Sborman cp = arg; 255038689Sborman 255138689Sborman /* 255238689Sborman * Next, decide whether we have a loose source 255338689Sborman * route or a strict source route, and fill in 255438689Sborman * the begining of the option. 255538689Sborman */ 255638689Sborman if (*cp == '!') { 255738689Sborman cp++; 255838689Sborman *lsrp++ = IPOPT_SSRR; 255938689Sborman } else 256038689Sborman *lsrp++ = IPOPT_LSRR; 256138689Sborman 256238689Sborman if (*cp != '@') 256338689Sborman return((unsigned long)-1); 256438689Sborman 256538689Sborman lsrp++; /* skip over length, we'll fill it in later */ 256638689Sborman *lsrp++ = 4; 256738689Sborman 256838689Sborman cp++; 256938689Sborman 257038689Sborman sin_addr.s_addr = 0; 257138689Sborman 257238689Sborman for (c = 0;;) { 257338689Sborman if (c == ':') 257438689Sborman cp2 = 0; 257538689Sborman else for (cp2 = cp; c = *cp2; cp2++) { 257638689Sborman if (c == ',') { 257738689Sborman *cp2++ = '\0'; 257838689Sborman if (*cp2 == '@') 257938689Sborman cp2++; 258038689Sborman } else if (c == '@') { 258138689Sborman *cp2++ = '\0'; 258238689Sborman } else if (c == ':') { 258338689Sborman *cp2++ = '\0'; 258438689Sborman } else 258538689Sborman continue; 258638689Sborman break; 258738689Sborman } 258838689Sborman if (!c) 258938689Sborman cp2 = 0; 259038689Sborman 259138689Sborman if ((tmp = inet_addr(cp)) != -1) { 259238689Sborman sin_addr.s_addr = tmp; 259338689Sborman } else if (host = gethostbyname(cp)) { 259438689Sborman #if defined(h_addr) 259538689Sborman memcpy((caddr_t)&sin_addr, 259638689Sborman host->h_addr_list[0], host->h_length); 259738689Sborman #else 259838689Sborman memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); 259938689Sborman #endif 260038689Sborman } else { 260138689Sborman *cpp = cp; 260238689Sborman return(0); 260338689Sborman } 260438689Sborman memcpy(lsrp, (char *)&sin_addr, 4); 260538689Sborman lsrp += 4; 260638689Sborman if (cp2) 260738689Sborman cp = cp2; 260838689Sborman else 260938689Sborman break; 261038689Sborman /* 261138689Sborman * Check to make sure there is space for next address 261238689Sborman */ 261338689Sborman if (lsrp + 4 > lsrep) 261438689Sborman return((unsigned long)-1); 261538689Sborman } 261638689Sborman if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 261738689Sborman *cpp = 0; 261838689Sborman *lenp = 0; 261938689Sborman return((unsigned long)-1); 262038689Sborman } 262138689Sborman *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 262238689Sborman *lenp = lsrp - *cpp; 262338689Sborman return(sin_addr.s_addr); 262438689Sborman } 262538689Sborman #endif 262638689Sborman 262738909Sborman #if defined(NOSTRNCASECMP) 262838689Sborman strncasecmp(p1, p2, len) 262938689Sborman register char *p1, *p2; 263038689Sborman int len; 263138689Sborman { 263238689Sborman while (len--) { 263338689Sborman if (tolower(*p1) != tolower(*p2)) 263438689Sborman return(tolower(*p1) - tolower(*p2)); 263538689Sborman if (*p1 == '\0') 263638689Sborman return(0); 263738689Sborman p1++, p2++; 263838689Sborman } 263938689Sborman return(0); 264038689Sborman } 264138689Sborman #endif 2642