]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/apr/file_io/unix/pipe.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.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 APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool)
180 {
181     int filedes[2];
182
183     if (pipe(filedes) == -1) {
184         return errno;
185     }
186     
187     (*in) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
188     (*in)->pool = pool;
189     (*in)->filedes = filedes[0];
190     (*in)->is_pipe = 1;
191     (*in)->fname = NULL;
192     (*in)->buffered = 0;
193     (*in)->blocking = BLK_ON;
194     (*in)->timeout = -1;
195     (*in)->ungetchar = -1;
196     (*in)->flags = APR_INHERIT;
197 #if APR_HAS_THREADS
198     (*in)->thlock = NULL;
199 #endif
200 #ifndef WAITIO_USES_POLL
201     (*in)->pollset = NULL;
202 #endif
203     (*out) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
204     (*out)->pool = pool;
205     (*out)->filedes = filedes[1];
206     (*out)->is_pipe = 1;
207     (*out)->fname = NULL;
208     (*out)->buffered = 0;
209     (*out)->blocking = BLK_ON;
210     (*out)->flags = APR_INHERIT;
211     (*out)->timeout = -1;
212 #if APR_HAS_THREADS
213     (*out)->thlock = NULL;
214 #endif
215 #ifndef WAITIO_USES_POLL
216     (*out)->pollset = NULL;
217 #endif
218     apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup,
219                          apr_pool_cleanup_null);
220     apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup,
221                          apr_pool_cleanup_null);
222     return APR_SUCCESS;
223 }
224
225 APR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 
226                                                   apr_file_t **out, 
227                                                   apr_int32_t blocking,
228                                                   apr_pool_t *pool)
229 {
230     apr_status_t status;
231
232     if ((status = apr_file_pipe_create(in, out, pool)) != APR_SUCCESS)
233         return status;
234
235     switch (blocking) {
236         case APR_FULL_BLOCK:
237             break;
238         case APR_READ_BLOCK:
239             apr_file_pipe_timeout_set(*out, 0);
240             break;
241         case APR_WRITE_BLOCK:
242             apr_file_pipe_timeout_set(*in, 0);
243             break;
244         default:
245             apr_file_pipe_timeout_set(*out, 0);
246             apr_file_pipe_timeout_set(*in, 0);
247     }
248
249     return APR_SUCCESS;
250 }
251
252 APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
253                                                     apr_fileperms_t perm, apr_pool_t *pool)
254 {
255     mode_t mode = apr_unix_perms2mode(perm);
256
257     if (mkfifo(filename, mode) == -1) {
258         return errno;
259     }
260     return APR_SUCCESS;
261
262
263     
264