1*7348b5c5SDavid van Moolenbroek /* $NetBSD: telnet.c,v 1.36 2012/01/10 13:49:32 christos Exp $ */
2*7348b5c5SDavid van Moolenbroek
3*7348b5c5SDavid van Moolenbroek /*
4*7348b5c5SDavid van Moolenbroek * Copyright (c) 1988, 1990, 1993
5*7348b5c5SDavid van Moolenbroek * The Regents of the University of California. 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 University 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 REGENTS 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 REGENTS 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 #include <sys/cdefs.h>
33*7348b5c5SDavid van Moolenbroek #ifndef lint
34*7348b5c5SDavid van Moolenbroek #if 0
35*7348b5c5SDavid van Moolenbroek static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95";
36*7348b5c5SDavid van Moolenbroek #else
37*7348b5c5SDavid van Moolenbroek __RCSID("$NetBSD: telnet.c,v 1.36 2012/01/10 13:49:32 christos Exp $");
38*7348b5c5SDavid van Moolenbroek #endif
39*7348b5c5SDavid van Moolenbroek #endif /* not lint */
40*7348b5c5SDavid van Moolenbroek
41*7348b5c5SDavid van Moolenbroek #include <sys/param.h>
42*7348b5c5SDavid van Moolenbroek
43*7348b5c5SDavid van Moolenbroek #include <signal.h>
44*7348b5c5SDavid van Moolenbroek #include <term.h>
45*7348b5c5SDavid van Moolenbroek #include <unistd.h>
46*7348b5c5SDavid van Moolenbroek /* By the way, we need to include curses.h before telnet.h since,
47*7348b5c5SDavid van Moolenbroek * among other things, telnet.h #defines 'DO', which is a variable
48*7348b5c5SDavid van Moolenbroek * declared in curses.h.
49*7348b5c5SDavid van Moolenbroek */
50*7348b5c5SDavid van Moolenbroek
51*7348b5c5SDavid van Moolenbroek #include <arpa/telnet.h>
52*7348b5c5SDavid van Moolenbroek
53*7348b5c5SDavid van Moolenbroek #include <ctype.h>
54*7348b5c5SDavid van Moolenbroek
55*7348b5c5SDavid van Moolenbroek #include "ring.h"
56*7348b5c5SDavid van Moolenbroek #include "defines.h"
57*7348b5c5SDavid van Moolenbroek #include "externs.h"
58*7348b5c5SDavid van Moolenbroek #include "types.h"
59*7348b5c5SDavid van Moolenbroek #include "general.h"
60*7348b5c5SDavid van Moolenbroek
61*7348b5c5SDavid van Moolenbroek #include <libtelnet/misc.h>
62*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
63*7348b5c5SDavid van Moolenbroek #include <libtelnet/auth.h>
64*7348b5c5SDavid van Moolenbroek #endif
65*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
66*7348b5c5SDavid van Moolenbroek #include <libtelnet/encrypt.h>
67*7348b5c5SDavid van Moolenbroek #endif
68*7348b5c5SDavid van Moolenbroek
69*7348b5c5SDavid van Moolenbroek #define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
70*7348b5c5SDavid van Moolenbroek
71*7348b5c5SDavid van Moolenbroek static unsigned char subbuffer[SUBBUFSIZE],
72*7348b5c5SDavid van Moolenbroek *subpointer, *subend; /* buffer for sub-options */
73*7348b5c5SDavid van Moolenbroek #define SB_CLEAR() subpointer = subbuffer;
74*7348b5c5SDavid van Moolenbroek #define SB_TERM() { subend = subpointer; SB_CLEAR(); }
75*7348b5c5SDavid van Moolenbroek #define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
76*7348b5c5SDavid van Moolenbroek *subpointer++ = (c); \
77*7348b5c5SDavid van Moolenbroek }
78*7348b5c5SDavid van Moolenbroek
79*7348b5c5SDavid van Moolenbroek #define SB_GET() ((*subpointer++)&0xff)
80*7348b5c5SDavid van Moolenbroek #define SB_PEEK() ((*subpointer)&0xff)
81*7348b5c5SDavid van Moolenbroek #define SB_EOF() (subpointer >= subend)
82*7348b5c5SDavid van Moolenbroek #define SB_LEN() (subend - subpointer)
83*7348b5c5SDavid van Moolenbroek
84*7348b5c5SDavid van Moolenbroek char options[256]; /* The combined options */
85*7348b5c5SDavid van Moolenbroek char do_dont_resp[256];
86*7348b5c5SDavid van Moolenbroek char will_wont_resp[256];
87*7348b5c5SDavid van Moolenbroek
88*7348b5c5SDavid van Moolenbroek int
89*7348b5c5SDavid van Moolenbroek eight = 0,
90*7348b5c5SDavid van Moolenbroek autologin = 0, /* Autologin anyone? */
91*7348b5c5SDavid van Moolenbroek skiprc = 0,
92*7348b5c5SDavid van Moolenbroek connected,
93*7348b5c5SDavid van Moolenbroek showoptions,
94*7348b5c5SDavid van Moolenbroek In3270, /* Are we in 3270 mode? */
95*7348b5c5SDavid van Moolenbroek ISend, /* trying to send network data in */
96*7348b5c5SDavid van Moolenbroek telnet_debug = 0,
97*7348b5c5SDavid van Moolenbroek crmod,
98*7348b5c5SDavid van Moolenbroek netdata, /* Print out network data flow */
99*7348b5c5SDavid van Moolenbroek crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
100*7348b5c5SDavid van Moolenbroek #ifdef TN3270
101*7348b5c5SDavid van Moolenbroek noasynchtty = 0,/* User specified "-noasynch" on command line */
102*7348b5c5SDavid van Moolenbroek noasynchnet = 0,/* User specified "-noasynch" on command line */
103*7348b5c5SDavid van Moolenbroek askedSGA = 0, /* We have talked about suppress go ahead */
104*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
105*7348b5c5SDavid van Moolenbroek telnetport,
106*7348b5c5SDavid van Moolenbroek SYNCHing, /* we are in TELNET SYNCH mode */
107*7348b5c5SDavid van Moolenbroek flushout, /* flush output */
108*7348b5c5SDavid van Moolenbroek autoflush = 0, /* flush output when interrupting? */
109*7348b5c5SDavid van Moolenbroek autosynch, /* send interrupt characters with SYNCH? */
110*7348b5c5SDavid van Moolenbroek localflow, /* we handle flow control locally */
111*7348b5c5SDavid van Moolenbroek restartany, /* if flow control enabled, restart on any character */
112*7348b5c5SDavid van Moolenbroek localchars, /* we recognize interrupt/quit */
113*7348b5c5SDavid van Moolenbroek donelclchars, /* the user has set "localchars" */
114*7348b5c5SDavid van Moolenbroek donebinarytoggle, /* the user has put us in binary */
115*7348b5c5SDavid van Moolenbroek dontlecho, /* do we suppress local echoing right now? */
116*7348b5c5SDavid van Moolenbroek globalmode,
117*7348b5c5SDavid van Moolenbroek doaddrlookup = 1, /* do a reverse address lookup? */
118*7348b5c5SDavid van Moolenbroek clienteof = 0;
119*7348b5c5SDavid van Moolenbroek
120*7348b5c5SDavid van Moolenbroek char *prompt = 0;
121*7348b5c5SDavid van Moolenbroek
122*7348b5c5SDavid van Moolenbroek cc_t escape;
123*7348b5c5SDavid van Moolenbroek cc_t rlogin;
124*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
125*7348b5c5SDavid van Moolenbroek cc_t echoc;
126*7348b5c5SDavid van Moolenbroek #endif
127*7348b5c5SDavid van Moolenbroek
128*7348b5c5SDavid van Moolenbroek /*
129*7348b5c5SDavid van Moolenbroek * Telnet receiver states for fsm
130*7348b5c5SDavid van Moolenbroek */
131*7348b5c5SDavid van Moolenbroek #define TS_DATA 0
132*7348b5c5SDavid van Moolenbroek #define TS_IAC 1
133*7348b5c5SDavid van Moolenbroek #define TS_WILL 2
134*7348b5c5SDavid van Moolenbroek #define TS_WONT 3
135*7348b5c5SDavid van Moolenbroek #define TS_DO 4
136*7348b5c5SDavid van Moolenbroek #define TS_DONT 5
137*7348b5c5SDavid van Moolenbroek #define TS_CR 6
138*7348b5c5SDavid van Moolenbroek #define TS_SB 7 /* sub-option collection */
139*7348b5c5SDavid van Moolenbroek #define TS_SE 8 /* looking for sub-option end */
140*7348b5c5SDavid van Moolenbroek
141*7348b5c5SDavid van Moolenbroek static int telrcv_state;
142*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
143*7348b5c5SDavid van Moolenbroek unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
144*7348b5c5SDavid van Moolenbroek #else
145*7348b5c5SDavid van Moolenbroek # define telopt_environ TELOPT_NEW_ENVIRON
146*7348b5c5SDavid van Moolenbroek #endif
147*7348b5c5SDavid van Moolenbroek
148*7348b5c5SDavid van Moolenbroek jmp_buf toplevel = { 0 };
149*7348b5c5SDavid van Moolenbroek
150*7348b5c5SDavid van Moolenbroek int flushline;
151*7348b5c5SDavid van Moolenbroek int linemode;
152*7348b5c5SDavid van Moolenbroek
153*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
154*7348b5c5SDavid van Moolenbroek int kludgelinemode = 1;
155*7348b5c5SDavid van Moolenbroek #endif
156*7348b5c5SDavid van Moolenbroek
157*7348b5c5SDavid van Moolenbroek static void dooption(int);
158*7348b5c5SDavid van Moolenbroek static void dontoption(int);
159*7348b5c5SDavid van Moolenbroek static void suboption(void);
160*7348b5c5SDavid van Moolenbroek static int telsnd(void);
161*7348b5c5SDavid van Moolenbroek static void netclear(void);
162*7348b5c5SDavid van Moolenbroek static void doflush(void);
163*7348b5c5SDavid van Moolenbroek
164*7348b5c5SDavid van Moolenbroek /*
165*7348b5c5SDavid van Moolenbroek * The following are some clocks used to decide how to interpret
166*7348b5c5SDavid van Moolenbroek * the relationship between various variables.
167*7348b5c5SDavid van Moolenbroek */
168*7348b5c5SDavid van Moolenbroek
169*7348b5c5SDavid van Moolenbroek Clocks clocks;
170*7348b5c5SDavid van Moolenbroek
171*7348b5c5SDavid van Moolenbroek #ifdef notdef
172*7348b5c5SDavid van Moolenbroek Modelist modelist[] = {
173*7348b5c5SDavid van Moolenbroek { "telnet command mode", COMMAND_LINE },
174*7348b5c5SDavid van Moolenbroek { "character-at-a-time mode", 0 },
175*7348b5c5SDavid van Moolenbroek { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
176*7348b5c5SDavid van Moolenbroek { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
177*7348b5c5SDavid van Moolenbroek { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
178*7348b5c5SDavid van Moolenbroek { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
179*7348b5c5SDavid van Moolenbroek { "3270 mode", 0 },
180*7348b5c5SDavid van Moolenbroek };
181*7348b5c5SDavid van Moolenbroek #endif
182*7348b5c5SDavid van Moolenbroek
183*7348b5c5SDavid van Moolenbroek
184*7348b5c5SDavid van Moolenbroek /*
185*7348b5c5SDavid van Moolenbroek * Initialize telnet environment.
186*7348b5c5SDavid van Moolenbroek */
187*7348b5c5SDavid van Moolenbroek
188*7348b5c5SDavid van Moolenbroek void
init_telnet(void)189*7348b5c5SDavid van Moolenbroek init_telnet(void)
190*7348b5c5SDavid van Moolenbroek {
191*7348b5c5SDavid van Moolenbroek env_init();
192*7348b5c5SDavid van Moolenbroek
193*7348b5c5SDavid van Moolenbroek SB_CLEAR();
194*7348b5c5SDavid van Moolenbroek ClearArray(options);
195*7348b5c5SDavid van Moolenbroek
196*7348b5c5SDavid van Moolenbroek connected = In3270 = ISend = localflow = donebinarytoggle = 0;
197*7348b5c5SDavid van Moolenbroek #if defined(AUTHENTICATION) || defined(ENCRYPTION)
198*7348b5c5SDavid van Moolenbroek auth_encrypt_connect(connected);
199*7348b5c5SDavid van Moolenbroek #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
200*7348b5c5SDavid van Moolenbroek restartany = -1;
201*7348b5c5SDavid van Moolenbroek
202*7348b5c5SDavid van Moolenbroek SYNCHing = 0;
203*7348b5c5SDavid van Moolenbroek
204*7348b5c5SDavid van Moolenbroek /* Don't change NetTrace */
205*7348b5c5SDavid van Moolenbroek
206*7348b5c5SDavid van Moolenbroek escape = CONTROL(']');
207*7348b5c5SDavid van Moolenbroek rlogin = _POSIX_VDISABLE;
208*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
209*7348b5c5SDavid van Moolenbroek echoc = CONTROL('E');
210*7348b5c5SDavid van Moolenbroek #endif
211*7348b5c5SDavid van Moolenbroek
212*7348b5c5SDavid van Moolenbroek flushline = 1;
213*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
214*7348b5c5SDavid van Moolenbroek }
215*7348b5c5SDavid van Moolenbroek
216*7348b5c5SDavid van Moolenbroek
217*7348b5c5SDavid van Moolenbroek #ifdef notdef
218*7348b5c5SDavid van Moolenbroek #include <stdarg.h>
219*7348b5c5SDavid van Moolenbroek
220*7348b5c5SDavid van Moolenbroek /*VARARGS*/
221*7348b5c5SDavid van Moolenbroek static void
printring(Ring * ring,char * format,...)222*7348b5c5SDavid van Moolenbroek printring(Ring *ring, char *format, ...)
223*7348b5c5SDavid van Moolenbroek va_dcl
224*7348b5c5SDavid van Moolenbroek {
225*7348b5c5SDavid van Moolenbroek va_list ap;
226*7348b5c5SDavid van Moolenbroek char buffer[100]; /* where things go */
227*7348b5c5SDavid van Moolenbroek char *ptr;
228*7348b5c5SDavid van Moolenbroek char *string;
229*7348b5c5SDavid van Moolenbroek int i;
230*7348b5c5SDavid van Moolenbroek
231*7348b5c5SDavid van Moolenbroek va_start(ap, format);
232*7348b5c5SDavid van Moolenbroek
233*7348b5c5SDavid van Moolenbroek ptr = buffer;
234*7348b5c5SDavid van Moolenbroek
235*7348b5c5SDavid van Moolenbroek while ((i = *format++) != 0) {
236*7348b5c5SDavid van Moolenbroek if (i == '%') {
237*7348b5c5SDavid van Moolenbroek i = *format++;
238*7348b5c5SDavid van Moolenbroek switch (i) {
239*7348b5c5SDavid van Moolenbroek case 'c':
240*7348b5c5SDavid van Moolenbroek *ptr++ = va_arg(ap, int);
241*7348b5c5SDavid van Moolenbroek break;
242*7348b5c5SDavid van Moolenbroek case 's':
243*7348b5c5SDavid van Moolenbroek string = va_arg(ap, char *);
244*7348b5c5SDavid van Moolenbroek ring_supply_data(ring, buffer, ptr-buffer);
245*7348b5c5SDavid van Moolenbroek ring_supply_data(ring, string, strlen(string));
246*7348b5c5SDavid van Moolenbroek ptr = buffer;
247*7348b5c5SDavid van Moolenbroek break;
248*7348b5c5SDavid van Moolenbroek case 0:
249*7348b5c5SDavid van Moolenbroek ExitString("printring: trailing %%.\n", 1);
250*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
251*7348b5c5SDavid van Moolenbroek default:
252*7348b5c5SDavid van Moolenbroek ExitString("printring: unknown format character.\n", 1);
253*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
254*7348b5c5SDavid van Moolenbroek }
255*7348b5c5SDavid van Moolenbroek } else {
256*7348b5c5SDavid van Moolenbroek *ptr++ = i;
257*7348b5c5SDavid van Moolenbroek }
258*7348b5c5SDavid van Moolenbroek }
259*7348b5c5SDavid van Moolenbroek va_end(ap);
260*7348b5c5SDavid van Moolenbroek ring_supply_data(ring, buffer, ptr-buffer);
261*7348b5c5SDavid van Moolenbroek }
262*7348b5c5SDavid van Moolenbroek #endif
263*7348b5c5SDavid van Moolenbroek
264*7348b5c5SDavid van Moolenbroek /*
265*7348b5c5SDavid van Moolenbroek * These routines are in charge of sending option negotiations
266*7348b5c5SDavid van Moolenbroek * to the other side.
267*7348b5c5SDavid van Moolenbroek *
268*7348b5c5SDavid van Moolenbroek * The basic idea is that we send the negotiation if either side
269*7348b5c5SDavid van Moolenbroek * is in disagreement as to what the current state should be.
270*7348b5c5SDavid van Moolenbroek */
271*7348b5c5SDavid van Moolenbroek
272*7348b5c5SDavid van Moolenbroek void
send_do(int c,int init)273*7348b5c5SDavid van Moolenbroek send_do(int c, int init)
274*7348b5c5SDavid van Moolenbroek {
275*7348b5c5SDavid van Moolenbroek if (init) {
276*7348b5c5SDavid van Moolenbroek if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
277*7348b5c5SDavid van Moolenbroek my_want_state_is_do(c))
278*7348b5c5SDavid van Moolenbroek return;
279*7348b5c5SDavid van Moolenbroek set_my_want_state_do(c);
280*7348b5c5SDavid van Moolenbroek do_dont_resp[c]++;
281*7348b5c5SDavid van Moolenbroek }
282*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, DO);
283*7348b5c5SDavid van Moolenbroek NETADD(c);
284*7348b5c5SDavid van Moolenbroek printoption("SENT", DO, c);
285*7348b5c5SDavid van Moolenbroek }
286*7348b5c5SDavid van Moolenbroek
287*7348b5c5SDavid van Moolenbroek void
send_dont(int c,int init)288*7348b5c5SDavid van Moolenbroek send_dont(int c, int init)
289*7348b5c5SDavid van Moolenbroek {
290*7348b5c5SDavid van Moolenbroek if (init) {
291*7348b5c5SDavid van Moolenbroek if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
292*7348b5c5SDavid van Moolenbroek my_want_state_is_dont(c))
293*7348b5c5SDavid van Moolenbroek return;
294*7348b5c5SDavid van Moolenbroek set_my_want_state_dont(c);
295*7348b5c5SDavid van Moolenbroek do_dont_resp[c]++;
296*7348b5c5SDavid van Moolenbroek }
297*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, DONT);
298*7348b5c5SDavid van Moolenbroek NETADD(c);
299*7348b5c5SDavid van Moolenbroek printoption("SENT", DONT, c);
300*7348b5c5SDavid van Moolenbroek }
301*7348b5c5SDavid van Moolenbroek
302*7348b5c5SDavid van Moolenbroek void
send_will(int c,int init)303*7348b5c5SDavid van Moolenbroek send_will(int c, int init)
304*7348b5c5SDavid van Moolenbroek {
305*7348b5c5SDavid van Moolenbroek if (init) {
306*7348b5c5SDavid van Moolenbroek if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
307*7348b5c5SDavid van Moolenbroek my_want_state_is_will(c))
308*7348b5c5SDavid van Moolenbroek return;
309*7348b5c5SDavid van Moolenbroek set_my_want_state_will(c);
310*7348b5c5SDavid van Moolenbroek will_wont_resp[c]++;
311*7348b5c5SDavid van Moolenbroek }
312*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, WILL);
313*7348b5c5SDavid van Moolenbroek NETADD(c);
314*7348b5c5SDavid van Moolenbroek printoption("SENT", WILL, c);
315*7348b5c5SDavid van Moolenbroek }
316*7348b5c5SDavid van Moolenbroek
317*7348b5c5SDavid van Moolenbroek void
send_wont(int c,int init)318*7348b5c5SDavid van Moolenbroek send_wont(int c, int init)
319*7348b5c5SDavid van Moolenbroek {
320*7348b5c5SDavid van Moolenbroek if (init) {
321*7348b5c5SDavid van Moolenbroek if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
322*7348b5c5SDavid van Moolenbroek my_want_state_is_wont(c))
323*7348b5c5SDavid van Moolenbroek return;
324*7348b5c5SDavid van Moolenbroek set_my_want_state_wont(c);
325*7348b5c5SDavid van Moolenbroek will_wont_resp[c]++;
326*7348b5c5SDavid van Moolenbroek }
327*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, WONT);
328*7348b5c5SDavid van Moolenbroek NETADD(c);
329*7348b5c5SDavid van Moolenbroek printoption("SENT", WONT, c);
330*7348b5c5SDavid van Moolenbroek }
331*7348b5c5SDavid van Moolenbroek
332*7348b5c5SDavid van Moolenbroek
333*7348b5c5SDavid van Moolenbroek void
willoption(int option)334*7348b5c5SDavid van Moolenbroek willoption(int option)
335*7348b5c5SDavid van Moolenbroek {
336*7348b5c5SDavid van Moolenbroek int new_state_ok = 0;
337*7348b5c5SDavid van Moolenbroek
338*7348b5c5SDavid van Moolenbroek if (do_dont_resp[option]) {
339*7348b5c5SDavid van Moolenbroek --do_dont_resp[option];
340*7348b5c5SDavid van Moolenbroek if (do_dont_resp[option] && my_state_is_do(option))
341*7348b5c5SDavid van Moolenbroek --do_dont_resp[option];
342*7348b5c5SDavid van Moolenbroek }
343*7348b5c5SDavid van Moolenbroek
344*7348b5c5SDavid van Moolenbroek if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
345*7348b5c5SDavid van Moolenbroek
346*7348b5c5SDavid van Moolenbroek switch (option) {
347*7348b5c5SDavid van Moolenbroek
348*7348b5c5SDavid van Moolenbroek case TELOPT_ECHO:
349*7348b5c5SDavid van Moolenbroek # if defined(TN3270)
350*7348b5c5SDavid van Moolenbroek /*
351*7348b5c5SDavid van Moolenbroek * The following is a pain in the rear-end.
352*7348b5c5SDavid van Moolenbroek * Various IBM servers (some versions of Wiscnet,
353*7348b5c5SDavid van Moolenbroek * possibly Fibronics/Spartacus, and who knows who
354*7348b5c5SDavid van Moolenbroek * else) will NOT allow us to send "DO SGA" too early
355*7348b5c5SDavid van Moolenbroek * in the setup proceedings. On the other hand,
356*7348b5c5SDavid van Moolenbroek * 4.2 servers (telnetd) won't set SGA correctly.
357*7348b5c5SDavid van Moolenbroek * So, we are stuck. Empirically (but, based on
358*7348b5c5SDavid van Moolenbroek * a VERY small sample), the IBM servers don't send
359*7348b5c5SDavid van Moolenbroek * out anything about ECHO, so we postpone our sending
360*7348b5c5SDavid van Moolenbroek * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
361*7348b5c5SDavid van Moolenbroek * DO send).
362*7348b5c5SDavid van Moolenbroek */
363*7348b5c5SDavid van Moolenbroek {
364*7348b5c5SDavid van Moolenbroek if (askedSGA == 0) {
365*7348b5c5SDavid van Moolenbroek askedSGA = 1;
366*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_SGA))
367*7348b5c5SDavid van Moolenbroek send_do(TELOPT_SGA, 1);
368*7348b5c5SDavid van Moolenbroek }
369*7348b5c5SDavid van Moolenbroek }
370*7348b5c5SDavid van Moolenbroek /* Fall through */
371*7348b5c5SDavid van Moolenbroek case TELOPT_EOR:
372*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
373*7348b5c5SDavid van Moolenbroek case TELOPT_BINARY:
374*7348b5c5SDavid van Moolenbroek case TELOPT_SGA:
375*7348b5c5SDavid van Moolenbroek settimer(modenegotiated);
376*7348b5c5SDavid van Moolenbroek /* FALL THROUGH */
377*7348b5c5SDavid van Moolenbroek case TELOPT_STATUS:
378*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
379*7348b5c5SDavid van Moolenbroek case TELOPT_AUTHENTICATION:
380*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
381*7348b5c5SDavid van Moolenbroek case TELOPT_ENCRYPT:
382*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
383*7348b5c5SDavid van Moolenbroek #endif
384*7348b5c5SDavid van Moolenbroek new_state_ok = 1;
385*7348b5c5SDavid van Moolenbroek break;
386*7348b5c5SDavid van Moolenbroek
387*7348b5c5SDavid van Moolenbroek case TELOPT_TM:
388*7348b5c5SDavid van Moolenbroek if (flushout)
389*7348b5c5SDavid van Moolenbroek flushout = 0;
390*7348b5c5SDavid van Moolenbroek /*
391*7348b5c5SDavid van Moolenbroek * Special case for TM. If we get back a WILL,
392*7348b5c5SDavid van Moolenbroek * pretend we got back a WONT.
393*7348b5c5SDavid van Moolenbroek */
394*7348b5c5SDavid van Moolenbroek set_my_want_state_dont(option);
395*7348b5c5SDavid van Moolenbroek set_my_state_dont(option);
396*7348b5c5SDavid van Moolenbroek return; /* Never reply to TM will's/wont's */
397*7348b5c5SDavid van Moolenbroek
398*7348b5c5SDavid van Moolenbroek case TELOPT_LINEMODE:
399*7348b5c5SDavid van Moolenbroek default:
400*7348b5c5SDavid van Moolenbroek break;
401*7348b5c5SDavid van Moolenbroek }
402*7348b5c5SDavid van Moolenbroek
403*7348b5c5SDavid van Moolenbroek if (new_state_ok) {
404*7348b5c5SDavid van Moolenbroek set_my_want_state_do(option);
405*7348b5c5SDavid van Moolenbroek send_do(option, 0);
406*7348b5c5SDavid van Moolenbroek setconnmode(0); /* possibly set new tty mode */
407*7348b5c5SDavid van Moolenbroek } else {
408*7348b5c5SDavid van Moolenbroek do_dont_resp[option]++;
409*7348b5c5SDavid van Moolenbroek send_dont(option, 0);
410*7348b5c5SDavid van Moolenbroek }
411*7348b5c5SDavid van Moolenbroek }
412*7348b5c5SDavid van Moolenbroek set_my_state_do(option);
413*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
414*7348b5c5SDavid van Moolenbroek if (option == TELOPT_ENCRYPT)
415*7348b5c5SDavid van Moolenbroek encrypt_send_support();
416*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
417*7348b5c5SDavid van Moolenbroek }
418*7348b5c5SDavid van Moolenbroek
419*7348b5c5SDavid van Moolenbroek void
wontoption(int option)420*7348b5c5SDavid van Moolenbroek wontoption(int option)
421*7348b5c5SDavid van Moolenbroek {
422*7348b5c5SDavid van Moolenbroek if (do_dont_resp[option]) {
423*7348b5c5SDavid van Moolenbroek --do_dont_resp[option];
424*7348b5c5SDavid van Moolenbroek if (do_dont_resp[option] && my_state_is_dont(option))
425*7348b5c5SDavid van Moolenbroek --do_dont_resp[option];
426*7348b5c5SDavid van Moolenbroek }
427*7348b5c5SDavid van Moolenbroek
428*7348b5c5SDavid van Moolenbroek if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
429*7348b5c5SDavid van Moolenbroek
430*7348b5c5SDavid van Moolenbroek switch (option) {
431*7348b5c5SDavid van Moolenbroek
432*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
433*7348b5c5SDavid van Moolenbroek case TELOPT_SGA:
434*7348b5c5SDavid van Moolenbroek if (!kludgelinemode)
435*7348b5c5SDavid van Moolenbroek break;
436*7348b5c5SDavid van Moolenbroek /* FALL THROUGH */
437*7348b5c5SDavid van Moolenbroek #endif
438*7348b5c5SDavid van Moolenbroek case TELOPT_ECHO:
439*7348b5c5SDavid van Moolenbroek settimer(modenegotiated);
440*7348b5c5SDavid van Moolenbroek break;
441*7348b5c5SDavid van Moolenbroek
442*7348b5c5SDavid van Moolenbroek case TELOPT_TM:
443*7348b5c5SDavid van Moolenbroek if (flushout)
444*7348b5c5SDavid van Moolenbroek flushout = 0;
445*7348b5c5SDavid van Moolenbroek set_my_want_state_dont(option);
446*7348b5c5SDavid van Moolenbroek set_my_state_dont(option);
447*7348b5c5SDavid van Moolenbroek return; /* Never reply to TM will's/wont's */
448*7348b5c5SDavid van Moolenbroek
449*7348b5c5SDavid van Moolenbroek default:
450*7348b5c5SDavid van Moolenbroek break;
451*7348b5c5SDavid van Moolenbroek }
452*7348b5c5SDavid van Moolenbroek set_my_want_state_dont(option);
453*7348b5c5SDavid van Moolenbroek if (my_state_is_do(option))
454*7348b5c5SDavid van Moolenbroek send_dont(option, 0);
455*7348b5c5SDavid van Moolenbroek setconnmode(0); /* Set new tty mode */
456*7348b5c5SDavid van Moolenbroek } else if (option == TELOPT_TM) {
457*7348b5c5SDavid van Moolenbroek /*
458*7348b5c5SDavid van Moolenbroek * Special case for TM.
459*7348b5c5SDavid van Moolenbroek */
460*7348b5c5SDavid van Moolenbroek if (flushout)
461*7348b5c5SDavid van Moolenbroek flushout = 0;
462*7348b5c5SDavid van Moolenbroek set_my_want_state_dont(option);
463*7348b5c5SDavid van Moolenbroek }
464*7348b5c5SDavid van Moolenbroek set_my_state_dont(option);
465*7348b5c5SDavid van Moolenbroek }
466*7348b5c5SDavid van Moolenbroek
467*7348b5c5SDavid van Moolenbroek static void
dooption(int option)468*7348b5c5SDavid van Moolenbroek dooption(int option)
469*7348b5c5SDavid van Moolenbroek {
470*7348b5c5SDavid van Moolenbroek int new_state_ok = 0;
471*7348b5c5SDavid van Moolenbroek
472*7348b5c5SDavid van Moolenbroek if (will_wont_resp[option]) {
473*7348b5c5SDavid van Moolenbroek --will_wont_resp[option];
474*7348b5c5SDavid van Moolenbroek if (will_wont_resp[option] && my_state_is_will(option))
475*7348b5c5SDavid van Moolenbroek --will_wont_resp[option];
476*7348b5c5SDavid van Moolenbroek }
477*7348b5c5SDavid van Moolenbroek
478*7348b5c5SDavid van Moolenbroek if (will_wont_resp[option] == 0) {
479*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(option)) {
480*7348b5c5SDavid van Moolenbroek
481*7348b5c5SDavid van Moolenbroek switch (option) {
482*7348b5c5SDavid van Moolenbroek
483*7348b5c5SDavid van Moolenbroek case TELOPT_TM:
484*7348b5c5SDavid van Moolenbroek /*
485*7348b5c5SDavid van Moolenbroek * Special case for TM. We send a WILL, but pretend
486*7348b5c5SDavid van Moolenbroek * we sent WONT.
487*7348b5c5SDavid van Moolenbroek */
488*7348b5c5SDavid van Moolenbroek send_will(option, 0);
489*7348b5c5SDavid van Moolenbroek set_my_want_state_wont(TELOPT_TM);
490*7348b5c5SDavid van Moolenbroek set_my_state_wont(TELOPT_TM);
491*7348b5c5SDavid van Moolenbroek return;
492*7348b5c5SDavid van Moolenbroek
493*7348b5c5SDavid van Moolenbroek # if defined(TN3270)
494*7348b5c5SDavid van Moolenbroek case TELOPT_EOR: /* end of record */
495*7348b5c5SDavid van Moolenbroek # endif /* defined(TN3270) */
496*7348b5c5SDavid van Moolenbroek case TELOPT_BINARY: /* binary mode */
497*7348b5c5SDavid van Moolenbroek case TELOPT_NAWS: /* window size */
498*7348b5c5SDavid van Moolenbroek case TELOPT_TSPEED: /* terminal speed */
499*7348b5c5SDavid van Moolenbroek case TELOPT_LFLOW: /* local flow control */
500*7348b5c5SDavid van Moolenbroek case TELOPT_TTYPE: /* terminal type option */
501*7348b5c5SDavid van Moolenbroek case TELOPT_SGA: /* no big deal */
502*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
503*7348b5c5SDavid van Moolenbroek case TELOPT_ENCRYPT: /* encryption variable option */
504*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
505*7348b5c5SDavid van Moolenbroek new_state_ok = 1;
506*7348b5c5SDavid van Moolenbroek break;
507*7348b5c5SDavid van Moolenbroek
508*7348b5c5SDavid van Moolenbroek case TELOPT_NEW_ENVIRON: /* New environment variable option */
509*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
510*7348b5c5SDavid van Moolenbroek if (my_state_is_will(TELOPT_OLD_ENVIRON))
511*7348b5c5SDavid van Moolenbroek send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
512*7348b5c5SDavid van Moolenbroek goto env_common;
513*7348b5c5SDavid van Moolenbroek case TELOPT_OLD_ENVIRON: /* Old environment variable option */
514*7348b5c5SDavid van Moolenbroek if (my_state_is_will(TELOPT_NEW_ENVIRON))
515*7348b5c5SDavid van Moolenbroek break; /* Don't enable if new one is in use! */
516*7348b5c5SDavid van Moolenbroek env_common:
517*7348b5c5SDavid van Moolenbroek telopt_environ = option;
518*7348b5c5SDavid van Moolenbroek #endif
519*7348b5c5SDavid van Moolenbroek new_state_ok = 1;
520*7348b5c5SDavid van Moolenbroek break;
521*7348b5c5SDavid van Moolenbroek
522*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
523*7348b5c5SDavid van Moolenbroek case TELOPT_AUTHENTICATION:
524*7348b5c5SDavid van Moolenbroek if (autologin)
525*7348b5c5SDavid van Moolenbroek new_state_ok = 1;
526*7348b5c5SDavid van Moolenbroek break;
527*7348b5c5SDavid van Moolenbroek #endif
528*7348b5c5SDavid van Moolenbroek
529*7348b5c5SDavid van Moolenbroek case TELOPT_XDISPLOC: /* X Display location */
530*7348b5c5SDavid van Moolenbroek if (env_getvalue((const unsigned char *)"DISPLAY"))
531*7348b5c5SDavid van Moolenbroek new_state_ok = 1;
532*7348b5c5SDavid van Moolenbroek break;
533*7348b5c5SDavid van Moolenbroek
534*7348b5c5SDavid van Moolenbroek case TELOPT_LINEMODE:
535*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
536*7348b5c5SDavid van Moolenbroek kludgelinemode = 0;
537*7348b5c5SDavid van Moolenbroek send_do(TELOPT_SGA, 1);
538*7348b5c5SDavid van Moolenbroek #endif
539*7348b5c5SDavid van Moolenbroek set_my_want_state_will(TELOPT_LINEMODE);
540*7348b5c5SDavid van Moolenbroek send_will(option, 0);
541*7348b5c5SDavid van Moolenbroek set_my_state_will(TELOPT_LINEMODE);
542*7348b5c5SDavid van Moolenbroek slc_init();
543*7348b5c5SDavid van Moolenbroek return;
544*7348b5c5SDavid van Moolenbroek
545*7348b5c5SDavid van Moolenbroek case TELOPT_ECHO: /* We're never going to echo... */
546*7348b5c5SDavid van Moolenbroek default:
547*7348b5c5SDavid van Moolenbroek break;
548*7348b5c5SDavid van Moolenbroek }
549*7348b5c5SDavid van Moolenbroek
550*7348b5c5SDavid van Moolenbroek if (new_state_ok) {
551*7348b5c5SDavid van Moolenbroek set_my_want_state_will(option);
552*7348b5c5SDavid van Moolenbroek send_will(option, 0);
553*7348b5c5SDavid van Moolenbroek setconnmode(0); /* Set new tty mode */
554*7348b5c5SDavid van Moolenbroek } else {
555*7348b5c5SDavid van Moolenbroek will_wont_resp[option]++;
556*7348b5c5SDavid van Moolenbroek send_wont(option, 0);
557*7348b5c5SDavid van Moolenbroek }
558*7348b5c5SDavid van Moolenbroek } else {
559*7348b5c5SDavid van Moolenbroek /*
560*7348b5c5SDavid van Moolenbroek * Handle options that need more things done after the
561*7348b5c5SDavid van Moolenbroek * other side has acknowledged the option.
562*7348b5c5SDavid van Moolenbroek */
563*7348b5c5SDavid van Moolenbroek switch (option) {
564*7348b5c5SDavid van Moolenbroek case TELOPT_LINEMODE:
565*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
566*7348b5c5SDavid van Moolenbroek kludgelinemode = 0;
567*7348b5c5SDavid van Moolenbroek send_do(TELOPT_SGA, 1);
568*7348b5c5SDavid van Moolenbroek #endif
569*7348b5c5SDavid van Moolenbroek set_my_state_will(option);
570*7348b5c5SDavid van Moolenbroek slc_init();
571*7348b5c5SDavid van Moolenbroek send_do(TELOPT_SGA, 0);
572*7348b5c5SDavid van Moolenbroek return;
573*7348b5c5SDavid van Moolenbroek }
574*7348b5c5SDavid van Moolenbroek }
575*7348b5c5SDavid van Moolenbroek }
576*7348b5c5SDavid van Moolenbroek set_my_state_will(option);
577*7348b5c5SDavid van Moolenbroek }
578*7348b5c5SDavid van Moolenbroek
579*7348b5c5SDavid van Moolenbroek static void
dontoption(int option)580*7348b5c5SDavid van Moolenbroek dontoption(int option)
581*7348b5c5SDavid van Moolenbroek {
582*7348b5c5SDavid van Moolenbroek
583*7348b5c5SDavid van Moolenbroek if (will_wont_resp[option]) {
584*7348b5c5SDavid van Moolenbroek --will_wont_resp[option];
585*7348b5c5SDavid van Moolenbroek if (will_wont_resp[option] && my_state_is_wont(option))
586*7348b5c5SDavid van Moolenbroek --will_wont_resp[option];
587*7348b5c5SDavid van Moolenbroek }
588*7348b5c5SDavid van Moolenbroek
589*7348b5c5SDavid van Moolenbroek if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
590*7348b5c5SDavid van Moolenbroek switch (option) {
591*7348b5c5SDavid van Moolenbroek case TELOPT_LINEMODE:
592*7348b5c5SDavid van Moolenbroek linemode = 0; /* put us back to the default state */
593*7348b5c5SDavid van Moolenbroek break;
594*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
595*7348b5c5SDavid van Moolenbroek case TELOPT_NEW_ENVIRON:
596*7348b5c5SDavid van Moolenbroek /*
597*7348b5c5SDavid van Moolenbroek * The new environ option wasn't recognized, try
598*7348b5c5SDavid van Moolenbroek * the old one.
599*7348b5c5SDavid van Moolenbroek */
600*7348b5c5SDavid van Moolenbroek send_will(TELOPT_OLD_ENVIRON, 1);
601*7348b5c5SDavid van Moolenbroek telopt_environ = TELOPT_OLD_ENVIRON;
602*7348b5c5SDavid van Moolenbroek break;
603*7348b5c5SDavid van Moolenbroek #endif
604*7348b5c5SDavid van Moolenbroek }
605*7348b5c5SDavid van Moolenbroek /* we always accept a DONT */
606*7348b5c5SDavid van Moolenbroek set_my_want_state_wont(option);
607*7348b5c5SDavid van Moolenbroek if (my_state_is_will(option))
608*7348b5c5SDavid van Moolenbroek send_wont(option, 0);
609*7348b5c5SDavid van Moolenbroek setconnmode(0); /* Set new tty mode */
610*7348b5c5SDavid van Moolenbroek }
611*7348b5c5SDavid van Moolenbroek set_my_state_wont(option);
612*7348b5c5SDavid van Moolenbroek }
613*7348b5c5SDavid van Moolenbroek
614*7348b5c5SDavid van Moolenbroek /*
615*7348b5c5SDavid van Moolenbroek * Given a buffer returned by tgetent(), this routine will turn
616*7348b5c5SDavid van Moolenbroek * the pipe separated list of names in the buffer into an array
617*7348b5c5SDavid van Moolenbroek * of pointers to null terminated names. We toss out any bad,
618*7348b5c5SDavid van Moolenbroek * duplicate, or verbose names (names with spaces).
619*7348b5c5SDavid van Moolenbroek */
620*7348b5c5SDavid van Moolenbroek
621*7348b5c5SDavid van Moolenbroek static char name_unknown[] = "UNKNOWN";
622*7348b5c5SDavid van Moolenbroek static char *unknown[] = { 0, 0 };
623*7348b5c5SDavid van Moolenbroek
624*7348b5c5SDavid van Moolenbroek char **
mklist(char * buf,char * name)625*7348b5c5SDavid van Moolenbroek mklist(char *buf, char *name)
626*7348b5c5SDavid van Moolenbroek {
627*7348b5c5SDavid van Moolenbroek int n;
628*7348b5c5SDavid van Moolenbroek char c, *cp, **argvp, *cp2, **argv, **avt;
629*7348b5c5SDavid van Moolenbroek
630*7348b5c5SDavid van Moolenbroek if (name) {
631*7348b5c5SDavid van Moolenbroek if ((int)strlen(name) > 40) {
632*7348b5c5SDavid van Moolenbroek name = 0;
633*7348b5c5SDavid van Moolenbroek unknown[0] = name_unknown;
634*7348b5c5SDavid van Moolenbroek } else {
635*7348b5c5SDavid van Moolenbroek unknown[0] = name;
636*7348b5c5SDavid van Moolenbroek upcase(name);
637*7348b5c5SDavid van Moolenbroek }
638*7348b5c5SDavid van Moolenbroek } else
639*7348b5c5SDavid van Moolenbroek unknown[0] = name_unknown;
640*7348b5c5SDavid van Moolenbroek /*
641*7348b5c5SDavid van Moolenbroek * Count up the number of names.
642*7348b5c5SDavid van Moolenbroek */
643*7348b5c5SDavid van Moolenbroek for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
644*7348b5c5SDavid van Moolenbroek if (*cp == '|')
645*7348b5c5SDavid van Moolenbroek n++;
646*7348b5c5SDavid van Moolenbroek }
647*7348b5c5SDavid van Moolenbroek /*
648*7348b5c5SDavid van Moolenbroek * Allocate an array to put the name pointers into
649*7348b5c5SDavid van Moolenbroek */
650*7348b5c5SDavid van Moolenbroek argv = (char **)malloc((n+3)*sizeof(char *));
651*7348b5c5SDavid van Moolenbroek if (argv == 0)
652*7348b5c5SDavid van Moolenbroek return(unknown);
653*7348b5c5SDavid van Moolenbroek
654*7348b5c5SDavid van Moolenbroek /*
655*7348b5c5SDavid van Moolenbroek * Fill up the array of pointers to names.
656*7348b5c5SDavid van Moolenbroek */
657*7348b5c5SDavid van Moolenbroek *argv = 0;
658*7348b5c5SDavid van Moolenbroek argvp = argv+1;
659*7348b5c5SDavid van Moolenbroek n = 0;
660*7348b5c5SDavid van Moolenbroek for (cp = cp2 = buf; (c = *cp); cp++) {
661*7348b5c5SDavid van Moolenbroek if (c == '|' || c == ':') {
662*7348b5c5SDavid van Moolenbroek *cp++ = '\0';
663*7348b5c5SDavid van Moolenbroek /*
664*7348b5c5SDavid van Moolenbroek * Skip entries that have spaces or are over 40
665*7348b5c5SDavid van Moolenbroek * characters long. If this is our environment
666*7348b5c5SDavid van Moolenbroek * name, then put it up front. Otherwise, as
667*7348b5c5SDavid van Moolenbroek * long as this is not a duplicate name (case
668*7348b5c5SDavid van Moolenbroek * insensitive) add it to the list.
669*7348b5c5SDavid van Moolenbroek */
670*7348b5c5SDavid van Moolenbroek if (n || (cp - cp2 > 41))
671*7348b5c5SDavid van Moolenbroek ;
672*7348b5c5SDavid van Moolenbroek else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
673*7348b5c5SDavid van Moolenbroek *argv = cp2;
674*7348b5c5SDavid van Moolenbroek else if (is_unique(cp2, argv+1, argvp))
675*7348b5c5SDavid van Moolenbroek *argvp++ = cp2;
676*7348b5c5SDavid van Moolenbroek if (c == ':')
677*7348b5c5SDavid van Moolenbroek break;
678*7348b5c5SDavid van Moolenbroek /*
679*7348b5c5SDavid van Moolenbroek * Skip multiple delimiters. Reset cp2 to
680*7348b5c5SDavid van Moolenbroek * the beginning of the next name. Reset n,
681*7348b5c5SDavid van Moolenbroek * the flag for names with spaces.
682*7348b5c5SDavid van Moolenbroek */
683*7348b5c5SDavid van Moolenbroek while ((c = *cp) == '|')
684*7348b5c5SDavid van Moolenbroek cp++;
685*7348b5c5SDavid van Moolenbroek cp2 = cp;
686*7348b5c5SDavid van Moolenbroek n = 0;
687*7348b5c5SDavid van Moolenbroek }
688*7348b5c5SDavid van Moolenbroek /*
689*7348b5c5SDavid van Moolenbroek * Skip entries with spaces or non-ascii values.
690*7348b5c5SDavid van Moolenbroek * Convert lower case letters to upper case.
691*7348b5c5SDavid van Moolenbroek */
692*7348b5c5SDavid van Moolenbroek if ((c == ' ') || !isascii(c))
693*7348b5c5SDavid van Moolenbroek n = 1;
694*7348b5c5SDavid van Moolenbroek else if (islower((unsigned char)c))
695*7348b5c5SDavid van Moolenbroek *cp = toupper((unsigned char)c);
696*7348b5c5SDavid van Moolenbroek }
697*7348b5c5SDavid van Moolenbroek
698*7348b5c5SDavid van Moolenbroek /*
699*7348b5c5SDavid van Moolenbroek * Check for an old V6 2 character name. If the second
700*7348b5c5SDavid van Moolenbroek * name points to the beginning of the buffer, and is
701*7348b5c5SDavid van Moolenbroek * only 2 characters long, move it to the end of the array.
702*7348b5c5SDavid van Moolenbroek */
703*7348b5c5SDavid van Moolenbroek if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
704*7348b5c5SDavid van Moolenbroek --argvp;
705*7348b5c5SDavid van Moolenbroek for (avt = &argv[1]; avt < argvp; avt++)
706*7348b5c5SDavid van Moolenbroek *avt = *(avt+1);
707*7348b5c5SDavid van Moolenbroek *argvp++ = buf;
708*7348b5c5SDavid van Moolenbroek }
709*7348b5c5SDavid van Moolenbroek
710*7348b5c5SDavid van Moolenbroek /*
711*7348b5c5SDavid van Moolenbroek * Duplicate last name, for TTYPE option, and null
712*7348b5c5SDavid van Moolenbroek * terminate the array. If we didn't find a match on
713*7348b5c5SDavid van Moolenbroek * our terminal name, put that name at the beginning.
714*7348b5c5SDavid van Moolenbroek */
715*7348b5c5SDavid van Moolenbroek cp = *(argvp-1);
716*7348b5c5SDavid van Moolenbroek *argvp++ = cp;
717*7348b5c5SDavid van Moolenbroek *argvp = 0;
718*7348b5c5SDavid van Moolenbroek
719*7348b5c5SDavid van Moolenbroek if (*argv == 0) {
720*7348b5c5SDavid van Moolenbroek if (name)
721*7348b5c5SDavid van Moolenbroek *argv = name;
722*7348b5c5SDavid van Moolenbroek else {
723*7348b5c5SDavid van Moolenbroek --argvp;
724*7348b5c5SDavid van Moolenbroek for (avt = argv; avt < argvp; avt++)
725*7348b5c5SDavid van Moolenbroek *avt = *(avt+1);
726*7348b5c5SDavid van Moolenbroek }
727*7348b5c5SDavid van Moolenbroek }
728*7348b5c5SDavid van Moolenbroek if (*argv)
729*7348b5c5SDavid van Moolenbroek return(argv);
730*7348b5c5SDavid van Moolenbroek else
731*7348b5c5SDavid van Moolenbroek return(unknown);
732*7348b5c5SDavid van Moolenbroek }
733*7348b5c5SDavid van Moolenbroek
734*7348b5c5SDavid van Moolenbroek int
is_unique(char * name,char ** as,char ** ae)735*7348b5c5SDavid van Moolenbroek is_unique(char *name, char **as, char **ae)
736*7348b5c5SDavid van Moolenbroek {
737*7348b5c5SDavid van Moolenbroek char **ap;
738*7348b5c5SDavid van Moolenbroek int n;
739*7348b5c5SDavid van Moolenbroek
740*7348b5c5SDavid van Moolenbroek n = strlen(name) + 1;
741*7348b5c5SDavid van Moolenbroek for (ap = as; ap < ae; ap++)
742*7348b5c5SDavid van Moolenbroek if (strncasecmp(*ap, name, n) == 0)
743*7348b5c5SDavid van Moolenbroek return(0);
744*7348b5c5SDavid van Moolenbroek return (1);
745*7348b5c5SDavid van Moolenbroek }
746*7348b5c5SDavid van Moolenbroek
747*7348b5c5SDavid van Moolenbroek #ifdef TERMCAP
748*7348b5c5SDavid van Moolenbroek char *termbuf;
749*7348b5c5SDavid van Moolenbroek
750*7348b5c5SDavid van Moolenbroek /*ARGSUSED*/
751*7348b5c5SDavid van Moolenbroek int
setupterm(char * tname,int fd,int * errp)752*7348b5c5SDavid van Moolenbroek setupterm(char *tname, int fd, int *errp)
753*7348b5c5SDavid van Moolenbroek {
754*7348b5c5SDavid van Moolenbroek char zz[1024], *zz_ptr;
755*7348b5c5SDavid van Moolenbroek char *ext_tc, *newptr;
756*7348b5c5SDavid van Moolenbroek size_t len;
757*7348b5c5SDavid van Moolenbroek
758*7348b5c5SDavid van Moolenbroek if ((termbuf = malloc(1024)) == NULL)
759*7348b5c5SDavid van Moolenbroek goto error;
760*7348b5c5SDavid van Moolenbroek
761*7348b5c5SDavid van Moolenbroek if (tgetent(termbuf, tname) == 1) {
762*7348b5c5SDavid van Moolenbroek /* check for ZZ capability, indicating termcap truncated */
763*7348b5c5SDavid van Moolenbroek zz_ptr = zz;
764*7348b5c5SDavid van Moolenbroek if (tgetstr("ZZ", &zz_ptr) != NULL) {
765*7348b5c5SDavid van Moolenbroek /* it was, fish back the full termcap */
766*7348b5c5SDavid van Moolenbroek sscanf(zz, "%p", &ext_tc);
767*7348b5c5SDavid van Moolenbroek len = strlen(ext_tc) + 1;
768*7348b5c5SDavid van Moolenbroek if ((newptr = realloc(termbuf, len)) == NULL)
769*7348b5c5SDavid van Moolenbroek goto error;
770*7348b5c5SDavid van Moolenbroek
771*7348b5c5SDavid van Moolenbroek memcpy(newptr, ext_tc, len);
772*7348b5c5SDavid van Moolenbroek termbuf = newptr;
773*7348b5c5SDavid van Moolenbroek }
774*7348b5c5SDavid van Moolenbroek
775*7348b5c5SDavid van Moolenbroek if (errp)
776*7348b5c5SDavid van Moolenbroek *errp = 1;
777*7348b5c5SDavid van Moolenbroek return(0);
778*7348b5c5SDavid van Moolenbroek }
779*7348b5c5SDavid van Moolenbroek error:
780*7348b5c5SDavid van Moolenbroek if (errp)
781*7348b5c5SDavid van Moolenbroek *errp = 0;
782*7348b5c5SDavid van Moolenbroek return(-1);
783*7348b5c5SDavid van Moolenbroek }
784*7348b5c5SDavid van Moolenbroek #else
785*7348b5c5SDavid van Moolenbroek #define termbuf ttytype
786*7348b5c5SDavid van Moolenbroek extern char ttytype[];
787*7348b5c5SDavid van Moolenbroek #endif
788*7348b5c5SDavid van Moolenbroek
789*7348b5c5SDavid van Moolenbroek int resettermname = 1;
790*7348b5c5SDavid van Moolenbroek
791*7348b5c5SDavid van Moolenbroek char *
gettermname(void)792*7348b5c5SDavid van Moolenbroek gettermname(void)
793*7348b5c5SDavid van Moolenbroek {
794*7348b5c5SDavid van Moolenbroek char *tname;
795*7348b5c5SDavid van Moolenbroek static char **tnamep = 0;
796*7348b5c5SDavid van Moolenbroek static char **next;
797*7348b5c5SDavid van Moolenbroek int err;
798*7348b5c5SDavid van Moolenbroek
799*7348b5c5SDavid van Moolenbroek if (resettermname) {
800*7348b5c5SDavid van Moolenbroek resettermname = 0;
801*7348b5c5SDavid van Moolenbroek if (tnamep && tnamep != unknown)
802*7348b5c5SDavid van Moolenbroek free(tnamep);
803*7348b5c5SDavid van Moolenbroek if ((tname = (char *)env_getvalue((const unsigned char *)"TERM")) &&
804*7348b5c5SDavid van Moolenbroek (setupterm(tname, 1, &err) == 0)) {
805*7348b5c5SDavid van Moolenbroek tnamep = mklist(termbuf, tname);
806*7348b5c5SDavid van Moolenbroek } else {
807*7348b5c5SDavid van Moolenbroek if (tname && ((int)strlen(tname) <= 40)) {
808*7348b5c5SDavid van Moolenbroek unknown[0] = tname;
809*7348b5c5SDavid van Moolenbroek upcase(tname);
810*7348b5c5SDavid van Moolenbroek } else
811*7348b5c5SDavid van Moolenbroek unknown[0] = name_unknown;
812*7348b5c5SDavid van Moolenbroek tnamep = unknown;
813*7348b5c5SDavid van Moolenbroek }
814*7348b5c5SDavid van Moolenbroek next = tnamep;
815*7348b5c5SDavid van Moolenbroek }
816*7348b5c5SDavid van Moolenbroek if (*next == 0)
817*7348b5c5SDavid van Moolenbroek next = tnamep;
818*7348b5c5SDavid van Moolenbroek return(*next++);
819*7348b5c5SDavid van Moolenbroek }
820*7348b5c5SDavid van Moolenbroek /*
821*7348b5c5SDavid van Moolenbroek * suboption()
822*7348b5c5SDavid van Moolenbroek *
823*7348b5c5SDavid van Moolenbroek * Look at the sub-option buffer, and try to be helpful to the other
824*7348b5c5SDavid van Moolenbroek * side.
825*7348b5c5SDavid van Moolenbroek *
826*7348b5c5SDavid van Moolenbroek * Currently we recognize:
827*7348b5c5SDavid van Moolenbroek *
828*7348b5c5SDavid van Moolenbroek * Terminal type, send request.
829*7348b5c5SDavid van Moolenbroek * Terminal speed (send request).
830*7348b5c5SDavid van Moolenbroek * Local flow control (is request).
831*7348b5c5SDavid van Moolenbroek * Linemode
832*7348b5c5SDavid van Moolenbroek */
833*7348b5c5SDavid van Moolenbroek
834*7348b5c5SDavid van Moolenbroek static void
suboption(void)835*7348b5c5SDavid van Moolenbroek suboption(void)
836*7348b5c5SDavid van Moolenbroek {
837*7348b5c5SDavid van Moolenbroek unsigned char subchar;
838*7348b5c5SDavid van Moolenbroek
839*7348b5c5SDavid van Moolenbroek printsub('<', subbuffer, SB_LEN()+2);
840*7348b5c5SDavid van Moolenbroek switch (subchar = SB_GET()) {
841*7348b5c5SDavid van Moolenbroek case TELOPT_TTYPE:
842*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_TTYPE))
843*7348b5c5SDavid van Moolenbroek return;
844*7348b5c5SDavid van Moolenbroek if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
845*7348b5c5SDavid van Moolenbroek return;
846*7348b5c5SDavid van Moolenbroek } else {
847*7348b5c5SDavid van Moolenbroek char *name;
848*7348b5c5SDavid van Moolenbroek unsigned char temp[50];
849*7348b5c5SDavid van Moolenbroek int len;
850*7348b5c5SDavid van Moolenbroek
851*7348b5c5SDavid van Moolenbroek #ifdef TN3270
852*7348b5c5SDavid van Moolenbroek if (tn3270_ttype()) {
853*7348b5c5SDavid van Moolenbroek return;
854*7348b5c5SDavid van Moolenbroek }
855*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
856*7348b5c5SDavid van Moolenbroek name = gettermname();
857*7348b5c5SDavid van Moolenbroek len = strlen(name) + 4 + 2;
858*7348b5c5SDavid van Moolenbroek if (len < NETROOM()) {
859*7348b5c5SDavid van Moolenbroek sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
860*7348b5c5SDavid van Moolenbroek TELQUAL_IS, name, IAC, SE);
861*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, temp, len);
862*7348b5c5SDavid van Moolenbroek printsub('>', &temp[2], len-2);
863*7348b5c5SDavid van Moolenbroek } else {
864*7348b5c5SDavid van Moolenbroek ExitString("No room in buffer for terminal type.\n", 1);
865*7348b5c5SDavid van Moolenbroek /*NOTREACHED*/
866*7348b5c5SDavid van Moolenbroek }
867*7348b5c5SDavid van Moolenbroek }
868*7348b5c5SDavid van Moolenbroek break;
869*7348b5c5SDavid van Moolenbroek case TELOPT_TSPEED:
870*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_TSPEED))
871*7348b5c5SDavid van Moolenbroek return;
872*7348b5c5SDavid van Moolenbroek if (SB_EOF())
873*7348b5c5SDavid van Moolenbroek return;
874*7348b5c5SDavid van Moolenbroek if (SB_GET() == TELQUAL_SEND) {
875*7348b5c5SDavid van Moolenbroek long osp, isp;
876*7348b5c5SDavid van Moolenbroek unsigned char temp[50];
877*7348b5c5SDavid van Moolenbroek int len;
878*7348b5c5SDavid van Moolenbroek
879*7348b5c5SDavid van Moolenbroek TerminalSpeeds(&isp, &osp);
880*7348b5c5SDavid van Moolenbroek
881*7348b5c5SDavid van Moolenbroek sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
882*7348b5c5SDavid van Moolenbroek TELQUAL_IS, osp, isp, IAC, SE);
883*7348b5c5SDavid van Moolenbroek len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
884*7348b5c5SDavid van Moolenbroek
885*7348b5c5SDavid van Moolenbroek if (len < NETROOM()) {
886*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, temp, len);
887*7348b5c5SDavid van Moolenbroek printsub('>', temp+2, len - 2);
888*7348b5c5SDavid van Moolenbroek }
889*7348b5c5SDavid van Moolenbroek /*@*/ else printf("lm_will: not enough room in buffer\n");
890*7348b5c5SDavid van Moolenbroek }
891*7348b5c5SDavid van Moolenbroek break;
892*7348b5c5SDavid van Moolenbroek case TELOPT_LFLOW:
893*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_LFLOW))
894*7348b5c5SDavid van Moolenbroek return;
895*7348b5c5SDavid van Moolenbroek if (SB_EOF())
896*7348b5c5SDavid van Moolenbroek return;
897*7348b5c5SDavid van Moolenbroek switch(SB_GET()) {
898*7348b5c5SDavid van Moolenbroek case LFLOW_RESTART_ANY:
899*7348b5c5SDavid van Moolenbroek restartany = 1;
900*7348b5c5SDavid van Moolenbroek break;
901*7348b5c5SDavid van Moolenbroek case LFLOW_RESTART_XON:
902*7348b5c5SDavid van Moolenbroek restartany = 0;
903*7348b5c5SDavid van Moolenbroek break;
904*7348b5c5SDavid van Moolenbroek case LFLOW_ON:
905*7348b5c5SDavid van Moolenbroek localflow = 1;
906*7348b5c5SDavid van Moolenbroek break;
907*7348b5c5SDavid van Moolenbroek case LFLOW_OFF:
908*7348b5c5SDavid van Moolenbroek localflow = 0;
909*7348b5c5SDavid van Moolenbroek break;
910*7348b5c5SDavid van Moolenbroek default:
911*7348b5c5SDavid van Moolenbroek return;
912*7348b5c5SDavid van Moolenbroek }
913*7348b5c5SDavid van Moolenbroek setcommandmode();
914*7348b5c5SDavid van Moolenbroek setconnmode(0);
915*7348b5c5SDavid van Moolenbroek break;
916*7348b5c5SDavid van Moolenbroek
917*7348b5c5SDavid van Moolenbroek case TELOPT_LINEMODE:
918*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_LINEMODE))
919*7348b5c5SDavid van Moolenbroek return;
920*7348b5c5SDavid van Moolenbroek if (SB_EOF())
921*7348b5c5SDavid van Moolenbroek return;
922*7348b5c5SDavid van Moolenbroek switch (SB_GET()) {
923*7348b5c5SDavid van Moolenbroek case WILL:
924*7348b5c5SDavid van Moolenbroek lm_will(subpointer, SB_LEN());
925*7348b5c5SDavid van Moolenbroek break;
926*7348b5c5SDavid van Moolenbroek case WONT:
927*7348b5c5SDavid van Moolenbroek lm_wont(subpointer, SB_LEN());
928*7348b5c5SDavid van Moolenbroek break;
929*7348b5c5SDavid van Moolenbroek case DO:
930*7348b5c5SDavid van Moolenbroek lm_do(subpointer, SB_LEN());
931*7348b5c5SDavid van Moolenbroek break;
932*7348b5c5SDavid van Moolenbroek case DONT:
933*7348b5c5SDavid van Moolenbroek lm_dont(subpointer, SB_LEN());
934*7348b5c5SDavid van Moolenbroek break;
935*7348b5c5SDavid van Moolenbroek case LM_SLC:
936*7348b5c5SDavid van Moolenbroek slc(subpointer, SB_LEN());
937*7348b5c5SDavid van Moolenbroek break;
938*7348b5c5SDavid van Moolenbroek case LM_MODE:
939*7348b5c5SDavid van Moolenbroek lm_mode(subpointer, SB_LEN(), 0);
940*7348b5c5SDavid van Moolenbroek break;
941*7348b5c5SDavid van Moolenbroek default:
942*7348b5c5SDavid van Moolenbroek break;
943*7348b5c5SDavid van Moolenbroek }
944*7348b5c5SDavid van Moolenbroek break;
945*7348b5c5SDavid van Moolenbroek
946*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
947*7348b5c5SDavid van Moolenbroek case TELOPT_OLD_ENVIRON:
948*7348b5c5SDavid van Moolenbroek #endif
949*7348b5c5SDavid van Moolenbroek case TELOPT_NEW_ENVIRON:
950*7348b5c5SDavid van Moolenbroek if (SB_EOF())
951*7348b5c5SDavid van Moolenbroek return;
952*7348b5c5SDavid van Moolenbroek switch(SB_PEEK()) {
953*7348b5c5SDavid van Moolenbroek case TELQUAL_IS:
954*7348b5c5SDavid van Moolenbroek case TELQUAL_INFO:
955*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(subchar))
956*7348b5c5SDavid van Moolenbroek return;
957*7348b5c5SDavid van Moolenbroek break;
958*7348b5c5SDavid van Moolenbroek case TELQUAL_SEND:
959*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(subchar)) {
960*7348b5c5SDavid van Moolenbroek return;
961*7348b5c5SDavid van Moolenbroek }
962*7348b5c5SDavid van Moolenbroek break;
963*7348b5c5SDavid van Moolenbroek default:
964*7348b5c5SDavid van Moolenbroek return;
965*7348b5c5SDavid van Moolenbroek }
966*7348b5c5SDavid van Moolenbroek env_opt(subpointer, SB_LEN());
967*7348b5c5SDavid van Moolenbroek break;
968*7348b5c5SDavid van Moolenbroek
969*7348b5c5SDavid van Moolenbroek case TELOPT_XDISPLOC:
970*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_XDISPLOC))
971*7348b5c5SDavid van Moolenbroek return;
972*7348b5c5SDavid van Moolenbroek if (SB_EOF())
973*7348b5c5SDavid van Moolenbroek return;
974*7348b5c5SDavid van Moolenbroek if (SB_GET() == TELQUAL_SEND) {
975*7348b5c5SDavid van Moolenbroek unsigned char temp[50], *dp;
976*7348b5c5SDavid van Moolenbroek int len;
977*7348b5c5SDavid van Moolenbroek
978*7348b5c5SDavid van Moolenbroek if ((dp = env_getvalue((const unsigned char *)"DISPLAY")) == NULL) {
979*7348b5c5SDavid van Moolenbroek /*
980*7348b5c5SDavid van Moolenbroek * Something happened, we no longer have a DISPLAY
981*7348b5c5SDavid van Moolenbroek * variable. So, turn off the option.
982*7348b5c5SDavid van Moolenbroek */
983*7348b5c5SDavid van Moolenbroek send_wont(TELOPT_XDISPLOC, 1);
984*7348b5c5SDavid van Moolenbroek break;
985*7348b5c5SDavid van Moolenbroek }
986*7348b5c5SDavid van Moolenbroek sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
987*7348b5c5SDavid van Moolenbroek TELQUAL_IS, dp, IAC, SE);
988*7348b5c5SDavid van Moolenbroek len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
989*7348b5c5SDavid van Moolenbroek
990*7348b5c5SDavid van Moolenbroek if (len < NETROOM()) {
991*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, temp, len);
992*7348b5c5SDavid van Moolenbroek printsub('>', temp+2, len - 2);
993*7348b5c5SDavid van Moolenbroek }
994*7348b5c5SDavid van Moolenbroek /*@*/ else printf("lm_will: not enough room in buffer\n");
995*7348b5c5SDavid van Moolenbroek }
996*7348b5c5SDavid van Moolenbroek break;
997*7348b5c5SDavid van Moolenbroek
998*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
999*7348b5c5SDavid van Moolenbroek case TELOPT_AUTHENTICATION: {
1000*7348b5c5SDavid van Moolenbroek if (!autologin)
1001*7348b5c5SDavid van Moolenbroek break;
1002*7348b5c5SDavid van Moolenbroek if (SB_EOF())
1003*7348b5c5SDavid van Moolenbroek return;
1004*7348b5c5SDavid van Moolenbroek switch(SB_GET()) {
1005*7348b5c5SDavid van Moolenbroek case TELQUAL_IS:
1006*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
1007*7348b5c5SDavid van Moolenbroek return;
1008*7348b5c5SDavid van Moolenbroek auth_is(subpointer, SB_LEN());
1009*7348b5c5SDavid van Moolenbroek break;
1010*7348b5c5SDavid van Moolenbroek case TELQUAL_SEND:
1011*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
1012*7348b5c5SDavid van Moolenbroek return;
1013*7348b5c5SDavid van Moolenbroek auth_send(subpointer, SB_LEN());
1014*7348b5c5SDavid van Moolenbroek break;
1015*7348b5c5SDavid van Moolenbroek case TELQUAL_REPLY:
1016*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
1017*7348b5c5SDavid van Moolenbroek return;
1018*7348b5c5SDavid van Moolenbroek auth_reply(subpointer, SB_LEN());
1019*7348b5c5SDavid van Moolenbroek break;
1020*7348b5c5SDavid van Moolenbroek case TELQUAL_NAME:
1021*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
1022*7348b5c5SDavid van Moolenbroek return;
1023*7348b5c5SDavid van Moolenbroek auth_name(subpointer, SB_LEN());
1024*7348b5c5SDavid van Moolenbroek break;
1025*7348b5c5SDavid van Moolenbroek }
1026*7348b5c5SDavid van Moolenbroek }
1027*7348b5c5SDavid van Moolenbroek break;
1028*7348b5c5SDavid van Moolenbroek #endif
1029*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1030*7348b5c5SDavid van Moolenbroek case TELOPT_ENCRYPT:
1031*7348b5c5SDavid van Moolenbroek if (SB_EOF())
1032*7348b5c5SDavid van Moolenbroek return;
1033*7348b5c5SDavid van Moolenbroek switch(SB_GET()) {
1034*7348b5c5SDavid van Moolenbroek case ENCRYPT_START:
1035*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_ENCRYPT))
1036*7348b5c5SDavid van Moolenbroek return;
1037*7348b5c5SDavid van Moolenbroek encrypt_start(subpointer, SB_LEN());
1038*7348b5c5SDavid van Moolenbroek break;
1039*7348b5c5SDavid van Moolenbroek case ENCRYPT_END:
1040*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_ENCRYPT))
1041*7348b5c5SDavid van Moolenbroek return;
1042*7348b5c5SDavid van Moolenbroek encrypt_end();
1043*7348b5c5SDavid van Moolenbroek break;
1044*7348b5c5SDavid van Moolenbroek case ENCRYPT_SUPPORT:
1045*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_ENCRYPT))
1046*7348b5c5SDavid van Moolenbroek return;
1047*7348b5c5SDavid van Moolenbroek encrypt_support(subpointer, SB_LEN());
1048*7348b5c5SDavid van Moolenbroek break;
1049*7348b5c5SDavid van Moolenbroek case ENCRYPT_REQSTART:
1050*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_ENCRYPT))
1051*7348b5c5SDavid van Moolenbroek return;
1052*7348b5c5SDavid van Moolenbroek encrypt_request_start(subpointer, SB_LEN());
1053*7348b5c5SDavid van Moolenbroek break;
1054*7348b5c5SDavid van Moolenbroek case ENCRYPT_REQEND:
1055*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_ENCRYPT))
1056*7348b5c5SDavid van Moolenbroek return;
1057*7348b5c5SDavid van Moolenbroek /*
1058*7348b5c5SDavid van Moolenbroek * We can always send an REQEND so that we cannot
1059*7348b5c5SDavid van Moolenbroek * get stuck encrypting. We should only get this
1060*7348b5c5SDavid van Moolenbroek * if we have been able to get in the correct mode
1061*7348b5c5SDavid van Moolenbroek * anyhow.
1062*7348b5c5SDavid van Moolenbroek */
1063*7348b5c5SDavid van Moolenbroek encrypt_request_end();
1064*7348b5c5SDavid van Moolenbroek break;
1065*7348b5c5SDavid van Moolenbroek case ENCRYPT_IS:
1066*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_ENCRYPT))
1067*7348b5c5SDavid van Moolenbroek return;
1068*7348b5c5SDavid van Moolenbroek encrypt_is(subpointer, SB_LEN());
1069*7348b5c5SDavid van Moolenbroek break;
1070*7348b5c5SDavid van Moolenbroek case ENCRYPT_REPLY:
1071*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_ENCRYPT))
1072*7348b5c5SDavid van Moolenbroek return;
1073*7348b5c5SDavid van Moolenbroek encrypt_reply(subpointer, SB_LEN());
1074*7348b5c5SDavid van Moolenbroek break;
1075*7348b5c5SDavid van Moolenbroek case ENCRYPT_ENC_KEYID:
1076*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_ENCRYPT))
1077*7348b5c5SDavid van Moolenbroek return;
1078*7348b5c5SDavid van Moolenbroek encrypt_enc_keyid(subpointer, SB_LEN());
1079*7348b5c5SDavid van Moolenbroek break;
1080*7348b5c5SDavid van Moolenbroek case ENCRYPT_DEC_KEYID:
1081*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_ENCRYPT))
1082*7348b5c5SDavid van Moolenbroek return;
1083*7348b5c5SDavid van Moolenbroek encrypt_dec_keyid(subpointer, SB_LEN());
1084*7348b5c5SDavid van Moolenbroek break;
1085*7348b5c5SDavid van Moolenbroek default:
1086*7348b5c5SDavid van Moolenbroek break;
1087*7348b5c5SDavid van Moolenbroek }
1088*7348b5c5SDavid van Moolenbroek break;
1089*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
1090*7348b5c5SDavid van Moolenbroek default:
1091*7348b5c5SDavid van Moolenbroek break;
1092*7348b5c5SDavid van Moolenbroek }
1093*7348b5c5SDavid van Moolenbroek }
1094*7348b5c5SDavid van Moolenbroek
1095*7348b5c5SDavid van Moolenbroek static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
1096*7348b5c5SDavid van Moolenbroek
1097*7348b5c5SDavid van Moolenbroek void
lm_will(unsigned char * cmd,int len)1098*7348b5c5SDavid van Moolenbroek lm_will(unsigned char *cmd, int len)
1099*7348b5c5SDavid van Moolenbroek {
1100*7348b5c5SDavid van Moolenbroek if (len < 1) {
1101*7348b5c5SDavid van Moolenbroek /*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
1102*7348b5c5SDavid van Moolenbroek return;
1103*7348b5c5SDavid van Moolenbroek }
1104*7348b5c5SDavid van Moolenbroek switch(cmd[0]) {
1105*7348b5c5SDavid van Moolenbroek case LM_FORWARDMASK: /* We shouldn't ever get this... */
1106*7348b5c5SDavid van Moolenbroek default:
1107*7348b5c5SDavid van Moolenbroek str_lm[3] = DONT;
1108*7348b5c5SDavid van Moolenbroek str_lm[4] = cmd[0];
1109*7348b5c5SDavid van Moolenbroek if ((size_t)NETROOM() > sizeof(str_lm)) {
1110*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1111*7348b5c5SDavid van Moolenbroek printsub('>', &str_lm[2], sizeof(str_lm)-2);
1112*7348b5c5SDavid van Moolenbroek }
1113*7348b5c5SDavid van Moolenbroek /*@*/ else printf("lm_will: not enough room in buffer\n");
1114*7348b5c5SDavid van Moolenbroek break;
1115*7348b5c5SDavid van Moolenbroek }
1116*7348b5c5SDavid van Moolenbroek }
1117*7348b5c5SDavid van Moolenbroek
1118*7348b5c5SDavid van Moolenbroek void
lm_wont(unsigned char * cmd,int len)1119*7348b5c5SDavid van Moolenbroek lm_wont(unsigned char *cmd, int len)
1120*7348b5c5SDavid van Moolenbroek {
1121*7348b5c5SDavid van Moolenbroek if (len < 1) {
1122*7348b5c5SDavid van Moolenbroek /*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
1123*7348b5c5SDavid van Moolenbroek return;
1124*7348b5c5SDavid van Moolenbroek }
1125*7348b5c5SDavid van Moolenbroek switch(cmd[0]) {
1126*7348b5c5SDavid van Moolenbroek case LM_FORWARDMASK: /* We shouldn't ever get this... */
1127*7348b5c5SDavid van Moolenbroek default:
1128*7348b5c5SDavid van Moolenbroek /* We are always DONT, so don't respond */
1129*7348b5c5SDavid van Moolenbroek return;
1130*7348b5c5SDavid van Moolenbroek }
1131*7348b5c5SDavid van Moolenbroek }
1132*7348b5c5SDavid van Moolenbroek
1133*7348b5c5SDavid van Moolenbroek void
lm_do(unsigned char * cmd,int len)1134*7348b5c5SDavid van Moolenbroek lm_do(unsigned char *cmd, int len)
1135*7348b5c5SDavid van Moolenbroek {
1136*7348b5c5SDavid van Moolenbroek if (len < 1) {
1137*7348b5c5SDavid van Moolenbroek /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
1138*7348b5c5SDavid van Moolenbroek return;
1139*7348b5c5SDavid van Moolenbroek }
1140*7348b5c5SDavid van Moolenbroek switch(cmd[0]) {
1141*7348b5c5SDavid van Moolenbroek case LM_FORWARDMASK:
1142*7348b5c5SDavid van Moolenbroek default:
1143*7348b5c5SDavid van Moolenbroek str_lm[3] = WONT;
1144*7348b5c5SDavid van Moolenbroek str_lm[4] = cmd[0];
1145*7348b5c5SDavid van Moolenbroek if ((size_t)NETROOM() > sizeof(str_lm)) {
1146*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1147*7348b5c5SDavid van Moolenbroek printsub('>', &str_lm[2], sizeof(str_lm)-2);
1148*7348b5c5SDavid van Moolenbroek }
1149*7348b5c5SDavid van Moolenbroek /*@*/ else printf("lm_do: not enough room in buffer\n");
1150*7348b5c5SDavid van Moolenbroek break;
1151*7348b5c5SDavid van Moolenbroek }
1152*7348b5c5SDavid van Moolenbroek }
1153*7348b5c5SDavid van Moolenbroek
1154*7348b5c5SDavid van Moolenbroek void
lm_dont(unsigned char * cmd,int len)1155*7348b5c5SDavid van Moolenbroek lm_dont(unsigned char *cmd, int len)
1156*7348b5c5SDavid van Moolenbroek {
1157*7348b5c5SDavid van Moolenbroek if (len < 1) {
1158*7348b5c5SDavid van Moolenbroek /*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
1159*7348b5c5SDavid van Moolenbroek return;
1160*7348b5c5SDavid van Moolenbroek }
1161*7348b5c5SDavid van Moolenbroek switch(cmd[0]) {
1162*7348b5c5SDavid van Moolenbroek case LM_FORWARDMASK:
1163*7348b5c5SDavid van Moolenbroek default:
1164*7348b5c5SDavid van Moolenbroek /* we are always WONT, so don't respond */
1165*7348b5c5SDavid van Moolenbroek break;
1166*7348b5c5SDavid van Moolenbroek }
1167*7348b5c5SDavid van Moolenbroek }
1168*7348b5c5SDavid van Moolenbroek
1169*7348b5c5SDavid van Moolenbroek static unsigned char str_lm_mode[] = {
1170*7348b5c5SDavid van Moolenbroek IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1171*7348b5c5SDavid van Moolenbroek };
1172*7348b5c5SDavid van Moolenbroek
1173*7348b5c5SDavid van Moolenbroek void
lm_mode(unsigned char * cmd,int len,int init)1174*7348b5c5SDavid van Moolenbroek lm_mode(unsigned char *cmd, int len, int init)
1175*7348b5c5SDavid van Moolenbroek {
1176*7348b5c5SDavid van Moolenbroek if (len != 1)
1177*7348b5c5SDavid van Moolenbroek return;
1178*7348b5c5SDavid van Moolenbroek if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
1179*7348b5c5SDavid van Moolenbroek return;
1180*7348b5c5SDavid van Moolenbroek if (*cmd&MODE_ACK)
1181*7348b5c5SDavid van Moolenbroek return;
1182*7348b5c5SDavid van Moolenbroek linemode = *cmd&(MODE_MASK&~MODE_ACK);
1183*7348b5c5SDavid van Moolenbroek str_lm_mode[4] = linemode;
1184*7348b5c5SDavid van Moolenbroek if (!init)
1185*7348b5c5SDavid van Moolenbroek str_lm_mode[4] |= MODE_ACK;
1186*7348b5c5SDavid van Moolenbroek if ((size_t)NETROOM() > sizeof(str_lm_mode)) {
1187*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
1188*7348b5c5SDavid van Moolenbroek printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
1189*7348b5c5SDavid van Moolenbroek }
1190*7348b5c5SDavid van Moolenbroek /*@*/ else printf("lm_mode: not enough room in buffer\n");
1191*7348b5c5SDavid van Moolenbroek setconnmode(0); /* set changed mode */
1192*7348b5c5SDavid van Moolenbroek }
1193*7348b5c5SDavid van Moolenbroek
1194*7348b5c5SDavid van Moolenbroek
1195*7348b5c5SDavid van Moolenbroek
1196*7348b5c5SDavid van Moolenbroek /*
1197*7348b5c5SDavid van Moolenbroek * slc()
1198*7348b5c5SDavid van Moolenbroek * Handle special character suboption of LINEMODE.
1199*7348b5c5SDavid van Moolenbroek */
1200*7348b5c5SDavid van Moolenbroek
1201*7348b5c5SDavid van Moolenbroek struct spc {
1202*7348b5c5SDavid van Moolenbroek cc_t val;
1203*7348b5c5SDavid van Moolenbroek cc_t *valp;
1204*7348b5c5SDavid van Moolenbroek char flags; /* Current flags & level */
1205*7348b5c5SDavid van Moolenbroek char mylevel; /* Maximum level & flags */
1206*7348b5c5SDavid van Moolenbroek } spc_data[NSLC+1];
1207*7348b5c5SDavid van Moolenbroek
1208*7348b5c5SDavid van Moolenbroek #define SLC_IMPORT 0
1209*7348b5c5SDavid van Moolenbroek #define SLC_EXPORT 1
1210*7348b5c5SDavid van Moolenbroek #define SLC_RVALUE 2
1211*7348b5c5SDavid van Moolenbroek static int slc_mode = SLC_EXPORT;
1212*7348b5c5SDavid van Moolenbroek
1213*7348b5c5SDavid van Moolenbroek void
slc_init(void)1214*7348b5c5SDavid van Moolenbroek slc_init(void)
1215*7348b5c5SDavid van Moolenbroek {
1216*7348b5c5SDavid van Moolenbroek struct spc *spcp;
1217*7348b5c5SDavid van Moolenbroek
1218*7348b5c5SDavid van Moolenbroek localchars = 1;
1219*7348b5c5SDavid van Moolenbroek for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
1220*7348b5c5SDavid van Moolenbroek spcp->val = 0;
1221*7348b5c5SDavid van Moolenbroek spcp->valp = 0;
1222*7348b5c5SDavid van Moolenbroek spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1223*7348b5c5SDavid van Moolenbroek }
1224*7348b5c5SDavid van Moolenbroek
1225*7348b5c5SDavid van Moolenbroek #define initfunc(func, flags) { \
1226*7348b5c5SDavid van Moolenbroek spcp = &spc_data[func]; \
1227*7348b5c5SDavid van Moolenbroek if ((spcp->valp = tcval(func)) != NULL){ \
1228*7348b5c5SDavid van Moolenbroek spcp->val = *spcp->valp; \
1229*7348b5c5SDavid van Moolenbroek spcp->mylevel = SLC_VARIABLE|flags; \
1230*7348b5c5SDavid van Moolenbroek } else { \
1231*7348b5c5SDavid van Moolenbroek spcp->val = 0; \
1232*7348b5c5SDavid van Moolenbroek spcp->mylevel = SLC_DEFAULT; \
1233*7348b5c5SDavid van Moolenbroek } \
1234*7348b5c5SDavid van Moolenbroek }
1235*7348b5c5SDavid van Moolenbroek
1236*7348b5c5SDavid van Moolenbroek initfunc(SLC_SYNCH, 0);
1237*7348b5c5SDavid van Moolenbroek /* No BRK */
1238*7348b5c5SDavid van Moolenbroek initfunc(SLC_AO, 0);
1239*7348b5c5SDavid van Moolenbroek initfunc(SLC_AYT, 0);
1240*7348b5c5SDavid van Moolenbroek /* No EOR */
1241*7348b5c5SDavid van Moolenbroek initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
1242*7348b5c5SDavid van Moolenbroek initfunc(SLC_EOF, 0);
1243*7348b5c5SDavid van Moolenbroek initfunc(SLC_SUSP, SLC_FLUSHIN);
1244*7348b5c5SDavid van Moolenbroek initfunc(SLC_EC, 0);
1245*7348b5c5SDavid van Moolenbroek initfunc(SLC_EL, 0);
1246*7348b5c5SDavid van Moolenbroek initfunc(SLC_EW, 0);
1247*7348b5c5SDavid van Moolenbroek initfunc(SLC_RP, 0);
1248*7348b5c5SDavid van Moolenbroek initfunc(SLC_LNEXT, 0);
1249*7348b5c5SDavid van Moolenbroek initfunc(SLC_XON, 0);
1250*7348b5c5SDavid van Moolenbroek initfunc(SLC_XOFF, 0);
1251*7348b5c5SDavid van Moolenbroek initfunc(SLC_FORW1, 0);
1252*7348b5c5SDavid van Moolenbroek initfunc(SLC_FORW2, 0);
1253*7348b5c5SDavid van Moolenbroek /* No FORW2 */
1254*7348b5c5SDavid van Moolenbroek
1255*7348b5c5SDavid van Moolenbroek initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
1256*7348b5c5SDavid van Moolenbroek #undef initfunc
1257*7348b5c5SDavid van Moolenbroek
1258*7348b5c5SDavid van Moolenbroek if (slc_mode == SLC_EXPORT)
1259*7348b5c5SDavid van Moolenbroek slc_export();
1260*7348b5c5SDavid van Moolenbroek else
1261*7348b5c5SDavid van Moolenbroek slc_import(1);
1262*7348b5c5SDavid van Moolenbroek
1263*7348b5c5SDavid van Moolenbroek }
1264*7348b5c5SDavid van Moolenbroek
1265*7348b5c5SDavid van Moolenbroek void
slcstate(void)1266*7348b5c5SDavid van Moolenbroek slcstate(void)
1267*7348b5c5SDavid van Moolenbroek {
1268*7348b5c5SDavid van Moolenbroek printf("Special characters are %s values\n",
1269*7348b5c5SDavid van Moolenbroek slc_mode == SLC_IMPORT ? "remote default" :
1270*7348b5c5SDavid van Moolenbroek slc_mode == SLC_EXPORT ? "local" :
1271*7348b5c5SDavid van Moolenbroek "remote");
1272*7348b5c5SDavid van Moolenbroek }
1273*7348b5c5SDavid van Moolenbroek
1274*7348b5c5SDavid van Moolenbroek void
slc_mode_export(int n)1275*7348b5c5SDavid van Moolenbroek slc_mode_export(int n)
1276*7348b5c5SDavid van Moolenbroek {
1277*7348b5c5SDavid van Moolenbroek slc_mode = SLC_EXPORT;
1278*7348b5c5SDavid van Moolenbroek if (my_state_is_will(TELOPT_LINEMODE))
1279*7348b5c5SDavid van Moolenbroek slc_export();
1280*7348b5c5SDavid van Moolenbroek }
1281*7348b5c5SDavid van Moolenbroek
1282*7348b5c5SDavid van Moolenbroek void
slc_mode_import(int def)1283*7348b5c5SDavid van Moolenbroek slc_mode_import(int def)
1284*7348b5c5SDavid van Moolenbroek {
1285*7348b5c5SDavid van Moolenbroek slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1286*7348b5c5SDavid van Moolenbroek if (my_state_is_will(TELOPT_LINEMODE))
1287*7348b5c5SDavid van Moolenbroek slc_import(def);
1288*7348b5c5SDavid van Moolenbroek }
1289*7348b5c5SDavid van Moolenbroek
1290*7348b5c5SDavid van Moolenbroek unsigned char slc_import_val[] = {
1291*7348b5c5SDavid van Moolenbroek IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1292*7348b5c5SDavid van Moolenbroek };
1293*7348b5c5SDavid van Moolenbroek unsigned char slc_import_def[] = {
1294*7348b5c5SDavid van Moolenbroek IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1295*7348b5c5SDavid van Moolenbroek };
1296*7348b5c5SDavid van Moolenbroek
1297*7348b5c5SDavid van Moolenbroek void
slc_import(int def)1298*7348b5c5SDavid van Moolenbroek slc_import(int def)
1299*7348b5c5SDavid van Moolenbroek {
1300*7348b5c5SDavid van Moolenbroek if ((size_t)NETROOM() > sizeof(slc_import_val)) {
1301*7348b5c5SDavid van Moolenbroek if (def) {
1302*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1303*7348b5c5SDavid van Moolenbroek printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1304*7348b5c5SDavid van Moolenbroek } else {
1305*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1306*7348b5c5SDavid van Moolenbroek printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1307*7348b5c5SDavid van Moolenbroek }
1308*7348b5c5SDavid van Moolenbroek }
1309*7348b5c5SDavid van Moolenbroek /*@*/ else printf("slc_import: not enough room\n");
1310*7348b5c5SDavid van Moolenbroek }
1311*7348b5c5SDavid van Moolenbroek
1312*7348b5c5SDavid van Moolenbroek void
slc_export(void)1313*7348b5c5SDavid van Moolenbroek slc_export(void)
1314*7348b5c5SDavid van Moolenbroek {
1315*7348b5c5SDavid van Moolenbroek struct spc *spcp;
1316*7348b5c5SDavid van Moolenbroek
1317*7348b5c5SDavid van Moolenbroek TerminalDefaultChars();
1318*7348b5c5SDavid van Moolenbroek
1319*7348b5c5SDavid van Moolenbroek slc_start_reply();
1320*7348b5c5SDavid van Moolenbroek for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1321*7348b5c5SDavid van Moolenbroek if (spcp->mylevel != SLC_NOSUPPORT) {
1322*7348b5c5SDavid van Moolenbroek if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1323*7348b5c5SDavid van Moolenbroek spcp->flags = SLC_NOSUPPORT;
1324*7348b5c5SDavid van Moolenbroek else
1325*7348b5c5SDavid van Moolenbroek spcp->flags = spcp->mylevel;
1326*7348b5c5SDavid van Moolenbroek if (spcp->valp)
1327*7348b5c5SDavid van Moolenbroek spcp->val = *spcp->valp;
1328*7348b5c5SDavid van Moolenbroek slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1329*7348b5c5SDavid van Moolenbroek }
1330*7348b5c5SDavid van Moolenbroek }
1331*7348b5c5SDavid van Moolenbroek slc_end_reply();
1332*7348b5c5SDavid van Moolenbroek (void)slc_update();
1333*7348b5c5SDavid van Moolenbroek setconnmode(1); /* Make sure the character values are set */
1334*7348b5c5SDavid van Moolenbroek }
1335*7348b5c5SDavid van Moolenbroek
1336*7348b5c5SDavid van Moolenbroek void
slc(unsigned char * cp,int len)1337*7348b5c5SDavid van Moolenbroek slc(unsigned char *cp, int len)
1338*7348b5c5SDavid van Moolenbroek {
1339*7348b5c5SDavid van Moolenbroek struct spc *spcp;
1340*7348b5c5SDavid van Moolenbroek int func,level;
1341*7348b5c5SDavid van Moolenbroek
1342*7348b5c5SDavid van Moolenbroek slc_start_reply();
1343*7348b5c5SDavid van Moolenbroek
1344*7348b5c5SDavid van Moolenbroek for (; len >= 3; len -=3, cp +=3) {
1345*7348b5c5SDavid van Moolenbroek
1346*7348b5c5SDavid van Moolenbroek func = cp[SLC_FUNC];
1347*7348b5c5SDavid van Moolenbroek
1348*7348b5c5SDavid van Moolenbroek if (func == 0) {
1349*7348b5c5SDavid van Moolenbroek /*
1350*7348b5c5SDavid van Moolenbroek * Client side: always ignore 0 function.
1351*7348b5c5SDavid van Moolenbroek */
1352*7348b5c5SDavid van Moolenbroek continue;
1353*7348b5c5SDavid van Moolenbroek }
1354*7348b5c5SDavid van Moolenbroek if (func > NSLC) {
1355*7348b5c5SDavid van Moolenbroek if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1356*7348b5c5SDavid van Moolenbroek slc_add_reply(func, SLC_NOSUPPORT, 0);
1357*7348b5c5SDavid van Moolenbroek continue;
1358*7348b5c5SDavid van Moolenbroek }
1359*7348b5c5SDavid van Moolenbroek
1360*7348b5c5SDavid van Moolenbroek spcp = &spc_data[func];
1361*7348b5c5SDavid van Moolenbroek
1362*7348b5c5SDavid van Moolenbroek level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1363*7348b5c5SDavid van Moolenbroek
1364*7348b5c5SDavid van Moolenbroek if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1365*7348b5c5SDavid van Moolenbroek ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1366*7348b5c5SDavid van Moolenbroek continue;
1367*7348b5c5SDavid van Moolenbroek }
1368*7348b5c5SDavid van Moolenbroek
1369*7348b5c5SDavid van Moolenbroek if (level == (SLC_DEFAULT|SLC_ACK)) {
1370*7348b5c5SDavid van Moolenbroek /*
1371*7348b5c5SDavid van Moolenbroek * This is an error condition, the SLC_ACK
1372*7348b5c5SDavid van Moolenbroek * bit should never be set for the SLC_DEFAULT
1373*7348b5c5SDavid van Moolenbroek * level. Our best guess to recover is to
1374*7348b5c5SDavid van Moolenbroek * ignore the SLC_ACK bit.
1375*7348b5c5SDavid van Moolenbroek */
1376*7348b5c5SDavid van Moolenbroek cp[SLC_FLAGS] &= ~SLC_ACK;
1377*7348b5c5SDavid van Moolenbroek }
1378*7348b5c5SDavid van Moolenbroek
1379*7348b5c5SDavid van Moolenbroek if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1380*7348b5c5SDavid van Moolenbroek spcp->val = (cc_t)cp[SLC_VALUE];
1381*7348b5c5SDavid van Moolenbroek spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
1382*7348b5c5SDavid van Moolenbroek continue;
1383*7348b5c5SDavid van Moolenbroek }
1384*7348b5c5SDavid van Moolenbroek
1385*7348b5c5SDavid van Moolenbroek level &= ~SLC_ACK;
1386*7348b5c5SDavid van Moolenbroek
1387*7348b5c5SDavid van Moolenbroek if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1388*7348b5c5SDavid van Moolenbroek spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1389*7348b5c5SDavid van Moolenbroek spcp->val = (cc_t)cp[SLC_VALUE];
1390*7348b5c5SDavid van Moolenbroek }
1391*7348b5c5SDavid van Moolenbroek if (level == SLC_DEFAULT) {
1392*7348b5c5SDavid van Moolenbroek if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1393*7348b5c5SDavid van Moolenbroek spcp->flags = spcp->mylevel;
1394*7348b5c5SDavid van Moolenbroek else
1395*7348b5c5SDavid van Moolenbroek spcp->flags = SLC_NOSUPPORT;
1396*7348b5c5SDavid van Moolenbroek }
1397*7348b5c5SDavid van Moolenbroek slc_add_reply(func, spcp->flags, spcp->val);
1398*7348b5c5SDavid van Moolenbroek }
1399*7348b5c5SDavid van Moolenbroek slc_end_reply();
1400*7348b5c5SDavid van Moolenbroek if (slc_update())
1401*7348b5c5SDavid van Moolenbroek setconnmode(1); /* set the new character values */
1402*7348b5c5SDavid van Moolenbroek }
1403*7348b5c5SDavid van Moolenbroek
1404*7348b5c5SDavid van Moolenbroek void
slc_check(void)1405*7348b5c5SDavid van Moolenbroek slc_check(void)
1406*7348b5c5SDavid van Moolenbroek {
1407*7348b5c5SDavid van Moolenbroek struct spc *spcp;
1408*7348b5c5SDavid van Moolenbroek
1409*7348b5c5SDavid van Moolenbroek slc_start_reply();
1410*7348b5c5SDavid van Moolenbroek for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1411*7348b5c5SDavid van Moolenbroek if (spcp->valp && spcp->val != *spcp->valp) {
1412*7348b5c5SDavid van Moolenbroek spcp->val = *spcp->valp;
1413*7348b5c5SDavid van Moolenbroek if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1414*7348b5c5SDavid van Moolenbroek spcp->flags = SLC_NOSUPPORT;
1415*7348b5c5SDavid van Moolenbroek else
1416*7348b5c5SDavid van Moolenbroek spcp->flags = spcp->mylevel;
1417*7348b5c5SDavid van Moolenbroek slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1418*7348b5c5SDavid van Moolenbroek }
1419*7348b5c5SDavid van Moolenbroek }
1420*7348b5c5SDavid van Moolenbroek slc_end_reply();
1421*7348b5c5SDavid van Moolenbroek setconnmode(1);
1422*7348b5c5SDavid van Moolenbroek }
1423*7348b5c5SDavid van Moolenbroek
1424*7348b5c5SDavid van Moolenbroek
1425*7348b5c5SDavid van Moolenbroek unsigned char slc_reply[128];
1426*7348b5c5SDavid van Moolenbroek unsigned char *slc_replyp;
1427*7348b5c5SDavid van Moolenbroek
1428*7348b5c5SDavid van Moolenbroek void
slc_start_reply(void)1429*7348b5c5SDavid van Moolenbroek slc_start_reply(void)
1430*7348b5c5SDavid van Moolenbroek {
1431*7348b5c5SDavid van Moolenbroek slc_replyp = slc_reply;
1432*7348b5c5SDavid van Moolenbroek *slc_replyp++ = IAC;
1433*7348b5c5SDavid van Moolenbroek *slc_replyp++ = SB;
1434*7348b5c5SDavid van Moolenbroek *slc_replyp++ = TELOPT_LINEMODE;
1435*7348b5c5SDavid van Moolenbroek *slc_replyp++ = LM_SLC;
1436*7348b5c5SDavid van Moolenbroek }
1437*7348b5c5SDavid van Moolenbroek
1438*7348b5c5SDavid van Moolenbroek void
slc_add_reply(unsigned int func,unsigned int flags,cc_t value)1439*7348b5c5SDavid van Moolenbroek slc_add_reply(unsigned int func, unsigned int flags, cc_t value)
1440*7348b5c5SDavid van Moolenbroek {
1441*7348b5c5SDavid van Moolenbroek if ((size_t)(slc_replyp - slc_reply) + 6 > sizeof(slc_reply))
1442*7348b5c5SDavid van Moolenbroek return;
1443*7348b5c5SDavid van Moolenbroek if ((*slc_replyp++ = func) == IAC)
1444*7348b5c5SDavid van Moolenbroek *slc_replyp++ = IAC;
1445*7348b5c5SDavid van Moolenbroek if ((*slc_replyp++ = flags) == IAC)
1446*7348b5c5SDavid van Moolenbroek *slc_replyp++ = IAC;
1447*7348b5c5SDavid van Moolenbroek if ((*slc_replyp++ = (unsigned char)value) == IAC)
1448*7348b5c5SDavid van Moolenbroek *slc_replyp++ = IAC;
1449*7348b5c5SDavid van Moolenbroek }
1450*7348b5c5SDavid van Moolenbroek
1451*7348b5c5SDavid van Moolenbroek void
slc_end_reply(void)1452*7348b5c5SDavid van Moolenbroek slc_end_reply(void)
1453*7348b5c5SDavid van Moolenbroek {
1454*7348b5c5SDavid van Moolenbroek int len;
1455*7348b5c5SDavid van Moolenbroek
1456*7348b5c5SDavid van Moolenbroek len = slc_replyp - slc_reply;
1457*7348b5c5SDavid van Moolenbroek if (len <= 4 || ((size_t)len + 2 > sizeof(slc_reply)))
1458*7348b5c5SDavid van Moolenbroek return;
1459*7348b5c5SDavid van Moolenbroek *slc_replyp++ = IAC;
1460*7348b5c5SDavid van Moolenbroek *slc_replyp++ = SE;
1461*7348b5c5SDavid van Moolenbroek len += 2;
1462*7348b5c5SDavid van Moolenbroek if (NETROOM() > len) {
1463*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1464*7348b5c5SDavid van Moolenbroek printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1465*7348b5c5SDavid van Moolenbroek }
1466*7348b5c5SDavid van Moolenbroek /*@*/else printf("slc_end_reply: not enough room\n");
1467*7348b5c5SDavid van Moolenbroek }
1468*7348b5c5SDavid van Moolenbroek
1469*7348b5c5SDavid van Moolenbroek int
slc_update(void)1470*7348b5c5SDavid van Moolenbroek slc_update(void)
1471*7348b5c5SDavid van Moolenbroek {
1472*7348b5c5SDavid van Moolenbroek struct spc *spcp;
1473*7348b5c5SDavid van Moolenbroek int need_update = 0;
1474*7348b5c5SDavid van Moolenbroek
1475*7348b5c5SDavid van Moolenbroek for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1476*7348b5c5SDavid van Moolenbroek if (!(spcp->flags&SLC_ACK))
1477*7348b5c5SDavid van Moolenbroek continue;
1478*7348b5c5SDavid van Moolenbroek spcp->flags &= ~SLC_ACK;
1479*7348b5c5SDavid van Moolenbroek if (spcp->valp && (*spcp->valp != spcp->val)) {
1480*7348b5c5SDavid van Moolenbroek *spcp->valp = spcp->val;
1481*7348b5c5SDavid van Moolenbroek need_update = 1;
1482*7348b5c5SDavid van Moolenbroek }
1483*7348b5c5SDavid van Moolenbroek }
1484*7348b5c5SDavid van Moolenbroek return(need_update);
1485*7348b5c5SDavid van Moolenbroek }
1486*7348b5c5SDavid van Moolenbroek
1487*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
1488*7348b5c5SDavid van Moolenbroek # ifdef ENV_HACK
1489*7348b5c5SDavid van Moolenbroek /*
1490*7348b5c5SDavid van Moolenbroek * Earlier version of telnet/telnetd from the BSD code had
1491*7348b5c5SDavid van Moolenbroek * the definitions of VALUE and VAR reversed. To ensure
1492*7348b5c5SDavid van Moolenbroek * maximum interoperability, we assume that the server is
1493*7348b5c5SDavid van Moolenbroek * an older BSD server, until proven otherwise. The newer
1494*7348b5c5SDavid van Moolenbroek * BSD servers should be able to handle either definition,
1495*7348b5c5SDavid van Moolenbroek * so it is better to use the wrong values if we don't
1496*7348b5c5SDavid van Moolenbroek * know what type of server it is.
1497*7348b5c5SDavid van Moolenbroek */
1498*7348b5c5SDavid van Moolenbroek int env_auto = 1;
1499*7348b5c5SDavid van Moolenbroek int old_env_var = OLD_ENV_VAR;
1500*7348b5c5SDavid van Moolenbroek int old_env_value = OLD_ENV_VALUE;
1501*7348b5c5SDavid van Moolenbroek # else
1502*7348b5c5SDavid van Moolenbroek # define old_env_var OLD_ENV_VAR
1503*7348b5c5SDavid van Moolenbroek # define old_env_value OLD_ENV_VALUE
1504*7348b5c5SDavid van Moolenbroek # endif
1505*7348b5c5SDavid van Moolenbroek #endif
1506*7348b5c5SDavid van Moolenbroek
1507*7348b5c5SDavid van Moolenbroek void
env_opt(unsigned char * buf,int len)1508*7348b5c5SDavid van Moolenbroek env_opt(unsigned char *buf, int len)
1509*7348b5c5SDavid van Moolenbroek {
1510*7348b5c5SDavid van Moolenbroek unsigned char *ep = 0, *epc = 0;
1511*7348b5c5SDavid van Moolenbroek int i;
1512*7348b5c5SDavid van Moolenbroek
1513*7348b5c5SDavid van Moolenbroek switch(buf[0]&0xff) {
1514*7348b5c5SDavid van Moolenbroek case TELQUAL_SEND:
1515*7348b5c5SDavid van Moolenbroek env_opt_start();
1516*7348b5c5SDavid van Moolenbroek if (len == 1) {
1517*7348b5c5SDavid van Moolenbroek env_opt_add(NULL);
1518*7348b5c5SDavid van Moolenbroek } else for (i = 1; i < len; i++) {
1519*7348b5c5SDavid van Moolenbroek switch (buf[i]&0xff) {
1520*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
1521*7348b5c5SDavid van Moolenbroek case OLD_ENV_VAR:
1522*7348b5c5SDavid van Moolenbroek # ifdef ENV_HACK
1523*7348b5c5SDavid van Moolenbroek if (telopt_environ == TELOPT_OLD_ENVIRON
1524*7348b5c5SDavid van Moolenbroek && env_auto) {
1525*7348b5c5SDavid van Moolenbroek /* Server has the same definitions */
1526*7348b5c5SDavid van Moolenbroek old_env_var = OLD_ENV_VAR;
1527*7348b5c5SDavid van Moolenbroek old_env_value = OLD_ENV_VALUE;
1528*7348b5c5SDavid van Moolenbroek }
1529*7348b5c5SDavid van Moolenbroek /* FALL THROUGH */
1530*7348b5c5SDavid van Moolenbroek # endif
1531*7348b5c5SDavid van Moolenbroek case OLD_ENV_VALUE:
1532*7348b5c5SDavid van Moolenbroek /*
1533*7348b5c5SDavid van Moolenbroek * Although OLD_ENV_VALUE is not legal, we will
1534*7348b5c5SDavid van Moolenbroek * still recognize it, just in case it is an
1535*7348b5c5SDavid van Moolenbroek * old server that has VAR & VALUE mixed up...
1536*7348b5c5SDavid van Moolenbroek */
1537*7348b5c5SDavid van Moolenbroek /* FALL THROUGH */
1538*7348b5c5SDavid van Moolenbroek #else
1539*7348b5c5SDavid van Moolenbroek case NEW_ENV_VAR:
1540*7348b5c5SDavid van Moolenbroek #endif
1541*7348b5c5SDavid van Moolenbroek case ENV_USERVAR:
1542*7348b5c5SDavid van Moolenbroek if (ep) {
1543*7348b5c5SDavid van Moolenbroek *epc = 0;
1544*7348b5c5SDavid van Moolenbroek env_opt_add(ep);
1545*7348b5c5SDavid van Moolenbroek }
1546*7348b5c5SDavid van Moolenbroek ep = epc = &buf[i+1];
1547*7348b5c5SDavid van Moolenbroek break;
1548*7348b5c5SDavid van Moolenbroek case ENV_ESC:
1549*7348b5c5SDavid van Moolenbroek i++;
1550*7348b5c5SDavid van Moolenbroek /*FALL THROUGH*/
1551*7348b5c5SDavid van Moolenbroek default:
1552*7348b5c5SDavid van Moolenbroek if (epc)
1553*7348b5c5SDavid van Moolenbroek *epc++ = buf[i];
1554*7348b5c5SDavid van Moolenbroek break;
1555*7348b5c5SDavid van Moolenbroek }
1556*7348b5c5SDavid van Moolenbroek }
1557*7348b5c5SDavid van Moolenbroek if (ep) {
1558*7348b5c5SDavid van Moolenbroek *epc = 0;
1559*7348b5c5SDavid van Moolenbroek env_opt_add(ep);
1560*7348b5c5SDavid van Moolenbroek }
1561*7348b5c5SDavid van Moolenbroek env_opt_end(1);
1562*7348b5c5SDavid van Moolenbroek break;
1563*7348b5c5SDavid van Moolenbroek
1564*7348b5c5SDavid van Moolenbroek case TELQUAL_IS:
1565*7348b5c5SDavid van Moolenbroek case TELQUAL_INFO:
1566*7348b5c5SDavid van Moolenbroek /* Ignore for now. We shouldn't get it anyway. */
1567*7348b5c5SDavid van Moolenbroek break;
1568*7348b5c5SDavid van Moolenbroek
1569*7348b5c5SDavid van Moolenbroek default:
1570*7348b5c5SDavid van Moolenbroek break;
1571*7348b5c5SDavid van Moolenbroek }
1572*7348b5c5SDavid van Moolenbroek }
1573*7348b5c5SDavid van Moolenbroek
1574*7348b5c5SDavid van Moolenbroek #define OPT_REPLY_SIZE 256
1575*7348b5c5SDavid van Moolenbroek unsigned char *opt_reply;
1576*7348b5c5SDavid van Moolenbroek unsigned char *opt_replyp;
1577*7348b5c5SDavid van Moolenbroek unsigned char *opt_replyend;
1578*7348b5c5SDavid van Moolenbroek
1579*7348b5c5SDavid van Moolenbroek void
env_opt_start(void)1580*7348b5c5SDavid van Moolenbroek env_opt_start(void)
1581*7348b5c5SDavid van Moolenbroek {
1582*7348b5c5SDavid van Moolenbroek unsigned char *p;
1583*7348b5c5SDavid van Moolenbroek
1584*7348b5c5SDavid van Moolenbroek if (opt_reply) {
1585*7348b5c5SDavid van Moolenbroek p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
1586*7348b5c5SDavid van Moolenbroek if (p == NULL)
1587*7348b5c5SDavid van Moolenbroek free(opt_reply);
1588*7348b5c5SDavid van Moolenbroek } else
1589*7348b5c5SDavid van Moolenbroek p = (unsigned char *)malloc(OPT_REPLY_SIZE);
1590*7348b5c5SDavid van Moolenbroek opt_reply = p;
1591*7348b5c5SDavid van Moolenbroek if (opt_reply == NULL) {
1592*7348b5c5SDavid van Moolenbroek /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
1593*7348b5c5SDavid van Moolenbroek opt_reply = opt_replyp = opt_replyend = NULL;
1594*7348b5c5SDavid van Moolenbroek return;
1595*7348b5c5SDavid van Moolenbroek }
1596*7348b5c5SDavid van Moolenbroek opt_replyp = opt_reply;
1597*7348b5c5SDavid van Moolenbroek opt_replyend = opt_reply + OPT_REPLY_SIZE;
1598*7348b5c5SDavid van Moolenbroek *opt_replyp++ = IAC;
1599*7348b5c5SDavid van Moolenbroek *opt_replyp++ = SB;
1600*7348b5c5SDavid van Moolenbroek *opt_replyp++ = telopt_environ;
1601*7348b5c5SDavid van Moolenbroek *opt_replyp++ = TELQUAL_IS;
1602*7348b5c5SDavid van Moolenbroek }
1603*7348b5c5SDavid van Moolenbroek
1604*7348b5c5SDavid van Moolenbroek void
env_opt_start_info(void)1605*7348b5c5SDavid van Moolenbroek env_opt_start_info(void)
1606*7348b5c5SDavid van Moolenbroek {
1607*7348b5c5SDavid van Moolenbroek env_opt_start();
1608*7348b5c5SDavid van Moolenbroek if (opt_replyp)
1609*7348b5c5SDavid van Moolenbroek opt_replyp[-1] = TELQUAL_INFO;
1610*7348b5c5SDavid van Moolenbroek }
1611*7348b5c5SDavid van Moolenbroek
1612*7348b5c5SDavid van Moolenbroek void
env_opt_add(unsigned char * ep)1613*7348b5c5SDavid van Moolenbroek env_opt_add(unsigned char *ep)
1614*7348b5c5SDavid van Moolenbroek {
1615*7348b5c5SDavid van Moolenbroek unsigned char *vp, c;
1616*7348b5c5SDavid van Moolenbroek unsigned int len, olen, elen;
1617*7348b5c5SDavid van Moolenbroek
1618*7348b5c5SDavid van Moolenbroek if (opt_reply == NULL) /*XXX*/
1619*7348b5c5SDavid van Moolenbroek return; /*XXX*/
1620*7348b5c5SDavid van Moolenbroek
1621*7348b5c5SDavid van Moolenbroek if (ep == NULL || *ep == '\0') {
1622*7348b5c5SDavid van Moolenbroek /* Send user defined variables first. */
1623*7348b5c5SDavid van Moolenbroek env_default(1, 0);
1624*7348b5c5SDavid van Moolenbroek while ((ep = env_default(0, 0)) != NULL)
1625*7348b5c5SDavid van Moolenbroek env_opt_add(ep);
1626*7348b5c5SDavid van Moolenbroek
1627*7348b5c5SDavid van Moolenbroek /* Now add the list of well know variables. */
1628*7348b5c5SDavid van Moolenbroek env_default(1, 1);
1629*7348b5c5SDavid van Moolenbroek while ((ep = env_default(0, 1)) != NULL)
1630*7348b5c5SDavid van Moolenbroek env_opt_add(ep);
1631*7348b5c5SDavid van Moolenbroek return;
1632*7348b5c5SDavid van Moolenbroek }
1633*7348b5c5SDavid van Moolenbroek vp = env_getvalue(ep);
1634*7348b5c5SDavid van Moolenbroek elen = 2 * (vp ? strlen((char *)vp) : 0) +
1635*7348b5c5SDavid van Moolenbroek 2 * strlen((char *)ep) + 6;
1636*7348b5c5SDavid van Moolenbroek if ((unsigned int)(opt_replyend - opt_replyp) < elen)
1637*7348b5c5SDavid van Moolenbroek {
1638*7348b5c5SDavid van Moolenbroek unsigned char *p;
1639*7348b5c5SDavid van Moolenbroek len = opt_replyend - opt_reply + elen;
1640*7348b5c5SDavid van Moolenbroek olen = opt_replyp - opt_reply;
1641*7348b5c5SDavid van Moolenbroek p = (unsigned char *)realloc(opt_reply, len);
1642*7348b5c5SDavid van Moolenbroek if (p == NULL)
1643*7348b5c5SDavid van Moolenbroek free(opt_reply);
1644*7348b5c5SDavid van Moolenbroek opt_reply = p;
1645*7348b5c5SDavid van Moolenbroek if (opt_reply == NULL) {
1646*7348b5c5SDavid van Moolenbroek /*@*/ printf("env_opt_add: realloc() failed!!!\n");
1647*7348b5c5SDavid van Moolenbroek opt_reply = opt_replyp = opt_replyend = NULL;
1648*7348b5c5SDavid van Moolenbroek return;
1649*7348b5c5SDavid van Moolenbroek }
1650*7348b5c5SDavid van Moolenbroek opt_replyp = opt_reply + olen;
1651*7348b5c5SDavid van Moolenbroek opt_replyend = opt_reply + len;
1652*7348b5c5SDavid van Moolenbroek }
1653*7348b5c5SDavid van Moolenbroek if (opt_welldefined(ep))
1654*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
1655*7348b5c5SDavid van Moolenbroek if (telopt_environ == TELOPT_OLD_ENVIRON)
1656*7348b5c5SDavid van Moolenbroek *opt_replyp++ = old_env_var;
1657*7348b5c5SDavid van Moolenbroek else
1658*7348b5c5SDavid van Moolenbroek #endif
1659*7348b5c5SDavid van Moolenbroek *opt_replyp++ = NEW_ENV_VAR;
1660*7348b5c5SDavid van Moolenbroek else
1661*7348b5c5SDavid van Moolenbroek *opt_replyp++ = ENV_USERVAR;
1662*7348b5c5SDavid van Moolenbroek for (;;) {
1663*7348b5c5SDavid van Moolenbroek while ((c = *ep++) != '\0') {
1664*7348b5c5SDavid van Moolenbroek switch(c&0xff) {
1665*7348b5c5SDavid van Moolenbroek case IAC:
1666*7348b5c5SDavid van Moolenbroek *opt_replyp++ = IAC;
1667*7348b5c5SDavid van Moolenbroek break;
1668*7348b5c5SDavid van Moolenbroek case NEW_ENV_VAR:
1669*7348b5c5SDavid van Moolenbroek case NEW_ENV_VALUE:
1670*7348b5c5SDavid van Moolenbroek case ENV_ESC:
1671*7348b5c5SDavid van Moolenbroek case ENV_USERVAR:
1672*7348b5c5SDavid van Moolenbroek *opt_replyp++ = ENV_ESC;
1673*7348b5c5SDavid van Moolenbroek break;
1674*7348b5c5SDavid van Moolenbroek }
1675*7348b5c5SDavid van Moolenbroek *opt_replyp++ = c;
1676*7348b5c5SDavid van Moolenbroek }
1677*7348b5c5SDavid van Moolenbroek if ((ep = vp) != NULL) {
1678*7348b5c5SDavid van Moolenbroek #ifdef OLD_ENVIRON
1679*7348b5c5SDavid van Moolenbroek if (telopt_environ == TELOPT_OLD_ENVIRON)
1680*7348b5c5SDavid van Moolenbroek *opt_replyp++ = old_env_value;
1681*7348b5c5SDavid van Moolenbroek else
1682*7348b5c5SDavid van Moolenbroek #endif
1683*7348b5c5SDavid van Moolenbroek *opt_replyp++ = NEW_ENV_VALUE;
1684*7348b5c5SDavid van Moolenbroek vp = NULL;
1685*7348b5c5SDavid van Moolenbroek } else
1686*7348b5c5SDavid van Moolenbroek break;
1687*7348b5c5SDavid van Moolenbroek }
1688*7348b5c5SDavid van Moolenbroek }
1689*7348b5c5SDavid van Moolenbroek
1690*7348b5c5SDavid van Moolenbroek int
opt_welldefined(const char * ep)1691*7348b5c5SDavid van Moolenbroek opt_welldefined(const char *ep)
1692*7348b5c5SDavid van Moolenbroek {
1693*7348b5c5SDavid van Moolenbroek if ((strcmp(ep, "USER") == 0) ||
1694*7348b5c5SDavid van Moolenbroek (strcmp(ep, "DISPLAY") == 0) ||
1695*7348b5c5SDavid van Moolenbroek (strcmp(ep, "PRINTER") == 0) ||
1696*7348b5c5SDavid van Moolenbroek (strcmp(ep, "SYSTEMTYPE") == 0) ||
1697*7348b5c5SDavid van Moolenbroek (strcmp(ep, "JOB") == 0) ||
1698*7348b5c5SDavid van Moolenbroek (strcmp(ep, "ACCT") == 0))
1699*7348b5c5SDavid van Moolenbroek return(1);
1700*7348b5c5SDavid van Moolenbroek return(0);
1701*7348b5c5SDavid van Moolenbroek }
1702*7348b5c5SDavid van Moolenbroek void
env_opt_end(int emptyok)1703*7348b5c5SDavid van Moolenbroek env_opt_end(int emptyok)
1704*7348b5c5SDavid van Moolenbroek {
1705*7348b5c5SDavid van Moolenbroek int len;
1706*7348b5c5SDavid van Moolenbroek
1707*7348b5c5SDavid van Moolenbroek len = opt_replyp - opt_reply + 2;
1708*7348b5c5SDavid van Moolenbroek if (emptyok || len > 6) {
1709*7348b5c5SDavid van Moolenbroek *opt_replyp++ = IAC;
1710*7348b5c5SDavid van Moolenbroek *opt_replyp++ = SE;
1711*7348b5c5SDavid van Moolenbroek if (NETROOM() > len) {
1712*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, opt_reply, len);
1713*7348b5c5SDavid van Moolenbroek printsub('>', &opt_reply[2], len - 2);
1714*7348b5c5SDavid van Moolenbroek }
1715*7348b5c5SDavid van Moolenbroek /*@*/ else printf("slc_end_reply: not enough room\n");
1716*7348b5c5SDavid van Moolenbroek }
1717*7348b5c5SDavid van Moolenbroek if (opt_reply) {
1718*7348b5c5SDavid van Moolenbroek free(opt_reply);
1719*7348b5c5SDavid van Moolenbroek opt_reply = opt_replyp = opt_replyend = NULL;
1720*7348b5c5SDavid van Moolenbroek }
1721*7348b5c5SDavid van Moolenbroek }
1722*7348b5c5SDavid van Moolenbroek
1723*7348b5c5SDavid van Moolenbroek
1724*7348b5c5SDavid van Moolenbroek
1725*7348b5c5SDavid van Moolenbroek int
telrcv(void)1726*7348b5c5SDavid van Moolenbroek telrcv(void)
1727*7348b5c5SDavid van Moolenbroek {
1728*7348b5c5SDavid van Moolenbroek int c;
1729*7348b5c5SDavid van Moolenbroek int scc;
1730*7348b5c5SDavid van Moolenbroek unsigned char *sbp = NULL;
1731*7348b5c5SDavid van Moolenbroek int count;
1732*7348b5c5SDavid van Moolenbroek int returnValue = 0;
1733*7348b5c5SDavid van Moolenbroek
1734*7348b5c5SDavid van Moolenbroek scc = 0;
1735*7348b5c5SDavid van Moolenbroek count = 0;
1736*7348b5c5SDavid van Moolenbroek while (TTYROOM() > 2) {
1737*7348b5c5SDavid van Moolenbroek if (scc == 0) {
1738*7348b5c5SDavid van Moolenbroek if (count) {
1739*7348b5c5SDavid van Moolenbroek ring_consumed(&netiring, count);
1740*7348b5c5SDavid van Moolenbroek returnValue = 1;
1741*7348b5c5SDavid van Moolenbroek count = 0;
1742*7348b5c5SDavid van Moolenbroek }
1743*7348b5c5SDavid van Moolenbroek sbp = netiring.consume;
1744*7348b5c5SDavid van Moolenbroek scc = ring_full_consecutive(&netiring);
1745*7348b5c5SDavid van Moolenbroek if (scc == 0) {
1746*7348b5c5SDavid van Moolenbroek /* No more data coming in */
1747*7348b5c5SDavid van Moolenbroek break;
1748*7348b5c5SDavid van Moolenbroek }
1749*7348b5c5SDavid van Moolenbroek }
1750*7348b5c5SDavid van Moolenbroek
1751*7348b5c5SDavid van Moolenbroek c = *sbp++ & 0xff, scc--; count++;
1752*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1753*7348b5c5SDavid van Moolenbroek if (decrypt_input)
1754*7348b5c5SDavid van Moolenbroek c = (*decrypt_input)(c);
1755*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
1756*7348b5c5SDavid van Moolenbroek
1757*7348b5c5SDavid van Moolenbroek switch (telrcv_state) {
1758*7348b5c5SDavid van Moolenbroek
1759*7348b5c5SDavid van Moolenbroek case TS_CR:
1760*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1761*7348b5c5SDavid van Moolenbroek if (c == '\0') {
1762*7348b5c5SDavid van Moolenbroek break; /* Ignore \0 after CR */
1763*7348b5c5SDavid van Moolenbroek }
1764*7348b5c5SDavid van Moolenbroek else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1765*7348b5c5SDavid van Moolenbroek TTYADD(c);
1766*7348b5c5SDavid van Moolenbroek break;
1767*7348b5c5SDavid van Moolenbroek }
1768*7348b5c5SDavid van Moolenbroek /* Else, fall through */
1769*7348b5c5SDavid van Moolenbroek
1770*7348b5c5SDavid van Moolenbroek case TS_DATA:
1771*7348b5c5SDavid van Moolenbroek if (c == IAC) {
1772*7348b5c5SDavid van Moolenbroek telrcv_state = TS_IAC;
1773*7348b5c5SDavid van Moolenbroek break;
1774*7348b5c5SDavid van Moolenbroek }
1775*7348b5c5SDavid van Moolenbroek # if defined(TN3270)
1776*7348b5c5SDavid van Moolenbroek if (In3270) {
1777*7348b5c5SDavid van Moolenbroek *Ifrontp++ = c;
1778*7348b5c5SDavid van Moolenbroek while (scc > 0) {
1779*7348b5c5SDavid van Moolenbroek c = *sbp++ & 0377, scc--; count++;
1780*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1781*7348b5c5SDavid van Moolenbroek if (decrypt_input)
1782*7348b5c5SDavid van Moolenbroek c = (*decrypt_input)(c);
1783*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
1784*7348b5c5SDavid van Moolenbroek if (c == IAC) {
1785*7348b5c5SDavid van Moolenbroek telrcv_state = TS_IAC;
1786*7348b5c5SDavid van Moolenbroek break;
1787*7348b5c5SDavid van Moolenbroek }
1788*7348b5c5SDavid van Moolenbroek *Ifrontp++ = c;
1789*7348b5c5SDavid van Moolenbroek }
1790*7348b5c5SDavid van Moolenbroek } else
1791*7348b5c5SDavid van Moolenbroek # endif /* defined(TN3270) */
1792*7348b5c5SDavid van Moolenbroek /*
1793*7348b5c5SDavid van Moolenbroek * The 'crmod' hack (see following) is needed
1794*7348b5c5SDavid van Moolenbroek * since we can't * set CRMOD on output only.
1795*7348b5c5SDavid van Moolenbroek * Machines like MULTICS like to send \r without
1796*7348b5c5SDavid van Moolenbroek * \n; since we must turn off CRMOD to get proper
1797*7348b5c5SDavid van Moolenbroek * input, the mapping is done here (sigh).
1798*7348b5c5SDavid van Moolenbroek */
1799*7348b5c5SDavid van Moolenbroek if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1800*7348b5c5SDavid van Moolenbroek if (scc > 0) {
1801*7348b5c5SDavid van Moolenbroek c = *sbp&0xff;
1802*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1803*7348b5c5SDavid van Moolenbroek if (decrypt_input)
1804*7348b5c5SDavid van Moolenbroek c = (*decrypt_input)(c);
1805*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
1806*7348b5c5SDavid van Moolenbroek if (c == 0) {
1807*7348b5c5SDavid van Moolenbroek sbp++, scc--; count++;
1808*7348b5c5SDavid van Moolenbroek /* a "true" CR */
1809*7348b5c5SDavid van Moolenbroek TTYADD('\r');
1810*7348b5c5SDavid van Moolenbroek } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1811*7348b5c5SDavid van Moolenbroek (c == '\n')) {
1812*7348b5c5SDavid van Moolenbroek sbp++, scc--; count++;
1813*7348b5c5SDavid van Moolenbroek TTYADD('\n');
1814*7348b5c5SDavid van Moolenbroek } else {
1815*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
1816*7348b5c5SDavid van Moolenbroek if (decrypt_input)
1817*7348b5c5SDavid van Moolenbroek (*decrypt_input)(-1);
1818*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
1819*7348b5c5SDavid van Moolenbroek
1820*7348b5c5SDavid van Moolenbroek TTYADD('\r');
1821*7348b5c5SDavid van Moolenbroek if (crmod) {
1822*7348b5c5SDavid van Moolenbroek TTYADD('\n');
1823*7348b5c5SDavid van Moolenbroek }
1824*7348b5c5SDavid van Moolenbroek }
1825*7348b5c5SDavid van Moolenbroek } else {
1826*7348b5c5SDavid van Moolenbroek telrcv_state = TS_CR;
1827*7348b5c5SDavid van Moolenbroek TTYADD('\r');
1828*7348b5c5SDavid van Moolenbroek if (crmod) {
1829*7348b5c5SDavid van Moolenbroek TTYADD('\n');
1830*7348b5c5SDavid van Moolenbroek }
1831*7348b5c5SDavid van Moolenbroek }
1832*7348b5c5SDavid van Moolenbroek } else {
1833*7348b5c5SDavid van Moolenbroek TTYADD(c);
1834*7348b5c5SDavid van Moolenbroek }
1835*7348b5c5SDavid van Moolenbroek continue;
1836*7348b5c5SDavid van Moolenbroek
1837*7348b5c5SDavid van Moolenbroek case TS_IAC:
1838*7348b5c5SDavid van Moolenbroek process_iac:
1839*7348b5c5SDavid van Moolenbroek switch (c) {
1840*7348b5c5SDavid van Moolenbroek
1841*7348b5c5SDavid van Moolenbroek case WILL:
1842*7348b5c5SDavid van Moolenbroek telrcv_state = TS_WILL;
1843*7348b5c5SDavid van Moolenbroek continue;
1844*7348b5c5SDavid van Moolenbroek
1845*7348b5c5SDavid van Moolenbroek case WONT:
1846*7348b5c5SDavid van Moolenbroek telrcv_state = TS_WONT;
1847*7348b5c5SDavid van Moolenbroek continue;
1848*7348b5c5SDavid van Moolenbroek
1849*7348b5c5SDavid van Moolenbroek case DO:
1850*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DO;
1851*7348b5c5SDavid van Moolenbroek continue;
1852*7348b5c5SDavid van Moolenbroek
1853*7348b5c5SDavid van Moolenbroek case DONT:
1854*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DONT;
1855*7348b5c5SDavid van Moolenbroek continue;
1856*7348b5c5SDavid van Moolenbroek
1857*7348b5c5SDavid van Moolenbroek case DM:
1858*7348b5c5SDavid van Moolenbroek /*
1859*7348b5c5SDavid van Moolenbroek * We may have missed an urgent notification,
1860*7348b5c5SDavid van Moolenbroek * so make sure we flush whatever is in the
1861*7348b5c5SDavid van Moolenbroek * buffer currently.
1862*7348b5c5SDavid van Moolenbroek */
1863*7348b5c5SDavid van Moolenbroek printoption("RCVD", IAC, DM);
1864*7348b5c5SDavid van Moolenbroek SYNCHing = 1;
1865*7348b5c5SDavid van Moolenbroek (void) ttyflush(1);
1866*7348b5c5SDavid van Moolenbroek SYNCHing = stilloob();
1867*7348b5c5SDavid van Moolenbroek settimer(gotDM);
1868*7348b5c5SDavid van Moolenbroek break;
1869*7348b5c5SDavid van Moolenbroek
1870*7348b5c5SDavid van Moolenbroek case SB:
1871*7348b5c5SDavid van Moolenbroek SB_CLEAR();
1872*7348b5c5SDavid van Moolenbroek telrcv_state = TS_SB;
1873*7348b5c5SDavid van Moolenbroek continue;
1874*7348b5c5SDavid van Moolenbroek
1875*7348b5c5SDavid van Moolenbroek # if defined(TN3270)
1876*7348b5c5SDavid van Moolenbroek case EOR:
1877*7348b5c5SDavid van Moolenbroek if (In3270) {
1878*7348b5c5SDavid van Moolenbroek if (Ibackp == Ifrontp) {
1879*7348b5c5SDavid van Moolenbroek Ibackp = Ifrontp = Ibuf;
1880*7348b5c5SDavid van Moolenbroek ISend = 0; /* should have been! */
1881*7348b5c5SDavid van Moolenbroek } else {
1882*7348b5c5SDavid van Moolenbroek Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1883*7348b5c5SDavid van Moolenbroek ISend = 1;
1884*7348b5c5SDavid van Moolenbroek }
1885*7348b5c5SDavid van Moolenbroek }
1886*7348b5c5SDavid van Moolenbroek printoption("RCVD", IAC, EOR);
1887*7348b5c5SDavid van Moolenbroek break;
1888*7348b5c5SDavid van Moolenbroek # endif /* defined(TN3270) */
1889*7348b5c5SDavid van Moolenbroek
1890*7348b5c5SDavid van Moolenbroek case IAC:
1891*7348b5c5SDavid van Moolenbroek # if !defined(TN3270)
1892*7348b5c5SDavid van Moolenbroek TTYADD(IAC);
1893*7348b5c5SDavid van Moolenbroek # else /* !defined(TN3270) */
1894*7348b5c5SDavid van Moolenbroek if (In3270) {
1895*7348b5c5SDavid van Moolenbroek *Ifrontp++ = IAC;
1896*7348b5c5SDavid van Moolenbroek } else {
1897*7348b5c5SDavid van Moolenbroek TTYADD(IAC);
1898*7348b5c5SDavid van Moolenbroek }
1899*7348b5c5SDavid van Moolenbroek # endif /* !defined(TN3270) */
1900*7348b5c5SDavid van Moolenbroek break;
1901*7348b5c5SDavid van Moolenbroek
1902*7348b5c5SDavid van Moolenbroek case NOP:
1903*7348b5c5SDavid van Moolenbroek case GA:
1904*7348b5c5SDavid van Moolenbroek default:
1905*7348b5c5SDavid van Moolenbroek printoption("RCVD", IAC, c);
1906*7348b5c5SDavid van Moolenbroek break;
1907*7348b5c5SDavid van Moolenbroek }
1908*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1909*7348b5c5SDavid van Moolenbroek continue;
1910*7348b5c5SDavid van Moolenbroek
1911*7348b5c5SDavid van Moolenbroek case TS_WILL:
1912*7348b5c5SDavid van Moolenbroek printoption("RCVD", WILL, c);
1913*7348b5c5SDavid van Moolenbroek willoption(c);
1914*7348b5c5SDavid van Moolenbroek SetIn3270();
1915*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1916*7348b5c5SDavid van Moolenbroek continue;
1917*7348b5c5SDavid van Moolenbroek
1918*7348b5c5SDavid van Moolenbroek case TS_WONT:
1919*7348b5c5SDavid van Moolenbroek printoption("RCVD", WONT, c);
1920*7348b5c5SDavid van Moolenbroek wontoption(c);
1921*7348b5c5SDavid van Moolenbroek SetIn3270();
1922*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1923*7348b5c5SDavid van Moolenbroek continue;
1924*7348b5c5SDavid van Moolenbroek
1925*7348b5c5SDavid van Moolenbroek case TS_DO:
1926*7348b5c5SDavid van Moolenbroek printoption("RCVD", DO, c);
1927*7348b5c5SDavid van Moolenbroek dooption(c);
1928*7348b5c5SDavid van Moolenbroek SetIn3270();
1929*7348b5c5SDavid van Moolenbroek if (c == TELOPT_NAWS) {
1930*7348b5c5SDavid van Moolenbroek sendnaws();
1931*7348b5c5SDavid van Moolenbroek } else if (c == TELOPT_LFLOW) {
1932*7348b5c5SDavid van Moolenbroek localflow = 1;
1933*7348b5c5SDavid van Moolenbroek setcommandmode();
1934*7348b5c5SDavid van Moolenbroek setconnmode(0);
1935*7348b5c5SDavid van Moolenbroek }
1936*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1937*7348b5c5SDavid van Moolenbroek continue;
1938*7348b5c5SDavid van Moolenbroek
1939*7348b5c5SDavid van Moolenbroek case TS_DONT:
1940*7348b5c5SDavid van Moolenbroek printoption("RCVD", DONT, c);
1941*7348b5c5SDavid van Moolenbroek dontoption(c);
1942*7348b5c5SDavid van Moolenbroek flushline = 1;
1943*7348b5c5SDavid van Moolenbroek setconnmode(0); /* set new tty mode (maybe) */
1944*7348b5c5SDavid van Moolenbroek SetIn3270();
1945*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1946*7348b5c5SDavid van Moolenbroek continue;
1947*7348b5c5SDavid van Moolenbroek
1948*7348b5c5SDavid van Moolenbroek case TS_SB:
1949*7348b5c5SDavid van Moolenbroek if (c == IAC) {
1950*7348b5c5SDavid van Moolenbroek telrcv_state = TS_SE;
1951*7348b5c5SDavid van Moolenbroek } else {
1952*7348b5c5SDavid van Moolenbroek SB_ACCUM(c);
1953*7348b5c5SDavid van Moolenbroek }
1954*7348b5c5SDavid van Moolenbroek continue;
1955*7348b5c5SDavid van Moolenbroek
1956*7348b5c5SDavid van Moolenbroek case TS_SE:
1957*7348b5c5SDavid van Moolenbroek if (c != SE) {
1958*7348b5c5SDavid van Moolenbroek if (c != IAC) {
1959*7348b5c5SDavid van Moolenbroek /*
1960*7348b5c5SDavid van Moolenbroek * This is an error. We only expect to get
1961*7348b5c5SDavid van Moolenbroek * "IAC IAC" or "IAC SE". Several things may
1962*7348b5c5SDavid van Moolenbroek * have happened. An IAC was not doubled, the
1963*7348b5c5SDavid van Moolenbroek * IAC SE was left off, or another option got
1964*7348b5c5SDavid van Moolenbroek * inserted into the suboption are all possibilities.
1965*7348b5c5SDavid van Moolenbroek * If we assume that the IAC was not doubled,
1966*7348b5c5SDavid van Moolenbroek * and really the IAC SE was left off, we could
1967*7348b5c5SDavid van Moolenbroek * get into an infinite loop here. So, instead,
1968*7348b5c5SDavid van Moolenbroek * we terminate the suboption, and process the
1969*7348b5c5SDavid van Moolenbroek * partial suboption if we can.
1970*7348b5c5SDavid van Moolenbroek */
1971*7348b5c5SDavid van Moolenbroek SB_ACCUM(IAC);
1972*7348b5c5SDavid van Moolenbroek SB_ACCUM(c);
1973*7348b5c5SDavid van Moolenbroek subpointer -= 2;
1974*7348b5c5SDavid van Moolenbroek SB_TERM();
1975*7348b5c5SDavid van Moolenbroek
1976*7348b5c5SDavid van Moolenbroek printoption("In SUBOPTION processing, RCVD", IAC, c);
1977*7348b5c5SDavid van Moolenbroek suboption(); /* handle sub-option */
1978*7348b5c5SDavid van Moolenbroek SetIn3270();
1979*7348b5c5SDavid van Moolenbroek telrcv_state = TS_IAC;
1980*7348b5c5SDavid van Moolenbroek goto process_iac;
1981*7348b5c5SDavid van Moolenbroek }
1982*7348b5c5SDavid van Moolenbroek SB_ACCUM(c);
1983*7348b5c5SDavid van Moolenbroek telrcv_state = TS_SB;
1984*7348b5c5SDavid van Moolenbroek } else {
1985*7348b5c5SDavid van Moolenbroek SB_ACCUM(IAC);
1986*7348b5c5SDavid van Moolenbroek SB_ACCUM(SE);
1987*7348b5c5SDavid van Moolenbroek subpointer -= 2;
1988*7348b5c5SDavid van Moolenbroek SB_TERM();
1989*7348b5c5SDavid van Moolenbroek suboption(); /* handle sub-option */
1990*7348b5c5SDavid van Moolenbroek SetIn3270();
1991*7348b5c5SDavid van Moolenbroek telrcv_state = TS_DATA;
1992*7348b5c5SDavid van Moolenbroek }
1993*7348b5c5SDavid van Moolenbroek }
1994*7348b5c5SDavid van Moolenbroek }
1995*7348b5c5SDavid van Moolenbroek if (count)
1996*7348b5c5SDavid van Moolenbroek ring_consumed(&netiring, count);
1997*7348b5c5SDavid van Moolenbroek return returnValue||count;
1998*7348b5c5SDavid van Moolenbroek }
1999*7348b5c5SDavid van Moolenbroek
2000*7348b5c5SDavid van Moolenbroek static int bol = 1, local = 0;
2001*7348b5c5SDavid van Moolenbroek
2002*7348b5c5SDavid van Moolenbroek int
rlogin_susp(void)2003*7348b5c5SDavid van Moolenbroek rlogin_susp(void)
2004*7348b5c5SDavid van Moolenbroek {
2005*7348b5c5SDavid van Moolenbroek if (local) {
2006*7348b5c5SDavid van Moolenbroek local = 0;
2007*7348b5c5SDavid van Moolenbroek bol = 1;
2008*7348b5c5SDavid van Moolenbroek command(0, "z\n", 2);
2009*7348b5c5SDavid van Moolenbroek return(1);
2010*7348b5c5SDavid van Moolenbroek }
2011*7348b5c5SDavid van Moolenbroek return(0);
2012*7348b5c5SDavid van Moolenbroek }
2013*7348b5c5SDavid van Moolenbroek
2014*7348b5c5SDavid van Moolenbroek static int
telsnd(void)2015*7348b5c5SDavid van Moolenbroek telsnd(void)
2016*7348b5c5SDavid van Moolenbroek {
2017*7348b5c5SDavid van Moolenbroek int tcc;
2018*7348b5c5SDavid van Moolenbroek int count;
2019*7348b5c5SDavid van Moolenbroek int returnValue = 0;
2020*7348b5c5SDavid van Moolenbroek unsigned char *tbp = NULL;
2021*7348b5c5SDavid van Moolenbroek
2022*7348b5c5SDavid van Moolenbroek tcc = 0;
2023*7348b5c5SDavid van Moolenbroek count = 0;
2024*7348b5c5SDavid van Moolenbroek while (NETROOM() > 2) {
2025*7348b5c5SDavid van Moolenbroek int sc;
2026*7348b5c5SDavid van Moolenbroek int c;
2027*7348b5c5SDavid van Moolenbroek
2028*7348b5c5SDavid van Moolenbroek if (tcc == 0) {
2029*7348b5c5SDavid van Moolenbroek if (count) {
2030*7348b5c5SDavid van Moolenbroek ring_consumed(&ttyiring, count);
2031*7348b5c5SDavid van Moolenbroek returnValue = 1;
2032*7348b5c5SDavid van Moolenbroek count = 0;
2033*7348b5c5SDavid van Moolenbroek }
2034*7348b5c5SDavid van Moolenbroek tbp = ttyiring.consume;
2035*7348b5c5SDavid van Moolenbroek tcc = ring_full_consecutive(&ttyiring);
2036*7348b5c5SDavid van Moolenbroek if (tcc == 0) {
2037*7348b5c5SDavid van Moolenbroek break;
2038*7348b5c5SDavid van Moolenbroek }
2039*7348b5c5SDavid van Moolenbroek }
2040*7348b5c5SDavid van Moolenbroek c = *tbp++ & 0xff, sc = strip(c), tcc--; count++;
2041*7348b5c5SDavid van Moolenbroek if (rlogin != _POSIX_VDISABLE) {
2042*7348b5c5SDavid van Moolenbroek if (bol) {
2043*7348b5c5SDavid van Moolenbroek bol = 0;
2044*7348b5c5SDavid van Moolenbroek if (sc == rlogin) {
2045*7348b5c5SDavid van Moolenbroek local = 1;
2046*7348b5c5SDavid van Moolenbroek continue;
2047*7348b5c5SDavid van Moolenbroek }
2048*7348b5c5SDavid van Moolenbroek } else if (local) {
2049*7348b5c5SDavid van Moolenbroek local = 0;
2050*7348b5c5SDavid van Moolenbroek if (sc == '.' || c == termEofChar) {
2051*7348b5c5SDavid van Moolenbroek bol = 1;
2052*7348b5c5SDavid van Moolenbroek command(0, "close\n", 6);
2053*7348b5c5SDavid van Moolenbroek continue;
2054*7348b5c5SDavid van Moolenbroek }
2055*7348b5c5SDavid van Moolenbroek if (sc == termSuspChar) {
2056*7348b5c5SDavid van Moolenbroek bol = 1;
2057*7348b5c5SDavid van Moolenbroek command(0, "z\n", 2);
2058*7348b5c5SDavid van Moolenbroek continue;
2059*7348b5c5SDavid van Moolenbroek }
2060*7348b5c5SDavid van Moolenbroek if (sc == escape) {
2061*7348b5c5SDavid van Moolenbroek command(0, (char *)tbp, tcc);
2062*7348b5c5SDavid van Moolenbroek bol = 1;
2063*7348b5c5SDavid van Moolenbroek count += tcc;
2064*7348b5c5SDavid van Moolenbroek tcc = 0;
2065*7348b5c5SDavid van Moolenbroek flushline = 1;
2066*7348b5c5SDavid van Moolenbroek break;
2067*7348b5c5SDavid van Moolenbroek }
2068*7348b5c5SDavid van Moolenbroek if (sc != rlogin) {
2069*7348b5c5SDavid van Moolenbroek ++tcc;
2070*7348b5c5SDavid van Moolenbroek --tbp;
2071*7348b5c5SDavid van Moolenbroek --count;
2072*7348b5c5SDavid van Moolenbroek c = sc = rlogin;
2073*7348b5c5SDavid van Moolenbroek }
2074*7348b5c5SDavid van Moolenbroek }
2075*7348b5c5SDavid van Moolenbroek if ((sc == '\n') || (sc == '\r'))
2076*7348b5c5SDavid van Moolenbroek bol = 1;
2077*7348b5c5SDavid van Moolenbroek } else if (sc == escape && escape != _POSIX_VDISABLE) {
2078*7348b5c5SDavid van Moolenbroek /*
2079*7348b5c5SDavid van Moolenbroek * Double escape is a pass through of a single escape character.
2080*7348b5c5SDavid van Moolenbroek */
2081*7348b5c5SDavid van Moolenbroek if (tcc && strip(*tbp) == escape) {
2082*7348b5c5SDavid van Moolenbroek tbp++;
2083*7348b5c5SDavid van Moolenbroek tcc--;
2084*7348b5c5SDavid van Moolenbroek count++;
2085*7348b5c5SDavid van Moolenbroek bol = 0;
2086*7348b5c5SDavid van Moolenbroek } else {
2087*7348b5c5SDavid van Moolenbroek command(0, (char *)tbp, tcc);
2088*7348b5c5SDavid van Moolenbroek bol = 1;
2089*7348b5c5SDavid van Moolenbroek count += tcc;
2090*7348b5c5SDavid van Moolenbroek tcc = 0;
2091*7348b5c5SDavid van Moolenbroek flushline = 1;
2092*7348b5c5SDavid van Moolenbroek break;
2093*7348b5c5SDavid van Moolenbroek }
2094*7348b5c5SDavid van Moolenbroek } else
2095*7348b5c5SDavid van Moolenbroek bol = 0;
2096*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
2097*7348b5c5SDavid van Moolenbroek if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
2098*7348b5c5SDavid van Moolenbroek if (tcc > 0 && strip(*tbp) == echoc) {
2099*7348b5c5SDavid van Moolenbroek tcc--; tbp++; count++;
2100*7348b5c5SDavid van Moolenbroek } else {
2101*7348b5c5SDavid van Moolenbroek dontlecho = !dontlecho;
2102*7348b5c5SDavid van Moolenbroek settimer(echotoggle);
2103*7348b5c5SDavid van Moolenbroek setconnmode(0);
2104*7348b5c5SDavid van Moolenbroek flushline = 1;
2105*7348b5c5SDavid van Moolenbroek break;
2106*7348b5c5SDavid van Moolenbroek }
2107*7348b5c5SDavid van Moolenbroek }
2108*7348b5c5SDavid van Moolenbroek #endif
2109*7348b5c5SDavid van Moolenbroek if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
2110*7348b5c5SDavid van Moolenbroek if (TerminalSpecialChars(sc) == 0) {
2111*7348b5c5SDavid van Moolenbroek bol = 1;
2112*7348b5c5SDavid van Moolenbroek break;
2113*7348b5c5SDavid van Moolenbroek }
2114*7348b5c5SDavid van Moolenbroek }
2115*7348b5c5SDavid van Moolenbroek if (my_want_state_is_wont(TELOPT_BINARY)) {
2116*7348b5c5SDavid van Moolenbroek switch (c) {
2117*7348b5c5SDavid van Moolenbroek case '\n':
2118*7348b5c5SDavid van Moolenbroek /*
2119*7348b5c5SDavid van Moolenbroek * If we are in CRMOD mode (\r ==> \n)
2120*7348b5c5SDavid van Moolenbroek * on our local machine, then probably
2121*7348b5c5SDavid van Moolenbroek * a newline (unix) is CRLF (TELNET).
2122*7348b5c5SDavid van Moolenbroek */
2123*7348b5c5SDavid van Moolenbroek if (MODE_LOCAL_CHARS(globalmode)) {
2124*7348b5c5SDavid van Moolenbroek NETADD('\r');
2125*7348b5c5SDavid van Moolenbroek }
2126*7348b5c5SDavid van Moolenbroek NETADD('\n');
2127*7348b5c5SDavid van Moolenbroek bol = flushline = 1;
2128*7348b5c5SDavid van Moolenbroek break;
2129*7348b5c5SDavid van Moolenbroek case '\r':
2130*7348b5c5SDavid van Moolenbroek if (!crlf) {
2131*7348b5c5SDavid van Moolenbroek NET2ADD('\r', '\0');
2132*7348b5c5SDavid van Moolenbroek } else {
2133*7348b5c5SDavid van Moolenbroek NET2ADD('\r', '\n');
2134*7348b5c5SDavid van Moolenbroek }
2135*7348b5c5SDavid van Moolenbroek bol = flushline = 1;
2136*7348b5c5SDavid van Moolenbroek break;
2137*7348b5c5SDavid van Moolenbroek case IAC:
2138*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, IAC);
2139*7348b5c5SDavid van Moolenbroek break;
2140*7348b5c5SDavid van Moolenbroek default:
2141*7348b5c5SDavid van Moolenbroek NETADD(c);
2142*7348b5c5SDavid van Moolenbroek break;
2143*7348b5c5SDavid van Moolenbroek }
2144*7348b5c5SDavid van Moolenbroek } else if (c == IAC) {
2145*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, IAC);
2146*7348b5c5SDavid van Moolenbroek } else {
2147*7348b5c5SDavid van Moolenbroek NETADD(c);
2148*7348b5c5SDavid van Moolenbroek }
2149*7348b5c5SDavid van Moolenbroek }
2150*7348b5c5SDavid van Moolenbroek if (count)
2151*7348b5c5SDavid van Moolenbroek ring_consumed(&ttyiring, count);
2152*7348b5c5SDavid van Moolenbroek return returnValue||count; /* Non-zero if we did anything */
2153*7348b5c5SDavid van Moolenbroek }
2154*7348b5c5SDavid van Moolenbroek
2155*7348b5c5SDavid van Moolenbroek /*
2156*7348b5c5SDavid van Moolenbroek * Scheduler()
2157*7348b5c5SDavid van Moolenbroek *
2158*7348b5c5SDavid van Moolenbroek * Try to do something.
2159*7348b5c5SDavid van Moolenbroek *
2160*7348b5c5SDavid van Moolenbroek * If we do something useful, return 1; else return 0.
2161*7348b5c5SDavid van Moolenbroek *
2162*7348b5c5SDavid van Moolenbroek */
2163*7348b5c5SDavid van Moolenbroek
2164*7348b5c5SDavid van Moolenbroek
2165*7348b5c5SDavid van Moolenbroek int
Scheduler(int block)2166*7348b5c5SDavid van Moolenbroek Scheduler(int block) /* should we block in the select ? */
2167*7348b5c5SDavid van Moolenbroek {
2168*7348b5c5SDavid van Moolenbroek /* One wants to be a bit careful about setting returnValue
2169*7348b5c5SDavid van Moolenbroek * to one, since a one implies we did some useful work,
2170*7348b5c5SDavid van Moolenbroek * and therefore probably won't be called to block next
2171*7348b5c5SDavid van Moolenbroek * time (TN3270 mode only).
2172*7348b5c5SDavid van Moolenbroek */
2173*7348b5c5SDavid van Moolenbroek int returnValue;
2174*7348b5c5SDavid van Moolenbroek int netin, netout, netex, ttyin, ttyout;
2175*7348b5c5SDavid van Moolenbroek
2176*7348b5c5SDavid van Moolenbroek /* Decide which rings should be processed */
2177*7348b5c5SDavid van Moolenbroek
2178*7348b5c5SDavid van Moolenbroek netout = ring_full_count(&netoring) &&
2179*7348b5c5SDavid van Moolenbroek (flushline ||
2180*7348b5c5SDavid van Moolenbroek (my_want_state_is_wont(TELOPT_LINEMODE)
2181*7348b5c5SDavid van Moolenbroek #ifdef KLUDGELINEMODE
2182*7348b5c5SDavid van Moolenbroek && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
2183*7348b5c5SDavid van Moolenbroek #endif
2184*7348b5c5SDavid van Moolenbroek ) ||
2185*7348b5c5SDavid van Moolenbroek my_want_state_is_will(TELOPT_BINARY));
2186*7348b5c5SDavid van Moolenbroek ttyout = ring_full_count(&ttyoring);
2187*7348b5c5SDavid van Moolenbroek
2188*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2189*7348b5c5SDavid van Moolenbroek ttyin = ring_empty_count(&ttyiring) && (clienteof == 0) && (shell_active == 0);
2190*7348b5c5SDavid van Moolenbroek #else /* defined(TN3270) */
2191*7348b5c5SDavid van Moolenbroek ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
2192*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
2193*7348b5c5SDavid van Moolenbroek
2194*7348b5c5SDavid van Moolenbroek #ifdef TN3270
2195*7348b5c5SDavid van Moolenbroek netin = ring_empty_count(&netiring);
2196*7348b5c5SDavid van Moolenbroek # else /* !defined(TN3270) */
2197*7348b5c5SDavid van Moolenbroek netin = !ISend && ring_empty_count(&netiring);
2198*7348b5c5SDavid van Moolenbroek # endif /* !defined(TN3270) */
2199*7348b5c5SDavid van Moolenbroek
2200*7348b5c5SDavid van Moolenbroek netex = !SYNCHing;
2201*7348b5c5SDavid van Moolenbroek
2202*7348b5c5SDavid van Moolenbroek /* If we have seen a signal recently, reset things */
2203*7348b5c5SDavid van Moolenbroek # ifdef TN3270
2204*7348b5c5SDavid van Moolenbroek if (HaveInput) {
2205*7348b5c5SDavid van Moolenbroek HaveInput = 0;
2206*7348b5c5SDavid van Moolenbroek (void) signal(SIGIO, inputAvailable);
2207*7348b5c5SDavid van Moolenbroek }
2208*7348b5c5SDavid van Moolenbroek #endif /* defined(TN3270) */
2209*7348b5c5SDavid van Moolenbroek
2210*7348b5c5SDavid van Moolenbroek /* Call to system code to process rings */
2211*7348b5c5SDavid van Moolenbroek
2212*7348b5c5SDavid van Moolenbroek returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
2213*7348b5c5SDavid van Moolenbroek
2214*7348b5c5SDavid van Moolenbroek /* Now, look at the input rings, looking for work to do. */
2215*7348b5c5SDavid van Moolenbroek
2216*7348b5c5SDavid van Moolenbroek if (ring_full_count(&ttyiring)) {
2217*7348b5c5SDavid van Moolenbroek # if defined(TN3270)
2218*7348b5c5SDavid van Moolenbroek if (In3270) {
2219*7348b5c5SDavid van Moolenbroek int c;
2220*7348b5c5SDavid van Moolenbroek
2221*7348b5c5SDavid van Moolenbroek c = DataFromTerminal(ttyiring.consume,
2222*7348b5c5SDavid van Moolenbroek ring_full_consecutive(&ttyiring));
2223*7348b5c5SDavid van Moolenbroek if (c) {
2224*7348b5c5SDavid van Moolenbroek returnValue = 1;
2225*7348b5c5SDavid van Moolenbroek ring_consumed(&ttyiring, c);
2226*7348b5c5SDavid van Moolenbroek }
2227*7348b5c5SDavid van Moolenbroek } else {
2228*7348b5c5SDavid van Moolenbroek # endif /* defined(TN3270) */
2229*7348b5c5SDavid van Moolenbroek returnValue |= telsnd();
2230*7348b5c5SDavid van Moolenbroek # if defined(TN3270)
2231*7348b5c5SDavid van Moolenbroek }
2232*7348b5c5SDavid van Moolenbroek # endif /* defined(TN3270) */
2233*7348b5c5SDavid van Moolenbroek }
2234*7348b5c5SDavid van Moolenbroek
2235*7348b5c5SDavid van Moolenbroek if (ring_full_count(&netiring)) {
2236*7348b5c5SDavid van Moolenbroek # if !defined(TN3270)
2237*7348b5c5SDavid van Moolenbroek returnValue |= telrcv();
2238*7348b5c5SDavid van Moolenbroek # else /* !defined(TN3270) */
2239*7348b5c5SDavid van Moolenbroek returnValue = Push3270();
2240*7348b5c5SDavid van Moolenbroek # endif /* !defined(TN3270) */
2241*7348b5c5SDavid van Moolenbroek }
2242*7348b5c5SDavid van Moolenbroek return returnValue;
2243*7348b5c5SDavid van Moolenbroek }
2244*7348b5c5SDavid van Moolenbroek
2245*7348b5c5SDavid van Moolenbroek /*
2246*7348b5c5SDavid van Moolenbroek * Select from tty and network...
2247*7348b5c5SDavid van Moolenbroek */
2248*7348b5c5SDavid van Moolenbroek void
telnet(const char * user)2249*7348b5c5SDavid van Moolenbroek telnet(const char *user)
2250*7348b5c5SDavid van Moolenbroek {
2251*7348b5c5SDavid van Moolenbroek sys_telnet_init();
2252*7348b5c5SDavid van Moolenbroek
2253*7348b5c5SDavid van Moolenbroek #if defined(AUTHENTICATION) || defined(ENCRYPTION)
2254*7348b5c5SDavid van Moolenbroek {
2255*7348b5c5SDavid van Moolenbroek static char local_host[MAXHOSTNAMELEN + 1] = { 0 };
2256*7348b5c5SDavid van Moolenbroek
2257*7348b5c5SDavid van Moolenbroek if (!local_host[0]) {
2258*7348b5c5SDavid van Moolenbroek gethostname(local_host, sizeof(local_host));
2259*7348b5c5SDavid van Moolenbroek local_host[sizeof(local_host)-1] = 0;
2260*7348b5c5SDavid van Moolenbroek }
2261*7348b5c5SDavid van Moolenbroek auth_encrypt_init(local_host, hostname, "TELNET", 0);
2262*7348b5c5SDavid van Moolenbroek auth_encrypt_user(user);
2263*7348b5c5SDavid van Moolenbroek }
2264*7348b5c5SDavid van Moolenbroek #endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
2265*7348b5c5SDavid van Moolenbroek # if !defined(TN3270)
2266*7348b5c5SDavid van Moolenbroek if (telnetport) {
2267*7348b5c5SDavid van Moolenbroek #ifdef AUTHENTICATION
2268*7348b5c5SDavid van Moolenbroek if (autologin)
2269*7348b5c5SDavid van Moolenbroek send_will(TELOPT_AUTHENTICATION, 1);
2270*7348b5c5SDavid van Moolenbroek #endif
2271*7348b5c5SDavid van Moolenbroek #ifdef ENCRYPTION
2272*7348b5c5SDavid van Moolenbroek send_do(TELOPT_ENCRYPT, 1);
2273*7348b5c5SDavid van Moolenbroek send_will(TELOPT_ENCRYPT, 1);
2274*7348b5c5SDavid van Moolenbroek #endif /* ENCRYPTION */
2275*7348b5c5SDavid van Moolenbroek send_do(TELOPT_SGA, 1);
2276*7348b5c5SDavid van Moolenbroek send_will(TELOPT_TTYPE, 1);
2277*7348b5c5SDavid van Moolenbroek send_will(TELOPT_NAWS, 1);
2278*7348b5c5SDavid van Moolenbroek send_will(TELOPT_TSPEED, 1);
2279*7348b5c5SDavid van Moolenbroek send_will(TELOPT_LFLOW, 1);
2280*7348b5c5SDavid van Moolenbroek send_will(TELOPT_LINEMODE, 1);
2281*7348b5c5SDavid van Moolenbroek send_will(TELOPT_NEW_ENVIRON, 1);
2282*7348b5c5SDavid van Moolenbroek send_do(TELOPT_STATUS, 1);
2283*7348b5c5SDavid van Moolenbroek if (env_getvalue((const unsigned char *)"DISPLAY"))
2284*7348b5c5SDavid van Moolenbroek send_will(TELOPT_XDISPLOC, 1);
2285*7348b5c5SDavid van Moolenbroek if (eight)
2286*7348b5c5SDavid van Moolenbroek tel_enter_binary(eight);
2287*7348b5c5SDavid van Moolenbroek }
2288*7348b5c5SDavid van Moolenbroek # endif /* !defined(TN3270) */
2289*7348b5c5SDavid van Moolenbroek
2290*7348b5c5SDavid van Moolenbroek # if !defined(TN3270)
2291*7348b5c5SDavid van Moolenbroek for (;;) {
2292*7348b5c5SDavid van Moolenbroek int schedValue;
2293*7348b5c5SDavid van Moolenbroek
2294*7348b5c5SDavid van Moolenbroek while ((schedValue = Scheduler(0)) != 0) {
2295*7348b5c5SDavid van Moolenbroek if (schedValue == -1) {
2296*7348b5c5SDavid van Moolenbroek setcommandmode();
2297*7348b5c5SDavid van Moolenbroek return;
2298*7348b5c5SDavid van Moolenbroek }
2299*7348b5c5SDavid van Moolenbroek }
2300*7348b5c5SDavid van Moolenbroek
2301*7348b5c5SDavid van Moolenbroek if (Scheduler(1) == -1) {
2302*7348b5c5SDavid van Moolenbroek setcommandmode();
2303*7348b5c5SDavid van Moolenbroek return;
2304*7348b5c5SDavid van Moolenbroek }
2305*7348b5c5SDavid van Moolenbroek }
2306*7348b5c5SDavid van Moolenbroek # else /* !defined(TN3270) */
2307*7348b5c5SDavid van Moolenbroek for (;;) {
2308*7348b5c5SDavid van Moolenbroek int schedValue;
2309*7348b5c5SDavid van Moolenbroek
2310*7348b5c5SDavid van Moolenbroek while (!In3270 && !shell_active) {
2311*7348b5c5SDavid van Moolenbroek if (Scheduler(1) == -1) {
2312*7348b5c5SDavid van Moolenbroek setcommandmode();
2313*7348b5c5SDavid van Moolenbroek return;
2314*7348b5c5SDavid van Moolenbroek }
2315*7348b5c5SDavid van Moolenbroek }
2316*7348b5c5SDavid van Moolenbroek
2317*7348b5c5SDavid van Moolenbroek while ((schedValue = Scheduler(0)) != 0) {
2318*7348b5c5SDavid van Moolenbroek if (schedValue == -1) {
2319*7348b5c5SDavid van Moolenbroek setcommandmode();
2320*7348b5c5SDavid van Moolenbroek return;
2321*7348b5c5SDavid van Moolenbroek }
2322*7348b5c5SDavid van Moolenbroek }
2323*7348b5c5SDavid van Moolenbroek /* If there is data waiting to go out to terminal, don't
2324*7348b5c5SDavid van Moolenbroek * schedule any more data for the terminal.
2325*7348b5c5SDavid van Moolenbroek */
2326*7348b5c5SDavid van Moolenbroek if (ring_full_count(&ttyoring)) {
2327*7348b5c5SDavid van Moolenbroek schedValue = 1;
2328*7348b5c5SDavid van Moolenbroek } else {
2329*7348b5c5SDavid van Moolenbroek if (shell_active) {
2330*7348b5c5SDavid van Moolenbroek if (shell_continue() == 0) {
2331*7348b5c5SDavid van Moolenbroek ConnectScreen();
2332*7348b5c5SDavid van Moolenbroek }
2333*7348b5c5SDavid van Moolenbroek } else if (In3270) {
2334*7348b5c5SDavid van Moolenbroek schedValue = DoTerminalOutput();
2335*7348b5c5SDavid van Moolenbroek }
2336*7348b5c5SDavid van Moolenbroek }
2337*7348b5c5SDavid van Moolenbroek if (schedValue && (shell_active == 0)) {
2338*7348b5c5SDavid van Moolenbroek if (Scheduler(1) == -1) {
2339*7348b5c5SDavid van Moolenbroek setcommandmode();
2340*7348b5c5SDavid van Moolenbroek return;
2341*7348b5c5SDavid van Moolenbroek }
2342*7348b5c5SDavid van Moolenbroek }
2343*7348b5c5SDavid van Moolenbroek }
2344*7348b5c5SDavid van Moolenbroek # endif /* !defined(TN3270) */
2345*7348b5c5SDavid van Moolenbroek }
2346*7348b5c5SDavid van Moolenbroek
2347*7348b5c5SDavid van Moolenbroek #if 0 /* XXX - this not being in is a bug */
2348*7348b5c5SDavid van Moolenbroek /*
2349*7348b5c5SDavid van Moolenbroek * nextitem()
2350*7348b5c5SDavid van Moolenbroek *
2351*7348b5c5SDavid van Moolenbroek * Return the address of the next "item" in the TELNET data
2352*7348b5c5SDavid van Moolenbroek * stream. This will be the address of the next character if
2353*7348b5c5SDavid van Moolenbroek * the current address is a user data character, or it will
2354*7348b5c5SDavid van Moolenbroek * be the address of the character following the TELNET command
2355*7348b5c5SDavid van Moolenbroek * if the current address is a TELNET IAC ("I Am a Command")
2356*7348b5c5SDavid van Moolenbroek * character.
2357*7348b5c5SDavid van Moolenbroek */
2358*7348b5c5SDavid van Moolenbroek
2359*7348b5c5SDavid van Moolenbroek static char *
2360*7348b5c5SDavid van Moolenbroek nextitem(char *current)
2361*7348b5c5SDavid van Moolenbroek {
2362*7348b5c5SDavid van Moolenbroek if ((*current&0xff) != IAC) {
2363*7348b5c5SDavid van Moolenbroek return current+1;
2364*7348b5c5SDavid van Moolenbroek }
2365*7348b5c5SDavid van Moolenbroek switch (*(current+1)&0xff) {
2366*7348b5c5SDavid van Moolenbroek case DO:
2367*7348b5c5SDavid van Moolenbroek case DONT:
2368*7348b5c5SDavid van Moolenbroek case WILL:
2369*7348b5c5SDavid van Moolenbroek case WONT:
2370*7348b5c5SDavid van Moolenbroek return current+3;
2371*7348b5c5SDavid van Moolenbroek case SB: /* loop forever looking for the SE */
2372*7348b5c5SDavid van Moolenbroek {
2373*7348b5c5SDavid van Moolenbroek char *look = current+2;
2374*7348b5c5SDavid van Moolenbroek
2375*7348b5c5SDavid van Moolenbroek for (;;) {
2376*7348b5c5SDavid van Moolenbroek if ((*look++&0xff) == IAC) {
2377*7348b5c5SDavid van Moolenbroek if ((*look++&0xff) == SE) {
2378*7348b5c5SDavid van Moolenbroek return look;
2379*7348b5c5SDavid van Moolenbroek }
2380*7348b5c5SDavid van Moolenbroek }
2381*7348b5c5SDavid van Moolenbroek }
2382*7348b5c5SDavid van Moolenbroek }
2383*7348b5c5SDavid van Moolenbroek default:
2384*7348b5c5SDavid van Moolenbroek return current+2;
2385*7348b5c5SDavid van Moolenbroek }
2386*7348b5c5SDavid van Moolenbroek }
2387*7348b5c5SDavid van Moolenbroek #endif /* 0 */
2388*7348b5c5SDavid van Moolenbroek
2389*7348b5c5SDavid van Moolenbroek /*
2390*7348b5c5SDavid van Moolenbroek * netclear()
2391*7348b5c5SDavid van Moolenbroek *
2392*7348b5c5SDavid van Moolenbroek * We are about to do a TELNET SYNCH operation. Clear
2393*7348b5c5SDavid van Moolenbroek * the path to the network.
2394*7348b5c5SDavid van Moolenbroek *
2395*7348b5c5SDavid van Moolenbroek * Things are a bit tricky since we may have sent the first
2396*7348b5c5SDavid van Moolenbroek * byte or so of a previous TELNET command into the network.
2397*7348b5c5SDavid van Moolenbroek * So, we have to scan the network buffer from the beginning
2398*7348b5c5SDavid van Moolenbroek * until we are up to where we want to be.
2399*7348b5c5SDavid van Moolenbroek *
2400*7348b5c5SDavid van Moolenbroek * A side effect of what we do, just to keep things
2401*7348b5c5SDavid van Moolenbroek * simple, is to clear the urgent data pointer. The principal
2402*7348b5c5SDavid van Moolenbroek * caller should be setting the urgent data pointer AFTER calling
2403*7348b5c5SDavid van Moolenbroek * us in any case.
2404*7348b5c5SDavid van Moolenbroek */
2405*7348b5c5SDavid van Moolenbroek
2406*7348b5c5SDavid van Moolenbroek static void
netclear(void)2407*7348b5c5SDavid van Moolenbroek netclear(void)
2408*7348b5c5SDavid van Moolenbroek {
2409*7348b5c5SDavid van Moolenbroek #if 0 /* XXX */
2410*7348b5c5SDavid van Moolenbroek char *thisitem, *next;
2411*7348b5c5SDavid van Moolenbroek char *good;
2412*7348b5c5SDavid van Moolenbroek #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
2413*7348b5c5SDavid van Moolenbroek ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
2414*7348b5c5SDavid van Moolenbroek
2415*7348b5c5SDavid van Moolenbroek thisitem = netobuf;
2416*7348b5c5SDavid van Moolenbroek
2417*7348b5c5SDavid van Moolenbroek while ((next = nextitem(thisitem)) <= netobuf.send) {
2418*7348b5c5SDavid van Moolenbroek thisitem = next;
2419*7348b5c5SDavid van Moolenbroek }
2420*7348b5c5SDavid van Moolenbroek
2421*7348b5c5SDavid van Moolenbroek /* Now, thisitem is first before/at boundary. */
2422*7348b5c5SDavid van Moolenbroek
2423*7348b5c5SDavid van Moolenbroek good = netobuf; /* where the good bytes go */
2424*7348b5c5SDavid van Moolenbroek
2425*7348b5c5SDavid van Moolenbroek while (netoring.add > thisitem) {
2426*7348b5c5SDavid van Moolenbroek if (wewant(thisitem)) {
2427*7348b5c5SDavid van Moolenbroek int length;
2428*7348b5c5SDavid van Moolenbroek
2429*7348b5c5SDavid van Moolenbroek next = thisitem;
2430*7348b5c5SDavid van Moolenbroek do {
2431*7348b5c5SDavid van Moolenbroek next = nextitem(next);
2432*7348b5c5SDavid van Moolenbroek } while (wewant(next) && (nfrontp > next));
2433*7348b5c5SDavid van Moolenbroek length = next-thisitem;
2434*7348b5c5SDavid van Moolenbroek memmove(good, thisitem, length);
2435*7348b5c5SDavid van Moolenbroek good += length;
2436*7348b5c5SDavid van Moolenbroek thisitem = next;
2437*7348b5c5SDavid van Moolenbroek } else {
2438*7348b5c5SDavid van Moolenbroek thisitem = nextitem(thisitem);
2439*7348b5c5SDavid van Moolenbroek }
2440*7348b5c5SDavid van Moolenbroek }
2441*7348b5c5SDavid van Moolenbroek
2442*7348b5c5SDavid van Moolenbroek #endif /* 0 */
2443*7348b5c5SDavid van Moolenbroek }
2444*7348b5c5SDavid van Moolenbroek
2445*7348b5c5SDavid van Moolenbroek /*
2446*7348b5c5SDavid van Moolenbroek * These routines add various telnet commands to the data stream.
2447*7348b5c5SDavid van Moolenbroek */
2448*7348b5c5SDavid van Moolenbroek
2449*7348b5c5SDavid van Moolenbroek static void
doflush(void)2450*7348b5c5SDavid van Moolenbroek doflush(void)
2451*7348b5c5SDavid van Moolenbroek {
2452*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, DO);
2453*7348b5c5SDavid van Moolenbroek NETADD(TELOPT_TM);
2454*7348b5c5SDavid van Moolenbroek flushline = 1;
2455*7348b5c5SDavid van Moolenbroek flushout = 1;
2456*7348b5c5SDavid van Moolenbroek (void) ttyflush(1); /* Flush/drop output */
2457*7348b5c5SDavid van Moolenbroek /* do printoption AFTER flush, otherwise the output gets tossed... */
2458*7348b5c5SDavid van Moolenbroek printoption("SENT", DO, TELOPT_TM);
2459*7348b5c5SDavid van Moolenbroek }
2460*7348b5c5SDavid van Moolenbroek
2461*7348b5c5SDavid van Moolenbroek void
xmitAO(void)2462*7348b5c5SDavid van Moolenbroek xmitAO(void)
2463*7348b5c5SDavid van Moolenbroek {
2464*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, AO);
2465*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, AO);
2466*7348b5c5SDavid van Moolenbroek if (autoflush) {
2467*7348b5c5SDavid van Moolenbroek doflush();
2468*7348b5c5SDavid van Moolenbroek }
2469*7348b5c5SDavid van Moolenbroek }
2470*7348b5c5SDavid van Moolenbroek
2471*7348b5c5SDavid van Moolenbroek
2472*7348b5c5SDavid van Moolenbroek void
xmitEL(void)2473*7348b5c5SDavid van Moolenbroek xmitEL(void)
2474*7348b5c5SDavid van Moolenbroek {
2475*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, EL);
2476*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, EL);
2477*7348b5c5SDavid van Moolenbroek }
2478*7348b5c5SDavid van Moolenbroek
2479*7348b5c5SDavid van Moolenbroek void
xmitEC(void)2480*7348b5c5SDavid van Moolenbroek xmitEC(void)
2481*7348b5c5SDavid van Moolenbroek {
2482*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, EC);
2483*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, EC);
2484*7348b5c5SDavid van Moolenbroek }
2485*7348b5c5SDavid van Moolenbroek
2486*7348b5c5SDavid van Moolenbroek
2487*7348b5c5SDavid van Moolenbroek int
dosynch(char * s)2488*7348b5c5SDavid van Moolenbroek dosynch(char *s)
2489*7348b5c5SDavid van Moolenbroek {
2490*7348b5c5SDavid van Moolenbroek netclear(); /* clear the path to the network */
2491*7348b5c5SDavid van Moolenbroek NETADD(IAC);
2492*7348b5c5SDavid van Moolenbroek setneturg();
2493*7348b5c5SDavid van Moolenbroek NETADD(DM);
2494*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, DM);
2495*7348b5c5SDavid van Moolenbroek return 1;
2496*7348b5c5SDavid van Moolenbroek }
2497*7348b5c5SDavid van Moolenbroek
2498*7348b5c5SDavid van Moolenbroek int want_status_response = 0;
2499*7348b5c5SDavid van Moolenbroek
2500*7348b5c5SDavid van Moolenbroek int
get_status(char * s)2501*7348b5c5SDavid van Moolenbroek get_status(char *s)
2502*7348b5c5SDavid van Moolenbroek {
2503*7348b5c5SDavid van Moolenbroek unsigned char tmp[16];
2504*7348b5c5SDavid van Moolenbroek unsigned char *cp;
2505*7348b5c5SDavid van Moolenbroek
2506*7348b5c5SDavid van Moolenbroek if (my_want_state_is_dont(TELOPT_STATUS)) {
2507*7348b5c5SDavid van Moolenbroek printf("Remote side does not support STATUS option\n");
2508*7348b5c5SDavid van Moolenbroek return 0;
2509*7348b5c5SDavid van Moolenbroek }
2510*7348b5c5SDavid van Moolenbroek cp = tmp;
2511*7348b5c5SDavid van Moolenbroek
2512*7348b5c5SDavid van Moolenbroek *cp++ = IAC;
2513*7348b5c5SDavid van Moolenbroek *cp++ = SB;
2514*7348b5c5SDavid van Moolenbroek *cp++ = TELOPT_STATUS;
2515*7348b5c5SDavid van Moolenbroek *cp++ = TELQUAL_SEND;
2516*7348b5c5SDavid van Moolenbroek *cp++ = IAC;
2517*7348b5c5SDavid van Moolenbroek *cp++ = SE;
2518*7348b5c5SDavid van Moolenbroek if (NETROOM() >= cp - tmp) {
2519*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, tmp, cp-tmp);
2520*7348b5c5SDavid van Moolenbroek printsub('>', tmp+2, cp - tmp - 2);
2521*7348b5c5SDavid van Moolenbroek }
2522*7348b5c5SDavid van Moolenbroek ++want_status_response;
2523*7348b5c5SDavid van Moolenbroek return 1;
2524*7348b5c5SDavid van Moolenbroek }
2525*7348b5c5SDavid van Moolenbroek
2526*7348b5c5SDavid van Moolenbroek void
intp(void)2527*7348b5c5SDavid van Moolenbroek intp(void)
2528*7348b5c5SDavid van Moolenbroek {
2529*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, IP);
2530*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, IP);
2531*7348b5c5SDavid van Moolenbroek flushline = 1;
2532*7348b5c5SDavid van Moolenbroek if (autoflush) {
2533*7348b5c5SDavid van Moolenbroek doflush();
2534*7348b5c5SDavid van Moolenbroek }
2535*7348b5c5SDavid van Moolenbroek if (autosynch) {
2536*7348b5c5SDavid van Moolenbroek dosynch(NULL);
2537*7348b5c5SDavid van Moolenbroek }
2538*7348b5c5SDavid van Moolenbroek }
2539*7348b5c5SDavid van Moolenbroek
2540*7348b5c5SDavid van Moolenbroek void
sendbrk(void)2541*7348b5c5SDavid van Moolenbroek sendbrk(void)
2542*7348b5c5SDavid van Moolenbroek {
2543*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, BREAK);
2544*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, BREAK);
2545*7348b5c5SDavid van Moolenbroek flushline = 1;
2546*7348b5c5SDavid van Moolenbroek if (autoflush) {
2547*7348b5c5SDavid van Moolenbroek doflush();
2548*7348b5c5SDavid van Moolenbroek }
2549*7348b5c5SDavid van Moolenbroek if (autosynch) {
2550*7348b5c5SDavid van Moolenbroek dosynch(NULL);
2551*7348b5c5SDavid van Moolenbroek }
2552*7348b5c5SDavid van Moolenbroek }
2553*7348b5c5SDavid van Moolenbroek
2554*7348b5c5SDavid van Moolenbroek void
sendabort(void)2555*7348b5c5SDavid van Moolenbroek sendabort(void)
2556*7348b5c5SDavid van Moolenbroek {
2557*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, ABORT);
2558*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, ABORT);
2559*7348b5c5SDavid van Moolenbroek flushline = 1;
2560*7348b5c5SDavid van Moolenbroek if (autoflush) {
2561*7348b5c5SDavid van Moolenbroek doflush();
2562*7348b5c5SDavid van Moolenbroek }
2563*7348b5c5SDavid van Moolenbroek if (autosynch) {
2564*7348b5c5SDavid van Moolenbroek dosynch(NULL);
2565*7348b5c5SDavid van Moolenbroek }
2566*7348b5c5SDavid van Moolenbroek }
2567*7348b5c5SDavid van Moolenbroek
2568*7348b5c5SDavid van Moolenbroek void
sendsusp(void)2569*7348b5c5SDavid van Moolenbroek sendsusp(void)
2570*7348b5c5SDavid van Moolenbroek {
2571*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, SUSP);
2572*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, SUSP);
2573*7348b5c5SDavid van Moolenbroek flushline = 1;
2574*7348b5c5SDavid van Moolenbroek if (autoflush) {
2575*7348b5c5SDavid van Moolenbroek doflush();
2576*7348b5c5SDavid van Moolenbroek }
2577*7348b5c5SDavid van Moolenbroek if (autosynch) {
2578*7348b5c5SDavid van Moolenbroek dosynch(NULL);
2579*7348b5c5SDavid van Moolenbroek }
2580*7348b5c5SDavid van Moolenbroek }
2581*7348b5c5SDavid van Moolenbroek
2582*7348b5c5SDavid van Moolenbroek void
sendeof(void)2583*7348b5c5SDavid van Moolenbroek sendeof(void)
2584*7348b5c5SDavid van Moolenbroek {
2585*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, xEOF);
2586*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, xEOF);
2587*7348b5c5SDavid van Moolenbroek }
2588*7348b5c5SDavid van Moolenbroek
2589*7348b5c5SDavid van Moolenbroek void
sendayt(void)2590*7348b5c5SDavid van Moolenbroek sendayt(void)
2591*7348b5c5SDavid van Moolenbroek {
2592*7348b5c5SDavid van Moolenbroek NET2ADD(IAC, AYT);
2593*7348b5c5SDavid van Moolenbroek printoption("SENT", IAC, AYT);
2594*7348b5c5SDavid van Moolenbroek }
2595*7348b5c5SDavid van Moolenbroek
2596*7348b5c5SDavid van Moolenbroek /*
2597*7348b5c5SDavid van Moolenbroek * Send a window size update to the remote system.
2598*7348b5c5SDavid van Moolenbroek */
2599*7348b5c5SDavid van Moolenbroek
2600*7348b5c5SDavid van Moolenbroek void
sendnaws(void)2601*7348b5c5SDavid van Moolenbroek sendnaws(void)
2602*7348b5c5SDavid van Moolenbroek {
2603*7348b5c5SDavid van Moolenbroek long rows, cols;
2604*7348b5c5SDavid van Moolenbroek unsigned char tmp[16];
2605*7348b5c5SDavid van Moolenbroek unsigned char *cp;
2606*7348b5c5SDavid van Moolenbroek
2607*7348b5c5SDavid van Moolenbroek if (my_state_is_wont(TELOPT_NAWS))
2608*7348b5c5SDavid van Moolenbroek return;
2609*7348b5c5SDavid van Moolenbroek
2610*7348b5c5SDavid van Moolenbroek #define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2611*7348b5c5SDavid van Moolenbroek if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2612*7348b5c5SDavid van Moolenbroek
2613*7348b5c5SDavid van Moolenbroek if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
2614*7348b5c5SDavid van Moolenbroek return;
2615*7348b5c5SDavid van Moolenbroek }
2616*7348b5c5SDavid van Moolenbroek
2617*7348b5c5SDavid van Moolenbroek cp = tmp;
2618*7348b5c5SDavid van Moolenbroek
2619*7348b5c5SDavid van Moolenbroek *cp++ = IAC;
2620*7348b5c5SDavid van Moolenbroek *cp++ = SB;
2621*7348b5c5SDavid van Moolenbroek *cp++ = TELOPT_NAWS;
2622*7348b5c5SDavid van Moolenbroek PUTSHORT(cp, cols);
2623*7348b5c5SDavid van Moolenbroek PUTSHORT(cp, rows);
2624*7348b5c5SDavid van Moolenbroek *cp++ = IAC;
2625*7348b5c5SDavid van Moolenbroek *cp++ = SE;
2626*7348b5c5SDavid van Moolenbroek if (NETROOM() >= cp - tmp) {
2627*7348b5c5SDavid van Moolenbroek ring_supply_data(&netoring, tmp, cp-tmp);
2628*7348b5c5SDavid van Moolenbroek printsub('>', tmp+2, cp - tmp - 2);
2629*7348b5c5SDavid van Moolenbroek }
2630*7348b5c5SDavid van Moolenbroek }
2631*7348b5c5SDavid van Moolenbroek
2632*7348b5c5SDavid van Moolenbroek void
tel_enter_binary(int rw)2633*7348b5c5SDavid van Moolenbroek tel_enter_binary(int rw)
2634*7348b5c5SDavid van Moolenbroek {
2635*7348b5c5SDavid van Moolenbroek if (rw&1)
2636*7348b5c5SDavid van Moolenbroek send_do(TELOPT_BINARY, 1);
2637*7348b5c5SDavid van Moolenbroek if (rw&2)
2638*7348b5c5SDavid van Moolenbroek send_will(TELOPT_BINARY, 1);
2639*7348b5c5SDavid van Moolenbroek }
2640*7348b5c5SDavid van Moolenbroek
2641*7348b5c5SDavid van Moolenbroek void
tel_leave_binary(int rw)2642*7348b5c5SDavid van Moolenbroek tel_leave_binary(int rw)
2643*7348b5c5SDavid van Moolenbroek {
2644*7348b5c5SDavid van Moolenbroek if (rw&1)
2645*7348b5c5SDavid van Moolenbroek send_dont(TELOPT_BINARY, 1);
2646*7348b5c5SDavid van Moolenbroek if (rw&2)
2647*7348b5c5SDavid van Moolenbroek send_wont(TELOPT_BINARY, 1);
2648*7348b5c5SDavid van Moolenbroek }
2649