diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/user/app/init/init.c | 16 | ||||
-rw-r--r-- | src/user/app/login/login.c | 95 |
2 files changed, 107 insertions, 4 deletions
diff --git a/src/user/app/init/init.c b/src/user/app/init/init.c index d9dabc6..49cc085 100644 --- a/src/user/app/init/init.c +++ b/src/user/app/init/init.c @@ -47,6 +47,18 @@ int main(void) { NULL }); } + MOUNT_AT("/Users/") { + MOUNT_AT("/tmp/") { + const char *argv[] = {"/bin/tmpfs", NULL}; + execv(argv[0], (void*)argv); + } + // TODO a simple union isn't enough here + fs_union((const char*[]){ + "/tmp/", + "/init/Users/", + NULL + }); + } MOUNT_AT("/tmp/") { const char *argv[] = {"/bin/tmpfs", NULL}; execv(argv[0], (void*)argv); @@ -55,10 +67,6 @@ int main(void) { const char *argv[] = {"/bin/vterm", NULL}; execv(argv[0], (void*)argv); } - MOUNT_AT("/union/") { - const char *list[] = {"/tmp/", "/init/", NULL}; - fs_union(list); - } if (_syscall_pipe(killswitch_pipe, 0) < 0) { printf("couldn't create the killswitch pipe, quitting...\n"); diff --git a/src/user/app/login/login.c b/src/user/app/login/login.c new file mode 100644 index 0000000..c1fab3f --- /dev/null +++ b/src/user/app/login/login.c @@ -0,0 +1,95 @@ +#include <camellia/flags.h> +#include <camellia/syscalls.h> +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <user/lib/fs/misc.h> + +static const char *shell = "/bin/shell"; + +static void cutspace(char *s) { + for (; *s; s++) { + if (isspace(*s)) { + *s = '\0'; + break; + } + } +} + +static bool accesscheck(const char *path) { + const char *prefix = "/Users/"; + if (strlen(path) < strlen(prefix) || memcmp(path, prefix, strlen(prefix))) + return true; /* not an user dir - access allowed */ + path += strlen(prefix); + + /* skip username */ + path = strchr(path, '/'); + if (!path) return true; + path++; + + /* inside an user dir */ + const char *private = "private/"; + return strlen(path) < strlen(private) || memcmp(path, private, strlen(private)); +} + +static void drv(const char *prefix) { + struct fs_wait_response res; + size_t prefixlen = strlen(prefix); + char buf[128]; + while (!_syscall_fs_wait(buf, sizeof buf, &res)) { + switch (res.op) { + handle_t h; + case VFSOP_OPEN: + if (res.len == sizeof buf) { + _syscall_fs_respond(NULL, -1, 0); + break; + } + buf[res.len] = '\0'; + + if (res.len >= prefixlen && !memcmp(prefix, buf, prefixlen)) { + h = _syscall_open(buf, res.len, res.flags); + } else if (accesscheck(buf)) { + h = _syscall_open(buf, res.len, res.flags | OPEN_RO); + } else { + h = -EACCES; + } + _syscall_fs_respond(NULL, h, FSR_DELEGATE); + break; + + default: + _syscall_fs_respond(NULL, -1, 0); + break; + } + } +} + +static void trylogin(const char *user) { + if (strcmp(user, "root")) { + char buf[128]; + snprintf(buf, sizeof buf, "/Users/%s/", user); + if (chdir(buf) < 0) { + printf("no such user: %s\n", user); + return; + } + MOUNT_AT("/") { drv(buf); } + } + + execv(shell, NULL); + fprintf(stderr, "login: couldn't launch %s\n", shell); + exit(1); +} + +int main(void) { + char user[64]; + printf("\nCamellia\n"); + for (;;) { + printf("login: "); + fgets(user, sizeof user, stdin); + if (ferror(stdin)) return -1; + + cutspace(user); + if (user[0]) trylogin(user); + } +} |