Home | History | Annotate | Line # | Download | only in yppush
yppush.c revision 1.11.6.1
      1  1.11.6.1  minoura /*	$NetBSD: yppush.c,v 1.11.6.1 2000/06/22 18:01:16 minoura Exp $	*/
      2       1.1  thorpej 
      3       1.1  thorpej /*
      4       1.8    lukem  *
      5       1.8    lukem  * Copyright (c) 1997 Charles D. Cranor
      6       1.1  thorpej  * All rights reserved.
      7       1.1  thorpej  *
      8       1.1  thorpej  * Redistribution and use in source and binary forms, with or without
      9       1.1  thorpej  * modification, are permitted provided that the following conditions
     10       1.1  thorpej  * are met:
     11       1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     12       1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     13       1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     14       1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     15       1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     16       1.8    lukem  * 3. The name of the author may not be used to endorse or promote products
     17       1.1  thorpej  *    derived from this software without specific prior written permission.
     18       1.1  thorpej  *
     19       1.8    lukem  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20       1.8    lukem  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21       1.8    lukem  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22       1.8    lukem  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23       1.8    lukem  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24       1.8    lukem  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25       1.8    lukem  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26       1.8    lukem  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27       1.8    lukem  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28       1.8    lukem  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29       1.8    lukem  */
     30       1.1  thorpej 
     31       1.8    lukem /*
     32       1.8    lukem  * yppush
     33       1.8    lukem  * author: Chuck Cranor <chuck (at) ccrc.wustl.edu>
     34       1.8    lukem  * date: 05-Nov-97
     35       1.8    lukem  *
     36       1.8    lukem  * notes: this is a full rewrite of Mats O Jansson <moj (at) stacken.kth.se>'s
     37       1.8    lukem  * yppush.c.   i have restructured and cleaned up the entire file.
     38       1.8    lukem  */
     39       1.1  thorpej #include <sys/types.h>
     40       1.8    lukem #include <sys/param.h>
     41       1.1  thorpej #include <sys/stat.h>
     42       1.8    lukem #include <sys/time.h>
     43       1.4  thorpej #include <sys/wait.h>
     44       1.1  thorpej 
     45       1.4  thorpej #include <ctype.h>
     46       1.1  thorpej #include <err.h>
     47      1.10   kleink #include <errno.h>
     48       1.1  thorpej #include <fcntl.h>
     49       1.8    lukem #include <signal.h>
     50       1.1  thorpej #include <stdio.h>
     51       1.9  thorpej #include <string.h>
     52       1.1  thorpej #include <unistd.h>
     53       1.1  thorpej 
     54       1.1  thorpej #include <rpc/rpc.h>
     55       1.1  thorpej #include <rpcsvc/yp_prot.h>
     56       1.1  thorpej #include <rpcsvc/ypclnt.h>
     57       1.1  thorpej 
     58       1.8    lukem #include "ypdb.h"
     59       1.8    lukem #include "ypdef.h"
     60       1.1  thorpej #include "yplib_host.h"
     61       1.1  thorpej #include "yppush.h"
     62       1.1  thorpej 
     63       1.8    lukem /*
     64       1.8    lukem  * yppush: push a new YP map out YP servers
     65       1.8    lukem  *
     66       1.8    lukem  * usage:
     67       1.8    lukem  *   yppush [-d domain] [-h host] [-v] mapname
     68       1.8    lukem  *
     69       1.8    lukem  *   -d: the domainname the map lives in [if different from default]
     70       1.8    lukem  *   -h: push only to this host [otherwise, push to all hosts]
     71       1.8    lukem  *   -v: verbose
     72       1.8    lukem  */
     73       1.8    lukem 
     74       1.8    lukem /*
     75       1.8    lukem  * structures
     76       1.8    lukem  */
     77       1.8    lukem 
     78       1.8    lukem struct yppush_info {
     79       1.8    lukem 	char   *ourdomain;	/* domain of interest */
     80       1.8    lukem 	char   *map;		/* map we are pushing */
     81       1.8    lukem 	char   *owner;		/* owner of map */
     82       1.8    lukem 	int     order;		/* order number of map (version) */
     83       1.8    lukem };
     84       1.8    lukem /*
     85       1.8    lukem  * global vars
     86       1.8    lukem  */
     87       1.8    lukem 
     88       1.8    lukem extern char *__progname;	/* from crt0.o */
     89       1.8    lukem int     verbo = 0;		/* verbose */
     90       1.8    lukem 
     91       1.8    lukem /*
     92       1.8    lukem  * prototypes
     93       1.8    lukem  */
     94       1.1  thorpej 
     95       1.4  thorpej int	main __P((int, char *[]));
     96       1.1  thorpej int	pushit __P((int, char *, int, char *, int, char *));
     97       1.8    lukem void	push __P((char *, int, struct yppush_info *));
     98       1.1  thorpej void	_svc_run __P((void));
     99       1.1  thorpej void	usage __P((void));
    100       1.1  thorpej 
    101       1.1  thorpej 
    102       1.8    lukem /*
    103       1.8    lukem  * main
    104       1.8    lukem  */
    105       1.1  thorpej 
    106       1.1  thorpej int
    107       1.1  thorpej main(argc, argv)
    108       1.8    lukem 	int     argc;
    109       1.8    lukem 	char   *argv[];
    110       1.8    lukem 
    111       1.1  thorpej {
    112       1.8    lukem 	char   *targhost = NULL;
    113       1.8    lukem 	struct yppush_info ypi = {NULL, NULL, NULL, 0};
    114       1.8    lukem 	int     c, rv;
    115       1.8    lukem 	const char *cp;
    116       1.8    lukem 	char   *master;
    117       1.8    lukem 	DBM    *ypdb;
    118       1.8    lukem 	datum   datum;
    119       1.8    lukem 	CLIENT *ypserv;
    120       1.8    lukem 	struct timeval tv;
    121       1.8    lukem 	enum clnt_stat retval;
    122       1.8    lukem 	struct ypall_callback ypallcb;
    123       1.1  thorpej 
    124       1.8    lukem 	/*
    125       1.8    lukem          * parse command line
    126       1.8    lukem          */
    127       1.1  thorpej 	while ((c = getopt(argc, argv, "d:h:v")) != -1) {
    128       1.8    lukem 		switch (c) {
    129       1.1  thorpej 		case 'd':
    130       1.8    lukem 			ypi.ourdomain = optarg;
    131       1.1  thorpej 			break;
    132       1.1  thorpej 		case 'h':
    133       1.8    lukem 			targhost = optarg;
    134       1.1  thorpej 			break;
    135       1.8    lukem 		case 'v':
    136       1.8    lukem 			verbo = 1;
    137       1.1  thorpej 			break;
    138       1.1  thorpej 		default:
    139       1.8    lukem 			usage();
    140       1.8    lukem 			/* NOTREACHED */
    141       1.1  thorpej 		}
    142       1.1  thorpej 	}
    143       1.8    lukem 	argc -= optind;
    144       1.8    lukem 	argv += optind;
    145       1.1  thorpej 	if (argc != 1)
    146       1.1  thorpej 		usage();
    147       1.8    lukem 	ypi.map = argv[0];
    148       1.8    lukem 	if (strlen(ypi.map) > YPMAXMAP)
    149       1.8    lukem 		errx(1, "%s: map name too long (limit %d)", ypi.map, YPMAXMAP);
    150       1.8    lukem 
    151       1.8    lukem 	/*
    152       1.8    lukem          * ensure we have a domain
    153       1.8    lukem          */
    154       1.8    lukem 	if (ypi.ourdomain == NULL) {
    155       1.8    lukem 		c = yp_get_default_domain(&ypi.ourdomain);
    156       1.8    lukem 		if (ypi.ourdomain == NULL)
    157       1.8    lukem 			errx(1, "unable to get default domain: %s",
    158       1.3  thorpej 			    yperr_string(c));
    159       1.8    lukem 	}
    160       1.8    lukem 	/*
    161       1.8    lukem          * verify that the domain and specified database exsists
    162       1.8    lukem          *
    163       1.8    lukem          * XXXCDC: this effectively prevents us from pushing from any
    164       1.8    lukem          * host but the master.   an alternate plan is to find the master
    165       1.8    lukem          * host for a map, clear it, ask for the order number, and then
    166       1.8    lukem          * send xfr requests.   if that was used we would not need local
    167       1.8    lukem          * file access.
    168       1.8    lukem          */
    169       1.8    lukem 	if (chdir(YP_DB_PATH) < 0)
    170       1.8    lukem 		err(1, "%s", YP_DB_PATH);
    171       1.8    lukem 	if (chdir(ypi.ourdomain) < 0)
    172       1.8    lukem 		err(1, "%s/%s", YP_DB_PATH, ypi.ourdomain);
    173       1.8    lukem 
    174       1.8    lukem 	/*
    175       1.8    lukem          * now open the database so we can extract "order number"
    176       1.8    lukem          * (i.e. timestamp) of the map.
    177       1.8    lukem          */
    178       1.8    lukem 	ypdb = ypdb_open(ypi.map, 0, O_RDONLY);
    179       1.8    lukem 	if (ypdb == NULL)
    180       1.8    lukem 		err(1, "ypdb_open %s/%s/%s", YP_DB_PATH, ypi.ourdomain,
    181       1.8    lukem 		    ypi.map);
    182       1.8    lukem 	datum.dptr = YP_LAST_KEY;
    183       1.8    lukem 	datum.dsize = YP_LAST_LEN;
    184       1.8    lukem 	datum = ypdb_fetch(ypdb, datum);
    185       1.8    lukem 	if (datum.dptr == NULL)
    186       1.8    lukem 		errx(1,
    187       1.8    lukem 		    "unable to fetch %s key: check database with 'makedbm -u'",
    188       1.8    lukem 		    YP_LAST_KEY);
    189       1.8    lukem 	ypi.order = 0;
    190       1.8    lukem 	cp = datum.dptr;
    191       1.8    lukem 	while (cp < datum.dptr + datum.dsize) {
    192       1.8    lukem 		if (!isdigit(*cp))
    193       1.8    lukem 			errx(1,
    194       1.8    lukem 		    "invalid order number: check database with 'makedbm -u'");
    195       1.8    lukem 		ypi.order = (ypi.order * 10) + *cp - '0';
    196       1.8    lukem 		cp++;
    197       1.8    lukem 	}
    198      1.11    lukem 	ypdb_close(ypdb);
    199       1.1  thorpej 
    200       1.8    lukem 	if (verbo)
    201       1.8    lukem 		printf("pushing %s [order=%d] in domain %s\n", ypi.map,
    202       1.8    lukem 		    ypi.order, ypi.ourdomain);
    203       1.8    lukem 
    204       1.8    lukem 	/*
    205       1.8    lukem          * ok, we are ready to do it.   first we send a clear_2 request
    206       1.8    lukem          * to the local server [should be the master] to make sure it has
    207       1.8    lukem          * the correct database open.
    208       1.8    lukem          *
    209       1.8    lukem          * XXXCDC: note that yp_bind_local exits on failure so ypserv can't
    210       1.8    lukem          * be null.   this makes it difficult to print a useful error message.
    211       1.8    lukem          * [it will print "clntudp_create: no contact with localhost"]
    212       1.8    lukem          */
    213       1.8    lukem 	tv.tv_sec = 10;
    214       1.8    lukem 	tv.tv_usec = 0;
    215       1.8    lukem 	ypserv = yp_bind_local(YPPROG, YPVERS);
    216       1.8    lukem 	retval = clnt_call(ypserv, YPPROC_CLEAR, xdr_void, 0, xdr_void, 0, tv);
    217       1.8    lukem 	if (retval != RPC_SUCCESS)
    218       1.8    lukem 		errx(1, "clnt_call CLEAR to local ypserv: %s",
    219       1.8    lukem 		    clnt_sperrno(retval));
    220       1.8    lukem 	clnt_destroy(ypserv);
    221       1.8    lukem 
    222       1.8    lukem 	/*
    223       1.8    lukem          * now use normal yplib functions to bind to the domain.
    224       1.8    lukem          */
    225       1.8    lukem 	rv = yp_bind(ypi.ourdomain);
    226       1.8    lukem 	if (rv)
    227       1.8    lukem 		errx(1, "error binding to %s: %s", ypi.ourdomain,
    228       1.8    lukem 		    yperr_string(rv));
    229       1.8    lukem 
    230       1.8    lukem 	/*
    231       1.8    lukem          * find 'owner' of the map (see pushit for usage)
    232       1.8    lukem          */
    233       1.8    lukem 	rv = yp_master(ypi.ourdomain, ypi.map, &ypi.owner);
    234       1.8    lukem 	if (rv)
    235       1.8    lukem 		errx(1, "error finding master for %s in %s: %s", ypi.map,
    236       1.8    lukem 		    ypi.ourdomain, yperr_string(rv));
    237       1.8    lukem 
    238       1.8    lukem 	/*
    239       1.8    lukem          * inform user of our progress
    240       1.8    lukem          */
    241       1.8    lukem 	if (verbo) {
    242       1.8    lukem 		printf("pushing map %s in %s: order=%d, owner=%s\n", ypi.map,
    243       1.8    lukem 		    ypi.ourdomain, ypi.order, ypi.owner);
    244       1.8    lukem 		printf("pushing to %s\n",
    245       1.8    lukem 		    (targhost) ? targhost : "<all ypservs>");
    246       1.8    lukem 	}
    247       1.1  thorpej 
    248       1.8    lukem 	/*
    249       1.8    lukem          * finally, do it.
    250       1.8    lukem          */
    251       1.8    lukem 	if (targhost) {
    252       1.8    lukem 		push(targhost, strlen(targhost), &ypi);
    253       1.8    lukem 	} else {
    254       1.8    lukem 
    255       1.8    lukem 		/*
    256       1.8    lukem 	         * no host specified, do all hosts the master knows about via
    257       1.8    lukem 	         * the ypservers map.
    258       1.8    lukem 	         */
    259       1.8    lukem 		rv = yp_master(ypi.ourdomain, "ypservers", &master);
    260       1.8    lukem 		if (rv)
    261       1.8    lukem 			errx(1, "error finding master for ypservers in %s: %s",
    262       1.8    lukem 			    ypi.ourdomain, yperr_string(rv));
    263       1.8    lukem 
    264       1.8    lukem 		if (verbo)
    265       1.8    lukem 			printf(
    266       1.8    lukem 		"contacting ypservers %s master on %s for list of ypservs...\n",
    267       1.8    lukem 			    ypi.ourdomain, master);
    268       1.8    lukem 
    269       1.8    lukem 		ypserv = yp_bind_host(master, YPPROG, YPVERS, 0, 1);
    270       1.8    lukem 
    271       1.8    lukem 		ypallcb.foreach = pushit;	/* callback function */
    272       1.8    lukem 		ypallcb.data = (char *) &ypi;	/* data to pass into callback */
    273       1.8    lukem 
    274       1.8    lukem 		rv = yp_all_host(ypserv, ypi.ourdomain, "ypservers", &ypallcb);
    275       1.8    lukem 		if (rv)
    276       1.8    lukem 			errx(1, "pushing %s in %s failed: %s", ypi.map,
    277       1.8    lukem 			    ypi.ourdomain, yperr_string(rv));
    278       1.1  thorpej 	}
    279       1.8    lukem 	exit(0);
    280       1.1  thorpej }
    281       1.1  thorpej 
    282       1.8    lukem /*
    283       1.8    lukem  * usage: print usage and exit
    284       1.8    lukem  */
    285       1.1  thorpej void
    286       1.1  thorpej usage()
    287       1.1  thorpej {
    288       1.8    lukem 	fprintf(stderr, "usage: %s [-d domain] [-h host] [-v] map\n",
    289       1.1  thorpej 	    __progname);
    290       1.1  thorpej 	exit(1);
    291       1.1  thorpej }
    292       1.1  thorpej 
    293       1.8    lukem /*
    294       1.8    lukem  * pushit: called from yp_all_host to push a specific host.
    295       1.8    lukem  * the key/value pairs are from the ypservers map.
    296       1.8    lukem  */
    297       1.8    lukem int
    298       1.8    lukem pushit(instatus, inkey, inkeylen, inval, invallen, indata)
    299       1.8    lukem 	int     instatus, inkeylen, invallen;
    300       1.8    lukem 	char   *inkey, *inval, *indata;
    301       1.1  thorpej {
    302       1.8    lukem 	struct yppush_info *ypi = (struct yppush_info *) indata;
    303       1.1  thorpej 
    304       1.8    lukem 	if (instatus != YP_TRUE)		/* failure? */
    305       1.8    lukem 		return (instatus);
    306       1.1  thorpej 
    307       1.8    lukem 	push(inkey, inkeylen, ypi);		/* do it! */
    308       1.8    lukem 	return (0);
    309       1.1  thorpej }
    310       1.1  thorpej 
    311       1.8    lukem /*
    312       1.8    lukem  * push: push a specific map on a specific host
    313       1.8    lukem  */
    314       1.1  thorpej void
    315       1.8    lukem push(host, hostlen, ypi)
    316       1.8    lukem 	char   *host;
    317       1.8    lukem 	int     hostlen;
    318       1.8    lukem 	struct yppush_info *ypi;
    319       1.8    lukem {
    320       1.8    lukem 	char    target[YPMAXPEER];
    321       1.8    lukem 	CLIENT *ypserv;
    322       1.1  thorpej 	SVCXPRT *transp;
    323       1.8    lukem 	int     prog, pid, rv;
    324       1.1  thorpej 	struct timeval tv;
    325       1.8    lukem 	struct ypreq_xfr req;
    326       1.1  thorpej 
    327       1.8    lukem 	/*
    328       1.8    lukem          * get our target host in a null terminated string
    329       1.8    lukem          */
    330       1.8    lukem 	snprintf(target, sizeof(target), "%*.*s", hostlen, hostlen, host);
    331       1.8    lukem 
    332       1.8    lukem 	/*
    333       1.8    lukem          * XXXCDC: arg!  we would like to use yp_bind_host here, except that
    334       1.8    lukem          * it exits on failure and we don't want to give up just because
    335       1.8    lukem          * one host fails.  thus, we have to do it the hard way.
    336       1.8    lukem          */
    337       1.8    lukem 	ypserv = clnt_create(target, YPPROG, YPVERS, "tcp");
    338       1.8    lukem 	if (ypserv == NULL) {
    339       1.8    lukem 		clnt_pcreateerror(target);
    340       1.1  thorpej 		return;
    341       1.1  thorpej 	}
    342       1.1  thorpej 
    343       1.8    lukem 	/*
    344       1.8    lukem          * our XFR rpc request to the client just starts the transfer.
    345       1.8    lukem          * when the client is done, it wants to call a procedure that
    346       1.8    lukem          * we are serving to tell us that it is done.   so we must create
    347       1.8    lukem          * and register a procedure for us for it to call.
    348       1.8    lukem          */
    349       1.8    lukem 	transp = svcudp_create(RPC_ANYSOCK);
    350       1.1  thorpej 	if (transp == NULL) {
    351       1.8    lukem 		warnx("callback svcudp_create failed");
    352       1.8    lukem 		goto error;
    353       1.1  thorpej 	}
    354       1.1  thorpej 
    355       1.8    lukem 	/* register it with portmap */
    356       1.1  thorpej 	for (prog = 0x40000000; prog < 0x5fffffff; prog++) {
    357       1.8    lukem 		if (svc_register(transp, prog, 1, yppush_xfrrespprog_1,
    358       1.8    lukem 		    IPPROTO_UDP))
    359       1.1  thorpej 			break;
    360       1.1  thorpej 	}
    361       1.8    lukem 	if (prog >= 0x5fffffff) {
    362       1.8    lukem 		warnx("unable to register callback");
    363       1.8    lukem 		goto error;
    364       1.8    lukem 	}
    365       1.1  thorpej 
    366       1.8    lukem 	/*
    367       1.8    lukem          * now fork off a server to catch our reply
    368       1.8    lukem          */
    369       1.8    lukem 	pid = fork();
    370       1.8    lukem 	if (pid == -1) {
    371       1.8    lukem 		svc_unregister(prog, 1);	/* drop our mapping with
    372       1.8    lukem 						 * portmap */
    373       1.8    lukem 		warn("fork failed");
    374       1.8    lukem 		goto error;
    375       1.1  thorpej 	}
    376       1.1  thorpej 
    377       1.8    lukem 	/*
    378       1.8    lukem          * child process becomes the server
    379       1.8    lukem          */
    380       1.8    lukem 	if (pid == 0) {
    381       1.1  thorpej 		_svc_run();
    382       1.1  thorpej 		exit(0);
    383       1.8    lukem 	}
    384       1.8    lukem 
    385       1.8    lukem 	/*
    386       1.8    lukem          * we are the parent process: send XFR request to server.
    387       1.8    lukem          * the "owner" field isn't used by ypserv (and shouldn't be, since
    388       1.8    lukem          * the ypserv has no idea if we are a legitimate yppush or not).
    389       1.8    lukem          * instead, the owner of the map is determined by the master value
    390       1.8    lukem          * currently cached on the slave server.
    391       1.8    lukem          */
    392  1.11.6.1  minoura 	close(transp->xp_fd);	/* close child's socket, we don't need it */
    393       1.8    lukem 	/* don't wait for anything here, we will wait for child's exit */
    394       1.8    lukem 	tv.tv_sec = 0;
    395       1.8    lukem 	tv.tv_usec = 0;
    396       1.8    lukem 	req.map_parms.domain = ypi->ourdomain;
    397       1.8    lukem 	req.map_parms.map = ypi->map;
    398       1.8    lukem 	req.map_parms.owner = ypi->owner;	/* NOT USED */
    399       1.8    lukem 	req.map_parms.ordernum = ypi->order;
    400       1.8    lukem 	req.transid = (u_int) pid;
    401       1.8    lukem 	req.proto = prog;
    402       1.8    lukem 	req.port = transp->xp_port;
    403       1.8    lukem 
    404       1.8    lukem 	if (verbo)
    405       1.8    lukem 		printf("asking host %s to transfer map (xid=%d)\n", target,
    406       1.8    lukem 		    req.transid);
    407       1.8    lukem 
    408       1.8    lukem 	rv = clnt_call(ypserv, YPPROC_XFR, xdr_ypreq_xfr, &req,
    409       1.8    lukem 	    		xdr_void, NULL, tv);			/* do it! */
    410       1.1  thorpej 
    411       1.8    lukem 	if (rv != RPC_SUCCESS && rv != RPC_TIMEDOUT) {
    412       1.8    lukem 		warnx("unable to xfr to host %s: %s", target, clnt_sperrno(rv));
    413       1.8    lukem 		kill(pid, SIGTERM);
    414       1.1  thorpej 	}
    415       1.8    lukem 
    416       1.8    lukem 	/*
    417       1.8    lukem          * now wait for child to get the reply and exit
    418       1.8    lukem          */
    419       1.8    lukem 	wait4(pid, NULL, 0, NULL);
    420       1.8    lukem 	svc_unregister(prog, 1);
    421       1.8    lukem 
    422       1.8    lukem 	/*
    423       1.8    lukem          * ... and we are done.   fall through
    424       1.8    lukem          */
    425       1.8    lukem 
    426       1.8    lukem error:
    427       1.8    lukem 	if (transp)
    428       1.8    lukem 		svc_destroy(transp);
    429       1.8    lukem 	clnt_destroy(ypserv);
    430       1.8    lukem 	return;
    431       1.1  thorpej }
    432       1.1  thorpej 
    433       1.8    lukem /*
    434       1.8    lukem  * _svc_run: this is the main loop for the RPC server that we fork off
    435       1.8    lukem  * to await the reply from ypxfr.
    436       1.8    lukem  */
    437       1.8    lukem void
    438       1.8    lukem _svc_run()
    439       1.1  thorpej {
    440       1.8    lukem 	fd_set  readfds;
    441       1.8    lukem 	struct timeval tv;
    442       1.8    lukem 	int     rv, nfds;
    443       1.1  thorpej 
    444       1.8    lukem 	nfds = sysconf(_SC_OPEN_MAX);
    445       1.8    lukem 	while (1) {
    446       1.1  thorpej 
    447       1.8    lukem 		readfds = svc_fdset;	/* structure copy from global var */
    448       1.8    lukem 		tv.tv_sec = 60;
    449       1.8    lukem 		tv.tv_usec = 0;
    450       1.8    lukem 
    451       1.8    lukem 		rv = select(nfds, &readfds, NULL, NULL, &tv);
    452       1.8    lukem 
    453       1.8    lukem 		if (rv < 0) {
    454       1.8    lukem 			if (errno == EINTR)
    455       1.8    lukem 				continue;
    456       1.8    lukem 			warn("_svc_run: select failed");
    457       1.8    lukem 			return;
    458       1.8    lukem 		}
    459       1.8    lukem 		if (rv == 0)
    460       1.8    lukem 			errx(0, "_svc_run: callback timed out");
    461       1.1  thorpej 
    462       1.8    lukem 		/*
    463       1.8    lukem 	         * got something
    464       1.8    lukem 	         */
    465       1.8    lukem 		svc_getreqset(&readfds);
    466       1.1  thorpej 
    467       1.8    lukem 	}
    468       1.1  thorpej }
    469