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 * 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 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 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 * 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 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 * 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 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 * 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 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