Tue Dec 18 18:37:26 2018 UTC ()
Pull up following revision(s) (requested by maya in ticket #1665):

	usr.bin/telnet/utilities.c: revision 1.24
	usr.bin/telnet/telnet.c: revision 1.37

switch sprintf to snprintf in places.

Reported by hacker fantastic, thanks!

ok xtos.


(martin)
diff -r1.36 -r1.36.20.1 src/usr.bin/telnet/telnet.c
diff -r1.23 -r1.23.20.1 src/usr.bin/telnet/utilities.c

cvs diff -r1.36 -r1.36.20.1 src/usr.bin/telnet/telnet.c (switch to unified diff)

--- src/usr.bin/telnet/telnet.c 2012/01/10 13:49:32 1.36
+++ src/usr.bin/telnet/telnet.c 2018/12/18 18:37:26 1.36.20.1
@@ -1,1986 +1,1986 @@ @@ -1,1986 +1,1986 @@
1/* $NetBSD: telnet.c,v 1.36 2012/01/10 13:49:32 christos Exp $ */ 1/* $NetBSD: telnet.c,v 1.36.20.1 2018/12/18 18:37:26 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1990, 1993 4 * Copyright (c) 1988, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34#if 0 34#if 0
35static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; 35static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95";
36#else 36#else
37__RCSID("$NetBSD: telnet.c,v 1.36 2012/01/10 13:49:32 christos Exp $"); 37__RCSID("$NetBSD: telnet.c,v 1.36.20.1 2018/12/18 18:37:26 martin Exp $");
38#endif 38#endif
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#include <sys/param.h> 41#include <sys/param.h>
42 42
43#include <signal.h> 43#include <signal.h>
44#include <term.h> 44#include <term.h>
45#include <unistd.h> 45#include <unistd.h>
46/* By the way, we need to include curses.h before telnet.h since, 46/* By the way, we need to include curses.h before telnet.h since,
47 * among other things, telnet.h #defines 'DO', which is a variable 47 * among other things, telnet.h #defines 'DO', which is a variable
48 * declared in curses.h. 48 * declared in curses.h.
49 */ 49 */
50 50
51#include <arpa/telnet.h> 51#include <arpa/telnet.h>
52 52
53#include <ctype.h> 53#include <ctype.h>
54 54
55#include "ring.h" 55#include "ring.h"
56#include "defines.h" 56#include "defines.h"
57#include "externs.h" 57#include "externs.h"
58#include "types.h" 58#include "types.h"
59#include "general.h" 59#include "general.h"
60 60
61#include <libtelnet/misc.h> 61#include <libtelnet/misc.h>
62#ifdef AUTHENTICATION 62#ifdef AUTHENTICATION
63#include <libtelnet/auth.h> 63#include <libtelnet/auth.h>
64#endif 64#endif
65#ifdef ENCRYPTION 65#ifdef ENCRYPTION
66#include <libtelnet/encrypt.h> 66#include <libtelnet/encrypt.h>
67#endif 67#endif
68 68
69#define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) 69#define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x))
70 70
71static unsigned char subbuffer[SUBBUFSIZE], 71static unsigned char subbuffer[SUBBUFSIZE],
72 *subpointer, *subend; /* buffer for sub-options */ 72 *subpointer, *subend; /* buffer for sub-options */
73#define SB_CLEAR() subpointer = subbuffer; 73#define SB_CLEAR() subpointer = subbuffer;
74#define SB_TERM() { subend = subpointer; SB_CLEAR(); } 74#define SB_TERM() { subend = subpointer; SB_CLEAR(); }
75#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ 75#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \
76 *subpointer++ = (c); \ 76 *subpointer++ = (c); \
77 } 77 }
78 78
79#define SB_GET() ((*subpointer++)&0xff) 79#define SB_GET() ((*subpointer++)&0xff)
80#define SB_PEEK() ((*subpointer)&0xff) 80#define SB_PEEK() ((*subpointer)&0xff)
81#define SB_EOF() (subpointer >= subend) 81#define SB_EOF() (subpointer >= subend)
82#define SB_LEN() (subend - subpointer) 82#define SB_LEN() (subend - subpointer)
83 83
84char options[256]; /* The combined options */ 84char options[256]; /* The combined options */
85char do_dont_resp[256]; 85char do_dont_resp[256];
86char will_wont_resp[256]; 86char will_wont_resp[256];
87 87
88int 88int
89 eight = 0, 89 eight = 0,
90 autologin = 0, /* Autologin anyone? */ 90 autologin = 0, /* Autologin anyone? */
91 skiprc = 0, 91 skiprc = 0,
92 connected, 92 connected,
93 showoptions, 93 showoptions,
94 In3270, /* Are we in 3270 mode? */ 94 In3270, /* Are we in 3270 mode? */
95 ISend, /* trying to send network data in */ 95 ISend, /* trying to send network data in */
96 telnet_debug = 0, 96 telnet_debug = 0,
97 crmod, 97 crmod,
98 netdata, /* Print out network data flow */ 98 netdata, /* Print out network data flow */
99 crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */ 99 crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
100#ifdef TN3270 100#ifdef TN3270
101 noasynchtty = 0,/* User specified "-noasynch" on command line */ 101 noasynchtty = 0,/* User specified "-noasynch" on command line */
102 noasynchnet = 0,/* User specified "-noasynch" on command line */ 102 noasynchnet = 0,/* User specified "-noasynch" on command line */
103 askedSGA = 0, /* We have talked about suppress go ahead */ 103 askedSGA = 0, /* We have talked about suppress go ahead */
104#endif /* defined(TN3270) */ 104#endif /* defined(TN3270) */
105 telnetport, 105 telnetport,
106 SYNCHing, /* we are in TELNET SYNCH mode */ 106 SYNCHing, /* we are in TELNET SYNCH mode */
107 flushout, /* flush output */ 107 flushout, /* flush output */
108 autoflush = 0, /* flush output when interrupting? */ 108 autoflush = 0, /* flush output when interrupting? */
109 autosynch, /* send interrupt characters with SYNCH? */ 109 autosynch, /* send interrupt characters with SYNCH? */
110 localflow, /* we handle flow control locally */ 110 localflow, /* we handle flow control locally */
111 restartany, /* if flow control enabled, restart on any character */ 111 restartany, /* if flow control enabled, restart on any character */
112 localchars, /* we recognize interrupt/quit */ 112 localchars, /* we recognize interrupt/quit */
113 donelclchars, /* the user has set "localchars" */ 113 donelclchars, /* the user has set "localchars" */
114 donebinarytoggle, /* the user has put us in binary */ 114 donebinarytoggle, /* the user has put us in binary */
115 dontlecho, /* do we suppress local echoing right now? */ 115 dontlecho, /* do we suppress local echoing right now? */
116 globalmode, 116 globalmode,
117 doaddrlookup = 1, /* do a reverse address lookup? */ 117 doaddrlookup = 1, /* do a reverse address lookup? */
118 clienteof = 0; 118 clienteof = 0;
119 119
120char *prompt = 0; 120char *prompt = 0;
121 121
122cc_t escape; 122cc_t escape;
123cc_t rlogin; 123cc_t rlogin;
124#ifdef KLUDGELINEMODE 124#ifdef KLUDGELINEMODE
125cc_t echoc; 125cc_t echoc;
126#endif 126#endif
127 127
128/* 128/*
129 * Telnet receiver states for fsm 129 * Telnet receiver states for fsm
130 */ 130 */
131#define TS_DATA 0 131#define TS_DATA 0
132#define TS_IAC 1 132#define TS_IAC 1
133#define TS_WILL 2 133#define TS_WILL 2
134#define TS_WONT 3 134#define TS_WONT 3
135#define TS_DO 4 135#define TS_DO 4
136#define TS_DONT 5 136#define TS_DONT 5
137#define TS_CR 6 137#define TS_CR 6
138#define TS_SB 7 /* sub-option collection */ 138#define TS_SB 7 /* sub-option collection */
139#define TS_SE 8 /* looking for sub-option end */ 139#define TS_SE 8 /* looking for sub-option end */
140 140
141static int telrcv_state; 141static int telrcv_state;
142#ifdef OLD_ENVIRON 142#ifdef OLD_ENVIRON
143unsigned char telopt_environ = TELOPT_NEW_ENVIRON; 143unsigned char telopt_environ = TELOPT_NEW_ENVIRON;
144#else 144#else
145# define telopt_environ TELOPT_NEW_ENVIRON 145# define telopt_environ TELOPT_NEW_ENVIRON
146#endif 146#endif
147 147
148jmp_buf toplevel = { 0 }; 148jmp_buf toplevel = { 0 };
149 149
150int flushline; 150int flushline;
151int linemode; 151int linemode;
152 152
153#ifdef KLUDGELINEMODE 153#ifdef KLUDGELINEMODE
154int kludgelinemode = 1; 154int kludgelinemode = 1;
155#endif 155#endif
156 156
157static void dooption(int); 157static void dooption(int);
158static void dontoption(int); 158static void dontoption(int);
159static void suboption(void); 159static void suboption(void);
160static int telsnd(void); 160static int telsnd(void);
161static void netclear(void); 161static void netclear(void);
162static void doflush(void); 162static void doflush(void);
163 163
164/* 164/*
165 * The following are some clocks used to decide how to interpret 165 * The following are some clocks used to decide how to interpret
166 * the relationship between various variables. 166 * the relationship between various variables.
167 */ 167 */
168 168
169Clocks clocks; 169Clocks clocks;
170  170
171#ifdef notdef 171#ifdef notdef
172Modelist modelist[] = { 172Modelist modelist[] = {
173 { "telnet command mode", COMMAND_LINE }, 173 { "telnet command mode", COMMAND_LINE },
174 { "character-at-a-time mode", 0 }, 174 { "character-at-a-time mode", 0 },
175 { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, 175 { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
176 { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, 176 { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
177 { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, 177 { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
178 { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, 178 { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
179 { "3270 mode", 0 }, 179 { "3270 mode", 0 },
180}; 180};
181#endif 181#endif
182 182
183  183
184/* 184/*
185 * Initialize telnet environment. 185 * Initialize telnet environment.
186 */ 186 */
187 187
188void 188void
189init_telnet(void) 189init_telnet(void)
190{ 190{
191 env_init(); 191 env_init();
192 192
193 SB_CLEAR(); 193 SB_CLEAR();
194 ClearArray(options); 194 ClearArray(options);
195 195
196 connected = In3270 = ISend = localflow = donebinarytoggle = 0; 196 connected = In3270 = ISend = localflow = donebinarytoggle = 0;
197#if defined(AUTHENTICATION) || defined(ENCRYPTION) 197#if defined(AUTHENTICATION) || defined(ENCRYPTION)
198 auth_encrypt_connect(connected); 198 auth_encrypt_connect(connected);
199#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ 199#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */
200 restartany = -1; 200 restartany = -1;
201 201
202 SYNCHing = 0; 202 SYNCHing = 0;
203 203
204 /* Don't change NetTrace */ 204 /* Don't change NetTrace */
205 205
206 escape = CONTROL(']'); 206 escape = CONTROL(']');
207 rlogin = _POSIX_VDISABLE; 207 rlogin = _POSIX_VDISABLE;
208#ifdef KLUDGELINEMODE 208#ifdef KLUDGELINEMODE
209 echoc = CONTROL('E'); 209 echoc = CONTROL('E');
210#endif 210#endif
211 211
212 flushline = 1; 212 flushline = 1;
213 telrcv_state = TS_DATA; 213 telrcv_state = TS_DATA;
214} 214}
215  215
216 216
217#ifdef notdef 217#ifdef notdef
218#include <stdarg.h> 218#include <stdarg.h>
219 219
220/*VARARGS*/ 220/*VARARGS*/
221static void 221static void
222printring(Ring *ring, char *format, ...) 222printring(Ring *ring, char *format, ...)
223 va_dcl 223 va_dcl
224{ 224{
225 va_list ap; 225 va_list ap;
226 char buffer[100]; /* where things go */ 226 char buffer[100]; /* where things go */
227 char *ptr; 227 char *ptr;
228 char *string; 228 char *string;
229 int i; 229 int i;
230 230
231 va_start(ap, format); 231 va_start(ap, format);
232 232
233 ptr = buffer; 233 ptr = buffer;
234 234
235 while ((i = *format++) != 0) { 235 while ((i = *format++) != 0) {
236 if (i == '%') { 236 if (i == '%') {
237 i = *format++; 237 i = *format++;
238 switch (i) { 238 switch (i) {
239 case 'c': 239 case 'c':
240 *ptr++ = va_arg(ap, int); 240 *ptr++ = va_arg(ap, int);
241 break; 241 break;
242 case 's': 242 case 's':
243 string = va_arg(ap, char *); 243 string = va_arg(ap, char *);
244 ring_supply_data(ring, buffer, ptr-buffer); 244 ring_supply_data(ring, buffer, ptr-buffer);
245 ring_supply_data(ring, string, strlen(string)); 245 ring_supply_data(ring, string, strlen(string));
246 ptr = buffer; 246 ptr = buffer;
247 break; 247 break;
248 case 0: 248 case 0:
249 ExitString("printring: trailing %%.\n", 1); 249 ExitString("printring: trailing %%.\n", 1);
250 /*NOTREACHED*/ 250 /*NOTREACHED*/
251 default: 251 default:
252 ExitString("printring: unknown format character.\n", 1); 252 ExitString("printring: unknown format character.\n", 1);
253 /*NOTREACHED*/ 253 /*NOTREACHED*/
254 } 254 }
255 } else { 255 } else {
256 *ptr++ = i; 256 *ptr++ = i;
257 } 257 }
258 } 258 }
259 va_end(ap); 259 va_end(ap);
260 ring_supply_data(ring, buffer, ptr-buffer); 260 ring_supply_data(ring, buffer, ptr-buffer);
261} 261}
262#endif 262#endif
263 263
264/* 264/*
265 * These routines are in charge of sending option negotiations 265 * These routines are in charge of sending option negotiations
266 * to the other side. 266 * to the other side.
267 * 267 *
268 * The basic idea is that we send the negotiation if either side 268 * The basic idea is that we send the negotiation if either side
269 * is in disagreement as to what the current state should be. 269 * is in disagreement as to what the current state should be.
270 */ 270 */
271 271
272void 272void
273send_do(int c, int init) 273send_do(int c, int init)
274{ 274{
275 if (init) { 275 if (init) {
276 if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || 276 if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
277 my_want_state_is_do(c)) 277 my_want_state_is_do(c))
278 return; 278 return;
279 set_my_want_state_do(c); 279 set_my_want_state_do(c);
280 do_dont_resp[c]++; 280 do_dont_resp[c]++;
281 } 281 }
282 NET2ADD(IAC, DO); 282 NET2ADD(IAC, DO);
283 NETADD(c); 283 NETADD(c);
284 printoption("SENT", DO, c); 284 printoption("SENT", DO, c);
285} 285}
286 286
287void 287void
288send_dont(int c, int init) 288send_dont(int c, int init)
289{ 289{
290 if (init) { 290 if (init) {
291 if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || 291 if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
292 my_want_state_is_dont(c)) 292 my_want_state_is_dont(c))
293 return; 293 return;
294 set_my_want_state_dont(c); 294 set_my_want_state_dont(c);
295 do_dont_resp[c]++; 295 do_dont_resp[c]++;
296 } 296 }
297 NET2ADD(IAC, DONT); 297 NET2ADD(IAC, DONT);
298 NETADD(c); 298 NETADD(c);
299 printoption("SENT", DONT, c); 299 printoption("SENT", DONT, c);
300} 300}
301 301
302void 302void
303send_will(int c, int init) 303send_will(int c, int init)
304{ 304{
305 if (init) { 305 if (init) {
306 if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || 306 if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
307 my_want_state_is_will(c)) 307 my_want_state_is_will(c))
308 return; 308 return;
309 set_my_want_state_will(c); 309 set_my_want_state_will(c);
310 will_wont_resp[c]++; 310 will_wont_resp[c]++;
311 } 311 }
312 NET2ADD(IAC, WILL); 312 NET2ADD(IAC, WILL);
313 NETADD(c); 313 NETADD(c);
314 printoption("SENT", WILL, c); 314 printoption("SENT", WILL, c);
315} 315}
316 316
317void 317void
318send_wont(int c, int init) 318send_wont(int c, int init)
319{ 319{
320 if (init) { 320 if (init) {
321 if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || 321 if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
322 my_want_state_is_wont(c)) 322 my_want_state_is_wont(c))
323 return; 323 return;
324 set_my_want_state_wont(c); 324 set_my_want_state_wont(c);
325 will_wont_resp[c]++; 325 will_wont_resp[c]++;
326 } 326 }
327 NET2ADD(IAC, WONT); 327 NET2ADD(IAC, WONT);
328 NETADD(c); 328 NETADD(c);
329 printoption("SENT", WONT, c); 329 printoption("SENT", WONT, c);
330} 330}
331 331
332 332
333void 333void
334willoption(int option) 334willoption(int option)
335{ 335{
336 int new_state_ok = 0; 336 int new_state_ok = 0;
337 337
338 if (do_dont_resp[option]) { 338 if (do_dont_resp[option]) {
339 --do_dont_resp[option]; 339 --do_dont_resp[option];
340 if (do_dont_resp[option] && my_state_is_do(option)) 340 if (do_dont_resp[option] && my_state_is_do(option))
341 --do_dont_resp[option]; 341 --do_dont_resp[option];
342 } 342 }
343 343
344 if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { 344 if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
345 345
346 switch (option) { 346 switch (option) {
347 347
348 case TELOPT_ECHO: 348 case TELOPT_ECHO:
349# if defined(TN3270) 349# if defined(TN3270)
350 /* 350 /*
351 * The following is a pain in the rear-end. 351 * The following is a pain in the rear-end.
352 * Various IBM servers (some versions of Wiscnet, 352 * Various IBM servers (some versions of Wiscnet,
353 * possibly Fibronics/Spartacus, and who knows who 353 * possibly Fibronics/Spartacus, and who knows who
354 * else) will NOT allow us to send "DO SGA" too early 354 * else) will NOT allow us to send "DO SGA" too early
355 * in the setup proceedings. On the other hand, 355 * in the setup proceedings. On the other hand,
356 * 4.2 servers (telnetd) won't set SGA correctly. 356 * 4.2 servers (telnetd) won't set SGA correctly.
357 * So, we are stuck. Empirically (but, based on 357 * So, we are stuck. Empirically (but, based on
358 * a VERY small sample), the IBM servers don't send 358 * a VERY small sample), the IBM servers don't send
359 * out anything about ECHO, so we postpone our sending 359 * out anything about ECHO, so we postpone our sending
360 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers 360 * "DO SGA" until we see "WILL ECHO" (which 4.2 servers
361 * DO send). 361 * DO send).
362 */ 362 */
363 { 363 {
364 if (askedSGA == 0) { 364 if (askedSGA == 0) {
365 askedSGA = 1; 365 askedSGA = 1;
366 if (my_want_state_is_dont(TELOPT_SGA)) 366 if (my_want_state_is_dont(TELOPT_SGA))
367 send_do(TELOPT_SGA, 1); 367 send_do(TELOPT_SGA, 1);
368 } 368 }
369 } 369 }
370 /* Fall through */ 370 /* Fall through */
371 case TELOPT_EOR: 371 case TELOPT_EOR:
372#endif /* defined(TN3270) */ 372#endif /* defined(TN3270) */
373 case TELOPT_BINARY: 373 case TELOPT_BINARY:
374 case TELOPT_SGA: 374 case TELOPT_SGA:
375 settimer(modenegotiated); 375 settimer(modenegotiated);
376 /* FALL THROUGH */ 376 /* FALL THROUGH */
377 case TELOPT_STATUS: 377 case TELOPT_STATUS:
378#ifdef AUTHENTICATION 378#ifdef AUTHENTICATION
379 case TELOPT_AUTHENTICATION: 379 case TELOPT_AUTHENTICATION:
380#ifdef ENCRYPTION 380#ifdef ENCRYPTION
381 case TELOPT_ENCRYPT: 381 case TELOPT_ENCRYPT:
382#endif /* ENCRYPTION */ 382#endif /* ENCRYPTION */
383#endif 383#endif
384 new_state_ok = 1; 384 new_state_ok = 1;
385 break; 385 break;
386 386
387 case TELOPT_TM: 387 case TELOPT_TM:
388 if (flushout) 388 if (flushout)
389 flushout = 0; 389 flushout = 0;
390 /* 390 /*
391 * Special case for TM. If we get back a WILL, 391 * Special case for TM. If we get back a WILL,
392 * pretend we got back a WONT. 392 * pretend we got back a WONT.
393 */ 393 */
394 set_my_want_state_dont(option); 394 set_my_want_state_dont(option);
395 set_my_state_dont(option); 395 set_my_state_dont(option);
396 return; /* Never reply to TM will's/wont's */ 396 return; /* Never reply to TM will's/wont's */
397 397
398 case TELOPT_LINEMODE: 398 case TELOPT_LINEMODE:
399 default: 399 default:
400 break; 400 break;
401 } 401 }
402 402
403 if (new_state_ok) { 403 if (new_state_ok) {
404 set_my_want_state_do(option); 404 set_my_want_state_do(option);
405 send_do(option, 0); 405 send_do(option, 0);
406 setconnmode(0); /* possibly set new tty mode */ 406 setconnmode(0); /* possibly set new tty mode */
407 } else { 407 } else {
408 do_dont_resp[option]++; 408 do_dont_resp[option]++;
409 send_dont(option, 0); 409 send_dont(option, 0);
410 } 410 }
411 } 411 }
412 set_my_state_do(option); 412 set_my_state_do(option);
413#ifdef ENCRYPTION 413#ifdef ENCRYPTION
414 if (option == TELOPT_ENCRYPT) 414 if (option == TELOPT_ENCRYPT)
415 encrypt_send_support(); 415 encrypt_send_support();
416#endif /* ENCRYPTION */ 416#endif /* ENCRYPTION */
417} 417}
418 418
419void 419void
420wontoption(int option) 420wontoption(int option)
421{ 421{
422 if (do_dont_resp[option]) { 422 if (do_dont_resp[option]) {
423 --do_dont_resp[option]; 423 --do_dont_resp[option];
424 if (do_dont_resp[option] && my_state_is_dont(option)) 424 if (do_dont_resp[option] && my_state_is_dont(option))
425 --do_dont_resp[option]; 425 --do_dont_resp[option];
426 } 426 }
427 427
428 if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { 428 if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
429 429
430 switch (option) { 430 switch (option) {
431 431
432#ifdef KLUDGELINEMODE 432#ifdef KLUDGELINEMODE
433 case TELOPT_SGA: 433 case TELOPT_SGA:
434 if (!kludgelinemode) 434 if (!kludgelinemode)
435 break; 435 break;
436 /* FALL THROUGH */ 436 /* FALL THROUGH */
437#endif 437#endif
438 case TELOPT_ECHO: 438 case TELOPT_ECHO:
439 settimer(modenegotiated); 439 settimer(modenegotiated);
440 break; 440 break;
441 441
442 case TELOPT_TM: 442 case TELOPT_TM:
443 if (flushout) 443 if (flushout)
444 flushout = 0; 444 flushout = 0;
445 set_my_want_state_dont(option); 445 set_my_want_state_dont(option);
446 set_my_state_dont(option); 446 set_my_state_dont(option);
447 return; /* Never reply to TM will's/wont's */ 447 return; /* Never reply to TM will's/wont's */
448 448
449 default: 449 default:
450 break; 450 break;
451 } 451 }
452 set_my_want_state_dont(option); 452 set_my_want_state_dont(option);
453 if (my_state_is_do(option)) 453 if (my_state_is_do(option))
454 send_dont(option, 0); 454 send_dont(option, 0);
455 setconnmode(0); /* Set new tty mode */ 455 setconnmode(0); /* Set new tty mode */
456 } else if (option == TELOPT_TM) { 456 } else if (option == TELOPT_TM) {
457 /* 457 /*
458 * Special case for TM. 458 * Special case for TM.
459 */ 459 */
460 if (flushout) 460 if (flushout)
461 flushout = 0; 461 flushout = 0;
462 set_my_want_state_dont(option); 462 set_my_want_state_dont(option);
463 } 463 }
464 set_my_state_dont(option); 464 set_my_state_dont(option);
465} 465}
466 466
467static void 467static void
468dooption(int option) 468dooption(int option)
469{ 469{
470 int new_state_ok = 0; 470 int new_state_ok = 0;
471 471
472 if (will_wont_resp[option]) { 472 if (will_wont_resp[option]) {
473 --will_wont_resp[option]; 473 --will_wont_resp[option];
474 if (will_wont_resp[option] && my_state_is_will(option)) 474 if (will_wont_resp[option] && my_state_is_will(option))
475 --will_wont_resp[option]; 475 --will_wont_resp[option];
476 } 476 }
477 477
478 if (will_wont_resp[option] == 0) { 478 if (will_wont_resp[option] == 0) {
479 if (my_want_state_is_wont(option)) { 479 if (my_want_state_is_wont(option)) {
480 480
481 switch (option) { 481 switch (option) {
482 482
483 case TELOPT_TM: 483 case TELOPT_TM:
484 /* 484 /*
485 * Special case for TM. We send a WILL, but pretend 485 * Special case for TM. We send a WILL, but pretend
486 * we sent WONT. 486 * we sent WONT.
487 */ 487 */
488 send_will(option, 0); 488 send_will(option, 0);
489 set_my_want_state_wont(TELOPT_TM); 489 set_my_want_state_wont(TELOPT_TM);
490 set_my_state_wont(TELOPT_TM); 490 set_my_state_wont(TELOPT_TM);
491 return; 491 return;
492 492
493# if defined(TN3270) 493# if defined(TN3270)
494 case TELOPT_EOR: /* end of record */ 494 case TELOPT_EOR: /* end of record */
495# endif /* defined(TN3270) */ 495# endif /* defined(TN3270) */
496 case TELOPT_BINARY: /* binary mode */ 496 case TELOPT_BINARY: /* binary mode */
497 case TELOPT_NAWS: /* window size */ 497 case TELOPT_NAWS: /* window size */
498 case TELOPT_TSPEED: /* terminal speed */ 498 case TELOPT_TSPEED: /* terminal speed */
499 case TELOPT_LFLOW: /* local flow control */ 499 case TELOPT_LFLOW: /* local flow control */
500 case TELOPT_TTYPE: /* terminal type option */ 500 case TELOPT_TTYPE: /* terminal type option */
501 case TELOPT_SGA: /* no big deal */ 501 case TELOPT_SGA: /* no big deal */
502#ifdef ENCRYPTION 502#ifdef ENCRYPTION
503 case TELOPT_ENCRYPT: /* encryption variable option */ 503 case TELOPT_ENCRYPT: /* encryption variable option */
504#endif /* ENCRYPTION */ 504#endif /* ENCRYPTION */
505 new_state_ok = 1; 505 new_state_ok = 1;
506 break; 506 break;
507 507
508 case TELOPT_NEW_ENVIRON: /* New environment variable option */ 508 case TELOPT_NEW_ENVIRON: /* New environment variable option */
509#ifdef OLD_ENVIRON 509#ifdef OLD_ENVIRON
510 if (my_state_is_will(TELOPT_OLD_ENVIRON)) 510 if (my_state_is_will(TELOPT_OLD_ENVIRON))
511 send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ 511 send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */
512 goto env_common; 512 goto env_common;
513 case TELOPT_OLD_ENVIRON: /* Old environment variable option */ 513 case TELOPT_OLD_ENVIRON: /* Old environment variable option */
514 if (my_state_is_will(TELOPT_NEW_ENVIRON)) 514 if (my_state_is_will(TELOPT_NEW_ENVIRON))
515 break; /* Don't enable if new one is in use! */ 515 break; /* Don't enable if new one is in use! */
516 env_common: 516 env_common:
517 telopt_environ = option; 517 telopt_environ = option;
518#endif 518#endif
519 new_state_ok = 1; 519 new_state_ok = 1;
520 break; 520 break;
521 521
522#ifdef AUTHENTICATION 522#ifdef AUTHENTICATION
523 case TELOPT_AUTHENTICATION: 523 case TELOPT_AUTHENTICATION:
524 if (autologin) 524 if (autologin)
525 new_state_ok = 1; 525 new_state_ok = 1;
526 break; 526 break;
527#endif 527#endif
528 528
529 case TELOPT_XDISPLOC: /* X Display location */ 529 case TELOPT_XDISPLOC: /* X Display location */
530 if (env_getvalue((const unsigned char *)"DISPLAY")) 530 if (env_getvalue((const unsigned char *)"DISPLAY"))
531 new_state_ok = 1; 531 new_state_ok = 1;
532 break; 532 break;
533 533
534 case TELOPT_LINEMODE: 534 case TELOPT_LINEMODE:
535#ifdef KLUDGELINEMODE 535#ifdef KLUDGELINEMODE
536 kludgelinemode = 0; 536 kludgelinemode = 0;
537 send_do(TELOPT_SGA, 1); 537 send_do(TELOPT_SGA, 1);
538#endif 538#endif
539 set_my_want_state_will(TELOPT_LINEMODE); 539 set_my_want_state_will(TELOPT_LINEMODE);
540 send_will(option, 0); 540 send_will(option, 0);
541 set_my_state_will(TELOPT_LINEMODE); 541 set_my_state_will(TELOPT_LINEMODE);
542 slc_init(); 542 slc_init();
543 return; 543 return;
544 544
545 case TELOPT_ECHO: /* We're never going to echo... */ 545 case TELOPT_ECHO: /* We're never going to echo... */
546 default: 546 default:
547 break; 547 break;
548 } 548 }
549 549
550 if (new_state_ok) { 550 if (new_state_ok) {
551 set_my_want_state_will(option); 551 set_my_want_state_will(option);
552 send_will(option, 0); 552 send_will(option, 0);
553 setconnmode(0); /* Set new tty mode */ 553 setconnmode(0); /* Set new tty mode */
554 } else { 554 } else {
555 will_wont_resp[option]++; 555 will_wont_resp[option]++;
556 send_wont(option, 0); 556 send_wont(option, 0);
557 } 557 }
558 } else { 558 } else {
559 /* 559 /*
560 * Handle options that need more things done after the 560 * Handle options that need more things done after the
561 * other side has acknowledged the option. 561 * other side has acknowledged the option.
562 */ 562 */
563 switch (option) { 563 switch (option) {
564 case TELOPT_LINEMODE: 564 case TELOPT_LINEMODE:
565#ifdef KLUDGELINEMODE 565#ifdef KLUDGELINEMODE
566 kludgelinemode = 0; 566 kludgelinemode = 0;
567 send_do(TELOPT_SGA, 1); 567 send_do(TELOPT_SGA, 1);
568#endif 568#endif
569 set_my_state_will(option); 569 set_my_state_will(option);
570 slc_init(); 570 slc_init();
571 send_do(TELOPT_SGA, 0); 571 send_do(TELOPT_SGA, 0);
572 return; 572 return;
573 } 573 }
574 } 574 }
575 } 575 }
576 set_my_state_will(option); 576 set_my_state_will(option);
577} 577}
578 578
579static void 579static void
580dontoption(int option) 580dontoption(int option)
581{ 581{
582 582
583 if (will_wont_resp[option]) { 583 if (will_wont_resp[option]) {
584 --will_wont_resp[option]; 584 --will_wont_resp[option];
585 if (will_wont_resp[option] && my_state_is_wont(option)) 585 if (will_wont_resp[option] && my_state_is_wont(option))
586 --will_wont_resp[option]; 586 --will_wont_resp[option];
587 } 587 }
588 588
589 if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { 589 if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
590 switch (option) { 590 switch (option) {
591 case TELOPT_LINEMODE: 591 case TELOPT_LINEMODE:
592 linemode = 0; /* put us back to the default state */ 592 linemode = 0; /* put us back to the default state */
593 break; 593 break;
594#ifdef OLD_ENVIRON 594#ifdef OLD_ENVIRON
595 case TELOPT_NEW_ENVIRON: 595 case TELOPT_NEW_ENVIRON:
596 /* 596 /*
597 * The new environ option wasn't recognized, try 597 * The new environ option wasn't recognized, try
598 * the old one. 598 * the old one.
599 */ 599 */
600 send_will(TELOPT_OLD_ENVIRON, 1); 600 send_will(TELOPT_OLD_ENVIRON, 1);
601 telopt_environ = TELOPT_OLD_ENVIRON; 601 telopt_environ = TELOPT_OLD_ENVIRON;
602 break; 602 break;
603#endif 603#endif
604 } 604 }
605 /* we always accept a DONT */ 605 /* we always accept a DONT */
606 set_my_want_state_wont(option); 606 set_my_want_state_wont(option);
607 if (my_state_is_will(option)) 607 if (my_state_is_will(option))
608 send_wont(option, 0); 608 send_wont(option, 0);
609 setconnmode(0); /* Set new tty mode */ 609 setconnmode(0); /* Set new tty mode */
610 } 610 }
611 set_my_state_wont(option); 611 set_my_state_wont(option);
612} 612}
613 613
614/* 614/*
615 * Given a buffer returned by tgetent(), this routine will turn 615 * Given a buffer returned by tgetent(), this routine will turn
616 * the pipe separated list of names in the buffer into an array 616 * the pipe separated list of names in the buffer into an array
617 * of pointers to null terminated names. We toss out any bad, 617 * of pointers to null terminated names. We toss out any bad,
618 * duplicate, or verbose names (names with spaces). 618 * duplicate, or verbose names (names with spaces).
619 */ 619 */
620 620
621static char name_unknown[] = "UNKNOWN"; 621static char name_unknown[] = "UNKNOWN";
622static char *unknown[] = { 0, 0 }; 622static char *unknown[] = { 0, 0 };
623 623
624char ** 624char **
625mklist(char *buf, char *name) 625mklist(char *buf, char *name)
626{ 626{
627 int n; 627 int n;
628 char c, *cp, **argvp, *cp2, **argv, **avt; 628 char c, *cp, **argvp, *cp2, **argv, **avt;
629 629
630 if (name) { 630 if (name) {
631 if ((int)strlen(name) > 40) { 631 if ((int)strlen(name) > 40) {
632 name = 0; 632 name = 0;
633 unknown[0] = name_unknown; 633 unknown[0] = name_unknown;
634 } else { 634 } else {
635 unknown[0] = name; 635 unknown[0] = name;
636 upcase(name); 636 upcase(name);
637 } 637 }
638 } else 638 } else
639 unknown[0] = name_unknown; 639 unknown[0] = name_unknown;
640 /* 640 /*
641 * Count up the number of names. 641 * Count up the number of names.
642 */ 642 */
643 for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { 643 for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
644 if (*cp == '|') 644 if (*cp == '|')
645 n++; 645 n++;
646 } 646 }
647 /* 647 /*
648 * Allocate an array to put the name pointers into 648 * Allocate an array to put the name pointers into
649 */ 649 */
650 argv = (char **)malloc((n+3)*sizeof(char *)); 650 argv = (char **)malloc((n+3)*sizeof(char *));
651 if (argv == 0) 651 if (argv == 0)
652 return(unknown); 652 return(unknown);
653 653
654 /* 654 /*
655 * Fill up the array of pointers to names. 655 * Fill up the array of pointers to names.
656 */ 656 */
657 *argv = 0; 657 *argv = 0;
658 argvp = argv+1; 658 argvp = argv+1;
659 n = 0; 659 n = 0;
660 for (cp = cp2 = buf; (c = *cp); cp++) { 660 for (cp = cp2 = buf; (c = *cp); cp++) {
661 if (c == '|' || c == ':') { 661 if (c == '|' || c == ':') {
662 *cp++ = '\0'; 662 *cp++ = '\0';
663 /* 663 /*
664 * Skip entries that have spaces or are over 40 664 * Skip entries that have spaces or are over 40
665 * characters long. If this is our environment 665 * characters long. If this is our environment
666 * name, then put it up front. Otherwise, as 666 * name, then put it up front. Otherwise, as
667 * long as this is not a duplicate name (case 667 * long as this is not a duplicate name (case
668 * insensitive) add it to the list. 668 * insensitive) add it to the list.
669 */ 669 */
670 if (n || (cp - cp2 > 41)) 670 if (n || (cp - cp2 > 41))
671 ; 671 ;
672 else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) 672 else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
673 *argv = cp2; 673 *argv = cp2;
674 else if (is_unique(cp2, argv+1, argvp)) 674 else if (is_unique(cp2, argv+1, argvp))
675 *argvp++ = cp2; 675 *argvp++ = cp2;
676 if (c == ':') 676 if (c == ':')
677 break; 677 break;
678 /* 678 /*
679 * Skip multiple delimiters. Reset cp2 to 679 * Skip multiple delimiters. Reset cp2 to
680 * the beginning of the next name. Reset n, 680 * the beginning of the next name. Reset n,
681 * the flag for names with spaces. 681 * the flag for names with spaces.
682 */ 682 */
683 while ((c = *cp) == '|') 683 while ((c = *cp) == '|')
684 cp++; 684 cp++;
685 cp2 = cp; 685 cp2 = cp;
686 n = 0; 686 n = 0;
687 } 687 }
688 /* 688 /*
689 * Skip entries with spaces or non-ascii values. 689 * Skip entries with spaces or non-ascii values.
690 * Convert lower case letters to upper case. 690 * Convert lower case letters to upper case.
691 */ 691 */
692 if ((c == ' ') || !isascii(c)) 692 if ((c == ' ') || !isascii(c))
693 n = 1; 693 n = 1;
694 else if (islower((unsigned char)c)) 694 else if (islower((unsigned char)c))
695 *cp = toupper((unsigned char)c); 695 *cp = toupper((unsigned char)c);
696 } 696 }
697 697
698 /* 698 /*
699 * Check for an old V6 2 character name. If the second 699 * Check for an old V6 2 character name. If the second
700 * name points to the beginning of the buffer, and is 700 * name points to the beginning of the buffer, and is
701 * only 2 characters long, move it to the end of the array. 701 * only 2 characters long, move it to the end of the array.
702 */ 702 */
703 if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { 703 if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
704 --argvp; 704 --argvp;
705 for (avt = &argv[1]; avt < argvp; avt++) 705 for (avt = &argv[1]; avt < argvp; avt++)
706 *avt = *(avt+1); 706 *avt = *(avt+1);
707 *argvp++ = buf; 707 *argvp++ = buf;
708 } 708 }
709 709
710 /* 710 /*
711 * Duplicate last name, for TTYPE option, and null 711 * Duplicate last name, for TTYPE option, and null
712 * terminate the array. If we didn't find a match on 712 * terminate the array. If we didn't find a match on
713 * our terminal name, put that name at the beginning. 713 * our terminal name, put that name at the beginning.
714 */ 714 */
715 cp = *(argvp-1); 715 cp = *(argvp-1);
716 *argvp++ = cp; 716 *argvp++ = cp;
717 *argvp = 0; 717 *argvp = 0;
718 718
719 if (*argv == 0) { 719 if (*argv == 0) {
720 if (name) 720 if (name)
721 *argv = name; 721 *argv = name;
722 else { 722 else {
723 --argvp; 723 --argvp;
724 for (avt = argv; avt < argvp; avt++) 724 for (avt = argv; avt < argvp; avt++)
725 *avt = *(avt+1); 725 *avt = *(avt+1);
726 } 726 }
727 } 727 }
728 if (*argv) 728 if (*argv)
729 return(argv); 729 return(argv);
730 else 730 else
731 return(unknown); 731 return(unknown);
732} 732}
733 733
734int 734int
735is_unique(char *name, char **as, char **ae) 735is_unique(char *name, char **as, char **ae)
736{ 736{
737 char **ap; 737 char **ap;
738 int n; 738 int n;
739 739
740 n = strlen(name) + 1; 740 n = strlen(name) + 1;
741 for (ap = as; ap < ae; ap++) 741 for (ap = as; ap < ae; ap++)
742 if (strncasecmp(*ap, name, n) == 0) 742 if (strncasecmp(*ap, name, n) == 0)
743 return(0); 743 return(0);
744 return (1); 744 return (1);
745} 745}
746 746
747#ifdef TERMCAP 747#ifdef TERMCAP
748char *termbuf; 748char *termbuf;
749 749
750/*ARGSUSED*/ 750/*ARGSUSED*/
751int 751int
752setupterm(char *tname, int fd, int *errp) 752setupterm(char *tname, int fd, int *errp)
753{ 753{
754 char zz[1024], *zz_ptr; 754 char zz[1024], *zz_ptr;
755 char *ext_tc, *newptr; 755 char *ext_tc, *newptr;
756 size_t len; 756 size_t len;
757  757
758 if ((termbuf = malloc(1024)) == NULL) 758 if ((termbuf = malloc(1024)) == NULL)
759 goto error; 759 goto error;
760  760
761 if (tgetent(termbuf, tname) == 1) { 761 if (tgetent(termbuf, tname) == 1) {
762 /* check for ZZ capability, indicating termcap truncated */ 762 /* check for ZZ capability, indicating termcap truncated */
763 zz_ptr = zz; 763 zz_ptr = zz;
764 if (tgetstr("ZZ", &zz_ptr) != NULL) { 764 if (tgetstr("ZZ", &zz_ptr) != NULL) {
765 /* it was, fish back the full termcap */ 765 /* it was, fish back the full termcap */
766 sscanf(zz, "%p", &ext_tc); 766 sscanf(zz, "%p", &ext_tc);
767 len = strlen(ext_tc) + 1; 767 len = strlen(ext_tc) + 1;
768 if ((newptr = realloc(termbuf, len)) == NULL) 768 if ((newptr = realloc(termbuf, len)) == NULL)
769 goto error; 769 goto error;
770 770
771 memcpy(newptr, ext_tc, len); 771 memcpy(newptr, ext_tc, len);
772 termbuf = newptr; 772 termbuf = newptr;
773 } 773 }
774 774
775 if (errp) 775 if (errp)
776 *errp = 1; 776 *errp = 1;
777 return(0); 777 return(0);
778 } 778 }
779 error: 779 error:
780 if (errp) 780 if (errp)
781 *errp = 0; 781 *errp = 0;
782 return(-1); 782 return(-1);
783} 783}
784#else 784#else
785#define termbuf ttytype 785#define termbuf ttytype
786extern char ttytype[]; 786extern char ttytype[];
787#endif 787#endif
788 788
789int resettermname = 1; 789int resettermname = 1;
790 790
791char * 791char *
792gettermname(void) 792gettermname(void)
793{ 793{
794 char *tname; 794 char *tname;
795 static char **tnamep = 0; 795 static char **tnamep = 0;
796 static char **next; 796 static char **next;
797 int err; 797 int err;
798 798
799 if (resettermname) { 799 if (resettermname) {
800 resettermname = 0; 800 resettermname = 0;
801 if (tnamep && tnamep != unknown) 801 if (tnamep && tnamep != unknown)
802 free(tnamep); 802 free(tnamep);
803 if ((tname = (char *)env_getvalue((const unsigned char *)"TERM")) && 803 if ((tname = (char *)env_getvalue((const unsigned char *)"TERM")) &&
804 (setupterm(tname, 1, &err) == 0)) { 804 (setupterm(tname, 1, &err) == 0)) {
805 tnamep = mklist(termbuf, tname); 805 tnamep = mklist(termbuf, tname);
806 } else { 806 } else {
807 if (tname && ((int)strlen(tname) <= 40)) { 807 if (tname && ((int)strlen(tname) <= 40)) {
808 unknown[0] = tname; 808 unknown[0] = tname;
809 upcase(tname); 809 upcase(tname);
810 } else 810 } else
811 unknown[0] = name_unknown; 811 unknown[0] = name_unknown;
812 tnamep = unknown; 812 tnamep = unknown;
813 } 813 }
814 next = tnamep; 814 next = tnamep;
815 } 815 }
816 if (*next == 0) 816 if (*next == 0)
817 next = tnamep; 817 next = tnamep;
818 return(*next++); 818 return(*next++);
819} 819}
820/* 820/*
821 * suboption() 821 * suboption()
822 * 822 *
823 * Look at the sub-option buffer, and try to be helpful to the other 823 * Look at the sub-option buffer, and try to be helpful to the other
824 * side. 824 * side.
825 * 825 *
826 * Currently we recognize: 826 * Currently we recognize:
827 * 827 *
828 * Terminal type, send request. 828 * Terminal type, send request.
829 * Terminal speed (send request). 829 * Terminal speed (send request).
830 * Local flow control (is request). 830 * Local flow control (is request).
831 * Linemode 831 * Linemode
832 */ 832 */
833 833
834static void 834static void
835suboption(void) 835suboption(void)
836{ 836{
837 unsigned char subchar; 837 unsigned char subchar;
838 838
839 printsub('<', subbuffer, SB_LEN()+2); 839 printsub('<', subbuffer, SB_LEN()+2);
840 switch (subchar = SB_GET()) { 840 switch (subchar = SB_GET()) {
841 case TELOPT_TTYPE: 841 case TELOPT_TTYPE:
842 if (my_want_state_is_wont(TELOPT_TTYPE)) 842 if (my_want_state_is_wont(TELOPT_TTYPE))
843 return; 843 return;
844 if (SB_EOF() || SB_GET() != TELQUAL_SEND) { 844 if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
845 return; 845 return;
846 } else { 846 } else {
847 char *name; 847 char *name;
848 unsigned char temp[50]; 848 unsigned char temp[50];
849 int len; 849 int len;
850 850
851#ifdef TN3270 851#ifdef TN3270
852 if (tn3270_ttype()) { 852 if (tn3270_ttype()) {
853 return; 853 return;
854 } 854 }
855#endif /* defined(TN3270) */ 855#endif /* defined(TN3270) */
856 name = gettermname(); 856 name = gettermname();
857 len = strlen(name) + 4 + 2; 857 len = strlen(name) + 4 + 2;
858 if (len < NETROOM()) { 858 if (len < NETROOM()) {
859 sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, 859 snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB,
860 TELQUAL_IS, name, IAC, SE); 860 TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE);
861 ring_supply_data(&netoring, temp, len); 861 ring_supply_data(&netoring, temp, len);
862 printsub('>', &temp[2], len-2); 862 printsub('>', &temp[2], len-2);
863 } else { 863 } else {
864 ExitString("No room in buffer for terminal type.\n", 1); 864 ExitString("No room in buffer for terminal type.\n", 1);
865 /*NOTREACHED*/ 865 /*NOTREACHED*/
866 } 866 }
867 } 867 }
868 break; 868 break;
869 case TELOPT_TSPEED: 869 case TELOPT_TSPEED:
870 if (my_want_state_is_wont(TELOPT_TSPEED)) 870 if (my_want_state_is_wont(TELOPT_TSPEED))
871 return; 871 return;
872 if (SB_EOF()) 872 if (SB_EOF())
873 return; 873 return;
874 if (SB_GET() == TELQUAL_SEND) { 874 if (SB_GET() == TELQUAL_SEND) {
875 long osp, isp; 875 long osp, isp;
876 unsigned char temp[50]; 876 unsigned char temp[50];
877 int len; 877 int len;
878 878
879 TerminalSpeeds(&isp, &osp); 879 TerminalSpeeds(&isp, &osp);
880 880
881 sprintf((char *)temp, "%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED, 881 snprintf((char *)temp, sizeof(temp), "%c%c%c%c%ld,%ld%c%c", IAC, SB,
882 TELQUAL_IS, osp, isp, IAC, SE); 882 TELOPT_TSPEED, TELQUAL_IS, osp, isp, IAC, SE);
883 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 883 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
884 884
885 if (len < NETROOM()) { 885 if (len < NETROOM()) {
886 ring_supply_data(&netoring, temp, len); 886 ring_supply_data(&netoring, temp, len);
887 printsub('>', temp+2, len - 2); 887 printsub('>', temp+2, len - 2);
888 } 888 }
889/*@*/ else printf("lm_will: not enough room in buffer\n"); 889/*@*/ else printf("lm_will: not enough room in buffer\n");
890 } 890 }
891 break; 891 break;
892 case TELOPT_LFLOW: 892 case TELOPT_LFLOW:
893 if (my_want_state_is_wont(TELOPT_LFLOW)) 893 if (my_want_state_is_wont(TELOPT_LFLOW))
894 return; 894 return;
895 if (SB_EOF()) 895 if (SB_EOF())
896 return; 896 return;
897 switch(SB_GET()) { 897 switch(SB_GET()) {
898 case LFLOW_RESTART_ANY: 898 case LFLOW_RESTART_ANY:
899 restartany = 1; 899 restartany = 1;
900 break; 900 break;
901 case LFLOW_RESTART_XON: 901 case LFLOW_RESTART_XON:
902 restartany = 0; 902 restartany = 0;
903 break; 903 break;
904 case LFLOW_ON: 904 case LFLOW_ON:
905 localflow = 1; 905 localflow = 1;
906 break; 906 break;
907 case LFLOW_OFF: 907 case LFLOW_OFF:
908 localflow = 0; 908 localflow = 0;
909 break; 909 break;
910 default: 910 default:
911 return; 911 return;
912 } 912 }
913 setcommandmode(); 913 setcommandmode();
914 setconnmode(0); 914 setconnmode(0);
915 break; 915 break;
916 916
917 case TELOPT_LINEMODE: 917 case TELOPT_LINEMODE:
918 if (my_want_state_is_wont(TELOPT_LINEMODE)) 918 if (my_want_state_is_wont(TELOPT_LINEMODE))
919 return; 919 return;
920 if (SB_EOF()) 920 if (SB_EOF())
921 return; 921 return;
922 switch (SB_GET()) { 922 switch (SB_GET()) {
923 case WILL: 923 case WILL:
924 lm_will(subpointer, SB_LEN()); 924 lm_will(subpointer, SB_LEN());
925 break; 925 break;
926 case WONT: 926 case WONT:
927 lm_wont(subpointer, SB_LEN()); 927 lm_wont(subpointer, SB_LEN());
928 break; 928 break;
929 case DO: 929 case DO:
930 lm_do(subpointer, SB_LEN()); 930 lm_do(subpointer, SB_LEN());
931 break; 931 break;
932 case DONT: 932 case DONT:
933 lm_dont(subpointer, SB_LEN()); 933 lm_dont(subpointer, SB_LEN());
934 break; 934 break;
935 case LM_SLC: 935 case LM_SLC:
936 slc(subpointer, SB_LEN()); 936 slc(subpointer, SB_LEN());
937 break; 937 break;
938 case LM_MODE: 938 case LM_MODE:
939 lm_mode(subpointer, SB_LEN(), 0); 939 lm_mode(subpointer, SB_LEN(), 0);
940 break; 940 break;
941 default: 941 default:
942 break; 942 break;
943 } 943 }
944 break; 944 break;
945 945
946#ifdef OLD_ENVIRON 946#ifdef OLD_ENVIRON
947 case TELOPT_OLD_ENVIRON: 947 case TELOPT_OLD_ENVIRON:
948#endif 948#endif
949 case TELOPT_NEW_ENVIRON: 949 case TELOPT_NEW_ENVIRON:
950 if (SB_EOF()) 950 if (SB_EOF())
951 return; 951 return;
952 switch(SB_PEEK()) { 952 switch(SB_PEEK()) {
953 case TELQUAL_IS: 953 case TELQUAL_IS:
954 case TELQUAL_INFO: 954 case TELQUAL_INFO:
955 if (my_want_state_is_dont(subchar)) 955 if (my_want_state_is_dont(subchar))
956 return; 956 return;
957 break; 957 break;
958 case TELQUAL_SEND: 958 case TELQUAL_SEND:
959 if (my_want_state_is_wont(subchar)) { 959 if (my_want_state_is_wont(subchar)) {
960 return; 960 return;
961 } 961 }
962 break; 962 break;
963 default: 963 default:
964 return; 964 return;
965 } 965 }
966 env_opt(subpointer, SB_LEN()); 966 env_opt(subpointer, SB_LEN());
967 break; 967 break;
968 968
969 case TELOPT_XDISPLOC: 969 case TELOPT_XDISPLOC:
970 if (my_want_state_is_wont(TELOPT_XDISPLOC)) 970 if (my_want_state_is_wont(TELOPT_XDISPLOC))
971 return; 971 return;
972 if (SB_EOF()) 972 if (SB_EOF())
973 return; 973 return;
974 if (SB_GET() == TELQUAL_SEND) { 974 if (SB_GET() == TELQUAL_SEND) {
975 unsigned char temp[50], *dp; 975 unsigned char temp[50], *dp;
976 int len; 976 int len;
977 977
978 if ((dp = env_getvalue((const unsigned char *)"DISPLAY")) == NULL) { 978 if ((dp = env_getvalue((const unsigned char *)"DISPLAY")) == NULL) {
979 /* 979 /*
980 * Something happened, we no longer have a DISPLAY 980 * Something happened, we no longer have a DISPLAY
981 * variable. So, turn off the option. 981 * variable. So, turn off the option.
982 */ 982 */
983 send_wont(TELOPT_XDISPLOC, 1); 983 send_wont(TELOPT_XDISPLOC, 1);
984 break; 984 break;
985 } 985 }
986 sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, 986 snprintf((char *)temp, sizeof(temp), "%c%c%c%c%s%c%c", IAC, SB,
987 TELQUAL_IS, dp, IAC, SE); 987 TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE);
988 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ 988 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
989 989
990 if (len < NETROOM()) { 990 if (len < NETROOM()) {
991 ring_supply_data(&netoring, temp, len); 991 ring_supply_data(&netoring, temp, len);
992 printsub('>', temp+2, len - 2); 992 printsub('>', temp+2, len - 2);
993 } 993 }
994/*@*/ else printf("lm_will: not enough room in buffer\n"); 994/*@*/ else printf("lm_will: not enough room in buffer\n");
995 } 995 }
996 break; 996 break;
997 997
998#ifdef AUTHENTICATION 998#ifdef AUTHENTICATION
999 case TELOPT_AUTHENTICATION: { 999 case TELOPT_AUTHENTICATION: {
1000 if (!autologin) 1000 if (!autologin)
1001 break; 1001 break;
1002 if (SB_EOF()) 1002 if (SB_EOF())
1003 return; 1003 return;
1004 switch(SB_GET()) { 1004 switch(SB_GET()) {
1005 case TELQUAL_IS: 1005 case TELQUAL_IS:
1006 if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) 1006 if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
1007 return; 1007 return;
1008 auth_is(subpointer, SB_LEN()); 1008 auth_is(subpointer, SB_LEN());
1009 break; 1009 break;
1010 case TELQUAL_SEND: 1010 case TELQUAL_SEND:
1011 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 1011 if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
1012 return; 1012 return;
1013 auth_send(subpointer, SB_LEN()); 1013 auth_send(subpointer, SB_LEN());
1014 break; 1014 break;
1015 case TELQUAL_REPLY: 1015 case TELQUAL_REPLY:
1016 if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) 1016 if (my_want_state_is_wont(TELOPT_AUTHENTICATION))
1017 return; 1017 return;
1018 auth_reply(subpointer, SB_LEN()); 1018 auth_reply(subpointer, SB_LEN());
1019 break; 1019 break;
1020 case TELQUAL_NAME: 1020 case TELQUAL_NAME:
1021 if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) 1021 if (my_want_state_is_dont(TELOPT_AUTHENTICATION))
1022 return; 1022 return;
1023 auth_name(subpointer, SB_LEN()); 1023 auth_name(subpointer, SB_LEN());
1024 break; 1024 break;
1025 } 1025 }
1026 } 1026 }
1027 break; 1027 break;
1028#endif 1028#endif
1029#ifdef ENCRYPTION 1029#ifdef ENCRYPTION
1030 case TELOPT_ENCRYPT: 1030 case TELOPT_ENCRYPT:
1031 if (SB_EOF()) 1031 if (SB_EOF())
1032 return; 1032 return;
1033 switch(SB_GET()) { 1033 switch(SB_GET()) {
1034 case ENCRYPT_START: 1034 case ENCRYPT_START:
1035 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1035 if (my_want_state_is_dont(TELOPT_ENCRYPT))
1036 return; 1036 return;
1037 encrypt_start(subpointer, SB_LEN()); 1037 encrypt_start(subpointer, SB_LEN());
1038 break; 1038 break;
1039 case ENCRYPT_END: 1039 case ENCRYPT_END:
1040 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1040 if (my_want_state_is_dont(TELOPT_ENCRYPT))
1041 return; 1041 return;
1042 encrypt_end(); 1042 encrypt_end();
1043 break; 1043 break;
1044 case ENCRYPT_SUPPORT: 1044 case ENCRYPT_SUPPORT:
1045 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1045 if (my_want_state_is_wont(TELOPT_ENCRYPT))
1046 return; 1046 return;
1047 encrypt_support(subpointer, SB_LEN()); 1047 encrypt_support(subpointer, SB_LEN());
1048 break; 1048 break;
1049 case ENCRYPT_REQSTART: 1049 case ENCRYPT_REQSTART:
1050 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1050 if (my_want_state_is_wont(TELOPT_ENCRYPT))
1051 return; 1051 return;
1052 encrypt_request_start(subpointer, SB_LEN()); 1052 encrypt_request_start(subpointer, SB_LEN());
1053 break; 1053 break;
1054 case ENCRYPT_REQEND: 1054 case ENCRYPT_REQEND:
1055 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1055 if (my_want_state_is_wont(TELOPT_ENCRYPT))
1056 return; 1056 return;
1057 /* 1057 /*
1058 * We can always send an REQEND so that we cannot 1058 * We can always send an REQEND so that we cannot
1059 * get stuck encrypting. We should only get this 1059 * get stuck encrypting. We should only get this
1060 * if we have been able to get in the correct mode 1060 * if we have been able to get in the correct mode
1061 * anyhow. 1061 * anyhow.
1062 */ 1062 */
1063 encrypt_request_end(); 1063 encrypt_request_end();
1064 break; 1064 break;
1065 case ENCRYPT_IS: 1065 case ENCRYPT_IS:
1066 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1066 if (my_want_state_is_dont(TELOPT_ENCRYPT))
1067 return; 1067 return;
1068 encrypt_is(subpointer, SB_LEN()); 1068 encrypt_is(subpointer, SB_LEN());
1069 break; 1069 break;
1070 case ENCRYPT_REPLY: 1070 case ENCRYPT_REPLY:
1071 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1071 if (my_want_state_is_wont(TELOPT_ENCRYPT))
1072 return; 1072 return;
1073 encrypt_reply(subpointer, SB_LEN()); 1073 encrypt_reply(subpointer, SB_LEN());
1074 break; 1074 break;
1075 case ENCRYPT_ENC_KEYID: 1075 case ENCRYPT_ENC_KEYID:
1076 if (my_want_state_is_dont(TELOPT_ENCRYPT)) 1076 if (my_want_state_is_dont(TELOPT_ENCRYPT))
1077 return; 1077 return;
1078 encrypt_enc_keyid(subpointer, SB_LEN()); 1078 encrypt_enc_keyid(subpointer, SB_LEN());
1079 break; 1079 break;
1080 case ENCRYPT_DEC_KEYID: 1080 case ENCRYPT_DEC_KEYID:
1081 if (my_want_state_is_wont(TELOPT_ENCRYPT)) 1081 if (my_want_state_is_wont(TELOPT_ENCRYPT))
1082 return; 1082 return;
1083 encrypt_dec_keyid(subpointer, SB_LEN()); 1083 encrypt_dec_keyid(subpointer, SB_LEN());
1084 break; 1084 break;
1085 default: 1085 default:
1086 break; 1086 break;
1087 } 1087 }
1088 break; 1088 break;
1089#endif /* ENCRYPTION */ 1089#endif /* ENCRYPTION */
1090 default: 1090 default:
1091 break; 1091 break;
1092 } 1092 }
1093} 1093}
1094 1094
1095static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; 1095static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
1096 1096
1097void 1097void
1098lm_will(unsigned char *cmd, int len) 1098lm_will(unsigned char *cmd, int len)
1099{ 1099{
1100 if (len < 1) { 1100 if (len < 1) {
1101/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ 1101/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
1102 return; 1102 return;
1103 } 1103 }
1104 switch(cmd[0]) { 1104 switch(cmd[0]) {
1105 case LM_FORWARDMASK: /* We shouldn't ever get this... */ 1105 case LM_FORWARDMASK: /* We shouldn't ever get this... */
1106 default: 1106 default:
1107 str_lm[3] = DONT; 1107 str_lm[3] = DONT;
1108 str_lm[4] = cmd[0]; 1108 str_lm[4] = cmd[0];
1109 if ((size_t)NETROOM() > sizeof(str_lm)) { 1109 if ((size_t)NETROOM() > sizeof(str_lm)) {
1110 ring_supply_data(&netoring, str_lm, sizeof(str_lm)); 1110 ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1111 printsub('>', &str_lm[2], sizeof(str_lm)-2); 1111 printsub('>', &str_lm[2], sizeof(str_lm)-2);
1112 } 1112 }
1113/*@*/ else printf("lm_will: not enough room in buffer\n"); 1113/*@*/ else printf("lm_will: not enough room in buffer\n");
1114 break; 1114 break;
1115 } 1115 }
1116} 1116}
1117 1117
1118void 1118void
1119lm_wont(unsigned char *cmd, int len) 1119lm_wont(unsigned char *cmd, int len)
1120{ 1120{
1121 if (len < 1) { 1121 if (len < 1) {
1122/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ 1122/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
1123 return; 1123 return;
1124 } 1124 }
1125 switch(cmd[0]) { 1125 switch(cmd[0]) {
1126 case LM_FORWARDMASK: /* We shouldn't ever get this... */ 1126 case LM_FORWARDMASK: /* We shouldn't ever get this... */
1127 default: 1127 default:
1128 /* We are always DONT, so don't respond */ 1128 /* We are always DONT, so don't respond */
1129 return; 1129 return;
1130 } 1130 }
1131} 1131}
1132 1132
1133void 1133void
1134lm_do(unsigned char *cmd, int len) 1134lm_do(unsigned char *cmd, int len)
1135{ 1135{
1136 if (len < 1) { 1136 if (len < 1) {
1137/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ 1137/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
1138 return; 1138 return;
1139 } 1139 }
1140 switch(cmd[0]) { 1140 switch(cmd[0]) {
1141 case LM_FORWARDMASK: 1141 case LM_FORWARDMASK:
1142 default: 1142 default:
1143 str_lm[3] = WONT; 1143 str_lm[3] = WONT;
1144 str_lm[4] = cmd[0]; 1144 str_lm[4] = cmd[0];
1145 if ((size_t)NETROOM() > sizeof(str_lm)) { 1145 if ((size_t)NETROOM() > sizeof(str_lm)) {
1146 ring_supply_data(&netoring, str_lm, sizeof(str_lm)); 1146 ring_supply_data(&netoring, str_lm, sizeof(str_lm));
1147 printsub('>', &str_lm[2], sizeof(str_lm)-2); 1147 printsub('>', &str_lm[2], sizeof(str_lm)-2);
1148 } 1148 }
1149/*@*/ else printf("lm_do: not enough room in buffer\n"); 1149/*@*/ else printf("lm_do: not enough room in buffer\n");
1150 break; 1150 break;
1151 } 1151 }
1152} 1152}
1153 1153
1154void 1154void
1155lm_dont(unsigned char *cmd, int len) 1155lm_dont(unsigned char *cmd, int len)
1156{ 1156{
1157 if (len < 1) { 1157 if (len < 1) {
1158/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ 1158/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
1159 return; 1159 return;
1160 } 1160 }
1161 switch(cmd[0]) { 1161 switch(cmd[0]) {
1162 case LM_FORWARDMASK: 1162 case LM_FORWARDMASK:
1163 default: 1163 default:
1164 /* we are always WONT, so don't respond */ 1164 /* we are always WONT, so don't respond */
1165 break; 1165 break;
1166 } 1166 }
1167} 1167}
1168 1168
1169static unsigned char str_lm_mode[] = { 1169static unsigned char str_lm_mode[] = {
1170 IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE 1170 IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
1171}; 1171};
1172 1172
1173void 1173void
1174lm_mode(unsigned char *cmd, int len, int init) 1174lm_mode(unsigned char *cmd, int len, int init)
1175{ 1175{
1176 if (len != 1) 1176 if (len != 1)
1177 return; 1177 return;
1178 if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) 1178 if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
1179 return; 1179 return;
1180 if (*cmd&MODE_ACK) 1180 if (*cmd&MODE_ACK)
1181 return; 1181 return;
1182 linemode = *cmd&(MODE_MASK&~MODE_ACK); 1182 linemode = *cmd&(MODE_MASK&~MODE_ACK);
1183 str_lm_mode[4] = linemode; 1183 str_lm_mode[4] = linemode;
1184 if (!init) 1184 if (!init)
1185 str_lm_mode[4] |= MODE_ACK; 1185 str_lm_mode[4] |= MODE_ACK;
1186 if ((size_t)NETROOM() > sizeof(str_lm_mode)) { 1186 if ((size_t)NETROOM() > sizeof(str_lm_mode)) {
1187 ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); 1187 ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
1188 printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); 1188 printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
1189 } 1189 }
1190/*@*/ else printf("lm_mode: not enough room in buffer\n"); 1190/*@*/ else printf("lm_mode: not enough room in buffer\n");
1191 setconnmode(0); /* set changed mode */ 1191 setconnmode(0); /* set changed mode */
1192} 1192}
1193 1193
1194  1194
1195 1195
1196/* 1196/*
1197 * slc() 1197 * slc()
1198 * Handle special character suboption of LINEMODE. 1198 * Handle special character suboption of LINEMODE.
1199 */ 1199 */
1200 1200
1201struct spc { 1201struct spc {
1202 cc_t val; 1202 cc_t val;
1203 cc_t *valp; 1203 cc_t *valp;
1204 char flags; /* Current flags & level */ 1204 char flags; /* Current flags & level */
1205 char mylevel; /* Maximum level & flags */ 1205 char mylevel; /* Maximum level & flags */
1206} spc_data[NSLC+1]; 1206} spc_data[NSLC+1];
1207 1207
1208#define SLC_IMPORT 0 1208#define SLC_IMPORT 0
1209#define SLC_EXPORT 1 1209#define SLC_EXPORT 1
1210#define SLC_RVALUE 2 1210#define SLC_RVALUE 2
1211static int slc_mode = SLC_EXPORT; 1211static int slc_mode = SLC_EXPORT;
1212 1212
1213void 1213void
1214slc_init(void) 1214slc_init(void)
1215{ 1215{
1216 struct spc *spcp; 1216 struct spc *spcp;
1217 1217
1218 localchars = 1; 1218 localchars = 1;
1219 for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { 1219 for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
1220 spcp->val = 0; 1220 spcp->val = 0;
1221 spcp->valp = 0; 1221 spcp->valp = 0;
1222 spcp->flags = spcp->mylevel = SLC_NOSUPPORT; 1222 spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
1223 } 1223 }
1224 1224
1225#define initfunc(func, flags) { \ 1225#define initfunc(func, flags) { \
1226 spcp = &spc_data[func]; \ 1226 spcp = &spc_data[func]; \
1227 if ((spcp->valp = tcval(func)) != NULL){ \ 1227 if ((spcp->valp = tcval(func)) != NULL){ \
1228 spcp->val = *spcp->valp; \ 1228 spcp->val = *spcp->valp; \
1229 spcp->mylevel = SLC_VARIABLE|flags; \ 1229 spcp->mylevel = SLC_VARIABLE|flags; \
1230 } else { \ 1230 } else { \
1231 spcp->val = 0; \ 1231 spcp->val = 0; \
1232 spcp->mylevel = SLC_DEFAULT; \ 1232 spcp->mylevel = SLC_DEFAULT; \
1233 } \ 1233 } \
1234 } 1234 }
1235 1235
1236 initfunc(SLC_SYNCH, 0); 1236 initfunc(SLC_SYNCH, 0);
1237 /* No BRK */ 1237 /* No BRK */
1238 initfunc(SLC_AO, 0); 1238 initfunc(SLC_AO, 0);
1239 initfunc(SLC_AYT, 0); 1239 initfunc(SLC_AYT, 0);
1240 /* No EOR */ 1240 /* No EOR */
1241 initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); 1241 initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
1242 initfunc(SLC_EOF, 0); 1242 initfunc(SLC_EOF, 0);
1243 initfunc(SLC_SUSP, SLC_FLUSHIN); 1243 initfunc(SLC_SUSP, SLC_FLUSHIN);
1244 initfunc(SLC_EC, 0); 1244 initfunc(SLC_EC, 0);
1245 initfunc(SLC_EL, 0); 1245 initfunc(SLC_EL, 0);
1246 initfunc(SLC_EW, 0); 1246 initfunc(SLC_EW, 0);
1247 initfunc(SLC_RP, 0); 1247 initfunc(SLC_RP, 0);
1248 initfunc(SLC_LNEXT, 0); 1248 initfunc(SLC_LNEXT, 0);
1249 initfunc(SLC_XON, 0); 1249 initfunc(SLC_XON, 0);
1250 initfunc(SLC_XOFF, 0); 1250 initfunc(SLC_XOFF, 0);
1251 initfunc(SLC_FORW1, 0); 1251 initfunc(SLC_FORW1, 0);
1252 initfunc(SLC_FORW2, 0); 1252 initfunc(SLC_FORW2, 0);
1253 /* No FORW2 */ 1253 /* No FORW2 */
1254 1254
1255 initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); 1255 initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
1256#undef initfunc 1256#undef initfunc
1257 1257
1258 if (slc_mode == SLC_EXPORT) 1258 if (slc_mode == SLC_EXPORT)
1259 slc_export(); 1259 slc_export();
1260 else 1260 else
1261 slc_import(1); 1261 slc_import(1);
1262 1262
1263} 1263}
1264 1264
1265void 1265void
1266slcstate(void) 1266slcstate(void)
1267{ 1267{
1268 printf("Special characters are %s values\n", 1268 printf("Special characters are %s values\n",
1269 slc_mode == SLC_IMPORT ? "remote default" : 1269 slc_mode == SLC_IMPORT ? "remote default" :
1270 slc_mode == SLC_EXPORT ? "local" : 1270 slc_mode == SLC_EXPORT ? "local" :
1271 "remote"); 1271 "remote");
1272} 1272}
1273 1273
1274void 1274void
1275slc_mode_export(int n) 1275slc_mode_export(int n)
1276{ 1276{
1277 slc_mode = SLC_EXPORT; 1277 slc_mode = SLC_EXPORT;
1278 if (my_state_is_will(TELOPT_LINEMODE)) 1278 if (my_state_is_will(TELOPT_LINEMODE))
1279 slc_export(); 1279 slc_export();
1280} 1280}
1281 1281
1282void 1282void
1283slc_mode_import(int def) 1283slc_mode_import(int def)
1284{ 1284{
1285 slc_mode = def ? SLC_IMPORT : SLC_RVALUE; 1285 slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
1286 if (my_state_is_will(TELOPT_LINEMODE)) 1286 if (my_state_is_will(TELOPT_LINEMODE))
1287 slc_import(def); 1287 slc_import(def);
1288} 1288}
1289 1289
1290unsigned char slc_import_val[] = { 1290unsigned char slc_import_val[] = {
1291 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE 1291 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1292}; 1292};
1293unsigned char slc_import_def[] = { 1293unsigned char slc_import_def[] = {
1294 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE 1294 IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1295}; 1295};
1296 1296
1297void 1297void
1298slc_import(int def) 1298slc_import(int def)
1299{ 1299{
1300 if ((size_t)NETROOM() > sizeof(slc_import_val)) { 1300 if ((size_t)NETROOM() > sizeof(slc_import_val)) {
1301 if (def) { 1301 if (def) {
1302 ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); 1302 ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1303 printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); 1303 printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1304 } else { 1304 } else {
1305 ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); 1305 ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1306 printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); 1306 printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1307 } 1307 }
1308 } 1308 }
1309/*@*/ else printf("slc_import: not enough room\n"); 1309/*@*/ else printf("slc_import: not enough room\n");
1310} 1310}
1311 1311
1312void 1312void
1313slc_export(void) 1313slc_export(void)
1314{ 1314{
1315 struct spc *spcp; 1315 struct spc *spcp;
1316 1316
1317 TerminalDefaultChars(); 1317 TerminalDefaultChars();
1318 1318
1319 slc_start_reply(); 1319 slc_start_reply();
1320 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1320 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1321 if (spcp->mylevel != SLC_NOSUPPORT) { 1321 if (spcp->mylevel != SLC_NOSUPPORT) {
1322 if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 1322 if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1323 spcp->flags = SLC_NOSUPPORT; 1323 spcp->flags = SLC_NOSUPPORT;
1324 else 1324 else
1325 spcp->flags = spcp->mylevel; 1325 spcp->flags = spcp->mylevel;
1326 if (spcp->valp) 1326 if (spcp->valp)
1327 spcp->val = *spcp->valp; 1327 spcp->val = *spcp->valp;
1328 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 1328 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1329 } 1329 }
1330 } 1330 }
1331 slc_end_reply(); 1331 slc_end_reply();
1332 (void)slc_update(); 1332 (void)slc_update();
1333 setconnmode(1); /* Make sure the character values are set */ 1333 setconnmode(1); /* Make sure the character values are set */
1334} 1334}
1335 1335
1336void 1336void
1337slc(unsigned char *cp, int len) 1337slc(unsigned char *cp, int len)
1338{ 1338{
1339 struct spc *spcp; 1339 struct spc *spcp;
1340 int func,level; 1340 int func,level;
1341 1341
1342 slc_start_reply(); 1342 slc_start_reply();
1343 1343
1344 for (; len >= 3; len -=3, cp +=3) { 1344 for (; len >= 3; len -=3, cp +=3) {
1345 1345
1346 func = cp[SLC_FUNC]; 1346 func = cp[SLC_FUNC];
1347 1347
1348 if (func == 0) { 1348 if (func == 0) {
1349 /* 1349 /*
1350 * Client side: always ignore 0 function. 1350 * Client side: always ignore 0 function.
1351 */ 1351 */
1352 continue; 1352 continue;
1353 } 1353 }
1354 if (func > NSLC) { 1354 if (func > NSLC) {
1355 if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) 1355 if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1356 slc_add_reply(func, SLC_NOSUPPORT, 0); 1356 slc_add_reply(func, SLC_NOSUPPORT, 0);
1357 continue; 1357 continue;
1358 } 1358 }
1359 1359
1360 spcp = &spc_data[func]; 1360 spcp = &spc_data[func];
1361 1361
1362 level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); 1362 level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1363 1363
1364 if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && 1364 if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1365 ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { 1365 ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1366 continue; 1366 continue;
1367 } 1367 }
1368 1368
1369 if (level == (SLC_DEFAULT|SLC_ACK)) { 1369 if (level == (SLC_DEFAULT|SLC_ACK)) {
1370 /* 1370 /*
1371 * This is an error condition, the SLC_ACK 1371 * This is an error condition, the SLC_ACK
1372 * bit should never be set for the SLC_DEFAULT 1372 * bit should never be set for the SLC_DEFAULT
1373 * level. Our best guess to recover is to 1373 * level. Our best guess to recover is to
1374 * ignore the SLC_ACK bit. 1374 * ignore the SLC_ACK bit.
1375 */ 1375 */
1376 cp[SLC_FLAGS] &= ~SLC_ACK; 1376 cp[SLC_FLAGS] &= ~SLC_ACK;
1377 } 1377 }
1378 1378
1379 if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { 1379 if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1380 spcp->val = (cc_t)cp[SLC_VALUE]; 1380 spcp->val = (cc_t)cp[SLC_VALUE];
1381 spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ 1381 spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */
1382 continue; 1382 continue;
1383 } 1383 }
1384 1384
1385 level &= ~SLC_ACK; 1385 level &= ~SLC_ACK;
1386 1386
1387 if (level <= (spcp->mylevel&SLC_LEVELBITS)) { 1387 if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1388 spcp->flags = cp[SLC_FLAGS]|SLC_ACK; 1388 spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1389 spcp->val = (cc_t)cp[SLC_VALUE]; 1389 spcp->val = (cc_t)cp[SLC_VALUE];
1390 } 1390 }
1391 if (level == SLC_DEFAULT) { 1391 if (level == SLC_DEFAULT) {
1392 if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) 1392 if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1393 spcp->flags = spcp->mylevel; 1393 spcp->flags = spcp->mylevel;
1394 else 1394 else
1395 spcp->flags = SLC_NOSUPPORT; 1395 spcp->flags = SLC_NOSUPPORT;
1396 } 1396 }
1397 slc_add_reply(func, spcp->flags, spcp->val); 1397 slc_add_reply(func, spcp->flags, spcp->val);
1398 } 1398 }
1399 slc_end_reply(); 1399 slc_end_reply();
1400 if (slc_update()) 1400 if (slc_update())
1401 setconnmode(1); /* set the new character values */ 1401 setconnmode(1); /* set the new character values */
1402} 1402}
1403 1403
1404void 1404void
1405slc_check(void) 1405slc_check(void)
1406{ 1406{
1407 struct spc *spcp; 1407 struct spc *spcp;
1408 1408
1409 slc_start_reply(); 1409 slc_start_reply();
1410 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1410 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1411 if (spcp->valp && spcp->val != *spcp->valp) { 1411 if (spcp->valp && spcp->val != *spcp->valp) {
1412 spcp->val = *spcp->valp; 1412 spcp->val = *spcp->valp;
1413 if (spcp->val == (cc_t)(_POSIX_VDISABLE)) 1413 if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1414 spcp->flags = SLC_NOSUPPORT; 1414 spcp->flags = SLC_NOSUPPORT;
1415 else 1415 else
1416 spcp->flags = spcp->mylevel; 1416 spcp->flags = spcp->mylevel;
1417 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); 1417 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1418 } 1418 }
1419 } 1419 }
1420 slc_end_reply(); 1420 slc_end_reply();
1421 setconnmode(1); 1421 setconnmode(1);
1422} 1422}
1423 1423
1424 1424
1425unsigned char slc_reply[128]; 1425unsigned char slc_reply[128];
1426unsigned char *slc_replyp; 1426unsigned char *slc_replyp;
1427 1427
1428void 1428void
1429slc_start_reply(void) 1429slc_start_reply(void)
1430{ 1430{
1431 slc_replyp = slc_reply; 1431 slc_replyp = slc_reply;
1432 *slc_replyp++ = IAC; 1432 *slc_replyp++ = IAC;
1433 *slc_replyp++ = SB; 1433 *slc_replyp++ = SB;
1434 *slc_replyp++ = TELOPT_LINEMODE; 1434 *slc_replyp++ = TELOPT_LINEMODE;
1435 *slc_replyp++ = LM_SLC; 1435 *slc_replyp++ = LM_SLC;
1436} 1436}
1437 1437
1438void 1438void
1439slc_add_reply(unsigned int func, unsigned int flags, cc_t value) 1439slc_add_reply(unsigned int func, unsigned int flags, cc_t value)
1440{ 1440{
1441 if ((size_t)(slc_replyp - slc_reply) + 6 > sizeof(slc_reply)) 1441 if ((size_t)(slc_replyp - slc_reply) + 6 > sizeof(slc_reply))
1442 return; 1442 return;
1443 if ((*slc_replyp++ = func) == IAC) 1443 if ((*slc_replyp++ = func) == IAC)
1444 *slc_replyp++ = IAC; 1444 *slc_replyp++ = IAC;
1445 if ((*slc_replyp++ = flags) == IAC) 1445 if ((*slc_replyp++ = flags) == IAC)
1446 *slc_replyp++ = IAC; 1446 *slc_replyp++ = IAC;
1447 if ((*slc_replyp++ = (unsigned char)value) == IAC) 1447 if ((*slc_replyp++ = (unsigned char)value) == IAC)
1448 *slc_replyp++ = IAC; 1448 *slc_replyp++ = IAC;
1449} 1449}
1450 1450
1451void 1451void
1452slc_end_reply(void) 1452slc_end_reply(void)
1453{ 1453{
1454 int len; 1454 int len;
1455 1455
1456 len = slc_replyp - slc_reply; 1456 len = slc_replyp - slc_reply;
1457 if (len <= 4 || ((size_t)len + 2 > sizeof(slc_reply))) 1457 if (len <= 4 || ((size_t)len + 2 > sizeof(slc_reply)))
1458 return; 1458 return;
1459 *slc_replyp++ = IAC; 1459 *slc_replyp++ = IAC;
1460 *slc_replyp++ = SE; 1460 *slc_replyp++ = SE;
1461 len += 2; 1461 len += 2;
1462 if (NETROOM() > len) { 1462 if (NETROOM() > len) {
1463 ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); 1463 ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1464 printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); 1464 printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1465 } 1465 }
1466/*@*/else printf("slc_end_reply: not enough room\n"); 1466/*@*/else printf("slc_end_reply: not enough room\n");
1467} 1467}
1468 1468
1469int 1469int
1470slc_update(void) 1470slc_update(void)
1471{ 1471{
1472 struct spc *spcp; 1472 struct spc *spcp;
1473 int need_update = 0; 1473 int need_update = 0;
1474 1474
1475 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { 1475 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1476 if (!(spcp->flags&SLC_ACK)) 1476 if (!(spcp->flags&SLC_ACK))
1477 continue; 1477 continue;
1478 spcp->flags &= ~SLC_ACK; 1478 spcp->flags &= ~SLC_ACK;
1479 if (spcp->valp && (*spcp->valp != spcp->val)) { 1479 if (spcp->valp && (*spcp->valp != spcp->val)) {
1480 *spcp->valp = spcp->val; 1480 *spcp->valp = spcp->val;
1481 need_update = 1; 1481 need_update = 1;
1482 } 1482 }
1483 } 1483 }
1484 return(need_update); 1484 return(need_update);
1485} 1485}
1486 1486
1487#ifdef OLD_ENVIRON 1487#ifdef OLD_ENVIRON
1488# ifdef ENV_HACK 1488# ifdef ENV_HACK
1489/* 1489/*
1490 * Earlier version of telnet/telnetd from the BSD code had 1490 * Earlier version of telnet/telnetd from the BSD code had
1491 * the definitions of VALUE and VAR reversed. To ensure 1491 * the definitions of VALUE and VAR reversed. To ensure
1492 * maximum interoperability, we assume that the server is 1492 * maximum interoperability, we assume that the server is
1493 * an older BSD server, until proven otherwise. The newer 1493 * an older BSD server, until proven otherwise. The newer
1494 * BSD servers should be able to handle either definition, 1494 * BSD servers should be able to handle either definition,
1495 * so it is better to use the wrong values if we don't 1495 * so it is better to use the wrong values if we don't
1496 * know what type of server it is. 1496 * know what type of server it is.
1497 */ 1497 */
1498int env_auto = 1; 1498int env_auto = 1;
1499int old_env_var = OLD_ENV_VAR; 1499int old_env_var = OLD_ENV_VAR;
1500int old_env_value = OLD_ENV_VALUE; 1500int old_env_value = OLD_ENV_VALUE;
1501# else 1501# else
1502# define old_env_var OLD_ENV_VAR 1502# define old_env_var OLD_ENV_VAR
1503# define old_env_value OLD_ENV_VALUE 1503# define old_env_value OLD_ENV_VALUE
1504# endif 1504# endif
1505#endif 1505#endif
1506 1506
1507void 1507void
1508env_opt(unsigned char *buf, int len) 1508env_opt(unsigned char *buf, int len)
1509{ 1509{
1510 unsigned char *ep = 0, *epc = 0; 1510 unsigned char *ep = 0, *epc = 0;
1511 int i; 1511 int i;
1512 1512
1513 switch(buf[0]&0xff) { 1513 switch(buf[0]&0xff) {
1514 case TELQUAL_SEND: 1514 case TELQUAL_SEND:
1515 env_opt_start(); 1515 env_opt_start();
1516 if (len == 1) { 1516 if (len == 1) {
1517 env_opt_add(NULL); 1517 env_opt_add(NULL);
1518 } else for (i = 1; i < len; i++) { 1518 } else for (i = 1; i < len; i++) {
1519 switch (buf[i]&0xff) { 1519 switch (buf[i]&0xff) {
1520#ifdef OLD_ENVIRON 1520#ifdef OLD_ENVIRON
1521 case OLD_ENV_VAR: 1521 case OLD_ENV_VAR:
1522# ifdef ENV_HACK 1522# ifdef ENV_HACK
1523 if (telopt_environ == TELOPT_OLD_ENVIRON 1523 if (telopt_environ == TELOPT_OLD_ENVIRON
1524 && env_auto) { 1524 && env_auto) {
1525 /* Server has the same definitions */ 1525 /* Server has the same definitions */
1526 old_env_var = OLD_ENV_VAR; 1526 old_env_var = OLD_ENV_VAR;
1527 old_env_value = OLD_ENV_VALUE; 1527 old_env_value = OLD_ENV_VALUE;
1528 } 1528 }
1529 /* FALL THROUGH */ 1529 /* FALL THROUGH */
1530# endif 1530# endif
1531 case OLD_ENV_VALUE: 1531 case OLD_ENV_VALUE:
1532 /* 1532 /*
1533 * Although OLD_ENV_VALUE is not legal, we will 1533 * Although OLD_ENV_VALUE is not legal, we will
1534 * still recognize it, just in case it is an 1534 * still recognize it, just in case it is an
1535 * old server that has VAR & VALUE mixed up... 1535 * old server that has VAR & VALUE mixed up...
1536 */ 1536 */
1537 /* FALL THROUGH */ 1537 /* FALL THROUGH */
1538#else 1538#else
1539 case NEW_ENV_VAR: 1539 case NEW_ENV_VAR:
1540#endif 1540#endif
1541 case ENV_USERVAR: 1541 case ENV_USERVAR:
1542 if (ep) { 1542 if (ep) {
1543 *epc = 0; 1543 *epc = 0;
1544 env_opt_add(ep); 1544 env_opt_add(ep);
1545 } 1545 }
1546 ep = epc = &buf[i+1]; 1546 ep = epc = &buf[i+1];
1547 break; 1547 break;
1548 case ENV_ESC: 1548 case ENV_ESC:
1549 i++; 1549 i++;
1550 /*FALL THROUGH*/ 1550 /*FALL THROUGH*/
1551 default: 1551 default:
1552 if (epc) 1552 if (epc)
1553 *epc++ = buf[i]; 1553 *epc++ = buf[i];
1554 break; 1554 break;
1555 } 1555 }
1556 } 1556 }
1557 if (ep) { 1557 if (ep) {
1558 *epc = 0; 1558 *epc = 0;
1559 env_opt_add(ep); 1559 env_opt_add(ep);
1560 } 1560 }
1561 env_opt_end(1); 1561 env_opt_end(1);
1562 break; 1562 break;
1563 1563
1564 case TELQUAL_IS: 1564 case TELQUAL_IS:
1565 case TELQUAL_INFO: 1565 case TELQUAL_INFO:
1566 /* Ignore for now. We shouldn't get it anyway. */ 1566 /* Ignore for now. We shouldn't get it anyway. */
1567 break; 1567 break;
1568 1568
1569 default: 1569 default:
1570 break; 1570 break;
1571 } 1571 }
1572} 1572}
1573 1573
1574#define OPT_REPLY_SIZE 256 1574#define OPT_REPLY_SIZE 256
1575unsigned char *opt_reply; 1575unsigned char *opt_reply;
1576unsigned char *opt_replyp; 1576unsigned char *opt_replyp;
1577unsigned char *opt_replyend; 1577unsigned char *opt_replyend;
1578 1578
1579void 1579void
1580env_opt_start(void) 1580env_opt_start(void)
1581{ 1581{
1582 unsigned char *p; 1582 unsigned char *p;
1583 1583
1584 if (opt_reply) { 1584 if (opt_reply) {
1585 p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); 1585 p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
1586 if (p == NULL) 1586 if (p == NULL)
1587 free(opt_reply); 1587 free(opt_reply);
1588 } else 1588 } else
1589 p = (unsigned char *)malloc(OPT_REPLY_SIZE); 1589 p = (unsigned char *)malloc(OPT_REPLY_SIZE);
1590 opt_reply = p; 1590 opt_reply = p;
1591 if (opt_reply == NULL) { 1591 if (opt_reply == NULL) {
1592/*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); 1592/*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
1593 opt_reply = opt_replyp = opt_replyend = NULL; 1593 opt_reply = opt_replyp = opt_replyend = NULL;
1594 return; 1594 return;
1595 } 1595 }
1596 opt_replyp = opt_reply; 1596 opt_replyp = opt_reply;
1597 opt_replyend = opt_reply + OPT_REPLY_SIZE; 1597 opt_replyend = opt_reply + OPT_REPLY_SIZE;
1598 *opt_replyp++ = IAC; 1598 *opt_replyp++ = IAC;
1599 *opt_replyp++ = SB; 1599 *opt_replyp++ = SB;
1600 *opt_replyp++ = telopt_environ; 1600 *opt_replyp++ = telopt_environ;
1601 *opt_replyp++ = TELQUAL_IS; 1601 *opt_replyp++ = TELQUAL_IS;
1602} 1602}
1603 1603
1604void 1604void
1605env_opt_start_info(void) 1605env_opt_start_info(void)
1606{ 1606{
1607 env_opt_start(); 1607 env_opt_start();
1608 if (opt_replyp) 1608 if (opt_replyp)
1609 opt_replyp[-1] = TELQUAL_INFO; 1609 opt_replyp[-1] = TELQUAL_INFO;
1610} 1610}
1611 1611
1612void 1612void
1613env_opt_add(unsigned char *ep) 1613env_opt_add(unsigned char *ep)
1614{ 1614{
1615 unsigned char *vp, c; 1615 unsigned char *vp, c;
1616 unsigned int len, olen, elen; 1616 unsigned int len, olen, elen;
1617 1617
1618 if (opt_reply == NULL) /*XXX*/ 1618 if (opt_reply == NULL) /*XXX*/
1619 return; /*XXX*/ 1619 return; /*XXX*/
1620 1620
1621 if (ep == NULL || *ep == '\0') { 1621 if (ep == NULL || *ep == '\0') {
1622 /* Send user defined variables first. */ 1622 /* Send user defined variables first. */
1623 env_default(1, 0); 1623 env_default(1, 0);
1624 while ((ep = env_default(0, 0)) != NULL) 1624 while ((ep = env_default(0, 0)) != NULL)
1625 env_opt_add(ep); 1625 env_opt_add(ep);
1626 1626
1627 /* Now add the list of well know variables. */ 1627 /* Now add the list of well know variables. */
1628 env_default(1, 1); 1628 env_default(1, 1);
1629 while ((ep = env_default(0, 1)) != NULL) 1629 while ((ep = env_default(0, 1)) != NULL)
1630 env_opt_add(ep); 1630 env_opt_add(ep);
1631 return; 1631 return;
1632 } 1632 }
1633 vp = env_getvalue(ep); 1633 vp = env_getvalue(ep);
1634 elen = 2 * (vp ? strlen((char *)vp) : 0) + 1634 elen = 2 * (vp ? strlen((char *)vp) : 0) +
1635 2 * strlen((char *)ep) + 6; 1635 2 * strlen((char *)ep) + 6;
1636 if ((unsigned int)(opt_replyend - opt_replyp) < elen) 1636 if ((unsigned int)(opt_replyend - opt_replyp) < elen)
1637 { 1637 {
1638 unsigned char *p; 1638 unsigned char *p;
1639 len = opt_replyend - opt_reply + elen; 1639 len = opt_replyend - opt_reply + elen;
1640 olen = opt_replyp - opt_reply; 1640 olen = opt_replyp - opt_reply;
1641 p = (unsigned char *)realloc(opt_reply, len); 1641 p = (unsigned char *)realloc(opt_reply, len);
1642 if (p == NULL) 1642 if (p == NULL)
1643 free(opt_reply); 1643 free(opt_reply);
1644 opt_reply = p; 1644 opt_reply = p;
1645 if (opt_reply == NULL) { 1645 if (opt_reply == NULL) {
1646/*@*/ printf("env_opt_add: realloc() failed!!!\n"); 1646/*@*/ printf("env_opt_add: realloc() failed!!!\n");
1647 opt_reply = opt_replyp = opt_replyend = NULL; 1647 opt_reply = opt_replyp = opt_replyend = NULL;
1648 return; 1648 return;
1649 } 1649 }
1650 opt_replyp = opt_reply + olen; 1650 opt_replyp = opt_reply + olen;
1651 opt_replyend = opt_reply + len; 1651 opt_replyend = opt_reply + len;
1652 } 1652 }
1653 if (opt_welldefined(ep)) 1653 if (opt_welldefined(ep))
1654#ifdef OLD_ENVIRON 1654#ifdef OLD_ENVIRON
1655 if (telopt_environ == TELOPT_OLD_ENVIRON) 1655 if (telopt_environ == TELOPT_OLD_ENVIRON)
1656 *opt_replyp++ = old_env_var; 1656 *opt_replyp++ = old_env_var;
1657 else 1657 else
1658#endif 1658#endif
1659 *opt_replyp++ = NEW_ENV_VAR; 1659 *opt_replyp++ = NEW_ENV_VAR;
1660 else 1660 else
1661 *opt_replyp++ = ENV_USERVAR; 1661 *opt_replyp++ = ENV_USERVAR;
1662 for (;;) { 1662 for (;;) {
1663 while ((c = *ep++) != '\0') { 1663 while ((c = *ep++) != '\0') {
1664 switch(c&0xff) { 1664 switch(c&0xff) {
1665 case IAC: 1665 case IAC:
1666 *opt_replyp++ = IAC; 1666 *opt_replyp++ = IAC;
1667 break; 1667 break;
1668 case NEW_ENV_VAR: 1668 case NEW_ENV_VAR:
1669 case NEW_ENV_VALUE: 1669 case NEW_ENV_VALUE:
1670 case ENV_ESC: 1670 case ENV_ESC:
1671 case ENV_USERVAR: 1671 case ENV_USERVAR:
1672 *opt_replyp++ = ENV_ESC; 1672 *opt_replyp++ = ENV_ESC;
1673 break; 1673 break;
1674 } 1674 }
1675 *opt_replyp++ = c; 1675 *opt_replyp++ = c;
1676 } 1676 }
1677 if ((ep = vp) != NULL) { 1677 if ((ep = vp) != NULL) {
1678#ifdef OLD_ENVIRON 1678#ifdef OLD_ENVIRON
1679 if (telopt_environ == TELOPT_OLD_ENVIRON) 1679 if (telopt_environ == TELOPT_OLD_ENVIRON)
1680 *opt_replyp++ = old_env_value; 1680 *opt_replyp++ = old_env_value;
1681 else 1681 else
1682#endif 1682#endif
1683 *opt_replyp++ = NEW_ENV_VALUE; 1683 *opt_replyp++ = NEW_ENV_VALUE;
1684 vp = NULL; 1684 vp = NULL;
1685 } else 1685 } else
1686 break; 1686 break;
1687 } 1687 }
1688} 1688}
1689 1689
1690int 1690int
1691opt_welldefined(const char *ep) 1691opt_welldefined(const char *ep)
1692{ 1692{
1693 if ((strcmp(ep, "USER") == 0) || 1693 if ((strcmp(ep, "USER") == 0) ||
1694 (strcmp(ep, "DISPLAY") == 0) || 1694 (strcmp(ep, "DISPLAY") == 0) ||
1695 (strcmp(ep, "PRINTER") == 0) || 1695 (strcmp(ep, "PRINTER") == 0) ||
1696 (strcmp(ep, "SYSTEMTYPE") == 0) || 1696 (strcmp(ep, "SYSTEMTYPE") == 0) ||
1697 (strcmp(ep, "JOB") == 0) || 1697 (strcmp(ep, "JOB") == 0) ||
1698 (strcmp(ep, "ACCT") == 0)) 1698 (strcmp(ep, "ACCT") == 0))
1699 return(1); 1699 return(1);
1700 return(0); 1700 return(0);
1701} 1701}
1702void 1702void
1703env_opt_end(int emptyok) 1703env_opt_end(int emptyok)
1704{ 1704{
1705 int len; 1705 int len;
1706 1706
1707 len = opt_replyp - opt_reply + 2; 1707 len = opt_replyp - opt_reply + 2;
1708 if (emptyok || len > 6) { 1708 if (emptyok || len > 6) {
1709 *opt_replyp++ = IAC; 1709 *opt_replyp++ = IAC;
1710 *opt_replyp++ = SE; 1710 *opt_replyp++ = SE;
1711 if (NETROOM() > len) { 1711 if (NETROOM() > len) {
1712 ring_supply_data(&netoring, opt_reply, len); 1712 ring_supply_data(&netoring, opt_reply, len);
1713 printsub('>', &opt_reply[2], len - 2); 1713 printsub('>', &opt_reply[2], len - 2);
1714 } 1714 }
1715/*@*/ else printf("slc_end_reply: not enough room\n"); 1715/*@*/ else printf("slc_end_reply: not enough room\n");
1716 } 1716 }
1717 if (opt_reply) { 1717 if (opt_reply) {
1718 free(opt_reply); 1718 free(opt_reply);
1719 opt_reply = opt_replyp = opt_replyend = NULL; 1719 opt_reply = opt_replyp = opt_replyend = NULL;
1720 } 1720 }
1721} 1721}
1722 1722
1723  1723
1724 1724
1725int 1725int
1726telrcv(void) 1726telrcv(void)
1727{ 1727{
1728 int c; 1728 int c;
1729 int scc; 1729 int scc;
1730 unsigned char *sbp = NULL; 1730 unsigned char *sbp = NULL;
1731 int count; 1731 int count;
1732 int returnValue = 0; 1732 int returnValue = 0;
1733 1733
1734 scc = 0; 1734 scc = 0;
1735 count = 0; 1735 count = 0;
1736 while (TTYROOM() > 2) { 1736 while (TTYROOM() > 2) {
1737 if (scc == 0) { 1737 if (scc == 0) {
1738 if (count) { 1738 if (count) {
1739 ring_consumed(&netiring, count); 1739 ring_consumed(&netiring, count);
1740 returnValue = 1; 1740 returnValue = 1;
1741 count = 0; 1741 count = 0;
1742 } 1742 }
1743 sbp = netiring.consume; 1743 sbp = netiring.consume;
1744 scc = ring_full_consecutive(&netiring); 1744 scc = ring_full_consecutive(&netiring);
1745 if (scc == 0) { 1745 if (scc == 0) {
1746 /* No more data coming in */ 1746 /* No more data coming in */
1747 break; 1747 break;
1748 } 1748 }
1749 } 1749 }
1750 1750
1751 c = *sbp++ & 0xff, scc--; count++; 1751 c = *sbp++ & 0xff, scc--; count++;
1752#ifdef ENCRYPTION 1752#ifdef ENCRYPTION
1753 if (decrypt_input) 1753 if (decrypt_input)
1754 c = (*decrypt_input)(c); 1754 c = (*decrypt_input)(c);
1755#endif /* ENCRYPTION */ 1755#endif /* ENCRYPTION */
1756 1756
1757 switch (telrcv_state) { 1757 switch (telrcv_state) {
1758 1758
1759 case TS_CR: 1759 case TS_CR:
1760 telrcv_state = TS_DATA; 1760 telrcv_state = TS_DATA;
1761 if (c == '\0') { 1761 if (c == '\0') {
1762 break; /* Ignore \0 after CR */ 1762 break; /* Ignore \0 after CR */
1763 } 1763 }
1764 else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { 1764 else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1765 TTYADD(c); 1765 TTYADD(c);
1766 break; 1766 break;
1767 } 1767 }
1768 /* Else, fall through */ 1768 /* Else, fall through */
1769 1769
1770 case TS_DATA: 1770 case TS_DATA:
1771 if (c == IAC) { 1771 if (c == IAC) {
1772 telrcv_state = TS_IAC; 1772 telrcv_state = TS_IAC;
1773 break; 1773 break;
1774 } 1774 }
1775# if defined(TN3270) 1775# if defined(TN3270)
1776 if (In3270) { 1776 if (In3270) {
1777 *Ifrontp++ = c; 1777 *Ifrontp++ = c;
1778 while (scc > 0) { 1778 while (scc > 0) {
1779 c = *sbp++ & 0377, scc--; count++; 1779 c = *sbp++ & 0377, scc--; count++;
1780#ifdef ENCRYPTION 1780#ifdef ENCRYPTION
1781 if (decrypt_input) 1781 if (decrypt_input)
1782 c = (*decrypt_input)(c); 1782 c = (*decrypt_input)(c);
1783#endif /* ENCRYPTION */ 1783#endif /* ENCRYPTION */
1784 if (c == IAC) { 1784 if (c == IAC) {
1785 telrcv_state = TS_IAC; 1785 telrcv_state = TS_IAC;
1786 break; 1786 break;
1787 } 1787 }
1788 *Ifrontp++ = c; 1788 *Ifrontp++ = c;
1789 } 1789 }
1790 } else 1790 } else
1791# endif /* defined(TN3270) */ 1791# endif /* defined(TN3270) */
1792 /* 1792 /*
1793 * The 'crmod' hack (see following) is needed 1793 * The 'crmod' hack (see following) is needed
1794 * since we can't * set CRMOD on output only. 1794 * since we can't * set CRMOD on output only.
1795 * Machines like MULTICS like to send \r without 1795 * Machines like MULTICS like to send \r without
1796 * \n; since we must turn off CRMOD to get proper 1796 * \n; since we must turn off CRMOD to get proper
1797 * input, the mapping is done here (sigh). 1797 * input, the mapping is done here (sigh).
1798 */ 1798 */
1799 if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { 1799 if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) {
1800 if (scc > 0) { 1800 if (scc > 0) {
1801 c = *sbp&0xff; 1801 c = *sbp&0xff;
1802#ifdef ENCRYPTION 1802#ifdef ENCRYPTION
1803 if (decrypt_input) 1803 if (decrypt_input)
1804 c = (*decrypt_input)(c); 1804 c = (*decrypt_input)(c);
1805#endif /* ENCRYPTION */ 1805#endif /* ENCRYPTION */
1806 if (c == 0) { 1806 if (c == 0) {
1807 sbp++, scc--; count++; 1807 sbp++, scc--; count++;
1808 /* a "true" CR */ 1808 /* a "true" CR */
1809 TTYADD('\r'); 1809 TTYADD('\r');
1810 } else if (my_want_state_is_dont(TELOPT_ECHO) && 1810 } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1811 (c == '\n')) { 1811 (c == '\n')) {
1812 sbp++, scc--; count++; 1812 sbp++, scc--; count++;
1813 TTYADD('\n'); 1813 TTYADD('\n');
1814 } else { 1814 } else {
1815#ifdef ENCRYPTION 1815#ifdef ENCRYPTION
1816 if (decrypt_input) 1816 if (decrypt_input)
1817 (*decrypt_input)(-1); 1817 (*decrypt_input)(-1);
1818#endif /* ENCRYPTION */ 1818#endif /* ENCRYPTION */
1819 1819
1820 TTYADD('\r'); 1820 TTYADD('\r');
1821 if (crmod) { 1821 if (crmod) {
1822 TTYADD('\n'); 1822 TTYADD('\n');
1823 } 1823 }
1824 } 1824 }
1825 } else { 1825 } else {
1826 telrcv_state = TS_CR; 1826 telrcv_state = TS_CR;
1827 TTYADD('\r'); 1827 TTYADD('\r');
1828 if (crmod) { 1828 if (crmod) {
1829 TTYADD('\n'); 1829 TTYADD('\n');
1830 } 1830 }
1831 } 1831 }
1832 } else { 1832 } else {
1833 TTYADD(c); 1833 TTYADD(c);
1834 } 1834 }
1835 continue; 1835 continue;
1836 1836
1837 case TS_IAC: 1837 case TS_IAC:
1838process_iac: 1838process_iac:
1839 switch (c) { 1839 switch (c) {
1840 1840
1841 case WILL: 1841 case WILL:
1842 telrcv_state = TS_WILL; 1842 telrcv_state = TS_WILL;
1843 continue; 1843 continue;
1844 1844
1845 case WONT: 1845 case WONT:
1846 telrcv_state = TS_WONT; 1846 telrcv_state = TS_WONT;
1847 continue; 1847 continue;
1848 1848
1849 case DO: 1849 case DO:
1850 telrcv_state = TS_DO; 1850 telrcv_state = TS_DO;
1851 continue; 1851 continue;
1852 1852
1853 case DONT: 1853 case DONT:
1854 telrcv_state = TS_DONT; 1854 telrcv_state = TS_DONT;
1855 continue; 1855 continue;
1856 1856
1857 case DM: 1857 case DM:
1858 /* 1858 /*
1859 * We may have missed an urgent notification, 1859 * We may have missed an urgent notification,
1860 * so make sure we flush whatever is in the 1860 * so make sure we flush whatever is in the
1861 * buffer currently. 1861 * buffer currently.
1862 */ 1862 */
1863 printoption("RCVD", IAC, DM); 1863 printoption("RCVD", IAC, DM);
1864 SYNCHing = 1; 1864 SYNCHing = 1;
1865 (void) ttyflush(1); 1865 (void) ttyflush(1);
1866 SYNCHing = stilloob(); 1866 SYNCHing = stilloob();
1867 settimer(gotDM); 1867 settimer(gotDM);
1868 break; 1868 break;
1869 1869
1870 case SB: 1870 case SB:
1871 SB_CLEAR(); 1871 SB_CLEAR();
1872 telrcv_state = TS_SB; 1872 telrcv_state = TS_SB;
1873 continue; 1873 continue;
1874 1874
1875# if defined(TN3270) 1875# if defined(TN3270)
1876 case EOR: 1876 case EOR:
1877 if (In3270) { 1877 if (In3270) {
1878 if (Ibackp == Ifrontp) { 1878 if (Ibackp == Ifrontp) {
1879 Ibackp = Ifrontp = Ibuf; 1879 Ibackp = Ifrontp = Ibuf;
1880 ISend = 0; /* should have been! */ 1880 ISend = 0; /* should have been! */
1881 } else { 1881 } else {
1882 Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); 1882 Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1);
1883 ISend = 1; 1883 ISend = 1;
1884 } 1884 }
1885 } 1885 }
1886 printoption("RCVD", IAC, EOR); 1886 printoption("RCVD", IAC, EOR);
1887 break; 1887 break;
1888# endif /* defined(TN3270) */ 1888# endif /* defined(TN3270) */
1889 1889
1890 case IAC: 1890 case IAC:
1891# if !defined(TN3270) 1891# if !defined(TN3270)
1892 TTYADD(IAC); 1892 TTYADD(IAC);
1893# else /* !defined(TN3270) */ 1893# else /* !defined(TN3270) */
1894 if (In3270) { 1894 if (In3270) {
1895 *Ifrontp++ = IAC; 1895 *Ifrontp++ = IAC;
1896 } else { 1896 } else {
1897 TTYADD(IAC); 1897 TTYADD(IAC);
1898 } 1898 }
1899# endif /* !defined(TN3270) */ 1899# endif /* !defined(TN3270) */
1900 break; 1900 break;
1901 1901
1902 case NOP: 1902 case NOP:
1903 case GA: 1903 case GA:
1904 default: 1904 default:
1905 printoption("RCVD", IAC, c); 1905 printoption("RCVD", IAC, c);
1906 break; 1906 break;
1907 } 1907 }
1908 telrcv_state = TS_DATA; 1908 telrcv_state = TS_DATA;
1909 continue; 1909 continue;
1910 1910
1911 case TS_WILL: 1911 case TS_WILL:
1912 printoption("RCVD", WILL, c); 1912 printoption("RCVD", WILL, c);
1913 willoption(c); 1913 willoption(c);
1914 SetIn3270(); 1914 SetIn3270();
1915 telrcv_state = TS_DATA; 1915 telrcv_state = TS_DATA;
1916 continue; 1916 continue;
1917 1917
1918 case TS_WONT: 1918 case TS_WONT:
1919 printoption("RCVD", WONT, c); 1919 printoption("RCVD", WONT, c);
1920 wontoption(c); 1920 wontoption(c);
1921 SetIn3270(); 1921 SetIn3270();
1922 telrcv_state = TS_DATA; 1922 telrcv_state = TS_DATA;
1923 continue; 1923 continue;
1924 1924
1925 case TS_DO: 1925 case TS_DO:
1926 printoption("RCVD", DO, c); 1926 printoption("RCVD", DO, c);
1927 dooption(c); 1927 dooption(c);
1928 SetIn3270(); 1928 SetIn3270();
1929 if (c == TELOPT_NAWS) { 1929 if (c == TELOPT_NAWS) {
1930 sendnaws(); 1930 sendnaws();
1931 } else if (c == TELOPT_LFLOW) { 1931 } else if (c == TELOPT_LFLOW) {
1932 localflow = 1; 1932 localflow = 1;
1933 setcommandmode(); 1933 setcommandmode();
1934 setconnmode(0); 1934 setconnmode(0);
1935 } 1935 }
1936 telrcv_state = TS_DATA; 1936 telrcv_state = TS_DATA;
1937 continue; 1937 continue;
1938 1938
1939 case TS_DONT: 1939 case TS_DONT:
1940 printoption("RCVD", DONT, c); 1940 printoption("RCVD", DONT, c);
1941 dontoption(c); 1941 dontoption(c);
1942 flushline = 1; 1942 flushline = 1;
1943 setconnmode(0); /* set new tty mode (maybe) */ 1943 setconnmode(0); /* set new tty mode (maybe) */
1944 SetIn3270(); 1944 SetIn3270();
1945 telrcv_state = TS_DATA; 1945 telrcv_state = TS_DATA;
1946 continue; 1946 continue;
1947 1947
1948 case TS_SB: 1948 case TS_SB:
1949 if (c == IAC) { 1949 if (c == IAC) {
1950 telrcv_state = TS_SE; 1950 telrcv_state = TS_SE;
1951 } else { 1951 } else {
1952 SB_ACCUM(c); 1952 SB_ACCUM(c);
1953 } 1953 }
1954 continue; 1954 continue;
1955 1955
1956 case TS_SE: 1956 case TS_SE:
1957 if (c != SE) { 1957 if (c != SE) {
1958 if (c != IAC) { 1958 if (c != IAC) {
1959 /* 1959 /*
1960 * This is an error. We only expect to get 1960 * This is an error. We only expect to get
1961 * "IAC IAC" or "IAC SE". Several things may 1961 * "IAC IAC" or "IAC SE". Several things may
1962 * have happened. An IAC was not doubled, the 1962 * have happened. An IAC was not doubled, the
1963 * IAC SE was left off, or another option got 1963 * IAC SE was left off, or another option got
1964 * inserted into the suboption are all possibilities. 1964 * inserted into the suboption are all possibilities.
1965 * If we assume that the IAC was not doubled, 1965 * If we assume that the IAC was not doubled,
1966 * and really the IAC SE was left off, we could 1966 * and really the IAC SE was left off, we could
1967 * get into an infinite loop here. So, instead, 1967 * get into an infinite loop here. So, instead,
1968 * we terminate the suboption, and process the 1968 * we terminate the suboption, and process the
1969 * partial suboption if we can. 1969 * partial suboption if we can.
1970 */ 1970 */
1971 SB_ACCUM(IAC); 1971 SB_ACCUM(IAC);
1972 SB_ACCUM(c); 1972 SB_ACCUM(c);
1973 subpointer -= 2; 1973 subpointer -= 2;
1974 SB_TERM(); 1974 SB_TERM();
1975 1975
1976 printoption("In SUBOPTION processing, RCVD", IAC, c); 1976 printoption("In SUBOPTION processing, RCVD", IAC, c);
1977 suboption(); /* handle sub-option */ 1977 suboption(); /* handle sub-option */
1978 SetIn3270(); 1978 SetIn3270();
1979 telrcv_state = TS_IAC; 1979 telrcv_state = TS_IAC;
1980 goto process_iac; 1980 goto process_iac;
1981 } 1981 }
1982 SB_ACCUM(c); 1982 SB_ACCUM(c);
1983 telrcv_state = TS_SB; 1983 telrcv_state = TS_SB;
1984 } else { 1984 } else {
1985 SB_ACCUM(IAC); 1985 SB_ACCUM(IAC);
1986 SB_ACCUM(SE); 1986 SB_ACCUM(SE);

cvs diff -r1.23 -r1.23.20.1 src/usr.bin/telnet/utilities.c (switch to unified diff)

--- src/usr.bin/telnet/utilities.c 2012/01/09 16:08:55 1.23
+++ src/usr.bin/telnet/utilities.c 2018/12/18 18:37:26 1.23.20.1
@@ -1,925 +1,925 @@ @@ -1,925 +1,925 @@
1/* $NetBSD: utilities.c,v 1.23 2012/01/09 16:08:55 christos Exp $ */ 1/* $NetBSD: utilities.c,v 1.23.20.1 2018/12/18 18:37:26 martin Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1993 4 * Copyright (c) 1988, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors 15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software 16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission. 17 * without specific prior written permission.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34#if 0 34#if 0
35static char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; 35static char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95";
36#else 36#else
37__RCSID("$NetBSD: utilities.c,v 1.23 2012/01/09 16:08:55 christos Exp $"); 37__RCSID("$NetBSD: utilities.c,v 1.23.20.1 2018/12/18 18:37:26 martin Exp $");
38#endif 38#endif
39#endif /* not lint */ 39#endif /* not lint */
40 40
41#define TELOPTS 41#define TELOPTS
42#define TELCMDS 42#define TELCMDS
43#define SLC_NAMES 43#define SLC_NAMES
44#include <arpa/telnet.h> 44#include <arpa/telnet.h>
45#include <sys/types.h> 45#include <sys/types.h>
46#include <sys/time.h> 46#include <sys/time.h>
47#include <sys/socket.h> 47#include <sys/socket.h>
48#include <unistd.h> 48#include <unistd.h>
49#include <poll.h> 49#include <poll.h>
50 50
51#include <ctype.h> 51#include <ctype.h>
52 52
53#include "general.h" 53#include "general.h"
54#include "ring.h" 54#include "ring.h"
55#include "defines.h" 55#include "defines.h"
56#include "externs.h" 56#include "externs.h"
57 57
58#ifdef TN3270 58#ifdef TN3270
59#include "../sys_curses/telextrn.h" 59#include "../sys_curses/telextrn.h"
60#endif 60#endif
61 61
62#ifdef AUTHENTICATION 62#ifdef AUTHENTICATION
63#include <libtelnet/auth.h> 63#include <libtelnet/auth.h>
64#endif 64#endif
65#ifdef ENCRYPTION 65#ifdef ENCRYPTION
66#include <libtelnet/encrypt.h> 66#include <libtelnet/encrypt.h>
67#endif 67#endif
68 68
69FILE *NetTrace = 0; /* Not in bss, since needs to stay */ 69FILE *NetTrace = 0; /* Not in bss, since needs to stay */
70int prettydump; 70int prettydump;
71 71
72/* 72/*
73 * upcase() 73 * upcase()
74 * 74 *
75 * Upcase (in place) the argument. 75 * Upcase (in place) the argument.
76 */ 76 */
77 77
78void 78void
79upcase(char *argument) 79upcase(char *argument)
80{ 80{
81 int c; 81 int c;
82 82
83 while ((c = *argument) != 0) { 83 while ((c = *argument) != 0) {
84 if (islower(c)) { 84 if (islower(c)) {
85 *argument = toupper(c); 85 *argument = toupper(c);
86 } 86 }
87 argument++; 87 argument++;
88 } 88 }
89} 89}
90 90
91/* 91/*
92 * SetSockOpt() 92 * SetSockOpt()
93 * 93 *
94 * Compensate for differences in 4.2 and 4.3 systems. 94 * Compensate for differences in 4.2 and 4.3 systems.
95 */ 95 */
96 96
97int 97int
98SetSockOpt(int fd, int level, int option, int yesno) 98SetSockOpt(int fd, int level, int option, int yesno)
99{ 99{
100 return setsockopt(fd, level, option, (char *)&yesno, sizeof yesno); 100 return setsockopt(fd, level, option, (char *)&yesno, sizeof yesno);
101} 101}
102  102
103/* 103/*
104 * The following are routines used to print out debugging information. 104 * The following are routines used to print out debugging information.
105 */ 105 */
106 106
107char NetTraceFile[256] = "(standard output)"; 107char NetTraceFile[256] = "(standard output)";
108 108
109void 109void
110SetNetTrace(char *file) 110SetNetTrace(char *file)
111{ 111{
112 if (NetTrace && NetTrace != stdout) 112 if (NetTrace && NetTrace != stdout)
113 fclose(NetTrace); 113 fclose(NetTrace);
114 if (file && (strcmp(file, "-") != 0)) { 114 if (file && (strcmp(file, "-") != 0)) {
115 NetTrace = fopen(file, "w"); 115 NetTrace = fopen(file, "w");
116 if (NetTrace) { 116 if (NetTrace) {
117 strlcpy(NetTraceFile, file, sizeof(NetTraceFile)); 117 strlcpy(NetTraceFile, file, sizeof(NetTraceFile));
118 return; 118 return;
119 } 119 }
120 fprintf(stderr, "Cannot open %s.\n", file); 120 fprintf(stderr, "Cannot open %s.\n", file);
121 } 121 }
122 NetTrace = stdout; 122 NetTrace = stdout;
123 strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile)); 123 strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile));
124} 124}
125 125
126void 126void
127Dump(int direction, unsigned char *buffer, int length) 127Dump(int direction, unsigned char *buffer, int length)
128{ 128{
129# define BYTES_PER_LINE 32 129# define BYTES_PER_LINE 32
130# define min(x,y) ((x<y)? x:y) 130# define min(x,y) ((x<y)? x:y)
131 unsigned char *pThis; 131 unsigned char *pThis;
132 int offset; 132 int offset;
133 133
134 offset = 0; 134 offset = 0;
135 135
136 while (length) { 136 while (length) {
137 /* print one line */ 137 /* print one line */
138 fprintf(NetTrace, "%c 0x%x\t", direction, offset); 138 fprintf(NetTrace, "%c 0x%x\t", direction, offset);
139 pThis = buffer; 139 pThis = buffer;
140 if (prettydump) { 140 if (prettydump) {
141 buffer = buffer + min(length, BYTES_PER_LINE/2); 141 buffer = buffer + min(length, BYTES_PER_LINE/2);
142 while (pThis < buffer) { 142 while (pThis < buffer) {
143 fprintf(NetTrace, "%c%.2x", 143 fprintf(NetTrace, "%c%.2x",
144 (((*pThis)&0xff) == 0xff) ? '*' : ' ', 144 (((*pThis)&0xff) == 0xff) ? '*' : ' ',
145 (*pThis)&0xff); 145 (*pThis)&0xff);
146 pThis++; 146 pThis++;
147 } 147 }
148 length -= BYTES_PER_LINE/2; 148 length -= BYTES_PER_LINE/2;
149 offset += BYTES_PER_LINE/2; 149 offset += BYTES_PER_LINE/2;
150 } else { 150 } else {
151 buffer = buffer + min(length, BYTES_PER_LINE); 151 buffer = buffer + min(length, BYTES_PER_LINE);
152 while (pThis < buffer) { 152 while (pThis < buffer) {
153 fprintf(NetTrace, "%.2x", (*pThis)&0xff); 153 fprintf(NetTrace, "%.2x", (*pThis)&0xff);
154 pThis++; 154 pThis++;
155 } 155 }
156 length -= BYTES_PER_LINE; 156 length -= BYTES_PER_LINE;
157 offset += BYTES_PER_LINE; 157 offset += BYTES_PER_LINE;
158 } 158 }
159 if (NetTrace == stdout) { 159 if (NetTrace == stdout) {
160 fprintf(NetTrace, "\r\n"); 160 fprintf(NetTrace, "\r\n");
161 } else { 161 } else {
162 fprintf(NetTrace, "\n"); 162 fprintf(NetTrace, "\n");
163 } 163 }
164 if (length < 0) { 164 if (length < 0) {
165 fflush(NetTrace); 165 fflush(NetTrace);
166 return; 166 return;
167 } 167 }
168 /* find next unique line */ 168 /* find next unique line */
169 } 169 }
170 fflush(NetTrace); 170 fflush(NetTrace);
171} 171}
172 172
173 173
174void 174void
175printoption(const char *direction, int cmd, int option) 175printoption(const char *direction, int cmd, int option)
176{ 176{
177 if (!showoptions) 177 if (!showoptions)
178 return; 178 return;
179 if (cmd == IAC) { 179 if (cmd == IAC) {
180 if (TELCMD_OK(option)) 180 if (TELCMD_OK(option))
181 fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); 181 fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option));
182 else 182 else
183 fprintf(NetTrace, "%s IAC %d", direction, option); 183 fprintf(NetTrace, "%s IAC %d", direction, option);
184 } else { 184 } else {
185 const char *fmt; 185 const char *fmt;
186 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : 186 fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" :
187 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; 187 (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0;
188 if (fmt) { 188 if (fmt) {
189 fprintf(NetTrace, "%s %s ", direction, fmt); 189 fprintf(NetTrace, "%s %s ", direction, fmt);
190 if (TELOPT_OK(option)) 190 if (TELOPT_OK(option))
191 fprintf(NetTrace, "%s", TELOPT(option)); 191 fprintf(NetTrace, "%s", TELOPT(option));
192 else if (option == TELOPT_EXOPL) 192 else if (option == TELOPT_EXOPL)
193 fprintf(NetTrace, "EXOPL"); 193 fprintf(NetTrace, "EXOPL");
194 else 194 else
195 fprintf(NetTrace, "%d", option); 195 fprintf(NetTrace, "%d", option);
196 } else 196 } else
197 fprintf(NetTrace, "%s %d %d", direction, cmd, option); 197 fprintf(NetTrace, "%s %d %d", direction, cmd, option);
198 } 198 }
199 if (NetTrace == stdout) { 199 if (NetTrace == stdout) {
200 fprintf(NetTrace, "\r\n"); 200 fprintf(NetTrace, "\r\n");
201 fflush(NetTrace); 201 fflush(NetTrace);
202 } else { 202 } else {
203 fprintf(NetTrace, "\n"); 203 fprintf(NetTrace, "\n");
204 } 204 }
205 return; 205 return;
206} 206}
207 207
208void 208void
209optionstatus(void) 209optionstatus(void)
210{ 210{
211 int i; 211 int i;
212 extern char will_wont_resp[], do_dont_resp[]; 212 extern char will_wont_resp[], do_dont_resp[];
213 213
214 for (i = 0; i < 256; i++) { 214 for (i = 0; i < 256; i++) {
215 if (do_dont_resp[i]) { 215 if (do_dont_resp[i]) {
216 if (TELOPT_OK(i)) 216 if (TELOPT_OK(i))
217 printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); 217 printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]);
218 else if (TELCMD_OK(i)) 218 else if (TELCMD_OK(i))
219 printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); 219 printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]);
220 else 220 else
221 printf("resp DO_DONT %d: %d\n", i, 221 printf("resp DO_DONT %d: %d\n", i,
222 do_dont_resp[i]); 222 do_dont_resp[i]);
223 if (my_want_state_is_do(i)) { 223 if (my_want_state_is_do(i)) {
224 if (TELOPT_OK(i)) 224 if (TELOPT_OK(i))
225 printf("want DO %s\n", TELOPT(i)); 225 printf("want DO %s\n", TELOPT(i));
226 else if (TELCMD_OK(i)) 226 else if (TELCMD_OK(i))
227 printf("want DO %s\n", TELCMD(i)); 227 printf("want DO %s\n", TELCMD(i));
228 else 228 else
229 printf("want DO %d\n", i); 229 printf("want DO %d\n", i);
230 } else { 230 } else {
231 if (TELOPT_OK(i)) 231 if (TELOPT_OK(i))
232 printf("want DONT %s\n", TELOPT(i)); 232 printf("want DONT %s\n", TELOPT(i));
233 else if (TELCMD_OK(i)) 233 else if (TELCMD_OK(i))
234 printf("want DONT %s\n", TELCMD(i)); 234 printf("want DONT %s\n", TELCMD(i));
235 else 235 else
236 printf("want DONT %d\n", i); 236 printf("want DONT %d\n", i);
237 } 237 }
238 } else { 238 } else {
239 if (my_state_is_do(i)) { 239 if (my_state_is_do(i)) {
240 if (TELOPT_OK(i)) 240 if (TELOPT_OK(i))
241 printf(" DO %s\n", TELOPT(i)); 241 printf(" DO %s\n", TELOPT(i));
242 else if (TELCMD_OK(i)) 242 else if (TELCMD_OK(i))
243 printf(" DO %s\n", TELCMD(i)); 243 printf(" DO %s\n", TELCMD(i));
244 else 244 else
245 printf(" DO %d\n", i); 245 printf(" DO %d\n", i);
246 } 246 }
247 } 247 }
248 if (will_wont_resp[i]) { 248 if (will_wont_resp[i]) {
249 if (TELOPT_OK(i)) 249 if (TELOPT_OK(i))
250 printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); 250 printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]);
251 else if (TELCMD_OK(i)) 251 else if (TELCMD_OK(i))
252 printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); 252 printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]);
253 else 253 else
254 printf("resp WILL_WONT %d: %d\n", 254 printf("resp WILL_WONT %d: %d\n",
255 i, will_wont_resp[i]); 255 i, will_wont_resp[i]);
256 if (my_want_state_is_will(i)) { 256 if (my_want_state_is_will(i)) {
257 if (TELOPT_OK(i)) 257 if (TELOPT_OK(i))
258 printf("want WILL %s\n", TELOPT(i)); 258 printf("want WILL %s\n", TELOPT(i));
259 else if (TELCMD_OK(i)) 259 else if (TELCMD_OK(i))
260 printf("want WILL %s\n", TELCMD(i)); 260 printf("want WILL %s\n", TELCMD(i));
261 else 261 else
262 printf("want WILL %d\n", i); 262 printf("want WILL %d\n", i);
263 } else { 263 } else {
264 if (TELOPT_OK(i)) 264 if (TELOPT_OK(i))
265 printf("want WONT %s\n", TELOPT(i)); 265 printf("want WONT %s\n", TELOPT(i));
266 else if (TELCMD_OK(i)) 266 else if (TELCMD_OK(i))
267 printf("want WONT %s\n", TELCMD(i)); 267 printf("want WONT %s\n", TELCMD(i));
268 else 268 else
269 printf("want WONT %d\n", i); 269 printf("want WONT %d\n", i);
270 } 270 }
271 } else { 271 } else {
272 if (my_state_is_will(i)) { 272 if (my_state_is_will(i)) {
273 if (TELOPT_OK(i)) 273 if (TELOPT_OK(i))
274 printf(" WILL %s\n", TELOPT(i)); 274 printf(" WILL %s\n", TELOPT(i));
275 else if (TELCMD_OK(i)) 275 else if (TELCMD_OK(i))
276 printf(" WILL %s\n", TELCMD(i)); 276 printf(" WILL %s\n", TELCMD(i));
277 else 277 else
278 printf(" WILL %d\n", i); 278 printf(" WILL %d\n", i);
279 } 279 }
280 } 280 }
281 } 281 }
282 282
283} 283}
284 284
285void 285void
286printsub( 286printsub(
287 int direction, /* '<' or '>' */ 287 int direction, /* '<' or '>' */
288 unsigned char *pointer, /* where suboption data sits */ 288 unsigned char *pointer, /* where suboption data sits */
289 int length) /* length of suboption data */ 289 int length) /* length of suboption data */
290{ 290{
291 int i; 291 int i;
292#ifdef ENCRYPTION 292#ifdef ENCRYPTION
293 char buf[512]; 293 char buf[512];
294#endif /* ENCRYPTION */ 294#endif /* ENCRYPTION */
295 extern int want_status_response; 295 extern int want_status_response;
296 296
297 if (showoptions || direction == 0 || 297 if (showoptions || direction == 0 ||
298 (want_status_response && (pointer[0] == TELOPT_STATUS))) { 298 (want_status_response && (pointer[0] == TELOPT_STATUS))) {
299 if (direction) { 299 if (direction) {
300 fprintf(NetTrace, "%s IAC SB ", 300 fprintf(NetTrace, "%s IAC SB ",
301 (direction == '<')? "RCVD":"SENT"); 301 (direction == '<')? "RCVD":"SENT");
302 if (length >= 3) { 302 if (length >= 3) {
303 int j; 303 int j;
304 304
305 i = pointer[length-2]; 305 i = pointer[length-2];
306 j = pointer[length-1]; 306 j = pointer[length-1];
307 307
308 if (i != IAC || j != SE) { 308 if (i != IAC || j != SE) {
309 fprintf(NetTrace, "(terminated by "); 309 fprintf(NetTrace, "(terminated by ");
310 if (TELOPT_OK(i)) 310 if (TELOPT_OK(i))
311 fprintf(NetTrace, "%s ", TELOPT(i)); 311 fprintf(NetTrace, "%s ", TELOPT(i));
312 else if (TELCMD_OK(i)) 312 else if (TELCMD_OK(i))
313 fprintf(NetTrace, "%s ", TELCMD(i)); 313 fprintf(NetTrace, "%s ", TELCMD(i));
314 else 314 else
315 fprintf(NetTrace, "%d ", i); 315 fprintf(NetTrace, "%d ", i);
316 if (TELOPT_OK(j)) 316 if (TELOPT_OK(j))
317 fprintf(NetTrace, "%s", TELOPT(j)); 317 fprintf(NetTrace, "%s", TELOPT(j));
318 else if (TELCMD_OK(j)) 318 else if (TELCMD_OK(j))
319 fprintf(NetTrace, "%s", TELCMD(j)); 319 fprintf(NetTrace, "%s", TELCMD(j));
320 else 320 else
321 fprintf(NetTrace, "%d", j); 321 fprintf(NetTrace, "%d", j);
322 fprintf(NetTrace, ", not IAC SE!) "); 322 fprintf(NetTrace, ", not IAC SE!) ");
323 } 323 }
324 } 324 }
325 length -= 2; 325 length -= 2;
326 } 326 }
327 if (length < 1) { 327 if (length < 1) {
328 fprintf(NetTrace, "(Empty suboption??\?)"); 328 fprintf(NetTrace, "(Empty suboption??\?)");
329 if (NetTrace == stdout) 329 if (NetTrace == stdout)
330 fflush(NetTrace); 330 fflush(NetTrace);
331 return; 331 return;
332 } 332 }
333 switch (pointer[0]) { 333 switch (pointer[0]) {
334 case TELOPT_TTYPE: 334 case TELOPT_TTYPE:
335 fprintf(NetTrace, "TERMINAL-TYPE "); 335 fprintf(NetTrace, "TERMINAL-TYPE ");
336 switch (pointer[1]) { 336 switch (pointer[1]) {
337 case TELQUAL_IS: 337 case TELQUAL_IS:
338 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 338 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
339 break; 339 break;
340 case TELQUAL_SEND: 340 case TELQUAL_SEND:
341 fprintf(NetTrace, "SEND"); 341 fprintf(NetTrace, "SEND");
342 break; 342 break;
343 default: 343 default:
344 fprintf(NetTrace, 344 fprintf(NetTrace,
345 "- unknown qualifier %d (0x%x).", 345 "- unknown qualifier %d (0x%x).",
346 pointer[1], pointer[1]); 346 pointer[1], pointer[1]);
347 } 347 }
348 break; 348 break;
349 case TELOPT_TSPEED: 349 case TELOPT_TSPEED:
350 fprintf(NetTrace, "TERMINAL-SPEED"); 350 fprintf(NetTrace, "TERMINAL-SPEED");
351 if (length < 2) { 351 if (length < 2) {
352 fprintf(NetTrace, " (empty suboption??\?)"); 352 fprintf(NetTrace, " (empty suboption??\?)");
353 break; 353 break;
354 } 354 }
355 switch (pointer[1]) { 355 switch (pointer[1]) {
356 case TELQUAL_IS: 356 case TELQUAL_IS:
357 fprintf(NetTrace, " IS "); 357 fprintf(NetTrace, " IS ");
358 fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); 358 fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2);
359 break; 359 break;
360 default: 360 default:
361 if (pointer[1] == 1) 361 if (pointer[1] == 1)
362 fprintf(NetTrace, " SEND"); 362 fprintf(NetTrace, " SEND");
363 else 363 else
364 fprintf(NetTrace, " %d (unknown)", pointer[1]); 364 fprintf(NetTrace, " %d (unknown)", pointer[1]);
365 for (i = 2; i < length; i++) 365 for (i = 2; i < length; i++)
366 fprintf(NetTrace, " ?%d?", pointer[i]); 366 fprintf(NetTrace, " ?%d?", pointer[i]);
367 break; 367 break;
368 } 368 }
369 break; 369 break;
370 370
371 case TELOPT_LFLOW: 371 case TELOPT_LFLOW:
372 fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); 372 fprintf(NetTrace, "TOGGLE-FLOW-CONTROL");
373 if (length < 2) { 373 if (length < 2) {
374 fprintf(NetTrace, " (empty suboption??\?)"); 374 fprintf(NetTrace, " (empty suboption??\?)");
375 break; 375 break;
376 } 376 }
377 switch (pointer[1]) { 377 switch (pointer[1]) {
378 case LFLOW_OFF: 378 case LFLOW_OFF:
379 fprintf(NetTrace, " OFF"); break; 379 fprintf(NetTrace, " OFF"); break;
380 case LFLOW_ON: 380 case LFLOW_ON:
381 fprintf(NetTrace, " ON"); break; 381 fprintf(NetTrace, " ON"); break;
382 case LFLOW_RESTART_ANY: 382 case LFLOW_RESTART_ANY:
383 fprintf(NetTrace, " RESTART-ANY"); break; 383 fprintf(NetTrace, " RESTART-ANY"); break;
384 case LFLOW_RESTART_XON: 384 case LFLOW_RESTART_XON:
385 fprintf(NetTrace, " RESTART-XON"); break; 385 fprintf(NetTrace, " RESTART-XON"); break;
386 default: 386 default:
387 fprintf(NetTrace, " %d (unknown)", pointer[1]); 387 fprintf(NetTrace, " %d (unknown)", pointer[1]);
388 } 388 }
389 for (i = 2; i < length; i++) 389 for (i = 2; i < length; i++)
390 fprintf(NetTrace, " ?%d?", pointer[i]); 390 fprintf(NetTrace, " ?%d?", pointer[i]);
391 break; 391 break;
392 392
393 case TELOPT_NAWS: 393 case TELOPT_NAWS:
394 fprintf(NetTrace, "NAWS"); 394 fprintf(NetTrace, "NAWS");
395 if (length < 2) { 395 if (length < 2) {
396 fprintf(NetTrace, " (empty suboption??\?)"); 396 fprintf(NetTrace, " (empty suboption??\?)");
397 break; 397 break;
398 } 398 }
399 if (length == 2) { 399 if (length == 2) {
400 fprintf(NetTrace, " ?%d?", pointer[1]); 400 fprintf(NetTrace, " ?%d?", pointer[1]);
401 break; 401 break;
402 } 402 }
403 fprintf(NetTrace, " %d %d (%d)", 403 fprintf(NetTrace, " %d %d (%d)",
404 pointer[1], pointer[2], 404 pointer[1], pointer[2],
405 (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 405 (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
406 if (length == 4) { 406 if (length == 4) {
407 fprintf(NetTrace, " ?%d?", pointer[3]); 407 fprintf(NetTrace, " ?%d?", pointer[3]);
408 break; 408 break;
409 } 409 }
410 fprintf(NetTrace, " %d %d (%d)", 410 fprintf(NetTrace, " %d %d (%d)",
411 pointer[3], pointer[4], 411 pointer[3], pointer[4],
412 (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 412 (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
413 for (i = 5; i < length; i++) 413 for (i = 5; i < length; i++)
414 fprintf(NetTrace, " ?%d?", pointer[i]); 414 fprintf(NetTrace, " ?%d?", pointer[i]);
415 break; 415 break;
416 416
417#ifdef AUTHENTICATION 417#ifdef AUTHENTICATION
418 case TELOPT_AUTHENTICATION: 418 case TELOPT_AUTHENTICATION:
419 fprintf(NetTrace, "AUTHENTICATION"); 419 fprintf(NetTrace, "AUTHENTICATION");
420 if (length < 2) { 420 if (length < 2) {
421 fprintf(NetTrace, " (empty suboption??\?)"); 421 fprintf(NetTrace, " (empty suboption??\?)");
422 break; 422 break;
423 } 423 }
424 switch (pointer[1]) { 424 switch (pointer[1]) {
425 case TELQUAL_REPLY: 425 case TELQUAL_REPLY:
426 case TELQUAL_IS: 426 case TELQUAL_IS:
427 fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? 427 fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ?
428 "IS" : "REPLY"); 428 "IS" : "REPLY");
429 if (AUTHTYPE_NAME_OK(pointer[2])) 429 if (AUTHTYPE_NAME_OK(pointer[2]))
430 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); 430 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2]));
431 else 431 else
432 fprintf(NetTrace, "%d ", pointer[2]); 432 fprintf(NetTrace, "%d ", pointer[2]);
433 if (length < 3) { 433 if (length < 3) {
434 fprintf(NetTrace, "(partial suboption??\?)"); 434 fprintf(NetTrace, "(partial suboption??\?)");
435 break; 435 break;
436 } 436 }
437 fprintf(NetTrace, "%s|%s", 437 fprintf(NetTrace, "%s|%s",
438 ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 438 ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
439 "CLIENT" : "SERVER", 439 "CLIENT" : "SERVER",
440 ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 440 ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
441 "MUTUAL" : "ONE-WAY"); 441 "MUTUAL" : "ONE-WAY");
442 442
443 auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 443 auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
444 fprintf(NetTrace, "%s", buf); 444 fprintf(NetTrace, "%s", buf);
445 break; 445 break;
446 446
447 case TELQUAL_SEND: 447 case TELQUAL_SEND:
448 i = 2; 448 i = 2;
449 fprintf(NetTrace, " SEND "); 449 fprintf(NetTrace, " SEND ");
450 while (i < length) { 450 while (i < length) {
451 if (AUTHTYPE_NAME_OK(pointer[i])) 451 if (AUTHTYPE_NAME_OK(pointer[i]))
452 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); 452 fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i]));
453 else 453 else
454 fprintf(NetTrace, "%d ", pointer[i]); 454 fprintf(NetTrace, "%d ", pointer[i]);
455 if (++i >= length) { 455 if (++i >= length) {
456 fprintf(NetTrace, "(partial suboption??\?)"); 456 fprintf(NetTrace, "(partial suboption??\?)");
457 break; 457 break;
458 } 458 }
459 fprintf(NetTrace, "%s|%s ", 459 fprintf(NetTrace, "%s|%s ",
460 ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 460 ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
461 "CLIENT" : "SERVER", 461 "CLIENT" : "SERVER",
462 ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 462 ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
463 "MUTUAL" : "ONE-WAY"); 463 "MUTUAL" : "ONE-WAY");
464 ++i; 464 ++i;
465 } 465 }
466 break; 466 break;
467 467
468 case TELQUAL_NAME: 468 case TELQUAL_NAME:
469 i = 2; 469 i = 2;
470 fprintf(NetTrace, " NAME \""); 470 fprintf(NetTrace, " NAME \"");
471 while (i < length) 471 while (i < length)
472 putc(pointer[i++], NetTrace); 472 putc(pointer[i++], NetTrace);
473 putc('"', NetTrace); 473 putc('"', NetTrace);
474 break; 474 break;
475 475
476 default: 476 default:
477 for (i = 2; i < length; i++) 477 for (i = 2; i < length; i++)
478 fprintf(NetTrace, " ?%d?", pointer[i]); 478 fprintf(NetTrace, " ?%d?", pointer[i]);
479 break; 479 break;
480 } 480 }
481 break; 481 break;
482#endif 482#endif
483 483
484#ifdef ENCRYPTION 484#ifdef ENCRYPTION
485 case TELOPT_ENCRYPT: 485 case TELOPT_ENCRYPT:
486 fprintf(NetTrace, "ENCRYPT"); 486 fprintf(NetTrace, "ENCRYPT");
487 if (length < 2) { 487 if (length < 2) {
488 fprintf(NetTrace, " (empty suboption??\?)"); 488 fprintf(NetTrace, " (empty suboption??\?)");
489 break; 489 break;
490 } 490 }
491 switch (pointer[1]) { 491 switch (pointer[1]) {
492 case ENCRYPT_START: 492 case ENCRYPT_START:
493 fprintf(NetTrace, " START"); 493 fprintf(NetTrace, " START");
494 break; 494 break;
495 495
496 case ENCRYPT_END: 496 case ENCRYPT_END:
497 fprintf(NetTrace, " END"); 497 fprintf(NetTrace, " END");
498 break; 498 break;
499 499
500 case ENCRYPT_REQSTART: 500 case ENCRYPT_REQSTART:
501 fprintf(NetTrace, " REQUEST-START"); 501 fprintf(NetTrace, " REQUEST-START");
502 break; 502 break;
503 503
504 case ENCRYPT_REQEND: 504 case ENCRYPT_REQEND:
505 fprintf(NetTrace, " REQUEST-END"); 505 fprintf(NetTrace, " REQUEST-END");
506 break; 506 break;
507 507
508 case ENCRYPT_IS: 508 case ENCRYPT_IS:
509 case ENCRYPT_REPLY: 509 case ENCRYPT_REPLY:
510 fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? 510 fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ?
511 "IS" : "REPLY"); 511 "IS" : "REPLY");
512 if (length < 3) { 512 if (length < 3) {
513 fprintf(NetTrace, " (partial suboption??\?)"); 513 fprintf(NetTrace, " (partial suboption??\?)");
514 break; 514 break;
515 } 515 }
516 if (ENCTYPE_NAME_OK(pointer[2])) 516 if (ENCTYPE_NAME_OK(pointer[2]))
517 fprintf(NetTrace, "%s ", 517 fprintf(NetTrace, "%s ",
518 ENCTYPE_NAME(pointer[2])); 518 ENCTYPE_NAME(pointer[2]));
519 else 519 else
520 fprintf(NetTrace, " %d (unknown)", pointer[2]); 520 fprintf(NetTrace, " %d (unknown)", pointer[2]);
521 521
522 encrypt_printsub(&pointer[1], length - 1, buf, 522 encrypt_printsub(&pointer[1], length - 1, buf,
523 sizeof(buf)); 523 sizeof(buf));
524 fprintf(NetTrace, "%s", buf); 524 fprintf(NetTrace, "%s", buf);
525 break; 525 break;
526 526
527 case ENCRYPT_SUPPORT: 527 case ENCRYPT_SUPPORT:
528 i = 2; 528 i = 2;
529 fprintf(NetTrace, " SUPPORT "); 529 fprintf(NetTrace, " SUPPORT ");
530 while (i < length) { 530 while (i < length) {
531 if (ENCTYPE_NAME_OK(pointer[i])) 531 if (ENCTYPE_NAME_OK(pointer[i]))
532 fprintf(NetTrace, "%s ", 532 fprintf(NetTrace, "%s ",
533 ENCTYPE_NAME(pointer[i])); 533 ENCTYPE_NAME(pointer[i]));
534 else 534 else
535 fprintf(NetTrace, "%d ", pointer[i]); 535 fprintf(NetTrace, "%d ", pointer[i]);
536 i++; 536 i++;
537 } 537 }
538 break; 538 break;
539 539
540 case ENCRYPT_ENC_KEYID: 540 case ENCRYPT_ENC_KEYID:
541 fprintf(NetTrace, " ENC_KEYID "); 541 fprintf(NetTrace, " ENC_KEYID ");
542 goto encommon; 542 goto encommon;
543 543
544 case ENCRYPT_DEC_KEYID: 544 case ENCRYPT_DEC_KEYID:
545 fprintf(NetTrace, " DEC_KEYID "); 545 fprintf(NetTrace, " DEC_KEYID ");
546 goto encommon; 546 goto encommon;
547 547
548 default: 548 default:
549 fprintf(NetTrace, " %d (unknown)", pointer[1]); 549 fprintf(NetTrace, " %d (unknown)", pointer[1]);
550 encommon: 550 encommon:
551 for (i = 2; i < length; i++) 551 for (i = 2; i < length; i++)
552 fprintf(NetTrace, " %d", pointer[i]); 552 fprintf(NetTrace, " %d", pointer[i]);
553 break; 553 break;
554 } 554 }
555 break; 555 break;
556#endif /* ENCRYPTION */ 556#endif /* ENCRYPTION */
557 557
558 case TELOPT_LINEMODE: 558 case TELOPT_LINEMODE:
559 fprintf(NetTrace, "LINEMODE "); 559 fprintf(NetTrace, "LINEMODE ");
560 if (length < 2) { 560 if (length < 2) {
561 fprintf(NetTrace, " (empty suboption??\?)"); 561 fprintf(NetTrace, " (empty suboption??\?)");
562 break; 562 break;
563 } 563 }
564 switch (pointer[1]) { 564 switch (pointer[1]) {
565 case WILL: 565 case WILL:
566 fprintf(NetTrace, "WILL "); 566 fprintf(NetTrace, "WILL ");
567 goto common; 567 goto common;
568 case WONT: 568 case WONT:
569 fprintf(NetTrace, "WONT "); 569 fprintf(NetTrace, "WONT ");
570 goto common; 570 goto common;
571 case DO: 571 case DO:
572 fprintf(NetTrace, "DO "); 572 fprintf(NetTrace, "DO ");
573 goto common; 573 goto common;
574 case DONT: 574 case DONT:
575 fprintf(NetTrace, "DONT "); 575 fprintf(NetTrace, "DONT ");
576 common: 576 common:
577 if (length < 3) { 577 if (length < 3) {
578 fprintf(NetTrace, "(no option??\?)"); 578 fprintf(NetTrace, "(no option??\?)");
579 break; 579 break;
580 } 580 }
581 switch (pointer[2]) { 581 switch (pointer[2]) {
582 case LM_FORWARDMASK: 582 case LM_FORWARDMASK:
583 fprintf(NetTrace, "Forward Mask"); 583 fprintf(NetTrace, "Forward Mask");
584 for (i = 3; i < length; i++) 584 for (i = 3; i < length; i++)
585 fprintf(NetTrace, " %x", pointer[i]); 585 fprintf(NetTrace, " %x", pointer[i]);
586 break; 586 break;
587 default: 587 default:
588 fprintf(NetTrace, "%d (unknown)", pointer[2]); 588 fprintf(NetTrace, "%d (unknown)", pointer[2]);
589 for (i = 3; i < length; i++) 589 for (i = 3; i < length; i++)
590 fprintf(NetTrace, " %d", pointer[i]); 590 fprintf(NetTrace, " %d", pointer[i]);
591 break; 591 break;
592 } 592 }
593 break; 593 break;
594 594
595 case LM_SLC: 595 case LM_SLC:
596 fprintf(NetTrace, "SLC"); 596 fprintf(NetTrace, "SLC");
597 for (i = 2; i < length - 2; i += 3) { 597 for (i = 2; i < length - 2; i += 3) {
598 if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 598 if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
599 fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 599 fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC]));
600 else 600 else
601 fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); 601 fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]);
602 switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 602 switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
603 case SLC_NOSUPPORT: 603 case SLC_NOSUPPORT:
604 fprintf(NetTrace, " NOSUPPORT"); break; 604 fprintf(NetTrace, " NOSUPPORT"); break;
605 case SLC_CANTCHANGE: 605 case SLC_CANTCHANGE:
606 fprintf(NetTrace, " CANTCHANGE"); break; 606 fprintf(NetTrace, " CANTCHANGE"); break;
607 case SLC_VARIABLE: 607 case SLC_VARIABLE:
608 fprintf(NetTrace, " VARIABLE"); break; 608 fprintf(NetTrace, " VARIABLE"); break;
609 case SLC_DEFAULT: 609 case SLC_DEFAULT:
610 fprintf(NetTrace, " DEFAULT"); break; 610 fprintf(NetTrace, " DEFAULT"); break;
611 } 611 }
612 fprintf(NetTrace, "%s%s%s", 612 fprintf(NetTrace, "%s%s%s",
613 pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 613 pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
614 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 614 pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
615 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 615 pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
616 if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 616 if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
617 SLC_FLUSHOUT| SLC_LEVELBITS)) 617 SLC_FLUSHOUT| SLC_LEVELBITS))
618 fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); 618 fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]);
619 fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); 619 fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]);
620 if ((pointer[i+SLC_VALUE] == IAC) && 620 if ((pointer[i+SLC_VALUE] == IAC) &&
621 (pointer[i+SLC_VALUE+1] == IAC)) 621 (pointer[i+SLC_VALUE+1] == IAC))
622 i++; 622 i++;
623 } 623 }
624 for (; i < length; i++) 624 for (; i < length; i++)
625 fprintf(NetTrace, " ?%d?", pointer[i]); 625 fprintf(NetTrace, " ?%d?", pointer[i]);
626 break; 626 break;
627 627
628 case LM_MODE: 628 case LM_MODE:
629 fprintf(NetTrace, "MODE "); 629 fprintf(NetTrace, "MODE ");
630 if (length < 3) { 630 if (length < 3) {
631 fprintf(NetTrace, "(no mode??\?)"); 631 fprintf(NetTrace, "(no mode??\?)");
632 break; 632 break;
633 } 633 }
634 { 634 {
635 char tbuf[64]; 635 char tbuf[64];
636 sprintf(tbuf, "%s%s%s%s%s", 636 snprintf(tbuf, sizeof(tbuf), "%s%s%s%s%s",
637 pointer[2]&MODE_EDIT ? "|EDIT" : "", 637 pointer[2]&MODE_EDIT ? "|EDIT" : "",
638 pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 638 pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
639 pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 639 pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
640 pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 640 pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
641 pointer[2]&MODE_ACK ? "|ACK" : ""); 641 pointer[2]&MODE_ACK ? "|ACK" : "");
642 fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); 642 fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
643 } 643 }
644 if (pointer[2]&~(MODE_MASK)) 644 if (pointer[2]&~(MODE_MASK))
645 fprintf(NetTrace, " (0x%x)", pointer[2]); 645 fprintf(NetTrace, " (0x%x)", pointer[2]);
646 for (i = 3; i < length; i++) 646 for (i = 3; i < length; i++)
647 fprintf(NetTrace, " ?0x%x?", pointer[i]); 647 fprintf(NetTrace, " ?0x%x?", pointer[i]);
648 break; 648 break;
649 default: 649 default:
650 fprintf(NetTrace, "%d (unknown)", pointer[1]); 650 fprintf(NetTrace, "%d (unknown)", pointer[1]);
651 for (i = 2; i < length; i++) 651 for (i = 2; i < length; i++)
652 fprintf(NetTrace, " %d", pointer[i]); 652 fprintf(NetTrace, " %d", pointer[i]);
653 } 653 }
654 break; 654 break;
655 655
656 case TELOPT_STATUS: { 656 case TELOPT_STATUS: {
657 const char *cp; 657 const char *cp;
658 int j, k; 658 int j, k;
659 659
660 fprintf(NetTrace, "STATUS"); 660 fprintf(NetTrace, "STATUS");
661 661
662 switch (pointer[1]) { 662 switch (pointer[1]) {
663 default: 663 default:
664 if (pointer[1] == TELQUAL_SEND) 664 if (pointer[1] == TELQUAL_SEND)
665 fprintf(NetTrace, " SEND"); 665 fprintf(NetTrace, " SEND");
666 else 666 else
667 fprintf(NetTrace, " %d (unknown)", pointer[1]); 667 fprintf(NetTrace, " %d (unknown)", pointer[1]);
668 for (i = 2; i < length; i++) 668 for (i = 2; i < length; i++)
669 fprintf(NetTrace, " ?%d?", pointer[i]); 669 fprintf(NetTrace, " ?%d?", pointer[i]);
670 break; 670 break;
671 case TELQUAL_IS: 671 case TELQUAL_IS:
672 if (--want_status_response < 0) 672 if (--want_status_response < 0)
673 want_status_response = 0; 673 want_status_response = 0;
674 if (NetTrace == stdout) 674 if (NetTrace == stdout)
675 fprintf(NetTrace, " IS\r\n"); 675 fprintf(NetTrace, " IS\r\n");
676 else 676 else
677 fprintf(NetTrace, " IS\n"); 677 fprintf(NetTrace, " IS\n");
678 678
679 for (i = 2; i < length; i++) { 679 for (i = 2; i < length; i++) {
680 switch(pointer[i]) { 680 switch(pointer[i]) {
681 case DO: cp = "DO"; goto common2; 681 case DO: cp = "DO"; goto common2;
682 case DONT: cp = "DONT"; goto common2; 682 case DONT: cp = "DONT"; goto common2;
683 case WILL: cp = "WILL"; goto common2; 683 case WILL: cp = "WILL"; goto common2;
684 case WONT: cp = "WONT"; goto common2; 684 case WONT: cp = "WONT"; goto common2;
685 common2: 685 common2:
686 i++; 686 i++;
687 if (TELOPT_OK((int)pointer[i])) 687 if (TELOPT_OK((int)pointer[i]))
688 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); 688 fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i]));
689 else 689 else
690 fprintf(NetTrace, " %s %d", cp, pointer[i]); 690 fprintf(NetTrace, " %s %d", cp, pointer[i]);
691 691
692 if (NetTrace == stdout) 692 if (NetTrace == stdout)
693 fprintf(NetTrace, "\r\n"); 693 fprintf(NetTrace, "\r\n");
694 else 694 else
695 fprintf(NetTrace, "\n"); 695 fprintf(NetTrace, "\n");
696 break; 696 break;
697 697
698 case SB: 698 case SB:
699 fprintf(NetTrace, " SB "); 699 fprintf(NetTrace, " SB ");
700 i++; 700 i++;
701 j = k = i; 701 j = k = i;
702 while (j < length) { 702 while (j < length) {
703 if (pointer[j] == SE) { 703 if (pointer[j] == SE) {
704 if (j+1 == length) 704 if (j+1 == length)
705 break; 705 break;
706 if (pointer[j+1] == SE) 706 if (pointer[j+1] == SE)
707 j++; 707 j++;
708 else 708 else
709 break; 709 break;
710 } 710 }
711 pointer[k++] = pointer[j++]; 711 pointer[k++] = pointer[j++];
712 } 712 }
713 printsub(0, &pointer[i], k - i); 713 printsub(0, &pointer[i], k - i);
714 if (i < length) { 714 if (i < length) {
715 fprintf(NetTrace, " SE"); 715 fprintf(NetTrace, " SE");
716 i = j; 716 i = j;
717 } else 717 } else
718 i = j - 1; 718 i = j - 1;
719 719
720 if (NetTrace == stdout) 720 if (NetTrace == stdout)
721 fprintf(NetTrace, "\r\n"); 721 fprintf(NetTrace, "\r\n");
722 else 722 else
723 fprintf(NetTrace, "\n"); 723 fprintf(NetTrace, "\n");
724 724
725 break; 725 break;
726 726
727 default: 727 default:
728 fprintf(NetTrace, " %d", pointer[i]); 728 fprintf(NetTrace, " %d", pointer[i]);
729 break; 729 break;
730 } 730 }
731 } 731 }
732 break; 732 break;
733 } 733 }
734 break; 734 break;
735 } 735 }
736 736
737 case TELOPT_XDISPLOC: 737 case TELOPT_XDISPLOC:
738 fprintf(NetTrace, "X-DISPLAY-LOCATION "); 738 fprintf(NetTrace, "X-DISPLAY-LOCATION ");
739 switch (pointer[1]) { 739 switch (pointer[1]) {
740 case TELQUAL_IS: 740 case TELQUAL_IS:
741 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 741 fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2);
742 break; 742 break;
743 case TELQUAL_SEND: 743 case TELQUAL_SEND:
744 fprintf(NetTrace, "SEND"); 744 fprintf(NetTrace, "SEND");
745 break; 745 break;
746 default: 746 default:
747 fprintf(NetTrace, "- unknown qualifier %d (0x%x).", 747 fprintf(NetTrace, "- unknown qualifier %d (0x%x).",
748 pointer[1], pointer[1]); 748 pointer[1], pointer[1]);
749 } 749 }
750 break; 750 break;
751 751
752 case TELOPT_NEW_ENVIRON: 752 case TELOPT_NEW_ENVIRON:
753 fprintf(NetTrace, "NEW-ENVIRON "); 753 fprintf(NetTrace, "NEW-ENVIRON ");
754#ifdef OLD_ENVIRON 754#ifdef OLD_ENVIRON
755 goto env_common1; 755 goto env_common1;
756 case TELOPT_OLD_ENVIRON: 756 case TELOPT_OLD_ENVIRON:
757 fprintf(NetTrace, "OLD-ENVIRON"); 757 fprintf(NetTrace, "OLD-ENVIRON");
758 env_common1: 758 env_common1:
759#endif 759#endif
760 switch (pointer[1]) { 760 switch (pointer[1]) {
761 case TELQUAL_IS: 761 case TELQUAL_IS:
762 fprintf(NetTrace, "IS "); 762 fprintf(NetTrace, "IS ");
763 goto env_common; 763 goto env_common;
764 case TELQUAL_SEND: 764 case TELQUAL_SEND:
765 fprintf(NetTrace, "SEND "); 765 fprintf(NetTrace, "SEND ");
766 goto env_common; 766 goto env_common;
767 case TELQUAL_INFO: 767 case TELQUAL_INFO:
768 fprintf(NetTrace, "INFO "); 768 fprintf(NetTrace, "INFO ");
769 env_common: 769 env_common:
770 { 770 {
771 static const char NQ[] = "\" "; 771 static const char NQ[] = "\" ";
772 const char *noquote = NQ; 772 const char *noquote = NQ;
773#if defined(ENV_HACK) && defined(OLD_ENVIRON) 773#if defined(ENV_HACK) && defined(OLD_ENVIRON)
774 extern int old_env_var, old_env_value; 774 extern int old_env_var, old_env_value;
775#endif 775#endif
776 for (i = 2; i < length; i++ ) { 776 for (i = 2; i < length; i++ ) {
777 switch (pointer[i]) { 777 switch (pointer[i]) {
778 case NEW_ENV_VALUE: 778 case NEW_ENV_VALUE:
779#ifdef OLD_ENVIRON 779#ifdef OLD_ENVIRON
780 /* case NEW_ENV_OVAR: */ 780 /* case NEW_ENV_OVAR: */
781 if (pointer[0] == TELOPT_OLD_ENVIRON) { 781 if (pointer[0] == TELOPT_OLD_ENVIRON) {
782# ifdef ENV_HACK 782# ifdef ENV_HACK
783 if (old_env_var == OLD_ENV_VALUE) 783 if (old_env_var == OLD_ENV_VALUE)
784 fprintf(NetTrace, "%s(VALUE) ", noquote); 784 fprintf(NetTrace, "%s(VALUE) ", noquote);
785 else 785 else
786# endif 786# endif
787 fprintf(NetTrace, "%sVAR ", noquote); 787 fprintf(NetTrace, "%sVAR ", noquote);
788 } else 788 } else
789#endif /* OLD_ENVIRON */ 789#endif /* OLD_ENVIRON */
790 fprintf(NetTrace, "%sVALUE ", noquote); 790 fprintf(NetTrace, "%sVALUE ", noquote);
791 noquote = NQ; 791 noquote = NQ;
792 break; 792 break;
793 793
794 case NEW_ENV_VAR: 794 case NEW_ENV_VAR:
795#ifdef OLD_ENVIRON 795#ifdef OLD_ENVIRON
796 /* case OLD_ENV_VALUE: */ 796 /* case OLD_ENV_VALUE: */
797 if (pointer[0] == TELOPT_OLD_ENVIRON) { 797 if (pointer[0] == TELOPT_OLD_ENVIRON) {
798# ifdef ENV_HACK 798# ifdef ENV_HACK
799 if (old_env_value == OLD_ENV_VAR) 799 if (old_env_value == OLD_ENV_VAR)
800 fprintf(NetTrace, "%s(VAR) ", noquote); 800 fprintf(NetTrace, "%s(VAR) ", noquote);
801 else 801 else
802# endif 802# endif
803 fprintf(NetTrace, "%sVALUE ", noquote); 803 fprintf(NetTrace, "%sVALUE ", noquote);
804 } else 804 } else
805#endif /* OLD_ENVIRON */ 805#endif /* OLD_ENVIRON */
806 fprintf(NetTrace, "%sVAR ", noquote); 806 fprintf(NetTrace, "%sVAR ", noquote);
807 noquote = NQ; 807 noquote = NQ;
808 break; 808 break;
809 809
810 case ENV_ESC: 810 case ENV_ESC:
811 fprintf(NetTrace, "%sESC ", noquote); 811 fprintf(NetTrace, "%sESC ", noquote);
812 noquote = NQ; 812 noquote = NQ;
813 break; 813 break;
814 814
815 case ENV_USERVAR: 815 case ENV_USERVAR:
816 fprintf(NetTrace, "%sUSERVAR ", noquote); 816 fprintf(NetTrace, "%sUSERVAR ", noquote);
817 noquote = NQ; 817 noquote = NQ;
818 break; 818 break;
819 819
820 default: 820 default:
821 if (isprint(pointer[i]) && pointer[i] != '"') { 821 if (isprint(pointer[i]) && pointer[i] != '"') {
822 if (*noquote) { 822 if (*noquote) {
823 putc('"', NetTrace); 823 putc('"', NetTrace);
824 noquote = ""; 824 noquote = "";
825 } 825 }
826 putc(pointer[i], NetTrace); 826 putc(pointer[i], NetTrace);
827 } else { 827 } else {
828 fprintf(NetTrace, "%s%03o ", noquote, 828 fprintf(NetTrace, "%s%03o ", noquote,
829 pointer[i]); 829 pointer[i]);
830 noquote = NQ; 830 noquote = NQ;
831 } 831 }
832 break; 832 break;
833 } 833 }
834 } 834 }
835 if (!noquote) 835 if (!noquote)
836 putc('"', NetTrace); 836 putc('"', NetTrace);
837 break; 837 break;
838 } 838 }
839 } 839 }
840 break; 840 break;
841 841
842 default: 842 default:
843 if (TELOPT_OK(pointer[0])) 843 if (TELOPT_OK(pointer[0]))
844 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); 844 fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
845 else 845 else
846 fprintf(NetTrace, "%d (unknown)", pointer[0]); 846 fprintf(NetTrace, "%d (unknown)", pointer[0]);
847 for (i = 1; i < length; i++) 847 for (i = 1; i < length; i++)
848 fprintf(NetTrace, " %d", pointer[i]); 848 fprintf(NetTrace, " %d", pointer[i]);
849 break; 849 break;
850 } 850 }
851 if (direction) { 851 if (direction) {
852 if (NetTrace == stdout) 852 if (NetTrace == stdout)
853 fprintf(NetTrace, "\r\n"); 853 fprintf(NetTrace, "\r\n");
854 else 854 else
855 fprintf(NetTrace, "\n"); 855 fprintf(NetTrace, "\n");
856 } 856 }
857 if (NetTrace == stdout) 857 if (NetTrace == stdout)
858 fflush(NetTrace); 858 fflush(NetTrace);
859 } 859 }
860} 860}
861 861
862/* EmptyTerminal - called to make sure that the terminal buffer is empty. 862/* EmptyTerminal - called to make sure that the terminal buffer is empty.
863 * Note that we consider the buffer to run all the 863 * Note that we consider the buffer to run all the
864 * way to the kernel (thus the poll). 864 * way to the kernel (thus the poll).
865 */ 865 */
866 866
867void 867void
868EmptyTerminal(void) 868EmptyTerminal(void)
869{ 869{
870 struct pollfd set[1]; 870 struct pollfd set[1];
871 871
872 set[0].fd = tout; 872 set[0].fd = tout;
873 set[0].events = POLLOUT; 873 set[0].events = POLLOUT;
874 874
875 if (TTYBYTES() == 0) { 875 if (TTYBYTES() == 0) {
876 (void) poll(set, 1, INFTIM); 876 (void) poll(set, 1, INFTIM);
877 } else { 877 } else {
878 while (TTYBYTES()) { 878 while (TTYBYTES()) {
879 (void) ttyflush(0); 879 (void) ttyflush(0);
880 (void) poll(set, 1, INFTIM); 880 (void) poll(set, 1, INFTIM);
881 } 881 }
882 } 882 }
883} 883}
884 884
885void 885void
886SetForExit(void) 886SetForExit(void)
887{ 887{
888 setconnmode(0); 888 setconnmode(0);
889#ifdef TN3270 889#ifdef TN3270
890 if (In3270) { 890 if (In3270) {
891 Finish3270(); 891 Finish3270();
892 } 892 }
893#else /* defined(TN3270) */ 893#else /* defined(TN3270) */
894 do { 894 do {
895 (void)telrcv(); /* Process any incoming data */ 895 (void)telrcv(); /* Process any incoming data */
896 EmptyTerminal(); 896 EmptyTerminal();
897 } while (ring_full_count(&netiring)); /* While there is any */ 897 } while (ring_full_count(&netiring)); /* While there is any */
898#endif /* defined(TN3270) */ 898#endif /* defined(TN3270) */
899 setcommandmode(); 899 setcommandmode();
900 fflush(stdout); 900 fflush(stdout);
901 fflush(stderr); 901 fflush(stderr);
902#ifdef TN3270 902#ifdef TN3270
903 if (In3270) { 903 if (In3270) {
904 StopScreen(1); 904 StopScreen(1);
905 } 905 }
906#endif /* defined(TN3270) */ 906#endif /* defined(TN3270) */
907 setconnmode(0); 907 setconnmode(0);
908 EmptyTerminal(); /* Flush the path to the tty */ 908 EmptyTerminal(); /* Flush the path to the tty */
909 setcommandmode(); 909 setcommandmode();
910} 910}
911 911
912void 912void
913Exit(int returnCode) 913Exit(int returnCode)
914{ 914{
915 SetForExit(); 915 SetForExit();
916 exit(returnCode); 916 exit(returnCode);
917} 917}
918 918
919void 919void
920ExitString(const char *string, int returnCode) 920ExitString(const char *string, int returnCode)
921{ 921{
922 SetForExit(); 922 SetForExit();
923 fwrite(string, 1, strlen(string), stderr); 923 fwrite(string, 1, strlen(string), stderr);
924 exit(returnCode); 924 exit(returnCode);
925} 925}