+/*
+ * This function reads aliases and default module options from a configuration file
+ * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
+ */
+static void include_conf(struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd)
+{
+ int continuation_line = 0;
+
+ // alias parsing is not 100% correct (no correct handling of continuation lines within an alias)!
+
+ while (reads(fd, buffer, buflen)) {
+ int l;
+
+ *strchrnul(buffer, '#') = '\0';
+
+ l = strlen(buffer);
+
+ while (l && isspace(buffer[l-1])) {
+ buffer[l-1] = '\0';
+ l--;
+ }
+
+ if (l == 0) {
+ continuation_line = 0;
+ continue;
+ }
+
+ if (continuation_line)
+ continue;
+
+ if (is_conf_command(buffer, "alias")) {
+ char *alias, *mod;
+
+ if (parse_tag_value(buffer + 6, &alias, &mod)) {
+ /* handle alias as a module dependent on the aliased module */
+ if (!*current) {
+ (*first) = (*current) = xzalloc(sizeof(struct dep_t));
+ } else {
+ (*current)->m_next = xzalloc(sizeof(struct dep_t));
+ (*current) = (*current)->m_next;
+ }
+ (*current)->m_name = xstrdup(alias);
+ (*current)->m_isalias = 1;
+
+ if ((strcmp(mod, "off") == 0) || (strcmp(mod, "null") == 0)) {
+ /*(*current)->m_depcnt = 0; - done by xzalloc */
+ /*(*current)->m_deparr = 0;*/
+ } else {
+ (*current)->m_depcnt = 1;
+ (*current)->m_deparr = xmalloc(sizeof(char *));
+ (*current)->m_deparr[0] = xstrdup(mod);
+ }
+ /*(*current)->m_next = NULL; - done by xzalloc */
+ }
+ } else if (is_conf_command(buffer, "options")) {
+ char *mod, *opt;
+
+ /* split the line in the module/alias name, and options */
+ if (parse_tag_value(buffer + 8, &mod, &opt)) {
+ struct dep_t *dt;
+
+ /* find the corresponding module */
+ for (dt = *first; dt; dt = dt->m_next) {
+ if (strcmp(dt->m_name, mod) == 0)
+ break;
+ }
+ if (dt) {
+ if (ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS) {
+ char* new_opt = NULL;
+ while ((opt = parse_command_string(opt, &new_opt))) {
+ dt->m_options = append_option(dt->m_options, new_opt);
+ }
+ } else {
+ dt->m_options = append_option(dt->m_options, opt);
+ }
+ }
+ }
+ } else if (is_conf_command(buffer, "include")) {
+ int fdi;
+ char *filename;
+
+ filename = skip_whitespace(buffer + 8);
+ fdi = open(filename, O_RDONLY);
+ if (fdi >= 0) {
+ include_conf(first, current, buffer, buflen, fdi);
+ close(fdi);
+ }
+ } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST &&
+ (is_conf_command(buffer, "blacklist"))) {
+ char *mod;
+ struct dep_t *dt;
+
+ mod = skip_whitespace(buffer + 10);
+ for (dt = *first; dt; dt = dt->m_next) {
+ if (strcmp(dt->m_name, mod) == 0)
+ break;
+ }
+ if (dt)
+ dt->m_isblacklisted = 1;
+ }
+ } /* while (reads(...)) */
+}
+
+/*
+ * This function builds a list of dependency rules from /lib/modules/`uname -r`/modules.dep.
+ * It then fills every modules and aliases with their default options, found by parsing
+ * modprobe.conf (or modules.conf, or conf.modules).
+ */
+static struct dep_t *build_dep(void)