dualinit.c (3341B)
1 #include "common.h" 2 #include "config.h" 3 #include "console.h" 4 #include "default.h" 5 6 #include <dirent.h> 7 #include <errno.h> 8 #include <fcntl.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <sys/mount.h> 13 #include <unistd.h> 14 15 // mounts `mnt` relative to `root` 16 static void mount_chroot(const char* root, const mount_t* mnt) { 17 static char dest[100]; 18 strcpy(dest, root); 19 strcat(dest, mnt->target); 20 21 INFO("mounting %s -> %s", mnt->source, dest); 22 if (mnt->type != NULL) 23 printf(" (%s)", mnt->type); 24 if (mnt->options != NULL) 25 printf(" [%s]", mnt->options); 26 27 printf("\n"); 28 29 if (mount(mnt->source, dest, mnt->type, mnt->flags, mnt->options) != 0) { 30 if (mnt->try) { 31 WARN("mounting %s to %s failed: %s\n", mnt->source, dest, strerror(errno)); 32 } else { 33 PANIC("mounting %s to %s failed: %s\n", mnt->source, dest, strerror(errno)); 34 } 35 } 36 } 37 38 int main() { 39 if (getpid() != 1) { 40 PANIC("must run as PID 1\n"); 41 } 42 43 // initiates the console as it's not initiated if init-system 44 init_console(); 45 46 // opens the config file (`fopen` is not working yet) 47 int config_file = open(DEFAULT_CONFIG, O_RDONLY | O_NONBLOCK); 48 if (config_file == -1) { 49 // if it can't be opened, die! 50 PANIC("cannot open %s: %s\n", DEFAULT_CONFIG, strerror(errno)); 51 } 52 53 // parse the config 54 parse_error_t parse_code = config_parse(config_file, DEFAULT_CONFIG); 55 if (parse_code != 0) { 56 // if config can't be parse, die! (again lol) 57 PANIC("invalid config"); 58 } 59 // and close the file as it's not needed anymore 60 close(config_file); 61 62 int section_index; 63 while (1) { 64 // politely asking for which init you want to load 65 printf("which init do you want to start?\n"); 66 // listing the sections 67 for (int i = 0; i < section_size; i++) { 68 printf("[%d] %s at %s\n", i, sections[i].name, sections[i].root); 69 } 70 71 printf(": "); 72 fflush(stdout); 73 74 scanf("%d", §ion_index); 75 if (section_index >= 0 && section_index < section_size) 76 break; 77 78 // mmph, you didn't enter a valid number 79 WARN("your choice %d must be lower than %d\n\n", section_index, section_size); 80 } 81 82 section_t* section = §ions[section_index]; 83 bool is_root = strcmp(section->root, "/") == 0; 84 85 // if the section is not `/` (as it should be), mount everything 86 if (!is_root) { 87 mount_t self_mount = { 88 .type = NULL, 89 .source = section->root, 90 .target = "/", 91 .options = NULL, 92 .flags = MS_BIND, 93 .try = false, 94 }; 95 96 mount_chroot(section->root, &self_mount); 97 98 for (int i = 0; i < mount_size; i++) { 99 mount_chroot(section->root, &mounts[i]); 100 } 101 } 102 103 for (int i = 0; i < section->mount_size; i++) { 104 mount_chroot(section->root, §ion->mounts[i]); 105 } 106 107 if (!is_root) { 108 // if it's not '/', chroot into it 109 INFO("chrooting into %s\n", section->root); 110 111 if (chroot(section->root) == -1) { 112 PANIC("cannot chroot into %s: %s\n", section->root, strerror(errno)); 113 } 114 } 115 116 // chdir '/', otherwise the init-system will have funny errors 117 if (chdir("/") == -1) { 118 PANIC("error: cannot chdir into '/': %s\n", strerror(errno)); 119 } 120 121 // aaand finally entering `init` 122 char init[PATH_MAX] = DEFAULT_INIT; 123 if (section->init != NULL) 124 strcpy(init, section->init); 125 126 config_cleanup(); 127 128 INFO("entering %s\n\n", init); 129 130 execlp(section->init, section->init, NULL); 131 132 PANIC("error: cannot execute %s: %s\n", section->init, strerror(errno)); 133 }