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