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