xref: /netbsd-src/lib/libc/stdlib/getsubopt.c (revision 48875230b6c3331b32b9c7bfc518969d58c388e0)
1*48875230Schristos /*	$NetBSD: getsubopt.c,v 1.10 2018/08/30 12:06:06 christos Exp $	*/
2edf59accSthorpej 
378ef0c30Sperry /*-
478ef0c30Sperry  * Copyright (c) 1990, 1993
578ef0c30Sperry  *	The Regents of the University of California.  All rights reserved.
678ef0c30Sperry  *
778ef0c30Sperry  * Redistribution and use in source and binary forms, with or without
878ef0c30Sperry  * modification, are permitted provided that the following conditions
978ef0c30Sperry  * are met:
1078ef0c30Sperry  * 1. Redistributions of source code must retain the above copyright
1178ef0c30Sperry  *    notice, this list of conditions and the following disclaimer.
1278ef0c30Sperry  * 2. Redistributions in binary form must reproduce the above copyright
1378ef0c30Sperry  *    notice, this list of conditions and the following disclaimer in the
1478ef0c30Sperry  *    documentation and/or other materials provided with the distribution.
15eb7c1594Sagc  * 3. Neither the name of the University nor the names of its contributors
1678ef0c30Sperry  *    may be used to endorse or promote products derived from this software
1778ef0c30Sperry  *    without specific prior written permission.
1878ef0c30Sperry  *
1978ef0c30Sperry  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2078ef0c30Sperry  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2178ef0c30Sperry  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2278ef0c30Sperry  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2378ef0c30Sperry  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2478ef0c30Sperry  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2578ef0c30Sperry  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2678ef0c30Sperry  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2778ef0c30Sperry  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2878ef0c30Sperry  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2978ef0c30Sperry  * SUCH DAMAGE.
3078ef0c30Sperry  */
3178ef0c30Sperry 
32*48875230Schristos #if HAVE_NBTOOL_CONFIG_H
33*48875230Schristos #include "nbtool_config.h"
34*48875230Schristos #endif
35*48875230Schristos 
36edf59accSthorpej #include <sys/cdefs.h>
37edf59accSthorpej #if defined(LIBC_SCCS) && !defined(lint)
38edf59accSthorpej #if 0
3978ef0c30Sperry static char sccsid[] = "@(#)getsubopt.c	8.1 (Berkeley) 6/4/93";
40edf59accSthorpej #else
41*48875230Schristos __RCSID("$NetBSD: getsubopt.c,v 1.10 2018/08/30 12:06:06 christos Exp $");
42edf59accSthorpej #endif
43edf59accSthorpej #endif /* LIBC_SCCS and not lint */
4478ef0c30Sperry 
45f379d2c8Skleink #include "namespace.h"
46f379d2c8Skleink 
47b48252f3Slukem #include <assert.h>
4878ef0c30Sperry #include <stdlib.h>
49163c89fbSthorpej #include <string.h>
50163c89fbSthorpej #include <unistd.h>
5178ef0c30Sperry 
52f379d2c8Skleink #ifdef __weak_alias
__weak_alias(getsubopt,_getsubopt)53f379d2c8Skleink __weak_alias(getsubopt,_getsubopt)
54f379d2c8Skleink #endif
55f379d2c8Skleink 
5678ef0c30Sperry /*
5778ef0c30Sperry  * The SVID interface to getsubopt provides no way of figuring out which
5878ef0c30Sperry  * part of the suboptions list wasn't matched.  This makes error messages
5978ef0c30Sperry  * tricky...  The extern variable suboptarg is a pointer to the token
6078ef0c30Sperry  * which didn't match.
6178ef0c30Sperry  */
6278ef0c30Sperry char *suboptarg;
6378ef0c30Sperry 
64edf59accSthorpej int
659e66e6d7Sabs getsubopt(char **optionp, char * const *tokens, char **valuep)
6678ef0c30Sperry {
67c8bafd62Sperry 	int cnt;
68c8bafd62Sperry 	char *p;
6978ef0c30Sperry 
70b48252f3Slukem 	_DIAGASSERT(tokens != NULL);
71f379d2c8Skleink 	_DIAGASSERT(valuep != NULL);
72b48252f3Slukem 	/* optionp is tested below */
73b48252f3Slukem 
7478ef0c30Sperry 	suboptarg = *valuep = NULL;
7578ef0c30Sperry 
7678ef0c30Sperry 	if (!optionp || !*optionp)
7778ef0c30Sperry 		return(-1);
7878ef0c30Sperry 
7978ef0c30Sperry 	/* skip leading white-space, commas */
8078ef0c30Sperry 	for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
8178ef0c30Sperry 
8278ef0c30Sperry 	if (!*p) {
8378ef0c30Sperry 		*optionp = p;
8478ef0c30Sperry 		return(-1);
8578ef0c30Sperry 	}
8678ef0c30Sperry 
8778ef0c30Sperry 	/* save the start of the token, and skip the rest of the token. */
8878ef0c30Sperry 	for (suboptarg = p;
8978ef0c30Sperry 	    *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
9078ef0c30Sperry 
9178ef0c30Sperry 	if (*p) {
9278ef0c30Sperry 		/*
9378ef0c30Sperry 		 * If there's an equals sign, set the value pointer, and
9478ef0c30Sperry 		 * skip over the value part of the token.  Terminate the
9578ef0c30Sperry 		 * token.
9678ef0c30Sperry 		 */
9778ef0c30Sperry 		if (*p == '=') {
9878ef0c30Sperry 			*p = '\0';
9978ef0c30Sperry 			for (*valuep = ++p;
10078ef0c30Sperry 			    *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
10178ef0c30Sperry 			if (*p)
10278ef0c30Sperry 				*p++ = '\0';
10378ef0c30Sperry 		} else
10478ef0c30Sperry 			*p++ = '\0';
10578ef0c30Sperry 		/* Skip any whitespace or commas after this token. */
10678ef0c30Sperry 		for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
10778ef0c30Sperry 	}
10878ef0c30Sperry 
10978ef0c30Sperry 	/* set optionp for next round. */
11078ef0c30Sperry 	*optionp = p;
11178ef0c30Sperry 
11278ef0c30Sperry 	for (cnt = 0; *tokens; ++tokens, ++cnt)
11378ef0c30Sperry 		if (!strcmp(suboptarg, *tokens))
11478ef0c30Sperry 			return(cnt);
11578ef0c30Sperry 	return(-1);
11678ef0c30Sperry }
117