⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yp_bind.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#if	!defined(lint) && defined(SCCSIDS)static  char sccsid[] = "@(#)yp_bind.c 1.1 92/07/30 Copyr 1990 Sun Micro";#endif#ifdef	sun#define	MAP_STUFF 1#endif#include <stdio.h>#include <errno.h>#include <fcntl.h>#include <sys/time.h>#include <rpc/rpc.h>#include <rpc/pmap_prot.h>#include <sys/socket.h>#include <sys/fcntl.h>#include <sys/file.h>#include <sys/syslog.h>#include "yp_prot.h"#include "ypv1_prot.h"#include "ypclnt.h"#define	BFSIZE (YPMAXDOMAIN + 32) /* size of binding file *//* This should match the one in ypbind.c */#define	CACHE_DIR "/var/yp/binding"extern int errno;extern int sleep();extern malloc_t malloc();extern char *strcpy();static void _yp_unbind();enum	bind_status {	BS_BAGIT,	BS_RETRY,	BS_OK};bool check_pmap_up();bool check_binder_up();enum	bind_status talk2_pmap();enum	bind_status talk2_binder();void talk2_server();enum	bind_status get_binder_port();bool check_binding();void newborn();struct	dom_binding *load_dom_binding();/* * Time parameters when talking to the ypbind and pmap processes */#define	YPSLEEPTIME 5			/* Time to sleep between tries */unsigned int _ypsleeptime = YPSLEEPTIME;#define	YPBIND_TIMEOUT 30		/* Total seconds for timeout */#define	YPBIND_INTER_TRY 30		/* Seconds between tries */static struct timeval bind_intertry = {	YPBIND_INTER_TRY,		/* Seconds */	0				/* Microseconds */	};static struct timeval bind_timeout = {	YPBIND_TIMEOUT,			/* Seconds */	0				/* Microseconds */	};/* * Time parameters when talking to the ypserv process */#ifdef	 DEBUG#define	YPTIMEOUT 120			/* Total seconds for timeout */#define	YPINTER_TRY 60			/* Seconds between tries */#else#define	YPTIMEOUT 90			/* Total seconds for timeout */#define	YPINTER_TRY 5			/* Seconds between tries */#endif#define	MAX_TRIES_FOR_NEW_YP 1		/* Number of times we'll try to get					 *   a new YP server before we'll					 *   settle for an old one. */static struct timeval ypserv_intertry = {	YPINTER_TRY,			/* Seconds */	0				/* Microseconds */	};struct	timeval _ypserv_timeout = {	YPTIMEOUT,			/* Seconds */	0				/* Microseconds */	};static struct in_addr my_addr;		/* Local internet addr */static struct dom_binding *bound_domains; /* List of bound domains */static char *default_domain;static char	bfinvalid;		/* Binding file invalid	*/static char     *bfname;#ifdef	MAP_STUFF#include <sys/mman.h>static u_short	*binderfilemap;		/* Mapped version of binder */#define	MAP_LEN (2+sizeof(struct ypbind_resp))			/* just for current udp only*/#endifstatic int	bf;			/* Binding file fd	*//* * binder_port holds what we believe to be the local port for ypbind.  It is * set only by talk2_pmap.  It is cleared (set to 0) by: *	1. talk2_pmap: always upon entry. *	2. check_binder_up if: *		- It can't create a socket to speak to the binder. *		- If it fails to bind to the port. *	3. talk2_binder if there are RPC errors when trying to use the port. */static unsigned long binder_port;	/* Initialize to "no port" *//* * Attempts to locate a NIS server that serves a passed domain.  If * one is found, an entry is created on the static list of domain-server pairs * pointed to by cell bound_domains, a udp path to the server is created and * the function returns 0.  Otherwise, the function returns a defined errorcode * YPERR_xxxx. */int_yp_dobind(domain, binding)	char *domain;	struct dom_binding **binding;	/* if result == 0, ptr to dom_binding */{return (_yp_dobind_soft(domain,binding, -1));}int_yp_dobind_soft(domain, binding,usertries)	char *domain;	struct dom_binding **binding;	/* if result == 0, ptr to dom_binding */	int usertries;{	struct dom_binding *pdomb;	/* Ptr to new domain binding */	struct sockaddr_in ypbinder;	/* To talk with ypbinder */	char *pdomain;			/* For xdr interface */	struct ypbind_resp ypbind_resp; /* Response from local ypbinder */	int vers;			/* ypbind program version number */	int tries;			/* Number of times we've tried with					 *  the current protocol */	int gbtries;			/* Number of times we've tried to					 *  get the binder */	int status;	u_short		b_port;	enum bind_status loopctl;	bool bound;	bool oldport = FALSE;#ifdef	MAP_STUFF	char tmpbfname[BFSIZE];#endif	if ( (domain == NULL) ||(strlen(domain) == 0) ) {		return (YPERR_BADARGS);	}	newborn();	if (bfname==0){	bfname=(char *)calloc(1,BFSIZE);	}	if (bfname==0){	bfinvalid=TRUE;	}	if (!bfinvalid) {#ifdef	MAP_STUFF		sprintf(tmpbfname,"%s/%s.%d",CACHE_DIR,domain,YPVERS);		if (strcmp(bfname,tmpbfname)==0){ /*same name*/			if (binderfilemap){			binder_port =  binderfilemap[0];			}		} else {			bfname[0]=0;			if (binderfilemap){			munmap(binderfilemap,MAP_LEN);			binderfilemap=0;			}			if ((bf = open(tmpbfname,O_RDONLY)) != -1) {			if (flock(bf,LOCK_EX+LOCK_NB) == 0) {				close(bf);				bf = -1; /* Not valid if we would lock it */			} else {			binderfilemap=(u_short *)mmap(bfname,MAP_LEN,PROT_READ,MAP_SHARED,bf,0);			if ((int)binderfilemap == -1) binderfilemap=0;			if (binderfilemap){				strcpy(bfname,tmpbfname);				binder_port =  binderfilemap[0];				close(bf);				}			else   {				close(bf);				bf= -1; /*map failed*/				}			   }			}		}#else		sprintf(bfname,"%s/%s.%d",CACHE_DIR,domain,YPVERS);		if ((bf = open(bfname,O_RDONLY)) != -1) {			if (flock(bf,LOCK_EX+LOCK_NB) == 0) {				close(bf);				bf = -1; /* Not valid if we would lock it */			} else {				read(bf,&b_port,sizeof(u_short));				binder_port = b_port;				close(bf);			}		}#endif	}	if (check_binding(domain, binding) )		return (0);		/* We are bound */	/*	 * Use loopback address.	 */	my_addr.s_addr = INADDR_LOOPBACK;	pdomain = domain;	/*	 * Try to get the binder's port, using the current program version.	 * The version may be changed to the old version, deep in the bowels	 * of talk2_binder.	 */	for (bound = FALSE, vers = YPBINDVERS; !bound; ) {		if (binder_port) {			oldport = TRUE;		} else {			oldport = FALSE;			/*			 * Get the binder's port.  We'll loop as long as			 * get_binder_port returns BS_RETRY.			 */			for (gbtries=0,loopctl = BS_RETRY; loopctl != BS_OK;gbtries++ ) {				if ((usertries>=0) && gbtries >=usertries) return (status);	 			switch (loopctl =				    get_binder_port(vers, &status) ) {				case BS_BAGIT:					return (status);				case BS_OK:					break;				}			}		}		/*		 * See whether ypbind is up.  If no, bag it if it's a		 * resource error, or if we are using a port we just got		 * from the port mapper.  Otherwise loop around to try to		 * get a valid port.		 */		if (!check_binder_up(&ypbinder, &status)) {			if (status == YPERR_RESRC) {				return (status);			}			if (!oldport && status == YPERR_YPBIND) {				return (status);			}			continue;		}		/*		 * At this point, we think we know how to talk to the		 * binder, and the binder is apparently alive.  Until we		 * succeed in binding the domain, or we know we can't ever		 * bind the domain, we will try forever.  This loops when		 * talk2_binder returns BS_RETRY, and terminates when		 * talk2_binder returns BS_BAGIT, or BS_OK.  If binder_port		 * gets cleared, we will not execute this loop again, but		 * will go to the top of the enclosing loop to try to get		 * the binder's port again.  It is never the case that both		 * talk2_binder returns  BS_OK and that it clears the		 * binder_port.		 */		for (loopctl = BS_RETRY, tries = 1;		    binder_port && (loopctl != BS_OK); tries++) {			switch (loopctl = talk2_binder(&ypbinder, &vers,			    tries, &pdomain, &ypbind_resp, &status) ) {			case BS_BAGIT:				return (status);			case BS_OK:				bound = TRUE;			}			if ((usertries>=0) && tries >=usertries) return (status);		}	}	if ( (pdomb = load_dom_binding(&ypbind_resp, vers, domain, &status) ) ==	    (struct dom_binding *) NULL) {		return (status);	}	if (vers == YPBINDOLDVERS) {		talk2_server(pdomb);	}	*binding = pdomb;			/* Return ptr to the binding						 *   entry */	return (0);				/* This is the go path */}/* * This is a "wrapper" function for _yp_dobind_soft for vanilla user-level * functions which neither know nor care about struct dom_bindings. */intyp_bind(domain)	char *domain;{	struct dom_binding *binding;	return (_yp_dobind(domain, &binding) );}/* * This is a "wrapper" function for _yp_dobind_soft for vanilla user-level * functions which neither know nor care about struct dom_bindings. */intyp_softbind(domain,tries)	char *domain;	int tries;{	struct dom_binding *binding;	return (_yp_dobind_soft(domain, &binding, tries) );}/* * Attempts to find a dom_binding in the list at bound_domains having the * domain name field equal to the passed domain name, and removes it if found. * The domain-server binding will not exist after the call to this function. * All resources associated with the binding will be freed. */voidyp_unbind (domain)	char *domain;{_yp_unbind(domain, TRUE);}static void_yp_unbind (domain, invalidate)	char *domain;	bool_t invalidate; /*the binding file*/{	struct dom_binding *pdomb;	struct dom_binding *ptrail = 0;	struct sockaddr_in local_name;	int local_name_len;	if ( (domain == NULL) ||(strlen(domain) == 0) ) {		return;	}	if (invalidate) bfinvalid = TRUE; /* Don't use binding file again */	for (pdomb = bound_domains; pdomb != NULL;	    ptrail = pdomb, pdomb = pdomb->dom_pnext) {		if (strcmp(domain, pdomb->dom_domain) == 0) {			/*			 * The act of destroying the rpc client closes			 * the associated socket.  However, the fd			 * representing what we believe to be our socket may			 * really belong to someone else due to closes			 * followed by new opens.   So let us be very careful!			 */			local_name_len = sizeof (local_name);			if ((getsockname(pdomb->dom_socket,			    (struct sockaddr *) &local_name,			    &local_name_len) != 0)  ||			    (local_name.sin_family != AF_INET) ||			    (local_name.sin_port != pdomb->dom_local_port) ) {				int tmp, tobesaved;				tmp = dup(tobesaved = pdomb->dom_socket);				clnt_destroy(pdomb->dom_client);				tobesaved = dup2(tmp, tobesaved);				(void) close(tmp);			} else {				clnt_destroy(pdomb->dom_client);				(void) close(pdomb->dom_socket);			}			if (pdomb == bound_domains) {				bound_domains = pdomb->dom_pnext;			} else {				ptrail->dom_pnext = pdomb->dom_pnext;			}			free((char *) pdomb);			break;		}	}}static char *_default_domain(){	char temp[256];	if (default_domain)		return (default_domain);	if (getdomainname(temp, sizeof(temp)))		return (0);	if (strlen(temp) > 0) {		default_domain = (char *)malloc(strlen(temp)+1);		if (default_domain == 0)			return (0);		strcpy(default_domain, temp);		return (default_domain);	}	return (0);}/* * This is a wrapper for the system call getdomainname which returns a * ypclnt.h error code in the failure case.  It also checks to see that * the domain name is non-null, knowing that the null string is going to * get rejected elsewhere in the NIS client package. */intyp_get_default_domain(domain)	char **domain;{	if ((*domain = _default_domain()) != 0)		return (0);	return (YPERR_YPERR);}/* * This checks to see if this is a new process incarnation which has * inherited bindings from a parent, and unbinds the world if so. */static voidnewborn(){	static long int mypid;	/* Cached to detect forks */	long int testpid;	if ((testpid = getpid() ) != mypid) {		mypid = testpid;		while (bound_domains) {			_yp_unbind(bound_domains->dom_domain, FALSE);			/*do not unmap the file*/		}	}}/* * This checks that the socket for a domain which has already been bound * hasn't been closed or changed under us.  If it has, unbind the domain * without closing the socket, which may be in use by some higher level * code.  This returns TRUE and points the binding parameter at the found * dom_binding if the binding is found and the socket looks OK, and FALSE

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -