14bc4b131SDaniel Bristot de Oliveira // SPDX-License-Identifier: GPL-2.0
24bc4b131SDaniel Bristot de Oliveira /*
34bc4b131SDaniel Bristot de Oliveira * rv tool, the interface for the Linux kernel RV subsystem and home of
44bc4b131SDaniel Bristot de Oliveira * user-space controlled monitors.
54bc4b131SDaniel Bristot de Oliveira *
64bc4b131SDaniel Bristot de Oliveira * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>
74bc4b131SDaniel Bristot de Oliveira */
84bc4b131SDaniel Bristot de Oliveira
94bc4b131SDaniel Bristot de Oliveira #include <stdlib.h>
104bc4b131SDaniel Bristot de Oliveira #include <signal.h>
114bc4b131SDaniel Bristot de Oliveira #include <unistd.h>
124bc4b131SDaniel Bristot de Oliveira
134bc4b131SDaniel Bristot de Oliveira #include <trace.h>
144bc4b131SDaniel Bristot de Oliveira #include <utils.h>
156d60f896SDaniel Bristot de Oliveira #include <in_kernel.h>
164bc4b131SDaniel Bristot de Oliveira
174bc4b131SDaniel Bristot de Oliveira static int stop_session;
184bc4b131SDaniel Bristot de Oliveira
194bc4b131SDaniel Bristot de Oliveira /*
204bc4b131SDaniel Bristot de Oliveira * stop_rv - tell monitors to stop
214bc4b131SDaniel Bristot de Oliveira */
stop_rv(int sig)224bc4b131SDaniel Bristot de Oliveira static void stop_rv(int sig)
234bc4b131SDaniel Bristot de Oliveira {
244bc4b131SDaniel Bristot de Oliveira stop_session = 1;
254bc4b131SDaniel Bristot de Oliveira }
264bc4b131SDaniel Bristot de Oliveira
274bc4b131SDaniel Bristot de Oliveira /**
284bc4b131SDaniel Bristot de Oliveira * should_stop - check if the monitor should stop.
294bc4b131SDaniel Bristot de Oliveira *
304bc4b131SDaniel Bristot de Oliveira * Returns 1 if the monitor should stop, 0 otherwise.
314bc4b131SDaniel Bristot de Oliveira */
should_stop(void)324bc4b131SDaniel Bristot de Oliveira int should_stop(void)
334bc4b131SDaniel Bristot de Oliveira {
344bc4b131SDaniel Bristot de Oliveira return stop_session;
354bc4b131SDaniel Bristot de Oliveira }
364bc4b131SDaniel Bristot de Oliveira
374bc4b131SDaniel Bristot de Oliveira /*
384bc4b131SDaniel Bristot de Oliveira * rv_list - list all available monitors
394bc4b131SDaniel Bristot de Oliveira */
rv_list(int argc,char ** argv)404bc4b131SDaniel Bristot de Oliveira static void rv_list(int argc, char **argv)
414bc4b131SDaniel Bristot de Oliveira {
424bc4b131SDaniel Bristot de Oliveira static const char *const usage[] = {
434bc4b131SDaniel Bristot de Oliveira "",
444bc4b131SDaniel Bristot de Oliveira " usage: rv list [-h]",
454bc4b131SDaniel Bristot de Oliveira "",
464bc4b131SDaniel Bristot de Oliveira " list all available monitors",
474bc4b131SDaniel Bristot de Oliveira "",
484bc4b131SDaniel Bristot de Oliveira " -h/--help: print this menu",
494bc4b131SDaniel Bristot de Oliveira NULL,
504bc4b131SDaniel Bristot de Oliveira };
514bc4b131SDaniel Bristot de Oliveira int i;
524bc4b131SDaniel Bristot de Oliveira
534bc4b131SDaniel Bristot de Oliveira if (argc > 1) {
544bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "rv version %s\n", VERSION);
554bc4b131SDaniel Bristot de Oliveira
564bc4b131SDaniel Bristot de Oliveira /* more than 1 is always usage */
574bc4b131SDaniel Bristot de Oliveira for (i = 0; usage[i]; i++)
584bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage[i]);
594bc4b131SDaniel Bristot de Oliveira
604bc4b131SDaniel Bristot de Oliveira /* but only -h is valid */
614bc4b131SDaniel Bristot de Oliveira if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
624bc4b131SDaniel Bristot de Oliveira exit(0);
634bc4b131SDaniel Bristot de Oliveira else
644bc4b131SDaniel Bristot de Oliveira exit(1);
654bc4b131SDaniel Bristot de Oliveira }
664bc4b131SDaniel Bristot de Oliveira
676d60f896SDaniel Bristot de Oliveira ikm_list_monitors();
684bc4b131SDaniel Bristot de Oliveira exit(0);
694bc4b131SDaniel Bristot de Oliveira }
704bc4b131SDaniel Bristot de Oliveira
714bc4b131SDaniel Bristot de Oliveira /*
724bc4b131SDaniel Bristot de Oliveira * rv_mon - try to run a monitor passed as argument
734bc4b131SDaniel Bristot de Oliveira */
rv_mon(int argc,char ** argv)744bc4b131SDaniel Bristot de Oliveira static void rv_mon(int argc, char **argv)
754bc4b131SDaniel Bristot de Oliveira {
764bc4b131SDaniel Bristot de Oliveira char *monitor_name;
77*54a0dffaSColin Ian King int i, run = 0;
784bc4b131SDaniel Bristot de Oliveira
794bc4b131SDaniel Bristot de Oliveira static const char *const usage[] = {
804bc4b131SDaniel Bristot de Oliveira "",
814bc4b131SDaniel Bristot de Oliveira " usage: rv mon [-h] monitor [monitor options]",
824bc4b131SDaniel Bristot de Oliveira "",
834bc4b131SDaniel Bristot de Oliveira " run a monitor",
844bc4b131SDaniel Bristot de Oliveira "",
854bc4b131SDaniel Bristot de Oliveira " -h/--help: print this menu",
864bc4b131SDaniel Bristot de Oliveira "",
874bc4b131SDaniel Bristot de Oliveira " monitor [monitor options]: the monitor, passing",
884bc4b131SDaniel Bristot de Oliveira " the arguments to the [monitor options]",
894bc4b131SDaniel Bristot de Oliveira NULL,
904bc4b131SDaniel Bristot de Oliveira };
914bc4b131SDaniel Bristot de Oliveira
924bc4b131SDaniel Bristot de Oliveira /* requires at least one argument */
934bc4b131SDaniel Bristot de Oliveira if (argc == 1) {
944bc4b131SDaniel Bristot de Oliveira
954bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "rv version %s\n", VERSION);
964bc4b131SDaniel Bristot de Oliveira
974bc4b131SDaniel Bristot de Oliveira for (i = 0; usage[i]; i++)
984bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage[i]);
994bc4b131SDaniel Bristot de Oliveira exit(1);
1004bc4b131SDaniel Bristot de Oliveira } else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
1014bc4b131SDaniel Bristot de Oliveira
1024bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "rv version %s\n", VERSION);
1034bc4b131SDaniel Bristot de Oliveira
1044bc4b131SDaniel Bristot de Oliveira for (i = 0; usage[i]; i++)
1054bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage[i]);
1064bc4b131SDaniel Bristot de Oliveira exit(0);
1074bc4b131SDaniel Bristot de Oliveira }
1084bc4b131SDaniel Bristot de Oliveira
1094bc4b131SDaniel Bristot de Oliveira monitor_name = argv[1];
1104bc4b131SDaniel Bristot de Oliveira /*
1114bc4b131SDaniel Bristot de Oliveira * Call all possible monitor implementations, looking
1124bc4b131SDaniel Bristot de Oliveira * for the [monitor].
1134bc4b131SDaniel Bristot de Oliveira */
1146d60f896SDaniel Bristot de Oliveira run += ikm_run_monitor(monitor_name, argc-1, &argv[1]);
1154bc4b131SDaniel Bristot de Oliveira
1164bc4b131SDaniel Bristot de Oliveira if (!run)
1174bc4b131SDaniel Bristot de Oliveira err_msg("rv: monitor %s does not exist\n", monitor_name);
1184bc4b131SDaniel Bristot de Oliveira exit(!run);
1194bc4b131SDaniel Bristot de Oliveira }
1204bc4b131SDaniel Bristot de Oliveira
usage(int exit_val,const char * fmt,...)1214bc4b131SDaniel Bristot de Oliveira static void usage(int exit_val, const char *fmt, ...)
1224bc4b131SDaniel Bristot de Oliveira {
1234bc4b131SDaniel Bristot de Oliveira char message[1024];
1244bc4b131SDaniel Bristot de Oliveira va_list ap;
1254bc4b131SDaniel Bristot de Oliveira int i;
1264bc4b131SDaniel Bristot de Oliveira
1274bc4b131SDaniel Bristot de Oliveira static const char *const usage[] = {
1284bc4b131SDaniel Bristot de Oliveira "",
1294bc4b131SDaniel Bristot de Oliveira " usage: rv command [-h] [command_options]",
1304bc4b131SDaniel Bristot de Oliveira "",
1314bc4b131SDaniel Bristot de Oliveira " -h/--help: print this menu",
1324bc4b131SDaniel Bristot de Oliveira "",
1334bc4b131SDaniel Bristot de Oliveira " command: run one of the following command:",
1344bc4b131SDaniel Bristot de Oliveira " list: list all available monitors",
1354bc4b131SDaniel Bristot de Oliveira " mon: run a monitor",
1364bc4b131SDaniel Bristot de Oliveira "",
1374bc4b131SDaniel Bristot de Oliveira " [command options]: each command has its own set of options",
1384bc4b131SDaniel Bristot de Oliveira " run rv command -h for further information",
1394bc4b131SDaniel Bristot de Oliveira NULL,
1404bc4b131SDaniel Bristot de Oliveira };
1414bc4b131SDaniel Bristot de Oliveira
1424bc4b131SDaniel Bristot de Oliveira va_start(ap, fmt);
1434bc4b131SDaniel Bristot de Oliveira vsnprintf(message, sizeof(message), fmt, ap);
1444bc4b131SDaniel Bristot de Oliveira va_end(ap);
1454bc4b131SDaniel Bristot de Oliveira
1464bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "rv version %s: %s\n", VERSION, message);
1474bc4b131SDaniel Bristot de Oliveira
1484bc4b131SDaniel Bristot de Oliveira for (i = 0; usage[i]; i++)
1494bc4b131SDaniel Bristot de Oliveira fprintf(stderr, "%s\n", usage[i]);
1504bc4b131SDaniel Bristot de Oliveira
1514bc4b131SDaniel Bristot de Oliveira exit(exit_val);
1524bc4b131SDaniel Bristot de Oliveira }
1534bc4b131SDaniel Bristot de Oliveira
1544bc4b131SDaniel Bristot de Oliveira /*
1554bc4b131SDaniel Bristot de Oliveira * main - select which main sending the command
1564bc4b131SDaniel Bristot de Oliveira *
1574bc4b131SDaniel Bristot de Oliveira * main itself redirects the arguments to the sub-commands
1584bc4b131SDaniel Bristot de Oliveira * to handle the options.
1594bc4b131SDaniel Bristot de Oliveira *
1604bc4b131SDaniel Bristot de Oliveira * subcommands should exit.
1614bc4b131SDaniel Bristot de Oliveira */
main(int argc,char ** argv)1624bc4b131SDaniel Bristot de Oliveira int main(int argc, char **argv)
1634bc4b131SDaniel Bristot de Oliveira {
1644bc4b131SDaniel Bristot de Oliveira if (geteuid())
1654bc4b131SDaniel Bristot de Oliveira usage(1, "%s needs root permission", argv[0]);
1664bc4b131SDaniel Bristot de Oliveira
1674bc4b131SDaniel Bristot de Oliveira if (argc <= 1)
1684bc4b131SDaniel Bristot de Oliveira usage(1, "%s requires a command", argv[0]);
1694bc4b131SDaniel Bristot de Oliveira
1704bc4b131SDaniel Bristot de Oliveira if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
1714bc4b131SDaniel Bristot de Oliveira usage(0, "help");
1724bc4b131SDaniel Bristot de Oliveira
1734bc4b131SDaniel Bristot de Oliveira if (!strcmp(argv[1], "list"))
1744bc4b131SDaniel Bristot de Oliveira rv_list(--argc, &argv[1]);
1754bc4b131SDaniel Bristot de Oliveira
1764bc4b131SDaniel Bristot de Oliveira if (!strcmp(argv[1], "mon")) {
1774bc4b131SDaniel Bristot de Oliveira /*
1784bc4b131SDaniel Bristot de Oliveira * monitor's main should monitor should_stop() function.
1794bc4b131SDaniel Bristot de Oliveira * and exit.
1804bc4b131SDaniel Bristot de Oliveira */
1814bc4b131SDaniel Bristot de Oliveira signal(SIGINT, stop_rv);
1824bc4b131SDaniel Bristot de Oliveira
1834bc4b131SDaniel Bristot de Oliveira rv_mon(argc - 1, &argv[1]);
1844bc4b131SDaniel Bristot de Oliveira }
1854bc4b131SDaniel Bristot de Oliveira
1864bc4b131SDaniel Bristot de Oliveira /* invalid sub-command */
1874bc4b131SDaniel Bristot de Oliveira usage(1, "%s does not know the %s command, old version?", argv[0], argv[1]);
1884bc4b131SDaniel Bristot de Oliveira }
189