1*4e4f3181Sskrll /* $NetBSD: subr_optstr.c,v 1.8 2023/04/20 09:04:45 skrll Exp $ */
247d8ee41Sjmmv
347d8ee41Sjmmv /*-
447d8ee41Sjmmv * Copyright (c) 2006 The NetBSD Foundation, Inc.
547d8ee41Sjmmv * All rights reserved.
647d8ee41Sjmmv *
747d8ee41Sjmmv * This code is derived from software contributed to The NetBSD Foundation
847d8ee41Sjmmv * by Julio M. Merino Vidal.
947d8ee41Sjmmv *
1047d8ee41Sjmmv * Redistribution and use in source and binary forms, with or without
1147d8ee41Sjmmv * modification, are permitted provided that the following conditions
1247d8ee41Sjmmv * are met:
1347d8ee41Sjmmv * 1. Redistributions of source code must retain the above copyright
1447d8ee41Sjmmv * notice, this list of conditions and the following disclaimer.
1547d8ee41Sjmmv * 2. Redistributions in binary form must reproduce the above copyright
1647d8ee41Sjmmv * notice, this list of conditions and the following disclaimer in the
1747d8ee41Sjmmv * documentation and/or other materials provided with the distribution.
1847d8ee41Sjmmv *
1947d8ee41Sjmmv * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2047d8ee41Sjmmv * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2147d8ee41Sjmmv * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2247d8ee41Sjmmv * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2347d8ee41Sjmmv * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2447d8ee41Sjmmv * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2547d8ee41Sjmmv * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2647d8ee41Sjmmv * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2747d8ee41Sjmmv * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2847d8ee41Sjmmv * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2947d8ee41Sjmmv * POSSIBILITY OF SUCH DAMAGE.
3047d8ee41Sjmmv */
3147d8ee41Sjmmv
3247d8ee41Sjmmv #include <sys/cdefs.h>
33*4e4f3181Sskrll __KERNEL_RCSID(0, "$NetBSD: subr_optstr.c,v 1.8 2023/04/20 09:04:45 skrll Exp $");
3447d8ee41Sjmmv
3547d8ee41Sjmmv #include <sys/param.h>
3647d8ee41Sjmmv #include <sys/optstr.h>
3747d8ee41Sjmmv
3847d8ee41Sjmmv /* --------------------------------------------------------------------- */
3947d8ee41Sjmmv
4047d8ee41Sjmmv /*
4147d8ee41Sjmmv * Given an options string of the form 'a=b c=d ... y=z' and a key,
4247d8ee41Sjmmv * looks for the given key's value in the string and returns it in buf
434f3d5a9cSthorpej * with a maximum of bufsize bytes. If the key is found, returns true;
4447d8ee41Sjmmv * otherwise FALSE.
4547d8ee41Sjmmv */
46*4e4f3181Sskrll
47*4e4f3181Sskrll
48*4e4f3181Sskrll static bool
optstr_get_pointer(const char * optstr,const char * key,const char ** result)49*4e4f3181Sskrll optstr_get_pointer(const char *optstr, const char *key, const char **result)
5047d8ee41Sjmmv {
510616ec8aSskrll bool found = false;
5247d8ee41Sjmmv
53*4e4f3181Sskrll /* Skip any initial spaces or tabs until we find a word. */
54*4e4f3181Sskrll while (*optstr == ' ' || *optstr == '\t')
5547d8ee41Sjmmv optstr++;
5647d8ee41Sjmmv
5747d8ee41Sjmmv /* Search for the given key within the option string. */
5847d8ee41Sjmmv while (!found && *optstr != '\0') {
59d4cb7c85Sjmmv const char *keyp;
60d4cb7c85Sjmmv
6147d8ee41Sjmmv /* Check if the next word matches the key. */
6247d8ee41Sjmmv keyp = key;
6347d8ee41Sjmmv while (*optstr == *keyp) {
6447d8ee41Sjmmv optstr++;
6547d8ee41Sjmmv keyp++;
6647d8ee41Sjmmv }
6747d8ee41Sjmmv
68d4cb7c85Sjmmv if (*optstr == '=' && *keyp == '\0')
694f3d5a9cSthorpej found = true;
7047d8ee41Sjmmv else {
7147d8ee41Sjmmv /* Key not found; skip until next space. */
7247d8ee41Sjmmv while (*optstr != ' ' && *optstr != '\0')
7347d8ee41Sjmmv optstr++;
7447d8ee41Sjmmv
7547d8ee41Sjmmv /* And now skip until next word. */
765fc637a5Smartin while (*optstr == ' ')
7747d8ee41Sjmmv optstr++;
7847d8ee41Sjmmv }
7947d8ee41Sjmmv }
8047d8ee41Sjmmv
8147d8ee41Sjmmv if (found) {
8247d8ee41Sjmmv optstr++; /* Skip '='. */
83*4e4f3181Sskrll *result = optstr;
8447d8ee41Sjmmv }
8547d8ee41Sjmmv
8647d8ee41Sjmmv return found;
8747d8ee41Sjmmv }
88*4e4f3181Sskrll
89*4e4f3181Sskrll bool
optstr_get(const char * optstr,const char * key,char * buf,size_t bufsize)90*4e4f3181Sskrll optstr_get(const char *optstr, const char *key, char *buf, size_t bufsize)
91*4e4f3181Sskrll {
92*4e4f3181Sskrll const char *data;
93*4e4f3181Sskrll bool found = optstr_get_pointer(optstr, key, &data);
94*4e4f3181Sskrll
95*4e4f3181Sskrll /* If the key was found; copy its value to the target buffer. */
96*4e4f3181Sskrll if (found) {
97*4e4f3181Sskrll const char *lastbuf = buf + (bufsize - 1);
98*4e4f3181Sskrll
99*4e4f3181Sskrll while (buf != lastbuf && *data != ' ' && *data != '\0')
100*4e4f3181Sskrll *buf++ = *data++;
101*4e4f3181Sskrll *buf = '\0';
102*4e4f3181Sskrll }
103*4e4f3181Sskrll return found;
104*4e4f3181Sskrll }
105*4e4f3181Sskrll
106*4e4f3181Sskrll
107*4e4f3181Sskrll bool
optstr_get_string(const char * optstr,const char * key,const char ** result)108*4e4f3181Sskrll optstr_get_string(const char *optstr, const char *key, const char **result)
109*4e4f3181Sskrll {
110*4e4f3181Sskrll const char *data;
111*4e4f3181Sskrll const bool found = optstr_get_pointer(optstr, key, &data);
112*4e4f3181Sskrll
113*4e4f3181Sskrll /* If the key was found; copy its value to the target buffer. */
114*4e4f3181Sskrll if (found) {
115*4e4f3181Sskrll *result = data;
116*4e4f3181Sskrll }
117*4e4f3181Sskrll return found;
118*4e4f3181Sskrll }
119*4e4f3181Sskrll
120*4e4f3181Sskrll bool
optstr_get_number(const char * optstr,const char * key,unsigned long * result)121*4e4f3181Sskrll optstr_get_number(const char *optstr, const char *key, unsigned long *result)
122*4e4f3181Sskrll {
123*4e4f3181Sskrll const char *data;
124*4e4f3181Sskrll const bool found = optstr_get_pointer(optstr, key, &data);
125*4e4f3181Sskrll
126*4e4f3181Sskrll /* If the key was found; copy its value to the target buffer. */
127*4e4f3181Sskrll if (found) {
128*4e4f3181Sskrll char *ep;
129*4e4f3181Sskrll const unsigned long ulval = strtoul(data, &ep, 10);
130*4e4f3181Sskrll if (ep == data)
131*4e4f3181Sskrll return false;
132*4e4f3181Sskrll *result = ulval;
133*4e4f3181Sskrll return true;
134*4e4f3181Sskrll }
135*4e4f3181Sskrll return false;
136*4e4f3181Sskrll }
137*4e4f3181Sskrll
138*4e4f3181Sskrll bool
optstr_get_number_hex(const char * optstr,const char * key,unsigned long * result)139*4e4f3181Sskrll optstr_get_number_hex(const char *optstr, const char *key,
140*4e4f3181Sskrll unsigned long *result)
141*4e4f3181Sskrll {
142*4e4f3181Sskrll const char *data;
143*4e4f3181Sskrll const bool found = optstr_get_pointer(optstr, key, &data);
144*4e4f3181Sskrll
145*4e4f3181Sskrll /* If the key was found; copy its value to the target buffer. */
146*4e4f3181Sskrll if (found) {
147*4e4f3181Sskrll char *ep;
148*4e4f3181Sskrll const unsigned long ulval = strtoul(data, &ep, 16);
149*4e4f3181Sskrll if (ep == data)
150*4e4f3181Sskrll return false;
151*4e4f3181Sskrll *result = ulval;
152*4e4f3181Sskrll return true;
153*4e4f3181Sskrll }
154*4e4f3181Sskrll return false;
155*4e4f3181Sskrll }
156*4e4f3181Sskrll
157*4e4f3181Sskrll bool
optstr_get_number_binary(const char * optstr,const char * key,unsigned long * result)158*4e4f3181Sskrll optstr_get_number_binary(const char *optstr, const char *key,
159*4e4f3181Sskrll unsigned long *result)
160*4e4f3181Sskrll {
161*4e4f3181Sskrll const char *data;
162*4e4f3181Sskrll const bool found = optstr_get_pointer(optstr, key, &data);
163*4e4f3181Sskrll
164*4e4f3181Sskrll /* If the key was found; copy its value to the target buffer. */
165*4e4f3181Sskrll if (found) {
166*4e4f3181Sskrll char *ep;
167*4e4f3181Sskrll const unsigned long ulval = strtoul(data, &ep, 2);
168*4e4f3181Sskrll if (ep == data)
169*4e4f3181Sskrll return false;
170*4e4f3181Sskrll *result = ulval;
171*4e4f3181Sskrll return true;
172*4e4f3181Sskrll }
173*4e4f3181Sskrll return false;
174*4e4f3181Sskrll }
175*4e4f3181Sskrll
176*4e4f3181Sskrll
177*4e4f3181Sskrll #if NETHER > 0
178*4e4f3181Sskrll bool
optstr_get_macaddr(const char * optstr,const char * key,uint8_t result[ETHER_ADDR_LEN])179*4e4f3181Sskrll optstr_get_macaddr(const char *optstr, const char *key,
180*4e4f3181Sskrll uint8_t result[ETHER_ADDR_LEN])
181*4e4f3181Sskrll {
182*4e4f3181Sskrll const char *data;
183*4e4f3181Sskrll const bool found = optstr_get_pointer(optstr, key, &data);
184*4e4f3181Sskrll
185*4e4f3181Sskrll /* If the key was found; copy its value to the target buffer. */
186*4e4f3181Sskrll if (found) {
187*4e4f3181Sskrll uint8_t temp[ETHER_ADDR_LEN];
188*4e4f3181Sskrll int error = ether_aton_r(temp, sizeof(temp), data);
189*4e4f3181Sskrll if (error)
190*4e4f3181Sskrll return false;
191*4e4f3181Sskrll memcpy(result, temp, sizeof(temp));
192*4e4f3181Sskrll }
193*4e4f3181Sskrll return found;
194*4e4f3181Sskrll }
195*4e4f3181Sskrll #endif
196