xref: /freebsd/sys/contrib/rdma/krping/getopt.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
1 /*
2  * lifted from fs/ncpfs/getopt.c
3  *
4  */
5 #include <sys/cdefs.h>
6 __FBSDID("$FreeBSD$");
7 
8 #include <sys/ctype.h>
9 #include <sys/param.h>
10 #include <sys/libkern.h>
11 #include "getopt.h"
12 
13 /**
14  *	krping_getopt - option parser
15  *	@caller: name of the caller, for error messages
16  *	@options: the options string
17  *	@opts: an array of &struct option entries controlling parser operations
18  *	@optopt: output; will contain the current option
19  *	@optarg: output; will contain the value (if one exists)
20  *	@flag: output; may be NULL; should point to a long for or'ing flags
21  *	@value: output; may be NULL; will be overwritten with the integer value
22  *		of the current argument.
23  *
24  *	Helper to parse options on the format used by mount ("a=b,c=d,e,f").
25  *	Returns opts->val if a matching entry in the 'opts' array is found,
26  *	0 when no more tokens are found, -1 if an error is encountered.
27  */
28 int krping_getopt(const char *caller, char **options,
29 		  const struct krping_option *opts, char **optopt,
30 		  char **optarg, unsigned long *value)
31 {
32 	char *token;
33 	char *val;
34 
35 	do {
36 		if ((token = strsep(options, ",")) == NULL)
37 			return 0;
38 	} while (*token == '\0');
39 	if (optopt)
40 		*optopt = token;
41 
42 	if ((val = strchr (token, '=')) != NULL) {
43 		*val++ = 0;
44 	}
45 	*optarg = val;
46 	for (; opts->name; opts++) {
47 		if (!strcmp(opts->name, token)) {
48 			if (!val) {
49 				if (opts->has_arg & OPT_NOPARAM) {
50 					return opts->val;
51 				}
52 				printf("%s: the %s option requires "
53 				       "an argument\n", caller, token);
54 				return -EINVAL;
55 			}
56 			if (opts->has_arg & OPT_INT) {
57 				char* v;
58 
59 				*value = strtoul(val, &v, 0);
60 				if (!*v) {
61 					return opts->val;
62 				}
63 				printf("%s: invalid numeric value "
64 				       "in %s=%s\n", caller, token, val);
65 				return -EDOM;
66 			}
67 			if (opts->has_arg & OPT_STRING) {
68 				return opts->val;
69 			}
70 			printf("%s: unexpected argument %s to the "
71 			       "%s option\n", caller, val, token);
72 			return -EINVAL;
73 		}
74 	}
75 	printf("%s: Unrecognized option %s\n", caller, token);
76 	return -EOPNOTSUPP;
77 }
78