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