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. 13351432Semaste * 3. Neither the name of the University nor the names of its contributors 1429088Smarkm * may be used to endorse or promote products derived from this software 1529088Smarkm * without specific prior written permission. 1629088Smarkm * 1729088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1829088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1929088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2029088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2129088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2229088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2329088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2429088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2529088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2629088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2729088Smarkm * SUCH DAMAGE. 2829088Smarkm */ 2929088Smarkm 30114630Sobrien#if 0 3129088Smarkm#ifndef lint 3229181Smarkmstatic const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; 3387139Smarkm#endif 34114630Sobrien#endif 35114630Sobrien#include <sys/cdefs.h> 36114630Sobrien__FBSDID("$FreeBSD: stable/11/contrib/telnet/telnet/commands.c 351432 2019-08-23 17:40:47Z emaste $"); 3729088Smarkm 3829088Smarkm#include <sys/param.h> 3977095Sdillon#include <sys/un.h> 4029088Smarkm#include <sys/file.h> 4129088Smarkm#include <sys/socket.h> 4229088Smarkm#include <netinet/in.h> 4329088Smarkm 44350140Sphilip#include <assert.h> 4587139Smarkm#include <ctype.h> 4687139Smarkm#include <err.h> 4787139Smarkm#include <errno.h> 4829088Smarkm#include <netdb.h> 4929088Smarkm#include <pwd.h> 5087139Smarkm#include <signal.h> 5187139Smarkm#include <stdarg.h> 5287139Smarkm#include <stdlib.h> 5387139Smarkm#include <string.h> 5429181Smarkm#include <unistd.h> 5529088Smarkm 5629088Smarkm#include <arpa/telnet.h> 5781965Smarkm#include <arpa/inet.h> 5829088Smarkm 5929088Smarkm#include "general.h" 6029088Smarkm 6129088Smarkm#include "ring.h" 6229088Smarkm 6329088Smarkm#include "externs.h" 6429088Smarkm#include "defines.h" 6529088Smarkm#include "types.h" 6687139Smarkm#include "misc.h" 6729088Smarkm 6887139Smarkm#ifdef AUTHENTICATION 6929181Smarkm#include <libtelnet/auth.h> 7029181Smarkm#endif 7187139Smarkm#ifdef ENCRYPTION 7229181Smarkm#include <libtelnet/encrypt.h> 7329181Smarkm#endif 7429181Smarkm 7529088Smarkm#include <netinet/in_systm.h> 7629088Smarkm#include <netinet/ip.h> 7756668Sshin#include <netinet/ip6.h> 7829088Smarkm 7981965Smarkm#ifndef MAXHOSTNAMELEN 8081965Smarkm#define MAXHOSTNAMELEN 256 8196385Salfred#endif 8229088Smarkm 8387139Smarkmtypedef int (*intrtn_t)(int, char **); 8487139Smarkm 8587139Smarkm#ifdef AUTHENTICATION 8687155Smarkmextern int auth_togdebug(int); 8787139Smarkm#endif 8887139Smarkm#ifdef ENCRYPTION 8987155Smarkmextern int EncryptAutoEnc(int); 9087155Smarkmextern int EncryptAutoDec(int); 9187155Smarkmextern int EncryptDebug(int); 9287155Smarkmextern int EncryptVerbose(int); 9387139Smarkm#endif /* ENCRYPTION */ 9429088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 9529088Smarkmint tos = -1; 9629088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 9729088Smarkm 9829088Smarkmchar *hostname; 9929088Smarkmstatic char _hostname[MAXHOSTNAMELEN]; 10029088Smarkm 10187139Smarkmstatic int help(int, char **); 10287139Smarkmstatic int call(intrtn_t, ...); 10387139Smarkmstatic void cmdrc(char *, char *); 10487277Sjhay#ifdef INET6 10587139Smarkmstatic int switch_af(struct addrinfo **); 10687277Sjhay#endif 10787139Smarkmstatic int togglehelp(void); 10887139Smarkmstatic int send_tncmd(void (*)(int, int), const char *, char *); 10987139Smarkmstatic int setmod(int); 11087139Smarkmstatic int clearmode(int); 11187139Smarkmstatic int modehelp(void); 112305552Sdimstatic int sourceroute(struct addrinfo *, char *, unsigned char **, int *, int *, int *); 11329088Smarkm 11429088Smarkmtypedef struct { 11587139Smarkm const char *name; /* command name */ 11687139Smarkm const char *help; /* help string (NULL for no help) */ 11787139Smarkm int (*handler)(int, char **); /* routine which executes command */ 11829088Smarkm int needconnect; /* Do we need to be connected to execute? */ 11929088Smarkm} Command; 12029088Smarkm 12129088Smarkmstatic char line[256]; 12229088Smarkmstatic char saveline[256]; 12329088Smarkmstatic int margc; 12429088Smarkmstatic char *margv[20]; 12529088Smarkm 12687139Smarkm#ifdef OPIE 12729181Smarkm#include <sys/wait.h> 12881965Smarkm#define PATH_OPIEKEY "/usr/bin/opiekey" 12987139Smarkmstatic int 13087139Smarkmopie_calc(int argc, char *argv[]) 13129181Smarkm{ 13229181Smarkm int status; 13329181Smarkm 13429181Smarkm if(argc != 3) { 13529181Smarkm printf("%s sequence challenge\n", argv[0]); 13687139Smarkm return (0); 13729181Smarkm } 13829181Smarkm 13929181Smarkm switch(fork()) { 14029181Smarkm case 0: 14181965Smarkm execv(PATH_OPIEKEY, argv); 14229181Smarkm exit (1); 14329181Smarkm case -1: 14429181Smarkm perror("fork"); 14529181Smarkm break; 14629181Smarkm default: 14729181Smarkm (void) wait(&status); 14829181Smarkm if (WIFEXITED(status)) 14929181Smarkm return (WEXITSTATUS(status)); 15029181Smarkm } 15187139Smarkm return (0); 15229181Smarkm} 15329181Smarkm#endif 15429181Smarkm 15587139Smarkmstatic void 15687139Smarkmmakeargv(void) 15729088Smarkm{ 15887139Smarkm char *cp, *cp2, c; 15987139Smarkm char **argp = margv; 16029088Smarkm 16129088Smarkm margc = 0; 16229088Smarkm cp = line; 16329088Smarkm if (*cp == '!') { /* Special case shell escape */ 16429088Smarkm strcpy(saveline, line); /* save for shell command */ 16587139Smarkm *argp++ = strdup("!"); /* No room in string to get this */ 16629088Smarkm margc++; 16729088Smarkm cp++; 16829088Smarkm } 16929181Smarkm while ((c = *cp)) { 17087139Smarkm int inquote = 0; 17129088Smarkm while (isspace(c)) 17229088Smarkm c = *++cp; 17329088Smarkm if (c == '\0') 17429088Smarkm break; 17529088Smarkm *argp++ = cp; 17629088Smarkm margc += 1; 17729088Smarkm for (cp2 = cp; c != '\0'; c = *++cp) { 17829088Smarkm if (inquote) { 17929088Smarkm if (c == inquote) { 18029088Smarkm inquote = 0; 18129088Smarkm continue; 18229088Smarkm } 18329088Smarkm } else { 18429088Smarkm if (c == '\\') { 18529088Smarkm if ((c = *++cp) == '\0') 18629088Smarkm break; 18729088Smarkm } else if (c == '"') { 18829088Smarkm inquote = '"'; 18929088Smarkm continue; 19029088Smarkm } else if (c == '\'') { 19129088Smarkm inquote = '\''; 19229088Smarkm continue; 19329088Smarkm } else if (isspace(c)) 19429088Smarkm break; 19529088Smarkm } 19629088Smarkm *cp2++ = c; 19729088Smarkm } 19829088Smarkm *cp2 = '\0'; 19929088Smarkm if (c == '\0') 20029088Smarkm break; 20129088Smarkm cp++; 20229088Smarkm } 20329088Smarkm *argp++ = 0; 20429088Smarkm} 20529088Smarkm 20629088Smarkm/* 20729088Smarkm * Make a character string into a number. 20829088Smarkm * 20929088Smarkm * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 21029088Smarkm */ 21129088Smarkm 21287139Smarkmstatic int 21387139Smarkmspecial(char *s) 21429088Smarkm{ 21587139Smarkm char c; 21629088Smarkm char b; 21729088Smarkm 21829088Smarkm switch (*s) { 21929088Smarkm case '^': 22029088Smarkm b = *++s; 22129088Smarkm if (b == '?') { 22229088Smarkm c = b | 0x40; /* DEL */ 22329088Smarkm } else { 22429088Smarkm c = b & 0x1f; 22529088Smarkm } 22629088Smarkm break; 22729088Smarkm default: 22829088Smarkm c = *s; 22929088Smarkm break; 23029088Smarkm } 23129088Smarkm return c; 23229088Smarkm} 23329088Smarkm 23429088Smarkm/* 23529088Smarkm * Construct a control character sequence 23629088Smarkm * for a special character. 23729088Smarkm */ 23887139Smarkmstatic const char * 23987139Smarkmcontrol(cc_t c) 24029088Smarkm{ 24129088Smarkm static char buf[5]; 24229088Smarkm /* 24329088Smarkm * The only way I could get the Sun 3.5 compiler 24429088Smarkm * to shut up about 24529088Smarkm * if ((unsigned int)c >= 0x80) 24629088Smarkm * was to assign "c" to an unsigned int variable... 24729088Smarkm * Arggg.... 24829088Smarkm */ 24987139Smarkm unsigned int uic = (unsigned int)c; 25029088Smarkm 25129088Smarkm if (uic == 0x7f) 25229088Smarkm return ("^?"); 25329088Smarkm if (c == (cc_t)_POSIX_VDISABLE) { 25429088Smarkm return "off"; 25529088Smarkm } 25629088Smarkm if (uic >= 0x80) { 25729088Smarkm buf[0] = '\\'; 25829088Smarkm buf[1] = ((c>>6)&07) + '0'; 25929088Smarkm buf[2] = ((c>>3)&07) + '0'; 26029088Smarkm buf[3] = (c&07) + '0'; 26129088Smarkm buf[4] = 0; 26229088Smarkm } else if (uic >= 0x20) { 26329088Smarkm buf[0] = c; 26429088Smarkm buf[1] = 0; 26529088Smarkm } else { 26629088Smarkm buf[0] = '^'; 26729088Smarkm buf[1] = '@'+c; 26829088Smarkm buf[2] = 0; 26929088Smarkm } 27029088Smarkm return (buf); 27129088Smarkm} 27229088Smarkm 27329088Smarkm/* 27429088Smarkm * The following are data structures and routines for 27529088Smarkm * the "send" command. 27629088Smarkm * 27729088Smarkm */ 27829088Smarkm 27929088Smarkmstruct sendlist { 28087139Smarkm const char *name; /* How user refers to it (case independent) */ 28187139Smarkm const char *help; /* Help information (0 ==> no help) */ 28229088Smarkm int needconnect; /* Need to be connected */ 28329088Smarkm int narg; /* Number of arguments */ 28487139Smarkm int (*handler)(char *, ...); /* Routine to perform (for special ops) */ 28529088Smarkm int nbyte; /* Number of bytes to send this command */ 28629088Smarkm int what; /* Character to be sent (<0 ==> special) */ 28729088Smarkm}; 28829088Smarkm 28929088Smarkm 29029088Smarkmstatic int 29187155Smarkm send_esc(void), 29287155Smarkm send_help(void), 29387155Smarkm send_docmd(char *), 29487155Smarkm send_dontcmd(char *), 29587155Smarkm send_willcmd(char *), 29687155Smarkm send_wontcmd(char *); 29729088Smarkm 29829088Smarkmstatic struct sendlist Sendlist[] = { 29987139Smarkm { "ao", "Send Telnet Abort output", 1, 0, NULL, 2, AO }, 30087139Smarkm { "ayt", "Send Telnet 'Are You There'", 1, 0, NULL, 2, AYT }, 30187139Smarkm { "brk", "Send Telnet Break", 1, 0, NULL, 2, BREAK }, 30287139Smarkm { "break", NULL, 1, 0, NULL, 2, BREAK }, 30387139Smarkm { "ec", "Send Telnet Erase Character", 1, 0, NULL, 2, EC }, 30487139Smarkm { "el", "Send Telnet Erase Line", 1, 0, NULL, 2, EL }, 30587139Smarkm { "escape", "Send current escape character",1, 0, (int (*)(char *, ...))send_esc, 1, 0 }, 30687139Smarkm { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, NULL, 2, GA }, 30787139Smarkm { "ip", "Send Telnet Interrupt Process",1, 0, NULL, 2, IP }, 30887139Smarkm { "intp", NULL, 1, 0, NULL, 2, IP }, 30987139Smarkm { "interrupt", NULL, 1, 0, NULL, 2, IP }, 31087139Smarkm { "intr", NULL, 1, 0, NULL, 2, IP }, 31187139Smarkm { "nop", "Send Telnet 'No operation'", 1, 0, NULL, 2, NOP }, 31287139Smarkm { "eor", "Send Telnet 'End of Record'", 1, 0, NULL, 2, EOR }, 31387139Smarkm { "abort", "Send Telnet 'Abort Process'", 1, 0, NULL, 2, ABORT }, 31487139Smarkm { "susp", "Send Telnet 'Suspend Process'",1, 0, NULL, 2, SUSP }, 31587139Smarkm { "eof", "Send Telnet End of File Character", 1, 0, NULL, 2, xEOF }, 31687139Smarkm { "synch", "Perform Telnet 'Synch operation'", 1, 0, (int (*)(char *, ...))dosynch, 2, 0 }, 31787139Smarkm { "getstatus", "Send request for STATUS", 1, 0, (int (*)(char *, ...))get_status, 6, 0 }, 31887139Smarkm { "?", "Display send options", 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, 31987139Smarkm { "help", NULL, 0, 0, (int (*)(char *, ...))send_help, 0, 0 }, 32087139Smarkm { "do", NULL, 0, 1, (int (*)(char *, ...))send_docmd, 3, 0 }, 32187139Smarkm { "dont", NULL, 0, 1, (int (*)(char *, ...))send_dontcmd, 3, 0 }, 32287139Smarkm { "will", NULL, 0, 1, (int (*)(char *, ...))send_willcmd, 3, 0 }, 32387139Smarkm { "wont", NULL, 0, 1, (int (*)(char *, ...))send_wontcmd, 3, 0 }, 32487139Smarkm { NULL, NULL, 0, 0, NULL, 0, 0 } 32529088Smarkm}; 32629088Smarkm 32729088Smarkm#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ 32829088Smarkm sizeof(struct sendlist))) 32929088Smarkm 33087139Smarkmstatic int 33187139Smarkmsendcmd(int argc, char *argv[]) 33229088Smarkm{ 33329088Smarkm int count; /* how many bytes we are going to need to send */ 33429088Smarkm int i; 33529088Smarkm struct sendlist *s; /* pointer to current command */ 33629088Smarkm int success = 0; 33729088Smarkm int needconnect = 0; 33829088Smarkm 33929088Smarkm if (argc < 2) { 34029088Smarkm printf("need at least one argument for 'send' command\n"); 34129088Smarkm printf("'send ?' for help\n"); 34229088Smarkm return 0; 34329088Smarkm } 34429088Smarkm /* 34529088Smarkm * First, validate all the send arguments. 34629088Smarkm * In addition, we see how much space we are going to need, and 34729088Smarkm * whether or not we will be doing a "SYNCH" operation (which 34829088Smarkm * flushes the network queue). 34929088Smarkm */ 35029088Smarkm count = 0; 35129088Smarkm for (i = 1; i < argc; i++) { 35229088Smarkm s = GETSEND(argv[i]); 35329088Smarkm if (s == 0) { 35429088Smarkm printf("Unknown send argument '%s'\n'send ?' for help.\n", 35529088Smarkm argv[i]); 35629088Smarkm return 0; 35787139Smarkm } else if (Ambiguous((void *)s)) { 35829088Smarkm printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 35929088Smarkm argv[i]); 36029088Smarkm return 0; 36129088Smarkm } 36229088Smarkm if (i + s->narg >= argc) { 36329088Smarkm fprintf(stderr, 36429088Smarkm "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", 36529088Smarkm s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 36629088Smarkm return 0; 36729088Smarkm } 36829088Smarkm count += s->nbyte; 36987139Smarkm if ((void *)s->handler == (void *)send_help) { 37029088Smarkm send_help(); 37129088Smarkm return 0; 37229088Smarkm } 37329088Smarkm 37429088Smarkm i += s->narg; 37529088Smarkm needconnect += s->needconnect; 37629088Smarkm } 37729088Smarkm if (!connected && needconnect) { 37829088Smarkm printf("?Need to be connected first.\n"); 37929088Smarkm printf("'send ?' for help\n"); 38029088Smarkm return 0; 38129088Smarkm } 38229088Smarkm /* Now, do we have enough room? */ 38329088Smarkm if (NETROOM() < count) { 38429088Smarkm printf("There is not enough room in the buffer TO the network\n"); 38529088Smarkm printf("to process your request. Nothing will be done.\n"); 38629088Smarkm printf("('send synch' will throw away most data in the network\n"); 38729088Smarkm printf("buffer, if this might help.)\n"); 38829088Smarkm return 0; 38929088Smarkm } 39029088Smarkm /* OK, they are all OK, now go through again and actually send */ 39129088Smarkm count = 0; 39229088Smarkm for (i = 1; i < argc; i++) { 39329088Smarkm if ((s = GETSEND(argv[i])) == 0) { 39429088Smarkm fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 39587139Smarkm quit(); 39629088Smarkm /*NOTREACHED*/ 39729088Smarkm } 39829088Smarkm if (s->handler) { 39929088Smarkm count++; 40029088Smarkm success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 40129088Smarkm (s->narg > 1) ? argv[i+2] : 0); 40229088Smarkm i += s->narg; 40329088Smarkm } else { 40429088Smarkm NET2ADD(IAC, s->what); 40529088Smarkm printoption("SENT", IAC, s->what); 40629088Smarkm } 40729088Smarkm } 40829088Smarkm return (count == success); 40929088Smarkm} 41029088Smarkm 41187139Smarkmstatic int 41287139Smarkmsend_esc(void) 41329088Smarkm{ 41429088Smarkm NETADD(escape); 41529088Smarkm return 1; 41629088Smarkm} 41729088Smarkm 41887139Smarkmstatic int 41987139Smarkmsend_docmd(char *name) 42029088Smarkm{ 42129088Smarkm return(send_tncmd(send_do, "do", name)); 42229088Smarkm} 42329088Smarkm 42487139Smarkmstatic int 42529088Smarkmsend_dontcmd(name) 42629088Smarkm char *name; 42729088Smarkm{ 42829088Smarkm return(send_tncmd(send_dont, "dont", name)); 42929088Smarkm} 43087139Smarkm 43187139Smarkmstatic int 43287139Smarkmsend_willcmd(char *name) 43329088Smarkm{ 43429088Smarkm return(send_tncmd(send_will, "will", name)); 43529088Smarkm} 43687139Smarkm 43787139Smarkmstatic int 43887139Smarkmsend_wontcmd(char *name) 43929088Smarkm{ 44029088Smarkm return(send_tncmd(send_wont, "wont", name)); 44129088Smarkm} 44229088Smarkm 44387139Smarkmstatic int 44487139Smarkmsend_tncmd(void (*func)(int, int), const char *cmd, char *name) 44529088Smarkm{ 44629088Smarkm char **cpp; 44729088Smarkm extern char *telopts[]; 44887139Smarkm int val = 0; 44929088Smarkm 45029088Smarkm if (isprefix(name, "help") || isprefix(name, "?")) { 45187139Smarkm int col, len; 45229088Smarkm 453103955Smarkm printf("usage: send %s <value|option>\n", cmd); 45429088Smarkm printf("\"value\" must be from 0 to 255\n"); 45529088Smarkm printf("Valid options are:\n\t"); 45629088Smarkm 45729088Smarkm col = 8; 45829088Smarkm for (cpp = telopts; *cpp; cpp++) { 45929088Smarkm len = strlen(*cpp) + 3; 46029088Smarkm if (col + len > 65) { 46129088Smarkm printf("\n\t"); 46229088Smarkm col = 8; 46329088Smarkm } 46429088Smarkm printf(" \"%s\"", *cpp); 46529088Smarkm col += len; 46629088Smarkm } 46729088Smarkm printf("\n"); 46829088Smarkm return 0; 46929088Smarkm } 47029088Smarkm cpp = (char **)genget(name, telopts, sizeof(char *)); 47129088Smarkm if (Ambiguous(cpp)) { 47229088Smarkm fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", 47329088Smarkm name, cmd); 47429088Smarkm return 0; 47529088Smarkm } 47629088Smarkm if (cpp) { 47729088Smarkm val = cpp - telopts; 47829088Smarkm } else { 47987139Smarkm char *cp = name; 48029088Smarkm 48129088Smarkm while (*cp >= '0' && *cp <= '9') { 48229088Smarkm val *= 10; 48329088Smarkm val += *cp - '0'; 48429088Smarkm cp++; 48529088Smarkm } 48629088Smarkm if (*cp != 0) { 48729088Smarkm fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 48829088Smarkm name, cmd); 48929088Smarkm return 0; 49029088Smarkm } else if (val < 0 || val > 255) { 49129088Smarkm fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", 49229088Smarkm name, cmd); 49329088Smarkm return 0; 49429088Smarkm } 49529088Smarkm } 49629088Smarkm if (!connected) { 49729088Smarkm printf("?Need to be connected first.\n"); 49829088Smarkm return 0; 49929088Smarkm } 50029088Smarkm (*func)(val, 1); 50129088Smarkm return 1; 50229088Smarkm} 50329088Smarkm 50487139Smarkmstatic int 50587139Smarkmsend_help(void) 50629088Smarkm{ 50729088Smarkm struct sendlist *s; /* pointer to current command */ 50829088Smarkm for (s = Sendlist; s->name; s++) { 50929088Smarkm if (s->help) 51029088Smarkm printf("%-15s %s\n", s->name, s->help); 51129088Smarkm } 51229088Smarkm return(0); 51329088Smarkm} 51429088Smarkm 51529088Smarkm/* 51629088Smarkm * The following are the routines and data structures referred 51729088Smarkm * to by the arguments to the "toggle" command. 51829088Smarkm */ 51929088Smarkm 52087139Smarkmstatic int 52187139Smarkmlclchars(void) 52229088Smarkm{ 52329088Smarkm donelclchars = 1; 52429088Smarkm return 1; 52529088Smarkm} 52629088Smarkm 52787139Smarkmstatic int 52887139Smarkmtogdebug(void) 52929088Smarkm{ 53029088Smarkm#ifndef NOT43 53129088Smarkm if (net > 0 && 532114911Smarkm (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, telnet_debug)) < 0) { 53329088Smarkm perror("setsockopt (SO_DEBUG)"); 53429088Smarkm } 53529088Smarkm#else /* NOT43 */ 536114911Smarkm if (telnet_debug) { 53729181Smarkm if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) 53829088Smarkm perror("setsockopt (SO_DEBUG)"); 53929088Smarkm } else 54029088Smarkm printf("Cannot turn off socket debugging\n"); 54129088Smarkm#endif /* NOT43 */ 54229088Smarkm return 1; 54329088Smarkm} 54429088Smarkm 54529088Smarkm 54687139Smarkmstatic int 54787139Smarkmtogcrlf(void) 54829088Smarkm{ 54929088Smarkm if (crlf) { 55029088Smarkm printf("Will send carriage returns as telnet <CR><LF>.\n"); 55129088Smarkm } else { 55229088Smarkm printf("Will send carriage returns as telnet <CR><NUL>.\n"); 55329088Smarkm } 55429088Smarkm return 1; 55529088Smarkm} 55629088Smarkm 55729088Smarkmint binmode; 55829088Smarkm 55987139Smarkmstatic int 56087139Smarkmtogbinary(int val) 56129088Smarkm{ 56229088Smarkm donebinarytoggle = 1; 56329088Smarkm 56429088Smarkm if (val >= 0) { 56529088Smarkm binmode = val; 56629088Smarkm } else { 56729088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 56829088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 56929088Smarkm binmode = 1; 57029088Smarkm } else if (my_want_state_is_wont(TELOPT_BINARY) && 57129088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 57229088Smarkm binmode = 0; 57329088Smarkm } 57429088Smarkm val = binmode ? 0 : 1; 57529088Smarkm } 57629088Smarkm 57729088Smarkm if (val == 1) { 57829088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 57929088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 58029088Smarkm printf("Already operating in binary mode with remote host.\n"); 58129088Smarkm } else { 58229088Smarkm printf("Negotiating binary mode with remote host.\n"); 58329088Smarkm tel_enter_binary(3); 58429088Smarkm } 58529088Smarkm } else { 58629088Smarkm if (my_want_state_is_wont(TELOPT_BINARY) && 58729088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 58829088Smarkm printf("Already in network ascii mode with remote host.\n"); 58929088Smarkm } else { 59029088Smarkm printf("Negotiating network ascii mode with remote host.\n"); 59129088Smarkm tel_leave_binary(3); 59229088Smarkm } 59329088Smarkm } 59429088Smarkm return 1; 59529088Smarkm} 59629088Smarkm 59787139Smarkmstatic int 59887139Smarkmtogrbinary(int val) 59929088Smarkm{ 60029088Smarkm donebinarytoggle = 1; 60129088Smarkm 60229088Smarkm if (val == -1) 60329088Smarkm val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 60429088Smarkm 60529088Smarkm if (val == 1) { 60629088Smarkm if (my_want_state_is_do(TELOPT_BINARY)) { 60729088Smarkm printf("Already receiving in binary mode.\n"); 60829088Smarkm } else { 60929088Smarkm printf("Negotiating binary mode on input.\n"); 61029088Smarkm tel_enter_binary(1); 61129088Smarkm } 61229088Smarkm } else { 61329088Smarkm if (my_want_state_is_dont(TELOPT_BINARY)) { 61429088Smarkm printf("Already receiving in network ascii mode.\n"); 61529088Smarkm } else { 61629088Smarkm printf("Negotiating network ascii mode on input.\n"); 61729088Smarkm tel_leave_binary(1); 61829088Smarkm } 61929088Smarkm } 62029088Smarkm return 1; 62129088Smarkm} 62229088Smarkm 62387139Smarkmstatic int 62487139Smarkmtogxbinary(int val) 62529088Smarkm{ 62629088Smarkm donebinarytoggle = 1; 62729088Smarkm 62829088Smarkm if (val == -1) 62929088Smarkm val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 63029088Smarkm 63129088Smarkm if (val == 1) { 63229088Smarkm if (my_want_state_is_will(TELOPT_BINARY)) { 63329088Smarkm printf("Already transmitting in binary mode.\n"); 63429088Smarkm } else { 63529088Smarkm printf("Negotiating binary mode on output.\n"); 63629088Smarkm tel_enter_binary(2); 63729088Smarkm } 63829088Smarkm } else { 63929088Smarkm if (my_want_state_is_wont(TELOPT_BINARY)) { 64029088Smarkm printf("Already transmitting in network ascii mode.\n"); 64129088Smarkm } else { 64229088Smarkm printf("Negotiating network ascii mode on output.\n"); 64329088Smarkm tel_leave_binary(2); 64429088Smarkm } 64529088Smarkm } 64629088Smarkm return 1; 64729088Smarkm} 64829088Smarkm 64929088Smarkmstruct togglelist { 65087139Smarkm const char *name; /* name of toggle */ 65187139Smarkm const char *help; /* help message */ 65287139Smarkm int (*handler)(int); /* routine to do actual setting */ 65329088Smarkm int *variable; 65487139Smarkm const char *actionexplanation; 65529088Smarkm}; 65629088Smarkm 65729088Smarkmstatic struct togglelist Togglelist[] = { 65829088Smarkm { "autoflush", 65929088Smarkm "flushing of output when sending interrupt characters", 66029088Smarkm 0, 66129088Smarkm &autoflush, 66229088Smarkm "flush output when sending interrupt characters" }, 66329088Smarkm { "autosynch", 66429088Smarkm "automatic sending of interrupt characters in urgent mode", 66529088Smarkm 0, 66629088Smarkm &autosynch, 66729088Smarkm "send interrupt characters in urgent mode" }, 66887139Smarkm#ifdef AUTHENTICATION 66929088Smarkm { "autologin", 67029088Smarkm "automatic sending of login and/or authentication info", 67129088Smarkm 0, 67229088Smarkm &autologin, 67329088Smarkm "send login name and/or authentication information" }, 67429088Smarkm { "authdebug", 67529088Smarkm "Toggle authentication debugging", 67629088Smarkm auth_togdebug, 67729088Smarkm 0, 67829088Smarkm "print authentication debugging information" }, 67929088Smarkm#endif 68029088Smarkm#ifdef ENCRYPTION 68129088Smarkm { "autoencrypt", 68229088Smarkm "automatic encryption of data stream", 68329088Smarkm EncryptAutoEnc, 68429088Smarkm 0, 68529088Smarkm "automatically encrypt output" }, 68629088Smarkm { "autodecrypt", 68729088Smarkm "automatic decryption of data stream", 68829088Smarkm EncryptAutoDec, 68929088Smarkm 0, 69029088Smarkm "automatically decrypt input" }, 69129088Smarkm { "verbose_encrypt", 69229088Smarkm "Toggle verbose encryption output", 69329088Smarkm EncryptVerbose, 69429088Smarkm 0, 69529088Smarkm "print verbose encryption output" }, 69629088Smarkm { "encdebug", 69729088Smarkm "Toggle encryption debugging", 69829088Smarkm EncryptDebug, 69929088Smarkm 0, 70029088Smarkm "print encryption debugging information" }, 70129088Smarkm#endif /* ENCRYPTION */ 70229088Smarkm { "skiprc", 70329088Smarkm "don't read ~/.telnetrc file", 70429088Smarkm 0, 70529088Smarkm &skiprc, 70629088Smarkm "skip reading of ~/.telnetrc file" }, 70729088Smarkm { "binary", 70829088Smarkm "sending and receiving of binary data", 70929088Smarkm togbinary, 71029088Smarkm 0, 71129088Smarkm 0 }, 71229088Smarkm { "inbinary", 71329088Smarkm "receiving of binary data", 71429088Smarkm togrbinary, 71529088Smarkm 0, 71629088Smarkm 0 }, 71729088Smarkm { "outbinary", 71829088Smarkm "sending of binary data", 71929088Smarkm togxbinary, 72029088Smarkm 0, 72129088Smarkm 0 }, 72229088Smarkm { "crlf", 72329088Smarkm "sending carriage returns as telnet <CR><LF>", 72487139Smarkm (int (*)(int))togcrlf, 72529088Smarkm &crlf, 72629088Smarkm 0 }, 72729088Smarkm { "crmod", 72829088Smarkm "mapping of received carriage returns", 72929088Smarkm 0, 73029088Smarkm &crmod, 73129088Smarkm "map carriage return on output" }, 73229088Smarkm { "localchars", 73329088Smarkm "local recognition of certain control characters", 73487139Smarkm (int (*)(int))lclchars, 73529088Smarkm &localchars, 73629088Smarkm "recognize certain control characters" }, 73787139Smarkm { " ", "", NULL, NULL, NULL }, /* empty line */ 73829088Smarkm { "debug", 73929088Smarkm "debugging", 74087139Smarkm (int (*)(int))togdebug, 741114911Smarkm &telnet_debug, 74229088Smarkm "turn on socket level debugging" }, 74329088Smarkm { "netdata", 74429088Smarkm "printing of hexadecimal network data (debugging)", 74529088Smarkm 0, 74629088Smarkm &netdata, 74729088Smarkm "print hexadecimal representation of network traffic" }, 74829088Smarkm { "prettydump", 74929088Smarkm "output of \"netdata\" to user readable format (debugging)", 75029088Smarkm 0, 75129088Smarkm &prettydump, 75229088Smarkm "print user readable output for \"netdata\"" }, 75329088Smarkm { "options", 75429088Smarkm "viewing of options processing (debugging)", 75529088Smarkm 0, 75629088Smarkm &showoptions, 75729088Smarkm "show option processing" }, 75829088Smarkm { "termdata", 75929088Smarkm "(debugging) toggle printing of hexadecimal terminal data", 76029088Smarkm 0, 76129088Smarkm &termdata, 76229088Smarkm "print hexadecimal representation of terminal traffic" }, 76329088Smarkm { "?", 76487139Smarkm NULL, 76587139Smarkm (int (*)(int))togglehelp, 76687139Smarkm NULL, 76787139Smarkm NULL }, 76887139Smarkm { NULL, NULL, NULL, NULL, NULL }, 76929088Smarkm { "help", 77087139Smarkm NULL, 77187139Smarkm (int (*)(int))togglehelp, 77287139Smarkm NULL, 77387139Smarkm NULL }, 77487139Smarkm { NULL, NULL, NULL, NULL, NULL } 77529088Smarkm}; 77629088Smarkm 77787139Smarkmstatic int 77887139Smarkmtogglehelp(void) 77929088Smarkm{ 78029088Smarkm struct togglelist *c; 78129088Smarkm 78229088Smarkm for (c = Togglelist; c->name; c++) { 78329088Smarkm if (c->help) { 78429088Smarkm if (*c->help) 78529088Smarkm printf("%-15s toggle %s\n", c->name, c->help); 78629088Smarkm else 78729088Smarkm printf("\n"); 78829088Smarkm } 78929088Smarkm } 79029088Smarkm printf("\n"); 79129088Smarkm printf("%-15s %s\n", "?", "display help information"); 79229088Smarkm return 0; 79329088Smarkm} 79429088Smarkm 79587139Smarkmstatic void 79687139Smarkmsettogglehelp(int set) 79729088Smarkm{ 79829088Smarkm struct togglelist *c; 79929088Smarkm 80029088Smarkm for (c = Togglelist; c->name; c++) { 80129088Smarkm if (c->help) { 80229088Smarkm if (*c->help) 80329088Smarkm printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 80429088Smarkm c->help); 80529088Smarkm else 80629088Smarkm printf("\n"); 80729088Smarkm } 80829088Smarkm } 80929088Smarkm} 81029088Smarkm 81129088Smarkm#define GETTOGGLE(name) (struct togglelist *) \ 81229088Smarkm genget(name, (char **) Togglelist, sizeof(struct togglelist)) 81329088Smarkm 81487139Smarkmstatic int 81587139Smarkmtoggle(int argc, char *argv[]) 81629088Smarkm{ 81729088Smarkm int retval = 1; 81829088Smarkm char *name; 81929088Smarkm struct togglelist *c; 82029088Smarkm 82129088Smarkm if (argc < 2) { 82229088Smarkm fprintf(stderr, 82329088Smarkm "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 82429088Smarkm return 0; 82529088Smarkm } 82629088Smarkm argc--; 82729088Smarkm argv++; 82829088Smarkm while (argc--) { 82929088Smarkm name = *argv++; 83029088Smarkm c = GETTOGGLE(name); 83187139Smarkm if (Ambiguous((void *)c)) { 83229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 83329088Smarkm name); 83429088Smarkm return 0; 83529088Smarkm } else if (c == 0) { 83629088Smarkm fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 83729088Smarkm name); 83829088Smarkm return 0; 83929088Smarkm } else { 84029088Smarkm if (c->variable) { 84129088Smarkm *c->variable = !*c->variable; /* invert it */ 84229088Smarkm if (c->actionexplanation) { 84329088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 84429088Smarkm c->actionexplanation); 84529088Smarkm } 84629088Smarkm } 84729088Smarkm if (c->handler) { 84829088Smarkm retval &= (*c->handler)(-1); 84929088Smarkm } 85029088Smarkm } 85129088Smarkm } 85229088Smarkm return retval; 85329088Smarkm} 85429088Smarkm 85529088Smarkm/* 85629088Smarkm * The following perform the "set" command. 85729088Smarkm */ 85829088Smarkm 85929088Smarkm#ifdef USE_TERMIO 86087139Smarkmstruct termio new_tc = { 0, 0, 0, 0, {}, 0, 0 }; 86129088Smarkm#endif 86229088Smarkm 86329088Smarkmstruct setlist { 86487139Smarkm const char *name; /* name */ 86587139Smarkm const char *help; /* help information */ 86687139Smarkm void (*handler)(char *); 86729088Smarkm cc_t *charp; /* where it is located at */ 86829088Smarkm}; 86929088Smarkm 87029088Smarkmstatic struct setlist Setlist[] = { 87129088Smarkm#ifdef KLUDGELINEMODE 87287139Smarkm { "echo", "character to toggle local echoing on/off", NULL, &echoc }, 87329088Smarkm#endif 87487139Smarkm { "escape", "character to escape back to telnet command mode", NULL, &escape }, 87529088Smarkm { "rlogin", "rlogin escape character", 0, &rlogin }, 87629088Smarkm { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, 87787139Smarkm { " ", "", NULL, NULL }, 87887139Smarkm { " ", "The following need 'localchars' to be toggled true", NULL, NULL }, 87987139Smarkm { "flushoutput", "character to cause an Abort Output", NULL, termFlushCharp }, 88087139Smarkm { "interrupt", "character to cause an Interrupt Process", NULL, termIntCharp }, 88187139Smarkm { "quit", "character to cause an Abort process", NULL, termQuitCharp }, 88287139Smarkm { "eof", "character to cause an EOF ", NULL, termEofCharp }, 88387139Smarkm { " ", "", NULL, NULL }, 88487139Smarkm { " ", "The following are for local editing in linemode", NULL, NULL }, 88587139Smarkm { "erase", "character to use to erase a character", NULL, termEraseCharp }, 88687139Smarkm { "kill", "character to use to erase a line", NULL, termKillCharp }, 88787139Smarkm { "lnext", "character to use for literal next", NULL, termLiteralNextCharp }, 88887139Smarkm { "susp", "character to cause a Suspend Process", NULL, termSuspCharp }, 88987139Smarkm { "reprint", "character to use for line reprint", NULL, termRprntCharp }, 89087139Smarkm { "worderase", "character to use to erase a word", NULL, termWerasCharp }, 89187139Smarkm { "start", "character to use for XON", NULL, termStartCharp }, 89287139Smarkm { "stop", "character to use for XOFF", NULL, termStopCharp }, 89387139Smarkm { "forw1", "alternate end of line character", NULL, termForw1Charp }, 89487139Smarkm { "forw2", "alternate end of line character", NULL, termForw2Charp }, 89587139Smarkm { "ayt", "alternate AYT character", NULL, termAytCharp }, 896274364Sngie { "baudrate", "set remote baud rate", DoBaudRate, ComPortBaudRate }, 89787139Smarkm { NULL, NULL, NULL, NULL } 89829088Smarkm}; 89929088Smarkm 90087139Smarkmstatic struct setlist * 90187139Smarkmgetset(char *name) 90229088Smarkm{ 90329088Smarkm return (struct setlist *) 90429088Smarkm genget(name, (char **) Setlist, sizeof(struct setlist)); 90529088Smarkm} 90629088Smarkm 90787139Smarkmvoid 90887139Smarkmset_escape_char(char *s) 90929088Smarkm{ 91029088Smarkm if (rlogin != _POSIX_VDISABLE) { 91129088Smarkm rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 91229088Smarkm printf("Telnet rlogin escape character is '%s'.\n", 91329088Smarkm control(rlogin)); 91429088Smarkm } else { 91529088Smarkm escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 91629088Smarkm printf("Telnet escape character is '%s'.\n", control(escape)); 91729088Smarkm } 91829088Smarkm} 91929088Smarkm 92087139Smarkmstatic int 92187139Smarkmsetcmd(int argc, char *argv[]) 92229088Smarkm{ 92329088Smarkm int value; 92429088Smarkm struct setlist *ct; 92529088Smarkm struct togglelist *c; 92629088Smarkm 92729088Smarkm if (argc < 2 || argc > 3) { 92829088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 92929088Smarkm return 0; 93029088Smarkm } 93129088Smarkm if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 93229088Smarkm for (ct = Setlist; ct->name; ct++) 93329088Smarkm printf("%-15s %s\n", ct->name, ct->help); 93429088Smarkm printf("\n"); 93529088Smarkm settogglehelp(1); 93629088Smarkm printf("%-15s %s\n", "?", "display help information"); 93729088Smarkm return 0; 93829088Smarkm } 93929088Smarkm 94029088Smarkm ct = getset(argv[1]); 94129088Smarkm if (ct == 0) { 94229088Smarkm c = GETTOGGLE(argv[1]); 94329088Smarkm if (c == 0) { 94429088Smarkm fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 94529088Smarkm argv[1]); 94629088Smarkm return 0; 94787139Smarkm } else if (Ambiguous((void *)c)) { 94829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 94929088Smarkm argv[1]); 95029088Smarkm return 0; 95129088Smarkm } 95229088Smarkm if (c->variable) { 95329088Smarkm if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 95429088Smarkm *c->variable = 1; 95529088Smarkm else if (strcmp("off", argv[2]) == 0) 95629088Smarkm *c->variable = 0; 95729088Smarkm else { 95829088Smarkm printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 95929088Smarkm return 0; 96029088Smarkm } 96129088Smarkm if (c->actionexplanation) { 96229088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 96329088Smarkm c->actionexplanation); 96429088Smarkm } 96529088Smarkm } 96629088Smarkm if (c->handler) 96729088Smarkm (*c->handler)(1); 96829088Smarkm } else if (argc != 3) { 96929088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 97029088Smarkm return 0; 97187139Smarkm } else if (Ambiguous((void *)ct)) { 97229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 97329088Smarkm argv[1]); 97429088Smarkm return 0; 97529088Smarkm } else if (ct->handler) { 97629088Smarkm (*ct->handler)(argv[2]); 97729088Smarkm printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 97829088Smarkm } else { 97929088Smarkm if (strcmp("off", argv[2])) { 98029088Smarkm value = special(argv[2]); 98129088Smarkm } else { 98229088Smarkm value = _POSIX_VDISABLE; 98329088Smarkm } 98429088Smarkm *(ct->charp) = (cc_t)value; 98529088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 98629088Smarkm } 98729088Smarkm slc_check(); 98829088Smarkm return 1; 98929088Smarkm} 99029088Smarkm 99187139Smarkmstatic int 99287139Smarkmunsetcmd(int argc, char *argv[]) 99329088Smarkm{ 99429088Smarkm struct setlist *ct; 99529088Smarkm struct togglelist *c; 99687139Smarkm char *name; 99729088Smarkm 99829088Smarkm if (argc < 2) { 99929088Smarkm fprintf(stderr, 100029088Smarkm "Need an argument to 'unset' command. 'unset ?' for help.\n"); 100129088Smarkm return 0; 100229088Smarkm } 100329088Smarkm if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 100429088Smarkm for (ct = Setlist; ct->name; ct++) 100529088Smarkm printf("%-15s %s\n", ct->name, ct->help); 100629088Smarkm printf("\n"); 100729088Smarkm settogglehelp(0); 100829088Smarkm printf("%-15s %s\n", "?", "display help information"); 100929088Smarkm return 0; 101029088Smarkm } 101129088Smarkm 101229088Smarkm argc--; 101329088Smarkm argv++; 101429088Smarkm while (argc--) { 101529088Smarkm name = *argv++; 101629088Smarkm ct = getset(name); 101729088Smarkm if (ct == 0) { 101829088Smarkm c = GETTOGGLE(name); 101929088Smarkm if (c == 0) { 102029088Smarkm fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 102129088Smarkm name); 102229088Smarkm return 0; 102387139Smarkm } else if (Ambiguous((void *)c)) { 102429088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 102529088Smarkm name); 102629088Smarkm return 0; 102729088Smarkm } 102829088Smarkm if (c->variable) { 102929088Smarkm *c->variable = 0; 103029088Smarkm if (c->actionexplanation) { 103129088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 103229088Smarkm c->actionexplanation); 103329088Smarkm } 103429088Smarkm } 103529088Smarkm if (c->handler) 103629088Smarkm (*c->handler)(0); 103787139Smarkm } else if (Ambiguous((void *)ct)) { 103829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 103929088Smarkm name); 104029088Smarkm return 0; 104129088Smarkm } else if (ct->handler) { 104229088Smarkm (*ct->handler)(0); 104329088Smarkm printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 104429088Smarkm } else { 104529088Smarkm *(ct->charp) = _POSIX_VDISABLE; 104629088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 104729088Smarkm } 104829088Smarkm } 104929088Smarkm return 1; 105029088Smarkm} 105129088Smarkm 105229088Smarkm/* 105329088Smarkm * The following are the data structures and routines for the 105429088Smarkm * 'mode' command. 105529088Smarkm */ 105629088Smarkm#ifdef KLUDGELINEMODE 105729088Smarkmextern int kludgelinemode; 105829088Smarkm 105987139Smarkmstatic int 106087139Smarkmdokludgemode(void) 106129088Smarkm{ 106229088Smarkm kludgelinemode = 1; 106329088Smarkm send_wont(TELOPT_LINEMODE, 1); 106429088Smarkm send_dont(TELOPT_SGA, 1); 106529088Smarkm send_dont(TELOPT_ECHO, 1); 106649861Snsayer return 1; 106729088Smarkm} 106829088Smarkm#endif 106929088Smarkm 107087139Smarkmstatic int 107187139Smarkmdolinemode(void) 107229088Smarkm{ 107329088Smarkm#ifdef KLUDGELINEMODE 107429088Smarkm if (kludgelinemode) 107529088Smarkm send_dont(TELOPT_SGA, 1); 107629088Smarkm#endif 107729088Smarkm send_will(TELOPT_LINEMODE, 1); 107829088Smarkm send_dont(TELOPT_ECHO, 1); 107929088Smarkm return 1; 108029088Smarkm} 108129088Smarkm 108287139Smarkmstatic int 108387139Smarkmdocharmode(void) 108429088Smarkm{ 108529088Smarkm#ifdef KLUDGELINEMODE 108629088Smarkm if (kludgelinemode) 108729088Smarkm send_do(TELOPT_SGA, 1); 108829088Smarkm else 108929088Smarkm#endif 109029088Smarkm send_wont(TELOPT_LINEMODE, 1); 109129088Smarkm send_do(TELOPT_ECHO, 1); 109229088Smarkm return 1; 109329088Smarkm} 109429088Smarkm 109587139Smarkmstatic int 109687139Smarkmdolmmode(int bit, int on) 109729088Smarkm{ 109829088Smarkm unsigned char c; 109929088Smarkm extern int linemode; 110029088Smarkm 110129088Smarkm if (my_want_state_is_wont(TELOPT_LINEMODE)) { 110229088Smarkm printf("?Need to have LINEMODE option enabled first.\n"); 110329088Smarkm printf("'mode ?' for help.\n"); 110429088Smarkm return 0; 110529088Smarkm } 110629088Smarkm 110729088Smarkm if (on) 110829088Smarkm c = (linemode | bit); 110929088Smarkm else 111029088Smarkm c = (linemode & ~bit); 111129088Smarkm lm_mode(&c, 1, 1); 111229088Smarkm return 1; 111329088Smarkm} 111429088Smarkm 111587139Smarkmstatic int 111687139Smarkmsetmod(int bit) 111729088Smarkm{ 111829088Smarkm return dolmmode(bit, 1); 111929088Smarkm} 112029088Smarkm 112187139Smarkmstatic int 112287139Smarkmclearmode(int bit) 112329088Smarkm{ 112429088Smarkm return dolmmode(bit, 0); 112529088Smarkm} 112629088Smarkm 112729088Smarkmstruct modelist { 112887139Smarkm const char *name; /* command name */ 112987139Smarkm const char *help; /* help string */ 113087139Smarkm int (*handler)(int);/* routine which executes command */ 113129088Smarkm int needconnect; /* Do we need to be connected to execute? */ 113229088Smarkm int arg1; 113329088Smarkm}; 113429088Smarkm 113529088Smarkmstatic struct modelist ModeList[] = { 113687139Smarkm { "character", "Disable LINEMODE option", (int (*)(int))docharmode, 1, 0 }, 113729088Smarkm#ifdef KLUDGELINEMODE 113887139Smarkm { "", "(or disable obsolete line-by-line mode)", NULL, 0, 0 }, 113929088Smarkm#endif 114087139Smarkm { "line", "Enable LINEMODE option", (int (*)(int))dolinemode, 1, 0 }, 114129088Smarkm#ifdef KLUDGELINEMODE 114287139Smarkm { "", "(or enable obsolete line-by-line mode)", NULL, 0, 0 }, 114329088Smarkm#endif 114487139Smarkm { "", "", NULL, 0, 0 }, 114587139Smarkm { "", "These require the LINEMODE option to be enabled", NULL, 0, 0 }, 114629181Smarkm { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, 114729181Smarkm { "+isig", 0, setmod, 1, MODE_TRAPSIG }, 114829088Smarkm { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 114929181Smarkm { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, 115029181Smarkm { "+edit", 0, setmod, 1, MODE_EDIT }, 115129088Smarkm { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 115229181Smarkm { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, 115329181Smarkm { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, 115429088Smarkm { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 115529181Smarkm { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, 115629181Smarkm { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, 115729088Smarkm { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 115887139Smarkm { "help", 0, (int (*)(int))modehelp, 0, 0 }, 115929088Smarkm#ifdef KLUDGELINEMODE 116087139Smarkm { "kludgeline", 0, (int (*)(int))dokludgemode, 1, 0 }, 116129088Smarkm#endif 116287139Smarkm { "", "", NULL, 0, 0 }, 116387139Smarkm { "?", "Print help information", (int (*)(int))modehelp, 0, 0 }, 116487139Smarkm { NULL, NULL, NULL, 0, 0 }, 116529088Smarkm}; 116629088Smarkm 116729088Smarkm 116887139Smarkmstatic int 116987139Smarkmmodehelp(void) 117029088Smarkm{ 117129088Smarkm struct modelist *mt; 117229088Smarkm 117329088Smarkm printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 117429088Smarkm for (mt = ModeList; mt->name; mt++) { 117529088Smarkm if (mt->help) { 117629088Smarkm if (*mt->help) 117729088Smarkm printf("%-15s %s\n", mt->name, mt->help); 117829088Smarkm else 117929088Smarkm printf("\n"); 118029088Smarkm } 118129088Smarkm } 118229088Smarkm return 0; 118329088Smarkm} 118429088Smarkm 118529088Smarkm#define GETMODECMD(name) (struct modelist *) \ 118629088Smarkm genget(name, (char **) ModeList, sizeof(struct modelist)) 118729088Smarkm 118887139Smarkmstatic int 118987139Smarkmmodecmd(int argc, char *argv[]) 119029088Smarkm{ 119129088Smarkm struct modelist *mt; 119229088Smarkm 119329088Smarkm if (argc != 2) { 119429088Smarkm printf("'mode' command requires an argument\n"); 119529088Smarkm printf("'mode ?' for help.\n"); 119629088Smarkm } else if ((mt = GETMODECMD(argv[1])) == 0) { 119729088Smarkm fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 119887139Smarkm } else if (Ambiguous((void *)mt)) { 119929088Smarkm fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 120029088Smarkm } else if (mt->needconnect && !connected) { 120129088Smarkm printf("?Need to be connected first.\n"); 120229088Smarkm printf("'mode ?' for help.\n"); 120329088Smarkm } else if (mt->handler) { 120429088Smarkm return (*mt->handler)(mt->arg1); 120529088Smarkm } 120629088Smarkm return 0; 120729088Smarkm} 120829088Smarkm 120929088Smarkm/* 121029088Smarkm * The following data structures and routines implement the 121129088Smarkm * "display" command. 121229088Smarkm */ 121329088Smarkm 121487139Smarkmstatic int 121587139Smarkmdisplay(int argc, char *argv[]) 121629088Smarkm{ 121729088Smarkm struct togglelist *tl; 121829088Smarkm struct setlist *sl; 121929088Smarkm 122029088Smarkm#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 122129088Smarkm if (*tl->variable) { \ 122229088Smarkm printf("will"); \ 122329088Smarkm } else { \ 122429088Smarkm printf("won't"); \ 122529088Smarkm } \ 122629088Smarkm printf(" %s.\n", tl->actionexplanation); \ 122729088Smarkm } 122829088Smarkm 122929088Smarkm#define doset(sl) if (sl->name && *sl->name != ' ') { \ 123029088Smarkm if (sl->handler == 0) \ 123129088Smarkm printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 123229088Smarkm else \ 123329088Smarkm printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 123429088Smarkm } 123529088Smarkm 123629088Smarkm if (argc == 1) { 123729088Smarkm for (tl = Togglelist; tl->name; tl++) { 123829088Smarkm dotog(tl); 123929088Smarkm } 124029088Smarkm printf("\n"); 124129088Smarkm for (sl = Setlist; sl->name; sl++) { 124229088Smarkm doset(sl); 124329088Smarkm } 124429088Smarkm } else { 124529088Smarkm int i; 124629088Smarkm 124729088Smarkm for (i = 1; i < argc; i++) { 124829088Smarkm sl = getset(argv[i]); 124929088Smarkm tl = GETTOGGLE(argv[i]); 125087139Smarkm if (Ambiguous((void *)sl) || Ambiguous((void *)tl)) { 125129088Smarkm printf("?Ambiguous argument '%s'.\n", argv[i]); 125229088Smarkm return 0; 125329088Smarkm } else if (!sl && !tl) { 125429088Smarkm printf("?Unknown argument '%s'.\n", argv[i]); 125529088Smarkm return 0; 125629088Smarkm } else { 125729088Smarkm if (tl) { 125829088Smarkm dotog(tl); 125929088Smarkm } 126029088Smarkm if (sl) { 126129088Smarkm doset(sl); 126229088Smarkm } 126329088Smarkm } 126429088Smarkm } 126529088Smarkm } 126629088Smarkm/*@*/optionstatus(); 126729088Smarkm#ifdef ENCRYPTION 126829088Smarkm EncryptStatus(); 126929088Smarkm#endif /* ENCRYPTION */ 127029088Smarkm return 1; 127129088Smarkm#undef doset 127229088Smarkm#undef dotog 127329088Smarkm} 127429088Smarkm 127529088Smarkm/* 127629088Smarkm * The following are the data structures, and many of the routines, 127729088Smarkm * relating to command processing. 127829088Smarkm */ 127929088Smarkm 128029088Smarkm/* 128129088Smarkm * Set the escape character. 128229088Smarkm */ 128387139Smarkmstatic int 128487139Smarkmsetescape(int argc, char *argv[]) 128529088Smarkm{ 128687139Smarkm char *arg; 128729088Smarkm char buf[50]; 128829088Smarkm 128929088Smarkm printf( 129029088Smarkm "Deprecated usage - please use 'set escape%s%s' in the future.\n", 129129088Smarkm (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 129229088Smarkm if (argc > 2) 129329088Smarkm arg = argv[1]; 129429088Smarkm else { 129529088Smarkm printf("new escape character: "); 129629088Smarkm (void) fgets(buf, sizeof(buf), stdin); 129729088Smarkm arg = buf; 129829088Smarkm } 129929088Smarkm if (arg[0] != '\0') 130029088Smarkm escape = arg[0]; 130129088Smarkm (void) fflush(stdout); 130229088Smarkm return 1; 130329088Smarkm} 130429088Smarkm 130587139Smarkmstatic int 130687139Smarkmtogcrmod(void) 130729088Smarkm{ 130829088Smarkm crmod = !crmod; 130929088Smarkm printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 131029088Smarkm printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 131129088Smarkm (void) fflush(stdout); 131229088Smarkm return 1; 131329088Smarkm} 131429088Smarkm 131587139Smarkmstatic int 131687139Smarkmsuspend(void) 131729088Smarkm{ 131829088Smarkm#ifdef SIGTSTP 131929088Smarkm setcommandmode(); 132029088Smarkm { 132187139Smarkm long oldrows, oldcols, newrows, newcols, err_; 132229088Smarkm 132387139Smarkm err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 132429088Smarkm (void) kill(0, SIGTSTP); 132529088Smarkm /* 132629088Smarkm * If we didn't get the window size before the SUSPEND, but we 132729088Smarkm * can get them now (?), then send the NAWS to make sure that 132829088Smarkm * we are set up for the right window size. 132929088Smarkm */ 133029088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 133187139Smarkm (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { 133229088Smarkm sendnaws(); 133329088Smarkm } 133429088Smarkm } 133529088Smarkm /* reget parameters in case they were changed */ 133629088Smarkm TerminalSaveState(); 133729088Smarkm setconnmode(0); 133829088Smarkm#else 133929088Smarkm printf("Suspend is not supported. Try the '!' command instead\n"); 134029088Smarkm#endif 134129088Smarkm return 1; 134229088Smarkm} 134329088Smarkm 134487139Smarkmstatic int 134587139Smarkmshell(int argc, char *argv[] __unused) 134629088Smarkm{ 134787139Smarkm long oldrows, oldcols, newrows, newcols, err_; 134829088Smarkm 134929088Smarkm setcommandmode(); 135029088Smarkm 135187139Smarkm err_ = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 135229088Smarkm switch(vfork()) { 135329088Smarkm case -1: 135429088Smarkm perror("Fork failed\n"); 135529088Smarkm break; 135629088Smarkm 135729088Smarkm case 0: 135829088Smarkm { 135929088Smarkm /* 136029088Smarkm * Fire up the shell in the child. 136129088Smarkm */ 136287139Smarkm const char *shellp, *shellname; 136329088Smarkm 136429088Smarkm shellp = getenv("SHELL"); 136529088Smarkm if (shellp == NULL) 136629088Smarkm shellp = "/bin/sh"; 136729088Smarkm if ((shellname = strrchr(shellp, '/')) == 0) 136829088Smarkm shellname = shellp; 136929088Smarkm else 137029088Smarkm shellname++; 137129088Smarkm if (argc > 1) 137281965Smarkm execl(shellp, shellname, "-c", &saveline[1], (char *)0); 137329088Smarkm else 137481965Smarkm execl(shellp, shellname, (char *)0); 137529088Smarkm perror("Execl"); 137629088Smarkm _exit(1); 137729088Smarkm } 137829088Smarkm default: 137929088Smarkm (void)wait((int *)0); /* Wait for the shell to complete */ 138029088Smarkm 138129088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 138287139Smarkm (err_ || ((oldrows != newrows) || (oldcols != newcols)))) { 138329088Smarkm sendnaws(); 138429088Smarkm } 138529088Smarkm break; 138629088Smarkm } 138729088Smarkm return 1; 138829088Smarkm} 138929088Smarkm 139087139Smarkmstatic int 139187139Smarkmbye(int argc, char *argv[]) 139229088Smarkm{ 139329088Smarkm extern int resettermname; 139429088Smarkm 139529088Smarkm if (connected) { 139629088Smarkm (void) shutdown(net, 2); 139729088Smarkm printf("Connection closed.\n"); 139829088Smarkm (void) NetClose(net); 139929088Smarkm connected = 0; 140029088Smarkm resettermname = 1; 140187139Smarkm#ifdef AUTHENTICATION 140287139Smarkm#ifdef ENCRYPTION 140329088Smarkm auth_encrypt_connect(connected); 140487139Smarkm#endif 140587139Smarkm#endif 140629088Smarkm /* reset options */ 140729088Smarkm tninit(); 140829088Smarkm } 140929088Smarkm if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 141029088Smarkm longjmp(toplevel, 1); 141129088Smarkm /* NOTREACHED */ 141229088Smarkm } 141329088Smarkm return 1; /* Keep lint, etc., happy */ 141429088Smarkm} 141529088Smarkm 141687139Smarkmvoid 141787139Smarkmquit(void) 141829088Smarkm{ 141929088Smarkm (void) call(bye, "bye", "fromquit", 0); 142029088Smarkm Exit(0); 142129088Smarkm} 142229088Smarkm 142387139Smarkmstatic int 142487139Smarkmlogout(void) 142529088Smarkm{ 142629088Smarkm send_do(TELOPT_LOGOUT, 1); 142729088Smarkm (void) netflush(); 142829088Smarkm return 1; 142929088Smarkm} 143029088Smarkm 143129088Smarkm 143229088Smarkm/* 143329088Smarkm * The SLC command. 143429088Smarkm */ 143529088Smarkm 143629088Smarkmstruct slclist { 143787139Smarkm const char *name; 143887139Smarkm const char *help; 143987139Smarkm void (*handler)(int); 144029088Smarkm int arg; 144129088Smarkm}; 144229088Smarkm 144387139Smarkmstatic void slc_help(void); 144429088Smarkm 144529088Smarkmstruct slclist SlcList[] = { 144629088Smarkm { "export", "Use local special character definitions", 144787139Smarkm (void (*)(int))slc_mode_export, 0 }, 144829088Smarkm { "import", "Use remote special character definitions", 144929088Smarkm slc_mode_import, 1 }, 145029088Smarkm { "check", "Verify remote special character definitions", 145129088Smarkm slc_mode_import, 0 }, 145287139Smarkm { "help", NULL, (void (*)(int))slc_help, 0 }, 145387139Smarkm { "?", "Print help information", (void (*)(int))slc_help, 0 }, 145487139Smarkm { NULL, NULL, NULL, 0 }, 145529088Smarkm}; 145629088Smarkm 145787139Smarkmstatic void 145887139Smarkmslc_help(void) 145929088Smarkm{ 146029088Smarkm struct slclist *c; 146129088Smarkm 146229088Smarkm for (c = SlcList; c->name; c++) { 146329088Smarkm if (c->help) { 146429088Smarkm if (*c->help) 146529088Smarkm printf("%-15s %s\n", c->name, c->help); 146629088Smarkm else 146729088Smarkm printf("\n"); 146829088Smarkm } 146929088Smarkm } 147029088Smarkm} 147129088Smarkm 147287139Smarkmstatic struct slclist * 147387139Smarkmgetslc(char *name) 147429088Smarkm{ 147529088Smarkm return (struct slclist *) 147629088Smarkm genget(name, (char **) SlcList, sizeof(struct slclist)); 147729088Smarkm} 147829088Smarkm 147987139Smarkmstatic int 148087139Smarkmslccmd(int argc, char *argv[]) 148129088Smarkm{ 148229088Smarkm struct slclist *c; 148329088Smarkm 148429088Smarkm if (argc != 2) { 148529088Smarkm fprintf(stderr, 148629088Smarkm "Need an argument to 'slc' command. 'slc ?' for help.\n"); 148729088Smarkm return 0; 148829088Smarkm } 148929088Smarkm c = getslc(argv[1]); 149029088Smarkm if (c == 0) { 149129088Smarkm fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 149229088Smarkm argv[1]); 149329088Smarkm return 0; 149429088Smarkm } 149587139Smarkm if (Ambiguous((void *)c)) { 149629088Smarkm fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 149729088Smarkm argv[1]); 149829088Smarkm return 0; 149929088Smarkm } 150029088Smarkm (*c->handler)(c->arg); 150129088Smarkm slcstate(); 150229088Smarkm return 1; 150329088Smarkm} 150429088Smarkm 150529088Smarkm/* 150629088Smarkm * The ENVIRON command. 150729088Smarkm */ 150829088Smarkm 150929088Smarkmstruct envlist { 151087139Smarkm const char *name; 151187139Smarkm const char *help; 151287139Smarkm void (*handler)(unsigned char *, unsigned char *); 151329088Smarkm int narg; 151429088Smarkm}; 151529088Smarkm 151629088Smarkmextern struct env_lst * 151787155Smarkm env_define(const unsigned char *, unsigned char *); 151829088Smarkmextern void 151987155Smarkm env_undefine(unsigned char *), 152087155Smarkm env_export(const unsigned char *), 152187155Smarkm env_unexport(const unsigned char *), 152287155Smarkm env_send(unsigned char *), 152329088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 152487155Smarkm env_varval(unsigned char *), 152529088Smarkm#endif 152687155Smarkm env_list(void); 152729088Smarkmstatic void 152887155Smarkm env_help(void); 152929088Smarkm 153029088Smarkmstruct envlist EnvList[] = { 153129088Smarkm { "define", "Define an environment variable", 153287139Smarkm (void (*)(unsigned char *, unsigned char *))env_define, 2 }, 153329088Smarkm { "undefine", "Undefine an environment variable", 153487139Smarkm (void (*)(unsigned char *, unsigned char *))env_undefine, 1 }, 153529088Smarkm { "export", "Mark an environment variable for automatic export", 153687139Smarkm (void (*)(unsigned char *, unsigned char *))env_export, 1 }, 153729088Smarkm { "unexport", "Don't mark an environment variable for automatic export", 153887139Smarkm (void (*)(unsigned char *, unsigned char *))env_unexport, 1 }, 153987139Smarkm { "send", "Send an environment variable", (void (*)(unsigned char *, unsigned char *))env_send, 1 }, 154029088Smarkm { "list", "List the current environment variables", 154187139Smarkm (void (*)(unsigned char *, unsigned char *))env_list, 0 }, 154229088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 154329088Smarkm { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 154487139Smarkm (void (*)(unsigned char *, unsigned char *))env_varval, 1 }, 154529088Smarkm#endif 154687139Smarkm { "help", NULL, (void (*)(unsigned char *, unsigned char *))env_help, 0 }, 154787139Smarkm { "?", "Print help information", (void (*)(unsigned char *, unsigned char *))env_help, 0 }, 154887139Smarkm { NULL, NULL, NULL, 0 }, 154929088Smarkm}; 155029088Smarkm 155187139Smarkmstatic void 155287139Smarkmenv_help(void) 155329088Smarkm{ 155429088Smarkm struct envlist *c; 155529088Smarkm 155629088Smarkm for (c = EnvList; c->name; c++) { 155729088Smarkm if (c->help) { 155829088Smarkm if (*c->help) 155929088Smarkm printf("%-15s %s\n", c->name, c->help); 156029088Smarkm else 156129088Smarkm printf("\n"); 156229088Smarkm } 156329088Smarkm } 156429088Smarkm} 156529088Smarkm 156687139Smarkmstatic struct envlist * 156787139Smarkmgetenvcmd(char *name) 156829088Smarkm{ 156929088Smarkm return (struct envlist *) 157029088Smarkm genget(name, (char **) EnvList, sizeof(struct envlist)); 157129088Smarkm} 157229088Smarkm 157387139Smarkmstatic int 157487139Smarkmenv_cmd(int argc, char *argv[]) 157529088Smarkm{ 157629088Smarkm struct envlist *c; 157729088Smarkm 157829088Smarkm if (argc < 2) { 157929088Smarkm fprintf(stderr, 158029088Smarkm "Need an argument to 'environ' command. 'environ ?' for help.\n"); 158129088Smarkm return 0; 158229088Smarkm } 158329088Smarkm c = getenvcmd(argv[1]); 158429088Smarkm if (c == 0) { 158529088Smarkm fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 158629088Smarkm argv[1]); 158729088Smarkm return 0; 158829088Smarkm } 158987139Smarkm if (Ambiguous((void *)c)) { 159029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 159129088Smarkm argv[1]); 159229088Smarkm return 0; 159329088Smarkm } 159429088Smarkm if (c->narg + 2 != argc) { 159529088Smarkm fprintf(stderr, 159629088Smarkm "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 159729088Smarkm c->narg < argc + 2 ? "only " : "", 159829088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 159929088Smarkm return 0; 160029088Smarkm } 160129088Smarkm (*c->handler)(argv[2], argv[3]); 160229088Smarkm return 1; 160329088Smarkm} 160429088Smarkm 160529088Smarkmstruct env_lst { 160629088Smarkm struct env_lst *next; /* pointer to next structure */ 160729088Smarkm struct env_lst *prev; /* pointer to previous structure */ 160829088Smarkm unsigned char *var; /* pointer to variable name */ 160929088Smarkm unsigned char *value; /* pointer to variable value */ 161029088Smarkm int export; /* 1 -> export with default list of variables */ 161129088Smarkm int welldefined; /* A well defined variable */ 161229088Smarkm}; 161329088Smarkm 161429088Smarkmstruct env_lst envlisthead; 161529088Smarkm 161687139Smarkmstatic struct env_lst * 161787139Smarkmenv_find(const unsigned char *var) 161829088Smarkm{ 161987139Smarkm struct env_lst *ep; 162029088Smarkm 162129088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 162287139Smarkm if (strcmp(ep->var, var) == 0) 162329088Smarkm return(ep); 162429088Smarkm } 162529088Smarkm return(NULL); 162629088Smarkm} 162729088Smarkm 162887139Smarkmvoid 162987139Smarkmenv_init(void) 163029088Smarkm{ 163129088Smarkm extern char **environ; 163287139Smarkm char **epp, *cp; 163387139Smarkm struct env_lst *ep; 163429088Smarkm 163529088Smarkm for (epp = environ; *epp; epp++) { 163629181Smarkm if ((cp = strchr(*epp, '='))) { 163729088Smarkm *cp = '\0'; 163829088Smarkm ep = env_define((unsigned char *)*epp, 163929088Smarkm (unsigned char *)cp+1); 164029088Smarkm ep->export = 0; 164129088Smarkm *cp = '='; 164229088Smarkm } 164329088Smarkm } 164429088Smarkm /* 164529088Smarkm * Special case for DISPLAY variable. If it is ":0.0" or 164629088Smarkm * "unix:0.0", we have to get rid of "unix" and insert our 164729088Smarkm * hostname. 164829088Smarkm */ 164929088Smarkm if ((ep = env_find("DISPLAY")) 165029088Smarkm && ((*ep->value == ':') 165129088Smarkm || (strncmp((char *)ep->value, "unix:", 5) == 0))) { 165229088Smarkm char hbuf[256+1]; 165329088Smarkm char *cp2 = strchr((char *)ep->value, ':'); 165429088Smarkm 1655350140Sphilip gethostname(hbuf, sizeof(hbuf)); 1656350140Sphilip hbuf[sizeof(hbuf)-1] = '\0'; 1657350901Semaste asprintf(&cp, "%s%s", hbuf, cp2); 1658350140Sphilip assert(cp != NULL); 165929088Smarkm free(ep->value); 166029088Smarkm ep->value = (unsigned char *)cp; 166129088Smarkm } 166229088Smarkm /* 166329088Smarkm * If USER is not defined, but LOGNAME is, then add 166429088Smarkm * USER with the value from LOGNAME. By default, we 166529088Smarkm * don't export the USER variable. 166629088Smarkm */ 166729088Smarkm if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { 166887139Smarkm env_define("USER", ep->value); 166987139Smarkm env_unexport("USER"); 167029088Smarkm } 167187139Smarkm env_export("DISPLAY"); 167287139Smarkm env_export("PRINTER"); 167329088Smarkm} 167429088Smarkm 167587139Smarkmstruct env_lst * 167687139Smarkmenv_define(const unsigned char *var, unsigned char *value) 167729088Smarkm{ 167887139Smarkm struct env_lst *ep; 167929088Smarkm 168029181Smarkm if ((ep = env_find(var))) { 168129088Smarkm if (ep->var) 168229088Smarkm free(ep->var); 168329088Smarkm if (ep->value) 168429088Smarkm free(ep->value); 168529088Smarkm } else { 168629088Smarkm ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 168729088Smarkm ep->next = envlisthead.next; 168829088Smarkm envlisthead.next = ep; 168929088Smarkm ep->prev = &envlisthead; 169029088Smarkm if (ep->next) 169129088Smarkm ep->next->prev = ep; 169229088Smarkm } 169329088Smarkm ep->welldefined = opt_welldefined(var); 169429088Smarkm ep->export = 1; 169587139Smarkm ep->var = strdup(var); 169687139Smarkm ep->value = strdup(value); 169729088Smarkm return(ep); 169829088Smarkm} 169929088Smarkm 170087139Smarkmvoid 170187139Smarkmenv_undefine(unsigned char *var) 170229088Smarkm{ 170387139Smarkm struct env_lst *ep; 170429088Smarkm 170529181Smarkm if ((ep = env_find(var))) { 170629088Smarkm ep->prev->next = ep->next; 170729088Smarkm if (ep->next) 170829088Smarkm ep->next->prev = ep->prev; 170929088Smarkm if (ep->var) 171029088Smarkm free(ep->var); 171129088Smarkm if (ep->value) 171229088Smarkm free(ep->value); 171329088Smarkm free(ep); 171429088Smarkm } 171529088Smarkm} 171629088Smarkm 171787139Smarkmvoid 171887139Smarkmenv_export(const unsigned char *var) 171929088Smarkm{ 172087139Smarkm struct env_lst *ep; 172129088Smarkm 172229181Smarkm if ((ep = env_find(var))) 172329088Smarkm ep->export = 1; 172429088Smarkm} 172529088Smarkm 172687139Smarkmvoid 172787139Smarkmenv_unexport(const unsigned char *var) 172829088Smarkm{ 172987139Smarkm struct env_lst *ep; 173029088Smarkm 173129181Smarkm if ((ep = env_find(var))) 173229088Smarkm ep->export = 0; 173329088Smarkm} 173429088Smarkm 173587139Smarkmvoid 173687139Smarkmenv_send(unsigned char *var) 173729088Smarkm{ 173887139Smarkm struct env_lst *ep; 173929088Smarkm 174029088Smarkm if (my_state_is_wont(TELOPT_NEW_ENVIRON) 174129088Smarkm#ifdef OLD_ENVIRON 174229088Smarkm && my_state_is_wont(TELOPT_OLD_ENVIRON) 174329088Smarkm#endif 174429088Smarkm ) { 174529088Smarkm fprintf(stderr, 174629088Smarkm "Cannot send '%s': Telnet ENVIRON option not enabled\n", 174729088Smarkm var); 174829088Smarkm return; 174929088Smarkm } 175029088Smarkm ep = env_find(var); 175129088Smarkm if (ep == 0) { 175229088Smarkm fprintf(stderr, "Cannot send '%s': variable not defined\n", 175329088Smarkm var); 175429088Smarkm return; 175529088Smarkm } 175629088Smarkm env_opt_start_info(); 175729088Smarkm env_opt_add(ep->var); 175829088Smarkm env_opt_end(0); 175929088Smarkm} 176029088Smarkm 176187139Smarkmvoid 176287139Smarkmenv_list(void) 176329088Smarkm{ 176487139Smarkm struct env_lst *ep; 176529088Smarkm 176629088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 176729088Smarkm printf("%c %-20s %s\n", ep->export ? '*' : ' ', 176829088Smarkm ep->var, ep->value); 176929088Smarkm } 177029088Smarkm} 177129088Smarkm 177287139Smarkmunsigned char * 177387139Smarkmenv_default(int init, int welldefined) 177429088Smarkm{ 177529088Smarkm static struct env_lst *nep = NULL; 177629088Smarkm 177729088Smarkm if (init) { 177829088Smarkm nep = &envlisthead; 177929181Smarkm return(NULL); 178029088Smarkm } 178129088Smarkm if (nep) { 178229181Smarkm while ((nep = nep->next)) { 178329088Smarkm if (nep->export && (nep->welldefined == welldefined)) 178429088Smarkm return(nep->var); 178529088Smarkm } 178629088Smarkm } 178729088Smarkm return(NULL); 178829088Smarkm} 178929088Smarkm 179087139Smarkmunsigned char * 179187139Smarkmenv_getvalue(const unsigned char *var) 179229088Smarkm{ 179387139Smarkm struct env_lst *ep; 179429088Smarkm 179529181Smarkm if ((ep = env_find(var))) 179629088Smarkm return(ep->value); 179729088Smarkm return(NULL); 179829088Smarkm} 179929088Smarkm 180029088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 180187139Smarkmvoid 180287139Smarkmenv_varval(unsigned char *what) 180329088Smarkm{ 180429088Smarkm extern int old_env_var, old_env_value, env_auto; 180529088Smarkm int len = strlen((char *)what); 180629088Smarkm 180729088Smarkm if (len == 0) 180829088Smarkm goto unknown; 180929088Smarkm 181029088Smarkm if (strncasecmp((char *)what, "status", len) == 0) { 181129088Smarkm if (env_auto) 181229088Smarkm printf("%s%s", "VAR and VALUE are/will be ", 181329088Smarkm "determined automatically\n"); 181429088Smarkm if (old_env_var == OLD_ENV_VAR) 181529088Smarkm printf("VAR and VALUE set to correct definitions\n"); 181629088Smarkm else 181729088Smarkm printf("VAR and VALUE definitions are reversed\n"); 181829088Smarkm } else if (strncasecmp((char *)what, "auto", len) == 0) { 181929088Smarkm env_auto = 1; 182029088Smarkm old_env_var = OLD_ENV_VALUE; 182129088Smarkm old_env_value = OLD_ENV_VAR; 182229088Smarkm } else if (strncasecmp((char *)what, "right", len) == 0) { 182329088Smarkm env_auto = 0; 182429088Smarkm old_env_var = OLD_ENV_VAR; 182529088Smarkm old_env_value = OLD_ENV_VALUE; 182629088Smarkm } else if (strncasecmp((char *)what, "wrong", len) == 0) { 182729088Smarkm env_auto = 0; 182829088Smarkm old_env_var = OLD_ENV_VALUE; 182929088Smarkm old_env_value = OLD_ENV_VAR; 183029088Smarkm } else { 183129088Smarkmunknown: 183229088Smarkm printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); 183329088Smarkm } 183429088Smarkm} 183529088Smarkm#endif 183629088Smarkm 183787139Smarkm#ifdef AUTHENTICATION 183829088Smarkm/* 183929088Smarkm * The AUTHENTICATE command. 184029088Smarkm */ 184129088Smarkm 184229088Smarkmstruct authlist { 184387139Smarkm const char *name; 184487139Smarkm const char *help; 184587139Smarkm int (*handler)(char *); 184629088Smarkm int narg; 184729088Smarkm}; 184829088Smarkm 184929088Smarkmextern int 185087155Smarkm auth_enable(char *), 185187155Smarkm auth_disable(char *), 185287155Smarkm auth_status(void); 185329088Smarkmstatic int 185487155Smarkm auth_help(void); 185529088Smarkm 185629088Smarkmstruct authlist AuthList[] = { 185729088Smarkm { "status", "Display current status of authentication information", 185887139Smarkm (int (*)(char *))auth_status, 0 }, 185929088Smarkm { "disable", "Disable an authentication type ('auth disable ?' for more)", 186029088Smarkm auth_disable, 1 }, 186129088Smarkm { "enable", "Enable an authentication type ('auth enable ?' for more)", 186229088Smarkm auth_enable, 1 }, 186387139Smarkm { "help", NULL, (int (*)(char *))auth_help, 0 }, 186487139Smarkm { "?", "Print help information", (int (*)(char *))auth_help, 0 }, 186587139Smarkm { NULL, NULL, NULL, 0 }, 186629088Smarkm}; 186729088Smarkm 186887139Smarkmstatic int 186987139Smarkmauth_help(void) 187029088Smarkm{ 187129088Smarkm struct authlist *c; 187229088Smarkm 187329088Smarkm for (c = AuthList; c->name; c++) { 187429088Smarkm if (c->help) { 187529088Smarkm if (*c->help) 187629088Smarkm printf("%-15s %s\n", c->name, c->help); 187729088Smarkm else 187829088Smarkm printf("\n"); 187929088Smarkm } 188029088Smarkm } 188129088Smarkm return 0; 188229088Smarkm} 188329088Smarkm 188487139Smarkmint 188587139Smarkmauth_cmd(int argc, char *argv[]) 188629088Smarkm{ 188729088Smarkm struct authlist *c; 188829088Smarkm 188929088Smarkm if (argc < 2) { 189029088Smarkm fprintf(stderr, 189129088Smarkm "Need an argument to 'auth' command. 'auth ?' for help.\n"); 189229088Smarkm return 0; 189329088Smarkm } 189429088Smarkm 189529088Smarkm c = (struct authlist *) 189629088Smarkm genget(argv[1], (char **) AuthList, sizeof(struct authlist)); 189729088Smarkm if (c == 0) { 189829088Smarkm fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", 189929088Smarkm argv[1]); 190029088Smarkm return 0; 190129088Smarkm } 190287139Smarkm if (Ambiguous((void *)c)) { 190329088Smarkm fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", 190429088Smarkm argv[1]); 190529088Smarkm return 0; 190629088Smarkm } 190729088Smarkm if (c->narg + 2 != argc) { 190829088Smarkm fprintf(stderr, 190929088Smarkm "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", 191029088Smarkm c->narg < argc + 2 ? "only " : "", 191129088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 191229088Smarkm return 0; 191329088Smarkm } 191487139Smarkm return((*c->handler)(argv[2])); 191529088Smarkm} 191629088Smarkm#endif 191729088Smarkm 191829088Smarkm#ifdef ENCRYPTION 191929088Smarkm/* 192029088Smarkm * The ENCRYPT command. 192129088Smarkm */ 192229088Smarkm 192329088Smarkmstruct encryptlist { 192487139Smarkm const char *name; 192587139Smarkm const char *help; 192687139Smarkm int (*handler)(char *, char *); 192729088Smarkm int needconnect; 192829088Smarkm int minarg; 192929088Smarkm int maxarg; 193029088Smarkm}; 193129088Smarkm 193229088Smarkmextern int 193387155Smarkm EncryptEnable(char *, char *), 193487155Smarkm EncryptDisable(char *, char *), 193587155Smarkm EncryptType(char *, char *), 193687155Smarkm EncryptStart(char *), 193787155Smarkm EncryptStartInput(void), 193887155Smarkm EncryptStartOutput(void), 193987155Smarkm EncryptStop(char *), 194087155Smarkm EncryptStopInput(void), 194187155Smarkm EncryptStopOutput(void), 194287155Smarkm EncryptStatus(void); 194329088Smarkmstatic int 194487155Smarkm EncryptHelp(void); 194529088Smarkm 194629088Smarkmstruct encryptlist EncryptList[] = { 194729088Smarkm { "enable", "Enable encryption. ('encrypt enable ?' for more)", 194829088Smarkm EncryptEnable, 1, 1, 2 }, 194929088Smarkm { "disable", "Disable encryption. ('encrypt enable ?' for more)", 195029088Smarkm EncryptDisable, 0, 1, 2 }, 195129088Smarkm { "type", "Set encryption type. ('encrypt type ?' for more)", 195229088Smarkm EncryptType, 0, 1, 1 }, 195329088Smarkm { "start", "Start encryption. ('encrypt start ?' for more)", 195487139Smarkm (int (*)(char *, char *))EncryptStart, 1, 0, 1 }, 195529088Smarkm { "stop", "Stop encryption. ('encrypt stop ?' for more)", 195687139Smarkm (int (*)(char *, char *))EncryptStop, 1, 0, 1 }, 195729088Smarkm { "input", "Start encrypting the input stream", 195887139Smarkm (int (*)(char *, char *))EncryptStartInput, 1, 0, 0 }, 195929088Smarkm { "-input", "Stop encrypting the input stream", 196087139Smarkm (int (*)(char *, char *))EncryptStopInput, 1, 0, 0 }, 196129088Smarkm { "output", "Start encrypting the output stream", 196287139Smarkm (int (*)(char *, char *))EncryptStartOutput, 1, 0, 0 }, 196329088Smarkm { "-output", "Stop encrypting the output stream", 196487139Smarkm (int (*)(char *, char *))EncryptStopOutput, 1, 0, 0 }, 196529088Smarkm 196629088Smarkm { "status", "Display current status of authentication information", 196787139Smarkm (int (*)(char *, char *))EncryptStatus, 0, 0, 0 }, 196887139Smarkm { "help", NULL, (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, 196987139Smarkm { "?", "Print help information", (int (*)(char *, char *))EncryptHelp, 0, 0, 0 }, 197087139Smarkm { NULL, NULL, NULL, 0, 0, 0 }, 197129088Smarkm}; 197229088Smarkm 197387139Smarkmstatic int 197487139SmarkmEncryptHelp(void) 197529088Smarkm{ 197629088Smarkm struct encryptlist *c; 197729088Smarkm 197829088Smarkm for (c = EncryptList; c->name; c++) { 197929088Smarkm if (c->help) { 198029088Smarkm if (*c->help) 198129088Smarkm printf("%-15s %s\n", c->name, c->help); 198229088Smarkm else 198329088Smarkm printf("\n"); 198429088Smarkm } 198529088Smarkm } 198629088Smarkm return 0; 198729088Smarkm} 198829088Smarkm 198987139Smarkmstatic int 199087139Smarkmencrypt_cmd(int argc, char *argv[]) 199129088Smarkm{ 199229088Smarkm struct encryptlist *c; 199329088Smarkm 199429088Smarkm if (argc < 2) { 199529088Smarkm fprintf(stderr, 199629088Smarkm "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); 199729088Smarkm return 0; 199829088Smarkm } 199929088Smarkm 200029088Smarkm c = (struct encryptlist *) 200129088Smarkm genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); 200229088Smarkm if (c == 0) { 200329088Smarkm fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", 200429088Smarkm argv[1]); 200529088Smarkm return 0; 200629088Smarkm } 200787139Smarkm if (Ambiguous((void *)c)) { 200829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", 200929088Smarkm argv[1]); 201029088Smarkm return 0; 201129088Smarkm } 201229088Smarkm argc -= 2; 201329088Smarkm if (argc < c->minarg || argc > c->maxarg) { 201429088Smarkm if (c->minarg == c->maxarg) { 201529088Smarkm fprintf(stderr, "Need %s%d argument%s ", 201629088Smarkm c->minarg < argc ? "only " : "", c->minarg, 201729088Smarkm c->minarg == 1 ? "" : "s"); 201829088Smarkm } else { 201929088Smarkm fprintf(stderr, "Need %s%d-%d arguments ", 202029088Smarkm c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); 202129088Smarkm } 202229088Smarkm fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", 202329088Smarkm c->name); 202429088Smarkm return 0; 202529088Smarkm } 202629088Smarkm if (c->needconnect && !connected) { 202729088Smarkm if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 202829088Smarkm printf("?Need to be connected first.\n"); 202929088Smarkm return 0; 203029088Smarkm } 203129088Smarkm } 203229088Smarkm return ((*c->handler)(argc > 0 ? argv[2] : 0, 203387139Smarkm argc > 1 ? argv[3] : 0)); 203429088Smarkm} 203529088Smarkm#endif /* ENCRYPTION */ 203629088Smarkm 203729088Smarkm/* 203829088Smarkm * Print status about the connection. 203929088Smarkm */ 204087139Smarkm/*ARGSUSED*/ 204187139Smarkmstatic int 204287139Smarkmstatus(int argc, char *argv[]) 204329088Smarkm{ 204429088Smarkm if (connected) { 204529088Smarkm printf("Connected to %s.\n", hostname); 204629088Smarkm if ((argc < 2) || strcmp(argv[1], "notmuch")) { 204729088Smarkm int mode = getconnmode(); 204829088Smarkm 204929088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 205029088Smarkm printf("Operating with LINEMODE option\n"); 205129088Smarkm printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 205229088Smarkm printf("%s catching of signals\n", 205329088Smarkm (mode&MODE_TRAPSIG) ? "Local" : "No"); 205429088Smarkm slcstate(); 205529088Smarkm#ifdef KLUDGELINEMODE 205629088Smarkm } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 205729088Smarkm printf("Operating in obsolete linemode\n"); 205829088Smarkm#endif 205929088Smarkm } else { 206029088Smarkm printf("Operating in single character mode\n"); 206129088Smarkm if (localchars) 206229088Smarkm printf("Catching signals locally\n"); 206329088Smarkm } 206429088Smarkm printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 206529088Smarkm if (my_want_state_is_will(TELOPT_LFLOW)) 206629088Smarkm printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 206729088Smarkm#ifdef ENCRYPTION 206829088Smarkm encrypt_display(); 206929088Smarkm#endif /* ENCRYPTION */ 207029088Smarkm } 207129088Smarkm } else { 207229088Smarkm printf("No connection.\n"); 207329088Smarkm } 207429088Smarkm printf("Escape character is '%s'.\n", control(escape)); 207529088Smarkm (void) fflush(stdout); 207629088Smarkm return 1; 207729088Smarkm} 207829088Smarkm 207929088Smarkm#ifdef SIGINFO 208029088Smarkm/* 208129088Smarkm * Function that gets called when SIGINFO is received. 208229088Smarkm */ 208387139Smarkmvoid 208487139Smarkmayt_status(void) 208529088Smarkm{ 208629088Smarkm (void) call(status, "status", "notmuch", 0); 208729088Smarkm} 208829088Smarkm#endif 208929088Smarkm 209056668Sshinstatic const char * 209187139Smarkmsockaddr_ntop(struct sockaddr *sa) 209256668Sshin{ 209356668Sshin void *addr; 209456668Sshin static char addrbuf[INET6_ADDRSTRLEN]; 209529088Smarkm 209656668Sshin switch (sa->sa_family) { 209756668Sshin case AF_INET: 209856668Sshin addr = &((struct sockaddr_in *)sa)->sin_addr; 209956668Sshin break; 210077095Sdillon case AF_UNIX: 210177095Sdillon addr = &((struct sockaddr_un *)sa)->sun_path; 210277095Sdillon break; 210356668Sshin#ifdef INET6 210456668Sshin case AF_INET6: 210556668Sshin addr = &((struct sockaddr_in6 *)sa)->sin6_addr; 210656668Sshin break; 210756668Sshin#endif 210856668Sshin default: 210956668Sshin return NULL; 211056668Sshin } 211156668Sshin inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); 211256668Sshin return addrbuf; 211356668Sshin} 211456668Sshin 211556668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 211656668Sshinstatic int 211787139Smarkmsetpolicy(int lnet, struct addrinfo *res, char *policy) 211856668Sshin{ 211956668Sshin char *buf; 212056668Sshin int level; 212156668Sshin int optname; 212256668Sshin 212356668Sshin if (policy == NULL) 212456668Sshin return 0; 212556668Sshin 212656668Sshin buf = ipsec_set_policy(policy, strlen(policy)); 212756668Sshin if (buf == NULL) { 212856668Sshin printf("%s\n", ipsec_strerror()); 212956668Sshin return -1; 213056668Sshin } 213156668Sshin level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 213256668Sshin optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; 213387139Smarkm if (setsockopt(lnet, level, optname, buf, ipsec_get_policylen(buf)) < 0){ 213456668Sshin perror("setsockopt"); 213556668Sshin return -1; 213656668Sshin } 213756668Sshin 213856668Sshin free(buf); 213987139Smarkm return 0; 214056668Sshin} 214156668Sshin#endif 214256668Sshin 214357125Sshin#ifdef INET6 214457125Sshin/* 214557125Sshin * When an Address Family related error happend, check if retry with 214657125Sshin * another AF is possible or not. 214757125Sshin * Return 1, if retry with another af is OK. Else, return 0. 214857125Sshin */ 214957125Sshinstatic int 215087139Smarkmswitch_af(struct addrinfo **aip) 215157125Sshin{ 215257125Sshin int nextaf; 215357125Sshin struct addrinfo *ai; 215457125Sshin 215557125Sshin ai = *aip; 215657125Sshin nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; 215757125Sshin do 215857125Sshin ai=ai->ai_next; 215957125Sshin while (ai != NULL && ai->ai_family != nextaf); 216057125Sshin *aip = ai; 216157125Sshin if (*aip != NULL) { 216257125Sshin return 1; 216357125Sshin } 216457125Sshin return 0; 216557125Sshin} 216657125Sshin#endif 216757125Sshin 216887139Smarkmint 216987139Smarkmtn(int argc, char *argv[]) 217029088Smarkm{ 2171305552Sdim unsigned char *srp = 0; 217256668Sshin int proto, opt; 217387139Smarkm int srlen; 217456668Sshin int srcroute = 0, result; 217529088Smarkm char *cmd, *hostp = 0, *portp = 0, *user = 0; 217647973Sru char *src_addr = NULL; 217757125Sshin struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; 217857125Sshin int error = 0, af_error = 0; 217929088Smarkm 218029088Smarkm if (connected) { 218129088Smarkm printf("?Already connected to %s\n", hostname); 218229088Smarkm setuid(getuid()); 218329088Smarkm return 0; 218429088Smarkm } 218529088Smarkm if (argc < 2) { 218629088Smarkm (void) strcpy(line, "open "); 218729088Smarkm printf("(to) "); 218829088Smarkm (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); 218929088Smarkm makeargv(); 219029088Smarkm argc = margc; 219129088Smarkm argv = margv; 219229088Smarkm } 219329088Smarkm cmd = *argv; 219429088Smarkm --argc; ++argv; 219529088Smarkm while (argc) { 219629088Smarkm if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) 219729088Smarkm goto usage; 219829088Smarkm if (strcmp(*argv, "-l") == 0) { 219929088Smarkm --argc; ++argv; 220029088Smarkm if (argc == 0) 220129088Smarkm goto usage; 220229088Smarkm user = *argv++; 220329088Smarkm --argc; 220429088Smarkm continue; 220529088Smarkm } 220629088Smarkm if (strcmp(*argv, "-a") == 0) { 220729088Smarkm --argc; ++argv; 220829088Smarkm autologin = 1; 220929088Smarkm continue; 221029088Smarkm } 221147973Sru if (strcmp(*argv, "-s") == 0) { 221247973Sru --argc; ++argv; 221347973Sru if (argc == 0) 221447973Sru goto usage; 221547973Sru src_addr = *argv++; 221647973Sru --argc; 221747973Sru continue; 221847973Sru } 221929088Smarkm if (hostp == 0) { 222029088Smarkm hostp = *argv++; 222129088Smarkm --argc; 222229088Smarkm continue; 222329088Smarkm } 222429088Smarkm if (portp == 0) { 222529088Smarkm portp = *argv++; 222629088Smarkm --argc; 222729088Smarkm continue; 222829088Smarkm } 222929088Smarkm usage: 223047973Sru printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); 223129088Smarkm setuid(getuid()); 223229088Smarkm return 0; 223329088Smarkm } 223429088Smarkm if (hostp == 0) 223529088Smarkm goto usage; 223629088Smarkm 223747973Sru if (src_addr != NULL) { 223856668Sshin memset(&hints, 0, sizeof(hints)); 223956668Sshin hints.ai_family = family; 224056668Sshin hints.ai_socktype = SOCK_STREAM; 224157125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 2242121425Sume if (error == EAI_NONAME) { 224356668Sshin hints.ai_flags = 0; 224457125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 224556668Sshin } 224656668Sshin if (error != 0) { 224756668Sshin fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); 224856668Sshin if (error == EAI_SYSTEM) 224956668Sshin fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); 225057125Sshin setuid(getuid()); 225147973Sru return 0; 225247973Sru } 225357125Sshin src_res0 = src_res; 225447973Sru } 225577095Sdillon if (hostp[0] == '/') { 225677095Sdillon struct sockaddr_un su; 225777095Sdillon 225877095Sdillon if (strlen(hostp) >= sizeof(su.sun_path)) { 225977095Sdillon fprintf(stderr, "hostname too long for unix domain socket: %s", 226077095Sdillon hostp); 226177095Sdillon goto fail; 226277095Sdillon } 2263139687Smaxim hostname = hostp; 226477095Sdillon memset(&su, 0, sizeof su); 226577095Sdillon su.sun_family = AF_UNIX; 226677095Sdillon strncpy(su.sun_path, hostp, sizeof su.sun_path); 226787139Smarkm printf("Trying %s...\n", hostp); 226877095Sdillon net = socket(PF_UNIX, SOCK_STREAM, 0); 226977095Sdillon if ( net < 0) { 227077095Sdillon perror("socket"); 227177095Sdillon goto fail; 227277095Sdillon } 227377095Sdillon if (connect(net, (struct sockaddr *)&su, sizeof su) == -1) { 227477095Sdillon perror(su.sun_path); 227577095Sdillon (void) NetClose(net); 227677095Sdillon goto fail; 227777095Sdillon } 227877095Sdillon goto af_unix; 227977095Sdillon } else if (hostp[0] == '@' || hostp[0] == '!') { 228056668Sshin if ( 228156668Sshin#ifdef INET6 228256668Sshin family == AF_INET6 || 228356668Sshin#endif 228456668Sshin (hostname = strrchr(hostp, ':')) == NULL) 228529088Smarkm hostname = strrchr(hostp, '@'); 2286107299Seric if (hostname == NULL) { 2287107299Seric hostname = hostp; 2288107299Seric } else { 2289107299Seric hostname++; 2290107299Seric srcroute = 1; 2291107299Seric } 229256668Sshin } else 229356668Sshin hostname = hostp; 229456668Sshin if (!portp) { 229556668Sshin telnetport = 1; 229687139Smarkm portp = strdup("telnet"); 229756668Sshin } else if (*portp == '-') { 229856668Sshin portp++; 229956668Sshin telnetport = 1; 2300142790Stobez } else if (*portp == '+') { 2301142790Stobez portp++; 2302142790Stobez telnetport = -1; 230356668Sshin } else 230456668Sshin telnetport = 0; 230556668Sshin 230656668Sshin memset(&hints, 0, sizeof(hints)); 230756668Sshin hints.ai_flags = AI_NUMERICHOST; 230856668Sshin hints.ai_family = family; 230956668Sshin hints.ai_socktype = SOCK_STREAM; 231056668Sshin error = getaddrinfo(hostname, portp, &hints, &res); 231162773Sitojun if (error) { 231262773Sitojun hints.ai_flags = AI_CANONNAME; 231362773Sitojun error = getaddrinfo(hostname, portp, &hints, &res); 231462773Sitojun } 231562773Sitojun if (error != 0) { 231662773Sitojun fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); 231762773Sitojun if (error == EAI_SYSTEM) 231862773Sitojun fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); 231962773Sitojun setuid(getuid()); 232062773Sitojun goto fail; 232162773Sitojun } 232262773Sitojun if (hints.ai_flags == AI_NUMERICHOST) { 232362773Sitojun /* hostname has numeric */ 232456668Sshin int gni_err = 1; 232556668Sshin 232656668Sshin if (doaddrlookup) 232756668Sshin gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, 232856668Sshin _hostname, sizeof(_hostname) - 1, NULL, 0, 232956870Sshin NI_NAMEREQD); 233056668Sshin if (gni_err != 0) 233162773Sitojun (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 233256668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 233356668Sshin hostname = _hostname; 233462773Sitojun } else { 233562773Sitojun /* hostname has FQDN */ 233656668Sshin if (srcroute != 0) 233756668Sshin (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); 233856668Sshin else if (res->ai_canonname != NULL) 233956668Sshin strcpy(_hostname, res->ai_canonname); 234056668Sshin else 234156668Sshin (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 234256668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 234356668Sshin hostname = _hostname; 234456668Sshin } 234557125Sshin res0 = res; 234687277Sjhay #ifdef INET6 234757233Sshin af_again: 234887277Sjhay #endif 234956668Sshin if (srcroute != 0) { 235057343Sshin static char hostbuf[BUFSIZ]; 235157125Sshin 235257233Sshin if (af_error == 0) { /* save intermediate hostnames for retry */ 235357233Sshin strncpy(hostbuf, hostp, BUFSIZ - 1); 235457233Sshin hostbuf[BUFSIZ - 1] = '\0'; 235557233Sshin } else 235657125Sshin hostp = hostbuf; 235729088Smarkm srp = 0; 235856668Sshin result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); 235956668Sshin if (result == 0) { 236057125Sshin#ifdef INET6 236157125Sshin if (family == AF_UNSPEC && af_error == 0 && 236257125Sshin switch_af(&res) == 1) { 236357125Sshin af_error = 1; 236457125Sshin goto af_again; 236557125Sshin } 236657125Sshin#endif 236729088Smarkm setuid(getuid()); 236857125Sshin goto fail; 236956668Sshin } else if (result == -1) { 237029088Smarkm printf("Bad source route option: %s\n", hostp); 237129088Smarkm setuid(getuid()); 237257125Sshin goto fail; 237329088Smarkm } 237429088Smarkm } 237529088Smarkm do { 237657342Sshin printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); 237756668Sshin net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 237829088Smarkm setuid(getuid()); 237929088Smarkm if (net < 0) { 238057125Sshin#ifdef INET6 238157125Sshin if (family == AF_UNSPEC && af_error == 0 && 238257125Sshin switch_af(&res) == 1) { 238357125Sshin af_error = 1; 238457125Sshin goto af_again; 238557125Sshin } 238657125Sshin#endif 238729088Smarkm perror("telnet: socket"); 238857125Sshin goto fail; 238929088Smarkm } 239056668Sshin if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) 239156668Sshin perror("setsockopt (source route)"); 239229088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 239356668Sshin if (res->ai_family == PF_INET) { 239429088Smarkm# if defined(HAS_GETTOS) 239529088Smarkm struct tosent *tp; 239629088Smarkm if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 239729088Smarkm tos = tp->t_tos; 239829088Smarkm# endif 239929088Smarkm if (tos < 0) 240081965Smarkm tos = IPTOS_LOWDELAY; 240129088Smarkm if (tos 240229088Smarkm && (setsockopt(net, IPPROTO_IP, IP_TOS, 240329088Smarkm (char *)&tos, sizeof(int)) < 0) 240429088Smarkm && (errno != ENOPROTOOPT)) 240529088Smarkm perror("telnet: setsockopt (IP_TOS) (ignored)"); 240629088Smarkm } 240729088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 240829088Smarkm 2409114911Smarkm if (telnet_debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 241029088Smarkm perror("setsockopt (SO_DEBUG)"); 241129088Smarkm } 241229088Smarkm 241347973Sru if (src_addr != NULL) { 241457125Sshin for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) 241557233Sshin if (src_res->ai_family == res->ai_family) 241657233Sshin break; 241757125Sshin if (src_res == NULL) 241857125Sshin src_res = src_res0; 241957125Sshin if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { 242057125Sshin#ifdef INET6 242157125Sshin if (family == AF_UNSPEC && af_error == 0 && 242257125Sshin switch_af(&res) == 1) { 242357125Sshin af_error = 1; 242457233Sshin (void) NetClose(net); 242557125Sshin goto af_again; 242657125Sshin } 242757125Sshin#endif 242847973Sru perror("bind"); 242957233Sshin (void) NetClose(net); 243057125Sshin goto fail; 243147973Sru } 243247973Sru } 243356668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 243457233Sshin if (setpolicy(net, res, ipsec_policy_in) < 0) { 243557233Sshin (void) NetClose(net); 243657125Sshin goto fail; 243757233Sshin } 243857233Sshin if (setpolicy(net, res, ipsec_policy_out) < 0) { 243957233Sshin (void) NetClose(net); 244057125Sshin goto fail; 244157233Sshin } 244256668Sshin#endif 244347973Sru 244456668Sshin if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { 244557125Sshin struct addrinfo *next; 244657125Sshin 244757125Sshin next = res->ai_next; 244857125Sshin /* If already an af failed, only try same af. */ 244957125Sshin if (af_error != 0) 245057125Sshin while (next != NULL && next->ai_family != res->ai_family) 245157125Sshin next = next->ai_next; 245257342Sshin warn("connect to address %s", sockaddr_ntop(res->ai_addr)); 245357125Sshin if (next != NULL) { 245457125Sshin res = next; 245529088Smarkm (void) NetClose(net); 245629088Smarkm continue; 245729088Smarkm } 245857342Sshin warnx("Unable to connect to remote host"); 245957233Sshin (void) NetClose(net); 246057125Sshin goto fail; 246129088Smarkm } 246229088Smarkm connected++; 246387139Smarkm#ifdef AUTHENTICATION 246487139Smarkm#ifdef ENCRYPTION 246529088Smarkm auth_encrypt_connect(connected); 246687139Smarkm#endif 246787139Smarkm#endif 246829088Smarkm } while (connected == 0); 246957125Sshin freeaddrinfo(res0); 247057125Sshin if (src_res0 != NULL) 247157125Sshin freeaddrinfo(src_res0); 247229088Smarkm cmdrc(hostp, hostname); 247377095Sdillon af_unix: 2474139687Smaxim connected = 1; 247529088Smarkm if (autologin && user == NULL) { 247629088Smarkm struct passwd *pw; 247729088Smarkm 247829088Smarkm user = getenv("USER"); 247929088Smarkm if (user == NULL || 248029181Smarkm ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { 248129181Smarkm if ((pw = getpwuid(getuid()))) 248229088Smarkm user = pw->pw_name; 248329088Smarkm else 248429088Smarkm user = NULL; 248529088Smarkm } 248629088Smarkm } 248729088Smarkm if (user) { 248887139Smarkm env_define("USER", user); 248987139Smarkm env_export("USER"); 249029088Smarkm } 249129088Smarkm (void) call(status, "status", "notmuch", 0); 2492207449Sjilles telnet(user); 249329088Smarkm (void) NetClose(net); 249429088Smarkm ExitString("Connection closed by foreign host.\n",1); 249529088Smarkm /*NOTREACHED*/ 249657125Sshin fail: 249757125Sshin if (res0 != NULL) 249857125Sshin freeaddrinfo(res0); 249957125Sshin if (src_res0 != NULL) 250057125Sshin freeaddrinfo(src_res0); 250157125Sshin return 0; 250229088Smarkm} 250329088Smarkm 250429088Smarkm#define HELPINDENT (sizeof ("connect")) 250529088Smarkm 250629088Smarkmstatic char 250729088Smarkm openhelp[] = "connect to a site", 250829088Smarkm closehelp[] = "close current connection", 250929088Smarkm logouthelp[] = "forcibly logout remote user and close the connection", 251029088Smarkm quithelp[] = "exit telnet", 251129088Smarkm statushelp[] = "print status information", 251229088Smarkm helphelp[] = "print help information", 251329088Smarkm sendhelp[] = "transmit special characters ('send ?' for more)", 251429088Smarkm sethelp[] = "set operating parameters ('set ?' for more)", 251529088Smarkm unsethelp[] = "unset operating parameters ('unset ?' for more)", 251629088Smarkm togglestring[] ="toggle operating parameters ('toggle ?' for more)", 251729088Smarkm slchelp[] = "change state of special charaters ('slc ?' for more)", 251829088Smarkm displayhelp[] = "display operating parameters", 251987139Smarkm#ifdef AUTHENTICATION 252029088Smarkm authhelp[] = "turn on (off) authentication ('auth ?' for more)", 252129088Smarkm#endif 252229088Smarkm#ifdef ENCRYPTION 252329088Smarkm encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", 252429088Smarkm#endif /* ENCRYPTION */ 252529088Smarkm zhelp[] = "suspend telnet", 252687139Smarkm#ifdef OPIE 252781965Smarkm opiehelp[] = "compute response to OPIE challenge", 252829181Smarkm#endif 252929088Smarkm shellhelp[] = "invoke a subshell", 253029088Smarkm envhelp[] = "change environment variables ('environ ?' for more)", 253129088Smarkm modestring[] = "try to enter line or character mode ('mode ?' for more)"; 253229088Smarkm 253329088Smarkmstatic Command cmdtab[] = { 253429088Smarkm { "close", closehelp, bye, 1 }, 253587139Smarkm { "logout", logouthelp, (int (*)(int, char **))logout, 1 }, 253629088Smarkm { "display", displayhelp, display, 0 }, 253729088Smarkm { "mode", modestring, modecmd, 0 }, 253881965Smarkm { "telnet", openhelp, tn, 0 }, 253929088Smarkm { "open", openhelp, tn, 0 }, 254087139Smarkm { "quit", quithelp, (int (*)(int, char **))quit, 0 }, 254129088Smarkm { "send", sendhelp, sendcmd, 0 }, 254229088Smarkm { "set", sethelp, setcmd, 0 }, 254329088Smarkm { "unset", unsethelp, unsetcmd, 0 }, 254429088Smarkm { "status", statushelp, status, 0 }, 254529088Smarkm { "toggle", togglestring, toggle, 0 }, 254629088Smarkm { "slc", slchelp, slccmd, 0 }, 254787139Smarkm#ifdef AUTHENTICATION 254829088Smarkm { "auth", authhelp, auth_cmd, 0 }, 254929088Smarkm#endif 255029088Smarkm#ifdef ENCRYPTION 255129088Smarkm { "encrypt", encrypthelp, encrypt_cmd, 0 }, 255229088Smarkm#endif /* ENCRYPTION */ 255387139Smarkm { "z", zhelp, (int (*)(int, char **))suspend, 0 }, 255429088Smarkm { "!", shellhelp, shell, 1 }, 255529088Smarkm { "environ", envhelp, env_cmd, 0 }, 255629088Smarkm { "?", helphelp, help, 0 }, 255787139Smarkm#ifdef OPIE 255881965Smarkm { "opie", opiehelp, opie_calc, 0 }, 255929181Smarkm#endif 256087139Smarkm { NULL, NULL, NULL, 0 } 256129088Smarkm}; 256229088Smarkm 256329088Smarkmstatic char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 256429088Smarkmstatic char escapehelp[] = "deprecated command -- use 'set escape' instead"; 256529088Smarkm 256629088Smarkmstatic Command cmdtab2[] = { 256729088Smarkm { "help", 0, help, 0 }, 256829088Smarkm { "escape", escapehelp, setescape, 0 }, 256987139Smarkm { "crmod", crmodhelp, (int (*)(int, char **))togcrmod, 0 }, 257087139Smarkm { NULL, NULL, NULL, 0 } 257129088Smarkm}; 257229088Smarkm 257329088Smarkm 257429088Smarkm/* 257529088Smarkm * Call routine with argc, argv set from args (terminated by 0). 257629088Smarkm */ 257729088Smarkm 257887139Smarkmstatic int 257987139Smarkmcall(intrtn_t routine, ...) 258029088Smarkm{ 258129088Smarkm va_list ap; 258229088Smarkm char *args[100]; 258329088Smarkm int argno = 0; 258429088Smarkm 258587139Smarkm va_start(ap, routine); 258687139Smarkm while ((args[argno++] = va_arg(ap, char *)) != 0); 258729088Smarkm va_end(ap); 258829088Smarkm return (*routine)(argno-1, args); 258929088Smarkm} 259029088Smarkm 259129088Smarkm 259287139Smarkmstatic Command * 259387139Smarkmgetcmd(char *name) 259429088Smarkm{ 259529088Smarkm Command *cm; 259629088Smarkm 259729181Smarkm if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) 259829088Smarkm return cm; 259929088Smarkm return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); 260029088Smarkm} 260129088Smarkm 260287139Smarkmvoid 260387139Smarkmcommand(int top, const char *tbuf, int cnt) 260429088Smarkm{ 260587139Smarkm Command *c; 260629088Smarkm 260729088Smarkm setcommandmode(); 260829088Smarkm if (!top) { 260929088Smarkm putchar('\n'); 261029088Smarkm } else { 261129088Smarkm (void) signal(SIGINT, SIG_DFL); 261229088Smarkm (void) signal(SIGQUIT, SIG_DFL); 261329088Smarkm } 261429088Smarkm for (;;) { 261529088Smarkm if (rlogin == _POSIX_VDISABLE) 261629088Smarkm printf("%s> ", prompt); 261729088Smarkm if (tbuf) { 261887139Smarkm char *cp; 261929088Smarkm cp = line; 262029088Smarkm while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 262129088Smarkm cnt--; 262229088Smarkm tbuf = 0; 262329088Smarkm if (cp == line || *--cp != '\n' || cp == line) 262429088Smarkm goto getline; 262529088Smarkm *cp = '\0'; 262629088Smarkm if (rlogin == _POSIX_VDISABLE) 262729088Smarkm printf("%s\n", line); 262829088Smarkm } else { 262929088Smarkm getline: 263029088Smarkm if (rlogin != _POSIX_VDISABLE) 263129088Smarkm printf("%s> ", prompt); 263229088Smarkm if (fgets(line, sizeof(line), stdin) == NULL) { 263329088Smarkm if (feof(stdin) || ferror(stdin)) { 263429088Smarkm (void) quit(); 263529088Smarkm /*NOTREACHED*/ 263629088Smarkm } 263729088Smarkm break; 263829088Smarkm } 263929088Smarkm } 264029088Smarkm if (line[0] == 0) 264129088Smarkm break; 264229088Smarkm makeargv(); 264329088Smarkm if (margv[0] == 0) { 264429088Smarkm break; 264529088Smarkm } 264629088Smarkm c = getcmd(margv[0]); 264787139Smarkm if (Ambiguous((void *)c)) { 264829088Smarkm printf("?Ambiguous command\n"); 264929088Smarkm continue; 265029088Smarkm } 265129088Smarkm if (c == 0) { 265229088Smarkm printf("?Invalid command\n"); 265329088Smarkm continue; 265429088Smarkm } 265529088Smarkm if (c->needconnect && !connected) { 265629088Smarkm printf("?Need to be connected first.\n"); 265729088Smarkm continue; 265829088Smarkm } 265929088Smarkm if ((*c->handler)(margc, margv)) { 266029088Smarkm break; 266129088Smarkm } 266229088Smarkm } 266329088Smarkm if (!top) { 266429088Smarkm if (!connected) { 266529088Smarkm longjmp(toplevel, 1); 266629088Smarkm /*NOTREACHED*/ 266729088Smarkm } 266829088Smarkm setconnmode(0); 266929088Smarkm } 267029088Smarkm} 267129088Smarkm 267229088Smarkm/* 267329088Smarkm * Help command. 267429088Smarkm */ 267587139Smarkmstatic int 267687139Smarkmhelp(int argc, char *argv[]) 267729088Smarkm{ 267887139Smarkm Command *c; 267929088Smarkm 268029088Smarkm if (argc == 1) { 268129088Smarkm printf("Commands may be abbreviated. Commands are:\n\n"); 268229088Smarkm for (c = cmdtab; c->name; c++) 268329088Smarkm if (c->help) { 268487266Smarkm printf("%-*s\t%s\n", (int)HELPINDENT, c->name, 268529088Smarkm c->help); 268629088Smarkm } 268781965Smarkm return 0; 268829088Smarkm } 268929181Smarkm else while (--argc > 0) { 269087139Smarkm char *arg; 269129088Smarkm arg = *++argv; 269229088Smarkm c = getcmd(arg); 269387139Smarkm if (Ambiguous((void *)c)) 269429088Smarkm printf("?Ambiguous help command %s\n", arg); 269529088Smarkm else if (c == (Command *)0) 269629088Smarkm printf("?Invalid help command %s\n", arg); 269729088Smarkm else 269829088Smarkm printf("%s\n", c->help); 269929088Smarkm } 270081965Smarkm return 0; 270129088Smarkm} 270229088Smarkm 270329088Smarkmstatic char *rcname = 0; 270429088Smarkmstatic char rcbuf[128]; 270529088Smarkm 270687139Smarkmvoid 270787139Smarkmcmdrc(char *m1, char *m2) 270829088Smarkm{ 270987139Smarkm Command *c; 271029088Smarkm FILE *rcfile; 271129088Smarkm int gotmachine = 0; 271229088Smarkm int l1 = strlen(m1); 271329088Smarkm int l2 = strlen(m2); 271468891Skris char m1save[MAXHOSTNAMELEN]; 271529088Smarkm 271629088Smarkm if (skiprc) 271729088Smarkm return; 271829088Smarkm 271968891Skris strlcpy(m1save, m1, sizeof(m1save)); 272029088Smarkm m1 = m1save; 272129088Smarkm 272229088Smarkm if (rcname == 0) { 272329088Smarkm rcname = getenv("HOME"); 272429181Smarkm if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) 272529088Smarkm strcpy(rcbuf, rcname); 272629088Smarkm else 272729088Smarkm rcbuf[0] = '\0'; 272829088Smarkm strcat(rcbuf, "/.telnetrc"); 272929088Smarkm rcname = rcbuf; 273029088Smarkm } 273129088Smarkm 273229088Smarkm if ((rcfile = fopen(rcname, "r")) == 0) { 273329088Smarkm return; 273429088Smarkm } 273529088Smarkm 273629088Smarkm for (;;) { 273729088Smarkm if (fgets(line, sizeof(line), rcfile) == NULL) 273829088Smarkm break; 273929088Smarkm if (line[0] == 0) 274029088Smarkm break; 274129088Smarkm if (line[0] == '#') 274229088Smarkm continue; 274329088Smarkm if (gotmachine) { 274429088Smarkm if (!isspace(line[0])) 274529088Smarkm gotmachine = 0; 274629088Smarkm } 274729088Smarkm if (gotmachine == 0) { 274829088Smarkm if (isspace(line[0])) 274929088Smarkm continue; 275029088Smarkm if (strncasecmp(line, m1, l1) == 0) 275129088Smarkm strncpy(line, &line[l1], sizeof(line) - l1); 275229088Smarkm else if (strncasecmp(line, m2, l2) == 0) 275329088Smarkm strncpy(line, &line[l2], sizeof(line) - l2); 275429088Smarkm else if (strncasecmp(line, "DEFAULT", 7) == 0) 275529088Smarkm strncpy(line, &line[7], sizeof(line) - 7); 275629088Smarkm else 275729088Smarkm continue; 275829088Smarkm if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') 275929088Smarkm continue; 276029088Smarkm gotmachine = 1; 276129088Smarkm } 276229088Smarkm makeargv(); 276329088Smarkm if (margv[0] == 0) 276429088Smarkm continue; 276529088Smarkm c = getcmd(margv[0]); 276687139Smarkm if (Ambiguous((void *)c)) { 276729088Smarkm printf("?Ambiguous command: %s\n", margv[0]); 276829088Smarkm continue; 276929088Smarkm } 277029088Smarkm if (c == 0) { 277129088Smarkm printf("?Invalid command: %s\n", margv[0]); 277229088Smarkm continue; 277329088Smarkm } 277429088Smarkm /* 277529088Smarkm * This should never happen... 277629088Smarkm */ 277729088Smarkm if (c->needconnect && !connected) { 277829088Smarkm printf("?Need to be connected first for %s.\n", margv[0]); 277929088Smarkm continue; 278029088Smarkm } 278129088Smarkm (*c->handler)(margc, margv); 278229088Smarkm } 278329088Smarkm fclose(rcfile); 278429088Smarkm} 278529088Smarkm 278629088Smarkm/* 278729088Smarkm * Source route is handed in as 278829088Smarkm * [!]@hop1@hop2...[@|:]dst 278929088Smarkm * If the leading ! is present, it is a 279029088Smarkm * strict source route, otherwise it is 279129088Smarkm * assmed to be a loose source route. 279229088Smarkm * 279329088Smarkm * We fill in the source route option as 279429088Smarkm * hop1,hop2,hop3...dest 279529088Smarkm * and return a pointer to hop1, which will 279629088Smarkm * be the address to connect() to. 279729088Smarkm * 279829088Smarkm * Arguments: 279956668Sshin * 280056668Sshin * res: ponter to addrinfo structure which contains sockaddr to 280156668Sshin * the host to connect to. 280256668Sshin * 280329088Smarkm * arg: pointer to route list to decipher 280429088Smarkm * 280529088Smarkm * cpp: If *cpp is not equal to NULL, this is a 280629088Smarkm * pointer to a pointer to a character array 280729088Smarkm * that should be filled in with the option. 280829088Smarkm * 280929088Smarkm * lenp: pointer to an integer that contains the 281029088Smarkm * length of *cpp if *cpp != NULL. 281129088Smarkm * 281256668Sshin * protop: pointer to an integer that should be filled in with 281356668Sshin * appropriate protocol for setsockopt, as socket 281456668Sshin * protocol family. 281556668Sshin * 281656668Sshin * optp: pointer to an integer that should be filled in with 281756668Sshin * appropriate option for setsockopt, as socket protocol 281856668Sshin * family. 281956668Sshin * 282029088Smarkm * Return values: 282129088Smarkm * 282256668Sshin * If the return value is 1, then all operations are 282356668Sshin * successful. If the 282429088Smarkm * return value is -1, there was a syntax error in the 282529088Smarkm * option, either unknown characters, or too many hosts. 282629088Smarkm * If the return value is 0, one of the hostnames in the 282729088Smarkm * path is unknown, and *cpp is set to point to the bad 282829088Smarkm * hostname. 282929088Smarkm * 283029088Smarkm * *cpp: If *cpp was equal to NULL, it will be filled 283129088Smarkm * in with a pointer to our static area that has 283229088Smarkm * the option filled in. This will be 32bit aligned. 283329088Smarkm * 283429088Smarkm * *lenp: This will be filled in with how long the option 283529088Smarkm * pointed to by *cpp is. 283629088Smarkm * 283756668Sshin * *protop: This will be filled in with appropriate protocol for 283856668Sshin * setsockopt, as socket protocol family. 283956668Sshin * 284056668Sshin * *optp: This will be filled in with appropriate option for 284156668Sshin * setsockopt, as socket protocol family. 284229088Smarkm */ 284387139Smarkmstatic int 2844305552Sdimsourceroute(struct addrinfo *ai, char *arg, unsigned char **cpp, int *lenp, int *protop, int *optp) 284529088Smarkm{ 284663662Sume static char buf[1024 + ALIGNBYTES]; /*XXX*/ 2847305552Sdim unsigned char *cp, *cp2, *lsrp, *ep; 284887139Smarkm struct sockaddr_in *_sin; 284987277Sjhay#ifdef INET6 285056668Sshin struct sockaddr_in6 *sin6; 2851121472Sume struct ip6_rthdr *rth; 285287277Sjhay#endif 285356668Sshin struct addrinfo hints, *res; 285456668Sshin int error; 285587139Smarkm char c; 285629088Smarkm 285729088Smarkm /* 285829088Smarkm * Verify the arguments, and make sure we have 285929088Smarkm * at least 7 bytes for the option. 286029088Smarkm */ 286129088Smarkm if (cpp == NULL || lenp == NULL) 286257724Sshin return -1; 286356668Sshin if (*cpp != NULL) { 286456668Sshin switch (res->ai_family) { 286556668Sshin case AF_INET: 286656668Sshin if (*lenp < 7) 286757724Sshin return -1; 286856668Sshin break; 286956668Sshin#ifdef INET6 287056668Sshin case AF_INET6: 287187139Smarkm if (*lenp < (int)CMSG_SPACE(sizeof(struct ip6_rthdr) + 287257724Sshin sizeof(struct in6_addr))) 287357724Sshin return -1; 287456668Sshin break; 287556668Sshin#endif 287656668Sshin } 287756668Sshin } 287829088Smarkm /* 287929088Smarkm * Decide whether we have a buffer passed to us, 288029088Smarkm * or if we need to use our own static buffer. 288129088Smarkm */ 288229088Smarkm if (*cpp) { 288329088Smarkm lsrp = *cpp; 288456668Sshin ep = lsrp + *lenp; 288529088Smarkm } else { 288663662Sume *cpp = lsrp = (char *)ALIGN(buf); 288756668Sshin ep = lsrp + 1024; 288829088Smarkm } 288929088Smarkm 289029088Smarkm cp = arg; 289129088Smarkm 289256668Sshin#ifdef INET6 289356668Sshin if (ai->ai_family == AF_INET6) { 2894121472Sume if ((rth = inet6_rth_init((void *)*cpp, sizeof(buf), 2895121472Sume IPV6_RTHDR_TYPE_0, 0)) == NULL) 2896121472Sume return -1; 289756668Sshin if (*cp != '@') 289856668Sshin return -1; 289956668Sshin *protop = IPPROTO_IPV6; 2900121472Sume *optp = IPV6_RTHDR; 290156668Sshin } else 290256668Sshin#endif 290356668Sshin { 290429088Smarkm /* 290529088Smarkm * Next, decide whether we have a loose source 290629088Smarkm * route or a strict source route, and fill in 290729088Smarkm * the begining of the option. 290829088Smarkm */ 290929088Smarkm if (*cp == '!') { 291029088Smarkm cp++; 291129088Smarkm *lsrp++ = IPOPT_SSRR; 291229088Smarkm } else 291329088Smarkm *lsrp++ = IPOPT_LSRR; 291429088Smarkm 291529088Smarkm if (*cp != '@') 291657724Sshin return -1; 291729088Smarkm 291829088Smarkm lsrp++; /* skip over length, we'll fill it in later */ 291929088Smarkm *lsrp++ = 4; 292056668Sshin *protop = IPPROTO_IP; 292156668Sshin *optp = IP_OPTIONS; 292256668Sshin } 292329088Smarkm 292429088Smarkm cp++; 292556668Sshin memset(&hints, 0, sizeof(hints)); 292656668Sshin hints.ai_family = ai->ai_family; 292756668Sshin hints.ai_socktype = SOCK_STREAM; 292829088Smarkm for (c = 0;;) { 292956668Sshin if ( 293056668Sshin#ifdef INET6 293156668Sshin ai->ai_family != AF_INET6 && 293256668Sshin#endif 293356668Sshin c == ':') 293429088Smarkm cp2 = 0; 293529181Smarkm else for (cp2 = cp; (c = *cp2); cp2++) { 293629088Smarkm if (c == ',') { 293729088Smarkm *cp2++ = '\0'; 293829088Smarkm if (*cp2 == '@') 293929088Smarkm cp2++; 294029088Smarkm } else if (c == '@') { 294129088Smarkm *cp2++ = '\0'; 294256668Sshin } else if ( 294356668Sshin#ifdef INET6 294456668Sshin ai->ai_family != AF_INET6 && 294556668Sshin#endif 294656668Sshin c == ':') { 294729088Smarkm *cp2++ = '\0'; 294829088Smarkm } else 294929088Smarkm continue; 295029088Smarkm break; 295129088Smarkm } 295229088Smarkm if (!c) 295329088Smarkm cp2 = 0; 295429088Smarkm 295556668Sshin hints.ai_flags = AI_NUMERICHOST; 295681965Smarkm error = getaddrinfo(cp, NULL, &hints, &res); 2957121425Sume if (error == EAI_NONAME) { 295856668Sshin hints.ai_flags = 0; 295956668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 296056668Sshin } 296156668Sshin if (error != 0) { 296256668Sshin fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); 296356668Sshin if (error == EAI_SYSTEM) 296456668Sshin fprintf(stderr, "%s: %s\n", cp, 296556668Sshin strerror(errno)); 296629088Smarkm *cpp = cp; 296729088Smarkm return(0); 296829088Smarkm } 296956668Sshin#ifdef INET6 297056668Sshin if (res->ai_family == AF_INET6) { 297156668Sshin sin6 = (struct sockaddr_in6 *)res->ai_addr; 2972121472Sume if (inet6_rth_add((void *)rth, &sin6->sin6_addr) == -1) 2973121472Sume return(0); 297456668Sshin } else 297556668Sshin#endif 297656668Sshin { 297787139Smarkm _sin = (struct sockaddr_in *)res->ai_addr; 297887139Smarkm memcpy(lsrp, (char *)&_sin->sin_addr, 4); 297929088Smarkm lsrp += 4; 298056668Sshin } 298129088Smarkm if (cp2) 298229088Smarkm cp = cp2; 298329088Smarkm else 298429088Smarkm break; 298529088Smarkm /* 298629088Smarkm * Check to make sure there is space for next address 298729088Smarkm */ 298856668Sshin if (lsrp + 4 > ep) 298957724Sshin return -1; 299056668Sshin freeaddrinfo(res); 299129088Smarkm } 299256668Sshin#ifdef INET6 299356668Sshin if (res->ai_family == AF_INET6) { 2994121472Sume rth->ip6r_len = rth->ip6r_segleft * 2; 2995121472Sume *lenp = (rth->ip6r_len + 1) << 3; 299656668Sshin } else 299756668Sshin#endif 299856668Sshin { 299929088Smarkm if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 300029088Smarkm *cpp = 0; 300129088Smarkm *lenp = 0; 300257724Sshin return -1; 300329088Smarkm } 300429088Smarkm *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 300529088Smarkm *lenp = lsrp - *cpp; 300656668Sshin } 300756668Sshin freeaddrinfo(res); 300856668Sshin return 1; 300929088Smarkm} 3010