commands.c revision 87155
129088Smarkm/* 229088Smarkm * Copyright (c) 1988, 1990, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3229088Smarkm */ 3329088Smarkm 3487139Smarkm#include <sys/cdefs.h> 3587139Smarkm 3687139Smarkm__FBSDID("$FreeBSD: head/contrib/telnet/telnet/commands.c 87155 2001-11-30 22:28:07Z markm $"); 3787139Smarkm 3829088Smarkm#ifndef lint 3929181Smarkmstatic const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; 4087139Smarkm#endif 4129088Smarkm 4229088Smarkm#include <sys/param.h> 4377095Sdillon#include <sys/un.h> 4429088Smarkm#include <sys/file.h> 4529088Smarkm#include <sys/socket.h> 4629088Smarkm#include <netinet/in.h> 4729088Smarkm 4887139Smarkm#include <ctype.h> 4987139Smarkm#include <err.h> 5087139Smarkm#include <errno.h> 5129088Smarkm#include <netdb.h> 5229088Smarkm#include <pwd.h> 5387139Smarkm#include <signal.h> 5487139Smarkm#include <stdarg.h> 5587139Smarkm#include <stdlib.h> 5687139Smarkm#include <string.h> 5729181Smarkm#include <unistd.h> 5829088Smarkm 5929088Smarkm#include <arpa/telnet.h> 6081965Smarkm#include <arpa/inet.h> 6129088Smarkm 6229088Smarkm#include "general.h" 6329088Smarkm 6429088Smarkm#include "ring.h" 6529088Smarkm 6629088Smarkm#include "externs.h" 6729088Smarkm#include "defines.h" 6829088Smarkm#include "types.h" 6987139Smarkm#include "misc.h" 7029088Smarkm 7187139Smarkm#ifdef AUTHENTICATION 7229181Smarkm#include <libtelnet/auth.h> 7329181Smarkm#endif 7487139Smarkm#ifdef ENCRYPTION 7529181Smarkm#include <libtelnet/encrypt.h> 7629181Smarkm#endif 7729181Smarkm 7829088Smarkm#include <netinet/in_systm.h> 7929088Smarkm#include <netinet/ip.h> 8056668Sshin#include <netinet/ip6.h> 8129088Smarkm 8281965Smarkm#ifndef MAXHOSTNAMELEN 8381965Smarkm#define MAXHOSTNAMELEN 256 8481965Smarkm#endif MAXHOSTNAMELEN 8529088Smarkm 8687139Smarkmtypedef int (*intrtn_t)(int, char **); 8787139Smarkm 8887139Smarkm#ifdef AUTHENTICATION 8987155Smarkmextern int auth_togdebug(int); 9087139Smarkm#endif 9187139Smarkm#ifdef ENCRYPTION 9287155Smarkmextern int EncryptAutoEnc(int); 9387155Smarkmextern int EncryptAutoDec(int); 9487155Smarkmextern int EncryptDebug(int); 9587155Smarkmextern int EncryptVerbose(int); 9687139Smarkm#endif /* ENCRYPTION */ 9729088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 9829088Smarkmint tos = -1; 9929088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 10029088Smarkm 10129088Smarkmchar *hostname; 10229088Smarkmstatic char _hostname[MAXHOSTNAMELEN]; 10329088Smarkm 10487139Smarkmstatic int help(int, char **); 10587139Smarkmstatic int call(intrtn_t, ...); 10687139Smarkmstatic void cmdrc(char *, char *); 10787139Smarkmstatic int switch_af(struct addrinfo **); 10887139Smarkmstatic int togglehelp(void); 10987139Smarkmstatic int send_tncmd(void (*)(int, int), const char *, char *); 11087139Smarkmstatic int setmod(int); 11187139Smarkmstatic int clearmode(int); 11287139Smarkmstatic int modehelp(void); 11387139Smarkmstatic int sourceroute(struct addrinfo *, char *, char **, int *, int *, int *); 11429088Smarkm 11529088Smarkmtypedef struct { 11687139Smarkm const char *name; /* command name */ 11787139Smarkm const char *help; /* help string (NULL for no help) */ 11887139Smarkm int (*handler)(int, char **); /* routine which executes command */ 11929088Smarkm int needconnect; /* Do we need to be connected to execute? */ 12029088Smarkm} Command; 12129088Smarkm 12229088Smarkmstatic char line[256]; 12329088Smarkmstatic char saveline[256]; 12429088Smarkmstatic int margc; 12529088Smarkmstatic char *margv[20]; 12629088Smarkm 12787139Smarkm#ifdef OPIE 12829181Smarkm#include <sys/wait.h> 12981965Smarkm#define PATH_OPIEKEY "/usr/bin/opiekey" 13087139Smarkmstatic int 13187139Smarkmopie_calc(int argc, char *argv[]) 13229181Smarkm{ 13329181Smarkm int status; 13429181Smarkm 13529181Smarkm if(argc != 3) { 13629181Smarkm printf("%s sequence challenge\n", argv[0]); 13787139Smarkm return (0); 13829181Smarkm } 13929181Smarkm 14029181Smarkm switch(fork()) { 14129181Smarkm case 0: 14281965Smarkm execv(PATH_OPIEKEY, argv); 14329181Smarkm exit (1); 14429181Smarkm case -1: 14529181Smarkm perror("fork"); 14629181Smarkm break; 14729181Smarkm default: 14829181Smarkm (void) wait(&status); 14929181Smarkm if (WIFEXITED(status)) 15029181Smarkm return (WEXITSTATUS(status)); 15129181Smarkm } 15287139Smarkm return (0); 15329181Smarkm} 15429181Smarkm#endif 15529181Smarkm 15687139Smarkmstatic void 15787139Smarkmmakeargv(void) 15829088Smarkm{ 15987139Smarkm char *cp, *cp2, c; 16087139Smarkm char **argp = margv; 16129088Smarkm 16229088Smarkm margc = 0; 16329088Smarkm cp = line; 16429088Smarkm if (*cp == '!') { /* Special case shell escape */ 16529088Smarkm strcpy(saveline, line); /* save for shell command */ 16687139Smarkm *argp++ = strdup("!"); /* No room in string to get this */ 16729088Smarkm margc++; 16829088Smarkm cp++; 16929088Smarkm } 17029181Smarkm while ((c = *cp)) { 17187139Smarkm int inquote = 0; 17229088Smarkm while (isspace(c)) 17329088Smarkm c = *++cp; 17429088Smarkm if (c == '\0') 17529088Smarkm break; 17629088Smarkm *argp++ = cp; 17729088Smarkm margc += 1; 17829088Smarkm for (cp2 = cp; c != '\0'; c = *++cp) { 17929088Smarkm if (inquote) { 18029088Smarkm if (c == inquote) { 18129088Smarkm inquote = 0; 18229088Smarkm continue; 18329088Smarkm } 18429088Smarkm } else { 18529088Smarkm if (c == '\\') { 18629088Smarkm if ((c = *++cp) == '\0') 18729088Smarkm break; 18829088Smarkm } else if (c == '"') { 18929088Smarkm inquote = '"'; 19029088Smarkm continue; 19129088Smarkm } else if (c == '\'') { 19229088Smarkm inquote = '\''; 19329088Smarkm continue; 19429088Smarkm } else if (isspace(c)) 19529088Smarkm break; 19629088Smarkm } 19729088Smarkm *cp2++ = c; 19829088Smarkm } 19929088Smarkm *cp2 = '\0'; 20029088Smarkm if (c == '\0') 20129088Smarkm break; 20229088Smarkm cp++; 20329088Smarkm } 20429088Smarkm *argp++ = 0; 20529088Smarkm} 20629088Smarkm 20729088Smarkm/* 20829088Smarkm * Make a character string into a number. 20929088Smarkm * 21029088Smarkm * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 21129088Smarkm */ 21229088Smarkm 21387139Smarkmstatic int 21487139Smarkmspecial(char *s) 21529088Smarkm{ 21687139Smarkm char c; 21729088Smarkm char b; 21829088Smarkm 21929088Smarkm switch (*s) { 22029088Smarkm case '^': 22129088Smarkm b = *++s; 22229088Smarkm if (b == '?') { 22329088Smarkm c = b | 0x40; /* DEL */ 22429088Smarkm } else { 22529088Smarkm c = b & 0x1f; 22629088Smarkm } 22729088Smarkm break; 22829088Smarkm default: 22929088Smarkm c = *s; 23029088Smarkm break; 23129088Smarkm } 23229088Smarkm return c; 23329088Smarkm} 23429088Smarkm 23529088Smarkm/* 23629088Smarkm * Construct a control character sequence 23729088Smarkm * for a special character. 23829088Smarkm */ 23987139Smarkmstatic const char * 24087139Smarkmcontrol(cc_t c) 24129088Smarkm{ 24229088Smarkm static char buf[5]; 24329088Smarkm /* 24429088Smarkm * The only way I could get the Sun 3.5 compiler 24529088Smarkm * to shut up about 24629088Smarkm * if ((unsigned int)c >= 0x80) 24729088Smarkm * was to assign "c" to an unsigned int variable... 24829088Smarkm * Arggg.... 24929088Smarkm */ 25087139Smarkm unsigned int uic = (unsigned int)c; 25129088Smarkm 25229088Smarkm if (uic == 0x7f) 25329088Smarkm return ("^?"); 25429088Smarkm if (c == (cc_t)_POSIX_VDISABLE) { 25529088Smarkm return "off"; 25629088Smarkm } 25729088Smarkm if (uic >= 0x80) { 25829088Smarkm buf[0] = '\\'; 25929088Smarkm buf[1] = ((c>>6)&07) + '0'; 26029088Smarkm buf[2] = ((c>>3)&07) + '0'; 26129088Smarkm buf[3] = (c&07) + '0'; 26229088Smarkm buf[4] = 0; 26329088Smarkm } else if (uic >= 0x20) { 26429088Smarkm buf[0] = c; 26529088Smarkm buf[1] = 0; 26629088Smarkm } else { 26729088Smarkm buf[0] = '^'; 26829088Smarkm buf[1] = '@'+c; 26929088Smarkm buf[2] = 0; 27029088Smarkm } 27129088Smarkm return (buf); 27229088Smarkm} 27329088Smarkm 27429088Smarkm/* 27529088Smarkm * The following are data structures and routines for 27629088Smarkm * the "send" command. 27729088Smarkm * 27829088Smarkm */ 27929088Smarkm 28029088Smarkmstruct sendlist { 28187139Smarkm const char *name; /* How user refers to it (case independent) */ 28287139Smarkm const char *help; /* Help information (0 ==> no help) */ 28329088Smarkm int needconnect; /* Need to be connected */ 28429088Smarkm int narg; /* Number of arguments */ 28587139Smarkm int (*handler)(char *, ...); /* Routine to perform (for special ops) */ 28629088Smarkm int nbyte; /* Number of bytes to send this command */ 28729088Smarkm int what; /* Character to be sent (<0 ==> special) */ 28829088Smarkm}; 28929088Smarkm 29029088Smarkm 29129088Smarkmstatic int 29287155Smarkm send_esc(void), 29387155Smarkm send_help(void), 29487155Smarkm send_docmd(char *), 29587155Smarkm send_dontcmd(char *), 29687155Smarkm send_willcmd(char *), 29787155Smarkm send_wontcmd(char *); 29829088Smarkm 29929088Smarkmstatic struct sendlist Sendlist[] = { 30087139Smarkm { "ao", "Send Telnet Abort output", 1, 0, NULL, 2, AO }, 30187139Smarkm { "ayt", "Send Telnet 'Are You There'", 1, 0, NULL, 2, AYT }, 30287139Smarkm { "brk", "Send Telnet Break", 1, 0, NULL, 2, BREAK }, 30387139Smarkm { "break", NULL, 1, 0, NULL, 2, BREAK }, 30487139Smarkm { "ec", "Send Telnet Erase Character", 1, 0, NULL, 2, EC }, 30587139Smarkm { "el", "Send Telnet Erase Line", 1, 0, NULL, 2, EL }, 30687139Smarkm { "escape", "Send current escape character",1, 0, (int (*)(char *, ...))send_esc, 1, 0 }, 30787139Smarkm { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, NULL, 2, GA }, 30887139Smarkm { "ip", "Send Telnet Interrupt Process",1, 0, NULL, 2, IP }, 30987139Smarkm { "intp", NULL, 1, 0, NULL, 2, IP }, 31087139Smarkm { "interrupt", NULL, 1, 0, NULL, 2, IP }, 31187139Smarkm { "intr", NULL, 1, 0, NULL, 2, IP }, 31287139Smarkm { "nop", "Send Telnet 'No operation'", 1, 0, NULL, 2, NOP }, 31387139Smarkm { "eor", "Send Telnet 'End of Record'", 1, 0, NULL, 2, EOR }, 31487139Smarkm { "abort", "Send Telnet 'Abort Process'", 1, 0, NULL, 2, ABORT }, 31587139Smarkm { "susp", "Send Telnet 'Suspend Process'",1, 0, NULL, 2, SUSP }, 31687139Smarkm { "eof", "Send Telnet End of File Character", 1, 0, NULL, 2, xEOF }, 31787139Smarkm { "synch", "Perform Telnet 'Synch operation'", 1, 0, (int (*)(char *, ...))dosynch, 2, 0 }, 31887139Smarkm { "getstatus", "Send request for STATUS", 1, 0, (int (*)(char *, ...))get_status, 6, 0 }, 31987139Smarkm { "?", "Display send options", 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, 32087139Smarkm { "help", NULL, 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, 32187139Smarkm { "do", NULL, 0, 1, (int (*)(char *, ...))send_docmd, 3, 0 }, 32287139Smarkm { "dont", NULL, 0, 1, (int (*)(char *, ...))send_dontcmd, 3, 0 }, 32387139Smarkm { "will", NULL, 0, 1, (int (*)(char *, ...))send_willcmd, 3, 0 }, 32487139Smarkm { "wont", NULL, 0, 1, (int (*)(char *, ...))send_wontcmd, 3, 0 }, 32587139Smarkm { NULL, NULL, 0, 0, NULL, 0, 0 } 32629088Smarkm}; 32729088Smarkm 32829088Smarkm#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ 32929088Smarkm sizeof(struct sendlist))) 33029088Smarkm 33187139Smarkmstatic int 33287139Smarkmsendcmd(int argc, char *argv[]) 33329088Smarkm{ 33429088Smarkm int count; /* how many bytes we are going to need to send */ 33529088Smarkm int i; 33629088Smarkm struct sendlist *s; /* pointer to current command */ 33729088Smarkm int success = 0; 33829088Smarkm int needconnect = 0; 33929088Smarkm 34029088Smarkm if (argc < 2) { 34129088Smarkm printf("need at least one argument for 'send' command\n"); 34229088Smarkm printf("'send ?' for help\n"); 34329088Smarkm return 0; 34429088Smarkm } 34529088Smarkm /* 34629088Smarkm * First, validate all the send arguments. 34729088Smarkm * In addition, we see how much space we are going to need, and 34829088Smarkm * whether or not we will be doing a "SYNCH" operation (which 34929088Smarkm * flushes the network queue). 35029088Smarkm */ 35129088Smarkm count = 0; 35229088Smarkm for (i = 1; i < argc; i++) { 35329088Smarkm s = GETSEND(argv[i]); 35429088Smarkm if (s == 0) { 35529088Smarkm printf("Unknown send argument '%s'\n'send ?' for help.\n", 35629088Smarkm argv[i]); 35729088Smarkm return 0; 35887139Smarkm } else if (Ambiguous((void *)s)) { 35929088Smarkm printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 36029088Smarkm argv[i]); 36129088Smarkm return 0; 36229088Smarkm } 36329088Smarkm if (i + s->narg >= argc) { 36429088Smarkm fprintf(stderr, 36529088Smarkm "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", 36629088Smarkm s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 36729088Smarkm return 0; 36829088Smarkm } 36929088Smarkm count += s->nbyte; 37087139Smarkm if ((void *)s->handler == (void *)send_help) { 37129088Smarkm send_help(); 37229088Smarkm return 0; 37329088Smarkm } 37429088Smarkm 37529088Smarkm i += s->narg; 37629088Smarkm needconnect += s->needconnect; 37729088Smarkm } 37829088Smarkm if (!connected && needconnect) { 37929088Smarkm printf("?Need to be connected first.\n"); 38029088Smarkm printf("'send ?' for help\n"); 38129088Smarkm return 0; 38229088Smarkm } 38329088Smarkm /* Now, do we have enough room? */ 38429088Smarkm if (NETROOM() < count) { 38529088Smarkm printf("There is not enough room in the buffer TO the network\n"); 38629088Smarkm printf("to process your request. Nothing will be done.\n"); 38729088Smarkm printf("('send synch' will throw away most data in the network\n"); 38829088Smarkm printf("buffer, if this might help.)\n"); 38929088Smarkm return 0; 39029088Smarkm } 39129088Smarkm /* OK, they are all OK, now go through again and actually send */ 39229088Smarkm count = 0; 39329088Smarkm for (i = 1; i < argc; i++) { 39429088Smarkm if ((s = GETSEND(argv[i])) == 0) { 39529088Smarkm fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 39687139Smarkm quit(); 39729088Smarkm /*NOTREACHED*/ 39829088Smarkm } 39929088Smarkm if (s->handler) { 40029088Smarkm count++; 40129088Smarkm success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 40229088Smarkm (s->narg > 1) ? argv[i+2] : 0); 40329088Smarkm i += s->narg; 40429088Smarkm } else { 40529088Smarkm NET2ADD(IAC, s->what); 40629088Smarkm printoption("SENT", IAC, s->what); 40729088Smarkm } 40829088Smarkm } 40929088Smarkm return (count == success); 41029088Smarkm} 41129088Smarkm 41287139Smarkmstatic int 41387139Smarkmsend_esc(void) 41429088Smarkm{ 41529088Smarkm NETADD(escape); 41629088Smarkm return 1; 41729088Smarkm} 41829088Smarkm 41987139Smarkmstatic int 42087139Smarkmsend_docmd(char *name) 42129088Smarkm{ 42229088Smarkm return(send_tncmd(send_do, "do", name)); 42329088Smarkm} 42429088Smarkm 42587139Smarkmstatic int 42629088Smarkmsend_dontcmd(name) 42729088Smarkm char *name; 42829088Smarkm{ 42929088Smarkm return(send_tncmd(send_dont, "dont", name)); 43029088Smarkm} 43187139Smarkm 43287139Smarkmstatic int 43387139Smarkmsend_willcmd(char *name) 43429088Smarkm{ 43529088Smarkm return(send_tncmd(send_will, "will", name)); 43629088Smarkm} 43787139Smarkm 43887139Smarkmstatic int 43987139Smarkmsend_wontcmd(char *name) 44029088Smarkm{ 44129088Smarkm return(send_tncmd(send_wont, "wont", name)); 44229088Smarkm} 44329088Smarkm 44487139Smarkmstatic int 44587139Smarkmsend_tncmd(void (*func)(int, int), const char *cmd, char *name) 44629088Smarkm{ 44729088Smarkm char **cpp; 44829088Smarkm extern char *telopts[]; 44987139Smarkm int val = 0; 45029088Smarkm 45129088Smarkm if (isprefix(name, "help") || isprefix(name, "?")) { 45287139Smarkm int col, len; 45329088Smarkm 45429088Smarkm printf("Usage: send %s <value|option>\n", cmd); 45529088Smarkm printf("\"value\" must be from 0 to 255\n"); 45629088Smarkm printf("Valid options are:\n\t"); 45729088Smarkm 45829088Smarkm col = 8; 45929088Smarkm for (cpp = telopts; *cpp; cpp++) { 46029088Smarkm len = strlen(*cpp) + 3; 46129088Smarkm if (col + len > 65) { 46229088Smarkm printf("\n\t"); 46329088Smarkm col = 8; 46429088Smarkm } 46529088Smarkm printf(" \"%s\"", *cpp); 46629088Smarkm col += len; 46729088Smarkm } 46829088Smarkm printf("\n"); 46929088Smarkm return 0; 47029088Smarkm } 47129088Smarkm cpp = (char **)genget(name, telopts, sizeof(char *)); 47229088Smarkm if (Ambiguous(cpp)) { 47329088Smarkm fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", 47429088Smarkm name, cmd); 47529088Smarkm return 0; 47629088Smarkm } 47729088Smarkm if (cpp) { 47829088Smarkm val = cpp - telopts; 47929088Smarkm } else { 48087139Smarkm char *cp = name; 48129088Smarkm 48229088Smarkm while (*cp >= '0' && *cp <= '9') { 48329088Smarkm val *= 10; 48429088Smarkm val += *cp - '0'; 48529088Smarkm cp++; 48629088Smarkm } 48729088Smarkm if (*cp != 0) { 48829088Smarkm fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 48929088Smarkm name, cmd); 49029088Smarkm return 0; 49129088Smarkm } else if (val < 0 || val > 255) { 49229088Smarkm fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", 49329088Smarkm name, cmd); 49429088Smarkm return 0; 49529088Smarkm } 49629088Smarkm } 49729088Smarkm if (!connected) { 49829088Smarkm printf("?Need to be connected first.\n"); 49929088Smarkm return 0; 50029088Smarkm } 50129088Smarkm (*func)(val, 1); 50229088Smarkm return 1; 50329088Smarkm} 50429088Smarkm 50587139Smarkmstatic int 50687139Smarkmsend_help(void) 50729088Smarkm{ 50829088Smarkm struct sendlist *s; /* pointer to current command */ 50929088Smarkm for (s = Sendlist; s->name; s++) { 51029088Smarkm if (s->help) 51129088Smarkm printf("%-15s %s\n", s->name, s->help); 51229088Smarkm } 51329088Smarkm return(0); 51429088Smarkm} 51529088Smarkm 51629088Smarkm/* 51729088Smarkm * The following are the routines and data structures referred 51829088Smarkm * to by the arguments to the "toggle" command. 51929088Smarkm */ 52029088Smarkm 52187139Smarkmstatic int 52287139Smarkmlclchars(void) 52329088Smarkm{ 52429088Smarkm donelclchars = 1; 52529088Smarkm return 1; 52629088Smarkm} 52729088Smarkm 52887139Smarkmstatic int 52987139Smarkmtogdebug(void) 53029088Smarkm{ 53129088Smarkm#ifndef NOT43 53229088Smarkm if (net > 0 && 53329088Smarkm (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 53429088Smarkm perror("setsockopt (SO_DEBUG)"); 53529088Smarkm } 53629088Smarkm#else /* NOT43 */ 53729088Smarkm if (debug) { 53829181Smarkm if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) 53929088Smarkm perror("setsockopt (SO_DEBUG)"); 54029088Smarkm } else 54129088Smarkm printf("Cannot turn off socket debugging\n"); 54229088Smarkm#endif /* NOT43 */ 54329088Smarkm return 1; 54429088Smarkm} 54529088Smarkm 54629088Smarkm 54787139Smarkmstatic int 54887139Smarkmtogcrlf(void) 54929088Smarkm{ 55029088Smarkm if (crlf) { 55129088Smarkm printf("Will send carriage returns as telnet <CR><LF>.\n"); 55229088Smarkm } else { 55329088Smarkm printf("Will send carriage returns as telnet <CR><NUL>.\n"); 55429088Smarkm } 55529088Smarkm return 1; 55629088Smarkm} 55729088Smarkm 55829088Smarkmint binmode; 55929088Smarkm 56087139Smarkmstatic int 56187139Smarkmtogbinary(int val) 56229088Smarkm{ 56329088Smarkm donebinarytoggle = 1; 56429088Smarkm 56529088Smarkm if (val >= 0) { 56629088Smarkm binmode = val; 56729088Smarkm } else { 56829088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 56929088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 57029088Smarkm binmode = 1; 57129088Smarkm } else if (my_want_state_is_wont(TELOPT_BINARY) && 57229088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 57329088Smarkm binmode = 0; 57429088Smarkm } 57529088Smarkm val = binmode ? 0 : 1; 57629088Smarkm } 57729088Smarkm 57829088Smarkm if (val == 1) { 57929088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 58029088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 58129088Smarkm printf("Already operating in binary mode with remote host.\n"); 58229088Smarkm } else { 58329088Smarkm printf("Negotiating binary mode with remote host.\n"); 58429088Smarkm tel_enter_binary(3); 58529088Smarkm } 58629088Smarkm } else { 58729088Smarkm if (my_want_state_is_wont(TELOPT_BINARY) && 58829088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 58929088Smarkm printf("Already in network ascii mode with remote host.\n"); 59029088Smarkm } else { 59129088Smarkm printf("Negotiating network ascii mode with remote host.\n"); 59229088Smarkm tel_leave_binary(3); 59329088Smarkm } 59429088Smarkm } 59529088Smarkm return 1; 59629088Smarkm} 59729088Smarkm 59887139Smarkmstatic int 59987139Smarkmtogrbinary(int val) 60029088Smarkm{ 60129088Smarkm donebinarytoggle = 1; 60229088Smarkm 60329088Smarkm if (val == -1) 60429088Smarkm val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 60529088Smarkm 60629088Smarkm if (val == 1) { 60729088Smarkm if (my_want_state_is_do(TELOPT_BINARY)) { 60829088Smarkm printf("Already receiving in binary mode.\n"); 60929088Smarkm } else { 61029088Smarkm printf("Negotiating binary mode on input.\n"); 61129088Smarkm tel_enter_binary(1); 61229088Smarkm } 61329088Smarkm } else { 61429088Smarkm if (my_want_state_is_dont(TELOPT_BINARY)) { 61529088Smarkm printf("Already receiving in network ascii mode.\n"); 61629088Smarkm } else { 61729088Smarkm printf("Negotiating network ascii mode on input.\n"); 61829088Smarkm tel_leave_binary(1); 61929088Smarkm } 62029088Smarkm } 62129088Smarkm return 1; 62229088Smarkm} 62329088Smarkm 62487139Smarkmstatic int 62587139Smarkmtogxbinary(int val) 62629088Smarkm{ 62729088Smarkm donebinarytoggle = 1; 62829088Smarkm 62929088Smarkm if (val == -1) 63029088Smarkm val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 63129088Smarkm 63229088Smarkm if (val == 1) { 63329088Smarkm if (my_want_state_is_will(TELOPT_BINARY)) { 63429088Smarkm printf("Already transmitting in binary mode.\n"); 63529088Smarkm } else { 63629088Smarkm printf("Negotiating binary mode on output.\n"); 63729088Smarkm tel_enter_binary(2); 63829088Smarkm } 63929088Smarkm } else { 64029088Smarkm if (my_want_state_is_wont(TELOPT_BINARY)) { 64129088Smarkm printf("Already transmitting in network ascii mode.\n"); 64229088Smarkm } else { 64329088Smarkm printf("Negotiating network ascii mode on output.\n"); 64429088Smarkm tel_leave_binary(2); 64529088Smarkm } 64629088Smarkm } 64729088Smarkm return 1; 64829088Smarkm} 64929088Smarkm 65029088Smarkmstruct togglelist { 65187139Smarkm const char *name; /* name of toggle */ 65287139Smarkm const char *help; /* help message */ 65387139Smarkm int (*handler)(int); /* routine to do actual setting */ 65429088Smarkm int *variable; 65587139Smarkm const char *actionexplanation; 65629088Smarkm}; 65729088Smarkm 65829088Smarkmstatic struct togglelist Togglelist[] = { 65929088Smarkm { "autoflush", 66029088Smarkm "flushing of output when sending interrupt characters", 66129088Smarkm 0, 66229088Smarkm &autoflush, 66329088Smarkm "flush output when sending interrupt characters" }, 66429088Smarkm { "autosynch", 66529088Smarkm "automatic sending of interrupt characters in urgent mode", 66629088Smarkm 0, 66729088Smarkm &autosynch, 66829088Smarkm "send interrupt characters in urgent mode" }, 66987139Smarkm#ifdef AUTHENTICATION 67029088Smarkm { "autologin", 67129088Smarkm "automatic sending of login and/or authentication info", 67229088Smarkm 0, 67329088Smarkm &autologin, 67429088Smarkm "send login name and/or authentication information" }, 67529088Smarkm { "authdebug", 67629088Smarkm "Toggle authentication debugging", 67729088Smarkm auth_togdebug, 67829088Smarkm 0, 67929088Smarkm "print authentication debugging information" }, 68029088Smarkm#endif 68129088Smarkm#ifdef ENCRYPTION 68229088Smarkm { "autoencrypt", 68329088Smarkm "automatic encryption of data stream", 68429088Smarkm EncryptAutoEnc, 68529088Smarkm 0, 68629088Smarkm "automatically encrypt output" }, 68729088Smarkm { "autodecrypt", 68829088Smarkm "automatic decryption of data stream", 68929088Smarkm EncryptAutoDec, 69029088Smarkm 0, 69129088Smarkm "automatically decrypt input" }, 69229088Smarkm { "verbose_encrypt", 69329088Smarkm "Toggle verbose encryption output", 69429088Smarkm EncryptVerbose, 69529088Smarkm 0, 69629088Smarkm "print verbose encryption output" }, 69729088Smarkm { "encdebug", 69829088Smarkm "Toggle encryption debugging", 69929088Smarkm EncryptDebug, 70029088Smarkm 0, 70129088Smarkm "print encryption debugging information" }, 70229088Smarkm#endif /* ENCRYPTION */ 70329088Smarkm { "skiprc", 70429088Smarkm "don't read ~/.telnetrc file", 70529088Smarkm 0, 70629088Smarkm &skiprc, 70729088Smarkm "skip reading of ~/.telnetrc file" }, 70829088Smarkm { "binary", 70929088Smarkm "sending and receiving of binary data", 71029088Smarkm togbinary, 71129088Smarkm 0, 71229088Smarkm 0 }, 71329088Smarkm { "inbinary", 71429088Smarkm "receiving of binary data", 71529088Smarkm togrbinary, 71629088Smarkm 0, 71729088Smarkm 0 }, 71829088Smarkm { "outbinary", 71929088Smarkm "sending of binary data", 72029088Smarkm togxbinary, 72129088Smarkm 0, 72229088Smarkm 0 }, 72329088Smarkm { "crlf", 72429088Smarkm "sending carriage returns as telnet <CR><LF>", 72587139Smarkm (int (*)(int))togcrlf, 72629088Smarkm &crlf, 72729088Smarkm 0 }, 72829088Smarkm { "crmod", 72929088Smarkm "mapping of received carriage returns", 73029088Smarkm 0, 73129088Smarkm &crmod, 73229088Smarkm "map carriage return on output" }, 73329088Smarkm { "localchars", 73429088Smarkm "local recognition of certain control characters", 73587139Smarkm (int (*)(int))lclchars, 73629088Smarkm &localchars, 73729088Smarkm "recognize certain control characters" }, 73887139Smarkm { " ", "", NULL, NULL, NULL }, /* empty line */ 73929088Smarkm { "debug", 74029088Smarkm "debugging", 74187139Smarkm (int (*)(int))togdebug, 74229088Smarkm &debug, 74329088Smarkm "turn on socket level debugging" }, 74429088Smarkm { "netdata", 74529088Smarkm "printing of hexadecimal network data (debugging)", 74629088Smarkm 0, 74729088Smarkm &netdata, 74829088Smarkm "print hexadecimal representation of network traffic" }, 74929088Smarkm { "prettydump", 75029088Smarkm "output of \"netdata\" to user readable format (debugging)", 75129088Smarkm 0, 75229088Smarkm &prettydump, 75329088Smarkm "print user readable output for \"netdata\"" }, 75429088Smarkm { "options", 75529088Smarkm "viewing of options processing (debugging)", 75629088Smarkm 0, 75729088Smarkm &showoptions, 75829088Smarkm "show option processing" }, 75929088Smarkm { "termdata", 76029088Smarkm "(debugging) toggle printing of hexadecimal terminal data", 76129088Smarkm 0, 76229088Smarkm &termdata, 76329088Smarkm "print hexadecimal representation of terminal traffic" }, 76429088Smarkm { "?", 76587139Smarkm NULL, 76687139Smarkm (int (*)(int))togglehelp, 76787139Smarkm NULL, 76887139Smarkm NULL }, 76987139Smarkm { NULL, NULL, NULL, NULL, NULL }, 77029088Smarkm { "help", 77187139Smarkm NULL, 77287139Smarkm (int (*)(int))togglehelp, 77387139Smarkm NULL, 77487139Smarkm NULL }, 77587139Smarkm { NULL, NULL, NULL, NULL, NULL } 77629088Smarkm}; 77729088Smarkm 77887139Smarkmstatic int 77987139Smarkmtogglehelp(void) 78029088Smarkm{ 78129088Smarkm struct togglelist *c; 78229088Smarkm 78329088Smarkm for (c = Togglelist; c->name; c++) { 78429088Smarkm if (c->help) { 78529088Smarkm if (*c->help) 78629088Smarkm printf("%-15s toggle %s\n", c->name, c->help); 78729088Smarkm else 78829088Smarkm printf("\n"); 78929088Smarkm } 79029088Smarkm } 79129088Smarkm printf("\n"); 79229088Smarkm printf("%-15s %s\n", "?", "display help information"); 79329088Smarkm return 0; 79429088Smarkm} 79529088Smarkm 79687139Smarkmstatic void 79787139Smarkmsettogglehelp(int set) 79829088Smarkm{ 79929088Smarkm struct togglelist *c; 80029088Smarkm 80129088Smarkm for (c = Togglelist; c->name; c++) { 80229088Smarkm if (c->help) { 80329088Smarkm if (*c->help) 80429088Smarkm printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 80529088Smarkm c->help); 80629088Smarkm else 80729088Smarkm printf("\n"); 80829088Smarkm } 80929088Smarkm } 81029088Smarkm} 81129088Smarkm 81229088Smarkm#define GETTOGGLE(name) (struct togglelist *) \ 81329088Smarkm genget(name, (char **) Togglelist, sizeof(struct togglelist)) 81429088Smarkm 81587139Smarkmstatic int 81687139Smarkmtoggle(int argc, char *argv[]) 81729088Smarkm{ 81829088Smarkm int retval = 1; 81929088Smarkm char *name; 82029088Smarkm struct togglelist *c; 82129088Smarkm 82229088Smarkm if (argc < 2) { 82329088Smarkm fprintf(stderr, 82429088Smarkm "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 82529088Smarkm return 0; 82629088Smarkm } 82729088Smarkm argc--; 82829088Smarkm argv++; 82929088Smarkm while (argc--) { 83029088Smarkm name = *argv++; 83129088Smarkm c = GETTOGGLE(name); 83287139Smarkm if (Ambiguous((void *)c)) { 83329088Smarkm fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 83429088Smarkm name); 83529088Smarkm return 0; 83629088Smarkm } else if (c == 0) { 83729088Smarkm fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 83829088Smarkm name); 83929088Smarkm return 0; 84029088Smarkm } else { 84129088Smarkm if (c->variable) { 84229088Smarkm *c->variable = !*c->variable; /* invert it */ 84329088Smarkm if (c->actionexplanation) { 84429088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 84529088Smarkm c->actionexplanation); 84629088Smarkm } 84729088Smarkm } 84829088Smarkm if (c->handler) { 84929088Smarkm retval &= (*c->handler)(-1); 85029088Smarkm } 85129088Smarkm } 85229088Smarkm } 85329088Smarkm return retval; 85429088Smarkm} 85529088Smarkm 85629088Smarkm/* 85729088Smarkm * The following perform the "set" command. 85829088Smarkm */ 85929088Smarkm 86029088Smarkm#ifdef USE_TERMIO 86187139Smarkmstruct termio new_tc = { 0, 0, 0, 0, {}, 0, 0 }; 86229088Smarkm#endif 86329088Smarkm 86429088Smarkmstruct setlist { 86587139Smarkm const char *name; /* name */ 86687139Smarkm const char *help; /* help information */ 86787139Smarkm void (*handler)(char *); 86829088Smarkm cc_t *charp; /* where it is located at */ 86929088Smarkm}; 87029088Smarkm 87129088Smarkmstatic struct setlist Setlist[] = { 87229088Smarkm#ifdef KLUDGELINEMODE 87387139Smarkm { "echo", "character to toggle local echoing on/off", NULL, &echoc }, 87429088Smarkm#endif 87587139Smarkm { "escape", "character to escape back to telnet command mode", NULL, &escape }, 87629088Smarkm { "rlogin", "rlogin escape character", 0, &rlogin }, 87729088Smarkm { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, 87887139Smarkm { " ", "", NULL, NULL }, 87987139Smarkm { " ", "The following need 'localchars' to be toggled true", NULL, NULL }, 88087139Smarkm { "flushoutput", "character to cause an Abort Output", NULL, termFlushCharp }, 88187139Smarkm { "interrupt", "character to cause an Interrupt Process", NULL, termIntCharp }, 88287139Smarkm { "quit", "character to cause an Abort process", NULL, termQuitCharp }, 88387139Smarkm { "eof", "character to cause an EOF ", NULL, termEofCharp }, 88487139Smarkm { " ", "", NULL, NULL }, 88587139Smarkm { " ", "The following are for local editing in linemode", NULL, NULL }, 88687139Smarkm { "erase", "character to use to erase a character", NULL, termEraseCharp }, 88787139Smarkm { "kill", "character to use to erase a line", NULL, termKillCharp }, 88887139Smarkm { "lnext", "character to use for literal next", NULL, termLiteralNextCharp }, 88987139Smarkm { "susp", "character to cause a Suspend Process", NULL, termSuspCharp }, 89087139Smarkm { "reprint", "character to use for line reprint", NULL, termRprntCharp }, 89187139Smarkm { "worderase", "character to use to erase a word", NULL, termWerasCharp }, 89287139Smarkm { "start", "character to use for XON", NULL, termStartCharp }, 89387139Smarkm { "stop", "character to use for XOFF", NULL, termStopCharp }, 89487139Smarkm { "forw1", "alternate end of line character", NULL, termForw1Charp }, 89587139Smarkm { "forw2", "alternate end of line character", NULL, termForw2Charp }, 89687139Smarkm { "ayt", "alternate AYT character", NULL, termAytCharp }, 89787139Smarkm { NULL, NULL, NULL, NULL } 89829088Smarkm}; 89929088Smarkm 90087139Smarkmstatic struct setlist * 90187139Smarkmgetset(char *name) 90229088Smarkm{ 90329088Smarkm return (struct setlist *) 90429088Smarkm genget(name, (char **) Setlist, sizeof(struct setlist)); 90529088Smarkm} 90629088Smarkm 90787139Smarkmvoid 90887139Smarkmset_escape_char(char *s) 90929088Smarkm{ 91029088Smarkm if (rlogin != _POSIX_VDISABLE) { 91129088Smarkm rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 91229088Smarkm printf("Telnet rlogin escape character is '%s'.\n", 91329088Smarkm control(rlogin)); 91429088Smarkm } else { 91529088Smarkm escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 91629088Smarkm printf("Telnet escape character is '%s'.\n", control(escape)); 91729088Smarkm } 91829088Smarkm} 91929088Smarkm 92087139Smarkmstatic int 92187139Smarkmsetcmd(int argc, char *argv[]) 92229088Smarkm{ 92329088Smarkm int value; 92429088Smarkm struct setlist *ct; 92529088Smarkm struct togglelist *c; 92629088Smarkm 92729088Smarkm if (argc < 2 || argc > 3) { 92829088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 92929088Smarkm return 0; 93029088Smarkm } 93129088Smarkm if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 93229088Smarkm for (ct = Setlist; ct->name; ct++) 93329088Smarkm printf("%-15s %s\n", ct->name, ct->help); 93429088Smarkm printf("\n"); 93529088Smarkm settogglehelp(1); 93629088Smarkm printf("%-15s %s\n", "?", "display help information"); 93729088Smarkm return 0; 93829088Smarkm } 93929088Smarkm 94029088Smarkm ct = getset(argv[1]); 94129088Smarkm if (ct == 0) { 94229088Smarkm c = GETTOGGLE(argv[1]); 94329088Smarkm if (c == 0) { 94429088Smarkm fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 94529088Smarkm argv[1]); 94629088Smarkm return 0; 94787139Smarkm } else if (Ambiguous((void *)c)) { 94829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 94929088Smarkm argv[1]); 95029088Smarkm return 0; 95129088Smarkm } 95229088Smarkm if (c->variable) { 95329088Smarkm if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 95429088Smarkm *c->variable = 1; 95529088Smarkm else if (strcmp("off", argv[2]) == 0) 95629088Smarkm *c->variable = 0; 95729088Smarkm else { 95829088Smarkm printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 95929088Smarkm return 0; 96029088Smarkm } 96129088Smarkm if (c->actionexplanation) { 96229088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 96329088Smarkm c->actionexplanation); 96429088Smarkm } 96529088Smarkm } 96629088Smarkm if (c->handler) 96729088Smarkm (*c->handler)(1); 96829088Smarkm } else if (argc != 3) { 96929088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 97029088Smarkm return 0; 97187139Smarkm } else if (Ambiguous((void *)ct)) { 97229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 97329088Smarkm argv[1]); 97429088Smarkm return 0; 97529088Smarkm } else if (ct->handler) { 97629088Smarkm (*ct->handler)(argv[2]); 97729088Smarkm printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 97829088Smarkm } else { 97929088Smarkm if (strcmp("off", argv[2])) { 98029088Smarkm value = special(argv[2]); 98129088Smarkm } else { 98229088Smarkm value = _POSIX_VDISABLE; 98329088Smarkm } 98429088Smarkm *(ct->charp) = (cc_t)value; 98529088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 98629088Smarkm } 98729088Smarkm slc_check(); 98829088Smarkm return 1; 98929088Smarkm} 99029088Smarkm 99187139Smarkmstatic int 99287139Smarkmunsetcmd(int argc, char *argv[]) 99329088Smarkm{ 99429088Smarkm struct setlist *ct; 99529088Smarkm struct togglelist *c; 99687139Smarkm char *name; 99729088Smarkm 99829088Smarkm if (argc < 2) { 99929088Smarkm fprintf(stderr, 100029088Smarkm "Need an argument to 'unset' command. 'unset ?' for help.\n"); 100129088Smarkm return 0; 100229088Smarkm } 100329088Smarkm if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 100429088Smarkm for (ct = Setlist; ct->name; ct++) 100529088Smarkm printf("%-15s %s\n", ct->name, ct->help); 100629088Smarkm printf("\n"); 100729088Smarkm settogglehelp(0); 100829088Smarkm printf("%-15s %s\n", "?", "display help information"); 100929088Smarkm return 0; 101029088Smarkm } 101129088Smarkm 101229088Smarkm argc--; 101329088Smarkm argv++; 101429088Smarkm while (argc--) { 101529088Smarkm name = *argv++; 101629088Smarkm ct = getset(name); 101729088Smarkm if (ct == 0) { 101829088Smarkm c = GETTOGGLE(name); 101929088Smarkm if (c == 0) { 102029088Smarkm fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 102129088Smarkm name); 102229088Smarkm return 0; 102387139Smarkm } else if (Ambiguous((void *)c)) { 102429088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 102529088Smarkm name); 102629088Smarkm return 0; 102729088Smarkm } 102829088Smarkm if (c->variable) { 102929088Smarkm *c->variable = 0; 103029088Smarkm if (c->actionexplanation) { 103129088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 103229088Smarkm c->actionexplanation); 103329088Smarkm } 103429088Smarkm } 103529088Smarkm if (c->handler) 103629088Smarkm (*c->handler)(0); 103787139Smarkm } else if (Ambiguous((void *)ct)) { 103829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 103929088Smarkm name); 104029088Smarkm return 0; 104129088Smarkm } else if (ct->handler) { 104229088Smarkm (*ct->handler)(0); 104329088Smarkm printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 104429088Smarkm } else { 104529088Smarkm *(ct->charp) = _POSIX_VDISABLE; 104629088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 104729088Smarkm } 104829088Smarkm } 104929088Smarkm return 1; 105029088Smarkm} 105129088Smarkm 105229088Smarkm/* 105329088Smarkm * The following are the data structures and routines for the 105429088Smarkm * 'mode' command. 105529088Smarkm */ 105629088Smarkm#ifdef KLUDGELINEMODE 105729088Smarkmextern int kludgelinemode; 105829088Smarkm 105987139Smarkmstatic int 106087139Smarkmdokludgemode(void) 106129088Smarkm{ 106229088Smarkm kludgelinemode = 1; 106329088Smarkm send_wont(TELOPT_LINEMODE, 1); 106429088Smarkm send_dont(TELOPT_SGA, 1); 106529088Smarkm send_dont(TELOPT_ECHO, 1); 106649861Snsayer return 1; 106729088Smarkm} 106829088Smarkm#endif 106929088Smarkm 107087139Smarkmstatic int 107187139Smarkmdolinemode(void) 107229088Smarkm{ 107329088Smarkm#ifdef KLUDGELINEMODE 107429088Smarkm if (kludgelinemode) 107529088Smarkm send_dont(TELOPT_SGA, 1); 107629088Smarkm#endif 107729088Smarkm send_will(TELOPT_LINEMODE, 1); 107829088Smarkm send_dont(TELOPT_ECHO, 1); 107929088Smarkm return 1; 108029088Smarkm} 108129088Smarkm 108287139Smarkmstatic int 108387139Smarkmdocharmode(void) 108429088Smarkm{ 108529088Smarkm#ifdef KLUDGELINEMODE 108629088Smarkm if (kludgelinemode) 108729088Smarkm send_do(TELOPT_SGA, 1); 108829088Smarkm else 108929088Smarkm#endif 109029088Smarkm send_wont(TELOPT_LINEMODE, 1); 109129088Smarkm send_do(TELOPT_ECHO, 1); 109229088Smarkm return 1; 109329088Smarkm} 109429088Smarkm 109587139Smarkmstatic int 109687139Smarkmdolmmode(int bit, int on) 109729088Smarkm{ 109829088Smarkm unsigned char c; 109929088Smarkm extern int linemode; 110029088Smarkm 110129088Smarkm if (my_want_state_is_wont(TELOPT_LINEMODE)) { 110229088Smarkm printf("?Need to have LINEMODE option enabled first.\n"); 110329088Smarkm printf("'mode ?' for help.\n"); 110429088Smarkm return 0; 110529088Smarkm } 110629088Smarkm 110729088Smarkm if (on) 110829088Smarkm c = (linemode | bit); 110929088Smarkm else 111029088Smarkm c = (linemode & ~bit); 111129088Smarkm lm_mode(&c, 1, 1); 111229088Smarkm return 1; 111329088Smarkm} 111429088Smarkm 111587139Smarkmstatic int 111687139Smarkmsetmod(int bit) 111729088Smarkm{ 111829088Smarkm return dolmmode(bit, 1); 111929088Smarkm} 112029088Smarkm 112187139Smarkmstatic int 112287139Smarkmclearmode(int bit) 112329088Smarkm{ 112429088Smarkm return dolmmode(bit, 0); 112529088Smarkm} 112629088Smarkm 112729088Smarkmstruct modelist { 112887139Smarkm const char *name; /* command name */ 112987139Smarkm const char *help; /* help string */ 113087139Smarkm int (*handler)(int);/* routine which executes command */ 113129088Smarkm int needconnect; /* Do we need to be connected to execute? */ 113229088Smarkm int arg1; 113329088Smarkm}; 113429088Smarkm 113529088Smarkmstatic struct modelist ModeList[] = { 113687139Smarkm { "character", "Disable LINEMODE option", (int (*)(int))docharmode, 1, 0 }, 113729088Smarkm#ifdef KLUDGELINEMODE 113887139Smarkm { "", "(or disable obsolete line-by-line mode)", NULL, 0, 0 }, 113929088Smarkm#endif 114087139Smarkm { "line", "Enable LINEMODE option", (int (*)(int))dolinemode, 1, 0 }, 114129088Smarkm#ifdef KLUDGELINEMODE 114287139Smarkm { "", "(or enable obsolete line-by-line mode)", NULL, 0, 0 }, 114329088Smarkm#endif 114487139Smarkm { "", "", NULL, 0, 0 }, 114587139Smarkm { "", "These require the LINEMODE option to be enabled", NULL, 0, 0 }, 114629181Smarkm { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, 114729181Smarkm { "+isig", 0, setmod, 1, MODE_TRAPSIG }, 114829088Smarkm { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 114929181Smarkm { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, 115029181Smarkm { "+edit", 0, setmod, 1, MODE_EDIT }, 115129088Smarkm { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 115229181Smarkm { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, 115329181Smarkm { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, 115429088Smarkm { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 115529181Smarkm { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, 115629181Smarkm { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, 115729088Smarkm { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 115887139Smarkm { "help", 0, (int (*)(int))modehelp, 0, 0 }, 115929088Smarkm#ifdef KLUDGELINEMODE 116087139Smarkm { "kludgeline", 0, (int (*)(int))dokludgemode, 1, 0 }, 116129088Smarkm#endif 116287139Smarkm { "", "", NULL, 0, 0 }, 116387139Smarkm { "?", "Print help information", (int (*)(int))modehelp, 0, 0 }, 116487139Smarkm { NULL, NULL, NULL, 0, 0 }, 116529088Smarkm}; 116629088Smarkm 116729088Smarkm 116887139Smarkmstatic int 116987139Smarkmmodehelp(void) 117029088Smarkm{ 117129088Smarkm struct modelist *mt; 117229088Smarkm 117329088Smarkm printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 117429088Smarkm for (mt = ModeList; mt->name; mt++) { 117529088Smarkm if (mt->help) { 117629088Smarkm if (*mt->help) 117729088Smarkm printf("%-15s %s\n", mt->name, mt->help); 117829088Smarkm else 117929088Smarkm printf("\n"); 118029088Smarkm } 118129088Smarkm } 118229088Smarkm return 0; 118329088Smarkm} 118429088Smarkm 118529088Smarkm#define GETMODECMD(name) (struct modelist *) \ 118629088Smarkm genget(name, (char **) ModeList, sizeof(struct modelist)) 118729088Smarkm 118887139Smarkmstatic int 118987139Smarkmmodecmd(int argc, char *argv[]) 119029088Smarkm{ 119129088Smarkm struct modelist *mt; 119229088Smarkm 119329088Smarkm if (argc != 2) { 119429088Smarkm printf("'mode' command requires an argument\n"); 119529088Smarkm printf("'mode ?' for help.\n"); 119629088Smarkm } else if ((mt = GETMODECMD(argv[1])) == 0) { 119729088Smarkm fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 119887139Smarkm } else if (Ambiguous((void *)mt)) { 119929088Smarkm fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 120029088Smarkm } else if (mt->needconnect && !connected) { 120129088Smarkm printf("?Need to be connected first.\n"); 120229088Smarkm printf("'mode ?' for help.\n"); 120329088Smarkm } else if (mt->handler) { 120429088Smarkm return (*mt->handler)(mt->arg1); 120529088Smarkm } 120629088Smarkm return 0; 120729088Smarkm} 120829088Smarkm 120929088Smarkm/* 121029088Smarkm * The following data structures and routines implement the 121129088Smarkm * "display" command. 121229088Smarkm */ 121329088Smarkm 121487139Smarkmstatic int 121587139Smarkmdisplay(int argc, char *argv[]) 121629088Smarkm{ 121729088Smarkm struct togglelist *tl; 121829088Smarkm struct setlist *sl; 121929088Smarkm 122029088Smarkm#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 122129088Smarkm if (*tl->variable) { \ 122229088Smarkm printf("will"); \ 122329088Smarkm } else { \ 122429088Smarkm printf("won't"); \ 122529088Smarkm } \ 122629088Smarkm printf(" %s.\n", tl->actionexplanation); \ 122729088Smarkm } 122829088Smarkm 122929088Smarkm#define doset(sl) if (sl->name && *sl->name != ' ') { \ 123029088Smarkm if (sl->handler == 0) \ 123129088Smarkm printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 123229088Smarkm else \ 123329088Smarkm printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 123429088Smarkm } 123529088Smarkm 123629088Smarkm if (argc == 1) { 123729088Smarkm for (tl = Togglelist; tl->name; tl++) { 123829088Smarkm dotog(tl); 123929088Smarkm } 124029088Smarkm printf("\n"); 124129088Smarkm for (sl = Setlist; sl->name; sl++) { 124229088Smarkm doset(sl); 124329088Smarkm } 124429088Smarkm } else { 124529088Smarkm int i; 124629088Smarkm 124729088Smarkm for (i = 1; i < argc; i++) { 124829088Smarkm sl = getset(argv[i]); 124929088Smarkm tl = GETTOGGLE(argv[i]); 125087139Smarkm if (Ambiguous((void *)sl) || Ambiguous((void *)tl)) { 125129088Smarkm printf("?Ambiguous argument '%s'.\n", argv[i]); 125229088Smarkm return 0; 125329088Smarkm } else if (!sl && !tl) { 125429088Smarkm printf("?Unknown argument '%s'.\n", argv[i]); 125529088Smarkm return 0; 125629088Smarkm } else { 125729088Smarkm if (tl) { 125829088Smarkm dotog(tl); 125929088Smarkm } 126029088Smarkm if (sl) { 126129088Smarkm doset(sl); 126229088Smarkm } 126329088Smarkm } 126429088Smarkm } 126529088Smarkm } 126629088Smarkm/*@*/optionstatus(); 126729088Smarkm#ifdef ENCRYPTION 126829088Smarkm EncryptStatus(); 126929088Smarkm#endif /* ENCRYPTION */ 127029088Smarkm return 1; 127129088Smarkm#undef doset 127229088Smarkm#undef dotog 127329088Smarkm} 127429088Smarkm 127529088Smarkm/* 127629088Smarkm * The following are the data structures, and many of the routines, 127729088Smarkm * relating to command processing. 127829088Smarkm */ 127929088Smarkm 128029088Smarkm/* 128129088Smarkm * Set the escape character. 128229088Smarkm */ 128387139Smarkmstatic int 128487139Smarkmsetescape(int argc, char *argv[]) 128529088Smarkm{ 128687139Smarkm char *arg; 128729088Smarkm char buf[50]; 128829088Smarkm 128929088Smarkm printf( 129029088Smarkm "Deprecated usage - please use 'set escape%s%s' in the future.\n", 129129088Smarkm (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 129229088Smarkm if (argc > 2) 129329088Smarkm arg = argv[1]; 129429088Smarkm else { 129529088Smarkm printf("new escape character: "); 129629088Smarkm (void) fgets(buf, sizeof(buf), stdin); 129729088Smarkm arg = buf; 129829088Smarkm } 129929088Smarkm if (arg[0] != '\0') 130029088Smarkm escape = arg[0]; 130129088Smarkm (void) fflush(stdout); 130229088Smarkm return 1; 130329088Smarkm} 130429088Smarkm 130587139Smarkmstatic int 130687139Smarkmtogcrmod(void) 130729088Smarkm{ 130829088Smarkm crmod = !crmod; 130929088Smarkm printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 131029088Smarkm printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 131129088Smarkm (void) fflush(stdout); 131229088Smarkm return 1; 131329088Smarkm} 131429088Smarkm 131587139Smarkmstatic int 131687139Smarkmsuspend(void) 131729088Smarkm{ 131829088Smarkm#ifdef SIGTSTP 131929088Smarkm setcommandmode(); 132029088Smarkm { 132187139Smarkm long oldrows, oldcols, newrows, newcols, err_; 132229088Smarkm 132387139Smarkm err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 132429088Smarkm (void) kill(0, SIGTSTP); 132529088Smarkm /* 132629088Smarkm * If we didn't get the window size before the SUSPEND, but we 132729088Smarkm * can get them now (?), then send the NAWS to make sure that 132829088Smarkm * we are set up for the right window size. 132929088Smarkm */ 133029088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 133187139Smarkm (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { 133229088Smarkm sendnaws(); 133329088Smarkm } 133429088Smarkm } 133529088Smarkm /* reget parameters in case they were changed */ 133629088Smarkm TerminalSaveState(); 133729088Smarkm setconnmode(0); 133829088Smarkm#else 133929088Smarkm printf("Suspend is not supported. Try the '!' command instead\n"); 134029088Smarkm#endif 134129088Smarkm return 1; 134229088Smarkm} 134329088Smarkm 134487139Smarkmstatic int 134587139Smarkmshell(int argc, char *argv[] __unused) 134629088Smarkm{ 134787139Smarkm long oldrows, oldcols, newrows, newcols, err_; 134829088Smarkm 134929088Smarkm setcommandmode(); 135029088Smarkm 135187139Smarkm err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 135229088Smarkm switch(vfork()) { 135329088Smarkm case -1: 135429088Smarkm perror("Fork failed\n"); 135529088Smarkm break; 135629088Smarkm 135729088Smarkm case 0: 135829088Smarkm { 135929088Smarkm /* 136029088Smarkm * Fire up the shell in the child. 136129088Smarkm */ 136287139Smarkm const char *shellp, *shellname; 136329088Smarkm 136429088Smarkm shellp = getenv("SHELL"); 136529088Smarkm if (shellp == NULL) 136629088Smarkm shellp = "/bin/sh"; 136729088Smarkm if ((shellname = strrchr(shellp, '/')) == 0) 136829088Smarkm shellname = shellp; 136929088Smarkm else 137029088Smarkm shellname++; 137129088Smarkm if (argc > 1) 137281965Smarkm execl(shellp, shellname, "-c", &saveline[1], (char *)0); 137329088Smarkm else 137481965Smarkm execl(shellp, shellname, (char *)0); 137529088Smarkm perror("Execl"); 137629088Smarkm _exit(1); 137729088Smarkm } 137829088Smarkm default: 137929088Smarkm (void)wait((int *)0); /* Wait for the shell to complete */ 138029088Smarkm 138129088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 138287139Smarkm (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { 138329088Smarkm sendnaws(); 138429088Smarkm } 138529088Smarkm break; 138629088Smarkm } 138729088Smarkm return 1; 138829088Smarkm} 138929088Smarkm 139087139Smarkmstatic int 139187139Smarkmbye(int argc, char *argv[]) 139229088Smarkm{ 139329088Smarkm extern int resettermname; 139429088Smarkm 139529088Smarkm if (connected) { 139629088Smarkm (void) shutdown(net, 2); 139729088Smarkm printf("Connection closed.\n"); 139829088Smarkm (void) NetClose(net); 139929088Smarkm connected = 0; 140029088Smarkm resettermname = 1; 140187139Smarkm#ifdef AUTHENTICATION 140287139Smarkm#ifdef ENCRYPTION 140329088Smarkm auth_encrypt_connect(connected); 140487139Smarkm#endif 140587139Smarkm#endif 140629088Smarkm /* reset options */ 140729088Smarkm tninit(); 140829088Smarkm } 140929088Smarkm if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 141029088Smarkm longjmp(toplevel, 1); 141129088Smarkm /* NOTREACHED */ 141229088Smarkm } 141329088Smarkm return 1; /* Keep lint, etc., happy */ 141429088Smarkm} 141529088Smarkm 141687139Smarkmvoid 141787139Smarkmquit(void) 141829088Smarkm{ 141929088Smarkm (void) call(bye, "bye", "fromquit", 0); 142029088Smarkm Exit(0); 142129088Smarkm} 142229088Smarkm 142387139Smarkmstatic int 142487139Smarkmlogout(void) 142529088Smarkm{ 142629088Smarkm send_do(TELOPT_LOGOUT, 1); 142729088Smarkm (void) netflush(); 142829088Smarkm return 1; 142929088Smarkm} 143029088Smarkm 143129088Smarkm 143229088Smarkm/* 143329088Smarkm * The SLC command. 143429088Smarkm */ 143529088Smarkm 143629088Smarkmstruct slclist { 143787139Smarkm const char *name; 143887139Smarkm const char *help; 143987139Smarkm void (*handler)(int); 144029088Smarkm int arg; 144129088Smarkm}; 144229088Smarkm 144387139Smarkmstatic void slc_help(void); 144429088Smarkm 144529088Smarkmstruct slclist SlcList[] = { 144629088Smarkm { "export", "Use local special character definitions", 144787139Smarkm (void (*)(int))slc_mode_export, 0 }, 144829088Smarkm { "import", "Use remote special character definitions", 144929088Smarkm slc_mode_import, 1 }, 145029088Smarkm { "check", "Verify remote special character definitions", 145129088Smarkm slc_mode_import, 0 }, 145287139Smarkm { "help", NULL, (void (*)(int))slc_help, 0 }, 145387139Smarkm { "?", "Print help information", (void (*)(int))slc_help, 0 }, 145487139Smarkm { NULL, NULL, NULL, 0 }, 145529088Smarkm}; 145629088Smarkm 145787139Smarkmstatic void 145887139Smarkmslc_help(void) 145929088Smarkm{ 146029088Smarkm struct slclist *c; 146129088Smarkm 146229088Smarkm for (c = SlcList; c->name; c++) { 146329088Smarkm if (c->help) { 146429088Smarkm if (*c->help) 146529088Smarkm printf("%-15s %s\n", c->name, c->help); 146629088Smarkm else 146729088Smarkm printf("\n"); 146829088Smarkm } 146929088Smarkm } 147029088Smarkm} 147129088Smarkm 147287139Smarkmstatic struct slclist * 147387139Smarkmgetslc(char *name) 147429088Smarkm{ 147529088Smarkm return (struct slclist *) 147629088Smarkm genget(name, (char **) SlcList, sizeof(struct slclist)); 147729088Smarkm} 147829088Smarkm 147987139Smarkmstatic int 148087139Smarkmslccmd(int argc, char *argv[]) 148129088Smarkm{ 148229088Smarkm struct slclist *c; 148329088Smarkm 148429088Smarkm if (argc != 2) { 148529088Smarkm fprintf(stderr, 148629088Smarkm "Need an argument to 'slc' command. 'slc ?' for help.\n"); 148729088Smarkm return 0; 148829088Smarkm } 148929088Smarkm c = getslc(argv[1]); 149029088Smarkm if (c == 0) { 149129088Smarkm fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 149229088Smarkm argv[1]); 149329088Smarkm return 0; 149429088Smarkm } 149587139Smarkm if (Ambiguous((void *)c)) { 149629088Smarkm fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 149729088Smarkm argv[1]); 149829088Smarkm return 0; 149929088Smarkm } 150029088Smarkm (*c->handler)(c->arg); 150129088Smarkm slcstate(); 150229088Smarkm return 1; 150329088Smarkm} 150429088Smarkm 150529088Smarkm/* 150629088Smarkm * The ENVIRON command. 150729088Smarkm */ 150829088Smarkm 150929088Smarkmstruct envlist { 151087139Smarkm const char *name; 151187139Smarkm const char *help; 151287139Smarkm void (*handler)(unsigned char *, unsigned char *); 151329088Smarkm int narg; 151429088Smarkm}; 151529088Smarkm 151629088Smarkmextern struct env_lst * 151787155Smarkm env_define(const unsigned char *, unsigned char *); 151829088Smarkmextern void 151987155Smarkm env_undefine(unsigned char *), 152087155Smarkm env_export(const unsigned char *), 152187155Smarkm env_unexport(const unsigned char *), 152287155Smarkm env_send(unsigned char *), 152329088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 152487155Smarkm env_varval(unsigned char *), 152529088Smarkm#endif 152687155Smarkm env_list(void); 152729088Smarkmstatic void 152887155Smarkm env_help(void); 152929088Smarkm 153029088Smarkmstruct envlist EnvList[] = { 153129088Smarkm { "define", "Define an environment variable", 153287139Smarkm (void (*)(unsigned char *, unsigned char *))env_define, 2 }, 153329088Smarkm { "undefine", "Undefine an environment variable", 153487139Smarkm (void (*)(unsigned char *, unsigned char *))env_undefine, 1 }, 153529088Smarkm { "export", "Mark an environment variable for automatic export", 153687139Smarkm (void (*)(unsigned char *, unsigned char *))env_export, 1 }, 153729088Smarkm { "unexport", "Don't mark an environment variable for automatic export", 153887139Smarkm (void (*)(unsigned char *, unsigned char *))env_unexport, 1 }, 153987139Smarkm { "send", "Send an environment variable", (void (*)(unsigned char *, unsigned char *))env_send, 1 }, 154029088Smarkm { "list", "List the current environment variables", 154187139Smarkm (void (*)(unsigned char *, unsigned char *))env_list, 0 }, 154229088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 154329088Smarkm { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 154487139Smarkm (void (*)(unsigned char *, unsigned char *))env_varval, 1 }, 154529088Smarkm#endif 154687139Smarkm { "help", NULL, (void (*)(unsigned char *, unsigned char *))env_help, 0 }, 154787139Smarkm { "?", "Print help information", (void (*)(unsigned char *, unsigned char *))env_help, 0 }, 154887139Smarkm { NULL, NULL, NULL, 0 }, 154929088Smarkm}; 155029088Smarkm 155187139Smarkmstatic void 155287139Smarkmenv_help(void) 155329088Smarkm{ 155429088Smarkm struct envlist *c; 155529088Smarkm 155629088Smarkm for (c = EnvList; c->name; c++) { 155729088Smarkm if (c->help) { 155829088Smarkm if (*c->help) 155929088Smarkm printf("%-15s %s\n", c->name, c->help); 156029088Smarkm else 156129088Smarkm printf("\n"); 156229088Smarkm } 156329088Smarkm } 156429088Smarkm} 156529088Smarkm 156687139Smarkmstatic struct envlist * 156787139Smarkmgetenvcmd(char *name) 156829088Smarkm{ 156929088Smarkm return (struct envlist *) 157029088Smarkm genget(name, (char **) EnvList, sizeof(struct envlist)); 157129088Smarkm} 157229088Smarkm 157387139Smarkmstatic int 157487139Smarkmenv_cmd(int argc, char *argv[]) 157529088Smarkm{ 157629088Smarkm struct envlist *c; 157729088Smarkm 157829088Smarkm if (argc < 2) { 157929088Smarkm fprintf(stderr, 158029088Smarkm "Need an argument to 'environ' command. 'environ ?' for help.\n"); 158129088Smarkm return 0; 158229088Smarkm } 158329088Smarkm c = getenvcmd(argv[1]); 158429088Smarkm if (c == 0) { 158529088Smarkm fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 158629088Smarkm argv[1]); 158729088Smarkm return 0; 158829088Smarkm } 158987139Smarkm if (Ambiguous((void *)c)) { 159029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 159129088Smarkm argv[1]); 159229088Smarkm return 0; 159329088Smarkm } 159429088Smarkm if (c->narg + 2 != argc) { 159529088Smarkm fprintf(stderr, 159629088Smarkm "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 159729088Smarkm c->narg < argc + 2 ? "only " : "", 159829088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 159929088Smarkm return 0; 160029088Smarkm } 160129088Smarkm (*c->handler)(argv[2], argv[3]); 160229088Smarkm return 1; 160329088Smarkm} 160429088Smarkm 160529088Smarkmstruct env_lst { 160629088Smarkm struct env_lst *next; /* pointer to next structure */ 160729088Smarkm struct env_lst *prev; /* pointer to previous structure */ 160829088Smarkm unsigned char *var; /* pointer to variable name */ 160929088Smarkm unsigned char *value; /* pointer to variable value */ 161029088Smarkm int export; /* 1 -> export with default list of variables */ 161129088Smarkm int welldefined; /* A well defined variable */ 161229088Smarkm}; 161329088Smarkm 161429088Smarkmstruct env_lst envlisthead; 161529088Smarkm 161687139Smarkmstatic struct env_lst * 161787139Smarkmenv_find(const unsigned char *var) 161829088Smarkm{ 161987139Smarkm struct env_lst *ep; 162029088Smarkm 162129088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 162287139Smarkm if (strcmp(ep->var, var) == 0) 162329088Smarkm return(ep); 162429088Smarkm } 162529088Smarkm return(NULL); 162629088Smarkm} 162729088Smarkm 162887139Smarkmvoid 162987139Smarkmenv_init(void) 163029088Smarkm{ 163129088Smarkm extern char **environ; 163287139Smarkm char **epp, *cp; 163387139Smarkm struct env_lst *ep; 163429088Smarkm 163529088Smarkm for (epp = environ; *epp; epp++) { 163629181Smarkm if ((cp = strchr(*epp, '='))) { 163729088Smarkm *cp = '\0'; 163829088Smarkm ep = env_define((unsigned char *)*epp, 163929088Smarkm (unsigned char *)cp+1); 164029088Smarkm ep->export = 0; 164129088Smarkm *cp = '='; 164229088Smarkm } 164329088Smarkm } 164429088Smarkm /* 164529088Smarkm * Special case for DISPLAY variable. If it is ":0.0" or 164629088Smarkm * "unix:0.0", we have to get rid of "unix" and insert our 164729088Smarkm * hostname. 164829088Smarkm */ 164929088Smarkm if ((ep = env_find("DISPLAY")) 165029088Smarkm && ((*ep->value == ':') 165129088Smarkm || (strncmp((char *)ep->value, "unix:", 5) == 0))) { 165229088Smarkm char hbuf[256+1]; 165329088Smarkm char *cp2 = strchr((char *)ep->value, ':'); 165429088Smarkm 165529088Smarkm gethostname(hbuf, 256); 165629088Smarkm hbuf[256] = '\0'; 165729088Smarkm cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); 165829088Smarkm sprintf((char *)cp, "%s%s", hbuf, cp2); 165929088Smarkm free(ep->value); 166029088Smarkm ep->value = (unsigned char *)cp; 166129088Smarkm } 166229088Smarkm /* 166329088Smarkm * If USER is not defined, but LOGNAME is, then add 166429088Smarkm * USER with the value from LOGNAME. By default, we 166529088Smarkm * don't export the USER variable. 166629088Smarkm */ 166729088Smarkm if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { 166887139Smarkm env_define("USER", ep->value); 166987139Smarkm env_unexport("USER"); 167029088Smarkm } 167187139Smarkm env_export("DISPLAY"); 167287139Smarkm env_export("PRINTER"); 167329088Smarkm} 167429088Smarkm 167587139Smarkmstruct env_lst * 167687139Smarkmenv_define(const unsigned char *var, unsigned char *value) 167729088Smarkm{ 167887139Smarkm struct env_lst *ep; 167929088Smarkm 168029181Smarkm if ((ep = env_find(var))) { 168129088Smarkm if (ep->var) 168229088Smarkm free(ep->var); 168329088Smarkm if (ep->value) 168429088Smarkm free(ep->value); 168529088Smarkm } else { 168629088Smarkm ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 168729088Smarkm ep->next = envlisthead.next; 168829088Smarkm envlisthead.next = ep; 168929088Smarkm ep->prev = &envlisthead; 169029088Smarkm if (ep->next) 169129088Smarkm ep->next->prev = ep; 169229088Smarkm } 169329088Smarkm ep->welldefined = opt_welldefined(var); 169429088Smarkm ep->export = 1; 169587139Smarkm ep->var = strdup(var); 169687139Smarkm ep->value = strdup(value); 169729088Smarkm return(ep); 169829088Smarkm} 169929088Smarkm 170087139Smarkmvoid 170187139Smarkmenv_undefine(unsigned char *var) 170229088Smarkm{ 170387139Smarkm struct env_lst *ep; 170429088Smarkm 170529181Smarkm if ((ep = env_find(var))) { 170629088Smarkm ep->prev->next = ep->next; 170729088Smarkm if (ep->next) 170829088Smarkm ep->next->prev = ep->prev; 170929088Smarkm if (ep->var) 171029088Smarkm free(ep->var); 171129088Smarkm if (ep->value) 171229088Smarkm free(ep->value); 171329088Smarkm free(ep); 171429088Smarkm } 171529088Smarkm} 171629088Smarkm 171787139Smarkmvoid 171887139Smarkmenv_export(const unsigned char *var) 171929088Smarkm{ 172087139Smarkm struct env_lst *ep; 172129088Smarkm 172229181Smarkm if ((ep = env_find(var))) 172329088Smarkm ep->export = 1; 172429088Smarkm} 172529088Smarkm 172687139Smarkmvoid 172787139Smarkmenv_unexport(const unsigned char *var) 172829088Smarkm{ 172987139Smarkm struct env_lst *ep; 173029088Smarkm 173129181Smarkm if ((ep = env_find(var))) 173229088Smarkm ep->export = 0; 173329088Smarkm} 173429088Smarkm 173587139Smarkmvoid 173687139Smarkmenv_send(unsigned char *var) 173729088Smarkm{ 173887139Smarkm struct env_lst *ep; 173929088Smarkm 174029088Smarkm if (my_state_is_wont(TELOPT_NEW_ENVIRON) 174129088Smarkm#ifdef OLD_ENVIRON 174229088Smarkm && my_state_is_wont(TELOPT_OLD_ENVIRON) 174329088Smarkm#endif 174429088Smarkm ) { 174529088Smarkm fprintf(stderr, 174629088Smarkm "Cannot send '%s': Telnet ENVIRON option not enabled\n", 174729088Smarkm var); 174829088Smarkm return; 174929088Smarkm } 175029088Smarkm ep = env_find(var); 175129088Smarkm if (ep == 0) { 175229088Smarkm fprintf(stderr, "Cannot send '%s': variable not defined\n", 175329088Smarkm var); 175429088Smarkm return; 175529088Smarkm } 175629088Smarkm env_opt_start_info(); 175729088Smarkm env_opt_add(ep->var); 175829088Smarkm env_opt_end(0); 175929088Smarkm} 176029088Smarkm 176187139Smarkmvoid 176287139Smarkmenv_list(void) 176329088Smarkm{ 176487139Smarkm struct env_lst *ep; 176529088Smarkm 176629088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 176729088Smarkm printf("%c %-20s %s\n", ep->export ? '*' : ' ', 176829088Smarkm ep->var, ep->value); 176929088Smarkm } 177029088Smarkm} 177129088Smarkm 177287139Smarkmunsigned char * 177387139Smarkmenv_default(int init, int welldefined) 177429088Smarkm{ 177529088Smarkm static struct env_lst *nep = NULL; 177629088Smarkm 177729088Smarkm if (init) { 177829088Smarkm nep = &envlisthead; 177929181Smarkm return(NULL); 178029088Smarkm } 178129088Smarkm if (nep) { 178229181Smarkm while ((nep = nep->next)) { 178329088Smarkm if (nep->export && (nep->welldefined == welldefined)) 178429088Smarkm return(nep->var); 178529088Smarkm } 178629088Smarkm } 178729088Smarkm return(NULL); 178829088Smarkm} 178929088Smarkm 179087139Smarkmunsigned char * 179187139Smarkmenv_getvalue(const unsigned char *var) 179229088Smarkm{ 179387139Smarkm struct env_lst *ep; 179429088Smarkm 179529181Smarkm if ((ep = env_find(var))) 179629088Smarkm return(ep->value); 179729088Smarkm return(NULL); 179829088Smarkm} 179929088Smarkm 180029088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 180187139Smarkmvoid 180287139Smarkmenv_varval(unsigned char *what) 180329088Smarkm{ 180429088Smarkm extern int old_env_var, old_env_value, env_auto; 180529088Smarkm int len = strlen((char *)what); 180629088Smarkm 180729088Smarkm if (len == 0) 180829088Smarkm goto unknown; 180929088Smarkm 181029088Smarkm if (strncasecmp((char *)what, "status", len) == 0) { 181129088Smarkm if (env_auto) 181229088Smarkm printf("%s%s", "VAR and VALUE are/will be ", 181329088Smarkm "determined automatically\n"); 181429088Smarkm if (old_env_var == OLD_ENV_VAR) 181529088Smarkm printf("VAR and VALUE set to correct definitions\n"); 181629088Smarkm else 181729088Smarkm printf("VAR and VALUE definitions are reversed\n"); 181829088Smarkm } else if (strncasecmp((char *)what, "auto", len) == 0) { 181929088Smarkm env_auto = 1; 182029088Smarkm old_env_var = OLD_ENV_VALUE; 182129088Smarkm old_env_value = OLD_ENV_VAR; 182229088Smarkm } else if (strncasecmp((char *)what, "right", len) == 0) { 182329088Smarkm env_auto = 0; 182429088Smarkm old_env_var = OLD_ENV_VAR; 182529088Smarkm old_env_value = OLD_ENV_VALUE; 182629088Smarkm } else if (strncasecmp((char *)what, "wrong", len) == 0) { 182729088Smarkm env_auto = 0; 182829088Smarkm old_env_var = OLD_ENV_VALUE; 182929088Smarkm old_env_value = OLD_ENV_VAR; 183029088Smarkm } else { 183129088Smarkmunknown: 183229088Smarkm printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); 183329088Smarkm } 183429088Smarkm} 183529088Smarkm#endif 183629088Smarkm 183787139Smarkm#ifdef AUTHENTICATION 183829088Smarkm/* 183929088Smarkm * The AUTHENTICATE command. 184029088Smarkm */ 184129088Smarkm 184229088Smarkmstruct authlist { 184387139Smarkm const char *name; 184487139Smarkm const char *help; 184587139Smarkm int (*handler)(char *); 184629088Smarkm int narg; 184729088Smarkm}; 184829088Smarkm 184929088Smarkmextern int 185087155Smarkm auth_enable(char *), 185187155Smarkm auth_disable(char *), 185287155Smarkm auth_status(void); 185329088Smarkmstatic int 185487155Smarkm auth_help(void); 185529088Smarkm 185629088Smarkmstruct authlist AuthList[] = { 185729088Smarkm { "status", "Display current status of authentication information", 185887139Smarkm (int (*)(char *))auth_status, 0 }, 185929088Smarkm { "disable", "Disable an authentication type ('auth disable ?' for more)", 186029088Smarkm auth_disable, 1 }, 186129088Smarkm { "enable", "Enable an authentication type ('auth enable ?' for more)", 186229088Smarkm auth_enable, 1 }, 186387139Smarkm { "help", NULL, (int (*)(char *))auth_help, 0 }, 186487139Smarkm { "?", "Print help information", (int (*)(char *))auth_help, 0 }, 186587139Smarkm { NULL, NULL, NULL, 0 }, 186629088Smarkm}; 186729088Smarkm 186887139Smarkmstatic int 186987139Smarkmauth_help(void) 187029088Smarkm{ 187129088Smarkm struct authlist *c; 187229088Smarkm 187329088Smarkm for (c = AuthList; c->name; c++) { 187429088Smarkm if (c->help) { 187529088Smarkm if (*c->help) 187629088Smarkm printf("%-15s %s\n", c->name, c->help); 187729088Smarkm else 187829088Smarkm printf("\n"); 187929088Smarkm } 188029088Smarkm } 188129088Smarkm return 0; 188229088Smarkm} 188329088Smarkm 188487139Smarkmint 188587139Smarkmauth_cmd(int argc, char *argv[]) 188629088Smarkm{ 188729088Smarkm struct authlist *c; 188829088Smarkm 188929088Smarkm if (argc < 2) { 189029088Smarkm fprintf(stderr, 189129088Smarkm "Need an argument to 'auth' command. 'auth ?' for help.\n"); 189229088Smarkm return 0; 189329088Smarkm } 189429088Smarkm 189529088Smarkm c = (struct authlist *) 189629088Smarkm genget(argv[1], (char **) AuthList, sizeof(struct authlist)); 189729088Smarkm if (c == 0) { 189829088Smarkm fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", 189929088Smarkm argv[1]); 190029088Smarkm return 0; 190129088Smarkm } 190287139Smarkm if (Ambiguous((void *)c)) { 190329088Smarkm fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", 190429088Smarkm argv[1]); 190529088Smarkm return 0; 190629088Smarkm } 190729088Smarkm if (c->narg + 2 != argc) { 190829088Smarkm fprintf(stderr, 190929088Smarkm "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", 191029088Smarkm c->narg < argc + 2 ? "only " : "", 191129088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 191229088Smarkm return 0; 191329088Smarkm } 191487139Smarkm return((*c->handler)(argv[2])); 191529088Smarkm} 191629088Smarkm#endif 191729088Smarkm 191829088Smarkm#ifdef ENCRYPTION 191929088Smarkm/* 192029088Smarkm * The ENCRYPT command. 192129088Smarkm */ 192229088Smarkm 192329088Smarkmstruct encryptlist { 192487139Smarkm const char *name; 192587139Smarkm const char *help; 192687139Smarkm int (*handler)(char *, char *); 192729088Smarkm int needconnect; 192829088Smarkm int minarg; 192929088Smarkm int maxarg; 193029088Smarkm}; 193129088Smarkm 193229088Smarkmextern int 193387155Smarkm EncryptEnable(char *, char *), 193487155Smarkm EncryptDisable(char *, char *), 193587155Smarkm EncryptType(char *, char *), 193687155Smarkm EncryptStart(char *), 193787155Smarkm EncryptStartInput(void), 193887155Smarkm EncryptStartOutput(void), 193987155Smarkm EncryptStop(char *), 194087155Smarkm EncryptStopInput(void), 194187155Smarkm EncryptStopOutput(void), 194287155Smarkm EncryptStatus(void); 194329088Smarkmstatic int 194487155Smarkm EncryptHelp(void); 194529088Smarkm 194629088Smarkmstruct encryptlist EncryptList[] = { 194729088Smarkm { "enable", "Enable encryption. ('encrypt enable ?' for more)", 194829088Smarkm EncryptEnable, 1, 1, 2 }, 194929088Smarkm { "disable", "Disable encryption. ('encrypt enable ?' for more)", 195029088Smarkm EncryptDisable, 0, 1, 2 }, 195129088Smarkm { "type", "Set encryption type. ('encrypt type ?' for more)", 195229088Smarkm EncryptType, 0, 1, 1 }, 195329088Smarkm { "start", "Start encryption. ('encrypt start ?' for more)", 195487139Smarkm (int (*)(char *, char *))EncryptStart, 1, 0, 1 }, 195529088Smarkm { "stop", "Stop encryption. ('encrypt stop ?' for more)", 195687139Smarkm (int (*)(char *, char *))EncryptStop, 1, 0, 1 }, 195729088Smarkm { "input", "Start encrypting the input stream", 195887139Smarkm (int (*)(char *, char *))EncryptStartInput, 1, 0, 0 }, 195929088Smarkm { "-input", "Stop encrypting the input stream", 196087139Smarkm (int (*)(char *, char *))EncryptStopInput, 1, 0, 0 }, 196129088Smarkm { "output", "Start encrypting the output stream", 196287139Smarkm (int (*)(char *, char *))EncryptStartOutput, 1, 0, 0 }, 196329088Smarkm { "-output", "Stop encrypting the output stream", 196487139Smarkm (int (*)(char *, char *))EncryptStopOutput, 1, 0, 0 }, 196529088Smarkm 196629088Smarkm { "status", "Display current status of authentication information", 196787139Smarkm (int (*)(char *, char *))EncryptStatus, 0, 0, 0 }, 196887139Smarkm { "help", NULL, (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, 196987139Smarkm { "?", "Print help information", (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, 197087139Smarkm { NULL, NULL, NULL, 0, 0, 0 }, 197129088Smarkm}; 197229088Smarkm 197387139Smarkmstatic int 197487139SmarkmEncryptHelp(void) 197529088Smarkm{ 197629088Smarkm struct encryptlist *c; 197729088Smarkm 197829088Smarkm for (c = EncryptList; c->name; c++) { 197929088Smarkm if (c->help) { 198029088Smarkm if (*c->help) 198129088Smarkm printf("%-15s %s\n", c->name, c->help); 198229088Smarkm else 198329088Smarkm printf("\n"); 198429088Smarkm } 198529088Smarkm } 198629088Smarkm return 0; 198729088Smarkm} 198829088Smarkm 198987139Smarkmstatic int 199087139Smarkmencrypt_cmd(int argc, char *argv[]) 199129088Smarkm{ 199229088Smarkm struct encryptlist *c; 199329088Smarkm 199429088Smarkm if (argc < 2) { 199529088Smarkm fprintf(stderr, 199629088Smarkm "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); 199729088Smarkm return 0; 199829088Smarkm } 199929088Smarkm 200029088Smarkm c = (struct encryptlist *) 200129088Smarkm genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); 200229088Smarkm if (c == 0) { 200329088Smarkm fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", 200429088Smarkm argv[1]); 200529088Smarkm return 0; 200629088Smarkm } 200787139Smarkm if (Ambiguous((void *)c)) { 200829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", 200929088Smarkm argv[1]); 201029088Smarkm return 0; 201129088Smarkm } 201229088Smarkm argc -= 2; 201329088Smarkm if (argc < c->minarg || argc > c->maxarg) { 201429088Smarkm if (c->minarg == c->maxarg) { 201529088Smarkm fprintf(stderr, "Need %s%d argument%s ", 201629088Smarkm c->minarg < argc ? "only " : "", c->minarg, 201729088Smarkm c->minarg == 1 ? "" : "s"); 201829088Smarkm } else { 201929088Smarkm fprintf(stderr, "Need %s%d-%d arguments ", 202029088Smarkm c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); 202129088Smarkm } 202229088Smarkm fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", 202329088Smarkm c->name); 202429088Smarkm return 0; 202529088Smarkm } 202629088Smarkm if (c->needconnect && !connected) { 202729088Smarkm if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 202829088Smarkm printf("?Need to be connected first.\n"); 202929088Smarkm return 0; 203029088Smarkm } 203129088Smarkm } 203229088Smarkm return ((*c->handler)(argc > 0 ? argv[2] : 0, 203387139Smarkm argc > 1 ? argv[3] : 0)); 203429088Smarkm} 203529088Smarkm#endif /* ENCRYPTION */ 203629088Smarkm 203729088Smarkm/* 203829088Smarkm * Print status about the connection. 203929088Smarkm */ 204087139Smarkm/*ARGSUSED*/ 204187139Smarkmstatic int 204287139Smarkmstatus(int argc, char *argv[]) 204329088Smarkm{ 204429088Smarkm if (connected) { 204529088Smarkm printf("Connected to %s.\n", hostname); 204629088Smarkm if ((argc < 2) || strcmp(argv[1], "notmuch")) { 204729088Smarkm int mode = getconnmode(); 204829088Smarkm 204929088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 205029088Smarkm printf("Operating with LINEMODE option\n"); 205129088Smarkm printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 205229088Smarkm printf("%s catching of signals\n", 205329088Smarkm (mode&MODE_TRAPSIG) ? "Local" : "No"); 205429088Smarkm slcstate(); 205529088Smarkm#ifdef KLUDGELINEMODE 205629088Smarkm } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 205729088Smarkm printf("Operating in obsolete linemode\n"); 205829088Smarkm#endif 205929088Smarkm } else { 206029088Smarkm printf("Operating in single character mode\n"); 206129088Smarkm if (localchars) 206229088Smarkm printf("Catching signals locally\n"); 206329088Smarkm } 206429088Smarkm printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 206529088Smarkm if (my_want_state_is_will(TELOPT_LFLOW)) 206629088Smarkm printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 206729088Smarkm#ifdef ENCRYPTION 206829088Smarkm encrypt_display(); 206929088Smarkm#endif /* ENCRYPTION */ 207029088Smarkm } 207129088Smarkm } else { 207229088Smarkm printf("No connection.\n"); 207329088Smarkm } 207429088Smarkm printf("Escape character is '%s'.\n", control(escape)); 207529088Smarkm (void) fflush(stdout); 207629088Smarkm return 1; 207729088Smarkm} 207829088Smarkm 207929088Smarkm#ifdef SIGINFO 208029088Smarkm/* 208129088Smarkm * Function that gets called when SIGINFO is received. 208229088Smarkm */ 208387139Smarkmvoid 208487139Smarkmayt_status(void) 208529088Smarkm{ 208629088Smarkm (void) call(status, "status", "notmuch", 0); 208729088Smarkm} 208829088Smarkm#endif 208929088Smarkm 209056668Sshinstatic const char * 209187139Smarkmsockaddr_ntop(struct sockaddr *sa) 209256668Sshin{ 209356668Sshin void *addr; 209456668Sshin static char addrbuf[INET6_ADDRSTRLEN]; 209529088Smarkm 209656668Sshin switch (sa->sa_family) { 209756668Sshin case AF_INET: 209856668Sshin addr = &((struct sockaddr_in *)sa)->sin_addr; 209956668Sshin break; 210077095Sdillon case AF_UNIX: 210177095Sdillon addr = &((struct sockaddr_un *)sa)->sun_path; 210277095Sdillon break; 210356668Sshin#ifdef INET6 210456668Sshin case AF_INET6: 210556668Sshin addr = &((struct sockaddr_in6 *)sa)->sin6_addr; 210656668Sshin break; 210756668Sshin#endif 210856668Sshin default: 210956668Sshin return NULL; 211056668Sshin } 211156668Sshin inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); 211256668Sshin return addrbuf; 211356668Sshin} 211456668Sshin 211556668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 211656668Sshinstatic int 211787139Smarkmsetpolicy(int lnet, struct addrinfo *res, char *policy) 211856668Sshin{ 211956668Sshin char *buf; 212056668Sshin int level; 212156668Sshin int optname; 212256668Sshin 212356668Sshin if (policy == NULL) 212456668Sshin return 0; 212556668Sshin 212656668Sshin buf = ipsec_set_policy(policy, strlen(policy)); 212756668Sshin if (buf == NULL) { 212856668Sshin printf("%s\n", ipsec_strerror()); 212956668Sshin return -1; 213056668Sshin } 213156668Sshin level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 213256668Sshin optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; 213387139Smarkm if (setsockopt(lnet, level, optname, buf, ipsec_get_policylen(buf)) < 0){ 213456668Sshin perror("setsockopt"); 213556668Sshin return -1; 213656668Sshin } 213756668Sshin 213856668Sshin free(buf); 213987139Smarkm return 0; 214056668Sshin} 214156668Sshin#endif 214256668Sshin 214357125Sshin#ifdef INET6 214457125Sshin/* 214557125Sshin * When an Address Family related error happend, check if retry with 214657125Sshin * another AF is possible or not. 214757125Sshin * Return 1, if retry with another af is OK. Else, return 0. 214857125Sshin */ 214957125Sshinstatic int 215087139Smarkmswitch_af(struct addrinfo **aip) 215157125Sshin{ 215257125Sshin int nextaf; 215357125Sshin struct addrinfo *ai; 215457125Sshin 215557125Sshin ai = *aip; 215657125Sshin nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; 215757125Sshin do 215857125Sshin ai=ai->ai_next; 215957125Sshin while (ai != NULL && ai->ai_family != nextaf); 216057125Sshin *aip = ai; 216157125Sshin if (*aip != NULL) { 216257125Sshin return 1; 216357125Sshin } 216457125Sshin return 0; 216557125Sshin} 216657125Sshin#endif 216757125Sshin 216887139Smarkmint 216987139Smarkmtn(int argc, char *argv[]) 217029088Smarkm{ 217181965Smarkm char *srp = 0; 217256668Sshin int proto, opt; 217387139Smarkm int srlen; 217456668Sshin int srcroute = 0, result; 217529088Smarkm char *cmd, *hostp = 0, *portp = 0, *user = 0; 217647973Sru char *src_addr = NULL; 217757125Sshin struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; 217857125Sshin int error = 0, af_error = 0; 217929088Smarkm 218029088Smarkm if (connected) { 218129088Smarkm printf("?Already connected to %s\n", hostname); 218229088Smarkm setuid(getuid()); 218329088Smarkm return 0; 218429088Smarkm } 218529088Smarkm if (argc < 2) { 218629088Smarkm (void) strcpy(line, "open "); 218729088Smarkm printf("(to) "); 218829088Smarkm (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); 218929088Smarkm makeargv(); 219029088Smarkm argc = margc; 219129088Smarkm argv = margv; 219229088Smarkm } 219329088Smarkm cmd = *argv; 219429088Smarkm --argc; ++argv; 219529088Smarkm while (argc) { 219629088Smarkm if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) 219729088Smarkm goto usage; 219829088Smarkm if (strcmp(*argv, "-l") == 0) { 219929088Smarkm --argc; ++argv; 220029088Smarkm if (argc == 0) 220129088Smarkm goto usage; 220229088Smarkm user = *argv++; 220329088Smarkm --argc; 220429088Smarkm continue; 220529088Smarkm } 220629088Smarkm if (strcmp(*argv, "-a") == 0) { 220729088Smarkm --argc; ++argv; 220829088Smarkm autologin = 1; 220929088Smarkm continue; 221029088Smarkm } 221147973Sru if (strcmp(*argv, "-s") == 0) { 221247973Sru --argc; ++argv; 221347973Sru if (argc == 0) 221447973Sru goto usage; 221547973Sru src_addr = *argv++; 221647973Sru --argc; 221747973Sru continue; 221847973Sru } 221929088Smarkm if (hostp == 0) { 222029088Smarkm hostp = *argv++; 222129088Smarkm --argc; 222229088Smarkm continue; 222329088Smarkm } 222429088Smarkm if (portp == 0) { 222529088Smarkm portp = *argv++; 222629088Smarkm --argc; 222729088Smarkm continue; 222829088Smarkm } 222929088Smarkm usage: 223047973Sru printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); 223129088Smarkm setuid(getuid()); 223229088Smarkm return 0; 223329088Smarkm } 223429088Smarkm if (hostp == 0) 223529088Smarkm goto usage; 223629088Smarkm 223747973Sru if (src_addr != NULL) { 223856668Sshin memset(&hints, 0, sizeof(hints)); 223956668Sshin hints.ai_flags = AI_NUMERICHOST; 224056668Sshin hints.ai_family = family; 224156668Sshin hints.ai_socktype = SOCK_STREAM; 224257125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 224362805Sume if (error == EAI_NODATA) { 224456668Sshin hints.ai_flags = 0; 224557125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 224656668Sshin } 224756668Sshin if (error != 0) { 224856668Sshin fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); 224956668Sshin if (error == EAI_SYSTEM) 225056668Sshin fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); 225157125Sshin setuid(getuid()); 225247973Sru return 0; 225347973Sru } 225457125Sshin src_res0 = src_res; 225547973Sru } 225677095Sdillon if (hostp[0] == '/') { 225777095Sdillon struct sockaddr_un su; 225877095Sdillon 225977095Sdillon if (strlen(hostp) >= sizeof(su.sun_path)) { 226077095Sdillon fprintf(stderr, "hostname too long for unix domain socket: %s", 226177095Sdillon hostp); 226277095Sdillon goto fail; 226377095Sdillon } 226477095Sdillon memset(&su, 0, sizeof su); 226577095Sdillon su.sun_family = AF_UNIX; 226677095Sdillon strncpy(su.sun_path, hostp, sizeof su.sun_path); 226787139Smarkm printf("Trying %s...\n", hostp); 226877095Sdillon net = socket(PF_UNIX, SOCK_STREAM, 0); 226977095Sdillon if ( net < 0) { 227077095Sdillon perror("socket"); 227177095Sdillon goto fail; 227277095Sdillon } 227377095Sdillon if (connect(net, (struct sockaddr *)&su, sizeof su) == -1) { 227477095Sdillon perror(su.sun_path); 227577095Sdillon (void) NetClose(net); 227677095Sdillon goto fail; 227777095Sdillon } 227877095Sdillon goto af_unix; 227977095Sdillon } else if (hostp[0] == '@' || hostp[0] == '!') { 228056668Sshin if ( 228156668Sshin#ifdef INET6 228256668Sshin family == AF_INET6 || 228356668Sshin#endif 228456668Sshin (hostname = strrchr(hostp, ':')) == NULL) 228529088Smarkm hostname = strrchr(hostp, '@'); 228629088Smarkm hostname++; 228756668Sshin srcroute = 1; 228856668Sshin } else 228956668Sshin hostname = hostp; 229056668Sshin if (!portp) { 229156668Sshin telnetport = 1; 229287139Smarkm portp = strdup("telnet"); 229356668Sshin } else if (*portp == '-') { 229456668Sshin portp++; 229556668Sshin telnetport = 1; 229656668Sshin } else 229756668Sshin telnetport = 0; 229856668Sshin 229956668Sshin memset(&hints, 0, sizeof(hints)); 230056668Sshin hints.ai_flags = AI_NUMERICHOST; 230156668Sshin hints.ai_family = family; 230256668Sshin hints.ai_socktype = SOCK_STREAM; 230356668Sshin error = getaddrinfo(hostname, portp, &hints, &res); 230462773Sitojun if (error) { 230562773Sitojun hints.ai_flags = AI_CANONNAME; 230662773Sitojun error = getaddrinfo(hostname, portp, &hints, &res); 230762773Sitojun } 230862773Sitojun if (error != 0) { 230962773Sitojun fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); 231062773Sitojun if (error == EAI_SYSTEM) 231162773Sitojun fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); 231262773Sitojun setuid(getuid()); 231362773Sitojun goto fail; 231462773Sitojun } 231562773Sitojun if (hints.ai_flags == AI_NUMERICHOST) { 231662773Sitojun /* hostname has numeric */ 231756668Sshin int gni_err = 1; 231856668Sshin 231956668Sshin if (doaddrlookup) 232056668Sshin gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, 232156668Sshin _hostname, sizeof(_hostname) - 1, NULL, 0, 232256870Sshin NI_NAMEREQD); 232356668Sshin if (gni_err != 0) 232462773Sitojun (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 232556668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 232656668Sshin hostname = _hostname; 232762773Sitojun } else { 232862773Sitojun /* hostname has FQDN */ 232956668Sshin if (srcroute != 0) 233056668Sshin (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); 233156668Sshin else if (res->ai_canonname != NULL) 233256668Sshin strcpy(_hostname, res->ai_canonname); 233356668Sshin else 233456668Sshin (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 233556668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 233656668Sshin hostname = _hostname; 233756668Sshin } 233857125Sshin res0 = res; 233957233Sshin af_again: 234056668Sshin if (srcroute != 0) { 234157343Sshin static char hostbuf[BUFSIZ]; 234257125Sshin 234357233Sshin if (af_error == 0) { /* save intermediate hostnames for retry */ 234457233Sshin strncpy(hostbuf, hostp, BUFSIZ - 1); 234557233Sshin hostbuf[BUFSIZ - 1] = '\0'; 234657233Sshin } else 234757125Sshin hostp = hostbuf; 234829088Smarkm srp = 0; 234956668Sshin result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); 235056668Sshin if (result == 0) { 235157125Sshin#ifdef INET6 235257125Sshin if (family == AF_UNSPEC && af_error == 0 && 235357125Sshin switch_af(&res) == 1) { 235457125Sshin af_error = 1; 235557125Sshin goto af_again; 235657125Sshin } 235757125Sshin#endif 235829088Smarkm setuid(getuid()); 235957125Sshin goto fail; 236056668Sshin } else if (result == -1) { 236129088Smarkm printf("Bad source route option: %s\n", hostp); 236229088Smarkm setuid(getuid()); 236357125Sshin goto fail; 236429088Smarkm } 236529088Smarkm } 236629088Smarkm do { 236757342Sshin printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); 236856668Sshin net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 236929088Smarkm setuid(getuid()); 237029088Smarkm if (net < 0) { 237157125Sshin#ifdef INET6 237257125Sshin if (family == AF_UNSPEC && af_error == 0 && 237357125Sshin switch_af(&res) == 1) { 237457125Sshin af_error = 1; 237557125Sshin goto af_again; 237657125Sshin } 237757125Sshin#endif 237829088Smarkm perror("telnet: socket"); 237957125Sshin goto fail; 238029088Smarkm } 238156668Sshin if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) 238256668Sshin perror("setsockopt (source route)"); 238329088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 238456668Sshin if (res->ai_family == PF_INET) { 238529088Smarkm# if defined(HAS_GETTOS) 238629088Smarkm struct tosent *tp; 238729088Smarkm if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 238829088Smarkm tos = tp->t_tos; 238929088Smarkm# endif 239029088Smarkm if (tos < 0) 239181965Smarkm tos = IPTOS_LOWDELAY; 239229088Smarkm if (tos 239329088Smarkm && (setsockopt(net, IPPROTO_IP, IP_TOS, 239429088Smarkm (char *)&tos, sizeof(int)) < 0) 239529088Smarkm && (errno != ENOPROTOOPT)) 239629088Smarkm perror("telnet: setsockopt (IP_TOS) (ignored)"); 239729088Smarkm } 239829088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 239929088Smarkm 240029088Smarkm if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 240129088Smarkm perror("setsockopt (SO_DEBUG)"); 240229088Smarkm } 240329088Smarkm 240447973Sru if (src_addr != NULL) { 240557125Sshin for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) 240657233Sshin if (src_res->ai_family == res->ai_family) 240757233Sshin break; 240857125Sshin if (src_res == NULL) 240957125Sshin src_res = src_res0; 241057125Sshin if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { 241157125Sshin#ifdef INET6 241257125Sshin if (family == AF_UNSPEC && af_error == 0 && 241357125Sshin switch_af(&res) == 1) { 241457125Sshin af_error = 1; 241557233Sshin (void) NetClose(net); 241657125Sshin goto af_again; 241757125Sshin } 241857125Sshin#endif 241947973Sru perror("bind"); 242057233Sshin (void) NetClose(net); 242157125Sshin goto fail; 242247973Sru } 242347973Sru } 242456668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 242557233Sshin if (setpolicy(net, res, ipsec_policy_in) < 0) { 242657233Sshin (void) NetClose(net); 242757125Sshin goto fail; 242857233Sshin } 242957233Sshin if (setpolicy(net, res, ipsec_policy_out) < 0) { 243057233Sshin (void) NetClose(net); 243157125Sshin goto fail; 243257233Sshin } 243356668Sshin#endif 243447973Sru 243556668Sshin if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { 243657125Sshin struct addrinfo *next; 243757125Sshin 243857125Sshin next = res->ai_next; 243957125Sshin /* If already an af failed, only try same af. */ 244057125Sshin if (af_error != 0) 244157125Sshin while (next != NULL && next->ai_family != res->ai_family) 244257125Sshin next = next->ai_next; 244357342Sshin warn("connect to address %s", sockaddr_ntop(res->ai_addr)); 244457125Sshin if (next != NULL) { 244557125Sshin res = next; 244629088Smarkm (void) NetClose(net); 244729088Smarkm continue; 244829088Smarkm } 244957342Sshin warnx("Unable to connect to remote host"); 245057233Sshin (void) NetClose(net); 245157125Sshin goto fail; 245229088Smarkm } 245329088Smarkm connected++; 245487139Smarkm#ifdef AUTHENTICATION 245587139Smarkm#ifdef ENCRYPTION 245629088Smarkm auth_encrypt_connect(connected); 245787139Smarkm#endif 245887139Smarkm#endif 245929088Smarkm } while (connected == 0); 246057125Sshin freeaddrinfo(res0); 246157125Sshin if (src_res0 != NULL) 246257125Sshin freeaddrinfo(src_res0); 246329088Smarkm cmdrc(hostp, hostname); 246477095Sdillon af_unix: 246529088Smarkm if (autologin && user == NULL) { 246629088Smarkm struct passwd *pw; 246729088Smarkm 246829088Smarkm user = getenv("USER"); 246929088Smarkm if (user == NULL || 247029181Smarkm ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { 247129181Smarkm if ((pw = getpwuid(getuid()))) 247229088Smarkm user = pw->pw_name; 247329088Smarkm else 247429088Smarkm user = NULL; 247529088Smarkm } 247629088Smarkm } 247729088Smarkm if (user) { 247887139Smarkm env_define("USER", user); 247987139Smarkm env_export("USER"); 248029088Smarkm } 248129088Smarkm (void) call(status, "status", "notmuch", 0); 248229088Smarkm if (setjmp(peerdied) == 0) 248329088Smarkm telnet(user); 248429088Smarkm (void) NetClose(net); 248529088Smarkm ExitString("Connection closed by foreign host.\n",1); 248629088Smarkm /*NOTREACHED*/ 248757125Sshin fail: 248857125Sshin if (res0 != NULL) 248957125Sshin freeaddrinfo(res0); 249057125Sshin if (src_res0 != NULL) 249157125Sshin freeaddrinfo(src_res0); 249257125Sshin return 0; 249329088Smarkm} 249429088Smarkm 249529088Smarkm#define HELPINDENT (sizeof ("connect")) 249629088Smarkm 249729088Smarkmstatic char 249829088Smarkm openhelp[] = "connect to a site", 249929088Smarkm closehelp[] = "close current connection", 250029088Smarkm logouthelp[] = "forcibly logout remote user and close the connection", 250129088Smarkm quithelp[] = "exit telnet", 250229088Smarkm statushelp[] = "print status information", 250329088Smarkm helphelp[] = "print help information", 250429088Smarkm sendhelp[] = "transmit special characters ('send ?' for more)", 250529088Smarkm sethelp[] = "set operating parameters ('set ?' for more)", 250629088Smarkm unsethelp[] = "unset operating parameters ('unset ?' for more)", 250729088Smarkm togglestring[] ="toggle operating parameters ('toggle ?' for more)", 250829088Smarkm slchelp[] = "change state of special charaters ('slc ?' for more)", 250929088Smarkm displayhelp[] = "display operating parameters", 251087139Smarkm#ifdef AUTHENTICATION 251129088Smarkm authhelp[] = "turn on (off) authentication ('auth ?' for more)", 251229088Smarkm#endif 251329088Smarkm#ifdef ENCRYPTION 251429088Smarkm encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", 251529088Smarkm#endif /* ENCRYPTION */ 251629088Smarkm zhelp[] = "suspend telnet", 251787139Smarkm#ifdef OPIE 251881965Smarkm opiehelp[] = "compute response to OPIE challenge", 251929181Smarkm#endif 252029088Smarkm shellhelp[] = "invoke a subshell", 252129088Smarkm envhelp[] = "change environment variables ('environ ?' for more)", 252229088Smarkm modestring[] = "try to enter line or character mode ('mode ?' for more)"; 252329088Smarkm 252429088Smarkmstatic Command cmdtab[] = { 252529088Smarkm { "close", closehelp, bye, 1 }, 252687139Smarkm { "logout", logouthelp, (int (*)(int, char **))logout, 1 }, 252729088Smarkm { "display", displayhelp, display, 0 }, 252829088Smarkm { "mode", modestring, modecmd, 0 }, 252981965Smarkm { "telnet", openhelp, tn, 0 }, 253029088Smarkm { "open", openhelp, tn, 0 }, 253187139Smarkm { "quit", quithelp, (int (*)(int, char **))quit, 0 }, 253229088Smarkm { "send", sendhelp, sendcmd, 0 }, 253329088Smarkm { "set", sethelp, setcmd, 0 }, 253429088Smarkm { "unset", unsethelp, unsetcmd, 0 }, 253529088Smarkm { "status", statushelp, status, 0 }, 253629088Smarkm { "toggle", togglestring, toggle, 0 }, 253729088Smarkm { "slc", slchelp, slccmd, 0 }, 253887139Smarkm#ifdef AUTHENTICATION 253929088Smarkm { "auth", authhelp, auth_cmd, 0 }, 254029088Smarkm#endif 254129088Smarkm#ifdef ENCRYPTION 254229088Smarkm { "encrypt", encrypthelp, encrypt_cmd, 0 }, 254329088Smarkm#endif /* ENCRYPTION */ 254487139Smarkm { "z", zhelp, (int (*)(int, char **))suspend, 0 }, 254529088Smarkm { "!", shellhelp, shell, 1 }, 254629088Smarkm { "environ", envhelp, env_cmd, 0 }, 254729088Smarkm { "?", helphelp, help, 0 }, 254887139Smarkm#ifdef OPIE 254981965Smarkm { "opie", opiehelp, opie_calc, 0 }, 255029181Smarkm#endif 255187139Smarkm { NULL, NULL, NULL, 0 } 255229088Smarkm}; 255329088Smarkm 255429088Smarkmstatic char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 255529088Smarkmstatic char escapehelp[] = "deprecated command -- use 'set escape' instead"; 255629088Smarkm 255729088Smarkmstatic Command cmdtab2[] = { 255829088Smarkm { "help", 0, help, 0 }, 255929088Smarkm { "escape", escapehelp, setescape, 0 }, 256087139Smarkm { "crmod", crmodhelp, (int (*)(int, char **))togcrmod, 0 }, 256187139Smarkm { NULL, NULL, NULL, 0 } 256229088Smarkm}; 256329088Smarkm 256429088Smarkm 256529088Smarkm/* 256629088Smarkm * Call routine with argc, argv set from args (terminated by 0). 256729088Smarkm */ 256829088Smarkm 256987139Smarkmstatic int 257087139Smarkmcall(intrtn_t routine, ...) 257129088Smarkm{ 257229088Smarkm va_list ap; 257329088Smarkm char *args[100]; 257429088Smarkm int argno = 0; 257529088Smarkm 257687139Smarkm va_start(ap, routine); 257787139Smarkm while ((args[argno++] = va_arg(ap, char *)) != 0); 257829088Smarkm va_end(ap); 257929088Smarkm return (*routine)(argno-1, args); 258029088Smarkm} 258129088Smarkm 258229088Smarkm 258387139Smarkmstatic Command * 258487139Smarkmgetcmd(char *name) 258529088Smarkm{ 258629088Smarkm Command *cm; 258729088Smarkm 258829181Smarkm if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) 258929088Smarkm return cm; 259029088Smarkm return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); 259129088Smarkm} 259229088Smarkm 259387139Smarkmvoid 259487139Smarkmcommand(int top, const char *tbuf, int cnt) 259529088Smarkm{ 259687139Smarkm Command *c; 259729088Smarkm 259829088Smarkm setcommandmode(); 259929088Smarkm if (!top) { 260029088Smarkm putchar('\n'); 260129088Smarkm } else { 260229088Smarkm (void) signal(SIGINT, SIG_DFL); 260329088Smarkm (void) signal(SIGQUIT, SIG_DFL); 260429088Smarkm } 260529088Smarkm for (;;) { 260629088Smarkm if (rlogin == _POSIX_VDISABLE) 260729088Smarkm printf("%s> ", prompt); 260829088Smarkm if (tbuf) { 260987139Smarkm char *cp; 261029088Smarkm cp = line; 261129088Smarkm while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 261229088Smarkm cnt--; 261329088Smarkm tbuf = 0; 261429088Smarkm if (cp == line || *--cp != '\n' || cp == line) 261529088Smarkm goto getline; 261629088Smarkm *cp = '\0'; 261729088Smarkm if (rlogin == _POSIX_VDISABLE) 261829088Smarkm printf("%s\n", line); 261929088Smarkm } else { 262029088Smarkm getline: 262129088Smarkm if (rlogin != _POSIX_VDISABLE) 262229088Smarkm printf("%s> ", prompt); 262329088Smarkm if (fgets(line, sizeof(line), stdin) == NULL) { 262429088Smarkm if (feof(stdin) || ferror(stdin)) { 262529088Smarkm (void) quit(); 262629088Smarkm /*NOTREACHED*/ 262729088Smarkm } 262829088Smarkm break; 262929088Smarkm } 263029088Smarkm } 263129088Smarkm if (line[0] == 0) 263229088Smarkm break; 263329088Smarkm makeargv(); 263429088Smarkm if (margv[0] == 0) { 263529088Smarkm break; 263629088Smarkm } 263729088Smarkm c = getcmd(margv[0]); 263887139Smarkm if (Ambiguous((void *)c)) { 263929088Smarkm printf("?Ambiguous command\n"); 264029088Smarkm continue; 264129088Smarkm } 264229088Smarkm if (c == 0) { 264329088Smarkm printf("?Invalid command\n"); 264429088Smarkm continue; 264529088Smarkm } 264629088Smarkm if (c->needconnect && !connected) { 264729088Smarkm printf("?Need to be connected first.\n"); 264829088Smarkm continue; 264929088Smarkm } 265029088Smarkm if ((*c->handler)(margc, margv)) { 265129088Smarkm break; 265229088Smarkm } 265329088Smarkm } 265429088Smarkm if (!top) { 265529088Smarkm if (!connected) { 265629088Smarkm longjmp(toplevel, 1); 265729088Smarkm /*NOTREACHED*/ 265829088Smarkm } 265929088Smarkm setconnmode(0); 266029088Smarkm } 266129088Smarkm} 266229088Smarkm 266329088Smarkm/* 266429088Smarkm * Help command. 266529088Smarkm */ 266687139Smarkmstatic int 266787139Smarkmhelp(int argc, char *argv[]) 266829088Smarkm{ 266987139Smarkm Command *c; 267029088Smarkm 267129088Smarkm if (argc == 1) { 267229088Smarkm printf("Commands may be abbreviated. Commands are:\n\n"); 267329088Smarkm for (c = cmdtab; c->name; c++) 267429088Smarkm if (c->help) { 267529088Smarkm printf("%-*s\t%s\n", HELPINDENT, c->name, 267629088Smarkm c->help); 267729088Smarkm } 267881965Smarkm return 0; 267929088Smarkm } 268029181Smarkm else while (--argc > 0) { 268187139Smarkm char *arg; 268229088Smarkm arg = *++argv; 268329088Smarkm c = getcmd(arg); 268487139Smarkm if (Ambiguous((void *)c)) 268529088Smarkm printf("?Ambiguous help command %s\n", arg); 268629088Smarkm else if (c == (Command *)0) 268729088Smarkm printf("?Invalid help command %s\n", arg); 268829088Smarkm else 268929088Smarkm printf("%s\n", c->help); 269029088Smarkm } 269181965Smarkm return 0; 269229088Smarkm} 269329088Smarkm 269429088Smarkmstatic char *rcname = 0; 269529088Smarkmstatic char rcbuf[128]; 269629088Smarkm 269787139Smarkmvoid 269887139Smarkmcmdrc(char *m1, char *m2) 269929088Smarkm{ 270087139Smarkm Command *c; 270129088Smarkm FILE *rcfile; 270229088Smarkm int gotmachine = 0; 270329088Smarkm int l1 = strlen(m1); 270429088Smarkm int l2 = strlen(m2); 270568891Skris char m1save[MAXHOSTNAMELEN]; 270629088Smarkm 270729088Smarkm if (skiprc) 270829088Smarkm return; 270929088Smarkm 271068891Skris strlcpy(m1save, m1, sizeof(m1save)); 271129088Smarkm m1 = m1save; 271229088Smarkm 271329088Smarkm if (rcname == 0) { 271429088Smarkm rcname = getenv("HOME"); 271529181Smarkm if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) 271629088Smarkm strcpy(rcbuf, rcname); 271729088Smarkm else 271829088Smarkm rcbuf[0] = '\0'; 271929088Smarkm strcat(rcbuf, "/.telnetrc"); 272029088Smarkm rcname = rcbuf; 272129088Smarkm } 272229088Smarkm 272329088Smarkm if ((rcfile = fopen(rcname, "r")) == 0) { 272429088Smarkm return; 272529088Smarkm } 272629088Smarkm 272729088Smarkm for (;;) { 272829088Smarkm if (fgets(line, sizeof(line), rcfile) == NULL) 272929088Smarkm break; 273029088Smarkm if (line[0] == 0) 273129088Smarkm break; 273229088Smarkm if (line[0] == '#') 273329088Smarkm continue; 273429088Smarkm if (gotmachine) { 273529088Smarkm if (!isspace(line[0])) 273629088Smarkm gotmachine = 0; 273729088Smarkm } 273829088Smarkm if (gotmachine == 0) { 273929088Smarkm if (isspace(line[0])) 274029088Smarkm continue; 274129088Smarkm if (strncasecmp(line, m1, l1) == 0) 274229088Smarkm strncpy(line, &line[l1], sizeof(line) - l1); 274329088Smarkm else if (strncasecmp(line, m2, l2) == 0) 274429088Smarkm strncpy(line, &line[l2], sizeof(line) - l2); 274529088Smarkm else if (strncasecmp(line, "DEFAULT", 7) == 0) 274629088Smarkm strncpy(line, &line[7], sizeof(line) - 7); 274729088Smarkm else 274829088Smarkm continue; 274929088Smarkm if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') 275029088Smarkm continue; 275129088Smarkm gotmachine = 1; 275229088Smarkm } 275329088Smarkm makeargv(); 275429088Smarkm if (margv[0] == 0) 275529088Smarkm continue; 275629088Smarkm c = getcmd(margv[0]); 275787139Smarkm if (Ambiguous((void *)c)) { 275829088Smarkm printf("?Ambiguous command: %s\n", margv[0]); 275929088Smarkm continue; 276029088Smarkm } 276129088Smarkm if (c == 0) { 276229088Smarkm printf("?Invalid command: %s\n", margv[0]); 276329088Smarkm continue; 276429088Smarkm } 276529088Smarkm /* 276629088Smarkm * This should never happen... 276729088Smarkm */ 276829088Smarkm if (c->needconnect && !connected) { 276929088Smarkm printf("?Need to be connected first for %s.\n", margv[0]); 277029088Smarkm continue; 277129088Smarkm } 277229088Smarkm (*c->handler)(margc, margv); 277329088Smarkm } 277429088Smarkm fclose(rcfile); 277529088Smarkm} 277629088Smarkm 277729088Smarkm/* 277829088Smarkm * Source route is handed in as 277929088Smarkm * [!]@hop1@hop2...[@|:]dst 278029088Smarkm * If the leading ! is present, it is a 278129088Smarkm * strict source route, otherwise it is 278229088Smarkm * assmed to be a loose source route. 278329088Smarkm * 278429088Smarkm * We fill in the source route option as 278529088Smarkm * hop1,hop2,hop3...dest 278629088Smarkm * and return a pointer to hop1, which will 278729088Smarkm * be the address to connect() to. 278829088Smarkm * 278929088Smarkm * Arguments: 279056668Sshin * 279156668Sshin * res: ponter to addrinfo structure which contains sockaddr to 279256668Sshin * the host to connect to. 279356668Sshin * 279429088Smarkm * arg: pointer to route list to decipher 279529088Smarkm * 279629088Smarkm * cpp: If *cpp is not equal to NULL, this is a 279729088Smarkm * pointer to a pointer to a character array 279829088Smarkm * that should be filled in with the option. 279929088Smarkm * 280029088Smarkm * lenp: pointer to an integer that contains the 280129088Smarkm * length of *cpp if *cpp != NULL. 280229088Smarkm * 280356668Sshin * protop: pointer to an integer that should be filled in with 280456668Sshin * appropriate protocol for setsockopt, as socket 280556668Sshin * protocol family. 280656668Sshin * 280756668Sshin * optp: pointer to an integer that should be filled in with 280856668Sshin * appropriate option for setsockopt, as socket protocol 280956668Sshin * family. 281056668Sshin * 281129088Smarkm * Return values: 281229088Smarkm * 281356668Sshin * If the return value is 1, then all operations are 281456668Sshin * successful. If the 281529088Smarkm * return value is -1, there was a syntax error in the 281629088Smarkm * option, either unknown characters, or too many hosts. 281729088Smarkm * If the return value is 0, one of the hostnames in the 281829088Smarkm * path is unknown, and *cpp is set to point to the bad 281929088Smarkm * hostname. 282029088Smarkm * 282129088Smarkm * *cpp: If *cpp was equal to NULL, it will be filled 282229088Smarkm * in with a pointer to our static area that has 282329088Smarkm * the option filled in. This will be 32bit aligned. 282429088Smarkm * 282529088Smarkm * *lenp: This will be filled in with how long the option 282629088Smarkm * pointed to by *cpp is. 282729088Smarkm * 282856668Sshin * *protop: This will be filled in with appropriate protocol for 282956668Sshin * setsockopt, as socket protocol family. 283056668Sshin * 283156668Sshin * *optp: This will be filled in with appropriate option for 283256668Sshin * setsockopt, as socket protocol family. 283329088Smarkm */ 283487139Smarkmstatic int 283587139Smarkmsourceroute(struct addrinfo *ai, char *arg, char **cpp, int *lenp, int *protop, int *optp) 283629088Smarkm{ 283763662Sume static char buf[1024 + ALIGNBYTES]; /*XXX*/ 283856668Sshin struct cmsghdr *cmsg; 283956668Sshin char *cp, *cp2, *lsrp, *ep; 284087139Smarkm struct sockaddr_in *_sin; 284156668Sshin struct sockaddr_in6 *sin6; 284256668Sshin struct addrinfo hints, *res; 284356668Sshin int error; 284487139Smarkm char c; 284529088Smarkm 284629088Smarkm /* 284729088Smarkm * Verify the arguments, and make sure we have 284829088Smarkm * at least 7 bytes for the option. 284929088Smarkm */ 285029088Smarkm if (cpp == NULL || lenp == NULL) 285157724Sshin return -1; 285256668Sshin if (*cpp != NULL) { 285356668Sshin switch (res->ai_family) { 285456668Sshin case AF_INET: 285556668Sshin if (*lenp < 7) 285657724Sshin return -1; 285756668Sshin break; 285856668Sshin#ifdef INET6 285956668Sshin case AF_INET6: 286087139Smarkm if (*lenp < (int)CMSG_SPACE(sizeof(struct ip6_rthdr) + 286157724Sshin sizeof(struct in6_addr))) 286257724Sshin return -1; 286356668Sshin break; 286456668Sshin#endif 286556668Sshin } 286656668Sshin } 286729088Smarkm /* 286829088Smarkm * Decide whether we have a buffer passed to us, 286929088Smarkm * or if we need to use our own static buffer. 287029088Smarkm */ 287129088Smarkm if (*cpp) { 287229088Smarkm lsrp = *cpp; 287356668Sshin ep = lsrp + *lenp; 287429088Smarkm } else { 287563662Sume *cpp = lsrp = (char *)ALIGN(buf); 287656668Sshin ep = lsrp + 1024; 287729088Smarkm } 287829088Smarkm 287929088Smarkm cp = arg; 288029088Smarkm 288156668Sshin#ifdef INET6 288256668Sshin if (ai->ai_family == AF_INET6) { 288356668Sshin cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0); 288456668Sshin if (*cp != '@') 288556668Sshin return -1; 288656668Sshin *protop = IPPROTO_IPV6; 288756668Sshin *optp = IPV6_PKTOPTIONS; 288856668Sshin } else 288956668Sshin#endif 289056668Sshin { 289129088Smarkm /* 289229088Smarkm * Next, decide whether we have a loose source 289329088Smarkm * route or a strict source route, and fill in 289429088Smarkm * the begining of the option. 289529088Smarkm */ 289629088Smarkm if (*cp == '!') { 289729088Smarkm cp++; 289829088Smarkm *lsrp++ = IPOPT_SSRR; 289929088Smarkm } else 290029088Smarkm *lsrp++ = IPOPT_LSRR; 290129088Smarkm 290229088Smarkm if (*cp != '@') 290357724Sshin return -1; 290429088Smarkm 290529088Smarkm lsrp++; /* skip over length, we'll fill it in later */ 290629088Smarkm *lsrp++ = 4; 290756668Sshin *protop = IPPROTO_IP; 290856668Sshin *optp = IP_OPTIONS; 290956668Sshin } 291029088Smarkm 291129088Smarkm cp++; 291256668Sshin memset(&hints, 0, sizeof(hints)); 291356668Sshin hints.ai_family = ai->ai_family; 291456668Sshin hints.ai_socktype = SOCK_STREAM; 291529088Smarkm for (c = 0;;) { 291656668Sshin if ( 291756668Sshin#ifdef INET6 291856668Sshin ai->ai_family != AF_INET6 && 291956668Sshin#endif 292056668Sshin c == ':') 292129088Smarkm cp2 = 0; 292229181Smarkm else for (cp2 = cp; (c = *cp2); cp2++) { 292329088Smarkm if (c == ',') { 292429088Smarkm *cp2++ = '\0'; 292529088Smarkm if (*cp2 == '@') 292629088Smarkm cp2++; 292729088Smarkm } else if (c == '@') { 292829088Smarkm *cp2++ = '\0'; 292956668Sshin } else if ( 293056668Sshin#ifdef INET6 293156668Sshin ai->ai_family != AF_INET6 && 293256668Sshin#endif 293356668Sshin c == ':') { 293429088Smarkm *cp2++ = '\0'; 293529088Smarkm } else 293629088Smarkm continue; 293729088Smarkm break; 293829088Smarkm } 293929088Smarkm if (!c) 294029088Smarkm cp2 = 0; 294129088Smarkm 294256668Sshin hints.ai_flags = AI_NUMERICHOST; 294381965Smarkm error = getaddrinfo(cp, NULL, &hints, &res); 294462805Sume if (error == EAI_NODATA) { 294556668Sshin hints.ai_flags = 0; 294656668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 294756668Sshin } 294856668Sshin if (error != 0) { 294956668Sshin fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); 295056668Sshin if (error == EAI_SYSTEM) 295156668Sshin fprintf(stderr, "%s: %s\n", cp, 295256668Sshin strerror(errno)); 295329088Smarkm *cpp = cp; 295429088Smarkm return(0); 295529088Smarkm } 295656668Sshin#ifdef INET6 295756668Sshin if (res->ai_family == AF_INET6) { 295856668Sshin sin6 = (struct sockaddr_in6 *)res->ai_addr; 295956668Sshin inet6_rthdr_add(cmsg, &sin6->sin6_addr, 296056668Sshin IPV6_RTHDR_LOOSE); 296156668Sshin } else 296256668Sshin#endif 296356668Sshin { 296487139Smarkm _sin = (struct sockaddr_in *)res->ai_addr; 296587139Smarkm memcpy(lsrp, (char *)&_sin->sin_addr, 4); 296629088Smarkm lsrp += 4; 296756668Sshin } 296829088Smarkm if (cp2) 296929088Smarkm cp = cp2; 297029088Smarkm else 297129088Smarkm break; 297229088Smarkm /* 297329088Smarkm * Check to make sure there is space for next address 297429088Smarkm */ 297556668Sshin#ifdef INET6 297656668Sshin if (res->ai_family == AF_INET6) { 297757724Sshin if (((char *)CMSG_DATA(cmsg) + 297856668Sshin sizeof(struct ip6_rthdr) + 297956668Sshin ((inet6_rthdr_segments(cmsg) + 1) * 298056668Sshin sizeof(struct in6_addr))) > ep) 298157724Sshin return -1; 298256668Sshin } else 298356668Sshin#endif 298456668Sshin if (lsrp + 4 > ep) 298557724Sshin return -1; 298656668Sshin freeaddrinfo(res); 298729088Smarkm } 298856668Sshin#ifdef INET6 298956668Sshin if (res->ai_family == AF_INET6) { 299056668Sshin inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 299156668Sshin *lenp = cmsg->cmsg_len; 299256668Sshin } else 299356668Sshin#endif 299456668Sshin { 299529088Smarkm if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 299629088Smarkm *cpp = 0; 299729088Smarkm *lenp = 0; 299857724Sshin return -1; 299929088Smarkm } 300029088Smarkm *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 300129088Smarkm *lenp = lsrp - *cpp; 300256668Sshin } 300356668Sshin freeaddrinfo(res); 300456668Sshin return 1; 300529088Smarkm} 3006