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 |
|