xref: /netbsd-src/lib/libc/gen/posix_spawn_fileactions.c (revision 1c052966329e857098263b940f45dd4a9856a0c9)
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