OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [userland/] [telnet/] [telnet.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.