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