GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/telnet/telnet.c Lines: 0 881 0.0 %
Date: 2016-12-06 Branches: 0 708 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: telnet.c,v 1.35 2016/01/26 18:35:01 mmcc 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))
44
45
static unsigned char	subbuffer[SUBBUFSIZE],
46
			*subpointer, *subend;	 /* buffer for sub-options */
47
#define	SB_CLEAR()	subpointer = subbuffer;
48
#define	SB_TERM()	{ subend = subpointer; SB_CLEAR(); }
49
#define	SB_ACCUM(c)	if (subpointer < (subbuffer+sizeof subbuffer)) { \
50
				*subpointer++ = (c); \
51
			}
52
53
#define	SB_GET()	((*subpointer++)&0xff)
54
#define	SB_PEEK()	((*subpointer)&0xff)
55
#define	SB_EOF()	(subpointer >= subend)
56
#define	SB_LEN()	(subend - subpointer)
57
58
static void	lm_will(unsigned char *, int);
59
static void	lm_wont(unsigned char *, int);
60
static void	lm_do(unsigned char *, int);
61
static void	lm_dont(unsigned char *, int);
62
63
static void	slc_init(void);
64
static void	slc_import(int);
65
static void	slc_export(void);
66
static void	slc_start_reply(void);
67
static void	slc_add_reply(unsigned char, unsigned char, cc_t);
68
static void	slc_end_reply(void);
69
static void	slc(unsigned char *, int);
70
static int	slc_update(void);
71
72
static void	env_opt(char *, int);
73
static void	env_opt_start(void);
74
75
char	options[256];		/* The combined options */
76
char	do_dont_resp[256];
77
char	will_wont_resp[256];
78
79
int
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
105
char *prompt = NULL;
106
107
int scheduler_lockout_tty = 0;
108
109
cc_t escape;
110
cc_t rlogin;
111
#ifdef	KLUDGELINEMODE
112
cc_t echoc;
113
#endif
114
115
/*
116
 * Telnet receiver states for fsm
117
 */
118
#define	TS_DATA		0
119
#define	TS_IAC		1
120
#define	TS_WILL		2
121
#define	TS_WONT		3
122
#define	TS_DO		4
123
#define	TS_DONT		5
124
#define	TS_CR		6
125
#define	TS_SB		7		/* sub-option collection */
126
#define	TS_SE		8		/* looking for sub-option end */
127
128
static int	telrcv_state;
129
# define telopt_environ TELOPT_NEW_ENVIRON
130
131
jmp_buf	toplevel = { 0 };
132
jmp_buf	peerdied;
133
134
int	flushline;
135
int	linemode;
136
137
#ifdef	KLUDGELINEMODE
138
int	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
146
Clocks clocks;
147
148
149
/*
150
 * Initialize telnet environment.
151
 */
152
153
void
154
init_telnet(void)
155
{
156
    env_init();
157
158
    SB_CLEAR();
159
    memset(options, 0, sizeof options);
160
161
    connected = ISend = localflow = donebinarytoggle = 0;
162
    restartany = -1;
163
164
    SYNCHing = 0;
165
166
    escape = CONTROL(']');
167
    rlogin = _POSIX_VDISABLE;
168
#ifdef	KLUDGELINEMODE
169
    echoc = CONTROL('E');
170
#endif
171
172
    flushline = 1;
173
    telrcv_state = TS_DATA;
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
185
void
186
send_do(int c, int init)
187
{
188
    if (init) {
189
	if (((do_dont_resp[c] == 0) && my_state_is_do(c)) ||
190
				my_want_state_is_do(c))
191
	    return;
192
	set_my_want_state_do(c);
193
	do_dont_resp[c]++;
194
    }
195
    NET2ADD(IAC, DO);
196
    NETADD(c);
197
    printoption("SENT",DO, c);
198
}
199
200
void
201
send_dont(int c, int init)
202
{
203
    if (init) {
204
	if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) ||
205
				my_want_state_is_dont(c))
206
	    return;
207
	set_my_want_state_dont(c);
208
	do_dont_resp[c]++;
209
    }
210
    NET2ADD(IAC, DONT);
211
    NETADD(c);
212
    printoption("SENT", DONT, c);
213
}
214
215
void
216
send_will(int c, int init)
217
{
218
    if (init) {
219
	if (((will_wont_resp[c] == 0) && my_state_is_will(c)) ||
220
				my_want_state_is_will(c))
221
	    return;
222
	set_my_want_state_will(c);
223
	will_wont_resp[c]++;
224
    }
225
    NET2ADD(IAC, WILL);
226
    NETADD(c);
227
    printoption("SENT", WILL, c);
228
}
229
230
void
231
send_wont(int c, int init)
232
{
233
    if (init) {
234
	if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) ||
235
				my_want_state_is_wont(c))
236
	    return;
237
	set_my_want_state_wont(c);
238
	will_wont_resp[c]++;
239
    }
240
    NET2ADD(IAC, WONT);
241
    NETADD(c);
242
    printoption("SENT", WONT, c);
243
}
244
245
static void
246
willoption(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))
253
		--do_dont_resp[option];
254
	}
255
256
	if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) {
257
258
	    switch (option) {
259
260
	    case TELOPT_ECHO:
261
	    case TELOPT_BINARY:
262
	    case TELOPT_SGA:
263
		settimer(modenegotiated);
264
		/* FALL THROUGH */
265
	    case TELOPT_STATUS:
266
		new_state_ok = 1;
267
		break;
268
269
	    case TELOPT_TM:
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);
277
		set_my_state_dont(option);
278
		return;			/* Never reply to TM will's/wont's */
279
280
	    case TELOPT_LINEMODE:
281
	    default:
282
		break;
283
	    }
284
285
	    if (new_state_ok) {
286
		set_my_want_state_do(option);
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);
295
296
}
297
298
static void
299
wontoption(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))
304
		--do_dont_resp[option];
305
	}
306
307
	if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) {
308
309
	    switch (option) {
310
311
#ifdef	KLUDGELINEMODE
312
	    case TELOPT_SGA:
313
		if (!kludgelinemode)
314
		    break;
315
		/* FALL THROUGH */
316
#endif
317
	    case TELOPT_ECHO:
318
		settimer(modenegotiated);
319
		break;
320
321
	    case TELOPT_TM:
322
		if (flushout)
323
		    flushout = 0;
324
		set_my_want_state_dont(option);
325
		set_my_state_dont(option);
326
		return;		/* Never reply to TM will's/wont's */
327
328
	    default:
329
		break;
330
	    }
331
	    set_my_want_state_dont(option);
332
	    if (my_state_is_do(option))
333
		send_dont(option, 0);
334
	    setconnmode(0);			/* Set new tty mode */
335
	} else if (option == TELOPT_TM) {
336
	    /*
337
	     * Special case for TM.
338
	     */
339
	    if (flushout)
340
		flushout = 0;
341
	    set_my_want_state_dont(option);
342
	}
343
	set_my_state_dont(option);
344
}
345
346
static void
347
dooption(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))
354
		--will_wont_resp[option];
355
	}
356
357
	if (will_wont_resp[option] == 0) {
358
	  if (my_want_state_is_wont(option)) {
359
360
	    switch (option) {
361
362
	    case TELOPT_TM:
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);
369
		set_my_state_wont(TELOPT_TM);
370
		return;
371
372
	    case TELOPT_BINARY:		/* binary mode */
373
	    case TELOPT_NAWS:		/* window size */
374
	    case TELOPT_TSPEED:		/* terminal speed */
375
	    case TELOPT_LFLOW:		/* local flow control */
376
	    case TELOPT_TTYPE:		/* terminal type option */
377
	    case TELOPT_SGA:		/* no big deal */
378
		new_state_ok = 1;
379
		break;
380
381
	    case TELOPT_NEW_ENVIRON:	/* New environment variable option */
382
		new_state_ok = 1;
383
		break;
384
385
	    case TELOPT_XDISPLOC:	/* X Display location */
386
		if (env_getvalue("DISPLAY", 0))
387
		    new_state_ok = 1;
388
		break;
389
390
	    case TELOPT_LINEMODE:
391
#ifdef	KLUDGELINEMODE
392
		kludgelinemode = 0;
393
		send_do(TELOPT_SGA, 1);
394
#endif
395
		set_my_want_state_will(TELOPT_LINEMODE);
396
		send_will(option, 0);
397
		set_my_state_will(TELOPT_LINEMODE);
398
		slc_init();
399
		return;
400
401
	    case TELOPT_ECHO:		/* We're never going to echo... */
402
	    default:
403
		break;
404
	    }
405
406
	    if (new_state_ok) {
407
		set_my_want_state_will(option);
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_LINEMODE:
421
#ifdef	KLUDGELINEMODE
422
		kludgelinemode = 0;
423
		send_do(TELOPT_SGA, 1);
424
#endif
425
		set_my_state_will(option);
426
		slc_init();
427
		send_do(TELOPT_SGA, 0);
428
		return;
429
	    }
430
	  }
431
	}
432
	set_my_state_will(option);
433
}
434
435
static void
436
dontoption(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))
442
		--will_wont_resp[option];
443
	}
444
445
	if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) {
446
	    switch (option) {
447
	    case TELOPT_LINEMODE:
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);
453
	    if (my_state_is_will(option))
454
		send_wont(option, 0);
455
	    setconnmode(0);			/* Set new tty mode */
456
	}
457
	set_my_state_wont(option);
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
466
int is_unique(char *, char **, char **);
467
468
static char *name_unknown = "UNKNOWN";
469
static char *unknown[] = { NULL, NULL };
470
471
char **
472
mklist(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;
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, n+3, sizeof(char *));
498
	if (argv == NULL)
499
		return(unknown);
500
501
	/*
502
	 * Fill up the array of pointers to names.
503
	 */
504
	*argv = NULL;
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))
540
		if ((c == ' ') || !ISASCII(c))
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;
566
567
	if (*argv == NULL) {
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
582
int
583
is_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
595
int resettermname = 1;
596
597
char *
598
gettermname(void)
599
{
600
	char *tname;
601
	static char **tnamep = NULL;
602
	static char **next;
603
	int errret;
604
605
	if (resettermname) {
606
		resettermname = 0;
607
		if (tnamep && tnamep != unknown)
608
			free(tnamep);
609
		if ((tname = env_getvalue("TERM", 0)) &&
610
		    (setupterm(tname, 1, &errret) == OK)) {
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)
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
641
static void
642
suboption(void)
643
{
644
    unsigned char subchar;
645
646
    printsub('<', subbuffer, SB_LEN()+2);
647
    switch (subchar = SB_GET()) {
648
    case TELOPT_TTYPE:
649
	if (my_want_state_is_wont(TELOPT_TTYPE))
650
	    return;
651
	if (SB_EOF() || SB_GET() != TELQUAL_SEND) {
652
	    return;
653
	} else {
654
	    char *name;
655
	    unsigned char temp[50];
656
	    int len;
657
658
	    name = gettermname();
659
	    len = strlen(name) + 4 + 2;
660
	    if (len < NETROOM()) {
661
		snprintf((char *)temp, sizeof(temp),
662
			 "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
663
			 TELQUAL_IS, name, IAC, SE);
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_TSPEED:
671
	if (my_want_state_is_wont(TELOPT_TSPEED))
672
	    return;
673
	if (SB_EOF())
674
	    return;
675
	if (SB_GET() == TELQUAL_SEND) {
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", IAC, SB, TELOPT_TSPEED,
684
		     TELQUAL_IS, ospeed, ispeed, IAC, SE);
685
	    len = strlen((char *)temp+4) + 4;	/* temp[3] is 0 ... */
686
687
	    if (len < NETROOM()) {
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_LFLOW:
695
	if (my_want_state_is_wont(TELOPT_LFLOW))
696
	    return;
697
	if (SB_EOF())
698
	    return;
699
	switch(SB_GET()) {
700
	case LFLOW_RESTART_ANY:
701
	    restartany = 1;
702
	    break;
703
	case LFLOW_RESTART_XON:
704
	    restartany = 0;
705
	    break;
706
	case LFLOW_ON:
707
	    localflow = 1;
708
	    break;
709
	case LFLOW_OFF:
710
	    localflow = 0;
711
	    break;
712
	default:
713
	    return;
714
	}
715
	setcommandmode();
716
	setconnmode(0);
717
	break;
718
719
    case TELOPT_LINEMODE:
720
	if (my_want_state_is_wont(TELOPT_LINEMODE))
721
	    return;
722
	if (SB_EOF())
723
	    return;
724
	switch (SB_GET()) {
725
	case WILL:
726
	    lm_will(subpointer, SB_LEN());
727
	    break;
728
	case WONT:
729
	    lm_wont(subpointer, SB_LEN());
730
	    break;
731
	case DO:
732
	    lm_do(subpointer, SB_LEN());
733
	    break;
734
	case DONT:
735
	    lm_dont(subpointer, SB_LEN());
736
	    break;
737
	case LM_SLC:
738
	    slc(subpointer, SB_LEN());
739
	    break;
740
	case LM_MODE:
741
	    lm_mode(subpointer, SB_LEN(), 0);
742
	    break;
743
	default:
744
	    break;
745
	}
746
	break;
747
748
    case TELOPT_NEW_ENVIRON:
749
	if (SB_EOF())
750
	    return;
751
	switch(SB_PEEK()) {
752
	case TELQUAL_IS:
753
	case TELQUAL_INFO:
754
	    if (my_want_state_is_dont(subchar))
755
		return;
756
	    break;
757
	case TELQUAL_SEND:
758
	    if (my_want_state_is_wont(subchar)) {
759
		return;
760
	    }
761
	    break;
762
	default:
763
	    return;
764
	}
765
	env_opt(subpointer, SB_LEN());
766
	break;
767
768
    case TELOPT_XDISPLOC:
769
	if (my_want_state_is_wont(TELOPT_XDISPLOC))
770
	    return;
771
	if (SB_EOF())
772
	    return;
773
	if (SB_GET() == TELQUAL_SEND) {
774
	    unsigned char temp[50], *dp;
775
	    int len;
776
777
	    if ((dp = env_getvalue("DISPLAY", 0)) == NULL) {
778
		/*
779
		 * Something happened, we no longer have a DISPLAY
780
		 * variable.  So, turn off the option.
781
		 */
782
		send_wont(TELOPT_XDISPLOC, 1);
783
		break;
784
	    }
785
	    snprintf((char *)temp, sizeof(temp),
786
		    "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
787
		    TELQUAL_IS, dp, IAC, SE);
788
	    len = strlen((char *)temp+4) + 4;	/* temp[3] is 0 ... */
789
790
	    if (len < NETROOM()) {
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
803
static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE };
804
805
static void
806
lm_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_FORWARDMASK:	/* We shouldn't ever get this... */
814
    default:
815
	str_lm[3] = DONT;
816
	str_lm[4] = cmd[0];
817
	if (NETROOM() > 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
826
static void
827
lm_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_FORWARDMASK:	/* We shouldn't ever get this... */
835
    default:
836
	/* We are always DONT, so don't respond */
837
	return;
838
    }
839
}
840
841
static void
842
lm_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_FORWARDMASK:
850
    default:
851
	str_lm[3] = WONT;
852
	str_lm[4] = cmd[0];
853
	if (NETROOM() > 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
862
static void
863
lm_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_FORWARDMASK:
871
    default:
872
	/* we are always WONT, so don't respond */
873
	break;
874
    }
875
}
876
877
static unsigned char str_lm_mode[] = {
878
	IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE
879
};
880
881
void
882
lm_mode(unsigned char *cmd, int len, int init)
883
{
884
	if (len != 1)
885
		return;
886
	if ((linemode&MODE_MASK&~MODE_ACK) == *cmd)
887
		return;
888
	if (*cmd&MODE_ACK)
889
		return;
890
	linemode = *cmd&(MODE_MASK&~MODE_ACK);
891
	str_lm_mode[4] = linemode;
892
	if (!init)
893
	    str_lm_mode[4] |= MODE_ACK;
894
	if (NETROOM() > 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
909
struct spc {
910
	cc_t val;
911
	cc_t *valp;
912
	char flags;	/* Current flags & level */
913
	char mylevel;	/* Maximum level & flags */
914
} spc_data[NSLC+1];
915
916
#define SLC_IMPORT	0
917
#define	SLC_EXPORT	1
918
#define SLC_RVALUE	2
919
static int slc_mode = SLC_EXPORT;
920
921
static void
922
slc_init(void)
923
{
924
	struct spc *spcp;
925
926
	localchars = 1;
927
	for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) {
928
		spcp->val = 0;
929
		spcp->valp = NULL;
930
		spcp->flags = spcp->mylevel = SLC_NOSUPPORT;
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_VARIABLE|flags; \
938
					} else { \
939
					    spcp->val = 0; \
940
					    spcp->mylevel = SLC_DEFAULT; \
941
					} \
942
				    }
943
944
	initfunc(SLC_SYNCH, 0);
945
	/* No BRK */
946
	initfunc(SLC_AO, 0);
947
	initfunc(SLC_AYT, 0);
948
	/* No EOR */
949
	initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT);
950
	initfunc(SLC_EOF, 0);
951
	initfunc(SLC_SUSP, SLC_FLUSHIN);
952
	initfunc(SLC_EC, 0);
953
	initfunc(SLC_EL, 0);
954
	initfunc(SLC_EW, 0);
955
	initfunc(SLC_RP, 0);
956
	initfunc(SLC_LNEXT, 0);
957
	initfunc(SLC_XON, 0);
958
	initfunc(SLC_XOFF, 0);
959
	initfunc(SLC_FORW1, 0);
960
	initfunc(SLC_FORW2, 0);
961
	/* No FORW2 */
962
963
	initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT);
964
#undef	initfunc
965
966
	if (slc_mode == SLC_EXPORT)
967
		slc_export();
968
	else
969
		slc_import(1);
970
971
}
972
973
void
974
slcstate(void)
975
{
976
    printf("Special characters are %s values\n",
977
		slc_mode == SLC_IMPORT ? "remote default" :
978
		slc_mode == SLC_EXPORT ? "local" :
979
					 "remote");
980
}
981
982
void
983
slc_mode_export(int unused)
984
{
985
    slc_mode = SLC_EXPORT;
986
    if (my_state_is_will(TELOPT_LINEMODE))
987
	slc_export();
988
}
989
990
void
991
slc_mode_import(int def)
992
{
993
    slc_mode = def ? SLC_IMPORT : SLC_RVALUE;
994
    if (my_state_is_will(TELOPT_LINEMODE))
995
	slc_import(def);
996
}
997
998
unsigned char slc_import_val[] = {
999
	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE
1000
};
1001
unsigned char slc_import_def[] = {
1002
	IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE
1003
};
1004
1005
static void
1006
slc_import(int def)
1007
{
1008
    if (NETROOM() > 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
1020
static void
1021
slc_export(void)
1022
{
1023
    struct spc *spcp;
1024
1025
    TerminalDefaultChars();
1026
1027
    slc_start_reply();
1028
    for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1029
	if (spcp->mylevel != SLC_NOSUPPORT) {
1030
	    if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1031
		spcp->flags = SLC_NOSUPPORT;
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
1044
static void
1045
slc(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_FUNC];
1055
1056
		if (func == 0) {
1057
			/*
1058
			 * Client side: always ignore 0 function.
1059
			 */
1060
			continue;
1061
		}
1062
		if (func > NSLC) {
1063
			if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT)
1064
				slc_add_reply(func, SLC_NOSUPPORT, 0);
1065
			continue;
1066
		}
1067
1068
		spcp = &spc_data[func];
1069
1070
		level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK);
1071
1072
		if ((cp[SLC_VALUE] == (unsigned char)spcp->val) &&
1073
		    ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) {
1074
			continue;
1075
		}
1076
1077
		if (level == (SLC_DEFAULT|SLC_ACK)) {
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_FLAGS] &= ~SLC_ACK;
1085
		}
1086
1087
		if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) {
1088
			spcp->val = (cc_t)cp[SLC_VALUE];
1089
			spcp->flags = cp[SLC_FLAGS];	/* include SLC_ACK */
1090
			continue;
1091
		}
1092
1093
		level &= ~SLC_ACK;
1094
1095
		if (level <= (spcp->mylevel&SLC_LEVELBITS)) {
1096
			spcp->flags = cp[SLC_FLAGS]|SLC_ACK;
1097
			spcp->val = (cc_t)cp[SLC_VALUE];
1098
		}
1099
		if (level == SLC_DEFAULT) {
1100
			if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT)
1101
				spcp->flags = spcp->mylevel;
1102
			else
1103
				spcp->flags = SLC_NOSUPPORT;
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
1112
void
1113
slc_check(void)
1114
{
1115
    struct spc *spcp;
1116
1117
    slc_start_reply();
1118
    for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1119
	if (spcp->valp && spcp->val != *spcp->valp) {
1120
	    spcp->val = *spcp->valp;
1121
	    if (spcp->val == (cc_t)(_POSIX_VDISABLE))
1122
		spcp->flags = SLC_NOSUPPORT;
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
1133
static unsigned char slc_reply[2 * SUBBUFSIZE];
1134
static unsigned char *slc_replyp;
1135
1136
unsigned char
1137
slc_add(unsigned char ch)
1138
{
1139
	if (slc_replyp == slc_reply + sizeof(slc_reply))
1140
		return ch;
1141
	return *slc_replyp++ = ch;
1142
}
1143
1144
static void
1145
slc_start_reply(void)
1146
{
1147
	slc_replyp = slc_reply;
1148
	slc_add(IAC);
1149
	slc_add(SB);
1150
	slc_add(TELOPT_LINEMODE);
1151
	slc_add(LM_SLC);
1152
}
1153
1154
static void
1155
slc_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) == IAC)
1162
		slc_add(IAC);
1163
	if (slc_add(flags) == IAC)
1164
		slc_add(IAC);
1165
	if (slc_add((unsigned char)value) == IAC)
1166
		slc_add(IAC);
1167
}
1168
1169
static void
1170
slc_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(IAC);
1180
    slc_add(SE);
1181
    len = slc_replyp - slc_reply;
1182
    if (len <= 6)
1183
	return;
1184
    if (NETROOM() > 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
1191
static int
1192
slc_update(void)
1193
{
1194
	struct spc *spcp;
1195
	int need_update = 0;
1196
1197
	for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) {
1198
		if (!(spcp->flags&SLC_ACK))
1199
			continue;
1200
		spcp->flags &= ~SLC_ACK;
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
1209
static void
1210
env_opt(char *buf, int len)
1211
{
1212
	char *ep = 0, *epc = 0;
1213
	int i;
1214
1215
	switch(buf[0]&0xff) {
1216
	case TELQUAL_SEND:
1217
		env_opt_start();
1218
		if (len == 1) {
1219
			env_opt_add(NULL);
1220
		} else for (i = 1; i < len; i++) {
1221
			switch (buf[i]&0xff) {
1222
			case NEW_ENV_VAR:
1223
			case ENV_USERVAR:
1224
				if (ep) {
1225
					*epc = 0;
1226
					env_opt_add(ep);
1227
				}
1228
				ep = epc = &buf[i+1];
1229
				break;
1230
			case ENV_ESC:
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_IS:
1247
	case TELQUAL_INFO:
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 * SUBBUFSIZE)
1257
static unsigned char *opt_reply;
1258
static unsigned char *opt_replyp;
1259
static unsigned char *opt_replyend;
1260
1261
void
1262
opt_add(unsigned char ch)
1263
{
1264
	if (opt_replyp == opt_replyend)
1265
		return;
1266
	*opt_replyp++ = ch;
1267
}
1268
1269
static void
1270
env_opt_start(void)
1271
{
1272
	unsigned char *p;
1273
1274
	p = realloc(opt_reply, OPT_REPLY_SIZE);
1275
	if (p == NULL)
1276
		free(opt_reply);
1277
	opt_reply = p;
1278
	if (opt_reply == NULL) {
1279
/*@*/		printf("env_opt_start: realloc() failed!!!\n");
1280
		opt_reply = opt_replyp = opt_replyend = NULL;
1281
		return;
1282
	}
1283
	opt_replyp = opt_reply;
1284
	opt_replyend = opt_reply + OPT_REPLY_SIZE;
1285
	opt_add(IAC);
1286
	opt_add(SB);
1287
	opt_add(telopt_environ);
1288
	opt_add(TELQUAL_IS);
1289
}
1290
1291
void
1292
env_opt_start_info(void)
1293
{
1294
	env_opt_start();
1295
	if (opt_replyp)
1296
	    opt_replyp[-1] = TELQUAL_INFO;
1297
}
1298
1299
void
1300
env_opt_add(char *ep)
1301
{
1302
	char *vp, c;
1303
1304
	if (opt_reply == NULL)		/*XXX*/
1305
		return;			/*XXX*/
1306
1307
	if (ep == NULL || *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 * strlen(ep);
1328
		if (vp)
1329
			len += 2 * strlen(vp);
1330
		p = realloc(opt_reply, len);
1331
		if (p == NULL) {
1332
			free(opt_reply);
1333
/*@*/			printf("env_opt_add: realloc() failed!!!\n");
1334
			opt_reply = opt_replyp = opt_replyend = NULL;
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_VAR);
1343
	else
1344
		opt_add(ENV_USERVAR);
1345
1346
	for (;;) {
1347
		while ((c = *ep++)) {
1348
			switch(c&0xff) {
1349
			case IAC:
1350
				opt_add(IAC);
1351
				break;
1352
			case NEW_ENV_VAR:
1353
			case NEW_ENV_VALUE:
1354
			case ENV_ESC:
1355
			case ENV_USERVAR:
1356
				opt_add(ENV_ESC);
1357
				break;
1358
			}
1359
			opt_add(c);
1360
		}
1361
		if ((ep = vp)) {
1362
				opt_add(NEW_ENV_VALUE);
1363
			vp = NULL;
1364
		} else
1365
			break;
1366
	}
1367
}
1368
1369
int
1370
opt_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
1382
void
1383
env_opt_end(int emptyok)
1384
{
1385
	int len;
1386
1387
	len = opt_replyp - opt_reply + 2;
1388
	if (emptyok || len > 6) {
1389
		opt_add(IAC);
1390
		opt_add(SE);
1391
		if (NETROOM() > 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;
1400
	}
1401
}
1402
1403
1404
1405
int
1406
telrcv(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() > 2) {
1417
	if (scc == 0) {
1418
	    if (count) {
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) {
1426
		/* No more data coming in */
1427
		break;
1428
	    }
1429
	}
1430
1431
	c = *sbp++ & 0xff, scc--; count++;
1432
1433
	switch (telrcv_state) {
1434
1435
	case TS_CR:
1436
	    telrcv_state = TS_DATA;
1437
	    if (c == '\0') {
1438
		break;	/* Ignore \0 after CR */
1439
	    }
1440
	    else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) {
1441
		TTYADD(c);
1442
		break;
1443
	    }
1444
	    /* Else, fall through */
1445
1446
	case TS_DATA:
1447
	    if (c == IAC) {
1448
		telrcv_state = TS_IAC;
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)) {
1459
		if (scc > 0) {
1460
		    c = *sbp&0xff;
1461
		    if (c == 0) {
1462
			sbp++, scc--; count++;
1463
			/* a "true" CR */
1464
			TTYADD('\r');
1465
		    } else if (my_want_state_is_dont(TELOPT_ECHO) &&
1466
					(c == '\n')) {
1467
			sbp++, scc--; count++;
1468
			TTYADD('\n');
1469
		    } else {
1470
			TTYADD('\r');
1471
			if (crmod) {
1472
				TTYADD('\n');
1473
			}
1474
		    }
1475
		} else {
1476
		    telrcv_state = TS_CR;
1477
		    TTYADD('\r');
1478
		    if (crmod) {
1479
			    TTYADD('\n');
1480
		    }
1481
		}
1482
	    } else {
1483
		TTYADD(c);
1484
	    }
1485
	    continue;
1486
1487
	case TS_IAC:
1488
process_iac:
1489
	    switch (c) {
1490
1491
	    case WILL:
1492
		telrcv_state = TS_WILL;
1493
		continue;
1494
1495
	    case WONT:
1496
		telrcv_state = TS_WONT;
1497
		continue;
1498
1499
	    case DO:
1500
		telrcv_state = TS_DO;
1501
		continue;
1502
1503
	    case DONT:
1504
		telrcv_state = TS_DONT;
1505
		continue;
1506
1507
	    case DM:
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", IAC, DM);
1514
		SYNCHing = 1;
1515
		(void) ttyflush(1);
1516
		SYNCHing = stilloob();
1517
		break;
1518
1519
	    case SB:
1520
		SB_CLEAR();
1521
		telrcv_state = TS_SB;
1522
		continue;
1523
1524
	    case IAC:
1525
		TTYADD(IAC);
1526
		break;
1527
1528
	    case NOP:
1529
	    case GA:
1530
	    default:
1531
		printoption("RCVD", IAC, c);
1532
		break;
1533
	    }
1534
	    telrcv_state = TS_DATA;
1535
	    continue;
1536
1537
	case TS_WILL:
1538
	    printoption("RCVD", WILL, c);
1539
	    willoption(c);
1540
	    telrcv_state = TS_DATA;
1541
	    continue;
1542
1543
	case TS_WONT:
1544
	    printoption("RCVD", WONT, c);
1545
	    wontoption(c);
1546
	    telrcv_state = TS_DATA;
1547
	    continue;
1548
1549
	case TS_DO:
1550
	    printoption("RCVD", DO, c);
1551
	    dooption(c);
1552
	    if (c == TELOPT_NAWS) {
1553
		sendnaws();
1554
	    } else if (c == TELOPT_LFLOW) {
1555
		localflow = 1;
1556
		setcommandmode();
1557
		setconnmode(0);
1558
	    }
1559
	    telrcv_state = TS_DATA;
1560
	    continue;
1561
1562
	case TS_DONT:
1563
	    printoption("RCVD", DONT, c);
1564
	    dontoption(c);
1565
	    flushline = 1;
1566
	    setconnmode(0);	/* set new tty mode (maybe) */
1567
	    telrcv_state = TS_DATA;
1568
	    continue;
1569
1570
	case TS_SB:
1571
	    if (c == IAC) {
1572
		telrcv_state = TS_SE;
1573
	    } else {
1574
		SB_ACCUM(c);
1575
	    }
1576
	    continue;
1577
1578
	case TS_SE:
1579
	    if (c != SE) {
1580
		if (c != IAC) {
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);
1594
		    SB_ACCUM(c);
1595
		    subpointer -= 2;
1596
		    SB_TERM();
1597
1598
		    printoption("In SUBOPTION processing, RCVD", IAC, c);
1599
		    suboption();	/* handle sub-option */
1600
		    telrcv_state = TS_IAC;
1601
		    goto process_iac;
1602
		}
1603
		SB_ACCUM(c);
1604
		telrcv_state = TS_SB;
1605
	    } else {
1606
		SB_ACCUM(IAC);
1607
		SB_ACCUM(SE);
1608
		subpointer -= 2;
1609
		SB_TERM();
1610
		suboption();	/* handle sub-option */
1611
		telrcv_state = TS_DATA;
1612
	    }
1613
	}
1614
    }
1615
    if (count)
1616
	ring_consumed(&netiring, count);
1617
    return returnValue||count;
1618
}
1619
1620
static int bol = 1, local = 0;
1621
1622
int
1623
rlogin_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
1634
static int
1635
telsnd(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() > 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), tcc--; count++;
1661
	if (rlogin != _POSIX_VDISABLE) {
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 == termEofChar) {
1671
				bol = 1;
1672
				command(0, "close\n", 6);
1673
				continue;
1674
			}
1675
			if (sc == termSuspChar) {
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 && sc == escape) {
1698
	    /*
1699
	     * Double escape is a pass through of a single escape character.
1700
	     */
1701
	    if (tcc && strip(*tbp) == 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	KLUDGELINEMODE
1717
	if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) {
1718
	    if (tcc > 0 && strip(*tbp) == echoc) {
1719
		tcc--; tbp++; count++;
1720
	    } else {
1721
		dontlecho = !dontlecho;
1722
		settimer(echotoggle);
1723
		setconnmode(0);
1724
		flushline = 1;
1725
		break;
1726
	    }
1727
	}
1728
#endif
1729
	if (sc != _POSIX_VDISABLE && MODE_LOCAL_CHARS(globalmode)) {
1730
	    if (TerminalSpecialChars(sc) == 0) {
1731
		bol = 1;
1732
		break;
1733
	    }
1734
	}
1735
	if (my_want_state_is_wont(TELOPT_BINARY)) {
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)) {
1744
		    NETADD('\r');
1745
		}
1746
		NETADD('\n');
1747
		bol = flushline = 1;
1748
		break;
1749
	    case '\r':
1750
		if (!crlf) {
1751
		    NET2ADD('\r', '\0');
1752
		} else {
1753
		    NET2ADD('\r', '\n');
1754
		}
1755
		bol = flushline = 1;
1756
		break;
1757
	    case IAC:
1758
		NET2ADD(IAC, IAC);
1759
		break;
1760
	    default:
1761
		NETADD(c);
1762
		break;
1763
	    }
1764
	} else if (c == IAC) {
1765
	    NET2ADD(IAC, IAC);
1766
	} else {
1767
	    NETADD(c);
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
1784
int
1785
Scheduler(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)
1800
#ifdef	KLUDGELINEMODE
1801
			&& (!kludgelinemode || my_want_state_is_do(TELOPT_SGA))
1802
#endif
1803
		) ||
1804
			my_want_state_is_will(TELOPT_BINARY));
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
 */
1838
void
1839
telnet(char *user)
1840
{
1841
    connections++;
1842
    sys_telnet_init();
1843
1844
    if (pledge("stdio rpath tty wpath cpath", NULL) == -1) {
1845
	perror("pledge");
1846
	exit(1);
1847
    }
1848
1849
    if (telnetport) {
1850
	send_do(TELOPT_SGA, 1);
1851
	send_will(TELOPT_TTYPE, 1);
1852
	send_will(TELOPT_NAWS, 1);
1853
	send_will(TELOPT_TSPEED, 1);
1854
	send_will(TELOPT_LFLOW, 1);
1855
	send_will(TELOPT_LINEMODE, 1);
1856
	send_will(TELOPT_NEW_ENVIRON, 1);
1857
	send_do(TELOPT_STATUS, 1);
1858
	if (env_getvalue("DISPLAY", 0))
1859
	    send_will(TELOPT_XDISPLOC, 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
1893
static char *
1894
nextitem(char *current)
1895
{
1896
    if ((*current&0xff) != IAC) {
1897
	return current+1;
1898
    }
1899
    switch (*(current+1)&0xff) {
1900
    case DO:
1901
    case DONT:
1902
    case WILL:
1903
    case WONT:
1904
	return current+3;
1905
    case SB:		/* loop forever looking for the SE */
1906
	{
1907
	    char *look = current+2;
1908
1909
	    for (;;) {
1910
		if ((*look++&0xff) == IAC) {
1911
		    if ((*look++&0xff) == SE) {
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
1940
static void
1941
netclear(void)
1942
{
1943
#if	0	/* XXX */
1944
    char *thisitem, *next;
1945
    char *good;
1946
#define	wewant(p)	((nfrontp > p) && ((*p&0xff) == IAC) && \
1947
				((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
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
1983
static void
1984
doflush(void)
1985
{
1986
    NET2ADD(IAC, DO);
1987
    NETADD(TELOPT_TM);
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", DO, TELOPT_TM);
1993
}
1994
1995
void
1996
xmitAO(void)
1997
{
1998
    NET2ADD(IAC, AO);
1999
    printoption("SENT", IAC, AO);
2000
    if (autoflush) {
2001
	doflush();
2002
    }
2003
}
2004
2005
2006
void
2007
xmitEL(void)
2008
{
2009
    NET2ADD(IAC, EL);
2010
    printoption("SENT", IAC, EL);
2011
}
2012
2013
void
2014
xmitEC(void)
2015
{
2016
    NET2ADD(IAC, EC);
2017
    printoption("SENT", IAC, EC);
2018
}
2019
2020
2021
int
2022
dosynch(void)
2023
{
2024
    netclear();			/* clear the path to the network */
2025
    NETADD(IAC);
2026
    setneturg();
2027
    NETADD(DM);
2028
    printoption("SENT", IAC, DM);
2029
    return 1;
2030
}
2031
2032
int want_status_response = 0;
2033
2034
int
2035
get_status(void)
2036
{
2037
    unsigned char tmp[16];
2038
    unsigned char *cp;
2039
2040
    if (my_want_state_is_dont(TELOPT_STATUS)) {
2041
	printf("Remote side does not support STATUS option\n");
2042
	return 0;
2043
    }
2044
    cp = tmp;
2045
2046
    *cp++ = IAC;
2047
    *cp++ = SB;
2048
    *cp++ = TELOPT_STATUS;
2049
    *cp++ = TELQUAL_SEND;
2050
    *cp++ = IAC;
2051
    *cp++ = SE;
2052
    if (NETROOM() >= 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
2060
void
2061
intp(void)
2062
{
2063
    NET2ADD(IAC, IP);
2064
    printoption("SENT", IAC, IP);
2065
    flushline = 1;
2066
    if (autoflush) {
2067
	doflush();
2068
    }
2069
    if (autosynch) {
2070
	dosynch();
2071
    }
2072
}
2073
2074
void
2075
sendbrk(void)
2076
{
2077
    NET2ADD(IAC, BREAK);
2078
    printoption("SENT", IAC, BREAK);
2079
    flushline = 1;
2080
    if (autoflush) {
2081
	doflush();
2082
    }
2083
    if (autosynch) {
2084
	dosynch();
2085
    }
2086
}
2087
2088
void
2089
sendabort(void)
2090
{
2091
    NET2ADD(IAC, ABORT);
2092
    printoption("SENT", IAC, ABORT);
2093
    flushline = 1;
2094
    if (autoflush) {
2095
	doflush();
2096
    }
2097
    if (autosynch) {
2098
	dosynch();
2099
    }
2100
}
2101
2102
void
2103
sendsusp(void)
2104
{
2105
    NET2ADD(IAC, SUSP);
2106
    printoption("SENT", IAC, SUSP);
2107
    flushline = 1;
2108
    if (autoflush) {
2109
	doflush();
2110
    }
2111
    if (autosynch) {
2112
	dosynch();
2113
    }
2114
}
2115
2116
void
2117
sendeof(void)
2118
{
2119
    NET2ADD(IAC, xEOF);
2120
    printoption("SENT", IAC, xEOF);
2121
}
2122
2123
void
2124
sendayt(void)
2125
{
2126
    NET2ADD(IAC, AYT);
2127
    printoption("SENT", IAC, AYT);
2128
}
2129
2130
/*
2131
 * Send a window size update to the remote system.
2132
 */
2133
2134
void
2135
sendnaws(void)
2136
{
2137
    long rows, cols;
2138
    unsigned char tmp[16];
2139
    unsigned char *cp;
2140
2141
    if (my_state_is_wont(TELOPT_NAWS))
2142
	return;
2143
2144
#define	PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \
2145
			    if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; }
2146
2147
    if (TerminalWindowSize(&rows, &cols) == 0) {	/* Failed */
2148
	return;
2149
    }
2150
2151
    cp = tmp;
2152
2153
    *cp++ = IAC;
2154
    *cp++ = SB;
2155
    *cp++ = TELOPT_NAWS;
2156
    PUTSHORT(cp, cols);
2157
    PUTSHORT(cp, rows);
2158
    *cp++ = IAC;
2159
    *cp++ = SE;
2160
    if (NETROOM() >= cp - tmp) {
2161
	ring_supply_data(&netoring, tmp, cp-tmp);
2162
	printsub('>', tmp+2, cp - tmp - 2);
2163
    }
2164
}
2165
2166
void
2167
tel_enter_binary(int rw)
2168
{
2169
    if (rw&1)
2170
	send_do(TELOPT_BINARY, 1);
2171
    if (rw&2)
2172
	send_will(TELOPT_BINARY, 1);
2173
}
2174
2175
void
2176
tel_leave_binary(int rw)
2177
{
2178
    if (rw&1)
2179
	send_dont(TELOPT_BINARY, 1);
2180
    if (rw&2)
2181
	send_wont(TELOPT_BINARY, 1);
2182
}