133685Sbostic /* 233685Sbostic * Copyright (c) 1988 Regents of the University of California. 333685Sbostic * All rights reserved. 433685Sbostic * 533685Sbostic * Redistribution and use in source and binary forms are permitted 634898Sbostic * provided that the above copyright notice and this paragraph are 734898Sbostic * duplicated in all such forms and that any documentation, 834898Sbostic * advertising materials, and other materials related to such 934898Sbostic * distribution and use acknowledge that the software was developed 1034898Sbostic * by the University of California, Berkeley. The name of the 1134898Sbostic * University may not be used to endorse or promote products derived 1234898Sbostic * from this software without specific prior written permission. 1334898Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434898Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534898Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1633685Sbostic */ 1733685Sbostic 1833685Sbostic #ifndef lint 19*38689Sborman static char sccsid[] = "@(#)commands.c 1.19 (Berkeley) 08/21/89"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2232144Sminshall #include <sys/types.h> 2336274Sminshall #if defined(unix) 2436274Sminshall #include <sys/file.h> 2536274Sminshall #endif /* defined(unix) */ 2632144Sminshall #include <sys/socket.h> 2732144Sminshall #include <netinet/in.h> 28*38689Sborman #ifdef CRAY 29*38689Sborman #include <sys/fcntl.h> 30*38689Sborman #endif CRAY 3132144Sminshall 3232144Sminshall #include <signal.h> 3332144Sminshall #include <netdb.h> 3432144Sminshall #include <ctype.h> 3535298Sminshall #include <varargs.h> 3632144Sminshall 3732144Sminshall #include <arpa/telnet.h> 3832144Sminshall 3934305Sminshall #include "general.h" 4034305Sminshall 4132381Sminshall #include "ring.h" 4232381Sminshall 4332144Sminshall #include "externs.h" 4432144Sminshall #include "defines.h" 4532144Sminshall #include "types.h" 4632144Sminshall 47*38689Sborman #ifdef SRCRT 48*38689Sborman #if !defined(CRAY) 49*38689Sborman #include <netinet/in_systm.h> 50*38689Sborman #if !defined(sun) 51*38689Sborman #include <machine/endian.h> 52*38689Sborman #endif 53*38689Sborman #endif 54*38689Sborman #include <netinet/ip.h> 55*38689Sborman #endif 56*38689Sborman 57*38689Sborman 5832144Sminshall char *hostname; 59*38689Sborman extern char *getenv(); 6032144Sminshall 6136180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 6232144Sminshall static char *ambiguous; /* special return value for command routines */ 6332144Sminshall 6432144Sminshall typedef struct { 6532144Sminshall char *name; /* command name */ 66*38689Sborman char *help; /* help string (NULL for no help) */ 6732144Sminshall int (*handler)(); /* routine which executes command */ 6832144Sminshall int needconnect; /* Do we need to be connected to execute? */ 6932144Sminshall } Command; 7032144Sminshall 71*38689Sborman static char line[256]; 72*38689Sborman static char saveline[256]; 7332144Sminshall static int margc; 7432144Sminshall static char *margv[20]; 7532144Sminshall 7632144Sminshall /* 7732144Sminshall * Various utility routines. 7832144Sminshall */ 7932144Sminshall 8036180Sminshall #if !defined(BSD) || (BSD <= 43) 8136180Sminshall 8236180Sminshall char *h_errlist[] = { 8336180Sminshall "Error 0", 8436180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 8536180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 8636180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 8736180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 8836180Sminshall }; 8936180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 9036180Sminshall 9136274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 9236180Sminshall 9336180Sminshall /* 9436180Sminshall * herror -- 9536180Sminshall * print the error indicated by the h_errno value. 9636180Sminshall */ 9736180Sminshall herror(s) 9836180Sminshall char *s; 9936180Sminshall { 10036180Sminshall if (s && *s) { 10136180Sminshall fprintf(stderr, "%s: ", s); 10236180Sminshall } 10336180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 10436180Sminshall fprintf(stderr, "Unknown error\n"); 10536274Sminshall } else if (h_errno == 0) { 10636274Sminshall #if defined(sun) 10736274Sminshall fprintf(stderr, "Host unknown\n"); 10836274Sminshall #endif /* defined(sun) */ 10936180Sminshall } else { 11036180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 11136180Sminshall } 11236180Sminshall } 11336180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 11436180Sminshall 11532144Sminshall static void 11632144Sminshall makeargv() 11732144Sminshall { 11832144Sminshall register char *cp; 11932144Sminshall register char **argp = margv; 12032144Sminshall 12132144Sminshall margc = 0; 12232144Sminshall cp = line; 12332144Sminshall if (*cp == '!') { /* Special case shell escape */ 124*38689Sborman strcpy(saveline, line); /* save for shell command */ 12532144Sminshall *argp++ = "!"; /* No room in string to get this */ 12632144Sminshall margc++; 12732144Sminshall cp++; 12832144Sminshall } 12932144Sminshall while (*cp) { 13032144Sminshall while (isspace(*cp)) 13132144Sminshall cp++; 13232144Sminshall if (*cp == '\0') 13332144Sminshall break; 13432144Sminshall *argp++ = cp; 13532144Sminshall margc += 1; 13632144Sminshall while (*cp != '\0' && !isspace(*cp)) 13732144Sminshall cp++; 13832144Sminshall if (*cp == '\0') 13932144Sminshall break; 14032144Sminshall *cp++ = '\0'; 14132144Sminshall } 14232144Sminshall *argp++ = 0; 14332144Sminshall } 14432144Sminshall 14532144Sminshall 14632144Sminshall static char ** 14732144Sminshall genget(name, table, next) 14832144Sminshall char *name; /* name to match */ 14932144Sminshall char **table; /* name entry in table */ 15032144Sminshall char **(*next)(); /* routine to return next entry in table */ 15132144Sminshall { 15232144Sminshall register char *p, *q; 15332144Sminshall register char **c, **found; 15432144Sminshall register int nmatches, longest; 15532144Sminshall 15632144Sminshall if (name == 0) { 15732144Sminshall return 0; 15832144Sminshall } 15932144Sminshall longest = 0; 16032144Sminshall nmatches = 0; 16132144Sminshall found = 0; 16232144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 16332144Sminshall for (q = name; 16432144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 16532144Sminshall if (*q == 0) /* exact match? */ 16632144Sminshall return (c); 16732144Sminshall if (!*q) { /* the name was a prefix */ 16832144Sminshall if (q - name > longest) { 16932144Sminshall longest = q - name; 17032144Sminshall nmatches = 1; 17132144Sminshall found = c; 17232144Sminshall } else if (q - name == longest) 17332144Sminshall nmatches++; 17432144Sminshall } 17532144Sminshall } 17632144Sminshall if (nmatches > 1) 17736180Sminshall return &ambiguous; 17832144Sminshall return (found); 17932144Sminshall } 18032144Sminshall 18132144Sminshall /* 18232144Sminshall * Make a character string into a number. 18332144Sminshall * 18432144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 18532144Sminshall */ 18632144Sminshall 18732144Sminshall static 18832144Sminshall special(s) 18932144Sminshall register char *s; 19032144Sminshall { 19132144Sminshall register char c; 19232144Sminshall char b; 19332144Sminshall 19432144Sminshall switch (*s) { 19532144Sminshall case '^': 19632144Sminshall b = *++s; 19732144Sminshall if (b == '?') { 19832144Sminshall c = b | 0x40; /* DEL */ 19932144Sminshall } else { 20032144Sminshall c = b & 0x1f; 20132144Sminshall } 20232144Sminshall break; 20332144Sminshall default: 20432144Sminshall c = *s; 20532144Sminshall break; 20632144Sminshall } 20732144Sminshall return c; 20832144Sminshall } 20932144Sminshall 21032144Sminshall /* 21132144Sminshall * Construct a control character sequence 21232144Sminshall * for a special character. 21332144Sminshall */ 21432144Sminshall static char * 21532144Sminshall control(c) 21632144Sminshall register int c; 21732144Sminshall { 21832144Sminshall static char buf[3]; 21932144Sminshall 22032144Sminshall if (c == 0x7f) 22132144Sminshall return ("^?"); 22232144Sminshall if (c == '\377') { 22332144Sminshall return "off"; 22432144Sminshall } 22532144Sminshall if (c >= 0x20) { 22632144Sminshall buf[0] = c; 22732144Sminshall buf[1] = 0; 22832144Sminshall } else { 22932144Sminshall buf[0] = '^'; 23032144Sminshall buf[1] = '@'+c; 23132144Sminshall buf[2] = 0; 23232144Sminshall } 23332144Sminshall return (buf); 23432144Sminshall } 23532144Sminshall 23632144Sminshall 23732144Sminshall 23832144Sminshall /* 23932144Sminshall * The following are data structures and routines for 24032144Sminshall * the "send" command. 24132144Sminshall * 24232144Sminshall */ 24332144Sminshall 24432144Sminshall struct sendlist { 24532144Sminshall char *name; /* How user refers to it (case independent) */ 24632144Sminshall char *help; /* Help information (0 ==> no help) */ 24732144Sminshall #if defined(NOT43) 248*38689Sborman int (*handler)(); /* Routine to perform (for special ops) */ 24932144Sminshall #else /* defined(NOT43) */ 250*38689Sborman void (*handler)(); /* Routine to perform (for special ops) */ 25132144Sminshall #endif /* defined(NOT43) */ 252*38689Sborman int what; /* Character to be sent (<0 ==> special) */ 25332144Sminshall }; 25432144Sminshall 25532144Sminshall #define SENDQUESTION -1 25632144Sminshall #define SENDESCAPE -3 25732144Sminshall 25832144Sminshall static struct sendlist Sendlist[] = { 259*38689Sborman { "ao", "Send Telnet Abort output", 0, AO }, 260*38689Sborman { "ayt", "Send Telnet 'Are You There'", 0, AYT }, 261*38689Sborman { "brk", "Send Telnet Break", 0, BREAK }, 262*38689Sborman { "ec", "Send Telnet Erase Character", 0, EC }, 263*38689Sborman { "el", "Send Telnet Erase Line", 0, EL }, 264*38689Sborman { "escape", "Send current escape character", 0, SENDESCAPE }, 265*38689Sborman { "ga", "Send Telnet 'Go Ahead' sequence", 0, GA }, 266*38689Sborman { "ip", "Send Telnet Interrupt Process", 0, IP }, 267*38689Sborman { "nop", "Send Telnet 'No operation'", 0, NOP }, 268*38689Sborman { "eor", "Send Telnet 'End of Record'", 0, EOR }, 269*38689Sborman { "abort", "Send Telnet 'Abort Process'", 0, ABORT }, 270*38689Sborman { "susp", "Send Telnet 'Suspend Process'", 0, SUSP }, 271*38689Sborman { "eof", "Send Telnet End of File Character", 0, xEOF }, 272*38689Sborman { "synch", "Perform Telnet 'Synch operation'", dosynch, SYNCH }, 273*38689Sborman { "?", "Display send options", 0, SENDQUESTION }, 27432144Sminshall { 0 } 27532144Sminshall }; 27632144Sminshall 27732144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 278*38689Sborman { "break", 0, 0, BREAK }, 27932144Sminshall 280*38689Sborman { "intp", 0, 0, IP }, 281*38689Sborman { "interrupt", 0, 0, IP }, 282*38689Sborman { "intr", 0, 0, IP }, 28332144Sminshall 284*38689Sborman { "help", 0, 0, SENDQUESTION }, 28532144Sminshall 286*38689Sborman { 0 } 28732144Sminshall }; 28832144Sminshall 28932144Sminshall static char ** 29032144Sminshall getnextsend(name) 29132144Sminshall char *name; 29232144Sminshall { 29332144Sminshall struct sendlist *c = (struct sendlist *) name; 29432144Sminshall 29532144Sminshall return (char **) (c+1); 29632144Sminshall } 29732144Sminshall 29832144Sminshall static struct sendlist * 29932144Sminshall getsend(name) 30032144Sminshall char *name; 30132144Sminshall { 30232144Sminshall struct sendlist *sl; 30332144Sminshall 30432144Sminshall if ((sl = (struct sendlist *) 30532144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 30632144Sminshall return sl; 30732144Sminshall } else { 30832144Sminshall return (struct sendlist *) 30932144Sminshall genget(name, (char **) Sendlist2, getnextsend); 31032144Sminshall } 31132144Sminshall } 31232144Sminshall 31332144Sminshall static 31432144Sminshall sendcmd(argc, argv) 31532144Sminshall int argc; 31632144Sminshall char **argv; 31732144Sminshall { 31832144Sminshall int what; /* what we are sending this time */ 31932144Sminshall int count; /* how many bytes we are going to need to send */ 32032144Sminshall int i; 32132144Sminshall int question = 0; /* was at least one argument a question */ 32232144Sminshall struct sendlist *s; /* pointer to current command */ 32332144Sminshall 32432144Sminshall if (argc < 2) { 32532144Sminshall printf("need at least one argument for 'send' command\n"); 32632144Sminshall printf("'send ?' for help\n"); 32732144Sminshall return 0; 32832144Sminshall } 32932144Sminshall /* 33032144Sminshall * First, validate all the send arguments. 33132144Sminshall * In addition, we see how much space we are going to need, and 33232144Sminshall * whether or not we will be doing a "SYNCH" operation (which 33332144Sminshall * flushes the network queue). 33432144Sminshall */ 33532144Sminshall count = 0; 33632144Sminshall for (i = 1; i < argc; i++) { 33732144Sminshall s = getsend(argv[i]); 33832144Sminshall if (s == 0) { 33932144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 34032144Sminshall argv[i]); 34132144Sminshall return 0; 34232144Sminshall } else if (Ambiguous(s)) { 34332144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 34432144Sminshall argv[i]); 34532144Sminshall return 0; 34632144Sminshall } 34732144Sminshall switch (s->what) { 34832144Sminshall case SENDQUESTION: 349*38689Sborman question = 1; 35032144Sminshall break; 35132144Sminshall case SENDESCAPE: 35232144Sminshall count += 1; 35332144Sminshall break; 35432144Sminshall case SYNCH: 35532144Sminshall count += 2; 35632144Sminshall break; 35732144Sminshall default: 35832144Sminshall count += 2; 35932144Sminshall break; 36032144Sminshall } 36132144Sminshall } 362*38689Sborman if (!connected) { 363*38689Sborman if (count) 364*38689Sborman printf("?Need to be connected first.\n"); 365*38689Sborman if (question) { 366*38689Sborman for (s = Sendlist; s->name; s++) 367*38689Sborman if (s->help) 368*38689Sborman printf("%-15s %s\n", s->name, s->help); 369*38689Sborman } else 370*38689Sborman printf("'send ?' for help\n"); 371*38689Sborman return !question; 372*38689Sborman } 37332144Sminshall /* Now, do we have enough room? */ 37432144Sminshall if (NETROOM() < count) { 37532144Sminshall printf("There is not enough room in the buffer TO the network\n"); 37632144Sminshall printf("to process your request. Nothing will be done.\n"); 37732144Sminshall printf("('send synch' will throw away most data in the network\n"); 37832144Sminshall printf("buffer, if this might help.)\n"); 37932144Sminshall return 0; 38032144Sminshall } 38132144Sminshall /* OK, they are all OK, now go through again and actually send */ 38232144Sminshall for (i = 1; i < argc; i++) { 38332144Sminshall if ((s = getsend(argv[i])) == 0) { 38432144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 38532144Sminshall quit(); 38632144Sminshall /*NOTREACHED*/ 38732144Sminshall } 388*38689Sborman if (s->handler) { 389*38689Sborman (*s->handler)(s); 39032144Sminshall } else { 39132144Sminshall switch (what = s->what) { 39232144Sminshall case SYNCH: 39332144Sminshall dosynch(); 39432144Sminshall break; 39532144Sminshall case SENDQUESTION: 39632144Sminshall for (s = Sendlist; s->name; s++) { 397*38689Sborman if (s->help) 398*38689Sborman printf("%-15s %s\n", s->name, s->help); 39932144Sminshall } 40032144Sminshall question = 1; 40132144Sminshall break; 40232144Sminshall case SENDESCAPE: 40332144Sminshall NETADD(escape); 40432144Sminshall break; 40532144Sminshall default: 40632144Sminshall NET2ADD(IAC, what); 40732144Sminshall break; 40832144Sminshall } 40932144Sminshall } 41032144Sminshall } 41132144Sminshall return !question; 41232144Sminshall } 41332144Sminshall 41432144Sminshall /* 41532144Sminshall * The following are the routines and data structures referred 41632144Sminshall * to by the arguments to the "toggle" command. 41732144Sminshall */ 41832144Sminshall 41932144Sminshall static 42032144Sminshall lclchars() 42132144Sminshall { 42232144Sminshall donelclchars = 1; 42332144Sminshall return 1; 42432144Sminshall } 42532144Sminshall 42632144Sminshall static 42732144Sminshall togdebug() 42832144Sminshall { 42932144Sminshall #ifndef NOT43 43032144Sminshall if (net > 0 && 43132144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 43232144Sminshall perror("setsockopt (SO_DEBUG)"); 43332144Sminshall } 43432144Sminshall #else /* NOT43 */ 43532144Sminshall if (debug) { 43632144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 43732144Sminshall perror("setsockopt (SO_DEBUG)"); 43832144Sminshall } else 43932144Sminshall printf("Cannot turn off socket debugging\n"); 44032144Sminshall #endif /* NOT43 */ 44132144Sminshall return 1; 44232144Sminshall } 44332144Sminshall 44432144Sminshall 44532144Sminshall static int 44632144Sminshall togcrlf() 44732144Sminshall { 44832144Sminshall if (crlf) { 44932144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 45032144Sminshall } else { 45132144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 45232144Sminshall } 45332144Sminshall return 1; 45432144Sminshall } 45532144Sminshall 45632144Sminshall 45732144Sminshall static int 458*38689Sborman togbinary(val) 459*38689Sborman int val; 46032144Sminshall { 46132144Sminshall donebinarytoggle = 1; 46232144Sminshall 463*38689Sborman if (my_want_state_is_will(TELOPT_BINARY) || 464*38689Sborman my_want_state_is_do(TELOPT_BINARY)) { 465*38689Sborman if (val == 1) 466*38689Sborman printf("Already operating in binary mode with remote host.\n"); 467*38689Sborman else { 468*38689Sborman /* leave binary mode */ 469*38689Sborman printf("Negotiating network ascii mode with remote host.\n"); 470*38689Sborman tel_leave_binary(); 471*38689Sborman } 47237226Sminshall } else { /* Turn off binary mode */ 473*38689Sborman if (val == 0) 474*38689Sborman printf("Already in network ascii mode with remote host.\n"); 475*38689Sborman else { 476*38689Sborman printf("Negotiating binary mode with remote host.\n"); 477*38689Sborman tel_enter_binary(); 478*38689Sborman } 47932144Sminshall } 48032144Sminshall return 1; 48132144Sminshall } 48232144Sminshall 48332144Sminshall 48432144Sminshall 48532144Sminshall extern int togglehelp(); 486*38689Sborman extern int slc_check(); 48732144Sminshall 48832144Sminshall struct togglelist { 48932144Sminshall char *name; /* name of toggle */ 49032144Sminshall char *help; /* help message */ 49132144Sminshall int (*handler)(); /* routine to do actual setting */ 49232144Sminshall int *variable; 49332144Sminshall char *actionexplanation; 49432144Sminshall }; 49532144Sminshall 49632144Sminshall static struct togglelist Togglelist[] = { 49732144Sminshall { "autoflush", 498*38689Sborman "flushing of output when sending interrupt characters", 49932144Sminshall 0, 500*38689Sborman &autoflush, 501*38689Sborman "flush output when sending interrupt characters" }, 50232144Sminshall { "autosynch", 503*38689Sborman "automatic sending of interrupt characters in urgent mode", 50432144Sminshall 0, 505*38689Sborman &autosynch, 506*38689Sborman "send interrupt characters in urgent mode" }, 50732144Sminshall { "binary", 508*38689Sborman "sending and receiving of binary data", 50932144Sminshall togbinary, 510*38689Sborman 0, 511*38689Sborman 0 }, 51232144Sminshall { "crlf", 513*38689Sborman "sending carriage returns as telnet <CR><LF>", 51432144Sminshall togcrlf, 515*38689Sborman &crlf, 516*38689Sborman 0 }, 51732144Sminshall { "crmod", 518*38689Sborman "mapping of received carriage returns", 51932144Sminshall 0, 520*38689Sborman &crmod, 521*38689Sborman "map carriage return on output" }, 52232144Sminshall { "localchars", 523*38689Sborman "local recognition of certain control characters", 52432144Sminshall lclchars, 525*38689Sborman &localchars, 526*38689Sborman "recognize certain control characters" }, 527*38689Sborman { " ", "", 0 }, /* empty line */ 52838208Sminshall #if defined(unix) && defined(TN3270) 52938208Sminshall { "cursesdata", 53038208Sminshall "(debugging) toggle printing of hexadecimal curses data", 53138208Sminshall 0, 532*38689Sborman &cursesdata, 533*38689Sborman "print hexadecimal representation of curses data" }, 53438208Sminshall #endif /* defined(unix) && defined(TN3270) */ 53532144Sminshall { "debug", 536*38689Sborman "debugging", 53732144Sminshall togdebug, 538*38689Sborman &debug, 539*38689Sborman "turn on socket level debugging" }, 54032144Sminshall { "netdata", 541*38689Sborman "printing of hexadecimal network data (debugging)", 54232144Sminshall 0, 543*38689Sborman &netdata, 544*38689Sborman "print hexadecimal representation of network traffic" }, 545*38689Sborman { "prettydump", 546*38689Sborman "output of \"netdata\" to user readable format (debugging)", 547*38689Sborman 0, 548*38689Sborman &prettydump, 549*38689Sborman "print user readable output for \"netdata\"" }, 55032144Sminshall { "options", 551*38689Sborman "viewing of options processing (debugging)", 55232144Sminshall 0, 553*38689Sborman &showoptions, 554*38689Sborman "show option processing" }, 55538208Sminshall #if defined(unix) 55638208Sminshall { "termdata", 55738208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 55838208Sminshall 0, 559*38689Sborman &termdata, 560*38689Sborman "print hexadecimal representation of terminal traffic" }, 56138208Sminshall #endif /* defined(unix) */ 56232144Sminshall { "?", 563*38689Sborman 0, 564*38689Sborman togglehelp }, 56532144Sminshall { "help", 566*38689Sborman 0, 567*38689Sborman togglehelp }, 56832144Sminshall { 0 } 56932144Sminshall }; 57032144Sminshall 57132144Sminshall static 57232144Sminshall togglehelp() 57332144Sminshall { 57432144Sminshall struct togglelist *c; 57532144Sminshall 57632144Sminshall for (c = Togglelist; c->name; c++) { 577*38689Sborman if (c->help) { 578*38689Sborman if (*c->help) 579*38689Sborman printf("%-15s toggle %s\n", c->name, c->help); 580*38689Sborman else 581*38689Sborman printf("\n"); 58232144Sminshall } 58332144Sminshall } 584*38689Sborman printf("\n"); 585*38689Sborman printf("%-15s %s\n", "?", "display help information"); 58632144Sminshall return 0; 58732144Sminshall } 58832144Sminshall 589*38689Sborman static 590*38689Sborman settogglehelp(set) 591*38689Sborman int set; 592*38689Sborman { 593*38689Sborman struct togglelist *c; 594*38689Sborman 595*38689Sborman for (c = Togglelist; c->name; c++) { 596*38689Sborman if (c->help) { 597*38689Sborman if (*c->help) 598*38689Sborman printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 599*38689Sborman c->help); 600*38689Sborman else 601*38689Sborman printf("\n"); 602*38689Sborman } 603*38689Sborman } 604*38689Sborman } 605*38689Sborman 60632144Sminshall static char ** 60732144Sminshall getnexttoggle(name) 60832144Sminshall char *name; 60932144Sminshall { 61032144Sminshall struct togglelist *c = (struct togglelist *) name; 61132144Sminshall 61232144Sminshall return (char **) (c+1); 61332144Sminshall } 61432144Sminshall 61532144Sminshall static struct togglelist * 61632144Sminshall gettoggle(name) 61732144Sminshall char *name; 61832144Sminshall { 61932144Sminshall return (struct togglelist *) 62032144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 62132144Sminshall } 62232144Sminshall 62332144Sminshall static 62432144Sminshall toggle(argc, argv) 62532144Sminshall int argc; 62632144Sminshall char *argv[]; 62732144Sminshall { 62832144Sminshall int retval = 1; 62932144Sminshall char *name; 63032144Sminshall struct togglelist *c; 63132144Sminshall 63232144Sminshall if (argc < 2) { 63332144Sminshall fprintf(stderr, 63432144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 63532144Sminshall return 0; 63632144Sminshall } 63732144Sminshall argc--; 63832144Sminshall argv++; 63932144Sminshall while (argc--) { 64032144Sminshall name = *argv++; 64132144Sminshall c = gettoggle(name); 64232144Sminshall if (Ambiguous(c)) { 64332144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 64432144Sminshall name); 64532144Sminshall return 0; 64632144Sminshall } else if (c == 0) { 64732144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 64832144Sminshall name); 64932144Sminshall return 0; 65032144Sminshall } else { 65132144Sminshall if (c->variable) { 65232144Sminshall *c->variable = !*c->variable; /* invert it */ 65332144Sminshall if (c->actionexplanation) { 65432144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 65532144Sminshall c->actionexplanation); 65632144Sminshall } 65732144Sminshall } 65832144Sminshall if (c->handler) { 659*38689Sborman retval &= (*c->handler)(-1); 66032144Sminshall } 66132144Sminshall } 66232144Sminshall } 66332144Sminshall return retval; 66432144Sminshall } 66532144Sminshall 66632144Sminshall /* 66732144Sminshall * The following perform the "set" command. 66832144Sminshall */ 66932144Sminshall 670*38689Sborman #ifdef USE_TERMIO 671*38689Sborman struct termio new_tc = { 0 }; 672*38689Sborman #endif 673*38689Sborman 67432144Sminshall struct setlist { 67532144Sminshall char *name; /* name */ 67632144Sminshall char *help; /* help information */ 677*38689Sborman void (*handler)(); 67832144Sminshall char *charp; /* where it is located at */ 67932144Sminshall }; 68032144Sminshall 68132144Sminshall static struct setlist Setlist[] = { 682*38689Sborman { "echo", "character to toggle local echoing on/off", 0, &echoc }, 683*38689Sborman { "escape", "character to escape back to telnet command mode", 0, &escape }, 684*38689Sborman { "tracefile", "file to write trace intormation to", SetNetTrace, NetTraceFile}, 68532144Sminshall { " ", "" }, 686*38689Sborman { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 687*38689Sborman #ifndef CRAY 688*38689Sborman { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp }, 689*38689Sborman #endif 690*38689Sborman { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 691*38689Sborman { "quit", "character to cause an Abort process", 0, termQuitCharp }, 692*38689Sborman { "eof", "character to cause an EOF ", 0, termEofCharp }, 693*38689Sborman { " ", "" }, 694*38689Sborman { " ", "The following are for local editing in linemode", 0, 0 }, 695*38689Sborman { "erase", "character to use to erase a character", 0, termEraseCharp }, 696*38689Sborman { "kill", "character to use to erase a line", 0, termKillCharp }, 697*38689Sborman #ifndef CRAY 698*38689Sborman { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 699*38689Sborman { "susp", "character to cuase a Suspend Process", 0, termSuspCharp }, 700*38689Sborman { "reprint", "character to use for line reprint", 0, termRprntCharp }, 701*38689Sborman { "worderase", "character to use to erase a word", 0, termWerasCharp }, 702*38689Sborman { "start", "character to use for XON", 0, termStartCharp }, 703*38689Sborman { "stop", "character to sue for XOFF", 0, termStopCharp }, 704*38689Sborman #endif 70532144Sminshall { 0 } 70632144Sminshall }; 70732144Sminshall 708*38689Sborman #ifdef CRAY 709*38689Sborman /* Work around compiler bug */ 710*38689Sborman _setlist_init() 711*38689Sborman { 712*38689Sborman Setlist[6].charp = &termIntChar; 713*38689Sborman Setlist[7].charp = &termQuitChar; 714*38689Sborman Setlist[8].charp = &termEofChar; 715*38689Sborman Setlist[11].charp = &termEraseChar; 716*38689Sborman Setlist[12].charp = &termKillChar; 717*38689Sborman } 718*38689Sborman #endif CRAY 719*38689Sborman 72032144Sminshall static char ** 72132144Sminshall getnextset(name) 72232144Sminshall char *name; 72332144Sminshall { 72432144Sminshall struct setlist *c = (struct setlist *)name; 72532144Sminshall 72632144Sminshall return (char **) (c+1); 72732144Sminshall } 72832144Sminshall 72932144Sminshall static struct setlist * 73032144Sminshall getset(name) 73132144Sminshall char *name; 73232144Sminshall { 73332144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 73432144Sminshall } 73532144Sminshall 73632144Sminshall static 73732144Sminshall setcmd(argc, argv) 73832144Sminshall int argc; 73932144Sminshall char *argv[]; 74032144Sminshall { 74132144Sminshall int value; 74232144Sminshall struct setlist *ct; 743*38689Sborman struct togglelist *c; 74432144Sminshall 745*38689Sborman if (argc < 2 || argc > 3) { 746*38689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 74732144Sminshall return 0; 74832144Sminshall } 749*38689Sborman if ((argc == 2) && 750*38689Sborman ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 751*38689Sborman for (ct = Setlist; ct->name; ct++) 752*38689Sborman printf("%-15s %s\n", ct->name, ct->help); 753*38689Sborman printf("\n"); 754*38689Sborman settogglehelp(1); 755*38689Sborman printf("%-15s %s\n", "?", "display help information"); 756*38689Sborman return 0; 757*38689Sborman } 75832144Sminshall 75932144Sminshall ct = getset(argv[1]); 76032144Sminshall if (ct == 0) { 761*38689Sborman c = gettoggle(argv[1]); 762*38689Sborman if (c == 0) { 763*38689Sborman fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 76432144Sminshall argv[1]); 765*38689Sborman return 0; 766*38689Sborman } else if (Ambiguous(c)) { 767*38689Sborman fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 768*38689Sborman argv[1]); 769*38689Sborman return 0; 770*38689Sborman } 771*38689Sborman if (c->variable) { 772*38689Sborman if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 773*38689Sborman *c->variable = 1; 774*38689Sborman else if (strcmp("off", argv[2]) == 0) 775*38689Sborman *c->variable = 0; 776*38689Sborman else { 777*38689Sborman printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 778*38689Sborman return 0; 779*38689Sborman } 780*38689Sborman if (c->actionexplanation) { 781*38689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 782*38689Sborman c->actionexplanation); 783*38689Sborman } 784*38689Sborman } 785*38689Sborman if (c->handler) 786*38689Sborman (*c->handler)(1); 787*38689Sborman } else if (argc != 3) { 788*38689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 78932144Sminshall return 0; 79032144Sminshall } else if (Ambiguous(ct)) { 79132144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 79232144Sminshall argv[1]); 79332144Sminshall return 0; 794*38689Sborman } else if (ct->handler) { 795*38689Sborman (*ct->handler)(argv[2]); 796*38689Sborman printf("%s set to \"%s\".\n", ct->name, ct->charp); 79732144Sminshall } else { 79832144Sminshall if (strcmp("off", argv[2])) { 79932144Sminshall value = special(argv[2]); 80032144Sminshall } else { 80132144Sminshall value = -1; 80232144Sminshall } 80332144Sminshall *(ct->charp) = value; 80432144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 80532144Sminshall } 806*38689Sborman slc_check(); 80732144Sminshall return 1; 80832144Sminshall } 809*38689Sborman 810*38689Sborman static 811*38689Sborman unsetcmd(argc, argv) 812*38689Sborman int argc; 813*38689Sborman char *argv[]; 814*38689Sborman { 815*38689Sborman int value; 816*38689Sborman struct setlist *ct; 817*38689Sborman struct togglelist *c; 818*38689Sborman register char *name; 819*38689Sborman 820*38689Sborman if (argc < 2) { 821*38689Sborman fprintf(stderr, 822*38689Sborman "Need an argument to 'unset' command. 'unset ?' for help.\n"); 823*38689Sborman return 0; 824*38689Sborman } 825*38689Sborman if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) { 826*38689Sborman for (ct = Setlist; ct->name; ct++) 827*38689Sborman printf("%-15s %s\n", ct->name, ct->help); 828*38689Sborman printf("\n"); 829*38689Sborman settogglehelp(0); 830*38689Sborman printf("%-15s %s\n", "?", "display help information"); 831*38689Sborman return 0; 832*38689Sborman } 833*38689Sborman 834*38689Sborman argc--; 835*38689Sborman argv++; 836*38689Sborman while (argc--) { 837*38689Sborman name = *argv++; 838*38689Sborman ct = getset(name); 839*38689Sborman if (ct == 0) { 840*38689Sborman c = gettoggle(name); 841*38689Sborman if (c == 0) { 842*38689Sborman fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 843*38689Sborman name); 844*38689Sborman return 0; 845*38689Sborman } else if (Ambiguous(c)) { 846*38689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 847*38689Sborman name); 848*38689Sborman return 0; 849*38689Sborman } 850*38689Sborman if (c->variable) { 851*38689Sborman *c->variable = 0; 852*38689Sborman if (c->actionexplanation) { 853*38689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 854*38689Sborman c->actionexplanation); 855*38689Sborman } 856*38689Sborman } 857*38689Sborman if (c->handler) 858*38689Sborman (*c->handler)(0); 859*38689Sborman } else if (Ambiguous(ct)) { 860*38689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 861*38689Sborman name); 862*38689Sborman return 0; 863*38689Sborman } else if (ct->handler) { 864*38689Sborman (*ct->handler)(0); 865*38689Sborman printf("%s reset to \"%s\".\n", ct->name, ct->charp); 866*38689Sborman } else { 867*38689Sborman value = -1; 868*38689Sborman *(ct->charp) = -1; 869*38689Sborman printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 870*38689Sborman } 871*38689Sborman } 872*38689Sborman return 1; 873*38689Sborman } 87432144Sminshall 87532144Sminshall /* 87632144Sminshall * The following are the data structures and routines for the 87732144Sminshall * 'mode' command. 87832144Sminshall */ 879*38689Sborman #ifdef KLUDGELINEMODE 880*38689Sborman extern int kludgelinemode; 881*38689Sborman #endif 88232144Sminshall 88332144Sminshall static 88432144Sminshall dolinemode() 88532144Sminshall { 886*38689Sborman #ifdef KLUDGELINEMODE 887*38689Sborman if (kludgelinemode) 888*38689Sborman send_dont(TELOPT_SGA, 1); 889*38689Sborman #endif 890*38689Sborman send_will(TELOPT_LINEMODE, 1); 891*38689Sborman send_dont(TELOPT_ECHO, 1); 89232144Sminshall return 1; 89332144Sminshall } 89432144Sminshall 89532144Sminshall static 89632144Sminshall docharmode() 89732144Sminshall { 898*38689Sborman #ifdef KLUDGELINEMODE 899*38689Sborman if (kludgelinemode) 900*38689Sborman send_do(TELOPT_SGA, 1); 901*38689Sborman else 902*38689Sborman #endif 903*38689Sborman send_wont(TELOPT_LINEMODE, 1); 904*38689Sborman send_do(TELOPT_ECHO, 1); 905*38689Sborman return 1; 906*38689Sborman } 907*38689Sborman 908*38689Sborman setmode(bit) 909*38689Sborman { 910*38689Sborman return dolmmode(bit, 1); 911*38689Sborman } 912*38689Sborman 913*38689Sborman clearmode(bit) 914*38689Sborman { 915*38689Sborman return dolmmode(bit, 0); 916*38689Sborman } 917*38689Sborman 918*38689Sborman dolmmode(bit, on) 919*38689Sborman int bit, on; 920*38689Sborman { 921*38689Sborman char c; 922*38689Sborman extern int linemode; 923*38689Sborman 924*38689Sborman if (my_want_state_is_wont(TELOPT_LINEMODE)) { 925*38689Sborman printf("?Need to have LINEMODE option enabled first.\n"); 926*38689Sborman printf("'mode ?' for help.\n"); 927*38689Sborman return 0; 92832144Sminshall } 929*38689Sborman 930*38689Sborman if (on) 931*38689Sborman c = (linemode | bit); 932*38689Sborman else 933*38689Sborman c = (linemode & ~bit); 934*38689Sborman lm_mode(&c, 1, 1); 93532144Sminshall return 1; 93632144Sminshall } 93732144Sminshall 938*38689Sborman struct modelist { 939*38689Sborman char *name; /* command name */ 940*38689Sborman char *help; /* help string */ 941*38689Sborman int (*handler)(); /* routine which executes command */ 942*38689Sborman int needconnect; /* Do we need to be connected to execute? */ 943*38689Sborman int arg1; 944*38689Sborman }; 945*38689Sborman 946*38689Sborman extern int modehelp(); 947*38689Sborman 948*38689Sborman static struct modelist ModeList[] = { 949*38689Sborman { "character", "Disable LINEMODE option", docharmode, 1 }, 950*38689Sborman #ifdef KLUDEGLINEMODE 951*38689Sborman { "", "(or disable obsolete line-by-line mode)", 0 }; 952*38689Sborman #endif 953*38689Sborman { "line", "Enable LINEMODE option", dolinemode, 1 }, 954*38689Sborman #ifdef KLUDEGLINEMODE 955*38689Sborman { "", "(or enable obsolete line-by-line mode)", 0 }; 956*38689Sborman #endif 957*38689Sborman { "", "", 0 }, 958*38689Sborman { "", "These require the LINEMODE option to be enabled", 0 }, 959*38689Sborman { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 960*38689Sborman { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 961*38689Sborman { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 962*38689Sborman { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 963*38689Sborman { "+edit", 0, setmode, 1, MODE_EDIT }, 964*38689Sborman { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 965*38689Sborman { "help", 0, modehelp, 0 }, 966*38689Sborman { "?", "Print help information", modehelp, 0 }, 96732144Sminshall { 0 }, 96832144Sminshall }; 96932144Sminshall 97032144Sminshall static char ** 97132144Sminshall getnextmode(name) 97232144Sminshall char *name; 97332144Sminshall { 974*38689Sborman return (char **) (((struct modelist *)name)+1); 97532144Sminshall } 97632144Sminshall 977*38689Sborman static struct modelist * 97832144Sminshall getmodecmd(name) 97932144Sminshall char *name; 98032144Sminshall { 981*38689Sborman return (struct modelist *) genget(name, (char **) ModeList, getnextmode); 98232144Sminshall } 98332144Sminshall 984*38689Sborman modehelp() 985*38689Sborman { 986*38689Sborman struct modelist *mt; 987*38689Sborman 988*38689Sborman printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 989*38689Sborman for (mt = ModeList; mt->name; mt++) { 990*38689Sborman if (mt->help) { 991*38689Sborman if (*mt->help) 992*38689Sborman printf("%-15s %s\n", mt->name, mt->help); 993*38689Sborman else 994*38689Sborman printf("\n"); 995*38689Sborman } 996*38689Sborman } 997*38689Sborman return 0; 998*38689Sborman } 999*38689Sborman 100032144Sminshall static 100132144Sminshall modecmd(argc, argv) 100232144Sminshall int argc; 100332144Sminshall char *argv[]; 100432144Sminshall { 1005*38689Sborman struct modelist *mt; 100632144Sminshall 1007*38689Sborman if (argc != 2) { 1008*38689Sborman printf("'mode' command requires an argument\n"); 1009*38689Sborman printf("'mode ?' for help.\n"); 1010*38689Sborman } else if ((mt = getmodecmd(argv[1])) == 0) { 101132144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 101232144Sminshall } else if (Ambiguous(mt)) { 101332144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 1014*38689Sborman } else if (mt->needconnect && !connected) { 1015*38689Sborman printf("?Need to be connected first.\n"); 1016*38689Sborman printf("'mode ?' for help.\n"); 1017*38689Sborman } else if (mt->handler) { 1018*38689Sborman return (*mt->handler)(mt->arg1); 101932144Sminshall } 1020*38689Sborman return 0; 102132144Sminshall } 102232144Sminshall 102332144Sminshall /* 102432144Sminshall * The following data structures and routines implement the 102532144Sminshall * "display" command. 102632144Sminshall */ 102732144Sminshall 102832144Sminshall static 102932144Sminshall display(argc, argv) 103032144Sminshall int argc; 103132144Sminshall char *argv[]; 103232144Sminshall { 103332144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 103432144Sminshall if (*tl->variable) { \ 103532144Sminshall printf("will"); \ 103632144Sminshall } else { \ 103732144Sminshall printf("won't"); \ 103832144Sminshall } \ 103932144Sminshall printf(" %s.\n", tl->actionexplanation); \ 104032144Sminshall } 104132144Sminshall 104232144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 1043*38689Sborman if (sl->handler == 0) \ 1044*38689Sborman printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 1045*38689Sborman else \ 1046*38689Sborman printf("%-15s \"%s\"\n", sl->name, sl->charp); \ 104732144Sminshall } 104832144Sminshall 104932144Sminshall struct togglelist *tl; 105032144Sminshall struct setlist *sl; 105132144Sminshall 105232144Sminshall if (argc == 1) { 105332144Sminshall for (tl = Togglelist; tl->name; tl++) { 105432144Sminshall dotog(tl); 105532144Sminshall } 105632144Sminshall printf("\n"); 105732144Sminshall for (sl = Setlist; sl->name; sl++) { 105832144Sminshall doset(sl); 105932144Sminshall } 106032144Sminshall } else { 106132144Sminshall int i; 106232144Sminshall 106332144Sminshall for (i = 1; i < argc; i++) { 106432144Sminshall sl = getset(argv[i]); 106532144Sminshall tl = gettoggle(argv[i]); 106632144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 106732144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 106832144Sminshall return 0; 106932144Sminshall } else if (!sl && !tl) { 107032144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 107132144Sminshall return 0; 107232144Sminshall } else { 107332144Sminshall if (tl) { 107432144Sminshall dotog(tl); 107532144Sminshall } 107632144Sminshall if (sl) { 107732144Sminshall doset(sl); 107832144Sminshall } 107932144Sminshall } 108032144Sminshall } 108132144Sminshall } 1082*38689Sborman /*@*/optionstatus(); 108332144Sminshall return 1; 108432144Sminshall #undef doset 108532144Sminshall #undef dotog 108632144Sminshall } 108732144Sminshall 108832144Sminshall /* 108932144Sminshall * The following are the data structures, and many of the routines, 109032144Sminshall * relating to command processing. 109132144Sminshall */ 109232144Sminshall 109332144Sminshall /* 109432144Sminshall * Set the escape character. 109532144Sminshall */ 109632144Sminshall static 109732144Sminshall setescape(argc, argv) 109832144Sminshall int argc; 109932144Sminshall char *argv[]; 110032144Sminshall { 110132144Sminshall register char *arg; 110232144Sminshall char buf[50]; 110332144Sminshall 110432144Sminshall printf( 110532144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 110632144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 110732144Sminshall if (argc > 2) 110832144Sminshall arg = argv[1]; 110932144Sminshall else { 111032144Sminshall printf("new escape character: "); 111134849Sminshall (void) gets(buf); 111232144Sminshall arg = buf; 111332144Sminshall } 111432144Sminshall if (arg[0] != '\0') 111532144Sminshall escape = arg[0]; 111632144Sminshall if (!In3270) { 111732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 111832144Sminshall } 111934849Sminshall (void) fflush(stdout); 112032144Sminshall return 1; 112132144Sminshall } 112232144Sminshall 112332144Sminshall /*VARARGS*/ 112432144Sminshall static 112532144Sminshall togcrmod() 112632144Sminshall { 112732144Sminshall crmod = !crmod; 112832144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 112932144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 113034849Sminshall (void) fflush(stdout); 113132144Sminshall return 1; 113232144Sminshall } 113332144Sminshall 113432144Sminshall /*VARARGS*/ 113532144Sminshall suspend() 113632144Sminshall { 1137*38689Sborman #ifdef SIGTSTP 113837219Sminshall setcommandmode(); 113937219Sminshall { 114037219Sminshall long oldrows, oldcols, newrows, newcols; 114137219Sminshall 114237219Sminshall TerminalWindowSize(&oldrows, &oldcols); 114334849Sminshall (void) kill(0, SIGTSTP); 114437219Sminshall TerminalWindowSize(&newrows, &newcols); 114537219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 114637219Sminshall if (connected) { 114737219Sminshall sendnaws(); 114837219Sminshall } 114937219Sminshall } 115037219Sminshall } 115137219Sminshall /* reget parameters in case they were changed */ 115237219Sminshall TerminalSaveState(); 1153*38689Sborman setconnmode(0); 1154*38689Sborman #else 1155*38689Sborman printf("Suspend is not supported. Try the '!' command instead\n"); 1156*38689Sborman #endif 115737219Sminshall return 1; 115832144Sminshall } 115932144Sminshall 1160*38689Sborman #if !defined(TN3270) 1161*38689Sborman #ifdef CRAY 1162*38689Sborman #define vfork fork 1163*38689Sborman #endif 1164*38689Sborman shell(argc, argv) 1165*38689Sborman int argc; 1166*38689Sborman char *argv[]; 1167*38689Sborman { 1168*38689Sborman extern char *rindex(); 1169*38689Sborman char cmdbuf[256]; 1170*38689Sborman 1171*38689Sborman setcommandmode(); 1172*38689Sborman switch(vfork()) { 1173*38689Sborman case -1: 1174*38689Sborman perror("Fork failed\n"); 1175*38689Sborman break; 1176*38689Sborman 1177*38689Sborman case 0: 1178*38689Sborman { 1179*38689Sborman /* 1180*38689Sborman * Fire up the shell in the child. 1181*38689Sborman */ 1182*38689Sborman register char *shell, *shellname; 1183*38689Sborman 1184*38689Sborman shell = getenv("SHELL"); 1185*38689Sborman if (shell == NULL) 1186*38689Sborman shell = "/bin/sh"; 1187*38689Sborman if ((shellname = rindex(shell, '/')) == 0) 1188*38689Sborman shellname = shell; 1189*38689Sborman else 1190*38689Sborman shellname++; 1191*38689Sborman if (argc > 1) 1192*38689Sborman execl(shell, shellname, "-c", &saveline[1], 0); 1193*38689Sborman else 1194*38689Sborman execl(shell, shellname, 0); 1195*38689Sborman perror("Execl"); 1196*38689Sborman _exit(1); 1197*38689Sborman } 1198*38689Sborman default: 1199*38689Sborman wait((int *)0); /* Wait for the shell to complete */ 1200*38689Sborman } 1201*38689Sborman } 1202*38689Sborman #endif /* !defined(TN3270) */ 1203*38689Sborman 120432144Sminshall /*VARARGS*/ 120532144Sminshall static 120632144Sminshall bye(argc, argv) 120732144Sminshall int argc; /* Number of arguments */ 120832144Sminshall char *argv[]; /* arguments */ 120932144Sminshall { 121032144Sminshall if (connected) { 121134849Sminshall (void) shutdown(net, 2); 121232144Sminshall printf("Connection closed.\n"); 121334849Sminshall (void) NetClose(net); 121432144Sminshall connected = 0; 121532144Sminshall /* reset options */ 121632144Sminshall tninit(); 121732144Sminshall #if defined(TN3270) 121832144Sminshall SetIn3270(); /* Get out of 3270 mode */ 121932144Sminshall #endif /* defined(TN3270) */ 122032144Sminshall } 122132144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 122232144Sminshall longjmp(toplevel, 1); 122332144Sminshall /* NOTREACHED */ 122432144Sminshall } 122532144Sminshall return 1; /* Keep lint, etc., happy */ 122632144Sminshall } 122732144Sminshall 122832144Sminshall /*VARARGS*/ 122932144Sminshall quit() 123032144Sminshall { 123132144Sminshall (void) call(bye, "bye", "fromquit", 0); 123232144Sminshall Exit(0); 123332144Sminshall return 1; /* just to keep lint happy */ 123432144Sminshall } 1235*38689Sborman 1236*38689Sborman /* 1237*38689Sborman * The SLC command. 1238*38689Sborman */ 123932144Sminshall 1240*38689Sborman struct slclist { 1241*38689Sborman char *name; 1242*38689Sborman char *help; 1243*38689Sborman int (*handler)(); 1244*38689Sborman int arg; 1245*38689Sborman }; 1246*38689Sborman 1247*38689Sborman extern int slc_help(); 1248*38689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate(); 1249*38689Sborman 1250*38689Sborman struct slclist SlcList[] = { 1251*38689Sborman { "export", "Use local special character definitions", 1252*38689Sborman slc_mode_export, 0 }, 1253*38689Sborman { "import", "Use remote special character definitions", 1254*38689Sborman slc_mode_import, 1 }, 1255*38689Sborman { "check", "Verify remote special character definitions", 1256*38689Sborman slc_mode_import, 0 }, 1257*38689Sborman { "help", 0, slc_help, 0 }, 1258*38689Sborman { "?", "Print help information", slc_help, 0 }, 1259*38689Sborman { 0 }, 1260*38689Sborman }; 1261*38689Sborman 1262*38689Sborman static 1263*38689Sborman slc_help() 1264*38689Sborman { 1265*38689Sborman struct slclist *c; 1266*38689Sborman 1267*38689Sborman for (c = SlcList; c->name; c++) { 1268*38689Sborman if (c->help) { 1269*38689Sborman if (*c->help) 1270*38689Sborman printf("%-15s %s\n", c->name, c->help); 1271*38689Sborman else 1272*38689Sborman printf("\n"); 1273*38689Sborman } 1274*38689Sborman } 1275*38689Sborman } 1276*38689Sborman 1277*38689Sborman static char ** 1278*38689Sborman getnextslc(name) 1279*38689Sborman char *name; 1280*38689Sborman { 1281*38689Sborman return (char **)(((struct slclist *)name)+1); 1282*38689Sborman } 1283*38689Sborman 1284*38689Sborman static struct slclist * 1285*38689Sborman getslc(name) 1286*38689Sborman char *name; 1287*38689Sborman { 1288*38689Sborman return (struct slclist *)genget(name, (char **) SlcList, getnextslc); 1289*38689Sborman } 1290*38689Sborman 1291*38689Sborman static 1292*38689Sborman slccmd(argc, argv) 1293*38689Sborman int argc; 1294*38689Sborman char *argv[]; 1295*38689Sborman { 1296*38689Sborman struct slclist *c; 1297*38689Sborman 1298*38689Sborman if (argc != 2) { 1299*38689Sborman fprintf(stderr, 1300*38689Sborman "Need an argument to 'slc' command. 'slc ?' for help.\n"); 1301*38689Sborman return 0; 1302*38689Sborman } 1303*38689Sborman c = getslc(argv[1]); 1304*38689Sborman if (c == 0) { 1305*38689Sborman fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 1306*38689Sborman argv[1]); 1307*38689Sborman return 0; 1308*38689Sborman } 1309*38689Sborman if (Ambiguous(c)) { 1310*38689Sborman fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 1311*38689Sborman argv[1]); 1312*38689Sborman return 0; 1313*38689Sborman } 1314*38689Sborman (*c->handler)(c->arg); 1315*38689Sborman slcstate(); 1316*38689Sborman return 1; 1317*38689Sborman } 1318*38689Sborman 131936274Sminshall #if defined(unix) 132032144Sminshall /* 132136274Sminshall * Some information about our file descriptors. 132236274Sminshall */ 132336274Sminshall 132436274Sminshall char * 132536274Sminshall decodeflags(mask) 132636274Sminshall int mask; 132736274Sminshall { 132836274Sminshall static char buffer[100]; 132936274Sminshall #define do(m,s) \ 133036274Sminshall if (mask&(m)) { \ 133136274Sminshall strcat(buffer, (s)); \ 133236274Sminshall } 133336274Sminshall 133436274Sminshall buffer[0] = 0; /* Terminate it */ 133536274Sminshall 133636274Sminshall #ifdef FREAD 133736274Sminshall do(FREAD, " FREAD"); 133836274Sminshall #endif 133936274Sminshall #ifdef FWRITE 134036274Sminshall do(FWRITE, " FWRITE"); 134136274Sminshall #endif 134236274Sminshall #ifdef F_DUPFP 134336274Sminshall do(F_DUPFD, " F_DUPFD"); 134436274Sminshall #endif 134536274Sminshall #ifdef FNDELAY 134636274Sminshall do(FNDELAY, " FNDELAY"); 134736274Sminshall #endif 134836274Sminshall #ifdef FAPPEND 134936274Sminshall do(FAPPEND, " FAPPEND"); 135036274Sminshall #endif 135136274Sminshall #ifdef FMARK 135236274Sminshall do(FMARK, " FMARK"); 135336274Sminshall #endif 135436274Sminshall #ifdef FDEFER 135536274Sminshall do(FDEFER, " FDEFER"); 135636274Sminshall #endif 135736274Sminshall #ifdef FASYNC 135836274Sminshall do(FASYNC, " FASYNC"); 135936274Sminshall #endif 136036274Sminshall #ifdef FSHLOCK 136136274Sminshall do(FSHLOCK, " FSHLOCK"); 136236274Sminshall #endif 136336274Sminshall #ifdef FEXLOCK 136436274Sminshall do(FEXLOCK, " FEXLOCK"); 136536274Sminshall #endif 136636274Sminshall #ifdef FCREAT 136736274Sminshall do(FCREAT, " FCREAT"); 136836274Sminshall #endif 136936274Sminshall #ifdef FTRUNC 137036274Sminshall do(FTRUNC, " FTRUNC"); 137136274Sminshall #endif 137236274Sminshall #ifdef FEXCL 137336274Sminshall do(FEXCL, " FEXCL"); 137436274Sminshall #endif 137536274Sminshall 137636274Sminshall return buffer; 137736274Sminshall } 137836274Sminshall #undef do 137936274Sminshall 138036274Sminshall static void 138136274Sminshall filestuff(fd) 138236274Sminshall int fd; 138336274Sminshall { 138436274Sminshall int res; 138536274Sminshall 1386*38689Sborman #ifdef F_GETOWN 1387*38689Sborman setconnmode(0); 138836274Sminshall res = fcntl(fd, F_GETOWN, 0); 138936274Sminshall setcommandmode(); 139036274Sminshall 139136274Sminshall if (res == -1) { 139236274Sminshall perror("fcntl"); 139336274Sminshall return; 139436274Sminshall } 139536274Sminshall printf("\tOwner is %d.\n", res); 1396*38689Sborman #endif 139736274Sminshall 1398*38689Sborman setconnmode(0); 139936274Sminshall res = fcntl(fd, F_GETFL, 0); 140036274Sminshall setcommandmode(); 140136274Sminshall 140236274Sminshall if (res == -1) { 140336274Sminshall perror("fcntl"); 140436274Sminshall return; 140536274Sminshall } 140636274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 140736274Sminshall } 140836274Sminshall 140936274Sminshall 141036274Sminshall #endif /* defined(unix) */ 141136274Sminshall 141236274Sminshall /* 141332144Sminshall * Print status about the connection. 141432144Sminshall */ 141534849Sminshall /*ARGSUSED*/ 141632144Sminshall static 141732144Sminshall status(argc, argv) 141832144Sminshall int argc; 141932144Sminshall char *argv[]; 142032144Sminshall { 142132144Sminshall if (connected) { 142232144Sminshall printf("Connected to %s.\n", hostname); 142336242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 1424*38689Sborman int mode = getconnmode(); 1425*38689Sborman 1426*38689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 1427*38689Sborman printf("Operating with LINEMODE option\n"); 1428*38689Sborman printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 1429*38689Sborman printf("%s catching of signals\n", 1430*38689Sborman (mode&MODE_TRAPSIG) ? "Local" : "No"); 1431*38689Sborman slcstate(); 1432*38689Sborman #ifdef KLUDGELINEMODE 1433*38689Sborman } else if (kludgelinemode && my_want_state_is_wont(TELOPT_SGA)) { 1434*38689Sborman printf("Operating in obsolete linemode\n"); 1435*38689Sborman #endif 1436*38689Sborman } else { 1437*38689Sborman printf("Operating in single character mode\n"); 1438*38689Sborman if (localchars) 1439*38689Sborman printf("Catching signals locally\n"); 144032144Sminshall } 1441*38689Sborman printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 1442*38689Sborman if (my_want_state_is_will(TELOPT_LFLOW)) 1443*38689Sborman printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 144432144Sminshall } 144532144Sminshall } else { 144632144Sminshall printf("No connection.\n"); 144732144Sminshall } 144832144Sminshall # if !defined(TN3270) 144932144Sminshall printf("Escape character is '%s'.\n", control(escape)); 145034849Sminshall (void) fflush(stdout); 145132144Sminshall # else /* !defined(TN3270) */ 145232144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 145332144Sminshall printf("Escape character is '%s'.\n", control(escape)); 145432144Sminshall } 145532144Sminshall # if defined(unix) 145636242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 145736242Sminshall printf("SIGIO received %d time%s.\n", 145836242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 145936274Sminshall if (In3270) { 146036274Sminshall printf("Process ID %d, process group %d.\n", 146136274Sminshall getpid(), getpgrp(getpid())); 146236274Sminshall printf("Terminal input:\n"); 146336274Sminshall filestuff(tin); 146436274Sminshall printf("Terminal output:\n"); 146536274Sminshall filestuff(tout); 146636274Sminshall printf("Network socket:\n"); 146736274Sminshall filestuff(net); 146836274Sminshall } 146936242Sminshall } 147032144Sminshall if (In3270 && transcom) { 147132144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 147232144Sminshall } 147332144Sminshall # endif /* defined(unix) */ 147434849Sminshall (void) fflush(stdout); 147532144Sminshall if (In3270) { 147632144Sminshall return 0; 147732144Sminshall } 147832144Sminshall # endif /* defined(TN3270) */ 147932144Sminshall return 1; 148032144Sminshall } 148132144Sminshall 148232144Sminshall 148332144Sminshall 148432144Sminshall int 148532144Sminshall tn(argc, argv) 148632144Sminshall int argc; 148732144Sminshall char *argv[]; 148832144Sminshall { 148932144Sminshall register struct hostent *host = 0; 149032144Sminshall struct sockaddr_in sin; 149132144Sminshall struct servent *sp = 0; 149232144Sminshall static char hnamebuf[32]; 1493*38689Sborman unsigned long temp, inet_addr(); 149437219Sminshall extern char *inet_ntoa(); 1495*38689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 1496*38689Sborman char *srp = 0, *strrchr(); 1497*38689Sborman unsigned long sourceroute(), srlen; 1498*38689Sborman #endif 149932144Sminshall 150032144Sminshall 150132144Sminshall #if defined(MSDOS) 150232144Sminshall char *cp; 150332144Sminshall #endif /* defined(MSDOS) */ 150432144Sminshall 150532144Sminshall if (connected) { 150632144Sminshall printf("?Already connected to %s\n", hostname); 150732144Sminshall return 0; 150832144Sminshall } 150932144Sminshall if (argc < 2) { 151032144Sminshall (void) strcpy(line, "Connect "); 151132144Sminshall printf("(to) "); 151234849Sminshall (void) gets(&line[strlen(line)]); 151332144Sminshall makeargv(); 151432144Sminshall argc = margc; 151532144Sminshall argv = margv; 151632144Sminshall } 151732144Sminshall if ((argc < 2) || (argc > 3)) { 151832144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 151932144Sminshall return 0; 152032144Sminshall } 152132144Sminshall #if defined(MSDOS) 152232144Sminshall for (cp = argv[1]; *cp; cp++) { 152332144Sminshall if (isupper(*cp)) { 152432144Sminshall *cp = tolower(*cp); 152532144Sminshall } 152632144Sminshall } 152732144Sminshall #endif /* defined(MSDOS) */ 1528*38689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 1529*38689Sborman if (argv[1][0] == '@' || argv[1][0] == '!') { 1530*38689Sborman if ((hostname = strrchr(argv[1], ':')) == NULL) 1531*38689Sborman hostname = strrchr(argv[1], '@'); 1532*38689Sborman hostname++; 1533*38689Sborman srp = 0; 1534*38689Sborman temp = sourceroute(argv[1], &srp, &srlen); 1535*38689Sborman if (temp == 0) { 1536*38689Sborman herror(srp); 1537*38689Sborman return 0; 1538*38689Sborman } else if (temp == -1) { 1539*38689Sborman printf("Bad source route option: %s\n", argv[1]); 1540*38689Sborman return 0; 1541*38689Sborman } else { 1542*38689Sborman sin.sin_addr.s_addr = temp; 1543*38689Sborman sin.sin_family = AF_INET; 1544*38689Sborman } 154532144Sminshall } else { 1546*38689Sborman #endif 1547*38689Sborman temp = inet_addr(argv[1]); 1548*38689Sborman if (temp != (unsigned long) -1) { 1549*38689Sborman sin.sin_addr.s_addr = temp; 1550*38689Sborman sin.sin_family = AF_INET; 1551*38689Sborman (void) strcpy(hnamebuf, argv[1]); 1552*38689Sborman hostname = hnamebuf; 1553*38689Sborman } else { 1554*38689Sborman host = gethostbyname(argv[1]); 1555*38689Sborman if (host) { 1556*38689Sborman sin.sin_family = host->h_addrtype; 155732144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 1558*38689Sborman memcpy((caddr_t)&sin.sin_addr, 155932144Sminshall host->h_addr_list[0], host->h_length); 156032144Sminshall #else /* defined(h_addr) */ 1561*38689Sborman memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 156232144Sminshall #endif /* defined(h_addr) */ 1563*38689Sborman hostname = host->h_name; 1564*38689Sborman } else { 1565*38689Sborman herror(argv[1]); 1566*38689Sborman return 0; 1567*38689Sborman } 156832144Sminshall } 1569*38689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 157032144Sminshall } 1571*38689Sborman #endif 157232144Sminshall if (argc == 3) { 1573*38689Sborman int tmp; 1574*38689Sborman 1575*38689Sborman if (*argv[2] == '-') { 1576*38689Sborman argv[2]++; 1577*38689Sborman telnetport = 1; 1578*38689Sborman } else 1579*38689Sborman telnetport = 0; 158032144Sminshall sin.sin_port = atoi(argv[2]); 158132144Sminshall if (sin.sin_port == 0) { 158232144Sminshall sp = getservbyname(argv[2], "tcp"); 158332144Sminshall if (sp) 158432144Sminshall sin.sin_port = sp->s_port; 158532144Sminshall else { 158632144Sminshall printf("%s: bad port number\n", argv[2]); 158732144Sminshall return 0; 158832144Sminshall } 158932144Sminshall } else { 159034849Sminshall #if !defined(htons) 159134849Sminshall u_short htons(); 159234849Sminshall #endif /* !defined(htons) */ 159332144Sminshall sin.sin_port = htons(sin.sin_port); 159432144Sminshall } 159532144Sminshall } else { 159632144Sminshall if (sp == 0) { 159732144Sminshall sp = getservbyname("telnet", "tcp"); 159832144Sminshall if (sp == 0) { 159934849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 160032144Sminshall return 0; 160132144Sminshall } 160232144Sminshall sin.sin_port = sp->s_port; 160332144Sminshall } 160432144Sminshall telnetport = 1; 160532144Sminshall } 160637219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 160732144Sminshall do { 160832144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 160932144Sminshall if (net < 0) { 161032144Sminshall perror("telnet: socket"); 161132144Sminshall return 0; 161232144Sminshall } 1613*38689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 1614*38689Sborman if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) 1615*38689Sborman perror("setsockopt (IP_OPTIONS)"); 1616*38689Sborman #endif 161732144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 161832144Sminshall perror("setsockopt (SO_DEBUG)"); 161932144Sminshall } 162032144Sminshall 162132144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 162232144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 162332144Sminshall if (host && host->h_addr_list[1]) { 162432144Sminshall int oerrno = errno; 162532144Sminshall 162632144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 162732144Sminshall inet_ntoa(sin.sin_addr)); 162832144Sminshall errno = oerrno; 162932144Sminshall perror((char *)0); 163032144Sminshall host->h_addr_list++; 163132144Sminshall memcpy((caddr_t)&sin.sin_addr, 163232144Sminshall host->h_addr_list[0], host->h_length); 163332144Sminshall (void) NetClose(net); 163432144Sminshall continue; 163532144Sminshall } 163632144Sminshall #endif /* defined(h_addr) */ 163732144Sminshall perror("telnet: Unable to connect to remote host"); 163832144Sminshall return 0; 163937219Sminshall } 164032144Sminshall connected++; 164132144Sminshall } while (connected == 0); 1642*38689Sborman cmdrc(argv[1], hostname); 164334849Sminshall (void) call(status, "status", "notmuch", 0); 164432144Sminshall if (setjmp(peerdied) == 0) 164532144Sminshall telnet(); 164634849Sminshall (void) NetClose(net); 164732381Sminshall ExitString("Connection closed by foreign host.\n",1); 164832144Sminshall /*NOTREACHED*/ 164932144Sminshall } 165032144Sminshall 165132144Sminshall 165232144Sminshall #define HELPINDENT (sizeof ("connect")) 165332144Sminshall 165432144Sminshall static char 165532144Sminshall openhelp[] = "connect to a site", 165632144Sminshall closehelp[] = "close current connection", 165732144Sminshall quithelp[] = "exit telnet", 165832144Sminshall statushelp[] = "print status information", 165932144Sminshall helphelp[] = "print help information", 166032144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 166132144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 1662*38689Sborman unsethelp[] = "unset operating parameters ('unset ?' for more)", 166332144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 1664*38689Sborman slchelp[] = "change state of special charaters ('slc ?' for more)", 166532144Sminshall displayhelp[] = "display operating parameters", 166632144Sminshall #if defined(TN3270) && defined(unix) 166732144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 166832144Sminshall #endif /* defined(TN3270) && defined(unix) */ 166932144Sminshall #if defined(unix) 167032144Sminshall zhelp[] = "suspend telnet", 167132144Sminshall #endif /* defined(unix */ 167232144Sminshall shellhelp[] = "invoke a subshell", 1673*38689Sborman modestring[] = "try to enter line-by-line or character-at-a-time mode"; 167432144Sminshall 167532144Sminshall extern int help(), shell(); 167632144Sminshall 167732144Sminshall static Command cmdtab[] = { 1678*38689Sborman { "close", closehelp, bye, 1 }, 1679*38689Sborman { "display", displayhelp, display, 0 }, 1680*38689Sborman { "mode", modestring, modecmd, 0 }, 1681*38689Sborman { "open", openhelp, tn, 0 }, 1682*38689Sborman { "quit", quithelp, quit, 0 }, 1683*38689Sborman { "send", sendhelp, sendcmd, 0 }, 1684*38689Sborman { "set", sethelp, setcmd, 0 }, 1685*38689Sborman { "unset", unsethelp, unsetcmd, 0 }, 1686*38689Sborman { "status", statushelp, status, 0 }, 1687*38689Sborman { "toggle", togglestring, toggle, 0 }, 1688*38689Sborman { "slc", slchelp, slccmd, 0 }, 168932144Sminshall #if defined(TN3270) && defined(unix) 1690*38689Sborman { "transcom", transcomhelp, settranscom, 0 }, 169132144Sminshall #endif /* defined(TN3270) && defined(unix) */ 169232144Sminshall #if defined(unix) 1693*38689Sborman { "z", zhelp, suspend, 0 }, 169432144Sminshall #endif /* defined(unix) */ 169532144Sminshall #if defined(TN3270) 1696*38689Sborman { "!", shellhelp, shell, 1 }, 1697*38689Sborman #else 1698*38689Sborman { "!", shellhelp, shell, 0 }, 1699*38689Sborman #endif 1700*38689Sborman { "?", helphelp, help, 0 }, 170132144Sminshall 0 170232144Sminshall }; 170332144Sminshall 170432144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 170532144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 170632144Sminshall 170732144Sminshall static Command cmdtab2[] = { 1708*38689Sborman { "help", 0, help, 0 }, 1709*38689Sborman { "escape", escapehelp, setescape, 0 }, 1710*38689Sborman { "crmod", crmodhelp, togcrmod, 0 }, 171132144Sminshall 0 171232144Sminshall }; 171332144Sminshall 171435298Sminshall 171532144Sminshall /* 171632144Sminshall * Call routine with argc, argv set from args (terminated by 0). 171732144Sminshall */ 171835298Sminshall 171935417Sminshall /*VARARGS1*/ 172032144Sminshall static 172135298Sminshall call(va_alist) 172235298Sminshall va_dcl 172332144Sminshall { 172435298Sminshall va_list ap; 172535298Sminshall typedef int (*intrtn_t)(); 172635298Sminshall intrtn_t routine; 172735298Sminshall char *args[100]; 172835298Sminshall int argno = 0; 172935298Sminshall 173035298Sminshall va_start(ap); 173135298Sminshall routine = (va_arg(ap, intrtn_t)); 173235495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 173335298Sminshall ; 173435495Sminshall } 173535298Sminshall va_end(ap); 173635495Sminshall return (*routine)(argno-1, args); 173732144Sminshall } 173832144Sminshall 173935298Sminshall 174032144Sminshall static char ** 174132144Sminshall getnextcmd(name) 174232144Sminshall char *name; 174332144Sminshall { 174432144Sminshall Command *c = (Command *) name; 174532144Sminshall 174632144Sminshall return (char **) (c+1); 174732144Sminshall } 174832144Sminshall 174932144Sminshall static Command * 175032144Sminshall getcmd(name) 175132144Sminshall char *name; 175232144Sminshall { 175332144Sminshall Command *cm; 175432144Sminshall 175532144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 175632144Sminshall return cm; 175732144Sminshall } else { 175832144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 175932144Sminshall } 176032144Sminshall } 176132144Sminshall 176232144Sminshall void 1763*38689Sborman command(top, tbuf, cnt) 176432144Sminshall int top; 1765*38689Sborman char *tbuf; 1766*38689Sborman int cnt; 176732144Sminshall { 176832144Sminshall register Command *c; 176932144Sminshall 177032144Sminshall setcommandmode(); 177132144Sminshall if (!top) { 177232144Sminshall putchar('\n'); 177337219Sminshall #if defined(unix) 177432144Sminshall } else { 177532144Sminshall signal(SIGINT, SIG_DFL); 177632144Sminshall signal(SIGQUIT, SIG_DFL); 177732144Sminshall #endif /* defined(unix) */ 177832144Sminshall } 177932144Sminshall for (;;) { 178032144Sminshall printf("%s> ", prompt); 1781*38689Sborman if (tbuf) { 1782*38689Sborman register char *cp; 1783*38689Sborman cp = line; 1784*38689Sborman while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 1785*38689Sborman cnt--; 1786*38689Sborman tbuf = 0; 1787*38689Sborman if (cp == line || *--cp != '\n' || cp == line) 1788*38689Sborman goto getline; 1789*38689Sborman *cp = '\0'; 1790*38689Sborman printf("%s\n", line); 1791*38689Sborman } else { 1792*38689Sborman getline: 1793*38689Sborman if (gets(line) == NULL) { 1794*38689Sborman if (feof(stdin) || ferror(stdin)) 1795*38689Sborman quit(); 1796*38689Sborman break; 1797*38689Sborman } 179832144Sminshall } 179932144Sminshall if (line[0] == 0) 180032144Sminshall break; 180132144Sminshall makeargv(); 180237219Sminshall if (margv[0] == 0) { 180337219Sminshall break; 180437219Sminshall } 180532144Sminshall c = getcmd(margv[0]); 180632144Sminshall if (Ambiguous(c)) { 180732144Sminshall printf("?Ambiguous command\n"); 180832144Sminshall continue; 180932144Sminshall } 181032144Sminshall if (c == 0) { 181132144Sminshall printf("?Invalid command\n"); 181232144Sminshall continue; 181332144Sminshall } 181432144Sminshall if (c->needconnect && !connected) { 181532144Sminshall printf("?Need to be connected first.\n"); 181632144Sminshall continue; 181732144Sminshall } 181832144Sminshall if ((*c->handler)(margc, margv)) { 181932144Sminshall break; 182032144Sminshall } 182132144Sminshall } 182232144Sminshall if (!top) { 182332144Sminshall if (!connected) { 182432144Sminshall longjmp(toplevel, 1); 182532144Sminshall /*NOTREACHED*/ 182632144Sminshall } 182732144Sminshall #if defined(TN3270) 182832144Sminshall if (shell_active == 0) { 1829*38689Sborman setconnmode(0); 183032144Sminshall } 183132144Sminshall #else /* defined(TN3270) */ 1832*38689Sborman setconnmode(0); 183332144Sminshall #endif /* defined(TN3270) */ 183432144Sminshall } 183532144Sminshall } 183632144Sminshall 183732144Sminshall /* 183832144Sminshall * Help command. 183932144Sminshall */ 184032144Sminshall static 184132144Sminshall help(argc, argv) 184232144Sminshall int argc; 184332144Sminshall char *argv[]; 184432144Sminshall { 184532144Sminshall register Command *c; 184632144Sminshall 184732144Sminshall if (argc == 1) { 184832144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 184932144Sminshall for (c = cmdtab; c->name; c++) 1850*38689Sborman if (c->help) { 185132144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 185232144Sminshall c->help); 185332144Sminshall } 185432144Sminshall return 0; 185532144Sminshall } 185632144Sminshall while (--argc > 0) { 185732144Sminshall register char *arg; 185832144Sminshall arg = *++argv; 185932144Sminshall c = getcmd(arg); 186032144Sminshall if (Ambiguous(c)) 186132144Sminshall printf("?Ambiguous help command %s\n", arg); 186232144Sminshall else if (c == (Command *)0) 186332144Sminshall printf("?Invalid help command %s\n", arg); 186432144Sminshall else 186532144Sminshall printf("%s\n", c->help); 186632144Sminshall } 186732144Sminshall return 0; 186832144Sminshall } 1869*38689Sborman 1870*38689Sborman static char *rcname = 0; 1871*38689Sborman static char rcbuf[128]; 1872*38689Sborman 1873*38689Sborman cmdrc(m1, m2) 1874*38689Sborman char *m1, *m2; 1875*38689Sborman { 1876*38689Sborman register Command *c; 1877*38689Sborman FILE *rcfile; 1878*38689Sborman int gotmachine = 0; 1879*38689Sborman int l1 = strlen(m1); 1880*38689Sborman int l2 = strlen(m2); 1881*38689Sborman char m1save[64]; 1882*38689Sborman 1883*38689Sborman strcpy(m1save, m1); 1884*38689Sborman m1 = m1save; 1885*38689Sborman 1886*38689Sborman if (rcname == 0) { 1887*38689Sborman rcname = getenv("HOME"); 1888*38689Sborman if (rcname) 1889*38689Sborman strcpy(rcbuf, rcname); 1890*38689Sborman else 1891*38689Sborman rcbuf[0] = '\0'; 1892*38689Sborman strcat(rcbuf, "/.telnetrc"); 1893*38689Sborman rcname = rcbuf; 1894*38689Sborman } 1895*38689Sborman 1896*38689Sborman if ((rcfile = fopen(rcname, "r")) == 0) { 1897*38689Sborman return; 1898*38689Sborman } 1899*38689Sborman 1900*38689Sborman for (;;) { 1901*38689Sborman if (fgets(line, sizeof(line), rcfile) == NULL) 1902*38689Sborman break; 1903*38689Sborman if (line[0] == 0) 1904*38689Sborman break; 1905*38689Sborman if (line[0] == '#') 1906*38689Sborman continue; 1907*38689Sborman if (gotmachine == 0) { 1908*38689Sborman if (isspace(line[0])) 1909*38689Sborman continue; 1910*38689Sborman if (strncasecmp(line, m1, l1) == 0) 1911*38689Sborman strncpy(line, &line[l1], sizeof(line) - l1); 1912*38689Sborman else if (strncasecmp(line, m2, l2) == 0) 1913*38689Sborman strncpy(line, &line[l2], sizeof(line) - l2); 1914*38689Sborman else 1915*38689Sborman continue; 1916*38689Sborman gotmachine = 1; 1917*38689Sborman } else { 1918*38689Sborman if (!isspace(line[0])) { 1919*38689Sborman gotmachine = 0; 1920*38689Sborman continue; 1921*38689Sborman } 1922*38689Sborman } 1923*38689Sborman makeargv(); 1924*38689Sborman if (margv[0] == 0) 1925*38689Sborman continue; 1926*38689Sborman c = getcmd(margv[0]); 1927*38689Sborman if (Ambiguous(c)) { 1928*38689Sborman printf("?Ambiguous command: %s\n", margv[0]); 1929*38689Sborman continue; 1930*38689Sborman } 1931*38689Sborman if (c == 0) { 1932*38689Sborman printf("?Invalid command: %s\n", margv[0]); 1933*38689Sborman continue; 1934*38689Sborman } 1935*38689Sborman /* 1936*38689Sborman * This should never happen... 1937*38689Sborman */ 1938*38689Sborman if (c->needconnect && !connected) { 1939*38689Sborman printf("?Need to be connected first for %s.\n", margv[0]); 1940*38689Sborman continue; 1941*38689Sborman } 1942*38689Sborman (*c->handler)(margc, margv); 1943*38689Sborman } 1944*38689Sborman fclose(rcfile); 1945*38689Sborman } 1946*38689Sborman 1947*38689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 1948*38689Sborman 1949*38689Sborman /* 1950*38689Sborman * Source route is handed in as 1951*38689Sborman * [!]@hop1@hop2...[@|:]dst 1952*38689Sborman * If the leading ! is present, it is a 1953*38689Sborman * strict source route, otherwise it is 1954*38689Sborman * assmed to be a loose source route. 1955*38689Sborman * 1956*38689Sborman * We fill in the source route option as 1957*38689Sborman * hop1,hop2,hop3...dest 1958*38689Sborman * and return a pointer to hop1, which will 1959*38689Sborman * be the address to connect() to. 1960*38689Sborman * 1961*38689Sborman * Arguments: 1962*38689Sborman * arg: pointer to route list to decipher 1963*38689Sborman * 1964*38689Sborman * cpp: If *cpp is not equal to NULL, this is a 1965*38689Sborman * pointer to a pointer to a character array 1966*38689Sborman * that should be filled in with the option. 1967*38689Sborman * 1968*38689Sborman * lenp: pointer to an integer that contains the 1969*38689Sborman * length of *cpp if *cpp != NULL. 1970*38689Sborman * 1971*38689Sborman * Return values: 1972*38689Sborman * 1973*38689Sborman * Returns the address of the host to connect to. If the 1974*38689Sborman * return value is -1, there was a syntax error in the 1975*38689Sborman * option, either unknown characters, or too many hosts. 1976*38689Sborman * If the return value is 0, one of the hostnames in the 1977*38689Sborman * path is unknown, and *cpp is set to point to the bad 1978*38689Sborman * hostname. 1979*38689Sborman * 1980*38689Sborman * *cpp: If *cpp was equal to NULL, it will be filled 1981*38689Sborman * in with a pointer to our static area that has 1982*38689Sborman * the option filled in. This will be 32bit aligned. 1983*38689Sborman * 1984*38689Sborman * *lenp: This will be filled in with how long the option 1985*38689Sborman * pointed to by *cpp is. 1986*38689Sborman * 1987*38689Sborman */ 1988*38689Sborman unsigned long 1989*38689Sborman sourceroute(arg, cpp, lenp) 1990*38689Sborman char *arg; 1991*38689Sborman char **cpp; 1992*38689Sborman int *lenp; 1993*38689Sborman { 1994*38689Sborman static char lsr[44]; 1995*38689Sborman char *cp, *cp2, *lsrp, *lsrep, *index(); 1996*38689Sborman register int tmp; 1997*38689Sborman struct in_addr sin_addr; 1998*38689Sborman register struct hostent *host = 0; 1999*38689Sborman register char c; 2000*38689Sborman 2001*38689Sborman /* 2002*38689Sborman * Verify the arguments, and make sure we have 2003*38689Sborman * at least 7 bytes for the option. 2004*38689Sborman */ 2005*38689Sborman if (cpp == NULL || lenp == NULL) 2006*38689Sborman return((unsigned long)-1); 2007*38689Sborman if (*cpp != NULL && *lenp < 7) 2008*38689Sborman return((unsigned long)-1); 2009*38689Sborman /* 2010*38689Sborman * Decide whether we have a buffer passed to us, 2011*38689Sborman * or if we need to use our own static buffer. 2012*38689Sborman */ 2013*38689Sborman if (*cpp) { 2014*38689Sborman lsrp = *cpp; 2015*38689Sborman lsrep = lsrp + *lenp; 2016*38689Sborman } else { 2017*38689Sborman *cpp = lsrp = lsr; 2018*38689Sborman lsrep = lsrp + 44; 2019*38689Sborman } 2020*38689Sborman 2021*38689Sborman cp = arg; 2022*38689Sborman 2023*38689Sborman /* 2024*38689Sborman * Next, decide whether we have a loose source 2025*38689Sborman * route or a strict source route, and fill in 2026*38689Sborman * the begining of the option. 2027*38689Sborman */ 2028*38689Sborman if (*cp == '!') { 2029*38689Sborman cp++; 2030*38689Sborman *lsrp++ = IPOPT_SSRR; 2031*38689Sborman } else 2032*38689Sborman *lsrp++ = IPOPT_LSRR; 2033*38689Sborman 2034*38689Sborman if (*cp != '@') 2035*38689Sborman return((unsigned long)-1); 2036*38689Sborman 2037*38689Sborman lsrp++; /* skip over length, we'll fill it in later */ 2038*38689Sborman *lsrp++ = 4; 2039*38689Sborman 2040*38689Sborman cp++; 2041*38689Sborman 2042*38689Sborman sin_addr.s_addr = 0; 2043*38689Sborman 2044*38689Sborman for (c = 0;;) { 2045*38689Sborman if (c == ':') 2046*38689Sborman cp2 = 0; 2047*38689Sborman else for (cp2 = cp; c = *cp2; cp2++) { 2048*38689Sborman if (c == ',') { 2049*38689Sborman *cp2++ = '\0'; 2050*38689Sborman if (*cp2 == '@') 2051*38689Sborman cp2++; 2052*38689Sborman } else if (c == '@') { 2053*38689Sborman *cp2++ = '\0'; 2054*38689Sborman } else if (c == ':') { 2055*38689Sborman *cp2++ = '\0'; 2056*38689Sborman } else 2057*38689Sborman continue; 2058*38689Sborman break; 2059*38689Sborman } 2060*38689Sborman if (!c) 2061*38689Sborman cp2 = 0; 2062*38689Sborman 2063*38689Sborman if ((tmp = inet_addr(cp)) != -1) { 2064*38689Sborman sin_addr.s_addr = tmp; 2065*38689Sborman } else if (host = gethostbyname(cp)) { 2066*38689Sborman #if defined(h_addr) 2067*38689Sborman memcpy((caddr_t)&sin_addr, 2068*38689Sborman host->h_addr_list[0], host->h_length); 2069*38689Sborman #else 2070*38689Sborman memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); 2071*38689Sborman #endif 2072*38689Sborman } else { 2073*38689Sborman *cpp = cp; 2074*38689Sborman return(0); 2075*38689Sborman } 2076*38689Sborman memcpy(lsrp, (char *)&sin_addr, 4); 2077*38689Sborman lsrp += 4; 2078*38689Sborman if (cp2) 2079*38689Sborman cp = cp2; 2080*38689Sborman else 2081*38689Sborman break; 2082*38689Sborman /* 2083*38689Sborman * Check to make sure there is space for next address 2084*38689Sborman */ 2085*38689Sborman if (lsrp + 4 > lsrep) 2086*38689Sborman return((unsigned long)-1); 2087*38689Sborman } 2088*38689Sborman if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 2089*38689Sborman *cpp = 0; 2090*38689Sborman *lenp = 0; 2091*38689Sborman return((unsigned long)-1); 2092*38689Sborman } 2093*38689Sborman *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 2094*38689Sborman *lenp = lsrp - *cpp; 2095*38689Sborman return(sin_addr.s_addr); 2096*38689Sborman } 2097*38689Sborman #endif 2098*38689Sborman 2099*38689Sborman #if defined(sun) 2100*38689Sborman strncasecmp(p1, p2, len) 2101*38689Sborman register char *p1, *p2; 2102*38689Sborman int len; 2103*38689Sborman { 2104*38689Sborman while (len--) { 2105*38689Sborman if (tolower(*p1) != tolower(*p2)) 2106*38689Sborman return(tolower(*p1) - tolower(*p2)); 2107*38689Sborman if (*p1 == '\0') 2108*38689Sborman return(0); 2109*38689Sborman p1++, p2++; 2110*38689Sborman } 2111*38689Sborman return(0); 2112*38689Sborman } 2113*38689Sborman #endif 2114