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*38208Sminshall static char sccsid[] = "@(#)commands.c 1.18 (Berkeley) 05/30/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 43537226Sminshall if (did_he_say_will(TELOPT_BINARY) || did_I_say_will(TELOPT_BINARY)) { 43637226Sminshall /* leave binary mode */ 43737226Sminshall printf("Negotiating network ascii mode with remote host.\n"); 43837226Sminshall tel_leave_binary(); 43937226Sminshall } else { /* Turn off binary mode */ 44032144Sminshall printf("Negotiating binary mode with remote host.\n"); 44137226Sminshall 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 */ 497*38208Sminshall #if defined(unix) && defined(TN3270) 498*38208Sminshall { "cursesdata", 499*38208Sminshall "(debugging) toggle printing of hexadecimal curses data", 500*38208Sminshall 0, 501*38208Sminshall 1, 502*38208Sminshall &cursesdata, 503*38208Sminshall "print hexadecimal representation of curses data" }, 504*38208Sminshall #endif /* defined(unix) && defined(TN3270) */ 50532144Sminshall { "debug", 50632144Sminshall "(debugging) toggle debugging", 50732144Sminshall togdebug, 50832144Sminshall 1, 50932144Sminshall &debug, 51032144Sminshall "turn on socket level debugging" }, 51132144Sminshall { "netdata", 51232144Sminshall "(debugging) toggle printing of hexadecimal network data", 51332144Sminshall 0, 51432144Sminshall 1, 51532144Sminshall &netdata, 51632144Sminshall "print hexadecimal representation of network traffic" }, 51732144Sminshall { "options", 51832144Sminshall "(debugging) toggle viewing of options processing", 51932144Sminshall 0, 52032144Sminshall 1, 52132144Sminshall &showoptions, 52232144Sminshall "show option processing" }, 523*38208Sminshall #if defined(unix) 524*38208Sminshall { "termdata", 525*38208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 526*38208Sminshall 0, 527*38208Sminshall 1, 528*38208Sminshall &termdata, 529*38208Sminshall "print hexadecimal representation of terminal traffic" }, 530*38208Sminshall #endif /* defined(unix) */ 53132144Sminshall { " ", "", 0, 1 }, /* empty line */ 53232144Sminshall { "?", 53332144Sminshall "display help information", 53432144Sminshall togglehelp, 53532144Sminshall 1 }, 53632144Sminshall { "help", 53732144Sminshall "display help information", 53832144Sminshall togglehelp, 53932144Sminshall 0 }, 54032144Sminshall { 0 } 54132144Sminshall }; 54232144Sminshall 54332144Sminshall static 54432144Sminshall togglehelp() 54532144Sminshall { 54632144Sminshall struct togglelist *c; 54732144Sminshall 54832144Sminshall for (c = Togglelist; c->name; c++) { 54932144Sminshall if (c->dohelp) { 55032144Sminshall printf("%s\t%s\n", c->name, c->help); 55132144Sminshall } 55232144Sminshall } 55332144Sminshall return 0; 55432144Sminshall } 55532144Sminshall 55632144Sminshall static char ** 55732144Sminshall getnexttoggle(name) 55832144Sminshall char *name; 55932144Sminshall { 56032144Sminshall struct togglelist *c = (struct togglelist *) name; 56132144Sminshall 56232144Sminshall return (char **) (c+1); 56332144Sminshall } 56432144Sminshall 56532144Sminshall static struct togglelist * 56632144Sminshall gettoggle(name) 56732144Sminshall char *name; 56832144Sminshall { 56932144Sminshall return (struct togglelist *) 57032144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 57132144Sminshall } 57232144Sminshall 57332144Sminshall static 57432144Sminshall toggle(argc, argv) 57532144Sminshall int argc; 57632144Sminshall char *argv[]; 57732144Sminshall { 57832144Sminshall int retval = 1; 57932144Sminshall char *name; 58032144Sminshall struct togglelist *c; 58132144Sminshall 58232144Sminshall if (argc < 2) { 58332144Sminshall fprintf(stderr, 58432144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 58532144Sminshall return 0; 58632144Sminshall } 58732144Sminshall argc--; 58832144Sminshall argv++; 58932144Sminshall while (argc--) { 59032144Sminshall name = *argv++; 59132144Sminshall c = gettoggle(name); 59232144Sminshall if (Ambiguous(c)) { 59332144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 59432144Sminshall name); 59532144Sminshall return 0; 59632144Sminshall } else if (c == 0) { 59732144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 59832144Sminshall name); 59932144Sminshall return 0; 60032144Sminshall } else { 60132144Sminshall if (c->variable) { 60232144Sminshall *c->variable = !*c->variable; /* invert it */ 60332144Sminshall if (c->actionexplanation) { 60432144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 60532144Sminshall c->actionexplanation); 60632144Sminshall } 60732144Sminshall } 60832144Sminshall if (c->handler) { 60932144Sminshall retval &= (*c->handler)(c); 61032144Sminshall } 61132144Sminshall } 61232144Sminshall } 61332144Sminshall return retval; 61432144Sminshall } 61532144Sminshall 61632144Sminshall /* 61732144Sminshall * The following perform the "set" command. 61832144Sminshall */ 61932144Sminshall 62032144Sminshall struct setlist { 62132144Sminshall char *name; /* name */ 62232144Sminshall char *help; /* help information */ 62332144Sminshall char *charp; /* where it is located at */ 62432144Sminshall }; 62532144Sminshall 62632144Sminshall static struct setlist Setlist[] = { 62732144Sminshall { "echo", "character to toggle local echoing on/off", &echoc }, 62832144Sminshall { "escape", "character to escape back to telnet command mode", &escape }, 62932144Sminshall { " ", "" }, 63032144Sminshall { " ", "The following need 'localchars' to be toggled true", 0 }, 63132144Sminshall { "erase", "character to cause an Erase Character", &termEraseChar }, 63232144Sminshall { "flushoutput", "character to cause an Abort Oubput", &termFlushChar }, 63332144Sminshall { "interrupt", "character to cause an Interrupt Process", &termIntChar }, 63432144Sminshall { "kill", "character to cause an Erase Line", &termKillChar }, 63532144Sminshall { "quit", "character to cause a Break", &termQuitChar }, 63632144Sminshall { "eof", "character to cause an EOF ", &termEofChar }, 63732144Sminshall { 0 } 63832144Sminshall }; 63932144Sminshall 64032144Sminshall static char ** 64132144Sminshall getnextset(name) 64232144Sminshall char *name; 64332144Sminshall { 64432144Sminshall struct setlist *c = (struct setlist *)name; 64532144Sminshall 64632144Sminshall return (char **) (c+1); 64732144Sminshall } 64832144Sminshall 64932144Sminshall static struct setlist * 65032144Sminshall getset(name) 65132144Sminshall char *name; 65232144Sminshall { 65332144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 65432144Sminshall } 65532144Sminshall 65632144Sminshall static 65732144Sminshall setcmd(argc, argv) 65832144Sminshall int argc; 65932144Sminshall char *argv[]; 66032144Sminshall { 66132144Sminshall int value; 66232144Sminshall struct setlist *ct; 66332144Sminshall 66432144Sminshall /* XXX back we go... sigh */ 66532144Sminshall if (argc != 3) { 66632144Sminshall if ((argc == 2) && 66732144Sminshall ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 66832144Sminshall for (ct = Setlist; ct->name; ct++) { 66932144Sminshall printf("%s\t%s\n", ct->name, ct->help); 67032144Sminshall } 67132144Sminshall printf("?\tdisplay help information\n"); 67232144Sminshall } else { 67332144Sminshall printf("Format is 'set Name Value'\n'set ?' for help.\n"); 67432144Sminshall } 67532144Sminshall return 0; 67632144Sminshall } 67732144Sminshall 67832144Sminshall ct = getset(argv[1]); 67932144Sminshall if (ct == 0) { 68032144Sminshall fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 68132144Sminshall argv[1]); 68232144Sminshall return 0; 68332144Sminshall } else if (Ambiguous(ct)) { 68432144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 68532144Sminshall argv[1]); 68632144Sminshall return 0; 68732144Sminshall } else { 68832144Sminshall if (strcmp("off", argv[2])) { 68932144Sminshall value = special(argv[2]); 69032144Sminshall } else { 69132144Sminshall value = -1; 69232144Sminshall } 69332144Sminshall *(ct->charp) = value; 69432144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 69532144Sminshall } 69632144Sminshall return 1; 69732144Sminshall } 69832144Sminshall 69932144Sminshall /* 70032144Sminshall * The following are the data structures and routines for the 70132144Sminshall * 'mode' command. 70232144Sminshall */ 70332144Sminshall 70432144Sminshall static 70532144Sminshall dolinemode() 70632144Sminshall { 70737226Sminshall if (did_I_say_do(TELOPT_SGA)) { 70837226Sminshall send_dont(TELOPT_SGA); 70932144Sminshall } 71037226Sminshall if (did_I_say_do(TELOPT_ECHO)) { 71137226Sminshall send_dont(TELOPT_ECHO); 71232144Sminshall } 71332144Sminshall return 1; 71432144Sminshall } 71532144Sminshall 71632144Sminshall static 71732144Sminshall docharmode() 71832144Sminshall { 71937226Sminshall if (!did_I_say_do(TELOPT_SGA)) { 72037226Sminshall send_do(TELOPT_SGA); 72132144Sminshall } 72237226Sminshall if (!did_I_say_do(TELOPT_ECHO)) { 72337226Sminshall send_do(TELOPT_ECHO); 72432144Sminshall } 72532144Sminshall return 1; 72632144Sminshall } 72732144Sminshall 72832144Sminshall static Command Mode_commands[] = { 72932144Sminshall { "character", "character-at-a-time mode", docharmode, 1, 1 }, 73032144Sminshall { "line", "line-by-line mode", dolinemode, 1, 1 }, 73132144Sminshall { 0 }, 73232144Sminshall }; 73332144Sminshall 73432144Sminshall static char ** 73532144Sminshall getnextmode(name) 73632144Sminshall char *name; 73732144Sminshall { 73832144Sminshall Command *c = (Command *) name; 73932144Sminshall 74032144Sminshall return (char **) (c+1); 74132144Sminshall } 74232144Sminshall 74332144Sminshall static Command * 74432144Sminshall getmodecmd(name) 74532144Sminshall char *name; 74632144Sminshall { 74732144Sminshall return (Command *) genget(name, (char **) Mode_commands, getnextmode); 74832144Sminshall } 74932144Sminshall 75032144Sminshall static 75132144Sminshall modecmd(argc, argv) 75232144Sminshall int argc; 75332144Sminshall char *argv[]; 75432144Sminshall { 75532144Sminshall Command *mt; 75632144Sminshall 75732144Sminshall if ((argc != 2) || !strcmp(argv[1], "?") || !strcmp(argv[1], "help")) { 75832144Sminshall printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 75932144Sminshall for (mt = Mode_commands; mt->name; mt++) { 76032144Sminshall printf("%s\t%s\n", mt->name, mt->help); 76132144Sminshall } 76232144Sminshall return 0; 76332144Sminshall } 76432144Sminshall mt = getmodecmd(argv[1]); 76532144Sminshall if (mt == 0) { 76632144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 76732144Sminshall return 0; 76832144Sminshall } else if (Ambiguous(mt)) { 76932144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 77032144Sminshall return 0; 77132144Sminshall } else { 77232144Sminshall (*mt->handler)(); 77332144Sminshall } 77432144Sminshall return 1; 77532144Sminshall } 77632144Sminshall 77732144Sminshall /* 77832144Sminshall * The following data structures and routines implement the 77932144Sminshall * "display" command. 78032144Sminshall */ 78132144Sminshall 78232144Sminshall static 78332144Sminshall display(argc, argv) 78432144Sminshall int argc; 78532144Sminshall char *argv[]; 78632144Sminshall { 78732144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 78832144Sminshall if (*tl->variable) { \ 78932144Sminshall printf("will"); \ 79032144Sminshall } else { \ 79132144Sminshall printf("won't"); \ 79232144Sminshall } \ 79332144Sminshall printf(" %s.\n", tl->actionexplanation); \ 79432144Sminshall } 79532144Sminshall 79632144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 79732144Sminshall printf("[%s]\t%s.\n", control(*sl->charp), sl->name); \ 79832144Sminshall } 79932144Sminshall 80032144Sminshall struct togglelist *tl; 80132144Sminshall struct setlist *sl; 80232144Sminshall 80332144Sminshall if (argc == 1) { 80432144Sminshall for (tl = Togglelist; tl->name; tl++) { 80532144Sminshall dotog(tl); 80632144Sminshall } 80732144Sminshall printf("\n"); 80832144Sminshall for (sl = Setlist; sl->name; sl++) { 80932144Sminshall doset(sl); 81032144Sminshall } 81132144Sminshall } else { 81232144Sminshall int i; 81332144Sminshall 81432144Sminshall for (i = 1; i < argc; i++) { 81532144Sminshall sl = getset(argv[i]); 81632144Sminshall tl = gettoggle(argv[i]); 81732144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 81832144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 81932144Sminshall return 0; 82032144Sminshall } else if (!sl && !tl) { 82132144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 82232144Sminshall return 0; 82332144Sminshall } else { 82432144Sminshall if (tl) { 82532144Sminshall dotog(tl); 82632144Sminshall } 82732144Sminshall if (sl) { 82832144Sminshall doset(sl); 82932144Sminshall } 83032144Sminshall } 83132144Sminshall } 83232144Sminshall } 83332144Sminshall return 1; 83432144Sminshall #undef doset 83532144Sminshall #undef dotog 83632144Sminshall } 83732144Sminshall 83832144Sminshall /* 83932144Sminshall * The following are the data structures, and many of the routines, 84032144Sminshall * relating to command processing. 84132144Sminshall */ 84232144Sminshall 84332144Sminshall /* 84432144Sminshall * Set the escape character. 84532144Sminshall */ 84632144Sminshall static 84732144Sminshall setescape(argc, argv) 84832144Sminshall int argc; 84932144Sminshall char *argv[]; 85032144Sminshall { 85132144Sminshall register char *arg; 85232144Sminshall char buf[50]; 85332144Sminshall 85432144Sminshall printf( 85532144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 85632144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 85732144Sminshall if (argc > 2) 85832144Sminshall arg = argv[1]; 85932144Sminshall else { 86032144Sminshall printf("new escape character: "); 86134849Sminshall (void) gets(buf); 86232144Sminshall arg = buf; 86332144Sminshall } 86432144Sminshall if (arg[0] != '\0') 86532144Sminshall escape = arg[0]; 86632144Sminshall if (!In3270) { 86732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 86832144Sminshall } 86934849Sminshall (void) fflush(stdout); 87032144Sminshall return 1; 87132144Sminshall } 87232144Sminshall 87332144Sminshall /*VARARGS*/ 87432144Sminshall static 87532144Sminshall togcrmod() 87632144Sminshall { 87732144Sminshall crmod = !crmod; 87832144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 87932144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 88034849Sminshall (void) fflush(stdout); 88132144Sminshall return 1; 88232144Sminshall } 88332144Sminshall 88432144Sminshall /*VARARGS*/ 88532144Sminshall suspend() 88632144Sminshall { 88737219Sminshall setcommandmode(); 88832144Sminshall #if defined(unix) 88937219Sminshall { 89037219Sminshall long oldrows, oldcols, newrows, newcols; 89137219Sminshall 89237219Sminshall TerminalWindowSize(&oldrows, &oldcols); 89334849Sminshall (void) kill(0, SIGTSTP); 89437219Sminshall TerminalWindowSize(&newrows, &newcols); 89537219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 89637219Sminshall if (connected) { 89737219Sminshall sendnaws(); 89837219Sminshall } 89937219Sminshall } 90037219Sminshall } 90132144Sminshall #endif /* defined(unix) */ 90237219Sminshall /* reget parameters in case they were changed */ 90337219Sminshall TerminalSaveState(); 90437219Sminshall setconnmode(); 90537219Sminshall return 1; 90632144Sminshall } 90732144Sminshall 90832144Sminshall /*VARARGS*/ 90932144Sminshall static 91032144Sminshall bye(argc, argv) 91132144Sminshall int argc; /* Number of arguments */ 91232144Sminshall char *argv[]; /* arguments */ 91332144Sminshall { 91432144Sminshall if (connected) { 91534849Sminshall (void) shutdown(net, 2); 91632144Sminshall printf("Connection closed.\n"); 91734849Sminshall (void) NetClose(net); 91832144Sminshall connected = 0; 91932144Sminshall /* reset options */ 92032144Sminshall tninit(); 92132144Sminshall #if defined(TN3270) 92232144Sminshall SetIn3270(); /* Get out of 3270 mode */ 92332144Sminshall #endif /* defined(TN3270) */ 92432144Sminshall } 92532144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 92632144Sminshall longjmp(toplevel, 1); 92732144Sminshall /* NOTREACHED */ 92832144Sminshall } 92932144Sminshall return 1; /* Keep lint, etc., happy */ 93032144Sminshall } 93132144Sminshall 93232144Sminshall /*VARARGS*/ 93332144Sminshall quit() 93432144Sminshall { 93532144Sminshall (void) call(bye, "bye", "fromquit", 0); 93632144Sminshall Exit(0); 93732144Sminshall return 1; /* just to keep lint happy */ 93832144Sminshall } 93932144Sminshall 94036274Sminshall #if defined(unix) 94132144Sminshall /* 94236274Sminshall * Some information about our file descriptors. 94336274Sminshall */ 94436274Sminshall 94536274Sminshall char * 94636274Sminshall decodeflags(mask) 94736274Sminshall int mask; 94836274Sminshall { 94936274Sminshall static char buffer[100]; 95036274Sminshall #define do(m,s) \ 95136274Sminshall if (mask&(m)) { \ 95236274Sminshall strcat(buffer, (s)); \ 95336274Sminshall } 95436274Sminshall 95536274Sminshall buffer[0] = 0; /* Terminate it */ 95636274Sminshall 95736274Sminshall #ifdef FREAD 95836274Sminshall do(FREAD, " FREAD"); 95936274Sminshall #endif 96036274Sminshall #ifdef FWRITE 96136274Sminshall do(FWRITE, " FWRITE"); 96236274Sminshall #endif 96336274Sminshall #ifdef F_DUPFP 96436274Sminshall do(F_DUPFD, " F_DUPFD"); 96536274Sminshall #endif 96636274Sminshall #ifdef FNDELAY 96736274Sminshall do(FNDELAY, " FNDELAY"); 96836274Sminshall #endif 96936274Sminshall #ifdef FAPPEND 97036274Sminshall do(FAPPEND, " FAPPEND"); 97136274Sminshall #endif 97236274Sminshall #ifdef FMARK 97336274Sminshall do(FMARK, " FMARK"); 97436274Sminshall #endif 97536274Sminshall #ifdef FDEFER 97636274Sminshall do(FDEFER, " FDEFER"); 97736274Sminshall #endif 97836274Sminshall #ifdef FASYNC 97936274Sminshall do(FASYNC, " FASYNC"); 98036274Sminshall #endif 98136274Sminshall #ifdef FSHLOCK 98236274Sminshall do(FSHLOCK, " FSHLOCK"); 98336274Sminshall #endif 98436274Sminshall #ifdef FEXLOCK 98536274Sminshall do(FEXLOCK, " FEXLOCK"); 98636274Sminshall #endif 98736274Sminshall #ifdef FCREAT 98836274Sminshall do(FCREAT, " FCREAT"); 98936274Sminshall #endif 99036274Sminshall #ifdef FTRUNC 99136274Sminshall do(FTRUNC, " FTRUNC"); 99236274Sminshall #endif 99336274Sminshall #ifdef FEXCL 99436274Sminshall do(FEXCL, " FEXCL"); 99536274Sminshall #endif 99636274Sminshall 99736274Sminshall return buffer; 99836274Sminshall } 99936274Sminshall #undef do 100036274Sminshall 100136274Sminshall static void 100236274Sminshall filestuff(fd) 100336274Sminshall int fd; 100436274Sminshall { 100536274Sminshall int res; 100636274Sminshall 100736274Sminshall setconnmode(); 100836274Sminshall res = fcntl(fd, F_GETOWN, 0); 100936274Sminshall setcommandmode(); 101036274Sminshall 101136274Sminshall if (res == -1) { 101236274Sminshall perror("fcntl"); 101336274Sminshall return; 101436274Sminshall } 101536274Sminshall printf("\tOwner is %d.\n", res); 101636274Sminshall 101736274Sminshall setconnmode(); 101836274Sminshall res = fcntl(fd, F_GETFL, 0); 101936274Sminshall setcommandmode(); 102036274Sminshall 102136274Sminshall if (res == -1) { 102236274Sminshall perror("fcntl"); 102336274Sminshall return; 102436274Sminshall } 102536274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 102636274Sminshall } 102736274Sminshall 102836274Sminshall 102936274Sminshall #endif /* defined(unix) */ 103036274Sminshall 103136274Sminshall /* 103232144Sminshall * Print status about the connection. 103332144Sminshall */ 103434849Sminshall /*ARGSUSED*/ 103532144Sminshall static 103632144Sminshall status(argc, argv) 103732144Sminshall int argc; 103832144Sminshall char *argv[]; 103932144Sminshall { 104032144Sminshall if (connected) { 104132144Sminshall printf("Connected to %s.\n", hostname); 104236242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 104332144Sminshall printf("Operating in %s.\n", 104432144Sminshall modelist[getconnmode()].modedescriptions); 104532144Sminshall if (localchars) { 104632144Sminshall printf("Catching signals locally.\n"); 104732144Sminshall } 104832144Sminshall } 104932144Sminshall } else { 105032144Sminshall printf("No connection.\n"); 105132144Sminshall } 105232144Sminshall # if !defined(TN3270) 105332144Sminshall printf("Escape character is '%s'.\n", control(escape)); 105434849Sminshall (void) fflush(stdout); 105532144Sminshall # else /* !defined(TN3270) */ 105632144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 105732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 105832144Sminshall } 105932144Sminshall # if defined(unix) 106036242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 106136242Sminshall printf("SIGIO received %d time%s.\n", 106236242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 106336274Sminshall if (In3270) { 106436274Sminshall printf("Process ID %d, process group %d.\n", 106536274Sminshall getpid(), getpgrp(getpid())); 106636274Sminshall printf("Terminal input:\n"); 106736274Sminshall filestuff(tin); 106836274Sminshall printf("Terminal output:\n"); 106936274Sminshall filestuff(tout); 107036274Sminshall printf("Network socket:\n"); 107136274Sminshall filestuff(net); 107236274Sminshall } 107336242Sminshall } 107432144Sminshall if (In3270 && transcom) { 107532144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 107632144Sminshall } 107732144Sminshall # endif /* defined(unix) */ 107834849Sminshall (void) fflush(stdout); 107932144Sminshall if (In3270) { 108032144Sminshall return 0; 108132144Sminshall } 108232144Sminshall # endif /* defined(TN3270) */ 108332144Sminshall return 1; 108432144Sminshall } 108532144Sminshall 108632144Sminshall 108732144Sminshall 108832144Sminshall int 108932144Sminshall tn(argc, argv) 109032144Sminshall int argc; 109132144Sminshall char *argv[]; 109232144Sminshall { 109332144Sminshall register struct hostent *host = 0; 109432144Sminshall struct sockaddr_in sin; 109532144Sminshall struct servent *sp = 0; 109632144Sminshall static char hnamebuf[32]; 109734849Sminshall unsigned long inet_addr(); 109837219Sminshall extern char *inet_ntoa(); 109932144Sminshall 110032144Sminshall 110132144Sminshall #if defined(MSDOS) 110232144Sminshall char *cp; 110332144Sminshall #endif /* defined(MSDOS) */ 110432144Sminshall 110532144Sminshall if (connected) { 110632144Sminshall printf("?Already connected to %s\n", hostname); 110732144Sminshall return 0; 110832144Sminshall } 110932144Sminshall if (argc < 2) { 111032144Sminshall (void) strcpy(line, "Connect "); 111132144Sminshall printf("(to) "); 111234849Sminshall (void) gets(&line[strlen(line)]); 111332144Sminshall makeargv(); 111432144Sminshall argc = margc; 111532144Sminshall argv = margv; 111632144Sminshall } 111732144Sminshall if ((argc < 2) || (argc > 3)) { 111832144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 111932144Sminshall return 0; 112032144Sminshall } 112132144Sminshall #if defined(MSDOS) 112232144Sminshall for (cp = argv[1]; *cp; cp++) { 112332144Sminshall if (isupper(*cp)) { 112432144Sminshall *cp = tolower(*cp); 112532144Sminshall } 112632144Sminshall } 112732144Sminshall #endif /* defined(MSDOS) */ 112832144Sminshall sin.sin_addr.s_addr = inet_addr(argv[1]); 112936694Sminshall if (sin.sin_addr.s_addr != (unsigned long) -1) { 113032144Sminshall sin.sin_family = AF_INET; 113132144Sminshall (void) strcpy(hnamebuf, argv[1]); 113232144Sminshall hostname = hnamebuf; 113332144Sminshall } else { 113432144Sminshall host = gethostbyname(argv[1]); 113532144Sminshall if (host) { 113632144Sminshall sin.sin_family = host->h_addrtype; 113732144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 113832144Sminshall memcpy((caddr_t)&sin.sin_addr, 113932144Sminshall host->h_addr_list[0], host->h_length); 114032144Sminshall #else /* defined(h_addr) */ 114132144Sminshall memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 114232144Sminshall #endif /* defined(h_addr) */ 114332144Sminshall hostname = host->h_name; 114432144Sminshall } else { 114535789Sbostic herror(argv[1]); 114632144Sminshall return 0; 114732144Sminshall } 114832144Sminshall } 114932144Sminshall if (argc == 3) { 115032144Sminshall sin.sin_port = atoi(argv[2]); 115132144Sminshall if (sin.sin_port == 0) { 115232144Sminshall sp = getservbyname(argv[2], "tcp"); 115332144Sminshall if (sp) 115432144Sminshall sin.sin_port = sp->s_port; 115532144Sminshall else { 115632144Sminshall printf("%s: bad port number\n", argv[2]); 115732144Sminshall return 0; 115832144Sminshall } 115932144Sminshall } else { 116034849Sminshall #if !defined(htons) 116134849Sminshall u_short htons(); 116234849Sminshall #endif /* !defined(htons) */ 116332144Sminshall sin.sin_port = htons(sin.sin_port); 116432144Sminshall } 116532144Sminshall telnetport = 0; 116632144Sminshall } else { 116732144Sminshall if (sp == 0) { 116832144Sminshall sp = getservbyname("telnet", "tcp"); 116932144Sminshall if (sp == 0) { 117034849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 117132144Sminshall return 0; 117232144Sminshall } 117332144Sminshall sin.sin_port = sp->s_port; 117432144Sminshall } 117532144Sminshall telnetport = 1; 117632144Sminshall } 117737219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 117832144Sminshall do { 117932144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 118032144Sminshall if (net < 0) { 118132144Sminshall perror("telnet: socket"); 118232144Sminshall return 0; 118332144Sminshall } 118432144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 118532144Sminshall perror("setsockopt (SO_DEBUG)"); 118632144Sminshall } 118732144Sminshall 118832144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 118932144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 119032144Sminshall if (host && host->h_addr_list[1]) { 119132144Sminshall int oerrno = errno; 119232144Sminshall 119332144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 119432144Sminshall inet_ntoa(sin.sin_addr)); 119532144Sminshall errno = oerrno; 119632144Sminshall perror((char *)0); 119732144Sminshall host->h_addr_list++; 119832144Sminshall memcpy((caddr_t)&sin.sin_addr, 119932144Sminshall host->h_addr_list[0], host->h_length); 120032144Sminshall (void) NetClose(net); 120132144Sminshall continue; 120232144Sminshall } 120332144Sminshall #endif /* defined(h_addr) */ 120432144Sminshall perror("telnet: Unable to connect to remote host"); 120532144Sminshall return 0; 120637219Sminshall } 120732144Sminshall connected++; 120832144Sminshall } while (connected == 0); 120934849Sminshall (void) call(status, "status", "notmuch", 0); 121032144Sminshall if (setjmp(peerdied) == 0) 121132144Sminshall telnet(); 121234849Sminshall (void) NetClose(net); 121332381Sminshall ExitString("Connection closed by foreign host.\n",1); 121432144Sminshall /*NOTREACHED*/ 121532144Sminshall } 121632144Sminshall 121732144Sminshall 121832144Sminshall #define HELPINDENT (sizeof ("connect")) 121932144Sminshall 122032144Sminshall static char 122132144Sminshall openhelp[] = "connect to a site", 122232144Sminshall closehelp[] = "close current connection", 122332144Sminshall quithelp[] = "exit telnet", 122432144Sminshall statushelp[] = "print status information", 122532144Sminshall helphelp[] = "print help information", 122632144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 122732144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 122832144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 122932144Sminshall displayhelp[] = "display operating parameters", 123032144Sminshall #if defined(TN3270) && defined(unix) 123132144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 123232144Sminshall #endif /* defined(TN3270) && defined(unix) */ 123332144Sminshall #if defined(unix) 123432144Sminshall zhelp[] = "suspend telnet", 123532144Sminshall #endif /* defined(unix */ 123632144Sminshall #if defined(TN3270) 123732144Sminshall shellhelp[] = "invoke a subshell", 123832144Sminshall #endif /* defined(TN3270) */ 123932144Sminshall modehelp[] = "try to enter line-by-line or character-at-a-time mode"; 124032144Sminshall 124132144Sminshall extern int help(), shell(); 124232144Sminshall 124332144Sminshall static Command cmdtab[] = { 124432144Sminshall { "close", closehelp, bye, 1, 1 }, 124532144Sminshall { "display", displayhelp, display, 1, 0 }, 124632144Sminshall { "mode", modehelp, modecmd, 1, 1 }, 124732144Sminshall { "open", openhelp, tn, 1, 0 }, 124832144Sminshall { "quit", quithelp, quit, 1, 0 }, 124932144Sminshall { "send", sendhelp, sendcmd, 1, 1 }, 125032144Sminshall { "set", sethelp, setcmd, 1, 0 }, 125132144Sminshall { "status", statushelp, status, 1, 0 }, 125232144Sminshall { "toggle", togglestring, toggle, 1, 0 }, 125332144Sminshall #if defined(TN3270) && defined(unix) 125432144Sminshall { "transcom", transcomhelp, settranscom, 1, 0 }, 125532144Sminshall #endif /* defined(TN3270) && defined(unix) */ 125632144Sminshall #if defined(unix) 125732144Sminshall { "z", zhelp, suspend, 1, 0 }, 125832144Sminshall #endif /* defined(unix) */ 125932144Sminshall #if defined(TN3270) 126032144Sminshall { "!", shellhelp, shell, 1, 1 }, 126132144Sminshall #endif /* defined(TN3270) */ 126232144Sminshall { "?", helphelp, help, 1, 0 }, 126332144Sminshall 0 126432144Sminshall }; 126532144Sminshall 126632144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 126732144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 126832144Sminshall 126932144Sminshall static Command cmdtab2[] = { 127032144Sminshall { "help", helphelp, help, 0, 0 }, 127132144Sminshall { "escape", escapehelp, setescape, 1, 0 }, 127232144Sminshall { "crmod", crmodhelp, togcrmod, 1, 0 }, 127332144Sminshall 0 127432144Sminshall }; 127532144Sminshall 127635298Sminshall 127732144Sminshall /* 127832144Sminshall * Call routine with argc, argv set from args (terminated by 0). 127932144Sminshall */ 128035298Sminshall 128135417Sminshall /*VARARGS1*/ 128232144Sminshall static 128335298Sminshall call(va_alist) 128435298Sminshall va_dcl 128532144Sminshall { 128635298Sminshall va_list ap; 128735298Sminshall typedef int (*intrtn_t)(); 128835298Sminshall intrtn_t routine; 128935298Sminshall char *args[100]; 129035298Sminshall int argno = 0; 129135298Sminshall 129235298Sminshall va_start(ap); 129335298Sminshall routine = (va_arg(ap, intrtn_t)); 129435495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 129535298Sminshall ; 129635495Sminshall } 129735298Sminshall va_end(ap); 129835495Sminshall return (*routine)(argno-1, args); 129932144Sminshall } 130032144Sminshall 130135298Sminshall 130232144Sminshall static char ** 130332144Sminshall getnextcmd(name) 130432144Sminshall char *name; 130532144Sminshall { 130632144Sminshall Command *c = (Command *) name; 130732144Sminshall 130832144Sminshall return (char **) (c+1); 130932144Sminshall } 131032144Sminshall 131132144Sminshall static Command * 131232144Sminshall getcmd(name) 131332144Sminshall char *name; 131432144Sminshall { 131532144Sminshall Command *cm; 131632144Sminshall 131732144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 131832144Sminshall return cm; 131932144Sminshall } else { 132032144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 132132144Sminshall } 132232144Sminshall } 132332144Sminshall 132432144Sminshall void 132532144Sminshall command(top) 132632144Sminshall int top; 132732144Sminshall { 132832144Sminshall register Command *c; 132932144Sminshall 133032144Sminshall setcommandmode(); 133132144Sminshall if (!top) { 133232144Sminshall putchar('\n'); 133337219Sminshall #if defined(unix) 133432144Sminshall } else { 133532144Sminshall signal(SIGINT, SIG_DFL); 133632144Sminshall signal(SIGQUIT, SIG_DFL); 133732144Sminshall #endif /* defined(unix) */ 133832144Sminshall } 133932144Sminshall for (;;) { 134032144Sminshall printf("%s> ", prompt); 134132144Sminshall if (gets(line) == NULL) { 134232144Sminshall if (feof(stdin) || ferror(stdin)) 134332144Sminshall quit(); 134432144Sminshall break; 134532144Sminshall } 134632144Sminshall if (line[0] == 0) 134732144Sminshall break; 134832144Sminshall makeargv(); 134937219Sminshall if (margv[0] == 0) { 135037219Sminshall break; 135137219Sminshall } 135232144Sminshall c = getcmd(margv[0]); 135332144Sminshall if (Ambiguous(c)) { 135432144Sminshall printf("?Ambiguous command\n"); 135532144Sminshall continue; 135632144Sminshall } 135732144Sminshall if (c == 0) { 135832144Sminshall printf("?Invalid command\n"); 135932144Sminshall continue; 136032144Sminshall } 136132144Sminshall if (c->needconnect && !connected) { 136232144Sminshall printf("?Need to be connected first.\n"); 136332144Sminshall continue; 136432144Sminshall } 136532144Sminshall if ((*c->handler)(margc, margv)) { 136632144Sminshall break; 136732144Sminshall } 136832144Sminshall } 136932144Sminshall if (!top) { 137032144Sminshall if (!connected) { 137132144Sminshall longjmp(toplevel, 1); 137232144Sminshall /*NOTREACHED*/ 137332144Sminshall } 137432144Sminshall #if defined(TN3270) 137532144Sminshall if (shell_active == 0) { 137632144Sminshall setconnmode(); 137732144Sminshall } 137832144Sminshall #else /* defined(TN3270) */ 137932144Sminshall setconnmode(); 138032144Sminshall #endif /* defined(TN3270) */ 138132144Sminshall } 138232144Sminshall } 138332144Sminshall 138432144Sminshall /* 138532144Sminshall * Help command. 138632144Sminshall */ 138732144Sminshall static 138832144Sminshall help(argc, argv) 138932144Sminshall int argc; 139032144Sminshall char *argv[]; 139132144Sminshall { 139232144Sminshall register Command *c; 139332144Sminshall 139432144Sminshall if (argc == 1) { 139532144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 139632144Sminshall for (c = cmdtab; c->name; c++) 139732144Sminshall if (c->dohelp) { 139832144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 139932144Sminshall c->help); 140032144Sminshall } 140132144Sminshall return 0; 140232144Sminshall } 140332144Sminshall while (--argc > 0) { 140432144Sminshall register char *arg; 140532144Sminshall arg = *++argv; 140632144Sminshall c = getcmd(arg); 140732144Sminshall if (Ambiguous(c)) 140832144Sminshall printf("?Ambiguous help command %s\n", arg); 140932144Sminshall else if (c == (Command *)0) 141032144Sminshall printf("?Invalid help command %s\n", arg); 141132144Sminshall else 141232144Sminshall printf("%s\n", c->help); 141332144Sminshall } 141432144Sminshall return 0; 141532144Sminshall } 1416