diff options
author | dzwdz | 2023-09-03 01:30:53 +0200 |
---|---|---|
committer | dzwdz | 2023-09-03 01:30:53 +0200 |
commit | a492c6ec119bd1151a6f2f7b70875ba173e9c036 (patch) | |
tree | a96f9d4ff4b120ecd58f8f41ab26b5a28fd368c0 | |
parent | fd80c0b227336f4650d6b54d82469feb017aeded (diff) |
libc: split up large .c files, slimming down small binaries a bit
-rw-r--r-- | src/cmd/true/true.c | 3 | ||||
-rw-r--r-- | src/libc/_start2.c | 2 | ||||
-rw-r--r-- | src/libc/include/camellia/intr.h | 4 | ||||
-rw-r--r-- | src/libc/include/unistd.h | 8 | ||||
-rw-r--r-- | src/libc/intr.c | 13 | ||||
-rw-r--r-- | src/libc/stdio/fprintf.c (renamed from src/libc/printf.c) | 40 | ||||
-rw-r--r-- | src/libc/stdio/sprintf.c | 28 | ||||
-rw-r--r-- | src/libc/stdlib/progname.c | 28 | ||||
-rw-r--r-- | src/libc/stdlib/stdlib.c (renamed from src/libc/stdlib.c) | 24 | ||||
-rw-r--r-- | src/libc/string/basic.c | 105 | ||||
-rw-r--r-- | src/libc/string/string.c | 108 | ||||
-rw-r--r-- | src/libc/unistd.c | 315 | ||||
-rw-r--r-- | src/libc/unistd/cwd.c | 95 | ||||
-rw-r--r-- | src/libc/unistd/simple.c | 128 | ||||
-rw-r--r-- | src/libc/unistd/unistd.c | 85 |
15 files changed, 503 insertions, 483 deletions
diff --git a/src/cmd/true/true.c b/src/cmd/true/true.c new file mode 100644 index 0000000..061ed7e --- /dev/null +++ b/src/cmd/true/true.c @@ -0,0 +1,3 @@ +int main(void) { + return 0; +} diff --git a/src/libc/_start2.c b/src/libc/_start2.c index b4eb76a..dbc91d7 100644 --- a/src/libc/_start2.c +++ b/src/libc/_start2.c @@ -36,7 +36,7 @@ _Noreturn void _start2(struct execdata *ed) { _sys_intr_set(intr_trampoline); intr_set(intr_default); - __setinitialcwd(ed->cwd); + __initialcwd = ed->cwd; exit(main(ed->argc, ed->argv, ed->envp)); } diff --git a/src/libc/include/camellia/intr.h b/src/libc/include/camellia/intr.h new file mode 100644 index 0000000..b9390fd --- /dev/null +++ b/src/libc/include/camellia/intr.h @@ -0,0 +1,4 @@ +#pragma once + +void intr_set(void (*fn)(void)); +void intr_default(void); diff --git a/src/libc/include/unistd.h b/src/libc/include/unistd.h index 750d6e2..2158511 100644 --- a/src/libc/include/unistd.h +++ b/src/libc/include/unistd.h @@ -1,5 +1,6 @@ #pragma once #include <camellia/types.h> // TODO only needed because of hid_t +#include <camellia/intr.h> // TODO only included for backwards compat #include <sys/types.h> #include <getopt.h> @@ -64,8 +65,5 @@ unsigned int sleep(unsigned int seconds); * @return 0 on failure, length of the path otherwise */ size_t absolutepath(char *out, const char *in, size_t size); -// TODO put in an internal libc header -void __setinitialcwd(const char *c); - -void intr_set(void (*fn)(void)); -void intr_default(void); +/* used internally */ +extern const char *__initialcwd; diff --git a/src/libc/intr.c b/src/libc/intr.c new file mode 100644 index 0000000..cdefc2f --- /dev/null +++ b/src/libc/intr.c @@ -0,0 +1,13 @@ +#include <camellia/intr.h> +#include <stdlib.h> + +static void intr_null(void) { } + +extern void (*volatile _intr)(void); +void intr_set(void (*fn)(void)) { + _intr = fn ? fn : intr_null; +} + +void intr_default(void) { + exit(-1); +} diff --git a/src/libc/printf.c b/src/libc/stdio/fprintf.c index a760240..cd2851c 100644 --- a/src/libc/printf.c +++ b/src/libc/stdio/fprintf.c @@ -1,27 +1,10 @@ -#include <camellia/syscalls.h> #include <shared/printf.h> #include <stdio.h> -#include <string.h> - static void backend_file(void *arg, const char *buf, size_t len) { fwrite(buf, 1, len, arg); } -int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) { - return __printf_internal(fmt, ap, backend_file, f); -} - - -int printf(const char *restrict fmt, ...) { - int ret; - va_list argp; - va_start(argp, fmt); - ret = vprintf(fmt, argp); - va_end(argp); - return ret; -} - int fprintf(FILE *restrict f, const char *restrict fmt, ...) { int ret; va_list argp; @@ -31,11 +14,15 @@ int fprintf(FILE *restrict f, const char *restrict fmt, ...) { return ret; } -int sprintf(char *restrict s, const char *restrict fmt, ...) { +int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap) { + return __printf_internal(fmt, ap, backend_file, f); +} + +int printf(const char *restrict fmt, ...) { int ret; va_list argp; va_start(argp, fmt); - ret = vsnprintf(s, ~0, fmt, argp); + ret = vprintf(fmt, argp); va_end(argp); return ret; } @@ -43,18 +30,3 @@ int sprintf(char *restrict s, const char *restrict fmt, ...) { int vprintf(const char *restrict fmt, va_list ap) { return vfprintf(stdout, fmt, ap); } - -int vsprintf(char *restrict s, const char *restrict fmt, va_list ap) { - return vsnprintf(s, ~0, fmt, ap); -} - -int _klogf(const char *fmt, ...) { - char buf[256]; - int ret; - va_list argp; - va_start(argp, fmt); - ret = vsnprintf(buf, sizeof buf, fmt, argp); - va_end(argp); - _sys_debug_klog(buf, ret); - return ret; -} diff --git a/src/libc/stdio/sprintf.c b/src/libc/stdio/sprintf.c new file mode 100644 index 0000000..0bfbb17 --- /dev/null +++ b/src/libc/stdio/sprintf.c @@ -0,0 +1,28 @@ +#include <camellia/syscalls.h> +#include <shared/mem.h> +#include <shared/printf.h> +#include <stdio.h> + +int sprintf(char *restrict s, const char *restrict fmt, ...) { + int ret; + va_list argp; + va_start(argp, fmt); + ret = vsnprintf(s, ~0, fmt, argp); + va_end(argp); + return ret; +} + +int vsprintf(char *restrict s, const char *restrict fmt, va_list ap) { + return vsnprintf(s, ~0, fmt, ap); +} + +int _klogf(const char *fmt, ...) { + char buf[256]; + int ret; + va_list argp; + va_start(argp, fmt); + ret = vsnprintf(buf, sizeof buf, fmt, argp); + va_end(argp); + _sys_debug_klog(buf, ret); + return ret; +} diff --git a/src/libc/stdlib/progname.c b/src/libc/stdlib/progname.c new file mode 100644 index 0000000..4cc0fb2 --- /dev/null +++ b/src/libc/stdlib/progname.c @@ -0,0 +1,28 @@ +#include <_proc.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static const char *progname; +const char *getprogname(void) { + return progname; +} +void setprogname(const char *pg) { + progname = pg; + setproctitle(NULL); +} + +void setproctitle(const char *fmt, ...) { + // TODO bounds checking + if (!fmt) { + strcpy(_psdata_loc->desc, progname); + return; + } + sprintf(_psdata_loc->desc, "%s: ", progname); + + va_list argp; + va_start(argp, fmt); + vsnprintf(_psdata_loc->desc + strlen(_psdata_loc->desc), 128, fmt, argp); + va_end(argp); +} + diff --git a/src/libc/stdlib.c b/src/libc/stdlib/stdlib.c index 16c8f70..1dee760 100644 --- a/src/libc/stdlib.c +++ b/src/libc/stdlib/stdlib.c @@ -1,4 +1,3 @@ -#include <_proc.h> #include <bits/panic.h> #include <camellia.h> #include <camellia/syscalls.h> @@ -10,29 +9,6 @@ _Noreturn void abort(void) { _sys_exit(1); } -static const char *progname; -const char *getprogname(void) { - return progname; -} -void setprogname(const char *pg) { - progname = pg; - setproctitle(NULL); -} - -void setproctitle(const char *fmt, ...) { - // TODO bounds checking - if (!fmt) { - strcpy(_psdata_loc->desc, progname); - return; - } - sprintf(_psdata_loc->desc, "%s: ", progname); - - va_list argp; - va_start(argp, fmt); - vsnprintf(_psdata_loc->desc + strlen(_psdata_loc->desc), 128, fmt, argp); - va_end(argp); -} - char *mktemp(char *tmpl) { // TODO mktemp mkstemp return tmpl; diff --git a/src/libc/string/basic.c b/src/libc/string/basic.c new file mode 100644 index 0000000..902779b --- /dev/null +++ b/src/libc/string/basic.c @@ -0,0 +1,105 @@ +/** String functions that don't depend on any external functions. */ + +#include <string.h> + +char *strchr(const char *s, int c) { + for (; *s || c == 0; s++) { + if (*s == c) return (char *)s; + } + return NULL; +} + +char *strrchr(const char *s, int c) { + for (int i = strlen(s) + 1; i >= 0; i--) { + if (s[i] == c) return (char *)s + i; + } + return NULL; +} + +size_t strspn(const char *s, const char *accept) { + size_t l = 0; + for (; s[l] && strchr(accept, s[l]); l++); + return l; +} + +size_t strcspn(const char *s, const char *reject) { + size_t l = 0; + for (; s[l] && !strchr(reject, s[l]); l++); + return l; +} + +char *strpbrk(const char *s1, const char *s2) { + for (; *s1; s1++) { + if (strchr(s2, *s1)) return (char*)s1; + } + return NULL; +} + +char *strtok(char *restrict s, const char *restrict sep) { + static char *state; + return strtok_r(s, sep, &state); +} + +char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state) { + char *end; + if (!s) s = *state; + s += strspn(s, sep); /* beginning of token */ + if (!*s) return NULL; + + end = s + strcspn(s, sep); + if (*end) { + *end = '\0'; + *state = end + 1; + } else { + *state = end; + } + return s; +} + +int strncmp(const char *s1, const char *s2, size_t n) { + for (size_t i = 0; i < n; i++) { + if (s1[i] < s2[i]) return -1; + if (s1[i] > s2[i]) return 1; + } + return 0; +} + +int strcoll(const char *s1, const char *s2) { + return strcmp(s1, s2); +} + +char *strstr(const char *s1, const char *s2) { + size_t l1 = strlen(s1), l2 = strlen(s2); + for (; l2 <= l1; s1++, l1--) { + if (memcmp(s1, s2, l2) == 0) return (char*)s1; + } + return NULL; +} + +char *strcat(char *restrict dst, const char *restrict src) { + return strcpy(dst + strlen(dst), src); +} + +char *strcpy(char *restrict s1, const char *restrict s2) { + char *ret = s1; + while (*s2) *s1++ = *s2++; + *s1 = *s2; + return ret; +} + +char *strncpy(char *restrict dst, const char *restrict src, size_t n) { + for (size_t i = 0; i < n; i++) { + dst[i] = src[i]; + if (dst[i] == '\0') return dst + i; // TODO fill with null bytes + } + return dst; +} + +size_t strnlen(const char *s, size_t len) { + for (size_t i = 0; i < len; i++) { + if (!s[i]) { + return i; + } + } + return len; +} diff --git a/src/libc/string/string.c b/src/libc/string/string.c index 748b0b5..e93b0a6 100644 --- a/src/libc/string/string.c +++ b/src/libc/string/string.c @@ -1,3 +1,5 @@ +/** String functions that don't fit into any of the other .c files */ + #include <bits/panic.h> #include <ctype.h> #include <errno.h> @@ -5,107 +7,14 @@ #include <string.h> #include <strings.h> -char *strchr(const char *s, int c) { - for (; *s || c == 0; s++) { - if (*s == c) return (char *)s; - } - return NULL; -} - -char *strrchr(const char *s, int c) { - for (int i = strlen(s) + 1; i >= 0; i--) { - if (s[i] == c) return (char *)s + i; - } - return NULL; -} - -size_t strspn(const char *s, const char *accept) { - size_t l = 0; - for (; s[l] && strchr(accept, s[l]); l++); - return l; -} - -size_t strcspn(const char *s, const char *reject) { - size_t l = 0; - for (; s[l] && !strchr(reject, s[l]); l++); - return l; -} - -char *strpbrk(const char *s1, const char *s2) { - for (; *s1; s1++) { - if (strchr(s2, *s1)) return (char*)s1; - } - return NULL; -} - -char *strtok(char *restrict s, const char *restrict sep) { - static char *state; - return strtok_r(s, sep, &state); -} - -char *strtok_r(char *restrict s, const char *restrict sep, char **restrict state) { - char *end; - if (!s) s = *state; - s += strspn(s, sep); /* beginning of token */ - if (!*s) return NULL; - - end = s + strcspn(s, sep); - if (*end) { - *end = '\0'; - *state = end + 1; - } else { - *state = end; - } - return s; -} - -int strncmp(const char *s1, const char *s2, size_t n) { - for (size_t i = 0; i < n; i++) { - if (s1[i] < s2[i]) return -1; - if (s1[i] > s2[i]) return 1; - } - return 0; -} - -int strcoll(const char *s1, const char *s2) { - return strcmp(s1, s2); -} - -// TODO implement strstr using Boyer-Moore -char *strstr(const char *s1, const char *s2) { - size_t l1 = strlen(s1), l2 = strlen(s2); - for (; l2 <= l1; s1++, l1--) { - if (memcmp(s1, s2, l2) == 0) return (char*)s1; - } - return NULL; -} - -char *strcat(char *restrict dst, const char *restrict src) { - return strcpy(dst + strlen(dst), src); -} - -char *strcpy(char *restrict s1, const char *restrict s2) { - char *ret = s1; - while (*s2) *s1++ = *s2++; - *s1 = *s2; - return ret; -} - -char *strncpy(char *restrict dst, const char *restrict src, size_t n) { - for (size_t i = 0; i < n; i++) { - dst[i] = src[i]; - if (dst[i] == '\0') return dst + i; // TODO fill with null bytes - } - return dst; -} - char *strncat(char *restrict dst, const char *restrict src, size_t n) { (void)dst; (void)src; (void)n; __libc_panic("unimplemented"); } char *stpncpy(char *restrict dst, const char *restrict src, size_t n) { - return stpncpy(dst, src, n) + n; + (void)dst; (void)src; (void)n; + __libc_panic("unimplemented"); } char *strdup(const char *s) { @@ -115,15 +24,6 @@ char *strdup(const char *s) { return buf; } -size_t strnlen(const char *s, size_t len) { - for (size_t i = 0; i < len; i++) { - if (!s[i]) { - return i; - } - } - return len; -} - char *strsignal(int sig) { static char buf[32]; snprintf(buf, sizeof(buf), "signal %d", sig); diff --git a/src/libc/unistd.c b/src/libc/unistd.c deleted file mode 100644 index e87cdb9..0000000 --- a/src/libc/unistd.c +++ /dev/null @@ -1,315 +0,0 @@ -#include <bits/panic.h> -#include <camellia.h> -#include <camellia/path.h> -#include <camellia/syscalls.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <elfload.h> - -int errno = 0; -static char *_environ[] = {NULL}; -char **environ = _environ; - -int fork(void) { - return _sys_fork(0, NULL); -} - -pid_t vfork(void) { - // TODO vfork is implemented improperly and will break stuff - return _sys_fork(0, NULL); -} - -int close(hid_t h) { - return _sys_close(h); -} - -_Noreturn void exit(int c) { - _sys_exit(c); -} -_Noreturn void _exit(int c) { exit(c); }; - -ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize) { - (void)path; (void)buf; (void)bufsize; - errno = ENOSYS; - return -1; -} - -int link(const char *path1, const char *path2) { - (void)path1; (void)path2; - errno = ENOSYS; - return -1; -} - -int unlink(const char *path) { - hid_t h = camellia_open(path, OPEN_WRITE); - if (h < 0) return errno = -h, -1; - long ret = _sys_remove(h); - if (ret < 0) return errno = -ret, -1; - return 0; -} - -int rmdir(const char *path) { - (void)path; - __libc_panic("unimplemented"); -} - -int symlink(const char *path1, const char *path2) { - (void)path1; (void)path2; - errno = ENOSYS; - return -1; -} - -// TODO isatty -int isatty(int fd) { - return fd <= 2 ? 1 : 0; -} - - -int execv(const char *path, char *const argv[]) { - return execve(path, argv, NULL); -} - -int execvp(const char *path, char *const argv[]) { - // TODO execvp - 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}; - if (!file) - return -1; - - fread(hdr, 1, 4, file); - fseek(file, 0, SEEK_SET); - - if (!memcmp("\x7f""ELF", hdr, 4)) { - elf_execf(file, (void*)argv, (void*)envp); - 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}; - char *endl = strchr(buf, '\n'); - if (endl) *endl = '\0'; - execve(buf, (void*)argv, envp); - } - } - - errno = EINVAL; - return -1; -} - - -static const char *__initialcwd; -static char *cwd = NULL, *cwd2 = NULL; -static size_t cwdcapacity = 0; - -static const char *getrealcwd(void) { - /* __initialcwd can't just be initialized with "/" because ld has seemingly - * started to revolt against humanity and not process half the relocations - * it sees. */ - if (cwd) return cwd; - if (__initialcwd) return __initialcwd; - return "/"; -} - -int chdir(const char *path) { - hid_t h; - char *tmp; - size_t len = absolutepath(NULL, path, 0) + 1; /* +1 for the trailing slash */ - if (cwdcapacity < len) { - cwdcapacity = len; - if (cwd) { - cwd = realloc(cwd, len); - cwd2 = realloc(cwd2, len); - } else { - size_t initlen = strlen(__initialcwd) + 1; - if (len < initlen) - len = initlen; - cwd = malloc(initlen); - cwd2 = malloc(initlen); - memcpy(cwd, __initialcwd, initlen); - } - } - absolutepath(cwd2, path, cwdcapacity); - len = strlen(cwd2); - if (cwd2[len - 1] != '/') { - cwd2[len] = '/'; - cwd2[len + 1] = '\0'; - } - - /* check if exists */ - h = camellia_open(cwd2, OPEN_READ); - if (h < 0) return errno = ENOENT, -1; - close(h); - - tmp = cwd; - cwd = cwd2; - cwd2 = tmp; - return 0; -} - -char *getcwd(char *buf, size_t capacity) { - const char *realcwd = getrealcwd(); - size_t len = strlen(realcwd) + 1; - if (capacity < len) { - errno = capacity == 0 ? EINVAL : ERANGE; - return NULL; - } - memcpy(buf, realcwd, len); - return buf; -} - -uid_t getuid(void) { return 0; } -uid_t geteuid(void) { return 0; } -gid_t getgid(void) { return 0; } -gid_t getegid(void) { return 0; } - -int access(const char *path, int mode) { - // TODO impl access() - (void)path; (void)mode; - return 0; -} - -int chown(const char *path, uid_t owner, gid_t group) { - (void)path; (void)owner; (void)group; - errno = ENOSYS; - return -1; -} - -int setpgid(pid_t pid, pid_t pgid) { - (void)pid; (void)pgid; - return errno = ENOSYS, -1; -} - -pid_t tcgetpgrp(int fd) { - (void)fd; - return errno = ENOSYS, -1; -} - -int tcsetpgrp(int fd, pid_t pgrp) { - (void)fd; (void)pgrp; - return errno = ENOSYS, -1; -} - -pid_t getpgrp(void) { - __libc_panic("unimplemented"); -} - -pid_t getpid(void) { - return _sys_getpid(); -} - -pid_t getppid(void) { - return _sys_getppid(); -} - -int getgroups(int size, gid_t list[]) { - (void)size; (void)list; - __libc_panic("unimplemented"); -} - -ssize_t read(int fd, void *buf, size_t count) { - // TODO real file descriptor emulation - store offsets - return _sys_read(fd, buf, count, -1); -} - -ssize_t write(int fd, const void *buf, size_t count) { - // TODO real file descriptor emulation - store offsets - return _sys_write(fd, buf, count, -1, 0); -} - -int pipe(int pipefd[2]) { - // TODO pipe buffering - int ret = _sys_pipe(pipefd, 0); - if (ret < 0) { - errno = -ret; - return -1; - } - return 0; -} - -int dup(int oldfd) { - (void)oldfd; - __libc_panic("unimplemented"); -} - -int dup2(int oldfd, int newfd) { - int ret = _sys_dup(oldfd, newfd, 0); - if (ret < 0) { - errno = -ret; - ret = -1; - } - return ret; -} - -unsigned int sleep(unsigned int seconds) { - _sys_sleep(seconds * 1000); - return 0; -} - -size_t absolutepath(char *out, const char *in, size_t size) { - const char *realcwd = getrealcwd(); - size_t len, pos = 0; - if (!in) return strlen(realcwd) + 1; - - if (!(in[0] == '/')) { - len = strlen(realcwd); - if (pos + len <= size && out != realcwd) - memcpy(out + pos, realcwd, len); - pos += len; - - if (realcwd[len - 1] != '/') { - if (pos + 1 <= size) out[pos] = '/'; - pos++; - } - } - - len = strlen(in); - if (pos + len <= size) - memcpy(out + pos, in, len); - pos += len; - - if (pos <= size) { - pos = path_simplify(out, out, pos); - if (pos == 0) return 0; - } - - if (pos + 1 <= size) out[pos] = '\0'; - pos++; - - return pos; -} - -void __setinitialcwd(const char *s) { - __initialcwd = s; -} - -static void intr_null(void) { } - -extern void (*volatile _intr)(void); -void intr_set(void (*fn)(void)) { - _intr = fn ? fn : intr_null; -} - -void intr_default(void) { - exit(-1); -} diff --git a/src/libc/unistd/cwd.c b/src/libc/unistd/cwd.c new file mode 100644 index 0000000..7689d56 --- /dev/null +++ b/src/libc/unistd/cwd.c @@ -0,0 +1,95 @@ +#include <camellia.h> +#include <camellia/path.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static char *cwd = NULL, *cwd2 = NULL; +static size_t cwdcapacity = 0; + +static const char *getrealcwd(void) { + if (cwd) return cwd; + if (__initialcwd) return __initialcwd; + return "/"; +} + +int chdir(const char *path) { + hid_t h; + char *tmp; + size_t len = absolutepath(NULL, path, 0) + 1; /* +1 for the trailing slash */ + if (cwdcapacity < len) { + cwdcapacity = len; + if (cwd) { + cwd = realloc(cwd, len); + cwd2 = realloc(cwd2, len); + } else { + size_t initlen = strlen(__initialcwd) + 1; + if (len < initlen) + len = initlen; + cwd = malloc(initlen); + cwd2 = malloc(initlen); + memcpy(cwd, __initialcwd, initlen); + } + } + absolutepath(cwd2, path, cwdcapacity); + len = strlen(cwd2); + if (cwd2[len - 1] != '/') { + cwd2[len] = '/'; + cwd2[len + 1] = '\0'; + } + + /* check if exists */ + h = camellia_open(cwd2, OPEN_READ); + if (h < 0) return errno = ENOENT, -1; + close(h); + + tmp = cwd; + cwd = cwd2; + cwd2 = tmp; + return 0; +} + +char *getcwd(char *buf, size_t capacity) { + const char *realcwd = getrealcwd(); + size_t len = strlen(realcwd) + 1; + if (capacity < len) { + errno = capacity == 0 ? EINVAL : ERANGE; + return NULL; + } + memcpy(buf, realcwd, len); + return buf; +} + +size_t absolutepath(char *out, const char *in, size_t size) { + const char *realcwd = getrealcwd(); + size_t len, pos = 0; + if (!in) return strlen(realcwd) + 1; + + if (!(in[0] == '/')) { + len = strlen(realcwd); + if (pos + len <= size && out != realcwd) + memcpy(out + pos, realcwd, len); + pos += len; + + if (realcwd[len - 1] != '/') { + if (pos + 1 <= size) out[pos] = '/'; + pos++; + } + } + + len = strlen(in); + if (pos + len <= size) + memcpy(out + pos, in, len); + pos += len; + + if (pos <= size) { + pos = path_simplify(out, out, pos); + if (pos == 0) return 0; + } + + if (pos + 1 <= size) out[pos] = '\0'; + pos++; + + return pos; +} diff --git a/src/libc/unistd/simple.c b/src/libc/unistd/simple.c new file mode 100644 index 0000000..911c974 --- /dev/null +++ b/src/libc/unistd/simple.c @@ -0,0 +1,128 @@ +/** Functions from unistd.h that are either just a syscall or a return. */ + +#include <camellia/syscalls.h> +#include <errno.h> +#include <unistd.h> + +int errno = 0; +static char *_environ[] = {NULL}; +char **environ = _environ; +const char *__initialcwd = NULL; + +int fork(void) { + return _sys_fork(0, NULL); +} + +pid_t vfork(void) { + // TODO vfork is implemented improperly and will break stuff + return _sys_fork(0, NULL); +} + +int close(hid_t h) { + return _sys_close(h); +} + +_Noreturn void exit(int c) { + _sys_exit(c); +} +_Noreturn void _exit(int c) { + exit(c); +}; + +ssize_t readlink(const char *restrict path, char *restrict buf, size_t bufsize) { + (void)path; (void)buf; (void)bufsize; + errno = ENOSYS; + return -1; +} + +int link(const char *path1, const char *path2) { + (void)path1; (void)path2; + errno = ENOSYS; + return -1; +} + +int symlink(const char *path1, const char *path2) { + (void)path1; (void)path2; + errno = ENOSYS; + return -1; +} + +// TODO isatty +int isatty(int fd) { + return fd <= 2 ? 1 : 0; +} + +uid_t getuid(void) { return 0; } +uid_t geteuid(void) { return 0; } +gid_t getgid(void) { return 0; } +gid_t getegid(void) { return 0; } + +int access(const char *path, int mode) { + // TODO impl access() + (void)path; (void)mode; + return 0; +} + +int chown(const char *path, uid_t owner, gid_t group) { + (void)path; (void)owner; (void)group; + errno = ENOSYS; + return -1; +} + +int setpgid(pid_t pid, pid_t pgid) { + (void)pid; (void)pgid; + return errno = ENOSYS, -1; +} + +pid_t tcgetpgrp(int fd) { + (void)fd; + return errno = ENOSYS, -1; +} + +int tcsetpgrp(int fd, pid_t pgrp) { + (void)fd; (void)pgrp; + return errno = ENOSYS, -1; +} + +pid_t getpid(void) { + return _sys_getpid(); +} + +pid_t getppid(void) { + return _sys_getppid(); +} + +ssize_t read(int fd, void *buf, size_t count) { + // TODO real file descriptor emulation - store offsets + // TODO errno + return _sys_read(fd, buf, count, -1); +} + +ssize_t write(int fd, const void *buf, size_t count) { + // TODO real file descriptor emulation - store offsets + return _sys_write(fd, buf, count, -1, 0); +} + +int pipe(int pipefd[2]) { + // TODO pipe buffering + int ret = _sys_pipe(pipefd, 0); + if (ret < 0) { + errno = -ret; + return -1; + } + return 0; +} + +int dup2(int oldfd, int newfd) { + int ret = _sys_dup(oldfd, newfd, 0); + if (ret < 0) { + errno = -ret; + ret = -1; + } + return ret; +} + +unsigned int sleep(unsigned int seconds) { + _sys_sleep(seconds * 1000); + return 0; +} diff --git a/src/libc/unistd/unistd.c b/src/libc/unistd/unistd.c new file mode 100644 index 0000000..102e72a --- /dev/null +++ b/src/libc/unistd/unistd.c @@ -0,0 +1,85 @@ +#include <bits/panic.h> +#include <camellia.h> +#include <camellia/syscalls.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <elfload.h> + +int unlink(const char *path) { + hid_t h = camellia_open(path, OPEN_WRITE); + if (h < 0) return errno = -h, -1; + long ret = _sys_remove(h); + if (ret < 0) return errno = -ret, -1; + return 0; +} + +int rmdir(const char *path) { + (void)path; + __libc_panic("unimplemented"); +} + +int execv(const char *path, char *const argv[]) { + return execve(path, argv, NULL); +} + +int execvp(const char *path, char *const argv[]) { + // TODO execvp + 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}; + if (!file) + return -1; + + fread(hdr, 1, 4, file); + fseek(file, 0, SEEK_SET); + + if (!memcmp("\x7f""ELF", hdr, 4)) { + elf_execf(file, (void*)argv, (void*)envp); + 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}; + char *endl = strchr(buf, '\n'); + if (endl) *endl = '\0'; + execve(buf, (void*)argv, envp); + } + } + + errno = EINVAL; + return -1; +} + +pid_t getpgrp(void) { + __libc_panic("unimplemented"); +} + +int getgroups(int size, gid_t list[]) { + (void)size; (void)list; + __libc_panic("unimplemented"); +} + +int dup(int oldfd) { + (void)oldfd; + __libc_panic("unimplemented"); +} |