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 37static const char _ngstar[] = "*"; 38 39static int getstring(char **, int, char **); 40static struct netgroup *getnetgroup(char **); 41 42/* 43 * _ng_sl_init(): Initialize a string list 44 */ 45struct 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 */ 66int 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 */ 89void 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 */ 105char * 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 */ 124int 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 */ 164char * 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 181void 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 */ 191static struct netgroup * 192getnetgroup(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 218baddomain: 219 free(ng->ng_user); 220baduser: 221 free(ng->ng_host); 222badhost: 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 */ 231static int 232getstring(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