]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/libexec/uucp/libunix/pipe.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / gnu / libexec / uucp / libunix / pipe.c
1 /* pipe.c
2    The pipe port communication routines for Unix.
3    Contributed by Marc Boucher <marc@CAM.ORG>.
4
5    Copyright (C) 1993 Ian Lance Taylor
6
7    This file is part of the Taylor UUCP package.
8
9    This program is free software; you can redistribute it and/or
10    modify it under the terms of the GNU General Public License as
11    published by the Free Software Foundation; either version 2 of the
12    License, or (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful, but
15    WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17    General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23    The author of the program may be contacted at ian@airs.com or
24    c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
25    */
26
27 #include "uucp.h"
28
29 #if USE_RCS_ID
30 const char pipe_rcsid[] = "$FreeBSD$";
31 #endif
32
33 #include "uudefs.h"
34 #include "uuconf.h"
35 #include "system.h"
36 #include "conn.h"
37 #include "sysdep.h"
38
39 #include <errno.h>
40
41 #if HAVE_FCNTL_H
42 #include <fcntl.h>
43 #else
44 #if HAVE_SYS_FILE_H
45 #include <sys/file.h>
46 #endif
47 #endif
48 \f
49 /* Local functions.  */
50
51 static void uspipe_free P((struct sconnection *qconn));
52 static boolean fspipe_open P((struct sconnection *qconn, long ibaud,
53                               boolean fwait));
54 static boolean fspipe_close P((struct sconnection *qconn,
55                                pointer puuconf,
56                                struct uuconf_dialer *qdialer,
57                                boolean fsuccess));
58 static boolean fspipe_dial P((struct sconnection *qconn, pointer puuconf,
59                               const struct uuconf_system *qsys,
60                               const char *zphone,
61                               struct uuconf_dialer *qdialer,
62                               enum tdialerfound *ptdialer));
63 \f
64 /* The command table for standard input ports.  */
65
66 static const struct sconncmds spipecmds =
67 {
68   uspipe_free,
69   NULL, /* pflock */
70   NULL, /* pfunlock */
71   fspipe_open,
72   fspipe_close,
73   fspipe_dial,
74   fsdouble_read,
75   fsdouble_write,
76   fsysdep_conn_io,
77   NULL, /* pfbreak */
78   NULL, /* pfset */
79   NULL, /* pfcarrier */
80   fsdouble_chat,
81   NULL  /* pibaud */
82 };
83 \f
84 /* Initialize a pipe connection.  */
85
86 boolean
87 fsysdep_pipe_init (qconn)
88      struct sconnection *qconn;
89 {
90   struct ssysdep_conn *q;
91
92   q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn));
93   q->o = -1;
94   q->ord = -1;
95   q->owr = -1;
96   q->zdevice = NULL;
97   q->iflags = -1;
98   q->iwr_flags = -1;
99   q->fterminal = FALSE;
100   q->ftli = FALSE;
101   q->ibaud = 0;
102   q->ipid = -1;
103   qconn->psysdep = (pointer) q;
104   qconn->qcmds = &spipecmds;
105   return TRUE;
106 }
107
108 static void
109 uspipe_free (qconn)
110      struct sconnection *qconn;
111 {
112   xfree (qconn->psysdep);
113 }
114
115 /* Open a pipe port.  */
116
117 /*ARGSUSED*/
118 static boolean
119 fspipe_open (qconn, ibaud, fwait)
120      struct sconnection *qconn;
121      long ibaud;
122      boolean fwait;
123 {
124   /* We don't do incoming waits on pipes.  */
125   if (fwait)
126     return FALSE;
127
128   return TRUE;
129 }
130
131 /* Close a pipe port.  */
132
133 /*ARGSUSED*/
134 static boolean
135 fspipe_close (qconn, puuconf, qdialer, fsuccess)
136      struct sconnection *qconn;
137      pointer puuconf;
138      struct uuconf_dialer *qdialer;
139      boolean fsuccess;
140 {
141   struct ssysdep_conn *qsysdep;
142   boolean fret;
143
144   qsysdep = (struct ssysdep_conn *) qconn->psysdep;
145   fret = TRUE;
146
147   /* Close our sides of the pipe.  */
148   if (qsysdep->ord >= 0 && close (qsysdep->ord) < 0)
149     {
150       ulog (LOG_ERROR, "fspipe_close: close read fd: %s", strerror (errno));
151       fret = FALSE;
152     }
153   if (qsysdep->owr != qsysdep->ord
154       && qsysdep->owr >= 0
155       && close (qsysdep->owr) < 0)
156     {
157       ulog (LOG_ERROR, "fspipe_close: close write fd: %s", strerror (errno));
158       fret = FALSE;
159     }
160   qsysdep->ord = -1;
161   qsysdep->owr = -1;
162
163   /* Kill dangling child process.  */
164   if (qsysdep->ipid >= 0)
165     {
166       if (kill (qsysdep->ipid, SIGHUP) == 0)
167         usysdep_sleep (2);
168 #ifdef SIGPIPE
169       if (kill (qsysdep->ipid, SIGPIPE) == 0)
170         usysdep_sleep (2);
171 #endif
172       if (kill (qsysdep->ipid, SIGKILL) < 0 && errno == EPERM)
173         {
174           ulog (LOG_ERROR, "fspipe_close: Cannot kill child pid %lu: %s",
175                 (unsigned long) qsysdep->ipid, strerror (errno));
176           fret = FALSE;
177         }
178       else
179         (void) ixswait ((unsigned long) qsysdep->ipid, (const char *) NULL);
180     }
181   qsysdep->ipid = -1;
182   return fret;
183 }
184 \f
185 /* Dial out on a pipe port, so to speak: launch connection program
186    under us.  The code alternates q->o between q->ord and q->owr as
187    appropriate.  It is always q->ord before any call to fsblock.  */
188
189 /*ARGSUSED*/
190 static boolean
191 fspipe_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer)
192      struct sconnection *qconn;
193      pointer puuconf;
194      const struct uuconf_system *qsys;
195      const char *zphone;
196      struct uuconf_dialer *qdialer;
197      enum tdialerfound *ptdialer;
198 {
199   struct ssysdep_conn *q;
200   int aidescs[3];
201   const char **pzprog;
202
203   q = (struct ssysdep_conn *) qconn->psysdep;
204
205   *ptdialer = DIALERFOUND_FALSE;
206
207   pzprog = (const char **) qconn->qport->uuconf_u.uuconf_spipe.uuconf_pzcmd;
208
209   if (pzprog == NULL)
210     {
211       ulog (LOG_ERROR, "No command for pipe connection");
212       return FALSE;
213     }
214
215   aidescs[0] = SPAWN_WRITE_PIPE;
216   aidescs[1] = SPAWN_READ_PIPE;
217   aidescs[2] = SPAWN_NULL;
218
219   /* Pass fkeepuid, fkeepenv and fshell as TRUE.  This puts the
220      responsibility of security on the connection program.  */
221   q->ipid = ixsspawn (pzprog, aidescs, TRUE, TRUE, (const char *) NULL,
222                       FALSE, TRUE, (const char *) NULL,
223                       (const char *) NULL, (const char *) NULL);
224   if (q->ipid < 0)
225     {
226       ulog (LOG_ERROR, "ixsspawn (%s): %s", pzprog[0], strerror (errno));
227       return FALSE;
228     }
229
230   q->owr = aidescs[0];
231   q->ord = aidescs[1];
232   q->o = q->ord;
233
234   q->iflags = fcntl (q->ord, F_GETFL, 0);
235   q->iwr_flags = fcntl (q->owr, F_GETFL, 0);
236   if (q->iflags < 0 || q->iwr_flags < 0)
237     {
238       ulog (LOG_ERROR, "fspipe_dial: fcntl: %s", strerror (errno));
239       (void) fspipe_close (qconn, puuconf, qdialer, FALSE);
240       return FALSE;
241     }
242
243   return TRUE;
244 }
245 \f
246 #if 0
247
248 /* Marc Boucher's contributed code used an alarm to avoid waiting too
249    long when closing the pipe.  However, I believe that it is not
250    possible for the kernel to sleep when closing a pipe; it is only
251    possible when closing a device.  Therefore, I have removed the
252    code, but am preserving it in case I am wrong.  To reenable it, the
253    two calls to close in fspipe_close should be changed to call
254    fspipe_alarmclose.  */
255
256 static RETSIGTYPE
257 usalarm (isig)
258      int isig;
259 {
260 #if ! HAVE_SIGACTION && ! HAVE_SIGVEC && ! HAVE_SIGSET
261   (void) signal (isig, usalarm);
262 #endif
263
264 #if HAVE_RESTARTABLE_SYSCALLS
265   longjmp (sSjmp_buf, 1);
266 #endif
267 }
268
269 static int
270 fspipe_alarmclose (fd)
271      int fd;
272 {
273   int iret = -1;
274   int ierrno = 0;
275
276   if (fsysdep_catch ())
277     {
278       usysdep_start_catch ();
279       usset_signal (SIGALRM, usalarm, TRUE, (boolean *) NULL);
280       (void) alarm (30);
281
282       iret = close (fd);
283       ierrno = errno;
284     }
285
286   usset_signal (SIGALRM, SIG_IGN, TRUE, (boolean *) NULL);
287   (void) alarm (0);
288   usysdep_end_catch ();
289
290   errno = ierrno;
291   return iret;
292 }
293
294 #endif /* 0 */