fiss

Friedel's Initialization and Service Supervision
Log | Files | Refs | LICENSE

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 }