4 * Copyright (c) 2010 Nicholas Marriott <nicm@users.sourceforge.net>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
21 #include <bitstring.h>
27 /* Create an arguments set with no flags. */
29 args_create(int argc
, ...)
35 args
= xcalloc(1, sizeof *args
);
36 if ((args
->flags
= bit_alloc(SCHAR_MAX
)) == NULL
)
37 fatal("bit_alloc failed");
43 args
->argv
= xcalloc(argc
, sizeof *args
->argv
);
46 for (i
= 0; i
< argc
; i
++)
47 args
->argv
[i
] = xstrdup(va_arg(ap
, char *));
53 /* Parse an argv and argc into a new argument set. */
55 args_parse(const char *template, int argc
, char **argv
)
61 args
= xcalloc(1, sizeof *args
);
62 if ((args
->flags
= bit_alloc(SCHAR_MAX
)) == NULL
)
63 fatal("bit_alloc failed");
68 while ((opt
= getopt(argc
, argv
, template)) != -1) {
69 if (opt
< 0 || opt
>= SCHAR_MAX
)
71 if (opt
== '?' || (ptr
= strchr(template, opt
)) == NULL
) {
77 bit_set(args
->flags
, opt
);
79 if (args
->values
[opt
] != NULL
)
80 xfree(args
->values
[opt
]);
81 args
->values
[opt
] = xstrdup(optarg
);
88 args
->argv
= cmd_copy_argv(argc
, argv
);
93 /* Free an arguments set. */
95 args_free(struct args
*args
)
99 cmd_free_argv(args
->argc
, args
->argv
);
101 for (i
= 0; i
< SCHAR_MAX
; i
++) {
102 if (args
->values
[i
] != NULL
)
103 xfree(args
->values
[i
]);
110 /* Print a set of arguments. */
112 args_print(struct args
*args
, char *buf
, size_t len
)
118 /* There must be at least one byte at the start. */
123 /* Process the flags first. */
125 for (i
= 0; i
< SCHAR_MAX
; i
++) {
126 if (!bit_test(args
->flags
, i
) || args
->values
[i
] != NULL
)
129 if (off
== len
- 1) {
139 /* Then the flags with arguments. */
140 for (i
= 0; i
< SCHAR_MAX
; i
++) {
141 if (!bit_test(args
->flags
, i
) || args
->values
[i
] == NULL
)
145 /* snprintf will have zero terminated. */
149 if (strchr(args
->values
[i
], ' ') != NULL
)
153 off
+= xsnprintf(buf
+ off
, len
- off
, "%s-%c %s%s%s",
154 off
!= 0 ? " " : "", i
, quotes
, args
->values
[i
], quotes
);
157 /* And finally the argument vector. */
158 for (i
= 0; i
< args
->argc
; i
++) {
160 /* snprintf will have zero terminated. */
164 if (strchr(args
->argv
[i
], ' ') != NULL
)
168 off
+= xsnprintf(buf
+ off
, len
- off
, "%s%s%s%s",
169 off
!= 0 ? " " : "", quotes
, args
->argv
[i
], quotes
);
175 /* Return if an argument is present. */
177 args_has(struct args
*args
, u_char ch
)
179 return (bit_test(args
->flags
, ch
));
182 /* Set argument value. */
184 args_set(struct args
*args
, u_char ch
, const char *value
)
186 if (args
->values
[ch
] != NULL
)
187 xfree(args
->values
[ch
]);
189 args
->values
[ch
] = xstrdup(value
);
191 args
->values
[ch
] = NULL
;
192 bit_set(args
->flags
, ch
);
195 /* Get argument value. Will be NULL if it isn't present. */
197 args_get(struct args
*args
, u_char ch
)
199 return (args
->values
[ch
]);
202 /* Convert an argument value to a number. */
204 args_strtonum(struct args
*args
,
205 u_char ch
, long long minval
, long long maxval
, char **cause
)
210 if (!args_has(args
, ch
)) {
211 *cause
= xstrdup("missing");
215 ll
= strtonum(args
->values
[ch
], minval
, maxval
, &errstr
);
216 if (errstr
!= NULL
) {
217 *cause
= xstrdup(errstr
);