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*37226Sminshall static char sccsid[] = "@(#)commands.c 1.17 (Berkeley) 03/21/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 435*37226Sminshall if (did_he_say_will(TELOPT_BINARY) || did_I_say_will(TELOPT_BINARY)) { 436*37226Sminshall /* leave binary mode */ 437*37226Sminshall printf("Negotiating network ascii mode with remote host.\n"); 438*37226Sminshall tel_leave_binary(); 439*37226Sminshall } else { /* Turn off binary mode */ 44032144Sminshall printf("Negotiating binary mode with remote host.\n"); 441*37226Sminshall tel_enter_binary(); 44232144Sminshall } 44332144Sminshall return 1; 44432144Sminshall } 44532144Sminshall 44632144Sminshall 44732144Sminshall 44832144Sminshall extern int togglehelp(); 44932144Sminshall 45032144Sminshall struct togglelist { 45132144Sminshall char *name; /* name of toggle */ 45232144Sminshall char *help; /* help message */ 45332144Sminshall int (*handler)(); /* routine to do actual setting */ 45432144Sminshall int dohelp; /* should we display help information */ 45532144Sminshall int *variable; 45632144Sminshall char *actionexplanation; 45732144Sminshall }; 45832144Sminshall 45932144Sminshall static struct togglelist Togglelist[] = { 46032144Sminshall { "autoflush", 46132144Sminshall "toggle flushing of output when sending interrupt characters", 46232144Sminshall 0, 46332144Sminshall 1, 46432144Sminshall &autoflush, 46532144Sminshall "flush output when sending interrupt characters" }, 46632144Sminshall { "autosynch", 46732144Sminshall "toggle automatic sending of interrupt characters in urgent mode", 46832144Sminshall 0, 46932144Sminshall 1, 47032144Sminshall &autosynch, 47132144Sminshall "send interrupt characters in urgent mode" }, 47232144Sminshall { "binary", 47332144Sminshall "toggle sending and receiving of binary data", 47432144Sminshall togbinary, 47532144Sminshall 1, 47632144Sminshall 0, 47732144Sminshall 0 }, 47832144Sminshall { "crlf", 47932144Sminshall "toggle sending carriage returns as telnet <CR><LF>", 48032144Sminshall togcrlf, 48132144Sminshall 1, 48232144Sminshall &crlf, 48332144Sminshall 0 }, 48432144Sminshall { "crmod", 48532144Sminshall "toggle mapping of received carriage returns", 48632144Sminshall 0, 48732144Sminshall 1, 48832144Sminshall &crmod, 48932144Sminshall "map carriage return on output" }, 49032144Sminshall { "localchars", 49132144Sminshall "toggle local recognition of certain control characters", 49232144Sminshall lclchars, 49332144Sminshall 1, 49432144Sminshall &localchars, 49532144Sminshall "recognize certain control characters" }, 49632144Sminshall { " ", "", 0, 1 }, /* empty line */ 49732144Sminshall { "debug", 49832144Sminshall "(debugging) toggle debugging", 49932144Sminshall togdebug, 50032144Sminshall 1, 50132144Sminshall &debug, 50232144Sminshall "turn on socket level debugging" }, 50332144Sminshall { "netdata", 50432144Sminshall "(debugging) toggle printing of hexadecimal network data", 50532144Sminshall 0, 50632144Sminshall 1, 50732144Sminshall &netdata, 50832144Sminshall "print hexadecimal representation of network traffic" }, 50932144Sminshall { "options", 51032144Sminshall "(debugging) toggle viewing of options processing", 51132144Sminshall 0, 51232144Sminshall 1, 51332144Sminshall &showoptions, 51432144Sminshall "show option processing" }, 51532144Sminshall { " ", "", 0, 1 }, /* empty line */ 51632144Sminshall { "?", 51732144Sminshall "display help information", 51832144Sminshall togglehelp, 51932144Sminshall 1 }, 52032144Sminshall { "help", 52132144Sminshall "display help information", 52232144Sminshall togglehelp, 52332144Sminshall 0 }, 52432144Sminshall { 0 } 52532144Sminshall }; 52632144Sminshall 52732144Sminshall static 52832144Sminshall togglehelp() 52932144Sminshall { 53032144Sminshall struct togglelist *c; 53132144Sminshall 53232144Sminshall for (c = Togglelist; c->name; c++) { 53332144Sminshall if (c->dohelp) { 53432144Sminshall printf("%s\t%s\n", c->name, c->help); 53532144Sminshall } 53632144Sminshall } 53732144Sminshall return 0; 53832144Sminshall } 53932144Sminshall 54032144Sminshall static char ** 54132144Sminshall getnexttoggle(name) 54232144Sminshall char *name; 54332144Sminshall { 54432144Sminshall struct togglelist *c = (struct togglelist *) name; 54532144Sminshall 54632144Sminshall return (char **) (c+1); 54732144Sminshall } 54832144Sminshall 54932144Sminshall static struct togglelist * 55032144Sminshall gettoggle(name) 55132144Sminshall char *name; 55232144Sminshall { 55332144Sminshall return (struct togglelist *) 55432144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 55532144Sminshall } 55632144Sminshall 55732144Sminshall static 55832144Sminshall toggle(argc, argv) 55932144Sminshall int argc; 56032144Sminshall char *argv[]; 56132144Sminshall { 56232144Sminshall int retval = 1; 56332144Sminshall char *name; 56432144Sminshall struct togglelist *c; 56532144Sminshall 56632144Sminshall if (argc < 2) { 56732144Sminshall fprintf(stderr, 56832144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 56932144Sminshall return 0; 57032144Sminshall } 57132144Sminshall argc--; 57232144Sminshall argv++; 57332144Sminshall while (argc--) { 57432144Sminshall name = *argv++; 57532144Sminshall c = gettoggle(name); 57632144Sminshall if (Ambiguous(c)) { 57732144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 57832144Sminshall name); 57932144Sminshall return 0; 58032144Sminshall } else if (c == 0) { 58132144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 58232144Sminshall name); 58332144Sminshall return 0; 58432144Sminshall } else { 58532144Sminshall if (c->variable) { 58632144Sminshall *c->variable = !*c->variable; /* invert it */ 58732144Sminshall if (c->actionexplanation) { 58832144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 58932144Sminshall c->actionexplanation); 59032144Sminshall } 59132144Sminshall } 59232144Sminshall if (c->handler) { 59332144Sminshall retval &= (*c->handler)(c); 59432144Sminshall } 59532144Sminshall } 59632144Sminshall } 59732144Sminshall return retval; 59832144Sminshall } 59932144Sminshall 60032144Sminshall /* 60132144Sminshall * The following perform the "set" command. 60232144Sminshall */ 60332144Sminshall 60432144Sminshall struct setlist { 60532144Sminshall char *name; /* name */ 60632144Sminshall char *help; /* help information */ 60732144Sminshall char *charp; /* where it is located at */ 60832144Sminshall }; 60932144Sminshall 61032144Sminshall static struct setlist Setlist[] = { 61132144Sminshall { "echo", "character to toggle local echoing on/off", &echoc }, 61232144Sminshall { "escape", "character to escape back to telnet command mode", &escape }, 61332144Sminshall { " ", "" }, 61432144Sminshall { " ", "The following need 'localchars' to be toggled true", 0 }, 61532144Sminshall { "erase", "character to cause an Erase Character", &termEraseChar }, 61632144Sminshall { "flushoutput", "character to cause an Abort Oubput", &termFlushChar }, 61732144Sminshall { "interrupt", "character to cause an Interrupt Process", &termIntChar }, 61832144Sminshall { "kill", "character to cause an Erase Line", &termKillChar }, 61932144Sminshall { "quit", "character to cause a Break", &termQuitChar }, 62032144Sminshall { "eof", "character to cause an EOF ", &termEofChar }, 62132144Sminshall { 0 } 62232144Sminshall }; 62332144Sminshall 62432144Sminshall static char ** 62532144Sminshall getnextset(name) 62632144Sminshall char *name; 62732144Sminshall { 62832144Sminshall struct setlist *c = (struct setlist *)name; 62932144Sminshall 63032144Sminshall return (char **) (c+1); 63132144Sminshall } 63232144Sminshall 63332144Sminshall static struct setlist * 63432144Sminshall getset(name) 63532144Sminshall char *name; 63632144Sminshall { 63732144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 63832144Sminshall } 63932144Sminshall 64032144Sminshall static 64132144Sminshall setcmd(argc, argv) 64232144Sminshall int argc; 64332144Sminshall char *argv[]; 64432144Sminshall { 64532144Sminshall int value; 64632144Sminshall struct setlist *ct; 64732144Sminshall 64832144Sminshall /* XXX back we go... sigh */ 64932144Sminshall if (argc != 3) { 65032144Sminshall if ((argc == 2) && 65132144Sminshall ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 65232144Sminshall for (ct = Setlist; ct->name; ct++) { 65332144Sminshall printf("%s\t%s\n", ct->name, ct->help); 65432144Sminshall } 65532144Sminshall printf("?\tdisplay help information\n"); 65632144Sminshall } else { 65732144Sminshall printf("Format is 'set Name Value'\n'set ?' for help.\n"); 65832144Sminshall } 65932144Sminshall return 0; 66032144Sminshall } 66132144Sminshall 66232144Sminshall ct = getset(argv[1]); 66332144Sminshall if (ct == 0) { 66432144Sminshall fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 66532144Sminshall argv[1]); 66632144Sminshall return 0; 66732144Sminshall } else if (Ambiguous(ct)) { 66832144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 66932144Sminshall argv[1]); 67032144Sminshall return 0; 67132144Sminshall } else { 67232144Sminshall if (strcmp("off", argv[2])) { 67332144Sminshall value = special(argv[2]); 67432144Sminshall } else { 67532144Sminshall value = -1; 67632144Sminshall } 67732144Sminshall *(ct->charp) = value; 67832144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 67932144Sminshall } 68032144Sminshall return 1; 68132144Sminshall } 68232144Sminshall 68332144Sminshall /* 68432144Sminshall * The following are the data structures and routines for the 68532144Sminshall * 'mode' command. 68632144Sminshall */ 68732144Sminshall 68832144Sminshall static 68932144Sminshall dolinemode() 69032144Sminshall { 691*37226Sminshall if (did_I_say_do(TELOPT_SGA)) { 692*37226Sminshall send_dont(TELOPT_SGA); 69332144Sminshall } 694*37226Sminshall if (did_I_say_do(TELOPT_ECHO)) { 695*37226Sminshall send_dont(TELOPT_ECHO); 69632144Sminshall } 69732144Sminshall return 1; 69832144Sminshall } 69932144Sminshall 70032144Sminshall static 70132144Sminshall docharmode() 70232144Sminshall { 703*37226Sminshall if (!did_I_say_do(TELOPT_SGA)) { 704*37226Sminshall send_do(TELOPT_SGA); 70532144Sminshall } 706*37226Sminshall if (!did_I_say_do(TELOPT_ECHO)) { 707*37226Sminshall send_do(TELOPT_ECHO); 70832144Sminshall } 70932144Sminshall return 1; 71032144Sminshall } 71132144Sminshall 71232144Sminshall static Command Mode_commands[] = { 71332144Sminshall { "character", "character-at-a-time mode", docharmode, 1, 1 }, 71432144Sminshall { "line", "line-by-line mode", dolinemode, 1, 1 }, 71532144Sminshall { 0 }, 71632144Sminshall }; 71732144Sminshall 71832144Sminshall static char ** 71932144Sminshall getnextmode(name) 72032144Sminshall char *name; 72132144Sminshall { 72232144Sminshall Command *c = (Command *) name; 72332144Sminshall 72432144Sminshall return (char **) (c+1); 72532144Sminshall } 72632144Sminshall 72732144Sminshall static Command * 72832144Sminshall getmodecmd(name) 72932144Sminshall char *name; 73032144Sminshall { 73132144Sminshall return (Command *) genget(name, (char **) Mode_commands, getnextmode); 73232144Sminshall } 73332144Sminshall 73432144Sminshall static 73532144Sminshall modecmd(argc, argv) 73632144Sminshall int argc; 73732144Sminshall char *argv[]; 73832144Sminshall { 73932144Sminshall Command *mt; 74032144Sminshall 74132144Sminshall if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) { 74232144Sminshall printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 74332144Sminshall for (mt = Mode_commands; mt->name; mt++) { 74432144Sminshall printf("%s\t%s\n", mt->name, mt->help); 74532144Sminshall } 74632144Sminshall return 0; 74732144Sminshall } 74832144Sminshall mt = getmodecmd(argv[1]); 74932144Sminshall if (mt == 0) { 75032144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 75132144Sminshall return 0; 75232144Sminshall } else if (Ambiguous(mt)) { 75332144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 75432144Sminshall return 0; 75532144Sminshall } else { 75632144Sminshall (*mt->handler)(); 75732144Sminshall } 75832144Sminshall return 1; 75932144Sminshall } 76032144Sminshall 76132144Sminshall /* 76232144Sminshall * The following data structures and routines implement the 76332144Sminshall * "display" command. 76432144Sminshall */ 76532144Sminshall 76632144Sminshall static 76732144Sminshall display(argc, argv) 76832144Sminshall int argc; 76932144Sminshall char *argv[]; 77032144Sminshall { 77132144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 77232144Sminshall if (*tl->variable) { \ 77332144Sminshall printf("will"); \ 77432144Sminshall } else { \ 77532144Sminshall printf("won't"); \ 77632144Sminshall } \ 77732144Sminshall printf(" %s.\n", tl->actionexplanation); \ 77832144Sminshall } 77932144Sminshall 78032144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 78132144Sminshall printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \ 78232144Sminshall } 78332144Sminshall 78432144Sminshall struct togglelist *tl; 78532144Sminshall struct setlist *sl; 78632144Sminshall 78732144Sminshall if (argc == 1) { 78832144Sminshall for (tl = Togglelist; tl->name; tl++) { 78932144Sminshall dotog(tl); 79032144Sminshall } 79132144Sminshall printf("\n"); 79232144Sminshall for (sl = Setlist; sl->name; sl++) { 79332144Sminshall doset(sl); 79432144Sminshall } 79532144Sminshall } else { 79632144Sminshall int i; 79732144Sminshall 79832144Sminshall for (i = 1; i < argc; i++) { 79932144Sminshall sl = getset(argv[i]); 80032144Sminshall tl = gettoggle(argv[i]); 80132144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 80232144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 80332144Sminshall return 0; 80432144Sminshall } else if (!sl && !tl) { 80532144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 80632144Sminshall return 0; 80732144Sminshall } else { 80832144Sminshall if (tl) { 80932144Sminshall dotog(tl); 81032144Sminshall } 81132144Sminshall if (sl) { 81232144Sminshall doset(sl); 81332144Sminshall } 81432144Sminshall } 81532144Sminshall } 81632144Sminshall } 81732144Sminshall return 1; 81832144Sminshall #undef doset 81932144Sminshall #undef dotog 82032144Sminshall } 82132144Sminshall 82232144Sminshall /* 82332144Sminshall * The following are the data structures, and many of the routines, 82432144Sminshall * relating to command processing. 82532144Sminshall */ 82632144Sminshall 82732144Sminshall /* 82832144Sminshall * Set the escape character. 82932144Sminshall */ 83032144Sminshall static 83132144Sminshall setescape(argc, argv) 83232144Sminshall int argc; 83332144Sminshall char *argv[]; 83432144Sminshall { 83532144Sminshall register char *arg; 83632144Sminshall char buf[50]; 83732144Sminshall 83832144Sminshall printf( 83932144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 84032144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 84132144Sminshall if (argc > 2) 84232144Sminshall arg = argv[1]; 84332144Sminshall else { 84432144Sminshall printf("new escape character: "); 84534849Sminshall (void) gets(buf); 84632144Sminshall arg = buf; 84732144Sminshall } 84832144Sminshall if (arg[0] != '\0') 84932144Sminshall escape = arg[0]; 85032144Sminshall if (!In3270) { 85132144Sminshall printf("Escape character is '%s'.\n", control(escape)); 85232144Sminshall } 85334849Sminshall (void) fflush(stdout); 85432144Sminshall return 1; 85532144Sminshall } 85632144Sminshall 85732144Sminshall /*VARARGS*/ 85832144Sminshall static 85932144Sminshall togcrmod() 86032144Sminshall { 86132144Sminshall crmod = !crmod; 86232144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 86332144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 86434849Sminshall (void) fflush(stdout); 86532144Sminshall return 1; 86632144Sminshall } 86732144Sminshall 86832144Sminshall /*VARARGS*/ 86932144Sminshall suspend() 87032144Sminshall { 87137219Sminshall setcommandmode(); 87232144Sminshall #if defined(unix) 87337219Sminshall { 87437219Sminshall long oldrows, oldcols, newrows, newcols; 87537219Sminshall 87637219Sminshall TerminalWindowSize(&oldrows, &oldcols); 87734849Sminshall (void) kill(0, SIGTSTP); 87837219Sminshall TerminalWindowSize(&newrows, &newcols); 87937219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 88037219Sminshall if (connected) { 88137219Sminshall sendnaws(); 88237219Sminshall } 88337219Sminshall } 88437219Sminshall } 88532144Sminshall #endif /* defined(unix) */ 88637219Sminshall /* reget parameters in case they were changed */ 88737219Sminshall TerminalSaveState(); 88837219Sminshall setconnmode(); 88937219Sminshall 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 92436274Sminshall #if defined(unix) 92532144Sminshall /* 92636274Sminshall * Some information about our file descriptors. 92736274Sminshall */ 92836274Sminshall 92936274Sminshall char * 93036274Sminshall decodeflags(mask) 93136274Sminshall int mask; 93236274Sminshall { 93336274Sminshall static char buffer[100]; 93436274Sminshall #define do(m,s) \ 93536274Sminshall if (mask&(m)) { \ 93636274Sminshall strcat(buffer, (s)); \ 93736274Sminshall } 93836274Sminshall 93936274Sminshall buffer[0] = 0; /* Terminate it */ 94036274Sminshall 94136274Sminshall #ifdef FREAD 94236274Sminshall do(FREAD, " FREAD"); 94336274Sminshall #endif 94436274Sminshall #ifdef FWRITE 94536274Sminshall do(FWRITE, " FWRITE"); 94636274Sminshall #endif 94736274Sminshall #ifdef F_DUPFP 94836274Sminshall do(F_DUPFD, " F_DUPFD"); 94936274Sminshall #endif 95036274Sminshall #ifdef FNDELAY 95136274Sminshall do(FNDELAY, " FNDELAY"); 95236274Sminshall #endif 95336274Sminshall #ifdef FAPPEND 95436274Sminshall do(FAPPEND, " FAPPEND"); 95536274Sminshall #endif 95636274Sminshall #ifdef FMARK 95736274Sminshall do(FMARK, " FMARK"); 95836274Sminshall #endif 95936274Sminshall #ifdef FDEFER 96036274Sminshall do(FDEFER, " FDEFER"); 96136274Sminshall #endif 96236274Sminshall #ifdef FASYNC 96336274Sminshall do(FASYNC, " FASYNC"); 96436274Sminshall #endif 96536274Sminshall #ifdef FSHLOCK 96636274Sminshall do(FSHLOCK, " FSHLOCK"); 96736274Sminshall #endif 96836274Sminshall #ifdef FEXLOCK 96936274Sminshall do(FEXLOCK, " FEXLOCK"); 97036274Sminshall #endif 97136274Sminshall #ifdef FCREAT 97236274Sminshall do(FCREAT, " FCREAT"); 97336274Sminshall #endif 97436274Sminshall #ifdef FTRUNC 97536274Sminshall do(FTRUNC, " FTRUNC"); 97636274Sminshall #endif 97736274Sminshall #ifdef FEXCL 97836274Sminshall do(FEXCL, " FEXCL"); 97936274Sminshall #endif 98036274Sminshall 98136274Sminshall return buffer; 98236274Sminshall } 98336274Sminshall #undef do 98436274Sminshall 98536274Sminshall static void 98636274Sminshall filestuff(fd) 98736274Sminshall int fd; 98836274Sminshall { 98936274Sminshall int res; 99036274Sminshall 99136274Sminshall setconnmode(); 99236274Sminshall res = fcntl(fd, F_GETOWN, 0); 99336274Sminshall setcommandmode(); 99436274Sminshall 99536274Sminshall if (res == -1) { 99636274Sminshall perror("fcntl"); 99736274Sminshall return; 99836274Sminshall } 99936274Sminshall printf("\tOwner is %d.\n", res); 100036274Sminshall 100136274Sminshall setconnmode(); 100236274Sminshall res = fcntl(fd, F_GETFL, 0); 100336274Sminshall setcommandmode(); 100436274Sminshall 100536274Sminshall if (res == -1) { 100636274Sminshall perror("fcntl"); 100736274Sminshall return; 100836274Sminshall } 100936274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 101036274Sminshall } 101136274Sminshall 101236274Sminshall 101336274Sminshall #endif /* defined(unix) */ 101436274Sminshall 101536274Sminshall /* 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"); 104736274Sminshall if (In3270) { 104836274Sminshall printf("Process ID %d, process group %d.\n", 104936274Sminshall getpid(), getpgrp(getpid())); 105036274Sminshall printf("Terminal input:\n"); 105136274Sminshall filestuff(tin); 105236274Sminshall printf("Terminal output:\n"); 105336274Sminshall filestuff(tout); 105436274Sminshall printf("Network socket:\n"); 105536274Sminshall filestuff(net); 105636274Sminshall } 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(); 108237219Sminshall extern char *inet_ntoa(); 108332144Sminshall 108432144Sminshall 108532144Sminshall #if defined(MSDOS) 108632144Sminshall char *cp; 108732144Sminshall #endif /* defined(MSDOS) */ 108832144Sminshall 108932144Sminshall if (connected) { 109032144Sminshall printf("?Already connected to %s\n", hostname); 109132144Sminshall return 0; 109232144Sminshall } 109332144Sminshall if (argc < 2) { 109432144Sminshall (void) strcpy(line, "Connect "); 109532144Sminshall printf("(to) "); 109634849Sminshall (void) gets(&line[strlen(line)]); 109732144Sminshall makeargv(); 109832144Sminshall argc = margc; 109932144Sminshall argv = margv; 110032144Sminshall } 110132144Sminshall if ((argc < 2) || (argc > 3)) { 110232144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 110332144Sminshall return 0; 110432144Sminshall } 110532144Sminshall #if defined(MSDOS) 110632144Sminshall for (cp = argv[1]; *cp; cp++) { 110732144Sminshall if (isupper(*cp)) { 110832144Sminshall *cp = tolower(*cp); 110932144Sminshall } 111032144Sminshall } 111132144Sminshall #endif /* defined(MSDOS) */ 111232144Sminshall sin.sin_addr.s_addr = inet_addr(argv[1]); 111336694Sminshall if (sin.sin_addr.s_addr != (unsigned long) -1) { 111432144Sminshall sin.sin_family = AF_INET; 111532144Sminshall (void) strcpy(hnamebuf, argv[1]); 111632144Sminshall hostname = hnamebuf; 111732144Sminshall } else { 111832144Sminshall host = gethostbyname(argv[1]); 111932144Sminshall if (host) { 112032144Sminshall sin.sin_family = host->h_addrtype; 112132144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 112232144Sminshall memcpy((caddr_t)&sin.sin_addr, 112332144Sminshall host->h_addr_list[0], host->h_length); 112432144Sminshall #else /* defined(h_addr) */ 112532144Sminshall memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 112632144Sminshall #endif /* defined(h_addr) */ 112732144Sminshall hostname = host->h_name; 112832144Sminshall } else { 112935789Sbostic herror(argv[1]); 113032144Sminshall return 0; 113132144Sminshall } 113232144Sminshall } 113332144Sminshall if (argc == 3) { 113432144Sminshall sin.sin_port = atoi(argv[2]); 113532144Sminshall if (sin.sin_port == 0) { 113632144Sminshall sp = getservbyname(argv[2], "tcp"); 113732144Sminshall if (sp) 113832144Sminshall sin.sin_port = sp->s_port; 113932144Sminshall else { 114032144Sminshall printf("%s: bad port number\n", argv[2]); 114132144Sminshall return 0; 114232144Sminshall } 114332144Sminshall } else { 114434849Sminshall #if !defined(htons) 114534849Sminshall u_short htons(); 114634849Sminshall #endif /* !defined(htons) */ 114732144Sminshall sin.sin_port = htons(sin.sin_port); 114832144Sminshall } 114932144Sminshall telnetport = 0; 115032144Sminshall } else { 115132144Sminshall if (sp == 0) { 115232144Sminshall sp = getservbyname("telnet", "tcp"); 115332144Sminshall if (sp == 0) { 115434849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 115532144Sminshall return 0; 115632144Sminshall } 115732144Sminshall sin.sin_port = sp->s_port; 115832144Sminshall } 115932144Sminshall telnetport = 1; 116032144Sminshall } 116137219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 116232144Sminshall do { 116332144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 116432144Sminshall if (net < 0) { 116532144Sminshall perror("telnet: socket"); 116632144Sminshall return 0; 116732144Sminshall } 116832144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 116932144Sminshall perror("setsockopt (SO_DEBUG)"); 117032144Sminshall } 117132144Sminshall 117232144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 117332144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 117432144Sminshall if (host && host->h_addr_list[1]) { 117532144Sminshall int oerrno = errno; 117632144Sminshall 117732144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 117832144Sminshall inet_ntoa(sin.sin_addr)); 117932144Sminshall errno = oerrno; 118032144Sminshall perror((char *)0); 118132144Sminshall host->h_addr_list++; 118232144Sminshall memcpy((caddr_t)&sin.sin_addr, 118332144Sminshall host->h_addr_list[0], host->h_length); 118432144Sminshall (void) NetClose(net); 118532144Sminshall continue; 118632144Sminshall } 118732144Sminshall #endif /* defined(h_addr) */ 118832144Sminshall perror("telnet: Unable to connect to remote host"); 118932144Sminshall return 0; 119037219Sminshall } 119132144Sminshall connected++; 119232144Sminshall } while (connected == 0); 119334849Sminshall (void) call(status, "status", "notmuch", 0); 119432144Sminshall if (setjmp(peerdied) == 0) 119532144Sminshall telnet(); 119634849Sminshall (void) NetClose(net); 119732381Sminshall ExitString("Connection closed by foreign host.\n",1); 119832144Sminshall /*NOTREACHED*/ 119932144Sminshall } 120032144Sminshall 120132144Sminshall 120232144Sminshall #define HELPINDENT (sizeof ("connect")) 120332144Sminshall 120432144Sminshall static char 120532144Sminshall openhelp[] = "connect to a site", 120632144Sminshall closehelp[] = "close current connection", 120732144Sminshall quithelp[] = "exit telnet", 120832144Sminshall statushelp[] = "print status information", 120932144Sminshall helphelp[] = "print help information", 121032144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 121132144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 121232144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 121332144Sminshall displayhelp[] = "display operating parameters", 121432144Sminshall #if defined(TN3270) && defined(unix) 121532144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 121632144Sminshall #endif /* defined(TN3270) && defined(unix) */ 121732144Sminshall #if defined(unix) 121832144Sminshall zhelp[] = "suspend telnet", 121932144Sminshall #endif /* defined(unix */ 122032144Sminshall #if defined(TN3270) 122132144Sminshall shellhelp[] = "invoke a subshell", 122232144Sminshall #endif /* defined(TN3270) */ 122332144Sminshall modehelp[] = "try to enter line-by-line or character-at-a-time mode"; 122432144Sminshall 122532144Sminshall extern int help(), shell(); 122632144Sminshall 122732144Sminshall static Command cmdtab[] = { 122832144Sminshall { "close", closehelp, bye, 1, 1 }, 122932144Sminshall { "display", displayhelp, display, 1, 0 }, 123032144Sminshall { "mode", modehelp, modecmd, 1, 1 }, 123132144Sminshall { "open", openhelp, tn, 1, 0 }, 123232144Sminshall { "quit", quithelp, quit, 1, 0 }, 123332144Sminshall { "send", sendhelp, sendcmd, 1, 1 }, 123432144Sminshall { "set", sethelp, setcmd, 1, 0 }, 123532144Sminshall { "status", statushelp, status, 1, 0 }, 123632144Sminshall { "toggle", togglestring, toggle, 1, 0 }, 123732144Sminshall #if defined(TN3270) && defined(unix) 123832144Sminshall { "transcom", transcomhelp, settranscom, 1, 0 }, 123932144Sminshall #endif /* defined(TN3270) && defined(unix) */ 124032144Sminshall #if defined(unix) 124132144Sminshall { "z", zhelp, suspend, 1, 0 }, 124232144Sminshall #endif /* defined(unix) */ 124332144Sminshall #if defined(TN3270) 124432144Sminshall { "!", shellhelp, shell, 1, 1 }, 124532144Sminshall #endif /* defined(TN3270) */ 124632144Sminshall { "?", helphelp, help, 1, 0 }, 124732144Sminshall 0 124832144Sminshall }; 124932144Sminshall 125032144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 125132144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 125232144Sminshall 125332144Sminshall static Command cmdtab2[] = { 125432144Sminshall { "help", helphelp, help, 0, 0 }, 125532144Sminshall { "escape", escapehelp, setescape, 1, 0 }, 125632144Sminshall { "crmod", crmodhelp, togcrmod, 1, 0 }, 125732144Sminshall 0 125832144Sminshall }; 125932144Sminshall 126035298Sminshall 126132144Sminshall /* 126232144Sminshall * Call routine with argc, argv set from args (terminated by 0). 126332144Sminshall */ 126435298Sminshall 126535417Sminshall /*VARARGS1*/ 126632144Sminshall static 126735298Sminshall call(va_alist) 126835298Sminshall va_dcl 126932144Sminshall { 127035298Sminshall va_list ap; 127135298Sminshall typedef int (*intrtn_t)(); 127235298Sminshall intrtn_t routine; 127335298Sminshall char *args[100]; 127435298Sminshall int argno = 0; 127535298Sminshall 127635298Sminshall va_start(ap); 127735298Sminshall routine = (va_arg(ap, intrtn_t)); 127835495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 127935298Sminshall ; 128035495Sminshall } 128135298Sminshall va_end(ap); 128235495Sminshall return (*routine)(argno-1, args); 128332144Sminshall } 128432144Sminshall 128535298Sminshall 128632144Sminshall static char ** 128732144Sminshall getnextcmd(name) 128832144Sminshall char *name; 128932144Sminshall { 129032144Sminshall Command *c = (Command *) name; 129132144Sminshall 129232144Sminshall return (char **) (c+1); 129332144Sminshall } 129432144Sminshall 129532144Sminshall static Command * 129632144Sminshall getcmd(name) 129732144Sminshall char *name; 129832144Sminshall { 129932144Sminshall Command *cm; 130032144Sminshall 130132144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 130232144Sminshall return cm; 130332144Sminshall } else { 130432144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 130532144Sminshall } 130632144Sminshall } 130732144Sminshall 130832144Sminshall void 130932144Sminshall command(top) 131032144Sminshall int top; 131132144Sminshall { 131232144Sminshall register Command *c; 131332144Sminshall 131432144Sminshall setcommandmode(); 131532144Sminshall if (!top) { 131632144Sminshall putchar('\n'); 131737219Sminshall #if defined(unix) 131832144Sminshall } else { 131932144Sminshall signal(SIGINT, SIG_DFL); 132032144Sminshall signal(SIGQUIT, SIG_DFL); 132132144Sminshall #endif /* defined(unix) */ 132232144Sminshall } 132332144Sminshall for (;;) { 132432144Sminshall printf("%s> ", prompt); 132532144Sminshall if (gets(line) == NULL) { 132632144Sminshall if (feof(stdin) || ferror(stdin)) 132732144Sminshall quit(); 132832144Sminshall break; 132932144Sminshall } 133032144Sminshall if (line[0] == 0) 133132144Sminshall break; 133232144Sminshall makeargv(); 133337219Sminshall if (margv[0] == 0) { 133437219Sminshall break; 133537219Sminshall } 133632144Sminshall c = getcmd(margv[0]); 133732144Sminshall if (Ambiguous(c)) { 133832144Sminshall printf("?Ambiguous command\n"); 133932144Sminshall continue; 134032144Sminshall } 134132144Sminshall if (c == 0) { 134232144Sminshall printf("?Invalid command\n"); 134332144Sminshall continue; 134432144Sminshall } 134532144Sminshall if (c->needconnect && !connected) { 134632144Sminshall printf("?Need to be connected first.\n"); 134732144Sminshall continue; 134832144Sminshall } 134932144Sminshall if ((*c->handler)(margc, margv)) { 135032144Sminshall break; 135132144Sminshall } 135232144Sminshall } 135332144Sminshall if (!top) { 135432144Sminshall if (!connected) { 135532144Sminshall longjmp(toplevel, 1); 135632144Sminshall /*NOTREACHED*/ 135732144Sminshall } 135832144Sminshall #if defined(TN3270) 135932144Sminshall if (shell_active == 0) { 136032144Sminshall setconnmode(); 136132144Sminshall } 136232144Sminshall #else /* defined(TN3270) */ 136332144Sminshall setconnmode(); 136432144Sminshall #endif /* defined(TN3270) */ 136532144Sminshall } 136632144Sminshall } 136732144Sminshall 136832144Sminshall /* 136932144Sminshall * Help command. 137032144Sminshall */ 137132144Sminshall static 137232144Sminshall help(argc, argv) 137332144Sminshall int argc; 137432144Sminshall char *argv[]; 137532144Sminshall { 137632144Sminshall register Command *c; 137732144Sminshall 137832144Sminshall if (argc == 1) { 137932144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 138032144Sminshall for (c = cmdtab; c->name; c++) 138132144Sminshall if (c->dohelp) { 138232144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 138332144Sminshall c->help); 138432144Sminshall } 138532144Sminshall return 0; 138632144Sminshall } 138732144Sminshall while (--argc > 0) { 138832144Sminshall register char *arg; 138932144Sminshall arg = *++argv; 139032144Sminshall c = getcmd(arg); 139132144Sminshall if (Ambiguous(c)) 139232144Sminshall printf("?Ambiguous help command %s\n", arg); 139332144Sminshall else if (c == (Command *)0) 139432144Sminshall printf("?Invalid help command %s\n", arg); 139532144Sminshall else 139632144Sminshall printf("%s\n", c->help); 139732144Sminshall } 139832144Sminshall return 0; 139932144Sminshall } 1400