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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [userland/] [telnet/] [sys_bsd.c] - Blame information for rev 1770

Go to most recent revision | 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[] = "@(#)sys_bsd.c   8.2 (Berkeley) 12/15/93";
36
#endif /* not lint */
37
 
38
/*
39
 * The following routines try to encapsulate what is system dependent
40
 * (at least between 4.x and dos) which is used in telnet.c.
41
 */
42
 
43
 
44
#include <fcntl.h>
45
#include <sys/types.h>
46
#include <sys/time.h>
47
#include <sys/socket.h>
48
#include <signal.h>
49
#include <errno.h>
50
#include <arpa/telnet.h>
51
#include <unistd.h>
52
#include <stdlib.h>
53
 
54
#include "ring.h"
55
 
56
#include "fdset.h"
57
 
58
#include "defines.h"
59
#include "externs.h"
60
#include "types.h"
61
 
62
#if     defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO))
63
#define SIG_FUNC_RET    void
64
#else
65
#define SIG_FUNC_RET    int
66
#endif
67
 
68
#ifdef  SIGINFO
69
extern SIG_FUNC_RET ayt_status();
70
#endif
71
 
72
int
73
        tout,                   /* Output file descriptor */
74
        tin,                    /* Input file descriptor */
75
        net;
76
 
77
#ifdef __linux__
78
#define termio  termios
79
#endif
80
 
81
#ifndef USE_TERMIO
82
struct  tchars otc = { 0 }, ntc = { 0 };
83
struct  ltchars oltc = { 0 }, nltc = { 0 };
84
struct  sgttyb ottyb = { 0 }, nttyb = { 0 };
85
int     olmode = 0;
86
# define cfgetispeed(ptr)       (ptr)->sg_ispeed
87
# define cfgetospeed(ptr)       (ptr)->sg_ospeed
88
# define old_tc ottyb
89
 
90
#else   /* USE_TERMIO */
91
struct  termio old_tc = { 0 };
92
struct  termio new_tc = { 0 };
93
 
94
# ifndef        TCSANOW
95
#  ifdef TCSETS
96
#   define      TCSANOW         TCSETS
97
#   define      TCSADRAIN       TCSETSW
98
#   define      tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
99
#  else
100
#   ifdef TCSETA
101
#    define     TCSANOW         TCSETA
102
#    define     TCSADRAIN       TCSETAW
103
#    define     tcgetattr(f, t) ioctl(f, TCGETA, (char *)t)
104
#   else
105
#    define     TCSANOW         TIOCSETA
106
#    define     TCSADRAIN       TIOCSETAW
107
#    define     tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t)
108
#   endif
109
#  endif
110
#  define       tcsetattr(f, a, t) ioctl(f, a, (char *)t)
111
#  define       cfgetospeed(ptr)        ((ptr)->c_cflag&CBAUD)
112
#  ifdef CIBAUD
113
#   define      cfgetispeed(ptr)        (((ptr)->c_cflag&CIBAUD) >> IBSHIFT)
114
#  else
115
#   define      cfgetispeed(ptr)        cfgetospeed(ptr)
116
#  endif
117
# endif /* TCSANOW */
118
# ifdef sysV88
119
# define TIOCFLUSH TC_PX_DRAIN
120
# endif
121
#endif  /* USE_TERMIO */
122
 
123
static fd_set ibits, obits, xbits;
124
 
125
 
126
    void
127
init_sys()
128
{
129
    tout = fileno(stdout);
130
    tin = fileno(stdin);
131
    FD_ZERO(&ibits);
132
    FD_ZERO(&obits);
133
    FD_ZERO(&xbits);
134
 
135
    errno = 0;
136
}
137
 
138
 
139
    int
140
TerminalWrite(buf, n)
141
    char *buf;
142
    int  n;
143
{
144
    return write(tout, buf, n);
145
}
146
 
147
    int
148
TerminalRead(buf, n)
149
    char *buf;
150
    int  n;
151
{
152
    return read(tin, buf, n);
153
}
154
 
155
/*
156
 *
157
 */
158
 
159
    int
160
TerminalAutoFlush()
161
{
162
#if     defined(LNOFLSH)
163
    int flush;
164
 
165
    ioctl(0, TIOCLGET, (char *)&flush);
166
    return !(flush&LNOFLSH);    /* if LNOFLSH, no autoflush */
167
#else   /* LNOFLSH */
168
    return 1;
169
#endif  /* LNOFLSH */
170
}
171
 
172
#ifdef  KLUDGELINEMODE
173
extern int kludgelinemode;
174
#endif
175
/*
176
 * TerminalSpecialChars()
177
 *
178
 * Look at an input character to see if it is a special character
179
 * and decide what to do.
180
 *
181
 * Output:
182
 *
183
 *      0        Don't add this character.
184
 *      1       Do add this character
185
 */
186
 
187
extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk();
188
 
189
    int
190
TerminalSpecialChars(c)
191
    int c;
192
{
193
    if (c == termIntChar) {
194
        intp();
195
        return 0;
196
    } else if (c == termQuitChar) {
197
#ifdef  KLUDGELINEMODE
198
        if (kludgelinemode)
199
            sendbrk();
200
        else
201
#endif
202
            sendabort();
203
        return 0;
204
    } else if (c == termEofChar) {
205
        if (my_want_state_is_will(TELOPT_LINEMODE)) {
206
            sendeof();
207
            return 0;
208
        }
209
        return 1;
210
    } else if (c == termSuspChar) {
211
        sendsusp();
212
        return(0);
213
    } else if (c == termFlushChar) {
214
        xmitAO();               /* Transmit Abort Output */
215
        return 0;
216
    } else if (!MODE_LOCAL_CHARS(globalmode)) {
217
        if (c == termKillChar) {
218
            xmitEL();
219
            return 0;
220
        } else if (c == termEraseChar) {
221
            xmitEC();           /* Transmit Erase Character */
222
            return 0;
223
        }
224
    }
225
    return 1;
226
}
227
 
228
 
229
/*
230
 * Flush output to the terminal
231
 */
232
 
233
    void
234
TerminalFlushOutput()
235
{
236
#ifdef  TIOCFLUSH
237
    (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
238
#else
239
    (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
240
#endif
241
}
242
 
243
    void
244
TerminalSaveState()
245
{
246
#ifndef USE_TERMIO
247
    ioctl(0, TIOCGETP, (char *)&ottyb);
248
    ioctl(0, TIOCGETC, (char *)&otc);
249
    ioctl(0, TIOCGLTC, (char *)&oltc);
250
    ioctl(0, TIOCLGET, (char *)&olmode);
251
 
252
    ntc = otc;
253
    nltc = oltc;
254
    nttyb = ottyb;
255
 
256
#else   /* USE_TERMIO */
257
    tcgetattr(0, &old_tc);
258
 
259
    new_tc = old_tc;
260
 
261
#ifndef VDISCARD
262
    termFlushChar = CONTROL('O');
263
#endif
264
#ifndef VWERASE
265
    termWerasChar = CONTROL('W');
266
#endif
267
#ifndef VREPRINT
268
    termRprntChar = CONTROL('R');
269
#endif
270
#ifndef VLNEXT
271
    termLiteralNextChar = CONTROL('V');
272
#endif
273
#ifndef VSTART
274
    termStartChar = CONTROL('Q');
275
#endif
276
#ifndef VSTOP
277
    termStopChar = CONTROL('S');
278
#endif
279
#ifndef VSTATUS
280
    termAytChar = CONTROL('T');
281
#endif
282
#endif  /* USE_TERMIO */
283
}
284
 
285
    cc_t *
286
tcval(func)
287
    register int func;
288
{
289
    switch(func) {
290
    case SLC_IP:        return(&termIntChar);
291
    case SLC_ABORT:     return(&termQuitChar);
292
    case SLC_EOF:       return(&termEofChar);
293
    case SLC_EC:        return(&termEraseChar);
294
    case SLC_EL:        return(&termKillChar);
295
    case SLC_XON:       return(&termStartChar);
296
    case SLC_XOFF:      return(&termStopChar);
297
    case SLC_FORW1:     return(&termForw1Char);
298
#ifdef  USE_TERMIO
299
    case SLC_FORW2:     return(&termForw2Char);
300
# ifdef VDISCARD
301
    case SLC_AO:        return(&termFlushChar);
302
# endif
303
# ifdef VSUSP
304
    case SLC_SUSP:      return(&termSuspChar);
305
# endif
306
# ifdef VWERASE
307
    case SLC_EW:        return(&termWerasChar);
308
# endif
309
# ifdef VREPRINT
310
    case SLC_RP:        return(&termRprntChar);
311
# endif
312
# ifdef VLNEXT
313
    case SLC_LNEXT:     return(&termLiteralNextChar);
314
# endif
315
# ifdef VSTATUS
316
    case SLC_AYT:       return(&termAytChar);
317
# endif
318
#endif
319
 
320
    case SLC_SYNCH:
321
    case SLC_BRK:
322
    case SLC_EOR:
323
    default:
324
        return((cc_t *)0);
325
    }
326
}
327
 
328
    void
329
TerminalDefaultChars()
330
{
331
#ifndef USE_TERMIO
332
    ntc = otc;
333
    nltc = oltc;
334
    nttyb.sg_kill = ottyb.sg_kill;
335
    nttyb.sg_erase = ottyb.sg_erase;
336
#else   /* USE_TERMIO */
337
    memcpy(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc));
338
# ifndef        VDISCARD
339
    termFlushChar = CONTROL('O');
340
# endif
341
# ifndef        VWERASE
342
    termWerasChar = CONTROL('W');
343
# endif
344
# ifndef        VREPRINT
345
    termRprntChar = CONTROL('R');
346
# endif
347
# ifndef        VLNEXT
348
    termLiteralNextChar = CONTROL('V');
349
# endif
350
# ifndef        VSTART
351
    termStartChar = CONTROL('Q');
352
# endif
353
# ifndef        VSTOP
354
    termStopChar = CONTROL('S');
355
# endif
356
# ifndef        VSTATUS
357
    termAytChar = CONTROL('T');
358
# endif
359
#endif  /* USE_TERMIO */
360
}
361
 
362
#ifdef notdef
363
void
364
TerminalRestoreState()
365
{
366
}
367
#endif
368
 
369
/*
370
 * TerminalNewMode - set up terminal to a specific mode.
371
 *      MODE_ECHO: do local terminal echo
372
 *      MODE_FLOW: do local flow control
373
 *      MODE_TRAPSIG: do local mapping to TELNET IAC sequences
374
 *      MODE_EDIT: do local line editing
375
 *
376
 *      Command mode:
377
 *              MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG
378
 *              local echo
379
 *              local editing
380
 *              local xon/xoff
381
 *              local signal mapping
382
 *
383
 *      Linemode:
384
 *              local/no editing
385
 *      Both Linemode and Single Character mode:
386
 *              local/remote echo
387
 *              local/no xon/xoff
388
 *              local/no signal mapping
389
 */
390
 
391
 
392
    void
393
TerminalNewMode(f)
394
    register int f;
395
{
396
    static int prevmode = 0;
397
#ifndef USE_TERMIO
398
    struct tchars tc;
399
    struct ltchars ltc;
400
    struct sgttyb sb;
401
    int lmode;
402
#else   /* USE_TERMIO */
403
    struct termio tmp_tc;
404
#endif  /* USE_TERMIO */
405
    int onoff;
406
    int old;
407
    cc_t esc;
408
 
409
    globalmode = f&~MODE_FORCE;
410
    if (prevmode == f)
411
        return;
412
 
413
    /*
414
     * Write any outstanding data before switching modes
415
     * ttyflush() returns 0 only when there is no more data
416
     * left to write out, it returns -1 if it couldn't do
417
     * anything at all, otherwise it returns 1 + the number
418
     * of characters left to write.
419
#ifndef USE_TERMIO
420
     * We would really like ask the kernel to wait for the output
421
     * to drain, like we can do with the TCSADRAIN, but we don't have
422
     * that option.  The only ioctl that waits for the output to
423
     * drain, TIOCSETP, also flushes the input queue, which is NOT
424
     * what we want (TIOCSETP is like TCSADFLUSH).
425
#endif
426
     */
427
    old = ttyflush(SYNCHing|flushout);
428
    if (old < 0 || old > 1) {
429
#ifdef  USE_TERMIO
430
        tcgetattr(tin, &tmp_tc);
431
#endif  /* USE_TERMIO */
432
        do {
433
            /*
434
             * Wait for data to drain, then flush again.
435
             */
436
#ifdef  USE_TERMIO
437
            tcsetattr(tin, TCSADRAIN, &tmp_tc);
438
#endif  /* USE_TERMIO */
439
            old = ttyflush(SYNCHing|flushout);
440
        } while (old < 0 || old > 1);
441
    }
442
 
443
    old = prevmode;
444
    prevmode = f&~MODE_FORCE;
445
#ifndef USE_TERMIO
446
    sb = nttyb;
447
    tc = ntc;
448
    ltc = nltc;
449
    lmode = olmode;
450
#else
451
    tmp_tc = new_tc;
452
#endif
453
 
454
    if (f&MODE_ECHO) {
455
#ifndef USE_TERMIO
456
        sb.sg_flags |= ECHO;
457
#else
458
        tmp_tc.c_lflag |= ECHO;
459
        tmp_tc.c_oflag |= ONLCR;
460
        if (crlf)
461
                tmp_tc.c_iflag |= ICRNL;
462
#endif
463
    } else {
464
#ifndef USE_TERMIO
465
        sb.sg_flags &= ~ECHO;
466
#else
467
        tmp_tc.c_lflag &= ~ECHO;
468
        tmp_tc.c_oflag &= ~ONLCR;
469
# ifdef notdef
470
        if (crlf)
471
                tmp_tc.c_iflag &= ~ICRNL;
472
# endif
473
#endif
474
    }
475
 
476
    if ((f&MODE_FLOW) == 0) {
477
#ifndef USE_TERMIO
478
        tc.t_startc = _POSIX_VDISABLE;
479
        tc.t_stopc = _POSIX_VDISABLE;
480
#else
481
        tmp_tc.c_iflag &= ~(IXOFF|IXON);        /* Leave the IXANY bit alone */
482
    } else {
483
        if (restartany < 0) {
484
                tmp_tc.c_iflag |= IXOFF|IXON;   /* Leave the IXANY bit alone */
485
        } else if (restartany > 0) {
486
                tmp_tc.c_iflag |= IXOFF|IXON|IXANY;
487
        } else {
488
                tmp_tc.c_iflag |= IXOFF|IXON;
489
                tmp_tc.c_iflag &= ~IXANY;
490
        }
491
#endif
492
    }
493
 
494
    if ((f&MODE_TRAPSIG) == 0) {
495
#ifndef USE_TERMIO
496
        tc.t_intrc = _POSIX_VDISABLE;
497
        tc.t_quitc = _POSIX_VDISABLE;
498
        tc.t_eofc = _POSIX_VDISABLE;
499
        ltc.t_suspc = _POSIX_VDISABLE;
500
        ltc.t_dsuspc = _POSIX_VDISABLE;
501
#else
502
        tmp_tc.c_lflag &= ~ISIG;
503
#endif
504
        localchars = 0;
505
    } else {
506
#ifdef  USE_TERMIO
507
        tmp_tc.c_lflag |= ISIG;
508
#endif
509
        localchars = 1;
510
    }
511
 
512
    if (f&MODE_EDIT) {
513
#ifndef USE_TERMIO
514
        sb.sg_flags &= ~CBREAK;
515
        sb.sg_flags |= CRMOD;
516
#else
517
        tmp_tc.c_lflag |= ICANON;
518
#endif
519
    } else {
520
#ifndef USE_TERMIO
521
        sb.sg_flags |= CBREAK;
522
        if (f&MODE_ECHO)
523
            sb.sg_flags |= CRMOD;
524
        else
525
            sb.sg_flags &= ~CRMOD;
526
#else
527
        tmp_tc.c_lflag &= ~ICANON;
528
        tmp_tc.c_iflag &= ~ICRNL;
529
        tmp_tc.c_cc[VMIN] = 1;
530
        tmp_tc.c_cc[VTIME] = 0;
531
#endif
532
    }
533
 
534
    if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) {
535
#ifndef USE_TERMIO
536
        ltc.t_lnextc = _POSIX_VDISABLE;
537
#else
538
# ifdef VLNEXT
539
        tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE);
540
# endif
541
#endif
542
    }
543
 
544
    if (f&MODE_SOFT_TAB) {
545
#ifndef USE_TERMIO
546
        sb.sg_flags |= XTABS;
547
#else
548
# ifdef OXTABS
549
        tmp_tc.c_oflag |= OXTABS;
550
# endif
551
# ifdef TABDLY
552
        tmp_tc.c_oflag &= ~TABDLY;
553
        tmp_tc.c_oflag |= TAB3;
554
# endif
555
#endif
556
    } else {
557
#ifndef USE_TERMIO
558
        sb.sg_flags &= ~XTABS;
559
#else
560
# ifdef OXTABS
561
        tmp_tc.c_oflag &= ~OXTABS;
562
# endif
563
# ifdef TABDLY
564
        tmp_tc.c_oflag &= ~TABDLY;
565
# endif
566
#endif
567
    }
568
 
569
    if (f&MODE_LIT_ECHO) {
570
#ifndef USE_TERMIO
571
        lmode &= ~LCTLECH;
572
#else
573
# ifdef ECHOCTL
574
        tmp_tc.c_lflag &= ~ECHOCTL;
575
# endif
576
#endif
577
    } else {
578
#ifndef USE_TERMIO
579
        lmode |= LCTLECH;
580
#else
581
# ifdef ECHOCTL
582
        tmp_tc.c_lflag |= ECHOCTL;
583
# endif
584
#endif
585
    }
586
 
587
    if (f == -1) {
588
        onoff = 0;
589
    } else {
590
#ifndef USE_TERMIO
591
        if (f & MODE_OUTBIN)
592
                lmode |= LLITOUT;
593
        else
594
                lmode &= ~LLITOUT;
595
 
596
        if (f & MODE_INBIN)
597
                lmode |= LPASS8;
598
        else
599
                lmode &= ~LPASS8;
600
#else
601
        if (f & MODE_INBIN)
602
                tmp_tc.c_iflag &= ~ISTRIP;
603
        else
604
                tmp_tc.c_iflag |= ISTRIP;
605
        if (f & MODE_OUTBIN) {
606
                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
607
                tmp_tc.c_cflag |= CS8;
608
                tmp_tc.c_oflag &= ~OPOST;
609
        } else {
610
                tmp_tc.c_cflag &= ~(CSIZE|PARENB);
611
                tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
612
                tmp_tc.c_oflag |= OPOST;
613
        }
614
#endif
615
        onoff = 1;
616
    }
617
 
618
    if (f != -1) {
619
#ifdef  SIGTSTP
620
        SIG_FUNC_RET susp();
621
#endif  /* SIGTSTP */
622
#ifdef  SIGINFO
623
        SIG_FUNC_RET ayt();
624
#endif
625
 
626
#ifdef  SIGTSTP
627
        (void) signal(SIGTSTP, susp);
628
#endif  /* SIGTSTP */
629
#ifdef  SIGINFO
630
        (void) signal(SIGINFO, ayt);
631
#endif
632
#if     defined(USE_TERMIO) && defined(NOKERNINFO)
633
        tmp_tc.c_lflag |= NOKERNINFO;
634
#endif
635
        /*
636
         * We don't want to process ^Y here.  It's just another
637
         * character that we'll pass on to the back end.  It has
638
         * to process it because it will be processed when the
639
         * user attempts to read it, not when we send it.
640
         */
641
#ifndef USE_TERMIO
642
        ltc.t_dsuspc = _POSIX_VDISABLE;
643
#else
644
# ifdef VDSUSP
645
        tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE);
646
# endif
647
#endif
648
#ifdef  USE_TERMIO
649
        /*
650
         * If the VEOL character is already set, then use VEOL2,
651
         * otherwise use VEOL.
652
         */
653
        esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape;
654
        if ((tmp_tc.c_cc[VEOL] != esc)
655
# ifdef VEOL2
656
            && (tmp_tc.c_cc[VEOL2] != esc)
657
# endif
658
            ) {
659
                if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE))
660
                    tmp_tc.c_cc[VEOL] = esc;
661
# ifdef VEOL2
662
                else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE))
663
                    tmp_tc.c_cc[VEOL2] = esc;
664
# endif
665
        }
666
#else
667
        if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE))
668
                tc.t_brkc = esc;
669
#endif
670
    } else {
671
#ifdef  SIGINFO
672
        SIG_FUNC_RET ayt_status();
673
 
674
        (void) signal(SIGINFO, ayt_status);
675
#endif
676
#ifdef  SIGTSTP
677
        (void) signal(SIGTSTP, SIG_DFL);
678
        (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
679
#endif  /* SIGTSTP */
680
#ifndef USE_TERMIO
681
        ltc = oltc;
682
        tc = otc;
683
        sb = ottyb;
684
        lmode = olmode;
685
#else
686
        tmp_tc = old_tc;
687
#endif
688
    }
689
#ifndef USE_TERMIO
690
    ioctl(tin, TIOCLSET, (char *)&lmode);
691
    ioctl(tin, TIOCSLTC, (char *)&ltc);
692
    ioctl(tin, TIOCSETC, (char *)&tc);
693
    ioctl(tin, TIOCSETN, (char *)&sb);
694
#else
695
    if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0)
696
        tcsetattr(tin, TCSANOW, &tmp_tc);
697
#endif
698
 
699
#if     (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
700
# if    !defined(sysV88)
701
    ioctl(tin, FIONBIO, (char *)&onoff);
702
    ioctl(tout, FIONBIO, (char *)&onoff);
703
# endif
704
#endif  /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
705
#if     defined(TN3270)
706
    if (noasynchtty == 0) {
707
        ioctl(tin, FIOASYNC, (char *)&onoff);
708
    }
709
#endif  /* defined(TN3270) */
710
 
711
}
712
 
713
/*
714
 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD).
715
 */
716
#if B4800 != 4800
717
#define DECODE_BAUD
718
#endif
719
 
720
#ifdef  DECODE_BAUD
721
#ifndef B19200
722
# define B19200 B9600
723
#endif
724
 
725
#ifndef B38400
726
# define B38400 B19200
727
#endif
728
 
729
/*
730
 * This code assumes that the values B0, B50, B75...
731
 * are in ascending order.  They do not have to be
732
 * contiguous.
733
 */
734
struct termspeeds {
735
        long speed;
736
        long value;
737
} termspeeds[] = {
738
        { 0,     B0 },     { 50,    B50 },   { 75,    B75 },
739
        { 110,   B110 },   { 134,   B134 },  { 150,   B150 },
740
        { 200,   B200 },   { 300,   B300 },  { 600,   B600 },
741
        { 1200,  B1200 },  { 1800,  B1800 }, { 2400,  B2400 },
742
        { 4800,  B4800 },  { 9600,  B9600 }, { 19200, B19200 },
743
        { 38400, B38400 }, { -1,    B38400 }
744
};
745
#endif  /* DECODE_BAUD */
746
 
747
    void
748
TerminalSpeeds(ispeed, ospeed)
749
    long *ispeed;
750
    long *ospeed;
751
{
752
#ifdef  DECODE_BAUD
753
    register struct termspeeds *tp;
754
#endif  /* DECODE_BAUD */
755
    register long in, out;
756
 
757
    out = cfgetospeed(&old_tc);
758
    in = cfgetispeed(&old_tc);
759
    if (in == 0)
760
        in = out;
761
 
762
#ifdef  DECODE_BAUD
763
    tp = termspeeds;
764
    while ((tp->speed != -1) && (tp->value < in))
765
        tp++;
766
    *ispeed = tp->speed;
767
 
768
    tp = termspeeds;
769
    while ((tp->speed != -1) && (tp->value < out))
770
        tp++;
771
    *ospeed = tp->speed;
772
#else   /* DECODE_BAUD */
773
        *ispeed = in;
774
        *ospeed = out;
775
#endif  /* DECODE_BAUD */
776
}
777
 
778
    int
779
TerminalWindowSize(rows, cols)
780
    long *rows, *cols;
781
{
782
#ifdef  TIOCGWINSZ
783
    struct winsize ws;
784
 
785
    if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) {
786
        *rows = ws.ws_row;
787
        *cols = ws.ws_col;
788
        return 1;
789
    }
790
#endif  /* TIOCGWINSZ */
791
    return 0;
792
}
793
 
794
    int
795
NetClose(fd)
796
    int fd;
797
{
798
    return close(fd);
799
}
800
 
801
 
802
    void
803
NetNonblockingIO(fd, onoff)
804
    int fd;
805
    int onoff;
806
{
807
    ioctl(fd, FIONBIO, (char *)&onoff);
808
}
809
 
810
#if     defined(TN3270)
811
    void
812
NetSigIO(fd, onoff)
813
    int fd;
814
    int onoff;
815
{
816
    ioctl(fd, FIOASYNC, (char *)&onoff);        /* hear about input */
817
}
818
 
819
    void
820
NetSetPgrp(fd)
821
    int fd;
822
{
823
    int myPid;
824
 
825
    myPid = getpid();
826
    fcntl(fd, F_SETOWN, myPid);
827
}
828
#endif  /*defined(TN3270)*/
829
 
830
/*
831
 * Various signal handling routines.
832
 */
833
 
834
    /* ARGSUSED */
835
    SIG_FUNC_RET
836
deadpeer(sig)
837
    int sig;
838
{
839
        setcommandmode();
840
#ifdef EMBED
841
        printf("ERROR: no longjmp()\n");
842
        exit(1);
843
#else
844
        longjmp(peerdied, -1);
845
#endif
846
}
847
 
848
    /* ARGSUSED */
849
    SIG_FUNC_RET
850
intr(sig)
851
    int sig;
852
{
853
    if (localchars) {
854
        intp();
855
        return;
856
    }
857
    setcommandmode();
858
#ifdef EMBED
859
    printf("ERROR: no longjmp()\n");
860
    exit(1);
861
#else
862
    longjmp(toplevel, -1);
863
#endif
864
}
865
 
866
    /* ARGSUSED */
867
    SIG_FUNC_RET
868
intr2(sig)
869
    int sig;
870
{
871
    if (localchars) {
872
#ifdef  KLUDGELINEMODE
873
        if (kludgelinemode)
874
            sendbrk();
875
        else
876
#endif
877
            sendabort();
878
        return;
879
    }
880
}
881
 
882
#ifdef  SIGTSTP
883
    /* ARGSUSED */
884
    SIG_FUNC_RET
885
susp(sig)
886
    int sig;
887
{
888
    if ((rlogin != _POSIX_VDISABLE) && rlogin_susp())
889
        return;
890
    if (localchars)
891
        sendsusp();
892
        return;
893
}
894
#endif
895
 
896
#ifdef  SIGWINCH
897
    /* ARGSUSED */
898
    SIG_FUNC_RET
899
sendwin(sig)
900
    int sig;
901
{
902
    if (connected) {
903
        sendnaws();
904
    }
905
}
906
#endif
907
 
908
#ifdef  SIGINFO
909
    /* ARGSUSED */
910
    SIG_FUNC_RET
911
ayt(sig)
912
    int sig;
913
{
914
    if (connected)
915
        sendayt();
916
    else
917
        ayt_status();
918
}
919
#endif
920
 
921
 
922
    void
923
sys_telnet_init()
924
{
925
    (void) signal(SIGINT, intr);
926
    (void) signal(SIGQUIT, intr2);
927
    (void) signal(SIGPIPE, deadpeer);
928
#ifdef  SIGWINCH
929
    (void) signal(SIGWINCH, sendwin);
930
#endif
931
#ifdef  SIGTSTP
932
    (void) signal(SIGTSTP, susp);
933
#endif
934
#ifdef  SIGINFO
935
    (void) signal(SIGINFO, ayt);
936
#endif
937
 
938
    setconnmode(0);
939
 
940
    NetNonblockingIO(net, 1);
941
 
942
#if     defined(TN3270)
943
    if (noasynchnet == 0) {                      /* DBX can't handle! */
944
        NetSigIO(net, 1);
945
        NetSetPgrp(net);
946
    }
947
#endif  /* defined(TN3270) */
948
 
949
#if     defined(SO_OOBINLINE)
950
    if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) {
951
        perror("SetSockOpt");
952
    }
953
#endif  /* defined(SO_OOBINLINE) */
954
}
955
 
956
/*
957
 * Process rings -
958
 *
959
 *      This routine tries to fill up/empty our various rings.
960
 *
961
 *      The parameter specifies whether this is a poll operation,
962
 *      or a block-until-something-happens operation.
963
 *
964
 *      The return value is 1 if something happened, 0 if not.
965
 */
966
 
967
    int
968
process_rings(netin, netout, netex, ttyin, ttyout, poll)
969
    int poll;           /* If 0, then block until something to do */
970
{
971
    register int c;
972
                /* One wants to be a bit careful about setting returnValue
973
                 * to one, since a one implies we did some useful work,
974
                 * and therefore probably won't be called to block next
975
                 * time (TN3270 mode only).
976
                 */
977
    int returnValue = 0;
978
    static struct timeval TimeValue = { 0 };
979
 
980
    if (netout) {
981
        FD_SET(net, &obits);
982
    }
983
    if (ttyout) {
984
        FD_SET(tout, &obits);
985
    }
986
#if     defined(TN3270)
987
    if (ttyin) {
988
        FD_SET(tin, &ibits);
989
    }
990
#else   /* defined(TN3270) */
991
    if (ttyin) {
992
        FD_SET(tin, &ibits);
993
    }
994
#endif  /* defined(TN3270) */
995
#if     defined(TN3270)
996
    if (netin) {
997
        FD_SET(net, &ibits);
998
    }
999
#   else /* !defined(TN3270) */
1000
    if (netin) {
1001
        FD_SET(net, &ibits);
1002
    }
1003
#   endif /* !defined(TN3270) */
1004
    if (netex) {
1005
        FD_SET(net, &xbits);
1006
    }
1007
    if ((c = select(16, &ibits, &obits, &xbits,
1008
                        (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) {
1009
        if (c == -1) {
1010
                    /*
1011
                     * we can get EINTR if we are in line mode,
1012
                     * and the user does an escape (TSTP), or
1013
                     * some other signal generator.
1014
                     */
1015
            if (errno == EINTR) {
1016
                return 0;
1017
            }
1018
#           if defined(TN3270)
1019
                    /*
1020
                     * we can get EBADF if we were in transparent
1021
                     * mode, and the transcom process died.
1022
                    */
1023
            if (errno == EBADF) {
1024
                        /*
1025
                         * zero the bits (even though kernel does it)
1026
                         * to make sure we are selecting on the right
1027
                         * ones.
1028
                        */
1029
                FD_ZERO(&ibits);
1030
                FD_ZERO(&obits);
1031
                FD_ZERO(&xbits);
1032
                return 0;
1033
            }
1034
#           endif /* defined(TN3270) */
1035
                    /* I don't like this, does it ever happen? */
1036
            printf("sleep(5) from telnet, after select: %s\r\n", strerror(errno));
1037
            sleep(5);
1038
        }
1039
        return 0;
1040
    }
1041
 
1042
    /*
1043
     * Any urgent data?
1044
     */
1045
    if (FD_ISSET(net, &xbits)) {
1046
        FD_CLR(net, &xbits);
1047
        SYNCHing = 1;
1048
        (void) ttyflush(1);     /* flush already enqueued data */
1049
    }
1050
 
1051
    /*
1052
     * Something to read from the network...
1053
     */
1054
    if (FD_ISSET(net, &ibits)) {
1055
        int canread;
1056
 
1057
        FD_CLR(net, &ibits);
1058
        canread = ring_empty_consecutive(&netiring);
1059
#if     !defined(SO_OOBINLINE)
1060
            /*
1061
             * In 4.2 (and some early 4.3) systems, the
1062
             * OOB indication and data handling in the kernel
1063
             * is such that if two separate TCP Urgent requests
1064
             * come in, one byte of TCP data will be overlaid.
1065
             * This is fatal for Telnet, but we try to live
1066
             * with it.
1067
             *
1068
             * In addition, in 4.2 (and...), a special protocol
1069
             * is needed to pick up the TCP Urgent data in
1070
             * the correct sequence.
1071
             *
1072
             * What we do is:  if we think we are in urgent
1073
             * mode, we look to see if we are "at the mark".
1074
             * If we are, we do an OOB receive.  If we run
1075
             * this twice, we will do the OOB receive twice,
1076
             * but the second will fail, since the second
1077
             * time we were "at the mark", but there wasn't
1078
             * any data there (the kernel doesn't reset
1079
             * "at the mark" until we do a normal read).
1080
             * Once we've read the OOB data, we go ahead
1081
             * and do normal reads.
1082
             *
1083
             * There is also another problem, which is that
1084
             * since the OOB byte we read doesn't put us
1085
             * out of OOB state, and since that byte is most
1086
             * likely the TELNET DM (data mark), we would
1087
             * stay in the TELNET SYNCH (SYNCHing) state.
1088
             * So, clocks to the rescue.  If we've "just"
1089
             * received a DM, then we test for the
1090
             * presence of OOB data when the receive OOB
1091
             * fails (and AFTER we did the normal mode read
1092
             * to clear "at the mark").
1093
             */
1094
        if (SYNCHing) {
1095
            int atmark;
1096
            static int bogus_oob = 0, first = 1;
1097
 
1098
            ioctl(net, SIOCATMARK, (char *)&atmark);
1099
            if (atmark) {
1100
                c = recv(net, netiring.supply, canread, MSG_OOB);
1101
                if ((c == -1) && (errno == EINVAL)) {
1102
                    c = recv(net, netiring.supply, canread, 0);
1103
                    if (clocks.didnetreceive < clocks.gotDM) {
1104
                        SYNCHing = stilloob(net);
1105
                    }
1106
                } else if (first && c > 0) {
1107
                    /*
1108
                     * Bogosity check.  Systems based on 4.2BSD
1109
                     * do not return an error if you do a second
1110
                     * recv(MSG_OOB).  So, we do one.  If it
1111
                     * succeeds and returns exactly the same
1112
                     * data, then assume that we are running
1113
                     * on a broken system and set the bogus_oob
1114
                     * flag.  (If the data was different, then
1115
                     * we probably got some valid new data, so
1116
                     * increment the count...)
1117
                     */
1118
                    int i;
1119
                    i = recv(net, netiring.supply + c, canread - c, MSG_OOB);
1120
                    if (i == c &&
1121
                          bcmp(netiring.supply, netiring.supply + c, i) == 0) {
1122
                        bogus_oob = 1;
1123
                        first = 0;
1124
                    } else if (i < 0) {
1125
                        bogus_oob = 0;
1126
                        first = 0;
1127
                    } else
1128
                        c += i;
1129
                }
1130
                if (bogus_oob && c > 0) {
1131
                    int i;
1132
                    /*
1133
                     * Bogosity.  We have to do the read
1134
                     * to clear the atmark to get out of
1135
                     * an infinate loop.
1136
                     */
1137
                    i = read(net, netiring.supply + c, canread - c);
1138
                    if (i > 0)
1139
                        c += i;
1140
                }
1141
            } else {
1142
                c = recv(net, netiring.supply, canread, 0);
1143
            }
1144
        } else {
1145
            c = recv(net, netiring.supply, canread, 0);
1146
        }
1147
        settimer(didnetreceive);
1148
#else   /* !defined(SO_OOBINLINE) */
1149
        c = recv(net, (char *)netiring.supply, canread, 0);
1150
#endif  /* !defined(SO_OOBINLINE) */
1151
        if (c < 0 && errno == EWOULDBLOCK) {
1152
            c = 0;
1153
        } else if (c <= 0) {
1154
            return -1;
1155
        }
1156
        if (netdata) {
1157
            Dump('<', netiring.supply, c);
1158
        }
1159
        if (c)
1160
            ring_supplied(&netiring, c);
1161
        returnValue = 1;
1162
    }
1163
 
1164
    /*
1165
     * Something to read from the tty...
1166
     */
1167
    if (FD_ISSET(tin, &ibits)) {
1168
        FD_CLR(tin, &ibits);
1169
        c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring));
1170
        if (c < 0 && errno == EIO)
1171
            c = 0;
1172
        if (c < 0 && errno == EWOULDBLOCK) {
1173
            c = 0;
1174
        } else {
1175
            if (c < 0) {
1176
                return -1;
1177
            }
1178
            if (c == 0) {
1179
                        /* must be an EOF... */
1180
                if (MODE_LOCAL_CHARS(globalmode) && isatty(tin)) {
1181
                *ttyiring.supply = termEofChar;
1182
                c = 1;
1183
                } else {
1184
                    clienteof = 1;
1185
                    shutdown(net, 1);
1186
                    return 0;
1187
            }
1188
            }
1189
#if 0
1190
            if (termdata) {
1191
                Dump('<', ttyiring.supply, c);
1192
            }
1193
#endif 
1194
            ring_supplied(&ttyiring, c);
1195
        }
1196
        returnValue = 1;                /* did something useful */
1197
    }
1198
 
1199
    if (FD_ISSET(net, &obits)) {
1200
        FD_CLR(net, &obits);
1201
        returnValue |= netflush();
1202
    }
1203
    if (FD_ISSET(tout, &obits)) {
1204
        FD_CLR(tout, &obits);
1205
        returnValue |= (ttyflush(SYNCHing|flushout) > 0);
1206
    }
1207
 
1208
    return returnValue;
1209
}
1210
 
1211
#if 1
1212
#define isprint(x)      (((x) >= 0x20) && ((x) < 0x7f))
1213
dumpbuf(unsigned char *buf, int size)
1214
{
1215
        int     addr, i;
1216
        for (addr = 0; (addr < size); addr += 16) {
1217
                printf("%04x: ", addr);
1218
                for (i = 0; (i < 16); i++) {
1219
                        if ((addr + i) < size)
1220
                                printf("%02x ", buf[addr+i]);
1221
                        else
1222
                                printf("   ");
1223
                }
1224
                printf("    ");
1225
                for (i = 0; (i < 16); i++) {
1226
                        if (((addr + i) < size) && isprint(buf[addr+i]))
1227
                                printf("%c", buf[addr+i]);
1228
                        else
1229
                                printf(" ");
1230
                }
1231
                printf("\n");
1232
        }
1233
}
1234
#endif

powered by: WebSVN 2.1.0

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