diff options
| author | Kacper <kacper@mail.openlinux.dev> | 2025-12-07 20:10:31 +0100 |
|---|---|---|
| committer | Kacper <kacper@mail.openlinux.dev> | 2025-12-07 20:10:31 +0100 |
| commit | fc00c656c96528112d05cf0edf8631bd5eaea446 (patch) | |
| tree | a6e0e6c588191a8bd1c64afc3b7a258e3e66c236 /lib/libc/stdio/popen.c | |
Add build system scaffolding and libc headers
Diffstat (limited to 'lib/libc/stdio/popen.c')
| -rw-r--r-- | lib/libc/stdio/popen.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/libc/stdio/popen.c b/lib/libc/stdio/popen.c new file mode 100644 index 00000000..92b6a099 --- /dev/null +++ b/lib/libc/stdio/popen.c @@ -0,0 +1,65 @@ +#include <io.h> +#include <errno.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> + +FILE *popen(const char *command, const char *mode) +{ + FILE *stream; + int oflag; + int pipefd[2]; + + switch (*mode) { + case 'r': + oflag = O_RDONLY; + break; + case 'w': + oflag = O_WRONLY; + break; + default: + errno = EINVAL; + return NULL; + } + + if (pipe2(pipefd, O_CLOEXEC) < 0) + return NULL; + + stream = fdopen(pipefd[oflag], mode); + if (stream == NULL) { + close(pipefd[0]); + close(pipefd[1]); + return NULL; + } + + pid_t pid = fork(); + + if (pid < 0) { + close(pipefd[0]); + close(pipefd[1]); + fclose(stream); + return NULL; + } else if (pid == 0) { + if (oflag == O_RDONLY) { + dup2(pipefd[1], STDOUT_FILENO); + close(pipefd[0]); + close(pipefd[1]); + } else { + dup2(pipefd[0], STDIN_FILENO); + close(pipefd[0]); + close(pipefd[1]); + } + execl("/bin/sh", "sh", "-c", command, (char *)NULL); + _exit(127); + } else { + if (oflag == O_RDONLY) { + close(pipefd[1]); + } else { + close(pipefd[0]); + } + + stream->pid = pid; + + return stream; + } +} |
