yppush.c

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

C
844
字号
	name[namelen] = '\0';	(void) strcpy(ps->name, name);	ps->state = SSTAT_INIT;	ps->status = 0;	ps->oldvers = FALSE;		if (h = (struct hostent *) gethostbyname(name) ) {		ps->domb.dom_server_addr.sin_addr =		    *((struct in_addr *) h->h_addr);		ps->domb.dom_server_addr.sin_family = AF_INET;		ps->domb.dom_server_addr.sin_port = 0;		ps->domb.dom_server_port = 0;		ps->domb.dom_socket = RPC_ANYSOCK;		ps->xactid = xactid + seq++;		ps->pnext = server_list;		server_list = ps;	} else {		(void) fprintf(stderr, "Can't get an address for server %s.\n",		    name);		free(ps);	}}/* * This sets the base range for the transaction ids used in speaking the the *  server ypxfr processes. */voidxactid_seed(xactid)unsigned long *xactid;{	struct timeval t;	if (gettimeofday(&t, (struct timezone *) NULL) == -1) {		perror("yppush gettimeofday failure");		*xactid = 1234567;	} else {		*xactid = t.tv_sec;	}}/* *  This generates the udp channel which will be used as the listener process' *  service rendezvous point, and comes up with a transient program number *  for the use of the RPC messages from the ypxfr processes. */voidgenerate_callback(program, port, transport)	unsigned long *program;	unsigned short *port;	SVCXPRT **transport;{	struct sockaddr_in a;	long unsigned prognum;	SVCXPRT *xport;	if ((xport = svcudp_create(RPC_ANYSOCK) ) == (SVCXPRT *) NULL) {		(void) fprintf(stderr, "Can't set up as a udp server.\n");		exit(1);	}		*port = xport->xp_port;	*transport = xport;	prognum = 0x40000000;	while (!pmap_set(prognum++, YPPUSHVERS, IPPROTO_UDP, xport->xp_port) ) {		;	}	*program = --prognum;}/* * This is the main loop. Send messages to each server, * and then wait for a response. */voidmain_loop(program, port)	unsigned long program;	unsigned short port;{	int readfds;	register struct server *ps;	long error;	if (!svc_register(transport, program, YPPUSHVERS,	    listener_dispatch, 0) ) {		(void) fprintf(stderr,		    "Can't set up transient callback server.\n");	}	signal(SIGALRM, set_time_up);	signal(SIGHUP, set_interrupt);	signal(SIGINT, set_interrupt);	signal(SIGQUIT, set_interrupt);	signal(SIGTERM, set_interrupt);		for (ps = server_list; ps; ps = ps->pnext) {		ps->state = send_message(ps, program, port, &error);		print_state_msg(ps, error);		if (ps->state != SSTAT_CALLED) continue;		callback_timeout = FALSE;				(void) alarm(GRACE_PERIOD);		while ( callback_timeout == FALSE && 		         ps->state == SSTAT_CALLED ) {		  readfds = svc_fds;		  errno = 0;		  switch ( (int) select(32, &readfds, NULL, NULL, NULL) ) {		    case -1:					if (errno != EINTR) {				(void) perror("main loop select");				callback_timeout = TRUE;			}			break;		    case 0:			(void) fprintf (stderr,			    "Invalid timeout in main loop select.\n");			break;		    default: 			svc_getreq(readfds);			break;		} /* switch */	    } /* while */  	    (void) alarm(0);	    if (ps->state == SSTAT_CALLED && !INTERRUPT)	    	(void) fprintf( stderr,		  "No response from ypxfr on %s\n", ps->name);	    if (INTERRUPT) {		(void) fprintf(stderr,"\nyppush: Operation interrupted, exiting..\n");	        listener_exit(program, -1);	    }	} /* for each server */}/* * This does the listener process cleanup and process exit. */voidlistener_exit(program, stat)	unsigned long program;	int stat;{	(void) pmap_unset(program, YPPUSHVERS);	exit(stat);}/* * This is the listener process' RPC service dispatcher. */voidlistener_dispatch(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	switch (rqstp->rq_proc) {	case YPPUSHPROC_NULL:		if (!svc_sendreply(transp, xdr_void, 0) ) {			(void) fprintf(stderr,			    "Can't reply to rpc call.\n");		}		break;	case YPPUSHPROC_XFRRESP:		get_xfr_response(rqstp, transp);		break;			default:		svcerr_noproc(transp);		break;	}}/* *  This dumps a server state message to stdout.  It is called in cases where *  we have no expectation of receiving a callback from the remote ypxfr. */voidprint_state_msg(s, e)	struct server *s;	long e;{	struct state_duple *sd;	if (s->state == SSTAT_SYSTEM)		return;			/* already printed */	if (!verbose && ( s->state == SSTAT_RESPONDED ||			  s->state == SSTAT_CALLED) )		return;		for (sd = state_duples; sd->state_msg; sd++) {		if (sd->state == s->state) {			(void) printf(sd->state_msg, s->name);			if (s->state == SSTAT_RPC) {				rpcerr_msg((enum clnt_stat) e);			}						(void) printf("\n");			fflush(stdout);			return;		}	}	(void) fprintf(stderr,	  "yppush: Bad server state value %d.\n", s->state);}/* *  This dumps a transfer status message to stdout.  It is called in  *  response to a received RPC message from the called ypxfr. */voidprint_callback_msg(s)	struct server *s;{	register struct status_duple *sd;	if (!verbose && (s->status==YPPUSH_AGE) || (s->status==YPPUSH_SUCC))		return;	for (sd = status_duples; sd->status_msg; sd++) {		if (sd->status == s->status) {			(void) printf(			    "Status received from ypxfr on %s:\n\t%s\n",			    s->name, sd->status_msg);			fflush(stdout);			return;		}	}	(void) fprintf(stderr,	"yppush listener: Garbage transaction status value from ypxfr on %s.\n",	    s->name);}/* *  This dumps an RPC error message to stdout.  This is basically a rewrite *  of clnt_perrno, but writes to stdout instead of stderr. */voidrpcerr_msg(e)	enum clnt_stat e;{	struct rpcerr_duple *rd;	for (rd = rpcerr_duples; rd->rpc_msg; rd++) {		if (rd->rpc_stat == e) {			(void) printf(rd->rpc_msg);			return;		}	}	(void) fprintf(stderr,"Bad error code passed to rpcerr_msg: %d.\n",e);}/* * This picks up the response from the ypxfr process which has been started * up on the remote node.  The response status must be non-zero, otherwise * the status will be set to "ypxfr error". */voidget_xfr_response(rqstp, transp)	struct svc_req *rqstp;	SVCXPRT *transp;{	struct yppushresp_xfr resp;	register struct server *s;		if (!svc_getargs(transp, xdr_yppushresp_xfr, &resp) ) {		svcerr_decode(transp);		return;	}	if (!svc_sendreply(transp, xdr_void, 0) ) {		(void) fprintf(stderr, "Can't reply to rpc call.\n");	}	for (s = server_list; s; s = s->pnext) {				if (s->xactid == resp.transid) {			s->status  = resp.status ? resp.status: YPPUSH_XFRERR;			print_callback_msg(s);			s->state = SSTAT_RESPONDED;			return;		}	}}/* * This is a UNIX signal handler which is called when the * timer expires waiting for a callback. */voidset_time_up(){	callback_timeout = TRUE;}/* Signal handler for "other" interruptions. Used so we don't * leave spurious registrations with the portmapper. */voidset_interrupt(){	set_time_up();	INTERRUPT = TRUE;}/* * This sends a message to a single ypserv process.  The return value is * a state value.  If the RPC call fails because of a version * mismatch, we'll assume that we're talking to a version 1 ypserv process, * and will send him an old "YPPROC_GET" request, as was defined in the * earlier version of yp_prot.h */unsigned shortsend_message(ps, program, port, err)	struct server *ps;	unsigned long program;	unsigned short port;	long *err;{	struct ypreq_xfr req;	struct yprequest oldreq;	enum clnt_stat s;	char my_name[YPMAXPEER +1];	struct rpc_err rpcerr;	if ((ps->domb.dom_client = clntudp_create(&(ps->domb.dom_server_addr),	    YPPROG, YPVERS, udp_intertry, &(ps->domb.dom_socket)))  == NULL) {		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED) {			return(SSTAT_PROGNOTREG);		} else {			(void) printf("Error talking to %s: ",ps->name);			rpcerr_msg(rpc_createerr.cf_stat);			(void) printf("\n");			fflush(stdout);			return(SSTAT_SYSTEM);		}	}	if (gethostname(my_name, sizeof (my_name) ) == -1) {		return(SSTAT_RSCRC);	}	req.ypxfr_domain = domain;	req.ypxfr_map = map;	req.ypxfr_ordernum = 0;	req.ypxfr_owner = my_name;	req.transid = ps->xactid;	req.proto = program;	req.port = port;	s = (enum clnt_stat) clnt_call(ps->domb.dom_client, YPPROC_XFR,	    xdr_ypreq_xfr, &req, xdr_void, 0, udp_timeout);	clnt_geterr(ps->domb.dom_client, &rpcerr);	clnt_destroy(ps->domb.dom_client);	close(ps->domb.dom_socket);		if (s == RPC_SUCCESS) {		return (SSTAT_CALLED);	} else {		if (s == RPC_PROGVERSMISMATCH) {			ps->domb.dom_server_addr.sin_family = AF_INET;			ps->domb.dom_server_addr.sin_port = 0;			ps->domb.dom_server_port = 0;			ps->domb.dom_socket = RPC_ANYSOCK;						if ((ps->domb.dom_client =			    clntudp_create(&(ps->domb.dom_server_addr),	    		    YPPROG, (YPVERS - 1), udp_intertry,			    &(ps->domb.dom_socket)))  == NULL) {				if (rpc_createerr.cf_stat ==				    RPC_PROGNOTREGISTERED) {					return(SSTAT_PROGNOTREG);				} else {			(void) printf("V1 Error talking to %s: ",				ps->name);					rpcerr_msg(rpc_createerr.cf_stat);					(void) printf("\n");					fflush(stdout);					return(SSTAT_SYSTEM);				}			}						oldreq.yp_reqtype = YPGET_REQTYPE;			oldreq.ypget_req_domain = domain;			oldreq.ypget_req_map = map;			oldreq.ypget_req_ordernum = 0;			oldreq.ypget_req_owner = my_name;					s = (enum clnt_stat) clnt_call(			    ps->domb.dom_client, YPOLDPROC_GET,			    _xdr_yprequest, &oldreq, xdr_void, 0, udp_timeout);			clnt_geterr(ps->domb.dom_client, &rpcerr);			clnt_destroy(ps->domb.dom_client);			close(ps->domb.dom_socket);		}		if (s == RPC_SUCCESS) {			return (SSTAT_RESPONDED);		} else {			*err = (long) rpcerr.re_status;			return (SSTAT_RPC);		}	}}

⌨️ 快捷键说明

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