1/* $NetBSD: getservent_r.c,v 1.1.1.2 2012/09/09 16:07:59 christos Exp $ */ 2 3/* 4 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (c) 1998-1999 by Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 17 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20#if defined(LIBC_SCCS) && !defined(lint) 21static const char rcsid[] = "Id: getservent_r.c,v 1.6 2006/08/01 01:14:16 marka Exp "; 22#endif /* LIBC_SCCS and not lint */ 23 24#include <port_before.h> 25#if !defined(_REENTRANT) || !defined(DO_PTHREADS) 26 static int getservent_r_not_required = 0; 27#else 28#include <errno.h> 29#include <string.h> 30#include <stdio.h> 31#include <sys/types.h> 32#include <netinet/in.h> 33#include <netdb.h> 34#include <sys/param.h> 35#include <port_after.h> 36 37#ifdef SERV_R_RETURN 38 39static SERV_R_RETURN 40copy_servent(struct servent *, struct servent *, SERV_R_COPY_ARGS); 41 42SERV_R_RETURN 43getservbyname_r(const char *name, const char *proto, 44 struct servent *sptr, SERV_R_ARGS) { 45 struct servent *se = getservbyname(name, proto); 46#ifdef SERV_R_SETANSWER 47 int n = 0; 48 49 if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) 50 *answerp = NULL; 51 else 52 *answerp = sptr; 53 54 return (n); 55#else 56 if (se == NULL) 57 return (SERV_R_BAD); 58 59 return (copy_servent(se, sptr, SERV_R_COPY)); 60#endif 61} 62 63SERV_R_RETURN 64getservbyport_r(int port, const char *proto, 65 struct servent *sptr, SERV_R_ARGS) { 66 struct servent *se = getservbyport(port, proto); 67#ifdef SERV_R_SETANSWER 68 int n = 0; 69 70 if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) 71 *answerp = NULL; 72 else 73 *answerp = sptr; 74 75 return (n); 76#else 77 if (se == NULL) 78 return (SERV_R_BAD); 79 80 return (copy_servent(se, sptr, SERV_R_COPY)); 81#endif 82} 83 84/*% 85 * These assume a single context is in operation per thread. 86 * If this is not the case we will need to call irs directly 87 * rather than through the base functions. 88 */ 89 90SERV_R_RETURN 91getservent_r(struct servent *sptr, SERV_R_ARGS) { 92 struct servent *se = getservent(); 93#ifdef SERV_R_SETANSWER 94 int n = 0; 95 96 if (se == NULL || (n = copy_servent(se, sptr, SERV_R_COPY)) != 0) 97 *answerp = NULL; 98 else 99 *answerp = sptr; 100 101 return (n); 102#else 103 if (se == NULL) 104 return (SERV_R_BAD); 105 106 return (copy_servent(se, sptr, SERV_R_COPY)); 107#endif 108} 109 110SERV_R_SET_RETURN 111#ifdef SERV_R_ENT_ARGS 112setservent_r(int stay_open, SERV_R_ENT_ARGS) 113#else 114setservent_r(int stay_open) 115#endif 116{ 117#ifdef SERV_R_ENT_UNUSED 118 SERV_R_ENT_UNUSED; 119#endif 120 setservent(stay_open); 121#ifdef SERV_R_SET_RESULT 122 return (SERV_R_SET_RESULT); 123#endif 124} 125 126SERV_R_END_RETURN 127#ifdef SERV_R_ENT_ARGS 128endservent_r(SERV_R_ENT_ARGS) 129#else 130endservent_r() 131#endif 132{ 133#ifdef SERV_R_ENT_UNUSED 134 SERV_R_ENT_UNUSED; 135#endif 136 endservent(); 137 SERV_R_END_RESULT(SERV_R_OK); 138} 139 140/* Private */ 141 142#ifndef SERVENT_DATA 143static SERV_R_RETURN 144copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { 145 char *cp; 146 int i, n; 147 int numptr, len; 148 149 /* Find out the amount of space required to store the answer. */ 150 numptr = 1; /*%< NULL ptr */ 151 len = (char *)ALIGN(buf) - buf; 152 for (i = 0; se->s_aliases[i]; i++, numptr++) { 153 len += strlen(se->s_aliases[i]) + 1; 154 } 155 len += strlen(se->s_name) + 1; 156 len += strlen(se->s_proto) + 1; 157 len += numptr * sizeof(char*); 158 159 if (len > (int)buflen) { 160 errno = ERANGE; 161 return (SERV_R_BAD); 162 } 163 164 /* copy port value */ 165 sptr->s_port = se->s_port; 166 167 cp = (char *)ALIGN(buf) + numptr * sizeof(char *); 168 169 /* copy official name */ 170 n = strlen(se->s_name) + 1; 171 strcpy(cp, se->s_name); 172 sptr->s_name = cp; 173 cp += n; 174 175 /* copy aliases */ 176 sptr->s_aliases = (char **)ALIGN(buf); 177 for (i = 0 ; se->s_aliases[i]; i++) { 178 n = strlen(se->s_aliases[i]) + 1; 179 strcpy(cp, se->s_aliases[i]); 180 sptr->s_aliases[i] = cp; 181 cp += n; 182 } 183 sptr->s_aliases[i] = NULL; 184 185 /* copy proto */ 186 n = strlen(se->s_proto) + 1; 187 strcpy(cp, se->s_proto); 188 sptr->s_proto = cp; 189 cp += n; 190 191 return (SERV_R_OK); 192} 193#else /* !SERVENT_DATA */ 194static int 195copy_servent(struct servent *se, struct servent *sptr, SERV_R_COPY_ARGS) { 196 char *cp, *eob; 197 int i, n; 198 199 /* copy port value */ 200 sptr->s_port = se->s_port; 201 202 /* copy official name */ 203 cp = sdptr->line; 204 eob = sdptr->line + sizeof(sdptr->line); 205 if ((n = strlen(se->s_name) + 1) < (eob - cp)) { 206 strcpy(cp, se->s_name); 207 sptr->s_name = cp; 208 cp += n; 209 } else { 210 return (-1); 211 } 212 213 /* copy aliases */ 214 i = 0; 215 sptr->s_aliases = sdptr->serv_aliases; 216 while (se->s_aliases[i] && i < (_MAXALIASES-1)) { 217 if ((n = strlen(se->s_aliases[i]) + 1) < (eob - cp)) { 218 strcpy(cp, se->s_aliases[i]); 219 sptr->s_aliases[i] = cp; 220 cp += n; 221 } else { 222 break; 223 } 224 i++; 225 } 226 sptr->s_aliases[i] = NULL; 227 228 /* copy proto */ 229 if ((n = strlen(se->s_proto) + 1) < (eob - cp)) { 230 strcpy(cp, se->s_proto); 231 sptr->s_proto = cp; 232 cp += n; 233 } else { 234 return (-1); 235 } 236 237 return (SERV_R_OK); 238} 239#endif /* !SERVENT_DATA */ 240#else /*SERV_R_RETURN */ 241 static int getservent_r_unknown_system = 0; 242#endif /*SERV_R_RETURN */ 243#endif /* !defined(_REENTRANT) || !defined(DO_PTHREADS) */ 244/*! \file */ 245