132144Sminshall #include <sys/types.h> 232144Sminshall #include <sys/socket.h> 332144Sminshall #include <netinet/in.h> 432144Sminshall 532144Sminshall #include <signal.h> 632144Sminshall #include <netdb.h> 732144Sminshall #include <ctype.h> 832144Sminshall 932144Sminshall #include <arpa/telnet.h> 1032144Sminshall 11*32381Sminshall #include "ring.h" 12*32381Sminshall 1332144Sminshall #include "externs.h" 1432144Sminshall #include "defines.h" 1532144Sminshall #include "types.h" 1632144Sminshall 1732144Sminshall char *hostname; 1832144Sminshall 1932144Sminshall #define Ambiguous(s) ((char *)s == ambiguous) 2032144Sminshall static char *ambiguous; /* special return value for command routines */ 2132144Sminshall 2232144Sminshall typedef struct { 2332144Sminshall char *name; /* command name */ 2432144Sminshall char *help; /* help string */ 2532144Sminshall int (*handler)(); /* routine which executes command */ 2632144Sminshall int dohelp; /* Should we give general help information? */ 2732144Sminshall int needconnect; /* Do we need to be connected to execute? */ 2832144Sminshall } Command; 2932144Sminshall 3032144Sminshall static char line[200]; 3132144Sminshall static int margc; 3232144Sminshall static char *margv[20]; 3332144Sminshall 3432144Sminshall /* 3532144Sminshall * Various utility routines. 3632144Sminshall */ 3732144Sminshall 3832144Sminshall static void 3932144Sminshall makeargv() 4032144Sminshall { 4132144Sminshall register char *cp; 4232144Sminshall register char **argp = margv; 4332144Sminshall 4432144Sminshall margc = 0; 4532144Sminshall cp = line; 4632144Sminshall if (*cp == '!') { /* Special case shell escape */ 4732144Sminshall *argp++ = "!"; /* No room in string to get this */ 4832144Sminshall margc++; 4932144Sminshall cp++; 5032144Sminshall } 5132144Sminshall while (*cp) { 5232144Sminshall while (isspace(*cp)) 5332144Sminshall cp++; 5432144Sminshall if (*cp == '\0') 5532144Sminshall break; 5632144Sminshall *argp++ = cp; 5732144Sminshall margc += 1; 5832144Sminshall while (*cp != '\0' && !isspace(*cp)) 5932144Sminshall cp++; 6032144Sminshall if (*cp == '\0') 6132144Sminshall break; 6232144Sminshall *cp++ = '\0'; 6332144Sminshall } 6432144Sminshall *argp++ = 0; 6532144Sminshall } 6632144Sminshall 6732144Sminshall 6832144Sminshall static char ** 6932144Sminshall genget(name, table, next) 7032144Sminshall char *name; /* name to match */ 7132144Sminshall char **table; /* name entry in table */ 7232144Sminshall char **(*next)(); /* routine to return next entry in table */ 7332144Sminshall { 7432144Sminshall register char *p, *q; 7532144Sminshall register char **c, **found; 7632144Sminshall register int nmatches, longest; 7732144Sminshall 7832144Sminshall if (name == 0) { 7932144Sminshall return 0; 8032144Sminshall } 8132144Sminshall longest = 0; 8232144Sminshall nmatches = 0; 8332144Sminshall found = 0; 8432144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 8532144Sminshall for (q = name; 8632144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 8732144Sminshall if (*q == 0) /* exact match? */ 8832144Sminshall return (c); 8932144Sminshall if (!*q) { /* the name was a prefix */ 9032144Sminshall if (q - name > longest) { 9132144Sminshall longest = q - name; 9232144Sminshall nmatches = 1; 9332144Sminshall found = c; 9432144Sminshall } else if (q - name == longest) 9532144Sminshall nmatches++; 9632144Sminshall } 9732144Sminshall } 9832144Sminshall if (nmatches > 1) 9932144Sminshall return (char **)ambiguous; 10032144Sminshall return (found); 10132144Sminshall } 10232144Sminshall 10332144Sminshall /* 10432144Sminshall * Make a character string into a number. 10532144Sminshall * 10632144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 10732144Sminshall */ 10832144Sminshall 10932144Sminshall static 11032144Sminshall special(s) 11132144Sminshall register char *s; 11232144Sminshall { 11332144Sminshall register char c; 11432144Sminshall char b; 11532144Sminshall 11632144Sminshall switch (*s) { 11732144Sminshall case '^': 11832144Sminshall b = *++s; 11932144Sminshall if (b == '?') { 12032144Sminshall c = b | 0x40; /* DEL */ 12132144Sminshall } else { 12232144Sminshall c = b & 0x1f; 12332144Sminshall } 12432144Sminshall break; 12532144Sminshall default: 12632144Sminshall c = *s; 12732144Sminshall break; 12832144Sminshall } 12932144Sminshall return c; 13032144Sminshall } 13132144Sminshall 13232144Sminshall /* 13332144Sminshall * Construct a control character sequence 13432144Sminshall * for a special character. 13532144Sminshall */ 13632144Sminshall static char * 13732144Sminshall control(c) 13832144Sminshall register int c; 13932144Sminshall { 14032144Sminshall static char buf[3]; 14132144Sminshall 14232144Sminshall if (c == 0x7f) 14332144Sminshall return ("^?"); 14432144Sminshall if (c == '\377') { 14532144Sminshall return "off"; 14632144Sminshall } 14732144Sminshall if (c >= 0x20) { 14832144Sminshall buf[0] = c; 14932144Sminshall buf[1] = 0; 15032144Sminshall } else { 15132144Sminshall buf[0] = '^'; 15232144Sminshall buf[1] = '@'+c; 15332144Sminshall buf[2] = 0; 15432144Sminshall } 15532144Sminshall return (buf); 15632144Sminshall } 15732144Sminshall 15832144Sminshall 15932144Sminshall 16032144Sminshall /* 16132144Sminshall * The following are data structures and routines for 16232144Sminshall * the "send" command. 16332144Sminshall * 16432144Sminshall */ 16532144Sminshall 16632144Sminshall struct sendlist { 16732144Sminshall char *name; /* How user refers to it (case independent) */ 16832144Sminshall int what; /* Character to be sent (<0 ==> special) */ 16932144Sminshall char *help; /* Help information (0 ==> no help) */ 17032144Sminshall #if defined(NOT43) 17132144Sminshall int (*routine)(); /* Routine to perform (for special ops) */ 17232144Sminshall #else /* defined(NOT43) */ 17332144Sminshall void (*routine)(); /* Routine to perform (for special ops) */ 17432144Sminshall #endif /* defined(NOT43) */ 17532144Sminshall }; 17632144Sminshall 17732144Sminshall #define SENDQUESTION -1 17832144Sminshall #define SENDESCAPE -3 17932144Sminshall 18032144Sminshall static struct sendlist Sendlist[] = { 18132144Sminshall { "ao", AO, "Send Telnet Abort output" }, 18232144Sminshall { "ayt", AYT, "Send Telnet 'Are You There'" }, 18332144Sminshall { "brk", BREAK, "Send Telnet Break" }, 18432144Sminshall { "ec", EC, "Send Telnet Erase Character" }, 18532144Sminshall { "el", EL, "Send Telnet Erase Line" }, 18632144Sminshall { "escape", SENDESCAPE, "Send current escape character" }, 18732144Sminshall { "ga", GA, "Send Telnet 'Go Ahead' sequence" }, 18832144Sminshall { "ip", IP, "Send Telnet Interrupt Process" }, 18932144Sminshall { "nop", NOP, "Send Telnet 'No operation'" }, 19032144Sminshall { "synch", SYNCH, "Perform Telnet 'Synch operation'", dosynch }, 19132144Sminshall { "?", SENDQUESTION, "Display send options" }, 19232144Sminshall { 0 } 19332144Sminshall }; 19432144Sminshall 19532144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 19632144Sminshall { "break", BREAK, 0 }, 19732144Sminshall 19832144Sminshall { "intp", IP, 0 }, 19932144Sminshall { "interrupt", IP, 0 }, 20032144Sminshall { "intr", IP, 0 }, 20132144Sminshall 20232144Sminshall { "help", SENDQUESTION, 0 }, 20332144Sminshall 20432144Sminshall { 0 } 20532144Sminshall }; 20632144Sminshall 20732144Sminshall static char ** 20832144Sminshall getnextsend(name) 20932144Sminshall char *name; 21032144Sminshall { 21132144Sminshall struct sendlist *c = (struct sendlist *) name; 21232144Sminshall 21332144Sminshall return (char **) (c+1); 21432144Sminshall } 21532144Sminshall 21632144Sminshall static struct sendlist * 21732144Sminshall getsend(name) 21832144Sminshall char *name; 21932144Sminshall { 22032144Sminshall struct sendlist *sl; 22132144Sminshall 22232144Sminshall if ((sl = (struct sendlist *) 22332144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 22432144Sminshall return sl; 22532144Sminshall } else { 22632144Sminshall return (struct sendlist *) 22732144Sminshall genget(name, (char **) Sendlist2, getnextsend); 22832144Sminshall } 22932144Sminshall } 23032144Sminshall 23132144Sminshall static 23232144Sminshall sendcmd(argc, argv) 23332144Sminshall int argc; 23432144Sminshall char **argv; 23532144Sminshall { 23632144Sminshall int what; /* what we are sending this time */ 23732144Sminshall int count; /* how many bytes we are going to need to send */ 23832144Sminshall int i; 23932144Sminshall int question = 0; /* was at least one argument a question */ 24032144Sminshall struct sendlist *s; /* pointer to current command */ 24132144Sminshall 24232144Sminshall if (argc < 2) { 24332144Sminshall printf("need at least one argument for 'send' command\n"); 24432144Sminshall printf("'send ?' for help\n"); 24532144Sminshall return 0; 24632144Sminshall } 24732144Sminshall /* 24832144Sminshall * First, validate all the send arguments. 24932144Sminshall * In addition, we see how much space we are going to need, and 25032144Sminshall * whether or not we will be doing a "SYNCH" operation (which 25132144Sminshall * flushes the network queue). 25232144Sminshall */ 25332144Sminshall count = 0; 25432144Sminshall for (i = 1; i < argc; i++) { 25532144Sminshall s = getsend(argv[i]); 25632144Sminshall if (s == 0) { 25732144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 25832144Sminshall argv[i]); 25932144Sminshall return 0; 26032144Sminshall } else if (Ambiguous(s)) { 26132144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 26232144Sminshall argv[i]); 26332144Sminshall return 0; 26432144Sminshall } 26532144Sminshall switch (s->what) { 26632144Sminshall case SENDQUESTION: 26732144Sminshall break; 26832144Sminshall case SENDESCAPE: 26932144Sminshall count += 1; 27032144Sminshall break; 27132144Sminshall case SYNCH: 27232144Sminshall count += 2; 27332144Sminshall break; 27432144Sminshall default: 27532144Sminshall count += 2; 27632144Sminshall break; 27732144Sminshall } 27832144Sminshall } 27932144Sminshall /* Now, do we have enough room? */ 28032144Sminshall if (NETROOM() < count) { 28132144Sminshall printf("There is not enough room in the buffer TO the network\n"); 28232144Sminshall printf("to process your request. Nothing will be done.\n"); 28332144Sminshall printf("('send synch' will throw away most data in the network\n"); 28432144Sminshall printf("buffer, if this might help.)\n"); 28532144Sminshall return 0; 28632144Sminshall } 28732144Sminshall /* OK, they are all OK, now go through again and actually send */ 28832144Sminshall for (i = 1; i < argc; i++) { 28932144Sminshall if ((s = getsend(argv[i])) == 0) { 29032144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 29132144Sminshall quit(); 29232144Sminshall /*NOTREACHED*/ 29332144Sminshall } 29432144Sminshall if (s->routine) { 29532144Sminshall (*s->routine)(s); 29632144Sminshall } else { 29732144Sminshall switch (what = s->what) { 29832144Sminshall case SYNCH: 29932144Sminshall dosynch(); 30032144Sminshall break; 30132144Sminshall case SENDQUESTION: 30232144Sminshall for (s = Sendlist; s->name; s++) { 30332144Sminshall if (s->help) { 30432144Sminshall printf(s->name); 30532144Sminshall if (s->help) { 30632144Sminshall printf("\t%s", s->help); 30732144Sminshall } 30832144Sminshall printf("\n"); 30932144Sminshall } 31032144Sminshall } 31132144Sminshall question = 1; 31232144Sminshall break; 31332144Sminshall case SENDESCAPE: 31432144Sminshall NETADD(escape); 31532144Sminshall break; 31632144Sminshall default: 31732144Sminshall NET2ADD(IAC, what); 31832144Sminshall break; 31932144Sminshall } 32032144Sminshall } 32132144Sminshall } 32232144Sminshall return !question; 32332144Sminshall } 32432144Sminshall 32532144Sminshall /* 32632144Sminshall * The following are the routines and data structures referred 32732144Sminshall * to by the arguments to the "toggle" command. 32832144Sminshall */ 32932144Sminshall 33032144Sminshall static 33132144Sminshall lclchars() 33232144Sminshall { 33332144Sminshall donelclchars = 1; 33432144Sminshall return 1; 33532144Sminshall } 33632144Sminshall 33732144Sminshall static 33832144Sminshall togdebug() 33932144Sminshall { 34032144Sminshall #ifndef NOT43 34132144Sminshall if (net > 0 && 34232144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 34332144Sminshall perror("setsockopt (SO_DEBUG)"); 34432144Sminshall } 34532144Sminshall #else /* NOT43 */ 34632144Sminshall if (debug) { 34732144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 34832144Sminshall perror("setsockopt (SO_DEBUG)"); 34932144Sminshall } else 35032144Sminshall printf("Cannot turn off socket debugging\n"); 35132144Sminshall #endif /* NOT43 */ 35232144Sminshall return 1; 35332144Sminshall } 35432144Sminshall 35532144Sminshall 35632144Sminshall static int 35732144Sminshall togcrlf() 35832144Sminshall { 35932144Sminshall if (crlf) { 36032144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 36132144Sminshall } else { 36232144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 36332144Sminshall } 36432144Sminshall return 1; 36532144Sminshall } 36632144Sminshall 36732144Sminshall 36832144Sminshall static int 36932144Sminshall togbinary() 37032144Sminshall { 37132144Sminshall donebinarytoggle = 1; 37232144Sminshall 37332144Sminshall if (myopts[TELOPT_BINARY] == 0) { /* Go into binary mode */ 37432144Sminshall NET2ADD(IAC, DO); 37532144Sminshall NETADD(TELOPT_BINARY); 37632144Sminshall printoption("<SENT", doopt, TELOPT_BINARY, 0); 37732144Sminshall NET2ADD(IAC, WILL); 37832144Sminshall NETADD(TELOPT_BINARY); 37932144Sminshall printoption("<SENT", doopt, TELOPT_BINARY, 0); 38032144Sminshall hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 1; 38132144Sminshall printf("Negotiating binary mode with remote host.\n"); 38232144Sminshall } else { /* Turn off binary mode */ 38332144Sminshall NET2ADD(IAC, DONT); 38432144Sminshall NETADD(TELOPT_BINARY); 38532144Sminshall printoption("<SENT", dont, TELOPT_BINARY, 0); 38632144Sminshall NET2ADD(IAC, DONT); 38732144Sminshall NETADD(TELOPT_BINARY); 38832144Sminshall printoption("<SENT", dont, TELOPT_BINARY, 0); 38932144Sminshall hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 0; 39032144Sminshall printf("Negotiating network ascii mode with remote host.\n"); 39132144Sminshall } 39232144Sminshall return 1; 39332144Sminshall } 39432144Sminshall 39532144Sminshall 39632144Sminshall 39732144Sminshall extern int togglehelp(); 39832144Sminshall 39932144Sminshall struct togglelist { 40032144Sminshall char *name; /* name of toggle */ 40132144Sminshall char *help; /* help message */ 40232144Sminshall int (*handler)(); /* routine to do actual setting */ 40332144Sminshall int dohelp; /* should we display help information */ 40432144Sminshall int *variable; 40532144Sminshall char *actionexplanation; 40632144Sminshall }; 40732144Sminshall 40832144Sminshall static struct togglelist Togglelist[] = { 40932144Sminshall { "autoflush", 41032144Sminshall "toggle flushing of output when sending interrupt characters", 41132144Sminshall 0, 41232144Sminshall 1, 41332144Sminshall &autoflush, 41432144Sminshall "flush output when sending interrupt characters" }, 41532144Sminshall { "autosynch", 41632144Sminshall "toggle automatic sending of interrupt characters in urgent mode", 41732144Sminshall 0, 41832144Sminshall 1, 41932144Sminshall &autosynch, 42032144Sminshall "send interrupt characters in urgent mode" }, 42132144Sminshall { "binary", 42232144Sminshall "toggle sending and receiving of binary data", 42332144Sminshall togbinary, 42432144Sminshall 1, 42532144Sminshall 0, 42632144Sminshall 0 }, 42732144Sminshall { "crlf", 42832144Sminshall "toggle sending carriage returns as telnet <CR><LF>", 42932144Sminshall togcrlf, 43032144Sminshall 1, 43132144Sminshall &crlf, 43232144Sminshall 0 }, 43332144Sminshall { "crmod", 43432144Sminshall "toggle mapping of received carriage returns", 43532144Sminshall 0, 43632144Sminshall 1, 43732144Sminshall &crmod, 43832144Sminshall "map carriage return on output" }, 43932144Sminshall { "localchars", 44032144Sminshall "toggle local recognition of certain control characters", 44132144Sminshall lclchars, 44232144Sminshall 1, 44332144Sminshall &localchars, 44432144Sminshall "recognize certain control characters" }, 44532144Sminshall { " ", "", 0, 1 }, /* empty line */ 44632144Sminshall { "debug", 44732144Sminshall "(debugging) toggle debugging", 44832144Sminshall togdebug, 44932144Sminshall 1, 45032144Sminshall &debug, 45132144Sminshall "turn on socket level debugging" }, 45232144Sminshall { "netdata", 45332144Sminshall "(debugging) toggle printing of hexadecimal network data", 45432144Sminshall 0, 45532144Sminshall 1, 45632144Sminshall &netdata, 45732144Sminshall "print hexadecimal representation of network traffic" }, 45832144Sminshall { "options", 45932144Sminshall "(debugging) toggle viewing of options processing", 46032144Sminshall 0, 46132144Sminshall 1, 46232144Sminshall &showoptions, 46332144Sminshall "show option processing" }, 46432144Sminshall { " ", "", 0, 1 }, /* empty line */ 46532144Sminshall { "?", 46632144Sminshall "display help information", 46732144Sminshall togglehelp, 46832144Sminshall 1 }, 46932144Sminshall { "help", 47032144Sminshall "display help information", 47132144Sminshall togglehelp, 47232144Sminshall 0 }, 47332144Sminshall { 0 } 47432144Sminshall }; 47532144Sminshall 47632144Sminshall static 47732144Sminshall togglehelp() 47832144Sminshall { 47932144Sminshall struct togglelist *c; 48032144Sminshall 48132144Sminshall for (c = Togglelist; c->name; c++) { 48232144Sminshall if (c->dohelp) { 48332144Sminshall printf("%s\t%s\n", c->name, c->help); 48432144Sminshall } 48532144Sminshall } 48632144Sminshall return 0; 48732144Sminshall } 48832144Sminshall 48932144Sminshall static char ** 49032144Sminshall getnexttoggle(name) 49132144Sminshall char *name; 49232144Sminshall { 49332144Sminshall struct togglelist *c = (struct togglelist *) name; 49432144Sminshall 49532144Sminshall return (char **) (c+1); 49632144Sminshall } 49732144Sminshall 49832144Sminshall static struct togglelist * 49932144Sminshall gettoggle(name) 50032144Sminshall char *name; 50132144Sminshall { 50232144Sminshall return (struct togglelist *) 50332144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 50432144Sminshall } 50532144Sminshall 50632144Sminshall static 50732144Sminshall toggle(argc, argv) 50832144Sminshall int argc; 50932144Sminshall char *argv[]; 51032144Sminshall { 51132144Sminshall int retval = 1; 51232144Sminshall char *name; 51332144Sminshall struct togglelist *c; 51432144Sminshall 51532144Sminshall if (argc < 2) { 51632144Sminshall fprintf(stderr, 51732144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 51832144Sminshall return 0; 51932144Sminshall } 52032144Sminshall argc--; 52132144Sminshall argv++; 52232144Sminshall while (argc--) { 52332144Sminshall name = *argv++; 52432144Sminshall c = gettoggle(name); 52532144Sminshall if (Ambiguous(c)) { 52632144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 52732144Sminshall name); 52832144Sminshall return 0; 52932144Sminshall } else if (c == 0) { 53032144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 53132144Sminshall name); 53232144Sminshall return 0; 53332144Sminshall } else { 53432144Sminshall if (c->variable) { 53532144Sminshall *c->variable = !*c->variable; /* invert it */ 53632144Sminshall if (c->actionexplanation) { 53732144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 53832144Sminshall c->actionexplanation); 53932144Sminshall } 54032144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 54132144Sminshall c->actionexplanation); 54232144Sminshall } 54332144Sminshall if (c->handler) { 54432144Sminshall retval &= (*c->handler)(c); 54532144Sminshall } 54632144Sminshall } 54732144Sminshall } 54832144Sminshall return retval; 54932144Sminshall } 55032144Sminshall 55132144Sminshall /* 55232144Sminshall * The following perform the "set" command. 55332144Sminshall */ 55432144Sminshall 55532144Sminshall struct setlist { 55632144Sminshall char *name; /* name */ 55732144Sminshall char *help; /* help information */ 55832144Sminshall char *charp; /* where it is located at */ 55932144Sminshall }; 56032144Sminshall 56132144Sminshall static struct setlist Setlist[] = { 56232144Sminshall { "echo", "character to toggle local echoing on/off", &echoc }, 56332144Sminshall { "escape", "character to escape back to telnet command mode", &escape }, 56432144Sminshall { " ", "" }, 56532144Sminshall { " ", "The following need 'localchars' to be toggled true", 0 }, 56632144Sminshall { "erase", "character to cause an Erase Character", &termEraseChar }, 56732144Sminshall { "flushoutput", "character to cause an Abort Oubput", &termFlushChar }, 56832144Sminshall { "interrupt", "character to cause an Interrupt Process", &termIntChar }, 56932144Sminshall { "kill", "character to cause an Erase Line", &termKillChar }, 57032144Sminshall { "quit", "character to cause a Break", &termQuitChar }, 57132144Sminshall { "eof", "character to cause an EOF ", &termEofChar }, 57232144Sminshall { 0 } 57332144Sminshall }; 57432144Sminshall 57532144Sminshall static char ** 57632144Sminshall getnextset(name) 57732144Sminshall char *name; 57832144Sminshall { 57932144Sminshall struct setlist *c = (struct setlist *)name; 58032144Sminshall 58132144Sminshall return (char **) (c+1); 58232144Sminshall } 58332144Sminshall 58432144Sminshall static struct setlist * 58532144Sminshall getset(name) 58632144Sminshall char *name; 58732144Sminshall { 58832144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 58932144Sminshall } 59032144Sminshall 59132144Sminshall static 59232144Sminshall setcmd(argc, argv) 59332144Sminshall int argc; 59432144Sminshall char *argv[]; 59532144Sminshall { 59632144Sminshall int value; 59732144Sminshall struct setlist *ct; 59832144Sminshall 59932144Sminshall /* XXX back we go... sigh */ 60032144Sminshall if (argc != 3) { 60132144Sminshall if ((argc == 2) && 60232144Sminshall ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 60332144Sminshall for (ct = Setlist; ct->name; ct++) { 60432144Sminshall printf("%s\t%s\n", ct->name, ct->help); 60532144Sminshall } 60632144Sminshall printf("?\tdisplay help information\n"); 60732144Sminshall } else { 60832144Sminshall printf("Format is 'set Name Value'\n'set ?' for help.\n"); 60932144Sminshall } 61032144Sminshall return 0; 61132144Sminshall } 61232144Sminshall 61332144Sminshall ct = getset(argv[1]); 61432144Sminshall if (ct == 0) { 61532144Sminshall fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 61632144Sminshall argv[1]); 61732144Sminshall return 0; 61832144Sminshall } else if (Ambiguous(ct)) { 61932144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 62032144Sminshall argv[1]); 62132144Sminshall return 0; 62232144Sminshall } else { 62332144Sminshall if (strcmp("off", argv[2])) { 62432144Sminshall value = special(argv[2]); 62532144Sminshall } else { 62632144Sminshall value = -1; 62732144Sminshall } 62832144Sminshall *(ct->charp) = value; 62932144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 63032144Sminshall } 63132144Sminshall return 1; 63232144Sminshall } 63332144Sminshall 63432144Sminshall /* 63532144Sminshall * The following are the data structures and routines for the 63632144Sminshall * 'mode' command. 63732144Sminshall */ 63832144Sminshall 63932144Sminshall static 64032144Sminshall dolinemode() 64132144Sminshall { 64232144Sminshall if (hisopts[TELOPT_SGA]) { 64332144Sminshall wontoption(TELOPT_SGA, 0); 64432144Sminshall } 64532144Sminshall if (hisopts[TELOPT_ECHO]) { 64632144Sminshall wontoption(TELOPT_ECHO, 0); 64732144Sminshall } 64832144Sminshall return 1; 64932144Sminshall } 65032144Sminshall 65132144Sminshall static 65232144Sminshall docharmode() 65332144Sminshall { 65432144Sminshall if (!hisopts[TELOPT_SGA]) { 65532144Sminshall willoption(TELOPT_SGA, 0); 65632144Sminshall } 65732144Sminshall if (!hisopts[TELOPT_ECHO]) { 65832144Sminshall willoption(TELOPT_ECHO, 0); 65932144Sminshall } 66032144Sminshall return 1; 66132144Sminshall } 66232144Sminshall 66332144Sminshall static Command Mode_commands[] = { 66432144Sminshall { "character", "character-at-a-time mode", docharmode, 1, 1 }, 66532144Sminshall { "line", "line-by-line mode", dolinemode, 1, 1 }, 66632144Sminshall { 0 }, 66732144Sminshall }; 66832144Sminshall 66932144Sminshall static char ** 67032144Sminshall getnextmode(name) 67132144Sminshall char *name; 67232144Sminshall { 67332144Sminshall Command *c = (Command *) name; 67432144Sminshall 67532144Sminshall return (char **) (c+1); 67632144Sminshall } 67732144Sminshall 67832144Sminshall static Command * 67932144Sminshall getmodecmd(name) 68032144Sminshall char *name; 68132144Sminshall { 68232144Sminshall return (Command *) genget(name, (char **) Mode_commands, getnextmode); 68332144Sminshall } 68432144Sminshall 68532144Sminshall static 68632144Sminshall modecmd(argc, argv) 68732144Sminshall int argc; 68832144Sminshall char *argv[]; 68932144Sminshall { 69032144Sminshall Command *mt; 69132144Sminshall 69232144Sminshall if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) { 69332144Sminshall printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 69432144Sminshall for (mt = Mode_commands; mt->name; mt++) { 69532144Sminshall printf("%s\t%s\n", mt->name, mt->help); 69632144Sminshall } 69732144Sminshall return 0; 69832144Sminshall } 69932144Sminshall mt = getmodecmd(argv[1]); 70032144Sminshall if (mt == 0) { 70132144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 70232144Sminshall return 0; 70332144Sminshall } else if (Ambiguous(mt)) { 70432144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 70532144Sminshall return 0; 70632144Sminshall } else { 70732144Sminshall (*mt->handler)(); 70832144Sminshall } 70932144Sminshall return 1; 71032144Sminshall } 71132144Sminshall 71232144Sminshall /* 71332144Sminshall * The following data structures and routines implement the 71432144Sminshall * "display" command. 71532144Sminshall */ 71632144Sminshall 71732144Sminshall static 71832144Sminshall display(argc, argv) 71932144Sminshall int argc; 72032144Sminshall char *argv[]; 72132144Sminshall { 72232144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 72332144Sminshall if (*tl->variable) { \ 72432144Sminshall printf("will"); \ 72532144Sminshall } else { \ 72632144Sminshall printf("won't"); \ 72732144Sminshall } \ 72832144Sminshall printf(" %s.\n", tl->actionexplanation); \ 72932144Sminshall } 73032144Sminshall 73132144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 73232144Sminshall printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \ 73332144Sminshall } 73432144Sminshall 73532144Sminshall struct togglelist *tl; 73632144Sminshall struct setlist *sl; 73732144Sminshall 73832144Sminshall if (argc == 1) { 73932144Sminshall for (tl = Togglelist; tl->name; tl++) { 74032144Sminshall dotog(tl); 74132144Sminshall } 74232144Sminshall printf("\n"); 74332144Sminshall for (sl = Setlist; sl->name; sl++) { 74432144Sminshall doset(sl); 74532144Sminshall } 74632144Sminshall } else { 74732144Sminshall int i; 74832144Sminshall 74932144Sminshall for (i = 1; i < argc; i++) { 75032144Sminshall sl = getset(argv[i]); 75132144Sminshall tl = gettoggle(argv[i]); 75232144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 75332144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 75432144Sminshall return 0; 75532144Sminshall } else if (!sl && !tl) { 75632144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 75732144Sminshall return 0; 75832144Sminshall } else { 75932144Sminshall if (tl) { 76032144Sminshall dotog(tl); 76132144Sminshall } 76232144Sminshall if (sl) { 76332144Sminshall doset(sl); 76432144Sminshall } 76532144Sminshall } 76632144Sminshall } 76732144Sminshall } 76832144Sminshall return 1; 76932144Sminshall #undef doset 77032144Sminshall #undef dotog 77132144Sminshall } 77232144Sminshall 77332144Sminshall /* 77432144Sminshall * The following are the data structures, and many of the routines, 77532144Sminshall * relating to command processing. 77632144Sminshall */ 77732144Sminshall 77832144Sminshall /* 77932144Sminshall * Set the escape character. 78032144Sminshall */ 78132144Sminshall static 78232144Sminshall setescape(argc, argv) 78332144Sminshall int argc; 78432144Sminshall char *argv[]; 78532144Sminshall { 78632144Sminshall register char *arg; 78732144Sminshall char buf[50]; 78832144Sminshall 78932144Sminshall printf( 79032144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 79132144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 79232144Sminshall if (argc > 2) 79332144Sminshall arg = argv[1]; 79432144Sminshall else { 79532144Sminshall printf("new escape character: "); 79632144Sminshall gets(buf); 79732144Sminshall arg = buf; 79832144Sminshall } 79932144Sminshall if (arg[0] != '\0') 80032144Sminshall escape = arg[0]; 80132144Sminshall if (!In3270) { 80232144Sminshall printf("Escape character is '%s'.\n", control(escape)); 80332144Sminshall } 80432144Sminshall fflush(stdout); 80532144Sminshall return 1; 80632144Sminshall } 80732144Sminshall 80832144Sminshall /*VARARGS*/ 80932144Sminshall static 81032144Sminshall togcrmod() 81132144Sminshall { 81232144Sminshall crmod = !crmod; 81332144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 81432144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 81532144Sminshall fflush(stdout); 81632144Sminshall return 1; 81732144Sminshall } 81832144Sminshall 81932144Sminshall /*VARARGS*/ 82032144Sminshall suspend() 82132144Sminshall { 82232144Sminshall setcommandmode(); 82332144Sminshall #if defined(unix) 82432144Sminshall kill(0, SIGTSTP); 82532144Sminshall #endif /* defined(unix) */ 82632144Sminshall /* reget parameters in case they were changed */ 82732144Sminshall TerminalSaveState(); 82832144Sminshall setconnmode(); 82932144Sminshall return 1; 83032144Sminshall } 83132144Sminshall 83232144Sminshall /*VARARGS*/ 83332144Sminshall static 83432144Sminshall bye(argc, argv) 83532144Sminshall int argc; /* Number of arguments */ 83632144Sminshall char *argv[]; /* arguments */ 83732144Sminshall { 83832144Sminshall if (connected) { 83932144Sminshall shutdown(net, 2); 84032144Sminshall printf("Connection closed.\n"); 84132144Sminshall NetClose(net); 84232144Sminshall connected = 0; 84332144Sminshall /* reset options */ 84432144Sminshall tninit(); 84532144Sminshall #if defined(TN3270) 84632144Sminshall SetIn3270(); /* Get out of 3270 mode */ 84732144Sminshall #endif /* defined(TN3270) */ 84832144Sminshall } 84932144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 85032144Sminshall longjmp(toplevel, 1); 85132144Sminshall /* NOTREACHED */ 85232144Sminshall } 85332144Sminshall return 1; /* Keep lint, etc., happy */ 85432144Sminshall } 85532144Sminshall 85632144Sminshall /*VARARGS*/ 85732144Sminshall quit() 85832144Sminshall { 85932144Sminshall (void) call(bye, "bye", "fromquit", 0); 86032144Sminshall Exit(0); 86132144Sminshall /*NOTREACHED*/ 86232144Sminshall return 1; /* just to keep lint happy */ 86332144Sminshall } 86432144Sminshall 86532144Sminshall /* 86632144Sminshall * Print status about the connection. 86732144Sminshall */ 86832144Sminshall static 86932144Sminshall status(argc, argv) 87032144Sminshall int argc; 87132144Sminshall char *argv[]; 87232144Sminshall { 87332144Sminshall if (connected) { 87432144Sminshall printf("Connected to %s.\n", hostname); 87532144Sminshall if (argc < 2) { 87632144Sminshall printf("Operating in %s.\n", 87732144Sminshall modelist[getconnmode()].modedescriptions); 87832144Sminshall if (localchars) { 87932144Sminshall printf("Catching signals locally.\n"); 88032144Sminshall } 88132144Sminshall } 88232144Sminshall } else { 88332144Sminshall printf("No connection.\n"); 88432144Sminshall } 88532144Sminshall # if !defined(TN3270) 88632144Sminshall printf("Escape character is '%s'.\n", control(escape)); 88732144Sminshall fflush(stdout); 88832144Sminshall # else /* !defined(TN3270) */ 88932144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 89032144Sminshall printf("Escape character is '%s'.\n", control(escape)); 89132144Sminshall } 89232144Sminshall # if defined(unix) 89332144Sminshall if (In3270 && transcom) { 89432144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 89532144Sminshall } 89632144Sminshall # endif /* defined(unix) */ 89732144Sminshall fflush(stdout); 89832144Sminshall if (In3270) { 89932144Sminshall return 0; 90032144Sminshall } 90132144Sminshall # endif /* defined(TN3270) */ 90232144Sminshall return 1; 90332144Sminshall } 90432144Sminshall 90532144Sminshall #if defined(TN3270) && defined(unix) 90632144Sminshall static 90732144Sminshall settranscom(argc, argv) 90832144Sminshall int argc; 90932144Sminshall char *argv[]; 91032144Sminshall { 91132144Sminshall int i, len = 0; 91232144Sminshall char *strcpy(), *strcat(); 91332144Sminshall 91432144Sminshall if (argc == 1 && transcom) { 91532144Sminshall transcom = 0; 91632144Sminshall } 91732144Sminshall if (argc == 1) { 91832144Sminshall return; 91932144Sminshall } 92032144Sminshall for (i = 1; i < argc; ++i) { 92132144Sminshall len += 1 + strlen(argv[1]); 92232144Sminshall } 92332144Sminshall transcom = tline; 92432144Sminshall (void) strcpy(transcom, argv[1]); 92532144Sminshall for (i = 2; i < argc; ++i) { 92632144Sminshall (void) strcat(transcom, " "); 92732144Sminshall (void) strcat(transcom, argv[i]); 92832144Sminshall } 92932144Sminshall } 93032144Sminshall #endif /* defined(TN3270) && defined(unix) */ 93132144Sminshall 93232144Sminshall 93332144Sminshall 93432144Sminshall int 93532144Sminshall tn(argc, argv) 93632144Sminshall int argc; 93732144Sminshall char *argv[]; 93832144Sminshall { 93932144Sminshall register struct hostent *host = 0; 94032144Sminshall struct sockaddr_in sin; 94132144Sminshall struct servent *sp = 0; 94232144Sminshall static char hnamebuf[32]; 94332144Sminshall 94432144Sminshall 94532144Sminshall #if defined(MSDOS) 94632144Sminshall char *cp; 94732144Sminshall #endif /* defined(MSDOS) */ 94832144Sminshall 94932144Sminshall if (connected) { 95032144Sminshall printf("?Already connected to %s\n", hostname); 95132144Sminshall return 0; 95232144Sminshall } 95332144Sminshall if (argc < 2) { 95432144Sminshall (void) strcpy(line, "Connect "); 95532144Sminshall printf("(to) "); 95632144Sminshall gets(&line[strlen(line)]); 95732144Sminshall makeargv(); 95832144Sminshall argc = margc; 95932144Sminshall argv = margv; 96032144Sminshall } 96132144Sminshall if ((argc < 2) || (argc > 3)) { 96232144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 96332144Sminshall return 0; 96432144Sminshall } 96532144Sminshall #if defined(MSDOS) 96632144Sminshall for (cp = argv[1]; *cp; cp++) { 96732144Sminshall if (isupper(*cp)) { 96832144Sminshall *cp = tolower(*cp); 96932144Sminshall } 97032144Sminshall } 97132144Sminshall #endif /* defined(MSDOS) */ 97232144Sminshall sin.sin_addr.s_addr = inet_addr(argv[1]); 97332144Sminshall if (sin.sin_addr.s_addr != -1) { 97432144Sminshall sin.sin_family = AF_INET; 97532144Sminshall (void) strcpy(hnamebuf, argv[1]); 97632144Sminshall hostname = hnamebuf; 97732144Sminshall } else { 97832144Sminshall host = gethostbyname(argv[1]); 97932144Sminshall if (host) { 98032144Sminshall sin.sin_family = host->h_addrtype; 98132144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 98232144Sminshall memcpy((caddr_t)&sin.sin_addr, 98332144Sminshall host->h_addr_list[0], host->h_length); 98432144Sminshall #else /* defined(h_addr) */ 98532144Sminshall memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 98632144Sminshall #endif /* defined(h_addr) */ 98732144Sminshall hostname = host->h_name; 98832144Sminshall } else { 98932144Sminshall printf("%s: unknown host\n", argv[1]); 99032144Sminshall return 0; 99132144Sminshall } 99232144Sminshall } 99332144Sminshall if (argc == 3) { 99432144Sminshall sin.sin_port = atoi(argv[2]); 99532144Sminshall if (sin.sin_port == 0) { 99632144Sminshall sp = getservbyname(argv[2], "tcp"); 99732144Sminshall if (sp) 99832144Sminshall sin.sin_port = sp->s_port; 99932144Sminshall else { 100032144Sminshall printf("%s: bad port number\n", argv[2]); 100132144Sminshall return 0; 100232144Sminshall } 100332144Sminshall } else { 100432144Sminshall sin.sin_port = atoi(argv[2]); 100532144Sminshall sin.sin_port = htons(sin.sin_port); 100632144Sminshall } 100732144Sminshall telnetport = 0; 100832144Sminshall } else { 100932144Sminshall if (sp == 0) { 101032144Sminshall sp = getservbyname("telnet", "tcp"); 101132144Sminshall if (sp == 0) { 101232144Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n",1); 101332144Sminshall return 0; 101432144Sminshall } 101532144Sminshall sin.sin_port = sp->s_port; 101632144Sminshall } 101732144Sminshall telnetport = 1; 101832144Sminshall } 101932144Sminshall #if defined(unix) 102032144Sminshall signal(SIGINT, intr); 102132144Sminshall signal(SIGQUIT, intr2); 102232144Sminshall signal(SIGPIPE, deadpeer); 102332144Sminshall #endif /* defined(unix) */ 102432144Sminshall printf("Trying...\n"); 102532144Sminshall do { 102632144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 102732144Sminshall if (net < 0) { 102832144Sminshall perror("telnet: socket"); 102932144Sminshall return 0; 103032144Sminshall } 103132144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 103232144Sminshall perror("setsockopt (SO_DEBUG)"); 103332144Sminshall } 103432144Sminshall 103532144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 103632144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 103732144Sminshall if (host && host->h_addr_list[1]) { 103832144Sminshall int oerrno = errno; 103932144Sminshall 104032144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 104132144Sminshall inet_ntoa(sin.sin_addr)); 104232144Sminshall errno = oerrno; 104332144Sminshall perror((char *)0); 104432144Sminshall host->h_addr_list++; 104532144Sminshall memcpy((caddr_t)&sin.sin_addr, 104632144Sminshall host->h_addr_list[0], host->h_length); 104732144Sminshall fprintf(stderr, "Trying %s...\n", 104832144Sminshall inet_ntoa(sin.sin_addr)); 104932144Sminshall (void) NetClose(net); 105032144Sminshall continue; 105132144Sminshall } 105232144Sminshall #endif /* defined(h_addr) */ 105332144Sminshall perror("telnet: Unable to connect to remote host"); 105432144Sminshall #if defined(unix) 105532144Sminshall signal(SIGINT, SIG_DFL); 105632144Sminshall signal(SIGQUIT, SIG_DFL); 105732144Sminshall #endif /* defined(unix) */ 105832144Sminshall return 0; 105932144Sminshall } 106032144Sminshall connected++; 106132144Sminshall } while (connected == 0); 106232144Sminshall call(status, "status", "notmuch", 0); 106332144Sminshall if (setjmp(peerdied) == 0) 106432144Sminshall telnet(); 106532144Sminshall NetClose(net); 1066*32381Sminshall ExitString("Connection closed by foreign host.\n",1); 106732144Sminshall /*NOTREACHED*/ 106832144Sminshall } 106932144Sminshall 107032144Sminshall 107132144Sminshall #define HELPINDENT (sizeof ("connect")) 107232144Sminshall 107332144Sminshall static char 107432144Sminshall openhelp[] = "connect to a site", 107532144Sminshall closehelp[] = "close current connection", 107632144Sminshall quithelp[] = "exit telnet", 107732144Sminshall statushelp[] = "print status information", 107832144Sminshall helphelp[] = "print help information", 107932144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 108032144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 108132144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 108232144Sminshall displayhelp[] = "display operating parameters", 108332144Sminshall #if defined(TN3270) && defined(unix) 108432144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 108532144Sminshall #endif /* defined(TN3270) && defined(unix) */ 108632144Sminshall #if defined(unix) 108732144Sminshall zhelp[] = "suspend telnet", 108832144Sminshall #endif /* defined(unix */ 108932144Sminshall #if defined(TN3270) 109032144Sminshall shellhelp[] = "invoke a subshell", 109132144Sminshall #endif /* defined(TN3270) */ 109232144Sminshall modehelp[] = "try to enter line-by-line or character-at-a-time mode"; 109332144Sminshall 109432144Sminshall extern int help(), shell(); 109532144Sminshall 109632144Sminshall static Command cmdtab[] = { 109732144Sminshall { "close", closehelp, bye, 1, 1 }, 109832144Sminshall { "display", displayhelp, display, 1, 0 }, 109932144Sminshall { "mode", modehelp, modecmd, 1, 1 }, 110032144Sminshall { "open", openhelp, tn, 1, 0 }, 110132144Sminshall { "quit", quithelp, quit, 1, 0 }, 110232144Sminshall { "send", sendhelp, sendcmd, 1, 1 }, 110332144Sminshall { "set", sethelp, setcmd, 1, 0 }, 110432144Sminshall { "status", statushelp, status, 1, 0 }, 110532144Sminshall { "toggle", togglestring, toggle, 1, 0 }, 110632144Sminshall #if defined(TN3270) && defined(unix) 110732144Sminshall { "transcom", transcomhelp, settranscom, 1, 0 }, 110832144Sminshall #endif /* defined(TN3270) && defined(unix) */ 110932144Sminshall #if defined(unix) 111032144Sminshall { "z", zhelp, suspend, 1, 0 }, 111132144Sminshall #endif /* defined(unix) */ 111232144Sminshall #if defined(TN3270) 111332144Sminshall { "!", shellhelp, shell, 1, 1 }, 111432144Sminshall #endif /* defined(TN3270) */ 111532144Sminshall { "?", helphelp, help, 1, 0 }, 111632144Sminshall 0 111732144Sminshall }; 111832144Sminshall 111932144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 112032144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 112132144Sminshall 112232144Sminshall static Command cmdtab2[] = { 112332144Sminshall { "help", helphelp, help, 0, 0 }, 112432144Sminshall { "escape", escapehelp, setescape, 1, 0 }, 112532144Sminshall { "crmod", crmodhelp, togcrmod, 1, 0 }, 112632144Sminshall 0 112732144Sminshall }; 112832144Sminshall 112932144Sminshall /* 113032144Sminshall * Call routine with argc, argv set from args (terminated by 0). 113132144Sminshall * VARARGS2 113232144Sminshall */ 113332144Sminshall static 113432144Sminshall call(routine, args) 113532144Sminshall int (*routine)(); 113632144Sminshall char *args; 113732144Sminshall { 113832144Sminshall register char **argp; 113932144Sminshall register int argc; 114032144Sminshall 114132144Sminshall for (argc = 0, argp = &args; *argp++ != 0; argc++) 114232144Sminshall ; 114332144Sminshall return (*routine)(argc, &args); 114432144Sminshall } 114532144Sminshall 114632144Sminshall static char ** 114732144Sminshall getnextcmd(name) 114832144Sminshall char *name; 114932144Sminshall { 115032144Sminshall Command *c = (Command *) name; 115132144Sminshall 115232144Sminshall return (char **) (c+1); 115332144Sminshall } 115432144Sminshall 115532144Sminshall static Command * 115632144Sminshall getcmd(name) 115732144Sminshall char *name; 115832144Sminshall { 115932144Sminshall Command *cm; 116032144Sminshall 116132144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 116232144Sminshall return cm; 116332144Sminshall } else { 116432144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 116532144Sminshall } 116632144Sminshall } 116732144Sminshall 116832144Sminshall void 116932144Sminshall command(top) 117032144Sminshall int top; 117132144Sminshall { 117232144Sminshall register Command *c; 117332144Sminshall 117432144Sminshall setcommandmode(); 117532144Sminshall if (!top) { 117632144Sminshall putchar('\n'); 117732144Sminshall } else { 117832144Sminshall #if defined(unix) 117932144Sminshall signal(SIGINT, SIG_DFL); 118032144Sminshall signal(SIGQUIT, SIG_DFL); 118132144Sminshall #endif /* defined(unix) */ 118232144Sminshall } 118332144Sminshall for (;;) { 118432144Sminshall printf("%s> ", prompt); 118532144Sminshall if (gets(line) == NULL) { 118632144Sminshall if (feof(stdin) || ferror(stdin)) 118732144Sminshall quit(); 118832144Sminshall break; 118932144Sminshall } 119032144Sminshall if (line[0] == 0) 119132144Sminshall break; 119232144Sminshall makeargv(); 119332144Sminshall c = getcmd(margv[0]); 119432144Sminshall if (Ambiguous(c)) { 119532144Sminshall printf("?Ambiguous command\n"); 119632144Sminshall continue; 119732144Sminshall } 119832144Sminshall if (c == 0) { 119932144Sminshall printf("?Invalid command\n"); 120032144Sminshall continue; 120132144Sminshall } 120232144Sminshall if (c->needconnect && !connected) { 120332144Sminshall printf("?Need to be connected first.\n"); 120432144Sminshall continue; 120532144Sminshall } 120632144Sminshall if ((*c->handler)(margc, margv)) { 120732144Sminshall break; 120832144Sminshall } 120932144Sminshall } 121032144Sminshall if (!top) { 121132144Sminshall if (!connected) { 121232144Sminshall longjmp(toplevel, 1); 121332144Sminshall /*NOTREACHED*/ 121432144Sminshall } 121532144Sminshall #if defined(TN3270) 121632144Sminshall if (shell_active == 0) { 121732144Sminshall setconnmode(); 121832144Sminshall } 121932144Sminshall #else /* defined(TN3270) */ 122032144Sminshall setconnmode(); 122132144Sminshall #endif /* defined(TN3270) */ 122232144Sminshall } 122332144Sminshall } 122432144Sminshall 122532144Sminshall /* 122632144Sminshall * Help command. 122732144Sminshall */ 122832144Sminshall static 122932144Sminshall help(argc, argv) 123032144Sminshall int argc; 123132144Sminshall char *argv[]; 123232144Sminshall { 123332144Sminshall register Command *c; 123432144Sminshall 123532144Sminshall if (argc == 1) { 123632144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 123732144Sminshall for (c = cmdtab; c->name; c++) 123832144Sminshall if (c->dohelp) { 123932144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 124032144Sminshall c->help); 124132144Sminshall } 124232144Sminshall return 0; 124332144Sminshall } 124432144Sminshall while (--argc > 0) { 124532144Sminshall register char *arg; 124632144Sminshall arg = *++argv; 124732144Sminshall c = getcmd(arg); 124832144Sminshall if (Ambiguous(c)) 124932144Sminshall printf("?Ambiguous help command %s\n", arg); 125032144Sminshall else if (c == (Command *)0) 125132144Sminshall printf("?Invalid help command %s\n", arg); 125232144Sminshall else 125332144Sminshall printf("%s\n", c->help); 125432144Sminshall } 125532144Sminshall return 0; 125632144Sminshall } 1257