113394Swpaul/* 213394Swpaul * Copyright (c) 1995 313394Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 413394Swpaul * 513394Swpaul * Redistribution and use in source and binary forms, with or without 613394Swpaul * modification, are permitted provided that the following conditions 713394Swpaul * are met: 813394Swpaul * 1. Redistributions of source code must retain the above copyright 913394Swpaul * notice, this list of conditions and the following disclaimer. 1013394Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1113394Swpaul * notice, this list of conditions and the following disclaimer in the 1213394Swpaul * documentation and/or other materials provided with the distribution. 1313394Swpaul * 3. All advertising materials mentioning features or use of this software 1413394Swpaul * must display the following acknowledgement: 1513394Swpaul * This product includes software developed by Bill Paul. 1613394Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1713394Swpaul * may be used to endorse or promote products derived from this software 1813394Swpaul * without specific prior written permission. 1913394Swpaul * 2013394Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2113394Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2213394Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2313394Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2413394Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2513394Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2613394Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2713394Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2813394Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2913394Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3013394Swpaul * SUCH DAMAGE. 3113394Swpaul */ 3213394Swpaul 33114601Sobrien#include <sys/cdefs.h> 34114601Sobrien__FBSDID("$FreeBSD: releng/10.3/usr.sbin/yppush/yppush_main.c 201389 2010-01-02 11:06:39Z ed $"); 3530911Scharnier 3630911Scharnier#include <errno.h> 3730911Scharnier#include <signal.h> 3813394Swpaul#include <stdio.h> 3913394Swpaul#include <stdlib.h> 4013394Swpaul#include <string.h> 41161262Sru#include <strings.h> 4213394Swpaul#include <time.h> 4330911Scharnier#include <unistd.h> 4413394Swpaul#include <sys/socket.h> 4513394Swpaul#include <sys/fcntl.h> 4613394Swpaul#include <sys/wait.h> 4713394Swpaul#include <sys/param.h> 4813394Swpaul#include <rpc/rpc.h> 4913394Swpaul#include <rpc/clnt.h> 5013394Swpaul#include <rpc/pmap_clnt.h> 5113394Swpaul#include <rpcsvc/yp.h> 5213394Swpaul#include <rpcsvc/ypclnt.h> 5313394Swpaul#include "ypxfr_extern.h" 5413394Swpaul#include "yppush_extern.h" 5513394Swpaul 5613394Swpaulchar *progname = "yppush"; 5713394Swpaulint debug = 1; 5813394Swpaulint _rpcpmstart = 0; 5913394Swpaulchar *yp_dir = _PATH_YP; 6013394Swpaul 6113394Swpaulchar *yppush_mapname = NULL; /* Map to transfer. */ 6213394Swpaulchar *yppush_domain = NULL; /* Domain in which map resides. */ 6313394Swpaulchar *yppush_master = NULL; /* Master NIS server for said domain. */ 64161262Sruint skip_master = 0; /* Do not attempt to push map to master. */ 6513394Swpaulint verbose = 0; /* Toggle verbose mode. */ 6613394Swpaulunsigned long yppush_transid = 0; 6713394Swpaulint yppush_timeout = 80; /* Default timeout. */ 68161359Sthomasint yppush_jobs = 1; /* Number of allowed concurrent jobs. */ 6913394Swpaulint yppush_running_jobs = 0; /* Number of currently running jobs. */ 7013394Swpaul 7113394Swpaul/* Structure for holding information about a running job. */ 7213394Swpaulstruct jobs { 7313394Swpaul unsigned long tid; 7413394Swpaul int port; 7513394Swpaul ypxfrstat stat; 7613394Swpaul unsigned long prognum; 7713394Swpaul char *server; 7813394Swpaul char *map; 7913394Swpaul int polled; 8013394Swpaul struct jobs *next; 8113394Swpaul}; 8213394Swpaul 8313394Swpaulstruct jobs *yppush_joblist; /* Linked list of running jobs. */ 8413394Swpaul 85161359Sthomasstatic int yppush_svc_run(int); 86161359Sthomas 8713394Swpaul/* 8813394Swpaul * Local error messages. 8913394Swpaul */ 9094887Sdesstatic const char * 9190298Sdesyppusherr_string(int err) 9213394Swpaul{ 9390297Sdes switch (err) { 9494887Sdes case YPPUSH_TIMEDOUT: 9594887Sdes return("transfer or callback timed out"); 9694887Sdes case YPPUSH_YPSERV: 9794887Sdes return("failed to contact ypserv"); 9894887Sdes case YPPUSH_NOHOST: 9994887Sdes return("no such host"); 10094887Sdes case YPPUSH_PMAP: 10194887Sdes return("portmapper failure"); 10294887Sdes default: 10394887Sdes return("unknown error code"); 10413394Swpaul } 10513394Swpaul} 10613394Swpaul 10713394Swpaul/* 10813394Swpaul * Report state of a job. 10913394Swpaul */ 11090298Sdesstatic int 11190298Sdesyppush_show_status(ypxfrstat status, unsigned long tid) 11213394Swpaul{ 11313394Swpaul struct jobs *job; 11413394Swpaul 11513394Swpaul job = yppush_joblist; 11613394Swpaul 117161359Sthomas while (job != NULL) { 11813394Swpaul if (job->tid == tid) 11913394Swpaul break; 12013394Swpaul job = job->next; 12113394Swpaul } 12213394Swpaul 123161359Sthomas if (job == NULL) { 124161359Sthomas yp_error("warning: received callback with invalid transaction ID: %lu", 125161359Sthomas tid); 126161359Sthomas return (0); 127161359Sthomas } 128161359Sthomas 12913394Swpaul if (job->polled) { 130161359Sthomas yp_error("warning: received callback with duplicate transaction ID: %lu", 131161359Sthomas tid); 132161359Sthomas return (0); 13313394Swpaul } 13413394Swpaul 135161359Sthomas if (verbose > 1) { 13630911Scharnier yp_error("checking return status: transaction ID: %lu", 13713394Swpaul job->tid); 138161359Sthomas } 139161359Sthomas 14013394Swpaul if (status != YPPUSH_SUCC || verbose) { 14130911Scharnier yp_error("transfer of map %s to server %s %s", 14213394Swpaul job->map, job->server, status == YPPUSH_SUCC ? 14313394Swpaul "succeeded" : "failed"); 14413394Swpaul yp_error("status returned by ypxfr: %s", status > YPPUSH_AGE ? 14590297Sdes yppusherr_string(status) : 14613394Swpaul ypxfrerr_string(status)); 14713394Swpaul } 14813394Swpaul 14913394Swpaul job->polled = 1; 15013394Swpaul 15113394Swpaul svc_unregister(job->prognum, 1); 15290297Sdes 15313394Swpaul yppush_running_jobs--; 15413394Swpaul return(0); 15513394Swpaul} 15613394Swpaul 15713394Swpaul/* Exit routine. */ 15890298Sdesstatic void 15990298Sdesyppush_exit(int now) 16013394Swpaul{ 16113394Swpaul struct jobs *jptr; 16213799Swpaul int still_pending = 1; 16313394Swpaul 16413394Swpaul /* Let all the information trickle in. */ 16590297Sdes while (!now && still_pending) { 16613394Swpaul jptr = yppush_joblist; 16713394Swpaul still_pending = 0; 16813394Swpaul while (jptr) { 16913394Swpaul if (jptr->polled == 0) { 17013394Swpaul still_pending++; 17113394Swpaul if (verbose > 1) 17213394Swpaul yp_error("%s has not responded", 17313394Swpaul jptr->server); 17413394Swpaul } else { 17513394Swpaul if (verbose > 1) 17613394Swpaul yp_error("%s has responded", 17713394Swpaul jptr->server); 17813394Swpaul } 17913394Swpaul jptr = jptr->next; 18013394Swpaul } 18113394Swpaul if (still_pending) { 18213394Swpaul if (verbose > 1) 18313394Swpaul yp_error("%d transfer%sstill pending", 18413394Swpaul still_pending, 18513394Swpaul still_pending > 1 ? "s " : " "); 186161359Sthomas if (yppush_svc_run (YPPUSH_RESPONSE_TIMEOUT) == 0) { 18713799Swpaul yp_error("timed out"); 18813799Swpaul now = 1; 18913799Swpaul } 19013394Swpaul } else { 19113394Swpaul if (verbose) 19213394Swpaul yp_error("all transfers complete"); 19313394Swpaul break; 19413394Swpaul } 19513394Swpaul } 19613394Swpaul 19713394Swpaul 19813394Swpaul /* All stats collected and reported -- kill all the stragglers. */ 19913394Swpaul jptr = yppush_joblist; 20090297Sdes while (jptr) { 20113394Swpaul if (!jptr->polled) 20213394Swpaul yp_error("warning: exiting with transfer \ 20330911Scharnierto %s (transid = %lu) still pending", jptr->server, jptr->tid); 20413394Swpaul svc_unregister(jptr->prognum, 1); 20513394Swpaul jptr = jptr->next; 20613394Swpaul } 20713394Swpaul 20813394Swpaul exit(0); 20913394Swpaul} 21013394Swpaul 21113394Swpaul/* 21213394Swpaul * Handler for 'normal' signals. 21313394Swpaul */ 21413394Swpaul 21590298Sdesstatic void 21690298Sdeshandler(int sig) 21713394Swpaul{ 218161359Sthomas yppush_exit (1); 21913394Swpaul return; 22013394Swpaul} 22113394Swpaul 22213394Swpaul/* 22313394Swpaul * Dispatch loop for callback RPC services. 224161359Sthomas * Return value: 225161359Sthomas * -1 error 226161359Sthomas * 0 timeout 227161359Sthomas * >0 request serviced 22813394Swpaul */ 229161359Sthomasstatic int 230161359Sthomasyppush_svc_run(int timeout_secs) 23113394Swpaul{ 232161359Sthomas int rc; 23313394Swpaul fd_set readfds; 23413394Swpaul struct timeval timeout; 23513394Swpaul 23613394Swpaul timeout.tv_usec = 0; 237161359Sthomas timeout.tv_sec = timeout_secs; 23813394Swpaul 23913394Swpaulretry: 24013394Swpaul readfds = svc_fdset; 241161359Sthomas rc = select(svc_maxfd + 1, &readfds, NULL, NULL, &timeout); 242161359Sthomas switch (rc) { 24313394Swpaul case -1: 24413394Swpaul if (errno == EINTR) 24513394Swpaul goto retry; 24613394Swpaul yp_error("select failed: %s", strerror(errno)); 24713394Swpaul break; 24813394Swpaul case 0: 24913394Swpaul yp_error("select() timed out"); 25013394Swpaul break; 25113394Swpaul default: 25213394Swpaul svc_getreqset(&readfds); 25313394Swpaul break; 25413394Swpaul } 255161359Sthomas return rc; 25613394Swpaul} 25713394Swpaul 25813394Swpaul/* 25913799Swpaul * RPC service routines for callbacks. 26013394Swpaul */ 26113394Swpaulvoid * 26213394Swpaulyppushproc_null_1_svc(void *argp, struct svc_req *rqstp) 26313394Swpaul{ 26413394Swpaul static char * result; 26513394Swpaul /* Do nothing -- RPC conventions call for all a null proc. */ 26613394Swpaul return((void *) &result); 26713394Swpaul} 26813394Swpaul 26913394Swpaulvoid * 27013394Swpaulyppushproc_xfrresp_1_svc(yppushresp_xfr *argp, struct svc_req *rqstp) 27113394Swpaul{ 27213394Swpaul static char * result; 27313394Swpaul yppush_show_status(argp->status, argp->transid); 27413394Swpaul return((void *) &result); 27513394Swpaul} 27613394Swpaul 27713394Swpaul/* 27813394Swpaul * Transmit a YPPROC_XFR request to ypserv. 27990297Sdes */ 28090298Sdesstatic int 28190298Sdesyppush_send_xfr(struct jobs *job) 28213394Swpaul{ 28313394Swpaul ypreq_xfr req; 28413394Swpaul/* ypresp_xfr *resp; */ 28513394Swpaul DBT key, data; 28613394Swpaul CLIENT *clnt; 28713394Swpaul struct rpc_err err; 28813394Swpaul struct timeval timeout; 28913394Swpaul 29013394Swpaul timeout.tv_usec = 0; 29113394Swpaul timeout.tv_sec = 0; 29213394Swpaul 29313394Swpaul /* 29413394Swpaul * The ypreq_xfr structure has a member of type map_parms, 29513394Swpaul * which seems to require the order number of the map. 29613394Swpaul * It isn't actually used at the other end (at least the 29713394Swpaul * FreeBSD ypserv doesn't use it) but we fill it in here 29813394Swpaul * for the sake of completeness. 29913394Swpaul */ 30013394Swpaul key.data = "YP_LAST_MODIFIED"; 30113394Swpaul key.size = sizeof ("YP_LAST_MODIFIED") - 1; 30213394Swpaul 30313394Swpaul if (yp_get_record(yppush_domain, yppush_mapname, &key, &data, 30413394Swpaul 1) != YP_TRUE) { 30513394Swpaul yp_error("failed to read order number from %s: %s: %s", 30613394Swpaul yppush_mapname, yperr_string(yp_errno), 30713394Swpaul strerror(errno)); 30813394Swpaul return(1); 30913394Swpaul } 31013394Swpaul 31113394Swpaul /* Fill in the request arguments */ 31213394Swpaul req.map_parms.ordernum = atoi(data.data); 31313394Swpaul req.map_parms.domain = yppush_domain; 31413394Swpaul req.map_parms.peer = yppush_master; 31513394Swpaul req.map_parms.map = job->map; 31613394Swpaul req.transid = job->tid; 31713394Swpaul req.prog = job->prognum; 31813394Swpaul req.port = job->port; 31913394Swpaul 32013394Swpaul /* Get a handle to the remote ypserv. */ 32113394Swpaul if ((clnt = clnt_create(job->server, YPPROG, YPVERS, "udp")) == NULL) { 32213394Swpaul yp_error("%s: %s",job->server,clnt_spcreateerror("couldn't \ 32313394Swpaulcreate udp handle to NIS server")); 32490297Sdes switch (rpc_createerr.cf_stat) { 32513394Swpaul case RPC_UNKNOWNHOST: 32613394Swpaul job->stat = YPPUSH_NOHOST; 32713394Swpaul break; 32813394Swpaul case RPC_PMAPFAILURE: 32913394Swpaul job->stat = YPPUSH_PMAP; 33013394Swpaul break; 33113394Swpaul default: 33213394Swpaul job->stat = YPPUSH_RPC; 33313394Swpaul break; 33413394Swpaul } 33513394Swpaul return(1); 33613394Swpaul } 33713394Swpaul 33813394Swpaul /* 33913394Swpaul * Reduce timeout to nothing since we may not 34013394Swpaul * get a response from ypserv and we don't want to block. 34113394Swpaul */ 34213394Swpaul if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&timeout) == FALSE) 34313394Swpaul yp_error("failed to set timeout on ypproc_xfr call"); 34413394Swpaul 34513394Swpaul /* Invoke the ypproc_xfr service. */ 34613394Swpaul if (ypproc_xfr_2(&req, clnt) == NULL) { 34713394Swpaul clnt_geterr(clnt, &err); 34813394Swpaul if (err.re_status != RPC_SUCCESS && 34913394Swpaul err.re_status != RPC_TIMEDOUT) { 35013394Swpaul yp_error("%s: %s", job->server, clnt_sperror(clnt, 35113394Swpaul "yp_xfr failed")); 35213394Swpaul job->stat = YPPUSH_YPSERV; 35313394Swpaul clnt_destroy(clnt); 35413394Swpaul return(1); 35513394Swpaul } 35613394Swpaul } 35713394Swpaul 35813394Swpaul clnt_destroy(clnt); 35913394Swpaul 36013394Swpaul return(0); 36113394Swpaul} 36213394Swpaul 36313394Swpaul/* 36413394Swpaul * Main driver function. Register the callback service, add the transfer 36513394Swpaul * request to the internal list, send the YPPROC_XFR request to ypserv 36613394Swpaul * do other magic things. 36713394Swpaul */ 36890298Sdesint 36990298Sdesyp_push(char *server, char *map, unsigned long tid) 37013394Swpaul{ 37113394Swpaul unsigned long prognum; 37213394Swpaul int sock = RPC_ANYSOCK; 37313394Swpaul SVCXPRT *xprt; 37413394Swpaul struct jobs *job; 37513394Swpaul 376161359Sthomas /* Register the job in our linked list of jobs. */ 377161359Sthomas 378161359Sthomas /* First allocate job structure */ 379161359Sthomas if ((job = (struct jobs *)malloc(sizeof (struct jobs))) == NULL) { 380161359Sthomas yp_error("malloc failed"); 381161359Sthomas yppush_exit (1); 382161359Sthomas } 383161359Sthomas 38413394Swpaul /* 385161359Sthomas * Register the callback service on the first free transient 386161359Sthomas * program number. 38713394Swpaul */ 38813394Swpaul xprt = svcudp_create(sock); 38915443Swpaul for (prognum = 0x40000000; prognum < 0x5FFFFFFF; prognum++) { 39013394Swpaul if (svc_register(xprt, prognum, 1, 39113394Swpaul yppush_xfrrespprog_1, IPPROTO_UDP) == TRUE) 39213394Swpaul break; 39313394Swpaul } 394161359Sthomas if (prognum == 0x5FFFFFFF) { 395161359Sthomas yp_error ("can't register yppush_xfrrespprog_1"); 396161359Sthomas yppush_exit (1); 39713394Swpaul } 39813394Swpaul 39913394Swpaul /* Initialize the info for this job. */ 40013394Swpaul job->stat = 0; 40113394Swpaul job->tid = tid; 40213394Swpaul job->port = xprt->xp_port; 40313394Swpaul job->server = strdup(server); 40413394Swpaul job->map = strdup(map); 40513394Swpaul job->prognum = prognum; 40613394Swpaul job->polled = 0; 40713394Swpaul job->next = yppush_joblist; 40813394Swpaul yppush_joblist = job; 40913394Swpaul 41013394Swpaul if (verbose) { 41113394Swpaul yp_error("initiating transfer: %s -> %s (transid = %lu)", 41213394Swpaul yppush_mapname, server, tid); 41313394Swpaul } 41413394Swpaul 41513394Swpaul /* 41613394Swpaul * Send the XFR request to ypserv. We don't have to wait for 417161359Sthomas * a response here since we handle them asynchronously. 41813394Swpaul */ 41913394Swpaul 42013394Swpaul if (yppush_send_xfr(job)){ 42113394Swpaul /* Transfer request blew up. */ 42213394Swpaul yppush_show_status(job->stat ? job->stat : 42313394Swpaul YPPUSH_YPSERV,job->tid); 42413394Swpaul } else { 42513394Swpaul if (verbose > 1) 42613394Swpaul yp_error("%s has been called", server); 42713394Swpaul } 42813394Swpaul 42913394Swpaul return(0); 43013394Swpaul} 43113394Swpaul 43213394Swpaul/* 43313394Swpaul * Called for each entry in the ypservers map from yp_get_map(), which 43413394Swpaul * is our private yp_all() routine. 43513394Swpaul */ 43690298Sdesint 43790298Sdesyppush_foreach(int status, char *key, int keylen, char *val, int vallen, 43890298Sdes char *data) 43913394Swpaul{ 44013394Swpaul char server[YPMAXRECORD + 2]; 44113394Swpaul 44213394Swpaul if (status != YP_TRUE) 44313394Swpaul return (status); 44413394Swpaul 44513394Swpaul snprintf(server, sizeof(server), "%.*s", vallen, val); 446161262Sru if (skip_master && strcasecmp(server, yppush_master) == 0) 447161262Sru return (0); 44813394Swpaul 44913394Swpaul /* 450161359Sthomas * Restrict the number of concurrent jobs: if yppush_jobs number 45113394Swpaul * of jobs have already been dispatched and are still pending, 45213394Swpaul * wait for one of them to finish so we can reuse its slot. 45313394Swpaul */ 454161359Sthomas while (yppush_running_jobs >= yppush_jobs && (yppush_svc_run (yppush_timeout) > 0)) 455161359Sthomas ; 45613394Swpaul 45713394Swpaul /* Cleared for takeoff: set everything in motion. */ 45895658Sdes if (yp_push(server, yppush_mapname, yppush_transid)) 45913394Swpaul return(yp_errno); 46013394Swpaul 46113394Swpaul /* Bump the job counter and transaction ID. */ 46213394Swpaul yppush_running_jobs++; 46313394Swpaul yppush_transid++; 46413394Swpaul return (0); 46513394Swpaul} 46613394Swpaul 46713394Swpaulstatic void usage() 46813394Swpaul{ 46930911Scharnier fprintf (stderr, "%s\n%s\n", 47030911Scharnier "usage: yppush [-d domain] [-t timeout] [-j #parallel jobs] [-h host]", 47130911Scharnier " [-p path] mapname"); 47213394Swpaul exit(1); 47313394Swpaul} 47413394Swpaul 47513394Swpaul/* 47613394Swpaul * Entry point. (About time!) 47713394Swpaul */ 47830911Scharnierint 47990298Sdesmain(int argc, char *argv[]) 48013394Swpaul{ 48113394Swpaul int ch; 48213394Swpaul DBT key, data; 48313394Swpaul char myname[MAXHOSTNAMELEN]; 48413394Swpaul struct hostlist { 48513394Swpaul char *name; 48613394Swpaul struct hostlist *next; 48713394Swpaul }; 48813394Swpaul struct hostlist *yppush_hostlist = NULL; 48913394Swpaul struct hostlist *tmp; 49013394Swpaul 49124428Simp while ((ch = getopt(argc, argv, "d:j:p:h:t:v")) != -1) { 49290297Sdes switch (ch) { 49313394Swpaul case 'd': 49413394Swpaul yppush_domain = optarg; 49513394Swpaul break; 49613394Swpaul case 'j': 49713394Swpaul yppush_jobs = atoi(optarg); 49813394Swpaul if (yppush_jobs <= 0) 49913394Swpaul yppush_jobs = 1; 50013394Swpaul break; 50113394Swpaul case 'p': 50213394Swpaul yp_dir = optarg; 50313394Swpaul break; 50413394Swpaul case 'h': /* we can handle multiple hosts */ 50513394Swpaul if ((tmp = (struct hostlist *)malloc(sizeof(struct hostlist))) == NULL) { 50630911Scharnier yp_error("malloc failed"); 50713394Swpaul yppush_exit(1); 50813394Swpaul } 50913394Swpaul tmp->name = strdup(optarg); 51013394Swpaul tmp->next = yppush_hostlist; 51113394Swpaul yppush_hostlist = tmp; 51213394Swpaul break; 51313394Swpaul case 't': 51413394Swpaul yppush_timeout = atoi(optarg); 51513394Swpaul break; 51613394Swpaul case 'v': 51713394Swpaul verbose++; 51813394Swpaul break; 51913394Swpaul default: 52013394Swpaul usage(); 52113394Swpaul break; 52213394Swpaul } 52313394Swpaul } 52413394Swpaul 52513394Swpaul argc -= optind; 52613394Swpaul argv += optind; 52713394Swpaul 52813394Swpaul yppush_mapname = argv[0]; 52913394Swpaul 53013394Swpaul if (yppush_mapname == NULL) { 53113394Swpaul /* "No guts, no glory." */ 53213394Swpaul usage(); 53313394Swpaul } 53413394Swpaul 53513394Swpaul /* 53613394Swpaul * If no domain was specified, try to find the default 53713394Swpaul * domain. If we can't find that, we're doomed and must bail. 53813394Swpaul */ 53913394Swpaul if (yppush_domain == NULL) { 54013394Swpaul char *yppush_check_domain; 54113394Swpaul if (!yp_get_default_domain(&yppush_check_domain) && 54213394Swpaul !_yp_check(&yppush_check_domain)) { 54313394Swpaul yp_error("no domain specified and NIS not running"); 54413394Swpaul usage(); 54513394Swpaul } else 54613394Swpaul yp_get_default_domain(&yppush_domain); 54713394Swpaul } 54813394Swpaul 54913394Swpaul /* Check to see that we are the master for this map. */ 55013394Swpaul 55113394Swpaul if (gethostname ((char *)&myname, sizeof(myname))) { 55213394Swpaul yp_error("failed to get name of local host: %s", 55313394Swpaul strerror(errno)); 55413394Swpaul yppush_exit(1); 55513394Swpaul } 55613394Swpaul 55713394Swpaul key.data = "YP_MASTER_NAME"; 55813394Swpaul key.size = sizeof("YP_MASTER_NAME") - 1; 55913394Swpaul 56013394Swpaul if (yp_get_record(yppush_domain, yppush_mapname, 56113394Swpaul &key, &data, 1) != YP_TRUE) { 56213394Swpaul yp_error("couldn't open %s map: %s", yppush_mapname, 56313394Swpaul strerror(errno)); 56413394Swpaul yppush_exit(1); 56513394Swpaul } 56613394Swpaul 567161262Sru if (strncasecmp(myname, data.data, data.size) == 0) { 568161262Sru /* I am master server, and no explicit host list was 569161262Sru specified: do not push map to myself -- this will 570161262Sru fail with YPPUSH_AGE anyway. */ 571161262Sru if (yppush_hostlist == NULL) 572161262Sru skip_master = 1; 573161262Sru } else { 57415016Swpaul yp_error("warning: this host is not the master for %s", 57515016Swpaul yppush_mapname); 57615016Swpaul#ifdef NITPICKY 57713394Swpaul yppush_exit(1); 57815016Swpaul#endif 57913394Swpaul } 58013394Swpaul 58116242Speter yppush_master = malloc(data.size + 1); 58216242Speter strncpy(yppush_master, data.data, data.size); 58313394Swpaul yppush_master[data.size] = '\0'; 58413394Swpaul 58513394Swpaul /* Install some handy handlers. */ 58613394Swpaul signal(SIGTERM, handler); 58713394Swpaul signal(SIGINT, handler); 58813394Swpaul 58913394Swpaul /* set initial transaction ID */ 59037269Sbde yppush_transid = time((time_t *)NULL); 59113394Swpaul 59213394Swpaul if (yppush_hostlist) { 59313394Swpaul /* 59413394Swpaul * Host list was specified on the command line: 59513394Swpaul * kick off the transfers by hand. 59613394Swpaul */ 59713394Swpaul tmp = yppush_hostlist; 59890297Sdes while (tmp) { 59913394Swpaul yppush_foreach(YP_TRUE, NULL, 0, tmp->name, 60090298Sdes strlen(tmp->name), NULL); 60113394Swpaul tmp = tmp->next; 60213394Swpaul } 60313394Swpaul } else { 60413394Swpaul /* 60513394Swpaul * Do a yp_all() on the ypservers map and initiate a ypxfr 60613394Swpaul * for each one. 60713394Swpaul */ 60813394Swpaul ypxfr_get_map("ypservers", yppush_domain, 60913394Swpaul "localhost", yppush_foreach); 61013394Swpaul } 61113394Swpaul 61213394Swpaul if (verbose > 1) 61313394Swpaul yp_error("all jobs dispatched"); 61413394Swpaul 61513394Swpaul /* All done -- normal exit. */ 61613394Swpaul yppush_exit(0); 61713394Swpaul 61813394Swpaul /* Just in case. */ 61913394Swpaul exit(0); 62013394Swpaul} 621