diff options
Diffstat (limited to 'src/libc/unistd')
-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 |
3 files changed, 308 insertions, 0 deletions
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"); +} |