feat(process): fork/exec/id/session + system/popen

This commit is contained in:
2026-09-05 16:55:14 -04:00
parent c9e9676d38
commit 14c6fd6cf6
19 changed files with 2118 additions and 2 deletions
+15
View File
@@ -261,6 +261,21 @@ tmpfile(void);
__attribute__((pure)) int
fileno(FILE *stream);
/*
* Run command in a subshell ("sh -c command") with a pipe attached to
* its standard output (mode "r") or standard input (mode "w"). Only the
* two POSIX modes are accepted (the glibc "re"/"we" close-on-exec
* extension is not). Returns the stream, or NULL with errno set.
* pclose closes the stream, waits for the shell, and returns its
* termination status (the raw wait status, e.g. 0 for "exit 0"), or -1
* when the stream was not opened by popen or the wait failed.
*/
FILE *
popen(const char *command, const char *mode);
int
pclose(FILE *stream);
/* getc/putc/getchar/putchar as macros over fgetc/fputc (see above). */
#define getc(stream) fgetc(stream)
#define putc(c, stream) fputc((c), (stream))
+13
View File
@@ -463,6 +463,19 @@ mkstemp(char *);
char *
mkdtemp(char *);
/* process control (todo 20) */
/*
* Pass string to the command language interpreter: "sh -c string".
* Returns the shell's wait status (e.g. 768 for "exit 3"), 1 when
* string is NULL (a shell is always available), or -1 with errno set
* when the child cannot be created or reaped. During the run, SIGCHLD
* is blocked and SIGINT/SIGQUIT are ignored in the caller, as POSIX
* requires.
*/
int
system(const char *string);
#if VLIBC_LEVEL_GE(2)
/* Level 2 (muslmimic): XSI and BSD environment extras. */
+167 -2
View File
@@ -15,6 +15,15 @@
* Level 2 (muslmimic): dup3, pipe2 (Linux extensions), truncate (XSI),
* lseek64 (glibc LFS alias of lseek on x86_64).
*
* Process control (todo 20) is declared further down:
*
* Level 1 (onlyposix): fork, exec family (execl/execlp/execle/execv/
* execvp/execve/fexecve), getpid, getppid, getuid,
* geteuid, getgid, getegid, setuid, seteuid, setgid,
* setegid, getgroups, setpgid, getpgrp, setsid.
* Level 2 (muslmimic): vfork, setpgrp (obsolescent), setgroups, getpgid,
* getsid, tcgetpgrp, tcsetpgrp (XSI).
*
* The open-flag constants (O_RDONLY, O_CREAT, O_CLOEXEC, ...) belong to
* <fcntl.h> and are deliberately not defined here; the oflag arguments below
* are plain int and take their values from that header. The optional mode
@@ -23,7 +32,10 @@
*
* None of these declarations carry an intent attribute: every function
* performs I/O with side effects and reports failures through errno, so
* const/pure would be unsound.
* const/pure would be unsound. The process functions additionally must not
* be const/pure because their results are process state — marking getpid
* const, for example, would let the compiler hoist it across fork() and
* observe the parent's pid inside the child.
*/
#include <vlibc/features.h>
@@ -174,8 +186,119 @@ access(const char *path, int amode);
int
faccessat(int fd, const char *path, int amode, int flag);
/* Level 1 (POSIX base): process control. */
/*
* Create a child process that is a copy of the caller: fork() returns 0
* in the child, the child's pid in the parent, and -1 with errno set on
* failure.
*
* Around the fork, the atfork hook table runs: the prepare handlers in
* reverse registration order before the fork, then the child handlers in
* the child and the parent handlers in the parent, both in registration
* order (POSIX pthread_atfork protocol). The table is registered by
* pthread_atfork() (todo 45) and is empty — a no-op — in a process
* without threads.
*/
pid_t
fork(void);
/*
* Replace the calling process image. Success never returns; -1 with
* errno set otherwise. execl/execle/execlp take the arguments as a
* varargs list terminated by (char *)NULL (execle is followed by one
* final char *const envp[] argument); execv/execvp take an argv array.
* execvp and execlp search the PATH environment variable (default
* "/bin:/usr/bin") when file contains no '/'. execv/execvp/execl/execlp
* use the caller's environment; execve/execle/fexecve take envp.
*/
// NOLINTBEGIN(bugprone-easily-swappable-parameters)
int
execl(const char *path, const char *arg0, ...);
int
execle(const char *path, const char *arg0, ...);
int
execlp(const char *file, const char *arg0, ...);
// NOLINTEND(bugprone-easily-swappable-parameters)
int
execv(const char *path, char *const argv[]);
int
execvp(const char *file, char *const argv[]);
int
execve(const char *path, char *const argv[], char *const envp[]);
/*
* Like execve, but the image is the open descriptor fd.
*/
int
fexecve(int fd, char *const argv[], char *const envp[]);
/*
* Process ids. getpid/getppid/getuid/geteuid/getgid/getegid read the
* kernel's per-process ids; setuid/seteuid/setgid/setegid change them.
* seteuid/setegid change only the effective id (setresuid/setresgid
* underneath: Linux has no seteuid/setegid syscall).
*/
pid_t
getpid(void);
pid_t
getppid(void);
uid_t
getuid(void);
uid_t
geteuid(void);
gid_t
getgid(void);
gid_t
getegid(void);
int
setuid(uid_t uid);
int
seteuid(uid_t euid);
int
setgid(gid_t gid);
int
setegid(gid_t egid);
/*
* Supplementary groups: getgroups fills grouplist with up to gidsetsize
* group ids and returns the total count (0 can be passed to count only);
* setgroups (level 2, XSI) installs the list.
*/
int
getgroups(int gidsetsize, gid_t grouplist[]);
/*
* Session control: setpgid moves pid into process group pgid (0 means
* the caller / the caller's pid); getpgrp returns the caller's process
* group; setsid creates a new session with the caller as leader and
* returns the new session id.
*/
int
setpgid(pid_t pid, pid_t pgid);
pid_t
getpgrp(void);
pid_t
setsid(void);
#if VLIBC_LEVEL_GE(2)
/* Level 2 (muslmimic): Linux extensions + XSI. */
/* Level 2 (muslmimic): Linux extensions + XSI + obsolescent. */
/*
* Like dup2(), but with descriptor flags (O_CLOEXEC from <fcntl.h>) applied
@@ -205,6 +328,48 @@ truncate(const char *path, off_t length);
*/
off_t
lseek64(int fildes, off_t offset, int whence);
/*
* vfork (obsolescent): like fork(), but the child borrows the parent's
* address space until it execs or exits.
*/
pid_t
vfork(void);
/*
* setpgrp (obsolescent): setpgid(0, 0) — the caller becomes the leader
* of its own process group.
*/
int
setpgrp(void);
/*
* setgroups (XSI): install the supplementary group list of gidsetsize
* entries. Requires privilege.
*/
int
setgroups(size_t gidsetsize, const gid_t *grouplist);
/*
* getpgid/getsid (XSI): the process group / session of pid (0 = the
* caller).
*/
pid_t
getpgid(pid_t pid);
pid_t
getsid(pid_t pid);
/*
* Controlling-terminal foreground process group (XSI): tcgetpgrp reads
* the foreground group of the terminal on fildes; tcsetpgrp makes pgid
* the foreground group.
*/
pid_t
tcgetpgrp(int fildes);
int
tcsetpgrp(int fildes, pid_t pgid);
#endif /* VLIBC_LEVEL_GE(2) */
#ifdef __cplusplus