162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * command structure borrowed from udev 462306a36Sopenharmony_ci * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git) 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 762306a36Sopenharmony_ci * 2005-2007 Takahiro Hirofuchi 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <stdio.h> 1162306a36Sopenharmony_ci#include <stdlib.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#include <getopt.h> 1462306a36Sopenharmony_ci#include <syslog.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include "usbip_common.h" 1762306a36Sopenharmony_ci#include "usbip_network.h" 1862306a36Sopenharmony_ci#include "usbip.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic int usbip_help(int argc, char *argv[]); 2162306a36Sopenharmony_cistatic int usbip_version(int argc, char *argv[]); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic const char usbip_version_string[] = PACKAGE_STRING; 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic const char usbip_usage_string[] = 2662306a36Sopenharmony_ci "usbip [--debug] [--log] [--tcp-port PORT] [version]\n" 2762306a36Sopenharmony_ci " [help] <command> <args>\n"; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic void usbip_usage(void) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci printf("usage: %s", usbip_usage_string); 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistruct command { 3562306a36Sopenharmony_ci const char *name; 3662306a36Sopenharmony_ci int (*fn)(int argc, char *argv[]); 3762306a36Sopenharmony_ci const char *help; 3862306a36Sopenharmony_ci void (*usage)(void); 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic const struct command cmds[] = { 4262306a36Sopenharmony_ci { 4362306a36Sopenharmony_ci .name = "help", 4462306a36Sopenharmony_ci .fn = usbip_help, 4562306a36Sopenharmony_ci .help = NULL, 4662306a36Sopenharmony_ci .usage = NULL 4762306a36Sopenharmony_ci }, 4862306a36Sopenharmony_ci { 4962306a36Sopenharmony_ci .name = "version", 5062306a36Sopenharmony_ci .fn = usbip_version, 5162306a36Sopenharmony_ci .help = NULL, 5262306a36Sopenharmony_ci .usage = NULL 5362306a36Sopenharmony_ci }, 5462306a36Sopenharmony_ci { 5562306a36Sopenharmony_ci .name = "attach", 5662306a36Sopenharmony_ci .fn = usbip_attach, 5762306a36Sopenharmony_ci .help = "Attach a remote USB device", 5862306a36Sopenharmony_ci .usage = usbip_attach_usage 5962306a36Sopenharmony_ci }, 6062306a36Sopenharmony_ci { 6162306a36Sopenharmony_ci .name = "detach", 6262306a36Sopenharmony_ci .fn = usbip_detach, 6362306a36Sopenharmony_ci .help = "Detach a remote USB device", 6462306a36Sopenharmony_ci .usage = usbip_detach_usage 6562306a36Sopenharmony_ci }, 6662306a36Sopenharmony_ci { 6762306a36Sopenharmony_ci .name = "list", 6862306a36Sopenharmony_ci .fn = usbip_list, 6962306a36Sopenharmony_ci .help = "List exportable or local USB devices", 7062306a36Sopenharmony_ci .usage = usbip_list_usage 7162306a36Sopenharmony_ci }, 7262306a36Sopenharmony_ci { 7362306a36Sopenharmony_ci .name = "bind", 7462306a36Sopenharmony_ci .fn = usbip_bind, 7562306a36Sopenharmony_ci .help = "Bind device to " USBIP_HOST_DRV_NAME ".ko", 7662306a36Sopenharmony_ci .usage = usbip_bind_usage 7762306a36Sopenharmony_ci }, 7862306a36Sopenharmony_ci { 7962306a36Sopenharmony_ci .name = "unbind", 8062306a36Sopenharmony_ci .fn = usbip_unbind, 8162306a36Sopenharmony_ci .help = "Unbind device from " USBIP_HOST_DRV_NAME ".ko", 8262306a36Sopenharmony_ci .usage = usbip_unbind_usage 8362306a36Sopenharmony_ci }, 8462306a36Sopenharmony_ci { 8562306a36Sopenharmony_ci .name = "port", 8662306a36Sopenharmony_ci .fn = usbip_port_show, 8762306a36Sopenharmony_ci .help = "Show imported USB devices", 8862306a36Sopenharmony_ci .usage = NULL 8962306a36Sopenharmony_ci }, 9062306a36Sopenharmony_ci { NULL, NULL, NULL, NULL } 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic int usbip_help(int argc, char *argv[]) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci const struct command *cmd; 9662306a36Sopenharmony_ci int i; 9762306a36Sopenharmony_ci int ret = 0; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (argc > 1 && argv++) { 10062306a36Sopenharmony_ci for (i = 0; cmds[i].name != NULL; i++) 10162306a36Sopenharmony_ci if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) { 10262306a36Sopenharmony_ci cmds[i].usage(); 10362306a36Sopenharmony_ci goto done; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci ret = -1; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci usbip_usage(); 10962306a36Sopenharmony_ci printf("\n"); 11062306a36Sopenharmony_ci for (cmd = cmds; cmd->name != NULL; cmd++) 11162306a36Sopenharmony_ci if (cmd->help != NULL) 11262306a36Sopenharmony_ci printf(" %-10s %s\n", cmd->name, cmd->help); 11362306a36Sopenharmony_ci printf("\n"); 11462306a36Sopenharmony_cidone: 11562306a36Sopenharmony_ci return ret; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic int usbip_version(int argc, char *argv[]) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci (void) argc; 12162306a36Sopenharmony_ci (void) argv; 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci printf(PROGNAME " (%s)\n", usbip_version_string); 12462306a36Sopenharmony_ci return 0; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic int run_command(const struct command *cmd, int argc, char *argv[]) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci dbg("running command: `%s'", cmd->name); 13062306a36Sopenharmony_ci return cmd->fn(argc, argv); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciint main(int argc, char *argv[]) 13462306a36Sopenharmony_ci{ 13562306a36Sopenharmony_ci static const struct option opts[] = { 13662306a36Sopenharmony_ci { "debug", no_argument, NULL, 'd' }, 13762306a36Sopenharmony_ci { "log", no_argument, NULL, 'l' }, 13862306a36Sopenharmony_ci { "tcp-port", required_argument, NULL, 't' }, 13962306a36Sopenharmony_ci { NULL, 0, NULL, 0 } 14062306a36Sopenharmony_ci }; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci char *cmd; 14362306a36Sopenharmony_ci int opt; 14462306a36Sopenharmony_ci int i, rc = -1; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci usbip_use_stderr = 1; 14762306a36Sopenharmony_ci opterr = 0; 14862306a36Sopenharmony_ci for (;;) { 14962306a36Sopenharmony_ci opt = getopt_long(argc, argv, "+dlt:", opts, NULL); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (opt == -1) 15262306a36Sopenharmony_ci break; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci switch (opt) { 15562306a36Sopenharmony_ci case 'd': 15662306a36Sopenharmony_ci usbip_use_debug = 1; 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci case 'l': 15962306a36Sopenharmony_ci usbip_use_syslog = 1; 16062306a36Sopenharmony_ci openlog("", LOG_PID, LOG_USER); 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci case 't': 16362306a36Sopenharmony_ci usbip_setup_port_number(optarg); 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci case '?': 16662306a36Sopenharmony_ci printf("usbip: invalid option\n"); 16762306a36Sopenharmony_ci /* Terminate after printing error */ 16862306a36Sopenharmony_ci /* FALLTHRU */ 16962306a36Sopenharmony_ci default: 17062306a36Sopenharmony_ci usbip_usage(); 17162306a36Sopenharmony_ci goto out; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci } 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci cmd = argv[optind]; 17662306a36Sopenharmony_ci if (cmd) { 17762306a36Sopenharmony_ci for (i = 0; cmds[i].name != NULL; i++) 17862306a36Sopenharmony_ci if (!strcmp(cmds[i].name, cmd)) { 17962306a36Sopenharmony_ci argc -= optind; 18062306a36Sopenharmony_ci argv += optind; 18162306a36Sopenharmony_ci optind = 0; 18262306a36Sopenharmony_ci rc = run_command(&cmds[i], argc, argv); 18362306a36Sopenharmony_ci goto out; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci } 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* invalid command */ 18862306a36Sopenharmony_ci usbip_help(0, NULL); 18962306a36Sopenharmony_ciout: 19062306a36Sopenharmony_ci return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE); 19162306a36Sopenharmony_ci} 192