119370Spst/* $NetBSD: getservent_r.c,v 1.13 2022/03/12 17:31:39 christos Exp $ */ 2130803Smarcel 398944Sobrien/* 419370Spst * Copyright (c) 1983, 1993 519370Spst * The Regents of the University of California. All rights reserved. 619370Spst * 798944Sobrien * Redistribution and use in source and binary forms, with or without 819370Spst * modification, are permitted provided that the following conditions 998944Sobrien * are met: 1098944Sobrien * 1. Redistributions of source code must retain the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer. 1298944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1319370Spst * notice, this list of conditions and the following disclaimer in the 1498944Sobrien * documentation and/or other materials provided with the distribution. 1598944Sobrien * 3. Neither the name of the University nor the names of its contributors 1698944Sobrien * may be used to endorse or promote products derived from this software 1798944Sobrien * without specific prior written permission. 1819370Spst * 1998944Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2098944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2198944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2298944Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2319370Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2419370Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2519370Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2619370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2719370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2819370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2919370Spst * SUCH DAMAGE. 3019370Spst */ 3119370Spst 3298944Sobrien#include <sys/cdefs.h> 33130803Smarcel#if defined(LIBC_SCCS) && !defined(lint) 3419370Spst#if 0 3519370Spststatic char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; 3619370Spst#else 3719370Spst__RCSID("$NetBSD: getservent_r.c,v 1.13 2022/03/12 17:31:39 christos Exp $"); 3819370Spst#endif 3919370Spst#endif /* LIBC_SCCS and not lint */ 4019370Spst 4119370Spst#include "namespace.h" 4298944Sobrien#include <cdbr.h> 4319370Spst#include <errno.h> 4419370Spst#include <fcntl.h> 4519370Spst#include <netdb.h> 4619370Spst#include <stdio.h> 4719370Spst#include <stdlib.h> 4819370Spst#include <string.h> 4919370Spst 5019370Spst#include "servent.h" 5119370Spst 5246283Sdfr#ifdef __weak_alias 5346283Sdfr__weak_alias(endservent_r,_endservent_r) 5446283Sdfr__weak_alias(getservent_r,_getservent_r) 5598944Sobrien__weak_alias(setservent_r,_setservent_r) 5698944Sobrien#endif 5798944Sobrien 5898944Sobrienint 5946283Sdfr_servent_open(struct servent_data *sd) 6046283Sdfr{ 6198944Sobrien if (sd->flags & (_SV_CDB | _SV_PLAINFILE)) { 6298944Sobrien sd->flags |= _SV_FIRST; 6398944Sobrien return 0; 6498944Sobrien } 6598944Sobrien 6698944Sobrien free(sd->line); 6746283Sdfr sd->line = NULL; 6898944Sobrien free(sd->cdb_buf); 6998944Sobrien sd->cdb_buf = NULL; 7046283Sdfr sd->cdb_buf_len = 0; 7146283Sdfr free(sd->aliases); 7246283Sdfr sd->aliases = NULL; 7398944Sobrien sd->maxaliases = 0; 7446283Sdfr sd->flags |= _SV_FIRST; 7598944Sobrien 7698944Sobrien sd->cdb = cdbr_open(_PATH_SERVICES_CDB, CDBR_DEFAULT); 7798944Sobrien if (sd->cdb != NULL) { 7898944Sobrien sd->flags |= _SV_CDB; 7998944Sobrien return 0; 8098944Sobrien } 8198944Sobrien 8298944Sobrien sd->plainfile = fopen(_PATH_SERVICES, "re"); 8398944Sobrien if (sd->plainfile != NULL) { 8498944Sobrien sd->flags |= _SV_PLAINFILE; 8598944Sobrien return 0; 8698944Sobrien } 8746283Sdfr return -1; 8846283Sdfr} 8998944Sobrien 9098944Sobrienvoid 9198944Sobrien_servent_close(struct servent_data *sd) 9298944Sobrien{ 9398944Sobrien if (sd->flags & _SV_CDB) { 9498944Sobrien cdbr_close(sd->cdb); 9546283Sdfr sd->cdb = NULL; 9619370Spst sd->flags &= ~_SV_CDB; 9719370Spst } 9819370Spst 9919370Spst if (sd->flags & _SV_PLAINFILE) { 10019370Spst (void)fclose(sd->plainfile); 10119370Spst sd->plainfile = NULL; 10219370Spst sd->flags &= ~_SV_PLAINFILE; 103130803Smarcel } 10419370Spst sd->flags &= ~_SV_STAYOPEN; 10519370Spst} 10698944Sobrien 10719370Spst 10819370Spstint 10919370Spst_servent_getline(struct servent_data *sd) 11019370Spst{ 11119370Spst 11219370Spst if (sd->flags & _SV_CDB) 11319370Spst return -1; 11419370Spst 11519370Spst if ((sd->flags & _SV_PLAINFILE) == 0) 11619370Spst return -1; 11719370Spst 11819370Spst free(sd->line); 11919370Spst sd->line = NULL; 12019370Spst 12119370Spst if (sd->flags & _SV_FIRST) { 12219370Spst (void)rewind((FILE *)sd->plainfile); 12319370Spst sd->flags &= ~_SV_FIRST; 12419370Spst } 12519370Spst sd->line = fparseln(sd->plainfile, NULL, NULL, NULL, 12619370Spst FPARSELN_UNESCALL); 12719370Spst return sd->line == NULL ? -1 : 0; 12819370Spst} 12919370Spst 13019370Spststruct servent * 13119370Spst_servent_parseline(struct servent_data *sd, struct servent *sp) 13219370Spst{ 13319370Spst size_t i = 0; 13419370Spst int oerrno; 13519370Spst char *p, *cp, **q; 13619370Spst 13719370Spst if (sd->line == NULL) 13819370Spst return NULL; 13919370Spst 14019370Spst sp->s_name = p = sd->line; 14119370Spst p = strpbrk(p, " \t"); 14219370Spst if (p == NULL) 14319370Spst return NULL; 14419370Spst *p++ = '\0'; 14519370Spst while (*p == ' ' || *p == '\t') 14619370Spst p++; 14719370Spst cp = strpbrk(p, ",/"); 14819370Spst if (cp == NULL) 14998944Sobrien return NULL; 15019370Spst *cp++ = '\0'; 15119370Spst sp->s_port = htons((u_short)atoi(p)); 15246283Sdfr sp->s_proto = cp; 15319370Spst if (sd->aliases == NULL) { 15419370Spst sd->maxaliases = 10; 15519370Spst sd->aliases = calloc(sd->maxaliases, sizeof(*sd->aliases)); 15619370Spst if (sd->aliases == NULL) { 15719370Spst oerrno = errno; 15819370Spst endservent_r(sd); 15919370Spst errno = oerrno; 16019370Spst return NULL; 16119370Spst } 16219370Spst } 16319370Spst sp->s_aliases = sd->aliases; 16498944Sobrien cp = strpbrk(cp, " \t"); 16598944Sobrien if (cp != NULL) 16619370Spst *cp++ = '\0'; 167130803Smarcel while (cp && *cp) { 16819370Spst if (*cp == ' ' || *cp == '\t') { 16919370Spst cp++; 17019370Spst continue; 17198944Sobrien } 17219370Spst if (i == sd->maxaliases - 2) { 17319370Spst sd->maxaliases *= 2; 17446283Sdfr q = realloc(sd->aliases, sd->maxaliases * sizeof(*q)); 17519370Spst if (q == NULL) { 17619370Spst oerrno = errno; 17798944Sobrien endservent_r(sd); 17819370Spst errno = oerrno; 17919370Spst return NULL; 18019370Spst } 18198944Sobrien sp->s_aliases = sd->aliases = q; 18219370Spst } 18319370Spst sp->s_aliases[i++] = cp; 18419370Spst cp = strpbrk(cp, " \t"); 18598944Sobrien if (cp != NULL) 18619370Spst *cp++ = '\0'; 18798944Sobrien } 18819370Spst sp->s_aliases[i] = NULL; 18919370Spst return sp; 19019370Spst} 19119370Spst 19219370Spstvoid 19398944Sobriensetservent_r(int f, struct servent_data *sd) 19419370Spst{ 19519370Spst (void)_servent_open(sd); 19619370Spst sd->flags |= f ? _SV_STAYOPEN : 0; 19719370Spst} 19819370Spst 19919370Spstvoid 20019370Spstendservent_r(struct servent_data *sd) 20198944Sobrien{ 20219370Spst _servent_close(sd); 20319370Spst free(sd->aliases); 20419370Spst sd->aliases = NULL; 20519370Spst sd->maxaliases = 0; 20619370Spst free(sd->line); 20719370Spst sd->line = NULL; 20819370Spst free(sd->cdb_buf); 20919370Spst sd->cdb_buf = NULL; 21019370Spst sd->cdb_buf_len = 0; 21119370Spst} 21219370Spst 21319370Spststruct servent * 21419370Spstgetservent_r(struct servent *sp, struct servent_data *sd) 21519370Spst{ 21619370Spst 21719370Spst if ((sd->flags & (_SV_CDB | _SV_PLAINFILE)) == 0 && 21819370Spst _servent_open(sd) == -1) 21919370Spst return NULL; 22019370Spst 22119370Spst if (sd->flags & _SV_CDB) { 22219370Spst const void *data; 22319370Spst size_t len; 22419370Spst 22519370Spst if (sd->flags & _SV_FIRST) { 22619370Spst sd->cdb_index = 0; 22719370Spst sd->flags &= ~_SV_FIRST; 22846283Sdfr } 22919370Spst 23019370Spst if (cdbr_get(sd->cdb, sd->cdb_index, &data, &len)) 23119370Spst return NULL; 23298944Sobrien ++sd->cdb_index; 23319370Spst return _servent_parsedb(sd, sp, data, len); 23419370Spst } 23519370Spst if (sd->flags & _SV_PLAINFILE) { 23619370Spst for (;;) { 23719370Spst if (_servent_getline(sd) == -1) 23819370Spst return NULL; 23919370Spst if (_servent_parseline(sd, sp) == NULL) 24019370Spst continue; 24198944Sobrien return sp; 24219370Spst } 24319370Spst } 24419370Spst return NULL; 24519370Spst} 24619370Spst 24719370Spststruct servent * 24819370Spst_servent_parsedb(struct servent_data *sd, struct servent *sp, 24919370Spst const uint8_t *data, size_t len) 25019370Spst{ 25198944Sobrien char **q; 25219370Spst size_t i; 253130803Smarcel int oerrno; 25498944Sobrien 25519370Spst if ((sd->flags & _SV_STAYOPEN) == 0) { 25619370Spst if (len > sd->cdb_buf_len) { 25719370Spst void *tmp = realloc(sd->cdb_buf, len); 25819370Spst if (tmp == NULL) 25919370Spst goto fail; 26019370Spst sd->cdb_buf = tmp; 26119370Spst sd->cdb_buf_len = len; 26219370Spst } 26319370Spst memcpy(sd->cdb_buf, data, len); 26419370Spst data = sd->cdb_buf; 26519370Spst } 26619370Spst 26719370Spst if (len < 2) 26819370Spst goto fail; 26919370Spst sp->s_port = htobe16(be16dec(data)); 27019370Spst data += 2; 27119370Spst len -= 2; 27219370Spst 27319370Spst if (len == 0 || len < (size_t)data[0] + 2) 27419370Spst goto fail; 27519370Spst sp->s_proto = __UNCONST(data + 1); 27619370Spst 27719370Spst if (sp->s_proto[data[0]] != '\0') 27819370Spst goto fail; 27919370Spst 28019370Spst len -= 2 + data[0]; 28119370Spst data += 2 + data[0]; 28219370Spst 28319370Spst if (len == 0) 28419370Spst goto fail; 28519370Spst if (len < (size_t)data[0] + 2) 28619370Spst goto fail; 28719370Spst 28819370Spst sp->s_name = __UNCONST(data + 1); 28919370Spst len -= 2 + data[0]; 29019370Spst data += 2 + data[0]; 29119370Spst 29219370Spst if (sd->aliases == NULL) { 29319370Spst sd->maxaliases = 10; 29419370Spst sd->aliases = NULL; 29519370Spst errno = reallocarr(&sd->aliases, 29619370Spst sd->maxaliases, sizeof(*sd->aliases)); 29719370Spst if (errno) 29819370Spst goto fail; 29919370Spst } 30019370Spst sp->s_aliases = sd->aliases; 30119370Spst i = 0; 30219370Spst while (len) { 30319370Spst if (len < (size_t)data[0] + 2) 30419370Spst goto fail; 30519370Spst if (i == sd->maxaliases - 2) { 30619370Spst sd->maxaliases *= 2; 30719370Spst q = sd->aliases; 30819370Spst errno = reallocarr(&q, sd->maxaliases, sizeof(*q)); 30919370Spst if (errno) 31098944Sobrien goto fail; 31119370Spst sp->s_aliases = sd->aliases = q; 31219370Spst } 31398944Sobrien sp->s_aliases[i++] = __UNCONST(data + 1); 31419370Spst len -= 2 + data[0]; 31519370Spst data += 2 + data[0]; 31619370Spst } 31719370Spst sp->s_aliases[i] = NULL; 31819370Spst return sp; 31919370Spst 32019370Spstfail: 32119370Spst oerrno = errno; 32219370Spst endservent_r(sd); 32319370Spst errno = oerrno; 32419370Spst return NULL; 32519370Spst} 32619370Spst 32719370Spst