1*7348b5c5SDavid van Moolenbroek /* $NetBSD: commands.c,v 1.68 2012/01/09 16:08:55 christos Exp $ */
2*7348b5c5SDavid van Moolenbroek
3*7348b5c5SDavid van Moolenbroek /*
4*7348b5c5SDavid van Moolenbroek * Copyright (C) 1997 and 1998 WIDE Project.
5*7348b5c5SDavid van Moolenbroek * All rights reserved.
6*7348b5c5SDavid van Moolenbroek *
7*7348b5c5SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*7348b5c5SDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*7348b5c5SDavid van Moolenbroek * are met:
10*7348b5c5SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*7348b5c5SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*7348b5c5SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
13*7348b5c5SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
14*7348b5c5SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
15*7348b5c5SDavid van Moolenbroek * 3. Neither the name of the project nor the names of its contributors
16*7348b5c5SDavid van Moolenbroek * may be used to endorse or promote products derived from this software
17*7348b5c5SDavid van Moolenbroek * without specific prior written permission.
18*7348b5c5SDavid van Moolenbroek *
19*7348b5c5SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20*7348b5c5SDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*7348b5c5SDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*7348b5c5SDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23*7348b5c5SDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*7348b5c5SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*7348b5c5SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*7348b5c5SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*7348b5c5SDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*7348b5c5SDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*7348b5c5SDavid van Moolenbroek * SUCH DAMAGE.
30*7348b5c5SDavid van Moolenbroek */
31*7348b5c5SDavid van Moolenbroek
32*7348b5c5SDavid van Moolenbroek /*
33*7348b5c5SDavid van Moolenbroek * Copyright (c) 1988, 1990, 1993
34*7348b5c5SDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
35*7348b5c5SDavid van Moolenbroek *
36*7348b5c5SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
37*7348b5c5SDavid van Moolenbroek * modification, are permitted provided that the following conditions
38*7348b5c5SDavid van Moolenbroek * are met:
39*7348b5c5SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
40*7348b5c5SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
41*7348b5c5SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
42*7348b5c5SDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
43*7348b5c5SDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
44*7348b5c5SDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
45*7348b5c5SDavid van Moolenbroek * may be used to endorse or promote products derived from this software
46*7348b5c5SDavid van Moolenbroek * without specific prior written permission.
47*7348b5c5SDavid van Moolenbroek *
48*7348b5c5SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
49*7348b5c5SDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50*7348b5c5SDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51*7348b5c5SDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
52*7348b5c5SDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53*7348b5c5SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54*7348b5c5SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55*7348b5c5SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56*7348b5c5SDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57*7348b5c5SDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58*7348b5c5SDavid van Moolenbroek * SUCH DAMAGE.
59*7348b5c5SDavid van Moolenbroek */
60*7348b5c5SDavid van Moolenbroek
61*7348b5c5SDavid van Moolenbroek #include <sys/cdefs.h>
62*7348b5c5SDavid van Moolenbroek #ifndef lint
63*7348b5c5SDavid van Moolenbroek #if 0
64*7348b5c5SDavid van Moolenbroek static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95";
65*7348b5c5SDavid van Moolenbroek #else
66*7348b5c5SDavid van Moolenbroek __RCSID("$NetBSD: commands.c,v 1.68 2012/01/09 16:08:55 christos Exp $");
67*7348b5c5SDavid van Moolenbroek #endif
68*7348b5c5SDavid van Moolenbroek #endif /* not lint */
69*7348b5c5SDavid van Moolenbroek
70*7348b5c5SDavid van Moolenbroek #include <sys/param.h>
71*7348b5c5SDavid van Moolenbroek #include <sys/file.h>
72*7348b5c5SDavid van Moolenbroek #include <sys/wait.h>
73*7348b5c5SDavid van Moolenbroek #include <sys/socket.h>
74*7348b5c5SDavid van Moolenbroek #include <netinet/in.h>
75*7348b5c5SDavid van Moolenbroek #include <arpa/inet.h>
76*7348b5c5SDavid van Moolenbroek
77*7348b5c5SDavid van Moolenbroek #include <ctype.h>
78*7348b5c5SDavid van Moolenbroek #include <errno.h>
79*7348b5c5SDavid van Moolenbroek #include <netdb.h>
80*7348b5c5SDavid van Moolenbroek #include <pwd.h>
81*7348b5c5SDavid van Moolenbroek #include <signal.h>
82*7348b5c5SDavid van Moolenbroek #include <stdarg.h>
83*7348b5c5SDavid van Moolenbroek #include <unistd.h>
84*7348b5c5SDavid van Moolenbroek
85*7348b5c5SDavid van Moolenbroek #include <arpa/telnet.h>
86*7348b5c5SDavid van Moolenbroek
87*7348b5c5SDavid van Moolenbroek #include "general.h"
88*7348b5c5SDavid van Moolenbroek #include "ring.h"
89*7348b5c5SDavid van Moolenbroek #include "externs.h"
90*7348b5c5SDavid van Moolenbroek #include "defines.h"
91*7348b5c5SDavid van Moolenbroek #include "types.h"
92*7348b5c5SDavid van Moolenbroek #include <libtelnet/misc.h>
93*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
94*7348b5c5SDavid van Moolenbroek #include <libtelnet/auth.h>
95*7348b5c5SDavid van Moolenbroek #endif
96*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
97*7348b5c5SDavid van Moolenbroek #include <libtelnet/encrypt.h>
98*7348b5c5SDavid van Moolenbroek #endif
99*7348b5c5SDavid van Moolenbroek
100*7348b5c5SDavid van Moolenbroek #include <netinet/in_systm.h>
101*7348b5c5SDavid van Moolenbroek #include <netinet/ip.h>
102*7348b5c5SDavid van Moolenbroek
103*7348b5c5SDavid van Moolenbroek
104*7348b5c5SDavid van Moolenbroek #if defined(IPPROTO_IP) && defined(IP_TOS)
105*7348b5c5SDavid van Moolenbroek int tos = -1;
106*7348b5c5SDavid van Moolenbroek #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
107*7348b5c5SDavid van Moolenbroek
108*7348b5c5SDavid van Moolenbroek char *hostname;
109*7348b5c5SDavid van Moolenbroek static char _hostname[MAXHOSTNAMELEN];
110*7348b5c5SDavid van Moolenbroek
111*7348b5c5SDavid van Moolenbroek typedef struct {
112*7348b5c5SDavid van Moolenbroek const char *name; /* command name */
113*7348b5c5SDavid van Moolenbroek const char *help; /* help string (NULL for no help) */
114*7348b5c5SDavid van Moolenbroek int (*handler) /* routine which executes command */
115*7348b5c5SDavid van Moolenbroek (int, char *[]);
116*7348b5c5SDavid van Moolenbroek int needconnect; /* Do we need to be connected to execute? */
117*7348b5c5SDavid van Moolenbroek } Command;
118*7348b5c5SDavid van Moolenbroek
119*7348b5c5SDavid van Moolenbroek static char line[256];
120*7348b5c5SDavid van Moolenbroek static char saveline[256];
121*7348b5c5SDavid van Moolenbroek static int margc;
122*7348b5c5SDavid van Moolenbroek static char *margv[20];
123*7348b5c5SDavid van Moolenbroek
124*7348b5c5SDavid van Moolenbroek static void makeargv(void);
125*7348b5c5SDavid van Moolenbroek static int special(char *);
126*7348b5c5SDavid van Moolenbroek static const char *control(cc_t);
127*7348b5c5SDavid van Moolenbroek static int sendcmd(int, char **);
128*7348b5c5SDavid van Moolenbroek static int send_esc(char *);
129*7348b5c5SDavid van Moolenbroek static int send_docmd(char *);
130*7348b5c5SDavid van Moolenbroek static int send_dontcmd(char *);
131*7348b5c5SDavid van Moolenbroek static int send_willcmd(char *);
132*7348b5c5SDavid van Moolenbroek static int send_wontcmd(char *);
133*7348b5c5SDavid van Moolenbroek static int send_help(char *);
134*7348b5c5SDavid van Moolenbroek static int lclchars(int);
135*7348b5c5SDavid van Moolenbroek static int togdebug(int);
136*7348b5c5SDavid van Moolenbroek static int togcrlf(int);
137*7348b5c5SDavid van Moolenbroek static int togbinary(int);
138*7348b5c5SDavid van Moolenbroek static int togrbinary(int);
139*7348b5c5SDavid van Moolenbroek static int togxbinary(int);
140*7348b5c5SDavid van Moolenbroek static int togglehelp(int);
141*7348b5c5SDavid van Moolenbroek static void settogglehelp(int);
142*7348b5c5SDavid van Moolenbroek static int toggle(int, char *[]);
143*7348b5c5SDavid van Moolenbroek static struct setlist *getset(char *);
144*7348b5c5SDavid van Moolenbroek static int setcmd(int, char *[]);
145*7348b5c5SDavid van Moolenbroek static int unsetcmd(int, char *[]);
146*7348b5c5SDavid van Moolenbroek static int dokludgemode(int);
147*7348b5c5SDavid van Moolenbroek static int dolinemode(int);
148*7348b5c5SDavid van Moolenbroek static int docharmode(int);
149*7348b5c5SDavid van Moolenbroek static int dolmmode(int, int );
150*7348b5c5SDavid van Moolenbroek static int modecmd(int, char *[]);
151*7348b5c5SDavid van Moolenbroek static int display(int, char *[]);
152*7348b5c5SDavid van Moolenbroek static int setescape(int, char *[]);
153*7348b5c5SDavid van Moolenbroek static int togcrmod(int, char *[]);
154*7348b5c5SDavid van Moolenbroek static int bye(int, char *[]);
155*7348b5c5SDavid van Moolenbroek static void slc_help(int);
156*7348b5c5SDavid van Moolenbroek static struct slclist *getslc(char *);
157*7348b5c5SDavid van Moolenbroek static int slccmd(int, char *[]);
158*7348b5c5SDavid van Moolenbroek static struct env_lst *env_help(const unsigned char *, unsigned char *);
159*7348b5c5SDavid van Moolenbroek static struct envlist *getenvcmd(char *);
160*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
161*7348b5c5SDavid van Moolenbroek static int auth_help(char *);
162*7348b5c5SDavid van Moolenbroek #endif
163*7348b5c5SDavid van Moolenbroek #ifdef TN3270
164*7348b5c5SDavid van Moolenbroek static void filestuff(int);
165*7348b5c5SDavid van Moolenbroek #endif
166*7348b5c5SDavid van Moolenbroek static int status(int, char *[]);
167*7348b5c5SDavid van Moolenbroek static const char *sockaddr_ntop (struct sockaddr *);
168*7348b5c5SDavid van Moolenbroek typedef int (*intrtn_t)(int, char **);
169*7348b5c5SDavid van Moolenbroek static int call(intrtn_t, ...);
170*7348b5c5SDavid van Moolenbroek static Command *getcmd(char *);
171*7348b5c5SDavid van Moolenbroek static int help(int, char *[]);
172*7348b5c5SDavid van Moolenbroek
173*7348b5c5SDavid van Moolenbroek static void
makeargv(void)174*7348b5c5SDavid van Moolenbroek makeargv(void)
175*7348b5c5SDavid van Moolenbroek {
176*7348b5c5SDavid van Moolenbroek char *cp, *cp2, c;
177*7348b5c5SDavid van Moolenbroek char **argp = margv;
178*7348b5c5SDavid van Moolenbroek static char bang[] = "!";
179*7348b5c5SDavid van Moolenbroek
180*7348b5c5SDavid van Moolenbroek margc = 0;
181*7348b5c5SDavid van Moolenbroek cp = line;
182*7348b5c5SDavid van Moolenbroek if (*cp == '!') { /* Special case shell escape */
183*7348b5c5SDavid van Moolenbroek strlcpy(saveline, line, sizeof(saveline)); /* save for shell command */
184*7348b5c5SDavid van Moolenbroek *argp++ = bang; /* No room in string to get this */
185*7348b5c5SDavid van Moolenbroek margc++;
186*7348b5c5SDavid van Moolenbroek cp++;
187*7348b5c5SDavid van Moolenbroek }
188*7348b5c5SDavid van Moolenbroek while ((c = *cp) != '\0') {
189*7348b5c5SDavid van Moolenbroek int inquote = 0;
190*7348b5c5SDavid van Moolenbroek while (isspace((unsigned char)c))
191*7348b5c5SDavid van Moolenbroek c = *++cp;
192*7348b5c5SDavid van Moolenbroek if (c == '\0')
193*7348b5c5SDavid van Moolenbroek break;
194*7348b5c5SDavid van Moolenbroek *argp++ = cp;
195*7348b5c5SDavid van Moolenbroek margc += 1;
196*7348b5c5SDavid van Moolenbroek for (cp2 = cp; c != '\0'; c = *++cp) {
197*7348b5c5SDavid van Moolenbroek if (inquote) {
198*7348b5c5SDavid van Moolenbroek if (c == inquote) {
199*7348b5c5SDavid van Moolenbroek inquote = 0;
200*7348b5c5SDavid van Moolenbroek continue;
201*7348b5c5SDavid van Moolenbroek }
202*7348b5c5SDavid van Moolenbroek } else {
203*7348b5c5SDavid van Moolenbroek if (c == '\\') {
204*7348b5c5SDavid van Moolenbroek if ((c = *++cp) == '\0')
205*7348b5c5SDavid van Moolenbroek break;
206*7348b5c5SDavid van Moolenbroek } else if (c == '"') {
207*7348b5c5SDavid van Moolenbroek inquote = '"';
208*7348b5c5SDavid van Moolenbroek continue;
209*7348b5c5SDavid van Moolenbroek } else if (c == '\'') {
210*7348b5c5SDavid van Moolenbroek inquote = '\'';
211*7348b5c5SDavid van Moolenbroek continue;
212*7348b5c5SDavid van Moolenbroek } else if (isspace((unsigned char)c))
213*7348b5c5SDavid van Moolenbroek break;
214*7348b5c5SDavid van Moolenbroek }
215*7348b5c5SDavid van Moolenbroek *cp2++ = c;
216*7348b5c5SDavid van Moolenbroek }
217*7348b5c5SDavid van Moolenbroek *cp2 = '\0';
218*7348b5c5SDavid van Moolenbroek if (c == '\0')
219*7348b5c5SDavid van Moolenbroek break;
220*7348b5c5SDavid van Moolenbroek cp++;
221*7348b5c5SDavid van Moolenbroek }
222*7348b5c5SDavid van Moolenbroek *argp++ = 0;
223*7348b5c5SDavid van Moolenbroek }
224*7348b5c5SDavid van Moolenbroek
225*7348b5c5SDavid van Moolenbroek /*
226*7348b5c5SDavid van Moolenbroek * Make a character string into a number.
227*7348b5c5SDavid van Moolenbroek *
228*7348b5c5SDavid van Moolenbroek * Todo: 1. Could take random integers (12, 0x12, 012, 0b1).
229*7348b5c5SDavid van Moolenbroek */
230*7348b5c5SDavid van Moolenbroek
231*7348b5c5SDavid van Moolenbroek static int
special(char * s)232*7348b5c5SDavid van Moolenbroek special(char *s)
233*7348b5c5SDavid van Moolenbroek {
234*7348b5c5SDavid van Moolenbroek char c;
235*7348b5c5SDavid van Moolenbroek char b;
236*7348b5c5SDavid van Moolenbroek
237*7348b5c5SDavid van Moolenbroek switch (*s) {
238*7348b5c5SDavid van Moolenbroek case '^':
239*7348b5c5SDavid van Moolenbroek b = *++s;
240*7348b5c5SDavid van Moolenbroek if (b == '?') {
241*7348b5c5SDavid van Moolenbroek c = b | 0x40; /* DEL */
242*7348b5c5SDavid van Moolenbroek } else {
243*7348b5c5SDavid van Moolenbroek c = b & 0x1f;
244*7348b5c5SDavid van Moolenbroek }
245*7348b5c5SDavid van Moolenbroek break;
246*7348b5c5SDavid van Moolenbroek default:
247*7348b5c5SDavid van Moolenbroek c = *s;
248*7348b5c5SDavid van Moolenbroek break;
249*7348b5c5SDavid van Moolenbroek }
250*7348b5c5SDavid van Moolenbroek return c;
251*7348b5c5SDavid van Moolenbroek }
252*7348b5c5SDavid van Moolenbroek
253*7348b5c5SDavid van Moolenbroek /*
254*7348b5c5SDavid van Moolenbroek * Construct a control character sequence
255*7348b5c5SDavid van Moolenbroek * for a special character.
256*7348b5c5SDavid van Moolenbroek */
257*7348b5c5SDavid van Moolenbroek static const char *
control(cc_t c)258*7348b5c5SDavid van Moolenbroek control(cc_t c)
259*7348b5c5SDavid van Moolenbroek {
260*7348b5c5SDavid van Moolenbroek static char buf[5];
261*7348b5c5SDavid van Moolenbroek /*
262*7348b5c5SDavid van Moolenbroek * The only way I could get the Sun 3.5 compiler
263*7348b5c5SDavid van Moolenbroek * to shut up about
264*7348b5c5SDavid van Moolenbroek * if ((unsigned int)c >= 0x80)
265*7348b5c5SDavid van Moolenbroek * was to assign "c" to an unsigned int variable...
266*7348b5c5SDavid van Moolenbroek * Arggg....
267*7348b5c5SDavid van Moolenbroek */
268*7348b5c5SDavid van Moolenbroek unsigned int uic = (unsigned int)c;
269*7348b5c5SDavid van Moolenbroek
270*7348b5c5SDavid van Moolenbroek if (uic == 0x7f)
271*7348b5c5SDavid van Moolenbroek return ("^?");
272*7348b5c5SDavid van Moolenbroek if (c == (cc_t)_POSIX_VDISABLE) {
273*7348b5c5SDavid van Moolenbroek return "off";
274*7348b5c5SDavid van Moolenbroek }
275*7348b5c5SDavid van Moolenbroek if (uic >= 0x80) {
276*7348b5c5SDavid van Moolenbroek buf[0] = '\\';
277*7348b5c5SDavid van Moolenbroek buf[1] = ((c>>6)&07) + '0';
278*7348b5c5SDavid van Moolenbroek buf[2] = ((c>>3)&07) + '0';
279*7348b5c5SDavid van Moolenbroek buf[3] = (c&07) + '0';
280*7348b5c5SDavid van Moolenbroek buf[4] = 0;
281*7348b5c5SDavid van Moolenbroek } else if (uic >= 0x20) {
282*7348b5c5SDavid van Moolenbroek buf[0] = c;
283*7348b5c5SDavid van Moolenbroek buf[1] = 0;
284*7348b5c5SDavid van Moolenbroek } else {
285*7348b5c5SDavid van Moolenbroek buf[0] = '^';
286*7348b5c5SDavid van Moolenbroek buf[1] = '@'+c;
287*7348b5c5SDavid van Moolenbroek buf[2] = 0;
288*7348b5c5SDavid van Moolenbroek }
289*7348b5c5SDavid van Moolenbroek return (buf);
290*7348b5c5SDavid van Moolenbroek }
291*7348b5c5SDavid van Moolenbroek
292*7348b5c5SDavid van Moolenbroek
293*7348b5c5SDavid van Moolenbroek
294*7348b5c5SDavid van Moolenbroek /*
295*7348b5c5SDavid van Moolenbroek * The following are data structures and routines for
296*7348b5c5SDavid van Moolenbroek * the "send" command.
297*7348b5c5SDavid van Moolenbroek *
298*7348b5c5SDavid van Moolenbroek */
299*7348b5c5SDavid van Moolenbroek
300*7348b5c5SDavid van Moolenbroek struct sendlist {
301*7348b5c5SDavid van Moolenbroek const char *name; /* How user refers to it (case independent) */
302*7348b5c5SDavid van Moolenbroek const char *help; /* Help information (0 ==> no help) */
303*7348b5c5SDavid van Moolenbroek int needconnect; /* Need to be connected */
304*7348b5c5SDavid van Moolenbroek int narg; /* Number of arguments */
305*7348b5c5SDavid van Moolenbroek int (*handler) /* Routine to perform (for special ops) */
306*7348b5c5SDavid van Moolenbroek (char *);
307*7348b5c5SDavid van Moolenbroek int nbyte; /* Number of bytes to send this command */
308*7348b5c5SDavid van Moolenbroek int what; /* Character to be sent (<0 ==> special) */
309*7348b5c5SDavid van Moolenbroek };
310*7348b5c5SDavid van Moolenbroek
311*7348b5c5SDavid van Moolenbroek
312*7348b5c5SDavid van Moolenbroek static struct sendlist Sendlist[] = {
313*7348b5c5SDavid van Moolenbroek { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO },
314*7348b5c5SDavid van Moolenbroek { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT },
315*7348b5c5SDavid van Moolenbroek { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK },
316*7348b5c5SDavid van Moolenbroek { "break", 0, 1, 0, 0, 2, BREAK },
317*7348b5c5SDavid van Moolenbroek { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC },
318*7348b5c5SDavid van Moolenbroek { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL },
319*7348b5c5SDavid van Moolenbroek { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 },
320*7348b5c5SDavid van Moolenbroek { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA },
321*7348b5c5SDavid van Moolenbroek { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP },
322*7348b5c5SDavid van Moolenbroek { "intp", 0, 1, 0, 0, 2, IP },
323*7348b5c5SDavid van Moolenbroek { "interrupt", 0, 1, 0, 0, 2, IP },
324*7348b5c5SDavid van Moolenbroek { "intr", 0, 1, 0, 0, 2, IP },
325*7348b5c5SDavid van Moolenbroek { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP },
326*7348b5c5SDavid van Moolenbroek { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR },
327*7348b5c5SDavid van Moolenbroek { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT },
328*7348b5c5SDavid van Moolenbroek { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP },
329*7348b5c5SDavid van Moolenbroek { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF },
330*7348b5c5SDavid van Moolenbroek { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 },
331*7348b5c5SDavid van Moolenbroek { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 },
332*7348b5c5SDavid van Moolenbroek { "?", "Display send options", 0, 0, send_help, 0, 0 },
333*7348b5c5SDavid van Moolenbroek { "help", 0, 0, 0, send_help, 0, 0 },
334*7348b5c5SDavid van Moolenbroek { "do", 0, 0, 1, send_docmd, 3, 0 },
335*7348b5c5SDavid van Moolenbroek { "dont", 0, 0, 1, send_dontcmd, 3, 0 },
336*7348b5c5SDavid van Moolenbroek { "will", 0, 0, 1, send_willcmd, 3, 0 },
337*7348b5c5SDavid van Moolenbroek { "wont", 0, 0, 1, send_wontcmd, 3, 0 },
338*7348b5c5SDavid van Moolenbroek { .name = 0 }
339*7348b5c5SDavid van Moolenbroek };
340*7348b5c5SDavid van Moolenbroek
341*7348b5c5SDavid van Moolenbroek #define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \
342*7348b5c5SDavid van Moolenbroek sizeof(struct sendlist)))
343*7348b5c5SDavid van Moolenbroek
344*7348b5c5SDavid van Moolenbroek static int
sendcmd(int argc,char ** argv)345*7348b5c5SDavid van Moolenbroek sendcmd(int argc, char **argv)
346*7348b5c5SDavid van Moolenbroek {
347*7348b5c5SDavid van Moolenbroek int count; /* how many bytes we are going to need to send */
348*7348b5c5SDavid van Moolenbroek int i;
349*7348b5c5SDavid van Moolenbroek struct sendlist *s; /* pointer to current command */
350*7348b5c5SDavid van Moolenbroek int success = 0;
351*7348b5c5SDavid van Moolenbroek int needconnect = 0;
352*7348b5c5SDavid van Moolenbroek
353*7348b5c5SDavid van Moolenbroek if (argc < 2) {
354*7348b5c5SDavid van Moolenbroek printf("need at least one argument for 'send' command\n");
355*7348b5c5SDavid van Moolenbroek printf("'send ?' for help\n");
356*7348b5c5SDavid van Moolenbroek return 0;
357*7348b5c5SDavid van Moolenbroek }
358*7348b5c5SDavid van Moolenbroek /*
359*7348b5c5SDavid van Moolenbroek * First, validate all the send arguments.
360*7348b5c5SDavid van Moolenbroek * In addition, we see how much space we are going to need, and
361*7348b5c5SDavid van Moolenbroek * whether or not we will be doing a "SYNCH" operation (which
362*7348b5c5SDavid van Moolenbroek * flushes the network queue).
363*7348b5c5SDavid van Moolenbroek */
364*7348b5c5SDavid van Moolenbroek count = 0;
365*7348b5c5SDavid van Moolenbroek for (i = 1; i < argc; i++) {
366*7348b5c5SDavid van Moolenbroek s = GETSEND(argv[i]);
367*7348b5c5SDavid van Moolenbroek if (s == 0) {
368*7348b5c5SDavid van Moolenbroek printf("Unknown send argument '%s'\n'send ?' for help.\n",
369*7348b5c5SDavid van Moolenbroek argv[i]);
370*7348b5c5SDavid van Moolenbroek return 0;
371*7348b5c5SDavid van Moolenbroek } else if (Ambiguous(s)) {
372*7348b5c5SDavid van Moolenbroek printf("Ambiguous send argument '%s'\n'send ?' for help.\n",
373*7348b5c5SDavid van Moolenbroek argv[i]);
374*7348b5c5SDavid van Moolenbroek return 0;
375*7348b5c5SDavid van Moolenbroek }
376*7348b5c5SDavid van Moolenbroek if (i + s->narg >= argc) {
377*7348b5c5SDavid van Moolenbroek fprintf(stderr,
378*7348b5c5SDavid van Moolenbroek "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n",
379*7348b5c5SDavid van Moolenbroek s->narg, s->narg == 1 ? "" : "s", s->name, s->name);
380*7348b5c5SDavid van Moolenbroek return 0;
381*7348b5c5SDavid van Moolenbroek }
382*7348b5c5SDavid van Moolenbroek count += s->nbyte;
383*7348b5c5SDavid van Moolenbroek if (s->handler == send_help) {
384*7348b5c5SDavid van Moolenbroek send_help(NULL);
385*7348b5c5SDavid van Moolenbroek return 0;
386*7348b5c5SDavid van Moolenbroek }
387*7348b5c5SDavid van Moolenbroek
388*7348b5c5SDavid van Moolenbroek i += s->narg;
389*7348b5c5SDavid van Moolenbroek needconnect += s->needconnect;
390*7348b5c5SDavid van Moolenbroek }
391*7348b5c5SDavid van Moolenbroek if (!connected && needconnect) {
392*7348b5c5SDavid van Moolenbroek printf("?Need to be connected first.\n");
393*7348b5c5SDavid van Moolenbroek printf("'send ?' for help\n");
394*7348b5c5SDavid van Moolenbroek return 0;
395*7348b5c5SDavid van Moolenbroek }
396*7348b5c5SDavid van Moolenbroek /* Now, do we have enough room? */
397*7348b5c5SDavid van Moolenbroek if (NETROOM() < count) {
398*7348b5c5SDavid van Moolenbroek printf("There is not enough room in the buffer TO the network\n");
399*7348b5c5SDavid van Moolenbroek printf("to process your request. Nothing will be done.\n");
400*7348b5c5SDavid van Moolenbroek printf("('send synch' will throw away most data in the network\n");
401*7348b5c5SDavid van Moolenbroek printf("buffer, if this might help.)\n");
402*7348b5c5SDavid van Moolenbroek return 0;
403*7348b5c5SDavid van Moolenbroek }
404*7348b5c5SDavid van Moolenbroek /* OK, they are all OK, now go through again and actually send */
405*7348b5c5SDavid van Moolenbroek count = 0;
406*7348b5c5SDavid van Moolenbroek for (i = 1; i < argc; i++) {
407*7348b5c5SDavid van Moolenbroek if ((s = GETSEND(argv[i])) == 0) {
408*7348b5c5SDavid van Moolenbroek fprintf(stderr, "Telnet 'send' error - argument disappeared!\n");
409*7348b5c5SDavid van Moolenbroek (void) quit(0, NULL);
410*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
411*7348b5c5SDavid van Moolenbroek }
412*7348b5c5SDavid van Moolenbroek if (s->handler) {
413*7348b5c5SDavid van Moolenbroek count++;
414*7348b5c5SDavid van Moolenbroek success += (*s->handler)(argv[i+1]);
415*7348b5c5SDavid van Moolenbroek i += s->narg;
416*7348b5c5SDavid van Moolenbroek } else {
417*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, s->what);
418*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, s->what);
419*7348b5c5SDavid van Moolenbroek }
420*7348b5c5SDavid van Moolenbroek }
421*7348b5c5SDavid van Moolenbroek return (count == success);
422*7348b5c5SDavid van Moolenbroek }
423*7348b5c5SDavid van Moolenbroek
424*7348b5c5SDavid van Moolenbroek static int
send_esc(char * s)425*7348b5c5SDavid van Moolenbroek send_esc(char *s)
426*7348b5c5SDavid van Moolenbroek {
427*7348b5c5SDavid van Moolenbroek NETADD(escape);
428*7348b5c5SDavid van Moolenbroek return 1;
429*7348b5c5SDavid van Moolenbroek }
430*7348b5c5SDavid van Moolenbroek
431*7348b5c5SDavid van Moolenbroek static int
send_docmd(char * name)432*7348b5c5SDavid van Moolenbroek send_docmd(char *name)
433*7348b5c5SDavid van Moolenbroek {
434*7348b5c5SDavid van Moolenbroek return(send_tncmd(send_do, "do", name));
435*7348b5c5SDavid van Moolenbroek }
436*7348b5c5SDavid van Moolenbroek
437*7348b5c5SDavid van Moolenbroek static int
send_dontcmd(char * name)438*7348b5c5SDavid van Moolenbroek send_dontcmd(char *name)
439*7348b5c5SDavid van Moolenbroek {
440*7348b5c5SDavid van Moolenbroek return(send_tncmd(send_dont, "dont", name));
441*7348b5c5SDavid van Moolenbroek }
442*7348b5c5SDavid van Moolenbroek static int
send_willcmd(char * name)443*7348b5c5SDavid van Moolenbroek send_willcmd(char *name)
444*7348b5c5SDavid van Moolenbroek {
445*7348b5c5SDavid van Moolenbroek return(send_tncmd(send_will, "will", name));
446*7348b5c5SDavid van Moolenbroek }
447*7348b5c5SDavid van Moolenbroek static int
send_wontcmd(char * name)448*7348b5c5SDavid van Moolenbroek send_wontcmd(char *name)
449*7348b5c5SDavid van Moolenbroek {
450*7348b5c5SDavid van Moolenbroek return(send_tncmd(send_wont, "wont", name));
451*7348b5c5SDavid van Moolenbroek }
452*7348b5c5SDavid van Moolenbroek
453*7348b5c5SDavid van Moolenbroek int
send_tncmd(void (* func)(int,int),const char * cmd,char * name)454*7348b5c5SDavid van Moolenbroek send_tncmd(void (*func)(int, int), const char *cmd, char *name)
455*7348b5c5SDavid van Moolenbroek {
456*7348b5c5SDavid van Moolenbroek const char **cpp;
457*7348b5c5SDavid van Moolenbroek int val = 0;
458*7348b5c5SDavid van Moolenbroek
459*7348b5c5SDavid van Moolenbroek if (isprefix(name, "?")) {
460*7348b5c5SDavid van Moolenbroek int col, len;
461*7348b5c5SDavid van Moolenbroek
462*7348b5c5SDavid van Moolenbroek printf("usage: send %s <value|option>\n", cmd);
463*7348b5c5SDavid van Moolenbroek printf("\"value\" must be from 0 to 255\n");
464*7348b5c5SDavid van Moolenbroek printf("Valid options are:\n\t");
465*7348b5c5SDavid van Moolenbroek
466*7348b5c5SDavid van Moolenbroek col = 8;
467*7348b5c5SDavid van Moolenbroek for (cpp = telopts; *cpp; cpp++) {
468*7348b5c5SDavid van Moolenbroek len = strlen(*cpp) + 3;
469*7348b5c5SDavid van Moolenbroek if (col + len > 65) {
470*7348b5c5SDavid van Moolenbroek printf("\n\t");
471*7348b5c5SDavid van Moolenbroek col = 8;
472*7348b5c5SDavid van Moolenbroek }
473*7348b5c5SDavid van Moolenbroek printf(" \"%s\"", *cpp);
474*7348b5c5SDavid van Moolenbroek col += len;
475*7348b5c5SDavid van Moolenbroek }
476*7348b5c5SDavid van Moolenbroek printf("\n");
477*7348b5c5SDavid van Moolenbroek return 0;
478*7348b5c5SDavid van Moolenbroek }
479*7348b5c5SDavid van Moolenbroek cpp = (void *)genget(name, __UNCONST(telopts), sizeof(char *));
480*7348b5c5SDavid van Moolenbroek if (Ambiguous(cpp)) {
481*7348b5c5SDavid van Moolenbroek fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n",
482*7348b5c5SDavid van Moolenbroek name, cmd);
483*7348b5c5SDavid van Moolenbroek return 0;
484*7348b5c5SDavid van Moolenbroek }
485*7348b5c5SDavid van Moolenbroek if (cpp) {
486*7348b5c5SDavid van Moolenbroek val = cpp - telopts;
487*7348b5c5SDavid van Moolenbroek } else {
488*7348b5c5SDavid van Moolenbroek char *cp = name;
489*7348b5c5SDavid van Moolenbroek
490*7348b5c5SDavid van Moolenbroek while (*cp >= '0' && *cp <= '9') {
491*7348b5c5SDavid van Moolenbroek val *= 10;
492*7348b5c5SDavid van Moolenbroek val += *cp - '0';
493*7348b5c5SDavid van Moolenbroek cp++;
494*7348b5c5SDavid van Moolenbroek }
495*7348b5c5SDavid van Moolenbroek if (*cp != 0) {
496*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
497*7348b5c5SDavid van Moolenbroek name, cmd);
498*7348b5c5SDavid van Moolenbroek return 0;
499*7348b5c5SDavid van Moolenbroek } else if (val < 0 || val > 255) {
500*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n",
501*7348b5c5SDavid van Moolenbroek name, cmd);
502*7348b5c5SDavid van Moolenbroek return 0;
503*7348b5c5SDavid van Moolenbroek }
504*7348b5c5SDavid van Moolenbroek }
505*7348b5c5SDavid van Moolenbroek if (!connected) {
506*7348b5c5SDavid van Moolenbroek printf("?Need to be connected first.\n");
507*7348b5c5SDavid van Moolenbroek return 0;
508*7348b5c5SDavid van Moolenbroek }
509*7348b5c5SDavid van Moolenbroek (*func)(val, 1);
510*7348b5c5SDavid van Moolenbroek return 1;
511*7348b5c5SDavid van Moolenbroek }
512*7348b5c5SDavid van Moolenbroek
513*7348b5c5SDavid van Moolenbroek static int
send_help(char * n)514*7348b5c5SDavid van Moolenbroek send_help(char *n)
515*7348b5c5SDavid van Moolenbroek {
516*7348b5c5SDavid van Moolenbroek struct sendlist *s; /* pointer to current command */
517*7348b5c5SDavid van Moolenbroek for (s = Sendlist; s->name; s++) {
518*7348b5c5SDavid van Moolenbroek if (s->help)
519*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", s->name, s->help);
520*7348b5c5SDavid van Moolenbroek }
521*7348b5c5SDavid van Moolenbroek return(0);
522*7348b5c5SDavid van Moolenbroek }
523*7348b5c5SDavid van Moolenbroek
524*7348b5c5SDavid van Moolenbroek /*
525*7348b5c5SDavid van Moolenbroek * The following are the routines and data structures referred
526*7348b5c5SDavid van Moolenbroek * to by the arguments to the "toggle" command.
527*7348b5c5SDavid van Moolenbroek */
528*7348b5c5SDavid van Moolenbroek
529*7348b5c5SDavid van Moolenbroek static int
lclchars(int n)530*7348b5c5SDavid van Moolenbroek lclchars(int n)
531*7348b5c5SDavid van Moolenbroek {
532*7348b5c5SDavid van Moolenbroek donelclchars = 1;
533*7348b5c5SDavid van Moolenbroek return 1;
534*7348b5c5SDavid van Moolenbroek }
535*7348b5c5SDavid van Moolenbroek
536*7348b5c5SDavid van Moolenbroek static int
togdebug(int n)537*7348b5c5SDavid van Moolenbroek togdebug(int n)
538*7348b5c5SDavid van Moolenbroek {
539*7348b5c5SDavid van Moolenbroek if (net > 0 &&
540*7348b5c5SDavid van Moolenbroek (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, telnet_debug)) < 0) {
541*7348b5c5SDavid van Moolenbroek perror("setsockopt (SO_DEBUG)");
542*7348b5c5SDavid van Moolenbroek }
543*7348b5c5SDavid van Moolenbroek return 1;
544*7348b5c5SDavid van Moolenbroek }
545*7348b5c5SDavid van Moolenbroek
546*7348b5c5SDavid van Moolenbroek static int
togcrlf(int n)547*7348b5c5SDavid van Moolenbroek togcrlf(int n)
548*7348b5c5SDavid van Moolenbroek {
549*7348b5c5SDavid van Moolenbroek if (crlf) {
550*7348b5c5SDavid van Moolenbroek printf("Will send carriage returns as telnet <CR><LF>.\n");
551*7348b5c5SDavid van Moolenbroek } else {
552*7348b5c5SDavid van Moolenbroek printf("Will send carriage returns as telnet <CR><NUL>.\n");
553*7348b5c5SDavid van Moolenbroek }
554*7348b5c5SDavid van Moolenbroek return 1;
555*7348b5c5SDavid van Moolenbroek }
556*7348b5c5SDavid van Moolenbroek
557*7348b5c5SDavid van Moolenbroek int binmode;
558*7348b5c5SDavid van Moolenbroek
559*7348b5c5SDavid van Moolenbroek static int
togbinary(int val)560*7348b5c5SDavid van Moolenbroek togbinary(int val)
561*7348b5c5SDavid van Moolenbroek {
562*7348b5c5SDavid van Moolenbroek donebinarytoggle = 1;
563*7348b5c5SDavid van Moolenbroek
564*7348b5c5SDavid van Moolenbroek if (val >= 0) {
565*7348b5c5SDavid van Moolenbroek binmode = val;
566*7348b5c5SDavid van Moolenbroek } else {
567*7348b5c5SDavid van Moolenbroek if (my_want_state_is_will(TELOPT_BINARY) &&
568*7348b5c5SDavid van Moolenbroek my_want_state_is_do(TELOPT_BINARY)) {
569*7348b5c5SDavid van Moolenbroek binmode = 1;
570*7348b5c5SDavid van Moolenbroek } else if (my_want_state_is_wont(TELOPT_BINARY) &&
571*7348b5c5SDavid van Moolenbroek my_want_state_is_dont(TELOPT_BINARY)) {
572*7348b5c5SDavid van Moolenbroek binmode = 0;
573*7348b5c5SDavid van Moolenbroek }
574*7348b5c5SDavid van Moolenbroek val = binmode ? 0 : 1;
575*7348b5c5SDavid van Moolenbroek }
576*7348b5c5SDavid van Moolenbroek
577*7348b5c5SDavid van Moolenbroek if (val == 1) {
578*7348b5c5SDavid van Moolenbroek if (my_want_state_is_will(TELOPT_BINARY) &&
579*7348b5c5SDavid van Moolenbroek my_want_state_is_do(TELOPT_BINARY)) {
580*7348b5c5SDavid van Moolenbroek printf("Already operating in binary mode with remote host.\n");
581*7348b5c5SDavid van Moolenbroek } else {
582*7348b5c5SDavid van Moolenbroek printf("Negotiating binary mode with remote host.\n");
583*7348b5c5SDavid van Moolenbroek tel_enter_binary(3);
584*7348b5c5SDavid van Moolenbroek }
585*7348b5c5SDavid van Moolenbroek } else {
586*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_BINARY) &&
587*7348b5c5SDavid van Moolenbroek my_want_state_is_dont(TELOPT_BINARY)) {
588*7348b5c5SDavid van Moolenbroek printf("Already in network ascii mode with remote host.\n");
589*7348b5c5SDavid van Moolenbroek } else {
590*7348b5c5SDavid van Moolenbroek printf("Negotiating network ascii mode with remote host.\n");
591*7348b5c5SDavid van Moolenbroek tel_leave_binary(3);
592*7348b5c5SDavid van Moolenbroek }
593*7348b5c5SDavid van Moolenbroek }
594*7348b5c5SDavid van Moolenbroek return 1;
595*7348b5c5SDavid van Moolenbroek }
596*7348b5c5SDavid van Moolenbroek
597*7348b5c5SDavid van Moolenbroek static int
togrbinary(int val)598*7348b5c5SDavid van Moolenbroek togrbinary(int val)
599*7348b5c5SDavid van Moolenbroek {
600*7348b5c5SDavid van Moolenbroek donebinarytoggle = 1;
601*7348b5c5SDavid van Moolenbroek
602*7348b5c5SDavid van Moolenbroek if (val == -1)
603*7348b5c5SDavid van Moolenbroek val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1;
604*7348b5c5SDavid van Moolenbroek
605*7348b5c5SDavid van Moolenbroek if (val == 1) {
606*7348b5c5SDavid van Moolenbroek if (my_want_state_is_do(TELOPT_BINARY)) {
607*7348b5c5SDavid van Moolenbroek printf("Already receiving in binary mode.\n");
608*7348b5c5SDavid van Moolenbroek } else {
609*7348b5c5SDavid van Moolenbroek printf("Negotiating binary mode on input.\n");
610*7348b5c5SDavid van Moolenbroek tel_enter_binary(1);
611*7348b5c5SDavid van Moolenbroek }
612*7348b5c5SDavid van Moolenbroek } else {
613*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_BINARY)) {
614*7348b5c5SDavid van Moolenbroek printf("Already receiving in network ascii mode.\n");
615*7348b5c5SDavid van Moolenbroek } else {
616*7348b5c5SDavid van Moolenbroek printf("Negotiating network ascii mode on input.\n");
617*7348b5c5SDavid van Moolenbroek tel_leave_binary(1);
618*7348b5c5SDavid van Moolenbroek }
619*7348b5c5SDavid van Moolenbroek }
620*7348b5c5SDavid van Moolenbroek return 1;
621*7348b5c5SDavid van Moolenbroek }
622*7348b5c5SDavid van Moolenbroek
623*7348b5c5SDavid van Moolenbroek static int
togxbinary(int val)624*7348b5c5SDavid van Moolenbroek togxbinary(int val)
625*7348b5c5SDavid van Moolenbroek {
626*7348b5c5SDavid van Moolenbroek donebinarytoggle = 1;
627*7348b5c5SDavid van Moolenbroek
628*7348b5c5SDavid van Moolenbroek if (val == -1)
629*7348b5c5SDavid van Moolenbroek val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1;
630*7348b5c5SDavid van Moolenbroek
631*7348b5c5SDavid van Moolenbroek if (val == 1) {
632*7348b5c5SDavid van Moolenbroek if (my_want_state_is_will(TELOPT_BINARY)) {
633*7348b5c5SDavid van Moolenbroek printf("Already transmitting in binary mode.\n");
634*7348b5c5SDavid van Moolenbroek } else {
635*7348b5c5SDavid van Moolenbroek printf("Negotiating binary mode on output.\n");
636*7348b5c5SDavid van Moolenbroek tel_enter_binary(2);
637*7348b5c5SDavid van Moolenbroek }
638*7348b5c5SDavid van Moolenbroek } else {
639*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_BINARY)) {
640*7348b5c5SDavid van Moolenbroek printf("Already transmitting in network ascii mode.\n");
641*7348b5c5SDavid van Moolenbroek } else {
642*7348b5c5SDavid van Moolenbroek printf("Negotiating network ascii mode on output.\n");
643*7348b5c5SDavid van Moolenbroek tel_leave_binary(2);
644*7348b5c5SDavid van Moolenbroek }
645*7348b5c5SDavid van Moolenbroek }
646*7348b5c5SDavid van Moolenbroek return 1;
647*7348b5c5SDavid van Moolenbroek }
648*7348b5c5SDavid van Moolenbroek
649*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
650*7348b5c5SDavid van Moolenbroek extern int EncryptAutoEnc(int);
651*7348b5c5SDavid van Moolenbroek extern int EncryptAutoDec(int);
652*7348b5c5SDavid van Moolenbroek extern int EncryptDebug(int);
653*7348b5c5SDavid van Moolenbroek extern int EncryptVerbose(int);
654*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
655*7348b5c5SDavid van Moolenbroek
656*7348b5c5SDavid van Moolenbroek struct togglelist {
657*7348b5c5SDavid van Moolenbroek const char *name; /* name of toggle */
658*7348b5c5SDavid van Moolenbroek const char *help; /* help message */
659*7348b5c5SDavid van Moolenbroek int (*handler) /* routine to do actual setting */
660*7348b5c5SDavid van Moolenbroek (int);
661*7348b5c5SDavid van Moolenbroek int *variable;
662*7348b5c5SDavid van Moolenbroek const char *actionexplanation;
663*7348b5c5SDavid van Moolenbroek };
664*7348b5c5SDavid van Moolenbroek
665*7348b5c5SDavid van Moolenbroek static struct togglelist Togglelist[] = {
666*7348b5c5SDavid van Moolenbroek { "autoflush",
667*7348b5c5SDavid van Moolenbroek "flushing of output when sending interrupt characters",
668*7348b5c5SDavid van Moolenbroek 0,
669*7348b5c5SDavid van Moolenbroek &autoflush,
670*7348b5c5SDavid van Moolenbroek "flush output when sending interrupt characters" },
671*7348b5c5SDavid van Moolenbroek { "autosynch",
672*7348b5c5SDavid van Moolenbroek "automatic sending of interrupt characters in urgent mode",
673*7348b5c5SDavid van Moolenbroek 0,
674*7348b5c5SDavid van Moolenbroek &autosynch,
675*7348b5c5SDavid van Moolenbroek "send interrupt characters in urgent mode" },
676*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
677*7348b5c5SDavid van Moolenbroek { "autologin",
678*7348b5c5SDavid van Moolenbroek "automatic sending of login and/or authentication info",
679*7348b5c5SDavid van Moolenbroek 0,
680*7348b5c5SDavid van Moolenbroek &autologin,
681*7348b5c5SDavid van Moolenbroek "send login name and/or authentication information" },
682*7348b5c5SDavid van Moolenbroek { "authdebug",
683*7348b5c5SDavid van Moolenbroek "Toggle authentication debugging",
684*7348b5c5SDavid van Moolenbroek auth_togdebug,
685*7348b5c5SDavid van Moolenbroek 0,
686*7348b5c5SDavid van Moolenbroek "print authentication debugging information" },
687*7348b5c5SDavid van Moolenbroek #endif
688*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
689*7348b5c5SDavid van Moolenbroek { "autoencrypt",
690*7348b5c5SDavid van Moolenbroek "automatic encryption of data stream",
691*7348b5c5SDavid van Moolenbroek EncryptAutoEnc,
692*7348b5c5SDavid van Moolenbroek 0,
693*7348b5c5SDavid van Moolenbroek "automatically encrypt output" },
694*7348b5c5SDavid van Moolenbroek { "autodecrypt",
695*7348b5c5SDavid van Moolenbroek "automatic decryption of data stream",
696*7348b5c5SDavid van Moolenbroek EncryptAutoDec,
697*7348b5c5SDavid van Moolenbroek 0,
698*7348b5c5SDavid van Moolenbroek "automatically decrypt input" },
699*7348b5c5SDavid van Moolenbroek { "verbose_encrypt",
700*7348b5c5SDavid van Moolenbroek "Toggle verbose encryption output",
701*7348b5c5SDavid van Moolenbroek EncryptVerbose,
702*7348b5c5SDavid van Moolenbroek 0,
703*7348b5c5SDavid van Moolenbroek "print verbose encryption output" },
704*7348b5c5SDavid van Moolenbroek { "encdebug",
705*7348b5c5SDavid van Moolenbroek "Toggle encryption debugging",
706*7348b5c5SDavid van Moolenbroek EncryptDebug,
707*7348b5c5SDavid van Moolenbroek 0,
708*7348b5c5SDavid van Moolenbroek "print encryption debugging information" },
709*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
710*7348b5c5SDavid van Moolenbroek { "skiprc",
711*7348b5c5SDavid van Moolenbroek "don't read ~/.telnetrc file",
712*7348b5c5SDavid van Moolenbroek 0,
713*7348b5c5SDavid van Moolenbroek &skiprc,
714*7348b5c5SDavid van Moolenbroek "skip reading of ~/.telnetrc file" },
715*7348b5c5SDavid van Moolenbroek { "binary",
716*7348b5c5SDavid van Moolenbroek "sending and receiving of binary data",
717*7348b5c5SDavid van Moolenbroek togbinary,
718*7348b5c5SDavid van Moolenbroek 0,
719*7348b5c5SDavid van Moolenbroek 0 },
720*7348b5c5SDavid van Moolenbroek { "inbinary",
721*7348b5c5SDavid van Moolenbroek "receiving of binary data",
722*7348b5c5SDavid van Moolenbroek togrbinary,
723*7348b5c5SDavid van Moolenbroek 0,
724*7348b5c5SDavid van Moolenbroek 0 },
725*7348b5c5SDavid van Moolenbroek { "outbinary",
726*7348b5c5SDavid van Moolenbroek "sending of binary data",
727*7348b5c5SDavid van Moolenbroek togxbinary,
728*7348b5c5SDavid van Moolenbroek 0,
729*7348b5c5SDavid van Moolenbroek 0 },
730*7348b5c5SDavid van Moolenbroek { "crlf",
731*7348b5c5SDavid van Moolenbroek "sending carriage returns as telnet <CR><LF>",
732*7348b5c5SDavid van Moolenbroek togcrlf,
733*7348b5c5SDavid van Moolenbroek &crlf,
734*7348b5c5SDavid van Moolenbroek 0 },
735*7348b5c5SDavid van Moolenbroek { "crmod",
736*7348b5c5SDavid van Moolenbroek "mapping of received carriage returns",
737*7348b5c5SDavid van Moolenbroek 0,
738*7348b5c5SDavid van Moolenbroek &crmod,
739*7348b5c5SDavid van Moolenbroek "map carriage return on output" },
740*7348b5c5SDavid van Moolenbroek { "localchars",
741*7348b5c5SDavid van Moolenbroek "local recognition of certain control characters",
742*7348b5c5SDavid van Moolenbroek lclchars,
743*7348b5c5SDavid van Moolenbroek &localchars,
744*7348b5c5SDavid van Moolenbroek "recognize certain control characters" },
745*7348b5c5SDavid van Moolenbroek { " ", "", 0, NULL, NULL }, /* empty line */
746*7348b5c5SDavid van Moolenbroek #ifdef TN3270
747*7348b5c5SDavid van Moolenbroek { "apitrace",
748*7348b5c5SDavid van Moolenbroek "(debugging) toggle tracing of API transactions",
749*7348b5c5SDavid van Moolenbroek 0,
750*7348b5c5SDavid van Moolenbroek &apitrace,
751*7348b5c5SDavid van Moolenbroek "trace API transactions" },
752*7348b5c5SDavid van Moolenbroek { "cursesdata",
753*7348b5c5SDavid van Moolenbroek "(debugging) toggle printing of hexadecimal curses data",
754*7348b5c5SDavid van Moolenbroek 0,
755*7348b5c5SDavid van Moolenbroek &cursesdata,
756*7348b5c5SDavid van Moolenbroek "print hexadecimal representation of curses data" },
757*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
758*7348b5c5SDavid van Moolenbroek { "debug",
759*7348b5c5SDavid van Moolenbroek "debugging",
760*7348b5c5SDavid van Moolenbroek togdebug,
761*7348b5c5SDavid van Moolenbroek &telnet_debug,
762*7348b5c5SDavid van Moolenbroek "turn on socket level debugging" },
763*7348b5c5SDavid van Moolenbroek { "netdata",
764*7348b5c5SDavid van Moolenbroek "printing of hexadecimal network data (debugging)",
765*7348b5c5SDavid van Moolenbroek 0,
766*7348b5c5SDavid van Moolenbroek &netdata,
767*7348b5c5SDavid van Moolenbroek "print hexadecimal representation of network traffic" },
768*7348b5c5SDavid van Moolenbroek { "prettydump",
769*7348b5c5SDavid van Moolenbroek "output of \"netdata\" to user readable format (debugging)",
770*7348b5c5SDavid van Moolenbroek 0,
771*7348b5c5SDavid van Moolenbroek &prettydump,
772*7348b5c5SDavid van Moolenbroek "print user readable output for \"netdata\"" },
773*7348b5c5SDavid van Moolenbroek { "options",
774*7348b5c5SDavid van Moolenbroek "viewing of options processing (debugging)",
775*7348b5c5SDavid van Moolenbroek 0,
776*7348b5c5SDavid van Moolenbroek &showoptions,
777*7348b5c5SDavid van Moolenbroek "show option processing" },
778*7348b5c5SDavid van Moolenbroek { "termdata",
779*7348b5c5SDavid van Moolenbroek "(debugging) toggle printing of hexadecimal terminal data",
780*7348b5c5SDavid van Moolenbroek 0,
781*7348b5c5SDavid van Moolenbroek &termdata,
782*7348b5c5SDavid van Moolenbroek "print hexadecimal representation of terminal traffic" },
783*7348b5c5SDavid van Moolenbroek { "?",
784*7348b5c5SDavid van Moolenbroek 0,
785*7348b5c5SDavid van Moolenbroek togglehelp, NULL, NULL },
786*7348b5c5SDavid van Moolenbroek { "help",
787*7348b5c5SDavid van Moolenbroek 0,
788*7348b5c5SDavid van Moolenbroek togglehelp, NULL, NULL },
789*7348b5c5SDavid van Moolenbroek { .name = 0 }
790*7348b5c5SDavid van Moolenbroek };
791*7348b5c5SDavid van Moolenbroek
792*7348b5c5SDavid van Moolenbroek static int
togglehelp(int n)793*7348b5c5SDavid van Moolenbroek togglehelp(int n)
794*7348b5c5SDavid van Moolenbroek {
795*7348b5c5SDavid van Moolenbroek struct togglelist *c;
796*7348b5c5SDavid van Moolenbroek
797*7348b5c5SDavid van Moolenbroek for (c = Togglelist; c->name; c++) {
798*7348b5c5SDavid van Moolenbroek if (c->help) {
799*7348b5c5SDavid van Moolenbroek if (*c->help)
800*7348b5c5SDavid van Moolenbroek printf("%-15s toggle %s\n", c->name, c->help);
801*7348b5c5SDavid van Moolenbroek else
802*7348b5c5SDavid van Moolenbroek printf("\n");
803*7348b5c5SDavid van Moolenbroek }
804*7348b5c5SDavid van Moolenbroek }
805*7348b5c5SDavid van Moolenbroek printf("\n");
806*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", "?", "display help information");
807*7348b5c5SDavid van Moolenbroek return 0;
808*7348b5c5SDavid van Moolenbroek }
809*7348b5c5SDavid van Moolenbroek
810*7348b5c5SDavid van Moolenbroek static void
settogglehelp(int set)811*7348b5c5SDavid van Moolenbroek settogglehelp(int set)
812*7348b5c5SDavid van Moolenbroek {
813*7348b5c5SDavid van Moolenbroek struct togglelist *c;
814*7348b5c5SDavid van Moolenbroek
815*7348b5c5SDavid van Moolenbroek for (c = Togglelist; c->name; c++) {
816*7348b5c5SDavid van Moolenbroek if (c->help) {
817*7348b5c5SDavid van Moolenbroek if (*c->help)
818*7348b5c5SDavid van Moolenbroek printf("%-15s %s %s\n", c->name, set ? "enable" : "disable",
819*7348b5c5SDavid van Moolenbroek c->help);
820*7348b5c5SDavid van Moolenbroek else
821*7348b5c5SDavid van Moolenbroek printf("\n");
822*7348b5c5SDavid van Moolenbroek }
823*7348b5c5SDavid van Moolenbroek }
824*7348b5c5SDavid van Moolenbroek }
825*7348b5c5SDavid van Moolenbroek
826*7348b5c5SDavid van Moolenbroek #define GETTOGGLE(name) (struct togglelist *) \
827*7348b5c5SDavid van Moolenbroek genget(name, (char **) Togglelist, sizeof(struct togglelist))
828*7348b5c5SDavid van Moolenbroek
829*7348b5c5SDavid van Moolenbroek static int
toggle(int argc,char * argv[])830*7348b5c5SDavid van Moolenbroek toggle(int argc, char *argv[])
831*7348b5c5SDavid van Moolenbroek {
832*7348b5c5SDavid van Moolenbroek int retval = 1;
833*7348b5c5SDavid van Moolenbroek char *name;
834*7348b5c5SDavid van Moolenbroek struct togglelist *c;
835*7348b5c5SDavid van Moolenbroek
836*7348b5c5SDavid van Moolenbroek if (argc < 2) {
837*7348b5c5SDavid van Moolenbroek fprintf(stderr,
838*7348b5c5SDavid van Moolenbroek "Need an argument to 'toggle' command. 'toggle ?' for help.\n");
839*7348b5c5SDavid van Moolenbroek return 0;
840*7348b5c5SDavid van Moolenbroek }
841*7348b5c5SDavid van Moolenbroek argc--;
842*7348b5c5SDavid van Moolenbroek argv++;
843*7348b5c5SDavid van Moolenbroek while (argc--) {
844*7348b5c5SDavid van Moolenbroek name = *argv++;
845*7348b5c5SDavid van Moolenbroek c = GETTOGGLE(name);
846*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
847*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n",
848*7348b5c5SDavid van Moolenbroek name);
849*7348b5c5SDavid van Moolenbroek return 0;
850*7348b5c5SDavid van Moolenbroek } else if (c == 0) {
851*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n",
852*7348b5c5SDavid van Moolenbroek name);
853*7348b5c5SDavid van Moolenbroek return 0;
854*7348b5c5SDavid van Moolenbroek } else {
855*7348b5c5SDavid van Moolenbroek if (c->variable) {
856*7348b5c5SDavid van Moolenbroek *c->variable = !*c->variable; /* invert it */
857*7348b5c5SDavid van Moolenbroek if (c->actionexplanation) {
858*7348b5c5SDavid van Moolenbroek printf("%s %s.\n", *c->variable? "Will" : "Won't",
859*7348b5c5SDavid van Moolenbroek c->actionexplanation);
860*7348b5c5SDavid van Moolenbroek }
861*7348b5c5SDavid van Moolenbroek }
862*7348b5c5SDavid van Moolenbroek if (c->handler) {
863*7348b5c5SDavid van Moolenbroek retval &= (*c->handler)(-1);
864*7348b5c5SDavid van Moolenbroek }
865*7348b5c5SDavid van Moolenbroek }
866*7348b5c5SDavid van Moolenbroek }
867*7348b5c5SDavid van Moolenbroek return retval;
868*7348b5c5SDavid van Moolenbroek }
869*7348b5c5SDavid van Moolenbroek
870*7348b5c5SDavid van Moolenbroek /*
871*7348b5c5SDavid van Moolenbroek * The following perform the "set" command.
872*7348b5c5SDavid van Moolenbroek */
873*7348b5c5SDavid van Moolenbroek
874*7348b5c5SDavid van Moolenbroek struct termios new_tc = { .c_iflag = 0 };
875*7348b5c5SDavid van Moolenbroek
876*7348b5c5SDavid van Moolenbroek struct setlist {
877*7348b5c5SDavid van Moolenbroek const char *name; /* name */
878*7348b5c5SDavid van Moolenbroek const char *help; /* help information */
879*7348b5c5SDavid van Moolenbroek void (*handler)(char *);
880*7348b5c5SDavid van Moolenbroek cc_t *charp; /* where it is located at */
881*7348b5c5SDavid van Moolenbroek };
882*7348b5c5SDavid van Moolenbroek
883*7348b5c5SDavid van Moolenbroek static struct setlist Setlist[] = {
884*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
885*7348b5c5SDavid van Moolenbroek { "echo", "character to toggle local echoing on/off", 0, &echoc },
886*7348b5c5SDavid van Moolenbroek #endif
887*7348b5c5SDavid van Moolenbroek { "escape", "character to escape back to telnet command mode", 0, &escape },
888*7348b5c5SDavid van Moolenbroek { "rlogin", "rlogin escape character", 0, &rlogin },
889*7348b5c5SDavid van Moolenbroek { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile},
890*7348b5c5SDavid van Moolenbroek { " ", "", NULL, NULL },
891*7348b5c5SDavid van Moolenbroek { " ", "The following need 'localchars' to be toggled true", 0, 0 },
892*7348b5c5SDavid van Moolenbroek { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp },
893*7348b5c5SDavid van Moolenbroek { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp },
894*7348b5c5SDavid van Moolenbroek { "quit", "character to cause an Abort process", 0, termQuitCharp },
895*7348b5c5SDavid van Moolenbroek { "eof", "character to cause an EOF ", 0, termEofCharp },
896*7348b5c5SDavid van Moolenbroek { " ", "", NULL, NULL },
897*7348b5c5SDavid van Moolenbroek { " ", "The following are for local editing in linemode", 0, 0 },
898*7348b5c5SDavid van Moolenbroek { "erase", "character to use to erase a character", 0, termEraseCharp },
899*7348b5c5SDavid van Moolenbroek { "kill", "character to use to erase a line", 0, termKillCharp },
900*7348b5c5SDavid van Moolenbroek { "lnext", "character to use for literal next", 0, termLiteralNextCharp },
901*7348b5c5SDavid van Moolenbroek { "susp", "character to cause a Suspend Process", 0, termSuspCharp },
902*7348b5c5SDavid van Moolenbroek { "reprint", "character to use for line reprint", 0, termRprntCharp },
903*7348b5c5SDavid van Moolenbroek { "worderase", "character to use to erase a word", 0, termWerasCharp },
904*7348b5c5SDavid van Moolenbroek { "start", "character to use for XON", 0, termStartCharp },
905*7348b5c5SDavid van Moolenbroek { "stop", "character to use for XOFF", 0, termStopCharp },
906*7348b5c5SDavid van Moolenbroek { "forw1", "alternate end of line character", 0, termForw1Charp },
907*7348b5c5SDavid van Moolenbroek { "forw2", "alternate end of line character", 0, termForw2Charp },
908*7348b5c5SDavid van Moolenbroek { "ayt", "alternate AYT character", 0, termAytCharp },
909*7348b5c5SDavid van Moolenbroek { .name = 0 }
910*7348b5c5SDavid van Moolenbroek };
911*7348b5c5SDavid van Moolenbroek
912*7348b5c5SDavid van Moolenbroek static struct setlist *
getset(char * name)913*7348b5c5SDavid van Moolenbroek getset(char *name)
914*7348b5c5SDavid van Moolenbroek {
915*7348b5c5SDavid van Moolenbroek return (struct setlist *)
916*7348b5c5SDavid van Moolenbroek genget(name, (char **) Setlist, sizeof(struct setlist));
917*7348b5c5SDavid van Moolenbroek }
918*7348b5c5SDavid van Moolenbroek
919*7348b5c5SDavid van Moolenbroek void
set_escape_char(char * s)920*7348b5c5SDavid van Moolenbroek set_escape_char(char *s)
921*7348b5c5SDavid van Moolenbroek {
922*7348b5c5SDavid van Moolenbroek if (rlogin != _POSIX_VDISABLE) {
923*7348b5c5SDavid van Moolenbroek rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE;
924*7348b5c5SDavid van Moolenbroek printf("Telnet rlogin escape character is '%s'.\n",
925*7348b5c5SDavid van Moolenbroek control(rlogin));
926*7348b5c5SDavid van Moolenbroek } else {
927*7348b5c5SDavid van Moolenbroek escape = (s && *s) ? special(s) : _POSIX_VDISABLE;
928*7348b5c5SDavid van Moolenbroek printf("Telnet escape character is '%s'.\n", control(escape));
929*7348b5c5SDavid van Moolenbroek }
930*7348b5c5SDavid van Moolenbroek }
931*7348b5c5SDavid van Moolenbroek
932*7348b5c5SDavid van Moolenbroek static int
setcmd(int argc,char * argv[])933*7348b5c5SDavid van Moolenbroek setcmd(int argc, char *argv[])
934*7348b5c5SDavid van Moolenbroek {
935*7348b5c5SDavid van Moolenbroek int value;
936*7348b5c5SDavid van Moolenbroek struct setlist *ct;
937*7348b5c5SDavid van Moolenbroek struct togglelist *c;
938*7348b5c5SDavid van Moolenbroek
939*7348b5c5SDavid van Moolenbroek if (argc < 2 || argc > 3) {
940*7348b5c5SDavid van Moolenbroek printf("Format is 'set Name Value'\n'set ?' for help.\n");
941*7348b5c5SDavid van Moolenbroek return 0;
942*7348b5c5SDavid van Moolenbroek }
943*7348b5c5SDavid van Moolenbroek if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) {
944*7348b5c5SDavid van Moolenbroek for (ct = Setlist; ct->name; ct++)
945*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", ct->name, ct->help);
946*7348b5c5SDavid van Moolenbroek printf("\n");
947*7348b5c5SDavid van Moolenbroek settogglehelp(1);
948*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", "?", "display help information");
949*7348b5c5SDavid van Moolenbroek return 0;
950*7348b5c5SDavid van Moolenbroek }
951*7348b5c5SDavid van Moolenbroek
952*7348b5c5SDavid van Moolenbroek ct = getset(argv[1]);
953*7348b5c5SDavid van Moolenbroek if (ct == 0) {
954*7348b5c5SDavid van Moolenbroek c = GETTOGGLE(argv[1]);
955*7348b5c5SDavid van Moolenbroek if (c == 0) {
956*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n",
957*7348b5c5SDavid van Moolenbroek argv[1]);
958*7348b5c5SDavid van Moolenbroek return 0;
959*7348b5c5SDavid van Moolenbroek } else if (Ambiguous(c)) {
960*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
961*7348b5c5SDavid van Moolenbroek argv[1]);
962*7348b5c5SDavid van Moolenbroek return 0;
963*7348b5c5SDavid van Moolenbroek }
964*7348b5c5SDavid van Moolenbroek if (c->variable) {
965*7348b5c5SDavid van Moolenbroek if ((argc == 2) || (strcmp("on", argv[2]) == 0))
966*7348b5c5SDavid van Moolenbroek *c->variable = 1;
967*7348b5c5SDavid van Moolenbroek else if (strcmp("off", argv[2]) == 0)
968*7348b5c5SDavid van Moolenbroek *c->variable = 0;
969*7348b5c5SDavid van Moolenbroek else {
970*7348b5c5SDavid van Moolenbroek printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n");
971*7348b5c5SDavid van Moolenbroek return 0;
972*7348b5c5SDavid van Moolenbroek }
973*7348b5c5SDavid van Moolenbroek if (c->actionexplanation) {
974*7348b5c5SDavid van Moolenbroek printf("%s %s.\n", *c->variable? "Will" : "Won't",
975*7348b5c5SDavid van Moolenbroek c->actionexplanation);
976*7348b5c5SDavid van Moolenbroek }
977*7348b5c5SDavid van Moolenbroek }
978*7348b5c5SDavid van Moolenbroek if (c->handler)
979*7348b5c5SDavid van Moolenbroek (*c->handler)(1);
980*7348b5c5SDavid van Moolenbroek } else if (argc != 3) {
981*7348b5c5SDavid van Moolenbroek printf("Format is 'set Name Value'\n'set ?' for help.\n");
982*7348b5c5SDavid van Moolenbroek return 0;
983*7348b5c5SDavid van Moolenbroek } else if (Ambiguous(ct)) {
984*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n",
985*7348b5c5SDavid van Moolenbroek argv[1]);
986*7348b5c5SDavid van Moolenbroek return 0;
987*7348b5c5SDavid van Moolenbroek } else if (ct->handler) {
988*7348b5c5SDavid van Moolenbroek (*ct->handler)(argv[2]);
989*7348b5c5SDavid van Moolenbroek printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp);
990*7348b5c5SDavid van Moolenbroek } else {
991*7348b5c5SDavid van Moolenbroek if (strcmp("off", argv[2])) {
992*7348b5c5SDavid van Moolenbroek value = special(argv[2]);
993*7348b5c5SDavid van Moolenbroek } else {
994*7348b5c5SDavid van Moolenbroek value = _POSIX_VDISABLE;
995*7348b5c5SDavid van Moolenbroek }
996*7348b5c5SDavid van Moolenbroek *(ct->charp) = (cc_t)value;
997*7348b5c5SDavid van Moolenbroek printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
998*7348b5c5SDavid van Moolenbroek }
999*7348b5c5SDavid van Moolenbroek slc_check();
1000*7348b5c5SDavid van Moolenbroek return 1;
1001*7348b5c5SDavid van Moolenbroek }
1002*7348b5c5SDavid van Moolenbroek
1003*7348b5c5SDavid van Moolenbroek static int
unsetcmd(int argc,char * argv[])1004*7348b5c5SDavid van Moolenbroek unsetcmd(int argc, char *argv[])
1005*7348b5c5SDavid van Moolenbroek {
1006*7348b5c5SDavid van Moolenbroek struct setlist *ct;
1007*7348b5c5SDavid van Moolenbroek struct togglelist *c;
1008*7348b5c5SDavid van Moolenbroek char *name;
1009*7348b5c5SDavid van Moolenbroek
1010*7348b5c5SDavid van Moolenbroek if (argc < 2) {
1011*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1012*7348b5c5SDavid van Moolenbroek "Need an argument to 'unset' command. 'unset ?' for help.\n");
1013*7348b5c5SDavid van Moolenbroek return 0;
1014*7348b5c5SDavid van Moolenbroek }
1015*7348b5c5SDavid van Moolenbroek if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) {
1016*7348b5c5SDavid van Moolenbroek for (ct = Setlist; ct->name; ct++)
1017*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", ct->name, ct->help);
1018*7348b5c5SDavid van Moolenbroek printf("\n");
1019*7348b5c5SDavid van Moolenbroek settogglehelp(0);
1020*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", "?", "display help information");
1021*7348b5c5SDavid van Moolenbroek return 0;
1022*7348b5c5SDavid van Moolenbroek }
1023*7348b5c5SDavid van Moolenbroek
1024*7348b5c5SDavid van Moolenbroek argc--;
1025*7348b5c5SDavid van Moolenbroek argv++;
1026*7348b5c5SDavid van Moolenbroek while (argc--) {
1027*7348b5c5SDavid van Moolenbroek name = *argv++;
1028*7348b5c5SDavid van Moolenbroek ct = getset(name);
1029*7348b5c5SDavid van Moolenbroek if (ct == 0) {
1030*7348b5c5SDavid van Moolenbroek c = GETTOGGLE(name);
1031*7348b5c5SDavid van Moolenbroek if (c == 0) {
1032*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n",
1033*7348b5c5SDavid van Moolenbroek name);
1034*7348b5c5SDavid van Moolenbroek return 0;
1035*7348b5c5SDavid van Moolenbroek } else if (Ambiguous(c)) {
1036*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
1037*7348b5c5SDavid van Moolenbroek name);
1038*7348b5c5SDavid van Moolenbroek return 0;
1039*7348b5c5SDavid van Moolenbroek }
1040*7348b5c5SDavid van Moolenbroek if (c->variable) {
1041*7348b5c5SDavid van Moolenbroek *c->variable = 0;
1042*7348b5c5SDavid van Moolenbroek if (c->actionexplanation) {
1043*7348b5c5SDavid van Moolenbroek printf("%s %s.\n", *c->variable? "Will" : "Won't",
1044*7348b5c5SDavid van Moolenbroek c->actionexplanation);
1045*7348b5c5SDavid van Moolenbroek }
1046*7348b5c5SDavid van Moolenbroek }
1047*7348b5c5SDavid van Moolenbroek if (c->handler)
1048*7348b5c5SDavid van Moolenbroek (*c->handler)(0);
1049*7348b5c5SDavid van Moolenbroek } else if (Ambiguous(ct)) {
1050*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n",
1051*7348b5c5SDavid van Moolenbroek name);
1052*7348b5c5SDavid van Moolenbroek return 0;
1053*7348b5c5SDavid van Moolenbroek } else if (ct->handler) {
1054*7348b5c5SDavid van Moolenbroek (*ct->handler)(0);
1055*7348b5c5SDavid van Moolenbroek printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp);
1056*7348b5c5SDavid van Moolenbroek } else {
1057*7348b5c5SDavid van Moolenbroek *(ct->charp) = _POSIX_VDISABLE;
1058*7348b5c5SDavid van Moolenbroek printf("%s character is '%s'.\n", ct->name, control(*(ct->charp)));
1059*7348b5c5SDavid van Moolenbroek }
1060*7348b5c5SDavid van Moolenbroek }
1061*7348b5c5SDavid van Moolenbroek return 1;
1062*7348b5c5SDavid van Moolenbroek }
1063*7348b5c5SDavid van Moolenbroek
1064*7348b5c5SDavid van Moolenbroek /*
1065*7348b5c5SDavid van Moolenbroek * The following are the data structures and routines for the
1066*7348b5c5SDavid van Moolenbroek * 'mode' command.
1067*7348b5c5SDavid van Moolenbroek */
1068*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
1069*7348b5c5SDavid van Moolenbroek extern int kludgelinemode;
1070*7348b5c5SDavid van Moolenbroek
1071*7348b5c5SDavid van Moolenbroek static int
dokludgemode(int n)1072*7348b5c5SDavid van Moolenbroek dokludgemode(int n)
1073*7348b5c5SDavid van Moolenbroek {
1074*7348b5c5SDavid van Moolenbroek kludgelinemode = 1;
1075*7348b5c5SDavid van Moolenbroek send_wont(TELOPT_LINEMODE, 1);
1076*7348b5c5SDavid van Moolenbroek send_dont(TELOPT_SGA, 1);
1077*7348b5c5SDavid van Moolenbroek send_dont(TELOPT_ECHO, 1);
1078*7348b5c5SDavid van Moolenbroek return 1;
1079*7348b5c5SDavid van Moolenbroek }
1080*7348b5c5SDavid van Moolenbroek #endif
1081*7348b5c5SDavid van Moolenbroek
1082*7348b5c5SDavid van Moolenbroek static int
dolinemode(int n)1083*7348b5c5SDavid van Moolenbroek dolinemode(int n)
1084*7348b5c5SDavid van Moolenbroek {
1085*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
1086*7348b5c5SDavid van Moolenbroek if (kludgelinemode)
1087*7348b5c5SDavid van Moolenbroek send_dont(TELOPT_SGA, 1);
1088*7348b5c5SDavid van Moolenbroek #endif
1089*7348b5c5SDavid van Moolenbroek send_will(TELOPT_LINEMODE, 1);
1090*7348b5c5SDavid van Moolenbroek send_dont(TELOPT_ECHO, 1);
1091*7348b5c5SDavid van Moolenbroek return 1;
1092*7348b5c5SDavid van Moolenbroek }
1093*7348b5c5SDavid van Moolenbroek
1094*7348b5c5SDavid van Moolenbroek static int
docharmode(int n)1095*7348b5c5SDavid van Moolenbroek docharmode(int n)
1096*7348b5c5SDavid van Moolenbroek {
1097*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
1098*7348b5c5SDavid van Moolenbroek if (kludgelinemode)
1099*7348b5c5SDavid van Moolenbroek send_do(TELOPT_SGA, 1);
1100*7348b5c5SDavid van Moolenbroek else
1101*7348b5c5SDavid van Moolenbroek #endif
1102*7348b5c5SDavid van Moolenbroek send_wont(TELOPT_LINEMODE, 1);
1103*7348b5c5SDavid van Moolenbroek send_do(TELOPT_ECHO, 1);
1104*7348b5c5SDavid van Moolenbroek return 1;
1105*7348b5c5SDavid van Moolenbroek }
1106*7348b5c5SDavid van Moolenbroek
1107*7348b5c5SDavid van Moolenbroek static int
dolmmode(int bit,int on)1108*7348b5c5SDavid van Moolenbroek dolmmode(int bit, int on)
1109*7348b5c5SDavid van Moolenbroek {
1110*7348b5c5SDavid van Moolenbroek unsigned char c;
1111*7348b5c5SDavid van Moolenbroek extern int linemode;
1112*7348b5c5SDavid van Moolenbroek
1113*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_LINEMODE)) {
1114*7348b5c5SDavid van Moolenbroek printf("?Need to have LINEMODE option enabled first.\n");
1115*7348b5c5SDavid van Moolenbroek printf("'mode ?' for help.\n");
1116*7348b5c5SDavid van Moolenbroek return 0;
1117*7348b5c5SDavid van Moolenbroek }
1118*7348b5c5SDavid van Moolenbroek
1119*7348b5c5SDavid van Moolenbroek if (on)
1120*7348b5c5SDavid van Moolenbroek c = (linemode | bit);
1121*7348b5c5SDavid van Moolenbroek else
1122*7348b5c5SDavid van Moolenbroek c = (linemode & ~bit);
1123*7348b5c5SDavid van Moolenbroek lm_mode(&c, 1, 1);
1124*7348b5c5SDavid van Moolenbroek return 1;
1125*7348b5c5SDavid van Moolenbroek }
1126*7348b5c5SDavid van Moolenbroek
1127*7348b5c5SDavid van Moolenbroek int
set_mode(int bit)1128*7348b5c5SDavid van Moolenbroek set_mode(int bit)
1129*7348b5c5SDavid van Moolenbroek {
1130*7348b5c5SDavid van Moolenbroek return dolmmode(bit, 1);
1131*7348b5c5SDavid van Moolenbroek }
1132*7348b5c5SDavid van Moolenbroek
1133*7348b5c5SDavid van Moolenbroek int
clear_mode(int bit)1134*7348b5c5SDavid van Moolenbroek clear_mode(int bit)
1135*7348b5c5SDavid van Moolenbroek {
1136*7348b5c5SDavid van Moolenbroek return dolmmode(bit, 0);
1137*7348b5c5SDavid van Moolenbroek }
1138*7348b5c5SDavid van Moolenbroek
1139*7348b5c5SDavid van Moolenbroek struct modelist {
1140*7348b5c5SDavid van Moolenbroek const char *name; /* command name */
1141*7348b5c5SDavid van Moolenbroek const char *help; /* help string */
1142*7348b5c5SDavid van Moolenbroek int (*handler) /* routine which executes command */
1143*7348b5c5SDavid van Moolenbroek (int);
1144*7348b5c5SDavid van Moolenbroek int needconnect; /* Do we need to be connected to execute? */
1145*7348b5c5SDavid van Moolenbroek int arg1;
1146*7348b5c5SDavid van Moolenbroek };
1147*7348b5c5SDavid van Moolenbroek
1148*7348b5c5SDavid van Moolenbroek static struct modelist ModeList[] = {
1149*7348b5c5SDavid van Moolenbroek { "character", "Disable LINEMODE option", docharmode, 1, 0 },
1150*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
1151*7348b5c5SDavid van Moolenbroek { "", "(or disable obsolete line-by-line mode)", 0, 0, 0 },
1152*7348b5c5SDavid van Moolenbroek #endif
1153*7348b5c5SDavid van Moolenbroek { "line", "Enable LINEMODE option", dolinemode, 1, 0 },
1154*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
1155*7348b5c5SDavid van Moolenbroek { "", "(or enable obsolete line-by-line mode)", 0, 0, 0 },
1156*7348b5c5SDavid van Moolenbroek #endif
1157*7348b5c5SDavid van Moolenbroek { "", "", 0, 0, 0 },
1158*7348b5c5SDavid van Moolenbroek { "", "These require the LINEMODE option to be enabled", 0, 0, 0 },
1159*7348b5c5SDavid van Moolenbroek { "isig", "Enable signal trapping", set_mode, 1, MODE_TRAPSIG },
1160*7348b5c5SDavid van Moolenbroek { "+isig", 0, set_mode, 1, MODE_TRAPSIG },
1161*7348b5c5SDavid van Moolenbroek { "-isig", "Disable signal trapping", clear_mode, 1, MODE_TRAPSIG },
1162*7348b5c5SDavid van Moolenbroek { "edit", "Enable character editing", set_mode, 1, MODE_EDIT },
1163*7348b5c5SDavid van Moolenbroek { "+edit", 0, set_mode, 1, MODE_EDIT },
1164*7348b5c5SDavid van Moolenbroek { "-edit", "Disable character editing", clear_mode, 1, MODE_EDIT },
1165*7348b5c5SDavid van Moolenbroek { "softtabs", "Enable tab expansion", set_mode, 1, MODE_SOFT_TAB },
1166*7348b5c5SDavid van Moolenbroek { "+softtabs", 0, set_mode, 1, MODE_SOFT_TAB },
1167*7348b5c5SDavid van Moolenbroek { "-softtabs", "Disable character editing", clear_mode, 1, MODE_SOFT_TAB },
1168*7348b5c5SDavid van Moolenbroek { "litecho", "Enable literal character echo", set_mode, 1, MODE_LIT_ECHO },
1169*7348b5c5SDavid van Moolenbroek { "+litecho", 0, set_mode, 1, MODE_LIT_ECHO },
1170*7348b5c5SDavid van Moolenbroek { "-litecho", "Disable literal character echo", clear_mode, 1, MODE_LIT_ECHO },
1171*7348b5c5SDavid van Moolenbroek { "help", 0, modehelp, 0, 0 },
1172*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
1173*7348b5c5SDavid van Moolenbroek { "kludgeline", 0, dokludgemode, 1, 0 },
1174*7348b5c5SDavid van Moolenbroek #endif
1175*7348b5c5SDavid van Moolenbroek { "", "", 0, 0, 0 },
1176*7348b5c5SDavid van Moolenbroek { "?", "Print help information", modehelp, 0, 0 },
1177*7348b5c5SDavid van Moolenbroek { .name = 0 },
1178*7348b5c5SDavid van Moolenbroek };
1179*7348b5c5SDavid van Moolenbroek
1180*7348b5c5SDavid van Moolenbroek
1181*7348b5c5SDavid van Moolenbroek int
modehelp(int n)1182*7348b5c5SDavid van Moolenbroek modehelp(int n)
1183*7348b5c5SDavid van Moolenbroek {
1184*7348b5c5SDavid van Moolenbroek struct modelist *mt;
1185*7348b5c5SDavid van Moolenbroek
1186*7348b5c5SDavid van Moolenbroek printf("format is: 'mode Mode', where 'Mode' is one of:\n\n");
1187*7348b5c5SDavid van Moolenbroek for (mt = ModeList; mt->name; mt++) {
1188*7348b5c5SDavid van Moolenbroek if (mt->help) {
1189*7348b5c5SDavid van Moolenbroek if (*mt->help)
1190*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", mt->name, mt->help);
1191*7348b5c5SDavid van Moolenbroek else
1192*7348b5c5SDavid van Moolenbroek printf("\n");
1193*7348b5c5SDavid van Moolenbroek }
1194*7348b5c5SDavid van Moolenbroek }
1195*7348b5c5SDavid van Moolenbroek return 0;
1196*7348b5c5SDavid van Moolenbroek }
1197*7348b5c5SDavid van Moolenbroek
1198*7348b5c5SDavid van Moolenbroek #define GETMODECMD(name) (struct modelist *) \
1199*7348b5c5SDavid van Moolenbroek genget(name, (char **) ModeList, sizeof(struct modelist))
1200*7348b5c5SDavid van Moolenbroek
1201*7348b5c5SDavid van Moolenbroek static int
modecmd(int argc,char * argv[])1202*7348b5c5SDavid van Moolenbroek modecmd(int argc, char *argv[])
1203*7348b5c5SDavid van Moolenbroek {
1204*7348b5c5SDavid van Moolenbroek struct modelist *mt;
1205*7348b5c5SDavid van Moolenbroek
1206*7348b5c5SDavid van Moolenbroek if (argc != 2) {
1207*7348b5c5SDavid van Moolenbroek printf("'mode' command requires an argument\n");
1208*7348b5c5SDavid van Moolenbroek printf("'mode ?' for help.\n");
1209*7348b5c5SDavid van Moolenbroek } else if ((mt = GETMODECMD(argv[1])) == 0) {
1210*7348b5c5SDavid van Moolenbroek fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]);
1211*7348b5c5SDavid van Moolenbroek } else if (Ambiguous(mt)) {
1212*7348b5c5SDavid van Moolenbroek fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]);
1213*7348b5c5SDavid van Moolenbroek } else if (mt->needconnect && !connected) {
1214*7348b5c5SDavid van Moolenbroek printf("?Need to be connected first.\n");
1215*7348b5c5SDavid van Moolenbroek printf("'mode ?' for help.\n");
1216*7348b5c5SDavid van Moolenbroek } else if (mt->handler) {
1217*7348b5c5SDavid van Moolenbroek return (*mt->handler)(mt->arg1);
1218*7348b5c5SDavid van Moolenbroek }
1219*7348b5c5SDavid van Moolenbroek return 0;
1220*7348b5c5SDavid van Moolenbroek }
1221*7348b5c5SDavid van Moolenbroek
1222*7348b5c5SDavid van Moolenbroek /*
1223*7348b5c5SDavid van Moolenbroek * The following data structures and routines implement the
1224*7348b5c5SDavid van Moolenbroek * "display" command.
1225*7348b5c5SDavid van Moolenbroek */
1226*7348b5c5SDavid van Moolenbroek
1227*7348b5c5SDavid van Moolenbroek static int
display(int argc,char * argv[])1228*7348b5c5SDavid van Moolenbroek display(int argc, char *argv[])
1229*7348b5c5SDavid van Moolenbroek {
1230*7348b5c5SDavid van Moolenbroek struct togglelist *tl;
1231*7348b5c5SDavid van Moolenbroek struct setlist *sl;
1232*7348b5c5SDavid van Moolenbroek
1233*7348b5c5SDavid van Moolenbroek #define dotog(tl) if (tl->variable && tl->actionexplanation) { \
1234*7348b5c5SDavid van Moolenbroek if (*tl->variable) { \
1235*7348b5c5SDavid van Moolenbroek printf("will"); \
1236*7348b5c5SDavid van Moolenbroek } else { \
1237*7348b5c5SDavid van Moolenbroek printf("won't"); \
1238*7348b5c5SDavid van Moolenbroek } \
1239*7348b5c5SDavid van Moolenbroek printf(" %s.\n", tl->actionexplanation); \
1240*7348b5c5SDavid van Moolenbroek }
1241*7348b5c5SDavid van Moolenbroek
1242*7348b5c5SDavid van Moolenbroek #define doset(sl) if (sl->name && *sl->name != ' ') { \
1243*7348b5c5SDavid van Moolenbroek if (sl->handler == 0) \
1244*7348b5c5SDavid van Moolenbroek printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \
1245*7348b5c5SDavid van Moolenbroek else \
1246*7348b5c5SDavid van Moolenbroek printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \
1247*7348b5c5SDavid van Moolenbroek }
1248*7348b5c5SDavid van Moolenbroek
1249*7348b5c5SDavid van Moolenbroek if (argc == 1) {
1250*7348b5c5SDavid van Moolenbroek for (tl = Togglelist; tl->name; tl++) {
1251*7348b5c5SDavid van Moolenbroek dotog(tl);
1252*7348b5c5SDavid van Moolenbroek }
1253*7348b5c5SDavid van Moolenbroek printf("\n");
1254*7348b5c5SDavid van Moolenbroek for (sl = Setlist; sl->name; sl++) {
1255*7348b5c5SDavid van Moolenbroek doset(sl);
1256*7348b5c5SDavid van Moolenbroek }
1257*7348b5c5SDavid van Moolenbroek } else {
1258*7348b5c5SDavid van Moolenbroek int i;
1259*7348b5c5SDavid van Moolenbroek
1260*7348b5c5SDavid van Moolenbroek for (i = 1; i < argc; i++) {
1261*7348b5c5SDavid van Moolenbroek sl = getset(argv[i]);
1262*7348b5c5SDavid van Moolenbroek tl = GETTOGGLE(argv[i]);
1263*7348b5c5SDavid van Moolenbroek if (Ambiguous(sl) || Ambiguous(tl)) {
1264*7348b5c5SDavid van Moolenbroek printf("?Ambiguous argument '%s'.\n", argv[i]);
1265*7348b5c5SDavid van Moolenbroek return 0;
1266*7348b5c5SDavid van Moolenbroek } else if (!sl && !tl) {
1267*7348b5c5SDavid van Moolenbroek printf("?Unknown argument '%s'.\n", argv[i]);
1268*7348b5c5SDavid van Moolenbroek return 0;
1269*7348b5c5SDavid van Moolenbroek } else {
1270*7348b5c5SDavid van Moolenbroek if (tl) {
1271*7348b5c5SDavid van Moolenbroek dotog(tl);
1272*7348b5c5SDavid van Moolenbroek }
1273*7348b5c5SDavid van Moolenbroek if (sl) {
1274*7348b5c5SDavid van Moolenbroek doset(sl);
1275*7348b5c5SDavid van Moolenbroek }
1276*7348b5c5SDavid van Moolenbroek }
1277*7348b5c5SDavid van Moolenbroek }
1278*7348b5c5SDavid van Moolenbroek }
1279*7348b5c5SDavid van Moolenbroek /*@*/optionstatus();
1280*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1281*7348b5c5SDavid van Moolenbroek EncryptStatus();
1282*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
1283*7348b5c5SDavid van Moolenbroek return 1;
1284*7348b5c5SDavid van Moolenbroek #undef doset
1285*7348b5c5SDavid van Moolenbroek #undef dotog
1286*7348b5c5SDavid van Moolenbroek }
1287*7348b5c5SDavid van Moolenbroek
1288*7348b5c5SDavid van Moolenbroek /*
1289*7348b5c5SDavid van Moolenbroek * The following are the data structures, and many of the routines,
1290*7348b5c5SDavid van Moolenbroek * relating to command processing.
1291*7348b5c5SDavid van Moolenbroek */
1292*7348b5c5SDavid van Moolenbroek
1293*7348b5c5SDavid van Moolenbroek /*
1294*7348b5c5SDavid van Moolenbroek * Set the escape character.
1295*7348b5c5SDavid van Moolenbroek */
1296*7348b5c5SDavid van Moolenbroek static int
setescape(int argc,char * argv[])1297*7348b5c5SDavid van Moolenbroek setescape(int argc, char *argv[])
1298*7348b5c5SDavid van Moolenbroek {
1299*7348b5c5SDavid van Moolenbroek char *arg;
1300*7348b5c5SDavid van Moolenbroek char buf[50];
1301*7348b5c5SDavid van Moolenbroek
1302*7348b5c5SDavid van Moolenbroek printf(
1303*7348b5c5SDavid van Moolenbroek "Deprecated usage - please use 'set escape%s%s' in the future.\n",
1304*7348b5c5SDavid van Moolenbroek (argc > 2)? " ":"", (argc > 2)? argv[1]: "");
1305*7348b5c5SDavid van Moolenbroek if (argc > 2)
1306*7348b5c5SDavid van Moolenbroek arg = argv[1];
1307*7348b5c5SDavid van Moolenbroek else {
1308*7348b5c5SDavid van Moolenbroek printf("new escape character: ");
1309*7348b5c5SDavid van Moolenbroek (void) fgets(buf, sizeof(buf), stdin);
1310*7348b5c5SDavid van Moolenbroek arg = buf;
1311*7348b5c5SDavid van Moolenbroek }
1312*7348b5c5SDavid van Moolenbroek if (arg[0] != '\0')
1313*7348b5c5SDavid van Moolenbroek escape = arg[0];
1314*7348b5c5SDavid van Moolenbroek if (!In3270) {
1315*7348b5c5SDavid van Moolenbroek printf("Escape character is '%s'.\n", control(escape));
1316*7348b5c5SDavid van Moolenbroek }
1317*7348b5c5SDavid van Moolenbroek (void) fflush(stdout);
1318*7348b5c5SDavid van Moolenbroek return 1;
1319*7348b5c5SDavid van Moolenbroek }
1320*7348b5c5SDavid van Moolenbroek
1321*7348b5c5SDavid van Moolenbroek /*VARARGS*/
1322*7348b5c5SDavid van Moolenbroek static int
togcrmod(int argc,char * argv[])1323*7348b5c5SDavid van Moolenbroek togcrmod(int argc, char *argv[])
1324*7348b5c5SDavid van Moolenbroek {
1325*7348b5c5SDavid van Moolenbroek crmod = !crmod;
1326*7348b5c5SDavid van Moolenbroek printf("Deprecated usage - please use 'toggle crmod' in the future.\n");
1327*7348b5c5SDavid van Moolenbroek printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't");
1328*7348b5c5SDavid van Moolenbroek (void) fflush(stdout);
1329*7348b5c5SDavid van Moolenbroek return 1;
1330*7348b5c5SDavid van Moolenbroek }
1331*7348b5c5SDavid van Moolenbroek
1332*7348b5c5SDavid van Moolenbroek /*VARARGS*/
1333*7348b5c5SDavid van Moolenbroek int
suspend(int argc,char * argv[])1334*7348b5c5SDavid van Moolenbroek suspend(int argc, char *argv[])
1335*7348b5c5SDavid van Moolenbroek {
1336*7348b5c5SDavid van Moolenbroek setcommandmode();
1337*7348b5c5SDavid van Moolenbroek {
1338*7348b5c5SDavid van Moolenbroek long oldrows, oldcols, newrows, newcols, err;
1339*7348b5c5SDavid van Moolenbroek
1340*7348b5c5SDavid van Moolenbroek err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
1341*7348b5c5SDavid van Moolenbroek (void) kill(0, SIGTSTP);
1342*7348b5c5SDavid van Moolenbroek /*
1343*7348b5c5SDavid van Moolenbroek * If we didn't get the window size before the SUSPEND, but we
1344*7348b5c5SDavid van Moolenbroek * can get them now (?), then send the NAWS to make sure that
1345*7348b5c5SDavid van Moolenbroek * we are set up for the right window size.
1346*7348b5c5SDavid van Moolenbroek */
1347*7348b5c5SDavid van Moolenbroek if (TerminalWindowSize(&newrows, &newcols) && connected &&
1348*7348b5c5SDavid van Moolenbroek (err || ((oldrows != newrows) || (oldcols != newcols)))) {
1349*7348b5c5SDavid van Moolenbroek sendnaws();
1350*7348b5c5SDavid van Moolenbroek }
1351*7348b5c5SDavid van Moolenbroek }
1352*7348b5c5SDavid van Moolenbroek /* reget parameters in case they were changed */
1353*7348b5c5SDavid van Moolenbroek TerminalSaveState();
1354*7348b5c5SDavid van Moolenbroek setconnmode(0);
1355*7348b5c5SDavid van Moolenbroek return 1;
1356*7348b5c5SDavid van Moolenbroek }
1357*7348b5c5SDavid van Moolenbroek
1358*7348b5c5SDavid van Moolenbroek #ifndef TN3270
1359*7348b5c5SDavid van Moolenbroek /*ARGSUSED*/
1360*7348b5c5SDavid van Moolenbroek int
shell(int argc,char * argv[])1361*7348b5c5SDavid van Moolenbroek shell(int argc, char *argv[])
1362*7348b5c5SDavid van Moolenbroek {
1363*7348b5c5SDavid van Moolenbroek long oldrows, oldcols, newrows, newcols;
1364*7348b5c5SDavid van Moolenbroek long volatile err; /* Avoid vfork clobbering */
1365*7348b5c5SDavid van Moolenbroek
1366*7348b5c5SDavid van Moolenbroek setcommandmode();
1367*7348b5c5SDavid van Moolenbroek
1368*7348b5c5SDavid van Moolenbroek err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0;
1369*7348b5c5SDavid van Moolenbroek switch(vfork()) {
1370*7348b5c5SDavid van Moolenbroek case -1:
1371*7348b5c5SDavid van Moolenbroek perror("Fork failed");
1372*7348b5c5SDavid van Moolenbroek break;
1373*7348b5c5SDavid van Moolenbroek
1374*7348b5c5SDavid van Moolenbroek case 0:
1375*7348b5c5SDavid van Moolenbroek {
1376*7348b5c5SDavid van Moolenbroek /*
1377*7348b5c5SDavid van Moolenbroek * Fire up the shell in the child.
1378*7348b5c5SDavid van Moolenbroek */
1379*7348b5c5SDavid van Moolenbroek const char *shellp, *shellname;
1380*7348b5c5SDavid van Moolenbroek
1381*7348b5c5SDavid van Moolenbroek shellp = getenv("SHELL");
1382*7348b5c5SDavid van Moolenbroek if (shellp == NULL)
1383*7348b5c5SDavid van Moolenbroek shellp = "/bin/sh";
1384*7348b5c5SDavid van Moolenbroek if ((shellname = strrchr(shellp, '/')) == 0)
1385*7348b5c5SDavid van Moolenbroek shellname = shellp;
1386*7348b5c5SDavid van Moolenbroek else
1387*7348b5c5SDavid van Moolenbroek shellname++;
1388*7348b5c5SDavid van Moolenbroek if (argc > 1)
1389*7348b5c5SDavid van Moolenbroek execl(shellp, shellname, "-c", &saveline[1], NULL);
1390*7348b5c5SDavid van Moolenbroek else
1391*7348b5c5SDavid van Moolenbroek execl(shellp, shellname, NULL);
1392*7348b5c5SDavid van Moolenbroek perror("execl");
1393*7348b5c5SDavid van Moolenbroek _exit(1);
1394*7348b5c5SDavid van Moolenbroek }
1395*7348b5c5SDavid van Moolenbroek default:
1396*7348b5c5SDavid van Moolenbroek (void)wait((int *)0); /* Wait for the shell to complete */
1397*7348b5c5SDavid van Moolenbroek
1398*7348b5c5SDavid van Moolenbroek if (TerminalWindowSize(&newrows, &newcols) && connected &&
1399*7348b5c5SDavid van Moolenbroek (err || ((oldrows != newrows) || (oldcols != newcols)))) {
1400*7348b5c5SDavid van Moolenbroek sendnaws();
1401*7348b5c5SDavid van Moolenbroek }
1402*7348b5c5SDavid van Moolenbroek break;
1403*7348b5c5SDavid van Moolenbroek }
1404*7348b5c5SDavid van Moolenbroek return 1;
1405*7348b5c5SDavid van Moolenbroek }
1406*7348b5c5SDavid van Moolenbroek #endif /* !defined(TN3270) */
1407*7348b5c5SDavid van Moolenbroek
1408*7348b5c5SDavid van Moolenbroek /*VARARGS*/
1409*7348b5c5SDavid van Moolenbroek static int
bye(int argc,char * argv[])1410*7348b5c5SDavid van Moolenbroek bye(int argc, char *argv[])
1411*7348b5c5SDavid van Moolenbroek {
1412*7348b5c5SDavid van Moolenbroek extern int resettermname;
1413*7348b5c5SDavid van Moolenbroek
1414*7348b5c5SDavid van Moolenbroek if (connected) {
1415*7348b5c5SDavid van Moolenbroek (void) shutdown(net, 2);
1416*7348b5c5SDavid van Moolenbroek printf("Connection closed.\n");
1417*7348b5c5SDavid van Moolenbroek (void) NetClose(net);
1418*7348b5c5SDavid van Moolenbroek connected = 0;
1419*7348b5c5SDavid van Moolenbroek resettermname = 1;
1420*7348b5c5SDavid van Moolenbroek #if defined(AUTHENTICATION) || defined(ENCRYPTION)
1421*7348b5c5SDavid van Moolenbroek auth_encrypt_connect(connected);
1422*7348b5c5SDavid van Moolenbroek #endif /* defined(AUTHENTICATION) */
1423*7348b5c5SDavid van Moolenbroek /* reset options */
1424*7348b5c5SDavid van Moolenbroek tninit();
1425*7348b5c5SDavid van Moolenbroek #ifdef TN3270
1426*7348b5c5SDavid van Moolenbroek SetIn3270(); /* Get out of 3270 mode */
1427*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
1428*7348b5c5SDavid van Moolenbroek }
1429*7348b5c5SDavid van Moolenbroek if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) {
1430*7348b5c5SDavid van Moolenbroek longjmp(toplevel, 1);
1431*7348b5c5SDavid van Moolenbroek /* NOTREACHED */
1432*7348b5c5SDavid van Moolenbroek }
1433*7348b5c5SDavid van Moolenbroek return 1; /* Keep lint, etc., happy */
1434*7348b5c5SDavid van Moolenbroek }
1435*7348b5c5SDavid van Moolenbroek
1436*7348b5c5SDavid van Moolenbroek /*VARARGS*/
1437*7348b5c5SDavid van Moolenbroek int
quit(int argc,char * argv[])1438*7348b5c5SDavid van Moolenbroek quit(int argc, char *argv[])
1439*7348b5c5SDavid van Moolenbroek {
1440*7348b5c5SDavid van Moolenbroek (void) call(bye, "bye", "fromquit", 0);
1441*7348b5c5SDavid van Moolenbroek Exit(0);
1442*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
1443*7348b5c5SDavid van Moolenbroek }
1444*7348b5c5SDavid van Moolenbroek
1445*7348b5c5SDavid van Moolenbroek /*VARARGS*/
1446*7348b5c5SDavid van Moolenbroek int
logout(int argc,char * argv[])1447*7348b5c5SDavid van Moolenbroek logout(int argc, char *argv[])
1448*7348b5c5SDavid van Moolenbroek {
1449*7348b5c5SDavid van Moolenbroek send_do(TELOPT_LOGOUT, 1);
1450*7348b5c5SDavid van Moolenbroek (void) netflush();
1451*7348b5c5SDavid van Moolenbroek return 1;
1452*7348b5c5SDavid van Moolenbroek }
1453*7348b5c5SDavid van Moolenbroek
1454*7348b5c5SDavid van Moolenbroek
1455*7348b5c5SDavid van Moolenbroek /*
1456*7348b5c5SDavid van Moolenbroek * The SLC command.
1457*7348b5c5SDavid van Moolenbroek */
1458*7348b5c5SDavid van Moolenbroek
1459*7348b5c5SDavid van Moolenbroek struct slclist {
1460*7348b5c5SDavid van Moolenbroek const char *name;
1461*7348b5c5SDavid van Moolenbroek const char *help;
1462*7348b5c5SDavid van Moolenbroek void (*handler)(int);
1463*7348b5c5SDavid van Moolenbroek int arg;
1464*7348b5c5SDavid van Moolenbroek };
1465*7348b5c5SDavid van Moolenbroek
1466*7348b5c5SDavid van Moolenbroek struct slclist SlcList[] = {
1467*7348b5c5SDavid van Moolenbroek { "export", "Use local special character definitions",
1468*7348b5c5SDavid van Moolenbroek slc_mode_export, 0 },
1469*7348b5c5SDavid van Moolenbroek { "import", "Use remote special character definitions",
1470*7348b5c5SDavid van Moolenbroek slc_mode_import, 1 },
1471*7348b5c5SDavid van Moolenbroek { "check", "Verify remote special character definitions",
1472*7348b5c5SDavid van Moolenbroek slc_mode_import, 0 },
1473*7348b5c5SDavid van Moolenbroek { "help", 0, slc_help, 0 },
1474*7348b5c5SDavid van Moolenbroek { "?", "Print help information", slc_help, 0 },
1475*7348b5c5SDavid van Moolenbroek { .name = 0 },
1476*7348b5c5SDavid van Moolenbroek };
1477*7348b5c5SDavid van Moolenbroek
1478*7348b5c5SDavid van Moolenbroek static void
slc_help(int n)1479*7348b5c5SDavid van Moolenbroek slc_help(int n)
1480*7348b5c5SDavid van Moolenbroek {
1481*7348b5c5SDavid van Moolenbroek struct slclist *c;
1482*7348b5c5SDavid van Moolenbroek
1483*7348b5c5SDavid van Moolenbroek for (c = SlcList; c->name; c++) {
1484*7348b5c5SDavid van Moolenbroek if (c->help) {
1485*7348b5c5SDavid van Moolenbroek if (*c->help)
1486*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", c->name, c->help);
1487*7348b5c5SDavid van Moolenbroek else
1488*7348b5c5SDavid van Moolenbroek printf("\n");
1489*7348b5c5SDavid van Moolenbroek }
1490*7348b5c5SDavid van Moolenbroek }
1491*7348b5c5SDavid van Moolenbroek }
1492*7348b5c5SDavid van Moolenbroek
1493*7348b5c5SDavid van Moolenbroek static struct slclist *
getslc(char * name)1494*7348b5c5SDavid van Moolenbroek getslc(char *name)
1495*7348b5c5SDavid van Moolenbroek {
1496*7348b5c5SDavid van Moolenbroek return (struct slclist *)
1497*7348b5c5SDavid van Moolenbroek genget(name, (char **) SlcList, sizeof(struct slclist));
1498*7348b5c5SDavid van Moolenbroek }
1499*7348b5c5SDavid van Moolenbroek
1500*7348b5c5SDavid van Moolenbroek static int
slccmd(int argc,char * argv[])1501*7348b5c5SDavid van Moolenbroek slccmd(int argc, char *argv[])
1502*7348b5c5SDavid van Moolenbroek {
1503*7348b5c5SDavid van Moolenbroek struct slclist *c;
1504*7348b5c5SDavid van Moolenbroek
1505*7348b5c5SDavid van Moolenbroek if (argc != 2) {
1506*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1507*7348b5c5SDavid van Moolenbroek "Need an argument to 'slc' command. 'slc ?' for help.\n");
1508*7348b5c5SDavid van Moolenbroek return 0;
1509*7348b5c5SDavid van Moolenbroek }
1510*7348b5c5SDavid van Moolenbroek c = getslc(argv[1]);
1511*7348b5c5SDavid van Moolenbroek if (c == 0) {
1512*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n",
1513*7348b5c5SDavid van Moolenbroek argv[1]);
1514*7348b5c5SDavid van Moolenbroek return 0;
1515*7348b5c5SDavid van Moolenbroek }
1516*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
1517*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n",
1518*7348b5c5SDavid van Moolenbroek argv[1]);
1519*7348b5c5SDavid van Moolenbroek return 0;
1520*7348b5c5SDavid van Moolenbroek }
1521*7348b5c5SDavid van Moolenbroek (*c->handler)(c->arg);
1522*7348b5c5SDavid van Moolenbroek slcstate();
1523*7348b5c5SDavid van Moolenbroek return 1;
1524*7348b5c5SDavid van Moolenbroek }
1525*7348b5c5SDavid van Moolenbroek
1526*7348b5c5SDavid van Moolenbroek /*
1527*7348b5c5SDavid van Moolenbroek * The ENVIRON command.
1528*7348b5c5SDavid van Moolenbroek */
1529*7348b5c5SDavid van Moolenbroek
1530*7348b5c5SDavid van Moolenbroek struct envlist {
1531*7348b5c5SDavid van Moolenbroek const char *name;
1532*7348b5c5SDavid van Moolenbroek const char *help;
1533*7348b5c5SDavid van Moolenbroek struct env_lst *(*handler)(const unsigned char *, unsigned char *);
1534*7348b5c5SDavid van Moolenbroek int narg;
1535*7348b5c5SDavid van Moolenbroek };
1536*7348b5c5SDavid van Moolenbroek
1537*7348b5c5SDavid van Moolenbroek struct envlist EnvList[] = {
1538*7348b5c5SDavid van Moolenbroek { "define", "Define an environment variable",
1539*7348b5c5SDavid van Moolenbroek env_define, 2 },
1540*7348b5c5SDavid van Moolenbroek { "undefine", "Undefine an environment variable",
1541*7348b5c5SDavid van Moolenbroek env_undefine, 1 },
1542*7348b5c5SDavid van Moolenbroek { "export", "Mark an environment variable for automatic export",
1543*7348b5c5SDavid van Moolenbroek env_export, 1 },
1544*7348b5c5SDavid van Moolenbroek { "unexport", "Don't mark an environment variable for automatic export",
1545*7348b5c5SDavid van Moolenbroek env_unexport, 1 },
1546*7348b5c5SDavid van Moolenbroek { "send", "Send an environment variable", env_send, 1 },
1547*7348b5c5SDavid van Moolenbroek { "list", "List the current environment variables",
1548*7348b5c5SDavid van Moolenbroek env_list, 0 },
1549*7348b5c5SDavid van Moolenbroek #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1550*7348b5c5SDavid van Moolenbroek { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)",
1551*7348b5c5SDavid van Moolenbroek env_varval, 1 },
1552*7348b5c5SDavid van Moolenbroek #endif
1553*7348b5c5SDavid van Moolenbroek { "help", 0, env_help, 0 },
1554*7348b5c5SDavid van Moolenbroek { "?", "Print help information", env_help, 0 },
1555*7348b5c5SDavid van Moolenbroek { .name = 0 },
1556*7348b5c5SDavid van Moolenbroek };
1557*7348b5c5SDavid van Moolenbroek
1558*7348b5c5SDavid van Moolenbroek static struct env_lst *
env_help(const unsigned char * us1,unsigned char * us2)1559*7348b5c5SDavid van Moolenbroek env_help(const unsigned char *us1, unsigned char *us2)
1560*7348b5c5SDavid van Moolenbroek {
1561*7348b5c5SDavid van Moolenbroek struct envlist *c;
1562*7348b5c5SDavid van Moolenbroek
1563*7348b5c5SDavid van Moolenbroek for (c = EnvList; c->name; c++) {
1564*7348b5c5SDavid van Moolenbroek if (c->help) {
1565*7348b5c5SDavid van Moolenbroek if (*c->help)
1566*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", c->name, c->help);
1567*7348b5c5SDavid van Moolenbroek else
1568*7348b5c5SDavid van Moolenbroek printf("\n");
1569*7348b5c5SDavid van Moolenbroek }
1570*7348b5c5SDavid van Moolenbroek }
1571*7348b5c5SDavid van Moolenbroek return NULL;
1572*7348b5c5SDavid van Moolenbroek }
1573*7348b5c5SDavid van Moolenbroek
1574*7348b5c5SDavid van Moolenbroek static struct envlist *
getenvcmd(char * name)1575*7348b5c5SDavid van Moolenbroek getenvcmd(char *name)
1576*7348b5c5SDavid van Moolenbroek {
1577*7348b5c5SDavid van Moolenbroek return (struct envlist *)
1578*7348b5c5SDavid van Moolenbroek genget(name, (char **) EnvList, sizeof(struct envlist));
1579*7348b5c5SDavid van Moolenbroek }
1580*7348b5c5SDavid van Moolenbroek
1581*7348b5c5SDavid van Moolenbroek int
env_cmd(int argc,char * argv[])1582*7348b5c5SDavid van Moolenbroek env_cmd(int argc, char *argv[])
1583*7348b5c5SDavid van Moolenbroek {
1584*7348b5c5SDavid van Moolenbroek struct envlist *c;
1585*7348b5c5SDavid van Moolenbroek
1586*7348b5c5SDavid van Moolenbroek if (argc < 2) {
1587*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1588*7348b5c5SDavid van Moolenbroek "Need an argument to 'environ' command. 'environ ?' for help.\n");
1589*7348b5c5SDavid van Moolenbroek return 0;
1590*7348b5c5SDavid van Moolenbroek }
1591*7348b5c5SDavid van Moolenbroek c = getenvcmd(argv[1]);
1592*7348b5c5SDavid van Moolenbroek if (c == 0) {
1593*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n",
1594*7348b5c5SDavid van Moolenbroek argv[1]);
1595*7348b5c5SDavid van Moolenbroek return 0;
1596*7348b5c5SDavid van Moolenbroek }
1597*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
1598*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n",
1599*7348b5c5SDavid van Moolenbroek argv[1]);
1600*7348b5c5SDavid van Moolenbroek return 0;
1601*7348b5c5SDavid van Moolenbroek }
1602*7348b5c5SDavid van Moolenbroek if (c->narg + 2 != argc) {
1603*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1604*7348b5c5SDavid van Moolenbroek "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n",
1605*7348b5c5SDavid van Moolenbroek c->narg < argc + 2 ? "only " : "",
1606*7348b5c5SDavid van Moolenbroek c->narg, c->narg == 1 ? "" : "s", c->name);
1607*7348b5c5SDavid van Moolenbroek return 0;
1608*7348b5c5SDavid van Moolenbroek }
1609*7348b5c5SDavid van Moolenbroek (*c->handler)(argv[2], argv[3]);
1610*7348b5c5SDavid van Moolenbroek return 1;
1611*7348b5c5SDavid van Moolenbroek }
1612*7348b5c5SDavid van Moolenbroek
1613*7348b5c5SDavid van Moolenbroek struct env_lst {
1614*7348b5c5SDavid van Moolenbroek struct env_lst *next; /* pointer to next structure */
1615*7348b5c5SDavid van Moolenbroek struct env_lst *prev; /* pointer to previous structure */
1616*7348b5c5SDavid van Moolenbroek unsigned char *var; /* pointer to variable name */
1617*7348b5c5SDavid van Moolenbroek unsigned char *value; /* pointer to variable value */
1618*7348b5c5SDavid van Moolenbroek int export; /* 1 -> export with default list of variables */
1619*7348b5c5SDavid van Moolenbroek int welldefined; /* A well defined variable */
1620*7348b5c5SDavid van Moolenbroek };
1621*7348b5c5SDavid van Moolenbroek
1622*7348b5c5SDavid van Moolenbroek struct env_lst envlisthead;
1623*7348b5c5SDavid van Moolenbroek
1624*7348b5c5SDavid van Moolenbroek struct env_lst *
env_find(const unsigned char * var)1625*7348b5c5SDavid van Moolenbroek env_find(const unsigned char *var)
1626*7348b5c5SDavid van Moolenbroek {
1627*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1628*7348b5c5SDavid van Moolenbroek
1629*7348b5c5SDavid van Moolenbroek for (ep = envlisthead.next; ep; ep = ep->next) {
1630*7348b5c5SDavid van Moolenbroek if (strcmp((const char *)ep->var, (const char *)var) == 0)
1631*7348b5c5SDavid van Moolenbroek return(ep);
1632*7348b5c5SDavid van Moolenbroek }
1633*7348b5c5SDavid van Moolenbroek return(NULL);
1634*7348b5c5SDavid van Moolenbroek }
1635*7348b5c5SDavid van Moolenbroek
1636*7348b5c5SDavid van Moolenbroek void
env_init(void)1637*7348b5c5SDavid van Moolenbroek env_init(void)
1638*7348b5c5SDavid van Moolenbroek {
1639*7348b5c5SDavid van Moolenbroek extern char **environ;
1640*7348b5c5SDavid van Moolenbroek char **epp, *cp;
1641*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1642*7348b5c5SDavid van Moolenbroek
1643*7348b5c5SDavid van Moolenbroek for (epp = environ; *epp; epp++) {
1644*7348b5c5SDavid van Moolenbroek if ((cp = strchr(*epp, '=')) != NULL) {
1645*7348b5c5SDavid van Moolenbroek *cp = '\0';
1646*7348b5c5SDavid van Moolenbroek ep = env_define((unsigned char *)*epp,
1647*7348b5c5SDavid van Moolenbroek (unsigned char *)cp+1);
1648*7348b5c5SDavid van Moolenbroek ep->export = 0;
1649*7348b5c5SDavid van Moolenbroek *cp = '=';
1650*7348b5c5SDavid van Moolenbroek }
1651*7348b5c5SDavid van Moolenbroek }
1652*7348b5c5SDavid van Moolenbroek /*
1653*7348b5c5SDavid van Moolenbroek * Special case for DISPLAY variable. If it is ":0.0" or
1654*7348b5c5SDavid van Moolenbroek * "unix:0.0", we have to get rid of "unix" and insert our
1655*7348b5c5SDavid van Moolenbroek * hostname.
1656*7348b5c5SDavid van Moolenbroek */
1657*7348b5c5SDavid van Moolenbroek if ((ep = env_find("DISPLAY"))
1658*7348b5c5SDavid van Moolenbroek && ((*ep->value == ':')
1659*7348b5c5SDavid van Moolenbroek || (strncmp((char *)ep->value, "unix:", 5) == 0))) {
1660*7348b5c5SDavid van Moolenbroek char hbuf[MAXHOSTNAMELEN + 1];
1661*7348b5c5SDavid van Moolenbroek char *cp2 = strchr((char *)ep->value, ':');
1662*7348b5c5SDavid van Moolenbroek
1663*7348b5c5SDavid van Moolenbroek gethostname(hbuf, sizeof hbuf);
1664*7348b5c5SDavid van Moolenbroek hbuf[sizeof(hbuf) - 1] = '\0';
1665*7348b5c5SDavid van Moolenbroek cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1);
1666*7348b5c5SDavid van Moolenbroek sprintf((char *)cp, "%s%s", hbuf, cp2);
1667*7348b5c5SDavid van Moolenbroek free(ep->value);
1668*7348b5c5SDavid van Moolenbroek ep->value = (unsigned char *)cp;
1669*7348b5c5SDavid van Moolenbroek }
1670*7348b5c5SDavid van Moolenbroek /*
1671*7348b5c5SDavid van Moolenbroek * If USER is not defined, but LOGNAME is, then add
1672*7348b5c5SDavid van Moolenbroek * USER with the value from LOGNAME. By default, we
1673*7348b5c5SDavid van Moolenbroek * don't export the USER variable.
1674*7348b5c5SDavid van Moolenbroek */
1675*7348b5c5SDavid van Moolenbroek if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) {
1676*7348b5c5SDavid van Moolenbroek env_define((const unsigned char *)"USER", ep->value);
1677*7348b5c5SDavid van Moolenbroek env_unexport((const unsigned char *)"USER", NULL);
1678*7348b5c5SDavid van Moolenbroek }
1679*7348b5c5SDavid van Moolenbroek env_export((const unsigned char *)"DISPLAY", NULL);
1680*7348b5c5SDavid van Moolenbroek env_export((const unsigned char *)"PRINTER", NULL);
1681*7348b5c5SDavid van Moolenbroek }
1682*7348b5c5SDavid van Moolenbroek
1683*7348b5c5SDavid van Moolenbroek struct env_lst *
env_define(const unsigned char * var,unsigned char * value)1684*7348b5c5SDavid van Moolenbroek env_define(const unsigned char *var, unsigned char *value)
1685*7348b5c5SDavid van Moolenbroek {
1686*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1687*7348b5c5SDavid van Moolenbroek
1688*7348b5c5SDavid van Moolenbroek if ((ep = env_find(var)) != NULL) {
1689*7348b5c5SDavid van Moolenbroek if (ep->var)
1690*7348b5c5SDavid van Moolenbroek free(ep->var);
1691*7348b5c5SDavid van Moolenbroek if (ep->value)
1692*7348b5c5SDavid van Moolenbroek free(ep->value);
1693*7348b5c5SDavid van Moolenbroek } else {
1694*7348b5c5SDavid van Moolenbroek ep = (struct env_lst *)malloc(sizeof(struct env_lst));
1695*7348b5c5SDavid van Moolenbroek ep->next = envlisthead.next;
1696*7348b5c5SDavid van Moolenbroek envlisthead.next = ep;
1697*7348b5c5SDavid van Moolenbroek ep->prev = &envlisthead;
1698*7348b5c5SDavid van Moolenbroek if (ep->next)
1699*7348b5c5SDavid van Moolenbroek ep->next->prev = ep;
1700*7348b5c5SDavid van Moolenbroek }
1701*7348b5c5SDavid van Moolenbroek ep->welldefined = opt_welldefined(var);
1702*7348b5c5SDavid van Moolenbroek ep->export = 1;
1703*7348b5c5SDavid van Moolenbroek ep->var = (unsigned char *)strdup((const char *)var);
1704*7348b5c5SDavid van Moolenbroek ep->value = (unsigned char *)strdup((const char *)value);
1705*7348b5c5SDavid van Moolenbroek return(ep);
1706*7348b5c5SDavid van Moolenbroek }
1707*7348b5c5SDavid van Moolenbroek
1708*7348b5c5SDavid van Moolenbroek struct env_lst *
env_undefine(const unsigned char * var,unsigned char * d)1709*7348b5c5SDavid van Moolenbroek env_undefine(const unsigned char *var, unsigned char *d)
1710*7348b5c5SDavid van Moolenbroek {
1711*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1712*7348b5c5SDavid van Moolenbroek
1713*7348b5c5SDavid van Moolenbroek if ((ep = env_find(var)) != NULL) {
1714*7348b5c5SDavid van Moolenbroek ep->prev->next = ep->next;
1715*7348b5c5SDavid van Moolenbroek if (ep->next)
1716*7348b5c5SDavid van Moolenbroek ep->next->prev = ep->prev;
1717*7348b5c5SDavid van Moolenbroek if (ep->var)
1718*7348b5c5SDavid van Moolenbroek free(ep->var);
1719*7348b5c5SDavid van Moolenbroek if (ep->value)
1720*7348b5c5SDavid van Moolenbroek free(ep->value);
1721*7348b5c5SDavid van Moolenbroek free(ep);
1722*7348b5c5SDavid van Moolenbroek }
1723*7348b5c5SDavid van Moolenbroek return NULL;
1724*7348b5c5SDavid van Moolenbroek }
1725*7348b5c5SDavid van Moolenbroek
1726*7348b5c5SDavid van Moolenbroek struct env_lst *
env_export(const unsigned char * var,unsigned char * d)1727*7348b5c5SDavid van Moolenbroek env_export(const unsigned char *var, unsigned char *d)
1728*7348b5c5SDavid van Moolenbroek {
1729*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1730*7348b5c5SDavid van Moolenbroek
1731*7348b5c5SDavid van Moolenbroek if ((ep = env_find(var)) != NULL)
1732*7348b5c5SDavid van Moolenbroek ep->export = 1;
1733*7348b5c5SDavid van Moolenbroek return NULL;
1734*7348b5c5SDavid van Moolenbroek }
1735*7348b5c5SDavid van Moolenbroek
1736*7348b5c5SDavid van Moolenbroek struct env_lst *
env_unexport(const unsigned char * var,unsigned char * d)1737*7348b5c5SDavid van Moolenbroek env_unexport(const unsigned char *var, unsigned char *d)
1738*7348b5c5SDavid van Moolenbroek {
1739*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1740*7348b5c5SDavid van Moolenbroek
1741*7348b5c5SDavid van Moolenbroek if ((ep = env_find(var)) != NULL)
1742*7348b5c5SDavid van Moolenbroek ep->export = 0;
1743*7348b5c5SDavid van Moolenbroek return NULL;
1744*7348b5c5SDavid van Moolenbroek }
1745*7348b5c5SDavid van Moolenbroek
1746*7348b5c5SDavid van Moolenbroek struct env_lst *
env_send(const unsigned char * var,unsigned char * d)1747*7348b5c5SDavid van Moolenbroek env_send(const unsigned char *var, unsigned char *d)
1748*7348b5c5SDavid van Moolenbroek {
1749*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1750*7348b5c5SDavid van Moolenbroek
1751*7348b5c5SDavid van Moolenbroek if (my_state_is_wont(TELOPT_NEW_ENVIRON)
1752*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
1753*7348b5c5SDavid van Moolenbroek && my_state_is_wont(TELOPT_OLD_ENVIRON)
1754*7348b5c5SDavid van Moolenbroek #endif
1755*7348b5c5SDavid van Moolenbroek ) {
1756*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1757*7348b5c5SDavid van Moolenbroek "Cannot send '%s': Telnet ENVIRON option not enabled\n",
1758*7348b5c5SDavid van Moolenbroek var);
1759*7348b5c5SDavid van Moolenbroek return NULL;
1760*7348b5c5SDavid van Moolenbroek }
1761*7348b5c5SDavid van Moolenbroek ep = env_find(var);
1762*7348b5c5SDavid van Moolenbroek if (ep == 0) {
1763*7348b5c5SDavid van Moolenbroek fprintf(stderr, "Cannot send '%s': variable not defined\n",
1764*7348b5c5SDavid van Moolenbroek var);
1765*7348b5c5SDavid van Moolenbroek return NULL;
1766*7348b5c5SDavid van Moolenbroek }
1767*7348b5c5SDavid van Moolenbroek env_opt_start_info();
1768*7348b5c5SDavid van Moolenbroek env_opt_add(ep->var);
1769*7348b5c5SDavid van Moolenbroek env_opt_end(0);
1770*7348b5c5SDavid van Moolenbroek return NULL;
1771*7348b5c5SDavid van Moolenbroek }
1772*7348b5c5SDavid van Moolenbroek
1773*7348b5c5SDavid van Moolenbroek struct env_lst *
env_list(const unsigned char * d1,unsigned char * d2)1774*7348b5c5SDavid van Moolenbroek env_list(const unsigned char *d1, unsigned char *d2)
1775*7348b5c5SDavid van Moolenbroek {
1776*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1777*7348b5c5SDavid van Moolenbroek
1778*7348b5c5SDavid van Moolenbroek for (ep = envlisthead.next; ep; ep = ep->next) {
1779*7348b5c5SDavid van Moolenbroek printf("%c %-20s %s\n", ep->export ? '*' : ' ',
1780*7348b5c5SDavid van Moolenbroek ep->var, ep->value);
1781*7348b5c5SDavid van Moolenbroek }
1782*7348b5c5SDavid van Moolenbroek return NULL;
1783*7348b5c5SDavid van Moolenbroek }
1784*7348b5c5SDavid van Moolenbroek
1785*7348b5c5SDavid van Moolenbroek unsigned char *
env_default(int init,int welldefined)1786*7348b5c5SDavid van Moolenbroek env_default(int init, int welldefined)
1787*7348b5c5SDavid van Moolenbroek {
1788*7348b5c5SDavid van Moolenbroek static struct env_lst *nep = NULL;
1789*7348b5c5SDavid van Moolenbroek
1790*7348b5c5SDavid van Moolenbroek if (init) {
1791*7348b5c5SDavid van Moolenbroek nep = &envlisthead;
1792*7348b5c5SDavid van Moolenbroek return NULL;
1793*7348b5c5SDavid van Moolenbroek }
1794*7348b5c5SDavid van Moolenbroek if (nep) {
1795*7348b5c5SDavid van Moolenbroek while ((nep = nep->next) != NULL) {
1796*7348b5c5SDavid van Moolenbroek if (nep->export && (nep->welldefined == welldefined))
1797*7348b5c5SDavid van Moolenbroek return(nep->var);
1798*7348b5c5SDavid van Moolenbroek }
1799*7348b5c5SDavid van Moolenbroek }
1800*7348b5c5SDavid van Moolenbroek return(NULL);
1801*7348b5c5SDavid van Moolenbroek }
1802*7348b5c5SDavid van Moolenbroek
1803*7348b5c5SDavid van Moolenbroek unsigned char *
env_getvalue(const unsigned char * var)1804*7348b5c5SDavid van Moolenbroek env_getvalue(const unsigned char *var)
1805*7348b5c5SDavid van Moolenbroek {
1806*7348b5c5SDavid van Moolenbroek struct env_lst *ep;
1807*7348b5c5SDavid van Moolenbroek
1808*7348b5c5SDavid van Moolenbroek if ((ep = env_find(var)) != NULL)
1809*7348b5c5SDavid van Moolenbroek return(ep->value);
1810*7348b5c5SDavid van Moolenbroek return(NULL);
1811*7348b5c5SDavid van Moolenbroek }
1812*7348b5c5SDavid van Moolenbroek
1813*7348b5c5SDavid van Moolenbroek #if defined(OLD_ENVIRON) && defined(ENV_HACK)
1814*7348b5c5SDavid van Moolenbroek void
env_varval(const unsigned char * what)1815*7348b5c5SDavid van Moolenbroek env_varval(const unsigned char *what)
1816*7348b5c5SDavid van Moolenbroek {
1817*7348b5c5SDavid van Moolenbroek extern int old_env_var, old_env_value, env_auto;
1818*7348b5c5SDavid van Moolenbroek int len = strlen((char *)what);
1819*7348b5c5SDavid van Moolenbroek
1820*7348b5c5SDavid van Moolenbroek if (len == 0)
1821*7348b5c5SDavid van Moolenbroek goto unknown;
1822*7348b5c5SDavid van Moolenbroek
1823*7348b5c5SDavid van Moolenbroek if (strncasecmp((char *)what, "status", len) == 0) {
1824*7348b5c5SDavid van Moolenbroek if (env_auto)
1825*7348b5c5SDavid van Moolenbroek printf("%s%s", "VAR and VALUE are/will be ",
1826*7348b5c5SDavid van Moolenbroek "determined automatically\n");
1827*7348b5c5SDavid van Moolenbroek if (old_env_var == OLD_ENV_VAR)
1828*7348b5c5SDavid van Moolenbroek printf("VAR and VALUE set to correct definitions\n");
1829*7348b5c5SDavid van Moolenbroek else
1830*7348b5c5SDavid van Moolenbroek printf("VAR and VALUE definitions are reversed\n");
1831*7348b5c5SDavid van Moolenbroek } else if (strncasecmp((char *)what, "auto", len) == 0) {
1832*7348b5c5SDavid van Moolenbroek env_auto = 1;
1833*7348b5c5SDavid van Moolenbroek old_env_var = OLD_ENV_VALUE;
1834*7348b5c5SDavid van Moolenbroek old_env_value = OLD_ENV_VAR;
1835*7348b5c5SDavid van Moolenbroek } else if (strncasecmp((char *)what, "right", len) == 0) {
1836*7348b5c5SDavid van Moolenbroek env_auto = 0;
1837*7348b5c5SDavid van Moolenbroek old_env_var = OLD_ENV_VAR;
1838*7348b5c5SDavid van Moolenbroek old_env_value = OLD_ENV_VALUE;
1839*7348b5c5SDavid van Moolenbroek } else if (strncasecmp((char *)what, "wrong", len) == 0) {
1840*7348b5c5SDavid van Moolenbroek env_auto = 0;
1841*7348b5c5SDavid van Moolenbroek old_env_var = OLD_ENV_VALUE;
1842*7348b5c5SDavid van Moolenbroek old_env_value = OLD_ENV_VAR;
1843*7348b5c5SDavid van Moolenbroek } else {
1844*7348b5c5SDavid van Moolenbroek unknown:
1845*7348b5c5SDavid van Moolenbroek printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n");
1846*7348b5c5SDavid van Moolenbroek }
1847*7348b5c5SDavid van Moolenbroek }
1848*7348b5c5SDavid van Moolenbroek #endif
1849*7348b5c5SDavid van Moolenbroek
1850*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
1851*7348b5c5SDavid van Moolenbroek /*
1852*7348b5c5SDavid van Moolenbroek * The AUTHENTICATE command.
1853*7348b5c5SDavid van Moolenbroek */
1854*7348b5c5SDavid van Moolenbroek
1855*7348b5c5SDavid van Moolenbroek struct authlist {
1856*7348b5c5SDavid van Moolenbroek const char *name;
1857*7348b5c5SDavid van Moolenbroek const char *help;
1858*7348b5c5SDavid van Moolenbroek int (*handler)(char *);
1859*7348b5c5SDavid van Moolenbroek int narg;
1860*7348b5c5SDavid van Moolenbroek };
1861*7348b5c5SDavid van Moolenbroek
1862*7348b5c5SDavid van Moolenbroek struct authlist AuthList[] = {
1863*7348b5c5SDavid van Moolenbroek { "status", "Display current status of authentication information",
1864*7348b5c5SDavid van Moolenbroek auth_status, 0 },
1865*7348b5c5SDavid van Moolenbroek { "disable", "Disable an authentication type ('auth disable ?' for more)",
1866*7348b5c5SDavid van Moolenbroek auth_disable, 1 },
1867*7348b5c5SDavid van Moolenbroek { "enable", "Enable an authentication type ('auth enable ?' for more)",
1868*7348b5c5SDavid van Moolenbroek auth_enable, 1 },
1869*7348b5c5SDavid van Moolenbroek { "help", 0, auth_help, 0 },
1870*7348b5c5SDavid van Moolenbroek { "?", "Print help information", auth_help, 0 },
1871*7348b5c5SDavid van Moolenbroek { .name = 0 },
1872*7348b5c5SDavid van Moolenbroek };
1873*7348b5c5SDavid van Moolenbroek
1874*7348b5c5SDavid van Moolenbroek static int
auth_help(char * s)1875*7348b5c5SDavid van Moolenbroek auth_help(char *s)
1876*7348b5c5SDavid van Moolenbroek {
1877*7348b5c5SDavid van Moolenbroek struct authlist *c;
1878*7348b5c5SDavid van Moolenbroek
1879*7348b5c5SDavid van Moolenbroek for (c = AuthList; c->name; c++) {
1880*7348b5c5SDavid van Moolenbroek if (c->help) {
1881*7348b5c5SDavid van Moolenbroek if (*c->help)
1882*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", c->name, c->help);
1883*7348b5c5SDavid van Moolenbroek else
1884*7348b5c5SDavid van Moolenbroek printf("\n");
1885*7348b5c5SDavid van Moolenbroek }
1886*7348b5c5SDavid van Moolenbroek }
1887*7348b5c5SDavid van Moolenbroek return 0;
1888*7348b5c5SDavid van Moolenbroek }
1889*7348b5c5SDavid van Moolenbroek
1890*7348b5c5SDavid van Moolenbroek int
auth_cmd(int argc,char * argv[])1891*7348b5c5SDavid van Moolenbroek auth_cmd(int argc, char *argv[])
1892*7348b5c5SDavid van Moolenbroek {
1893*7348b5c5SDavid van Moolenbroek struct authlist *c;
1894*7348b5c5SDavid van Moolenbroek
1895*7348b5c5SDavid van Moolenbroek if (argc < 2) {
1896*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1897*7348b5c5SDavid van Moolenbroek "Need an argument to 'auth' command. 'auth ?' for help.\n");
1898*7348b5c5SDavid van Moolenbroek return 0;
1899*7348b5c5SDavid van Moolenbroek }
1900*7348b5c5SDavid van Moolenbroek
1901*7348b5c5SDavid van Moolenbroek c = (struct authlist *)
1902*7348b5c5SDavid van Moolenbroek genget(argv[1], (char **) AuthList, sizeof(struct authlist));
1903*7348b5c5SDavid van Moolenbroek if (c == 0) {
1904*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n",
1905*7348b5c5SDavid van Moolenbroek argv[1]);
1906*7348b5c5SDavid van Moolenbroek return 0;
1907*7348b5c5SDavid van Moolenbroek }
1908*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
1909*7348b5c5SDavid van Moolenbroek fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n",
1910*7348b5c5SDavid van Moolenbroek argv[1]);
1911*7348b5c5SDavid van Moolenbroek return 0;
1912*7348b5c5SDavid van Moolenbroek }
1913*7348b5c5SDavid van Moolenbroek if (c->narg + 2 != argc) {
1914*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1915*7348b5c5SDavid van Moolenbroek "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n",
1916*7348b5c5SDavid van Moolenbroek c->narg < argc + 2 ? "only " : "",
1917*7348b5c5SDavid van Moolenbroek c->narg, c->narg == 1 ? "" : "s", c->name);
1918*7348b5c5SDavid van Moolenbroek return 0;
1919*7348b5c5SDavid van Moolenbroek }
1920*7348b5c5SDavid van Moolenbroek return((*c->handler)(argv[2]));
1921*7348b5c5SDavid van Moolenbroek }
1922*7348b5c5SDavid van Moolenbroek #endif
1923*7348b5c5SDavid van Moolenbroek
1924*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1925*7348b5c5SDavid van Moolenbroek /*
1926*7348b5c5SDavid van Moolenbroek * The ENCRYPT command.
1927*7348b5c5SDavid van Moolenbroek */
1928*7348b5c5SDavid van Moolenbroek
1929*7348b5c5SDavid van Moolenbroek struct encryptlist {
1930*7348b5c5SDavid van Moolenbroek const char *name;
1931*7348b5c5SDavid van Moolenbroek const char *help;
1932*7348b5c5SDavid van Moolenbroek int (*handler)(char *, char *);
1933*7348b5c5SDavid van Moolenbroek int needconnect;
1934*7348b5c5SDavid van Moolenbroek int minarg;
1935*7348b5c5SDavid van Moolenbroek int maxarg;
1936*7348b5c5SDavid van Moolenbroek };
1937*7348b5c5SDavid van Moolenbroek
1938*7348b5c5SDavid van Moolenbroek static int
1939*7348b5c5SDavid van Moolenbroek EncryptHelp(char *, char *);
1940*7348b5c5SDavid van Moolenbroek typedef int (*encrypthandler)(char *, char *);
1941*7348b5c5SDavid van Moolenbroek
1942*7348b5c5SDavid van Moolenbroek struct encryptlist EncryptList[] = {
1943*7348b5c5SDavid van Moolenbroek { "enable", "Enable encryption. ('encrypt enable ?' for more)",
1944*7348b5c5SDavid van Moolenbroek EncryptEnable, 1, 1, 2 },
1945*7348b5c5SDavid van Moolenbroek { "disable", "Disable encryption. ('encrypt enable ?' for more)",
1946*7348b5c5SDavid van Moolenbroek EncryptDisable, 0, 1, 2 },
1947*7348b5c5SDavid van Moolenbroek { "type", "Set encryption type. ('encrypt type ?' for more)",
1948*7348b5c5SDavid van Moolenbroek EncryptType, 0, 1, 1 },
1949*7348b5c5SDavid van Moolenbroek { "start", "Start encryption. ('encrypt start ?' for more)",
1950*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStart, 1, 0, 1 },
1951*7348b5c5SDavid van Moolenbroek { "stop", "Stop encryption. ('encrypt stop ?' for more)",
1952*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStop, 1, 0, 1 },
1953*7348b5c5SDavid van Moolenbroek { "input", "Start encrypting the input stream",
1954*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStartInput, 1, 0, 0 },
1955*7348b5c5SDavid van Moolenbroek { "-input", "Stop encrypting the input stream",
1956*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStopInput, 1, 0, 0 },
1957*7348b5c5SDavid van Moolenbroek { "output", "Start encrypting the output stream",
1958*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStartOutput, 1, 0, 0 },
1959*7348b5c5SDavid van Moolenbroek { "-output", "Stop encrypting the output stream",
1960*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStopOutput, 1, 0, 0 },
1961*7348b5c5SDavid van Moolenbroek
1962*7348b5c5SDavid van Moolenbroek { "status", "Display current status of authentication information",
1963*7348b5c5SDavid van Moolenbroek (encrypthandler) EncryptStatus, 0, 0, 0 },
1964*7348b5c5SDavid van Moolenbroek { "help", 0, EncryptHelp, 0, 0, 0 },
1965*7348b5c5SDavid van Moolenbroek { "?", "Print help information", EncryptHelp, 0, 0, 0 },
1966*7348b5c5SDavid van Moolenbroek { .name = 0 },
1967*7348b5c5SDavid van Moolenbroek };
1968*7348b5c5SDavid van Moolenbroek
1969*7348b5c5SDavid van Moolenbroek static int
EncryptHelp(char * s1,char * s2)1970*7348b5c5SDavid van Moolenbroek EncryptHelp(char *s1, char *s2)
1971*7348b5c5SDavid van Moolenbroek {
1972*7348b5c5SDavid van Moolenbroek struct encryptlist *c;
1973*7348b5c5SDavid van Moolenbroek
1974*7348b5c5SDavid van Moolenbroek for (c = EncryptList; c->name; c++) {
1975*7348b5c5SDavid van Moolenbroek if (c->help) {
1976*7348b5c5SDavid van Moolenbroek if (*c->help)
1977*7348b5c5SDavid van Moolenbroek printf("%-15s %s\n", c->name, c->help);
1978*7348b5c5SDavid van Moolenbroek else
1979*7348b5c5SDavid van Moolenbroek printf("\n");
1980*7348b5c5SDavid van Moolenbroek }
1981*7348b5c5SDavid van Moolenbroek }
1982*7348b5c5SDavid van Moolenbroek return (0);
1983*7348b5c5SDavid van Moolenbroek }
1984*7348b5c5SDavid van Moolenbroek
1985*7348b5c5SDavid van Moolenbroek int
encrypt_cmd(int argc,char * argv[])1986*7348b5c5SDavid van Moolenbroek encrypt_cmd(int argc, char *argv[])
1987*7348b5c5SDavid van Moolenbroek {
1988*7348b5c5SDavid van Moolenbroek struct encryptlist *c;
1989*7348b5c5SDavid van Moolenbroek
1990*7348b5c5SDavid van Moolenbroek if (argc < 2) {
1991*7348b5c5SDavid van Moolenbroek fprintf(stderr,
1992*7348b5c5SDavid van Moolenbroek "Need an argument to 'encrypt' command. "
1993*7348b5c5SDavid van Moolenbroek "'encrypt ?' for help.\n");
1994*7348b5c5SDavid van Moolenbroek return (0);
1995*7348b5c5SDavid van Moolenbroek }
1996*7348b5c5SDavid van Moolenbroek
1997*7348b5c5SDavid van Moolenbroek c = (struct encryptlist *)
1998*7348b5c5SDavid van Moolenbroek genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist));
1999*7348b5c5SDavid van Moolenbroek if (c == NULL) {
2000*7348b5c5SDavid van Moolenbroek fprintf(stderr,
2001*7348b5c5SDavid van Moolenbroek "'%s': unknown argument ('encrypt ?' for help).\n",
2002*7348b5c5SDavid van Moolenbroek argv[1]);
2003*7348b5c5SDavid van Moolenbroek return (0);
2004*7348b5c5SDavid van Moolenbroek }
2005*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
2006*7348b5c5SDavid van Moolenbroek fprintf(stderr,
2007*7348b5c5SDavid van Moolenbroek "'%s': ambiguous argument ('encrypt ?' for help).\n",
2008*7348b5c5SDavid van Moolenbroek argv[1]);
2009*7348b5c5SDavid van Moolenbroek return (0);
2010*7348b5c5SDavid van Moolenbroek }
2011*7348b5c5SDavid van Moolenbroek argc -= 2;
2012*7348b5c5SDavid van Moolenbroek if (argc < c->minarg || argc > c->maxarg) {
2013*7348b5c5SDavid van Moolenbroek if (c->minarg == c->maxarg) {
2014*7348b5c5SDavid van Moolenbroek fprintf(stderr, "Need %s%d argument%s ",
2015*7348b5c5SDavid van Moolenbroek c->minarg < argc ? "only " : "", c->minarg,
2016*7348b5c5SDavid van Moolenbroek c->minarg == 1 ? "" : "s");
2017*7348b5c5SDavid van Moolenbroek } else {
2018*7348b5c5SDavid van Moolenbroek fprintf(stderr, "Need %s%d-%d arguments ",
2019*7348b5c5SDavid van Moolenbroek c->maxarg < argc ? "only " : "", c->minarg,
2020*7348b5c5SDavid van Moolenbroek c->maxarg);
2021*7348b5c5SDavid van Moolenbroek }
2022*7348b5c5SDavid van Moolenbroek fprintf(stderr,
2023*7348b5c5SDavid van Moolenbroek "to 'encrypt %s' command. 'encrypt ?' for help.\n",
2024*7348b5c5SDavid van Moolenbroek c->name);
2025*7348b5c5SDavid van Moolenbroek return (0);
2026*7348b5c5SDavid van Moolenbroek }
2027*7348b5c5SDavid van Moolenbroek if (c->needconnect && !connected) {
2028*7348b5c5SDavid van Moolenbroek if (!(argc && (isprefix(argv[2], "help") ||
2029*7348b5c5SDavid van Moolenbroek isprefix(argv[2], "?")))) {
2030*7348b5c5SDavid van Moolenbroek printf("?Need to be connected first.\n");
2031*7348b5c5SDavid van Moolenbroek return (0);
2032*7348b5c5SDavid van Moolenbroek }
2033*7348b5c5SDavid van Moolenbroek }
2034*7348b5c5SDavid van Moolenbroek return ((*c->handler)(argv[2], argv[3]));
2035*7348b5c5SDavid van Moolenbroek }
2036*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
2037*7348b5c5SDavid van Moolenbroek
2038*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2039*7348b5c5SDavid van Moolenbroek static void
filestuff(int fd)2040*7348b5c5SDavid van Moolenbroek filestuff(int fd)
2041*7348b5c5SDavid van Moolenbroek {
2042*7348b5c5SDavid van Moolenbroek int res;
2043*7348b5c5SDavid van Moolenbroek
2044*7348b5c5SDavid van Moolenbroek setconnmode(0);
2045*7348b5c5SDavid van Moolenbroek res = fcntl(fd, F_GETOWN, 0);
2046*7348b5c5SDavid van Moolenbroek setcommandmode();
2047*7348b5c5SDavid van Moolenbroek
2048*7348b5c5SDavid van Moolenbroek if (res == -1) {
2049*7348b5c5SDavid van Moolenbroek perror("fcntl");
2050*7348b5c5SDavid van Moolenbroek return;
2051*7348b5c5SDavid van Moolenbroek }
2052*7348b5c5SDavid van Moolenbroek printf("\tOwner is %d.\n", res);
2053*7348b5c5SDavid van Moolenbroek
2054*7348b5c5SDavid van Moolenbroek setconnmode(0);
2055*7348b5c5SDavid van Moolenbroek res = fcntl(fd, F_GETFL, 0);
2056*7348b5c5SDavid van Moolenbroek setcommandmode();
2057*7348b5c5SDavid van Moolenbroek
2058*7348b5c5SDavid van Moolenbroek if (res == -1) {
2059*7348b5c5SDavid van Moolenbroek perror("fcntl");
2060*7348b5c5SDavid van Moolenbroek return;
2061*7348b5c5SDavid van Moolenbroek }
2062*7348b5c5SDavid van Moolenbroek #ifdef notdef
2063*7348b5c5SDavid van Moolenbroek printf("\tFlags are 0x%x: %s\n", res, decodeflags(res));
2064*7348b5c5SDavid van Moolenbroek #endif
2065*7348b5c5SDavid van Moolenbroek }
2066*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
2067*7348b5c5SDavid van Moolenbroek
2068*7348b5c5SDavid van Moolenbroek /*
2069*7348b5c5SDavid van Moolenbroek * Print status about the connection.
2070*7348b5c5SDavid van Moolenbroek */
2071*7348b5c5SDavid van Moolenbroek /*ARGSUSED*/
2072*7348b5c5SDavid van Moolenbroek static int
status(int argc,char * argv[])2073*7348b5c5SDavid van Moolenbroek status(int argc, char *argv[])
2074*7348b5c5SDavid van Moolenbroek {
2075*7348b5c5SDavid van Moolenbroek if (connected) {
2076*7348b5c5SDavid van Moolenbroek printf("Connected to %s.\n", hostname);
2077*7348b5c5SDavid van Moolenbroek if ((argc < 2) || strcmp(argv[1], "notmuch")) {
2078*7348b5c5SDavid van Moolenbroek int mode = getconnmode();
2079*7348b5c5SDavid van Moolenbroek
2080*7348b5c5SDavid van Moolenbroek if (my_want_state_is_will(TELOPT_LINEMODE)) {
2081*7348b5c5SDavid van Moolenbroek printf("Operating with LINEMODE option\n");
2082*7348b5c5SDavid van Moolenbroek printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No");
2083*7348b5c5SDavid van Moolenbroek printf("%s catching of signals\n",
2084*7348b5c5SDavid van Moolenbroek (mode&MODE_TRAPSIG) ? "Local" : "No");
2085*7348b5c5SDavid van Moolenbroek slcstate();
2086*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
2087*7348b5c5SDavid van Moolenbroek } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) {
2088*7348b5c5SDavid van Moolenbroek printf("Operating in obsolete linemode\n");
2089*7348b5c5SDavid van Moolenbroek #endif
2090*7348b5c5SDavid van Moolenbroek } else {
2091*7348b5c5SDavid van Moolenbroek printf("Operating in single character mode\n");
2092*7348b5c5SDavid van Moolenbroek if (localchars)
2093*7348b5c5SDavid van Moolenbroek printf("Catching signals locally\n");
2094*7348b5c5SDavid van Moolenbroek }
2095*7348b5c5SDavid van Moolenbroek printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote");
2096*7348b5c5SDavid van Moolenbroek if (my_want_state_is_will(TELOPT_LFLOW))
2097*7348b5c5SDavid van Moolenbroek printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No");
2098*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
2099*7348b5c5SDavid van Moolenbroek encrypt_display();
2100*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
2101*7348b5c5SDavid van Moolenbroek }
2102*7348b5c5SDavid van Moolenbroek } else {
2103*7348b5c5SDavid van Moolenbroek printf("No connection.\n");
2104*7348b5c5SDavid van Moolenbroek }
2105*7348b5c5SDavid van Moolenbroek # ifndef TN3270
2106*7348b5c5SDavid van Moolenbroek printf("Escape character is '%s'.\n", control(escape));
2107*7348b5c5SDavid van Moolenbroek (void) fflush(stdout);
2108*7348b5c5SDavid van Moolenbroek # else /* !defined(TN3270) */
2109*7348b5c5SDavid van Moolenbroek if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) {
2110*7348b5c5SDavid van Moolenbroek printf("Escape character is '%s'.\n", control(escape));
2111*7348b5c5SDavid van Moolenbroek }
2112*7348b5c5SDavid van Moolenbroek if ((argc >= 2) && !strcmp(argv[1], "everything")) {
2113*7348b5c5SDavid van Moolenbroek printf("SIGIO received %d time%s.\n",
2114*7348b5c5SDavid van Moolenbroek sigiocount, (sigiocount == 1)? "":"s");
2115*7348b5c5SDavid van Moolenbroek if (In3270) {
2116*7348b5c5SDavid van Moolenbroek printf("Process ID %d, process group %d.\n",
2117*7348b5c5SDavid van Moolenbroek getpid(), getpgrp());
2118*7348b5c5SDavid van Moolenbroek printf("Terminal input:\n");
2119*7348b5c5SDavid van Moolenbroek filestuff(tin);
2120*7348b5c5SDavid van Moolenbroek printf("Terminal output:\n");
2121*7348b5c5SDavid van Moolenbroek filestuff(tout);
2122*7348b5c5SDavid van Moolenbroek printf("Network socket:\n");
2123*7348b5c5SDavid van Moolenbroek filestuff(net);
2124*7348b5c5SDavid van Moolenbroek }
2125*7348b5c5SDavid van Moolenbroek }
2126*7348b5c5SDavid van Moolenbroek if (In3270 && transcom) {
2127*7348b5c5SDavid van Moolenbroek printf("Transparent mode command is '%s'.\n", transcom);
2128*7348b5c5SDavid van Moolenbroek }
2129*7348b5c5SDavid van Moolenbroek (void) fflush(stdout);
2130*7348b5c5SDavid van Moolenbroek if (In3270) {
2131*7348b5c5SDavid van Moolenbroek return 0;
2132*7348b5c5SDavid van Moolenbroek }
2133*7348b5c5SDavid van Moolenbroek # endif /* defined(TN3270) */
2134*7348b5c5SDavid van Moolenbroek return 1;
2135*7348b5c5SDavid van Moolenbroek }
2136*7348b5c5SDavid van Moolenbroek
2137*7348b5c5SDavid van Moolenbroek /*
2138*7348b5c5SDavid van Moolenbroek * Function that gets called when SIGINFO is received.
2139*7348b5c5SDavid van Moolenbroek */
2140*7348b5c5SDavid van Moolenbroek int
ayt_status(void)2141*7348b5c5SDavid van Moolenbroek ayt_status(void)
2142*7348b5c5SDavid van Moolenbroek {
2143*7348b5c5SDavid van Moolenbroek return call(status, "status", "notmuch", 0);
2144*7348b5c5SDavid van Moolenbroek }
2145*7348b5c5SDavid van Moolenbroek
2146*7348b5c5SDavid van Moolenbroek static const char *
sockaddr_ntop(struct sockaddr * sa)2147*7348b5c5SDavid van Moolenbroek sockaddr_ntop(struct sockaddr *sa)
2148*7348b5c5SDavid van Moolenbroek {
2149*7348b5c5SDavid van Moolenbroek static char addrbuf[NI_MAXHOST];
2150*7348b5c5SDavid van Moolenbroek const int niflags = NI_NUMERICHOST;
2151*7348b5c5SDavid van Moolenbroek
2152*7348b5c5SDavid van Moolenbroek if (getnameinfo(sa, sa->sa_len, addrbuf, sizeof(addrbuf),
2153*7348b5c5SDavid van Moolenbroek NULL, 0, niflags) == 0)
2154*7348b5c5SDavid van Moolenbroek return addrbuf;
2155*7348b5c5SDavid van Moolenbroek else
2156*7348b5c5SDavid van Moolenbroek return NULL;
2157*7348b5c5SDavid van Moolenbroek }
2158*7348b5c5SDavid van Moolenbroek
2159*7348b5c5SDavid van Moolenbroek #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
2160*7348b5c5SDavid van Moolenbroek static int setpolicy (int, struct addrinfo *, char *);
2161*7348b5c5SDavid van Moolenbroek
2162*7348b5c5SDavid van Moolenbroek static int
setpolicy(int netw,struct addrinfo * res,char * policy)2163*7348b5c5SDavid van Moolenbroek setpolicy(int netw, struct addrinfo *res, char *policy)
2164*7348b5c5SDavid van Moolenbroek {
2165*7348b5c5SDavid van Moolenbroek char *buf;
2166*7348b5c5SDavid van Moolenbroek int level;
2167*7348b5c5SDavid van Moolenbroek int optname;
2168*7348b5c5SDavid van Moolenbroek
2169*7348b5c5SDavid van Moolenbroek if (policy == NULL)
2170*7348b5c5SDavid van Moolenbroek return 0;
2171*7348b5c5SDavid van Moolenbroek
2172*7348b5c5SDavid van Moolenbroek buf = ipsec_set_policy(policy, strlen(policy));
2173*7348b5c5SDavid van Moolenbroek if (buf == NULL) {
2174*7348b5c5SDavid van Moolenbroek printf("%s\n", ipsec_strerror());
2175*7348b5c5SDavid van Moolenbroek return -1;
2176*7348b5c5SDavid van Moolenbroek }
2177*7348b5c5SDavid van Moolenbroek level = res->ai_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6;
2178*7348b5c5SDavid van Moolenbroek optname = res->ai_family == AF_INET ? IP_IPSEC_POLICY : IPV6_IPSEC_POLICY;
2179*7348b5c5SDavid van Moolenbroek if (setsockopt(netw, level, optname, buf, ipsec_get_policylen(buf)) < 0){
2180*7348b5c5SDavid van Moolenbroek perror("setsockopt");
2181*7348b5c5SDavid van Moolenbroek return -1;
2182*7348b5c5SDavid van Moolenbroek }
2183*7348b5c5SDavid van Moolenbroek
2184*7348b5c5SDavid van Moolenbroek free(buf);
2185*7348b5c5SDavid van Moolenbroek return 0;
2186*7348b5c5SDavid van Moolenbroek }
2187*7348b5c5SDavid van Moolenbroek #endif
2188*7348b5c5SDavid van Moolenbroek
2189*7348b5c5SDavid van Moolenbroek int
tn(int argc,char * argv[])2190*7348b5c5SDavid van Moolenbroek tn(int argc, char *argv[])
2191*7348b5c5SDavid van Moolenbroek {
2192*7348b5c5SDavid van Moolenbroek struct addrinfo hints, *res, *res0;
2193*7348b5c5SDavid van Moolenbroek const char *cause = "telnet: unknown";
2194*7348b5c5SDavid van Moolenbroek int error;
2195*7348b5c5SDavid van Moolenbroek #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
2196*7348b5c5SDavid van Moolenbroek char *srp = 0;
2197*7348b5c5SDavid van Moolenbroek long srlen;
2198*7348b5c5SDavid van Moolenbroek int proto, opt;
2199*7348b5c5SDavid van Moolenbroek #endif
2200*7348b5c5SDavid van Moolenbroek char *cmd, *hostp = 0;
2201*7348b5c5SDavid van Moolenbroek const char *portp = 0;
2202*7348b5c5SDavid van Moolenbroek const char *user = 0;
2203*7348b5c5SDavid van Moolenbroek
2204*7348b5c5SDavid van Moolenbroek if (connected) {
2205*7348b5c5SDavid van Moolenbroek printf("?Already connected to %s\n", hostname);
2206*7348b5c5SDavid van Moolenbroek return 0;
2207*7348b5c5SDavid van Moolenbroek }
2208*7348b5c5SDavid van Moolenbroek if (argc < 2) {
2209*7348b5c5SDavid van Moolenbroek (void) strlcpy(line, "open ", sizeof(line));
2210*7348b5c5SDavid van Moolenbroek printf("(to) ");
2211*7348b5c5SDavid van Moolenbroek (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin);
2212*7348b5c5SDavid van Moolenbroek makeargv();
2213*7348b5c5SDavid van Moolenbroek argc = margc;
2214*7348b5c5SDavid van Moolenbroek argv = margv;
2215*7348b5c5SDavid van Moolenbroek }
2216*7348b5c5SDavid van Moolenbroek cmd = *argv;
2217*7348b5c5SDavid van Moolenbroek --argc; ++argv;
2218*7348b5c5SDavid van Moolenbroek while (argc) {
2219*7348b5c5SDavid van Moolenbroek if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?"))
2220*7348b5c5SDavid van Moolenbroek goto usage;
2221*7348b5c5SDavid van Moolenbroek if (strcmp(*argv, "-l") == 0) {
2222*7348b5c5SDavid van Moolenbroek --argc; ++argv;
2223*7348b5c5SDavid van Moolenbroek if (argc == 0)
2224*7348b5c5SDavid van Moolenbroek goto usage;
2225*7348b5c5SDavid van Moolenbroek user = *argv++;
2226*7348b5c5SDavid van Moolenbroek --argc;
2227*7348b5c5SDavid van Moolenbroek continue;
2228*7348b5c5SDavid van Moolenbroek }
2229*7348b5c5SDavid van Moolenbroek if (strcmp(*argv, "-a") == 0) {
2230*7348b5c5SDavid van Moolenbroek --argc; ++argv;
2231*7348b5c5SDavid van Moolenbroek autologin = 1;
2232*7348b5c5SDavid van Moolenbroek continue;
2233*7348b5c5SDavid van Moolenbroek }
2234*7348b5c5SDavid van Moolenbroek if (hostp == 0) {
2235*7348b5c5SDavid van Moolenbroek hostp = *argv++;
2236*7348b5c5SDavid van Moolenbroek --argc;
2237*7348b5c5SDavid van Moolenbroek continue;
2238*7348b5c5SDavid van Moolenbroek }
2239*7348b5c5SDavid van Moolenbroek if (portp == 0) {
2240*7348b5c5SDavid van Moolenbroek portp = *argv++;
2241*7348b5c5SDavid van Moolenbroek --argc;
2242*7348b5c5SDavid van Moolenbroek continue;
2243*7348b5c5SDavid van Moolenbroek }
2244*7348b5c5SDavid van Moolenbroek usage:
2245*7348b5c5SDavid van Moolenbroek printf("usage: %s [-l user] [-a] host-name [port]\n", cmd);
2246*7348b5c5SDavid van Moolenbroek return 0;
2247*7348b5c5SDavid van Moolenbroek }
2248*7348b5c5SDavid van Moolenbroek if (hostp == 0)
2249*7348b5c5SDavid van Moolenbroek goto usage;
2250*7348b5c5SDavid van Moolenbroek
2251*7348b5c5SDavid van Moolenbroek (void) strlcpy(_hostname, hostp, sizeof(_hostname));
2252*7348b5c5SDavid van Moolenbroek if (hostp[0] == '@' || hostp[0] == '!') {
2253*7348b5c5SDavid van Moolenbroek char *p;
2254*7348b5c5SDavid van Moolenbroek hostname = NULL;
2255*7348b5c5SDavid van Moolenbroek for (p = hostp + 1; *p; p++) {
2256*7348b5c5SDavid van Moolenbroek if (*p == ',' || *p == '@')
2257*7348b5c5SDavid van Moolenbroek hostname = p;
2258*7348b5c5SDavid van Moolenbroek }
2259*7348b5c5SDavid van Moolenbroek if (hostname == NULL) {
2260*7348b5c5SDavid van Moolenbroek fprintf(stderr, "%s: bad source route specification\n", hostp);
2261*7348b5c5SDavid van Moolenbroek return 0;
2262*7348b5c5SDavid van Moolenbroek }
2263*7348b5c5SDavid van Moolenbroek *hostname++ = '\0';
2264*7348b5c5SDavid van Moolenbroek } else
2265*7348b5c5SDavid van Moolenbroek hostname = hostp;
2266*7348b5c5SDavid van Moolenbroek
2267*7348b5c5SDavid van Moolenbroek if (!portp) {
2268*7348b5c5SDavid van Moolenbroek telnetport = 1;
2269*7348b5c5SDavid van Moolenbroek portp = "telnet";
2270*7348b5c5SDavid van Moolenbroek } else if (portp[0] == '-') {
2271*7348b5c5SDavid van Moolenbroek /* use telnet negotiation if port number/name preceded by minus sign */
2272*7348b5c5SDavid van Moolenbroek telnetport = 1;
2273*7348b5c5SDavid van Moolenbroek portp++;
2274*7348b5c5SDavid van Moolenbroek } else
2275*7348b5c5SDavid van Moolenbroek telnetport = 0;
2276*7348b5c5SDavid van Moolenbroek
2277*7348b5c5SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
2278*7348b5c5SDavid van Moolenbroek hints.ai_family = family;
2279*7348b5c5SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
2280*7348b5c5SDavid van Moolenbroek hints.ai_protocol = 0;
2281*7348b5c5SDavid van Moolenbroek hints.ai_flags = AI_NUMERICHOST; /* avoid forward lookup */
2282*7348b5c5SDavid van Moolenbroek error = getaddrinfo(hostname, portp, &hints, &res0);
2283*7348b5c5SDavid van Moolenbroek if (!error) {
2284*7348b5c5SDavid van Moolenbroek /* numeric */
2285*7348b5c5SDavid van Moolenbroek if (doaddrlookup &&
2286*7348b5c5SDavid van Moolenbroek getnameinfo(res0->ai_addr, res0->ai_addrlen,
2287*7348b5c5SDavid van Moolenbroek _hostname, sizeof(_hostname), NULL, 0, NI_NAMEREQD) == 0)
2288*7348b5c5SDavid van Moolenbroek ; /* okay */
2289*7348b5c5SDavid van Moolenbroek else
2290*7348b5c5SDavid van Moolenbroek strlcpy(_hostname, hostname, sizeof(_hostname));
2291*7348b5c5SDavid van Moolenbroek } else {
2292*7348b5c5SDavid van Moolenbroek /* FQDN - try again with forward DNS lookup */
2293*7348b5c5SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
2294*7348b5c5SDavid van Moolenbroek hints.ai_family = family;
2295*7348b5c5SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
2296*7348b5c5SDavid van Moolenbroek hints.ai_protocol = 0;
2297*7348b5c5SDavid van Moolenbroek hints.ai_flags = AI_CANONNAME;
2298*7348b5c5SDavid van Moolenbroek error = getaddrinfo(hostname, portp, &hints, &res0);
2299*7348b5c5SDavid van Moolenbroek if (error == EAI_SERVICE) {
2300*7348b5c5SDavid van Moolenbroek fprintf(stderr, "tcp/%s: unknown service\n", portp);
2301*7348b5c5SDavid van Moolenbroek return 0;
2302*7348b5c5SDavid van Moolenbroek } else if (error) {
2303*7348b5c5SDavid van Moolenbroek fprintf(stderr, "%s: %s\n", hostname, gai_strerror(error));
2304*7348b5c5SDavid van Moolenbroek return 0;
2305*7348b5c5SDavid van Moolenbroek }
2306*7348b5c5SDavid van Moolenbroek if (res0->ai_canonname)
2307*7348b5c5SDavid van Moolenbroek (void)strlcpy(_hostname, res0->ai_canonname, sizeof(_hostname));
2308*7348b5c5SDavid van Moolenbroek else
2309*7348b5c5SDavid van Moolenbroek (void)strlcpy(_hostname, hostname, sizeof(_hostname));
2310*7348b5c5SDavid van Moolenbroek }
2311*7348b5c5SDavid van Moolenbroek hostname = _hostname;
2312*7348b5c5SDavid van Moolenbroek
2313*7348b5c5SDavid van Moolenbroek net = -1;
2314*7348b5c5SDavid van Moolenbroek for (res = res0; res; res = res->ai_next) {
2315*7348b5c5SDavid van Moolenbroek printf("Trying %s...\n", sockaddr_ntop(res->ai_addr));
2316*7348b5c5SDavid van Moolenbroek net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
2317*7348b5c5SDavid van Moolenbroek if (net < 0) {
2318*7348b5c5SDavid van Moolenbroek cause = "telnet: socket";
2319*7348b5c5SDavid van Moolenbroek continue;
2320*7348b5c5SDavid van Moolenbroek }
2321*7348b5c5SDavid van Moolenbroek
2322*7348b5c5SDavid van Moolenbroek if (telnet_debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
2323*7348b5c5SDavid van Moolenbroek perror("setsockopt (SO_DEBUG)");
2324*7348b5c5SDavid van Moolenbroek }
2325*7348b5c5SDavid van Moolenbroek if (hostp[0] == '@' || hostp[0] == '!') {
2326*7348b5c5SDavid van Moolenbroek if ((srlen = sourceroute(res, hostp, &srp, &proto, &opt)) < 0) {
2327*7348b5c5SDavid van Moolenbroek (void) NetClose(net);
2328*7348b5c5SDavid van Moolenbroek net = -1;
2329*7348b5c5SDavid van Moolenbroek continue;
2330*7348b5c5SDavid van Moolenbroek }
2331*7348b5c5SDavid van Moolenbroek if (srp && setsockopt(net, proto, opt, srp, srlen) < 0)
2332*7348b5c5SDavid van Moolenbroek perror("setsockopt (source route)");
2333*7348b5c5SDavid van Moolenbroek }
2334*7348b5c5SDavid van Moolenbroek
2335*7348b5c5SDavid van Moolenbroek #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
2336*7348b5c5SDavid van Moolenbroek if (setpolicy(net, res, ipsec_policy_in) < 0) {
2337*7348b5c5SDavid van Moolenbroek (void) NetClose(net);
2338*7348b5c5SDavid van Moolenbroek net = -1;
2339*7348b5c5SDavid van Moolenbroek continue;
2340*7348b5c5SDavid van Moolenbroek }
2341*7348b5c5SDavid van Moolenbroek if (setpolicy(net, res, ipsec_policy_out) < 0) {
2342*7348b5c5SDavid van Moolenbroek (void) NetClose(net);
2343*7348b5c5SDavid van Moolenbroek net = -1;
2344*7348b5c5SDavid van Moolenbroek continue;
2345*7348b5c5SDavid van Moolenbroek }
2346*7348b5c5SDavid van Moolenbroek #endif
2347*7348b5c5SDavid van Moolenbroek
2348*7348b5c5SDavid van Moolenbroek if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
2349*7348b5c5SDavid van Moolenbroek if (res->ai_next) {
2350*7348b5c5SDavid van Moolenbroek int oerrno = errno;
2351*7348b5c5SDavid van Moolenbroek
2352*7348b5c5SDavid van Moolenbroek fprintf(stderr, "telnet: connect to address %s: ",
2353*7348b5c5SDavid van Moolenbroek sockaddr_ntop(res->ai_addr));
2354*7348b5c5SDavid van Moolenbroek errno = oerrno;
2355*7348b5c5SDavid van Moolenbroek perror((char *)0);
2356*7348b5c5SDavid van Moolenbroek }
2357*7348b5c5SDavid van Moolenbroek cause = "telnet: Unable to connect to remote host";
2358*7348b5c5SDavid van Moolenbroek (void) NetClose(net);
2359*7348b5c5SDavid van Moolenbroek net = -1;
2360*7348b5c5SDavid van Moolenbroek continue;
2361*7348b5c5SDavid van Moolenbroek }
2362*7348b5c5SDavid van Moolenbroek
2363*7348b5c5SDavid van Moolenbroek connected++;
2364*7348b5c5SDavid van Moolenbroek #if defined(AUTHENTICATION) || defined(ENCRYPTION)
2365*7348b5c5SDavid van Moolenbroek auth_encrypt_connect(connected);
2366*7348b5c5SDavid van Moolenbroek #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2367*7348b5c5SDavid van Moolenbroek break;
2368*7348b5c5SDavid van Moolenbroek }
2369*7348b5c5SDavid van Moolenbroek freeaddrinfo(res0);
2370*7348b5c5SDavid van Moolenbroek if (net < 0 || connected == 0) {
2371*7348b5c5SDavid van Moolenbroek perror(cause);
2372*7348b5c5SDavid van Moolenbroek return 0;
2373*7348b5c5SDavid van Moolenbroek }
2374*7348b5c5SDavid van Moolenbroek
2375*7348b5c5SDavid van Moolenbroek cmdrc(hostp, hostname);
2376*7348b5c5SDavid van Moolenbroek if (autologin && user == NULL) {
2377*7348b5c5SDavid van Moolenbroek struct passwd *pw;
2378*7348b5c5SDavid van Moolenbroek
2379*7348b5c5SDavid van Moolenbroek user = getenv("USER");
2380*7348b5c5SDavid van Moolenbroek if (user == NULL ||
2381*7348b5c5SDavid van Moolenbroek ((pw = getpwnam(user)) && pw->pw_uid != getuid())) {
2382*7348b5c5SDavid van Moolenbroek if ((pw = getpwuid(getuid())) != NULL)
2383*7348b5c5SDavid van Moolenbroek user = pw->pw_name;
2384*7348b5c5SDavid van Moolenbroek else
2385*7348b5c5SDavid van Moolenbroek user = NULL;
2386*7348b5c5SDavid van Moolenbroek }
2387*7348b5c5SDavid van Moolenbroek }
2388*7348b5c5SDavid van Moolenbroek if (user) {
2389*7348b5c5SDavid van Moolenbroek env_define((const unsigned char *)"USER", __UNCONST(user));
2390*7348b5c5SDavid van Moolenbroek env_export((const unsigned char *)"USER", NULL);
2391*7348b5c5SDavid van Moolenbroek }
2392*7348b5c5SDavid van Moolenbroek (void) call(status, "status", "notmuch", 0);
2393*7348b5c5SDavid van Moolenbroek telnet(user);
2394*7348b5c5SDavid van Moolenbroek (void) NetClose(net);
2395*7348b5c5SDavid van Moolenbroek ExitString("Connection closed by foreign host.\n",1);
2396*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
2397*7348b5c5SDavid van Moolenbroek }
2398*7348b5c5SDavid van Moolenbroek
2399*7348b5c5SDavid van Moolenbroek #define HELPINDENT ((int)sizeof ("connect"))
2400*7348b5c5SDavid van Moolenbroek
2401*7348b5c5SDavid van Moolenbroek static char
2402*7348b5c5SDavid van Moolenbroek openhelp[] = "connect to a site",
2403*7348b5c5SDavid van Moolenbroek closehelp[] = "close current connection",
2404*7348b5c5SDavid van Moolenbroek logouthelp[] = "forcibly logout remote user and close the connection",
2405*7348b5c5SDavid van Moolenbroek quithelp[] = "exit telnet",
2406*7348b5c5SDavid van Moolenbroek statushelp[] = "print status information",
2407*7348b5c5SDavid van Moolenbroek helphelp[] = "print help information",
2408*7348b5c5SDavid van Moolenbroek sendhelp[] = "transmit special characters ('send ?' for more)",
2409*7348b5c5SDavid van Moolenbroek sethelp[] = "set operating parameters ('set ?' for more)",
2410*7348b5c5SDavid van Moolenbroek unsethelp[] = "unset operating parameters ('unset ?' for more)",
2411*7348b5c5SDavid van Moolenbroek togglestring[] ="toggle operating parameters ('toggle ?' for more)",
2412*7348b5c5SDavid van Moolenbroek slchelp[] = "change state of special characters ('slc ?' for more)",
2413*7348b5c5SDavid van Moolenbroek displayhelp[] = "display operating parameters",
2414*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2415*7348b5c5SDavid van Moolenbroek transcomhelp[] = "specify Unix command for transparent mode pipe",
2416*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
2417*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
2418*7348b5c5SDavid van Moolenbroek authhelp[] = "turn on (off) authentication ('auth ?' for more)",
2419*7348b5c5SDavid van Moolenbroek #endif
2420*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
2421*7348b5c5SDavid van Moolenbroek encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)",
2422*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
2423*7348b5c5SDavid van Moolenbroek zhelp[] = "suspend telnet",
2424*7348b5c5SDavid van Moolenbroek shellhelp[] = "invoke a subshell",
2425*7348b5c5SDavid van Moolenbroek envhelp[] = "change environment variables ('environ ?' for more)",
2426*7348b5c5SDavid van Moolenbroek modestring[] = "try to enter line or character mode ('mode ?' for more)";
2427*7348b5c5SDavid van Moolenbroek
2428*7348b5c5SDavid van Moolenbroek static Command cmdtab[] = {
2429*7348b5c5SDavid van Moolenbroek { "close", closehelp, bye, 1 },
2430*7348b5c5SDavid van Moolenbroek { "logout", logouthelp, logout, 1 },
2431*7348b5c5SDavid van Moolenbroek { "display", displayhelp, display, 0 },
2432*7348b5c5SDavid van Moolenbroek { "mode", modestring, modecmd, 0 },
2433*7348b5c5SDavid van Moolenbroek { "open", openhelp, tn, 0 },
2434*7348b5c5SDavid van Moolenbroek { "quit", quithelp, quit, 0 },
2435*7348b5c5SDavid van Moolenbroek { "send", sendhelp, sendcmd, 0 },
2436*7348b5c5SDavid van Moolenbroek { "set", sethelp, setcmd, 0 },
2437*7348b5c5SDavid van Moolenbroek { "unset", unsethelp, unsetcmd, 0 },
2438*7348b5c5SDavid van Moolenbroek { "status", statushelp, status, 0 },
2439*7348b5c5SDavid van Moolenbroek { "toggle", togglestring, toggle, 0 },
2440*7348b5c5SDavid van Moolenbroek { "slc", slchelp, slccmd, 0 },
2441*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2442*7348b5c5SDavid van Moolenbroek { "transcom", transcomhelp, settranscom, 0 },
2443*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
2444*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
2445*7348b5c5SDavid van Moolenbroek { "auth", authhelp, auth_cmd, 0 },
2446*7348b5c5SDavid van Moolenbroek #endif
2447*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
2448*7348b5c5SDavid van Moolenbroek { "encrypt", encrypthelp, encrypt_cmd, 0 },
2449*7348b5c5SDavid van Moolenbroek #endif
2450*7348b5c5SDavid van Moolenbroek { "z", zhelp, suspend, 0 },
2451*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2452*7348b5c5SDavid van Moolenbroek { "!", shellhelp, shell, 1 },
2453*7348b5c5SDavid van Moolenbroek #else
2454*7348b5c5SDavid van Moolenbroek { "!", shellhelp, shell, 0 },
2455*7348b5c5SDavid van Moolenbroek #endif
2456*7348b5c5SDavid van Moolenbroek { "environ", envhelp, env_cmd, 0 },
2457*7348b5c5SDavid van Moolenbroek { "?", helphelp, help, 0 },
2458*7348b5c5SDavid van Moolenbroek { NULL, NULL, NULL, 0 }
2459*7348b5c5SDavid van Moolenbroek };
2460*7348b5c5SDavid van Moolenbroek
2461*7348b5c5SDavid van Moolenbroek static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead";
2462*7348b5c5SDavid van Moolenbroek static char escapehelp[] = "deprecated command -- use 'set escape' instead";
2463*7348b5c5SDavid van Moolenbroek
2464*7348b5c5SDavid van Moolenbroek static Command cmdtab2[] = {
2465*7348b5c5SDavid van Moolenbroek { "help", 0, help, 0 },
2466*7348b5c5SDavid van Moolenbroek { "escape", escapehelp, setescape, 0 },
2467*7348b5c5SDavid van Moolenbroek { "crmod", crmodhelp, togcrmod, 0 },
2468*7348b5c5SDavid van Moolenbroek { NULL, NULL, NULL, 0 }
2469*7348b5c5SDavid van Moolenbroek };
2470*7348b5c5SDavid van Moolenbroek
2471*7348b5c5SDavid van Moolenbroek
2472*7348b5c5SDavid van Moolenbroek /*
2473*7348b5c5SDavid van Moolenbroek * Call routine with argc, argv set from args (terminated by 0).
2474*7348b5c5SDavid van Moolenbroek */
2475*7348b5c5SDavid van Moolenbroek
2476*7348b5c5SDavid van Moolenbroek /*VARARGS1*/
2477*7348b5c5SDavid van Moolenbroek static int
call(intrtn_t routine,...)2478*7348b5c5SDavid van Moolenbroek call(intrtn_t routine, ...)
2479*7348b5c5SDavid van Moolenbroek {
2480*7348b5c5SDavid van Moolenbroek va_list ap;
2481*7348b5c5SDavid van Moolenbroek char *args[100];
2482*7348b5c5SDavid van Moolenbroek int argno = 0;
2483*7348b5c5SDavid van Moolenbroek
2484*7348b5c5SDavid van Moolenbroek va_start(ap, routine);
2485*7348b5c5SDavid van Moolenbroek while ((args[argno++] = va_arg(ap, char *)) != 0) {
2486*7348b5c5SDavid van Moolenbroek ;
2487*7348b5c5SDavid van Moolenbroek }
2488*7348b5c5SDavid van Moolenbroek va_end(ap);
2489*7348b5c5SDavid van Moolenbroek return (*routine)(argno-1, args);
2490*7348b5c5SDavid van Moolenbroek }
2491*7348b5c5SDavid van Moolenbroek
2492*7348b5c5SDavid van Moolenbroek
2493*7348b5c5SDavid van Moolenbroek static Command *
getcmd(char * name)2494*7348b5c5SDavid van Moolenbroek getcmd(char *name)
2495*7348b5c5SDavid van Moolenbroek {
2496*7348b5c5SDavid van Moolenbroek Command *cm;
2497*7348b5c5SDavid van Moolenbroek
2498*7348b5c5SDavid van Moolenbroek if ((cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command))) != NULL)
2499*7348b5c5SDavid van Moolenbroek return cm;
2500*7348b5c5SDavid van Moolenbroek return (Command *) genget(name, (char **) cmdtab2, sizeof(Command));
2501*7348b5c5SDavid van Moolenbroek }
2502*7348b5c5SDavid van Moolenbroek
2503*7348b5c5SDavid van Moolenbroek void
command(int top,const char * tbuf,int cnt)2504*7348b5c5SDavid van Moolenbroek command(int top, const char *tbuf, int cnt)
2505*7348b5c5SDavid van Moolenbroek {
2506*7348b5c5SDavid van Moolenbroek Command *c;
2507*7348b5c5SDavid van Moolenbroek
2508*7348b5c5SDavid van Moolenbroek setcommandmode();
2509*7348b5c5SDavid van Moolenbroek if (!top) {
2510*7348b5c5SDavid van Moolenbroek putchar('\n');
2511*7348b5c5SDavid van Moolenbroek } else {
2512*7348b5c5SDavid van Moolenbroek (void) signal(SIGINT, SIG_DFL);
2513*7348b5c5SDavid van Moolenbroek (void) signal(SIGQUIT, SIG_DFL);
2514*7348b5c5SDavid van Moolenbroek }
2515*7348b5c5SDavid van Moolenbroek for (;;) {
2516*7348b5c5SDavid van Moolenbroek if (rlogin == _POSIX_VDISABLE)
2517*7348b5c5SDavid van Moolenbroek printf("%s> ", prompt);
2518*7348b5c5SDavid van Moolenbroek if (tbuf) {
2519*7348b5c5SDavid van Moolenbroek char *cp;
2520*7348b5c5SDavid van Moolenbroek cp = line;
2521*7348b5c5SDavid van Moolenbroek while (cnt > 0 && (*cp++ = *tbuf++) != '\n')
2522*7348b5c5SDavid van Moolenbroek cnt--;
2523*7348b5c5SDavid van Moolenbroek tbuf = 0;
2524*7348b5c5SDavid van Moolenbroek if (cp == line || *--cp != '\n' || cp == line)
2525*7348b5c5SDavid van Moolenbroek goto getline;
2526*7348b5c5SDavid van Moolenbroek *cp = '\0';
2527*7348b5c5SDavid van Moolenbroek if (rlogin == _POSIX_VDISABLE)
2528*7348b5c5SDavid van Moolenbroek printf("%s\n", line);
2529*7348b5c5SDavid van Moolenbroek } else {
2530*7348b5c5SDavid van Moolenbroek getline:
2531*7348b5c5SDavid van Moolenbroek if (rlogin != _POSIX_VDISABLE)
2532*7348b5c5SDavid van Moolenbroek printf("%s> ", prompt);
2533*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2534*7348b5c5SDavid van Moolenbroek fflush(stdout);
2535*7348b5c5SDavid van Moolenbroek #endif
2536*7348b5c5SDavid van Moolenbroek if (fgets(line, sizeof(line), stdin) == NULL) {
2537*7348b5c5SDavid van Moolenbroek if (feof(stdin) || ferror(stdin)) {
2538*7348b5c5SDavid van Moolenbroek (void) quit(0, NULL);
2539*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
2540*7348b5c5SDavid van Moolenbroek }
2541*7348b5c5SDavid van Moolenbroek break;
2542*7348b5c5SDavid van Moolenbroek }
2543*7348b5c5SDavid van Moolenbroek }
2544*7348b5c5SDavid van Moolenbroek if (line[0] == 0)
2545*7348b5c5SDavid van Moolenbroek break;
2546*7348b5c5SDavid van Moolenbroek makeargv();
2547*7348b5c5SDavid van Moolenbroek if (margv[0] == 0) {
2548*7348b5c5SDavid van Moolenbroek break;
2549*7348b5c5SDavid van Moolenbroek }
2550*7348b5c5SDavid van Moolenbroek c = getcmd(margv[0]);
2551*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
2552*7348b5c5SDavid van Moolenbroek printf("?Ambiguous command\n");
2553*7348b5c5SDavid van Moolenbroek continue;
2554*7348b5c5SDavid van Moolenbroek }
2555*7348b5c5SDavid van Moolenbroek if (c == 0) {
2556*7348b5c5SDavid van Moolenbroek printf("?Invalid command\n");
2557*7348b5c5SDavid van Moolenbroek continue;
2558*7348b5c5SDavid van Moolenbroek }
2559*7348b5c5SDavid van Moolenbroek if (c->needconnect && !connected) {
2560*7348b5c5SDavid van Moolenbroek printf("?Need to be connected first.\n");
2561*7348b5c5SDavid van Moolenbroek continue;
2562*7348b5c5SDavid van Moolenbroek }
2563*7348b5c5SDavid van Moolenbroek if ((*c->handler)(margc, margv)) {
2564*7348b5c5SDavid van Moolenbroek break;
2565*7348b5c5SDavid van Moolenbroek }
2566*7348b5c5SDavid van Moolenbroek }
2567*7348b5c5SDavid van Moolenbroek if (!top) {
2568*7348b5c5SDavid van Moolenbroek if (!connected) {
2569*7348b5c5SDavid van Moolenbroek longjmp(toplevel, 1);
2570*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
2571*7348b5c5SDavid van Moolenbroek }
2572*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2573*7348b5c5SDavid van Moolenbroek if (shell_active == 0) {
2574*7348b5c5SDavid van Moolenbroek setconnmode(0);
2575*7348b5c5SDavid van Moolenbroek }
2576*7348b5c5SDavid van Moolenbroek #else /* defined(TN3270) */
2577*7348b5c5SDavid van Moolenbroek setconnmode(0);
2578*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
2579*7348b5c5SDavid van Moolenbroek }
2580*7348b5c5SDavid van Moolenbroek }
2581*7348b5c5SDavid van Moolenbroek
2582*7348b5c5SDavid van Moolenbroek /*
2583*7348b5c5SDavid van Moolenbroek * Help command.
2584*7348b5c5SDavid van Moolenbroek */
2585*7348b5c5SDavid van Moolenbroek static int
help(int argc,char * argv[])2586*7348b5c5SDavid van Moolenbroek help(int argc, char *argv[])
2587*7348b5c5SDavid van Moolenbroek {
2588*7348b5c5SDavid van Moolenbroek Command *c;
2589*7348b5c5SDavid van Moolenbroek
2590*7348b5c5SDavid van Moolenbroek if (argc == 1) {
2591*7348b5c5SDavid van Moolenbroek printf("Commands may be abbreviated. Commands are:\n\n");
2592*7348b5c5SDavid van Moolenbroek for (c = cmdtab; c->name; c++)
2593*7348b5c5SDavid van Moolenbroek if (c->help) {
2594*7348b5c5SDavid van Moolenbroek printf("%-*s\t%s\n", HELPINDENT, c->name,
2595*7348b5c5SDavid van Moolenbroek c->help);
2596*7348b5c5SDavid van Moolenbroek }
2597*7348b5c5SDavid van Moolenbroek return 0;
2598*7348b5c5SDavid van Moolenbroek }
2599*7348b5c5SDavid van Moolenbroek while (--argc > 0) {
2600*7348b5c5SDavid van Moolenbroek char *arg;
2601*7348b5c5SDavid van Moolenbroek arg = *++argv;
2602*7348b5c5SDavid van Moolenbroek c = getcmd(arg);
2603*7348b5c5SDavid van Moolenbroek if (Ambiguous(c))
2604*7348b5c5SDavid van Moolenbroek printf("?Ambiguous help command %s\n", arg);
2605*7348b5c5SDavid van Moolenbroek else if (c == (Command *)0)
2606*7348b5c5SDavid van Moolenbroek printf("?Invalid help command %s\n", arg);
2607*7348b5c5SDavid van Moolenbroek else
2608*7348b5c5SDavid van Moolenbroek printf("%s\n", c->help);
2609*7348b5c5SDavid van Moolenbroek }
2610*7348b5c5SDavid van Moolenbroek return 0;
2611*7348b5c5SDavid van Moolenbroek }
2612*7348b5c5SDavid van Moolenbroek
2613*7348b5c5SDavid van Moolenbroek static char *rcname = 0;
2614*7348b5c5SDavid van Moolenbroek static char rcbuf[128];
2615*7348b5c5SDavid van Moolenbroek
2616*7348b5c5SDavid van Moolenbroek void
cmdrc(const char * m1,const char * m2)2617*7348b5c5SDavid van Moolenbroek cmdrc(const char *m1, const char *m2)
2618*7348b5c5SDavid van Moolenbroek {
2619*7348b5c5SDavid van Moolenbroek Command *c;
2620*7348b5c5SDavid van Moolenbroek FILE *rcfile;
2621*7348b5c5SDavid van Moolenbroek int gotmachine = 0;
2622*7348b5c5SDavid van Moolenbroek int l1 = strlen(m1);
2623*7348b5c5SDavid van Moolenbroek int l2 = strlen(m2);
2624*7348b5c5SDavid van Moolenbroek char m1save[MAXHOSTNAMELEN + 1];
2625*7348b5c5SDavid van Moolenbroek
2626*7348b5c5SDavid van Moolenbroek if (skiprc)
2627*7348b5c5SDavid van Moolenbroek return;
2628*7348b5c5SDavid van Moolenbroek
2629*7348b5c5SDavid van Moolenbroek strlcpy(m1save, m1, sizeof(m1save));
2630*7348b5c5SDavid van Moolenbroek m1 = m1save;
2631*7348b5c5SDavid van Moolenbroek
2632*7348b5c5SDavid van Moolenbroek if (rcname == 0) {
2633*7348b5c5SDavid van Moolenbroek rcname = getenv("HOME");
2634*7348b5c5SDavid van Moolenbroek if (rcname)
2635*7348b5c5SDavid van Moolenbroek strlcpy(rcbuf, rcname, sizeof(rcbuf));
2636*7348b5c5SDavid van Moolenbroek else
2637*7348b5c5SDavid van Moolenbroek rcbuf[0] = '\0';
2638*7348b5c5SDavid van Moolenbroek strlcat(rcbuf, "/.telnetrc", sizeof(rcbuf));
2639*7348b5c5SDavid van Moolenbroek rcname = rcbuf;
2640*7348b5c5SDavid van Moolenbroek }
2641*7348b5c5SDavid van Moolenbroek
2642*7348b5c5SDavid van Moolenbroek if ((rcfile = fopen(rcname, "r")) == 0) {
2643*7348b5c5SDavid van Moolenbroek return;
2644*7348b5c5SDavid van Moolenbroek }
2645*7348b5c5SDavid van Moolenbroek
2646*7348b5c5SDavid van Moolenbroek for (;;) {
2647*7348b5c5SDavid van Moolenbroek if (fgets(line, sizeof(line), rcfile) == NULL)
2648*7348b5c5SDavid van Moolenbroek break;
2649*7348b5c5SDavid van Moolenbroek if (line[0] == 0)
2650*7348b5c5SDavid van Moolenbroek break;
2651*7348b5c5SDavid van Moolenbroek if (line[0] == '#')
2652*7348b5c5SDavid van Moolenbroek continue;
2653*7348b5c5SDavid van Moolenbroek if (gotmachine) {
2654*7348b5c5SDavid van Moolenbroek if (!isspace((unsigned char)line[0]))
2655*7348b5c5SDavid van Moolenbroek gotmachine = 0;
2656*7348b5c5SDavid van Moolenbroek }
2657*7348b5c5SDavid van Moolenbroek if (gotmachine == 0) {
2658*7348b5c5SDavid van Moolenbroek if (isspace((unsigned char)line[0]))
2659*7348b5c5SDavid van Moolenbroek continue;
2660*7348b5c5SDavid van Moolenbroek if (strncasecmp(line, m1, l1) == 0)
2661*7348b5c5SDavid van Moolenbroek strncpy(line, &line[l1], sizeof(line) - l1);
2662*7348b5c5SDavid van Moolenbroek else if (strncasecmp(line, m2, l2) == 0)
2663*7348b5c5SDavid van Moolenbroek strncpy(line, &line[l2], sizeof(line) - l2);
2664*7348b5c5SDavid van Moolenbroek else if (strncasecmp(line, "DEFAULT", 7) == 0)
2665*7348b5c5SDavid van Moolenbroek strncpy(line, &line[7], sizeof(line) - 7);
2666*7348b5c5SDavid van Moolenbroek else
2667*7348b5c5SDavid van Moolenbroek continue;
2668*7348b5c5SDavid van Moolenbroek if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
2669*7348b5c5SDavid van Moolenbroek continue;
2670*7348b5c5SDavid van Moolenbroek gotmachine = 1;
2671*7348b5c5SDavid van Moolenbroek }
2672*7348b5c5SDavid van Moolenbroek makeargv();
2673*7348b5c5SDavid van Moolenbroek if (margv[0] == 0)
2674*7348b5c5SDavid van Moolenbroek continue;
2675*7348b5c5SDavid van Moolenbroek c = getcmd(margv[0]);
2676*7348b5c5SDavid van Moolenbroek if (Ambiguous(c)) {
2677*7348b5c5SDavid van Moolenbroek printf("?Ambiguous command: %s\n", margv[0]);
2678*7348b5c5SDavid van Moolenbroek continue;
2679*7348b5c5SDavid van Moolenbroek }
2680*7348b5c5SDavid van Moolenbroek if (c == 0) {
2681*7348b5c5SDavid van Moolenbroek printf("?Invalid command: %s\n", margv[0]);
2682*7348b5c5SDavid van Moolenbroek continue;
2683*7348b5c5SDavid van Moolenbroek }
2684*7348b5c5SDavid van Moolenbroek /*
2685*7348b5c5SDavid van Moolenbroek * This should never happen...
2686*7348b5c5SDavid van Moolenbroek */
2687*7348b5c5SDavid van Moolenbroek if (c->needconnect && !connected) {
2688*7348b5c5SDavid van Moolenbroek printf("?Need to be connected first for %s.\n", margv[0]);
2689*7348b5c5SDavid van Moolenbroek continue;
2690*7348b5c5SDavid van Moolenbroek }
2691*7348b5c5SDavid van Moolenbroek (*c->handler)(margc, margv);
2692*7348b5c5SDavid van Moolenbroek }
2693*7348b5c5SDavid van Moolenbroek fclose(rcfile);
2694*7348b5c5SDavid van Moolenbroek }
2695*7348b5c5SDavid van Moolenbroek
2696*7348b5c5SDavid van Moolenbroek /*
2697*7348b5c5SDavid van Moolenbroek * Source route is handed in as
2698*7348b5c5SDavid van Moolenbroek * [!]@hop1@hop2...@dst
2699*7348b5c5SDavid van Moolenbroek *
2700*7348b5c5SDavid van Moolenbroek * If the leading ! is present, it is a strict source route, otherwise it is
2701*7348b5c5SDavid van Moolenbroek * assmed to be a loose source route. Note that leading ! is effective
2702*7348b5c5SDavid van Moolenbroek * only for IPv4 case.
2703*7348b5c5SDavid van Moolenbroek *
2704*7348b5c5SDavid van Moolenbroek * We fill in the source route option as
2705*7348b5c5SDavid van Moolenbroek * hop1,hop2,hop3...dest
2706*7348b5c5SDavid van Moolenbroek * and return a pointer to hop1, which will
2707*7348b5c5SDavid van Moolenbroek * be the address to connect() to.
2708*7348b5c5SDavid van Moolenbroek *
2709*7348b5c5SDavid van Moolenbroek * Arguments:
2710*7348b5c5SDavid van Moolenbroek * ai: The address (by struct addrinfo) for the final destination.
2711*7348b5c5SDavid van Moolenbroek *
2712*7348b5c5SDavid van Moolenbroek * arg: Pointer to route list to decipher
2713*7348b5c5SDavid van Moolenbroek *
2714*7348b5c5SDavid van Moolenbroek * cpp: Pointer to a pointer, so that sourceroute() can return
2715*7348b5c5SDavid van Moolenbroek * the address of result buffer (statically alloc'ed).
2716*7348b5c5SDavid van Moolenbroek *
2717*7348b5c5SDavid van Moolenbroek * protop/optp:
2718*7348b5c5SDavid van Moolenbroek * Pointer to an integer. The pointed variable
2719*7348b5c5SDavid van Moolenbroek * lenp: pointer to an integer that contains the
2720*7348b5c5SDavid van Moolenbroek * length of *cpp if *cpp != NULL.
2721*7348b5c5SDavid van Moolenbroek *
2722*7348b5c5SDavid van Moolenbroek * Return values:
2723*7348b5c5SDavid van Moolenbroek *
2724*7348b5c5SDavid van Moolenbroek * Returns the length of the option pointed to by *cpp. If the
2725*7348b5c5SDavid van Moolenbroek * return value is -1, there was a syntax error in the
2726*7348b5c5SDavid van Moolenbroek * option, either arg contained unknown characters or too many hosts,
2727*7348b5c5SDavid van Moolenbroek * or hostname cannot be resolved.
2728*7348b5c5SDavid van Moolenbroek *
2729*7348b5c5SDavid van Moolenbroek * The caller needs to pass return value (len), *cpp, *protop and *optp
2730*7348b5c5SDavid van Moolenbroek * to setsockopt(2).
2731*7348b5c5SDavid van Moolenbroek *
2732*7348b5c5SDavid van Moolenbroek * *cpp: Points to the result buffer. The region is statically
2733*7348b5c5SDavid van Moolenbroek * allocated by the function.
2734*7348b5c5SDavid van Moolenbroek *
2735*7348b5c5SDavid van Moolenbroek * *protop:
2736*7348b5c5SDavid van Moolenbroek * protocol # to be passed to setsockopt(2).
2737*7348b5c5SDavid van Moolenbroek *
2738*7348b5c5SDavid van Moolenbroek * *optp: option # to be passed to setsockopt(2).
2739*7348b5c5SDavid van Moolenbroek *
2740*7348b5c5SDavid van Moolenbroek */
2741*7348b5c5SDavid van Moolenbroek int
sourceroute(struct addrinfo * ai,char * arg,char ** cpp,int * protop,int * optp)2742*7348b5c5SDavid van Moolenbroek sourceroute(struct addrinfo *ai, char *arg, char **cpp, int *protop, int *optp)
2743*7348b5c5SDavid van Moolenbroek {
2744*7348b5c5SDavid van Moolenbroek char *cp, *cp2, *lsrp, *lsrep;
2745*7348b5c5SDavid van Moolenbroek struct addrinfo hints, *res;
2746*7348b5c5SDavid van Moolenbroek int len, error;
2747*7348b5c5SDavid van Moolenbroek struct sockaddr_in *sin;
2748*7348b5c5SDavid van Moolenbroek char c;
2749*7348b5c5SDavid van Moolenbroek static char lsr[44];
2750*7348b5c5SDavid van Moolenbroek #ifdef INET6
2751*7348b5c5SDavid van Moolenbroek struct cmsghdr *cmsg;
2752*7348b5c5SDavid van Moolenbroek struct sockaddr_in6 *sin6;
2753*7348b5c5SDavid van Moolenbroek static char rhbuf[1024];
2754*7348b5c5SDavid van Moolenbroek #endif
2755*7348b5c5SDavid van Moolenbroek
2756*7348b5c5SDavid van Moolenbroek /*
2757*7348b5c5SDavid van Moolenbroek * Verify the arguments.
2758*7348b5c5SDavid van Moolenbroek */
2759*7348b5c5SDavid van Moolenbroek if (cpp == NULL)
2760*7348b5c5SDavid van Moolenbroek return -1;
2761*7348b5c5SDavid van Moolenbroek
2762*7348b5c5SDavid van Moolenbroek cp = arg;
2763*7348b5c5SDavid van Moolenbroek
2764*7348b5c5SDavid van Moolenbroek *cpp = NULL;
2765*7348b5c5SDavid van Moolenbroek
2766*7348b5c5SDavid van Moolenbroek /* init these just in case.... */
2767*7348b5c5SDavid van Moolenbroek lsrp = NULL;
2768*7348b5c5SDavid van Moolenbroek lsrep = NULL;
2769*7348b5c5SDavid van Moolenbroek #ifdef INET6
2770*7348b5c5SDavid van Moolenbroek cmsg = NULL;
2771*7348b5c5SDavid van Moolenbroek #endif
2772*7348b5c5SDavid van Moolenbroek
2773*7348b5c5SDavid van Moolenbroek switch (ai->ai_family) {
2774*7348b5c5SDavid van Moolenbroek case AF_INET:
2775*7348b5c5SDavid van Moolenbroek lsrp = lsr;
2776*7348b5c5SDavid van Moolenbroek lsrep = lsrp + sizeof(lsr);
2777*7348b5c5SDavid van Moolenbroek
2778*7348b5c5SDavid van Moolenbroek /*
2779*7348b5c5SDavid van Moolenbroek * Next, decide whether we have a loose source
2780*7348b5c5SDavid van Moolenbroek * route or a strict source route, and fill in
2781*7348b5c5SDavid van Moolenbroek * the begining of the option.
2782*7348b5c5SDavid van Moolenbroek */
2783*7348b5c5SDavid van Moolenbroek if (*cp == '!') {
2784*7348b5c5SDavid van Moolenbroek cp++;
2785*7348b5c5SDavid van Moolenbroek *lsrp++ = IPOPT_SSRR;
2786*7348b5c5SDavid van Moolenbroek } else
2787*7348b5c5SDavid van Moolenbroek *lsrp++ = IPOPT_LSRR;
2788*7348b5c5SDavid van Moolenbroek if (*cp != '@')
2789*7348b5c5SDavid van Moolenbroek return -1;
2790*7348b5c5SDavid van Moolenbroek lsrp++; /* skip over length, we'll fill it in later */
2791*7348b5c5SDavid van Moolenbroek *lsrp++ = 4;
2792*7348b5c5SDavid van Moolenbroek cp++;
2793*7348b5c5SDavid van Moolenbroek *protop = IPPROTO_IP;
2794*7348b5c5SDavid van Moolenbroek *optp = IP_OPTIONS;
2795*7348b5c5SDavid van Moolenbroek break;
2796*7348b5c5SDavid van Moolenbroek #ifdef INET6
2797*7348b5c5SDavid van Moolenbroek case AF_INET6:
2798*7348b5c5SDavid van Moolenbroek #ifdef IPV6_PKTOPTIONS
2799*7348b5c5SDavid van Moolenbroek /* RFC2292 */
2800*7348b5c5SDavid van Moolenbroek cmsg = inet6_rthdr_init(rhbuf, IPV6_RTHDR_TYPE_0);
2801*7348b5c5SDavid van Moolenbroek if (*cp != '@')
2802*7348b5c5SDavid van Moolenbroek return -1;
2803*7348b5c5SDavid van Moolenbroek cp++;
2804*7348b5c5SDavid van Moolenbroek *protop = IPPROTO_IPV6;
2805*7348b5c5SDavid van Moolenbroek *optp = IPV6_PKTOPTIONS;
2806*7348b5c5SDavid van Moolenbroek break;
2807*7348b5c5SDavid van Moolenbroek #else
2808*7348b5c5SDavid van Moolenbroek /* no RFC2292 */
2809*7348b5c5SDavid van Moolenbroek return -1;
2810*7348b5c5SDavid van Moolenbroek #endif
2811*7348b5c5SDavid van Moolenbroek #endif
2812*7348b5c5SDavid van Moolenbroek default:
2813*7348b5c5SDavid van Moolenbroek return -1;
2814*7348b5c5SDavid van Moolenbroek }
2815*7348b5c5SDavid van Moolenbroek
2816*7348b5c5SDavid van Moolenbroek memset(&hints, 0, sizeof(hints));
2817*7348b5c5SDavid van Moolenbroek hints.ai_family = ai->ai_family;
2818*7348b5c5SDavid van Moolenbroek hints.ai_socktype = SOCK_STREAM;
2819*7348b5c5SDavid van Moolenbroek
2820*7348b5c5SDavid van Moolenbroek for (c = 0;;) {
2821*7348b5c5SDavid van Moolenbroek if (c == ':')
2822*7348b5c5SDavid van Moolenbroek cp2 = 0;
2823*7348b5c5SDavid van Moolenbroek else for (cp2 = cp; (c = *cp2) != '\0'; cp2++) {
2824*7348b5c5SDavid van Moolenbroek if (c == ',') {
2825*7348b5c5SDavid van Moolenbroek *cp2++ = '\0';
2826*7348b5c5SDavid van Moolenbroek if (*cp2 == '@')
2827*7348b5c5SDavid van Moolenbroek cp2++;
2828*7348b5c5SDavid van Moolenbroek } else if (c == '@') {
2829*7348b5c5SDavid van Moolenbroek *cp2++ = '\0';
2830*7348b5c5SDavid van Moolenbroek }
2831*7348b5c5SDavid van Moolenbroek #if 0 /*colon conflicts with IPv6 address*/
2832*7348b5c5SDavid van Moolenbroek else if (c == ':') {
2833*7348b5c5SDavid van Moolenbroek *cp2++ = '\0';
2834*7348b5c5SDavid van Moolenbroek }
2835*7348b5c5SDavid van Moolenbroek #endif
2836*7348b5c5SDavid van Moolenbroek else
2837*7348b5c5SDavid van Moolenbroek continue;
2838*7348b5c5SDavid van Moolenbroek break;
2839*7348b5c5SDavid van Moolenbroek }
2840*7348b5c5SDavid van Moolenbroek if (!c)
2841*7348b5c5SDavid van Moolenbroek cp2 = 0;
2842*7348b5c5SDavid van Moolenbroek
2843*7348b5c5SDavid van Moolenbroek error = getaddrinfo(cp, NULL, &hints, &res);
2844*7348b5c5SDavid van Moolenbroek if (error) {
2845*7348b5c5SDavid van Moolenbroek fprintf(stderr, "%s: %s\n", cp, gai_strerror(error));
2846*7348b5c5SDavid van Moolenbroek return -1;
2847*7348b5c5SDavid van Moolenbroek }
2848*7348b5c5SDavid van Moolenbroek if (ai->ai_family != res->ai_family) {
2849*7348b5c5SDavid van Moolenbroek freeaddrinfo(res);
2850*7348b5c5SDavid van Moolenbroek return -1;
2851*7348b5c5SDavid van Moolenbroek }
2852*7348b5c5SDavid van Moolenbroek if (ai->ai_family == AF_INET) {
2853*7348b5c5SDavid van Moolenbroek /*
2854*7348b5c5SDavid van Moolenbroek * Check to make sure there is space for address
2855*7348b5c5SDavid van Moolenbroek */
2856*7348b5c5SDavid van Moolenbroek if (lsrp + 4 > lsrep) {
2857*7348b5c5SDavid van Moolenbroek freeaddrinfo(res);
2858*7348b5c5SDavid van Moolenbroek return -1;
2859*7348b5c5SDavid van Moolenbroek }
2860*7348b5c5SDavid van Moolenbroek sin = (struct sockaddr_in *)res->ai_addr;
2861*7348b5c5SDavid van Moolenbroek memcpy(lsrp, &sin->sin_addr, sizeof(struct in_addr));
2862*7348b5c5SDavid van Moolenbroek lsrp += sizeof(struct in_addr);
2863*7348b5c5SDavid van Moolenbroek }
2864*7348b5c5SDavid van Moolenbroek #ifdef INET6
2865*7348b5c5SDavid van Moolenbroek else if (ai->ai_family == AF_INET6) {
2866*7348b5c5SDavid van Moolenbroek sin6 = (struct sockaddr_in6 *)res->ai_addr;
2867*7348b5c5SDavid van Moolenbroek inet6_rthdr_add(cmsg, &sin6->sin6_addr,
2868*7348b5c5SDavid van Moolenbroek IPV6_RTHDR_LOOSE);
2869*7348b5c5SDavid van Moolenbroek }
2870*7348b5c5SDavid van Moolenbroek #endif
2871*7348b5c5SDavid van Moolenbroek else {
2872*7348b5c5SDavid van Moolenbroek freeaddrinfo(res);
2873*7348b5c5SDavid van Moolenbroek return -1;
2874*7348b5c5SDavid van Moolenbroek }
2875*7348b5c5SDavid van Moolenbroek freeaddrinfo(res);
2876*7348b5c5SDavid van Moolenbroek if (cp2)
2877*7348b5c5SDavid van Moolenbroek cp = cp2;
2878*7348b5c5SDavid van Moolenbroek else
2879*7348b5c5SDavid van Moolenbroek break;
2880*7348b5c5SDavid van Moolenbroek }
2881*7348b5c5SDavid van Moolenbroek switch (ai->ai_family) {
2882*7348b5c5SDavid van Moolenbroek case AF_INET:
2883*7348b5c5SDavid van Moolenbroek /* record the last hop */
2884*7348b5c5SDavid van Moolenbroek if (lsrp + 4 > lsrep)
2885*7348b5c5SDavid van Moolenbroek return -1;
2886*7348b5c5SDavid van Moolenbroek sin = (struct sockaddr_in *)ai->ai_addr;
2887*7348b5c5SDavid van Moolenbroek memcpy(lsrp, &sin->sin_addr, sizeof(struct in_addr));
2888*7348b5c5SDavid van Moolenbroek lsrp += sizeof(struct in_addr);
2889*7348b5c5SDavid van Moolenbroek lsr[IPOPT_OLEN] = lsrp - lsr;
2890*7348b5c5SDavid van Moolenbroek if (lsr[IPOPT_OLEN] <= 7 || lsr[IPOPT_OLEN] > 40)
2891*7348b5c5SDavid van Moolenbroek return -1;
2892*7348b5c5SDavid van Moolenbroek *lsrp++ = IPOPT_NOP; /*32bit word align*/
2893*7348b5c5SDavid van Moolenbroek len = lsrp - lsr;
2894*7348b5c5SDavid van Moolenbroek *cpp = lsr;
2895*7348b5c5SDavid van Moolenbroek break;
2896*7348b5c5SDavid van Moolenbroek #ifdef INET6
2897*7348b5c5SDavid van Moolenbroek case AF_INET6:
2898*7348b5c5SDavid van Moolenbroek inet6_rthdr_lasthop(cmsg, IPV6_RTHDR_LOOSE);
2899*7348b5c5SDavid van Moolenbroek len = cmsg->cmsg_len;
2900*7348b5c5SDavid van Moolenbroek *cpp = rhbuf;
2901*7348b5c5SDavid van Moolenbroek break;
2902*7348b5c5SDavid van Moolenbroek #endif
2903*7348b5c5SDavid van Moolenbroek default:
2904*7348b5c5SDavid van Moolenbroek return -1;
2905*7348b5c5SDavid van Moolenbroek }
2906*7348b5c5SDavid van Moolenbroek return len;
2907*7348b5c5SDavid van Moolenbroek }
2908