blob: 55689c075ab13ea60490a3e5b23ad309a429e39c [file] [log] [blame]
Lucas De Marchi8900b912011-12-22 02:33:36 -02001/*
2 * kmod - one tool to rule them all
3 *
Lucas De Marchie6b0e492013-01-16 11:27:21 -02004 * Copyright (C) 2011-2013 ProFUSION embedded systems
Lucas De Marchi8900b912011-12-22 02:33:36 -02005 *
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
Lucas De Marchi8900b912011-12-22 02:33:36 -020020#include <errno.h>
Lucas De Marchibc854322011-12-23 02:56:27 -020021#include <getopt.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030022#include <stdio.h>
23#include <stdlib.h>
Lucas De Marchi8900b912011-12-22 02:33:36 -020024#include <string.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030025
Lucas De Marchi7db094c2015-01-14 12:28:02 -020026#include <shared/util.h>
27
Lucas De Marchif3578662015-01-02 12:38:27 -020028#include <libkmod/libkmod.h>
Lucas De Marchic2e42862014-10-03 01:41:42 -030029
Lucas De Marchi8900b912011-12-22 02:33:36 -020030#include "kmod.h"
31
Lucas De Marchibc854322011-12-23 02:56:27 -020032static const char options_s[] = "+hV";
33static const struct option options[] = {
34 { "help", no_argument, NULL, 'h' },
35 { "version", no_argument, NULL, 'V' },
36 {}
37};
38
Lucas De Marchi8900b912011-12-22 02:33:36 -020039static const struct kmod_cmd kmod_cmd_help;
40
41static const struct kmod_cmd *kmod_cmds[] = {
42 &kmod_cmd_help,
Lucas De Marchi252c51a2011-12-23 11:33:02 -020043 &kmod_cmd_list,
Tom Gundersendb6f2fc2013-04-16 22:39:55 +020044 &kmod_cmd_static_nodes,
Lucas De Marchi013e8552015-06-06 23:26:31 -030045
46#ifdef ENABLE_EXPERIMENTAL
47 &kmod_cmd_insert,
48 &kmod_cmd_remove,
49#endif
Lucas De Marchi8900b912011-12-22 02:33:36 -020050};
51
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -020052static const struct kmod_cmd *kmod_compat_cmds[] = {
53 &kmod_cmd_compat_lsmod,
Lucas De Marchif712ebc2011-12-22 03:39:11 -020054 &kmod_cmd_compat_rmmod,
Lucas De Marchiad602692011-12-22 03:45:07 -020055 &kmod_cmd_compat_insmod,
Lucas De Marchi769becb2011-12-22 03:50:54 -020056 &kmod_cmd_compat_modinfo,
Lucas De Marchifa29c0e2011-12-22 03:54:46 -020057 &kmod_cmd_compat_modprobe,
Lucas De Marchif6cf14c2011-12-27 19:56:33 -020058 &kmod_cmd_compat_depmod,
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -020059};
60
Lucas De Marchi8900b912011-12-22 02:33:36 -020061static int kmod_help(int argc, char *argv[])
62{
63 size_t i;
64
Lucas De Marchia458e362011-12-23 11:35:48 -020065 printf("kmod - Manage kernel modules: list, load, unload, etc\n"
Lucas De Marchibc854322011-12-23 02:56:27 -020066 "Usage:\n"
67 "\t%s [options] command [command_options]\n\n"
68 "Options:\n"
69 "\t-V, --version show version\n"
70 "\t-h, --help show this help\n\n"
71 "Commands:\n", basename(argv[0]));
Lucas De Marchi8900b912011-12-22 02:33:36 -020072
73 for (i = 0; i < ARRAY_SIZE(kmod_cmds); i++) {
74 if (kmod_cmds[i]->help != NULL) {
75 printf(" %-12s %s\n", kmod_cmds[i]->name,
76 kmod_cmds[i]->help);
77 }
78 }
79
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -020080 puts("\nkmod also handles gracefully if called from following symlinks:");
81
82 for (i = 0; i < ARRAY_SIZE(kmod_compat_cmds); i++) {
83 if (kmod_compat_cmds[i]->help != NULL) {
84 printf(" %-12s %s\n", kmod_compat_cmds[i]->name,
85 kmod_compat_cmds[i]->help);
86 }
87 }
Lucas De Marchi35a29aa2011-12-22 19:21:11 -020088
Lucas De Marchi8900b912011-12-22 02:33:36 -020089 return EXIT_SUCCESS;
90}
91
92static const struct kmod_cmd kmod_cmd_help = {
93 .name = "help",
94 .cmd = kmod_help,
95 .help = "Show help message",
96};
97
Lucas De Marchi35a29aa2011-12-22 19:21:11 -020098static int handle_kmod_commands(int argc, char *argv[])
Lucas De Marchi8900b912011-12-22 02:33:36 -020099{
100 const char *cmd;
101 int err = 0;
102 size_t i;
103
Lucas De Marchibc854322011-12-23 02:56:27 -0200104 for (;;) {
105 int c;
106
107 c = getopt_long(argc, argv, options_s, options, NULL);
108 if (c == -1)
109 break;
110
111 switch (c) {
112 case 'h':
113 kmod_help(argc, argv);
114 return EXIT_SUCCESS;
115 case 'V':
Lucas De Marchib1499092015-06-08 21:30:11 -0300116 puts(PACKAGE " version " VERSION);
Lucas De Marchi655de272015-06-07 02:46:22 -0300117 puts(KMOD_FEATURES);
Lucas De Marchibc854322011-12-23 02:56:27 -0200118 return EXIT_SUCCESS;
119 case '?':
120 return EXIT_FAILURE;
121 default:
122 fprintf(stderr, "Error: unexpected getopt_long() value '%c'.\n", c);
123 return EXIT_FAILURE;
124 }
125 }
126
127 if (optind >= argc) {
Lucas De Marchi9b966da2011-12-23 11:44:28 -0200128 fputs("missing command\n", stderr);
129 goto fail;
Lucas De Marchi8900b912011-12-22 02:33:36 -0200130 }
131
Lucas De Marchibc854322011-12-23 02:56:27 -0200132 cmd = argv[optind];
Lucas De Marchi8900b912011-12-22 02:33:36 -0200133
Lucas De Marchi9b966da2011-12-23 11:44:28 -0200134 for (i = 0, err = -EINVAL; i < ARRAY_SIZE(kmod_cmds); i++) {
Lucas De Marchi7db094c2015-01-14 12:28:02 -0200135 if (streq(kmod_cmds[i]->name, cmd)) {
Caio Marcelo de Oliveira Filhoace71982015-01-14 12:02:16 -0200136 err = kmod_cmds[i]->cmd(--argc, ++argv);
137 break;
138 }
Lucas De Marchi8900b912011-12-22 02:33:36 -0200139 }
140
Lucas De Marchi8900b912011-12-22 02:33:36 -0200141 if (err < 0) {
Lucas De Marchi9b966da2011-12-23 11:44:28 -0200142 fprintf(stderr, "invalid command '%s'\n", cmd);
143 goto fail;
Lucas De Marchi8900b912011-12-22 02:33:36 -0200144 }
145
146 return err;
Lucas De Marchi9b966da2011-12-23 11:44:28 -0200147
148fail:
149 kmod_help(argc, argv);
150 return EXIT_FAILURE;
Lucas De Marchi8900b912011-12-22 02:33:36 -0200151}
Lucas De Marchi35a29aa2011-12-22 19:21:11 -0200152
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -0200153
154static int handle_kmod_compat_commands(int argc, char *argv[])
155{
156 const char *cmd;
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -0200157 size_t i;
158
159 cmd = basename(argv[0]);
160
161 for (i = 0; i < ARRAY_SIZE(kmod_compat_cmds); i++) {
Lucas De Marchi7db094c2015-01-14 12:28:02 -0200162 if (streq(kmod_compat_cmds[i]->name, cmd))
Leandro Pereira4783d692011-12-27 18:22:30 -0200163 return kmod_compat_cmds[i]->cmd(argc, argv);
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -0200164 }
165
Leandro Pereira4783d692011-12-27 18:22:30 -0200166 return -ENOENT;
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -0200167}
168
Lucas De Marchi35a29aa2011-12-22 19:21:11 -0200169int main(int argc, char *argv[])
170{
Lucas De Marchi35a29aa2011-12-22 19:21:11 -0200171 int err;
172
Lucas De Marchi7db094c2015-01-14 12:28:02 -0200173 if (streq(program_invocation_short_name, "kmod"))
Lucas De Marchi35a29aa2011-12-22 19:21:11 -0200174 err = handle_kmod_commands(argc, argv);
175 else
Lucas De Marchi6fcf69e2011-12-22 03:01:45 -0200176 err = handle_kmod_compat_commands(argc, argv);
Lucas De Marchi35a29aa2011-12-22 19:21:11 -0200177
178 return err;
179}