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