Annotation of coherent/g/usr/lib/uucp/tay104/unix/serial.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.