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 #ifndef HOWMANY
57 #ifdef NFGVMIN
58 #define HOWMANY MAX_BLOCK
59 #else
60 #define HOWMANY 255
61 #endif
62 #endif
63
64
65 #if defined(HOWMANY) && HOWMANY > 255
66 #ifndef NFGVMIN
67 Howmany must be 255 or less
68 #endif
69 #endif
70
71 #define B110 110
72 #define B300 300
73 #define B600 600
74 #define B1200 1200
75 #define B2400 2400
76 #define B2400 2400
77 static struct {
78 unsigned baudr;
79 int speedcode;
80 } speeds[] = {
81 {110, B110},
82 {300, B300},
83 {600, B600},
84 {1200, B1200},
85 #ifdef B19200
86 {19200, B19200},
87 #endif
88 #ifdef B38400
89 {38400, B38400},
90 #endif
91 #ifdef B57600
92 {57600, B57600},
93 #endif
94 #ifdef B115200
95 {115200, B115200},
96 #endif
97 #ifdef B230400
98 {230400, B230400},
99 #endif
100 #ifdef B460800
101 {460800, B460800},
102 #endif
103 #ifdef EXTA
104 {19200, EXTA},
105 #endif
106 #ifdef EXTB
107 {38400, EXTB},
108 #endif
109 {0, 0}
110 };
111
112 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c);
113 extern void CYGACC_COMM_IF_PUTC (char x, char y);
114 extern int CYGACC_COMM_IF_GETC_TIMEOUT (char chan, char *c);
115
116 unsigned
getspeed(int code)117 getspeed(int code)
118 {
119 int n;
120
121 for (n=0; speeds[n].baudr; ++n)
122 if (speeds[n].speedcode == code)
123 return speeds[n].baudr;
124 return 38400; /* Assume fifo if ioctl failed */
125 }
126
127 /*
128 * return 1 if stdout and stderr are different devices
129 * indicating this program operating with a modem on a
130 * different line
131 */
132 int Fromcu; /* Were called from cu or yam */
133 int
from_cu(void)134 from_cu(void)
135 {
136 #if 0
137 #ifdef HAVE_ST_RDEV
138 struct stat a, b;
139 #if defined(makedev)
140 dev_t help=makedev(0,0);
141 #else
142 int help=0;
143 #endif
144
145 /* in case fstat fails */
146 a.st_rdev=b.st_rdev=a.st_dev=b.st_dev=help;
147
148 fstat(1, &a); fstat(2, &b);
149
150 #if defined(major) && defined(minor)
151 if (major(a.st_rdev) != major(b.st_rdev)
152 || minor(a.st_rdev) != minor(b.st_rdev))
153 Fromcu=1;
154 else if (major(a.st_dev) != major(b.st_dev)
155 || minor(a.st_dev) != minor(b.st_dev))
156 Fromcu=1;
157 else
158 Fromcu=0;
159 #else
160 Fromcu = (a.st_rdev != b.st_rdev) || (a.st_dev != b.st_dev);
161 #endif
162 #else
163 Fromcu = 1; /* a bad guess .. */
164 #endif
165 return Fromcu;
166 #endif
167 return 0;
168 }
169
170
171
172 int Twostop; /* Use two stop bits */
173
174
175 #ifdef READCHECK_FIONREAD
176 /*
177 * Return non 0 if something to read from io descriptor f
178 */
179 int
rdchk(int fd)180 rdchk(int fd)
181 {
182 static long lf;
183
184 ioctl(fd, FIONREAD, &lf);
185 return ((int) lf);
186 }
187 #endif
188
189 #ifdef READCHECK_GETFL
190 unsigned char checked = '\0' ;
191 /*
192 * Nonblocking I/O is a bit different in System V, Release 2
193 */
194 int
rdchk(int fd)195 rdchk(int fd)
196 {
197 int lf, savestat;
198
199 savestat = fcntl(fd, F_GETFL) ;
200 if (savestat == -1)
201 return 0;
202 #ifdef OVERLY_PARANOID
203 if (-1==fcntl(fd, F_SETFL, savestat | O_NDELAY))
204 return 0;
205 lf = read(fd, &checked, 1) ;
206 if (-1==fcntl(fd, F_SETFL, savestat)) {
207 #ifdef ENABLE_SYSLOG
208 if (enable_syslog)
209 lsyslog(LOG_CRIT,"F_SETFL failed in rdchk(): %s",
210 strerror(errno));
211 #endif
212 zpfatal("rdchk: F_SETFL failed\n"); /* lose */
213 /* there is really no way to recover. And we can't tell
214 * the other side what's going on if we can't write to
215 * fd, but we try.
216 */
217 canit(fd);
218 exit(1);
219 }
220 #else
221 fcntl(fd, F_SETFL, savestat | O_NDELAY);
222 lf = read(fd, &checked, 1) ;
223 fcntl(fd, F_SETFL, savestat);
224 #endif
225 return(lf == -1 && errno==EWOULDBLOCK ? 0 : lf) ;
226 }
227 #endif
228
229
230
231
232
233 #ifdef USE_TERMIOS
234 struct termios oldtty, tty;
235 #else
236 # if defined(USE_TERMIO)
237 struct termio oldtty, tty;
238 # else
239 //struct sgttyb oldtty, tty;
240 //struct tchars oldtch, tch;
241 # endif
242 #endif
243
244
245 /*
246 * mode(n)
247 * 3: save old tty stat, set raw mode with flow control
248 * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
249 * 1: save old tty stat, set raw mode
250 * 0: restore original tty mode
251 */
252 int
io_mode(int fd,int n)253 io_mode(int fd, int n)
254 {
255 #if 1
256 __maybe_unused static int did0 = FALSE;
257
258 vfile("mode:%d", n);
259
260 switch(n) {
261
262 #ifdef USE_TERMIOS
263 case 2: /* Un-raw mode used by sz, sb when -g detected */
264 if(!did0) {
265 did0 = TRUE;
266 tcgetattr(fd,&oldtty);
267 }
268 tty = oldtty;
269
270 tty.c_iflag = BRKINT|IXON;
271
272 tty.c_oflag = 0; /* Transparent output */
273
274 tty.c_cflag &= ~PARENB; /* Disable parity */
275 tty.c_cflag |= CS8; /* Set character size = 8 */
276 if (Twostop)
277 tty.c_cflag |= CSTOPB; /* Set two stop bits */
278
279 #ifdef READCHECK
280 tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
281 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */
282 #else
283 tty.c_lflag = 0;
284 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */
285 #endif
286 #ifdef _POSIX_VDISABLE
287 if (((int) _POSIX_VDISABLE)!=(-1)) {
288 tty.c_cc[VQUIT] = _POSIX_VDISABLE; /* Quit char */
289 } else {
290 tty.c_cc[VQUIT] = -1; /* Quit char */
291 }
292 #else
293 tty.c_cc[VQUIT] = -1; /* Quit char */
294 #endif
295 #ifdef NFGVMIN
296 tty.c_cc[VMIN] = 1;
297 #else
298 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
299 #endif
300 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
301
302 tcsetattr(fd,TCSADRAIN,&tty);
303
304 return OK;
305 case 1:
306 case 3:
307 if(!did0) {
308 did0 = TRUE;
309 tcgetattr(fd,&oldtty);
310 }
311 tty = oldtty;
312
313 tty.c_iflag = IGNBRK;
314 if (n==3) /* with flow control */
315 tty.c_iflag |= IXOFF;
316
317 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
318 tty.c_lflag &= ~(ECHO | ICANON | ISIG);
319 tty.c_oflag = 0; /* Transparent output */
320
321 tty.c_cflag &= ~(PARENB); /* Same baud rate, disable parity */
322 /* Set character size = 8 */
323 tty.c_cflag &= ~(CSIZE);
324 tty.c_cflag |= CS8;
325 if (Twostop)
326 tty.c_cflag |= CSTOPB; /* Set two stop bits */
327 #ifdef NFGVMIN
328 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
329 #else
330 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
331 #endif
332 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
333 tcsetattr(fd,TCSADRAIN,&tty);
334 Baudrate = getspeed(cfgetospeed(&tty));
335 return OK;
336 case 0:
337 if(!did0)
338 return ERROR;
339 tcdrain (fd); /* wait until everything is sent */
340 tcflush (fd,TCIOFLUSH); /* flush input queue */
341 tcsetattr (fd,TCSADRAIN,&oldtty);
342 tcflow (fd,TCOON); /* restart output */
343
344 return OK;
345 #endif
346
347 #ifdef USE_TERMIO
348 case 2: /* Un-raw mode used by sz, sb when -g detected */
349 if(!did0)
350 (void) ioctl(fd, TCGETA, &oldtty);
351 tty = oldtty;
352
353 tty.c_iflag = BRKINT|IXON;
354
355 tty.c_oflag = 0; /* Transparent output */
356
357 tty.c_cflag &= ~PARENB; /* Disable parity */
358 tty.c_cflag |= CS8; /* Set character size = 8 */
359 if (Twostop)
360 tty.c_cflag |= CSTOPB; /* Set two stop bits */
361
362
363 #ifdef READCHECK
364 tty.c_lflag = protocol==ZM_ZMODEM ? 0 : ISIG;
365 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? -1 : 030; /* Interrupt char */
366 #else
367 tty.c_lflag = 0;
368 tty.c_cc[VINTR] = protocol==ZM_ZMODEM ? 03 : 030; /* Interrupt char */
369 #endif
370 tty.c_cc[VQUIT] = -1; /* Quit char */
371 #ifdef NFGVMIN
372 tty.c_cc[VMIN] = 1;
373 #else
374 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
375 #endif
376 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
377
378 (void) ioctl(fd, TCSETAW, &tty);
379 did0 = TRUE;
380 return OK;
381 case 1:
382 case 3:
383 if(!did0)
384 (void) ioctl(fd, TCGETA, &oldtty);
385 tty = oldtty;
386
387 tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
388
389 /* No echo, crlf mapping, delays, no erase/kill */
390 tty.c_lflag &= ~(ECHO | ICANON | ISIG);
391
392 tty.c_oflag = 0; /* Transparent output */
393
394 tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */
395 tty.c_cflag |= CS8; /* Set character size = 8 */
396 if (Twostop)
397 tty.c_cflag |= CSTOPB; /* Set two stop bits */
398 #ifdef NFGVMIN
399 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
400 #else
401 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
402 #endif
403 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
404 (void) ioctl(fd, TCSETAW, &tty);
405 did0 = TRUE;
406 Baudrate = getspeed(tty.c_cflag & CBAUD);
407 return OK;
408 case 0:
409 if(!did0)
410 return ERROR;
411 (void) ioctl(fd, TCSBRK, 1); /* Wait for output to drain */
412 (void) ioctl(fd, TCFLSH, 0); /* Flush input queue */
413 (void) ioctl(fd, TCSETAW, &oldtty); /* Restore modes */
414 (void) ioctl(fd, TCXONC,1); /* Restart output */
415 return OK;
416 #endif
417
418
419 #ifdef USE_SGTTY
420 /*
421 * NOTE: this should transmit all 8 bits and at the same time
422 * respond to XOFF/XON flow control. If no FIONREAD or other
423 * READCHECK alternative, also must respond to INTRRUPT char
424 * This doesn't work with V7. It should work with LLITOUT,
425 * but LLITOUT was broken on the machine I tried it on.
426 */
427 case 2: /* Un-raw mode used by sz, sb when -g detected */
428 if(!did0) {
429 ioctl(fd, TIOCEXCL, 0);
430 ioctl(fd, TIOCGETP, &oldtty);
431 ioctl(fd, TIOCGETC, &oldtch);
432 #ifdef LLITOUT
433 ioctl(fd, TIOCLGET, &Locmode);
434 #endif
435 }
436 tty = oldtty;
437 tch = oldtch;
438 #ifdef READCHECK
439 tch.t_intrc = Zmodem ? -1:030; /* Interrupt char */
440 #else
441 tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */
442 #endif
443 tty.sg_flags |= (ODDP|EVENP|CBREAK);
444 tty.sg_flags &= ~(ALLDELAY|CRMOD|ECHO|LCASE);
445 ioctl(fd, TIOCSETP, &tty);
446 ioctl(fd, TIOCSETC, &tch);
447 #ifdef LLITOUT
448 ioctl(fd, TIOCLBIS, &Locbit);
449 #else
450 bibi(99); /* un-raw doesn't work w/o lit out */
451 #endif
452 did0 = TRUE;
453 return OK;
454 case 1:
455 case 3:
456 if(!did0) {
457 ioctl(fd, TIOCEXCL, 0);
458 ioctl(fd, TIOCGETP, &oldtty);
459 ioctl(fd, TIOCGETC, &oldtch);
460 #ifdef LLITOUT
461 ioctl(fd, TIOCLGET, &Locmode);
462 #endif
463 }
464 tty = oldtty;
465 tty.sg_flags |= RAW;
466 tty.sg_flags &= ~ECHO;
467 ioctl(fd, TIOCSETP, &tty);
468 did0 = TRUE;
469 Baudrate = getspeed(tty.sg_ospeed);
470 return OK;
471 case 0:
472 if(!did0)
473 return ERROR;
474 ioctl(fd, TIOCSETP, &oldtty);
475 ioctl(fd, TIOCSETC, &oldtch);
476 ioctl(fd, TIOCNXCL, 0);
477 #ifdef LLITOUT
478 ioctl(fd, TIOCLSET, &Locmode);
479 #endif
480 #ifdef TIOCFLUSH
481 { int x=1; ioctl(fd,TIOCFLUSH,&x); }
482 #endif
483 #endif
484
485 return OK;
486 default:
487 return ERROR;
488 }
489 #endif
490 }
491
492 void
sendbrk(int fd)493 sendbrk(int fd)
494 {
495 #if 0
496 #ifdef USE_TERMIOS
497 tcsendbreak(fd,0);
498 #endif
499 #ifdef USE_TERMIO
500 ioctl(fd, TCSBRK, 0);
501 #endif
502 #ifdef USE_SGTTY
503 #ifdef TIOCSBRK
504 sleep(1);
505 ioctl(fd, TIOCSBRK, 0);
506 sleep(1);
507 ioctl(fd, TIOCCBRK, 0);
508 #endif
509 #endif
510 #endif
511 }
512
513 void
purgeline(int fd)514 purgeline(int fd)
515 {
516 readline_purge();
517 #if 0
518 #ifdef TCFLSH
519 ioctl(fd, TCFLSH, 0);
520 #else
521 lseek(fd, 0L, 2);
522 #endif
523 #endif
524 }
525
526 /* End of rbsb.c */
527