From e43939bcc6123e02314aa403eef94d5ace441f7f Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sun, 27 Aug 2023 02:06:32 +0200 Subject: ports: qbe, cproc :^) --- src/libc/ctype.c | 4 ++ src/libc/elfload.c | 25 ++++++------ src/libc/include/ctype.h | 1 + src/libc/include/inttypes.h | 3 ++ src/libc/include/spawn.h | 21 ++++++++++ src/libc/include/stdio.h | 4 ++ src/libc/include/string.h | 1 + src/libc/include/sys/wait.h | 2 + src/libc/include/unistd.h | 1 + src/libc/spawn.c | 82 ++++++++++++++++++++++++++++++++++++++++ src/libc/stdio/file.c | 2 +- src/libc/string/string.c | 6 +++ src/libc/syswait.c | 11 +++++- src/libc/unistd.c | 30 +++++++++++++-- src/libc/vendor/sortix/fscanf.c | 30 +++++++++++++++ src/libc/vendor/sortix/vfscanf.c | 43 +++++++++++++++++++++ 16 files changed, 248 insertions(+), 18 deletions(-) create mode 100644 src/libc/include/spawn.h create mode 100644 src/libc/spawn.c create mode 100644 src/libc/vendor/sortix/fscanf.c create mode 100644 src/libc/vendor/sortix/vfscanf.c (limited to 'src/libc') diff --git a/src/libc/ctype.c b/src/libc/ctype.c index fa49a07..de10024 100644 --- a/src/libc/ctype.c +++ b/src/libc/ctype.c @@ -8,6 +8,10 @@ int isalpha(int c) { return islower(c) || isupper(c); } +int isblank(int c) { + return c == ' ' || c == '\t'; +} + int iscntrl(int c) { return c <= 0x1f || c == 0x7f; } diff --git a/src/libc/elfload.c b/src/libc/elfload.c index 66144bb..0038f9b 100644 --- a/src/libc/elfload.c +++ b/src/libc/elfload.c @@ -42,19 +42,22 @@ static bool valid_ehdr(const struct Elf64_Ehdr *h) { static bool load_phdr(const void *elf, void *exebase, size_t idx) { const struct Elf64_Ehdr *ehdr = elf; const struct Elf64_Phdr *phdr = elf + ehdr->e_phoff + idx * ehdr->e_phentsize; - - if (phdr->p_type == PT_DYNAMIC) return true; - - if (phdr->p_type != PT_LOAD) { - printf("unknown type %x\n", phdr->p_type); + + switch (phdr->p_type) { + case PT_DYNAMIC: + case 0x6474e551: /* GNU_STACK */ + return true; + case PT_LOAD: + // TODO overlap check + // TODO don't ignore flags + _sys_memflag(exebase + phdr->p_vaddr, phdr->p_memsz, MEMFLAG_PRESENT); + // TODO check that filesz <= memsz + memcpy(exebase + phdr->p_vaddr, elf + phdr->p_offset, phdr->p_filesz); + return true; + default: + printf("unknown elf phdr %x\n", phdr->p_type); return false; } - // TODO overlap check - // TODO don't ignore flags - _sys_memflag(exebase + phdr->p_vaddr, phdr->p_memsz, MEMFLAG_PRESENT); - // TODO check that filesz <= memsz - memcpy(exebase + phdr->p_vaddr, elf + phdr->p_offset, phdr->p_filesz); - return true; } static size_t elf_spread(const void *elf) { diff --git a/src/libc/include/ctype.h b/src/libc/include/ctype.h index 1ebb111..f33b645 100644 --- a/src/libc/include/ctype.h +++ b/src/libc/include/ctype.h @@ -2,6 +2,7 @@ int isalnum(int c); int isalpha(int c); +int isblank(int c); int iscntrl(int c); int isdigit(int c); int isgraph(int c); diff --git a/src/libc/include/inttypes.h b/src/libc/include/inttypes.h index d44129a..2890655 100644 --- a/src/libc/include/inttypes.h +++ b/src/libc/include/inttypes.h @@ -1,6 +1,7 @@ #include #define PRId64 "ld" +#define PRIi64 "li" #define PRIo64 "lo" #define PRIu64 "lu" #define PRIx64 "lx" @@ -9,11 +10,13 @@ #define PRId32 "d" #define PRIo32 "o" #define PRIu32 "u" +#define PRIuLEAST32 "u" #define PRIx32 "x" #define SCNu32 "u" #define PRId16 "d" #define PRIo16 "o" #define PRIu16 "u" +#define PRIuLEAST16 "u" #define PRIx16 "x" #define SCNu16 "u" diff --git a/src/libc/include/spawn.h b/src/libc/include/spawn.h new file mode 100644 index 0000000..936518a --- /dev/null +++ b/src/libc/include/spawn.h @@ -0,0 +1,21 @@ +#pragma once +#include + +typedef struct { + struct file_action *f; +} posix_spawn_file_actions_t; + +typedef struct {} posix_spawnattr_t; + +int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *facts, int from, int to); +int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *facts); +int posix_spawn_file_actions_init(posix_spawn_file_actions_t *facts); + +int posix_spawnp( + pid_t *restrict pid, + const char *restrict file, + const posix_spawn_file_actions_t *restrict file_actions, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict] +); diff --git a/src/libc/include/stdio.h b/src/libc/include/stdio.h index c579df5..b582e8f 100644 --- a/src/libc/include/stdio.h +++ b/src/libc/include/stdio.h @@ -1,4 +1,5 @@ #pragma once + #include #include #include @@ -27,6 +28,7 @@ int printf(const char *restrict fmt, ...); int fprintf(FILE *restrict f, const char *restrict fmt, ...); int sprintf(char *restrict s, const char *restrict fmt, ...); +int snprintf(char *restrict str, size_t len, const char *restrict fmt, ...); int vprintf(const char *restrict fmt, va_list ap); int vsprintf(char *restrict s, const char *restrict fmt, va_list ap); @@ -86,4 +88,6 @@ char *tmpnam(char *s); int sscanf(const char *restrict s, const char *restrict format, ...); int vsscanf(const char* str, const char* format, va_list ap); +int fscanf(FILE* fp, const char* format, ...); +int vfscanf(FILE* fp, const char* format, va_list ap); int vcbscanf(void* fp, int (*fgetc)(void*), int (*ungetc)(int, void*), const char* restrict format, va_list ap); diff --git a/src/libc/include/string.h b/src/libc/include/string.h index 8b04b39..0bf4082 100644 --- a/src/libc/include/string.h +++ b/src/libc/include/string.h @@ -27,3 +27,4 @@ char *strdup(const char *s); size_t strnlen(const char *s, size_t len); char *strerror(int errnum); +char *strsignal(int sig); diff --git a/src/libc/include/sys/wait.h b/src/libc/include/sys/wait.h index 5f0d2cc..cc8b9a8 100644 --- a/src/libc/include/sys/wait.h +++ b/src/libc/include/sys/wait.h @@ -4,6 +4,7 @@ #define WIFSTOPPED(x) 0 #define WEXITSTATUS(x) ((x)&0xFF) #define WIFEXITED(x) 1 +#define WIFSIGNALED(x) 0 #define WSTOPSIG(x) 0 #define WTERMSIG(x) 0 @@ -12,3 +13,4 @@ pid_t wait(int *wstatus); pid_t wait3(int *wstatus, int opts, struct rusage *rusage); +pid_t waitpid(pid_t pid, int *wstatus, int opts); diff --git a/src/libc/include/unistd.h b/src/libc/include/unistd.h index ac5afc0..750d6e2 100644 --- a/src/libc/include/unistd.h +++ b/src/libc/include/unistd.h @@ -22,6 +22,7 @@ int isatty(int fd); int execv(const char *path, char *const argv[]); int execvp(const char *path, char *const argv[]); +int execvpe(const char *path, char *const argv[], char *const envp[]); int execve(const char *path, char *const argv[], char *const envp[]); int chdir(const char *path); diff --git a/src/libc/spawn.c b/src/libc/spawn.c new file mode 100644 index 0000000..c10b428 --- /dev/null +++ b/src/libc/spawn.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include + +enum act { + ACT_DUP2 = 1, +}; + +struct file_action { + struct file_action *next; + enum act type; + int a, b; +}; + +int +posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *facts, int from, int to) +{ + struct file_action *fact, **tail; + fact = calloc(1, sizeof(*fact)); + if (!fact) return ENOMEM; + + fact->type = ACT_DUP2; + fact->a = from; + fact->b = to; + + tail = &facts->f; + while (*tail) { + tail = &(*tail)->next; + } + *tail = fact; + return 0; +} + +int +posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *facts) +{ + while (facts->f) { + struct file_action *cur = facts->f; + facts->f = cur->next; + free(cur); + } + return 0; +} + +int +posix_spawn_file_actions_init(posix_spawn_file_actions_t *facts) +{ + facts->f = NULL; + return 0; +} + +int +posix_spawnp( + pid_t *restrict pidp, + const char *restrict file, + const posix_spawn_file_actions_t *restrict facts, + const posix_spawnattr_t *restrict attrp, + char *const argv[restrict], + char *const envp[restrict] +) { + if (attrp) return ENOSYS; + + pid_t pid = fork(); + if (pid < 0) return errno; + if (pid == 0) { + struct file_action *fact = facts ? facts->f : NULL; + while (fact) { + switch (fact->type) { + case ACT_DUP2: + dup2(fact->a, fact->b); + break; + } + fact = fact->next; + } + execvpe(file, argv, envp); + _sys_exit(127); + } + if (pidp) *pidp = pid; + return 0; +} diff --git a/src/libc/stdio/file.c b/src/libc/stdio/file.c index de88a9f..30a578e 100644 --- a/src/libc/stdio/file.c +++ b/src/libc/stdio/file.c @@ -248,7 +248,7 @@ size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restri } int fputs(const char *s, FILE *f) { - return fprintf(f, "%s\n", s); + return fprintf(f, "%s", s); } char *fgets(char *buf, int size, FILE *f) { diff --git a/src/libc/string/string.c b/src/libc/string/string.c index 014be4a..748b0b5 100644 --- a/src/libc/string/string.c +++ b/src/libc/string/string.c @@ -124,6 +124,12 @@ size_t strnlen(const char *s, size_t len) { return len; } +char *strsignal(int sig) { + static char buf[32]; + snprintf(buf, sizeof(buf), "signal %d", sig); + return buf; +} + /* strings.h */ int strcasecmp(const char *s1, const char *s2) { return strncasecmp(s1, s2, ~0); diff --git a/src/libc/syswait.c b/src/libc/syswait.c index 43c20ae..d7da2e0 100644 --- a/src/libc/syswait.c +++ b/src/libc/syswait.c @@ -10,11 +10,18 @@ pid_t wait(int *wstatus) { } pid_t wait3(int *wstatus, int opts, struct rusage *rusage) { + if (rusage) { + __libc_panic("unimplemented"); + } + return waitpid(-1, wstatus, opts); +} + +pid_t waitpid(pid_t pid, int *wstatus, int opts) { struct sys_wait2 res; - if (opts || rusage) { + if (opts) { __libc_panic("unimplemented"); } - pid_t ret = _sys_wait2(-1, 0, &res); + pid_t ret = _sys_wait2(pid, 0, &res); if (ret < 0) { errno = -ret; return -1; diff --git a/src/libc/unistd.c b/src/libc/unistd.c index 549da89..e87cdb9 100644 --- a/src/libc/unistd.c +++ b/src/libc/unistd.c @@ -77,6 +77,19 @@ int execvp(const char *path, char *const argv[]) { return execve(path, argv, NULL); } +int execvpe(const char *path, char *const argv[], char *const envp[]) { + if (path[0] != '/') { + char *exp = malloc(strlen(path) + 6); + int ret; + strcpy(exp, "/bin/"); + strcat(exp, path); + ret = execve(exp, argv, envp); + free(exp); + return ret; + } + return execve(path, argv, envp); +} + int execve(const char *path, char *const argv[], char *const envp[]) { FILE *file = fopen(path, "e"); char hdr[4] = {0}; @@ -225,8 +238,13 @@ ssize_t write(int fd, const void *buf, size_t count) { } int pipe(int pipefd[2]) { - (void)pipefd; - __libc_panic("unimplemented"); + // TODO pipe buffering + int ret = _sys_pipe(pipefd, 0); + if (ret < 0) { + errno = -ret; + return -1; + } + return 0; } int dup(int oldfd) { @@ -235,8 +253,12 @@ int dup(int oldfd) { } int dup2(int oldfd, int newfd) { - (void)oldfd; (void)newfd; - __libc_panic("unimplemented"); + int ret = _sys_dup(oldfd, newfd, 0); + if (ret < 0) { + errno = -ret; + ret = -1; + } + return ret; } unsigned int sleep(unsigned int seconds) { diff --git a/src/libc/vendor/sortix/fscanf.c b/src/libc/vendor/sortix/fscanf.c new file mode 100644 index 0000000..93d300a --- /dev/null +++ b/src/libc/vendor/sortix/fscanf.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012, 2013 Jonas 'Sortie' Termansen. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * stdio/fscanf.c + * Input format conversion. + */ + +#include +#include + +int fscanf(FILE* fp, const char* format, ...) +{ + va_list ap; + va_start(ap, format); + int ret = vfscanf(fp, format, ap); + va_end(ap); + return ret; +} diff --git a/src/libc/vendor/sortix/vfscanf.c b/src/libc/vendor/sortix/vfscanf.c new file mode 100644 index 0000000..44efc38 --- /dev/null +++ b/src/libc/vendor/sortix/vfscanf.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012, 2013, 2014 Jonas 'Sortie' Termansen. + * Modified by dzwdz. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * stdio/vfscanf.c + * Input format conversion. + * + * stdio/vfscanf_unlocked.c + * Input format conversion. + */ + +#include +#include + +static int wrap_fgetc(void* fp) +{ + return fgetc((FILE*) fp); +} + +static int wrap_ungetc(int c, void* fp) +{ + return ungetc(c, (FILE*) fp); +} + +int vfscanf(FILE* fp, const char* format, va_list ap) +{ + // if ( !(fp->flags & _FILE_READABLE) ) + // return errno = EBADF, fp->flags |= _FILE_STATUS_ERROR, EOF; + + return vcbscanf(fp, wrap_fgetc, wrap_ungetc, format, ap); +} -- cgit v1.2.3