xref: /minix/minix/commands/zmodem/rbsb.c (revision 7f5f010b)
1 /*
2  *
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
8  *
9  *	V7/BSD HACKERS:  SEE NOTES UNDER mode(2) !!!
10  *
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.
13  */
14 
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
26 
27 #ifdef POSIX
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <termios.h>
31 #define OS "POSIX"
32 #endif
33 
34 #ifndef OS
35 #ifndef USG
36 #define USG
37 #endif
38 #endif
39 
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
49 
50 #include "zmodem.h"
51 
52 static unsigned getspeed(int code );
53 
54 #if HOWMANY  > 255
55 Howmany must be 255 or less
56 #endif
57 
58 /*
59  * return 1 iff stdout and stderr are different devices
60  *  indicating this program operating with a modem on a
61  *  different line
62  */
63 int Fromcu;		/* Were called from cu or yam */
64 
65 void from_cu()
66 {
67 	struct stat a, b;
68 
69 	fstat(1, &a); fstat(2, &b);
70 	Fromcu = a.st_rdev != b.st_rdev;
71 	return;
72 }
73 
74 void cucheck()
75 {
76 	if (Fromcu)
77 		fprintf(stderr,"Please read the manual page BUGS chapter!\r\n");
78 }
79 
80 
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
98 	{0},
99 };
100 
101 int Twostop;		/* Use two stop bits */
102 
103 
104 #ifndef READCHECK
105 #ifdef FIONREAD
106 #define READCHECK
107 /*
108  *  Return non 0 iff something to read from io descriptor f
109  */
110 int rdchk(int f)
111 {
112 	static long lf;
113 
114 	ioctl(f, FIONREAD, &lf);
115 	return ((int) lf);
116 }
117 #endif
118 #ifdef SV
119 #define READCHECK
120 #include <fcntl.h>
121 
122 char checked = '\0' ;
123 /*
124  * Nonblocking I/O is a bit different in System V, Release 2
125  */
126 int rdchk(f)
127 {
128 	int lf, savestat;
129 
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) ;
135 }
136 #endif
137 #endif
138 
139 
140 static unsigned
141 getspeed(int code)
142 {
143 	register int n;
144 
145 	for (n=0; speeds[n].baudr; ++n)
146 		if (speeds[n].speedcode == code)
147 			return speeds[n].baudr;
148 	return 38400;	/* Assume fifo if ioctl failed */
149 }
150 
151 
152 
153 #ifdef POSIX
154 struct termios oldtty, tty;
155 #else
156 #ifdef ICANON
157 struct termio oldtty, tty;
158 #else
159 struct sgttyb oldtty, tty;
160 struct tchars oldtch, tch;
161 #endif
162 #endif
163 
164 int iofd = 0;		/* File descriptor for ioctls & reads */
165 
166 /*
167  * mode(n)
168  *  3: save old tty stat, set raw mode with flow control
169  *  2: set XON/XOFF for sb/sz with ZMODEM or YMODEM-g
170  *  1: save old tty stat, set raw mode
171  *  0: restore original tty mode
172  */
173 int mode(n)
174 int n;
175 {
176 	static int did0 = FALSE;
177 
178 	vfile("mode:%d", n);
179 	switch(n) {
180 #ifdef POSIX
181 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
182 		if(!did0)
183 			(void) tcgetattr(iofd, &oldtty);
184 		tty = oldtty;
185 
186 		tty.c_iflag = BRKINT|IXON;
187 
188 		tty.c_oflag = 0;	/* Transparent output */
189 
190 		tty.c_cflag &= ~PARENB;	/* Disable parity */
191 		tty.c_cflag |= CS8;	/* Set character size = 8 */
192 		if (Twostop)
193 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
194 
195 
196 		tty.c_lflag = ISIG;
197 		tty.c_cc[VINTR] = Zmodem ? 03:030;	/* Interrupt char */
198 		tty.c_cc[VQUIT] = -1;			/* Quit char */
199 		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
200 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
201 
202 		(void) tcsetattr(iofd, TCSANOW, &tty);
203 		did0 = TRUE;
204 		return OK;
205 	case 1:
206 	case 3:
207 		if(!did0)
208 			(void) tcgetattr(iofd, &oldtty);
209 		tty = oldtty;
210 
211 		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
212 
213 		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
214 		tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
215 
216 		tty.c_oflag = 0;	/* Transparent output */
217 
218 		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
219 		tty.c_cflag |= CS8;	/* Set character size = 8 */
220 		if (Twostop)
221 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
222 		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
223 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
224 		(void) tcsetattr(iofd, TCSANOW, &tty);
225 		did0 = TRUE;
226 		Baudrate = cfgetospeed(&tty);
227 		return OK;
228 #endif
229 #ifdef USG
230 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
231 		if(!did0)
232 			(void) ioctl(iofd, TCGETA, &oldtty);
233 		tty = oldtty;
234 
235 		tty.c_iflag = BRKINT|IXON;
236 
237 		tty.c_oflag = 0;	/* Transparent output */
238 
239 		tty.c_cflag &= ~PARENB;	/* Disable parity */
240 		tty.c_cflag |= CS8;	/* Set character size = 8 */
241 		if (Twostop)
242 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
243 
244 
245 #ifdef READCHECK
246 		tty.c_lflag = Zmodem ? 0 : ISIG;
247 		tty.c_cc[VINTR] = Zmodem ? -1:030;	/* Interrupt char */
248 #else
249 		tty.c_lflag = ISIG;
250 		tty.c_cc[VINTR] = Zmodem ? 03:030;	/* Interrupt char */
251 #endif
252 		tty.c_cc[VQUIT] = -1;			/* Quit char */
253 #ifdef NFGVMIN
254 		tty.c_cc[VMIN] = 1;
255 #else
256 		tty.c_cc[VMIN] = 3;	 /* This many chars satisfies reads */
257 #endif
258 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
259 
260 		(void) ioctl(iofd, TCSETAW, &tty);
261 		did0 = TRUE;
262 		return OK;
263 	case 1:
264 	case 3:
265 		if(!did0)
266 			(void) ioctl(iofd, TCGETA, &oldtty);
267 		tty = oldtty;
268 
269 		tty.c_iflag = n==3 ? (IGNBRK|IXOFF) : IGNBRK;
270 
271 		 /* No echo, crlf mapping, INTR, QUIT, delays, no erase/kill */
272 		tty.c_lflag &= ~(ECHO | ICANON | ISIG);
273 
274 		tty.c_oflag = 0;	/* Transparent output */
275 
276 		tty.c_cflag &= ~PARENB;	/* Same baud rate, disable parity */
277 		tty.c_cflag |= CS8;	/* Set character size = 8 */
278 		if (Twostop)
279 			tty.c_cflag |= CSTOPB;	/* Set two stop bits */
280 #ifdef NFGVMIN
281 		tty.c_cc[VMIN] = 1; /* This many chars satisfies reads */
282 #else
283 		tty.c_cc[VMIN] = HOWMANY; /* This many chars satisfies reads */
284 #endif
285 		tty.c_cc[VTIME] = 1;	/* or in this many tenths of seconds */
286 		(void) ioctl(iofd, TCSETAW, &tty);
287 		did0 = TRUE;
288 		Baudrate = getspeed(tty.c_cflag & CBAUD);
289 		return OK;
290 #endif
291 #ifdef V7
292 	/*
293 	 *  NOTE: this should transmit all 8 bits and at the same time
294 	 *   respond to XOFF/XON flow control.  If no FIONREAD or other
295 	 *   READCHECK alternative, also must respond to INTRRUPT char
296 	 *   This doesn't work with V7.  It should work with LLITOUT,
297 	 *   but LLITOUT was broken on the machine I tried it on.
298 	 */
299 	case 2:		/* Un-raw mode used by sz, sb when -g detected */
300 		if(!did0) {
301 #ifdef TIOCEXCL
302 			ioctl(iofd, TIOCEXCL, 0);
303 #endif
304 			ioctl(iofd, TIOCGETP, &oldtty);
305 			ioctl(iofd, TIOCGETC, (struct sgttyb *) &oldtch);
306 #ifdef LLITOUT
307 			ioctl(iofd, TIOCLGET, &Locmode);
308 #endif
309 		}
310 		tty = oldtty;
311 		tch = oldtch;
312 #ifdef READCHECK
313 		tch.t_intrc = Zmodem ? -1:030;	/* Interrupt char */
314 #else
315 		tch.t_intrc = Zmodem ? 03:030;	/* Interrupt char */
316 #endif
317 #ifdef ODDP
318 		tty.sg_flags |= ODDP;
319 #endif
320 #ifdef EVENP
321 		tty.sg_flags |= EVENP;
322 #endif
323 #ifdef CBREAK
324 		tty.sg_flags |= CBREAK;
325 #endif
326 #ifdef ALLDELAY
327 		tty.sg_flags &= ~ALLDELAY;
328 #endif
329 #ifdef CRMOD
330 		tty.sg_flags &= ~CRMOD;
331 #endif
332 #ifdef ECHO
333 		tty.sg_flags &= ~ECHO;
334 #endif
335 #ifdef LCASE
336 		tty.sg_flags &= ~LCASE;
337 #endif
338 
339 		ioctl(iofd, TIOCSETP, &tty);
340 		ioctl(iofd, TIOCSETC, (struct sgttyb *) &tch);
341 #ifdef LLITOUT
342 		ioctl(iofd, TIOCLBIS, &Locbit);
343 #endif
344 		bibi(99);	/* un-raw doesn't work w/o lit out */
345 		did0 = TRUE;
346 		return OK;
347 	case 1:
348 	case 3:
349 		if(!did0) {
350 #ifdef TIOCEXCL
351 			ioctl(iofd, TIOCEXCL, 0);
352 #endif
353 			ioctl(iofd, TIOCGETP, &oldtty);
354 			ioctl(iofd, TIOCGETC, (struct sgttyb *) &oldtch);
355 #ifdef LLITOUT
356 			ioctl(iofd, TIOCLGET, &Locmode);
357 #endif
358 		}
359 		tty = oldtty;
360 		tty.sg_flags |= RAW;
361 		tty.sg_flags &= ~ECHO;
362 		ioctl(iofd, TIOCSETP, &tty);
363 		did0 = TRUE;
364 		Baudrate = getspeed(tty.sg_ospeed);
365 		return OK;
366 #endif
367 	case 0:
368 		if(!did0)
369 			return ERROR;
370 #ifdef POSIX
371 		/* Wait for output to drain, flush input queue, restore
372 		 * modes and restart output.
373 		 */
374 		(void) tcsetattr(iofd, TCSAFLUSH, &oldtty);
375 		(void) tcflow(iofd, TCOON);
376 #endif
377 #ifdef USG
378 		(void) ioctl(iofd, TCSBRK, 1);	/* Wait for output to drain */
379 		(void) ioctl(iofd, TCFLSH, 1);	/* Flush input queue */
380 		(void) ioctl(iofd, TCSETAW, &oldtty);	/* Restore modes */
381 		(void) ioctl(iofd, TCXONC,1);	/* Restart output */
382 #endif
383 #ifdef V7
384 		ioctl(iofd, TIOCSETP, &oldtty);
385 		ioctl(iofd, TIOCSETC, (struct sgttyb *) &oldtch);
386 #ifdef TIOCNXCL
387 		ioctl(iofd, TIOCNXCL, 0);
388 #endif
389 #ifdef LLITOUT
390 		ioctl(iofd, TIOCLSET, &Locmode);
391 #endif
392 #endif
393 
394 		return OK;
395 	default:
396 		return ERROR;
397 	}
398 }
399 
400 void sendbrk()
401 {
402 #ifdef POSIX
403 	tcsendbreak(iofd, 1);
404 #endif
405 #ifdef V7
406 #ifdef TIOCSBRK
407 #define CANBREAK
408 	sleep(1);
409 	ioctl(iofd, TIOCSBRK, 0);
410 	sleep(1);
411 	ioctl(iofd, TIOCCBRK, 0);
412 #endif
413 #endif
414 #ifdef USG
415 #define CANBREAK
416 	ioctl(iofd, TCSBRK, 0);
417 #endif
418 }
419 
420 /* End of rbsb.c */
421