diff options
author | dzwdz | 2023-08-27 02:06:32 +0200 |
---|---|---|
committer | dzwdz | 2023-08-27 02:06:32 +0200 |
commit | e43939bcc6123e02314aa403eef94d5ace441f7f (patch) | |
tree | ac0cea10e8708ae1a6a7a400257c4bc59175a91f /src | |
parent | 1f938c20b4a82ca1267ab9a1ec0922878a21ca6b (diff) |
ports: qbe, cproc :^)
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/pipe.c | 3 | ||||
-rw-r--r-- | src/kernel/proc.c | 6 | ||||
-rw-r--r-- | src/kernel/proc.h | 1 | ||||
-rw-r--r-- | src/kernel/syscalls.c | 5 | ||||
-rw-r--r-- | src/libc/ctype.c | 4 | ||||
-rw-r--r-- | src/libc/elfload.c | 25 | ||||
-rw-r--r-- | src/libc/include/ctype.h | 1 | ||||
-rw-r--r-- | src/libc/include/inttypes.h | 3 | ||||
-rw-r--r-- | src/libc/include/spawn.h | 21 | ||||
-rw-r--r-- | src/libc/include/stdio.h | 4 | ||||
-rw-r--r-- | src/libc/include/string.h | 1 | ||||
-rw-r--r-- | src/libc/include/sys/wait.h | 2 | ||||
-rw-r--r-- | src/libc/include/unistd.h | 1 | ||||
-rw-r--r-- | src/libc/spawn.c | 82 | ||||
-rw-r--r-- | src/libc/stdio/file.c | 2 | ||||
-rw-r--r-- | src/libc/string/string.c | 6 | ||||
-rw-r--r-- | src/libc/syswait.c | 11 | ||||
-rw-r--r-- | src/libc/unistd.c | 30 | ||||
-rw-r--r-- | src/libc/vendor/sortix/fscanf.c | 30 | ||||
-rw-r--r-- | src/libc/vendor/sortix/vfscanf.c | 43 | ||||
-rw-r--r-- | src/libk/printf.c | 32 |
21 files changed, 283 insertions, 30 deletions
diff --git a/src/kernel/pipe.c b/src/kernel/pipe.c index 6325369..b7f5ad3 100644 --- a/src/kernel/pipe.c +++ b/src/kernel/pipe.c @@ -1,3 +1,4 @@ +#include <camellia/errno.h> #include <kernel/panic.h> #include <kernel/pipe.h> #include <kernel/util.h> @@ -8,7 +9,7 @@ void pipe_joinqueue(Handle *h, Proc *proc, void __user *pbuf, size_t pbuflen) { assert(h && h->type == HANDLE_PIPE); assert(h->readable ^ h->writeable); if (!h->pipe.sister) { - regs_savereturn(&proc->regs, -1); + regs_savereturn(&proc->regs, h->readable ? 0 : -EPIPE); return; } diff --git a/src/kernel/proc.c b/src/kernel/proc.c index 3ef35c0..cd9db9b 100644 --- a/src/kernel/proc.c +++ b/src/kernel/proc.c @@ -349,10 +349,14 @@ void proc_tryreap(Proc *dead) { if (parent->state != PS_WAITS4CHILDDEATH) { return; /* don't reap yet */ } + uint32_t pid = proc_ns_id(parent->pns, dead); + if (parent->awaited_death.pid && parent->awaited_death.pid != pid) { + return; /* we're not The One */ + } if (parent->awaited_death.legacy) { regs_savereturn(&parent->regs, dead->death_msg); } else { - regs_savereturn(&parent->regs, proc_ns_id(parent->pns, dead)); + regs_savereturn(&parent->regs, pid); if (parent->awaited_death.out) { struct sys_wait2 __user *out = parent->awaited_death.out; struct sys_wait2 data; diff --git a/src/kernel/proc.h b/src/kernel/proc.h index a1820dc..afa4439 100644 --- a/src/kernel/proc.h +++ b/src/kernel/proc.h @@ -46,6 +46,7 @@ struct Proc { int death_msg; // PS_DEAD struct { bool legacy; /* false = wait2, true = await */ + uint32_t pid; /* valid if nonzero */ struct sys_wait2 __user *out; } awaited_death; struct { diff --git a/src/kernel/syscalls.c b/src/kernel/syscalls.c index ebdf64e..a8b47ae 100644 --- a/src/kernel/syscalls.c +++ b/src/kernel/syscalls.c @@ -26,6 +26,7 @@ long _sys_await(void) { bool has_children = false; proc_setstate(proc_cur, PS_WAITS4CHILDDEATH); proc_cur->awaited_death.legacy = true; + proc_cur->awaited_death.pid = 0; for (Proc *iter = proc_cur->child; iter; iter = iter->sibling) @@ -403,7 +404,7 @@ uint32_t _sys_getppid(void) { } int _sys_wait2(int pid, int flags, struct sys_wait2 __user *out) { - if (pid != -1 || flags != 0) { + if (flags != 0) { SYSCALL_RETURN(-ENOSYS); } @@ -411,13 +412,13 @@ int _sys_wait2(int pid, int flags, struct sys_wait2 __user *out) { proc_setstate(proc_cur, PS_WAITS4CHILDDEATH); proc_cur->awaited_death.legacy = false; proc_cur->awaited_death.out = out; + proc_cur->awaited_death.pid = (0 < pid) ? pid : 0; for (Proc *iter = proc_cur->child; iter; iter = iter->sibling) { if (iter->noreap) continue; has_children = true; if (iter->state == PS_TOREAP) { proc_tryreap(iter); - return 0; // dummy } } 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 <stdint.h> #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 <sys/types.h> + +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 <bits/file.h> #include <stdarg.h> #include <stddef.h> @@ -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 <camellia/syscalls.h> +#include <errno.h> +#include <spawn.h> +#include <stdlib.h> +#include <unistd.h> + +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 <stdarg.h> +#include <stdio.h> + +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 <errno.h> +#include <stdio.h> + +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); +} diff --git a/src/libk/printf.c b/src/libk/printf.c index fffd801..cbf89df 100644 --- a/src/libk/printf.c +++ b/src/libk/printf.c @@ -96,6 +96,22 @@ static void output_uint16(struct out_state *os, struct mods *m, unsigned long lo } } +static void output_octal(struct out_state *os, struct mods *m, unsigned long long n) { + char buf[sizeof(unsigned long long) * 3]; + size_t pos = sizeof(buf); + + if (!n) { + buf[--pos] = '0'; + } else while (n) { + unsigned long long q = n / 8, r = n % 8; + buf[--pos] = r + '0'; + n = q; + } + size_t len = sizeof(buf) - pos; + padnum(os, m, len, '\0'); + output(os, buf + pos, len); +} + int __printf_internal(const char *fmt, va_list argp, void (*back)(void*, const char*, size_t), void *backarg) @@ -170,6 +186,10 @@ int __printf_internal(const char *fmt, va_list argp, lm = LM_size; c = *fmt++; break; + case 'j': + lm = LM_longlong; + c = *fmt++; + break; default: lm = LM_int; break; @@ -201,19 +221,15 @@ int __printf_internal(const char *fmt, va_list argp, break; case 'x': - if (lm == LM_int) n = va_arg(argp, unsigned int); - else if (lm == LM_long) n = va_arg(argp, unsigned long); - else if (lm == LM_longlong) n = va_arg(argp, unsigned long long); - else if (lm == LM_size) n = va_arg(argp, size_t); - output_uint16(&os, &m, n); - break; - case 'u': + case 'o': if (lm == LM_int) n = va_arg(argp, unsigned int); else if (lm == LM_long) n = va_arg(argp, unsigned long); else if (lm == LM_longlong) n = va_arg(argp, unsigned long long); else if (lm == LM_size) n = va_arg(argp, size_t); - output_uint(&os, &m, n, '\0'); + if (c == 'x') output_uint16(&os, &m, n); + if (c == 'u') output_uint(&os, &m, n, '\0'); + if (c == 'o') output_octal(&os, &m, n); break; case 'd': |