// SPDX-License-Identifier: GPL-2.0-or-later /* * command structure borrowed from udev * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git) * * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> * 2005-2007 Takahiro Hirofuchi */ #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <syslog.h> #include "usbip_common.h" #include "usbip_network.h" #include "usbip.h" static int usbip_help(int argc, char *argv[]); static int usbip_version(int argc, char *argv[]); static const char usbip_version_string[] = PACKAGE_STRING; static const char usbip_usage_string[] = "usbip [--debug] [--log] [--tcp-port PORT] [version]\n" " [help] <command> <args>\n"; static void usbip_usage(void) { printf("usage: %s", usbip_usage_string); } struct command { const char *name; int (*fn)(int argc, char *argv[]); const char *help; void (*usage)(void); }; static const struct command cmds[] = { { .name = "help", .fn = usbip_help, .help = NULL, .usage = NULL }, { .name = "version", .fn = usbip_version, .help = NULL, .usage = NULL }, { .name = "attach", .fn = usbip_attach, .help = "Attach a remote USB device", .usage = usbip_attach_usage }, { .name = "detach", .fn = usbip_detach, .help = "Detach a remote USB device", .usage = usbip_detach_usage }, { .name = "list", .fn = usbip_list, .help = "List exportable or local USB devices", .usage = usbip_list_usage }, { .name = "bind", .fn = usbip_bind, .help = "Bind device to " USBIP_HOST_DRV_NAME ".ko", .usage = usbip_bind_usage }, { .name = "unbind", .fn = usbip_unbind, .help = "Unbind device from " USBIP_HOST_DRV_NAME ".ko", .usage = usbip_unbind_usage }, { .name = "port", .fn = usbip_port_show, .help = "Show imported USB devices", .usage = NULL }, { NULL, NULL, NULL, NULL } }; static int usbip_help(int argc, char *argv[]) { const struct command *cmd; int i; int ret = 0; if (argc > 1 && argv++) { for (i = 0; cmds[i].name != NULL; i++) if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) { cmds[i].usage(); goto done; } ret = -1; } usbip_usage(); printf("\n"); for (cmd = cmds; cmd->name != NULL; cmd++) if (cmd->help != NULL) printf(" %-10s %s\n", cmd->name, cmd->help); printf("\n"); done: return ret; } static int usbip_version(int argc, char *argv[]) { (void) argc; (void) argv; printf(PROGNAME " (%s)\n", usbip_version_string); return 0; } static int run_command(const struct command *cmd, int argc, char *argv[]) { dbg("running command: `%s'", cmd->name); return cmd->fn(argc, argv); } int main(int argc, char *argv[]) { static const struct option opts[] = { { "debug", no_argument, NULL, 'd' }, { "log", no_argument, NULL, 'l' }, { "tcp-port", required_argument, NULL, 't' }, { NULL, 0, NULL, 0 } }; char *cmd; int opt; int i, rc = -1; usbip_use_stderr = 1; opterr = 0; for (;;) { opt = getopt_long(argc, argv, "+dlt:", opts, NULL); if (opt == -1) break; switch (opt) { case 'd': usbip_use_debug = 1; break; case 'l': usbip_use_syslog = 1; openlog("", LOG_PID, LOG_USER); break; case 't': usbip_setup_port_number(optarg); break; case '?': printf("usbip: invalid option\n"); /* Terminate after printing error */ /* FALLTHRU */ default: usbip_usage(); goto out; } } cmd = argv[optind]; if (cmd) { for (i = 0; cmds[i].name != NULL; i++) if (!strcmp(cmds[i].name, cmd)) { argc -= optind; argv += optind; optind = 0; rc = run_command(&cmds[i], argc, argv); goto out; } } /* invalid command */ usbip_help(0, NULL); out: return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE); }