stringlist.c revision 1.2
1/*	$OpenBSD: stringlist.c,v 1.2 2015/10/01 13:04:42 jsg 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
42static const char _ngstar[] = "*";
43
44static int		getstring(char **, int, char **);
45static struct netgroup	*getnetgroup(char **);
46
47/*
48 * _ng_sl_init(): Initialize a string list
49 */
50struct 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 */
71int
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 */
94void
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 */
110char *
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 */
129int
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 */
169char *
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
186void
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 */
196static struct netgroup *
197getnetgroup(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
223baddomain:
224	if (ng->ng_user)
225		free(ng->ng_user);
226baduser:
227	if (ng->ng_host)
228		free(ng->ng_host);
229badhost:
230	free(ng);
231	return NULL;
232}
233
234/*
235 * getstring(): Get a string delimited by the character, skipping leading and
236 * trailing blanks and advancing the pointer
237 */
238static int
239getstring(char **pp, int del, char **str)
240{
241	char *sp, *ep, *dp;
242
243	/* skip leading blanks */
244	for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
245		continue;
246
247	/* accumulate till delimiter or space */
248	for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
249		continue;
250
251	/* hunt for the delimiter */
252	for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
253		continue;
254
255	if (*dp != del) {
256		*str = NULL;
257		return 0;
258	}
259
260	*pp = ++dp;
261
262	del = (ep - sp) + 1;
263	if (del > 1) {
264		dp = malloc(del);
265		if (dp == NULL)
266			return 0;
267		memcpy(dp, sp, del);
268		dp[del - 1] = '\0';
269	} else
270		dp = NULL;
271
272	*str = dp;
273	return 1;
274}
275