Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 23 Aug 2004 11:56:06 +0400
From:      Michael Bushkov <bushman@rsu.ru>
To:        DougB@DougBarton.net
Cc:        cvs-all@freebsd.org
Subject:   getserv* functions and lookupd
Message-ID:  <1093247765.10372.7.camel@localhost>

next in thread | raw e-mail | index | archive | help

--=-3nsEfv7dxSW/zpQIyhAD
Content-Type: text/plain
Content-Transfer-Encoding: 7bit


> Finally, the solution that has most often been discussed for improving
> the performance of getservbyname() and friends is a Berkeley db
> implementation similar to the way login.conf is done now. I'm not sure
> a
> lookup daemon is justified, and I'd like to see some discussion about
> this topic too.
> 
> Thanks,
> 
> Doug
> 

Hello!
I think the best way to solve the problems with getserv* functions is to
implement them via nsdispatch. It gives us an ability to plug in any
appropriate functionality later.
I've attached the patch to libc, which does it. It implements nis, files
and compat sources. Any other source can be plugged dynamically as
nsswitch module. I'll release next lookupd version, which supports
getserv* functions in the next 5-6 days. It solves a lot of problems, i
think, because of caching.

Thanks,
Michael

--=-3nsEfv7dxSW/zpQIyhAD
Content-Disposition: attachment; filename=getserv.patch
Content-Type: text/x-patch; name=getserv.patch; charset=KOI8-R
Content-Transfer-Encoding: 7bit

*** ./initial/getservent.c	Wed Jul 14 18:06:32 2004
--- getservent.c	Thu Jul 15 13:21:01 2004
***************
*** 29,44 ****
--- 29,49 ----
   * 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.
   */
  
+  /* 
+   * getserv* functions implementation was adapted to nsswitch model by Michael Bushkov
+   */
+ 
  #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/cdefs.h>
  __FBSDID("$FreeBSD: src/lib/libc/net/getservent.c,v 1.12 2003/02/27 13:40:00 nectar Exp $");
  
+ #include "namespace.h"
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <stdio.h>
***************
*** 46,91 ****
  #include <stdlib.h>
  #ifdef YP
  #include <rpc/rpc.h>
  #include <rpcsvc/yp_prot.h>
  #include <rpcsvc/ypclnt.h>
- static int serv_stepping_yp = 0;
  #endif
  #include "libc_private.h"
  
  #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
--- 51,602 ----
  #include <stdlib.h>
  #ifdef YP
  #include <rpc/rpc.h>
  #include <rpcsvc/yp_prot.h>
  #include <rpcsvc/ypclnt.h>
  #endif
+ #include <errno.h>
+ #include <pthread.h>
+ #include <pthread_np.h>
+ #include <nss.h>
  #include "libc_private.h"
+ #include "nss_tls.h"
  
  #define	MAXALIASES	35
  
! /* 
!  * declarations' beginning
!  */
! #define _SERVENT_UNPACK_AGAIN -1
! #define _SERVENT_UNPACK_RETURN 0
! 
! static const ns_src defaultsrc[] = { 
!         { NSSRC_COMPAT, NS_SUCCESS },
!         { 0 }
! };
! 
! 
! struct files_state {
! 	FILE * servf;
! 	char line[BUFSIZ+1];
! 	struct servent serv;
! 	char *serv_aliases[MAXALIASES];
! 	int _serv_stayopen;
! 	
! 	int _notfound_block;
! };
! 
! static	void	files_endstate(void * files_state);
! NSS_TLS_HANDLING(files);
! 
! static	int	 _files_setservent(void *, void *, va_list);
! static	int	 _files_endservent(void *, void *, va_list);
! static	int	 _files_getservent(void *, void *, va_list);
! static	int	 _files_getservbyname(void *, void *, va_list);
! static	int	 _files_getservbyport(void *, void *, va_list);
! 
! #ifdef YP
! struct nis_state {
! 	char *yp_domain;
! 	int serv_stepping_yp;
! 	
! 	char *key;
! 	int keylen;
! 
! 	char line[BUFSIZ+1];
! 	struct servent serv;
! 	char *serv_aliases[MAXALIASES];
! 
! 	int _notfound_block;
! };
! 
! static	void	nis_endstate(void * nis_state);
! NSS_TLS_HANDLING(nis);
! 
! static	int	 _nis_setservent(void *, void *, va_list);
! static	int	 _nis_endservent(void *, void *, va_list);
! static	int	 _nis_getservent(void *, void *, va_list);
! static	int	 _nis_getservbyname(void *, void *, va_list);
! static	int	 _nis_getservbyport(void *, void *, va_list);
! #endif
! 
! /*
!  * indicates what source is currently used by compat mode
!  */
! enum compat_condition {
! 	FILES_STATE = 0
! #ifdef YP	
! 	, NIS_STATE = 1
! #endif
! };
! 
! /*
!  * compat mode uses existing files_state and nis_state structures, because it
!  * should combine files and nis modules functionality
!  */
! struct compat_state {
! 	struct files_state files_st;
! #ifdef YP
! 	struct nis_state nis_st;
! #endif
! 	
! 	enum compat_condition current_condition;
! };
! 
! static	void	compat_endstate(void * compat_state);
! NSS_TLS_HANDLING(compat);
! 
! static	int	 _compat_setservent(void *, void *, va_list);
! static	int	 _compat_endservent(void *, void *, va_list);
! static	int	 _compat_getservent(void *, void *, va_list);
! static	int	 _compat_getservbyname(void *, void *, va_list);
! static	int	 _compat_getservbyport(void *, void *, va_list);
! 
! /*
!  * declarations' ending
!  */
! 
! /*
!  * processes the line, pointed by p and fills the dest structure
!  * q is the pointer, which should be kept during one service entry 
!  * traversal 
!  */
! static int
! _servent_unpack(struct servent * dest,char ** serv_aliases, char *p, char *** q)
! {
! 	char *cp;
! 
! 	if (*p == '#')
! 		return _SERVENT_UNPACK_AGAIN;
! 	cp = strpbrk(p, "#\n");
! 	if (cp == NULL)
! 		return _SERVENT_UNPACK_AGAIN;
! 	*cp = '\0';
! 	dest->s_name = p;
! 	p = strpbrk(p, " \t");
! 	if (p == NULL)
! 		return _SERVENT_UNPACK_AGAIN;
! 	*p++ = '\0';
! 	while (*p == ' ' || *p == '\t')
! 		p++;
! 	cp = strpbrk(p, ",/");
! 	if (cp == NULL)
! 		return _SERVENT_UNPACK_AGAIN;
! 	*cp++ = '\0';
! 	dest->s_port = htons((u_short)atoi(p));
! 	dest->s_proto = cp;
! 	*q = dest->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 _SERVENT_UNPACK_RETURN;
! }
! 
! 
! static void
! files_endstate(void * p)
! {
! 	FILE * f;
! 	
! 	if (p == NULL)
! 		return;
! 	f = ((struct files_state *)p)->servf;
! 	if (f != NULL)
! 		fclose(f);
! 	free(p);	
! }
!  
!  /*
!   * gets compat's files state if we are in compat mode and global files state otherwise
!   */
!  static int
! _get_compat_files_state(struct files_state ** state,void * mdata)
! {
! 	int rv;
! 	enum compat_condition * current_condition;
! 
! 	current_condition=(enum compat_condition *)mdata;	
! 	if (current_condition==NULL) {
! 		rv=files_getstate(state);
! 		if (rv != 0)
! 			return -1;
! 	} else {
! 		struct compat_state * c_st;
! 
! 		rv=compat_getstate(&c_st);		
! 		if (rv !=0)
! 			return -1;
! 		
! 		*state=&c_st->files_st;
! 	}
! 	return 0;
! }
! 
! /*
!  * changes compat_condition state, passed as mdata pointer
!  */
! static int
! _redispatch_to_nis(void * mdata)
! {
! #ifdef YP
! 	if (mdata==NULL)
! 		return -1;
! 	else {
! 		enum compat_condition * current_condition;
! 		current_condition=(enum compat_condition *)mdata;	
! 		*current_condition=NIS_STATE;
! 		return 0;
! 	}
! #else
! 	return -1;
! #endif
! }
! 
! static int
! _files_setservent(void *retval, void *mdata, va_list ap)
! {
! 	struct files_state * st;	
! 	int f, rv;
! 	
! 	f = va_arg(ap, int);	
! 	rv=_get_compat_files_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 			
! 	if (st->servf == NULL)
! 		st->servf = fopen(_PATH_SERVICES, "r" );
! 	else
! 		rewind(st->servf);
! 	st->_serv_stayopen |= f;
! 	st->_notfound_block = 0;
! 	
! 	return (NS_UNAVAIL);
! }
! 
! static int
! _files_endservent(void *retval, void *mdata, va_list ap)
! {
! 	int rv;
! 	struct files_state * st;
! 	
! 	rv=_get_compat_files_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 	
! 	if (st->servf) {
! 		fclose(st->servf);
! 		st->servf = NULL;
! 	}
! 	st->_serv_stayopen = 0;
! 	st->_notfound_block=0;
! 	
! 	return (NS_UNAVAIL);
! }
! 
! static int
! _files_getservent(void *retval, void *mdata, va_list ap)
! {
! 	int rv;
! 	struct files_state * st;
! 	
! 	char *p, **q;
! 	int parse_retval=_SERVENT_UNPACK_RETURN;
! 
! 	rv=_get_compat_files_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 		
! 	if (st->_notfound_block!=0)
! 		return (NS_NOTFOUND);
! 		
! 	if (st->servf == NULL && (st->servf = fopen(_PATH_SERVICES, "r" )) == NULL)
! 		return (NS_UNAVAIL);
! 
! 	do {
! 		if ((p = fgets(st->line, BUFSIZ, st->servf)) == NULL) 	{
! 			st->_notfound_block=1;
! 			return (NS_NOTFOUND);
! 		}
! 	
! 		if (*p=='+') {
! 			if (_redispatch_to_nis(mdata)==0)
! 				return (NS_UNAVAIL);
! 			else {
! 				parse_retval=_SERVENT_UNPACK_AGAIN;
! 				continue;
! 			}
! 		}
! 		
! 		parse_retval=_servent_unpack(&st->serv,st->serv_aliases,p,&q);
! 	} while (parse_retval==_SERVENT_UNPACK_AGAIN);
! 
! 	*(struct servent **)retval=&st->serv;
! 	return (NS_SUCCESS);
! }
! 
! static int
! _files_getservbyname(void *retval, void *mdata, va_list ap)
! {
! 	struct files_state * st;
! 	int rv;
! 	
! 	char *curline, **q;
! 	int parse_retval=_SERVENT_UNPACK_RETURN;
! 	
! 	struct servent *p;
! 	char **cp;
! 
! 	const char * name;
! 	const char * proto;
! 	
!  	name = va_arg(ap, const char *);
!  	proto = va_arg(ap, const char *);
! 	
! 	rv=_get_compat_files_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);	
! 	
! 	/* setservent analog */
! 	if (st->servf == NULL)
! 		st->servf = fopen(_PATH_SERVICES, "r" );
! 	else
! 		rewind(st->servf);
! 	
! 	for (;;) {
! 		do {
! 			if ((curline = fgets(st->line, BUFSIZ, st->servf)) == NULL)
! 				return (NS_NOTFOUND);
! 		
! 			if (*curline=='+') {
! 				if ((mdata!=NULL) && (_nis_getservbyname(retval,mdata,ap)==(NS_SUCCESS))) {
! 					if (!st->_serv_stayopen)
! 						_files_endservent(retval,mdata,ap);
! 					return (NS_SUCCESS);
! 				} else
! 					continue;
! 			}
! 			
! 			parse_retval=_servent_unpack(&st->serv,st->serv_aliases,curline,&q);
! 		} while (parse_retval==_SERVENT_UNPACK_AGAIN);
! 		
! 		p=&(st->serv);
! 
! 		if (strcmp(name, p->s_name) == 0)
! 			goto gotname;
! 		for (cp = p->s_aliases; *cp; cp++)
! 			if (strcmp(name, *cp) == 0)
! 				goto gotname;
! 
! 			continue;
! 		
! 		gotname:				
! 		if (proto == 0 || strcmp(p->s_proto, proto) == 0)
! 			break;
! 	}
! 	
! 	if (!st->_serv_stayopen)
! 		_files_endservent(retval,mdata,ap);
! 
! 	if (p==NULL)
! 		return (NS_NOTFOUND);
! 	else {
! 		*(struct servent **)retval=&st->serv;
! 		return (NS_SUCCESS);
! 	}
! }
! 
! static int
! _files_getservbyport(void *retval, void *mdata, va_list ap)
! {
! 	struct files_state * st;
! 	int rv;
! 	
! 	char *curline, **q;
! 	int parse_retval=_SERVENT_UNPACK_RETURN;
! 
! 	int port;
! 	const char * proto;
! 		
! 	struct servent *p;
! 
!  	port = va_arg(ap, int);
!  	proto = va_arg(ap, const char *);	
! 	
! 	rv=_get_compat_files_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);	
! 	
! 	/* setservent analog */
! 	if (st->servf == NULL)
! 		st->servf = fopen(_PATH_SERVICES, "r" );
! 	else
! 		rewind(st->servf);
! 	
! 	for (;;) {
! 		do {
! 			if ((curline = fgets(st->line, BUFSIZ, st->servf)) == NULL)
! 				return (NS_NOTFOUND);
! 		
! 			if (*curline=='+') {
! 				if ((mdata!=NULL) && (_nis_getservbyport(retval,mdata,ap)==(NS_SUCCESS))) {
! 					if (!st->_serv_stayopen)
! 						_files_endservent(retval,mdata,ap);
! 					return (NS_SUCCESS);
! 				} else
! 					continue;
! 			}
! 		
! 			parse_retval=_servent_unpack(&st->serv,st->serv_aliases,curline,&q);
! 		} while (parse_retval==_SERVENT_UNPACK_AGAIN);
! 
! 		
! 		p=&(st->serv);
! 
! 		if (p->s_port != port)
! 			continue;
! 		if (proto == 0 || strcmp(p->s_proto, proto) == 0)
! 			break;
! 	}
! 
! 	if (!st->_serv_stayopen)
! 		_files_endservent(retval,mdata,ap);
! 
! 	if (p==NULL)
! 		return (NS_NOTFOUND);
! 	else {
! 		*(struct servent **)retval=&(st->serv);
! 		return (NS_SUCCESS);
! 	}	
! }
! 
  
  #ifdef YP
! 
! static void
! nis_endstate(void * p)
! {
! 	struct nis_state * st;
! 	if (p == NULL)
! 		return;
! 
! 
! 	st=(struct nis_state *)p;	
! 	if (st->key)
! 	        free(st->key);
! 	free(p);
! }
! 
!  /*
!   * gets compat's nis state if we are in compat mode and global nis state otherwise
!   */
! static int
! _get_compat_nis_state(struct nis_state ** state,void * mdata)
! {
! 	int rv;
! 	enum compat_condition * current_condition;
! 
! 	current_condition=(enum compat_condition *)mdata;	
! 	if (current_condition==NULL) {
! 		rv=nis_getstate(state);
! 		if (rv != 0)
! 			return -1;
! 	} else {
! 		struct compat_state * c_st;
! 
! 		rv=compat_getstate(&c_st);		
! 		if (rv !=0)
! 			return -1;
! 		
! 		*state=&c_st->nis_st;
! 	}
! 	return 0;
! }
  
  static int
! _nis_getservbyname(void *retval, void *mdata, va_list ap)
  {
+ 	char ** q;
  	char *result;
  	int resultlen;
  	char buf[YPMAXRECORD + 2];
+ 
+ 	const char * name;
+ 	const char * proto;
+ 	
+ 	struct nis_state * st;
  	int rv;
  
! 	rv=_get_compat_nis_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 
!     	name = va_arg(ap, const char *);
!     	proto = va_arg(ap, const char *);
!     
! 	if(!st->yp_domain) {
! 		if(yp_get_default_domain(&st->yp_domain))
! 			return (NS_UNAVAIL);
! 	}
  
! 	snprintf(buf, sizeof(buf), "%s/%s", name, proto);
  
! 	if (yp_match(st->yp_domain, "services.byname", buf, strlen(buf),
! 						&result, &resultlen)) {
! 		return(NS_NOTFOUND);
! 	}
! 		
! 	/* getservent() expects lines terminated with \n -- make it happy */
! 	snprintf(st->line, BUFSIZ, "%.*s\n", resultlen, result);
! 	free(result);
! 
! 	if (_servent_unpack(&st->serv,st->serv_aliases,st->line,&q)!=_SERVENT_UNPACK_RETURN)
! 		return (NS_UNAVAIL);
! 
! 	*(struct servent **)retval=&st->serv;	
! 	return (NS_SUCCESS);
! }
! 
! static int
! _nis_getservbyport(void *retval, void *mdata, va_list ap)
! {
! 	char ** q;
! 	
! 	int port;
! 	const char * proto;
! 
! 	char *result;
! 	int resultlen;
! 	char buf[YPMAXRECORD + 2];
! 	int rv;
! 
! 	struct nis_state * st;
! 	rv=_get_compat_nis_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 
!     port = va_arg(ap, int);
!     proto = va_arg(ap, const char *);	
! 
! 	snprintf(buf, sizeof(buf), "%d/%s", ntohs(port),
! 						proto);
! 
! 	if(!st->yp_domain) {
! 		if(yp_get_default_domain(&st->yp_domain))
! 			return (NS_UNAVAIL);
  	}
  
  	/*
  	 * We have to be a little flexible here. Ideally you're supposed
  	 * to have both a services.byname and a services.byport map, but
***************
*** 93,280 ****
  	 * 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(f)
! 	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;
! 	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);
  }
--- 604,950 ----
  	 * 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(st->yp_domain, "services.byport", buf, strlen(buf),
  						&result, &resultlen))) {
  		if (rv == YPERR_MAP) {
! 			if (yp_match(st->yp_domain, "services.byname", buf,
  					strlen(buf), &result, &resultlen))
! 			return(NS_NOTFOUND);
  		} else
! 			return(NS_NOTFOUND);
  	}
  		
  	/* getservent() expects lines terminated with \n -- make it happy */
! 	snprintf(st->line, BUFSIZ, "%.*s\n", resultlen, result);
  	free(result);
! 	
! 	if (_servent_unpack(&st->serv,st->serv_aliases,st->line,&q)!=_SERVENT_UNPACK_RETURN)
! 		return (NS_UNAVAIL);
! 
! 	*(struct servent **)retval=&st->serv;	
! 	return (NS_SUCCESS);
  }
  
  static int
! _nis_setservent(void *retval, void *mdata, va_list ap)
  {
! 	struct nis_state * st;
! 	int rv;
  
! 	rv=_get_compat_nis_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 		
! 	st->serv_stepping_yp=0;
! 	st->_notfound_block=0;
! 	return (NS_UNAVAIL);
! }
  
! static int
! _nis_endservent(void *retval, void *mdata, va_list ap)
! {
! 	struct nis_state * st;
! 	int rv;
  
! 	rv=_get_compat_nis_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
  		
! 	st->yp_domain=NULL;
! 	st->serv_stepping_yp=0;
! 	st->_notfound_block=0;
! 	return (NS_UNAVAIL);
  }
  
  static int
! _nis_getservent(void *retval, void *mdata, va_list ap)
  {
! 	struct nis_state * st;
! 	
! 	char *p,**q;
! 
  	char *lastkey, *result;
  	int resultlen;
  	int rv;
  
! 	rv=_get_compat_nis_state(&st,mdata);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 
! 	if (st->_notfound_block!=0)
! 		return (NS_NOTFOUND);
! 
! 	if(!st->yp_domain) {
! 		if(yp_get_default_domain(&st->yp_domain))
! 			return (NS_UNAVAIL);
  	}
  
! 	if (!st->serv_stepping_yp) {
! 		if (st->key)
! 			free(st->key);
! 		if ((rv = yp_first(st->yp_domain, "services.byname", &st->key, &st->keylen,
  			     &result, &resultlen))) {
! 			st->serv_stepping_yp = 0;
! 			return(NS_NOTFOUND);
! 		} else
! 			st->serv_stepping_yp = 1;
  	} else {
! 		lastkey = st->key;
! 		rv = yp_next(st->yp_domain, "services.byname", st->key, st->keylen, &st->key,
! 			     &st->keylen, &result, &resultlen);
  		free(lastkey);
  		if (rv) {
! 			st->serv_stepping_yp = 0;
! 			st->_notfound_block=1;
! 			return (NS_NOTFOUND);
  		}
  	}
  
  	/* getservent() expects lines terminated with \n -- make it happy */
! 	snprintf(st->line, BUFSIZ, "%.*s\n", resultlen, result);
  	free(result);
  
! 	p=st->line;
! 	if (_servent_unpack(&st->serv,st->serv_aliases,p,&q)!=_SERVENT_UNPACK_RETURN)
! 		return (NS_UNAVAIL);
! 
! 	*(struct servent **)retval=&st->serv;
! 	return(NS_SUCCESS);
  }
+ 
  #endif
+  
+ static void
+ compat_endstate(void * p)
+ {
+ 	struct compat_state * st;
+ 	if (p == NULL)
+ 		return;
  
! 	st=(struct compat_state *)p;
! 	if (st->files_st.servf!=NULL)
! 		fclose(st->files_st.servf);	
! #ifdef YP
! 	if (st->nis_st.key!=NULL)
! 		free(st->nis_st.key);
! #endif
! 	free(p);
! }
!  
! static int
! _compat_setservent(void *retval, void *mdata, va_list ap)
  {
! 	struct compat_state * st;
! 	int rv;
! 
! 	rv=compat_getstate(&st);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 	
! 	_files_setservent(retval,&st->current_condition,ap);
! #ifdef YP	
! 	_nis_setservent(retval,&st->current_condition,ap);
! 	st->current_condition=FILES_STATE;
! #endif
! 	return (NS_UNAVAIL);
! }
! 
! static	int
! _compat_endservent(void *retval, void *mdata, va_list ap)
! {
! 	struct compat_state * st;
! 	int rv;
! 
! 	rv=compat_getstate(&st);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 	
! 	_files_endservent(retval,&st->current_condition,ap);
! #ifdef YP
! 	_nis_endservent(retval,&st->current_condition,ap);
! 	st->current_condition=FILES_STATE;
! #endif
! 	return (NS_UNAVAIL);
! }
! 
! static int
!  _compat_getservent(void *retval, void *mdata, va_list ap)
! {
! 	struct compat_state * st;
! 	int rv;
! 
! 	int continue_flag=0;
! 
! 	rv=compat_getstate(&st);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 
! #ifdef YP
! 	do {
! 		switch (st->current_condition) {
! 			case FILES_STATE:
! 				rv=_files_getservent(retval,&st->current_condition,ap);
! 				if (st->current_condition==NIS_STATE)
! 					continue_flag=1;
! 				else
! 					return rv;
! 			break;
! 			
! 			case NIS_STATE:
! 				rv=_nis_getservent(retval,&st->current_condition,ap);
! 				if (rv!=NS_SUCCESS) {
! 					st->current_condition=FILES_STATE;
! 					continue_flag=1;
! 				} else 
! 					return NS_SUCCESS;
! 			break;
! 			
! 			default:
! 				/* NOT REACHED */
! 			break;
! 		}
! 	} while (continue_flag==1);
! #else
! 	return _files_getservent(retval,&st->current_condition,ap);
! #endif
! 
! 	/* NOT REACHED */
! 	return (NS_UNAVAIL);
! }
! 
! static int
! _compat_getservbyname(void *retval, void *mdata, va_list ap)
! {
! 	struct compat_state * st;
! 	int rv;
! 
! 	enum compat_condition current_condition;
! 
! 	rv=compat_getstate(&st);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
! 
!     	current_condition=FILES_STATE;
! 	rv=_files_getservbyname(retval,&current_condition,ap);
! 	
! 	return rv;
! }
! 
! static int
! _compat_getservbyport(void *retval, void *mdata, va_list ap)
! {
! 	struct compat_state * st;
! 	int rv;
! 
! 	enum compat_condition current_condition;
! 
! 	rv=compat_getstate(&st);
! 	if (rv != 0)
! 		return (NS_UNAVAIL);
!     
! 	current_condition=FILES_STATE;
! 	rv=_files_getservbyport(retval,&current_condition,ap);
! 	
! 	return rv;	
! }
! 
! struct servent *
! getservent(void)
! {
! 	struct servent * sv = 0;
! 	int rval;
! 	
! 	static const ns_dtab dtab[] = {
! 		{ NSSRC_FILES, _files_getservent, NULL },
! #ifdef YP		
! 		{ NSSRC_NIS, _nis_getservent, NULL },
! #endif
! 		{ NSSRC_COMPAT, _compat_getservent, NULL },
! 		{ NULL, NULL, NULL }
! 	};
! 		
! 	rval = _nsdispatch( (void *) &sv, dtab, NSDB_SERVICES, "getservent", defaultsrc, 0);
! 	
! 	if (rval != NS_SUCCESS)
! 		return NULL;
  	else
! 		return sv;
  }
  
  void
! setservent(int stayopen)
  {
!         static const ns_dtab dtab[] = {
!                 { NSSRC_FILES, _files_setservent, NULL },
! #ifdef YP                
!                 { NSSRC_NIS, _nis_setservent, NULL },
! #endif
!                 { NSSRC_COMPAT, _compat_setservent, NULL},
!                 { NULL, NULL, NULL }
!         };
! 		
!         (void)_nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc, stayopen);
  }
  
! void
! endservent(void)
  {
!         static const ns_dtab dtab[] = {
!                 { NSSRC_FILES, _files_endservent, NULL },
! #ifdef YP                
!                 { NSSRC_NIS, _nis_endservent, NULL },
! #endif
!                 { NSSRC_COMPAT, _compat_endservent, NULL},
!                 { NULL, NULL, NULL }
!         };
! 		
!         (void)_nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
! }
  
+ struct servent *
+ getservbyname(const char * name, const char * proto)
+ {
+ 	struct servent * sv = 0;
+ 	int rval;
+ 	
+ 	static const ns_dtab dtab[] = {
+ 			{ NSSRC_FILES,_files_getservbyname,NULL },
  #ifdef YP
! 			{ NSSRC_NIS,_nis_getservbyname,NULL },
  #endif
! 			{ NSSRC_COMPAT, _compat_getservbyname, NULL },
! 			{ 0 }
! 	};
! 	
! 	rval = _nsdispatch( (void *) &sv, dtab, NSDB_SERVICES, "getservbyname", defaultsrc, name, proto);
! 	
! 	if (rval != NS_SUCCESS)
! 		return NULL;
! 	else
! 		return sv;
  }
+ 
+ struct servent *
+ getservbyport(int port, const char * proto)
+ {
+ 	struct servent * sv = 0;
+ 	int rval;
+ 	
+ 	static const ns_dtab dtab[] = {
+ 			{ NSSRC_FILES,_files_getservbyport,NULL },
+ #ifdef YP			
+ 			{ NSSRC_NIS, _nis_getservbyport,NULL },
+ #endif
+ 			{ NSSRC_COMPAT, _compat_getservbyport, NULL } ,
+ 			{ 0 }
+ 	};
+ 	
+ 	rval = _nsdispatch( (void *) &sv, dtab, NSDB_SERVICES, "getservbyport", defaultsrc, port, proto);
+ 	
+ 	if (rval != NS_SUCCESS)
+ 		return NULL;
+ 	else
+ 		return sv;
+ 	} 
*** ./initial/getservbyname.c	Wed Jul 14 18:06:32 2004
--- getservbyname.c	Wed Jul 14 18:05:10 2004
***************
*** 38,81 ****
  __FBSDID("$FreeBSD: src/lib/libc/net/getservbyname.c,v 1.4 2002/03/21 18:49:23 obrien Exp $");
  
  #include <netdb.h>
  #include <string.h>
  
- extern int _serv_stayopen;
- 
- struct servent *
- getservbyname(name, proto)
- 	const char *name, *proto;
- {
- 	struct servent *p;
- 	char **cp;
- 
- #ifdef YP
- 	extern char *___getservbyname_yp;
- 	extern char *___getservbyproto_yp;
- 
- 	___getservbyname_yp = (char *)name;
- 	___getservbyproto_yp = (char *)proto;
- #endif
- 
- 	setservent(_serv_stayopen);
- 	while ( (p = getservent()) ) {
- 		if (strcmp(name, p->s_name) == 0)
- 			goto gotname;
- 		for (cp = p->s_aliases; *cp; cp++)
- 			if (strcmp(name, *cp) == 0)
- 				goto gotname;
- 		continue;
- gotname:
- 		if (proto == 0 || strcmp(p->s_proto, proto) == 0)
- 			break;
- 	}
- 	if (!_serv_stayopen)
- 		endservent();
- 
- #ifdef YP
- 	___getservbyname_yp = NULL;
- 	___getservbyproto_yp = NULL;
- #endif
- 
- 	return (p);
- }
--- 38,42 ----
*** ./initial/getservbyport.c	Wed Jul 14 18:06:32 2004
--- getservbyport.c	Wed Jul 14 18:05:17 2004
***************
*** 38,76 ****
  __FBSDID("$FreeBSD: src/lib/libc/net/getservbyport.c,v 1.4 2002/03/21 18:49:23 obrien Exp $");
  
  #include <netdb.h>
  #include <string.h>
  
- extern int _serv_stayopen;
- 
- struct servent *
- getservbyport(port, proto)
- 	int port;
- 	const char *proto;
- {
- 	struct servent *p;
- 
- #ifdef YP
- 	extern int ___getservbyport_yp;
- 	extern char *___getservbyproto_yp;
- 
- 	___getservbyport_yp = port;
- 	___getservbyproto_yp = (char *)proto;
- #endif
- 
- 	setservent(_serv_stayopen);
- 	while ( (p = getservent()) ) {
- 		if (p->s_port != port)
- 			continue;
- 		if (proto == 0 || strcmp(p->s_proto, proto) == 0)
- 			break;
- 	}
- 	if (!_serv_stayopen)
- 		endservent();
- 
- #ifdef YP
- 	___getservbyport_yp = 0;
- 	___getservbyproto_yp = NULL;
- #endif
- 
- 	return (p);
- }
--- 38,42 ----

--=-3nsEfv7dxSW/zpQIyhAD--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1093247765.10372.7.camel>