ypxfr_main.c revision 16132
113007Swpaul/* 213007Swpaul * Copyright (c) 1995 313007Swpaul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 413007Swpaul * 513007Swpaul * Redistribution and use in source and binary forms, with or without 613007Swpaul * modification, are permitted provided that the following conditions 713007Swpaul * are met: 813007Swpaul * 1. Redistributions of source code must retain the above copyright 913007Swpaul * notice, this list of conditions and the following disclaimer. 1013007Swpaul * 2. Redistributions in binary form must reproduce the above copyright 1113007Swpaul * notice, this list of conditions and the following disclaimer in the 1213007Swpaul * documentation and/or other materials provided with the distribution. 1313007Swpaul * 3. All advertising materials mentioning features or use of this software 1413007Swpaul * must display the following acknowledgement: 1513007Swpaul * This product includes software developed by Bill Paul. 1613007Swpaul * 4. Neither the name of the author nor the names of any co-contributors 1713007Swpaul * may be used to endorse or promote products derived from this software 1813007Swpaul * without specific prior written permission. 1913007Swpaul * 2013007Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 2113007Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2213007Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2313007Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 2413007Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2513007Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2613007Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2713007Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2813007Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2913007Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3013007Swpaul * SUCH DAMAGE. 3113007Swpaul * 3216132Swpaul * $Id: ypxfr_main.c,v 1.17 1996/06/03 03:11:39 wpaul Exp $ 3313007Swpaul */ 3413007Swpaul#include <stdio.h> 3513007Swpaul#include <stdlib.h> 3613007Swpaul#include <unistd.h> 3713007Swpaul#include <string.h> 3813007Swpaul#include <syslog.h> 3913007Swpaul#include <errno.h> 4013007Swpaul#include <sys/types.h> 4113007Swpaul#include <sys/param.h> 4213007Swpaul#include <sys/socket.h> 4313007Swpaul#include <netinet/in.h> 4413007Swpaul#include <arpa/inet.h> 4513007Swpaul#include <rpc/rpc.h> 4613376Swpaul#include <rpc/clnt.h> 4713007Swpaul#include <rpcsvc/yp.h> 4813007Swpaulstruct dom_binding {}; 4913007Swpaul#include <rpcsvc/ypclnt.h> 5016132Swpaul#include <rpcsvc/ypxfrd.h> 5113007Swpaul#include "ypxfr_extern.h" 5213007Swpaul 5313007Swpaul#ifndef lint 5416132Swpaulstatic const char rcsid[] = "$Id: ypxfr_main.c,v 1.17 1996/06/03 03:11:39 wpaul Exp $"; 5513007Swpaul#endif 5613007Swpaul 5713007Swpaulchar *progname = "ypxfr"; 5813007Swpaulchar *yp_dir = _PATH_YP; 5913007Swpaulint _rpcpmstart = 0; 6013007Swpaulint ypxfr_use_yplib = 0; /* Assume the worst. */ 6113007Swpaulint ypxfr_clear = 1; 6213007Swpaulint ypxfr_prognum = 0; 6313007Swpaulstruct sockaddr_in ypxfr_callback_addr; 6413007Swpaulstruct yppushresp_xfr ypxfr_resp; 6513007SwpaulDB *dbp; 6613007Swpaul 6713007Swpaulstatic void ypxfr_exit(retval, temp) 6813007Swpaul ypxfrstat retval; 6913007Swpaul char *temp; 7013007Swpaul{ 7113007Swpaul CLIENT *clnt; 7213007Swpaul int sock = RPC_ANYSOCK; 7313007Swpaul struct timeval timeout; 7413007Swpaul 7513007Swpaul /* Clean up no matter what happened previously. */ 7613007Swpaul if (temp != NULL) { 7713276Swpaul if (dbp != NULL) 7813276Swpaul (void)(dbp->close)(dbp); 7913007Swpaul if (unlink(temp) == -1) { 8013007Swpaul yp_error("failed to unlink %s",strerror(errno)); 8113007Swpaul } 8213007Swpaul } 8313007Swpaul 8413007Swpaul if (_rpcpmstart) { 8513007Swpaul timeout.tv_sec = 20; 8613007Swpaul timeout.tv_usec = 0; 8713007Swpaul 8813007Swpaul if ((clnt = clntudp_create(&ypxfr_callback_addr, ypxfr_prognum, 8913007Swpaul 1, timeout, &sock)) == NULL) { 9016132Swpaul yp_error("%s", clnt_spcreateerror("failed to \ 9116132Swpaulestablish callback handle")); 9213007Swpaul exit(1); 9313007Swpaul } 9413007Swpaul 9513007Swpaul ypxfr_resp.status = retval; 9613007Swpaul 9713007Swpaul if (yppushproc_xfrresp_1(&ypxfr_resp, clnt) == NULL) { 9813007Swpaul yp_error("%s", clnt_sperror(clnt, "callback failed")); 9913007Swpaul clnt_destroy(clnt); 10013007Swpaul exit(1); 10113007Swpaul } 10213007Swpaul clnt_destroy(clnt); 10313007Swpaul } else { 10413007Swpaul yp_error("Exiting: %s", ypxfrerr_string(retval)); 10513007Swpaul } 10613007Swpaul 10713007Swpaul exit(0); 10813007Swpaul} 10913007Swpaul 11013007Swpaulstatic void usage() 11113007Swpaul{ 11213007Swpaul if (_rpcpmstart) { 11313007Swpaul ypxfr_exit(YPXFR_BADARGS,NULL); 11413007Swpaul } else { 11513007Swpaul fprintf(stderr,"usage: %s [-f] [-c] [-d target domain] \ 11613007Swpaul[-h source host] [-s source domain]\n", progname); 11713007Swpaul fprintf(stderr,"\t [-p path] [-C taskid program-number \ 11813007Swpaulipaddr port] mapname\n"); 11913007Swpaul exit(1); 12013007Swpaul } 12113007Swpaul} 12213007Swpaul 12313007Swpaulint ypxfr_foreach(status, key, keylen, val, vallen, data) 12413007Swpaul int status; 12513007Swpaul char *key; 12613007Swpaul int keylen; 12713007Swpaul char *val; 12813007Swpaul int vallen; 12913007Swpaul char *data; 13013007Swpaul{ 13113007Swpaul DBT dbkey, dbval; 13213007Swpaul 13313007Swpaul if (status != YP_TRUE) 13413007Swpaul return (status); 13513007Swpaul 13613007Swpaul dbkey.data = key; 13713007Swpaul dbkey.size = keylen; 13813007Swpaul dbval.data = val; 13913007Swpaul dbval.size = vallen; 14013007Swpaul 14116132Swpaul if (yp_put_record(dbp, &dbkey, &dbval, 0) != YP_TRUE) 14213007Swpaul return(yp_errno); 14313007Swpaul 14413007Swpaul return (0); 14513007Swpaul} 14613007Swpaul 14713007Swpaulmain(argc,argv) 14813007Swpaul int argc; 14913007Swpaul char *argv[]; 15013007Swpaul{ 15113007Swpaul int ch; 15213007Swpaul int ypxfr_force = 0; 15313007Swpaul char *ypxfr_dest_domain = NULL; 15413007Swpaul char *ypxfr_source_host = NULL; 15513007Swpaul char *ypxfr_source_domain = NULL; 15613007Swpaul char *ypxfr_local_domain = NULL; 15713007Swpaul char *ypxfr_master = NULL; 15813007Swpaul unsigned long ypxfr_order = -1, ypxfr_skew_check = -1; 15913007Swpaul char *ypxfr_mapname = NULL; 16013007Swpaul int ypxfr_args = 0; 16113007Swpaul char ypxfr_temp_map[MAXPATHLEN + 2]; 16213007Swpaul char tempmap[MAXPATHLEN + 2]; 16313007Swpaul char buf[MAXPATHLEN + 2]; 16413007Swpaul DBT key, data; 16513007Swpaul 16613007Swpaul debug = 1; 16713007Swpaul 16813007Swpaul if (!isatty(fileno(stderr))) { 16913007Swpaul openlog(progname, LOG_PID, LOG_DAEMON); 17013007Swpaul _rpcpmstart = 1; 17113007Swpaul } 17213007Swpaul 17313007Swpaul if (argc < 2) 17413007Swpaul usage(); 17513007Swpaul 17613007Swpaul while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != EOF) { 17713007Swpaul int my_optind; 17813007Swpaul switch(ch) { 17913007Swpaul case 'f': 18013007Swpaul ypxfr_force++; 18113007Swpaul ypxfr_args++; 18213007Swpaul break; 18313007Swpaul case 'c': 18413007Swpaul ypxfr_clear = 0; 18513007Swpaul ypxfr_args++; 18613007Swpaul break; 18713007Swpaul case 'd': 18813007Swpaul ypxfr_dest_domain = optarg; 18913007Swpaul ypxfr_args += 2; 19013007Swpaul break; 19113007Swpaul case 'h': 19213007Swpaul ypxfr_source_host = optarg; 19313007Swpaul ypxfr_args += 2; 19413007Swpaul break; 19513007Swpaul case 's': 19613007Swpaul ypxfr_source_domain = optarg; 19713007Swpaul ypxfr_args += 2; 19813007Swpaul break; 19913007Swpaul case 'p': 20013007Swpaul yp_dir = optarg; 20113007Swpaul ypxfr_args += 2; 20213007Swpaul break; 20313007Swpaul case 'C': 20413007Swpaul /* 20513007Swpaul * Whoever decided that the -C flag should take 20613007Swpaul * four arguments is a twit. 20713007Swpaul */ 20813007Swpaul my_optind = optind - 1; 20913007Swpaul if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { 21013007Swpaul yp_error("transaction ID not specified"); 21113007Swpaul usage(); 21213007Swpaul } 21313007Swpaul ypxfr_resp.transid = atol(argv[my_optind]); 21413007Swpaul my_optind++; 21513007Swpaul if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { 21613007Swpaul yp_error("RPC program number not specified"); 21713007Swpaul usage(); 21813007Swpaul } 21913007Swpaul ypxfr_prognum = atol(argv[my_optind]); 22013007Swpaul my_optind++; 22113007Swpaul if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { 22213007Swpaul yp_error("address not specified"); 22313007Swpaul usage(); 22413007Swpaul } 22513007Swpaul if (!inet_aton(argv[my_optind], &ypxfr_callback_addr.sin_addr)) { 22613007Swpaul yp_error("failed to convert '%s' to IP addr", 22713007Swpaul argv[my_optind]); 22813007Swpaul exit(1); 22913007Swpaul } 23013007Swpaul my_optind++; 23113007Swpaul if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { 23213007Swpaul yp_error("port not specified"); 23313007Swpaul usage(); 23413007Swpaul } 23513007Swpaul ypxfr_callback_addr.sin_port = htons((u_short)atoi(argv[my_optind])); 23613007Swpaul ypxfr_args += 5; 23713007Swpaul break; 23813007Swpaul default: 23913007Swpaul usage(); 24013007Swpaul break; 24113007Swpaul } 24213007Swpaul } 24313007Swpaul 24413007Swpaul ypxfr_mapname = argv[ypxfr_args + 1]; 24513007Swpaul 24613007Swpaul if (ypxfr_mapname == NULL) { 24713007Swpaul yp_error("no map name specified"); 24813007Swpaul usage(); 24913007Swpaul } 25013007Swpaul 25113007Swpaul /* Always the case. */ 25213007Swpaul ypxfr_callback_addr.sin_family = AF_INET; 25313007Swpaul 25413007Swpaul /* Determine if local NIS client facilities are turned on. */ 25513007Swpaul if (!yp_get_default_domain(&ypxfr_local_domain) && 25613007Swpaul _yp_check(&ypxfr_local_domain)) 25713007Swpaul ypxfr_use_yplib = 1; 25813007Swpaul 25913007Swpaul /* 26013007Swpaul * If no destination domain is specified, assume that the 26113007Swpaul * local default domain is to be used and try to obtain it. 26213007Swpaul * Fails if NIS client facilities are turned off. 26313007Swpaul */ 26413007Swpaul if (ypxfr_dest_domain == NULL) { 26513007Swpaul if (ypxfr_use_yplib) { 26613007Swpaul yp_get_default_domain(&ypxfr_dest_domain); 26713007Swpaul } else { 26813007Swpaul yp_error("no destination domain specified and \ 26913007Swpaulthe local domain name isn't set"); 27013007Swpaul ypxfr_exit(YPXFR_BADARGS,NULL); 27113007Swpaul } 27213007Swpaul } 27313007Swpaul 27413007Swpaul /* 27513007Swpaul * If a source domain is not specified, assume it to 27613007Swpaul * be the same as the destination domain. 27713007Swpaul */ 27813007Swpaul if (ypxfr_source_domain == NULL) { 27913007Swpaul ypxfr_source_domain = ypxfr_dest_domain; 28013007Swpaul } 28113007Swpaul 28213007Swpaul /* 28313007Swpaul * If the source host is not specified, assume it to be the 28413007Swpaul * master for the specified map. If local NIS client facilities 28513007Swpaul * are turned on, we can figure this out using yp_master(). 28613007Swpaul * If not, we have to see if a local copy of the map exists 28713007Swpaul * and extract its YP_MASTER_NAME record. If _that_ fails, 28813007Swpaul * we are stuck and must ask the user for more information. 28913007Swpaul */ 29013007Swpaul if (ypxfr_source_host == NULL) { 29113007Swpaul if (!ypxfr_use_yplib) { 29213007Swpaul /* 29313007Swpaul * Double whammy: NIS isn't turned on and the user 29413007Swpaul * didn't specify a source host. 29513007Swpaul */ 29613007Swpaul char *dptr; 29713007Swpaul key.data = "YP_MASTER_NAME"; 29813007Swpaul key.size = sizeof("YP_MASTER_NAME") - 1; 29913007Swpaul 30013007Swpaul if (yp_get_record(ypxfr_dest_domain, ypxfr_mapname, 30113007Swpaul &key, &data, 1) != YP_TRUE) { 30213007Swpaul yp_error("no source host specified"); 30313007Swpaul ypxfr_exit(YPXFR_BADARGS,NULL); 30413007Swpaul } 30513007Swpaul dptr = data.data; 30613007Swpaul dptr[data.size] = '\0'; 30713007Swpaul ypxfr_master = ypxfr_source_host = strdup(dptr); 30813007Swpaul } 30913007Swpaul } else { 31013007Swpaul if (ypxfr_use_yplib) 31113007Swpaul ypxfr_use_yplib = 0; 31213007Swpaul } 31313007Swpaul 31413007Swpaul if (ypxfr_master == NULL) { 31513007Swpaul if ((ypxfr_master = ypxfr_get_master(ypxfr_source_domain, 31613007Swpaul ypxfr_mapname, 31713007Swpaul ypxfr_source_host, 31813007Swpaul ypxfr_use_yplib)) == NULL) { 31913276Swpaul yp_error("failed to find master of %s in domain %s: %s", 32013276Swpaul ypxfr_mapname, ypxfr_source_domain, 32113276Swpaul ypxfrerr_string(yp_errno)); 32213007Swpaul ypxfr_exit(YPXFR_MADDR,NULL); 32313007Swpaul } 32413007Swpaul } 32513007Swpaul 32613007Swpaul /* 32713007Swpaul * If we got here and ypxfr_source_host is still undefined, 32813007Swpaul * it means we had to resort to using yp_master() to find the 32913007Swpaul * master server for the map. The source host and master should 33013007Swpaul * be identical. 33113007Swpaul */ 33213007Swpaul if (ypxfr_source_host == NULL) 33313007Swpaul ypxfr_source_host = ypxfr_master; 33413007Swpaul 33513007Swpaul if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain, 33613007Swpaul ypxfr_mapname, 33713007Swpaul ypxfr_master, 0)) == 0) { 33813276Swpaul yp_error("failed to get order number of %s: %s", 33913376Swpaul ypxfr_mapname, yp_errno == YPXFR_SUCC ? 34013376Swpaul "map has order 0" : ypxfrerr_string(yp_errno)); 34113007Swpaul ypxfr_exit(YPXFR_YPERR,NULL); 34213007Swpaul } 34313007Swpaul 34413007Swpaul key.data = "YP_LAST_MODIFIED"; 34513007Swpaul key.size = sizeof("YP_LAST_MODIFIED") - 1; 34613007Swpaul 34713007Swpaul /* The order number is immaterial when the 'force' flag is set. */ 34813007Swpaul 34913007Swpaul if (!ypxfr_force) { 35013007Swpaul int ignore = 0; 35113007Swpaul if (yp_get_record(ypxfr_dest_domain,ypxfr_mapname,&key,&data,1) != YP_TRUE) { 35213007Swpaul switch(yp_errno) { 35313007Swpaul case YP_NOKEY: 35413007Swpaul ypxfr_exit(YPXFR_FORCE,NULL); 35513007Swpaul break; 35613007Swpaul case YP_NOMAP: 35713007Swpaul /* 35813007Swpaul * If the map doesn't exist, we're 35913007Swpaul * creating it. Ignore the error. 36013007Swpaul */ 36113007Swpaul ignore++; 36213007Swpaul break; 36313007Swpaul case YP_BADDB: 36413007Swpaul default: 36513007Swpaul ypxfr_exit(YPXFR_DBM,NULL); 36613007Swpaul break; 36713007Swpaul } 36813007Swpaul } 36913007Swpaul if (!ignore && ypxfr_order <= atoi(data.data)) 37013007Swpaul ypxfr_exit(YPXFR_AGE, NULL); 37113007Swpaul 37213007Swpaul } 37313007Swpaul 37413007Swpaul /* Construct a temporary map file name */ 37513007Swpaul snprintf(tempmap, sizeof(tempmap), "%s.%d",ypxfr_mapname, getpid()); 37613007Swpaul snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir, 37713007Swpaul ypxfr_dest_domain, tempmap); 37813007Swpaul 37916132Swpaul if (getrpcport(ypxfr_master, YPXFRD_FREEBSD_PROG, 38016132Swpaul YPXFRD_FREEBSD_VERS, IPPROTO_TCP)) { 38116132Swpaul /* Try to send using ypxfrd. If it fails, use old method. */ 38216132Swpaul if (!ypxfrd_get_map(ypxfr_master, ypxfr_mapname, 38316132Swpaul ypxfr_source_domain, ypxfr_temp_map)) 38416132Swpaul goto leave; 38516132Swpaul } 38616132Swpaul 38713007Swpaul /* Open the temporary map read/write. */ 38816132Swpaul if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap, 0)) == NULL) { 38913007Swpaul yp_error("failed to open temporary map file"); 39013007Swpaul ypxfr_exit(YPXFR_DBM,NULL); 39113007Swpaul } 39213007Swpaul 39313007Swpaul /* 39413007Swpaul * Fill in the keys we already know, such as the order number, 39513007Swpaul * master name, input file name (we actually make up a bogus 39613007Swpaul * name for that) and output file name. 39713007Swpaul */ 39813007Swpaul snprintf(buf, sizeof(buf), "%d", ypxfr_order); 39913007Swpaul data.data = buf; 40013007Swpaul data.size = strlen(buf); 40113007Swpaul 40216132Swpaul if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { 40313007Swpaul yp_error("failed to write order number to database"); 40413007Swpaul ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); 40513007Swpaul } 40613007Swpaul 40713007Swpaul key.data = "YP_MASTER_NAME"; 40813007Swpaul key.size = sizeof("YP_MASTER_NAME") - 1; 40913007Swpaul data.data = ypxfr_master; 41013007Swpaul data.size = strlen(ypxfr_master); 41113007Swpaul 41216132Swpaul if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { 41313007Swpaul yp_error("failed to write master name to database"); 41413007Swpaul ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); 41513007Swpaul } 41613007Swpaul 41713007Swpaul key.data = "YP_DOMAIN_NAME"; 41813007Swpaul key.size = sizeof("YP_DOMAIN_NAME") - 1; 41913007Swpaul data.data = ypxfr_dest_domain; 42013007Swpaul data.size = strlen(ypxfr_dest_domain); 42113007Swpaul 42216132Swpaul if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { 42313007Swpaul yp_error("failed to write domain name to database"); 42413007Swpaul ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); 42513007Swpaul } 42613007Swpaul 42713007Swpaul snprintf (buf, sizeof(buf), "%s:%s", ypxfr_source_host, ypxfr_mapname); 42813007Swpaul 42913007Swpaul key.data = "YP_INPUT_NAME"; 43013007Swpaul key.size = sizeof("YP_INPUT_NAME") - 1; 43113007Swpaul data.data = &buf; 43213007Swpaul data.size = strlen(buf); 43313007Swpaul 43416132Swpaul if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { 43513007Swpaul yp_error("failed to write input name to database"); 43613007Swpaul ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); 43713007Swpaul 43813007Swpaul } 43913007Swpaul 44013007Swpaul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, 44113007Swpaul ypxfr_mapname); 44213007Swpaul 44313007Swpaul key.data = "YP_OUTPUT_NAME"; 44413007Swpaul key.size = sizeof("YP_OUTPUT_NAME") - 1; 44513007Swpaul data.data = &buf; 44613007Swpaul data.size = strlen(buf); 44713007Swpaul 44816132Swpaul if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { 44913007Swpaul yp_error("failed to write output name to database"); 45013007Swpaul ypxfr_exit(YPXFR_DBM,&ypxfr_temp_map); 45113007Swpaul } 45213007Swpaul 45313007Swpaul /* Now suck over the contents of the map from the master. */ 45413007Swpaul 45513007Swpaul if (ypxfr_get_map(ypxfr_mapname,ypxfr_source_domain, 45613007Swpaul ypxfr_source_host, ypxfr_foreach)){ 45713007Swpaul yp_error("failed to retrieve map from source host"); 45813007Swpaul ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map); 45913007Swpaul } 46013007Swpaul 46113007Swpaul (void)(dbp->close)(dbp); 46213276Swpaul dbp = NULL; /* <- yes, it seems this is necessary. */ 46313007Swpaul 46416132Swpaulleave: 46516132Swpaul 46616132Swpaul snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, 46716132Swpaul ypxfr_mapname); 46816132Swpaul 46913007Swpaul /* Peek at the order number again and check for skew. */ 47013007Swpaul if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain, 47113007Swpaul ypxfr_mapname, 47213007Swpaul ypxfr_master, 0)) == 0) { 47313276Swpaul yp_error("failed to get order number of %s: %s", 47413376Swpaul ypxfr_mapname, yp_errno == YPXFR_SUCC ? 47513376Swpaul "map has order 0" : ypxfrerr_string(yp_errno)); 47613007Swpaul ypxfr_exit(YPXFR_YPERR,&ypxfr_temp_map); 47713007Swpaul } 47813007Swpaul 47913007Swpaul if (ypxfr_order != ypxfr_skew_check) 48013007Swpaul ypxfr_exit(YPXFR_SKEW,&ypxfr_temp_map); 48113007Swpaul 48213007Swpaul /* 48313007Swpaul * Send a YPPROC_CLEAR to the local ypserv. 48413007Swpaul */ 48513376Swpaul if (ypxfr_clear) { 48613007Swpaul char in = 0; 48713007Swpaul char *out = NULL; 48813376Swpaul int stat; 48913376Swpaul if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, 49013376Swpaul xdr_void, (void *)&in, 49113376Swpaul xdr_void, (void *)out)) != RPC_SUCCESS) { 49213376Swpaul yp_error("failed to send 'clear' to local ypserv: %s", 49313376Swpaul clnt_sperrno((enum clnt_stat) stat)); 49413376Swpaul ypxfr_exit(YPXFR_CLEAR, &ypxfr_temp_map); 49513007Swpaul } 49613007Swpaul } 49713007Swpaul 49813376Swpaul /* 49913376Swpaul * Put the new map in place immediately. I'm not sure if the 50013376Swpaul * kernel does an unlink() and rename() atomically in the event 50113376Swpaul * that we move a new copy of a map over the top of an existing 50213376Swpaul * one, but there's less chance of a race condition happening 50313376Swpaul * than if we were to do the unlink() ourselves. 50413376Swpaul */ 50513007Swpaul if (rename(ypxfr_temp_map, buf) == -1) { 50613007Swpaul yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf, 50713007Swpaul strerror(errno)); 50813007Swpaul ypxfr_exit(YPXFR_FILE,NULL); 50913007Swpaul } 51013007Swpaul 51113007Swpaul ypxfr_exit(YPXFR_SUCC,NULL); 51213007Swpaul 51313007Swpaul return(1); 51413007Swpaul} 515