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 */ 28266735Speter#if defined(BEOS) 29266735Speter#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{ 38266735Speter#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{ 74266735Speter#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 179362181Sdimstatic apr_status_t file_pipe_create(apr_file_t **in, apr_file_t **out, 180362181Sdim apr_pool_t *pool_in, apr_pool_t *pool_out) 181251875Speter{ 182251875Speter int filedes[2]; 183251875Speter 184251875Speter if (pipe(filedes) == -1) { 185251875Speter return errno; 186251875Speter } 187251875Speter 188362181Sdim (*in) = (apr_file_t *)apr_pcalloc(pool_in, sizeof(apr_file_t)); 189362181Sdim (*in)->pool = pool_in; 190251875Speter (*in)->filedes = filedes[0]; 191251875Speter (*in)->is_pipe = 1; 192251875Speter (*in)->fname = NULL; 193251875Speter (*in)->buffered = 0; 194251875Speter (*in)->blocking = BLK_ON; 195251875Speter (*in)->timeout = -1; 196251875Speter (*in)->ungetchar = -1; 197251875Speter (*in)->flags = APR_INHERIT; 198251875Speter#if APR_HAS_THREADS 199251875Speter (*in)->thlock = NULL; 200251875Speter#endif 201251875Speter#ifndef WAITIO_USES_POLL 202251875Speter (*in)->pollset = NULL; 203251875Speter#endif 204362181Sdim (*out) = (apr_file_t *)apr_pcalloc(pool_out, sizeof(apr_file_t)); 205362181Sdim (*out)->pool = pool_out; 206251875Speter (*out)->filedes = filedes[1]; 207251875Speter (*out)->is_pipe = 1; 208251875Speter (*out)->fname = NULL; 209251875Speter (*out)->buffered = 0; 210251875Speter (*out)->blocking = BLK_ON; 211251875Speter (*out)->flags = APR_INHERIT; 212251875Speter (*out)->timeout = -1; 213251875Speter#if APR_HAS_THREADS 214251875Speter (*out)->thlock = NULL; 215251875Speter#endif 216251875Speter#ifndef WAITIO_USES_POLL 217251875Speter (*out)->pollset = NULL; 218251875Speter#endif 219251875Speter apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup, 220251875Speter apr_pool_cleanup_null); 221251875Speter apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup, 222251875Speter apr_pool_cleanup_null); 223251875Speter return APR_SUCCESS; 224251875Speter} 225251875Speter 226362181Sdimstatic void file_pipe_block(apr_file_t **in, apr_file_t **out, apr_int32_t blocking) 227362181Sdim{ 228362181Sdim switch (blocking) { 229362181Sdim case APR_FULL_BLOCK: 230362181Sdim break; 231362181Sdim case APR_READ_BLOCK: 232362181Sdim apr_file_pipe_timeout_set(*out, 0); 233362181Sdim break; 234362181Sdim case APR_WRITE_BLOCK: 235362181Sdim apr_file_pipe_timeout_set(*in, 0); 236362181Sdim break; 237362181Sdim default: 238362181Sdim apr_file_pipe_timeout_set(*out, 0); 239362181Sdim apr_file_pipe_timeout_set(*in, 0); 240362181Sdim break; 241362181Sdim } 242362181Sdim} 243362181Sdim 244362181SdimAPR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, 245362181Sdim apr_file_t **out, apr_pool_t *pool) 246362181Sdim{ 247362181Sdim return file_pipe_create(in, out, pool, pool); 248362181Sdim} 249362181Sdim 250251875SpeterAPR_DECLARE(apr_status_t) apr_file_pipe_create_ex(apr_file_t **in, 251251875Speter apr_file_t **out, 252251875Speter apr_int32_t blocking, 253251875Speter apr_pool_t *pool) 254251875Speter{ 255251875Speter apr_status_t status; 256251875Speter 257362181Sdim if ((status = file_pipe_create(in, out, pool, pool)) != APR_SUCCESS) { 258251875Speter return status; 259362181Sdim } 260251875Speter 261362181Sdim file_pipe_block(in, out, blocking); 262362181Sdim 263362181Sdim return APR_SUCCESS; 264362181Sdim} 265362181Sdim 266362181SdimAPR_DECLARE(apr_status_t) apr_file_pipe_create_pools(apr_file_t **in, 267362181Sdim apr_file_t **out, apr_int32_t blocking, apr_pool_t *pool_in, apr_pool_t *pool_out) 268362181Sdim{ 269362181Sdim apr_status_t status; 270362181Sdim 271362181Sdim if ((status = file_pipe_create(in, out, pool_in, pool_out)) != APR_SUCCESS) { 272362181Sdim return status; 273251875Speter } 274251875Speter 275362181Sdim file_pipe_block(in, out, blocking); 276362181Sdim 277251875Speter return APR_SUCCESS; 278251875Speter} 279251875Speter 280251875SpeterAPR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 281251875Speter apr_fileperms_t perm, apr_pool_t *pool) 282251875Speter{ 283251875Speter mode_t mode = apr_unix_perms2mode(perm); 284251875Speter 285251875Speter if (mkfifo(filename, mode) == -1) { 286251875Speter return errno; 287251875Speter } 288251875Speter return APR_SUCCESS; 289251875Speter} 290251875Speter 291251875Speter 292251875Speter 293