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.2 2012/04/08 11:27:44 martin 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 47 int 48 posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa) 49 { 50 if (fa == NULL) 51 return (-1); 52 53 fa->fae = malloc(MIN_SIZE * sizeof(struct posix_spawn_file_actions_entry)); 54 if (fa->fae == NULL) 55 return (-1); 56 fa->size = MIN_SIZE; 57 fa->len = 0; 58 59 return (0); 60 } 61 62 int 63 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa) 64 { 65 unsigned int i; 66 67 if (fa == NULL) 68 return (-1); 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 79 static int 80 posix_spawn_file_actions_getentry(posix_spawn_file_actions_t *fa) 81 { 82 if (fa == NULL) 83 return -1; 84 85 if (fa->len < fa->size) 86 return fa->len; 87 88 fa->fae = realloc(fa->fae, (fa->size + MIN_SIZE) * 89 sizeof(struct posix_spawn_file_actions_entry)); 90 91 if (fa->fae == NULL) 92 return -1; 93 94 fa->size += MIN_SIZE; 95 96 return fa->len; 97 } 98 99 int 100 posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa, 101 int fildes, const char * __restrict path, int oflag, mode_t mode) 102 { 103 int i, error; 104 105 if (fildes < 0) 106 return (EBADF); 107 108 i = posix_spawn_file_actions_getentry(fa); 109 if (i < 0) 110 return (ENOMEM); 111 112 fa->fae[i].fae_action = FAE_OPEN; 113 fa->fae[i].fae_path = strdup(path); 114 if (fa->fae[i].fae_path == NULL) { 115 error = errno; 116 return (error); 117 } 118 fa->fae[i].fae_fildes = fildes; 119 fa->fae[i].fae_oflag = oflag; 120 fa->fae[i].fae_mode = mode; 121 122 fa->len++; 123 124 return (0); 125 } 126 127 int 128 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, 129 int fildes, int newfildes) 130 { 131 int i; 132 133 if (fildes < 0 || newfildes < 0) 134 return (EBADF); 135 136 i = posix_spawn_file_actions_getentry(fa); 137 if (i < 0) 138 return (ENOMEM); 139 140 fa->fae[i].fae_action = FAE_DUP2; 141 fa->fae[i].fae_fildes = fildes; 142 fa->fae[i].fae_newfildes = newfildes; 143 fa->len++; 144 145 return (0); 146 } 147 148 int 149 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa, 150 int fildes) 151 { 152 int i; 153 154 if (fildes < 0) 155 return (EBADF); 156 157 i = posix_spawn_file_actions_getentry(fa); 158 if (i < 0) 159 return (ENOMEM); 160 161 fa->fae[i].fae_action = FAE_CLOSE; 162 fa->fae[i].fae_fildes = fildes; 163 fa->len++; 164 165 return (0); 166 } 167