mirror of
git://git.musl-libc.org/musl
synced 2025-03-06 20:48:29 +01:00
the newly allocated FILE * has not yet leaked to the application and is only visible to stdio internals until popen returns. since we do not change any fields of the structure observed by libc internals, only the pipe_pid member, locking is not necessary.
55 lines
1.1 KiB
C
55 lines
1.1 KiB
C
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <spawn.h>
|
|
#include "stdio_impl.h"
|
|
#include "syscall.h"
|
|
|
|
extern char **__environ;
|
|
|
|
FILE *popen(const char *cmd, const char *mode)
|
|
{
|
|
int p[2], op, e;
|
|
pid_t pid;
|
|
FILE *f;
|
|
posix_spawn_file_actions_t fa;
|
|
|
|
if (*mode == 'r') {
|
|
op = 0;
|
|
} else if (*mode == 'w') {
|
|
op = 1;
|
|
} else {
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
if (pipe2(p, O_CLOEXEC)) return NULL;
|
|
f = fdopen(p[op], mode);
|
|
if (!f) {
|
|
__syscall(SYS_close, p[0]);
|
|
__syscall(SYS_close, p[1]);
|
|
return NULL;
|
|
}
|
|
|
|
e = ENOMEM;
|
|
if (!posix_spawn_file_actions_init(&fa)) {
|
|
if (!posix_spawn_file_actions_adddup2(&fa, p[1-op], 1-op)) {
|
|
if (!(e = posix_spawn(&pid, "/bin/sh", &fa, 0,
|
|
(char *[]){ "sh", "-c", (char *)cmd, 0 }, __environ))) {
|
|
posix_spawn_file_actions_destroy(&fa);
|
|
f->pipe_pid = pid;
|
|
if (!strchr(mode, 'e'))
|
|
fcntl(p[op], F_SETFD, 0);
|
|
__syscall(SYS_close, p[1-op]);
|
|
return f;
|
|
}
|
|
}
|
|
posix_spawn_file_actions_destroy(&fa);
|
|
}
|
|
fclose(f);
|
|
__syscall(SYS_close, p[1-op]);
|
|
|
|
errno = e;
|
|
return 0;
|
|
}
|