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