1 /* sys2.unx 2 The system dependent communication routines for UNIX. 3 4 Copyright (C) 1991, 1992 Ian Lance Taylor 5 6 This file is part of the Taylor UUCP package. 7 8 This program is free software; you can redistribute it and/or 9 modify it under the terms of the GNU General Public License as 10 published by the Free Software Foundation; either version 2 of the 11 License, or (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 22 The author of the program may be contacted at ian@airs.com or 23 c/o AIRS, P.O. Box 520, Waltham, MA 02254. 24 25 $Log: sys2.unx,v $ 26 Revision 1.72 1992/04/03 17:43:39 ian 27 Petri Helenius: don't clobber undefined bits in termio or termios 28 29 Revision 1.71 1992/04/01 21:52:04 ian 30 T. William Wells: handle a system without <poll.h> or <stropts.h> 31 32 Revision 1.70 1992/03/30 15:29:58 ian 33 Added HAVE_SVR4_LOCKFILES 34 35 Revision 1.69 1992/03/29 22:25:27 ian 36 Always block and unblock read and write descriptors together 37 38 Revision 1.68 1992/03/28 04:12:17 ian 39 Gerben Wierda: minor cleanups 40 41 Revision 1.67 1992/03/28 03:06:04 ian 42 Don't use TIOCEXCL locking 43 44 Revision 1.66 1992/03/28 02:47:30 ian 45 Rework HAVE_UNBLOCKED_WRITES to work even if writes are unblocked 46 47 Revision 1.65 1992/03/17 15:35:28 ian 48 Log signals when they happen, even if we continue looping 49 50 Revision 1.64 1992/03/17 05:01:33 ian 51 Don't block when opening the write descriptor 52 53 Revision 1.63 1992/03/17 01:03:03 ian 54 Miscellaneous cleanup 55 56 Revision 1.62 1992/03/16 01:23:08 ian 57 Make blocking writes optional 58 59 Revision 1.61 1992/03/15 07:15:42 ian 60 T. William Wells: don't use unblocked writes 61 62 Revision 1.60 1992/03/15 04:51:17 ian 63 Keep an array of signals we've received rather than a single variable 64 65 Revision 1.59 1992/03/15 01:54:46 ian 66 All execs are now done in isspawn, all waits are done in iswait 67 68 Revision 1.58 1992/03/12 21:50:50 ian 69 Moved local header includes above sleep routine determination 70 71 Revision 1.57 1992/03/12 19:54:43 ian 72 Debugging based on types rather than number 73 74 Revision 1.56 1992/03/11 02:09:57 ian 75 Franc,ois Pinard: retry fork several times before giving up 76 77 Revision 1.55 1992/03/09 22:11:46 ian 78 Franc,ois Pinard: sleep for a second after closing a serial port 79 80 Revision 1.54 1992/03/09 22:07:36 ian 81 Wait for terminal output to drain at various points 82 83 Revision 1.53 1992/03/08 16:56:51 ian 84 Ted Lindgreen: if CRTSCTS is defined, don't turn on IXOFF 85 86 Revision 1.52 1992/03/08 04:56:21 ian 87 Peter da Silva: added ``lockname'' command for ports 88 89 Revision 1.51 1992/03/08 01:56:01 ian 90 Include <sys/ioctl.h> if we have it 91 92 Revision 1.50 1992/03/08 01:37:45 ian 93 Suppurt TIOCEXCL locking 94 95 Revision 1.49 1992/03/07 16:25:21 ian 96 Preserve unknown bits in c_cflag 97 98 Revision 1.48 1992/03/04 23:43:39 ian 99 Petri Helenius: didn't remove lock file if open failed 100 101 Revision 1.47 1992/03/04 01:40:51 ian 102 Thomas Fischer: tweaked a bit for the NeXT 103 104 Revision 1.46 1992/03/03 21:01:20 ian 105 Use strict timeout in fsserial_read, eliminate all race conditions 106 107 Revision 1.45 1992/03/03 04:25:00 ian 108 T. William Wells: don't arbitrarily extend read timeout 109 110 Revision 1.44 1992/03/02 04:53:07 ian 111 Marc Unangst: added HAVE_SCO_LOCKFILES configuration parameter 112 113 Revision 1.43 1992/02/28 05:06:15 ian 114 T. William Wells: fsysdep_catch must be a macro 115 116 Revision 1.42 1992/02/27 05:40:54 ian 117 T. William Wells: detach from controlling terminal, handle signals safely 118 119 Revision 1.41 1992/02/24 21:22:47 ian 120 The poll function takes milliseconds, not microseconds (my error) 121 122 Revision 1.40 1992/02/24 21:18:17 ian 123 Roberto Biancardi: use poll for sleeping if we haven't got anything else 124 125 Revision 1.39 1992/02/24 20:07:43 ian 126 John Theus: some systems don't have <fcntl.h> 127 128 Revision 1.38 1992/02/23 03:26:51 ian 129 Overhaul to use automatic configure shell script 130 131 Revision 1.37 1992/02/17 22:08:50 ian 132 Bob Denny: log chat script messages as LOG_NORMAL, not LOG_ERROR 133 134 Revision 1.36 1992/02/08 20:02:36 ian 135 Added HAVE_SETRET configuration option for systems without setjmp 136 137 Revision 1.35 1992/02/08 03:54:18 ian 138 Include <string.h> only in <uucp.h>, added 1992 copyright 139 140 Revision 1.34 1992/01/16 16:32:44 ian 141 Mike Park: ioctl is sometimes declared varadic, so we can't declare it 142 143 Revision 1.33 1992/01/15 21:06:11 ian 144 Mike Park: some systems can't include <sys/time.h> and <time.h> together 145 146 Revision 1.32 1992/01/15 20:40:04 ian 147 Mike Park: some systems don't have <limits.h> 148 149 Revision 1.31 1992/01/15 19:40:35 ian 150 Mike Park: handle HAVE_UNION_WAIT correctly and completely 151 152 Revision 1.30 1992/01/14 04:18:47 ian 153 Chip Salzenberg: added HAVE_USLEEP configuration parameter 154 155 Revision 1.29 1992/01/13 06:11:39 ian 156 David Nugent: can't declare open or fcntl 157 158 Revision 1.28 1991/12/31 04:16:19 ian 159 Chip Salzenberg: don't turn on IXON and IXOFF at the start 160 161 Revision 1.27 1991/12/29 04:04:18 ian 162 Added a bunch of extern definitions 163 164 Revision 1.26 1991/12/29 00:55:23 ian 165 Monty Solomon: added HAVE_UNION_WAIT 166 167 Revision 1.25 1991/12/22 22:14:19 ian 168 Monty Solomon: added HAVE_UNISTD_H configuration parameter 169 170 Revision 1.24 1991/12/20 02:23:10 ian 171 Don't change port settings if we don't have to 172 173 Revision 1.23 1991/12/19 04:25:57 ian 174 Terry Gardner: configuration parameter to not use both NONBLOCK and NDELAY 175 176 Revision 1.22 1991/12/17 23:14:08 ian 177 T. William Wells: allow dialer complete and abort to be chat scripts 178 179 Revision 1.21 1991/12/17 22:31:15 ian 180 Start in RAW mode, to avoid dropping characters when we switch to it 181 182 Revision 1.20 1991/12/17 05:24:01 ian 183 David Nugent: flush pending input in fsserial_open 184 185 Revision 1.19 1991/12/15 04:28:23 ian 186 Don't turn on ISTRIP initially 187 188 Revision 1.18 1991/12/10 19:45:05 ian 189 Added ulog_device to record device name for log file 190 191 Revision 1.17 1991/12/01 02:23:12 ian 192 Niels Baggesen: don't multiply include <unistd.h> 193 194 Revision 1.16 1991/11/26 01:50:30 ian 195 Set fread_blocking and fwrite_blocking correctly for TCP routines 196 197 Revision 1.15 1991/11/26 01:45:42 ian 198 Marty Shannon: configuration option to not include <sys/wait.h> 199 200 Revision 1.14 1991/11/22 06:05:57 ian 201 Gregory Gulik: fix wait status macro definitions 202 203 Revision 1.13 1991/11/21 20:58:18 ian 204 Brian Campbell: for HAVE_SIGSETJMP use sigjmp_buf, not jmp_buf 205 206 Revision 1.12 1991/11/15 23:13:53 ian 207 Fixed termio(s) version of fsserial_set 208 209 Revision 1.11 1991/11/13 20:38:00 ian 210 Added TCP port type for connections over TCP 211 212 Revision 1.10 1991/11/12 19:07:27 ian 213 Be careful to only call fsetterminfo on a terminal 214 215 Revision 1.9 1991/11/11 23:47:24 ian 216 Added chat-program to run a program to do a chat script 217 218 Revision 1.8 1991/11/11 00:39:45 ian 219 Open port in seven bit mode, added fport_set to change to eight bit 220 221 Revision 1.7 1991/11/08 22:52:34 ian 222 Brian Campbell: only include <sys/time.h> and <sys/ioctl.h> when needed 223 224 Revision 1.6 1991/11/08 22:11:45 ian 225 Brian Campbell: allow sigsetjmp as configuration option 226 227 Revision 1.5 1991/11/07 22:52:11 ian 228 Chip Salzenberg: force stdin and stdout to stay open in case of spawning 229 230 Revision 1.4 1991/11/07 21:43:59 ian 231 Chip Salzenberg: set terminal modes directly, don't or them in 232 233 Revision 1.3 1991/11/07 19:42:16 ian 234 Chip Salzenberg: declare inline functions consistently 235 236 Revision 1.2 1991/11/07 19:32:28 ian 237 Chip Salzenberg: allow LOCKDIR, and check that locking process exists 238 239 Revision 1.1 1991/09/10 19:45:50 ian 240 Initial revision 241 242 */ 243 244 #include "uucp.h" 245 246 #if USE_RCS_ID 247 char sys2_unx_rcsid[] = "$Id: sys2.unx,v 1.72 1992/04/03 17:43:39 ian Rel $"; 248 #endif 249 250 #include <errno.h> 251 252 #if HAVE_LIMITS_H 253 #include <limits.h> 254 #endif 255 256 #if USE_STDIO && HAVE_UNISTD_H 257 #include <unistd.h> 258 #endif 259 260 #include "system.h" 261 #include "sysdep.h" 262 #include "port.h" 263 264 /* Pick a timing routine to use. I somewhat arbitrarily picked usleep 265 above nap above napms above poll above select. */ 266 267 #if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS || HAVE_POLL 268 #define USE_SELECT_TIMER 0 269 #else 270 #define USE_SELECT_TIMER HAVE_SELECT 271 #endif 272 273 #if HAVE_USLEEP || HAVE_NAP || HAVE_NAPMS 274 #undef HAVE_POLL 275 #define HAVE_POLL 0 276 #endif 277 278 #if HAVE_USLEEP || HAVE_NAP 279 #undef HAVE_NAPMS 280 #define HAVE_NAPMS 0 281 #endif 282 283 #if HAVE_USLEEP 284 #undef HAVE_NAP 285 #define HAVE_NAP 0 286 #endif 287 288 #if HAVE_FCNTL_H 289 #include <fcntl.h> 290 #else 291 #if HAVE_SYS_FILE_H 292 #include <sys/file.h> 293 #endif 294 #endif 295 296 #ifndef O_RDONLY 297 #define O_RDONLY 0 298 #define O_WRONLY 1 299 #define O_RDWR 2 300 #endif 301 302 #if HAVE_SYS_IOCTL_H 303 #include <sys/ioctl.h> 304 #endif 305 306 #if USE_SELECT_TIMER || HAVE_BSD_TTY 307 #include <sys/time.h> 308 #endif 309 310 #if HAVE_POLL 311 #if HAVE_STROPTS_H 312 #include <stropts.h> 313 #endif 314 #if HAVE_POLL_H 315 #include <poll.h> 316 #endif 317 #if ! HAVE_STROPTS_H && ! HAVE_POLL_H 318 /* We need a definition for struct pollfd, although it doesn't matter 319 what it contains. It's used in usysdep_pause. */ 320 struct pollfd 321 { 322 int idummy; 323 }; 324 #endif /* ! HAVE_STROPTS_H && ! HAVE_POLL_H */ 325 #endif /* HAVE_POLL */ 326 327 #if HAVE_TIME_H 328 #if HAVE_SYS_TIME_AND_TIME_H || (! USE_SELECT_TIMER && ! HAVE_BSD_TTY) 329 #include <time.h> 330 #endif 331 #endif 332 333 /* Get definitions for both O_NONBLOCK and O_NDELAY. */ 334 335 #ifndef O_NDELAY 336 #ifdef FNDELAY 337 #define O_NDELAY FNDELAY 338 #else /* ! defined (FNDELAY) */ 339 #define O_NDELAY 0 340 #endif /* ! defined (FNDELAY) */ 341 #endif /* ! defined (O_NDELAY) */ 342 343 #ifndef O_NONBLOCK 344 #ifdef FNBLOCK 345 #define O_NONBLOCK FNBLOCK 346 #else /* ! defined (FNBLOCK) */ 347 #define O_NONBLOCK 0 348 #endif /* ! defined (FNBLOCK) */ 349 #endif /* ! defined (O_NONBLOCK) */ 350 351 #if O_NDELAY == 0 && O_NONBLOCK == 0 352 #error No way to do nonblocking I/O 353 #endif 354 355 /* If we can define them both together, do so. This is because some 356 ancient drivers on some systems appear to look for one but not the 357 other. Otherwise just use O_NONBLOCK. */ 358 #if COMBINED_UNBLOCK 359 #define FILE_UNBLOCKED (O_NDELAY | O_NONBLOCK) 360 #else 361 #define FILE_UNBLOCKED O_NONBLOCK 362 #endif 363 364 /* Get definitions for both EAGAIN and EWOULDBLOCK. */ 365 366 #ifndef EAGAIN 367 #ifndef EWOULDBLOCK 368 #define EAGAIN (-1) 369 #define EWOULDBLOCK (-1) 370 #else /* defined (EWOULDBLOCK) */ 371 #define EAGAIN EWOULDBLOCK 372 #endif /* defined (EWOULDBLOCK) */ 373 #else /* defined (EAGAIN) */ 374 #ifndef EWOULDBLOCK 375 #define EWOULDBLOCK EAGAIN 376 #endif /* ! defined (EWOULDBLOCK) */ 377 #endif /* defined (EAGAIN) */ 378 379 /* Make sure we have a definition for MAX_INPUT. */ 380 381 #ifndef MAX_INPUT 382 #define MAX_INPUT (256) 383 #endif 384 385 /* Make sure we have definitions for major and minor. */ 386 387 #ifndef major 388 #define major(i) (((i) >> 8) & 0xff) 389 #endif 390 #ifndef minor 391 #define minor(i) ((i) & 0xff) 392 #endif 393 394 /* If we have the TIOCSINUSE ioctl call, we use it to lock a terminal. 395 Otherwise, if we have the TIOCEXCL ioctl call, we have to open the 396 terminal before we know that it is unlocked. */ 397 #ifdef TIOCSINUSE 398 #define HAVE_TIOCSINUSE 1 399 #else 400 #ifdef TIOCEXCL 401 #define HAVE_TIOCEXCL 1 402 #endif 403 #endif 404 405 /* Determine bits to clear for the various terminal control fields for 406 HAVE_SYSV_TERMIO and HAVE_POSIX_TERMIOS. */ 407 408 #if HAVE_SYSV_TERMIO 409 #define ICLEAR_IFLAG (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK \ 410 | ISTRIP | INLCR | IGNCR | ICRNL | IUCLC \ 411 | IXON | IXANY | IXOFF) 412 #define ICLEAR_OFLAG (OPOST | OLCUC | ONLCR | OCRNL | ONOCR | ONLRET \ 413 | OFILL | OFDEL | NLDLY | CRDLY | TABDLY | BSDLY \ 414 | VTDLY | FFDLY) 415 #define ICLEAR_CFLAG (CBAUD | CLOCAL | CSIZE | PARENB | PARODD) 416 #define ISET_CFLAG (CS8 | CREAD | HUPCL) 417 #define ICLEAR_LFLAG (ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK \ 418 | ECHONL | NOFLSH) 419 #endif 420 #if HAVE_POSIX_TERMIOS 421 #define ICLEAR_IFLAG (BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR \ 422 | INLCR | INPCK | ISTRIP | IXOFF | IXON \ 423 | PARMRK) 424 #define ICLEAR_OFLAG (OPOST) 425 #define ICLEAR_CFLAG (CLOCAL | CSIZE | PARENB | PARODD) 426 #define ISET_CFLAG (CS8 | CREAD | HUPCL) 427 #define ICLEAR_LFLAG (ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN \ 428 | ISIG | NOFLSH | TOSTOP) 429 #endif 430 431 /* External functions. */ 432 extern char *strlwr (); 433 extern int close (), pipe (), dup2 (), read (), write (); 434 extern int fclose (); 435 extern void _exit (); 436 #if USE_SELECT_TIMER || HAVE_BSD_TTY 437 extern int select (); 438 #endif 439 #if HAVE_NAP 440 extern int nap (); 441 #endif 442 #if HAVE_NAPMS 443 extern int napms (); 444 #endif 445 #if HAVE_POLL 446 extern int poll (); 447 #endif 448 449 /* Local functions. */ 450 451 static SIGtype usalarm P((int isig)); 452 static boolean fsserial_lockfile P((boolean flok, const struct sport *, 453 const char *zdevice)); 454 static boolean fsserial_lock P((const struct sport *qport, 455 struct ssysdep_serial_port *q, 456 boolean fin, const char *zdevice)); 457 static boolean fsserial_open P((const char *z, long ibaud, boolean fwait, 458 struct ssysdep_serial_port *q)); 459 __inline__ static boolean fsblock P((struct ssysdep_serial_port *q, 460 boolean fblock)); 461 static boolean fsserial_close P((struct ssysdep_serial_port *q)); 462 static boolean fsserial_reset P((struct ssysdep_serial_port *q)); 463 static boolean fsserial_read P((struct ssysdep_serial_port *q, 464 char *zbuf, int *pclen, int cmin, 465 int ctimeout, boolean freport, 466 boolean fpty)); 467 static boolean fsserial_write P((struct ssysdep_serial_port *q, 468 const char *zwrite, int cwrite)); 469 static boolean fsserial_io P((struct ssysdep_serial_port *q, 470 const char *zwrite, int *pcwrite, 471 char *zread, int *pcread)); 472 static boolean fsserial_break P((struct ssysdep_serial_port *q)); 473 static boolean fsserial_set P((struct ssysdep_serial_port *q, 474 enum tportsetting tset)); 475 static boolean fsrun_chat P((int oread, int owrite, const char *zprog)); 476 477 /* This code handles SIGALRM. See the discussion above fsserial_read. 478 Normally we ignore SIGALRM, but the handler will temporarily be set 479 to this function, which should set fSalarm and then either longjmp 480 or schedule another SIGALRM. fSalarm is never referred to outside 481 of this file, but we don't make it static to try to fool compilers 482 which don't understand volatile. */ 483 484 volatile sig_atomic_t fSalarm; 485 486 static SIGtype 487 usalarm (isig) 488 int isig; 489 { 490 #if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET 491 (void) signal (isig, usalarm); 492 #endif 493 494 fSalarm = TRUE; 495 496 #if HAVE_RESTARTABLE_SYSCALLS 497 longjmp (sSjmp_buf, 1); 498 #else 499 alarm (1); 500 #endif 501 } 502 503 /* We need a simple routine to block SIGINT, SIGQUIT, SIGTERM and 504 SIGPIPE and another to restore the original state. When these 505 functions are called (in fsysdep_modem_close) SIGHUP is being 506 ignored. The routines are isblocksigs, which returns a value of 507 type HELD_SIG_MASK and usunblocksigs which takes a single argument 508 of type HELD_SIG_MASK. */ 509 510 #if HAVE_SIGPROCMASK 511 512 /* Use the POSIX sigprocmask call. */ 513 514 extern int sigprocmask (); 515 516 #define HELD_SIG_MASK sigset_t 517 518 static sigset_t isblocksigs P((void)); 519 520 static sigset_t 521 isblocksigs () 522 { 523 sigset_t sblock, sold; 524 525 sigemptyset (&sblock); 526 sigaddset (&sblock, SIGINT); 527 sigaddset (&sblock, SIGQUIT); 528 sigaddset (&sblock, SIGTERM); 529 sigaddset (&sblock, SIGPIPE); 530 sigprocmask (SIG_BLOCK, &sblock, &sold); 531 return sold; 532 } 533 534 #define usunblocksigs(s) \ 535 ((void) sigprocmask (SIG_SETMASK, &(s), (sigset_t *) NULL)) 536 537 #else /* ! HAVE_SIGPROCMASK */ 538 #if HAVE_SIGBLOCK 539 540 /* Use the BSD sigblock and sigsetmask calls. */ 541 542 extern int sigblock (), sigsetmask (); 543 544 #define HELD_SIG_MASK int 545 546 #ifndef sigmask 547 #define sigmask(i) (1 << ((i) - 1)) 548 #endif 549 550 #define isblocksigs() \ 551 sigblock (sigmask (SIGINT) | sigmask (SIGQUIT) \ 552 | sigmask (SIGTERM) | sigmask (SIGPIPE)) 553 554 #define usunblocksigs(i) ((void) sigsetmask (i)) 555 556 #else /* ! HAVE_SIGBLOCK */ 557 558 #if HAVE_SIGHOLD 559 560 /* Use the SVR3 sighold and sigrelse calls. */ 561 562 extern int sighold (), sigrelse (); 563 564 #define HELD_SIG_MASK int 565 566 static int isblocksigs P((void)); 567 568 static int 569 isblocksigs () 570 { 571 sighold (SIGINT); 572 sighold (SIGQUIT); 573 sighold (SIGTERM); 574 sighold (SIGPIPE); 575 return 0; 576 } 577 578 static void usunblocksigs P((int)); 579 580 /*ARGSUSED*/ 581 static void 582 usunblocksigs (i) 583 int i; 584 { 585 sigrelse (SIGINT); 586 sigrelse (SIGQUIT); 587 sigrelse (SIGTERM); 588 sigrelse (SIGPIPE); 589 } 590 591 #else /* ! HAVE_SIGHOLD */ 592 593 /* We have no way to block signals. This system will suffer from a 594 race condition in fsysdep_modem_close. */ 595 596 #define HELD_SIG_MASK int 597 598 #define isblocksigs() 0 599 600 #define usunblocksigs(i) 601 602 #endif /* ! HAVE_SIGHOLD */ 603 #endif /* ! HAVE_SIGBLOCK */ 604 #endif /* ! HAVE_SIGPROCMASK */ 605 606 /* Pause for half a second. This doesn't really belong in this file, 607 but all the timing routines are here. */ 608 609 void 610 usysdep_pause () 611 { 612 #if HAVE_NAPMS 613 napms (500); 614 #endif /* HAVE_NAPMS */ 615 #if HAVE_NAP 616 nap (500L); 617 #endif /* HAVE_NAP */ 618 #if HAVE_USLEEP 619 usleep (500 * (long) 1000); 620 #endif /* HAVE_USLEEP */ 621 #if HAVE_POLL 622 struct pollfd sdummy; 623 624 /* We need to pass an unused pollfd structure because poll checks 625 the address before checking the number of elements. */ 626 poll (&sdummy, 0, 500); 627 #endif /* HAVE_POLL */ 628 #if USE_SELECT_TIMER 629 struct timeval s; 630 631 s.tv_sec = 0; 632 s.tv_usec = 500 * (long) 1000; 633 select (0, (int *) NULL, (int *) NULL, (int *) NULL, &s); 634 #endif /* USE_SELECT_TIMER */ 635 #if ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP 636 #if ! USE_SELECT_TIMER && ! HAVE_POLL 637 sleep (1); 638 #endif /* ! USE_SELECT_TIMER && ! HAVE_POLL */ 639 #endif /* ! HAVE_NAPMS && ! HAVE_NAP && ! HAVE_USLEEP */ 640 } 641 642 /* This routine is used for both locking and unlocking. It is the 643 only routine which knows how to translate a device name into the 644 name of a lock file. If it can't figure out a name, it does 645 nothing and returns TRUE. */ 646 647 static boolean 648 fsserial_lockfile (flok, qport, zdevice) 649 boolean flok; 650 const struct sport *qport; 651 const char *zdevice; 652 { 653 const char *z; 654 655 z = qport->zlockname; 656 if (z == NULL) 657 { 658 char *zalc; 659 660 z = zdevice; 661 if (z == NULL) 662 { 663 z = qport->zname; 664 if (z == NULL) 665 return TRUE; 666 } 667 668 #if ! HAVE_SVR4_LOCKFILES 669 if (strncmp (z, "/dev/", sizeof "/dev/" - 1) == 0) 670 z += sizeof "/dev/" - 1; 671 zalc = (char *) alloca (strlen (z) + sizeof "LCK.."); 672 sprintf (zalc, "LCK..%s", z); 673 #if HAVE_SCO_LOCKFILES 674 strlwr (zalc + sizeof "LCK.." - 1); 675 #endif 676 #else /* HAVE_SVR4_LOCKFILES */ 677 { 678 struct stat s; 679 680 if (*z != '/') 681 { 682 zalc = (char *) alloca (sizeof "/dev/" + strlen (z)); 683 sprintf (zalc, "/dev/%s", z); 684 z = zalc; 685 } 686 if (stat (z, &s) != 0) 687 { 688 ulog (LOG_ERROR, "stat (%s): %s", z, strerror (errno)); 689 return FALSE; 690 } 691 zalc = (char *) alloca (sizeof "LK.123.123.123"); 692 sprintf (zalc, "LK.%03d.%03d.%03d", major (s.st_dev), 693 major (s.st_rdev), minor (s.st_rdev)); 694 } 695 #endif /* HAVE_SVR4_LOCKFILES */ 696 697 z = zalc; 698 } 699 700 if (flok) 701 return fsdo_lock (z, FALSE); 702 else 703 return fsdo_unlock (z, FALSE); 704 } 705 706 /* If we can mark a modem line in use, then when we lock a port we 707 must open it and mark it in use. We can't wait until the actual 708 open because we can't fail out if it is locked then. */ 709 710 static boolean 711 fsserial_lock (qport, q, fin, zdevice) 712 const struct sport *qport; 713 struct ssysdep_serial_port *q; 714 boolean fin; 715 const char *zdevice; 716 { 717 if (! fsserial_lockfile (TRUE, qport, zdevice)) 718 return FALSE; 719 720 #if HAVE_TIOCSINUSE || HAVE_TIOCEXCL 721 /* Open the line and, if possible, mark it in use. */ 722 { 723 const char *z; 724 int oread, iflag; 725 726 z = zdevice; 727 if (z == NULL) 728 { 729 z = qport->zname; 730 if (z == NULL) 731 return TRUE; 732 } 733 734 if (fin) 735 iflag = 0; 736 else 737 iflag = FILE_UNBLOCKED; 738 739 if (*z != '/') 740 { 741 char *zcopy; 742 743 zcopy = (char *) alloca (sizeof "/dev/" + strlen (z)); 744 sprintf (zcopy, "/dev/%s", z); 745 z = zcopy; 746 } 747 748 oread = open (z, O_RDWR | iflag); 749 if (oread < 0) 750 { 751 if (errno != EBUSY) 752 ulog (LOG_ERROR, "open (%s): %s", z, strerror (errno)); 753 (void) fsserial_lockfile (FALSE, qport, zdevice); 754 return FALSE; 755 } 756 757 #if HAVE_TIOCSINUSE 758 /* If we can't mark it in use, return FALSE to indicate that the 759 lock failed. */ 760 if (ioctl (oread, TIOCSINUSE, 0) < 0) 761 { 762 if (errno != EALREADY) 763 ulog (LOG_ERROR, "ioctl (TIOCSINUSE): %s", strerror (errno)); 764 (void) close (oread); 765 (void) fsserial_lockfile (FALSE, qport, zdevice); 766 return FALSE; 767 } 768 #endif 769 770 #ifdef TIOCSCTTY 771 /* On BSD 4.4, make it our controlling terminal. */ 772 (void) ioctl (oread, TIOCSCTTY, 0); 773 #endif 774 775 q->oread = q->owrite = oread; 776 } 777 #endif /* HAVE_TIOCSINUSE || HAVE_TIOCEXCL */ 778 779 return TRUE; 780 } 781 782 /* We don't need to lock a stdin port. */ 783 784 /*ARGSUSED*/ 785 boolean 786 fsysdep_stdin_lock (qport, fin) 787 struct sport *qport; 788 boolean fin; 789 { 790 return TRUE; 791 } 792 793 /* Lock a modem port. */ 794 795 boolean 796 fsysdep_modem_lock (qport, fin) 797 struct sport *qport; 798 boolean fin; 799 { 800 return fsserial_lock (qport, &qport->u.smodem.s.s, fin, 801 qport->u.smodem.zdevice); 802 } 803 804 /* Lock a direct port. */ 805 806 boolean 807 fsysdep_direct_lock (qport, fin) 808 struct sport *qport; 809 boolean fin; 810 { 811 return fsserial_lock (qport, &qport->u.sdirect.s.s, fin, 812 qport->u.sdirect.zdevice); 813 } 814 815 /* Open a serial line. This sets the terminal settings. We begin in 816 seven bit mode and let the protocol change if necessary. */ 817 818 static struct sbaud_table 819 { 820 #if HAVE_POSIX_TERMIOS 821 speed_t icode; 822 #else 823 int icode; 824 #endif 825 long ibaud; 826 } asSbaud_table[] = 827 { 828 { B50, 50 }, 829 { B75, 75 }, 830 { B110, 110 }, 831 { B134, 134 }, 832 { B150, 150 }, 833 { B200, 200 }, 834 { B300, 300 }, 835 { B600, 600 }, 836 { B1200, 1200 }, 837 { B1800, 1800 }, 838 { B2400, 2400 }, 839 { B4800, 4800 }, 840 { B9600, 9600 }, 841 #ifdef B19200 842 { B19200, 19200 }, 843 #else /* ! defined (B19200) */ 844 #ifdef EXTA 845 { EXTA, 19200 }, 846 #endif /* EXTA */ 847 #endif /* ! defined (B19200) */ 848 #ifdef B38400 849 { B38400, 38400 } 850 #else /* ! defined (B38400) */ 851 #ifdef EXTB 852 { EXTB, 38400 } 853 #endif /* EXTB */ 854 #endif /* ! defined (B38400) */ 855 }; 856 857 #define CBAUD_TABLE (sizeof asSbaud_table / sizeof asSbaud_table[0]) 858 859 #if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 860 /* Hold the MIN value for the terminal to avoid setting it 861 unnecessarily. */ 862 static int cSmin; 863 #endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 864 865 static boolean 866 fsserial_open (z, ibaud, fwait, q) 867 const char *z; 868 long ibaud; 869 boolean fwait; 870 struct ssysdep_serial_port *q; 871 { 872 #if HAVE_POSIX_TERMIOS 873 speed_t ib; 874 #else 875 int ib; 876 #endif 877 878 if (z == NULL) 879 { 880 const char *zport; 881 boolean fdummy; 882 883 zport = zsysdep_port_name (&fdummy); 884 if (zport != NULL) 885 ulog_device (zport); 886 } 887 else 888 { 889 if (strncmp (z, "/dev/", sizeof "/dev/" - 1) == 0) 890 ulog_device (z + sizeof "/dev/" - 1); 891 else 892 ulog_device (z); 893 } 894 895 ib = B0; 896 897 if (ibaud != 0) 898 { 899 int i; 900 901 for (i = 0; i < CBAUD_TABLE; i++) 902 if (asSbaud_table[i].ibaud == ibaud) 903 break; 904 if (i >= CBAUD_TABLE) 905 { 906 ulog (LOG_ERROR, "Unsupported baud rate %ld", ibaud); 907 if (q->oread != -1) 908 { 909 (void) close (q->oread); 910 if (q->oread != q->owrite) 911 (void) close (q->owrite); 912 } 913 return FALSE; 914 } 915 ib = asSbaud_table[i].icode; 916 } 917 918 /* The port may have already been opened by the locking routine. */ 919 if (q->oread == -1) 920 { 921 int oread, owrite; 922 923 if (z == NULL) 924 { 925 oread = 0; 926 owrite = 1; 927 } 928 else 929 { 930 int iflag; 931 932 if (fwait) 933 iflag = 0; 934 else 935 iflag = FILE_UNBLOCKED; 936 937 if (*z != '/') 938 { 939 char *zcopy; 940 941 zcopy = (char *) alloca (sizeof "/dev/" + strlen (z)); 942 sprintf (zcopy, "/dev/%s", z); 943 z = zcopy; 944 } 945 946 oread = open (z, O_RDWR | iflag); 947 if (oread < 0) 948 { 949 ulog (LOG_ERROR, "open (%s): %s", z, strerror (errno)); 950 return FALSE; 951 } 952 953 #ifdef TIOCSCTTY 954 /* On BSD 4.4, make it our controlling terminal. */ 955 (void) ioctl (oread, TIOCSCTTY, 0); 956 #endif 957 958 owrite = oread; 959 } 960 961 q->oread = oread; 962 q->owrite = owrite; 963 } 964 965 /* Make sure the ports are blocking. */ 966 967 if (fcntl (q->oread, F_SETFL, 0) < 0 968 || (q->oread != q->owrite 969 && fcntl (q->owrite, F_SETFL, 0) < 0)) 970 { 971 ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); 972 (void) close (q->oread); 973 if (q->oread != q->owrite) 974 (void) close (q->owrite); 975 return FALSE; 976 } 977 978 q->fread_blocking = TRUE; 979 980 if (! fgetterminfo (q->oread, &q->sorig)) 981 { 982 q->fterminal = FALSE; 983 return TRUE; 984 } 985 986 q->fterminal = TRUE; 987 988 q->snew = q->sorig; 989 990 #if HAVE_BSD_TTY 991 992 q->snew.sg_flags = RAW | ANYP; 993 if (ibaud == 0) 994 ib = q->snew.sg_ospeed; 995 else 996 { 997 q->snew.sg_ispeed = ib; 998 q->snew.sg_ospeed = ib; 999 } 1000 1001 #ifdef TIOCHPCL 1002 /* When the file is closed, hang up the line. This is a safety 1003 measure in case the program crashes. */ 1004 (void) ioctl (q->oread, TIOCHPCL, 0); 1005 #endif 1006 1007 #ifdef TIOCFLUSH 1008 { 1009 int iparam; 1010 1011 /* Flush pending input. */ 1012 #ifdef FREAD 1013 iparam = FREAD; 1014 #else 1015 iparam = 0; 1016 #endif 1017 (void) ioctl (q->oread, TIOCFLUSH, &iparam); 1018 } 1019 #endif /* TIOCFLUSH */ 1020 1021 #endif /* HAVE_BSD_TTY */ 1022 1023 #if HAVE_SYSV_TERMIO 1024 1025 if (ibaud == 0) 1026 ib = q->snew.c_cflag & CBAUD; 1027 1028 q->snew.c_iflag &=~ ICLEAR_IFLAG; 1029 q->snew.c_oflag &=~ ICLEAR_OFLAG; 1030 q->snew.c_cflag &=~ ICLEAR_CFLAG; 1031 q->snew.c_cflag |= (ib | ISET_CFLAG); 1032 q->snew.c_lflag &=~ ICLEAR_LFLAG; 1033 cSmin = 6; 1034 q->snew.c_cc[VMIN] = cSmin; 1035 q->snew.c_cc[VTIME] = 0; 1036 1037 #ifdef TCFLSH 1038 /* Flush pending input. */ 1039 (void) ioctl (q->oread, TCFLSH, 0); 1040 #endif 1041 1042 #endif /* HAVE_SYSV_TERMIO */ 1043 1044 #if HAVE_POSIX_TERMIOS 1045 1046 if (ibaud == 0) 1047 ib = cfgetospeed (&q->snew); 1048 1049 q->snew.c_iflag &=~ ICLEAR_IFLAG; 1050 q->snew.c_oflag &=~ ICLEAR_OFLAG; 1051 q->snew.c_cflag &=~ ICLEAR_CFLAG; 1052 q->snew.c_cflag |= ISET_CFLAG; 1053 q->snew.c_lflag &=~ ICLEAR_LFLAG; 1054 cSmin = 6; 1055 q->snew.c_cc[VMIN] = cSmin; 1056 q->snew.c_cc[VTIME] = 0; 1057 1058 (void) cfsetospeed (&q->snew, ib); 1059 (void) cfsetispeed (&q->snew, ib); 1060 1061 /* Flush pending input. */ 1062 (void) tcflush (q->oread, TCIFLUSH); 1063 1064 #endif /* HAVE_POSIX_TERMIOS */ 1065 1066 if (! fsetterminfo (q->oread, &q->snew)) 1067 { 1068 ulog (LOG_ERROR, "Can't set terminal settings: %s", strerror (errno)); 1069 (void) close (q->oread); 1070 if (q->oread != q->owrite) 1071 (void) close (q->owrite); 1072 return FALSE; 1073 } 1074 1075 if (ibaud != 0) 1076 q->ibaud = ibaud; 1077 else 1078 { 1079 int i; 1080 1081 q->ibaud = 1200; 1082 for (i = 0; i < CBAUD_TABLE; i++) 1083 { 1084 if (asSbaud_table[i].icode == ib) 1085 { 1086 q->ibaud = asSbaud_table[i].ibaud; 1087 break; 1088 } 1089 } 1090 1091 DEBUG_MESSAGE1 (DEBUG_PORT, 1092 "fsserial_open: Baud rate is %ld", q->ibaud); 1093 } 1094 1095 return TRUE; 1096 } 1097 1098 /* Open a stdin port. */ 1099 1100 boolean 1101 fsysdep_stdin_open (qport, ibaud, fwait) 1102 struct sport *qport; 1103 long ibaud; 1104 boolean fwait; 1105 { 1106 return fsserial_open ((const char *) NULL, ibaud, fwait, 1107 &qport->u.sstdin.s.s); 1108 } 1109 1110 /* Open a modem port. */ 1111 1112 boolean 1113 fsysdep_modem_open (qport, ibaud, fwait) 1114 struct sport *qport; 1115 long ibaud; 1116 boolean fwait; 1117 { 1118 const char *z; 1119 boolean fret; 1120 1121 z = qport->u.smodem.zdevice; 1122 if (z == NULL) 1123 { 1124 z = qport->zname; 1125 if (z == NULL) 1126 { 1127 ulog (LOG_ERROR, "Port has no name or device"); 1128 return FALSE; 1129 } 1130 } 1131 if (ibaud == 0) 1132 ibaud = qport->u.smodem.ibaud; 1133 fret = fsserial_open (z, ibaud, fwait, &qport->u.smodem.s.s); 1134 if (! fret) 1135 (void) fsserial_lockfile (FALSE, qport, qport->u.smodem.zdevice); 1136 return fret; 1137 } 1138 1139 /* Open a direct port. */ 1140 1141 boolean 1142 fsysdep_direct_open (qport, ibaud, fwait) 1143 struct sport *qport; 1144 long ibaud; 1145 boolean fwait; 1146 { 1147 const char *z; 1148 boolean fret; 1149 1150 z = qport->u.sdirect.zdevice; 1151 if (z == NULL) 1152 { 1153 z = qport->zname; 1154 if (z == NULL) 1155 { 1156 ulog (LOG_ERROR, "Port has no name or device"); 1157 return FALSE; 1158 } 1159 } 1160 if (ibaud == 0) 1161 ibaud = qport->u.sdirect.ibaud; 1162 fret = fsserial_open (z, ibaud, fwait, &qport->u.sdirect.s.s); 1163 if (! fret) 1164 (void) fsserial_lockfile (FALSE, qport, qport->u.sdirect.zdevice); 1165 return fret; 1166 } 1167 1168 /* Change the blocking status of the port. We keep track of the 1169 current blocking status to avoid calling fcntl unnecessarily; fcntl 1170 turns out to be surprisingly expensive, at least on Ultrix. We 1171 used to keep track of the blocking status of the read port and the 1172 write port independently. Unfortunately, this is nonportable, 1173 because on BSD, and probably some other systems, unblocking a 1174 terminal applies to all descriptors to that terminal. Now, if 1175 oread != owrite, we set both. */ 1176 1177 __inline__ 1178 static boolean 1179 fsblock (qs, fblock) 1180 struct ssysdep_serial_port *qs; 1181 boolean fblock; 1182 { 1183 if (fblock ? ! qs->fread_blocking : qs->fread_blocking) 1184 { 1185 int iset; 1186 1187 if (fblock) 1188 iset = 0; 1189 else 1190 iset = FILE_UNBLOCKED; 1191 if (fcntl (qs->oread, F_SETFL, iset) < 0 1192 || (qs->oread != qs->owrite 1193 && fcntl (qs->owrite, F_SETFL, iset) < 0)) 1194 { 1195 ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); 1196 return FALSE; 1197 } 1198 qs->fread_blocking = fblock; 1199 } 1200 return TRUE; 1201 } 1202 1203 /* Close a serial port. */ 1204 1205 static boolean 1206 fsserial_close (q) 1207 struct ssysdep_serial_port *q; 1208 { 1209 if (q->oread >= 0) 1210 { 1211 /* Use a 30 second timeout to avoid hanging while draining 1212 output. */ 1213 if (q->fterminal) 1214 { 1215 fSalarm = FALSE; 1216 1217 if (fsysdep_catch ()) 1218 { 1219 usysdep_start_catch (); 1220 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 1221 (void) alarm (30); 1222 1223 (void) fsetterminfodrain (q->oread, &q->sorig); 1224 } 1225 1226 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1227 (void) alarm (0); 1228 usysdep_end_catch (); 1229 1230 /* If we timed out, use the non draining call. Hopefully 1231 this can't hang. */ 1232 if (fSalarm) 1233 (void) fsetterminfo (q->oread, &q->sorig); 1234 } 1235 1236 (void) close (q->oread); 1237 if (q->oread != q->owrite) 1238 (void) close (q->owrite); 1239 q->oread = q->owrite = -1; 1240 1241 /* Sleep for a second to give the terminal a chance to settle, 1242 in case we are about to call out again. */ 1243 sleep (1); 1244 } 1245 1246 return TRUE; 1247 } 1248 1249 /* Close a stdin port. */ 1250 1251 /*ARGSUSED*/ 1252 boolean 1253 fsysdep_stdin_close (qport, fsuccess) 1254 struct sport *qport; 1255 boolean fsuccess; 1256 { 1257 return fsserial_close (&qport->u.sstdin.s.s); 1258 } 1259 1260 /* Close a modem port. */ 1261 1262 boolean 1263 fsysdep_modem_close (qport, fsuccess) 1264 struct sport *qport; 1265 boolean fsuccess; 1266 { 1267 boolean fret; 1268 struct sdialer *qdial; 1269 struct sdialer sdial; 1270 1271 fret = TRUE; 1272 qdial = NULL; 1273 1274 /* We're no longer interested in carrier. */ 1275 (void) fsysdep_modem_no_carrier (qport); 1276 1277 if (qport->u.smodem.zdialer != NULL) 1278 { 1279 char *zcopy; 1280 1281 zcopy = (char *) alloca (strlen (qport->u.smodem.zdialer) + 1); 1282 strcpy (zcopy, qport->u.smodem.zdialer); 1283 zcopy[strcspn (zcopy, " \t")] = '\0'; 1284 if (! fread_dialer_info (zcopy, &sdial)) 1285 fret = FALSE; 1286 else 1287 qdial = &sdial; 1288 } 1289 else 1290 qdial = qport->u.smodem.qdialer; 1291 1292 if (qdial != NULL) 1293 { 1294 boolean fsighup_ignored; 1295 HELD_SIG_MASK smask; 1296 int i; 1297 sig_atomic_t afhold[INDEXSIG_COUNT]; 1298 const struct schat_info *qchat; 1299 1300 /* The port I/O routines check whether any signal has been 1301 received, and abort if one has. While we are closing down 1302 the modem, we don't care if we received a signal in the past, 1303 but we do care if we receive a new signal (otherwise it would 1304 be difficult to kill a uucico which was closing down a 1305 modem). We never care if we get SIGHUP at this point. So we 1306 turn off SIGHUP, remember what signals we've already seen, 1307 and clear our notion of what signals we've seen. We have to 1308 block the signals while we remember and clear the array, 1309 since we might otherwise miss a signal which occurred between 1310 the copy and the clear (old systems can't block signals; they 1311 will just have to suffer the race). */ 1312 1313 usset_signal (SIGHUP, SIG_IGN, FALSE, &fsighup_ignored); 1314 smask = isblocksigs (); 1315 for (i = 0; i < INDEXSIG_COUNT; i++) 1316 { 1317 afhold[i] = afSignal[i]; 1318 afSignal[i] = FALSE; 1319 } 1320 usunblocksigs (smask); 1321 1322 if (fsuccess) 1323 qchat = &qdial->scomplete; 1324 else 1325 qchat = &qdial->sabort; 1326 if (! fchat (qchat, (const struct ssysteminfo *) NULL, 1327 (const struct sdialer *) NULL, (const char *) NULL, 1328 FALSE, qport->zname, qport->u.smodem.s.s.ibaud)) 1329 fret = FALSE; 1330 1331 /* Restore the old signal array and the SIGHUP handler. It is 1332 not necessary to block signals here, since all we are doing 1333 is exactly what the signal handler itself would do if the 1334 signal occurred. */ 1335 for (i = 0; i < INDEXSIG_COUNT; i++) 1336 if (afhold[i]) 1337 afSignal[i] = TRUE; 1338 if (! fsighup_ignored) 1339 usset_signal (SIGHUP, ussignal, TRUE, (boolean *) NULL); 1340 } 1341 1342 if (! fsserial_close (&qport->u.smodem.s.s)) 1343 fret = FALSE; 1344 1345 if (! fsserial_lockfile (FALSE, qport, qport->u.smodem.zdevice)) 1346 fret = FALSE; 1347 1348 return fret; 1349 } 1350 1351 /* Close a direct port. */ 1352 1353 /*ARGSUSED*/ 1354 boolean 1355 fsysdep_direct_close (qport, fsuccess) 1356 struct sport *qport; 1357 boolean fsuccess; 1358 { 1359 boolean fret; 1360 1361 fret = fsserial_close (&qport->u.sdirect.s.s); 1362 1363 if (! fsserial_lockfile (FALSE, qport, qport->u.sdirect.zdevice)) 1364 fret = FALSE; 1365 1366 return fret; 1367 } 1368 1369 /* Reset a serial port by hanging up. */ 1370 1371 #if ! HAVE_POSIX_TERMIOS 1372 1373 static boolean 1374 fsserial_reset (q) 1375 struct ssysdep_serial_port *q; 1376 { 1377 sterminal sbaud; 1378 1379 if (! q->fterminal) 1380 return TRUE; 1381 1382 sbaud = q->snew; 1383 1384 #if HAVE_BSD_TTY 1385 sbaud.sg_ispeed = B0; 1386 sbaud.sg_ospeed = B0; 1387 #else /* ! HAVE_BSD_TTY */ 1388 sbaud.c_cflag = (sbaud.c_cflag &~ CBAUD) | B0; 1389 #endif /* ! HAVE_BSD_TTY */ 1390 1391 if (! fsetterminfodrain (q->oread, &sbaud)) 1392 ulog (LOG_FATAL, "Can't hangup terminal: %s", strerror (errno)); 1393 1394 /* Give the terminal a chance to settle. */ 1395 sleep (1); 1396 1397 if (! fsetterminfo (q->oread, &q->snew)) 1398 ulog (LOG_FATAL, "Can't reopen terminal: %s", strerror (errno)); 1399 1400 return TRUE; 1401 } 1402 1403 #else /* HAVE_POSIX_TERMIOS */ 1404 1405 static boolean 1406 fsserial_reset (q) 1407 struct ssysdep_serial_port *q; 1408 { 1409 sterminal sbaud; 1410 speed_t iin, iout; 1411 1412 if (! q->fterminal) 1413 return TRUE; 1414 1415 iin = cfgetispeed (&q->snew); 1416 iout = cfgetospeed (&q->snew); 1417 1418 sbaud = q->snew; 1419 1420 if (cfsetospeed (&sbaud, B0) != 0 1421 || ! fsetterminfodrain (q->oread, &sbaud)) 1422 ulog (LOG_FATAL, "Can't hangup terminal: %s", strerror (errno)); 1423 1424 /* Give the terminal a chance to settle. */ 1425 sleep (1); 1426 1427 if (cfsetispeed (&q->snew, iin) != 0 1428 || cfsetospeed (&q->snew, iout) != 0 1429 || ! fsetterminfo (q->oread, &q->snew)) 1430 ulog (LOG_FATAL, "Can't reopen terminal: %s", strerror (errno)); 1431 1432 return TRUE; 1433 } 1434 1435 #endif /* HAVE_POSIX_TERMIOS */ 1436 1437 /* Reset a stdin port. */ 1438 1439 boolean 1440 fsysdep_stdin_reset (qport) 1441 struct sport *qport; 1442 { 1443 return fsserial_reset (&qport->u.sstdin.s.s); 1444 } 1445 1446 /* Reset a modem port. */ 1447 1448 boolean 1449 fsysdep_modem_reset (qport) 1450 struct sport *qport; 1451 { 1452 return fsserial_reset (&qport->u.smodem.s.s); 1453 } 1454 1455 /* Reset a direct port. */ 1456 1457 boolean 1458 fsysdep_direct_reset (qport) 1459 struct sport *qport; 1460 { 1461 return fsserial_reset (&qport->u.sdirect.s.s); 1462 } 1463 1464 /* Begin dialing out on a modem port. This opens the dialer device if 1465 there is one. */ 1466 1467 boolean 1468 fsysdep_modem_begin_dial (qport, qdial) 1469 struct sport *qport; 1470 struct sdialer *qdial; 1471 { 1472 #ifdef TIOCMODEM 1473 /* If we can tell the modem to obey modem control, do so. */ 1474 { 1475 int iperm; 1476 1477 iperm = 0; 1478 (void) ioctl (qport->u.smodem.s.s.oread, TIOCMODEM, &iperm); 1479 } 1480 #endif /* TIOCMODEM */ 1481 1482 #ifdef TIOCCDTR 1483 /* If we supposed to toggle DTR, do so. */ 1484 1485 if (qdial->fdtr_toggle) 1486 { 1487 (void) ioctl (qport->u.smodem.s.s.oread, TIOCCDTR, 0); 1488 (void) ioctl (qport->u.smodem.s.s.oread, TIOCSDTR, 0); 1489 1490 if (qdial->fdtr_toggle_wait) 1491 sleep (1); 1492 } 1493 #endif /* TIOCCDTR */ 1494 1495 if (! fsysdep_modem_no_carrier (qport)) 1496 return FALSE; 1497 1498 /* Open the dial device if there is one. */ 1499 if (qport->u.smodem.zdial_device != NULL) 1500 { 1501 const char *z; 1502 int oread; 1503 1504 qport->u.smodem.s.s.oholdread = qport->u.smodem.s.s.oread; 1505 qport->u.smodem.s.s.oholdwrite = qport->u.smodem.s.s.owrite; 1506 1507 z = qport->u.smodem.zdial_device; 1508 if (*z != '/') 1509 { 1510 char *zcopy; 1511 1512 zcopy = (char *) alloca (sizeof "/dev/" + strlen (z)); 1513 sprintf (zcopy, "/dev/%s", z); 1514 z = zcopy; 1515 } 1516 1517 oread = open (z, O_RDWR); 1518 if (oread < 0) 1519 { 1520 ulog (LOG_ERROR, "open (%s): %s", z, strerror (errno)); 1521 return FALSE; 1522 } 1523 1524 qport->u.smodem.s.s.oread = qport->u.smodem.s.s.owrite = oread; 1525 } 1526 1527 return TRUE; 1528 } 1529 1530 /* Tell the port to not require carrier. I don't know how to do this 1531 on a BSD system that doesn't support TIOCNCAR, if there are any 1532 such systems. */ 1533 1534 boolean 1535 fsysdep_modem_no_carrier (qport) 1536 struct sport *qport; 1537 { 1538 if (! qport->u.smodem.s.s.fterminal) 1539 return TRUE; 1540 1541 #ifdef TIOCNCAR 1542 /* Tell the modem to ignore carrier. */ 1543 if (ioctl (qport->u.smodem.s.s.oread, TIOCNCAR, 0) < 0) 1544 { 1545 ulog (LOG_ERROR, "ioctl (TIOCNCAR): %s", strerror (errno)); 1546 return FALSE; 1547 } 1548 #endif /* TIOCNCAR */ 1549 1550 #if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1551 /* Put the modem into local mode (ignore carrier) to start the chat 1552 script. */ 1553 qport->u.smodem.s.s.snew.c_cflag |= CLOCAL; 1554 if (! fsetterminfo (qport->u.smodem.s.s.oread, 1555 &qport->u.smodem.s.s.snew)) 1556 { 1557 ulog (LOG_ERROR, "Can't set CLOCAL: %s", strerror (errno)); 1558 return FALSE; 1559 } 1560 #endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1561 1562 return TRUE; 1563 } 1564 1565 /* Tell the port to require carrier. If the port does not support 1566 carrier, we do nothing. We do not need to worry whether the 1567 dialer supports carrier, since this will only be called when 1568 explicitly requested by a dialer chat script. */ 1569 1570 boolean 1571 fsysdep_modem_need_carrier (qport) 1572 struct sport *qport; 1573 { 1574 if (! qport->u.smodem.s.s.fterminal) 1575 return TRUE; 1576 1577 if (qport->u.smodem.fcarrier) 1578 { 1579 #ifdef TIOCCAR 1580 /* Tell the modem to pay attention to carrier. */ 1581 if (ioctl (qport->u.smodem.s.s.oread, TIOCCAR, 0) < 0) 1582 { 1583 ulog (LOG_ERROR, "ioctl (TIOCCAR): %s", strerror (errno)); 1584 return FALSE; 1585 } 1586 #endif /* TIOCCAR */ 1587 1588 #if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1589 /* Put the modem into nonlocal mode. */ 1590 qport->u.smodem.s.s.snew.c_cflag &=~ CLOCAL; 1591 if (! fsetterminfo (qport->u.smodem.s.s.oread, 1592 &qport->u.smodem.s.s.snew)) 1593 { 1594 ulog (LOG_ERROR, "Can't clear CLOCAL: %s", strerror (errno)); 1595 return FALSE; 1596 } 1597 #endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1598 } 1599 1600 return TRUE; 1601 } 1602 1603 /* Finish dialing out on a modem by closing any dialer device and waiting 1604 for carrier. */ 1605 1606 boolean 1607 fsysdep_modem_end_dial (qport, qdial) 1608 struct sport *qport; 1609 struct sdialer *qdial; 1610 { 1611 if (qport->u.smodem.zdial_device != NULL) 1612 { 1613 (void) close (qport->u.smodem.s.s.oread); 1614 qport->u.smodem.s.s.oread = qport->u.smodem.s.s.oholdread; 1615 qport->u.smodem.s.s.owrite = qport->u.smodem.s.s.oholdwrite; 1616 } 1617 1618 if (qport->u.smodem.fcarrier && qdial->fcarrier) 1619 { 1620 /* Tell the port that we need carrier. */ 1621 1622 if (! fsysdep_modem_need_carrier (qport)) 1623 return FALSE; 1624 1625 #ifdef TIOCWONLINE 1626 1627 /* We know how to wait for carrier, so do so. */ 1628 1629 /* If we already got a signal, just quit now. */ 1630 if (FGOT_QUIT_SIGNAL ()) 1631 return FALSE; 1632 1633 /* This bit of code handles signals just like fsserial_read 1634 does. See that function for a longer explanation. */ 1635 1636 /* Use fsysdep_catch to handle a longjmp from the signal 1637 handler. */ 1638 1639 fSalarm = FALSE; 1640 1641 if (fsysdep_catch ()) 1642 { 1643 /* Start catching SIGALRM; normally we ignore it. */ 1644 usysdep_start_catch (); 1645 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 1646 (void) alarm (qdial->ccarrier_wait); 1647 1648 /* We really don't care if we get an error, since that will 1649 probably just mean that TIOCWONLINE isn't supported in 1650 which case there's nothing we can do anyhow. If we get 1651 SIGINT we want to keep waiting for carrier, because 1652 SIGINT just means don't start any new sessions. We don't 1653 handle SIGINT correctly if we do a longjmp in the signal 1654 handler; too bad. */ 1655 while (ioctl (qport->u.smodem.s.s.oread, TIOCWONLINE, 0) < 0 1656 && errno == EINTR) 1657 { 1658 /* Log the signal. */ 1659 ulog (LOG_ERROR, (const char *) NULL); 1660 if (FGOT_QUIT_SIGNAL () || fSalarm) 1661 break; 1662 } 1663 } 1664 1665 /* Turn off the pending SIGALRM and ignore SIGALARM again. */ 1666 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1667 (void) alarm (0); 1668 usysdep_end_catch (); 1669 1670 /* If we got a random signal, just return FALSE. */ 1671 if (FGOT_QUIT_SIGNAL ()) 1672 return FALSE; 1673 1674 /* If we timed out, give an error. */ 1675 if (fSalarm) 1676 { 1677 ulog (LOG_ERROR, "Timed out waiting for carrier"); 1678 return FALSE; 1679 } 1680 1681 #endif /* TIOCWONLINE */ 1682 } 1683 1684 return TRUE; 1685 } 1686 1687 /* Read data from a serial port, with a timeout. 1688 1689 This function should return when we have read cmin characters or 1690 the timeout has occurred. We have to work a bit to get UNIX to do 1691 this efficiently. The simple implementation schedules a SIGALRM 1692 signal and then calls read; if there is a single character 1693 available, the call to read will return immediately, so there must 1694 be a loop which terminates when the SIGALRM is delivered or the 1695 correct number of characters has been read. This can be very 1696 inefficient with a fast CPU or a low baud rate (or both!), since 1697 each call to read may return only one or two characters. 1698 1699 Under POSIX or System V, we can specify a minimum number of 1700 characters to read, so there is no serious trouble. 1701 1702 Under BSD, we figure out how many characters we have left to read, 1703 how long it will take for them to arrive at the current baud rate, 1704 and sleep that long. 1705 1706 Doing this with a timeout and avoiding all possible race conditions 1707 get very hairy, though. Basically, we're going to schedule a 1708 SIGALRM for when the timeout expires. I don't really want to do a 1709 longjmp in the SIGALRM handler, though, because that may lose data. 1710 Therefore, I have the signal handler set a variable. However, this 1711 means that there will be a span of time between the time the code 1712 checks the variable and the time it calls the read system call; if 1713 the SIGALRM occurs during that time, the read might hang forever. 1714 To avoid this, the SIGALRM handler not only sets a global variable, 1715 it also schedules another SIGALRM for one second in the future 1716 (POSIX specifies that a signal handler is permitted to safely call 1717 alarm). To avoid getting a continual sequence of SIGALRM 1718 interrupts, we change the signal handler to ignore SIGALRM when 1719 we're about to exit the function. This means that every time we 1720 execute fsserial_read we make at least five system calls. It's the 1721 best I've been able to come up with, though. 1722 1723 When fsserial_read finishes, there will be no SIGALRM scheduled and 1724 SIGALRM will be ignored. */ 1725 1726 static boolean 1727 fsserial_read (q, zbuf, pclen, cmin, ctimeout, freport, fpty) 1728 struct ssysdep_serial_port *q; 1729 char *zbuf; 1730 int *pclen; 1731 int cmin; 1732 int ctimeout; 1733 boolean freport; 1734 boolean fpty; 1735 { 1736 CATCH_PROTECT int cwant; 1737 boolean fret; 1738 1739 cwant = *pclen; 1740 *pclen = 0; 1741 1742 /* Guard against a bad timeout. We return TRUE when a timeout 1743 expires. It is possible to get a negative timeout here because 1744 the calling code does not check user supplied timeouts for 1745 plausibility. */ 1746 if (ctimeout <= 0) 1747 return TRUE; 1748 1749 /* We want to do a blocking read. */ 1750 if (! fsblock (q, TRUE)) 1751 return FALSE; 1752 1753 fSalarm = FALSE; 1754 1755 /* We're going to set up an alarm signal to last for the entire 1756 read. If the read system call cannot be interrupted, the signal 1757 handler will do a longjmp causing fsysdep_catch (a macro) to 1758 return FALSE. We handle that here. If read can be interrupted, 1759 fsysdep_catch will be defined to TRUE. */ 1760 1761 if (fsysdep_catch ()) 1762 { 1763 /* Prepare to catch SIGALRM and schedule the signal. */ 1764 usysdep_start_catch (); 1765 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 1766 alarm (ctimeout); 1767 } 1768 else 1769 { 1770 /* We caught a signal. We don't actually have to do anything, 1771 as all the appropriate checks are made at the start of the 1772 following loop. */ 1773 } 1774 1775 fret = FALSE; 1776 1777 while (TRUE) 1778 { 1779 int cgot; 1780 1781 #if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1782 /* If we can tell the terminal not to return until we have a 1783 certain number of characters, do so. */ 1784 if (q->fterminal) 1785 { 1786 int csetmin; 1787 1788 /* I'm not that confident about setting MIN to values larger 1789 than 127, although up to 255 would probably work. */ 1790 if (cmin < 127) 1791 csetmin = cmin; 1792 else 1793 csetmin = 127; 1794 1795 if (csetmin != cSmin) 1796 { 1797 q->snew.c_cc[VMIN] = csetmin; 1798 if (! fsetterminfo (q->oread, &q->snew)) 1799 { 1800 int ierr; 1801 1802 /* We turn off the signal before reporting the error 1803 to minimize any problems with interrupted system 1804 calls. */ 1805 ierr = errno; 1806 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1807 alarm (0); 1808 usysdep_end_catch (); 1809 ulog (LOG_ERROR, "Can't set MIN for terminal: %s", 1810 strerror (ierr)); 1811 return FALSE; 1812 } 1813 cSmin = csetmin; 1814 } 1815 } 1816 #endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1817 1818 /* If we've received a signal, get out now. */ 1819 if (FGOT_QUIT_SIGNAL ()) 1820 break; 1821 1822 /* If we've already gotten a SIGALRM, get out with whatever 1823 we've accumulated. */ 1824 1825 if (fSalarm) 1826 { 1827 fret = TRUE; 1828 break; 1829 } 1830 1831 /* Right here is the race condition which we avoid by having the 1832 SIGALRM handler schedule another SIGALRM. */ 1833 1834 cgot = read (q->oread, zbuf, cwant); 1835 1836 /* If the read returned an error, check for signals. */ 1837 if (cgot < 0) 1838 { 1839 if (errno == EINTR) 1840 { 1841 /* Log the signal. */ 1842 ulog (LOG_ERROR, (const char *) NULL); 1843 } 1844 if (fSalarm) 1845 { 1846 fret = TRUE; 1847 break; 1848 } 1849 if (FGOT_QUIT_SIGNAL ()) 1850 break; 1851 } 1852 1853 /* If read returned an error, get out. We just ignore EINTR 1854 here, since it must be from some signal we don't care about. 1855 If the read returned 0 then the line must have been hung up 1856 (normally we would have received SIGHUP, but we can't count 1857 on that). We turn off the signals before calling ulog to 1858 reduce problems with interrupted system calls. */ 1859 if (cgot <= 0) 1860 { 1861 if (cgot < 0 && errno == EINTR) 1862 cgot = 0; 1863 else 1864 { 1865 int ierr; 1866 1867 ierr = errno; 1868 1869 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1870 alarm (0); 1871 usysdep_end_catch (); 1872 1873 if (freport) 1874 { 1875 if (cgot == 0) 1876 ulog (LOG_ERROR, "Line disconnected"); 1877 else 1878 ulog (LOG_ERROR, "read: %s", strerror (ierr)); 1879 } 1880 1881 return FALSE; 1882 } 1883 } 1884 1885 cwant -= cgot; 1886 cmin -= cgot; 1887 zbuf += cgot; 1888 *pclen += cgot; 1889 1890 /* If we have enough data, get out now. */ 1891 1892 if (cmin <= 0) 1893 { 1894 fret = TRUE; 1895 break; 1896 } 1897 1898 #if HAVE_BSD_TTY 1899 /* We still want more data, so sleep long enough for the rest of 1900 it to arrive. We don't this for System V or POSIX because 1901 setting MIN is good enough (we can't sleep longer than it 1902 takes to get MAX_INPUT characters anyhow). 1903 1904 The baud rate is approximately 10 times the number of 1905 characters which will arrive in one second, so the number of 1906 milliseconds to sleep == 1907 characters * (milliseconds / character) == 1908 characters * (1000 * (seconds / character)) == 1909 characters * (1000 * (1 / (baud / 10))) == 1910 characters * (10000 / baud) 1911 1912 We arbitrarily reduce the sleep amount by 10 milliseconds to 1913 attempt to account for the amount of time it takes to set up 1914 the sleep. This is how long it takes to get half a character 1915 at 19200 baud. We then don't bother to sleep for less than 1916 10 milliseconds. We don't sleep if the read was interrupted. 1917 1918 We use select to sleep. It would be easy to use poll as 1919 well, but it's unlikely that any system with BSD ttys would 1920 have poll but not select. Using select avoids hassles with 1921 the pending SIGALRM; if it hits the select will be 1922 interrupted, and otherwise the select will not affect it. */ 1923 1924 #if ! HAVE_SELECT 1925 #error This code requires select; feel free to extend it 1926 #endif 1927 1928 if (q->fterminal && ! fpty && cmin > 1 && cgot > 0) 1929 { 1930 int csleepchars; 1931 int isleep; 1932 1933 /* We don't try to read all the way up to MAX_INPUT, 1934 since that might drop a character. */ 1935 1936 if (cmin <= MAX_INPUT - 10) 1937 csleepchars = cmin; 1938 else 1939 csleepchars = MAX_INPUT - 10; 1940 1941 isleep = (int) (((long) csleepchars * 10000L) / q->ibaud); 1942 isleep -= 10; 1943 1944 if (isleep > 10) 1945 { 1946 struct timeval s; 1947 1948 s.tv_sec = isleep / 1000; 1949 s.tv_usec = (isleep % 1000) * 1000; 1950 1951 /* Some versions of select take a pointer to an int, 1952 while some take a pointer to an fd_set. I just cast 1953 the arguments to a generic pointer, and assume that 1954 any machine which distinguishes int * from fd_set * 1955 (I would be amazed if there are any such machines) 1956 have an appropriate prototype somewhere or other. */ 1957 (void) select (0, (pointer) NULL, (pointer) NULL, 1958 (pointer) NULL, &s); 1959 1960 /* Here either the select finished sleeping or we got a 1961 SIGALRM. If the latter occurred, fSalarm was set to 1962 TRUE; it will be checked at the top of the loop. */ 1963 } 1964 } 1965 #endif /* HAVE_BSD_TTY */ 1966 } 1967 1968 /* Turn off the pending SIGALRM and return. */ 1969 1970 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1971 alarm (0); 1972 usysdep_end_catch (); 1973 1974 return fret; 1975 } 1976 1977 /* Read from a stdin port. */ 1978 1979 boolean 1980 fsysdep_stdin_read (qport, zbuf, pclen, cmin, ctimeout, freport) 1981 struct sport *qport; 1982 char *zbuf; 1983 int *pclen; 1984 int cmin; 1985 int ctimeout; 1986 boolean freport; 1987 { 1988 return fsserial_read (&qport->u.sstdin.s.s, zbuf, pclen, cmin, ctimeout, 1989 freport, qport->u.sstdin.s.fpty); 1990 } 1991 1992 /* Read from a modem port. */ 1993 1994 boolean 1995 fsysdep_modem_read (qport, zbuf, pclen, cmin, ctimeout, freport) 1996 struct sport *qport; 1997 char *zbuf; 1998 int *pclen; 1999 int cmin; 2000 int ctimeout; 2001 boolean freport; 2002 { 2003 return fsserial_read (&qport->u.smodem.s.s, zbuf, pclen, cmin, ctimeout, 2004 freport, FALSE); 2005 } 2006 2007 /* Read from a direct port. */ 2008 2009 boolean 2010 fsysdep_direct_read (qport, zbuf, pclen, cmin, ctimeout, freport) 2011 struct sport *qport; 2012 char *zbuf; 2013 int *pclen; 2014 int cmin; 2015 int ctimeout; 2016 boolean freport; 2017 { 2018 return fsserial_read (&qport->u.sdirect.s.s, zbuf, pclen, cmin, ctimeout, 2019 freport, FALSE); 2020 } 2021 2022 /* Write data to a serial port. */ 2023 2024 static boolean 2025 fsserial_write (q, zwrite, cwrite) 2026 struct ssysdep_serial_port *q; 2027 const char *zwrite; 2028 int cwrite; 2029 { 2030 int czero; 2031 2032 /* We want blocking writes here. */ 2033 if (! fsblock (q, TRUE)) 2034 return FALSE; 2035 2036 czero = 0; 2037 2038 while (cwrite > 0) 2039 { 2040 int cdid; 2041 2042 /* If we've received a signal, don't continue. */ 2043 if (FGOT_QUIT_SIGNAL ()) 2044 return FALSE; 2045 2046 /* Loop until we don't get an interrupt. */ 2047 while ((cdid = write (q->owrite, zwrite, cwrite)) < 0 2048 && errno == EINTR) 2049 { 2050 /* Log the signal. */ 2051 ulog (LOG_ERROR, (const char *) NULL); 2052 if (FGOT_QUIT_SIGNAL ()) 2053 return FALSE; 2054 } 2055 2056 if (cdid < 0) 2057 { 2058 if (errno != EWOULDBLOCK && errno != EAGAIN) 2059 { 2060 ulog (LOG_ERROR, "write: %s", strerror (errno)); 2061 return FALSE; 2062 } 2063 cdid = 0; 2064 } 2065 2066 if (cdid == 0) 2067 { 2068 /* On some systems write will return 0 if carrier is lost. 2069 If we fail to write anything ten times in a row, we 2070 assume that this has happened. This is hacked in like 2071 this because there seems to be no reliable way to tell 2072 exactly why the write returned 0. */ 2073 ++czero; 2074 if (czero >= 10) 2075 { 2076 ulog (LOG_ERROR, "Line disconnected"); 2077 return FALSE; 2078 } 2079 } 2080 else 2081 { 2082 czero = 0; 2083 2084 cwrite -= cdid; 2085 zwrite += cdid; 2086 } 2087 } 2088 2089 return TRUE; 2090 } 2091 2092 /* Write to a stdin port. */ 2093 2094 boolean 2095 fsysdep_stdin_write (qport, zwrite, cwrite) 2096 struct sport *qport; 2097 const char *zwrite; 2098 int cwrite; 2099 { 2100 return fsserial_write (&qport->u.sstdin.s.s, zwrite, cwrite); 2101 } 2102 2103 /* Write to a modem port. */ 2104 2105 boolean 2106 fsysdep_modem_write (qport, zwrite, cwrite) 2107 struct sport *qport; 2108 const char *zwrite; 2109 int cwrite; 2110 { 2111 return fsserial_write (&qport->u.smodem.s.s, zwrite, cwrite); 2112 } 2113 2114 /* Write to a direct port. */ 2115 2116 boolean 2117 fsysdep_direct_write (qport, zwrite, cwrite) 2118 struct sport *qport; 2119 const char *zwrite; 2120 int cwrite; 2121 { 2122 return fsserial_write (&qport->u.sdirect.s.s, zwrite, cwrite); 2123 } 2124 2125 /* The fsysdep_io routine is supposed to both read and write data 2126 until it has either filled its read buffer or written out all the 2127 data it was given. This lets us write out large packets without 2128 losing incoming data. */ 2129 2130 static boolean 2131 fsserial_io (q, zwrite, pcwrite, zread, pcread) 2132 struct ssysdep_serial_port *q; 2133 const char *zwrite; 2134 int *pcwrite; 2135 char *zread; 2136 int *pcread; 2137 { 2138 int cwrite, cread, czero; 2139 2140 cwrite = *pcwrite; 2141 *pcwrite = 0; 2142 cread = *pcread; 2143 *pcread = 0; 2144 2145 czero = 0; 2146 2147 while (TRUE) 2148 { 2149 int cgot, cdo, cdid; 2150 2151 /* If we've received a signal, don't continue. */ 2152 if (FGOT_QUIT_SIGNAL ()) 2153 return FALSE; 2154 2155 /* This used to always use nonblocking writes, but it turns out 2156 that some systems don't support them on terminals. 2157 2158 The current algorithm is: 2159 loop: 2160 unblocked read 2161 if read buffer full, return 2162 if nothing to write, return 2163 if HAVE_UNBLOCKED_WRITES 2164 write all data 2165 else 2166 write up to SINGLE_WRITE bytes 2167 if all data written, return 2168 if no data written 2169 blocked write of up to SINGLE_WRITE bytes 2170 2171 This algorithm should work whether the system supports 2172 unblocked writes on terminals or not. If the system supports 2173 unblocked writes but HAVE_UNBLOCKED_WRITES is 0, then it will 2174 call write more often than it needs to. If the system does 2175 not support unblocked writes but HAVE_UNBLOCKED_WRITES is 1, 2176 then the write may hang so long that incoming data is lost. 2177 This is actually possible at high baud rates on any system 2178 when a blocking write is done; there is no solution, except 2179 hardware handshaking. */ 2180 2181 /* Do an unblocked read. */ 2182 2183 if (! fsblock (q, FALSE)) 2184 return FALSE; 2185 2186 /* Loop until we get something (error or data) other than an 2187 acceptable EINTR. */ 2188 while ((cgot = read (q->oread, zread, cread)) < 0 2189 && errno == EINTR) 2190 { 2191 /* Log the signal. */ 2192 ulog (LOG_ERROR, (const char *) NULL); 2193 if (FGOT_QUIT_SIGNAL ()) 2194 return FALSE; 2195 } 2196 2197 if (cgot < 0) 2198 { 2199 if (errno != EAGAIN && errno != EWOULDBLOCK) 2200 { 2201 ulog (LOG_ERROR, "read: %s", strerror (errno)); 2202 return FALSE; 2203 } 2204 cgot = 0; 2205 } 2206 2207 cread -= cgot; 2208 zread += cgot; 2209 *pcread += cgot; 2210 2211 /* If we've filled the read buffer, or we have nothing left to 2212 write, return out. */ 2213 2214 if (cread <= 0 || cwrite <= 0) 2215 return TRUE; 2216 2217 /* The port is currently unblocked. Do a write. */ 2218 2219 cdo = cwrite; 2220 2221 #if ! HAVE_UNBLOCKED_WRITES 2222 if (cdo > SINGLE_WRITE) 2223 cdo = SINGLE_WRITE; 2224 #endif 2225 2226 /* Loop until we get something besides EINTR. */ 2227 while ((cdid = write (q->owrite, zwrite, cdo)) < 0 2228 && errno == EINTR) 2229 { 2230 /* Log the signal. */ 2231 ulog (LOG_ERROR, (const char *) NULL); 2232 if (FGOT_QUIT_SIGNAL ()) 2233 return FALSE; 2234 } 2235 2236 if (cdid < 0) 2237 { 2238 if (errno != EWOULDBLOCK && errno != EAGAIN) 2239 { 2240 ulog (LOG_ERROR, "write: %s", strerror (errno)); 2241 return FALSE; 2242 } 2243 cdid = 0; 2244 } 2245 2246 if (cdid > 0) 2247 { 2248 /* We wrote some data. If we wrote everything, return out. 2249 Otherwise loop around and do another read. */ 2250 cwrite -= cdid; 2251 zwrite += cdid; 2252 *pcwrite += cdid; 2253 2254 if (cwrite <= 0) 2255 return TRUE; 2256 2257 czero = 0; 2258 } 2259 else 2260 { 2261 /* We didn't write any data. Do a blocking write. */ 2262 2263 if (! fsblock (q, TRUE)) 2264 return FALSE; 2265 2266 cdo = cwrite; 2267 if (cdo > SINGLE_WRITE) 2268 cdo = SINGLE_WRITE; 2269 2270 DEBUG_MESSAGE1 (DEBUG_PORT, 2271 "fsserial_io: Blocking write of %d", cdo); 2272 2273 /* Loop until we get something besides EINTR. */ 2274 while ((cdid = write (q->owrite, zwrite, cdo)) < 0 2275 && errno == EINTR) 2276 { 2277 /* Log the signal. */ 2278 ulog (LOG_ERROR, (const char *) NULL); 2279 if (FGOT_QUIT_SIGNAL ()) 2280 return FALSE; 2281 } 2282 2283 if (cdid < 0) 2284 { 2285 ulog (LOG_ERROR, "write: %s", strerror (errno)); 2286 return FALSE; 2287 } 2288 2289 if (cdid == 0) 2290 { 2291 /* On some systems write will return 0 if carrier is 2292 lost. If we fail to write anything ten times in a 2293 row, we assume that this has happened. This is 2294 hacked in like this because there seems to be no 2295 reliable way to tell exactly why the write returned 2296 0. */ 2297 ++czero; 2298 if (czero >= 10) 2299 { 2300 ulog (LOG_ERROR, "Line disconnected"); 2301 return FALSE; 2302 } 2303 } 2304 else 2305 { 2306 cwrite -= cdid; 2307 zwrite += cdid; 2308 *pcwrite += cdid; 2309 czero = 0; 2310 } 2311 } 2312 } 2313 } 2314 2315 /* I/O to a stdin port. */ 2316 2317 boolean 2318 fsysdep_stdin_io (qport, zwrite, pcwrite, zread, pcread) 2319 struct sport *qport; 2320 const char *zwrite; 2321 int *pcwrite; 2322 char *zread; 2323 int *pcread; 2324 { 2325 return fsserial_io (&qport->u.sstdin.s.s, zwrite, pcwrite, zread, pcread); 2326 } 2327 2328 /* I/O to a modem port. */ 2329 2330 boolean 2331 fsysdep_modem_io (qport, zwrite, pcwrite, zread, pcread) 2332 struct sport *qport; 2333 const char *zwrite; 2334 int *pcwrite; 2335 char *zread; 2336 int *pcread; 2337 { 2338 return fsserial_io (&qport->u.smodem.s.s, zwrite, pcwrite, zread, pcread); 2339 } 2340 2341 /* I/O to a direct port. */ 2342 2343 boolean 2344 fsysdep_direct_io (qport, zwrite, pcwrite, zread, pcread) 2345 struct sport *qport; 2346 const char *zwrite; 2347 int *pcwrite; 2348 char *zread; 2349 int *pcread; 2350 { 2351 return fsserial_io (&qport->u.sdirect.s.s, zwrite, pcwrite, zread, pcread); 2352 } 2353 2354 /* Send a break character to a serial port. */ 2355 2356 static boolean 2357 fsserial_break (q) 2358 struct ssysdep_serial_port *q; 2359 { 2360 #if HAVE_BSD_TTY 2361 ioctl (q->owrite, TIOCSBRK, 0); 2362 sleep (1); 2363 ioctl (q->owrite, TIOCCBRK, 0); 2364 return TRUE; 2365 #endif /* HAVE_BSD_TTY */ 2366 #if HAVE_SYSV_TERMIO 2367 ioctl (q->owrite, TCSBRK, 0); 2368 return TRUE; 2369 #endif /* HAVE_SYSV_TERMIO */ 2370 #if HAVE_POSIX_TERMIOS 2371 return tcsendbreak (q->owrite, 0) == 0; 2372 #endif /* HAVE_POSIX_TERMIOS */ 2373 } 2374 2375 /* Send a break character to a stdin port. */ 2376 2377 boolean 2378 fsysdep_stdin_break (qport) 2379 struct sport *qport; 2380 { 2381 return fsserial_break (&qport->u.sstdin.s.s); 2382 } 2383 2384 /* Send a break character to a modem port. */ 2385 2386 boolean 2387 fsysdep_modem_break (qport) 2388 struct sport *qport; 2389 { 2390 return fsserial_break (&qport->u.smodem.s.s); 2391 } 2392 2393 /* Send a break character to a direct port. */ 2394 2395 boolean 2396 fsysdep_direct_break (qport) 2397 struct sport *qport; 2398 { 2399 return fsserial_break (&qport->u.sdirect.s.s); 2400 } 2401 2402 /* Change the setting of a serial port. */ 2403 2404 static boolean 2405 fsserial_set (q, tset) 2406 struct ssysdep_serial_port *q; 2407 enum tportsetting tset; 2408 { 2409 if (! q->fterminal) 2410 return TRUE; 2411 2412 switch (tset) 2413 { 2414 case PORTSETTING_EIGHT: 2415 #if HAVE_BSD_TTY 2416 if (q->snew.sg_flags == (RAW | ANYP)) 2417 return TRUE; 2418 q->snew.sg_flags = RAW | ANYP; 2419 #endif 2420 #if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 2421 if ((q->snew.c_iflag & ICLEAR_IFLAG) == 0) 2422 return TRUE; 2423 q->snew.c_iflag &=~ ICLEAR_IFLAG; 2424 #endif 2425 if (! fsetterminfodrain (q->oread, &q->snew)) 2426 { 2427 ulog (LOG_ERROR, "Can't go to raw mode: %s", strerror (errno)); 2428 return FALSE; 2429 } 2430 return TRUE; 2431 2432 case PORTSETTING_SEVEN: 2433 #if HAVE_BSD_TTY 2434 if (q->snew.sg_flags == (CBREAK | ANYP | TANDEM)) 2435 return TRUE; 2436 q->snew.sg_flags = CBREAK | ANYP | TANDEM; 2437 #endif /* HAVE_BSD_TTY */ 2438 #if HAVE_SYSV_TERMIO | HAVE_POSIX_TERMIOS 2439 { 2440 int iwant; 2441 2442 #ifdef CRTSCTS 2443 /* It would be nice to do this is in a more portable fashion, 2444 but in any case this is apparently correct for SunOS. If 2445 we are doing hardware flow control, we don't also send 2446 start and stop characters; however, we do recognize 2447 incoming start and stop characters. */ 2448 if ((q->snew.c_cflag & CRTSCTS) != 0) 2449 iwant = ISTRIP | IXON; 2450 else 2451 iwant = ISTRIP | IXON | IXOFF; 2452 #else /* ! defined (CRTSCTS) */ 2453 iwant = ISTRIP | IXON | IXOFF; 2454 #endif /* ! defined (CRTSCTS) */ 2455 2456 if ((q->snew.c_iflag & ICLEAR_IFLAG) == iwant) 2457 return TRUE; 2458 2459 q->snew.c_iflag &=~ ICLEAR_IFLAG; 2460 q->snew.c_iflag |= iwant; 2461 } 2462 #endif /* HAVE_SYSV_TERMIO | HAVE_POSIX_TERMIOS */ 2463 2464 if (! fsetterminfodrain (q->oread, &q->snew)) 2465 { 2466 ulog (LOG_ERROR, "Can't go to seven bit mode: %s", 2467 strerror (errno)); 2468 return FALSE; 2469 } 2470 return TRUE; 2471 2472 default: 2473 #if DEBUG > 0 2474 ulog (LOG_FATAL, "fsserial_set: Can't happen"); 2475 #endif 2476 return FALSE; 2477 } 2478 } 2479 2480 /* Change settings of a stdin port. */ 2481 2482 boolean 2483 fsysdep_stdin_set (qport, tset) 2484 struct sport *qport; 2485 enum tportsetting tset; 2486 { 2487 return fsserial_set (&qport->u.sstdin.s.s, tset); 2488 } 2489 2490 /* Change settings of a modem port. */ 2491 2492 boolean 2493 fsysdep_modem_set (qport, tset) 2494 struct sport *qport; 2495 enum tportsetting tset; 2496 { 2497 return fsserial_set (&qport->u.smodem.s.s, tset); 2498 } 2499 2500 /* Change settings of a direct port. */ 2501 2502 boolean 2503 fsysdep_direct_set (qport, tset) 2504 struct sport *qport; 2505 enum tportsetting tset; 2506 { 2507 return fsserial_set (&qport->u.sdirect.s.s, tset); 2508 } 2509 2510 /* Run a chat program. */ 2511 2512 static boolean 2513 fsrun_chat (oread, owrite, zprog) 2514 int oread; 2515 int owrite; 2516 const char *zprog; 2517 { 2518 int cargs; 2519 const char **azargs; 2520 char *zcopy, *zarg; 2521 int aidescs[3]; 2522 FILE *e; 2523 pid_t ipid; 2524 char *z; 2525 2526 /* Get the arguments into an array to pass to isspawn. */ 2527 zcopy = (char *) alloca (strlen (zprog) + 1); 2528 strcpy (zcopy, zprog); 2529 cargs = 0; 2530 for (zarg = strtok (zcopy, " \t"); 2531 zarg != NULL; 2532 zarg = strtok ((char *) NULL, " \t")) 2533 ++cargs; 2534 2535 azargs = (const char **) alloca ((cargs + 1) * sizeof (const char *)); 2536 2537 strcpy (zcopy, zprog); 2538 cargs = 0; 2539 for (zarg = strtok (zcopy, " \t"); 2540 zarg != NULL; 2541 zarg = strtok ((char *) NULL, " \t")) 2542 { 2543 azargs[cargs] = zarg; 2544 ++cargs; 2545 } 2546 azargs[cargs] = NULL; 2547 2548 aidescs[0] = oread; 2549 aidescs[1] = owrite; 2550 aidescs[2] = SPAWN_READ_PIPE; 2551 2552 /* Pass fkeepuid, fkeepenv and fshell as TRUE. This puts the 2553 responsibility of maintaing security on the chat program. */ 2554 ipid = isspawn (azargs, aidescs, TRUE, TRUE, (const char *) NULL, 2555 FALSE, TRUE, (const char *) NULL, 2556 (const char *) NULL, (const char *) NULL); 2557 if (ipid < 0) 2558 { 2559 ulog (LOG_ERROR, "isspawn (%s): %s", azargs[0], strerror (errno)); 2560 return FALSE; 2561 } 2562 2563 e = fdopen (aidescs[2], (char *) "r"); 2564 if (e == NULL) 2565 { 2566 ulog (LOG_ERROR, "fdopen: %s", strerror (errno)); 2567 (void) close (aidescs[2]); 2568 (void) kill (ipid, SIGKILL); 2569 (void) iswait ((unsigned long) ipid, (const char *) NULL); 2570 return FALSE; 2571 } 2572 2573 /* The FILE e now is attached to stderr of the program. Forward 2574 every line the program outputs to the log file. */ 2575 while ((z = zfgets (e, FALSE)) != NULL) 2576 { 2577 int clen; 2578 2579 clen = strlen (z); 2580 if (z[clen - 1] == '\n') 2581 z[clen - 1] = '\0'; 2582 if (*z != '\0') 2583 ulog (LOG_NORMAL, "chat: %s", z); 2584 xfree ((pointer) z); 2585 } 2586 2587 (void) fclose (e); 2588 2589 return iswait ((unsigned long) ipid, "Chat program") == 0; 2590 } 2591 2592 /* Run a chat program on a stdin port. */ 2593 2594 boolean 2595 fsysdep_stdin_chat (qport, zprog) 2596 struct sport *qport; 2597 const char *zprog; 2598 { 2599 return fsrun_chat (qport->u.sstdin.s.s.oread, 2600 qport->u.sstdin.s.s.owrite, 2601 zprog); 2602 } 2603 2604 /* Run a chat program on a modem port. */ 2605 2606 boolean 2607 fsysdep_modem_chat (qport, zprog) 2608 struct sport *qport; 2609 const char *zprog; 2610 { 2611 return fsrun_chat (qport->u.smodem.s.s.oread, 2612 qport->u.smodem.s.s.owrite, 2613 zprog); 2614 } 2615 2616 /* Run a chat program on a direct port. */ 2617 2618 boolean 2619 fsysdep_direct_chat (qport, zprog) 2620 struct sport *qport; 2621 const char *zprog; 2622 { 2623 return fsrun_chat (qport->u.sdirect.s.s.oread, 2624 qport->u.sdirect.s.s.owrite, 2625 zprog); 2626 } 2627 2628 #if HAVE_TCP 2629 2630 /* Run a chat program on a TCP port. */ 2631 2632 boolean 2633 fsysdep_tcp_chat (qport, zprog) 2634 struct sport *qport; 2635 const char *zprog; 2636 { 2637 return fsrun_chat (qport->u.stcp.o, qport->u.stcp.o, zprog); 2638 } 2639 2640 #endif /* HAVE_TCP */ 2641 2642 /* Functions to return baud rates. */ 2643 2644 /* Return baud rate of a stdin port. */ 2645 2646 long 2647 isysdep_stdin_baud (qport) 2648 struct sport *qport; 2649 { 2650 return qport->u.sstdin.s.s.ibaud; 2651 } 2652 2653 /* Return baud rate of a modem port. */ 2654 2655 long 2656 isysdep_modem_baud (qport) 2657 struct sport *qport; 2658 { 2659 return qport->u.smodem.s.s.ibaud; 2660 } 2661 2662 /* Return baud rate of a direct port. */ 2663 2664 long 2665 isysdep_direct_baud (qport) 2666 struct sport *qport; 2667 { 2668 return qport->u.sdirect.s.s.ibaud; 2669 } 2670 2671 #if HAVE_TCP 2672 2673 /* Some system dependent routines for TCP ports. These work by 2674 setting up an ssysdep_serial_port structure to fake out the serial 2675 port routines. I'm doing it this way to avoid having to write the 2676 complicated timeout code twice, and because the serial port code 2677 will work fine. It does mean that if the serial port code changes 2678 this code will have to be considered. */ 2679 2680 /* Read data from a TCP port. */ 2681 2682 boolean 2683 fsysdep_tcp_read (qport, zread, pclen, cmin, ctimeout, freport) 2684 struct sport *qport; 2685 char *zread; 2686 int *pclen; 2687 int cmin; 2688 int ctimeout; 2689 boolean freport; 2690 { 2691 struct ssysdep_serial_port s; 2692 2693 s.oread = s.owrite = qport->u.stcp.o; 2694 s.fread_blocking = TRUE; 2695 s.fterminal = FALSE; 2696 return fsserial_read (&s, zread, pclen, cmin, ctimeout, freport, FALSE); 2697 } 2698 2699 /* Write data to a TCP port. */ 2700 2701 boolean 2702 fsysdep_tcp_write (qport, zwrite, cwrite) 2703 struct sport *qport; 2704 const char *zwrite; 2705 int cwrite; 2706 { 2707 struct ssysdep_serial_port s; 2708 2709 s.oread = s.owrite = qport->u.stcp.o; 2710 s.fread_blocking = TRUE; 2711 s.fterminal = FALSE; 2712 return fsserial_write (&s, zwrite, cwrite); 2713 } 2714 2715 /* Read and write data to and from a TCP port. We actually don't 2716 bother to really implement this, since the system will buffer up 2717 plenty of TCP data (only 256 bytes are buffered for a terminal, 2718 so losing data becomes a real possibility). */ 2719 2720 boolean 2721 fsysdep_tcp_io (qport, zwrite, pcwrite, zread, pcread) 2722 struct sport *qport; 2723 const char *zwrite; 2724 int *pcwrite; 2725 char *zread; 2726 int *pcread; 2727 { 2728 struct ssysdep_serial_port s; 2729 2730 s.oread = s.owrite = qport->u.stcp.o; 2731 s.fread_blocking = TRUE; 2732 s.fterminal = FALSE; 2733 *pcread = 0; 2734 return fsserial_write (&s, zwrite, *pcwrite); 2735 } 2736 2737 #endif /* HAVE_TCP */ 2738 2739 /* 2740 Local variables: 2741 mode:c 2742 End: 2743 */ 2744