Home | History | Annotate | Line # | Download | only in net
getservent_r.c revision 1.6
      1 /*	$NetBSD: getservent_r.c,v 1.6 2006/07/27 22:03:49 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1983, 1993
      5  *	The Regents of the University of California.  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. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #if defined(LIBC_SCCS) && !defined(lint)
     34 #if 0
     35 static char sccsid[] = "@(#)getservent.c	8.1 (Berkeley) 6/4/93";
     36 #else
     37 __RCSID("$NetBSD: getservent_r.c,v 1.6 2006/07/27 22:03:49 christos Exp $");
     38 #endif
     39 #endif /* LIBC_SCCS and not lint */
     40 
     41 #include "namespace.h"
     42 #include <netdb.h>
     43 #include <errno.h>
     44 #include <stdio.h>
     45 #include <string.h>
     46 #include <stdlib.h>
     47 #include <fcntl.h>
     48 #include <db.h>
     49 
     50 #include "servent.h"
     51 
     52 #ifdef __weak_alias
     53 __weak_alias(endservent_r,_endservent_r)
     54 __weak_alias(getservent_r,_getservent_r)
     55 __weak_alias(setservent_r,_setservent_r)
     56 #endif
     57 
     58 int
     59 _servent_open(struct servent_data *sd)
     60 {
     61 	sd->flags = _SV_FIRST;
     62 	if (sd->db == NULL) {
     63 		if ((sd->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0,
     64 		    DB_HASH, NULL)) != NULL)
     65 			sd->flags |= _SV_DB;
     66 		else
     67 			sd->db = fopen(_PATH_SERVICES, "r");
     68 	}
     69 	return sd->db ? 0 : -1;
     70 }
     71 
     72 void
     73 _servent_close(struct servent_data *sd)
     74 {
     75 	if (sd->db) {
     76 		if (sd->flags & _SV_DB) {
     77 			DB *db = sd->db;
     78 			(*db->close)(db);
     79 		} else
     80 			(void)fclose((FILE *)sd->db);
     81 		sd->db = NULL;
     82 	}
     83 	sd->flags &= ~_SV_STAYOPEN;
     84 }
     85 
     86 
     87 int
     88 _servent_getline(struct servent_data *sd)
     89 {
     90 	if (sd->line) {
     91 		free(sd->line);
     92 		sd->line = NULL;
     93 	}
     94 	if (sd->flags & _SV_DB) {
     95 		DB *db = sd->db;
     96 		DBT key, data;
     97 		int flags  = (sd->flags & _SV_FIRST) ? R_FIRST : R_NEXT;
     98 
     99 		while ((*db->seq)(db, &key, &data, flags) == 0) {
    100 			flags = R_NEXT;
    101 			switch (((u_char *)key.data)[0]) {
    102 			case (u_char)'\377':
    103 			case (u_char)'\376':
    104 				continue;
    105 			default:
    106 				break;
    107 			}
    108 			sd->line = strdup(data.data);
    109 			break;
    110 		}
    111 	} else {
    112 		if (sd->flags & _SV_FIRST)
    113 			(void)rewind((FILE *)sd->db);
    114 		sd->line = fparseln((FILE *)sd->db, NULL, NULL, NULL,
    115 		    FPARSELN_UNESCALL);
    116 	}
    117 	sd->flags &= ~_SV_FIRST;
    118 	return sd->line == NULL ? -1 : 0;
    119 }
    120 
    121 
    122 struct servent *
    123 _servent_parseline(struct servent_data *sd, struct servent *sp)
    124 {
    125 	size_t i = 0;
    126 	int oerrno;
    127 	char *p, *cp, **q;
    128 
    129 	if (sd->line == NULL)
    130 		return NULL;
    131 
    132 	sp->s_name = p = sd->line;
    133 	p = strpbrk(p, " \t");
    134 	if (p == NULL)
    135 		return NULL;
    136 	*p++ = '\0';
    137 	while (*p == ' ' || *p == '\t')
    138 		p++;
    139 	cp = strpbrk(p, ",/");
    140 	if (cp == NULL)
    141 		return NULL;
    142 	*cp++ = '\0';
    143 	sp->s_port = htons((u_short)atoi(p));
    144 	sp->s_proto = cp;
    145 	if (sd->aliases == NULL) {
    146 		sd->maxaliases = 10;
    147 		sd->aliases = malloc(sd->maxaliases * sizeof(char *));
    148 		if (sd->aliases == NULL) {
    149 			oerrno = errno;
    150 			endservent_r(sd);
    151 			errno = oerrno;
    152 			return NULL;
    153 		}
    154 	}
    155 	q = sp->s_aliases = sd->aliases;
    156 	cp = strpbrk(cp, " \t");
    157 	if (cp != NULL)
    158 		*cp++ = '\0';
    159 	while (cp && *cp) {
    160 		if (*cp == ' ' || *cp == '\t') {
    161 			cp++;
    162 			continue;
    163 		}
    164 		if (i == sd->maxaliases - 2) {
    165 			sd->maxaliases *= 2;
    166 			q = realloc(q,
    167 			    sd->maxaliases * sizeof(char *));
    168 			if (q == NULL) {
    169 				oerrno = errno;
    170 				endservent_r(sd);
    171 				errno = oerrno;
    172 				return NULL;
    173 			}
    174 			sp->s_aliases = sd->aliases = q;
    175 		}
    176 		q[i++] = cp;
    177 		cp = strpbrk(cp, " \t");
    178 		if (cp != NULL)
    179 			*cp++ = '\0';
    180 	}
    181 	q[i] = NULL;
    182 	return sp;
    183 }
    184 
    185 void
    186 setservent_r(int f, struct servent_data *sd)
    187 {
    188 	(void)_servent_open(sd);
    189 	sd->flags |= f ? _SV_STAYOPEN : 0;
    190 }
    191 
    192 void
    193 endservent_r(struct servent_data *sd)
    194 {
    195 	_servent_close(sd);
    196 	if (sd->aliases) {
    197 		free(sd->aliases);
    198 		sd->aliases = NULL;
    199 		sd->maxaliases = 0;
    200 	}
    201 	if (sd->line) {
    202 		free(sd->line);
    203 		sd->line = NULL;
    204 	}
    205 }
    206 
    207 struct servent *
    208 getservent_r(struct servent *sp, struct servent_data *sd)
    209 {
    210 	if (sd->db == NULL && _servent_open(sd) == -1)
    211 		return NULL;
    212 
    213 	for (;;) {
    214 		if (_servent_getline(sd) == -1)
    215 			return NULL;
    216 		if (_servent_parseline(sd, sp) == NULL)
    217 			continue;
    218 		return sp;
    219 	}
    220 }
    221