1 /*
2 * kmod - one tool to rule them all
3 *
4 * Copyright (C) 2011-2013 ProFUSION embedded systems
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <errno.h>
21 #include <getopt.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include <shared/util.h>
27
28 #include <libkmod/libkmod.h>
29
30 #include "kmod.h"
31
32 static const char options_s[] = "+hV";
33 static const struct option options[] = {
34 { "help", no_argument, NULL, 'h' },
35 { "version", no_argument, NULL, 'V' },
36 {}
37 };
38
39 static const struct kmod_cmd kmod_cmd_help;
40
41 static const struct kmod_cmd *kmod_cmds[] = {
42 &kmod_cmd_help,
43 &kmod_cmd_list,
44 &kmod_cmd_static_nodes,
45 };
46
47 static const struct kmod_cmd *kmod_compat_cmds[] = {
48 &kmod_cmd_compat_lsmod,
49 &kmod_cmd_compat_rmmod,
50 &kmod_cmd_compat_insmod,
51 &kmod_cmd_compat_modinfo,
52 &kmod_cmd_compat_modprobe,
53 &kmod_cmd_compat_depmod,
54 };
55
kmod_help(int argc,char * argv[])56 static int kmod_help(int argc, char *argv[])
57 {
58 size_t i;
59
60 printf("kmod - Manage kernel modules: list, load, unload, etc\n"
61 "Usage:\n"
62 "\t%s [options] command [command_options]\n\n"
63 "Options:\n"
64 "\t-V, --version show version\n"
65 "\t-h, --help show this help\n\n"
66 "Commands:\n", basename(argv[0]));
67
68 for (i = 0; i < ARRAY_SIZE(kmod_cmds); i++) {
69 if (kmod_cmds[i]->help != NULL) {
70 printf(" %-12s %s\n", kmod_cmds[i]->name,
71 kmod_cmds[i]->help);
72 }
73 }
74
75 puts("\nkmod also handles gracefully if called from following symlinks:");
76
77 for (i = 0; i < ARRAY_SIZE(kmod_compat_cmds); i++) {
78 if (kmod_compat_cmds[i]->help != NULL) {
79 printf(" %-12s %s\n", kmod_compat_cmds[i]->name,
80 kmod_compat_cmds[i]->help);
81 }
82 }
83
84 return EXIT_SUCCESS;
85 }
86
87 static const struct kmod_cmd kmod_cmd_help = {
88 .name = "help",
89 .cmd = kmod_help,
90 .help = "Show help message",
91 };
92
handle_kmod_commands(int argc,char * argv[])93 static int handle_kmod_commands(int argc, char *argv[])
94 {
95 const char *cmd;
96 int err = 0;
97 size_t i;
98
99 for (;;) {
100 int c;
101
102 c = getopt_long(argc, argv, options_s, options, NULL);
103 if (c == -1)
104 break;
105
106 switch (c) {
107 case 'h':
108 kmod_help(argc, argv);
109 return EXIT_SUCCESS;
110 case 'V':
111 puts(PACKAGE " version " VERSION);
112 puts(KMOD_FEATURES);
113 return EXIT_SUCCESS;
114 case '?':
115 return EXIT_FAILURE;
116 default:
117 fprintf(stderr, "Error: unexpected getopt_long() value '%c'.\n", c);
118 return EXIT_FAILURE;
119 }
120 }
121
122 if (optind >= argc) {
123 fputs("missing command\n", stderr);
124 goto fail;
125 }
126
127 cmd = argv[optind];
128
129 for (i = 0, err = -EINVAL; i < ARRAY_SIZE(kmod_cmds); i++) {
130 if (streq(kmod_cmds[i]->name, cmd)) {
131 err = kmod_cmds[i]->cmd(--argc, ++argv);
132 break;
133 }
134 }
135
136 if (err < 0) {
137 fprintf(stderr, "invalid command '%s'\n", cmd);
138 goto fail;
139 }
140
141 return err;
142
143 fail:
144 kmod_help(argc, argv);
145 return EXIT_FAILURE;
146 }
147
148
handle_kmod_compat_commands(int argc,char * argv[])149 static int handle_kmod_compat_commands(int argc, char *argv[])
150 {
151 const char *cmd;
152 size_t i;
153
154 cmd = basename(argv[0]);
155
156 for (i = 0; i < ARRAY_SIZE(kmod_compat_cmds); i++) {
157 if (streq(kmod_compat_cmds[i]->name, cmd))
158 return kmod_compat_cmds[i]->cmd(argc, argv);
159 }
160
161 return -ENOENT;
162 }
163
main(int argc,char * argv[])164 int main(int argc, char *argv[])
165 {
166 int err;
167
168 if (streq(program_invocation_short_name, "kmod"))
169 err = handle_kmod_commands(argc, argv);
170 else
171 err = handle_kmod_compat_commands(argc, argv);
172
173 return err;
174 }
175