GNU Linux-libre 5.13.14-gnu1
[releases.git] / tools / usb / usbip / src / usbip.c
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 }