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