133685Sbostic /* 233685Sbostic * Copyright (c) 1988 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 542770Sbostic * %sccs.include.redist.c% 633685Sbostic */ 733685Sbostic 833685Sbostic #ifndef lint 9*44361Sborman static char sccsid[] = "@(#)commands.c 1.30 (Berkeley) 06/28/90"; 1033685Sbostic #endif /* not lint */ 1133685Sbostic 12*44361Sborman #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> 2535298Sminshall #include <varargs.h> 2632144Sminshall 2732144Sminshall #include <arpa/telnet.h> 2832144Sminshall 2934305Sminshall #include "general.h" 3034305Sminshall 3132381Sminshall #include "ring.h" 3232381Sminshall 3332144Sminshall #include "externs.h" 3432144Sminshall #include "defines.h" 3532144Sminshall #include "types.h" 3632144Sminshall 37*44361Sborman #ifdef SRCRT 38*44361Sborman # ifndef CRAY 39*44361Sborman # include <netinet/in_systm.h> 40*44361Sborman # if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) 41*44361Sborman # include <machine/endian.h> 42*44361Sborman # endif /* vax */ 43*44361Sborman # endif /* CRAY */ 44*44361Sborman #include <netinet/ip.h> 45*44361Sborman #endif /* SRCRT */ 4638689Sborman 4740248Sborman #if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS) 48*44361Sborman # define HAS_IP_TOS 4940248Sborman #endif 5038689Sborman 5140248Sborman 5232144Sminshall char *hostname; 5338689Sborman extern char *getenv(); 5432144Sminshall 5536180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 5632144Sminshall static char *ambiguous; /* special return value for command routines */ 57*44361Sborman static call(); 5832144Sminshall 5932144Sminshall typedef struct { 6032144Sminshall char *name; /* command name */ 6138689Sborman char *help; /* help string (NULL for no help) */ 6232144Sminshall int (*handler)(); /* routine which executes command */ 6332144Sminshall int needconnect; /* Do we need to be connected to execute? */ 6432144Sminshall } Command; 6532144Sminshall 6638689Sborman static char line[256]; 6738689Sborman static char saveline[256]; 6832144Sminshall static int margc; 6932144Sminshall static char *margv[20]; 7032144Sminshall 7132144Sminshall /* 7232144Sminshall * Various utility routines. 7332144Sminshall */ 7432144Sminshall 7536180Sminshall #if !defined(BSD) || (BSD <= 43) 7636180Sminshall 7736180Sminshall char *h_errlist[] = { 7836180Sminshall "Error 0", 7936180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 8036180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 8136180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 8236180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 8336180Sminshall }; 8436180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 8536180Sminshall 8636274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 8736180Sminshall 8836180Sminshall /* 8936180Sminshall * herror -- 9036180Sminshall * print the error indicated by the h_errno value. 9136180Sminshall */ 9236180Sminshall herror(s) 9336180Sminshall char *s; 9436180Sminshall { 9536180Sminshall if (s && *s) { 9636180Sminshall fprintf(stderr, "%s: ", s); 9736180Sminshall } 9836180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 9936180Sminshall fprintf(stderr, "Unknown error\n"); 10036274Sminshall } else if (h_errno == 0) { 10136274Sminshall #if defined(sun) 10236274Sminshall fprintf(stderr, "Host unknown\n"); 10336274Sminshall #endif /* defined(sun) */ 10436180Sminshall } else { 10536180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 10636180Sminshall } 10736180Sminshall } 10836180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 10936180Sminshall 11032144Sminshall static void 11132144Sminshall makeargv() 11232144Sminshall { 113*44361Sborman register char *cp, *cp2, c; 11432144Sminshall register char **argp = margv; 11532144Sminshall 11632144Sminshall margc = 0; 11732144Sminshall cp = line; 11832144Sminshall if (*cp == '!') { /* Special case shell escape */ 11938689Sborman strcpy(saveline, line); /* save for shell command */ 12032144Sminshall *argp++ = "!"; /* No room in string to get this */ 12132144Sminshall margc++; 12232144Sminshall cp++; 12332144Sminshall } 124*44361Sborman while (c = *cp) { 125*44361Sborman register int inquote = 0; 126*44361Sborman while (isspace(c)) 127*44361Sborman c = *++cp; 128*44361Sborman if (c == '\0') 12932144Sminshall break; 13032144Sminshall *argp++ = cp; 13132144Sminshall margc += 1; 132*44361Sborman for (cp2 = cp; c != '\0'; c = *++cp) { 133*44361Sborman if (inquote) { 134*44361Sborman if (c == inquote) { 135*44361Sborman inquote = 0; 136*44361Sborman continue; 137*44361Sborman } 138*44361Sborman } else { 139*44361Sborman if (c == '\\') { 140*44361Sborman if ((c = *++cp) == '\0') 141*44361Sborman break; 142*44361Sborman } else if (c == '"') { 143*44361Sborman inquote = '"'; 144*44361Sborman continue; 145*44361Sborman } else if (c == '\'') { 146*44361Sborman inquote = '\''; 147*44361Sborman continue; 148*44361Sborman } else if (isspace(c)) 149*44361Sborman break; 150*44361Sborman } 151*44361Sborman *cp2++ = c; 152*44361Sborman } 153*44361Sborman *cp2 = '\0'; 154*44361Sborman if (c == '\0') 15532144Sminshall break; 156*44361Sborman cp++; 15732144Sminshall } 15832144Sminshall *argp++ = 0; 15932144Sminshall } 16032144Sminshall 16132144Sminshall 16232144Sminshall static char ** 16332144Sminshall genget(name, table, next) 16432144Sminshall char *name; /* name to match */ 16532144Sminshall char **table; /* name entry in table */ 16632144Sminshall char **(*next)(); /* routine to return next entry in table */ 16732144Sminshall { 16832144Sminshall register char *p, *q; 16932144Sminshall register char **c, **found; 17032144Sminshall register int nmatches, longest; 17132144Sminshall 17232144Sminshall if (name == 0) { 17332144Sminshall return 0; 17432144Sminshall } 17532144Sminshall longest = 0; 17632144Sminshall nmatches = 0; 17732144Sminshall found = 0; 17832144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 17932144Sminshall for (q = name; 18032144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 18132144Sminshall if (*q == 0) /* exact match? */ 18232144Sminshall return (c); 18332144Sminshall if (!*q) { /* the name was a prefix */ 18432144Sminshall if (q - name > longest) { 18532144Sminshall longest = q - name; 18632144Sminshall nmatches = 1; 18732144Sminshall found = c; 18832144Sminshall } else if (q - name == longest) 18932144Sminshall nmatches++; 19032144Sminshall } 19132144Sminshall } 19232144Sminshall if (nmatches > 1) 19336180Sminshall return &ambiguous; 19432144Sminshall return (found); 19532144Sminshall } 19632144Sminshall 19732144Sminshall /* 19832144Sminshall * Make a character string into a number. 19932144Sminshall * 20032144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 20132144Sminshall */ 20232144Sminshall 20332144Sminshall static 20432144Sminshall special(s) 20532144Sminshall register char *s; 20632144Sminshall { 20732144Sminshall register char c; 20832144Sminshall char b; 20932144Sminshall 21032144Sminshall switch (*s) { 21132144Sminshall case '^': 21232144Sminshall b = *++s; 21332144Sminshall if (b == '?') { 21432144Sminshall c = b | 0x40; /* DEL */ 21532144Sminshall } else { 21632144Sminshall c = b & 0x1f; 21732144Sminshall } 21832144Sminshall break; 21932144Sminshall default: 22032144Sminshall c = *s; 22132144Sminshall break; 22232144Sminshall } 22332144Sminshall return c; 22432144Sminshall } 22532144Sminshall 22632144Sminshall /* 22732144Sminshall * Construct a control character sequence 22832144Sminshall * for a special character. 22932144Sminshall */ 23032144Sminshall static char * 23132144Sminshall control(c) 23240245Sborman register cc_t c; 23332144Sminshall { 234*44361Sborman static char buf[5]; 23532144Sminshall 23632144Sminshall if (c == 0x7f) 23732144Sminshall return ("^?"); 23840245Sborman if (c == (cc_t)-1) { 23932144Sminshall return "off"; 24032144Sminshall } 241*44361Sborman if (c >= 0x80) { 242*44361Sborman buf[0] = '\\'; 243*44361Sborman buf[1] = ((c>>6)&07) + '0'; 244*44361Sborman buf[2] = ((c>>3)&07) + '0'; 245*44361Sborman buf[3] = (c&07) + '0'; 246*44361Sborman buf[4] = 0; 247*44361Sborman } else if (c >= 0x20) { 24832144Sminshall buf[0] = c; 24932144Sminshall buf[1] = 0; 25032144Sminshall } else { 25132144Sminshall buf[0] = '^'; 25232144Sminshall buf[1] = '@'+c; 25332144Sminshall buf[2] = 0; 25432144Sminshall } 25532144Sminshall return (buf); 25632144Sminshall } 25732144Sminshall 25832144Sminshall 25932144Sminshall 26032144Sminshall /* 26132144Sminshall * The following are data structures and routines for 26232144Sminshall * the "send" command. 26332144Sminshall * 26432144Sminshall */ 26532144Sminshall 26632144Sminshall struct sendlist { 26732144Sminshall char *name; /* How user refers to it (case independent) */ 26832144Sminshall char *help; /* Help information (0 ==> no help) */ 26932144Sminshall #if defined(NOT43) 27038689Sborman int (*handler)(); /* Routine to perform (for special ops) */ 27132144Sminshall #else /* defined(NOT43) */ 27238689Sborman void (*handler)(); /* Routine to perform (for special ops) */ 27332144Sminshall #endif /* defined(NOT43) */ 27438689Sborman int what; /* Character to be sent (<0 ==> special) */ 27532144Sminshall }; 27632144Sminshall 27732144Sminshall #define SENDQUESTION -1 27832144Sminshall #define SENDESCAPE -3 27932144Sminshall 28032144Sminshall static struct sendlist Sendlist[] = { 28138689Sborman { "ao", "Send Telnet Abort output", 0, AO }, 28238689Sborman { "ayt", "Send Telnet 'Are You There'", 0, AYT }, 28338689Sborman { "brk", "Send Telnet Break", 0, BREAK }, 28438689Sborman { "ec", "Send Telnet Erase Character", 0, EC }, 28538689Sborman { "el", "Send Telnet Erase Line", 0, EL }, 28638689Sborman { "escape", "Send current escape character", 0, SENDESCAPE }, 28738689Sborman { "ga", "Send Telnet 'Go Ahead' sequence", 0, GA }, 28838689Sborman { "ip", "Send Telnet Interrupt Process", 0, IP }, 28938689Sborman { "nop", "Send Telnet 'No operation'", 0, NOP }, 29038689Sborman { "eor", "Send Telnet 'End of Record'", 0, EOR }, 29138689Sborman { "abort", "Send Telnet 'Abort Process'", 0, ABORT }, 29238689Sborman { "susp", "Send Telnet 'Suspend Process'", 0, SUSP }, 29338689Sborman { "eof", "Send Telnet End of File Character", 0, xEOF }, 29438689Sborman { "synch", "Perform Telnet 'Synch operation'", dosynch, SYNCH }, 29538909Sborman { "getstatus", "Send request for STATUS", get_status, 0 }, 29638689Sborman { "?", "Display send options", 0, SENDQUESTION }, 29732144Sminshall { 0 } 29832144Sminshall }; 29932144Sminshall 30032144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 30138689Sborman { "break", 0, 0, BREAK }, 30232144Sminshall 30338689Sborman { "intp", 0, 0, IP }, 30438689Sborman { "interrupt", 0, 0, IP }, 30538689Sborman { "intr", 0, 0, IP }, 30632144Sminshall 30738689Sborman { "help", 0, 0, SENDQUESTION }, 30832144Sminshall 30938689Sborman { 0 } 31032144Sminshall }; 31132144Sminshall 31232144Sminshall static char ** 31332144Sminshall getnextsend(name) 31432144Sminshall char *name; 31532144Sminshall { 31632144Sminshall struct sendlist *c = (struct sendlist *) name; 31732144Sminshall 31832144Sminshall return (char **) (c+1); 31932144Sminshall } 32032144Sminshall 32132144Sminshall static struct sendlist * 32232144Sminshall getsend(name) 32332144Sminshall char *name; 32432144Sminshall { 32532144Sminshall struct sendlist *sl; 32632144Sminshall 32732144Sminshall if ((sl = (struct sendlist *) 32832144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 32932144Sminshall return sl; 33032144Sminshall } else { 33132144Sminshall return (struct sendlist *) 33232144Sminshall genget(name, (char **) Sendlist2, getnextsend); 33332144Sminshall } 33432144Sminshall } 33532144Sminshall 33632144Sminshall static 33732144Sminshall sendcmd(argc, argv) 33832144Sminshall int argc; 33932144Sminshall char **argv; 34032144Sminshall { 34132144Sminshall int what; /* what we are sending this time */ 34232144Sminshall int count; /* how many bytes we are going to need to send */ 34332144Sminshall int i; 34432144Sminshall int question = 0; /* was at least one argument a question */ 34532144Sminshall struct sendlist *s; /* pointer to current command */ 34632144Sminshall 34732144Sminshall if (argc < 2) { 34832144Sminshall printf("need at least one argument for 'send' command\n"); 34932144Sminshall printf("'send ?' for help\n"); 35032144Sminshall return 0; 35132144Sminshall } 35232144Sminshall /* 35332144Sminshall * First, validate all the send arguments. 35432144Sminshall * In addition, we see how much space we are going to need, and 35532144Sminshall * whether or not we will be doing a "SYNCH" operation (which 35632144Sminshall * flushes the network queue). 35732144Sminshall */ 35832144Sminshall count = 0; 35932144Sminshall for (i = 1; i < argc; i++) { 36032144Sminshall s = getsend(argv[i]); 36132144Sminshall if (s == 0) { 36232144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 36332144Sminshall argv[i]); 36432144Sminshall return 0; 36532144Sminshall } else if (Ambiguous(s)) { 36632144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 36732144Sminshall argv[i]); 36832144Sminshall return 0; 36932144Sminshall } 37032144Sminshall switch (s->what) { 37132144Sminshall case SENDQUESTION: 37238689Sborman question = 1; 37332144Sminshall break; 37432144Sminshall case SENDESCAPE: 37532144Sminshall count += 1; 37632144Sminshall break; 37732144Sminshall case SYNCH: 37832144Sminshall count += 2; 37932144Sminshall break; 38032144Sminshall default: 38132144Sminshall count += 2; 38232144Sminshall break; 38332144Sminshall } 38432144Sminshall } 38538689Sborman if (!connected) { 38638689Sborman if (count) 38738689Sborman printf("?Need to be connected first.\n"); 38838689Sborman if (question) { 38938689Sborman for (s = Sendlist; s->name; s++) 39038689Sborman if (s->help) 39138689Sborman printf("%-15s %s\n", s->name, s->help); 39238689Sborman } else 39338689Sborman printf("'send ?' for help\n"); 39438689Sborman return !question; 39538689Sborman } 39632144Sminshall /* Now, do we have enough room? */ 39732144Sminshall if (NETROOM() < count) { 39832144Sminshall printf("There is not enough room in the buffer TO the network\n"); 39932144Sminshall printf("to process your request. Nothing will be done.\n"); 40032144Sminshall printf("('send synch' will throw away most data in the network\n"); 40132144Sminshall printf("buffer, if this might help.)\n"); 40232144Sminshall return 0; 40332144Sminshall } 40432144Sminshall /* OK, they are all OK, now go through again and actually send */ 40532144Sminshall for (i = 1; i < argc; i++) { 40632144Sminshall if ((s = getsend(argv[i])) == 0) { 40732144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 408*44361Sborman (void) quit(); 40932144Sminshall /*NOTREACHED*/ 41032144Sminshall } 41138689Sborman if (s->handler) { 41238689Sborman (*s->handler)(s); 41332144Sminshall } else { 41432144Sminshall switch (what = s->what) { 41532144Sminshall case SYNCH: 41632144Sminshall dosynch(); 41732144Sminshall break; 41832144Sminshall case SENDQUESTION: 41932144Sminshall for (s = Sendlist; s->name; s++) { 42038689Sborman if (s->help) 42138689Sborman printf("%-15s %s\n", s->name, s->help); 42232144Sminshall } 42332144Sminshall question = 1; 42432144Sminshall break; 42532144Sminshall case SENDESCAPE: 42632144Sminshall NETADD(escape); 42732144Sminshall break; 42832144Sminshall default: 42932144Sminshall NET2ADD(IAC, what); 43032144Sminshall break; 43132144Sminshall } 43232144Sminshall } 43332144Sminshall } 43432144Sminshall return !question; 43532144Sminshall } 43632144Sminshall 43732144Sminshall /* 43832144Sminshall * The following are the routines and data structures referred 43932144Sminshall * to by the arguments to the "toggle" command. 44032144Sminshall */ 44132144Sminshall 44232144Sminshall static 44332144Sminshall lclchars() 44432144Sminshall { 44532144Sminshall donelclchars = 1; 44632144Sminshall return 1; 44732144Sminshall } 44832144Sminshall 44932144Sminshall static 45032144Sminshall togdebug() 45132144Sminshall { 45232144Sminshall #ifndef NOT43 45332144Sminshall if (net > 0 && 45432144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 45532144Sminshall perror("setsockopt (SO_DEBUG)"); 45632144Sminshall } 45732144Sminshall #else /* NOT43 */ 45832144Sminshall if (debug) { 45932144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 46032144Sminshall perror("setsockopt (SO_DEBUG)"); 46132144Sminshall } else 46232144Sminshall printf("Cannot turn off socket debugging\n"); 46332144Sminshall #endif /* NOT43 */ 46432144Sminshall return 1; 46532144Sminshall } 46632144Sminshall 46732144Sminshall 46832144Sminshall static int 46932144Sminshall togcrlf() 47032144Sminshall { 47132144Sminshall if (crlf) { 47232144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 47332144Sminshall } else { 47432144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 47532144Sminshall } 47632144Sminshall return 1; 47732144Sminshall } 47832144Sminshall 47938909Sborman int binmode; 48032144Sminshall 48132144Sminshall static int 48238689Sborman togbinary(val) 48338689Sborman int val; 48432144Sminshall { 48532144Sminshall donebinarytoggle = 1; 48632144Sminshall 48738909Sborman if (val >= 0) { 48838909Sborman binmode = val; 48938909Sborman } else { 49038909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 49138909Sborman my_want_state_is_do(TELOPT_BINARY)) { 49238909Sborman binmode = 1; 49338909Sborman } else if (my_want_state_is_wont(TELOPT_BINARY) && 49438909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 49538909Sborman binmode = 0; 49638909Sborman } 49738909Sborman val = binmode ? 0 : 1; 49838909Sborman } 49938909Sborman 50038909Sborman if (val == 1) { 50138909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 50238909Sborman my_want_state_is_do(TELOPT_BINARY)) { 50338689Sborman printf("Already operating in binary mode with remote host.\n"); 50438909Sborman } else { 50538909Sborman printf("Negotiating binary mode with remote host.\n"); 50638909Sborman tel_enter_binary(3); 50738689Sborman } 50838909Sborman } else { 50938909Sborman if (my_want_state_is_wont(TELOPT_BINARY) && 51038909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 51138689Sborman printf("Already in network ascii mode with remote host.\n"); 51238909Sborman } else { 51338909Sborman printf("Negotiating network ascii mode with remote host.\n"); 51438909Sborman tel_leave_binary(3); 51538689Sborman } 51632144Sminshall } 51732144Sminshall return 1; 51832144Sminshall } 51932144Sminshall 52038909Sborman static int 52138909Sborman togrbinary(val) 52238909Sborman int val; 52338909Sborman { 52438909Sborman donebinarytoggle = 1; 52532144Sminshall 52638909Sborman if (val == -1) 52738909Sborman val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 52832144Sminshall 52938909Sborman if (val == 1) { 53038909Sborman if (my_want_state_is_do(TELOPT_BINARY)) { 53138909Sborman printf("Already receiving in binary mode.\n"); 53238909Sborman } else { 53338909Sborman printf("Negotiating binary mode on input.\n"); 53438909Sborman tel_enter_binary(1); 53538909Sborman } 53638909Sborman } else { 53738909Sborman if (my_want_state_is_dont(TELOPT_BINARY)) { 53838909Sborman printf("Already receiving in network ascii mode.\n"); 53938909Sborman } else { 54038909Sborman printf("Negotiating network ascii mode on input.\n"); 54138909Sborman tel_leave_binary(1); 54238909Sborman } 54338909Sborman } 54438909Sborman return 1; 54538909Sborman } 54638909Sborman 54738909Sborman static int 54838909Sborman togxbinary(val) 54938909Sborman int val; 55038909Sborman { 55138909Sborman donebinarytoggle = 1; 55238909Sborman 55338909Sborman if (val == -1) 55438909Sborman val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 55538909Sborman 55638909Sborman if (val == 1) { 55738909Sborman if (my_want_state_is_will(TELOPT_BINARY)) { 55838909Sborman printf("Already transmitting in binary mode.\n"); 55938909Sborman } else { 56038909Sborman printf("Negotiating binary mode on output.\n"); 56138909Sborman tel_enter_binary(2); 56238909Sborman } 56338909Sborman } else { 56438909Sborman if (my_want_state_is_wont(TELOPT_BINARY)) { 56538909Sborman printf("Already transmitting in network ascii mode.\n"); 56638909Sborman } else { 56738909Sborman printf("Negotiating network ascii mode on output.\n"); 56838909Sborman tel_leave_binary(2); 56938909Sborman } 57038909Sborman } 57138909Sborman return 1; 57238909Sborman } 57338909Sborman 57438909Sborman 57532144Sminshall extern int togglehelp(); 57638689Sborman extern int slc_check(); 57732144Sminshall 57832144Sminshall struct togglelist { 57932144Sminshall char *name; /* name of toggle */ 58032144Sminshall char *help; /* help message */ 58132144Sminshall int (*handler)(); /* routine to do actual setting */ 58232144Sminshall int *variable; 58332144Sminshall char *actionexplanation; 58432144Sminshall }; 58532144Sminshall 58632144Sminshall static struct togglelist Togglelist[] = { 58732144Sminshall { "autoflush", 58838689Sborman "flushing of output when sending interrupt characters", 58932144Sminshall 0, 59038689Sborman &autoflush, 59138689Sborman "flush output when sending interrupt characters" }, 59232144Sminshall { "autosynch", 59338689Sborman "automatic sending of interrupt characters in urgent mode", 59432144Sminshall 0, 59538689Sborman &autosynch, 59638689Sborman "send interrupt characters in urgent mode" }, 59732144Sminshall { "binary", 59838689Sborman "sending and receiving of binary data", 59932144Sminshall togbinary, 60038689Sborman 0, 60138689Sborman 0 }, 60238909Sborman { "inbinary", 60338909Sborman "receiving of binary data", 60438909Sborman togrbinary, 60538909Sborman 0, 60638909Sborman 0 }, 60738909Sborman { "outbinary", 60838909Sborman "sending of binary data", 60938909Sborman togxbinary, 61038909Sborman 0, 61138909Sborman 0 }, 61232144Sminshall { "crlf", 61338689Sborman "sending carriage returns as telnet <CR><LF>", 61432144Sminshall togcrlf, 61538689Sborman &crlf, 61638689Sborman 0 }, 61732144Sminshall { "crmod", 61838689Sborman "mapping of received carriage returns", 61932144Sminshall 0, 62038689Sborman &crmod, 62138689Sborman "map carriage return on output" }, 62232144Sminshall { "localchars", 62338689Sborman "local recognition of certain control characters", 62432144Sminshall lclchars, 62538689Sborman &localchars, 62638689Sborman "recognize certain control characters" }, 62743317Skfall #ifdef KERBEROS 62843317Skfall { "kerberos", 62943317Skfall "toggle use of Kerberos authentication", 63043317Skfall 0, 63143317Skfall &kerberized, 63243317Skfall "use Kerberos authentication" }, 63343317Skfall #endif 63438689Sborman { " ", "", 0 }, /* empty line */ 63538208Sminshall #if defined(unix) && defined(TN3270) 63638920Sminshall { "apitrace", 63738920Sminshall "(debugging) toggle tracing of API transactions", 63838920Sminshall 0, 63938920Sminshall &apitrace, 64038920Sminshall "trace API transactions" }, 64138208Sminshall { "cursesdata", 64238208Sminshall "(debugging) toggle printing of hexadecimal curses data", 64338208Sminshall 0, 64438689Sborman &cursesdata, 64538689Sborman "print hexadecimal representation of curses data" }, 64638208Sminshall #endif /* defined(unix) && defined(TN3270) */ 64732144Sminshall { "debug", 64838689Sborman "debugging", 64932144Sminshall togdebug, 65038689Sborman &debug, 65138689Sborman "turn on socket level debugging" }, 65232144Sminshall { "netdata", 65338689Sborman "printing of hexadecimal network data (debugging)", 65432144Sminshall 0, 65538689Sborman &netdata, 65638689Sborman "print hexadecimal representation of network traffic" }, 65738689Sborman { "prettydump", 65838689Sborman "output of \"netdata\" to user readable format (debugging)", 65938689Sborman 0, 66038689Sborman &prettydump, 66138689Sborman "print user readable output for \"netdata\"" }, 66232144Sminshall { "options", 66338689Sborman "viewing of options processing (debugging)", 66432144Sminshall 0, 66538689Sborman &showoptions, 66638689Sborman "show option processing" }, 66738208Sminshall #if defined(unix) 66838208Sminshall { "termdata", 66938208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 67038208Sminshall 0, 67138689Sborman &termdata, 67238689Sborman "print hexadecimal representation of terminal traffic" }, 67338208Sminshall #endif /* defined(unix) */ 67432144Sminshall { "?", 67538689Sborman 0, 67638689Sborman togglehelp }, 67732144Sminshall { "help", 67838689Sborman 0, 67938689Sborman togglehelp }, 68032144Sminshall { 0 } 68132144Sminshall }; 68232144Sminshall 68332144Sminshall static 68432144Sminshall togglehelp() 68532144Sminshall { 68632144Sminshall struct togglelist *c; 68732144Sminshall 68832144Sminshall for (c = Togglelist; c->name; c++) { 68938689Sborman if (c->help) { 69038689Sborman if (*c->help) 69138689Sborman printf("%-15s toggle %s\n", c->name, c->help); 69238689Sborman else 69338689Sborman printf("\n"); 69432144Sminshall } 69532144Sminshall } 69638689Sborman printf("\n"); 69738689Sborman printf("%-15s %s\n", "?", "display help information"); 69832144Sminshall return 0; 69932144Sminshall } 70032144Sminshall 70138689Sborman static 70238689Sborman settogglehelp(set) 70338689Sborman int set; 70438689Sborman { 70538689Sborman struct togglelist *c; 70638689Sborman 70738689Sborman for (c = Togglelist; c->name; c++) { 70838689Sborman if (c->help) { 70938689Sborman if (*c->help) 71038689Sborman printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 71138689Sborman c->help); 71238689Sborman else 71338689Sborman printf("\n"); 71438689Sborman } 71538689Sborman } 71638689Sborman } 71738689Sborman 71832144Sminshall static char ** 71932144Sminshall getnexttoggle(name) 72032144Sminshall char *name; 72132144Sminshall { 72232144Sminshall struct togglelist *c = (struct togglelist *) name; 72332144Sminshall 72432144Sminshall return (char **) (c+1); 72532144Sminshall } 72632144Sminshall 72732144Sminshall static struct togglelist * 72832144Sminshall gettoggle(name) 72932144Sminshall char *name; 73032144Sminshall { 73132144Sminshall return (struct togglelist *) 73232144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 73332144Sminshall } 73432144Sminshall 73532144Sminshall static 73632144Sminshall toggle(argc, argv) 73732144Sminshall int argc; 73832144Sminshall char *argv[]; 73932144Sminshall { 74032144Sminshall int retval = 1; 74132144Sminshall char *name; 74232144Sminshall struct togglelist *c; 74332144Sminshall 74432144Sminshall if (argc < 2) { 74532144Sminshall fprintf(stderr, 74632144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 74732144Sminshall return 0; 74832144Sminshall } 74932144Sminshall argc--; 75032144Sminshall argv++; 75132144Sminshall while (argc--) { 75232144Sminshall name = *argv++; 75332144Sminshall c = gettoggle(name); 75432144Sminshall if (Ambiguous(c)) { 75532144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 75632144Sminshall name); 75732144Sminshall return 0; 75832144Sminshall } else if (c == 0) { 75932144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 76032144Sminshall name); 76132144Sminshall return 0; 76232144Sminshall } else { 76332144Sminshall if (c->variable) { 76432144Sminshall *c->variable = !*c->variable; /* invert it */ 76532144Sminshall if (c->actionexplanation) { 76632144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 76732144Sminshall c->actionexplanation); 76832144Sminshall } 76932144Sminshall } 77032144Sminshall if (c->handler) { 77138689Sborman retval &= (*c->handler)(-1); 77232144Sminshall } 77332144Sminshall } 77432144Sminshall } 77532144Sminshall return retval; 77632144Sminshall } 77732144Sminshall 77832144Sminshall /* 77932144Sminshall * The following perform the "set" command. 78032144Sminshall */ 78132144Sminshall 78238689Sborman #ifdef USE_TERMIO 78338689Sborman struct termio new_tc = { 0 }; 78438689Sborman #endif 78538689Sborman 78632144Sminshall struct setlist { 78732144Sminshall char *name; /* name */ 78832144Sminshall char *help; /* help information */ 78938689Sborman void (*handler)(); 79040245Sborman cc_t *charp; /* where it is located at */ 79132144Sminshall }; 79232144Sminshall 79332144Sminshall static struct setlist Setlist[] = { 794*44361Sborman #ifdef KLUDGELINEMODE 79538689Sborman { "echo", "character to toggle local echoing on/off", 0, &echoc }, 796*44361Sborman #endif 79738689Sborman { "escape", "character to escape back to telnet command mode", 0, &escape }, 79840245Sborman { "tracefile", "file to write trace intormation to", SetNetTrace, (cc_t *)NetTraceFile}, 79932144Sminshall { " ", "" }, 80038689Sborman { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 80138689Sborman { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp }, 80238689Sborman { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 80338689Sborman { "quit", "character to cause an Abort process", 0, termQuitCharp }, 80438689Sborman { "eof", "character to cause an EOF ", 0, termEofCharp }, 80538689Sborman { " ", "" }, 80638689Sborman { " ", "The following are for local editing in linemode", 0, 0 }, 80738689Sborman { "erase", "character to use to erase a character", 0, termEraseCharp }, 80838689Sborman { "kill", "character to use to erase a line", 0, termKillCharp }, 80938689Sborman { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 810*44361Sborman { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, 81138689Sborman { "reprint", "character to use for line reprint", 0, termRprntCharp }, 81238689Sborman { "worderase", "character to use to erase a word", 0, termWerasCharp }, 81338689Sborman { "start", "character to use for XON", 0, termStartCharp }, 814*44361Sborman { "stop", "character to use for XOFF", 0, termStopCharp }, 815*44361Sborman { "forw1", "alternate end of line character", 0, termForw1Charp }, 816*44361Sborman { "forw2", "alternate end of line character", 0, termForw2Charp }, 81732144Sminshall { 0 } 81832144Sminshall }; 81932144Sminshall 82038689Sborman #ifdef CRAY 82138689Sborman /* Work around compiler bug */ 82238689Sborman _setlist_init() 82338689Sborman { 824*44361Sborman #ifndef KLUDGELINEMODE 825*44361Sborman #define N 4 826*44361Sborman #else 827*44361Sborman #define N 5 828*44361Sborman #endif 829*44361Sborman Setlist[N+0].charp = &termFlushChar; 830*44361Sborman Setlist[N+1].charp = &termIntChar; 831*44361Sborman Setlist[N+2].charp = &termQuitChar; 832*44361Sborman Setlist[N+3].charp = &termEofChar; 833*44361Sborman Setlist[N+6].charp = &termEraseChar; 834*44361Sborman Setlist[N+7].charp = &termKillChar; 835*44361Sborman Setlist[N+8].charp = &termLiteralNextChar; 836*44361Sborman Setlist[N+9].charp = &termSuspChar; 837*44361Sborman Setlist[N+10].charp = &termRprntChar; 838*44361Sborman Setlist[N+11].charp = &termWerasChar; 839*44361Sborman Setlist[N+12].charp = &termStartChar; 840*44361Sborman Setlist[N+13].charp = &termStopChar; 841*44361Sborman Setlist[N+14].charp = &termForw1Char; 842*44361Sborman Setlist[N+15].charp = &termForw2Char; 843*44361Sborman #undef N 84438689Sborman } 84538810Sborman #endif /* CRAY */ 84638689Sborman 84732144Sminshall static char ** 84832144Sminshall getnextset(name) 84932144Sminshall char *name; 85032144Sminshall { 85132144Sminshall struct setlist *c = (struct setlist *)name; 85232144Sminshall 85332144Sminshall return (char **) (c+1); 85432144Sminshall } 85532144Sminshall 85632144Sminshall static struct setlist * 85732144Sminshall getset(name) 85832144Sminshall char *name; 85932144Sminshall { 86032144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 86132144Sminshall } 86232144Sminshall 863*44361Sborman set_escape_char(s) 864*44361Sborman char *s; 865*44361Sborman { 866*44361Sborman escape = (s && *s) ? special(s) : -1; 867*44361Sborman printf("escape character is '%s'.\n", control(escape)); 868*44361Sborman } 869*44361Sborman 87032144Sminshall static 87132144Sminshall setcmd(argc, argv) 87232144Sminshall int argc; 87332144Sminshall char *argv[]; 87432144Sminshall { 87532144Sminshall int value; 87632144Sminshall struct setlist *ct; 87738689Sborman struct togglelist *c; 87832144Sminshall 87938689Sborman if (argc < 2 || argc > 3) { 88038689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 88132144Sminshall return 0; 88232144Sminshall } 88338689Sborman if ((argc == 2) && 88438689Sborman ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 88538689Sborman for (ct = Setlist; ct->name; ct++) 88638689Sborman printf("%-15s %s\n", ct->name, ct->help); 88738689Sborman printf("\n"); 88838689Sborman settogglehelp(1); 88938689Sborman printf("%-15s %s\n", "?", "display help information"); 89038689Sborman return 0; 89138689Sborman } 89232144Sminshall 89332144Sminshall ct = getset(argv[1]); 89432144Sminshall if (ct == 0) { 89538689Sborman c = gettoggle(argv[1]); 89638689Sborman if (c == 0) { 89738689Sborman fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 89832144Sminshall argv[1]); 89938689Sborman return 0; 90038689Sborman } else if (Ambiguous(c)) { 90138689Sborman fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 90238689Sborman argv[1]); 90338689Sborman return 0; 90438689Sborman } 90538689Sborman if (c->variable) { 90638689Sborman if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 90738689Sborman *c->variable = 1; 90838689Sborman else if (strcmp("off", argv[2]) == 0) 90938689Sborman *c->variable = 0; 91038689Sborman else { 91138689Sborman printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 91238689Sborman return 0; 91338689Sborman } 91438689Sborman if (c->actionexplanation) { 91538689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 91638689Sborman c->actionexplanation); 91738689Sborman } 91838689Sborman } 91938689Sborman if (c->handler) 92038689Sborman (*c->handler)(1); 92138689Sborman } else if (argc != 3) { 92238689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 92332144Sminshall return 0; 92432144Sminshall } else if (Ambiguous(ct)) { 92532144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 92632144Sminshall argv[1]); 92732144Sminshall return 0; 92838689Sborman } else if (ct->handler) { 92938689Sborman (*ct->handler)(argv[2]); 930*44361Sborman printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 93132144Sminshall } else { 93232144Sminshall if (strcmp("off", argv[2])) { 93332144Sminshall value = special(argv[2]); 93432144Sminshall } else { 93532144Sminshall value = -1; 93632144Sminshall } 93740245Sborman *(ct->charp) = (cc_t)value; 93832144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 93932144Sminshall } 94038689Sborman slc_check(); 94132144Sminshall return 1; 94232144Sminshall } 94338689Sborman 94438689Sborman static 94538689Sborman unsetcmd(argc, argv) 94638689Sborman int argc; 94738689Sborman char *argv[]; 94838689Sborman { 94938689Sborman struct setlist *ct; 95038689Sborman struct togglelist *c; 95138689Sborman register char *name; 95238689Sborman 95338689Sborman if (argc < 2) { 95438689Sborman fprintf(stderr, 95538689Sborman "Need an argument to 'unset' command. 'unset ?' for help.\n"); 95638689Sborman return 0; 95738689Sborman } 95838689Sborman if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) { 95938689Sborman for (ct = Setlist; ct->name; ct++) 96038689Sborman printf("%-15s %s\n", ct->name, ct->help); 96138689Sborman printf("\n"); 96238689Sborman settogglehelp(0); 96338689Sborman printf("%-15s %s\n", "?", "display help information"); 96438689Sborman return 0; 96538689Sborman } 96638689Sborman 96738689Sborman argc--; 96838689Sborman argv++; 96938689Sborman while (argc--) { 97038689Sborman name = *argv++; 97138689Sborman ct = getset(name); 97238689Sborman if (ct == 0) { 97338689Sborman c = gettoggle(name); 97438689Sborman if (c == 0) { 97538689Sborman fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 97638689Sborman name); 97738689Sborman return 0; 97838689Sborman } else if (Ambiguous(c)) { 97938689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 98038689Sborman name); 98138689Sborman return 0; 98238689Sborman } 98338689Sborman if (c->variable) { 98438689Sborman *c->variable = 0; 98538689Sborman if (c->actionexplanation) { 98638689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 98738689Sborman c->actionexplanation); 98838689Sborman } 98938689Sborman } 99038689Sborman if (c->handler) 99138689Sborman (*c->handler)(0); 99238689Sborman } else if (Ambiguous(ct)) { 99338689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 99438689Sborman name); 99538689Sborman return 0; 99638689Sborman } else if (ct->handler) { 99738689Sborman (*ct->handler)(0); 998*44361Sborman printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 99938689Sborman } else { 100038689Sborman *(ct->charp) = -1; 100138689Sborman printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 100238689Sborman } 100338689Sborman } 100438689Sborman return 1; 100538689Sborman } 100632144Sminshall 100732144Sminshall /* 100832144Sminshall * The following are the data structures and routines for the 100932144Sminshall * 'mode' command. 101032144Sminshall */ 101138689Sborman #ifdef KLUDGELINEMODE 101238689Sborman extern int kludgelinemode; 1013*44361Sborman 1014*44361Sborman dokludgemode() 1015*44361Sborman { 1016*44361Sborman kludgelinemode = 1; 1017*44361Sborman send_wont(TELOPT_LINEMODE, 1); 1018*44361Sborman send_dont(TELOPT_SGA, 1); 1019*44361Sborman send_dont(TELOPT_ECHO, 1); 1020*44361Sborman } 102138689Sborman #endif 102232144Sminshall 102332144Sminshall static 102432144Sminshall dolinemode() 102532144Sminshall { 102638689Sborman #ifdef KLUDGELINEMODE 102738689Sborman if (kludgelinemode) 102838689Sborman send_dont(TELOPT_SGA, 1); 102938689Sborman #endif 103038689Sborman send_will(TELOPT_LINEMODE, 1); 103138689Sborman send_dont(TELOPT_ECHO, 1); 103232144Sminshall return 1; 103332144Sminshall } 103432144Sminshall 103532144Sminshall static 103632144Sminshall docharmode() 103732144Sminshall { 103838689Sborman #ifdef KLUDGELINEMODE 103938689Sborman if (kludgelinemode) 104038689Sborman send_do(TELOPT_SGA, 1); 104138689Sborman else 104238689Sborman #endif 104338689Sborman send_wont(TELOPT_LINEMODE, 1); 104438689Sborman send_do(TELOPT_ECHO, 1); 104538689Sborman return 1; 104638689Sborman } 104738689Sborman 104838689Sborman setmode(bit) 104938689Sborman { 105038689Sborman return dolmmode(bit, 1); 105138689Sborman } 105238689Sborman 105338689Sborman clearmode(bit) 105438689Sborman { 105538689Sborman return dolmmode(bit, 0); 105638689Sborman } 105738689Sborman 105838689Sborman dolmmode(bit, on) 105938689Sborman int bit, on; 106038689Sborman { 106138689Sborman char c; 106238689Sborman extern int linemode; 106338689Sborman 106438689Sborman if (my_want_state_is_wont(TELOPT_LINEMODE)) { 106538689Sborman printf("?Need to have LINEMODE option enabled first.\n"); 106638689Sborman printf("'mode ?' for help.\n"); 106738689Sborman return 0; 106832144Sminshall } 106938689Sborman 107038689Sborman if (on) 107138689Sborman c = (linemode | bit); 107238689Sborman else 107338689Sborman c = (linemode & ~bit); 107438689Sborman lm_mode(&c, 1, 1); 107532144Sminshall return 1; 107632144Sminshall } 107732144Sminshall 107838689Sborman struct modelist { 107938689Sborman char *name; /* command name */ 108038689Sborman char *help; /* help string */ 108138689Sborman int (*handler)(); /* routine which executes command */ 108238689Sborman int needconnect; /* Do we need to be connected to execute? */ 108338689Sborman int arg1; 108438689Sborman }; 108538689Sborman 108638689Sborman extern int modehelp(); 108738689Sborman 108838689Sborman static struct modelist ModeList[] = { 108938689Sborman { "character", "Disable LINEMODE option", docharmode, 1 }, 109039529Sborman #ifdef KLUDGELINEMODE 109139529Sborman { "", "(or disable obsolete line-by-line mode)", 0 }, 109238689Sborman #endif 109338689Sborman { "line", "Enable LINEMODE option", dolinemode, 1 }, 109439529Sborman #ifdef KLUDGELINEMODE 109539529Sborman { "", "(or enable obsolete line-by-line mode)", 0 }, 109638689Sborman #endif 109738689Sborman { "", "", 0 }, 109838689Sborman { "", "These require the LINEMODE option to be enabled", 0 }, 109938689Sborman { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 110038689Sborman { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 110138689Sborman { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 110238689Sborman { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 110338689Sborman { "+edit", 0, setmode, 1, MODE_EDIT }, 110438689Sborman { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 1105*44361Sborman { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB }, 1106*44361Sborman { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB }, 1107*44361Sborman { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 1108*44361Sborman { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO }, 1109*44361Sborman { "+litecho", 0, setmode, 1, MODE_LIT_ECHO }, 1110*44361Sborman { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 111138689Sborman { "help", 0, modehelp, 0 }, 1112*44361Sborman #ifdef KLUDGELINEMODE 1113*44361Sborman { "kludgeline", 0, dokludgemode, 1 }, 1114*44361Sborman #endif 1115*44361Sborman { "", "", 0 }, 111638689Sborman { "?", "Print help information", modehelp, 0 }, 111732144Sminshall { 0 }, 111832144Sminshall }; 111932144Sminshall 112032144Sminshall static char ** 112132144Sminshall getnextmode(name) 112232144Sminshall char *name; 112332144Sminshall { 112438689Sborman return (char **) (((struct modelist *)name)+1); 112532144Sminshall } 112632144Sminshall 112738689Sborman static struct modelist * 112832144Sminshall getmodecmd(name) 112932144Sminshall char *name; 113032144Sminshall { 113138689Sborman return (struct modelist *) genget(name, (char **) ModeList, getnextmode); 113232144Sminshall } 113332144Sminshall 113438689Sborman modehelp() 113538689Sborman { 113638689Sborman struct modelist *mt; 113738689Sborman 113838689Sborman printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 113938689Sborman for (mt = ModeList; mt->name; mt++) { 114038689Sborman if (mt->help) { 114138689Sborman if (*mt->help) 114238689Sborman printf("%-15s %s\n", mt->name, mt->help); 114338689Sborman else 114438689Sborman printf("\n"); 114538689Sborman } 114638689Sborman } 114738689Sborman return 0; 114838689Sborman } 114938689Sborman 115032144Sminshall static 115132144Sminshall modecmd(argc, argv) 115232144Sminshall int argc; 115332144Sminshall char *argv[]; 115432144Sminshall { 115538689Sborman struct modelist *mt; 115632144Sminshall 115738689Sborman if (argc != 2) { 115838689Sborman printf("'mode' command requires an argument\n"); 115938689Sborman printf("'mode ?' for help.\n"); 116038689Sborman } else if ((mt = getmodecmd(argv[1])) == 0) { 116132144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 116232144Sminshall } else if (Ambiguous(mt)) { 116332144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 116438689Sborman } else if (mt->needconnect && !connected) { 116538689Sborman printf("?Need to be connected first.\n"); 116638689Sborman printf("'mode ?' for help.\n"); 116738689Sborman } else if (mt->handler) { 116838689Sborman return (*mt->handler)(mt->arg1); 116932144Sminshall } 117038689Sborman return 0; 117132144Sminshall } 117232144Sminshall 117332144Sminshall /* 117432144Sminshall * The following data structures and routines implement the 117532144Sminshall * "display" command. 117632144Sminshall */ 117732144Sminshall 117832144Sminshall static 117932144Sminshall display(argc, argv) 118032144Sminshall int argc; 118132144Sminshall char *argv[]; 118232144Sminshall { 118332144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 118432144Sminshall if (*tl->variable) { \ 118532144Sminshall printf("will"); \ 118632144Sminshall } else { \ 118732144Sminshall printf("won't"); \ 118832144Sminshall } \ 118932144Sminshall printf(" %s.\n", tl->actionexplanation); \ 119032144Sminshall } 119132144Sminshall 119232144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 119338689Sborman if (sl->handler == 0) \ 119438689Sborman printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 119538689Sborman else \ 1196*44361Sborman printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 119732144Sminshall } 119832144Sminshall 119932144Sminshall struct togglelist *tl; 120032144Sminshall struct setlist *sl; 120132144Sminshall 120232144Sminshall if (argc == 1) { 120332144Sminshall for (tl = Togglelist; tl->name; tl++) { 120432144Sminshall dotog(tl); 120532144Sminshall } 120632144Sminshall printf("\n"); 120732144Sminshall for (sl = Setlist; sl->name; sl++) { 120832144Sminshall doset(sl); 120932144Sminshall } 121032144Sminshall } else { 121132144Sminshall int i; 121232144Sminshall 121332144Sminshall for (i = 1; i < argc; i++) { 121432144Sminshall sl = getset(argv[i]); 121532144Sminshall tl = gettoggle(argv[i]); 121632144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 121732144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 121832144Sminshall return 0; 121932144Sminshall } else if (!sl && !tl) { 122032144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 122132144Sminshall return 0; 122232144Sminshall } else { 122332144Sminshall if (tl) { 122432144Sminshall dotog(tl); 122532144Sminshall } 122632144Sminshall if (sl) { 122732144Sminshall doset(sl); 122832144Sminshall } 122932144Sminshall } 123032144Sminshall } 123132144Sminshall } 123238689Sborman /*@*/optionstatus(); 123332144Sminshall return 1; 123432144Sminshall #undef doset 123532144Sminshall #undef dotog 123632144Sminshall } 123732144Sminshall 123832144Sminshall /* 123932144Sminshall * The following are the data structures, and many of the routines, 124032144Sminshall * relating to command processing. 124132144Sminshall */ 124232144Sminshall 124332144Sminshall /* 124432144Sminshall * Set the escape character. 124532144Sminshall */ 124632144Sminshall static 124732144Sminshall setescape(argc, argv) 124832144Sminshall int argc; 124932144Sminshall char *argv[]; 125032144Sminshall { 125132144Sminshall register char *arg; 125232144Sminshall char buf[50]; 125332144Sminshall 125432144Sminshall printf( 125532144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 125632144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 125732144Sminshall if (argc > 2) 125832144Sminshall arg = argv[1]; 125932144Sminshall else { 126032144Sminshall printf("new escape character: "); 126134849Sminshall (void) gets(buf); 126232144Sminshall arg = buf; 126332144Sminshall } 126432144Sminshall if (arg[0] != '\0') 126532144Sminshall escape = arg[0]; 126632144Sminshall if (!In3270) { 126732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 126832144Sminshall } 126934849Sminshall (void) fflush(stdout); 127032144Sminshall return 1; 127132144Sminshall } 127232144Sminshall 127332144Sminshall /*VARARGS*/ 127432144Sminshall static 127532144Sminshall togcrmod() 127632144Sminshall { 127732144Sminshall crmod = !crmod; 127832144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 127932144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 128034849Sminshall (void) fflush(stdout); 128132144Sminshall return 1; 128232144Sminshall } 128332144Sminshall 128432144Sminshall /*VARARGS*/ 128532144Sminshall suspend() 128632144Sminshall { 128738689Sborman #ifdef SIGTSTP 128837219Sminshall setcommandmode(); 128937219Sminshall { 1290*44361Sborman long oldrows, oldcols, newrows, newcols, err; 129137219Sminshall 1292*44361Sborman err = TerminalWindowSize(&oldrows, &oldcols); 129334849Sminshall (void) kill(0, SIGTSTP); 1294*44361Sborman err += TerminalWindowSize(&newrows, &newcols); 1295*44361Sborman if (connected && !err && 1296*44361Sborman ((oldrows != newrows) || (oldcols != newcols))) { 129737219Sminshall sendnaws(); 129837219Sminshall } 129937219Sminshall } 130037219Sminshall /* reget parameters in case they were changed */ 130137219Sminshall TerminalSaveState(); 130238689Sborman setconnmode(0); 130338689Sborman #else 130438689Sborman printf("Suspend is not supported. Try the '!' command instead\n"); 130538689Sborman #endif 130637219Sminshall return 1; 130732144Sminshall } 130832144Sminshall 130938689Sborman #if !defined(TN3270) 1310*44361Sborman /*ARGSUSED*/ 131138689Sborman shell(argc, argv) 131238689Sborman int argc; 131338689Sborman char *argv[]; 131438689Sborman { 131538689Sborman extern char *rindex(); 131638689Sborman 131738689Sborman setcommandmode(); 131838689Sborman switch(vfork()) { 131938689Sborman case -1: 132038689Sborman perror("Fork failed\n"); 132138689Sborman break; 132238689Sborman 132338689Sborman case 0: 132438689Sborman { 132538689Sborman /* 132638689Sborman * Fire up the shell in the child. 132738689Sborman */ 132838689Sborman register char *shell, *shellname; 132938689Sborman 133038689Sborman shell = getenv("SHELL"); 133138689Sborman if (shell == NULL) 133238689Sborman shell = "/bin/sh"; 133338689Sborman if ((shellname = rindex(shell, '/')) == 0) 133438689Sborman shellname = shell; 133538689Sborman else 133638689Sborman shellname++; 133738689Sborman if (argc > 1) 133838689Sborman execl(shell, shellname, "-c", &saveline[1], 0); 133938689Sborman else 134038689Sborman execl(shell, shellname, 0); 134138689Sborman perror("Execl"); 134238689Sborman _exit(1); 134338689Sborman } 134438689Sborman default: 1345*44361Sborman (void)wait((int *)0); /* Wait for the shell to complete */ 134638689Sborman } 134738689Sborman } 134838689Sborman #endif /* !defined(TN3270) */ 134938689Sborman 135032144Sminshall /*VARARGS*/ 135132144Sminshall static 135232144Sminshall bye(argc, argv) 135332144Sminshall int argc; /* Number of arguments */ 135432144Sminshall char *argv[]; /* arguments */ 135532144Sminshall { 135632144Sminshall if (connected) { 135734849Sminshall (void) shutdown(net, 2); 135832144Sminshall printf("Connection closed.\n"); 135934849Sminshall (void) NetClose(net); 136032144Sminshall connected = 0; 136132144Sminshall /* reset options */ 136232144Sminshall tninit(); 136332144Sminshall #if defined(TN3270) 136432144Sminshall SetIn3270(); /* Get out of 3270 mode */ 136532144Sminshall #endif /* defined(TN3270) */ 136632144Sminshall } 136732144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 136832144Sminshall longjmp(toplevel, 1); 136932144Sminshall /* NOTREACHED */ 137032144Sminshall } 137132144Sminshall return 1; /* Keep lint, etc., happy */ 137232144Sminshall } 137332144Sminshall 137432144Sminshall /*VARARGS*/ 137532144Sminshall quit() 137632144Sminshall { 137732144Sminshall (void) call(bye, "bye", "fromquit", 0); 137832144Sminshall Exit(0); 1379*44361Sborman /*NOTREACHED*/ 138032144Sminshall } 138138689Sborman 138238689Sborman /* 138338689Sborman * The SLC command. 138438689Sborman */ 138532144Sminshall 138638689Sborman struct slclist { 138738689Sborman char *name; 138838689Sborman char *help; 138938689Sborman int (*handler)(); 139038689Sborman int arg; 139138689Sborman }; 139238689Sborman 139338689Sborman extern int slc_help(); 139438689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate(); 139538689Sborman 139638689Sborman struct slclist SlcList[] = { 139738689Sborman { "export", "Use local special character definitions", 139838689Sborman slc_mode_export, 0 }, 139938689Sborman { "import", "Use remote special character definitions", 140038689Sborman slc_mode_import, 1 }, 140138689Sborman { "check", "Verify remote special character definitions", 140238689Sborman slc_mode_import, 0 }, 140338689Sborman { "help", 0, slc_help, 0 }, 140438689Sborman { "?", "Print help information", slc_help, 0 }, 140538689Sborman { 0 }, 140638689Sborman }; 140738689Sborman 140838689Sborman static 140938689Sborman slc_help() 141038689Sborman { 141138689Sborman struct slclist *c; 141238689Sborman 141338689Sborman for (c = SlcList; c->name; c++) { 141438689Sborman if (c->help) { 141538689Sborman if (*c->help) 141638689Sborman printf("%-15s %s\n", c->name, c->help); 141738689Sborman else 141838689Sborman printf("\n"); 141938689Sborman } 142038689Sborman } 142138689Sborman } 142238689Sborman 142338689Sborman static char ** 142438689Sborman getnextslc(name) 142538689Sborman char *name; 142638689Sborman { 142738689Sborman return (char **)(((struct slclist *)name)+1); 142838689Sborman } 142938689Sborman 143038689Sborman static struct slclist * 143138689Sborman getslc(name) 143238689Sborman char *name; 143338689Sborman { 143438689Sborman return (struct slclist *)genget(name, (char **) SlcList, getnextslc); 143538689Sborman } 143638689Sborman 143738689Sborman static 143838689Sborman slccmd(argc, argv) 143938689Sborman int argc; 144038689Sborman char *argv[]; 144138689Sborman { 144238689Sborman struct slclist *c; 144338689Sborman 144438689Sborman if (argc != 2) { 144538689Sborman fprintf(stderr, 144638689Sborman "Need an argument to 'slc' command. 'slc ?' for help.\n"); 144738689Sborman return 0; 144838689Sborman } 144938689Sborman c = getslc(argv[1]); 145038689Sborman if (c == 0) { 145138689Sborman fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 145238689Sborman argv[1]); 145338689Sborman return 0; 145438689Sborman } 145538689Sborman if (Ambiguous(c)) { 145638689Sborman fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 145738689Sborman argv[1]); 145838689Sborman return 0; 145938689Sborman } 146038689Sborman (*c->handler)(c->arg); 146138689Sborman slcstate(); 146238689Sborman return 1; 146338689Sborman } 1464*44361Sborman 1465*44361Sborman /* 1466*44361Sborman * The ENVIRON command. 1467*44361Sborman */ 146838689Sborman 1469*44361Sborman struct envlist { 1470*44361Sborman char *name; 1471*44361Sborman char *help; 1472*44361Sborman int (*handler)(); 1473*44361Sborman int narg; 1474*44361Sborman }; 1475*44361Sborman 1476*44361Sborman extern struct env_lst *env_define(); 1477*44361Sborman extern int env_undefine(); 1478*44361Sborman extern int env_export(), env_unexport(); 1479*44361Sborman extern int env_list(), env_help(); 1480*44361Sborman 1481*44361Sborman struct envlist EnvList[] = { 1482*44361Sborman { "define", "Define an environment variable", 1483*44361Sborman (int (*)())env_define, 2 }, 1484*44361Sborman { "undefine", "Undefine an environment variable", 1485*44361Sborman env_undefine, 1 }, 1486*44361Sborman { "export", "Mark an environment variable for automatic export", 1487*44361Sborman env_export, 1 }, 1488*44361Sborman { "unexport", "Dont mark an environment variable for automatic export", 1489*44361Sborman env_unexport, 1 }, 1490*44361Sborman { "list", "List the current environment variables", 1491*44361Sborman env_list, 0 }, 1492*44361Sborman { "help", 0, env_help, 0 }, 1493*44361Sborman { "?", "Print help information", env_help, 0 }, 1494*44361Sborman { 0 }, 1495*44361Sborman }; 1496*44361Sborman 1497*44361Sborman static 1498*44361Sborman env_help() 1499*44361Sborman { 1500*44361Sborman struct envlist *c; 1501*44361Sborman 1502*44361Sborman for (c = EnvList; c->name; c++) { 1503*44361Sborman if (c->help) { 1504*44361Sborman if (*c->help) 1505*44361Sborman printf("%-15s %s\n", c->name, c->help); 1506*44361Sborman else 1507*44361Sborman printf("\n"); 1508*44361Sborman } 1509*44361Sborman } 1510*44361Sborman } 1511*44361Sborman 1512*44361Sborman static char ** 1513*44361Sborman getnextenv(name) 1514*44361Sborman char *name; 1515*44361Sborman { 1516*44361Sborman return (char **)(((struct envlist *)name)+1); 1517*44361Sborman } 1518*44361Sborman 1519*44361Sborman static struct envlist * 1520*44361Sborman getenvcmd(name) 1521*44361Sborman char *name; 1522*44361Sborman { 1523*44361Sborman return (struct envlist *)genget(name, (char **) EnvList, getnextenv); 1524*44361Sborman } 1525*44361Sborman 1526*44361Sborman env_cmd(argc, argv) 1527*44361Sborman int argc; 1528*44361Sborman char *argv[]; 1529*44361Sborman { 1530*44361Sborman struct envlist *c; 1531*44361Sborman 1532*44361Sborman if (argc < 2) { 1533*44361Sborman fprintf(stderr, 1534*44361Sborman "Need an argument to 'environ' command. 'environ ?' for help.\n"); 1535*44361Sborman return 0; 1536*44361Sborman } 1537*44361Sborman c = getenvcmd(argv[1]); 1538*44361Sborman if (c == 0) { 1539*44361Sborman fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 1540*44361Sborman argv[1]); 1541*44361Sborman return 0; 1542*44361Sborman } 1543*44361Sborman if (Ambiguous(c)) { 1544*44361Sborman fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 1545*44361Sborman argv[1]); 1546*44361Sborman return 0; 1547*44361Sborman } 1548*44361Sborman if (c->narg + 2 != argc) { 1549*44361Sborman fprintf(stderr, 1550*44361Sborman "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 1551*44361Sborman c->narg < argc + 2 ? "only " : "", 1552*44361Sborman c->narg, c->narg == 1 ? "" : "s", c->name); 1553*44361Sborman return 0; 1554*44361Sborman } 1555*44361Sborman (void)(*c->handler)(argv[2], argv[3]); 1556*44361Sborman return 1; 1557*44361Sborman } 1558*44361Sborman 1559*44361Sborman struct env_lst { 1560*44361Sborman struct env_lst *next; /* pointer to next structure */ 1561*44361Sborman struct env_lst *prev; /* pointer to next structure */ 1562*44361Sborman char *var; /* pointer to variable name */ 1563*44361Sborman char *value; /* pointer to varialbe value */ 1564*44361Sborman int export; /* 1 -> export with default list of variables */ 1565*44361Sborman }; 1566*44361Sborman 1567*44361Sborman struct env_lst envlisthead; 1568*44361Sborman 1569*44361Sborman struct env_lst * 1570*44361Sborman env_find(var) 1571*44361Sborman { 1572*44361Sborman register struct env_lst *ep; 1573*44361Sborman 1574*44361Sborman for (ep = envlisthead.next; ep; ep = ep->next) { 1575*44361Sborman if (strcmp(ep->var, var) == 0) 1576*44361Sborman return(ep); 1577*44361Sborman } 1578*44361Sborman return(NULL); 1579*44361Sborman } 1580*44361Sborman 1581*44361Sborman env_init() 1582*44361Sborman { 1583*44361Sborman extern char **environ, *index(); 1584*44361Sborman register char **epp, *cp; 1585*44361Sborman register struct env_lst *ep; 1586*44361Sborman 1587*44361Sborman for (epp = environ; *epp; epp++) { 1588*44361Sborman if (cp = index(*epp, '=')) { 1589*44361Sborman *cp = '\0'; 1590*44361Sborman ep = env_define(*epp, cp+1); 1591*44361Sborman ep->export = 0; 1592*44361Sborman *cp = '='; 1593*44361Sborman } 1594*44361Sborman } 1595*44361Sborman /* 1596*44361Sborman * Special case for DISPLAY variable. If it is ":0.0" or 1597*44361Sborman * "unix:0.0", we have to get rid of "unix" and insert our 1598*44361Sborman * hostname. 1599*44361Sborman */ 1600*44361Sborman if ((ep = env_find("DISPLAY")) && 1601*44361Sborman ((*ep->value == ':') || (strncmp(ep->value, "unix:", 5) == 0))) { 1602*44361Sborman char hbuf[256+1]; 1603*44361Sborman char *cp2 = index(ep->value, ':'); 1604*44361Sborman 1605*44361Sborman gethostname(hbuf, 256); 1606*44361Sborman hbuf[256] = '\0'; 1607*44361Sborman cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); 1608*44361Sborman sprintf(cp, "%s%s", hbuf, cp2); 1609*44361Sborman free(ep->value); 1610*44361Sborman ep->value = cp; 1611*44361Sborman } 1612*44361Sborman /* 1613*44361Sborman * If USER is not defined, but LOGNAME is, then add 1614*44361Sborman * USER with the value from LOGNAME. 1615*44361Sborman */ 1616*44361Sborman if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) 1617*44361Sborman env_define("USER", ep->value); 1618*44361Sborman env_export("USER"); 1619*44361Sborman env_export("DISPLAY"); 1620*44361Sborman env_export("PRINTER"); 1621*44361Sborman } 1622*44361Sborman 1623*44361Sborman struct env_lst * 1624*44361Sborman env_define(var, value) 1625*44361Sborman char *var, *value; 1626*44361Sborman { 1627*44361Sborman register struct env_lst *ep; 1628*44361Sborman extern char *savestr(); 1629*44361Sborman 1630*44361Sborman if (ep = env_find(var)) { 1631*44361Sborman if (ep->var) 1632*44361Sborman free(ep->var); 1633*44361Sborman if (ep->value) 1634*44361Sborman free(ep->value); 1635*44361Sborman } else { 1636*44361Sborman ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 1637*44361Sborman ep->export = 1; 1638*44361Sborman ep->next = envlisthead.next; 1639*44361Sborman envlisthead.next = ep; 1640*44361Sborman ep->prev = &envlisthead; 1641*44361Sborman if (ep->next) 1642*44361Sborman ep->next->prev = ep; 1643*44361Sborman } 1644*44361Sborman ep->var = savestr(var); 1645*44361Sborman ep->value = savestr(value); 1646*44361Sborman return(ep); 1647*44361Sborman } 1648*44361Sborman 1649*44361Sborman env_undefine(var) 1650*44361Sborman char *var; 1651*44361Sborman { 1652*44361Sborman register struct env_lst *ep; 1653*44361Sborman 1654*44361Sborman if (ep = env_find(var)) { 1655*44361Sborman ep->prev->next = ep->next; 1656*44361Sborman ep->next->prev = ep->prev; 1657*44361Sborman if (ep->var) 1658*44361Sborman free(ep->var); 1659*44361Sborman if (ep->value) 1660*44361Sborman free(ep->value); 1661*44361Sborman free(ep); 1662*44361Sborman } 1663*44361Sborman } 1664*44361Sborman 1665*44361Sborman env_export(var) 1666*44361Sborman char *var; 1667*44361Sborman { 1668*44361Sborman register struct env_lst *ep; 1669*44361Sborman 1670*44361Sborman if (ep = env_find(var)) 1671*44361Sborman ep->export = 1; 1672*44361Sborman } 1673*44361Sborman 1674*44361Sborman env_unexport(var) 1675*44361Sborman char *var; 1676*44361Sborman { 1677*44361Sborman register struct env_lst *ep; 1678*44361Sborman 1679*44361Sborman if (ep = env_find(var)) 1680*44361Sborman ep->export = 0; 1681*44361Sborman } 1682*44361Sborman 1683*44361Sborman env_list() 1684*44361Sborman { 1685*44361Sborman register struct env_lst *ep; 1686*44361Sborman 1687*44361Sborman for (ep = envlisthead.next; ep; ep = ep->next) { 1688*44361Sborman printf("%c %-20s %s\n", ep->export ? '*' : ' ', 1689*44361Sborman ep->var, ep->value); 1690*44361Sborman } 1691*44361Sborman } 1692*44361Sborman 1693*44361Sborman char * 1694*44361Sborman env_default(init) 1695*44361Sborman { 1696*44361Sborman static struct env_lst *nep = NULL; 1697*44361Sborman 1698*44361Sborman if (init) { 1699*44361Sborman nep = &envlisthead; 1700*44361Sborman return; 1701*44361Sborman } 1702*44361Sborman if (nep) { 1703*44361Sborman while (nep = nep->next) { 1704*44361Sborman if (nep->export) 1705*44361Sborman return(nep->var); 1706*44361Sborman } 1707*44361Sborman } 1708*44361Sborman return(NULL); 1709*44361Sborman } 1710*44361Sborman 1711*44361Sborman char * 1712*44361Sborman env_getvalue(var) 1713*44361Sborman char *var; 1714*44361Sborman { 1715*44361Sborman register struct env_lst *ep; 1716*44361Sborman 1717*44361Sborman if (ep = env_find(var)) 1718*44361Sborman return(ep->value); 1719*44361Sborman return(NULL); 1720*44361Sborman } 1721*44361Sborman 1722*44361Sborman char * 1723*44361Sborman savestr(s) 1724*44361Sborman register char *s; 1725*44361Sborman { 1726*44361Sborman register char *ret; 1727*44361Sborman if (ret = (char *)malloc(strlen(s)+1)) 1728*44361Sborman strcpy(ret, s); 1729*44361Sborman return(ret); 1730*44361Sborman } 1731*44361Sborman 173236274Sminshall #if defined(unix) 1733*44361Sborman #ifdef notdef 173432144Sminshall /* 173536274Sminshall * Some information about our file descriptors. 173636274Sminshall */ 173736274Sminshall 173836274Sminshall char * 173936274Sminshall decodeflags(mask) 174036274Sminshall int mask; 174136274Sminshall { 174236274Sminshall static char buffer[100]; 174336274Sminshall #define do(m,s) \ 174436274Sminshall if (mask&(m)) { \ 174536274Sminshall strcat(buffer, (s)); \ 174636274Sminshall } 174736274Sminshall 174836274Sminshall buffer[0] = 0; /* Terminate it */ 174936274Sminshall 175036274Sminshall #ifdef FREAD 175136274Sminshall do(FREAD, " FREAD"); 175236274Sminshall #endif 175336274Sminshall #ifdef FWRITE 175436274Sminshall do(FWRITE, " FWRITE"); 175536274Sminshall #endif 175636274Sminshall #ifdef F_DUPFP 175736274Sminshall do(F_DUPFD, " F_DUPFD"); 175836274Sminshall #endif 175936274Sminshall #ifdef FNDELAY 176036274Sminshall do(FNDELAY, " FNDELAY"); 176136274Sminshall #endif 176236274Sminshall #ifdef FAPPEND 176336274Sminshall do(FAPPEND, " FAPPEND"); 176436274Sminshall #endif 176536274Sminshall #ifdef FMARK 176636274Sminshall do(FMARK, " FMARK"); 176736274Sminshall #endif 176836274Sminshall #ifdef FDEFER 176936274Sminshall do(FDEFER, " FDEFER"); 177036274Sminshall #endif 177136274Sminshall #ifdef FASYNC 177236274Sminshall do(FASYNC, " FASYNC"); 177336274Sminshall #endif 177436274Sminshall #ifdef FSHLOCK 177536274Sminshall do(FSHLOCK, " FSHLOCK"); 177636274Sminshall #endif 177736274Sminshall #ifdef FEXLOCK 177836274Sminshall do(FEXLOCK, " FEXLOCK"); 177936274Sminshall #endif 178036274Sminshall #ifdef FCREAT 178136274Sminshall do(FCREAT, " FCREAT"); 178236274Sminshall #endif 178336274Sminshall #ifdef FTRUNC 178436274Sminshall do(FTRUNC, " FTRUNC"); 178536274Sminshall #endif 178636274Sminshall #ifdef FEXCL 178736274Sminshall do(FEXCL, " FEXCL"); 178836274Sminshall #endif 178936274Sminshall 179036274Sminshall return buffer; 179136274Sminshall } 179236274Sminshall #undef do 1793*44361Sborman #endif /* notdef */ 179436274Sminshall 1795*44361Sborman #if defined(TN3270) 179636274Sminshall static void 179736274Sminshall filestuff(fd) 179836274Sminshall int fd; 179936274Sminshall { 180036274Sminshall int res; 180136274Sminshall 180238689Sborman #ifdef F_GETOWN 180338689Sborman setconnmode(0); 180436274Sminshall res = fcntl(fd, F_GETOWN, 0); 180536274Sminshall setcommandmode(); 180636274Sminshall 180736274Sminshall if (res == -1) { 180836274Sminshall perror("fcntl"); 180936274Sminshall return; 181036274Sminshall } 181136274Sminshall printf("\tOwner is %d.\n", res); 181238689Sborman #endif 181336274Sminshall 181438689Sborman setconnmode(0); 181536274Sminshall res = fcntl(fd, F_GETFL, 0); 181636274Sminshall setcommandmode(); 181736274Sminshall 181836274Sminshall if (res == -1) { 181936274Sminshall perror("fcntl"); 182036274Sminshall return; 182136274Sminshall } 182236274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 182336274Sminshall } 1824*44361Sborman #endif /* defined(TN3270) */ 182536274Sminshall 182636274Sminshall 182736274Sminshall #endif /* defined(unix) */ 182836274Sminshall 182936274Sminshall /* 183032144Sminshall * Print status about the connection. 183132144Sminshall */ 183234849Sminshall /*ARGSUSED*/ 183332144Sminshall static 183432144Sminshall status(argc, argv) 183532144Sminshall int argc; 183632144Sminshall char *argv[]; 183732144Sminshall { 183832144Sminshall if (connected) { 183932144Sminshall printf("Connected to %s.\n", hostname); 184036242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 184138689Sborman int mode = getconnmode(); 184238689Sborman 184338689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 184438689Sborman printf("Operating with LINEMODE option\n"); 184538689Sborman printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 184638689Sborman printf("%s catching of signals\n", 184738689Sborman (mode&MODE_TRAPSIG) ? "Local" : "No"); 184838689Sborman slcstate(); 184938689Sborman #ifdef KLUDGELINEMODE 185039529Sborman } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 185138689Sborman printf("Operating in obsolete linemode\n"); 185238689Sborman #endif 185338689Sborman } else { 185438689Sborman printf("Operating in single character mode\n"); 185538689Sborman if (localchars) 185638689Sborman printf("Catching signals locally\n"); 185732144Sminshall } 185838689Sborman printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 185938689Sborman if (my_want_state_is_will(TELOPT_LFLOW)) 186038689Sborman printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 186132144Sminshall } 186232144Sminshall } else { 186332144Sminshall printf("No connection.\n"); 186432144Sminshall } 186532144Sminshall # if !defined(TN3270) 186632144Sminshall printf("Escape character is '%s'.\n", control(escape)); 186734849Sminshall (void) fflush(stdout); 186832144Sminshall # else /* !defined(TN3270) */ 186932144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 187032144Sminshall printf("Escape character is '%s'.\n", control(escape)); 187132144Sminshall } 187232144Sminshall # if defined(unix) 187336242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 187436242Sminshall printf("SIGIO received %d time%s.\n", 187536242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 187636274Sminshall if (In3270) { 187736274Sminshall printf("Process ID %d, process group %d.\n", 187836274Sminshall getpid(), getpgrp(getpid())); 187936274Sminshall printf("Terminal input:\n"); 188036274Sminshall filestuff(tin); 188136274Sminshall printf("Terminal output:\n"); 188236274Sminshall filestuff(tout); 188336274Sminshall printf("Network socket:\n"); 188436274Sminshall filestuff(net); 188536274Sminshall } 188636242Sminshall } 188732144Sminshall if (In3270 && transcom) { 188832144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 188932144Sminshall } 189032144Sminshall # endif /* defined(unix) */ 189134849Sminshall (void) fflush(stdout); 189232144Sminshall if (In3270) { 189332144Sminshall return 0; 189432144Sminshall } 189532144Sminshall # endif /* defined(TN3270) */ 189632144Sminshall return 1; 189732144Sminshall } 189832144Sminshall 189932144Sminshall 1900*44361Sborman #if defined(NEED_GETTOS) 1901*44361Sborman struct tosent { 1902*44361Sborman char *t_name; /* name */ 1903*44361Sborman char **t_aliases; /* alias list */ 1904*44361Sborman char *t_proto; /* protocol */ 1905*44361Sborman int t_tos; /* Type Of Service bits */ 1906*44361Sborman }; 1907*44361Sborman 1908*44361Sborman struct tosent * 1909*44361Sborman gettosbyname(name, proto) 1910*44361Sborman char *name, *proto; 1911*44361Sborman { 1912*44361Sborman static struct tosent te; 1913*44361Sborman static char *aliasp = 0; 1914*44361Sborman 1915*44361Sborman te.t_name = name; 1916*44361Sborman te.t_aliases = &aliasp; 1917*44361Sborman te.t_proto = proto; 1918*44361Sborman te.t_tos = 020; /* Low Delay bit */ 1919*44361Sborman return(&te); 1920*44361Sborman } 1921*44361Sborman #endif 1922*44361Sborman 192332144Sminshall int 192432144Sminshall tn(argc, argv) 192532144Sminshall int argc; 192632144Sminshall char *argv[]; 192732144Sminshall { 192832144Sminshall register struct hostent *host = 0; 192932144Sminshall struct sockaddr_in sin; 193032144Sminshall struct servent *sp = 0; 193132144Sminshall static char hnamebuf[32]; 193238689Sborman unsigned long temp, inet_addr(); 193337219Sminshall extern char *inet_ntoa(); 193438689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 193538689Sborman char *srp = 0, *strrchr(); 193638689Sborman unsigned long sourceroute(), srlen; 193738689Sborman #endif 1938*44361Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS) 193940245Sborman struct tosent *tp; 1940*44361Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */ 1941*44361Sborman char *cmd, *hostp = 0, *portp = 0, *user = 0; 194232144Sminshall 194332144Sminshall 194432144Sminshall if (connected) { 194532144Sminshall printf("?Already connected to %s\n", hostname); 194632144Sminshall return 0; 194732144Sminshall } 194832144Sminshall if (argc < 2) { 194932144Sminshall (void) strcpy(line, "Connect "); 195032144Sminshall printf("(to) "); 195134849Sminshall (void) gets(&line[strlen(line)]); 195232144Sminshall makeargv(); 195332144Sminshall argc = margc; 195432144Sminshall argv = margv; 195532144Sminshall } 1956*44361Sborman cmd = *argv; 1957*44361Sborman --argc; ++argv; 1958*44361Sborman while (argc) { 1959*44361Sborman if (strcmp(*argv, "-l") == 0) { 1960*44361Sborman --argc; ++argv; 1961*44361Sborman if (argc == 0) 1962*44361Sborman goto usage; 1963*44361Sborman user = *argv++; 1964*44361Sborman --argc; 1965*44361Sborman continue; 1966*44361Sborman } 1967*44361Sborman if (hostp == 0) { 1968*44361Sborman hostp = *argv++; 1969*44361Sborman --argc; 1970*44361Sborman continue; 1971*44361Sborman } 1972*44361Sborman if (portp == 0) { 1973*44361Sborman portp = *argv++; 1974*44361Sborman --argc; 1975*44361Sborman continue; 1976*44361Sborman } 1977*44361Sborman usage: 1978*44361Sborman printf("usage: %s [-l user] host-name [port]\n", cmd); 197932144Sminshall return 0; 198032144Sminshall } 198138689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 1982*44361Sborman if (hostp[0] == '@' || hostp[0] == '!') { 1983*44361Sborman if ((hostname = strrchr(hostp, ':')) == NULL) 1984*44361Sborman hostname = strrchr(hostp, '@'); 198538689Sborman hostname++; 198638689Sborman srp = 0; 1987*44361Sborman temp = sourceroute(hostp, &srp, &srlen); 198838689Sborman if (temp == 0) { 198938689Sborman herror(srp); 199038689Sborman return 0; 199138689Sborman } else if (temp == -1) { 1992*44361Sborman printf("Bad source route option: %s\n", hostp); 199338689Sborman return 0; 199438689Sborman } else { 199538689Sborman sin.sin_addr.s_addr = temp; 199638689Sborman sin.sin_family = AF_INET; 199738689Sborman } 199832144Sminshall } else { 199938689Sborman #endif 2000*44361Sborman temp = inet_addr(hostp); 200138689Sborman if (temp != (unsigned long) -1) { 200238689Sborman sin.sin_addr.s_addr = temp; 200338689Sborman sin.sin_family = AF_INET; 2004*44361Sborman (void) strcpy(hnamebuf, hostp); 200538689Sborman hostname = hnamebuf; 200638689Sborman } else { 2007*44361Sborman host = gethostbyname(hostp); 200838689Sborman if (host) { 200938689Sborman sin.sin_family = host->h_addrtype; 201032144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 201138689Sborman memcpy((caddr_t)&sin.sin_addr, 201232144Sminshall host->h_addr_list[0], host->h_length); 201332144Sminshall #else /* defined(h_addr) */ 201438689Sborman memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 201532144Sminshall #endif /* defined(h_addr) */ 201638689Sborman hostname = host->h_name; 201738689Sborman } else { 2018*44361Sborman herror(hostp); 201938689Sborman return 0; 202038689Sborman } 202132144Sminshall } 202238689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 202332144Sminshall } 202438689Sborman #endif 2025*44361Sborman if (portp) { 2026*44361Sborman if (*portp == '-') { 2027*44361Sborman portp++; 202838689Sborman telnetport = 1; 202938689Sborman } else 203038689Sborman telnetport = 0; 2031*44361Sborman sin.sin_port = atoi(portp); 203232144Sminshall if (sin.sin_port == 0) { 2033*44361Sborman sp = getservbyname(portp, "tcp"); 203432144Sminshall if (sp) 203532144Sminshall sin.sin_port = sp->s_port; 203632144Sminshall else { 2037*44361Sborman printf("%s: bad port number\n", portp); 203832144Sminshall return 0; 203932144Sminshall } 204032144Sminshall } else { 204134849Sminshall #if !defined(htons) 204234849Sminshall u_short htons(); 204334849Sminshall #endif /* !defined(htons) */ 204432144Sminshall sin.sin_port = htons(sin.sin_port); 204532144Sminshall } 204632144Sminshall } else { 204732144Sminshall if (sp == 0) { 204832144Sminshall sp = getservbyname("telnet", "tcp"); 204932144Sminshall if (sp == 0) { 205034849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 205132144Sminshall return 0; 205232144Sminshall } 205332144Sminshall sin.sin_port = sp->s_port; 205432144Sminshall } 205532144Sminshall telnetport = 1; 205632144Sminshall } 205737219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 205832144Sminshall do { 205932144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 206032144Sminshall if (net < 0) { 206132144Sminshall perror("telnet: socket"); 206232144Sminshall return 0; 206332144Sminshall } 206438689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 206538689Sborman if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) 206638689Sborman perror("setsockopt (IP_OPTIONS)"); 206738689Sborman #endif 2068*44361Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS) 2069*44361Sborman if ((tp = gettosbyname("telnet", "tcp")) && 2070*44361Sborman (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0)) 207140245Sborman perror("telnet: setsockopt TOS (ignored)"); 2072*44361Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */ 207340245Sborman 207432144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 207532144Sminshall perror("setsockopt (SO_DEBUG)"); 207632144Sminshall } 207732144Sminshall 207832144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 207932144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 208032144Sminshall if (host && host->h_addr_list[1]) { 208132144Sminshall int oerrno = errno; 208232144Sminshall 208332144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 208432144Sminshall inet_ntoa(sin.sin_addr)); 208532144Sminshall errno = oerrno; 208632144Sminshall perror((char *)0); 208732144Sminshall host->h_addr_list++; 208832144Sminshall memcpy((caddr_t)&sin.sin_addr, 208932144Sminshall host->h_addr_list[0], host->h_length); 209032144Sminshall (void) NetClose(net); 209132144Sminshall continue; 209232144Sminshall } 209332144Sminshall #endif /* defined(h_addr) */ 209432144Sminshall perror("telnet: Unable to connect to remote host"); 209532144Sminshall return 0; 209637219Sminshall } 209732144Sminshall connected++; 209832144Sminshall } while (connected == 0); 2099*44361Sborman cmdrc(hostp, hostname); 2100*44361Sborman if (user) 2101*44361Sborman env_define("USER", user); 210234849Sminshall (void) call(status, "status", "notmuch", 0); 210332144Sminshall if (setjmp(peerdied) == 0) 210432144Sminshall telnet(); 210534849Sminshall (void) NetClose(net); 210632381Sminshall ExitString("Connection closed by foreign host.\n",1); 210732144Sminshall /*NOTREACHED*/ 210832144Sminshall } 210932144Sminshall 211032144Sminshall 211132144Sminshall #define HELPINDENT (sizeof ("connect")) 211232144Sminshall 211332144Sminshall static char 211432144Sminshall openhelp[] = "connect to a site", 211532144Sminshall closehelp[] = "close current connection", 211632144Sminshall quithelp[] = "exit telnet", 211732144Sminshall statushelp[] = "print status information", 211832144Sminshall helphelp[] = "print help information", 211932144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 212032144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 212138689Sborman unsethelp[] = "unset operating parameters ('unset ?' for more)", 212232144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 212338689Sborman slchelp[] = "change state of special charaters ('slc ?' for more)", 212432144Sminshall displayhelp[] = "display operating parameters", 212532144Sminshall #if defined(TN3270) && defined(unix) 212632144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 212732144Sminshall #endif /* defined(TN3270) && defined(unix) */ 212832144Sminshall #if defined(unix) 212932144Sminshall zhelp[] = "suspend telnet", 213043317Skfall #endif /* defined(unix) */ 213132144Sminshall shellhelp[] = "invoke a subshell", 2132*44361Sborman envhelp[] = "change environment variables ('environ ?' for more)", 2133*44361Sborman modestring[] = "try to enter line or character mode ('mode ?' for more)"; 213432144Sminshall 213532144Sminshall extern int help(), shell(); 213632144Sminshall 213732144Sminshall static Command cmdtab[] = { 213838689Sborman { "close", closehelp, bye, 1 }, 213938689Sborman { "display", displayhelp, display, 0 }, 214038689Sborman { "mode", modestring, modecmd, 0 }, 214138689Sborman { "open", openhelp, tn, 0 }, 214238689Sborman { "quit", quithelp, quit, 0 }, 214338689Sborman { "send", sendhelp, sendcmd, 0 }, 214438689Sborman { "set", sethelp, setcmd, 0 }, 214538689Sborman { "unset", unsethelp, unsetcmd, 0 }, 214638689Sborman { "status", statushelp, status, 0 }, 214738689Sborman { "toggle", togglestring, toggle, 0 }, 214838689Sborman { "slc", slchelp, slccmd, 0 }, 214932144Sminshall #if defined(TN3270) && defined(unix) 215038689Sborman { "transcom", transcomhelp, settranscom, 0 }, 215132144Sminshall #endif /* defined(TN3270) && defined(unix) */ 215232144Sminshall #if defined(unix) 215338689Sborman { "z", zhelp, suspend, 0 }, 215432144Sminshall #endif /* defined(unix) */ 215532144Sminshall #if defined(TN3270) 215638689Sborman { "!", shellhelp, shell, 1 }, 215738689Sborman #else 215838689Sborman { "!", shellhelp, shell, 0 }, 215938689Sborman #endif 2160*44361Sborman { "environ", envhelp, env_cmd, 0 }, 216138689Sborman { "?", helphelp, help, 0 }, 216232144Sminshall 0 216332144Sminshall }; 216432144Sminshall 216532144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 216632144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 216732144Sminshall 216832144Sminshall static Command cmdtab2[] = { 216938689Sborman { "help", 0, help, 0 }, 217038689Sborman { "escape", escapehelp, setescape, 0 }, 217138689Sborman { "crmod", crmodhelp, togcrmod, 0 }, 217232144Sminshall 0 217332144Sminshall }; 217432144Sminshall 217535298Sminshall 217632144Sminshall /* 217732144Sminshall * Call routine with argc, argv set from args (terminated by 0). 217832144Sminshall */ 217935298Sminshall 218035417Sminshall /*VARARGS1*/ 218132144Sminshall static 218235298Sminshall call(va_alist) 218335298Sminshall va_dcl 218432144Sminshall { 218535298Sminshall va_list ap; 218635298Sminshall typedef int (*intrtn_t)(); 218735298Sminshall intrtn_t routine; 218835298Sminshall char *args[100]; 218935298Sminshall int argno = 0; 219035298Sminshall 219135298Sminshall va_start(ap); 219235298Sminshall routine = (va_arg(ap, intrtn_t)); 219335495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 219435298Sminshall ; 219535495Sminshall } 219635298Sminshall va_end(ap); 219735495Sminshall return (*routine)(argno-1, args); 219832144Sminshall } 219932144Sminshall 220035298Sminshall 220132144Sminshall static char ** 220232144Sminshall getnextcmd(name) 220332144Sminshall char *name; 220432144Sminshall { 220532144Sminshall Command *c = (Command *) name; 220632144Sminshall 220732144Sminshall return (char **) (c+1); 220832144Sminshall } 220932144Sminshall 221032144Sminshall static Command * 221132144Sminshall getcmd(name) 221232144Sminshall char *name; 221332144Sminshall { 221432144Sminshall Command *cm; 221532144Sminshall 221632144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 221732144Sminshall return cm; 221832144Sminshall } else { 221932144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 222032144Sminshall } 222132144Sminshall } 222232144Sminshall 222332144Sminshall void 222438689Sborman command(top, tbuf, cnt) 222532144Sminshall int top; 222638689Sborman char *tbuf; 222738689Sborman int cnt; 222832144Sminshall { 222932144Sminshall register Command *c; 223032144Sminshall 223132144Sminshall setcommandmode(); 223232144Sminshall if (!top) { 223332144Sminshall putchar('\n'); 223437219Sminshall #if defined(unix) 223532144Sminshall } else { 2236*44361Sborman (void) signal(SIGINT, SIG_DFL); 2237*44361Sborman (void) signal(SIGQUIT, SIG_DFL); 223832144Sminshall #endif /* defined(unix) */ 223932144Sminshall } 224032144Sminshall for (;;) { 224132144Sminshall printf("%s> ", prompt); 224238689Sborman if (tbuf) { 224338689Sborman register char *cp; 224438689Sborman cp = line; 224538689Sborman while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 224638689Sborman cnt--; 224738689Sborman tbuf = 0; 224838689Sborman if (cp == line || *--cp != '\n' || cp == line) 224938689Sborman goto getline; 225038689Sborman *cp = '\0'; 225138689Sborman printf("%s\n", line); 225238689Sborman } else { 225338689Sborman getline: 225438689Sborman if (gets(line) == NULL) { 2255*44361Sborman if (feof(stdin) || ferror(stdin)) { 2256*44361Sborman (void) quit(); 2257*44361Sborman /*NOTREACHED*/ 2258*44361Sborman } 225938689Sborman break; 226038689Sborman } 226132144Sminshall } 226232144Sminshall if (line[0] == 0) 226332144Sminshall break; 226432144Sminshall makeargv(); 226537219Sminshall if (margv[0] == 0) { 226637219Sminshall break; 226737219Sminshall } 226832144Sminshall c = getcmd(margv[0]); 226932144Sminshall if (Ambiguous(c)) { 227032144Sminshall printf("?Ambiguous command\n"); 227132144Sminshall continue; 227232144Sminshall } 227332144Sminshall if (c == 0) { 227432144Sminshall printf("?Invalid command\n"); 227532144Sminshall continue; 227632144Sminshall } 227732144Sminshall if (c->needconnect && !connected) { 227832144Sminshall printf("?Need to be connected first.\n"); 227932144Sminshall continue; 228032144Sminshall } 228132144Sminshall if ((*c->handler)(margc, margv)) { 228232144Sminshall break; 228332144Sminshall } 228432144Sminshall } 228532144Sminshall if (!top) { 228632144Sminshall if (!connected) { 228732144Sminshall longjmp(toplevel, 1); 228832144Sminshall /*NOTREACHED*/ 228932144Sminshall } 229032144Sminshall #if defined(TN3270) 229132144Sminshall if (shell_active == 0) { 229238689Sborman setconnmode(0); 229332144Sminshall } 229432144Sminshall #else /* defined(TN3270) */ 229538689Sborman setconnmode(0); 229632144Sminshall #endif /* defined(TN3270) */ 229732144Sminshall } 229832144Sminshall } 229932144Sminshall 230032144Sminshall /* 230132144Sminshall * Help command. 230232144Sminshall */ 230332144Sminshall static 230432144Sminshall help(argc, argv) 230532144Sminshall int argc; 230632144Sminshall char *argv[]; 230732144Sminshall { 230832144Sminshall register Command *c; 230932144Sminshall 231032144Sminshall if (argc == 1) { 231132144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 231232144Sminshall for (c = cmdtab; c->name; c++) 231338689Sborman if (c->help) { 231432144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 231532144Sminshall c->help); 231632144Sminshall } 231732144Sminshall return 0; 231832144Sminshall } 231932144Sminshall while (--argc > 0) { 232032144Sminshall register char *arg; 232132144Sminshall arg = *++argv; 232232144Sminshall c = getcmd(arg); 232332144Sminshall if (Ambiguous(c)) 232432144Sminshall printf("?Ambiguous help command %s\n", arg); 232532144Sminshall else if (c == (Command *)0) 232632144Sminshall printf("?Invalid help command %s\n", arg); 232732144Sminshall else 232832144Sminshall printf("%s\n", c->help); 232932144Sminshall } 233032144Sminshall return 0; 233132144Sminshall } 233238689Sborman 233338689Sborman static char *rcname = 0; 233438689Sborman static char rcbuf[128]; 233538689Sborman 233638689Sborman cmdrc(m1, m2) 233738689Sborman char *m1, *m2; 233838689Sborman { 233938689Sborman register Command *c; 234038689Sborman FILE *rcfile; 234138689Sborman int gotmachine = 0; 234238689Sborman int l1 = strlen(m1); 234338689Sborman int l2 = strlen(m2); 234438689Sborman char m1save[64]; 234538689Sborman 234638689Sborman strcpy(m1save, m1); 234738689Sborman m1 = m1save; 234838689Sborman 234938689Sborman if (rcname == 0) { 235038689Sborman rcname = getenv("HOME"); 235138689Sborman if (rcname) 235238689Sborman strcpy(rcbuf, rcname); 235338689Sborman else 235438689Sborman rcbuf[0] = '\0'; 235538689Sborman strcat(rcbuf, "/.telnetrc"); 235638689Sborman rcname = rcbuf; 235738689Sborman } 235838689Sborman 235938689Sborman if ((rcfile = fopen(rcname, "r")) == 0) { 236038689Sborman return; 236138689Sborman } 236238689Sborman 236338689Sborman for (;;) { 236438689Sborman if (fgets(line, sizeof(line), rcfile) == NULL) 236538689Sborman break; 236638689Sborman if (line[0] == 0) 236738689Sborman break; 236838689Sborman if (line[0] == '#') 236938689Sborman continue; 237038689Sborman if (gotmachine == 0) { 237138689Sborman if (isspace(line[0])) 237238689Sborman continue; 237338689Sborman if (strncasecmp(line, m1, l1) == 0) 237438689Sborman strncpy(line, &line[l1], sizeof(line) - l1); 237538689Sborman else if (strncasecmp(line, m2, l2) == 0) 237638689Sborman strncpy(line, &line[l2], sizeof(line) - l2); 237738689Sborman else 237838689Sborman continue; 237938689Sborman gotmachine = 1; 238038689Sborman } else { 238138689Sborman if (!isspace(line[0])) { 238238689Sborman gotmachine = 0; 238338689Sborman continue; 238438689Sborman } 238538689Sborman } 238638689Sborman makeargv(); 238738689Sborman if (margv[0] == 0) 238838689Sborman continue; 238938689Sborman c = getcmd(margv[0]); 239038689Sborman if (Ambiguous(c)) { 239138689Sborman printf("?Ambiguous command: %s\n", margv[0]); 239238689Sborman continue; 239338689Sborman } 239438689Sborman if (c == 0) { 239538689Sborman printf("?Invalid command: %s\n", margv[0]); 239638689Sborman continue; 239738689Sborman } 239838689Sborman /* 239938689Sborman * This should never happen... 240038689Sborman */ 240138689Sborman if (c->needconnect && !connected) { 240238689Sborman printf("?Need to be connected first for %s.\n", margv[0]); 240338689Sborman continue; 240438689Sborman } 240538689Sborman (*c->handler)(margc, margv); 240638689Sborman } 240738689Sborman fclose(rcfile); 240838689Sborman } 240938689Sborman 241038689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 241138689Sborman 241238689Sborman /* 241338689Sborman * Source route is handed in as 241438689Sborman * [!]@hop1@hop2...[@|:]dst 241538689Sborman * If the leading ! is present, it is a 241638689Sborman * strict source route, otherwise it is 241738689Sborman * assmed to be a loose source route. 241838689Sborman * 241938689Sborman * We fill in the source route option as 242038689Sborman * hop1,hop2,hop3...dest 242138689Sborman * and return a pointer to hop1, which will 242238689Sborman * be the address to connect() to. 242338689Sborman * 242438689Sborman * Arguments: 242538689Sborman * arg: pointer to route list to decipher 242638689Sborman * 242738689Sborman * cpp: If *cpp is not equal to NULL, this is a 242838689Sborman * pointer to a pointer to a character array 242938689Sborman * that should be filled in with the option. 243038689Sborman * 243138689Sborman * lenp: pointer to an integer that contains the 243238689Sborman * length of *cpp if *cpp != NULL. 243338689Sborman * 243438689Sborman * Return values: 243538689Sborman * 243638689Sborman * Returns the address of the host to connect to. If the 243738689Sborman * return value is -1, there was a syntax error in the 243838689Sborman * option, either unknown characters, or too many hosts. 243938689Sborman * If the return value is 0, one of the hostnames in the 244038689Sborman * path is unknown, and *cpp is set to point to the bad 244138689Sborman * hostname. 244238689Sborman * 244338689Sborman * *cpp: If *cpp was equal to NULL, it will be filled 244438689Sborman * in with a pointer to our static area that has 244538689Sborman * the option filled in. This will be 32bit aligned. 244638689Sborman * 244738689Sborman * *lenp: This will be filled in with how long the option 244838689Sborman * pointed to by *cpp is. 244938689Sborman * 245038689Sborman */ 245138689Sborman unsigned long 245238689Sborman sourceroute(arg, cpp, lenp) 245338689Sborman char *arg; 245438689Sborman char **cpp; 245538689Sborman int *lenp; 245638689Sborman { 245738689Sborman static char lsr[44]; 245838689Sborman char *cp, *cp2, *lsrp, *lsrep, *index(); 245938689Sborman register int tmp; 246038689Sborman struct in_addr sin_addr; 246138689Sborman register struct hostent *host = 0; 246238689Sborman register char c; 246338689Sborman 246438689Sborman /* 246538689Sborman * Verify the arguments, and make sure we have 246638689Sborman * at least 7 bytes for the option. 246738689Sborman */ 246838689Sborman if (cpp == NULL || lenp == NULL) 246938689Sborman return((unsigned long)-1); 247038689Sborman if (*cpp != NULL && *lenp < 7) 247138689Sborman return((unsigned long)-1); 247238689Sborman /* 247338689Sborman * Decide whether we have a buffer passed to us, 247438689Sborman * or if we need to use our own static buffer. 247538689Sborman */ 247638689Sborman if (*cpp) { 247738689Sborman lsrp = *cpp; 247838689Sborman lsrep = lsrp + *lenp; 247938689Sborman } else { 248038689Sborman *cpp = lsrp = lsr; 248138689Sborman lsrep = lsrp + 44; 248238689Sborman } 248338689Sborman 248438689Sborman cp = arg; 248538689Sborman 248638689Sborman /* 248738689Sborman * Next, decide whether we have a loose source 248838689Sborman * route or a strict source route, and fill in 248938689Sborman * the begining of the option. 249038689Sborman */ 249138689Sborman if (*cp == '!') { 249238689Sborman cp++; 249338689Sborman *lsrp++ = IPOPT_SSRR; 249438689Sborman } else 249538689Sborman *lsrp++ = IPOPT_LSRR; 249638689Sborman 249738689Sborman if (*cp != '@') 249838689Sborman return((unsigned long)-1); 249938689Sborman 250038689Sborman lsrp++; /* skip over length, we'll fill it in later */ 250138689Sborman *lsrp++ = 4; 250238689Sborman 250338689Sborman cp++; 250438689Sborman 250538689Sborman sin_addr.s_addr = 0; 250638689Sborman 250738689Sborman for (c = 0;;) { 250838689Sborman if (c == ':') 250938689Sborman cp2 = 0; 251038689Sborman else for (cp2 = cp; c = *cp2; cp2++) { 251138689Sborman if (c == ',') { 251238689Sborman *cp2++ = '\0'; 251338689Sborman if (*cp2 == '@') 251438689Sborman cp2++; 251538689Sborman } else if (c == '@') { 251638689Sborman *cp2++ = '\0'; 251738689Sborman } else if (c == ':') { 251838689Sborman *cp2++ = '\0'; 251938689Sborman } else 252038689Sborman continue; 252138689Sborman break; 252238689Sborman } 252338689Sborman if (!c) 252438689Sborman cp2 = 0; 252538689Sborman 252638689Sborman if ((tmp = inet_addr(cp)) != -1) { 252738689Sborman sin_addr.s_addr = tmp; 252838689Sborman } else if (host = gethostbyname(cp)) { 252938689Sborman #if defined(h_addr) 253038689Sborman memcpy((caddr_t)&sin_addr, 253138689Sborman host->h_addr_list[0], host->h_length); 253238689Sborman #else 253338689Sborman memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); 253438689Sborman #endif 253538689Sborman } else { 253638689Sborman *cpp = cp; 253738689Sborman return(0); 253838689Sborman } 253938689Sborman memcpy(lsrp, (char *)&sin_addr, 4); 254038689Sborman lsrp += 4; 254138689Sborman if (cp2) 254238689Sborman cp = cp2; 254338689Sborman else 254438689Sborman break; 254538689Sborman /* 254638689Sborman * Check to make sure there is space for next address 254738689Sborman */ 254838689Sborman if (lsrp + 4 > lsrep) 254938689Sborman return((unsigned long)-1); 255038689Sborman } 255138689Sborman if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 255238689Sborman *cpp = 0; 255338689Sborman *lenp = 0; 255438689Sborman return((unsigned long)-1); 255538689Sborman } 255638689Sborman *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 255738689Sborman *lenp = lsrp - *cpp; 255838689Sborman return(sin_addr.s_addr); 255938689Sborman } 256038689Sborman #endif 256138689Sborman 256238909Sborman #if defined(NOSTRNCASECMP) 256338689Sborman strncasecmp(p1, p2, len) 256438689Sborman register char *p1, *p2; 256538689Sborman int len; 256638689Sborman { 256738689Sborman while (len--) { 256838689Sborman if (tolower(*p1) != tolower(*p2)) 256938689Sborman return(tolower(*p1) - tolower(*p2)); 257038689Sborman if (*p1 == '\0') 257138689Sborman return(0); 257238689Sborman p1++, p2++; 257338689Sborman } 257438689Sborman return(0); 257538689Sborman } 257638689Sborman #endif 2577