commands.c revision 103955
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 103955 2002-09-25 07:26:25Z 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 8496385Salfred#endif 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 *); 10787277Sjhay#ifdef INET6 10887139Smarkmstatic int switch_af(struct addrinfo **); 10987277Sjhay#endif 11087139Smarkmstatic int togglehelp(void); 11187139Smarkmstatic int send_tncmd(void (*)(int, int), const char *, char *); 11287139Smarkmstatic int setmod(int); 11387139Smarkmstatic int clearmode(int); 11487139Smarkmstatic int modehelp(void); 11587139Smarkmstatic int sourceroute(struct addrinfo *, char *, char **, int *, int *, int *); 11629088Smarkm 11729088Smarkmtypedef struct { 11887139Smarkm const char *name; /* command name */ 11987139Smarkm const char *help; /* help string (NULL for no help) */ 12087139Smarkm int (*handler)(int, char **); /* routine which executes command */ 12129088Smarkm int needconnect; /* Do we need to be connected to execute? */ 12229088Smarkm} Command; 12329088Smarkm 12429088Smarkmstatic char line[256]; 12529088Smarkmstatic char saveline[256]; 12629088Smarkmstatic int margc; 12729088Smarkmstatic char *margv[20]; 12829088Smarkm 12987139Smarkm#ifdef OPIE 13029181Smarkm#include <sys/wait.h> 13181965Smarkm#define PATH_OPIEKEY "/usr/bin/opiekey" 13287139Smarkmstatic int 13387139Smarkmopie_calc(int argc, char *argv[]) 13429181Smarkm{ 13529181Smarkm int status; 13629181Smarkm 13729181Smarkm if(argc != 3) { 13829181Smarkm printf("%s sequence challenge\n", argv[0]); 13987139Smarkm return (0); 14029181Smarkm } 14129181Smarkm 14229181Smarkm switch(fork()) { 14329181Smarkm case 0: 14481965Smarkm execv(PATH_OPIEKEY, argv); 14529181Smarkm exit (1); 14629181Smarkm case -1: 14729181Smarkm perror("fork"); 14829181Smarkm break; 14929181Smarkm default: 15029181Smarkm (void) wait(&status); 15129181Smarkm if (WIFEXITED(status)) 15229181Smarkm return (WEXITSTATUS(status)); 15329181Smarkm } 15487139Smarkm return (0); 15529181Smarkm} 15629181Smarkm#endif 15729181Smarkm 15887139Smarkmstatic void 15987139Smarkmmakeargv(void) 16029088Smarkm{ 16187139Smarkm char *cp, *cp2, c; 16287139Smarkm char **argp = margv; 16329088Smarkm 16429088Smarkm margc = 0; 16529088Smarkm cp = line; 16629088Smarkm if (*cp == '!') { /* Special case shell escape */ 16729088Smarkm strcpy(saveline, line); /* save for shell command */ 16887139Smarkm *argp++ = strdup("!"); /* No room in string to get this */ 16929088Smarkm margc++; 17029088Smarkm cp++; 17129088Smarkm } 17229181Smarkm while ((c = *cp)) { 17387139Smarkm int inquote = 0; 17429088Smarkm while (isspace(c)) 17529088Smarkm c = *++cp; 17629088Smarkm if (c == '\0') 17729088Smarkm break; 17829088Smarkm *argp++ = cp; 17929088Smarkm margc += 1; 18029088Smarkm for (cp2 = cp; c != '\0'; c = *++cp) { 18129088Smarkm if (inquote) { 18229088Smarkm if (c == inquote) { 18329088Smarkm inquote = 0; 18429088Smarkm continue; 18529088Smarkm } 18629088Smarkm } else { 18729088Smarkm if (c == '\\') { 18829088Smarkm if ((c = *++cp) == '\0') 18929088Smarkm break; 19029088Smarkm } else if (c == '"') { 19129088Smarkm inquote = '"'; 19229088Smarkm continue; 19329088Smarkm } else if (c == '\'') { 19429088Smarkm inquote = '\''; 19529088Smarkm continue; 19629088Smarkm } else if (isspace(c)) 19729088Smarkm break; 19829088Smarkm } 19929088Smarkm *cp2++ = c; 20029088Smarkm } 20129088Smarkm *cp2 = '\0'; 20229088Smarkm if (c == '\0') 20329088Smarkm break; 20429088Smarkm cp++; 20529088Smarkm } 20629088Smarkm *argp++ = 0; 20729088Smarkm} 20829088Smarkm 20929088Smarkm/* 21029088Smarkm * Make a character string into a number. 21129088Smarkm * 21229088Smarkm * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 21329088Smarkm */ 21429088Smarkm 21587139Smarkmstatic int 21687139Smarkmspecial(char *s) 21729088Smarkm{ 21887139Smarkm char c; 21929088Smarkm char b; 22029088Smarkm 22129088Smarkm switch (*s) { 22229088Smarkm case '^': 22329088Smarkm b = *++s; 22429088Smarkm if (b == '?') { 22529088Smarkm c = b | 0x40; /* DEL */ 22629088Smarkm } else { 22729088Smarkm c = b & 0x1f; 22829088Smarkm } 22929088Smarkm break; 23029088Smarkm default: 23129088Smarkm c = *s; 23229088Smarkm break; 23329088Smarkm } 23429088Smarkm return c; 23529088Smarkm} 23629088Smarkm 23729088Smarkm/* 23829088Smarkm * Construct a control character sequence 23929088Smarkm * for a special character. 24029088Smarkm */ 24187139Smarkmstatic const char * 24287139Smarkmcontrol(cc_t c) 24329088Smarkm{ 24429088Smarkm static char buf[5]; 24529088Smarkm /* 24629088Smarkm * The only way I could get the Sun 3.5 compiler 24729088Smarkm * to shut up about 24829088Smarkm * if ((unsigned int)c >= 0x80) 24929088Smarkm * was to assign "c" to an unsigned int variable... 25029088Smarkm * Arggg.... 25129088Smarkm */ 25287139Smarkm unsigned int uic = (unsigned int)c; 25329088Smarkm 25429088Smarkm if (uic == 0x7f) 25529088Smarkm return ("^?"); 25629088Smarkm if (c == (cc_t)_POSIX_VDISABLE) { 25729088Smarkm return "off"; 25829088Smarkm } 25929088Smarkm if (uic >= 0x80) { 26029088Smarkm buf[0] = '\\'; 26129088Smarkm buf[1] = ((c>>6)&07) + '0'; 26229088Smarkm buf[2] = ((c>>3)&07) + '0'; 26329088Smarkm buf[3] = (c&07) + '0'; 26429088Smarkm buf[4] = 0; 26529088Smarkm } else if (uic >= 0x20) { 26629088Smarkm buf[0] = c; 26729088Smarkm buf[1] = 0; 26829088Smarkm } else { 26929088Smarkm buf[0] = '^'; 27029088Smarkm buf[1] = '@'+c; 27129088Smarkm buf[2] = 0; 27229088Smarkm } 27329088Smarkm return (buf); 27429088Smarkm} 27529088Smarkm 27629088Smarkm/* 27729088Smarkm * The following are data structures and routines for 27829088Smarkm * the "send" command. 27929088Smarkm * 28029088Smarkm */ 28129088Smarkm 28229088Smarkmstruct sendlist { 28387139Smarkm const char *name; /* How user refers to it (case independent) */ 28487139Smarkm const char *help; /* Help information (0 ==> no help) */ 28529088Smarkm int needconnect; /* Need to be connected */ 28629088Smarkm int narg; /* Number of arguments */ 28787139Smarkm int (*handler)(char *, ...); /* Routine to perform (for special ops) */ 28829088Smarkm int nbyte; /* Number of bytes to send this command */ 28929088Smarkm int what; /* Character to be sent (<0 ==> special) */ 29029088Smarkm}; 29129088Smarkm 29229088Smarkm 29329088Smarkmstatic int 29487155Smarkm send_esc(void), 29587155Smarkm send_help(void), 29687155Smarkm send_docmd(char *), 29787155Smarkm send_dontcmd(char *), 29887155Smarkm send_willcmd(char *), 29987155Smarkm send_wontcmd(char *); 30029088Smarkm 30129088Smarkmstatic struct sendlist Sendlist[] = { 30287139Smarkm { "ao", "Send Telnet Abort output", 1, 0, NULL, 2, AO }, 30387139Smarkm { "ayt", "Send Telnet 'Are You There'", 1, 0, NULL, 2, AYT }, 30487139Smarkm { "brk", "Send Telnet Break", 1, 0, NULL, 2, BREAK }, 30587139Smarkm { "break", NULL, 1, 0, NULL, 2, BREAK }, 30687139Smarkm { "ec", "Send Telnet Erase Character", 1, 0, NULL, 2, EC }, 30787139Smarkm { "el", "Send Telnet Erase Line", 1, 0, NULL, 2, EL }, 30887139Smarkm { "escape", "Send current escape character",1, 0, (int (*)(char *, ...))send_esc, 1, 0 }, 30987139Smarkm { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, NULL, 2, GA }, 31087139Smarkm { "ip", "Send Telnet Interrupt Process",1, 0, NULL, 2, IP }, 31187139Smarkm { "intp", NULL, 1, 0, NULL, 2, IP }, 31287139Smarkm { "interrupt", NULL, 1, 0, NULL, 2, IP }, 31387139Smarkm { "intr", NULL, 1, 0, NULL, 2, IP }, 31487139Smarkm { "nop", "Send Telnet 'No operation'", 1, 0, NULL, 2, NOP }, 31587139Smarkm { "eor", "Send Telnet 'End of Record'", 1, 0, NULL, 2, EOR }, 31687139Smarkm { "abort", "Send Telnet 'Abort Process'", 1, 0, NULL, 2, ABORT }, 31787139Smarkm { "susp", "Send Telnet 'Suspend Process'",1, 0, NULL, 2, SUSP }, 31887139Smarkm { "eof", "Send Telnet End of File Character", 1, 0, NULL, 2, xEOF }, 31987139Smarkm { "synch", "Perform Telnet 'Synch operation'", 1, 0, (int (*)(char *, ...))dosynch, 2, 0 }, 32087139Smarkm { "getstatus", "Send request for STATUS", 1, 0, (int (*)(char *, ...))get_status, 6, 0 }, 32187139Smarkm { "?", "Display send options", 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, 32287139Smarkm { "help", NULL, 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, 32387139Smarkm { "do", NULL, 0, 1, (int (*)(char *, ...))send_docmd, 3, 0 }, 32487139Smarkm { "dont", NULL, 0, 1, (int (*)(char *, ...))send_dontcmd, 3, 0 }, 32587139Smarkm { "will", NULL, 0, 1, (int (*)(char *, ...))send_willcmd, 3, 0 }, 32687139Smarkm { "wont", NULL, 0, 1, (int (*)(char *, ...))send_wontcmd, 3, 0 }, 32787139Smarkm { NULL, NULL, 0, 0, NULL, 0, 0 } 32829088Smarkm}; 32929088Smarkm 33029088Smarkm#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ 33129088Smarkm sizeof(struct sendlist))) 33229088Smarkm 33387139Smarkmstatic int 33487139Smarkmsendcmd(int argc, char *argv[]) 33529088Smarkm{ 33629088Smarkm int count; /* how many bytes we are going to need to send */ 33729088Smarkm int i; 33829088Smarkm struct sendlist *s; /* pointer to current command */ 33929088Smarkm int success = 0; 34029088Smarkm int needconnect = 0; 34129088Smarkm 34229088Smarkm if (argc < 2) { 34329088Smarkm printf("need at least one argument for 'send' command\n"); 34429088Smarkm printf("'send ?' for help\n"); 34529088Smarkm return 0; 34629088Smarkm } 34729088Smarkm /* 34829088Smarkm * First, validate all the send arguments. 34929088Smarkm * In addition, we see how much space we are going to need, and 35029088Smarkm * whether or not we will be doing a "SYNCH" operation (which 35129088Smarkm * flushes the network queue). 35229088Smarkm */ 35329088Smarkm count = 0; 35429088Smarkm for (i = 1; i < argc; i++) { 35529088Smarkm s = GETSEND(argv[i]); 35629088Smarkm if (s == 0) { 35729088Smarkm printf("Unknown send argument '%s'\n'send ?' for help.\n", 35829088Smarkm argv[i]); 35929088Smarkm return 0; 36087139Smarkm } else if (Ambiguous((void *)s)) { 36129088Smarkm printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 36229088Smarkm argv[i]); 36329088Smarkm return 0; 36429088Smarkm } 36529088Smarkm if (i + s->narg >= argc) { 36629088Smarkm fprintf(stderr, 36729088Smarkm "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", 36829088Smarkm s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 36929088Smarkm return 0; 37029088Smarkm } 37129088Smarkm count += s->nbyte; 37287139Smarkm if ((void *)s->handler == (void *)send_help) { 37329088Smarkm send_help(); 37429088Smarkm return 0; 37529088Smarkm } 37629088Smarkm 37729088Smarkm i += s->narg; 37829088Smarkm needconnect += s->needconnect; 37929088Smarkm } 38029088Smarkm if (!connected && needconnect) { 38129088Smarkm printf("?Need to be connected first.\n"); 38229088Smarkm printf("'send ?' for help\n"); 38329088Smarkm return 0; 38429088Smarkm } 38529088Smarkm /* Now, do we have enough room? */ 38629088Smarkm if (NETROOM() < count) { 38729088Smarkm printf("There is not enough room in the buffer TO the network\n"); 38829088Smarkm printf("to process your request. Nothing will be done.\n"); 38929088Smarkm printf("('send synch' will throw away most data in the network\n"); 39029088Smarkm printf("buffer, if this might help.)\n"); 39129088Smarkm return 0; 39229088Smarkm } 39329088Smarkm /* OK, they are all OK, now go through again and actually send */ 39429088Smarkm count = 0; 39529088Smarkm for (i = 1; i < argc; i++) { 39629088Smarkm if ((s = GETSEND(argv[i])) == 0) { 39729088Smarkm fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 39887139Smarkm quit(); 39929088Smarkm /*NOTREACHED*/ 40029088Smarkm } 40129088Smarkm if (s->handler) { 40229088Smarkm count++; 40329088Smarkm success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 40429088Smarkm (s->narg > 1) ? argv[i+2] : 0); 40529088Smarkm i += s->narg; 40629088Smarkm } else { 40729088Smarkm NET2ADD(IAC, s->what); 40829088Smarkm printoption("SENT", IAC, s->what); 40929088Smarkm } 41029088Smarkm } 41129088Smarkm return (count == success); 41229088Smarkm} 41329088Smarkm 41487139Smarkmstatic int 41587139Smarkmsend_esc(void) 41629088Smarkm{ 41729088Smarkm NETADD(escape); 41829088Smarkm return 1; 41929088Smarkm} 42029088Smarkm 42187139Smarkmstatic int 42287139Smarkmsend_docmd(char *name) 42329088Smarkm{ 42429088Smarkm return(send_tncmd(send_do, "do", name)); 42529088Smarkm} 42629088Smarkm 42787139Smarkmstatic int 42829088Smarkmsend_dontcmd(name) 42929088Smarkm char *name; 43029088Smarkm{ 43129088Smarkm return(send_tncmd(send_dont, "dont", name)); 43229088Smarkm} 43387139Smarkm 43487139Smarkmstatic int 43587139Smarkmsend_willcmd(char *name) 43629088Smarkm{ 43729088Smarkm return(send_tncmd(send_will, "will", name)); 43829088Smarkm} 43987139Smarkm 44087139Smarkmstatic int 44187139Smarkmsend_wontcmd(char *name) 44229088Smarkm{ 44329088Smarkm return(send_tncmd(send_wont, "wont", name)); 44429088Smarkm} 44529088Smarkm 44687139Smarkmstatic int 44787139Smarkmsend_tncmd(void (*func)(int, int), const char *cmd, char *name) 44829088Smarkm{ 44929088Smarkm char **cpp; 45029088Smarkm extern char *telopts[]; 45187139Smarkm int val = 0; 45229088Smarkm 45329088Smarkm if (isprefix(name, "help") || isprefix(name, "?")) { 45487139Smarkm int col, len; 45529088Smarkm 456103955Smarkm printf("usage: send %s <value|option>\n", cmd); 45729088Smarkm printf("\"value\" must be from 0 to 255\n"); 45829088Smarkm printf("Valid options are:\n\t"); 45929088Smarkm 46029088Smarkm col = 8; 46129088Smarkm for (cpp = telopts; *cpp; cpp++) { 46229088Smarkm len = strlen(*cpp) + 3; 46329088Smarkm if (col + len > 65) { 46429088Smarkm printf("\n\t"); 46529088Smarkm col = 8; 46629088Smarkm } 46729088Smarkm printf(" \"%s\"", *cpp); 46829088Smarkm col += len; 46929088Smarkm } 47029088Smarkm printf("\n"); 47129088Smarkm return 0; 47229088Smarkm } 47329088Smarkm cpp = (char **)genget(name, telopts, sizeof(char *)); 47429088Smarkm if (Ambiguous(cpp)) { 47529088Smarkm fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", 47629088Smarkm name, cmd); 47729088Smarkm return 0; 47829088Smarkm } 47929088Smarkm if (cpp) { 48029088Smarkm val = cpp - telopts; 48129088Smarkm } else { 48287139Smarkm char *cp = name; 48329088Smarkm 48429088Smarkm while (*cp >= '0' && *cp <= '9') { 48529088Smarkm val *= 10; 48629088Smarkm val += *cp - '0'; 48729088Smarkm cp++; 48829088Smarkm } 48929088Smarkm if (*cp != 0) { 49029088Smarkm fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 49129088Smarkm name, cmd); 49229088Smarkm return 0; 49329088Smarkm } else if (val < 0 || val > 255) { 49429088Smarkm fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", 49529088Smarkm name, cmd); 49629088Smarkm return 0; 49729088Smarkm } 49829088Smarkm } 49929088Smarkm if (!connected) { 50029088Smarkm printf("?Need to be connected first.\n"); 50129088Smarkm return 0; 50229088Smarkm } 50329088Smarkm (*func)(val, 1); 50429088Smarkm return 1; 50529088Smarkm} 50629088Smarkm 50787139Smarkmstatic int 50887139Smarkmsend_help(void) 50929088Smarkm{ 51029088Smarkm struct sendlist *s; /* pointer to current command */ 51129088Smarkm for (s = Sendlist; s->name; s++) { 51229088Smarkm if (s->help) 51329088Smarkm printf("%-15s %s\n", s->name, s->help); 51429088Smarkm } 51529088Smarkm return(0); 51629088Smarkm} 51729088Smarkm 51829088Smarkm/* 51929088Smarkm * The following are the routines and data structures referred 52029088Smarkm * to by the arguments to the "toggle" command. 52129088Smarkm */ 52229088Smarkm 52387139Smarkmstatic int 52487139Smarkmlclchars(void) 52529088Smarkm{ 52629088Smarkm donelclchars = 1; 52729088Smarkm return 1; 52829088Smarkm} 52929088Smarkm 53087139Smarkmstatic int 53187139Smarkmtogdebug(void) 53229088Smarkm{ 53329088Smarkm#ifndef NOT43 53429088Smarkm if (net > 0 && 53529088Smarkm (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 53629088Smarkm perror("setsockopt (SO_DEBUG)"); 53729088Smarkm } 53829088Smarkm#else /* NOT43 */ 53929088Smarkm if (debug) { 54029181Smarkm if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) 54129088Smarkm perror("setsockopt (SO_DEBUG)"); 54229088Smarkm } else 54329088Smarkm printf("Cannot turn off socket debugging\n"); 54429088Smarkm#endif /* NOT43 */ 54529088Smarkm return 1; 54629088Smarkm} 54729088Smarkm 54829088Smarkm 54987139Smarkmstatic int 55087139Smarkmtogcrlf(void) 55129088Smarkm{ 55229088Smarkm if (crlf) { 55329088Smarkm printf("Will send carriage returns as telnet <CR><LF>.\n"); 55429088Smarkm } else { 55529088Smarkm printf("Will send carriage returns as telnet <CR><NUL>.\n"); 55629088Smarkm } 55729088Smarkm return 1; 55829088Smarkm} 55929088Smarkm 56029088Smarkmint binmode; 56129088Smarkm 56287139Smarkmstatic int 56387139Smarkmtogbinary(int val) 56429088Smarkm{ 56529088Smarkm donebinarytoggle = 1; 56629088Smarkm 56729088Smarkm if (val >= 0) { 56829088Smarkm binmode = val; 56929088Smarkm } else { 57029088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 57129088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 57229088Smarkm binmode = 1; 57329088Smarkm } else if (my_want_state_is_wont(TELOPT_BINARY) && 57429088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 57529088Smarkm binmode = 0; 57629088Smarkm } 57729088Smarkm val = binmode ? 0 : 1; 57829088Smarkm } 57929088Smarkm 58029088Smarkm if (val == 1) { 58129088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 58229088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 58329088Smarkm printf("Already operating in binary mode with remote host.\n"); 58429088Smarkm } else { 58529088Smarkm printf("Negotiating binary mode with remote host.\n"); 58629088Smarkm tel_enter_binary(3); 58729088Smarkm } 58829088Smarkm } else { 58929088Smarkm if (my_want_state_is_wont(TELOPT_BINARY) && 59029088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 59129088Smarkm printf("Already in network ascii mode with remote host.\n"); 59229088Smarkm } else { 59329088Smarkm printf("Negotiating network ascii mode with remote host.\n"); 59429088Smarkm tel_leave_binary(3); 59529088Smarkm } 59629088Smarkm } 59729088Smarkm return 1; 59829088Smarkm} 59929088Smarkm 60087139Smarkmstatic int 60187139Smarkmtogrbinary(int val) 60229088Smarkm{ 60329088Smarkm donebinarytoggle = 1; 60429088Smarkm 60529088Smarkm if (val == -1) 60629088Smarkm val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 60729088Smarkm 60829088Smarkm if (val == 1) { 60929088Smarkm if (my_want_state_is_do(TELOPT_BINARY)) { 61029088Smarkm printf("Already receiving in binary mode.\n"); 61129088Smarkm } else { 61229088Smarkm printf("Negotiating binary mode on input.\n"); 61329088Smarkm tel_enter_binary(1); 61429088Smarkm } 61529088Smarkm } else { 61629088Smarkm if (my_want_state_is_dont(TELOPT_BINARY)) { 61729088Smarkm printf("Already receiving in network ascii mode.\n"); 61829088Smarkm } else { 61929088Smarkm printf("Negotiating network ascii mode on input.\n"); 62029088Smarkm tel_leave_binary(1); 62129088Smarkm } 62229088Smarkm } 62329088Smarkm return 1; 62429088Smarkm} 62529088Smarkm 62687139Smarkmstatic int 62787139Smarkmtogxbinary(int val) 62829088Smarkm{ 62929088Smarkm donebinarytoggle = 1; 63029088Smarkm 63129088Smarkm if (val == -1) 63229088Smarkm val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 63329088Smarkm 63429088Smarkm if (val == 1) { 63529088Smarkm if (my_want_state_is_will(TELOPT_BINARY)) { 63629088Smarkm printf("Already transmitting in binary mode.\n"); 63729088Smarkm } else { 63829088Smarkm printf("Negotiating binary mode on output.\n"); 63929088Smarkm tel_enter_binary(2); 64029088Smarkm } 64129088Smarkm } else { 64229088Smarkm if (my_want_state_is_wont(TELOPT_BINARY)) { 64329088Smarkm printf("Already transmitting in network ascii mode.\n"); 64429088Smarkm } else { 64529088Smarkm printf("Negotiating network ascii mode on output.\n"); 64629088Smarkm tel_leave_binary(2); 64729088Smarkm } 64829088Smarkm } 64929088Smarkm return 1; 65029088Smarkm} 65129088Smarkm 65229088Smarkmstruct togglelist { 65387139Smarkm const char *name; /* name of toggle */ 65487139Smarkm const char *help; /* help message */ 65587139Smarkm int (*handler)(int); /* routine to do actual setting */ 65629088Smarkm int *variable; 65787139Smarkm const char *actionexplanation; 65829088Smarkm}; 65929088Smarkm 66029088Smarkmstatic struct togglelist Togglelist[] = { 66129088Smarkm { "autoflush", 66229088Smarkm "flushing of output when sending interrupt characters", 66329088Smarkm 0, 66429088Smarkm &autoflush, 66529088Smarkm "flush output when sending interrupt characters" }, 66629088Smarkm { "autosynch", 66729088Smarkm "automatic sending of interrupt characters in urgent mode", 66829088Smarkm 0, 66929088Smarkm &autosynch, 67029088Smarkm "send interrupt characters in urgent mode" }, 67187139Smarkm#ifdef AUTHENTICATION 67229088Smarkm { "autologin", 67329088Smarkm "automatic sending of login and/or authentication info", 67429088Smarkm 0, 67529088Smarkm &autologin, 67629088Smarkm "send login name and/or authentication information" }, 67729088Smarkm { "authdebug", 67829088Smarkm "Toggle authentication debugging", 67929088Smarkm auth_togdebug, 68029088Smarkm 0, 68129088Smarkm "print authentication debugging information" }, 68229088Smarkm#endif 68329088Smarkm#ifdef ENCRYPTION 68429088Smarkm { "autoencrypt", 68529088Smarkm "automatic encryption of data stream", 68629088Smarkm EncryptAutoEnc, 68729088Smarkm 0, 68829088Smarkm "automatically encrypt output" }, 68929088Smarkm { "autodecrypt", 69029088Smarkm "automatic decryption of data stream", 69129088Smarkm EncryptAutoDec, 69229088Smarkm 0, 69329088Smarkm "automatically decrypt input" }, 69429088Smarkm { "verbose_encrypt", 69529088Smarkm "Toggle verbose encryption output", 69629088Smarkm EncryptVerbose, 69729088Smarkm 0, 69829088Smarkm "print verbose encryption output" }, 69929088Smarkm { "encdebug", 70029088Smarkm "Toggle encryption debugging", 70129088Smarkm EncryptDebug, 70229088Smarkm 0, 70329088Smarkm "print encryption debugging information" }, 70429088Smarkm#endif /* ENCRYPTION */ 70529088Smarkm { "skiprc", 70629088Smarkm "don't read ~/.telnetrc file", 70729088Smarkm 0, 70829088Smarkm &skiprc, 70929088Smarkm "skip reading of ~/.telnetrc file" }, 71029088Smarkm { "binary", 71129088Smarkm "sending and receiving of binary data", 71229088Smarkm togbinary, 71329088Smarkm 0, 71429088Smarkm 0 }, 71529088Smarkm { "inbinary", 71629088Smarkm "receiving of binary data", 71729088Smarkm togrbinary, 71829088Smarkm 0, 71929088Smarkm 0 }, 72029088Smarkm { "outbinary", 72129088Smarkm "sending of binary data", 72229088Smarkm togxbinary, 72329088Smarkm 0, 72429088Smarkm 0 }, 72529088Smarkm { "crlf", 72629088Smarkm "sending carriage returns as telnet <CR><LF>", 72787139Smarkm (int (*)(int))togcrlf, 72829088Smarkm &crlf, 72929088Smarkm 0 }, 73029088Smarkm { "crmod", 73129088Smarkm "mapping of received carriage returns", 73229088Smarkm 0, 73329088Smarkm &crmod, 73429088Smarkm "map carriage return on output" }, 73529088Smarkm { "localchars", 73629088Smarkm "local recognition of certain control characters", 73787139Smarkm (int (*)(int))lclchars, 73829088Smarkm &localchars, 73929088Smarkm "recognize certain control characters" }, 74087139Smarkm { " ", "", NULL, NULL, NULL }, /* empty line */ 74129088Smarkm { "debug", 74229088Smarkm "debugging", 74387139Smarkm (int (*)(int))togdebug, 74429088Smarkm &debug, 74529088Smarkm "turn on socket level debugging" }, 74629088Smarkm { "netdata", 74729088Smarkm "printing of hexadecimal network data (debugging)", 74829088Smarkm 0, 74929088Smarkm &netdata, 75029088Smarkm "print hexadecimal representation of network traffic" }, 75129088Smarkm { "prettydump", 75229088Smarkm "output of \"netdata\" to user readable format (debugging)", 75329088Smarkm 0, 75429088Smarkm &prettydump, 75529088Smarkm "print user readable output for \"netdata\"" }, 75629088Smarkm { "options", 75729088Smarkm "viewing of options processing (debugging)", 75829088Smarkm 0, 75929088Smarkm &showoptions, 76029088Smarkm "show option processing" }, 76129088Smarkm { "termdata", 76229088Smarkm "(debugging) toggle printing of hexadecimal terminal data", 76329088Smarkm 0, 76429088Smarkm &termdata, 76529088Smarkm "print hexadecimal representation of terminal traffic" }, 76629088Smarkm { "?", 76787139Smarkm NULL, 76887139Smarkm (int (*)(int))togglehelp, 76987139Smarkm NULL, 77087139Smarkm NULL }, 77187139Smarkm { NULL, NULL, NULL, NULL, NULL }, 77229088Smarkm { "help", 77387139Smarkm NULL, 77487139Smarkm (int (*)(int))togglehelp, 77587139Smarkm NULL, 77687139Smarkm NULL }, 77787139Smarkm { NULL, NULL, NULL, NULL, NULL } 77829088Smarkm}; 77929088Smarkm 78087139Smarkmstatic int 78187139Smarkmtogglehelp(void) 78229088Smarkm{ 78329088Smarkm struct togglelist *c; 78429088Smarkm 78529088Smarkm for (c = Togglelist; c->name; c++) { 78629088Smarkm if (c->help) { 78729088Smarkm if (*c->help) 78829088Smarkm printf("%-15s toggle %s\n", c->name, c->help); 78929088Smarkm else 79029088Smarkm printf("\n"); 79129088Smarkm } 79229088Smarkm } 79329088Smarkm printf("\n"); 79429088Smarkm printf("%-15s %s\n", "?", "display help information"); 79529088Smarkm return 0; 79629088Smarkm} 79729088Smarkm 79887139Smarkmstatic void 79987139Smarkmsettogglehelp(int set) 80029088Smarkm{ 80129088Smarkm struct togglelist *c; 80229088Smarkm 80329088Smarkm for (c = Togglelist; c->name; c++) { 80429088Smarkm if (c->help) { 80529088Smarkm if (*c->help) 80629088Smarkm printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 80729088Smarkm c->help); 80829088Smarkm else 80929088Smarkm printf("\n"); 81029088Smarkm } 81129088Smarkm } 81229088Smarkm} 81329088Smarkm 81429088Smarkm#define GETTOGGLE(name) (struct togglelist *) \ 81529088Smarkm genget(name, (char **) Togglelist, sizeof(struct togglelist)) 81629088Smarkm 81787139Smarkmstatic int 81887139Smarkmtoggle(int argc, char *argv[]) 81929088Smarkm{ 82029088Smarkm int retval = 1; 82129088Smarkm char *name; 82229088Smarkm struct togglelist *c; 82329088Smarkm 82429088Smarkm if (argc < 2) { 82529088Smarkm fprintf(stderr, 82629088Smarkm "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 82729088Smarkm return 0; 82829088Smarkm } 82929088Smarkm argc--; 83029088Smarkm argv++; 83129088Smarkm while (argc--) { 83229088Smarkm name = *argv++; 83329088Smarkm c = GETTOGGLE(name); 83487139Smarkm if (Ambiguous((void *)c)) { 83529088Smarkm fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 83629088Smarkm name); 83729088Smarkm return 0; 83829088Smarkm } else if (c == 0) { 83929088Smarkm fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 84029088Smarkm name); 84129088Smarkm return 0; 84229088Smarkm } else { 84329088Smarkm if (c->variable) { 84429088Smarkm *c->variable = !*c->variable; /* invert it */ 84529088Smarkm if (c->actionexplanation) { 84629088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 84729088Smarkm c->actionexplanation); 84829088Smarkm } 84929088Smarkm } 85029088Smarkm if (c->handler) { 85129088Smarkm retval &= (*c->handler)(-1); 85229088Smarkm } 85329088Smarkm } 85429088Smarkm } 85529088Smarkm return retval; 85629088Smarkm} 85729088Smarkm 85829088Smarkm/* 85929088Smarkm * The following perform the "set" command. 86029088Smarkm */ 86129088Smarkm 86229088Smarkm#ifdef USE_TERMIO 86387139Smarkmstruct termio new_tc = { 0, 0, 0, 0, {}, 0, 0 }; 86429088Smarkm#endif 86529088Smarkm 86629088Smarkmstruct setlist { 86787139Smarkm const char *name; /* name */ 86887139Smarkm const char *help; /* help information */ 86987139Smarkm void (*handler)(char *); 87029088Smarkm cc_t *charp; /* where it is located at */ 87129088Smarkm}; 87229088Smarkm 87329088Smarkmstatic struct setlist Setlist[] = { 87429088Smarkm#ifdef KLUDGELINEMODE 87587139Smarkm { "echo", "character to toggle local echoing on/off", NULL, &echoc }, 87629088Smarkm#endif 87787139Smarkm { "escape", "character to escape back to telnet command mode", NULL, &escape }, 87829088Smarkm { "rlogin", "rlogin escape character", 0, &rlogin }, 87929088Smarkm { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, 88087139Smarkm { " ", "", NULL, NULL }, 88187139Smarkm { " ", "The following need 'localchars' to be toggled true", NULL, NULL }, 88287139Smarkm { "flushoutput", "character to cause an Abort Output", NULL, termFlushCharp }, 88387139Smarkm { "interrupt", "character to cause an Interrupt Process", NULL, termIntCharp }, 88487139Smarkm { "quit", "character to cause an Abort process", NULL, termQuitCharp }, 88587139Smarkm { "eof", "character to cause an EOF ", NULL, termEofCharp }, 88687139Smarkm { " ", "", NULL, NULL }, 88787139Smarkm { " ", "The following are for local editing in linemode", NULL, NULL }, 88887139Smarkm { "erase", "character to use to erase a character", NULL, termEraseCharp }, 88987139Smarkm { "kill", "character to use to erase a line", NULL, termKillCharp }, 89087139Smarkm { "lnext", "character to use for literal next", NULL, termLiteralNextCharp }, 89187139Smarkm { "susp", "character to cause a Suspend Process", NULL, termSuspCharp }, 89287139Smarkm { "reprint", "character to use for line reprint", NULL, termRprntCharp }, 89387139Smarkm { "worderase", "character to use to erase a word", NULL, termWerasCharp }, 89487139Smarkm { "start", "character to use for XON", NULL, termStartCharp }, 89587139Smarkm { "stop", "character to use for XOFF", NULL, termStopCharp }, 89687139Smarkm { "forw1", "alternate end of line character", NULL, termForw1Charp }, 89787139Smarkm { "forw2", "alternate end of line character", NULL, termForw2Charp }, 89887139Smarkm { "ayt", "alternate AYT character", NULL, termAytCharp }, 89987139Smarkm { NULL, NULL, NULL, NULL } 90029088Smarkm}; 90129088Smarkm 90287139Smarkmstatic struct setlist * 90387139Smarkmgetset(char *name) 90429088Smarkm{ 90529088Smarkm return (struct setlist *) 90629088Smarkm genget(name, (char **) Setlist, sizeof(struct setlist)); 90729088Smarkm} 90829088Smarkm 90987139Smarkmvoid 91087139Smarkmset_escape_char(char *s) 91129088Smarkm{ 91229088Smarkm if (rlogin != _POSIX_VDISABLE) { 91329088Smarkm rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 91429088Smarkm printf("Telnet rlogin escape character is '%s'.\n", 91529088Smarkm control(rlogin)); 91629088Smarkm } else { 91729088Smarkm escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 91829088Smarkm printf("Telnet escape character is '%s'.\n", control(escape)); 91929088Smarkm } 92029088Smarkm} 92129088Smarkm 92287139Smarkmstatic int 92387139Smarkmsetcmd(int argc, char *argv[]) 92429088Smarkm{ 92529088Smarkm int value; 92629088Smarkm struct setlist *ct; 92729088Smarkm struct togglelist *c; 92829088Smarkm 92929088Smarkm if (argc < 2 || argc > 3) { 93029088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 93129088Smarkm return 0; 93229088Smarkm } 93329088Smarkm if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 93429088Smarkm for (ct = Setlist; ct->name; ct++) 93529088Smarkm printf("%-15s %s\n", ct->name, ct->help); 93629088Smarkm printf("\n"); 93729088Smarkm settogglehelp(1); 93829088Smarkm printf("%-15s %s\n", "?", "display help information"); 93929088Smarkm return 0; 94029088Smarkm } 94129088Smarkm 94229088Smarkm ct = getset(argv[1]); 94329088Smarkm if (ct == 0) { 94429088Smarkm c = GETTOGGLE(argv[1]); 94529088Smarkm if (c == 0) { 94629088Smarkm fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 94729088Smarkm argv[1]); 94829088Smarkm return 0; 94987139Smarkm } else if (Ambiguous((void *)c)) { 95029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 95129088Smarkm argv[1]); 95229088Smarkm return 0; 95329088Smarkm } 95429088Smarkm if (c->variable) { 95529088Smarkm if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 95629088Smarkm *c->variable = 1; 95729088Smarkm else if (strcmp("off", argv[2]) == 0) 95829088Smarkm *c->variable = 0; 95929088Smarkm else { 96029088Smarkm printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 96129088Smarkm return 0; 96229088Smarkm } 96329088Smarkm if (c->actionexplanation) { 96429088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 96529088Smarkm c->actionexplanation); 96629088Smarkm } 96729088Smarkm } 96829088Smarkm if (c->handler) 96929088Smarkm (*c->handler)(1); 97029088Smarkm } else if (argc != 3) { 97129088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 97229088Smarkm return 0; 97387139Smarkm } else if (Ambiguous((void *)ct)) { 97429088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 97529088Smarkm argv[1]); 97629088Smarkm return 0; 97729088Smarkm } else if (ct->handler) { 97829088Smarkm (*ct->handler)(argv[2]); 97929088Smarkm printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 98029088Smarkm } else { 98129088Smarkm if (strcmp("off", argv[2])) { 98229088Smarkm value = special(argv[2]); 98329088Smarkm } else { 98429088Smarkm value = _POSIX_VDISABLE; 98529088Smarkm } 98629088Smarkm *(ct->charp) = (cc_t)value; 98729088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 98829088Smarkm } 98929088Smarkm slc_check(); 99029088Smarkm return 1; 99129088Smarkm} 99229088Smarkm 99387139Smarkmstatic int 99487139Smarkmunsetcmd(int argc, char *argv[]) 99529088Smarkm{ 99629088Smarkm struct setlist *ct; 99729088Smarkm struct togglelist *c; 99887139Smarkm char *name; 99929088Smarkm 100029088Smarkm if (argc < 2) { 100129088Smarkm fprintf(stderr, 100229088Smarkm "Need an argument to 'unset' command. 'unset ?' for help.\n"); 100329088Smarkm return 0; 100429088Smarkm } 100529088Smarkm if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 100629088Smarkm for (ct = Setlist; ct->name; ct++) 100729088Smarkm printf("%-15s %s\n", ct->name, ct->help); 100829088Smarkm printf("\n"); 100929088Smarkm settogglehelp(0); 101029088Smarkm printf("%-15s %s\n", "?", "display help information"); 101129088Smarkm return 0; 101229088Smarkm } 101329088Smarkm 101429088Smarkm argc--; 101529088Smarkm argv++; 101629088Smarkm while (argc--) { 101729088Smarkm name = *argv++; 101829088Smarkm ct = getset(name); 101929088Smarkm if (ct == 0) { 102029088Smarkm c = GETTOGGLE(name); 102129088Smarkm if (c == 0) { 102229088Smarkm fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 102329088Smarkm name); 102429088Smarkm return 0; 102587139Smarkm } else if (Ambiguous((void *)c)) { 102629088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 102729088Smarkm name); 102829088Smarkm return 0; 102929088Smarkm } 103029088Smarkm if (c->variable) { 103129088Smarkm *c->variable = 0; 103229088Smarkm if (c->actionexplanation) { 103329088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 103429088Smarkm c->actionexplanation); 103529088Smarkm } 103629088Smarkm } 103729088Smarkm if (c->handler) 103829088Smarkm (*c->handler)(0); 103987139Smarkm } else if (Ambiguous((void *)ct)) { 104029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 104129088Smarkm name); 104229088Smarkm return 0; 104329088Smarkm } else if (ct->handler) { 104429088Smarkm (*ct->handler)(0); 104529088Smarkm printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 104629088Smarkm } else { 104729088Smarkm *(ct->charp) = _POSIX_VDISABLE; 104829088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 104929088Smarkm } 105029088Smarkm } 105129088Smarkm return 1; 105229088Smarkm} 105329088Smarkm 105429088Smarkm/* 105529088Smarkm * The following are the data structures and routines for the 105629088Smarkm * 'mode' command. 105729088Smarkm */ 105829088Smarkm#ifdef KLUDGELINEMODE 105929088Smarkmextern int kludgelinemode; 106029088Smarkm 106187139Smarkmstatic int 106287139Smarkmdokludgemode(void) 106329088Smarkm{ 106429088Smarkm kludgelinemode = 1; 106529088Smarkm send_wont(TELOPT_LINEMODE, 1); 106629088Smarkm send_dont(TELOPT_SGA, 1); 106729088Smarkm send_dont(TELOPT_ECHO, 1); 106849861Snsayer return 1; 106929088Smarkm} 107029088Smarkm#endif 107129088Smarkm 107287139Smarkmstatic int 107387139Smarkmdolinemode(void) 107429088Smarkm{ 107529088Smarkm#ifdef KLUDGELINEMODE 107629088Smarkm if (kludgelinemode) 107729088Smarkm send_dont(TELOPT_SGA, 1); 107829088Smarkm#endif 107929088Smarkm send_will(TELOPT_LINEMODE, 1); 108029088Smarkm send_dont(TELOPT_ECHO, 1); 108129088Smarkm return 1; 108229088Smarkm} 108329088Smarkm 108487139Smarkmstatic int 108587139Smarkmdocharmode(void) 108629088Smarkm{ 108729088Smarkm#ifdef KLUDGELINEMODE 108829088Smarkm if (kludgelinemode) 108929088Smarkm send_do(TELOPT_SGA, 1); 109029088Smarkm else 109129088Smarkm#endif 109229088Smarkm send_wont(TELOPT_LINEMODE, 1); 109329088Smarkm send_do(TELOPT_ECHO, 1); 109429088Smarkm return 1; 109529088Smarkm} 109629088Smarkm 109787139Smarkmstatic int 109887139Smarkmdolmmode(int bit, int on) 109929088Smarkm{ 110029088Smarkm unsigned char c; 110129088Smarkm extern int linemode; 110229088Smarkm 110329088Smarkm if (my_want_state_is_wont(TELOPT_LINEMODE)) { 110429088Smarkm printf("?Need to have LINEMODE option enabled first.\n"); 110529088Smarkm printf("'mode ?' for help.\n"); 110629088Smarkm return 0; 110729088Smarkm } 110829088Smarkm 110929088Smarkm if (on) 111029088Smarkm c = (linemode | bit); 111129088Smarkm else 111229088Smarkm c = (linemode & ~bit); 111329088Smarkm lm_mode(&c, 1, 1); 111429088Smarkm return 1; 111529088Smarkm} 111629088Smarkm 111787139Smarkmstatic int 111887139Smarkmsetmod(int bit) 111929088Smarkm{ 112029088Smarkm return dolmmode(bit, 1); 112129088Smarkm} 112229088Smarkm 112387139Smarkmstatic int 112487139Smarkmclearmode(int bit) 112529088Smarkm{ 112629088Smarkm return dolmmode(bit, 0); 112729088Smarkm} 112829088Smarkm 112929088Smarkmstruct modelist { 113087139Smarkm const char *name; /* command name */ 113187139Smarkm const char *help; /* help string */ 113287139Smarkm int (*handler)(int);/* routine which executes command */ 113329088Smarkm int needconnect; /* Do we need to be connected to execute? */ 113429088Smarkm int arg1; 113529088Smarkm}; 113629088Smarkm 113729088Smarkmstatic struct modelist ModeList[] = { 113887139Smarkm { "character", "Disable LINEMODE option", (int (*)(int))docharmode, 1, 0 }, 113929088Smarkm#ifdef KLUDGELINEMODE 114087139Smarkm { "", "(or disable obsolete line-by-line mode)", NULL, 0, 0 }, 114129088Smarkm#endif 114287139Smarkm { "line", "Enable LINEMODE option", (int (*)(int))dolinemode, 1, 0 }, 114329088Smarkm#ifdef KLUDGELINEMODE 114487139Smarkm { "", "(or enable obsolete line-by-line mode)", NULL, 0, 0 }, 114529088Smarkm#endif 114687139Smarkm { "", "", NULL, 0, 0 }, 114787139Smarkm { "", "These require the LINEMODE option to be enabled", NULL, 0, 0 }, 114829181Smarkm { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, 114929181Smarkm { "+isig", 0, setmod, 1, MODE_TRAPSIG }, 115029088Smarkm { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 115129181Smarkm { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, 115229181Smarkm { "+edit", 0, setmod, 1, MODE_EDIT }, 115329088Smarkm { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 115429181Smarkm { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, 115529181Smarkm { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, 115629088Smarkm { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 115729181Smarkm { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, 115829181Smarkm { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, 115929088Smarkm { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 116087139Smarkm { "help", 0, (int (*)(int))modehelp, 0, 0 }, 116129088Smarkm#ifdef KLUDGELINEMODE 116287139Smarkm { "kludgeline", 0, (int (*)(int))dokludgemode, 1, 0 }, 116329088Smarkm#endif 116487139Smarkm { "", "", NULL, 0, 0 }, 116587139Smarkm { "?", "Print help information", (int (*)(int))modehelp, 0, 0 }, 116687139Smarkm { NULL, NULL, NULL, 0, 0 }, 116729088Smarkm}; 116829088Smarkm 116929088Smarkm 117087139Smarkmstatic int 117187139Smarkmmodehelp(void) 117229088Smarkm{ 117329088Smarkm struct modelist *mt; 117429088Smarkm 117529088Smarkm printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 117629088Smarkm for (mt = ModeList; mt->name; mt++) { 117729088Smarkm if (mt->help) { 117829088Smarkm if (*mt->help) 117929088Smarkm printf("%-15s %s\n", mt->name, mt->help); 118029088Smarkm else 118129088Smarkm printf("\n"); 118229088Smarkm } 118329088Smarkm } 118429088Smarkm return 0; 118529088Smarkm} 118629088Smarkm 118729088Smarkm#define GETMODECMD(name) (struct modelist *) \ 118829088Smarkm genget(name, (char **) ModeList, sizeof(struct modelist)) 118929088Smarkm 119087139Smarkmstatic int 119187139Smarkmmodecmd(int argc, char *argv[]) 119229088Smarkm{ 119329088Smarkm struct modelist *mt; 119429088Smarkm 119529088Smarkm if (argc != 2) { 119629088Smarkm printf("'mode' command requires an argument\n"); 119729088Smarkm printf("'mode ?' for help.\n"); 119829088Smarkm } else if ((mt = GETMODECMD(argv[1])) == 0) { 119929088Smarkm fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 120087139Smarkm } else if (Ambiguous((void *)mt)) { 120129088Smarkm fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 120229088Smarkm } else if (mt->needconnect && !connected) { 120329088Smarkm printf("?Need to be connected first.\n"); 120429088Smarkm printf("'mode ?' for help.\n"); 120529088Smarkm } else if (mt->handler) { 120629088Smarkm return (*mt->handler)(mt->arg1); 120729088Smarkm } 120829088Smarkm return 0; 120929088Smarkm} 121029088Smarkm 121129088Smarkm/* 121229088Smarkm * The following data structures and routines implement the 121329088Smarkm * "display" command. 121429088Smarkm */ 121529088Smarkm 121687139Smarkmstatic int 121787139Smarkmdisplay(int argc, char *argv[]) 121829088Smarkm{ 121929088Smarkm struct togglelist *tl; 122029088Smarkm struct setlist *sl; 122129088Smarkm 122229088Smarkm#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 122329088Smarkm if (*tl->variable) { \ 122429088Smarkm printf("will"); \ 122529088Smarkm } else { \ 122629088Smarkm printf("won't"); \ 122729088Smarkm } \ 122829088Smarkm printf(" %s.\n", tl->actionexplanation); \ 122929088Smarkm } 123029088Smarkm 123129088Smarkm#define doset(sl) if (sl->name && *sl->name != ' ') { \ 123229088Smarkm if (sl->handler == 0) \ 123329088Smarkm printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 123429088Smarkm else \ 123529088Smarkm printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 123629088Smarkm } 123729088Smarkm 123829088Smarkm if (argc == 1) { 123929088Smarkm for (tl = Togglelist; tl->name; tl++) { 124029088Smarkm dotog(tl); 124129088Smarkm } 124229088Smarkm printf("\n"); 124329088Smarkm for (sl = Setlist; sl->name; sl++) { 124429088Smarkm doset(sl); 124529088Smarkm } 124629088Smarkm } else { 124729088Smarkm int i; 124829088Smarkm 124929088Smarkm for (i = 1; i < argc; i++) { 125029088Smarkm sl = getset(argv[i]); 125129088Smarkm tl = GETTOGGLE(argv[i]); 125287139Smarkm if (Ambiguous((void *)sl) || Ambiguous((void *)tl)) { 125329088Smarkm printf("?Ambiguous argument '%s'.\n", argv[i]); 125429088Smarkm return 0; 125529088Smarkm } else if (!sl && !tl) { 125629088Smarkm printf("?Unknown argument '%s'.\n", argv[i]); 125729088Smarkm return 0; 125829088Smarkm } else { 125929088Smarkm if (tl) { 126029088Smarkm dotog(tl); 126129088Smarkm } 126229088Smarkm if (sl) { 126329088Smarkm doset(sl); 126429088Smarkm } 126529088Smarkm } 126629088Smarkm } 126729088Smarkm } 126829088Smarkm/*@*/optionstatus(); 126929088Smarkm#ifdef ENCRYPTION 127029088Smarkm EncryptStatus(); 127129088Smarkm#endif /* ENCRYPTION */ 127229088Smarkm return 1; 127329088Smarkm#undef doset 127429088Smarkm#undef dotog 127529088Smarkm} 127629088Smarkm 127729088Smarkm/* 127829088Smarkm * The following are the data structures, and many of the routines, 127929088Smarkm * relating to command processing. 128029088Smarkm */ 128129088Smarkm 128229088Smarkm/* 128329088Smarkm * Set the escape character. 128429088Smarkm */ 128587139Smarkmstatic int 128687139Smarkmsetescape(int argc, char *argv[]) 128729088Smarkm{ 128887139Smarkm char *arg; 128929088Smarkm char buf[50]; 129029088Smarkm 129129088Smarkm printf( 129229088Smarkm "Deprecated usage - please use 'set escape%s%s' in the future.\n", 129329088Smarkm (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 129429088Smarkm if (argc > 2) 129529088Smarkm arg = argv[1]; 129629088Smarkm else { 129729088Smarkm printf("new escape character: "); 129829088Smarkm (void) fgets(buf, sizeof(buf), stdin); 129929088Smarkm arg = buf; 130029088Smarkm } 130129088Smarkm if (arg[0] != '\0') 130229088Smarkm escape = arg[0]; 130329088Smarkm (void) fflush(stdout); 130429088Smarkm return 1; 130529088Smarkm} 130629088Smarkm 130787139Smarkmstatic int 130887139Smarkmtogcrmod(void) 130929088Smarkm{ 131029088Smarkm crmod = !crmod; 131129088Smarkm printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 131229088Smarkm printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 131329088Smarkm (void) fflush(stdout); 131429088Smarkm return 1; 131529088Smarkm} 131629088Smarkm 131787139Smarkmstatic int 131887139Smarkmsuspend(void) 131929088Smarkm{ 132029088Smarkm#ifdef SIGTSTP 132129088Smarkm setcommandmode(); 132229088Smarkm { 132387139Smarkm long oldrows, oldcols, newrows, newcols, err_; 132429088Smarkm 132587139Smarkm err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 132629088Smarkm (void) kill(0, SIGTSTP); 132729088Smarkm /* 132829088Smarkm * If we didn't get the window size before the SUSPEND, but we 132929088Smarkm * can get them now (?), then send the NAWS to make sure that 133029088Smarkm * we are set up for the right window size. 133129088Smarkm */ 133229088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 133387139Smarkm (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { 133429088Smarkm sendnaws(); 133529088Smarkm } 133629088Smarkm } 133729088Smarkm /* reget parameters in case they were changed */ 133829088Smarkm TerminalSaveState(); 133929088Smarkm setconnmode(0); 134029088Smarkm#else 134129088Smarkm printf("Suspend is not supported. Try the '!' command instead\n"); 134229088Smarkm#endif 134329088Smarkm return 1; 134429088Smarkm} 134529088Smarkm 134687139Smarkmstatic int 134787139Smarkmshell(int argc, char *argv[] __unused) 134829088Smarkm{ 134987139Smarkm long oldrows, oldcols, newrows, newcols, err_; 135029088Smarkm 135129088Smarkm setcommandmode(); 135229088Smarkm 135387139Smarkm err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 135429088Smarkm switch(vfork()) { 135529088Smarkm case -1: 135629088Smarkm perror("Fork failed\n"); 135729088Smarkm break; 135829088Smarkm 135929088Smarkm case 0: 136029088Smarkm { 136129088Smarkm /* 136229088Smarkm * Fire up the shell in the child. 136329088Smarkm */ 136487139Smarkm const char *shellp, *shellname; 136529088Smarkm 136629088Smarkm shellp = getenv("SHELL"); 136729088Smarkm if (shellp == NULL) 136829088Smarkm shellp = "/bin/sh"; 136929088Smarkm if ((shellname = strrchr(shellp, '/')) == 0) 137029088Smarkm shellname = shellp; 137129088Smarkm else 137229088Smarkm shellname++; 137329088Smarkm if (argc > 1) 137481965Smarkm execl(shellp, shellname, "-c", &saveline[1], (char *)0); 137529088Smarkm else 137681965Smarkm execl(shellp, shellname, (char *)0); 137729088Smarkm perror("Execl"); 137829088Smarkm _exit(1); 137929088Smarkm } 138029088Smarkm default: 138129088Smarkm (void)wait((int *)0); /* Wait for the shell to complete */ 138229088Smarkm 138329088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 138487139Smarkm (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { 138529088Smarkm sendnaws(); 138629088Smarkm } 138729088Smarkm break; 138829088Smarkm } 138929088Smarkm return 1; 139029088Smarkm} 139129088Smarkm 139287139Smarkmstatic int 139387139Smarkmbye(int argc, char *argv[]) 139429088Smarkm{ 139529088Smarkm extern int resettermname; 139629088Smarkm 139729088Smarkm if (connected) { 139829088Smarkm (void) shutdown(net, 2); 139929088Smarkm printf("Connection closed.\n"); 140029088Smarkm (void) NetClose(net); 140129088Smarkm connected = 0; 140229088Smarkm resettermname = 1; 140387139Smarkm#ifdef AUTHENTICATION 140487139Smarkm#ifdef ENCRYPTION 140529088Smarkm auth_encrypt_connect(connected); 140687139Smarkm#endif 140787139Smarkm#endif 140829088Smarkm /* reset options */ 140929088Smarkm tninit(); 141029088Smarkm } 141129088Smarkm if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 141229088Smarkm longjmp(toplevel, 1); 141329088Smarkm /* NOTREACHED */ 141429088Smarkm } 141529088Smarkm return 1; /* Keep lint, etc., happy */ 141629088Smarkm} 141729088Smarkm 141887139Smarkmvoid 141987139Smarkmquit(void) 142029088Smarkm{ 142129088Smarkm (void) call(bye, "bye", "fromquit", 0); 142229088Smarkm Exit(0); 142329088Smarkm} 142429088Smarkm 142587139Smarkmstatic int 142687139Smarkmlogout(void) 142729088Smarkm{ 142829088Smarkm send_do(TELOPT_LOGOUT, 1); 142929088Smarkm (void) netflush(); 143029088Smarkm return 1; 143129088Smarkm} 143229088Smarkm 143329088Smarkm 143429088Smarkm/* 143529088Smarkm * The SLC command. 143629088Smarkm */ 143729088Smarkm 143829088Smarkmstruct slclist { 143987139Smarkm const char *name; 144087139Smarkm const char *help; 144187139Smarkm void (*handler)(int); 144229088Smarkm int arg; 144329088Smarkm}; 144429088Smarkm 144587139Smarkmstatic void slc_help(void); 144629088Smarkm 144729088Smarkmstruct slclist SlcList[] = { 144829088Smarkm { "export", "Use local special character definitions", 144987139Smarkm (void (*)(int))slc_mode_export, 0 }, 145029088Smarkm { "import", "Use remote special character definitions", 145129088Smarkm slc_mode_import, 1 }, 145229088Smarkm { "check", "Verify remote special character definitions", 145329088Smarkm slc_mode_import, 0 }, 145487139Smarkm { "help", NULL, (void (*)(int))slc_help, 0 }, 145587139Smarkm { "?", "Print help information", (void (*)(int))slc_help, 0 }, 145687139Smarkm { NULL, NULL, NULL, 0 }, 145729088Smarkm}; 145829088Smarkm 145987139Smarkmstatic void 146087139Smarkmslc_help(void) 146129088Smarkm{ 146229088Smarkm struct slclist *c; 146329088Smarkm 146429088Smarkm for (c = SlcList; c->name; c++) { 146529088Smarkm if (c->help) { 146629088Smarkm if (*c->help) 146729088Smarkm printf("%-15s %s\n", c->name, c->help); 146829088Smarkm else 146929088Smarkm printf("\n"); 147029088Smarkm } 147129088Smarkm } 147229088Smarkm} 147329088Smarkm 147487139Smarkmstatic struct slclist * 147587139Smarkmgetslc(char *name) 147629088Smarkm{ 147729088Smarkm return (struct slclist *) 147829088Smarkm genget(name, (char **) SlcList, sizeof(struct slclist)); 147929088Smarkm} 148029088Smarkm 148187139Smarkmstatic int 148287139Smarkmslccmd(int argc, char *argv[]) 148329088Smarkm{ 148429088Smarkm struct slclist *c; 148529088Smarkm 148629088Smarkm if (argc != 2) { 148729088Smarkm fprintf(stderr, 148829088Smarkm "Need an argument to 'slc' command. 'slc ?' for help.\n"); 148929088Smarkm return 0; 149029088Smarkm } 149129088Smarkm c = getslc(argv[1]); 149229088Smarkm if (c == 0) { 149329088Smarkm fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 149429088Smarkm argv[1]); 149529088Smarkm return 0; 149629088Smarkm } 149787139Smarkm if (Ambiguous((void *)c)) { 149829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 149929088Smarkm argv[1]); 150029088Smarkm return 0; 150129088Smarkm } 150229088Smarkm (*c->handler)(c->arg); 150329088Smarkm slcstate(); 150429088Smarkm return 1; 150529088Smarkm} 150629088Smarkm 150729088Smarkm/* 150829088Smarkm * The ENVIRON command. 150929088Smarkm */ 151029088Smarkm 151129088Smarkmstruct envlist { 151287139Smarkm const char *name; 151387139Smarkm const char *help; 151487139Smarkm void (*handler)(unsigned char *, unsigned char *); 151529088Smarkm int narg; 151629088Smarkm}; 151729088Smarkm 151829088Smarkmextern struct env_lst * 151987155Smarkm env_define(const unsigned char *, unsigned char *); 152029088Smarkmextern void 152187155Smarkm env_undefine(unsigned char *), 152287155Smarkm env_export(const unsigned char *), 152387155Smarkm env_unexport(const unsigned char *), 152487155Smarkm env_send(unsigned char *), 152529088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 152687155Smarkm env_varval(unsigned char *), 152729088Smarkm#endif 152887155Smarkm env_list(void); 152929088Smarkmstatic void 153087155Smarkm env_help(void); 153129088Smarkm 153229088Smarkmstruct envlist EnvList[] = { 153329088Smarkm { "define", "Define an environment variable", 153487139Smarkm (void (*)(unsigned char *, unsigned char *))env_define, 2 }, 153529088Smarkm { "undefine", "Undefine an environment variable", 153687139Smarkm (void (*)(unsigned char *, unsigned char *))env_undefine, 1 }, 153729088Smarkm { "export", "Mark an environment variable for automatic export", 153887139Smarkm (void (*)(unsigned char *, unsigned char *))env_export, 1 }, 153929088Smarkm { "unexport", "Don't mark an environment variable for automatic export", 154087139Smarkm (void (*)(unsigned char *, unsigned char *))env_unexport, 1 }, 154187139Smarkm { "send", "Send an environment variable", (void (*)(unsigned char *, unsigned char *))env_send, 1 }, 154229088Smarkm { "list", "List the current environment variables", 154387139Smarkm (void (*)(unsigned char *, unsigned char *))env_list, 0 }, 154429088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 154529088Smarkm { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 154687139Smarkm (void (*)(unsigned char *, unsigned char *))env_varval, 1 }, 154729088Smarkm#endif 154887139Smarkm { "help", NULL, (void (*)(unsigned char *, unsigned char *))env_help, 0 }, 154987139Smarkm { "?", "Print help information", (void (*)(unsigned char *, unsigned char *))env_help, 0 }, 155087139Smarkm { NULL, NULL, NULL, 0 }, 155129088Smarkm}; 155229088Smarkm 155387139Smarkmstatic void 155487139Smarkmenv_help(void) 155529088Smarkm{ 155629088Smarkm struct envlist *c; 155729088Smarkm 155829088Smarkm for (c = EnvList; c->name; c++) { 155929088Smarkm if (c->help) { 156029088Smarkm if (*c->help) 156129088Smarkm printf("%-15s %s\n", c->name, c->help); 156229088Smarkm else 156329088Smarkm printf("\n"); 156429088Smarkm } 156529088Smarkm } 156629088Smarkm} 156729088Smarkm 156887139Smarkmstatic struct envlist * 156987139Smarkmgetenvcmd(char *name) 157029088Smarkm{ 157129088Smarkm return (struct envlist *) 157229088Smarkm genget(name, (char **) EnvList, sizeof(struct envlist)); 157329088Smarkm} 157429088Smarkm 157587139Smarkmstatic int 157687139Smarkmenv_cmd(int argc, char *argv[]) 157729088Smarkm{ 157829088Smarkm struct envlist *c; 157929088Smarkm 158029088Smarkm if (argc < 2) { 158129088Smarkm fprintf(stderr, 158229088Smarkm "Need an argument to 'environ' command. 'environ ?' for help.\n"); 158329088Smarkm return 0; 158429088Smarkm } 158529088Smarkm c = getenvcmd(argv[1]); 158629088Smarkm if (c == 0) { 158729088Smarkm fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 158829088Smarkm argv[1]); 158929088Smarkm return 0; 159029088Smarkm } 159187139Smarkm if (Ambiguous((void *)c)) { 159229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 159329088Smarkm argv[1]); 159429088Smarkm return 0; 159529088Smarkm } 159629088Smarkm if (c->narg + 2 != argc) { 159729088Smarkm fprintf(stderr, 159829088Smarkm "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 159929088Smarkm c->narg < argc + 2 ? "only " : "", 160029088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 160129088Smarkm return 0; 160229088Smarkm } 160329088Smarkm (*c->handler)(argv[2], argv[3]); 160429088Smarkm return 1; 160529088Smarkm} 160629088Smarkm 160729088Smarkmstruct env_lst { 160829088Smarkm struct env_lst *next; /* pointer to next structure */ 160929088Smarkm struct env_lst *prev; /* pointer to previous structure */ 161029088Smarkm unsigned char *var; /* pointer to variable name */ 161129088Smarkm unsigned char *value; /* pointer to variable value */ 161229088Smarkm int export; /* 1 -> export with default list of variables */ 161329088Smarkm int welldefined; /* A well defined variable */ 161429088Smarkm}; 161529088Smarkm 161629088Smarkmstruct env_lst envlisthead; 161729088Smarkm 161887139Smarkmstatic struct env_lst * 161987139Smarkmenv_find(const unsigned char *var) 162029088Smarkm{ 162187139Smarkm struct env_lst *ep; 162229088Smarkm 162329088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 162487139Smarkm if (strcmp(ep->var, var) == 0) 162529088Smarkm return(ep); 162629088Smarkm } 162729088Smarkm return(NULL); 162829088Smarkm} 162929088Smarkm 163087139Smarkmvoid 163187139Smarkmenv_init(void) 163229088Smarkm{ 163329088Smarkm extern char **environ; 163487139Smarkm char **epp, *cp; 163587139Smarkm struct env_lst *ep; 163629088Smarkm 163729088Smarkm for (epp = environ; *epp; epp++) { 163829181Smarkm if ((cp = strchr(*epp, '='))) { 163929088Smarkm *cp = '\0'; 164029088Smarkm ep = env_define((unsigned char *)*epp, 164129088Smarkm (unsigned char *)cp+1); 164229088Smarkm ep->export = 0; 164329088Smarkm *cp = '='; 164429088Smarkm } 164529088Smarkm } 164629088Smarkm /* 164729088Smarkm * Special case for DISPLAY variable. If it is ":0.0" or 164829088Smarkm * "unix:0.0", we have to get rid of "unix" and insert our 164929088Smarkm * hostname. 165029088Smarkm */ 165129088Smarkm if ((ep = env_find("DISPLAY")) 165229088Smarkm && ((*ep->value == ':') 165329088Smarkm || (strncmp((char *)ep->value, "unix:", 5) == 0))) { 165429088Smarkm char hbuf[256+1]; 165529088Smarkm char *cp2 = strchr((char *)ep->value, ':'); 165629088Smarkm 165729088Smarkm gethostname(hbuf, 256); 165829088Smarkm hbuf[256] = '\0'; 165929088Smarkm cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); 166029088Smarkm sprintf((char *)cp, "%s%s", hbuf, cp2); 166129088Smarkm free(ep->value); 166229088Smarkm ep->value = (unsigned char *)cp; 166329088Smarkm } 166429088Smarkm /* 166529088Smarkm * If USER is not defined, but LOGNAME is, then add 166629088Smarkm * USER with the value from LOGNAME. By default, we 166729088Smarkm * don't export the USER variable. 166829088Smarkm */ 166929088Smarkm if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { 167087139Smarkm env_define("USER", ep->value); 167187139Smarkm env_unexport("USER"); 167229088Smarkm } 167387139Smarkm env_export("DISPLAY"); 167487139Smarkm env_export("PRINTER"); 167529088Smarkm} 167629088Smarkm 167787139Smarkmstruct env_lst * 167887139Smarkmenv_define(const unsigned char *var, unsigned char *value) 167929088Smarkm{ 168087139Smarkm struct env_lst *ep; 168129088Smarkm 168229181Smarkm if ((ep = env_find(var))) { 168329088Smarkm if (ep->var) 168429088Smarkm free(ep->var); 168529088Smarkm if (ep->value) 168629088Smarkm free(ep->value); 168729088Smarkm } else { 168829088Smarkm ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 168929088Smarkm ep->next = envlisthead.next; 169029088Smarkm envlisthead.next = ep; 169129088Smarkm ep->prev = &envlisthead; 169229088Smarkm if (ep->next) 169329088Smarkm ep->next->prev = ep; 169429088Smarkm } 169529088Smarkm ep->welldefined = opt_welldefined(var); 169629088Smarkm ep->export = 1; 169787139Smarkm ep->var = strdup(var); 169887139Smarkm ep->value = strdup(value); 169929088Smarkm return(ep); 170029088Smarkm} 170129088Smarkm 170287139Smarkmvoid 170387139Smarkmenv_undefine(unsigned char *var) 170429088Smarkm{ 170587139Smarkm struct env_lst *ep; 170629088Smarkm 170729181Smarkm if ((ep = env_find(var))) { 170829088Smarkm ep->prev->next = ep->next; 170929088Smarkm if (ep->next) 171029088Smarkm ep->next->prev = ep->prev; 171129088Smarkm if (ep->var) 171229088Smarkm free(ep->var); 171329088Smarkm if (ep->value) 171429088Smarkm free(ep->value); 171529088Smarkm free(ep); 171629088Smarkm } 171729088Smarkm} 171829088Smarkm 171987139Smarkmvoid 172087139Smarkmenv_export(const unsigned char *var) 172129088Smarkm{ 172287139Smarkm struct env_lst *ep; 172329088Smarkm 172429181Smarkm if ((ep = env_find(var))) 172529088Smarkm ep->export = 1; 172629088Smarkm} 172729088Smarkm 172887139Smarkmvoid 172987139Smarkmenv_unexport(const unsigned char *var) 173029088Smarkm{ 173187139Smarkm struct env_lst *ep; 173229088Smarkm 173329181Smarkm if ((ep = env_find(var))) 173429088Smarkm ep->export = 0; 173529088Smarkm} 173629088Smarkm 173787139Smarkmvoid 173887139Smarkmenv_send(unsigned char *var) 173929088Smarkm{ 174087139Smarkm struct env_lst *ep; 174129088Smarkm 174229088Smarkm if (my_state_is_wont(TELOPT_NEW_ENVIRON) 174329088Smarkm#ifdef OLD_ENVIRON 174429088Smarkm && my_state_is_wont(TELOPT_OLD_ENVIRON) 174529088Smarkm#endif 174629088Smarkm ) { 174729088Smarkm fprintf(stderr, 174829088Smarkm "Cannot send '%s': Telnet ENVIRON option not enabled\n", 174929088Smarkm var); 175029088Smarkm return; 175129088Smarkm } 175229088Smarkm ep = env_find(var); 175329088Smarkm if (ep == 0) { 175429088Smarkm fprintf(stderr, "Cannot send '%s': variable not defined\n", 175529088Smarkm var); 175629088Smarkm return; 175729088Smarkm } 175829088Smarkm env_opt_start_info(); 175929088Smarkm env_opt_add(ep->var); 176029088Smarkm env_opt_end(0); 176129088Smarkm} 176229088Smarkm 176387139Smarkmvoid 176487139Smarkmenv_list(void) 176529088Smarkm{ 176687139Smarkm struct env_lst *ep; 176729088Smarkm 176829088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 176929088Smarkm printf("%c %-20s %s\n", ep->export ? '*' : ' ', 177029088Smarkm ep->var, ep->value); 177129088Smarkm } 177229088Smarkm} 177329088Smarkm 177487139Smarkmunsigned char * 177587139Smarkmenv_default(int init, int welldefined) 177629088Smarkm{ 177729088Smarkm static struct env_lst *nep = NULL; 177829088Smarkm 177929088Smarkm if (init) { 178029088Smarkm nep = &envlisthead; 178129181Smarkm return(NULL); 178229088Smarkm } 178329088Smarkm if (nep) { 178429181Smarkm while ((nep = nep->next)) { 178529088Smarkm if (nep->export && (nep->welldefined == welldefined)) 178629088Smarkm return(nep->var); 178729088Smarkm } 178829088Smarkm } 178929088Smarkm return(NULL); 179029088Smarkm} 179129088Smarkm 179287139Smarkmunsigned char * 179387139Smarkmenv_getvalue(const unsigned char *var) 179429088Smarkm{ 179587139Smarkm struct env_lst *ep; 179629088Smarkm 179729181Smarkm if ((ep = env_find(var))) 179829088Smarkm return(ep->value); 179929088Smarkm return(NULL); 180029088Smarkm} 180129088Smarkm 180229088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 180387139Smarkmvoid 180487139Smarkmenv_varval(unsigned char *what) 180529088Smarkm{ 180629088Smarkm extern int old_env_var, old_env_value, env_auto; 180729088Smarkm int len = strlen((char *)what); 180829088Smarkm 180929088Smarkm if (len == 0) 181029088Smarkm goto unknown; 181129088Smarkm 181229088Smarkm if (strncasecmp((char *)what, "status", len) == 0) { 181329088Smarkm if (env_auto) 181429088Smarkm printf("%s%s", "VAR and VALUE are/will be ", 181529088Smarkm "determined automatically\n"); 181629088Smarkm if (old_env_var == OLD_ENV_VAR) 181729088Smarkm printf("VAR and VALUE set to correct definitions\n"); 181829088Smarkm else 181929088Smarkm printf("VAR and VALUE definitions are reversed\n"); 182029088Smarkm } else if (strncasecmp((char *)what, "auto", len) == 0) { 182129088Smarkm env_auto = 1; 182229088Smarkm old_env_var = OLD_ENV_VALUE; 182329088Smarkm old_env_value = OLD_ENV_VAR; 182429088Smarkm } else if (strncasecmp((char *)what, "right", len) == 0) { 182529088Smarkm env_auto = 0; 182629088Smarkm old_env_var = OLD_ENV_VAR; 182729088Smarkm old_env_value = OLD_ENV_VALUE; 182829088Smarkm } else if (strncasecmp((char *)what, "wrong", len) == 0) { 182929088Smarkm env_auto = 0; 183029088Smarkm old_env_var = OLD_ENV_VALUE; 183129088Smarkm old_env_value = OLD_ENV_VAR; 183229088Smarkm } else { 183329088Smarkmunknown: 183429088Smarkm printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); 183529088Smarkm } 183629088Smarkm} 183729088Smarkm#endif 183829088Smarkm 183987139Smarkm#ifdef AUTHENTICATION 184029088Smarkm/* 184129088Smarkm * The AUTHENTICATE command. 184229088Smarkm */ 184329088Smarkm 184429088Smarkmstruct authlist { 184587139Smarkm const char *name; 184687139Smarkm const char *help; 184787139Smarkm int (*handler)(char *); 184829088Smarkm int narg; 184929088Smarkm}; 185029088Smarkm 185129088Smarkmextern int 185287155Smarkm auth_enable(char *), 185387155Smarkm auth_disable(char *), 185487155Smarkm auth_status(void); 185529088Smarkmstatic int 185687155Smarkm auth_help(void); 185729088Smarkm 185829088Smarkmstruct authlist AuthList[] = { 185929088Smarkm { "status", "Display current status of authentication information", 186087139Smarkm (int (*)(char *))auth_status, 0 }, 186129088Smarkm { "disable", "Disable an authentication type ('auth disable ?' for more)", 186229088Smarkm auth_disable, 1 }, 186329088Smarkm { "enable", "Enable an authentication type ('auth enable ?' for more)", 186429088Smarkm auth_enable, 1 }, 186587139Smarkm { "help", NULL, (int (*)(char *))auth_help, 0 }, 186687139Smarkm { "?", "Print help information", (int (*)(char *))auth_help, 0 }, 186787139Smarkm { NULL, NULL, NULL, 0 }, 186829088Smarkm}; 186929088Smarkm 187087139Smarkmstatic int 187187139Smarkmauth_help(void) 187229088Smarkm{ 187329088Smarkm struct authlist *c; 187429088Smarkm 187529088Smarkm for (c = AuthList; c->name; c++) { 187629088Smarkm if (c->help) { 187729088Smarkm if (*c->help) 187829088Smarkm printf("%-15s %s\n", c->name, c->help); 187929088Smarkm else 188029088Smarkm printf("\n"); 188129088Smarkm } 188229088Smarkm } 188329088Smarkm return 0; 188429088Smarkm} 188529088Smarkm 188687139Smarkmint 188787139Smarkmauth_cmd(int argc, char *argv[]) 188829088Smarkm{ 188929088Smarkm struct authlist *c; 189029088Smarkm 189129088Smarkm if (argc < 2) { 189229088Smarkm fprintf(stderr, 189329088Smarkm "Need an argument to 'auth' command. 'auth ?' for help.\n"); 189429088Smarkm return 0; 189529088Smarkm } 189629088Smarkm 189729088Smarkm c = (struct authlist *) 189829088Smarkm genget(argv[1], (char **) AuthList, sizeof(struct authlist)); 189929088Smarkm if (c == 0) { 190029088Smarkm fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", 190129088Smarkm argv[1]); 190229088Smarkm return 0; 190329088Smarkm } 190487139Smarkm if (Ambiguous((void *)c)) { 190529088Smarkm fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", 190629088Smarkm argv[1]); 190729088Smarkm return 0; 190829088Smarkm } 190929088Smarkm if (c->narg + 2 != argc) { 191029088Smarkm fprintf(stderr, 191129088Smarkm "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", 191229088Smarkm c->narg < argc + 2 ? "only " : "", 191329088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 191429088Smarkm return 0; 191529088Smarkm } 191687139Smarkm return((*c->handler)(argv[2])); 191729088Smarkm} 191829088Smarkm#endif 191929088Smarkm 192029088Smarkm#ifdef ENCRYPTION 192129088Smarkm/* 192229088Smarkm * The ENCRYPT command. 192329088Smarkm */ 192429088Smarkm 192529088Smarkmstruct encryptlist { 192687139Smarkm const char *name; 192787139Smarkm const char *help; 192887139Smarkm int (*handler)(char *, char *); 192929088Smarkm int needconnect; 193029088Smarkm int minarg; 193129088Smarkm int maxarg; 193229088Smarkm}; 193329088Smarkm 193429088Smarkmextern int 193587155Smarkm EncryptEnable(char *, char *), 193687155Smarkm EncryptDisable(char *, char *), 193787155Smarkm EncryptType(char *, char *), 193887155Smarkm EncryptStart(char *), 193987155Smarkm EncryptStartInput(void), 194087155Smarkm EncryptStartOutput(void), 194187155Smarkm EncryptStop(char *), 194287155Smarkm EncryptStopInput(void), 194387155Smarkm EncryptStopOutput(void), 194487155Smarkm EncryptStatus(void); 194529088Smarkmstatic int 194687155Smarkm EncryptHelp(void); 194729088Smarkm 194829088Smarkmstruct encryptlist EncryptList[] = { 194929088Smarkm { "enable", "Enable encryption. ('encrypt enable ?' for more)", 195029088Smarkm EncryptEnable, 1, 1, 2 }, 195129088Smarkm { "disable", "Disable encryption. ('encrypt enable ?' for more)", 195229088Smarkm EncryptDisable, 0, 1, 2 }, 195329088Smarkm { "type", "Set encryption type. ('encrypt type ?' for more)", 195429088Smarkm EncryptType, 0, 1, 1 }, 195529088Smarkm { "start", "Start encryption. ('encrypt start ?' for more)", 195687139Smarkm (int (*)(char *, char *))EncryptStart, 1, 0, 1 }, 195729088Smarkm { "stop", "Stop encryption. ('encrypt stop ?' for more)", 195887139Smarkm (int (*)(char *, char *))EncryptStop, 1, 0, 1 }, 195929088Smarkm { "input", "Start encrypting the input stream", 196087139Smarkm (int (*)(char *, char *))EncryptStartInput, 1, 0, 0 }, 196129088Smarkm { "-input", "Stop encrypting the input stream", 196287139Smarkm (int (*)(char *, char *))EncryptStopInput, 1, 0, 0 }, 196329088Smarkm { "output", "Start encrypting the output stream", 196487139Smarkm (int (*)(char *, char *))EncryptStartOutput, 1, 0, 0 }, 196529088Smarkm { "-output", "Stop encrypting the output stream", 196687139Smarkm (int (*)(char *, char *))EncryptStopOutput, 1, 0, 0 }, 196729088Smarkm 196829088Smarkm { "status", "Display current status of authentication information", 196987139Smarkm (int (*)(char *, char *))EncryptStatus, 0, 0, 0 }, 197087139Smarkm { "help", NULL, (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, 197187139Smarkm { "?", "Print help information", (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, 197287139Smarkm { NULL, NULL, NULL, 0, 0, 0 }, 197329088Smarkm}; 197429088Smarkm 197587139Smarkmstatic int 197687139SmarkmEncryptHelp(void) 197729088Smarkm{ 197829088Smarkm struct encryptlist *c; 197929088Smarkm 198029088Smarkm for (c = EncryptList; c->name; c++) { 198129088Smarkm if (c->help) { 198229088Smarkm if (*c->help) 198329088Smarkm printf("%-15s %s\n", c->name, c->help); 198429088Smarkm else 198529088Smarkm printf("\n"); 198629088Smarkm } 198729088Smarkm } 198829088Smarkm return 0; 198929088Smarkm} 199029088Smarkm 199187139Smarkmstatic int 199287139Smarkmencrypt_cmd(int argc, char *argv[]) 199329088Smarkm{ 199429088Smarkm struct encryptlist *c; 199529088Smarkm 199629088Smarkm if (argc < 2) { 199729088Smarkm fprintf(stderr, 199829088Smarkm "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); 199929088Smarkm return 0; 200029088Smarkm } 200129088Smarkm 200229088Smarkm c = (struct encryptlist *) 200329088Smarkm genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); 200429088Smarkm if (c == 0) { 200529088Smarkm fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", 200629088Smarkm argv[1]); 200729088Smarkm return 0; 200829088Smarkm } 200987139Smarkm if (Ambiguous((void *)c)) { 201029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", 201129088Smarkm argv[1]); 201229088Smarkm return 0; 201329088Smarkm } 201429088Smarkm argc -= 2; 201529088Smarkm if (argc < c->minarg || argc > c->maxarg) { 201629088Smarkm if (c->minarg == c->maxarg) { 201729088Smarkm fprintf(stderr, "Need %s%d argument%s ", 201829088Smarkm c->minarg < argc ? "only " : "", c->minarg, 201929088Smarkm c->minarg == 1 ? "" : "s"); 202029088Smarkm } else { 202129088Smarkm fprintf(stderr, "Need %s%d-%d arguments ", 202229088Smarkm c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); 202329088Smarkm } 202429088Smarkm fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", 202529088Smarkm c->name); 202629088Smarkm return 0; 202729088Smarkm } 202829088Smarkm if (c->needconnect && !connected) { 202929088Smarkm if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 203029088Smarkm printf("?Need to be connected first.\n"); 203129088Smarkm return 0; 203229088Smarkm } 203329088Smarkm } 203429088Smarkm return ((*c->handler)(argc > 0 ? argv[2] : 0, 203587139Smarkm argc > 1 ? argv[3] : 0)); 203629088Smarkm} 203729088Smarkm#endif /* ENCRYPTION */ 203829088Smarkm 203929088Smarkm/* 204029088Smarkm * Print status about the connection. 204129088Smarkm */ 204287139Smarkm/*ARGSUSED*/ 204387139Smarkmstatic int 204487139Smarkmstatus(int argc, char *argv[]) 204529088Smarkm{ 204629088Smarkm if (connected) { 204729088Smarkm printf("Connected to %s.\n", hostname); 204829088Smarkm if ((argc < 2) || strcmp(argv[1], "notmuch")) { 204929088Smarkm int mode = getconnmode(); 205029088Smarkm 205129088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 205229088Smarkm printf("Operating with LINEMODE option\n"); 205329088Smarkm printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 205429088Smarkm printf("%s catching of signals\n", 205529088Smarkm (mode&MODE_TRAPSIG) ? "Local" : "No"); 205629088Smarkm slcstate(); 205729088Smarkm#ifdef KLUDGELINEMODE 205829088Smarkm } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 205929088Smarkm printf("Operating in obsolete linemode\n"); 206029088Smarkm#endif 206129088Smarkm } else { 206229088Smarkm printf("Operating in single character mode\n"); 206329088Smarkm if (localchars) 206429088Smarkm printf("Catching signals locally\n"); 206529088Smarkm } 206629088Smarkm printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 206729088Smarkm if (my_want_state_is_will(TELOPT_LFLOW)) 206829088Smarkm printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 206929088Smarkm#ifdef ENCRYPTION 207029088Smarkm encrypt_display(); 207129088Smarkm#endif /* ENCRYPTION */ 207229088Smarkm } 207329088Smarkm } else { 207429088Smarkm printf("No connection.\n"); 207529088Smarkm } 207629088Smarkm printf("Escape character is '%s'.\n", control(escape)); 207729088Smarkm (void) fflush(stdout); 207829088Smarkm return 1; 207929088Smarkm} 208029088Smarkm 208129088Smarkm#ifdef SIGINFO 208229088Smarkm/* 208329088Smarkm * Function that gets called when SIGINFO is received. 208429088Smarkm */ 208587139Smarkmvoid 208687139Smarkmayt_status(void) 208729088Smarkm{ 208829088Smarkm (void) call(status, "status", "notmuch", 0); 208929088Smarkm} 209029088Smarkm#endif 209129088Smarkm 209256668Sshinstatic const char * 209387139Smarkmsockaddr_ntop(struct sockaddr *sa) 209456668Sshin{ 209556668Sshin void *addr; 209656668Sshin static char addrbuf[INET6_ADDRSTRLEN]; 209729088Smarkm 209856668Sshin switch (sa->sa_family) { 209956668Sshin case AF_INET: 210056668Sshin addr = &((struct sockaddr_in *)sa)->sin_addr; 210156668Sshin break; 210277095Sdillon case AF_UNIX: 210377095Sdillon addr = &((struct sockaddr_un *)sa)->sun_path; 210477095Sdillon break; 210556668Sshin#ifdef INET6 210656668Sshin case AF_INET6: 210756668Sshin addr = &((struct sockaddr_in6 *)sa)->sin6_addr; 210856668Sshin break; 210956668Sshin#endif 211056668Sshin default: 211156668Sshin return NULL; 211256668Sshin } 211356668Sshin inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); 211456668Sshin return addrbuf; 211556668Sshin} 211656668Sshin 211756668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 211856668Sshinstatic int 211987139Smarkmsetpolicy(int lnet, struct addrinfo *res, char *policy) 212056668Sshin{ 212156668Sshin char *buf; 212256668Sshin int level; 212356668Sshin int optname; 212456668Sshin 212556668Sshin if (policy == NULL) 212656668Sshin return 0; 212756668Sshin 212856668Sshin buf = ipsec_set_policy(policy, strlen(policy)); 212956668Sshin if (buf == NULL) { 213056668Sshin printf("%s\n", ipsec_strerror()); 213156668Sshin return -1; 213256668Sshin } 213356668Sshin level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 213456668Sshin optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; 213587139Smarkm if (setsockopt(lnet, level, optname, buf, ipsec_get_policylen(buf)) < 0){ 213656668Sshin perror("setsockopt"); 213756668Sshin return -1; 213856668Sshin } 213956668Sshin 214056668Sshin free(buf); 214187139Smarkm return 0; 214256668Sshin} 214356668Sshin#endif 214456668Sshin 214557125Sshin#ifdef INET6 214657125Sshin/* 214757125Sshin * When an Address Family related error happend, check if retry with 214857125Sshin * another AF is possible or not. 214957125Sshin * Return 1, if retry with another af is OK. Else, return 0. 215057125Sshin */ 215157125Sshinstatic int 215287139Smarkmswitch_af(struct addrinfo **aip) 215357125Sshin{ 215457125Sshin int nextaf; 215557125Sshin struct addrinfo *ai; 215657125Sshin 215757125Sshin ai = *aip; 215857125Sshin nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; 215957125Sshin do 216057125Sshin ai=ai->ai_next; 216157125Sshin while (ai != NULL && ai->ai_family != nextaf); 216257125Sshin *aip = ai; 216357125Sshin if (*aip != NULL) { 216457125Sshin return 1; 216557125Sshin } 216657125Sshin return 0; 216757125Sshin} 216857125Sshin#endif 216957125Sshin 217087139Smarkmint 217187139Smarkmtn(int argc, char *argv[]) 217229088Smarkm{ 217381965Smarkm char *srp = 0; 217456668Sshin int proto, opt; 217587139Smarkm int srlen; 217656668Sshin int srcroute = 0, result; 217729088Smarkm char *cmd, *hostp = 0, *portp = 0, *user = 0; 217847973Sru char *src_addr = NULL; 217957125Sshin struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; 218057125Sshin int error = 0, af_error = 0; 218129088Smarkm 218229088Smarkm if (connected) { 218329088Smarkm printf("?Already connected to %s\n", hostname); 218429088Smarkm setuid(getuid()); 218529088Smarkm return 0; 218629088Smarkm } 218729088Smarkm if (argc < 2) { 218829088Smarkm (void) strcpy(line, "open "); 218929088Smarkm printf("(to) "); 219029088Smarkm (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); 219129088Smarkm makeargv(); 219229088Smarkm argc = margc; 219329088Smarkm argv = margv; 219429088Smarkm } 219529088Smarkm cmd = *argv; 219629088Smarkm --argc; ++argv; 219729088Smarkm while (argc) { 219829088Smarkm if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) 219929088Smarkm goto usage; 220029088Smarkm if (strcmp(*argv, "-l") == 0) { 220129088Smarkm --argc; ++argv; 220229088Smarkm if (argc == 0) 220329088Smarkm goto usage; 220429088Smarkm user = *argv++; 220529088Smarkm --argc; 220629088Smarkm continue; 220729088Smarkm } 220829088Smarkm if (strcmp(*argv, "-a") == 0) { 220929088Smarkm --argc; ++argv; 221029088Smarkm autologin = 1; 221129088Smarkm continue; 221229088Smarkm } 221347973Sru if (strcmp(*argv, "-s") == 0) { 221447973Sru --argc; ++argv; 221547973Sru if (argc == 0) 221647973Sru goto usage; 221747973Sru src_addr = *argv++; 221847973Sru --argc; 221947973Sru continue; 222047973Sru } 222129088Smarkm if (hostp == 0) { 222229088Smarkm hostp = *argv++; 222329088Smarkm --argc; 222429088Smarkm continue; 222529088Smarkm } 222629088Smarkm if (portp == 0) { 222729088Smarkm portp = *argv++; 222829088Smarkm --argc; 222929088Smarkm continue; 223029088Smarkm } 223129088Smarkm usage: 223247973Sru printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); 223329088Smarkm setuid(getuid()); 223429088Smarkm return 0; 223529088Smarkm } 223629088Smarkm if (hostp == 0) 223729088Smarkm goto usage; 223829088Smarkm 223947973Sru if (src_addr != NULL) { 224056668Sshin memset(&hints, 0, sizeof(hints)); 224156668Sshin hints.ai_flags = AI_NUMERICHOST; 224256668Sshin hints.ai_family = family; 224356668Sshin hints.ai_socktype = SOCK_STREAM; 224457125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 224562805Sume if (error == EAI_NODATA) { 224656668Sshin hints.ai_flags = 0; 224757125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 224856668Sshin } 224956668Sshin if (error != 0) { 225056668Sshin fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); 225156668Sshin if (error == EAI_SYSTEM) 225256668Sshin fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); 225357125Sshin setuid(getuid()); 225447973Sru return 0; 225547973Sru } 225657125Sshin src_res0 = src_res; 225747973Sru } 225877095Sdillon if (hostp[0] == '/') { 225977095Sdillon struct sockaddr_un su; 226077095Sdillon 226177095Sdillon if (strlen(hostp) >= sizeof(su.sun_path)) { 226277095Sdillon fprintf(stderr, "hostname too long for unix domain socket: %s", 226377095Sdillon hostp); 226477095Sdillon goto fail; 226577095Sdillon } 226677095Sdillon memset(&su, 0, sizeof su); 226777095Sdillon su.sun_family = AF_UNIX; 226877095Sdillon strncpy(su.sun_path, hostp, sizeof su.sun_path); 226987139Smarkm printf("Trying %s...\n", hostp); 227077095Sdillon net = socket(PF_UNIX, SOCK_STREAM, 0); 227177095Sdillon if ( net < 0) { 227277095Sdillon perror("socket"); 227377095Sdillon goto fail; 227477095Sdillon } 227577095Sdillon if (connect(net, (struct sockaddr *)&su, sizeof su) == -1) { 227677095Sdillon perror(su.sun_path); 227777095Sdillon (void) NetClose(net); 227877095Sdillon goto fail; 227977095Sdillon } 228077095Sdillon goto af_unix; 228177095Sdillon } else if (hostp[0] == '@' || hostp[0] == '!') { 228256668Sshin if ( 228356668Sshin#ifdef INET6 228456668Sshin family == AF_INET6 || 228556668Sshin#endif 228656668Sshin (hostname = strrchr(hostp, ':')) == NULL) 228729088Smarkm hostname = strrchr(hostp, '@'); 228829088Smarkm hostname++; 228956668Sshin srcroute = 1; 229056668Sshin } else 229156668Sshin hostname = hostp; 229256668Sshin if (!portp) { 229356668Sshin telnetport = 1; 229487139Smarkm portp = strdup("telnet"); 229556668Sshin } else if (*portp == '-') { 229656668Sshin portp++; 229756668Sshin telnetport = 1; 229856668Sshin } else 229956668Sshin telnetport = 0; 230056668Sshin 230156668Sshin memset(&hints, 0, sizeof(hints)); 230256668Sshin hints.ai_flags = AI_NUMERICHOST; 230356668Sshin hints.ai_family = family; 230456668Sshin hints.ai_socktype = SOCK_STREAM; 230556668Sshin error = getaddrinfo(hostname, portp, &hints, &res); 230662773Sitojun if (error) { 230762773Sitojun hints.ai_flags = AI_CANONNAME; 230862773Sitojun error = getaddrinfo(hostname, portp, &hints, &res); 230962773Sitojun } 231062773Sitojun if (error != 0) { 231162773Sitojun fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); 231262773Sitojun if (error == EAI_SYSTEM) 231362773Sitojun fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); 231462773Sitojun setuid(getuid()); 231562773Sitojun goto fail; 231662773Sitojun } 231762773Sitojun if (hints.ai_flags == AI_NUMERICHOST) { 231862773Sitojun /* hostname has numeric */ 231956668Sshin int gni_err = 1; 232056668Sshin 232156668Sshin if (doaddrlookup) 232256668Sshin gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, 232356668Sshin _hostname, sizeof(_hostname) - 1, NULL, 0, 232456870Sshin NI_NAMEREQD); 232556668Sshin if (gni_err != 0) 232662773Sitojun (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 232756668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 232856668Sshin hostname = _hostname; 232962773Sitojun } else { 233062773Sitojun /* hostname has FQDN */ 233156668Sshin if (srcroute != 0) 233256668Sshin (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); 233356668Sshin else if (res->ai_canonname != NULL) 233456668Sshin strcpy(_hostname, res->ai_canonname); 233556668Sshin else 233656668Sshin (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 233756668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 233856668Sshin hostname = _hostname; 233956668Sshin } 234057125Sshin res0 = res; 234187277Sjhay #ifdef INET6 234257233Sshin af_again: 234387277Sjhay #endif 234456668Sshin if (srcroute != 0) { 234557343Sshin static char hostbuf[BUFSIZ]; 234657125Sshin 234757233Sshin if (af_error == 0) { /* save intermediate hostnames for retry */ 234857233Sshin strncpy(hostbuf, hostp, BUFSIZ - 1); 234957233Sshin hostbuf[BUFSIZ - 1] = '\0'; 235057233Sshin } else 235157125Sshin hostp = hostbuf; 235229088Smarkm srp = 0; 235356668Sshin result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); 235456668Sshin if (result == 0) { 235557125Sshin#ifdef INET6 235657125Sshin if (family == AF_UNSPEC && af_error == 0 && 235757125Sshin switch_af(&res) == 1) { 235857125Sshin af_error = 1; 235957125Sshin goto af_again; 236057125Sshin } 236157125Sshin#endif 236229088Smarkm setuid(getuid()); 236357125Sshin goto fail; 236456668Sshin } else if (result == -1) { 236529088Smarkm printf("Bad source route option: %s\n", hostp); 236629088Smarkm setuid(getuid()); 236757125Sshin goto fail; 236829088Smarkm } 236929088Smarkm } 237029088Smarkm do { 237157342Sshin printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); 237256668Sshin net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 237329088Smarkm setuid(getuid()); 237429088Smarkm if (net < 0) { 237557125Sshin#ifdef INET6 237657125Sshin if (family == AF_UNSPEC && af_error == 0 && 237757125Sshin switch_af(&res) == 1) { 237857125Sshin af_error = 1; 237957125Sshin goto af_again; 238057125Sshin } 238157125Sshin#endif 238229088Smarkm perror("telnet: socket"); 238357125Sshin goto fail; 238429088Smarkm } 238556668Sshin if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) 238656668Sshin perror("setsockopt (source route)"); 238729088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 238856668Sshin if (res->ai_family == PF_INET) { 238929088Smarkm# if defined(HAS_GETTOS) 239029088Smarkm struct tosent *tp; 239129088Smarkm if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 239229088Smarkm tos = tp->t_tos; 239329088Smarkm# endif 239429088Smarkm if (tos < 0) 239581965Smarkm tos = IPTOS_LOWDELAY; 239629088Smarkm if (tos 239729088Smarkm && (setsockopt(net, IPPROTO_IP, IP_TOS, 239829088Smarkm (char *)&tos, sizeof(int)) < 0) 239929088Smarkm && (errno != ENOPROTOOPT)) 240029088Smarkm perror("telnet: setsockopt (IP_TOS) (ignored)"); 240129088Smarkm } 240229088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 240329088Smarkm 240429088Smarkm if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 240529088Smarkm perror("setsockopt (SO_DEBUG)"); 240629088Smarkm } 240729088Smarkm 240847973Sru if (src_addr != NULL) { 240957125Sshin for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) 241057233Sshin if (src_res->ai_family == res->ai_family) 241157233Sshin break; 241257125Sshin if (src_res == NULL) 241357125Sshin src_res = src_res0; 241457125Sshin if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { 241557125Sshin#ifdef INET6 241657125Sshin if (family == AF_UNSPEC && af_error == 0 && 241757125Sshin switch_af(&res) == 1) { 241857125Sshin af_error = 1; 241957233Sshin (void) NetClose(net); 242057125Sshin goto af_again; 242157125Sshin } 242257125Sshin#endif 242347973Sru perror("bind"); 242457233Sshin (void) NetClose(net); 242557125Sshin goto fail; 242647973Sru } 242747973Sru } 242856668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 242957233Sshin if (setpolicy(net, res, ipsec_policy_in) < 0) { 243057233Sshin (void) NetClose(net); 243157125Sshin goto fail; 243257233Sshin } 243357233Sshin if (setpolicy(net, res, ipsec_policy_out) < 0) { 243457233Sshin (void) NetClose(net); 243557125Sshin goto fail; 243657233Sshin } 243756668Sshin#endif 243847973Sru 243956668Sshin if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { 244057125Sshin struct addrinfo *next; 244157125Sshin 244257125Sshin next = res->ai_next; 244357125Sshin /* If already an af failed, only try same af. */ 244457125Sshin if (af_error != 0) 244557125Sshin while (next != NULL && next->ai_family != res->ai_family) 244657125Sshin next = next->ai_next; 244757342Sshin warn("connect to address %s", sockaddr_ntop(res->ai_addr)); 244857125Sshin if (next != NULL) { 244957125Sshin res = next; 245029088Smarkm (void) NetClose(net); 245129088Smarkm continue; 245229088Smarkm } 245357342Sshin warnx("Unable to connect to remote host"); 245457233Sshin (void) NetClose(net); 245557125Sshin goto fail; 245629088Smarkm } 245729088Smarkm connected++; 245887139Smarkm#ifdef AUTHENTICATION 245987139Smarkm#ifdef ENCRYPTION 246029088Smarkm auth_encrypt_connect(connected); 246187139Smarkm#endif 246287139Smarkm#endif 246329088Smarkm } while (connected == 0); 246457125Sshin freeaddrinfo(res0); 246557125Sshin if (src_res0 != NULL) 246657125Sshin freeaddrinfo(src_res0); 246729088Smarkm cmdrc(hostp, hostname); 246877095Sdillon af_unix: 246929088Smarkm if (autologin && user == NULL) { 247029088Smarkm struct passwd *pw; 247129088Smarkm 247229088Smarkm user = getenv("USER"); 247329088Smarkm if (user == NULL || 247429181Smarkm ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { 247529181Smarkm if ((pw = getpwuid(getuid()))) 247629088Smarkm user = pw->pw_name; 247729088Smarkm else 247829088Smarkm user = NULL; 247929088Smarkm } 248029088Smarkm } 248129088Smarkm if (user) { 248287139Smarkm env_define("USER", user); 248387139Smarkm env_export("USER"); 248429088Smarkm } 248529088Smarkm (void) call(status, "status", "notmuch", 0); 248629088Smarkm if (setjmp(peerdied) == 0) 248729088Smarkm telnet(user); 248829088Smarkm (void) NetClose(net); 248929088Smarkm ExitString("Connection closed by foreign host.\n",1); 249029088Smarkm /*NOTREACHED*/ 249157125Sshin fail: 249257125Sshin if (res0 != NULL) 249357125Sshin freeaddrinfo(res0); 249457125Sshin if (src_res0 != NULL) 249557125Sshin freeaddrinfo(src_res0); 249657125Sshin return 0; 249729088Smarkm} 249829088Smarkm 249929088Smarkm#define HELPINDENT (sizeof ("connect")) 250029088Smarkm 250129088Smarkmstatic char 250229088Smarkm openhelp[] = "connect to a site", 250329088Smarkm closehelp[] = "close current connection", 250429088Smarkm logouthelp[] = "forcibly logout remote user and close the connection", 250529088Smarkm quithelp[] = "exit telnet", 250629088Smarkm statushelp[] = "print status information", 250729088Smarkm helphelp[] = "print help information", 250829088Smarkm sendhelp[] = "transmit special characters ('send ?' for more)", 250929088Smarkm sethelp[] = "set operating parameters ('set ?' for more)", 251029088Smarkm unsethelp[] = "unset operating parameters ('unset ?' for more)", 251129088Smarkm togglestring[] ="toggle operating parameters ('toggle ?' for more)", 251229088Smarkm slchelp[] = "change state of special charaters ('slc ?' for more)", 251329088Smarkm displayhelp[] = "display operating parameters", 251487139Smarkm#ifdef AUTHENTICATION 251529088Smarkm authhelp[] = "turn on (off) authentication ('auth ?' for more)", 251629088Smarkm#endif 251729088Smarkm#ifdef ENCRYPTION 251829088Smarkm encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", 251929088Smarkm#endif /* ENCRYPTION */ 252029088Smarkm zhelp[] = "suspend telnet", 252187139Smarkm#ifdef OPIE 252281965Smarkm opiehelp[] = "compute response to OPIE challenge", 252329181Smarkm#endif 252429088Smarkm shellhelp[] = "invoke a subshell", 252529088Smarkm envhelp[] = "change environment variables ('environ ?' for more)", 252629088Smarkm modestring[] = "try to enter line or character mode ('mode ?' for more)"; 252729088Smarkm 252829088Smarkmstatic Command cmdtab[] = { 252929088Smarkm { "close", closehelp, bye, 1 }, 253087139Smarkm { "logout", logouthelp, (int (*)(int, char **))logout, 1 }, 253129088Smarkm { "display", displayhelp, display, 0 }, 253229088Smarkm { "mode", modestring, modecmd, 0 }, 253381965Smarkm { "telnet", openhelp, tn, 0 }, 253429088Smarkm { "open", openhelp, tn, 0 }, 253587139Smarkm { "quit", quithelp, (int (*)(int, char **))quit, 0 }, 253629088Smarkm { "send", sendhelp, sendcmd, 0 }, 253729088Smarkm { "set", sethelp, setcmd, 0 }, 253829088Smarkm { "unset", unsethelp, unsetcmd, 0 }, 253929088Smarkm { "status", statushelp, status, 0 }, 254029088Smarkm { "toggle", togglestring, toggle, 0 }, 254129088Smarkm { "slc", slchelp, slccmd, 0 }, 254287139Smarkm#ifdef AUTHENTICATION 254329088Smarkm { "auth", authhelp, auth_cmd, 0 }, 254429088Smarkm#endif 254529088Smarkm#ifdef ENCRYPTION 254629088Smarkm { "encrypt", encrypthelp, encrypt_cmd, 0 }, 254729088Smarkm#endif /* ENCRYPTION */ 254887139Smarkm { "z", zhelp, (int (*)(int, char **))suspend, 0 }, 254929088Smarkm { "!", shellhelp, shell, 1 }, 255029088Smarkm { "environ", envhelp, env_cmd, 0 }, 255129088Smarkm { "?", helphelp, help, 0 }, 255287139Smarkm#ifdef OPIE 255381965Smarkm { "opie", opiehelp, opie_calc, 0 }, 255429181Smarkm#endif 255587139Smarkm { NULL, NULL, NULL, 0 } 255629088Smarkm}; 255729088Smarkm 255829088Smarkmstatic char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 255929088Smarkmstatic char escapehelp[] = "deprecated command -- use 'set escape' instead"; 256029088Smarkm 256129088Smarkmstatic Command cmdtab2[] = { 256229088Smarkm { "help", 0, help, 0 }, 256329088Smarkm { "escape", escapehelp, setescape, 0 }, 256487139Smarkm { "crmod", crmodhelp, (int (*)(int, char **))togcrmod, 0 }, 256587139Smarkm { NULL, NULL, NULL, 0 } 256629088Smarkm}; 256729088Smarkm 256829088Smarkm 256929088Smarkm/* 257029088Smarkm * Call routine with argc, argv set from args (terminated by 0). 257129088Smarkm */ 257229088Smarkm 257387139Smarkmstatic int 257487139Smarkmcall(intrtn_t routine, ...) 257529088Smarkm{ 257629088Smarkm va_list ap; 257729088Smarkm char *args[100]; 257829088Smarkm int argno = 0; 257929088Smarkm 258087139Smarkm va_start(ap, routine); 258187139Smarkm while ((args[argno++] = va_arg(ap, char *)) != 0); 258229088Smarkm va_end(ap); 258329088Smarkm return (*routine)(argno-1, args); 258429088Smarkm} 258529088Smarkm 258629088Smarkm 258787139Smarkmstatic Command * 258887139Smarkmgetcmd(char *name) 258929088Smarkm{ 259029088Smarkm Command *cm; 259129088Smarkm 259229181Smarkm if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) 259329088Smarkm return cm; 259429088Smarkm return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); 259529088Smarkm} 259629088Smarkm 259787139Smarkmvoid 259887139Smarkmcommand(int top, const char *tbuf, int cnt) 259929088Smarkm{ 260087139Smarkm Command *c; 260129088Smarkm 260229088Smarkm setcommandmode(); 260329088Smarkm if (!top) { 260429088Smarkm putchar('\n'); 260529088Smarkm } else { 260629088Smarkm (void) signal(SIGINT, SIG_DFL); 260729088Smarkm (void) signal(SIGQUIT, SIG_DFL); 260829088Smarkm } 260929088Smarkm for (;;) { 261029088Smarkm if (rlogin == _POSIX_VDISABLE) 261129088Smarkm printf("%s> ", prompt); 261229088Smarkm if (tbuf) { 261387139Smarkm char *cp; 261429088Smarkm cp = line; 261529088Smarkm while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 261629088Smarkm cnt--; 261729088Smarkm tbuf = 0; 261829088Smarkm if (cp == line || *--cp != '\n' || cp == line) 261929088Smarkm goto getline; 262029088Smarkm *cp = '\0'; 262129088Smarkm if (rlogin == _POSIX_VDISABLE) 262229088Smarkm printf("%s\n", line); 262329088Smarkm } else { 262429088Smarkm getline: 262529088Smarkm if (rlogin != _POSIX_VDISABLE) 262629088Smarkm printf("%s> ", prompt); 262729088Smarkm if (fgets(line, sizeof(line), stdin) == NULL) { 262829088Smarkm if (feof(stdin) || ferror(stdin)) { 262929088Smarkm (void) quit(); 263029088Smarkm /*NOTREACHED*/ 263129088Smarkm } 263229088Smarkm break; 263329088Smarkm } 263429088Smarkm } 263529088Smarkm if (line[0] == 0) 263629088Smarkm break; 263729088Smarkm makeargv(); 263829088Smarkm if (margv[0] == 0) { 263929088Smarkm break; 264029088Smarkm } 264129088Smarkm c = getcmd(margv[0]); 264287139Smarkm if (Ambiguous((void *)c)) { 264329088Smarkm printf("?Ambiguous command\n"); 264429088Smarkm continue; 264529088Smarkm } 264629088Smarkm if (c == 0) { 264729088Smarkm printf("?Invalid command\n"); 264829088Smarkm continue; 264929088Smarkm } 265029088Smarkm if (c->needconnect && !connected) { 265129088Smarkm printf("?Need to be connected first.\n"); 265229088Smarkm continue; 265329088Smarkm } 265429088Smarkm if ((*c->handler)(margc, margv)) { 265529088Smarkm break; 265629088Smarkm } 265729088Smarkm } 265829088Smarkm if (!top) { 265929088Smarkm if (!connected) { 266029088Smarkm longjmp(toplevel, 1); 266129088Smarkm /*NOTREACHED*/ 266229088Smarkm } 266329088Smarkm setconnmode(0); 266429088Smarkm } 266529088Smarkm} 266629088Smarkm 266729088Smarkm/* 266829088Smarkm * Help command. 266929088Smarkm */ 267087139Smarkmstatic int 267187139Smarkmhelp(int argc, char *argv[]) 267229088Smarkm{ 267387139Smarkm Command *c; 267429088Smarkm 267529088Smarkm if (argc == 1) { 267629088Smarkm printf("Commands may be abbreviated. Commands are:\n\n"); 267729088Smarkm for (c = cmdtab; c->name; c++) 267829088Smarkm if (c->help) { 267987266Smarkm printf("%-*s\t%s\n", (int)HELPINDENT, c->name, 268029088Smarkm c->help); 268129088Smarkm } 268281965Smarkm return 0; 268329088Smarkm } 268429181Smarkm else while (--argc > 0) { 268587139Smarkm char *arg; 268629088Smarkm arg = *++argv; 268729088Smarkm c = getcmd(arg); 268887139Smarkm if (Ambiguous((void *)c)) 268929088Smarkm printf("?Ambiguous help command %s\n", arg); 269029088Smarkm else if (c == (Command *)0) 269129088Smarkm printf("?Invalid help command %s\n", arg); 269229088Smarkm else 269329088Smarkm printf("%s\n", c->help); 269429088Smarkm } 269581965Smarkm return 0; 269629088Smarkm} 269729088Smarkm 269829088Smarkmstatic char *rcname = 0; 269929088Smarkmstatic char rcbuf[128]; 270029088Smarkm 270187139Smarkmvoid 270287139Smarkmcmdrc(char *m1, char *m2) 270329088Smarkm{ 270487139Smarkm Command *c; 270529088Smarkm FILE *rcfile; 270629088Smarkm int gotmachine = 0; 270729088Smarkm int l1 = strlen(m1); 270829088Smarkm int l2 = strlen(m2); 270968891Skris char m1save[MAXHOSTNAMELEN]; 271029088Smarkm 271129088Smarkm if (skiprc) 271229088Smarkm return; 271329088Smarkm 271468891Skris strlcpy(m1save, m1, sizeof(m1save)); 271529088Smarkm m1 = m1save; 271629088Smarkm 271729088Smarkm if (rcname == 0) { 271829088Smarkm rcname = getenv("HOME"); 271929181Smarkm if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) 272029088Smarkm strcpy(rcbuf, rcname); 272129088Smarkm else 272229088Smarkm rcbuf[0] = '\0'; 272329088Smarkm strcat(rcbuf, "/.telnetrc"); 272429088Smarkm rcname = rcbuf; 272529088Smarkm } 272629088Smarkm 272729088Smarkm if ((rcfile = fopen(rcname, "r")) == 0) { 272829088Smarkm return; 272929088Smarkm } 273029088Smarkm 273129088Smarkm for (;;) { 273229088Smarkm if (fgets(line, sizeof(line), rcfile) == NULL) 273329088Smarkm break; 273429088Smarkm if (line[0] == 0) 273529088Smarkm break; 273629088Smarkm if (line[0] == '#') 273729088Smarkm continue; 273829088Smarkm if (gotmachine) { 273929088Smarkm if (!isspace(line[0])) 274029088Smarkm gotmachine = 0; 274129088Smarkm } 274229088Smarkm if (gotmachine == 0) { 274329088Smarkm if (isspace(line[0])) 274429088Smarkm continue; 274529088Smarkm if (strncasecmp(line, m1, l1) == 0) 274629088Smarkm strncpy(line, &line[l1], sizeof(line) - l1); 274729088Smarkm else if (strncasecmp(line, m2, l2) == 0) 274829088Smarkm strncpy(line, &line[l2], sizeof(line) - l2); 274929088Smarkm else if (strncasecmp(line, "DEFAULT", 7) == 0) 275029088Smarkm strncpy(line, &line[7], sizeof(line) - 7); 275129088Smarkm else 275229088Smarkm continue; 275329088Smarkm if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') 275429088Smarkm continue; 275529088Smarkm gotmachine = 1; 275629088Smarkm } 275729088Smarkm makeargv(); 275829088Smarkm if (margv[0] == 0) 275929088Smarkm continue; 276029088Smarkm c = getcmd(margv[0]); 276187139Smarkm if (Ambiguous((void *)c)) { 276229088Smarkm printf("?Ambiguous command: %s\n", margv[0]); 276329088Smarkm continue; 276429088Smarkm } 276529088Smarkm if (c == 0) { 276629088Smarkm printf("?Invalid command: %s\n", margv[0]); 276729088Smarkm continue; 276829088Smarkm } 276929088Smarkm /* 277029088Smarkm * This should never happen... 277129088Smarkm */ 277229088Smarkm if (c->needconnect && !connected) { 277329088Smarkm printf("?Need to be connected first for %s.\n", margv[0]); 277429088Smarkm continue; 277529088Smarkm } 277629088Smarkm (*c->handler)(margc, margv); 277729088Smarkm } 277829088Smarkm fclose(rcfile); 277929088Smarkm} 278029088Smarkm 278129088Smarkm/* 278229088Smarkm * Source route is handed in as 278329088Smarkm * [!]@hop1@hop2...[@|:]dst 278429088Smarkm * If the leading ! is present, it is a 278529088Smarkm * strict source route, otherwise it is 278629088Smarkm * assmed to be a loose source route. 278729088Smarkm * 278829088Smarkm * We fill in the source route option as 278929088Smarkm * hop1,hop2,hop3...dest 279029088Smarkm * and return a pointer to hop1, which will 279129088Smarkm * be the address to connect() to. 279229088Smarkm * 279329088Smarkm * Arguments: 279456668Sshin * 279556668Sshin * res: ponter to addrinfo structure which contains sockaddr to 279656668Sshin * the host to connect to. 279756668Sshin * 279829088Smarkm * arg: pointer to route list to decipher 279929088Smarkm * 280029088Smarkm * cpp: If *cpp is not equal to NULL, this is a 280129088Smarkm * pointer to a pointer to a character array 280229088Smarkm * that should be filled in with the option. 280329088Smarkm * 280429088Smarkm * lenp: pointer to an integer that contains the 280529088Smarkm * length of *cpp if *cpp != NULL. 280629088Smarkm * 280756668Sshin * protop: pointer to an integer that should be filled in with 280856668Sshin * appropriate protocol for setsockopt, as socket 280956668Sshin * protocol family. 281056668Sshin * 281156668Sshin * optp: pointer to an integer that should be filled in with 281256668Sshin * appropriate option for setsockopt, as socket protocol 281356668Sshin * family. 281456668Sshin * 281529088Smarkm * Return values: 281629088Smarkm * 281756668Sshin * If the return value is 1, then all operations are 281856668Sshin * successful. If the 281929088Smarkm * return value is -1, there was a syntax error in the 282029088Smarkm * option, either unknown characters, or too many hosts. 282129088Smarkm * If the return value is 0, one of the hostnames in the 282229088Smarkm * path is unknown, and *cpp is set to point to the bad 282329088Smarkm * hostname. 282429088Smarkm * 282529088Smarkm * *cpp: If *cpp was equal to NULL, it will be filled 282629088Smarkm * in with a pointer to our static area that has 282729088Smarkm * the option filled in. This will be 32bit aligned. 282829088Smarkm * 282929088Smarkm * *lenp: This will be filled in with how long the option 283029088Smarkm * pointed to by *cpp is. 283129088Smarkm * 283256668Sshin * *protop: This will be filled in with appropriate protocol for 283356668Sshin * setsockopt, as socket protocol family. 283456668Sshin * 283556668Sshin * *optp: This will be filled in with appropriate option for 283656668Sshin * setsockopt, as socket protocol family. 283729088Smarkm */ 283887139Smarkmstatic int 283987139Smarkmsourceroute(struct addrinfo *ai, char *arg, char **cpp, int *lenp, int *protop, int *optp) 284029088Smarkm{ 284163662Sume static char buf[1024 + ALIGNBYTES]; /*XXX*/ 284256668Sshin char *cp, *cp2, *lsrp, *ep; 284387139Smarkm struct sockaddr_in *_sin; 284487277Sjhay#ifdef INET6 284556668Sshin struct sockaddr_in6 *sin6; 284687277Sjhay struct cmsghdr *cmsg; 284787277Sjhay#endif 284856668Sshin struct addrinfo hints, *res; 284956668Sshin int error; 285087139Smarkm char c; 285129088Smarkm 285229088Smarkm /* 285329088Smarkm * Verify the arguments, and make sure we have 285429088Smarkm * at least 7 bytes for the option. 285529088Smarkm */ 285629088Smarkm if (cpp == NULL || lenp == NULL) 285757724Sshin return -1; 285856668Sshin if (*cpp != NULL) { 285956668Sshin switch (res->ai_family) { 286056668Sshin case AF_INET: 286156668Sshin if (*lenp < 7) 286257724Sshin return -1; 286356668Sshin break; 286456668Sshin#ifdef INET6 286556668Sshin case AF_INET6: 286687139Smarkm if (*lenp < (int)CMSG_SPACE(sizeof(struct ip6_rthdr) + 286757724Sshin sizeof(struct in6_addr))) 286857724Sshin return -1; 286956668Sshin break; 287056668Sshin#endif 287156668Sshin } 287256668Sshin } 287329088Smarkm /* 287429088Smarkm * Decide whether we have a buffer passed to us, 287529088Smarkm * or if we need to use our own static buffer. 287629088Smarkm */ 287729088Smarkm if (*cpp) { 287829088Smarkm lsrp = *cpp; 287956668Sshin ep = lsrp + *lenp; 288029088Smarkm } else { 288163662Sume *cpp = lsrp = (char *)ALIGN(buf); 288256668Sshin ep = lsrp + 1024; 288329088Smarkm } 288429088Smarkm 288529088Smarkm cp = arg; 288629088Smarkm 288756668Sshin#ifdef INET6 288856668Sshin if (ai->ai_family == AF_INET6) { 288956668Sshin cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0); 289056668Sshin if (*cp != '@') 289156668Sshin return -1; 289256668Sshin *protop = IPPROTO_IPV6; 289356668Sshin *optp = IPV6_PKTOPTIONS; 289456668Sshin } else 289556668Sshin#endif 289656668Sshin { 289729088Smarkm /* 289829088Smarkm * Next, decide whether we have a loose source 289929088Smarkm * route or a strict source route, and fill in 290029088Smarkm * the begining of the option. 290129088Smarkm */ 290229088Smarkm if (*cp == '!') { 290329088Smarkm cp++; 290429088Smarkm *lsrp++ = IPOPT_SSRR; 290529088Smarkm } else 290629088Smarkm *lsrp++ = IPOPT_LSRR; 290729088Smarkm 290829088Smarkm if (*cp != '@') 290957724Sshin return -1; 291029088Smarkm 291129088Smarkm lsrp++; /* skip over length, we'll fill it in later */ 291229088Smarkm *lsrp++ = 4; 291356668Sshin *protop = IPPROTO_IP; 291456668Sshin *optp = IP_OPTIONS; 291556668Sshin } 291629088Smarkm 291729088Smarkm cp++; 291856668Sshin memset(&hints, 0, sizeof(hints)); 291956668Sshin hints.ai_family = ai->ai_family; 292056668Sshin hints.ai_socktype = SOCK_STREAM; 292129088Smarkm for (c = 0;;) { 292256668Sshin if ( 292356668Sshin#ifdef INET6 292456668Sshin ai->ai_family != AF_INET6 && 292556668Sshin#endif 292656668Sshin c == ':') 292729088Smarkm cp2 = 0; 292829181Smarkm else for (cp2 = cp; (c = *cp2); cp2++) { 292929088Smarkm if (c == ',') { 293029088Smarkm *cp2++ = '\0'; 293129088Smarkm if (*cp2 == '@') 293229088Smarkm cp2++; 293329088Smarkm } else if (c == '@') { 293429088Smarkm *cp2++ = '\0'; 293556668Sshin } else if ( 293656668Sshin#ifdef INET6 293756668Sshin ai->ai_family != AF_INET6 && 293856668Sshin#endif 293956668Sshin c == ':') { 294029088Smarkm *cp2++ = '\0'; 294129088Smarkm } else 294229088Smarkm continue; 294329088Smarkm break; 294429088Smarkm } 294529088Smarkm if (!c) 294629088Smarkm cp2 = 0; 294729088Smarkm 294856668Sshin hints.ai_flags = AI_NUMERICHOST; 294981965Smarkm error = getaddrinfo(cp, NULL, &hints, &res); 295062805Sume if (error == EAI_NODATA) { 295156668Sshin hints.ai_flags = 0; 295256668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 295356668Sshin } 295456668Sshin if (error != 0) { 295556668Sshin fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); 295656668Sshin if (error == EAI_SYSTEM) 295756668Sshin fprintf(stderr, "%s: %s\n", cp, 295856668Sshin strerror(errno)); 295929088Smarkm *cpp = cp; 296029088Smarkm return(0); 296129088Smarkm } 296256668Sshin#ifdef INET6 296356668Sshin if (res->ai_family == AF_INET6) { 296456668Sshin sin6 = (struct sockaddr_in6 *)res->ai_addr; 296556668Sshin inet6_rthdr_add(cmsg, &sin6->sin6_addr, 296656668Sshin IPV6_RTHDR_LOOSE); 296756668Sshin } else 296856668Sshin#endif 296956668Sshin { 297087139Smarkm _sin = (struct sockaddr_in *)res->ai_addr; 297187139Smarkm memcpy(lsrp, (char *)&_sin->sin_addr, 4); 297229088Smarkm lsrp += 4; 297356668Sshin } 297429088Smarkm if (cp2) 297529088Smarkm cp = cp2; 297629088Smarkm else 297729088Smarkm break; 297829088Smarkm /* 297929088Smarkm * Check to make sure there is space for next address 298029088Smarkm */ 298156668Sshin#ifdef INET6 298256668Sshin if (res->ai_family == AF_INET6) { 298357724Sshin if (((char *)CMSG_DATA(cmsg) + 298456668Sshin sizeof(struct ip6_rthdr) + 298556668Sshin ((inet6_rthdr_segments(cmsg) + 1) * 298656668Sshin sizeof(struct in6_addr))) > ep) 298757724Sshin return -1; 298856668Sshin } else 298956668Sshin#endif 299056668Sshin if (lsrp + 4 > ep) 299157724Sshin return -1; 299256668Sshin freeaddrinfo(res); 299329088Smarkm } 299456668Sshin#ifdef INET6 299556668Sshin if (res->ai_family == AF_INET6) { 299656668Sshin inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 299756668Sshin *lenp = cmsg->cmsg_len; 299856668Sshin } else 299956668Sshin#endif 300056668Sshin { 300129088Smarkm if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 300229088Smarkm *cpp = 0; 300329088Smarkm *lenp = 0; 300457724Sshin return -1; 300529088Smarkm } 300629088Smarkm *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 300729088Smarkm *lenp = lsrp - *cpp; 300856668Sshin } 300956668Sshin freeaddrinfo(res); 301056668Sshin return 1; 301129088Smarkm} 3012