xref: /openbsd-src/usr.sbin/netgroup_mkdb/stringlist.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: stringlist.c,v 1.3 2015/12/19 20:37:11 mmcc Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Christos Zoulas
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by Christos Zoulas.
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #include <sys/types.h>
35 #include <stdio.h>
36 #include <netgroup.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include <ctype.h>
40 #include "stringlist.h"
41 
42 static const char _ngstar[] = "*";
43 
44 static int		getstring(char **, int, char **);
45 static struct netgroup	*getnetgroup(char **);
46 
47 /*
48  * _ng_sl_init(): Initialize a string list
49  */
50 struct stringlist *
51 _ng_sl_init(void)
52 {
53 	struct stringlist *sl = malloc(sizeof(struct stringlist));
54 	if (sl == NULL)
55 		return NULL;
56 
57 	sl->sl_cur = 0;
58 	sl->sl_max = 20;
59 	sl->sl_str = calloc(sl->sl_max, sizeof(char *));
60 	if (sl->sl_str == NULL) {
61 		free(sl);
62 		return NULL;
63 	}
64 	return sl;
65 }
66 
67 
68 /*
69  * _ng_sl_add(): Add an item to the string list
70  */
71 int
72 _ng_sl_add(struct stringlist *sl, char *name)
73 {
74 	if (sl->sl_cur == sl->sl_max - 1) {
75 		char **slstr;
76 
77 		sl->sl_max += 20;
78 		slstr = reallocarray(sl->sl_str, sl->sl_max, sizeof(char *));
79 		if (slstr == NULL) {
80 			free(sl->sl_str);
81 			sl->sl_str = NULL;
82 			return -1;
83 		}
84 		sl->sl_str = slstr;
85 	}
86 	sl->sl_str[sl->sl_cur++] = name;
87 	return 0;
88 }
89 
90 
91 /*
92  * _ng_sl_free(): Free a stringlist
93  */
94 void
95 _ng_sl_free(struct stringlist *sl, int all)
96 {
97 	size_t	i;
98 
99 	if (all)
100 		for (i = 0; i < sl->sl_cur; i++)
101 			free(sl->sl_str[i]);
102 	free(sl->sl_str);
103 	free(sl);
104 }
105 
106 
107 /*
108  * sl_find(): Find a name in the string list
109  */
110 char *
111 _ng_sl_find(struct stringlist *sl, char *name)
112 {
113 	size_t	i;
114 
115 	for (i = 0; i < sl->sl_cur; i++)
116 		if (strcmp(sl->sl_str[i], name) == 0)
117 			return sl->sl_str[i];
118 
119 	return NULL;
120 }
121 
122 /*
123  * _ng_parse(): Parse a line and return: _NG_ERROR: Syntax Error _NG_NONE:
124  * line was empty or a comment _NG_GROUP: line had a netgroup definition,
125  * returned in ng _NG_NAME:  line had a netgroup name, returned in name
126  *
127  * Public since used by netgroup_mkdb
128  */
129 int
130 _ng_parse(char **p, char **name, struct netgroup **ng)
131 {
132 	while (**p) {
133 		if (**p == '#')
134 			/* comment */
135 			return _NG_NONE;
136 
137 		while (**p && _NG_ISSPACE(**p))
138 			/* skipblank */
139 			(*p)++;
140 
141 		if (**p == '(') {
142 			if ((*ng = getnetgroup(p)) == NULL)
143 				return _NG_ERROR;
144 			return _NG_GROUP;
145 		} else {
146 			char	*np;
147 			int	i;
148 
149 			for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++)
150 				continue;
151 			if (np != *p) {
152 				i = (*p - np) + 1;
153 				*name = malloc(i);
154 				if (*name == NULL)
155 					return _NG_ERROR;
156 				memcpy(*name, np, i);
157 				(*name)[i - 1] = '\0';
158 				return _NG_NAME;
159 			}
160 		}
161 	}
162 	return _NG_NONE;
163 }
164 
165 /*
166  * _ng_makekey(): Make a key from the two names given. The key is of the form
167  * <name1>.<name2> Names strings are replaced with * if they are empty;
168  */
169 char *
170 _ng_makekey(const char *s1, const char *s2, size_t len)
171 {
172 	char *buf = malloc(len);
173 	int ret;
174 
175 	if (buf == NULL)
176 		return NULL;
177 	ret = snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2));
178 	if (ret < 0 || ret >= len) {
179 		free(buf);
180 		return NULL;
181 	}
182 
183 	return buf;
184 }
185 
186 void
187 _ng_print(char *buf, size_t len, const struct netgroup *ng)
188 {
189 	(void) snprintf(buf, len, "(%s,%s,%s)", _NG_EMPTY(ng->ng_host),
190 	    _NG_EMPTY(ng->ng_user), _NG_EMPTY(ng->ng_domain));
191 }
192 
193 /*
194  * getnetgroup(): Parse a netgroup, and advance the pointer
195  */
196 static struct netgroup *
197 getnetgroup(char **pp)
198 {
199 	struct netgroup *ng = malloc(sizeof(struct netgroup));
200 
201 	if (ng == NULL)
202 		return NULL;
203 
204 	(*pp)++;	/* skip '(' */
205 	if (!getstring(pp, ',', &ng->ng_host))
206 		goto badhost;
207 
208 	if (!getstring(pp, ',', &ng->ng_user))
209 		goto baduser;
210 
211 	if (!getstring(pp, ')', &ng->ng_domain))
212 		goto baddomain;
213 
214 #ifdef DEBUG_NG
215 	{
216 		char buf[1024];
217 		_ng_print(buf, sizeof(buf), ng);
218 		fprintf(stderr, "netgroup %s\n", buf);
219 	}
220 #endif
221 	return ng;
222 
223 baddomain:
224 	free(ng->ng_user);
225 baduser:
226 	free(ng->ng_host);
227 badhost:
228 	free(ng);
229 	return NULL;
230 }
231 
232 /*
233  * getstring(): Get a string delimited by the character, skipping leading and
234  * trailing blanks and advancing the pointer
235  */
236 static int
237 getstring(char **pp, int del, char **str)
238 {
239 	char *sp, *ep, *dp;
240 
241 	/* skip leading blanks */
242 	for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
243 		continue;
244 
245 	/* accumulate till delimiter or space */
246 	for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
247 		continue;
248 
249 	/* hunt for the delimiter */
250 	for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
251 		continue;
252 
253 	if (*dp != del) {
254 		*str = NULL;
255 		return 0;
256 	}
257 
258 	*pp = ++dp;
259 
260 	del = (ep - sp) + 1;
261 	if (del > 1) {
262 		dp = malloc(del);
263 		if (dp == NULL)
264 			return 0;
265 		memcpy(dp, sp, del);
266 		dp[del - 1] = '\0';
267 	} else
268 		dp = NULL;
269 
270 	*str = dp;
271 	return 1;
272 }
273