summaryrefslogtreecommitdiff
path: root/src/libc
diff options
context:
space:
mode:
authordzwdz2023-08-27 02:06:32 +0200
committerdzwdz2023-08-27 02:06:32 +0200
commite43939bcc6123e02314aa403eef94d5ace441f7f (patch)
treeac0cea10e8708ae1a6a7a400257c4bc59175a91f /src/libc
parent1f938c20b4a82ca1267ab9a1ec0922878a21ca6b (diff)
ports: qbe, cproc :^)
Diffstat (limited to 'src/libc')
-rw-r--r--src/libc/ctype.c4
-rw-r--r--src/libc/elfload.c25
-rw-r--r--src/libc/include/ctype.h1
-rw-r--r--src/libc/include/inttypes.h3
-rw-r--r--src/libc/include/spawn.h21
-rw-r--r--src/libc/include/stdio.h4
-rw-r--r--src/libc/include/string.h1
-rw-r--r--src/libc/include/sys/wait.h2
-rw-r--r--src/libc/include/unistd.h1
-rw-r--r--src/libc/spawn.c82
-rw-r--r--src/libc/stdio/file.c2
-rw-r--r--src/libc/string/string.c6
-rw-r--r--src/libc/syswait.c11
-rw-r--r--src/libc/unistd.c30
-rw-r--r--src/libc/vendor/sortix/fscanf.c30
-rw-r--r--src/libc/vendor/sortix/vfscanf.c43
16 files changed, 248 insertions, 18 deletions
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);
+}