unstack, sort: cleanup and improvement
[minix.git] / commands / zmodem / rbsb.c
blobb9d8ab1ec13f7d5d9760a296176d4321cca7a8e9
1 /*
3 * Rev 05-05-1988
4 * This file contains Unix specific code for setting terminal modes,
5 * very little is specific to ZMODEM or YMODEM per se (that code is in
6 * sz.c and rz.c). The CRC-16 routines used by XMODEM, YMODEM, and ZMODEM
7 * are also in this file, a fast table driven macro version
9 * V7/BSD HACKERS: SEE NOTES UNDER mode(2) !!!
11 * This file is #included so the main file can set parameters such as HOWMANY.
12 * See the main files (rz.c/sz.c) for compile instructions.
15 #ifdef V7
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <sgtty.h>
19 #define OS "V7/BSD"
20 #ifdef LLITOUT
21 long Locmode; /* Saved "local mode" for 4.x BSD "new driver" */
22 long Locbit = LLITOUT; /* Bit SUPPOSED to disable output translations */
23 #include <strings.h>
24 #endif
25 #endif
27 #ifdef POSIX
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <termios.h>
31 #define OS "POSIX"
32 #endif
34 #ifndef OS
35 #ifndef USG
36 #define USG
37 #endif
38 #endif
40 #ifdef USG
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <termio.h>
44 #include <sys/ioctl.h>
45 #define OS "SYS III/V"
46 #define MODE2OK
47 #include <string.h>
48 #endif
50 #include "zmodem.h"
52 static unsigned getspeed(int code );
54 #if HOWMANY > 255
55 Howmany must be 255 or less
56 #endif
59 * return 1 iff stdout and stderr are different devices
60 * indicating this program operating with a modem on a
61 * different line
63 int Fromcu; /* Were called from cu or yam */
65 void from_cu()
67 struct stat a, b;
69 fstat(1, &a); fstat(2, &b);
70 Fromcu = a.st_rdev != b.st_rdev;
71 return;
74 void cucheck()
76 if (Fromcu)
77 fprintf(stderr,"Please read the manual page BUGS chapter!\r\n");
81 struct {
82 unsigned baudr;
83 int speedcode;
84 } speeds[] = {
85 110, B110,
86 300, B300,
87 #ifdef B600
88 600, B600,
89 #endif
90 1200, B1200,
91 2400, B2400,
92 4800, B4800,
93 9600, B9600,
94 #ifdef EXTA
95 19200, EXTA,
96 38400, EXTB,
97 #endif
101 int Twostop; /* Use two stop bits */
104 #ifndef READCHECK
105 #ifdef FIONREAD
106 #define READCHECK
108 * Return non 0 iff something to read from io descriptor f
110 int rdchk(f)
112 static long lf;
114 ioctl(f, FIONREAD, &lf);
115 return ((int) lf);
117 #endif
118 #ifdef SV
119 #define READCHECK
120 #include <fcntl.h>
122 char checked = '\0' ;
124 * Nonblocking I/O is a bit different in System V, Release 2
126 int rdchk(f)
128 int lf, savestat;
130 savestat = fcntl(f, F_GETFL) ;
131 fcntl(f, F_SETFL, savestat | O_NDELAY) ;
132 lf = read(f, &checked, 1) ;
133 fcntl(f, F_SETFL, savestat) ;
134 return(lf) ;
136 #endif
137 #endif
140 static unsigned
141 getspeed(code)
142 int code;
144 register n;
146 for (n=0; speeds[n].baudr; ++n)
147 if (speeds[n].speedcode == code)
148 return speeds[n].baudr;
149 return 38400; /* Assume fifo if ioctl failed */
154 #ifdef POSIX
155 struct termios oldtty, tty;
156 #else
157 #ifdef ICANON
158 struct termio oldtty, tty;
159 #else
160 struct sgttyb oldtty, tty;
161 struct tchars oldtch, tch;
162 #endif
163 #endif
165 int iofd = 0; /* File descriptor for ioctls & reads */
168 * mode(n)
169 * 3: save old tty stat, set raw mode with flow control
170 * 2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
171 * 1: save old tty stat, set raw mode
172 * 0: restore original tty mode
174 int mode(n)
175 int n;
177 static did0 = FALSE;
179 vfile("mode:%d", n);
180 switch(n) {
181 #ifdef POSIX
182 case 2: /* Un-raw mode used by sz, sb when -g detected */
183 if(!did0)
184 (void) tcgetattr(iofd, &oldtty);
185 tty = oldtty;
187 tty.c_iflag = BRKINT|IXON;
189 tty.c_oflag = 0; /* Transparent output */
191 tty.c_cflag &= ~PARENB; /* Disable parity */
192 tty.c_cflag |= CS8; /* Set character size = 8 */
193 if (Twostop)
194 tty.c_cflag |= CSTOPB; /* Set two stop bits */
197 tty.c_lflag = ISIG;
198 tty.c_cc[VINTR] = Zmodem ? 03:030; /* Interrupt char */
199 tty.c_cc[VQUIT] = -1; /* Quit char */
200 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
201 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
203 (void) tcsetattr(iofd, TCSANOW, &tty);
204 did0 = TRUE;
205 return OK;
206 case 1:
207 case 3:
208 if(!did0)
209 (void) tcgetattr(iofd, &oldtty);
210 tty = oldtty;
212 tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
214 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
215 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
217 tty.c_oflag = 0; /* Transparent output */
219 tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */
220 tty.c_cflag |= CS8; /* Set character size = 8 */
221 if (Twostop)
222 tty.c_cflag |= CSTOPB; /* Set two stop bits */
223 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
224 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
225 (void) tcsetattr(iofd, TCSANOW, &tty);
226 did0 = TRUE;
227 Baudrate = cfgetospeed(&tty);
228 return OK;
229 #endif
230 #ifdef USG
231 case 2: /* Un-raw mode used by sz, sb when -g detected */
232 if(!did0)
233 (void) ioctl(iofd, TCGETA, &oldtty);
234 tty = oldtty;
236 tty.c_iflag = BRKINT|IXON;
238 tty.c_oflag = 0; /* Transparent output */
240 tty.c_cflag &= ~PARENB; /* Disable parity */
241 tty.c_cflag |= CS8; /* Set character size = 8 */
242 if (Twostop)
243 tty.c_cflag |= CSTOPB; /* Set two stop bits */
246 #ifdef READCHECK
247 tty.c_lflag = Zmodem ? 0 : ISIG;
248 tty.c_cc[VINTR] = Zmodem ? -1:030; /* Interrupt char */
249 #else
250 tty.c_lflag = ISIG;
251 tty.c_cc[VINTR] = Zmodem ? 03:030; /* Interrupt char */
252 #endif
253 tty.c_cc[VQUIT] = -1; /* Quit char */
254 #ifdef NFGVMIN
255 tty.c_cc[VMIN] = 1;
256 #else
257 tty.c_cc[VMIN] = 3; /* This many chars satisfies reads */
258 #endif
259 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
261 (void) ioctl(iofd, TCSETAW, &tty);
262 did0 = TRUE;
263 return OK;
264 case 1:
265 case 3:
266 if(!did0)
267 (void) ioctl(iofd, TCGETA, &oldtty);
268 tty = oldtty;
270 tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
272 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
273 tty.c_lflag &= ~(ECHO | ICANON | ISIG);
275 tty.c_oflag = 0; /* Transparent output */
277 tty.c_cflag &= ~PARENB; /* Same baud rate, disable parity */
278 tty.c_cflag |= CS8; /* Set character size = 8 */
279 if (Twostop)
280 tty.c_cflag |= CSTOPB; /* Set two stop bits */
281 #ifdef NFGVMIN
282 tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
283 #else
284 tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
285 #endif
286 tty.c_cc[VTIME] = 1; /* or in this many tenths of seconds */
287 (void) ioctl(iofd, TCSETAW, &tty);
288 did0 = TRUE;
289 Baudrate = getspeed(tty.c_cflag & CBAUD);
290 return OK;
291 #endif
292 #ifdef V7
294 * NOTE: this should transmit all 8 bits and at the same time
295 * respond to XOFF/XON flow control. If no FIONREAD or other
296 * READCHECK alternative, also must respond to INTRRUPT char
297 * This doesn't work with V7. It should work with LLITOUT,
298 * but LLITOUT was broken on the machine I tried it on.
300 case 2: /* Un-raw mode used by sz, sb when -g detected */
301 if(!did0) {
302 #ifdef TIOCEXCL
303 ioctl(iofd, TIOCEXCL, 0);
304 #endif
305 ioctl(iofd, TIOCGETP, &oldtty);
306 ioctl(iofd, TIOCGETC, (struct sgttyb *) &oldtch);
307 #ifdef LLITOUT
308 ioctl(iofd, TIOCLGET, &Locmode);
309 #endif
311 tty = oldtty;
312 tch = oldtch;
313 #ifdef READCHECK
314 tch.t_intrc = Zmodem ? -1:030; /* Interrupt char */
315 #else
316 tch.t_intrc = Zmodem ? 03:030; /* Interrupt char */
317 #endif
318 #ifdef ODDP
319 tty.sg_flags |= ODDP;
320 #endif
321 #ifdef EVENP
322 tty.sg_flags |= EVENP;
323 #endif
324 #ifdef CBREAK
325 tty.sg_flags |= CBREAK;
326 #endif
327 #ifdef ALLDELAY
328 tty.sg_flags &= ~ALLDELAY;
329 #endif
330 #ifdef CRMOD
331 tty.sg_flags &= ~CRMOD;
332 #endif
333 #ifdef ECHO
334 tty.sg_flags &= ~ECHO;
335 #endif
336 #ifdef LCASE
337 tty.sg_flags &= ~LCASE;
338 #endif
340 ioctl(iofd, TIOCSETP, &tty);
341 ioctl(iofd, TIOCSETC, (struct sgttyb *) &tch);
342 #ifdef LLITOUT
343 ioctl(iofd, TIOCLBIS, &Locbit);
344 #endif
345 bibi(99); /* un-raw doesn't work w/o lit out */
346 did0 = TRUE;
347 return OK;
348 case 1:
349 case 3:
350 if(!did0) {
351 #ifdef TIOCEXCL
352 ioctl(iofd, TIOCEXCL, 0);
353 #endif
354 ioctl(iofd, TIOCGETP, &oldtty);
355 ioctl(iofd, TIOCGETC, (struct sgttyb *) &oldtch);
356 #ifdef LLITOUT
357 ioctl(iofd, TIOCLGET, &Locmode);
358 #endif
360 tty = oldtty;
361 tty.sg_flags |= RAW;
362 tty.sg_flags &= ~ECHO;
363 ioctl(iofd, TIOCSETP, &tty);
364 did0 = TRUE;
365 Baudrate = getspeed(tty.sg_ospeed);
366 return OK;
367 #endif
368 case 0:
369 if(!did0)
370 return ERROR;
371 #ifdef POSIX
372 /* Wait for output to drain, flush input queue, restore
373 * modes and restart output.
375 (void) tcsetattr(iofd, TCSAFLUSH, &oldtty);
376 (void) tcflow(iofd, TCOON);
377 #endif
378 #ifdef USG
379 (void) ioctl(iofd, TCSBRK, 1); /* Wait for output to drain */
380 (void) ioctl(iofd, TCFLSH, 1); /* Flush input queue */
381 (void) ioctl(iofd, TCSETAW, &oldtty); /* Restore modes */
382 (void) ioctl(iofd, TCXONC,1); /* Restart output */
383 #endif
384 #ifdef V7
385 ioctl(iofd, TIOCSETP, &oldtty);
386 ioctl(iofd, TIOCSETC, (struct sgttyb *) &oldtch);
387 #ifdef TIOCNXCL
388 ioctl(iofd, TIOCNXCL, 0);
389 #endif
390 #ifdef LLITOUT
391 ioctl(iofd, TIOCLSET, &Locmode);
392 #endif
393 #endif
395 return OK;
396 default:
397 return ERROR;
401 void sendbrk()
403 #ifdef POSIX
404 tcsendbreak(iofd, 1);
405 #endif
406 #ifdef V7
407 #ifdef TIOCSBRK
408 #define CANBREAK
409 sleep(1);
410 ioctl(iofd, TIOCSBRK, 0);
411 sleep(1);
412 ioctl(iofd, TIOCCBRK, 0);
413 #endif
414 #endif
415 #ifdef USG
416 #define CANBREAK
417 ioctl(iofd, TCSBRK, 0);
418 #endif
421 /* End of rbsb.c */