commands.c revision 63662
129088Smarkm/* 229088Smarkm * Copyright (c) 1988, 1990, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 1329088Smarkm * 3. All advertising materials mentioning features or use of this software 1429088Smarkm * must display the following acknowledgement: 1529088Smarkm * This product includes software developed by the University of 1629088Smarkm * California, Berkeley and its contributors. 1729088Smarkm * 4. Neither the name of the University nor the names of its contributors 1829088Smarkm * may be used to endorse or promote products derived from this software 1929088Smarkm * without specific prior written permission. 2029088Smarkm * 2129088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2229088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2329088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2429088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2529088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2629088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2729088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2829088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2929088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3029088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3129088Smarkm * SUCH DAMAGE. 3256668Sshin * 3356668Sshin * $FreeBSD: head/contrib/telnet/telnet/commands.c 63662 2000-07-20 14:54:04Z ume $ 3429088Smarkm */ 3529088Smarkm 3629088Smarkm#ifndef lint 3729181Smarkmstatic const char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; 3829088Smarkm#endif /* not lint */ 3929088Smarkm 4029088Smarkm#if defined(unix) 4129088Smarkm#include <sys/param.h> 4229088Smarkm#if defined(CRAY) || defined(sysV88) 4329088Smarkm#include <sys/types.h> 4429088Smarkm#endif 4529088Smarkm#include <sys/file.h> 4629088Smarkm#else 4729088Smarkm#include <sys/types.h> 4829088Smarkm#endif /* defined(unix) */ 4929088Smarkm#include <sys/socket.h> 5029088Smarkm#include <netinet/in.h> 5129088Smarkm#ifdef CRAY 5229088Smarkm#include <fcntl.h> 5329088Smarkm#endif /* CRAY */ 5429088Smarkm 5529088Smarkm#include <signal.h> 5629088Smarkm#include <netdb.h> 5729088Smarkm#include <ctype.h> 5829088Smarkm#include <pwd.h> 5929088Smarkm#include <varargs.h> 6029088Smarkm#include <errno.h> 6129181Smarkm#include <unistd.h> 6229181Smarkm#include <stdlib.h> 6329088Smarkm 6429088Smarkm#include <arpa/telnet.h> 6529088Smarkm 6629088Smarkm#include "general.h" 6729088Smarkm 6829088Smarkm#include "ring.h" 6929088Smarkm 7029088Smarkm#include "externs.h" 7129088Smarkm#include "defines.h" 7229088Smarkm#include "types.h" 7329088Smarkm 7429181Smarkm#if defined(AUTHENTICATION) 7529181Smarkm#include <libtelnet/auth.h> 7629181Smarkm#endif 7729181Smarkm#if defined(ENCRYPTION) 7829181Smarkm#include <libtelnet/encrypt.h> 7929181Smarkm#endif 8029181Smarkm 8129088Smarkm#if !defined(CRAY) && !defined(sysV88) 8229088Smarkm#include <netinet/in_systm.h> 8329088Smarkm# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) 8429088Smarkm# include <machine/endian.h> 8529088Smarkm# endif /* vax */ 8629088Smarkm#endif /* !defined(CRAY) && !defined(sysV88) */ 8729088Smarkm#include <netinet/ip.h> 8856668Sshin#include <netinet/ip6.h> 8929088Smarkm 9029088Smarkm 9129088Smarkm#ifndef MAXHOSTNAMELEN 9229088Smarkm#define MAXHOSTNAMELEN 64 9329088Smarkm#endif MAXHOSTNAMELEN 9429088Smarkm 9529088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 9629088Smarkmint tos = -1; 9729088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 9829088Smarkm 9929088Smarkmchar *hostname; 10029088Smarkmstatic char _hostname[MAXHOSTNAMELEN]; 10129088Smarkm 10229088Smarkmextern char *getenv(); 10329088Smarkm 10429088Smarkmextern int isprefix(); 10529088Smarkmextern char **genget(); 10629088Smarkmextern int Ambiguous(); 10729088Smarkm 10829181Smarkmstatic int help(int argc, char *argv[]); 10929181Smarkmstatic int call(); 11029181Smarkmstatic void cmdrc(char *m1, char *m2); 11157125Sshinstatic int switch_af(struct addrinfo **aip); 11229088Smarkm 11329181Smarkmint quit(void); 11429181Smarkm 11529088Smarkmtypedef struct { 11629088Smarkm char *name; /* command name */ 11729088Smarkm char *help; /* help string (NULL for no help) */ 11829088Smarkm int (*handler)(); /* routine which executes command */ 11929088Smarkm int needconnect; /* Do we need to be connected to execute? */ 12029088Smarkm} Command; 12129088Smarkm 12229088Smarkmstatic char line[256]; 12329088Smarkmstatic char saveline[256]; 12429088Smarkmstatic int margc; 12529088Smarkmstatic char *margv[20]; 12629088Smarkm 12729181Smarkm#if defined(SKEY) 12829181Smarkm#include <sys/wait.h> 12929181Smarkm#define PATH_SKEY "/usr/bin/key" 13029181Smarkm int 13129181Smarkmskey_calc(argc, argv) 13229181Smarkm int argc; 13329181Smarkm char **argv; 13429181Smarkm{ 13529181Smarkm int status; 13629181Smarkm 13729181Smarkm if(argc != 3) { 13829181Smarkm printf("%s sequence challenge\n", argv[0]); 13929181Smarkm return; 14029181Smarkm } 14129181Smarkm 14229181Smarkm switch(fork()) { 14329181Smarkm case 0: 14429181Smarkm execv(PATH_SKEY, argv); 14529181Smarkm exit (1); 14629181Smarkm case -1: 14729181Smarkm perror("fork"); 14829181Smarkm break; 14929181Smarkm default: 15029181Smarkm (void) wait(&status); 15129181Smarkm if (WIFEXITED(status)) 15229181Smarkm return (WEXITSTATUS(status)); 15329181Smarkm return (0); 15429181Smarkm } 15529181Smarkm} 15629181Smarkm#endif 15729181Smarkm 15829088Smarkm static void 15929088Smarkmmakeargv() 16029088Smarkm{ 16129088Smarkm register char *cp, *cp2, c; 16229088Smarkm register char **argp = margv; 16329088Smarkm 16429088Smarkm margc = 0; 16529088Smarkm cp = line; 16629088Smarkm if (*cp == '!') { /* Special case shell escape */ 16729088Smarkm strcpy(saveline, line); /* save for shell command */ 16829088Smarkm *argp++ = "!"; /* No room in string to get this */ 16929088Smarkm margc++; 17029088Smarkm cp++; 17129088Smarkm } 17229181Smarkm while ((c = *cp)) { 17329088Smarkm register int inquote = 0; 17429088Smarkm while (isspace(c)) 17529088Smarkm c = *++cp; 17629088Smarkm if (c == '\0') 17729088Smarkm break; 17829088Smarkm *argp++ = cp; 17929088Smarkm margc += 1; 18029088Smarkm for (cp2 = cp; c != '\0'; c = *++cp) { 18129088Smarkm if (inquote) { 18229088Smarkm if (c == inquote) { 18329088Smarkm inquote = 0; 18429088Smarkm continue; 18529088Smarkm } 18629088Smarkm } else { 18729088Smarkm if (c == '\\') { 18829088Smarkm if ((c = *++cp) == '\0') 18929088Smarkm break; 19029088Smarkm } else if (c == '"') { 19129088Smarkm inquote = '"'; 19229088Smarkm continue; 19329088Smarkm } else if (c == '\'') { 19429088Smarkm inquote = '\''; 19529088Smarkm continue; 19629088Smarkm } else if (isspace(c)) 19729088Smarkm break; 19829088Smarkm } 19929088Smarkm *cp2++ = c; 20029088Smarkm } 20129088Smarkm *cp2 = '\0'; 20229088Smarkm if (c == '\0') 20329088Smarkm break; 20429088Smarkm cp++; 20529088Smarkm } 20629088Smarkm *argp++ = 0; 20729088Smarkm} 20829088Smarkm 20929088Smarkm/* 21029088Smarkm * Make a character string into a number. 21129088Smarkm * 21229088Smarkm * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 21329088Smarkm */ 21429088Smarkm 21529181Smarkm static int 21629088Smarkmspecial(s) 21729088Smarkm register char *s; 21829088Smarkm{ 21929088Smarkm register char c; 22029088Smarkm char b; 22129088Smarkm 22229088Smarkm switch (*s) { 22329088Smarkm case '^': 22429088Smarkm b = *++s; 22529088Smarkm if (b == '?') { 22629088Smarkm c = b | 0x40; /* DEL */ 22729088Smarkm } else { 22829088Smarkm c = b & 0x1f; 22929088Smarkm } 23029088Smarkm break; 23129088Smarkm default: 23229088Smarkm c = *s; 23329088Smarkm break; 23429088Smarkm } 23529088Smarkm return c; 23629088Smarkm} 23729088Smarkm 23829088Smarkm/* 23929088Smarkm * Construct a control character sequence 24029088Smarkm * for a special character. 24129088Smarkm */ 24229088Smarkm static char * 24329088Smarkmcontrol(c) 24429088Smarkm register cc_t c; 24529088Smarkm{ 24629088Smarkm static char buf[5]; 24729088Smarkm /* 24829088Smarkm * The only way I could get the Sun 3.5 compiler 24929088Smarkm * to shut up about 25029088Smarkm * if ((unsigned int)c >= 0x80) 25129088Smarkm * was to assign "c" to an unsigned int variable... 25229088Smarkm * Arggg.... 25329088Smarkm */ 25429088Smarkm register unsigned int uic = (unsigned int)c; 25529088Smarkm 25629088Smarkm if (uic == 0x7f) 25729088Smarkm return ("^?"); 25829088Smarkm if (c == (cc_t)_POSIX_VDISABLE) { 25929088Smarkm return "off"; 26029088Smarkm } 26129088Smarkm if (uic >= 0x80) { 26229088Smarkm buf[0] = '\\'; 26329088Smarkm buf[1] = ((c>>6)&07) + '0'; 26429088Smarkm buf[2] = ((c>>3)&07) + '0'; 26529088Smarkm buf[3] = (c&07) + '0'; 26629088Smarkm buf[4] = 0; 26729088Smarkm } else if (uic >= 0x20) { 26829088Smarkm buf[0] = c; 26929088Smarkm buf[1] = 0; 27029088Smarkm } else { 27129088Smarkm buf[0] = '^'; 27229088Smarkm buf[1] = '@'+c; 27329088Smarkm buf[2] = 0; 27429088Smarkm } 27529088Smarkm return (buf); 27629088Smarkm} 27729088Smarkm 27829088Smarkm 27929088Smarkm 28029088Smarkm/* 28129088Smarkm * The following are data structures and routines for 28229088Smarkm * the "send" command. 28329088Smarkm * 28429088Smarkm */ 28529088Smarkm 28629088Smarkmstruct sendlist { 28729088Smarkm char *name; /* How user refers to it (case independent) */ 28829088Smarkm char *help; /* Help information (0 ==> no help) */ 28929088Smarkm int needconnect; /* Need to be connected */ 29029088Smarkm int narg; /* Number of arguments */ 29129088Smarkm int (*handler)(); /* Routine to perform (for special ops) */ 29229088Smarkm int nbyte; /* Number of bytes to send this command */ 29329088Smarkm int what; /* Character to be sent (<0 ==> special) */ 29429088Smarkm}; 29529088Smarkm 29629088Smarkm 29729088Smarkmstatic int 29829088Smarkm send_esc P((void)), 29929088Smarkm send_help P((void)), 30029088Smarkm send_docmd P((char *)), 30129088Smarkm send_dontcmd P((char *)), 30229088Smarkm send_willcmd P((char *)), 30329088Smarkm send_wontcmd P((char *)); 30429088Smarkm 30529088Smarkmstatic struct sendlist Sendlist[] = { 30629088Smarkm { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, 30729088Smarkm { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, 30829088Smarkm { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, 30929088Smarkm { "break", 0, 1, 0, 0, 2, BREAK }, 31029088Smarkm { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, 31129088Smarkm { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, 31229088Smarkm { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, 31329088Smarkm { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, 31429088Smarkm { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, 31529088Smarkm { "intp", 0, 1, 0, 0, 2, IP }, 31629088Smarkm { "interrupt", 0, 1, 0, 0, 2, IP }, 31729088Smarkm { "intr", 0, 1, 0, 0, 2, IP }, 31829088Smarkm { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, 31929088Smarkm { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, 32029088Smarkm { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, 32129088Smarkm { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, 32229088Smarkm { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, 32329088Smarkm { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, 32429088Smarkm { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, 32529088Smarkm { "?", "Display send options", 0, 0, send_help, 0, 0 }, 32629088Smarkm { "help", 0, 0, 0, send_help, 0, 0 }, 32729088Smarkm { "do", 0, 0, 1, send_docmd, 3, 0 }, 32829088Smarkm { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, 32929088Smarkm { "will", 0, 0, 1, send_willcmd, 3, 0 }, 33029088Smarkm { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, 33129088Smarkm { 0 } 33229088Smarkm}; 33329088Smarkm 33429088Smarkm#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ 33529088Smarkm sizeof(struct sendlist))) 33629088Smarkm 33729088Smarkm static int 33829088Smarkmsendcmd(argc, argv) 33929088Smarkm int argc; 34029088Smarkm char **argv; 34129088Smarkm{ 34229088Smarkm int count; /* how many bytes we are going to need to send */ 34329088Smarkm int i; 34429088Smarkm struct sendlist *s; /* pointer to current command */ 34529088Smarkm int success = 0; 34629088Smarkm int needconnect = 0; 34729088Smarkm 34829088Smarkm if (argc < 2) { 34929088Smarkm printf("need at least one argument for 'send' command\n"); 35029088Smarkm printf("'send ?' for help\n"); 35129088Smarkm return 0; 35229088Smarkm } 35329088Smarkm /* 35429088Smarkm * First, validate all the send arguments. 35529088Smarkm * In addition, we see how much space we are going to need, and 35629088Smarkm * whether or not we will be doing a "SYNCH" operation (which 35729088Smarkm * flushes the network queue). 35829088Smarkm */ 35929088Smarkm count = 0; 36029088Smarkm for (i = 1; i < argc; i++) { 36129088Smarkm s = GETSEND(argv[i]); 36229088Smarkm if (s == 0) { 36329088Smarkm printf("Unknown send argument '%s'\n'send ?' for help.\n", 36429088Smarkm argv[i]); 36529088Smarkm return 0; 36629088Smarkm } else if (Ambiguous(s)) { 36729088Smarkm printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 36829088Smarkm argv[i]); 36929088Smarkm return 0; 37029088Smarkm } 37129088Smarkm if (i + s->narg >= argc) { 37229088Smarkm fprintf(stderr, 37329088Smarkm "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", 37429088Smarkm s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 37529088Smarkm return 0; 37629088Smarkm } 37729088Smarkm count += s->nbyte; 37829088Smarkm if (s->handler == send_help) { 37929088Smarkm send_help(); 38029088Smarkm return 0; 38129088Smarkm } 38229088Smarkm 38329088Smarkm i += s->narg; 38429088Smarkm needconnect += s->needconnect; 38529088Smarkm } 38629088Smarkm if (!connected && needconnect) { 38729088Smarkm printf("?Need to be connected first.\n"); 38829088Smarkm printf("'send ?' for help\n"); 38929088Smarkm return 0; 39029088Smarkm } 39129088Smarkm /* Now, do we have enough room? */ 39229088Smarkm if (NETROOM() < count) { 39329088Smarkm printf("There is not enough room in the buffer TO the network\n"); 39429088Smarkm printf("to process your request. Nothing will be done.\n"); 39529088Smarkm printf("('send synch' will throw away most data in the network\n"); 39629088Smarkm printf("buffer, if this might help.)\n"); 39729088Smarkm return 0; 39829088Smarkm } 39929088Smarkm /* OK, they are all OK, now go through again and actually send */ 40029088Smarkm count = 0; 40129088Smarkm for (i = 1; i < argc; i++) { 40229088Smarkm if ((s = GETSEND(argv[i])) == 0) { 40329088Smarkm fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 40429088Smarkm (void) quit(); 40529088Smarkm /*NOTREACHED*/ 40629088Smarkm } 40729088Smarkm if (s->handler) { 40829088Smarkm count++; 40929088Smarkm success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 41029088Smarkm (s->narg > 1) ? argv[i+2] : 0); 41129088Smarkm i += s->narg; 41229088Smarkm } else { 41329088Smarkm NET2ADD(IAC, s->what); 41429088Smarkm printoption("SENT", IAC, s->what); 41529088Smarkm } 41629088Smarkm } 41729088Smarkm return (count == success); 41829088Smarkm} 41929088Smarkm 42029088Smarkm static int 42129088Smarkmsend_esc() 42229088Smarkm{ 42329088Smarkm NETADD(escape); 42429088Smarkm return 1; 42529088Smarkm} 42629088Smarkm 42729088Smarkm static int 42829088Smarkmsend_docmd(name) 42929088Smarkm char *name; 43029088Smarkm{ 43129088Smarkm return(send_tncmd(send_do, "do", name)); 43229088Smarkm} 43329088Smarkm 43429088Smarkm static int 43529088Smarkmsend_dontcmd(name) 43629088Smarkm char *name; 43729088Smarkm{ 43829088Smarkm return(send_tncmd(send_dont, "dont", name)); 43929088Smarkm} 44029088Smarkm static int 44129088Smarkmsend_willcmd(name) 44229088Smarkm char *name; 44329088Smarkm{ 44429088Smarkm return(send_tncmd(send_will, "will", name)); 44529088Smarkm} 44629088Smarkm static int 44729088Smarkmsend_wontcmd(name) 44829088Smarkm char *name; 44929088Smarkm{ 45029088Smarkm return(send_tncmd(send_wont, "wont", name)); 45129088Smarkm} 45229088Smarkm 45329088Smarkm int 45429088Smarkmsend_tncmd(func, cmd, name) 45529088Smarkm void (*func)(); 45629088Smarkm char *cmd, *name; 45729088Smarkm{ 45829088Smarkm char **cpp; 45929088Smarkm extern char *telopts[]; 46029088Smarkm register int val = 0; 46129088Smarkm 46229088Smarkm if (isprefix(name, "help") || isprefix(name, "?")) { 46329088Smarkm register int col, len; 46429088Smarkm 46529088Smarkm printf("Usage: send %s <value|option>\n", cmd); 46629088Smarkm printf("\"value\" must be from 0 to 255\n"); 46729088Smarkm printf("Valid options are:\n\t"); 46829088Smarkm 46929088Smarkm col = 8; 47029088Smarkm for (cpp = telopts; *cpp; cpp++) { 47129088Smarkm len = strlen(*cpp) + 3; 47229088Smarkm if (col + len > 65) { 47329088Smarkm printf("\n\t"); 47429088Smarkm col = 8; 47529088Smarkm } 47629088Smarkm printf(" \"%s\"", *cpp); 47729088Smarkm col += len; 47829088Smarkm } 47929088Smarkm printf("\n"); 48029088Smarkm return 0; 48129088Smarkm } 48229088Smarkm cpp = (char **)genget(name, telopts, sizeof(char *)); 48329088Smarkm if (Ambiguous(cpp)) { 48429088Smarkm fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", 48529088Smarkm name, cmd); 48629088Smarkm return 0; 48729088Smarkm } 48829088Smarkm if (cpp) { 48929088Smarkm val = cpp - telopts; 49029088Smarkm } else { 49129088Smarkm register char *cp = name; 49229088Smarkm 49329088Smarkm while (*cp >= '0' && *cp <= '9') { 49429088Smarkm val *= 10; 49529088Smarkm val += *cp - '0'; 49629088Smarkm cp++; 49729088Smarkm } 49829088Smarkm if (*cp != 0) { 49929088Smarkm fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 50029088Smarkm name, cmd); 50129088Smarkm return 0; 50229088Smarkm } else if (val < 0 || val > 255) { 50329088Smarkm fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", 50429088Smarkm name, cmd); 50529088Smarkm return 0; 50629088Smarkm } 50729088Smarkm } 50829088Smarkm if (!connected) { 50929088Smarkm printf("?Need to be connected first.\n"); 51029088Smarkm return 0; 51129088Smarkm } 51229088Smarkm (*func)(val, 1); 51329088Smarkm return 1; 51429088Smarkm} 51529088Smarkm 51629088Smarkm static int 51729088Smarkmsend_help() 51829088Smarkm{ 51929088Smarkm struct sendlist *s; /* pointer to current command */ 52029088Smarkm for (s = Sendlist; s->name; s++) { 52129088Smarkm if (s->help) 52229088Smarkm printf("%-15s %s\n", s->name, s->help); 52329088Smarkm } 52429088Smarkm return(0); 52529088Smarkm} 52629088Smarkm 52729088Smarkm/* 52829088Smarkm * The following are the routines and data structures referred 52929088Smarkm * to by the arguments to the "toggle" command. 53029088Smarkm */ 53129088Smarkm 53229088Smarkm static int 53329088Smarkmlclchars() 53429088Smarkm{ 53529088Smarkm donelclchars = 1; 53629088Smarkm return 1; 53729088Smarkm} 53829088Smarkm 53929088Smarkm static int 54029088Smarkmtogdebug() 54129088Smarkm{ 54229088Smarkm#ifndef NOT43 54329088Smarkm if (net > 0 && 54429088Smarkm (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 54529088Smarkm perror("setsockopt (SO_DEBUG)"); 54629088Smarkm } 54729088Smarkm#else /* NOT43 */ 54829088Smarkm if (debug) { 54929181Smarkm if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) 55029088Smarkm perror("setsockopt (SO_DEBUG)"); 55129088Smarkm } else 55229088Smarkm printf("Cannot turn off socket debugging\n"); 55329088Smarkm#endif /* NOT43 */ 55429088Smarkm return 1; 55529088Smarkm} 55629088Smarkm 55729088Smarkm 55829088Smarkm static int 55929088Smarkmtogcrlf() 56029088Smarkm{ 56129088Smarkm if (crlf) { 56229088Smarkm printf("Will send carriage returns as telnet <CR><LF>.\n"); 56329088Smarkm } else { 56429088Smarkm printf("Will send carriage returns as telnet <CR><NUL>.\n"); 56529088Smarkm } 56629088Smarkm return 1; 56729088Smarkm} 56829088Smarkm 56929088Smarkmint binmode; 57029088Smarkm 57129088Smarkm static int 57229088Smarkmtogbinary(val) 57329088Smarkm int val; 57429088Smarkm{ 57529088Smarkm donebinarytoggle = 1; 57629088Smarkm 57729088Smarkm if (val >= 0) { 57829088Smarkm binmode = val; 57929088Smarkm } else { 58029088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 58129088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 58229088Smarkm binmode = 1; 58329088Smarkm } else if (my_want_state_is_wont(TELOPT_BINARY) && 58429088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 58529088Smarkm binmode = 0; 58629088Smarkm } 58729088Smarkm val = binmode ? 0 : 1; 58829088Smarkm } 58929088Smarkm 59029088Smarkm if (val == 1) { 59129088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 59229088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 59329088Smarkm printf("Already operating in binary mode with remote host.\n"); 59429088Smarkm } else { 59529088Smarkm printf("Negotiating binary mode with remote host.\n"); 59629088Smarkm tel_enter_binary(3); 59729088Smarkm } 59829088Smarkm } else { 59929088Smarkm if (my_want_state_is_wont(TELOPT_BINARY) && 60029088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 60129088Smarkm printf("Already in network ascii mode with remote host.\n"); 60229088Smarkm } else { 60329088Smarkm printf("Negotiating network ascii mode with remote host.\n"); 60429088Smarkm tel_leave_binary(3); 60529088Smarkm } 60629088Smarkm } 60729088Smarkm return 1; 60829088Smarkm} 60929088Smarkm 61029088Smarkm static int 61129088Smarkmtogrbinary(val) 61229088Smarkm int val; 61329088Smarkm{ 61429088Smarkm donebinarytoggle = 1; 61529088Smarkm 61629088Smarkm if (val == -1) 61729088Smarkm val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 61829088Smarkm 61929088Smarkm if (val == 1) { 62029088Smarkm if (my_want_state_is_do(TELOPT_BINARY)) { 62129088Smarkm printf("Already receiving in binary mode.\n"); 62229088Smarkm } else { 62329088Smarkm printf("Negotiating binary mode on input.\n"); 62429088Smarkm tel_enter_binary(1); 62529088Smarkm } 62629088Smarkm } else { 62729088Smarkm if (my_want_state_is_dont(TELOPT_BINARY)) { 62829088Smarkm printf("Already receiving in network ascii mode.\n"); 62929088Smarkm } else { 63029088Smarkm printf("Negotiating network ascii mode on input.\n"); 63129088Smarkm tel_leave_binary(1); 63229088Smarkm } 63329088Smarkm } 63429088Smarkm return 1; 63529088Smarkm} 63629088Smarkm 63729088Smarkm static int 63829088Smarkmtogxbinary(val) 63929088Smarkm int val; 64029088Smarkm{ 64129088Smarkm donebinarytoggle = 1; 64229088Smarkm 64329088Smarkm if (val == -1) 64429088Smarkm val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 64529088Smarkm 64629088Smarkm if (val == 1) { 64729088Smarkm if (my_want_state_is_will(TELOPT_BINARY)) { 64829088Smarkm printf("Already transmitting in binary mode.\n"); 64929088Smarkm } else { 65029088Smarkm printf("Negotiating binary mode on output.\n"); 65129088Smarkm tel_enter_binary(2); 65229088Smarkm } 65329088Smarkm } else { 65429088Smarkm if (my_want_state_is_wont(TELOPT_BINARY)) { 65529088Smarkm printf("Already transmitting in network ascii mode.\n"); 65629088Smarkm } else { 65729088Smarkm printf("Negotiating network ascii mode on output.\n"); 65829088Smarkm tel_leave_binary(2); 65929088Smarkm } 66029088Smarkm } 66129088Smarkm return 1; 66229088Smarkm} 66329088Smarkm 66429088Smarkm 66529088Smarkmstatic int togglehelp P((void)); 66629088Smarkm#if defined(AUTHENTICATION) 66729088Smarkmextern int auth_togdebug P((int)); 66829088Smarkm#endif 66929088Smarkm#ifdef ENCRYPTION 67029088Smarkmextern int EncryptAutoEnc P((int)); 67129088Smarkmextern int EncryptAutoDec P((int)); 67229088Smarkmextern int EncryptDebug P((int)); 67329088Smarkmextern int EncryptVerbose P((int)); 67429088Smarkm#endif /* ENCRYPTION */ 67529088Smarkm 67629088Smarkmstruct togglelist { 67729088Smarkm char *name; /* name of toggle */ 67829088Smarkm char *help; /* help message */ 67929088Smarkm int (*handler)(); /* routine to do actual setting */ 68029088Smarkm int *variable; 68129088Smarkm char *actionexplanation; 68229088Smarkm}; 68329088Smarkm 68429088Smarkmstatic struct togglelist Togglelist[] = { 68529088Smarkm { "autoflush", 68629088Smarkm "flushing of output when sending interrupt characters", 68729088Smarkm 0, 68829088Smarkm &autoflush, 68929088Smarkm "flush output when sending interrupt characters" }, 69029088Smarkm { "autosynch", 69129088Smarkm "automatic sending of interrupt characters in urgent mode", 69229088Smarkm 0, 69329088Smarkm &autosynch, 69429088Smarkm "send interrupt characters in urgent mode" }, 69529088Smarkm#if defined(AUTHENTICATION) 69629088Smarkm { "autologin", 69729088Smarkm "automatic sending of login and/or authentication info", 69829088Smarkm 0, 69929088Smarkm &autologin, 70029088Smarkm "send login name and/or authentication information" }, 70129088Smarkm { "authdebug", 70229088Smarkm "Toggle authentication debugging", 70329088Smarkm auth_togdebug, 70429088Smarkm 0, 70529088Smarkm "print authentication debugging information" }, 70629088Smarkm#endif 70729088Smarkm#ifdef ENCRYPTION 70829088Smarkm { "autoencrypt", 70929088Smarkm "automatic encryption of data stream", 71029088Smarkm EncryptAutoEnc, 71129088Smarkm 0, 71229088Smarkm "automatically encrypt output" }, 71329088Smarkm { "autodecrypt", 71429088Smarkm "automatic decryption of data stream", 71529088Smarkm EncryptAutoDec, 71629088Smarkm 0, 71729088Smarkm "automatically decrypt input" }, 71829088Smarkm { "verbose_encrypt", 71929088Smarkm "Toggle verbose encryption output", 72029088Smarkm EncryptVerbose, 72129088Smarkm 0, 72229088Smarkm "print verbose encryption output" }, 72329088Smarkm { "encdebug", 72429088Smarkm "Toggle encryption debugging", 72529088Smarkm EncryptDebug, 72629088Smarkm 0, 72729088Smarkm "print encryption debugging information" }, 72829088Smarkm#endif /* ENCRYPTION */ 72929088Smarkm { "skiprc", 73029088Smarkm "don't read ~/.telnetrc file", 73129088Smarkm 0, 73229088Smarkm &skiprc, 73329088Smarkm "skip reading of ~/.telnetrc file" }, 73429088Smarkm { "binary", 73529088Smarkm "sending and receiving of binary data", 73629088Smarkm togbinary, 73729088Smarkm 0, 73829088Smarkm 0 }, 73929088Smarkm { "inbinary", 74029088Smarkm "receiving of binary data", 74129088Smarkm togrbinary, 74229088Smarkm 0, 74329088Smarkm 0 }, 74429088Smarkm { "outbinary", 74529088Smarkm "sending of binary data", 74629088Smarkm togxbinary, 74729088Smarkm 0, 74829088Smarkm 0 }, 74929088Smarkm { "crlf", 75029088Smarkm "sending carriage returns as telnet <CR><LF>", 75129088Smarkm togcrlf, 75229088Smarkm &crlf, 75329088Smarkm 0 }, 75429088Smarkm { "crmod", 75529088Smarkm "mapping of received carriage returns", 75629088Smarkm 0, 75729088Smarkm &crmod, 75829088Smarkm "map carriage return on output" }, 75929088Smarkm { "localchars", 76029088Smarkm "local recognition of certain control characters", 76129088Smarkm lclchars, 76229088Smarkm &localchars, 76329088Smarkm "recognize certain control characters" }, 76429088Smarkm { " ", "", 0 }, /* empty line */ 76529088Smarkm#if defined(unix) && defined(TN3270) 76629088Smarkm { "apitrace", 76729088Smarkm "(debugging) toggle tracing of API transactions", 76829088Smarkm 0, 76929088Smarkm &apitrace, 77029088Smarkm "trace API transactions" }, 77129088Smarkm { "cursesdata", 77229088Smarkm "(debugging) toggle printing of hexadecimal curses data", 77329088Smarkm 0, 77429088Smarkm &cursesdata, 77529088Smarkm "print hexadecimal representation of curses data" }, 77629088Smarkm#endif /* defined(unix) && defined(TN3270) */ 77729088Smarkm { "debug", 77829088Smarkm "debugging", 77929088Smarkm togdebug, 78029088Smarkm &debug, 78129088Smarkm "turn on socket level debugging" }, 78229088Smarkm { "netdata", 78329088Smarkm "printing of hexadecimal network data (debugging)", 78429088Smarkm 0, 78529088Smarkm &netdata, 78629088Smarkm "print hexadecimal representation of network traffic" }, 78729088Smarkm { "prettydump", 78829088Smarkm "output of \"netdata\" to user readable format (debugging)", 78929088Smarkm 0, 79029088Smarkm &prettydump, 79129088Smarkm "print user readable output for \"netdata\"" }, 79229088Smarkm { "options", 79329088Smarkm "viewing of options processing (debugging)", 79429088Smarkm 0, 79529088Smarkm &showoptions, 79629088Smarkm "show option processing" }, 79729088Smarkm#if defined(unix) 79829088Smarkm { "termdata", 79929088Smarkm "(debugging) toggle printing of hexadecimal terminal data", 80029088Smarkm 0, 80129088Smarkm &termdata, 80229088Smarkm "print hexadecimal representation of terminal traffic" }, 80329088Smarkm#endif /* defined(unix) */ 80429088Smarkm { "?", 80529088Smarkm 0, 80629088Smarkm togglehelp }, 80729088Smarkm { "help", 80829088Smarkm 0, 80929088Smarkm togglehelp }, 81029088Smarkm { 0 } 81129088Smarkm}; 81229088Smarkm 81329088Smarkm static int 81429088Smarkmtogglehelp() 81529088Smarkm{ 81629088Smarkm struct togglelist *c; 81729088Smarkm 81829088Smarkm for (c = Togglelist; c->name; c++) { 81929088Smarkm if (c->help) { 82029088Smarkm if (*c->help) 82129088Smarkm printf("%-15s toggle %s\n", c->name, c->help); 82229088Smarkm else 82329088Smarkm printf("\n"); 82429088Smarkm } 82529088Smarkm } 82629088Smarkm printf("\n"); 82729088Smarkm printf("%-15s %s\n", "?", "display help information"); 82829088Smarkm return 0; 82929088Smarkm} 83029088Smarkm 83129088Smarkm static void 83229088Smarkmsettogglehelp(set) 83329088Smarkm int set; 83429088Smarkm{ 83529088Smarkm struct togglelist *c; 83629088Smarkm 83729088Smarkm for (c = Togglelist; c->name; c++) { 83829088Smarkm if (c->help) { 83929088Smarkm if (*c->help) 84029088Smarkm printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 84129088Smarkm c->help); 84229088Smarkm else 84329088Smarkm printf("\n"); 84429088Smarkm } 84529088Smarkm } 84629088Smarkm} 84729088Smarkm 84829088Smarkm#define GETTOGGLE(name) (struct togglelist *) \ 84929088Smarkm genget(name, (char **) Togglelist, sizeof(struct togglelist)) 85029088Smarkm 85129088Smarkm static int 85229088Smarkmtoggle(argc, argv) 85329088Smarkm int argc; 85429088Smarkm char *argv[]; 85529088Smarkm{ 85629088Smarkm int retval = 1; 85729088Smarkm char *name; 85829088Smarkm struct togglelist *c; 85929088Smarkm 86029088Smarkm if (argc < 2) { 86129088Smarkm fprintf(stderr, 86229088Smarkm "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 86329088Smarkm return 0; 86429088Smarkm } 86529088Smarkm argc--; 86629088Smarkm argv++; 86729088Smarkm while (argc--) { 86829088Smarkm name = *argv++; 86929088Smarkm c = GETTOGGLE(name); 87029088Smarkm if (Ambiguous(c)) { 87129088Smarkm fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 87229088Smarkm name); 87329088Smarkm return 0; 87429088Smarkm } else if (c == 0) { 87529088Smarkm fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 87629088Smarkm name); 87729088Smarkm return 0; 87829088Smarkm } else { 87929088Smarkm if (c->variable) { 88029088Smarkm *c->variable = !*c->variable; /* invert it */ 88129088Smarkm if (c->actionexplanation) { 88229088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 88329088Smarkm c->actionexplanation); 88429088Smarkm } 88529088Smarkm } 88629088Smarkm if (c->handler) { 88729088Smarkm retval &= (*c->handler)(-1); 88829088Smarkm } 88929088Smarkm } 89029088Smarkm } 89129088Smarkm return retval; 89229088Smarkm} 89329088Smarkm 89429088Smarkm/* 89529088Smarkm * The following perform the "set" command. 89629088Smarkm */ 89729088Smarkm 89829088Smarkm#ifdef USE_TERMIO 89929088Smarkmstruct termio new_tc = { 0 }; 90029088Smarkm#endif 90129088Smarkm 90229088Smarkmstruct setlist { 90329088Smarkm char *name; /* name */ 90429088Smarkm char *help; /* help information */ 90529088Smarkm void (*handler)(); 90629088Smarkm cc_t *charp; /* where it is located at */ 90729088Smarkm}; 90829088Smarkm 90929088Smarkmstatic struct setlist Setlist[] = { 91029088Smarkm#ifdef KLUDGELINEMODE 91129088Smarkm { "echo", "character to toggle local echoing on/off", 0, &echoc }, 91229088Smarkm#endif 91329088Smarkm { "escape", "character to escape back to telnet command mode", 0, &escape }, 91429088Smarkm { "rlogin", "rlogin escape character", 0, &rlogin }, 91529088Smarkm { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, 91629088Smarkm { " ", "" }, 91729088Smarkm { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 91829088Smarkm { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, 91929088Smarkm { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 92029088Smarkm { "quit", "character to cause an Abort process", 0, termQuitCharp }, 92129088Smarkm { "eof", "character to cause an EOF ", 0, termEofCharp }, 92229088Smarkm { " ", "" }, 92329088Smarkm { " ", "The following are for local editing in linemode", 0, 0 }, 92429088Smarkm { "erase", "character to use to erase a character", 0, termEraseCharp }, 92529088Smarkm { "kill", "character to use to erase a line", 0, termKillCharp }, 92629088Smarkm { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 92729088Smarkm { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, 92829088Smarkm { "reprint", "character to use for line reprint", 0, termRprntCharp }, 92929088Smarkm { "worderase", "character to use to erase a word", 0, termWerasCharp }, 93029088Smarkm { "start", "character to use for XON", 0, termStartCharp }, 93129088Smarkm { "stop", "character to use for XOFF", 0, termStopCharp }, 93229088Smarkm { "forw1", "alternate end of line character", 0, termForw1Charp }, 93329088Smarkm { "forw2", "alternate end of line character", 0, termForw2Charp }, 93429088Smarkm { "ayt", "alternate AYT character", 0, termAytCharp }, 93529088Smarkm { 0 } 93629088Smarkm}; 93729088Smarkm 93829088Smarkm#if defined(CRAY) && !defined(__STDC__) 93929088Smarkm/* Work around compiler bug in pcc 4.1.5 */ 94029088Smarkm void 94129088Smarkm_setlist_init() 94229088Smarkm{ 94329088Smarkm#ifndef KLUDGELINEMODE 94429088Smarkm#define N 5 94529088Smarkm#else 94629088Smarkm#define N 6 94729088Smarkm#endif 94829088Smarkm Setlist[N+0].charp = &termFlushChar; 94929088Smarkm Setlist[N+1].charp = &termIntChar; 95029088Smarkm Setlist[N+2].charp = &termQuitChar; 95129088Smarkm Setlist[N+3].charp = &termEofChar; 95229088Smarkm Setlist[N+6].charp = &termEraseChar; 95329088Smarkm Setlist[N+7].charp = &termKillChar; 95429088Smarkm Setlist[N+8].charp = &termLiteralNextChar; 95529088Smarkm Setlist[N+9].charp = &termSuspChar; 95629088Smarkm Setlist[N+10].charp = &termRprntChar; 95729088Smarkm Setlist[N+11].charp = &termWerasChar; 95829088Smarkm Setlist[N+12].charp = &termStartChar; 95929088Smarkm Setlist[N+13].charp = &termStopChar; 96029088Smarkm Setlist[N+14].charp = &termForw1Char; 96129088Smarkm Setlist[N+15].charp = &termForw2Char; 96229088Smarkm Setlist[N+16].charp = &termAytChar; 96329088Smarkm#undef N 96429088Smarkm} 96529088Smarkm#endif /* defined(CRAY) && !defined(__STDC__) */ 96629088Smarkm 96729088Smarkm static struct setlist * 96829088Smarkmgetset(name) 96929088Smarkm char *name; 97029088Smarkm{ 97129088Smarkm return (struct setlist *) 97229088Smarkm genget(name, (char **) Setlist, sizeof(struct setlist)); 97329088Smarkm} 97429088Smarkm 97529088Smarkm void 97629088Smarkmset_escape_char(s) 97729088Smarkm char *s; 97829088Smarkm{ 97929088Smarkm if (rlogin != _POSIX_VDISABLE) { 98029088Smarkm rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 98129088Smarkm printf("Telnet rlogin escape character is '%s'.\n", 98229088Smarkm control(rlogin)); 98329088Smarkm } else { 98429088Smarkm escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 98529088Smarkm printf("Telnet escape character is '%s'.\n", control(escape)); 98629088Smarkm } 98729088Smarkm} 98829088Smarkm 98929088Smarkm static int 99029088Smarkmsetcmd(argc, argv) 99129088Smarkm int argc; 99229088Smarkm char *argv[]; 99329088Smarkm{ 99429088Smarkm int value; 99529088Smarkm struct setlist *ct; 99629088Smarkm struct togglelist *c; 99729088Smarkm 99829088Smarkm if (argc < 2 || argc > 3) { 99929088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 100029088Smarkm return 0; 100129088Smarkm } 100229088Smarkm if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 100329088Smarkm for (ct = Setlist; ct->name; ct++) 100429088Smarkm printf("%-15s %s\n", ct->name, ct->help); 100529088Smarkm printf("\n"); 100629088Smarkm settogglehelp(1); 100729088Smarkm printf("%-15s %s\n", "?", "display help information"); 100829088Smarkm return 0; 100929088Smarkm } 101029088Smarkm 101129088Smarkm ct = getset(argv[1]); 101229088Smarkm if (ct == 0) { 101329088Smarkm c = GETTOGGLE(argv[1]); 101429088Smarkm if (c == 0) { 101529088Smarkm fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 101629088Smarkm argv[1]); 101729088Smarkm return 0; 101829088Smarkm } else if (Ambiguous(c)) { 101929088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 102029088Smarkm argv[1]); 102129088Smarkm return 0; 102229088Smarkm } 102329088Smarkm if (c->variable) { 102429088Smarkm if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 102529088Smarkm *c->variable = 1; 102629088Smarkm else if (strcmp("off", argv[2]) == 0) 102729088Smarkm *c->variable = 0; 102829088Smarkm else { 102929088Smarkm printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 103029088Smarkm return 0; 103129088Smarkm } 103229088Smarkm if (c->actionexplanation) { 103329088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 103429088Smarkm c->actionexplanation); 103529088Smarkm } 103629088Smarkm } 103729088Smarkm if (c->handler) 103829088Smarkm (*c->handler)(1); 103929088Smarkm } else if (argc != 3) { 104029088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 104129088Smarkm return 0; 104229088Smarkm } else if (Ambiguous(ct)) { 104329088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 104429088Smarkm argv[1]); 104529088Smarkm return 0; 104629088Smarkm } else if (ct->handler) { 104729088Smarkm (*ct->handler)(argv[2]); 104829088Smarkm printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 104929088Smarkm } else { 105029088Smarkm if (strcmp("off", argv[2])) { 105129088Smarkm value = special(argv[2]); 105229088Smarkm } else { 105329088Smarkm value = _POSIX_VDISABLE; 105429088Smarkm } 105529088Smarkm *(ct->charp) = (cc_t)value; 105629088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 105729088Smarkm } 105829088Smarkm slc_check(); 105929088Smarkm return 1; 106029088Smarkm} 106129088Smarkm 106229088Smarkm static int 106329088Smarkmunsetcmd(argc, argv) 106429088Smarkm int argc; 106529088Smarkm char *argv[]; 106629088Smarkm{ 106729088Smarkm struct setlist *ct; 106829088Smarkm struct togglelist *c; 106929088Smarkm register char *name; 107029088Smarkm 107129088Smarkm if (argc < 2) { 107229088Smarkm fprintf(stderr, 107329088Smarkm "Need an argument to 'unset' command. 'unset ?' for help.\n"); 107429088Smarkm return 0; 107529088Smarkm } 107629088Smarkm if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 107729088Smarkm for (ct = Setlist; ct->name; ct++) 107829088Smarkm printf("%-15s %s\n", ct->name, ct->help); 107929088Smarkm printf("\n"); 108029088Smarkm settogglehelp(0); 108129088Smarkm printf("%-15s %s\n", "?", "display help information"); 108229088Smarkm return 0; 108329088Smarkm } 108429088Smarkm 108529088Smarkm argc--; 108629088Smarkm argv++; 108729088Smarkm while (argc--) { 108829088Smarkm name = *argv++; 108929088Smarkm ct = getset(name); 109029088Smarkm if (ct == 0) { 109129088Smarkm c = GETTOGGLE(name); 109229088Smarkm if (c == 0) { 109329088Smarkm fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 109429088Smarkm name); 109529088Smarkm return 0; 109629088Smarkm } else if (Ambiguous(c)) { 109729088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 109829088Smarkm name); 109929088Smarkm return 0; 110029088Smarkm } 110129088Smarkm if (c->variable) { 110229088Smarkm *c->variable = 0; 110329088Smarkm if (c->actionexplanation) { 110429088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 110529088Smarkm c->actionexplanation); 110629088Smarkm } 110729088Smarkm } 110829088Smarkm if (c->handler) 110929088Smarkm (*c->handler)(0); 111029088Smarkm } else if (Ambiguous(ct)) { 111129088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 111229088Smarkm name); 111329088Smarkm return 0; 111429088Smarkm } else if (ct->handler) { 111529088Smarkm (*ct->handler)(0); 111629088Smarkm printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 111729088Smarkm } else { 111829088Smarkm *(ct->charp) = _POSIX_VDISABLE; 111929088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 112029088Smarkm } 112129088Smarkm } 112229088Smarkm return 1; 112329088Smarkm} 112429088Smarkm 112529088Smarkm/* 112629088Smarkm * The following are the data structures and routines for the 112729088Smarkm * 'mode' command. 112829088Smarkm */ 112929088Smarkm#ifdef KLUDGELINEMODE 113029088Smarkmextern int kludgelinemode; 113129088Smarkm 113247973Sru static int 113329088Smarkmdokludgemode() 113429088Smarkm{ 113529088Smarkm kludgelinemode = 1; 113629088Smarkm send_wont(TELOPT_LINEMODE, 1); 113729088Smarkm send_dont(TELOPT_SGA, 1); 113829088Smarkm send_dont(TELOPT_ECHO, 1); 113949861Snsayer return 1; 114029088Smarkm} 114129088Smarkm#endif 114229088Smarkm 114329088Smarkm static int 114429088Smarkmdolinemode() 114529088Smarkm{ 114629088Smarkm#ifdef KLUDGELINEMODE 114729088Smarkm if (kludgelinemode) 114829088Smarkm send_dont(TELOPT_SGA, 1); 114929088Smarkm#endif 115029088Smarkm send_will(TELOPT_LINEMODE, 1); 115129088Smarkm send_dont(TELOPT_ECHO, 1); 115229088Smarkm return 1; 115329088Smarkm} 115429088Smarkm 115529088Smarkm static int 115629088Smarkmdocharmode() 115729088Smarkm{ 115829088Smarkm#ifdef KLUDGELINEMODE 115929088Smarkm if (kludgelinemode) 116029088Smarkm send_do(TELOPT_SGA, 1); 116129088Smarkm else 116229088Smarkm#endif 116329088Smarkm send_wont(TELOPT_LINEMODE, 1); 116429088Smarkm send_do(TELOPT_ECHO, 1); 116529088Smarkm return 1; 116629088Smarkm} 116729088Smarkm 116829088Smarkm static int 116929088Smarkmdolmmode(bit, on) 117029088Smarkm int bit, on; 117129088Smarkm{ 117229088Smarkm unsigned char c; 117329088Smarkm extern int linemode; 117429088Smarkm 117529088Smarkm if (my_want_state_is_wont(TELOPT_LINEMODE)) { 117629088Smarkm printf("?Need to have LINEMODE option enabled first.\n"); 117729088Smarkm printf("'mode ?' for help.\n"); 117829088Smarkm return 0; 117929088Smarkm } 118029088Smarkm 118129088Smarkm if (on) 118229088Smarkm c = (linemode | bit); 118329088Smarkm else 118429088Smarkm c = (linemode & ~bit); 118529088Smarkm lm_mode(&c, 1, 1); 118629088Smarkm return 1; 118729088Smarkm} 118829088Smarkm 118929088Smarkm int 119029181Smarkmsetmod(bit) 119129088Smarkm{ 119229088Smarkm return dolmmode(bit, 1); 119329088Smarkm} 119429088Smarkm 119529088Smarkm int 119629088Smarkmclearmode(bit) 119729088Smarkm{ 119829088Smarkm return dolmmode(bit, 0); 119929088Smarkm} 120029088Smarkm 120129088Smarkmstruct modelist { 120229088Smarkm char *name; /* command name */ 120329088Smarkm char *help; /* help string */ 120429088Smarkm int (*handler)(); /* routine which executes command */ 120529088Smarkm int needconnect; /* Do we need to be connected to execute? */ 120629088Smarkm int arg1; 120729088Smarkm}; 120829088Smarkm 120929088Smarkmextern int modehelp(); 121029088Smarkm 121129088Smarkmstatic struct modelist ModeList[] = { 121229088Smarkm { "character", "Disable LINEMODE option", docharmode, 1 }, 121329088Smarkm#ifdef KLUDGELINEMODE 121429088Smarkm { "", "(or disable obsolete line-by-line mode)", 0 }, 121529088Smarkm#endif 121629088Smarkm { "line", "Enable LINEMODE option", dolinemode, 1 }, 121729088Smarkm#ifdef KLUDGELINEMODE 121829088Smarkm { "", "(or enable obsolete line-by-line mode)", 0 }, 121929088Smarkm#endif 122029088Smarkm { "", "", 0 }, 122129088Smarkm { "", "These require the LINEMODE option to be enabled", 0 }, 122229181Smarkm { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, 122329181Smarkm { "+isig", 0, setmod, 1, MODE_TRAPSIG }, 122429088Smarkm { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 122529181Smarkm { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, 122629181Smarkm { "+edit", 0, setmod, 1, MODE_EDIT }, 122729088Smarkm { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 122829181Smarkm { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, 122929181Smarkm { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, 123029088Smarkm { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 123129181Smarkm { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, 123229181Smarkm { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, 123329088Smarkm { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 123429088Smarkm { "help", 0, modehelp, 0 }, 123529088Smarkm#ifdef KLUDGELINEMODE 123629088Smarkm { "kludgeline", 0, dokludgemode, 1 }, 123729088Smarkm#endif 123829088Smarkm { "", "", 0 }, 123929088Smarkm { "?", "Print help information", modehelp, 0 }, 124029088Smarkm { 0 }, 124129088Smarkm}; 124229088Smarkm 124329088Smarkm 124429088Smarkm int 124529088Smarkmmodehelp() 124629088Smarkm{ 124729088Smarkm struct modelist *mt; 124829088Smarkm 124929088Smarkm printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 125029088Smarkm for (mt = ModeList; mt->name; mt++) { 125129088Smarkm if (mt->help) { 125229088Smarkm if (*mt->help) 125329088Smarkm printf("%-15s %s\n", mt->name, mt->help); 125429088Smarkm else 125529088Smarkm printf("\n"); 125629088Smarkm } 125729088Smarkm } 125829088Smarkm return 0; 125929088Smarkm} 126029088Smarkm 126129088Smarkm#define GETMODECMD(name) (struct modelist *) \ 126229088Smarkm genget(name, (char **) ModeList, sizeof(struct modelist)) 126329088Smarkm 126429088Smarkm static int 126529088Smarkmmodecmd(argc, argv) 126629088Smarkm int argc; 126729088Smarkm char *argv[]; 126829088Smarkm{ 126929088Smarkm struct modelist *mt; 127029088Smarkm 127129088Smarkm if (argc != 2) { 127229088Smarkm printf("'mode' command requires an argument\n"); 127329088Smarkm printf("'mode ?' for help.\n"); 127429088Smarkm } else if ((mt = GETMODECMD(argv[1])) == 0) { 127529088Smarkm fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 127629088Smarkm } else if (Ambiguous(mt)) { 127729088Smarkm fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 127829088Smarkm } else if (mt->needconnect && !connected) { 127929088Smarkm printf("?Need to be connected first.\n"); 128029088Smarkm printf("'mode ?' for help.\n"); 128129088Smarkm } else if (mt->handler) { 128229088Smarkm return (*mt->handler)(mt->arg1); 128329088Smarkm } 128429088Smarkm return 0; 128529088Smarkm} 128629088Smarkm 128729088Smarkm/* 128829088Smarkm * The following data structures and routines implement the 128929088Smarkm * "display" command. 129029088Smarkm */ 129129088Smarkm 129229088Smarkm static int 129329088Smarkmdisplay(argc, argv) 129429088Smarkm int argc; 129529088Smarkm char *argv[]; 129629088Smarkm{ 129729088Smarkm struct togglelist *tl; 129829088Smarkm struct setlist *sl; 129929088Smarkm 130029088Smarkm#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 130129088Smarkm if (*tl->variable) { \ 130229088Smarkm printf("will"); \ 130329088Smarkm } else { \ 130429088Smarkm printf("won't"); \ 130529088Smarkm } \ 130629088Smarkm printf(" %s.\n", tl->actionexplanation); \ 130729088Smarkm } 130829088Smarkm 130929088Smarkm#define doset(sl) if (sl->name && *sl->name != ' ') { \ 131029088Smarkm if (sl->handler == 0) \ 131129088Smarkm printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 131229088Smarkm else \ 131329088Smarkm printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 131429088Smarkm } 131529088Smarkm 131629088Smarkm if (argc == 1) { 131729088Smarkm for (tl = Togglelist; tl->name; tl++) { 131829088Smarkm dotog(tl); 131929088Smarkm } 132029088Smarkm printf("\n"); 132129088Smarkm for (sl = Setlist; sl->name; sl++) { 132229088Smarkm doset(sl); 132329088Smarkm } 132429088Smarkm } else { 132529088Smarkm int i; 132629088Smarkm 132729088Smarkm for (i = 1; i < argc; i++) { 132829088Smarkm sl = getset(argv[i]); 132929088Smarkm tl = GETTOGGLE(argv[i]); 133029088Smarkm if (Ambiguous(sl) || Ambiguous(tl)) { 133129088Smarkm printf("?Ambiguous argument '%s'.\n", argv[i]); 133229088Smarkm return 0; 133329088Smarkm } else if (!sl && !tl) { 133429088Smarkm printf("?Unknown argument '%s'.\n", argv[i]); 133529088Smarkm return 0; 133629088Smarkm } else { 133729088Smarkm if (tl) { 133829088Smarkm dotog(tl); 133929088Smarkm } 134029088Smarkm if (sl) { 134129088Smarkm doset(sl); 134229088Smarkm } 134329088Smarkm } 134429088Smarkm } 134529088Smarkm } 134629088Smarkm/*@*/optionstatus(); 134729088Smarkm#ifdef ENCRYPTION 134829088Smarkm EncryptStatus(); 134929088Smarkm#endif /* ENCRYPTION */ 135029088Smarkm return 1; 135129088Smarkm#undef doset 135229088Smarkm#undef dotog 135329088Smarkm} 135429088Smarkm 135529088Smarkm/* 135629088Smarkm * The following are the data structures, and many of the routines, 135729088Smarkm * relating to command processing. 135829088Smarkm */ 135929088Smarkm 136029088Smarkm/* 136129088Smarkm * Set the escape character. 136229088Smarkm */ 136329088Smarkm static int 136429088Smarkmsetescape(argc, argv) 136529088Smarkm int argc; 136629088Smarkm char *argv[]; 136729088Smarkm{ 136829088Smarkm register char *arg; 136929088Smarkm char buf[50]; 137029088Smarkm 137129088Smarkm printf( 137229088Smarkm "Deprecated usage - please use 'set escape%s%s' in the future.\n", 137329088Smarkm (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 137429088Smarkm if (argc > 2) 137529088Smarkm arg = argv[1]; 137629088Smarkm else { 137729088Smarkm printf("new escape character: "); 137829088Smarkm (void) fgets(buf, sizeof(buf), stdin); 137929088Smarkm arg = buf; 138029088Smarkm } 138129088Smarkm if (arg[0] != '\0') 138229088Smarkm escape = arg[0]; 138329088Smarkm if (!In3270) { 138429088Smarkm printf("Escape character is '%s'.\n", control(escape)); 138529088Smarkm } 138629088Smarkm (void) fflush(stdout); 138729088Smarkm return 1; 138829088Smarkm} 138929088Smarkm 139029088Smarkm /*VARARGS*/ 139129088Smarkm static int 139229088Smarkmtogcrmod() 139329088Smarkm{ 139429088Smarkm crmod = !crmod; 139529088Smarkm printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 139629088Smarkm printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 139729088Smarkm (void) fflush(stdout); 139829088Smarkm return 1; 139929088Smarkm} 140029088Smarkm 140129088Smarkm /*VARARGS*/ 140229088Smarkm int 140329088Smarkmsuspend() 140429088Smarkm{ 140529088Smarkm#ifdef SIGTSTP 140629088Smarkm setcommandmode(); 140729088Smarkm { 140829088Smarkm long oldrows, oldcols, newrows, newcols, err; 140929088Smarkm 141029088Smarkm err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 141129088Smarkm (void) kill(0, SIGTSTP); 141229088Smarkm /* 141329088Smarkm * If we didn't get the window size before the SUSPEND, but we 141429088Smarkm * can get them now (?), then send the NAWS to make sure that 141529088Smarkm * we are set up for the right window size. 141629088Smarkm */ 141729088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 141829088Smarkm (err || ((oldrows != newrows) || (oldcols != newcols)))) { 141929088Smarkm sendnaws(); 142029088Smarkm } 142129088Smarkm } 142229088Smarkm /* reget parameters in case they were changed */ 142329088Smarkm TerminalSaveState(); 142429088Smarkm setconnmode(0); 142529088Smarkm#else 142629088Smarkm printf("Suspend is not supported. Try the '!' command instead\n"); 142729088Smarkm#endif 142829088Smarkm return 1; 142929088Smarkm} 143029088Smarkm 143129088Smarkm#if !defined(TN3270) 143229088Smarkm /*ARGSUSED*/ 143329088Smarkm int 143429088Smarkmshell(argc, argv) 143529088Smarkm int argc; 143629088Smarkm char *argv[]; 143729088Smarkm{ 143829088Smarkm long oldrows, oldcols, newrows, newcols, err; 143929088Smarkm 144029088Smarkm setcommandmode(); 144129088Smarkm 144229088Smarkm err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 144329088Smarkm switch(vfork()) { 144429088Smarkm case -1: 144529088Smarkm perror("Fork failed\n"); 144629088Smarkm break; 144729088Smarkm 144829088Smarkm case 0: 144929088Smarkm { 145029088Smarkm /* 145129088Smarkm * Fire up the shell in the child. 145229088Smarkm */ 145329088Smarkm register char *shellp, *shellname; 145429088Smarkm extern char *strrchr(); 145529088Smarkm 145629088Smarkm shellp = getenv("SHELL"); 145729088Smarkm if (shellp == NULL) 145829088Smarkm shellp = "/bin/sh"; 145929088Smarkm if ((shellname = strrchr(shellp, '/')) == 0) 146029088Smarkm shellname = shellp; 146129088Smarkm else 146229088Smarkm shellname++; 146329088Smarkm if (argc > 1) 146429088Smarkm execl(shellp, shellname, "-c", &saveline[1], 0); 146529088Smarkm else 146629088Smarkm execl(shellp, shellname, 0); 146729088Smarkm perror("Execl"); 146829088Smarkm _exit(1); 146929088Smarkm } 147029088Smarkm default: 147129088Smarkm (void)wait((int *)0); /* Wait for the shell to complete */ 147229088Smarkm 147329088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 147429088Smarkm (err || ((oldrows != newrows) || (oldcols != newcols)))) { 147529088Smarkm sendnaws(); 147629088Smarkm } 147729088Smarkm break; 147829088Smarkm } 147929088Smarkm return 1; 148029088Smarkm} 148129088Smarkm#else /* !defined(TN3270) */ 148229088Smarkmextern int shell(); 148329088Smarkm#endif /* !defined(TN3270) */ 148429088Smarkm 148529088Smarkm /*VARARGS*/ 148629181Smarkm static int 148729088Smarkmbye(argc, argv) 148829088Smarkm int argc; /* Number of arguments */ 148929088Smarkm char *argv[]; /* arguments */ 149029088Smarkm{ 149129088Smarkm extern int resettermname; 149229088Smarkm 149329088Smarkm if (connected) { 149429088Smarkm (void) shutdown(net, 2); 149529088Smarkm printf("Connection closed.\n"); 149629088Smarkm (void) NetClose(net); 149729088Smarkm connected = 0; 149829088Smarkm resettermname = 1; 149929088Smarkm#if defined(AUTHENTICATION) || defined(ENCRYPTION) 150029088Smarkm auth_encrypt_connect(connected); 150129088Smarkm#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 150229088Smarkm /* reset options */ 150329088Smarkm tninit(); 150429088Smarkm#if defined(TN3270) 150529088Smarkm SetIn3270(); /* Get out of 3270 mode */ 150629088Smarkm#endif /* defined(TN3270) */ 150729088Smarkm } 150829088Smarkm if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 150929088Smarkm longjmp(toplevel, 1); 151029088Smarkm /* NOTREACHED */ 151129088Smarkm } 151229088Smarkm return 1; /* Keep lint, etc., happy */ 151329088Smarkm} 151429088Smarkm 151529088Smarkm/*VARARGS*/ 151629181Smarkm int 151729088Smarkmquit() 151829088Smarkm{ 151929088Smarkm (void) call(bye, "bye", "fromquit", 0); 152029088Smarkm Exit(0); 152129088Smarkm /*NOTREACHED*/ 152229088Smarkm} 152329088Smarkm 152429088Smarkm/*VARARGS*/ 152529088Smarkm int 152629088Smarkmlogout() 152729088Smarkm{ 152829088Smarkm send_do(TELOPT_LOGOUT, 1); 152929088Smarkm (void) netflush(); 153029088Smarkm return 1; 153129088Smarkm} 153229088Smarkm 153329088Smarkm 153429088Smarkm/* 153529088Smarkm * The SLC command. 153629088Smarkm */ 153729088Smarkm 153829088Smarkmstruct slclist { 153929088Smarkm char *name; 154029088Smarkm char *help; 154129088Smarkm void (*handler)(); 154229088Smarkm int arg; 154329088Smarkm}; 154429088Smarkm 154529088Smarkmstatic void slc_help(); 154629088Smarkm 154729088Smarkmstruct slclist SlcList[] = { 154829088Smarkm { "export", "Use local special character definitions", 154929088Smarkm slc_mode_export, 0 }, 155029088Smarkm { "import", "Use remote special character definitions", 155129088Smarkm slc_mode_import, 1 }, 155229088Smarkm { "check", "Verify remote special character definitions", 155329088Smarkm slc_mode_import, 0 }, 155429088Smarkm { "help", 0, slc_help, 0 }, 155529088Smarkm { "?", "Print help information", slc_help, 0 }, 155629088Smarkm { 0 }, 155729088Smarkm}; 155829088Smarkm 155929088Smarkm static void 156029088Smarkmslc_help() 156129088Smarkm{ 156229088Smarkm struct slclist *c; 156329088Smarkm 156429088Smarkm for (c = SlcList; c->name; c++) { 156529088Smarkm if (c->help) { 156629088Smarkm if (*c->help) 156729088Smarkm printf("%-15s %s\n", c->name, c->help); 156829088Smarkm else 156929088Smarkm printf("\n"); 157029088Smarkm } 157129088Smarkm } 157229088Smarkm} 157329088Smarkm 157429088Smarkm static struct slclist * 157529088Smarkmgetslc(name) 157629088Smarkm char *name; 157729088Smarkm{ 157829088Smarkm return (struct slclist *) 157929088Smarkm genget(name, (char **) SlcList, sizeof(struct slclist)); 158029088Smarkm} 158129088Smarkm 158229181Smarkm static int 158329088Smarkmslccmd(argc, argv) 158429088Smarkm int argc; 158529088Smarkm char *argv[]; 158629088Smarkm{ 158729088Smarkm struct slclist *c; 158829088Smarkm 158929088Smarkm if (argc != 2) { 159029088Smarkm fprintf(stderr, 159129088Smarkm "Need an argument to 'slc' command. 'slc ?' for help.\n"); 159229088Smarkm return 0; 159329088Smarkm } 159429088Smarkm c = getslc(argv[1]); 159529088Smarkm if (c == 0) { 159629088Smarkm fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 159729088Smarkm argv[1]); 159829088Smarkm return 0; 159929088Smarkm } 160029088Smarkm if (Ambiguous(c)) { 160129088Smarkm fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 160229088Smarkm argv[1]); 160329088Smarkm return 0; 160429088Smarkm } 160529088Smarkm (*c->handler)(c->arg); 160629088Smarkm slcstate(); 160729088Smarkm return 1; 160829088Smarkm} 160929088Smarkm 161029088Smarkm/* 161129088Smarkm * The ENVIRON command. 161229088Smarkm */ 161329088Smarkm 161429088Smarkmstruct envlist { 161529088Smarkm char *name; 161629088Smarkm char *help; 161729088Smarkm void (*handler)(); 161829088Smarkm int narg; 161929088Smarkm}; 162029088Smarkm 162129088Smarkmextern struct env_lst * 162229088Smarkm env_define P((unsigned char *, unsigned char *)); 162329088Smarkmextern void 162429088Smarkm env_undefine P((unsigned char *)), 162529088Smarkm env_export P((unsigned char *)), 162629088Smarkm env_unexport P((unsigned char *)), 162729088Smarkm env_send P((unsigned char *)), 162829088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 162929088Smarkm env_varval P((unsigned char *)), 163029088Smarkm#endif 163129088Smarkm env_list P((void)); 163229088Smarkmstatic void 163329088Smarkm env_help P((void)); 163429088Smarkm 163529088Smarkmstruct envlist EnvList[] = { 163629088Smarkm { "define", "Define an environment variable", 163729088Smarkm (void (*)())env_define, 2 }, 163829088Smarkm { "undefine", "Undefine an environment variable", 163929088Smarkm env_undefine, 1 }, 164029088Smarkm { "export", "Mark an environment variable for automatic export", 164129088Smarkm env_export, 1 }, 164229088Smarkm { "unexport", "Don't mark an environment variable for automatic export", 164329088Smarkm env_unexport, 1 }, 164429088Smarkm { "send", "Send an environment variable", env_send, 1 }, 164529088Smarkm { "list", "List the current environment variables", 164629088Smarkm env_list, 0 }, 164729088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 164829088Smarkm { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 164929088Smarkm env_varval, 1 }, 165029088Smarkm#endif 165129088Smarkm { "help", 0, env_help, 0 }, 165229088Smarkm { "?", "Print help information", env_help, 0 }, 165329088Smarkm { 0 }, 165429088Smarkm}; 165529088Smarkm 165629088Smarkm static void 165729088Smarkmenv_help() 165829088Smarkm{ 165929088Smarkm struct envlist *c; 166029088Smarkm 166129088Smarkm for (c = EnvList; c->name; c++) { 166229088Smarkm if (c->help) { 166329088Smarkm if (*c->help) 166429088Smarkm printf("%-15s %s\n", c->name, c->help); 166529088Smarkm else 166629088Smarkm printf("\n"); 166729088Smarkm } 166829088Smarkm } 166929088Smarkm} 167029088Smarkm 167129088Smarkm static struct envlist * 167229088Smarkmgetenvcmd(name) 167329088Smarkm char *name; 167429088Smarkm{ 167529088Smarkm return (struct envlist *) 167629088Smarkm genget(name, (char **) EnvList, sizeof(struct envlist)); 167729088Smarkm} 167829088Smarkm 167929181Smarkm int 168029088Smarkmenv_cmd(argc, argv) 168129088Smarkm int argc; 168229088Smarkm char *argv[]; 168329088Smarkm{ 168429088Smarkm struct envlist *c; 168529088Smarkm 168629088Smarkm if (argc < 2) { 168729088Smarkm fprintf(stderr, 168829088Smarkm "Need an argument to 'environ' command. 'environ ?' for help.\n"); 168929088Smarkm return 0; 169029088Smarkm } 169129088Smarkm c = getenvcmd(argv[1]); 169229088Smarkm if (c == 0) { 169329088Smarkm fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 169429088Smarkm argv[1]); 169529088Smarkm return 0; 169629088Smarkm } 169729088Smarkm if (Ambiguous(c)) { 169829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 169929088Smarkm argv[1]); 170029088Smarkm return 0; 170129088Smarkm } 170229088Smarkm if (c->narg + 2 != argc) { 170329088Smarkm fprintf(stderr, 170429088Smarkm "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 170529088Smarkm c->narg < argc + 2 ? "only " : "", 170629088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 170729088Smarkm return 0; 170829088Smarkm } 170929088Smarkm (*c->handler)(argv[2], argv[3]); 171029088Smarkm return 1; 171129088Smarkm} 171229088Smarkm 171329088Smarkmstruct env_lst { 171429088Smarkm struct env_lst *next; /* pointer to next structure */ 171529088Smarkm struct env_lst *prev; /* pointer to previous structure */ 171629088Smarkm unsigned char *var; /* pointer to variable name */ 171729088Smarkm unsigned char *value; /* pointer to variable value */ 171829088Smarkm int export; /* 1 -> export with default list of variables */ 171929088Smarkm int welldefined; /* A well defined variable */ 172029088Smarkm}; 172129088Smarkm 172229088Smarkmstruct env_lst envlisthead; 172329088Smarkm 172429088Smarkm struct env_lst * 172529088Smarkmenv_find(var) 172629088Smarkm unsigned char *var; 172729088Smarkm{ 172829088Smarkm register struct env_lst *ep; 172929088Smarkm 173029088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 173129088Smarkm if (strcmp((char *)ep->var, (char *)var) == 0) 173229088Smarkm return(ep); 173329088Smarkm } 173429088Smarkm return(NULL); 173529088Smarkm} 173629088Smarkm 173729088Smarkm void 173829088Smarkmenv_init() 173929088Smarkm{ 174029088Smarkm extern char **environ; 174129088Smarkm register char **epp, *cp; 174229088Smarkm register struct env_lst *ep; 174329088Smarkm extern char *strchr(); 174429088Smarkm 174529088Smarkm for (epp = environ; *epp; epp++) { 174629181Smarkm if ((cp = strchr(*epp, '='))) { 174729088Smarkm *cp = '\0'; 174829088Smarkm ep = env_define((unsigned char *)*epp, 174929088Smarkm (unsigned char *)cp+1); 175029088Smarkm ep->export = 0; 175129088Smarkm *cp = '='; 175229088Smarkm } 175329088Smarkm } 175429088Smarkm /* 175529088Smarkm * Special case for DISPLAY variable. If it is ":0.0" or 175629088Smarkm * "unix:0.0", we have to get rid of "unix" and insert our 175729088Smarkm * hostname. 175829088Smarkm */ 175929088Smarkm if ((ep = env_find("DISPLAY")) 176029088Smarkm && ((*ep->value == ':') 176129088Smarkm || (strncmp((char *)ep->value, "unix:", 5) == 0))) { 176229088Smarkm char hbuf[256+1]; 176329088Smarkm char *cp2 = strchr((char *)ep->value, ':'); 176429088Smarkm 176529088Smarkm gethostname(hbuf, 256); 176629088Smarkm hbuf[256] = '\0'; 176729088Smarkm cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); 176829088Smarkm sprintf((char *)cp, "%s%s", hbuf, cp2); 176929088Smarkm free(ep->value); 177029088Smarkm ep->value = (unsigned char *)cp; 177129088Smarkm } 177229088Smarkm /* 177329088Smarkm * If USER is not defined, but LOGNAME is, then add 177429088Smarkm * USER with the value from LOGNAME. By default, we 177529088Smarkm * don't export the USER variable. 177629088Smarkm */ 177729088Smarkm if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { 177829088Smarkm env_define((unsigned char *)"USER", ep->value); 177929088Smarkm env_unexport((unsigned char *)"USER"); 178029088Smarkm } 178129088Smarkm env_export((unsigned char *)"DISPLAY"); 178229088Smarkm env_export((unsigned char *)"PRINTER"); 178329088Smarkm} 178429088Smarkm 178529088Smarkm struct env_lst * 178629088Smarkmenv_define(var, value) 178729088Smarkm unsigned char *var, *value; 178829088Smarkm{ 178929088Smarkm register struct env_lst *ep; 179029088Smarkm 179129181Smarkm if ((ep = env_find(var))) { 179229088Smarkm if (ep->var) 179329088Smarkm free(ep->var); 179429088Smarkm if (ep->value) 179529088Smarkm free(ep->value); 179629088Smarkm } else { 179729088Smarkm ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 179829088Smarkm ep->next = envlisthead.next; 179929088Smarkm envlisthead.next = ep; 180029088Smarkm ep->prev = &envlisthead; 180129088Smarkm if (ep->next) 180229088Smarkm ep->next->prev = ep; 180329088Smarkm } 180429088Smarkm ep->welldefined = opt_welldefined(var); 180529088Smarkm ep->export = 1; 180629088Smarkm ep->var = (unsigned char *)strdup((char *)var); 180729088Smarkm ep->value = (unsigned char *)strdup((char *)value); 180829088Smarkm return(ep); 180929088Smarkm} 181029088Smarkm 181129088Smarkm void 181229088Smarkmenv_undefine(var) 181329088Smarkm unsigned char *var; 181429088Smarkm{ 181529088Smarkm register struct env_lst *ep; 181629088Smarkm 181729181Smarkm if ((ep = env_find(var))) { 181829088Smarkm ep->prev->next = ep->next; 181929088Smarkm if (ep->next) 182029088Smarkm ep->next->prev = ep->prev; 182129088Smarkm if (ep->var) 182229088Smarkm free(ep->var); 182329088Smarkm if (ep->value) 182429088Smarkm free(ep->value); 182529088Smarkm free(ep); 182629088Smarkm } 182729088Smarkm} 182829088Smarkm 182929088Smarkm void 183029088Smarkmenv_export(var) 183129088Smarkm unsigned char *var; 183229088Smarkm{ 183329088Smarkm register struct env_lst *ep; 183429088Smarkm 183529181Smarkm if ((ep = env_find(var))) 183629088Smarkm ep->export = 1; 183729088Smarkm} 183829088Smarkm 183929088Smarkm void 184029088Smarkmenv_unexport(var) 184129088Smarkm unsigned char *var; 184229088Smarkm{ 184329088Smarkm register struct env_lst *ep; 184429088Smarkm 184529181Smarkm if ((ep = env_find(var))) 184629088Smarkm ep->export = 0; 184729088Smarkm} 184829088Smarkm 184929088Smarkm void 185029088Smarkmenv_send(var) 185129088Smarkm unsigned char *var; 185229088Smarkm{ 185329088Smarkm register struct env_lst *ep; 185429088Smarkm 185529088Smarkm if (my_state_is_wont(TELOPT_NEW_ENVIRON) 185629088Smarkm#ifdef OLD_ENVIRON 185729088Smarkm && my_state_is_wont(TELOPT_OLD_ENVIRON) 185829088Smarkm#endif 185929088Smarkm ) { 186029088Smarkm fprintf(stderr, 186129088Smarkm "Cannot send '%s': Telnet ENVIRON option not enabled\n", 186229088Smarkm var); 186329088Smarkm return; 186429088Smarkm } 186529088Smarkm ep = env_find(var); 186629088Smarkm if (ep == 0) { 186729088Smarkm fprintf(stderr, "Cannot send '%s': variable not defined\n", 186829088Smarkm var); 186929088Smarkm return; 187029088Smarkm } 187129088Smarkm env_opt_start_info(); 187229088Smarkm env_opt_add(ep->var); 187329088Smarkm env_opt_end(0); 187429088Smarkm} 187529088Smarkm 187629088Smarkm void 187729088Smarkmenv_list() 187829088Smarkm{ 187929088Smarkm register struct env_lst *ep; 188029088Smarkm 188129088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 188229088Smarkm printf("%c %-20s %s\n", ep->export ? '*' : ' ', 188329088Smarkm ep->var, ep->value); 188429088Smarkm } 188529088Smarkm} 188629088Smarkm 188729088Smarkm unsigned char * 188829088Smarkmenv_default(init, welldefined) 188929088Smarkm int init; 189029088Smarkm{ 189129088Smarkm static struct env_lst *nep = NULL; 189229088Smarkm 189329088Smarkm if (init) { 189429088Smarkm nep = &envlisthead; 189529181Smarkm return(NULL); 189629088Smarkm } 189729088Smarkm if (nep) { 189829181Smarkm while ((nep = nep->next)) { 189929088Smarkm if (nep->export && (nep->welldefined == welldefined)) 190029088Smarkm return(nep->var); 190129088Smarkm } 190229088Smarkm } 190329088Smarkm return(NULL); 190429088Smarkm} 190529088Smarkm 190629088Smarkm unsigned char * 190729088Smarkmenv_getvalue(var) 190829088Smarkm unsigned char *var; 190929088Smarkm{ 191029088Smarkm register struct env_lst *ep; 191129088Smarkm 191229181Smarkm if ((ep = env_find(var))) 191329088Smarkm return(ep->value); 191429088Smarkm return(NULL); 191529088Smarkm} 191629088Smarkm 191729088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 191829088Smarkm void 191929088Smarkmenv_varval(what) 192029088Smarkm unsigned char *what; 192129088Smarkm{ 192229088Smarkm extern int old_env_var, old_env_value, env_auto; 192329088Smarkm int len = strlen((char *)what); 192429088Smarkm 192529088Smarkm if (len == 0) 192629088Smarkm goto unknown; 192729088Smarkm 192829088Smarkm if (strncasecmp((char *)what, "status", len) == 0) { 192929088Smarkm if (env_auto) 193029088Smarkm printf("%s%s", "VAR and VALUE are/will be ", 193129088Smarkm "determined automatically\n"); 193229088Smarkm if (old_env_var == OLD_ENV_VAR) 193329088Smarkm printf("VAR and VALUE set to correct definitions\n"); 193429088Smarkm else 193529088Smarkm printf("VAR and VALUE definitions are reversed\n"); 193629088Smarkm } else if (strncasecmp((char *)what, "auto", len) == 0) { 193729088Smarkm env_auto = 1; 193829088Smarkm old_env_var = OLD_ENV_VALUE; 193929088Smarkm old_env_value = OLD_ENV_VAR; 194029088Smarkm } else if (strncasecmp((char *)what, "right", len) == 0) { 194129088Smarkm env_auto = 0; 194229088Smarkm old_env_var = OLD_ENV_VAR; 194329088Smarkm old_env_value = OLD_ENV_VALUE; 194429088Smarkm } else if (strncasecmp((char *)what, "wrong", len) == 0) { 194529088Smarkm env_auto = 0; 194629088Smarkm old_env_var = OLD_ENV_VALUE; 194729088Smarkm old_env_value = OLD_ENV_VAR; 194829088Smarkm } else { 194929088Smarkmunknown: 195029088Smarkm printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); 195129088Smarkm } 195229088Smarkm} 195329088Smarkm#endif 195429088Smarkm 195529088Smarkm#if defined(AUTHENTICATION) 195629088Smarkm/* 195729088Smarkm * The AUTHENTICATE command. 195829088Smarkm */ 195929088Smarkm 196029088Smarkmstruct authlist { 196129088Smarkm char *name; 196229088Smarkm char *help; 196329088Smarkm int (*handler)(); 196429088Smarkm int narg; 196529088Smarkm}; 196629088Smarkm 196729088Smarkmextern int 196829088Smarkm auth_enable P((char *)), 196929088Smarkm auth_disable P((char *)), 197029088Smarkm auth_status P((void)); 197129088Smarkmstatic int 197229088Smarkm auth_help P((void)); 197329088Smarkm 197429088Smarkmstruct authlist AuthList[] = { 197529088Smarkm { "status", "Display current status of authentication information", 197629088Smarkm auth_status, 0 }, 197729088Smarkm { "disable", "Disable an authentication type ('auth disable ?' for more)", 197829088Smarkm auth_disable, 1 }, 197929088Smarkm { "enable", "Enable an authentication type ('auth enable ?' for more)", 198029088Smarkm auth_enable, 1 }, 198129088Smarkm { "help", 0, auth_help, 0 }, 198229088Smarkm { "?", "Print help information", auth_help, 0 }, 198329088Smarkm { 0 }, 198429088Smarkm}; 198529088Smarkm 198629088Smarkm static int 198729088Smarkmauth_help() 198829088Smarkm{ 198929088Smarkm struct authlist *c; 199029088Smarkm 199129088Smarkm for (c = AuthList; c->name; c++) { 199229088Smarkm if (c->help) { 199329088Smarkm if (*c->help) 199429088Smarkm printf("%-15s %s\n", c->name, c->help); 199529088Smarkm else 199629088Smarkm printf("\n"); 199729088Smarkm } 199829088Smarkm } 199929088Smarkm return 0; 200029088Smarkm} 200129088Smarkm 200229181Smarkm int 200329088Smarkmauth_cmd(argc, argv) 200429088Smarkm int argc; 200529088Smarkm char *argv[]; 200629088Smarkm{ 200729088Smarkm struct authlist *c; 200829088Smarkm 200929088Smarkm if (argc < 2) { 201029088Smarkm fprintf(stderr, 201129088Smarkm "Need an argument to 'auth' command. 'auth ?' for help.\n"); 201229088Smarkm return 0; 201329088Smarkm } 201429088Smarkm 201529088Smarkm c = (struct authlist *) 201629088Smarkm genget(argv[1], (char **) AuthList, sizeof(struct authlist)); 201729088Smarkm if (c == 0) { 201829088Smarkm fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", 201929088Smarkm argv[1]); 202029088Smarkm return 0; 202129088Smarkm } 202229088Smarkm if (Ambiguous(c)) { 202329088Smarkm fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", 202429088Smarkm argv[1]); 202529088Smarkm return 0; 202629088Smarkm } 202729088Smarkm if (c->narg + 2 != argc) { 202829088Smarkm fprintf(stderr, 202929088Smarkm "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", 203029088Smarkm c->narg < argc + 2 ? "only " : "", 203129088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 203229088Smarkm return 0; 203329088Smarkm } 203429088Smarkm return((*c->handler)(argv[2], argv[3])); 203529088Smarkm} 203629088Smarkm#endif 203729088Smarkm 203829088Smarkm#ifdef ENCRYPTION 203929088Smarkm/* 204029088Smarkm * The ENCRYPT command. 204129088Smarkm */ 204229088Smarkm 204329088Smarkmstruct encryptlist { 204429088Smarkm char *name; 204529088Smarkm char *help; 204629088Smarkm int (*handler)(); 204729088Smarkm int needconnect; 204829088Smarkm int minarg; 204929088Smarkm int maxarg; 205029088Smarkm}; 205129088Smarkm 205229088Smarkmextern int 205329088Smarkm EncryptEnable P((char *, char *)), 205429088Smarkm EncryptDisable P((char *, char *)), 205529088Smarkm EncryptType P((char *, char *)), 205629088Smarkm EncryptStart P((char *)), 205729088Smarkm EncryptStartInput P((void)), 205829088Smarkm EncryptStartOutput P((void)), 205929088Smarkm EncryptStop P((char *)), 206029088Smarkm EncryptStopInput P((void)), 206129088Smarkm EncryptStopOutput P((void)), 206229088Smarkm EncryptStatus P((void)); 206329088Smarkmstatic int 206429088Smarkm EncryptHelp P((void)); 206529088Smarkm 206629088Smarkmstruct encryptlist EncryptList[] = { 206729088Smarkm { "enable", "Enable encryption. ('encrypt enable ?' for more)", 206829088Smarkm EncryptEnable, 1, 1, 2 }, 206929088Smarkm { "disable", "Disable encryption. ('encrypt enable ?' for more)", 207029088Smarkm EncryptDisable, 0, 1, 2 }, 207129088Smarkm { "type", "Set encryption type. ('encrypt type ?' for more)", 207229088Smarkm EncryptType, 0, 1, 1 }, 207329088Smarkm { "start", "Start encryption. ('encrypt start ?' for more)", 207429088Smarkm EncryptStart, 1, 0, 1 }, 207529088Smarkm { "stop", "Stop encryption. ('encrypt stop ?' for more)", 207629088Smarkm EncryptStop, 1, 0, 1 }, 207729088Smarkm { "input", "Start encrypting the input stream", 207829088Smarkm EncryptStartInput, 1, 0, 0 }, 207929088Smarkm { "-input", "Stop encrypting the input stream", 208029088Smarkm EncryptStopInput, 1, 0, 0 }, 208129088Smarkm { "output", "Start encrypting the output stream", 208229088Smarkm EncryptStartOutput, 1, 0, 0 }, 208329088Smarkm { "-output", "Stop encrypting the output stream", 208429088Smarkm EncryptStopOutput, 1, 0, 0 }, 208529088Smarkm 208629088Smarkm { "status", "Display current status of authentication information", 208729088Smarkm EncryptStatus, 0, 0, 0 }, 208829088Smarkm { "help", 0, EncryptHelp, 0, 0, 0 }, 208929088Smarkm { "?", "Print help information", EncryptHelp, 0, 0, 0 }, 209029088Smarkm { 0 }, 209129088Smarkm}; 209229088Smarkm 209329088Smarkm static int 209429088SmarkmEncryptHelp() 209529088Smarkm{ 209629088Smarkm struct encryptlist *c; 209729088Smarkm 209829088Smarkm for (c = EncryptList; c->name; c++) { 209929088Smarkm if (c->help) { 210029088Smarkm if (*c->help) 210129088Smarkm printf("%-15s %s\n", c->name, c->help); 210229088Smarkm else 210329088Smarkm printf("\n"); 210429088Smarkm } 210529088Smarkm } 210629088Smarkm return 0; 210729088Smarkm} 210829088Smarkm 210929181Smarkm int 211029088Smarkmencrypt_cmd(argc, argv) 211129088Smarkm int argc; 211229088Smarkm char *argv[]; 211329088Smarkm{ 211429088Smarkm struct encryptlist *c; 211529088Smarkm 211629088Smarkm if (argc < 2) { 211729088Smarkm fprintf(stderr, 211829088Smarkm "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); 211929088Smarkm return 0; 212029088Smarkm } 212129088Smarkm 212229088Smarkm c = (struct encryptlist *) 212329088Smarkm genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); 212429088Smarkm if (c == 0) { 212529088Smarkm fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", 212629088Smarkm argv[1]); 212729088Smarkm return 0; 212829088Smarkm } 212929088Smarkm if (Ambiguous(c)) { 213029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", 213129088Smarkm argv[1]); 213229088Smarkm return 0; 213329088Smarkm } 213429088Smarkm argc -= 2; 213529088Smarkm if (argc < c->minarg || argc > c->maxarg) { 213629088Smarkm if (c->minarg == c->maxarg) { 213729088Smarkm fprintf(stderr, "Need %s%d argument%s ", 213829088Smarkm c->minarg < argc ? "only " : "", c->minarg, 213929088Smarkm c->minarg == 1 ? "" : "s"); 214029088Smarkm } else { 214129088Smarkm fprintf(stderr, "Need %s%d-%d arguments ", 214229088Smarkm c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); 214329088Smarkm } 214429088Smarkm fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", 214529088Smarkm c->name); 214629088Smarkm return 0; 214729088Smarkm } 214829088Smarkm if (c->needconnect && !connected) { 214929088Smarkm if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 215029088Smarkm printf("?Need to be connected first.\n"); 215129088Smarkm return 0; 215229088Smarkm } 215329088Smarkm } 215429088Smarkm return ((*c->handler)(argc > 0 ? argv[2] : 0, 215529088Smarkm argc > 1 ? argv[3] : 0, 215629088Smarkm argc > 2 ? argv[4] : 0)); 215729088Smarkm} 215829088Smarkm#endif /* ENCRYPTION */ 215929088Smarkm 216029088Smarkm#if defined(unix) && defined(TN3270) 216129088Smarkm static void 216229088Smarkmfilestuff(fd) 216329088Smarkm int fd; 216429088Smarkm{ 216529088Smarkm int res; 216629088Smarkm 216729088Smarkm#ifdef F_GETOWN 216829088Smarkm setconnmode(0); 216929088Smarkm res = fcntl(fd, F_GETOWN, 0); 217029088Smarkm setcommandmode(); 217129088Smarkm 217229088Smarkm if (res == -1) { 217329088Smarkm perror("fcntl"); 217429088Smarkm return; 217529088Smarkm } 217629088Smarkm printf("\tOwner is %d.\n", res); 217729088Smarkm#endif 217829088Smarkm 217929088Smarkm setconnmode(0); 218029088Smarkm res = fcntl(fd, F_GETFL, 0); 218129088Smarkm setcommandmode(); 218229088Smarkm 218329088Smarkm if (res == -1) { 218429088Smarkm perror("fcntl"); 218529088Smarkm return; 218629088Smarkm } 218729088Smarkm#ifdef notdef 218829088Smarkm printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 218929088Smarkm#endif 219029088Smarkm} 219129088Smarkm#endif /* defined(unix) && defined(TN3270) */ 219229088Smarkm 219329088Smarkm/* 219429088Smarkm * Print status about the connection. 219529088Smarkm */ 219629088Smarkm /*ARGSUSED*/ 219729181Smarkm static int 219829088Smarkmstatus(argc, argv) 219929088Smarkm int argc; 220029088Smarkm char *argv[]; 220129088Smarkm{ 220229088Smarkm if (connected) { 220329088Smarkm printf("Connected to %s.\n", hostname); 220429088Smarkm if ((argc < 2) || strcmp(argv[1], "notmuch")) { 220529088Smarkm int mode = getconnmode(); 220629088Smarkm 220729088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 220829088Smarkm printf("Operating with LINEMODE option\n"); 220929088Smarkm printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 221029088Smarkm printf("%s catching of signals\n", 221129088Smarkm (mode&MODE_TRAPSIG) ? "Local" : "No"); 221229088Smarkm slcstate(); 221329088Smarkm#ifdef KLUDGELINEMODE 221429088Smarkm } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 221529088Smarkm printf("Operating in obsolete linemode\n"); 221629088Smarkm#endif 221729088Smarkm } else { 221829088Smarkm printf("Operating in single character mode\n"); 221929088Smarkm if (localchars) 222029088Smarkm printf("Catching signals locally\n"); 222129088Smarkm } 222229088Smarkm printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 222329088Smarkm if (my_want_state_is_will(TELOPT_LFLOW)) 222429088Smarkm printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 222529088Smarkm#ifdef ENCRYPTION 222629088Smarkm encrypt_display(); 222729088Smarkm#endif /* ENCRYPTION */ 222829088Smarkm } 222929088Smarkm } else { 223029088Smarkm printf("No connection.\n"); 223129088Smarkm } 223229088Smarkm# if !defined(TN3270) 223329088Smarkm printf("Escape character is '%s'.\n", control(escape)); 223429088Smarkm (void) fflush(stdout); 223529088Smarkm# else /* !defined(TN3270) */ 223629088Smarkm if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 223729088Smarkm printf("Escape character is '%s'.\n", control(escape)); 223829088Smarkm } 223929088Smarkm# if defined(unix) 224029088Smarkm if ((argc >= 2) && !strcmp(argv[1], "everything")) { 224129088Smarkm printf("SIGIO received %d time%s.\n", 224229088Smarkm sigiocount, (sigiocount == 1)? "":"s"); 224329088Smarkm if (In3270) { 224429088Smarkm printf("Process ID %d, process group %d.\n", 224529088Smarkm getpid(), getpgrp(getpid())); 224629088Smarkm printf("Terminal input:\n"); 224729088Smarkm filestuff(tin); 224829088Smarkm printf("Terminal output:\n"); 224929088Smarkm filestuff(tout); 225029088Smarkm printf("Network socket:\n"); 225129088Smarkm filestuff(net); 225229088Smarkm } 225329088Smarkm } 225429088Smarkm if (In3270 && transcom) { 225529088Smarkm printf("Transparent mode command is '%s'.\n", transcom); 225629088Smarkm } 225729088Smarkm# endif /* defined(unix) */ 225829088Smarkm (void) fflush(stdout); 225929088Smarkm if (In3270) { 226029088Smarkm return 0; 226129088Smarkm } 226229088Smarkm# endif /* defined(TN3270) */ 226329088Smarkm return 1; 226429088Smarkm} 226529088Smarkm 226629088Smarkm#ifdef SIGINFO 226729088Smarkm/* 226829088Smarkm * Function that gets called when SIGINFO is received. 226929088Smarkm */ 227029181Smarkm void 227129088Smarkmayt_status() 227229088Smarkm{ 227329088Smarkm (void) call(status, "status", "notmuch", 0); 227429088Smarkm} 227529088Smarkm#endif 227629088Smarkm 227756668Sshinstatic const char * 227856668Sshinsockaddr_ntop(sa) 227956668Sshin struct sockaddr *sa; 228056668Sshin{ 228156668Sshin void *addr; 228256668Sshin static char addrbuf[INET6_ADDRSTRLEN]; 228329088Smarkm 228456668Sshin switch (sa->sa_family) { 228556668Sshin case AF_INET: 228656668Sshin addr = &((struct sockaddr_in *)sa)->sin_addr; 228756668Sshin break; 228856668Sshin#ifdef INET6 228956668Sshin case AF_INET6: 229056668Sshin addr = &((struct sockaddr_in6 *)sa)->sin6_addr; 229156668Sshin break; 229256668Sshin#endif 229356668Sshin default: 229456668Sshin return NULL; 229556668Sshin } 229656668Sshin inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); 229756668Sshin return addrbuf; 229856668Sshin} 229956668Sshin 230056668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 230156668Sshinstatic int 230256668Sshinsetpolicy(net, res, policy) 230356668Sshin int net; 230456668Sshin struct addrinfo *res; 230556668Sshin char *policy; 230656668Sshin{ 230756668Sshin char *buf; 230856668Sshin int level; 230956668Sshin int optname; 231056668Sshin 231156668Sshin if (policy == NULL) 231256668Sshin return 0; 231356668Sshin 231456668Sshin buf = ipsec_set_policy(policy, strlen(policy)); 231556668Sshin if (buf == NULL) { 231656668Sshin printf("%s\n", ipsec_strerror()); 231756668Sshin return -1; 231856668Sshin } 231956668Sshin level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 232056668Sshin optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; 232156668Sshin if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){ 232256668Sshin perror("setsockopt"); 232356668Sshin return -1; 232456668Sshin } 232556668Sshin 232656668Sshin free(buf); 232756668Sshin} 232856668Sshin#endif 232956668Sshin 233057125Sshin#ifdef INET6 233157125Sshin/* 233257125Sshin * When an Address Family related error happend, check if retry with 233357125Sshin * another AF is possible or not. 233457125Sshin * Return 1, if retry with another af is OK. Else, return 0. 233557125Sshin */ 233657125Sshinstatic int 233757125Sshinswitch_af(aip) 233857125Sshin struct addrinfo **aip; 233957125Sshin{ 234057125Sshin int nextaf; 234157125Sshin struct addrinfo *ai; 234257125Sshin 234357125Sshin ai = *aip; 234457125Sshin nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; 234557125Sshin do 234657125Sshin ai=ai->ai_next; 234757125Sshin while (ai != NULL && ai->ai_family != nextaf); 234857125Sshin *aip = ai; 234957125Sshin if (*aip != NULL) { 235057125Sshin return 1; 235157125Sshin } 235257125Sshin return 0; 235357125Sshin} 235457125Sshin#endif 235557125Sshin 235629088Smarkm int 235729088Smarkmtn(argc, argv) 235829088Smarkm int argc; 235929088Smarkm char *argv[]; 236029088Smarkm{ 236129088Smarkm char *srp = 0, *strrchr(); 236256668Sshin int proto, opt; 236356668Sshin int sourceroute(), srlen; 236456668Sshin int srcroute = 0, result; 236529088Smarkm char *cmd, *hostp = 0, *portp = 0, *user = 0; 236647973Sru char *src_addr = NULL; 236757125Sshin struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; 236857125Sshin int error = 0, af_error = 0; 236929088Smarkm 237029088Smarkm if (connected) { 237129088Smarkm printf("?Already connected to %s\n", hostname); 237229088Smarkm setuid(getuid()); 237329088Smarkm return 0; 237429088Smarkm } 237529088Smarkm if (argc < 2) { 237629088Smarkm (void) strcpy(line, "open "); 237729088Smarkm printf("(to) "); 237829088Smarkm (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); 237929088Smarkm makeargv(); 238029088Smarkm argc = margc; 238129088Smarkm argv = margv; 238229088Smarkm } 238329088Smarkm cmd = *argv; 238429088Smarkm --argc; ++argv; 238529088Smarkm while (argc) { 238629088Smarkm if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) 238729088Smarkm goto usage; 238829088Smarkm if (strcmp(*argv, "-l") == 0) { 238929088Smarkm --argc; ++argv; 239029088Smarkm if (argc == 0) 239129088Smarkm goto usage; 239229088Smarkm user = *argv++; 239329088Smarkm --argc; 239429088Smarkm continue; 239529088Smarkm } 239629088Smarkm if (strcmp(*argv, "-a") == 0) { 239729088Smarkm --argc; ++argv; 239829088Smarkm autologin = 1; 239929088Smarkm continue; 240029088Smarkm } 240147973Sru if (strcmp(*argv, "-s") == 0) { 240247973Sru --argc; ++argv; 240347973Sru if (argc == 0) 240447973Sru goto usage; 240547973Sru src_addr = *argv++; 240647973Sru --argc; 240747973Sru continue; 240847973Sru } 240929088Smarkm if (hostp == 0) { 241029088Smarkm hostp = *argv++; 241129088Smarkm --argc; 241229088Smarkm continue; 241329088Smarkm } 241429088Smarkm if (portp == 0) { 241529088Smarkm portp = *argv++; 241629088Smarkm --argc; 241729088Smarkm continue; 241829088Smarkm } 241929088Smarkm usage: 242047973Sru printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); 242129088Smarkm setuid(getuid()); 242229088Smarkm return 0; 242329088Smarkm } 242429088Smarkm if (hostp == 0) 242529088Smarkm goto usage; 242629088Smarkm 242747973Sru if (src_addr != NULL) { 242856668Sshin memset(&hints, 0, sizeof(hints)); 242956668Sshin hints.ai_flags = AI_NUMERICHOST; 243056668Sshin hints.ai_family = family; 243156668Sshin hints.ai_socktype = SOCK_STREAM; 243257125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 243362805Sume if (error == EAI_NODATA) { 243456668Sshin hints.ai_flags = 0; 243557125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 243656668Sshin } 243756668Sshin if (error != 0) { 243856668Sshin fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); 243956668Sshin if (error == EAI_SYSTEM) 244056668Sshin fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); 244157125Sshin setuid(getuid()); 244247973Sru return 0; 244347973Sru } 244457125Sshin src_res0 = src_res; 244547973Sru } 244629088Smarkm if (hostp[0] == '@' || hostp[0] == '!') { 244756668Sshin if ( 244856668Sshin#ifdef INET6 244956668Sshin family == AF_INET6 || 245056668Sshin#endif 245156668Sshin (hostname = strrchr(hostp, ':')) == NULL) 245229088Smarkm hostname = strrchr(hostp, '@'); 245329088Smarkm hostname++; 245456668Sshin srcroute = 1; 245556668Sshin } else 245656668Sshin hostname = hostp; 245756668Sshin if (!portp) { 245856668Sshin telnetport = 1; 245956668Sshin portp = "telnet"; 246056668Sshin } else if (*portp == '-') { 246156668Sshin portp++; 246256668Sshin telnetport = 1; 246356668Sshin } else 246456668Sshin telnetport = 0; 246556668Sshin 246656668Sshin memset(&hints, 0, sizeof(hints)); 246756668Sshin hints.ai_flags = AI_NUMERICHOST; 246856668Sshin hints.ai_family = family; 246956668Sshin hints.ai_socktype = SOCK_STREAM; 247056668Sshin error = getaddrinfo(hostname, portp, &hints, &res); 247162773Sitojun if (error) { 247262773Sitojun hints.ai_flags = AI_CANONNAME; 247362773Sitojun error = getaddrinfo(hostname, portp, &hints, &res); 247462773Sitojun } 247562773Sitojun if (error != 0) { 247662773Sitojun fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); 247762773Sitojun if (error == EAI_SYSTEM) 247862773Sitojun fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); 247962773Sitojun setuid(getuid()); 248062773Sitojun goto fail; 248162773Sitojun } 248262773Sitojun if (hints.ai_flags == AI_NUMERICHOST) { 248362773Sitojun /* hostname has numeric */ 248456668Sshin int gni_err = 1; 248556668Sshin 248656668Sshin if (doaddrlookup) 248756668Sshin gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, 248856668Sshin _hostname, sizeof(_hostname) - 1, NULL, 0, 248956870Sshin NI_NAMEREQD); 249056668Sshin if (gni_err != 0) 249162773Sitojun (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 249256668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 249356668Sshin hostname = _hostname; 249462773Sitojun } else { 249562773Sitojun /* hostname has FQDN */ 249656668Sshin if (srcroute != 0) 249756668Sshin (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); 249856668Sshin else if (res->ai_canonname != NULL) 249956668Sshin strcpy(_hostname, res->ai_canonname); 250056668Sshin else 250156668Sshin (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 250256668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 250356668Sshin hostname = _hostname; 250456668Sshin } 250557125Sshin res0 = res; 250657233Sshin af_again: 250756668Sshin if (srcroute != 0) { 250857343Sshin static char hostbuf[BUFSIZ]; 250957125Sshin 251057233Sshin if (af_error == 0) { /* save intermediate hostnames for retry */ 251157233Sshin strncpy(hostbuf, hostp, BUFSIZ - 1); 251257233Sshin hostbuf[BUFSIZ - 1] = '\0'; 251357233Sshin } else 251457125Sshin hostp = hostbuf; 251529088Smarkm srp = 0; 251656668Sshin result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); 251756668Sshin if (result == 0) { 251857125Sshin#ifdef INET6 251957125Sshin if (family == AF_UNSPEC && af_error == 0 && 252057125Sshin switch_af(&res) == 1) { 252157125Sshin af_error = 1; 252257125Sshin goto af_again; 252357125Sshin } 252457125Sshin#endif 252529088Smarkm setuid(getuid()); 252657125Sshin goto fail; 252756668Sshin } else if (result == -1) { 252829088Smarkm printf("Bad source route option: %s\n", hostp); 252929088Smarkm setuid(getuid()); 253057125Sshin goto fail; 253129088Smarkm } 253229088Smarkm } 253329088Smarkm do { 253457342Sshin printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); 253556668Sshin net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 253629088Smarkm setuid(getuid()); 253729088Smarkm if (net < 0) { 253857125Sshin#ifdef INET6 253957125Sshin if (family == AF_UNSPEC && af_error == 0 && 254057125Sshin switch_af(&res) == 1) { 254157125Sshin af_error = 1; 254257125Sshin goto af_again; 254357125Sshin } 254457125Sshin#endif 254529088Smarkm perror("telnet: socket"); 254657125Sshin goto fail; 254729088Smarkm } 254856668Sshin if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) 254956668Sshin perror("setsockopt (source route)"); 255029088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 255156668Sshin if (res->ai_family == PF_INET) { 255229088Smarkm# if defined(HAS_GETTOS) 255329088Smarkm struct tosent *tp; 255429088Smarkm if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 255529088Smarkm tos = tp->t_tos; 255629088Smarkm# endif 255729088Smarkm if (tos < 0) 255829088Smarkm tos = 020; /* Low Delay bit */ 255929088Smarkm if (tos 256029088Smarkm && (setsockopt(net, IPPROTO_IP, IP_TOS, 256129088Smarkm (char *)&tos, sizeof(int)) < 0) 256229088Smarkm && (errno != ENOPROTOOPT)) 256329088Smarkm perror("telnet: setsockopt (IP_TOS) (ignored)"); 256429088Smarkm } 256529088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 256629088Smarkm 256729088Smarkm if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 256829088Smarkm perror("setsockopt (SO_DEBUG)"); 256929088Smarkm } 257029088Smarkm 257147973Sru if (src_addr != NULL) { 257257125Sshin for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) 257357233Sshin if (src_res->ai_family == res->ai_family) 257457233Sshin break; 257557125Sshin if (src_res == NULL) 257657125Sshin src_res = src_res0; 257757125Sshin if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { 257857125Sshin#ifdef INET6 257957125Sshin if (family == AF_UNSPEC && af_error == 0 && 258057125Sshin switch_af(&res) == 1) { 258157125Sshin af_error = 1; 258257233Sshin (void) NetClose(net); 258357125Sshin goto af_again; 258457125Sshin } 258557125Sshin#endif 258647973Sru perror("bind"); 258757233Sshin (void) NetClose(net); 258857125Sshin goto fail; 258947973Sru } 259047973Sru } 259156668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 259257233Sshin if (setpolicy(net, res, ipsec_policy_in) < 0) { 259357233Sshin (void) NetClose(net); 259457125Sshin goto fail; 259557233Sshin } 259657233Sshin if (setpolicy(net, res, ipsec_policy_out) < 0) { 259757233Sshin (void) NetClose(net); 259857125Sshin goto fail; 259957233Sshin } 260056668Sshin#endif 260147973Sru 260256668Sshin if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { 260357125Sshin struct addrinfo *next; 260457125Sshin 260557125Sshin next = res->ai_next; 260657125Sshin /* If already an af failed, only try same af. */ 260757125Sshin if (af_error != 0) 260857125Sshin while (next != NULL && next->ai_family != res->ai_family) 260957125Sshin next = next->ai_next; 261057342Sshin warn("connect to address %s", sockaddr_ntop(res->ai_addr)); 261157125Sshin if (next != NULL) { 261257125Sshin res = next; 261329088Smarkm (void) NetClose(net); 261429088Smarkm continue; 261529088Smarkm } 261657342Sshin warnx("Unable to connect to remote host"); 261757233Sshin (void) NetClose(net); 261857125Sshin goto fail; 261929088Smarkm } 262029088Smarkm connected++; 262129088Smarkm#if defined(AUTHENTICATION) || defined(ENCRYPTION) 262229088Smarkm auth_encrypt_connect(connected); 262329088Smarkm#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 262429088Smarkm } while (connected == 0); 262557125Sshin freeaddrinfo(res0); 262657125Sshin if (src_res0 != NULL) 262757125Sshin freeaddrinfo(src_res0); 262829088Smarkm cmdrc(hostp, hostname); 262929088Smarkm if (autologin && user == NULL) { 263029088Smarkm struct passwd *pw; 263129088Smarkm 263229088Smarkm user = getenv("USER"); 263329088Smarkm if (user == NULL || 263429181Smarkm ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { 263529181Smarkm if ((pw = getpwuid(getuid()))) 263629088Smarkm user = pw->pw_name; 263729088Smarkm else 263829088Smarkm user = NULL; 263929088Smarkm } 264029088Smarkm } 264129088Smarkm if (user) { 264229088Smarkm env_define((unsigned char *)"USER", (unsigned char *)user); 264329088Smarkm env_export((unsigned char *)"USER"); 264429088Smarkm } 264529088Smarkm (void) call(status, "status", "notmuch", 0); 264629088Smarkm if (setjmp(peerdied) == 0) 264729088Smarkm telnet(user); 264829088Smarkm (void) NetClose(net); 264929088Smarkm ExitString("Connection closed by foreign host.\n",1); 265029088Smarkm /*NOTREACHED*/ 265157125Sshin fail: 265257125Sshin if (res0 != NULL) 265357125Sshin freeaddrinfo(res0); 265457125Sshin if (src_res0 != NULL) 265557125Sshin freeaddrinfo(src_res0); 265657125Sshin return 0; 265729088Smarkm} 265829088Smarkm 265929088Smarkm#define HELPINDENT (sizeof ("connect")) 266029088Smarkm 266129088Smarkmstatic char 266229088Smarkm openhelp[] = "connect to a site", 266329088Smarkm closehelp[] = "close current connection", 266429088Smarkm logouthelp[] = "forcibly logout remote user and close the connection", 266529088Smarkm quithelp[] = "exit telnet", 266629088Smarkm statushelp[] = "print status information", 266729088Smarkm helphelp[] = "print help information", 266829088Smarkm sendhelp[] = "transmit special characters ('send ?' for more)", 266929088Smarkm sethelp[] = "set operating parameters ('set ?' for more)", 267029088Smarkm unsethelp[] = "unset operating parameters ('unset ?' for more)", 267129088Smarkm togglestring[] ="toggle operating parameters ('toggle ?' for more)", 267229088Smarkm slchelp[] = "change state of special charaters ('slc ?' for more)", 267329088Smarkm displayhelp[] = "display operating parameters", 267429088Smarkm#if defined(TN3270) && defined(unix) 267529088Smarkm transcomhelp[] = "specify Unix command for transparent mode pipe", 267629088Smarkm#endif /* defined(TN3270) && defined(unix) */ 267729088Smarkm#if defined(AUTHENTICATION) 267829088Smarkm authhelp[] = "turn on (off) authentication ('auth ?' for more)", 267929088Smarkm#endif 268029088Smarkm#ifdef ENCRYPTION 268129088Smarkm encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", 268229088Smarkm#endif /* ENCRYPTION */ 268329088Smarkm#if defined(unix) 268429088Smarkm zhelp[] = "suspend telnet", 268529088Smarkm#endif /* defined(unix) */ 268629181Smarkm#if defined(SKEY) 268729181Smarkm skeyhelp[] = "compute response to s/key challenge", 268829181Smarkm#endif 268929088Smarkm shellhelp[] = "invoke a subshell", 269029088Smarkm envhelp[] = "change environment variables ('environ ?' for more)", 269129088Smarkm modestring[] = "try to enter line or character mode ('mode ?' for more)"; 269229088Smarkm 269329088Smarkmstatic Command cmdtab[] = { 269429088Smarkm { "close", closehelp, bye, 1 }, 269529088Smarkm { "logout", logouthelp, logout, 1 }, 269629088Smarkm { "display", displayhelp, display, 0 }, 269729088Smarkm { "mode", modestring, modecmd, 0 }, 269829088Smarkm { "open", openhelp, tn, 0 }, 269929088Smarkm { "quit", quithelp, quit, 0 }, 270029088Smarkm { "send", sendhelp, sendcmd, 0 }, 270129088Smarkm { "set", sethelp, setcmd, 0 }, 270229088Smarkm { "unset", unsethelp, unsetcmd, 0 }, 270329088Smarkm { "status", statushelp, status, 0 }, 270429088Smarkm { "toggle", togglestring, toggle, 0 }, 270529088Smarkm { "slc", slchelp, slccmd, 0 }, 270629088Smarkm#if defined(TN3270) && defined(unix) 270729088Smarkm { "transcom", transcomhelp, settranscom, 0 }, 270829088Smarkm#endif /* defined(TN3270) && defined(unix) */ 270929088Smarkm#if defined(AUTHENTICATION) 271029088Smarkm { "auth", authhelp, auth_cmd, 0 }, 271129088Smarkm#endif 271229088Smarkm#ifdef ENCRYPTION 271329088Smarkm { "encrypt", encrypthelp, encrypt_cmd, 0 }, 271429088Smarkm#endif /* ENCRYPTION */ 271529088Smarkm#if defined(unix) 271629088Smarkm { "z", zhelp, suspend, 0 }, 271729088Smarkm#endif /* defined(unix) */ 271829088Smarkm#if defined(TN3270) 271929088Smarkm { "!", shellhelp, shell, 1 }, 272029088Smarkm#else 272129088Smarkm { "!", shellhelp, shell, 0 }, 272229088Smarkm#endif 272329088Smarkm { "environ", envhelp, env_cmd, 0 }, 272429088Smarkm { "?", helphelp, help, 0 }, 272529181Smarkm#if defined(SKEY) 272629181Smarkm { "skey", skeyhelp, skey_calc, 0 }, 272729181Smarkm#endif 272829181Smarkm { 0, 0, 0, 0 } 272929088Smarkm}; 273029088Smarkm 273129088Smarkmstatic char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 273229088Smarkmstatic char escapehelp[] = "deprecated command -- use 'set escape' instead"; 273329088Smarkm 273429088Smarkmstatic Command cmdtab2[] = { 273529088Smarkm { "help", 0, help, 0 }, 273629088Smarkm { "escape", escapehelp, setescape, 0 }, 273729088Smarkm { "crmod", crmodhelp, togcrmod, 0 }, 273829181Smarkm { 0, 0, 0, 0 } 273929088Smarkm}; 274029088Smarkm 274129088Smarkm 274229088Smarkm/* 274329088Smarkm * Call routine with argc, argv set from args (terminated by 0). 274429088Smarkm */ 274529088Smarkm 274629088Smarkm /*VARARGS1*/ 274729181Smarkm static int 274829088Smarkmcall(va_alist) 274929088Smarkm va_dcl 275029088Smarkm{ 275129088Smarkm va_list ap; 275229088Smarkm typedef int (*intrtn_t)(); 275329088Smarkm intrtn_t routine; 275429088Smarkm char *args[100]; 275529088Smarkm int argno = 0; 275629088Smarkm 275729088Smarkm va_start(ap); 275829088Smarkm routine = (va_arg(ap, intrtn_t)); 275929088Smarkm while ((args[argno++] = va_arg(ap, char *)) != 0) { 276029088Smarkm ; 276129088Smarkm } 276229088Smarkm va_end(ap); 276329088Smarkm return (*routine)(argno-1, args); 276429088Smarkm} 276529088Smarkm 276629088Smarkm 276729088Smarkm static Command * 276829088Smarkmgetcmd(name) 276929088Smarkm char *name; 277029088Smarkm{ 277129088Smarkm Command *cm; 277229088Smarkm 277329181Smarkm if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) 277429088Smarkm return cm; 277529088Smarkm return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); 277629088Smarkm} 277729088Smarkm 277829088Smarkm void 277929088Smarkmcommand(top, tbuf, cnt) 278029088Smarkm int top; 278129088Smarkm char *tbuf; 278229088Smarkm int cnt; 278329088Smarkm{ 278429088Smarkm register Command *c; 278529088Smarkm 278629088Smarkm setcommandmode(); 278729088Smarkm if (!top) { 278829088Smarkm putchar('\n'); 278929088Smarkm#if defined(unix) 279029088Smarkm } else { 279129088Smarkm (void) signal(SIGINT, SIG_DFL); 279229088Smarkm (void) signal(SIGQUIT, SIG_DFL); 279329088Smarkm#endif /* defined(unix) */ 279429088Smarkm } 279529088Smarkm for (;;) { 279629088Smarkm if (rlogin == _POSIX_VDISABLE) 279729088Smarkm printf("%s> ", prompt); 279829088Smarkm if (tbuf) { 279929088Smarkm register char *cp; 280029088Smarkm cp = line; 280129088Smarkm while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 280229088Smarkm cnt--; 280329088Smarkm tbuf = 0; 280429088Smarkm if (cp == line || *--cp != '\n' || cp == line) 280529088Smarkm goto getline; 280629088Smarkm *cp = '\0'; 280729088Smarkm if (rlogin == _POSIX_VDISABLE) 280829088Smarkm printf("%s\n", line); 280929088Smarkm } else { 281029088Smarkm getline: 281129088Smarkm if (rlogin != _POSIX_VDISABLE) 281229088Smarkm printf("%s> ", prompt); 281329088Smarkm if (fgets(line, sizeof(line), stdin) == NULL) { 281429088Smarkm if (feof(stdin) || ferror(stdin)) { 281529088Smarkm (void) quit(); 281629088Smarkm /*NOTREACHED*/ 281729088Smarkm } 281829088Smarkm break; 281929088Smarkm } 282029088Smarkm } 282129088Smarkm if (line[0] == 0) 282229088Smarkm break; 282329088Smarkm makeargv(); 282429088Smarkm if (margv[0] == 0) { 282529088Smarkm break; 282629088Smarkm } 282729088Smarkm c = getcmd(margv[0]); 282829088Smarkm if (Ambiguous(c)) { 282929088Smarkm printf("?Ambiguous command\n"); 283029088Smarkm continue; 283129088Smarkm } 283229088Smarkm if (c == 0) { 283329088Smarkm printf("?Invalid command\n"); 283429088Smarkm continue; 283529088Smarkm } 283629088Smarkm if (c->needconnect && !connected) { 283729088Smarkm printf("?Need to be connected first.\n"); 283829088Smarkm continue; 283929088Smarkm } 284029088Smarkm if ((*c->handler)(margc, margv)) { 284129088Smarkm break; 284229088Smarkm } 284329088Smarkm } 284429088Smarkm if (!top) { 284529088Smarkm if (!connected) { 284629088Smarkm longjmp(toplevel, 1); 284729088Smarkm /*NOTREACHED*/ 284829088Smarkm } 284929088Smarkm#if defined(TN3270) 285029088Smarkm if (shell_active == 0) { 285129088Smarkm setconnmode(0); 285229088Smarkm } 285329088Smarkm#else /* defined(TN3270) */ 285429088Smarkm setconnmode(0); 285529088Smarkm#endif /* defined(TN3270) */ 285629088Smarkm } 285729088Smarkm} 285829088Smarkm 285929088Smarkm/* 286029088Smarkm * Help command. 286129088Smarkm */ 286229181Smarkm static int 286329088Smarkmhelp(argc, argv) 286429088Smarkm int argc; 286529088Smarkm char *argv[]; 286629088Smarkm{ 286729088Smarkm register Command *c; 286829088Smarkm 286929088Smarkm if (argc == 1) { 287029088Smarkm printf("Commands may be abbreviated. Commands are:\n\n"); 287129088Smarkm for (c = cmdtab; c->name; c++) 287229088Smarkm if (c->help) { 287329088Smarkm printf("%-*s\t%s\n", HELPINDENT, c->name, 287429088Smarkm c->help); 287529088Smarkm } 287629088Smarkm } 287729181Smarkm else while (--argc > 0) { 287829088Smarkm register char *arg; 287929088Smarkm arg = *++argv; 288029088Smarkm c = getcmd(arg); 288129088Smarkm if (Ambiguous(c)) 288229088Smarkm printf("?Ambiguous help command %s\n", arg); 288329088Smarkm else if (c == (Command *)0) 288429088Smarkm printf("?Invalid help command %s\n", arg); 288529088Smarkm else 288629088Smarkm printf("%s\n", c->help); 288729088Smarkm } 288829181Smarkm return(0); 288929088Smarkm} 289029088Smarkm 289129088Smarkmstatic char *rcname = 0; 289229088Smarkmstatic char rcbuf[128]; 289329088Smarkm 289429181Smarkm void 289529088Smarkmcmdrc(m1, m2) 289629088Smarkm char *m1, *m2; 289729088Smarkm{ 289829088Smarkm register Command *c; 289929088Smarkm FILE *rcfile; 290029088Smarkm int gotmachine = 0; 290129088Smarkm int l1 = strlen(m1); 290229088Smarkm int l2 = strlen(m2); 290329088Smarkm char m1save[64]; 290429088Smarkm 290529088Smarkm if (skiprc) 290629088Smarkm return; 290729088Smarkm 290829088Smarkm strcpy(m1save, m1); 290929088Smarkm m1 = m1save; 291029088Smarkm 291129088Smarkm if (rcname == 0) { 291229088Smarkm rcname = getenv("HOME"); 291329181Smarkm if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) 291429088Smarkm strcpy(rcbuf, rcname); 291529088Smarkm else 291629088Smarkm rcbuf[0] = '\0'; 291729088Smarkm strcat(rcbuf, "/.telnetrc"); 291829088Smarkm rcname = rcbuf; 291929088Smarkm } 292029088Smarkm 292129088Smarkm if ((rcfile = fopen(rcname, "r")) == 0) { 292229088Smarkm return; 292329088Smarkm } 292429088Smarkm 292529088Smarkm for (;;) { 292629088Smarkm if (fgets(line, sizeof(line), rcfile) == NULL) 292729088Smarkm break; 292829088Smarkm if (line[0] == 0) 292929088Smarkm break; 293029088Smarkm if (line[0] == '#') 293129088Smarkm continue; 293229088Smarkm if (gotmachine) { 293329088Smarkm if (!isspace(line[0])) 293429088Smarkm gotmachine = 0; 293529088Smarkm } 293629088Smarkm if (gotmachine == 0) { 293729088Smarkm if (isspace(line[0])) 293829088Smarkm continue; 293929088Smarkm if (strncasecmp(line, m1, l1) == 0) 294029088Smarkm strncpy(line, &line[l1], sizeof(line) - l1); 294129088Smarkm else if (strncasecmp(line, m2, l2) == 0) 294229088Smarkm strncpy(line, &line[l2], sizeof(line) - l2); 294329088Smarkm else if (strncasecmp(line, "DEFAULT", 7) == 0) 294429088Smarkm strncpy(line, &line[7], sizeof(line) - 7); 294529088Smarkm else 294629088Smarkm continue; 294729088Smarkm if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') 294829088Smarkm continue; 294929088Smarkm gotmachine = 1; 295029088Smarkm } 295129088Smarkm makeargv(); 295229088Smarkm if (margv[0] == 0) 295329088Smarkm continue; 295429088Smarkm c = getcmd(margv[0]); 295529088Smarkm if (Ambiguous(c)) { 295629088Smarkm printf("?Ambiguous command: %s\n", margv[0]); 295729088Smarkm continue; 295829088Smarkm } 295929088Smarkm if (c == 0) { 296029088Smarkm printf("?Invalid command: %s\n", margv[0]); 296129088Smarkm continue; 296229088Smarkm } 296329088Smarkm /* 296429088Smarkm * This should never happen... 296529088Smarkm */ 296629088Smarkm if (c->needconnect && !connected) { 296729088Smarkm printf("?Need to be connected first for %s.\n", margv[0]); 296829088Smarkm continue; 296929088Smarkm } 297029088Smarkm (*c->handler)(margc, margv); 297129088Smarkm } 297229088Smarkm fclose(rcfile); 297329088Smarkm} 297429088Smarkm 297529088Smarkm/* 297629088Smarkm * Source route is handed in as 297729088Smarkm * [!]@hop1@hop2...[@|:]dst 297829088Smarkm * If the leading ! is present, it is a 297929088Smarkm * strict source route, otherwise it is 298029088Smarkm * assmed to be a loose source route. 298129088Smarkm * 298229088Smarkm * We fill in the source route option as 298329088Smarkm * hop1,hop2,hop3...dest 298429088Smarkm * and return a pointer to hop1, which will 298529088Smarkm * be the address to connect() to. 298629088Smarkm * 298729088Smarkm * Arguments: 298856668Sshin * 298956668Sshin * res: ponter to addrinfo structure which contains sockaddr to 299056668Sshin * the host to connect to. 299156668Sshin * 299229088Smarkm * arg: pointer to route list to decipher 299329088Smarkm * 299429088Smarkm * cpp: If *cpp is not equal to NULL, this is a 299529088Smarkm * pointer to a pointer to a character array 299629088Smarkm * that should be filled in with the option. 299729088Smarkm * 299829088Smarkm * lenp: pointer to an integer that contains the 299929088Smarkm * length of *cpp if *cpp != NULL. 300029088Smarkm * 300156668Sshin * protop: pointer to an integer that should be filled in with 300256668Sshin * appropriate protocol for setsockopt, as socket 300356668Sshin * protocol family. 300456668Sshin * 300556668Sshin * optp: pointer to an integer that should be filled in with 300656668Sshin * appropriate option for setsockopt, as socket protocol 300756668Sshin * family. 300856668Sshin * 300929088Smarkm * Return values: 301029088Smarkm * 301156668Sshin * If the return value is 1, then all operations are 301256668Sshin * successful. If the 301329088Smarkm * return value is -1, there was a syntax error in the 301429088Smarkm * option, either unknown characters, or too many hosts. 301529088Smarkm * If the return value is 0, one of the hostnames in the 301629088Smarkm * path is unknown, and *cpp is set to point to the bad 301729088Smarkm * hostname. 301829088Smarkm * 301929088Smarkm * *cpp: If *cpp was equal to NULL, it will be filled 302029088Smarkm * in with a pointer to our static area that has 302129088Smarkm * the option filled in. This will be 32bit aligned. 302229088Smarkm * 302329088Smarkm * *lenp: This will be filled in with how long the option 302429088Smarkm * pointed to by *cpp is. 302529088Smarkm * 302656668Sshin * *protop: This will be filled in with appropriate protocol for 302756668Sshin * setsockopt, as socket protocol family. 302856668Sshin * 302956668Sshin * *optp: This will be filled in with appropriate option for 303056668Sshin * setsockopt, as socket protocol family. 303129088Smarkm */ 303256668Sshinint 303356668Sshinsourceroute(ai, arg, cpp, lenp, protop, optp) 303456668Sshin struct addrinfo *ai; 303529088Smarkm char *arg; 303629088Smarkm char **cpp; 303729088Smarkm int *lenp; 303856668Sshin int *protop; 303956668Sshin int *optp; 304029088Smarkm{ 304163662Sume static char buf[1024 + ALIGNBYTES]; /*XXX*/ 304256668Sshin struct cmsghdr *cmsg; 304329088Smarkm#ifdef sysV88 304429088Smarkm static IOPTN ipopt; 304529088Smarkm#endif 304656668Sshin char *cp, *cp2, *lsrp, *ep; 304729088Smarkm register int tmp; 304856668Sshin struct sockaddr_in *sin; 304956668Sshin struct sockaddr_in6 *sin6; 305056668Sshin struct addrinfo hints, *res; 305156668Sshin int error; 305229088Smarkm register char c; 305329088Smarkm 305429088Smarkm /* 305529088Smarkm * Verify the arguments, and make sure we have 305629088Smarkm * at least 7 bytes for the option. 305729088Smarkm */ 305829088Smarkm if (cpp == NULL || lenp == NULL) 305957724Sshin return -1; 306056668Sshin if (*cpp != NULL) { 306156668Sshin switch (res->ai_family) { 306256668Sshin case AF_INET: 306356668Sshin if (*lenp < 7) 306457724Sshin return -1; 306556668Sshin break; 306656668Sshin#ifdef INET6 306756668Sshin case AF_INET6: 306857724Sshin if (*lenp < CMSG_SPACE(sizeof(struct ip6_rthdr) + 306957724Sshin sizeof(struct in6_addr))) 307057724Sshin return -1; 307156668Sshin break; 307256668Sshin#endif 307356668Sshin } 307456668Sshin } 307529088Smarkm /* 307629088Smarkm * Decide whether we have a buffer passed to us, 307729088Smarkm * or if we need to use our own static buffer. 307829088Smarkm */ 307929088Smarkm if (*cpp) { 308029088Smarkm lsrp = *cpp; 308156668Sshin ep = lsrp + *lenp; 308229088Smarkm } else { 308363662Sume *cpp = lsrp = (char *)ALIGN(buf); 308456668Sshin ep = lsrp + 1024; 308529088Smarkm } 308629088Smarkm 308729088Smarkm cp = arg; 308829088Smarkm 308956668Sshin#ifdef INET6 309056668Sshin if (ai->ai_family == AF_INET6) { 309156668Sshin cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0); 309256668Sshin if (*cp != '@') 309356668Sshin return -1; 309456668Sshin *protop = IPPROTO_IPV6; 309556668Sshin *optp = IPV6_PKTOPTIONS; 309656668Sshin } else 309756668Sshin#endif 309856668Sshin { 309929088Smarkm /* 310029088Smarkm * Next, decide whether we have a loose source 310129088Smarkm * route or a strict source route, and fill in 310229088Smarkm * the begining of the option. 310329088Smarkm */ 310429088Smarkm#ifndef sysV88 310529088Smarkm if (*cp == '!') { 310629088Smarkm cp++; 310729088Smarkm *lsrp++ = IPOPT_SSRR; 310829088Smarkm } else 310929088Smarkm *lsrp++ = IPOPT_LSRR; 311029088Smarkm#else 311129088Smarkm if (*cp == '!') { 311229088Smarkm cp++; 311329088Smarkm ipopt.io_type = IPOPT_SSRR; 311429088Smarkm } else 311529088Smarkm ipopt.io_type = IPOPT_LSRR; 311629088Smarkm#endif 311729088Smarkm 311829088Smarkm if (*cp != '@') 311957724Sshin return -1; 312029088Smarkm 312129088Smarkm#ifndef sysV88 312229088Smarkm lsrp++; /* skip over length, we'll fill it in later */ 312329088Smarkm *lsrp++ = 4; 312429088Smarkm#endif 312556668Sshin *protop = IPPROTO_IP; 312656668Sshin *optp = IP_OPTIONS; 312756668Sshin } 312829088Smarkm 312929088Smarkm cp++; 313056668Sshin memset(&hints, 0, sizeof(hints)); 313156668Sshin hints.ai_family = ai->ai_family; 313256668Sshin hints.ai_socktype = SOCK_STREAM; 313329088Smarkm for (c = 0;;) { 313456668Sshin if ( 313556668Sshin#ifdef INET6 313656668Sshin ai->ai_family != AF_INET6 && 313756668Sshin#endif 313856668Sshin c == ':') 313929088Smarkm cp2 = 0; 314029181Smarkm else for (cp2 = cp; (c = *cp2); cp2++) { 314129088Smarkm if (c == ',') { 314229088Smarkm *cp2++ = '\0'; 314329088Smarkm if (*cp2 == '@') 314429088Smarkm cp2++; 314529088Smarkm } else if (c == '@') { 314629088Smarkm *cp2++ = '\0'; 314756668Sshin } else if ( 314856668Sshin#ifdef INET6 314956668Sshin ai->ai_family != AF_INET6 && 315056668Sshin#endif 315156668Sshin c == ':') { 315229088Smarkm *cp2++ = '\0'; 315329088Smarkm } else 315429088Smarkm continue; 315529088Smarkm break; 315629088Smarkm } 315729088Smarkm if (!c) 315829088Smarkm cp2 = 0; 315929088Smarkm 316056668Sshin hints.ai_flags = AI_NUMERICHOST; 316156668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 316262805Sume if (error == EAI_NODATA) { 316356668Sshin hints.ai_flags = 0; 316456668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 316556668Sshin } 316656668Sshin if (error != 0) { 316756668Sshin fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); 316856668Sshin if (error == EAI_SYSTEM) 316956668Sshin fprintf(stderr, "%s: %s\n", cp, 317056668Sshin strerror(errno)); 317129088Smarkm *cpp = cp; 317229088Smarkm return(0); 317329088Smarkm } 317456668Sshin#ifdef INET6 317556668Sshin if (res->ai_family == AF_INET6) { 317656668Sshin sin6 = (struct sockaddr_in6 *)res->ai_addr; 317756668Sshin inet6_rthdr_add(cmsg, &sin6->sin6_addr, 317856668Sshin IPV6_RTHDR_LOOSE); 317956668Sshin } else 318056668Sshin#endif 318156668Sshin { 318256668Sshin sin = (struct sockaddr_in *)res->ai_addr; 318356668Sshin memcpy(lsrp, (char *)&sin->sin_addr, 4); 318429088Smarkm lsrp += 4; 318556668Sshin } 318629088Smarkm if (cp2) 318729088Smarkm cp = cp2; 318829088Smarkm else 318929088Smarkm break; 319029088Smarkm /* 319129088Smarkm * Check to make sure there is space for next address 319229088Smarkm */ 319356668Sshin#ifdef INET6 319456668Sshin if (res->ai_family == AF_INET6) { 319557724Sshin if (((char *)CMSG_DATA(cmsg) + 319656668Sshin sizeof(struct ip6_rthdr) + 319756668Sshin ((inet6_rthdr_segments(cmsg) + 1) * 319856668Sshin sizeof(struct in6_addr))) > ep) 319957724Sshin return -1; 320056668Sshin } else 320156668Sshin#endif 320256668Sshin if (lsrp + 4 > ep) 320357724Sshin return -1; 320456668Sshin freeaddrinfo(res); 320529088Smarkm } 320656668Sshin#ifdef INET6 320756668Sshin if (res->ai_family == AF_INET6) { 320856668Sshin inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 320956668Sshin *lenp = cmsg->cmsg_len; 321056668Sshin } else 321156668Sshin#endif 321256668Sshin { 321329088Smarkm#ifndef sysV88 321429088Smarkm if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 321529088Smarkm *cpp = 0; 321629088Smarkm *lenp = 0; 321757724Sshin return -1; 321829088Smarkm } 321929088Smarkm *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 322029088Smarkm *lenp = lsrp - *cpp; 322129088Smarkm#else 322229088Smarkm ipopt.io_len = lsrp - *cpp; 322329088Smarkm if (ipopt.io_len <= 5) { /* Is 3 better ? */ 322429088Smarkm *cpp = 0; 322529088Smarkm *lenp = 0; 322657724Sshin return -1; 322729088Smarkm } 322829088Smarkm *lenp = sizeof(ipopt); 322929088Smarkm *cpp = (char *) &ipopt; 323029088Smarkm#endif 323156668Sshin } 323256668Sshin freeaddrinfo(res); 323356668Sshin return 1; 323429088Smarkm} 323556668Sshin 323656668Sshin 323756668Sshin 3238