]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/apr/file_io/unix/pipe.c
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / apr / file_io / unix / pipe.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_arch_file_io.h"
18 #include "apr_strings.h"
19 #include "apr_portable.h"
20
21 #include "apr_arch_inherit.h"
22
23 /* Figure out how to get pipe block/nonblock on BeOS...
24  * Basically, BONE7 changed things again so that ioctl didn't work,
25  * but now fcntl does, hence we need to do this extra checking.
26  * The joys of beta programs. :-)
27  */
28 #if defined(BEOS)
29 #if !defined(BONE7)
30 # define BEOS_BLOCKING 1
31 #else
32 # define BEOS_BLOCKING 0
33 #endif
34 #endif
35
36 static apr_status_t pipeblock(apr_file_t *thepipe)
37 {
38 #if !defined(BEOS) || !BEOS_BLOCKING
39       int fd_flags;
40
41       fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
42 #  if defined(O_NONBLOCK)
43       fd_flags &= ~O_NONBLOCK;
44 #  elif defined(O_NDELAY)
45       fd_flags &= ~O_NDELAY;
46 #  elif defined(O_FNDELAY)
47       fd_flags &= ~O_FNDELAY;
48 #  else 
49       /* XXXX: this breaks things, but an alternative isn't obvious...*/
50       return APR_ENOTIMPL;
51 #  endif
52       if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
53           return errno;
54       }
55 #else /* BEOS_BLOCKING */
56
57 #  if BEOS_BONE /* This only works on BONE 0-6 */
58       int on = 0;
59       if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
60           return errno;
61       }
62 #  else /* "classic" BeOS doesn't support this at all */
63       return APR_ENOTIMPL;
64 #  endif 
65  
66 #endif /* !BEOS_BLOCKING */
67
68     thepipe->blocking = BLK_ON;
69     return APR_SUCCESS;
70 }
71
72 static apr_status_t pipenonblock(apr_file_t *thepipe)
73 {
74 #if !defined(BEOS) || !BEOS_BLOCKING
75       int fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
76
77 #  if defined(O_NONBLOCK)
78       fd_flags |= O_NONBLOCK;
79 #  elif defined(O_NDELAY)
80       fd_flags |= O_NDELAY;
81 #  elif defined(O_FNDELAY)
82       fd_flags |= O_FNDELAY;
83 #  else
84       /* XXXX: this breaks things, but an alternative isn't obvious...*/
85       return APR_ENOTIMPL;
86 #  endif
87       if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
88           return errno;
89       }
90     
91 #else /* BEOS_BLOCKING */
92
93 #  if BEOS_BONE /* This only works on BONE 0-6 */
94       int on = 1;
95       if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
96           return errno;
97       }
98 #  else /* "classic" BeOS doesn't support this at all */
99       return APR_ENOTIMPL;
100 #  endif
101
102 #endif /* !BEOS_BLOCKING */
103
104     thepipe->blocking = BLK_OFF;
105     return APR_SUCCESS;
106 }
107
108 APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
109 {
110     if (thepipe->is_pipe == 1) {
111         thepipe->timeout = timeout;
112         if (timeout >= 0) {
113             if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */
114                 return pipenonblock(thepipe);
115             }
116         }
117         else {
118             if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */
119                 return pipeblock(thepipe);
120             }
121         }
122         return APR_SUCCESS;
123     }
124     return APR_EINVAL;
125 }
126
127 APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
128 {
129     if (thepipe->is_pipe == 1) {
130         *timeout = thepipe->timeout;
131         return APR_SUCCESS;
132     }
133     return APR_EINVAL;
134 }
135
136 APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
137                                              apr_os_file_t *thefile,
138                                              int register_cleanup,
139                                              apr_pool_t *pool)
140 {
141     int *dafile = thefile;
142     
143     (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
144     (*file)->pool = pool;
145     (*file)->eof_hit = 0;
146     (*file)->is_pipe = 1;
147     (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
148     (*file)->timeout = -1;
149     (*file)->ungetchar = -1; /* no char avail */
150     (*file)->filedes = *dafile;
151     if (!register_cleanup) {
152         (*file)->flags = APR_FOPEN_NOCLEANUP;
153     }
154     (*file)->buffered = 0;
155 #if APR_HAS_THREADS
156     (*file)->thlock = NULL;
157 #endif
158     if (register_cleanup) {
159         apr_pool_cleanup_register((*file)->pool, (void *)(*file),
160                                   apr_unix_file_cleanup,
161                                   apr_pool_cleanup_null);
162     }
163 #ifndef WAITIO_USES_POLL
164     /* Start out with no pollset.  apr_wait_for_io_or_timeout() will
165      * initialize the pollset if needed.
166      */
167     (*file)->pollset = NULL;
168 #endif
169     return APR_SUCCESS;
170 }
171
172 APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
173                                           apr_os_file_t *thefile,
174                                           apr_pool_t *pool)
175 {
176     return apr_os_pipe_put_ex(file, thefile, 0, pool);
177 }
178
179 static apr_status_t file_pipe_create(apr_file_t **in, apr_file_t **out,
180         apr_pool_t *pool_in, apr_pool_t *pool_out)
181 {
182     int filedes[2];
183
184     if (pipe(filedes) == -1) {
185         return errno;
186     }
187     
188     (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t));
189     (*in)->pool = pool_in;
190     (*in)->filedes = filedes[0];
191     (*in)->is_pipe = 1;
192     (*in)->fname = NULL;
193     (*in)->buffered = 0;
194     (*in)->blocking = BLK_ON;
195     (*in)->timeout = -1;
196     (*in)->ungetchar = -1;
197     (*in)->flags = APR_INHERIT;
198 #if APR_HAS_THREADS
199     (*in)->thlock = NULL;
200 #endif
201 #ifndef WAITIO_USES_POLL
202     (*in)->pollset = NULL;
203 #endif
204     (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t));
205     (*out)->pool = pool_out;
206     (*out)->filedes = filedes[1];
207     (*out)->is_pipe = 1;
208     (*out)->fname = NULL;
209     (*out)->buffered = 0;
210     (*out)->blocking = BLK_ON;
211     (*out)->flags = APR_INHERIT;
212     (*out)->timeout = -1;
213 #if APR_HAS_THREADS
214     (*out)->thlock = NULL;
215 #endif
216 #ifndef WAITIO_USES_POLL
217     (*out)->pollset = NULL;
218 #endif
219     apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup,
220                          apr_pool_cleanup_null);
221     apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup,
222                          apr_pool_cleanup_null);
223     return APR_SUCCESS;
224 }
225
226 static void file_pipe_block(apr_file_t **in, apr_file_t **out, apr_int32_t blocking)
227 {
228     switch (blocking) {
229     case APR_FULL_BLOCK:
230         break;
231     case APR_READ_BLOCK:
232         apr_file_pipe_timeout_set(*out, 0);
233         break;
234     case APR_WRITE_BLOCK:
235         apr_file_pipe_timeout_set(*in, 0);
236         break;
237     default:
238         apr_file_pipe_timeout_set(*out, 0);
239         apr_file_pipe_timeout_set(*in, 0);
240         break;
241     }
242 }
243
244 APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in,
245         apr_file_t **out, apr_pool_t *pool)
246 {
247     return file_pipe_create(in, out, pool, pool);
248 }
249
250 APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 
251                                                   apr_file_t **out, 
252                                                   apr_int32_t blocking,
253                                                   apr_pool_t *pool)
254 {
255     apr_status_t status;
256
257     if ((status = file_pipe_create(in, out, pool, pool)) != APR_SUCCESS) {
258         return status;
259     }
260
261     file_pipe_block(in, out, blocking);
262
263     return APR_SUCCESS;
264 }
265
266 APR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in,
267         apr_file_t **out, apr_int32_t blocking, apr_pool_t *pool_in, apr_pool_t *pool_out)
268 {
269     apr_status_t status;
270
271     if ((status = file_pipe_create(in, out, pool_in, pool_out)) != APR_SUCCESS) {
272         return status;
273     }
274
275     file_pipe_block(in, out, blocking);
276
277     return APR_SUCCESS;
278 }
279
280 APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
281                                                     apr_fileperms_t perm, apr_pool_t *pool)
282 {
283     mode_t mode = apr_unix_perms2mode(perm);
284
285     if (mkfifo(filename, mode) == -1) {
286         return errno;
287     }
288     return APR_SUCCESS;
289
290
291     
292