1 1.13 christos /* $NetBSD: getservent_r.c,v 1.13 2022/03/12 17:31:39 christos Exp $ */ 2 1.1 christos 3 1.1 christos /* 4 1.1 christos * Copyright (c) 1983, 1993 5 1.1 christos * The Regents of the University of California. All rights reserved. 6 1.1 christos * 7 1.1 christos * Redistribution and use in source and binary forms, with or without 8 1.1 christos * modification, are permitted provided that the following conditions 9 1.1 christos * are met: 10 1.1 christos * 1. Redistributions of source code must retain the above copyright 11 1.1 christos * notice, this list of conditions and the following disclaimer. 12 1.1 christos * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 christos * notice, this list of conditions and the following disclaimer in the 14 1.1 christos * documentation and/or other materials provided with the distribution. 15 1.1 christos * 3. Neither the name of the University nor the names of its contributors 16 1.1 christos * may be used to endorse or promote products derived from this software 17 1.1 christos * without specific prior written permission. 18 1.1 christos * 19 1.1 christos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 christos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 christos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 christos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 christos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 christos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 christos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 christos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 christos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 christos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 christos * SUCH DAMAGE. 30 1.1 christos */ 31 1.1 christos 32 1.1 christos #include <sys/cdefs.h> 33 1.1 christos #if defined(LIBC_SCCS) && !defined(lint) 34 1.1 christos #if 0 35 1.1 christos static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; 36 1.1 christos #else 37 1.13 christos __RCSID("$NetBSD: getservent_r.c,v 1.13 2022/03/12 17:31:39 christos Exp $"); 38 1.1 christos #endif 39 1.1 christos #endif /* LIBC_SCCS and not lint */ 40 1.1 christos 41 1.1 christos #include "namespace.h" 42 1.10 joerg #include <cdbr.h> 43 1.10 joerg #include <errno.h> 44 1.10 joerg #include <fcntl.h> 45 1.1 christos #include <netdb.h> 46 1.1 christos #include <stdio.h> 47 1.10 joerg #include <stdlib.h> 48 1.1 christos #include <string.h> 49 1.1 christos 50 1.5 kleink #include "servent.h" 51 1.5 kleink 52 1.1 christos #ifdef __weak_alias 53 1.1 christos __weak_alias(endservent_r,_endservent_r) 54 1.1 christos __weak_alias(getservent_r,_getservent_r) 55 1.1 christos __weak_alias(setservent_r,_setservent_r) 56 1.1 christos #endif 57 1.1 christos 58 1.6 christos int 59 1.6 christos _servent_open(struct servent_data *sd) 60 1.1 christos { 61 1.10 joerg if (sd->flags & (_SV_CDB | _SV_PLAINFILE)) { 62 1.10 joerg sd->flags |= _SV_FIRST; 63 1.10 joerg return 0; 64 1.10 joerg } 65 1.10 joerg 66 1.10 joerg free(sd->line); 67 1.10 joerg sd->line = NULL; 68 1.10 joerg free(sd->cdb_buf); 69 1.10 joerg sd->cdb_buf = NULL; 70 1.10 joerg sd->cdb_buf_len = 0; 71 1.10 joerg free(sd->aliases); 72 1.10 joerg sd->aliases = NULL; 73 1.10 joerg sd->maxaliases = 0; 74 1.8 christos sd->flags |= _SV_FIRST; 75 1.10 joerg 76 1.10 joerg sd->cdb = cdbr_open(_PATH_SERVICES_CDB, CDBR_DEFAULT); 77 1.10 joerg if (sd->cdb != NULL) { 78 1.10 joerg sd->flags |= _SV_CDB; 79 1.10 joerg return 0; 80 1.10 joerg } 81 1.10 joerg 82 1.11 christos sd->plainfile = fopen(_PATH_SERVICES, "re"); 83 1.10 joerg if (sd->plainfile != NULL) { 84 1.10 joerg sd->flags |= _SV_PLAINFILE; 85 1.10 joerg return 0; 86 1.6 christos } 87 1.10 joerg return -1; 88 1.1 christos } 89 1.1 christos 90 1.1 christos void 91 1.6 christos _servent_close(struct servent_data *sd) 92 1.1 christos { 93 1.10 joerg if (sd->flags & _SV_CDB) { 94 1.10 joerg cdbr_close(sd->cdb); 95 1.10 joerg sd->cdb = NULL; 96 1.10 joerg sd->flags &= ~_SV_CDB; 97 1.10 joerg } 98 1.10 joerg 99 1.10 joerg if (sd->flags & _SV_PLAINFILE) { 100 1.10 joerg (void)fclose(sd->plainfile); 101 1.10 joerg sd->plainfile = NULL; 102 1.10 joerg sd->flags &= ~_SV_PLAINFILE; 103 1.1 christos } 104 1.6 christos sd->flags &= ~_SV_STAYOPEN; 105 1.6 christos } 106 1.6 christos 107 1.6 christos 108 1.6 christos int 109 1.6 christos _servent_getline(struct servent_data *sd) 110 1.6 christos { 111 1.9 christos 112 1.10 joerg if (sd->flags & _SV_CDB) 113 1.10 joerg return -1; 114 1.10 joerg 115 1.10 joerg if ((sd->flags & _SV_PLAINFILE) == 0) 116 1.9 christos return -1; 117 1.9 christos 118 1.10 joerg free(sd->line); 119 1.10 joerg sd->line = NULL; 120 1.10 joerg 121 1.10 joerg if (sd->flags & _SV_FIRST) { 122 1.10 joerg (void)rewind((FILE *)sd->plainfile); 123 1.10 joerg sd->flags &= ~_SV_FIRST; 124 1.6 christos } 125 1.10 joerg sd->line = fparseln(sd->plainfile, NULL, NULL, NULL, 126 1.10 joerg FPARSELN_UNESCALL); 127 1.6 christos return sd->line == NULL ? -1 : 0; 128 1.1 christos } 129 1.1 christos 130 1.1 christos struct servent * 131 1.6 christos _servent_parseline(struct servent_data *sd, struct servent *sp) 132 1.1 christos { 133 1.1 christos size_t i = 0; 134 1.1 christos int oerrno; 135 1.6 christos char *p, *cp, **q; 136 1.1 christos 137 1.6 christos if (sd->line == NULL) 138 1.1 christos return NULL; 139 1.1 christos 140 1.6 christos sp->s_name = p = sd->line; 141 1.6 christos p = strpbrk(p, " \t"); 142 1.6 christos if (p == NULL) 143 1.6 christos return NULL; 144 1.6 christos *p++ = '\0'; 145 1.6 christos while (*p == ' ' || *p == '\t') 146 1.6 christos p++; 147 1.6 christos cp = strpbrk(p, ",/"); 148 1.6 christos if (cp == NULL) 149 1.6 christos return NULL; 150 1.6 christos *cp++ = '\0'; 151 1.6 christos sp->s_port = htons((u_short)atoi(p)); 152 1.6 christos sp->s_proto = cp; 153 1.6 christos if (sd->aliases == NULL) { 154 1.6 christos sd->maxaliases = 10; 155 1.10 joerg sd->aliases = calloc(sd->maxaliases, sizeof(*sd->aliases)); 156 1.6 christos if (sd->aliases == NULL) { 157 1.6 christos oerrno = errno; 158 1.6 christos endservent_r(sd); 159 1.6 christos errno = oerrno; 160 1.1 christos return NULL; 161 1.6 christos } 162 1.6 christos } 163 1.10 joerg sp->s_aliases = sd->aliases; 164 1.6 christos cp = strpbrk(cp, " \t"); 165 1.6 christos if (cp != NULL) 166 1.6 christos *cp++ = '\0'; 167 1.6 christos while (cp && *cp) { 168 1.6 christos if (*cp == ' ' || *cp == '\t') { 169 1.6 christos cp++; 170 1.1 christos continue; 171 1.6 christos } 172 1.6 christos if (i == sd->maxaliases - 2) { 173 1.6 christos sd->maxaliases *= 2; 174 1.10 joerg q = realloc(sd->aliases, sd->maxaliases * sizeof(*q)); 175 1.6 christos if (q == NULL) { 176 1.1 christos oerrno = errno; 177 1.1 christos endservent_r(sd); 178 1.1 christos errno = oerrno; 179 1.1 christos return NULL; 180 1.1 christos } 181 1.6 christos sp->s_aliases = sd->aliases = q; 182 1.1 christos } 183 1.10 joerg sp->s_aliases[i++] = cp; 184 1.1 christos cp = strpbrk(cp, " \t"); 185 1.1 christos if (cp != NULL) 186 1.1 christos *cp++ = '\0'; 187 1.6 christos } 188 1.10 joerg sp->s_aliases[i] = NULL; 189 1.6 christos return sp; 190 1.6 christos } 191 1.6 christos 192 1.6 christos void 193 1.6 christos setservent_r(int f, struct servent_data *sd) 194 1.6 christos { 195 1.6 christos (void)_servent_open(sd); 196 1.6 christos sd->flags |= f ? _SV_STAYOPEN : 0; 197 1.6 christos } 198 1.6 christos 199 1.6 christos void 200 1.6 christos endservent_r(struct servent_data *sd) 201 1.6 christos { 202 1.6 christos _servent_close(sd); 203 1.10 joerg free(sd->aliases); 204 1.10 joerg sd->aliases = NULL; 205 1.10 joerg sd->maxaliases = 0; 206 1.10 joerg free(sd->line); 207 1.10 joerg sd->line = NULL; 208 1.10 joerg free(sd->cdb_buf); 209 1.10 joerg sd->cdb_buf = NULL; 210 1.10 joerg sd->cdb_buf_len = 0; 211 1.6 christos } 212 1.6 christos 213 1.6 christos struct servent * 214 1.6 christos getservent_r(struct servent *sp, struct servent_data *sd) 215 1.6 christos { 216 1.10 joerg 217 1.10 joerg if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0 && 218 1.10 joerg _servent_open(sd) == -1) 219 1.6 christos return NULL; 220 1.6 christos 221 1.10 joerg if (sd->flags & _SV_CDB) { 222 1.10 joerg const void *data; 223 1.10 joerg size_t len; 224 1.10 joerg 225 1.10 joerg if (sd->flags & _SV_FIRST) { 226 1.10 joerg sd->cdb_index = 0; 227 1.10 joerg sd->flags &= ~_SV_FIRST; 228 1.10 joerg } 229 1.10 joerg 230 1.10 joerg if (cdbr_get(sd->cdb, sd->cdb_index, &data, &len)) 231 1.6 christos return NULL; 232 1.10 joerg ++sd->cdb_index; 233 1.10 joerg return _servent_parsedb(sd, sp, data, len); 234 1.10 joerg } 235 1.10 joerg if (sd->flags & _SV_PLAINFILE) { 236 1.10 joerg for (;;) { 237 1.10 joerg if (_servent_getline(sd) == -1) 238 1.10 joerg return NULL; 239 1.10 joerg if (_servent_parseline(sd, sp) == NULL) 240 1.10 joerg continue; 241 1.10 joerg return sp; 242 1.10 joerg } 243 1.10 joerg } 244 1.10 joerg return NULL; 245 1.10 joerg } 246 1.10 joerg 247 1.10 joerg struct servent * 248 1.10 joerg _servent_parsedb(struct servent_data *sd, struct servent *sp, 249 1.10 joerg const uint8_t *data, size_t len) 250 1.10 joerg { 251 1.10 joerg char **q; 252 1.10 joerg size_t i; 253 1.10 joerg int oerrno; 254 1.10 joerg 255 1.10 joerg if ((sd->flags & _SV_STAYOPEN) == 0) { 256 1.10 joerg if (len > sd->cdb_buf_len) { 257 1.10 joerg void *tmp = realloc(sd->cdb_buf, len); 258 1.10 joerg if (tmp == NULL) 259 1.10 joerg goto fail; 260 1.10 joerg sd->cdb_buf = tmp; 261 1.10 joerg sd->cdb_buf_len = len; 262 1.10 joerg } 263 1.10 joerg memcpy(sd->cdb_buf, data, len); 264 1.10 joerg data = sd->cdb_buf; 265 1.10 joerg } 266 1.10 joerg 267 1.10 joerg if (len < 2) 268 1.10 joerg goto fail; 269 1.10 joerg sp->s_port = htobe16(be16dec(data)); 270 1.10 joerg data += 2; 271 1.10 joerg len -= 2; 272 1.10 joerg 273 1.10 joerg if (len == 0 || len < (size_t)data[0] + 2) 274 1.10 joerg goto fail; 275 1.10 joerg sp->s_proto = __UNCONST(data + 1); 276 1.10 joerg 277 1.10 joerg if (sp->s_proto[data[0]] != '\0') 278 1.10 joerg goto fail; 279 1.10 joerg 280 1.10 joerg len -= 2 + data[0]; 281 1.10 joerg data += 2 + data[0]; 282 1.10 joerg 283 1.10 joerg if (len == 0) 284 1.10 joerg goto fail; 285 1.10 joerg if (len < (size_t)data[0] + 2) 286 1.10 joerg goto fail; 287 1.10 joerg 288 1.10 joerg sp->s_name = __UNCONST(data + 1); 289 1.10 joerg len -= 2 + data[0]; 290 1.10 joerg data += 2 + data[0]; 291 1.10 joerg 292 1.10 joerg if (sd->aliases == NULL) { 293 1.10 joerg sd->maxaliases = 10; 294 1.12 nia sd->aliases = NULL; 295 1.13 christos errno = reallocarr(&sd->aliases, 296 1.13 christos sd->maxaliases, sizeof(*sd->aliases)); 297 1.13 christos if (errno) 298 1.10 joerg goto fail; 299 1.10 joerg } 300 1.10 joerg sp->s_aliases = sd->aliases; 301 1.10 joerg i = 0; 302 1.10 joerg while (len) { 303 1.10 joerg if (len < (size_t)data[0] + 2) 304 1.10 joerg goto fail; 305 1.10 joerg if (i == sd->maxaliases - 2) { 306 1.10 joerg sd->maxaliases *= 2; 307 1.12 nia q = sd->aliases; 308 1.13 christos errno = reallocarr(&q, sd->maxaliases, sizeof(*q)); 309 1.13 christos if (errno) 310 1.10 joerg goto fail; 311 1.10 joerg sp->s_aliases = sd->aliases = q; 312 1.10 joerg } 313 1.10 joerg sp->s_aliases[i++] = __UNCONST(data + 1); 314 1.10 joerg len -= 2 + data[0]; 315 1.10 joerg data += 2 + data[0]; 316 1.1 christos } 317 1.10 joerg sp->s_aliases[i] = NULL; 318 1.10 joerg return sp; 319 1.10 joerg 320 1.10 joerg fail: 321 1.10 joerg oerrno = errno; 322 1.10 joerg endservent_r(sd); 323 1.10 joerg errno = oerrno; 324 1.10 joerg return NULL; 325 1.1 christos } 326 1.10 joerg 327