192 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * command structure borrowed from udev4 * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git)5 *6 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>7 * 2005-2007 Takahiro Hirofuchi8 */9 10#include <stdio.h>11#include <stdlib.h>12 13#include <getopt.h>14#include <syslog.h>15 16#include "usbip_common.h"17#include "usbip_network.h"18#include "usbip.h"19 20static int usbip_help(int argc, char *argv[]);21static int usbip_version(int argc, char *argv[]);22 23static const char usbip_version_string[] = PACKAGE_STRING;24 25static const char usbip_usage_string[] =26 "usbip [--debug] [--log] [--tcp-port PORT] [version]\n"27 " [help] <command> <args>\n";28 29static void usbip_usage(void)30{31 printf("usage: %s", usbip_usage_string);32}33 34struct command {35 const char *name;36 int (*fn)(int argc, char *argv[]);37 const char *help;38 void (*usage)(void);39};40 41static const struct command cmds[] = {42 {43 .name = "help",44 .fn = usbip_help,45 .help = NULL,46 .usage = NULL47 },48 {49 .name = "version",50 .fn = usbip_version,51 .help = NULL,52 .usage = NULL53 },54 {55 .name = "attach",56 .fn = usbip_attach,57 .help = "Attach a remote USB device",58 .usage = usbip_attach_usage59 },60 {61 .name = "detach",62 .fn = usbip_detach,63 .help = "Detach a remote USB device",64 .usage = usbip_detach_usage65 },66 {67 .name = "list",68 .fn = usbip_list,69 .help = "List exportable or local USB devices",70 .usage = usbip_list_usage71 },72 {73 .name = "bind",74 .fn = usbip_bind,75 .help = "Bind device to " USBIP_HOST_DRV_NAME ".ko",76 .usage = usbip_bind_usage77 },78 {79 .name = "unbind",80 .fn = usbip_unbind,81 .help = "Unbind device from " USBIP_HOST_DRV_NAME ".ko",82 .usage = usbip_unbind_usage83 },84 {85 .name = "port",86 .fn = usbip_port_show,87 .help = "Show imported USB devices",88 .usage = NULL89 },90 { NULL, NULL, NULL, NULL }91};92 93static int usbip_help(int argc, char *argv[])94{95 const struct command *cmd;96 int i;97 int ret = 0;98 99 if (argc > 1 && argv++) {100 for (i = 0; cmds[i].name != NULL; i++)101 if (!strcmp(cmds[i].name, argv[0]) && cmds[i].usage) {102 cmds[i].usage();103 goto done;104 }105 ret = -1;106 }107 108 usbip_usage();109 printf("\n");110 for (cmd = cmds; cmd->name != NULL; cmd++)111 if (cmd->help != NULL)112 printf(" %-10s %s\n", cmd->name, cmd->help);113 printf("\n");114done:115 return ret;116}117 118static int usbip_version(int argc, char *argv[])119{120 (void) argc;121 (void) argv;122 123 printf(PROGNAME " (%s)\n", usbip_version_string);124 return 0;125}126 127static int run_command(const struct command *cmd, int argc, char *argv[])128{129 dbg("running command: `%s'", cmd->name);130 return cmd->fn(argc, argv);131}132 133int main(int argc, char *argv[])134{135 static const struct option opts[] = {136 { "debug", no_argument, NULL, 'd' },137 { "log", no_argument, NULL, 'l' },138 { "tcp-port", required_argument, NULL, 't' },139 { NULL, 0, NULL, 0 }140 };141 142 char *cmd;143 int opt;144 int i, rc = -1;145 146 usbip_use_stderr = 1;147 opterr = 0;148 for (;;) {149 opt = getopt_long(argc, argv, "+dlt:", opts, NULL);150 151 if (opt == -1)152 break;153 154 switch (opt) {155 case 'd':156 usbip_use_debug = 1;157 break;158 case 'l':159 usbip_use_syslog = 1;160 openlog("", LOG_PID, LOG_USER);161 break;162 case 't':163 usbip_setup_port_number(optarg);164 break;165 case '?':166 printf("usbip: invalid option\n");167 /* Terminate after printing error */168 /* FALLTHRU */169 default:170 usbip_usage();171 goto out;172 }173 }174 175 cmd = argv[optind];176 if (cmd) {177 for (i = 0; cmds[i].name != NULL; i++)178 if (!strcmp(cmds[i].name, cmd)) {179 argc -= optind;180 argv += optind;181 optind = 0;182 rc = run_command(&cmds[i], argc, argv);183 goto out;184 }185 }186 187 /* invalid command */188 usbip_help(0, NULL);189out:190 return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE);191}192