119f52532Smartin /*-
219f52532Smartin * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
319f52532Smartin * All rights reserved.
419f52532Smartin *
519f52532Smartin * Redistribution and use in source and binary forms, with or without
619f52532Smartin * modification, are permitted provided that the following conditions
719f52532Smartin * are met:
819f52532Smartin * 1. Redistributions of source code must retain the above copyright
919f52532Smartin * notice, this list of conditions and the following disclaimer.
1019f52532Smartin * 2. Redistributions in binary form must reproduce the above copyright
1119f52532Smartin * notice, this list of conditions and the following disclaimer in the
1219f52532Smartin * documentation and/or other materials provided with the distribution.
1319f52532Smartin *
1419f52532Smartin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1519f52532Smartin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1619f52532Smartin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1719f52532Smartin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1819f52532Smartin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1919f52532Smartin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2019f52532Smartin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2119f52532Smartin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2219f52532Smartin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2319f52532Smartin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419f52532Smartin * SUCH DAMAGE.
2519f52532Smartin */
2619f52532Smartin
2719f52532Smartin #include <sys/cdefs.h>
28*1c052966Schristos __RCSID("$NetBSD: posix_spawn_fileactions.c,v 1.5 2021/11/07 14:34:30 christos Exp $");
2919f52532Smartin
3019f52532Smartin #include "namespace.h"
3119f52532Smartin
3219f52532Smartin #include <errno.h>
3319f52532Smartin #include <fcntl.h>
3419f52532Smartin #include <sched.h>
3519f52532Smartin #include <signal.h>
3619f52532Smartin #include <stdlib.h>
3719f52532Smartin #include <string.h>
3819f52532Smartin #include <unistd.h>
3919f52532Smartin #include <spawn.h>
4019f52532Smartin
4119f52532Smartin #define MIN_SIZE 16
4219f52532Smartin
4319f52532Smartin /*
4419f52532Smartin * File descriptor actions
4519f52532Smartin */
4619f52532Smartin
4719f52532Smartin int
posix_spawn_file_actions_init(posix_spawn_file_actions_t * fa)4819f52532Smartin posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa)
4919f52532Smartin {
5019f52532Smartin if (fa == NULL)
51b450cd5bSmartin return EINVAL;
5219f52532Smartin
5319f52532Smartin fa->fae = malloc(MIN_SIZE * sizeof(struct posix_spawn_file_actions_entry));
5419f52532Smartin if (fa->fae == NULL)
55b450cd5bSmartin return ENOMEM;
5619f52532Smartin fa->size = MIN_SIZE;
5719f52532Smartin fa->len = 0;
5819f52532Smartin
59b450cd5bSmartin return 0;
6019f52532Smartin }
6119f52532Smartin
6219f52532Smartin int
posix_spawn_file_actions_destroy(posix_spawn_file_actions_t * fa)6319f52532Smartin posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa)
6419f52532Smartin {
6594b761b6Smartin unsigned int i;
6619f52532Smartin
6719f52532Smartin if (fa == NULL)
68b450cd5bSmartin return EINVAL;
6919f52532Smartin
7019f52532Smartin for (i = 0; i < fa->len; i++) {
7119f52532Smartin if (fa->fae[i].fae_action == FAE_OPEN)
7219f52532Smartin free(fa->fae[i].fae_path);
7319f52532Smartin }
7419f52532Smartin
7519f52532Smartin free(fa->fae);
76b450cd5bSmartin return 0;
7719f52532Smartin }
7819f52532Smartin
7919f52532Smartin static int
posix_spawn_file_actions_getentry(posix_spawn_file_actions_t * fa,unsigned int * i)802934fa70Smartin posix_spawn_file_actions_getentry(posix_spawn_file_actions_t *fa,
812934fa70Smartin unsigned int *i)
8219f52532Smartin {
832934fa70Smartin posix_spawn_file_actions_entry_t *fae;
842934fa70Smartin
8519f52532Smartin if (fa == NULL)
86b450cd5bSmartin return EINVAL;
8719f52532Smartin
8819f52532Smartin if (fa->len < fa->size)
892934fa70Smartin goto out;
9019f52532Smartin
912934fa70Smartin fae = realloc(fa->fae, (fa->size + MIN_SIZE) * sizeof(*fa->fae));
922934fa70Smartin if (fae == NULL)
93b450cd5bSmartin return ENOMEM;
9419f52532Smartin
952934fa70Smartin fa->fae = fae;
9619f52532Smartin fa->size += MIN_SIZE;
9719f52532Smartin
982934fa70Smartin out:
992934fa70Smartin *i = fa->len;
100b450cd5bSmartin return 0;
10119f52532Smartin }
10219f52532Smartin
10319f52532Smartin int
posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,int fildes,const char * __restrict path,int oflag,mode_t mode)10419f52532Smartin posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,
10519f52532Smartin int fildes, const char * __restrict path, int oflag, mode_t mode)
10619f52532Smartin {
1072934fa70Smartin char *faepath;
1082934fa70Smartin unsigned int i;
1092934fa70Smartin int error;
11019f52532Smartin
11119f52532Smartin if (fildes < 0)
112b450cd5bSmartin return EBADF;
11319f52532Smartin
1142934fa70Smartin error = posix_spawn_file_actions_getentry(fa, &i);
1152934fa70Smartin if (error)
116b450cd5bSmartin return error;
1172934fa70Smartin
1182934fa70Smartin faepath = strdup(path);
1192934fa70Smartin if (faepath == NULL)
120b450cd5bSmartin return ENOMEM;
12119f52532Smartin
12219f52532Smartin fa->fae[i].fae_action = FAE_OPEN;
1232934fa70Smartin fa->fae[i].fae_path = faepath;
12419f52532Smartin fa->fae[i].fae_fildes = fildes;
12519f52532Smartin fa->fae[i].fae_oflag = oflag;
12619f52532Smartin fa->fae[i].fae_mode = mode;
12719f52532Smartin fa->len++;
12819f52532Smartin
129b450cd5bSmartin return 0;
13019f52532Smartin }
13119f52532Smartin
13219f52532Smartin int
posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t * fa,int fildes,int newfildes)13319f52532Smartin posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa,
13419f52532Smartin int fildes, int newfildes)
13519f52532Smartin {
1362934fa70Smartin unsigned int i;
1372934fa70Smartin int error;
13819f52532Smartin
13919f52532Smartin if (fildes < 0 || newfildes < 0)
140b450cd5bSmartin return EBADF;
14119f52532Smartin
1422934fa70Smartin error = posix_spawn_file_actions_getentry(fa, &i);
1432934fa70Smartin if (error)
144b450cd5bSmartin return error;
14519f52532Smartin
14619f52532Smartin fa->fae[i].fae_action = FAE_DUP2;
14719f52532Smartin fa->fae[i].fae_fildes = fildes;
14819f52532Smartin fa->fae[i].fae_newfildes = newfildes;
14919f52532Smartin fa->len++;
15019f52532Smartin
151b450cd5bSmartin return 0;
15219f52532Smartin }
15319f52532Smartin
15419f52532Smartin int
posix_spawn_file_actions_addclose(posix_spawn_file_actions_t * fa,int fildes)15519f52532Smartin posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa,
15619f52532Smartin int fildes)
15719f52532Smartin {
1582934fa70Smartin unsigned int i;
1592934fa70Smartin int error;
16019f52532Smartin
16119f52532Smartin if (fildes < 0)
162b450cd5bSmartin return EBADF;
16319f52532Smartin
1642934fa70Smartin error = posix_spawn_file_actions_getentry(fa, &i);
1652934fa70Smartin if (error)
166b450cd5bSmartin return error;
16719f52532Smartin
16819f52532Smartin fa->fae[i].fae_action = FAE_CLOSE;
16919f52532Smartin fa->fae[i].fae_fildes = fildes;
17019f52532Smartin fa->len++;
17119f52532Smartin
172b450cd5bSmartin return 0;
17319f52532Smartin }
174*1c052966Schristos
175*1c052966Schristos int
posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t * __restrict fa,const char * __restrict path)176*1c052966Schristos posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t * __restrict fa,
177*1c052966Schristos const char * __restrict path)
178*1c052966Schristos {
179*1c052966Schristos char *dirpath;
180*1c052966Schristos unsigned int i;
181*1c052966Schristos int error;
182*1c052966Schristos
183*1c052966Schristos error = posix_spawn_file_actions_getentry(fa, &i);
184*1c052966Schristos if (error)
185*1c052966Schristos return error;
186*1c052966Schristos
187*1c052966Schristos dirpath = strdup(path);
188*1c052966Schristos if (dirpath == NULL)
189*1c052966Schristos return ENOMEM;
190*1c052966Schristos
191*1c052966Schristos fa->fae[i].fae_action = FAE_CHDIR;
192*1c052966Schristos fa->fae[i].fae_chdir_path = dirpath;
193*1c052966Schristos fa->fae[i].fae_fildes = -1;
194*1c052966Schristos fa->len++;
195*1c052966Schristos
196*1c052966Schristos return 0;
197*1c052966Schristos }
198*1c052966Schristos
199*1c052966Schristos int
posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t * fa,int fildes)200*1c052966Schristos posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t *fa, int fildes)
201*1c052966Schristos {
202*1c052966Schristos unsigned int i;
203*1c052966Schristos int error;
204*1c052966Schristos
205*1c052966Schristos if (fildes < 0)
206*1c052966Schristos return EBADF;
207*1c052966Schristos
208*1c052966Schristos error = posix_spawn_file_actions_getentry(fa, &i);
209*1c052966Schristos if (error)
210*1c052966Schristos return error;
211*1c052966Schristos
212*1c052966Schristos fa->fae[i].fae_action = FAE_FCHDIR;
213*1c052966Schristos fa->fae[i].fae_fildes = fildes;
214*1c052966Schristos fa->len++;
215*1c052966Schristos
216*1c052966Schristos return 0;
217*1c052966Schristos }
218