misc/69650: make getserv* functions work with nsdispatch

Michael Bushkov bushman at stinger.cc.rsu.ru
Tue Jul 27 00:40:37 PDT 2004


>Number:         69650
>Category:       misc
>Synopsis:       make getserv* functions work with nsdispatch
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 27 07:40:36 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Michael Bushkov
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
Rostov State Universiry
>Environment:
System: FreeBSD stinger.cc.rsu.ru 5.2-CURRENT FreeBSD 5.2-CURRENT #1: Fri Jun 25 12:56:22 MSD 2004 bushman at stinger.cc.rsu.ru:/usr/obj/usr/src/sys/STINGER i386


	
>Description:
	Patch adds nsdispatch functionality to getserv* functions.
	It implements nis, files and compat sources.
	It shold be applied to files in src/lib/libc/net/
>How-To-Repeat:
>Fix:

--- getserv.patch begins here ---
*** ./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, 0);
  }
  
! 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, 0);
! }
  
+ 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 ----
--- getserv.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list