git: a423411a1cad - stable/13 - usbconfig: use getopt(3) for option handling

From: Joerg Wunsch <joerg_at_FreeBSD.org>
Date: Tue, 18 Jan 2022 21:13:38 UTC
The branch stable/13 has been updated by joerg:

URL: https://cgit.FreeBSD.org/src/commit/?id=a423411a1cad45531cf1ad86128bd4790e991f67

commit a423411a1cad45531cf1ad86128bd4790e991f67
Author:     Joerg Wunsch <joerg@FreeBSD.org>
AuthorDate: 2021-12-19 22:49:23 +0000
Commit:     Joerg Wunsch <joerg@FreeBSD.org>
CommitDate: 2022-01-18 21:12:00 +0000

    usbconfig: use getopt(3) for option handling
    
    This makes option handling consistent with other utilities as well as
    Posix rules. By that, it's no longer important whether option name and
    its argument are separated by a space or not, so -d5.3 works the same
    as -d 5.3.
    
    Also, recognize either /dev/ugen or ugen as prefix to the -d argument.
    
    Note that this removes the undocumented feature that allowed to
    specify multiple -d n.m options interleaved with commands referring to
    that particular device in a single run.
    
    (cherry picked from commit ae450e6de96b5ec65f425a52b08dc859576ab8d0)
---
 usr.sbin/usbconfig/usbconfig.8 |   4 +-
 usr.sbin/usbconfig/usbconfig.c | 104 +++++++++++++++++++----------------------
 2 files changed, 52 insertions(+), 56 deletions(-)

diff --git a/usr.sbin/usbconfig/usbconfig.8 b/usr.sbin/usbconfig/usbconfig.8
index 79f070b169c6..ecfd0246eaac 100644
--- a/usr.sbin/usbconfig/usbconfig.8
+++ b/usr.sbin/usbconfig/usbconfig.8
@@ -51,7 +51,9 @@ Limit device range to the given USB device index.
 Should only be used in conjunction with the unit argument.
 .It Fl d Ar [ugen]<unit>.<addr>
 Limit device range to USB devices connected to the given unit and address.
-The unit and address coordinates may be prefixed by the lowercased word "ugen".
+The unit and address coordinates may be prefixed by the lowercased word "ugen",
+or the full path name
+.Pa /dev/ugen .
 .It Fl i Ar interface_index
 Specify interface index as indicated by the command description.
 If this argument is not specified a value of zero will be used for the interface index.
diff --git a/usr.sbin/usbconfig/usbconfig.c b/usr.sbin/usbconfig/usbconfig.c
index c25468fe6da4..a19ff8039186 100644
--- a/usr.sbin/usbconfig/usbconfig.c
+++ b/usr.sbin/usbconfig/usbconfig.c
@@ -31,6 +31,7 @@
 #include <stdint.h>
 #include <err.h>
 #include <string.h>
+#include <unistd.h>
 #include <pwd.h>
 #include <grp.h>
 #include <errno.h>
@@ -100,10 +101,6 @@ struct token {
 };
 
 enum {
-	T_UNIT,
-	T_ADDR,
-	T_UGEN,
-	T_IFACE,
 	T_SET_CONFIG,
 	T_SET_ALT,
 	T_SET_TEMPLATE,
@@ -136,10 +133,6 @@ enum {
 static struct options options;
 
 static const struct token token[] = {
-	{"-u", T_UNIT, 1},
-	{"-a", T_ADDR, 1},
-	{"-d", T_UGEN, 1},
-	{"-i", T_IFACE, 1},
 	{"set_config", T_SET_CONFIG, 1},
 	{"set_alt", T_SET_ALT, 1},
 	{"set_template", T_SET_TEMPLATE, 1},
@@ -563,6 +556,7 @@ main(int argc, char **argv)
 	int addr;
 	int n;
 	int t;
+	int ch;
 
 	if (argc < 1) {
 		usage();
@@ -571,7 +565,53 @@ main(int argc, char **argv)
 	if (pbe == NULL)
 		err(1, "could not access USB backend\n");
 
-	for (n = 1; n != argc; n++) {
+	while ((ch = getopt(argc, argv, "a:d:i:u:")) != -1) {
+		switch (ch) {
+		case 'a':
+			opt->addr = num_id(optarg, "addr");
+			opt->got_addr = 1;
+			break;
+
+		case 'd':
+			if (strncmp(optarg, "ugen", strlen("ugen")) == 0) {
+				ptr = optarg + strlen("ugen");
+			} else if (strncmp(optarg, "/dev/ugen",
+					 strlen("/dev/ugen")) == 0) {
+				ptr = optarg + strlen("/dev/ugen");
+			} else {
+				ptr = optarg;
+			}
+			if ((sscanf(ptr, "%d.%d",
+			    &unit, &addr) != 2) ||
+			    (unit < 0) || (unit > 65535) ||
+			    (addr < 0) || (addr > 65535)) {
+				errx(1, "cannot "
+				    "parse '%s'", optarg);
+			}
+			opt->bus = unit;
+			opt->addr = addr;
+			opt->got_bus = 1;
+			opt->got_addr = 1;
+			break;
+
+		case 'i':
+			opt->iface = num_id(optarg, "iface");
+			opt->got_iface = 1;
+			break;
+
+		case 'u':
+			opt->bus = num_id(optarg, "busnum");
+			opt->got_bus = 1;
+			break;
+
+		default:
+			usage();
+		}
+	}
+	argc -= optind;
+	argv += optind;
+
+	for (n = 0; n != argc; n++) {
 
 		/* get number of additional options */
 		t = (argc - n - 1);
@@ -654,52 +694,6 @@ main(int argc, char **argv)
 			opt->got_show_iface_driver = 1;
 			break;
 
-		case T_UGEN:
-			if (opt->got_any) {
-				/* allow multiple commands on the same line */
-				flush_command(pbe, opt);
-			}
-			ptr = argv[n + 1];
-
-			if ((ptr[0] == 'u') &&
-			    (ptr[1] == 'g') &&
-			    (ptr[2] == 'e') &&
-			    (ptr[3] == 'n'))
-				ptr += 4;
-
-			if ((sscanf(ptr, "%d.%d",
-			    &unit, &addr) != 2) ||
-			    (unit < 0) || (unit > 65535) ||
-			    (addr < 0) || (addr > 65535)) {
-				errx(1, "cannot "
-				    "parse '%s'", argv[n + 1]);
-			}
-			opt->bus = unit;
-			opt->addr = addr;
-			opt->got_bus = 1;
-			opt->got_addr = 1;
-			n++;
-			break;
-
-		case T_UNIT:
-			if (opt->got_any) {
-				/* allow multiple commands on the same line */
-				flush_command(pbe, opt);
-			}
-			opt->bus = num_id(argv[n + 1], "busnum");
-			opt->got_bus = 1;
-			n++;
-			break;
-		case T_ADDR:
-			opt->addr = num_id(argv[n + 1], "addr");
-			opt->got_addr = 1;
-			n++;
-			break;
-		case T_IFACE:
-			opt->iface = num_id(argv[n + 1], "iface");
-			opt->got_iface = 1;
-			n++;
-			break;
 		case T_SET_CONFIG:
 			if (opt->got_set_config)
 				duplicate_option(argv[n]);