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*38909Sborman static char sccsid[] = "@(#)commands.c 1.21 (Berkeley) 09/01/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> 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> 5038810Sborman # ifndef sun 5138810Sborman # include <machine/endian.h> 5238810Sborman # endif /* sun */ 5338810Sborman # endif /* CRAY */ 5438689Sborman #include <netinet/ip.h> 5538810Sborman #endif /* SRCRT */ 5638689Sborman 5738689Sborman 5832144Sminshall char *hostname; 5938689Sborman extern char *getenv(); 6032144Sminshall 6136180Sminshall #define Ambiguous(s) ((char **)s == &ambiguous) 6232144Sminshall static char *ambiguous; /* special return value for command routines */ 6332144Sminshall 6432144Sminshall typedef struct { 6532144Sminshall char *name; /* command name */ 6638689Sborman char *help; /* help string (NULL for no help) */ 6732144Sminshall int (*handler)(); /* routine which executes command */ 6832144Sminshall int needconnect; /* Do we need to be connected to execute? */ 6932144Sminshall } Command; 7032144Sminshall 7138689Sborman static char line[256]; 7238689Sborman static char saveline[256]; 7332144Sminshall static int margc; 7432144Sminshall static char *margv[20]; 7532144Sminshall 7632144Sminshall /* 7732144Sminshall * Various utility routines. 7832144Sminshall */ 7932144Sminshall 8036180Sminshall #if !defined(BSD) || (BSD <= 43) 8136180Sminshall 8236180Sminshall char *h_errlist[] = { 8336180Sminshall "Error 0", 8436180Sminshall "Unknown host", /* 1 HOST_NOT_FOUND */ 8536180Sminshall "Host name lookup failure", /* 2 TRY_AGAIN */ 8636180Sminshall "Unknown server error", /* 3 NO_RECOVERY */ 8736180Sminshall "No address associated with name", /* 4 NO_ADDRESS */ 8836180Sminshall }; 8936180Sminshall int h_nerr = { sizeof(h_errlist)/sizeof(h_errlist[0]) }; 9036180Sminshall 9136274Sminshall int h_errno; /* In some version of SunOS this is necessary */ 9236180Sminshall 9336180Sminshall /* 9436180Sminshall * herror -- 9536180Sminshall * print the error indicated by the h_errno value. 9636180Sminshall */ 9736180Sminshall herror(s) 9836180Sminshall char *s; 9936180Sminshall { 10036180Sminshall if (s && *s) { 10136180Sminshall fprintf(stderr, "%s: ", s); 10236180Sminshall } 10336180Sminshall if ((h_errno < 0) || (h_errno >= h_nerr)) { 10436180Sminshall fprintf(stderr, "Unknown error\n"); 10536274Sminshall } else if (h_errno == 0) { 10636274Sminshall #if defined(sun) 10736274Sminshall fprintf(stderr, "Host unknown\n"); 10836274Sminshall #endif /* defined(sun) */ 10936180Sminshall } else { 11036180Sminshall fprintf(stderr, "%s\n", h_errlist[h_errno]); 11136180Sminshall } 11236180Sminshall } 11336180Sminshall #endif /* !define(BSD) || (BSD <= 43) */ 11436180Sminshall 11532144Sminshall static void 11632144Sminshall makeargv() 11732144Sminshall { 11832144Sminshall register char *cp; 11932144Sminshall register char **argp = margv; 12032144Sminshall 12132144Sminshall margc = 0; 12232144Sminshall cp = line; 12332144Sminshall if (*cp == '!') { /* Special case shell escape */ 12438689Sborman strcpy(saveline, line); /* save for shell command */ 12532144Sminshall *argp++ = "!"; /* No room in string to get this */ 12632144Sminshall margc++; 12732144Sminshall cp++; 12832144Sminshall } 12932144Sminshall while (*cp) { 13032144Sminshall while (isspace(*cp)) 13132144Sminshall cp++; 13232144Sminshall if (*cp == '\0') 13332144Sminshall break; 13432144Sminshall *argp++ = cp; 13532144Sminshall margc += 1; 13632144Sminshall while (*cp != '\0' && !isspace(*cp)) 13732144Sminshall cp++; 13832144Sminshall if (*cp == '\0') 13932144Sminshall break; 14032144Sminshall *cp++ = '\0'; 14132144Sminshall } 14232144Sminshall *argp++ = 0; 14332144Sminshall } 14432144Sminshall 14532144Sminshall 14632144Sminshall static char ** 14732144Sminshall genget(name, table, next) 14832144Sminshall char *name; /* name to match */ 14932144Sminshall char **table; /* name entry in table */ 15032144Sminshall char **(*next)(); /* routine to return next entry in table */ 15132144Sminshall { 15232144Sminshall register char *p, *q; 15332144Sminshall register char **c, **found; 15432144Sminshall register int nmatches, longest; 15532144Sminshall 15632144Sminshall if (name == 0) { 15732144Sminshall return 0; 15832144Sminshall } 15932144Sminshall longest = 0; 16032144Sminshall nmatches = 0; 16132144Sminshall found = 0; 16232144Sminshall for (c = table; (p = *c) != 0; c = (*next)(c)) { 16332144Sminshall for (q = name; 16432144Sminshall (*q == *p) || (isupper(*q) && tolower(*q) == *p); p++, q++) 16532144Sminshall if (*q == 0) /* exact match? */ 16632144Sminshall return (c); 16732144Sminshall if (!*q) { /* the name was a prefix */ 16832144Sminshall if (q - name > longest) { 16932144Sminshall longest = q - name; 17032144Sminshall nmatches = 1; 17132144Sminshall found = c; 17232144Sminshall } else if (q - name == longest) 17332144Sminshall nmatches++; 17432144Sminshall } 17532144Sminshall } 17632144Sminshall if (nmatches > 1) 17736180Sminshall return &ambiguous; 17832144Sminshall return (found); 17932144Sminshall } 18032144Sminshall 18132144Sminshall /* 18232144Sminshall * Make a character string into a number. 18332144Sminshall * 18432144Sminshall * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 18532144Sminshall */ 18632144Sminshall 18732144Sminshall static 18832144Sminshall special(s) 18932144Sminshall register char *s; 19032144Sminshall { 19132144Sminshall register char c; 19232144Sminshall char b; 19332144Sminshall 19432144Sminshall switch (*s) { 19532144Sminshall case '^': 19632144Sminshall b = *++s; 19732144Sminshall if (b == '?') { 19832144Sminshall c = b | 0x40; /* DEL */ 19932144Sminshall } else { 20032144Sminshall c = b & 0x1f; 20132144Sminshall } 20232144Sminshall break; 20332144Sminshall default: 20432144Sminshall c = *s; 20532144Sminshall break; 20632144Sminshall } 20732144Sminshall return c; 20832144Sminshall } 20932144Sminshall 21032144Sminshall /* 21132144Sminshall * Construct a control character sequence 21232144Sminshall * for a special character. 21332144Sminshall */ 21432144Sminshall static char * 21532144Sminshall control(c) 21632144Sminshall register int c; 21732144Sminshall { 21832144Sminshall static char buf[3]; 21932144Sminshall 22032144Sminshall if (c == 0x7f) 22132144Sminshall return ("^?"); 22232144Sminshall if (c == '\377') { 22332144Sminshall return "off"; 22432144Sminshall } 22532144Sminshall if (c >= 0x20) { 22632144Sminshall buf[0] = c; 22732144Sminshall buf[1] = 0; 22832144Sminshall } else { 22932144Sminshall buf[0] = '^'; 23032144Sminshall buf[1] = '@'+c; 23132144Sminshall buf[2] = 0; 23232144Sminshall } 23332144Sminshall return (buf); 23432144Sminshall } 23532144Sminshall 23632144Sminshall 23732144Sminshall 23832144Sminshall /* 23932144Sminshall * The following are data structures and routines for 24032144Sminshall * the "send" command. 24132144Sminshall * 24232144Sminshall */ 24332144Sminshall 24432144Sminshall struct sendlist { 24532144Sminshall char *name; /* How user refers to it (case independent) */ 24632144Sminshall char *help; /* Help information (0 ==> no help) */ 24732144Sminshall #if defined(NOT43) 24838689Sborman int (*handler)(); /* Routine to perform (for special ops) */ 24932144Sminshall #else /* defined(NOT43) */ 25038689Sborman void (*handler)(); /* Routine to perform (for special ops) */ 25132144Sminshall #endif /* defined(NOT43) */ 25238689Sborman int what; /* Character to be sent (<0 ==> special) */ 25332144Sminshall }; 25432144Sminshall 25532144Sminshall #define SENDQUESTION -1 25632144Sminshall #define SENDESCAPE -3 25732144Sminshall 25832144Sminshall static struct sendlist Sendlist[] = { 25938689Sborman { "ao", "Send Telnet Abort output", 0, AO }, 26038689Sborman { "ayt", "Send Telnet 'Are You There'", 0, AYT }, 26138689Sborman { "brk", "Send Telnet Break", 0, BREAK }, 26238689Sborman { "ec", "Send Telnet Erase Character", 0, EC }, 26338689Sborman { "el", "Send Telnet Erase Line", 0, EL }, 26438689Sborman { "escape", "Send current escape character", 0, SENDESCAPE }, 26538689Sborman { "ga", "Send Telnet 'Go Ahead' sequence", 0, GA }, 26638689Sborman { "ip", "Send Telnet Interrupt Process", 0, IP }, 26738689Sborman { "nop", "Send Telnet 'No operation'", 0, NOP }, 26838689Sborman { "eor", "Send Telnet 'End of Record'", 0, EOR }, 26938689Sborman { "abort", "Send Telnet 'Abort Process'", 0, ABORT }, 27038689Sborman { "susp", "Send Telnet 'Suspend Process'", 0, SUSP }, 27138689Sborman { "eof", "Send Telnet End of File Character", 0, xEOF }, 27238689Sborman { "synch", "Perform Telnet 'Synch operation'", dosynch, SYNCH }, 273*38909Sborman { "getstatus", "Send request for STATUS", get_status, 0 }, 27438689Sborman { "?", "Display send options", 0, SENDQUESTION }, 27532144Sminshall { 0 } 27632144Sminshall }; 27732144Sminshall 27832144Sminshall static struct sendlist Sendlist2[] = { /* some synonyms */ 27938689Sborman { "break", 0, 0, BREAK }, 28032144Sminshall 28138689Sborman { "intp", 0, 0, IP }, 28238689Sborman { "interrupt", 0, 0, IP }, 28338689Sborman { "intr", 0, 0, IP }, 28432144Sminshall 28538689Sborman { "help", 0, 0, SENDQUESTION }, 28632144Sminshall 28738689Sborman { 0 } 28832144Sminshall }; 28932144Sminshall 29032144Sminshall static char ** 29132144Sminshall getnextsend(name) 29232144Sminshall char *name; 29332144Sminshall { 29432144Sminshall struct sendlist *c = (struct sendlist *) name; 29532144Sminshall 29632144Sminshall return (char **) (c+1); 29732144Sminshall } 29832144Sminshall 29932144Sminshall static struct sendlist * 30032144Sminshall getsend(name) 30132144Sminshall char *name; 30232144Sminshall { 30332144Sminshall struct sendlist *sl; 30432144Sminshall 30532144Sminshall if ((sl = (struct sendlist *) 30632144Sminshall genget(name, (char **) Sendlist, getnextsend)) != 0) { 30732144Sminshall return sl; 30832144Sminshall } else { 30932144Sminshall return (struct sendlist *) 31032144Sminshall genget(name, (char **) Sendlist2, getnextsend); 31132144Sminshall } 31232144Sminshall } 31332144Sminshall 31432144Sminshall static 31532144Sminshall sendcmd(argc, argv) 31632144Sminshall int argc; 31732144Sminshall char **argv; 31832144Sminshall { 31932144Sminshall int what; /* what we are sending this time */ 32032144Sminshall int count; /* how many bytes we are going to need to send */ 32132144Sminshall int i; 32232144Sminshall int question = 0; /* was at least one argument a question */ 32332144Sminshall struct sendlist *s; /* pointer to current command */ 32432144Sminshall 32532144Sminshall if (argc < 2) { 32632144Sminshall printf("need at least one argument for 'send' command\n"); 32732144Sminshall printf("'send ?' for help\n"); 32832144Sminshall return 0; 32932144Sminshall } 33032144Sminshall /* 33132144Sminshall * First, validate all the send arguments. 33232144Sminshall * In addition, we see how much space we are going to need, and 33332144Sminshall * whether or not we will be doing a "SYNCH" operation (which 33432144Sminshall * flushes the network queue). 33532144Sminshall */ 33632144Sminshall count = 0; 33732144Sminshall for (i = 1; i < argc; i++) { 33832144Sminshall s = getsend(argv[i]); 33932144Sminshall if (s == 0) { 34032144Sminshall printf("Unknown send argument '%s'\n'send ?' for help.\n", 34132144Sminshall argv[i]); 34232144Sminshall return 0; 34332144Sminshall } else if (Ambiguous(s)) { 34432144Sminshall printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 34532144Sminshall argv[i]); 34632144Sminshall return 0; 34732144Sminshall } 34832144Sminshall switch (s->what) { 34932144Sminshall case SENDQUESTION: 35038689Sborman question = 1; 35132144Sminshall break; 35232144Sminshall case SENDESCAPE: 35332144Sminshall count += 1; 35432144Sminshall break; 35532144Sminshall case SYNCH: 35632144Sminshall count += 2; 35732144Sminshall break; 35832144Sminshall default: 35932144Sminshall count += 2; 36032144Sminshall break; 36132144Sminshall } 36232144Sminshall } 36338689Sborman if (!connected) { 36438689Sborman if (count) 36538689Sborman printf("?Need to be connected first.\n"); 36638689Sborman if (question) { 36738689Sborman for (s = Sendlist; s->name; s++) 36838689Sborman if (s->help) 36938689Sborman printf("%-15s %s\n", s->name, s->help); 37038689Sborman } else 37138689Sborman printf("'send ?' for help\n"); 37238689Sborman return !question; 37338689Sborman } 37432144Sminshall /* Now, do we have enough room? */ 37532144Sminshall if (NETROOM() < count) { 37632144Sminshall printf("There is not enough room in the buffer TO the network\n"); 37732144Sminshall printf("to process your request. Nothing will be done.\n"); 37832144Sminshall printf("('send synch' will throw away most data in the network\n"); 37932144Sminshall printf("buffer, if this might help.)\n"); 38032144Sminshall return 0; 38132144Sminshall } 38232144Sminshall /* OK, they are all OK, now go through again and actually send */ 38332144Sminshall for (i = 1; i < argc; i++) { 38432144Sminshall if ((s = getsend(argv[i])) == 0) { 38532144Sminshall fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 38632144Sminshall quit(); 38732144Sminshall /*NOTREACHED*/ 38832144Sminshall } 38938689Sborman if (s->handler) { 39038689Sborman (*s->handler)(s); 39132144Sminshall } else { 39232144Sminshall switch (what = s->what) { 39332144Sminshall case SYNCH: 39432144Sminshall dosynch(); 39532144Sminshall break; 39632144Sminshall case SENDQUESTION: 39732144Sminshall for (s = Sendlist; s->name; s++) { 39838689Sborman if (s->help) 39938689Sborman printf("%-15s %s\n", s->name, s->help); 40032144Sminshall } 40132144Sminshall question = 1; 40232144Sminshall break; 40332144Sminshall case SENDESCAPE: 40432144Sminshall NETADD(escape); 40532144Sminshall break; 40632144Sminshall default: 40732144Sminshall NET2ADD(IAC, what); 40832144Sminshall break; 40932144Sminshall } 41032144Sminshall } 41132144Sminshall } 41232144Sminshall return !question; 41332144Sminshall } 41432144Sminshall 41532144Sminshall /* 41632144Sminshall * The following are the routines and data structures referred 41732144Sminshall * to by the arguments to the "toggle" command. 41832144Sminshall */ 41932144Sminshall 42032144Sminshall static 42132144Sminshall lclchars() 42232144Sminshall { 42332144Sminshall donelclchars = 1; 42432144Sminshall return 1; 42532144Sminshall } 42632144Sminshall 42732144Sminshall static 42832144Sminshall togdebug() 42932144Sminshall { 43032144Sminshall #ifndef NOT43 43132144Sminshall if (net > 0 && 43232144Sminshall (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 43332144Sminshall perror("setsockopt (SO_DEBUG)"); 43432144Sminshall } 43532144Sminshall #else /* NOT43 */ 43632144Sminshall if (debug) { 43732144Sminshall if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) 43832144Sminshall perror("setsockopt (SO_DEBUG)"); 43932144Sminshall } else 44032144Sminshall printf("Cannot turn off socket debugging\n"); 44132144Sminshall #endif /* NOT43 */ 44232144Sminshall return 1; 44332144Sminshall } 44432144Sminshall 44532144Sminshall 44632144Sminshall static int 44732144Sminshall togcrlf() 44832144Sminshall { 44932144Sminshall if (crlf) { 45032144Sminshall printf("Will send carriage returns as telnet <CR><LF>.\n"); 45132144Sminshall } else { 45232144Sminshall printf("Will send carriage returns as telnet <CR><NUL>.\n"); 45332144Sminshall } 45432144Sminshall return 1; 45532144Sminshall } 45632144Sminshall 457*38909Sborman int binmode; 45832144Sminshall 45932144Sminshall static int 46038689Sborman togbinary(val) 46138689Sborman int val; 46232144Sminshall { 46332144Sminshall donebinarytoggle = 1; 46432144Sminshall 465*38909Sborman if (val >= 0) { 466*38909Sborman binmode = val; 467*38909Sborman } else { 468*38909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 469*38909Sborman my_want_state_is_do(TELOPT_BINARY)) { 470*38909Sborman binmode = 1; 471*38909Sborman } else if (my_want_state_is_wont(TELOPT_BINARY) && 472*38909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 473*38909Sborman binmode = 0; 474*38909Sborman } 475*38909Sborman val = binmode ? 0 : 1; 476*38909Sborman } 477*38909Sborman 478*38909Sborman if (val == 1) { 479*38909Sborman if (my_want_state_is_will(TELOPT_BINARY) && 480*38909Sborman my_want_state_is_do(TELOPT_BINARY)) { 48138689Sborman printf("Already operating in binary mode with remote host.\n"); 482*38909Sborman } else { 483*38909Sborman printf("Negotiating binary mode with remote host.\n"); 484*38909Sborman tel_enter_binary(3); 48538689Sborman } 486*38909Sborman } else { 487*38909Sborman if (my_want_state_is_wont(TELOPT_BINARY) && 488*38909Sborman my_want_state_is_dont(TELOPT_BINARY)) { 48938689Sborman printf("Already in network ascii mode with remote host.\n"); 490*38909Sborman } else { 491*38909Sborman printf("Negotiating network ascii mode with remote host.\n"); 492*38909Sborman tel_leave_binary(3); 49338689Sborman } 49432144Sminshall } 49532144Sminshall return 1; 49632144Sminshall } 49732144Sminshall 498*38909Sborman static int 499*38909Sborman togrbinary(val) 500*38909Sborman int val; 501*38909Sborman { 502*38909Sborman donebinarytoggle = 1; 50332144Sminshall 504*38909Sborman if (val == -1) 505*38909Sborman val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 50632144Sminshall 507*38909Sborman if (val == 1) { 508*38909Sborman if (my_want_state_is_do(TELOPT_BINARY)) { 509*38909Sborman printf("Already receiving in binary mode.\n"); 510*38909Sborman } else { 511*38909Sborman printf("Negotiating binary mode on input.\n"); 512*38909Sborman tel_enter_binary(1); 513*38909Sborman } 514*38909Sborman } else { 515*38909Sborman if (my_want_state_is_dont(TELOPT_BINARY)) { 516*38909Sborman printf("Already receiving in network ascii mode.\n"); 517*38909Sborman } else { 518*38909Sborman printf("Negotiating network ascii mode on input.\n"); 519*38909Sborman tel_leave_binary(1); 520*38909Sborman } 521*38909Sborman } 522*38909Sborman return 1; 523*38909Sborman } 524*38909Sborman 525*38909Sborman static int 526*38909Sborman togxbinary(val) 527*38909Sborman int val; 528*38909Sborman { 529*38909Sborman donebinarytoggle = 1; 530*38909Sborman 531*38909Sborman if (val == -1) 532*38909Sborman val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 533*38909Sborman 534*38909Sborman if (val == 1) { 535*38909Sborman if (my_want_state_is_will(TELOPT_BINARY)) { 536*38909Sborman printf("Already transmitting in binary mode.\n"); 537*38909Sborman } else { 538*38909Sborman printf("Negotiating binary mode on output.\n"); 539*38909Sborman tel_enter_binary(2); 540*38909Sborman } 541*38909Sborman } else { 542*38909Sborman if (my_want_state_is_wont(TELOPT_BINARY)) { 543*38909Sborman printf("Already transmitting in network ascii mode.\n"); 544*38909Sborman } else { 545*38909Sborman printf("Negotiating network ascii mode on output.\n"); 546*38909Sborman tel_leave_binary(2); 547*38909Sborman } 548*38909Sborman } 549*38909Sborman return 1; 550*38909Sborman } 551*38909Sborman 552*38909Sborman 55332144Sminshall extern int togglehelp(); 55438689Sborman extern int slc_check(); 55532144Sminshall 55632144Sminshall struct togglelist { 55732144Sminshall char *name; /* name of toggle */ 55832144Sminshall char *help; /* help message */ 55932144Sminshall int (*handler)(); /* routine to do actual setting */ 56032144Sminshall int *variable; 56132144Sminshall char *actionexplanation; 56232144Sminshall }; 56332144Sminshall 56432144Sminshall static struct togglelist Togglelist[] = { 56532144Sminshall { "autoflush", 56638689Sborman "flushing of output when sending interrupt characters", 56732144Sminshall 0, 56838689Sborman &autoflush, 56938689Sborman "flush output when sending interrupt characters" }, 57032144Sminshall { "autosynch", 57138689Sborman "automatic sending of interrupt characters in urgent mode", 57232144Sminshall 0, 57338689Sborman &autosynch, 57438689Sborman "send interrupt characters in urgent mode" }, 57532144Sminshall { "binary", 57638689Sborman "sending and receiving of binary data", 57732144Sminshall togbinary, 57838689Sborman 0, 57938689Sborman 0 }, 580*38909Sborman { "inbinary", 581*38909Sborman "receiving of binary data", 582*38909Sborman togrbinary, 583*38909Sborman 0, 584*38909Sborman 0 }, 585*38909Sborman { "outbinary", 586*38909Sborman "sending of binary data", 587*38909Sborman togxbinary, 588*38909Sborman 0, 589*38909Sborman 0 }, 59032144Sminshall { "crlf", 59138689Sborman "sending carriage returns as telnet <CR><LF>", 59232144Sminshall togcrlf, 59338689Sborman &crlf, 59438689Sborman 0 }, 59532144Sminshall { "crmod", 59638689Sborman "mapping of received carriage returns", 59732144Sminshall 0, 59838689Sborman &crmod, 59938689Sborman "map carriage return on output" }, 60032144Sminshall { "localchars", 60138689Sborman "local recognition of certain control characters", 60232144Sminshall lclchars, 60338689Sborman &localchars, 60438689Sborman "recognize certain control characters" }, 60538689Sborman { " ", "", 0 }, /* empty line */ 60638208Sminshall #if defined(unix) && defined(TN3270) 60738208Sminshall { "cursesdata", 60838208Sminshall "(debugging) toggle printing of hexadecimal curses data", 60938208Sminshall 0, 61038689Sborman &cursesdata, 61138689Sborman "print hexadecimal representation of curses data" }, 61238208Sminshall #endif /* defined(unix) && defined(TN3270) */ 61332144Sminshall { "debug", 61438689Sborman "debugging", 61532144Sminshall togdebug, 61638689Sborman &debug, 61738689Sborman "turn on socket level debugging" }, 61832144Sminshall { "netdata", 61938689Sborman "printing of hexadecimal network data (debugging)", 62032144Sminshall 0, 62138689Sborman &netdata, 62238689Sborman "print hexadecimal representation of network traffic" }, 62338689Sborman { "prettydump", 62438689Sborman "output of \"netdata\" to user readable format (debugging)", 62538689Sborman 0, 62638689Sborman &prettydump, 62738689Sborman "print user readable output for \"netdata\"" }, 62832144Sminshall { "options", 62938689Sborman "viewing of options processing (debugging)", 63032144Sminshall 0, 63138689Sborman &showoptions, 63238689Sborman "show option processing" }, 63338208Sminshall #if defined(unix) 63438208Sminshall { "termdata", 63538208Sminshall "(debugging) toggle printing of hexadecimal terminal data", 63638208Sminshall 0, 63738689Sborman &termdata, 63838689Sborman "print hexadecimal representation of terminal traffic" }, 63938208Sminshall #endif /* defined(unix) */ 64032144Sminshall { "?", 64138689Sborman 0, 64238689Sborman togglehelp }, 64332144Sminshall { "help", 64438689Sborman 0, 64538689Sborman togglehelp }, 64632144Sminshall { 0 } 64732144Sminshall }; 64832144Sminshall 64932144Sminshall static 65032144Sminshall togglehelp() 65132144Sminshall { 65232144Sminshall struct togglelist *c; 65332144Sminshall 65432144Sminshall for (c = Togglelist; c->name; c++) { 65538689Sborman if (c->help) { 65638689Sborman if (*c->help) 65738689Sborman printf("%-15s toggle %s\n", c->name, c->help); 65838689Sborman else 65938689Sborman printf("\n"); 66032144Sminshall } 66132144Sminshall } 66238689Sborman printf("\n"); 66338689Sborman printf("%-15s %s\n", "?", "display help information"); 66432144Sminshall return 0; 66532144Sminshall } 66632144Sminshall 66738689Sborman static 66838689Sborman settogglehelp(set) 66938689Sborman int set; 67038689Sborman { 67138689Sborman struct togglelist *c; 67238689Sborman 67338689Sborman for (c = Togglelist; c->name; c++) { 67438689Sborman if (c->help) { 67538689Sborman if (*c->help) 67638689Sborman printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 67738689Sborman c->help); 67838689Sborman else 67938689Sborman printf("\n"); 68038689Sborman } 68138689Sborman } 68238689Sborman } 68338689Sborman 68432144Sminshall static char ** 68532144Sminshall getnexttoggle(name) 68632144Sminshall char *name; 68732144Sminshall { 68832144Sminshall struct togglelist *c = (struct togglelist *) name; 68932144Sminshall 69032144Sminshall return (char **) (c+1); 69132144Sminshall } 69232144Sminshall 69332144Sminshall static struct togglelist * 69432144Sminshall gettoggle(name) 69532144Sminshall char *name; 69632144Sminshall { 69732144Sminshall return (struct togglelist *) 69832144Sminshall genget(name, (char **) Togglelist, getnexttoggle); 69932144Sminshall } 70032144Sminshall 70132144Sminshall static 70232144Sminshall toggle(argc, argv) 70332144Sminshall int argc; 70432144Sminshall char *argv[]; 70532144Sminshall { 70632144Sminshall int retval = 1; 70732144Sminshall char *name; 70832144Sminshall struct togglelist *c; 70932144Sminshall 71032144Sminshall if (argc < 2) { 71132144Sminshall fprintf(stderr, 71232144Sminshall "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 71332144Sminshall return 0; 71432144Sminshall } 71532144Sminshall argc--; 71632144Sminshall argv++; 71732144Sminshall while (argc--) { 71832144Sminshall name = *argv++; 71932144Sminshall c = gettoggle(name); 72032144Sminshall if (Ambiguous(c)) { 72132144Sminshall fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 72232144Sminshall name); 72332144Sminshall return 0; 72432144Sminshall } else if (c == 0) { 72532144Sminshall fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 72632144Sminshall name); 72732144Sminshall return 0; 72832144Sminshall } else { 72932144Sminshall if (c->variable) { 73032144Sminshall *c->variable = !*c->variable; /* invert it */ 73132144Sminshall if (c->actionexplanation) { 73232144Sminshall printf("%s %s.\n", *c->variable? "Will" : "Won't", 73332144Sminshall c->actionexplanation); 73432144Sminshall } 73532144Sminshall } 73632144Sminshall if (c->handler) { 73738689Sborman retval &= (*c->handler)(-1); 73832144Sminshall } 73932144Sminshall } 74032144Sminshall } 74132144Sminshall return retval; 74232144Sminshall } 74332144Sminshall 74432144Sminshall /* 74532144Sminshall * The following perform the "set" command. 74632144Sminshall */ 74732144Sminshall 74838689Sborman #ifdef USE_TERMIO 74938689Sborman struct termio new_tc = { 0 }; 75038689Sborman #endif 75138689Sborman 75232144Sminshall struct setlist { 75332144Sminshall char *name; /* name */ 75432144Sminshall char *help; /* help information */ 75538689Sborman void (*handler)(); 75632144Sminshall char *charp; /* where it is located at */ 75732144Sminshall }; 75832144Sminshall 75932144Sminshall static struct setlist Setlist[] = { 76038689Sborman { "echo", "character to toggle local echoing on/off", 0, &echoc }, 76138689Sborman { "escape", "character to escape back to telnet command mode", 0, &escape }, 76238689Sborman { "tracefile", "file to write trace intormation to", SetNetTrace, NetTraceFile}, 76332144Sminshall { " ", "" }, 76438689Sborman { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 76538689Sborman #ifndef CRAY 76638689Sborman { "flushoutput", "character to cause an Abort Oubput", 0, termFlushCharp }, 76738689Sborman #endif 76838689Sborman { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 76938689Sborman { "quit", "character to cause an Abort process", 0, termQuitCharp }, 77038689Sborman { "eof", "character to cause an EOF ", 0, termEofCharp }, 77138689Sborman { " ", "" }, 77238689Sborman { " ", "The following are for local editing in linemode", 0, 0 }, 77338689Sborman { "erase", "character to use to erase a character", 0, termEraseCharp }, 77438689Sborman { "kill", "character to use to erase a line", 0, termKillCharp }, 77538689Sborman #ifndef CRAY 77638689Sborman { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 77738689Sborman { "susp", "character to cuase a Suspend Process", 0, termSuspCharp }, 77838689Sborman { "reprint", "character to use for line reprint", 0, termRprntCharp }, 77938689Sborman { "worderase", "character to use to erase a word", 0, termWerasCharp }, 78038689Sborman { "start", "character to use for XON", 0, termStartCharp }, 78138689Sborman { "stop", "character to sue for XOFF", 0, termStopCharp }, 78238689Sborman #endif 78332144Sminshall { 0 } 78432144Sminshall }; 78532144Sminshall 78638689Sborman #ifdef CRAY 78738689Sborman /* Work around compiler bug */ 78838689Sborman _setlist_init() 78938689Sborman { 79038689Sborman Setlist[6].charp = &termIntChar; 79138689Sborman Setlist[7].charp = &termQuitChar; 79238689Sborman Setlist[8].charp = &termEofChar; 79338689Sborman Setlist[11].charp = &termEraseChar; 79438689Sborman Setlist[12].charp = &termKillChar; 79538689Sborman } 79638810Sborman #endif /* CRAY */ 79738689Sborman 79832144Sminshall static char ** 79932144Sminshall getnextset(name) 80032144Sminshall char *name; 80132144Sminshall { 80232144Sminshall struct setlist *c = (struct setlist *)name; 80332144Sminshall 80432144Sminshall return (char **) (c+1); 80532144Sminshall } 80632144Sminshall 80732144Sminshall static struct setlist * 80832144Sminshall getset(name) 80932144Sminshall char *name; 81032144Sminshall { 81132144Sminshall return (struct setlist *) genget(name, (char **) Setlist, getnextset); 81232144Sminshall } 81332144Sminshall 81432144Sminshall static 81532144Sminshall setcmd(argc, argv) 81632144Sminshall int argc; 81732144Sminshall char *argv[]; 81832144Sminshall { 81932144Sminshall int value; 82032144Sminshall struct setlist *ct; 82138689Sborman struct togglelist *c; 82232144Sminshall 82338689Sborman if (argc < 2 || argc > 3) { 82438689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 82532144Sminshall return 0; 82632144Sminshall } 82738689Sborman if ((argc == 2) && 82838689Sborman ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help")))) { 82938689Sborman for (ct = Setlist; ct->name; ct++) 83038689Sborman printf("%-15s %s\n", ct->name, ct->help); 83138689Sborman printf("\n"); 83238689Sborman settogglehelp(1); 83338689Sborman printf("%-15s %s\n", "?", "display help information"); 83438689Sborman return 0; 83538689Sborman } 83632144Sminshall 83732144Sminshall ct = getset(argv[1]); 83832144Sminshall if (ct == 0) { 83938689Sborman c = gettoggle(argv[1]); 84038689Sborman if (c == 0) { 84138689Sborman fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 84232144Sminshall argv[1]); 84338689Sborman return 0; 84438689Sborman } else if (Ambiguous(c)) { 84538689Sborman fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 84638689Sborman argv[1]); 84738689Sborman return 0; 84838689Sborman } 84938689Sborman if (c->variable) { 85038689Sborman if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 85138689Sborman *c->variable = 1; 85238689Sborman else if (strcmp("off", argv[2]) == 0) 85338689Sborman *c->variable = 0; 85438689Sborman else { 85538689Sborman printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 85638689Sborman return 0; 85738689Sborman } 85838689Sborman if (c->actionexplanation) { 85938689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 86038689Sborman c->actionexplanation); 86138689Sborman } 86238689Sborman } 86338689Sborman if (c->handler) 86438689Sborman (*c->handler)(1); 86538689Sborman } else if (argc != 3) { 86638689Sborman printf("Format is 'set Name Value'\n'set ?' for help.\n"); 86732144Sminshall return 0; 86832144Sminshall } else if (Ambiguous(ct)) { 86932144Sminshall fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 87032144Sminshall argv[1]); 87132144Sminshall return 0; 87238689Sborman } else if (ct->handler) { 87338689Sborman (*ct->handler)(argv[2]); 87438689Sborman printf("%s set to \"%s\".\n", ct->name, ct->charp); 87532144Sminshall } else { 87632144Sminshall if (strcmp("off", argv[2])) { 87732144Sminshall value = special(argv[2]); 87832144Sminshall } else { 87932144Sminshall value = -1; 88032144Sminshall } 88132144Sminshall *(ct->charp) = value; 88232144Sminshall printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 88332144Sminshall } 88438689Sborman slc_check(); 88532144Sminshall return 1; 88632144Sminshall } 88738689Sborman 88838689Sborman static 88938689Sborman unsetcmd(argc, argv) 89038689Sborman int argc; 89138689Sborman char *argv[]; 89238689Sborman { 89338689Sborman int value; 89438689Sborman struct setlist *ct; 89538689Sborman struct togglelist *c; 89638689Sborman register char *name; 89738689Sborman 89838689Sborman if (argc < 2) { 89938689Sborman fprintf(stderr, 90038689Sborman "Need an argument to 'unset' command. 'unset ?' for help.\n"); 90138689Sborman return 0; 90238689Sborman } 90338689Sborman if ((!strcmp(argv[1], "?")) || (!strcmp(argv[1], "help"))) { 90438689Sborman for (ct = Setlist; ct->name; ct++) 90538689Sborman printf("%-15s %s\n", ct->name, ct->help); 90638689Sborman printf("\n"); 90738689Sborman settogglehelp(0); 90838689Sborman printf("%-15s %s\n", "?", "display help information"); 90938689Sborman return 0; 91038689Sborman } 91138689Sborman 91238689Sborman argc--; 91338689Sborman argv++; 91438689Sborman while (argc--) { 91538689Sborman name = *argv++; 91638689Sborman ct = getset(name); 91738689Sborman if (ct == 0) { 91838689Sborman c = gettoggle(name); 91938689Sborman if (c == 0) { 92038689Sborman fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 92138689Sborman name); 92238689Sborman return 0; 92338689Sborman } else if (Ambiguous(c)) { 92438689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 92538689Sborman name); 92638689Sborman return 0; 92738689Sborman } 92838689Sborman if (c->variable) { 92938689Sborman *c->variable = 0; 93038689Sborman if (c->actionexplanation) { 93138689Sborman printf("%s %s.\n", *c->variable? "Will" : "Won't", 93238689Sborman c->actionexplanation); 93338689Sborman } 93438689Sborman } 93538689Sborman if (c->handler) 93638689Sborman (*c->handler)(0); 93738689Sborman } else if (Ambiguous(ct)) { 93838689Sborman fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 93938689Sborman name); 94038689Sborman return 0; 94138689Sborman } else if (ct->handler) { 94238689Sborman (*ct->handler)(0); 94338689Sborman printf("%s reset to \"%s\".\n", ct->name, ct->charp); 94438689Sborman } else { 94538689Sborman value = -1; 94638689Sborman *(ct->charp) = -1; 94738689Sborman printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 94838689Sborman } 94938689Sborman } 95038689Sborman return 1; 95138689Sborman } 95232144Sminshall 95332144Sminshall /* 95432144Sminshall * The following are the data structures and routines for the 95532144Sminshall * 'mode' command. 95632144Sminshall */ 95738689Sborman #ifdef KLUDGELINEMODE 95838689Sborman extern int kludgelinemode; 95938689Sborman #endif 96032144Sminshall 96132144Sminshall static 96232144Sminshall dolinemode() 96332144Sminshall { 96438689Sborman #ifdef KLUDGELINEMODE 96538689Sborman if (kludgelinemode) 96638689Sborman send_dont(TELOPT_SGA, 1); 96738689Sborman #endif 96838689Sborman send_will(TELOPT_LINEMODE, 1); 96938689Sborman send_dont(TELOPT_ECHO, 1); 97032144Sminshall return 1; 97132144Sminshall } 97232144Sminshall 97332144Sminshall static 97432144Sminshall docharmode() 97532144Sminshall { 97638689Sborman #ifdef KLUDGELINEMODE 97738689Sborman if (kludgelinemode) 97838689Sborman send_do(TELOPT_SGA, 1); 97938689Sborman else 98038689Sborman #endif 98138689Sborman send_wont(TELOPT_LINEMODE, 1); 98238689Sborman send_do(TELOPT_ECHO, 1); 98338689Sborman return 1; 98438689Sborman } 98538689Sborman 98638689Sborman setmode(bit) 98738689Sborman { 98838689Sborman return dolmmode(bit, 1); 98938689Sborman } 99038689Sborman 99138689Sborman clearmode(bit) 99238689Sborman { 99338689Sborman return dolmmode(bit, 0); 99438689Sborman } 99538689Sborman 99638689Sborman dolmmode(bit, on) 99738689Sborman int bit, on; 99838689Sborman { 99938689Sborman char c; 100038689Sborman extern int linemode; 100138689Sborman 100238689Sborman if (my_want_state_is_wont(TELOPT_LINEMODE)) { 100338689Sborman printf("?Need to have LINEMODE option enabled first.\n"); 100438689Sborman printf("'mode ?' for help.\n"); 100538689Sborman return 0; 100632144Sminshall } 100738689Sborman 100838689Sborman if (on) 100938689Sborman c = (linemode | bit); 101038689Sborman else 101138689Sborman c = (linemode & ~bit); 101238689Sborman lm_mode(&c, 1, 1); 101332144Sminshall return 1; 101432144Sminshall } 101532144Sminshall 101638689Sborman struct modelist { 101738689Sborman char *name; /* command name */ 101838689Sborman char *help; /* help string */ 101938689Sborman int (*handler)(); /* routine which executes command */ 102038689Sborman int needconnect; /* Do we need to be connected to execute? */ 102138689Sborman int arg1; 102238689Sborman }; 102338689Sborman 102438689Sborman extern int modehelp(); 102538689Sborman 102638689Sborman static struct modelist ModeList[] = { 102738689Sborman { "character", "Disable LINEMODE option", docharmode, 1 }, 102838689Sborman #ifdef KLUDEGLINEMODE 102938689Sborman { "", "(or disable obsolete line-by-line mode)", 0 }; 103038689Sborman #endif 103138689Sborman { "line", "Enable LINEMODE option", dolinemode, 1 }, 103238689Sborman #ifdef KLUDEGLINEMODE 103338689Sborman { "", "(or enable obsolete line-by-line mode)", 0 }; 103438689Sborman #endif 103538689Sborman { "", "", 0 }, 103638689Sborman { "", "These require the LINEMODE option to be enabled", 0 }, 103738689Sborman { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 103838689Sborman { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 103938689Sborman { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 104038689Sborman { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 104138689Sborman { "+edit", 0, setmode, 1, MODE_EDIT }, 104238689Sborman { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 104338689Sborman { "help", 0, modehelp, 0 }, 104438689Sborman { "?", "Print help information", modehelp, 0 }, 104532144Sminshall { 0 }, 104632144Sminshall }; 104732144Sminshall 104832144Sminshall static char ** 104932144Sminshall getnextmode(name) 105032144Sminshall char *name; 105132144Sminshall { 105238689Sborman return (char **) (((struct modelist *)name)+1); 105332144Sminshall } 105432144Sminshall 105538689Sborman static struct modelist * 105632144Sminshall getmodecmd(name) 105732144Sminshall char *name; 105832144Sminshall { 105938689Sborman return (struct modelist *) genget(name, (char **) ModeList, getnextmode); 106032144Sminshall } 106132144Sminshall 106238689Sborman modehelp() 106338689Sborman { 106438689Sborman struct modelist *mt; 106538689Sborman 106638689Sborman printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 106738689Sborman for (mt = ModeList; mt->name; mt++) { 106838689Sborman if (mt->help) { 106938689Sborman if (*mt->help) 107038689Sborman printf("%-15s %s\n", mt->name, mt->help); 107138689Sborman else 107238689Sborman printf("\n"); 107338689Sborman } 107438689Sborman } 107538689Sborman return 0; 107638689Sborman } 107738689Sborman 107832144Sminshall static 107932144Sminshall modecmd(argc, argv) 108032144Sminshall int argc; 108132144Sminshall char *argv[]; 108232144Sminshall { 108338689Sborman struct modelist *mt; 108432144Sminshall 108538689Sborman if (argc != 2) { 108638689Sborman printf("'mode' command requires an argument\n"); 108738689Sborman printf("'mode ?' for help.\n"); 108838689Sborman } else if ((mt = getmodecmd(argv[1])) == 0) { 108932144Sminshall fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 109032144Sminshall } else if (Ambiguous(mt)) { 109132144Sminshall fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 109238689Sborman } else if (mt->needconnect && !connected) { 109338689Sborman printf("?Need to be connected first.\n"); 109438689Sborman printf("'mode ?' for help.\n"); 109538689Sborman } else if (mt->handler) { 109638689Sborman return (*mt->handler)(mt->arg1); 109732144Sminshall } 109838689Sborman return 0; 109932144Sminshall } 110032144Sminshall 110132144Sminshall /* 110232144Sminshall * The following data structures and routines implement the 110332144Sminshall * "display" command. 110432144Sminshall */ 110532144Sminshall 110632144Sminshall static 110732144Sminshall display(argc, argv) 110832144Sminshall int argc; 110932144Sminshall char *argv[]; 111032144Sminshall { 111132144Sminshall #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 111232144Sminshall if (*tl->variable) { \ 111332144Sminshall printf("will"); \ 111432144Sminshall } else { \ 111532144Sminshall printf("won't"); \ 111632144Sminshall } \ 111732144Sminshall printf(" %s.\n", tl->actionexplanation); \ 111832144Sminshall } 111932144Sminshall 112032144Sminshall #define doset(sl) if (sl->name && *sl->name != ' ') { \ 112138689Sborman if (sl->handler == 0) \ 112238689Sborman printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 112338689Sborman else \ 112438689Sborman printf("%-15s \"%s\"\n", sl->name, sl->charp); \ 112532144Sminshall } 112632144Sminshall 112732144Sminshall struct togglelist *tl; 112832144Sminshall struct setlist *sl; 112932144Sminshall 113032144Sminshall if (argc == 1) { 113132144Sminshall for (tl = Togglelist; tl->name; tl++) { 113232144Sminshall dotog(tl); 113332144Sminshall } 113432144Sminshall printf("\n"); 113532144Sminshall for (sl = Setlist; sl->name; sl++) { 113632144Sminshall doset(sl); 113732144Sminshall } 113832144Sminshall } else { 113932144Sminshall int i; 114032144Sminshall 114132144Sminshall for (i = 1; i < argc; i++) { 114232144Sminshall sl = getset(argv[i]); 114332144Sminshall tl = gettoggle(argv[i]); 114432144Sminshall if (Ambiguous(sl) || Ambiguous(tl)) { 114532144Sminshall printf("?Ambiguous argument '%s'.\n", argv[i]); 114632144Sminshall return 0; 114732144Sminshall } else if (!sl && !tl) { 114832144Sminshall printf("?Unknown argument '%s'.\n", argv[i]); 114932144Sminshall return 0; 115032144Sminshall } else { 115132144Sminshall if (tl) { 115232144Sminshall dotog(tl); 115332144Sminshall } 115432144Sminshall if (sl) { 115532144Sminshall doset(sl); 115632144Sminshall } 115732144Sminshall } 115832144Sminshall } 115932144Sminshall } 116038689Sborman /*@*/optionstatus(); 116132144Sminshall return 1; 116232144Sminshall #undef doset 116332144Sminshall #undef dotog 116432144Sminshall } 116532144Sminshall 116632144Sminshall /* 116732144Sminshall * The following are the data structures, and many of the routines, 116832144Sminshall * relating to command processing. 116932144Sminshall */ 117032144Sminshall 117132144Sminshall /* 117232144Sminshall * Set the escape character. 117332144Sminshall */ 117432144Sminshall static 117532144Sminshall setescape(argc, argv) 117632144Sminshall int argc; 117732144Sminshall char *argv[]; 117832144Sminshall { 117932144Sminshall register char *arg; 118032144Sminshall char buf[50]; 118132144Sminshall 118232144Sminshall printf( 118332144Sminshall "Deprecated usage - please use 'set escape%s%s' in the future.\n", 118432144Sminshall (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 118532144Sminshall if (argc > 2) 118632144Sminshall arg = argv[1]; 118732144Sminshall else { 118832144Sminshall printf("new escape character: "); 118934849Sminshall (void) gets(buf); 119032144Sminshall arg = buf; 119132144Sminshall } 119232144Sminshall if (arg[0] != '\0') 119332144Sminshall escape = arg[0]; 119432144Sminshall if (!In3270) { 119532144Sminshall printf("Escape character is '%s'.\n", control(escape)); 119632144Sminshall } 119734849Sminshall (void) fflush(stdout); 119832144Sminshall return 1; 119932144Sminshall } 120032144Sminshall 120132144Sminshall /*VARARGS*/ 120232144Sminshall static 120332144Sminshall togcrmod() 120432144Sminshall { 120532144Sminshall crmod = !crmod; 120632144Sminshall printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 120732144Sminshall printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 120834849Sminshall (void) fflush(stdout); 120932144Sminshall return 1; 121032144Sminshall } 121132144Sminshall 121232144Sminshall /*VARARGS*/ 121332144Sminshall suspend() 121432144Sminshall { 121538689Sborman #ifdef SIGTSTP 121637219Sminshall setcommandmode(); 121737219Sminshall { 121837219Sminshall long oldrows, oldcols, newrows, newcols; 121937219Sminshall 122037219Sminshall TerminalWindowSize(&oldrows, &oldcols); 122134849Sminshall (void) kill(0, SIGTSTP); 122237219Sminshall TerminalWindowSize(&newrows, &newcols); 122337219Sminshall if ((oldrows != newrows) || (oldcols != newcols)) { 122437219Sminshall if (connected) { 122537219Sminshall sendnaws(); 122637219Sminshall } 122737219Sminshall } 122837219Sminshall } 122937219Sminshall /* reget parameters in case they were changed */ 123037219Sminshall TerminalSaveState(); 123138689Sborman setconnmode(0); 123238689Sborman #else 123338689Sborman printf("Suspend is not supported. Try the '!' command instead\n"); 123438689Sborman #endif 123537219Sminshall return 1; 123632144Sminshall } 123732144Sminshall 123838689Sborman #if !defined(TN3270) 123938689Sborman #ifdef CRAY 124038689Sborman #define vfork fork 124138689Sborman #endif 124238689Sborman shell(argc, argv) 124338689Sborman int argc; 124438689Sborman char *argv[]; 124538689Sborman { 124638689Sborman extern char *rindex(); 124738689Sborman char cmdbuf[256]; 124838689Sborman 124938689Sborman setcommandmode(); 125038689Sborman switch(vfork()) { 125138689Sborman case -1: 125238689Sborman perror("Fork failed\n"); 125338689Sborman break; 125438689Sborman 125538689Sborman case 0: 125638689Sborman { 125738689Sborman /* 125838689Sborman * Fire up the shell in the child. 125938689Sborman */ 126038689Sborman register char *shell, *shellname; 126138689Sborman 126238689Sborman shell = getenv("SHELL"); 126338689Sborman if (shell == NULL) 126438689Sborman shell = "/bin/sh"; 126538689Sborman if ((shellname = rindex(shell, '/')) == 0) 126638689Sborman shellname = shell; 126738689Sborman else 126838689Sborman shellname++; 126938689Sborman if (argc > 1) 127038689Sborman execl(shell, shellname, "-c", &saveline[1], 0); 127138689Sborman else 127238689Sborman execl(shell, shellname, 0); 127338689Sborman perror("Execl"); 127438689Sborman _exit(1); 127538689Sborman } 127638689Sborman default: 127738689Sborman wait((int *)0); /* Wait for the shell to complete */ 127838689Sborman } 127938689Sborman } 128038689Sborman #endif /* !defined(TN3270) */ 128138689Sborman 128232144Sminshall /*VARARGS*/ 128332144Sminshall static 128432144Sminshall bye(argc, argv) 128532144Sminshall int argc; /* Number of arguments */ 128632144Sminshall char *argv[]; /* arguments */ 128732144Sminshall { 128832144Sminshall if (connected) { 128934849Sminshall (void) shutdown(net, 2); 129032144Sminshall printf("Connection closed.\n"); 129134849Sminshall (void) NetClose(net); 129232144Sminshall connected = 0; 129332144Sminshall /* reset options */ 129432144Sminshall tninit(); 129532144Sminshall #if defined(TN3270) 129632144Sminshall SetIn3270(); /* Get out of 3270 mode */ 129732144Sminshall #endif /* defined(TN3270) */ 129832144Sminshall } 129932144Sminshall if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 130032144Sminshall longjmp(toplevel, 1); 130132144Sminshall /* NOTREACHED */ 130232144Sminshall } 130332144Sminshall return 1; /* Keep lint, etc., happy */ 130432144Sminshall } 130532144Sminshall 130632144Sminshall /*VARARGS*/ 130732144Sminshall quit() 130832144Sminshall { 130932144Sminshall (void) call(bye, "bye", "fromquit", 0); 131032144Sminshall Exit(0); 131132144Sminshall return 1; /* just to keep lint happy */ 131232144Sminshall } 131338689Sborman 131438689Sborman /* 131538689Sborman * The SLC command. 131638689Sborman */ 131732144Sminshall 131838689Sborman struct slclist { 131938689Sborman char *name; 132038689Sborman char *help; 132138689Sborman int (*handler)(); 132238689Sborman int arg; 132338689Sborman }; 132438689Sborman 132538689Sborman extern int slc_help(); 132638689Sborman extern int slc_mode_export(), slc_mode_import(), slcstate(); 132738689Sborman 132838689Sborman struct slclist SlcList[] = { 132938689Sborman { "export", "Use local special character definitions", 133038689Sborman slc_mode_export, 0 }, 133138689Sborman { "import", "Use remote special character definitions", 133238689Sborman slc_mode_import, 1 }, 133338689Sborman { "check", "Verify remote special character definitions", 133438689Sborman slc_mode_import, 0 }, 133538689Sborman { "help", 0, slc_help, 0 }, 133638689Sborman { "?", "Print help information", slc_help, 0 }, 133738689Sborman { 0 }, 133838689Sborman }; 133938689Sborman 134038689Sborman static 134138689Sborman slc_help() 134238689Sborman { 134338689Sborman struct slclist *c; 134438689Sborman 134538689Sborman for (c = SlcList; c->name; c++) { 134638689Sborman if (c->help) { 134738689Sborman if (*c->help) 134838689Sborman printf("%-15s %s\n", c->name, c->help); 134938689Sborman else 135038689Sborman printf("\n"); 135138689Sborman } 135238689Sborman } 135338689Sborman } 135438689Sborman 135538689Sborman static char ** 135638689Sborman getnextslc(name) 135738689Sborman char *name; 135838689Sborman { 135938689Sborman return (char **)(((struct slclist *)name)+1); 136038689Sborman } 136138689Sborman 136238689Sborman static struct slclist * 136338689Sborman getslc(name) 136438689Sborman char *name; 136538689Sborman { 136638689Sborman return (struct slclist *)genget(name, (char **) SlcList, getnextslc); 136738689Sborman } 136838689Sborman 136938689Sborman static 137038689Sborman slccmd(argc, argv) 137138689Sborman int argc; 137238689Sborman char *argv[]; 137338689Sborman { 137438689Sborman struct slclist *c; 137538689Sborman 137638689Sborman if (argc != 2) { 137738689Sborman fprintf(stderr, 137838689Sborman "Need an argument to 'slc' command. 'slc ?' for help.\n"); 137938689Sborman return 0; 138038689Sborman } 138138689Sborman c = getslc(argv[1]); 138238689Sborman if (c == 0) { 138338689Sborman fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 138438689Sborman argv[1]); 138538689Sborman return 0; 138638689Sborman } 138738689Sborman if (Ambiguous(c)) { 138838689Sborman fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 138938689Sborman argv[1]); 139038689Sborman return 0; 139138689Sborman } 139238689Sborman (*c->handler)(c->arg); 139338689Sborman slcstate(); 139438689Sborman return 1; 139538689Sborman } 139638689Sborman 139736274Sminshall #if defined(unix) 139832144Sminshall /* 139936274Sminshall * Some information about our file descriptors. 140036274Sminshall */ 140136274Sminshall 140236274Sminshall char * 140336274Sminshall decodeflags(mask) 140436274Sminshall int mask; 140536274Sminshall { 140636274Sminshall static char buffer[100]; 140736274Sminshall #define do(m,s) \ 140836274Sminshall if (mask&(m)) { \ 140936274Sminshall strcat(buffer, (s)); \ 141036274Sminshall } 141136274Sminshall 141236274Sminshall buffer[0] = 0; /* Terminate it */ 141336274Sminshall 141436274Sminshall #ifdef FREAD 141536274Sminshall do(FREAD, " FREAD"); 141636274Sminshall #endif 141736274Sminshall #ifdef FWRITE 141836274Sminshall do(FWRITE, " FWRITE"); 141936274Sminshall #endif 142036274Sminshall #ifdef F_DUPFP 142136274Sminshall do(F_DUPFD, " F_DUPFD"); 142236274Sminshall #endif 142336274Sminshall #ifdef FNDELAY 142436274Sminshall do(FNDELAY, " FNDELAY"); 142536274Sminshall #endif 142636274Sminshall #ifdef FAPPEND 142736274Sminshall do(FAPPEND, " FAPPEND"); 142836274Sminshall #endif 142936274Sminshall #ifdef FMARK 143036274Sminshall do(FMARK, " FMARK"); 143136274Sminshall #endif 143236274Sminshall #ifdef FDEFER 143336274Sminshall do(FDEFER, " FDEFER"); 143436274Sminshall #endif 143536274Sminshall #ifdef FASYNC 143636274Sminshall do(FASYNC, " FASYNC"); 143736274Sminshall #endif 143836274Sminshall #ifdef FSHLOCK 143936274Sminshall do(FSHLOCK, " FSHLOCK"); 144036274Sminshall #endif 144136274Sminshall #ifdef FEXLOCK 144236274Sminshall do(FEXLOCK, " FEXLOCK"); 144336274Sminshall #endif 144436274Sminshall #ifdef FCREAT 144536274Sminshall do(FCREAT, " FCREAT"); 144636274Sminshall #endif 144736274Sminshall #ifdef FTRUNC 144836274Sminshall do(FTRUNC, " FTRUNC"); 144936274Sminshall #endif 145036274Sminshall #ifdef FEXCL 145136274Sminshall do(FEXCL, " FEXCL"); 145236274Sminshall #endif 145336274Sminshall 145436274Sminshall return buffer; 145536274Sminshall } 145636274Sminshall #undef do 145736274Sminshall 145836274Sminshall static void 145936274Sminshall filestuff(fd) 146036274Sminshall int fd; 146136274Sminshall { 146236274Sminshall int res; 146336274Sminshall 146438689Sborman #ifdef F_GETOWN 146538689Sborman setconnmode(0); 146636274Sminshall res = fcntl(fd, F_GETOWN, 0); 146736274Sminshall setcommandmode(); 146836274Sminshall 146936274Sminshall if (res == -1) { 147036274Sminshall perror("fcntl"); 147136274Sminshall return; 147236274Sminshall } 147336274Sminshall printf("\tOwner is %d.\n", res); 147438689Sborman #endif 147536274Sminshall 147638689Sborman setconnmode(0); 147736274Sminshall res = fcntl(fd, F_GETFL, 0); 147836274Sminshall setcommandmode(); 147936274Sminshall 148036274Sminshall if (res == -1) { 148136274Sminshall perror("fcntl"); 148236274Sminshall return; 148336274Sminshall } 148436274Sminshall printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 148536274Sminshall } 148636274Sminshall 148736274Sminshall 148836274Sminshall #endif /* defined(unix) */ 148936274Sminshall 149036274Sminshall /* 149132144Sminshall * Print status about the connection. 149232144Sminshall */ 149334849Sminshall /*ARGSUSED*/ 149432144Sminshall static 149532144Sminshall status(argc, argv) 149632144Sminshall int argc; 149732144Sminshall char *argv[]; 149832144Sminshall { 149932144Sminshall if (connected) { 150032144Sminshall printf("Connected to %s.\n", hostname); 150136242Sminshall if ((argc < 2) || strcmp(argv[1], "notmuch")) { 150238689Sborman int mode = getconnmode(); 150338689Sborman 150438689Sborman if (my_want_state_is_will(TELOPT_LINEMODE)) { 150538689Sborman printf("Operating with LINEMODE option\n"); 150638689Sborman printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 150738689Sborman printf("%s catching of signals\n", 150838689Sborman (mode&MODE_TRAPSIG) ? "Local" : "No"); 150938689Sborman slcstate(); 151038689Sborman #ifdef KLUDGELINEMODE 151138689Sborman } else if (kludgelinemode && my_want_state_is_wont(TELOPT_SGA)) { 151238689Sborman printf("Operating in obsolete linemode\n"); 151338689Sborman #endif 151438689Sborman } else { 151538689Sborman printf("Operating in single character mode\n"); 151638689Sborman if (localchars) 151738689Sborman printf("Catching signals locally\n"); 151832144Sminshall } 151938689Sborman printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 152038689Sborman if (my_want_state_is_will(TELOPT_LFLOW)) 152138689Sborman printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 152232144Sminshall } 152332144Sminshall } else { 152432144Sminshall printf("No connection.\n"); 152532144Sminshall } 152632144Sminshall # if !defined(TN3270) 152732144Sminshall printf("Escape character is '%s'.\n", control(escape)); 152834849Sminshall (void) fflush(stdout); 152932144Sminshall # else /* !defined(TN3270) */ 153032144Sminshall if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 153132144Sminshall printf("Escape character is '%s'.\n", control(escape)); 153232144Sminshall } 153332144Sminshall # if defined(unix) 153436242Sminshall if ((argc >= 2) && !strcmp(argv[1], "everything")) { 153536242Sminshall printf("SIGIO received %d time%s.\n", 153636242Sminshall sigiocount, (sigiocount == 1)? "":"s"); 153736274Sminshall if (In3270) { 153836274Sminshall printf("Process ID %d, process group %d.\n", 153936274Sminshall getpid(), getpgrp(getpid())); 154036274Sminshall printf("Terminal input:\n"); 154136274Sminshall filestuff(tin); 154236274Sminshall printf("Terminal output:\n"); 154336274Sminshall filestuff(tout); 154436274Sminshall printf("Network socket:\n"); 154536274Sminshall filestuff(net); 154636274Sminshall } 154736242Sminshall } 154832144Sminshall if (In3270 && transcom) { 154932144Sminshall printf("Transparent mode command is '%s'.\n", transcom); 155032144Sminshall } 155132144Sminshall # endif /* defined(unix) */ 155234849Sminshall (void) fflush(stdout); 155332144Sminshall if (In3270) { 155432144Sminshall return 0; 155532144Sminshall } 155632144Sminshall # endif /* defined(TN3270) */ 155732144Sminshall return 1; 155832144Sminshall } 155932144Sminshall 156032144Sminshall 156132144Sminshall 156232144Sminshall int 156332144Sminshall tn(argc, argv) 156432144Sminshall int argc; 156532144Sminshall char *argv[]; 156632144Sminshall { 156732144Sminshall register struct hostent *host = 0; 156832144Sminshall struct sockaddr_in sin; 156932144Sminshall struct servent *sp = 0; 157032144Sminshall static char hnamebuf[32]; 157138689Sborman unsigned long temp, inet_addr(); 157237219Sminshall extern char *inet_ntoa(); 157338689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 157438689Sborman char *srp = 0, *strrchr(); 157538689Sborman unsigned long sourceroute(), srlen; 157638689Sborman #endif 157732144Sminshall 157832144Sminshall 157932144Sminshall #if defined(MSDOS) 158032144Sminshall char *cp; 158132144Sminshall #endif /* defined(MSDOS) */ 158232144Sminshall 158332144Sminshall if (connected) { 158432144Sminshall printf("?Already connected to %s\n", hostname); 158532144Sminshall return 0; 158632144Sminshall } 158732144Sminshall if (argc < 2) { 158832144Sminshall (void) strcpy(line, "Connect "); 158932144Sminshall printf("(to) "); 159034849Sminshall (void) gets(&line[strlen(line)]); 159132144Sminshall makeargv(); 159232144Sminshall argc = margc; 159332144Sminshall argv = margv; 159432144Sminshall } 159532144Sminshall if ((argc < 2) || (argc > 3)) { 159632144Sminshall printf("usage: %s host-name [port]\n", argv[0]); 159732144Sminshall return 0; 159832144Sminshall } 159932144Sminshall #if defined(MSDOS) 160032144Sminshall for (cp = argv[1]; *cp; cp++) { 160132144Sminshall if (isupper(*cp)) { 160232144Sminshall *cp = tolower(*cp); 160332144Sminshall } 160432144Sminshall } 160532144Sminshall #endif /* defined(MSDOS) */ 160638689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 160738689Sborman if (argv[1][0] == '@' || argv[1][0] == '!') { 160838689Sborman if ((hostname = strrchr(argv[1], ':')) == NULL) 160938689Sborman hostname = strrchr(argv[1], '@'); 161038689Sborman hostname++; 161138689Sborman srp = 0; 161238689Sborman temp = sourceroute(argv[1], &srp, &srlen); 161338689Sborman if (temp == 0) { 161438689Sborman herror(srp); 161538689Sborman return 0; 161638689Sborman } else if (temp == -1) { 161738689Sborman printf("Bad source route option: %s\n", argv[1]); 161838689Sborman return 0; 161938689Sborman } else { 162038689Sborman sin.sin_addr.s_addr = temp; 162138689Sborman sin.sin_family = AF_INET; 162238689Sborman } 162332144Sminshall } else { 162438689Sborman #endif 162538689Sborman temp = inet_addr(argv[1]); 162638689Sborman if (temp != (unsigned long) -1) { 162738689Sborman sin.sin_addr.s_addr = temp; 162838689Sborman sin.sin_family = AF_INET; 162938689Sborman (void) strcpy(hnamebuf, argv[1]); 163038689Sborman hostname = hnamebuf; 163138689Sborman } else { 163238689Sborman host = gethostbyname(argv[1]); 163338689Sborman if (host) { 163438689Sborman sin.sin_family = host->h_addrtype; 163532144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 163638689Sborman memcpy((caddr_t)&sin.sin_addr, 163732144Sminshall host->h_addr_list[0], host->h_length); 163832144Sminshall #else /* defined(h_addr) */ 163938689Sborman memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); 164032144Sminshall #endif /* defined(h_addr) */ 164138689Sborman hostname = host->h_name; 164238689Sborman } else { 164338689Sborman herror(argv[1]); 164438689Sborman return 0; 164538689Sborman } 164632144Sminshall } 164738689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 164832144Sminshall } 164938689Sborman #endif 165032144Sminshall if (argc == 3) { 165138689Sborman int tmp; 165238689Sborman 165338689Sborman if (*argv[2] == '-') { 165438689Sborman argv[2]++; 165538689Sborman telnetport = 1; 165638689Sborman } else 165738689Sborman telnetport = 0; 165832144Sminshall sin.sin_port = atoi(argv[2]); 165932144Sminshall if (sin.sin_port == 0) { 166032144Sminshall sp = getservbyname(argv[2], "tcp"); 166132144Sminshall if (sp) 166232144Sminshall sin.sin_port = sp->s_port; 166332144Sminshall else { 166432144Sminshall printf("%s: bad port number\n", argv[2]); 166532144Sminshall return 0; 166632144Sminshall } 166732144Sminshall } else { 166834849Sminshall #if !defined(htons) 166934849Sminshall u_short htons(); 167034849Sminshall #endif /* !defined(htons) */ 167132144Sminshall sin.sin_port = htons(sin.sin_port); 167232144Sminshall } 167332144Sminshall } else { 167432144Sminshall if (sp == 0) { 167532144Sminshall sp = getservbyname("telnet", "tcp"); 167632144Sminshall if (sp == 0) { 167734849Sminshall fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); 167832144Sminshall return 0; 167932144Sminshall } 168032144Sminshall sin.sin_port = sp->s_port; 168132144Sminshall } 168232144Sminshall telnetport = 1; 168332144Sminshall } 168437219Sminshall printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); 168532144Sminshall do { 168632144Sminshall net = socket(AF_INET, SOCK_STREAM, 0); 168732144Sminshall if (net < 0) { 168832144Sminshall perror("telnet: socket"); 168932144Sminshall return 0; 169032144Sminshall } 169138689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 169238689Sborman if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) 169338689Sborman perror("setsockopt (IP_OPTIONS)"); 169438689Sborman #endif 169532144Sminshall if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 169632144Sminshall perror("setsockopt (SO_DEBUG)"); 169732144Sminshall } 169832144Sminshall 169932144Sminshall if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { 170032144Sminshall #if defined(h_addr) /* In 4.3, this is a #define */ 170132144Sminshall if (host && host->h_addr_list[1]) { 170232144Sminshall int oerrno = errno; 170332144Sminshall 170432144Sminshall fprintf(stderr, "telnet: connect to address %s: ", 170532144Sminshall inet_ntoa(sin.sin_addr)); 170632144Sminshall errno = oerrno; 170732144Sminshall perror((char *)0); 170832144Sminshall host->h_addr_list++; 170932144Sminshall memcpy((caddr_t)&sin.sin_addr, 171032144Sminshall host->h_addr_list[0], host->h_length); 171132144Sminshall (void) NetClose(net); 171232144Sminshall continue; 171332144Sminshall } 171432144Sminshall #endif /* defined(h_addr) */ 171532144Sminshall perror("telnet: Unable to connect to remote host"); 171632144Sminshall return 0; 171737219Sminshall } 171832144Sminshall connected++; 171932144Sminshall } while (connected == 0); 172038689Sborman cmdrc(argv[1], hostname); 172134849Sminshall (void) call(status, "status", "notmuch", 0); 172232144Sminshall if (setjmp(peerdied) == 0) 172332144Sminshall telnet(); 172434849Sminshall (void) NetClose(net); 172532381Sminshall ExitString("Connection closed by foreign host.\n",1); 172632144Sminshall /*NOTREACHED*/ 172732144Sminshall } 172832144Sminshall 172932144Sminshall 173032144Sminshall #define HELPINDENT (sizeof ("connect")) 173132144Sminshall 173232144Sminshall static char 173332144Sminshall openhelp[] = "connect to a site", 173432144Sminshall closehelp[] = "close current connection", 173532144Sminshall quithelp[] = "exit telnet", 173632144Sminshall statushelp[] = "print status information", 173732144Sminshall helphelp[] = "print help information", 173832144Sminshall sendhelp[] = "transmit special characters ('send ?' for more)", 173932144Sminshall sethelp[] = "set operating parameters ('set ?' for more)", 174038689Sborman unsethelp[] = "unset operating parameters ('unset ?' for more)", 174132144Sminshall togglestring[] ="toggle operating parameters ('toggle ?' for more)", 174238689Sborman slchelp[] = "change state of special charaters ('slc ?' for more)", 174332144Sminshall displayhelp[] = "display operating parameters", 174432144Sminshall #if defined(TN3270) && defined(unix) 174532144Sminshall transcomhelp[] = "specify Unix command for transparent mode pipe", 174632144Sminshall #endif /* defined(TN3270) && defined(unix) */ 174732144Sminshall #if defined(unix) 174832144Sminshall zhelp[] = "suspend telnet", 174932144Sminshall #endif /* defined(unix */ 175032144Sminshall shellhelp[] = "invoke a subshell", 175138689Sborman modestring[] = "try to enter line-by-line or character-at-a-time mode"; 175232144Sminshall 175332144Sminshall extern int help(), shell(); 175432144Sminshall 175532144Sminshall static Command cmdtab[] = { 175638689Sborman { "close", closehelp, bye, 1 }, 175738689Sborman { "display", displayhelp, display, 0 }, 175838689Sborman { "mode", modestring, modecmd, 0 }, 175938689Sborman { "open", openhelp, tn, 0 }, 176038689Sborman { "quit", quithelp, quit, 0 }, 176138689Sborman { "send", sendhelp, sendcmd, 0 }, 176238689Sborman { "set", sethelp, setcmd, 0 }, 176338689Sborman { "unset", unsethelp, unsetcmd, 0 }, 176438689Sborman { "status", statushelp, status, 0 }, 176538689Sborman { "toggle", togglestring, toggle, 0 }, 176638689Sborman { "slc", slchelp, slccmd, 0 }, 176732144Sminshall #if defined(TN3270) && defined(unix) 176838689Sborman { "transcom", transcomhelp, settranscom, 0 }, 176932144Sminshall #endif /* defined(TN3270) && defined(unix) */ 177032144Sminshall #if defined(unix) 177138689Sborman { "z", zhelp, suspend, 0 }, 177232144Sminshall #endif /* defined(unix) */ 177332144Sminshall #if defined(TN3270) 177438689Sborman { "!", shellhelp, shell, 1 }, 177538689Sborman #else 177638689Sborman { "!", shellhelp, shell, 0 }, 177738689Sborman #endif 177838689Sborman { "?", helphelp, help, 0 }, 177932144Sminshall 0 178032144Sminshall }; 178132144Sminshall 178232144Sminshall static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 178332144Sminshall static char escapehelp[] = "deprecated command -- use 'set escape' instead"; 178432144Sminshall 178532144Sminshall static Command cmdtab2[] = { 178638689Sborman { "help", 0, help, 0 }, 178738689Sborman { "escape", escapehelp, setescape, 0 }, 178838689Sborman { "crmod", crmodhelp, togcrmod, 0 }, 178932144Sminshall 0 179032144Sminshall }; 179132144Sminshall 179235298Sminshall 179332144Sminshall /* 179432144Sminshall * Call routine with argc, argv set from args (terminated by 0). 179532144Sminshall */ 179635298Sminshall 179735417Sminshall /*VARARGS1*/ 179832144Sminshall static 179935298Sminshall call(va_alist) 180035298Sminshall va_dcl 180132144Sminshall { 180235298Sminshall va_list ap; 180335298Sminshall typedef int (*intrtn_t)(); 180435298Sminshall intrtn_t routine; 180535298Sminshall char *args[100]; 180635298Sminshall int argno = 0; 180735298Sminshall 180835298Sminshall va_start(ap); 180935298Sminshall routine = (va_arg(ap, intrtn_t)); 181035495Sminshall while ((args[argno++] = va_arg(ap, char *)) != 0) { 181135298Sminshall ; 181235495Sminshall } 181335298Sminshall va_end(ap); 181435495Sminshall return (*routine)(argno-1, args); 181532144Sminshall } 181632144Sminshall 181735298Sminshall 181832144Sminshall static char ** 181932144Sminshall getnextcmd(name) 182032144Sminshall char *name; 182132144Sminshall { 182232144Sminshall Command *c = (Command *) name; 182332144Sminshall 182432144Sminshall return (char **) (c+1); 182532144Sminshall } 182632144Sminshall 182732144Sminshall static Command * 182832144Sminshall getcmd(name) 182932144Sminshall char *name; 183032144Sminshall { 183132144Sminshall Command *cm; 183232144Sminshall 183332144Sminshall if ((cm = (Command *) genget(name, (char **) cmdtab, getnextcmd)) != 0) { 183432144Sminshall return cm; 183532144Sminshall } else { 183632144Sminshall return (Command *) genget(name, (char **) cmdtab2, getnextcmd); 183732144Sminshall } 183832144Sminshall } 183932144Sminshall 184032144Sminshall void 184138689Sborman command(top, tbuf, cnt) 184232144Sminshall int top; 184338689Sborman char *tbuf; 184438689Sborman int cnt; 184532144Sminshall { 184632144Sminshall register Command *c; 184732144Sminshall 184832144Sminshall setcommandmode(); 184932144Sminshall if (!top) { 185032144Sminshall putchar('\n'); 185137219Sminshall #if defined(unix) 185232144Sminshall } else { 185332144Sminshall signal(SIGINT, SIG_DFL); 185432144Sminshall signal(SIGQUIT, SIG_DFL); 185532144Sminshall #endif /* defined(unix) */ 185632144Sminshall } 185732144Sminshall for (;;) { 185832144Sminshall printf("%s> ", prompt); 185938689Sborman if (tbuf) { 186038689Sborman register char *cp; 186138689Sborman cp = line; 186238689Sborman while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 186338689Sborman cnt--; 186438689Sborman tbuf = 0; 186538689Sborman if (cp == line || *--cp != '\n' || cp == line) 186638689Sborman goto getline; 186738689Sborman *cp = '\0'; 186838689Sborman printf("%s\n", line); 186938689Sborman } else { 187038689Sborman getline: 187138689Sborman if (gets(line) == NULL) { 187238689Sborman if (feof(stdin) || ferror(stdin)) 187338689Sborman quit(); 187438689Sborman break; 187538689Sborman } 187632144Sminshall } 187732144Sminshall if (line[0] == 0) 187832144Sminshall break; 187932144Sminshall makeargv(); 188037219Sminshall if (margv[0] == 0) { 188137219Sminshall break; 188237219Sminshall } 188332144Sminshall c = getcmd(margv[0]); 188432144Sminshall if (Ambiguous(c)) { 188532144Sminshall printf("?Ambiguous command\n"); 188632144Sminshall continue; 188732144Sminshall } 188832144Sminshall if (c == 0) { 188932144Sminshall printf("?Invalid command\n"); 189032144Sminshall continue; 189132144Sminshall } 189232144Sminshall if (c->needconnect && !connected) { 189332144Sminshall printf("?Need to be connected first.\n"); 189432144Sminshall continue; 189532144Sminshall } 189632144Sminshall if ((*c->handler)(margc, margv)) { 189732144Sminshall break; 189832144Sminshall } 189932144Sminshall } 190032144Sminshall if (!top) { 190132144Sminshall if (!connected) { 190232144Sminshall longjmp(toplevel, 1); 190332144Sminshall /*NOTREACHED*/ 190432144Sminshall } 190532144Sminshall #if defined(TN3270) 190632144Sminshall if (shell_active == 0) { 190738689Sborman setconnmode(0); 190832144Sminshall } 190932144Sminshall #else /* defined(TN3270) */ 191038689Sborman setconnmode(0); 191132144Sminshall #endif /* defined(TN3270) */ 191232144Sminshall } 191332144Sminshall } 191432144Sminshall 191532144Sminshall /* 191632144Sminshall * Help command. 191732144Sminshall */ 191832144Sminshall static 191932144Sminshall help(argc, argv) 192032144Sminshall int argc; 192132144Sminshall char *argv[]; 192232144Sminshall { 192332144Sminshall register Command *c; 192432144Sminshall 192532144Sminshall if (argc == 1) { 192632144Sminshall printf("Commands may be abbreviated. Commands are:\n\n"); 192732144Sminshall for (c = cmdtab; c->name; c++) 192838689Sborman if (c->help) { 192932144Sminshall printf("%-*s\t%s\n", HELPINDENT, c->name, 193032144Sminshall c->help); 193132144Sminshall } 193232144Sminshall return 0; 193332144Sminshall } 193432144Sminshall while (--argc > 0) { 193532144Sminshall register char *arg; 193632144Sminshall arg = *++argv; 193732144Sminshall c = getcmd(arg); 193832144Sminshall if (Ambiguous(c)) 193932144Sminshall printf("?Ambiguous help command %s\n", arg); 194032144Sminshall else if (c == (Command *)0) 194132144Sminshall printf("?Invalid help command %s\n", arg); 194232144Sminshall else 194332144Sminshall printf("%s\n", c->help); 194432144Sminshall } 194532144Sminshall return 0; 194632144Sminshall } 194738689Sborman 194838689Sborman static char *rcname = 0; 194938689Sborman static char rcbuf[128]; 195038689Sborman 195138689Sborman cmdrc(m1, m2) 195238689Sborman char *m1, *m2; 195338689Sborman { 195438689Sborman register Command *c; 195538689Sborman FILE *rcfile; 195638689Sborman int gotmachine = 0; 195738689Sborman int l1 = strlen(m1); 195838689Sborman int l2 = strlen(m2); 195938689Sborman char m1save[64]; 196038689Sborman 196138689Sborman strcpy(m1save, m1); 196238689Sborman m1 = m1save; 196338689Sborman 196438689Sborman if (rcname == 0) { 196538689Sborman rcname = getenv("HOME"); 196638689Sborman if (rcname) 196738689Sborman strcpy(rcbuf, rcname); 196838689Sborman else 196938689Sborman rcbuf[0] = '\0'; 197038689Sborman strcat(rcbuf, "/.telnetrc"); 197138689Sborman rcname = rcbuf; 197238689Sborman } 197338689Sborman 197438689Sborman if ((rcfile = fopen(rcname, "r")) == 0) { 197538689Sborman return; 197638689Sborman } 197738689Sborman 197838689Sborman for (;;) { 197938689Sborman if (fgets(line, sizeof(line), rcfile) == NULL) 198038689Sborman break; 198138689Sborman if (line[0] == 0) 198238689Sborman break; 198338689Sborman if (line[0] == '#') 198438689Sborman continue; 198538689Sborman if (gotmachine == 0) { 198638689Sborman if (isspace(line[0])) 198738689Sborman continue; 198838689Sborman if (strncasecmp(line, m1, l1) == 0) 198938689Sborman strncpy(line, &line[l1], sizeof(line) - l1); 199038689Sborman else if (strncasecmp(line, m2, l2) == 0) 199138689Sborman strncpy(line, &line[l2], sizeof(line) - l2); 199238689Sborman else 199338689Sborman continue; 199438689Sborman gotmachine = 1; 199538689Sborman } else { 199638689Sborman if (!isspace(line[0])) { 199738689Sborman gotmachine = 0; 199838689Sborman continue; 199938689Sborman } 200038689Sborman } 200138689Sborman makeargv(); 200238689Sborman if (margv[0] == 0) 200338689Sborman continue; 200438689Sborman c = getcmd(margv[0]); 200538689Sborman if (Ambiguous(c)) { 200638689Sborman printf("?Ambiguous command: %s\n", margv[0]); 200738689Sborman continue; 200838689Sborman } 200938689Sborman if (c == 0) { 201038689Sborman printf("?Invalid command: %s\n", margv[0]); 201138689Sborman continue; 201238689Sborman } 201338689Sborman /* 201438689Sborman * This should never happen... 201538689Sborman */ 201638689Sborman if (c->needconnect && !connected) { 201738689Sborman printf("?Need to be connected first for %s.\n", margv[0]); 201838689Sborman continue; 201938689Sborman } 202038689Sborman (*c->handler)(margc, margv); 202138689Sborman } 202238689Sborman fclose(rcfile); 202338689Sborman } 202438689Sborman 202538689Sborman #if defined(SRCRT) && defined(IPPROTO_IP) 202638689Sborman 202738689Sborman /* 202838689Sborman * Source route is handed in as 202938689Sborman * [!]@hop1@hop2...[@|:]dst 203038689Sborman * If the leading ! is present, it is a 203138689Sborman * strict source route, otherwise it is 203238689Sborman * assmed to be a loose source route. 203338689Sborman * 203438689Sborman * We fill in the source route option as 203538689Sborman * hop1,hop2,hop3...dest 203638689Sborman * and return a pointer to hop1, which will 203738689Sborman * be the address to connect() to. 203838689Sborman * 203938689Sborman * Arguments: 204038689Sborman * arg: pointer to route list to decipher 204138689Sborman * 204238689Sborman * cpp: If *cpp is not equal to NULL, this is a 204338689Sborman * pointer to a pointer to a character array 204438689Sborman * that should be filled in with the option. 204538689Sborman * 204638689Sborman * lenp: pointer to an integer that contains the 204738689Sborman * length of *cpp if *cpp != NULL. 204838689Sborman * 204938689Sborman * Return values: 205038689Sborman * 205138689Sborman * Returns the address of the host to connect to. If the 205238689Sborman * return value is -1, there was a syntax error in the 205338689Sborman * option, either unknown characters, or too many hosts. 205438689Sborman * If the return value is 0, one of the hostnames in the 205538689Sborman * path is unknown, and *cpp is set to point to the bad 205638689Sborman * hostname. 205738689Sborman * 205838689Sborman * *cpp: If *cpp was equal to NULL, it will be filled 205938689Sborman * in with a pointer to our static area that has 206038689Sborman * the option filled in. This will be 32bit aligned. 206138689Sborman * 206238689Sborman * *lenp: This will be filled in with how long the option 206338689Sborman * pointed to by *cpp is. 206438689Sborman * 206538689Sborman */ 206638689Sborman unsigned long 206738689Sborman sourceroute(arg, cpp, lenp) 206838689Sborman char *arg; 206938689Sborman char **cpp; 207038689Sborman int *lenp; 207138689Sborman { 207238689Sborman static char lsr[44]; 207338689Sborman char *cp, *cp2, *lsrp, *lsrep, *index(); 207438689Sborman register int tmp; 207538689Sborman struct in_addr sin_addr; 207638689Sborman register struct hostent *host = 0; 207738689Sborman register char c; 207838689Sborman 207938689Sborman /* 208038689Sborman * Verify the arguments, and make sure we have 208138689Sborman * at least 7 bytes for the option. 208238689Sborman */ 208338689Sborman if (cpp == NULL || lenp == NULL) 208438689Sborman return((unsigned long)-1); 208538689Sborman if (*cpp != NULL && *lenp < 7) 208638689Sborman return((unsigned long)-1); 208738689Sborman /* 208838689Sborman * Decide whether we have a buffer passed to us, 208938689Sborman * or if we need to use our own static buffer. 209038689Sborman */ 209138689Sborman if (*cpp) { 209238689Sborman lsrp = *cpp; 209338689Sborman lsrep = lsrp + *lenp; 209438689Sborman } else { 209538689Sborman *cpp = lsrp = lsr; 209638689Sborman lsrep = lsrp + 44; 209738689Sborman } 209838689Sborman 209938689Sborman cp = arg; 210038689Sborman 210138689Sborman /* 210238689Sborman * Next, decide whether we have a loose source 210338689Sborman * route or a strict source route, and fill in 210438689Sborman * the begining of the option. 210538689Sborman */ 210638689Sborman if (*cp == '!') { 210738689Sborman cp++; 210838689Sborman *lsrp++ = IPOPT_SSRR; 210938689Sborman } else 211038689Sborman *lsrp++ = IPOPT_LSRR; 211138689Sborman 211238689Sborman if (*cp != '@') 211338689Sborman return((unsigned long)-1); 211438689Sborman 211538689Sborman lsrp++; /* skip over length, we'll fill it in later */ 211638689Sborman *lsrp++ = 4; 211738689Sborman 211838689Sborman cp++; 211938689Sborman 212038689Sborman sin_addr.s_addr = 0; 212138689Sborman 212238689Sborman for (c = 0;;) { 212338689Sborman if (c == ':') 212438689Sborman cp2 = 0; 212538689Sborman else for (cp2 = cp; c = *cp2; cp2++) { 212638689Sborman if (c == ',') { 212738689Sborman *cp2++ = '\0'; 212838689Sborman if (*cp2 == '@') 212938689Sborman cp2++; 213038689Sborman } else if (c == '@') { 213138689Sborman *cp2++ = '\0'; 213238689Sborman } else if (c == ':') { 213338689Sborman *cp2++ = '\0'; 213438689Sborman } else 213538689Sborman continue; 213638689Sborman break; 213738689Sborman } 213838689Sborman if (!c) 213938689Sborman cp2 = 0; 214038689Sborman 214138689Sborman if ((tmp = inet_addr(cp)) != -1) { 214238689Sborman sin_addr.s_addr = tmp; 214338689Sborman } else if (host = gethostbyname(cp)) { 214438689Sborman #if defined(h_addr) 214538689Sborman memcpy((caddr_t)&sin_addr, 214638689Sborman host->h_addr_list[0], host->h_length); 214738689Sborman #else 214838689Sborman memcpy((caddr_t)&sin_addr, host->h_addr, host->h_length); 214938689Sborman #endif 215038689Sborman } else { 215138689Sborman *cpp = cp; 215238689Sborman return(0); 215338689Sborman } 215438689Sborman memcpy(lsrp, (char *)&sin_addr, 4); 215538689Sborman lsrp += 4; 215638689Sborman if (cp2) 215738689Sborman cp = cp2; 215838689Sborman else 215938689Sborman break; 216038689Sborman /* 216138689Sborman * Check to make sure there is space for next address 216238689Sborman */ 216338689Sborman if (lsrp + 4 > lsrep) 216438689Sborman return((unsigned long)-1); 216538689Sborman } 216638689Sborman if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 216738689Sborman *cpp = 0; 216838689Sborman *lenp = 0; 216938689Sborman return((unsigned long)-1); 217038689Sborman } 217138689Sborman *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 217238689Sborman *lenp = lsrp - *cpp; 217338689Sborman return(sin_addr.s_addr); 217438689Sborman } 217538689Sborman #endif 217638689Sborman 2177*38909Sborman #if defined(NOSTRNCASECMP) 217838689Sborman strncasecmp(p1, p2, len) 217938689Sborman register char *p1, *p2; 218038689Sborman int len; 218138689Sborman { 218238689Sborman while (len--) { 218338689Sborman if (tolower(*p1) != tolower(*p2)) 218438689Sborman return(tolower(*p1) - tolower(*p2)); 218538689Sborman if (*p1 == '\0') 218638689Sborman return(0); 218738689Sborman p1++, p2++; 218838689Sborman } 218938689Sborman return(0); 219038689Sborman } 219138689Sborman #endif 2192