modules-load.c (2968B) download
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
18const char* current_prog(void) {
19 return "modules-load";
20}
21
22static char kernel_cmdline[MAX_CMDLINE_SIZE];
23static char modules[MAX_MODULE_COUNT][MAX_MODULE_SIZE];
24static int modules_size = 0;
25
26static 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
64static const char trim_chars[] = "#;\n\r";
65
66static const char* search_dirs[] = {
67 "/etc/modules-load.d/",
68 "/run/modules-load.d/",
69 "/usr/lib/modules-load.d/",
70};
71
72static 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
92static 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
114int 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}