1251875Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
2251875Speter * contributor license agreements.  See the NOTICE file distributed with
3251875Speter * this work for additional information regarding copyright ownership.
4251875Speter * The ASF licenses this file to You under the Apache License, Version 2.0
5251875Speter * (the "License"); you may not use this file except in compliance with
6251875Speter * the License.  You may obtain a copy of the License at
7251875Speter *
8251875Speter *     http://www.apache.org/licenses/LICENSE-2.0
9251875Speter *
10251875Speter * Unless required by applicable law or agreed to in writing, software
11251875Speter * distributed under the License is distributed on an "AS IS" BASIS,
12251875Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13251875Speter * See the License for the specific language governing permissions and
14251875Speter * limitations under the License.
15251875Speter */
16251875Speter
17251875Speter#include "apr_arch_file_io.h"
18251875Speter#include "apr_strings.h"
19251875Speter#include "apr_portable.h"
20251875Speter
21251875Speter#include "apr_arch_inherit.h"
22251875Speter
23251875Speter/* Figure out how to get pipe block/nonblock on BeOS...
24251875Speter * Basically, BONE7 changed things again so that ioctl didn't work,
25251875Speter * but now fcntl does, hence we need to do this extra checking.
26251875Speter * The joys of beta programs. :-)
27251875Speter */
28269847Speter#if defined(BEOS)
29269847Speter#if !defined(BONE7)
30251875Speter# define BEOS_BLOCKING 1
31251875Speter#else
32251875Speter# define BEOS_BLOCKING 0
33251875Speter#endif
34251875Speter#endif
35251875Speter
36251875Speterstatic apr_status_t pipeblock(apr_file_t *thepipe)
37251875Speter{
38269847Speter#if !defined(BEOS) || !BEOS_BLOCKING
39251875Speter      int fd_flags;
40251875Speter
41251875Speter      fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
42251875Speter#  if defined(O_NONBLOCK)
43251875Speter      fd_flags &= ~O_NONBLOCK;
44251875Speter#  elif defined(O_NDELAY)
45251875Speter      fd_flags &= ~O_NDELAY;
46251875Speter#  elif defined(O_FNDELAY)
47251875Speter      fd_flags &= ~O_FNDELAY;
48251875Speter#  else
49251875Speter      /* XXXX: this breaks things, but an alternative isn't obvious...*/
50251875Speter      return APR_ENOTIMPL;
51251875Speter#  endif
52251875Speter      if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
53251875Speter          return errno;
54251875Speter      }
55251875Speter#else /* BEOS_BLOCKING */
56251875Speter
57251875Speter#  if BEOS_BONE /* This only works on BONE 0-6 */
58251875Speter      int on = 0;
59251875Speter      if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
60251875Speter          return errno;
61251875Speter      }
62251875Speter#  else /* "classic" BeOS doesn't support this at all */
63251875Speter      return APR_ENOTIMPL;
64251875Speter#  endif
65251875Speter
66251875Speter#endif /* !BEOS_BLOCKING */
67251875Speter
68251875Speter    thepipe->blocking = BLK_ON;
69251875Speter    return APR_SUCCESS;
70251875Speter}
71251875Speter
72251875Speterstatic apr_status_t pipenonblock(apr_file_t *thepipe)
73251875Speter{
74269847Speter#if !defined(BEOS) || !BEOS_BLOCKING
75251875Speter      int fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
76251875Speter
77251875Speter#  if defined(O_NONBLOCK)
78251875Speter      fd_flags |= O_NONBLOCK;
79251875Speter#  elif defined(O_NDELAY)
80251875Speter      fd_flags |= O_NDELAY;
81251875Speter#  elif defined(O_FNDELAY)
82251875Speter      fd_flags |= O_FNDELAY;
83251875Speter#  else
84251875Speter      /* XXXX: this breaks things, but an alternative isn't obvious...*/
85251875Speter      return APR_ENOTIMPL;
86251875Speter#  endif
87251875Speter      if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
88251875Speter          return errno;
89251875Speter      }
90251875Speter
91251875Speter#else /* BEOS_BLOCKING */
92251875Speter
93251875Speter#  if BEOS_BONE /* This only works on BONE 0-6 */
94251875Speter      int on = 1;
95251875Speter      if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
96251875Speter          return errno;
97251875Speter      }
98251875Speter#  else /* "classic" BeOS doesn't support this at all */
99251875Speter      return APR_ENOTIMPL;
100251875Speter#  endif
101251875Speter
102251875Speter#endif /* !BEOS_BLOCKING */
103251875Speter
104251875Speter    thepipe->blocking = BLK_OFF;
105251875Speter    return APR_SUCCESS;
106251875Speter}
107251875Speter
108251875SpeterAPR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
109251875Speter{
110251875Speter    if (thepipe->is_pipe == 1) {
111251875Speter        thepipe->timeout = timeout;
112251875Speter        if (timeout >= 0) {
113251875Speter            if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */
114251875Speter                return pipenonblock(thepipe);
115251875Speter            }
116251875Speter        }
117251875Speter        else {
118251875Speter            if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */
119251875Speter                return pipeblock(thepipe);
120251875Speter            }
121251875Speter        }
122251875Speter        return APR_SUCCESS;
123251875Speter    }
124251875Speter    return APR_EINVAL;
125251875Speter}
126251875Speter
127251875SpeterAPR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
128251875Speter{
129251875Speter    if (thepipe->is_pipe == 1) {
130251875Speter        *timeout = thepipe->timeout;
131251875Speter        return APR_SUCCESS;
132251875Speter    }
133251875Speter    return APR_EINVAL;
134251875Speter}
135251875Speter
136251875SpeterAPR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
137251875Speter                                             apr_os_file_t *thefile,
138251875Speter                                             int register_cleanup,
139251875Speter                                             apr_pool_t *pool)
140251875Speter{
141251875Speter    int *dafile = thefile;
142251875Speter
143251875Speter    (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
144251875Speter    (*file)->pool = pool;
145251875Speter    (*file)->eof_hit = 0;
146251875Speter    (*file)->is_pipe = 1;
147251875Speter    (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
148251875Speter    (*file)->timeout = -1;
149251875Speter    (*file)->ungetchar = -1; /* no char avail */
150251875Speter    (*file)->filedes = *dafile;
151251875Speter    if (!register_cleanup) {
152251875Speter        (*file)->flags = APR_FOPEN_NOCLEANUP;
153251875Speter    }
154251875Speter    (*file)->buffered = 0;
155251875Speter#if APR_HAS_THREADS
156251875Speter    (*file)->thlock = NULL;
157251875Speter#endif
158251875Speter    if (register_cleanup) {
159251875Speter        apr_pool_cleanup_register((*file)->pool, (void *)(*file),
160251875Speter                                  apr_unix_file_cleanup,
161251875Speter                                  apr_pool_cleanup_null);
162251875Speter    }
163251875Speter#ifndef WAITIO_USES_POLL
164251875Speter    /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
165251875Speter     * initialize the pollset if needed.
166251875Speter     */
167251875Speter    (*file)->pollset = NULL;
168251875Speter#endif
169251875Speter    return APR_SUCCESS;
170251875Speter}
171251875Speter
172251875SpeterAPR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
173251875Speter                                          apr_os_file_t *thefile,
174251875Speter                                          apr_pool_t *pool)
175251875Speter{
176251875Speter    return apr_os_pipe_put_ex(file, thefile, 0, pool);
177251875Speter}
178251875Speter
179251875SpeterAPR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool)
180251875Speter{
181251875Speter    int filedes[2];
182251875Speter
183251875Speter    if (pipe(filedes) == -1) {
184251875Speter        return errno;
185251875Speter    }
186251875Speter
187251875Speter    (*in) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
188251875Speter    (*in)->pool = pool;
189251875Speter    (*in)->filedes = filedes[0];
190251875Speter    (*in)->is_pipe = 1;
191251875Speter    (*in)->fname = NULL;
192251875Speter    (*in)->buffered = 0;
193251875Speter    (*in)->blocking = BLK_ON;
194251875Speter    (*in)->timeout = -1;
195251875Speter    (*in)->ungetchar = -1;
196251875Speter    (*in)->flags = APR_INHERIT;
197251875Speter#if APR_HAS_THREADS
198251875Speter    (*in)->thlock = NULL;
199251875Speter#endif
200251875Speter#ifndef WAITIO_USES_POLL
201251875Speter    (*in)->pollset = NULL;
202251875Speter#endif
203251875Speter    (*out) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
204251875Speter    (*out)->pool = pool;
205251875Speter    (*out)->filedes = filedes[1];
206251875Speter    (*out)->is_pipe = 1;
207251875Speter    (*out)->fname = NULL;
208251875Speter    (*out)->buffered = 0;
209251875Speter    (*out)->blocking = BLK_ON;
210251875Speter    (*out)->flags = APR_INHERIT;
211251875Speter    (*out)->timeout = -1;
212251875Speter#if APR_HAS_THREADS
213251875Speter    (*out)->thlock = NULL;
214251875Speter#endif
215251875Speter#ifndef WAITIO_USES_POLL
216251875Speter    (*out)->pollset = NULL;
217251875Speter#endif
218251875Speter    apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup,
219251875Speter                         apr_pool_cleanup_null);
220251875Speter    apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup,
221251875Speter                         apr_pool_cleanup_null);
222251875Speter    return APR_SUCCESS;
223251875Speter}
224251875Speter
225251875SpeterAPR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in,
226251875Speter                                                  apr_file_t **out,
227251875Speter                                                  apr_int32_t blocking,
228251875Speter                                                  apr_pool_t *pool)
229251875Speter{
230251875Speter    apr_status_t status;
231251875Speter
232251875Speter    if ((status = apr_file_pipe_create(in, out, pool)) != APR_SUCCESS)
233251875Speter        return status;
234251875Speter
235251875Speter    switch (blocking) {
236251875Speter        case APR_FULL_BLOCK:
237251875Speter            break;
238251875Speter        case APR_READ_BLOCK:
239251875Speter            apr_file_pipe_timeout_set(*out, 0);
240251875Speter            break;
241251875Speter        case APR_WRITE_BLOCK:
242251875Speter            apr_file_pipe_timeout_set(*in, 0);
243251875Speter            break;
244251875Speter        default:
245251875Speter            apr_file_pipe_timeout_set(*out, 0);
246251875Speter            apr_file_pipe_timeout_set(*in, 0);
247251875Speter    }
248251875Speter
249251875Speter    return APR_SUCCESS;
250251875Speter}
251251875Speter
252251875SpeterAPR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename,
253251875Speter                                                    apr_fileperms_t perm, apr_pool_t *pool)
254251875Speter{
255251875Speter    mode_t mode = apr_unix_perms2mode(perm);
256251875Speter
257251875Speter    if (mkfifo(filename, mode) == -1) {
258251875Speter        return errno;
259251875Speter    }
260251875Speter    return APR_SUCCESS;
261251875Speter}
262251875Speter
263251875Speter
264251875Speter
265