|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.