1*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 2*7c478bd9Sstevel@tonic-gate 3*7c478bd9Sstevel@tonic-gate /* 4*7c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1990, 1993 5*7c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 6*7c478bd9Sstevel@tonic-gate * 7*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 8*7c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 9*7c478bd9Sstevel@tonic-gate * are met: 10*7c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 11*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 12*7c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 13*7c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 14*7c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 15*7c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 16*7c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 17*7c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 18*7c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 19*7c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 20*7c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 21*7c478bd9Sstevel@tonic-gate * without specific prior written permission. 22*7c478bd9Sstevel@tonic-gate * 23*7c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24*7c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25*7c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26*7c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27*7c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28*7c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29*7c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30*7c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31*7c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32*7c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33*7c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 34*7c478bd9Sstevel@tonic-gate * 35*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 36*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 37*7c478bd9Sstevel@tonic-gate */ 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #ifndef lint 40*7c478bd9Sstevel@tonic-gate static char sccsid[] = "@(#)commands.c 8.1 (Berkeley) 6/6/93"; 41*7c478bd9Sstevel@tonic-gate #endif /* not lint */ 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 47*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 48*7c478bd9Sstevel@tonic-gate 49*7c478bd9Sstevel@tonic-gate #include <signal.h> 50*7c478bd9Sstevel@tonic-gate #include <netdb.h> 51*7c478bd9Sstevel@tonic-gate #include <ctype.h> 52*7c478bd9Sstevel@tonic-gate #include <pwd.h> 53*7c478bd9Sstevel@tonic-gate #include <errno.h> 54*7c478bd9Sstevel@tonic-gate #include <strings.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include <arpa/telnet.h> 57*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate #include "general.h" 60*7c478bd9Sstevel@tonic-gate 61*7c478bd9Sstevel@tonic-gate #include "ring.h" 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gate #include "externs.h" 64*7c478bd9Sstevel@tonic-gate #include "defines.h" 65*7c478bd9Sstevel@tonic-gate #include "types.h" 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate extern char *telnet_krb5_realm; 68*7c478bd9Sstevel@tonic-gate extern void krb5_profile_get_options(char *, char *, 69*7c478bd9Sstevel@tonic-gate profile_options_boolean*); 70*7c478bd9Sstevel@tonic-gate 71*7c478bd9Sstevel@tonic-gate #include <k5-int.h> 72*7c478bd9Sstevel@tonic-gate #include <profile/prof_int.h> 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate profile_options_boolean config_file_options[] = { 75*7c478bd9Sstevel@tonic-gate { "forwardable", &forwardable_flag, 0}, 76*7c478bd9Sstevel@tonic-gate { "forward", &forward_flag, 0}, 77*7c478bd9Sstevel@tonic-gate { "encrypt", &encrypt_flag, 0 }, 78*7c478bd9Sstevel@tonic-gate { "autologin", &autologin, 0 }, 79*7c478bd9Sstevel@tonic-gate { NULL, NULL, 0} 80*7c478bd9Sstevel@tonic-gate }; 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate #include <netinet/ip.h> 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * Number of maximum IPv4 gateways user can specify. This number is limited by 86*7c478bd9Sstevel@tonic-gate * the maximum size of the IPv4 options in the IPv4 header. 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate #define MAX_GATEWAY 8 89*7c478bd9Sstevel@tonic-gate /* 90*7c478bd9Sstevel@tonic-gate * Number of maximum IPv6 gateways user can specify. This number is limited by 91*7c478bd9Sstevel@tonic-gate * the maximum header extension length of the IPv6 routing header. 92*7c478bd9Sstevel@tonic-gate */ 93*7c478bd9Sstevel@tonic-gate #define MAX_GATEWAY6 127 94*7c478bd9Sstevel@tonic-gate #define MAXMAX_GATEWAY MAX(MAX_GATEWAY, MAX_GATEWAY6) 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate /* 97*7c478bd9Sstevel@tonic-gate * Depending on the address resolutions of the target and gateways, 98*7c478bd9Sstevel@tonic-gate * we determine which addresses of the target we'll try connecting to. 99*7c478bd9Sstevel@tonic-gate */ 100*7c478bd9Sstevel@tonic-gate #define ALL_ADDRS 0 /* try all addrs of target */ 101*7c478bd9Sstevel@tonic-gate #define ONLY_V4 1 /* try only IPv4 addrs of target */ 102*7c478bd9Sstevel@tonic-gate #define ONLY_V6 2 /* try only IPv6 addrs of target */ 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate #if defined(USE_TOS) 105*7c478bd9Sstevel@tonic-gate int tos = -1; 106*7c478bd9Sstevel@tonic-gate #endif 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate char *hostname; 109*7c478bd9Sstevel@tonic-gate static char _hostname[MAXHOSTNAMELEN]; 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static int send_tncmd(void (*func)(), char *, char *); 112*7c478bd9Sstevel@tonic-gate static void call(int n_ptrs, ...); 113*7c478bd9Sstevel@tonic-gate static int cmdrc(char *, char *); 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate typedef struct { 116*7c478bd9Sstevel@tonic-gate char *name; /* command name */ 117*7c478bd9Sstevel@tonic-gate char *help; /* help string (NULL for no help) */ 118*7c478bd9Sstevel@tonic-gate int (*handler)(); /* routine which executes command */ 119*7c478bd9Sstevel@tonic-gate int needconnect; /* Do we need to be connected to execute? */ 120*7c478bd9Sstevel@tonic-gate } Command; 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate /* 123*7c478bd9Sstevel@tonic-gate * storage for IPv6 and/or IPv4 addresses of gateways 124*7c478bd9Sstevel@tonic-gate */ 125*7c478bd9Sstevel@tonic-gate struct gateway { 126*7c478bd9Sstevel@tonic-gate struct in6_addr gw_addr6; 127*7c478bd9Sstevel@tonic-gate struct in_addr gw_addr; 128*7c478bd9Sstevel@tonic-gate }; 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate /* 131*7c478bd9Sstevel@tonic-gate * IPv4 source routing option. 132*7c478bd9Sstevel@tonic-gate * In order to avoid padding for the alignment of IPv4 addresses, ipsr_addrs 133*7c478bd9Sstevel@tonic-gate * is defined as a 2-D array of uint8_t, instead of 1-D array of struct in_addr. 134*7c478bd9Sstevel@tonic-gate * If it were defined as "struct in_addr ipsr_addrs[1]", "ipsr_ptr" would be 135*7c478bd9Sstevel@tonic-gate * followed by one byte of padding to avoid misaligned struct in_addr. 136*7c478bd9Sstevel@tonic-gate */ 137*7c478bd9Sstevel@tonic-gate struct ip_sourceroute { 138*7c478bd9Sstevel@tonic-gate uint8_t ipsr_code; 139*7c478bd9Sstevel@tonic-gate uint8_t ipsr_len; 140*7c478bd9Sstevel@tonic-gate uint8_t ipsr_ptr; 141*7c478bd9Sstevel@tonic-gate /* up to 9 IPv4 addresses */ 142*7c478bd9Sstevel@tonic-gate uint8_t ipsr_addrs[1][sizeof (struct in_addr)]; 143*7c478bd9Sstevel@tonic-gate }; 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate static char *line = NULL; 146*7c478bd9Sstevel@tonic-gate static unsigned linesize = 0; 147*7c478bd9Sstevel@tonic-gate static int margc; 148*7c478bd9Sstevel@tonic-gate static char **margv = NULL; 149*7c478bd9Sstevel@tonic-gate static unsigned margvlen = 0; 150*7c478bd9Sstevel@tonic-gate static int doing_rc = 0; /* .telnetrc file is being read and processed */ 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate static void 153*7c478bd9Sstevel@tonic-gate Close(int *fd) 154*7c478bd9Sstevel@tonic-gate { 155*7c478bd9Sstevel@tonic-gate if (*fd != -1) { 156*7c478bd9Sstevel@tonic-gate (void) close(*fd); 157*7c478bd9Sstevel@tonic-gate *fd = -1; 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate static void 162*7c478bd9Sstevel@tonic-gate Free(char **p) 163*7c478bd9Sstevel@tonic-gate { 164*7c478bd9Sstevel@tonic-gate if (*p != NULL) { 165*7c478bd9Sstevel@tonic-gate free(*p); 166*7c478bd9Sstevel@tonic-gate *p = NULL; 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate static void 171*7c478bd9Sstevel@tonic-gate FreeHostnameList(char *list[]) 172*7c478bd9Sstevel@tonic-gate { 173*7c478bd9Sstevel@tonic-gate unsigned i; 174*7c478bd9Sstevel@tonic-gate for (i = 0; i <= MAXMAX_GATEWAY && list[i] != NULL; i++) 175*7c478bd9Sstevel@tonic-gate Free(&list[i]); 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate 178*7c478bd9Sstevel@tonic-gate #define MARGV_CHUNK_SIZE 8 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate static void 181*7c478bd9Sstevel@tonic-gate set_argv(str) 182*7c478bd9Sstevel@tonic-gate char *str; 183*7c478bd9Sstevel@tonic-gate { 184*7c478bd9Sstevel@tonic-gate if (margc == margvlen) { 185*7c478bd9Sstevel@tonic-gate char **newmargv; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate margvlen += MARGV_CHUNK_SIZE; 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate if ((newmargv = realloc(margv, margvlen * sizeof (char *))) 190*7c478bd9Sstevel@tonic-gate == NULL) 191*7c478bd9Sstevel@tonic-gate ExitString("telnet: no space for arguments", 192*7c478bd9Sstevel@tonic-gate EXIT_FAILURE); 193*7c478bd9Sstevel@tonic-gate 194*7c478bd9Sstevel@tonic-gate margv = newmargv; 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate margv[margc] = str; 198*7c478bd9Sstevel@tonic-gate if (str != NULL) 199*7c478bd9Sstevel@tonic-gate margc++; 200*7c478bd9Sstevel@tonic-gate } 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate static void 203*7c478bd9Sstevel@tonic-gate makeargv() 204*7c478bd9Sstevel@tonic-gate { 205*7c478bd9Sstevel@tonic-gate char *cp, *cp2, c; 206*7c478bd9Sstevel@tonic-gate boolean_t shellcmd = B_FALSE; 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate margc = 0; 209*7c478bd9Sstevel@tonic-gate cp = line; 210*7c478bd9Sstevel@tonic-gate if (*cp == '!') { /* Special case shell escape */ 211*7c478bd9Sstevel@tonic-gate set_argv("!"); /* No room in string to get this */ 212*7c478bd9Sstevel@tonic-gate cp++; 213*7c478bd9Sstevel@tonic-gate shellcmd = B_TRUE; 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate while ((c = *cp) != '\0') { 216*7c478bd9Sstevel@tonic-gate register int inquote = 0; 217*7c478bd9Sstevel@tonic-gate while (isspace(c)) 218*7c478bd9Sstevel@tonic-gate c = *++cp; 219*7c478bd9Sstevel@tonic-gate if (c == '\0') 220*7c478bd9Sstevel@tonic-gate break; 221*7c478bd9Sstevel@tonic-gate set_argv(cp); 222*7c478bd9Sstevel@tonic-gate /* 223*7c478bd9Sstevel@tonic-gate * For the shell escape, put the rest of the line, less 224*7c478bd9Sstevel@tonic-gate * leading space, into a single argument, breaking out from 225*7c478bd9Sstevel@tonic-gate * the loop to prevent the rest of the line being split up 226*7c478bd9Sstevel@tonic-gate * into smaller arguments. 227*7c478bd9Sstevel@tonic-gate */ 228*7c478bd9Sstevel@tonic-gate if (shellcmd) 229*7c478bd9Sstevel@tonic-gate break; 230*7c478bd9Sstevel@tonic-gate for (cp2 = cp; c != '\0'; c = *++cp) { 231*7c478bd9Sstevel@tonic-gate if (inquote) { 232*7c478bd9Sstevel@tonic-gate if (c == inquote) { 233*7c478bd9Sstevel@tonic-gate inquote = 0; 234*7c478bd9Sstevel@tonic-gate continue; 235*7c478bd9Sstevel@tonic-gate } 236*7c478bd9Sstevel@tonic-gate } else { 237*7c478bd9Sstevel@tonic-gate if (c == '\\') { 238*7c478bd9Sstevel@tonic-gate if ((c = *++cp) == '\0') 239*7c478bd9Sstevel@tonic-gate break; 240*7c478bd9Sstevel@tonic-gate } else if (c == '"') { 241*7c478bd9Sstevel@tonic-gate inquote = '"'; 242*7c478bd9Sstevel@tonic-gate continue; 243*7c478bd9Sstevel@tonic-gate } else if (c == '\'') { 244*7c478bd9Sstevel@tonic-gate inquote = '\''; 245*7c478bd9Sstevel@tonic-gate continue; 246*7c478bd9Sstevel@tonic-gate } else if (isspace(c)) 247*7c478bd9Sstevel@tonic-gate break; 248*7c478bd9Sstevel@tonic-gate } 249*7c478bd9Sstevel@tonic-gate *cp2++ = c; 250*7c478bd9Sstevel@tonic-gate } 251*7c478bd9Sstevel@tonic-gate *cp2 = '\0'; 252*7c478bd9Sstevel@tonic-gate if (c == '\0') 253*7c478bd9Sstevel@tonic-gate break; 254*7c478bd9Sstevel@tonic-gate cp++; 255*7c478bd9Sstevel@tonic-gate } 256*7c478bd9Sstevel@tonic-gate set_argv((char *)NULL); 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate 259*7c478bd9Sstevel@tonic-gate /* 260*7c478bd9Sstevel@tonic-gate * Make a character string into a number. 261*7c478bd9Sstevel@tonic-gate * 262*7c478bd9Sstevel@tonic-gate * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 263*7c478bd9Sstevel@tonic-gate */ 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate static 266*7c478bd9Sstevel@tonic-gate special(s) 267*7c478bd9Sstevel@tonic-gate register char *s; 268*7c478bd9Sstevel@tonic-gate { 269*7c478bd9Sstevel@tonic-gate register char c; 270*7c478bd9Sstevel@tonic-gate char b; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate switch (*s) { 273*7c478bd9Sstevel@tonic-gate case '^': 274*7c478bd9Sstevel@tonic-gate b = *++s; 275*7c478bd9Sstevel@tonic-gate if (b == '?') { 276*7c478bd9Sstevel@tonic-gate c = b | 0x40; /* DEL */ 277*7c478bd9Sstevel@tonic-gate } else { 278*7c478bd9Sstevel@tonic-gate c = b & 0x1f; 279*7c478bd9Sstevel@tonic-gate } 280*7c478bd9Sstevel@tonic-gate break; 281*7c478bd9Sstevel@tonic-gate default: 282*7c478bd9Sstevel@tonic-gate c = *s; 283*7c478bd9Sstevel@tonic-gate break; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate return (c); 286*7c478bd9Sstevel@tonic-gate } 287*7c478bd9Sstevel@tonic-gate 288*7c478bd9Sstevel@tonic-gate /* 289*7c478bd9Sstevel@tonic-gate * Construct a control character sequence 290*7c478bd9Sstevel@tonic-gate * for a special character. 291*7c478bd9Sstevel@tonic-gate */ 292*7c478bd9Sstevel@tonic-gate static char * 293*7c478bd9Sstevel@tonic-gate control(c) 294*7c478bd9Sstevel@tonic-gate register cc_t c; 295*7c478bd9Sstevel@tonic-gate { 296*7c478bd9Sstevel@tonic-gate static char buf[5]; 297*7c478bd9Sstevel@tonic-gate /* 298*7c478bd9Sstevel@tonic-gate * The only way I could get the Sun 3.5 compiler 299*7c478bd9Sstevel@tonic-gate * to shut up about 300*7c478bd9Sstevel@tonic-gate * if ((unsigned int)c >= 0x80) 301*7c478bd9Sstevel@tonic-gate * was to assign "c" to an unsigned int variable... 302*7c478bd9Sstevel@tonic-gate * Arggg.... 303*7c478bd9Sstevel@tonic-gate */ 304*7c478bd9Sstevel@tonic-gate register unsigned int uic = (unsigned int)c; 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate if (uic == 0x7f) 307*7c478bd9Sstevel@tonic-gate return ("^?"); 308*7c478bd9Sstevel@tonic-gate if (c == (cc_t)_POSIX_VDISABLE) { 309*7c478bd9Sstevel@tonic-gate return ("off"); 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate if (uic >= 0x80) { 312*7c478bd9Sstevel@tonic-gate buf[0] = '\\'; 313*7c478bd9Sstevel@tonic-gate buf[1] = ((c>>6)&07) + '0'; 314*7c478bd9Sstevel@tonic-gate buf[2] = ((c>>3)&07) + '0'; 315*7c478bd9Sstevel@tonic-gate buf[3] = (c&07) + '0'; 316*7c478bd9Sstevel@tonic-gate buf[4] = 0; 317*7c478bd9Sstevel@tonic-gate } else if (uic >= 0x20) { 318*7c478bd9Sstevel@tonic-gate buf[0] = c; 319*7c478bd9Sstevel@tonic-gate buf[1] = 0; 320*7c478bd9Sstevel@tonic-gate } else { 321*7c478bd9Sstevel@tonic-gate buf[0] = '^'; 322*7c478bd9Sstevel@tonic-gate buf[1] = '@'+c; 323*7c478bd9Sstevel@tonic-gate buf[2] = 0; 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate return (buf); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* 329*7c478bd9Sstevel@tonic-gate * Same as control() except that its only used for escape handling, which uses 330*7c478bd9Sstevel@tonic-gate * _POSIX_VDISABLE differently and is aided by the use of the state variable 331*7c478bd9Sstevel@tonic-gate * escape_valid. 332*7c478bd9Sstevel@tonic-gate */ 333*7c478bd9Sstevel@tonic-gate static char * 334*7c478bd9Sstevel@tonic-gate esc_control(c) 335*7c478bd9Sstevel@tonic-gate register cc_t c; 336*7c478bd9Sstevel@tonic-gate { 337*7c478bd9Sstevel@tonic-gate static char buf[5]; 338*7c478bd9Sstevel@tonic-gate /* 339*7c478bd9Sstevel@tonic-gate * The only way I could get the Sun 3.5 compiler 340*7c478bd9Sstevel@tonic-gate * to shut up about 341*7c478bd9Sstevel@tonic-gate * if ((unsigned int)c >= 0x80) 342*7c478bd9Sstevel@tonic-gate * was to assign "c" to an unsigned int variable... 343*7c478bd9Sstevel@tonic-gate * Arggg.... 344*7c478bd9Sstevel@tonic-gate */ 345*7c478bd9Sstevel@tonic-gate register unsigned int uic = (unsigned int)c; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate if (escape_valid == B_FALSE) 348*7c478bd9Sstevel@tonic-gate return ("off"); 349*7c478bd9Sstevel@tonic-gate if (uic == 0x7f) 350*7c478bd9Sstevel@tonic-gate return ("^?"); 351*7c478bd9Sstevel@tonic-gate if (uic >= 0x80) { 352*7c478bd9Sstevel@tonic-gate buf[0] = '\\'; 353*7c478bd9Sstevel@tonic-gate buf[1] = ((c>>6)&07) + '0'; 354*7c478bd9Sstevel@tonic-gate buf[2] = ((c>>3)&07) + '0'; 355*7c478bd9Sstevel@tonic-gate buf[3] = (c&07) + '0'; 356*7c478bd9Sstevel@tonic-gate buf[4] = 0; 357*7c478bd9Sstevel@tonic-gate } else if (uic >= 0x20) { 358*7c478bd9Sstevel@tonic-gate buf[0] = c; 359*7c478bd9Sstevel@tonic-gate buf[1] = 0; 360*7c478bd9Sstevel@tonic-gate } else { 361*7c478bd9Sstevel@tonic-gate buf[0] = '^'; 362*7c478bd9Sstevel@tonic-gate buf[1] = '@'+c; 363*7c478bd9Sstevel@tonic-gate buf[2] = 0; 364*7c478bd9Sstevel@tonic-gate } 365*7c478bd9Sstevel@tonic-gate return (buf); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate /* 369*7c478bd9Sstevel@tonic-gate * The following are data structures and routines for 370*7c478bd9Sstevel@tonic-gate * the "send" command. 371*7c478bd9Sstevel@tonic-gate * 372*7c478bd9Sstevel@tonic-gate */ 373*7c478bd9Sstevel@tonic-gate 374*7c478bd9Sstevel@tonic-gate struct sendlist { 375*7c478bd9Sstevel@tonic-gate char *name; /* How user refers to it (case independent) */ 376*7c478bd9Sstevel@tonic-gate char *help; /* Help information (0 ==> no help) */ 377*7c478bd9Sstevel@tonic-gate int needconnect; /* Need to be connected */ 378*7c478bd9Sstevel@tonic-gate int narg; /* Number of arguments */ 379*7c478bd9Sstevel@tonic-gate int (*handler)(); /* Routine to perform (for special ops) */ 380*7c478bd9Sstevel@tonic-gate int nbyte; /* Number of bytes to send this command */ 381*7c478bd9Sstevel@tonic-gate int what; /* Character to be sent (<0 ==> special) */ 382*7c478bd9Sstevel@tonic-gate }; 383*7c478bd9Sstevel@tonic-gate 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate static int send_esc(void); 386*7c478bd9Sstevel@tonic-gate static int send_help(void); 387*7c478bd9Sstevel@tonic-gate static int send_docmd(char *); 388*7c478bd9Sstevel@tonic-gate static int send_dontcmd(char *); 389*7c478bd9Sstevel@tonic-gate static int send_willcmd(char *); 390*7c478bd9Sstevel@tonic-gate static int send_wontcmd(char *); 391*7c478bd9Sstevel@tonic-gate 392*7c478bd9Sstevel@tonic-gate static struct sendlist Sendlist[] = { 393*7c478bd9Sstevel@tonic-gate { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, 394*7c478bd9Sstevel@tonic-gate { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, 395*7c478bd9Sstevel@tonic-gate { "b", 0, 1, 0, 0, 2, BREAK }, 396*7c478bd9Sstevel@tonic-gate { "br", 0, 1, 0, 0, 2, BREAK }, 397*7c478bd9Sstevel@tonic-gate { "break", 0, 1, 0, 0, 2, BREAK }, 398*7c478bd9Sstevel@tonic-gate { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, 399*7c478bd9Sstevel@tonic-gate { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, 400*7c478bd9Sstevel@tonic-gate { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, 401*7c478bd9Sstevel@tonic-gate { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, 402*7c478bd9Sstevel@tonic-gate { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, 403*7c478bd9Sstevel@tonic-gate { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, 404*7c478bd9Sstevel@tonic-gate { "intp", 0, 1, 0, 0, 2, IP }, 405*7c478bd9Sstevel@tonic-gate { "interrupt", 0, 1, 0, 0, 2, IP }, 406*7c478bd9Sstevel@tonic-gate { "intr", 0, 1, 0, 0, 2, IP }, 407*7c478bd9Sstevel@tonic-gate { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, 408*7c478bd9Sstevel@tonic-gate { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, 409*7c478bd9Sstevel@tonic-gate { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, 410*7c478bd9Sstevel@tonic-gate { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, 411*7c478bd9Sstevel@tonic-gate { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, 412*7c478bd9Sstevel@tonic-gate { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, 413*7c478bd9Sstevel@tonic-gate { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, 414*7c478bd9Sstevel@tonic-gate { "?", "Display send options", 0, 0, send_help, 0, 0 }, 415*7c478bd9Sstevel@tonic-gate { "help", 0, 0, 0, send_help, 0, 0 }, 416*7c478bd9Sstevel@tonic-gate { "do", 0, 0, 1, send_docmd, 3, 0 }, 417*7c478bd9Sstevel@tonic-gate { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, 418*7c478bd9Sstevel@tonic-gate { "will", 0, 0, 1, send_willcmd, 3, 0 }, 419*7c478bd9Sstevel@tonic-gate { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, 420*7c478bd9Sstevel@tonic-gate { 0 } 421*7c478bd9Sstevel@tonic-gate }; 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate #define GETSEND(name) ((struct sendlist *)genget(name, (char **)Sendlist, \ 424*7c478bd9Sstevel@tonic-gate sizeof (struct sendlist))) 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static int 427*7c478bd9Sstevel@tonic-gate sendcmd(argc, argv) 428*7c478bd9Sstevel@tonic-gate int argc; 429*7c478bd9Sstevel@tonic-gate char **argv; 430*7c478bd9Sstevel@tonic-gate { 431*7c478bd9Sstevel@tonic-gate int count; /* how many bytes we are going to need to send */ 432*7c478bd9Sstevel@tonic-gate int i; 433*7c478bd9Sstevel@tonic-gate struct sendlist *s; /* pointer to current command */ 434*7c478bd9Sstevel@tonic-gate int success = 0; 435*7c478bd9Sstevel@tonic-gate int needconnect = 0; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate if (argc < 2) { 438*7c478bd9Sstevel@tonic-gate (void) printf( 439*7c478bd9Sstevel@tonic-gate "need at least one argument for 'send' command\n"); 440*7c478bd9Sstevel@tonic-gate (void) printf("'send ?' for help\n"); 441*7c478bd9Sstevel@tonic-gate return (0); 442*7c478bd9Sstevel@tonic-gate } 443*7c478bd9Sstevel@tonic-gate /* 444*7c478bd9Sstevel@tonic-gate * First, validate all the send arguments. 445*7c478bd9Sstevel@tonic-gate * In addition, we see how much space we are going to need, and 446*7c478bd9Sstevel@tonic-gate * whether or not we will be doing a "SYNCH" operation (which 447*7c478bd9Sstevel@tonic-gate * flushes the network queue). 448*7c478bd9Sstevel@tonic-gate */ 449*7c478bd9Sstevel@tonic-gate count = 0; 450*7c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 451*7c478bd9Sstevel@tonic-gate s = GETSEND(argv[i]); 452*7c478bd9Sstevel@tonic-gate if (s == 0) { 453*7c478bd9Sstevel@tonic-gate (void) printf("Unknown send argument '%s'\n'send ?' " 454*7c478bd9Sstevel@tonic-gate "for help.\n", argv[i]); 455*7c478bd9Sstevel@tonic-gate return (0); 456*7c478bd9Sstevel@tonic-gate } else if (Ambiguous(s)) { 457*7c478bd9Sstevel@tonic-gate (void) printf("Ambiguous send argument '%s'\n'send ?' " 458*7c478bd9Sstevel@tonic-gate "for help.\n", argv[i]); 459*7c478bd9Sstevel@tonic-gate return (0); 460*7c478bd9Sstevel@tonic-gate } 461*7c478bd9Sstevel@tonic-gate if (i + s->narg >= argc) { 462*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 463*7c478bd9Sstevel@tonic-gate "Need %d argument%s to 'send %s' " 464*7c478bd9Sstevel@tonic-gate "command. 'send %s ?' for help.\n", 465*7c478bd9Sstevel@tonic-gate s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 466*7c478bd9Sstevel@tonic-gate return (0); 467*7c478bd9Sstevel@tonic-gate } 468*7c478bd9Sstevel@tonic-gate count += s->nbyte; 469*7c478bd9Sstevel@tonic-gate if (s->handler == send_help) { 470*7c478bd9Sstevel@tonic-gate (void) send_help(); 471*7c478bd9Sstevel@tonic-gate return (0); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate i += s->narg; 475*7c478bd9Sstevel@tonic-gate needconnect += s->needconnect; 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate if (!connected && needconnect) { 478*7c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 479*7c478bd9Sstevel@tonic-gate (void) printf("'send ?' for help\n"); 480*7c478bd9Sstevel@tonic-gate return (0); 481*7c478bd9Sstevel@tonic-gate } 482*7c478bd9Sstevel@tonic-gate /* Now, do we have enough room? */ 483*7c478bd9Sstevel@tonic-gate if (NETROOM() < count) { 484*7c478bd9Sstevel@tonic-gate (void) printf("There is not enough room in the buffer " 485*7c478bd9Sstevel@tonic-gate "TO the network\n"); 486*7c478bd9Sstevel@tonic-gate (void) printf( 487*7c478bd9Sstevel@tonic-gate "to process your request. Nothing will be done.\n"); 488*7c478bd9Sstevel@tonic-gate (void) printf("('send synch' will throw away most " 489*7c478bd9Sstevel@tonic-gate "data in the network\n"); 490*7c478bd9Sstevel@tonic-gate (void) printf("buffer, if this might help.)\n"); 491*7c478bd9Sstevel@tonic-gate return (0); 492*7c478bd9Sstevel@tonic-gate } 493*7c478bd9Sstevel@tonic-gate /* OK, they are all OK, now go through again and actually send */ 494*7c478bd9Sstevel@tonic-gate count = 0; 495*7c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 496*7c478bd9Sstevel@tonic-gate if ((s = GETSEND(argv[i])) == 0) { 497*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 498*7c478bd9Sstevel@tonic-gate "Telnet 'send' error - argument disappeared!\n"); 499*7c478bd9Sstevel@tonic-gate (void) quit(); 500*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 501*7c478bd9Sstevel@tonic-gate } 502*7c478bd9Sstevel@tonic-gate if (s->handler) { 503*7c478bd9Sstevel@tonic-gate count++; 504*7c478bd9Sstevel@tonic-gate success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 505*7c478bd9Sstevel@tonic-gate (s->narg > 1) ? argv[i+2] : 0); 506*7c478bd9Sstevel@tonic-gate i += s->narg; 507*7c478bd9Sstevel@tonic-gate } else { 508*7c478bd9Sstevel@tonic-gate NET2ADD(IAC, s->what); 509*7c478bd9Sstevel@tonic-gate printoption("SENT", IAC, s->what); 510*7c478bd9Sstevel@tonic-gate } 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate return (count == success); 513*7c478bd9Sstevel@tonic-gate } 514*7c478bd9Sstevel@tonic-gate 515*7c478bd9Sstevel@tonic-gate static int 516*7c478bd9Sstevel@tonic-gate send_esc() 517*7c478bd9Sstevel@tonic-gate { 518*7c478bd9Sstevel@tonic-gate NETADD(escape); 519*7c478bd9Sstevel@tonic-gate return (1); 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate static int 523*7c478bd9Sstevel@tonic-gate send_docmd(name) 524*7c478bd9Sstevel@tonic-gate char *name; 525*7c478bd9Sstevel@tonic-gate { 526*7c478bd9Sstevel@tonic-gate return (send_tncmd(send_do, "do", name)); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate static int 530*7c478bd9Sstevel@tonic-gate send_dontcmd(name) 531*7c478bd9Sstevel@tonic-gate char *name; 532*7c478bd9Sstevel@tonic-gate { 533*7c478bd9Sstevel@tonic-gate return (send_tncmd(send_dont, "dont", name)); 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate static int 537*7c478bd9Sstevel@tonic-gate send_willcmd(name) 538*7c478bd9Sstevel@tonic-gate char *name; 539*7c478bd9Sstevel@tonic-gate { 540*7c478bd9Sstevel@tonic-gate return (send_tncmd(send_will, "will", name)); 541*7c478bd9Sstevel@tonic-gate } 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate static int 544*7c478bd9Sstevel@tonic-gate send_wontcmd(name) 545*7c478bd9Sstevel@tonic-gate char *name; 546*7c478bd9Sstevel@tonic-gate { 547*7c478bd9Sstevel@tonic-gate return (send_tncmd(send_wont, "wont", name)); 548*7c478bd9Sstevel@tonic-gate } 549*7c478bd9Sstevel@tonic-gate 550*7c478bd9Sstevel@tonic-gate int 551*7c478bd9Sstevel@tonic-gate send_tncmd(func, cmd, name) 552*7c478bd9Sstevel@tonic-gate void (*func)(); 553*7c478bd9Sstevel@tonic-gate char *cmd, *name; 554*7c478bd9Sstevel@tonic-gate { 555*7c478bd9Sstevel@tonic-gate char **cpp; 556*7c478bd9Sstevel@tonic-gate extern char *telopts[]; 557*7c478bd9Sstevel@tonic-gate register int val = 0; 558*7c478bd9Sstevel@tonic-gate 559*7c478bd9Sstevel@tonic-gate if (isprefix(name, "help") || isprefix(name, "?")) { 560*7c478bd9Sstevel@tonic-gate register int col, len; 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate (void) printf("Usage: send %s <value|option>\n", cmd); 563*7c478bd9Sstevel@tonic-gate (void) printf("\"value\" must be from 0 to 255\n"); 564*7c478bd9Sstevel@tonic-gate (void) printf("Valid options are:\n\t"); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate col = 8; 567*7c478bd9Sstevel@tonic-gate for (cpp = telopts; *cpp; cpp++) { 568*7c478bd9Sstevel@tonic-gate len = strlen(*cpp) + 3; 569*7c478bd9Sstevel@tonic-gate if (col + len > 65) { 570*7c478bd9Sstevel@tonic-gate (void) printf("\n\t"); 571*7c478bd9Sstevel@tonic-gate col = 8; 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate (void) printf(" \"%s\"", *cpp); 574*7c478bd9Sstevel@tonic-gate col += len; 575*7c478bd9Sstevel@tonic-gate } 576*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 577*7c478bd9Sstevel@tonic-gate return (0); 578*7c478bd9Sstevel@tonic-gate } 579*7c478bd9Sstevel@tonic-gate cpp = (char **)genget(name, telopts, sizeof (char *)); 580*7c478bd9Sstevel@tonic-gate if (Ambiguous(cpp)) { 581*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 582*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('send %s ?' for help).\n", 583*7c478bd9Sstevel@tonic-gate name, cmd); 584*7c478bd9Sstevel@tonic-gate return (0); 585*7c478bd9Sstevel@tonic-gate } 586*7c478bd9Sstevel@tonic-gate if (cpp) { 587*7c478bd9Sstevel@tonic-gate val = cpp - telopts; 588*7c478bd9Sstevel@tonic-gate } else { 589*7c478bd9Sstevel@tonic-gate register char *cp = name; 590*7c478bd9Sstevel@tonic-gate 591*7c478bd9Sstevel@tonic-gate while (*cp >= '0' && *cp <= '9') { 592*7c478bd9Sstevel@tonic-gate val *= 10; 593*7c478bd9Sstevel@tonic-gate val += *cp - '0'; 594*7c478bd9Sstevel@tonic-gate cp++; 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate if (*cp != 0) { 597*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 598*7c478bd9Sstevel@tonic-gate "'%s': unknown argument ('send %s ?' for help).\n", 599*7c478bd9Sstevel@tonic-gate name, cmd); 600*7c478bd9Sstevel@tonic-gate return (0); 601*7c478bd9Sstevel@tonic-gate } else if (val < 0 || val > 255) { 602*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 603*7c478bd9Sstevel@tonic-gate "'%s': bad value ('send %s ?' for help).\n", 604*7c478bd9Sstevel@tonic-gate name, cmd); 605*7c478bd9Sstevel@tonic-gate return (0); 606*7c478bd9Sstevel@tonic-gate } 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate if (!connected) { 609*7c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 610*7c478bd9Sstevel@tonic-gate return (0); 611*7c478bd9Sstevel@tonic-gate } 612*7c478bd9Sstevel@tonic-gate (*func)(val, 1); 613*7c478bd9Sstevel@tonic-gate return (1); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate static int 617*7c478bd9Sstevel@tonic-gate send_help() 618*7c478bd9Sstevel@tonic-gate { 619*7c478bd9Sstevel@tonic-gate struct sendlist *s; /* pointer to current command */ 620*7c478bd9Sstevel@tonic-gate for (s = Sendlist; s->name; s++) { 621*7c478bd9Sstevel@tonic-gate if (s->help) 622*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", s->name, s->help); 623*7c478bd9Sstevel@tonic-gate } 624*7c478bd9Sstevel@tonic-gate return (0); 625*7c478bd9Sstevel@tonic-gate } 626*7c478bd9Sstevel@tonic-gate 627*7c478bd9Sstevel@tonic-gate /* 628*7c478bd9Sstevel@tonic-gate * The following are the routines and data structures referred 629*7c478bd9Sstevel@tonic-gate * to by the arguments to the "toggle" command. 630*7c478bd9Sstevel@tonic-gate */ 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate static int 633*7c478bd9Sstevel@tonic-gate lclchars() 634*7c478bd9Sstevel@tonic-gate { 635*7c478bd9Sstevel@tonic-gate donelclchars = 1; 636*7c478bd9Sstevel@tonic-gate return (1); 637*7c478bd9Sstevel@tonic-gate } 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate static int 640*7c478bd9Sstevel@tonic-gate togdebug() 641*7c478bd9Sstevel@tonic-gate { 642*7c478bd9Sstevel@tonic-gate if (net > 0 && 643*7c478bd9Sstevel@tonic-gate (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 644*7c478bd9Sstevel@tonic-gate perror("setsockopt (SO_DEBUG)"); 645*7c478bd9Sstevel@tonic-gate } 646*7c478bd9Sstevel@tonic-gate return (1); 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate static int 651*7c478bd9Sstevel@tonic-gate togcrlf() 652*7c478bd9Sstevel@tonic-gate { 653*7c478bd9Sstevel@tonic-gate if (crlf) { 654*7c478bd9Sstevel@tonic-gate (void) printf( 655*7c478bd9Sstevel@tonic-gate "Will send carriage returns as telnet <CR><LF>.\n"); 656*7c478bd9Sstevel@tonic-gate } else { 657*7c478bd9Sstevel@tonic-gate (void) printf( 658*7c478bd9Sstevel@tonic-gate "Will send carriage returns as telnet <CR><NUL>.\n"); 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate return (1); 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate static int binmode; 664*7c478bd9Sstevel@tonic-gate 665*7c478bd9Sstevel@tonic-gate static int 666*7c478bd9Sstevel@tonic-gate togbinary(val) 667*7c478bd9Sstevel@tonic-gate int val; 668*7c478bd9Sstevel@tonic-gate { 669*7c478bd9Sstevel@tonic-gate donebinarytoggle = 1; 670*7c478bd9Sstevel@tonic-gate 671*7c478bd9Sstevel@tonic-gate if (val >= 0) { 672*7c478bd9Sstevel@tonic-gate binmode = val; 673*7c478bd9Sstevel@tonic-gate } else { 674*7c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_BINARY) && 675*7c478bd9Sstevel@tonic-gate my_want_state_is_do(TELOPT_BINARY)) { 676*7c478bd9Sstevel@tonic-gate binmode = 1; 677*7c478bd9Sstevel@tonic-gate } else if (my_want_state_is_wont(TELOPT_BINARY) && 678*7c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_BINARY)) { 679*7c478bd9Sstevel@tonic-gate binmode = 0; 680*7c478bd9Sstevel@tonic-gate } 681*7c478bd9Sstevel@tonic-gate val = binmode ? 0 : 1; 682*7c478bd9Sstevel@tonic-gate } 683*7c478bd9Sstevel@tonic-gate 684*7c478bd9Sstevel@tonic-gate if (val == 1) { 685*7c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_BINARY) && 686*7c478bd9Sstevel@tonic-gate my_want_state_is_do(TELOPT_BINARY)) { 687*7c478bd9Sstevel@tonic-gate (void) printf("Already operating in binary mode " 688*7c478bd9Sstevel@tonic-gate "with remote host.\n"); 689*7c478bd9Sstevel@tonic-gate } else { 690*7c478bd9Sstevel@tonic-gate (void) printf( 691*7c478bd9Sstevel@tonic-gate "Negotiating binary mode with remote host.\n"); 692*7c478bd9Sstevel@tonic-gate tel_enter_binary(3); 693*7c478bd9Sstevel@tonic-gate } 694*7c478bd9Sstevel@tonic-gate } else { 695*7c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_BINARY) && 696*7c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_BINARY)) { 697*7c478bd9Sstevel@tonic-gate (void) printf("Already in network ascii mode " 698*7c478bd9Sstevel@tonic-gate "with remote host.\n"); 699*7c478bd9Sstevel@tonic-gate } else { 700*7c478bd9Sstevel@tonic-gate (void) printf("Negotiating network ascii mode " 701*7c478bd9Sstevel@tonic-gate "with remote host.\n"); 702*7c478bd9Sstevel@tonic-gate tel_leave_binary(3); 703*7c478bd9Sstevel@tonic-gate } 704*7c478bd9Sstevel@tonic-gate } 705*7c478bd9Sstevel@tonic-gate return (1); 706*7c478bd9Sstevel@tonic-gate } 707*7c478bd9Sstevel@tonic-gate 708*7c478bd9Sstevel@tonic-gate static int 709*7c478bd9Sstevel@tonic-gate togrbinary(val) 710*7c478bd9Sstevel@tonic-gate int val; 711*7c478bd9Sstevel@tonic-gate { 712*7c478bd9Sstevel@tonic-gate donebinarytoggle = 1; 713*7c478bd9Sstevel@tonic-gate 714*7c478bd9Sstevel@tonic-gate if (val == -1) 715*7c478bd9Sstevel@tonic-gate val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate if (val == 1) { 718*7c478bd9Sstevel@tonic-gate if (my_want_state_is_do(TELOPT_BINARY)) { 719*7c478bd9Sstevel@tonic-gate (void) printf("Already receiving in binary mode.\n"); 720*7c478bd9Sstevel@tonic-gate } else { 721*7c478bd9Sstevel@tonic-gate (void) printf("Negotiating binary mode on input.\n"); 722*7c478bd9Sstevel@tonic-gate tel_enter_binary(1); 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate } else { 725*7c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_BINARY)) { 726*7c478bd9Sstevel@tonic-gate (void) printf( 727*7c478bd9Sstevel@tonic-gate "Already receiving in network ascii mode.\n"); 728*7c478bd9Sstevel@tonic-gate } else { 729*7c478bd9Sstevel@tonic-gate (void) printf( 730*7c478bd9Sstevel@tonic-gate "Negotiating network ascii mode on input.\n"); 731*7c478bd9Sstevel@tonic-gate tel_leave_binary(1); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate return (1); 735*7c478bd9Sstevel@tonic-gate } 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate static int 738*7c478bd9Sstevel@tonic-gate togxbinary(val) 739*7c478bd9Sstevel@tonic-gate int val; 740*7c478bd9Sstevel@tonic-gate { 741*7c478bd9Sstevel@tonic-gate donebinarytoggle = 1; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate if (val == -1) 744*7c478bd9Sstevel@tonic-gate val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate if (val == 1) { 747*7c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_BINARY)) { 748*7c478bd9Sstevel@tonic-gate (void) printf("Already transmitting in binary mode.\n"); 749*7c478bd9Sstevel@tonic-gate } else { 750*7c478bd9Sstevel@tonic-gate (void) printf("Negotiating binary mode on output.\n"); 751*7c478bd9Sstevel@tonic-gate tel_enter_binary(2); 752*7c478bd9Sstevel@tonic-gate } 753*7c478bd9Sstevel@tonic-gate } else { 754*7c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_BINARY)) { 755*7c478bd9Sstevel@tonic-gate (void) printf( 756*7c478bd9Sstevel@tonic-gate "Already transmitting in network ascii mode.\n"); 757*7c478bd9Sstevel@tonic-gate } else { 758*7c478bd9Sstevel@tonic-gate (void) printf( 759*7c478bd9Sstevel@tonic-gate "Negotiating network ascii mode on output.\n"); 760*7c478bd9Sstevel@tonic-gate tel_leave_binary(2); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate } 763*7c478bd9Sstevel@tonic-gate return (1); 764*7c478bd9Sstevel@tonic-gate } 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate 767*7c478bd9Sstevel@tonic-gate static int togglehelp(void); 768*7c478bd9Sstevel@tonic-gate extern int auth_togdebug(int); 769*7c478bd9Sstevel@tonic-gate 770*7c478bd9Sstevel@tonic-gate struct togglelist { 771*7c478bd9Sstevel@tonic-gate char *name; /* name of toggle */ 772*7c478bd9Sstevel@tonic-gate char *help; /* help message */ 773*7c478bd9Sstevel@tonic-gate int (*handler)(); /* routine to do actual setting */ 774*7c478bd9Sstevel@tonic-gate int *variable; 775*7c478bd9Sstevel@tonic-gate char *actionexplanation; 776*7c478bd9Sstevel@tonic-gate }; 777*7c478bd9Sstevel@tonic-gate 778*7c478bd9Sstevel@tonic-gate static struct togglelist Togglelist[] = { 779*7c478bd9Sstevel@tonic-gate { "autoflush", 780*7c478bd9Sstevel@tonic-gate "flushing of output when sending interrupt characters", 781*7c478bd9Sstevel@tonic-gate 0, 782*7c478bd9Sstevel@tonic-gate &autoflush, 783*7c478bd9Sstevel@tonic-gate "flush output when sending interrupt characters" }, 784*7c478bd9Sstevel@tonic-gate { "autosynch", 785*7c478bd9Sstevel@tonic-gate "automatic sending of interrupt characters in urgent mode", 786*7c478bd9Sstevel@tonic-gate 0, 787*7c478bd9Sstevel@tonic-gate &autosynch, 788*7c478bd9Sstevel@tonic-gate "send interrupt characters in urgent mode" }, 789*7c478bd9Sstevel@tonic-gate { "autologin", 790*7c478bd9Sstevel@tonic-gate "automatic sending of login and/or authentication info", 791*7c478bd9Sstevel@tonic-gate 0, 792*7c478bd9Sstevel@tonic-gate &autologin, 793*7c478bd9Sstevel@tonic-gate "send login name and/or authentication information" }, 794*7c478bd9Sstevel@tonic-gate { "authdebug", 795*7c478bd9Sstevel@tonic-gate "authentication debugging", 796*7c478bd9Sstevel@tonic-gate auth_togdebug, 797*7c478bd9Sstevel@tonic-gate 0, 798*7c478bd9Sstevel@tonic-gate "print authentication debugging information" }, 799*7c478bd9Sstevel@tonic-gate { "autoencrypt", 800*7c478bd9Sstevel@tonic-gate "automatic encryption of data stream", 801*7c478bd9Sstevel@tonic-gate EncryptAutoEnc, 802*7c478bd9Sstevel@tonic-gate 0, 803*7c478bd9Sstevel@tonic-gate "automatically encrypt output" }, 804*7c478bd9Sstevel@tonic-gate { "autodecrypt", 805*7c478bd9Sstevel@tonic-gate "automatic decryption of data stream", 806*7c478bd9Sstevel@tonic-gate EncryptAutoDec, 807*7c478bd9Sstevel@tonic-gate 0, 808*7c478bd9Sstevel@tonic-gate "automatically decrypt input" }, 809*7c478bd9Sstevel@tonic-gate { "verbose_encrypt", 810*7c478bd9Sstevel@tonic-gate "verbose encryption output", 811*7c478bd9Sstevel@tonic-gate EncryptVerbose, 812*7c478bd9Sstevel@tonic-gate 0, 813*7c478bd9Sstevel@tonic-gate "print verbose encryption output" }, 814*7c478bd9Sstevel@tonic-gate { "encdebug", 815*7c478bd9Sstevel@tonic-gate "encryption debugging", 816*7c478bd9Sstevel@tonic-gate EncryptDebug, 817*7c478bd9Sstevel@tonic-gate 0, 818*7c478bd9Sstevel@tonic-gate "print encryption debugging information" }, 819*7c478bd9Sstevel@tonic-gate { "skiprc", 820*7c478bd9Sstevel@tonic-gate "don't read ~/.telnetrc file", 821*7c478bd9Sstevel@tonic-gate 0, 822*7c478bd9Sstevel@tonic-gate &skiprc, 823*7c478bd9Sstevel@tonic-gate "skip reading of ~/.telnetrc file" }, 824*7c478bd9Sstevel@tonic-gate { "binary", 825*7c478bd9Sstevel@tonic-gate "sending and receiving of binary data", 826*7c478bd9Sstevel@tonic-gate togbinary, 827*7c478bd9Sstevel@tonic-gate 0, 828*7c478bd9Sstevel@tonic-gate 0 }, 829*7c478bd9Sstevel@tonic-gate { "inbinary", 830*7c478bd9Sstevel@tonic-gate "receiving of binary data", 831*7c478bd9Sstevel@tonic-gate togrbinary, 832*7c478bd9Sstevel@tonic-gate 0, 833*7c478bd9Sstevel@tonic-gate 0 }, 834*7c478bd9Sstevel@tonic-gate { "outbinary", 835*7c478bd9Sstevel@tonic-gate "sending of binary data", 836*7c478bd9Sstevel@tonic-gate togxbinary, 837*7c478bd9Sstevel@tonic-gate 0, 838*7c478bd9Sstevel@tonic-gate 0 }, 839*7c478bd9Sstevel@tonic-gate { "crlf", 840*7c478bd9Sstevel@tonic-gate "sending carriage returns as telnet <CR><LF>", 841*7c478bd9Sstevel@tonic-gate togcrlf, 842*7c478bd9Sstevel@tonic-gate &crlf, 843*7c478bd9Sstevel@tonic-gate 0 }, 844*7c478bd9Sstevel@tonic-gate { "crmod", 845*7c478bd9Sstevel@tonic-gate "mapping of received carriage returns", 846*7c478bd9Sstevel@tonic-gate 0, 847*7c478bd9Sstevel@tonic-gate &crmod, 848*7c478bd9Sstevel@tonic-gate "map carriage return on output" }, 849*7c478bd9Sstevel@tonic-gate { "localchars", 850*7c478bd9Sstevel@tonic-gate "local recognition of certain control characters", 851*7c478bd9Sstevel@tonic-gate lclchars, 852*7c478bd9Sstevel@tonic-gate &localchars, 853*7c478bd9Sstevel@tonic-gate "recognize certain control characters" }, 854*7c478bd9Sstevel@tonic-gate { " ", "", 0 }, /* empty line */ 855*7c478bd9Sstevel@tonic-gate { "debug", 856*7c478bd9Sstevel@tonic-gate "debugging", 857*7c478bd9Sstevel@tonic-gate togdebug, 858*7c478bd9Sstevel@tonic-gate &debug, 859*7c478bd9Sstevel@tonic-gate "turn on socket level debugging" }, 860*7c478bd9Sstevel@tonic-gate { "netdata", 861*7c478bd9Sstevel@tonic-gate "printing of hexadecimal network data (debugging)", 862*7c478bd9Sstevel@tonic-gate 0, 863*7c478bd9Sstevel@tonic-gate &netdata, 864*7c478bd9Sstevel@tonic-gate "print hexadecimal representation of network traffic" }, 865*7c478bd9Sstevel@tonic-gate { "prettydump", 866*7c478bd9Sstevel@tonic-gate "output of \"netdata\" to user readable format (debugging)", 867*7c478bd9Sstevel@tonic-gate 0, 868*7c478bd9Sstevel@tonic-gate &prettydump, 869*7c478bd9Sstevel@tonic-gate "print user readable output for \"netdata\"" }, 870*7c478bd9Sstevel@tonic-gate { "options", 871*7c478bd9Sstevel@tonic-gate "viewing of options processing (debugging)", 872*7c478bd9Sstevel@tonic-gate 0, 873*7c478bd9Sstevel@tonic-gate &showoptions, 874*7c478bd9Sstevel@tonic-gate "show option processing" }, 875*7c478bd9Sstevel@tonic-gate { "termdata", 876*7c478bd9Sstevel@tonic-gate "(debugging) toggle printing of hexadecimal terminal data", 877*7c478bd9Sstevel@tonic-gate 0, 878*7c478bd9Sstevel@tonic-gate &termdata, 879*7c478bd9Sstevel@tonic-gate "print hexadecimal representation of terminal traffic" }, 880*7c478bd9Sstevel@tonic-gate { "?", 881*7c478bd9Sstevel@tonic-gate 0, 882*7c478bd9Sstevel@tonic-gate togglehelp }, 883*7c478bd9Sstevel@tonic-gate { "help", 884*7c478bd9Sstevel@tonic-gate 0, 885*7c478bd9Sstevel@tonic-gate togglehelp }, 886*7c478bd9Sstevel@tonic-gate { 0 } 887*7c478bd9Sstevel@tonic-gate }; 888*7c478bd9Sstevel@tonic-gate 889*7c478bd9Sstevel@tonic-gate static int 890*7c478bd9Sstevel@tonic-gate togglehelp() 891*7c478bd9Sstevel@tonic-gate { 892*7c478bd9Sstevel@tonic-gate struct togglelist *c; 893*7c478bd9Sstevel@tonic-gate 894*7c478bd9Sstevel@tonic-gate for (c = Togglelist; c->name; c++) { 895*7c478bd9Sstevel@tonic-gate if (c->help) { 896*7c478bd9Sstevel@tonic-gate if (*c->help) 897*7c478bd9Sstevel@tonic-gate (void) printf( 898*7c478bd9Sstevel@tonic-gate "%-15s toggle %s\n", c->name, c->help); 899*7c478bd9Sstevel@tonic-gate else 900*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 901*7c478bd9Sstevel@tonic-gate } 902*7c478bd9Sstevel@tonic-gate } 903*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 904*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", "?", "display help information"); 905*7c478bd9Sstevel@tonic-gate return (0); 906*7c478bd9Sstevel@tonic-gate } 907*7c478bd9Sstevel@tonic-gate 908*7c478bd9Sstevel@tonic-gate static void 909*7c478bd9Sstevel@tonic-gate settogglehelp(set) 910*7c478bd9Sstevel@tonic-gate int set; 911*7c478bd9Sstevel@tonic-gate { 912*7c478bd9Sstevel@tonic-gate struct togglelist *c; 913*7c478bd9Sstevel@tonic-gate 914*7c478bd9Sstevel@tonic-gate for (c = Togglelist; c->name; c++) { 915*7c478bd9Sstevel@tonic-gate if (c->help) { 916*7c478bd9Sstevel@tonic-gate if (*c->help) 917*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s %s\n", c->name, 918*7c478bd9Sstevel@tonic-gate set ? "enable" : "disable", c->help); 919*7c478bd9Sstevel@tonic-gate else 920*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 921*7c478bd9Sstevel@tonic-gate } 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate } 924*7c478bd9Sstevel@tonic-gate 925*7c478bd9Sstevel@tonic-gate #define GETTOGGLE(name) (struct togglelist *) \ 926*7c478bd9Sstevel@tonic-gate genget(name, (char **)Togglelist, sizeof (struct togglelist)) 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate static int 929*7c478bd9Sstevel@tonic-gate toggle(argc, argv) 930*7c478bd9Sstevel@tonic-gate int argc; 931*7c478bd9Sstevel@tonic-gate char *argv[]; 932*7c478bd9Sstevel@tonic-gate { 933*7c478bd9Sstevel@tonic-gate int retval = 1; 934*7c478bd9Sstevel@tonic-gate char *name; 935*7c478bd9Sstevel@tonic-gate struct togglelist *c; 936*7c478bd9Sstevel@tonic-gate 937*7c478bd9Sstevel@tonic-gate if (argc < 2) { 938*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 939*7c478bd9Sstevel@tonic-gate "Need an argument to 'toggle' command. " 940*7c478bd9Sstevel@tonic-gate "'toggle ?' for help.\n"); 941*7c478bd9Sstevel@tonic-gate return (0); 942*7c478bd9Sstevel@tonic-gate } 943*7c478bd9Sstevel@tonic-gate argc--; 944*7c478bd9Sstevel@tonic-gate argv++; 945*7c478bd9Sstevel@tonic-gate while (argc--) { 946*7c478bd9Sstevel@tonic-gate name = *argv++; 947*7c478bd9Sstevel@tonic-gate c = GETTOGGLE(name); 948*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 949*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 950*7c478bd9Sstevel@tonic-gate "('toggle ?' for help).\n", name); 951*7c478bd9Sstevel@tonic-gate return (0); 952*7c478bd9Sstevel@tonic-gate } else if (c == 0) { 953*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 954*7c478bd9Sstevel@tonic-gate "('toggle ?' for help).\n", name); 955*7c478bd9Sstevel@tonic-gate return (0); 956*7c478bd9Sstevel@tonic-gate } else { 957*7c478bd9Sstevel@tonic-gate if (c->variable) { 958*7c478bd9Sstevel@tonic-gate *c->variable = !*c->variable; /* invert it */ 959*7c478bd9Sstevel@tonic-gate if (c->actionexplanation) { 960*7c478bd9Sstevel@tonic-gate (void) printf("%s %s.\n", 961*7c478bd9Sstevel@tonic-gate *c->variable ? "Will" : "Won't", 962*7c478bd9Sstevel@tonic-gate c->actionexplanation); 963*7c478bd9Sstevel@tonic-gate } 964*7c478bd9Sstevel@tonic-gate } 965*7c478bd9Sstevel@tonic-gate if (c->handler) { 966*7c478bd9Sstevel@tonic-gate retval &= (*c->handler)(-1); 967*7c478bd9Sstevel@tonic-gate } 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate } 970*7c478bd9Sstevel@tonic-gate return (retval); 971*7c478bd9Sstevel@tonic-gate } 972*7c478bd9Sstevel@tonic-gate 973*7c478bd9Sstevel@tonic-gate /* 974*7c478bd9Sstevel@tonic-gate * The following perform the "set" command. 975*7c478bd9Sstevel@tonic-gate */ 976*7c478bd9Sstevel@tonic-gate 977*7c478bd9Sstevel@tonic-gate #ifdef USE_TERMIO 978*7c478bd9Sstevel@tonic-gate struct termio new_tc = { 0 }; 979*7c478bd9Sstevel@tonic-gate #endif 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate struct setlist { 982*7c478bd9Sstevel@tonic-gate char *name; /* name */ 983*7c478bd9Sstevel@tonic-gate char *help; /* help information */ 984*7c478bd9Sstevel@tonic-gate void (*handler)(); 985*7c478bd9Sstevel@tonic-gate cc_t *charp; /* where it is located at */ 986*7c478bd9Sstevel@tonic-gate }; 987*7c478bd9Sstevel@tonic-gate 988*7c478bd9Sstevel@tonic-gate static struct setlist Setlist[] = { 989*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 990*7c478bd9Sstevel@tonic-gate { "echo", "character to toggle local echoing on/off", 0, &echoc }, 991*7c478bd9Sstevel@tonic-gate #endif 992*7c478bd9Sstevel@tonic-gate { "escape", "character to escape back to telnet command mode", 0, 993*7c478bd9Sstevel@tonic-gate &escape }, 994*7c478bd9Sstevel@tonic-gate { "rlogin", "rlogin escape character", 0, &rlogin }, 995*7c478bd9Sstevel@tonic-gate { "tracefile", "file to write trace information to", SetNetTrace, 996*7c478bd9Sstevel@tonic-gate (cc_t *)NetTraceFile}, 997*7c478bd9Sstevel@tonic-gate { " ", "" }, 998*7c478bd9Sstevel@tonic-gate { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 999*7c478bd9Sstevel@tonic-gate { "flushoutput", "character to cause an Abort Output", 0, 1000*7c478bd9Sstevel@tonic-gate termFlushCharp }, 1001*7c478bd9Sstevel@tonic-gate { "interrupt", "character to cause an Interrupt Process", 0, 1002*7c478bd9Sstevel@tonic-gate termIntCharp }, 1003*7c478bd9Sstevel@tonic-gate { "quit", "character to cause an Abort process", 0, termQuitCharp }, 1004*7c478bd9Sstevel@tonic-gate { "eof", "character to cause an EOF ", 0, termEofCharp }, 1005*7c478bd9Sstevel@tonic-gate { " ", "" }, 1006*7c478bd9Sstevel@tonic-gate { " ", "The following are for local editing in linemode", 0, 0 }, 1007*7c478bd9Sstevel@tonic-gate { "erase", "character to use to erase a character", 0, termEraseCharp }, 1008*7c478bd9Sstevel@tonic-gate { "kill", "character to use to erase a line", 0, termKillCharp }, 1009*7c478bd9Sstevel@tonic-gate { "lnext", "character to use for literal next", 0, 1010*7c478bd9Sstevel@tonic-gate termLiteralNextCharp }, 1011*7c478bd9Sstevel@tonic-gate { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, 1012*7c478bd9Sstevel@tonic-gate { "reprint", "character to use for line reprint", 0, termRprntCharp }, 1013*7c478bd9Sstevel@tonic-gate { "worderase", "character to use to erase a word", 0, termWerasCharp }, 1014*7c478bd9Sstevel@tonic-gate { "start", "character to use for XON", 0, termStartCharp }, 1015*7c478bd9Sstevel@tonic-gate { "stop", "character to use for XOFF", 0, termStopCharp }, 1016*7c478bd9Sstevel@tonic-gate { "forw1", "alternate end of line character", 0, termForw1Charp }, 1017*7c478bd9Sstevel@tonic-gate { "forw2", "alternate end of line character", 0, termForw2Charp }, 1018*7c478bd9Sstevel@tonic-gate { "ayt", "alternate AYT character", 0, termAytCharp }, 1019*7c478bd9Sstevel@tonic-gate { 0 } 1020*7c478bd9Sstevel@tonic-gate }; 1021*7c478bd9Sstevel@tonic-gate 1022*7c478bd9Sstevel@tonic-gate static struct setlist * 1023*7c478bd9Sstevel@tonic-gate getset(name) 1024*7c478bd9Sstevel@tonic-gate char *name; 1025*7c478bd9Sstevel@tonic-gate { 1026*7c478bd9Sstevel@tonic-gate return ((struct setlist *) 1027*7c478bd9Sstevel@tonic-gate genget(name, (char **)Setlist, sizeof (struct setlist))); 1028*7c478bd9Sstevel@tonic-gate } 1029*7c478bd9Sstevel@tonic-gate 1030*7c478bd9Sstevel@tonic-gate void 1031*7c478bd9Sstevel@tonic-gate set_escape_char(s) 1032*7c478bd9Sstevel@tonic-gate char *s; 1033*7c478bd9Sstevel@tonic-gate { 1034*7c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) { 1035*7c478bd9Sstevel@tonic-gate rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 1036*7c478bd9Sstevel@tonic-gate (void) printf("Telnet rlogin escape character is '%s'.\n", 1037*7c478bd9Sstevel@tonic-gate control(rlogin)); 1038*7c478bd9Sstevel@tonic-gate } else { 1039*7c478bd9Sstevel@tonic-gate escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 1040*7c478bd9Sstevel@tonic-gate (void) printf("Telnet escape character is '%s'.\n", 1041*7c478bd9Sstevel@tonic-gate esc_control(escape)); 1042*7c478bd9Sstevel@tonic-gate } 1043*7c478bd9Sstevel@tonic-gate } 1044*7c478bd9Sstevel@tonic-gate 1045*7c478bd9Sstevel@tonic-gate static int 1046*7c478bd9Sstevel@tonic-gate setcmd(argc, argv) 1047*7c478bd9Sstevel@tonic-gate int argc; 1048*7c478bd9Sstevel@tonic-gate char *argv[]; 1049*7c478bd9Sstevel@tonic-gate { 1050*7c478bd9Sstevel@tonic-gate int value; 1051*7c478bd9Sstevel@tonic-gate struct setlist *ct; 1052*7c478bd9Sstevel@tonic-gate struct togglelist *c; 1053*7c478bd9Sstevel@tonic-gate 1054*7c478bd9Sstevel@tonic-gate if (argc < 2 || argc > 3) { 1055*7c478bd9Sstevel@tonic-gate (void) printf( 1056*7c478bd9Sstevel@tonic-gate "Format is 'set Name Value'\n'set ?' for help.\n"); 1057*7c478bd9Sstevel@tonic-gate return (0); 1058*7c478bd9Sstevel@tonic-gate } 1059*7c478bd9Sstevel@tonic-gate if ((argc == 2) && 1060*7c478bd9Sstevel@tonic-gate (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 1061*7c478bd9Sstevel@tonic-gate for (ct = Setlist; ct->name; ct++) 1062*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", ct->name, ct->help); 1063*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1064*7c478bd9Sstevel@tonic-gate settogglehelp(1); 1065*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", "?", "display help information"); 1066*7c478bd9Sstevel@tonic-gate return (0); 1067*7c478bd9Sstevel@tonic-gate } 1068*7c478bd9Sstevel@tonic-gate 1069*7c478bd9Sstevel@tonic-gate ct = getset(argv[1]); 1070*7c478bd9Sstevel@tonic-gate if (ct == 0) { 1071*7c478bd9Sstevel@tonic-gate c = GETTOGGLE(argv[1]); 1072*7c478bd9Sstevel@tonic-gate if (c == 0) { 1073*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 1074*7c478bd9Sstevel@tonic-gate "('set ?' for help).\n", argv[1]); 1075*7c478bd9Sstevel@tonic-gate return (0); 1076*7c478bd9Sstevel@tonic-gate } else if (Ambiguous(c)) { 1077*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 1078*7c478bd9Sstevel@tonic-gate "('set ?' for help).\n", argv[1]); 1079*7c478bd9Sstevel@tonic-gate return (0); 1080*7c478bd9Sstevel@tonic-gate } 1081*7c478bd9Sstevel@tonic-gate if (c->variable) { 1082*7c478bd9Sstevel@tonic-gate if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 1083*7c478bd9Sstevel@tonic-gate *c->variable = 1; 1084*7c478bd9Sstevel@tonic-gate else if (strcmp("off", argv[2]) == 0) 1085*7c478bd9Sstevel@tonic-gate *c->variable = 0; 1086*7c478bd9Sstevel@tonic-gate else { 1087*7c478bd9Sstevel@tonic-gate (void) printf( 1088*7c478bd9Sstevel@tonic-gate "Format is 'set togglename [on|off]'\n" 1089*7c478bd9Sstevel@tonic-gate "'set ?' for help.\n"); 1090*7c478bd9Sstevel@tonic-gate return (0); 1091*7c478bd9Sstevel@tonic-gate } 1092*7c478bd9Sstevel@tonic-gate if (c->actionexplanation) { 1093*7c478bd9Sstevel@tonic-gate (void) printf("%s %s.\n", 1094*7c478bd9Sstevel@tonic-gate *c->variable? "Will" : "Won't", 1095*7c478bd9Sstevel@tonic-gate c->actionexplanation); 1096*7c478bd9Sstevel@tonic-gate } 1097*7c478bd9Sstevel@tonic-gate } 1098*7c478bd9Sstevel@tonic-gate if (c->handler) 1099*7c478bd9Sstevel@tonic-gate (*c->handler)(1); 1100*7c478bd9Sstevel@tonic-gate } else if (argc != 3) { 1101*7c478bd9Sstevel@tonic-gate (void) printf( 1102*7c478bd9Sstevel@tonic-gate "Format is 'set Name Value'\n'set ?' for help.\n"); 1103*7c478bd9Sstevel@tonic-gate return (0); 1104*7c478bd9Sstevel@tonic-gate } else if (Ambiguous(ct)) { 1105*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1106*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); 1107*7c478bd9Sstevel@tonic-gate return (0); 1108*7c478bd9Sstevel@tonic-gate } else if (ct->handler) { 1109*7c478bd9Sstevel@tonic-gate (*ct->handler)(argv[2]); 1110*7c478bd9Sstevel@tonic-gate (void) printf( 1111*7c478bd9Sstevel@tonic-gate "%s set to \"%s\".\n", ct->name, (char *)ct->charp); 1112*7c478bd9Sstevel@tonic-gate } else { 1113*7c478bd9Sstevel@tonic-gate if (strcmp("off", argv[2])) { 1114*7c478bd9Sstevel@tonic-gate value = special(argv[2]); 1115*7c478bd9Sstevel@tonic-gate } else { 1116*7c478bd9Sstevel@tonic-gate value = _POSIX_VDISABLE; 1117*7c478bd9Sstevel@tonic-gate } 1118*7c478bd9Sstevel@tonic-gate *(ct->charp) = (cc_t)value; 1119*7c478bd9Sstevel@tonic-gate (void) printf("%s character is '%s'.\n", ct->name, 1120*7c478bd9Sstevel@tonic-gate control(*(ct->charp))); 1121*7c478bd9Sstevel@tonic-gate } 1122*7c478bd9Sstevel@tonic-gate slc_check(); 1123*7c478bd9Sstevel@tonic-gate return (1); 1124*7c478bd9Sstevel@tonic-gate } 1125*7c478bd9Sstevel@tonic-gate 1126*7c478bd9Sstevel@tonic-gate static int 1127*7c478bd9Sstevel@tonic-gate unsetcmd(argc, argv) 1128*7c478bd9Sstevel@tonic-gate int argc; 1129*7c478bd9Sstevel@tonic-gate char *argv[]; 1130*7c478bd9Sstevel@tonic-gate { 1131*7c478bd9Sstevel@tonic-gate struct setlist *ct; 1132*7c478bd9Sstevel@tonic-gate struct togglelist *c; 1133*7c478bd9Sstevel@tonic-gate register char *name; 1134*7c478bd9Sstevel@tonic-gate 1135*7c478bd9Sstevel@tonic-gate if (argc < 2) { 1136*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Need an argument to 'unset' command. " 1137*7c478bd9Sstevel@tonic-gate "'unset ?' for help.\n"); 1138*7c478bd9Sstevel@tonic-gate return (0); 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 1141*7c478bd9Sstevel@tonic-gate for (ct = Setlist; ct->name; ct++) 1142*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", ct->name, ct->help); 1143*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1144*7c478bd9Sstevel@tonic-gate settogglehelp(0); 1145*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", "?", "display help information"); 1146*7c478bd9Sstevel@tonic-gate return (0); 1147*7c478bd9Sstevel@tonic-gate } 1148*7c478bd9Sstevel@tonic-gate 1149*7c478bd9Sstevel@tonic-gate argc--; 1150*7c478bd9Sstevel@tonic-gate argv++; 1151*7c478bd9Sstevel@tonic-gate while (argc--) { 1152*7c478bd9Sstevel@tonic-gate name = *argv++; 1153*7c478bd9Sstevel@tonic-gate ct = getset(name); 1154*7c478bd9Sstevel@tonic-gate if (ct == 0) { 1155*7c478bd9Sstevel@tonic-gate c = GETTOGGLE(name); 1156*7c478bd9Sstevel@tonic-gate if (c == 0) { 1157*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 1158*7c478bd9Sstevel@tonic-gate "('unset ?' for help).\n", name); 1159*7c478bd9Sstevel@tonic-gate return (0); 1160*7c478bd9Sstevel@tonic-gate } else if (Ambiguous(c)) { 1161*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1162*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument " 1163*7c478bd9Sstevel@tonic-gate "('unset ?' for help).\n", name); 1164*7c478bd9Sstevel@tonic-gate return (0); 1165*7c478bd9Sstevel@tonic-gate } 1166*7c478bd9Sstevel@tonic-gate if (c->variable) { 1167*7c478bd9Sstevel@tonic-gate *c->variable = 0; 1168*7c478bd9Sstevel@tonic-gate if (c->actionexplanation) { 1169*7c478bd9Sstevel@tonic-gate (void) printf("%s %s.\n", 1170*7c478bd9Sstevel@tonic-gate *c->variable? "Will" : "Won't", 1171*7c478bd9Sstevel@tonic-gate c->actionexplanation); 1172*7c478bd9Sstevel@tonic-gate } 1173*7c478bd9Sstevel@tonic-gate } 1174*7c478bd9Sstevel@tonic-gate if (c->handler) 1175*7c478bd9Sstevel@tonic-gate (*c->handler)(0); 1176*7c478bd9Sstevel@tonic-gate } else if (Ambiguous(ct)) { 1177*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 1178*7c478bd9Sstevel@tonic-gate "('unset ?' for help).\n", name); 1179*7c478bd9Sstevel@tonic-gate return (0); 1180*7c478bd9Sstevel@tonic-gate } else if (ct->handler) { 1181*7c478bd9Sstevel@tonic-gate (*ct->handler)(0); 1182*7c478bd9Sstevel@tonic-gate (void) printf("%s reset to \"%s\".\n", ct->name, 1183*7c478bd9Sstevel@tonic-gate (char *)ct->charp); 1184*7c478bd9Sstevel@tonic-gate } else { 1185*7c478bd9Sstevel@tonic-gate *(ct->charp) = _POSIX_VDISABLE; 1186*7c478bd9Sstevel@tonic-gate (void) printf("%s character is '%s'.\n", ct->name, 1187*7c478bd9Sstevel@tonic-gate control(*(ct->charp))); 1188*7c478bd9Sstevel@tonic-gate } 1189*7c478bd9Sstevel@tonic-gate } 1190*7c478bd9Sstevel@tonic-gate return (1); 1191*7c478bd9Sstevel@tonic-gate } 1192*7c478bd9Sstevel@tonic-gate 1193*7c478bd9Sstevel@tonic-gate /* 1194*7c478bd9Sstevel@tonic-gate * The following are the data structures and routines for the 1195*7c478bd9Sstevel@tonic-gate * 'mode' command. 1196*7c478bd9Sstevel@tonic-gate */ 1197*7c478bd9Sstevel@tonic-gate extern int reqd_linemode; 1198*7c478bd9Sstevel@tonic-gate 1199*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 1200*7c478bd9Sstevel@tonic-gate extern int kludgelinemode; 1201*7c478bd9Sstevel@tonic-gate 1202*7c478bd9Sstevel@tonic-gate static int 1203*7c478bd9Sstevel@tonic-gate dokludgemode() 1204*7c478bd9Sstevel@tonic-gate { 1205*7c478bd9Sstevel@tonic-gate kludgelinemode = 1; 1206*7c478bd9Sstevel@tonic-gate send_wont(TELOPT_LINEMODE, 1); 1207*7c478bd9Sstevel@tonic-gate send_dont(TELOPT_SGA, 1); 1208*7c478bd9Sstevel@tonic-gate send_dont(TELOPT_ECHO, 1); 1209*7c478bd9Sstevel@tonic-gate /* 1210*7c478bd9Sstevel@tonic-gate * If processing the .telnetrc file, keep track of linemode and/or 1211*7c478bd9Sstevel@tonic-gate * kludgelinemode requests which are processed before initial option 1212*7c478bd9Sstevel@tonic-gate * negotiations occur. 1213*7c478bd9Sstevel@tonic-gate */ 1214*7c478bd9Sstevel@tonic-gate if (doing_rc) 1215*7c478bd9Sstevel@tonic-gate reqd_linemode = 1; 1216*7c478bd9Sstevel@tonic-gate return (1); 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate #endif 1219*7c478bd9Sstevel@tonic-gate 1220*7c478bd9Sstevel@tonic-gate static int 1221*7c478bd9Sstevel@tonic-gate dolinemode() 1222*7c478bd9Sstevel@tonic-gate { 1223*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 1224*7c478bd9Sstevel@tonic-gate if (kludgelinemode) 1225*7c478bd9Sstevel@tonic-gate send_dont(TELOPT_SGA, 1); 1226*7c478bd9Sstevel@tonic-gate #endif 1227*7c478bd9Sstevel@tonic-gate send_will(TELOPT_LINEMODE, 1); 1228*7c478bd9Sstevel@tonic-gate send_dont(TELOPT_ECHO, 1); 1229*7c478bd9Sstevel@tonic-gate 1230*7c478bd9Sstevel@tonic-gate /* 1231*7c478bd9Sstevel@tonic-gate * If processing the .telnetrc file, keep track of linemode and/or 1232*7c478bd9Sstevel@tonic-gate * kludgelinemode requests which are processed before initial option 1233*7c478bd9Sstevel@tonic-gate * negotiations occur. 1234*7c478bd9Sstevel@tonic-gate */ 1235*7c478bd9Sstevel@tonic-gate if (doing_rc) 1236*7c478bd9Sstevel@tonic-gate reqd_linemode = 1; 1237*7c478bd9Sstevel@tonic-gate return (1); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate static int 1241*7c478bd9Sstevel@tonic-gate docharmode() 1242*7c478bd9Sstevel@tonic-gate { 1243*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 1244*7c478bd9Sstevel@tonic-gate if (kludgelinemode) 1245*7c478bd9Sstevel@tonic-gate send_do(TELOPT_SGA, 1); 1246*7c478bd9Sstevel@tonic-gate else 1247*7c478bd9Sstevel@tonic-gate #endif 1248*7c478bd9Sstevel@tonic-gate send_wont(TELOPT_LINEMODE, 1); 1249*7c478bd9Sstevel@tonic-gate send_do(TELOPT_ECHO, 1); 1250*7c478bd9Sstevel@tonic-gate reqd_linemode = 0; 1251*7c478bd9Sstevel@tonic-gate return (1); 1252*7c478bd9Sstevel@tonic-gate } 1253*7c478bd9Sstevel@tonic-gate 1254*7c478bd9Sstevel@tonic-gate static int 1255*7c478bd9Sstevel@tonic-gate dolmmode(bit, on) 1256*7c478bd9Sstevel@tonic-gate int bit, on; 1257*7c478bd9Sstevel@tonic-gate { 1258*7c478bd9Sstevel@tonic-gate unsigned char c; 1259*7c478bd9Sstevel@tonic-gate extern int linemode; 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_LINEMODE)) { 1262*7c478bd9Sstevel@tonic-gate (void) printf("?Need to have LINEMODE option enabled first.\n"); 1263*7c478bd9Sstevel@tonic-gate (void) printf("'mode ?' for help.\n"); 1264*7c478bd9Sstevel@tonic-gate return (0); 1265*7c478bd9Sstevel@tonic-gate } 1266*7c478bd9Sstevel@tonic-gate 1267*7c478bd9Sstevel@tonic-gate if (on) 1268*7c478bd9Sstevel@tonic-gate c = (linemode | bit); 1269*7c478bd9Sstevel@tonic-gate else 1270*7c478bd9Sstevel@tonic-gate c = (linemode & ~bit); 1271*7c478bd9Sstevel@tonic-gate lm_mode(&c, 1, 1); 1272*7c478bd9Sstevel@tonic-gate return (1); 1273*7c478bd9Sstevel@tonic-gate } 1274*7c478bd9Sstevel@tonic-gate 1275*7c478bd9Sstevel@tonic-gate static int 1276*7c478bd9Sstevel@tonic-gate setmode(bit) 1277*7c478bd9Sstevel@tonic-gate { 1278*7c478bd9Sstevel@tonic-gate return (dolmmode(bit, 1)); 1279*7c478bd9Sstevel@tonic-gate } 1280*7c478bd9Sstevel@tonic-gate 1281*7c478bd9Sstevel@tonic-gate static int 1282*7c478bd9Sstevel@tonic-gate clearmode(bit) 1283*7c478bd9Sstevel@tonic-gate { 1284*7c478bd9Sstevel@tonic-gate return (dolmmode(bit, 0)); 1285*7c478bd9Sstevel@tonic-gate } 1286*7c478bd9Sstevel@tonic-gate 1287*7c478bd9Sstevel@tonic-gate struct modelist { 1288*7c478bd9Sstevel@tonic-gate char *name; /* command name */ 1289*7c478bd9Sstevel@tonic-gate char *help; /* help string */ 1290*7c478bd9Sstevel@tonic-gate int (*handler)(); /* routine which executes command */ 1291*7c478bd9Sstevel@tonic-gate int needconnect; /* Do we need to be connected to execute? */ 1292*7c478bd9Sstevel@tonic-gate int arg1; 1293*7c478bd9Sstevel@tonic-gate }; 1294*7c478bd9Sstevel@tonic-gate 1295*7c478bd9Sstevel@tonic-gate static int modehelp(); 1296*7c478bd9Sstevel@tonic-gate 1297*7c478bd9Sstevel@tonic-gate static struct modelist ModeList[] = { 1298*7c478bd9Sstevel@tonic-gate { "character", "Disable LINEMODE option", docharmode, 1 }, 1299*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 1300*7c478bd9Sstevel@tonic-gate { "", "(or disable obsolete line-by-line mode)", 0 }, 1301*7c478bd9Sstevel@tonic-gate #endif 1302*7c478bd9Sstevel@tonic-gate { "line", "Enable LINEMODE option", dolinemode, 1 }, 1303*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 1304*7c478bd9Sstevel@tonic-gate { "", "(or enable obsolete line-by-line mode)", 0 }, 1305*7c478bd9Sstevel@tonic-gate #endif 1306*7c478bd9Sstevel@tonic-gate { "", "", 0 }, 1307*7c478bd9Sstevel@tonic-gate { "", "These require the LINEMODE option to be enabled", 0 }, 1308*7c478bd9Sstevel@tonic-gate { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 1309*7c478bd9Sstevel@tonic-gate { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 1310*7c478bd9Sstevel@tonic-gate { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 1311*7c478bd9Sstevel@tonic-gate { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 1312*7c478bd9Sstevel@tonic-gate { "+edit", 0, setmode, 1, MODE_EDIT }, 1313*7c478bd9Sstevel@tonic-gate { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 1314*7c478bd9Sstevel@tonic-gate { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB }, 1315*7c478bd9Sstevel@tonic-gate { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB }, 1316*7c478bd9Sstevel@tonic-gate { "-softtabs", "Disable tab expansion", 1317*7c478bd9Sstevel@tonic-gate clearmode, 1, MODE_SOFT_TAB }, 1318*7c478bd9Sstevel@tonic-gate { "litecho", "Enable literal character echo", 1319*7c478bd9Sstevel@tonic-gate setmode, 1, MODE_LIT_ECHO }, 1320*7c478bd9Sstevel@tonic-gate { "+litecho", 0, setmode, 1, MODE_LIT_ECHO }, 1321*7c478bd9Sstevel@tonic-gate { "-litecho", "Disable literal character echo", clearmode, 1, 1322*7c478bd9Sstevel@tonic-gate MODE_LIT_ECHO }, 1323*7c478bd9Sstevel@tonic-gate { "help", 0, modehelp, 0 }, 1324*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 1325*7c478bd9Sstevel@tonic-gate { "kludgeline", 0, dokludgemode, 1 }, 1326*7c478bd9Sstevel@tonic-gate #endif 1327*7c478bd9Sstevel@tonic-gate { "", "", 0 }, 1328*7c478bd9Sstevel@tonic-gate { "?", "Print help information", modehelp, 0 }, 1329*7c478bd9Sstevel@tonic-gate { 0 }, 1330*7c478bd9Sstevel@tonic-gate }; 1331*7c478bd9Sstevel@tonic-gate 1332*7c478bd9Sstevel@tonic-gate 1333*7c478bd9Sstevel@tonic-gate static int 1334*7c478bd9Sstevel@tonic-gate modehelp() 1335*7c478bd9Sstevel@tonic-gate { 1336*7c478bd9Sstevel@tonic-gate struct modelist *mt; 1337*7c478bd9Sstevel@tonic-gate 1338*7c478bd9Sstevel@tonic-gate (void) printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 1339*7c478bd9Sstevel@tonic-gate for (mt = ModeList; mt->name; mt++) { 1340*7c478bd9Sstevel@tonic-gate if (mt->help) { 1341*7c478bd9Sstevel@tonic-gate if (*mt->help) 1342*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", mt->name, mt->help); 1343*7c478bd9Sstevel@tonic-gate else 1344*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1345*7c478bd9Sstevel@tonic-gate } 1346*7c478bd9Sstevel@tonic-gate } 1347*7c478bd9Sstevel@tonic-gate return (0); 1348*7c478bd9Sstevel@tonic-gate } 1349*7c478bd9Sstevel@tonic-gate 1350*7c478bd9Sstevel@tonic-gate #define GETMODECMD(name) (struct modelist *) \ 1351*7c478bd9Sstevel@tonic-gate genget(name, (char **)ModeList, sizeof (struct modelist)) 1352*7c478bd9Sstevel@tonic-gate 1353*7c478bd9Sstevel@tonic-gate static int 1354*7c478bd9Sstevel@tonic-gate modecmd(argc, argv) 1355*7c478bd9Sstevel@tonic-gate int argc; 1356*7c478bd9Sstevel@tonic-gate char *argv[]; 1357*7c478bd9Sstevel@tonic-gate { 1358*7c478bd9Sstevel@tonic-gate struct modelist *mt; 1359*7c478bd9Sstevel@tonic-gate 1360*7c478bd9Sstevel@tonic-gate if (argc != 2) { 1361*7c478bd9Sstevel@tonic-gate (void) printf("'mode' command requires an argument\n"); 1362*7c478bd9Sstevel@tonic-gate (void) printf("'mode ?' for help.\n"); 1363*7c478bd9Sstevel@tonic-gate } else if ((mt = GETMODECMD(argv[1])) == 0) { 1364*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1365*7c478bd9Sstevel@tonic-gate "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 1366*7c478bd9Sstevel@tonic-gate } else if (Ambiguous(mt)) { 1367*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1368*7c478bd9Sstevel@tonic-gate "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 1369*7c478bd9Sstevel@tonic-gate } else if (mt->needconnect && !connected) { 1370*7c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 1371*7c478bd9Sstevel@tonic-gate (void) printf("'mode ?' for help.\n"); 1372*7c478bd9Sstevel@tonic-gate } else if (mt->handler) { 1373*7c478bd9Sstevel@tonic-gate return (*mt->handler)(mt->arg1); 1374*7c478bd9Sstevel@tonic-gate } 1375*7c478bd9Sstevel@tonic-gate return (0); 1376*7c478bd9Sstevel@tonic-gate } 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate /* 1379*7c478bd9Sstevel@tonic-gate * The following data structures and routines implement the 1380*7c478bd9Sstevel@tonic-gate * "display" command. 1381*7c478bd9Sstevel@tonic-gate */ 1382*7c478bd9Sstevel@tonic-gate 1383*7c478bd9Sstevel@tonic-gate static int 1384*7c478bd9Sstevel@tonic-gate display(argc, argv) 1385*7c478bd9Sstevel@tonic-gate int argc; 1386*7c478bd9Sstevel@tonic-gate char *argv[]; 1387*7c478bd9Sstevel@tonic-gate { 1388*7c478bd9Sstevel@tonic-gate struct togglelist *tl; 1389*7c478bd9Sstevel@tonic-gate struct setlist *sl; 1390*7c478bd9Sstevel@tonic-gate 1391*7c478bd9Sstevel@tonic-gate #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 1392*7c478bd9Sstevel@tonic-gate if (*tl->variable) { \ 1393*7c478bd9Sstevel@tonic-gate (void) printf("will"); \ 1394*7c478bd9Sstevel@tonic-gate } else { \ 1395*7c478bd9Sstevel@tonic-gate (void) printf("won't"); \ 1396*7c478bd9Sstevel@tonic-gate } \ 1397*7c478bd9Sstevel@tonic-gate (void) printf(" %s.\n", tl->actionexplanation); \ 1398*7c478bd9Sstevel@tonic-gate } 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate #define doset(sl) if (sl->name && *sl->name != ' ') { \ 1401*7c478bd9Sstevel@tonic-gate if (sl->handler == 0) \ 1402*7c478bd9Sstevel@tonic-gate (void) printf("%-15s [%s]\n", sl->name, \ 1403*7c478bd9Sstevel@tonic-gate control(*sl->charp)); \ 1404*7c478bd9Sstevel@tonic-gate else \ 1405*7c478bd9Sstevel@tonic-gate (void) printf("%-15s \"%s\"\n", sl->name, \ 1406*7c478bd9Sstevel@tonic-gate (char *)sl->charp); \ 1407*7c478bd9Sstevel@tonic-gate } 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate if (argc == 1) { 1410*7c478bd9Sstevel@tonic-gate for (tl = Togglelist; tl->name; tl++) { 1411*7c478bd9Sstevel@tonic-gate dotog(tl); 1412*7c478bd9Sstevel@tonic-gate } 1413*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1414*7c478bd9Sstevel@tonic-gate for (sl = Setlist; sl->name; sl++) { 1415*7c478bd9Sstevel@tonic-gate doset(sl); 1416*7c478bd9Sstevel@tonic-gate } 1417*7c478bd9Sstevel@tonic-gate } else { 1418*7c478bd9Sstevel@tonic-gate int i; 1419*7c478bd9Sstevel@tonic-gate 1420*7c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 1421*7c478bd9Sstevel@tonic-gate sl = getset(argv[i]); 1422*7c478bd9Sstevel@tonic-gate tl = GETTOGGLE(argv[i]); 1423*7c478bd9Sstevel@tonic-gate if (Ambiguous(sl) || Ambiguous(tl)) { 1424*7c478bd9Sstevel@tonic-gate (void) printf( 1425*7c478bd9Sstevel@tonic-gate "?Ambiguous argument '%s'.\n", argv[i]); 1426*7c478bd9Sstevel@tonic-gate return (0); 1427*7c478bd9Sstevel@tonic-gate } else if (!sl && !tl) { 1428*7c478bd9Sstevel@tonic-gate (void) printf( 1429*7c478bd9Sstevel@tonic-gate "?Unknown argument '%s'.\n", argv[i]); 1430*7c478bd9Sstevel@tonic-gate return (0); 1431*7c478bd9Sstevel@tonic-gate } else { 1432*7c478bd9Sstevel@tonic-gate if (tl) { 1433*7c478bd9Sstevel@tonic-gate dotog(tl); 1434*7c478bd9Sstevel@tonic-gate } 1435*7c478bd9Sstevel@tonic-gate if (sl) { 1436*7c478bd9Sstevel@tonic-gate doset(sl); 1437*7c478bd9Sstevel@tonic-gate } 1438*7c478bd9Sstevel@tonic-gate } 1439*7c478bd9Sstevel@tonic-gate } 1440*7c478bd9Sstevel@tonic-gate } 1441*7c478bd9Sstevel@tonic-gate optionstatus(); 1442*7c478bd9Sstevel@tonic-gate (void) EncryptStatus(); 1443*7c478bd9Sstevel@tonic-gate return (1); 1444*7c478bd9Sstevel@tonic-gate #undef doset 1445*7c478bd9Sstevel@tonic-gate #undef dotog 1446*7c478bd9Sstevel@tonic-gate } 1447*7c478bd9Sstevel@tonic-gate 1448*7c478bd9Sstevel@tonic-gate /* 1449*7c478bd9Sstevel@tonic-gate * The following are the data structures, and many of the routines, 1450*7c478bd9Sstevel@tonic-gate * relating to command processing. 1451*7c478bd9Sstevel@tonic-gate */ 1452*7c478bd9Sstevel@tonic-gate 1453*7c478bd9Sstevel@tonic-gate /* 1454*7c478bd9Sstevel@tonic-gate * Set the escape character. 1455*7c478bd9Sstevel@tonic-gate */ 1456*7c478bd9Sstevel@tonic-gate static int 1457*7c478bd9Sstevel@tonic-gate setescape(argc, argv) 1458*7c478bd9Sstevel@tonic-gate int argc; 1459*7c478bd9Sstevel@tonic-gate char *argv[]; 1460*7c478bd9Sstevel@tonic-gate { 1461*7c478bd9Sstevel@tonic-gate register char *arg; 1462*7c478bd9Sstevel@tonic-gate char *buf = NULL; 1463*7c478bd9Sstevel@tonic-gate 1464*7c478bd9Sstevel@tonic-gate if (argc > 2) 1465*7c478bd9Sstevel@tonic-gate arg = argv[1]; 1466*7c478bd9Sstevel@tonic-gate else { 1467*7c478bd9Sstevel@tonic-gate (void) printf("new escape character: "); 1468*7c478bd9Sstevel@tonic-gate if (GetString(&buf, NULL, stdin) == NULL) { 1469*7c478bd9Sstevel@tonic-gate if (!feof(stdin)) { 1470*7c478bd9Sstevel@tonic-gate perror("can't set escape character"); 1471*7c478bd9Sstevel@tonic-gate goto setescape_exit; 1472*7c478bd9Sstevel@tonic-gate } 1473*7c478bd9Sstevel@tonic-gate } 1474*7c478bd9Sstevel@tonic-gate arg = buf; 1475*7c478bd9Sstevel@tonic-gate } 1476*7c478bd9Sstevel@tonic-gate /* we place no limitations on what escape can be. */ 1477*7c478bd9Sstevel@tonic-gate escape = arg[0]; 1478*7c478bd9Sstevel@tonic-gate (void) printf("Escape character is '%s'.\n", esc_control(escape)); 1479*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1480*7c478bd9Sstevel@tonic-gate setescape_exit: 1481*7c478bd9Sstevel@tonic-gate Free(&buf); 1482*7c478bd9Sstevel@tonic-gate return (1); 1483*7c478bd9Sstevel@tonic-gate } 1484*7c478bd9Sstevel@tonic-gate 1485*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1486*7c478bd9Sstevel@tonic-gate static int 1487*7c478bd9Sstevel@tonic-gate togcrmod(argc, argv) 1488*7c478bd9Sstevel@tonic-gate int argc; 1489*7c478bd9Sstevel@tonic-gate char *argv[]; 1490*7c478bd9Sstevel@tonic-gate { 1491*7c478bd9Sstevel@tonic-gate crmod = !crmod; 1492*7c478bd9Sstevel@tonic-gate (void) printf( 1493*7c478bd9Sstevel@tonic-gate "%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 1494*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 1495*7c478bd9Sstevel@tonic-gate return (1); 1496*7c478bd9Sstevel@tonic-gate } 1497*7c478bd9Sstevel@tonic-gate 1498*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1499*7c478bd9Sstevel@tonic-gate static int 1500*7c478bd9Sstevel@tonic-gate suspend(argc, argv) 1501*7c478bd9Sstevel@tonic-gate int argc; 1502*7c478bd9Sstevel@tonic-gate char *argv[]; 1503*7c478bd9Sstevel@tonic-gate { 1504*7c478bd9Sstevel@tonic-gate setcommandmode(); 1505*7c478bd9Sstevel@tonic-gate { 1506*7c478bd9Sstevel@tonic-gate unsigned short oldrows, oldcols, newrows, newcols; 1507*7c478bd9Sstevel@tonic-gate int err; 1508*7c478bd9Sstevel@tonic-gate 1509*7c478bd9Sstevel@tonic-gate err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 1510*7c478bd9Sstevel@tonic-gate (void) kill(0, SIGTSTP); 1511*7c478bd9Sstevel@tonic-gate /* 1512*7c478bd9Sstevel@tonic-gate * If we didn't get the window size before the SUSPEND, but we 1513*7c478bd9Sstevel@tonic-gate * can get them now (?), then send the NAWS to make sure that 1514*7c478bd9Sstevel@tonic-gate * we are set up for the right window size. 1515*7c478bd9Sstevel@tonic-gate */ 1516*7c478bd9Sstevel@tonic-gate if (TerminalWindowSize(&newrows, &newcols) && connected && 1517*7c478bd9Sstevel@tonic-gate (err || ((oldrows != newrows) || (oldcols != newcols)))) { 1518*7c478bd9Sstevel@tonic-gate sendnaws(); 1519*7c478bd9Sstevel@tonic-gate } 1520*7c478bd9Sstevel@tonic-gate } 1521*7c478bd9Sstevel@tonic-gate /* reget parameters in case they were changed */ 1522*7c478bd9Sstevel@tonic-gate TerminalSaveState(); 1523*7c478bd9Sstevel@tonic-gate setconnmode(0); 1524*7c478bd9Sstevel@tonic-gate return (1); 1525*7c478bd9Sstevel@tonic-gate } 1526*7c478bd9Sstevel@tonic-gate 1527*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1528*7c478bd9Sstevel@tonic-gate static int 1529*7c478bd9Sstevel@tonic-gate shell(argc, argv) 1530*7c478bd9Sstevel@tonic-gate int argc; 1531*7c478bd9Sstevel@tonic-gate char *argv[]; 1532*7c478bd9Sstevel@tonic-gate { 1533*7c478bd9Sstevel@tonic-gate unsigned short oldrows, oldcols, newrows, newcols; 1534*7c478bd9Sstevel@tonic-gate int err; 1535*7c478bd9Sstevel@tonic-gate 1536*7c478bd9Sstevel@tonic-gate setcommandmode(); 1537*7c478bd9Sstevel@tonic-gate 1538*7c478bd9Sstevel@tonic-gate err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 1539*7c478bd9Sstevel@tonic-gate switch (vfork()) { 1540*7c478bd9Sstevel@tonic-gate case -1: 1541*7c478bd9Sstevel@tonic-gate perror("Fork failed\n"); 1542*7c478bd9Sstevel@tonic-gate break; 1543*7c478bd9Sstevel@tonic-gate 1544*7c478bd9Sstevel@tonic-gate case 0: 1545*7c478bd9Sstevel@tonic-gate { 1546*7c478bd9Sstevel@tonic-gate /* 1547*7c478bd9Sstevel@tonic-gate * Fire up the shell in the child. 1548*7c478bd9Sstevel@tonic-gate */ 1549*7c478bd9Sstevel@tonic-gate register char *shellp, *shellname; 1550*7c478bd9Sstevel@tonic-gate 1551*7c478bd9Sstevel@tonic-gate shellp = getenv("SHELL"); 1552*7c478bd9Sstevel@tonic-gate if (shellp == NULL) 1553*7c478bd9Sstevel@tonic-gate shellp = "/bin/sh"; 1554*7c478bd9Sstevel@tonic-gate if ((shellname = strrchr(shellp, '/')) == 0) 1555*7c478bd9Sstevel@tonic-gate shellname = shellp; 1556*7c478bd9Sstevel@tonic-gate else 1557*7c478bd9Sstevel@tonic-gate shellname++; 1558*7c478bd9Sstevel@tonic-gate if (argc > 1) 1559*7c478bd9Sstevel@tonic-gate (void) execl(shellp, shellname, "-c", argv[1], 0); 1560*7c478bd9Sstevel@tonic-gate else 1561*7c478bd9Sstevel@tonic-gate (void) execl(shellp, shellname, 0); 1562*7c478bd9Sstevel@tonic-gate perror("Execl"); 1563*7c478bd9Sstevel@tonic-gate _exit(EXIT_FAILURE); 1564*7c478bd9Sstevel@tonic-gate } 1565*7c478bd9Sstevel@tonic-gate default: 1566*7c478bd9Sstevel@tonic-gate (void) wait((int *)0); /* Wait for the shell to complete */ 1567*7c478bd9Sstevel@tonic-gate 1568*7c478bd9Sstevel@tonic-gate if (TerminalWindowSize(&newrows, &newcols) && connected && 1569*7c478bd9Sstevel@tonic-gate (err || ((oldrows != newrows) || (oldcols != newcols)))) { 1570*7c478bd9Sstevel@tonic-gate sendnaws(); 1571*7c478bd9Sstevel@tonic-gate } 1572*7c478bd9Sstevel@tonic-gate break; 1573*7c478bd9Sstevel@tonic-gate } 1574*7c478bd9Sstevel@tonic-gate return (1); 1575*7c478bd9Sstevel@tonic-gate } 1576*7c478bd9Sstevel@tonic-gate 1577*7c478bd9Sstevel@tonic-gate static int 1578*7c478bd9Sstevel@tonic-gate bye(argc, argv) 1579*7c478bd9Sstevel@tonic-gate int argc; /* Number of arguments */ 1580*7c478bd9Sstevel@tonic-gate char *argv[]; /* arguments */ 1581*7c478bd9Sstevel@tonic-gate { 1582*7c478bd9Sstevel@tonic-gate extern int resettermname; 1583*7c478bd9Sstevel@tonic-gate 1584*7c478bd9Sstevel@tonic-gate if (connected) { 1585*7c478bd9Sstevel@tonic-gate (void) shutdown(net, 2); 1586*7c478bd9Sstevel@tonic-gate (void) printf("Connection to %.*s closed.\n", MAXHOSTNAMELEN, 1587*7c478bd9Sstevel@tonic-gate hostname); 1588*7c478bd9Sstevel@tonic-gate Close(&net); 1589*7c478bd9Sstevel@tonic-gate connected = 0; 1590*7c478bd9Sstevel@tonic-gate resettermname = 1; 1591*7c478bd9Sstevel@tonic-gate /* reset options */ 1592*7c478bd9Sstevel@tonic-gate (void) tninit(); 1593*7c478bd9Sstevel@tonic-gate } 1594*7c478bd9Sstevel@tonic-gate if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 1595*7c478bd9Sstevel@tonic-gate longjmp(toplevel, 1); 1596*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 1597*7c478bd9Sstevel@tonic-gate } 1598*7c478bd9Sstevel@tonic-gate return (1); /* Keep lint, etc., happy */ 1599*7c478bd9Sstevel@tonic-gate } 1600*7c478bd9Sstevel@tonic-gate 1601*7c478bd9Sstevel@tonic-gate /*VARARGS*/ 1602*7c478bd9Sstevel@tonic-gate int 1603*7c478bd9Sstevel@tonic-gate quit() 1604*7c478bd9Sstevel@tonic-gate { 1605*7c478bd9Sstevel@tonic-gate (void) call(3, bye, "bye", "fromquit"); 1606*7c478bd9Sstevel@tonic-gate Exit(EXIT_SUCCESS); 1607*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1608*7c478bd9Sstevel@tonic-gate return (1); 1609*7c478bd9Sstevel@tonic-gate } 1610*7c478bd9Sstevel@tonic-gate 1611*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1612*7c478bd9Sstevel@tonic-gate static int 1613*7c478bd9Sstevel@tonic-gate logout(argc, argv) 1614*7c478bd9Sstevel@tonic-gate int argc; 1615*7c478bd9Sstevel@tonic-gate char *argv[]; 1616*7c478bd9Sstevel@tonic-gate { 1617*7c478bd9Sstevel@tonic-gate send_do(TELOPT_LOGOUT, 1); 1618*7c478bd9Sstevel@tonic-gate (void) netflush(); 1619*7c478bd9Sstevel@tonic-gate return (1); 1620*7c478bd9Sstevel@tonic-gate } 1621*7c478bd9Sstevel@tonic-gate 1622*7c478bd9Sstevel@tonic-gate 1623*7c478bd9Sstevel@tonic-gate /* 1624*7c478bd9Sstevel@tonic-gate * The SLC command. 1625*7c478bd9Sstevel@tonic-gate */ 1626*7c478bd9Sstevel@tonic-gate 1627*7c478bd9Sstevel@tonic-gate struct slclist { 1628*7c478bd9Sstevel@tonic-gate char *name; 1629*7c478bd9Sstevel@tonic-gate char *help; 1630*7c478bd9Sstevel@tonic-gate void (*handler)(); 1631*7c478bd9Sstevel@tonic-gate int arg; 1632*7c478bd9Sstevel@tonic-gate }; 1633*7c478bd9Sstevel@tonic-gate 1634*7c478bd9Sstevel@tonic-gate static void slc_help(); 1635*7c478bd9Sstevel@tonic-gate 1636*7c478bd9Sstevel@tonic-gate static struct slclist SlcList[] = { 1637*7c478bd9Sstevel@tonic-gate { "export", "Use local special character definitions", 1638*7c478bd9Sstevel@tonic-gate slc_mode_export, 0 }, 1639*7c478bd9Sstevel@tonic-gate { "import", "Use remote special character definitions", 1640*7c478bd9Sstevel@tonic-gate slc_mode_import, 1 }, 1641*7c478bd9Sstevel@tonic-gate { "check", "Verify remote special character definitions", 1642*7c478bd9Sstevel@tonic-gate slc_mode_import, 0 }, 1643*7c478bd9Sstevel@tonic-gate { "help", 0, slc_help, 0 }, 1644*7c478bd9Sstevel@tonic-gate { "?", "Print help information", slc_help, 0 }, 1645*7c478bd9Sstevel@tonic-gate { 0 }, 1646*7c478bd9Sstevel@tonic-gate }; 1647*7c478bd9Sstevel@tonic-gate 1648*7c478bd9Sstevel@tonic-gate static void 1649*7c478bd9Sstevel@tonic-gate slc_help() 1650*7c478bd9Sstevel@tonic-gate { 1651*7c478bd9Sstevel@tonic-gate struct slclist *c; 1652*7c478bd9Sstevel@tonic-gate 1653*7c478bd9Sstevel@tonic-gate for (c = SlcList; c->name; c++) { 1654*7c478bd9Sstevel@tonic-gate if (c->help) { 1655*7c478bd9Sstevel@tonic-gate if (*c->help) 1656*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 1657*7c478bd9Sstevel@tonic-gate else 1658*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1659*7c478bd9Sstevel@tonic-gate } 1660*7c478bd9Sstevel@tonic-gate } 1661*7c478bd9Sstevel@tonic-gate } 1662*7c478bd9Sstevel@tonic-gate 1663*7c478bd9Sstevel@tonic-gate static struct slclist * 1664*7c478bd9Sstevel@tonic-gate getslc(name) 1665*7c478bd9Sstevel@tonic-gate char *name; 1666*7c478bd9Sstevel@tonic-gate { 1667*7c478bd9Sstevel@tonic-gate return ((struct slclist *) 1668*7c478bd9Sstevel@tonic-gate genget(name, (char **)SlcList, sizeof (struct slclist))); 1669*7c478bd9Sstevel@tonic-gate } 1670*7c478bd9Sstevel@tonic-gate 1671*7c478bd9Sstevel@tonic-gate static 1672*7c478bd9Sstevel@tonic-gate slccmd(argc, argv) 1673*7c478bd9Sstevel@tonic-gate int argc; 1674*7c478bd9Sstevel@tonic-gate char *argv[]; 1675*7c478bd9Sstevel@tonic-gate { 1676*7c478bd9Sstevel@tonic-gate struct slclist *c; 1677*7c478bd9Sstevel@tonic-gate 1678*7c478bd9Sstevel@tonic-gate if (argc != 2) { 1679*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1680*7c478bd9Sstevel@tonic-gate "Need an argument to 'slc' command. 'slc ?' for help.\n"); 1681*7c478bd9Sstevel@tonic-gate return (0); 1682*7c478bd9Sstevel@tonic-gate } 1683*7c478bd9Sstevel@tonic-gate c = getslc(argv[1]); 1684*7c478bd9Sstevel@tonic-gate if (c == 0) { 1685*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1686*7c478bd9Sstevel@tonic-gate "'%s': unknown argument ('slc ?' for help).\n", 1687*7c478bd9Sstevel@tonic-gate argv[1]); 1688*7c478bd9Sstevel@tonic-gate return (0); 1689*7c478bd9Sstevel@tonic-gate } 1690*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 1691*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1692*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('slc ?' for help).\n", argv[1]); 1693*7c478bd9Sstevel@tonic-gate return (0); 1694*7c478bd9Sstevel@tonic-gate } 1695*7c478bd9Sstevel@tonic-gate (*c->handler)(c->arg); 1696*7c478bd9Sstevel@tonic-gate slcstate(); 1697*7c478bd9Sstevel@tonic-gate return (1); 1698*7c478bd9Sstevel@tonic-gate } 1699*7c478bd9Sstevel@tonic-gate 1700*7c478bd9Sstevel@tonic-gate /* 1701*7c478bd9Sstevel@tonic-gate * The ENVIRON command. 1702*7c478bd9Sstevel@tonic-gate */ 1703*7c478bd9Sstevel@tonic-gate 1704*7c478bd9Sstevel@tonic-gate struct envlist { 1705*7c478bd9Sstevel@tonic-gate char *name; 1706*7c478bd9Sstevel@tonic-gate char *help; 1707*7c478bd9Sstevel@tonic-gate void (*handler)(); 1708*7c478bd9Sstevel@tonic-gate int narg; 1709*7c478bd9Sstevel@tonic-gate }; 1710*7c478bd9Sstevel@tonic-gate 1711*7c478bd9Sstevel@tonic-gate static struct env_lst *env_define(unsigned char *, unsigned char *); 1712*7c478bd9Sstevel@tonic-gate static void env_undefine(unsigned char *); 1713*7c478bd9Sstevel@tonic-gate static void env_export(unsigned char *); 1714*7c478bd9Sstevel@tonic-gate static void env_unexport(unsigned char *); 1715*7c478bd9Sstevel@tonic-gate static void env_send(unsigned char *); 1716*7c478bd9Sstevel@tonic-gate #if defined(OLD_ENVIRON) && defined(ENV_HACK) 1717*7c478bd9Sstevel@tonic-gate static void env_varval(unsigned char *); 1718*7c478bd9Sstevel@tonic-gate #endif 1719*7c478bd9Sstevel@tonic-gate static void env_list(void); 1720*7c478bd9Sstevel@tonic-gate 1721*7c478bd9Sstevel@tonic-gate static void env_help(void); 1722*7c478bd9Sstevel@tonic-gate 1723*7c478bd9Sstevel@tonic-gate static struct envlist EnvList[] = { 1724*7c478bd9Sstevel@tonic-gate { "define", "Define an environment variable", 1725*7c478bd9Sstevel@tonic-gate (void (*)())env_define, 2 }, 1726*7c478bd9Sstevel@tonic-gate { "undefine", "Undefine an environment variable", 1727*7c478bd9Sstevel@tonic-gate env_undefine, 1 }, 1728*7c478bd9Sstevel@tonic-gate { "export", "Mark an environment variable for automatic export", 1729*7c478bd9Sstevel@tonic-gate env_export, 1 }, 1730*7c478bd9Sstevel@tonic-gate { "unexport", "Don't mark an environment variable for automatic export", 1731*7c478bd9Sstevel@tonic-gate env_unexport, 1 }, 1732*7c478bd9Sstevel@tonic-gate { "send", "Send an environment variable", env_send, 1 }, 1733*7c478bd9Sstevel@tonic-gate { "list", "List the current environment variables", 1734*7c478bd9Sstevel@tonic-gate env_list, 0 }, 1735*7c478bd9Sstevel@tonic-gate #if defined(OLD_ENVIRON) && defined(ENV_HACK) 1736*7c478bd9Sstevel@tonic-gate { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 1737*7c478bd9Sstevel@tonic-gate env_varval, 1 }, 1738*7c478bd9Sstevel@tonic-gate #endif 1739*7c478bd9Sstevel@tonic-gate { "help", 0, env_help, 0 }, 1740*7c478bd9Sstevel@tonic-gate { "?", "Print help information", env_help, 0 }, 1741*7c478bd9Sstevel@tonic-gate { 0 }, 1742*7c478bd9Sstevel@tonic-gate }; 1743*7c478bd9Sstevel@tonic-gate 1744*7c478bd9Sstevel@tonic-gate static void 1745*7c478bd9Sstevel@tonic-gate env_help() 1746*7c478bd9Sstevel@tonic-gate { 1747*7c478bd9Sstevel@tonic-gate struct envlist *c; 1748*7c478bd9Sstevel@tonic-gate 1749*7c478bd9Sstevel@tonic-gate for (c = EnvList; c->name; c++) { 1750*7c478bd9Sstevel@tonic-gate if (c->help) { 1751*7c478bd9Sstevel@tonic-gate if (*c->help) 1752*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 1753*7c478bd9Sstevel@tonic-gate else 1754*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 1755*7c478bd9Sstevel@tonic-gate } 1756*7c478bd9Sstevel@tonic-gate } 1757*7c478bd9Sstevel@tonic-gate } 1758*7c478bd9Sstevel@tonic-gate 1759*7c478bd9Sstevel@tonic-gate static struct envlist * 1760*7c478bd9Sstevel@tonic-gate getenvcmd(name) 1761*7c478bd9Sstevel@tonic-gate char *name; 1762*7c478bd9Sstevel@tonic-gate { 1763*7c478bd9Sstevel@tonic-gate return ((struct envlist *) 1764*7c478bd9Sstevel@tonic-gate genget(name, (char **)EnvList, sizeof (struct envlist))); 1765*7c478bd9Sstevel@tonic-gate } 1766*7c478bd9Sstevel@tonic-gate 1767*7c478bd9Sstevel@tonic-gate static int 1768*7c478bd9Sstevel@tonic-gate env_cmd(argc, argv) 1769*7c478bd9Sstevel@tonic-gate int argc; 1770*7c478bd9Sstevel@tonic-gate char *argv[]; 1771*7c478bd9Sstevel@tonic-gate { 1772*7c478bd9Sstevel@tonic-gate struct envlist *c; 1773*7c478bd9Sstevel@tonic-gate 1774*7c478bd9Sstevel@tonic-gate if (argc < 2) { 1775*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1776*7c478bd9Sstevel@tonic-gate "Need an argument to 'environ' command. " 1777*7c478bd9Sstevel@tonic-gate "'environ ?' for help.\n"); 1778*7c478bd9Sstevel@tonic-gate return (0); 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate c = getenvcmd(argv[1]); 1781*7c478bd9Sstevel@tonic-gate if (c == 0) { 1782*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 1783*7c478bd9Sstevel@tonic-gate "('environ ?' for help).\n", argv[1]); 1784*7c478bd9Sstevel@tonic-gate return (0); 1785*7c478bd9Sstevel@tonic-gate } 1786*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 1787*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 1788*7c478bd9Sstevel@tonic-gate "('environ ?' for help).\n", argv[1]); 1789*7c478bd9Sstevel@tonic-gate return (0); 1790*7c478bd9Sstevel@tonic-gate } 1791*7c478bd9Sstevel@tonic-gate if (c->narg + 2 != argc) { 1792*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1793*7c478bd9Sstevel@tonic-gate "Need %s%d argument%s to 'environ %s' command. " 1794*7c478bd9Sstevel@tonic-gate "'environ ?' for help.\n", 1795*7c478bd9Sstevel@tonic-gate c->narg + 2 < argc ? "only " : "", 1796*7c478bd9Sstevel@tonic-gate c->narg, c->narg == 1 ? "" : "s", c->name); 1797*7c478bd9Sstevel@tonic-gate return (0); 1798*7c478bd9Sstevel@tonic-gate } 1799*7c478bd9Sstevel@tonic-gate (*c->handler)(argv[2], argv[3]); 1800*7c478bd9Sstevel@tonic-gate return (1); 1801*7c478bd9Sstevel@tonic-gate } 1802*7c478bd9Sstevel@tonic-gate 1803*7c478bd9Sstevel@tonic-gate struct env_lst { 1804*7c478bd9Sstevel@tonic-gate struct env_lst *next; /* pointer to next structure */ 1805*7c478bd9Sstevel@tonic-gate struct env_lst *prev; /* pointer to previous structure */ 1806*7c478bd9Sstevel@tonic-gate unsigned char *var; /* pointer to variable name */ 1807*7c478bd9Sstevel@tonic-gate unsigned char *value; /* pointer to variable value */ 1808*7c478bd9Sstevel@tonic-gate int export; /* 1 -> export with default list of variables */ 1809*7c478bd9Sstevel@tonic-gate int welldefined; /* A well defined variable */ 1810*7c478bd9Sstevel@tonic-gate }; 1811*7c478bd9Sstevel@tonic-gate 1812*7c478bd9Sstevel@tonic-gate static struct env_lst envlisthead; 1813*7c478bd9Sstevel@tonic-gate 1814*7c478bd9Sstevel@tonic-gate static struct env_lst * 1815*7c478bd9Sstevel@tonic-gate env_find(var) 1816*7c478bd9Sstevel@tonic-gate unsigned char *var; 1817*7c478bd9Sstevel@tonic-gate { 1818*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 1819*7c478bd9Sstevel@tonic-gate 1820*7c478bd9Sstevel@tonic-gate for (ep = envlisthead.next; ep; ep = ep->next) { 1821*7c478bd9Sstevel@tonic-gate if (strcmp((char *)ep->var, (char *)var) == 0) 1822*7c478bd9Sstevel@tonic-gate return (ep); 1823*7c478bd9Sstevel@tonic-gate } 1824*7c478bd9Sstevel@tonic-gate return (NULL); 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate 1827*7c478bd9Sstevel@tonic-gate int 1828*7c478bd9Sstevel@tonic-gate env_init() 1829*7c478bd9Sstevel@tonic-gate { 1830*7c478bd9Sstevel@tonic-gate #ifdef lint 1831*7c478bd9Sstevel@tonic-gate char **environ = NULL; 1832*7c478bd9Sstevel@tonic-gate #else /* lint */ 1833*7c478bd9Sstevel@tonic-gate extern char **environ; 1834*7c478bd9Sstevel@tonic-gate #endif /* lint */ 1835*7c478bd9Sstevel@tonic-gate char **epp, *cp; 1836*7c478bd9Sstevel@tonic-gate struct env_lst *ep; 1837*7c478bd9Sstevel@tonic-gate 1838*7c478bd9Sstevel@tonic-gate for (epp = environ; *epp; epp++) { 1839*7c478bd9Sstevel@tonic-gate if (cp = strchr(*epp, '=')) { 1840*7c478bd9Sstevel@tonic-gate *cp = '\0'; 1841*7c478bd9Sstevel@tonic-gate 1842*7c478bd9Sstevel@tonic-gate ep = env_define((unsigned char *)*epp, 1843*7c478bd9Sstevel@tonic-gate (unsigned char *)cp+1); 1844*7c478bd9Sstevel@tonic-gate if (ep == NULL) 1845*7c478bd9Sstevel@tonic-gate return (0); 1846*7c478bd9Sstevel@tonic-gate ep->export = 0; 1847*7c478bd9Sstevel@tonic-gate *cp = '='; 1848*7c478bd9Sstevel@tonic-gate } 1849*7c478bd9Sstevel@tonic-gate } 1850*7c478bd9Sstevel@tonic-gate /* 1851*7c478bd9Sstevel@tonic-gate * Special case for DISPLAY variable. If it is ":0.0" or 1852*7c478bd9Sstevel@tonic-gate * "unix:0.0", we have to get rid of "unix" and insert our 1853*7c478bd9Sstevel@tonic-gate * hostname. 1854*7c478bd9Sstevel@tonic-gate */ 1855*7c478bd9Sstevel@tonic-gate if (((ep = env_find((uchar_t *)"DISPLAY")) != NULL) && 1856*7c478bd9Sstevel@tonic-gate ((*ep->value == ':') || 1857*7c478bd9Sstevel@tonic-gate (strncmp((char *)ep->value, "unix:", 5) == 0))) { 1858*7c478bd9Sstevel@tonic-gate char hbuf[MAXHOSTNAMELEN]; 1859*7c478bd9Sstevel@tonic-gate char *cp2 = strchr((char *)ep->value, ':'); 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate if (gethostname(hbuf, MAXHOSTNAMELEN) == -1) { 1862*7c478bd9Sstevel@tonic-gate perror("telnet: cannot get hostname"); 1863*7c478bd9Sstevel@tonic-gate return (0); 1864*7c478bd9Sstevel@tonic-gate } 1865*7c478bd9Sstevel@tonic-gate hbuf[MAXHOSTNAMELEN-1] = '\0'; 1866*7c478bd9Sstevel@tonic-gate cp = malloc(strlen(hbuf) + strlen(cp2) + 1); 1867*7c478bd9Sstevel@tonic-gate if (cp == NULL) { 1868*7c478bd9Sstevel@tonic-gate perror("telnet: cannot define DISPLAY variable"); 1869*7c478bd9Sstevel@tonic-gate return (0); 1870*7c478bd9Sstevel@tonic-gate } 1871*7c478bd9Sstevel@tonic-gate (void) sprintf((char *)cp, "%s%s", hbuf, cp2); 1872*7c478bd9Sstevel@tonic-gate free(ep->value); 1873*7c478bd9Sstevel@tonic-gate ep->value = (unsigned char *)cp; 1874*7c478bd9Sstevel@tonic-gate } 1875*7c478bd9Sstevel@tonic-gate /* 1876*7c478bd9Sstevel@tonic-gate * If LOGNAME is defined, but USER is not, then add 1877*7c478bd9Sstevel@tonic-gate * USER with the value from LOGNAME. We do this because the "accepted 1878*7c478bd9Sstevel@tonic-gate * practice" is to always pass USER on the wire, but SVR4 uses 1879*7c478bd9Sstevel@tonic-gate * LOGNAME by default. 1880*7c478bd9Sstevel@tonic-gate */ 1881*7c478bd9Sstevel@tonic-gate if ((ep = env_find((uchar_t *)"LOGNAME")) != NULL && 1882*7c478bd9Sstevel@tonic-gate env_find((uchar_t *)"USER") == NULL) { 1883*7c478bd9Sstevel@tonic-gate if (env_define((unsigned char *)"USER", ep->value) != NULL) 1884*7c478bd9Sstevel@tonic-gate env_unexport((unsigned char *)"USER"); 1885*7c478bd9Sstevel@tonic-gate } 1886*7c478bd9Sstevel@tonic-gate env_export((unsigned char *)"DISPLAY"); 1887*7c478bd9Sstevel@tonic-gate env_export((unsigned char *)"PRINTER"); 1888*7c478bd9Sstevel@tonic-gate 1889*7c478bd9Sstevel@tonic-gate return (1); 1890*7c478bd9Sstevel@tonic-gate } 1891*7c478bd9Sstevel@tonic-gate 1892*7c478bd9Sstevel@tonic-gate static struct env_lst * 1893*7c478bd9Sstevel@tonic-gate env_define(var, value) 1894*7c478bd9Sstevel@tonic-gate unsigned char *var, *value; 1895*7c478bd9Sstevel@tonic-gate { 1896*7c478bd9Sstevel@tonic-gate unsigned char *tmp_value; 1897*7c478bd9Sstevel@tonic-gate unsigned char *tmp_var; 1898*7c478bd9Sstevel@tonic-gate struct env_lst *ep; 1899*7c478bd9Sstevel@tonic-gate 1900*7c478bd9Sstevel@tonic-gate /* 1901*7c478bd9Sstevel@tonic-gate * Allocate copies of arguments first, to make cleanup easier 1902*7c478bd9Sstevel@tonic-gate * in the case of allocation errors. 1903*7c478bd9Sstevel@tonic-gate */ 1904*7c478bd9Sstevel@tonic-gate tmp_var = (unsigned char *)strdup((char *)var); 1905*7c478bd9Sstevel@tonic-gate if (tmp_var == NULL) { 1906*7c478bd9Sstevel@tonic-gate perror("telnet: can't copy environment variable name"); 1907*7c478bd9Sstevel@tonic-gate return (NULL); 1908*7c478bd9Sstevel@tonic-gate } 1909*7c478bd9Sstevel@tonic-gate 1910*7c478bd9Sstevel@tonic-gate tmp_value = (unsigned char *)strdup((char *)value); 1911*7c478bd9Sstevel@tonic-gate if (tmp_value == NULL) { 1912*7c478bd9Sstevel@tonic-gate free(tmp_var); 1913*7c478bd9Sstevel@tonic-gate perror("telnet: can't copy environment variable value"); 1914*7c478bd9Sstevel@tonic-gate return (NULL); 1915*7c478bd9Sstevel@tonic-gate } 1916*7c478bd9Sstevel@tonic-gate 1917*7c478bd9Sstevel@tonic-gate if (ep = env_find(var)) { 1918*7c478bd9Sstevel@tonic-gate if (ep->var) 1919*7c478bd9Sstevel@tonic-gate free(ep->var); 1920*7c478bd9Sstevel@tonic-gate if (ep->value) 1921*7c478bd9Sstevel@tonic-gate free(ep->value); 1922*7c478bd9Sstevel@tonic-gate } else { 1923*7c478bd9Sstevel@tonic-gate ep = malloc(sizeof (struct env_lst)); 1924*7c478bd9Sstevel@tonic-gate if (ep == NULL) { 1925*7c478bd9Sstevel@tonic-gate perror("telnet: can't define environment variable"); 1926*7c478bd9Sstevel@tonic-gate free(tmp_var); 1927*7c478bd9Sstevel@tonic-gate free(tmp_value); 1928*7c478bd9Sstevel@tonic-gate return (NULL); 1929*7c478bd9Sstevel@tonic-gate } 1930*7c478bd9Sstevel@tonic-gate 1931*7c478bd9Sstevel@tonic-gate ep->next = envlisthead.next; 1932*7c478bd9Sstevel@tonic-gate envlisthead.next = ep; 1933*7c478bd9Sstevel@tonic-gate ep->prev = &envlisthead; 1934*7c478bd9Sstevel@tonic-gate if (ep->next) 1935*7c478bd9Sstevel@tonic-gate ep->next->prev = ep; 1936*7c478bd9Sstevel@tonic-gate } 1937*7c478bd9Sstevel@tonic-gate ep->welldefined = opt_welldefined((char *)var); 1938*7c478bd9Sstevel@tonic-gate ep->export = 1; 1939*7c478bd9Sstevel@tonic-gate ep->var = tmp_var; 1940*7c478bd9Sstevel@tonic-gate ep->value = tmp_value; 1941*7c478bd9Sstevel@tonic-gate 1942*7c478bd9Sstevel@tonic-gate return (ep); 1943*7c478bd9Sstevel@tonic-gate } 1944*7c478bd9Sstevel@tonic-gate 1945*7c478bd9Sstevel@tonic-gate static void 1946*7c478bd9Sstevel@tonic-gate env_undefine(var) 1947*7c478bd9Sstevel@tonic-gate unsigned char *var; 1948*7c478bd9Sstevel@tonic-gate { 1949*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 1950*7c478bd9Sstevel@tonic-gate 1951*7c478bd9Sstevel@tonic-gate if (ep = env_find(var)) { 1952*7c478bd9Sstevel@tonic-gate ep->prev->next = ep->next; 1953*7c478bd9Sstevel@tonic-gate if (ep->next) 1954*7c478bd9Sstevel@tonic-gate ep->next->prev = ep->prev; 1955*7c478bd9Sstevel@tonic-gate if (ep->var) 1956*7c478bd9Sstevel@tonic-gate free(ep->var); 1957*7c478bd9Sstevel@tonic-gate if (ep->value) 1958*7c478bd9Sstevel@tonic-gate free(ep->value); 1959*7c478bd9Sstevel@tonic-gate free(ep); 1960*7c478bd9Sstevel@tonic-gate } 1961*7c478bd9Sstevel@tonic-gate } 1962*7c478bd9Sstevel@tonic-gate 1963*7c478bd9Sstevel@tonic-gate static void 1964*7c478bd9Sstevel@tonic-gate env_export(var) 1965*7c478bd9Sstevel@tonic-gate unsigned char *var; 1966*7c478bd9Sstevel@tonic-gate { 1967*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 1968*7c478bd9Sstevel@tonic-gate 1969*7c478bd9Sstevel@tonic-gate if (ep = env_find(var)) 1970*7c478bd9Sstevel@tonic-gate ep->export = 1; 1971*7c478bd9Sstevel@tonic-gate } 1972*7c478bd9Sstevel@tonic-gate 1973*7c478bd9Sstevel@tonic-gate static void 1974*7c478bd9Sstevel@tonic-gate env_unexport(var) 1975*7c478bd9Sstevel@tonic-gate unsigned char *var; 1976*7c478bd9Sstevel@tonic-gate { 1977*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 1978*7c478bd9Sstevel@tonic-gate 1979*7c478bd9Sstevel@tonic-gate if (ep = env_find(var)) 1980*7c478bd9Sstevel@tonic-gate ep->export = 0; 1981*7c478bd9Sstevel@tonic-gate } 1982*7c478bd9Sstevel@tonic-gate 1983*7c478bd9Sstevel@tonic-gate static void 1984*7c478bd9Sstevel@tonic-gate env_send(var) 1985*7c478bd9Sstevel@tonic-gate unsigned char *var; 1986*7c478bd9Sstevel@tonic-gate { 1987*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 1988*7c478bd9Sstevel@tonic-gate 1989*7c478bd9Sstevel@tonic-gate if (my_state_is_wont(TELOPT_NEW_ENVIRON) 1990*7c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON 1991*7c478bd9Sstevel@tonic-gate /* old style */ && my_state_is_wont(TELOPT_OLD_ENVIRON) 1992*7c478bd9Sstevel@tonic-gate #endif 1993*7c478bd9Sstevel@tonic-gate /* no environ */) { 1994*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 1995*7c478bd9Sstevel@tonic-gate "Cannot send '%s': Telnet ENVIRON option not enabled\n", 1996*7c478bd9Sstevel@tonic-gate var); 1997*7c478bd9Sstevel@tonic-gate return; 1998*7c478bd9Sstevel@tonic-gate } 1999*7c478bd9Sstevel@tonic-gate ep = env_find(var); 2000*7c478bd9Sstevel@tonic-gate if (ep == 0) { 2001*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2002*7c478bd9Sstevel@tonic-gate "Cannot send '%s': variable not defined\n", var); 2003*7c478bd9Sstevel@tonic-gate return; 2004*7c478bd9Sstevel@tonic-gate } 2005*7c478bd9Sstevel@tonic-gate env_opt_start_info(); 2006*7c478bd9Sstevel@tonic-gate env_opt_add(ep->var); 2007*7c478bd9Sstevel@tonic-gate env_opt_end(0); 2008*7c478bd9Sstevel@tonic-gate } 2009*7c478bd9Sstevel@tonic-gate 2010*7c478bd9Sstevel@tonic-gate static void 2011*7c478bd9Sstevel@tonic-gate env_list() 2012*7c478bd9Sstevel@tonic-gate { 2013*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate for (ep = envlisthead.next; ep; ep = ep->next) { 2016*7c478bd9Sstevel@tonic-gate (void) printf("%c %-20s %s\n", ep->export ? '*' : ' ', 2017*7c478bd9Sstevel@tonic-gate ep->var, ep->value); 2018*7c478bd9Sstevel@tonic-gate } 2019*7c478bd9Sstevel@tonic-gate } 2020*7c478bd9Sstevel@tonic-gate 2021*7c478bd9Sstevel@tonic-gate unsigned char * 2022*7c478bd9Sstevel@tonic-gate env_default(init, welldefined) 2023*7c478bd9Sstevel@tonic-gate int init; 2024*7c478bd9Sstevel@tonic-gate { 2025*7c478bd9Sstevel@tonic-gate static struct env_lst *nep = NULL; 2026*7c478bd9Sstevel@tonic-gate 2027*7c478bd9Sstevel@tonic-gate if (init) { 2028*7c478bd9Sstevel@tonic-gate /* return value is not used */ 2029*7c478bd9Sstevel@tonic-gate nep = &envlisthead; 2030*7c478bd9Sstevel@tonic-gate return (NULL); 2031*7c478bd9Sstevel@tonic-gate } 2032*7c478bd9Sstevel@tonic-gate if (nep) { 2033*7c478bd9Sstevel@tonic-gate while ((nep = nep->next) != NULL) { 2034*7c478bd9Sstevel@tonic-gate if (nep->export && (nep->welldefined == welldefined)) 2035*7c478bd9Sstevel@tonic-gate return (nep->var); 2036*7c478bd9Sstevel@tonic-gate } 2037*7c478bd9Sstevel@tonic-gate } 2038*7c478bd9Sstevel@tonic-gate return (NULL); 2039*7c478bd9Sstevel@tonic-gate } 2040*7c478bd9Sstevel@tonic-gate 2041*7c478bd9Sstevel@tonic-gate unsigned char * 2042*7c478bd9Sstevel@tonic-gate env_getvalue(var) 2043*7c478bd9Sstevel@tonic-gate unsigned char *var; 2044*7c478bd9Sstevel@tonic-gate { 2045*7c478bd9Sstevel@tonic-gate register struct env_lst *ep; 2046*7c478bd9Sstevel@tonic-gate 2047*7c478bd9Sstevel@tonic-gate if (ep = env_find(var)) 2048*7c478bd9Sstevel@tonic-gate return (ep->value); 2049*7c478bd9Sstevel@tonic-gate return (NULL); 2050*7c478bd9Sstevel@tonic-gate } 2051*7c478bd9Sstevel@tonic-gate 2052*7c478bd9Sstevel@tonic-gate #if defined(OLD_ENVIRON) && defined(ENV_HACK) 2053*7c478bd9Sstevel@tonic-gate static void 2054*7c478bd9Sstevel@tonic-gate env_varval(what) 2055*7c478bd9Sstevel@tonic-gate unsigned char *what; 2056*7c478bd9Sstevel@tonic-gate { 2057*7c478bd9Sstevel@tonic-gate extern int old_env_var, old_env_value, env_auto; 2058*7c478bd9Sstevel@tonic-gate int len = strlen((char *)what); 2059*7c478bd9Sstevel@tonic-gate 2060*7c478bd9Sstevel@tonic-gate if (len == 0) 2061*7c478bd9Sstevel@tonic-gate goto unknown; 2062*7c478bd9Sstevel@tonic-gate 2063*7c478bd9Sstevel@tonic-gate if (strncasecmp((char *)what, "status", len) == 0) { 2064*7c478bd9Sstevel@tonic-gate if (env_auto) 2065*7c478bd9Sstevel@tonic-gate (void) printf("%s%s", "VAR and VALUE are/will be ", 2066*7c478bd9Sstevel@tonic-gate "determined automatically\n"); 2067*7c478bd9Sstevel@tonic-gate if (old_env_var == OLD_ENV_VAR) 2068*7c478bd9Sstevel@tonic-gate (void) printf( 2069*7c478bd9Sstevel@tonic-gate "VAR and VALUE set to correct definitions\n"); 2070*7c478bd9Sstevel@tonic-gate else 2071*7c478bd9Sstevel@tonic-gate (void) printf( 2072*7c478bd9Sstevel@tonic-gate "VAR and VALUE definitions are reversed\n"); 2073*7c478bd9Sstevel@tonic-gate } else if (strncasecmp((char *)what, "auto", len) == 0) { 2074*7c478bd9Sstevel@tonic-gate env_auto = 1; 2075*7c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VALUE; 2076*7c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VAR; 2077*7c478bd9Sstevel@tonic-gate } else if (strncasecmp((char *)what, "right", len) == 0) { 2078*7c478bd9Sstevel@tonic-gate env_auto = 0; 2079*7c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VAR; 2080*7c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VALUE; 2081*7c478bd9Sstevel@tonic-gate } else if (strncasecmp((char *)what, "wrong", len) == 0) { 2082*7c478bd9Sstevel@tonic-gate env_auto = 0; 2083*7c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VALUE; 2084*7c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VAR; 2085*7c478bd9Sstevel@tonic-gate } else { 2086*7c478bd9Sstevel@tonic-gate unknown: 2087*7c478bd9Sstevel@tonic-gate (void) printf( 2088*7c478bd9Sstevel@tonic-gate "Unknown \"varval\" command. (\"auto\", \"right\", " 2089*7c478bd9Sstevel@tonic-gate "\"wrong\", \"status\")\n"); 2090*7c478bd9Sstevel@tonic-gate } 2091*7c478bd9Sstevel@tonic-gate } 2092*7c478bd9Sstevel@tonic-gate #endif /* OLD_ENVIRON && ENV_HACK */ 2093*7c478bd9Sstevel@tonic-gate 2094*7c478bd9Sstevel@tonic-gate /* 2095*7c478bd9Sstevel@tonic-gate * The AUTHENTICATE command. 2096*7c478bd9Sstevel@tonic-gate */ 2097*7c478bd9Sstevel@tonic-gate 2098*7c478bd9Sstevel@tonic-gate struct authlist { 2099*7c478bd9Sstevel@tonic-gate char *name; 2100*7c478bd9Sstevel@tonic-gate char *help; 2101*7c478bd9Sstevel@tonic-gate int (*handler)(); 2102*7c478bd9Sstevel@tonic-gate int narg; 2103*7c478bd9Sstevel@tonic-gate }; 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate extern int auth_enable(char *); 2106*7c478bd9Sstevel@tonic-gate extern int auth_disable(char *); 2107*7c478bd9Sstevel@tonic-gate extern int auth_status(void); 2108*7c478bd9Sstevel@tonic-gate 2109*7c478bd9Sstevel@tonic-gate static int auth_help(void); 2110*7c478bd9Sstevel@tonic-gate 2111*7c478bd9Sstevel@tonic-gate static struct authlist AuthList[] = { 2112*7c478bd9Sstevel@tonic-gate { "status", 2113*7c478bd9Sstevel@tonic-gate "Display current status of authentication information", 2114*7c478bd9Sstevel@tonic-gate auth_status, 0 }, 2115*7c478bd9Sstevel@tonic-gate { "disable", 2116*7c478bd9Sstevel@tonic-gate "Disable an authentication type ('auth disable ?' for more)", 2117*7c478bd9Sstevel@tonic-gate auth_disable, 1 }, 2118*7c478bd9Sstevel@tonic-gate { "enable", 2119*7c478bd9Sstevel@tonic-gate "Enable an authentication type ('auth enable ?' for more)", 2120*7c478bd9Sstevel@tonic-gate auth_enable, 1 }, 2121*7c478bd9Sstevel@tonic-gate { "help", 0, auth_help, 0 }, 2122*7c478bd9Sstevel@tonic-gate { "?", "Print help information", auth_help, 0 }, 2123*7c478bd9Sstevel@tonic-gate { 0 }, 2124*7c478bd9Sstevel@tonic-gate }; 2125*7c478bd9Sstevel@tonic-gate 2126*7c478bd9Sstevel@tonic-gate static int 2127*7c478bd9Sstevel@tonic-gate auth_help(void) 2128*7c478bd9Sstevel@tonic-gate { 2129*7c478bd9Sstevel@tonic-gate struct authlist *c; 2130*7c478bd9Sstevel@tonic-gate 2131*7c478bd9Sstevel@tonic-gate for (c = AuthList; c->name; c++) { 2132*7c478bd9Sstevel@tonic-gate if (c->help) { 2133*7c478bd9Sstevel@tonic-gate if (*c->help) 2134*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 2135*7c478bd9Sstevel@tonic-gate else 2136*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 2137*7c478bd9Sstevel@tonic-gate } 2138*7c478bd9Sstevel@tonic-gate } 2139*7c478bd9Sstevel@tonic-gate return (0); 2140*7c478bd9Sstevel@tonic-gate } 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate 2143*7c478bd9Sstevel@tonic-gate static int 2144*7c478bd9Sstevel@tonic-gate auth_cmd(argc, argv) 2145*7c478bd9Sstevel@tonic-gate int argc; 2146*7c478bd9Sstevel@tonic-gate char *argv[]; 2147*7c478bd9Sstevel@tonic-gate { 2148*7c478bd9Sstevel@tonic-gate struct authlist *c; 2149*7c478bd9Sstevel@tonic-gate 2150*7c478bd9Sstevel@tonic-gate if (argc < 2) { 2151*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Need an argument to 'auth' " 2152*7c478bd9Sstevel@tonic-gate "command. 'auth ?' for help.\n"); 2153*7c478bd9Sstevel@tonic-gate return (0); 2154*7c478bd9Sstevel@tonic-gate } 2155*7c478bd9Sstevel@tonic-gate 2156*7c478bd9Sstevel@tonic-gate c = (struct authlist *) 2157*7c478bd9Sstevel@tonic-gate genget(argv[1], (char **)AuthList, sizeof (struct authlist)); 2158*7c478bd9Sstevel@tonic-gate if (c == 0) { 2159*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2160*7c478bd9Sstevel@tonic-gate "'%s': unknown argument ('auth ?' for help).\n", 2161*7c478bd9Sstevel@tonic-gate argv[1]); 2162*7c478bd9Sstevel@tonic-gate return (0); 2163*7c478bd9Sstevel@tonic-gate } 2164*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 2165*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2166*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('auth ?' for help).\n", argv[1]); 2167*7c478bd9Sstevel@tonic-gate return (0); 2168*7c478bd9Sstevel@tonic-gate } 2169*7c478bd9Sstevel@tonic-gate if (c->narg + 2 != argc) { 2170*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2171*7c478bd9Sstevel@tonic-gate "Need %s%d argument%s to 'auth %s' command." 2172*7c478bd9Sstevel@tonic-gate " 'auth ?' for help.\n", 2173*7c478bd9Sstevel@tonic-gate c->narg + 2 < argc ? "only " : "", 2174*7c478bd9Sstevel@tonic-gate c->narg, c->narg == 1 ? "" : "s", c->name); 2175*7c478bd9Sstevel@tonic-gate return (0); 2176*7c478bd9Sstevel@tonic-gate } 2177*7c478bd9Sstevel@tonic-gate return ((*c->handler)(argv[2], argv[3])); 2178*7c478bd9Sstevel@tonic-gate } 2179*7c478bd9Sstevel@tonic-gate 2180*7c478bd9Sstevel@tonic-gate /* 2181*7c478bd9Sstevel@tonic-gate * The FORWARD command. 2182*7c478bd9Sstevel@tonic-gate */ 2183*7c478bd9Sstevel@tonic-gate 2184*7c478bd9Sstevel@tonic-gate extern int forward_flags; 2185*7c478bd9Sstevel@tonic-gate 2186*7c478bd9Sstevel@tonic-gate struct forwlist { 2187*7c478bd9Sstevel@tonic-gate char *name; 2188*7c478bd9Sstevel@tonic-gate char *help; 2189*7c478bd9Sstevel@tonic-gate int (*handler)(); 2190*7c478bd9Sstevel@tonic-gate int f_flags; 2191*7c478bd9Sstevel@tonic-gate }; 2192*7c478bd9Sstevel@tonic-gate 2193*7c478bd9Sstevel@tonic-gate static int forw_status(void); 2194*7c478bd9Sstevel@tonic-gate static int forw_set(int); 2195*7c478bd9Sstevel@tonic-gate static int forw_help(void); 2196*7c478bd9Sstevel@tonic-gate 2197*7c478bd9Sstevel@tonic-gate static struct forwlist ForwList[] = { 2198*7c478bd9Sstevel@tonic-gate {"status", 2199*7c478bd9Sstevel@tonic-gate "Display current status of credential forwarding", 2200*7c478bd9Sstevel@tonic-gate forw_status, 0}, 2201*7c478bd9Sstevel@tonic-gate {"disable", 2202*7c478bd9Sstevel@tonic-gate "Disable credential forwarding", 2203*7c478bd9Sstevel@tonic-gate forw_set, 0}, 2204*7c478bd9Sstevel@tonic-gate {"enable", 2205*7c478bd9Sstevel@tonic-gate "Enable credential forwarding", 2206*7c478bd9Sstevel@tonic-gate forw_set, OPTS_FORWARD_CREDS}, 2207*7c478bd9Sstevel@tonic-gate {"forwardable", 2208*7c478bd9Sstevel@tonic-gate "Enable credential forwarding of " 2209*7c478bd9Sstevel@tonic-gate "forwardable credentials", 2210*7c478bd9Sstevel@tonic-gate forw_set, OPTS_FORWARD_CREDS | OPTS_FORWARDABLE_CREDS}, 2211*7c478bd9Sstevel@tonic-gate {"help", 2212*7c478bd9Sstevel@tonic-gate 0, 2213*7c478bd9Sstevel@tonic-gate forw_help, 0}, 2214*7c478bd9Sstevel@tonic-gate {"?", 2215*7c478bd9Sstevel@tonic-gate "Print help information", 2216*7c478bd9Sstevel@tonic-gate forw_help, 0}, 2217*7c478bd9Sstevel@tonic-gate {0}, 2218*7c478bd9Sstevel@tonic-gate }; 2219*7c478bd9Sstevel@tonic-gate 2220*7c478bd9Sstevel@tonic-gate static int 2221*7c478bd9Sstevel@tonic-gate forw_status(void) 2222*7c478bd9Sstevel@tonic-gate { 2223*7c478bd9Sstevel@tonic-gate if (forward_flags & OPTS_FORWARD_CREDS) { 2224*7c478bd9Sstevel@tonic-gate if (forward_flags & OPTS_FORWARDABLE_CREDS) 2225*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 2226*7c478bd9Sstevel@tonic-gate "Credential forwarding of " 2227*7c478bd9Sstevel@tonic-gate "forwardable credentials enabled\n")); 2228*7c478bd9Sstevel@tonic-gate else 2229*7c478bd9Sstevel@tonic-gate (void) printf(gettext( 2230*7c478bd9Sstevel@tonic-gate "Credential forwarding enabled\n")); 2231*7c478bd9Sstevel@tonic-gate } else 2232*7c478bd9Sstevel@tonic-gate (void) printf(gettext("Credential forwarding disabled\n")); 2233*7c478bd9Sstevel@tonic-gate return (0); 2234*7c478bd9Sstevel@tonic-gate } 2235*7c478bd9Sstevel@tonic-gate 2236*7c478bd9Sstevel@tonic-gate forw_set(int f_flags) 2237*7c478bd9Sstevel@tonic-gate { 2238*7c478bd9Sstevel@tonic-gate forward_flags = f_flags; 2239*7c478bd9Sstevel@tonic-gate return (0); 2240*7c478bd9Sstevel@tonic-gate } 2241*7c478bd9Sstevel@tonic-gate 2242*7c478bd9Sstevel@tonic-gate static int 2243*7c478bd9Sstevel@tonic-gate forw_help(void) 2244*7c478bd9Sstevel@tonic-gate { 2245*7c478bd9Sstevel@tonic-gate struct forwlist *c; 2246*7c478bd9Sstevel@tonic-gate 2247*7c478bd9Sstevel@tonic-gate for (c = ForwList; c->name; c++) { 2248*7c478bd9Sstevel@tonic-gate if (c->help) { 2249*7c478bd9Sstevel@tonic-gate if (*c->help) 2250*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\r\n", c->name, c->help); 2251*7c478bd9Sstevel@tonic-gate else 2252*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 2253*7c478bd9Sstevel@tonic-gate } 2254*7c478bd9Sstevel@tonic-gate } 2255*7c478bd9Sstevel@tonic-gate return (0); 2256*7c478bd9Sstevel@tonic-gate } 2257*7c478bd9Sstevel@tonic-gate 2258*7c478bd9Sstevel@tonic-gate static int 2259*7c478bd9Sstevel@tonic-gate forw_cmd(int argc, char *argv[]) 2260*7c478bd9Sstevel@tonic-gate { 2261*7c478bd9Sstevel@tonic-gate struct forwlist *c; 2262*7c478bd9Sstevel@tonic-gate 2263*7c478bd9Sstevel@tonic-gate if (argc < 2) { 2264*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2265*7c478bd9Sstevel@tonic-gate "Need an argument to 'forward' " 2266*7c478bd9Sstevel@tonic-gate "command. 'forward ?' for help.\n")); 2267*7c478bd9Sstevel@tonic-gate return (0); 2268*7c478bd9Sstevel@tonic-gate } 2269*7c478bd9Sstevel@tonic-gate c = (struct forwlist *)genget(argv[1], (char **)ForwList, 2270*7c478bd9Sstevel@tonic-gate sizeof (struct forwlist)); 2271*7c478bd9Sstevel@tonic-gate if (c == 0) { 2272*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2273*7c478bd9Sstevel@tonic-gate "'%s': unknown argument ('forward ?' for help).\n"), 2274*7c478bd9Sstevel@tonic-gate argv[1]); 2275*7c478bd9Sstevel@tonic-gate return (0); 2276*7c478bd9Sstevel@tonic-gate } 2277*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 2278*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2279*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('forward ?' for help).\n"), 2280*7c478bd9Sstevel@tonic-gate argv[1]); 2281*7c478bd9Sstevel@tonic-gate return (0); 2282*7c478bd9Sstevel@tonic-gate } 2283*7c478bd9Sstevel@tonic-gate if (argc != 2) { 2284*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2285*7c478bd9Sstevel@tonic-gate "No arguments needed to 'forward %s' command. " 2286*7c478bd9Sstevel@tonic-gate "'forward ?' for help.\n"), c->name); 2287*7c478bd9Sstevel@tonic-gate return (0); 2288*7c478bd9Sstevel@tonic-gate } 2289*7c478bd9Sstevel@tonic-gate return ((*c->handler) (c->f_flags)); 2290*7c478bd9Sstevel@tonic-gate } 2291*7c478bd9Sstevel@tonic-gate 2292*7c478bd9Sstevel@tonic-gate /* 2293*7c478bd9Sstevel@tonic-gate * The ENCRYPT command. 2294*7c478bd9Sstevel@tonic-gate */ 2295*7c478bd9Sstevel@tonic-gate 2296*7c478bd9Sstevel@tonic-gate struct encryptlist { 2297*7c478bd9Sstevel@tonic-gate char *name; 2298*7c478bd9Sstevel@tonic-gate char *help; 2299*7c478bd9Sstevel@tonic-gate int (*handler)(); 2300*7c478bd9Sstevel@tonic-gate int needconnect; 2301*7c478bd9Sstevel@tonic-gate int minarg; 2302*7c478bd9Sstevel@tonic-gate int maxarg; 2303*7c478bd9Sstevel@tonic-gate }; 2304*7c478bd9Sstevel@tonic-gate 2305*7c478bd9Sstevel@tonic-gate static int EncryptHelp(void); 2306*7c478bd9Sstevel@tonic-gate 2307*7c478bd9Sstevel@tonic-gate static struct encryptlist EncryptList[] = { 2308*7c478bd9Sstevel@tonic-gate { "enable", "Enable encryption. ('encrypt enable ?' for more)", 2309*7c478bd9Sstevel@tonic-gate EncryptEnable, 1, 1, 2 }, 2310*7c478bd9Sstevel@tonic-gate { "disable", "Disable encryption. ('encrypt disable ?' for more)", 2311*7c478bd9Sstevel@tonic-gate EncryptDisable, 0, 1, 2 }, 2312*7c478bd9Sstevel@tonic-gate { "type", "Set encryption type. ('encrypt type ?' for more)", 2313*7c478bd9Sstevel@tonic-gate EncryptType, 0, 1, 2 }, 2314*7c478bd9Sstevel@tonic-gate { "start", "Start encryption. ('encrypt start ?' for more)", 2315*7c478bd9Sstevel@tonic-gate EncryptStart, 1, 0, 1 }, 2316*7c478bd9Sstevel@tonic-gate { "stop", "Stop encryption. ('encrypt stop ?' for more)", 2317*7c478bd9Sstevel@tonic-gate EncryptStop, 1, 0, 1 }, 2318*7c478bd9Sstevel@tonic-gate { "input", "Start encrypting the input stream", 2319*7c478bd9Sstevel@tonic-gate EncryptStartInput, 1, 0, 0 }, 2320*7c478bd9Sstevel@tonic-gate { "-input", "Stop encrypting the input stream", 2321*7c478bd9Sstevel@tonic-gate EncryptStopInput, 1, 0, 0 }, 2322*7c478bd9Sstevel@tonic-gate { "output", "Start encrypting the output stream", 2323*7c478bd9Sstevel@tonic-gate EncryptStartOutput, 1, 0, 0 }, 2324*7c478bd9Sstevel@tonic-gate { "-output", "Stop encrypting the output stream", 2325*7c478bd9Sstevel@tonic-gate EncryptStopOutput, 1, 0, 0 }, 2326*7c478bd9Sstevel@tonic-gate 2327*7c478bd9Sstevel@tonic-gate { "status", "Display current status of encryption information", 2328*7c478bd9Sstevel@tonic-gate EncryptStatus, 0, 0, 0 }, 2329*7c478bd9Sstevel@tonic-gate { "help", 0, 2330*7c478bd9Sstevel@tonic-gate EncryptHelp, 0, 0, 0 }, 2331*7c478bd9Sstevel@tonic-gate { "?", "Print help information", EncryptHelp, 0, 0, 0 }, 2332*7c478bd9Sstevel@tonic-gate { 0 }, 2333*7c478bd9Sstevel@tonic-gate }; 2334*7c478bd9Sstevel@tonic-gate 2335*7c478bd9Sstevel@tonic-gate static int 2336*7c478bd9Sstevel@tonic-gate EncryptHelp(void) 2337*7c478bd9Sstevel@tonic-gate { 2338*7c478bd9Sstevel@tonic-gate struct encryptlist *c; 2339*7c478bd9Sstevel@tonic-gate 2340*7c478bd9Sstevel@tonic-gate for (c = EncryptList; c->name; c++) { 2341*7c478bd9Sstevel@tonic-gate if (c->help) { 2342*7c478bd9Sstevel@tonic-gate if (*c->help) 2343*7c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 2344*7c478bd9Sstevel@tonic-gate else 2345*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 2346*7c478bd9Sstevel@tonic-gate } 2347*7c478bd9Sstevel@tonic-gate } 2348*7c478bd9Sstevel@tonic-gate return (0); 2349*7c478bd9Sstevel@tonic-gate } 2350*7c478bd9Sstevel@tonic-gate 2351*7c478bd9Sstevel@tonic-gate static int 2352*7c478bd9Sstevel@tonic-gate encrypt_cmd(int argc, char *argv[]) 2353*7c478bd9Sstevel@tonic-gate { 2354*7c478bd9Sstevel@tonic-gate struct encryptlist *c; 2355*7c478bd9Sstevel@tonic-gate 2356*7c478bd9Sstevel@tonic-gate if (argc < 2) { 2357*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2358*7c478bd9Sstevel@tonic-gate "Need an argument to 'encrypt' command. " 2359*7c478bd9Sstevel@tonic-gate "'encrypt ?' for help.\n")); 2360*7c478bd9Sstevel@tonic-gate return (0); 2361*7c478bd9Sstevel@tonic-gate } 2362*7c478bd9Sstevel@tonic-gate 2363*7c478bd9Sstevel@tonic-gate c = (struct encryptlist *) 2364*7c478bd9Sstevel@tonic-gate genget(argv[1], (char **)EncryptList, sizeof (struct encryptlist)); 2365*7c478bd9Sstevel@tonic-gate if (c == 0) { 2366*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2367*7c478bd9Sstevel@tonic-gate "'%s': unknown argument ('encrypt ?' for help).\n"), 2368*7c478bd9Sstevel@tonic-gate argv[1]); 2369*7c478bd9Sstevel@tonic-gate return (0); 2370*7c478bd9Sstevel@tonic-gate } 2371*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 2372*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2373*7c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('encrypt ?' for help).\n"), 2374*7c478bd9Sstevel@tonic-gate argv[1]); 2375*7c478bd9Sstevel@tonic-gate return (0); 2376*7c478bd9Sstevel@tonic-gate } 2377*7c478bd9Sstevel@tonic-gate argc -= 2; 2378*7c478bd9Sstevel@tonic-gate if (argc < c->minarg || argc > c->maxarg) { 2379*7c478bd9Sstevel@tonic-gate if (c->minarg == c->maxarg) { 2380*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Need %s%d %s "), 2381*7c478bd9Sstevel@tonic-gate c->minarg < argc ? 2382*7c478bd9Sstevel@tonic-gate gettext("only ") : "", c->minarg, 2383*7c478bd9Sstevel@tonic-gate c->minarg == 1 ? 2384*7c478bd9Sstevel@tonic-gate gettext("argument") : gettext("arguments")); 2385*7c478bd9Sstevel@tonic-gate } else { 2386*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2387*7c478bd9Sstevel@tonic-gate gettext("Need %s%d-%d arguments "), 2388*7c478bd9Sstevel@tonic-gate c->maxarg < argc ? 2389*7c478bd9Sstevel@tonic-gate gettext("only ") : "", c->minarg, c->maxarg); 2390*7c478bd9Sstevel@tonic-gate } 2391*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 2392*7c478bd9Sstevel@tonic-gate "to 'encrypt %s' command. 'encrypt ?' for help.\n"), 2393*7c478bd9Sstevel@tonic-gate c->name); 2394*7c478bd9Sstevel@tonic-gate return (0); 2395*7c478bd9Sstevel@tonic-gate } 2396*7c478bd9Sstevel@tonic-gate if (c->needconnect && !connected) { 2397*7c478bd9Sstevel@tonic-gate if (!(argc && 2398*7c478bd9Sstevel@tonic-gate (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 2399*7c478bd9Sstevel@tonic-gate (void) printf( 2400*7c478bd9Sstevel@tonic-gate gettext("?Need to be connected first.\n")); 2401*7c478bd9Sstevel@tonic-gate return (0); 2402*7c478bd9Sstevel@tonic-gate } 2403*7c478bd9Sstevel@tonic-gate } 2404*7c478bd9Sstevel@tonic-gate return ((*c->handler)(argc > 0 ? argv[2] : 0, 2405*7c478bd9Sstevel@tonic-gate argc > 1 ? argv[3] : 0, argc > 2 ? argv[4] : 0)); 2406*7c478bd9Sstevel@tonic-gate } 2407*7c478bd9Sstevel@tonic-gate 2408*7c478bd9Sstevel@tonic-gate /* 2409*7c478bd9Sstevel@tonic-gate * Print status about the connection. 2410*7c478bd9Sstevel@tonic-gate */ 2411*7c478bd9Sstevel@tonic-gate static 2412*7c478bd9Sstevel@tonic-gate status(int argc, char *argv[]) 2413*7c478bd9Sstevel@tonic-gate { 2414*7c478bd9Sstevel@tonic-gate if (connected) { 2415*7c478bd9Sstevel@tonic-gate (void) printf("Connected to %s.\n", hostname); 2416*7c478bd9Sstevel@tonic-gate if ((argc < 2) || strcmp(argv[1], "notmuch")) { 2417*7c478bd9Sstevel@tonic-gate int mode = getconnmode(); 2418*7c478bd9Sstevel@tonic-gate 2419*7c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_LINEMODE)) { 2420*7c478bd9Sstevel@tonic-gate (void) printf( 2421*7c478bd9Sstevel@tonic-gate "Operating with LINEMODE option\n"); 2422*7c478bd9Sstevel@tonic-gate (void) printf( 2423*7c478bd9Sstevel@tonic-gate "%s line editing\n", (mode&MODE_EDIT) ? 2424*7c478bd9Sstevel@tonic-gate "Local" : "No"); 2425*7c478bd9Sstevel@tonic-gate (void) printf("%s catching of signals\n", 2426*7c478bd9Sstevel@tonic-gate (mode&MODE_TRAPSIG) ? "Local" : "No"); 2427*7c478bd9Sstevel@tonic-gate slcstate(); 2428*7c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 2429*7c478bd9Sstevel@tonic-gate } else if (kludgelinemode && 2430*7c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_SGA)) { 2431*7c478bd9Sstevel@tonic-gate (void) printf( 2432*7c478bd9Sstevel@tonic-gate "Operating in obsolete linemode\n"); 2433*7c478bd9Sstevel@tonic-gate #endif 2434*7c478bd9Sstevel@tonic-gate } else { 2435*7c478bd9Sstevel@tonic-gate (void) printf( 2436*7c478bd9Sstevel@tonic-gate "Operating in single character mode\n"); 2437*7c478bd9Sstevel@tonic-gate if (localchars) 2438*7c478bd9Sstevel@tonic-gate (void) printf( 2439*7c478bd9Sstevel@tonic-gate "Catching signals locally\n"); 2440*7c478bd9Sstevel@tonic-gate } 2441*7c478bd9Sstevel@tonic-gate (void) printf("%s character echo\n", (mode&MODE_ECHO) ? 2442*7c478bd9Sstevel@tonic-gate "Local" : "Remote"); 2443*7c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_LFLOW)) 2444*7c478bd9Sstevel@tonic-gate (void) printf("%s flow control\n", 2445*7c478bd9Sstevel@tonic-gate (mode&MODE_FLOW) ? "Local" : "No"); 2446*7c478bd9Sstevel@tonic-gate 2447*7c478bd9Sstevel@tonic-gate encrypt_display(); 2448*7c478bd9Sstevel@tonic-gate } 2449*7c478bd9Sstevel@tonic-gate } else { 2450*7c478bd9Sstevel@tonic-gate (void) printf("No connection.\n"); 2451*7c478bd9Sstevel@tonic-gate } 2452*7c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) 2453*7c478bd9Sstevel@tonic-gate (void) printf("Escape character is '%s'.\n", control(rlogin)); 2454*7c478bd9Sstevel@tonic-gate else 2455*7c478bd9Sstevel@tonic-gate (void) printf( 2456*7c478bd9Sstevel@tonic-gate "Escape character is '%s'.\n", esc_control(escape)); 2457*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 2458*7c478bd9Sstevel@tonic-gate return (1); 2459*7c478bd9Sstevel@tonic-gate } 2460*7c478bd9Sstevel@tonic-gate 2461*7c478bd9Sstevel@tonic-gate /* 2462*7c478bd9Sstevel@tonic-gate * Parse the user input (cmd_line_input) which should: 2463*7c478bd9Sstevel@tonic-gate * - start with the target host, or with "@" or "!@" followed by at least one 2464*7c478bd9Sstevel@tonic-gate * gateway. 2465*7c478bd9Sstevel@tonic-gate * - each host (can be literal address or hostname) can be separated by ",", 2466*7c478bd9Sstevel@tonic-gate * "@", or ",@". 2467*7c478bd9Sstevel@tonic-gate * Note that the last host is the target, all the others (if any ) are the 2468*7c478bd9Sstevel@tonic-gate * gateways. 2469*7c478bd9Sstevel@tonic-gate * 2470*7c478bd9Sstevel@tonic-gate * Returns: -1 if a library call fails, too many gateways, or parse 2471*7c478bd9Sstevel@tonic-gate * error 2472*7c478bd9Sstevel@tonic-gate * num_gw otherwise 2473*7c478bd9Sstevel@tonic-gate * On successful return, hostname_list points to a list of hosts (last one being 2474*7c478bd9Sstevel@tonic-gate * the target, others gateways), src_rtng_type points to the type of source 2475*7c478bd9Sstevel@tonic-gate * routing (strict vs. loose) 2476*7c478bd9Sstevel@tonic-gate */ 2477*7c478bd9Sstevel@tonic-gate static int 2478*7c478bd9Sstevel@tonic-gate parse_input(char *cmd_line_input, char **hostname_list, uchar_t *src_rtng_type) 2479*7c478bd9Sstevel@tonic-gate { 2480*7c478bd9Sstevel@tonic-gate char hname[MAXHOSTNAMELEN + 1]; 2481*7c478bd9Sstevel@tonic-gate char *cp; 2482*7c478bd9Sstevel@tonic-gate int gw_count; 2483*7c478bd9Sstevel@tonic-gate int i; 2484*7c478bd9Sstevel@tonic-gate 2485*7c478bd9Sstevel@tonic-gate gw_count = 0; 2486*7c478bd9Sstevel@tonic-gate cp = cmd_line_input; 2487*7c478bd9Sstevel@tonic-gate 2488*7c478bd9Sstevel@tonic-gate /* 2489*7c478bd9Sstevel@tonic-gate * Defining ICMD generates the Itelnet binary, the special version of 2490*7c478bd9Sstevel@tonic-gate * telnet which is used with firewall proxy. 2491*7c478bd9Sstevel@tonic-gate * If ICMD is defined, parse_input will treat the whole cmd_line_input 2492*7c478bd9Sstevel@tonic-gate * as the target host and set the num_gw to 0. Therefore, none of the 2493*7c478bd9Sstevel@tonic-gate * source routing related code paths will be executed. 2494*7c478bd9Sstevel@tonic-gate */ 2495*7c478bd9Sstevel@tonic-gate #ifndef ICMD 2496*7c478bd9Sstevel@tonic-gate if (*cp == '@') { 2497*7c478bd9Sstevel@tonic-gate *src_rtng_type = IPOPT_LSRR; 2498*7c478bd9Sstevel@tonic-gate cp++; 2499*7c478bd9Sstevel@tonic-gate } else if (*cp == '!') { 2500*7c478bd9Sstevel@tonic-gate *src_rtng_type = IPOPT_SSRR; 2501*7c478bd9Sstevel@tonic-gate 2502*7c478bd9Sstevel@tonic-gate /* "!" must be followed by '@' */ 2503*7c478bd9Sstevel@tonic-gate if (*(cp + 1) != '@') 2504*7c478bd9Sstevel@tonic-gate goto parse_error; 2505*7c478bd9Sstevel@tonic-gate cp += 2; 2506*7c478bd9Sstevel@tonic-gate } else { 2507*7c478bd9Sstevel@tonic-gate #endif /* ICMD */ 2508*7c478bd9Sstevel@tonic-gate /* no gateways, just the target */ 2509*7c478bd9Sstevel@tonic-gate hostname_list[0] = strdup(cp); 2510*7c478bd9Sstevel@tonic-gate if (hostname_list[0] == NULL) { 2511*7c478bd9Sstevel@tonic-gate perror("telnet: copying host name"); 2512*7c478bd9Sstevel@tonic-gate return (-1); 2513*7c478bd9Sstevel@tonic-gate } 2514*7c478bd9Sstevel@tonic-gate return (0); 2515*7c478bd9Sstevel@tonic-gate #ifndef ICMD 2516*7c478bd9Sstevel@tonic-gate } 2517*7c478bd9Sstevel@tonic-gate 2518*7c478bd9Sstevel@tonic-gate while (*cp != '\0') { 2519*7c478bd9Sstevel@tonic-gate /* 2520*7c478bd9Sstevel@tonic-gate * Identify each gateway separated by ",", "@" or ",@" and 2521*7c478bd9Sstevel@tonic-gate * store in hname[]. 2522*7c478bd9Sstevel@tonic-gate */ 2523*7c478bd9Sstevel@tonic-gate i = 0; 2524*7c478bd9Sstevel@tonic-gate while (*cp != '@' && *cp != ',' && *cp != '\0') { 2525*7c478bd9Sstevel@tonic-gate hname[i++] = *cp++; 2526*7c478bd9Sstevel@tonic-gate if (i > MAXHOSTNAMELEN) 2527*7c478bd9Sstevel@tonic-gate goto parse_error; 2528*7c478bd9Sstevel@tonic-gate } 2529*7c478bd9Sstevel@tonic-gate hname[i] = '\0'; 2530*7c478bd9Sstevel@tonic-gate 2531*7c478bd9Sstevel@tonic-gate /* 2532*7c478bd9Sstevel@tonic-gate * Two consecutive delimiters which result in a 0 length hname 2533*7c478bd9Sstevel@tonic-gate * is a parse error. 2534*7c478bd9Sstevel@tonic-gate */ 2535*7c478bd9Sstevel@tonic-gate if (i == 0) 2536*7c478bd9Sstevel@tonic-gate goto parse_error; 2537*7c478bd9Sstevel@tonic-gate 2538*7c478bd9Sstevel@tonic-gate hostname_list[gw_count] = strdup(hname); 2539*7c478bd9Sstevel@tonic-gate if (hostname_list[gw_count] == NULL) { 2540*7c478bd9Sstevel@tonic-gate perror("telnet: copying hostname from list"); 2541*7c478bd9Sstevel@tonic-gate return (-1); 2542*7c478bd9Sstevel@tonic-gate } 2543*7c478bd9Sstevel@tonic-gate 2544*7c478bd9Sstevel@tonic-gate if (++gw_count > MAXMAX_GATEWAY) { 2545*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "telnet: too many gateways\n"); 2546*7c478bd9Sstevel@tonic-gate return (-1); 2547*7c478bd9Sstevel@tonic-gate } 2548*7c478bd9Sstevel@tonic-gate 2549*7c478bd9Sstevel@tonic-gate /* Jump over the next delimiter. */ 2550*7c478bd9Sstevel@tonic-gate if (*cp != '\0') { 2551*7c478bd9Sstevel@tonic-gate /* ...gw1,@gw2... accepted */ 2552*7c478bd9Sstevel@tonic-gate if (*cp == ',' && *(cp + 1) == '@') 2553*7c478bd9Sstevel@tonic-gate cp += 2; 2554*7c478bd9Sstevel@tonic-gate else 2555*7c478bd9Sstevel@tonic-gate cp++; 2556*7c478bd9Sstevel@tonic-gate } 2557*7c478bd9Sstevel@tonic-gate } 2558*7c478bd9Sstevel@tonic-gate 2559*7c478bd9Sstevel@tonic-gate /* discount the target */ 2560*7c478bd9Sstevel@tonic-gate gw_count--; 2561*7c478bd9Sstevel@tonic-gate 2562*7c478bd9Sstevel@tonic-gate /* Any input starting with '!@' or '@' must have at least one gateway */ 2563*7c478bd9Sstevel@tonic-gate if (gw_count <= 0) 2564*7c478bd9Sstevel@tonic-gate goto parse_error; 2565*7c478bd9Sstevel@tonic-gate 2566*7c478bd9Sstevel@tonic-gate return (gw_count); 2567*7c478bd9Sstevel@tonic-gate 2568*7c478bd9Sstevel@tonic-gate parse_error: 2569*7c478bd9Sstevel@tonic-gate (void) printf("Bad source route option: %s\n", cmd_line_input); 2570*7c478bd9Sstevel@tonic-gate return (-1); 2571*7c478bd9Sstevel@tonic-gate #endif /* ICMD */ 2572*7c478bd9Sstevel@tonic-gate } 2573*7c478bd9Sstevel@tonic-gate 2574*7c478bd9Sstevel@tonic-gate /* 2575*7c478bd9Sstevel@tonic-gate * Resolves the target and gateway addresses, determines what type of addresses 2576*7c478bd9Sstevel@tonic-gate * (ALL_ADDRS, ONLY_V6, ONLY_V4) telnet will be trying to connect. 2577*7c478bd9Sstevel@tonic-gate * 2578*7c478bd9Sstevel@tonic-gate * Returns: pointer to resolved target if name resolutions succeed 2579*7c478bd9Sstevel@tonic-gate * NULL if name resolutions fail or 2580*7c478bd9Sstevel@tonic-gate * a library function call fails 2581*7c478bd9Sstevel@tonic-gate * 2582*7c478bd9Sstevel@tonic-gate * The last host in the hostname_list is the target. After resolving the target, 2583*7c478bd9Sstevel@tonic-gate * determines for what type of addresses it should try to resolve gateways. It 2584*7c478bd9Sstevel@tonic-gate * resolves gateway addresses and picks one address for each desired address 2585*7c478bd9Sstevel@tonic-gate * type and stores in the array pointed by gw_addrsp. Also, this 'type of 2586*7c478bd9Sstevel@tonic-gate * addresses' is pointed by addr_type argument on successful return. 2587*7c478bd9Sstevel@tonic-gate */ 2588*7c478bd9Sstevel@tonic-gate static struct addrinfo * 2589*7c478bd9Sstevel@tonic-gate resolve_hosts(char **hostname_list, int num_gw, struct gateway **gw_addrsp, 2590*7c478bd9Sstevel@tonic-gate int *addr_type, const char *portp) 2591*7c478bd9Sstevel@tonic-gate { 2592*7c478bd9Sstevel@tonic-gate struct gateway *gw_addrs = NULL; 2593*7c478bd9Sstevel@tonic-gate struct gateway *gw; 2594*7c478bd9Sstevel@tonic-gate /* whether we already picked an IPv4 address for the current gateway */ 2595*7c478bd9Sstevel@tonic-gate boolean_t got_v4_addr; 2596*7c478bd9Sstevel@tonic-gate boolean_t got_v6_addr; 2597*7c478bd9Sstevel@tonic-gate /* whether we need to get an IPv4 address for the current gateway */ 2598*7c478bd9Sstevel@tonic-gate boolean_t need_v4_addr = B_FALSE; 2599*7c478bd9Sstevel@tonic-gate boolean_t need_v6_addr = B_FALSE; 2600*7c478bd9Sstevel@tonic-gate int res_failed_at4; /* save which gateway failed to resolve */ 2601*7c478bd9Sstevel@tonic-gate int res_failed_at6; 2602*7c478bd9Sstevel@tonic-gate boolean_t is_v4mapped; 2603*7c478bd9Sstevel@tonic-gate struct in6_addr *v6addrp; 2604*7c478bd9Sstevel@tonic-gate struct in_addr *v4addrp; 2605*7c478bd9Sstevel@tonic-gate int error_num; 2606*7c478bd9Sstevel@tonic-gate int i; 2607*7c478bd9Sstevel@tonic-gate int rc; 2608*7c478bd9Sstevel@tonic-gate struct addrinfo *res, *host, *gateway, *addr; 2609*7c478bd9Sstevel@tonic-gate struct addrinfo hints; 2610*7c478bd9Sstevel@tonic-gate 2611*7c478bd9Sstevel@tonic-gate *addr_type = ALL_ADDRS; 2612*7c478bd9Sstevel@tonic-gate 2613*7c478bd9Sstevel@tonic-gate memset(&hints, 0, sizeof (hints)); 2614*7c478bd9Sstevel@tonic-gate hints.ai_flags = AI_CANONNAME; /* used for config files, diags */ 2615*7c478bd9Sstevel@tonic-gate hints.ai_socktype = SOCK_STREAM; 2616*7c478bd9Sstevel@tonic-gate rc = getaddrinfo(hostname_list[num_gw], 2617*7c478bd9Sstevel@tonic-gate (portp != NULL) ? portp : "telnet", &hints, &res); 2618*7c478bd9Sstevel@tonic-gate if (rc != 0) { 2619*7c478bd9Sstevel@tonic-gate if (hostname_list[num_gw] != NULL && 2620*7c478bd9Sstevel@tonic-gate *hostname_list[num_gw] != '\0') 2621*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", hostname_list[num_gw]); 2622*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gai_strerror(rc)); 2623*7c478bd9Sstevel@tonic-gate return (NULL); 2624*7c478bd9Sstevel@tonic-gate } 2625*7c478bd9Sstevel@tonic-gate 2626*7c478bd9Sstevel@tonic-gate /* 2627*7c478bd9Sstevel@tonic-gate * Let's see what type of addresses we got for the target. This 2628*7c478bd9Sstevel@tonic-gate * determines what type of addresses we'd like to resolve gateways 2629*7c478bd9Sstevel@tonic-gate * later. 2630*7c478bd9Sstevel@tonic-gate */ 2631*7c478bd9Sstevel@tonic-gate for (host = res; host != NULL; host = host->ai_next) { 2632*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *s6; 2633*7c478bd9Sstevel@tonic-gate 2634*7c478bd9Sstevel@tonic-gate s6 = (struct sockaddr_in6 *)host->ai_addr; 2635*7c478bd9Sstevel@tonic-gate 2636*7c478bd9Sstevel@tonic-gate if (host->ai_addr->sa_family == AF_INET || 2637*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) 2638*7c478bd9Sstevel@tonic-gate need_v4_addr = B_TRUE; 2639*7c478bd9Sstevel@tonic-gate else 2640*7c478bd9Sstevel@tonic-gate need_v6_addr = B_TRUE; 2641*7c478bd9Sstevel@tonic-gate 2642*7c478bd9Sstevel@tonic-gate /* 2643*7c478bd9Sstevel@tonic-gate * Let's stop after seeing we need both IPv6 and IPv4. 2644*7c478bd9Sstevel@tonic-gate */ 2645*7c478bd9Sstevel@tonic-gate if (need_v4_addr && need_v6_addr) 2646*7c478bd9Sstevel@tonic-gate break; 2647*7c478bd9Sstevel@tonic-gate } 2648*7c478bd9Sstevel@tonic-gate 2649*7c478bd9Sstevel@tonic-gate if (num_gw > 0) { 2650*7c478bd9Sstevel@tonic-gate /* 2651*7c478bd9Sstevel@tonic-gate * In the prepare_optbuf(), we'll store the IPv4 address of the 2652*7c478bd9Sstevel@tonic-gate * target in the last slot of gw_addrs array. Therefore we need 2653*7c478bd9Sstevel@tonic-gate * space for num_gw+1 hosts. 2654*7c478bd9Sstevel@tonic-gate */ 2655*7c478bd9Sstevel@tonic-gate gw_addrs = calloc(num_gw + 1, sizeof (struct gateway)); 2656*7c478bd9Sstevel@tonic-gate if (gw_addrs == NULL) { 2657*7c478bd9Sstevel@tonic-gate perror("telnet: calloc"); 2658*7c478bd9Sstevel@tonic-gate freeaddrinfo(res); 2659*7c478bd9Sstevel@tonic-gate return (NULL); 2660*7c478bd9Sstevel@tonic-gate } 2661*7c478bd9Sstevel@tonic-gate } 2662*7c478bd9Sstevel@tonic-gate 2663*7c478bd9Sstevel@tonic-gate /* 2664*7c478bd9Sstevel@tonic-gate * Now we'll go through all the gateways and try to resolve them to 2665*7c478bd9Sstevel@tonic-gate * the desired address types. 2666*7c478bd9Sstevel@tonic-gate */ 2667*7c478bd9Sstevel@tonic-gate gw = gw_addrs; 2668*7c478bd9Sstevel@tonic-gate 2669*7c478bd9Sstevel@tonic-gate /* -1 means 'no address resolution failure yet' */ 2670*7c478bd9Sstevel@tonic-gate res_failed_at4 = -1; 2671*7c478bd9Sstevel@tonic-gate res_failed_at6 = -1; 2672*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_gw; i++) { 2673*7c478bd9Sstevel@tonic-gate rc = getaddrinfo(hostname_list[i], NULL, NULL, &gateway); 2674*7c478bd9Sstevel@tonic-gate if (rc != 0) { 2675*7c478bd9Sstevel@tonic-gate if (hostname_list[i] != NULL && 2676*7c478bd9Sstevel@tonic-gate *hostname_list[i] != '\0') 2677*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", 2678*7c478bd9Sstevel@tonic-gate hostname_list[i]); 2679*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "bad address\n"); 2680*7c478bd9Sstevel@tonic-gate return (NULL); 2681*7c478bd9Sstevel@tonic-gate } 2682*7c478bd9Sstevel@tonic-gate 2683*7c478bd9Sstevel@tonic-gate /* 2684*7c478bd9Sstevel@tonic-gate * Initially we have no address of any type for this gateway. 2685*7c478bd9Sstevel@tonic-gate */ 2686*7c478bd9Sstevel@tonic-gate got_v6_addr = B_FALSE; 2687*7c478bd9Sstevel@tonic-gate got_v4_addr = B_FALSE; 2688*7c478bd9Sstevel@tonic-gate 2689*7c478bd9Sstevel@tonic-gate /* 2690*7c478bd9Sstevel@tonic-gate * Let's go through all the addresses of this gateway. 2691*7c478bd9Sstevel@tonic-gate * Use the first address which matches the needed family. 2692*7c478bd9Sstevel@tonic-gate */ 2693*7c478bd9Sstevel@tonic-gate for (addr = gateway; addr != NULL; addr = addr->ai_next) { 2694*7c478bd9Sstevel@tonic-gate /*LINTED*/ 2695*7c478bd9Sstevel@tonic-gate v6addrp = &((struct sockaddr_in6 *)addr->ai_addr)-> 2696*7c478bd9Sstevel@tonic-gate sin6_addr; 2697*7c478bd9Sstevel@tonic-gate v4addrp = &((struct sockaddr_in *)addr->ai_addr)-> 2698*7c478bd9Sstevel@tonic-gate sin_addr; 2699*7c478bd9Sstevel@tonic-gate 2700*7c478bd9Sstevel@tonic-gate if (addr->ai_family == AF_INET6) 2701*7c478bd9Sstevel@tonic-gate is_v4mapped = IN6_IS_ADDR_V4MAPPED(v6addrp); 2702*7c478bd9Sstevel@tonic-gate else 2703*7c478bd9Sstevel@tonic-gate is_v4mapped = B_FALSE; 2704*7c478bd9Sstevel@tonic-gate 2705*7c478bd9Sstevel@tonic-gate /* 2706*7c478bd9Sstevel@tonic-gate * If we need to determine an IPv4 address and haven't 2707*7c478bd9Sstevel@tonic-gate * found one yet and this is a IPv4-mapped IPv6 address, 2708*7c478bd9Sstevel@tonic-gate * then bingo! 2709*7c478bd9Sstevel@tonic-gate */ 2710*7c478bd9Sstevel@tonic-gate if (need_v4_addr && !got_v4_addr) { 2711*7c478bd9Sstevel@tonic-gate if (is_v4mapped) { 2712*7c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(v6addrp, 2713*7c478bd9Sstevel@tonic-gate &gw->gw_addr); 2714*7c478bd9Sstevel@tonic-gate got_v4_addr = B_TRUE; 2715*7c478bd9Sstevel@tonic-gate } else if (addr->ai_family = AF_INET) { 2716*7c478bd9Sstevel@tonic-gate gw->gw_addr = *v4addrp; 2717*7c478bd9Sstevel@tonic-gate got_v4_addr = B_TRUE; 2718*7c478bd9Sstevel@tonic-gate } 2719*7c478bd9Sstevel@tonic-gate } 2720*7c478bd9Sstevel@tonic-gate 2721*7c478bd9Sstevel@tonic-gate if (need_v6_addr && !got_v6_addr && 2722*7c478bd9Sstevel@tonic-gate addr->ai_family == AF_INET6) { 2723*7c478bd9Sstevel@tonic-gate gw->gw_addr6 = *v6addrp; 2724*7c478bd9Sstevel@tonic-gate got_v6_addr = B_TRUE; 2725*7c478bd9Sstevel@tonic-gate } 2726*7c478bd9Sstevel@tonic-gate 2727*7c478bd9Sstevel@tonic-gate /* 2728*7c478bd9Sstevel@tonic-gate * Let's stop if we got all what we looked for. 2729*7c478bd9Sstevel@tonic-gate */ 2730*7c478bd9Sstevel@tonic-gate if ((!need_v4_addr || got_v4_addr) && 2731*7c478bd9Sstevel@tonic-gate (!need_v6_addr || got_v6_addr)) 2732*7c478bd9Sstevel@tonic-gate break; 2733*7c478bd9Sstevel@tonic-gate } 2734*7c478bd9Sstevel@tonic-gate 2735*7c478bd9Sstevel@tonic-gate /* 2736*7c478bd9Sstevel@tonic-gate * We needed an IPv4 address for this gateway but couldn't 2737*7c478bd9Sstevel@tonic-gate * find one. 2738*7c478bd9Sstevel@tonic-gate */ 2739*7c478bd9Sstevel@tonic-gate if (need_v4_addr && !got_v4_addr) { 2740*7c478bd9Sstevel@tonic-gate res_failed_at4 = i; 2741*7c478bd9Sstevel@tonic-gate /* 2742*7c478bd9Sstevel@tonic-gate * Since we couldn't resolve a gateway to IPv4 address 2743*7c478bd9Sstevel@tonic-gate * we can't use IPv4 at all. Therefore we no longer 2744*7c478bd9Sstevel@tonic-gate * need IPv4 addresses for any of the gateways. 2745*7c478bd9Sstevel@tonic-gate */ 2746*7c478bd9Sstevel@tonic-gate need_v4_addr = B_FALSE; 2747*7c478bd9Sstevel@tonic-gate } 2748*7c478bd9Sstevel@tonic-gate 2749*7c478bd9Sstevel@tonic-gate if (need_v6_addr && !got_v6_addr) { 2750*7c478bd9Sstevel@tonic-gate res_failed_at6 = i; 2751*7c478bd9Sstevel@tonic-gate need_v6_addr = B_FALSE; 2752*7c478bd9Sstevel@tonic-gate } 2753*7c478bd9Sstevel@tonic-gate 2754*7c478bd9Sstevel@tonic-gate /* 2755*7c478bd9Sstevel@tonic-gate * If some gateways don't resolve to any of the desired 2756*7c478bd9Sstevel@tonic-gate * address types, we fail. 2757*7c478bd9Sstevel@tonic-gate */ 2758*7c478bd9Sstevel@tonic-gate if (!need_v4_addr && !need_v6_addr) { 2759*7c478bd9Sstevel@tonic-gate if (res_failed_at6 != -1) { 2760*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2761*7c478bd9Sstevel@tonic-gate "%s: Host doesn't have any IPv6 address\n", 2762*7c478bd9Sstevel@tonic-gate hostname_list[res_failed_at6]); 2763*7c478bd9Sstevel@tonic-gate } 2764*7c478bd9Sstevel@tonic-gate if (res_failed_at4 != -1) { 2765*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2766*7c478bd9Sstevel@tonic-gate "%s: Host doesn't have any IPv4 address\n", 2767*7c478bd9Sstevel@tonic-gate hostname_list[res_failed_at4]); 2768*7c478bd9Sstevel@tonic-gate } 2769*7c478bd9Sstevel@tonic-gate free(gw_addrs); 2770*7c478bd9Sstevel@tonic-gate return (NULL); 2771*7c478bd9Sstevel@tonic-gate } 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate gw++; 2774*7c478bd9Sstevel@tonic-gate } 2775*7c478bd9Sstevel@tonic-gate 2776*7c478bd9Sstevel@tonic-gate *gw_addrsp = gw_addrs; 2777*7c478bd9Sstevel@tonic-gate 2778*7c478bd9Sstevel@tonic-gate /* 2779*7c478bd9Sstevel@tonic-gate * When we get here, need_v4_addr and need_v6_addr have their final 2780*7c478bd9Sstevel@tonic-gate * values based on the name resolution of the target and gateways. 2781*7c478bd9Sstevel@tonic-gate */ 2782*7c478bd9Sstevel@tonic-gate if (need_v4_addr && need_v6_addr) 2783*7c478bd9Sstevel@tonic-gate *addr_type = ALL_ADDRS; 2784*7c478bd9Sstevel@tonic-gate else if (need_v4_addr && !need_v6_addr) 2785*7c478bd9Sstevel@tonic-gate *addr_type = ONLY_V4; 2786*7c478bd9Sstevel@tonic-gate else if (!need_v4_addr && need_v6_addr) 2787*7c478bd9Sstevel@tonic-gate *addr_type = ONLY_V6; 2788*7c478bd9Sstevel@tonic-gate 2789*7c478bd9Sstevel@tonic-gate return (res); 2790*7c478bd9Sstevel@tonic-gate } 2791*7c478bd9Sstevel@tonic-gate 2792*7c478bd9Sstevel@tonic-gate 2793*7c478bd9Sstevel@tonic-gate /* 2794*7c478bd9Sstevel@tonic-gate * Initializes the buffer pointed by opt_bufpp for a IPv4 option of type 2795*7c478bd9Sstevel@tonic-gate * src_rtng_type using the gateway addresses stored in gw_addrs. If no buffer 2796*7c478bd9Sstevel@tonic-gate * is passed, it allocates one. If a buffer is passed, checks if it's big 2797*7c478bd9Sstevel@tonic-gate * enough. 2798*7c478bd9Sstevel@tonic-gate * On return opt_buf_len points to the buffer length which we need later for the 2799*7c478bd9Sstevel@tonic-gate * setsockopt() call, and opt_bufpp points to the newly allocated or already 2800*7c478bd9Sstevel@tonic-gate * passed buffer. Returns B_FALSE if a library function call fails or passed 2801*7c478bd9Sstevel@tonic-gate * buffer is not big enough, B_TRUE otherwise. 2802*7c478bd9Sstevel@tonic-gate */ 2803*7c478bd9Sstevel@tonic-gate static boolean_t 2804*7c478bd9Sstevel@tonic-gate prepare_optbuf(struct gateway *gw_addrs, int num_gw, char **opt_bufpp, 2805*7c478bd9Sstevel@tonic-gate size_t *opt_buf_len, struct in_addr *target, uchar_t src_rtng_type) 2806*7c478bd9Sstevel@tonic-gate { 2807*7c478bd9Sstevel@tonic-gate struct ip_sourceroute *sr_opt; 2808*7c478bd9Sstevel@tonic-gate size_t needed_buflen; 2809*7c478bd9Sstevel@tonic-gate int i; 2810*7c478bd9Sstevel@tonic-gate 2811*7c478bd9Sstevel@tonic-gate /* 2812*7c478bd9Sstevel@tonic-gate * We have (num_gw + 1) IP addresses in the buffer because the number 2813*7c478bd9Sstevel@tonic-gate * of gateway addresses we put in the option buffer includes the target 2814*7c478bd9Sstevel@tonic-gate * address. 2815*7c478bd9Sstevel@tonic-gate * At the time of setsockopt() call, passed option length needs to be 2816*7c478bd9Sstevel@tonic-gate * multiple of 4 bytes. Therefore we need one IPOPT_NOP before (or 2817*7c478bd9Sstevel@tonic-gate * after) IPOPT_LSRR. 2818*7c478bd9Sstevel@tonic-gate * 1 = preceding 1 byte of IPOPT_NOP 2819*7c478bd9Sstevel@tonic-gate * 3 = 1 (code) + 1 (len) + 1 (ptr) 2820*7c478bd9Sstevel@tonic-gate */ 2821*7c478bd9Sstevel@tonic-gate needed_buflen = 1 + 3 + (num_gw + 1) * sizeof (struct in_addr); 2822*7c478bd9Sstevel@tonic-gate 2823*7c478bd9Sstevel@tonic-gate if (*opt_bufpp != NULL) { 2824*7c478bd9Sstevel@tonic-gate /* check if the passed buffer is big enough */ 2825*7c478bd9Sstevel@tonic-gate if (*opt_buf_len < needed_buflen) { 2826*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2827*7c478bd9Sstevel@tonic-gate "telnet: buffer too small for IPv4 source routing " 2828*7c478bd9Sstevel@tonic-gate "option\n"); 2829*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2830*7c478bd9Sstevel@tonic-gate } 2831*7c478bd9Sstevel@tonic-gate } else { 2832*7c478bd9Sstevel@tonic-gate *opt_bufpp = malloc(needed_buflen); 2833*7c478bd9Sstevel@tonic-gate if (*opt_bufpp == NULL) { 2834*7c478bd9Sstevel@tonic-gate perror("telnet: malloc"); 2835*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2836*7c478bd9Sstevel@tonic-gate } 2837*7c478bd9Sstevel@tonic-gate } 2838*7c478bd9Sstevel@tonic-gate 2839*7c478bd9Sstevel@tonic-gate *opt_buf_len = needed_buflen; 2840*7c478bd9Sstevel@tonic-gate 2841*7c478bd9Sstevel@tonic-gate /* final hop is the target */ 2842*7c478bd9Sstevel@tonic-gate gw_addrs[num_gw].gw_addr = *target; 2843*7c478bd9Sstevel@tonic-gate 2844*7c478bd9Sstevel@tonic-gate *opt_bufpp[0] = IPOPT_NOP; 2845*7c478bd9Sstevel@tonic-gate /* IPOPT_LSRR starts right after IPOPT_NOP */ 2846*7c478bd9Sstevel@tonic-gate sr_opt = (struct ip_sourceroute *)(*opt_bufpp + 1); 2847*7c478bd9Sstevel@tonic-gate sr_opt->ipsr_code = src_rtng_type; 2848*7c478bd9Sstevel@tonic-gate /* discount the 1 byte of IPOPT_NOP */ 2849*7c478bd9Sstevel@tonic-gate sr_opt->ipsr_len = needed_buflen - 1; 2850*7c478bd9Sstevel@tonic-gate sr_opt->ipsr_ptr = IPOPT_MINOFF; 2851*7c478bd9Sstevel@tonic-gate 2852*7c478bd9Sstevel@tonic-gate /* copy the gateways into the optlist */ 2853*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_gw + 1; i++) { 2854*7c478bd9Sstevel@tonic-gate (void) bcopy(&gw_addrs[i].gw_addr, &sr_opt->ipsr_addrs[i], 2855*7c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 2856*7c478bd9Sstevel@tonic-gate } 2857*7c478bd9Sstevel@tonic-gate 2858*7c478bd9Sstevel@tonic-gate return (B_TRUE); 2859*7c478bd9Sstevel@tonic-gate } 2860*7c478bd9Sstevel@tonic-gate 2861*7c478bd9Sstevel@tonic-gate /* 2862*7c478bd9Sstevel@tonic-gate * Initializes the buffer pointed by opt_bufpp for a IPv6 routing header option 2863*7c478bd9Sstevel@tonic-gate * using the gateway addresses stored in gw_addrs. If no buffer is passed, it 2864*7c478bd9Sstevel@tonic-gate * allocates one. If a buffer is passed, checks if it's big enough. 2865*7c478bd9Sstevel@tonic-gate * On return opt_buf_len points to the buffer length which we need later for the 2866*7c478bd9Sstevel@tonic-gate * setsockopt() call, and opt_bufpp points to the newly allocated or already 2867*7c478bd9Sstevel@tonic-gate * passed buffer. Returns B_FALSE if a library function call fails or passed 2868*7c478bd9Sstevel@tonic-gate * buffer is not big enough, B_TRUE otherwise. 2869*7c478bd9Sstevel@tonic-gate */ 2870*7c478bd9Sstevel@tonic-gate static boolean_t 2871*7c478bd9Sstevel@tonic-gate prepare_optbuf6(struct gateway *gw_addrs, int num_gw, char **opt_bufpp, 2872*7c478bd9Sstevel@tonic-gate size_t *opt_buf_len) 2873*7c478bd9Sstevel@tonic-gate { 2874*7c478bd9Sstevel@tonic-gate char *opt_bufp; 2875*7c478bd9Sstevel@tonic-gate size_t needed_buflen; 2876*7c478bd9Sstevel@tonic-gate int i; 2877*7c478bd9Sstevel@tonic-gate 2878*7c478bd9Sstevel@tonic-gate needed_buflen = inet6_rth_space(IPV6_RTHDR_TYPE_0, num_gw); 2879*7c478bd9Sstevel@tonic-gate 2880*7c478bd9Sstevel@tonic-gate if (*opt_bufpp != NULL) { 2881*7c478bd9Sstevel@tonic-gate /* check if the passed buffer is big enough */ 2882*7c478bd9Sstevel@tonic-gate if (*opt_buf_len < needed_buflen) { 2883*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 2884*7c478bd9Sstevel@tonic-gate "telnet: buffer too small for IPv6 routing " 2885*7c478bd9Sstevel@tonic-gate "header option\n"); 2886*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2887*7c478bd9Sstevel@tonic-gate } 2888*7c478bd9Sstevel@tonic-gate } else { 2889*7c478bd9Sstevel@tonic-gate *opt_bufpp = malloc(needed_buflen); 2890*7c478bd9Sstevel@tonic-gate if (*opt_bufpp == NULL) { 2891*7c478bd9Sstevel@tonic-gate perror("telnet: malloc"); 2892*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2893*7c478bd9Sstevel@tonic-gate } 2894*7c478bd9Sstevel@tonic-gate } 2895*7c478bd9Sstevel@tonic-gate *opt_buf_len = needed_buflen; 2896*7c478bd9Sstevel@tonic-gate opt_bufp = *opt_bufpp; 2897*7c478bd9Sstevel@tonic-gate 2898*7c478bd9Sstevel@tonic-gate /* 2899*7c478bd9Sstevel@tonic-gate * Initialize the buffer to be used for IPv6 routing header type 0. 2900*7c478bd9Sstevel@tonic-gate */ 2901*7c478bd9Sstevel@tonic-gate if (inet6_rth_init(opt_bufp, needed_buflen, IPV6_RTHDR_TYPE_0, 2902*7c478bd9Sstevel@tonic-gate num_gw) == NULL) { 2903*7c478bd9Sstevel@tonic-gate perror("telnet: inet6_rth_init"); 2904*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2905*7c478bd9Sstevel@tonic-gate } 2906*7c478bd9Sstevel@tonic-gate 2907*7c478bd9Sstevel@tonic-gate /* 2908*7c478bd9Sstevel@tonic-gate * Add gateways one by one. 2909*7c478bd9Sstevel@tonic-gate */ 2910*7c478bd9Sstevel@tonic-gate for (i = 0; i < num_gw; i++) { 2911*7c478bd9Sstevel@tonic-gate if (inet6_rth_add(opt_bufp, &gw_addrs[i].gw_addr6) == -1) { 2912*7c478bd9Sstevel@tonic-gate perror("telnet: inet6_rth_add"); 2913*7c478bd9Sstevel@tonic-gate return (B_FALSE); 2914*7c478bd9Sstevel@tonic-gate } 2915*7c478bd9Sstevel@tonic-gate } 2916*7c478bd9Sstevel@tonic-gate 2917*7c478bd9Sstevel@tonic-gate /* successful operation */ 2918*7c478bd9Sstevel@tonic-gate return (B_TRUE); 2919*7c478bd9Sstevel@tonic-gate } 2920*7c478bd9Sstevel@tonic-gate 2921*7c478bd9Sstevel@tonic-gate int 2922*7c478bd9Sstevel@tonic-gate tn(argc, argv) 2923*7c478bd9Sstevel@tonic-gate int argc; 2924*7c478bd9Sstevel@tonic-gate char *argv[]; 2925*7c478bd9Sstevel@tonic-gate { 2926*7c478bd9Sstevel@tonic-gate struct addrinfo *host = NULL; 2927*7c478bd9Sstevel@tonic-gate struct addrinfo *h; 2928*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6; 2929*7c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 2930*7c478bd9Sstevel@tonic-gate struct in6_addr addr6; 2931*7c478bd9Sstevel@tonic-gate struct in_addr addr; 2932*7c478bd9Sstevel@tonic-gate void *addrp; 2933*7c478bd9Sstevel@tonic-gate struct gateway *gw_addrs; 2934*7c478bd9Sstevel@tonic-gate char *hostname_list[MAXMAX_GATEWAY + 1] = {NULL}; 2935*7c478bd9Sstevel@tonic-gate char *opt_buf6 = NULL; /* used for IPv6 routing header */ 2936*7c478bd9Sstevel@tonic-gate size_t opt_buf_len6 = 0; 2937*7c478bd9Sstevel@tonic-gate uchar_t src_rtng_type; /* type of IPv4 source routing */ 2938*7c478bd9Sstevel@tonic-gate struct servent *sp = 0; 2939*7c478bd9Sstevel@tonic-gate char *opt_buf = NULL; /* used for IPv4 source routing */ 2940*7c478bd9Sstevel@tonic-gate size_t opt_buf_len = 0; 2941*7c478bd9Sstevel@tonic-gate char *cmd; 2942*7c478bd9Sstevel@tonic-gate char *hostp = NULL; 2943*7c478bd9Sstevel@tonic-gate char *portp = NULL; 2944*7c478bd9Sstevel@tonic-gate char *user = NULL; 2945*7c478bd9Sstevel@tonic-gate #ifdef ICMD 2946*7c478bd9Sstevel@tonic-gate char *itelnet_host; 2947*7c478bd9Sstevel@tonic-gate char *real_host; 2948*7c478bd9Sstevel@tonic-gate unsigned short dest_port; 2949*7c478bd9Sstevel@tonic-gate #endif /* ICMD */ 2950*7c478bd9Sstevel@tonic-gate /* 2951*7c478bd9Sstevel@tonic-gate * The two strings at the end of this function are 24 and 39 2952*7c478bd9Sstevel@tonic-gate * characters long (minus the %.*s in the format strings). Add 2953*7c478bd9Sstevel@tonic-gate * one for the null terminator making the longest print string 40. 2954*7c478bd9Sstevel@tonic-gate */ 2955*7c478bd9Sstevel@tonic-gate char buf[MAXHOSTNAMELEN+40]; 2956*7c478bd9Sstevel@tonic-gate /* 2957*7c478bd9Sstevel@tonic-gate * In the case of ICMD defined, dest_port will contain the real port 2958*7c478bd9Sstevel@tonic-gate * we are trying to telnet to, and target_port will contain 2959*7c478bd9Sstevel@tonic-gate * "telnet-passthru" port. 2960*7c478bd9Sstevel@tonic-gate */ 2961*7c478bd9Sstevel@tonic-gate unsigned short target_port; 2962*7c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 2963*7c478bd9Sstevel@tonic-gate int num_gw; 2964*7c478bd9Sstevel@tonic-gate int ret_val; 2965*7c478bd9Sstevel@tonic-gate boolean_t is_v4mapped; 2966*7c478bd9Sstevel@tonic-gate /* 2967*7c478bd9Sstevel@tonic-gate * Type of addresses we'll try to connect to (ALL_ADDRS, ONLY_V6, 2968*7c478bd9Sstevel@tonic-gate * ONLY_V4). 2969*7c478bd9Sstevel@tonic-gate */ 2970*7c478bd9Sstevel@tonic-gate int addr_type; 2971*7c478bd9Sstevel@tonic-gate 2972*7c478bd9Sstevel@tonic-gate /* clear the socket address prior to use */ 2973*7c478bd9Sstevel@tonic-gate (void) memset(&sin6, '\0', sizeof (sin6)); 2974*7c478bd9Sstevel@tonic-gate sin6.sin6_family = AF_INET6; 2975*7c478bd9Sstevel@tonic-gate 2976*7c478bd9Sstevel@tonic-gate (void) memset(&sin, '\0', sizeof (sin)); 2977*7c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 2978*7c478bd9Sstevel@tonic-gate 2979*7c478bd9Sstevel@tonic-gate if (connected) { 2980*7c478bd9Sstevel@tonic-gate (void) printf("?Already connected to %s\n", hostname); 2981*7c478bd9Sstevel@tonic-gate return (0); 2982*7c478bd9Sstevel@tonic-gate } 2983*7c478bd9Sstevel@tonic-gate #ifdef ICMD 2984*7c478bd9Sstevel@tonic-gate itelnet_host = getenv("INTERNET_HOST"); 2985*7c478bd9Sstevel@tonic-gate if (itelnet_host == NULL || itelnet_host[0] == '\0') { 2986*7c478bd9Sstevel@tonic-gate (void) printf("INTERNET_HOST environment variable undefined\n"); 2987*7c478bd9Sstevel@tonic-gate goto tn_exit; 2988*7c478bd9Sstevel@tonic-gate } 2989*7c478bd9Sstevel@tonic-gate #endif 2990*7c478bd9Sstevel@tonic-gate if (argc < 2) { 2991*7c478bd9Sstevel@tonic-gate (void) printf("(to) "); 2992*7c478bd9Sstevel@tonic-gate if (GetAndAppendString(&line, &linesize, "open ", 2993*7c478bd9Sstevel@tonic-gate stdin) == NULL) { 2994*7c478bd9Sstevel@tonic-gate if (!feof(stdin)) { 2995*7c478bd9Sstevel@tonic-gate perror("telnet"); 2996*7c478bd9Sstevel@tonic-gate goto tn_exit; 2997*7c478bd9Sstevel@tonic-gate } 2998*7c478bd9Sstevel@tonic-gate } 2999*7c478bd9Sstevel@tonic-gate makeargv(); 3000*7c478bd9Sstevel@tonic-gate argc = margc; 3001*7c478bd9Sstevel@tonic-gate argv = margv; 3002*7c478bd9Sstevel@tonic-gate } 3003*7c478bd9Sstevel@tonic-gate cmd = *argv; 3004*7c478bd9Sstevel@tonic-gate --argc; ++argv; 3005*7c478bd9Sstevel@tonic-gate while (argc) { 3006*7c478bd9Sstevel@tonic-gate if (isprefix(*argv, "help") == 4 || isprefix(*argv, "?") == 1) 3007*7c478bd9Sstevel@tonic-gate goto usage; 3008*7c478bd9Sstevel@tonic-gate if (strcmp(*argv, "-l") == 0) { 3009*7c478bd9Sstevel@tonic-gate --argc; ++argv; 3010*7c478bd9Sstevel@tonic-gate if (argc == 0) 3011*7c478bd9Sstevel@tonic-gate goto usage; 3012*7c478bd9Sstevel@tonic-gate user = *argv++; 3013*7c478bd9Sstevel@tonic-gate --argc; 3014*7c478bd9Sstevel@tonic-gate continue; 3015*7c478bd9Sstevel@tonic-gate } 3016*7c478bd9Sstevel@tonic-gate if (strcmp(*argv, "-a") == 0) { 3017*7c478bd9Sstevel@tonic-gate --argc; ++argv; 3018*7c478bd9Sstevel@tonic-gate autologin = autologin_set = 1; 3019*7c478bd9Sstevel@tonic-gate continue; 3020*7c478bd9Sstevel@tonic-gate } 3021*7c478bd9Sstevel@tonic-gate if (hostp == 0) { 3022*7c478bd9Sstevel@tonic-gate hostp = *argv++; 3023*7c478bd9Sstevel@tonic-gate --argc; 3024*7c478bd9Sstevel@tonic-gate continue; 3025*7c478bd9Sstevel@tonic-gate } 3026*7c478bd9Sstevel@tonic-gate if (portp == 0) { 3027*7c478bd9Sstevel@tonic-gate portp = *argv++; 3028*7c478bd9Sstevel@tonic-gate --argc; 3029*7c478bd9Sstevel@tonic-gate /* 3030*7c478bd9Sstevel@tonic-gate * Do we treat this like a telnet port or raw? 3031*7c478bd9Sstevel@tonic-gate */ 3032*7c478bd9Sstevel@tonic-gate if (*portp == '-') { 3033*7c478bd9Sstevel@tonic-gate portp++; 3034*7c478bd9Sstevel@tonic-gate telnetport = 1; 3035*7c478bd9Sstevel@tonic-gate } else 3036*7c478bd9Sstevel@tonic-gate telnetport = 0; 3037*7c478bd9Sstevel@tonic-gate continue; 3038*7c478bd9Sstevel@tonic-gate } 3039*7c478bd9Sstevel@tonic-gate usage: 3040*7c478bd9Sstevel@tonic-gate (void) printf( 3041*7c478bd9Sstevel@tonic-gate "usage: %s [-l user] [-a] host-name [port]\n", cmd); 3042*7c478bd9Sstevel@tonic-gate goto tn_exit; 3043*7c478bd9Sstevel@tonic-gate } 3044*7c478bd9Sstevel@tonic-gate if (hostp == 0) 3045*7c478bd9Sstevel@tonic-gate goto usage; 3046*7c478bd9Sstevel@tonic-gate 3047*7c478bd9Sstevel@tonic-gate #ifdef ICMD 3048*7c478bd9Sstevel@tonic-gate /* 3049*7c478bd9Sstevel@tonic-gate * For setup phase treat the relay host as the target host. 3050*7c478bd9Sstevel@tonic-gate */ 3051*7c478bd9Sstevel@tonic-gate real_host = hostp; 3052*7c478bd9Sstevel@tonic-gate hostp = itelnet_host; 3053*7c478bd9Sstevel@tonic-gate #endif 3054*7c478bd9Sstevel@tonic-gate num_gw = parse_input(hostp, hostname_list, &src_rtng_type); 3055*7c478bd9Sstevel@tonic-gate if (num_gw < 0) { 3056*7c478bd9Sstevel@tonic-gate goto tn_exit; 3057*7c478bd9Sstevel@tonic-gate } 3058*7c478bd9Sstevel@tonic-gate 3059*7c478bd9Sstevel@tonic-gate /* Last host in the hostname_list is the target */ 3060*7c478bd9Sstevel@tonic-gate hostp = hostname_list[num_gw]; 3061*7c478bd9Sstevel@tonic-gate 3062*7c478bd9Sstevel@tonic-gate host = resolve_hosts(hostname_list, num_gw, &gw_addrs, &addr_type, 3063*7c478bd9Sstevel@tonic-gate portp); 3064*7c478bd9Sstevel@tonic-gate if (host == NULL) { 3065*7c478bd9Sstevel@tonic-gate goto tn_exit; 3066*7c478bd9Sstevel@tonic-gate } 3067*7c478bd9Sstevel@tonic-gate 3068*7c478bd9Sstevel@tonic-gate /* 3069*7c478bd9Sstevel@tonic-gate * Check if number of gateways is less than max. available 3070*7c478bd9Sstevel@tonic-gate */ 3071*7c478bd9Sstevel@tonic-gate if ((addr_type == ALL_ADDRS || addr_type == ONLY_V6) && 3072*7c478bd9Sstevel@tonic-gate num_gw > MAX_GATEWAY6) { 3073*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "telnet: too many IPv6 gateways\n"); 3074*7c478bd9Sstevel@tonic-gate goto tn_exit; 3075*7c478bd9Sstevel@tonic-gate } 3076*7c478bd9Sstevel@tonic-gate 3077*7c478bd9Sstevel@tonic-gate if ((addr_type == ALL_ADDRS || addr_type == ONLY_V4) && 3078*7c478bd9Sstevel@tonic-gate num_gw > MAX_GATEWAY) { 3079*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "telnet: too many IPv4 gateways\n"); 3080*7c478bd9Sstevel@tonic-gate goto tn_exit; 3081*7c478bd9Sstevel@tonic-gate } 3082*7c478bd9Sstevel@tonic-gate 3083*7c478bd9Sstevel@tonic-gate /* 3084*7c478bd9Sstevel@tonic-gate * If we pass a literal IPv4 address to getaddrinfo(), in the 3085*7c478bd9Sstevel@tonic-gate * returned addrinfo structure, hostname is the IPv4-mapped IPv6 3086*7c478bd9Sstevel@tonic-gate * address string. We prefer to preserve the literal IPv4 address 3087*7c478bd9Sstevel@tonic-gate * string as the hostname. Also, if the hostname entered by the 3088*7c478bd9Sstevel@tonic-gate * user is IPv4-mapped IPv6 address, we'll downgrade it to IPv4 3089*7c478bd9Sstevel@tonic-gate * address. 3090*7c478bd9Sstevel@tonic-gate */ 3091*7c478bd9Sstevel@tonic-gate if (inet_addr(hostp) != (in_addr_t)-1) { 3092*7c478bd9Sstevel@tonic-gate /* this is a literal IPv4 address */ 3093*7c478bd9Sstevel@tonic-gate (void) strlcpy(_hostname, hostp, sizeof (_hostname)); 3094*7c478bd9Sstevel@tonic-gate } else if ((inet_pton(AF_INET6, hostp, &addr6) > 0) && 3095*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr6)) { 3096*7c478bd9Sstevel@tonic-gate /* this is a IPv4-mapped IPv6 address */ 3097*7c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(&addr6, &addr); 3098*7c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, &addr, _hostname, sizeof (_hostname)); 3099*7c478bd9Sstevel@tonic-gate } else { 3100*7c478bd9Sstevel@tonic-gate (void) strlcpy(_hostname, host->ai_canonname, 3101*7c478bd9Sstevel@tonic-gate sizeof (_hostname)); 3102*7c478bd9Sstevel@tonic-gate } 3103*7c478bd9Sstevel@tonic-gate hostname = _hostname; 3104*7c478bd9Sstevel@tonic-gate 3105*7c478bd9Sstevel@tonic-gate if (portp == NULL) { 3106*7c478bd9Sstevel@tonic-gate telnetport = 1; 3107*7c478bd9Sstevel@tonic-gate } 3108*7c478bd9Sstevel@tonic-gate 3109*7c478bd9Sstevel@tonic-gate if (host->ai_family == AF_INET) { 3110*7c478bd9Sstevel@tonic-gate target_port = ((struct sockaddr_in *)(host->ai_addr))->sin_port; 3111*7c478bd9Sstevel@tonic-gate } else { 3112*7c478bd9Sstevel@tonic-gate target_port = ((struct sockaddr_in6 *)(host->ai_addr)) 3113*7c478bd9Sstevel@tonic-gate ->sin6_port; 3114*7c478bd9Sstevel@tonic-gate } 3115*7c478bd9Sstevel@tonic-gate 3116*7c478bd9Sstevel@tonic-gate #ifdef ICMD 3117*7c478bd9Sstevel@tonic-gate /* 3118*7c478bd9Sstevel@tonic-gate * Since we pass the port number as an ascii string to the proxy, 3119*7c478bd9Sstevel@tonic-gate * we need it in host format. 3120*7c478bd9Sstevel@tonic-gate */ 3121*7c478bd9Sstevel@tonic-gate dest_port = ntohs(target_port); 3122*7c478bd9Sstevel@tonic-gate sp = getservbyname("telnet-passthru", "tcp"); 3123*7c478bd9Sstevel@tonic-gate if (sp == 0) { 3124*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3125*7c478bd9Sstevel@tonic-gate "telnet: tcp/telnet-passthru: unknown service\n"); 3126*7c478bd9Sstevel@tonic-gate goto tn_exit; 3127*7c478bd9Sstevel@tonic-gate } 3128*7c478bd9Sstevel@tonic-gate target_port = sp->s_port; 3129*7c478bd9Sstevel@tonic-gate #endif 3130*7c478bd9Sstevel@tonic-gate h = host; 3131*7c478bd9Sstevel@tonic-gate 3132*7c478bd9Sstevel@tonic-gate /* 3133*7c478bd9Sstevel@tonic-gate * For IPv6 source routing, we need to initialize option buffer only 3134*7c478bd9Sstevel@tonic-gate * once. 3135*7c478bd9Sstevel@tonic-gate */ 3136*7c478bd9Sstevel@tonic-gate if (num_gw > 0 && (addr_type == ALL_ADDRS || addr_type == ONLY_V6)) { 3137*7c478bd9Sstevel@tonic-gate if (!prepare_optbuf6(gw_addrs, num_gw, &opt_buf6, 3138*7c478bd9Sstevel@tonic-gate &opt_buf_len6)) { 3139*7c478bd9Sstevel@tonic-gate goto tn_exit; 3140*7c478bd9Sstevel@tonic-gate } 3141*7c478bd9Sstevel@tonic-gate } 3142*7c478bd9Sstevel@tonic-gate 3143*7c478bd9Sstevel@tonic-gate /* 3144*7c478bd9Sstevel@tonic-gate * We procure the Kerberos config files options only 3145*7c478bd9Sstevel@tonic-gate * if the user has choosen Krb5 authentication. 3146*7c478bd9Sstevel@tonic-gate */ 3147*7c478bd9Sstevel@tonic-gate if (krb5auth_flag > 0) { 3148*7c478bd9Sstevel@tonic-gate krb5_profile_get_options(hostname, telnet_krb5_realm, 3149*7c478bd9Sstevel@tonic-gate config_file_options); 3150*7c478bd9Sstevel@tonic-gate } 3151*7c478bd9Sstevel@tonic-gate 3152*7c478bd9Sstevel@tonic-gate if (encrypt_flag) { 3153*7c478bd9Sstevel@tonic-gate extern boolean_t auth_enable_encrypt; 3154*7c478bd9Sstevel@tonic-gate if (krb5_privacy_allowed()) { 3155*7c478bd9Sstevel@tonic-gate encrypt_auto(1); 3156*7c478bd9Sstevel@tonic-gate decrypt_auto(1); 3157*7c478bd9Sstevel@tonic-gate wantencryption = B_TRUE; 3158*7c478bd9Sstevel@tonic-gate autologin = 1; 3159*7c478bd9Sstevel@tonic-gate auth_enable_encrypt = B_TRUE; 3160*7c478bd9Sstevel@tonic-gate } else { 3161*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3162*7c478bd9Sstevel@tonic-gate "%s:Encryption not supported.\n"), prompt); 3163*7c478bd9Sstevel@tonic-gate exit(1); 3164*7c478bd9Sstevel@tonic-gate } 3165*7c478bd9Sstevel@tonic-gate } 3166*7c478bd9Sstevel@tonic-gate 3167*7c478bd9Sstevel@tonic-gate if (forward_flag && forwardable_flag) { 3168*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 3169*7c478bd9Sstevel@tonic-gate "Error in krb5 configuration file. " 3170*7c478bd9Sstevel@tonic-gate "Both forward and forwardable are set.\n")); 3171*7c478bd9Sstevel@tonic-gate exit(1); 3172*7c478bd9Sstevel@tonic-gate } 3173*7c478bd9Sstevel@tonic-gate if (forwardable_flag) { 3174*7c478bd9Sstevel@tonic-gate forward_flags |= OPTS_FORWARD_CREDS | OPTS_FORWARDABLE_CREDS; 3175*7c478bd9Sstevel@tonic-gate } else if (forward_flag) 3176*7c478bd9Sstevel@tonic-gate forward_flags |= OPTS_FORWARD_CREDS; 3177*7c478bd9Sstevel@tonic-gate 3178*7c478bd9Sstevel@tonic-gate 3179*7c478bd9Sstevel@tonic-gate do { 3180*7c478bd9Sstevel@tonic-gate /* 3181*7c478bd9Sstevel@tonic-gate * Search for an address of desired type in the IP address list 3182*7c478bd9Sstevel@tonic-gate * of the target. 3183*7c478bd9Sstevel@tonic-gate */ 3184*7c478bd9Sstevel@tonic-gate while (h != NULL) { 3185*7c478bd9Sstevel@tonic-gate struct sockaddr_in6 *addr; 3186*7c478bd9Sstevel@tonic-gate 3187*7c478bd9Sstevel@tonic-gate addr = (struct sockaddr_in6 *)h->ai_addr; 3188*7c478bd9Sstevel@tonic-gate 3189*7c478bd9Sstevel@tonic-gate if (h->ai_family == AF_INET6) 3190*7c478bd9Sstevel@tonic-gate is_v4mapped = 3191*7c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr); 3192*7c478bd9Sstevel@tonic-gate else 3193*7c478bd9Sstevel@tonic-gate is_v4mapped = B_FALSE; 3194*7c478bd9Sstevel@tonic-gate 3195*7c478bd9Sstevel@tonic-gate if (addr_type == ALL_ADDRS || 3196*7c478bd9Sstevel@tonic-gate (addr_type == ONLY_V6 && 3197*7c478bd9Sstevel@tonic-gate h->ai_family == AF_INET6) || 3198*7c478bd9Sstevel@tonic-gate (addr_type == ONLY_V4 && 3199*7c478bd9Sstevel@tonic-gate (h->ai_family == AF_INET || is_v4mapped))) 3200*7c478bd9Sstevel@tonic-gate break; 3201*7c478bd9Sstevel@tonic-gate 3202*7c478bd9Sstevel@tonic-gate /* skip undesired typed addresses */ 3203*7c478bd9Sstevel@tonic-gate h = h->ai_next; 3204*7c478bd9Sstevel@tonic-gate } 3205*7c478bd9Sstevel@tonic-gate 3206*7c478bd9Sstevel@tonic-gate if (h == NULL) { 3207*7c478bd9Sstevel@tonic-gate fprintf(stderr, 3208*7c478bd9Sstevel@tonic-gate "telnet: Unable to connect to remote host"); 3209*7c478bd9Sstevel@tonic-gate goto tn_exit; 3210*7c478bd9Sstevel@tonic-gate } 3211*7c478bd9Sstevel@tonic-gate 3212*7c478bd9Sstevel@tonic-gate /* 3213*7c478bd9Sstevel@tonic-gate * We need to open a socket with a family matching the type of 3214*7c478bd9Sstevel@tonic-gate * address we are trying to connect to. This is because we 3215*7c478bd9Sstevel@tonic-gate * deal with IPv4 options and IPv6 extension headers. 3216*7c478bd9Sstevel@tonic-gate */ 3217*7c478bd9Sstevel@tonic-gate if (h->ai_family == AF_INET) { 3218*7c478bd9Sstevel@tonic-gate addrp = &((struct sockaddr_in *)(h->ai_addr))->sin_addr; 3219*7c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)(h->ai_addr))->sin_port = 3220*7c478bd9Sstevel@tonic-gate target_port; 3221*7c478bd9Sstevel@tonic-gate } else { 3222*7c478bd9Sstevel@tonic-gate addrp = &((struct sockaddr_in6 *)(h->ai_addr)) 3223*7c478bd9Sstevel@tonic-gate ->sin6_addr; 3224*7c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)(h->ai_addr))->sin6_port = 3225*7c478bd9Sstevel@tonic-gate target_port; 3226*7c478bd9Sstevel@tonic-gate } 3227*7c478bd9Sstevel@tonic-gate 3228*7c478bd9Sstevel@tonic-gate (void) printf("Trying %s...\n", inet_ntop(h->ai_family, 3229*7c478bd9Sstevel@tonic-gate addrp, abuf, sizeof (abuf))); 3230*7c478bd9Sstevel@tonic-gate 3231*7c478bd9Sstevel@tonic-gate net = socket(h->ai_family, SOCK_STREAM, 0); 3232*7c478bd9Sstevel@tonic-gate 3233*7c478bd9Sstevel@tonic-gate if (net < 0) { 3234*7c478bd9Sstevel@tonic-gate perror("telnet: socket"); 3235*7c478bd9Sstevel@tonic-gate goto tn_exit; 3236*7c478bd9Sstevel@tonic-gate } 3237*7c478bd9Sstevel@tonic-gate #ifndef ICMD 3238*7c478bd9Sstevel@tonic-gate if (num_gw > 0) { 3239*7c478bd9Sstevel@tonic-gate if (h->ai_family == AF_INET || is_v4mapped) { 3240*7c478bd9Sstevel@tonic-gate if (!prepare_optbuf(gw_addrs, num_gw, &opt_buf, 3241*7c478bd9Sstevel@tonic-gate &opt_buf_len, addrp, src_rtng_type)) { 3242*7c478bd9Sstevel@tonic-gate goto tn_exit; 3243*7c478bd9Sstevel@tonic-gate } 3244*7c478bd9Sstevel@tonic-gate 3245*7c478bd9Sstevel@tonic-gate if (setsockopt(net, IPPROTO_IP, IP_OPTIONS, 3246*7c478bd9Sstevel@tonic-gate opt_buf, opt_buf_len) < 0) 3247*7c478bd9Sstevel@tonic-gate perror("setsockopt (IP_OPTIONS)"); 3248*7c478bd9Sstevel@tonic-gate } else { 3249*7c478bd9Sstevel@tonic-gate if (setsockopt(net, IPPROTO_IPV6, IPV6_RTHDR, 3250*7c478bd9Sstevel@tonic-gate opt_buf6, opt_buf_len6) < 0) 3251*7c478bd9Sstevel@tonic-gate perror("setsockopt (IPV6_RTHDR)"); 3252*7c478bd9Sstevel@tonic-gate } 3253*7c478bd9Sstevel@tonic-gate } 3254*7c478bd9Sstevel@tonic-gate #endif 3255*7c478bd9Sstevel@tonic-gate #if defined(USE_TOS) 3256*7c478bd9Sstevel@tonic-gate if (is_v4mapped) { 3257*7c478bd9Sstevel@tonic-gate if (tos < 0) 3258*7c478bd9Sstevel@tonic-gate tos = 020; /* Low Delay bit */ 3259*7c478bd9Sstevel@tonic-gate if (tos && 3260*7c478bd9Sstevel@tonic-gate (setsockopt(net, IPPROTO_IP, IP_TOS, 3261*7c478bd9Sstevel@tonic-gate &tos, sizeof (int)) < 0) && 3262*7c478bd9Sstevel@tonic-gate (errno != ENOPROTOOPT)) 3263*7c478bd9Sstevel@tonic-gate perror("telnet: setsockopt (IP_TOS) (ignored)"); 3264*7c478bd9Sstevel@tonic-gate } 3265*7c478bd9Sstevel@tonic-gate #endif /* defined(USE_TOS) */ 3266*7c478bd9Sstevel@tonic-gate 3267*7c478bd9Sstevel@tonic-gate if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 3268*7c478bd9Sstevel@tonic-gate perror("setsockopt (SO_DEBUG)"); 3269*7c478bd9Sstevel@tonic-gate } 3270*7c478bd9Sstevel@tonic-gate 3271*7c478bd9Sstevel@tonic-gate ret_val = connect(net, h->ai_addr, h->ai_addrlen); 3272*7c478bd9Sstevel@tonic-gate 3273*7c478bd9Sstevel@tonic-gate /* 3274*7c478bd9Sstevel@tonic-gate * If failed, try the next address of the target. 3275*7c478bd9Sstevel@tonic-gate */ 3276*7c478bd9Sstevel@tonic-gate if (ret_val < 0) { 3277*7c478bd9Sstevel@tonic-gate Close(&net); 3278*7c478bd9Sstevel@tonic-gate if (h->ai_next != NULL) { 3279*7c478bd9Sstevel@tonic-gate 3280*7c478bd9Sstevel@tonic-gate int oerrno = errno; 3281*7c478bd9Sstevel@tonic-gate 3282*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 3283*7c478bd9Sstevel@tonic-gate "telnet: connect to address %s: ", abuf); 3284*7c478bd9Sstevel@tonic-gate errno = oerrno; 3285*7c478bd9Sstevel@tonic-gate perror((char *)0); 3286*7c478bd9Sstevel@tonic-gate 3287*7c478bd9Sstevel@tonic-gate h = h->ai_next; 3288*7c478bd9Sstevel@tonic-gate continue; 3289*7c478bd9Sstevel@tonic-gate } 3290*7c478bd9Sstevel@tonic-gate perror("telnet: Unable to connect to remote host"); 3291*7c478bd9Sstevel@tonic-gate goto tn_exit; 3292*7c478bd9Sstevel@tonic-gate } 3293*7c478bd9Sstevel@tonic-gate connected++; 3294*7c478bd9Sstevel@tonic-gate } while (connected == 0); 3295*7c478bd9Sstevel@tonic-gate freeaddrinfo(host); 3296*7c478bd9Sstevel@tonic-gate host = NULL; 3297*7c478bd9Sstevel@tonic-gate #ifdef ICMD 3298*7c478bd9Sstevel@tonic-gate /* 3299*7c478bd9Sstevel@tonic-gate * Do initial protocol to connect to farther end... 3300*7c478bd9Sstevel@tonic-gate */ 3301*7c478bd9Sstevel@tonic-gate { 3302*7c478bd9Sstevel@tonic-gate char buf[1024]; 3303*7c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s %d\n", real_host, (int)dest_port); 3304*7c478bd9Sstevel@tonic-gate write(net, buf, strlen(buf)); 3305*7c478bd9Sstevel@tonic-gate } 3306*7c478bd9Sstevel@tonic-gate #endif 3307*7c478bd9Sstevel@tonic-gate if (cmdrc(hostp, hostname) != 0) 3308*7c478bd9Sstevel@tonic-gate goto tn_exit; 3309*7c478bd9Sstevel@tonic-gate FreeHostnameList(hostname_list); 3310*7c478bd9Sstevel@tonic-gate if (autologin && user == NULL) { 3311*7c478bd9Sstevel@tonic-gate struct passwd *pw; 3312*7c478bd9Sstevel@tonic-gate 3313*7c478bd9Sstevel@tonic-gate user = getenv("LOGNAME"); 3314*7c478bd9Sstevel@tonic-gate if (user == NULL || 3315*7c478bd9Sstevel@tonic-gate ((pw = getpwnam(user)) != NULL) && 3316*7c478bd9Sstevel@tonic-gate pw->pw_uid != getuid()) { 3317*7c478bd9Sstevel@tonic-gate if (pw = getpwuid(getuid())) 3318*7c478bd9Sstevel@tonic-gate user = pw->pw_name; 3319*7c478bd9Sstevel@tonic-gate else 3320*7c478bd9Sstevel@tonic-gate user = NULL; 3321*7c478bd9Sstevel@tonic-gate } 3322*7c478bd9Sstevel@tonic-gate } 3323*7c478bd9Sstevel@tonic-gate 3324*7c478bd9Sstevel@tonic-gate if (user) { 3325*7c478bd9Sstevel@tonic-gate if (env_define((unsigned char *)"USER", (unsigned char *)user)) 3326*7c478bd9Sstevel@tonic-gate env_export((unsigned char *)"USER"); 3327*7c478bd9Sstevel@tonic-gate else { 3328*7c478bd9Sstevel@tonic-gate /* Clean up and exit. */ 3329*7c478bd9Sstevel@tonic-gate Close(&net); 3330*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 3331*7c478bd9Sstevel@tonic-gate "Connection to %.*s closed.\n", 3332*7c478bd9Sstevel@tonic-gate MAXHOSTNAMELEN, hostname); 3333*7c478bd9Sstevel@tonic-gate ExitString(buf, EXIT_FAILURE); 3334*7c478bd9Sstevel@tonic-gate 3335*7c478bd9Sstevel@tonic-gate /* NOTREACHED */ 3336*7c478bd9Sstevel@tonic-gate } 3337*7c478bd9Sstevel@tonic-gate } 3338*7c478bd9Sstevel@tonic-gate (void) call(3, status, "status", "notmuch"); 3339*7c478bd9Sstevel@tonic-gate if (setjmp(peerdied) == 0) 3340*7c478bd9Sstevel@tonic-gate telnet(user); 3341*7c478bd9Sstevel@tonic-gate 3342*7c478bd9Sstevel@tonic-gate Close(&net); 3343*7c478bd9Sstevel@tonic-gate 3344*7c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 3345*7c478bd9Sstevel@tonic-gate "Connection to %.*s closed by foreign host.\n", 3346*7c478bd9Sstevel@tonic-gate MAXHOSTNAMELEN, hostname); 3347*7c478bd9Sstevel@tonic-gate ExitString(buf, EXIT_FAILURE); 3348*7c478bd9Sstevel@tonic-gate 3349*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3350*7c478bd9Sstevel@tonic-gate 3351*7c478bd9Sstevel@tonic-gate tn_exit: 3352*7c478bd9Sstevel@tonic-gate FreeHostnameList(hostname_list); 3353*7c478bd9Sstevel@tonic-gate Close(&net); 3354*7c478bd9Sstevel@tonic-gate connected = 0; 3355*7c478bd9Sstevel@tonic-gate if (host != NULL) 3356*7c478bd9Sstevel@tonic-gate freeaddrinfo(host); 3357*7c478bd9Sstevel@tonic-gate return (0); 3358*7c478bd9Sstevel@tonic-gate } 3359*7c478bd9Sstevel@tonic-gate 3360*7c478bd9Sstevel@tonic-gate #define HELPINDENT (sizeof ("connect")) 3361*7c478bd9Sstevel@tonic-gate 3362*7c478bd9Sstevel@tonic-gate static char openhelp[] = "connect to a site"; 3363*7c478bd9Sstevel@tonic-gate static char closehelp[] = "close current connection"; 3364*7c478bd9Sstevel@tonic-gate static char logouthelp[] = 3365*7c478bd9Sstevel@tonic-gate "forcibly logout remote user and close the connection"; 3366*7c478bd9Sstevel@tonic-gate static char quithelp[] = "exit telnet"; 3367*7c478bd9Sstevel@tonic-gate static char statushelp[] = "print status information"; 3368*7c478bd9Sstevel@tonic-gate static char helphelp[] = "print help information"; 3369*7c478bd9Sstevel@tonic-gate static char sendhelp[] = 3370*7c478bd9Sstevel@tonic-gate "transmit special characters ('send ?' for more)"; 3371*7c478bd9Sstevel@tonic-gate static char sethelp[] = "set operating parameters ('set ?' for more)"; 3372*7c478bd9Sstevel@tonic-gate static char unsethelp[] = "unset operating parameters ('unset ?' for more)"; 3373*7c478bd9Sstevel@tonic-gate static char togglestring[] = 3374*7c478bd9Sstevel@tonic-gate "toggle operating parameters ('toggle ?' for more)"; 3375*7c478bd9Sstevel@tonic-gate static char slchelp[] = "change state of special charaters ('slc ?' for more)"; 3376*7c478bd9Sstevel@tonic-gate static char displayhelp[] = "display operating parameters"; 3377*7c478bd9Sstevel@tonic-gate static char authhelp[] = 3378*7c478bd9Sstevel@tonic-gate "turn on (off) authentication ('auth ?' for more)"; 3379*7c478bd9Sstevel@tonic-gate static char forwardhelp[] = 3380*7c478bd9Sstevel@tonic-gate "turn on (off) credential forwarding ('forward ?' for more)"; 3381*7c478bd9Sstevel@tonic-gate static char encrypthelp[] = 3382*7c478bd9Sstevel@tonic-gate "turn on (off) encryption ('encrypt ?' for more)"; 3383*7c478bd9Sstevel@tonic-gate static char zhelp[] = "suspend telnet"; 3384*7c478bd9Sstevel@tonic-gate static char shellhelp[] = "invoke a subshell"; 3385*7c478bd9Sstevel@tonic-gate static char envhelp[] = "change environment variables ('environ ?' for more)"; 3386*7c478bd9Sstevel@tonic-gate static char modestring[] = 3387*7c478bd9Sstevel@tonic-gate "try to enter line or character mode ('mode ?' for more)"; 3388*7c478bd9Sstevel@tonic-gate 3389*7c478bd9Sstevel@tonic-gate static int help(); 3390*7c478bd9Sstevel@tonic-gate 3391*7c478bd9Sstevel@tonic-gate static Command cmdtab[] = { 3392*7c478bd9Sstevel@tonic-gate { "close", closehelp, bye, 1 }, 3393*7c478bd9Sstevel@tonic-gate { "logout", logouthelp, logout, 1 }, 3394*7c478bd9Sstevel@tonic-gate { "display", displayhelp, display, 0 }, 3395*7c478bd9Sstevel@tonic-gate { "mode", modestring, modecmd, 0 }, 3396*7c478bd9Sstevel@tonic-gate { "open", openhelp, tn, 0 }, 3397*7c478bd9Sstevel@tonic-gate { "quit", quithelp, quit, 0 }, 3398*7c478bd9Sstevel@tonic-gate { "send", sendhelp, sendcmd, 0 }, 3399*7c478bd9Sstevel@tonic-gate { "set", sethelp, setcmd, 0 }, 3400*7c478bd9Sstevel@tonic-gate { "unset", unsethelp, unsetcmd, 0 }, 3401*7c478bd9Sstevel@tonic-gate { "status", statushelp, status, 0 }, 3402*7c478bd9Sstevel@tonic-gate { "toggle", togglestring, toggle, 0 }, 3403*7c478bd9Sstevel@tonic-gate { "slc", slchelp, slccmd, 0 }, 3404*7c478bd9Sstevel@tonic-gate { "auth", authhelp, auth_cmd, 0 }, 3405*7c478bd9Sstevel@tonic-gate { "encrypt", encrypthelp, encrypt_cmd, 0 }, 3406*7c478bd9Sstevel@tonic-gate { "forward", forwardhelp, forw_cmd, 0 }, 3407*7c478bd9Sstevel@tonic-gate { "z", zhelp, suspend, 0 }, 3408*7c478bd9Sstevel@tonic-gate { "!", shellhelp, shell, 0 }, 3409*7c478bd9Sstevel@tonic-gate { "environ", envhelp, env_cmd, 0 }, 3410*7c478bd9Sstevel@tonic-gate { "?", helphelp, help, 0 }, 3411*7c478bd9Sstevel@tonic-gate 0 3412*7c478bd9Sstevel@tonic-gate }; 3413*7c478bd9Sstevel@tonic-gate 3414*7c478bd9Sstevel@tonic-gate 3415*7c478bd9Sstevel@tonic-gate static Command cmdtab2[] = { 3416*7c478bd9Sstevel@tonic-gate { "help", 0, help, 0 }, 3417*7c478bd9Sstevel@tonic-gate { "escape", 0, setescape, 0 }, 3418*7c478bd9Sstevel@tonic-gate { "crmod", 0, togcrmod, 0 }, 3419*7c478bd9Sstevel@tonic-gate 0 3420*7c478bd9Sstevel@tonic-gate }; 3421*7c478bd9Sstevel@tonic-gate 3422*7c478bd9Sstevel@tonic-gate 3423*7c478bd9Sstevel@tonic-gate /* 3424*7c478bd9Sstevel@tonic-gate * Call routine with argc, argv set from args. 3425*7c478bd9Sstevel@tonic-gate * Uses /usr/include/stdarg.h 3426*7c478bd9Sstevel@tonic-gate */ 3427*7c478bd9Sstevel@tonic-gate #define MAXVARGS 100 3428*7c478bd9Sstevel@tonic-gate /*VARARGS1*/ 3429*7c478bd9Sstevel@tonic-gate static void 3430*7c478bd9Sstevel@tonic-gate call(int n_ptrs, ...) 3431*7c478bd9Sstevel@tonic-gate { 3432*7c478bd9Sstevel@tonic-gate va_list ap; 3433*7c478bd9Sstevel@tonic-gate typedef int (*intrtn_t)(); 3434*7c478bd9Sstevel@tonic-gate intrtn_t routine; 3435*7c478bd9Sstevel@tonic-gate char *args[MAXVARGS+1]; /* leave 1 for trailing NULL */ 3436*7c478bd9Sstevel@tonic-gate int argno = 0; 3437*7c478bd9Sstevel@tonic-gate 3438*7c478bd9Sstevel@tonic-gate if (n_ptrs > MAXVARGS) 3439*7c478bd9Sstevel@tonic-gate n_ptrs = MAXVARGS; 3440*7c478bd9Sstevel@tonic-gate va_start(ap, MAXVARGS); 3441*7c478bd9Sstevel@tonic-gate 3442*7c478bd9Sstevel@tonic-gate routine = (va_arg(ap, intrtn_t)); /* extract the routine's name */ 3443*7c478bd9Sstevel@tonic-gate n_ptrs--; 3444*7c478bd9Sstevel@tonic-gate 3445*7c478bd9Sstevel@tonic-gate while (argno < n_ptrs) /* extract the routine's args */ 3446*7c478bd9Sstevel@tonic-gate args[argno++] = va_arg(ap, char *); 3447*7c478bd9Sstevel@tonic-gate args[argno] = NULL; /* NULL terminate for good luck */ 3448*7c478bd9Sstevel@tonic-gate va_end(ap); 3449*7c478bd9Sstevel@tonic-gate 3450*7c478bd9Sstevel@tonic-gate (*routine)(argno, args); 3451*7c478bd9Sstevel@tonic-gate } 3452*7c478bd9Sstevel@tonic-gate 3453*7c478bd9Sstevel@tonic-gate 3454*7c478bd9Sstevel@tonic-gate static Command * 3455*7c478bd9Sstevel@tonic-gate getcmd(name) 3456*7c478bd9Sstevel@tonic-gate char *name; 3457*7c478bd9Sstevel@tonic-gate { 3458*7c478bd9Sstevel@tonic-gate Command *cm; 3459*7c478bd9Sstevel@tonic-gate 3460*7c478bd9Sstevel@tonic-gate if (cm = (Command *) genget(name, (char **)cmdtab, sizeof (Command))) 3461*7c478bd9Sstevel@tonic-gate return (cm); 3462*7c478bd9Sstevel@tonic-gate return (Command *) genget(name, (char **)cmdtab2, sizeof (Command)); 3463*7c478bd9Sstevel@tonic-gate } 3464*7c478bd9Sstevel@tonic-gate 3465*7c478bd9Sstevel@tonic-gate void 3466*7c478bd9Sstevel@tonic-gate command(top, tbuf, cnt) 3467*7c478bd9Sstevel@tonic-gate int top; 3468*7c478bd9Sstevel@tonic-gate char *tbuf; 3469*7c478bd9Sstevel@tonic-gate int cnt; 3470*7c478bd9Sstevel@tonic-gate { 3471*7c478bd9Sstevel@tonic-gate Command *c; 3472*7c478bd9Sstevel@tonic-gate 3473*7c478bd9Sstevel@tonic-gate setcommandmode(); 3474*7c478bd9Sstevel@tonic-gate if (!top) { 3475*7c478bd9Sstevel@tonic-gate (void) putchar('\n'); 3476*7c478bd9Sstevel@tonic-gate } else { 3477*7c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_DFL); 3478*7c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 3479*7c478bd9Sstevel@tonic-gate } 3480*7c478bd9Sstevel@tonic-gate for (;;) { 3481*7c478bd9Sstevel@tonic-gate if (rlogin == _POSIX_VDISABLE) 3482*7c478bd9Sstevel@tonic-gate (void) printf("%s> ", prompt); 3483*7c478bd9Sstevel@tonic-gate if (tbuf) { 3484*7c478bd9Sstevel@tonic-gate char *cp; 3485*7c478bd9Sstevel@tonic-gate if (AllocStringBuffer(&line, &linesize, cnt) == NULL) 3486*7c478bd9Sstevel@tonic-gate goto command_exit; 3487*7c478bd9Sstevel@tonic-gate cp = line; 3488*7c478bd9Sstevel@tonic-gate while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 3489*7c478bd9Sstevel@tonic-gate cnt--; 3490*7c478bd9Sstevel@tonic-gate tbuf = 0; 3491*7c478bd9Sstevel@tonic-gate if (cp == line || *--cp != '\n' || cp == line) 3492*7c478bd9Sstevel@tonic-gate goto getline; 3493*7c478bd9Sstevel@tonic-gate *cp = '\0'; 3494*7c478bd9Sstevel@tonic-gate if (rlogin == _POSIX_VDISABLE) 3495*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", line); 3496*7c478bd9Sstevel@tonic-gate } else { 3497*7c478bd9Sstevel@tonic-gate getline: 3498*7c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) 3499*7c478bd9Sstevel@tonic-gate (void) printf("%s> ", prompt); 3500*7c478bd9Sstevel@tonic-gate if (GetString(&line, &linesize, stdin) == NULL) { 3501*7c478bd9Sstevel@tonic-gate if (!feof(stdin)) 3502*7c478bd9Sstevel@tonic-gate perror("telnet"); 3503*7c478bd9Sstevel@tonic-gate (void) quit(); 3504*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3505*7c478bd9Sstevel@tonic-gate break; 3506*7c478bd9Sstevel@tonic-gate } 3507*7c478bd9Sstevel@tonic-gate } 3508*7c478bd9Sstevel@tonic-gate if (line[0] == 0) 3509*7c478bd9Sstevel@tonic-gate break; 3510*7c478bd9Sstevel@tonic-gate makeargv(); 3511*7c478bd9Sstevel@tonic-gate if (margv[0] == 0) { 3512*7c478bd9Sstevel@tonic-gate break; 3513*7c478bd9Sstevel@tonic-gate } 3514*7c478bd9Sstevel@tonic-gate c = getcmd(margv[0]); 3515*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 3516*7c478bd9Sstevel@tonic-gate (void) printf("?Ambiguous command\n"); 3517*7c478bd9Sstevel@tonic-gate continue; 3518*7c478bd9Sstevel@tonic-gate } 3519*7c478bd9Sstevel@tonic-gate if (c == 0) { 3520*7c478bd9Sstevel@tonic-gate (void) printf("?Invalid command\n"); 3521*7c478bd9Sstevel@tonic-gate continue; 3522*7c478bd9Sstevel@tonic-gate } 3523*7c478bd9Sstevel@tonic-gate if (c->needconnect && !connected) { 3524*7c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 3525*7c478bd9Sstevel@tonic-gate continue; 3526*7c478bd9Sstevel@tonic-gate } 3527*7c478bd9Sstevel@tonic-gate if ((*c->handler)(margc, margv)) { 3528*7c478bd9Sstevel@tonic-gate break; 3529*7c478bd9Sstevel@tonic-gate } 3530*7c478bd9Sstevel@tonic-gate } 3531*7c478bd9Sstevel@tonic-gate command_exit: 3532*7c478bd9Sstevel@tonic-gate if (!top) { 3533*7c478bd9Sstevel@tonic-gate if (!connected) { 3534*7c478bd9Sstevel@tonic-gate longjmp(toplevel, 1); 3535*7c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3536*7c478bd9Sstevel@tonic-gate } 3537*7c478bd9Sstevel@tonic-gate setconnmode(0); 3538*7c478bd9Sstevel@tonic-gate } 3539*7c478bd9Sstevel@tonic-gate } 3540*7c478bd9Sstevel@tonic-gate 3541*7c478bd9Sstevel@tonic-gate /* 3542*7c478bd9Sstevel@tonic-gate * Help command. 3543*7c478bd9Sstevel@tonic-gate */ 3544*7c478bd9Sstevel@tonic-gate static 3545*7c478bd9Sstevel@tonic-gate help(argc, argv) 3546*7c478bd9Sstevel@tonic-gate int argc; 3547*7c478bd9Sstevel@tonic-gate char *argv[]; 3548*7c478bd9Sstevel@tonic-gate { 3549*7c478bd9Sstevel@tonic-gate register Command *c; 3550*7c478bd9Sstevel@tonic-gate 3551*7c478bd9Sstevel@tonic-gate if (argc == 1) { 3552*7c478bd9Sstevel@tonic-gate (void) printf( 3553*7c478bd9Sstevel@tonic-gate "Commands may be abbreviated. Commands are:\n\n"); 3554*7c478bd9Sstevel@tonic-gate for (c = cmdtab; c->name; c++) 3555*7c478bd9Sstevel@tonic-gate if (c->help) { 3556*7c478bd9Sstevel@tonic-gate (void) printf("%-*s\t%s\n", HELPINDENT, 3557*7c478bd9Sstevel@tonic-gate c->name, c->help); 3558*7c478bd9Sstevel@tonic-gate } 3559*7c478bd9Sstevel@tonic-gate (void) printf("<return>\tleave command mode\n"); 3560*7c478bd9Sstevel@tonic-gate return (0); 3561*7c478bd9Sstevel@tonic-gate } 3562*7c478bd9Sstevel@tonic-gate while (--argc > 0) { 3563*7c478bd9Sstevel@tonic-gate register char *arg; 3564*7c478bd9Sstevel@tonic-gate arg = *++argv; 3565*7c478bd9Sstevel@tonic-gate c = getcmd(arg); 3566*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) 3567*7c478bd9Sstevel@tonic-gate (void) printf("?Ambiguous help command %s\n", arg); 3568*7c478bd9Sstevel@tonic-gate else if (c == (Command *)0) 3569*7c478bd9Sstevel@tonic-gate (void) printf("?Invalid help command %s\n", arg); 3570*7c478bd9Sstevel@tonic-gate else if (c->help) { 3571*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", c->help); 3572*7c478bd9Sstevel@tonic-gate } else { 3573*7c478bd9Sstevel@tonic-gate (void) printf("No additional help on %s\n", arg); 3574*7c478bd9Sstevel@tonic-gate } 3575*7c478bd9Sstevel@tonic-gate } 3576*7c478bd9Sstevel@tonic-gate return (0); 3577*7c478bd9Sstevel@tonic-gate } 3578*7c478bd9Sstevel@tonic-gate 3579*7c478bd9Sstevel@tonic-gate static char *rcname = NULL; 3580*7c478bd9Sstevel@tonic-gate #define TELNETRC_NAME "telnetrc" 3581*7c478bd9Sstevel@tonic-gate #define TELNETRC_COMP "/." TELNETRC_NAME 3582*7c478bd9Sstevel@tonic-gate 3583*7c478bd9Sstevel@tonic-gate static int 3584*7c478bd9Sstevel@tonic-gate cmdrc(char *m1, char *m2) 3585*7c478bd9Sstevel@tonic-gate { 3586*7c478bd9Sstevel@tonic-gate Command *c; 3587*7c478bd9Sstevel@tonic-gate FILE *rcfile = NULL; 3588*7c478bd9Sstevel@tonic-gate int gotmachine = 0; 3589*7c478bd9Sstevel@tonic-gate int l1 = strlen(m1); 3590*7c478bd9Sstevel@tonic-gate int l2 = strlen(m2); 3591*7c478bd9Sstevel@tonic-gate char m1save[MAXHOSTNAMELEN]; 3592*7c478bd9Sstevel@tonic-gate int ret = 0; 3593*7c478bd9Sstevel@tonic-gate char def[] = "DEFAULT"; 3594*7c478bd9Sstevel@tonic-gate 3595*7c478bd9Sstevel@tonic-gate if (skiprc) 3596*7c478bd9Sstevel@tonic-gate goto cmdrc_exit; 3597*7c478bd9Sstevel@tonic-gate 3598*7c478bd9Sstevel@tonic-gate doing_rc = 1; 3599*7c478bd9Sstevel@tonic-gate 3600*7c478bd9Sstevel@tonic-gate (void) strlcpy(m1save, m1, sizeof (m1save)); 3601*7c478bd9Sstevel@tonic-gate m1 = m1save; 3602*7c478bd9Sstevel@tonic-gate 3603*7c478bd9Sstevel@tonic-gate if (rcname == NULL) { 3604*7c478bd9Sstevel@tonic-gate char *homedir; 3605*7c478bd9Sstevel@tonic-gate unsigned rcbuflen; 3606*7c478bd9Sstevel@tonic-gate 3607*7c478bd9Sstevel@tonic-gate if ((homedir = getenv("HOME")) == NULL) 3608*7c478bd9Sstevel@tonic-gate homedir = ""; 3609*7c478bd9Sstevel@tonic-gate 3610*7c478bd9Sstevel@tonic-gate rcbuflen = strlen(homedir) + strlen(TELNETRC_COMP) + 1; 3611*7c478bd9Sstevel@tonic-gate if ((rcname = malloc(rcbuflen)) == NULL) { 3612*7c478bd9Sstevel@tonic-gate perror("telnet: can't process " TELNETRC_NAME); 3613*7c478bd9Sstevel@tonic-gate ret = 1; 3614*7c478bd9Sstevel@tonic-gate goto cmdrc_exit; 3615*7c478bd9Sstevel@tonic-gate } 3616*7c478bd9Sstevel@tonic-gate (void) strcpy(rcname, homedir); 3617*7c478bd9Sstevel@tonic-gate (void) strcat(rcname, TELNETRC_COMP); 3618*7c478bd9Sstevel@tonic-gate } 3619*7c478bd9Sstevel@tonic-gate 3620*7c478bd9Sstevel@tonic-gate if ((rcfile = fopen(rcname, "r")) == NULL) 3621*7c478bd9Sstevel@tonic-gate goto cmdrc_exit; 3622*7c478bd9Sstevel@tonic-gate 3623*7c478bd9Sstevel@tonic-gate for (;;) { 3624*7c478bd9Sstevel@tonic-gate if (GetString(&line, &linesize, rcfile) == NULL) { 3625*7c478bd9Sstevel@tonic-gate if (!feof(rcfile)) { 3626*7c478bd9Sstevel@tonic-gate perror("telnet: error reading " TELNETRC_NAME); 3627*7c478bd9Sstevel@tonic-gate ret = 1; 3628*7c478bd9Sstevel@tonic-gate goto cmdrc_exit; 3629*7c478bd9Sstevel@tonic-gate } 3630*7c478bd9Sstevel@tonic-gate break; 3631*7c478bd9Sstevel@tonic-gate } 3632*7c478bd9Sstevel@tonic-gate if (line[0] == 0) 3633*7c478bd9Sstevel@tonic-gate continue; 3634*7c478bd9Sstevel@tonic-gate if (line[0] == '#') 3635*7c478bd9Sstevel@tonic-gate continue; 3636*7c478bd9Sstevel@tonic-gate if (gotmachine) { 3637*7c478bd9Sstevel@tonic-gate if (!isspace(line[0])) 3638*7c478bd9Sstevel@tonic-gate gotmachine = 0; 3639*7c478bd9Sstevel@tonic-gate } 3640*7c478bd9Sstevel@tonic-gate if (gotmachine == 0) { 3641*7c478bd9Sstevel@tonic-gate if (isspace(line[0])) 3642*7c478bd9Sstevel@tonic-gate continue; 3643*7c478bd9Sstevel@tonic-gate if (strncasecmp(line, m1, l1) == 0) 3644*7c478bd9Sstevel@tonic-gate (void) strcpy(line, &line[l1]); 3645*7c478bd9Sstevel@tonic-gate else if (strncasecmp(line, m2, l2) == 0) 3646*7c478bd9Sstevel@tonic-gate (void) strcpy(line, &line[l2]); 3647*7c478bd9Sstevel@tonic-gate else if (strncasecmp(line, def, sizeof (def) - 1) == 0) 3648*7c478bd9Sstevel@tonic-gate (void) strcpy(line, &line[sizeof (def) - 1]); 3649*7c478bd9Sstevel@tonic-gate else 3650*7c478bd9Sstevel@tonic-gate continue; 3651*7c478bd9Sstevel@tonic-gate if (line[0] != ' ' && line[0] != '\t' && 3652*7c478bd9Sstevel@tonic-gate line[0] != '\n') 3653*7c478bd9Sstevel@tonic-gate continue; 3654*7c478bd9Sstevel@tonic-gate gotmachine = 1; 3655*7c478bd9Sstevel@tonic-gate } 3656*7c478bd9Sstevel@tonic-gate makeargv(); 3657*7c478bd9Sstevel@tonic-gate if (margv[0] == 0) 3658*7c478bd9Sstevel@tonic-gate continue; 3659*7c478bd9Sstevel@tonic-gate c = getcmd(margv[0]); 3660*7c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 3661*7c478bd9Sstevel@tonic-gate (void) printf("?Ambiguous command: %s\n", margv[0]); 3662*7c478bd9Sstevel@tonic-gate continue; 3663*7c478bd9Sstevel@tonic-gate } 3664*7c478bd9Sstevel@tonic-gate if (c == 0) { 3665*7c478bd9Sstevel@tonic-gate (void) printf("?Invalid command: %s\n", margv[0]); 3666*7c478bd9Sstevel@tonic-gate continue; 3667*7c478bd9Sstevel@tonic-gate } 3668*7c478bd9Sstevel@tonic-gate /* 3669*7c478bd9Sstevel@tonic-gate * This should never happen... 3670*7c478bd9Sstevel@tonic-gate */ 3671*7c478bd9Sstevel@tonic-gate if (c->needconnect && !connected) { 3672*7c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first for %s.\n", 3673*7c478bd9Sstevel@tonic-gate margv[0]); 3674*7c478bd9Sstevel@tonic-gate continue; 3675*7c478bd9Sstevel@tonic-gate } 3676*7c478bd9Sstevel@tonic-gate (*c->handler)(margc, margv); 3677*7c478bd9Sstevel@tonic-gate } 3678*7c478bd9Sstevel@tonic-gate cmdrc_exit: 3679*7c478bd9Sstevel@tonic-gate if (rcfile != NULL) 3680*7c478bd9Sstevel@tonic-gate (void) fclose(rcfile); 3681*7c478bd9Sstevel@tonic-gate doing_rc = 0; 3682*7c478bd9Sstevel@tonic-gate 3683*7c478bd9Sstevel@tonic-gate return (ret); 3684*7c478bd9Sstevel@tonic-gate } 3685