17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1990, 1993 37c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 47c478bd9Sstevel@tonic-gate * 57c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 67c478bd9Sstevel@tonic-gate * modification, are permitted provided that the following conditions 77c478bd9Sstevel@tonic-gate * are met: 87c478bd9Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 97c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 107c478bd9Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 117c478bd9Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 127c478bd9Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 137c478bd9Sstevel@tonic-gate * 3. All advertising materials mentioning features or use of this software 147c478bd9Sstevel@tonic-gate * must display the following acknowledgement: 157c478bd9Sstevel@tonic-gate * This product includes software developed by the University of 167c478bd9Sstevel@tonic-gate * California, Berkeley and its contributors. 177c478bd9Sstevel@tonic-gate * 4. Neither the name of the University nor the names of its contributors 187c478bd9Sstevel@tonic-gate * may be used to endorse or promote products derived from this software 197c478bd9Sstevel@tonic-gate * without specific prior written permission. 207c478bd9Sstevel@tonic-gate * 217c478bd9Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 227c478bd9Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 237c478bd9Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 247c478bd9Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 257c478bd9Sstevel@tonic-gate * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 267c478bd9Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 277c478bd9Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 287c478bd9Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 297c478bd9Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 307c478bd9Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 317c478bd9Sstevel@tonic-gate * SUCH DAMAGE. 327c478bd9Sstevel@tonic-gate * 33740638c8Sbw * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 347c478bd9Sstevel@tonic-gate * Use is subject to license terms. 357c478bd9Sstevel@tonic-gate */ 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <sys/param.h> 387c478bd9Sstevel@tonic-gate #include <sys/file.h> 397c478bd9Sstevel@tonic-gate #include <sys/socket.h> 407c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 417c478bd9Sstevel@tonic-gate #include <netinet/in.h> 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate #include <signal.h> 447c478bd9Sstevel@tonic-gate #include <netdb.h> 457c478bd9Sstevel@tonic-gate #include <ctype.h> 467c478bd9Sstevel@tonic-gate #include <pwd.h> 477c478bd9Sstevel@tonic-gate #include <errno.h> 487c478bd9Sstevel@tonic-gate #include <strings.h> 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate #include <arpa/telnet.h> 517c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate #include "general.h" 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate #include "ring.h" 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate #include "externs.h" 587c478bd9Sstevel@tonic-gate #include "defines.h" 597c478bd9Sstevel@tonic-gate #include "types.h" 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate extern char *telnet_krb5_realm; 627c478bd9Sstevel@tonic-gate extern void krb5_profile_get_options(char *, char *, 637c478bd9Sstevel@tonic-gate profile_options_boolean*); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate #include <k5-int.h> 667c478bd9Sstevel@tonic-gate #include <profile/prof_int.h> 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate profile_options_boolean config_file_options[] = { 697c478bd9Sstevel@tonic-gate { "forwardable", &forwardable_flag, 0}, 707c478bd9Sstevel@tonic-gate { "forward", &forward_flag, 0}, 717c478bd9Sstevel@tonic-gate { "encrypt", &encrypt_flag, 0 }, 727c478bd9Sstevel@tonic-gate { "autologin", &autologin, 0 }, 737c478bd9Sstevel@tonic-gate { NULL, NULL, 0} 747c478bd9Sstevel@tonic-gate }; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate #include <netinet/ip.h> 777c478bd9Sstevel@tonic-gate 787c478bd9Sstevel@tonic-gate /* 797c478bd9Sstevel@tonic-gate * Number of maximum IPv4 gateways user can specify. This number is limited by 807c478bd9Sstevel@tonic-gate * the maximum size of the IPv4 options in the IPv4 header. 817c478bd9Sstevel@tonic-gate */ 827c478bd9Sstevel@tonic-gate #define MAX_GATEWAY 8 837c478bd9Sstevel@tonic-gate /* 847c478bd9Sstevel@tonic-gate * Number of maximum IPv6 gateways user can specify. This number is limited by 857c478bd9Sstevel@tonic-gate * the maximum header extension length of the IPv6 routing header. 867c478bd9Sstevel@tonic-gate */ 877c478bd9Sstevel@tonic-gate #define MAX_GATEWAY6 127 887c478bd9Sstevel@tonic-gate #define MAXMAX_GATEWAY MAX(MAX_GATEWAY, MAX_GATEWAY6) 897c478bd9Sstevel@tonic-gate 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate * Depending on the address resolutions of the target and gateways, 927c478bd9Sstevel@tonic-gate * we determine which addresses of the target we'll try connecting to. 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate #define ALL_ADDRS 0 /* try all addrs of target */ 957c478bd9Sstevel@tonic-gate #define ONLY_V4 1 /* try only IPv4 addrs of target */ 967c478bd9Sstevel@tonic-gate #define ONLY_V6 2 /* try only IPv6 addrs of target */ 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate #if defined(USE_TOS) 997c478bd9Sstevel@tonic-gate int tos = -1; 1007c478bd9Sstevel@tonic-gate #endif 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate char *hostname; 1037c478bd9Sstevel@tonic-gate static char _hostname[MAXHOSTNAMELEN]; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate static int send_tncmd(void (*func)(), char *, char *); 1067c478bd9Sstevel@tonic-gate static void call(int n_ptrs, ...); 1077c478bd9Sstevel@tonic-gate static int cmdrc(char *, char *); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate typedef struct { 1107c478bd9Sstevel@tonic-gate char *name; /* command name */ 1117c478bd9Sstevel@tonic-gate char *help; /* help string (NULL for no help) */ 1127c478bd9Sstevel@tonic-gate int (*handler)(); /* routine which executes command */ 1137c478bd9Sstevel@tonic-gate int needconnect; /* Do we need to be connected to execute? */ 1147c478bd9Sstevel@tonic-gate } Command; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * storage for IPv6 and/or IPv4 addresses of gateways 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate struct gateway { 1207c478bd9Sstevel@tonic-gate struct in6_addr gw_addr6; 1217c478bd9Sstevel@tonic-gate struct in_addr gw_addr; 1227c478bd9Sstevel@tonic-gate }; 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate /* 1257c478bd9Sstevel@tonic-gate * IPv4 source routing option. 1267c478bd9Sstevel@tonic-gate * In order to avoid padding for the alignment of IPv4 addresses, ipsr_addrs 1277c478bd9Sstevel@tonic-gate * is defined as a 2-D array of uint8_t, instead of 1-D array of struct in_addr. 1287c478bd9Sstevel@tonic-gate * If it were defined as "struct in_addr ipsr_addrs[1]", "ipsr_ptr" would be 1297c478bd9Sstevel@tonic-gate * followed by one byte of padding to avoid misaligned struct in_addr. 1307c478bd9Sstevel@tonic-gate */ 1317c478bd9Sstevel@tonic-gate struct ip_sourceroute { 1327c478bd9Sstevel@tonic-gate uint8_t ipsr_code; 1337c478bd9Sstevel@tonic-gate uint8_t ipsr_len; 1347c478bd9Sstevel@tonic-gate uint8_t ipsr_ptr; 1357c478bd9Sstevel@tonic-gate /* up to 9 IPv4 addresses */ 1367c478bd9Sstevel@tonic-gate uint8_t ipsr_addrs[1][sizeof (struct in_addr)]; 1377c478bd9Sstevel@tonic-gate }; 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate static char *line = NULL; 1407c478bd9Sstevel@tonic-gate static unsigned linesize = 0; 1417c478bd9Sstevel@tonic-gate static int margc; 1427c478bd9Sstevel@tonic-gate static char **margv = NULL; 1437c478bd9Sstevel@tonic-gate static unsigned margvlen = 0; 1447c478bd9Sstevel@tonic-gate static int doing_rc = 0; /* .telnetrc file is being read and processed */ 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate static void 1477c478bd9Sstevel@tonic-gate Close(int *fd) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate if (*fd != -1) { 1507c478bd9Sstevel@tonic-gate (void) close(*fd); 1517c478bd9Sstevel@tonic-gate *fd = -1; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate static void 1567c478bd9Sstevel@tonic-gate Free(char **p) 1577c478bd9Sstevel@tonic-gate { 1587c478bd9Sstevel@tonic-gate if (*p != NULL) { 1597c478bd9Sstevel@tonic-gate free(*p); 1607c478bd9Sstevel@tonic-gate *p = NULL; 1617c478bd9Sstevel@tonic-gate } 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate 1647c478bd9Sstevel@tonic-gate static void 1657c478bd9Sstevel@tonic-gate FreeHostnameList(char *list[]) 1667c478bd9Sstevel@tonic-gate { 1677c478bd9Sstevel@tonic-gate unsigned i; 1687c478bd9Sstevel@tonic-gate for (i = 0; i <= MAXMAX_GATEWAY && list[i] != NULL; i++) 1697c478bd9Sstevel@tonic-gate Free(&list[i]); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate #define MARGV_CHUNK_SIZE 8 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate static void 1757c478bd9Sstevel@tonic-gate set_argv(str) 1767c478bd9Sstevel@tonic-gate char *str; 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate if (margc == margvlen) { 1797c478bd9Sstevel@tonic-gate char **newmargv; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate margvlen += MARGV_CHUNK_SIZE; 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate if ((newmargv = realloc(margv, margvlen * sizeof (char *))) 1847c478bd9Sstevel@tonic-gate == NULL) 1857c478bd9Sstevel@tonic-gate ExitString("telnet: no space for arguments", 1867c478bd9Sstevel@tonic-gate EXIT_FAILURE); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate margv = newmargv; 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate margv[margc] = str; 1927c478bd9Sstevel@tonic-gate if (str != NULL) 1937c478bd9Sstevel@tonic-gate margc++; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate 1967c478bd9Sstevel@tonic-gate static void 1977c478bd9Sstevel@tonic-gate makeargv() 1987c478bd9Sstevel@tonic-gate { 1997c478bd9Sstevel@tonic-gate char *cp, *cp2, c; 2007c478bd9Sstevel@tonic-gate boolean_t shellcmd = B_FALSE; 2017c478bd9Sstevel@tonic-gate 2027c478bd9Sstevel@tonic-gate margc = 0; 2037c478bd9Sstevel@tonic-gate cp = line; 2047c478bd9Sstevel@tonic-gate if (*cp == '!') { /* Special case shell escape */ 2057c478bd9Sstevel@tonic-gate set_argv("!"); /* No room in string to get this */ 2067c478bd9Sstevel@tonic-gate cp++; 2077c478bd9Sstevel@tonic-gate shellcmd = B_TRUE; 2087c478bd9Sstevel@tonic-gate } 2097c478bd9Sstevel@tonic-gate while ((c = *cp) != '\0') { 2107c478bd9Sstevel@tonic-gate register int inquote = 0; 2117c478bd9Sstevel@tonic-gate while (isspace(c)) 2127c478bd9Sstevel@tonic-gate c = *++cp; 2137c478bd9Sstevel@tonic-gate if (c == '\0') 2147c478bd9Sstevel@tonic-gate break; 2157c478bd9Sstevel@tonic-gate set_argv(cp); 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * For the shell escape, put the rest of the line, less 2187c478bd9Sstevel@tonic-gate * leading space, into a single argument, breaking out from 2197c478bd9Sstevel@tonic-gate * the loop to prevent the rest of the line being split up 2207c478bd9Sstevel@tonic-gate * into smaller arguments. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate if (shellcmd) 2237c478bd9Sstevel@tonic-gate break; 2247c478bd9Sstevel@tonic-gate for (cp2 = cp; c != '\0'; c = *++cp) { 2257c478bd9Sstevel@tonic-gate if (inquote) { 2267c478bd9Sstevel@tonic-gate if (c == inquote) { 2277c478bd9Sstevel@tonic-gate inquote = 0; 2287c478bd9Sstevel@tonic-gate continue; 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate } else { 2317c478bd9Sstevel@tonic-gate if (c == '\\') { 2327c478bd9Sstevel@tonic-gate if ((c = *++cp) == '\0') 2337c478bd9Sstevel@tonic-gate break; 2347c478bd9Sstevel@tonic-gate } else if (c == '"') { 2357c478bd9Sstevel@tonic-gate inquote = '"'; 2367c478bd9Sstevel@tonic-gate continue; 2377c478bd9Sstevel@tonic-gate } else if (c == '\'') { 2387c478bd9Sstevel@tonic-gate inquote = '\''; 2397c478bd9Sstevel@tonic-gate continue; 2407c478bd9Sstevel@tonic-gate } else if (isspace(c)) 2417c478bd9Sstevel@tonic-gate break; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate *cp2++ = c; 2447c478bd9Sstevel@tonic-gate } 2457c478bd9Sstevel@tonic-gate *cp2 = '\0'; 2467c478bd9Sstevel@tonic-gate if (c == '\0') 2477c478bd9Sstevel@tonic-gate break; 2487c478bd9Sstevel@tonic-gate cp++; 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate set_argv((char *)NULL); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate /* 2547c478bd9Sstevel@tonic-gate * Make a character string into a number. 2557c478bd9Sstevel@tonic-gate * 2567c478bd9Sstevel@tonic-gate * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 2577c478bd9Sstevel@tonic-gate */ 2587c478bd9Sstevel@tonic-gate 259740638c8Sbw static int 2607c478bd9Sstevel@tonic-gate special(s) 2617c478bd9Sstevel@tonic-gate register char *s; 2627c478bd9Sstevel@tonic-gate { 2637c478bd9Sstevel@tonic-gate register char c; 2647c478bd9Sstevel@tonic-gate char b; 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate switch (*s) { 2677c478bd9Sstevel@tonic-gate case '^': 2687c478bd9Sstevel@tonic-gate b = *++s; 2697c478bd9Sstevel@tonic-gate if (b == '?') { 2707c478bd9Sstevel@tonic-gate c = b | 0x40; /* DEL */ 2717c478bd9Sstevel@tonic-gate } else { 2727c478bd9Sstevel@tonic-gate c = b & 0x1f; 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate break; 2757c478bd9Sstevel@tonic-gate default: 2767c478bd9Sstevel@tonic-gate c = *s; 2777c478bd9Sstevel@tonic-gate break; 2787c478bd9Sstevel@tonic-gate } 2797c478bd9Sstevel@tonic-gate return (c); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * Construct a control character sequence 2847c478bd9Sstevel@tonic-gate * for a special character. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate static char * 2877c478bd9Sstevel@tonic-gate control(c) 2887c478bd9Sstevel@tonic-gate register cc_t c; 2897c478bd9Sstevel@tonic-gate { 2907c478bd9Sstevel@tonic-gate static char buf[5]; 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * The only way I could get the Sun 3.5 compiler 2937c478bd9Sstevel@tonic-gate * to shut up about 2947c478bd9Sstevel@tonic-gate * if ((unsigned int)c >= 0x80) 2957c478bd9Sstevel@tonic-gate * was to assign "c" to an unsigned int variable... 2967c478bd9Sstevel@tonic-gate * Arggg.... 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate register unsigned int uic = (unsigned int)c; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate if (uic == 0x7f) 3017c478bd9Sstevel@tonic-gate return ("^?"); 3027c478bd9Sstevel@tonic-gate if (c == (cc_t)_POSIX_VDISABLE) { 3037c478bd9Sstevel@tonic-gate return ("off"); 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate if (uic >= 0x80) { 3067c478bd9Sstevel@tonic-gate buf[0] = '\\'; 3077c478bd9Sstevel@tonic-gate buf[1] = ((c>>6)&07) + '0'; 3087c478bd9Sstevel@tonic-gate buf[2] = ((c>>3)&07) + '0'; 3097c478bd9Sstevel@tonic-gate buf[3] = (c&07) + '0'; 3107c478bd9Sstevel@tonic-gate buf[4] = 0; 3117c478bd9Sstevel@tonic-gate } else if (uic >= 0x20) { 3127c478bd9Sstevel@tonic-gate buf[0] = c; 3137c478bd9Sstevel@tonic-gate buf[1] = 0; 3147c478bd9Sstevel@tonic-gate } else { 3157c478bd9Sstevel@tonic-gate buf[0] = '^'; 3167c478bd9Sstevel@tonic-gate buf[1] = '@'+c; 3177c478bd9Sstevel@tonic-gate buf[2] = 0; 3187c478bd9Sstevel@tonic-gate } 3197c478bd9Sstevel@tonic-gate return (buf); 3207c478bd9Sstevel@tonic-gate } 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* 3237c478bd9Sstevel@tonic-gate * Same as control() except that its only used for escape handling, which uses 3247c478bd9Sstevel@tonic-gate * _POSIX_VDISABLE differently and is aided by the use of the state variable 3257c478bd9Sstevel@tonic-gate * escape_valid. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate static char * 3287c478bd9Sstevel@tonic-gate esc_control(c) 3297c478bd9Sstevel@tonic-gate register cc_t c; 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate static char buf[5]; 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * The only way I could get the Sun 3.5 compiler 3347c478bd9Sstevel@tonic-gate * to shut up about 3357c478bd9Sstevel@tonic-gate * if ((unsigned int)c >= 0x80) 3367c478bd9Sstevel@tonic-gate * was to assign "c" to an unsigned int variable... 3377c478bd9Sstevel@tonic-gate * Arggg.... 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate register unsigned int uic = (unsigned int)c; 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate if (escape_valid == B_FALSE) 3427c478bd9Sstevel@tonic-gate return ("off"); 3437c478bd9Sstevel@tonic-gate if (uic == 0x7f) 3447c478bd9Sstevel@tonic-gate return ("^?"); 3457c478bd9Sstevel@tonic-gate if (uic >= 0x80) { 3467c478bd9Sstevel@tonic-gate buf[0] = '\\'; 3477c478bd9Sstevel@tonic-gate buf[1] = ((c>>6)&07) + '0'; 3487c478bd9Sstevel@tonic-gate buf[2] = ((c>>3)&07) + '0'; 3497c478bd9Sstevel@tonic-gate buf[3] = (c&07) + '0'; 3507c478bd9Sstevel@tonic-gate buf[4] = 0; 3517c478bd9Sstevel@tonic-gate } else if (uic >= 0x20) { 3527c478bd9Sstevel@tonic-gate buf[0] = c; 3537c478bd9Sstevel@tonic-gate buf[1] = 0; 3547c478bd9Sstevel@tonic-gate } else { 3557c478bd9Sstevel@tonic-gate buf[0] = '^'; 3567c478bd9Sstevel@tonic-gate buf[1] = '@'+c; 3577c478bd9Sstevel@tonic-gate buf[2] = 0; 3587c478bd9Sstevel@tonic-gate } 3597c478bd9Sstevel@tonic-gate return (buf); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * The following are data structures and routines for 3647c478bd9Sstevel@tonic-gate * the "send" command. 3657c478bd9Sstevel@tonic-gate * 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate struct sendlist { 3697c478bd9Sstevel@tonic-gate char *name; /* How user refers to it (case independent) */ 3707c478bd9Sstevel@tonic-gate char *help; /* Help information (0 ==> no help) */ 3717c478bd9Sstevel@tonic-gate int needconnect; /* Need to be connected */ 3727c478bd9Sstevel@tonic-gate int narg; /* Number of arguments */ 3737c478bd9Sstevel@tonic-gate int (*handler)(); /* Routine to perform (for special ops) */ 3747c478bd9Sstevel@tonic-gate int nbyte; /* Number of bytes to send this command */ 3757c478bd9Sstevel@tonic-gate int what; /* Character to be sent (<0 ==> special) */ 3767c478bd9Sstevel@tonic-gate }; 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate 3797c478bd9Sstevel@tonic-gate static int send_esc(void); 3807c478bd9Sstevel@tonic-gate static int send_help(void); 3817c478bd9Sstevel@tonic-gate static int send_docmd(char *); 3827c478bd9Sstevel@tonic-gate static int send_dontcmd(char *); 3837c478bd9Sstevel@tonic-gate static int send_willcmd(char *); 3847c478bd9Sstevel@tonic-gate static int send_wontcmd(char *); 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate static struct sendlist Sendlist[] = { 3877c478bd9Sstevel@tonic-gate { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, 3887c478bd9Sstevel@tonic-gate { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, 3897c478bd9Sstevel@tonic-gate { "b", 0, 1, 0, 0, 2, BREAK }, 3907c478bd9Sstevel@tonic-gate { "br", 0, 1, 0, 0, 2, BREAK }, 3917c478bd9Sstevel@tonic-gate { "break", 0, 1, 0, 0, 2, BREAK }, 3927c478bd9Sstevel@tonic-gate { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, 3937c478bd9Sstevel@tonic-gate { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, 3947c478bd9Sstevel@tonic-gate { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, 3957c478bd9Sstevel@tonic-gate { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, 3967c478bd9Sstevel@tonic-gate { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, 3977c478bd9Sstevel@tonic-gate { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, 3987c478bd9Sstevel@tonic-gate { "intp", 0, 1, 0, 0, 2, IP }, 3997c478bd9Sstevel@tonic-gate { "interrupt", 0, 1, 0, 0, 2, IP }, 4007c478bd9Sstevel@tonic-gate { "intr", 0, 1, 0, 0, 2, IP }, 4017c478bd9Sstevel@tonic-gate { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, 4027c478bd9Sstevel@tonic-gate { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, 4037c478bd9Sstevel@tonic-gate { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, 4047c478bd9Sstevel@tonic-gate { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, 4057c478bd9Sstevel@tonic-gate { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, 4067c478bd9Sstevel@tonic-gate { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, 4077c478bd9Sstevel@tonic-gate { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, 4087c478bd9Sstevel@tonic-gate { "?", "Display send options", 0, 0, send_help, 0, 0 }, 4097c478bd9Sstevel@tonic-gate { "help", 0, 0, 0, send_help, 0, 0 }, 4107c478bd9Sstevel@tonic-gate { "do", 0, 0, 1, send_docmd, 3, 0 }, 4117c478bd9Sstevel@tonic-gate { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, 4127c478bd9Sstevel@tonic-gate { "will", 0, 0, 1, send_willcmd, 3, 0 }, 4137c478bd9Sstevel@tonic-gate { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, 4147c478bd9Sstevel@tonic-gate { 0 } 4157c478bd9Sstevel@tonic-gate }; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate #define GETSEND(name) ((struct sendlist *)genget(name, (char **)Sendlist, \ 4187c478bd9Sstevel@tonic-gate sizeof (struct sendlist))) 4197c478bd9Sstevel@tonic-gate 4207c478bd9Sstevel@tonic-gate static int 4217c478bd9Sstevel@tonic-gate sendcmd(argc, argv) 4227c478bd9Sstevel@tonic-gate int argc; 4237c478bd9Sstevel@tonic-gate char **argv; 4247c478bd9Sstevel@tonic-gate { 4257c478bd9Sstevel@tonic-gate int count; /* how many bytes we are going to need to send */ 4267c478bd9Sstevel@tonic-gate int i; 4277c478bd9Sstevel@tonic-gate struct sendlist *s; /* pointer to current command */ 4287c478bd9Sstevel@tonic-gate int success = 0; 4297c478bd9Sstevel@tonic-gate int needconnect = 0; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate if (argc < 2) { 4327c478bd9Sstevel@tonic-gate (void) printf( 4337c478bd9Sstevel@tonic-gate "need at least one argument for 'send' command\n"); 4347c478bd9Sstevel@tonic-gate (void) printf("'send ?' for help\n"); 4357c478bd9Sstevel@tonic-gate return (0); 4367c478bd9Sstevel@tonic-gate } 4377c478bd9Sstevel@tonic-gate /* 4387c478bd9Sstevel@tonic-gate * First, validate all the send arguments. 4397c478bd9Sstevel@tonic-gate * In addition, we see how much space we are going to need, and 4407c478bd9Sstevel@tonic-gate * whether or not we will be doing a "SYNCH" operation (which 4417c478bd9Sstevel@tonic-gate * flushes the network queue). 4427c478bd9Sstevel@tonic-gate */ 4437c478bd9Sstevel@tonic-gate count = 0; 4447c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 4457c478bd9Sstevel@tonic-gate s = GETSEND(argv[i]); 4467c478bd9Sstevel@tonic-gate if (s == 0) { 4477c478bd9Sstevel@tonic-gate (void) printf("Unknown send argument '%s'\n'send ?' " 4487c478bd9Sstevel@tonic-gate "for help.\n", argv[i]); 4497c478bd9Sstevel@tonic-gate return (0); 4507c478bd9Sstevel@tonic-gate } else if (Ambiguous(s)) { 4517c478bd9Sstevel@tonic-gate (void) printf("Ambiguous send argument '%s'\n'send ?' " 4527c478bd9Sstevel@tonic-gate "for help.\n", argv[i]); 4537c478bd9Sstevel@tonic-gate return (0); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate if (i + s->narg >= argc) { 4567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4577c478bd9Sstevel@tonic-gate "Need %d argument%s to 'send %s' " 4587c478bd9Sstevel@tonic-gate "command. 'send %s ?' for help.\n", 4597c478bd9Sstevel@tonic-gate s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 4607c478bd9Sstevel@tonic-gate return (0); 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate count += s->nbyte; 4637c478bd9Sstevel@tonic-gate if (s->handler == send_help) { 4647c478bd9Sstevel@tonic-gate (void) send_help(); 4657c478bd9Sstevel@tonic-gate return (0); 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate i += s->narg; 4697c478bd9Sstevel@tonic-gate needconnect += s->needconnect; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate if (!connected && needconnect) { 4727c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 4737c478bd9Sstevel@tonic-gate (void) printf("'send ?' for help\n"); 4747c478bd9Sstevel@tonic-gate return (0); 4757c478bd9Sstevel@tonic-gate } 4767c478bd9Sstevel@tonic-gate /* Now, do we have enough room? */ 4777c478bd9Sstevel@tonic-gate if (NETROOM() < count) { 4787c478bd9Sstevel@tonic-gate (void) printf("There is not enough room in the buffer " 4797c478bd9Sstevel@tonic-gate "TO the network\n"); 4807c478bd9Sstevel@tonic-gate (void) printf( 4817c478bd9Sstevel@tonic-gate "to process your request. Nothing will be done.\n"); 4827c478bd9Sstevel@tonic-gate (void) printf("('send synch' will throw away most " 4837c478bd9Sstevel@tonic-gate "data in the network\n"); 4847c478bd9Sstevel@tonic-gate (void) printf("buffer, if this might help.)\n"); 4857c478bd9Sstevel@tonic-gate return (0); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate /* OK, they are all OK, now go through again and actually send */ 4887c478bd9Sstevel@tonic-gate count = 0; 4897c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 4907c478bd9Sstevel@tonic-gate if ((s = GETSEND(argv[i])) == 0) { 4917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 4927c478bd9Sstevel@tonic-gate "Telnet 'send' error - argument disappeared!\n"); 4937c478bd9Sstevel@tonic-gate (void) quit(); 4947c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4957c478bd9Sstevel@tonic-gate } 4967c478bd9Sstevel@tonic-gate if (s->handler) { 4977c478bd9Sstevel@tonic-gate count++; 4987c478bd9Sstevel@tonic-gate success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 4997c478bd9Sstevel@tonic-gate (s->narg > 1) ? argv[i+2] : 0); 5007c478bd9Sstevel@tonic-gate i += s->narg; 5017c478bd9Sstevel@tonic-gate } else { 5027c478bd9Sstevel@tonic-gate NET2ADD(IAC, s->what); 5037c478bd9Sstevel@tonic-gate printoption("SENT", IAC, s->what); 5047c478bd9Sstevel@tonic-gate } 5057c478bd9Sstevel@tonic-gate } 5067c478bd9Sstevel@tonic-gate return (count == success); 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate static int 5107c478bd9Sstevel@tonic-gate send_esc() 5117c478bd9Sstevel@tonic-gate { 5127c478bd9Sstevel@tonic-gate NETADD(escape); 5137c478bd9Sstevel@tonic-gate return (1); 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate static int 5177c478bd9Sstevel@tonic-gate send_docmd(name) 5187c478bd9Sstevel@tonic-gate char *name; 5197c478bd9Sstevel@tonic-gate { 5207c478bd9Sstevel@tonic-gate return (send_tncmd(send_do, "do", name)); 5217c478bd9Sstevel@tonic-gate } 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate static int 5247c478bd9Sstevel@tonic-gate send_dontcmd(name) 5257c478bd9Sstevel@tonic-gate char *name; 5267c478bd9Sstevel@tonic-gate { 5277c478bd9Sstevel@tonic-gate return (send_tncmd(send_dont, "dont", name)); 5287c478bd9Sstevel@tonic-gate } 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate static int 5317c478bd9Sstevel@tonic-gate send_willcmd(name) 5327c478bd9Sstevel@tonic-gate char *name; 5337c478bd9Sstevel@tonic-gate { 5347c478bd9Sstevel@tonic-gate return (send_tncmd(send_will, "will", name)); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate 5377c478bd9Sstevel@tonic-gate static int 5387c478bd9Sstevel@tonic-gate send_wontcmd(name) 5397c478bd9Sstevel@tonic-gate char *name; 5407c478bd9Sstevel@tonic-gate { 5417c478bd9Sstevel@tonic-gate return (send_tncmd(send_wont, "wont", name)); 5427c478bd9Sstevel@tonic-gate } 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate int 5457c478bd9Sstevel@tonic-gate send_tncmd(func, cmd, name) 5467c478bd9Sstevel@tonic-gate void (*func)(); 5477c478bd9Sstevel@tonic-gate char *cmd, *name; 5487c478bd9Sstevel@tonic-gate { 5497c478bd9Sstevel@tonic-gate char **cpp; 5507c478bd9Sstevel@tonic-gate extern char *telopts[]; 5517c478bd9Sstevel@tonic-gate register int val = 0; 5527c478bd9Sstevel@tonic-gate 5537c478bd9Sstevel@tonic-gate if (isprefix(name, "help") || isprefix(name, "?")) { 5547c478bd9Sstevel@tonic-gate register int col, len; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate (void) printf("Usage: send %s <value|option>\n", cmd); 5577c478bd9Sstevel@tonic-gate (void) printf("\"value\" must be from 0 to 255\n"); 5587c478bd9Sstevel@tonic-gate (void) printf("Valid options are:\n\t"); 5597c478bd9Sstevel@tonic-gate 5607c478bd9Sstevel@tonic-gate col = 8; 5617c478bd9Sstevel@tonic-gate for (cpp = telopts; *cpp; cpp++) { 5627c478bd9Sstevel@tonic-gate len = strlen(*cpp) + 3; 5637c478bd9Sstevel@tonic-gate if (col + len > 65) { 5647c478bd9Sstevel@tonic-gate (void) printf("\n\t"); 5657c478bd9Sstevel@tonic-gate col = 8; 5667c478bd9Sstevel@tonic-gate } 5677c478bd9Sstevel@tonic-gate (void) printf(" \"%s\"", *cpp); 5687c478bd9Sstevel@tonic-gate col += len; 5697c478bd9Sstevel@tonic-gate } 5707c478bd9Sstevel@tonic-gate (void) printf("\n"); 5717c478bd9Sstevel@tonic-gate return (0); 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate cpp = (char **)genget(name, telopts, sizeof (char *)); 5747c478bd9Sstevel@tonic-gate if (Ambiguous(cpp)) { 5757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5767c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('send %s ?' for help).\n", 5777c478bd9Sstevel@tonic-gate name, cmd); 5787c478bd9Sstevel@tonic-gate return (0); 5797c478bd9Sstevel@tonic-gate } 5807c478bd9Sstevel@tonic-gate if (cpp) { 5817c478bd9Sstevel@tonic-gate val = cpp - telopts; 5827c478bd9Sstevel@tonic-gate } else { 5837c478bd9Sstevel@tonic-gate register char *cp = name; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate while (*cp >= '0' && *cp <= '9') { 5867c478bd9Sstevel@tonic-gate val *= 10; 5877c478bd9Sstevel@tonic-gate val += *cp - '0'; 5887c478bd9Sstevel@tonic-gate cp++; 5897c478bd9Sstevel@tonic-gate } 5907c478bd9Sstevel@tonic-gate if (*cp != 0) { 5917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5927c478bd9Sstevel@tonic-gate "'%s': unknown argument ('send %s ?' for help).\n", 5937c478bd9Sstevel@tonic-gate name, cmd); 5947c478bd9Sstevel@tonic-gate return (0); 5957c478bd9Sstevel@tonic-gate } else if (val < 0 || val > 255) { 5967c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 5977c478bd9Sstevel@tonic-gate "'%s': bad value ('send %s ?' for help).\n", 5987c478bd9Sstevel@tonic-gate name, cmd); 5997c478bd9Sstevel@tonic-gate return (0); 6007c478bd9Sstevel@tonic-gate } 6017c478bd9Sstevel@tonic-gate } 6027c478bd9Sstevel@tonic-gate if (!connected) { 6037c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 6047c478bd9Sstevel@tonic-gate return (0); 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate (*func)(val, 1); 6077c478bd9Sstevel@tonic-gate return (1); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate static int 6117c478bd9Sstevel@tonic-gate send_help() 6127c478bd9Sstevel@tonic-gate { 6137c478bd9Sstevel@tonic-gate struct sendlist *s; /* pointer to current command */ 6147c478bd9Sstevel@tonic-gate for (s = Sendlist; s->name; s++) { 6157c478bd9Sstevel@tonic-gate if (s->help) 6167c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", s->name, s->help); 6177c478bd9Sstevel@tonic-gate } 6187c478bd9Sstevel@tonic-gate return (0); 6197c478bd9Sstevel@tonic-gate } 6207c478bd9Sstevel@tonic-gate 6217c478bd9Sstevel@tonic-gate /* 6227c478bd9Sstevel@tonic-gate * The following are the routines and data structures referred 6237c478bd9Sstevel@tonic-gate * to by the arguments to the "toggle" command. 6247c478bd9Sstevel@tonic-gate */ 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate static int 6277c478bd9Sstevel@tonic-gate lclchars() 6287c478bd9Sstevel@tonic-gate { 6297c478bd9Sstevel@tonic-gate donelclchars = 1; 6307c478bd9Sstevel@tonic-gate return (1); 6317c478bd9Sstevel@tonic-gate } 6327c478bd9Sstevel@tonic-gate 6337c478bd9Sstevel@tonic-gate static int 6347c478bd9Sstevel@tonic-gate togdebug() 6357c478bd9Sstevel@tonic-gate { 6367c478bd9Sstevel@tonic-gate if (net > 0 && 6377c478bd9Sstevel@tonic-gate (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 6387c478bd9Sstevel@tonic-gate perror("setsockopt (SO_DEBUG)"); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate return (1); 6417c478bd9Sstevel@tonic-gate } 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate static int 6457c478bd9Sstevel@tonic-gate togcrlf() 6467c478bd9Sstevel@tonic-gate { 6477c478bd9Sstevel@tonic-gate if (crlf) { 6487c478bd9Sstevel@tonic-gate (void) printf( 6497c478bd9Sstevel@tonic-gate "Will send carriage returns as telnet <CR><LF>.\n"); 6507c478bd9Sstevel@tonic-gate } else { 6517c478bd9Sstevel@tonic-gate (void) printf( 6527c478bd9Sstevel@tonic-gate "Will send carriage returns as telnet <CR><NUL>.\n"); 6537c478bd9Sstevel@tonic-gate } 6547c478bd9Sstevel@tonic-gate return (1); 6557c478bd9Sstevel@tonic-gate } 6567c478bd9Sstevel@tonic-gate 6577c478bd9Sstevel@tonic-gate static int binmode; 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate static int 6607c478bd9Sstevel@tonic-gate togbinary(val) 6617c478bd9Sstevel@tonic-gate int val; 6627c478bd9Sstevel@tonic-gate { 6637c478bd9Sstevel@tonic-gate donebinarytoggle = 1; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (val >= 0) { 6667c478bd9Sstevel@tonic-gate binmode = val; 6677c478bd9Sstevel@tonic-gate } else { 6687c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_BINARY) && 6697c478bd9Sstevel@tonic-gate my_want_state_is_do(TELOPT_BINARY)) { 6707c478bd9Sstevel@tonic-gate binmode = 1; 6717c478bd9Sstevel@tonic-gate } else if (my_want_state_is_wont(TELOPT_BINARY) && 6727c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_BINARY)) { 6737c478bd9Sstevel@tonic-gate binmode = 0; 6747c478bd9Sstevel@tonic-gate } 6757c478bd9Sstevel@tonic-gate val = binmode ? 0 : 1; 6767c478bd9Sstevel@tonic-gate } 6777c478bd9Sstevel@tonic-gate 6787c478bd9Sstevel@tonic-gate if (val == 1) { 6797c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_BINARY) && 6807c478bd9Sstevel@tonic-gate my_want_state_is_do(TELOPT_BINARY)) { 6817c478bd9Sstevel@tonic-gate (void) printf("Already operating in binary mode " 6827c478bd9Sstevel@tonic-gate "with remote host.\n"); 6837c478bd9Sstevel@tonic-gate } else { 6847c478bd9Sstevel@tonic-gate (void) printf( 6857c478bd9Sstevel@tonic-gate "Negotiating binary mode with remote host.\n"); 6867c478bd9Sstevel@tonic-gate tel_enter_binary(3); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate } else { 6897c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_BINARY) && 6907c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_BINARY)) { 6917c478bd9Sstevel@tonic-gate (void) printf("Already in network ascii mode " 6927c478bd9Sstevel@tonic-gate "with remote host.\n"); 6937c478bd9Sstevel@tonic-gate } else { 6947c478bd9Sstevel@tonic-gate (void) printf("Negotiating network ascii mode " 6957c478bd9Sstevel@tonic-gate "with remote host.\n"); 6967c478bd9Sstevel@tonic-gate tel_leave_binary(3); 6977c478bd9Sstevel@tonic-gate } 6987c478bd9Sstevel@tonic-gate } 6997c478bd9Sstevel@tonic-gate return (1); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate static int 7037c478bd9Sstevel@tonic-gate togrbinary(val) 7047c478bd9Sstevel@tonic-gate int val; 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate donebinarytoggle = 1; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (val == -1) 7097c478bd9Sstevel@tonic-gate val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate if (val == 1) { 7127c478bd9Sstevel@tonic-gate if (my_want_state_is_do(TELOPT_BINARY)) { 7137c478bd9Sstevel@tonic-gate (void) printf("Already receiving in binary mode.\n"); 7147c478bd9Sstevel@tonic-gate } else { 7157c478bd9Sstevel@tonic-gate (void) printf("Negotiating binary mode on input.\n"); 7167c478bd9Sstevel@tonic-gate tel_enter_binary(1); 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate } else { 7197c478bd9Sstevel@tonic-gate if (my_want_state_is_dont(TELOPT_BINARY)) { 7207c478bd9Sstevel@tonic-gate (void) printf( 7217c478bd9Sstevel@tonic-gate "Already receiving in network ascii mode.\n"); 7227c478bd9Sstevel@tonic-gate } else { 7237c478bd9Sstevel@tonic-gate (void) printf( 7247c478bd9Sstevel@tonic-gate "Negotiating network ascii mode on input.\n"); 7257c478bd9Sstevel@tonic-gate tel_leave_binary(1); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate return (1); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317c478bd9Sstevel@tonic-gate static int 7327c478bd9Sstevel@tonic-gate togxbinary(val) 7337c478bd9Sstevel@tonic-gate int val; 7347c478bd9Sstevel@tonic-gate { 7357c478bd9Sstevel@tonic-gate donebinarytoggle = 1; 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate if (val == -1) 7387c478bd9Sstevel@tonic-gate val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate if (val == 1) { 7417c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_BINARY)) { 7427c478bd9Sstevel@tonic-gate (void) printf("Already transmitting in binary mode.\n"); 7437c478bd9Sstevel@tonic-gate } else { 7447c478bd9Sstevel@tonic-gate (void) printf("Negotiating binary mode on output.\n"); 7457c478bd9Sstevel@tonic-gate tel_enter_binary(2); 7467c478bd9Sstevel@tonic-gate } 7477c478bd9Sstevel@tonic-gate } else { 7487c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_BINARY)) { 7497c478bd9Sstevel@tonic-gate (void) printf( 7507c478bd9Sstevel@tonic-gate "Already transmitting in network ascii mode.\n"); 7517c478bd9Sstevel@tonic-gate } else { 7527c478bd9Sstevel@tonic-gate (void) printf( 7537c478bd9Sstevel@tonic-gate "Negotiating network ascii mode on output.\n"); 7547c478bd9Sstevel@tonic-gate tel_leave_binary(2); 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate return (1); 7587c478bd9Sstevel@tonic-gate } 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate static int togglehelp(void); 7627c478bd9Sstevel@tonic-gate extern int auth_togdebug(int); 7637c478bd9Sstevel@tonic-gate 7647c478bd9Sstevel@tonic-gate struct togglelist { 7657c478bd9Sstevel@tonic-gate char *name; /* name of toggle */ 7667c478bd9Sstevel@tonic-gate char *help; /* help message */ 7677c478bd9Sstevel@tonic-gate int (*handler)(); /* routine to do actual setting */ 7687c478bd9Sstevel@tonic-gate int *variable; 7697c478bd9Sstevel@tonic-gate char *actionexplanation; 7707c478bd9Sstevel@tonic-gate }; 7717c478bd9Sstevel@tonic-gate 7727c478bd9Sstevel@tonic-gate static struct togglelist Togglelist[] = { 7737c478bd9Sstevel@tonic-gate { "autoflush", 7747c478bd9Sstevel@tonic-gate "flushing of output when sending interrupt characters", 7757c478bd9Sstevel@tonic-gate 0, 7767c478bd9Sstevel@tonic-gate &autoflush, 7777c478bd9Sstevel@tonic-gate "flush output when sending interrupt characters" }, 7787c478bd9Sstevel@tonic-gate { "autosynch", 7797c478bd9Sstevel@tonic-gate "automatic sending of interrupt characters in urgent mode", 7807c478bd9Sstevel@tonic-gate 0, 7817c478bd9Sstevel@tonic-gate &autosynch, 7827c478bd9Sstevel@tonic-gate "send interrupt characters in urgent mode" }, 7837c478bd9Sstevel@tonic-gate { "autologin", 7847c478bd9Sstevel@tonic-gate "automatic sending of login and/or authentication info", 7857c478bd9Sstevel@tonic-gate 0, 7867c478bd9Sstevel@tonic-gate &autologin, 7877c478bd9Sstevel@tonic-gate "send login name and/or authentication information" }, 7887c478bd9Sstevel@tonic-gate { "authdebug", 7897c478bd9Sstevel@tonic-gate "authentication debugging", 7907c478bd9Sstevel@tonic-gate auth_togdebug, 7917c478bd9Sstevel@tonic-gate 0, 7927c478bd9Sstevel@tonic-gate "print authentication debugging information" }, 7937c478bd9Sstevel@tonic-gate { "autoencrypt", 7947c478bd9Sstevel@tonic-gate "automatic encryption of data stream", 7957c478bd9Sstevel@tonic-gate EncryptAutoEnc, 7967c478bd9Sstevel@tonic-gate 0, 7977c478bd9Sstevel@tonic-gate "automatically encrypt output" }, 7987c478bd9Sstevel@tonic-gate { "autodecrypt", 7997c478bd9Sstevel@tonic-gate "automatic decryption of data stream", 8007c478bd9Sstevel@tonic-gate EncryptAutoDec, 8017c478bd9Sstevel@tonic-gate 0, 8027c478bd9Sstevel@tonic-gate "automatically decrypt input" }, 8037c478bd9Sstevel@tonic-gate { "verbose_encrypt", 8047c478bd9Sstevel@tonic-gate "verbose encryption output", 8057c478bd9Sstevel@tonic-gate EncryptVerbose, 8067c478bd9Sstevel@tonic-gate 0, 8077c478bd9Sstevel@tonic-gate "print verbose encryption output" }, 8087c478bd9Sstevel@tonic-gate { "encdebug", 8097c478bd9Sstevel@tonic-gate "encryption debugging", 8107c478bd9Sstevel@tonic-gate EncryptDebug, 8117c478bd9Sstevel@tonic-gate 0, 8127c478bd9Sstevel@tonic-gate "print encryption debugging information" }, 8137c478bd9Sstevel@tonic-gate { "skiprc", 8147c478bd9Sstevel@tonic-gate "don't read ~/.telnetrc file", 8157c478bd9Sstevel@tonic-gate 0, 8167c478bd9Sstevel@tonic-gate &skiprc, 8177c478bd9Sstevel@tonic-gate "skip reading of ~/.telnetrc file" }, 8187c478bd9Sstevel@tonic-gate { "binary", 8197c478bd9Sstevel@tonic-gate "sending and receiving of binary data", 8207c478bd9Sstevel@tonic-gate togbinary, 8217c478bd9Sstevel@tonic-gate 0, 8227c478bd9Sstevel@tonic-gate 0 }, 8237c478bd9Sstevel@tonic-gate { "inbinary", 8247c478bd9Sstevel@tonic-gate "receiving of binary data", 8257c478bd9Sstevel@tonic-gate togrbinary, 8267c478bd9Sstevel@tonic-gate 0, 8277c478bd9Sstevel@tonic-gate 0 }, 8287c478bd9Sstevel@tonic-gate { "outbinary", 8297c478bd9Sstevel@tonic-gate "sending of binary data", 8307c478bd9Sstevel@tonic-gate togxbinary, 8317c478bd9Sstevel@tonic-gate 0, 8327c478bd9Sstevel@tonic-gate 0 }, 8337c478bd9Sstevel@tonic-gate { "crlf", 8347c478bd9Sstevel@tonic-gate "sending carriage returns as telnet <CR><LF>", 8357c478bd9Sstevel@tonic-gate togcrlf, 8367c478bd9Sstevel@tonic-gate &crlf, 8377c478bd9Sstevel@tonic-gate 0 }, 8387c478bd9Sstevel@tonic-gate { "crmod", 8397c478bd9Sstevel@tonic-gate "mapping of received carriage returns", 8407c478bd9Sstevel@tonic-gate 0, 8417c478bd9Sstevel@tonic-gate &crmod, 8427c478bd9Sstevel@tonic-gate "map carriage return on output" }, 8437c478bd9Sstevel@tonic-gate { "localchars", 8447c478bd9Sstevel@tonic-gate "local recognition of certain control characters", 8457c478bd9Sstevel@tonic-gate lclchars, 8467c478bd9Sstevel@tonic-gate &localchars, 8477c478bd9Sstevel@tonic-gate "recognize certain control characters" }, 8487c478bd9Sstevel@tonic-gate { " ", "", 0 }, /* empty line */ 8497c478bd9Sstevel@tonic-gate { "debug", 8507c478bd9Sstevel@tonic-gate "debugging", 8517c478bd9Sstevel@tonic-gate togdebug, 8527c478bd9Sstevel@tonic-gate &debug, 8537c478bd9Sstevel@tonic-gate "turn on socket level debugging" }, 8547c478bd9Sstevel@tonic-gate { "netdata", 8557c478bd9Sstevel@tonic-gate "printing of hexadecimal network data (debugging)", 8567c478bd9Sstevel@tonic-gate 0, 8577c478bd9Sstevel@tonic-gate &netdata, 8587c478bd9Sstevel@tonic-gate "print hexadecimal representation of network traffic" }, 8597c478bd9Sstevel@tonic-gate { "prettydump", 8607c478bd9Sstevel@tonic-gate "output of \"netdata\" to user readable format (debugging)", 8617c478bd9Sstevel@tonic-gate 0, 8627c478bd9Sstevel@tonic-gate &prettydump, 8637c478bd9Sstevel@tonic-gate "print user readable output for \"netdata\"" }, 8647c478bd9Sstevel@tonic-gate { "options", 8657c478bd9Sstevel@tonic-gate "viewing of options processing (debugging)", 8667c478bd9Sstevel@tonic-gate 0, 8677c478bd9Sstevel@tonic-gate &showoptions, 8687c478bd9Sstevel@tonic-gate "show option processing" }, 8697c478bd9Sstevel@tonic-gate { "termdata", 8707c478bd9Sstevel@tonic-gate "(debugging) toggle printing of hexadecimal terminal data", 8717c478bd9Sstevel@tonic-gate 0, 8727c478bd9Sstevel@tonic-gate &termdata, 8737c478bd9Sstevel@tonic-gate "print hexadecimal representation of terminal traffic" }, 8747c478bd9Sstevel@tonic-gate { "?", 8757c478bd9Sstevel@tonic-gate 0, 8767c478bd9Sstevel@tonic-gate togglehelp }, 8777c478bd9Sstevel@tonic-gate { "help", 8787c478bd9Sstevel@tonic-gate 0, 8797c478bd9Sstevel@tonic-gate togglehelp }, 8807c478bd9Sstevel@tonic-gate { 0 } 8817c478bd9Sstevel@tonic-gate }; 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate static int 8847c478bd9Sstevel@tonic-gate togglehelp() 8857c478bd9Sstevel@tonic-gate { 8867c478bd9Sstevel@tonic-gate struct togglelist *c; 8877c478bd9Sstevel@tonic-gate 8887c478bd9Sstevel@tonic-gate for (c = Togglelist; c->name; c++) { 8897c478bd9Sstevel@tonic-gate if (c->help) { 8907c478bd9Sstevel@tonic-gate if (*c->help) 8917c478bd9Sstevel@tonic-gate (void) printf( 8927c478bd9Sstevel@tonic-gate "%-15s toggle %s\n", c->name, c->help); 8937c478bd9Sstevel@tonic-gate else 8947c478bd9Sstevel@tonic-gate (void) printf("\n"); 8957c478bd9Sstevel@tonic-gate } 8967c478bd9Sstevel@tonic-gate } 8977c478bd9Sstevel@tonic-gate (void) printf("\n"); 8987c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", "?", "display help information"); 8997c478bd9Sstevel@tonic-gate return (0); 9007c478bd9Sstevel@tonic-gate } 9017c478bd9Sstevel@tonic-gate 9027c478bd9Sstevel@tonic-gate static void 9037c478bd9Sstevel@tonic-gate settogglehelp(set) 9047c478bd9Sstevel@tonic-gate int set; 9057c478bd9Sstevel@tonic-gate { 9067c478bd9Sstevel@tonic-gate struct togglelist *c; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate for (c = Togglelist; c->name; c++) { 9097c478bd9Sstevel@tonic-gate if (c->help) { 9107c478bd9Sstevel@tonic-gate if (*c->help) 9117c478bd9Sstevel@tonic-gate (void) printf("%-15s %s %s\n", c->name, 9127c478bd9Sstevel@tonic-gate set ? "enable" : "disable", c->help); 9137c478bd9Sstevel@tonic-gate else 9147c478bd9Sstevel@tonic-gate (void) printf("\n"); 9157c478bd9Sstevel@tonic-gate } 9167c478bd9Sstevel@tonic-gate } 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate 9197c478bd9Sstevel@tonic-gate #define GETTOGGLE(name) (struct togglelist *) \ 9207c478bd9Sstevel@tonic-gate genget(name, (char **)Togglelist, sizeof (struct togglelist)) 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate static int 9237c478bd9Sstevel@tonic-gate toggle(argc, argv) 9247c478bd9Sstevel@tonic-gate int argc; 9257c478bd9Sstevel@tonic-gate char *argv[]; 9267c478bd9Sstevel@tonic-gate { 9277c478bd9Sstevel@tonic-gate int retval = 1; 9287c478bd9Sstevel@tonic-gate char *name; 9297c478bd9Sstevel@tonic-gate struct togglelist *c; 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate if (argc < 2) { 9327c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 9337c478bd9Sstevel@tonic-gate "Need an argument to 'toggle' command. " 9347c478bd9Sstevel@tonic-gate "'toggle ?' for help.\n"); 9357c478bd9Sstevel@tonic-gate return (0); 9367c478bd9Sstevel@tonic-gate } 9377c478bd9Sstevel@tonic-gate argc--; 9387c478bd9Sstevel@tonic-gate argv++; 9397c478bd9Sstevel@tonic-gate while (argc--) { 9407c478bd9Sstevel@tonic-gate name = *argv++; 9417c478bd9Sstevel@tonic-gate c = GETTOGGLE(name); 9427c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 9437c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 9447c478bd9Sstevel@tonic-gate "('toggle ?' for help).\n", name); 9457c478bd9Sstevel@tonic-gate return (0); 9467c478bd9Sstevel@tonic-gate } else if (c == 0) { 9477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 9487c478bd9Sstevel@tonic-gate "('toggle ?' for help).\n", name); 9497c478bd9Sstevel@tonic-gate return (0); 9507c478bd9Sstevel@tonic-gate } else { 9517c478bd9Sstevel@tonic-gate if (c->variable) { 9527c478bd9Sstevel@tonic-gate *c->variable = !*c->variable; /* invert it */ 9537c478bd9Sstevel@tonic-gate if (c->actionexplanation) { 9547c478bd9Sstevel@tonic-gate (void) printf("%s %s.\n", 9557c478bd9Sstevel@tonic-gate *c->variable ? "Will" : "Won't", 9567c478bd9Sstevel@tonic-gate c->actionexplanation); 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate } 9597c478bd9Sstevel@tonic-gate if (c->handler) { 9607c478bd9Sstevel@tonic-gate retval &= (*c->handler)(-1); 9617c478bd9Sstevel@tonic-gate } 9627c478bd9Sstevel@tonic-gate } 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate return (retval); 9657c478bd9Sstevel@tonic-gate } 9667c478bd9Sstevel@tonic-gate 9677c478bd9Sstevel@tonic-gate /* 9687c478bd9Sstevel@tonic-gate * The following perform the "set" command. 9697c478bd9Sstevel@tonic-gate */ 9707c478bd9Sstevel@tonic-gate 9717c478bd9Sstevel@tonic-gate #ifdef USE_TERMIO 9727c478bd9Sstevel@tonic-gate struct termio new_tc = { 0 }; 9737c478bd9Sstevel@tonic-gate #endif 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate struct setlist { 9767c478bd9Sstevel@tonic-gate char *name; /* name */ 9777c478bd9Sstevel@tonic-gate char *help; /* help information */ 9787c478bd9Sstevel@tonic-gate void (*handler)(); 9797c478bd9Sstevel@tonic-gate cc_t *charp; /* where it is located at */ 9807c478bd9Sstevel@tonic-gate }; 9817c478bd9Sstevel@tonic-gate 9827c478bd9Sstevel@tonic-gate static struct setlist Setlist[] = { 9837c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 9847c478bd9Sstevel@tonic-gate { "echo", "character to toggle local echoing on/off", 0, &echoc }, 9857c478bd9Sstevel@tonic-gate #endif 9867c478bd9Sstevel@tonic-gate { "escape", "character to escape back to telnet command mode", 0, 9877c478bd9Sstevel@tonic-gate &escape }, 9887c478bd9Sstevel@tonic-gate { "rlogin", "rlogin escape character", 0, &rlogin }, 9897c478bd9Sstevel@tonic-gate { "tracefile", "file to write trace information to", SetNetTrace, 9907c478bd9Sstevel@tonic-gate (cc_t *)NetTraceFile}, 9917c478bd9Sstevel@tonic-gate { " ", "" }, 9927c478bd9Sstevel@tonic-gate { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 9937c478bd9Sstevel@tonic-gate { "flushoutput", "character to cause an Abort Output", 0, 9947c478bd9Sstevel@tonic-gate termFlushCharp }, 9957c478bd9Sstevel@tonic-gate { "interrupt", "character to cause an Interrupt Process", 0, 9967c478bd9Sstevel@tonic-gate termIntCharp }, 9977c478bd9Sstevel@tonic-gate { "quit", "character to cause an Abort process", 0, termQuitCharp }, 9987c478bd9Sstevel@tonic-gate { "eof", "character to cause an EOF ", 0, termEofCharp }, 9997c478bd9Sstevel@tonic-gate { " ", "" }, 10007c478bd9Sstevel@tonic-gate { " ", "The following are for local editing in linemode", 0, 0 }, 10017c478bd9Sstevel@tonic-gate { "erase", "character to use to erase a character", 0, termEraseCharp }, 10027c478bd9Sstevel@tonic-gate { "kill", "character to use to erase a line", 0, termKillCharp }, 10037c478bd9Sstevel@tonic-gate { "lnext", "character to use for literal next", 0, 10047c478bd9Sstevel@tonic-gate termLiteralNextCharp }, 10057c478bd9Sstevel@tonic-gate { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, 10067c478bd9Sstevel@tonic-gate { "reprint", "character to use for line reprint", 0, termRprntCharp }, 10077c478bd9Sstevel@tonic-gate { "worderase", "character to use to erase a word", 0, termWerasCharp }, 10087c478bd9Sstevel@tonic-gate { "start", "character to use for XON", 0, termStartCharp }, 10097c478bd9Sstevel@tonic-gate { "stop", "character to use for XOFF", 0, termStopCharp }, 10107c478bd9Sstevel@tonic-gate { "forw1", "alternate end of line character", 0, termForw1Charp }, 10117c478bd9Sstevel@tonic-gate { "forw2", "alternate end of line character", 0, termForw2Charp }, 10127c478bd9Sstevel@tonic-gate { "ayt", "alternate AYT character", 0, termAytCharp }, 10137c478bd9Sstevel@tonic-gate { 0 } 10147c478bd9Sstevel@tonic-gate }; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate static struct setlist * 10177c478bd9Sstevel@tonic-gate getset(name) 10187c478bd9Sstevel@tonic-gate char *name; 10197c478bd9Sstevel@tonic-gate { 10207c478bd9Sstevel@tonic-gate return ((struct setlist *) 10217c478bd9Sstevel@tonic-gate genget(name, (char **)Setlist, sizeof (struct setlist))); 10227c478bd9Sstevel@tonic-gate } 10237c478bd9Sstevel@tonic-gate 10247c478bd9Sstevel@tonic-gate void 10257c478bd9Sstevel@tonic-gate set_escape_char(s) 10267c478bd9Sstevel@tonic-gate char *s; 10277c478bd9Sstevel@tonic-gate { 10287c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) { 10297c478bd9Sstevel@tonic-gate rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 10307c478bd9Sstevel@tonic-gate (void) printf("Telnet rlogin escape character is '%s'.\n", 10317c478bd9Sstevel@tonic-gate control(rlogin)); 10327c478bd9Sstevel@tonic-gate } else { 10337c478bd9Sstevel@tonic-gate escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 10347c478bd9Sstevel@tonic-gate (void) printf("Telnet escape character is '%s'.\n", 10357c478bd9Sstevel@tonic-gate esc_control(escape)); 10367c478bd9Sstevel@tonic-gate } 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate static int 10407c478bd9Sstevel@tonic-gate setcmd(argc, argv) 10417c478bd9Sstevel@tonic-gate int argc; 10427c478bd9Sstevel@tonic-gate char *argv[]; 10437c478bd9Sstevel@tonic-gate { 10447c478bd9Sstevel@tonic-gate int value; 10457c478bd9Sstevel@tonic-gate struct setlist *ct; 10467c478bd9Sstevel@tonic-gate struct togglelist *c; 10477c478bd9Sstevel@tonic-gate 10487c478bd9Sstevel@tonic-gate if (argc < 2 || argc > 3) { 10497c478bd9Sstevel@tonic-gate (void) printf( 10507c478bd9Sstevel@tonic-gate "Format is 'set Name Value'\n'set ?' for help.\n"); 10517c478bd9Sstevel@tonic-gate return (0); 10527c478bd9Sstevel@tonic-gate } 10537c478bd9Sstevel@tonic-gate if ((argc == 2) && 10547c478bd9Sstevel@tonic-gate (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 10557c478bd9Sstevel@tonic-gate for (ct = Setlist; ct->name; ct++) 10567c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", ct->name, ct->help); 10577c478bd9Sstevel@tonic-gate (void) printf("\n"); 10587c478bd9Sstevel@tonic-gate settogglehelp(1); 10597c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", "?", "display help information"); 10607c478bd9Sstevel@tonic-gate return (0); 10617c478bd9Sstevel@tonic-gate } 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate ct = getset(argv[1]); 10647c478bd9Sstevel@tonic-gate if (ct == 0) { 10657c478bd9Sstevel@tonic-gate c = GETTOGGLE(argv[1]); 10667c478bd9Sstevel@tonic-gate if (c == 0) { 10677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 10687c478bd9Sstevel@tonic-gate "('set ?' for help).\n", argv[1]); 10697c478bd9Sstevel@tonic-gate return (0); 10707c478bd9Sstevel@tonic-gate } else if (Ambiguous(c)) { 10717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 10727c478bd9Sstevel@tonic-gate "('set ?' for help).\n", argv[1]); 10737c478bd9Sstevel@tonic-gate return (0); 10747c478bd9Sstevel@tonic-gate } 10757c478bd9Sstevel@tonic-gate if (c->variable) { 10767c478bd9Sstevel@tonic-gate if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 10777c478bd9Sstevel@tonic-gate *c->variable = 1; 10787c478bd9Sstevel@tonic-gate else if (strcmp("off", argv[2]) == 0) 10797c478bd9Sstevel@tonic-gate *c->variable = 0; 10807c478bd9Sstevel@tonic-gate else { 10817c478bd9Sstevel@tonic-gate (void) printf( 10827c478bd9Sstevel@tonic-gate "Format is 'set togglename [on|off]'\n" 10837c478bd9Sstevel@tonic-gate "'set ?' for help.\n"); 10847c478bd9Sstevel@tonic-gate return (0); 10857c478bd9Sstevel@tonic-gate } 10867c478bd9Sstevel@tonic-gate if (c->actionexplanation) { 10877c478bd9Sstevel@tonic-gate (void) printf("%s %s.\n", 10887c478bd9Sstevel@tonic-gate *c->variable? "Will" : "Won't", 10897c478bd9Sstevel@tonic-gate c->actionexplanation); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate if (c->handler) 10937c478bd9Sstevel@tonic-gate (*c->handler)(1); 10947c478bd9Sstevel@tonic-gate } else if (argc != 3) { 10957c478bd9Sstevel@tonic-gate (void) printf( 10967c478bd9Sstevel@tonic-gate "Format is 'set Name Value'\n'set ?' for help.\n"); 10977c478bd9Sstevel@tonic-gate return (0); 10987c478bd9Sstevel@tonic-gate } else if (Ambiguous(ct)) { 10997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11007c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('set ?' for help).\n", argv[1]); 11017c478bd9Sstevel@tonic-gate return (0); 11027c478bd9Sstevel@tonic-gate } else if (ct->handler) { 11037c478bd9Sstevel@tonic-gate (*ct->handler)(argv[2]); 11047c478bd9Sstevel@tonic-gate (void) printf( 11057c478bd9Sstevel@tonic-gate "%s set to \"%s\".\n", ct->name, (char *)ct->charp); 11067c478bd9Sstevel@tonic-gate } else { 11077c478bd9Sstevel@tonic-gate if (strcmp("off", argv[2])) { 11087c478bd9Sstevel@tonic-gate value = special(argv[2]); 11097c478bd9Sstevel@tonic-gate } else { 11107c478bd9Sstevel@tonic-gate value = _POSIX_VDISABLE; 11117c478bd9Sstevel@tonic-gate } 11127c478bd9Sstevel@tonic-gate *(ct->charp) = (cc_t)value; 11137c478bd9Sstevel@tonic-gate (void) printf("%s character is '%s'.\n", ct->name, 11147c478bd9Sstevel@tonic-gate control(*(ct->charp))); 11157c478bd9Sstevel@tonic-gate } 11167c478bd9Sstevel@tonic-gate slc_check(); 11177c478bd9Sstevel@tonic-gate return (1); 11187c478bd9Sstevel@tonic-gate } 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate static int 11217c478bd9Sstevel@tonic-gate unsetcmd(argc, argv) 11227c478bd9Sstevel@tonic-gate int argc; 11237c478bd9Sstevel@tonic-gate char *argv[]; 11247c478bd9Sstevel@tonic-gate { 11257c478bd9Sstevel@tonic-gate struct setlist *ct; 11267c478bd9Sstevel@tonic-gate struct togglelist *c; 11277c478bd9Sstevel@tonic-gate register char *name; 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate if (argc < 2) { 11307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Need an argument to 'unset' command. " 11317c478bd9Sstevel@tonic-gate "'unset ?' for help.\n"); 11327c478bd9Sstevel@tonic-gate return (0); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 11357c478bd9Sstevel@tonic-gate for (ct = Setlist; ct->name; ct++) 11367c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", ct->name, ct->help); 11377c478bd9Sstevel@tonic-gate (void) printf("\n"); 11387c478bd9Sstevel@tonic-gate settogglehelp(0); 11397c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", "?", "display help information"); 11407c478bd9Sstevel@tonic-gate return (0); 11417c478bd9Sstevel@tonic-gate } 11427c478bd9Sstevel@tonic-gate 11437c478bd9Sstevel@tonic-gate argc--; 11447c478bd9Sstevel@tonic-gate argv++; 11457c478bd9Sstevel@tonic-gate while (argc--) { 11467c478bd9Sstevel@tonic-gate name = *argv++; 11477c478bd9Sstevel@tonic-gate ct = getset(name); 11487c478bd9Sstevel@tonic-gate if (ct == 0) { 11497c478bd9Sstevel@tonic-gate c = GETTOGGLE(name); 11507c478bd9Sstevel@tonic-gate if (c == 0) { 11517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 11527c478bd9Sstevel@tonic-gate "('unset ?' for help).\n", name); 11537c478bd9Sstevel@tonic-gate return (0); 11547c478bd9Sstevel@tonic-gate } else if (Ambiguous(c)) { 11557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 11567c478bd9Sstevel@tonic-gate "'%s': ambiguous argument " 11577c478bd9Sstevel@tonic-gate "('unset ?' for help).\n", name); 11587c478bd9Sstevel@tonic-gate return (0); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate if (c->variable) { 11617c478bd9Sstevel@tonic-gate *c->variable = 0; 11627c478bd9Sstevel@tonic-gate if (c->actionexplanation) { 11637c478bd9Sstevel@tonic-gate (void) printf("%s %s.\n", 11647c478bd9Sstevel@tonic-gate *c->variable? "Will" : "Won't", 11657c478bd9Sstevel@tonic-gate c->actionexplanation); 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate } 11687c478bd9Sstevel@tonic-gate if (c->handler) 11697c478bd9Sstevel@tonic-gate (*c->handler)(0); 11707c478bd9Sstevel@tonic-gate } else if (Ambiguous(ct)) { 11717c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 11727c478bd9Sstevel@tonic-gate "('unset ?' for help).\n", name); 11737c478bd9Sstevel@tonic-gate return (0); 11747c478bd9Sstevel@tonic-gate } else if (ct->handler) { 11757c478bd9Sstevel@tonic-gate (*ct->handler)(0); 11767c478bd9Sstevel@tonic-gate (void) printf("%s reset to \"%s\".\n", ct->name, 11777c478bd9Sstevel@tonic-gate (char *)ct->charp); 11787c478bd9Sstevel@tonic-gate } else { 11797c478bd9Sstevel@tonic-gate *(ct->charp) = _POSIX_VDISABLE; 11807c478bd9Sstevel@tonic-gate (void) printf("%s character is '%s'.\n", ct->name, 11817c478bd9Sstevel@tonic-gate control(*(ct->charp))); 11827c478bd9Sstevel@tonic-gate } 11837c478bd9Sstevel@tonic-gate } 11847c478bd9Sstevel@tonic-gate return (1); 11857c478bd9Sstevel@tonic-gate } 11867c478bd9Sstevel@tonic-gate 11877c478bd9Sstevel@tonic-gate /* 11887c478bd9Sstevel@tonic-gate * The following are the data structures and routines for the 11897c478bd9Sstevel@tonic-gate * 'mode' command. 11907c478bd9Sstevel@tonic-gate */ 11917c478bd9Sstevel@tonic-gate extern int reqd_linemode; 11927c478bd9Sstevel@tonic-gate 11937c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 11947c478bd9Sstevel@tonic-gate extern int kludgelinemode; 11957c478bd9Sstevel@tonic-gate 11967c478bd9Sstevel@tonic-gate static int 11977c478bd9Sstevel@tonic-gate dokludgemode() 11987c478bd9Sstevel@tonic-gate { 11997c478bd9Sstevel@tonic-gate kludgelinemode = 1; 12007c478bd9Sstevel@tonic-gate send_wont(TELOPT_LINEMODE, 1); 12017c478bd9Sstevel@tonic-gate send_dont(TELOPT_SGA, 1); 12027c478bd9Sstevel@tonic-gate send_dont(TELOPT_ECHO, 1); 12037c478bd9Sstevel@tonic-gate /* 12047c478bd9Sstevel@tonic-gate * If processing the .telnetrc file, keep track of linemode and/or 12057c478bd9Sstevel@tonic-gate * kludgelinemode requests which are processed before initial option 12067c478bd9Sstevel@tonic-gate * negotiations occur. 12077c478bd9Sstevel@tonic-gate */ 12087c478bd9Sstevel@tonic-gate if (doing_rc) 12097c478bd9Sstevel@tonic-gate reqd_linemode = 1; 12107c478bd9Sstevel@tonic-gate return (1); 12117c478bd9Sstevel@tonic-gate } 12127c478bd9Sstevel@tonic-gate #endif 12137c478bd9Sstevel@tonic-gate 12147c478bd9Sstevel@tonic-gate static int 12157c478bd9Sstevel@tonic-gate dolinemode() 12167c478bd9Sstevel@tonic-gate { 12177c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 12187c478bd9Sstevel@tonic-gate if (kludgelinemode) 12197c478bd9Sstevel@tonic-gate send_dont(TELOPT_SGA, 1); 12207c478bd9Sstevel@tonic-gate #endif 12217c478bd9Sstevel@tonic-gate send_will(TELOPT_LINEMODE, 1); 12227c478bd9Sstevel@tonic-gate send_dont(TELOPT_ECHO, 1); 12237c478bd9Sstevel@tonic-gate 12247c478bd9Sstevel@tonic-gate /* 12257c478bd9Sstevel@tonic-gate * If processing the .telnetrc file, keep track of linemode and/or 12267c478bd9Sstevel@tonic-gate * kludgelinemode requests which are processed before initial option 12277c478bd9Sstevel@tonic-gate * negotiations occur. 12287c478bd9Sstevel@tonic-gate */ 12297c478bd9Sstevel@tonic-gate if (doing_rc) 12307c478bd9Sstevel@tonic-gate reqd_linemode = 1; 12317c478bd9Sstevel@tonic-gate return (1); 12327c478bd9Sstevel@tonic-gate } 12337c478bd9Sstevel@tonic-gate 12347c478bd9Sstevel@tonic-gate static int 12357c478bd9Sstevel@tonic-gate docharmode() 12367c478bd9Sstevel@tonic-gate { 12377c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 12387c478bd9Sstevel@tonic-gate if (kludgelinemode) 12397c478bd9Sstevel@tonic-gate send_do(TELOPT_SGA, 1); 12407c478bd9Sstevel@tonic-gate else 12417c478bd9Sstevel@tonic-gate #endif 12427c478bd9Sstevel@tonic-gate send_wont(TELOPT_LINEMODE, 1); 12437c478bd9Sstevel@tonic-gate send_do(TELOPT_ECHO, 1); 12447c478bd9Sstevel@tonic-gate reqd_linemode = 0; 12457c478bd9Sstevel@tonic-gate return (1); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate static int 12497c478bd9Sstevel@tonic-gate dolmmode(bit, on) 12507c478bd9Sstevel@tonic-gate int bit, on; 12517c478bd9Sstevel@tonic-gate { 12527c478bd9Sstevel@tonic-gate unsigned char c; 12537c478bd9Sstevel@tonic-gate extern int linemode; 12547c478bd9Sstevel@tonic-gate 12557c478bd9Sstevel@tonic-gate if (my_want_state_is_wont(TELOPT_LINEMODE)) { 12567c478bd9Sstevel@tonic-gate (void) printf("?Need to have LINEMODE option enabled first.\n"); 12577c478bd9Sstevel@tonic-gate (void) printf("'mode ?' for help.\n"); 12587c478bd9Sstevel@tonic-gate return (0); 12597c478bd9Sstevel@tonic-gate } 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate if (on) 12627c478bd9Sstevel@tonic-gate c = (linemode | bit); 12637c478bd9Sstevel@tonic-gate else 12647c478bd9Sstevel@tonic-gate c = (linemode & ~bit); 12657c478bd9Sstevel@tonic-gate lm_mode(&c, 1, 1); 12667c478bd9Sstevel@tonic-gate return (1); 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate 12697c478bd9Sstevel@tonic-gate static int 12707c478bd9Sstevel@tonic-gate setmode(bit) 12717c478bd9Sstevel@tonic-gate { 12727c478bd9Sstevel@tonic-gate return (dolmmode(bit, 1)); 12737c478bd9Sstevel@tonic-gate } 12747c478bd9Sstevel@tonic-gate 12757c478bd9Sstevel@tonic-gate static int 12767c478bd9Sstevel@tonic-gate clearmode(bit) 12777c478bd9Sstevel@tonic-gate { 12787c478bd9Sstevel@tonic-gate return (dolmmode(bit, 0)); 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate struct modelist { 12827c478bd9Sstevel@tonic-gate char *name; /* command name */ 12837c478bd9Sstevel@tonic-gate char *help; /* help string */ 12847c478bd9Sstevel@tonic-gate int (*handler)(); /* routine which executes command */ 12857c478bd9Sstevel@tonic-gate int needconnect; /* Do we need to be connected to execute? */ 12867c478bd9Sstevel@tonic-gate int arg1; 12877c478bd9Sstevel@tonic-gate }; 12887c478bd9Sstevel@tonic-gate 12897c478bd9Sstevel@tonic-gate static int modehelp(); 12907c478bd9Sstevel@tonic-gate 12917c478bd9Sstevel@tonic-gate static struct modelist ModeList[] = { 12927c478bd9Sstevel@tonic-gate { "character", "Disable LINEMODE option", docharmode, 1 }, 12937c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 12947c478bd9Sstevel@tonic-gate { "", "(or disable obsolete line-by-line mode)", 0 }, 12957c478bd9Sstevel@tonic-gate #endif 12967c478bd9Sstevel@tonic-gate { "line", "Enable LINEMODE option", dolinemode, 1 }, 12977c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 12987c478bd9Sstevel@tonic-gate { "", "(or enable obsolete line-by-line mode)", 0 }, 12997c478bd9Sstevel@tonic-gate #endif 13007c478bd9Sstevel@tonic-gate { "", "", 0 }, 13017c478bd9Sstevel@tonic-gate { "", "These require the LINEMODE option to be enabled", 0 }, 13027c478bd9Sstevel@tonic-gate { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, 13037c478bd9Sstevel@tonic-gate { "+isig", 0, setmode, 1, MODE_TRAPSIG }, 13047c478bd9Sstevel@tonic-gate { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 13057c478bd9Sstevel@tonic-gate { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, 13067c478bd9Sstevel@tonic-gate { "+edit", 0, setmode, 1, MODE_EDIT }, 13077c478bd9Sstevel@tonic-gate { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 13087c478bd9Sstevel@tonic-gate { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB }, 13097c478bd9Sstevel@tonic-gate { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB }, 13107c478bd9Sstevel@tonic-gate { "-softtabs", "Disable tab expansion", 13117c478bd9Sstevel@tonic-gate clearmode, 1, MODE_SOFT_TAB }, 13127c478bd9Sstevel@tonic-gate { "litecho", "Enable literal character echo", 13137c478bd9Sstevel@tonic-gate setmode, 1, MODE_LIT_ECHO }, 13147c478bd9Sstevel@tonic-gate { "+litecho", 0, setmode, 1, MODE_LIT_ECHO }, 13157c478bd9Sstevel@tonic-gate { "-litecho", "Disable literal character echo", clearmode, 1, 13167c478bd9Sstevel@tonic-gate MODE_LIT_ECHO }, 13177c478bd9Sstevel@tonic-gate { "help", 0, modehelp, 0 }, 13187c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 13197c478bd9Sstevel@tonic-gate { "kludgeline", 0, dokludgemode, 1 }, 13207c478bd9Sstevel@tonic-gate #endif 13217c478bd9Sstevel@tonic-gate { "", "", 0 }, 13227c478bd9Sstevel@tonic-gate { "?", "Print help information", modehelp, 0 }, 13237c478bd9Sstevel@tonic-gate { 0 }, 13247c478bd9Sstevel@tonic-gate }; 13257c478bd9Sstevel@tonic-gate 13267c478bd9Sstevel@tonic-gate 13277c478bd9Sstevel@tonic-gate static int 13287c478bd9Sstevel@tonic-gate modehelp() 13297c478bd9Sstevel@tonic-gate { 13307c478bd9Sstevel@tonic-gate struct modelist *mt; 13317c478bd9Sstevel@tonic-gate 13327c478bd9Sstevel@tonic-gate (void) printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 13337c478bd9Sstevel@tonic-gate for (mt = ModeList; mt->name; mt++) { 13347c478bd9Sstevel@tonic-gate if (mt->help) { 13357c478bd9Sstevel@tonic-gate if (*mt->help) 13367c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", mt->name, mt->help); 13377c478bd9Sstevel@tonic-gate else 13387c478bd9Sstevel@tonic-gate (void) printf("\n"); 13397c478bd9Sstevel@tonic-gate } 13407c478bd9Sstevel@tonic-gate } 13417c478bd9Sstevel@tonic-gate return (0); 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate #define GETMODECMD(name) (struct modelist *) \ 13457c478bd9Sstevel@tonic-gate genget(name, (char **)ModeList, sizeof (struct modelist)) 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate static int 13487c478bd9Sstevel@tonic-gate modecmd(argc, argv) 13497c478bd9Sstevel@tonic-gate int argc; 13507c478bd9Sstevel@tonic-gate char *argv[]; 13517c478bd9Sstevel@tonic-gate { 13527c478bd9Sstevel@tonic-gate struct modelist *mt; 13537c478bd9Sstevel@tonic-gate 13547c478bd9Sstevel@tonic-gate if (argc != 2) { 13557c478bd9Sstevel@tonic-gate (void) printf("'mode' command requires an argument\n"); 13567c478bd9Sstevel@tonic-gate (void) printf("'mode ?' for help.\n"); 13577c478bd9Sstevel@tonic-gate } else if ((mt = GETMODECMD(argv[1])) == 0) { 13587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13597c478bd9Sstevel@tonic-gate "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 13607c478bd9Sstevel@tonic-gate } else if (Ambiguous(mt)) { 13617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 13627c478bd9Sstevel@tonic-gate "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 13637c478bd9Sstevel@tonic-gate } else if (mt->needconnect && !connected) { 13647c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 13657c478bd9Sstevel@tonic-gate (void) printf("'mode ?' for help.\n"); 13667c478bd9Sstevel@tonic-gate } else if (mt->handler) { 13677c478bd9Sstevel@tonic-gate return (*mt->handler)(mt->arg1); 13687c478bd9Sstevel@tonic-gate } 13697c478bd9Sstevel@tonic-gate return (0); 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate /* 13737c478bd9Sstevel@tonic-gate * The following data structures and routines implement the 13747c478bd9Sstevel@tonic-gate * "display" command. 13757c478bd9Sstevel@tonic-gate */ 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate static int 13787c478bd9Sstevel@tonic-gate display(argc, argv) 13797c478bd9Sstevel@tonic-gate int argc; 13807c478bd9Sstevel@tonic-gate char *argv[]; 13817c478bd9Sstevel@tonic-gate { 13827c478bd9Sstevel@tonic-gate struct togglelist *tl; 13837c478bd9Sstevel@tonic-gate struct setlist *sl; 13847c478bd9Sstevel@tonic-gate 13857c478bd9Sstevel@tonic-gate #define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 13867c478bd9Sstevel@tonic-gate if (*tl->variable) { \ 13877c478bd9Sstevel@tonic-gate (void) printf("will"); \ 13887c478bd9Sstevel@tonic-gate } else { \ 13897c478bd9Sstevel@tonic-gate (void) printf("won't"); \ 13907c478bd9Sstevel@tonic-gate } \ 13917c478bd9Sstevel@tonic-gate (void) printf(" %s.\n", tl->actionexplanation); \ 13927c478bd9Sstevel@tonic-gate } 13937c478bd9Sstevel@tonic-gate 13947c478bd9Sstevel@tonic-gate #define doset(sl) if (sl->name && *sl->name != ' ') { \ 13957c478bd9Sstevel@tonic-gate if (sl->handler == 0) \ 13967c478bd9Sstevel@tonic-gate (void) printf("%-15s [%s]\n", sl->name, \ 13977c478bd9Sstevel@tonic-gate control(*sl->charp)); \ 13987c478bd9Sstevel@tonic-gate else \ 13997c478bd9Sstevel@tonic-gate (void) printf("%-15s \"%s\"\n", sl->name, \ 14007c478bd9Sstevel@tonic-gate (char *)sl->charp); \ 14017c478bd9Sstevel@tonic-gate } 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate if (argc == 1) { 14047c478bd9Sstevel@tonic-gate for (tl = Togglelist; tl->name; tl++) { 14057c478bd9Sstevel@tonic-gate dotog(tl); 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate (void) printf("\n"); 14087c478bd9Sstevel@tonic-gate for (sl = Setlist; sl->name; sl++) { 14097c478bd9Sstevel@tonic-gate doset(sl); 14107c478bd9Sstevel@tonic-gate } 14117c478bd9Sstevel@tonic-gate } else { 14127c478bd9Sstevel@tonic-gate int i; 14137c478bd9Sstevel@tonic-gate 14147c478bd9Sstevel@tonic-gate for (i = 1; i < argc; i++) { 14157c478bd9Sstevel@tonic-gate sl = getset(argv[i]); 14167c478bd9Sstevel@tonic-gate tl = GETTOGGLE(argv[i]); 14177c478bd9Sstevel@tonic-gate if (Ambiguous(sl) || Ambiguous(tl)) { 14187c478bd9Sstevel@tonic-gate (void) printf( 14197c478bd9Sstevel@tonic-gate "?Ambiguous argument '%s'.\n", argv[i]); 14207c478bd9Sstevel@tonic-gate return (0); 14217c478bd9Sstevel@tonic-gate } else if (!sl && !tl) { 14227c478bd9Sstevel@tonic-gate (void) printf( 14237c478bd9Sstevel@tonic-gate "?Unknown argument '%s'.\n", argv[i]); 14247c478bd9Sstevel@tonic-gate return (0); 14257c478bd9Sstevel@tonic-gate } else { 14267c478bd9Sstevel@tonic-gate if (tl) { 14277c478bd9Sstevel@tonic-gate dotog(tl); 14287c478bd9Sstevel@tonic-gate } 14297c478bd9Sstevel@tonic-gate if (sl) { 14307c478bd9Sstevel@tonic-gate doset(sl); 14317c478bd9Sstevel@tonic-gate } 14327c478bd9Sstevel@tonic-gate } 14337c478bd9Sstevel@tonic-gate } 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate optionstatus(); 14367c478bd9Sstevel@tonic-gate (void) EncryptStatus(); 14377c478bd9Sstevel@tonic-gate return (1); 14387c478bd9Sstevel@tonic-gate #undef doset 14397c478bd9Sstevel@tonic-gate #undef dotog 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate 14427c478bd9Sstevel@tonic-gate /* 14437c478bd9Sstevel@tonic-gate * The following are the data structures, and many of the routines, 14447c478bd9Sstevel@tonic-gate * relating to command processing. 14457c478bd9Sstevel@tonic-gate */ 14467c478bd9Sstevel@tonic-gate 14477c478bd9Sstevel@tonic-gate /* 14487c478bd9Sstevel@tonic-gate * Set the escape character. 14497c478bd9Sstevel@tonic-gate */ 14507c478bd9Sstevel@tonic-gate static int 14517c478bd9Sstevel@tonic-gate setescape(argc, argv) 14527c478bd9Sstevel@tonic-gate int argc; 14537c478bd9Sstevel@tonic-gate char *argv[]; 14547c478bd9Sstevel@tonic-gate { 14557c478bd9Sstevel@tonic-gate register char *arg; 14567c478bd9Sstevel@tonic-gate char *buf = NULL; 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate if (argc > 2) 14597c478bd9Sstevel@tonic-gate arg = argv[1]; 14607c478bd9Sstevel@tonic-gate else { 14617c478bd9Sstevel@tonic-gate (void) printf("new escape character: "); 14627c478bd9Sstevel@tonic-gate if (GetString(&buf, NULL, stdin) == NULL) { 14637c478bd9Sstevel@tonic-gate if (!feof(stdin)) { 14647c478bd9Sstevel@tonic-gate perror("can't set escape character"); 14657c478bd9Sstevel@tonic-gate goto setescape_exit; 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate } 14687c478bd9Sstevel@tonic-gate arg = buf; 14697c478bd9Sstevel@tonic-gate } 14707c478bd9Sstevel@tonic-gate /* we place no limitations on what escape can be. */ 14717c478bd9Sstevel@tonic-gate escape = arg[0]; 14727c478bd9Sstevel@tonic-gate (void) printf("Escape character is '%s'.\n", esc_control(escape)); 14737c478bd9Sstevel@tonic-gate (void) fflush(stdout); 14747c478bd9Sstevel@tonic-gate setescape_exit: 14757c478bd9Sstevel@tonic-gate Free(&buf); 14767c478bd9Sstevel@tonic-gate return (1); 14777c478bd9Sstevel@tonic-gate } 14787c478bd9Sstevel@tonic-gate 14797c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 14807c478bd9Sstevel@tonic-gate static int 14817c478bd9Sstevel@tonic-gate togcrmod(argc, argv) 14827c478bd9Sstevel@tonic-gate int argc; 14837c478bd9Sstevel@tonic-gate char *argv[]; 14847c478bd9Sstevel@tonic-gate { 14857c478bd9Sstevel@tonic-gate crmod = !crmod; 14867c478bd9Sstevel@tonic-gate (void) printf( 14877c478bd9Sstevel@tonic-gate "%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 14887c478bd9Sstevel@tonic-gate (void) fflush(stdout); 14897c478bd9Sstevel@tonic-gate return (1); 14907c478bd9Sstevel@tonic-gate } 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 14937c478bd9Sstevel@tonic-gate static int 14947c478bd9Sstevel@tonic-gate suspend(argc, argv) 14957c478bd9Sstevel@tonic-gate int argc; 14967c478bd9Sstevel@tonic-gate char *argv[]; 14977c478bd9Sstevel@tonic-gate { 14987c478bd9Sstevel@tonic-gate setcommandmode(); 14997c478bd9Sstevel@tonic-gate { 15007c478bd9Sstevel@tonic-gate unsigned short oldrows, oldcols, newrows, newcols; 15017c478bd9Sstevel@tonic-gate int err; 15027c478bd9Sstevel@tonic-gate 15037c478bd9Sstevel@tonic-gate err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 15047c478bd9Sstevel@tonic-gate (void) kill(0, SIGTSTP); 15057c478bd9Sstevel@tonic-gate /* 15067c478bd9Sstevel@tonic-gate * If we didn't get the window size before the SUSPEND, but we 15077c478bd9Sstevel@tonic-gate * can get them now (?), then send the NAWS to make sure that 15087c478bd9Sstevel@tonic-gate * we are set up for the right window size. 15097c478bd9Sstevel@tonic-gate */ 15107c478bd9Sstevel@tonic-gate if (TerminalWindowSize(&newrows, &newcols) && connected && 15117c478bd9Sstevel@tonic-gate (err || ((oldrows != newrows) || (oldcols != newcols)))) { 15127c478bd9Sstevel@tonic-gate sendnaws(); 15137c478bd9Sstevel@tonic-gate } 15147c478bd9Sstevel@tonic-gate } 15157c478bd9Sstevel@tonic-gate /* reget parameters in case they were changed */ 15167c478bd9Sstevel@tonic-gate TerminalSaveState(); 15177c478bd9Sstevel@tonic-gate setconnmode(0); 15187c478bd9Sstevel@tonic-gate return (1); 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate 15217c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 15227c478bd9Sstevel@tonic-gate static int 15237c478bd9Sstevel@tonic-gate shell(argc, argv) 15247c478bd9Sstevel@tonic-gate int argc; 15257c478bd9Sstevel@tonic-gate char *argv[]; 15267c478bd9Sstevel@tonic-gate { 15277c478bd9Sstevel@tonic-gate unsigned short oldrows, oldcols, newrows, newcols; 15287c478bd9Sstevel@tonic-gate int err; 15297c478bd9Sstevel@tonic-gate 15307c478bd9Sstevel@tonic-gate setcommandmode(); 15317c478bd9Sstevel@tonic-gate 15327c478bd9Sstevel@tonic-gate err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 15337c478bd9Sstevel@tonic-gate switch (vfork()) { 15347c478bd9Sstevel@tonic-gate case -1: 15357c478bd9Sstevel@tonic-gate perror("Fork failed\n"); 15367c478bd9Sstevel@tonic-gate break; 15377c478bd9Sstevel@tonic-gate 15387c478bd9Sstevel@tonic-gate case 0: 15397c478bd9Sstevel@tonic-gate { 15407c478bd9Sstevel@tonic-gate /* 15417c478bd9Sstevel@tonic-gate * Fire up the shell in the child. 15427c478bd9Sstevel@tonic-gate */ 15437c478bd9Sstevel@tonic-gate register char *shellp, *shellname; 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate shellp = getenv("SHELL"); 15467c478bd9Sstevel@tonic-gate if (shellp == NULL) 15477c478bd9Sstevel@tonic-gate shellp = "/bin/sh"; 15487c478bd9Sstevel@tonic-gate if ((shellname = strrchr(shellp, '/')) == 0) 15497c478bd9Sstevel@tonic-gate shellname = shellp; 15507c478bd9Sstevel@tonic-gate else 15517c478bd9Sstevel@tonic-gate shellname++; 15527c478bd9Sstevel@tonic-gate if (argc > 1) 15537c478bd9Sstevel@tonic-gate (void) execl(shellp, shellname, "-c", argv[1], 0); 15547c478bd9Sstevel@tonic-gate else 15557c478bd9Sstevel@tonic-gate (void) execl(shellp, shellname, 0); 15567c478bd9Sstevel@tonic-gate perror("Execl"); 15577c478bd9Sstevel@tonic-gate _exit(EXIT_FAILURE); 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate default: 15607c478bd9Sstevel@tonic-gate (void) wait((int *)0); /* Wait for the shell to complete */ 15617c478bd9Sstevel@tonic-gate 15627c478bd9Sstevel@tonic-gate if (TerminalWindowSize(&newrows, &newcols) && connected && 15637c478bd9Sstevel@tonic-gate (err || ((oldrows != newrows) || (oldcols != newcols)))) { 15647c478bd9Sstevel@tonic-gate sendnaws(); 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate break; 15677c478bd9Sstevel@tonic-gate } 15687c478bd9Sstevel@tonic-gate return (1); 15697c478bd9Sstevel@tonic-gate } 15707c478bd9Sstevel@tonic-gate 15717c478bd9Sstevel@tonic-gate static int 15727c478bd9Sstevel@tonic-gate bye(argc, argv) 15737c478bd9Sstevel@tonic-gate int argc; /* Number of arguments */ 15747c478bd9Sstevel@tonic-gate char *argv[]; /* arguments */ 15757c478bd9Sstevel@tonic-gate { 15767c478bd9Sstevel@tonic-gate extern int resettermname; 15777c478bd9Sstevel@tonic-gate 15787c478bd9Sstevel@tonic-gate if (connected) { 15797c478bd9Sstevel@tonic-gate (void) shutdown(net, 2); 15807c478bd9Sstevel@tonic-gate (void) printf("Connection to %.*s closed.\n", MAXHOSTNAMELEN, 15817c478bd9Sstevel@tonic-gate hostname); 15827c478bd9Sstevel@tonic-gate Close(&net); 15837c478bd9Sstevel@tonic-gate connected = 0; 15847c478bd9Sstevel@tonic-gate resettermname = 1; 15857c478bd9Sstevel@tonic-gate /* reset options */ 15867c478bd9Sstevel@tonic-gate (void) tninit(); 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 15897c478bd9Sstevel@tonic-gate longjmp(toplevel, 1); 15907c478bd9Sstevel@tonic-gate /* NOTREACHED */ 15917c478bd9Sstevel@tonic-gate } 15927c478bd9Sstevel@tonic-gate return (1); /* Keep lint, etc., happy */ 15937c478bd9Sstevel@tonic-gate } 15947c478bd9Sstevel@tonic-gate 15957c478bd9Sstevel@tonic-gate /*VARARGS*/ 15967c478bd9Sstevel@tonic-gate int 15977c478bd9Sstevel@tonic-gate quit() 15987c478bd9Sstevel@tonic-gate { 15997c478bd9Sstevel@tonic-gate (void) call(3, bye, "bye", "fromquit"); 16007c478bd9Sstevel@tonic-gate Exit(EXIT_SUCCESS); 16017c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 16027c478bd9Sstevel@tonic-gate return (1); 16037c478bd9Sstevel@tonic-gate } 16047c478bd9Sstevel@tonic-gate 16057c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 16067c478bd9Sstevel@tonic-gate static int 16077c478bd9Sstevel@tonic-gate logout(argc, argv) 16087c478bd9Sstevel@tonic-gate int argc; 16097c478bd9Sstevel@tonic-gate char *argv[]; 16107c478bd9Sstevel@tonic-gate { 16117c478bd9Sstevel@tonic-gate send_do(TELOPT_LOGOUT, 1); 16127c478bd9Sstevel@tonic-gate (void) netflush(); 16137c478bd9Sstevel@tonic-gate return (1); 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate 16167c478bd9Sstevel@tonic-gate 16177c478bd9Sstevel@tonic-gate /* 16187c478bd9Sstevel@tonic-gate * The SLC command. 16197c478bd9Sstevel@tonic-gate */ 16207c478bd9Sstevel@tonic-gate 16217c478bd9Sstevel@tonic-gate struct slclist { 16227c478bd9Sstevel@tonic-gate char *name; 16237c478bd9Sstevel@tonic-gate char *help; 16247c478bd9Sstevel@tonic-gate void (*handler)(); 16257c478bd9Sstevel@tonic-gate int arg; 16267c478bd9Sstevel@tonic-gate }; 16277c478bd9Sstevel@tonic-gate 16287c478bd9Sstevel@tonic-gate static void slc_help(); 16297c478bd9Sstevel@tonic-gate 16307c478bd9Sstevel@tonic-gate static struct slclist SlcList[] = { 16317c478bd9Sstevel@tonic-gate { "export", "Use local special character definitions", 16327c478bd9Sstevel@tonic-gate slc_mode_export, 0 }, 16337c478bd9Sstevel@tonic-gate { "import", "Use remote special character definitions", 16347c478bd9Sstevel@tonic-gate slc_mode_import, 1 }, 16357c478bd9Sstevel@tonic-gate { "check", "Verify remote special character definitions", 16367c478bd9Sstevel@tonic-gate slc_mode_import, 0 }, 16377c478bd9Sstevel@tonic-gate { "help", 0, slc_help, 0 }, 16387c478bd9Sstevel@tonic-gate { "?", "Print help information", slc_help, 0 }, 16397c478bd9Sstevel@tonic-gate { 0 }, 16407c478bd9Sstevel@tonic-gate }; 16417c478bd9Sstevel@tonic-gate 16427c478bd9Sstevel@tonic-gate static void 16437c478bd9Sstevel@tonic-gate slc_help() 16447c478bd9Sstevel@tonic-gate { 16457c478bd9Sstevel@tonic-gate struct slclist *c; 16467c478bd9Sstevel@tonic-gate 16477c478bd9Sstevel@tonic-gate for (c = SlcList; c->name; c++) { 16487c478bd9Sstevel@tonic-gate if (c->help) { 16497c478bd9Sstevel@tonic-gate if (*c->help) 16507c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 16517c478bd9Sstevel@tonic-gate else 16527c478bd9Sstevel@tonic-gate (void) printf("\n"); 16537c478bd9Sstevel@tonic-gate } 16547c478bd9Sstevel@tonic-gate } 16557c478bd9Sstevel@tonic-gate } 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate static struct slclist * 16587c478bd9Sstevel@tonic-gate getslc(name) 16597c478bd9Sstevel@tonic-gate char *name; 16607c478bd9Sstevel@tonic-gate { 16617c478bd9Sstevel@tonic-gate return ((struct slclist *) 16627c478bd9Sstevel@tonic-gate genget(name, (char **)SlcList, sizeof (struct slclist))); 16637c478bd9Sstevel@tonic-gate } 16647c478bd9Sstevel@tonic-gate 1665740638c8Sbw static int 16667c478bd9Sstevel@tonic-gate slccmd(argc, argv) 16677c478bd9Sstevel@tonic-gate int argc; 16687c478bd9Sstevel@tonic-gate char *argv[]; 16697c478bd9Sstevel@tonic-gate { 16707c478bd9Sstevel@tonic-gate struct slclist *c; 16717c478bd9Sstevel@tonic-gate 16727c478bd9Sstevel@tonic-gate if (argc != 2) { 16737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16747c478bd9Sstevel@tonic-gate "Need an argument to 'slc' command. 'slc ?' for help.\n"); 16757c478bd9Sstevel@tonic-gate return (0); 16767c478bd9Sstevel@tonic-gate } 16777c478bd9Sstevel@tonic-gate c = getslc(argv[1]); 16787c478bd9Sstevel@tonic-gate if (c == 0) { 16797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16807c478bd9Sstevel@tonic-gate "'%s': unknown argument ('slc ?' for help).\n", 16817c478bd9Sstevel@tonic-gate argv[1]); 16827c478bd9Sstevel@tonic-gate return (0); 16837c478bd9Sstevel@tonic-gate } 16847c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 16857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 16867c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('slc ?' for help).\n", argv[1]); 16877c478bd9Sstevel@tonic-gate return (0); 16887c478bd9Sstevel@tonic-gate } 16897c478bd9Sstevel@tonic-gate (*c->handler)(c->arg); 16907c478bd9Sstevel@tonic-gate slcstate(); 16917c478bd9Sstevel@tonic-gate return (1); 16927c478bd9Sstevel@tonic-gate } 16937c478bd9Sstevel@tonic-gate 16947c478bd9Sstevel@tonic-gate /* 16957c478bd9Sstevel@tonic-gate * The ENVIRON command. 16967c478bd9Sstevel@tonic-gate */ 16977c478bd9Sstevel@tonic-gate 16987c478bd9Sstevel@tonic-gate struct envlist { 16997c478bd9Sstevel@tonic-gate char *name; 17007c478bd9Sstevel@tonic-gate char *help; 17017c478bd9Sstevel@tonic-gate void (*handler)(); 17027c478bd9Sstevel@tonic-gate int narg; 17037c478bd9Sstevel@tonic-gate }; 17047c478bd9Sstevel@tonic-gate 17057c478bd9Sstevel@tonic-gate static struct env_lst *env_define(unsigned char *, unsigned char *); 17067c478bd9Sstevel@tonic-gate static void env_undefine(unsigned char *); 17077c478bd9Sstevel@tonic-gate static void env_export(unsigned char *); 17087c478bd9Sstevel@tonic-gate static void env_unexport(unsigned char *); 17097c478bd9Sstevel@tonic-gate static void env_send(unsigned char *); 17107c478bd9Sstevel@tonic-gate #if defined(OLD_ENVIRON) && defined(ENV_HACK) 17117c478bd9Sstevel@tonic-gate static void env_varval(unsigned char *); 17127c478bd9Sstevel@tonic-gate #endif 17137c478bd9Sstevel@tonic-gate static void env_list(void); 17147c478bd9Sstevel@tonic-gate 17157c478bd9Sstevel@tonic-gate static void env_help(void); 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate static struct envlist EnvList[] = { 17187c478bd9Sstevel@tonic-gate { "define", "Define an environment variable", 17197c478bd9Sstevel@tonic-gate (void (*)())env_define, 2 }, 17207c478bd9Sstevel@tonic-gate { "undefine", "Undefine an environment variable", 17217c478bd9Sstevel@tonic-gate env_undefine, 1 }, 17227c478bd9Sstevel@tonic-gate { "export", "Mark an environment variable for automatic export", 17237c478bd9Sstevel@tonic-gate env_export, 1 }, 17247c478bd9Sstevel@tonic-gate { "unexport", "Don't mark an environment variable for automatic export", 17257c478bd9Sstevel@tonic-gate env_unexport, 1 }, 17267c478bd9Sstevel@tonic-gate { "send", "Send an environment variable", env_send, 1 }, 17277c478bd9Sstevel@tonic-gate { "list", "List the current environment variables", 17287c478bd9Sstevel@tonic-gate env_list, 0 }, 17297c478bd9Sstevel@tonic-gate #if defined(OLD_ENVIRON) && defined(ENV_HACK) 17307c478bd9Sstevel@tonic-gate { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 17317c478bd9Sstevel@tonic-gate env_varval, 1 }, 17327c478bd9Sstevel@tonic-gate #endif 17337c478bd9Sstevel@tonic-gate { "help", 0, env_help, 0 }, 17347c478bd9Sstevel@tonic-gate { "?", "Print help information", env_help, 0 }, 17357c478bd9Sstevel@tonic-gate { 0 }, 17367c478bd9Sstevel@tonic-gate }; 17377c478bd9Sstevel@tonic-gate 17387c478bd9Sstevel@tonic-gate static void 17397c478bd9Sstevel@tonic-gate env_help() 17407c478bd9Sstevel@tonic-gate { 17417c478bd9Sstevel@tonic-gate struct envlist *c; 17427c478bd9Sstevel@tonic-gate 17437c478bd9Sstevel@tonic-gate for (c = EnvList; c->name; c++) { 17447c478bd9Sstevel@tonic-gate if (c->help) { 17457c478bd9Sstevel@tonic-gate if (*c->help) 17467c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 17477c478bd9Sstevel@tonic-gate else 17487c478bd9Sstevel@tonic-gate (void) printf("\n"); 17497c478bd9Sstevel@tonic-gate } 17507c478bd9Sstevel@tonic-gate } 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate static struct envlist * 17547c478bd9Sstevel@tonic-gate getenvcmd(name) 17557c478bd9Sstevel@tonic-gate char *name; 17567c478bd9Sstevel@tonic-gate { 17577c478bd9Sstevel@tonic-gate return ((struct envlist *) 17587c478bd9Sstevel@tonic-gate genget(name, (char **)EnvList, sizeof (struct envlist))); 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate static int 17627c478bd9Sstevel@tonic-gate env_cmd(argc, argv) 17637c478bd9Sstevel@tonic-gate int argc; 17647c478bd9Sstevel@tonic-gate char *argv[]; 17657c478bd9Sstevel@tonic-gate { 17667c478bd9Sstevel@tonic-gate struct envlist *c; 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate if (argc < 2) { 17697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17707c478bd9Sstevel@tonic-gate "Need an argument to 'environ' command. " 17717c478bd9Sstevel@tonic-gate "'environ ?' for help.\n"); 17727c478bd9Sstevel@tonic-gate return (0); 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate c = getenvcmd(argv[1]); 17757c478bd9Sstevel@tonic-gate if (c == 0) { 17767c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': unknown argument " 17777c478bd9Sstevel@tonic-gate "('environ ?' for help).\n", argv[1]); 17787c478bd9Sstevel@tonic-gate return (0); 17797c478bd9Sstevel@tonic-gate } 17807c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 17817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "'%s': ambiguous argument " 17827c478bd9Sstevel@tonic-gate "('environ ?' for help).\n", argv[1]); 17837c478bd9Sstevel@tonic-gate return (0); 17847c478bd9Sstevel@tonic-gate } 17857c478bd9Sstevel@tonic-gate if (c->narg + 2 != argc) { 17867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 17877c478bd9Sstevel@tonic-gate "Need %s%d argument%s to 'environ %s' command. " 17887c478bd9Sstevel@tonic-gate "'environ ?' for help.\n", 17897c478bd9Sstevel@tonic-gate c->narg + 2 < argc ? "only " : "", 17907c478bd9Sstevel@tonic-gate c->narg, c->narg == 1 ? "" : "s", c->name); 17917c478bd9Sstevel@tonic-gate return (0); 17927c478bd9Sstevel@tonic-gate } 17937c478bd9Sstevel@tonic-gate (*c->handler)(argv[2], argv[3]); 17947c478bd9Sstevel@tonic-gate return (1); 17957c478bd9Sstevel@tonic-gate } 17967c478bd9Sstevel@tonic-gate 17977c478bd9Sstevel@tonic-gate struct env_lst { 17987c478bd9Sstevel@tonic-gate struct env_lst *next; /* pointer to next structure */ 17997c478bd9Sstevel@tonic-gate struct env_lst *prev; /* pointer to previous structure */ 18007c478bd9Sstevel@tonic-gate unsigned char *var; /* pointer to variable name */ 18017c478bd9Sstevel@tonic-gate unsigned char *value; /* pointer to variable value */ 18027c478bd9Sstevel@tonic-gate int export; /* 1 -> export with default list of variables */ 18037c478bd9Sstevel@tonic-gate int welldefined; /* A well defined variable */ 18047c478bd9Sstevel@tonic-gate }; 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate static struct env_lst envlisthead; 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate static struct env_lst * 18097c478bd9Sstevel@tonic-gate env_find(var) 18107c478bd9Sstevel@tonic-gate unsigned char *var; 18117c478bd9Sstevel@tonic-gate { 18127c478bd9Sstevel@tonic-gate register struct env_lst *ep; 18137c478bd9Sstevel@tonic-gate 18147c478bd9Sstevel@tonic-gate for (ep = envlisthead.next; ep; ep = ep->next) { 18157c478bd9Sstevel@tonic-gate if (strcmp((char *)ep->var, (char *)var) == 0) 18167c478bd9Sstevel@tonic-gate return (ep); 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate return (NULL); 18197c478bd9Sstevel@tonic-gate } 18207c478bd9Sstevel@tonic-gate 18217c478bd9Sstevel@tonic-gate int 18227c478bd9Sstevel@tonic-gate env_init() 18237c478bd9Sstevel@tonic-gate { 18247c478bd9Sstevel@tonic-gate #ifdef lint 18257c478bd9Sstevel@tonic-gate char **environ = NULL; 18267c478bd9Sstevel@tonic-gate #else /* lint */ 18277c478bd9Sstevel@tonic-gate extern char **environ; 18287c478bd9Sstevel@tonic-gate #endif /* lint */ 18297c478bd9Sstevel@tonic-gate char **epp, *cp; 18307c478bd9Sstevel@tonic-gate struct env_lst *ep; 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate for (epp = environ; *epp; epp++) { 18337c478bd9Sstevel@tonic-gate if (cp = strchr(*epp, '=')) { 18347c478bd9Sstevel@tonic-gate *cp = '\0'; 18357c478bd9Sstevel@tonic-gate 18367c478bd9Sstevel@tonic-gate ep = env_define((unsigned char *)*epp, 18377c478bd9Sstevel@tonic-gate (unsigned char *)cp+1); 18387c478bd9Sstevel@tonic-gate if (ep == NULL) 18397c478bd9Sstevel@tonic-gate return (0); 18407c478bd9Sstevel@tonic-gate ep->export = 0; 18417c478bd9Sstevel@tonic-gate *cp = '='; 18427c478bd9Sstevel@tonic-gate } 18437c478bd9Sstevel@tonic-gate } 18447c478bd9Sstevel@tonic-gate /* 18457c478bd9Sstevel@tonic-gate * Special case for DISPLAY variable. If it is ":0.0" or 18467c478bd9Sstevel@tonic-gate * "unix:0.0", we have to get rid of "unix" and insert our 18477c478bd9Sstevel@tonic-gate * hostname. 18487c478bd9Sstevel@tonic-gate */ 18497c478bd9Sstevel@tonic-gate if (((ep = env_find((uchar_t *)"DISPLAY")) != NULL) && 18507c478bd9Sstevel@tonic-gate ((*ep->value == ':') || 18517c478bd9Sstevel@tonic-gate (strncmp((char *)ep->value, "unix:", 5) == 0))) { 18527c478bd9Sstevel@tonic-gate char hbuf[MAXHOSTNAMELEN]; 18537c478bd9Sstevel@tonic-gate char *cp2 = strchr((char *)ep->value, ':'); 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate if (gethostname(hbuf, MAXHOSTNAMELEN) == -1) { 18567c478bd9Sstevel@tonic-gate perror("telnet: cannot get hostname"); 18577c478bd9Sstevel@tonic-gate return (0); 18587c478bd9Sstevel@tonic-gate } 18597c478bd9Sstevel@tonic-gate hbuf[MAXHOSTNAMELEN-1] = '\0'; 18607c478bd9Sstevel@tonic-gate cp = malloc(strlen(hbuf) + strlen(cp2) + 1); 18617c478bd9Sstevel@tonic-gate if (cp == NULL) { 18627c478bd9Sstevel@tonic-gate perror("telnet: cannot define DISPLAY variable"); 18637c478bd9Sstevel@tonic-gate return (0); 18647c478bd9Sstevel@tonic-gate } 18657c478bd9Sstevel@tonic-gate (void) sprintf((char *)cp, "%s%s", hbuf, cp2); 18667c478bd9Sstevel@tonic-gate free(ep->value); 18677c478bd9Sstevel@tonic-gate ep->value = (unsigned char *)cp; 18687c478bd9Sstevel@tonic-gate } 18697c478bd9Sstevel@tonic-gate /* 18707c478bd9Sstevel@tonic-gate * If LOGNAME is defined, but USER is not, then add 18717c478bd9Sstevel@tonic-gate * USER with the value from LOGNAME. We do this because the "accepted 18727c478bd9Sstevel@tonic-gate * practice" is to always pass USER on the wire, but SVR4 uses 18737c478bd9Sstevel@tonic-gate * LOGNAME by default. 18747c478bd9Sstevel@tonic-gate */ 18757c478bd9Sstevel@tonic-gate if ((ep = env_find((uchar_t *)"LOGNAME")) != NULL && 18767c478bd9Sstevel@tonic-gate env_find((uchar_t *)"USER") == NULL) { 18777c478bd9Sstevel@tonic-gate if (env_define((unsigned char *)"USER", ep->value) != NULL) 18787c478bd9Sstevel@tonic-gate env_unexport((unsigned char *)"USER"); 18797c478bd9Sstevel@tonic-gate } 18807c478bd9Sstevel@tonic-gate env_export((unsigned char *)"DISPLAY"); 18817c478bd9Sstevel@tonic-gate env_export((unsigned char *)"PRINTER"); 18827c478bd9Sstevel@tonic-gate 18837c478bd9Sstevel@tonic-gate return (1); 18847c478bd9Sstevel@tonic-gate } 18857c478bd9Sstevel@tonic-gate 18867c478bd9Sstevel@tonic-gate static struct env_lst * 18877c478bd9Sstevel@tonic-gate env_define(var, value) 18887c478bd9Sstevel@tonic-gate unsigned char *var, *value; 18897c478bd9Sstevel@tonic-gate { 18907c478bd9Sstevel@tonic-gate unsigned char *tmp_value; 18917c478bd9Sstevel@tonic-gate unsigned char *tmp_var; 18927c478bd9Sstevel@tonic-gate struct env_lst *ep; 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate /* 18957c478bd9Sstevel@tonic-gate * Allocate copies of arguments first, to make cleanup easier 18967c478bd9Sstevel@tonic-gate * in the case of allocation errors. 18977c478bd9Sstevel@tonic-gate */ 18987c478bd9Sstevel@tonic-gate tmp_var = (unsigned char *)strdup((char *)var); 18997c478bd9Sstevel@tonic-gate if (tmp_var == NULL) { 19007c478bd9Sstevel@tonic-gate perror("telnet: can't copy environment variable name"); 19017c478bd9Sstevel@tonic-gate return (NULL); 19027c478bd9Sstevel@tonic-gate } 19037c478bd9Sstevel@tonic-gate 19047c478bd9Sstevel@tonic-gate tmp_value = (unsigned char *)strdup((char *)value); 19057c478bd9Sstevel@tonic-gate if (tmp_value == NULL) { 19067c478bd9Sstevel@tonic-gate free(tmp_var); 19077c478bd9Sstevel@tonic-gate perror("telnet: can't copy environment variable value"); 19087c478bd9Sstevel@tonic-gate return (NULL); 19097c478bd9Sstevel@tonic-gate } 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate if (ep = env_find(var)) { 19127c478bd9Sstevel@tonic-gate if (ep->var) 19137c478bd9Sstevel@tonic-gate free(ep->var); 19147c478bd9Sstevel@tonic-gate if (ep->value) 19157c478bd9Sstevel@tonic-gate free(ep->value); 19167c478bd9Sstevel@tonic-gate } else { 19177c478bd9Sstevel@tonic-gate ep = malloc(sizeof (struct env_lst)); 19187c478bd9Sstevel@tonic-gate if (ep == NULL) { 19197c478bd9Sstevel@tonic-gate perror("telnet: can't define environment variable"); 19207c478bd9Sstevel@tonic-gate free(tmp_var); 19217c478bd9Sstevel@tonic-gate free(tmp_value); 19227c478bd9Sstevel@tonic-gate return (NULL); 19237c478bd9Sstevel@tonic-gate } 19247c478bd9Sstevel@tonic-gate 19257c478bd9Sstevel@tonic-gate ep->next = envlisthead.next; 19267c478bd9Sstevel@tonic-gate envlisthead.next = ep; 19277c478bd9Sstevel@tonic-gate ep->prev = &envlisthead; 19287c478bd9Sstevel@tonic-gate if (ep->next) 19297c478bd9Sstevel@tonic-gate ep->next->prev = ep; 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate ep->welldefined = opt_welldefined((char *)var); 19327c478bd9Sstevel@tonic-gate ep->export = 1; 19337c478bd9Sstevel@tonic-gate ep->var = tmp_var; 19347c478bd9Sstevel@tonic-gate ep->value = tmp_value; 19357c478bd9Sstevel@tonic-gate 19367c478bd9Sstevel@tonic-gate return (ep); 19377c478bd9Sstevel@tonic-gate } 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate static void 19407c478bd9Sstevel@tonic-gate env_undefine(var) 19417c478bd9Sstevel@tonic-gate unsigned char *var; 19427c478bd9Sstevel@tonic-gate { 19437c478bd9Sstevel@tonic-gate register struct env_lst *ep; 19447c478bd9Sstevel@tonic-gate 19457c478bd9Sstevel@tonic-gate if (ep = env_find(var)) { 19467c478bd9Sstevel@tonic-gate ep->prev->next = ep->next; 19477c478bd9Sstevel@tonic-gate if (ep->next) 19487c478bd9Sstevel@tonic-gate ep->next->prev = ep->prev; 19497c478bd9Sstevel@tonic-gate if (ep->var) 19507c478bd9Sstevel@tonic-gate free(ep->var); 19517c478bd9Sstevel@tonic-gate if (ep->value) 19527c478bd9Sstevel@tonic-gate free(ep->value); 19537c478bd9Sstevel@tonic-gate free(ep); 19547c478bd9Sstevel@tonic-gate } 19557c478bd9Sstevel@tonic-gate } 19567c478bd9Sstevel@tonic-gate 19577c478bd9Sstevel@tonic-gate static void 19587c478bd9Sstevel@tonic-gate env_export(var) 19597c478bd9Sstevel@tonic-gate unsigned char *var; 19607c478bd9Sstevel@tonic-gate { 19617c478bd9Sstevel@tonic-gate register struct env_lst *ep; 19627c478bd9Sstevel@tonic-gate 19637c478bd9Sstevel@tonic-gate if (ep = env_find(var)) 19647c478bd9Sstevel@tonic-gate ep->export = 1; 19657c478bd9Sstevel@tonic-gate } 19667c478bd9Sstevel@tonic-gate 19677c478bd9Sstevel@tonic-gate static void 19687c478bd9Sstevel@tonic-gate env_unexport(var) 19697c478bd9Sstevel@tonic-gate unsigned char *var; 19707c478bd9Sstevel@tonic-gate { 19717c478bd9Sstevel@tonic-gate register struct env_lst *ep; 19727c478bd9Sstevel@tonic-gate 19737c478bd9Sstevel@tonic-gate if (ep = env_find(var)) 19747c478bd9Sstevel@tonic-gate ep->export = 0; 19757c478bd9Sstevel@tonic-gate } 19767c478bd9Sstevel@tonic-gate 19777c478bd9Sstevel@tonic-gate static void 19787c478bd9Sstevel@tonic-gate env_send(var) 19797c478bd9Sstevel@tonic-gate unsigned char *var; 19807c478bd9Sstevel@tonic-gate { 19817c478bd9Sstevel@tonic-gate register struct env_lst *ep; 19827c478bd9Sstevel@tonic-gate 19837c478bd9Sstevel@tonic-gate if (my_state_is_wont(TELOPT_NEW_ENVIRON) 19847c478bd9Sstevel@tonic-gate #ifdef OLD_ENVIRON 19857c478bd9Sstevel@tonic-gate /* old style */ && my_state_is_wont(TELOPT_OLD_ENVIRON) 19867c478bd9Sstevel@tonic-gate #endif 19877c478bd9Sstevel@tonic-gate /* no environ */) { 19887c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19897c478bd9Sstevel@tonic-gate "Cannot send '%s': Telnet ENVIRON option not enabled\n", 19907c478bd9Sstevel@tonic-gate var); 19917c478bd9Sstevel@tonic-gate return; 19927c478bd9Sstevel@tonic-gate } 19937c478bd9Sstevel@tonic-gate ep = env_find(var); 19947c478bd9Sstevel@tonic-gate if (ep == 0) { 19957c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 19967c478bd9Sstevel@tonic-gate "Cannot send '%s': variable not defined\n", var); 19977c478bd9Sstevel@tonic-gate return; 19987c478bd9Sstevel@tonic-gate } 19997c478bd9Sstevel@tonic-gate env_opt_start_info(); 20007c478bd9Sstevel@tonic-gate env_opt_add(ep->var); 20017c478bd9Sstevel@tonic-gate env_opt_end(0); 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate 20047c478bd9Sstevel@tonic-gate static void 20057c478bd9Sstevel@tonic-gate env_list() 20067c478bd9Sstevel@tonic-gate { 20077c478bd9Sstevel@tonic-gate register struct env_lst *ep; 20087c478bd9Sstevel@tonic-gate 20097c478bd9Sstevel@tonic-gate for (ep = envlisthead.next; ep; ep = ep->next) { 20107c478bd9Sstevel@tonic-gate (void) printf("%c %-20s %s\n", ep->export ? '*' : ' ', 20117c478bd9Sstevel@tonic-gate ep->var, ep->value); 20127c478bd9Sstevel@tonic-gate } 20137c478bd9Sstevel@tonic-gate } 20147c478bd9Sstevel@tonic-gate 20157c478bd9Sstevel@tonic-gate unsigned char * 20167c478bd9Sstevel@tonic-gate env_default(init, welldefined) 20177c478bd9Sstevel@tonic-gate int init; 20187c478bd9Sstevel@tonic-gate { 20197c478bd9Sstevel@tonic-gate static struct env_lst *nep = NULL; 20207c478bd9Sstevel@tonic-gate 20217c478bd9Sstevel@tonic-gate if (init) { 20227c478bd9Sstevel@tonic-gate /* return value is not used */ 20237c478bd9Sstevel@tonic-gate nep = &envlisthead; 20247c478bd9Sstevel@tonic-gate return (NULL); 20257c478bd9Sstevel@tonic-gate } 20267c478bd9Sstevel@tonic-gate if (nep) { 20277c478bd9Sstevel@tonic-gate while ((nep = nep->next) != NULL) { 20287c478bd9Sstevel@tonic-gate if (nep->export && (nep->welldefined == welldefined)) 20297c478bd9Sstevel@tonic-gate return (nep->var); 20307c478bd9Sstevel@tonic-gate } 20317c478bd9Sstevel@tonic-gate } 20327c478bd9Sstevel@tonic-gate return (NULL); 20337c478bd9Sstevel@tonic-gate } 20347c478bd9Sstevel@tonic-gate 20357c478bd9Sstevel@tonic-gate unsigned char * 20367c478bd9Sstevel@tonic-gate env_getvalue(var) 20377c478bd9Sstevel@tonic-gate unsigned char *var; 20387c478bd9Sstevel@tonic-gate { 20397c478bd9Sstevel@tonic-gate register struct env_lst *ep; 20407c478bd9Sstevel@tonic-gate 20417c478bd9Sstevel@tonic-gate if (ep = env_find(var)) 20427c478bd9Sstevel@tonic-gate return (ep->value); 20437c478bd9Sstevel@tonic-gate return (NULL); 20447c478bd9Sstevel@tonic-gate } 20457c478bd9Sstevel@tonic-gate 20467c478bd9Sstevel@tonic-gate #if defined(OLD_ENVIRON) && defined(ENV_HACK) 20477c478bd9Sstevel@tonic-gate static void 20487c478bd9Sstevel@tonic-gate env_varval(what) 20497c478bd9Sstevel@tonic-gate unsigned char *what; 20507c478bd9Sstevel@tonic-gate { 20517c478bd9Sstevel@tonic-gate extern int old_env_var, old_env_value, env_auto; 20527c478bd9Sstevel@tonic-gate int len = strlen((char *)what); 20537c478bd9Sstevel@tonic-gate 20547c478bd9Sstevel@tonic-gate if (len == 0) 20557c478bd9Sstevel@tonic-gate goto unknown; 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate if (strncasecmp((char *)what, "status", len) == 0) { 20587c478bd9Sstevel@tonic-gate if (env_auto) 20597c478bd9Sstevel@tonic-gate (void) printf("%s%s", "VAR and VALUE are/will be ", 20607c478bd9Sstevel@tonic-gate "determined automatically\n"); 20617c478bd9Sstevel@tonic-gate if (old_env_var == OLD_ENV_VAR) 20627c478bd9Sstevel@tonic-gate (void) printf( 20637c478bd9Sstevel@tonic-gate "VAR and VALUE set to correct definitions\n"); 20647c478bd9Sstevel@tonic-gate else 20657c478bd9Sstevel@tonic-gate (void) printf( 20667c478bd9Sstevel@tonic-gate "VAR and VALUE definitions are reversed\n"); 20677c478bd9Sstevel@tonic-gate } else if (strncasecmp((char *)what, "auto", len) == 0) { 20687c478bd9Sstevel@tonic-gate env_auto = 1; 20697c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VALUE; 20707c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VAR; 20717c478bd9Sstevel@tonic-gate } else if (strncasecmp((char *)what, "right", len) == 0) { 20727c478bd9Sstevel@tonic-gate env_auto = 0; 20737c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VAR; 20747c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VALUE; 20757c478bd9Sstevel@tonic-gate } else if (strncasecmp((char *)what, "wrong", len) == 0) { 20767c478bd9Sstevel@tonic-gate env_auto = 0; 20777c478bd9Sstevel@tonic-gate old_env_var = OLD_ENV_VALUE; 20787c478bd9Sstevel@tonic-gate old_env_value = OLD_ENV_VAR; 20797c478bd9Sstevel@tonic-gate } else { 20807c478bd9Sstevel@tonic-gate unknown: 20817c478bd9Sstevel@tonic-gate (void) printf( 20827c478bd9Sstevel@tonic-gate "Unknown \"varval\" command. (\"auto\", \"right\", " 20837c478bd9Sstevel@tonic-gate "\"wrong\", \"status\")\n"); 20847c478bd9Sstevel@tonic-gate } 20857c478bd9Sstevel@tonic-gate } 20867c478bd9Sstevel@tonic-gate #endif /* OLD_ENVIRON && ENV_HACK */ 20877c478bd9Sstevel@tonic-gate 20887c478bd9Sstevel@tonic-gate /* 20897c478bd9Sstevel@tonic-gate * The AUTHENTICATE command. 20907c478bd9Sstevel@tonic-gate */ 20917c478bd9Sstevel@tonic-gate 20927c478bd9Sstevel@tonic-gate struct authlist { 20937c478bd9Sstevel@tonic-gate char *name; 20947c478bd9Sstevel@tonic-gate char *help; 20957c478bd9Sstevel@tonic-gate int (*handler)(); 20967c478bd9Sstevel@tonic-gate int narg; 20977c478bd9Sstevel@tonic-gate }; 20987c478bd9Sstevel@tonic-gate 20997c478bd9Sstevel@tonic-gate extern int auth_enable(char *); 21007c478bd9Sstevel@tonic-gate extern int auth_disable(char *); 21017c478bd9Sstevel@tonic-gate extern int auth_status(void); 21027c478bd9Sstevel@tonic-gate 21037c478bd9Sstevel@tonic-gate static int auth_help(void); 21047c478bd9Sstevel@tonic-gate 21057c478bd9Sstevel@tonic-gate static struct authlist AuthList[] = { 21067c478bd9Sstevel@tonic-gate { "status", 21077c478bd9Sstevel@tonic-gate "Display current status of authentication information", 21087c478bd9Sstevel@tonic-gate auth_status, 0 }, 21097c478bd9Sstevel@tonic-gate { "disable", 21107c478bd9Sstevel@tonic-gate "Disable an authentication type ('auth disable ?' for more)", 21117c478bd9Sstevel@tonic-gate auth_disable, 1 }, 21127c478bd9Sstevel@tonic-gate { "enable", 21137c478bd9Sstevel@tonic-gate "Enable an authentication type ('auth enable ?' for more)", 21147c478bd9Sstevel@tonic-gate auth_enable, 1 }, 21157c478bd9Sstevel@tonic-gate { "help", 0, auth_help, 0 }, 21167c478bd9Sstevel@tonic-gate { "?", "Print help information", auth_help, 0 }, 21177c478bd9Sstevel@tonic-gate { 0 }, 21187c478bd9Sstevel@tonic-gate }; 21197c478bd9Sstevel@tonic-gate 21207c478bd9Sstevel@tonic-gate static int 21217c478bd9Sstevel@tonic-gate auth_help(void) 21227c478bd9Sstevel@tonic-gate { 21237c478bd9Sstevel@tonic-gate struct authlist *c; 21247c478bd9Sstevel@tonic-gate 21257c478bd9Sstevel@tonic-gate for (c = AuthList; c->name; c++) { 21267c478bd9Sstevel@tonic-gate if (c->help) { 21277c478bd9Sstevel@tonic-gate if (*c->help) 21287c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 21297c478bd9Sstevel@tonic-gate else 21307c478bd9Sstevel@tonic-gate (void) printf("\n"); 21317c478bd9Sstevel@tonic-gate } 21327c478bd9Sstevel@tonic-gate } 21337c478bd9Sstevel@tonic-gate return (0); 21347c478bd9Sstevel@tonic-gate } 21357c478bd9Sstevel@tonic-gate 21367c478bd9Sstevel@tonic-gate 21377c478bd9Sstevel@tonic-gate static int 21387c478bd9Sstevel@tonic-gate auth_cmd(argc, argv) 21397c478bd9Sstevel@tonic-gate int argc; 21407c478bd9Sstevel@tonic-gate char *argv[]; 21417c478bd9Sstevel@tonic-gate { 21427c478bd9Sstevel@tonic-gate struct authlist *c; 21437c478bd9Sstevel@tonic-gate 21447c478bd9Sstevel@tonic-gate if (argc < 2) { 21457c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Need an argument to 'auth' " 21467c478bd9Sstevel@tonic-gate "command. 'auth ?' for help.\n"); 21477c478bd9Sstevel@tonic-gate return (0); 21487c478bd9Sstevel@tonic-gate } 21497c478bd9Sstevel@tonic-gate 21507c478bd9Sstevel@tonic-gate c = (struct authlist *) 21517c478bd9Sstevel@tonic-gate genget(argv[1], (char **)AuthList, sizeof (struct authlist)); 21527c478bd9Sstevel@tonic-gate if (c == 0) { 21537c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 21547c478bd9Sstevel@tonic-gate "'%s': unknown argument ('auth ?' for help).\n", 21557c478bd9Sstevel@tonic-gate argv[1]); 21567c478bd9Sstevel@tonic-gate return (0); 21577c478bd9Sstevel@tonic-gate } 21587c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 21597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 21607c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('auth ?' for help).\n", argv[1]); 21617c478bd9Sstevel@tonic-gate return (0); 21627c478bd9Sstevel@tonic-gate } 21637c478bd9Sstevel@tonic-gate if (c->narg + 2 != argc) { 21647c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 21657c478bd9Sstevel@tonic-gate "Need %s%d argument%s to 'auth %s' command." 21667c478bd9Sstevel@tonic-gate " 'auth ?' for help.\n", 21677c478bd9Sstevel@tonic-gate c->narg + 2 < argc ? "only " : "", 21687c478bd9Sstevel@tonic-gate c->narg, c->narg == 1 ? "" : "s", c->name); 21697c478bd9Sstevel@tonic-gate return (0); 21707c478bd9Sstevel@tonic-gate } 21717c478bd9Sstevel@tonic-gate return ((*c->handler)(argv[2], argv[3])); 21727c478bd9Sstevel@tonic-gate } 21737c478bd9Sstevel@tonic-gate 21747c478bd9Sstevel@tonic-gate /* 21757c478bd9Sstevel@tonic-gate * The FORWARD command. 21767c478bd9Sstevel@tonic-gate */ 21777c478bd9Sstevel@tonic-gate 21787c478bd9Sstevel@tonic-gate extern int forward_flags; 21797c478bd9Sstevel@tonic-gate 21807c478bd9Sstevel@tonic-gate struct forwlist { 21817c478bd9Sstevel@tonic-gate char *name; 21827c478bd9Sstevel@tonic-gate char *help; 21837c478bd9Sstevel@tonic-gate int (*handler)(); 21847c478bd9Sstevel@tonic-gate int f_flags; 21857c478bd9Sstevel@tonic-gate }; 21867c478bd9Sstevel@tonic-gate 21877c478bd9Sstevel@tonic-gate static int forw_status(void); 21887c478bd9Sstevel@tonic-gate static int forw_set(int); 21897c478bd9Sstevel@tonic-gate static int forw_help(void); 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate static struct forwlist ForwList[] = { 21927c478bd9Sstevel@tonic-gate {"status", 21937c478bd9Sstevel@tonic-gate "Display current status of credential forwarding", 21947c478bd9Sstevel@tonic-gate forw_status, 0}, 21957c478bd9Sstevel@tonic-gate {"disable", 21967c478bd9Sstevel@tonic-gate "Disable credential forwarding", 21977c478bd9Sstevel@tonic-gate forw_set, 0}, 21987c478bd9Sstevel@tonic-gate {"enable", 21997c478bd9Sstevel@tonic-gate "Enable credential forwarding", 22007c478bd9Sstevel@tonic-gate forw_set, OPTS_FORWARD_CREDS}, 22017c478bd9Sstevel@tonic-gate {"forwardable", 22027c478bd9Sstevel@tonic-gate "Enable credential forwarding of " 22037c478bd9Sstevel@tonic-gate "forwardable credentials", 22047c478bd9Sstevel@tonic-gate forw_set, OPTS_FORWARD_CREDS | OPTS_FORWARDABLE_CREDS}, 22057c478bd9Sstevel@tonic-gate {"help", 22067c478bd9Sstevel@tonic-gate 0, 22077c478bd9Sstevel@tonic-gate forw_help, 0}, 22087c478bd9Sstevel@tonic-gate {"?", 22097c478bd9Sstevel@tonic-gate "Print help information", 22107c478bd9Sstevel@tonic-gate forw_help, 0}, 22117c478bd9Sstevel@tonic-gate {0}, 22127c478bd9Sstevel@tonic-gate }; 22137c478bd9Sstevel@tonic-gate 22147c478bd9Sstevel@tonic-gate static int 22157c478bd9Sstevel@tonic-gate forw_status(void) 22167c478bd9Sstevel@tonic-gate { 22177c478bd9Sstevel@tonic-gate if (forward_flags & OPTS_FORWARD_CREDS) { 22187c478bd9Sstevel@tonic-gate if (forward_flags & OPTS_FORWARDABLE_CREDS) 22197c478bd9Sstevel@tonic-gate (void) printf(gettext( 22207c478bd9Sstevel@tonic-gate "Credential forwarding of " 22217c478bd9Sstevel@tonic-gate "forwardable credentials enabled\n")); 22227c478bd9Sstevel@tonic-gate else 22237c478bd9Sstevel@tonic-gate (void) printf(gettext( 22247c478bd9Sstevel@tonic-gate "Credential forwarding enabled\n")); 22257c478bd9Sstevel@tonic-gate } else 22267c478bd9Sstevel@tonic-gate (void) printf(gettext("Credential forwarding disabled\n")); 22277c478bd9Sstevel@tonic-gate return (0); 22287c478bd9Sstevel@tonic-gate } 22297c478bd9Sstevel@tonic-gate 2230740638c8Sbw static int 22317c478bd9Sstevel@tonic-gate forw_set(int f_flags) 22327c478bd9Sstevel@tonic-gate { 22337c478bd9Sstevel@tonic-gate forward_flags = f_flags; 22347c478bd9Sstevel@tonic-gate return (0); 22357c478bd9Sstevel@tonic-gate } 22367c478bd9Sstevel@tonic-gate 22377c478bd9Sstevel@tonic-gate static int 22387c478bd9Sstevel@tonic-gate forw_help(void) 22397c478bd9Sstevel@tonic-gate { 22407c478bd9Sstevel@tonic-gate struct forwlist *c; 22417c478bd9Sstevel@tonic-gate 22427c478bd9Sstevel@tonic-gate for (c = ForwList; c->name; c++) { 22437c478bd9Sstevel@tonic-gate if (c->help) { 22447c478bd9Sstevel@tonic-gate if (*c->help) 22457c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\r\n", c->name, c->help); 22467c478bd9Sstevel@tonic-gate else 22477c478bd9Sstevel@tonic-gate (void) printf("\n"); 22487c478bd9Sstevel@tonic-gate } 22497c478bd9Sstevel@tonic-gate } 22507c478bd9Sstevel@tonic-gate return (0); 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate static int 22547c478bd9Sstevel@tonic-gate forw_cmd(int argc, char *argv[]) 22557c478bd9Sstevel@tonic-gate { 22567c478bd9Sstevel@tonic-gate struct forwlist *c; 22577c478bd9Sstevel@tonic-gate 22587c478bd9Sstevel@tonic-gate if (argc < 2) { 22597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 22607c478bd9Sstevel@tonic-gate "Need an argument to 'forward' " 22617c478bd9Sstevel@tonic-gate "command. 'forward ?' for help.\n")); 22627c478bd9Sstevel@tonic-gate return (0); 22637c478bd9Sstevel@tonic-gate } 22647c478bd9Sstevel@tonic-gate c = (struct forwlist *)genget(argv[1], (char **)ForwList, 22657c478bd9Sstevel@tonic-gate sizeof (struct forwlist)); 22667c478bd9Sstevel@tonic-gate if (c == 0) { 22677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 22687c478bd9Sstevel@tonic-gate "'%s': unknown argument ('forward ?' for help).\n"), 22697c478bd9Sstevel@tonic-gate argv[1]); 22707c478bd9Sstevel@tonic-gate return (0); 22717c478bd9Sstevel@tonic-gate } 22727c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 22737c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 22747c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('forward ?' for help).\n"), 22757c478bd9Sstevel@tonic-gate argv[1]); 22767c478bd9Sstevel@tonic-gate return (0); 22777c478bd9Sstevel@tonic-gate } 22787c478bd9Sstevel@tonic-gate if (argc != 2) { 22797c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 22807c478bd9Sstevel@tonic-gate "No arguments needed to 'forward %s' command. " 22817c478bd9Sstevel@tonic-gate "'forward ?' for help.\n"), c->name); 22827c478bd9Sstevel@tonic-gate return (0); 22837c478bd9Sstevel@tonic-gate } 22847c478bd9Sstevel@tonic-gate return ((*c->handler) (c->f_flags)); 22857c478bd9Sstevel@tonic-gate } 22867c478bd9Sstevel@tonic-gate 22877c478bd9Sstevel@tonic-gate /* 22887c478bd9Sstevel@tonic-gate * The ENCRYPT command. 22897c478bd9Sstevel@tonic-gate */ 22907c478bd9Sstevel@tonic-gate 22917c478bd9Sstevel@tonic-gate struct encryptlist { 22927c478bd9Sstevel@tonic-gate char *name; 22937c478bd9Sstevel@tonic-gate char *help; 22947c478bd9Sstevel@tonic-gate int (*handler)(); 22957c478bd9Sstevel@tonic-gate int needconnect; 22967c478bd9Sstevel@tonic-gate int minarg; 22977c478bd9Sstevel@tonic-gate int maxarg; 22987c478bd9Sstevel@tonic-gate }; 22997c478bd9Sstevel@tonic-gate 23007c478bd9Sstevel@tonic-gate static int EncryptHelp(void); 23017c478bd9Sstevel@tonic-gate 23027c478bd9Sstevel@tonic-gate static struct encryptlist EncryptList[] = { 23037c478bd9Sstevel@tonic-gate { "enable", "Enable encryption. ('encrypt enable ?' for more)", 23047c478bd9Sstevel@tonic-gate EncryptEnable, 1, 1, 2 }, 23057c478bd9Sstevel@tonic-gate { "disable", "Disable encryption. ('encrypt disable ?' for more)", 23067c478bd9Sstevel@tonic-gate EncryptDisable, 0, 1, 2 }, 23077c478bd9Sstevel@tonic-gate { "type", "Set encryption type. ('encrypt type ?' for more)", 23087c478bd9Sstevel@tonic-gate EncryptType, 0, 1, 2 }, 23097c478bd9Sstevel@tonic-gate { "start", "Start encryption. ('encrypt start ?' for more)", 23107c478bd9Sstevel@tonic-gate EncryptStart, 1, 0, 1 }, 23117c478bd9Sstevel@tonic-gate { "stop", "Stop encryption. ('encrypt stop ?' for more)", 23127c478bd9Sstevel@tonic-gate EncryptStop, 1, 0, 1 }, 23137c478bd9Sstevel@tonic-gate { "input", "Start encrypting the input stream", 23147c478bd9Sstevel@tonic-gate EncryptStartInput, 1, 0, 0 }, 23157c478bd9Sstevel@tonic-gate { "-input", "Stop encrypting the input stream", 23167c478bd9Sstevel@tonic-gate EncryptStopInput, 1, 0, 0 }, 23177c478bd9Sstevel@tonic-gate { "output", "Start encrypting the output stream", 23187c478bd9Sstevel@tonic-gate EncryptStartOutput, 1, 0, 0 }, 23197c478bd9Sstevel@tonic-gate { "-output", "Stop encrypting the output stream", 23207c478bd9Sstevel@tonic-gate EncryptStopOutput, 1, 0, 0 }, 23217c478bd9Sstevel@tonic-gate 23227c478bd9Sstevel@tonic-gate { "status", "Display current status of encryption information", 23237c478bd9Sstevel@tonic-gate EncryptStatus, 0, 0, 0 }, 23247c478bd9Sstevel@tonic-gate { "help", 0, 23257c478bd9Sstevel@tonic-gate EncryptHelp, 0, 0, 0 }, 23267c478bd9Sstevel@tonic-gate { "?", "Print help information", EncryptHelp, 0, 0, 0 }, 23277c478bd9Sstevel@tonic-gate { 0 }, 23287c478bd9Sstevel@tonic-gate }; 23297c478bd9Sstevel@tonic-gate 23307c478bd9Sstevel@tonic-gate static int 23317c478bd9Sstevel@tonic-gate EncryptHelp(void) 23327c478bd9Sstevel@tonic-gate { 23337c478bd9Sstevel@tonic-gate struct encryptlist *c; 23347c478bd9Sstevel@tonic-gate 23357c478bd9Sstevel@tonic-gate for (c = EncryptList; c->name; c++) { 23367c478bd9Sstevel@tonic-gate if (c->help) { 23377c478bd9Sstevel@tonic-gate if (*c->help) 23387c478bd9Sstevel@tonic-gate (void) printf("%-15s %s\n", c->name, c->help); 23397c478bd9Sstevel@tonic-gate else 23407c478bd9Sstevel@tonic-gate (void) printf("\n"); 23417c478bd9Sstevel@tonic-gate } 23427c478bd9Sstevel@tonic-gate } 23437c478bd9Sstevel@tonic-gate return (0); 23447c478bd9Sstevel@tonic-gate } 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate static int 23477c478bd9Sstevel@tonic-gate encrypt_cmd(int argc, char *argv[]) 23487c478bd9Sstevel@tonic-gate { 23497c478bd9Sstevel@tonic-gate struct encryptlist *c; 23507c478bd9Sstevel@tonic-gate 23517c478bd9Sstevel@tonic-gate if (argc < 2) { 23527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 23537c478bd9Sstevel@tonic-gate "Need an argument to 'encrypt' command. " 23547c478bd9Sstevel@tonic-gate "'encrypt ?' for help.\n")); 23557c478bd9Sstevel@tonic-gate return (0); 23567c478bd9Sstevel@tonic-gate } 23577c478bd9Sstevel@tonic-gate 23587c478bd9Sstevel@tonic-gate c = (struct encryptlist *) 23597c478bd9Sstevel@tonic-gate genget(argv[1], (char **)EncryptList, sizeof (struct encryptlist)); 23607c478bd9Sstevel@tonic-gate if (c == 0) { 23617c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 23627c478bd9Sstevel@tonic-gate "'%s': unknown argument ('encrypt ?' for help).\n"), 23637c478bd9Sstevel@tonic-gate argv[1]); 23647c478bd9Sstevel@tonic-gate return (0); 23657c478bd9Sstevel@tonic-gate } 23667c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 23677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 23687c478bd9Sstevel@tonic-gate "'%s': ambiguous argument ('encrypt ?' for help).\n"), 23697c478bd9Sstevel@tonic-gate argv[1]); 23707c478bd9Sstevel@tonic-gate return (0); 23717c478bd9Sstevel@tonic-gate } 23727c478bd9Sstevel@tonic-gate argc -= 2; 23737c478bd9Sstevel@tonic-gate if (argc < c->minarg || argc > c->maxarg) { 23747c478bd9Sstevel@tonic-gate if (c->minarg == c->maxarg) { 23757c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Need %s%d %s "), 23767c478bd9Sstevel@tonic-gate c->minarg < argc ? 23777c478bd9Sstevel@tonic-gate gettext("only ") : "", c->minarg, 23787c478bd9Sstevel@tonic-gate c->minarg == 1 ? 23797c478bd9Sstevel@tonic-gate gettext("argument") : gettext("arguments")); 23807c478bd9Sstevel@tonic-gate } else { 23817c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 23827c478bd9Sstevel@tonic-gate gettext("Need %s%d-%d arguments "), 23837c478bd9Sstevel@tonic-gate c->maxarg < argc ? 23847c478bd9Sstevel@tonic-gate gettext("only ") : "", c->minarg, c->maxarg); 23857c478bd9Sstevel@tonic-gate } 23867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 23877c478bd9Sstevel@tonic-gate "to 'encrypt %s' command. 'encrypt ?' for help.\n"), 23887c478bd9Sstevel@tonic-gate c->name); 23897c478bd9Sstevel@tonic-gate return (0); 23907c478bd9Sstevel@tonic-gate } 23917c478bd9Sstevel@tonic-gate if (c->needconnect && !connected) { 23927c478bd9Sstevel@tonic-gate if (!(argc && 23937c478bd9Sstevel@tonic-gate (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 23947c478bd9Sstevel@tonic-gate (void) printf( 23957c478bd9Sstevel@tonic-gate gettext("?Need to be connected first.\n")); 23967c478bd9Sstevel@tonic-gate return (0); 23977c478bd9Sstevel@tonic-gate } 23987c478bd9Sstevel@tonic-gate } 23997c478bd9Sstevel@tonic-gate return ((*c->handler)(argc > 0 ? argv[2] : 0, 24007c478bd9Sstevel@tonic-gate argc > 1 ? argv[3] : 0, argc > 2 ? argv[4] : 0)); 24017c478bd9Sstevel@tonic-gate } 24027c478bd9Sstevel@tonic-gate 24037c478bd9Sstevel@tonic-gate /* 24047c478bd9Sstevel@tonic-gate * Print status about the connection. 24057c478bd9Sstevel@tonic-gate */ 2406740638c8Sbw static int 24077c478bd9Sstevel@tonic-gate status(int argc, char *argv[]) 24087c478bd9Sstevel@tonic-gate { 24097c478bd9Sstevel@tonic-gate if (connected) { 24107c478bd9Sstevel@tonic-gate (void) printf("Connected to %s.\n", hostname); 24117c478bd9Sstevel@tonic-gate if ((argc < 2) || strcmp(argv[1], "notmuch")) { 24127c478bd9Sstevel@tonic-gate int mode = getconnmode(); 24137c478bd9Sstevel@tonic-gate 24147c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_LINEMODE)) { 24157c478bd9Sstevel@tonic-gate (void) printf( 24167c478bd9Sstevel@tonic-gate "Operating with LINEMODE option\n"); 24177c478bd9Sstevel@tonic-gate (void) printf( 24187c478bd9Sstevel@tonic-gate "%s line editing\n", (mode&MODE_EDIT) ? 24197c478bd9Sstevel@tonic-gate "Local" : "No"); 24207c478bd9Sstevel@tonic-gate (void) printf("%s catching of signals\n", 24217c478bd9Sstevel@tonic-gate (mode&MODE_TRAPSIG) ? "Local" : "No"); 24227c478bd9Sstevel@tonic-gate slcstate(); 24237c478bd9Sstevel@tonic-gate #ifdef KLUDGELINEMODE 24247c478bd9Sstevel@tonic-gate } else if (kludgelinemode && 24257c478bd9Sstevel@tonic-gate my_want_state_is_dont(TELOPT_SGA)) { 24267c478bd9Sstevel@tonic-gate (void) printf( 24277c478bd9Sstevel@tonic-gate "Operating in obsolete linemode\n"); 24287c478bd9Sstevel@tonic-gate #endif 24297c478bd9Sstevel@tonic-gate } else { 24307c478bd9Sstevel@tonic-gate (void) printf( 24317c478bd9Sstevel@tonic-gate "Operating in single character mode\n"); 24327c478bd9Sstevel@tonic-gate if (localchars) 24337c478bd9Sstevel@tonic-gate (void) printf( 24347c478bd9Sstevel@tonic-gate "Catching signals locally\n"); 24357c478bd9Sstevel@tonic-gate } 24367c478bd9Sstevel@tonic-gate (void) printf("%s character echo\n", (mode&MODE_ECHO) ? 24377c478bd9Sstevel@tonic-gate "Local" : "Remote"); 24387c478bd9Sstevel@tonic-gate if (my_want_state_is_will(TELOPT_LFLOW)) 24397c478bd9Sstevel@tonic-gate (void) printf("%s flow control\n", 24407c478bd9Sstevel@tonic-gate (mode&MODE_FLOW) ? "Local" : "No"); 24417c478bd9Sstevel@tonic-gate 2442*23a2029dSToomas Soome encrypt_display(); 24437c478bd9Sstevel@tonic-gate } 24447c478bd9Sstevel@tonic-gate } else { 24457c478bd9Sstevel@tonic-gate (void) printf("No connection.\n"); 24467c478bd9Sstevel@tonic-gate } 24477c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) 24487c478bd9Sstevel@tonic-gate (void) printf("Escape character is '%s'.\n", control(rlogin)); 24497c478bd9Sstevel@tonic-gate else 24507c478bd9Sstevel@tonic-gate (void) printf( 24517c478bd9Sstevel@tonic-gate "Escape character is '%s'.\n", esc_control(escape)); 24527c478bd9Sstevel@tonic-gate (void) fflush(stdout); 24537c478bd9Sstevel@tonic-gate return (1); 24547c478bd9Sstevel@tonic-gate } 24557c478bd9Sstevel@tonic-gate 24567c478bd9Sstevel@tonic-gate /* 24577c478bd9Sstevel@tonic-gate * Parse the user input (cmd_line_input) which should: 24587c478bd9Sstevel@tonic-gate * - start with the target host, or with "@" or "!@" followed by at least one 24597c478bd9Sstevel@tonic-gate * gateway. 24607c478bd9Sstevel@tonic-gate * - each host (can be literal address or hostname) can be separated by ",", 24617c478bd9Sstevel@tonic-gate * "@", or ",@". 24627c478bd9Sstevel@tonic-gate * Note that the last host is the target, all the others (if any ) are the 24637c478bd9Sstevel@tonic-gate * gateways. 24647c478bd9Sstevel@tonic-gate * 24657c478bd9Sstevel@tonic-gate * Returns: -1 if a library call fails, too many gateways, or parse 24667c478bd9Sstevel@tonic-gate * error 24677c478bd9Sstevel@tonic-gate * num_gw otherwise 24687c478bd9Sstevel@tonic-gate * On successful return, hostname_list points to a list of hosts (last one being 24697c478bd9Sstevel@tonic-gate * the target, others gateways), src_rtng_type points to the type of source 24707c478bd9Sstevel@tonic-gate * routing (strict vs. loose) 24717c478bd9Sstevel@tonic-gate */ 24727c478bd9Sstevel@tonic-gate static int 24737c478bd9Sstevel@tonic-gate parse_input(char *cmd_line_input, char **hostname_list, uchar_t *src_rtng_type) 24747c478bd9Sstevel@tonic-gate { 24757c478bd9Sstevel@tonic-gate char hname[MAXHOSTNAMELEN + 1]; 24767c478bd9Sstevel@tonic-gate char *cp; 24777c478bd9Sstevel@tonic-gate int gw_count; 24787c478bd9Sstevel@tonic-gate int i; 24797c478bd9Sstevel@tonic-gate 24807c478bd9Sstevel@tonic-gate gw_count = 0; 24817c478bd9Sstevel@tonic-gate cp = cmd_line_input; 24827c478bd9Sstevel@tonic-gate 24837c478bd9Sstevel@tonic-gate /* 24847c478bd9Sstevel@tonic-gate * Defining ICMD generates the Itelnet binary, the special version of 24857c478bd9Sstevel@tonic-gate * telnet which is used with firewall proxy. 24867c478bd9Sstevel@tonic-gate * If ICMD is defined, parse_input will treat the whole cmd_line_input 24877c478bd9Sstevel@tonic-gate * as the target host and set the num_gw to 0. Therefore, none of the 24887c478bd9Sstevel@tonic-gate * source routing related code paths will be executed. 24897c478bd9Sstevel@tonic-gate */ 24907c478bd9Sstevel@tonic-gate #ifndef ICMD 24917c478bd9Sstevel@tonic-gate if (*cp == '@') { 24927c478bd9Sstevel@tonic-gate *src_rtng_type = IPOPT_LSRR; 24937c478bd9Sstevel@tonic-gate cp++; 24947c478bd9Sstevel@tonic-gate } else if (*cp == '!') { 24957c478bd9Sstevel@tonic-gate *src_rtng_type = IPOPT_SSRR; 24967c478bd9Sstevel@tonic-gate 24977c478bd9Sstevel@tonic-gate /* "!" must be followed by '@' */ 24987c478bd9Sstevel@tonic-gate if (*(cp + 1) != '@') 24997c478bd9Sstevel@tonic-gate goto parse_error; 25007c478bd9Sstevel@tonic-gate cp += 2; 25017c478bd9Sstevel@tonic-gate } else { 25027c478bd9Sstevel@tonic-gate #endif /* ICMD */ 25037c478bd9Sstevel@tonic-gate /* no gateways, just the target */ 25047c478bd9Sstevel@tonic-gate hostname_list[0] = strdup(cp); 25057c478bd9Sstevel@tonic-gate if (hostname_list[0] == NULL) { 25067c478bd9Sstevel@tonic-gate perror("telnet: copying host name"); 25077c478bd9Sstevel@tonic-gate return (-1); 25087c478bd9Sstevel@tonic-gate } 25097c478bd9Sstevel@tonic-gate return (0); 25107c478bd9Sstevel@tonic-gate #ifndef ICMD 25117c478bd9Sstevel@tonic-gate } 25127c478bd9Sstevel@tonic-gate 25137c478bd9Sstevel@tonic-gate while (*cp != '\0') { 25147c478bd9Sstevel@tonic-gate /* 25157c478bd9Sstevel@tonic-gate * Identify each gateway separated by ",", "@" or ",@" and 25167c478bd9Sstevel@tonic-gate * store in hname[]. 25177c478bd9Sstevel@tonic-gate */ 25187c478bd9Sstevel@tonic-gate i = 0; 25197c478bd9Sstevel@tonic-gate while (*cp != '@' && *cp != ',' && *cp != '\0') { 25207c478bd9Sstevel@tonic-gate hname[i++] = *cp++; 25217c478bd9Sstevel@tonic-gate if (i > MAXHOSTNAMELEN) 25227c478bd9Sstevel@tonic-gate goto parse_error; 25237c478bd9Sstevel@tonic-gate } 25247c478bd9Sstevel@tonic-gate hname[i] = '\0'; 25257c478bd9Sstevel@tonic-gate 25267c478bd9Sstevel@tonic-gate /* 25277c478bd9Sstevel@tonic-gate * Two consecutive delimiters which result in a 0 length hname 25287c478bd9Sstevel@tonic-gate * is a parse error. 25297c478bd9Sstevel@tonic-gate */ 25307c478bd9Sstevel@tonic-gate if (i == 0) 25317c478bd9Sstevel@tonic-gate goto parse_error; 25327c478bd9Sstevel@tonic-gate 25337c478bd9Sstevel@tonic-gate hostname_list[gw_count] = strdup(hname); 25347c478bd9Sstevel@tonic-gate if (hostname_list[gw_count] == NULL) { 25357c478bd9Sstevel@tonic-gate perror("telnet: copying hostname from list"); 25367c478bd9Sstevel@tonic-gate return (-1); 25377c478bd9Sstevel@tonic-gate } 25387c478bd9Sstevel@tonic-gate 25397c478bd9Sstevel@tonic-gate if (++gw_count > MAXMAX_GATEWAY) { 25407c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "telnet: too many gateways\n"); 25417c478bd9Sstevel@tonic-gate return (-1); 25427c478bd9Sstevel@tonic-gate } 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate /* Jump over the next delimiter. */ 25457c478bd9Sstevel@tonic-gate if (*cp != '\0') { 25467c478bd9Sstevel@tonic-gate /* ...gw1,@gw2... accepted */ 25477c478bd9Sstevel@tonic-gate if (*cp == ',' && *(cp + 1) == '@') 25487c478bd9Sstevel@tonic-gate cp += 2; 25497c478bd9Sstevel@tonic-gate else 25507c478bd9Sstevel@tonic-gate cp++; 25517c478bd9Sstevel@tonic-gate } 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate 25547c478bd9Sstevel@tonic-gate /* discount the target */ 25557c478bd9Sstevel@tonic-gate gw_count--; 25567c478bd9Sstevel@tonic-gate 25577c478bd9Sstevel@tonic-gate /* Any input starting with '!@' or '@' must have at least one gateway */ 25587c478bd9Sstevel@tonic-gate if (gw_count <= 0) 25597c478bd9Sstevel@tonic-gate goto parse_error; 25607c478bd9Sstevel@tonic-gate 25617c478bd9Sstevel@tonic-gate return (gw_count); 25627c478bd9Sstevel@tonic-gate 25637c478bd9Sstevel@tonic-gate parse_error: 25647c478bd9Sstevel@tonic-gate (void) printf("Bad source route option: %s\n", cmd_line_input); 25657c478bd9Sstevel@tonic-gate return (-1); 25667c478bd9Sstevel@tonic-gate #endif /* ICMD */ 25677c478bd9Sstevel@tonic-gate } 25687c478bd9Sstevel@tonic-gate 25697c478bd9Sstevel@tonic-gate /* 25707c478bd9Sstevel@tonic-gate * Resolves the target and gateway addresses, determines what type of addresses 25717c478bd9Sstevel@tonic-gate * (ALL_ADDRS, ONLY_V6, ONLY_V4) telnet will be trying to connect. 25727c478bd9Sstevel@tonic-gate * 25737c478bd9Sstevel@tonic-gate * Returns: pointer to resolved target if name resolutions succeed 25747c478bd9Sstevel@tonic-gate * NULL if name resolutions fail or 25757c478bd9Sstevel@tonic-gate * a library function call fails 25767c478bd9Sstevel@tonic-gate * 25777c478bd9Sstevel@tonic-gate * The last host in the hostname_list is the target. After resolving the target, 25787c478bd9Sstevel@tonic-gate * determines for what type of addresses it should try to resolve gateways. It 25797c478bd9Sstevel@tonic-gate * resolves gateway addresses and picks one address for each desired address 25807c478bd9Sstevel@tonic-gate * type and stores in the array pointed by gw_addrsp. Also, this 'type of 25817c478bd9Sstevel@tonic-gate * addresses' is pointed by addr_type argument on successful return. 25827c478bd9Sstevel@tonic-gate */ 25837c478bd9Sstevel@tonic-gate static struct addrinfo * 25847c478bd9Sstevel@tonic-gate resolve_hosts(char **hostname_list, int num_gw, struct gateway **gw_addrsp, 25857c478bd9Sstevel@tonic-gate int *addr_type, const char *portp) 25867c478bd9Sstevel@tonic-gate { 25877c478bd9Sstevel@tonic-gate struct gateway *gw_addrs = NULL; 25887c478bd9Sstevel@tonic-gate struct gateway *gw; 25897c478bd9Sstevel@tonic-gate /* whether we already picked an IPv4 address for the current gateway */ 25907c478bd9Sstevel@tonic-gate boolean_t got_v4_addr; 25917c478bd9Sstevel@tonic-gate boolean_t got_v6_addr; 25927c478bd9Sstevel@tonic-gate /* whether we need to get an IPv4 address for the current gateway */ 25937c478bd9Sstevel@tonic-gate boolean_t need_v4_addr = B_FALSE; 25947c478bd9Sstevel@tonic-gate boolean_t need_v6_addr = B_FALSE; 25957c478bd9Sstevel@tonic-gate int res_failed_at4; /* save which gateway failed to resolve */ 25967c478bd9Sstevel@tonic-gate int res_failed_at6; 25977c478bd9Sstevel@tonic-gate boolean_t is_v4mapped; 25987c478bd9Sstevel@tonic-gate struct in6_addr *v6addrp; 25997c478bd9Sstevel@tonic-gate struct in_addr *v4addrp; 26007c478bd9Sstevel@tonic-gate int error_num; 26017c478bd9Sstevel@tonic-gate int i; 26027c478bd9Sstevel@tonic-gate int rc; 26037c478bd9Sstevel@tonic-gate struct addrinfo *res, *host, *gateway, *addr; 26047c478bd9Sstevel@tonic-gate struct addrinfo hints; 26057c478bd9Sstevel@tonic-gate 26067c478bd9Sstevel@tonic-gate *addr_type = ALL_ADDRS; 26077c478bd9Sstevel@tonic-gate 26087c478bd9Sstevel@tonic-gate memset(&hints, 0, sizeof (hints)); 26097c478bd9Sstevel@tonic-gate hints.ai_flags = AI_CANONNAME; /* used for config files, diags */ 26107c478bd9Sstevel@tonic-gate hints.ai_socktype = SOCK_STREAM; 26117c478bd9Sstevel@tonic-gate rc = getaddrinfo(hostname_list[num_gw], 26127c478bd9Sstevel@tonic-gate (portp != NULL) ? portp : "telnet", &hints, &res); 26137c478bd9Sstevel@tonic-gate if (rc != 0) { 26147c478bd9Sstevel@tonic-gate if (hostname_list[num_gw] != NULL && 26157c478bd9Sstevel@tonic-gate *hostname_list[num_gw] != '\0') 26167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", hostname_list[num_gw]); 26177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", gai_strerror(rc)); 26187c478bd9Sstevel@tonic-gate return (NULL); 26197c478bd9Sstevel@tonic-gate } 26207c478bd9Sstevel@tonic-gate 26217c478bd9Sstevel@tonic-gate /* 26227c478bd9Sstevel@tonic-gate * Let's see what type of addresses we got for the target. This 26237c478bd9Sstevel@tonic-gate * determines what type of addresses we'd like to resolve gateways 26247c478bd9Sstevel@tonic-gate * later. 26257c478bd9Sstevel@tonic-gate */ 26267c478bd9Sstevel@tonic-gate for (host = res; host != NULL; host = host->ai_next) { 26277c478bd9Sstevel@tonic-gate struct sockaddr_in6 *s6; 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate s6 = (struct sockaddr_in6 *)host->ai_addr; 26307c478bd9Sstevel@tonic-gate 26317c478bd9Sstevel@tonic-gate if (host->ai_addr->sa_family == AF_INET || 26327c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr)) 26337c478bd9Sstevel@tonic-gate need_v4_addr = B_TRUE; 26347c478bd9Sstevel@tonic-gate else 26357c478bd9Sstevel@tonic-gate need_v6_addr = B_TRUE; 26367c478bd9Sstevel@tonic-gate 26377c478bd9Sstevel@tonic-gate /* 26387c478bd9Sstevel@tonic-gate * Let's stop after seeing we need both IPv6 and IPv4. 26397c478bd9Sstevel@tonic-gate */ 26407c478bd9Sstevel@tonic-gate if (need_v4_addr && need_v6_addr) 26417c478bd9Sstevel@tonic-gate break; 26427c478bd9Sstevel@tonic-gate } 26437c478bd9Sstevel@tonic-gate 26447c478bd9Sstevel@tonic-gate if (num_gw > 0) { 26457c478bd9Sstevel@tonic-gate /* 26467c478bd9Sstevel@tonic-gate * In the prepare_optbuf(), we'll store the IPv4 address of the 26477c478bd9Sstevel@tonic-gate * target in the last slot of gw_addrs array. Therefore we need 26487c478bd9Sstevel@tonic-gate * space for num_gw+1 hosts. 26497c478bd9Sstevel@tonic-gate */ 26507c478bd9Sstevel@tonic-gate gw_addrs = calloc(num_gw + 1, sizeof (struct gateway)); 26517c478bd9Sstevel@tonic-gate if (gw_addrs == NULL) { 26527c478bd9Sstevel@tonic-gate perror("telnet: calloc"); 26537c478bd9Sstevel@tonic-gate freeaddrinfo(res); 26547c478bd9Sstevel@tonic-gate return (NULL); 26557c478bd9Sstevel@tonic-gate } 26567c478bd9Sstevel@tonic-gate } 26577c478bd9Sstevel@tonic-gate 26587c478bd9Sstevel@tonic-gate /* 26597c478bd9Sstevel@tonic-gate * Now we'll go through all the gateways and try to resolve them to 26607c478bd9Sstevel@tonic-gate * the desired address types. 26617c478bd9Sstevel@tonic-gate */ 26627c478bd9Sstevel@tonic-gate gw = gw_addrs; 26637c478bd9Sstevel@tonic-gate 26647c478bd9Sstevel@tonic-gate /* -1 means 'no address resolution failure yet' */ 26657c478bd9Sstevel@tonic-gate res_failed_at4 = -1; 26667c478bd9Sstevel@tonic-gate res_failed_at6 = -1; 26677c478bd9Sstevel@tonic-gate for (i = 0; i < num_gw; i++) { 26687c478bd9Sstevel@tonic-gate rc = getaddrinfo(hostname_list[i], NULL, NULL, &gateway); 26697c478bd9Sstevel@tonic-gate if (rc != 0) { 26707c478bd9Sstevel@tonic-gate if (hostname_list[i] != NULL && 26717c478bd9Sstevel@tonic-gate *hostname_list[i] != '\0') 26727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", 26737c478bd9Sstevel@tonic-gate hostname_list[i]); 26747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "bad address\n"); 26757c478bd9Sstevel@tonic-gate return (NULL); 26767c478bd9Sstevel@tonic-gate } 26777c478bd9Sstevel@tonic-gate 26787c478bd9Sstevel@tonic-gate /* 26797c478bd9Sstevel@tonic-gate * Initially we have no address of any type for this gateway. 26807c478bd9Sstevel@tonic-gate */ 26817c478bd9Sstevel@tonic-gate got_v6_addr = B_FALSE; 26827c478bd9Sstevel@tonic-gate got_v4_addr = B_FALSE; 26837c478bd9Sstevel@tonic-gate 26847c478bd9Sstevel@tonic-gate /* 26857c478bd9Sstevel@tonic-gate * Let's go through all the addresses of this gateway. 26867c478bd9Sstevel@tonic-gate * Use the first address which matches the needed family. 26877c478bd9Sstevel@tonic-gate */ 26887c478bd9Sstevel@tonic-gate for (addr = gateway; addr != NULL; addr = addr->ai_next) { 26897c478bd9Sstevel@tonic-gate /*LINTED*/ 26907c478bd9Sstevel@tonic-gate v6addrp = &((struct sockaddr_in6 *)addr->ai_addr)-> 26917c478bd9Sstevel@tonic-gate sin6_addr; 26927c478bd9Sstevel@tonic-gate v4addrp = &((struct sockaddr_in *)addr->ai_addr)-> 26937c478bd9Sstevel@tonic-gate sin_addr; 26947c478bd9Sstevel@tonic-gate 26957c478bd9Sstevel@tonic-gate if (addr->ai_family == AF_INET6) 26967c478bd9Sstevel@tonic-gate is_v4mapped = IN6_IS_ADDR_V4MAPPED(v6addrp); 26977c478bd9Sstevel@tonic-gate else 26987c478bd9Sstevel@tonic-gate is_v4mapped = B_FALSE; 26997c478bd9Sstevel@tonic-gate 27007c478bd9Sstevel@tonic-gate /* 27017c478bd9Sstevel@tonic-gate * If we need to determine an IPv4 address and haven't 27027c478bd9Sstevel@tonic-gate * found one yet and this is a IPv4-mapped IPv6 address, 27037c478bd9Sstevel@tonic-gate * then bingo! 27047c478bd9Sstevel@tonic-gate */ 27057c478bd9Sstevel@tonic-gate if (need_v4_addr && !got_v4_addr) { 27067c478bd9Sstevel@tonic-gate if (is_v4mapped) { 27077c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(v6addrp, 27087c478bd9Sstevel@tonic-gate &gw->gw_addr); 27097c478bd9Sstevel@tonic-gate got_v4_addr = B_TRUE; 27107c478bd9Sstevel@tonic-gate } else if (addr->ai_family = AF_INET) { 27117c478bd9Sstevel@tonic-gate gw->gw_addr = *v4addrp; 27127c478bd9Sstevel@tonic-gate got_v4_addr = B_TRUE; 27137c478bd9Sstevel@tonic-gate } 27147c478bd9Sstevel@tonic-gate } 27157c478bd9Sstevel@tonic-gate 27167c478bd9Sstevel@tonic-gate if (need_v6_addr && !got_v6_addr && 27177c478bd9Sstevel@tonic-gate addr->ai_family == AF_INET6) { 27187c478bd9Sstevel@tonic-gate gw->gw_addr6 = *v6addrp; 27197c478bd9Sstevel@tonic-gate got_v6_addr = B_TRUE; 27207c478bd9Sstevel@tonic-gate } 27217c478bd9Sstevel@tonic-gate 27227c478bd9Sstevel@tonic-gate /* 27237c478bd9Sstevel@tonic-gate * Let's stop if we got all what we looked for. 27247c478bd9Sstevel@tonic-gate */ 27257c478bd9Sstevel@tonic-gate if ((!need_v4_addr || got_v4_addr) && 27267c478bd9Sstevel@tonic-gate (!need_v6_addr || got_v6_addr)) 27277c478bd9Sstevel@tonic-gate break; 27287c478bd9Sstevel@tonic-gate } 27297c478bd9Sstevel@tonic-gate 27307c478bd9Sstevel@tonic-gate /* 27317c478bd9Sstevel@tonic-gate * We needed an IPv4 address for this gateway but couldn't 27327c478bd9Sstevel@tonic-gate * find one. 27337c478bd9Sstevel@tonic-gate */ 27347c478bd9Sstevel@tonic-gate if (need_v4_addr && !got_v4_addr) { 27357c478bd9Sstevel@tonic-gate res_failed_at4 = i; 27367c478bd9Sstevel@tonic-gate /* 27377c478bd9Sstevel@tonic-gate * Since we couldn't resolve a gateway to IPv4 address 27387c478bd9Sstevel@tonic-gate * we can't use IPv4 at all. Therefore we no longer 27397c478bd9Sstevel@tonic-gate * need IPv4 addresses for any of the gateways. 27407c478bd9Sstevel@tonic-gate */ 27417c478bd9Sstevel@tonic-gate need_v4_addr = B_FALSE; 27427c478bd9Sstevel@tonic-gate } 27437c478bd9Sstevel@tonic-gate 27447c478bd9Sstevel@tonic-gate if (need_v6_addr && !got_v6_addr) { 27457c478bd9Sstevel@tonic-gate res_failed_at6 = i; 27467c478bd9Sstevel@tonic-gate need_v6_addr = B_FALSE; 27477c478bd9Sstevel@tonic-gate } 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate /* 27507c478bd9Sstevel@tonic-gate * If some gateways don't resolve to any of the desired 27517c478bd9Sstevel@tonic-gate * address types, we fail. 27527c478bd9Sstevel@tonic-gate */ 27537c478bd9Sstevel@tonic-gate if (!need_v4_addr && !need_v6_addr) { 27547c478bd9Sstevel@tonic-gate if (res_failed_at6 != -1) { 27557c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 27567c478bd9Sstevel@tonic-gate "%s: Host doesn't have any IPv6 address\n", 27577c478bd9Sstevel@tonic-gate hostname_list[res_failed_at6]); 27587c478bd9Sstevel@tonic-gate } 27597c478bd9Sstevel@tonic-gate if (res_failed_at4 != -1) { 27607c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 27617c478bd9Sstevel@tonic-gate "%s: Host doesn't have any IPv4 address\n", 27627c478bd9Sstevel@tonic-gate hostname_list[res_failed_at4]); 27637c478bd9Sstevel@tonic-gate } 27647c478bd9Sstevel@tonic-gate free(gw_addrs); 27657c478bd9Sstevel@tonic-gate return (NULL); 27667c478bd9Sstevel@tonic-gate } 27677c478bd9Sstevel@tonic-gate 27687c478bd9Sstevel@tonic-gate gw++; 27697c478bd9Sstevel@tonic-gate } 27707c478bd9Sstevel@tonic-gate 27717c478bd9Sstevel@tonic-gate *gw_addrsp = gw_addrs; 27727c478bd9Sstevel@tonic-gate 27737c478bd9Sstevel@tonic-gate /* 27747c478bd9Sstevel@tonic-gate * When we get here, need_v4_addr and need_v6_addr have their final 27757c478bd9Sstevel@tonic-gate * values based on the name resolution of the target and gateways. 27767c478bd9Sstevel@tonic-gate */ 27777c478bd9Sstevel@tonic-gate if (need_v4_addr && need_v6_addr) 27787c478bd9Sstevel@tonic-gate *addr_type = ALL_ADDRS; 27797c478bd9Sstevel@tonic-gate else if (need_v4_addr && !need_v6_addr) 27807c478bd9Sstevel@tonic-gate *addr_type = ONLY_V4; 27817c478bd9Sstevel@tonic-gate else if (!need_v4_addr && need_v6_addr) 27827c478bd9Sstevel@tonic-gate *addr_type = ONLY_V6; 27837c478bd9Sstevel@tonic-gate 27847c478bd9Sstevel@tonic-gate return (res); 27857c478bd9Sstevel@tonic-gate } 27867c478bd9Sstevel@tonic-gate 27877c478bd9Sstevel@tonic-gate 27887c478bd9Sstevel@tonic-gate /* 27897c478bd9Sstevel@tonic-gate * Initializes the buffer pointed by opt_bufpp for a IPv4 option of type 27907c478bd9Sstevel@tonic-gate * src_rtng_type using the gateway addresses stored in gw_addrs. If no buffer 27917c478bd9Sstevel@tonic-gate * is passed, it allocates one. If a buffer is passed, checks if it's big 27927c478bd9Sstevel@tonic-gate * enough. 27937c478bd9Sstevel@tonic-gate * On return opt_buf_len points to the buffer length which we need later for the 27947c478bd9Sstevel@tonic-gate * setsockopt() call, and opt_bufpp points to the newly allocated or already 27957c478bd9Sstevel@tonic-gate * passed buffer. Returns B_FALSE if a library function call fails or passed 27967c478bd9Sstevel@tonic-gate * buffer is not big enough, B_TRUE otherwise. 27977c478bd9Sstevel@tonic-gate */ 27987c478bd9Sstevel@tonic-gate static boolean_t 27997c478bd9Sstevel@tonic-gate prepare_optbuf(struct gateway *gw_addrs, int num_gw, char **opt_bufpp, 28007c478bd9Sstevel@tonic-gate size_t *opt_buf_len, struct in_addr *target, uchar_t src_rtng_type) 28017c478bd9Sstevel@tonic-gate { 28027c478bd9Sstevel@tonic-gate struct ip_sourceroute *sr_opt; 28037c478bd9Sstevel@tonic-gate size_t needed_buflen; 28047c478bd9Sstevel@tonic-gate int i; 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate /* 28077c478bd9Sstevel@tonic-gate * We have (num_gw + 1) IP addresses in the buffer because the number 28087c478bd9Sstevel@tonic-gate * of gateway addresses we put in the option buffer includes the target 28097c478bd9Sstevel@tonic-gate * address. 28107c478bd9Sstevel@tonic-gate * At the time of setsockopt() call, passed option length needs to be 28117c478bd9Sstevel@tonic-gate * multiple of 4 bytes. Therefore we need one IPOPT_NOP before (or 28127c478bd9Sstevel@tonic-gate * after) IPOPT_LSRR. 28137c478bd9Sstevel@tonic-gate * 1 = preceding 1 byte of IPOPT_NOP 28147c478bd9Sstevel@tonic-gate * 3 = 1 (code) + 1 (len) + 1 (ptr) 28157c478bd9Sstevel@tonic-gate */ 28167c478bd9Sstevel@tonic-gate needed_buflen = 1 + 3 + (num_gw + 1) * sizeof (struct in_addr); 28177c478bd9Sstevel@tonic-gate 28187c478bd9Sstevel@tonic-gate if (*opt_bufpp != NULL) { 28197c478bd9Sstevel@tonic-gate /* check if the passed buffer is big enough */ 28207c478bd9Sstevel@tonic-gate if (*opt_buf_len < needed_buflen) { 28217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 28227c478bd9Sstevel@tonic-gate "telnet: buffer too small for IPv4 source routing " 28237c478bd9Sstevel@tonic-gate "option\n"); 28247c478bd9Sstevel@tonic-gate return (B_FALSE); 28257c478bd9Sstevel@tonic-gate } 28267c478bd9Sstevel@tonic-gate } else { 28277c478bd9Sstevel@tonic-gate *opt_bufpp = malloc(needed_buflen); 28287c478bd9Sstevel@tonic-gate if (*opt_bufpp == NULL) { 28297c478bd9Sstevel@tonic-gate perror("telnet: malloc"); 28307c478bd9Sstevel@tonic-gate return (B_FALSE); 28317c478bd9Sstevel@tonic-gate } 28327c478bd9Sstevel@tonic-gate } 28337c478bd9Sstevel@tonic-gate 28347c478bd9Sstevel@tonic-gate *opt_buf_len = needed_buflen; 28357c478bd9Sstevel@tonic-gate 28367c478bd9Sstevel@tonic-gate /* final hop is the target */ 28377c478bd9Sstevel@tonic-gate gw_addrs[num_gw].gw_addr = *target; 28387c478bd9Sstevel@tonic-gate 28397c478bd9Sstevel@tonic-gate *opt_bufpp[0] = IPOPT_NOP; 28407c478bd9Sstevel@tonic-gate /* IPOPT_LSRR starts right after IPOPT_NOP */ 28417c478bd9Sstevel@tonic-gate sr_opt = (struct ip_sourceroute *)(*opt_bufpp + 1); 28427c478bd9Sstevel@tonic-gate sr_opt->ipsr_code = src_rtng_type; 28437c478bd9Sstevel@tonic-gate /* discount the 1 byte of IPOPT_NOP */ 28447c478bd9Sstevel@tonic-gate sr_opt->ipsr_len = needed_buflen - 1; 28457c478bd9Sstevel@tonic-gate sr_opt->ipsr_ptr = IPOPT_MINOFF; 28467c478bd9Sstevel@tonic-gate 28477c478bd9Sstevel@tonic-gate /* copy the gateways into the optlist */ 28487c478bd9Sstevel@tonic-gate for (i = 0; i < num_gw + 1; i++) { 28497c478bd9Sstevel@tonic-gate (void) bcopy(&gw_addrs[i].gw_addr, &sr_opt->ipsr_addrs[i], 28507c478bd9Sstevel@tonic-gate sizeof (struct in_addr)); 28517c478bd9Sstevel@tonic-gate } 28527c478bd9Sstevel@tonic-gate 28537c478bd9Sstevel@tonic-gate return (B_TRUE); 28547c478bd9Sstevel@tonic-gate } 28557c478bd9Sstevel@tonic-gate 28567c478bd9Sstevel@tonic-gate /* 28577c478bd9Sstevel@tonic-gate * Initializes the buffer pointed by opt_bufpp for a IPv6 routing header option 28587c478bd9Sstevel@tonic-gate * using the gateway addresses stored in gw_addrs. If no buffer is passed, it 28597c478bd9Sstevel@tonic-gate * allocates one. If a buffer is passed, checks if it's big enough. 28607c478bd9Sstevel@tonic-gate * On return opt_buf_len points to the buffer length which we need later for the 28617c478bd9Sstevel@tonic-gate * setsockopt() call, and opt_bufpp points to the newly allocated or already 28627c478bd9Sstevel@tonic-gate * passed buffer. Returns B_FALSE if a library function call fails or passed 28637c478bd9Sstevel@tonic-gate * buffer is not big enough, B_TRUE otherwise. 28647c478bd9Sstevel@tonic-gate */ 28657c478bd9Sstevel@tonic-gate static boolean_t 28667c478bd9Sstevel@tonic-gate prepare_optbuf6(struct gateway *gw_addrs, int num_gw, char **opt_bufpp, 28677c478bd9Sstevel@tonic-gate size_t *opt_buf_len) 28687c478bd9Sstevel@tonic-gate { 28697c478bd9Sstevel@tonic-gate char *opt_bufp; 28707c478bd9Sstevel@tonic-gate size_t needed_buflen; 28717c478bd9Sstevel@tonic-gate int i; 28727c478bd9Sstevel@tonic-gate 28737c478bd9Sstevel@tonic-gate needed_buflen = inet6_rth_space(IPV6_RTHDR_TYPE_0, num_gw); 28747c478bd9Sstevel@tonic-gate 28757c478bd9Sstevel@tonic-gate if (*opt_bufpp != NULL) { 28767c478bd9Sstevel@tonic-gate /* check if the passed buffer is big enough */ 28777c478bd9Sstevel@tonic-gate if (*opt_buf_len < needed_buflen) { 28787c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 28797c478bd9Sstevel@tonic-gate "telnet: buffer too small for IPv6 routing " 28807c478bd9Sstevel@tonic-gate "header option\n"); 28817c478bd9Sstevel@tonic-gate return (B_FALSE); 28827c478bd9Sstevel@tonic-gate } 28837c478bd9Sstevel@tonic-gate } else { 28847c478bd9Sstevel@tonic-gate *opt_bufpp = malloc(needed_buflen); 28857c478bd9Sstevel@tonic-gate if (*opt_bufpp == NULL) { 28867c478bd9Sstevel@tonic-gate perror("telnet: malloc"); 28877c478bd9Sstevel@tonic-gate return (B_FALSE); 28887c478bd9Sstevel@tonic-gate } 28897c478bd9Sstevel@tonic-gate } 28907c478bd9Sstevel@tonic-gate *opt_buf_len = needed_buflen; 28917c478bd9Sstevel@tonic-gate opt_bufp = *opt_bufpp; 28927c478bd9Sstevel@tonic-gate 28937c478bd9Sstevel@tonic-gate /* 28947c478bd9Sstevel@tonic-gate * Initialize the buffer to be used for IPv6 routing header type 0. 28957c478bd9Sstevel@tonic-gate */ 28967c478bd9Sstevel@tonic-gate if (inet6_rth_init(opt_bufp, needed_buflen, IPV6_RTHDR_TYPE_0, 28977c478bd9Sstevel@tonic-gate num_gw) == NULL) { 28987c478bd9Sstevel@tonic-gate perror("telnet: inet6_rth_init"); 28997c478bd9Sstevel@tonic-gate return (B_FALSE); 29007c478bd9Sstevel@tonic-gate } 29017c478bd9Sstevel@tonic-gate 29027c478bd9Sstevel@tonic-gate /* 29037c478bd9Sstevel@tonic-gate * Add gateways one by one. 29047c478bd9Sstevel@tonic-gate */ 29057c478bd9Sstevel@tonic-gate for (i = 0; i < num_gw; i++) { 29067c478bd9Sstevel@tonic-gate if (inet6_rth_add(opt_bufp, &gw_addrs[i].gw_addr6) == -1) { 29077c478bd9Sstevel@tonic-gate perror("telnet: inet6_rth_add"); 29087c478bd9Sstevel@tonic-gate return (B_FALSE); 29097c478bd9Sstevel@tonic-gate } 29107c478bd9Sstevel@tonic-gate } 29117c478bd9Sstevel@tonic-gate 29127c478bd9Sstevel@tonic-gate /* successful operation */ 29137c478bd9Sstevel@tonic-gate return (B_TRUE); 29147c478bd9Sstevel@tonic-gate } 29157c478bd9Sstevel@tonic-gate 29167c478bd9Sstevel@tonic-gate int 29177c478bd9Sstevel@tonic-gate tn(argc, argv) 29187c478bd9Sstevel@tonic-gate int argc; 29197c478bd9Sstevel@tonic-gate char *argv[]; 29207c478bd9Sstevel@tonic-gate { 29217c478bd9Sstevel@tonic-gate struct addrinfo *host = NULL; 29227c478bd9Sstevel@tonic-gate struct addrinfo *h; 29237c478bd9Sstevel@tonic-gate struct sockaddr_in6 sin6; 29247c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 29257c478bd9Sstevel@tonic-gate struct in6_addr addr6; 29267c478bd9Sstevel@tonic-gate struct in_addr addr; 29277c478bd9Sstevel@tonic-gate void *addrp; 29287c478bd9Sstevel@tonic-gate struct gateway *gw_addrs; 29297c478bd9Sstevel@tonic-gate char *hostname_list[MAXMAX_GATEWAY + 1] = {NULL}; 29307c478bd9Sstevel@tonic-gate char *opt_buf6 = NULL; /* used for IPv6 routing header */ 29317c478bd9Sstevel@tonic-gate size_t opt_buf_len6 = 0; 29327c478bd9Sstevel@tonic-gate uchar_t src_rtng_type; /* type of IPv4 source routing */ 29337c478bd9Sstevel@tonic-gate struct servent *sp = 0; 29347c478bd9Sstevel@tonic-gate char *opt_buf = NULL; /* used for IPv4 source routing */ 29357c478bd9Sstevel@tonic-gate size_t opt_buf_len = 0; 29367c478bd9Sstevel@tonic-gate char *cmd; 29377c478bd9Sstevel@tonic-gate char *hostp = NULL; 29387c478bd9Sstevel@tonic-gate char *portp = NULL; 29397c478bd9Sstevel@tonic-gate char *user = NULL; 29407c478bd9Sstevel@tonic-gate #ifdef ICMD 29417c478bd9Sstevel@tonic-gate char *itelnet_host; 29427c478bd9Sstevel@tonic-gate char *real_host; 29437c478bd9Sstevel@tonic-gate unsigned short dest_port; 29447c478bd9Sstevel@tonic-gate #endif /* ICMD */ 29457c478bd9Sstevel@tonic-gate /* 29467c478bd9Sstevel@tonic-gate * The two strings at the end of this function are 24 and 39 29477c478bd9Sstevel@tonic-gate * characters long (minus the %.*s in the format strings). Add 29487c478bd9Sstevel@tonic-gate * one for the null terminator making the longest print string 40. 29497c478bd9Sstevel@tonic-gate */ 29507c478bd9Sstevel@tonic-gate char buf[MAXHOSTNAMELEN+40]; 29517c478bd9Sstevel@tonic-gate /* 29527c478bd9Sstevel@tonic-gate * In the case of ICMD defined, dest_port will contain the real port 29537c478bd9Sstevel@tonic-gate * we are trying to telnet to, and target_port will contain 29547c478bd9Sstevel@tonic-gate * "telnet-passthru" port. 29557c478bd9Sstevel@tonic-gate */ 29567c478bd9Sstevel@tonic-gate unsigned short target_port; 29577c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 29587c478bd9Sstevel@tonic-gate int num_gw; 29597c478bd9Sstevel@tonic-gate int ret_val; 29607c478bd9Sstevel@tonic-gate boolean_t is_v4mapped; 29617c478bd9Sstevel@tonic-gate /* 29627c478bd9Sstevel@tonic-gate * Type of addresses we'll try to connect to (ALL_ADDRS, ONLY_V6, 29637c478bd9Sstevel@tonic-gate * ONLY_V4). 29647c478bd9Sstevel@tonic-gate */ 29657c478bd9Sstevel@tonic-gate int addr_type; 29667c478bd9Sstevel@tonic-gate 29677c478bd9Sstevel@tonic-gate /* clear the socket address prior to use */ 29687c478bd9Sstevel@tonic-gate (void) memset(&sin6, '\0', sizeof (sin6)); 29697c478bd9Sstevel@tonic-gate sin6.sin6_family = AF_INET6; 29707c478bd9Sstevel@tonic-gate 29717c478bd9Sstevel@tonic-gate (void) memset(&sin, '\0', sizeof (sin)); 29727c478bd9Sstevel@tonic-gate sin.sin_family = AF_INET; 29737c478bd9Sstevel@tonic-gate 29747c478bd9Sstevel@tonic-gate if (connected) { 29757c478bd9Sstevel@tonic-gate (void) printf("?Already connected to %s\n", hostname); 29767c478bd9Sstevel@tonic-gate return (0); 29777c478bd9Sstevel@tonic-gate } 29787c478bd9Sstevel@tonic-gate #ifdef ICMD 29797c478bd9Sstevel@tonic-gate itelnet_host = getenv("INTERNET_HOST"); 29807c478bd9Sstevel@tonic-gate if (itelnet_host == NULL || itelnet_host[0] == '\0') { 29817c478bd9Sstevel@tonic-gate (void) printf("INTERNET_HOST environment variable undefined\n"); 29827c478bd9Sstevel@tonic-gate goto tn_exit; 29837c478bd9Sstevel@tonic-gate } 29847c478bd9Sstevel@tonic-gate #endif 29857c478bd9Sstevel@tonic-gate if (argc < 2) { 29867c478bd9Sstevel@tonic-gate (void) printf("(to) "); 29877c478bd9Sstevel@tonic-gate if (GetAndAppendString(&line, &linesize, "open ", 29887c478bd9Sstevel@tonic-gate stdin) == NULL) { 29897c478bd9Sstevel@tonic-gate if (!feof(stdin)) { 29907c478bd9Sstevel@tonic-gate perror("telnet"); 29917c478bd9Sstevel@tonic-gate goto tn_exit; 29927c478bd9Sstevel@tonic-gate } 29937c478bd9Sstevel@tonic-gate } 29947c478bd9Sstevel@tonic-gate makeargv(); 29957c478bd9Sstevel@tonic-gate argc = margc; 29967c478bd9Sstevel@tonic-gate argv = margv; 29977c478bd9Sstevel@tonic-gate } 29987c478bd9Sstevel@tonic-gate cmd = *argv; 29997c478bd9Sstevel@tonic-gate --argc; ++argv; 30007c478bd9Sstevel@tonic-gate while (argc) { 30017c478bd9Sstevel@tonic-gate if (isprefix(*argv, "help") == 4 || isprefix(*argv, "?") == 1) 30027c478bd9Sstevel@tonic-gate goto usage; 30037c478bd9Sstevel@tonic-gate if (strcmp(*argv, "-l") == 0) { 30047c478bd9Sstevel@tonic-gate --argc; ++argv; 30057c478bd9Sstevel@tonic-gate if (argc == 0) 30067c478bd9Sstevel@tonic-gate goto usage; 30077c478bd9Sstevel@tonic-gate user = *argv++; 30087c478bd9Sstevel@tonic-gate --argc; 30097c478bd9Sstevel@tonic-gate continue; 30107c478bd9Sstevel@tonic-gate } 30117c478bd9Sstevel@tonic-gate if (strcmp(*argv, "-a") == 0) { 30127c478bd9Sstevel@tonic-gate --argc; ++argv; 30137c478bd9Sstevel@tonic-gate autologin = autologin_set = 1; 30147c478bd9Sstevel@tonic-gate continue; 30157c478bd9Sstevel@tonic-gate } 30167c478bd9Sstevel@tonic-gate if (hostp == 0) { 30177c478bd9Sstevel@tonic-gate hostp = *argv++; 30187c478bd9Sstevel@tonic-gate --argc; 30197c478bd9Sstevel@tonic-gate continue; 30207c478bd9Sstevel@tonic-gate } 30217c478bd9Sstevel@tonic-gate if (portp == 0) { 30227c478bd9Sstevel@tonic-gate portp = *argv++; 30237c478bd9Sstevel@tonic-gate --argc; 30247c478bd9Sstevel@tonic-gate /* 30257c478bd9Sstevel@tonic-gate * Do we treat this like a telnet port or raw? 30267c478bd9Sstevel@tonic-gate */ 30277c478bd9Sstevel@tonic-gate if (*portp == '-') { 30287c478bd9Sstevel@tonic-gate portp++; 30297c478bd9Sstevel@tonic-gate telnetport = 1; 30307c478bd9Sstevel@tonic-gate } else 30317c478bd9Sstevel@tonic-gate telnetport = 0; 30327c478bd9Sstevel@tonic-gate continue; 30337c478bd9Sstevel@tonic-gate } 30347c478bd9Sstevel@tonic-gate usage: 30357c478bd9Sstevel@tonic-gate (void) printf( 30367c478bd9Sstevel@tonic-gate "usage: %s [-l user] [-a] host-name [port]\n", cmd); 30377c478bd9Sstevel@tonic-gate goto tn_exit; 30387c478bd9Sstevel@tonic-gate } 30397c478bd9Sstevel@tonic-gate if (hostp == 0) 30407c478bd9Sstevel@tonic-gate goto usage; 30417c478bd9Sstevel@tonic-gate 30427c478bd9Sstevel@tonic-gate #ifdef ICMD 30437c478bd9Sstevel@tonic-gate /* 30447c478bd9Sstevel@tonic-gate * For setup phase treat the relay host as the target host. 30457c478bd9Sstevel@tonic-gate */ 30467c478bd9Sstevel@tonic-gate real_host = hostp; 30477c478bd9Sstevel@tonic-gate hostp = itelnet_host; 30487c478bd9Sstevel@tonic-gate #endif 30497c478bd9Sstevel@tonic-gate num_gw = parse_input(hostp, hostname_list, &src_rtng_type); 30507c478bd9Sstevel@tonic-gate if (num_gw < 0) { 30517c478bd9Sstevel@tonic-gate goto tn_exit; 30527c478bd9Sstevel@tonic-gate } 30537c478bd9Sstevel@tonic-gate 30547c478bd9Sstevel@tonic-gate /* Last host in the hostname_list is the target */ 30557c478bd9Sstevel@tonic-gate hostp = hostname_list[num_gw]; 30567c478bd9Sstevel@tonic-gate 30577c478bd9Sstevel@tonic-gate host = resolve_hosts(hostname_list, num_gw, &gw_addrs, &addr_type, 30587c478bd9Sstevel@tonic-gate portp); 30597c478bd9Sstevel@tonic-gate if (host == NULL) { 30607c478bd9Sstevel@tonic-gate goto tn_exit; 30617c478bd9Sstevel@tonic-gate } 30627c478bd9Sstevel@tonic-gate 30637c478bd9Sstevel@tonic-gate /* 30647c478bd9Sstevel@tonic-gate * Check if number of gateways is less than max. available 30657c478bd9Sstevel@tonic-gate */ 30667c478bd9Sstevel@tonic-gate if ((addr_type == ALL_ADDRS || addr_type == ONLY_V6) && 30677c478bd9Sstevel@tonic-gate num_gw > MAX_GATEWAY6) { 30687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "telnet: too many IPv6 gateways\n"); 30697c478bd9Sstevel@tonic-gate goto tn_exit; 30707c478bd9Sstevel@tonic-gate } 30717c478bd9Sstevel@tonic-gate 30727c478bd9Sstevel@tonic-gate if ((addr_type == ALL_ADDRS || addr_type == ONLY_V4) && 30737c478bd9Sstevel@tonic-gate num_gw > MAX_GATEWAY) { 30747c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "telnet: too many IPv4 gateways\n"); 30757c478bd9Sstevel@tonic-gate goto tn_exit; 30767c478bd9Sstevel@tonic-gate } 30777c478bd9Sstevel@tonic-gate 30787c478bd9Sstevel@tonic-gate /* 30797c478bd9Sstevel@tonic-gate * If we pass a literal IPv4 address to getaddrinfo(), in the 30807c478bd9Sstevel@tonic-gate * returned addrinfo structure, hostname is the IPv4-mapped IPv6 30817c478bd9Sstevel@tonic-gate * address string. We prefer to preserve the literal IPv4 address 30827c478bd9Sstevel@tonic-gate * string as the hostname. Also, if the hostname entered by the 30837c478bd9Sstevel@tonic-gate * user is IPv4-mapped IPv6 address, we'll downgrade it to IPv4 30847c478bd9Sstevel@tonic-gate * address. 30857c478bd9Sstevel@tonic-gate */ 30867c478bd9Sstevel@tonic-gate if (inet_addr(hostp) != (in_addr_t)-1) { 30877c478bd9Sstevel@tonic-gate /* this is a literal IPv4 address */ 30887c478bd9Sstevel@tonic-gate (void) strlcpy(_hostname, hostp, sizeof (_hostname)); 30897c478bd9Sstevel@tonic-gate } else if ((inet_pton(AF_INET6, hostp, &addr6) > 0) && 30907c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr6)) { 30917c478bd9Sstevel@tonic-gate /* this is a IPv4-mapped IPv6 address */ 30927c478bd9Sstevel@tonic-gate IN6_V4MAPPED_TO_INADDR(&addr6, &addr); 30937c478bd9Sstevel@tonic-gate (void) inet_ntop(AF_INET, &addr, _hostname, sizeof (_hostname)); 30947c478bd9Sstevel@tonic-gate } else { 30957c478bd9Sstevel@tonic-gate (void) strlcpy(_hostname, host->ai_canonname, 30967c478bd9Sstevel@tonic-gate sizeof (_hostname)); 30977c478bd9Sstevel@tonic-gate } 30987c478bd9Sstevel@tonic-gate hostname = _hostname; 30997c478bd9Sstevel@tonic-gate 31007c478bd9Sstevel@tonic-gate if (portp == NULL) { 31017c478bd9Sstevel@tonic-gate telnetport = 1; 31027c478bd9Sstevel@tonic-gate } 31037c478bd9Sstevel@tonic-gate 31047c478bd9Sstevel@tonic-gate if (host->ai_family == AF_INET) { 31057c478bd9Sstevel@tonic-gate target_port = ((struct sockaddr_in *)(host->ai_addr))->sin_port; 31067c478bd9Sstevel@tonic-gate } else { 31077c478bd9Sstevel@tonic-gate target_port = ((struct sockaddr_in6 *)(host->ai_addr)) 31087c478bd9Sstevel@tonic-gate ->sin6_port; 31097c478bd9Sstevel@tonic-gate } 31107c478bd9Sstevel@tonic-gate 31117c478bd9Sstevel@tonic-gate #ifdef ICMD 31127c478bd9Sstevel@tonic-gate /* 31137c478bd9Sstevel@tonic-gate * Since we pass the port number as an ascii string to the proxy, 31147c478bd9Sstevel@tonic-gate * we need it in host format. 31157c478bd9Sstevel@tonic-gate */ 31167c478bd9Sstevel@tonic-gate dest_port = ntohs(target_port); 31177c478bd9Sstevel@tonic-gate sp = getservbyname("telnet-passthru", "tcp"); 31187c478bd9Sstevel@tonic-gate if (sp == 0) { 31197c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 31207c478bd9Sstevel@tonic-gate "telnet: tcp/telnet-passthru: unknown service\n"); 31217c478bd9Sstevel@tonic-gate goto tn_exit; 31227c478bd9Sstevel@tonic-gate } 31237c478bd9Sstevel@tonic-gate target_port = sp->s_port; 31247c478bd9Sstevel@tonic-gate #endif 31257c478bd9Sstevel@tonic-gate h = host; 31267c478bd9Sstevel@tonic-gate 31277c478bd9Sstevel@tonic-gate /* 31287c478bd9Sstevel@tonic-gate * For IPv6 source routing, we need to initialize option buffer only 31297c478bd9Sstevel@tonic-gate * once. 31307c478bd9Sstevel@tonic-gate */ 31317c478bd9Sstevel@tonic-gate if (num_gw > 0 && (addr_type == ALL_ADDRS || addr_type == ONLY_V6)) { 31327c478bd9Sstevel@tonic-gate if (!prepare_optbuf6(gw_addrs, num_gw, &opt_buf6, 31337c478bd9Sstevel@tonic-gate &opt_buf_len6)) { 31347c478bd9Sstevel@tonic-gate goto tn_exit; 31357c478bd9Sstevel@tonic-gate } 31367c478bd9Sstevel@tonic-gate } 31377c478bd9Sstevel@tonic-gate 31387c478bd9Sstevel@tonic-gate /* 31397c478bd9Sstevel@tonic-gate * We procure the Kerberos config files options only 31407c478bd9Sstevel@tonic-gate * if the user has choosen Krb5 authentication. 31417c478bd9Sstevel@tonic-gate */ 31427c478bd9Sstevel@tonic-gate if (krb5auth_flag > 0) { 31437c478bd9Sstevel@tonic-gate krb5_profile_get_options(hostname, telnet_krb5_realm, 31447c478bd9Sstevel@tonic-gate config_file_options); 31457c478bd9Sstevel@tonic-gate } 31467c478bd9Sstevel@tonic-gate 31477c478bd9Sstevel@tonic-gate if (encrypt_flag) { 31487c478bd9Sstevel@tonic-gate extern boolean_t auth_enable_encrypt; 31497c478bd9Sstevel@tonic-gate if (krb5_privacy_allowed()) { 31507c478bd9Sstevel@tonic-gate encrypt_auto(1); 31517c478bd9Sstevel@tonic-gate decrypt_auto(1); 31527c478bd9Sstevel@tonic-gate wantencryption = B_TRUE; 31537c478bd9Sstevel@tonic-gate autologin = 1; 31547c478bd9Sstevel@tonic-gate auth_enable_encrypt = B_TRUE; 31557c478bd9Sstevel@tonic-gate } else { 31567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 31577c478bd9Sstevel@tonic-gate "%s:Encryption not supported.\n"), prompt); 31587c478bd9Sstevel@tonic-gate exit(1); 31597c478bd9Sstevel@tonic-gate } 31607c478bd9Sstevel@tonic-gate } 31617c478bd9Sstevel@tonic-gate 31627c478bd9Sstevel@tonic-gate if (forward_flag && forwardable_flag) { 31637c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 31647c478bd9Sstevel@tonic-gate "Error in krb5 configuration file. " 31657c478bd9Sstevel@tonic-gate "Both forward and forwardable are set.\n")); 31667c478bd9Sstevel@tonic-gate exit(1); 31677c478bd9Sstevel@tonic-gate } 31687c478bd9Sstevel@tonic-gate if (forwardable_flag) { 31697c478bd9Sstevel@tonic-gate forward_flags |= OPTS_FORWARD_CREDS | OPTS_FORWARDABLE_CREDS; 31707c478bd9Sstevel@tonic-gate } else if (forward_flag) 31717c478bd9Sstevel@tonic-gate forward_flags |= OPTS_FORWARD_CREDS; 31727c478bd9Sstevel@tonic-gate 31737c478bd9Sstevel@tonic-gate 31747c478bd9Sstevel@tonic-gate do { 31757c478bd9Sstevel@tonic-gate /* 31767c478bd9Sstevel@tonic-gate * Search for an address of desired type in the IP address list 31777c478bd9Sstevel@tonic-gate * of the target. 31787c478bd9Sstevel@tonic-gate */ 31797c478bd9Sstevel@tonic-gate while (h != NULL) { 31807c478bd9Sstevel@tonic-gate struct sockaddr_in6 *addr; 31817c478bd9Sstevel@tonic-gate 31827c478bd9Sstevel@tonic-gate addr = (struct sockaddr_in6 *)h->ai_addr; 31837c478bd9Sstevel@tonic-gate 31847c478bd9Sstevel@tonic-gate if (h->ai_family == AF_INET6) 31857c478bd9Sstevel@tonic-gate is_v4mapped = 31867c478bd9Sstevel@tonic-gate IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr); 31877c478bd9Sstevel@tonic-gate else 31887c478bd9Sstevel@tonic-gate is_v4mapped = B_FALSE; 31897c478bd9Sstevel@tonic-gate 31907c478bd9Sstevel@tonic-gate if (addr_type == ALL_ADDRS || 31917c478bd9Sstevel@tonic-gate (addr_type == ONLY_V6 && 31927c478bd9Sstevel@tonic-gate h->ai_family == AF_INET6) || 31937c478bd9Sstevel@tonic-gate (addr_type == ONLY_V4 && 31947c478bd9Sstevel@tonic-gate (h->ai_family == AF_INET || is_v4mapped))) 31957c478bd9Sstevel@tonic-gate break; 31967c478bd9Sstevel@tonic-gate 31977c478bd9Sstevel@tonic-gate /* skip undesired typed addresses */ 31987c478bd9Sstevel@tonic-gate h = h->ai_next; 31997c478bd9Sstevel@tonic-gate } 32007c478bd9Sstevel@tonic-gate 32017c478bd9Sstevel@tonic-gate if (h == NULL) { 32027c478bd9Sstevel@tonic-gate fprintf(stderr, 32037c478bd9Sstevel@tonic-gate "telnet: Unable to connect to remote host"); 32047c478bd9Sstevel@tonic-gate goto tn_exit; 32057c478bd9Sstevel@tonic-gate } 32067c478bd9Sstevel@tonic-gate 32077c478bd9Sstevel@tonic-gate /* 32087c478bd9Sstevel@tonic-gate * We need to open a socket with a family matching the type of 32097c478bd9Sstevel@tonic-gate * address we are trying to connect to. This is because we 32107c478bd9Sstevel@tonic-gate * deal with IPv4 options and IPv6 extension headers. 32117c478bd9Sstevel@tonic-gate */ 32127c478bd9Sstevel@tonic-gate if (h->ai_family == AF_INET) { 32137c478bd9Sstevel@tonic-gate addrp = &((struct sockaddr_in *)(h->ai_addr))->sin_addr; 32147c478bd9Sstevel@tonic-gate ((struct sockaddr_in *)(h->ai_addr))->sin_port = 32157c478bd9Sstevel@tonic-gate target_port; 32167c478bd9Sstevel@tonic-gate } else { 32177c478bd9Sstevel@tonic-gate addrp = &((struct sockaddr_in6 *)(h->ai_addr)) 32187c478bd9Sstevel@tonic-gate ->sin6_addr; 32197c478bd9Sstevel@tonic-gate ((struct sockaddr_in6 *)(h->ai_addr))->sin6_port = 32207c478bd9Sstevel@tonic-gate target_port; 32217c478bd9Sstevel@tonic-gate } 32227c478bd9Sstevel@tonic-gate 32237c478bd9Sstevel@tonic-gate (void) printf("Trying %s...\n", inet_ntop(h->ai_family, 32247c478bd9Sstevel@tonic-gate addrp, abuf, sizeof (abuf))); 32257c478bd9Sstevel@tonic-gate 32267c478bd9Sstevel@tonic-gate net = socket(h->ai_family, SOCK_STREAM, 0); 32277c478bd9Sstevel@tonic-gate 32287c478bd9Sstevel@tonic-gate if (net < 0) { 32297c478bd9Sstevel@tonic-gate perror("telnet: socket"); 32307c478bd9Sstevel@tonic-gate goto tn_exit; 32317c478bd9Sstevel@tonic-gate } 32327c478bd9Sstevel@tonic-gate #ifndef ICMD 32337c478bd9Sstevel@tonic-gate if (num_gw > 0) { 32347c478bd9Sstevel@tonic-gate if (h->ai_family == AF_INET || is_v4mapped) { 32357c478bd9Sstevel@tonic-gate if (!prepare_optbuf(gw_addrs, num_gw, &opt_buf, 32367c478bd9Sstevel@tonic-gate &opt_buf_len, addrp, src_rtng_type)) { 32377c478bd9Sstevel@tonic-gate goto tn_exit; 32387c478bd9Sstevel@tonic-gate } 32397c478bd9Sstevel@tonic-gate 32407c478bd9Sstevel@tonic-gate if (setsockopt(net, IPPROTO_IP, IP_OPTIONS, 32417c478bd9Sstevel@tonic-gate opt_buf, opt_buf_len) < 0) 32427c478bd9Sstevel@tonic-gate perror("setsockopt (IP_OPTIONS)"); 32437c478bd9Sstevel@tonic-gate } else { 32447c478bd9Sstevel@tonic-gate if (setsockopt(net, IPPROTO_IPV6, IPV6_RTHDR, 32457c478bd9Sstevel@tonic-gate opt_buf6, opt_buf_len6) < 0) 32467c478bd9Sstevel@tonic-gate perror("setsockopt (IPV6_RTHDR)"); 32477c478bd9Sstevel@tonic-gate } 32487c478bd9Sstevel@tonic-gate } 32497c478bd9Sstevel@tonic-gate #endif 32507c478bd9Sstevel@tonic-gate #if defined(USE_TOS) 32517c478bd9Sstevel@tonic-gate if (is_v4mapped) { 32527c478bd9Sstevel@tonic-gate if (tos < 0) 32537c478bd9Sstevel@tonic-gate tos = 020; /* Low Delay bit */ 32547c478bd9Sstevel@tonic-gate if (tos && 32557c478bd9Sstevel@tonic-gate (setsockopt(net, IPPROTO_IP, IP_TOS, 32567c478bd9Sstevel@tonic-gate &tos, sizeof (int)) < 0) && 32577c478bd9Sstevel@tonic-gate (errno != ENOPROTOOPT)) 32587c478bd9Sstevel@tonic-gate perror("telnet: setsockopt (IP_TOS) (ignored)"); 32597c478bd9Sstevel@tonic-gate } 32607c478bd9Sstevel@tonic-gate #endif /* defined(USE_TOS) */ 32617c478bd9Sstevel@tonic-gate 32627c478bd9Sstevel@tonic-gate if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 32637c478bd9Sstevel@tonic-gate perror("setsockopt (SO_DEBUG)"); 32647c478bd9Sstevel@tonic-gate } 32657c478bd9Sstevel@tonic-gate 32667c478bd9Sstevel@tonic-gate ret_val = connect(net, h->ai_addr, h->ai_addrlen); 32677c478bd9Sstevel@tonic-gate 32687c478bd9Sstevel@tonic-gate /* 32697c478bd9Sstevel@tonic-gate * If failed, try the next address of the target. 32707c478bd9Sstevel@tonic-gate */ 32717c478bd9Sstevel@tonic-gate if (ret_val < 0) { 32727c478bd9Sstevel@tonic-gate Close(&net); 32737c478bd9Sstevel@tonic-gate if (h->ai_next != NULL) { 32747c478bd9Sstevel@tonic-gate 32757c478bd9Sstevel@tonic-gate int oerrno = errno; 32767c478bd9Sstevel@tonic-gate 32777c478bd9Sstevel@tonic-gate (void) fprintf(stderr, 32787c478bd9Sstevel@tonic-gate "telnet: connect to address %s: ", abuf); 32797c478bd9Sstevel@tonic-gate errno = oerrno; 32807c478bd9Sstevel@tonic-gate perror((char *)0); 32817c478bd9Sstevel@tonic-gate 32827c478bd9Sstevel@tonic-gate h = h->ai_next; 32837c478bd9Sstevel@tonic-gate continue; 32847c478bd9Sstevel@tonic-gate } 32857c478bd9Sstevel@tonic-gate perror("telnet: Unable to connect to remote host"); 32867c478bd9Sstevel@tonic-gate goto tn_exit; 32877c478bd9Sstevel@tonic-gate } 32887c478bd9Sstevel@tonic-gate connected++; 32897c478bd9Sstevel@tonic-gate } while (connected == 0); 32907c478bd9Sstevel@tonic-gate freeaddrinfo(host); 32917c478bd9Sstevel@tonic-gate host = NULL; 32927c478bd9Sstevel@tonic-gate #ifdef ICMD 32937c478bd9Sstevel@tonic-gate /* 32947c478bd9Sstevel@tonic-gate * Do initial protocol to connect to farther end... 32957c478bd9Sstevel@tonic-gate */ 32967c478bd9Sstevel@tonic-gate { 32977c478bd9Sstevel@tonic-gate char buf[1024]; 32987c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s %d\n", real_host, (int)dest_port); 32997c478bd9Sstevel@tonic-gate write(net, buf, strlen(buf)); 33007c478bd9Sstevel@tonic-gate } 33017c478bd9Sstevel@tonic-gate #endif 33027c478bd9Sstevel@tonic-gate if (cmdrc(hostp, hostname) != 0) 33037c478bd9Sstevel@tonic-gate goto tn_exit; 33047c478bd9Sstevel@tonic-gate FreeHostnameList(hostname_list); 33057c478bd9Sstevel@tonic-gate if (autologin && user == NULL) { 33067c478bd9Sstevel@tonic-gate struct passwd *pw; 33077c478bd9Sstevel@tonic-gate 33087c478bd9Sstevel@tonic-gate user = getenv("LOGNAME"); 33097c478bd9Sstevel@tonic-gate if (user == NULL || 33107c478bd9Sstevel@tonic-gate ((pw = getpwnam(user)) != NULL) && 33117c478bd9Sstevel@tonic-gate pw->pw_uid != getuid()) { 33127c478bd9Sstevel@tonic-gate if (pw = getpwuid(getuid())) 33137c478bd9Sstevel@tonic-gate user = pw->pw_name; 33147c478bd9Sstevel@tonic-gate else 33157c478bd9Sstevel@tonic-gate user = NULL; 33167c478bd9Sstevel@tonic-gate } 33177c478bd9Sstevel@tonic-gate } 33187c478bd9Sstevel@tonic-gate 33197c478bd9Sstevel@tonic-gate if (user) { 33207c478bd9Sstevel@tonic-gate if (env_define((unsigned char *)"USER", (unsigned char *)user)) 33217c478bd9Sstevel@tonic-gate env_export((unsigned char *)"USER"); 33227c478bd9Sstevel@tonic-gate else { 33237c478bd9Sstevel@tonic-gate /* Clean up and exit. */ 33247c478bd9Sstevel@tonic-gate Close(&net); 33257c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 33267c478bd9Sstevel@tonic-gate "Connection to %.*s closed.\n", 33277c478bd9Sstevel@tonic-gate MAXHOSTNAMELEN, hostname); 33287c478bd9Sstevel@tonic-gate ExitString(buf, EXIT_FAILURE); 33297c478bd9Sstevel@tonic-gate 33307c478bd9Sstevel@tonic-gate /* NOTREACHED */ 33317c478bd9Sstevel@tonic-gate } 33327c478bd9Sstevel@tonic-gate } 33337c478bd9Sstevel@tonic-gate (void) call(3, status, "status", "notmuch"); 33347c478bd9Sstevel@tonic-gate if (setjmp(peerdied) == 0) 33357c478bd9Sstevel@tonic-gate telnet(user); 33367c478bd9Sstevel@tonic-gate 33377c478bd9Sstevel@tonic-gate Close(&net); 33387c478bd9Sstevel@tonic-gate 33397c478bd9Sstevel@tonic-gate (void) snprintf(buf, sizeof (buf), 33407c478bd9Sstevel@tonic-gate "Connection to %.*s closed by foreign host.\n", 33417c478bd9Sstevel@tonic-gate MAXHOSTNAMELEN, hostname); 33427c478bd9Sstevel@tonic-gate ExitString(buf, EXIT_FAILURE); 33437c478bd9Sstevel@tonic-gate 33447c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 33457c478bd9Sstevel@tonic-gate 33467c478bd9Sstevel@tonic-gate tn_exit: 33477c478bd9Sstevel@tonic-gate FreeHostnameList(hostname_list); 33487c478bd9Sstevel@tonic-gate Close(&net); 33497c478bd9Sstevel@tonic-gate connected = 0; 33507c478bd9Sstevel@tonic-gate if (host != NULL) 33517c478bd9Sstevel@tonic-gate freeaddrinfo(host); 33527c478bd9Sstevel@tonic-gate return (0); 33537c478bd9Sstevel@tonic-gate } 33547c478bd9Sstevel@tonic-gate 33557c478bd9Sstevel@tonic-gate #define HELPINDENT (sizeof ("connect")) 33567c478bd9Sstevel@tonic-gate 33577c478bd9Sstevel@tonic-gate static char openhelp[] = "connect to a site"; 33587c478bd9Sstevel@tonic-gate static char closehelp[] = "close current connection"; 33597c478bd9Sstevel@tonic-gate static char logouthelp[] = 33607c478bd9Sstevel@tonic-gate "forcibly logout remote user and close the connection"; 33617c478bd9Sstevel@tonic-gate static char quithelp[] = "exit telnet"; 33627c478bd9Sstevel@tonic-gate static char statushelp[] = "print status information"; 33637c478bd9Sstevel@tonic-gate static char helphelp[] = "print help information"; 33647c478bd9Sstevel@tonic-gate static char sendhelp[] = 33657c478bd9Sstevel@tonic-gate "transmit special characters ('send ?' for more)"; 33667c478bd9Sstevel@tonic-gate static char sethelp[] = "set operating parameters ('set ?' for more)"; 33677c478bd9Sstevel@tonic-gate static char unsethelp[] = "unset operating parameters ('unset ?' for more)"; 33687c478bd9Sstevel@tonic-gate static char togglestring[] = 33697c478bd9Sstevel@tonic-gate "toggle operating parameters ('toggle ?' for more)"; 33707c478bd9Sstevel@tonic-gate static char slchelp[] = "change state of special charaters ('slc ?' for more)"; 33717c478bd9Sstevel@tonic-gate static char displayhelp[] = "display operating parameters"; 33727c478bd9Sstevel@tonic-gate static char authhelp[] = 33737c478bd9Sstevel@tonic-gate "turn on (off) authentication ('auth ?' for more)"; 33747c478bd9Sstevel@tonic-gate static char forwardhelp[] = 33757c478bd9Sstevel@tonic-gate "turn on (off) credential forwarding ('forward ?' for more)"; 33767c478bd9Sstevel@tonic-gate static char encrypthelp[] = 33777c478bd9Sstevel@tonic-gate "turn on (off) encryption ('encrypt ?' for more)"; 33787c478bd9Sstevel@tonic-gate static char zhelp[] = "suspend telnet"; 33797c478bd9Sstevel@tonic-gate static char shellhelp[] = "invoke a subshell"; 33807c478bd9Sstevel@tonic-gate static char envhelp[] = "change environment variables ('environ ?' for more)"; 33817c478bd9Sstevel@tonic-gate static char modestring[] = 33827c478bd9Sstevel@tonic-gate "try to enter line or character mode ('mode ?' for more)"; 33837c478bd9Sstevel@tonic-gate 33847c478bd9Sstevel@tonic-gate static int help(); 33857c478bd9Sstevel@tonic-gate 33867c478bd9Sstevel@tonic-gate static Command cmdtab[] = { 33877c478bd9Sstevel@tonic-gate { "close", closehelp, bye, 1 }, 33887c478bd9Sstevel@tonic-gate { "logout", logouthelp, logout, 1 }, 33897c478bd9Sstevel@tonic-gate { "display", displayhelp, display, 0 }, 33907c478bd9Sstevel@tonic-gate { "mode", modestring, modecmd, 0 }, 33917c478bd9Sstevel@tonic-gate { "open", openhelp, tn, 0 }, 33927c478bd9Sstevel@tonic-gate { "quit", quithelp, quit, 0 }, 33937c478bd9Sstevel@tonic-gate { "send", sendhelp, sendcmd, 0 }, 33947c478bd9Sstevel@tonic-gate { "set", sethelp, setcmd, 0 }, 33957c478bd9Sstevel@tonic-gate { "unset", unsethelp, unsetcmd, 0 }, 33967c478bd9Sstevel@tonic-gate { "status", statushelp, status, 0 }, 33977c478bd9Sstevel@tonic-gate { "toggle", togglestring, toggle, 0 }, 33987c478bd9Sstevel@tonic-gate { "slc", slchelp, slccmd, 0 }, 33997c478bd9Sstevel@tonic-gate { "auth", authhelp, auth_cmd, 0 }, 34007c478bd9Sstevel@tonic-gate { "encrypt", encrypthelp, encrypt_cmd, 0 }, 34017c478bd9Sstevel@tonic-gate { "forward", forwardhelp, forw_cmd, 0 }, 34027c478bd9Sstevel@tonic-gate { "z", zhelp, suspend, 0 }, 34037c478bd9Sstevel@tonic-gate { "!", shellhelp, shell, 0 }, 34047c478bd9Sstevel@tonic-gate { "environ", envhelp, env_cmd, 0 }, 34057c478bd9Sstevel@tonic-gate { "?", helphelp, help, 0 }, 34067c478bd9Sstevel@tonic-gate 0 34077c478bd9Sstevel@tonic-gate }; 34087c478bd9Sstevel@tonic-gate 34097c478bd9Sstevel@tonic-gate 34107c478bd9Sstevel@tonic-gate static Command cmdtab2[] = { 34117c478bd9Sstevel@tonic-gate { "help", 0, help, 0 }, 34127c478bd9Sstevel@tonic-gate { "escape", 0, setescape, 0 }, 34137c478bd9Sstevel@tonic-gate { "crmod", 0, togcrmod, 0 }, 34147c478bd9Sstevel@tonic-gate 0 34157c478bd9Sstevel@tonic-gate }; 34167c478bd9Sstevel@tonic-gate 34177c478bd9Sstevel@tonic-gate 34187c478bd9Sstevel@tonic-gate /* 34197c478bd9Sstevel@tonic-gate * Call routine with argc, argv set from args. 34207c478bd9Sstevel@tonic-gate * Uses /usr/include/stdarg.h 34217c478bd9Sstevel@tonic-gate */ 34227c478bd9Sstevel@tonic-gate #define MAXVARGS 100 34237c478bd9Sstevel@tonic-gate /*VARARGS1*/ 34247c478bd9Sstevel@tonic-gate static void 34257c478bd9Sstevel@tonic-gate call(int n_ptrs, ...) 34267c478bd9Sstevel@tonic-gate { 34277c478bd9Sstevel@tonic-gate va_list ap; 34287c478bd9Sstevel@tonic-gate typedef int (*intrtn_t)(); 34297c478bd9Sstevel@tonic-gate intrtn_t routine; 34307c478bd9Sstevel@tonic-gate char *args[MAXVARGS+1]; /* leave 1 for trailing NULL */ 34317c478bd9Sstevel@tonic-gate int argno = 0; 34327c478bd9Sstevel@tonic-gate 34337c478bd9Sstevel@tonic-gate if (n_ptrs > MAXVARGS) 34347c478bd9Sstevel@tonic-gate n_ptrs = MAXVARGS; 3435740638c8Sbw va_start(ap, n_ptrs); 34367c478bd9Sstevel@tonic-gate 34377c478bd9Sstevel@tonic-gate routine = (va_arg(ap, intrtn_t)); /* extract the routine's name */ 34387c478bd9Sstevel@tonic-gate n_ptrs--; 34397c478bd9Sstevel@tonic-gate 34407c478bd9Sstevel@tonic-gate while (argno < n_ptrs) /* extract the routine's args */ 34417c478bd9Sstevel@tonic-gate args[argno++] = va_arg(ap, char *); 34427c478bd9Sstevel@tonic-gate args[argno] = NULL; /* NULL terminate for good luck */ 34437c478bd9Sstevel@tonic-gate va_end(ap); 34447c478bd9Sstevel@tonic-gate 34457c478bd9Sstevel@tonic-gate (*routine)(argno, args); 34467c478bd9Sstevel@tonic-gate } 34477c478bd9Sstevel@tonic-gate 34487c478bd9Sstevel@tonic-gate 34497c478bd9Sstevel@tonic-gate static Command * 34507c478bd9Sstevel@tonic-gate getcmd(name) 34517c478bd9Sstevel@tonic-gate char *name; 34527c478bd9Sstevel@tonic-gate { 34537c478bd9Sstevel@tonic-gate Command *cm; 34547c478bd9Sstevel@tonic-gate 34557c478bd9Sstevel@tonic-gate if (cm = (Command *) genget(name, (char **)cmdtab, sizeof (Command))) 34567c478bd9Sstevel@tonic-gate return (cm); 34577c478bd9Sstevel@tonic-gate return (Command *) genget(name, (char **)cmdtab2, sizeof (Command)); 34587c478bd9Sstevel@tonic-gate } 34597c478bd9Sstevel@tonic-gate 34607c478bd9Sstevel@tonic-gate void 34617c478bd9Sstevel@tonic-gate command(top, tbuf, cnt) 34627c478bd9Sstevel@tonic-gate int top; 34637c478bd9Sstevel@tonic-gate char *tbuf; 34647c478bd9Sstevel@tonic-gate int cnt; 34657c478bd9Sstevel@tonic-gate { 34667c478bd9Sstevel@tonic-gate Command *c; 34677c478bd9Sstevel@tonic-gate 34687c478bd9Sstevel@tonic-gate setcommandmode(); 34697c478bd9Sstevel@tonic-gate if (!top) { 34707c478bd9Sstevel@tonic-gate (void) putchar('\n'); 34717c478bd9Sstevel@tonic-gate } else { 34727c478bd9Sstevel@tonic-gate (void) signal(SIGINT, SIG_DFL); 34737c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, SIG_DFL); 34747c478bd9Sstevel@tonic-gate } 34757c478bd9Sstevel@tonic-gate for (;;) { 34767c478bd9Sstevel@tonic-gate if (rlogin == _POSIX_VDISABLE) 34777c478bd9Sstevel@tonic-gate (void) printf("%s> ", prompt); 34787c478bd9Sstevel@tonic-gate if (tbuf) { 34797c478bd9Sstevel@tonic-gate char *cp; 34807c478bd9Sstevel@tonic-gate if (AllocStringBuffer(&line, &linesize, cnt) == NULL) 34817c478bd9Sstevel@tonic-gate goto command_exit; 34827c478bd9Sstevel@tonic-gate cp = line; 34837c478bd9Sstevel@tonic-gate while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 34847c478bd9Sstevel@tonic-gate cnt--; 34857c478bd9Sstevel@tonic-gate tbuf = 0; 34867c478bd9Sstevel@tonic-gate if (cp == line || *--cp != '\n' || cp == line) 34877c478bd9Sstevel@tonic-gate goto getline; 34887c478bd9Sstevel@tonic-gate *cp = '\0'; 34897c478bd9Sstevel@tonic-gate if (rlogin == _POSIX_VDISABLE) 34907c478bd9Sstevel@tonic-gate (void) printf("%s\n", line); 34917c478bd9Sstevel@tonic-gate } else { 34927c478bd9Sstevel@tonic-gate getline: 34937c478bd9Sstevel@tonic-gate if (rlogin != _POSIX_VDISABLE) 34947c478bd9Sstevel@tonic-gate (void) printf("%s> ", prompt); 34957c478bd9Sstevel@tonic-gate if (GetString(&line, &linesize, stdin) == NULL) { 34967c478bd9Sstevel@tonic-gate if (!feof(stdin)) 34977c478bd9Sstevel@tonic-gate perror("telnet"); 34987c478bd9Sstevel@tonic-gate (void) quit(); 34997c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 35007c478bd9Sstevel@tonic-gate break; 35017c478bd9Sstevel@tonic-gate } 35027c478bd9Sstevel@tonic-gate } 35037c478bd9Sstevel@tonic-gate if (line[0] == 0) 35047c478bd9Sstevel@tonic-gate break; 35057c478bd9Sstevel@tonic-gate makeargv(); 35067c478bd9Sstevel@tonic-gate if (margv[0] == 0) { 35077c478bd9Sstevel@tonic-gate break; 35087c478bd9Sstevel@tonic-gate } 35097c478bd9Sstevel@tonic-gate c = getcmd(margv[0]); 35107c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 35117c478bd9Sstevel@tonic-gate (void) printf("?Ambiguous command\n"); 35127c478bd9Sstevel@tonic-gate continue; 35137c478bd9Sstevel@tonic-gate } 35147c478bd9Sstevel@tonic-gate if (c == 0) { 35157c478bd9Sstevel@tonic-gate (void) printf("?Invalid command\n"); 35167c478bd9Sstevel@tonic-gate continue; 35177c478bd9Sstevel@tonic-gate } 35187c478bd9Sstevel@tonic-gate if (c->needconnect && !connected) { 35197c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first.\n"); 35207c478bd9Sstevel@tonic-gate continue; 35217c478bd9Sstevel@tonic-gate } 35227c478bd9Sstevel@tonic-gate if ((*c->handler)(margc, margv)) { 35237c478bd9Sstevel@tonic-gate break; 35247c478bd9Sstevel@tonic-gate } 35257c478bd9Sstevel@tonic-gate } 35267c478bd9Sstevel@tonic-gate command_exit: 35277c478bd9Sstevel@tonic-gate if (!top) { 35287c478bd9Sstevel@tonic-gate if (!connected) { 35297c478bd9Sstevel@tonic-gate longjmp(toplevel, 1); 35307c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 35317c478bd9Sstevel@tonic-gate } 35327c478bd9Sstevel@tonic-gate setconnmode(0); 35337c478bd9Sstevel@tonic-gate } 35347c478bd9Sstevel@tonic-gate } 35357c478bd9Sstevel@tonic-gate 35367c478bd9Sstevel@tonic-gate /* 35377c478bd9Sstevel@tonic-gate * Help command. 35387c478bd9Sstevel@tonic-gate */ 3539740638c8Sbw static int 35407c478bd9Sstevel@tonic-gate help(argc, argv) 35417c478bd9Sstevel@tonic-gate int argc; 35427c478bd9Sstevel@tonic-gate char *argv[]; 35437c478bd9Sstevel@tonic-gate { 35447c478bd9Sstevel@tonic-gate register Command *c; 35457c478bd9Sstevel@tonic-gate 35467c478bd9Sstevel@tonic-gate if (argc == 1) { 35477c478bd9Sstevel@tonic-gate (void) printf( 35487c478bd9Sstevel@tonic-gate "Commands may be abbreviated. Commands are:\n\n"); 35497c478bd9Sstevel@tonic-gate for (c = cmdtab; c->name; c++) 35507c478bd9Sstevel@tonic-gate if (c->help) { 35517c478bd9Sstevel@tonic-gate (void) printf("%-*s\t%s\n", HELPINDENT, 35527c478bd9Sstevel@tonic-gate c->name, c->help); 35537c478bd9Sstevel@tonic-gate } 35547c478bd9Sstevel@tonic-gate (void) printf("<return>\tleave command mode\n"); 35557c478bd9Sstevel@tonic-gate return (0); 35567c478bd9Sstevel@tonic-gate } 35577c478bd9Sstevel@tonic-gate while (--argc > 0) { 35587c478bd9Sstevel@tonic-gate register char *arg; 35597c478bd9Sstevel@tonic-gate arg = *++argv; 35607c478bd9Sstevel@tonic-gate c = getcmd(arg); 35617c478bd9Sstevel@tonic-gate if (Ambiguous(c)) 35627c478bd9Sstevel@tonic-gate (void) printf("?Ambiguous help command %s\n", arg); 35637c478bd9Sstevel@tonic-gate else if (c == (Command *)0) 35647c478bd9Sstevel@tonic-gate (void) printf("?Invalid help command %s\n", arg); 35657c478bd9Sstevel@tonic-gate else if (c->help) { 35667c478bd9Sstevel@tonic-gate (void) printf("%s\n", c->help); 35677c478bd9Sstevel@tonic-gate } else { 35687c478bd9Sstevel@tonic-gate (void) printf("No additional help on %s\n", arg); 35697c478bd9Sstevel@tonic-gate } 35707c478bd9Sstevel@tonic-gate } 35717c478bd9Sstevel@tonic-gate return (0); 35727c478bd9Sstevel@tonic-gate } 35737c478bd9Sstevel@tonic-gate 35747c478bd9Sstevel@tonic-gate static char *rcname = NULL; 35757c478bd9Sstevel@tonic-gate #define TELNETRC_NAME "telnetrc" 35767c478bd9Sstevel@tonic-gate #define TELNETRC_COMP "/." TELNETRC_NAME 35777c478bd9Sstevel@tonic-gate 35787c478bd9Sstevel@tonic-gate static int 35797c478bd9Sstevel@tonic-gate cmdrc(char *m1, char *m2) 35807c478bd9Sstevel@tonic-gate { 35817c478bd9Sstevel@tonic-gate Command *c; 35827c478bd9Sstevel@tonic-gate FILE *rcfile = NULL; 35837c478bd9Sstevel@tonic-gate int gotmachine = 0; 35847c478bd9Sstevel@tonic-gate int l1 = strlen(m1); 35857c478bd9Sstevel@tonic-gate int l2 = strlen(m2); 35867c478bd9Sstevel@tonic-gate char m1save[MAXHOSTNAMELEN]; 35877c478bd9Sstevel@tonic-gate int ret = 0; 35887c478bd9Sstevel@tonic-gate char def[] = "DEFAULT"; 35897c478bd9Sstevel@tonic-gate 35907c478bd9Sstevel@tonic-gate if (skiprc) 35917c478bd9Sstevel@tonic-gate goto cmdrc_exit; 35927c478bd9Sstevel@tonic-gate 35937c478bd9Sstevel@tonic-gate doing_rc = 1; 35947c478bd9Sstevel@tonic-gate 35957c478bd9Sstevel@tonic-gate (void) strlcpy(m1save, m1, sizeof (m1save)); 35967c478bd9Sstevel@tonic-gate m1 = m1save; 35977c478bd9Sstevel@tonic-gate 35987c478bd9Sstevel@tonic-gate if (rcname == NULL) { 35997c478bd9Sstevel@tonic-gate char *homedir; 36007c478bd9Sstevel@tonic-gate unsigned rcbuflen; 36017c478bd9Sstevel@tonic-gate 36027c478bd9Sstevel@tonic-gate if ((homedir = getenv("HOME")) == NULL) 36037c478bd9Sstevel@tonic-gate homedir = ""; 36047c478bd9Sstevel@tonic-gate 36057c478bd9Sstevel@tonic-gate rcbuflen = strlen(homedir) + strlen(TELNETRC_COMP) + 1; 36067c478bd9Sstevel@tonic-gate if ((rcname = malloc(rcbuflen)) == NULL) { 36077c478bd9Sstevel@tonic-gate perror("telnet: can't process " TELNETRC_NAME); 36087c478bd9Sstevel@tonic-gate ret = 1; 36097c478bd9Sstevel@tonic-gate goto cmdrc_exit; 36107c478bd9Sstevel@tonic-gate } 36117c478bd9Sstevel@tonic-gate (void) strcpy(rcname, homedir); 36127c478bd9Sstevel@tonic-gate (void) strcat(rcname, TELNETRC_COMP); 36137c478bd9Sstevel@tonic-gate } 36147c478bd9Sstevel@tonic-gate 36157c478bd9Sstevel@tonic-gate if ((rcfile = fopen(rcname, "r")) == NULL) 36167c478bd9Sstevel@tonic-gate goto cmdrc_exit; 36177c478bd9Sstevel@tonic-gate 36187c478bd9Sstevel@tonic-gate for (;;) { 36197c478bd9Sstevel@tonic-gate if (GetString(&line, &linesize, rcfile) == NULL) { 36207c478bd9Sstevel@tonic-gate if (!feof(rcfile)) { 36217c478bd9Sstevel@tonic-gate perror("telnet: error reading " TELNETRC_NAME); 36227c478bd9Sstevel@tonic-gate ret = 1; 36237c478bd9Sstevel@tonic-gate goto cmdrc_exit; 36247c478bd9Sstevel@tonic-gate } 36257c478bd9Sstevel@tonic-gate break; 36267c478bd9Sstevel@tonic-gate } 36277c478bd9Sstevel@tonic-gate if (line[0] == 0) 36287c478bd9Sstevel@tonic-gate continue; 36297c478bd9Sstevel@tonic-gate if (line[0] == '#') 36307c478bd9Sstevel@tonic-gate continue; 36317c478bd9Sstevel@tonic-gate if (gotmachine) { 36327c478bd9Sstevel@tonic-gate if (!isspace(line[0])) 36337c478bd9Sstevel@tonic-gate gotmachine = 0; 36347c478bd9Sstevel@tonic-gate } 36357c478bd9Sstevel@tonic-gate if (gotmachine == 0) { 36367c478bd9Sstevel@tonic-gate if (isspace(line[0])) 36377c478bd9Sstevel@tonic-gate continue; 36387c478bd9Sstevel@tonic-gate if (strncasecmp(line, m1, l1) == 0) 36397c478bd9Sstevel@tonic-gate (void) strcpy(line, &line[l1]); 36407c478bd9Sstevel@tonic-gate else if (strncasecmp(line, m2, l2) == 0) 36417c478bd9Sstevel@tonic-gate (void) strcpy(line, &line[l2]); 36427c478bd9Sstevel@tonic-gate else if (strncasecmp(line, def, sizeof (def) - 1) == 0) 36437c478bd9Sstevel@tonic-gate (void) strcpy(line, &line[sizeof (def) - 1]); 36447c478bd9Sstevel@tonic-gate else 36457c478bd9Sstevel@tonic-gate continue; 36467c478bd9Sstevel@tonic-gate if (line[0] != ' ' && line[0] != '\t' && 36477c478bd9Sstevel@tonic-gate line[0] != '\n') 36487c478bd9Sstevel@tonic-gate continue; 36497c478bd9Sstevel@tonic-gate gotmachine = 1; 36507c478bd9Sstevel@tonic-gate } 36517c478bd9Sstevel@tonic-gate makeargv(); 36527c478bd9Sstevel@tonic-gate if (margv[0] == 0) 36537c478bd9Sstevel@tonic-gate continue; 36547c478bd9Sstevel@tonic-gate c = getcmd(margv[0]); 36557c478bd9Sstevel@tonic-gate if (Ambiguous(c)) { 36567c478bd9Sstevel@tonic-gate (void) printf("?Ambiguous command: %s\n", margv[0]); 36577c478bd9Sstevel@tonic-gate continue; 36587c478bd9Sstevel@tonic-gate } 36597c478bd9Sstevel@tonic-gate if (c == 0) { 36607c478bd9Sstevel@tonic-gate (void) printf("?Invalid command: %s\n", margv[0]); 36617c478bd9Sstevel@tonic-gate continue; 36627c478bd9Sstevel@tonic-gate } 36637c478bd9Sstevel@tonic-gate /* 36647c478bd9Sstevel@tonic-gate * This should never happen... 36657c478bd9Sstevel@tonic-gate */ 36667c478bd9Sstevel@tonic-gate if (c->needconnect && !connected) { 36677c478bd9Sstevel@tonic-gate (void) printf("?Need to be connected first for %s.\n", 36687c478bd9Sstevel@tonic-gate margv[0]); 36697c478bd9Sstevel@tonic-gate continue; 36707c478bd9Sstevel@tonic-gate } 36717c478bd9Sstevel@tonic-gate (*c->handler)(margc, margv); 36727c478bd9Sstevel@tonic-gate } 36737c478bd9Sstevel@tonic-gate cmdrc_exit: 36747c478bd9Sstevel@tonic-gate if (rcfile != NULL) 36757c478bd9Sstevel@tonic-gate (void) fclose(rcfile); 36767c478bd9Sstevel@tonic-gate doing_rc = 0; 36777c478bd9Sstevel@tonic-gate 36787c478bd9Sstevel@tonic-gate return (ret); 36797c478bd9Sstevel@tonic-gate } 3680