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 | |