Index | Thread | Search

From:
Stuart Henderson <stu@spacehopper.org>
Subject:
Re: posix_spawn_file_actions_addchdir/addfchdir
To:
tech <tech@openbsd.org>
Date:
Fri, 28 Aug 2026 10:18:48 +0100

Download raw body.

Thread
updated for daniel@'s feedback

Index: include/spawn.h
===================================================================
RCS file: /cvs/src/include/spawn.h,v
diff -u -p -r1.3 spawn.h
--- include/spawn.h	20 May 2015 22:50:07 -0000	1.3
+++ include/spawn.h	28 Aug 2026 09:17:56 -0000
@@ -69,6 +69,11 @@ int posix_spawn_file_actions_addopen(pos
     int, const char *__restrict, int, mode_t);
 int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int);
 int posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *, int);
+#if __POSIX_VISIBLE >= 202405
+int posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t *__restrict,
+    const char *__restrict);
+int posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t *, int);
+#endif
 
 /*
  * Spawn attributes
Index: lib/libc/Symbols.list
===================================================================
RCS file: /cvs/src/lib/libc/Symbols.list,v
diff -u -p -r1.95 Symbols.list
--- lib/libc/Symbols.list	24 Oct 2025 11:30:06 -0000	1.95
+++ lib/libc/Symbols.list	28 Aug 2026 09:17:56 -0000
@@ -725,8 +725,10 @@ pause
 pclose
 popen
 posix_spawn
+posix_spawn_file_actions_addchdir
 posix_spawn_file_actions_addclose
 posix_spawn_file_actions_adddup2
+posix_spawn_file_actions_addfchdir
 posix_spawn_file_actions_addopen
 posix_spawn_file_actions_destroy
 posix_spawn_file_actions_init
Index: lib/libc/gen/posix_spawn.3
===================================================================
RCS file: /cvs/src/lib/libc/gen/posix_spawn.3,v
diff -u -p -r1.11 posix_spawn.3
--- lib/libc/gen/posix_spawn.3	26 Jun 2023 15:28:52 -0000	1.11
+++ lib/libc/gen/posix_spawn.3	28 Aug 2026 09:17:56 -0000
@@ -73,8 +73,10 @@ with
 Otherwise, file descriptors in the child process
 are altered according to
 .Xr posix_spawn_file_actions_init 3 ,
+.Xr posix_spawn_file_actions_addchdir 3 ,
 .Xr posix_spawn_file_actions_addclose 3 ,
 .Xr posix_spawn_file_actions_adddup2 3 ,
+.Xr posix_spawn_file_actions_addfchdir 3 ,
 and
 .Xr posix_spawn_file_actions_addopen 3 .
 .Pp
Index: lib/libc/gen/posix_spawn.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/posix_spawn.c,v
diff -u -p -r1.10 posix_spawn.c
--- lib/libc/gen/posix_spawn.c	28 Jun 2019 13:32:41 -0000	1.10
+++ lib/libc/gen/posix_spawn.c	28 Aug 2026 09:17:56 -0000
@@ -51,7 +51,7 @@ struct __posix_spawn_file_actions {
 
 typedef struct __posix_spawn_file_actions_entry {
 	SIMPLEQ_ENTRY(__posix_spawn_file_actions_entry) fae_list;
-	enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action;
+	enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE, FAE_CHDIR, FAE_FCHDIR } fae_action;
 
 	int fae_fildes;
 	union {
@@ -171,6 +171,14 @@ process_file_actions_entry(posix_spawn_f
 		/* Perform a close(), do not fail if already closed */
 		(void)close(fae->fae_fildes);
 		break;
+	case FAE_CHDIR:
+		if (chdir(fae->fae_path) == -1)
+			return (errno);
+		break;
+	case FAE_FCHDIR:
+		if (fchdir(fae->fae_fildes) == -1)
+			return (errno);
+		break;
 	}
 	return (0);
 }
@@ -273,7 +281,8 @@ posix_spawn_file_actions_destroy(posix_s
 		SIMPLEQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list);
 
 		/* Deallocate file action entry */
-		if (fae->fae_action == FAE_OPEN)
+		if (fae->fae_action == FAE_OPEN ||
+		    fae->fae_action == FAE_CHDIR)
 			free(fae->fae_path);
 		free(fae);
 	}
@@ -352,6 +361,53 @@ posix_spawn_file_actions_addclose(posix_
 
 	/* Set values and store in queue */
 	fae->fae_action = FAE_CLOSE;
+	fae->fae_fildes = fildes;
+
+	SIMPLEQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
+	return (0);
+}
+
+int
+posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t *fa,
+    const char *__restrict path)
+{
+	posix_spawn_file_actions_entry_t *fae;
+	int error;
+
+	/* Allocate object */
+	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
+	if (fae == NULL)
+		return (errno);
+
+	/* Set values and store in queue */
+	fae->fae_action = FAE_CHDIR;
+	fae->fae_path = strdup(path);
+	if (fae->fae_path == NULL) {
+		error = errno;
+		free(fae);
+		return (error);
+	}
+
+	SIMPLEQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
+	return (0);
+}
+
+int
+posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t *fa,
+    int fildes)
+{
+	posix_spawn_file_actions_entry_t *fae;
+
+	if (fildes < 0)
+		return (EBADF);
+
+	/* Allocate object */
+	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
+	if (fae == NULL)
+		return (errno);
+
+	/* Set values and store in queue */
+	fae->fae_action = FAE_FCHDIR;
 	fae->fae_fildes = fildes;
 
 	SIMPLEQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
Index: lib/libc/gen/posix_spawn_file_actions_addopen.3
===================================================================
RCS file: /cvs/src/lib/libc/gen/posix_spawn_file_actions_addopen.3,v
diff -u -p -r1.9 posix_spawn_file_actions_addopen.3
--- lib/libc/gen/posix_spawn_file_actions_addopen.3	29 Mar 2022 18:15:52 -0000	1.9
+++ lib/libc/gen/posix_spawn_file_actions_addopen.3	28 Aug 2026 09:17:56 -0000
@@ -18,22 +18,31 @@
 .Dt POSIX_SPAWN_FILE_ACTIONS_ADDOPEN 3
 .Os
 .Sh NAME
+.Nm posix_spawn_file_actions_addchdir ,
 .Nm posix_spawn_file_actions_addclose ,
 .Nm posix_spawn_file_actions_adddup2 ,
+.Nm posix_spawn_file_actions_addfchdir ,
 .Nm posix_spawn_file_actions_addopen
-.Nd add action to close, dup2 or open file descriptor to file actions object
+.Nd add action to change directory, close, dup2 or open file descriptor
+to file actions object
 .Sh SYNOPSIS
 .In spawn.h
 .Ft int
+.Fn posix_spawn_file_actions_addchdir "posix_spawn_file_actions_t *file_actions" "const char *restrict path"
+.Ft int
 .Fn posix_spawn_file_actions_addclose "posix_spawn_file_actions_t *file_actions" "int fildes"
 .Ft int
 .Fn posix_spawn_file_actions_adddup2 "posix_spawn_file_actions_t *file_actions" "int fildes" "int newfildes"
 .Ft int
+.Fn posix_spawn_file_actions_addfchdir "posix_spawn_file_actions_t *file_actions" "int fildes"
+.Ft int
 .Fn posix_spawn_file_actions_addopen "posix_spawn_file_actions_t *file_actions" "int fildes" "const char *restrict path" "int oflag" "mode_t mode"
 .Sh DESCRIPTION
-These function add an action to
+These functions add an action to
+.Xr chdir 2 ,
 .Xr close 2 ,
 .Xr dup2 2 ,
+.Xr fchdir 2 ,
 or
 .Xr open 2
 a file descriptor
@@ -45,6 +54,15 @@ Actions are executed in order in the chi
 .Bl -dash
 .It
 The
+.Fn posix_spawn_file_actions_addchdir
+function adds an action that causes
+.Bd -literal -offset indent
+chdir(path);
+.Ed
+.Pp
+to be called.
+.It
+The
 .Fn posix_spawn_file_actions_addclose
 function adds an action that causes
 .Bd -literal -offset indent
@@ -69,6 +87,15 @@ equals
 .Fa fildes .
 .It
 The
+.Fn posix_spawn_file_actions_addfchdir
+function adds an action that causes
+.Bd -literal -offset indent
+fchdir(fildes);
+.Ed
+.Pp
+to be called.
+.It
+The
 .Fn posix_spawn_file_actions_addopen
 function adds an action that causes
 .Bd -literal -offset indent
@@ -91,7 +118,7 @@ argument.
 .Sh RETURN VALUES
 Upon successful completion, these functions return zero.
 Otherwise they may return
-.Er EINVAL
+.Er EBADF
 for negative file descriptors, or
 .Er ENOMEM
 if they run out of memory.
@@ -101,6 +128,6 @@ if they run out of memory.
 .Xr posix_spawnp 3
 .Sh STANDARDS
 These functions conform to
-.St -p1003.1-2001 .
+.St -p1003.1-2024 .
 .Sh AUTHORS
 .An \&Ed Schouten Aq Mt ed@FreeBSD.org
Index: lib/libc/hidden/spawn.h
===================================================================
RCS file: /cvs/src/lib/libc/hidden/spawn.h,v
diff -u -p -r1.1 spawn.h
--- lib/libc/hidden/spawn.h	4 Oct 2015 07:57:21 -0000	1.1
+++ lib/libc/hidden/spawn.h	28 Aug 2026 09:17:56 -0000
@@ -21,8 +21,10 @@
 #include_next <spawn.h>
 
 PROTO_DEPRECATED(posix_spawn);
+PROTO_DEPRECATED(posix_spawn_file_actions_addchdir);
 PROTO_DEPRECATED(posix_spawn_file_actions_addclose);
 PROTO_DEPRECATED(posix_spawn_file_actions_adddup2);
+PROTO_DEPRECATED(posix_spawn_file_actions_addfchdir);
 PROTO_DEPRECATED(posix_spawn_file_actions_addopen);
 PROTO_DEPRECATED(posix_spawn_file_actions_destroy);
 PROTO_DEPRECATED(posix_spawn_file_actions_init);