1994-05-07 18:14:43 +00:00
|
|
|
|
/* 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
|
1995-08-19 21:30:30 +00:00
|
|
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1994-05-07 18:14:43 +00:00
|
|
|
|
|
|
|
|
|
The author of the program may be contacted at ian@airs.com or
|
1995-08-19 21:30:30 +00:00
|
|
|
|
c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
|
1994-05-07 18:14:43 +00:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "uucp.h"
|
|
|
|
|
|
|
|
|
|
#if USE_RCS_ID
|
1997-02-22 15:28:58 +00:00
|
|
|
|
const char pipe_rcsid[] = "$Id$";
|
1994-05-07 18:14:43 +00:00
|
|
|
|
#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 */
|