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