commands.c revision 77095
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 77095 2001-05-23 22:54:07Z dillon $ 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> 4277095Sdillon#include <sys/un.h> 4329088Smarkm#if defined(CRAY) || defined(sysV88) 4429088Smarkm#include <sys/types.h> 4529088Smarkm#endif 4629088Smarkm#include <sys/file.h> 4729088Smarkm#else 4829088Smarkm#include <sys/types.h> 4929088Smarkm#endif /* defined(unix) */ 5029088Smarkm#include <sys/socket.h> 5129088Smarkm#include <netinet/in.h> 5229088Smarkm#ifdef CRAY 5329088Smarkm#include <fcntl.h> 5429088Smarkm#endif /* CRAY */ 5529088Smarkm 5629088Smarkm#include <signal.h> 5729088Smarkm#include <netdb.h> 5829088Smarkm#include <ctype.h> 5929088Smarkm#include <pwd.h> 6029088Smarkm#include <varargs.h> 6129088Smarkm#include <errno.h> 6229181Smarkm#include <unistd.h> 6329181Smarkm#include <stdlib.h> 6429088Smarkm 6529088Smarkm#include <arpa/telnet.h> 6629088Smarkm 6729088Smarkm#include "general.h" 6829088Smarkm 6929088Smarkm#include "ring.h" 7029088Smarkm 7129088Smarkm#include "externs.h" 7229088Smarkm#include "defines.h" 7329088Smarkm#include "types.h" 7429088Smarkm 7529181Smarkm#if defined(AUTHENTICATION) 7629181Smarkm#include <libtelnet/auth.h> 7729181Smarkm#endif 7829181Smarkm#if defined(ENCRYPTION) 7929181Smarkm#include <libtelnet/encrypt.h> 8029181Smarkm#endif 8129181Smarkm 8229088Smarkm#if !defined(CRAY) && !defined(sysV88) 8329088Smarkm#include <netinet/in_systm.h> 8429088Smarkm# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) 8529088Smarkm# include <machine/endian.h> 8629088Smarkm# endif /* vax */ 8729088Smarkm#endif /* !defined(CRAY) && !defined(sysV88) */ 8829088Smarkm#include <netinet/ip.h> 8956668Sshin#include <netinet/ip6.h> 9029088Smarkm 9129088Smarkm 9229088Smarkm#ifndef MAXHOSTNAMELEN 9369223Skris#define MAXHOSTNAMELEN 256 9429088Smarkm#endif MAXHOSTNAMELEN 9529088Smarkm 9629088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 9729088Smarkmint tos = -1; 9829088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 9929088Smarkm 10029088Smarkmchar *hostname; 10129088Smarkmstatic char _hostname[MAXHOSTNAMELEN]; 10229088Smarkm 10329088Smarkmextern char *getenv(); 10429088Smarkm 10529088Smarkmextern int isprefix(); 10629088Smarkmextern char **genget(); 10729088Smarkmextern int Ambiguous(); 10829088Smarkm 10929181Smarkmstatic int help(int argc, char *argv[]); 11029181Smarkmstatic int call(); 11129181Smarkmstatic void cmdrc(char *m1, char *m2); 11257125Sshinstatic int switch_af(struct addrinfo **aip); 11329088Smarkm 11429181Smarkmint quit(void); 11529181Smarkm 11629088Smarkmtypedef struct { 11729088Smarkm char *name; /* command name */ 11829088Smarkm char *help; /* help string (NULL for no help) */ 11929088Smarkm int (*handler)(); /* routine which executes command */ 12029088Smarkm int needconnect; /* Do we need to be connected to execute? */ 12129088Smarkm} Command; 12229088Smarkm 12329088Smarkmstatic char line[256]; 12429088Smarkmstatic char saveline[256]; 12529088Smarkmstatic int margc; 12629088Smarkmstatic char *margv[20]; 12729088Smarkm 12829181Smarkm#if defined(SKEY) 12929181Smarkm#include <sys/wait.h> 13029181Smarkm#define PATH_SKEY "/usr/bin/key" 13129181Smarkm int 13229181Smarkmskey_calc(argc, argv) 13329181Smarkm int argc; 13429181Smarkm char **argv; 13529181Smarkm{ 13629181Smarkm int status; 13729181Smarkm 13829181Smarkm if(argc != 3) { 13929181Smarkm printf("%s sequence challenge\n", argv[0]); 14029181Smarkm return; 14129181Smarkm } 14229181Smarkm 14329181Smarkm switch(fork()) { 14429181Smarkm case 0: 14529181Smarkm execv(PATH_SKEY, argv); 14629181Smarkm exit (1); 14729181Smarkm case -1: 14829181Smarkm perror("fork"); 14929181Smarkm break; 15029181Smarkm default: 15129181Smarkm (void) wait(&status); 15229181Smarkm if (WIFEXITED(status)) 15329181Smarkm return (WEXITSTATUS(status)); 15429181Smarkm return (0); 15529181Smarkm } 15629181Smarkm} 15729181Smarkm#endif 15829181Smarkm 15929088Smarkm static void 16029088Smarkmmakeargv() 16129088Smarkm{ 16229088Smarkm register char *cp, *cp2, c; 16329088Smarkm register char **argp = margv; 16429088Smarkm 16529088Smarkm margc = 0; 16629088Smarkm cp = line; 16729088Smarkm if (*cp == '!') { /* Special case shell escape */ 16829088Smarkm strcpy(saveline, line); /* save for shell command */ 16929088Smarkm *argp++ = "!"; /* No room in string to get this */ 17029088Smarkm margc++; 17129088Smarkm cp++; 17229088Smarkm } 17329181Smarkm while ((c = *cp)) { 17429088Smarkm register int inquote = 0; 17529088Smarkm while (isspace(c)) 17629088Smarkm c = *++cp; 17729088Smarkm if (c == '\0') 17829088Smarkm break; 17929088Smarkm *argp++ = cp; 18029088Smarkm margc += 1; 18129088Smarkm for (cp2 = cp; c != '\0'; c = *++cp) { 18229088Smarkm if (inquote) { 18329088Smarkm if (c == inquote) { 18429088Smarkm inquote = 0; 18529088Smarkm continue; 18629088Smarkm } 18729088Smarkm } else { 18829088Smarkm if (c == '\\') { 18929088Smarkm if ((c = *++cp) == '\0') 19029088Smarkm break; 19129088Smarkm } else if (c == '"') { 19229088Smarkm inquote = '"'; 19329088Smarkm continue; 19429088Smarkm } else if (c == '\'') { 19529088Smarkm inquote = '\''; 19629088Smarkm continue; 19729088Smarkm } else if (isspace(c)) 19829088Smarkm break; 19929088Smarkm } 20029088Smarkm *cp2++ = c; 20129088Smarkm } 20229088Smarkm *cp2 = '\0'; 20329088Smarkm if (c == '\0') 20429088Smarkm break; 20529088Smarkm cp++; 20629088Smarkm } 20729088Smarkm *argp++ = 0; 20829088Smarkm} 20929088Smarkm 21029088Smarkm/* 21129088Smarkm * Make a character string into a number. 21229088Smarkm * 21329088Smarkm * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). 21429088Smarkm */ 21529088Smarkm 21629181Smarkm static int 21729088Smarkmspecial(s) 21829088Smarkm register char *s; 21929088Smarkm{ 22029088Smarkm register char c; 22129088Smarkm char b; 22229088Smarkm 22329088Smarkm switch (*s) { 22429088Smarkm case '^': 22529088Smarkm b = *++s; 22629088Smarkm if (b == '?') { 22729088Smarkm c = b | 0x40; /* DEL */ 22829088Smarkm } else { 22929088Smarkm c = b & 0x1f; 23029088Smarkm } 23129088Smarkm break; 23229088Smarkm default: 23329088Smarkm c = *s; 23429088Smarkm break; 23529088Smarkm } 23629088Smarkm return c; 23729088Smarkm} 23829088Smarkm 23929088Smarkm/* 24029088Smarkm * Construct a control character sequence 24129088Smarkm * for a special character. 24229088Smarkm */ 24329088Smarkm static char * 24429088Smarkmcontrol(c) 24529088Smarkm register cc_t c; 24629088Smarkm{ 24729088Smarkm static char buf[5]; 24829088Smarkm /* 24929088Smarkm * The only way I could get the Sun 3.5 compiler 25029088Smarkm * to shut up about 25129088Smarkm * if ((unsigned int)c >= 0x80) 25229088Smarkm * was to assign "c" to an unsigned int variable... 25329088Smarkm * Arggg.... 25429088Smarkm */ 25529088Smarkm register unsigned int uic = (unsigned int)c; 25629088Smarkm 25729088Smarkm if (uic == 0x7f) 25829088Smarkm return ("^?"); 25929088Smarkm if (c == (cc_t)_POSIX_VDISABLE) { 26029088Smarkm return "off"; 26129088Smarkm } 26229088Smarkm if (uic >= 0x80) { 26329088Smarkm buf[0] = '\\'; 26429088Smarkm buf[1] = ((c>>6)&07) + '0'; 26529088Smarkm buf[2] = ((c>>3)&07) + '0'; 26629088Smarkm buf[3] = (c&07) + '0'; 26729088Smarkm buf[4] = 0; 26829088Smarkm } else if (uic >= 0x20) { 26929088Smarkm buf[0] = c; 27029088Smarkm buf[1] = 0; 27129088Smarkm } else { 27229088Smarkm buf[0] = '^'; 27329088Smarkm buf[1] = '@'+c; 27429088Smarkm buf[2] = 0; 27529088Smarkm } 27629088Smarkm return (buf); 27729088Smarkm} 27829088Smarkm 27929088Smarkm 28029088Smarkm 28129088Smarkm/* 28229088Smarkm * The following are data structures and routines for 28329088Smarkm * the "send" command. 28429088Smarkm * 28529088Smarkm */ 28629088Smarkm 28729088Smarkmstruct sendlist { 28829088Smarkm char *name; /* How user refers to it (case independent) */ 28929088Smarkm char *help; /* Help information (0 ==> no help) */ 29029088Smarkm int needconnect; /* Need to be connected */ 29129088Smarkm int narg; /* Number of arguments */ 29229088Smarkm int (*handler)(); /* Routine to perform (for special ops) */ 29329088Smarkm int nbyte; /* Number of bytes to send this command */ 29429088Smarkm int what; /* Character to be sent (<0 ==> special) */ 29529088Smarkm}; 29629088Smarkm 29729088Smarkm 29829088Smarkmstatic int 29929088Smarkm send_esc P((void)), 30029088Smarkm send_help P((void)), 30129088Smarkm send_docmd P((char *)), 30229088Smarkm send_dontcmd P((char *)), 30329088Smarkm send_willcmd P((char *)), 30429088Smarkm send_wontcmd P((char *)); 30529088Smarkm 30629088Smarkmstatic struct sendlist Sendlist[] = { 30729088Smarkm { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, 30829088Smarkm { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, 30929088Smarkm { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, 31029088Smarkm { "break", 0, 1, 0, 0, 2, BREAK }, 31129088Smarkm { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, 31229088Smarkm { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, 31329088Smarkm { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, 31429088Smarkm { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, 31529088Smarkm { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, 31629088Smarkm { "intp", 0, 1, 0, 0, 2, IP }, 31729088Smarkm { "interrupt", 0, 1, 0, 0, 2, IP }, 31829088Smarkm { "intr", 0, 1, 0, 0, 2, IP }, 31929088Smarkm { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, 32029088Smarkm { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, 32129088Smarkm { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, 32229088Smarkm { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, 32329088Smarkm { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, 32429088Smarkm { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, 32529088Smarkm { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, 32629088Smarkm { "?", "Display send options", 0, 0, send_help, 0, 0 }, 32729088Smarkm { "help", 0, 0, 0, send_help, 0, 0 }, 32829088Smarkm { "do", 0, 0, 1, send_docmd, 3, 0 }, 32929088Smarkm { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, 33029088Smarkm { "will", 0, 0, 1, send_willcmd, 3, 0 }, 33129088Smarkm { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, 33229088Smarkm { 0 } 33329088Smarkm}; 33429088Smarkm 33529088Smarkm#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ 33629088Smarkm sizeof(struct sendlist))) 33729088Smarkm 33829088Smarkm static int 33929088Smarkmsendcmd(argc, argv) 34029088Smarkm int argc; 34129088Smarkm char **argv; 34229088Smarkm{ 34329088Smarkm int count; /* how many bytes we are going to need to send */ 34429088Smarkm int i; 34529088Smarkm struct sendlist *s; /* pointer to current command */ 34629088Smarkm int success = 0; 34729088Smarkm int needconnect = 0; 34829088Smarkm 34929088Smarkm if (argc < 2) { 35029088Smarkm printf("need at least one argument for 'send' command\n"); 35129088Smarkm printf("'send ?' for help\n"); 35229088Smarkm return 0; 35329088Smarkm } 35429088Smarkm /* 35529088Smarkm * First, validate all the send arguments. 35629088Smarkm * In addition, we see how much space we are going to need, and 35729088Smarkm * whether or not we will be doing a "SYNCH" operation (which 35829088Smarkm * flushes the network queue). 35929088Smarkm */ 36029088Smarkm count = 0; 36129088Smarkm for (i = 1; i < argc; i++) { 36229088Smarkm s = GETSEND(argv[i]); 36329088Smarkm if (s == 0) { 36429088Smarkm printf("Unknown send argument '%s'\n'send ?' for help.\n", 36529088Smarkm argv[i]); 36629088Smarkm return 0; 36729088Smarkm } else if (Ambiguous(s)) { 36829088Smarkm printf("Ambiguous send argument '%s'\n'send ?' for help.\n", 36929088Smarkm argv[i]); 37029088Smarkm return 0; 37129088Smarkm } 37229088Smarkm if (i + s->narg >= argc) { 37329088Smarkm fprintf(stderr, 37429088Smarkm "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", 37529088Smarkm s->narg, s->narg == 1 ? "" : "s", s->name, s->name); 37629088Smarkm return 0; 37729088Smarkm } 37829088Smarkm count += s->nbyte; 37929088Smarkm if (s->handler == send_help) { 38029088Smarkm send_help(); 38129088Smarkm return 0; 38229088Smarkm } 38329088Smarkm 38429088Smarkm i += s->narg; 38529088Smarkm needconnect += s->needconnect; 38629088Smarkm } 38729088Smarkm if (!connected && needconnect) { 38829088Smarkm printf("?Need to be connected first.\n"); 38929088Smarkm printf("'send ?' for help\n"); 39029088Smarkm return 0; 39129088Smarkm } 39229088Smarkm /* Now, do we have enough room? */ 39329088Smarkm if (NETROOM() < count) { 39429088Smarkm printf("There is not enough room in the buffer TO the network\n"); 39529088Smarkm printf("to process your request. Nothing will be done.\n"); 39629088Smarkm printf("('send synch' will throw away most data in the network\n"); 39729088Smarkm printf("buffer, if this might help.)\n"); 39829088Smarkm return 0; 39929088Smarkm } 40029088Smarkm /* OK, they are all OK, now go through again and actually send */ 40129088Smarkm count = 0; 40229088Smarkm for (i = 1; i < argc; i++) { 40329088Smarkm if ((s = GETSEND(argv[i])) == 0) { 40429088Smarkm fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); 40529088Smarkm (void) quit(); 40629088Smarkm /*NOTREACHED*/ 40729088Smarkm } 40829088Smarkm if (s->handler) { 40929088Smarkm count++; 41029088Smarkm success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, 41129088Smarkm (s->narg > 1) ? argv[i+2] : 0); 41229088Smarkm i += s->narg; 41329088Smarkm } else { 41429088Smarkm NET2ADD(IAC, s->what); 41529088Smarkm printoption("SENT", IAC, s->what); 41629088Smarkm } 41729088Smarkm } 41829088Smarkm return (count == success); 41929088Smarkm} 42029088Smarkm 42129088Smarkm static int 42229088Smarkmsend_esc() 42329088Smarkm{ 42429088Smarkm NETADD(escape); 42529088Smarkm return 1; 42629088Smarkm} 42729088Smarkm 42829088Smarkm static int 42929088Smarkmsend_docmd(name) 43029088Smarkm char *name; 43129088Smarkm{ 43229088Smarkm return(send_tncmd(send_do, "do", name)); 43329088Smarkm} 43429088Smarkm 43529088Smarkm static int 43629088Smarkmsend_dontcmd(name) 43729088Smarkm char *name; 43829088Smarkm{ 43929088Smarkm return(send_tncmd(send_dont, "dont", name)); 44029088Smarkm} 44129088Smarkm static int 44229088Smarkmsend_willcmd(name) 44329088Smarkm char *name; 44429088Smarkm{ 44529088Smarkm return(send_tncmd(send_will, "will", name)); 44629088Smarkm} 44729088Smarkm static int 44829088Smarkmsend_wontcmd(name) 44929088Smarkm char *name; 45029088Smarkm{ 45129088Smarkm return(send_tncmd(send_wont, "wont", name)); 45229088Smarkm} 45329088Smarkm 45429088Smarkm int 45529088Smarkmsend_tncmd(func, cmd, name) 45629088Smarkm void (*func)(); 45729088Smarkm char *cmd, *name; 45829088Smarkm{ 45929088Smarkm char **cpp; 46029088Smarkm extern char *telopts[]; 46129088Smarkm register int val = 0; 46229088Smarkm 46329088Smarkm if (isprefix(name, "help") || isprefix(name, "?")) { 46429088Smarkm register int col, len; 46529088Smarkm 46629088Smarkm printf("Usage: send %s <value|option>\n", cmd); 46729088Smarkm printf("\"value\" must be from 0 to 255\n"); 46829088Smarkm printf("Valid options are:\n\t"); 46929088Smarkm 47029088Smarkm col = 8; 47129088Smarkm for (cpp = telopts; *cpp; cpp++) { 47229088Smarkm len = strlen(*cpp) + 3; 47329088Smarkm if (col + len > 65) { 47429088Smarkm printf("\n\t"); 47529088Smarkm col = 8; 47629088Smarkm } 47729088Smarkm printf(" \"%s\"", *cpp); 47829088Smarkm col += len; 47929088Smarkm } 48029088Smarkm printf("\n"); 48129088Smarkm return 0; 48229088Smarkm } 48329088Smarkm cpp = (char **)genget(name, telopts, sizeof(char *)); 48429088Smarkm if (Ambiguous(cpp)) { 48529088Smarkm fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", 48629088Smarkm name, cmd); 48729088Smarkm return 0; 48829088Smarkm } 48929088Smarkm if (cpp) { 49029088Smarkm val = cpp - telopts; 49129088Smarkm } else { 49229088Smarkm register char *cp = name; 49329088Smarkm 49429088Smarkm while (*cp >= '0' && *cp <= '9') { 49529088Smarkm val *= 10; 49629088Smarkm val += *cp - '0'; 49729088Smarkm cp++; 49829088Smarkm } 49929088Smarkm if (*cp != 0) { 50029088Smarkm fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", 50129088Smarkm name, cmd); 50229088Smarkm return 0; 50329088Smarkm } else if (val < 0 || val > 255) { 50429088Smarkm fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", 50529088Smarkm name, cmd); 50629088Smarkm return 0; 50729088Smarkm } 50829088Smarkm } 50929088Smarkm if (!connected) { 51029088Smarkm printf("?Need to be connected first.\n"); 51129088Smarkm return 0; 51229088Smarkm } 51329088Smarkm (*func)(val, 1); 51429088Smarkm return 1; 51529088Smarkm} 51629088Smarkm 51729088Smarkm static int 51829088Smarkmsend_help() 51929088Smarkm{ 52029088Smarkm struct sendlist *s; /* pointer to current command */ 52129088Smarkm for (s = Sendlist; s->name; s++) { 52229088Smarkm if (s->help) 52329088Smarkm printf("%-15s %s\n", s->name, s->help); 52429088Smarkm } 52529088Smarkm return(0); 52629088Smarkm} 52729088Smarkm 52829088Smarkm/* 52929088Smarkm * The following are the routines and data structures referred 53029088Smarkm * to by the arguments to the "toggle" command. 53129088Smarkm */ 53229088Smarkm 53329088Smarkm static int 53429088Smarkmlclchars() 53529088Smarkm{ 53629088Smarkm donelclchars = 1; 53729088Smarkm return 1; 53829088Smarkm} 53929088Smarkm 54029088Smarkm static int 54129088Smarkmtogdebug() 54229088Smarkm{ 54329088Smarkm#ifndef NOT43 54429088Smarkm if (net > 0 && 54529088Smarkm (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { 54629088Smarkm perror("setsockopt (SO_DEBUG)"); 54729088Smarkm } 54829088Smarkm#else /* NOT43 */ 54929088Smarkm if (debug) { 55029181Smarkm if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) 55129088Smarkm perror("setsockopt (SO_DEBUG)"); 55229088Smarkm } else 55329088Smarkm printf("Cannot turn off socket debugging\n"); 55429088Smarkm#endif /* NOT43 */ 55529088Smarkm return 1; 55629088Smarkm} 55729088Smarkm 55829088Smarkm 55929088Smarkm static int 56029088Smarkmtogcrlf() 56129088Smarkm{ 56229088Smarkm if (crlf) { 56329088Smarkm printf("Will send carriage returns as telnet <CR><LF>.\n"); 56429088Smarkm } else { 56529088Smarkm printf("Will send carriage returns as telnet <CR><NUL>.\n"); 56629088Smarkm } 56729088Smarkm return 1; 56829088Smarkm} 56929088Smarkm 57029088Smarkmint binmode; 57129088Smarkm 57229088Smarkm static int 57329088Smarkmtogbinary(val) 57429088Smarkm int val; 57529088Smarkm{ 57629088Smarkm donebinarytoggle = 1; 57729088Smarkm 57829088Smarkm if (val >= 0) { 57929088Smarkm binmode = val; 58029088Smarkm } else { 58129088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 58229088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 58329088Smarkm binmode = 1; 58429088Smarkm } else if (my_want_state_is_wont(TELOPT_BINARY) && 58529088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 58629088Smarkm binmode = 0; 58729088Smarkm } 58829088Smarkm val = binmode ? 0 : 1; 58929088Smarkm } 59029088Smarkm 59129088Smarkm if (val == 1) { 59229088Smarkm if (my_want_state_is_will(TELOPT_BINARY) && 59329088Smarkm my_want_state_is_do(TELOPT_BINARY)) { 59429088Smarkm printf("Already operating in binary mode with remote host.\n"); 59529088Smarkm } else { 59629088Smarkm printf("Negotiating binary mode with remote host.\n"); 59729088Smarkm tel_enter_binary(3); 59829088Smarkm } 59929088Smarkm } else { 60029088Smarkm if (my_want_state_is_wont(TELOPT_BINARY) && 60129088Smarkm my_want_state_is_dont(TELOPT_BINARY)) { 60229088Smarkm printf("Already in network ascii mode with remote host.\n"); 60329088Smarkm } else { 60429088Smarkm printf("Negotiating network ascii mode with remote host.\n"); 60529088Smarkm tel_leave_binary(3); 60629088Smarkm } 60729088Smarkm } 60829088Smarkm return 1; 60929088Smarkm} 61029088Smarkm 61129088Smarkm static int 61229088Smarkmtogrbinary(val) 61329088Smarkm int val; 61429088Smarkm{ 61529088Smarkm donebinarytoggle = 1; 61629088Smarkm 61729088Smarkm if (val == -1) 61829088Smarkm val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; 61929088Smarkm 62029088Smarkm if (val == 1) { 62129088Smarkm if (my_want_state_is_do(TELOPT_BINARY)) { 62229088Smarkm printf("Already receiving in binary mode.\n"); 62329088Smarkm } else { 62429088Smarkm printf("Negotiating binary mode on input.\n"); 62529088Smarkm tel_enter_binary(1); 62629088Smarkm } 62729088Smarkm } else { 62829088Smarkm if (my_want_state_is_dont(TELOPT_BINARY)) { 62929088Smarkm printf("Already receiving in network ascii mode.\n"); 63029088Smarkm } else { 63129088Smarkm printf("Negotiating network ascii mode on input.\n"); 63229088Smarkm tel_leave_binary(1); 63329088Smarkm } 63429088Smarkm } 63529088Smarkm return 1; 63629088Smarkm} 63729088Smarkm 63829088Smarkm static int 63929088Smarkmtogxbinary(val) 64029088Smarkm int val; 64129088Smarkm{ 64229088Smarkm donebinarytoggle = 1; 64329088Smarkm 64429088Smarkm if (val == -1) 64529088Smarkm val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; 64629088Smarkm 64729088Smarkm if (val == 1) { 64829088Smarkm if (my_want_state_is_will(TELOPT_BINARY)) { 64929088Smarkm printf("Already transmitting in binary mode.\n"); 65029088Smarkm } else { 65129088Smarkm printf("Negotiating binary mode on output.\n"); 65229088Smarkm tel_enter_binary(2); 65329088Smarkm } 65429088Smarkm } else { 65529088Smarkm if (my_want_state_is_wont(TELOPT_BINARY)) { 65629088Smarkm printf("Already transmitting in network ascii mode.\n"); 65729088Smarkm } else { 65829088Smarkm printf("Negotiating network ascii mode on output.\n"); 65929088Smarkm tel_leave_binary(2); 66029088Smarkm } 66129088Smarkm } 66229088Smarkm return 1; 66329088Smarkm} 66429088Smarkm 66529088Smarkm 66629088Smarkmstatic int togglehelp P((void)); 66729088Smarkm#if defined(AUTHENTICATION) 66829088Smarkmextern int auth_togdebug P((int)); 66929088Smarkm#endif 67029088Smarkm#ifdef ENCRYPTION 67129088Smarkmextern int EncryptAutoEnc P((int)); 67229088Smarkmextern int EncryptAutoDec P((int)); 67329088Smarkmextern int EncryptDebug P((int)); 67429088Smarkmextern int EncryptVerbose P((int)); 67529088Smarkm#endif /* ENCRYPTION */ 67629088Smarkm 67729088Smarkmstruct togglelist { 67829088Smarkm char *name; /* name of toggle */ 67929088Smarkm char *help; /* help message */ 68029088Smarkm int (*handler)(); /* routine to do actual setting */ 68129088Smarkm int *variable; 68229088Smarkm char *actionexplanation; 68329088Smarkm}; 68429088Smarkm 68529088Smarkmstatic struct togglelist Togglelist[] = { 68629088Smarkm { "autoflush", 68729088Smarkm "flushing of output when sending interrupt characters", 68829088Smarkm 0, 68929088Smarkm &autoflush, 69029088Smarkm "flush output when sending interrupt characters" }, 69129088Smarkm { "autosynch", 69229088Smarkm "automatic sending of interrupt characters in urgent mode", 69329088Smarkm 0, 69429088Smarkm &autosynch, 69529088Smarkm "send interrupt characters in urgent mode" }, 69629088Smarkm#if defined(AUTHENTICATION) 69729088Smarkm { "autologin", 69829088Smarkm "automatic sending of login and/or authentication info", 69929088Smarkm 0, 70029088Smarkm &autologin, 70129088Smarkm "send login name and/or authentication information" }, 70229088Smarkm { "authdebug", 70329088Smarkm "Toggle authentication debugging", 70429088Smarkm auth_togdebug, 70529088Smarkm 0, 70629088Smarkm "print authentication debugging information" }, 70729088Smarkm#endif 70829088Smarkm#ifdef ENCRYPTION 70929088Smarkm { "autoencrypt", 71029088Smarkm "automatic encryption of data stream", 71129088Smarkm EncryptAutoEnc, 71229088Smarkm 0, 71329088Smarkm "automatically encrypt output" }, 71429088Smarkm { "autodecrypt", 71529088Smarkm "automatic decryption of data stream", 71629088Smarkm EncryptAutoDec, 71729088Smarkm 0, 71829088Smarkm "automatically decrypt input" }, 71929088Smarkm { "verbose_encrypt", 72029088Smarkm "Toggle verbose encryption output", 72129088Smarkm EncryptVerbose, 72229088Smarkm 0, 72329088Smarkm "print verbose encryption output" }, 72429088Smarkm { "encdebug", 72529088Smarkm "Toggle encryption debugging", 72629088Smarkm EncryptDebug, 72729088Smarkm 0, 72829088Smarkm "print encryption debugging information" }, 72929088Smarkm#endif /* ENCRYPTION */ 73029088Smarkm { "skiprc", 73129088Smarkm "don't read ~/.telnetrc file", 73229088Smarkm 0, 73329088Smarkm &skiprc, 73429088Smarkm "skip reading of ~/.telnetrc file" }, 73529088Smarkm { "binary", 73629088Smarkm "sending and receiving of binary data", 73729088Smarkm togbinary, 73829088Smarkm 0, 73929088Smarkm 0 }, 74029088Smarkm { "inbinary", 74129088Smarkm "receiving of binary data", 74229088Smarkm togrbinary, 74329088Smarkm 0, 74429088Smarkm 0 }, 74529088Smarkm { "outbinary", 74629088Smarkm "sending of binary data", 74729088Smarkm togxbinary, 74829088Smarkm 0, 74929088Smarkm 0 }, 75029088Smarkm { "crlf", 75129088Smarkm "sending carriage returns as telnet <CR><LF>", 75229088Smarkm togcrlf, 75329088Smarkm &crlf, 75429088Smarkm 0 }, 75529088Smarkm { "crmod", 75629088Smarkm "mapping of received carriage returns", 75729088Smarkm 0, 75829088Smarkm &crmod, 75929088Smarkm "map carriage return on output" }, 76029088Smarkm { "localchars", 76129088Smarkm "local recognition of certain control characters", 76229088Smarkm lclchars, 76329088Smarkm &localchars, 76429088Smarkm "recognize certain control characters" }, 76529088Smarkm { " ", "", 0 }, /* empty line */ 76629088Smarkm#if defined(unix) && defined(TN3270) 76729088Smarkm { "apitrace", 76829088Smarkm "(debugging) toggle tracing of API transactions", 76929088Smarkm 0, 77029088Smarkm &apitrace, 77129088Smarkm "trace API transactions" }, 77229088Smarkm { "cursesdata", 77329088Smarkm "(debugging) toggle printing of hexadecimal curses data", 77429088Smarkm 0, 77529088Smarkm &cursesdata, 77629088Smarkm "print hexadecimal representation of curses data" }, 77729088Smarkm#endif /* defined(unix) && defined(TN3270) */ 77829088Smarkm { "debug", 77929088Smarkm "debugging", 78029088Smarkm togdebug, 78129088Smarkm &debug, 78229088Smarkm "turn on socket level debugging" }, 78329088Smarkm { "netdata", 78429088Smarkm "printing of hexadecimal network data (debugging)", 78529088Smarkm 0, 78629088Smarkm &netdata, 78729088Smarkm "print hexadecimal representation of network traffic" }, 78829088Smarkm { "prettydump", 78929088Smarkm "output of \"netdata\" to user readable format (debugging)", 79029088Smarkm 0, 79129088Smarkm &prettydump, 79229088Smarkm "print user readable output for \"netdata\"" }, 79329088Smarkm { "options", 79429088Smarkm "viewing of options processing (debugging)", 79529088Smarkm 0, 79629088Smarkm &showoptions, 79729088Smarkm "show option processing" }, 79829088Smarkm#if defined(unix) 79929088Smarkm { "termdata", 80029088Smarkm "(debugging) toggle printing of hexadecimal terminal data", 80129088Smarkm 0, 80229088Smarkm &termdata, 80329088Smarkm "print hexadecimal representation of terminal traffic" }, 80429088Smarkm#endif /* defined(unix) */ 80529088Smarkm { "?", 80629088Smarkm 0, 80729088Smarkm togglehelp }, 80829088Smarkm { "help", 80929088Smarkm 0, 81029088Smarkm togglehelp }, 81129088Smarkm { 0 } 81229088Smarkm}; 81329088Smarkm 81429088Smarkm static int 81529088Smarkmtogglehelp() 81629088Smarkm{ 81729088Smarkm struct togglelist *c; 81829088Smarkm 81929088Smarkm for (c = Togglelist; c->name; c++) { 82029088Smarkm if (c->help) { 82129088Smarkm if (*c->help) 82229088Smarkm printf("%-15s toggle %s\n", c->name, c->help); 82329088Smarkm else 82429088Smarkm printf("\n"); 82529088Smarkm } 82629088Smarkm } 82729088Smarkm printf("\n"); 82829088Smarkm printf("%-15s %s\n", "?", "display help information"); 82929088Smarkm return 0; 83029088Smarkm} 83129088Smarkm 83229088Smarkm static void 83329088Smarkmsettogglehelp(set) 83429088Smarkm int set; 83529088Smarkm{ 83629088Smarkm struct togglelist *c; 83729088Smarkm 83829088Smarkm for (c = Togglelist; c->name; c++) { 83929088Smarkm if (c->help) { 84029088Smarkm if (*c->help) 84129088Smarkm printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", 84229088Smarkm c->help); 84329088Smarkm else 84429088Smarkm printf("\n"); 84529088Smarkm } 84629088Smarkm } 84729088Smarkm} 84829088Smarkm 84929088Smarkm#define GETTOGGLE(name) (struct togglelist *) \ 85029088Smarkm genget(name, (char **) Togglelist, sizeof(struct togglelist)) 85129088Smarkm 85229088Smarkm static int 85329088Smarkmtoggle(argc, argv) 85429088Smarkm int argc; 85529088Smarkm char *argv[]; 85629088Smarkm{ 85729088Smarkm int retval = 1; 85829088Smarkm char *name; 85929088Smarkm struct togglelist *c; 86029088Smarkm 86129088Smarkm if (argc < 2) { 86229088Smarkm fprintf(stderr, 86329088Smarkm "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); 86429088Smarkm return 0; 86529088Smarkm } 86629088Smarkm argc--; 86729088Smarkm argv++; 86829088Smarkm while (argc--) { 86929088Smarkm name = *argv++; 87029088Smarkm c = GETTOGGLE(name); 87129088Smarkm if (Ambiguous(c)) { 87229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", 87329088Smarkm name); 87429088Smarkm return 0; 87529088Smarkm } else if (c == 0) { 87629088Smarkm fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", 87729088Smarkm name); 87829088Smarkm return 0; 87929088Smarkm } else { 88029088Smarkm if (c->variable) { 88129088Smarkm *c->variable = !*c->variable; /* invert it */ 88229088Smarkm if (c->actionexplanation) { 88329088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 88429088Smarkm c->actionexplanation); 88529088Smarkm } 88629088Smarkm } 88729088Smarkm if (c->handler) { 88829088Smarkm retval &= (*c->handler)(-1); 88929088Smarkm } 89029088Smarkm } 89129088Smarkm } 89229088Smarkm return retval; 89329088Smarkm} 89429088Smarkm 89529088Smarkm/* 89629088Smarkm * The following perform the "set" command. 89729088Smarkm */ 89829088Smarkm 89929088Smarkm#ifdef USE_TERMIO 90029088Smarkmstruct termio new_tc = { 0 }; 90129088Smarkm#endif 90229088Smarkm 90329088Smarkmstruct setlist { 90429088Smarkm char *name; /* name */ 90529088Smarkm char *help; /* help information */ 90629088Smarkm void (*handler)(); 90729088Smarkm cc_t *charp; /* where it is located at */ 90829088Smarkm}; 90929088Smarkm 91029088Smarkmstatic struct setlist Setlist[] = { 91129088Smarkm#ifdef KLUDGELINEMODE 91229088Smarkm { "echo", "character to toggle local echoing on/off", 0, &echoc }, 91329088Smarkm#endif 91429088Smarkm { "escape", "character to escape back to telnet command mode", 0, &escape }, 91529088Smarkm { "rlogin", "rlogin escape character", 0, &rlogin }, 91629088Smarkm { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, 91729088Smarkm { " ", "" }, 91829088Smarkm { " ", "The following need 'localchars' to be toggled true", 0, 0 }, 91929088Smarkm { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, 92029088Smarkm { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, 92129088Smarkm { "quit", "character to cause an Abort process", 0, termQuitCharp }, 92229088Smarkm { "eof", "character to cause an EOF ", 0, termEofCharp }, 92329088Smarkm { " ", "" }, 92429088Smarkm { " ", "The following are for local editing in linemode", 0, 0 }, 92529088Smarkm { "erase", "character to use to erase a character", 0, termEraseCharp }, 92629088Smarkm { "kill", "character to use to erase a line", 0, termKillCharp }, 92729088Smarkm { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, 92829088Smarkm { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, 92929088Smarkm { "reprint", "character to use for line reprint", 0, termRprntCharp }, 93029088Smarkm { "worderase", "character to use to erase a word", 0, termWerasCharp }, 93129088Smarkm { "start", "character to use for XON", 0, termStartCharp }, 93229088Smarkm { "stop", "character to use for XOFF", 0, termStopCharp }, 93329088Smarkm { "forw1", "alternate end of line character", 0, termForw1Charp }, 93429088Smarkm { "forw2", "alternate end of line character", 0, termForw2Charp }, 93529088Smarkm { "ayt", "alternate AYT character", 0, termAytCharp }, 93629088Smarkm { 0 } 93729088Smarkm}; 93829088Smarkm 93929088Smarkm#if defined(CRAY) && !defined(__STDC__) 94029088Smarkm/* Work around compiler bug in pcc 4.1.5 */ 94129088Smarkm void 94229088Smarkm_setlist_init() 94329088Smarkm{ 94429088Smarkm#ifndef KLUDGELINEMODE 94529088Smarkm#define N 5 94629088Smarkm#else 94729088Smarkm#define N 6 94829088Smarkm#endif 94929088Smarkm Setlist[N+0].charp = &termFlushChar; 95029088Smarkm Setlist[N+1].charp = &termIntChar; 95129088Smarkm Setlist[N+2].charp = &termQuitChar; 95229088Smarkm Setlist[N+3].charp = &termEofChar; 95329088Smarkm Setlist[N+6].charp = &termEraseChar; 95429088Smarkm Setlist[N+7].charp = &termKillChar; 95529088Smarkm Setlist[N+8].charp = &termLiteralNextChar; 95629088Smarkm Setlist[N+9].charp = &termSuspChar; 95729088Smarkm Setlist[N+10].charp = &termRprntChar; 95829088Smarkm Setlist[N+11].charp = &termWerasChar; 95929088Smarkm Setlist[N+12].charp = &termStartChar; 96029088Smarkm Setlist[N+13].charp = &termStopChar; 96129088Smarkm Setlist[N+14].charp = &termForw1Char; 96229088Smarkm Setlist[N+15].charp = &termForw2Char; 96329088Smarkm Setlist[N+16].charp = &termAytChar; 96429088Smarkm#undef N 96529088Smarkm} 96629088Smarkm#endif /* defined(CRAY) && !defined(__STDC__) */ 96729088Smarkm 96829088Smarkm static struct setlist * 96929088Smarkmgetset(name) 97029088Smarkm char *name; 97129088Smarkm{ 97229088Smarkm return (struct setlist *) 97329088Smarkm genget(name, (char **) Setlist, sizeof(struct setlist)); 97429088Smarkm} 97529088Smarkm 97629088Smarkm void 97729088Smarkmset_escape_char(s) 97829088Smarkm char *s; 97929088Smarkm{ 98029088Smarkm if (rlogin != _POSIX_VDISABLE) { 98129088Smarkm rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; 98229088Smarkm printf("Telnet rlogin escape character is '%s'.\n", 98329088Smarkm control(rlogin)); 98429088Smarkm } else { 98529088Smarkm escape = (s && *s) ? special(s) : _POSIX_VDISABLE; 98629088Smarkm printf("Telnet escape character is '%s'.\n", control(escape)); 98729088Smarkm } 98829088Smarkm} 98929088Smarkm 99029088Smarkm static int 99129088Smarkmsetcmd(argc, argv) 99229088Smarkm int argc; 99329088Smarkm char *argv[]; 99429088Smarkm{ 99529088Smarkm int value; 99629088Smarkm struct setlist *ct; 99729088Smarkm struct togglelist *c; 99829088Smarkm 99929088Smarkm if (argc < 2 || argc > 3) { 100029088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 100129088Smarkm return 0; 100229088Smarkm } 100329088Smarkm if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { 100429088Smarkm for (ct = Setlist; ct->name; ct++) 100529088Smarkm printf("%-15s %s\n", ct->name, ct->help); 100629088Smarkm printf("\n"); 100729088Smarkm settogglehelp(1); 100829088Smarkm printf("%-15s %s\n", "?", "display help information"); 100929088Smarkm return 0; 101029088Smarkm } 101129088Smarkm 101229088Smarkm ct = getset(argv[1]); 101329088Smarkm if (ct == 0) { 101429088Smarkm c = GETTOGGLE(argv[1]); 101529088Smarkm if (c == 0) { 101629088Smarkm fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", 101729088Smarkm argv[1]); 101829088Smarkm return 0; 101929088Smarkm } else if (Ambiguous(c)) { 102029088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 102129088Smarkm argv[1]); 102229088Smarkm return 0; 102329088Smarkm } 102429088Smarkm if (c->variable) { 102529088Smarkm if ((argc == 2) || (strcmp("on", argv[2]) == 0)) 102629088Smarkm *c->variable = 1; 102729088Smarkm else if (strcmp("off", argv[2]) == 0) 102829088Smarkm *c->variable = 0; 102929088Smarkm else { 103029088Smarkm printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); 103129088Smarkm return 0; 103229088Smarkm } 103329088Smarkm if (c->actionexplanation) { 103429088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 103529088Smarkm c->actionexplanation); 103629088Smarkm } 103729088Smarkm } 103829088Smarkm if (c->handler) 103929088Smarkm (*c->handler)(1); 104029088Smarkm } else if (argc != 3) { 104129088Smarkm printf("Format is 'set Name Value'\n'set ?' for help.\n"); 104229088Smarkm return 0; 104329088Smarkm } else if (Ambiguous(ct)) { 104429088Smarkm fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", 104529088Smarkm argv[1]); 104629088Smarkm return 0; 104729088Smarkm } else if (ct->handler) { 104829088Smarkm (*ct->handler)(argv[2]); 104929088Smarkm printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); 105029088Smarkm } else { 105129088Smarkm if (strcmp("off", argv[2])) { 105229088Smarkm value = special(argv[2]); 105329088Smarkm } else { 105429088Smarkm value = _POSIX_VDISABLE; 105529088Smarkm } 105629088Smarkm *(ct->charp) = (cc_t)value; 105729088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 105829088Smarkm } 105929088Smarkm slc_check(); 106029088Smarkm return 1; 106129088Smarkm} 106229088Smarkm 106329088Smarkm static int 106429088Smarkmunsetcmd(argc, argv) 106529088Smarkm int argc; 106629088Smarkm char *argv[]; 106729088Smarkm{ 106829088Smarkm struct setlist *ct; 106929088Smarkm struct togglelist *c; 107029088Smarkm register char *name; 107129088Smarkm 107229088Smarkm if (argc < 2) { 107329088Smarkm fprintf(stderr, 107429088Smarkm "Need an argument to 'unset' command. 'unset ?' for help.\n"); 107529088Smarkm return 0; 107629088Smarkm } 107729088Smarkm if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { 107829088Smarkm for (ct = Setlist; ct->name; ct++) 107929088Smarkm printf("%-15s %s\n", ct->name, ct->help); 108029088Smarkm printf("\n"); 108129088Smarkm settogglehelp(0); 108229088Smarkm printf("%-15s %s\n", "?", "display help information"); 108329088Smarkm return 0; 108429088Smarkm } 108529088Smarkm 108629088Smarkm argc--; 108729088Smarkm argv++; 108829088Smarkm while (argc--) { 108929088Smarkm name = *argv++; 109029088Smarkm ct = getset(name); 109129088Smarkm if (ct == 0) { 109229088Smarkm c = GETTOGGLE(name); 109329088Smarkm if (c == 0) { 109429088Smarkm fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", 109529088Smarkm name); 109629088Smarkm return 0; 109729088Smarkm } else if (Ambiguous(c)) { 109829088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 109929088Smarkm name); 110029088Smarkm return 0; 110129088Smarkm } 110229088Smarkm if (c->variable) { 110329088Smarkm *c->variable = 0; 110429088Smarkm if (c->actionexplanation) { 110529088Smarkm printf("%s %s.\n", *c->variable? "Will" : "Won't", 110629088Smarkm c->actionexplanation); 110729088Smarkm } 110829088Smarkm } 110929088Smarkm if (c->handler) 111029088Smarkm (*c->handler)(0); 111129088Smarkm } else if (Ambiguous(ct)) { 111229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", 111329088Smarkm name); 111429088Smarkm return 0; 111529088Smarkm } else if (ct->handler) { 111629088Smarkm (*ct->handler)(0); 111729088Smarkm printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); 111829088Smarkm } else { 111929088Smarkm *(ct->charp) = _POSIX_VDISABLE; 112029088Smarkm printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); 112129088Smarkm } 112229088Smarkm } 112329088Smarkm return 1; 112429088Smarkm} 112529088Smarkm 112629088Smarkm/* 112729088Smarkm * The following are the data structures and routines for the 112829088Smarkm * 'mode' command. 112929088Smarkm */ 113029088Smarkm#ifdef KLUDGELINEMODE 113129088Smarkmextern int kludgelinemode; 113229088Smarkm 113347973Sru static int 113429088Smarkmdokludgemode() 113529088Smarkm{ 113629088Smarkm kludgelinemode = 1; 113729088Smarkm send_wont(TELOPT_LINEMODE, 1); 113829088Smarkm send_dont(TELOPT_SGA, 1); 113929088Smarkm send_dont(TELOPT_ECHO, 1); 114049861Snsayer return 1; 114129088Smarkm} 114229088Smarkm#endif 114329088Smarkm 114429088Smarkm static int 114529088Smarkmdolinemode() 114629088Smarkm{ 114729088Smarkm#ifdef KLUDGELINEMODE 114829088Smarkm if (kludgelinemode) 114929088Smarkm send_dont(TELOPT_SGA, 1); 115029088Smarkm#endif 115129088Smarkm send_will(TELOPT_LINEMODE, 1); 115229088Smarkm send_dont(TELOPT_ECHO, 1); 115329088Smarkm return 1; 115429088Smarkm} 115529088Smarkm 115629088Smarkm static int 115729088Smarkmdocharmode() 115829088Smarkm{ 115929088Smarkm#ifdef KLUDGELINEMODE 116029088Smarkm if (kludgelinemode) 116129088Smarkm send_do(TELOPT_SGA, 1); 116229088Smarkm else 116329088Smarkm#endif 116429088Smarkm send_wont(TELOPT_LINEMODE, 1); 116529088Smarkm send_do(TELOPT_ECHO, 1); 116629088Smarkm return 1; 116729088Smarkm} 116829088Smarkm 116929088Smarkm static int 117029088Smarkmdolmmode(bit, on) 117129088Smarkm int bit, on; 117229088Smarkm{ 117329088Smarkm unsigned char c; 117429088Smarkm extern int linemode; 117529088Smarkm 117629088Smarkm if (my_want_state_is_wont(TELOPT_LINEMODE)) { 117729088Smarkm printf("?Need to have LINEMODE option enabled first.\n"); 117829088Smarkm printf("'mode ?' for help.\n"); 117929088Smarkm return 0; 118029088Smarkm } 118129088Smarkm 118229088Smarkm if (on) 118329088Smarkm c = (linemode | bit); 118429088Smarkm else 118529088Smarkm c = (linemode & ~bit); 118629088Smarkm lm_mode(&c, 1, 1); 118729088Smarkm return 1; 118829088Smarkm} 118929088Smarkm 119029088Smarkm int 119129181Smarkmsetmod(bit) 119229088Smarkm{ 119329088Smarkm return dolmmode(bit, 1); 119429088Smarkm} 119529088Smarkm 119629088Smarkm int 119729088Smarkmclearmode(bit) 119829088Smarkm{ 119929088Smarkm return dolmmode(bit, 0); 120029088Smarkm} 120129088Smarkm 120229088Smarkmstruct modelist { 120329088Smarkm char *name; /* command name */ 120429088Smarkm char *help; /* help string */ 120529088Smarkm int (*handler)(); /* routine which executes command */ 120629088Smarkm int needconnect; /* Do we need to be connected to execute? */ 120729088Smarkm int arg1; 120829088Smarkm}; 120929088Smarkm 121029088Smarkmextern int modehelp(); 121129088Smarkm 121229088Smarkmstatic struct modelist ModeList[] = { 121329088Smarkm { "character", "Disable LINEMODE option", docharmode, 1 }, 121429088Smarkm#ifdef KLUDGELINEMODE 121529088Smarkm { "", "(or disable obsolete line-by-line mode)", 0 }, 121629088Smarkm#endif 121729088Smarkm { "line", "Enable LINEMODE option", dolinemode, 1 }, 121829088Smarkm#ifdef KLUDGELINEMODE 121929088Smarkm { "", "(or enable obsolete line-by-line mode)", 0 }, 122029088Smarkm#endif 122129088Smarkm { "", "", 0 }, 122229088Smarkm { "", "These require the LINEMODE option to be enabled", 0 }, 122329181Smarkm { "isig", "Enable signal trapping", setmod, 1, MODE_TRAPSIG }, 122429181Smarkm { "+isig", 0, setmod, 1, MODE_TRAPSIG }, 122529088Smarkm { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, 122629181Smarkm { "edit", "Enable character editing", setmod, 1, MODE_EDIT }, 122729181Smarkm { "+edit", 0, setmod, 1, MODE_EDIT }, 122829088Smarkm { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, 122929181Smarkm { "softtabs", "Enable tab expansion", setmod, 1, MODE_SOFT_TAB }, 123029181Smarkm { "+softtabs", 0, setmod, 1, MODE_SOFT_TAB }, 123129088Smarkm { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, 123229181Smarkm { "litecho", "Enable literal character echo", setmod, 1, MODE_LIT_ECHO }, 123329181Smarkm { "+litecho", 0, setmod, 1, MODE_LIT_ECHO }, 123429088Smarkm { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, 123529088Smarkm { "help", 0, modehelp, 0 }, 123629088Smarkm#ifdef KLUDGELINEMODE 123729088Smarkm { "kludgeline", 0, dokludgemode, 1 }, 123829088Smarkm#endif 123929088Smarkm { "", "", 0 }, 124029088Smarkm { "?", "Print help information", modehelp, 0 }, 124129088Smarkm { 0 }, 124229088Smarkm}; 124329088Smarkm 124429088Smarkm 124529088Smarkm int 124629088Smarkmmodehelp() 124729088Smarkm{ 124829088Smarkm struct modelist *mt; 124929088Smarkm 125029088Smarkm printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); 125129088Smarkm for (mt = ModeList; mt->name; mt++) { 125229088Smarkm if (mt->help) { 125329088Smarkm if (*mt->help) 125429088Smarkm printf("%-15s %s\n", mt->name, mt->help); 125529088Smarkm else 125629088Smarkm printf("\n"); 125729088Smarkm } 125829088Smarkm } 125929088Smarkm return 0; 126029088Smarkm} 126129088Smarkm 126229088Smarkm#define GETMODECMD(name) (struct modelist *) \ 126329088Smarkm genget(name, (char **) ModeList, sizeof(struct modelist)) 126429088Smarkm 126529088Smarkm static int 126629088Smarkmmodecmd(argc, argv) 126729088Smarkm int argc; 126829088Smarkm char *argv[]; 126929088Smarkm{ 127029088Smarkm struct modelist *mt; 127129088Smarkm 127229088Smarkm if (argc != 2) { 127329088Smarkm printf("'mode' command requires an argument\n"); 127429088Smarkm printf("'mode ?' for help.\n"); 127529088Smarkm } else if ((mt = GETMODECMD(argv[1])) == 0) { 127629088Smarkm fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); 127729088Smarkm } else if (Ambiguous(mt)) { 127829088Smarkm fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); 127929088Smarkm } else if (mt->needconnect && !connected) { 128029088Smarkm printf("?Need to be connected first.\n"); 128129088Smarkm printf("'mode ?' for help.\n"); 128229088Smarkm } else if (mt->handler) { 128329088Smarkm return (*mt->handler)(mt->arg1); 128429088Smarkm } 128529088Smarkm return 0; 128629088Smarkm} 128729088Smarkm 128829088Smarkm/* 128929088Smarkm * The following data structures and routines implement the 129029088Smarkm * "display" command. 129129088Smarkm */ 129229088Smarkm 129329088Smarkm static int 129429088Smarkmdisplay(argc, argv) 129529088Smarkm int argc; 129629088Smarkm char *argv[]; 129729088Smarkm{ 129829088Smarkm struct togglelist *tl; 129929088Smarkm struct setlist *sl; 130029088Smarkm 130129088Smarkm#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ 130229088Smarkm if (*tl->variable) { \ 130329088Smarkm printf("will"); \ 130429088Smarkm } else { \ 130529088Smarkm printf("won't"); \ 130629088Smarkm } \ 130729088Smarkm printf(" %s.\n", tl->actionexplanation); \ 130829088Smarkm } 130929088Smarkm 131029088Smarkm#define doset(sl) if (sl->name && *sl->name != ' ') { \ 131129088Smarkm if (sl->handler == 0) \ 131229088Smarkm printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ 131329088Smarkm else \ 131429088Smarkm printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ 131529088Smarkm } 131629088Smarkm 131729088Smarkm if (argc == 1) { 131829088Smarkm for (tl = Togglelist; tl->name; tl++) { 131929088Smarkm dotog(tl); 132029088Smarkm } 132129088Smarkm printf("\n"); 132229088Smarkm for (sl = Setlist; sl->name; sl++) { 132329088Smarkm doset(sl); 132429088Smarkm } 132529088Smarkm } else { 132629088Smarkm int i; 132729088Smarkm 132829088Smarkm for (i = 1; i < argc; i++) { 132929088Smarkm sl = getset(argv[i]); 133029088Smarkm tl = GETTOGGLE(argv[i]); 133129088Smarkm if (Ambiguous(sl) || Ambiguous(tl)) { 133229088Smarkm printf("?Ambiguous argument '%s'.\n", argv[i]); 133329088Smarkm return 0; 133429088Smarkm } else if (!sl && !tl) { 133529088Smarkm printf("?Unknown argument '%s'.\n", argv[i]); 133629088Smarkm return 0; 133729088Smarkm } else { 133829088Smarkm if (tl) { 133929088Smarkm dotog(tl); 134029088Smarkm } 134129088Smarkm if (sl) { 134229088Smarkm doset(sl); 134329088Smarkm } 134429088Smarkm } 134529088Smarkm } 134629088Smarkm } 134729088Smarkm/*@*/optionstatus(); 134829088Smarkm#ifdef ENCRYPTION 134929088Smarkm EncryptStatus(); 135029088Smarkm#endif /* ENCRYPTION */ 135129088Smarkm return 1; 135229088Smarkm#undef doset 135329088Smarkm#undef dotog 135429088Smarkm} 135529088Smarkm 135629088Smarkm/* 135729088Smarkm * The following are the data structures, and many of the routines, 135829088Smarkm * relating to command processing. 135929088Smarkm */ 136029088Smarkm 136129088Smarkm/* 136229088Smarkm * Set the escape character. 136329088Smarkm */ 136429088Smarkm static int 136529088Smarkmsetescape(argc, argv) 136629088Smarkm int argc; 136729088Smarkm char *argv[]; 136829088Smarkm{ 136929088Smarkm register char *arg; 137029088Smarkm char buf[50]; 137129088Smarkm 137229088Smarkm printf( 137329088Smarkm "Deprecated usage - please use 'set escape%s%s' in the future.\n", 137429088Smarkm (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); 137529088Smarkm if (argc > 2) 137629088Smarkm arg = argv[1]; 137729088Smarkm else { 137829088Smarkm printf("new escape character: "); 137929088Smarkm (void) fgets(buf, sizeof(buf), stdin); 138029088Smarkm arg = buf; 138129088Smarkm } 138229088Smarkm if (arg[0] != '\0') 138329088Smarkm escape = arg[0]; 138429088Smarkm if (!In3270) { 138529088Smarkm printf("Escape character is '%s'.\n", control(escape)); 138629088Smarkm } 138729088Smarkm (void) fflush(stdout); 138829088Smarkm return 1; 138929088Smarkm} 139029088Smarkm 139129088Smarkm /*VARARGS*/ 139229088Smarkm static int 139329088Smarkmtogcrmod() 139429088Smarkm{ 139529088Smarkm crmod = !crmod; 139629088Smarkm printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); 139729088Smarkm printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); 139829088Smarkm (void) fflush(stdout); 139929088Smarkm return 1; 140029088Smarkm} 140129088Smarkm 140229088Smarkm /*VARARGS*/ 140329088Smarkm int 140429088Smarkmsuspend() 140529088Smarkm{ 140629088Smarkm#ifdef SIGTSTP 140729088Smarkm setcommandmode(); 140829088Smarkm { 140929088Smarkm long oldrows, oldcols, newrows, newcols, err; 141029088Smarkm 141129088Smarkm err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 141229088Smarkm (void) kill(0, SIGTSTP); 141329088Smarkm /* 141429088Smarkm * If we didn't get the window size before the SUSPEND, but we 141529088Smarkm * can get them now (?), then send the NAWS to make sure that 141629088Smarkm * we are set up for the right window size. 141729088Smarkm */ 141829088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 141929088Smarkm (err || ((oldrows != newrows) || (oldcols != newcols)))) { 142029088Smarkm sendnaws(); 142129088Smarkm } 142229088Smarkm } 142329088Smarkm /* reget parameters in case they were changed */ 142429088Smarkm TerminalSaveState(); 142529088Smarkm setconnmode(0); 142629088Smarkm#else 142729088Smarkm printf("Suspend is not supported. Try the '!' command instead\n"); 142829088Smarkm#endif 142929088Smarkm return 1; 143029088Smarkm} 143129088Smarkm 143229088Smarkm#if !defined(TN3270) 143329088Smarkm /*ARGSUSED*/ 143429088Smarkm int 143529088Smarkmshell(argc, argv) 143629088Smarkm int argc; 143729088Smarkm char *argv[]; 143829088Smarkm{ 143929088Smarkm long oldrows, oldcols, newrows, newcols, err; 144029088Smarkm 144129088Smarkm setcommandmode(); 144229088Smarkm 144329088Smarkm err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; 144429088Smarkm switch(vfork()) { 144529088Smarkm case -1: 144629088Smarkm perror("Fork failed\n"); 144729088Smarkm break; 144829088Smarkm 144929088Smarkm case 0: 145029088Smarkm { 145129088Smarkm /* 145229088Smarkm * Fire up the shell in the child. 145329088Smarkm */ 145429088Smarkm register char *shellp, *shellname; 145529088Smarkm extern char *strrchr(); 145629088Smarkm 145729088Smarkm shellp = getenv("SHELL"); 145829088Smarkm if (shellp == NULL) 145929088Smarkm shellp = "/bin/sh"; 146029088Smarkm if ((shellname = strrchr(shellp, '/')) == 0) 146129088Smarkm shellname = shellp; 146229088Smarkm else 146329088Smarkm shellname++; 146429088Smarkm if (argc > 1) 146529088Smarkm execl(shellp, shellname, "-c", &saveline[1], 0); 146629088Smarkm else 146729088Smarkm execl(shellp, shellname, 0); 146829088Smarkm perror("Execl"); 146929088Smarkm _exit(1); 147029088Smarkm } 147129088Smarkm default: 147229088Smarkm (void)wait((int *)0); /* Wait for the shell to complete */ 147329088Smarkm 147429088Smarkm if (TerminalWindowSize(&newrows, &newcols) && connected && 147529088Smarkm (err || ((oldrows != newrows) || (oldcols != newcols)))) { 147629088Smarkm sendnaws(); 147729088Smarkm } 147829088Smarkm break; 147929088Smarkm } 148029088Smarkm return 1; 148129088Smarkm} 148229088Smarkm#else /* !defined(TN3270) */ 148329088Smarkmextern int shell(); 148429088Smarkm#endif /* !defined(TN3270) */ 148529088Smarkm 148629088Smarkm /*VARARGS*/ 148729181Smarkm static int 148829088Smarkmbye(argc, argv) 148929088Smarkm int argc; /* Number of arguments */ 149029088Smarkm char *argv[]; /* arguments */ 149129088Smarkm{ 149229088Smarkm extern int resettermname; 149329088Smarkm 149429088Smarkm if (connected) { 149529088Smarkm (void) shutdown(net, 2); 149629088Smarkm printf("Connection closed.\n"); 149729088Smarkm (void) NetClose(net); 149829088Smarkm connected = 0; 149929088Smarkm resettermname = 1; 150029088Smarkm#if defined(AUTHENTICATION) || defined(ENCRYPTION) 150129088Smarkm auth_encrypt_connect(connected); 150229088Smarkm#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 150329088Smarkm /* reset options */ 150429088Smarkm tninit(); 150529088Smarkm#if defined(TN3270) 150629088Smarkm SetIn3270(); /* Get out of 3270 mode */ 150729088Smarkm#endif /* defined(TN3270) */ 150829088Smarkm } 150929088Smarkm if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { 151029088Smarkm longjmp(toplevel, 1); 151129088Smarkm /* NOTREACHED */ 151229088Smarkm } 151329088Smarkm return 1; /* Keep lint, etc., happy */ 151429088Smarkm} 151529088Smarkm 151629088Smarkm/*VARARGS*/ 151729181Smarkm int 151829088Smarkmquit() 151929088Smarkm{ 152029088Smarkm (void) call(bye, "bye", "fromquit", 0); 152129088Smarkm Exit(0); 152229088Smarkm /*NOTREACHED*/ 152329088Smarkm} 152429088Smarkm 152529088Smarkm/*VARARGS*/ 152629088Smarkm int 152729088Smarkmlogout() 152829088Smarkm{ 152929088Smarkm send_do(TELOPT_LOGOUT, 1); 153029088Smarkm (void) netflush(); 153129088Smarkm return 1; 153229088Smarkm} 153329088Smarkm 153429088Smarkm 153529088Smarkm/* 153629088Smarkm * The SLC command. 153729088Smarkm */ 153829088Smarkm 153929088Smarkmstruct slclist { 154029088Smarkm char *name; 154129088Smarkm char *help; 154229088Smarkm void (*handler)(); 154329088Smarkm int arg; 154429088Smarkm}; 154529088Smarkm 154629088Smarkmstatic void slc_help(); 154729088Smarkm 154829088Smarkmstruct slclist SlcList[] = { 154929088Smarkm { "export", "Use local special character definitions", 155029088Smarkm slc_mode_export, 0 }, 155129088Smarkm { "import", "Use remote special character definitions", 155229088Smarkm slc_mode_import, 1 }, 155329088Smarkm { "check", "Verify remote special character definitions", 155429088Smarkm slc_mode_import, 0 }, 155529088Smarkm { "help", 0, slc_help, 0 }, 155629088Smarkm { "?", "Print help information", slc_help, 0 }, 155729088Smarkm { 0 }, 155829088Smarkm}; 155929088Smarkm 156029088Smarkm static void 156129088Smarkmslc_help() 156229088Smarkm{ 156329088Smarkm struct slclist *c; 156429088Smarkm 156529088Smarkm for (c = SlcList; c->name; c++) { 156629088Smarkm if (c->help) { 156729088Smarkm if (*c->help) 156829088Smarkm printf("%-15s %s\n", c->name, c->help); 156929088Smarkm else 157029088Smarkm printf("\n"); 157129088Smarkm } 157229088Smarkm } 157329088Smarkm} 157429088Smarkm 157529088Smarkm static struct slclist * 157629088Smarkmgetslc(name) 157729088Smarkm char *name; 157829088Smarkm{ 157929088Smarkm return (struct slclist *) 158029088Smarkm genget(name, (char **) SlcList, sizeof(struct slclist)); 158129088Smarkm} 158229088Smarkm 158329181Smarkm static int 158429088Smarkmslccmd(argc, argv) 158529088Smarkm int argc; 158629088Smarkm char *argv[]; 158729088Smarkm{ 158829088Smarkm struct slclist *c; 158929088Smarkm 159029088Smarkm if (argc != 2) { 159129088Smarkm fprintf(stderr, 159229088Smarkm "Need an argument to 'slc' command. 'slc ?' for help.\n"); 159329088Smarkm return 0; 159429088Smarkm } 159529088Smarkm c = getslc(argv[1]); 159629088Smarkm if (c == 0) { 159729088Smarkm fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", 159829088Smarkm argv[1]); 159929088Smarkm return 0; 160029088Smarkm } 160129088Smarkm if (Ambiguous(c)) { 160229088Smarkm fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", 160329088Smarkm argv[1]); 160429088Smarkm return 0; 160529088Smarkm } 160629088Smarkm (*c->handler)(c->arg); 160729088Smarkm slcstate(); 160829088Smarkm return 1; 160929088Smarkm} 161029088Smarkm 161129088Smarkm/* 161229088Smarkm * The ENVIRON command. 161329088Smarkm */ 161429088Smarkm 161529088Smarkmstruct envlist { 161629088Smarkm char *name; 161729088Smarkm char *help; 161829088Smarkm void (*handler)(); 161929088Smarkm int narg; 162029088Smarkm}; 162129088Smarkm 162229088Smarkmextern struct env_lst * 162329088Smarkm env_define P((unsigned char *, unsigned char *)); 162429088Smarkmextern void 162529088Smarkm env_undefine P((unsigned char *)), 162629088Smarkm env_export P((unsigned char *)), 162729088Smarkm env_unexport P((unsigned char *)), 162829088Smarkm env_send P((unsigned char *)), 162929088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 163029088Smarkm env_varval P((unsigned char *)), 163129088Smarkm#endif 163229088Smarkm env_list P((void)); 163329088Smarkmstatic void 163429088Smarkm env_help P((void)); 163529088Smarkm 163629088Smarkmstruct envlist EnvList[] = { 163729088Smarkm { "define", "Define an environment variable", 163829088Smarkm (void (*)())env_define, 2 }, 163929088Smarkm { "undefine", "Undefine an environment variable", 164029088Smarkm env_undefine, 1 }, 164129088Smarkm { "export", "Mark an environment variable for automatic export", 164229088Smarkm env_export, 1 }, 164329088Smarkm { "unexport", "Don't mark an environment variable for automatic export", 164429088Smarkm env_unexport, 1 }, 164529088Smarkm { "send", "Send an environment variable", env_send, 1 }, 164629088Smarkm { "list", "List the current environment variables", 164729088Smarkm env_list, 0 }, 164829088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 164929088Smarkm { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", 165029088Smarkm env_varval, 1 }, 165129088Smarkm#endif 165229088Smarkm { "help", 0, env_help, 0 }, 165329088Smarkm { "?", "Print help information", env_help, 0 }, 165429088Smarkm { 0 }, 165529088Smarkm}; 165629088Smarkm 165729088Smarkm static void 165829088Smarkmenv_help() 165929088Smarkm{ 166029088Smarkm struct envlist *c; 166129088Smarkm 166229088Smarkm for (c = EnvList; c->name; c++) { 166329088Smarkm if (c->help) { 166429088Smarkm if (*c->help) 166529088Smarkm printf("%-15s %s\n", c->name, c->help); 166629088Smarkm else 166729088Smarkm printf("\n"); 166829088Smarkm } 166929088Smarkm } 167029088Smarkm} 167129088Smarkm 167229088Smarkm static struct envlist * 167329088Smarkmgetenvcmd(name) 167429088Smarkm char *name; 167529088Smarkm{ 167629088Smarkm return (struct envlist *) 167729088Smarkm genget(name, (char **) EnvList, sizeof(struct envlist)); 167829088Smarkm} 167929088Smarkm 168029181Smarkm int 168129088Smarkmenv_cmd(argc, argv) 168229088Smarkm int argc; 168329088Smarkm char *argv[]; 168429088Smarkm{ 168529088Smarkm struct envlist *c; 168629088Smarkm 168729088Smarkm if (argc < 2) { 168829088Smarkm fprintf(stderr, 168929088Smarkm "Need an argument to 'environ' command. 'environ ?' for help.\n"); 169029088Smarkm return 0; 169129088Smarkm } 169229088Smarkm c = getenvcmd(argv[1]); 169329088Smarkm if (c == 0) { 169429088Smarkm fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", 169529088Smarkm argv[1]); 169629088Smarkm return 0; 169729088Smarkm } 169829088Smarkm if (Ambiguous(c)) { 169929088Smarkm fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", 170029088Smarkm argv[1]); 170129088Smarkm return 0; 170229088Smarkm } 170329088Smarkm if (c->narg + 2 != argc) { 170429088Smarkm fprintf(stderr, 170529088Smarkm "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", 170629088Smarkm c->narg < argc + 2 ? "only " : "", 170729088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 170829088Smarkm return 0; 170929088Smarkm } 171029088Smarkm (*c->handler)(argv[2], argv[3]); 171129088Smarkm return 1; 171229088Smarkm} 171329088Smarkm 171429088Smarkmstruct env_lst { 171529088Smarkm struct env_lst *next; /* pointer to next structure */ 171629088Smarkm struct env_lst *prev; /* pointer to previous structure */ 171729088Smarkm unsigned char *var; /* pointer to variable name */ 171829088Smarkm unsigned char *value; /* pointer to variable value */ 171929088Smarkm int export; /* 1 -> export with default list of variables */ 172029088Smarkm int welldefined; /* A well defined variable */ 172129088Smarkm}; 172229088Smarkm 172329088Smarkmstruct env_lst envlisthead; 172429088Smarkm 172529088Smarkm struct env_lst * 172629088Smarkmenv_find(var) 172729088Smarkm unsigned char *var; 172829088Smarkm{ 172929088Smarkm register struct env_lst *ep; 173029088Smarkm 173129088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 173229088Smarkm if (strcmp((char *)ep->var, (char *)var) == 0) 173329088Smarkm return(ep); 173429088Smarkm } 173529088Smarkm return(NULL); 173629088Smarkm} 173729088Smarkm 173829088Smarkm void 173929088Smarkmenv_init() 174029088Smarkm{ 174129088Smarkm extern char **environ; 174229088Smarkm register char **epp, *cp; 174329088Smarkm register struct env_lst *ep; 174429088Smarkm extern char *strchr(); 174529088Smarkm 174629088Smarkm for (epp = environ; *epp; epp++) { 174729181Smarkm if ((cp = strchr(*epp, '='))) { 174829088Smarkm *cp = '\0'; 174929088Smarkm ep = env_define((unsigned char *)*epp, 175029088Smarkm (unsigned char *)cp+1); 175129088Smarkm ep->export = 0; 175229088Smarkm *cp = '='; 175329088Smarkm } 175429088Smarkm } 175529088Smarkm /* 175629088Smarkm * Special case for DISPLAY variable. If it is ":0.0" or 175729088Smarkm * "unix:0.0", we have to get rid of "unix" and insert our 175829088Smarkm * hostname. 175929088Smarkm */ 176029088Smarkm if ((ep = env_find("DISPLAY")) 176129088Smarkm && ((*ep->value == ':') 176229088Smarkm || (strncmp((char *)ep->value, "unix:", 5) == 0))) { 176329088Smarkm char hbuf[256+1]; 176429088Smarkm char *cp2 = strchr((char *)ep->value, ':'); 176529088Smarkm 176629088Smarkm gethostname(hbuf, 256); 176729088Smarkm hbuf[256] = '\0'; 176829088Smarkm cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); 176929088Smarkm sprintf((char *)cp, "%s%s", hbuf, cp2); 177029088Smarkm free(ep->value); 177129088Smarkm ep->value = (unsigned char *)cp; 177229088Smarkm } 177329088Smarkm /* 177429088Smarkm * If USER is not defined, but LOGNAME is, then add 177529088Smarkm * USER with the value from LOGNAME. By default, we 177629088Smarkm * don't export the USER variable. 177729088Smarkm */ 177829088Smarkm if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { 177929088Smarkm env_define((unsigned char *)"USER", ep->value); 178029088Smarkm env_unexport((unsigned char *)"USER"); 178129088Smarkm } 178229088Smarkm env_export((unsigned char *)"DISPLAY"); 178329088Smarkm env_export((unsigned char *)"PRINTER"); 178429088Smarkm} 178529088Smarkm 178629088Smarkm struct env_lst * 178729088Smarkmenv_define(var, value) 178829088Smarkm unsigned char *var, *value; 178929088Smarkm{ 179029088Smarkm register struct env_lst *ep; 179129088Smarkm 179229181Smarkm if ((ep = env_find(var))) { 179329088Smarkm if (ep->var) 179429088Smarkm free(ep->var); 179529088Smarkm if (ep->value) 179629088Smarkm free(ep->value); 179729088Smarkm } else { 179829088Smarkm ep = (struct env_lst *)malloc(sizeof(struct env_lst)); 179929088Smarkm ep->next = envlisthead.next; 180029088Smarkm envlisthead.next = ep; 180129088Smarkm ep->prev = &envlisthead; 180229088Smarkm if (ep->next) 180329088Smarkm ep->next->prev = ep; 180429088Smarkm } 180529088Smarkm ep->welldefined = opt_welldefined(var); 180629088Smarkm ep->export = 1; 180729088Smarkm ep->var = (unsigned char *)strdup((char *)var); 180829088Smarkm ep->value = (unsigned char *)strdup((char *)value); 180929088Smarkm return(ep); 181029088Smarkm} 181129088Smarkm 181229088Smarkm void 181329088Smarkmenv_undefine(var) 181429088Smarkm unsigned char *var; 181529088Smarkm{ 181629088Smarkm register struct env_lst *ep; 181729088Smarkm 181829181Smarkm if ((ep = env_find(var))) { 181929088Smarkm ep->prev->next = ep->next; 182029088Smarkm if (ep->next) 182129088Smarkm ep->next->prev = ep->prev; 182229088Smarkm if (ep->var) 182329088Smarkm free(ep->var); 182429088Smarkm if (ep->value) 182529088Smarkm free(ep->value); 182629088Smarkm free(ep); 182729088Smarkm } 182829088Smarkm} 182929088Smarkm 183029088Smarkm void 183129088Smarkmenv_export(var) 183229088Smarkm unsigned char *var; 183329088Smarkm{ 183429088Smarkm register struct env_lst *ep; 183529088Smarkm 183629181Smarkm if ((ep = env_find(var))) 183729088Smarkm ep->export = 1; 183829088Smarkm} 183929088Smarkm 184029088Smarkm void 184129088Smarkmenv_unexport(var) 184229088Smarkm unsigned char *var; 184329088Smarkm{ 184429088Smarkm register struct env_lst *ep; 184529088Smarkm 184629181Smarkm if ((ep = env_find(var))) 184729088Smarkm ep->export = 0; 184829088Smarkm} 184929088Smarkm 185029088Smarkm void 185129088Smarkmenv_send(var) 185229088Smarkm unsigned char *var; 185329088Smarkm{ 185429088Smarkm register struct env_lst *ep; 185529088Smarkm 185629088Smarkm if (my_state_is_wont(TELOPT_NEW_ENVIRON) 185729088Smarkm#ifdef OLD_ENVIRON 185829088Smarkm && my_state_is_wont(TELOPT_OLD_ENVIRON) 185929088Smarkm#endif 186029088Smarkm ) { 186129088Smarkm fprintf(stderr, 186229088Smarkm "Cannot send '%s': Telnet ENVIRON option not enabled\n", 186329088Smarkm var); 186429088Smarkm return; 186529088Smarkm } 186629088Smarkm ep = env_find(var); 186729088Smarkm if (ep == 0) { 186829088Smarkm fprintf(stderr, "Cannot send '%s': variable not defined\n", 186929088Smarkm var); 187029088Smarkm return; 187129088Smarkm } 187229088Smarkm env_opt_start_info(); 187329088Smarkm env_opt_add(ep->var); 187429088Smarkm env_opt_end(0); 187529088Smarkm} 187629088Smarkm 187729088Smarkm void 187829088Smarkmenv_list() 187929088Smarkm{ 188029088Smarkm register struct env_lst *ep; 188129088Smarkm 188229088Smarkm for (ep = envlisthead.next; ep; ep = ep->next) { 188329088Smarkm printf("%c %-20s %s\n", ep->export ? '*' : ' ', 188429088Smarkm ep->var, ep->value); 188529088Smarkm } 188629088Smarkm} 188729088Smarkm 188829088Smarkm unsigned char * 188929088Smarkmenv_default(init, welldefined) 189029088Smarkm int init; 189129088Smarkm{ 189229088Smarkm static struct env_lst *nep = NULL; 189329088Smarkm 189429088Smarkm if (init) { 189529088Smarkm nep = &envlisthead; 189629181Smarkm return(NULL); 189729088Smarkm } 189829088Smarkm if (nep) { 189929181Smarkm while ((nep = nep->next)) { 190029088Smarkm if (nep->export && (nep->welldefined == welldefined)) 190129088Smarkm return(nep->var); 190229088Smarkm } 190329088Smarkm } 190429088Smarkm return(NULL); 190529088Smarkm} 190629088Smarkm 190729088Smarkm unsigned char * 190829088Smarkmenv_getvalue(var) 190929088Smarkm unsigned char *var; 191029088Smarkm{ 191129088Smarkm register struct env_lst *ep; 191229088Smarkm 191329181Smarkm if ((ep = env_find(var))) 191429088Smarkm return(ep->value); 191529088Smarkm return(NULL); 191629088Smarkm} 191729088Smarkm 191829088Smarkm#if defined(OLD_ENVIRON) && defined(ENV_HACK) 191929088Smarkm void 192029088Smarkmenv_varval(what) 192129088Smarkm unsigned char *what; 192229088Smarkm{ 192329088Smarkm extern int old_env_var, old_env_value, env_auto; 192429088Smarkm int len = strlen((char *)what); 192529088Smarkm 192629088Smarkm if (len == 0) 192729088Smarkm goto unknown; 192829088Smarkm 192929088Smarkm if (strncasecmp((char *)what, "status", len) == 0) { 193029088Smarkm if (env_auto) 193129088Smarkm printf("%s%s", "VAR and VALUE are/will be ", 193229088Smarkm "determined automatically\n"); 193329088Smarkm if (old_env_var == OLD_ENV_VAR) 193429088Smarkm printf("VAR and VALUE set to correct definitions\n"); 193529088Smarkm else 193629088Smarkm printf("VAR and VALUE definitions are reversed\n"); 193729088Smarkm } else if (strncasecmp((char *)what, "auto", len) == 0) { 193829088Smarkm env_auto = 1; 193929088Smarkm old_env_var = OLD_ENV_VALUE; 194029088Smarkm old_env_value = OLD_ENV_VAR; 194129088Smarkm } else if (strncasecmp((char *)what, "right", len) == 0) { 194229088Smarkm env_auto = 0; 194329088Smarkm old_env_var = OLD_ENV_VAR; 194429088Smarkm old_env_value = OLD_ENV_VALUE; 194529088Smarkm } else if (strncasecmp((char *)what, "wrong", len) == 0) { 194629088Smarkm env_auto = 0; 194729088Smarkm old_env_var = OLD_ENV_VALUE; 194829088Smarkm old_env_value = OLD_ENV_VAR; 194929088Smarkm } else { 195029088Smarkmunknown: 195129088Smarkm printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); 195229088Smarkm } 195329088Smarkm} 195429088Smarkm#endif 195529088Smarkm 195629088Smarkm#if defined(AUTHENTICATION) 195729088Smarkm/* 195829088Smarkm * The AUTHENTICATE command. 195929088Smarkm */ 196029088Smarkm 196129088Smarkmstruct authlist { 196229088Smarkm char *name; 196329088Smarkm char *help; 196429088Smarkm int (*handler)(); 196529088Smarkm int narg; 196629088Smarkm}; 196729088Smarkm 196829088Smarkmextern int 196929088Smarkm auth_enable P((char *)), 197029088Smarkm auth_disable P((char *)), 197129088Smarkm auth_status P((void)); 197229088Smarkmstatic int 197329088Smarkm auth_help P((void)); 197429088Smarkm 197529088Smarkmstruct authlist AuthList[] = { 197629088Smarkm { "status", "Display current status of authentication information", 197729088Smarkm auth_status, 0 }, 197829088Smarkm { "disable", "Disable an authentication type ('auth disable ?' for more)", 197929088Smarkm auth_disable, 1 }, 198029088Smarkm { "enable", "Enable an authentication type ('auth enable ?' for more)", 198129088Smarkm auth_enable, 1 }, 198229088Smarkm { "help", 0, auth_help, 0 }, 198329088Smarkm { "?", "Print help information", auth_help, 0 }, 198429088Smarkm { 0 }, 198529088Smarkm}; 198629088Smarkm 198729088Smarkm static int 198829088Smarkmauth_help() 198929088Smarkm{ 199029088Smarkm struct authlist *c; 199129088Smarkm 199229088Smarkm for (c = AuthList; c->name; c++) { 199329088Smarkm if (c->help) { 199429088Smarkm if (*c->help) 199529088Smarkm printf("%-15s %s\n", c->name, c->help); 199629088Smarkm else 199729088Smarkm printf("\n"); 199829088Smarkm } 199929088Smarkm } 200029088Smarkm return 0; 200129088Smarkm} 200229088Smarkm 200329181Smarkm int 200429088Smarkmauth_cmd(argc, argv) 200529088Smarkm int argc; 200629088Smarkm char *argv[]; 200729088Smarkm{ 200829088Smarkm struct authlist *c; 200929088Smarkm 201029088Smarkm if (argc < 2) { 201129088Smarkm fprintf(stderr, 201229088Smarkm "Need an argument to 'auth' command. 'auth ?' for help.\n"); 201329088Smarkm return 0; 201429088Smarkm } 201529088Smarkm 201629088Smarkm c = (struct authlist *) 201729088Smarkm genget(argv[1], (char **) AuthList, sizeof(struct authlist)); 201829088Smarkm if (c == 0) { 201929088Smarkm fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", 202029088Smarkm argv[1]); 202129088Smarkm return 0; 202229088Smarkm } 202329088Smarkm if (Ambiguous(c)) { 202429088Smarkm fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", 202529088Smarkm argv[1]); 202629088Smarkm return 0; 202729088Smarkm } 202829088Smarkm if (c->narg + 2 != argc) { 202929088Smarkm fprintf(stderr, 203029088Smarkm "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", 203129088Smarkm c->narg < argc + 2 ? "only " : "", 203229088Smarkm c->narg, c->narg == 1 ? "" : "s", c->name); 203329088Smarkm return 0; 203429088Smarkm } 203529088Smarkm return((*c->handler)(argv[2], argv[3])); 203629088Smarkm} 203729088Smarkm#endif 203829088Smarkm 203929088Smarkm#ifdef ENCRYPTION 204029088Smarkm/* 204129088Smarkm * The ENCRYPT command. 204229088Smarkm */ 204329088Smarkm 204429088Smarkmstruct encryptlist { 204529088Smarkm char *name; 204629088Smarkm char *help; 204729088Smarkm int (*handler)(); 204829088Smarkm int needconnect; 204929088Smarkm int minarg; 205029088Smarkm int maxarg; 205129088Smarkm}; 205229088Smarkm 205329088Smarkmextern int 205429088Smarkm EncryptEnable P((char *, char *)), 205529088Smarkm EncryptDisable P((char *, char *)), 205629088Smarkm EncryptType P((char *, char *)), 205729088Smarkm EncryptStart P((char *)), 205829088Smarkm EncryptStartInput P((void)), 205929088Smarkm EncryptStartOutput P((void)), 206029088Smarkm EncryptStop P((char *)), 206129088Smarkm EncryptStopInput P((void)), 206229088Smarkm EncryptStopOutput P((void)), 206329088Smarkm EncryptStatus P((void)); 206429088Smarkmstatic int 206529088Smarkm EncryptHelp P((void)); 206629088Smarkm 206729088Smarkmstruct encryptlist EncryptList[] = { 206829088Smarkm { "enable", "Enable encryption. ('encrypt enable ?' for more)", 206929088Smarkm EncryptEnable, 1, 1, 2 }, 207029088Smarkm { "disable", "Disable encryption. ('encrypt enable ?' for more)", 207129088Smarkm EncryptDisable, 0, 1, 2 }, 207229088Smarkm { "type", "Set encryption type. ('encrypt type ?' for more)", 207329088Smarkm EncryptType, 0, 1, 1 }, 207429088Smarkm { "start", "Start encryption. ('encrypt start ?' for more)", 207529088Smarkm EncryptStart, 1, 0, 1 }, 207629088Smarkm { "stop", "Stop encryption. ('encrypt stop ?' for more)", 207729088Smarkm EncryptStop, 1, 0, 1 }, 207829088Smarkm { "input", "Start encrypting the input stream", 207929088Smarkm EncryptStartInput, 1, 0, 0 }, 208029088Smarkm { "-input", "Stop encrypting the input stream", 208129088Smarkm EncryptStopInput, 1, 0, 0 }, 208229088Smarkm { "output", "Start encrypting the output stream", 208329088Smarkm EncryptStartOutput, 1, 0, 0 }, 208429088Smarkm { "-output", "Stop encrypting the output stream", 208529088Smarkm EncryptStopOutput, 1, 0, 0 }, 208629088Smarkm 208729088Smarkm { "status", "Display current status of authentication information", 208829088Smarkm EncryptStatus, 0, 0, 0 }, 208929088Smarkm { "help", 0, EncryptHelp, 0, 0, 0 }, 209029088Smarkm { "?", "Print help information", EncryptHelp, 0, 0, 0 }, 209129088Smarkm { 0 }, 209229088Smarkm}; 209329088Smarkm 209429088Smarkm static int 209529088SmarkmEncryptHelp() 209629088Smarkm{ 209729088Smarkm struct encryptlist *c; 209829088Smarkm 209929088Smarkm for (c = EncryptList; c->name; c++) { 210029088Smarkm if (c->help) { 210129088Smarkm if (*c->help) 210229088Smarkm printf("%-15s %s\n", c->name, c->help); 210329088Smarkm else 210429088Smarkm printf("\n"); 210529088Smarkm } 210629088Smarkm } 210729088Smarkm return 0; 210829088Smarkm} 210929088Smarkm 211029181Smarkm int 211129088Smarkmencrypt_cmd(argc, argv) 211229088Smarkm int argc; 211329088Smarkm char *argv[]; 211429088Smarkm{ 211529088Smarkm struct encryptlist *c; 211629088Smarkm 211729088Smarkm if (argc < 2) { 211829088Smarkm fprintf(stderr, 211929088Smarkm "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); 212029088Smarkm return 0; 212129088Smarkm } 212229088Smarkm 212329088Smarkm c = (struct encryptlist *) 212429088Smarkm genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); 212529088Smarkm if (c == 0) { 212629088Smarkm fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", 212729088Smarkm argv[1]); 212829088Smarkm return 0; 212929088Smarkm } 213029088Smarkm if (Ambiguous(c)) { 213129088Smarkm fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", 213229088Smarkm argv[1]); 213329088Smarkm return 0; 213429088Smarkm } 213529088Smarkm argc -= 2; 213629088Smarkm if (argc < c->minarg || argc > c->maxarg) { 213729088Smarkm if (c->minarg == c->maxarg) { 213829088Smarkm fprintf(stderr, "Need %s%d argument%s ", 213929088Smarkm c->minarg < argc ? "only " : "", c->minarg, 214029088Smarkm c->minarg == 1 ? "" : "s"); 214129088Smarkm } else { 214229088Smarkm fprintf(stderr, "Need %s%d-%d arguments ", 214329088Smarkm c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); 214429088Smarkm } 214529088Smarkm fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", 214629088Smarkm c->name); 214729088Smarkm return 0; 214829088Smarkm } 214929088Smarkm if (c->needconnect && !connected) { 215029088Smarkm if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { 215129088Smarkm printf("?Need to be connected first.\n"); 215229088Smarkm return 0; 215329088Smarkm } 215429088Smarkm } 215529088Smarkm return ((*c->handler)(argc > 0 ? argv[2] : 0, 215629088Smarkm argc > 1 ? argv[3] : 0, 215729088Smarkm argc > 2 ? argv[4] : 0)); 215829088Smarkm} 215929088Smarkm#endif /* ENCRYPTION */ 216029088Smarkm 216129088Smarkm#if defined(unix) && defined(TN3270) 216229088Smarkm static void 216329088Smarkmfilestuff(fd) 216429088Smarkm int fd; 216529088Smarkm{ 216629088Smarkm int res; 216729088Smarkm 216829088Smarkm#ifdef F_GETOWN 216929088Smarkm setconnmode(0); 217029088Smarkm res = fcntl(fd, F_GETOWN, 0); 217129088Smarkm setcommandmode(); 217229088Smarkm 217329088Smarkm if (res == -1) { 217429088Smarkm perror("fcntl"); 217529088Smarkm return; 217629088Smarkm } 217729088Smarkm printf("\tOwner is %d.\n", res); 217829088Smarkm#endif 217929088Smarkm 218029088Smarkm setconnmode(0); 218129088Smarkm res = fcntl(fd, F_GETFL, 0); 218229088Smarkm setcommandmode(); 218329088Smarkm 218429088Smarkm if (res == -1) { 218529088Smarkm perror("fcntl"); 218629088Smarkm return; 218729088Smarkm } 218829088Smarkm#ifdef notdef 218929088Smarkm printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); 219029088Smarkm#endif 219129088Smarkm} 219229088Smarkm#endif /* defined(unix) && defined(TN3270) */ 219329088Smarkm 219429088Smarkm/* 219529088Smarkm * Print status about the connection. 219629088Smarkm */ 219729088Smarkm /*ARGSUSED*/ 219829181Smarkm static int 219929088Smarkmstatus(argc, argv) 220029088Smarkm int argc; 220129088Smarkm char *argv[]; 220229088Smarkm{ 220329088Smarkm if (connected) { 220429088Smarkm printf("Connected to %s.\n", hostname); 220529088Smarkm if ((argc < 2) || strcmp(argv[1], "notmuch")) { 220629088Smarkm int mode = getconnmode(); 220729088Smarkm 220829088Smarkm if (my_want_state_is_will(TELOPT_LINEMODE)) { 220929088Smarkm printf("Operating with LINEMODE option\n"); 221029088Smarkm printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); 221129088Smarkm printf("%s catching of signals\n", 221229088Smarkm (mode&MODE_TRAPSIG) ? "Local" : "No"); 221329088Smarkm slcstate(); 221429088Smarkm#ifdef KLUDGELINEMODE 221529088Smarkm } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { 221629088Smarkm printf("Operating in obsolete linemode\n"); 221729088Smarkm#endif 221829088Smarkm } else { 221929088Smarkm printf("Operating in single character mode\n"); 222029088Smarkm if (localchars) 222129088Smarkm printf("Catching signals locally\n"); 222229088Smarkm } 222329088Smarkm printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); 222429088Smarkm if (my_want_state_is_will(TELOPT_LFLOW)) 222529088Smarkm printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); 222629088Smarkm#ifdef ENCRYPTION 222729088Smarkm encrypt_display(); 222829088Smarkm#endif /* ENCRYPTION */ 222929088Smarkm } 223029088Smarkm } else { 223129088Smarkm printf("No connection.\n"); 223229088Smarkm } 223329088Smarkm# if !defined(TN3270) 223429088Smarkm printf("Escape character is '%s'.\n", control(escape)); 223529088Smarkm (void) fflush(stdout); 223629088Smarkm# else /* !defined(TN3270) */ 223729088Smarkm if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { 223829088Smarkm printf("Escape character is '%s'.\n", control(escape)); 223929088Smarkm } 224029088Smarkm# if defined(unix) 224129088Smarkm if ((argc >= 2) && !strcmp(argv[1], "everything")) { 224229088Smarkm printf("SIGIO received %d time%s.\n", 224329088Smarkm sigiocount, (sigiocount == 1)? "":"s"); 224429088Smarkm if (In3270) { 224529088Smarkm printf("Process ID %d, process group %d.\n", 224629088Smarkm getpid(), getpgrp(getpid())); 224729088Smarkm printf("Terminal input:\n"); 224829088Smarkm filestuff(tin); 224929088Smarkm printf("Terminal output:\n"); 225029088Smarkm filestuff(tout); 225129088Smarkm printf("Network socket:\n"); 225229088Smarkm filestuff(net); 225329088Smarkm } 225429088Smarkm } 225529088Smarkm if (In3270 && transcom) { 225629088Smarkm printf("Transparent mode command is '%s'.\n", transcom); 225729088Smarkm } 225829088Smarkm# endif /* defined(unix) */ 225929088Smarkm (void) fflush(stdout); 226029088Smarkm if (In3270) { 226129088Smarkm return 0; 226229088Smarkm } 226329088Smarkm# endif /* defined(TN3270) */ 226429088Smarkm return 1; 226529088Smarkm} 226629088Smarkm 226729088Smarkm#ifdef SIGINFO 226829088Smarkm/* 226929088Smarkm * Function that gets called when SIGINFO is received. 227029088Smarkm */ 227129181Smarkm void 227229088Smarkmayt_status() 227329088Smarkm{ 227429088Smarkm (void) call(status, "status", "notmuch", 0); 227529088Smarkm} 227629088Smarkm#endif 227729088Smarkm 227856668Sshinstatic const char * 227956668Sshinsockaddr_ntop(sa) 228056668Sshin struct sockaddr *sa; 228156668Sshin{ 228256668Sshin void *addr; 228356668Sshin static char addrbuf[INET6_ADDRSTRLEN]; 228429088Smarkm 228556668Sshin switch (sa->sa_family) { 228656668Sshin case AF_INET: 228756668Sshin addr = &((struct sockaddr_in *)sa)->sin_addr; 228856668Sshin break; 228977095Sdillon case AF_UNIX: 229077095Sdillon addr = &((struct sockaddr_un *)sa)->sun_path; 229177095Sdillon break; 229256668Sshin#ifdef INET6 229356668Sshin case AF_INET6: 229456668Sshin addr = &((struct sockaddr_in6 *)sa)->sin6_addr; 229556668Sshin break; 229656668Sshin#endif 229756668Sshin default: 229856668Sshin return NULL; 229956668Sshin } 230056668Sshin inet_ntop(sa->sa_family, addr, addrbuf, sizeof(addrbuf)); 230156668Sshin return addrbuf; 230256668Sshin} 230356668Sshin 230456668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 230556668Sshinstatic int 230656668Sshinsetpolicy(net, res, policy) 230756668Sshin int net; 230856668Sshin struct addrinfo *res; 230956668Sshin char *policy; 231056668Sshin{ 231156668Sshin char *buf; 231256668Sshin int level; 231356668Sshin int optname; 231456668Sshin 231556668Sshin if (policy == NULL) 231656668Sshin return 0; 231756668Sshin 231856668Sshin buf = ipsec_set_policy(policy, strlen(policy)); 231956668Sshin if (buf == NULL) { 232056668Sshin printf("%s\n", ipsec_strerror()); 232156668Sshin return -1; 232256668Sshin } 232356668Sshin level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; 232456668Sshin optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY; 232556668Sshin if (setsockopt(net, level, optname, buf, ipsec_get_policylen(buf)) < 0){ 232656668Sshin perror("setsockopt"); 232756668Sshin return -1; 232856668Sshin } 232956668Sshin 233056668Sshin free(buf); 233156668Sshin} 233256668Sshin#endif 233356668Sshin 233457125Sshin#ifdef INET6 233557125Sshin/* 233657125Sshin * When an Address Family related error happend, check if retry with 233757125Sshin * another AF is possible or not. 233857125Sshin * Return 1, if retry with another af is OK. Else, return 0. 233957125Sshin */ 234057125Sshinstatic int 234157125Sshinswitch_af(aip) 234257125Sshin struct addrinfo **aip; 234357125Sshin{ 234457125Sshin int nextaf; 234557125Sshin struct addrinfo *ai; 234657125Sshin 234757125Sshin ai = *aip; 234857125Sshin nextaf = (ai->ai_family == AF_INET) ? AF_INET6 : AF_INET; 234957125Sshin do 235057125Sshin ai=ai->ai_next; 235157125Sshin while (ai != NULL && ai->ai_family != nextaf); 235257125Sshin *aip = ai; 235357125Sshin if (*aip != NULL) { 235457125Sshin return 1; 235557125Sshin } 235657125Sshin return 0; 235757125Sshin} 235857125Sshin#endif 235957125Sshin 236029088Smarkm int 236129088Smarkmtn(argc, argv) 236229088Smarkm int argc; 236329088Smarkm char *argv[]; 236429088Smarkm{ 236529088Smarkm char *srp = 0, *strrchr(); 236656668Sshin int proto, opt; 236756668Sshin int sourceroute(), srlen; 236856668Sshin int srcroute = 0, result; 236929088Smarkm char *cmd, *hostp = 0, *portp = 0, *user = 0; 237047973Sru char *src_addr = NULL; 237157125Sshin struct addrinfo hints, *res, *res0 = NULL, *src_res, *src_res0 = NULL; 237257125Sshin int error = 0, af_error = 0; 237329088Smarkm 237429088Smarkm if (connected) { 237529088Smarkm printf("?Already connected to %s\n", hostname); 237629088Smarkm setuid(getuid()); 237729088Smarkm return 0; 237829088Smarkm } 237929088Smarkm if (argc < 2) { 238029088Smarkm (void) strcpy(line, "open "); 238129088Smarkm printf("(to) "); 238229088Smarkm (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); 238329088Smarkm makeargv(); 238429088Smarkm argc = margc; 238529088Smarkm argv = margv; 238629088Smarkm } 238729088Smarkm cmd = *argv; 238829088Smarkm --argc; ++argv; 238929088Smarkm while (argc) { 239029088Smarkm if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) 239129088Smarkm goto usage; 239229088Smarkm if (strcmp(*argv, "-l") == 0) { 239329088Smarkm --argc; ++argv; 239429088Smarkm if (argc == 0) 239529088Smarkm goto usage; 239629088Smarkm user = *argv++; 239729088Smarkm --argc; 239829088Smarkm continue; 239929088Smarkm } 240029088Smarkm if (strcmp(*argv, "-a") == 0) { 240129088Smarkm --argc; ++argv; 240229088Smarkm autologin = 1; 240329088Smarkm continue; 240429088Smarkm } 240547973Sru if (strcmp(*argv, "-s") == 0) { 240647973Sru --argc; ++argv; 240747973Sru if (argc == 0) 240847973Sru goto usage; 240947973Sru src_addr = *argv++; 241047973Sru --argc; 241147973Sru continue; 241247973Sru } 241329088Smarkm if (hostp == 0) { 241429088Smarkm hostp = *argv++; 241529088Smarkm --argc; 241629088Smarkm continue; 241729088Smarkm } 241829088Smarkm if (portp == 0) { 241929088Smarkm portp = *argv++; 242029088Smarkm --argc; 242129088Smarkm continue; 242229088Smarkm } 242329088Smarkm usage: 242447973Sru printf("usage: %s [-l user] [-a] [-s src_addr] host-name [port]\n", cmd); 242529088Smarkm setuid(getuid()); 242629088Smarkm return 0; 242729088Smarkm } 242829088Smarkm if (hostp == 0) 242929088Smarkm goto usage; 243029088Smarkm 243147973Sru if (src_addr != NULL) { 243256668Sshin memset(&hints, 0, sizeof(hints)); 243356668Sshin hints.ai_flags = AI_NUMERICHOST; 243456668Sshin hints.ai_family = family; 243556668Sshin hints.ai_socktype = SOCK_STREAM; 243657125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 243762805Sume if (error == EAI_NODATA) { 243856668Sshin hints.ai_flags = 0; 243957125Sshin error = getaddrinfo(src_addr, 0, &hints, &src_res); 244056668Sshin } 244156668Sshin if (error != 0) { 244256668Sshin fprintf(stderr, "%s: %s\n", src_addr, gai_strerror(error)); 244356668Sshin if (error == EAI_SYSTEM) 244456668Sshin fprintf(stderr, "%s: %s\n", src_addr, strerror(errno)); 244557125Sshin setuid(getuid()); 244647973Sru return 0; 244747973Sru } 244857125Sshin src_res0 = src_res; 244947973Sru } 245077095Sdillon if (hostp[0] == '/') { 245177095Sdillon struct sockaddr_un su; 245277095Sdillon 245377095Sdillon if (strlen(hostp) >= sizeof(su.sun_path)) { 245477095Sdillon fprintf(stderr, "hostname too long for unix domain socket: %s", 245577095Sdillon hostp); 245677095Sdillon goto fail; 245777095Sdillon } 245877095Sdillon memset(&su, 0, sizeof su); 245977095Sdillon su.sun_family = AF_UNIX; 246077095Sdillon strncpy(su.sun_path, hostp, sizeof su.sun_path); 246177095Sdillon printf("Trying %s...\n", &su.sun_path); 246277095Sdillon net = socket(PF_UNIX, SOCK_STREAM, 0); 246377095Sdillon if ( net < 0) { 246477095Sdillon perror("socket"); 246577095Sdillon goto fail; 246677095Sdillon } 246777095Sdillon if (connect(net, (struct sockaddr *)&su, sizeof su) == -1) { 246877095Sdillon perror(su.sun_path); 246977095Sdillon (void) NetClose(net); 247077095Sdillon goto fail; 247177095Sdillon } 247277095Sdillon goto af_unix; 247377095Sdillon } else if (hostp[0] == '@' || hostp[0] == '!') { 247456668Sshin if ( 247556668Sshin#ifdef INET6 247656668Sshin family == AF_INET6 || 247756668Sshin#endif 247856668Sshin (hostname = strrchr(hostp, ':')) == NULL) 247929088Smarkm hostname = strrchr(hostp, '@'); 248029088Smarkm hostname++; 248156668Sshin srcroute = 1; 248256668Sshin } else 248356668Sshin hostname = hostp; 248456668Sshin if (!portp) { 248556668Sshin telnetport = 1; 248656668Sshin portp = "telnet"; 248756668Sshin } else if (*portp == '-') { 248856668Sshin portp++; 248956668Sshin telnetport = 1; 249056668Sshin } else 249156668Sshin telnetport = 0; 249256668Sshin 249356668Sshin memset(&hints, 0, sizeof(hints)); 249456668Sshin hints.ai_flags = AI_NUMERICHOST; 249556668Sshin hints.ai_family = family; 249656668Sshin hints.ai_socktype = SOCK_STREAM; 249756668Sshin error = getaddrinfo(hostname, portp, &hints, &res); 249862773Sitojun if (error) { 249962773Sitojun hints.ai_flags = AI_CANONNAME; 250062773Sitojun error = getaddrinfo(hostname, portp, &hints, &res); 250162773Sitojun } 250262773Sitojun if (error != 0) { 250362773Sitojun fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error)); 250462773Sitojun if (error == EAI_SYSTEM) 250562773Sitojun fprintf(stderr, "%s: %s\n", hostname, strerror(errno)); 250662773Sitojun setuid(getuid()); 250762773Sitojun goto fail; 250862773Sitojun } 250962773Sitojun if (hints.ai_flags == AI_NUMERICHOST) { 251062773Sitojun /* hostname has numeric */ 251156668Sshin int gni_err = 1; 251256668Sshin 251356668Sshin if (doaddrlookup) 251456668Sshin gni_err = getnameinfo(res->ai_addr, res->ai_addr->sa_len, 251556668Sshin _hostname, sizeof(_hostname) - 1, NULL, 0, 251656870Sshin NI_NAMEREQD); 251756668Sshin if (gni_err != 0) 251862773Sitojun (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 251956668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 252056668Sshin hostname = _hostname; 252162773Sitojun } else { 252262773Sitojun /* hostname has FQDN */ 252356668Sshin if (srcroute != 0) 252456668Sshin (void) strncpy(_hostname, hostname, sizeof(_hostname) - 1); 252556668Sshin else if (res->ai_canonname != NULL) 252656668Sshin strcpy(_hostname, res->ai_canonname); 252756668Sshin else 252856668Sshin (void) strncpy(_hostname, hostp, sizeof(_hostname) - 1); 252956668Sshin _hostname[sizeof(_hostname)-1] = '\0'; 253056668Sshin hostname = _hostname; 253156668Sshin } 253257125Sshin res0 = res; 253357233Sshin af_again: 253456668Sshin if (srcroute != 0) { 253557343Sshin static char hostbuf[BUFSIZ]; 253657125Sshin 253757233Sshin if (af_error == 0) { /* save intermediate hostnames for retry */ 253857233Sshin strncpy(hostbuf, hostp, BUFSIZ - 1); 253957233Sshin hostbuf[BUFSIZ - 1] = '\0'; 254057233Sshin } else 254157125Sshin hostp = hostbuf; 254229088Smarkm srp = 0; 254356668Sshin result = sourceroute(res, hostp, &srp, &srlen, &proto, &opt); 254456668Sshin if (result == 0) { 254557125Sshin#ifdef INET6 254657125Sshin if (family == AF_UNSPEC && af_error == 0 && 254757125Sshin switch_af(&res) == 1) { 254857125Sshin af_error = 1; 254957125Sshin goto af_again; 255057125Sshin } 255157125Sshin#endif 255229088Smarkm setuid(getuid()); 255357125Sshin goto fail; 255456668Sshin } else if (result == -1) { 255529088Smarkm printf("Bad source route option: %s\n", hostp); 255629088Smarkm setuid(getuid()); 255757125Sshin goto fail; 255829088Smarkm } 255929088Smarkm } 256029088Smarkm do { 256157342Sshin printf("Trying %s...\n", sockaddr_ntop(res->ai_addr)); 256256668Sshin net = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 256329088Smarkm setuid(getuid()); 256429088Smarkm if (net < 0) { 256557125Sshin#ifdef INET6 256657125Sshin if (family == AF_UNSPEC && af_error == 0 && 256757125Sshin switch_af(&res) == 1) { 256857125Sshin af_error = 1; 256957125Sshin goto af_again; 257057125Sshin } 257157125Sshin#endif 257229088Smarkm perror("telnet: socket"); 257357125Sshin goto fail; 257429088Smarkm } 257556668Sshin if (srp && setsockopt(net, proto, opt, (char *)srp, srlen) < 0) 257656668Sshin perror("setsockopt (source route)"); 257729088Smarkm#if defined(IPPROTO_IP) && defined(IP_TOS) 257856668Sshin if (res->ai_family == PF_INET) { 257929088Smarkm# if defined(HAS_GETTOS) 258029088Smarkm struct tosent *tp; 258129088Smarkm if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 258229088Smarkm tos = tp->t_tos; 258329088Smarkm# endif 258429088Smarkm if (tos < 0) 258529088Smarkm tos = 020; /* Low Delay bit */ 258629088Smarkm if (tos 258729088Smarkm && (setsockopt(net, IPPROTO_IP, IP_TOS, 258829088Smarkm (char *)&tos, sizeof(int)) < 0) 258929088Smarkm && (errno != ENOPROTOOPT)) 259029088Smarkm perror("telnet: setsockopt (IP_TOS) (ignored)"); 259129088Smarkm } 259229088Smarkm#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 259329088Smarkm 259429088Smarkm if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { 259529088Smarkm perror("setsockopt (SO_DEBUG)"); 259629088Smarkm } 259729088Smarkm 259847973Sru if (src_addr != NULL) { 259957125Sshin for (src_res = src_res0; src_res != 0; src_res = src_res->ai_next) 260057233Sshin if (src_res->ai_family == res->ai_family) 260157233Sshin break; 260257125Sshin if (src_res == NULL) 260357125Sshin src_res = src_res0; 260457125Sshin if (bind(net, src_res->ai_addr, src_res->ai_addrlen) == -1) { 260557125Sshin#ifdef INET6 260657125Sshin if (family == AF_UNSPEC && af_error == 0 && 260757125Sshin switch_af(&res) == 1) { 260857125Sshin af_error = 1; 260957233Sshin (void) NetClose(net); 261057125Sshin goto af_again; 261157125Sshin } 261257125Sshin#endif 261347973Sru perror("bind"); 261457233Sshin (void) NetClose(net); 261557125Sshin goto fail; 261647973Sru } 261747973Sru } 261856668Sshin#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) 261957233Sshin if (setpolicy(net, res, ipsec_policy_in) < 0) { 262057233Sshin (void) NetClose(net); 262157125Sshin goto fail; 262257233Sshin } 262357233Sshin if (setpolicy(net, res, ipsec_policy_out) < 0) { 262457233Sshin (void) NetClose(net); 262557125Sshin goto fail; 262657233Sshin } 262756668Sshin#endif 262847973Sru 262956668Sshin if (connect(net, res->ai_addr, res->ai_addrlen) < 0) { 263057125Sshin struct addrinfo *next; 263157125Sshin 263257125Sshin next = res->ai_next; 263357125Sshin /* If already an af failed, only try same af. */ 263457125Sshin if (af_error != 0) 263557125Sshin while (next != NULL && next->ai_family != res->ai_family) 263657125Sshin next = next->ai_next; 263757342Sshin warn("connect to address %s", sockaddr_ntop(res->ai_addr)); 263857125Sshin if (next != NULL) { 263957125Sshin res = next; 264029088Smarkm (void) NetClose(net); 264129088Smarkm continue; 264229088Smarkm } 264357342Sshin warnx("Unable to connect to remote host"); 264457233Sshin (void) NetClose(net); 264557125Sshin goto fail; 264629088Smarkm } 264729088Smarkm connected++; 264829088Smarkm#if defined(AUTHENTICATION) || defined(ENCRYPTION) 264929088Smarkm auth_encrypt_connect(connected); 265029088Smarkm#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 265129088Smarkm } while (connected == 0); 265257125Sshin freeaddrinfo(res0); 265357125Sshin if (src_res0 != NULL) 265457125Sshin freeaddrinfo(src_res0); 265529088Smarkm cmdrc(hostp, hostname); 265677095Sdillon af_unix: 265729088Smarkm if (autologin && user == NULL) { 265829088Smarkm struct passwd *pw; 265929088Smarkm 266029088Smarkm user = getenv("USER"); 266129088Smarkm if (user == NULL || 266229181Smarkm ((pw = getpwnam(user)) && pw->pw_uid != getuid())) { 266329181Smarkm if ((pw = getpwuid(getuid()))) 266429088Smarkm user = pw->pw_name; 266529088Smarkm else 266629088Smarkm user = NULL; 266729088Smarkm } 266829088Smarkm } 266929088Smarkm if (user) { 267029088Smarkm env_define((unsigned char *)"USER", (unsigned char *)user); 267129088Smarkm env_export((unsigned char *)"USER"); 267229088Smarkm } 267329088Smarkm (void) call(status, "status", "notmuch", 0); 267429088Smarkm if (setjmp(peerdied) == 0) 267529088Smarkm telnet(user); 267629088Smarkm (void) NetClose(net); 267729088Smarkm ExitString("Connection closed by foreign host.\n",1); 267829088Smarkm /*NOTREACHED*/ 267957125Sshin fail: 268057125Sshin if (res0 != NULL) 268157125Sshin freeaddrinfo(res0); 268257125Sshin if (src_res0 != NULL) 268357125Sshin freeaddrinfo(src_res0); 268457125Sshin return 0; 268529088Smarkm} 268629088Smarkm 268729088Smarkm#define HELPINDENT (sizeof ("connect")) 268829088Smarkm 268929088Smarkmstatic char 269029088Smarkm openhelp[] = "connect to a site", 269129088Smarkm closehelp[] = "close current connection", 269229088Smarkm logouthelp[] = "forcibly logout remote user and close the connection", 269329088Smarkm quithelp[] = "exit telnet", 269429088Smarkm statushelp[] = "print status information", 269529088Smarkm helphelp[] = "print help information", 269629088Smarkm sendhelp[] = "transmit special characters ('send ?' for more)", 269729088Smarkm sethelp[] = "set operating parameters ('set ?' for more)", 269829088Smarkm unsethelp[] = "unset operating parameters ('unset ?' for more)", 269929088Smarkm togglestring[] ="toggle operating parameters ('toggle ?' for more)", 270029088Smarkm slchelp[] = "change state of special charaters ('slc ?' for more)", 270129088Smarkm displayhelp[] = "display operating parameters", 270229088Smarkm#if defined(TN3270) && defined(unix) 270329088Smarkm transcomhelp[] = "specify Unix command for transparent mode pipe", 270429088Smarkm#endif /* defined(TN3270) && defined(unix) */ 270529088Smarkm#if defined(AUTHENTICATION) 270629088Smarkm authhelp[] = "turn on (off) authentication ('auth ?' for more)", 270729088Smarkm#endif 270829088Smarkm#ifdef ENCRYPTION 270929088Smarkm encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", 271029088Smarkm#endif /* ENCRYPTION */ 271129088Smarkm#if defined(unix) 271229088Smarkm zhelp[] = "suspend telnet", 271329088Smarkm#endif /* defined(unix) */ 271429181Smarkm#if defined(SKEY) 271529181Smarkm skeyhelp[] = "compute response to s/key challenge", 271629181Smarkm#endif 271729088Smarkm shellhelp[] = "invoke a subshell", 271829088Smarkm envhelp[] = "change environment variables ('environ ?' for more)", 271929088Smarkm modestring[] = "try to enter line or character mode ('mode ?' for more)"; 272029088Smarkm 272129088Smarkmstatic Command cmdtab[] = { 272229088Smarkm { "close", closehelp, bye, 1 }, 272329088Smarkm { "logout", logouthelp, logout, 1 }, 272429088Smarkm { "display", displayhelp, display, 0 }, 272529088Smarkm { "mode", modestring, modecmd, 0 }, 272629088Smarkm { "open", openhelp, tn, 0 }, 272729088Smarkm { "quit", quithelp, quit, 0 }, 272829088Smarkm { "send", sendhelp, sendcmd, 0 }, 272929088Smarkm { "set", sethelp, setcmd, 0 }, 273029088Smarkm { "unset", unsethelp, unsetcmd, 0 }, 273129088Smarkm { "status", statushelp, status, 0 }, 273229088Smarkm { "toggle", togglestring, toggle, 0 }, 273329088Smarkm { "slc", slchelp, slccmd, 0 }, 273429088Smarkm#if defined(TN3270) && defined(unix) 273529088Smarkm { "transcom", transcomhelp, settranscom, 0 }, 273629088Smarkm#endif /* defined(TN3270) && defined(unix) */ 273729088Smarkm#if defined(AUTHENTICATION) 273829088Smarkm { "auth", authhelp, auth_cmd, 0 }, 273929088Smarkm#endif 274029088Smarkm#ifdef ENCRYPTION 274129088Smarkm { "encrypt", encrypthelp, encrypt_cmd, 0 }, 274229088Smarkm#endif /* ENCRYPTION */ 274329088Smarkm#if defined(unix) 274429088Smarkm { "z", zhelp, suspend, 0 }, 274529088Smarkm#endif /* defined(unix) */ 274629088Smarkm#if defined(TN3270) 274729088Smarkm { "!", shellhelp, shell, 1 }, 274829088Smarkm#else 274929088Smarkm { "!", shellhelp, shell, 0 }, 275029088Smarkm#endif 275129088Smarkm { "environ", envhelp, env_cmd, 0 }, 275229088Smarkm { "?", helphelp, help, 0 }, 275329181Smarkm#if defined(SKEY) 275429181Smarkm { "skey", skeyhelp, skey_calc, 0 }, 275529181Smarkm#endif 275629181Smarkm { 0, 0, 0, 0 } 275729088Smarkm}; 275829088Smarkm 275929088Smarkmstatic char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; 276029088Smarkmstatic char escapehelp[] = "deprecated command -- use 'set escape' instead"; 276129088Smarkm 276229088Smarkmstatic Command cmdtab2[] = { 276329088Smarkm { "help", 0, help, 0 }, 276429088Smarkm { "escape", escapehelp, setescape, 0 }, 276529088Smarkm { "crmod", crmodhelp, togcrmod, 0 }, 276629181Smarkm { 0, 0, 0, 0 } 276729088Smarkm}; 276829088Smarkm 276929088Smarkm 277029088Smarkm/* 277129088Smarkm * Call routine with argc, argv set from args (terminated by 0). 277229088Smarkm */ 277329088Smarkm 277429088Smarkm /*VARARGS1*/ 277529181Smarkm static int 277629088Smarkmcall(va_alist) 277729088Smarkm va_dcl 277829088Smarkm{ 277929088Smarkm va_list ap; 278029088Smarkm typedef int (*intrtn_t)(); 278129088Smarkm intrtn_t routine; 278229088Smarkm char *args[100]; 278329088Smarkm int argno = 0; 278429088Smarkm 278529088Smarkm va_start(ap); 278629088Smarkm routine = (va_arg(ap, intrtn_t)); 278729088Smarkm while ((args[argno++] = va_arg(ap, char *)) != 0) { 278829088Smarkm ; 278929088Smarkm } 279029088Smarkm va_end(ap); 279129088Smarkm return (*routine)(argno-1, args); 279229088Smarkm} 279329088Smarkm 279429088Smarkm 279529088Smarkm static Command * 279629088Smarkmgetcmd(name) 279729088Smarkm char *name; 279829088Smarkm{ 279929088Smarkm Command *cm; 280029088Smarkm 280129181Smarkm if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command)))) 280229088Smarkm return cm; 280329088Smarkm return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); 280429088Smarkm} 280529088Smarkm 280629088Smarkm void 280729088Smarkmcommand(top, tbuf, cnt) 280829088Smarkm int top; 280929088Smarkm char *tbuf; 281029088Smarkm int cnt; 281129088Smarkm{ 281229088Smarkm register Command *c; 281329088Smarkm 281429088Smarkm setcommandmode(); 281529088Smarkm if (!top) { 281629088Smarkm putchar('\n'); 281729088Smarkm#if defined(unix) 281829088Smarkm } else { 281929088Smarkm (void) signal(SIGINT, SIG_DFL); 282029088Smarkm (void) signal(SIGQUIT, SIG_DFL); 282129088Smarkm#endif /* defined(unix) */ 282229088Smarkm } 282329088Smarkm for (;;) { 282429088Smarkm if (rlogin == _POSIX_VDISABLE) 282529088Smarkm printf("%s> ", prompt); 282629088Smarkm if (tbuf) { 282729088Smarkm register char *cp; 282829088Smarkm cp = line; 282929088Smarkm while (cnt > 0 && (*cp++ = *tbuf++) != '\n') 283029088Smarkm cnt--; 283129088Smarkm tbuf = 0; 283229088Smarkm if (cp == line || *--cp != '\n' || cp == line) 283329088Smarkm goto getline; 283429088Smarkm *cp = '\0'; 283529088Smarkm if (rlogin == _POSIX_VDISABLE) 283629088Smarkm printf("%s\n", line); 283729088Smarkm } else { 283829088Smarkm getline: 283929088Smarkm if (rlogin != _POSIX_VDISABLE) 284029088Smarkm printf("%s> ", prompt); 284129088Smarkm if (fgets(line, sizeof(line), stdin) == NULL) { 284229088Smarkm if (feof(stdin) || ferror(stdin)) { 284329088Smarkm (void) quit(); 284429088Smarkm /*NOTREACHED*/ 284529088Smarkm } 284629088Smarkm break; 284729088Smarkm } 284829088Smarkm } 284929088Smarkm if (line[0] == 0) 285029088Smarkm break; 285129088Smarkm makeargv(); 285229088Smarkm if (margv[0] == 0) { 285329088Smarkm break; 285429088Smarkm } 285529088Smarkm c = getcmd(margv[0]); 285629088Smarkm if (Ambiguous(c)) { 285729088Smarkm printf("?Ambiguous command\n"); 285829088Smarkm continue; 285929088Smarkm } 286029088Smarkm if (c == 0) { 286129088Smarkm printf("?Invalid command\n"); 286229088Smarkm continue; 286329088Smarkm } 286429088Smarkm if (c->needconnect && !connected) { 286529088Smarkm printf("?Need to be connected first.\n"); 286629088Smarkm continue; 286729088Smarkm } 286829088Smarkm if ((*c->handler)(margc, margv)) { 286929088Smarkm break; 287029088Smarkm } 287129088Smarkm } 287229088Smarkm if (!top) { 287329088Smarkm if (!connected) { 287429088Smarkm longjmp(toplevel, 1); 287529088Smarkm /*NOTREACHED*/ 287629088Smarkm } 287729088Smarkm#if defined(TN3270) 287829088Smarkm if (shell_active == 0) { 287929088Smarkm setconnmode(0); 288029088Smarkm } 288129088Smarkm#else /* defined(TN3270) */ 288229088Smarkm setconnmode(0); 288329088Smarkm#endif /* defined(TN3270) */ 288429088Smarkm } 288529088Smarkm} 288629088Smarkm 288729088Smarkm/* 288829088Smarkm * Help command. 288929088Smarkm */ 289029181Smarkm static int 289129088Smarkmhelp(argc, argv) 289229088Smarkm int argc; 289329088Smarkm char *argv[]; 289429088Smarkm{ 289529088Smarkm register Command *c; 289629088Smarkm 289729088Smarkm if (argc == 1) { 289829088Smarkm printf("Commands may be abbreviated. Commands are:\n\n"); 289929088Smarkm for (c = cmdtab; c->name; c++) 290029088Smarkm if (c->help) { 290129088Smarkm printf("%-*s\t%s\n", HELPINDENT, c->name, 290229088Smarkm c->help); 290329088Smarkm } 290429088Smarkm } 290529181Smarkm else while (--argc > 0) { 290629088Smarkm register char *arg; 290729088Smarkm arg = *++argv; 290829088Smarkm c = getcmd(arg); 290929088Smarkm if (Ambiguous(c)) 291029088Smarkm printf("?Ambiguous help command %s\n", arg); 291129088Smarkm else if (c == (Command *)0) 291229088Smarkm printf("?Invalid help command %s\n", arg); 291329088Smarkm else 291429088Smarkm printf("%s\n", c->help); 291529088Smarkm } 291629181Smarkm return(0); 291729088Smarkm} 291829088Smarkm 291929088Smarkmstatic char *rcname = 0; 292029088Smarkmstatic char rcbuf[128]; 292129088Smarkm 292229181Smarkm void 292329088Smarkmcmdrc(m1, m2) 292429088Smarkm char *m1, *m2; 292529088Smarkm{ 292629088Smarkm register Command *c; 292729088Smarkm FILE *rcfile; 292829088Smarkm int gotmachine = 0; 292929088Smarkm int l1 = strlen(m1); 293029088Smarkm int l2 = strlen(m2); 293168891Skris char m1save[MAXHOSTNAMELEN]; 293229088Smarkm 293329088Smarkm if (skiprc) 293429088Smarkm return; 293529088Smarkm 293668891Skris strlcpy(m1save, m1, sizeof(m1save)); 293729088Smarkm m1 = m1save; 293829088Smarkm 293929088Smarkm if (rcname == 0) { 294029088Smarkm rcname = getenv("HOME"); 294129181Smarkm if (rcname && (strlen(rcname) + 10) < sizeof(rcbuf)) 294229088Smarkm strcpy(rcbuf, rcname); 294329088Smarkm else 294429088Smarkm rcbuf[0] = '\0'; 294529088Smarkm strcat(rcbuf, "/.telnetrc"); 294629088Smarkm rcname = rcbuf; 294729088Smarkm } 294829088Smarkm 294929088Smarkm if ((rcfile = fopen(rcname, "r")) == 0) { 295029088Smarkm return; 295129088Smarkm } 295229088Smarkm 295329088Smarkm for (;;) { 295429088Smarkm if (fgets(line, sizeof(line), rcfile) == NULL) 295529088Smarkm break; 295629088Smarkm if (line[0] == 0) 295729088Smarkm break; 295829088Smarkm if (line[0] == '#') 295929088Smarkm continue; 296029088Smarkm if (gotmachine) { 296129088Smarkm if (!isspace(line[0])) 296229088Smarkm gotmachine = 0; 296329088Smarkm } 296429088Smarkm if (gotmachine == 0) { 296529088Smarkm if (isspace(line[0])) 296629088Smarkm continue; 296729088Smarkm if (strncasecmp(line, m1, l1) == 0) 296829088Smarkm strncpy(line, &line[l1], sizeof(line) - l1); 296929088Smarkm else if (strncasecmp(line, m2, l2) == 0) 297029088Smarkm strncpy(line, &line[l2], sizeof(line) - l2); 297129088Smarkm else if (strncasecmp(line, "DEFAULT", 7) == 0) 297229088Smarkm strncpy(line, &line[7], sizeof(line) - 7); 297329088Smarkm else 297429088Smarkm continue; 297529088Smarkm if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') 297629088Smarkm continue; 297729088Smarkm gotmachine = 1; 297829088Smarkm } 297929088Smarkm makeargv(); 298029088Smarkm if (margv[0] == 0) 298129088Smarkm continue; 298229088Smarkm c = getcmd(margv[0]); 298329088Smarkm if (Ambiguous(c)) { 298429088Smarkm printf("?Ambiguous command: %s\n", margv[0]); 298529088Smarkm continue; 298629088Smarkm } 298729088Smarkm if (c == 0) { 298829088Smarkm printf("?Invalid command: %s\n", margv[0]); 298929088Smarkm continue; 299029088Smarkm } 299129088Smarkm /* 299229088Smarkm * This should never happen... 299329088Smarkm */ 299429088Smarkm if (c->needconnect && !connected) { 299529088Smarkm printf("?Need to be connected first for %s.\n", margv[0]); 299629088Smarkm continue; 299729088Smarkm } 299829088Smarkm (*c->handler)(margc, margv); 299929088Smarkm } 300029088Smarkm fclose(rcfile); 300129088Smarkm} 300229088Smarkm 300329088Smarkm/* 300429088Smarkm * Source route is handed in as 300529088Smarkm * [!]@hop1@hop2...[@|:]dst 300629088Smarkm * If the leading ! is present, it is a 300729088Smarkm * strict source route, otherwise it is 300829088Smarkm * assmed to be a loose source route. 300929088Smarkm * 301029088Smarkm * We fill in the source route option as 301129088Smarkm * hop1,hop2,hop3...dest 301229088Smarkm * and return a pointer to hop1, which will 301329088Smarkm * be the address to connect() to. 301429088Smarkm * 301529088Smarkm * Arguments: 301656668Sshin * 301756668Sshin * res: ponter to addrinfo structure which contains sockaddr to 301856668Sshin * the host to connect to. 301956668Sshin * 302029088Smarkm * arg: pointer to route list to decipher 302129088Smarkm * 302229088Smarkm * cpp: If *cpp is not equal to NULL, this is a 302329088Smarkm * pointer to a pointer to a character array 302429088Smarkm * that should be filled in with the option. 302529088Smarkm * 302629088Smarkm * lenp: pointer to an integer that contains the 302729088Smarkm * length of *cpp if *cpp != NULL. 302829088Smarkm * 302956668Sshin * protop: pointer to an integer that should be filled in with 303056668Sshin * appropriate protocol for setsockopt, as socket 303156668Sshin * protocol family. 303256668Sshin * 303356668Sshin * optp: pointer to an integer that should be filled in with 303456668Sshin * appropriate option for setsockopt, as socket protocol 303556668Sshin * family. 303656668Sshin * 303729088Smarkm * Return values: 303829088Smarkm * 303956668Sshin * If the return value is 1, then all operations are 304056668Sshin * successful. If the 304129088Smarkm * return value is -1, there was a syntax error in the 304229088Smarkm * option, either unknown characters, or too many hosts. 304329088Smarkm * If the return value is 0, one of the hostnames in the 304429088Smarkm * path is unknown, and *cpp is set to point to the bad 304529088Smarkm * hostname. 304629088Smarkm * 304729088Smarkm * *cpp: If *cpp was equal to NULL, it will be filled 304829088Smarkm * in with a pointer to our static area that has 304929088Smarkm * the option filled in. This will be 32bit aligned. 305029088Smarkm * 305129088Smarkm * *lenp: This will be filled in with how long the option 305229088Smarkm * pointed to by *cpp is. 305329088Smarkm * 305456668Sshin * *protop: This will be filled in with appropriate protocol for 305556668Sshin * setsockopt, as socket protocol family. 305656668Sshin * 305756668Sshin * *optp: This will be filled in with appropriate option for 305856668Sshin * setsockopt, as socket protocol family. 305929088Smarkm */ 306056668Sshinint 306156668Sshinsourceroute(ai, arg, cpp, lenp, protop, optp) 306256668Sshin struct addrinfo *ai; 306329088Smarkm char *arg; 306429088Smarkm char **cpp; 306529088Smarkm int *lenp; 306656668Sshin int *protop; 306756668Sshin int *optp; 306829088Smarkm{ 306963662Sume static char buf[1024 + ALIGNBYTES]; /*XXX*/ 307056668Sshin struct cmsghdr *cmsg; 307129088Smarkm#ifdef sysV88 307229088Smarkm static IOPTN ipopt; 307329088Smarkm#endif 307456668Sshin char *cp, *cp2, *lsrp, *ep; 307529088Smarkm register int tmp; 307656668Sshin struct sockaddr_in *sin; 307756668Sshin struct sockaddr_in6 *sin6; 307856668Sshin struct addrinfo hints, *res; 307956668Sshin int error; 308029088Smarkm register char c; 308129088Smarkm 308229088Smarkm /* 308329088Smarkm * Verify the arguments, and make sure we have 308429088Smarkm * at least 7 bytes for the option. 308529088Smarkm */ 308629088Smarkm if (cpp == NULL || lenp == NULL) 308757724Sshin return -1; 308856668Sshin if (*cpp != NULL) { 308956668Sshin switch (res->ai_family) { 309056668Sshin case AF_INET: 309156668Sshin if (*lenp < 7) 309257724Sshin return -1; 309356668Sshin break; 309456668Sshin#ifdef INET6 309556668Sshin case AF_INET6: 309657724Sshin if (*lenp < CMSG_SPACE(sizeof(struct ip6_rthdr) + 309757724Sshin sizeof(struct in6_addr))) 309857724Sshin return -1; 309956668Sshin break; 310056668Sshin#endif 310156668Sshin } 310256668Sshin } 310329088Smarkm /* 310429088Smarkm * Decide whether we have a buffer passed to us, 310529088Smarkm * or if we need to use our own static buffer. 310629088Smarkm */ 310729088Smarkm if (*cpp) { 310829088Smarkm lsrp = *cpp; 310956668Sshin ep = lsrp + *lenp; 311029088Smarkm } else { 311163662Sume *cpp = lsrp = (char *)ALIGN(buf); 311256668Sshin ep = lsrp + 1024; 311329088Smarkm } 311429088Smarkm 311529088Smarkm cp = arg; 311629088Smarkm 311756668Sshin#ifdef INET6 311856668Sshin if (ai->ai_family == AF_INET6) { 311956668Sshin cmsg = inet6_rthdr_init(*cpp, IPV6_RTHDR_TYPE_0); 312056668Sshin if (*cp != '@') 312156668Sshin return -1; 312256668Sshin *protop = IPPROTO_IPV6; 312356668Sshin *optp = IPV6_PKTOPTIONS; 312456668Sshin } else 312556668Sshin#endif 312656668Sshin { 312729088Smarkm /* 312829088Smarkm * Next, decide whether we have a loose source 312929088Smarkm * route or a strict source route, and fill in 313029088Smarkm * the begining of the option. 313129088Smarkm */ 313229088Smarkm#ifndef sysV88 313329088Smarkm if (*cp == '!') { 313429088Smarkm cp++; 313529088Smarkm *lsrp++ = IPOPT_SSRR; 313629088Smarkm } else 313729088Smarkm *lsrp++ = IPOPT_LSRR; 313829088Smarkm#else 313929088Smarkm if (*cp == '!') { 314029088Smarkm cp++; 314129088Smarkm ipopt.io_type = IPOPT_SSRR; 314229088Smarkm } else 314329088Smarkm ipopt.io_type = IPOPT_LSRR; 314429088Smarkm#endif 314529088Smarkm 314629088Smarkm if (*cp != '@') 314757724Sshin return -1; 314829088Smarkm 314929088Smarkm#ifndef sysV88 315029088Smarkm lsrp++; /* skip over length, we'll fill it in later */ 315129088Smarkm *lsrp++ = 4; 315229088Smarkm#endif 315356668Sshin *protop = IPPROTO_IP; 315456668Sshin *optp = IP_OPTIONS; 315556668Sshin } 315629088Smarkm 315729088Smarkm cp++; 315856668Sshin memset(&hints, 0, sizeof(hints)); 315956668Sshin hints.ai_family = ai->ai_family; 316056668Sshin hints.ai_socktype = SOCK_STREAM; 316129088Smarkm for (c = 0;;) { 316256668Sshin if ( 316356668Sshin#ifdef INET6 316456668Sshin ai->ai_family != AF_INET6 && 316556668Sshin#endif 316656668Sshin c == ':') 316729088Smarkm cp2 = 0; 316829181Smarkm else for (cp2 = cp; (c = *cp2); cp2++) { 316929088Smarkm if (c == ',') { 317029088Smarkm *cp2++ = '\0'; 317129088Smarkm if (*cp2 == '@') 317229088Smarkm cp2++; 317329088Smarkm } else if (c == '@') { 317429088Smarkm *cp2++ = '\0'; 317556668Sshin } else if ( 317656668Sshin#ifdef INET6 317756668Sshin ai->ai_family != AF_INET6 && 317856668Sshin#endif 317956668Sshin c == ':') { 318029088Smarkm *cp2++ = '\0'; 318129088Smarkm } else 318229088Smarkm continue; 318329088Smarkm break; 318429088Smarkm } 318529088Smarkm if (!c) 318629088Smarkm cp2 = 0; 318729088Smarkm 318856668Sshin hints.ai_flags = AI_NUMERICHOST; 318956668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 319062805Sume if (error == EAI_NODATA) { 319156668Sshin hints.ai_flags = 0; 319256668Sshin error = getaddrinfo(cp, NULL, &hints, &res); 319356668Sshin } 319456668Sshin if (error != 0) { 319556668Sshin fprintf(stderr, "%s: %s\n", cp, gai_strerror(error)); 319656668Sshin if (error == EAI_SYSTEM) 319756668Sshin fprintf(stderr, "%s: %s\n", cp, 319856668Sshin strerror(errno)); 319929088Smarkm *cpp = cp; 320029088Smarkm return(0); 320129088Smarkm } 320256668Sshin#ifdef INET6 320356668Sshin if (res->ai_family == AF_INET6) { 320456668Sshin sin6 = (struct sockaddr_in6 *)res->ai_addr; 320556668Sshin inet6_rthdr_add(cmsg, &sin6->sin6_addr, 320656668Sshin IPV6_RTHDR_LOOSE); 320756668Sshin } else 320856668Sshin#endif 320956668Sshin { 321056668Sshin sin = (struct sockaddr_in *)res->ai_addr; 321156668Sshin memcpy(lsrp, (char *)&sin->sin_addr, 4); 321229088Smarkm lsrp += 4; 321356668Sshin } 321429088Smarkm if (cp2) 321529088Smarkm cp = cp2; 321629088Smarkm else 321729088Smarkm break; 321829088Smarkm /* 321929088Smarkm * Check to make sure there is space for next address 322029088Smarkm */ 322156668Sshin#ifdef INET6 322256668Sshin if (res->ai_family == AF_INET6) { 322357724Sshin if (((char *)CMSG_DATA(cmsg) + 322456668Sshin sizeof(struct ip6_rthdr) + 322556668Sshin ((inet6_rthdr_segments(cmsg) + 1) * 322656668Sshin sizeof(struct in6_addr))) > ep) 322757724Sshin return -1; 322856668Sshin } else 322956668Sshin#endif 323056668Sshin if (lsrp + 4 > ep) 323157724Sshin return -1; 323256668Sshin freeaddrinfo(res); 323329088Smarkm } 323456668Sshin#ifdef INET6 323556668Sshin if (res->ai_family == AF_INET6) { 323656668Sshin inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE); 323756668Sshin *lenp = cmsg->cmsg_len; 323856668Sshin } else 323956668Sshin#endif 324056668Sshin { 324129088Smarkm#ifndef sysV88 324229088Smarkm if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { 324329088Smarkm *cpp = 0; 324429088Smarkm *lenp = 0; 324557724Sshin return -1; 324629088Smarkm } 324729088Smarkm *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ 324829088Smarkm *lenp = lsrp - *cpp; 324929088Smarkm#else 325029088Smarkm ipopt.io_len = lsrp - *cpp; 325129088Smarkm if (ipopt.io_len <= 5) { /* Is 3 better ? */ 325229088Smarkm *cpp = 0; 325329088Smarkm *lenp = 0; 325457724Sshin return -1; 325529088Smarkm } 325629088Smarkm *lenp = sizeof(ipopt); 325729088Smarkm *cpp = (char *) &ipopt; 325829088Smarkm#endif 325956668Sshin } 326056668Sshin freeaddrinfo(res); 326156668Sshin return 1; 326229088Smarkm} 326356668Sshin 326456668Sshin 326556668Sshin 3266