		/* Copyright 2000-2004 The Apache Software Foundation
		 *
		 * Licensed under the Apache License, Version 2.0 (the "License");
		 * you may not use this file except in compliance with the License.
		 * You may obtain a copy of the License at
		 *
		 *     http://www.apache.org/licenses/LICENSE-2.0
		 *
		 * Unless required by applicable law or agreed to in writing, software
		 * distributed under the License is distributed on an "AS IS" BASIS,
		 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
		 * See the License for the specific language governing permissions and
		 * limitations under the License.
		 */
		
		#include "apr_arch_file_io.h"
		#include "apr_strings.h"
		#include "apr_portable.h"
		
		#include "apr_arch_inherit.h"
		
		/* Figure out how to get pipe block/nonblock on BeOS...
		 * Basically, BONE7 changed things again so that ioctl didn't work,
		 * but now fcntl does, hence we need to do this extra checking.
		 * The joys of beta programs. :-)
		 */
		#if BEOS
		#if !BONE7
		# define BEOS_BLOCKING 1
		#else
		# define BEOS_BLOCKING 0
		#endif
		#endif
		
		static apr_status_t pipeblock(apr_file_t *thepipe)
      ######    {
		#if !BEOS_BLOCKING
      ######          int fd_flags;
		
      ######          fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
		#  if defined(O_NONBLOCK)
      ######          fd_flags &= ~O_NONBLOCK;
		#  elif defined(O_NDELAY)
		      fd_flags &= ~O_NDELAY;
		#  elif defined(FNDELAY)
		      fd_flags &= ~O_FNDELAY;
		#  else 
		      /* XXXX: this breaks things, but an alternative isn't obvious...*/
		      return APR_ENOTIMPL;
		#  endif
      ######          if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
      ######              return errno;
		      }
		#else /* BEOS_BLOCKING */
		
		#  if BEOS_BONE /* This only works on BONE 0-6 */
		      int on = 0;
		      if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
		          return errno;
		      }
		#  else /* "classic" BeOS doesn't support this at all */
		      return APR_ENOTIMPL;
		#  endif 
		 
		#endif /* !BEOS_BLOCKING */
		
      ######        thepipe->blocking = BLK_ON;
      ######        return APR_SUCCESS;
		}
		
		static apr_status_t pipenonblock(apr_file_t *thepipe)
           5    {
		#if !BEOS_BLOCKING
           5          int fd_flags = fcntl(thepipe->filedes, F_GETFL, 0);
		
		#  if defined(O_NONBLOCK)
           5          fd_flags |= O_NONBLOCK;
		#  elif defined(O_NDELAY)
		      fd_flags |= O_NDELAY;
		#  elif defined(FNDELAY)
		      fd_flags |= O_FNDELAY;
		#  else
		      /* XXXX: this breaks things, but an alternative isn't obvious...*/
		      return APR_ENOTIMPL;
		#  endif
           5          if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) {
      ######              return errno;
		      }
		    
		#else /* BEOS_BLOCKING */
		
		#  if BEOS_BONE /* This only works on BONE 0-6 */
		      int on = 1;
		      if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) {
		          return errno;
		      }
		#  else /* "classic" BeOS doesn't support this at all */
		      return APR_ENOTIMPL;
		#  endif
		
		#endif /* !BEOS_BLOCKING */
		
           5        thepipe->blocking = BLK_OFF;
           5        return APR_SUCCESS;
		}
		
		APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout)
           7    {
           7        if (thepipe->is_pipe == 1) {
           7            thepipe->timeout = timeout;
           7            if (timeout >= 0) {
           7                if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */
           5                    return pipenonblock(thepipe);
		            }
		        }
		        else {
      ######                if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */
      ######                    return pipeblock(thepipe);
		            }
		        }
           2            return APR_SUCCESS;
		    }
      ######        return APR_EINVAL;
		}
		
		APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout)
           2    {
           2        if (thepipe->is_pipe == 1) {
           2            *timeout = thepipe->timeout;
           2            return APR_SUCCESS;
		    }
      ######        return APR_EINVAL;
		}
		
		APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file,
		                                             apr_os_file_t *thefile,
		                                             int register_cleanup,
		                                             apr_pool_t *pool)
      ######    {
      ######        int *dafile = thefile;
		    
      ######        (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
      ######        (*file)->pool = pool;
      ######        (*file)->eof_hit = 0;
      ######        (*file)->is_pipe = 1;
      ######        (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */
      ######        (*file)->timeout = -1;
      ######        (*file)->ungetchar = -1; /* no char avail */
      ######        (*file)->filedes = *dafile;
      ######        if (!register_cleanup) {
      ######            (*file)->flags = APR_FILE_NOCLEANUP;
		    }
      ######        (*file)->buffered = 0;
		#if APR_HAS_THREADS
      ######        (*file)->thlock = NULL;
		#endif
      ######        if (register_cleanup) {
      ######            apr_pool_cleanup_register((*file)->pool, (void *)(*file),
		                                  apr_unix_file_cleanup,
		                                  apr_pool_cleanup_null);
		    }
		#ifndef WAITIO_USES_POLL
		    /* Create a pollset with room for one descriptor. */
		    /* ### check return codes */
		    (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0);
		#endif
      ######        return APR_SUCCESS;
		}
		
		APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file,
		                                          apr_os_file_t *thefile,
		                                          apr_pool_t *pool)
      ######    {
      ######        return apr_os_pipe_put_ex(file, thefile, 0, pool);
		}
		
		APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool)
          13    {
          13        int filedes[2];
		
          13        if (pipe(filedes) == -1) {
      ######            return errno;
		    }
		    
          13        (*in) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
          13        (*in)->pool = pool;
          13        (*in)->filedes = filedes[0];
          13        (*in)->is_pipe = 1;
          13        (*in)->fname = NULL;
          13        (*in)->buffered = 0;
          13        (*in)->blocking = BLK_ON;
          13        (*in)->timeout = -1;
          13        (*in)->ungetchar = -1;
          13        (*in)->flags = APR_INHERIT;
		#if APR_HAS_THREADS
          13        (*in)->thlock = NULL;
		#endif
		#ifndef WAITIO_USES_POLL
		    (void) apr_pollset_create(&(*in)->pollset, 1, pool, 0);
		#endif
          13        (*out) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
          13        (*out)->pool = pool;
          13        (*out)->filedes = filedes[1];
          13        (*out)->is_pipe = 1;
          13        (*out)->fname = NULL;
          13        (*out)->buffered = 0;
          13        (*out)->blocking = BLK_ON;
          13        (*out)->flags = APR_INHERIT;
          13        (*out)->timeout = -1;
		#if APR_HAS_THREADS
          13        (*out)->thlock = NULL;
		#endif
		#ifndef WAITIO_USES_POLL
		    (void) apr_pollset_create(&(*out)->pollset, 1, pool, 0);
		#endif
          13        apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup,
		                         apr_pool_cleanup_null);
          13        apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup,
		                         apr_pool_cleanup_null);
          13        return APR_SUCCESS;
		}
		
		APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, 
		                                                    apr_fileperms_t perm, apr_pool_t *pool)
      ######    {
      ######        mode_t mode = apr_unix_perms2mode(perm);
		
      ######        if (mkfifo(filename, mode) == -1) {
      ######            return errno;
		    }
      ######        return APR_SUCCESS;
		} 
		
		    
		
