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 */ 35 36 #include <sys/types.h> 37 #include <sys/socket.h> 38 #include <netdb.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <stdlib.h> 42 #ifdef YP 43 #include <rpc/rpc.h> 44 #include <rpcsvc/yp_prot.h> 45 #include <rpcsvc/ypclnt.h> 46 static int serv_stepping_yp = 0; 47 extern int _yp_check __P(( char ** )); 48 #endif 49 50 51 #define MAXALIASES 35 52 53 static FILE *servf = NULL; 54 static char line[BUFSIZ+1]; 55 static struct servent serv; 56 static char *serv_aliases[MAXALIASES]; 57 int _serv_stayopen; 58 59 #ifdef YP 60 char *___getservbyname_yp = NULL; 61 char *___getservbyproto_yp = NULL; 62 int ___getservbyport_yp = 0; 63 static char *yp_domain = NULL; 64 65 static int 66 _getservbyport_yp(line) 67 char *line; 68 { 69 char *result; 70 int resultlen; 71 char buf[YPMAXRECORD + 2]; 72 int rv; 73 74 snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp), 75 ___getservbyproto_yp); 76 77 ___getservbyport_yp = 0; 78 ___getservbyproto_yp = NULL; 79 80 if(!yp_domain) { 81 if(yp_get_default_domain(&yp_domain)) 82 return (0); 83 } 84 85 /* 86 * We have to be a little flexible here. Ideally you're supposed 87 * to have both a services.byname and a services.byport map, but 88 * some systems have only services.byname. FreeBSD cheats a little 89 * by putting the services.byport information in the same map as 90 * services.byname so that either case will work. We allow for both 91 * possibilities here: if there is no services.byport map, we try 92 * services.byname instead. 93 */ 94 if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf), 95 &result, &resultlen))) { 96 if (rv == YPERR_MAP) { 97 if (yp_match(yp_domain, "services.byname", buf, 98 strlen(buf), &result, &resultlen)) 99 return(0); 100 } else 101 return(0); 102 } 103 104 /* getservent() expects lines terminated with \n -- make it happy */ 105 snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); 106 107 free(result); 108 return(1); 109 } 110 111 static int 112 _getservbyname_yp(line) 113 char *line; 114 { 115 char *result; 116 int resultlen; 117 char buf[YPMAXRECORD + 2]; 118 119 if(!yp_domain) { 120 if(yp_get_default_domain(&yp_domain)) 121 return (0); 122 } 123 124 snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp, 125 ___getservbyproto_yp); 126 127 ___getservbyname_yp = 0; 128 ___getservbyproto_yp = NULL; 129 130 if (yp_match(yp_domain, "services.byname", buf, strlen(buf), 131 &result, &resultlen)) { 132 return(0); 133 } 134 135 /* getservent() expects lines terminated with \n -- make it happy */ 136 snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); 137 138 free(result); 139 return(1); 140 } 141 142 static int 143 _getservent_yp(line) 144 char *line; 145 { 146 static char *key = NULL; 147 static int keylen; 148 char *lastkey, *result; 149 int resultlen; 150 int rv; 151 152 if(!yp_domain) { 153 if(yp_get_default_domain(&yp_domain)) 154 return (0); 155 } 156 157 if (!serv_stepping_yp) { 158 if (key) 159 free(key); 160 if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen, 161 &result, &resultlen))) { 162 serv_stepping_yp = 0; 163 return(0); 164 } 165 serv_stepping_yp = 1; 166 } else { 167 lastkey = key; 168 rv = yp_next(yp_domain, "services.byname", key, keylen, &key, 169 &keylen, &result, &resultlen); 170 free(lastkey); 171 if (rv) { 172 serv_stepping_yp = 0; 173 return (0); 174 } 175 } 176 177 /* getservent() expects lines terminated with \n -- make it happy */ 178 snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); 179 180 free(result); 181 182 return(1); 183 } 184 #endif 185 186 void 187 setservent(f) 188 int f; 189 { 190 if (servf == NULL) 191 servf = fopen(_PATH_SERVICES, "r" ); 192 else 193 rewind(servf); 194 _serv_stayopen |= f; 195 } 196 197 void 198 endservent() 199 { 200 if (servf) { 201 fclose(servf); 202 servf = NULL; 203 } 204 _serv_stayopen = 0; 205 } 206 207 struct servent * 208 getservent() 209 { 210 char *p; 211 register char *cp, **q; 212 213 #ifdef YP 214 if (serv_stepping_yp && _getservent_yp(line)) { 215 p = (char *)&line; 216 goto unpack; 217 } 218 tryagain: 219 #endif 220 if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) 221 return (NULL); 222 again: 223 if ((p = fgets(line, BUFSIZ, servf)) == NULL) 224 return (NULL); 225 #ifdef YP 226 if (*p == '+' && _yp_check(NULL)) { 227 if (___getservbyname_yp != NULL) { 228 if (!_getservbyname_yp(line)) 229 goto tryagain; 230 } 231 else if (___getservbyport_yp != 0) { 232 if (!_getservbyport_yp(line)) 233 goto tryagain; 234 } 235 else if (!_getservent_yp(line)) 236 goto tryagain; 237 } 238 unpack: 239 #endif 240 if (*p == '#') 241 goto again; 242 cp = strpbrk(p, "#\n"); 243 if (cp == NULL) 244 goto again; 245 *cp = '\0'; 246 serv.s_name = p; 247 p = strpbrk(p, " \t"); 248 if (p == NULL) 249 goto again; 250 *p++ = '\0'; 251 while (*p == ' ' || *p == '\t') 252 p++; 253 cp = strpbrk(p, ",/"); 254 if (cp == NULL) 255 goto again; 256 *cp++ = '\0'; 257 serv.s_port = htons((u_short)atoi(p)); 258 serv.s_proto = cp; 259 q = serv.s_aliases = serv_aliases; 260 cp = strpbrk(cp, " \t"); 261 if (cp != NULL) 262 *cp++ = '\0'; 263 while (cp && *cp) { 264 if (*cp == ' ' || *cp == '\t') { 265 cp++; 266 continue; 267 } 268 if (q < &serv_aliases[MAXALIASES - 1]) 269 *q++ = cp; 270 cp = strpbrk(cp, " \t"); 271 if (cp != NULL) 272 *cp++ = '\0'; 273 } 274 *q = NULL; 275 return (&serv); 276 } 277