/ stdlib / FreeBSD / getsubopt.c
getsubopt.c
 1  /*-
 2   * Copyright (c) 1990, 1993
 3   *	The Regents of the University of California.  All rights reserved.
 4   *
 5   * Redistribution and use in source and binary forms, with or without
 6   * modification, are permitted provided that the following conditions
 7   * are met:
 8   * 1. Redistributions of source code must retain the above copyright
 9   *    notice, this list of conditions and the following disclaimer.
10   * 2. Redistributions in binary form must reproduce the above copyright
11   *    notice, this list of conditions and the following disclaimer in the
12   *    documentation and/or other materials provided with the distribution.
13   * 4. Neither the name of the University nor the names of its contributors
14   *    may be used to endorse or promote products derived from this software
15   *    without specific prior written permission.
16   *
17   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20   * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27   * SUCH DAMAGE.
28   */
29  
30  #if defined(LIBC_SCCS) && !defined(lint)
31  static char sccsid[] = "@(#)getsubopt.c	8.1 (Berkeley) 6/4/93";
32  #endif /* LIBC_SCCS and not lint */
33  #include <sys/cdefs.h>
34  __FBSDID("$FreeBSD: src/lib/libc/stdlib/getsubopt.c,v 1.7 2007/01/09 00:28:10 imp Exp $");
35  
36  #include <stdlib.h>
37  #include <string.h>
38  
39  /*
40   * The SVID interface to getsubopt provides no way of figuring out which
41   * part of the suboptions list wasn't matched.  This makes error messages
42   * tricky...  The extern variable suboptarg is a pointer to the token
43   * which didn't match.
44   */
45  char *suboptarg;
46  
47  int
48  getsubopt(optionp, tokens, valuep)
49  	char **optionp, **valuep;
50  	char * const *tokens;
51  {
52  	int cnt;
53  	char *p;
54  
55  	suboptarg = *valuep = NULL;
56  
57  	if (!optionp || !*optionp)
58  		return(-1);
59  
60  	/* skip leading white-space, commas */
61  	for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
62  
63  	if (!*p) {
64  		*optionp = p;
65  		return(-1);
66  	}
67  
68  	/* save the start of the token, and skip the rest of the token. */
69  	for (suboptarg = p;
70  	    *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
71  
72  	if (*p) {
73  		/*
74  		 * If there's an equals sign, set the value pointer, and
75  		 * skip over the value part of the token.  Terminate the
76  		 * token.
77  		 */
78  		if (*p == '=') {
79  			*p = '\0';
80  			for (*valuep = ++p;
81  			    *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
82  			if (*p)
83  				*p++ = '\0';
84  		} else
85  			*p++ = '\0';
86  		/* Skip any whitespace or commas after this token. */
87  		for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
88  	}
89  
90  	/* set optionp for next round. */
91  	*optionp = p;
92  
93  	for (cnt = 0; *tokens; ++tokens, ++cnt)
94  		if (!strcmp(suboptarg, *tokens))
95  			return(cnt);
96  	return(-1);
97  }