~ubuntu-branches/ubuntu/oneiric/likewise-open/oneiric

« back to all changes in this revision

Viewing changes to krb5/src/appl/telnet/telnet/telnet.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Salley
  • Date: 2010-11-22 12:06:00 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122120600-8lba1fpceot71wlb
Tags: 6.0.0.53010-1
Likewise Open 6.0

Show diffs side-by-side

added added

removed removed

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