modules-load.c (2968B)
1 #include "common.h" 2 3 #include <bio.h> 4 #include <dirent.h> 5 #include <fcntl.h> 6 #include <fmt.h> 7 #include <regex.h> 8 #include <stdio.h> 9 #include <stdlib.h> 10 #include <string.h> 11 #include <unistd.h> 12 13 #define MAX_CMDLINE_SIZE 4096 14 #define MAX_MODULE_SIZE 256 15 #define MAX_MODULE_COUNT 64 16 17 18 const char* current_prog(void) { 19 return "modules-load"; 20 } 21 22 static char kernel_cmdline[MAX_CMDLINE_SIZE]; 23 static char modules[MAX_MODULE_COUNT][MAX_MODULE_SIZE]; 24 static int modules_size = 0; 25 26 static void read_cmdline(void) { 27 int fd; 28 int size; 29 char *end, *match, *com; 30 31 if ((fd = open("/proc/cmdline", O_RDONLY)) == -1) 32 return; 33 34 if ((size = read(fd, kernel_cmdline, sizeof(kernel_cmdline))) == -1) { 35 fprint(1, "cannot read /proc/cmdline: %r\n"); 36 close(fd); 37 return; 38 } 39 kernel_cmdline[size] = '\0'; 40 41 end = kernel_cmdline; 42 43 while (end < kernel_cmdline + size && (match = strstr(end, "modules-load=")) != NULL) { 44 if (match != end && match[-1] != '.' && match[-1] != ' ') { 45 end += sizeof("modules-load=") - 1; // -1 because of implicit '\0' 46 continue; 47 } 48 49 match += sizeof("modules-load=") - 1; // -1 because of implicit '\0' 50 if ((end = strchr(match, ' ')) == NULL) 51 end = kernel_cmdline + size; 52 *end = '\0'; 53 54 while ((com = strchr(match, ',')) != NULL) { 55 *com = '\0'; 56 strcpy(modules[modules_size++], match); 57 match = com + 1; 58 } 59 if (match[0] != '\0') 60 strcpy(modules[modules_size++], match); 61 } 62 } 63 64 static const char trim_chars[] = "#;\n\r"; 65 66 static const char* search_dirs[] = { 67 "/etc/modules-load.d/", 68 "/run/modules-load.d/", 69 "/usr/lib/modules-load.d/", 70 }; 71 72 static void read_file(char* path) { 73 FILE* fd; 74 char line[MAX_MODULE_SIZE]; 75 char* ending; 76 77 if (!(fd = fopen(path, "r"))) { 78 fprint(1, "unable to open %s: %r\n", path); 79 return; 80 } 81 82 while (fgets(line, sizeof(line), fd)) { 83 for (const char* chr = trim_chars; *chr; chr++) 84 if ((ending = strchr(line, *chr)) != NULL) 85 *ending = '\0'; 86 87 if (line[0] != '\0') 88 strcpy(modules[modules_size++], line); 89 } 90 } 91 92 static void read_dir(const char* path) { 93 DIR* dir; 94 struct dirent* de; 95 96 if ((dir = opendir(path)) == NULL) { 97 return; 98 } 99 100 char filepath[1024]; 101 while ((de = readdir(dir)) != NULL) { 102 if (*de->d_name == '.') 103 continue; 104 105 strcpy(filepath, path); 106 strcat(filepath, de->d_name); 107 108 read_file(filepath); 109 } 110 111 closedir(dir); 112 } 113 114 int main(int argc, char** argv) { 115 read_cmdline(); 116 117 for (int i = 0; i < (int) (sizeof(search_dirs) / sizeof(*search_dirs)); i++) 118 read_dir(search_dirs[i]); 119 120 if (modules_size == 0) 121 return 0; 122 123 for (int i = 0; i < modules_size; i++) 124 print("%s\n", modules[i]); 125 126 char* args[modules_size + argc - 1 + 2 + 1]; 127 int argi = 0; 128 129 args[argi++] = "modprobe"; 130 args[argi++] = "-ab"; 131 132 for (int i = 1; i < argc; i++) 133 args[argi++] = argv[i]; 134 135 for (int i = 0; i < modules_size; i++) 136 args[argi++] = modules[i]; 137 138 args[argi++] = NULL; 139 140 execvp("modprobe", args); 141 142 fprint(1, "cannot exec modprobe: %r\n"); 143 return 1; 144 }