189 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * rv tool, the interface for the Linux kernel RV subsystem and home of4 * user-space controlled monitors.5 *6 * Copyright (C) 2022 Red Hat Inc, Daniel Bristot de Oliveira <bristot@kernel.org>7 */8 9#include <stdlib.h>10#include <signal.h>11#include <unistd.h>12 13#include <trace.h>14#include <utils.h>15#include <in_kernel.h>16 17static int stop_session;18 19/*20 * stop_rv - tell monitors to stop21 */22static void stop_rv(int sig)23{24 stop_session = 1;25}26 27/**28 * should_stop - check if the monitor should stop.29 *30 * Returns 1 if the monitor should stop, 0 otherwise.31 */32int should_stop(void)33{34 return stop_session;35}36 37/*38 * rv_list - list all available monitors39 */40static void rv_list(int argc, char **argv)41{42 static const char *const usage[] = {43 "",44 " usage: rv list [-h]",45 "",46 " list all available monitors",47 "",48 " -h/--help: print this menu",49 NULL,50 };51 int i;52 53 if (argc > 1) {54 fprintf(stderr, "rv version %s\n", VERSION);55 56 /* more than 1 is always usage */57 for (i = 0; usage[i]; i++)58 fprintf(stderr, "%s\n", usage[i]);59 60 /* but only -h is valid */61 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))62 exit(0);63 else64 exit(1);65 }66 67 ikm_list_monitors();68 exit(0);69}70 71/*72 * rv_mon - try to run a monitor passed as argument73 */74static void rv_mon(int argc, char **argv)75{76 char *monitor_name;77 int i, run = 0;78 79 static const char *const usage[] = {80 "",81 " usage: rv mon [-h] monitor [monitor options]",82 "",83 " run a monitor",84 "",85 " -h/--help: print this menu",86 "",87 " monitor [monitor options]: the monitor, passing",88 " the arguments to the [monitor options]",89 NULL,90 };91 92 /* requires at least one argument */93 if (argc == 1) {94 95 fprintf(stderr, "rv version %s\n", VERSION);96 97 for (i = 0; usage[i]; i++)98 fprintf(stderr, "%s\n", usage[i]);99 exit(1);100 } else if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {101 102 fprintf(stderr, "rv version %s\n", VERSION);103 104 for (i = 0; usage[i]; i++)105 fprintf(stderr, "%s\n", usage[i]);106 exit(0);107 }108 109 monitor_name = argv[1];110 /*111 * Call all possible monitor implementations, looking112 * for the [monitor].113 */114 run += ikm_run_monitor(monitor_name, argc-1, &argv[1]);115 116 if (!run)117 err_msg("rv: monitor %s does not exist\n", monitor_name);118 exit(!run);119}120 121static void usage(int exit_val, const char *fmt, ...)122{123 char message[1024];124 va_list ap;125 int i;126 127 static const char *const usage[] = {128 "",129 " usage: rv command [-h] [command_options]",130 "",131 " -h/--help: print this menu",132 "",133 " command: run one of the following command:",134 " list: list all available monitors",135 " mon: run a monitor",136 "",137 " [command options]: each command has its own set of options",138 " run rv command -h for further information",139 NULL,140 };141 142 va_start(ap, fmt);143 vsnprintf(message, sizeof(message), fmt, ap);144 va_end(ap);145 146 fprintf(stderr, "rv version %s: %s\n", VERSION, message);147 148 for (i = 0; usage[i]; i++)149 fprintf(stderr, "%s\n", usage[i]);150 151 exit(exit_val);152}153 154/*155 * main - select which main sending the command156 *157 * main itself redirects the arguments to the sub-commands158 * to handle the options.159 *160 * subcommands should exit.161 */162int main(int argc, char **argv)163{164 if (geteuid())165 usage(1, "%s needs root permission", argv[0]);166 167 if (argc <= 1)168 usage(1, "%s requires a command", argv[0]);169 170 if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))171 usage(0, "help");172 173 if (!strcmp(argv[1], "list"))174 rv_list(--argc, &argv[1]);175 176 if (!strcmp(argv[1], "mon")) {177 /*178 * monitor's main should monitor should_stop() function.179 * and exit.180 */181 signal(SIGINT, stop_rv);182 183 rv_mon(argc - 1, &argv[1]);184 }185 186 /* invalid sub-command */187 usage(1, "%s does not know the %s command, old version?", argv[0], argv[1]);188}189