Index | Thread | Search

From:
Mike Larkin <mlarkin@nested.page>
Subject:
Re: posix_spawn_file_actions_addchdir/addfchdir
To:
tech@openbsd.org
Date:
Mon, 10 Aug 2026 05:25:34 -0700

Download raw body.

Thread
On Thu, Aug 06, 2026 at 06:56:23PM +0200, Kirill A. Korinsky wrote:
> On Thu, 06 Aug 2026 14:24:15 +0200,
> Stuart Henderson <stu@spacehopper.org> wrote:
> >
> > posix_spawn_file_actions_addchdir and posix_spawn_file_actions_addfchdir
> > have been implemented as _np in some OS for a while, but have made it
> > into posix now.
> >
> > https://pubs.opengroup.org/onlinepubs/9799919799.2024edition/functions/posix_spawn_file_actions_addchdir.html
> >
> > a number of things in ports print information about testing for them
> > during configure (mostly via gnulib which provides replacements).
> > also the subprocess mode in llama.cpp is forcibly disabled via a
> > patch because we don't have ..._addchdir().
> >
> > https://exopi.bsdfrog.org/cgi-bin/omega?P=posix_spawn_file_actions_addchdir&DEFAULTOP=and&DB=default&FMT=query&xDB=default&xFILTERS=5
> >
> > do we want them (yet)? is this diff vaguely along the right lines?
> > (obviously needs shlib bump and testing in ports bulk).
> >
> > I wrote an initial diff, then discovered FreeBSD had them already
> > (then added the missing free which I spotted after comparing ;)
> >
>
> NetBSD also has them:
> https://man.netbsd.org/posix_spawn_file_actions_addchdir.3
>
> And yes, we need them for ports, I had encountered at least one case when it
> required: llama.cpp via https://github.com/sheredom/subprocess.h
>

I ran into the same thing with llama.cpp, so the change below would be welcome.

-ml

> Your diff reads sane enough, but I not sure that can review it the right way.
>
> > 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	6 Aug 2026 12:18:31 -0000
> > @@ -69,6 +69,9 @@ 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);
> > +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);
> >
> >  /*
> >   * 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	6 Aug 2026 12:18:31 -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	6 Aug 2026 12:18:31 -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	6 Aug 2026 12:18:31 -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,54 @@ 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 *__restrict 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 *__restrict fa,
> > +    int fildes)
> > +{
> > +	posix_spawn_file_actions_entry_t *fae;
> > +	int error;
> > +
> > +	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	6 Aug 2026 12:18:31 -0000
> > @@ -18,17 +18,23 @@
> >  .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
> >  .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
> > @@ -45,6 +51,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 +84,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
> > @@ -100,7 +124,12 @@ if they run out of memory.
> >  .Xr posix_spawn_file_actions_init 3 ,
> >  .Xr posix_spawnp 3
> >  .Sh STANDARDS
> > -These functions conform to
> > +.Fn posix_spawn_file_actions_addchdir
> > +and
> > +.Fn posix_spawn_file_actions_addfchdir
> > +conform to
> > +.St -p1003.1-2024 .
> > +Other functions conform to
> >  .St -p1003.1-2001 .
> >  .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	6 Aug 2026 12:18:31 -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);
> >
>
> --
> wbr, Kirill
>