1/* serial.c 2 The serial port communication routines for Unix. 3 4 Copyright (C) 1991, 1992, 1993, 1994, 1995, 2002 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. 21 22 The author of the program may be contacted at ian@airs.com. 23 */ 24 25#include "uucp.h" 26 27#if USE_RCS_ID 28const char serial_rcsid[] = "$Id: serial.c,v 1.78 2002/03/05 19:10:42 ian Rel $"; 29#endif 30 31#include "uudefs.h" 32#include "uuconf.h" 33#include "system.h" 34#include "conn.h" 35#include "sysdep.h" 36 37#include <errno.h> 38#include <ctype.h> 39 40#if HAVE_SYS_PARAM_H 41#include <sys/param.h> 42#endif 43 44#if HAVE_LIMITS_H 45#include <limits.h> 46#endif 47 48#if HAVE_TLI 49#if HAVE_TIUSER_H 50#include <tiuser.h> 51#else /* ! HAVE_TIUSER_H */ 52#if HAVE_XTI_H 53#include <xti.h> 54#endif /* HAVE_XTI_H */ 55#endif /* ! HAVE_TIUSER_H */ 56#endif /* HAVE_TLI */ 57 58#if HAVE_FCNTL_H 59#include <fcntl.h> 60#else 61#if HAVE_SYS_FILE_H 62#include <sys/file.h> 63#endif 64#endif 65 66#ifndef O_RDONLY 67#define O_RDONLY 0 68#define O_WRONLY 1 69#define O_RDWR 2 70#endif 71 72#ifndef O_NOCTTY 73#define O_NOCTTY 0 74#endif 75 76#ifndef FD_CLOEXEC 77#define FD_CLOEXEC 1 78#endif 79 80#if HAVE_SYS_IOCTL_H || HAVE_TXADDCD 81#include <sys/ioctl.h> 82#endif 83 84#if HAVE_SELECT 85#if HAVE_SYS_TIME_H 86#include <sys/time.h> 87#endif 88#if HAVE_SYS_SELECT_H 89#include <sys/select.h> 90#endif 91#endif 92 93#if HAVE_TIME_H 94#if ! HAVE_SYS_TIME_H || ! HAVE_SELECT || TIME_WITH_SYS_TIME 95#include <time.h> 96#endif 97#endif 98 99#if HAVE_STRIP_BUG && HAVE_BSD_TTY 100#include <termio.h> 101#endif 102 103#if HAVE_SVR4_LOCKFILES 104/* Get the right definitions for major and minor. */ 105#if MAJOR_IN_MKDEV 106#include <sys/mkdev.h> 107#endif /* MAJOR_IN_MKDEV */ 108#if MAJOR_IN_SYSMACROS 109#include <sys/sysmacros.h> 110#endif /* MAJOR_IN_SYSMACROS */ 111#if ! MAJOR_IN_MKDEV && ! MAJOR_IN_SYSMACROS 112#ifndef major 113#define major(i) (((i) >> 8) & 0xff) 114#endif 115#ifndef minor 116#define minor(i) ((i) & 0xff) 117#endif 118#endif /* ! MAJOR_IN_MKDEV && ! MAJOR_IN_SYSMACROS */ 119#endif /* HAVE_SVR4_LOCKFILES */ 120 121#if HAVE_DEV_INFO 122#include <sys/dev.h> 123#endif 124 125#if HAVE_SYS_TERMIOX_H 126#include <sys/termiox.h> 127#endif 128 129/* Get definitions for both O_NONBLOCK and O_NDELAY. */ 130#ifndef O_NDELAY 131#ifdef FNDELAY 132#define O_NDELAY FNDELAY 133#else /* ! defined (FNDELAY) */ 134#define O_NDELAY 0 135#endif /* ! defined (FNDELAY) */ 136#endif /* ! defined (O_NDELAY) */ 137 138#ifndef O_NONBLOCK 139#ifdef FNBLOCK 140#define O_NONBLOCK FNBLOCK 141#else /* ! defined (FNBLOCK) */ 142#define O_NONBLOCK 0 143#endif /* ! defined (FNBLOCK) */ 144#endif /* ! defined (O_NONBLOCK) */ 145 146#if O_NDELAY == 0 && O_NONBLOCK == 0 147 #error No way to do nonblocking I/O 148#endif 149 150/* Get definitions for EAGAIN, EWOULDBLOCK and ENODATA. */ 151#ifndef EAGAIN 152#ifndef EWOULDBLOCK 153#define EAGAIN (-1) 154#define EWOULDBLOCK (-1) 155#else /* defined (EWOULDBLOCK) */ 156#define EAGAIN EWOULDBLOCK 157#endif /* defined (EWOULDBLOCK) */ 158#else /* defined (EAGAIN) */ 159#ifndef EWOULDBLOCK 160#define EWOULDBLOCK EAGAIN 161#endif /* ! defined (EWOULDBLOCK) */ 162#endif /* defined (EAGAIN) */ 163 164#ifndef ENODATA 165#define ENODATA EAGAIN 166#endif 167 168/* Make sure we have a definition for MAX_INPUT. */ 169#ifndef MAX_INPUT 170#define MAX_INPUT (256) 171#endif 172 173/* If we have the TIOCSINUSE ioctl call, we use it to lock a terminal. 174 Otherwise, if we have the TIOCEXCL ioctl call, we have to open the 175 terminal before we know that it is unlocked. */ 176#ifdef TIOCSINUSE 177#define HAVE_TIOCSINUSE 1 178#else 179#ifdef TIOCEXCL 180#define HAVE_TIOCEXCL 1 181#endif 182#endif 183 184#if HAVE_TLI 185extern int t_errno; 186extern char *t_errlist[]; 187extern int t_nerr; 188#endif 189 190/* Determine bits to clear for the various terminal control fields for 191 HAVE_SYSV_TERMIO and HAVE_POSIX_TERMIOS. */ 192 193/* These fields are defined on some systems, and I am told that it 194 does not hurt to clear them, and it sometimes helps. */ 195#ifndef IMAXBEL 196#define IMAXBEL 0 197#endif 198 199#ifndef PENDIN 200#define PENDIN 0 201#endif 202 203#if HAVE_SYSV_TERMIO 204#define ICLEAR_IFLAG (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK \ 205 | ISTRIP | INLCR | IGNCR | ICRNL | IUCLC \ 206 | IXON | IXANY | IXOFF | IMAXBEL) 207#define ICLEAR_OFLAG (OPOST | OLCUC | ONLCR | OCRNL | ONOCR | ONLRET \ 208 | OFILL | OFDEL | NLDLY | CRDLY | TABDLY | BSDLY \ 209 | VTDLY | FFDLY) 210#define ICLEAR_CFLAG (CBAUD | CSIZE | PARENB | PARODD) 211#define ISET_CFLAG (CS8 | CREAD | HUPCL) 212#define ICLEAR_LFLAG (ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK \ 213 | ECHONL | NOFLSH | PENDIN) 214#endif 215#if HAVE_POSIX_TERMIOS 216#define ICLEAR_IFLAG (BRKINT | ICRNL | IGNBRK | IGNCR | IGNPAR \ 217 | INLCR | INPCK | ISTRIP | IXOFF | IXON \ 218 | PARMRK | IMAXBEL) 219#define ICLEAR_OFLAG (OPOST) 220#define ICLEAR_CFLAG (CSIZE | PARENB | PARODD) 221#define ISET_CFLAG (CS8 | CREAD | HUPCL) 222#define ICLEAR_LFLAG (ECHO | ECHOE | ECHOK | ECHONL | ICANON | IEXTEN \ 223 | ISIG | NOFLSH | TOSTOP | PENDIN) 224#endif 225 226enum tclocal_setting 227{ 228 SET_CLOCAL, 229 CLEAR_CLOCAL, 230 IGNORE_CLOCAL 231}; 232 233/* Local functions. */ 234 235static RETSIGTYPE usalarm P((int isig)); 236static boolean fsserial_init P((struct sconnection *qconn, 237 const struct sconncmds *qcmds, 238 const char *zdevice)); 239static void usserial_free P((struct sconnection *qconn)); 240static boolean fsserial_lockfile P((boolean flok, 241 const struct sconnection *)); 242static boolean fsserial_lock P((struct sconnection *qconn, 243 boolean fin, boolean fuser)); 244static boolean fsserial_unlock P((struct sconnection *qconn)); 245static boolean fsserial_open P((struct sconnection *qconn, long ibaud, 246 boolean fwait, boolean fuser, 247 enum tclocal_setting tlocal)); 248static boolean fsstdin_open P((struct sconnection *qconn, long ibaud, 249 boolean fwait, boolean fuser)); 250static boolean fsmodem_open P((struct sconnection *qconn, long ibaud, 251 boolean fwait, boolean fuser)); 252static boolean fsdirect_open P((struct sconnection *qconn, long ibaud, 253 boolean fwait, boolean fuser)); 254static boolean fsblock P((struct ssysdep_conn *q, boolean fblock)); 255static boolean fsserial_close P((struct ssysdep_conn *q)); 256static boolean fsstdin_close P((struct sconnection *qconn, 257 pointer puuconf, 258 struct uuconf_dialer *qdialer, 259 boolean fsuccess)); 260static boolean fsmodem_close P((struct sconnection *qconn, 261 pointer puuconf, 262 struct uuconf_dialer *qdialer, 263 boolean fsuccess)); 264static boolean fsdirect_close P((struct sconnection *qconn, 265 pointer puuconf, 266 struct uuconf_dialer *qdialer, 267 boolean fsuccess)); 268static boolean fsserial_break P((struct sconnection *qconn)); 269static boolean fsstdin_break P((struct sconnection *qconn)); 270static boolean fsserial_set P((struct sconnection *qconn, 271 enum tparitysetting tparity, 272 enum tstripsetting tstrip, 273 enum txonxoffsetting txonxoff)); 274static boolean fsstdin_set P((struct sconnection *qconn, 275 enum tparitysetting tparity, 276 enum tstripsetting tstrip, 277 enum txonxoffsetting txonxoff)); 278static boolean fsmodem_carrier P((struct sconnection *qconn, 279 boolean fcarrier)); 280static boolean fsserial_hardflow P((struct sconnection *qconn, 281 boolean fhardflow)); 282static boolean fsrun_chat P((int oread, int owrite, char **pzprog)); 283static long isserial_baud P((struct sconnection *qconn)); 284 285/* The command table for standard input ports. */ 286 287static const struct sconncmds sstdincmds = 288{ 289 usserial_free, 290 NULL, /* pflock */ 291 NULL, /* pfunlock */ 292 fsstdin_open, 293 fsstdin_close, 294 NULL, /* pfdial */ 295 fsdouble_read, 296 fsdouble_write, 297 fsysdep_conn_io, 298 fsstdin_break, 299 fsstdin_set, 300 NULL, /* pfcarrier */ 301 fsdouble_chat, 302 isserial_baud 303}; 304 305/* The command table for modem ports. */ 306 307static const struct sconncmds smodemcmds = 308{ 309 usserial_free, 310 fsserial_lock, 311 fsserial_unlock, 312 fsmodem_open, 313 fsmodem_close, 314 fmodem_dial, 315 fsysdep_conn_read, 316 fsysdep_conn_write, 317 fsysdep_conn_io, 318 fsserial_break, 319 fsserial_set, 320 fsmodem_carrier, 321 fsysdep_conn_chat, 322 isserial_baud 323}; 324 325/* The command table for direct ports. */ 326 327static const struct sconncmds sdirectcmds = 328{ 329 usserial_free, 330 fsserial_lock, 331 fsserial_unlock, 332 fsdirect_open, 333 fsdirect_close, 334 NULL, /* pfdial */ 335 fsysdep_conn_read, 336 fsysdep_conn_write, 337 fsysdep_conn_io, 338 fsserial_break, 339 fsserial_set, 340 NULL, /* pfcarrier */ 341 fsysdep_conn_chat, 342 isserial_baud 343}; 344 345/* If the system will let us set both O_NDELAY and O_NONBLOCK, we do 346 so. This is because some ancient drivers on some systems appear to 347 look for one but not the other. Some other systems will give an 348 EINVAL error if we attempt to set both, so we use a static global 349 to hold the value we want to set. If we get EINVAL, we change the 350 global and try again (if some system gives an error other than 351 EINVAL, the code will have to be modified). */ 352static int iSunblock = O_NDELAY | O_NONBLOCK; 353 354/* This code handles SIGALRM. See the discussion above 355 fsysdep_conn_read. Normally we ignore SIGALRM, but the handler 356 will temporarily be set to this function, which should set fSalarm 357 and then either longjmp or schedule another SIGALRM. fSalarm is 358 never referred to outside of this file, but we don't make it static 359 to try to fool compilers which don't understand volatile. */ 360 361volatile sig_atomic_t fSalarm; 362 363static RETSIGTYPE 364usalarm (isig) 365 int isig ATTRIBUTE_UNUSED; 366{ 367#if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET 368 (void) signal (isig, usalarm); 369#endif 370 371 fSalarm = TRUE; 372 373#if HAVE_RESTARTABLE_SYSCALLS 374 longjmp (sSjmp_buf, 1); 375#else 376 alarm (1); 377#endif 378} 379 380/* We need a simple routine to block SIGINT, SIGQUIT, SIGTERM and 381 SIGPIPE and another to restore the original state. When these 382 functions are called (in fsysdep_modem_close) SIGHUP is being 383 ignored. The routines are isblocksigs, which returns a value of 384 type HELD_SIG_MASK and usunblocksigs which takes a single argument 385 of type HELD_SIG_MASK. */ 386 387#if HAVE_SIGPROCMASK 388 389/* Use the POSIX sigprocmask call. */ 390 391#define HELD_SIG_MASK sigset_t 392 393static sigset_t isblocksigs P((void)); 394 395static sigset_t 396isblocksigs () 397{ 398 sigset_t sblock, sold; 399 400 /* These expressions need an extra set of parentheses to avoid a bug 401 in SCO 3.2.2. */ 402 (void) (sigemptyset (&sblock)); 403 (void) (sigaddset (&sblock, SIGINT)); 404 (void) (sigaddset (&sblock, SIGQUIT)); 405 (void) (sigaddset (&sblock, SIGTERM)); 406 (void) (sigaddset (&sblock, SIGPIPE)); 407 408 (void) sigprocmask (SIG_BLOCK, &sblock, &sold); 409 return sold; 410} 411 412#define usunblocksigs(s) \ 413 ((void) sigprocmask (SIG_SETMASK, &(s), (sigset_t *) NULL)) 414 415#else /* ! HAVE_SIGPROCMASK */ 416#if HAVE_SIGBLOCK 417 418/* Use the BSD sigblock and sigsetmask calls. */ 419 420#define HELD_SIG_MASK int 421 422#ifndef sigmask 423#define sigmask(i) (1 << ((i) - 1)) 424#endif 425 426#define isblocksigs() \ 427 sigblock (sigmask (SIGINT) | sigmask (SIGQUIT) \ 428 | sigmask (SIGTERM) | sigmask (SIGPIPE)) 429 430#define usunblocksigs(i) ((void) sigsetmask (i)) 431 432#else /* ! HAVE_SIGBLOCK */ 433 434#if HAVE_SIGHOLD 435 436/* Use the SVR3 sighold and sigrelse calls. */ 437 438#define HELD_SIG_MASK int 439 440static int isblocksigs P((void)); 441 442static int 443isblocksigs () 444{ 445 sighold (SIGINT); 446 sighold (SIGQUIT); 447 sighold (SIGTERM); 448 sighold (SIGPIPE); 449 return 0; 450} 451 452static void usunblocksigs P((int)); 453 454/*ARGSUSED*/ 455static void 456usunblocksigs (i) 457 int i; 458{ 459 sigrelse (SIGINT); 460 sigrelse (SIGQUIT); 461 sigrelse (SIGTERM); 462 sigrelse (SIGPIPE); 463} 464 465#else /* ! HAVE_SIGHOLD */ 466 467/* We have no way to block signals. This system will suffer from a 468 race condition in fsysdep_modem_close. */ 469 470#define HELD_SIG_MASK int 471 472#define isblocksigs() 0 473 474#define usunblocksigs(i) 475 476#endif /* ! HAVE_SIGHOLD */ 477#endif /* ! HAVE_SIGBLOCK */ 478#endif /* ! HAVE_SIGPROCMASK */ 479 480/* Initialize a connection for use on a serial port. */ 481 482static boolean 483fsserial_init (qconn, qcmds, zdevice) 484 struct sconnection *qconn; 485 const struct sconncmds *qcmds; 486 const char *zdevice; 487{ 488 struct ssysdep_conn *q; 489 490 q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn)); 491 if (zdevice == NULL 492 && qconn->qport != NULL 493 && qconn->qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN) 494 zdevice = qconn->qport->uuconf_zname; 495 if (zdevice == NULL) 496 q->zdevice = NULL; 497 else if (*zdevice == '/') 498 q->zdevice = zbufcpy (zdevice); 499 else 500 { 501 size_t clen; 502 503 clen = strlen (zdevice); 504 q->zdevice = zbufalc (sizeof "/dev/" + clen); 505 memcpy (q->zdevice, "/dev/", sizeof "/dev/" - 1); 506 memcpy (q->zdevice + sizeof "/dev/" - 1, zdevice, clen); 507 q->zdevice[sizeof "/dev/" + clen - 1] = '\0'; 508 } 509 q->o = -1; 510 q->ord = -1; 511 q->owr = -1; 512 q->ftli = FALSE; 513 qconn->psysdep = (pointer) q; 514 qconn->qcmds = qcmds; 515 return TRUE; 516} 517 518/* Initialize a connection for use on standard input. */ 519 520boolean 521fsysdep_stdin_init (qconn) 522 struct sconnection *qconn; 523{ 524 /* chmod /dev/tty to prevent other users from writing messages to 525 it. This is essentially `mesg n'. */ 526 (void) chmod ("/dev/tty", S_IRUSR | S_IWUSR); 527 return fsserial_init (qconn, &sstdincmds, (const char *) NULL); 528} 529 530/* Initialize a connection for use on a modem port. */ 531 532boolean 533fsysdep_modem_init (qconn) 534 struct sconnection *qconn; 535{ 536 return fsserial_init (qconn, &smodemcmds, 537 qconn->qport->uuconf_u.uuconf_smodem.uuconf_zdevice); 538} 539 540/* Initialize a connection for use on a direct port. */ 541 542boolean 543fsysdep_direct_init (qconn) 544 struct sconnection *qconn; 545{ 546 return fsserial_init (qconn, &sdirectcmds, 547 qconn->qport->uuconf_u.uuconf_sdirect.uuconf_zdevice); 548} 549 550/* Free up a serial port. */ 551 552static void 553usserial_free (qconn) 554 struct sconnection *qconn; 555{ 556 struct ssysdep_conn *qsysdep; 557 558 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 559 ubuffree (qsysdep->zdevice); 560 xfree ((pointer) qsysdep); 561 qconn->psysdep = NULL; 562} 563 564#if HAVE_SEQUENT_LOCKFILES 565#define LCK_TEMPLATE "LCK..tty" 566#else 567#define LCK_TEMPLATE "LCK.." 568#endif 569 570/* This routine is used for both locking and unlocking. It is the 571 only routine which knows how to translate a device name into the 572 name of a lock file. If it can't figure out a name, it does 573 nothing and returns TRUE. */ 574 575static boolean 576fsserial_lockfile (flok, qconn) 577 boolean flok; 578 const struct sconnection *qconn; 579{ 580 struct ssysdep_conn *qsysdep; 581 const char *z; 582 char *zalc; 583 boolean fret; 584 585 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 586 if (qconn->qport == NULL) 587 z = NULL; 588 else 589 z = qconn->qport->uuconf_zlockname; 590 zalc = NULL; 591 if (z == NULL) 592 { 593#if HAVE_QNX_LOCKFILES 594 { 595 nid_t idevice_nid; 596 char abdevice_nid[13]; /* length of long, a period, and a NUL */ 597 size_t cdevice_nid; 598 const char *zbase; 599 size_t clen; 600 601 /* If the node ID is explicitly specified as part of the 602 pathname to the device, use that. Otherwise, presume the 603 device is local to the current node. */ 604 if (qsysdep->zdevice[0] == '/' && qsysdep->zdevice[1] == '/') 605 idevice_nid = (nid_t) strtol (qsysdep->zdevice + 2, 606 (char **) NULL, 10); 607 else 608 idevice_nid = getnid (); 609 610 sprintf (abdevice_nid, "%ld.", (long) idevice_nid); 611 cdevice_nid = strlen (abdevice_nid); 612 613 zbase = strrchr (qsysdep->zdevice, '/') + 1; 614 clen = strlen (zbase); 615 616 zalc = zbufalc (sizeof LCK_TEMPLATE + cdevice_nid + clen); 617 618 memcpy (zalc, LCK_TEMPLATE, sizeof LCK_TEMPLATE - 1); 619 memcpy (zalc + sizeof LCK_TEMPLATE - 1, abdevice_nid, cdevice_nid); 620 memcpy (zalc + sizeof LCK_TEMPLATE - 1 + cdevice_nid, 621 zbase, clen + 1); 622 623 z = zalc; 624 } 625#else /* ! HAVE_QNX_LOCKFILES */ 626#if ! HAVE_SVR4_LOCKFILES 627 { 628 const char *zbase; 629 size_t clen; 630 631 zbase = strrchr (qsysdep->zdevice, '/') + 1; 632 clen = strlen (zbase); 633 zalc = zbufalc (sizeof LCK_TEMPLATE + clen); 634 memcpy (zalc, LCK_TEMPLATE, sizeof LCK_TEMPLATE - 1); 635 memcpy (zalc + sizeof LCK_TEMPLATE - 1, zbase, clen + 1); 636#if HAVE_SCO_LOCKFILES 637 { 638 char *zl; 639 640 zl = zalc + sizeof LCK_TEMPLATE + clen - 2; 641 if (isupper (*zl)) 642 *zl = tolower (*zl); 643 } 644#endif 645 z = zalc; 646 } 647#else /* HAVE_SVR4_LOCKFILES */ 648 { 649 struct stat s; 650 651 if (stat (qsysdep->zdevice, &s) != 0) 652 { 653 ulog (LOG_ERROR, "stat (%s): %s", qsysdep->zdevice, 654 strerror (errno)); 655 return FALSE; 656 } 657 zalc = zbufalc (sizeof "LK.1234567890.1234567890.1234567890"); 658 sprintf (zalc, "LK.%03d.%03d.%03d", major (s.st_dev), 659 major (s.st_rdev), minor (s.st_rdev)); 660 z = zalc; 661 } 662#endif /* HAVE_SVR4_LOCKFILES */ 663#endif /* ! HAVE_QNX_LOCKFILES */ 664 } 665 666 if (flok) 667 fret = fsdo_lock (z, FALSE, (boolean *) NULL); 668 else 669 fret = fsdo_unlock (z, FALSE); 670 671#if HAVE_COHERENT_LOCKFILES 672 if (fret) 673 { 674 if (flok) 675 { 676 if (lockttyexist (z + sizeof LCK_TEMPLATE - 1)) 677 { 678 ulog (LOG_NORMAL, "%s: port already locked", 679 z + sizeof LCK_TEMPLATE - 1); 680 fret = FALSE; 681 } 682 else 683 fret = fscoherent_disable_tty (z + sizeof LCK_TEMPLATE - 1, 684 &qsysdep->zenable); 685 } 686 else 687 { 688 fret = TRUE; 689 if (qsysdep->zenable != NULL) 690 { 691 const char *azargs[3]; 692 int aidescs[3]; 693 pid_t ipid; 694 695 azargs[0] = "/etc/enable"; 696 azargs[1] = qsysdep->zenable; 697 azargs[2] = NULL; 698 aidescs[0] = SPAWN_NULL; 699 aidescs[1] = SPAWN_NULL; 700 aidescs[2] = SPAWN_NULL; 701 702 ipid = ixsspawn (azargs, aidescs, TRUE, FALSE, 703 (const char *) NULL, TRUE, TRUE, 704 (const char *) NULL, (const char *) NULL, 705 (const char *) NULL); 706 if (ipid < 0) 707 { 708 ulog (LOG_ERROR, "ixsspawn (/etc/enable %s): %s", 709 qsysdep->zenable, strerror (errno)); 710 fret = FALSE; 711 } 712 else 713 { 714 if (ixswait ((unsigned long) ipid, (const char *) NULL) 715 == 0) 716 fret = TRUE; 717 else 718 fret = FALSE; 719 } 720 ubuffree (qsysdep->zenable); 721 qsysdep->zenable = NULL; 722 } 723 } 724 } 725#endif /* HAVE_COHERENT_LOCKFILES */ 726 727 ubuffree (zalc); 728 return fret; 729} 730 731/* If we can mark a modem line in use, then when we lock a port we 732 must open it and mark it in use. We can't wait until the actual 733 open because we can't fail out if it is locked then. */ 734 735static boolean 736fsserial_lock (qconn, fin, fuser) 737 struct sconnection *qconn; 738 boolean fin; 739 boolean fuser; 740{ 741 if (! fsserial_lockfile (TRUE, qconn)) 742 return FALSE; 743 744#if HAVE_TIOCSINUSE || HAVE_TIOCEXCL || HAVE_DEV_INFO 745 /* Open the line and try to mark it in use. */ 746 { 747 struct ssysdep_conn *qsysdep; 748 int iflag; 749 uid_t ieuid; 750 gid_t iegid; 751 752 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 753 754 if (fin) 755 iflag = 0; 756 else 757 iflag = iSunblock; 758 759 if (fuser) 760 { 761 if (! fsuser_perms (&ieuid, &iegid)) 762 { 763 (void) fsserial_lockfile (FALSE, qconn); 764 return FALSE; 765 } 766 } 767 768 qsysdep->o = open (qsysdep->zdevice, O_RDWR | iflag); 769 if (qsysdep->o < 0) 770 { 771#if O_NONBLOCK != 0 772 if (! fin && iSunblock != O_NONBLOCK && errno == EINVAL) 773 { 774 iSunblock = O_NONBLOCK; 775 qsysdep->o = open (qsysdep->zdevice, 776 O_RDWR | O_NONBLOCK); 777 } 778#endif 779 if (qsysdep->o < 0) 780 { 781 int ierr; 782 783 ierr = errno; 784 if (fuser) 785 (void) fsuucp_perms ((long) ieuid, (long) iegid); 786 if (ierr != EBUSY) 787 ulog (LOG_ERROR, "open (%s): %s", qsysdep->zdevice, 788 strerror (ierr)); 789 (void) fsserial_lockfile (FALSE, qconn); 790 return FALSE; 791 } 792 } 793 794 if (fuser) 795 { 796 if (! fsuucp_perms ((long) ieuid, (long) iegid)) 797 { 798 (void) close (qsysdep->o); 799 qsysdep->o = -1; 800 (void) fsserial_lockfile (FALSE, qconn); 801 return FALSE; 802 } 803 } 804 805#if HAVE_TIOCSINUSE 806 /* If we can't mark it in use, return FALSE to indicate that the 807 lock failed. */ 808 if (ioctl (qsysdep->o, TIOCSINUSE, 0) < 0) 809 { 810 if (errno != EALREADY) 811 ulog (LOG_ERROR, "ioctl (TIOCSINUSE): %s", strerror (errno)); 812#ifdef TIOCNOTTY 813 (void) ioctl (qsysdep->o, TIOCNOTTY, (char *) NULL); 814#endif 815 (void) close (qsysdep->o); 816 qsysdep->o = -1; 817 (void) fsserial_lockfile (FALSE, qconn); 818 return FALSE; 819 } 820#endif 821 822#if HAVE_DEV_INFO 823 /* QNX programs "lock" a serial port by simply opening it and 824 checking if some other program also has the port open. If the 825 count of openers is greater than one, the program presumes the 826 port is "locked" and backs off. This isn't really "locking" of 827 course, but it pretty much seems to work. This can result in 828 dropping incoming connections if an outgoing connection is 829 started at exactly the same time. It would probably be better 830 to stop using the lock files at all for this case, but that 831 would involve more complex changes to the code, and I'm afraid 832 I would break something. -- Joe Wells <jbw@cs.bu.edu> */ 833 { 834 struct _dev_info_entry sdevinfo; 835 836 if (dev_info (qsysdep->o, &sdevinfo) == -1) 837 { 838 ulog (LOG_ERROR, "dev_info: %s", strerror (errno)); 839 sdevinfo.open_count = 2; /* force presumption of "locked" */ 840 } 841 if (sdevinfo.open_count != 1) 842 { 843#ifdef TIOCNOTTY 844 (void) ioctl (qsysdep->o, TIOCNOTTY, (char *) NULL); 845#endif /* TIOCNOTTY */ 846 (void) close (qsysdep->o); 847 qsysdep->o = -1; 848 (void) fsserial_lockfile (FALSE, qconn); 849 return FALSE; 850 } 851 } 852#endif /* HAVE_DEV_INFO */ 853 854 if (fcntl (qsysdep->o, F_SETFD, 855 fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0) 856 { 857 ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); 858#ifdef TIOCNOTTY 859 (void) ioctl (qsysdep->o, TIOCNOTTY, (char *) NULL); 860#endif 861 (void) close (qsysdep->o); 862 qsysdep->o = -1; 863 (void) fsserial_lockfile (FALSE, qconn); 864 return FALSE; 865 } 866 } 867#endif /* HAVE_TIOCSINUSE || HAVE_TIOCEXCL */ 868 869 return TRUE; 870} 871 872/* Unlock a modem or direct port. */ 873 874static boolean 875fsserial_unlock (qconn) 876 struct sconnection *qconn; 877{ 878 boolean fret; 879 struct ssysdep_conn *qsysdep; 880 881 fret = TRUE; 882 883 /* The file may have been opened by fsserial_lock, so close it here 884 if necessary. */ 885 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 886 if (qsysdep->o >= 0) 887 { 888#ifdef TIOCNOTTY 889 (void) ioctl (qsysdep->o, TIOCNOTTY, (char *) NULL); 890#endif 891 if (close (qsysdep->o) < 0) 892 { 893 ulog (LOG_ERROR, "close: %s", strerror (errno)); 894 fret = FALSE; 895 } 896 qsysdep->o = -1; 897 } 898 899 if (! fsserial_lockfile (FALSE, qconn)) 900 fret = FALSE; 901 902 return fret; 903} 904 905/* A table to map baud rates into index numbers. */ 906 907#if HAVE_POSIX_TERMIOS 908typedef speed_t baud_code; 909#else 910typedef int baud_code; 911#endif 912 913static struct sbaud_table 914{ 915 baud_code icode; 916 long ibaud; 917} asSbaud_table[] = 918{ 919 { B50, 50 }, 920 { B75, 75 }, 921 { B110, 110 }, 922 { B134, 134 }, 923 { B150, 150 }, 924 { B200, 200 }, 925 { B300, 300 }, 926 { B600, 600 }, 927 { B1200, 1200 }, 928 { B1800, 1800 }, 929 { B2400, 2400 }, 930 { B4800, 4800 }, 931 { B9600, 9600 }, 932#ifdef B19200 933 { B19200, 19200 }, 934#else /* ! defined (B19200) */ 935#ifdef EXTA 936 { EXTA, 19200 }, 937#endif /* EXTA */ 938#endif /* ! defined (B19200) */ 939#ifdef B38400 940 { B38400, 38400 }, 941#else /* ! defined (B38400) */ 942#ifdef EXTB 943 { EXTB, 38400 }, 944#endif /* EXTB */ 945#endif /* ! defined (B38400) */ 946#ifdef B57600 947 { B57600, 57600 }, 948#endif 949#ifdef B76800 950 { B76800, 76800 }, 951#endif 952#ifdef B115200 953 { B115200, 115200 }, 954#endif 955#ifdef B230400 956 { B230400, 230400 }, 957#else 958#ifdef _B230400 959 { _B230400, 230400 }, 960#endif /* _B230400 */ 961#endif /* ! defined (B230400) */ 962#ifdef B460800 963 { B460800, 460800 }, 964#else 965#ifdef _B460800 966 { _B460800, 460800 }, 967#endif /* _B460800 */ 968#endif /* ! defined (B460800) */ 969#ifdef B500000 970 { B500000, 500000 }, 971#endif 972#ifdef B576000 973 { B576000, 576000 }, 974#endif 975#ifdef B921600 976 { B921600, 921600 }, 977#endif 978#ifdef B1000000 979 { B1000000, 1000000 }, 980#endif 981#ifdef B1152000 982 { B1152000, 1152000 }, 983#endif 984#ifdef B1500000 985 { B1500000, 1500000 }, 986#endif 987#ifdef B2000000 988 { B2000000, 2000000 }, 989#endif 990#ifdef B2500000 991 { B2500000, 2500000 }, 992#endif 993#ifdef B3000000 994 { B3000000, 3000000 }, 995#endif 996#ifdef B3500000 997 { B3500000, 3500000 }, 998#endif 999#ifdef B4000000 1000 { B4000000, 4000000 }, 1001#endif 1002 { B0, 0 } 1003}; 1004 1005#define CBAUD_TABLE (sizeof asSbaud_table / sizeof asSbaud_table[0]) 1006 1007#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1008/* Hold the MIN value for the terminal to avoid setting it 1009 unnecessarily. */ 1010static int cSmin; 1011#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1012 1013/* Open a serial line. This sets the terminal settings. We begin in 1014 seven bit mode and let the protocol change if necessary. If fwait 1015 is FALSE we open the terminal in non-blocking mode. If fuser is 1016 true we open the port using the user's permissions. The tlocal 1017 parameter indicates whether to set, clear, or ignore CLOCAL. */ 1018 1019static boolean 1020fsserial_open (qconn, ibaud, fwait, fuser, tlocal) 1021 struct sconnection *qconn; 1022 long ibaud; 1023 boolean fwait; 1024 boolean fuser; 1025 enum tclocal_setting tlocal; 1026{ 1027 struct ssysdep_conn *q; 1028 baud_code ib; 1029 1030 q = (struct ssysdep_conn *) qconn->psysdep; 1031 1032 if (q->zdevice != NULL) 1033 { 1034#if LOG_DEVICE_PREFIX 1035 ulog_device (q->zdevice); 1036#else 1037 const char *z; 1038 1039 if (strncmp (q->zdevice, "/dev/", sizeof "/dev/" - 1) == 0) 1040 z = q->zdevice + sizeof "/dev/" - 1; 1041 else 1042 z = q->zdevice; 1043 ulog_device (z); 1044#endif 1045 } 1046 else 1047 { 1048 const char *zport; 1049 boolean fdummy; 1050 1051#if DEBUG > 0 1052 if (qconn->qport != NULL && 1053 qconn->qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN) 1054 ulog (LOG_FATAL, "fsserial_open: Can't happen"); 1055#endif 1056 zport = zsysdep_port_name (&fdummy); 1057 if (zport != NULL) 1058 ulog_device (zport); 1059 } 1060 1061 ib = B0; 1062 if (ibaud != 0) 1063 { 1064 size_t i; 1065 1066 for (i = 0; i < CBAUD_TABLE; i++) 1067 if (asSbaud_table[i].ibaud == ibaud) 1068 break; 1069 if (i >= CBAUD_TABLE) 1070 { 1071 ulog (LOG_ERROR, "Unsupported baud rate %ld", ibaud); 1072 return FALSE; 1073 } 1074 ib = asSbaud_table[i].icode; 1075 } 1076 1077 /* The port may have already been opened by the locking routine. */ 1078 if (q->o < 0) 1079 { 1080 int iflag; 1081 uid_t ieuid; 1082 gid_t iegid; 1083 1084 if (fwait) 1085 iflag = 0; 1086 else 1087 iflag = iSunblock; 1088 1089 if (fuser) 1090 { 1091 if (! fsuser_perms (&ieuid, &iegid)) 1092 return FALSE; 1093 } 1094 1095 q->o = open (q->zdevice, O_RDWR | iflag); 1096 if (q->o < 0) 1097 { 1098#if O_NONBLOCK != 0 1099 if (! fwait && iSunblock != O_NONBLOCK && errno == EINVAL) 1100 { 1101 iSunblock = O_NONBLOCK; 1102 q->o = open (q->zdevice, O_RDWR | O_NONBLOCK); 1103 } 1104#endif 1105 if (q->o < 0) 1106 { 1107 int ierr; 1108 1109 ierr = errno; 1110 if (fuser) 1111 (void) fsuucp_perms ((long) ieuid, (long) iegid); 1112 ulog (LOG_ERROR, "open (%s): %s", q->zdevice, 1113 strerror (ierr)); 1114 return FALSE; 1115 } 1116 } 1117 1118 if (fuser) 1119 { 1120 if (! fsuucp_perms ((long) ieuid, (long) iegid)) 1121 return FALSE; 1122 } 1123 1124 if (fcntl (q->o, F_SETFD, fcntl (q->o, F_GETFD, 0) | FD_CLOEXEC) < 0) 1125 { 1126 ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); 1127 return FALSE; 1128 } 1129 } 1130 1131 /* Get the port flags, and make sure the ports are blocking. */ 1132 1133 q->iflags = fcntl (q->o, F_GETFL, 0); 1134 if (q->iflags < 0) 1135 { 1136 ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); 1137 return FALSE; 1138 } 1139 q->iwr_flags = -1; 1140 1141 if (! fsblock (q, TRUE)) 1142 return FALSE; 1143 1144 if (! fgetterminfo (q->o, &q->sorig)) 1145 { 1146 q->fterminal = FALSE; 1147 return TRUE; 1148 } 1149 1150 q->fterminal = TRUE; 1151 1152 q->snew = q->sorig; 1153 1154#if HAVE_BSD_TTY 1155 1156 q->snew.stty.sg_flags = RAW | ANYP; 1157 if (ibaud == 0) 1158 ib = q->snew.stty.sg_ospeed; 1159 else 1160 { 1161 q->snew.stty.sg_ispeed = ib; 1162 q->snew.stty.sg_ospeed = ib; 1163 } 1164 1165 /* We don't want to receive any interrupt characters. */ 1166 q->snew.stchars.t_intrc = -1; 1167 q->snew.stchars.t_quitc = -1; 1168 q->snew.stchars.t_eofc = -1; 1169 q->snew.stchars.t_brkc = -1; 1170 q->snew.sltchars.t_suspc = -1; 1171 q->snew.sltchars.t_rprntc = -1; 1172 q->snew.sltchars.t_dsuspc = -1; 1173 q->snew.sltchars.t_flushc = -1; 1174 q->snew.sltchars.t_werasc = -1; 1175 q->snew.sltchars.t_lnextc = -1; 1176 1177#ifdef NTTYDISC 1178 /* We want to use the ``new'' terminal driver so that we can use the 1179 local mode bits to control XON/XOFF. */ 1180 { 1181 int iparam; 1182 1183 if (ioctl (q->o, TIOCGETD, &iparam) >= 0 1184 && iparam != NTTYDISC) 1185 { 1186 iparam = NTTYDISC; 1187 (void) ioctl (q->o, TIOCSETD, &iparam); 1188 } 1189 } 1190#endif 1191 1192#ifdef TIOCHPCL 1193 /* When the file is closed, hang up the line. This is a safety 1194 measure in case the program crashes. */ 1195 (void) ioctl (q->o, TIOCHPCL, 0); 1196#endif 1197 1198#ifdef TIOCFLUSH 1199 { 1200 int iparam; 1201 1202 /* Flush pending input. */ 1203#ifdef FREAD 1204 iparam = FREAD; 1205#else 1206 iparam = 0; 1207#endif 1208 (void) ioctl (q->o, TIOCFLUSH, &iparam); 1209 } 1210#endif /* TIOCFLUSH */ 1211 1212#endif /* HAVE_BSD_TTY */ 1213 1214#if HAVE_SYSV_TERMIO 1215 1216 if (ibaud == 0) 1217 ib = q->snew.c_cflag & CBAUD; 1218 1219 q->snew.c_iflag &=~ ICLEAR_IFLAG; 1220 q->snew.c_oflag &=~ ICLEAR_OFLAG; 1221 q->snew.c_cflag &=~ ICLEAR_CFLAG; 1222 q->snew.c_cflag |= ib | ISET_CFLAG; 1223 q->snew.c_lflag &=~ ICLEAR_LFLAG; 1224 cSmin = 1; 1225 q->snew.c_cc[VMIN] = cSmin; 1226 q->snew.c_cc[VTIME] = 1; 1227 1228#ifdef TCFLSH 1229 /* Flush pending input. */ 1230 (void) ioctl (q->o, TCFLSH, 0); 1231#endif 1232 1233#endif /* HAVE_SYSV_TERMIO */ 1234 1235#if HAVE_POSIX_TERMIOS 1236 1237 if (ibaud == 0) 1238 ib = cfgetospeed (&q->snew); 1239 1240 q->snew.c_iflag &=~ ICLEAR_IFLAG; 1241 q->snew.c_oflag &=~ ICLEAR_OFLAG; 1242 q->snew.c_cflag &=~ ICLEAR_CFLAG; 1243 q->snew.c_cflag |= ISET_CFLAG; 1244 q->snew.c_lflag &=~ ICLEAR_LFLAG; 1245 cSmin = 1; 1246 q->snew.c_cc[VMIN] = cSmin; 1247 q->snew.c_cc[VTIME] = 1; 1248 1249 (void) cfsetospeed (&q->snew, ib); 1250 (void) cfsetispeed (&q->snew, ib); 1251 1252 /* Flush pending input. */ 1253 (void) tcflush (q->o, TCIFLUSH); 1254 1255#endif /* HAVE_POSIX_TERMIOS */ 1256 1257#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1258 switch (tlocal) 1259 { 1260 case SET_CLOCAL: 1261 q->snew.c_cflag |= CLOCAL; 1262 break; 1263 case CLEAR_CLOCAL: 1264 q->snew.c_cflag &=~ CLOCAL; 1265 break; 1266 case IGNORE_CLOCAL: 1267 break; 1268 } 1269#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1270 1271 if (! fsetterminfo (q->o, &q->snew)) 1272 { 1273 ulog (LOG_ERROR, "Can't set terminal settings: %s", strerror (errno)); 1274 return FALSE; 1275 } 1276 1277#ifdef TIOCSCTTY 1278 /* On BSD 4.4, make it our controlling terminal. */ 1279 (void) ioctl (q->o, TIOCSCTTY, 0); 1280#endif 1281 1282 if (ibaud != 0) 1283 q->ibaud = ibaud; 1284 else 1285 { 1286 size_t i; 1287 1288 q->ibaud = (long) 1200; 1289 for (i = 0; i < CBAUD_TABLE; i++) 1290 { 1291 if (asSbaud_table[i].icode == ib 1292 && asSbaud_table[i].ibaud != 0) 1293 { 1294 q->ibaud = asSbaud_table[i].ibaud; 1295 break; 1296 } 1297 } 1298 1299 DEBUG_MESSAGE1 (DEBUG_PORT, 1300 "fsserial_open: Baud rate is %ld", q->ibaud); 1301 } 1302 1303 return TRUE; 1304} 1305 1306/* Open a standard input port. The code alternates q->o between 1307 q->ord and q->owr as appropriate. It is always q->ord before any 1308 call to fsblock. */ 1309 1310static boolean 1311fsstdin_open (qconn, ibaud, fwait, fuser) 1312 struct sconnection *qconn; 1313 long ibaud; 1314 boolean fwait; 1315 boolean fuser; 1316{ 1317 struct ssysdep_conn *q; 1318 1319 q = (struct ssysdep_conn *) qconn->psysdep; 1320 q->ord = 0; 1321 q->owr = 1; 1322 1323 q->o = q->ord; 1324 if (! fsserial_open (qconn, ibaud, fwait, fuser, IGNORE_CLOCAL)) 1325 return FALSE; 1326 q->iwr_flags = fcntl (q->owr, F_GETFL, 0); 1327 if (q->iwr_flags < 0) 1328 { 1329 ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); 1330 return FALSE; 1331 } 1332 return TRUE; 1333} 1334 1335/* Open a modem port. */ 1336 1337static boolean 1338fsmodem_open (qconn, ibaud, fwait, fuser) 1339 struct sconnection *qconn; 1340 long ibaud; 1341 boolean fwait; 1342 boolean fuser; 1343{ 1344 struct uuconf_modem_port *qm; 1345 1346 qm = &qconn->qport->uuconf_u.uuconf_smodem; 1347 if (ibaud == (long) 0) 1348 ibaud = qm->uuconf_ibaud; 1349 1350 if (! fsserial_open (qconn, ibaud, fwait, fuser, 1351 fwait ? CLEAR_CLOCAL : SET_CLOCAL)) 1352 return FALSE; 1353 1354 /* If we are waiting for carrier, then turn on hardware flow 1355 control. We don't turn on hardware flow control when dialing 1356 out, because some modems don't assert the necessary signals until 1357 they see carrier. Instead, we turn on hardware flow control in 1358 fsmodem_carrier. */ 1359 if (fwait 1360 && ! fsserial_hardflow (qconn, qm->uuconf_fhardflow)) 1361 return FALSE; 1362 1363 return TRUE; 1364} 1365 1366/* Open a direct port. */ 1367 1368static boolean 1369fsdirect_open (qconn, ibaud, fwait, fuser) 1370 struct sconnection *qconn; 1371 long ibaud; 1372 boolean fwait; 1373 boolean fuser; 1374{ 1375 struct uuconf_direct_port *qd; 1376 1377 qd = &qconn->qport->uuconf_u.uuconf_sdirect; 1378 if (ibaud == (long) 0) 1379 ibaud = qd->uuconf_ibaud; 1380 if (! fsserial_open (qconn, ibaud, fwait, fuser, 1381 qd->uuconf_fcarrier ? CLEAR_CLOCAL : SET_CLOCAL)) 1382 return FALSE; 1383 1384 /* Always turn on hardware flow control for a direct port when it is 1385 opened. There is no other sensible time to turn it on. */ 1386 return fsserial_hardflow (qconn, qd->uuconf_fhardflow); 1387} 1388 1389/* Change the blocking status of the port. We keep track of the 1390 current blocking status to avoid calling fcntl unnecessarily; fcntl 1391 turns out to be surprisingly expensive, at least on Ultrix. */ 1392 1393static boolean 1394fsblock (qs, fblock) 1395 struct ssysdep_conn *qs; 1396 boolean fblock; 1397{ 1398 int iwant; 1399 int isys; 1400 1401 if (fblock) 1402 iwant = qs->iflags &~ (O_NDELAY | O_NONBLOCK); 1403 else 1404 iwant = qs->iflags | iSunblock; 1405 1406 if (iwant == qs->iflags) 1407 return TRUE; 1408 1409 isys = fcntl (qs->o, F_SETFL, iwant); 1410 if (isys < 0) 1411 { 1412#if O_NONBLOCK != 0 1413 if (! fblock && iSunblock != O_NONBLOCK && errno == EINVAL) 1414 { 1415 iSunblock = O_NONBLOCK; 1416 iwant = qs->iflags | O_NONBLOCK; 1417 isys = fcntl (qs->o, F_SETFL, iwant); 1418 } 1419#endif 1420 if (isys < 0) 1421 { 1422 ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); 1423 return FALSE; 1424 } 1425 } 1426 1427 qs->iflags = iwant; 1428 1429 if (qs->iwr_flags >= 0 && qs->ord != qs->owr) 1430 { 1431 if (fblock) 1432 iwant = qs->iwr_flags &~ (O_NDELAY | O_NONBLOCK); 1433 else 1434 iwant = qs->iwr_flags | iSunblock; 1435 1436 isys = fcntl (qs->owr, F_SETFL, iwant); 1437 if (isys < 0) 1438 { 1439#if O_NONBLOCK != 0 1440 if (! fblock && iSunblock != O_NONBLOCK && errno == EINVAL) 1441 { 1442 iSunblock = O_NONBLOCK; 1443 iwant = qs->iwr_flags | O_NONBLOCK; 1444 isys = fcntl (qs->owr, F_SETFL, iwant); 1445 } 1446#endif 1447 if (isys < 0) 1448 { 1449 ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); 1450 return FALSE; 1451 } 1452 } 1453 1454 qs->iwr_flags = iwant; 1455 } 1456 1457 return TRUE; 1458} 1459 1460/* Close a serial port. */ 1461 1462static boolean 1463fsserial_close (q) 1464 struct ssysdep_conn *q; 1465{ 1466 if (q->o >= 0) 1467 { 1468 /* Use a 30 second timeout to avoid hanging while draining 1469 output. */ 1470 if (q->fterminal) 1471 { 1472 fSalarm = FALSE; 1473 1474 if (fsysdep_catch ()) 1475 { 1476 usysdep_start_catch (); 1477 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 1478 (void) alarm (30); 1479 1480 (void) fsetterminfodrain (q->o, &q->sorig); 1481 } 1482 1483 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1484 (void) alarm (0); 1485 usysdep_end_catch (); 1486 1487 /* If we timed out, use the non draining call. Hopefully 1488 this can't hang. */ 1489 if (fSalarm) 1490 (void) fsetterminfo (q->o, &q->sorig); 1491 } 1492 1493#ifdef TIOCNOTTY 1494 /* We don't want this as our controlling terminal any more, so 1495 get rid of it. This is necessary because we don't want to 1496 open /dev/tty, since that can confuse the serial port locking 1497 on some computers. */ 1498 (void) ioctl (q->o, TIOCNOTTY, (char *) NULL); 1499#endif 1500 1501 (void) close (q->o); 1502 q->o = -1; 1503 1504 /* Sleep to give the terminal a chance to settle, in case we are 1505 about to call out again. */ 1506 sleep (2); 1507 } 1508 1509 return TRUE; 1510} 1511 1512/* Close a stdin port. */ 1513 1514/*ARGSUSED*/ 1515static boolean 1516fsstdin_close (qconn, puuconf, qdialer, fsuccess) 1517 struct sconnection *qconn; 1518 pointer puuconf ATTRIBUTE_UNUSED; 1519 struct uuconf_dialer *qdialer ATTRIBUTE_UNUSED; 1520 boolean fsuccess ATTRIBUTE_UNUSED; 1521{ 1522 struct ssysdep_conn *qsysdep; 1523 1524 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 1525 (void) close (qsysdep->owr); 1526 (void) close (2); 1527 qsysdep->o = qsysdep->ord; 1528 return fsserial_close (qsysdep); 1529} 1530 1531/* Close a modem port. */ 1532 1533static boolean 1534fsmodem_close (qconn, puuconf, qdialer, fsuccess) 1535 struct sconnection *qconn; 1536 pointer puuconf; 1537 struct uuconf_dialer *qdialer; 1538 boolean fsuccess; 1539{ 1540 struct ssysdep_conn *qsysdep; 1541 boolean fret; 1542 struct uuconf_dialer sdialer; 1543 const struct uuconf_chat *qchat; 1544 1545 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 1546 1547 fret = TRUE; 1548 1549 /* Figure out the dialer so that we can run the complete or abort 1550 chat scripts. */ 1551 if (qdialer == NULL) 1552 { 1553 if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL) 1554 { 1555 const char *zdialer; 1556 int iuuconf; 1557 1558 zdialer = qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer[0]; 1559 iuuconf = uuconf_dialer_info (puuconf, zdialer, &sdialer); 1560 if (iuuconf == UUCONF_SUCCESS) 1561 qdialer = &sdialer; 1562 else 1563 { 1564 ulog_uuconf (LOG_ERROR, puuconf, iuuconf); 1565 fret = FALSE; 1566 } 1567 } 1568 else 1569 qdialer = qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer; 1570 } 1571 1572 /* Get the complete or abort chat script to use. */ 1573 qchat = NULL; 1574 if (qdialer != NULL) 1575 { 1576 if (fsuccess) 1577 qchat = &qdialer->uuconf_scomplete; 1578 else 1579 qchat = &qdialer->uuconf_sabort; 1580 } 1581 1582 if (qchat != NULL 1583 && (qchat->uuconf_pzprogram != NULL 1584 || qchat->uuconf_pzchat != NULL)) 1585 { 1586 boolean fsighup_ignored; 1587 HELD_SIG_MASK smask; 1588 int i; 1589 sig_atomic_t afhold[INDEXSIG_COUNT]; 1590 1591 /* We're no longer interested in carrier. */ 1592 (void) fsmodem_carrier (qconn, FALSE); 1593 1594 /* The port I/O routines check whether any signal has been 1595 received, and abort if one has. While we are closing down 1596 the modem, we don't care if we received a signal in the past, 1597 but we do care if we receive a new signal (otherwise it would 1598 be difficult to kill a uucico which was closing down a 1599 modem). We never care if we get SIGHUP at this point. So we 1600 turn off SIGHUP, remember what signals we've already seen, 1601 and clear our notion of what signals we've seen. We have to 1602 block the signals while we remember and clear the array, 1603 since we might otherwise miss a signal which occurred between 1604 the copy and the clear (old systems can't block signals; they 1605 will just have to suffer the race). */ 1606 usset_signal (SIGHUP, SIG_IGN, FALSE, &fsighup_ignored); 1607 smask = isblocksigs (); 1608 for (i = 0; i < INDEXSIG_COUNT; i++) 1609 { 1610 afhold[i] = afSignal[i]; 1611 afSignal[i] = FALSE; 1612 } 1613 usunblocksigs (smask); 1614 1615 if (! fchat (qconn, puuconf, qchat, (const struct uuconf_system *) NULL, 1616 (const struct uuconf_dialer *) NULL, (const char *) NULL, 1617 FALSE, qconn->qport->uuconf_zname, 1618 qsysdep->ibaud)) 1619 fret = FALSE; 1620 1621 /* Restore the old signal array and the SIGHUP handler. It is 1622 not necessary to block signals here, since all we are doing 1623 is exactly what the signal handler itself would do if the 1624 signal occurred. */ 1625 for (i = 0; i < INDEXSIG_COUNT; i++) 1626 if (afhold[i]) 1627 afSignal[i] = TRUE; 1628 if (! fsighup_ignored) 1629 usset_signal (SIGHUP, ussignal, TRUE, (boolean *) NULL); 1630 } 1631 1632 if (qdialer != NULL 1633 && qdialer == &sdialer) 1634 (void) uuconf_dialer_free (puuconf, &sdialer); 1635 1636#if ! HAVE_RESET_BUG 1637 /* Reset the terminal to make sure we drop DTR. It should be 1638 dropped when we close the descriptor, but that doesn't seem to 1639 happen on some systems. Use a 30 second timeout to avoid hanging 1640 while draining output. */ 1641 if (qsysdep->fterminal) 1642 { 1643#if HAVE_BSD_TTY 1644 qsysdep->snew.stty.sg_ispeed = B0; 1645 qsysdep->snew.stty.sg_ospeed = B0; 1646#endif 1647#if HAVE_SYSV_TERMIO 1648 qsysdep->snew.c_cflag = (qsysdep->snew.c_cflag &~ CBAUD) | B0; 1649#endif 1650#if HAVE_POSIX_TERMIOS 1651 (void) cfsetospeed (&qsysdep->snew, B0); 1652#endif 1653 1654 fSalarm = FALSE; 1655 1656 if (fsysdep_catch ()) 1657 { 1658 usysdep_start_catch (); 1659 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 1660 (void) alarm (30); 1661 1662 (void) fsetterminfodrain (qsysdep->o, &qsysdep->snew); 1663 } 1664 1665 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 1666 (void) alarm (0); 1667 usysdep_end_catch (); 1668 1669 /* Let the port settle. */ 1670 sleep (2); 1671 } 1672#endif /* ! HAVE_RESET_BUG */ 1673 1674 if (! fsserial_close (qsysdep)) 1675 fret = FALSE; 1676 1677 return fret; 1678} 1679 1680/* Close a direct port. */ 1681 1682/*ARGSUSED*/ 1683static boolean 1684fsdirect_close (qconn, puuconf, qdialer, fsuccess) 1685 struct sconnection *qconn; 1686 pointer puuconf ATTRIBUTE_UNUSED; 1687 struct uuconf_dialer *qdialer ATTRIBUTE_UNUSED; 1688 boolean fsuccess ATTRIBUTE_UNUSED; 1689{ 1690 return fsserial_close ((struct ssysdep_conn *) qconn->psysdep); 1691} 1692 1693/* Begin dialing out on a modem port. This opens the dialer device if 1694 there is one. */ 1695 1696boolean 1697fsysdep_modem_begin_dial (qconn, qdial) 1698 struct sconnection *qconn; 1699 struct uuconf_dialer *qdial; 1700{ 1701 struct ssysdep_conn *qsysdep; 1702 const char *z; 1703 1704 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 1705 1706#ifdef TIOCMODEM 1707 /* If we can tell the modem to obey modem control, do so. */ 1708 { 1709 int iperm; 1710 1711 iperm = 0; 1712 (void) ioctl (qsysdep->o, TIOCMODEM, &iperm); 1713 } 1714#endif /* TIOCMODEM */ 1715 1716 /* If we supposed to toggle DTR, do so. */ 1717 1718 if (qdial->uuconf_fdtr_toggle) 1719 { 1720#ifdef TIOCCDTR 1721 (void) ioctl (qsysdep->o, TIOCCDTR, 0); 1722 sleep (2); 1723 (void) ioctl (qsysdep->o, TIOCSDTR, 0); 1724#else /* ! defined (TIOCCDTR) */ 1725 if (qsysdep->fterminal) 1726 { 1727 sterminal sbaud; 1728 1729 sbaud = qsysdep->snew; 1730 1731#if HAVE_BSD_TTY 1732 sbaud.stty.sg_ispeed = B0; 1733 sbaud.stty.sg_ospeed = B0; 1734#endif 1735#if HAVE_SYSV_TERMIO 1736 sbaud.c_cflag = (sbaud.c_cflag &~ CBAUD) | B0; 1737#endif 1738#if HAVE_POSIX_TERMIOS 1739 (void) cfsetospeed (&sbaud, B0); 1740#endif 1741 1742 (void) fsetterminfodrain (qsysdep->o, &sbaud); 1743 sleep (2); 1744 (void) fsetterminfo (qsysdep->o, &qsysdep->snew); 1745 } 1746#endif /* ! defined (TIOCCDTR) */ 1747 1748 if (qdial->uuconf_fdtr_toggle_wait) 1749 sleep (2); 1750 } 1751 1752 if (! fsmodem_carrier (qconn, FALSE)) 1753 return FALSE; 1754 1755 /* Open the dial device if there is one. */ 1756 z = qconn->qport->uuconf_u.uuconf_smodem.uuconf_zdial_device; 1757 if (z != NULL) 1758 { 1759 char *zfree; 1760 int o; 1761 1762 qsysdep->ohold = qsysdep->o; 1763 1764 zfree = NULL; 1765 if (*z != '/') 1766 { 1767 zfree = zbufalc (sizeof "/dev/" + strlen (z)); 1768 sprintf (zfree, "/dev/%s", z); 1769 z = zfree; 1770 } 1771 1772 o = open ((char *) z, O_RDWR | O_NOCTTY); 1773 if (o < 0) 1774 { 1775 ulog (LOG_ERROR, "open (%s): %s", z, strerror (errno)); 1776 ubuffree (zfree); 1777 return FALSE; 1778 } 1779 ubuffree (zfree); 1780 1781 if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0) 1782 { 1783 ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); 1784 (void) close (o); 1785 return FALSE; 1786 } 1787 1788 qsysdep->o = o; 1789 } 1790 1791 return TRUE; 1792} 1793 1794/* Tell the port to require or not require carrier. On BSD this uses 1795 TIOCCAR and TIOCNCAR, which I assume are generally supported (it 1796 can also use the LNOMDM bit supported by IS68K Unix). On System V 1797 it resets or sets CLOCAL. We only require carrier if the port 1798 supports it. This will only be called with fcarrier TRUE if the 1799 dialer supports carrier. */ 1800 1801static boolean 1802fsmodem_carrier (qconn, fcarrier) 1803 struct sconnection *qconn; 1804 boolean fcarrier; 1805{ 1806 register struct ssysdep_conn *q; 1807 struct uuconf_modem_port *qm; 1808 1809 q = (struct ssysdep_conn *) qconn->psysdep; 1810 1811 if (! q->fterminal) 1812 return TRUE; 1813 1814 qm = &qconn->qport->uuconf_u.uuconf_smodem; 1815 if (fcarrier) 1816 { 1817 if (qm->uuconf_fcarrier) 1818 { 1819#ifdef TIOCCAR 1820 /* Tell the modem to pay attention to carrier. */ 1821 if (ioctl (q->o, TIOCCAR, 0) < 0) 1822 { 1823 ulog (LOG_ERROR, "ioctl (TIOCCAR): %s", strerror (errno)); 1824 return FALSE; 1825 } 1826#endif /* TIOCCAR */ 1827 1828#if HAVE_BSD_TTY 1829#ifdef LNOMDM 1830 /* IS68K Unix uses a local LNOMDM bit. */ 1831 { 1832 int iparam; 1833 1834 iparam = LNOMDM; 1835 if (ioctl (q->o, TIOCLBIC, &iparam) < 0) 1836 { 1837 ulog (LOG_ERROR, "ioctl (TIOCLBIC, LNOMDM): %s", 1838 strerror (errno)); 1839 return FALSE; 1840 } 1841 } 1842#endif /* LNOMDM */ 1843#endif /* HAVE_BSD_TTY */ 1844 1845#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1846 /* Put the modem into nonlocal mode. */ 1847 q->snew.c_cflag &=~ CLOCAL; 1848 if (! fsetterminfo (q->o, &q->snew)) 1849 { 1850 ulog (LOG_ERROR, "Can't clear CLOCAL: %s", strerror (errno)); 1851 return FALSE; 1852 } 1853#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1854 } 1855 1856 /* Turn on hardware flow control after turning on carrier. We 1857 don't do it until now because some modems don't assert the 1858 right signals until they see carrier. */ 1859 if (! fsserial_hardflow (qconn, qm->uuconf_fhardflow)) 1860 return FALSE; 1861 } 1862 else 1863 { 1864 /* Turn off any hardware flow control before turning off 1865 carrier. */ 1866 if (! fsserial_hardflow (qconn, FALSE)) 1867 return FALSE; 1868 1869#ifdef TIOCNCAR 1870 /* Tell the modem to ignore carrier. */ 1871 if (ioctl (q->o, TIOCNCAR, 0) < 0) 1872 { 1873 ulog (LOG_ERROR, "ioctl (TIOCNCAR): %s", strerror (errno)); 1874 return FALSE; 1875 } 1876#endif /* TIOCNCAR */ 1877 1878#if HAVE_BSD_TTY 1879#ifdef LNOMDM 1880 /* IS68K Unix uses a local LNOMDM bit. */ 1881 { 1882 int iparam; 1883 1884 iparam = LNOMDM; 1885 if (ioctl (q->o, TIOCLBIS, &iparam) < 0) 1886 { 1887 ulog (LOG_ERROR, "ioctl (TIOCLBIS, LNOMDM): %s", 1888 strerror (errno)); 1889 return FALSE; 1890 } 1891 } 1892#endif /* LNOMDM */ 1893#endif /* HAVE_BSD_TTY */ 1894 1895#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1896 /* Put the modem into local mode (ignore carrier) to start the chat 1897 script. */ 1898 q->snew.c_cflag |= CLOCAL; 1899 if (! fsetterminfo (q->o, &q->snew)) 1900 { 1901 ulog (LOG_ERROR, "Can't set CLOCAL: %s", strerror (errno)); 1902 return FALSE; 1903 } 1904 1905#if HAVE_CLOCAL_BUG 1906 /* On SCO and AT&T UNIX PC you have to reopen the port. */ 1907 { 1908 int onew; 1909 1910 onew = open (q->zdevice, O_RDWR); 1911 if (onew < 0) 1912 { 1913 ulog (LOG_ERROR, "open (%s): %s", q->zdevice, strerror (errno)); 1914 return FALSE; 1915 } 1916 1917 if (fcntl (onew, F_SETFD, 1918 fcntl (onew, F_GETFD, 0) | FD_CLOEXEC) < 0) 1919 { 1920 ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); 1921 (void) close (onew); 1922 return FALSE; 1923 } 1924 1925 (void) close (q->o); 1926 q->o = onew; 1927 } 1928#endif /* HAVE_CLOCAL_BUG */ 1929 1930#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 1931 } 1932 1933 return TRUE; 1934} 1935 1936/* Tell the port to use hardware flow control. There is no standard 1937 mechanism for controlling this. This implementation supports 1938 CRTSCTS and CRTSXOFF on SunOS/Solaris, RTS/CTSFLOW on 386(ish) 1939 unix, CTSCD on the 3b1, CCTS_OFLOW/CRTS_IFLOW on BSDI, 1940 TXADDCD/TXDELCD on AIX, IRTS on NCR Tower, and TCGETX/TCSETX on 1941 HP/UX. If you know how to do it on other systems, please implement 1942 it and send me the patches. */ 1943 1944static boolean 1945fsserial_hardflow (qconn, fhardflow) 1946 struct sconnection *qconn; 1947 boolean fhardflow; 1948{ 1949 register struct ssysdep_conn *q; 1950 1951 q = (struct ssysdep_conn *) qconn->psysdep; 1952 1953 if (! q->fterminal) 1954 return TRUE; 1955 1956 /* Don't do anything if we don't know what to do. */ 1957#if HAVE_BSD_TTY 1958#define HAVE_HARDFLOW 0 1959#endif 1960#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1961#if ! HAVE_TXADDCD 1962#ifndef CRTSFL 1963#ifndef CRTSCTS 1964#ifndef CTSCD 1965#ifndef CCTS_OFLOW 1966#ifndef IRTS 1967#define HAVE_HARDFLOW 0 1968#endif 1969#endif 1970#endif 1971#endif 1972#endif 1973#endif 1974#endif 1975 1976#ifndef HAVE_HARDFLOW 1977#define HAVE_HARDFLOW 1 1978#endif 1979 1980#if HAVE_HARDFLOW 1981 if (fhardflow) 1982 { 1983#if HAVE_TXADDCD 1984 /* The return value does not reliably indicate whether this 1985 actually succeeded. */ 1986 (void) ioctl (q->o, TXADDCD, "rts"); 1987#else /* ! HAVE_TXADDCD */ 1988#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 1989#ifdef CRTSFL 1990 q->snew.c_cflag |= CRTSFL; 1991 q->snew.c_cflag &=~ (RTSFLOW | CTSFLOW); 1992#endif /* defined (CRTSFL) */ 1993#ifdef CRTSCTS 1994 q->snew.c_cflag |= CRTSCTS; 1995#endif /* defined (CRTSCTS) */ 1996#ifdef CRTSXOFF 1997 q->snew.c_cflag |= CRTSXOFF; 1998#endif /* defined (CRTSXOFF) */ 1999#ifdef CTSCD 2000 q->snew.c_cflag |= CTSCD; 2001#endif /* defined (CTSCD) */ 2002#ifdef CCTS_OFLOW 2003 q->snew.c_cflag |= CCTS_OFLOW | CRTS_IFLOW; 2004#endif 2005#ifdef IRTS 2006 q->snew.c_iflag |= IRTS; 2007#endif 2008#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 2009 if (! fsetterminfo (q->o, &q->snew)) 2010 { 2011 ulog (LOG_ERROR, "Can't enable hardware flow control: %s", 2012 strerror (errno)); 2013 return FALSE; 2014 } 2015#if HAVE_SYS_TERMIOX 2016#ifdef TCGETX 2017 { 2018 struct termiox tx; 2019 2020 if (ioctl (q->o, TCGETX, &tx) < 0) 2021 { 2022 ulog (LOG_ERROR, 2023 "Can't enable hardware flow control: ioctl (TCGETX): %s", 2024 strerror (errno)); 2025 return FALSE; 2026 } 2027 tx.x_hflag |= RTSXOFF | CTSXON; 2028 if (ioctl (q->o, TCSETX, &tx) < 0) 2029 { 2030 ulog (LOG_ERROR, 2031 "Can't enable hardware flow control: ioctl (TCSETX): %s", 2032 strerror (errno)); 2033 return FALSE; 2034 } 2035 } 2036#endif /* TCGETX */ 2037#endif /* HAVE_SYS_TERMIOX */ 2038#endif /* ! HAVE_TXADDCD */ 2039 } 2040 else 2041 { 2042#if HAVE_TXADDCD 2043 /* The return value does not reliably indicate whether this 2044 actually succeeded. */ 2045 (void) ioctl (q->o, TXDELCD, "rts"); 2046#else /* ! HAVE_TXADDCD */ 2047#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 2048#ifdef CRTSFL 2049 q->snew.c_cflag &=~ CRTSFL; 2050 q->snew.c_cflag &=~ (RTSFLOW | CTSFLOW); 2051#endif /* defined (CRTSFL) */ 2052#ifdef CRTSCTS 2053 q->snew.c_cflag &=~ CRTSCTS; 2054#endif /* defined (CRTSCTS) */ 2055#ifdef CRTSXOFF 2056 q->snew.c_cflag &=~ CRTSXOFF; 2057#endif /* defined (CRTSXOFF) */ 2058#ifdef CTSCD 2059 q->snew.c_cflag &=~ CTSCD; 2060#endif /* defined (CTSCD) */ 2061#ifdef CCTS_OFLOW 2062 q->snew.c_cflag &=~ (CCTS_OFLOW | CRTS_IFLOW); 2063#endif 2064#ifdef IRTS 2065 q->snew.c_iflag &=~ IRTS; 2066#endif 2067#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 2068 if (! fsetterminfo (q->o, &q->snew)) 2069 { 2070 ulog (LOG_ERROR, "Can't disable hardware flow control: %s", 2071 strerror (errno)); 2072 return FALSE; 2073 } 2074#if HAVE_SYS_TERMIOX 2075#ifdef TCGETX 2076 { 2077 struct termiox tx; 2078 2079 if (ioctl (q->o, TCGETX, &tx) < 0) 2080 { 2081 ulog (LOG_ERROR, 2082 "Can't disable hardware flow control: ioctl (TCGETX): %s", 2083 strerror (errno)); 2084 return FALSE; 2085 } 2086 tx.x_hflag &=~ (RTSXOFF | CTSXON); 2087 if (ioctl (q->o, TCSETX, &tx) < 0) 2088 { 2089 ulog (LOG_ERROR, 2090 "Can't disable hardware flow control: ioctl (TCSETX): %s", 2091 strerror (errno)); 2092 return FALSE; 2093 } 2094 } 2095#endif /* TCGETX */ 2096#endif /* HAVE_SYS_TERMIOX */ 2097#endif /* ! HAVE_TXADDCD */ 2098 } 2099#endif /* HAVE_HARDFLOW */ 2100 2101 return TRUE; 2102} 2103 2104/* Finish dialing out on a modem by closing any dialer device and waiting 2105 for carrier. */ 2106 2107boolean 2108fsysdep_modem_end_dial (qconn, qdial) 2109 struct sconnection *qconn; 2110 struct uuconf_dialer *qdial; 2111{ 2112 struct ssysdep_conn *q; 2113 2114 q = (struct ssysdep_conn *) qconn->psysdep; 2115 2116 if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_zdial_device != NULL) 2117 { 2118 (void) close (q->o); 2119 q->o = q->ohold; 2120 } 2121 2122 if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_fcarrier 2123 && qdial->uuconf_fcarrier) 2124 { 2125 /* Tell the port that we need carrier. */ 2126 if (! fsmodem_carrier (qconn, TRUE)) 2127 return FALSE; 2128 2129#ifdef TIOCWONLINE 2130 2131 /* We know how to wait for carrier, so do so. */ 2132 2133 /* If we already got a signal, just quit now. */ 2134 if (FGOT_QUIT_SIGNAL ()) 2135 return FALSE; 2136 2137 /* This bit of code handles signals just like fsysdep_conn_read 2138 does. See that function for a longer explanation. */ 2139 2140 /* Use fsysdep_catch to handle a longjmp from the signal 2141 handler. */ 2142 2143 fSalarm = FALSE; 2144 2145 if (fsysdep_catch ()) 2146 { 2147 /* Start catching SIGALRM; normally we ignore it. */ 2148 usysdep_start_catch (); 2149 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 2150 (void) alarm (qdial->uuconf_ccarrier_wait); 2151 2152 /* We really don't care if we get an error, since that will 2153 probably just mean that TIOCWONLINE isn't supported in 2154 which case there's nothing we can do anyhow. If we get 2155 SIGINT we want to keep waiting for carrier, because 2156 SIGINT just means don't start any new sessions. We don't 2157 handle SIGINT correctly if we do a longjmp in the signal 2158 handler; too bad. */ 2159 while (ioctl (q->o, TIOCWONLINE, 0) < 0 2160 && errno == EINTR) 2161 { 2162 /* Log the signal. */ 2163 ulog (LOG_ERROR, (const char *) NULL); 2164 if (FGOT_QUIT_SIGNAL () || fSalarm) 2165 break; 2166 } 2167 } 2168 2169 /* Turn off the pending SIGALRM and ignore SIGALARM again. */ 2170 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 2171 (void) alarm (0); 2172 usysdep_end_catch (); 2173 2174 /* If we got a random signal, just return FALSE. */ 2175 if (FGOT_QUIT_SIGNAL ()) 2176 return FALSE; 2177 2178 /* If we timed out, give an error. */ 2179 if (fSalarm) 2180 { 2181 ulog (LOG_ERROR, "Timed out waiting for carrier"); 2182 return FALSE; 2183 } 2184 2185#else /* ! defined (TIOCWONLINE) */ 2186 2187 /* Try to open the port again without using O_NDELAY. In 2188 principle, the open should delay until carrier is available. 2189 This may not work on some systems, so we just ignore any 2190 errors. */ 2191 { 2192 int onew; 2193 2194 onew = open (q->zdevice, O_RDWR); 2195 if (onew >= 0) 2196 { 2197 boolean fbad; 2198 int iflags; 2199 2200 fbad = FALSE; 2201 2202 if (fcntl (onew, F_SETFD, 2203 fcntl (onew, F_GETFD, 0) | FD_CLOEXEC) < 0) 2204 fbad = TRUE; 2205 2206 if (! fbad) 2207 { 2208 iflags = fcntl (onew, F_GETFL, 0); 2209 if (iflags < 0 2210 || ! fsetterminfo (onew, &q->snew)) 2211 fbad = TRUE; 2212 } 2213 2214 if (fbad) 2215 (void) close (onew); 2216 else 2217 { 2218 (void) close (q->o); 2219 q->o = onew; 2220 q->iflags = iflags; 2221#if HAVE_TIOCSINUSE 2222 (void) ioctl (onew, TIOCSINUSE, 0); 2223#endif 2224 } 2225 } 2226 } 2227 2228#endif /* ! defined (TIOCWONLINE) */ 2229 } 2230 2231 return TRUE; 2232} 2233 2234/* Read data from a connection, with a timeout. This routine handles 2235 all types of connections, including TLI. 2236 2237 This function should return when we have read cmin characters or 2238 the timeout has occurred. We have to work a bit to get Unix to do 2239 this efficiently on a terminal. The simple implementation 2240 schedules a SIGALRM signal and then calls read; if there is a 2241 single character available, the call to read will return 2242 immediately, so there must be a loop which terminates when the 2243 SIGALRM is delivered or the correct number of characters has been 2244 read. This can be very inefficient with a fast CPU or a low baud 2245 rate (or both!), since each call to read may return only one or two 2246 characters. 2247 2248 Under POSIX or System V, we can specify a minimum number of 2249 characters to read, so there is no serious trouble. 2250 2251 Under BSD, we figure out how many characters we have left to read, 2252 how long it will take for them to arrive at the current baud rate, 2253 and sleep that long. 2254 2255 Doing this with a timeout and avoiding all possible race conditions 2256 get very hairy, though. Basically, we're going to schedule a 2257 SIGALRM for when the timeout expires. I don't really want to do a 2258 longjmp in the SIGALRM handler, though, because that may lose data. 2259 Therefore, I have the signal handler set a variable. However, this 2260 means that there will be a span of time between the time the code 2261 checks the variable and the time it calls the read system call; if 2262 the SIGALRM occurs during that time, the read might hang forever. 2263 To avoid this, the SIGALRM handler not only sets a global variable, 2264 it also schedules another SIGALRM for one second in the future 2265 (POSIX specifies that a signal handler is permitted to safely call 2266 alarm). To avoid getting a continual sequence of SIGALRM 2267 interrupts, we change the signal handler to ignore SIGALRM when 2268 we're about to exit the function. This means that every time we 2269 execute fsysdep_conn_read we make at least five system calls. It's 2270 the best I've been able to come up with, though. 2271 2272 When fsysdep_conn_read finishes, there will be no SIGALRM scheduled 2273 and SIGALRM will be ignored. */ 2274 2275boolean 2276fsysdep_conn_read (qconn, zbuf, pclen, cmin, ctimeout, freport) 2277 struct sconnection *qconn; 2278 char *zbuf; 2279 size_t *pclen; 2280 size_t cmin; 2281 int ctimeout; 2282 boolean freport; 2283{ 2284 CATCH_PROTECT size_t cwant; 2285 boolean fret; 2286 register struct ssysdep_conn * const q 2287 = (struct ssysdep_conn *) qconn->psysdep; 2288 int cwouldblock; 2289 2290 cwant = *pclen; 2291 *pclen = 0; 2292 2293 /* Guard against a bad timeout. We return TRUE when a timeout 2294 expires. It is possible to get a negative timeout here because 2295 the calling code does not check user supplied timeouts for 2296 plausibility. */ 2297 if (ctimeout <= 0) 2298 return TRUE; 2299 2300 /* We want to do a blocking read. */ 2301 if (! fsblock (q, TRUE)) 2302 return FALSE; 2303 2304 fSalarm = FALSE; 2305 2306 /* We're going to set up an alarm signal to last for the entire 2307 read. If the read system call cannot be interrupted, the signal 2308 handler will do a longjmp causing fsysdep_catch (a macro) to 2309 return FALSE. We handle that here. If read can be interrupted, 2310 fsysdep_catch will be defined to TRUE. */ 2311 if (fsysdep_catch ()) 2312 { 2313 /* Prepare to catch SIGALRM and schedule the signal. */ 2314 usysdep_start_catch (); 2315 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 2316 alarm (ctimeout); 2317 } 2318 else 2319 { 2320 /* We caught a signal. We don't actually have to do anything, 2321 as all the appropriate checks are made at the start of the 2322 following loop. */ 2323 } 2324 2325 fret = FALSE; 2326 2327 cwouldblock = 0; 2328 while (TRUE) 2329 { 2330 int cgot; 2331 2332#if HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS 2333 /* If we can tell the terminal not to return until we have a 2334 certain number of characters, do so. */ 2335 if (q->fterminal) 2336 { 2337 int csetmin; 2338 2339 /* I'm not that confident about setting MIN to values larger 2340 than 127, although up to 255 would probably work. */ 2341 if (cmin < 127) 2342 csetmin = cmin; 2343 else 2344 csetmin = 127; 2345 2346 if (csetmin != cSmin) 2347 { 2348 q->snew.c_cc[VMIN] = csetmin; 2349 while (! fsetterminfo (q->o, &q->snew)) 2350 { 2351 if (errno != EINTR 2352 || FGOT_QUIT_SIGNAL ()) 2353 { 2354 int ierr; 2355 2356 /* We turn off the signal before reporting the 2357 error to minimize any problems with 2358 interrupted system calls. */ 2359 ierr = errno; 2360 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 2361 alarm (0); 2362 usysdep_end_catch (); 2363 ulog (LOG_ERROR, "Can't set MIN for terminal: %s", 2364 strerror (ierr)); 2365 return FALSE; 2366 } 2367 2368 if (fSalarm) 2369 { 2370 ulog (LOG_ERROR, 2371 "Timed out when setting MIN to %d; retrying", 2372 csetmin); 2373 fSalarm = FALSE; 2374 alarm (ctimeout); 2375 } 2376 } 2377 cSmin = csetmin; 2378 } 2379 } 2380#endif /* HAVE_SYSV_TERMIO || HAVE_POSIX_TERMIOS */ 2381 2382 /* If we've received a signal, get out now. */ 2383 if (FGOT_QUIT_SIGNAL ()) 2384 break; 2385 2386 /* If we've already gotten a SIGALRM, get out with whatever 2387 we've accumulated. */ 2388 if (fSalarm) 2389 { 2390 fret = TRUE; 2391 break; 2392 } 2393 2394 /* Right here is the race condition which we avoid by having the 2395 SIGALRM handler schedule another SIGALRM. */ 2396#if HAVE_TLI 2397 if (q->ftli) 2398 { 2399 int iflags; 2400 2401 cgot = t_rcv (q->o, zbuf, cwant, &iflags); 2402 if (cgot < 0 && t_errno != TSYSERR) 2403 { 2404 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 2405 alarm (0); 2406 usysdep_end_catch (); 2407 2408 if (freport) 2409 ulog (LOG_ERROR, "t_rcv: %s", 2410 (t_errno >= 0 && t_errno < t_nerr 2411 ? t_errlist[t_errno] 2412 : "unknown TLI error")); 2413 2414 return FALSE; 2415 } 2416 } 2417 else 2418#endif 2419 cgot = read (q->o, zbuf, cwant); 2420 2421 /* If the read returned an error, check for signals. */ 2422 if (cgot < 0) 2423 { 2424 if (errno == EINTR) 2425 { 2426 /* Log the signal. */ 2427 ulog (LOG_ERROR, (const char *) NULL); 2428 } 2429 if (fSalarm) 2430 { 2431 fret = TRUE; 2432 break; 2433 } 2434 if (FGOT_QUIT_SIGNAL ()) 2435 break; 2436 } 2437 2438 /* If read returned an error, get out. We just ignore EINTR 2439 here, since it must be from some signal we don't care about. 2440 If the read returned 0 then the line must have been hung up 2441 (normally we would have received SIGHUP, but we can't count 2442 on that). We turn off the signals before calling ulog to 2443 reduce problems with interrupted system calls. */ 2444 if (cgot > 0) 2445 cwouldblock = 0; 2446 else 2447 { 2448 if (cgot < 0 && errno == EINTR) 2449 cgot = 0; 2450 else if (cgot < 0 2451 && (errno == EAGAIN || errno == EWOULDBLOCK) 2452 && cwouldblock < 2) 2453 { 2454 /* Incomprehensibly, on some systems the read will 2455 return EWOULDBLOCK even though the descriptor has 2456 been set to blocking mode. We permit the read call 2457 to do this twice in a row, and then error out. We 2458 don't want to permit an arbitrary number of 2459 EWOULDBLOCK errors, since that could hang us up 2460 indefinitely. */ 2461 ++cwouldblock; 2462 cgot = 0; 2463 } 2464 else 2465 { 2466 int ierr; 2467 2468 ierr = errno; 2469 2470 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 2471 alarm (0); 2472 usysdep_end_catch (); 2473 2474 if (freport) 2475 { 2476 if (cgot == 0) 2477 ulog (LOG_ERROR, "Line disconnected"); 2478 else 2479 ulog (LOG_ERROR, "read: %s", strerror (ierr)); 2480 } 2481 2482 return FALSE; 2483 } 2484 } 2485 2486 cwant -= cgot; 2487 if ((size_t) cgot >= cmin) 2488 cmin = 0; 2489 else 2490 cmin -= cgot; 2491 zbuf += cgot; 2492 *pclen += cgot; 2493 2494 /* If we have enough data, get out now. */ 2495 if (cmin == 0) 2496 { 2497 fret = TRUE; 2498 break; 2499 } 2500 2501#if HAVE_BSD_TTY 2502 /* We still want more data, so sleep long enough for the rest of 2503 it to arrive. We don't this for System V or POSIX because 2504 setting MIN is good enough (we can't sleep longer than it 2505 takes to get MAX_INPUT characters anyhow). 2506 2507 The baud rate is approximately 10 times the number of 2508 characters which will arrive in one second, so the number of 2509 milliseconds to sleep == 2510 characters * (milliseconds / character) == 2511 characters * (1000 * (seconds / character)) == 2512 characters * (1000 * (1 / (baud / 10))) == 2513 characters * (10000 / baud) 2514 2515 We arbitrarily reduce the sleep amount by 10 milliseconds to 2516 attempt to account for the amount of time it takes to set up 2517 the sleep. This is how long it takes to get half a character 2518 at 19200 baud. We then don't bother to sleep for less than 2519 10 milliseconds. We don't sleep if the read was interrupted. 2520 2521 We use select to sleep. It would be easy to use poll as 2522 well, but it's unlikely that any system with BSD ttys would 2523 have poll but not select. Using select avoids hassles with 2524 the pending SIGALRM; if it hits the select will be 2525 interrupted, and otherwise the select will not affect it. */ 2526 2527#if ! HAVE_SELECT 2528 #error This code requires select; feel free to extend it 2529#endif 2530 2531 if (q->fterminal && cmin > 1 && cgot > 0) 2532 { 2533 int csleepchars; 2534 int isleep; 2535 2536 /* We don't try to read all the way up to MAX_INPUT, 2537 since that might drop a character. */ 2538 if (cmin <= MAX_INPUT - 10) 2539 csleepchars = cmin; 2540 else 2541 csleepchars = MAX_INPUT - 10; 2542 2543 isleep = (int) (((long) csleepchars * 10000L) / q->ibaud); 2544 isleep -= 10; 2545 2546 if (isleep > 10) 2547 { 2548 struct timeval s; 2549 2550 s.tv_sec = isleep / 1000; 2551 s.tv_usec = (isleep % 1000) * 1000; 2552 2553 /* Some versions of select take a pointer to an int, 2554 while some take a pointer to an fd_set. I just cast 2555 the arguments to a generic pointer, and assume that 2556 any machine which distinguishes int * from fd_set * 2557 (I would be amazed if there are any such machines) 2558 have an appropriate prototype somewhere or other. */ 2559 (void) select (0, (pointer) NULL, (pointer) NULL, 2560 (pointer) NULL, &s); 2561 2562 /* Here either the select finished sleeping or we got a 2563 SIGALRM. If the latter occurred, fSalarm was set to 2564 TRUE; it will be checked at the top of the loop. */ 2565 } 2566 } 2567#endif /* HAVE_BSD_TTY */ 2568 } 2569 2570 /* Turn off the pending SIGALRM and return. */ 2571 2572 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 2573 alarm (0); 2574 usysdep_end_catch (); 2575 2576 return fret; 2577} 2578 2579/* Read from a port with separate read/write file descriptors. */ 2580 2581boolean 2582fsdouble_read (qconn, zbuf, pclen, cmin, ctimeout, freport) 2583 struct sconnection *qconn; 2584 char *zbuf; 2585 size_t *pclen; 2586 size_t cmin; 2587 int ctimeout; 2588 boolean freport; 2589{ 2590 struct ssysdep_conn *qsysdep; 2591 2592 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 2593 qsysdep->o = qsysdep->ord; 2594 return fsysdep_conn_read (qconn, zbuf, pclen, cmin, ctimeout, freport); 2595} 2596 2597/* Write data to a connection. This routine handles all types of 2598 connections, including TLI. */ 2599 2600boolean 2601fsysdep_conn_write (qconn, zwrite, cwrite) 2602 struct sconnection *qconn; 2603 const char *zwrite; 2604 size_t cwrite; 2605{ 2606 struct ssysdep_conn *q; 2607 int czero; 2608 2609 q = (struct ssysdep_conn *) qconn->psysdep; 2610 2611 /* We want blocking writes here. */ 2612 if (! fsblock (q, TRUE)) 2613 return FALSE; 2614 2615 czero = 0; 2616 2617 while (cwrite > 0) 2618 { 2619 int cdid; 2620 2621 /* Loop until we don't get an interrupt. */ 2622 while (TRUE) 2623 { 2624 /* If we've received a signal, don't continue. */ 2625 if (FGOT_QUIT_SIGNAL ()) 2626 return FALSE; 2627 2628#if HAVE_TLI 2629 if (q->ftli) 2630 { 2631 cdid = t_snd (q->o, (char *) zwrite, cwrite, 0); 2632 if (cdid < 0 && t_errno != TSYSERR) 2633 { 2634 ulog (LOG_ERROR, "t_snd: %s", 2635 (t_errno >= 0 && t_errno < t_nerr 2636 ? t_errlist[t_errno] 2637 : "unknown TLI error")); 2638 return FALSE; 2639 } 2640 } 2641 else 2642#endif 2643 cdid = write (q->o, zwrite, cwrite); 2644 2645 if (cdid >= 0) 2646 break; 2647 if (errno != EINTR) 2648 break; 2649 2650 /* We were interrupted by a signal. Log it. */ 2651 ulog (LOG_ERROR, (const char *) NULL); 2652 } 2653 2654 if (cdid < 0) 2655 { 2656 if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENODATA) 2657 { 2658 ulog (LOG_ERROR, "write: %s", strerror (errno)); 2659 return FALSE; 2660 } 2661 cdid = 0; 2662 } 2663 2664 if (cdid == 0) 2665 { 2666 /* On some systems write will return 0 if carrier is lost. 2667 If we fail to write anything ten times in a row, we 2668 assume that this has happened. This is hacked in like 2669 this because there seems to be no reliable way to tell 2670 exactly why the write returned 0. */ 2671 ++czero; 2672 if (czero >= 10) 2673 { 2674 ulog (LOG_ERROR, "Line disconnected"); 2675 return FALSE; 2676 } 2677 } 2678 else 2679 { 2680 czero = 0; 2681 2682 cwrite -= cdid; 2683 zwrite += cdid; 2684 } 2685 } 2686 2687 return TRUE; 2688} 2689 2690/* Write to a port with separate read/write file descriptors. */ 2691 2692boolean 2693fsdouble_write (qconn, zwrite, cwrite) 2694 struct sconnection *qconn; 2695 const char *zwrite; 2696 size_t cwrite; 2697{ 2698 struct ssysdep_conn *qsysdep; 2699 2700 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 2701 qsysdep->o = qsysdep->ord; 2702 if (! fsblock (qsysdep, TRUE)) 2703 return FALSE; 2704 qsysdep->o = qsysdep->owr; 2705 return fsysdep_conn_write (qconn, zwrite, cwrite); 2706} 2707 2708/* The fsysdep_conn_io routine is supposed to both read and write data 2709 until it has either filled its read buffer or written out all the 2710 data it was given. This lets us write out large packets without 2711 losing incoming data. It handles all types of connections, 2712 including TLI. */ 2713 2714boolean 2715fsysdep_conn_io (qconn, zwrite, pcwrite, zread, pcread) 2716 struct sconnection *qconn; 2717 const char *zwrite; 2718 size_t *pcwrite; 2719 char *zread; 2720 size_t *pcread; 2721{ 2722 struct ssysdep_conn *q; 2723 size_t cwrite, cread; 2724 int czero; 2725 2726 q = (struct ssysdep_conn *) qconn->psysdep; 2727 2728 cwrite = *pcwrite; 2729 *pcwrite = 0; 2730 cread = *pcread; 2731 *pcread = 0; 2732 2733 czero = 0; 2734 2735 while (TRUE) 2736 { 2737 int cgot, cdid; 2738 size_t cdo; 2739 2740 /* This used to always use nonblocking writes, but it turns out 2741 that some systems don't support them on terminals. 2742 2743 The current algorithm is: 2744 loop: 2745 unblocked read 2746 if read buffer full, return 2747 if nothing to write, return 2748 if HAVE_UNBLOCKED_WRITES 2749 write all data 2750 else 2751 write up to SINGLE_WRITE bytes 2752 if all data written, return 2753 if no data written 2754 if select works 2755 select on the write descriptor with a ten second timeout 2756 else 2757 blocked write of one byte with a ten second alarm 2758 2759 This algorithm should work whether the system supports 2760 unblocked writes on terminals or not. If the system supports 2761 unblocked writes but HAVE_UNBLOCKED_WRITES is 0, then it will 2762 call write more often than it needs to. If the system does 2763 not support unblocked writes but HAVE_UNBLOCKED_WRITES is 1, 2764 then the write may hang so long that incoming data is lost. 2765 This is actually possible at high baud rates on any system 2766 when a blocking write is done; there is no solution, except 2767 hardware handshaking. 2768 2769 If we were not able to write any data, then we need to block 2770 until we can write something. The code used to simply do a 2771 blocking write. However, that fails when a bidirectional 2772 protocol is permitted to push out enough bytes to fill the 2773 entire pipe between the two communicating uucico processes. 2774 They can both block on writing, because neither is reading. 2775 2776 In this case, we use select. We could select on both the 2777 read and write descriptor, but on some systems that would 2778 lead to calling read on each byte, which would be very 2779 inefficient. Instead, we select only on the write 2780 descriptor. After the select succeeds or times out, we retry 2781 the read. 2782 2783 Of course, some systems don't have select, and on some 2784 systems that have it it doesn't work on terminal devices. If 2785 we can't use select, then we do a blocked write of a single 2786 byte after setting an alarm. We only write a single byte to 2787 avoid any confusion as to whether or not the byte was 2788 actually written. */ 2789 2790 /* If we are running on standard input, we switch the file 2791 descriptors by hand. */ 2792 if (q->ord >= 0) 2793 q->o = q->ord; 2794 2795 /* Do an unblocked read. */ 2796 if (! fsblock (q, FALSE)) 2797 return FALSE; 2798 2799 /* Loop until we get something (error or data) other than an 2800 acceptable EINTR. */ 2801 while (TRUE) 2802 { 2803 /* If we've received a signal, don't continue. */ 2804 if (FGOT_QUIT_SIGNAL ()) 2805 return FALSE; 2806 2807#if HAVE_TLI 2808 if (q->ftli) 2809 { 2810 int iflags; 2811 2812 cgot = t_rcv (q->o, zread, cread, &iflags); 2813 if (cgot < 0) 2814 { 2815 if (t_errno == TNODATA) 2816 errno = EAGAIN; 2817 else if (t_errno != TSYSERR) 2818 { 2819 ulog (LOG_ERROR, "t_rcv: %s", 2820 (t_errno >= 0 && t_errno < t_nerr 2821 ? t_errlist[t_errno] 2822 : "unknown TLI error")); 2823 return FALSE; 2824 } 2825 } 2826 } 2827 else 2828#endif 2829 cgot = read (q->o, zread, cread); 2830 2831 if (cgot >= 0) 2832 break; 2833 if (errno != EINTR) 2834 break; 2835 2836 /* We got interrupted by a signal. Log it. */ 2837 ulog (LOG_ERROR, (const char *) NULL); 2838 } 2839 2840 if (cgot < 0) 2841 { 2842 if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENODATA) 2843 { 2844 ulog (LOG_ERROR, "read: %s", strerror (errno)); 2845 return FALSE; 2846 } 2847 cgot = 0; 2848 } 2849 2850 cread -= cgot; 2851 zread += cgot; 2852 *pcread += cgot; 2853 2854 /* If we've filled the read buffer, or we have nothing left to 2855 write, return out. */ 2856 if (cread == 0 || cwrite == 0) 2857 return TRUE; 2858 2859 /* The port is currently unblocked. Do a write. */ 2860 cdo = cwrite; 2861 2862#if ! HAVE_UNBLOCKED_WRITES 2863 if (q->fterminal && cdo > SINGLE_WRITE) 2864 cdo = SINGLE_WRITE; 2865#endif 2866 2867 if (q->owr >= 0) 2868 q->o = q->owr; 2869 2870 /* Loop until we get something besides EINTR. */ 2871 while (TRUE) 2872 { 2873 /* If we've received a signal, don't continue. */ 2874 if (FGOT_QUIT_SIGNAL ()) 2875 return FALSE; 2876 2877#if HAVE_TLI 2878 if (q->ftli) 2879 { 2880 cdid = t_snd (q->o, (char *) zwrite, cdo, 0); 2881 if (cdid < 0) 2882 { 2883 if (t_errno == TFLOW) 2884 errno = EAGAIN; 2885 else if (t_errno != TSYSERR) 2886 { 2887 ulog (LOG_ERROR, "t_snd: %s", 2888 (t_errno >= 0 && t_errno < t_nerr 2889 ? t_errlist[t_errno] 2890 : "unknown TLI error")); 2891 return FALSE; 2892 } 2893 } 2894 } 2895 else 2896#endif 2897 cdid = write (q->o, zwrite, cdo); 2898 2899 if (cdid >= 0) 2900 break; 2901 if (errno != EINTR) 2902 break; 2903 2904 /* We got interrupted by a signal. Log it. */ 2905 ulog (LOG_ERROR, (const char *) NULL); 2906 } 2907 2908 if (cdid < 0) 2909 { 2910 if (errno != EAGAIN && errno != EWOULDBLOCK && errno != ENODATA) 2911 { 2912 ulog (LOG_ERROR, "write: %s", strerror (errno)); 2913 return FALSE; 2914 } 2915 cdid = 0; 2916 } 2917 2918 if (cdid > 0) 2919 { 2920 /* We wrote some data. If we wrote everything, return out. 2921 Otherwise loop around and do another read. */ 2922 cwrite -= cdid; 2923 zwrite += cdid; 2924 *pcwrite += cdid; 2925 2926 if (cwrite == 0) 2927 return TRUE; 2928 2929 czero = 0; 2930 } 2931 else 2932 { 2933#if HAVE_SELECT 2934 struct timeval stime; 2935#ifdef FD_ZERO 2936 fd_set smask; 2937#else 2938 int smask; 2939#endif 2940 int c; 2941 2942 /* We didn't write any data. Call select. We use a timeout 2943 long enough for 1024 bytes to be sent. But we don't wait 2944 longer than the times it takes to receive cread bytes, in 2945 case our read buffer is small. 2946 secs/kbyte == (1024 bytes/kbyte * 10 bits/byte) / baud bits/sec 2947 usecs/kbyte == (((1024 bytes/kbyte * 1000000 usecs/sec) 2948 / baud bits/sec) 2949 * 10 bits/byte) 2950 2951 */ 2952 if (q->fterminal) 2953 { 2954 unsigned long cwait; 2955 2956 cwait = 1024; 2957 if (cwait > cread) 2958 cwait = cread; 2959 stime.tv_sec = (cwait * 10) / q->ibaud; 2960 stime.tv_usec = ((((cwait * 1000000) / q->ibaud) * 10) 2961 % 1000000); 2962 } 2963 else 2964 { 2965 /* This is some sort of network connection. We can't 2966 estimate how long it will take to write data. It 2967 also doesn't matter as much, as most systems will 2968 buffer much more incoming network data than they will 2969 incoming serial data. Sleep for a second, although 2970 normally the select will return sonner because we can 2971 write more data. */ 2972 stime.tv_sec = 1; 2973 stime.tv_usec = 0; 2974 } 2975 2976#ifdef FD_ZERO 2977 FD_ZERO (&smask); 2978 FD_SET (q->o, &smask); 2979#else 2980 smask = 1 << q->o; 2981 if (smask == 0) 2982 ulog (LOG_FATAL, "fsysdep_conn_io: File descriptors too large"); 2983#endif 2984 2985 /* If we've received a signal, don't continue. */ 2986 if (FGOT_QUIT_SIGNAL ()) 2987 return FALSE; 2988 2989 DEBUG_MESSAGE0 (DEBUG_PORT, "fsysdep_conn_io: Calling select"); 2990 2991 /* We don't bother to loop on EINTR. If we get a signal, we 2992 just loop around and try the read and write again. */ 2993 c = select (q->o + 1, (pointer) NULL, (pointer) &smask, 2994 (pointer) NULL, &stime); 2995 if (c < 0 && errno == EINTR) 2996 { 2997 /* We got interrupted by a signal. Log it. */ 2998 ulog (LOG_ERROR, (const char *) NULL); 2999 } 3000 else if (c >= 0) 3001 { 3002 /* The select either discovered that we could write 3003 something, or it timed out. Either way, we go around 3004 the main read/write loop again. */ 3005 } 3006 else 3007#endif /* HAVE_SELECT */ 3008 { 3009 int ierr; 3010 3011 /* Either the select failed for some reason other than 3012 EINTR, or the system does not support select at all. 3013 Fall back on a timed write. We don't worry about why 3014 the select might have failed, we just assume that it 3015 will not succeed on this descriptor. */ 3016 3017#if HAVE_RESTARTABLE_SYSCALLS 3018 /* If HAVE_RESTARTABLE_SYSCALLS, then receiving an alarm 3019 signal in the middle of a write will not cause the 3020 write to return EINTR, and the only way to interrupt 3021 the write is to longjmp out of it (see sysh.unx). 3022 That is unreliable, because it means that we won't 3023 know whether the byte was actually written or not. 3024 However, I believe that the only system on which we 3025 need to do this longjmp is BSD 4.2, and that system 3026 supports select, so we should never execute this 3027 case. */ 3028 ulog (LOG_FATAL, "fsysdep_conn_io: Unsupported case; see code"); 3029#endif 3030 3031 if (q->ord >= 0) 3032 q->o = q->ord; 3033 3034 if (! fsblock (q, TRUE)) 3035 return FALSE; 3036 3037 DEBUG_MESSAGE0 (DEBUG_PORT, "fsysdep_conn_io: Blocking write"); 3038 3039 if (q->owr >= 0) 3040 q->o = q->owr; 3041 3042 /* If we've received a signal, don't continue. */ 3043 if (FGOT_QUIT_SIGNAL ()) 3044 return FALSE; 3045 3046 /* Start up an alarm to interrupt the write. Note that 3047 we don't need to use the catch stuff, since we know 3048 that HAVE_RESTARTABLE_SYSCALLS is 0. */ 3049 usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL); 3050 if (q->fterminal) 3051 alarm ((int) ((long) 10240 / q->ibaud) + 1); 3052 else 3053 alarm (1); 3054 3055 /* There is a race condition here: on a severely loaded 3056 system, we could get the alarm before we start the 3057 write call. This would not be a disaster; often the 3058 write will succeed anyhow. */ 3059#if HAVE_TLI 3060 if (q->ftli) 3061 { 3062 cdid = t_snd (q->o, (char *) zwrite, 1, 0); 3063 if (cdid < 0 && t_errno != TSYSERR) 3064 { 3065 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 3066 alarm (0); 3067 ulog (LOG_ERROR, "t_snd: %s", 3068 (t_errno >= 0 && t_errno < t_nerr 3069 ? t_errlist[t_errno] 3070 : "unknown TLI error")); 3071 return FALSE; 3072 } 3073 } 3074 else 3075#endif 3076 cdid = write (q->o, zwrite, 1); 3077 3078 ierr = errno; 3079 3080 /* Note that we don't really care whether the write 3081 finished because the byte was written out or whether 3082 it finished because the alarm was triggered. Either 3083 way, we are going to loop around and try another 3084 read. */ 3085 3086 usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL); 3087 alarm (0); 3088 3089 if (cdid < 0) 3090 { 3091 if (ierr == EINTR) 3092 { 3093 /* We got interrupted by a signal. Log it. */ 3094 ulog (LOG_ERROR, (const char *) NULL); 3095 } 3096 else 3097 { 3098 ulog (LOG_ERROR, "write: %s", strerror (ierr)); 3099 return FALSE; 3100 } 3101 } 3102 else if (cdid == 0) 3103 { 3104 /* On some systems write will return 0 if carrier is 3105 lost. If we fail to write anything ten times in 3106 a row, we assume that this has happened. This is 3107 hacked in like this because there seems to be no 3108 reliable way to tell exactly why the write 3109 returned 0. */ 3110 ++czero; 3111 if (czero >= 10) 3112 { 3113 ulog (LOG_ERROR, "Line disconnected"); 3114 return FALSE; 3115 } 3116 } 3117 else 3118 { 3119 cwrite -= cdid; 3120 zwrite += cdid; 3121 *pcwrite += cdid; 3122 czero = 0; 3123 } 3124 } 3125 } 3126 } 3127} 3128 3129/* Send a break character to a serial port. */ 3130 3131static boolean 3132fsserial_break (qconn) 3133 struct sconnection *qconn; 3134{ 3135 struct ssysdep_conn *q; 3136 3137 q = (struct ssysdep_conn *) qconn->psysdep; 3138 3139#if HAVE_BSD_TTY 3140 (void) ioctl (q->o, TIOCSBRK, 0); 3141 sleep (2); 3142 (void) ioctl (q->o, TIOCCBRK, 0); 3143 return TRUE; 3144#endif /* HAVE_BSD_TTY */ 3145#if HAVE_SYSV_TERMIO 3146 (void) ioctl (q->o, TCSBRK, 0); 3147 return TRUE; 3148#endif /* HAVE_SYSV_TERMIO */ 3149#if HAVE_POSIX_TERMIOS 3150 return tcsendbreak (q->o, 0) == 0; 3151#endif /* HAVE_POSIX_TERMIOS */ 3152} 3153 3154/* Send a break character to a stdin port. */ 3155 3156static boolean 3157fsstdin_break (qconn) 3158 struct sconnection *qconn; 3159{ 3160 struct ssysdep_conn *qsysdep; 3161 3162 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 3163 qsysdep->o = qsysdep->owr; 3164 return fsserial_break (qconn); 3165} 3166 3167/* Change the setting of a serial port. */ 3168 3169/*ARGSUSED*/ 3170static boolean 3171fsserial_set (qconn, tparity, tstrip, txonxoff) 3172 struct sconnection *qconn; 3173 enum tparitysetting tparity; 3174 enum tstripsetting tstrip; 3175 enum txonxoffsetting txonxoff; 3176{ 3177 register struct ssysdep_conn *q; 3178 boolean fchanged, fdo; 3179 unsigned int iset = 0; 3180 unsigned int iclear = 0; 3181 3182 q = (struct ssysdep_conn *) qconn->psysdep; 3183 3184 if (! q->fterminal) 3185 return TRUE; 3186 3187 fchanged = FALSE; 3188 3189 /* Set the parity for output characters. */ 3190 3191#if HAVE_BSD_TTY 3192 3193 /* This will also cause parity detection on input characters. */ 3194 3195 fdo = FALSE; 3196 switch (tparity) 3197 { 3198 case PARITYSETTING_DEFAULT: 3199 break; 3200 case PARITYSETTING_NONE: 3201#if HAVE_PARITY_BUG 3202 /* The Sony NEWS mishandles this for some reason. */ 3203 iset = 0; 3204 iclear = ANYP; 3205#else 3206 iset = ANYP; 3207 iclear = 0; 3208#endif 3209 fdo = TRUE; 3210 break; 3211 case PARITYSETTING_EVEN: 3212 iset = EVENP; 3213 iclear = ODDP; 3214 fdo = TRUE; 3215 break; 3216 case PARITYSETTING_ODD: 3217 iset = ODDP; 3218 iclear = EVENP; 3219 fdo = TRUE; 3220 break; 3221 case PARITYSETTING_MARK: 3222 case PARITYSETTING_SPACE: 3223 /* Not supported. */ 3224 break; 3225 } 3226 3227 if (fdo) 3228 { 3229 if ((q->snew.stty.sg_flags & iset) != iset 3230 || (q->snew.stty.sg_flags & iclear) != 0) 3231 { 3232 q->snew.stty.sg_flags |= iset; 3233 q->snew.stty.sg_flags &=~ iclear; 3234 fchanged = TRUE; 3235 } 3236 } 3237 3238#else /* ! HAVE_BSD_TTY */ 3239 3240 fdo = FALSE; 3241 switch (tparity) 3242 { 3243 case PARITYSETTING_DEFAULT: 3244 break; 3245 case PARITYSETTING_NONE: 3246 iset = CS8; 3247 iclear = PARENB | PARODD | (CSIZE &~ CS8); 3248 fdo = TRUE; 3249 break; 3250 case PARITYSETTING_EVEN: 3251 iset = PARENB | CS7; 3252 iclear = PARODD | (CSIZE &~ CS7); 3253 fdo = TRUE; 3254 break; 3255 case PARITYSETTING_ODD: 3256 iset = PARENB | PARODD | CS7; 3257 iclear = CSIZE &~ CS7; 3258 fdo = TRUE; 3259 break; 3260 case PARITYSETTING_MARK: 3261 case PARITYSETTING_SPACE: 3262 /* Not supported. */ 3263 break; 3264 } 3265 3266 if (fdo) 3267 { 3268 if ((q->snew.c_cflag & iset) != iset 3269 || (q->snew.c_cflag & iclear) != 0) 3270 { 3271 q->snew.c_cflag |= iset; 3272 q->snew.c_cflag &=~ iclear; 3273 fchanged = TRUE; 3274 } 3275 } 3276 3277#endif /* ! HAVE_BSD_TTY */ 3278 3279 /* Set whether input characters are stripped to seven bits. */ 3280 3281#if HAVE_BSD_TTY 3282 3283#ifdef LPASS8 3284 { 3285 int i; 3286 3287 i = LPASS8; 3288 if (tstrip == STRIPSETTING_EIGHTBITS) 3289 { 3290 i = LPASS8; 3291 (void) ioctl (q->o, TIOCLBIS, &i); 3292 } 3293 else if (tstrip == STRIPSETTING_SEVENBITS) 3294 { 3295 i = LPASS8; 3296 (void) ioctl (q->o, TIOCLBIC, &i); 3297 } 3298 } 3299#endif 3300 3301#else /* ! HAVE_BSD_TTY */ 3302 3303 fdo = FALSE; 3304 switch (tstrip) 3305 { 3306 case STRIPSETTING_DEFAULT: 3307 break; 3308 case STRIPSETTING_EIGHTBITS: 3309 iset = 0; 3310 iclear = ISTRIP; 3311 fdo = TRUE; 3312 break; 3313 case STRIPSETTING_SEVENBITS: 3314 iset = ISTRIP; 3315 iclear = 0; 3316 fdo = TRUE; 3317 break; 3318 } 3319 3320 if (fdo) 3321 { 3322 if ((q->snew.c_iflag & iset) != iset 3323 || (q->snew.c_iflag & iclear) != 0) 3324 { 3325 q->snew.c_iflag |= iset; 3326 q->snew.c_iflag &=~ iclear; 3327 fchanged = TRUE; 3328 } 3329 } 3330 3331#endif /* ! HAVE_BSD_TTY */ 3332 3333 /* Set XON/XOFF handshaking. */ 3334 3335#if HAVE_BSD_TTY 3336 3337 fdo = FALSE; 3338 switch (txonxoff) 3339 { 3340 case XONXOFF_DEFAULT: 3341 break; 3342 case XONXOFF_OFF: 3343 iset = RAW; 3344 iclear = TANDEM | CBREAK; 3345 fdo = TRUE; 3346 break; 3347 case XONXOFF_ON: 3348 iset = CBREAK | TANDEM; 3349 iclear = RAW; 3350 fdo = TRUE; 3351 break; 3352 } 3353 3354 if (fdo) 3355 { 3356 if ((q->snew.stty.sg_flags & iset) != iset 3357 || (q->snew.stty.sg_flags & iclear) != 0) 3358 { 3359 q->snew.stty.sg_flags |= iset; 3360 q->snew.stty.sg_flags &=~ iclear; 3361 fchanged = TRUE; 3362 } 3363 } 3364 3365#else /* ! HAVE_BSD_TTY */ 3366 3367 fdo = FALSE; 3368 switch (txonxoff) 3369 { 3370 case XONXOFF_DEFAULT: 3371 break; 3372 case XONXOFF_OFF: 3373 iset = 0; 3374 iclear = IXON | IXOFF; 3375 fdo = TRUE; 3376 break; 3377 case XONXOFF_ON: 3378#ifdef CRTSCTS 3379#if HAVE_POSIX_TERMIOS 3380 /* This is system dependent, but I haven't figured out a good 3381 way around it yet. If we are doing hardware flow control, we 3382 don't send XON/XOFF characters but we do recognize them. */ 3383 if ((q->snew.c_cflag & CRTSCTS) != 0) 3384 { 3385 iset = IXON; 3386 iclear = IXOFF; 3387 fdo = TRUE; 3388 break; 3389 } 3390#endif /* HAVE_POSIX_TERMIOS */ 3391#endif /* defined (CRTSCTS) */ 3392#ifdef CRTSFL 3393 if ((q->snew.c_cflag & CRTSFL) != 0) 3394 { 3395 iset = IXON; 3396 iclear = IXOFF; 3397 /* SCO says we cant have CRTSFL **and** RTSFLOW/CTSFLOW */ 3398#ifdef RTSFLOW 3399 iclear |= RTSFLOW; 3400#endif 3401#ifdef CTSFLOW 3402 iclear |= CTSFLOW; 3403#endif 3404 fdo = TRUE; 3405 break; 3406 } 3407#endif /* defined(CRTSFL) */ 3408 iset = IXON | IXOFF; 3409 iclear = 0; 3410 fdo = TRUE; 3411 break; 3412 } 3413 3414 if (fdo) 3415 { 3416 if ((q->snew.c_iflag & iset) != iset 3417 || (q->snew.c_iflag & iclear) != 0) 3418 { 3419 q->snew.c_iflag |= iset; 3420 q->snew.c_iflag &=~ iclear; 3421 fchanged = TRUE; 3422 } 3423 } 3424 3425#endif /* ! HAVE_BSD_TTY */ 3426 3427 if (fchanged) 3428 { 3429 if (! fsetterminfodrain (q->o, &q->snew)) 3430 { 3431 ulog (LOG_ERROR, "Can't change terminal settings: %s", 3432 strerror (errno)); 3433 return FALSE; 3434 } 3435 } 3436 3437#if HAVE_BSD_TTY 3438 if (txonxoff == XONXOFF_ON 3439 && (q->snew.stty.sg_flags & ANYP) == ANYP) 3440 { 3441 int i; 3442 3443 /* At least on Ultrix, we seem to have to set LLITOUT and 3444 LPASS8. This shouldn't foul things up anywhere else. As far 3445 as I can tell, this has to be done after setting the terminal 3446 into cbreak mode, not before. */ 3447#ifndef LLITOUT 3448#define LLITOUT 0 3449#endif 3450#ifndef LPASS8 3451#define LPASS8 0 3452#endif 3453#ifndef LAUTOFLOW 3454#define LAUTOFLOW 0 3455#endif 3456 i = LLITOUT | LPASS8 | LAUTOFLOW; 3457 (void) ioctl (q->o, TIOCLBIS, &i); 3458 3459#if HAVE_STRIP_BUG 3460 /* Ultrix 4.0 has a peculiar problem: setting CBREAK always 3461 causes input characters to be stripped. I hope this does not 3462 apply to other BSD systems. It is possible to work around 3463 this by using the termio call. I wish this sort of stuff was 3464 not necessary!!! */ 3465 { 3466 struct termio s; 3467 3468 if (ioctl (q->o, TCGETA, &s) >= 0) 3469 { 3470 s.c_iflag &=~ ISTRIP; 3471 (void) ioctl (q->o, TCSETA, &s); 3472 } 3473 } 3474#endif /* HAVE_STRIP_BUG */ 3475 } 3476#endif /* HAVE_BSD_TTY */ 3477 3478 return TRUE; 3479} 3480 3481/* Change settings of a stdin port. */ 3482 3483static boolean 3484fsstdin_set (qconn, tparity, tstrip, txonxoff) 3485 struct sconnection *qconn; 3486 enum tparitysetting tparity; 3487 enum tstripsetting tstrip; 3488 enum txonxoffsetting txonxoff; 3489{ 3490 struct ssysdep_conn *qsysdep; 3491 3492 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 3493 qsysdep->o = qsysdep->ord; 3494 return fsserial_set (qconn, tparity, tstrip, txonxoff); 3495} 3496 3497/* Run a chat program. */ 3498 3499static boolean 3500fsrun_chat (oread, owrite, pzprog) 3501 int oread; 3502 int owrite; 3503 char **pzprog; 3504{ 3505 int aidescs[3]; 3506 FILE *e; 3507 pid_t ipid; 3508 char *z; 3509 size_t c; 3510 3511 aidescs[0] = oread; 3512 aidescs[1] = owrite; 3513 aidescs[2] = SPAWN_READ_PIPE; 3514 3515 /* Pass fkeepuid, fkeepenv and fshell as TRUE. This puts the 3516 responsibility of maintaing security on the chat program. */ 3517 ipid = ixsspawn ((const char **) pzprog, aidescs, TRUE, TRUE, 3518 (const char *) NULL, FALSE, TRUE, (const char *) NULL, 3519 (const char *) NULL, (const char *) NULL); 3520 if (ipid < 0) 3521 { 3522 ulog (LOG_ERROR, "ixsspawn (%s): %s", pzprog[0], strerror (errno)); 3523 return FALSE; 3524 } 3525 3526 e = fdopen (aidescs[2], (char *) "r"); 3527 if (e == NULL) 3528 { 3529 ulog (LOG_ERROR, "fdopen: %s", strerror (errno)); 3530 (void) close (aidescs[2]); 3531 (void) kill (ipid, SIGKILL); 3532 (void) ixswait ((unsigned long) ipid, (const char *) NULL); 3533 return FALSE; 3534 } 3535 3536 /* The FILE e now is attached to stderr of the program. Forward 3537 every line the program outputs to the log file. */ 3538 z = NULL; 3539 c = 0; 3540 while (getline (&z, &c, e) > 0) 3541 { 3542 size_t clen; 3543 3544 clen = strlen (z); 3545 if (z[clen - 1] == '\n') 3546 z[clen - 1] = '\0'; 3547 if (*z != '\0') 3548 ulog (LOG_NORMAL, "chat: %s", z); 3549 } 3550 3551 xfree ((pointer) z); 3552 (void) fclose (e); 3553 3554 return ixswait ((unsigned long) ipid, "Chat program") == 0; 3555} 3556 3557/* Run a chat program on a port using separate read/write file 3558 descriptors. */ 3559 3560boolean 3561fsdouble_chat (qconn, pzprog) 3562 struct sconnection *qconn; 3563 char **pzprog; 3564{ 3565 struct ssysdep_conn *qsysdep; 3566 boolean fret; 3567 3568 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 3569 fret = fsrun_chat (qsysdep->ord, qsysdep->owr, pzprog); 3570 if (qsysdep->fterminal) 3571 (void) fgetterminfo (qsysdep->ord, &qsysdep->snew); 3572 return fret; 3573} 3574 3575/* Run a chat program on any general type of connection. */ 3576 3577boolean 3578fsysdep_conn_chat (qconn, pzprog) 3579 struct sconnection *qconn; 3580 char **pzprog; 3581{ 3582 struct ssysdep_conn *qsysdep; 3583 boolean fret; 3584 3585 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 3586 fret = fsrun_chat (qsysdep->o, qsysdep->o, pzprog); 3587 if (qsysdep->fterminal) 3588 (void) fgetterminfo (qsysdep->o, &qsysdep->snew); 3589 return fret; 3590} 3591 3592/* Return baud rate of a serial port. */ 3593 3594static long 3595isserial_baud (qconn) 3596 struct sconnection *qconn; 3597{ 3598 struct ssysdep_conn *qsysdep; 3599 3600 qsysdep = (struct ssysdep_conn *) qconn->psysdep; 3601 return qsysdep->ibaud; 3602} 3603