189 lines
3.7 KiB
C
189 lines
3.7 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* rv tool, the interface for the Linux kernel RV subsystem and home of
|
|
* user-space controlled monitors.
|
|
*
|
|
* Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#include <trace.h>
|
|
#include <utils.h>
|
|
#include <in_kernel.h>
|
|
|
|
static int stop_session;
|
|
|
|
/*
|
|
* stop_rv - tell monitors to stop
|
|
*/
|
|
static void stop_rv(int sig)
|
|
{
|
|
stop_session = 1;
|
|
}
|
|
|
|
/**
|
|
* should_stop - check if the monitor should stop.
|
|
*
|
|
* Returns 1 if the monitor should stop, 0 otherwise.
|
|
*/
|
|
int should_stop(void)
|
|
{
|
|
return stop_session;
|
|
}
|
|
|
|
/*
|
|
* rv_list - list all available monitors
|
|
*/
|
|
static void rv_list(int argc, char **argv)
|
|
{
|
|
static const char *const usage[] = {
|
|
"",
|
|
" usage: rv list [-h]",
|
|
"",
|
|
" list all available monitors",
|
|
"",
|
|
" -h/--help: print this menu",
|
|
NULL,
|
|
};
|
|
int i;
|
|
|
|
if (argc > 1) {
|
|
fprintf(stderr, "rv version %s\n", VERSION);
|
|
|
|
/* more than 1 is always usage */
|
|
for (i = 0; usage[i]; i++)
|
|
fprintf(stderr, "%s\n", usage[i]);
|
|
|
|
/* but only -h is valid */
|
|
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
|
|
exit(0);
|
|
else
|
|
exit(1);
|
|
}
|
|
|
|
ikm_list_monitors();
|
|
exit(0);
|
|
}
|
|
|
|
/*
|
|
* rv_mon - try to run a monitor passed as argument
|
|
*/
|
|
static void rv_mon(int argc, char **argv)
|
|
{
|
|
char *monitor_name;
|
|
int i, run = 0;
|
|
|
|
static const char *const usage[] = {
|
|
"",
|
|
" usage: rv mon [-h] monitor [monitor options]",
|
|
"",
|
|
" run a monitor",
|
|
"",
|
|
" -h/--help: print this menu",
|
|
"",
|
|
" monitor [monitor options]: the monitor, passing",
|
|
" the arguments to the [monitor options]",
|
|
NULL,
|
|
};
|
|
|
|
/* requires at least one argument */
|
|
if (argc == 1) {
|
|
|
|
fprintf(stderr, "rv version %s\n", VERSION);
|
|
|
|
for (i = 0; usage[i]; i++)
|
|
fprintf(stderr, "%s\n", usage[i]);
|
|
exit(1);
|
|
} else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
|
|
|
|
fprintf(stderr, "rv version %s\n", VERSION);
|
|
|
|
for (i = 0; usage[i]; i++)
|
|
fprintf(stderr, "%s\n", usage[i]);
|
|
exit(0);
|
|
}
|
|
|
|
monitor_name = argv[1];
|
|
/*
|
|
* Call all possible monitor implementations, looking
|
|
* for the [monitor].
|
|
*/
|
|
run += ikm_run_monitor(monitor_name, argc-1, &argv[1]);
|
|
|
|
if (!run)
|
|
err_msg("rv: monitor %s does not exist\n", monitor_name);
|
|
exit(!run);
|
|
}
|
|
|
|
static void usage(int exit_val, const char *fmt, ...)
|
|
{
|
|
char message[1024];
|
|
va_list ap;
|
|
int i;
|
|
|
|
static const char *const usage[] = {
|
|
"",
|
|
" usage: rv command [-h] [command_options]",
|
|
"",
|
|
" -h/--help: print this menu",
|
|
"",
|
|
" command: run one of the following command:",
|
|
" list: list all available monitors",
|
|
" mon: run a monitor",
|
|
"",
|
|
" [command options]: each command has its own set of options",
|
|
" run rv command -h for further information",
|
|
NULL,
|
|
};
|
|
|
|
va_start(ap, fmt);
|
|
vsnprintf(message, sizeof(message), fmt, ap);
|
|
va_end(ap);
|
|
|
|
fprintf(stderr, "rv version %s: %s\n", VERSION, message);
|
|
|
|
for (i = 0; usage[i]; i++)
|
|
fprintf(stderr, "%s\n", usage[i]);
|
|
|
|
exit(exit_val);
|
|
}
|
|
|
|
/*
|
|
* main - select which main sending the command
|
|
*
|
|
* main itself redirects the arguments to the sub-commands
|
|
* to handle the options.
|
|
*
|
|
* subcommands should exit.
|
|
*/
|
|
int main(int argc, char **argv)
|
|
{
|
|
if (geteuid())
|
|
usage(1, "%s needs root permission", argv[0]);
|
|
|
|
if (argc <= 1)
|
|
usage(1, "%s requires a command", argv[0]);
|
|
|
|
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
|
|
usage(0, "help");
|
|
|
|
if (!strcmp(argv[1], "list"))
|
|
rv_list(--argc, &argv[1]);
|
|
|
|
if (!strcmp(argv[1], "mon")) {
|
|
/*
|
|
* monitor's main should monitor should_stop() function.
|
|
* and exit.
|
|
*/
|
|
signal(SIGINT, stop_rv);
|
|
|
|
rv_mon(argc - 1, &argv[1]);
|
|
}
|
|
|
|
/* invalid sub-command */
|
|
usage(1, "%s does not know the %s command, old version?", argv[0], argv[1]);
|
|
}
|