1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * command structure borrowed from udev 4 * (git://git.kernel.org/pub/scm/linux/hotplug/udev.git) 5 * 6 * Copyright (C) 2011 matt mooney <mfm@muteddisk.com> 7 * 2005-2007 Takahiro Hirofuchi 8 */ 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 20 static int usbip_help(int argc, char *argv[]); 21 static int usbip_version(int argc, char *argv[]); 22 23 static const char usbip_version_string[] = PACKAGE_STRING; 24 25 static const char usbip_usage_string[] = 26 "usbip [--debug] [--log] [--tcp-port PORT] [version]\n" 27 " [help] <command> <args>\n"; 28 29 static void usbip_usage(void) 30 { 31 printf("usage: %s", usbip_usage_string); 32 } 33 34 struct command { 35 const char *name; 36 int (*fn)(int argc, char *argv[]); 37 const char *help; 38 void (*usage)(void); 39 }; 40 41 static const struct command cmds[] = { 42 { 43 .name = "help", 44 .fn = usbip_help, 45 .help = NULL, 46 .usage = NULL 47 }, 48 { 49 .name = "version", 50 .fn = usbip_version, 51 .help = NULL, 52 .usage = NULL 53 }, 54 { 55 .name = "attach", 56 .fn = usbip_attach, 57 .help = "Attach a remote USB device", 58 .usage = usbip_attach_usage 59 }, 60 { 61 .name = "detach", 62 .fn = usbip_detach, 63 .help = "Detach a remote USB device", 64 .usage = usbip_detach_usage 65 }, 66 { 67 .name = "list", 68 .fn = usbip_list, 69 .help = "List exportable or local USB devices", 70 .usage = usbip_list_usage 71 }, 72 { 73 .name = "bind", 74 .fn = usbip_bind, 75 .help = "Bind device to " USBIP_HOST_DRV_NAME ".ko", 76 .usage = usbip_bind_usage 77 }, 78 { 79 .name = "unbind", 80 .fn = usbip_unbind, 81 .help = "Unbind device from " USBIP_HOST_DRV_NAME ".ko", 82 .usage = usbip_unbind_usage 83 }, 84 { 85 .name = "port", 86 .fn = usbip_port_show, 87 .help = "Show imported USB devices", 88 .usage = NULL 89 }, 90 { NULL, NULL, NULL, NULL } 91 }; 92 93 static 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"); 114 done: 115 return ret; 116 } 117 118 static 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 127 static 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 133 int 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); 189 out: 190 return (rc > -1 ? EXIT_SUCCESS : EXIT_FAILURE); 191 } 192