| /* | |
| * Copyright (c) 1983, 1993 | |
| * The Regents of the University of California. All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions | |
| * are met: | |
| * 1. Redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution. | |
| * 3. All advertising materials mentioning features or use of this software | |
| * must display the following acknowledgement: | |
| * This product includes software developed by the University of | |
| * California, Berkeley and its contributors. | |
| * 4. Neither the name of the University nor the names of its contributors | |
| * may be used to endorse or promote products derived from this software | |
| * without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
| * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
| * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
| * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
| * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
| * SUCH DAMAGE. | |
| */ | |
| #if defined(LIBC_SCCS) && !defined(lint) | |
| static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93"; | |
| #endif /* LIBC_SCCS and not lint */ | |
| #include <sys/types.h> | |
| #include <sys/socket.h> | |
| #include <netdb.h> | |
| #include <stdio.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #ifdef YP | |
| #include <rpc/rpc.h> | |
| #include <rpcsvc/yp_prot.h> | |
| #include <rpcsvc/ypclnt.h> | |
| static int serv_stepping_yp = 0; | |
| extern int _yp_check __P(( char ** )); | |
| #endif | |
| #define MAXALIASES 35 | |
| static FILE *servf = NULL; | |
| static char line[BUFSIZ+1]; | |
| static struct servent serv; | |
| static char *serv_aliases[MAXALIASES]; | |
| int _serv_stayopen; | |
| #ifdef YP | |
| char *___getservbyname_yp = NULL; | |
| char *___getservbyproto_yp = NULL; | |
| int ___getservbyport_yp = 0; | |
| static char *yp_domain = NULL; | |
| static int | |
| _getservbyport_yp(line) | |
| char *line; | |
| { | |
| char *result; | |
| int resultlen; | |
| char buf[YPMAXRECORD + 2]; | |
| int rv; | |
| snprintf(buf, sizeof(buf), "%d/%s", ntohs(___getservbyport_yp), | |
| ___getservbyproto_yp); | |
| ___getservbyport_yp = 0; | |
| ___getservbyproto_yp = NULL; | |
| if(!yp_domain) { | |
| if(yp_get_default_domain(&yp_domain)) | |
| return (0); | |
| } | |
| /* | |
| * We have to be a little flexible here. Ideally you're supposed | |
| * to have both a services.byname and a services.byport map, but | |
| * some systems have only services.byname. FreeBSD cheats a little | |
| * by putting the services.byport information in the same map as | |
| * services.byname so that either case will work. We allow for both | |
| * possibilities here: if there is no services.byport map, we try | |
| * services.byname instead. | |
| */ | |
| if ((rv = yp_match(yp_domain, "services.byport", buf, strlen(buf), | |
| &result, &resultlen))) { | |
| if (rv == YPERR_MAP) { | |
| if (yp_match(yp_domain, "services.byname", buf, | |
| strlen(buf), &result, &resultlen)) | |
| return(0); | |
| } else | |
| return(0); | |
| } | |
| /* getservent() expects lines terminated with \n -- make it happy */ | |
| snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); | |
| free(result); | |
| return(1); | |
| } | |
| static int | |
| _getservbyname_yp(line) | |
| char *line; | |
| { | |
| char *result; | |
| int resultlen; | |
| char buf[YPMAXRECORD + 2]; | |
| if(!yp_domain) { | |
| if(yp_get_default_domain(&yp_domain)) | |
| return (0); | |
| } | |
| snprintf(buf, sizeof(buf), "%s/%s", ___getservbyname_yp, | |
| ___getservbyproto_yp); | |
| ___getservbyname_yp = 0; | |
| ___getservbyproto_yp = NULL; | |
| if (yp_match(yp_domain, "services.byname", buf, strlen(buf), | |
| &result, &resultlen)) { | |
| return(0); | |
| } | |
| /* getservent() expects lines terminated with \n -- make it happy */ | |
| snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); | |
| free(result); | |
| return(1); | |
| } | |
| static int | |
| _getservent_yp(line) | |
| char *line; | |
| { | |
| static char *key = NULL; | |
| static int keylen; | |
| char *lastkey, *result; | |
| int resultlen; | |
| int rv; | |
| if(!yp_domain) { | |
| if(yp_get_default_domain(&yp_domain)) | |
| return (0); | |
| } | |
| if (!serv_stepping_yp) { | |
| if (key) | |
| free(key); | |
| if ((rv = yp_first(yp_domain, "services.byname", &key, &keylen, | |
| &result, &resultlen))) { | |
| serv_stepping_yp = 0; | |
| return(0); | |
| } | |
| serv_stepping_yp = 1; | |
| } else { | |
| lastkey = key; | |
| rv = yp_next(yp_domain, "services.byname", key, keylen, &key, | |
| &keylen, &result, &resultlen); | |
| free(lastkey); | |
| if (rv) { | |
| serv_stepping_yp = 0; | |
| return (0); | |
| } | |
| } | |
| /* getservent() expects lines terminated with \n -- make it happy */ | |
| snprintf(line, BUFSIZ, "%.*s\n", resultlen, result); | |
| free(result); | |
| return(1); | |
| } | |
| #endif | |
| void | |
| setservent(int f) | |
| { | |
| if (servf == NULL) | |
| servf = fopen(_PATH_SERVICES, "r" ); | |
| else | |
| rewind(servf); | |
| _serv_stayopen |= f; | |
| } | |
| void | |
| endservent() | |
| { | |
| if (servf) { | |
| fclose(servf); | |
| servf = NULL; | |
| } | |
| _serv_stayopen = 0; | |
| } | |
| struct servent * | |
| getservent() | |
| { | |
| char *p; | |
| register char *cp, **q; | |
| #ifdef YP | |
| if (serv_stepping_yp && _getservent_yp(line)) { | |
| p = (char *)&line; | |
| goto unpack; | |
| } | |
| tryagain: | |
| #endif | |
| if (servf == NULL && (servf = fopen(_PATH_SERVICES, "r" )) == NULL) | |
| return (NULL); | |
| again: | |
| if ((p = fgets(line, BUFSIZ, servf)) == NULL) | |
| return (NULL); | |
| #ifdef YP | |
| if (*p == '+' && _yp_check(NULL)) { | |
| if (___getservbyname_yp != NULL) { | |
| if (!_getservbyname_yp(line)) | |
| goto tryagain; | |
| } | |
| else if (___getservbyport_yp != 0) { | |
| if (!_getservbyport_yp(line)) | |
| goto tryagain; | |
| } | |
| else if (!_getservent_yp(line)) | |
| goto tryagain; | |
| } | |
| unpack: | |
| #endif | |
| if (*p == '#') | |
| goto again; | |
| cp = strpbrk(p, "#\n"); | |
| if (cp == NULL) | |
| goto again; | |
| *cp = '\0'; | |
| serv.s_name = p; | |
| p = strpbrk(p, " \t"); | |
| if (p == NULL) | |
| goto again; | |
| *p++ = '\0'; | |
| while (*p == ' ' || *p == '\t') | |
| p++; | |
| cp = strpbrk(p, ",/"); | |
| if (cp == NULL) | |
| goto again; | |
| *cp++ = '\0'; | |
| serv.s_port = htons((u_short)atoi(p)); | |
| serv.s_proto = cp; | |
| q = serv.s_aliases = serv_aliases; | |
| cp = strpbrk(cp, " \t"); | |
| if (cp != NULL) | |
| *cp++ = '\0'; | |
| while (cp && *cp) { | |
| if (*cp == ' ' || *cp == '\t') { | |
| cp++; | |
| continue; | |
| } | |
| if (q < &serv_aliases[MAXALIASES - 1]) | |
| *q++ = cp; | |
| cp = strpbrk(cp, " \t"); | |
| if (cp != NULL) | |
| *cp++ = '\0'; | |
| } | |
| *q = NULL; | |
| return (&serv); | |
| } |