Annotation of embedaddon/lrzsz/src/rbsb.c, revision 1.1.1.1
1.1 misho 1: /*
2: rbsb.c - terminal handling stuff for lrzsz
3: Copyright (C) until 1988 Chuck Forsberg (Omen Technology INC)
4: Copyright (C) 1994 Matt Porter, Michael D. Black
5: Copyright (C) 1996, 1997 Uwe Ohse
6:
7: This program is free software; you can redistribute it and/or modify
8: it under the terms of the GNU General Public License as published by
9: the Free Software Foundation; either version 2, or (at your option)
10: any later version.
11:
12: This program is distributed in the hope that it will be useful,
13: but WITHOUT ANY WARRANTY; without even the implied warranty of
14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15: GNU General Public License for more details.
16:
17: You should have received a copy of the GNU General Public License
18: along with this program; if not, write to the Free Software
19: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20: 02111-1307, USA.
21:
22: originally written by Chuck Forsberg
23: */
24:
25: /*
26: * Rev 05-05-1988
27: * ============== (not quite, but originated there :-). -- uwe
28: */
29: #include "zglobal.h"
30:
31: #include <stdio.h>
32: #include <errno.h>
33:
34: #ifndef HAVE_ERRNO_DECLARATION
35: extern int errno;
36: #endif
37:
38: #ifdef USE_SGTTY
39: # ifdef LLITOUT
40: long Locmode; /* Saved "local mode" for 4.x BSD "new driver" */
41: long Locbit = LLITOUT; /* Bit SUPPOSED to disable output translations */
42: # endif
43: #endif
44:
45: #ifdef HAVE_SYS_IOCTL_H
46: #include <sys/ioctl.h>
47: #endif
48:
49: #ifdef MAJOR_IN_MKDEV
50: #include <sys/mkdev.h>
51: #else
52: # ifdef MAJOR_IN_SYSMACROS
53: # include <sys/sysmacros.h>
54: # endif
55: #endif
56:
57: #if defined(HOWMANY) && HOWMANY > 255
58: #ifndef NFGVMIN
59: Howmany must be 255 or less
60: #endif
61: #endif
62:
63: static struct {
64: unsigned baudr;
65: speed_t speedcode;
66: } speeds[] = {
67: {110, B110},
68: {300, B300},
69: {600, B600},
70: {1200, B1200},
71: {2400, B2400},
72: {4800, B4800},
73: {9600, B9600},
74: #ifdef B19200
75: {19200, B19200},
76: #endif
77: #ifdef B38400
78: {38400, B38400},
79: #endif
80: #ifdef B57600
81: {57600, B57600},
82: #endif
83: #ifdef B115200
84: {115200, B115200},
85: #endif
86: #ifdef B230400
87: {230400, B230400},
88: #endif
89: #ifdef B460800
90: {460800, B460800},
91: #endif
92: #ifdef EXTA
93: {19200, EXTA},
94: #endif
95: #ifdef EXTB
96: {38400, EXTB},
97: #endif
98: {0, 0}
99: };
100:
101: static unsigned
102: getspeed(speed_t code)
103: {
104: int n;
105:
106: for (n=0; speeds[n].baudr; ++n)
107: if (speeds[n].speedcode == code)
108: return speeds[n].baudr;
109: return 38400; /* Assume fifo if ioctl failed */
110: }
111:
112: /*
113: * return 1 if stdout and stderr are different devices
114: * indicating this program operating with a modem on a
115: * different line
116: */
117: int Fromcu; /* Were called from cu or yam */
118: int
119: from_cu(void)
120: {
121: #ifdef HAVE_ST_RDEV
122: struct stat a, b;
123: #if defined(makedev)
124: dev_t help=makedev(0,0);
125: #else
126: int help=0;
127: #endif
128:
129: /* in case fstat fails */
130: a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help;
131:
132: fstat(1, &a); fstat(2, &b);
133:
134: #if defined(major) && defined(minor)
135: if (major(a.st_rdev) != major(b.st_rdev)
136: || minor(a.st_rdev) != minor(b.st_rdev))
137: Fromcu=1;
138: else if (major(a.st_dev) != major(b.st_dev)
139: || minor(a.st_dev) != minor(b.st_dev))
140: Fromcu=1;
141: else
142: Fromcu=0;
143: #else
144: Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev);
145: #endif
146: #else
147: Fromcu = 1; /* a bad guess .. */
148: #endif
149: return Fromcu;
150: }
151:
152:
153:
154: int Twostop; /* Use two stop bits */
155:
156:
157: #ifdef READCHECK_FIONREAD
158: /*
159: * Return non 0 if something to read from io descriptor f
160: */
161: int
162: rdchk(int fd)
163: {
164: static long lf;
165:
166: ioctl(fd, FIONREAD, &lf);
167: return ((int) lf);
168: }
169: #endif
170:
171: #ifdef READCHECK_GETFL
172: unsigned char checked = '\0' ;
173: /*
174: * Nonblocking I/O is a bit different in System V, Release 2
175: */
176: int
177: rdchk(int fd)
178: {
179: int lf, savestat;
180:
181: savestat = fcntl(fd, F_GETFL) ;
182: if (savestat == -1)
183: return 0;
184: #ifdef OVERLY_PARANOID
185: if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY))
186: return 0;
187: lf = read(fd, &checked, 1) ;
188: if (-1==fcntl(fd, F_SETFL, savestat)) {
189: #ifdef ENABLE_SYSLOG
190: if (enable_syslog)
191: lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s",
192: strerror(errno));
193: #endif
194: zpfatal("rdchk: F_SETFL failed\n"); /* lose */
195: /* there is really no way to recover. And we can't tell
196: * the other side what's going on if we can't write to
197: * fd, but we try.
198: */
199: canit(fd);
200: exit(1);
201: }
202: #else
203: fcntl(fd, F_SETFL, savestat | O_NDELAY);
204: lf = read(fd, &checked, 1) ;
205: fcntl(fd, F_SETFL, savestat);
206: #endif
207: return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ;
208: }
209: #endif
210:
211:
212:
213:
214:
215: #ifdef USE_TERMIOS
216: struct termios oldtty, tty;
217: #else
218: # if defined(USE_TERMIO)
219: struct termio oldtty, tty;
220: # else
221: struct sgttyb oldtty, tty;
222: struct tchars oldtch, tch;
223: # endif
224: #endif
225:
226:
227: /*
228: * mode(n)
229: * 3: save old tty stat, set raw mode with flow control
230: * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
231: * 1: save old tty stat, set raw mode
232: * 0: restore original tty mode
233: */
234: int
235: io_mode(int fd, int n)
236: {
237: static int did0 = FALSE;
238:
239: vfile("mode:%d", n);
240:
241: switch(n) {
242:
243: #ifdef USE_TERMIOS
244: case 2: /* Un-raw mode used by sz, sb when -g detected */
245: if(!did0) {
246: did0 = TRUE;
247: tcgetattr(fd,&oldtty);
248: }
249: tty = oldtty;
250:
251: tty.c_iflag = BRKINT|IXON;
252:
253: tty.c_oflag = 0; /* Transparent output */
254:
255: tty.c_cflag &= ~PARENB; /* Disable parity */
256: tty.c_cflag |= CS8; /* Set character size = 8 */
257: if (Twostop)
258: tty.c_cflag |= CSTOPB; /* Set two stop bits */
259:
260: #ifdef READCHECK
261: tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
262: tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */
263: #else
264: tty.c_lflag = 0;
265: tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */
266: #endif
267: #ifdef _POSIX_VDISABLE
268: if (((int) _POSIX_VDISABLE)!=(-1)) {
269: tty.c_cc[VQUIT] = _POSIX_VDISABLE; /* Quit char */
270: } else {
271: tty.c_cc[VQUIT] = -1; /* Quit char */
272: }
273: #else
274: tty.c_cc[VQUIT] = -1; /* Quit char */
275: #endif
276: #ifdef NFGVMIN
277: tty.c_cc[VMIN] = 1;
278: #else
279: tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
280: #endif
281: tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
282:
283: tcsetattr(fd,TCSADRAIN,&tty);
284:
285: return OK;
286: case 1:
287: case 3:
288: if(!did0) {
289: did0 = TRUE;
290: tcgetattr(fd,&oldtty);
291: }
292: tty = oldtty;
293:
294: tty.c_iflag = IGNBRK;
295: if (n==3) /* with flow control */
296: tty.c_iflag |= IXOFF;
297:
298: /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
299: tty.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
300: tty.c_oflag = 0; /* Transparent output */
301:
302: tty.c_cflag &= ~(PARENB); /* Same baud rate, disable parity */
303: /* Set character size = 8 */
304: tty.c_cflag &= ~(CSIZE);
305: tty.c_cflag |= CS8;
306: if (Twostop)
307: tty.c_cflag |= CSTOPB; /* Set two stop bits */
308: #ifdef NFGVMIN
309: tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
310: #else
311: tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
312: #endif
313: tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
314: tcsetattr(fd,TCSADRAIN,&tty);
315: Baudrate = getspeed(cfgetospeed(&tty));
316: return OK;
317: case 0:
318: if(!did0)
319: return ERROR;
320: tcdrain (fd); /* wait until everything is sent */
321: tcflush (fd,TCIOFLUSH); /* flush input queue */
322: tcsetattr (fd,TCSADRAIN,&oldtty);
323: tcflow (fd,TCOON); /* restart output */
324:
325: return OK;
326: #endif
327:
328: #ifdef USE_TERMIO
329: case 2: /* Un-raw mode used by sz, sb when -g detected */
330: if(!did0)
331: (void) ioctl(fd, TCGETA, &oldtty);
332: tty = oldtty;
333:
334: tty.c_iflag = BRKINT|IXON;
335:
336: tty.c_oflag = 0; /* Transparent output */
337:
338: tty.c_cflag &= ~PARENB; /* Disable parity */
339: tty.c_cflag |= CS8; /* Set character size = 8 */
340: if (Twostop)
341: tty.c_cflag |= CSTOPB; /* Set two stop bits */
342:
343:
344: #ifdef READCHECK
345: tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
346: tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */
347: #else
348: tty.c_lflag = 0;
349: tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */
350: #endif
351: tty.c_cc[VQUIT] = -1; /* Quit char */
352: #ifdef NFGVMIN
353: tty.c_cc[VMIN] = 1;
354: #else
355: tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
356: #endif
357: tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
358:
359: (void) ioctl(fd, TCSETAW, &tty);
360: did0 = TRUE;
361: return OK;
362: case 1:
363: case 3:
364: if(!did0)
365: (void) ioctl(fd, TCGETA, &oldtty);
366: tty = oldtty;
367:
368: tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
369:
370: /* No echo, crlf mapping, delays, no erase/kill */
371: tty.c_lflag &= ~(ECHO | ICANON | ISIG);
372:
373: tty.c_oflag = 0; /* Transparent output */
374:
375: tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */
376: tty.c_cflag |= CS8; /* Set character size = 8 */
377: if (Twostop)
378: tty.c_cflag |= CSTOPB; /* Set two stop bits */
379: #ifdef NFGVMIN
380: tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
381: #else
382: tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
383: #endif
384: tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
385: (void) ioctl(fd, TCSETAW, &tty);
386: did0 = TRUE;
387: Baudrate = getspeed(tty.c_cflag & CBAUD);
388: return OK;
389: case 0:
390: if(!did0)
391: return ERROR;
392: (void) ioctl(fd, TCSBRK, 1); /* Wait for output to drain */
393: (void) ioctl(fd, TCFLSH, 0); /* Flush input queue */
394: (void) ioctl(fd, TCSETAW, &oldtty); /* Restore modes */
395: (void) ioctl(fd, TCXONC,1); /* Restart output */
396: return OK;
397: #endif
398:
399:
400: #ifdef USE_SGTTY
401: /*
402: * NOTE: this should transmit all 8 bits and at the same time
403: * respond to XOFF/XON flow control. If no FIONREAD or other
404: * READCHECK alternative, also must respond to INTRRUPT char
405: * This doesn't work with V7. It should work with LLITOUT,
406: * but LLITOUT was broken on the machine I tried it on.
407: */
408: case 2: /* Un-raw mode used by sz, sb when -g detected */
409: if(!did0) {
410: ioctl(fd, TIOCEXCL, 0);
411: ioctl(fd, TIOCGETP, &oldtty);
412: ioctl(fd, TIOCGETC, &oldtch);
413: #ifdef LLITOUT
414: ioctl(fd, TIOCLGET, &Locmode);
415: #endif
416: }
417: tty = oldtty;
418: tch = oldtch;
419: #ifdef READCHECK
420: tch.t_intrc = Zmodem ? -1:030; /* Interrupt char */
421: #else
422: tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */
423: #endif
424: tty.sg_flags |= (ODDP|EVENP|CBREAK);
425: tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
426: ioctl(fd, TIOCSETP, &tty);
427: ioctl(fd, TIOCSETC, &tch);
428: #ifdef LLITOUT
429: ioctl(fd, TIOCLBIS, &Locbit);
430: #else
431: bibi(99); /* un-raw doesn't work w/o lit out */
432: #endif
433: did0 = TRUE;
434: return OK;
435: case 1:
436: case 3:
437: if(!did0) {
438: ioctl(fd, TIOCEXCL, 0);
439: ioctl(fd, TIOCGETP, &oldtty);
440: ioctl(fd, TIOCGETC, &oldtch);
441: #ifdef LLITOUT
442: ioctl(fd, TIOCLGET, &Locmode);
443: #endif
444: }
445: tty = oldtty;
446: tty.sg_flags |= RAW;
447: tty.sg_flags &= ~ECHO;
448: ioctl(fd, TIOCSETP, &tty);
449: did0 = TRUE;
450: Baudrate = getspeed(tty.sg_ospeed);
451: return OK;
452: case 0:
453: if(!did0)
454: return ERROR;
455: ioctl(fd, TIOCSETP, &oldtty);
456: ioctl(fd, TIOCSETC, &oldtch);
457: ioctl(fd, TIOCNXCL, 0);
458: #ifdef LLITOUT
459: ioctl(fd, TIOCLSET, &Locmode);
460: #endif
461: #ifdef TIOCFLUSH
462: { int x=1; ioctl(fd,TIOCFLUSH,&x); }
463: #endif
464: #endif
465:
466: return OK;
467: default:
468: return ERROR;
469: }
470: }
471:
472: void
473: sendbrk(int fd)
474: {
475: #ifdef USE_TERMIOS
476: tcsendbreak(fd,0);
477: #endif
478: #ifdef USE_TERMIO
479: ioctl(fd, TCSBRK, 0);
480: #endif
481: #ifdef USE_SGTTY
482: #ifdef TIOCSBRK
483: sleep(1);
484: ioctl(fd, TIOCSBRK, 0);
485: sleep(1);
486: ioctl(fd, TIOCCBRK, 0);
487: #endif
488: #endif
489: }
490:
491: void
492: purgeline(int fd)
493: {
494: readline_purge();
495: #ifdef TCFLSH
496: ioctl(fd, TCFLSH, 0);
497: #else
498: lseek(fd, 0L, 2);
499: #endif
500: }
501:
502: /* End of rbsb.c */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>