diff options
author | dzwdz | 2022-07-27 21:44:31 +0200 |
---|---|---|
committer | dzwdz | 2022-07-27 21:44:31 +0200 |
commit | 473cc957826064840bce7a5c5ff97614e0c6cb9e (patch) | |
tree | 70699f03cb4e28b0d7fd701e82455c25f78b1932 /src | |
parent | c8998127732765aabba020ece5e42befc6f1e305 (diff) |
user/exec: shebang support
Diffstat (limited to 'src')
-rw-r--r-- | src/user/lib/elfload.c | 1 | ||||
-rw-r--r-- | src/user/lib/stdlib.c | 25 |
2 files changed, 21 insertions, 5 deletions
diff --git a/src/user/lib/elfload.c b/src/user/lib/elfload.c index 6cf09c7..71714ab 100644 --- a/src/user/lib/elfload.c +++ b/src/user/lib/elfload.c @@ -12,7 +12,6 @@ void elf_execf(FILE *f, char **argv, char **envp) { const size_t cap = 0x60000; size_t pos = 0; void *buf = malloc(cap); // TODO a way to get file size - fseek(f, 0, SEEK_SET); if (buf && fread(buf, 1, cap - pos, f)) elf_exec(buf, argv, envp); diff --git a/src/user/lib/stdlib.c b/src/user/lib/stdlib.c index 0795d3d..11ca7b6 100644 --- a/src/user/lib/stdlib.c +++ b/src/user/lib/stdlib.c @@ -1,6 +1,7 @@ #include <camellia/syscalls.h> #include <errno.h> #include <stdio.h> +#include <string.h> #include <unistd.h> #include <user/lib/elfload.h> @@ -19,14 +20,30 @@ _Noreturn void exit(int c) { } int execv(const char *path, char *const argv[]) { - (void)argv; - FILE *file = fopen(path, "r"); + char hdr[4] = {0}; if (!file) return -1; - elf_execf(file, (void*)argv, NULL); - fclose(file); + fread(hdr, 1, 4, file); + fseek(file, 0, SEEK_SET); + + if (!memcmp("\x7f""ELF", hdr, 4)) { + elf_execf(file, (void*)argv, NULL); + fclose(file); + } else if (!memcmp("#!", hdr, 2)) { + char buf[256]; + fseek(file, 2, SEEK_SET); + if (fgets(buf, sizeof buf, file)) { + const char *argv [] = {buf, path, NULL}; + // TODO strchr + char *s = buf; + while (*s && *s != '\n') s++; + *s = '\0'; + execv(argv[0], (void*)argv); + } + } + errno = EINVAL; return -1; } |