Add popen(3)/pclose(3), add missing signatures to headers

This commit is contained in:
Mark
2020-07-23 13:33:46 +03:00
parent 0547f201f1
commit c7ff6ce9a1
13 changed files with 162 additions and 9 deletions
+2
View File
@@ -12,6 +12,8 @@ SHARED_LIBS=
# Build
CFLAGS=-I include \
-ggdb \
-Og \
-ffreestanding \
-Wall \
-Wextra \
+19
View File
@@ -3,4 +3,23 @@
#define HUGE_VAL (__builtin_huge_val())
double log10(double f);
double log2(double f);
double log(double f);
double sqrt(double f);
double floor(double f);
double ceil(double f);
double fmod(double x, double y);
double atan2(double x, double y);
double asin(double x);
double acos(double x);
double fabs(double x);
double pow(double x, double y);
double tanh(double f);
double cosh(double f);
double sinh(double f);
double sin(double f);
double cos(double f);
double tan(double f);
double frexp(double x, int *exp);
double ldexp(double x, int exp);
double exp(double f);
+2
View File
@@ -4,5 +4,7 @@ typedef struct {
unsigned long _v[8];
} jmp_buf[1];
int _setjmp(jmp_buf env);
int setjmp(jmp_buf env);
void _longjmp(jmp_buf env, int val);
void longjmp(jmp_buf env, int val);
+6
View File
@@ -34,6 +34,12 @@ int renameat(int olddfd, const char *oldpath, int newdfd, const char *newpath
char *ctermid(char *s);
int setvbuf(FILE *fp, char *buf, int mode, size_t size);
void setbuf(FILE *fp, char *buf);
int ungetc(int ch, FILE *fp);
FILE *tmpfile(void);
FILE *popen(const char *command, const char *type);
int pclose(FILE *fp);
void flockfile(FILE *fp);
void funlockfile(FILE *fp);
+6 -3
View File
@@ -11,12 +11,15 @@ __Malloc void *calloc(size_t size, size_t nmemb);
__Malloc void *malloc(size_t size);
void *realloc(void *p, size_t newsz);
void free(void *ptr);
_Noreturn void abort(void);
int abs(int d);
int system(const char *command);
int atoi(const char *str);
char *getenv(const char *name);
int setenv(const char *name, const char *value, int overwrite);
// XXX: POSIX doesn't define _Noreturn attribute on those?
void _Exit(int status);
void exit(int status);
_Noreturn void _Exit(int status);
_Noreturn void exit(int status);
+2
View File
@@ -23,4 +23,6 @@ time_t time(time_t *t);
double difftime(time_t t1, time_t t0);
struct tm *gmtime_r(const time_t *restrict timep, struct tm *restrict res);
struct tm *localtime_r(const time_t *restrict timep, struct tm *restrict res);
time_t mktime(struct tm *tm);
size_t strftime(char *restrict buf, size_t lim, const char *restrict fmt, const struct tm *restrict tm);
+10
View File
@@ -0,0 +1,10 @@
#include <stdlib.h>
#include <string.h>
void *calloc(size_t size, size_t nmemb) {
void *blk = malloc(size * nmemb);
if (blk) {
memset(blk, 0, size * nmemb);
}
return blk;
}
+4
View File
@@ -2,6 +2,10 @@
#include <stdio.h>
int fflush(FILE *fp) {
if (!fp) {
// TODO: flush all open files
return 0;
}
if (fp->buf_mode != _IONBF) {
if (__libc_file_flush_read(fp) != 0) {
return -1;
+1
View File
@@ -20,6 +20,7 @@ FILE *__libc_file_create(void) {
res->free = file_default_free;
res->buf = ((void *) res) + sizeof(FILE);
res->buf_mode = _IOLBF;
res->ungetc = -1;
return res;
+1
View File
@@ -23,6 +23,7 @@ ssize_t getdelim(char **lineptr, size_t *n, int delim, FILE *fp) {
}
p = *lineptr;
rem = *n;
while (1) {
if (!rem) {
+1 -2
View File
@@ -1,6 +1,5 @@
#include <stdio.h>
int pclose(FILE *fp) {
(void) fp;
return 0;
return fclose(fp);
}
+107 -3
View File
@@ -1,9 +1,113 @@
#include <_libc/stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
// Internal pipe state
struct pipe {
int fd;
pid_t pid;
};
static ssize_t pipe_read(void *ctx, void *buf, size_t lim) {
return read(((struct pipe *) ctx)->fd, buf, lim);
}
static ssize_t pipe_write(void *ctx, const void *buf, size_t lim) {
return write(((struct pipe *) ctx)->fd, buf, lim);
}
static off_t pipe_seek(void *ctx, off_t offset, int whence) {
(void) ctx;
(void) offset;
(void) whence;
errno = ESPIPE;
return -1;
}
static int pipe_close(void *_ctx) {
struct pipe *ctx = _ctx;
close(ctx->fd);
int r;
if (waitpid(ctx->pid, &r, 0) < 0) {
return -1;
}
free(ctx);
return r;
}
FILE *popen(const char *command, const char *mode) {
(void) command;
(void) mode;
errno = EINVAL;
int fds[2];
struct pipe *ctx;
FILE *fp = NULL;
int flags = __libc_file_mode(mode);
if (flags < 0) {
errno = EINVAL;
return NULL;
}
if ((flags & (FILE_MODE_WRITE | FILE_MODE_READ)) == (FILE_MODE_READ | FILE_MODE_WRITE)) {
errno = EINVAL;
return NULL;
}
if (!(ctx = calloc(1, sizeof(struct pipe)))) {
goto err;
}
if (!(fp = __libc_file_create())) {
goto err_ctx;
}
if (pipe(fds) != 0) {
goto err_file;
}
if ((ctx->pid = fork()) == -1) {
goto err_pipe;
}
if (ctx->pid == 0) {
// In child
if (flags & FILE_MODE_WRITE) {
if (dup2(fds[0], STDIN_FILENO) < 0) {
_exit(-1);
}
} else {
if (dup2(fds[1], STDOUT_FILENO) < 0) {
_exit(-1);
}
}
close(fds[0]);
close(fds[1]);
_exit(execl("/bin/sh", "sh", "-c", command, NULL));
}
if (flags & FILE_MODE_WRITE) {
close(fds[0]);
ctx->fd = fds[1];
fp->flags = FILE_MODE_WRITE;
} else {
close(fds[1]);
ctx->fd = fds[0];
fp->flags = FILE_MODE_READ;
}
fp->ctx = ctx;
fp->read = pipe_read;
fp->write = pipe_write;
fp->seek = pipe_seek;
fp->close = pipe_close;
return fp;
// TODO: preserve errno here
err_pipe:
close(fds[0]);
close(fds[1]);
err_file:
fclose(fp);
err_ctx:
free(ctx);
err:
return NULL;
}
+1 -1
View File
@@ -6,5 +6,5 @@ time_t time(time_t *t) {
if (gettimeofday(&now, NULL) != 0) {
return -1;
}
return t ? *t = now.tv_sec : now.tv_sec;
return t ? *t = (time_t) now.tv_sec : (time_t) now.tv_sec;
}