1/*- 2 * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__RCSID("$NetBSD: posix_spawn_fileactions.c,v 1.1.2.1 2012/04/12 17:05:37 riz Exp $"); 29 30#include "namespace.h" 31 32#include <errno.h> 33#include <fcntl.h> 34#include <sched.h> 35#include <signal.h> 36#include <stdlib.h> 37#include <string.h> 38#include <unistd.h> 39#include <spawn.h> 40 41#define MIN_SIZE 16 42 43/* 44 * File descriptor actions 45 */ 46 47int 48posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa) 49{ 50 if (fa == NULL) 51 return (EINVAL); 52 53 fa->fae = malloc(MIN_SIZE * sizeof(struct posix_spawn_file_actions_entry)); 54 if (fa->fae == NULL) 55 return (ENOMEM); 56 fa->size = MIN_SIZE; 57 fa->len = 0; 58 59 return (0); 60} 61 62int 63posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) 64{ 65 unsigned int i; 66 67 if (fa == NULL) 68 return (EINVAL); 69 70 for (i = 0; i < fa->len; i++) { 71 if (fa->fae[i].fae_action == FAE_OPEN) 72 free(fa->fae[i].fae_path); 73 } 74 75 free(fa->fae); 76 return (0); 77} 78 79static int 80posix_spawn_file_actions_getentry(posix_spawn_file_actions_t *fa, 81 unsigned int *i) 82{ 83 posix_spawn_file_actions_entry_t *fae; 84 85 if (fa == NULL) 86 return (EINVAL); 87 88 if (fa->len < fa->size) 89 goto out; 90 91 fae = realloc(fa->fae, (fa->size + MIN_SIZE) * sizeof(*fa->fae)); 92 if (fae == NULL) 93 return (ENOMEM); 94 95 fa->fae = fae; 96 fa->size += MIN_SIZE; 97 98out: 99 *i = fa->len; 100 return (0); 101} 102 103int 104posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, 105 int fildes, const char * __restrict path, int oflag, mode_t mode) 106{ 107 char *faepath; 108 unsigned int i; 109 int error; 110 111 if (fildes < 0) 112 return (EBADF); 113 114 error = posix_spawn_file_actions_getentry(fa, &i); 115 if (error) 116 return (error); 117 118 faepath = strdup(path); 119 if (faepath == NULL) 120 return (ENOMEM); 121 122 fa->fae[i].fae_action = FAE_OPEN; 123 fa->fae[i].fae_path = faepath; 124 fa->fae[i].fae_fildes = fildes; 125 fa->fae[i].fae_oflag = oflag; 126 fa->fae[i].fae_mode = mode; 127 fa->len++; 128 129 return (0); 130} 131 132int 133posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, 134 int fildes, int newfildes) 135{ 136 unsigned int i; 137 int error; 138 139 if (fildes < 0 || newfildes < 0) 140 return (EBADF); 141 142 error = posix_spawn_file_actions_getentry(fa, &i); 143 if (error) 144 return (error); 145 146 fa->fae[i].fae_action = FAE_DUP2; 147 fa->fae[i].fae_fildes = fildes; 148 fa->fae[i].fae_newfildes = newfildes; 149 fa->len++; 150 151 return (0); 152} 153 154int 155posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, 156 int fildes) 157{ 158 unsigned int i; 159 int error; 160 161 if (fildes < 0) 162 return (EBADF); 163 164 error = posix_spawn_file_actions_getentry(fa, &i); 165 if (error) 166 return (error); 167 168 fa->fae[i].fae_action = FAE_CLOSE; 169 fa->fae[i].fae_fildes = fildes; 170 fa->len++; 171 172 return (0); 173} 174