summaryrefslogtreecommitdiff
path: root/gnu/libexec/uucp/libunix/pipe.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /gnu/libexec/uucp/libunix/pipe.c
initial import of NetBSD tree
Diffstat (limited to 'gnu/libexec/uucp/libunix/pipe.c')
-rw-r--r--gnu/libexec/uucp/libunix/pipe.c294
1 files changed, 294 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/libunix/pipe.c b/gnu/libexec/uucp/libunix/pipe.c
new file mode 100644
index 00000000000..7ae992ceceb
--- /dev/null
+++ b/gnu/libexec/uucp/libunix/pipe.c
@@ -0,0 +1,294 @@
+/* pipe.c
+ The pipe port communication routines for Unix.
+ Contributed by Marc Boucher <marc@CAM.ORG>.
+
+ Copyright (C) 1993 Ian Lance Taylor
+
+ This file is part of the Taylor UUCP package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ The author of the program may be contacted at ian@airs.com or
+ c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
+ */
+
+#include "uucp.h"
+
+#if USE_RCS_ID
+const char pipe_rcsid[] = "$Id: pipe.c,v 1.1 1995/10/18 08:38:29 deraadt Exp $";
+#endif
+
+#include "uudefs.h"
+#include "uuconf.h"
+#include "system.h"
+#include "conn.h"
+#include "sysdep.h"
+
+#include <errno.h>
+
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#else
+#if HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#endif
+
+/* Local functions. */
+
+static void uspipe_free P((struct sconnection *qconn));
+static boolean fspipe_open P((struct sconnection *qconn, long ibaud,
+ boolean fwait));
+static boolean fspipe_close P((struct sconnection *qconn,
+ pointer puuconf,
+ struct uuconf_dialer *qdialer,
+ boolean fsuccess));
+static boolean fspipe_dial P((struct sconnection *qconn, pointer puuconf,
+ const struct uuconf_system *qsys,
+ const char *zphone,
+ struct uuconf_dialer *qdialer,
+ enum tdialerfound *ptdialer));
+
+/* The command table for standard input ports. */
+
+static const struct sconncmds spipecmds =
+{
+ uspipe_free,
+ NULL, /* pflock */
+ NULL, /* pfunlock */
+ fspipe_open,
+ fspipe_close,
+ fspipe_dial,
+ fsdouble_read,
+ fsdouble_write,
+ fsysdep_conn_io,
+ NULL, /* pfbreak */
+ NULL, /* pfset */
+ NULL, /* pfcarrier */
+ fsdouble_chat,
+ NULL /* pibaud */
+};
+
+/* Initialize a pipe connection. */
+
+boolean
+fsysdep_pipe_init (qconn)
+ struct sconnection *qconn;
+{
+ struct ssysdep_conn *q;
+
+ q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
+ q->o = -1;
+ q->ord = -1;
+ q->owr = -1;
+ q->zdevice = NULL;
+ q->iflags = -1;
+ q->iwr_flags = -1;
+ q->fterminal = FALSE;
+ q->ftli = FALSE;
+ q->ibaud = 0;
+ q->ipid = -1;
+ qconn->psysdep = (pointer) q;
+ qconn->qcmds = &spipecmds;
+ return TRUE;
+}
+
+static void
+uspipe_free (qconn)
+ struct sconnection *qconn;
+{
+ xfree (qconn->psysdep);
+}
+
+/* Open a pipe port. */
+
+/*ARGSUSED*/
+static boolean
+fspipe_open (qconn, ibaud, fwait)
+ struct sconnection *qconn;
+ long ibaud;
+ boolean fwait;
+{
+ /* We don't do incoming waits on pipes. */
+ if (fwait)
+ return FALSE;
+
+ return TRUE;
+}
+
+/* Close a pipe port. */
+
+/*ARGSUSED*/
+static boolean
+fspipe_close (qconn, puuconf, qdialer, fsuccess)
+ struct sconnection *qconn;
+ pointer puuconf;
+ struct uuconf_dialer *qdialer;
+ boolean fsuccess;
+{
+ struct ssysdep_conn *qsysdep;
+ boolean fret;
+
+ qsysdep = (struct ssysdep_conn *) qconn->psysdep;
+ fret = TRUE;
+
+ /* Close our sides of the pipe. */
+ if (qsysdep->ord >= 0 && close (qsysdep->ord) < 0)
+ {
+ ulog (LOG_ERROR, "fspipe_close: close read fd: %s", strerror (errno));
+ fret = FALSE;
+ }
+ if (qsysdep->owr != qsysdep->ord
+ && qsysdep->owr >= 0
+ && close (qsysdep->owr) < 0)
+ {
+ ulog (LOG_ERROR, "fspipe_close: close write fd: %s", strerror (errno));
+ fret = FALSE;
+ }
+ qsysdep->ord = -1;
+ qsysdep->owr = -1;
+
+ /* Kill dangling child process. */
+ if (qsysdep->ipid >= 0)
+ {
+ if (kill (qsysdep->ipid, SIGHUP) == 0)
+ usysdep_sleep (2);
+#ifdef SIGPIPE
+ if (kill (qsysdep->ipid, SIGPIPE) == 0)
+ usysdep_sleep (2);
+#endif
+ if (kill (qsysdep->ipid, SIGKILL) < 0 && errno == EPERM)
+ {
+ ulog (LOG_ERROR, "fspipe_close: Cannot kill child pid %lu: %s",
+ (unsigned long) qsysdep->ipid, strerror (errno));
+ fret = FALSE;
+ }
+ else
+ (void) ixswait ((unsigned long) qsysdep->ipid, (const char *) NULL);
+ }
+ qsysdep->ipid = -1;
+ return fret;
+}
+
+/* Dial out on a pipe port, so to speak: launch connection program
+ under us. The code alternates q->o between q->ord and q->owr as
+ appropriate. It is always q->ord before any call to fsblock. */
+
+/*ARGSUSED*/
+static boolean
+fspipe_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
+ struct sconnection *qconn;
+ pointer puuconf;
+ const struct uuconf_system *qsys;
+ const char *zphone;
+ struct uuconf_dialer *qdialer;
+ enum tdialerfound *ptdialer;
+{
+ struct ssysdep_conn *q;
+ int aidescs[3];
+ const char **pzprog;
+
+ q = (struct ssysdep_conn *) qconn->psysdep;
+
+ *ptdialer = DIALERFOUND_FALSE;
+
+ pzprog = (const char **) qconn->qport->uuconf_u.uuconf_spipe.uuconf_pzcmd;
+
+ if (pzprog == NULL)
+ {
+ ulog (LOG_ERROR, "No command for pipe connection");
+ return FALSE;
+ }
+
+ aidescs[0] = SPAWN_WRITE_PIPE;
+ aidescs[1] = SPAWN_READ_PIPE;
+ aidescs[2] = SPAWN_NULL;
+
+ /* Pass fkeepuid, fkeepenv and fshell as TRUE. This puts the
+ responsibility of security on the connection program. */
+ q->ipid = ixsspawn (pzprog, aidescs, TRUE, TRUE, (const char *) NULL,
+ FALSE, TRUE, (const char *) NULL,
+ (const char *) NULL, (const char *) NULL);
+ if (q->ipid < 0)
+ {
+ ulog (LOG_ERROR, "ixsspawn (%s): %s", pzprog[0], strerror (errno));
+ return FALSE;
+ }
+
+ q->owr = aidescs[0];
+ q->ord = aidescs[1];
+ q->o = q->ord;
+
+ q->iflags = fcntl (q->ord, F_GETFL, 0);
+ q->iwr_flags = fcntl (q->owr, F_GETFL, 0);
+ if (q->iflags < 0 || q->iwr_flags < 0)
+ {
+ ulog (LOG_ERROR, "fspipe_dial: fcntl: %s", strerror (errno));
+ (void) fspipe_close (qconn, puuconf, qdialer, FALSE);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#if 0
+
+/* Marc Boucher's contributed code used an alarm to avoid waiting too
+ long when closing the pipe. However, I believe that it is not
+ possible for the kernel to sleep when closing a pipe; it is only
+ possible when closing a device. Therefore, I have removed the
+ code, but am preserving it in case I am wrong. To reenable it, the
+ two calls to close in fspipe_close should be changed to call
+ fspipe_alarmclose. */
+
+static RETSIGTYPE
+usalarm (isig)
+ int isig;
+{
+#if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET
+ (void) signal (isig, usalarm);
+#endif
+
+#if HAVE_RESTARTABLE_SYSCALLS
+ longjmp (sSjmp_buf, 1);
+#endif
+}
+
+static int
+fspipe_alarmclose (fd)
+ int fd;
+{
+ int iret = -1;
+ int ierrno = 0;
+
+ if (fsysdep_catch ())
+ {
+ usysdep_start_catch ();
+ usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL);
+ (void) alarm (30);
+
+ iret = close (fd);
+ ierrno = errno;
+ }
+
+ usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL);
+ (void) alarm (0);
+ usysdep_end_catch ();
+
+ errno = ierrno;
+ return iret;
+}
+
+#endif /* 0 */