1 /* 2 * Copyright (c) 1983, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * @(#)getservent.c 8.1 (Berkeley) 6/4/93 34 * $DragonFly: src/lib/libc/net/getservent.c,v 1.5 2004/10/25 19:38:01 drhodus Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/socket.h> 39 #include <netdb.h> 40 #include <stdio.h> 41 #include <string.h> 42 #include <stdlib.h> 43 #ifdef YP 44 #include <rpc/rpc.h> 45 #include <rpcsvc/yp_prot.h> 46 #include <rpcsvc/ypclnt.h> 47 static int serv_stepping_yp = 0; 48 extern int _yp_check ( char ** ); 49 #endif 50 51 52 #define MAXALIASES 35 53 54 static FILE *servf = NULL; 55 static char line[BUFSIZ+1]; 56 static struct servent serv; 57 static char *serv_aliases[MAXALIASES]; 58 int _serv_stayopen; 59 60 #ifdef YP 61 char *___getservbyname_yp = NULL; 62 char *___getservbyproto_yp = NULL; 63 int ___getservbyport_yp = 0; 64 static char *yp_domain = NULL; 65 66 static int 67 _getservbyport_yp(line) 68 char *line; 69 { 70 char *result; 71 int resultlen; 72 char buf[YPMAXRECORD + 2]; 73 int rv; 74 75 snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp), 76 ___getservbyproto_yp); 77 78 ___getservbyport_yp = 0; 79 ___getservbyproto_yp = NULL; 80 81 if(!yp_domain) { 82 if(yp_get_default_domain(&yp_domain)) 83 return (0); 84 } 85 86 /* 87 * We have to be a little flexible here. Ideally you're supposed 88 * to have both a services.byname and a services.byport map, but 89 * some systems have only services.byname. FreeBSD cheats a little 90 * by putting the services.byport information in the same map as 91 * services.byname so that either case will work. We allow for both 92 * possibilities here: if there is no services.byport map, we try 93 * services.byname instead. 94 */ 95 if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf), 96 &result, &resultlen))) { 97 if (rv == YPERR_MAP) { 98 if (yp_match(yp_domain, "services.byname", buf, 99 strlen(buf), &result, &resultlen)) 100 return(0); 101 } else 102 return(0); 103 } 104 105 /* getservent() expects lines terminated with \n -- make it happy */ 106 snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); 107 108 free(result); 109 return(1); 110 } 111 112 static int 113 _getservbyname_yp(line) 114 char *line; 115 { 116 char *result; 117 int resultlen; 118 char buf[YPMAXRECORD + 2]; 119 120 if(!yp_domain) { 121 if(yp_get_default_domain(&yp_domain)) 122 return (0); 123 } 124 125 snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp, 126 ___getservbyproto_yp); 127 128 ___getservbyname_yp = 0; 129 ___getservbyproto_yp = NULL; 130 131 if (yp_match(yp_domain, "services.byname", buf, strlen(buf), 132 &result, &resultlen)) { 133 return(0); 134 } 135 136 /* getservent() expects lines terminated with \n -- make it happy */ 137 snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); 138 139 free(result); 140 return(1); 141 } 142 143 static int 144 _getservent_yp(line) 145 char *line; 146 { 147 static char *key = NULL; 148 static int keylen; 149 char *lastkey, *result; 150 int resultlen; 151 int rv; 152 153 if(!yp_domain) { 154 if(yp_get_default_domain(&yp_domain)) 155 return (0); 156 } 157 158 if (!serv_stepping_yp) { 159 if (key) 160 free(key); 161 if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen, 162 &result, &resultlen))) { 163 serv_stepping_yp = 0; 164 return(0); 165 } 166 serv_stepping_yp = 1; 167 } else { 168 lastkey = key; 169 rv = yp_next(yp_domain, "services.byname", key, keylen, &key, 170 &keylen, &result, &resultlen); 171 free(lastkey); 172 if (rv) { 173 serv_stepping_yp = 0; 174 return (0); 175 } 176 } 177 178 /* getservent() expects lines terminated with \n -- make it happy */ 179 snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); 180 181 free(result); 182 183 return(1); 184 } 185 #endif 186 187 void 188 setservent(f) 189 int f; 190 { 191 if (servf == NULL) 192 servf = fopen(_PATH_SERVICES, "r" ); 193 else 194 rewind(servf); 195 _serv_stayopen |= f; 196 } 197 198 void 199 endservent() 200 { 201 if (servf) { 202 fclose(servf); 203 servf = NULL; 204 } 205 _serv_stayopen = 0; 206 } 207 208 struct servent * 209 getservent() 210 { 211 char *p; 212 char *cp, **q; 213 214 #ifdef YP 215 if (serv_stepping_yp && _getservent_yp(line)) { 216 p = (char *)&line; 217 goto unpack; 218 } 219 tryagain: 220 #endif 221 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) 222 return (NULL); 223 again: 224 if ((p = fgets(line, BUFSIZ, servf)) == NULL) 225 return (NULL); 226 #ifdef YP 227 if (*p == '+' && _yp_check(NULL)) { 228 if (___getservbyname_yp != NULL) { 229 if (!_getservbyname_yp(line)) 230 goto tryagain; 231 } 232 else if (___getservbyport_yp != 0) { 233 if (!_getservbyport_yp(line)) 234 goto tryagain; 235 } 236 else if (!_getservent_yp(line)) 237 goto tryagain; 238 } 239 unpack: 240 #endif 241 if (*p == '#') 242 goto again; 243 cp = strpbrk(p, "#\n"); 244 if (cp == NULL) 245 goto again; 246 *cp = '\0'; 247 serv.s_name = p; 248 p = strpbrk(p, " \t"); 249 if (p == NULL) 250 goto again; 251 *p++ = '\0'; 252 while (*p == ' ' || *p == '\t') 253 p++; 254 cp = strpbrk(p, ",/"); 255 if (cp == NULL) 256 goto again; 257 *cp++ = '\0'; 258 serv.s_port = htons((u_short)atoi(p)); 259 serv.s_proto = cp; 260 q = serv.s_aliases = serv_aliases; 261 cp = strpbrk(cp, " \t"); 262 if (cp != NULL) 263 *cp++ = '\0'; 264 while (cp && *cp) { 265 if (*cp == ' ' || *cp == '\t') { 266 cp++; 267 continue; 268 } 269 if (q < &serv_aliases[MAXALIASES - 1]) 270 *q++ = cp; 271 cp = strpbrk(cp, " \t"); 272 if (cp != NULL) 273 *cp++ = '\0'; 274 } 275 *q = NULL; 276 return (&serv); 277 } 278