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