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*37219Sminshall static char sccsid[] = "@(#)commands.c 1.16 (Berkeley) 03/20/89"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2232144Sminshall #include <sys/types.h> 2336274Sminshall #if defined(unix) 2436274Sminshall #include <sys/file.h> 2536274Sminshall #endif /* defined(unix) */ 2632144Sminshall #include <sys/socket.h> 2732144Sminshall #include <netinet/in.h> 2832144Sminshall 2932144Sminshall #include <signal.h> 3032144Sminshall #include <netdb.h> 3132144Sminshall #include <ctype.h> 3235298Sminshall #include <varargs.h> 3332144Sminshall 3432144Sminshall #include <arpa/telnet.h> 3532144Sminshall 3634305Sminshall #include "general.h" 3734305Sminshall 3832381Sminshall #include "ring.h" 3932381Sminshall 4032144Sminshall #include "externs.h" 4132144Sminshall #include "defines.h" 4232144Sminshall #include "types.h" 4332144Sminshall 4432144Sminshall char *hostname; 4532144Sminshall 4636180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 4732144Sminshall static char *ambiguous; /* special return value for command routines */ 4832144Sminshall 4932144Sminshall typedef struct { 5032144Sminshall char *name; /* command name */ 5132144Sminshall char *help; /* help string */ 5232144Sminshall int (*handler)(); /* routine which executes command */ 5332144Sminshall int dohelp; /* Should we give general help information? */ 5432144Sminshall int needconnect; /* Do we need to be connected to execute? */ 5532144Sminshall } Command; 5632144Sminshall 5732144Sminshall static char line[200]; 5832144Sminshall static int margc; 5932144Sminshall static char *margv[20]; 6032144Sminshall 6132144Sminshall /* 6232144Sminshall * Various utility routines. 6332144Sminshall */ 6432144Sminshall 6536180Sminshall #if !defined(BSD) || (BSD <= 43) 6636180Sminshall 6736180Sminshall char *h_errlist[] = { 6836180Sminshall "Error 0", 6936180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 7036180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 7136180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 7236180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 7336180Sminshall }; 7436180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 7536180Sminshall 7636274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 7736180Sminshall 7836180Sminshall /* 7936180Sminshall * herror -- 8036180Sminshall * print the error indicated by the h_errno value. 8136180Sminshall */ 8236180Sminshall herror(s) 8336180Sminshall char *s; 8436180Sminshall { 8536180Sminshall if (s && *s) { 8636180Sminshall fprintf(stderr, "%s: ", s); 8736180Sminshall } 8836180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 8936180Sminshall fprintf(stderr, "Unknown error\n"); 9036274Sminshall } else if (h_errno == 0) { 9136274Sminshall #if defined(sun) 9236274Sminshall fprintf(stderr, "Host unknown\n"); 9336274Sminshall #endif /* defined(sun) */ 9436180Sminshall } else { 9536180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 9636180Sminshall } 9736180Sminshall } 9836180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 9936180Sminshall 10032144Sminshall static void 10132144Sminshall makeargv() 10232144Sminshall { 10332144Sminshall register char *cp; 10432144Sminshall register char **argp = margv; 10532144Sminshall 10632144Sminshall margc = 0; 10732144Sminshall cp = line; 10832144Sminshall if (*cp == '!') { /* Special case shell escape */ 10932144Sminshall *argp++ = "!"; /* No room in string to get this */ 11032144Sminshall margc++; 11132144Sminshall cp++; 11232144Sminshall } 11332144Sminshall while (*cp) { 11432144Sminshall while (isspace(*cp)) 11532144Sminshall cp++; 11632144Sminshall if (*cp == '\0') 11732144Sminshall break; 11832144Sminshall *argp++ = cp; 11932144Sminshall margc += 1; 12032144Sminshall while (*cp != '\0' && !isspace(*cp)) 12132144Sminshall cp++; 12232144Sminshall if (*cp == '\0') 12332144Sminshall break; 12432144Sminshall *cp++ = '\0'; 12532144Sminshall } 12632144Sminshall *argp++ = 0; 12732144Sminshall } 12832144Sminshall 12932144Sminshall 13032144Sminshall static char ** 13132144Sminshall genget(name, table, next) 13232144Sminshall char *name; /* name to match */ 13332144Sminshall char **table; /* name entry in table */ 13432144Sminshall char **(*next)(); /* routine to return next entry in table */ 13532144Sminshall { 13632144Sminshall register char *p, *q; 13732144Sminshall register char **c, **found; 13832144Sminshall register int nmatches, longest; 13932144Sminshall 14032144Sminshall if (name == 0) { 14132144Sminshall return 0; 14232144Sminshall } 14332144Sminshall longest = 0; 14432144Sminshall nmatches = 0; 14532144Sminshall found = 0; 14632144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 14732144Sminshall for (q = name; 14832144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 14932144Sminshall if (*q == 0) /* exact match? */ 15032144Sminshall return (c); 15132144Sminshall if (!*q) { /* the name was a prefix */ 15232144Sminshall if (q - name > longest) { 15332144Sminshall longest = q - name; 15432144Sminshall nmatches = 1; 15532144Sminshall found = c; 15632144Sminshall } else if (q - name == longest) 15732144Sminshall nmatches++; 15832144Sminshall } 15932144Sminshall } 16032144Sminshall if (nmatches > 1) 16136180Sminshall return &ambiguous; 16232144Sminshall return (found); 16332144Sminshall } 16432144Sminshall 16532144Sminshall /* 16632144Sminshall * Make a character string into a number. 16732144Sminshall * 16832144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 16932144Sminshall */ 17032144Sminshall 17132144Sminshall static 17232144Sminshall special(s) 17332144Sminshall register char *s; 17432144Sminshall { 17532144Sminshall register char c; 17632144Sminshall char b; 17732144Sminshall 17832144Sminshall switch (*s) { 17932144Sminshall case '^': 18032144Sminshall b = *++s; 18132144Sminshall if (b == '?') { 18232144Sminshall c = b | 0x40; /* DEL */ 18332144Sminshall } else { 18432144Sminshall c = b & 0x1f; 18532144Sminshall } 18632144Sminshall break; 18732144Sminshall default: 18832144Sminshall c = *s; 18932144Sminshall break; 19032144Sminshall } 19132144Sminshall return c; 19232144Sminshall } 19332144Sminshall 19432144Sminshall /* 19532144Sminshall * Construct a control character sequence 19632144Sminshall * for a special character. 19732144Sminshall */ 19832144Sminshall static char * 19932144Sminshall control(c) 20032144Sminshall register int c; 20132144Sminshall { 20232144Sminshall static char buf[3]; 20332144Sminshall 20432144Sminshall if (c == 0x7f) 20532144Sminshall return ("^?"); 20632144Sminshall if (c == '\377') { 20732144Sminshall return "off"; 20832144Sminshall } 20932144Sminshall if (c >= 0x20) { 21032144Sminshall buf[0] = c; 21132144Sminshall buf[1] = 0; 21232144Sminshall } else { 21332144Sminshall buf[0] = '^'; 21432144Sminshall buf[1] = '@'+c; 21532144Sminshall buf[2] = 0; 21632144Sminshall } 21732144Sminshall return (buf); 21832144Sminshall } 21932144Sminshall 22032144Sminshall 22132144Sminshall 22232144Sminshall /* 22332144Sminshall * The following are data structures and routines for 22432144Sminshall * the "send" command. 22532144Sminshall * 22632144Sminshall */ 22732144Sminshall 22832144Sminshall struct sendlist { 22932144Sminshall char *name; /* How user refers to it (case independent) */ 23032144Sminshall int what; /* Character to be sent (<0 ==> special) */ 23132144Sminshall char *help; /* Help information (0 ==> no help) */ 23232144Sminshall #if defined(NOT43) 23332144Sminshall int (*routine)(); /* Routine to perform (for special ops) */ 23432144Sminshall #else /* defined(NOT43) */ 23532144Sminshall void (*routine)(); /* Routine to perform (for special ops) */ 23632144Sminshall #endif /* defined(NOT43) */ 23732144Sminshall }; 23832144Sminshall 23932144Sminshall #define SENDQUESTION -1 24032144Sminshall #define SENDESCAPE -3 24132144Sminshall 24232144Sminshall static struct sendlist Sendlist[] = { 24332144Sminshall { "ao", AO, "Send Telnet Abort output" }, 24432144Sminshall { "ayt", AYT, "Send Telnet 'Are You There'" }, 24532144Sminshall { "brk", BREAK, "Send Telnet Break" }, 24632144Sminshall { "ec", EC, "Send Telnet Erase Character" }, 24732144Sminshall { "el", EL, "Send Telnet Erase Line" }, 24832144Sminshall { "escape", SENDESCAPE, "Send current escape character" }, 24932144Sminshall { "ga", GA, "Send Telnet 'Go Ahead' sequence" }, 25032144Sminshall { "ip", IP, "Send Telnet Interrupt Process" }, 25132144Sminshall { "nop", NOP, "Send Telnet 'No operation'" }, 25232144Sminshall { "synch", SYNCH, "Perform Telnet 'Synch operation'", dosynch }, 25332144Sminshall { "?", SENDQUESTION, "Display send options" }, 25432144Sminshall { 0 } 25532144Sminshall }; 25632144Sminshall 25732144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 25832144Sminshall { "break", BREAK, 0 }, 25932144Sminshall 26032144Sminshall { "intp", IP, 0 }, 26132144Sminshall { "interrupt", IP, 0 }, 26232144Sminshall { "intr", IP, 0 }, 26332144Sminshall 26432144Sminshall { "help", SENDQUESTION, 0 }, 26532144Sminshall 26632144Sminshall { 0 } 26732144Sminshall }; 26832144Sminshall 26932144Sminshall static char ** 27032144Sminshall getnextsend(name) 27132144Sminshall char *name; 27232144Sminshall { 27332144Sminshall struct sendlist *c = (struct sendlist *) name; 27432144Sminshall 27532144Sminshall return (char **) (c+1); 27632144Sminshall } 27732144Sminshall 27832144Sminshall static struct sendlist * 27932144Sminshall getsend(name) 28032144Sminshall char *name; 28132144Sminshall { 28232144Sminshall struct sendlist *sl; 28332144Sminshall 28432144Sminshall if ((sl = (struct sendlist *) 28532144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 28632144Sminshall return sl; 28732144Sminshall } else { 28832144Sminshall return (struct sendlist *) 28932144Sminshall genget(name, (char **) Sendlist2, getnextsend); 29032144Sminshall } 29132144Sminshall } 29232144Sminshall 29332144Sminshall static 29432144Sminshall sendcmd(argc, argv) 29532144Sminshall int argc; 29632144Sminshall char **argv; 29732144Sminshall { 29832144Sminshall int what; /* what we are sending this time */ 29932144Sminshall int count; /* how many bytes we are going to need to send */ 30032144Sminshall int i; 30132144Sminshall int question = 0; /* was at least one argument a question */ 30232144Sminshall struct sendlist *s; /* pointer to current command */ 30332144Sminshall 30432144Sminshall if (argc < 2) { 30532144Sminshall printf("need at least one argument for 'send' command\n"); 30632144Sminshall printf("'send ?' for help\n"); 30732144Sminshall return 0; 30832144Sminshall } 30932144Sminshall /* 31032144Sminshall * First, validate all the send arguments. 31132144Sminshall * In addition, we see how much space we are going to need, and 31232144Sminshall * whether or not we will be doing a "SYNCH" operation (which 31332144Sminshall * flushes the network queue). 31432144Sminshall */ 31532144Sminshall count = 0; 31632144Sminshall for (i = 1; i < argc; i++) { 31732144Sminshall s = getsend(argv[i]); 31832144Sminshall if (s == 0) { 31932144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 32032144Sminshall argv[i]); 32132144Sminshall return 0; 32232144Sminshall } else if (Ambiguous(s)) { 32332144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 32432144Sminshall argv[i]); 32532144Sminshall return 0; 32632144Sminshall } 32732144Sminshall switch (s->what) { 32832144Sminshall case SENDQUESTION: 32932144Sminshall break; 33032144Sminshall case SENDESCAPE: 33132144Sminshall count += 1; 33232144Sminshall break; 33332144Sminshall case SYNCH: 33432144Sminshall count += 2; 33532144Sminshall break; 33632144Sminshall default: 33732144Sminshall count += 2; 33832144Sminshall break; 33932144Sminshall } 34032144Sminshall } 34132144Sminshall /* Now, do we have enough room? */ 34232144Sminshall if (NETROOM() < count) { 34332144Sminshall printf("There is not enough room in the buffer TO the network\n"); 34432144Sminshall printf("to process your request. Nothing will be done.\n"); 34532144Sminshall printf("('send synch' will throw away most data in the network\n"); 34632144Sminshall printf("buffer, if this might help.)\n"); 34732144Sminshall return 0; 34832144Sminshall } 34932144Sminshall /* OK, they are all OK, now go through again and actually send */ 35032144Sminshall for (i = 1; i < argc; i++) { 35132144Sminshall if ((s = getsend(argv[i])) == 0) { 35232144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 35332144Sminshall quit(); 35432144Sminshall /*NOTREACHED*/ 35532144Sminshall } 35632144Sminshall if (s->routine) { 35732144Sminshall (*s->routine)(s); 35832144Sminshall } else { 35932144Sminshall switch (what = s->what) { 36032144Sminshall case SYNCH: 36132144Sminshall dosynch(); 36232144Sminshall break; 36332144Sminshall case SENDQUESTION: 36432144Sminshall for (s = Sendlist; s->name; s++) { 36532144Sminshall if (s->help) { 36632144Sminshall printf(s->name); 36732144Sminshall if (s->help) { 36832144Sminshall printf("\t%s", s->help); 36932144Sminshall } 37032144Sminshall printf("\n"); 37132144Sminshall } 37232144Sminshall } 37332144Sminshall question = 1; 37432144Sminshall break; 37532144Sminshall case SENDESCAPE: 37632144Sminshall NETADD(escape); 37732144Sminshall break; 37832144Sminshall default: 37932144Sminshall NET2ADD(IAC, what); 38032144Sminshall break; 38132144Sminshall } 38232144Sminshall } 38332144Sminshall } 38432144Sminshall return !question; 38532144Sminshall } 38632144Sminshall 38732144Sminshall /* 38832144Sminshall * The following are the routines and data structures referred 38932144Sminshall * to by the arguments to the "toggle" command. 39032144Sminshall */ 39132144Sminshall 39232144Sminshall static 39332144Sminshall lclchars() 39432144Sminshall { 39532144Sminshall donelclchars = 1; 39632144Sminshall return 1; 39732144Sminshall } 39832144Sminshall 39932144Sminshall static 40032144Sminshall togdebug() 40132144Sminshall { 40232144Sminshall #ifndef NOT43 40332144Sminshall if (net > 0 && 40432144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 40532144Sminshall perror("setsockopt (SO_DEBUG)"); 40632144Sminshall } 40732144Sminshall #else /* NOT43 */ 40832144Sminshall if (debug) { 40932144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 41032144Sminshall perror("setsockopt (SO_DEBUG)"); 41132144Sminshall } else 41232144Sminshall printf("Cannot turn off socket debugging\n"); 41332144Sminshall #endif /* NOT43 */ 41432144Sminshall return 1; 41532144Sminshall } 41632144Sminshall 41732144Sminshall 41832144Sminshall static int 41932144Sminshall togcrlf() 42032144Sminshall { 42132144Sminshall if (crlf) { 42232144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 42332144Sminshall } else { 42432144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 42532144Sminshall } 42632144Sminshall return 1; 42732144Sminshall } 42832144Sminshall 42932144Sminshall 43032144Sminshall static int 43132144Sminshall togbinary() 43232144Sminshall { 43332144Sminshall donebinarytoggle = 1; 43432144Sminshall 43532144Sminshall if (myopts[TELOPT_BINARY] == 0) { /* Go into binary mode */ 43632144Sminshall NET2ADD(IAC, DO); 43732144Sminshall NETADD(TELOPT_BINARY); 43832144Sminshall printoption("<SENT", doopt, TELOPT_BINARY, 0); 43932144Sminshall NET2ADD(IAC, WILL); 44032144Sminshall NETADD(TELOPT_BINARY); 44132144Sminshall printoption("<SENT", doopt, TELOPT_BINARY, 0); 44232144Sminshall hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 1; 44332144Sminshall printf("Negotiating binary mode with remote host.\n"); 44432144Sminshall } else { /* Turn off binary mode */ 44532144Sminshall NET2ADD(IAC, DONT); 44632144Sminshall NETADD(TELOPT_BINARY); 44732144Sminshall printoption("<SENT", dont, TELOPT_BINARY, 0); 44832144Sminshall NET2ADD(IAC, DONT); 44932144Sminshall NETADD(TELOPT_BINARY); 45032144Sminshall printoption("<SENT", dont, TELOPT_BINARY, 0); 45132144Sminshall hisopts[TELOPT_BINARY] = myopts[TELOPT_BINARY] = 0; 45232144Sminshall printf("Negotiating network ascii mode with remote host.\n"); 45332144Sminshall } 45432144Sminshall return 1; 45532144Sminshall } 45632144Sminshall 45732144Sminshall 45832144Sminshall 45932144Sminshall extern int togglehelp(); 46032144Sminshall 46132144Sminshall struct togglelist { 46232144Sminshall char *name; /* name of toggle */ 46332144Sminshall char *help; /* help message */ 46432144Sminshall int (*handler)(); /* routine to do actual setting */ 46532144Sminshall int dohelp; /* should we display help information */ 46632144Sminshall int *variable; 46732144Sminshall char *actionexplanation; 46832144Sminshall }; 46932144Sminshall 47032144Sminshall static struct togglelist Togglelist[] = { 47132144Sminshall { "autoflush", 47232144Sminshall "toggle flushing of output when sending interrupt characters", 47332144Sminshall 0, 47432144Sminshall 1, 47532144Sminshall &autoflush, 47632144Sminshall "flush output when sending interrupt characters" }, 47732144Sminshall { "autosynch", 47832144Sminshall "toggle automatic sending of interrupt characters in urgent mode", 47932144Sminshall 0, 48032144Sminshall 1, 48132144Sminshall &autosynch, 48232144Sminshall "send interrupt characters in urgent mode" }, 48332144Sminshall { "binary", 48432144Sminshall "toggle sending and receiving of binary data", 48532144Sminshall togbinary, 48632144Sminshall 1, 48732144Sminshall 0, 48832144Sminshall 0 }, 48932144Sminshall { "crlf", 49032144Sminshall "toggle sending carriage returns as telnet <CR><LF>", 49132144Sminshall togcrlf, 49232144Sminshall 1, 49332144Sminshall &crlf, 49432144Sminshall 0 }, 49532144Sminshall { "crmod", 49632144Sminshall "toggle mapping of received carriage returns", 49732144Sminshall 0, 49832144Sminshall 1, 49932144Sminshall &crmod, 50032144Sminshall "map carriage return on output" }, 50132144Sminshall { "localchars", 50232144Sminshall "toggle local recognition of certain control characters", 50332144Sminshall lclchars, 50432144Sminshall 1, 50532144Sminshall &localchars, 50632144Sminshall "recognize certain control characters" }, 50732144Sminshall { " ", "", 0, 1 }, /* empty line */ 50832144Sminshall { "debug", 50932144Sminshall "(debugging) toggle debugging", 51032144Sminshall togdebug, 51132144Sminshall 1, 51232144Sminshall &debug, 51332144Sminshall "turn on socket level debugging" }, 51432144Sminshall { "netdata", 51532144Sminshall "(debugging) toggle printing of hexadecimal network data", 51632144Sminshall 0, 51732144Sminshall 1, 51832144Sminshall &netdata, 51932144Sminshall "print hexadecimal representation of network traffic" }, 52032144Sminshall { "options", 52132144Sminshall "(debugging) toggle viewing of options processing", 52232144Sminshall 0, 52332144Sminshall 1, 52432144Sminshall &showoptions, 52532144Sminshall "show option processing" }, 52632144Sminshall { " ", "", 0, 1 }, /* empty line */ 52732144Sminshall { "?", 52832144Sminshall "display help information", 52932144Sminshall togglehelp, 53032144Sminshall 1 }, 53132144Sminshall { "help", 53232144Sminshall "display help information", 53332144Sminshall togglehelp, 53432144Sminshall 0 }, 53532144Sminshall { 0 } 53632144Sminshall }; 53732144Sminshall 53832144Sminshall static 53932144Sminshall togglehelp() 54032144Sminshall { 54132144Sminshall struct togglelist *c; 54232144Sminshall 54332144Sminshall for (c = Togglelist; c->name; c++) { 54432144Sminshall if (c->dohelp) { 54532144Sminshall printf("%s\t%s\n", c->name, c->help); 54632144Sminshall } 54732144Sminshall } 54832144Sminshall return 0; 54932144Sminshall } 55032144Sminshall 55132144Sminshall static char ** 55232144Sminshall getnexttoggle(name) 55332144Sminshall char *name; 55432144Sminshall { 55532144Sminshall struct togglelist *c = (struct togglelist *) name; 55632144Sminshall 55732144Sminshall return (char **) (c+1); 55832144Sminshall } 55932144Sminshall 56032144Sminshall static struct togglelist * 56132144Sminshall gettoggle(name) 56232144Sminshall char *name; 56332144Sminshall { 56432144Sminshall return (struct togglelist *) 56532144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 56632144Sminshall } 56732144Sminshall 56832144Sminshall static 56932144Sminshall toggle(argc, argv) 57032144Sminshall int argc; 57132144Sminshall char *argv[]; 57232144Sminshall { 57332144Sminshall int retval = 1; 57432144Sminshall char *name; 57532144Sminshall struct togglelist *c; 57632144Sminshall 57732144Sminshall if (argc < 2) { 57832144Sminshall fprintf(stderr, 57932144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 58032144Sminshall return 0; 58132144Sminshall } 58232144Sminshall argc--; 58332144Sminshall argv++; 58432144Sminshall while (argc--) { 58532144Sminshall name = *argv++; 58632144Sminshall c = gettoggle(name); 58732144Sminshall if (Ambiguous(c)) { 58832144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 58932144Sminshall name); 59032144Sminshall return 0; 59132144Sminshall } else if (c == 0) { 59232144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 59332144Sminshall name); 59432144Sminshall return 0; 59532144Sminshall } else { 59632144Sminshall if (c->variable) { 59732144Sminshall *c->variable = !*c->variable; /* invert it */ 59832144Sminshall if (c->actionexplanation) { 59932144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 60032144Sminshall c->actionexplanation); 60132144Sminshall } 60232144Sminshall } 60332144Sminshall if (c->handler) { 60432144Sminshall retval &= (*c->handler)(c); 60532144Sminshall } 60632144Sminshall } 60732144Sminshall } 60832144Sminshall return retval; 60932144Sminshall } 61032144Sminshall 61132144Sminshall /* 61232144Sminshall * The following perform the "set" command. 61332144Sminshall */ 61432144Sminshall 61532144Sminshall struct setlist { 61632144Sminshall char *name; /* name */ 61732144Sminshall char *help; /* help information */ 61832144Sminshall char *charp; /* where it is located at */ 61932144Sminshall }; 62032144Sminshall 62132144Sminshall static struct setlist Setlist[] = { 62232144Sminshall { "echo", "character to toggle local echoing on/off", &echoc }, 62332144Sminshall { "escape", "character to escape back to telnet command mode", &escape }, 62432144Sminshall { " ", "" }, 62532144Sminshall { " ", "The following need 'localchars' to be toggled true", 0 }, 62632144Sminshall { "erase", "character to cause an Erase Character", &termEraseChar }, 62732144Sminshall { "flushoutput", "character to cause an Abort Oubput", &termFlushChar }, 62832144Sminshall { "interrupt", "character to cause an Interrupt Process", &termIntChar }, 62932144Sminshall { "kill", "character to cause an Erase Line", &termKillChar }, 63032144Sminshall { "quit", "character to cause a Break", &termQuitChar }, 63132144Sminshall { "eof", "character to cause an EOF ", &termEofChar }, 63232144Sminshall { 0 } 63332144Sminshall }; 63432144Sminshall 63532144Sminshall static char ** 63632144Sminshall getnextset(name) 63732144Sminshall char *name; 63832144Sminshall { 63932144Sminshall struct setlist *c = (struct setlist *)name; 64032144Sminshall 64132144Sminshall return (char **) (c+1); 64232144Sminshall } 64332144Sminshall 64432144Sminshall static struct setlist * 64532144Sminshall getset(name) 64632144Sminshall char *name; 64732144Sminshall { 64832144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 64932144Sminshall } 65032144Sminshall 65132144Sminshall static 65232144Sminshall setcmd(argc, argv) 65332144Sminshall int argc; 65432144Sminshall char *argv[]; 65532144Sminshall { 65632144Sminshall int value; 65732144Sminshall struct setlist *ct; 65832144Sminshall 65932144Sminshall /* XXX back we go... sigh */ 66032144Sminshall if (argc != 3) { 66132144Sminshall if ((argc == 2) && 66232144Sminshall ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 66332144Sminshall for (ct = Setlist; ct->name; ct++) { 66432144Sminshall printf("%s\t%s\n", ct->name, ct->help); 66532144Sminshall } 66632144Sminshall printf("?\tdisplay help information\n"); 66732144Sminshall } else { 66832144Sminshall printf("Format is 'set Name Value'\n'set ?' for help.\n"); 66932144Sminshall } 67032144Sminshall return 0; 67132144Sminshall } 67232144Sminshall 67332144Sminshall ct = getset(argv[1]); 67432144Sminshall if (ct == 0) { 67532144Sminshall fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 67632144Sminshall argv[1]); 67732144Sminshall return 0; 67832144Sminshall } else if (Ambiguous(ct)) { 67932144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 68032144Sminshall argv[1]); 68132144Sminshall return 0; 68232144Sminshall } else { 68332144Sminshall if (strcmp("off", argv[2])) { 68432144Sminshall value = special(argv[2]); 68532144Sminshall } else { 68632144Sminshall value = -1; 68732144Sminshall } 68832144Sminshall *(ct->charp) = value; 68932144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 69032144Sminshall } 69132144Sminshall return 1; 69232144Sminshall } 69332144Sminshall 69432144Sminshall /* 69532144Sminshall * The following are the data structures and routines for the 69632144Sminshall * 'mode' command. 69732144Sminshall */ 69832144Sminshall 69932144Sminshall static 70032144Sminshall dolinemode() 70132144Sminshall { 70232144Sminshall if (hisopts[TELOPT_SGA]) { 70332144Sminshall wontoption(TELOPT_SGA, 0); 70432144Sminshall } 70532144Sminshall if (hisopts[TELOPT_ECHO]) { 70632144Sminshall wontoption(TELOPT_ECHO, 0); 70732144Sminshall } 70832144Sminshall return 1; 70932144Sminshall } 71032144Sminshall 71132144Sminshall static 71232144Sminshall docharmode() 71332144Sminshall { 71432144Sminshall if (!hisopts[TELOPT_SGA]) { 71532144Sminshall willoption(TELOPT_SGA, 0); 71632144Sminshall } 71732144Sminshall if (!hisopts[TELOPT_ECHO]) { 71832144Sminshall willoption(TELOPT_ECHO, 0); 71932144Sminshall } 72032144Sminshall return 1; 72132144Sminshall } 72232144Sminshall 72332144Sminshall static Command Mode_commands[] = { 72432144Sminshall { "character", "character-at-a-time mode", docharmode, 1, 1 }, 72532144Sminshall { "line", "line-by-line mode", dolinemode, 1, 1 }, 72632144Sminshall { 0 }, 72732144Sminshall }; 72832144Sminshall 72932144Sminshall static char ** 73032144Sminshall getnextmode(name) 73132144Sminshall char *name; 73232144Sminshall { 73332144Sminshall Command *c = (Command *) name; 73432144Sminshall 73532144Sminshall return (char **) (c+1); 73632144Sminshall } 73732144Sminshall 73832144Sminshall static Command * 73932144Sminshall getmodecmd(name) 74032144Sminshall char *name; 74132144Sminshall { 74232144Sminshall return (Command *) genget(name, (char **) Mode_commands, getnextmode); 74332144Sminshall } 74432144Sminshall 74532144Sminshall static 74632144Sminshall modecmd(argc, argv) 74732144Sminshall int argc; 74832144Sminshall char *argv[]; 74932144Sminshall { 75032144Sminshall Command *mt; 75132144Sminshall 75232144Sminshall if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) { 75332144Sminshall printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 75432144Sminshall for (mt = Mode_commands; mt->name; mt++) { 75532144Sminshall printf("%s\t%s\n", mt->name, mt->help); 75632144Sminshall } 75732144Sminshall return 0; 75832144Sminshall } 75932144Sminshall mt = getmodecmd(argv[1]); 76032144Sminshall if (mt == 0) { 76132144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 76232144Sminshall return 0; 76332144Sminshall } else if (Ambiguous(mt)) { 76432144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 76532144Sminshall return 0; 76632144Sminshall } else { 76732144Sminshall (*mt->handler)(); 76832144Sminshall } 76932144Sminshall return 1; 77032144Sminshall } 77132144Sminshall 77232144Sminshall /* 77332144Sminshall * The following data structures and routines implement the 77432144Sminshall * "display" command. 77532144Sminshall */ 77632144Sminshall 77732144Sminshall static 77832144Sminshall display(argc, argv) 77932144Sminshall int argc; 78032144Sminshall char *argv[]; 78132144Sminshall { 78232144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 78332144Sminshall if (*tl->variable) { \ 78432144Sminshall printf("will"); \ 78532144Sminshall } else { \ 78632144Sminshall printf("won't"); \ 78732144Sminshall } \ 78832144Sminshall printf(" %s.\n", tl->actionexplanation); \ 78932144Sminshall } 79032144Sminshall 79132144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 79232144Sminshall printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \ 79332144Sminshall } 79432144Sminshall 79532144Sminshall struct togglelist *tl; 79632144Sminshall struct setlist *sl; 79732144Sminshall 79832144Sminshall if (argc == 1) { 79932144Sminshall for (tl = Togglelist; tl->name; tl++) { 80032144Sminshall dotog(tl); 80132144Sminshall } 80232144Sminshall printf("\n"); 80332144Sminshall for (sl = Setlist; sl->name; sl++) { 80432144Sminshall doset(sl); 80532144Sminshall } 80632144Sminshall } else { 80732144Sminshall int i; 80832144Sminshall 80932144Sminshall for (i = 1; i < argc; i++) { 81032144Sminshall sl = getset(argv[i]); 81132144Sminshall tl = gettoggle(argv[i]); 81232144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 81332144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 81432144Sminshall return 0; 81532144Sminshall } else if (!sl && !tl) { 81632144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 81732144Sminshall return 0; 81832144Sminshall } else { 81932144Sminshall if (tl) { 82032144Sminshall dotog(tl); 82132144Sminshall } 82232144Sminshall if (sl) { 82332144Sminshall doset(sl); 82432144Sminshall } 82532144Sminshall } 82632144Sminshall } 82732144Sminshall } 82832144Sminshall return 1; 82932144Sminshall #undef doset 83032144Sminshall #undef dotog 83132144Sminshall } 83232144Sminshall 83332144Sminshall /* 83432144Sminshall * The following are the data structures, and many of the routines, 83532144Sminshall * relating to command processing. 83632144Sminshall */ 83732144Sminshall 83832144Sminshall /* 83932144Sminshall * Set the escape character. 84032144Sminshall */ 84132144Sminshall static 84232144Sminshall setescape(argc, argv) 84332144Sminshall int argc; 84432144Sminshall char *argv[]; 84532144Sminshall { 84632144Sminshall register char *arg; 84732144Sminshall char buf[50]; 84832144Sminshall 84932144Sminshall printf( 85032144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 85132144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 85232144Sminshall if (argc > 2) 85332144Sminshall arg = argv[1]; 85432144Sminshall else { 85532144Sminshall printf("new escape character: "); 85634849Sminshall (void) gets(buf); 85732144Sminshall arg = buf; 85832144Sminshall } 85932144Sminshall if (arg[0] != '\0') 86032144Sminshall escape = arg[0]; 86132144Sminshall if (!In3270) { 86232144Sminshall printf("Escape character is '%s'.\n", control(escape)); 86332144Sminshall } 86434849Sminshall (void) fflush(stdout); 86532144Sminshall return 1; 86632144Sminshall } 86732144Sminshall 86832144Sminshall /*VARARGS*/ 86932144Sminshall static 87032144Sminshall togcrmod() 87132144Sminshall { 87232144Sminshall crmod = !crmod; 87332144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 87432144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 87534849Sminshall (void) fflush(stdout); 87632144Sminshall return 1; 87732144Sminshall } 87832144Sminshall 87932144Sminshall /*VARARGS*/ 88032144Sminshall suspend() 88132144Sminshall { 882*37219Sminshall setcommandmode(); 88332144Sminshall #if defined(unix) 884*37219Sminshall { 885*37219Sminshall long oldrows, oldcols, newrows, newcols; 886*37219Sminshall 887*37219Sminshall TerminalWindowSize(&oldrows, &oldcols); 88834849Sminshall (void) kill(0, SIGTSTP); 889*37219Sminshall TerminalWindowSize(&newrows, &newcols); 890*37219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 891*37219Sminshall if (connected) { 892*37219Sminshall sendnaws(); 893*37219Sminshall } 894*37219Sminshall } 895*37219Sminshall } 89632144Sminshall #endif /* defined(unix) */ 897*37219Sminshall /* reget parameters in case they were changed */ 898*37219Sminshall TerminalSaveState(); 899*37219Sminshall setconnmode(); 900*37219Sminshall return 1; 90132144Sminshall } 90232144Sminshall 90332144Sminshall /*VARARGS*/ 90432144Sminshall static 90532144Sminshall bye(argc, argv) 90632144Sminshall int argc; /* Number of arguments */ 90732144Sminshall char *argv[]; /* arguments */ 90832144Sminshall { 90932144Sminshall if (connected) { 91034849Sminshall (void) shutdown(net, 2); 91132144Sminshall printf("Connection closed.\n"); 91234849Sminshall (void) NetClose(net); 91332144Sminshall connected = 0; 91432144Sminshall /* reset options */ 91532144Sminshall tninit(); 91632144Sminshall #if defined(TN3270) 91732144Sminshall SetIn3270(); /* Get out of 3270 mode */ 91832144Sminshall #endif /* defined(TN3270) */ 91932144Sminshall } 92032144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 92132144Sminshall longjmp(toplevel, 1); 92232144Sminshall /* NOTREACHED */ 92332144Sminshall } 92432144Sminshall return 1; /* Keep lint, etc., happy */ 92532144Sminshall } 92632144Sminshall 92732144Sminshall /*VARARGS*/ 92832144Sminshall quit() 92932144Sminshall { 93032144Sminshall (void) call(bye, "bye", "fromquit", 0); 93132144Sminshall Exit(0); 93232144Sminshall return 1; /* just to keep lint happy */ 93332144Sminshall } 93432144Sminshall 93536274Sminshall #if defined(unix) 93632144Sminshall /* 93736274Sminshall * Some information about our file descriptors. 93836274Sminshall */ 93936274Sminshall 94036274Sminshall char * 94136274Sminshall decodeflags(mask) 94236274Sminshall int mask; 94336274Sminshall { 94436274Sminshall static char buffer[100]; 94536274Sminshall #define do(m,s) \ 94636274Sminshall if (mask&(m)) { \ 94736274Sminshall strcat(buffer, (s)); \ 94836274Sminshall } 94936274Sminshall 95036274Sminshall buffer[0] = 0; /* Terminate it */ 95136274Sminshall 95236274Sminshall #ifdef FREAD 95336274Sminshall do(FREAD, " FREAD"); 95436274Sminshall #endif 95536274Sminshall #ifdef FWRITE 95636274Sminshall do(FWRITE, " FWRITE"); 95736274Sminshall #endif 95836274Sminshall #ifdef F_DUPFP 95936274Sminshall do(F_DUPFD, " F_DUPFD"); 96036274Sminshall #endif 96136274Sminshall #ifdef FNDELAY 96236274Sminshall do(FNDELAY, " FNDELAY"); 96336274Sminshall #endif 96436274Sminshall #ifdef FAPPEND 96536274Sminshall do(FAPPEND, " FAPPEND"); 96636274Sminshall #endif 96736274Sminshall #ifdef FMARK 96836274Sminshall do(FMARK, " FMARK"); 96936274Sminshall #endif 97036274Sminshall #ifdef FDEFER 97136274Sminshall do(FDEFER, " FDEFER"); 97236274Sminshall #endif 97336274Sminshall #ifdef FASYNC 97436274Sminshall do(FASYNC, " FASYNC"); 97536274Sminshall #endif 97636274Sminshall #ifdef FSHLOCK 97736274Sminshall do(FSHLOCK, " FSHLOCK"); 97836274Sminshall #endif 97936274Sminshall #ifdef FEXLOCK 98036274Sminshall do(FEXLOCK, " FEXLOCK"); 98136274Sminshall #endif 98236274Sminshall #ifdef FCREAT 98336274Sminshall do(FCREAT, " FCREAT"); 98436274Sminshall #endif 98536274Sminshall #ifdef FTRUNC 98636274Sminshall do(FTRUNC, " FTRUNC"); 98736274Sminshall #endif 98836274Sminshall #ifdef FEXCL 98936274Sminshall do(FEXCL, " FEXCL"); 99036274Sminshall #endif 99136274Sminshall 99236274Sminshall return buffer; 99336274Sminshall } 99436274Sminshall #undef do 99536274Sminshall 99636274Sminshall static void 99736274Sminshall filestuff(fd) 99836274Sminshall int fd; 99936274Sminshall { 100036274Sminshall int res; 100136274Sminshall 100236274Sminshall setconnmode(); 100336274Sminshall res = fcntl(fd, F_GETOWN, 0); 100436274Sminshall setcommandmode(); 100536274Sminshall 100636274Sminshall if (res == -1) { 100736274Sminshall perror("fcntl"); 100836274Sminshall return; 100936274Sminshall } 101036274Sminshall printf("\tOwner is %d.\n", res); 101136274Sminshall 101236274Sminshall setconnmode(); 101336274Sminshall res = fcntl(fd, F_GETFL, 0); 101436274Sminshall setcommandmode(); 101536274Sminshall 101636274Sminshall if (res == -1) { 101736274Sminshall perror("fcntl"); 101836274Sminshall return; 101936274Sminshall } 102036274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 102136274Sminshall } 102236274Sminshall 102336274Sminshall 102436274Sminshall #endif /* defined(unix) */ 102536274Sminshall 102636274Sminshall /* 102732144Sminshall * Print status about the connection. 102832144Sminshall */ 102934849Sminshall /*ARGSUSED*/ 103032144Sminshall static 103132144Sminshall status(argc, argv) 103232144Sminshall int argc; 103332144Sminshall char *argv[]; 103432144Sminshall { 103532144Sminshall if (connected) { 103632144Sminshall printf("Connected to %s.\n", hostname); 103736242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 103832144Sminshall printf("Operating in %s.\n", 103932144Sminshall modelist[getconnmode()].modedescriptions); 104032144Sminshall if (localchars) { 104132144Sminshall printf("Catching signals locally.\n"); 104232144Sminshall } 104332144Sminshall } 104432144Sminshall } else { 104532144Sminshall printf("No connection.\n"); 104632144Sminshall } 104732144Sminshall # if !defined(TN3270) 104832144Sminshall printf("Escape character is '%s'.\n", control(escape)); 104934849Sminshall (void) fflush(stdout); 105032144Sminshall # else /* !defined(TN3270) */ 105132144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 105232144Sminshall printf("Escape character is '%s'.\n", control(escape)); 105332144Sminshall } 105432144Sminshall # if defined(unix) 105536242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 105636242Sminshall printf("SIGIO received %d time%s.\n", 105736242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 105836274Sminshall if (In3270) { 105936274Sminshall printf("Process ID %d, process group %d.\n", 106036274Sminshall getpid(), getpgrp(getpid())); 106136274Sminshall printf("Terminal input:\n"); 106236274Sminshall filestuff(tin); 106336274Sminshall printf("Terminal output:\n"); 106436274Sminshall filestuff(tout); 106536274Sminshall printf("Network socket:\n"); 106636274Sminshall filestuff(net); 106736274Sminshall } 106836242Sminshall } 106932144Sminshall if (In3270 && transcom) { 107032144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 107132144Sminshall } 107232144Sminshall # endif /* defined(unix) */ 107334849Sminshall (void) fflush(stdout); 107432144Sminshall if (In3270) { 107532144Sminshall return 0; 107632144Sminshall } 107732144Sminshall # endif /* defined(TN3270) */ 107832144Sminshall return 1; 107932144Sminshall } 108032144Sminshall 108132144Sminshall 108232144Sminshall 108332144Sminshall int 108432144Sminshall tn(argc, argv) 108532144Sminshall int argc; 108632144Sminshall char *argv[]; 108732144Sminshall { 108832144Sminshall register struct hostent *host = 0; 108932144Sminshall struct sockaddr_in sin; 109032144Sminshall struct servent *sp = 0; 109132144Sminshall static char hnamebuf[32]; 109234849Sminshall unsigned long inet_addr(); 1093*37219Sminshall extern char *inet_ntoa(); 109432144Sminshall 109532144Sminshall 109632144Sminshall #if defined(MSDOS) 109732144Sminshall char *cp; 109832144Sminshall #endif /* defined(MSDOS) */ 109932144Sminshall 110032144Sminshall if (connected) { 110132144Sminshall printf("?Already connected to %s\n", hostname); 110232144Sminshall return 0; 110332144Sminshall } 110432144Sminshall if (argc < 2) { 110532144Sminshall (void) strcpy(line, "Connect "); 110632144Sminshall printf("(to) "); 110734849Sminshall (void) gets(&line[strlen(line)]); 110832144Sminshall makeargv(); 110932144Sminshall argc = margc; 111032144Sminshall argv = margv; 111132144Sminshall } 111232144Sminshall if ((argc < 2) || (argc > 3)) { 111332144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 111432144Sminshall return 0; 111532144Sminshall } 111632144Sminshall #if defined(MSDOS) 111732144Sminshall for (cp = argv[1]; *cp; cp++) { 111832144Sminshall if (isupper(*cp)) { 111932144Sminshall *cp = tolower(*cp); 112032144Sminshall } 112132144Sminshall } 112232144Sminshall #endif /* defined(MSDOS) */ 112332144Sminshall sin.sin_addr.s_addr = inet_addr(argv[1]); 112436694Sminshall if (sin.sin_addr.s_addr != (unsigned long) -1) { 112532144Sminshall sin.sin_family = AF_INET; 112632144Sminshall (void) strcpy(hnamebuf, argv[1]); 112732144Sminshall hostname = hnamebuf; 112832144Sminshall } else { 112932144Sminshall host = gethostbyname(argv[1]); 113032144Sminshall if (host) { 113132144Sminshall sin.sin_family = host->h_addrtype; 113232144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 113332144Sminshall memcpy((caddr_t)&sin.sin_addr, 113432144Sminshall host->h_addr_list[0], host->h_length); 113532144Sminshall #else /* defined(h_addr) */ 113632144Sminshall memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 113732144Sminshall #endif /* defined(h_addr) */ 113832144Sminshall hostname = host->h_name; 113932144Sminshall } else { 114035789Sbostic herror(argv[1]); 114132144Sminshall return 0; 114232144Sminshall } 114332144Sminshall } 114432144Sminshall if (argc == 3) { 114532144Sminshall sin.sin_port = atoi(argv[2]); 114632144Sminshall if (sin.sin_port == 0) { 114732144Sminshall sp = getservbyname(argv[2], "tcp"); 114832144Sminshall if (sp) 114932144Sminshall sin.sin_port = sp->s_port; 115032144Sminshall else { 115132144Sminshall printf("%s: bad port number\n", argv[2]); 115232144Sminshall return 0; 115332144Sminshall } 115432144Sminshall } else { 115534849Sminshall #if !defined(htons) 115634849Sminshall u_short htons(); 115734849Sminshall #endif /* !defined(htons) */ 115832144Sminshall sin.sin_port = htons(sin.sin_port); 115932144Sminshall } 116032144Sminshall telnetport = 0; 116132144Sminshall } else { 116232144Sminshall if (sp == 0) { 116332144Sminshall sp = getservbyname("telnet", "tcp"); 116432144Sminshall if (sp == 0) { 116534849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 116632144Sminshall return 0; 116732144Sminshall } 116832144Sminshall sin.sin_port = sp->s_port; 116932144Sminshall } 117032144Sminshall telnetport = 1; 117132144Sminshall } 1172*37219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 117332144Sminshall do { 117432144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 117532144Sminshall if (net < 0) { 117632144Sminshall perror("telnet: socket"); 117732144Sminshall return 0; 117832144Sminshall } 117932144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 118032144Sminshall perror("setsockopt (SO_DEBUG)"); 118132144Sminshall } 118232144Sminshall 118332144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 118432144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 118532144Sminshall if (host && host->h_addr_list[1]) { 118632144Sminshall int oerrno = errno; 118732144Sminshall 118832144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 118932144Sminshall inet_ntoa(sin.sin_addr)); 119032144Sminshall errno = oerrno; 119132144Sminshall perror((char *)0); 119232144Sminshall host->h_addr_list++; 119332144Sminshall memcpy((caddr_t)&sin.sin_addr, 119432144Sminshall host->h_addr_list[0], host->h_length); 119532144Sminshall (void) NetClose(net); 119632144Sminshall continue; 119732144Sminshall } 119832144Sminshall #endif /* defined(h_addr) */ 119932144Sminshall perror("telnet: Unable to connect to remote host"); 120032144Sminshall return 0; 1201*37219Sminshall } 120232144Sminshall connected++; 120332144Sminshall } while (connected == 0); 120434849Sminshall (void) call(status, "status", "notmuch", 0); 120532144Sminshall if (setjmp(peerdied) == 0) 120632144Sminshall telnet(); 120734849Sminshall (void) NetClose(net); 120832381Sminshall ExitString("Connection closed by foreign host.\n",1); 120932144Sminshall /*NOTREACHED*/ 121032144Sminshall } 121132144Sminshall 121232144Sminshall 121332144Sminshall #define HELPINDENT (sizeof ("connect")) 121432144Sminshall 121532144Sminshall static char 121632144Sminshall openhelp[] = "connect to a site", 121732144Sminshall closehelp[] = "close current connection", 121832144Sminshall quithelp[] = "exit telnet", 121932144Sminshall statushelp[] = "print status information", 122032144Sminshall helphelp[] = "print help information", 122132144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 122232144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 122332144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 122432144Sminshall displayhelp[] = "display operating parameters", 122532144Sminshall #if defined(TN3270) && defined(unix) 122632144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 122732144Sminshall #endif /* defined(TN3270) && defined(unix) */ 122832144Sminshall #if defined(unix) 122932144Sminshall zhelp[] = "suspend telnet", 123032144Sminshall #endif /* defined(unix */ 123132144Sminshall #if defined(TN3270) 123232144Sminshall shellhelp[] = "invoke a subshell", 123332144Sminshall #endif /* defined(TN3270) */ 123432144Sminshall modehelp[] = "try to enter line-by-line or character-at-a-time mode"; 123532144Sminshall 123632144Sminshall extern int help(), shell(); 123732144Sminshall 123832144Sminshall static Command cmdtab[] = { 123932144Sminshall { "close", closehelp, bye, 1, 1 }, 124032144Sminshall { "display", displayhelp, display, 1, 0 }, 124132144Sminshall { "mode", modehelp, modecmd, 1, 1 }, 124232144Sminshall { "open", openhelp, tn, 1, 0 }, 124332144Sminshall { "quit", quithelp, quit, 1, 0 }, 124432144Sminshall { "send", sendhelp, sendcmd, 1, 1 }, 124532144Sminshall { "set", sethelp, setcmd, 1, 0 }, 124632144Sminshall { "status", statushelp, status, 1, 0 }, 124732144Sminshall { "toggle", togglestring, toggle, 1, 0 }, 124832144Sminshall #if defined(TN3270) && defined(unix) 124932144Sminshall { "transcom", transcomhelp, settranscom, 1, 0 }, 125032144Sminshall #endif /* defined(TN3270) && defined(unix) */ 125132144Sminshall #if defined(unix) 125232144Sminshall { "z", zhelp, suspend, 1, 0 }, 125332144Sminshall #endif /* defined(unix) */ 125432144Sminshall #if defined(TN3270) 125532144Sminshall { "!", shellhelp, shell, 1, 1 }, 125632144Sminshall #endif /* defined(TN3270) */ 125732144Sminshall { "?", helphelp, help, 1, 0 }, 125832144Sminshall 0 125932144Sminshall }; 126032144Sminshall 126132144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 126232144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 126332144Sminshall 126432144Sminshall static Command cmdtab2[] = { 126532144Sminshall { "help", helphelp, help, 0, 0 }, 126632144Sminshall { "escape", escapehelp, setescape, 1, 0 }, 126732144Sminshall { "crmod", crmodhelp, togcrmod, 1, 0 }, 126832144Sminshall 0 126932144Sminshall }; 127032144Sminshall 127135298Sminshall 127232144Sminshall /* 127332144Sminshall * Call routine with argc, argv set from args (terminated by 0). 127432144Sminshall */ 127535298Sminshall 127635417Sminshall /*VARARGS1*/ 127732144Sminshall static 127835298Sminshall call(va_alist) 127935298Sminshall va_dcl 128032144Sminshall { 128135298Sminshall va_list ap; 128235298Sminshall typedef int (*intrtn_t)(); 128335298Sminshall intrtn_t routine; 128435298Sminshall char *args[100]; 128535298Sminshall int argno = 0; 128635298Sminshall 128735298Sminshall va_start(ap); 128835298Sminshall routine = (va_arg(ap, intrtn_t)); 128935495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 129035298Sminshall ; 129135495Sminshall } 129235298Sminshall va_end(ap); 129335495Sminshall return (*routine)(argno-1, args); 129432144Sminshall } 129532144Sminshall 129635298Sminshall 129732144Sminshall static char ** 129832144Sminshall getnextcmd(name) 129932144Sminshall char *name; 130032144Sminshall { 130132144Sminshall Command *c = (Command *) name; 130232144Sminshall 130332144Sminshall return (char **) (c+1); 130432144Sminshall } 130532144Sminshall 130632144Sminshall static Command * 130732144Sminshall getcmd(name) 130832144Sminshall char *name; 130932144Sminshall { 131032144Sminshall Command *cm; 131132144Sminshall 131232144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 131332144Sminshall return cm; 131432144Sminshall } else { 131532144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 131632144Sminshall } 131732144Sminshall } 131832144Sminshall 131932144Sminshall void 132032144Sminshall command(top) 132132144Sminshall int top; 132232144Sminshall { 132332144Sminshall register Command *c; 132432144Sminshall 132532144Sminshall setcommandmode(); 132632144Sminshall if (!top) { 132732144Sminshall putchar('\n'); 1328*37219Sminshall #if defined(unix) 132932144Sminshall } else { 133032144Sminshall signal(SIGINT, SIG_DFL); 133132144Sminshall signal(SIGQUIT, SIG_DFL); 133232144Sminshall #endif /* defined(unix) */ 133332144Sminshall } 133432144Sminshall for (;;) { 133532144Sminshall printf("%s> ", prompt); 133632144Sminshall if (gets(line) == NULL) { 133732144Sminshall if (feof(stdin) || ferror(stdin)) 133832144Sminshall quit(); 133932144Sminshall break; 134032144Sminshall } 134132144Sminshall if (line[0] == 0) 134232144Sminshall break; 134332144Sminshall makeargv(); 1344*37219Sminshall if (margv[0] == 0) { 1345*37219Sminshall break; 1346*37219Sminshall } 134732144Sminshall c = getcmd(margv[0]); 134832144Sminshall if (Ambiguous(c)) { 134932144Sminshall printf("?Ambiguous command\n"); 135032144Sminshall continue; 135132144Sminshall } 135232144Sminshall if (c == 0) { 135332144Sminshall printf("?Invalid command\n"); 135432144Sminshall continue; 135532144Sminshall } 135632144Sminshall if (c->needconnect && !connected) { 135732144Sminshall printf("?Need to be connected first.\n"); 135832144Sminshall continue; 135932144Sminshall } 136032144Sminshall if ((*c->handler)(margc, margv)) { 136132144Sminshall break; 136232144Sminshall } 136332144Sminshall } 136432144Sminshall if (!top) { 136532144Sminshall if (!connected) { 136632144Sminshall longjmp(toplevel, 1); 136732144Sminshall /*NOTREACHED*/ 136832144Sminshall } 136932144Sminshall #if defined(TN3270) 137032144Sminshall if (shell_active == 0) { 137132144Sminshall setconnmode(); 137232144Sminshall } 137332144Sminshall #else /* defined(TN3270) */ 137432144Sminshall setconnmode(); 137532144Sminshall #endif /* defined(TN3270) */ 137632144Sminshall } 137732144Sminshall } 137832144Sminshall 137932144Sminshall /* 138032144Sminshall * Help command. 138132144Sminshall */ 138232144Sminshall static 138332144Sminshall help(argc, argv) 138432144Sminshall int argc; 138532144Sminshall char *argv[]; 138632144Sminshall { 138732144Sminshall register Command *c; 138832144Sminshall 138932144Sminshall if (argc == 1) { 139032144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 139132144Sminshall for (c = cmdtab; c->name; c++) 139232144Sminshall if (c->dohelp) { 139332144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 139432144Sminshall c->help); 139532144Sminshall } 139632144Sminshall return 0; 139732144Sminshall } 139832144Sminshall while (--argc > 0) { 139932144Sminshall register char *arg; 140032144Sminshall arg = *++argv; 140132144Sminshall c = getcmd(arg); 140232144Sminshall if (Ambiguous(c)) 140332144Sminshall printf("?Ambiguous help command %s\n", arg); 140432144Sminshall else if (c == (Command *)0) 140532144Sminshall printf("?Invalid help command %s\n", arg); 140632144Sminshall else 140732144Sminshall printf("%s\n", c->help); 140832144Sminshall } 140932144Sminshall return 0; 141032144Sminshall } 1411