ypwhich.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 687 行

C
687
字号
#ifndef lintstatic char *sccsid = "@(#)ypwhich.c	4.3  (ULTRIX)       11/13/90";#endif lint/**************************************************************** *								* *  Licensed to Digital Equipment Corporation, Maynard, MA	* *		Copyright 1985 Sun Microsystems, Inc.		* *			All rights reserved.			* *								* ****************************************************************//* Modification History: *  * Oct 30 1990  terry *              Fixed bug in "print_server" which printed internet *              addresses in reverse order. *//* * This is a user command which tells which yp server is being used by a * given machine, or which yp server is the master for a named map. *  * Usage is: * ypwhich [-d domain] [-m [mname] [-t] | [-V1 | -V2] host] * or * ypwhich -x *  * where:  the -d switch can be used to specify a domain other than the * default domain.  -m tells the master of that map. * mname may be either a  mapname, or a nickname which will be * translated into a mapname according to the translation table at * transtable.  The  -t switch inhibits this translation. * If the -m option is used, ypwhich will act like a vanilla * yp client, and will not attempt to choose a particular yp server. * On the other hand, if no -m switch is used, ypwhich will talk * directly to the yp bind process on the named host, or to the local * ypbind process if no host name is specified.  The -x switch can be * used to dump the nickname translation table. *   */#include <stdio.h>#include <ctype.h>#include <rpc/rpc.h>#include <netdb.h>#include <sys/time.h>#include <sys/socket.h>#include <rpcsvc/yp_prot.h>#include <rpcsvc/ypv1_prot.h>#include <rpcsvc/ypclnt.h>#define TIMEOUT 30			/* Total seconds for timeout */#define INTER_TRY 10			/* Seconds between tries */bool translate = TRUE;bool dodump = FALSE;bool newvers = FALSE;bool oldvers = FALSE;bool ask_specific = FALSE;char *domain = NULL;char default_domain_name[YPMAXDOMAIN];char *host = NULL;char default_host_name[256];struct in_addr host_addr;bool get_master = FALSE;bool get_server = FALSE;char *map = NULL;struct timeval udp_intertry = {	INTER_TRY,			/* Seconds */	0				/* Microseconds */	};struct timeval udp_timeout = {	TIMEOUT,			/* Seconds */	0				/* Microseconds */	};char *transtable[] = {	"passwd", "passwd.byname",	"group", "group.byname",	"networks", "networks.byaddr",	"hosts", "hosts.byaddr",	"protocols","protocols.bynumber",	"services","services.byname",	"aliases","mail.aliases",	"ethers", "ethers.byname",	NULL};char err_usage[] ="Usage:\n\	ypwhich [-d domain] [[-t] -m [mname] | [-V1 | -V2] host]\n\	ypwhich -x\n";char err_bad_args[] =	"ypwhich:  %s argument is bad.\n";char err_cant_get_kname[] =	"ypwhich:  can't get %s back from system call.\n";char err_null_kname[] =	"ypwhich:  the %s hasn't been set on this machine.\n";char err_bad_mapname[] = "mapname";char err_bad_domainname[] = "domainname";char err_bad_hostname[] = "hostname";char err_first_failed[] =	"ypwhich:  can't get first record from yp.  Reason:  %s.\n";char err_next_failed[] =	"ypwhich:  can't get next record from yp.  Reason:  %s.\n";void get_command_line_args();void getdomain();void getlochost();void getrmthost();void get_server_name();bool call_binder();void print_server();void get_map_master();void dumptable();void dump_ypmaps();void v1dumpmaps();void v2dumpmaps();/* * This is the main line for the ypwhich process. */main(argc, argv)	char **argv;{	int addr;	int err;	struct ypbind_resp response;	int i;	get_command_line_args(argc, argv);	if (dodump) {		dumptable();		exit(0);	}	if (!domain) {		getdomain();	}		if (get_server) {				if (!host) {			getlochost();		} else {			getrmthost();		}		get_server_name();	} else {				if (map) {				if (translate) {										for (i = 0; transtable[i]; i+=2) {					    					if (strcmp(map, transtable[i]) == 0) {						map = transtable[i+1];					}				}			}						get_map_master();		} else {			dump_ypmaps();		}	}	exit(0);}/* * This does the command line argument processing. */voidget_command_line_args(argc, argv)	int argc;	char **argv;	{	argv++;	if (argc == 1) {		get_server = TRUE;		return;	}		while (--argc) {		if ( (*argv)[0] == '-') {			switch ((*argv)[1]) {			case 't': 				translate = FALSE;				argv++;				break;			case 'x': 				dodump = TRUE;				argv++;				break;			case 'V':				if ((*argv)[2] == '1') {					oldvers = TRUE;					argv++;					break;				} else if ((*argv)[2] == '2') {					newvers = TRUE;					argv++;					break;				} else {					fprintf(stderr, err_usage);					exit(1);				}			case 'm': 				get_master = TRUE;				argv++;								if (argc > 1) {										if ( (*(argv))[0] == '-') {						break;					}										argc--;					map = *argv;					argv++;					if (strlen(map) > YPMAXMAP) {						fprintf(stderr, err_bad_args,						    err_bad_mapname);						exit(1);					}									}								break;							case 'd': 				if (argc > 1) {					argv++;					argc--;					domain = *argv;					argv++;					if (strlen(domain) > YPMAXDOMAIN) {						fprintf(stderr, err_bad_args,						    err_bad_domainname);						exit(1);					}									} else {					fprintf(stderr, err_usage);					exit(1);				}								break;							default: 				fprintf(stderr, err_usage);				exit(1);			}					} else {						if (get_server) {				fprintf(stderr, err_usage);				exit(1);			}					get_server = TRUE;			host = *argv;			argv++;						if (strlen(host) > 256) {				fprintf(stderr, err_bad_args, err_bad_hostname);				exit(1);			}		}	}	if (newvers && oldvers) {		fprintf(stderr, err_usage);		exit(1);	}		if (newvers || oldvers) {		ask_specific = TRUE;	}		if (get_master && get_server) {		fprintf(stderr, err_usage);		exit(1);	}		if (!get_master && !get_server) {		get_server = TRUE;	} }/* * This gets the local default domainname, and makes sure that it's set * to something reasonable.  domain is set here. */voidgetdomain()		{	if (!getdomainname(default_domain_name, YPMAXDOMAIN) ) {		domain = default_domain_name;	} else {		fprintf(stderr, err_cant_get_kname, err_bad_domainname);		exit(1);	}	if (strlen(domain) == 0) {		fprintf(stderr, err_null_kname, err_bad_domainname);		exit(1);	}}/* * This gets the local hostname back from the kernel, and comes up with an * address for the local node without using the yp.  host_addr is set here. */voidgetlochost(){	struct sockaddr_in myaddr;	if (! gethostname(default_host_name, 256)) {		host = default_host_name;	} else {		fprintf(stderr, err_cant_get_kname, err_bad_hostname);		exit(1);	}	get_myaddress(&myaddr);	host_addr = myaddr.sin_addr;}/* * This gets an address for some named node by calling the standard library * routine gethostbyname.  host_addr is set here. */voidgetrmthost(){			struct in_addr tempaddr;	struct hostent *hp;		if (isdigit(*host) ) {		tempaddr.s_addr = inet_addr(host);		if ((int) tempaddr.s_addr != -1) {			host_addr = tempaddr;			return;		}	}		hp = gethostbyname(host);			if (hp == NULL) {	    	fprintf(stderr, "ypwhich: can't find %s\n", host);		exit(1);	}		host_addr.s_addr = *(u_long *)hp->h_addr;}/* * This tries to find the name of the server to which the binder in question * is bound.  If one of the -Vx flags was specified, it will try only for * that protocol version, otherwise, it will start with the current version, * then drop back to the previous version. */voidget_server_name(){	int vers;	struct in_addr server;	char *notbound = "Domain %s not bound.\n";		if (ask_specific) {		vers = oldvers ? YPBINDOLDVERS : YPBINDVERS;				if (call_binder(vers, &server)) {			print_server(&server);		} else {			fprintf(stderr, notbound, domain);			exit(2);		}			} else {		vers = YPBINDVERS;				if (call_binder(vers, &server)) {			print_server(&server);		} else {			vers = YPBINDOLDVERS;					if (call_binder(vers, &server)) {				print_server(&server);			} else {				fprintf(stderr, notbound, domain);				exit(2);			}		}	}}/* * This sends a message to the ypbind process on the node with address held * in host_addr. */boolcall_binder(vers, server)	int vers;	struct in_addr *server;{	struct sockaddr_in query;	CLIENT *client;	int sock = RPC_ANYSOCK;	enum clnt_stat rpc_stat;	struct ypbind_resp response;	char errstring[256];	query.sin_family = AF_INET;	query.sin_port = 0;	query.sin_addr = host_addr;	bzero(query.sin_zero, 8);		if ((client = clntudp_create(&query, YPBINDPROG, vers, udp_intertry,	    &sock)) == NULL) {                if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) {                        (void) printf("ypwhich: %s is not running ypbind\n",                                host);                        exit(1);                }                if (rpc_createerr.cf_stat == RPC_PMAPFAILURE) {                    (void) printf("ypwhich: %s is not running port mapper\n",                                host);                        exit(1);                }		(void) clnt_pcreateerror("ypwhich:  clntudp_create error");		exit(1);	}	rpc_stat = clnt_call(client, YPBINDPROC_DOMAIN,	    xdr_ypdomain_wrap_string, &domain, xdr_ypbind_resp, &response,	    udp_timeout);	    	if ((rpc_stat != RPC_SUCCESS) &&	    (rpc_stat != RPC_PROGVERSMISMATCH) ) {		(void) sprintf(errstring,		    "ypwhich: can't call ypbind on %s", host);		(void) clnt_perror(client, errstring);		exit(1);	}	*server = response.ypbind_respbody.ypbind_bindinfo.ypbind_binding_addr;	clnt_destroy(client);	close(sock);		if ((rpc_stat != RPC_SUCCESS) ||	    (response.ypbind_status != YPBIND_SUCC_VAL) ) {		return (FALSE);	}		return (TRUE);}/* * This translates a server address to a name and prints it.  If the address * is the same as the local address as returned by get_myaddress, the name * is that retrieved from the kernel.  If it's any other address (including * another ip address for the local machine), we'll get a name by using the * standard library routine (which calls the yp).   */voidprint_server(server)	struct in_addr *server;{	struct sockaddr_in myaddr;	char myname[256];	struct hostent *hp;		get_myaddress(&myaddr);		if (server->s_addr == myaddr.sin_addr.s_addr) {				if (gethostname(myname, 256)) {			fprintf(stderr, err_cant_get_kname, err_bad_hostname);			exit(1);		}		printf(myname);		printf("\n");	} else {		extern char *inet_ntoa();				/** this should be fixed in the future **/		/** hack because vax yp code doesn't do htonl() with addresses **/		if((hp = gethostbyaddr(server, sizeof(server), AF_INET)) == NULL){			server->s_addr = htonl(server->s_addr);			hp = gethostbyaddr(server, sizeof(server), AF_INET); 		}		if (!hp)		        server->s_addr = ntohl(server->s_addr);		printf("%s\n", hp ? hp->h_name : inet_ntoa(*server) );	}}/* * This asks any yp server for the map's master.   */voidget_map_master(){	int err;	char *master;     	err = yp_master(domain, map, &master);		if (err) {		fprintf(stderr,		    "ypwhich:  Can't find the master of %s.  Reason: %s.\n",		    map, yperr_string(err) );	} else {		printf("%s\n", master);	}}/* * This will print out the map nickname translation table. */voiddumptable(){	int i;	for (i = 0; transtable[i]; i += 2) {		printf("Use \"%s\" for map \"%s\"\n", transtable[i],		    transtable[i + 1]);	}}/* * This enumerates the entries within map "ypmaps" in the domain at global  * "domain", and prints them out key and value per single line.  dump_ypmaps * just decides whether we are (probably) able to speak the new YP protocol, * and dispatches to the appropriate function. */voiddump_ypmaps(){	int err;	struct dom_binding *binding;		if (err = _yp_dobind(domain, &binding)) {		fprintf(stderr,		    "dump_ypmaps: Can't bind for domain %s.  Reason: %s\n",		    domain, yperr_string(ypprot_err(err)));		return;	}	if (binding->dom_vers == YPVERS) {		v2dumpmaps(binding);	} else {		v1dumpmaps();	}}voidv1dumpmaps(){	char *key;	int keylen;	char *outkey;	int outkeylen;	char *val;	int vallen;	int err;	char *scan;		if (err = yp_first(domain, "ypmaps", &outkey, &outkeylen, &val,	    &vallen) ) {		if (err = YPERR_NOMORE) {			exit(0);		} else {			fprintf(stderr, err_first_failed,			    yperr_string(err) );		}		exit(1);	}	while (TRUE) {		for (scan = outkey; *scan != NULL; scan++) {			if (*scan == '\n') {				*scan = ' ';  			}		}		if (strlen(outkey) < 3 || strncmp(outkey, "YP_", 3) ) {			printf(outkey);			printf(val);		}				free(val);		key = outkey;		keylen = outkeylen;				if (err = yp_next(domain, "ypmaps", key, keylen, &outkey,		    &outkeylen, &val, &vallen) ) {			if (err == YPERR_NOMORE) {				break;			} else {				fprintf(stderr, err_next_failed,				    yperr_string(err) );				exit(1);			}		}		free(key);	}}voidv2dumpmaps(binding)	struct dom_binding *binding;{	enum clnt_stat rpc_stat;	int err;	char *master;	struct ypmaplist *pmpl;	struct ypresp_maplist maplist;	maplist.list = (struct ypmaplist *) NULL;		rpc_stat = clnt_call(binding->dom_client, YPPROC_MAPLIST,	    xdr_ypdomain_wrap_string, &domain, xdr_ypresp_maplist, &maplist,	    udp_timeout);	if (rpc_stat != RPC_SUCCESS) {		(void) clnt_perror(binding->dom_client,		    "ypwhich(v2dumpmaps): can't get maplist");		exit(1);	}	if (maplist.status != YP_TRUE) {		fprintf(stderr,		    "ypwhich:  Can't get maplist.  Reason:  %s.\n",		    yperr_string(ypprot_err(maplist.status)) );		exit(1);	}	for (pmpl = maplist.list; pmpl; pmpl = pmpl->ypml_next) {		printf("%s ", pmpl->ypml_name);				err = yp_master(domain, pmpl->ypml_name, &master);			if (err) {			printf("????????\n");			fprintf(stderr,		  "      ypwhich:  Can't find the master of %s.  Reason: %s.\n",		   	    pmpl->ypml_name, yperr_string(err) );		} else {			printf("%s\n", master);		}	}}

⌨️ 快捷键说明

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