minidlna support now Samsung TV C550/C650 (thx amir909)
[tomato.git] / release / src / router / hotplug2 / linux24_compat / hotplug2-modwrap.c
blob541d9fe635bcc8afc2b3fcd7838a75929b2274ba
1 /*****************************************************************************\
2 * _ _ _ _ ___ *
3 * | || | ___ | |_ _ __ | | _ _ __ _ |_ ) *
4 * | __ |/ _ \| _|| '_ \| || || |/ _` | / / *
5 * |_||_|\___/ \__|| .__/|_| \_,_|\__, |/___| *
6 * |_| |___/ *
7 \*****************************************************************************/
9 #define _GNU_SOURCE
11 #include <fcntl.h>
12 #include <stdio.h>
13 #include <unistd.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <dirent.h>
18 #include <ctype.h>
19 #include <fnmatch.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <sys/stat.h>
23 #include <sys/mman.h>
24 #include <sys/utsname.h>
25 #include <linux/types.h>
26 #include <linux/input.h>
28 #include "../hotplug2.h"
29 #include "../mem_utils.h"
30 #include "../parser_utils.h"
31 #include "../filemap_utils.h"
33 #define MODULES_PATH "/lib/modules/"
34 #define MODULES_ALIAS "modules.alias"
36 /**
37 * A simple fork/exec wrapper
39 * @1 Complete argv, including app path
41 * Returns: -1 if error, children return value otherwise
43 int execute(char **argv) {
44 pid_t p;
45 int status;
47 p = fork();
48 switch (p) {
49 case -1:
50 return -1;
51 case 0:
52 execvp(argv[0], argv);
53 exit(1);
54 break;
55 default:
56 waitpid(p, &status, 0);
57 break;
60 return WEXITSTATUS(status);
63 int main(int argc, char *argv[]) {
64 struct utsname unamebuf;
65 struct filemap_t aliasmap;
66 char *line, *nline, *nptr;
67 char *token;
68 char *filename;
70 char *cur_alias, *match_alias, *module;
72 if (argc < 2) {
73 fprintf(stderr, "Usage: hotplug2-modwrap [options for modprobe] <alias>\n");
76 match_alias = strdup(argv[argc - 1]);
79 * If we can't do uname, we're absolutely screwed and there's no
80 * sense thinking twice about anything.
82 if (uname(&unamebuf)) {
83 ERROR("uname", "Unable to perform uname: %s.", strerror(errno));
84 return 1;
88 * We allow setting the modprobe command to an arbitrary value.
90 * The whole trick lies in executing modprobe with exactly the
91 * same argv as this app was executed, except we use a different
92 * argv[0] (application path) and argv[argc-1] (we substitute
93 * the given modalias by the matching module name)
95 argv[0] = getenv("MODPROBE_COMMAND");
96 if (argv[0] == NULL)
97 argv[0] = "/sbin/modprobe";
100 * Compose a path, /lib/modules/`uname -r`/modules.alias
102 * "/lib/modules/" + "/" + "\0"
104 filename = xmalloc(strlen(MODULES_PATH) + strlen(unamebuf.release) + strlen(MODULES_ALIAS));
105 strcpy(filename, MODULES_PATH);
106 strcat(filename, unamebuf.release);
107 strcat(filename, MODULES_ALIAS);
109 if (map_file(filename, &aliasmap)) {
110 ERROR("map_file", "Unable to map file: `%s'.", filename);
111 free(filename);
112 free(match_alias);
113 return 1;
117 * Read all the aliases, match them against given parameter.
119 nptr = aliasmap.map;
120 while ((line = dup_line(nptr, &nptr)) != NULL) {
121 nline = line;
124 * We want aliases only
126 token = dup_token(nline, &nline, isspace);
127 if (!token || strcmp(token, "alias")) {
128 free(token);
129 free(line);
130 continue;
132 free(token);
135 * It's an alias, so fetch it
137 cur_alias = dup_token(nline, &nline, isspace);
138 if (!cur_alias) {
139 free(line);
140 continue;
144 * And now we get the module name
146 module = dup_token(nline, &nline, isspace);
147 if (!module) {
148 free(line);
149 free(cur_alias);
150 continue;
154 * If we match, we do the modalias->module name
155 * substitution as described above and execute.
157 if (!fnmatch(cur_alias, match_alias, 0)) {
158 argv[argc - 1] = module;
159 if (execute(argv)) {
160 ERROR("execute", "Error during exection of: `%s'.", argv[0]);
164 free(cur_alias);
165 free(module);
166 free(line);
170 * Perhaps we didn't match anything, so we might've been given
171 * a module name instead of a modalias. Try to modprobe it
172 * right away.
174 if (strcmp(argv[argc - 1], match_alias) == 0) {
175 if (execute(argv)) {
176 ERROR("execute", "Error during exection of: `%s'.", argv[0]);
180 free(filename);
181 free(match_alias);
182 unmap_file(&aliasmap);
184 return 0;