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*40248Sborman static char sccsid[] = "@(#)commands.c 1.25 (Berkeley) 03/01/90"; 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> 2838689Sborman #ifdef CRAY 2938689Sborman #include <sys/fcntl.h> 3038810Sborman #endif /* CRAY */ 3132144Sminshall 3232144Sminshall #include <signal.h> 3332144Sminshall #include <netdb.h> 3432144Sminshall #include <ctype.h> 3535298Sminshall #include <varargs.h> 3632144Sminshall 3732144Sminshall #include <arpa/telnet.h> 3832144Sminshall 3934305Sminshall #include "general.h" 4034305Sminshall 4132381Sminshall #include "ring.h" 4232381Sminshall 4332144Sminshall #include "externs.h" 4432144Sminshall #include "defines.h" 4532144Sminshall #include "types.h" 4632144Sminshall 4738689Sborman #ifdef SRCRT 4838810Sborman # ifndef CRAY 4938810Sborman # include <netinet/in_systm.h> 5039529Sborman # if defined(vax) || defined(tahoe) 5138810Sborman # include <machine/endian.h> 5239529Sborman # endif /* vax */ 5338810Sborman # endif /* CRAY */ 5438689Sborman #include <netinet/ip.h> 5538810Sborman #endif /* SRCRT */ 5638689Sborman 57*40248Sborman #if defined(CRAY) && defined(IP_TOS) && !defined(HAS_IP_TOS) 58*40248Sborman # define HAS_IP_TOS 59*40248Sborman #endif 6038689Sborman 61*40248Sborman 6232144Sminshall char *hostname; 6338689Sborman extern char *getenv(); 6432144Sminshall 6536180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 6632144Sminshall static char *ambiguous; /* special return value for command routines */ 6732144Sminshall 6832144Sminshall typedef struct { 6932144Sminshall char *name; /* command name */ 7038689Sborman char *help; /* help string (NULL for no help) */ 7132144Sminshall int (*handler)(); /* routine which executes command */ 7232144Sminshall int needconnect; /* Do we need to be connected to execute? */ 7332144Sminshall } Command; 7432144Sminshall 7538689Sborman static char line[256]; 7638689Sborman static char saveline[256]; 7732144Sminshall static int margc; 7832144Sminshall static char *margv[20]; 7932144Sminshall 8032144Sminshall /* 8132144Sminshall * Various utility routines. 8232144Sminshall */ 8332144Sminshall 8436180Sminshall #if !defined(BSD) || (BSD <= 43) 8536180Sminshall 8636180Sminshall char *h_errlist[] = { 8736180Sminshall "Error 0", 8836180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 8936180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 9036180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 9136180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 9236180Sminshall }; 9336180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 9436180Sminshall 9536274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 9636180Sminshall 9736180Sminshall /* 9836180Sminshall * herror -- 9936180Sminshall * print the error indicated by the h_errno value. 10036180Sminshall */ 10136180Sminshall herror(s) 10236180Sminshall char *s; 10336180Sminshall { 10436180Sminshall if (s && *s) { 10536180Sminshall fprintf(stderr, "%s: ", s); 10636180Sminshall } 10736180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 10836180Sminshall fprintf(stderr, "Unknown error\n"); 10936274Sminshall } else if (h_errno == 0) { 11036274Sminshall #if defined(sun) 11136274Sminshall fprintf(stderr, "Host unknown\n"); 11236274Sminshall #endif /* defined(sun) */ 11336180Sminshall } else { 11436180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 11536180Sminshall } 11636180Sminshall } 11736180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 11836180Sminshall 11932144Sminshall static void 12032144Sminshall makeargv() 12132144Sminshall { 12232144Sminshall register char *cp; 12332144Sminshall register char **argp = margv; 12432144Sminshall 12532144Sminshall margc = 0; 12632144Sminshall cp = line; 12732144Sminshall if (*cp == '!') { /* Special case shell escape */ 12838689Sborman strcpy(saveline, line); /* save for shell command */ 12932144Sminshall *argp++ = "!"; /* No room in string to get this */ 13032144Sminshall margc++; 13132144Sminshall cp++; 13232144Sminshall } 13332144Sminshall while (*cp) { 13432144Sminshall while (isspace(*cp)) 13532144Sminshall cp++; 13632144Sminshall if (*cp == '\0') 13732144Sminshall break; 13832144Sminshall *argp++ = cp; 13932144Sminshall margc += 1; 14032144Sminshall while (*cp != '\0' && !isspace(*cp)) 14132144Sminshall cp++; 14232144Sminshall if (*cp == '\0') 14332144Sminshall break; 14432144Sminshall *cp++ = '\0'; 14532144Sminshall } 14632144Sminshall *argp++ = 0; 14732144Sminshall } 14832144Sminshall 14932144Sminshall 15032144Sminshall static char ** 15132144Sminshall genget(name, table, next) 15232144Sminshall char *name; /* name to match */ 15332144Sminshall char **table; /* name entry in table */ 15432144Sminshall char **(*next)(); /* routine to return next entry in table */ 15532144Sminshall { 15632144Sminshall register char *p, *q; 15732144Sminshall register char **c, **found; 15832144Sminshall register int nmatches, longest; 15932144Sminshall 16032144Sminshall if (name == 0) { 16132144Sminshall return 0; 16232144Sminshall } 16332144Sminshall longest = 0; 16432144Sminshall nmatches = 0; 16532144Sminshall found = 0; 16632144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 16732144Sminshall for (q = name; 16832144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 16932144Sminshall if (*q == 0) /* exact match? */ 17032144Sminshall return (c); 17132144Sminshall if (!*q) { /* the name was a prefix */ 17232144Sminshall if (q - name > longest) { 17332144Sminshall longest = q - name; 17432144Sminshall nmatches = 1; 17532144Sminshall found = c; 17632144Sminshall } else if (q - name == longest) 17732144Sminshall nmatches++; 17832144Sminshall } 17932144Sminshall } 18032144Sminshall if (nmatches > 1) 18136180Sminshall return &ambiguous; 18232144Sminshall return (found); 18332144Sminshall } 18432144Sminshall 18532144Sminshall /* 18632144Sminshall * Make a character string into a number. 18732144Sminshall * 18832144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 18932144Sminshall */ 19032144Sminshall 19132144Sminshall static 19232144Sminshall special(s) 19332144Sminshall register char *s; 19432144Sminshall { 19532144Sminshall register char c; 19632144Sminshall char b; 19732144Sminshall 19832144Sminshall switch (*s) { 19932144Sminshall case '^': 20032144Sminshall b = *++s; 20132144Sminshall if (b == '?') { 20232144Sminshall c = b | 0x40; /* DEL */ 20332144Sminshall } else { 20432144Sminshall c = b & 0x1f; 20532144Sminshall } 20632144Sminshall break; 20732144Sminshall default: 20832144Sminshall c = *s; 20932144Sminshall break; 21032144Sminshall } 21132144Sminshall return c; 21232144Sminshall } 21332144Sminshall 21432144Sminshall /* 21532144Sminshall * Construct a control character sequence 21632144Sminshall * for a special character. 21732144Sminshall */ 21832144Sminshall static char * 21932144Sminshall control(c) 22040245Sborman register cc_t c; 22132144Sminshall { 22232144Sminshall static char buf[3]; 22332144Sminshall 22432144Sminshall if (c == 0x7f) 22532144Sminshall return ("^?"); 22640245Sborman if (c == (cc_t)-1) { 22732144Sminshall return "off"; 22832144Sminshall } 22932144Sminshall if (c >= 0x20) { 23032144Sminshall buf[0] = c; 23132144Sminshall buf[1] = 0; 23232144Sminshall } else { 23332144Sminshall buf[0] = '^'; 23432144Sminshall buf[1] = '@'+c; 23532144Sminshall buf[2] = 0; 23632144Sminshall } 23732144Sminshall return (buf); 23832144Sminshall } 23932144Sminshall 24032144Sminshall 24132144Sminshall 24232144Sminshall /* 24332144Sminshall * The following are data structures and routines for 24432144Sminshall * the "send" command. 24532144Sminshall * 24632144Sminshall */ 24732144Sminshall 24832144Sminshall struct sendlist { 24932144Sminshall char *name; /* How user refers to it (case independent) */ 25032144Sminshall char *help; /* Help information (0 ==> no help) */ 25132144Sminshall #if defined(NOT43) 25238689Sborman int (*handler)(); /* Routine to perform (for special ops) */ 25332144Sminshall #else /* defined(NOT43) */ 25438689Sborman void (*handler)(); /* Routine to perform (for special ops) */ 25532144Sminshall #endif /* defined(NOT43) */ 25638689Sborman int what; /* Character to be sent (<0 ==> special) */ 25732144Sminshall }; 25832144Sminshall 25932144Sminshall #define SENDQUESTION -1 26032144Sminshall #define SENDESCAPE -3 26132144Sminshall 26232144Sminshall static struct sendlist Sendlist[] = { 26338689Sborman { "ao", "Send Telnet Abort output", 0, AO }, 26438689Sborman { "ayt", "Send Telnet 'Are You There'", 0, AYT }, 26538689Sborman { "brk", "Send Telnet Break", 0, BREAK }, 26638689Sborman { "ec", "Send Telnet Erase Character", 0, EC }, 26738689Sborman { "el", "Send Telnet Erase Line", 0, EL }, 26838689Sborman { "escape", "Send current escape character", 0, SENDESCAPE }, 26938689Sborman { "ga", "Send Telnet 'Go Ahead' sequence", 0, GA }, 27038689Sborman { "ip", "Send Telnet Interrupt Process", 0, IP }, 27138689Sborman { "nop", "Send Telnet 'No operation'", 0, NOP }, 27238689Sborman { "eor", "Send Telnet 'End of Record'", 0, EOR }, 27338689Sborman { "abort", "Send Telnet 'Abort Process'", 0, ABORT }, 27438689Sborman { "susp", "Send Telnet 'Suspend Process'", 0, SUSP }, 27538689Sborman { "eof", "Send Telnet End of File Character", 0, xEOF }, 27638689Sborman { "synch", "Perform Telnet 'Synch operation'", dosynch, SYNCH }, 27738909Sborman { "getstatus", "Send request for STATUS", get_status, 0 }, 27838689Sborman { "?", "Display send options", 0, SENDQUESTION }, 27932144Sminshall { 0 } 28032144Sminshall }; 28132144Sminshall 28232144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 28338689Sborman { "break", 0, 0, BREAK }, 28432144Sminshall 28538689Sborman { "intp", 0, 0, IP }, 28638689Sborman { "interrupt", 0, 0, IP }, 28738689Sborman { "intr", 0, 0, IP }, 28832144Sminshall 28938689Sborman { "help", 0, 0, SENDQUESTION }, 29032144Sminshall 29138689Sborman { 0 } 29232144Sminshall }; 29332144Sminshall 29432144Sminshall static char ** 29532144Sminshall getnextsend(name) 29632144Sminshall char *name; 29732144Sminshall { 29832144Sminshall struct sendlist *c = (struct sendlist *) name; 29932144Sminshall 30032144Sminshall return (char **) (c+1); 30132144Sminshall } 30232144Sminshall 30332144Sminshall static struct sendlist * 30432144Sminshall getsend(name) 30532144Sminshall char *name; 30632144Sminshall { 30732144Sminshall struct sendlist *sl; 30832144Sminshall 30932144Sminshall if ((sl = (struct sendlist *) 31032144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 31132144Sminshall return sl; 31232144Sminshall } else { 31332144Sminshall return (struct sendlist *) 31432144Sminshall genget(name, (char **) Sendlist2, getnextsend); 31532144Sminshall } 31632144Sminshall } 31732144Sminshall 31832144Sminshall static 31932144Sminshall sendcmd(argc, argv) 32032144Sminshall int argc; 32132144Sminshall char **argv; 32232144Sminshall { 32332144Sminshall int what; /* what we are sending this time */ 32432144Sminshall int count; /* how many bytes we are going to need to send */ 32532144Sminshall int i; 32632144Sminshall int question = 0; /* was at least one argument a question */ 32732144Sminshall struct sendlist *s; /* pointer to current command */ 32832144Sminshall 32932144Sminshall if (argc < 2) { 33032144Sminshall printf("need at least one argument for 'send' command\n"); 33132144Sminshall printf("'send ?' for help\n"); 33232144Sminshall return 0; 33332144Sminshall } 33432144Sminshall /* 33532144Sminshall * First, validate all the send arguments. 33632144Sminshall * In addition, we see how much space we are going to need, and 33732144Sminshall * whether or not we will be doing a "SYNCH" operation (which 33832144Sminshall * flushes the network queue). 33932144Sminshall */ 34032144Sminshall count = 0; 34132144Sminshall for (i = 1; i < argc; i++) { 34232144Sminshall s = getsend(argv[i]); 34332144Sminshall if (s == 0) { 34432144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 34532144Sminshall argv[i]); 34632144Sminshall return 0; 34732144Sminshall } else if (Ambiguous(s)) { 34832144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 34932144Sminshall argv[i]); 35032144Sminshall return 0; 35132144Sminshall } 35232144Sminshall switch (s->what) { 35332144Sminshall case SENDQUESTION: 35438689Sborman question = 1; 35532144Sminshall break; 35632144Sminshall case SENDESCAPE: 35732144Sminshall count += 1; 35832144Sminshall break; 35932144Sminshall case SYNCH: 36032144Sminshall count += 2; 36132144Sminshall break; 36232144Sminshall default: 36332144Sminshall count += 2; 36432144Sminshall break; 36532144Sminshall } 36632144Sminshall } 36738689Sborman if (!connected) { 36838689Sborman if (count) 36938689Sborman printf("?Need to be connected first.\n"); 37038689Sborman if (question) { 37138689Sborman for (s = Sendlist; s->name; s++) 37238689Sborman if (s->help) 37338689Sborman printf("%-15s %s\n", s->name, s->help); 37438689Sborman } else 37538689Sborman printf("'send ?' for help\n"); 37638689Sborman return !question; 37738689Sborman } 37832144Sminshall /* Now, do we have enough room? */ 37932144Sminshall if (NETROOM() < count) { 38032144Sminshall printf("There is not enough room in the buffer TO the network\n"); 38132144Sminshall printf("to process your request. Nothing will be done.\n"); 38232144Sminshall printf("('send synch' will throw away most data in the network\n"); 38332144Sminshall printf("buffer, if this might help.)\n"); 38432144Sminshall return 0; 38532144Sminshall } 38632144Sminshall /* OK, they are all OK, now go through again and actually send */ 38732144Sminshall for (i = 1; i < argc; i++) { 38832144Sminshall if ((s = getsend(argv[i])) == 0) { 38932144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 39032144Sminshall quit(); 39132144Sminshall /*NOTREACHED*/ 39232144Sminshall } 39338689Sborman if (s->handler) { 39438689Sborman (*s->handler)(s); 39532144Sminshall } else { 39632144Sminshall switch (what = s->what) { 39732144Sminshall case SYNCH: 39832144Sminshall dosynch(); 39932144Sminshall break; 40032144Sminshall case SENDQUESTION: 40132144Sminshall for (s = Sendlist; s->name; s++) { 40238689Sborman if (s->help) 40338689Sborman printf("%-15s %s\n", s->name, s->help); 40432144Sminshall } 40532144Sminshall question = 1; 40632144Sminshall break; 40732144Sminshall case SENDESCAPE: 40832144Sminshall NETADD(escape); 40932144Sminshall break; 41032144Sminshall default: 41132144Sminshall NET2ADD(IAC, what); 41232144Sminshall break; 41332144Sminshall } 41432144Sminshall } 41532144Sminshall } 41632144Sminshall return !question; 41732144Sminshall } 41832144Sminshall 41932144Sminshall /* 42032144Sminshall * The following are the routines and data structures referred 42132144Sminshall * to by the arguments to the "toggle" command. 42232144Sminshall */ 42332144Sminshall 42432144Sminshall static 42532144Sminshall lclchars() 42632144Sminshall { 42732144Sminshall donelclchars = 1; 42832144Sminshall return 1; 42932144Sminshall } 43032144Sminshall 43132144Sminshall static 43232144Sminshall togdebug() 43332144Sminshall { 43432144Sminshall #ifndef NOT43 43532144Sminshall if (net > 0 && 43632144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 43732144Sminshall perror("setsockopt (SO_DEBUG)"); 43832144Sminshall } 43932144Sminshall #else /* NOT43 */ 44032144Sminshall if (debug) { 44132144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 44232144Sminshall perror("setsockopt (SO_DEBUG)"); 44332144Sminshall } else 44432144Sminshall printf("Cannot turn off socket debugging\n"); 44532144Sminshall #endif /* NOT43 */ 44632144Sminshall return 1; 44732144Sminshall } 44832144Sminshall 44932144Sminshall 45032144Sminshall static int 45132144Sminshall togcrlf() 45232144Sminshall { 45332144Sminshall if (crlf) { 45432144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 45532144Sminshall } else { 45632144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 45732144Sminshall } 45832144Sminshall return 1; 45932144Sminshall } 46032144Sminshall 46138909Sborman int binmode; 46232144Sminshall 46332144Sminshall static int 46438689Sborman togbinary(val) 46538689Sborman int val; 46632144Sminshall { 46732144Sminshall donebinarytoggle = 1; 46832144Sminshall 46938909Sborman if (val >= 0) { 47038909Sborman binmode = val; 47138909Sborman } else { 47238909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 47338909Sborman my_want_state_is_do(TELOPT_BINARY)) { 47438909Sborman binmode = 1; 47538909Sborman } else if (my_want_state_is_wont(TELOPT_BINARY) && 47638909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 47738909Sborman binmode = 0; 47838909Sborman } 47938909Sborman val = binmode ? 0 : 1; 48038909Sborman } 48138909Sborman 48238909Sborman if (val == 1) { 48338909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 48438909Sborman my_want_state_is_do(TELOPT_BINARY)) { 48538689Sborman printf("Already operating in binary mode with remote host.\n"); 48638909Sborman } else { 48738909Sborman printf("Negotiating binary mode with remote host.\n"); 48838909Sborman tel_enter_binary(3); 48938689Sborman } 49038909Sborman } else { 49138909Sborman if (my_want_state_is_wont(TELOPT_BINARY) && 49238909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 49338689Sborman printf("Already in network ascii mode with remote host.\n"); 49438909Sborman } else { 49538909Sborman printf("Negotiating network ascii mode with remote host.\n"); 49638909Sborman tel_leave_binary(3); 49738689Sborman } 49832144Sminshall } 49932144Sminshall return 1; 50032144Sminshall } 50132144Sminshall 50238909Sborman static int 50338909Sborman togrbinary(val) 50438909Sborman int val; 50538909Sborman { 50638909Sborman donebinarytoggle = 1; 50732144Sminshall 50838909Sborman if (val == -1) 50938909Sborman val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 51032144Sminshall 51138909Sborman if (val == 1) { 51238909Sborman if (my_want_state_is_do(TELOPT_BINARY)) { 51338909Sborman printf("Already receiving in binary mode.\n"); 51438909Sborman } else { 51538909Sborman printf("Negotiating binary mode on input.\n"); 51638909Sborman tel_enter_binary(1); 51738909Sborman } 51838909Sborman } else { 51938909Sborman if (my_want_state_is_dont(TELOPT_BINARY)) { 52038909Sborman printf("Already receiving in network ascii mode.\n"); 52138909Sborman } else { 52238909Sborman printf("Negotiating network ascii mode on input.\n"); 52338909Sborman tel_leave_binary(1); 52438909Sborman } 52538909Sborman } 52638909Sborman return 1; 52738909Sborman } 52838909Sborman 52938909Sborman static int 53038909Sborman togxbinary(val) 53138909Sborman int val; 53238909Sborman { 53338909Sborman donebinarytoggle = 1; 53438909Sborman 53538909Sborman if (val == -1) 53638909Sborman val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 53738909Sborman 53838909Sborman if (val == 1) { 53938909Sborman if (my_want_state_is_will(TELOPT_BINARY)) { 54038909Sborman printf("Already transmitting in binary mode.\n"); 54138909Sborman } else { 54238909Sborman printf("Negotiating binary mode on output.\n"); 54338909Sborman tel_enter_binary(2); 54438909Sborman } 54538909Sborman } else { 54638909Sborman if (my_want_state_is_wont(TELOPT_BINARY)) { 54738909Sborman printf("Already transmitting in network ascii mode.\n"); 54838909Sborman } else { 54938909Sborman printf("Negotiating network ascii mode on output.\n"); 55038909Sborman tel_leave_binary(2); 55138909Sborman } 55238909Sborman } 55338909Sborman return 1; 55438909Sborman } 55538909Sborman 55638909Sborman 55732144Sminshall extern int togglehelp(); 55838689Sborman extern int slc_check(); 55932144Sminshall 56032144Sminshall struct togglelist { 56132144Sminshall char *name; /* name of toggle */ 56232144Sminshall char *help; /* help message */ 56332144Sminshall int (*handler)(); /* routine to do actual setting */ 56432144Sminshall int *variable; 56532144Sminshall char *actionexplanation; 56632144Sminshall }; 56732144Sminshall 56832144Sminshall static struct togglelist Togglelist[] = { 56932144Sminshall { "autoflush", 57038689Sborman "flushing of output when sending interrupt characters", 57132144Sminshall 0, 57238689Sborman &autoflush, 57338689Sborman "flush output when sending interrupt characters" }, 57432144Sminshall { "autosynch", 57538689Sborman "automatic sending of interrupt characters in urgent mode", 57632144Sminshall 0, 57738689Sborman &autosynch, 57838689Sborman "send interrupt characters in urgent mode" }, 57932144Sminshall { "binary", 58038689Sborman "sending and receiving of binary data", 58132144Sminshall togbinary, 58238689Sborman 0, 58338689Sborman 0 }, 58438909Sborman { "inbinary", 58538909Sborman "receiving of binary data", 58638909Sborman togrbinary, 58738909Sborman 0, 58838909Sborman 0 }, 58938909Sborman { "outbinary", 59038909Sborman "sending of binary data", 59138909Sborman togxbinary, 59238909Sborman 0, 59338909Sborman 0 }, 59432144Sminshall { "crlf", 59538689Sborman "sending carriage returns as telnet <CR><LF>", 59632144Sminshall togcrlf, 59738689Sborman &crlf, 59838689Sborman 0 }, 59932144Sminshall { "crmod", 60038689Sborman "mapping of received carriage returns", 60132144Sminshall 0, 60238689Sborman &crmod, 60338689Sborman "map carriage return on output" }, 60432144Sminshall { "localchars", 60538689Sborman "local recognition of certain control characters", 60632144Sminshall lclchars, 60738689Sborman &localchars, 60838689Sborman "recognize certain control characters" }, 60938689Sborman { " ", "", 0 }, /* empty line */ 61038208Sminshall #if defined(unix) && defined(TN3270) 61138920Sminshall { "apitrace", 61238920Sminshall "(debugging) toggle tracing of API transactions", 61338920Sminshall 0, 61438920Sminshall &apitrace, 61538920Sminshall "trace API transactions" }, 61638208Sminshall { "cursesdata", 61738208Sminshall "(debugging) toggle printing of hexadecimal curses data", 61838208Sminshall 0, 61938689Sborman &cursesdata, 62038689Sborman "print hexadecimal representation of curses data" }, 62138208Sminshall #endif /* defined(unix) && defined(TN3270) */ 62232144Sminshall { "debug", 62338689Sborman "debugging", 62432144Sminshall togdebug, 62538689Sborman &debug, 62638689Sborman "turn on socket level debugging" }, 62732144Sminshall { "netdata", 62838689Sborman "printing of hexadecimal network data (debugging)", 62932144Sminshall 0, 63038689Sborman &netdata, 63138689Sborman "print hexadecimal representation of network traffic" }, 63238689Sborman { "prettydump", 63338689Sborman "output of \"netdata\" to user readable format (debugging)", 63438689Sborman 0, 63538689Sborman &prettydump, 63638689Sborman "print user readable output for \"netdata\"" }, 63732144Sminshall { "options", 63838689Sborman "viewing of options processing (debugging)", 63932144Sminshall 0, 64038689Sborman &showoptions, 64138689Sborman "show option processing" }, 64238208Sminshall #if defined(unix) 64338208Sminshall { "termdata", 64438208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 64538208Sminshall 0, 64638689Sborman &termdata, 64738689Sborman "print hexadecimal representation of terminal traffic" }, 64838208Sminshall #endif /* defined(unix) */ 64932144Sminshall { "?", 65038689Sborman 0, 65138689Sborman togglehelp }, 65232144Sminshall { "help", 65338689Sborman 0, 65438689Sborman togglehelp }, 65532144Sminshall { 0 } 65632144Sminshall }; 65732144Sminshall 65832144Sminshall static 65932144Sminshall togglehelp() 66032144Sminshall { 66132144Sminshall struct togglelist *c; 66232144Sminshall 66332144Sminshall for (c = Togglelist; c->name; c++) { 66438689Sborman if (c->help) { 66538689Sborman if (*c->help) 66638689Sborman printf("%-15s toggle %s\n", c->name, c->help); 66738689Sborman else 66838689Sborman printf("\n"); 66932144Sminshall } 67032144Sminshall } 67138689Sborman printf("\n"); 67238689Sborman printf("%-15s %s\n", "?", "display help information"); 67332144Sminshall return 0; 67432144Sminshall } 67532144Sminshall 67638689Sborman static 67738689Sborman settogglehelp(set) 67838689Sborman int set; 67938689Sborman { 68038689Sborman struct togglelist *c; 68138689Sborman 68238689Sborman for (c = Togglelist; c->name; c++) { 68338689Sborman if (c->help) { 68438689Sborman if (*c->help) 68538689Sborman printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 68638689Sborman c->help); 68738689Sborman else 68838689Sborman printf("\n"); 68938689Sborman } 69038689Sborman } 69138689Sborman } 69238689Sborman 69332144Sminshall static char ** 69432144Sminshall getnexttoggle(name) 69532144Sminshall char *name; 69632144Sminshall { 69732144Sminshall struct togglelist *c = (struct togglelist *) name; 69832144Sminshall 69932144Sminshall return (char **) (c+1); 70032144Sminshall } 70132144Sminshall 70232144Sminshall static struct togglelist * 70332144Sminshall gettoggle(name) 70432144Sminshall char *name; 70532144Sminshall { 70632144Sminshall return (struct togglelist *) 70732144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 70832144Sminshall } 70932144Sminshall 71032144Sminshall static 71132144Sminshall toggle(argc, argv) 71232144Sminshall int argc; 71332144Sminshall char *argv[]; 71432144Sminshall { 71532144Sminshall int retval = 1; 71632144Sminshall char *name; 71732144Sminshall struct togglelist *c; 71832144Sminshall 71932144Sminshall if (argc < 2) { 72032144Sminshall fprintf(stderr, 72132144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 72232144Sminshall return 0; 72332144Sminshall } 72432144Sminshall argc--; 72532144Sminshall argv++; 72632144Sminshall while (argc--) { 72732144Sminshall name = *argv++; 72832144Sminshall c = gettoggle(name); 72932144Sminshall if (Ambiguous(c)) { 73032144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 73132144Sminshall name); 73232144Sminshall return 0; 73332144Sminshall } else if (c == 0) { 73432144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 73532144Sminshall name); 73632144Sminshall return 0; 73732144Sminshall } else { 73832144Sminshall if (c->variable) { 73932144Sminshall *c->variable = !*c->variable; /* invert it */ 74032144Sminshall if (c->actionexplanation) { 74132144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 74232144Sminshall c->actionexplanation); 74332144Sminshall } 74432144Sminshall } 74532144Sminshall if (c->handler) { 74638689Sborman retval &= (*c->handler)(-1); 74732144Sminshall } 74832144Sminshall } 74932144Sminshall } 75032144Sminshall return retval; 75132144Sminshall } 75232144Sminshall 75332144Sminshall /* 75432144Sminshall * The following perform the "set" command. 75532144Sminshall */ 75632144Sminshall 75738689Sborman #ifdef USE_TERMIO 75838689Sborman struct termio new_tc = { 0 }; 75938689Sborman #endif 76038689Sborman 76132144Sminshall struct setlist { 76232144Sminshall char *name; /* name */ 76332144Sminshall char *help; /* help information */ 76438689Sborman void (*handler)(); 76540245Sborman cc_t *charp; /* where it is located at */ 76632144Sminshall }; 76732144Sminshall 76832144Sminshall static struct setlist Setlist[] = { 76938689Sborman { "echo", "character to toggle local echoing on/off", 0, &echoc }, 77038689Sborman { "escape", "character to escape back to telnet command mode", 0, &escape }, 77140245Sborman { "tracefile", "file to write trace intormation to", SetNetTrace, (cc_t *)NetTraceFile}, 77232144Sminshall { " ", "" }, 77338689Sborman { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 77438689Sborman { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp }, 77538689Sborman { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 77638689Sborman { "quit", "character to cause an Abort process", 0, termQuitCharp }, 77738689Sborman { "eof", "character to cause an EOF ", 0, termEofCharp }, 77838689Sborman { " ", "" }, 77938689Sborman { " ", "The following are for local editing in linemode", 0, 0 }, 78038689Sborman { "erase", "character to use to erase a character", 0, termEraseCharp }, 78138689Sborman { "kill", "character to use to erase a line", 0, termKillCharp }, 78238689Sborman { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 78338689Sborman { "susp", "character to cuase a Suspend Process", 0, termSuspCharp }, 78438689Sborman { "reprint", "character to use for line reprint", 0, termRprntCharp }, 78538689Sborman { "worderase", "character to use to erase a word", 0, termWerasCharp }, 78638689Sborman { "start", "character to use for XON", 0, termStartCharp }, 78738689Sborman { "stop", "character to sue for XOFF", 0, termStopCharp }, 78832144Sminshall { 0 } 78932144Sminshall }; 79032144Sminshall 79138689Sborman #ifdef CRAY 79238689Sborman /* Work around compiler bug */ 79338689Sborman _setlist_init() 79438689Sborman { 79539529Sborman Setlist[5].charp = &termFlushChar; 79638689Sborman Setlist[6].charp = &termIntChar; 79738689Sborman Setlist[7].charp = &termQuitChar; 79838689Sborman Setlist[8].charp = &termEofChar; 79938689Sborman Setlist[11].charp = &termEraseChar; 80038689Sborman Setlist[12].charp = &termKillChar; 80139529Sborman Setlist[13].charp = &termLiteralNextChar; 80239529Sborman Setlist[14].charp = &termSuspChar; 80339529Sborman Setlist[15].charp = &termRprntChar; 80439529Sborman Setlist[16].charp = &termWerasChar; 80539529Sborman Setlist[17].charp = &termStartChar; 80639529Sborman Setlist[18].charp = &termStopChar; 80738689Sborman } 80838810Sborman #endif /* CRAY */ 80938689Sborman 81032144Sminshall static char ** 81132144Sminshall getnextset(name) 81232144Sminshall char *name; 81332144Sminshall { 81432144Sminshall struct setlist *c = (struct setlist *)name; 81532144Sminshall 81632144Sminshall return (char **) (c+1); 81732144Sminshall } 81832144Sminshall 81932144Sminshall static struct setlist * 82032144Sminshall getset(name) 82132144Sminshall char *name; 82232144Sminshall { 82332144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 82432144Sminshall } 82532144Sminshall 82632144Sminshall static 82732144Sminshall setcmd(argc, argv) 82832144Sminshall int argc; 82932144Sminshall char *argv[]; 83032144Sminshall { 83132144Sminshall int value; 83232144Sminshall struct setlist *ct; 83338689Sborman struct togglelist *c; 83432144Sminshall 83538689Sborman if (argc < 2 || argc > 3) { 83638689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 83732144Sminshall return 0; 83832144Sminshall } 83938689Sborman if ((argc == 2) && 84038689Sborman ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 84138689Sborman for (ct = Setlist; ct->name; ct++) 84238689Sborman printf("%-15s %s\n", ct->name, ct->help); 84338689Sborman printf("\n"); 84438689Sborman settogglehelp(1); 84538689Sborman printf("%-15s %s\n", "?", "display help information"); 84638689Sborman return 0; 84738689Sborman } 84832144Sminshall 84932144Sminshall ct = getset(argv[1]); 85032144Sminshall if (ct == 0) { 85138689Sborman c = gettoggle(argv[1]); 85238689Sborman if (c == 0) { 85338689Sborman fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 85432144Sminshall argv[1]); 85538689Sborman return 0; 85638689Sborman } else if (Ambiguous(c)) { 85738689Sborman fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 85838689Sborman argv[1]); 85938689Sborman return 0; 86038689Sborman } 86138689Sborman if (c->variable) { 86238689Sborman if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 86338689Sborman *c->variable = 1; 86438689Sborman else if (strcmp("off", argv[2]) == 0) 86538689Sborman *c->variable = 0; 86638689Sborman else { 86738689Sborman printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 86838689Sborman return 0; 86938689Sborman } 87038689Sborman if (c->actionexplanation) { 87138689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 87238689Sborman c->actionexplanation); 87338689Sborman } 87438689Sborman } 87538689Sborman if (c->handler) 87638689Sborman (*c->handler)(1); 87738689Sborman } else if (argc != 3) { 87838689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 87932144Sminshall return 0; 88032144Sminshall } else if (Ambiguous(ct)) { 88132144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 88232144Sminshall argv[1]); 88332144Sminshall return 0; 88438689Sborman } else if (ct->handler) { 88538689Sborman (*ct->handler)(argv[2]); 88640245Sborman printf("%s set to \"%s\".\n", ct->name, (unsigned char *)ct->charp); 88732144Sminshall } else { 88832144Sminshall if (strcmp("off", argv[2])) { 88932144Sminshall value = special(argv[2]); 89032144Sminshall } else { 89132144Sminshall value = -1; 89232144Sminshall } 89340245Sborman *(ct->charp) = (cc_t)value; 89432144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 89532144Sminshall } 89638689Sborman slc_check(); 89732144Sminshall return 1; 89832144Sminshall } 89938689Sborman 90038689Sborman static 90138689Sborman unsetcmd(argc, argv) 90238689Sborman int argc; 90338689Sborman char *argv[]; 90438689Sborman { 90538689Sborman int value; 90638689Sborman struct setlist *ct; 90738689Sborman struct togglelist *c; 90838689Sborman register char *name; 90938689Sborman 91038689Sborman if (argc < 2) { 91138689Sborman fprintf(stderr, 91238689Sborman "Need an argument to 'unset' command. 'unset ?' for help.\n"); 91338689Sborman return 0; 91438689Sborman } 91538689Sborman if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) { 91638689Sborman for (ct = Setlist; ct->name; ct++) 91738689Sborman printf("%-15s %s\n", ct->name, ct->help); 91838689Sborman printf("\n"); 91938689Sborman settogglehelp(0); 92038689Sborman printf("%-15s %s\n", "?", "display help information"); 92138689Sborman return 0; 92238689Sborman } 92338689Sborman 92438689Sborman argc--; 92538689Sborman argv++; 92638689Sborman while (argc--) { 92738689Sborman name = *argv++; 92838689Sborman ct = getset(name); 92938689Sborman if (ct == 0) { 93038689Sborman c = gettoggle(name); 93138689Sborman if (c == 0) { 93238689Sborman fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 93338689Sborman name); 93438689Sborman return 0; 93538689Sborman } else if (Ambiguous(c)) { 93638689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 93738689Sborman name); 93838689Sborman return 0; 93938689Sborman } 94038689Sborman if (c->variable) { 94138689Sborman *c->variable = 0; 94238689Sborman if (c->actionexplanation) { 94338689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 94438689Sborman c->actionexplanation); 94538689Sborman } 94638689Sborman } 94738689Sborman if (c->handler) 94838689Sborman (*c->handler)(0); 94938689Sborman } else if (Ambiguous(ct)) { 95038689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 95138689Sborman name); 95238689Sborman return 0; 95338689Sborman } else if (ct->handler) { 95438689Sborman (*ct->handler)(0); 95538689Sborman printf("%s reset to \"%s\".\n", ct->name, ct->charp); 95638689Sborman } else { 95738689Sborman value = -1; 95838689Sborman *(ct->charp) = -1; 95938689Sborman printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 96038689Sborman } 96138689Sborman } 96238689Sborman return 1; 96338689Sborman } 96432144Sminshall 96532144Sminshall /* 96632144Sminshall * The following are the data structures and routines for the 96732144Sminshall * 'mode' command. 96832144Sminshall */ 96938689Sborman #ifdef KLUDGELINEMODE 97038689Sborman extern int kludgelinemode; 97138689Sborman #endif 97232144Sminshall 97332144Sminshall static 97432144Sminshall dolinemode() 97532144Sminshall { 97638689Sborman #ifdef KLUDGELINEMODE 97738689Sborman if (kludgelinemode) 97838689Sborman send_dont(TELOPT_SGA, 1); 97938689Sborman #endif 98038689Sborman send_will(TELOPT_LINEMODE, 1); 98138689Sborman send_dont(TELOPT_ECHO, 1); 98232144Sminshall return 1; 98332144Sminshall } 98432144Sminshall 98532144Sminshall static 98632144Sminshall docharmode() 98732144Sminshall { 98838689Sborman #ifdef KLUDGELINEMODE 98938689Sborman if (kludgelinemode) 99038689Sborman send_do(TELOPT_SGA, 1); 99138689Sborman else 99238689Sborman #endif 99338689Sborman send_wont(TELOPT_LINEMODE, 1); 99438689Sborman send_do(TELOPT_ECHO, 1); 99538689Sborman return 1; 99638689Sborman } 99738689Sborman 99838689Sborman setmode(bit) 99938689Sborman { 100038689Sborman return dolmmode(bit, 1); 100138689Sborman } 100238689Sborman 100338689Sborman clearmode(bit) 100438689Sborman { 100538689Sborman return dolmmode(bit, 0); 100638689Sborman } 100738689Sborman 100838689Sborman dolmmode(bit, on) 100938689Sborman int bit, on; 101038689Sborman { 101138689Sborman char c; 101238689Sborman extern int linemode; 101338689Sborman 101438689Sborman if (my_want_state_is_wont(TELOPT_LINEMODE)) { 101538689Sborman printf("?Need to have LINEMODE option enabled first.\n"); 101638689Sborman printf("'mode ?' for help.\n"); 101738689Sborman return 0; 101832144Sminshall } 101938689Sborman 102038689Sborman if (on) 102138689Sborman c = (linemode | bit); 102238689Sborman else 102338689Sborman c = (linemode & ~bit); 102438689Sborman lm_mode(&c, 1, 1); 102532144Sminshall return 1; 102632144Sminshall } 102732144Sminshall 102838689Sborman struct modelist { 102938689Sborman char *name; /* command name */ 103038689Sborman char *help; /* help string */ 103138689Sborman int (*handler)(); /* routine which executes command */ 103238689Sborman int needconnect; /* Do we need to be connected to execute? */ 103338689Sborman int arg1; 103438689Sborman }; 103538689Sborman 103638689Sborman extern int modehelp(); 103738689Sborman 103838689Sborman static struct modelist ModeList[] = { 103938689Sborman { "character", "Disable LINEMODE option", docharmode, 1 }, 104039529Sborman #ifdef KLUDGELINEMODE 104139529Sborman { "", "(or disable obsolete line-by-line mode)", 0 }, 104238689Sborman #endif 104338689Sborman { "line", "Enable LINEMODE option", dolinemode, 1 }, 104439529Sborman #ifdef KLUDGELINEMODE 104539529Sborman { "", "(or enable obsolete line-by-line mode)", 0 }, 104638689Sborman #endif 104738689Sborman { "", "", 0 }, 104838689Sborman { "", "These require the LINEMODE option to be enabled", 0 }, 104938689Sborman { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 105038689Sborman { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 105138689Sborman { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 105238689Sborman { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 105338689Sborman { "+edit", 0, setmode, 1, MODE_EDIT }, 105438689Sborman { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 105538689Sborman { "help", 0, modehelp, 0 }, 105638689Sborman { "?", "Print help information", modehelp, 0 }, 105732144Sminshall { 0 }, 105832144Sminshall }; 105932144Sminshall 106032144Sminshall static char ** 106132144Sminshall getnextmode(name) 106232144Sminshall char *name; 106332144Sminshall { 106438689Sborman return (char **) (((struct modelist *)name)+1); 106532144Sminshall } 106632144Sminshall 106738689Sborman static struct modelist * 106832144Sminshall getmodecmd(name) 106932144Sminshall char *name; 107032144Sminshall { 107138689Sborman return (struct modelist *) genget(name, (char **) ModeList, getnextmode); 107232144Sminshall } 107332144Sminshall 107438689Sborman modehelp() 107538689Sborman { 107638689Sborman struct modelist *mt; 107738689Sborman 107838689Sborman printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 107938689Sborman for (mt = ModeList; mt->name; mt++) { 108038689Sborman if (mt->help) { 108138689Sborman if (*mt->help) 108238689Sborman printf("%-15s %s\n", mt->name, mt->help); 108338689Sborman else 108438689Sborman printf("\n"); 108538689Sborman } 108638689Sborman } 108738689Sborman return 0; 108838689Sborman } 108938689Sborman 109032144Sminshall static 109132144Sminshall modecmd(argc, argv) 109232144Sminshall int argc; 109332144Sminshall char *argv[]; 109432144Sminshall { 109538689Sborman struct modelist *mt; 109632144Sminshall 109738689Sborman if (argc != 2) { 109838689Sborman printf("'mode' command requires an argument\n"); 109938689Sborman printf("'mode ?' for help.\n"); 110038689Sborman } else if ((mt = getmodecmd(argv[1])) == 0) { 110132144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 110232144Sminshall } else if (Ambiguous(mt)) { 110332144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 110438689Sborman } else if (mt->needconnect && !connected) { 110538689Sborman printf("?Need to be connected first.\n"); 110638689Sborman printf("'mode ?' for help.\n"); 110738689Sborman } else if (mt->handler) { 110838689Sborman return (*mt->handler)(mt->arg1); 110932144Sminshall } 111038689Sborman return 0; 111132144Sminshall } 111232144Sminshall 111332144Sminshall /* 111432144Sminshall * The following data structures and routines implement the 111532144Sminshall * "display" command. 111632144Sminshall */ 111732144Sminshall 111832144Sminshall static 111932144Sminshall display(argc, argv) 112032144Sminshall int argc; 112132144Sminshall char *argv[]; 112232144Sminshall { 112332144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 112432144Sminshall if (*tl->variable) { \ 112532144Sminshall printf("will"); \ 112632144Sminshall } else { \ 112732144Sminshall printf("won't"); \ 112832144Sminshall } \ 112932144Sminshall printf(" %s.\n", tl->actionexplanation); \ 113032144Sminshall } 113132144Sminshall 113232144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 113338689Sborman if (sl->handler == 0) \ 113438689Sborman printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 113538689Sborman else \ 113638689Sborman printf("%-15s \"%s\"\n", sl->name, sl->charp); \ 113732144Sminshall } 113832144Sminshall 113932144Sminshall struct togglelist *tl; 114032144Sminshall struct setlist *sl; 114132144Sminshall 114232144Sminshall if (argc == 1) { 114332144Sminshall for (tl = Togglelist; tl->name; tl++) { 114432144Sminshall dotog(tl); 114532144Sminshall } 114632144Sminshall printf("\n"); 114732144Sminshall for (sl = Setlist; sl->name; sl++) { 114832144Sminshall doset(sl); 114932144Sminshall } 115032144Sminshall } else { 115132144Sminshall int i; 115232144Sminshall 115332144Sminshall for (i = 1; i < argc; i++) { 115432144Sminshall sl = getset(argv[i]); 115532144Sminshall tl = gettoggle(argv[i]); 115632144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 115732144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 115832144Sminshall return 0; 115932144Sminshall } else if (!sl && !tl) { 116032144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 116132144Sminshall return 0; 116232144Sminshall } else { 116332144Sminshall if (tl) { 116432144Sminshall dotog(tl); 116532144Sminshall } 116632144Sminshall if (sl) { 116732144Sminshall doset(sl); 116832144Sminshall } 116932144Sminshall } 117032144Sminshall } 117132144Sminshall } 117238689Sborman /*@*/optionstatus(); 117332144Sminshall return 1; 117432144Sminshall #undef doset 117532144Sminshall #undef dotog 117632144Sminshall } 117732144Sminshall 117832144Sminshall /* 117932144Sminshall * The following are the data structures, and many of the routines, 118032144Sminshall * relating to command processing. 118132144Sminshall */ 118232144Sminshall 118332144Sminshall /* 118432144Sminshall * Set the escape character. 118532144Sminshall */ 118632144Sminshall static 118732144Sminshall setescape(argc, argv) 118832144Sminshall int argc; 118932144Sminshall char *argv[]; 119032144Sminshall { 119132144Sminshall register char *arg; 119232144Sminshall char buf[50]; 119332144Sminshall 119432144Sminshall printf( 119532144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 119632144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 119732144Sminshall if (argc > 2) 119832144Sminshall arg = argv[1]; 119932144Sminshall else { 120032144Sminshall printf("new escape character: "); 120134849Sminshall (void) gets(buf); 120232144Sminshall arg = buf; 120332144Sminshall } 120432144Sminshall if (arg[0] != '\0') 120532144Sminshall escape = arg[0]; 120632144Sminshall if (!In3270) { 120732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 120832144Sminshall } 120934849Sminshall (void) fflush(stdout); 121032144Sminshall return 1; 121132144Sminshall } 121232144Sminshall 121332144Sminshall /*VARARGS*/ 121432144Sminshall static 121532144Sminshall togcrmod() 121632144Sminshall { 121732144Sminshall crmod = !crmod; 121832144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 121932144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 122034849Sminshall (void) fflush(stdout); 122132144Sminshall return 1; 122232144Sminshall } 122332144Sminshall 122432144Sminshall /*VARARGS*/ 122532144Sminshall suspend() 122632144Sminshall { 122738689Sborman #ifdef SIGTSTP 122837219Sminshall setcommandmode(); 122937219Sminshall { 123037219Sminshall long oldrows, oldcols, newrows, newcols; 123137219Sminshall 123237219Sminshall TerminalWindowSize(&oldrows, &oldcols); 123334849Sminshall (void) kill(0, SIGTSTP); 123437219Sminshall TerminalWindowSize(&newrows, &newcols); 123537219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 123637219Sminshall if (connected) { 123737219Sminshall sendnaws(); 123837219Sminshall } 123937219Sminshall } 124037219Sminshall } 124137219Sminshall /* reget parameters in case they were changed */ 124237219Sminshall TerminalSaveState(); 124338689Sborman setconnmode(0); 124438689Sborman #else 124538689Sborman printf("Suspend is not supported. Try the '!' command instead\n"); 124638689Sborman #endif 124737219Sminshall return 1; 124832144Sminshall } 124932144Sminshall 125038689Sborman #if !defined(TN3270) 125138689Sborman shell(argc, argv) 125238689Sborman int argc; 125338689Sborman char *argv[]; 125438689Sborman { 125538689Sborman extern char *rindex(); 125638689Sborman char cmdbuf[256]; 125738689Sborman 125838689Sborman setcommandmode(); 125938689Sborman switch(vfork()) { 126038689Sborman case -1: 126138689Sborman perror("Fork failed\n"); 126238689Sborman break; 126338689Sborman 126438689Sborman case 0: 126538689Sborman { 126638689Sborman /* 126738689Sborman * Fire up the shell in the child. 126838689Sborman */ 126938689Sborman register char *shell, *shellname; 127038689Sborman 127138689Sborman shell = getenv("SHELL"); 127238689Sborman if (shell == NULL) 127338689Sborman shell = "/bin/sh"; 127438689Sborman if ((shellname = rindex(shell, '/')) == 0) 127538689Sborman shellname = shell; 127638689Sborman else 127738689Sborman shellname++; 127838689Sborman if (argc > 1) 127938689Sborman execl(shell, shellname, "-c", &saveline[1], 0); 128038689Sborman else 128138689Sborman execl(shell, shellname, 0); 128238689Sborman perror("Execl"); 128338689Sborman _exit(1); 128438689Sborman } 128538689Sborman default: 128638689Sborman wait((int *)0); /* Wait for the shell to complete */ 128738689Sborman } 128838689Sborman } 128938689Sborman #endif /* !defined(TN3270) */ 129038689Sborman 129132144Sminshall /*VARARGS*/ 129232144Sminshall static 129332144Sminshall bye(argc, argv) 129432144Sminshall int argc; /* Number of arguments */ 129532144Sminshall char *argv[]; /* arguments */ 129632144Sminshall { 129732144Sminshall if (connected) { 129834849Sminshall (void) shutdown(net, 2); 129932144Sminshall printf("Connection closed.\n"); 130034849Sminshall (void) NetClose(net); 130132144Sminshall connected = 0; 130232144Sminshall /* reset options */ 130332144Sminshall tninit(); 130432144Sminshall #if defined(TN3270) 130532144Sminshall SetIn3270(); /* Get out of 3270 mode */ 130632144Sminshall #endif /* defined(TN3270) */ 130732144Sminshall } 130832144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 130932144Sminshall longjmp(toplevel, 1); 131032144Sminshall /* NOTREACHED */ 131132144Sminshall } 131232144Sminshall return 1; /* Keep lint, etc., happy */ 131332144Sminshall } 131432144Sminshall 131532144Sminshall /*VARARGS*/ 131632144Sminshall quit() 131732144Sminshall { 131832144Sminshall (void) call(bye, "bye", "fromquit", 0); 131932144Sminshall Exit(0); 132032144Sminshall return 1; /* just to keep lint happy */ 132132144Sminshall } 132238689Sborman 132338689Sborman /* 132438689Sborman * The SLC command. 132538689Sborman */ 132632144Sminshall 132738689Sborman struct slclist { 132838689Sborman char *name; 132938689Sborman char *help; 133038689Sborman int (*handler)(); 133138689Sborman int arg; 133238689Sborman }; 133338689Sborman 133438689Sborman extern int slc_help(); 133538689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate(); 133638689Sborman 133738689Sborman struct slclist SlcList[] = { 133838689Sborman { "export", "Use local special character definitions", 133938689Sborman slc_mode_export, 0 }, 134038689Sborman { "import", "Use remote special character definitions", 134138689Sborman slc_mode_import, 1 }, 134238689Sborman { "check", "Verify remote special character definitions", 134338689Sborman slc_mode_import, 0 }, 134438689Sborman { "help", 0, slc_help, 0 }, 134538689Sborman { "?", "Print help information", slc_help, 0 }, 134638689Sborman { 0 }, 134738689Sborman }; 134838689Sborman 134938689Sborman static 135038689Sborman slc_help() 135138689Sborman { 135238689Sborman struct slclist *c; 135338689Sborman 135438689Sborman for (c = SlcList; c->name; c++) { 135538689Sborman if (c->help) { 135638689Sborman if (*c->help) 135738689Sborman printf("%-15s %s\n", c->name, c->help); 135838689Sborman else 135938689Sborman printf("\n"); 136038689Sborman } 136138689Sborman } 136238689Sborman } 136338689Sborman 136438689Sborman static char ** 136538689Sborman getnextslc(name) 136638689Sborman char *name; 136738689Sborman { 136838689Sborman return (char **)(((struct slclist *)name)+1); 136938689Sborman } 137038689Sborman 137138689Sborman static struct slclist * 137238689Sborman getslc(name) 137338689Sborman char *name; 137438689Sborman { 137538689Sborman return (struct slclist *)genget(name, (char **) SlcList, getnextslc); 137638689Sborman } 137738689Sborman 137838689Sborman static 137938689Sborman slccmd(argc, argv) 138038689Sborman int argc; 138138689Sborman char *argv[]; 138238689Sborman { 138338689Sborman struct slclist *c; 138438689Sborman 138538689Sborman if (argc != 2) { 138638689Sborman fprintf(stderr, 138738689Sborman "Need an argument to 'slc' command. 'slc ?' for help.\n"); 138838689Sborman return 0; 138938689Sborman } 139038689Sborman c = getslc(argv[1]); 139138689Sborman if (c == 0) { 139238689Sborman fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 139338689Sborman argv[1]); 139438689Sborman return 0; 139538689Sborman } 139638689Sborman if (Ambiguous(c)) { 139738689Sborman fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 139838689Sborman argv[1]); 139938689Sborman return 0; 140038689Sborman } 140138689Sborman (*c->handler)(c->arg); 140238689Sborman slcstate(); 140338689Sborman return 1; 140438689Sborman } 140538689Sborman 140636274Sminshall #if defined(unix) 140732144Sminshall /* 140836274Sminshall * Some information about our file descriptors. 140936274Sminshall */ 141036274Sminshall 141136274Sminshall char * 141236274Sminshall decodeflags(mask) 141336274Sminshall int mask; 141436274Sminshall { 141536274Sminshall static char buffer[100]; 141636274Sminshall #define do(m,s) \ 141736274Sminshall if (mask&(m)) { \ 141836274Sminshall strcat(buffer, (s)); \ 141936274Sminshall } 142036274Sminshall 142136274Sminshall buffer[0] = 0; /* Terminate it */ 142236274Sminshall 142336274Sminshall #ifdef FREAD 142436274Sminshall do(FREAD, " FREAD"); 142536274Sminshall #endif 142636274Sminshall #ifdef FWRITE 142736274Sminshall do(FWRITE, " FWRITE"); 142836274Sminshall #endif 142936274Sminshall #ifdef F_DUPFP 143036274Sminshall do(F_DUPFD, " F_DUPFD"); 143136274Sminshall #endif 143236274Sminshall #ifdef FNDELAY 143336274Sminshall do(FNDELAY, " FNDELAY"); 143436274Sminshall #endif 143536274Sminshall #ifdef FAPPEND 143636274Sminshall do(FAPPEND, " FAPPEND"); 143736274Sminshall #endif 143836274Sminshall #ifdef FMARK 143936274Sminshall do(FMARK, " FMARK"); 144036274Sminshall #endif 144136274Sminshall #ifdef FDEFER 144236274Sminshall do(FDEFER, " FDEFER"); 144336274Sminshall #endif 144436274Sminshall #ifdef FASYNC 144536274Sminshall do(FASYNC, " FASYNC"); 144636274Sminshall #endif 144736274Sminshall #ifdef FSHLOCK 144836274Sminshall do(FSHLOCK, " FSHLOCK"); 144936274Sminshall #endif 145036274Sminshall #ifdef FEXLOCK 145136274Sminshall do(FEXLOCK, " FEXLOCK"); 145236274Sminshall #endif 145336274Sminshall #ifdef FCREAT 145436274Sminshall do(FCREAT, " FCREAT"); 145536274Sminshall #endif 145636274Sminshall #ifdef FTRUNC 145736274Sminshall do(FTRUNC, " FTRUNC"); 145836274Sminshall #endif 145936274Sminshall #ifdef FEXCL 146036274Sminshall do(FEXCL, " FEXCL"); 146136274Sminshall #endif 146236274Sminshall 146336274Sminshall return buffer; 146436274Sminshall } 146536274Sminshall #undef do 146636274Sminshall 146736274Sminshall static void 146836274Sminshall filestuff(fd) 146936274Sminshall int fd; 147036274Sminshall { 147136274Sminshall int res; 147236274Sminshall 147338689Sborman #ifdef F_GETOWN 147438689Sborman setconnmode(0); 147536274Sminshall res = fcntl(fd, F_GETOWN, 0); 147636274Sminshall setcommandmode(); 147736274Sminshall 147836274Sminshall if (res == -1) { 147936274Sminshall perror("fcntl"); 148036274Sminshall return; 148136274Sminshall } 148236274Sminshall printf("\tOwner is %d.\n", res); 148338689Sborman #endif 148436274Sminshall 148538689Sborman setconnmode(0); 148636274Sminshall res = fcntl(fd, F_GETFL, 0); 148736274Sminshall setcommandmode(); 148836274Sminshall 148936274Sminshall if (res == -1) { 149036274Sminshall perror("fcntl"); 149136274Sminshall return; 149236274Sminshall } 149336274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 149436274Sminshall } 149536274Sminshall 149636274Sminshall 149736274Sminshall #endif /* defined(unix) */ 149836274Sminshall 149936274Sminshall /* 150032144Sminshall * Print status about the connection. 150132144Sminshall */ 150234849Sminshall /*ARGSUSED*/ 150332144Sminshall static 150432144Sminshall status(argc, argv) 150532144Sminshall int argc; 150632144Sminshall char *argv[]; 150732144Sminshall { 150832144Sminshall if (connected) { 150932144Sminshall printf("Connected to %s.\n", hostname); 151036242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 151138689Sborman int mode = getconnmode(); 151238689Sborman 151338689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 151438689Sborman printf("Operating with LINEMODE option\n"); 151538689Sborman printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 151638689Sborman printf("%s catching of signals\n", 151738689Sborman (mode&MODE_TRAPSIG) ? "Local" : "No"); 151838689Sborman slcstate(); 151938689Sborman #ifdef KLUDGELINEMODE 152039529Sborman } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 152138689Sborman printf("Operating in obsolete linemode\n"); 152238689Sborman #endif 152338689Sborman } else { 152438689Sborman printf("Operating in single character mode\n"); 152538689Sborman if (localchars) 152638689Sborman printf("Catching signals locally\n"); 152732144Sminshall } 152838689Sborman printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 152938689Sborman if (my_want_state_is_will(TELOPT_LFLOW)) 153038689Sborman printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 153132144Sminshall } 153232144Sminshall } else { 153332144Sminshall printf("No connection.\n"); 153432144Sminshall } 153532144Sminshall # if !defined(TN3270) 153632144Sminshall printf("Escape character is '%s'.\n", control(escape)); 153734849Sminshall (void) fflush(stdout); 153832144Sminshall # else /* !defined(TN3270) */ 153932144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 154032144Sminshall printf("Escape character is '%s'.\n", control(escape)); 154132144Sminshall } 154232144Sminshall # if defined(unix) 154336242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 154436242Sminshall printf("SIGIO received %d time%s.\n", 154536242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 154636274Sminshall if (In3270) { 154736274Sminshall printf("Process ID %d, process group %d.\n", 154836274Sminshall getpid(), getpgrp(getpid())); 154936274Sminshall printf("Terminal input:\n"); 155036274Sminshall filestuff(tin); 155136274Sminshall printf("Terminal output:\n"); 155236274Sminshall filestuff(tout); 155336274Sminshall printf("Network socket:\n"); 155436274Sminshall filestuff(net); 155536274Sminshall } 155636242Sminshall } 155732144Sminshall if (In3270 && transcom) { 155832144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 155932144Sminshall } 156032144Sminshall # endif /* defined(unix) */ 156134849Sminshall (void) fflush(stdout); 156232144Sminshall if (In3270) { 156332144Sminshall return 0; 156432144Sminshall } 156532144Sminshall # endif /* defined(TN3270) */ 156632144Sminshall return 1; 156732144Sminshall } 156832144Sminshall 156932144Sminshall 1570*40248Sborman #if defined(NEED_GETTOS) 157140245Sborman struct tosent { 157240245Sborman char *t_name; /* name */ 157340245Sborman char **t_aliases; /* alias list */ 157440245Sborman char *t_proto; /* protocol */ 157540245Sborman int t_tos; /* Type Of Service bits */ 157640245Sborman }; 157732144Sminshall 157840245Sborman struct tosent * 157940245Sborman gettosbyname(name, proto) 158040245Sborman char *name, *proto; 158140245Sborman { 158240245Sborman static struct tosent te; 158340245Sborman static char *aliasp = 0; 158440245Sborman 158540245Sborman te.t_name = name; 158640245Sborman te.t_aliases = &aliasp; 158740245Sborman te.t_proto = proto; 158840245Sborman te.t_tos = 020; /* Low Delay bit */ 158940245Sborman return(&te); 159040245Sborman } 159140245Sborman #endif 159240245Sborman 159332144Sminshall int 159432144Sminshall tn(argc, argv) 159532144Sminshall int argc; 159632144Sminshall char *argv[]; 159732144Sminshall { 159832144Sminshall register struct hostent *host = 0; 159932144Sminshall struct sockaddr_in sin; 160032144Sminshall struct servent *sp = 0; 160132144Sminshall static char hnamebuf[32]; 160238689Sborman unsigned long temp, inet_addr(); 160337219Sminshall extern char *inet_ntoa(); 160438689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 160538689Sborman char *srp = 0, *strrchr(); 160638689Sborman unsigned long sourceroute(), srlen; 160738689Sborman #endif 1608*40248Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS) 160940245Sborman struct tosent *tp; 1610*40248Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */ 161132144Sminshall 161232144Sminshall 161332144Sminshall if (connected) { 161432144Sminshall printf("?Already connected to %s\n", hostname); 161532144Sminshall return 0; 161632144Sminshall } 161732144Sminshall if (argc < 2) { 161832144Sminshall (void) strcpy(line, "Connect "); 161932144Sminshall printf("(to) "); 162034849Sminshall (void) gets(&line[strlen(line)]); 162132144Sminshall makeargv(); 162232144Sminshall argc = margc; 162332144Sminshall argv = margv; 162432144Sminshall } 162532144Sminshall if ((argc < 2) || (argc > 3)) { 162632144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 162732144Sminshall return 0; 162832144Sminshall } 162938689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 163038689Sborman if (argv[1][0] == '@' || argv[1][0] == '!') { 163138689Sborman if ((hostname = strrchr(argv[1], ':')) == NULL) 163238689Sborman hostname = strrchr(argv[1], '@'); 163338689Sborman hostname++; 163438689Sborman srp = 0; 163538689Sborman temp = sourceroute(argv[1], &srp, &srlen); 163638689Sborman if (temp == 0) { 163738689Sborman herror(srp); 163838689Sborman return 0; 163938689Sborman } else if (temp == -1) { 164038689Sborman printf("Bad source route option: %s\n", argv[1]); 164138689Sborman return 0; 164238689Sborman } else { 164338689Sborman sin.sin_addr.s_addr = temp; 164438689Sborman sin.sin_family = AF_INET; 164538689Sborman } 164632144Sminshall } else { 164738689Sborman #endif 164838689Sborman temp = inet_addr(argv[1]); 164938689Sborman if (temp != (unsigned long) -1) { 165038689Sborman sin.sin_addr.s_addr = temp; 165138689Sborman sin.sin_family = AF_INET; 165238689Sborman (void) strcpy(hnamebuf, argv[1]); 165338689Sborman hostname = hnamebuf; 165438689Sborman } else { 165538689Sborman host = gethostbyname(argv[1]); 165638689Sborman if (host) { 165738689Sborman sin.sin_family = host->h_addrtype; 165832144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 165938689Sborman memcpy((caddr_t)&sin.sin_addr, 166032144Sminshall host->h_addr_list[0], host->h_length); 166132144Sminshall #else /* defined(h_addr) */ 166238689Sborman memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 166332144Sminshall #endif /* defined(h_addr) */ 166438689Sborman hostname = host->h_name; 166538689Sborman } else { 166638689Sborman herror(argv[1]); 166738689Sborman return 0; 166838689Sborman } 166932144Sminshall } 167038689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 167132144Sminshall } 167238689Sborman #endif 167332144Sminshall if (argc == 3) { 167438689Sborman int tmp; 167538689Sborman 167638689Sborman if (*argv[2] == '-') { 167738689Sborman argv[2]++; 167838689Sborman telnetport = 1; 167938689Sborman } else 168038689Sborman telnetport = 0; 168132144Sminshall sin.sin_port = atoi(argv[2]); 168232144Sminshall if (sin.sin_port == 0) { 168332144Sminshall sp = getservbyname(argv[2], "tcp"); 168432144Sminshall if (sp) 168532144Sminshall sin.sin_port = sp->s_port; 168632144Sminshall else { 168732144Sminshall printf("%s: bad port number\n", argv[2]); 168832144Sminshall return 0; 168932144Sminshall } 169032144Sminshall } else { 169134849Sminshall #if !defined(htons) 169234849Sminshall u_short htons(); 169334849Sminshall #endif /* !defined(htons) */ 169432144Sminshall sin.sin_port = htons(sin.sin_port); 169532144Sminshall } 169632144Sminshall } else { 169732144Sminshall if (sp == 0) { 169832144Sminshall sp = getservbyname("telnet", "tcp"); 169932144Sminshall if (sp == 0) { 170034849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 170132144Sminshall return 0; 170232144Sminshall } 170332144Sminshall sin.sin_port = sp->s_port; 170432144Sminshall } 170532144Sminshall telnetport = 1; 170632144Sminshall } 170737219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 170832144Sminshall do { 170932144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 171032144Sminshall if (net < 0) { 171132144Sminshall perror("telnet: socket"); 171232144Sminshall return 0; 171332144Sminshall } 171438689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 171538689Sborman if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) 171638689Sborman perror("setsockopt (IP_OPTIONS)"); 171738689Sborman #endif 1718*40248Sborman #if defined(HAS_IP_TOS) || defined(NEED_GETTOS) 171940245Sborman if ((tp = gettosbyname("telnet", "tcp")) && 172040245Sborman (setsockopt(net, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0)) 172140245Sborman perror("telnet: setsockopt TOS (ignored)"); 1722*40248Sborman #endif /* defined(HAS_IP_TOS) || defined(NEED_GETTOS) */ 172340245Sborman 172432144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 172532144Sminshall perror("setsockopt (SO_DEBUG)"); 172632144Sminshall } 172732144Sminshall 172832144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 172932144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 173032144Sminshall if (host && host->h_addr_list[1]) { 173132144Sminshall int oerrno = errno; 173232144Sminshall 173332144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 173432144Sminshall inet_ntoa(sin.sin_addr)); 173532144Sminshall errno = oerrno; 173632144Sminshall perror((char *)0); 173732144Sminshall host->h_addr_list++; 173832144Sminshall memcpy((caddr_t)&sin.sin_addr, 173932144Sminshall host->h_addr_list[0], host->h_length); 174032144Sminshall (void) NetClose(net); 174132144Sminshall continue; 174232144Sminshall } 174332144Sminshall #endif /* defined(h_addr) */ 174432144Sminshall perror("telnet: Unable to connect to remote host"); 174532144Sminshall return 0; 174637219Sminshall } 174732144Sminshall connected++; 174832144Sminshall } while (connected == 0); 174938689Sborman cmdrc(argv[1], hostname); 175034849Sminshall (void) call(status, "status", "notmuch", 0); 175132144Sminshall if (setjmp(peerdied) == 0) 175232144Sminshall telnet(); 175334849Sminshall (void) NetClose(net); 175432381Sminshall ExitString("Connection closed by foreign host.\n",1); 175532144Sminshall /*NOTREACHED*/ 175632144Sminshall } 175732144Sminshall 175832144Sminshall 175932144Sminshall #define HELPINDENT (sizeof ("connect")) 176032144Sminshall 176132144Sminshall static char 176232144Sminshall openhelp[] = "connect to a site", 176332144Sminshall closehelp[] = "close current connection", 176432144Sminshall quithelp[] = "exit telnet", 176532144Sminshall statushelp[] = "print status information", 176632144Sminshall helphelp[] = "print help information", 176732144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 176832144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 176938689Sborman unsethelp[] = "unset operating parameters ('unset ?' for more)", 177032144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 177138689Sborman slchelp[] = "change state of special charaters ('slc ?' for more)", 177232144Sminshall displayhelp[] = "display operating parameters", 177332144Sminshall #if defined(TN3270) && defined(unix) 177432144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 177532144Sminshall #endif /* defined(TN3270) && defined(unix) */ 177632144Sminshall #if defined(unix) 177732144Sminshall zhelp[] = "suspend telnet", 177832144Sminshall #endif /* defined(unix */ 177932144Sminshall shellhelp[] = "invoke a subshell", 178038689Sborman modestring[] = "try to enter line-by-line or character-at-a-time mode"; 178132144Sminshall 178232144Sminshall extern int help(), shell(); 178332144Sminshall 178432144Sminshall static Command cmdtab[] = { 178538689Sborman { "close", closehelp, bye, 1 }, 178638689Sborman { "display", displayhelp, display, 0 }, 178738689Sborman { "mode", modestring, modecmd, 0 }, 178838689Sborman { "open", openhelp, tn, 0 }, 178938689Sborman { "quit", quithelp, quit, 0 }, 179038689Sborman { "send", sendhelp, sendcmd, 0 }, 179138689Sborman { "set", sethelp, setcmd, 0 }, 179238689Sborman { "unset", unsethelp, unsetcmd, 0 }, 179338689Sborman { "status", statushelp, status, 0 }, 179438689Sborman { "toggle", togglestring, toggle, 0 }, 179538689Sborman { "slc", slchelp, slccmd, 0 }, 179632144Sminshall #if defined(TN3270) && defined(unix) 179738689Sborman { "transcom", transcomhelp, settranscom, 0 }, 179832144Sminshall #endif /* defined(TN3270) && defined(unix) */ 179932144Sminshall #if defined(unix) 180038689Sborman { "z", zhelp, suspend, 0 }, 180132144Sminshall #endif /* defined(unix) */ 180232144Sminshall #if defined(TN3270) 180338689Sborman { "!", shellhelp, shell, 1 }, 180438689Sborman #else 180538689Sborman { "!", shellhelp, shell, 0 }, 180638689Sborman #endif 180738689Sborman { "?", helphelp, help, 0 }, 180832144Sminshall 0 180932144Sminshall }; 181032144Sminshall 181132144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 181232144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 181332144Sminshall 181432144Sminshall static Command cmdtab2[] = { 181538689Sborman { "help", 0, help, 0 }, 181638689Sborman { "escape", escapehelp, setescape, 0 }, 181738689Sborman { "crmod", crmodhelp, togcrmod, 0 }, 181832144Sminshall 0 181932144Sminshall }; 182032144Sminshall 182135298Sminshall 182232144Sminshall /* 182332144Sminshall * Call routine with argc, argv set from args (terminated by 0). 182432144Sminshall */ 182535298Sminshall 182635417Sminshall /*VARARGS1*/ 182732144Sminshall static 182835298Sminshall call(va_alist) 182935298Sminshall va_dcl 183032144Sminshall { 183135298Sminshall va_list ap; 183235298Sminshall typedef int (*intrtn_t)(); 183335298Sminshall intrtn_t routine; 183435298Sminshall char *args[100]; 183535298Sminshall int argno = 0; 183635298Sminshall 183735298Sminshall va_start(ap); 183835298Sminshall routine = (va_arg(ap, intrtn_t)); 183935495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 184035298Sminshall ; 184135495Sminshall } 184235298Sminshall va_end(ap); 184335495Sminshall return (*routine)(argno-1, args); 184432144Sminshall } 184532144Sminshall 184635298Sminshall 184732144Sminshall static char ** 184832144Sminshall getnextcmd(name) 184932144Sminshall char *name; 185032144Sminshall { 185132144Sminshall Command *c = (Command *) name; 185232144Sminshall 185332144Sminshall return (char **) (c+1); 185432144Sminshall } 185532144Sminshall 185632144Sminshall static Command * 185732144Sminshall getcmd(name) 185832144Sminshall char *name; 185932144Sminshall { 186032144Sminshall Command *cm; 186132144Sminshall 186232144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 186332144Sminshall return cm; 186432144Sminshall } else { 186532144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 186632144Sminshall } 186732144Sminshall } 186832144Sminshall 186932144Sminshall void 187038689Sborman command(top, tbuf, cnt) 187132144Sminshall int top; 187238689Sborman char *tbuf; 187338689Sborman int cnt; 187432144Sminshall { 187532144Sminshall register Command *c; 187632144Sminshall 187732144Sminshall setcommandmode(); 187832144Sminshall if (!top) { 187932144Sminshall putchar('\n'); 188037219Sminshall #if defined(unix) 188132144Sminshall } else { 188232144Sminshall signal(SIGINT, SIG_DFL); 188332144Sminshall signal(SIGQUIT, SIG_DFL); 188432144Sminshall #endif /* defined(unix) */ 188532144Sminshall } 188632144Sminshall for (;;) { 188732144Sminshall printf("%s> ", prompt); 188838689Sborman if (tbuf) { 188938689Sborman register char *cp; 189038689Sborman cp = line; 189138689Sborman while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 189238689Sborman cnt--; 189338689Sborman tbuf = 0; 189438689Sborman if (cp == line || *--cp != '\n' || cp == line) 189538689Sborman goto getline; 189638689Sborman *cp = '\0'; 189738689Sborman printf("%s\n", line); 189838689Sborman } else { 189938689Sborman getline: 190038689Sborman if (gets(line) == NULL) { 190138689Sborman if (feof(stdin) || ferror(stdin)) 190238689Sborman quit(); 190338689Sborman break; 190438689Sborman } 190532144Sminshall } 190632144Sminshall if (line[0] == 0) 190732144Sminshall break; 190832144Sminshall makeargv(); 190937219Sminshall if (margv[0] == 0) { 191037219Sminshall break; 191137219Sminshall } 191232144Sminshall c = getcmd(margv[0]); 191332144Sminshall if (Ambiguous(c)) { 191432144Sminshall printf("?Ambiguous command\n"); 191532144Sminshall continue; 191632144Sminshall } 191732144Sminshall if (c == 0) { 191832144Sminshall printf("?Invalid command\n"); 191932144Sminshall continue; 192032144Sminshall } 192132144Sminshall if (c->needconnect && !connected) { 192232144Sminshall printf("?Need to be connected first.\n"); 192332144Sminshall continue; 192432144Sminshall } 192532144Sminshall if ((*c->handler)(margc, margv)) { 192632144Sminshall break; 192732144Sminshall } 192832144Sminshall } 192932144Sminshall if (!top) { 193032144Sminshall if (!connected) { 193132144Sminshall longjmp(toplevel, 1); 193232144Sminshall /*NOTREACHED*/ 193332144Sminshall } 193432144Sminshall #if defined(TN3270) 193532144Sminshall if (shell_active == 0) { 193638689Sborman setconnmode(0); 193732144Sminshall } 193832144Sminshall #else /* defined(TN3270) */ 193938689Sborman setconnmode(0); 194032144Sminshall #endif /* defined(TN3270) */ 194132144Sminshall } 194232144Sminshall } 194332144Sminshall 194432144Sminshall /* 194532144Sminshall * Help command. 194632144Sminshall */ 194732144Sminshall static 194832144Sminshall help(argc, argv) 194932144Sminshall int argc; 195032144Sminshall char *argv[]; 195132144Sminshall { 195232144Sminshall register Command *c; 195332144Sminshall 195432144Sminshall if (argc == 1) { 195532144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 195632144Sminshall for (c = cmdtab; c->name; c++) 195738689Sborman if (c->help) { 195832144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 195932144Sminshall c->help); 196032144Sminshall } 196132144Sminshall return 0; 196232144Sminshall } 196332144Sminshall while (--argc > 0) { 196432144Sminshall register char *arg; 196532144Sminshall arg = *++argv; 196632144Sminshall c = getcmd(arg); 196732144Sminshall if (Ambiguous(c)) 196832144Sminshall printf("?Ambiguous help command %s\n", arg); 196932144Sminshall else if (c == (Command *)0) 197032144Sminshall printf("?Invalid help command %s\n", arg); 197132144Sminshall else 197232144Sminshall printf("%s\n", c->help); 197332144Sminshall } 197432144Sminshall return 0; 197532144Sminshall } 197638689Sborman 197738689Sborman static char *rcname = 0; 197838689Sborman static char rcbuf[128]; 197938689Sborman 198038689Sborman cmdrc(m1, m2) 198138689Sborman char *m1, *m2; 198238689Sborman { 198338689Sborman register Command *c; 198438689Sborman FILE *rcfile; 198538689Sborman int gotmachine = 0; 198638689Sborman int l1 = strlen(m1); 198738689Sborman int l2 = strlen(m2); 198838689Sborman char m1save[64]; 198938689Sborman 199038689Sborman strcpy(m1save, m1); 199138689Sborman m1 = m1save; 199238689Sborman 199338689Sborman if (rcname == 0) { 199438689Sborman rcname = getenv("HOME"); 199538689Sborman if (rcname) 199638689Sborman strcpy(rcbuf, rcname); 199738689Sborman else 199838689Sborman rcbuf[0] = '\0'; 199938689Sborman strcat(rcbuf, "/.telnetrc"); 200038689Sborman rcname = rcbuf; 200138689Sborman } 200238689Sborman 200338689Sborman if ((rcfile = fopen(rcname, "r")) == 0) { 200438689Sborman return; 200538689Sborman } 200638689Sborman 200738689Sborman for (;;) { 200838689Sborman if (fgets(line, sizeof(line), rcfile) == NULL) 200938689Sborman break; 201038689Sborman if (line[0] == 0) 201138689Sborman break; 201238689Sborman if (line[0] == '#') 201338689Sborman continue; 201438689Sborman if (gotmachine == 0) { 201538689Sborman if (isspace(line[0])) 201638689Sborman continue; 201738689Sborman if (strncasecmp(line, m1, l1) == 0) 201838689Sborman strncpy(line, &line[l1], sizeof(line) - l1); 201938689Sborman else if (strncasecmp(line, m2, l2) == 0) 202038689Sborman strncpy(line, &line[l2], sizeof(line) - l2); 202138689Sborman else 202238689Sborman continue; 202338689Sborman gotmachine = 1; 202438689Sborman } else { 202538689Sborman if (!isspace(line[0])) { 202638689Sborman gotmachine = 0; 202738689Sborman continue; 202838689Sborman } 202938689Sborman } 203038689Sborman makeargv(); 203138689Sborman if (margv[0] == 0) 203238689Sborman continue; 203338689Sborman c = getcmd(margv[0]); 203438689Sborman if (Ambiguous(c)) { 203538689Sborman printf("?Ambiguous command: %s\n", margv[0]); 203638689Sborman continue; 203738689Sborman } 203838689Sborman if (c == 0) { 203938689Sborman printf("?Invalid command: %s\n", margv[0]); 204038689Sborman continue; 204138689Sborman } 204238689Sborman /* 204338689Sborman * This should never happen... 204438689Sborman */ 204538689Sborman if (c->needconnect && !connected) { 204638689Sborman printf("?Need to be connected first for %s.\n", margv[0]); 204738689Sborman continue; 204838689Sborman } 204938689Sborman (*c->handler)(margc, margv); 205038689Sborman } 205138689Sborman fclose(rcfile); 205238689Sborman } 205338689Sborman 205438689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 205538689Sborman 205638689Sborman /* 205738689Sborman * Source route is handed in as 205838689Sborman * [!]@hop1@hop2...[@|:]dst 205938689Sborman * If the leading ! is present, it is a 206038689Sborman * strict source route, otherwise it is 206138689Sborman * assmed to be a loose source route. 206238689Sborman * 206338689Sborman * We fill in the source route option as 206438689Sborman * hop1,hop2,hop3...dest 206538689Sborman * and return a pointer to hop1, which will 206638689Sborman * be the address to connect() to. 206738689Sborman * 206838689Sborman * Arguments: 206938689Sborman * arg: pointer to route list to decipher 207038689Sborman * 207138689Sborman * cpp: If *cpp is not equal to NULL, this is a 207238689Sborman * pointer to a pointer to a character array 207338689Sborman * that should be filled in with the option. 207438689Sborman * 207538689Sborman * lenp: pointer to an integer that contains the 207638689Sborman * length of *cpp if *cpp != NULL. 207738689Sborman * 207838689Sborman * Return values: 207938689Sborman * 208038689Sborman * Returns the address of the host to connect to. If the 208138689Sborman * return value is -1, there was a syntax error in the 208238689Sborman * option, either unknown characters, or too many hosts. 208338689Sborman * If the return value is 0, one of the hostnames in the 208438689Sborman * path is unknown, and *cpp is set to point to the bad 208538689Sborman * hostname. 208638689Sborman * 208738689Sborman * *cpp: If *cpp was equal to NULL, it will be filled 208838689Sborman * in with a pointer to our static area that has 208938689Sborman * the option filled in. This will be 32bit aligned. 209038689Sborman * 209138689Sborman * *lenp: This will be filled in with how long the option 209238689Sborman * pointed to by *cpp is. 209338689Sborman * 209438689Sborman */ 209538689Sborman unsigned long 209638689Sborman sourceroute(arg, cpp, lenp) 209738689Sborman char *arg; 209838689Sborman char **cpp; 209938689Sborman int *lenp; 210038689Sborman { 210138689Sborman static char lsr[44]; 210238689Sborman char *cp, *cp2, *lsrp, *lsrep, *index(); 210338689Sborman register int tmp; 210438689Sborman struct in_addr sin_addr; 210538689Sborman register struct hostent *host = 0; 210638689Sborman register char c; 210738689Sborman 210838689Sborman /* 210938689Sborman * Verify the arguments, and make sure we have 211038689Sborman * at least 7 bytes for the option. 211138689Sborman */ 211238689Sborman if (cpp == NULL || lenp == NULL) 211338689Sborman return((unsigned long)-1); 211438689Sborman if (*cpp != NULL && *lenp < 7) 211538689Sborman return((unsigned long)-1); 211638689Sborman /* 211738689Sborman * Decide whether we have a buffer passed to us, 211838689Sborman * or if we need to use our own static buffer. 211938689Sborman */ 212038689Sborman if (*cpp) { 212138689Sborman lsrp = *cpp; 212238689Sborman lsrep = lsrp + *lenp; 212338689Sborman } else { 212438689Sborman *cpp = lsrp = lsr; 212538689Sborman lsrep = lsrp + 44; 212638689Sborman } 212738689Sborman 212838689Sborman cp = arg; 212938689Sborman 213038689Sborman /* 213138689Sborman * Next, decide whether we have a loose source 213238689Sborman * route or a strict source route, and fill in 213338689Sborman * the begining of the option. 213438689Sborman */ 213538689Sborman if (*cp == '!') { 213638689Sborman cp++; 213738689Sborman *lsrp++ = IPOPT_SSRR; 213838689Sborman } else 213938689Sborman *lsrp++ = IPOPT_LSRR; 214038689Sborman 214138689Sborman if (*cp != '@') 214238689Sborman return((unsigned long)-1); 214338689Sborman 214438689Sborman lsrp++; /* skip over length, we'll fill it in later */ 214538689Sborman *lsrp++ = 4; 214638689Sborman 214738689Sborman cp++; 214838689Sborman 214938689Sborman sin_addr.s_addr = 0; 215038689Sborman 215138689Sborman for (c = 0;;) { 215238689Sborman if (c == ':') 215338689Sborman cp2 = 0; 215438689Sborman else for (cp2 = cp; c = *cp2; cp2++) { 215538689Sborman if (c == ',') { 215638689Sborman *cp2++ = '\0'; 215738689Sborman if (*cp2 == '@') 215838689Sborman cp2++; 215938689Sborman } else if (c == '@') { 216038689Sborman *cp2++ = '\0'; 216138689Sborman } else if (c == ':') { 216238689Sborman *cp2++ = '\0'; 216338689Sborman } else 216438689Sborman continue; 216538689Sborman break; 216638689Sborman } 216738689Sborman if (!c) 216838689Sborman cp2 = 0; 216938689Sborman 217038689Sborman if ((tmp = inet_addr(cp)) != -1) { 217138689Sborman sin_addr.s_addr = tmp; 217238689Sborman } else if (host = gethostbyname(cp)) { 217338689Sborman #if defined(h_addr) 217438689Sborman memcpy((caddr_t)&sin_addr, 217538689Sborman host->h_addr_list[0], host->h_length); 217638689Sborman #else 217738689Sborman memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); 217838689Sborman #endif 217938689Sborman } else { 218038689Sborman *cpp = cp; 218138689Sborman return(0); 218238689Sborman } 218338689Sborman memcpy(lsrp, (char *)&sin_addr, 4); 218438689Sborman lsrp += 4; 218538689Sborman if (cp2) 218638689Sborman cp = cp2; 218738689Sborman else 218838689Sborman break; 218938689Sborman /* 219038689Sborman * Check to make sure there is space for next address 219138689Sborman */ 219238689Sborman if (lsrp + 4 > lsrep) 219338689Sborman return((unsigned long)-1); 219438689Sborman } 219538689Sborman if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 219638689Sborman *cpp = 0; 219738689Sborman *lenp = 0; 219838689Sborman return((unsigned long)-1); 219938689Sborman } 220038689Sborman *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 220138689Sborman *lenp = lsrp - *cpp; 220238689Sborman return(sin_addr.s_addr); 220338689Sborman } 220438689Sborman #endif 220538689Sborman 220638909Sborman #if defined(NOSTRNCASECMP) 220738689Sborman strncasecmp(p1, p2, len) 220838689Sborman register char *p1, *p2; 220938689Sborman int len; 221038689Sborman { 221138689Sborman while (len--) { 221238689Sborman if (tolower(*p1) != tolower(*p2)) 221338689Sborman return(tolower(*p1) - tolower(*p2)); 221438689Sborman if (*p1 == '\0') 221538689Sborman return(0); 221638689Sborman p1++, p2++; 221738689Sborman } 221838689Sborman return(0); 221938689Sborman } 222038689Sborman #endif 2221