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*36274Sminshall static char sccsid[] = "@(#)commands.c 1.14 (Berkeley) 11/29/88"; 2033685Sbostic #endif /* not lint */ 2133685Sbostic 2232144Sminshall #include <sys/types.h> 23*36274Sminshall #if defined(unix) 24*36274Sminshall #include <sys/file.h> 25*36274Sminshall #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 76*36274Sminshall 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"); 90*36274Sminshall } else if (h_errno == 0) { 91*36274Sminshall #if defined(sun) 92*36274Sminshall fprintf(stderr, "Host unknown\n"); 93*36274Sminshall #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 { 88232144Sminshall setcommandmode(); 88332144Sminshall #if defined(unix) 88434849Sminshall (void) kill(0, SIGTSTP); 88532144Sminshall #endif /* defined(unix) */ 88632144Sminshall /* reget parameters in case they were changed */ 88732144Sminshall TerminalSaveState(); 88832144Sminshall setconnmode(); 88932144Sminshall return 1; 89032144Sminshall } 89132144Sminshall 89232144Sminshall /*VARARGS*/ 89332144Sminshall static 89432144Sminshall bye(argc, argv) 89532144Sminshall int argc; /* Number of arguments */ 89632144Sminshall char *argv[]; /* arguments */ 89732144Sminshall { 89832144Sminshall if (connected) { 89934849Sminshall (void) shutdown(net, 2); 90032144Sminshall printf("Connection closed.\n"); 90134849Sminshall (void) NetClose(net); 90232144Sminshall connected = 0; 90332144Sminshall /* reset options */ 90432144Sminshall tninit(); 90532144Sminshall #if defined(TN3270) 90632144Sminshall SetIn3270(); /* Get out of 3270 mode */ 90732144Sminshall #endif /* defined(TN3270) */ 90832144Sminshall } 90932144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 91032144Sminshall longjmp(toplevel, 1); 91132144Sminshall /* NOTREACHED */ 91232144Sminshall } 91332144Sminshall return 1; /* Keep lint, etc., happy */ 91432144Sminshall } 91532144Sminshall 91632144Sminshall /*VARARGS*/ 91732144Sminshall quit() 91832144Sminshall { 91932144Sminshall (void) call(bye, "bye", "fromquit", 0); 92032144Sminshall Exit(0); 92132144Sminshall return 1; /* just to keep lint happy */ 92232144Sminshall } 92332144Sminshall 924*36274Sminshall #if defined(unix) 92532144Sminshall /* 926*36274Sminshall * Some information about our file descriptors. 927*36274Sminshall */ 928*36274Sminshall 929*36274Sminshall char * 930*36274Sminshall decodeflags(mask) 931*36274Sminshall int mask; 932*36274Sminshall { 933*36274Sminshall static char buffer[100]; 934*36274Sminshall #define do(m,s) \ 935*36274Sminshall if (mask&(m)) { \ 936*36274Sminshall strcat(buffer, (s)); \ 937*36274Sminshall } 938*36274Sminshall 939*36274Sminshall buffer[0] = 0; /* Terminate it */ 940*36274Sminshall 941*36274Sminshall #ifdef FREAD 942*36274Sminshall do(FREAD, " FREAD"); 943*36274Sminshall #endif 944*36274Sminshall #ifdef FWRITE 945*36274Sminshall do(FWRITE, " FWRITE"); 946*36274Sminshall #endif 947*36274Sminshall #ifdef F_DUPFP 948*36274Sminshall do(F_DUPFD, " F_DUPFD"); 949*36274Sminshall #endif 950*36274Sminshall #ifdef FNDELAY 951*36274Sminshall do(FNDELAY, " FNDELAY"); 952*36274Sminshall #endif 953*36274Sminshall #ifdef FAPPEND 954*36274Sminshall do(FAPPEND, " FAPPEND"); 955*36274Sminshall #endif 956*36274Sminshall #ifdef FMARK 957*36274Sminshall do(FMARK, " FMARK"); 958*36274Sminshall #endif 959*36274Sminshall #ifdef FDEFER 960*36274Sminshall do(FDEFER, " FDEFER"); 961*36274Sminshall #endif 962*36274Sminshall #ifdef FASYNC 963*36274Sminshall do(FASYNC, " FASYNC"); 964*36274Sminshall #endif 965*36274Sminshall #ifdef FSHLOCK 966*36274Sminshall do(FSHLOCK, " FSHLOCK"); 967*36274Sminshall #endif 968*36274Sminshall #ifdef FEXLOCK 969*36274Sminshall do(FEXLOCK, " FEXLOCK"); 970*36274Sminshall #endif 971*36274Sminshall #ifdef FCREAT 972*36274Sminshall do(FCREAT, " FCREAT"); 973*36274Sminshall #endif 974*36274Sminshall #ifdef FTRUNC 975*36274Sminshall do(FTRUNC, " FTRUNC"); 976*36274Sminshall #endif 977*36274Sminshall #ifdef FEXCL 978*36274Sminshall do(FEXCL, " FEXCL"); 979*36274Sminshall #endif 980*36274Sminshall 981*36274Sminshall return buffer; 982*36274Sminshall } 983*36274Sminshall #undef do 984*36274Sminshall 985*36274Sminshall static void 986*36274Sminshall filestuff(fd) 987*36274Sminshall int fd; 988*36274Sminshall { 989*36274Sminshall int res; 990*36274Sminshall 991*36274Sminshall setconnmode(); 992*36274Sminshall res = fcntl(fd, F_GETOWN, 0); 993*36274Sminshall setcommandmode(); 994*36274Sminshall 995*36274Sminshall if (res == -1) { 996*36274Sminshall perror("fcntl"); 997*36274Sminshall return; 998*36274Sminshall } 999*36274Sminshall printf("\tOwner is %d.\n", res); 1000*36274Sminshall 1001*36274Sminshall setconnmode(); 1002*36274Sminshall res = fcntl(fd, F_GETFL, 0); 1003*36274Sminshall setcommandmode(); 1004*36274Sminshall 1005*36274Sminshall if (res == -1) { 1006*36274Sminshall perror("fcntl"); 1007*36274Sminshall return; 1008*36274Sminshall } 1009*36274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 1010*36274Sminshall } 1011*36274Sminshall 1012*36274Sminshall 1013*36274Sminshall #endif /* defined(unix) */ 1014*36274Sminshall 1015*36274Sminshall /* 101632144Sminshall * Print status about the connection. 101732144Sminshall */ 101834849Sminshall /*ARGSUSED*/ 101932144Sminshall static 102032144Sminshall status(argc, argv) 102132144Sminshall int argc; 102232144Sminshall char *argv[]; 102332144Sminshall { 102432144Sminshall if (connected) { 102532144Sminshall printf("Connected to %s.\n", hostname); 102636242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 102732144Sminshall printf("Operating in %s.\n", 102832144Sminshall modelist[getconnmode()].modedescriptions); 102932144Sminshall if (localchars) { 103032144Sminshall printf("Catching signals locally.\n"); 103132144Sminshall } 103232144Sminshall } 103332144Sminshall } else { 103432144Sminshall printf("No connection.\n"); 103532144Sminshall } 103632144Sminshall # if !defined(TN3270) 103732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 103834849Sminshall (void) fflush(stdout); 103932144Sminshall # else /* !defined(TN3270) */ 104032144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 104132144Sminshall printf("Escape character is '%s'.\n", control(escape)); 104232144Sminshall } 104332144Sminshall # if defined(unix) 104436242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 104536242Sminshall printf("SIGIO received %d time%s.\n", 104636242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 1047*36274Sminshall if (In3270) { 1048*36274Sminshall printf("Process ID %d, process group %d.\n", 1049*36274Sminshall getpid(), getpgrp(getpid())); 1050*36274Sminshall printf("Terminal input:\n"); 1051*36274Sminshall filestuff(tin); 1052*36274Sminshall printf("Terminal output:\n"); 1053*36274Sminshall filestuff(tout); 1054*36274Sminshall printf("Network socket:\n"); 1055*36274Sminshall filestuff(net); 1056*36274Sminshall } 105736242Sminshall } 105832144Sminshall if (In3270 && transcom) { 105932144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 106032144Sminshall } 106132144Sminshall # endif /* defined(unix) */ 106234849Sminshall (void) fflush(stdout); 106332144Sminshall if (In3270) { 106432144Sminshall return 0; 106532144Sminshall } 106632144Sminshall # endif /* defined(TN3270) */ 106732144Sminshall return 1; 106832144Sminshall } 106932144Sminshall 107032144Sminshall 107132144Sminshall 107232144Sminshall int 107332144Sminshall tn(argc, argv) 107432144Sminshall int argc; 107532144Sminshall char *argv[]; 107632144Sminshall { 107732144Sminshall register struct hostent *host = 0; 107832144Sminshall struct sockaddr_in sin; 107932144Sminshall struct servent *sp = 0; 108032144Sminshall static char hnamebuf[32]; 108134849Sminshall unsigned long inet_addr(); 108232144Sminshall 108332144Sminshall 108432144Sminshall #if defined(MSDOS) 108532144Sminshall char *cp; 108632144Sminshall #endif /* defined(MSDOS) */ 108732144Sminshall 108832144Sminshall if (connected) { 108932144Sminshall printf("?Already connected to %s\n", hostname); 109032144Sminshall return 0; 109132144Sminshall } 109232144Sminshall if (argc < 2) { 109332144Sminshall (void) strcpy(line, "Connect "); 109432144Sminshall printf("(to) "); 109534849Sminshall (void) gets(&line[strlen(line)]); 109632144Sminshall makeargv(); 109732144Sminshall argc = margc; 109832144Sminshall argv = margv; 109932144Sminshall } 110032144Sminshall if ((argc < 2) || (argc > 3)) { 110132144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 110232144Sminshall return 0; 110332144Sminshall } 110432144Sminshall #if defined(MSDOS) 110532144Sminshall for (cp = argv[1]; *cp; cp++) { 110632144Sminshall if (isupper(*cp)) { 110732144Sminshall *cp = tolower(*cp); 110832144Sminshall } 110932144Sminshall } 111032144Sminshall #endif /* defined(MSDOS) */ 111132144Sminshall sin.sin_addr.s_addr = inet_addr(argv[1]); 111232144Sminshall if (sin.sin_addr.s_addr != -1) { 111332144Sminshall sin.sin_family = AF_INET; 111432144Sminshall (void) strcpy(hnamebuf, argv[1]); 111532144Sminshall hostname = hnamebuf; 111632144Sminshall } else { 111732144Sminshall host = gethostbyname(argv[1]); 111832144Sminshall if (host) { 111932144Sminshall sin.sin_family = host->h_addrtype; 112032144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 112132144Sminshall memcpy((caddr_t)&sin.sin_addr, 112232144Sminshall host->h_addr_list[0], host->h_length); 112332144Sminshall #else /* defined(h_addr) */ 112432144Sminshall memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 112532144Sminshall #endif /* defined(h_addr) */ 112632144Sminshall hostname = host->h_name; 112732144Sminshall } else { 112835789Sbostic herror(argv[1]); 112932144Sminshall return 0; 113032144Sminshall } 113132144Sminshall } 113232144Sminshall if (argc == 3) { 113332144Sminshall sin.sin_port = atoi(argv[2]); 113432144Sminshall if (sin.sin_port == 0) { 113532144Sminshall sp = getservbyname(argv[2], "tcp"); 113632144Sminshall if (sp) 113732144Sminshall sin.sin_port = sp->s_port; 113832144Sminshall else { 113932144Sminshall printf("%s: bad port number\n", argv[2]); 114032144Sminshall return 0; 114132144Sminshall } 114232144Sminshall } else { 114334849Sminshall #if !defined(htons) 114434849Sminshall u_short htons(); 114534849Sminshall #endif /* !defined(htons) */ 114634849Sminshall 114732144Sminshall sin.sin_port = atoi(argv[2]); 114832144Sminshall sin.sin_port = htons(sin.sin_port); 114932144Sminshall } 115032144Sminshall telnetport = 0; 115132144Sminshall } else { 115232144Sminshall if (sp == 0) { 115332144Sminshall sp = getservbyname("telnet", "tcp"); 115432144Sminshall if (sp == 0) { 115534849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 115632144Sminshall return 0; 115732144Sminshall } 115832144Sminshall sin.sin_port = sp->s_port; 115932144Sminshall } 116032144Sminshall telnetport = 1; 116132144Sminshall } 116232144Sminshall printf("Trying...\n"); 116332144Sminshall do { 116432144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 116532144Sminshall if (net < 0) { 116632144Sminshall perror("telnet: socket"); 116732144Sminshall return 0; 116832144Sminshall } 116932144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 117032144Sminshall perror("setsockopt (SO_DEBUG)"); 117132144Sminshall } 117232144Sminshall 117332144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 117432144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 117532144Sminshall if (host && host->h_addr_list[1]) { 117632144Sminshall int oerrno = errno; 117734849Sminshall extern char *inet_ntoa(); 117832144Sminshall 117932144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 118032144Sminshall inet_ntoa(sin.sin_addr)); 118132144Sminshall errno = oerrno; 118232144Sminshall perror((char *)0); 118332144Sminshall host->h_addr_list++; 118432144Sminshall memcpy((caddr_t)&sin.sin_addr, 118532144Sminshall host->h_addr_list[0], host->h_length); 118632144Sminshall fprintf(stderr, "Trying %s...\n", 118732144Sminshall inet_ntoa(sin.sin_addr)); 118832144Sminshall (void) NetClose(net); 118932144Sminshall continue; 119032144Sminshall } 119132144Sminshall #endif /* defined(h_addr) */ 119232144Sminshall perror("telnet: Unable to connect to remote host"); 119332144Sminshall return 0; 119432144Sminshall } 119532144Sminshall connected++; 119632144Sminshall } while (connected == 0); 119734849Sminshall (void) call(status, "status", "notmuch", 0); 119832144Sminshall if (setjmp(peerdied) == 0) 119932144Sminshall telnet(); 120034849Sminshall (void) NetClose(net); 120132381Sminshall ExitString("Connection closed by foreign host.\n",1); 120232144Sminshall /*NOTREACHED*/ 120332144Sminshall } 120432144Sminshall 120532144Sminshall 120632144Sminshall #define HELPINDENT (sizeof ("connect")) 120732144Sminshall 120832144Sminshall static char 120932144Sminshall openhelp[] = "connect to a site", 121032144Sminshall closehelp[] = "close current connection", 121132144Sminshall quithelp[] = "exit telnet", 121232144Sminshall statushelp[] = "print status information", 121332144Sminshall helphelp[] = "print help information", 121432144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 121532144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 121632144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 121732144Sminshall displayhelp[] = "display operating parameters", 121832144Sminshall #if defined(TN3270) && defined(unix) 121932144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 122032144Sminshall #endif /* defined(TN3270) && defined(unix) */ 122132144Sminshall #if defined(unix) 122232144Sminshall zhelp[] = "suspend telnet", 122332144Sminshall #endif /* defined(unix */ 122432144Sminshall #if defined(TN3270) 122532144Sminshall shellhelp[] = "invoke a subshell", 122632144Sminshall #endif /* defined(TN3270) */ 122732144Sminshall modehelp[] = "try to enter line-by-line or character-at-a-time mode"; 122832144Sminshall 122932144Sminshall extern int help(), shell(); 123032144Sminshall 123132144Sminshall static Command cmdtab[] = { 123232144Sminshall { "close", closehelp, bye, 1, 1 }, 123332144Sminshall { "display", displayhelp, display, 1, 0 }, 123432144Sminshall { "mode", modehelp, modecmd, 1, 1 }, 123532144Sminshall { "open", openhelp, tn, 1, 0 }, 123632144Sminshall { "quit", quithelp, quit, 1, 0 }, 123732144Sminshall { "send", sendhelp, sendcmd, 1, 1 }, 123832144Sminshall { "set", sethelp, setcmd, 1, 0 }, 123932144Sminshall { "status", statushelp, status, 1, 0 }, 124032144Sminshall { "toggle", togglestring, toggle, 1, 0 }, 124132144Sminshall #if defined(TN3270) && defined(unix) 124232144Sminshall { "transcom", transcomhelp, settranscom, 1, 0 }, 124332144Sminshall #endif /* defined(TN3270) && defined(unix) */ 124432144Sminshall #if defined(unix) 124532144Sminshall { "z", zhelp, suspend, 1, 0 }, 124632144Sminshall #endif /* defined(unix) */ 124732144Sminshall #if defined(TN3270) 124832144Sminshall { "!", shellhelp, shell, 1, 1 }, 124932144Sminshall #endif /* defined(TN3270) */ 125032144Sminshall { "?", helphelp, help, 1, 0 }, 125132144Sminshall 0 125232144Sminshall }; 125332144Sminshall 125432144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 125532144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 125632144Sminshall 125732144Sminshall static Command cmdtab2[] = { 125832144Sminshall { "help", helphelp, help, 0, 0 }, 125932144Sminshall { "escape", escapehelp, setescape, 1, 0 }, 126032144Sminshall { "crmod", crmodhelp, togcrmod, 1, 0 }, 126132144Sminshall 0 126232144Sminshall }; 126332144Sminshall 126435298Sminshall 126532144Sminshall /* 126632144Sminshall * Call routine with argc, argv set from args (terminated by 0). 126732144Sminshall */ 126835298Sminshall 126935417Sminshall /*VARARGS1*/ 127032144Sminshall static 127135298Sminshall call(va_alist) 127235298Sminshall va_dcl 127332144Sminshall { 127435298Sminshall va_list ap; 127535298Sminshall typedef int (*intrtn_t)(); 127635298Sminshall intrtn_t routine; 127735298Sminshall char *args[100]; 127835298Sminshall int argno = 0; 127935298Sminshall 128035298Sminshall va_start(ap); 128135298Sminshall routine = (va_arg(ap, intrtn_t)); 128235495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 128335298Sminshall ; 128435495Sminshall } 128535298Sminshall va_end(ap); 128635495Sminshall return (*routine)(argno-1, args); 128732144Sminshall } 128832144Sminshall 128935298Sminshall 129032144Sminshall static char ** 129132144Sminshall getnextcmd(name) 129232144Sminshall char *name; 129332144Sminshall { 129432144Sminshall Command *c = (Command *) name; 129532144Sminshall 129632144Sminshall return (char **) (c+1); 129732144Sminshall } 129832144Sminshall 129932144Sminshall static Command * 130032144Sminshall getcmd(name) 130132144Sminshall char *name; 130232144Sminshall { 130332144Sminshall Command *cm; 130432144Sminshall 130532144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 130632144Sminshall return cm; 130732144Sminshall } else { 130832144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 130932144Sminshall } 131032144Sminshall } 131132144Sminshall 131232144Sminshall void 131332144Sminshall command(top) 131432144Sminshall int top; 131532144Sminshall { 131632144Sminshall register Command *c; 131732144Sminshall 131832144Sminshall setcommandmode(); 131932144Sminshall if (!top) { 132032144Sminshall putchar('\n'); 132132144Sminshall } else { 132232144Sminshall #if defined(unix) 132332144Sminshall signal(SIGINT, SIG_DFL); 132432144Sminshall signal(SIGQUIT, SIG_DFL); 132532144Sminshall #endif /* defined(unix) */ 132632144Sminshall } 132732144Sminshall for (;;) { 132832144Sminshall printf("%s> ", prompt); 132932144Sminshall if (gets(line) == NULL) { 133032144Sminshall if (feof(stdin) || ferror(stdin)) 133132144Sminshall quit(); 133232144Sminshall break; 133332144Sminshall } 133432144Sminshall if (line[0] == 0) 133532144Sminshall break; 133632144Sminshall makeargv(); 133732144Sminshall c = getcmd(margv[0]); 133832144Sminshall if (Ambiguous(c)) { 133932144Sminshall printf("?Ambiguous command\n"); 134032144Sminshall continue; 134132144Sminshall } 134232144Sminshall if (c == 0) { 134332144Sminshall printf("?Invalid command\n"); 134432144Sminshall continue; 134532144Sminshall } 134632144Sminshall if (c->needconnect && !connected) { 134732144Sminshall printf("?Need to be connected first.\n"); 134832144Sminshall continue; 134932144Sminshall } 135032144Sminshall if ((*c->handler)(margc, margv)) { 135132144Sminshall break; 135232144Sminshall } 135332144Sminshall } 135432144Sminshall if (!top) { 135532144Sminshall if (!connected) { 135632144Sminshall longjmp(toplevel, 1); 135732144Sminshall /*NOTREACHED*/ 135832144Sminshall } 135932144Sminshall #if defined(TN3270) 136032144Sminshall if (shell_active == 0) { 136132144Sminshall setconnmode(); 136232144Sminshall } 136332144Sminshall #else /* defined(TN3270) */ 136432144Sminshall setconnmode(); 136532144Sminshall #endif /* defined(TN3270) */ 136632144Sminshall } 136732144Sminshall } 136832144Sminshall 136932144Sminshall /* 137032144Sminshall * Help command. 137132144Sminshall */ 137232144Sminshall static 137332144Sminshall help(argc, argv) 137432144Sminshall int argc; 137532144Sminshall char *argv[]; 137632144Sminshall { 137732144Sminshall register Command *c; 137832144Sminshall 137932144Sminshall if (argc == 1) { 138032144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 138132144Sminshall for (c = cmdtab; c->name; c++) 138232144Sminshall if (c->dohelp) { 138332144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 138432144Sminshall c->help); 138532144Sminshall } 138632144Sminshall return 0; 138732144Sminshall } 138832144Sminshall while (--argc > 0) { 138932144Sminshall register char *arg; 139032144Sminshall arg = *++argv; 139132144Sminshall c = getcmd(arg); 139232144Sminshall if (Ambiguous(c)) 139332144Sminshall printf("?Ambiguous help command %s\n", arg); 139432144Sminshall else if (c == (Command *)0) 139532144Sminshall printf("?Invalid help command %s\n", arg); 139632144Sminshall else 139732144Sminshall printf("%s\n", c->help); 139832144Sminshall } 139932144Sminshall return 0; 140032144Sminshall } 1401