summaryrefslogtreecommitdiff
path: root/src/user/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/app')
-rw-r--r--src/user/app/init/init.c16
-rw-r--r--src/user/app/login/login.c95
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);
+ }
+}