Bug Summary

File:src/usr.bin/telnet/telnet.c
Warning:line 622, column 6
Dereference of null pointer (loaded from variable 'next')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name telnet.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.bin/telnet/obj -resource-dir /usr/local/lib/clang/13.0.0 -D KLUDGELINEMODE -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.bin/telnet/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.bin/telnet/telnet.c
1/* $OpenBSD: telnet.c,v 1.36 2019/07/11 03:54:27 deraadt Exp $ */
2/* $NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $ */
3
4/*
5 * Copyright (c) 1988, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include "telnet_locl.h"
34
35#include <arpa/telnet.h>
36#include <ctype.h>
37#include <curses.h>
38#include <stdlib.h>
39#include <unistd.h>
40#include <string.h>
41#include <term.h>
42
43#define strip(x)(eight ? (x) : ((x) & 0x7f)) (eight ? (x) : ((x) & 0x7f))
44
45static unsigned char subbuffer[SUBBUFSIZE256],
46 *subpointer, *subend; /* buffer for sub-options */
47#define SB_CLEAR()subpointer = subbuffer; subpointer = subbuffer;
48#define SB_TERM(){ subend = subpointer; subpointer = subbuffer;; } { subend = subpointer; SB_CLEAR()subpointer = subbuffer;; }
49#define SB_ACCUM(c)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (c); }
if (subpointer < (subbuffer+sizeof subbuffer)) { \
50 *subpointer++ = (c); \
51 }
52
53#define SB_GET()((*subpointer++)&0xff) ((*subpointer++)&0xff)
54#define SB_PEEK()((*subpointer)&0xff) ((*subpointer)&0xff)
55#define SB_EOF()(subpointer >= subend) (subpointer >= subend)
56#define SB_LEN()(subend - subpointer) (subend - subpointer)
57
58static void lm_will(unsigned char *, int);
59static void lm_wont(unsigned char *, int);
60static void lm_do(unsigned char *, int);
61static void lm_dont(unsigned char *, int);
62
63static void slc_init(void);
64static void slc_import(int);
65static void slc_export(void);
66static void slc_start_reply(void);
67static void slc_add_reply(unsigned char, unsigned char, cc_t);
68static void slc_end_reply(void);
69static void slc(unsigned char *, int);
70static int slc_update(void);
71
72static void env_opt(char *, int);
73static void env_opt_start(void);
74
75char options[256]; /* The combined options */
76char do_dont_resp[256];
77char will_wont_resp[256];
78
79int
80 eight = 3,
81 binary = 0,
82 autologin = 0, /* Autologin anyone? */
83 skiprc = 0,
84 connections = 0,
85 connected,
86 showoptions,
87 ISend, /* trying to send network data in */
88 crmod,
89 netdata, /* Print out network data flow */
90 crlf, /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
91 telnetport,
92 SYNCHing, /* we are in TELNET SYNCH mode */
93 flushout, /* flush output */
94 autoflush = 0, /* flush output when interrupting? */
95 autosynch, /* send interrupt characters with SYNCH? */
96 localflow, /* we handle flow control locally */
97 restartany, /* if flow control enabled, restart on any character */
98 localchars, /* we recognize interrupt/quit */
99 donelclchars, /* the user has set "localchars" */
100 donebinarytoggle, /* the user has put us in binary */
101 dontlecho, /* do we suppress local echoing right now? */
102 globalmode,
103 clienteof = 0;
104
105char *prompt = NULL((void *)0);
106
107int scheduler_lockout_tty = 0;
108
109cc_t escape;
110cc_t rlogin;
111#ifdef KLUDGELINEMODE1
112cc_t echoc;
113#endif
114
115/*
116 * Telnet receiver states for fsm
117 */
118#define TS_DATA0 0
119#define TS_IAC1 1
120#define TS_WILL2 2
121#define TS_WONT3 3
122#define TS_DO4 4
123#define TS_DONT5 5
124#define TS_CR6 6
125#define TS_SB7 7 /* sub-option collection */
126#define TS_SE8 8 /* looking for sub-option end */
127
128static int telrcv_state;
129# define telopt_environ39 TELOPT_NEW_ENVIRON39
130
131jmp_buf toplevel = { 0 };
132jmp_buf peerdied;
133
134int flushline;
135int linemode;
136
137#ifdef KLUDGELINEMODE1
138int kludgelinemode = 1;
139#endif
140
141/*
142 * The following are some clocks used to decide how to interpret
143 * the relationship between various variables.
144 */
145
146Clocks clocks;
147
148
149/*
150 * Initialize telnet environment.
151 */
152
153void
154init_telnet(void)
155{
156 env_init();
157
158 SB_CLEAR()subpointer = subbuffer;;
159 memset(options, 0, sizeof options);
160
161 connected = ISend = localflow = donebinarytoggle = 0;
162 restartany = -1;
163
164 SYNCHing = 0;
165
166 escape = CONTROL(']')((']')&0x1f);
167 rlogin = _POSIX_VDISABLE(0377);
168#ifdef KLUDGELINEMODE1
169 echoc = CONTROL('E')(('E')&0x1f);
170#endif
171
172 flushline = 1;
173 telrcv_state = TS_DATA0;
174}
175
176
177/*
178 * These routines are in charge of sending option negotiations
179 * to the other side.
180 *
181 * The basic idea is that we send the negotiation if either side
182 * is in disagreement as to what the current state should be.
183 */
184
185void
186send_do(int c, int init)
187{
188 if (init) {
189 if (((do_dont_resp[c] == 0) && my_state_is_do(c)(options[c]&0x04)) ||
190 my_want_state_is_do(c)(options[c]&0x08))
191 return;
192 set_my_want_state_do(c){options[c] |= 0x08;};
193 do_dont_resp[c]++;
194 }
195 NET2ADD(IAC, DO){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 253; ring_supplied(&netoring, 1); }
; }
;
196 NETADD(c){ *netoring.supply = c; ring_supplied(&netoring, 1); };
197 printoption("SENT",DO253, c);
198}
199
200void
201send_dont(int c, int init)
202{
203 if (init) {
204 if (((do_dont_resp[c] == 0) && my_state_is_dont(c)(!(options[c]&0x04))) ||
205 my_want_state_is_dont(c)(!(options[c]&0x08)))
206 return;
207 set_my_want_state_dont(c){options[c] &= ~0x08;};
208 do_dont_resp[c]++;
209 }
210 NET2ADD(IAC, DONT){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 254; ring_supplied(&netoring, 1); }
; }
;
211 NETADD(c){ *netoring.supply = c; ring_supplied(&netoring, 1); };
212 printoption("SENT", DONT254, c);
213}
214
215void
216send_will(int c, int init)
217{
218 if (init) {
219 if (((will_wont_resp[c] == 0) && my_state_is_will(c)(options[c]&0x01)) ||
220 my_want_state_is_will(c)(options[c]&0x02))
221 return;
222 set_my_want_state_will(c){options[c] |= 0x02;};
223 will_wont_resp[c]++;
224 }
225 NET2ADD(IAC, WILL){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 251; ring_supplied(&netoring, 1); }
; }
;
226 NETADD(c){ *netoring.supply = c; ring_supplied(&netoring, 1); };
227 printoption("SENT", WILL251, c);
228}
229
230void
231send_wont(int c, int init)
232{
233 if (init) {
234 if (((will_wont_resp[c] == 0) && my_state_is_wont(c)(!(options[c]&0x01))) ||
235 my_want_state_is_wont(c)(!(options[c]&0x02)))
236 return;
237 set_my_want_state_wont(c){options[c] &= ~0x02;};
238 will_wont_resp[c]++;
239 }
240 NET2ADD(IAC, WONT){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 252; ring_supplied(&netoring, 1); }
; }
;
241 NETADD(c){ *netoring.supply = c; ring_supplied(&netoring, 1); };
242 printoption("SENT", WONT252, c);
243}
244
245static void
246willoption(int option)
247{
248 int new_state_ok = 0;
249
250 if (do_dont_resp[option]) {
251 --do_dont_resp[option];
252 if (do_dont_resp[option] && my_state_is_do(option)(options[option]&0x04))
253 --do_dont_resp[option];
254 }
255
256 if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)(!(options[option]&0x08))) {
257
258 switch (option) {
259
260 case TELOPT_ECHO1:
261 case TELOPT_BINARY0:
262 case TELOPT_SGA3:
263 settimer(modenegotiated)clocks.modenegotiated = clocks.system++;
264 /* FALL THROUGH */
265 case TELOPT_STATUS5:
266 new_state_ok = 1;
267 break;
268
269 case TELOPT_TM6:
270 if (flushout)
271 flushout = 0;
272 /*
273 * Special case for TM. If we get back a WILL,
274 * pretend we got back a WONT.
275 */
276 set_my_want_state_dont(option){options[option] &= ~0x08;};
277 set_my_state_dont(option){options[option] &= ~0x04;};
278 return; /* Never reply to TM will's/wont's */
279
280 case TELOPT_LINEMODE34:
281 default:
282 break;
283 }
284
285 if (new_state_ok) {
286 set_my_want_state_do(option){options[option] |= 0x08;};
287 send_do(option, 0);
288 setconnmode(0); /* possibly set new tty mode */
289 } else {
290 do_dont_resp[option]++;
291 send_dont(option, 0);
292 }
293 }
294 set_my_state_do(option){options[option] |= 0x04;};
295
296}
297
298static void
299wontoption(int option)
300{
301 if (do_dont_resp[option]) {
302 --do_dont_resp[option];
303 if (do_dont_resp[option] && my_state_is_dont(option)(!(options[option]&0x04)))
304 --do_dont_resp[option];
305 }
306
307 if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)(options[option]&0x08)) {
308
309 switch (option) {
310
311#ifdef KLUDGELINEMODE1
312 case TELOPT_SGA3:
313 if (!kludgelinemode)
314 break;
315 /* FALL THROUGH */
316#endif
317 case TELOPT_ECHO1:
318 settimer(modenegotiated)clocks.modenegotiated = clocks.system++;
319 break;
320
321 case TELOPT_TM6:
322 if (flushout)
323 flushout = 0;
324 set_my_want_state_dont(option){options[option] &= ~0x08;};
325 set_my_state_dont(option){options[option] &= ~0x04;};
326 return; /* Never reply to TM will's/wont's */
327
328 default:
329 break;
330 }
331 set_my_want_state_dont(option){options[option] &= ~0x08;};
332 if (my_state_is_do(option)(options[option]&0x04))
333 send_dont(option, 0);
334 setconnmode(0); /* Set new tty mode */
335 } else if (option == TELOPT_TM6) {
336 /*
337 * Special case for TM.
338 */
339 if (flushout)
340 flushout = 0;
341 set_my_want_state_dont(option){options[option] &= ~0x08;};
342 }
343 set_my_state_dont(option){options[option] &= ~0x04;};
344}
345
346static void
347dooption(int option)
348{
349 int new_state_ok = 0;
350
351 if (will_wont_resp[option]) {
352 --will_wont_resp[option];
353 if (will_wont_resp[option] && my_state_is_will(option)(options[option]&0x01))
354 --will_wont_resp[option];
355 }
356
357 if (will_wont_resp[option] == 0) {
358 if (my_want_state_is_wont(option)(!(options[option]&0x02))) {
359
360 switch (option) {
361
362 case TELOPT_TM6:
363 /*
364 * Special case for TM. We send a WILL, but pretend
365 * we sent WONT.
366 */
367 send_will(option, 0);
368 set_my_want_state_wont(TELOPT_TM){options[6] &= ~0x02;};
369 set_my_state_wont(TELOPT_TM){options[6] &= ~0x01;};
370 return;
371
372 case TELOPT_BINARY0: /* binary mode */
373 case TELOPT_NAWS31: /* window size */
374 case TELOPT_TSPEED32: /* terminal speed */
375 case TELOPT_LFLOW33: /* local flow control */
376 case TELOPT_TTYPE24: /* terminal type option */
377 case TELOPT_SGA3: /* no big deal */
378 new_state_ok = 1;
379 break;
380
381 case TELOPT_NEW_ENVIRON39: /* New environment variable option */
382 new_state_ok = 1;
383 break;
384
385 case TELOPT_XDISPLOC35: /* X Display location */
386 if (env_getvalue("DISPLAY", 0))
387 new_state_ok = 1;
388 break;
389
390 case TELOPT_LINEMODE34:
391#ifdef KLUDGELINEMODE1
392 kludgelinemode = 0;
393 send_do(TELOPT_SGA3, 1);
394#endif
395 set_my_want_state_will(TELOPT_LINEMODE){options[34] |= 0x02;};
396 send_will(option, 0);
397 set_my_state_will(TELOPT_LINEMODE){options[34] |= 0x01;};
398 slc_init();
399 return;
400
401 case TELOPT_ECHO1: /* We're never going to echo... */
402 default:
403 break;
404 }
405
406 if (new_state_ok) {
407 set_my_want_state_will(option){options[option] |= 0x02;};
408 send_will(option, 0);
409 setconnmode(0); /* Set new tty mode */
410 } else {
411 will_wont_resp[option]++;
412 send_wont(option, 0);
413 }
414 } else {
415 /*
416 * Handle options that need more things done after the
417 * other side has acknowledged the option.
418 */
419 switch (option) {
420 case TELOPT_LINEMODE34:
421#ifdef KLUDGELINEMODE1
422 kludgelinemode = 0;
423 send_do(TELOPT_SGA3, 1);
424#endif
425 set_my_state_will(option){options[option] |= 0x01;};
426 slc_init();
427 send_do(TELOPT_SGA3, 0);
428 return;
429 }
430 }
431 }
432 set_my_state_will(option){options[option] |= 0x01;};
433}
434
435static void
436dontoption(int option)
437{
438
439 if (will_wont_resp[option]) {
440 --will_wont_resp[option];
441 if (will_wont_resp[option] && my_state_is_wont(option)(!(options[option]&0x01)))
442 --will_wont_resp[option];
443 }
444
445 if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)(options[option]&0x02)) {
446 switch (option) {
447 case TELOPT_LINEMODE34:
448 linemode = 0; /* put us back to the default state */
449 break;
450 }
451 /* we always accept a DONT */
452 set_my_want_state_wont(option){options[option] &= ~0x02;};
453 if (my_state_is_will(option)(options[option]&0x01))
454 send_wont(option, 0);
455 setconnmode(0); /* Set new tty mode */
456 }
457 set_my_state_wont(option){options[option] &= ~0x01;};
458}
459
460/*
461 * This routine will turn a pipe separated list of names in the buffer
462 * into an array of pointers to NUL terminated names. We toss out any
463 * bad, duplicate, or verbose names (names with spaces).
464 */
465
466int is_unique(char *, char **, char **);
467
468static char *name_unknown = "UNKNOWN";
469static char *unknown[] = { NULL((void *)0), NULL((void *)0) };
470
471char **
472mklist(char *buf, char *name)
473{
474 int n;
475 char c, *cp, **argvp, *cp2, **argv, **avt;
476
477 if (name) {
478 if (strlen(name) > 40) {
479 name = NULL((void *)0);
480 unknown[0] = name_unknown;
481 } else {
482 unknown[0] = name;
483 upcase(name);
484 }
485 } else
486 unknown[0] = name_unknown;
487 /*
488 * Count up the number of names.
489 */
490 for (n = 1, cp = buf; *cp; cp++) {
491 if (*cp == '|')
492 n++;
493 }
494 /*
495 * Allocate an array to put the name pointers into
496 */
497 argv = reallocarray(NULL((void *)0), n+3, sizeof(char *));
498 if (argv == NULL((void *)0))
499 return(unknown);
500
501 /*
502 * Fill up the array of pointers to names.
503 */
504 *argv = NULL((void *)0);
505 argvp = argv+1;
506 n = 0;
507 for (cp = cp2 = buf; (c = *cp); cp++) {
508 if (c == '|' || c == ':') {
509 *cp++ = '\0';
510 /*
511 * Skip entries that have spaces or are over 40
512 * characters long. If this is our environment
513 * name, then put it up front. Otherwise, as
514 * long as this is not a duplicate name (case
515 * insensitive) add it to the list.
516 */
517 if (n || (cp - cp2 > 41))
518 ;
519 else if (name && (strncasecmp(name, cp2, cp-cp2) == 0))
520 *argv = cp2;
521 else if (is_unique(cp2, argv+1, argvp))
522 *argvp++ = cp2;
523 if (c == ':')
524 break;
525 /*
526 * Skip multiple delimiters. Reset cp2 to
527 * the beginning of the next name. Reset n,
528 * the flag for names with spaces.
529 */
530 while ((c = *cp) == '|')
531 cp++;
532 cp2 = cp;
533 n = 0;
534 }
535 /*
536 * Skip entries with spaces or non-ascii values.
537 * Convert lower case letters to upper case.
538 */
539#define ISASCII(c)(!((c)&0x80)) (!((c)&0x80))
540 if ((c == ' ') || !ISASCII(c)(!((c)&0x80)))
541 n = 1;
542 else
543 *cp = toupper((unsigned char)c);
544 }
545
546 /*
547 * Check for an old V6 2 character name. If the second
548 * name points to the beginning of the buffer, and is
549 * only 2 characters long, move it to the end of the array.
550 */
551 if ((argv[1] == buf) && (strlen(argv[1]) == 2)) {
552 --argvp;
553 for (avt = &argv[1]; avt < argvp; avt++)
554 *avt = *(avt+1);
555 *argvp++ = buf;
556 }
557
558 /*
559 * Duplicate last name, for TTYPE option, and null
560 * terminate the array. If we didn't find a match on
561 * our terminal name, put that name at the beginning.
562 */
563 cp = *(argvp-1);
564 *argvp++ = cp;
565 *argvp = NULL((void *)0);
566
567 if (*argv == NULL((void *)0)) {
568 if (name)
569 *argv = name;
570 else {
571 --argvp;
572 for (avt = argv; avt < argvp; avt++)
573 *avt = *(avt+1);
574 }
575 }
576 if (*argv)
577 return(argv);
578 else
579 return(unknown);
580}
581
582int
583is_unique(char *name, char **as, char **ae)
584{
585 char **ap;
586 int n;
587
588 n = strlen(name) + 1;
589 for (ap = as; ap < ae; ap++)
590 if (strncasecmp(*ap, name, n) == 0)
591 return(0);
592 return (1);
593}
594
595int resettermname = 1;
596
597char *
598gettermname(void)
599{
600 char *tname;
601 static char **tnamep = NULL((void *)0);
602 static char **next;
22
'next' initialized to a null pointer value
603 int errret;
604
605 if (resettermname) {
23
Assuming 'resettermname' is 0
24
Taking false branch
606 resettermname = 0;
607 if (tnamep && tnamep != unknown)
608 free(tnamep);
609 if ((tname = env_getvalue("TERM", 0)) &&
610 (setupterm(tname, 1, &errret) == OK(0))) {
611 tnamep = mklist(ttytype, tname);
612 } else {
613 if (tname && (strlen(tname) <= 40)) {
614 unknown[0] = tname;
615 upcase(tname);
616 } else
617 unknown[0] = name_unknown;
618 tnamep = unknown;
619 }
620 next = tnamep;
621 }
622 if (*next == NULL((void *)0))
25
Dereference of null pointer (loaded from variable 'next')
623 next = tnamep;
624 return(*next++);
625}
626
627/*
628 * suboption()
629 *
630 * Look at the sub-option buffer, and try to be helpful to the other
631 * side.
632 *
633 * Currently we recognize:
634 *
635 * Terminal type, send request.
636 * Terminal speed (send request).
637 * Local flow control (is request).
638 * Linemode
639 */
640
641static void
642suboption(void)
643{
644 unsigned char subchar;
645
646 printsub('<', subbuffer, SB_LEN()(subend - subpointer)+2);
647 switch (subchar = SB_GET()((*subpointer++)&0xff)) {
15
Control jumps to 'case 24:' at line 648
648 case TELOPT_TTYPE24:
649 if (my_want_state_is_wont(TELOPT_TTYPE)(!(options[24]&0x02)))
16
Assuming the condition is false
17
Taking false branch
650 return;
651 if (SB_EOF()(subpointer >= subend) || SB_GET()((*subpointer++)&0xff) != TELQUAL_SEND1) {
18
Assuming 'subpointer' is < 'subend'
19
Assuming the condition is false
20
Taking false branch
652 return;
653 } else {
654 char *name;
655 unsigned char temp[50];
656 int len;
657
658 name = gettermname();
21
Calling 'gettermname'
659 len = strlen(name) + 4 + 2;
660 if (len < NETROOM()(ring_empty_count(&netoring))) {
661 snprintf((char *)temp, sizeof(temp),
662 "%c%c%c%c%s%c%c", IAC255, SB250, TELOPT_TTYPE24,
663 TELQUAL_IS0, name, IAC255, SE240);
664 ring_supply_data(&netoring, temp, len);
665 printsub('>', &temp[2], len-2);
666 } else
667 ExitString("No room in buffer for terminal type.\n", 1);
668 }
669 break;
670 case TELOPT_TSPEED32:
671 if (my_want_state_is_wont(TELOPT_TSPEED)(!(options[32]&0x02)))
672 return;
673 if (SB_EOF()(subpointer >= subend))
674 return;
675 if (SB_GET()((*subpointer++)&0xff) == TELQUAL_SEND1) {
676 long ospeed, ispeed;
677 unsigned char temp[50];
678 int len;
679
680 TerminalSpeeds(&ispeed, &ospeed);
681
682 snprintf((char *)temp, sizeof(temp),
683 "%c%c%c%c%ld,%ld%c%c", IAC255, SB250, TELOPT_TSPEED32,
684 TELQUAL_IS0, ospeed, ispeed, IAC255, SE240);
685 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
686
687 if (len < NETROOM()(ring_empty_count(&netoring))) {
688 ring_supply_data(&netoring, temp, len);
689 printsub('>', temp+2, len - 2);
690 }
691/*@*/ else printf("lm_will: not enough room in buffer\n");
692 }
693 break;
694 case TELOPT_LFLOW33:
695 if (my_want_state_is_wont(TELOPT_LFLOW)(!(options[33]&0x02)))
696 return;
697 if (SB_EOF()(subpointer >= subend))
698 return;
699 switch(SB_GET()((*subpointer++)&0xff)) {
700 case LFLOW_RESTART_ANY2:
701 restartany = 1;
702 break;
703 case LFLOW_RESTART_XON3:
704 restartany = 0;
705 break;
706 case LFLOW_ON1:
707 localflow = 1;
708 break;
709 case LFLOW_OFF0:
710 localflow = 0;
711 break;
712 default:
713 return;
714 }
715 setcommandmode();
716 setconnmode(0);
717 break;
718
719 case TELOPT_LINEMODE34:
720 if (my_want_state_is_wont(TELOPT_LINEMODE)(!(options[34]&0x02)))
721 return;
722 if (SB_EOF()(subpointer >= subend))
723 return;
724 switch (SB_GET()((*subpointer++)&0xff)) {
725 case WILL251:
726 lm_will(subpointer, SB_LEN()(subend - subpointer));
727 break;
728 case WONT252:
729 lm_wont(subpointer, SB_LEN()(subend - subpointer));
730 break;
731 case DO253:
732 lm_do(subpointer, SB_LEN()(subend - subpointer));
733 break;
734 case DONT254:
735 lm_dont(subpointer, SB_LEN()(subend - subpointer));
736 break;
737 case LM_SLC3:
738 slc(subpointer, SB_LEN()(subend - subpointer));
739 break;
740 case LM_MODE1:
741 lm_mode(subpointer, SB_LEN()(subend - subpointer), 0);
742 break;
743 default:
744 break;
745 }
746 break;
747
748 case TELOPT_NEW_ENVIRON39:
749 if (SB_EOF()(subpointer >= subend))
750 return;
751 switch(SB_PEEK()((*subpointer)&0xff)) {
752 case TELQUAL_IS0:
753 case TELQUAL_INFO2:
754 if (my_want_state_is_dont(subchar)(!(options[subchar]&0x08)))
755 return;
756 break;
757 case TELQUAL_SEND1:
758 if (my_want_state_is_wont(subchar)(!(options[subchar]&0x02))) {
759 return;
760 }
761 break;
762 default:
763 return;
764 }
765 env_opt(subpointer, SB_LEN()(subend - subpointer));
766 break;
767
768 case TELOPT_XDISPLOC35:
769 if (my_want_state_is_wont(TELOPT_XDISPLOC)(!(options[35]&0x02)))
770 return;
771 if (SB_EOF()(subpointer >= subend))
772 return;
773 if (SB_GET()((*subpointer++)&0xff) == TELQUAL_SEND1) {
774 unsigned char temp[50], *dp;
775 int len;
776
777 if ((dp = env_getvalue("DISPLAY", 0)) == NULL((void *)0)) {
778 /*
779 * Something happened, we no longer have a DISPLAY
780 * variable. So, turn off the option.
781 */
782 send_wont(TELOPT_XDISPLOC35, 1);
783 break;
784 }
785 snprintf((char *)temp, sizeof(temp),
786 "%c%c%c%c%s%c%c", IAC255, SB250, TELOPT_XDISPLOC35,
787 TELQUAL_IS0, dp, IAC255, SE240);
788 len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */
789
790 if (len < NETROOM()(ring_empty_count(&netoring))) {
791 ring_supply_data(&netoring, temp, len);
792 printsub('>', temp+2, len - 2);
793 }
794/*@*/ else printf("lm_will: not enough room in buffer\n");
795 }
796 break;
797
798 default:
799 break;
800 }
801}
802
803static unsigned char str_lm[] = { IAC255, SB250, TELOPT_LINEMODE34, 0, 0, IAC255, SE240 };
804
805static void
806lm_will(unsigned char *cmd, int len)
807{
808 if (len < 1) {
809/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */
810 return;
811 }
812 switch(cmd[0]) {
813 case LM_FORWARDMASK2: /* We shouldn't ever get this... */
814 default:
815 str_lm[3] = DONT254;
816 str_lm[4] = cmd[0];
817 if (NETROOM()(ring_empty_count(&netoring)) > sizeof(str_lm)) {
818 ring_supply_data(&netoring, str_lm, sizeof(str_lm));
819 printsub('>', &str_lm[2], sizeof(str_lm)-2);
820 }
821/*@*/ else printf("lm_will: not enough room in buffer\n");
822 break;
823 }
824}
825
826static void
827lm_wont(unsigned char *cmd, int len)
828{
829 if (len < 1) {
830/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */
831 return;
832 }
833 switch(cmd[0]) {
834 case LM_FORWARDMASK2: /* We shouldn't ever get this... */
835 default:
836 /* We are always DONT, so don't respond */
837 return;
838 }
839}
840
841static void
842lm_do(unsigned char *cmd, int len)
843{
844 if (len < 1) {
845/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
846 return;
847 }
848 switch(cmd[0]) {
849 case LM_FORWARDMASK2:
850 default:
851 str_lm[3] = WONT252;
852 str_lm[4] = cmd[0];
853 if (NETROOM()(ring_empty_count(&netoring)) > sizeof(str_lm)) {
854 ring_supply_data(&netoring, str_lm, sizeof(str_lm));
855 printsub('>', &str_lm[2], sizeof(str_lm)-2);
856 }
857/*@*/ else printf("lm_do: not enough room in buffer\n");
858 break;
859 }
860}
861
862static void
863lm_dont(unsigned char *cmd, int len)
864{
865 if (len < 1) {
866/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */
867 return;
868 }
869 switch(cmd[0]) {
870 case LM_FORWARDMASK2:
871 default:
872 /* we are always WONT, so don't respond */
873 break;
874 }
875}
876
877static unsigned char str_lm_mode[] = {
878 IAC255, SB250, TELOPT_LINEMODE34, LM_MODE1, 0, IAC255, SE240
879};
880
881void
882lm_mode(unsigned char *cmd, int len, int init)
883{
884 if (len != 1)
885 return;
886 if ((linemode&MODE_MASK0x1f&~MODE_ACK0x04) == *cmd)
887 return;
888 if (*cmd&MODE_ACK0x04)
889 return;
890 linemode = *cmd&(MODE_MASK0x1f&~MODE_ACK0x04);
891 str_lm_mode[4] = linemode;
892 if (!init)
893 str_lm_mode[4] |= MODE_ACK0x04;
894 if (NETROOM()(ring_empty_count(&netoring)) > sizeof(str_lm_mode)) {
895 ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode));
896 printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2);
897 }
898/*@*/ else printf("lm_mode: not enough room in buffer\n");
899 setconnmode(0); /* set changed mode */
900}
901
902
903
904/*
905 * slc()
906 * Handle special character suboption of LINEMODE.
907 */
908
909struct spc {
910 cc_t val;
911 cc_t *valp;
912 char flags; /* Current flags & level */
913 char mylevel; /* Maximum level & flags */
914} spc_data[NSLC30+1];
915
916#define SLC_IMPORT0 0
917#define SLC_EXPORT1 1
918#define SLC_RVALUE2 2
919static int slc_mode = SLC_EXPORT1;
920
921static void
922slc_init(void)
923{
924 struct spc *spcp;
925
926 localchars = 1;
927 for (spcp = spc_data; spcp < &spc_data[NSLC30+1]; spcp++) {
928 spcp->val = 0;
929 spcp->valp = NULL((void *)0);
930 spcp->flags = spcp->mylevel = SLC_NOSUPPORT0;
931 }
932
933#define initfunc(func, flags) { \
934 spcp = &spc_data[func]; \
935 if ((spcp->valp = tcval(func))) { \
936 spcp->val = *spcp->valp; \
937 spcp->mylevel = SLC_VARIABLE2|flags; \
938 } else { \
939 spcp->val = 0; \
940 spcp->mylevel = SLC_DEFAULT3; \
941 } \
942 }
943
944 initfunc(SLC_SYNCH1, 0);
945 /* No BRK */
946 initfunc(SLC_AO4, 0);
947 initfunc(SLC_AYT5, 0);
948 /* No EOR */
949 initfunc(SLC_ABORT7, SLC_FLUSHIN0x40|SLC_FLUSHOUT0x20);
950 initfunc(SLC_EOF8, 0);
951 initfunc(SLC_SUSP9, SLC_FLUSHIN0x40);
952 initfunc(SLC_EC10, 0);
953 initfunc(SLC_EL11, 0);
954 initfunc(SLC_EW12, 0);
955 initfunc(SLC_RP13, 0);
956 initfunc(SLC_LNEXT14, 0);
957 initfunc(SLC_XON15, 0);
958 initfunc(SLC_XOFF16, 0);
959 initfunc(SLC_FORW117, 0);
960 initfunc(SLC_FORW218, 0);
961 /* No FORW2 */
962
963 initfunc(SLC_IP3, SLC_FLUSHIN0x40|SLC_FLUSHOUT0x20);
964#undef initfunc
965
966 if (slc_mode == SLC_EXPORT1)
967 slc_export();
968 else
969 slc_import(1);
970
971}
972
973void
974slcstate(void)
975{
976 printf("Special characters are %s values\n",
977 slc_mode == SLC_IMPORT0 ? "remote default" :
978 slc_mode == SLC_EXPORT1 ? "local" :
979 "remote");
980}
981
982void
983slc_mode_export(int unused)
984{
985 slc_mode = SLC_EXPORT1;
986 if (my_state_is_will(TELOPT_LINEMODE)(options[34]&0x01))
987 slc_export();
988}
989
990void
991slc_mode_import(int def)
992{
993 slc_mode = def ? SLC_IMPORT0 : SLC_RVALUE2;
994 if (my_state_is_will(TELOPT_LINEMODE)(options[34]&0x01))
995 slc_import(def);
996}
997
998unsigned char slc_import_val[] = {
999 IAC255, SB250, TELOPT_LINEMODE34, LM_SLC3, 0, SLC_VARIABLE2, 0, IAC255, SE240
1000};
1001unsigned char slc_import_def[] = {
1002 IAC255, SB250, TELOPT_LINEMODE34, LM_SLC3, 0, SLC_DEFAULT3, 0, IAC255, SE240
1003};
1004
1005static void
1006slc_import(int def)
1007{
1008 if (NETROOM()(ring_empty_count(&netoring)) > sizeof(slc_import_val)) {
1009 if (def) {
1010 ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def));
1011 printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2);
1012 } else {
1013 ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val));
1014 printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2);
1015 }
1016 }
1017/*@*/ else printf("slc_import: not enough room\n");
1018}
1019
1020static void
1021slc_export(void)
1022{
1023 struct spc *spcp;
1024
1025 TerminalDefaultChars();
1026
1027 slc_start_reply();
1028 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC30+1]; spcp++) {
1029 if (spcp->mylevel != SLC_NOSUPPORT0) {
1030 if (spcp->val == (cc_t)(_POSIX_VDISABLE(0377)))
1031 spcp->flags = SLC_NOSUPPORT0;
1032 else
1033 spcp->flags = spcp->mylevel;
1034 if (spcp->valp)
1035 spcp->val = *spcp->valp;
1036 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1037 }
1038 }
1039 slc_end_reply();
1040 (void)slc_update();
1041 setconnmode(1); /* Make sure the character values are set */
1042}
1043
1044static void
1045slc(unsigned char *cp, int len)
1046{
1047 struct spc *spcp;
1048 int func,level;
1049
1050 slc_start_reply();
1051
1052 for (; len >= 3; len -=3, cp +=3) {
1053
1054 func = cp[SLC_FUNC0];
1055
1056 if (func == 0) {
1057 /*
1058 * Client side: always ignore 0 function.
1059 */
1060 continue;
1061 }
1062 if (func > NSLC30) {
1063 if ((cp[SLC_FLAGS1] & SLC_LEVELBITS0x03) != SLC_NOSUPPORT0)
1064 slc_add_reply(func, SLC_NOSUPPORT0, 0);
1065 continue;
1066 }
1067
1068 spcp = &spc_data[func];
1069
1070 level = cp[SLC_FLAGS1]&(SLC_LEVELBITS0x03|SLC_ACK0x80);
1071
1072 if ((cp[SLC_VALUE2] == (unsigned char)spcp->val) &&
1073 ((level&SLC_LEVELBITS0x03) == (spcp->flags&SLC_LEVELBITS0x03))) {
1074 continue;
1075 }
1076
1077 if (level == (SLC_DEFAULT3|SLC_ACK0x80)) {
1078 /*
1079 * This is an error condition, the SLC_ACK
1080 * bit should never be set for the SLC_DEFAULT
1081 * level. Our best guess to recover is to
1082 * ignore the SLC_ACK bit.
1083 */
1084 cp[SLC_FLAGS1] &= ~SLC_ACK0x80;
1085 }
1086
1087 if (level == ((spcp->flags&SLC_LEVELBITS0x03)|SLC_ACK0x80)) {
1088 spcp->val = (cc_t)cp[SLC_VALUE2];
1089 spcp->flags = cp[SLC_FLAGS1]; /* include SLC_ACK */
1090 continue;
1091 }
1092
1093 level &= ~SLC_ACK0x80;
1094
1095 if (level <= (spcp->mylevel&SLC_LEVELBITS0x03)) {
1096 spcp->flags = cp[SLC_FLAGS1]|SLC_ACK0x80;
1097 spcp->val = (cc_t)cp[SLC_VALUE2];
1098 }
1099 if (level == SLC_DEFAULT3) {
1100 if ((spcp->mylevel&SLC_LEVELBITS0x03) != SLC_DEFAULT3)
1101 spcp->flags = spcp->mylevel;
1102 else
1103 spcp->flags = SLC_NOSUPPORT0;
1104 }
1105 slc_add_reply(func, spcp->flags, spcp->val);
1106 }
1107 slc_end_reply();
1108 if (slc_update())
1109 setconnmode(1); /* set the new character values */
1110}
1111
1112void
1113slc_check(void)
1114{
1115 struct spc *spcp;
1116
1117 slc_start_reply();
1118 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC30+1]; spcp++) {
1119 if (spcp->valp && spcp->val != *spcp->valp) {
1120 spcp->val = *spcp->valp;
1121 if (spcp->val == (cc_t)(_POSIX_VDISABLE(0377)))
1122 spcp->flags = SLC_NOSUPPORT0;
1123 else
1124 spcp->flags = spcp->mylevel;
1125 slc_add_reply(spcp - spc_data, spcp->flags, spcp->val);
1126 }
1127 }
1128 slc_end_reply();
1129 setconnmode(1);
1130}
1131
1132
1133static unsigned char slc_reply[2 * SUBBUFSIZE256];
1134static unsigned char *slc_replyp;
1135
1136unsigned char
1137slc_add(unsigned char ch)
1138{
1139 if (slc_replyp == slc_reply + sizeof(slc_reply))
1140 return ch;
1141 return *slc_replyp++ = ch;
1142}
1143
1144static void
1145slc_start_reply(void)
1146{
1147 slc_replyp = slc_reply;
1148 slc_add(IAC255);
1149 slc_add(SB250);
1150 slc_add(TELOPT_LINEMODE34);
1151 slc_add(LM_SLC3);
1152}
1153
1154static void
1155slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
1156{
1157 if (slc_replyp + 6 >= slc_reply + sizeof(slc_reply)) {
1158 printf("slc_add_reply: not enough room\n");
1159 return;
1160 }
1161 if (slc_add(func) == IAC255)
1162 slc_add(IAC255);
1163 if (slc_add(flags) == IAC255)
1164 slc_add(IAC255);
1165 if (slc_add((unsigned char)value) == IAC255)
1166 slc_add(IAC255);
1167}
1168
1169static void
1170slc_end_reply(void)
1171{
1172 int len;
1173
1174 if (slc_replyp + 2 >= slc_reply + sizeof(slc_reply)) {
1175 printf("slc_end_reply: not enough room\n");
1176 return;
1177 }
1178
1179 slc_add(IAC255);
1180 slc_add(SE240);
1181 len = slc_replyp - slc_reply;
1182 if (len <= 6)
1183 return;
1184 if (NETROOM()(ring_empty_count(&netoring)) > len) {
1185 ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply);
1186 printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2);
1187 }
1188/*@*/else printf("slc_end_reply: not enough room\n");
1189}
1190
1191static int
1192slc_update(void)
1193{
1194 struct spc *spcp;
1195 int need_update = 0;
1196
1197 for (spcp = &spc_data[1]; spcp < &spc_data[NSLC30+1]; spcp++) {
1198 if (!(spcp->flags&SLC_ACK0x80))
1199 continue;
1200 spcp->flags &= ~SLC_ACK0x80;
1201 if (spcp->valp && (*spcp->valp != spcp->val)) {
1202 *spcp->valp = spcp->val;
1203 need_update = 1;
1204 }
1205 }
1206 return(need_update);
1207}
1208
1209static void
1210env_opt(char *buf, int len)
1211{
1212 char *ep = 0, *epc = 0;
1213 int i;
1214
1215 switch(buf[0]&0xff) {
1216 case TELQUAL_SEND1:
1217 env_opt_start();
1218 if (len == 1) {
1219 env_opt_add(NULL((void *)0));
1220 } else for (i = 1; i < len; i++) {
1221 switch (buf[i]&0xff) {
1222 case NEW_ENV_VAR0:
1223 case ENV_USERVAR3:
1224 if (ep) {
1225 *epc = 0;
1226 env_opt_add(ep);
1227 }
1228 ep = epc = &buf[i+1];
1229 break;
1230 case ENV_ESC2:
1231 i++;
1232 /*FALL THROUGH*/
1233 default:
1234 if (epc)
1235 *epc++ = buf[i];
1236 break;
1237 }
1238 }
1239 if (ep) {
1240 *epc = 0;
1241 env_opt_add(ep);
1242 }
1243 env_opt_end(1);
1244 break;
1245
1246 case TELQUAL_IS0:
1247 case TELQUAL_INFO2:
1248 /* Ignore for now. We shouldn't get it anyway. */
1249 break;
1250
1251 default:
1252 break;
1253 }
1254}
1255
1256#define OPT_REPLY_SIZE(2 * 256) (2 * SUBBUFSIZE256)
1257static unsigned char *opt_reply;
1258static unsigned char *opt_replyp;
1259static unsigned char *opt_replyend;
1260
1261void
1262opt_add(unsigned char ch)
1263{
1264 if (opt_replyp == opt_replyend)
1265 return;
1266 *opt_replyp++ = ch;
1267}
1268
1269static void
1270env_opt_start(void)
1271{
1272 unsigned char *p;
1273
1274 p = realloc(opt_reply, OPT_REPLY_SIZE(2 * 256));
1275 if (p == NULL((void *)0))
1276 free(opt_reply);
1277 opt_reply = p;
1278 if (opt_reply == NULL((void *)0)) {
1279/*@*/ printf("env_opt_start: realloc() failed!!!\n");
1280 opt_reply = opt_replyp = opt_replyend = NULL((void *)0);
1281 return;
1282 }
1283 opt_replyp = opt_reply;
1284 opt_replyend = opt_reply + OPT_REPLY_SIZE(2 * 256);
1285 opt_add(IAC255);
1286 opt_add(SB250);
1287 opt_add(telopt_environ39);
1288 opt_add(TELQUAL_IS0);
1289}
1290
1291void
1292env_opt_start_info(void)
1293{
1294 env_opt_start();
1295 if (opt_replyp)
1296 opt_replyp[-1] = TELQUAL_INFO2;
1297}
1298
1299void
1300env_opt_add(char *ep)
1301{
1302 char *vp, c;
1303
1304 if (opt_reply == NULL((void *)0)) /*XXX*/
1305 return; /*XXX*/
1306
1307 if (ep == NULL((void *)0) || *ep == '\0') {
1308 /* Send user defined variables first. */
1309 env_default(1, 0);
1310 while ((ep = env_default(0, 0)))
1311 env_opt_add(ep);
1312
1313 /* Now add the list of well know variables. */
1314 env_default(1, 1);
1315 while ((ep = env_default(0, 1)))
1316 env_opt_add(ep);
1317 return;
1318 }
1319 vp = env_getvalue(ep, 1);
1320 if (2 * (vp ? strlen(vp) : 0) + 2 * strlen(ep) + 6 >
1321 opt_replyend - opt_replyp)
1322 {
1323 size_t len;
1324 unsigned char *p;
1325
1326 len = opt_replyend - opt_reply;
1327 len += OPT_REPLY_SIZE(2 * 256) + 2 * strlen(ep);
1328 if (vp)
1329 len += 2 * strlen(vp);
1330 p = realloc(opt_reply, len);
1331 if (p == NULL((void *)0)) {
1332 free(opt_reply);
1333/*@*/ printf("env_opt_add: realloc() failed!!!\n");
1334 opt_reply = opt_replyp = opt_replyend = NULL((void *)0);
1335 return;
1336 }
1337 opt_replyp = p + (opt_replyp - opt_reply);
1338 opt_replyend = p + len;
1339 opt_reply = p;
1340 }
1341 if (opt_welldefined(ep))
1342 opt_add(NEW_ENV_VAR0);
1343 else
1344 opt_add(ENV_USERVAR3);
1345
1346 for (;;) {
1347 while ((c = *ep++)) {
1348 switch(c&0xff) {
1349 case IAC255:
1350 opt_add(IAC255);
1351 break;
1352 case NEW_ENV_VAR0:
1353 case NEW_ENV_VALUE1:
1354 case ENV_ESC2:
1355 case ENV_USERVAR3:
1356 opt_add(ENV_ESC2);
1357 break;
1358 }
1359 opt_add(c);
1360 }
1361 if ((ep = vp)) {
1362 opt_add(NEW_ENV_VALUE1);
1363 vp = NULL((void *)0);
1364 } else
1365 break;
1366 }
1367}
1368
1369int
1370opt_welldefined(const char *ep)
1371{
1372 if ((strcmp(ep, "USER") == 0) ||
1373 (strcmp(ep, "DISPLAY") == 0) ||
1374 (strcmp(ep, "PRINTER") == 0) ||
1375 (strcmp(ep, "SYSTEMTYPE") == 0) ||
1376 (strcmp(ep, "JOB") == 0) ||
1377 (strcmp(ep, "ACCT") == 0))
1378 return(1);
1379 return(0);
1380}
1381
1382void
1383env_opt_end(int emptyok)
1384{
1385 int len;
1386
1387 len = opt_replyp - opt_reply + 2;
1388 if (emptyok || len > 6) {
1389 opt_add(IAC255);
1390 opt_add(SE240);
1391 if (NETROOM()(ring_empty_count(&netoring)) > len) {
1392 ring_supply_data(&netoring, opt_reply, len);
1393 printsub('>', &opt_reply[2], len - 2);
1394 }
1395/*@*/ else printf("slc_end_reply: not enough room\n");
1396 }
1397 if (opt_reply) {
1398 free(opt_reply);
1399 opt_reply = opt_replyp = opt_replyend = NULL((void *)0);
1400 }
1401}
1402
1403
1404
1405int
1406telrcv(void)
1407{
1408 int c;
1409 int scc;
1410 unsigned char *sbp;
1411 int count;
1412 int returnValue = 0;
1413
1414 scc = 0;
1415 count = 0;
1416 while (TTYROOM()(ring_empty_count(&ttyoring)) > 2) {
1
Assuming the condition is true
2
Loop condition is true. Entering loop body
1417 if (scc
2.1
'scc' is equal to 0
== 0) {
3
Taking true branch
1418 if (count
3.1
'count' is 0
) {
4
Taking false branch
1419 ring_consumed(&netiring, count);
1420 returnValue = 1;
1421 count = 0;
1422 }
1423 sbp = netiring.consume;
1424 scc = ring_full_consecutive(&netiring);
1425 if (scc == 0) {
5
Assuming 'scc' is not equal to 0
6
Taking false branch
1426 /* No more data coming in */
1427 break;
1428 }
1429 }
1430
1431 c = *sbp++ & 0xff, scc--; count++;
1432
1433 switch (telrcv_state) {
7
Control jumps to 'case 8:' at line 1578
1434
1435 case TS_CR6:
1436 telrcv_state = TS_DATA0;
1437 if (c == '\0') {
1438 break; /* Ignore \0 after CR */
1439 }
1440 else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO)(!(options[1]&0x08)) && !crmod) {
1441 TTYADD(c)if (!(SYNCHing||flushout)) { *ttyoring.supply = c; ring_supplied
(&ttyoring, 1); }
;
1442 break;
1443 }
1444 /* Else, fall through */
1445
1446 case TS_DATA0:
1447 if (c == IAC255) {
1448 telrcv_state = TS_IAC1;
1449 break;
1450 }
1451 /*
1452 * The 'crmod' hack (see following) is needed
1453 * since we can't set CRMOD on output only.
1454 * Machines like MULTICS like to send \r without
1455 * \n; since we must turn off CRMOD to get proper
1456 * input, the mapping is done here (sigh).
1457 */
1458 if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)(!(options[0]&0x08))) {
1459 if (scc > 0) {
1460 c = *sbp&0xff;
1461 if (c == 0) {
1462 sbp++, scc--; count++;
1463 /* a "true" CR */
1464 TTYADD('\r')if (!(SYNCHing||flushout)) { *ttyoring.supply = '\r'; ring_supplied
(&ttyoring, 1); }
;
1465 } else if (my_want_state_is_dont(TELOPT_ECHO)(!(options[1]&0x08)) &&
1466 (c == '\n')) {
1467 sbp++, scc--; count++;
1468 TTYADD('\n')if (!(SYNCHing||flushout)) { *ttyoring.supply = '\n'; ring_supplied
(&ttyoring, 1); }
;
1469 } else {
1470 TTYADD('\r')if (!(SYNCHing||flushout)) { *ttyoring.supply = '\r'; ring_supplied
(&ttyoring, 1); }
;
1471 if (crmod) {
1472 TTYADD('\n')if (!(SYNCHing||flushout)) { *ttyoring.supply = '\n'; ring_supplied
(&ttyoring, 1); }
;
1473 }
1474 }
1475 } else {
1476 telrcv_state = TS_CR6;
1477 TTYADD('\r')if (!(SYNCHing||flushout)) { *ttyoring.supply = '\r'; ring_supplied
(&ttyoring, 1); }
;
1478 if (crmod) {
1479 TTYADD('\n')if (!(SYNCHing||flushout)) { *ttyoring.supply = '\n'; ring_supplied
(&ttyoring, 1); }
;
1480 }
1481 }
1482 } else {
1483 TTYADD(c)if (!(SYNCHing||flushout)) { *ttyoring.supply = c; ring_supplied
(&ttyoring, 1); }
;
1484 }
1485 continue;
1486
1487 case TS_IAC1:
1488process_iac:
1489 switch (c) {
1490
1491 case WILL251:
1492 telrcv_state = TS_WILL2;
1493 continue;
1494
1495 case WONT252:
1496 telrcv_state = TS_WONT3;
1497 continue;
1498
1499 case DO253:
1500 telrcv_state = TS_DO4;
1501 continue;
1502
1503 case DONT254:
1504 telrcv_state = TS_DONT5;
1505 continue;
1506
1507 case DM242:
1508 /*
1509 * We may have missed an urgent notification,
1510 * so make sure we flush whatever is in the
1511 * buffer currently.
1512 */
1513 printoption("RCVD", IAC255, DM242);
1514 SYNCHing = 1;
1515 (void) ttyflush(1);
1516 SYNCHing = stilloob();
1517 break;
1518
1519 case SB250:
1520 SB_CLEAR()subpointer = subbuffer;;
1521 telrcv_state = TS_SB7;
1522 continue;
1523
1524 case IAC255:
1525 TTYADD(IAC)if (!(SYNCHing||flushout)) { *ttyoring.supply = 255; ring_supplied
(&ttyoring, 1); }
;
1526 break;
1527
1528 case NOP241:
1529 case GA249:
1530 default:
1531 printoption("RCVD", IAC255, c);
1532 break;
1533 }
1534 telrcv_state = TS_DATA0;
1535 continue;
1536
1537 case TS_WILL2:
1538 printoption("RCVD", WILL251, c);
1539 willoption(c);
1540 telrcv_state = TS_DATA0;
1541 continue;
1542
1543 case TS_WONT3:
1544 printoption("RCVD", WONT252, c);
1545 wontoption(c);
1546 telrcv_state = TS_DATA0;
1547 continue;
1548
1549 case TS_DO4:
1550 printoption("RCVD", DO253, c);
1551 dooption(c);
1552 if (c == TELOPT_NAWS31) {
1553 sendnaws();
1554 } else if (c == TELOPT_LFLOW33) {
1555 localflow = 1;
1556 setcommandmode();
1557 setconnmode(0);
1558 }
1559 telrcv_state = TS_DATA0;
1560 continue;
1561
1562 case TS_DONT5:
1563 printoption("RCVD", DONT254, c);
1564 dontoption(c);
1565 flushline = 1;
1566 setconnmode(0); /* set new tty mode (maybe) */
1567 telrcv_state = TS_DATA0;
1568 continue;
1569
1570 case TS_SB7:
1571 if (c == IAC255) {
1572 telrcv_state = TS_SE8;
1573 } else {
1574 SB_ACCUM(c)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (c); }
;
1575 }
1576 continue;
1577
1578 case TS_SE8:
1579 if (c != SE240) {
8
Assuming 'c' is equal to SE
9
Taking false branch
1580 if (c != IAC255) {
1581 /*
1582 * This is an error. We only expect to get
1583 * "IAC IAC" or "IAC SE". Several things may
1584 * have happened. An IAC was not doubled, the
1585 * IAC SE was left off, or another option got
1586 * inserted into the suboption are all possibilities.
1587 * If we assume that the IAC was not doubled,
1588 * and really the IAC SE was left off, we could
1589 * get into an infinite loop here. So, instead,
1590 * we terminate the suboption, and process the
1591 * partial suboption if we can.
1592 */
1593 SB_ACCUM(IAC)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (255); }
;
1594 SB_ACCUM(c)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (c); }
;
1595 subpointer -= 2;
1596 SB_TERM(){ subend = subpointer; subpointer = subbuffer;; };
1597
1598 printoption("In SUBOPTION processing, RCVD", IAC255, c);
1599 suboption(); /* handle sub-option */
1600 telrcv_state = TS_IAC1;
1601 goto process_iac;
1602 }
1603 SB_ACCUM(c)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (c); }
;
1604 telrcv_state = TS_SB7;
1605 } else {
1606 SB_ACCUM(IAC)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (255); }
;
10
Assuming the condition is false
11
Taking false branch
1607 SB_ACCUM(SE)if (subpointer < (subbuffer+sizeof subbuffer)) { *subpointer
++ = (240); }
;
12
Assuming the condition is false
13
Taking false branch
1608 subpointer -= 2;
1609 SB_TERM(){ subend = subpointer; subpointer = subbuffer;; };
1610 suboption(); /* handle sub-option */
14
Calling 'suboption'
1611 telrcv_state = TS_DATA0;
1612 }
1613 }
1614 }
1615 if (count)
1616 ring_consumed(&netiring, count);
1617 return returnValue||count;
1618}
1619
1620static int bol = 1, local = 0;
1621
1622int
1623rlogin_susp(void)
1624{
1625 if (local) {
1626 local = 0;
1627 bol = 1;
1628 command(0, "z\n", 2);
1629 return(1);
1630 }
1631 return(0);
1632}
1633
1634static int
1635telsnd(void)
1636{
1637 int tcc;
1638 int count;
1639 int returnValue = 0;
1640 unsigned char *tbp;
1641
1642 tcc = 0;
1643 count = 0;
1644 while (NETROOM()(ring_empty_count(&netoring)) > 2) {
1645 int sc;
1646 int c;
1647
1648 if (tcc == 0) {
1649 if (count) {
1650 ring_consumed(&ttyiring, count);
1651 returnValue = 1;
1652 count = 0;
1653 }
1654 tbp = ttyiring.consume;
1655 tcc = ring_full_consecutive(&ttyiring);
1656 if (tcc == 0) {
1657 break;
1658 }
1659 }
1660 c = *tbp++ & 0xff, sc = strip(c)(eight ? (c) : ((c) & 0x7f)), tcc--; count++;
1661 if (rlogin != _POSIX_VDISABLE(0377)) {
1662 if (bol) {
1663 bol = 0;
1664 if (sc == rlogin) {
1665 local = 1;
1666 continue;
1667 }
1668 } else if (local) {
1669 local = 0;
1670 if (sc == '.' || c == termEofCharnew_tc.c_cc[0]) {
1671 bol = 1;
1672 command(0, "close\n", 6);
1673 continue;
1674 }
1675 if (sc == termSuspCharnew_tc.c_cc[10]) {
1676 bol = 1;
1677 command(0, "z\n", 2);
1678 continue;
1679 }
1680 if (sc == escape) {
1681 command(0, (char *)tbp, tcc);
1682 bol = 1;
1683 count += tcc;
1684 tcc = 0;
1685 flushline = 1;
1686 break;
1687 }
1688 if (sc != rlogin) {
1689 ++tcc;
1690 --tbp;
1691 --count;
1692 c = sc = rlogin;
1693 }
1694 }
1695 if ((sc == '\n') || (sc == '\r'))
1696 bol = 1;
1697 } else if (escape != _POSIX_VDISABLE(0377) && sc == escape) {
1698 /*
1699 * Double escape is a pass through of a single escape character.
1700 */
1701 if (tcc && strip(*tbp)(eight ? (*tbp) : ((*tbp) & 0x7f)) == escape) {
1702 tbp++;
1703 tcc--;
1704 count++;
1705 bol = 0;
1706 } else {
1707 command(0, (char *)tbp, tcc);
1708 bol = 1;
1709 count += tcc;
1710 tcc = 0;
1711 flushline = 1;
1712 break;
1713 }
1714 } else
1715 bol = 0;
1716#ifdef KLUDGELINEMODE1
1717 if (kludgelinemode && (globalmode&MODE_EDIT0x01) && (sc == echoc)) {
1718 if (tcc > 0 && strip(*tbp)(eight ? (*tbp) : ((*tbp) & 0x7f)) == echoc) {
1719 tcc--; tbp++; count++;
1720 } else {
1721 dontlecho = !dontlecho;
1722 settimer(echotoggle)clocks.echotoggle = clocks.system++;
1723 setconnmode(0);
1724 flushline = 1;
1725 break;
1726 }
1727 }
1728#endif
1729 if (sc != _POSIX_VDISABLE(0377) && MODE_LOCAL_CHARS(globalmode)((globalmode)&(0x01|0x02))) {
1730 if (TerminalSpecialChars(sc) == 0) {
1731 bol = 1;
1732 break;
1733 }
1734 }
1735 if (my_want_state_is_wont(TELOPT_BINARY)(!(options[0]&0x02))) {
1736 switch (c) {
1737 case '\n':
1738 /*
1739 * If we are in CRMOD mode (\r ==> \n)
1740 * on our local machine, then probably
1741 * a newline (unix) is CRLF (TELNET).
1742 */
1743 if (MODE_LOCAL_CHARS(globalmode)((globalmode)&(0x01|0x02))) {
1744 NETADD('\r'){ *netoring.supply = '\r'; ring_supplied(&netoring, 1); };
1745 }
1746 NETADD('\n'){ *netoring.supply = '\n'; ring_supplied(&netoring, 1); };
1747 bol = flushline = 1;
1748 break;
1749 case '\r':
1750 if (!crlf) {
1751 NET2ADD('\r', '\0'){ { *netoring.supply = '\r'; ring_supplied(&netoring, 1);
}; { *netoring.supply = '\0'; ring_supplied(&netoring, 1
); }; }
;
1752 } else {
1753 NET2ADD('\r', '\n'){ { *netoring.supply = '\r'; ring_supplied(&netoring, 1);
}; { *netoring.supply = '\n'; ring_supplied(&netoring, 1
); }; }
;
1754 }
1755 bol = flushline = 1;
1756 break;
1757 case IAC255:
1758 NET2ADD(IAC, IAC){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; }
;
1759 break;
1760 default:
1761 NETADD(c){ *netoring.supply = c; ring_supplied(&netoring, 1); };
1762 break;
1763 }
1764 } else if (c == IAC255) {
1765 NET2ADD(IAC, IAC){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; }
;
1766 } else {
1767 NETADD(c){ *netoring.supply = c; ring_supplied(&netoring, 1); };
1768 }
1769 }
1770 if (count)
1771 ring_consumed(&ttyiring, count);
1772 return returnValue||count; /* Non-zero if we did anything */
1773}
1774
1775/*
1776 * Scheduler()
1777 *
1778 * Try to do something.
1779 *
1780 * If we do something useful, return 1; else return 0.
1781 *
1782 */
1783
1784int
1785Scheduler(int block) /* should we block in the select ? */
1786{
1787 /* One wants to be a bit careful about setting returnValue
1788 * to one, since a one implies we did some useful work,
1789 * and therefore probably won't be called to block next
1790 * time (TN3270 mode only).
1791 */
1792 int returnValue;
1793 int netin, netout, netex, ttyin, ttyout;
1794
1795 /* Decide which rings should be processed */
1796
1797 netout = ring_full_count(&netoring) &&
1798 (flushline ||
1799 (my_want_state_is_wont(TELOPT_LINEMODE)(!(options[34]&0x02))
1800#ifdef KLUDGELINEMODE1
1801 && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)(options[3]&0x08))
1802#endif
1803 ) ||
1804 my_want_state_is_will(TELOPT_BINARY)(options[0]&0x02));
1805 ttyout = ring_full_count(&ttyoring);
1806
1807 ttyin = ring_empty_count(&ttyiring) && (clienteof == 0);
1808
1809 netin = !ISend && ring_empty_count(&netiring);
1810
1811 netex = !SYNCHing;
1812
1813 /* If we have seen a signal recently, reset things */
1814
1815 if (scheduler_lockout_tty) {
1816 ttyin = ttyout = 0;
1817 }
1818
1819 /* Call to system code to process rings */
1820
1821 returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block);
1822
1823 /* Now, look at the input rings, looking for work to do. */
1824
1825 if (ring_full_count(&ttyiring)) {
1826 returnValue |= telsnd();
1827 }
1828
1829 if (ring_full_count(&netiring)) {
1830 returnValue |= telrcv();
1831 }
1832 return returnValue;
1833}
1834
1835/*
1836 * Select from tty and network...
1837 */
1838void
1839telnet(char *user)
1840{
1841 connections++;
1842 sys_telnet_init();
1843
1844 if (pledge("stdio rpath tty", NULL((void *)0)) == -1) {
1845 perror("pledge");
1846 exit(1);
1847 }
1848
1849 if (telnetport) {
1850 send_do(TELOPT_SGA3, 1);
1851 send_will(TELOPT_TTYPE24, 1);
1852 send_will(TELOPT_NAWS31, 1);
1853 send_will(TELOPT_TSPEED32, 1);
1854 send_will(TELOPT_LFLOW33, 1);
1855 send_will(TELOPT_LINEMODE34, 1);
1856 send_will(TELOPT_NEW_ENVIRON39, 1);
1857 send_do(TELOPT_STATUS5, 1);
1858 if (env_getvalue("DISPLAY", 0))
1859 send_will(TELOPT_XDISPLOC35, 1);
1860 if (binary)
1861 tel_enter_binary(binary);
1862 }
1863
1864 for (;;) {
1865 int schedValue;
1866
1867 while ((schedValue = Scheduler(0)) != 0) {
1868 if (schedValue == -1) {
1869 setcommandmode();
1870 return;
1871 }
1872 }
1873
1874 if (Scheduler(1) == -1) {
1875 setcommandmode();
1876 return;
1877 }
1878 }
1879}
1880
1881#if 0 /* XXX - this not being in is a bug */
1882/*
1883 * nextitem()
1884 *
1885 * Return the address of the next "item" in the TELNET data
1886 * stream. This will be the address of the next character if
1887 * the current address is a user data character, or it will
1888 * be the address of the character following the TELNET command
1889 * if the current address is a TELNET IAC ("I Am a Command")
1890 * character.
1891 */
1892
1893static char *
1894nextitem(char *current)
1895{
1896 if ((*current&0xff) != IAC255) {
1897 return current+1;
1898 }
1899 switch (*(current+1)&0xff) {
1900 case DO253:
1901 case DONT254:
1902 case WILL251:
1903 case WONT252:
1904 return current+3;
1905 case SB250: /* loop forever looking for the SE */
1906 {
1907 char *look = current+2;
1908
1909 for (;;) {
1910 if ((*look++&0xff) == IAC255) {
1911 if ((*look++&0xff) == SE240) {
1912 return look;
1913 }
1914 }
1915 }
1916 }
1917 default:
1918 return current+2;
1919 }
1920}
1921#endif /* 0 */
1922
1923/*
1924 * netclear()
1925 *
1926 * We are about to do a TELNET SYNCH operation. Clear
1927 * the path to the network.
1928 *
1929 * Things are a bit tricky since we may have sent the first
1930 * byte or so of a previous TELNET command into the network.
1931 * So, we have to scan the network buffer from the beginning
1932 * until we are up to where we want to be.
1933 *
1934 * A side effect of what we do, just to keep things
1935 * simple, is to clear the urgent data pointer. The principal
1936 * caller should be setting the urgent data pointer AFTER calling
1937 * us in any case.
1938 */
1939
1940static void
1941netclear(void)
1942{
1943#if 0 /* XXX */
1944 char *thisitem, *next;
1945 char *good;
1946#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC255) && \
1947 ((*(p+1)&0xff) != EC247) && ((*(p+1)&0xff) != EL248))
1948
1949 thisitem = netobuf;
1950
1951 while ((next = nextitem(thisitem)) <= netobuf.send) {
1952 thisitem = next;
1953 }
1954
1955 /* Now, thisitem is first before/at boundary. */
1956
1957 good = netobuf; /* where the good bytes go */
1958
1959 while (netoring.add > thisitem) {
1960 if (wewant(thisitem)) {
1961 int length;
1962
1963 next = thisitem;
1964 do {
1965 next = nextitem(next);
1966 } while (wewant(next) && (nfrontp > next));
1967 length = next-thisitem;
1968 memmove(good, thisitem, length);
1969 good += length;
1970 thisitem = next;
1971 } else {
1972 thisitem = nextitem(thisitem);
1973 }
1974 }
1975
1976#endif /* 0 */
1977}
1978
1979/*
1980 * These routines add various telnet commands to the data stream.
1981 */
1982
1983static void
1984doflush(void)
1985{
1986 NET2ADD(IAC, DO){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 253; ring_supplied(&netoring, 1); }
; }
;
1987 NETADD(TELOPT_TM){ *netoring.supply = 6; ring_supplied(&netoring, 1); };
1988 flushline = 1;
1989 flushout = 1;
1990 (void) ttyflush(1); /* Flush/drop output */
1991 /* do printoption AFTER flush, otherwise the output gets tossed... */
1992 printoption("SENT", DO253, TELOPT_TM6);
1993}
1994
1995void
1996xmitAO(void)
1997{
1998 NET2ADD(IAC, AO){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 245; ring_supplied(&netoring, 1); }
; }
;
1999 printoption("SENT", IAC255, AO245);
2000 if (autoflush) {
2001 doflush();
2002 }
2003}
2004
2005
2006void
2007xmitEL(void)
2008{
2009 NET2ADD(IAC, EL){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 248; ring_supplied(&netoring, 1); }
; }
;
2010 printoption("SENT", IAC255, EL248);
2011}
2012
2013void
2014xmitEC(void)
2015{
2016 NET2ADD(IAC, EC){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 247; ring_supplied(&netoring, 1); }
; }
;
2017 printoption("SENT", IAC255, EC247);
2018}
2019
2020
2021int
2022dosynch(void)
2023{
2024 netclear(); /* clear the path to the network */
2025 NETADD(IAC){ *netoring.supply = 255; ring_supplied(&netoring, 1); };
2026 setneturg();
2027 NETADD(DM){ *netoring.supply = 242; ring_supplied(&netoring, 1); };
2028 printoption("SENT", IAC255, DM242);
2029 return 1;
2030}
2031
2032int want_status_response = 0;
2033
2034int
2035get_status(void)
2036{
2037 unsigned char tmp[16];
2038 unsigned char *cp;
2039
2040 if (my_want_state_is_dont(TELOPT_STATUS)(!(options[5]&0x08))) {
2041 printf("Remote side does not support STATUS option\n");
2042 return 0;
2043 }
2044 cp = tmp;
2045
2046 *cp++ = IAC255;
2047 *cp++ = SB250;
2048 *cp++ = TELOPT_STATUS5;
2049 *cp++ = TELQUAL_SEND1;
2050 *cp++ = IAC255;
2051 *cp++ = SE240;
2052 if (NETROOM()(ring_empty_count(&netoring)) >= cp - tmp) {
2053 ring_supply_data(&netoring, tmp, cp-tmp);
2054 printsub('>', tmp+2, cp - tmp - 2);
2055 }
2056 ++want_status_response;
2057 return 1;
2058}
2059
2060void
2061intp(void)
2062{
2063 NET2ADD(IAC, IP){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 244; ring_supplied(&netoring, 1); }
; }
;
2064 printoption("SENT", IAC255, IP244);
2065 flushline = 1;
2066 if (autoflush) {
2067 doflush();
2068 }
2069 if (autosynch) {
2070 dosynch();
2071 }
2072}
2073
2074void
2075sendbrk(void)
2076{
2077 NET2ADD(IAC, BREAK){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 243; ring_supplied(&netoring, 1); }
; }
;
2078 printoption("SENT", IAC255, BREAK243);
2079 flushline = 1;
2080 if (autoflush) {
2081 doflush();
2082 }
2083 if (autosynch) {
2084 dosynch();
2085 }
2086}
2087
2088void
2089sendabort(void)
2090{
2091 NET2ADD(IAC, ABORT){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 238; ring_supplied(&netoring, 1); }
; }
;
2092 printoption("SENT", IAC255, ABORT238);
2093 flushline = 1;
2094 if (autoflush) {
2095 doflush();
2096 }
2097 if (autosynch) {
2098 dosynch();
2099 }
2100}
2101
2102void
2103sendsusp(void)
2104{
2105 NET2ADD(IAC, SUSP){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 237; ring_supplied(&netoring, 1); }
; }
;
2106 printoption("SENT", IAC255, SUSP237);
2107 flushline = 1;
2108 if (autoflush) {
2109 doflush();
2110 }
2111 if (autosynch) {
2112 dosynch();
2113 }
2114}
2115
2116void
2117sendeof(void)
2118{
2119 NET2ADD(IAC, xEOF){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 236; ring_supplied(&netoring, 1); }
; }
;
2120 printoption("SENT", IAC255, xEOF236);
2121}
2122
2123void
2124sendayt(void)
2125{
2126 NET2ADD(IAC, AYT){ { *netoring.supply = 255; ring_supplied(&netoring, 1); }
; { *netoring.supply = 246; ring_supplied(&netoring, 1); }
; }
;
2127 printoption("SENT", IAC255, AYT246);
2128}
2129
2130/*
2131 * Send a window size update to the remote system.
2132 */
2133
2134void
2135sendnaws(void)
2136{
2137 long rows, cols;
2138 unsigned char tmp[16];
2139 unsigned char *cp;
2140
2141 if (my_state_is_wont(TELOPT_NAWS)(!(options[31]&0x01)))
2142 return;
2143
2144#define PUTSHORT(cp, x){ if ((*cp++ = ((x)>>8)&0xff) == 255) *cp++ = 255; if
((*cp++ = ((x))&0xff) == 255) *cp++ = 255; }
{ if ((*cp++ = ((x)>>8)&0xff) == IAC255) *cp++ = IAC255; \
2145 if ((*cp++ = ((x))&0xff) == IAC255) *cp++ = IAC255; }
2146
2147 if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */
2148 return;
2149 }
2150
2151 cp = tmp;
2152
2153 *cp++ = IAC255;
2154 *cp++ = SB250;
2155 *cp++ = TELOPT_NAWS31;
2156 PUTSHORT(cp, cols){ if ((*cp++ = ((cols)>>8)&0xff) == 255) *cp++ = 255
; if ((*cp++ = ((cols))&0xff) == 255) *cp++ = 255; }
;
2157 PUTSHORT(cp, rows){ if ((*cp++ = ((rows)>>8)&0xff) == 255) *cp++ = 255
; if ((*cp++ = ((rows))&0xff) == 255) *cp++ = 255; }
;
2158 *cp++ = IAC255;
2159 *cp++ = SE240;
2160 if (NETROOM()(ring_empty_count(&netoring)) >= cp - tmp) {
2161 ring_supply_data(&netoring, tmp, cp-tmp);
2162 printsub('>', tmp+2, cp - tmp - 2);
2163 }
2164}
2165
2166void
2167tel_enter_binary(int rw)
2168{
2169 if (rw&1)
2170 send_do(TELOPT_BINARY0, 1);
2171 if (rw&2)
2172 send_will(TELOPT_BINARY0, 1);
2173}
2174
2175void
2176tel_leave_binary(int rw)
2177{
2178 if (rw&1)
2179 send_dont(TELOPT_BINARY0, 1);
2180 if (rw&2)
2181 send_wont(TELOPT_BINARY0, 1);
2182}