yp_mkdb.c revision 30777
1/* 2 * Copyright (c) 1995, 1996 3 * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Bill Paul. 16 * 4. Neither the name of the author nor the names of any co-contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33#ifndef lint 34static const char rcsid[] = 35 "$Id$"; 36#endif /* not lint */ 37 38#include <err.h> 39#include <fcntl.h> 40#include <limits.h> 41#include <stdio.h> 42#include <stdlib.h> 43#include <string.h> 44#include <time.h> 45#include <unistd.h> 46#include <rpc/rpc.h> 47#include <rpcsvc/yp.h> 48#include <sys/param.h> 49#include <sys/types.h> 50#include <sys/stat.h> 51#include "yp_extern.h" 52#include "ypxfr_extern.h" 53 54char *yp_dir = ""; /* No particular default needed. */ 55int _rpcpmstart = 0; 56int debug = 1; 57 58static void usage() 59{ 60 fprintf(stderr, "%s\n%s\n%s\n%s\n", 61 "usage: yp_mkdb -c", 62 " yp_mkdb -u dbname", 63 " yp_mkdb [-c] [-b] [-s] [-i inputfile] [-o outputfile]", 64 " [-d domainname ] [-m mastername] inputfile dbname"); 65 exit(1); 66} 67 68#define PERM_SECURE (S_IRUSR|S_IWUSR) 69 70static DB *open_db(path, flags) 71 char *path; 72 int flags; 73{ 74 extern HASHINFO openinfo; 75 76 return(dbopen(path, flags, PERM_SECURE, DB_HASH, &openinfo)); 77} 78 79static void unwind(map) 80 char *map; 81{ 82 DB *dbp; 83 DBT key, data; 84 85 dbp = open_db(map, O_RDONLY); 86 87 if (dbp == NULL) 88 err(1, "open_db(%s) failed", map); 89 90 key.data = NULL; 91 while(yp_next_record(dbp, &key, &data, 1, 1) == YP_TRUE) 92 printf("%.*s %.*s\n", key.size,key.data,data.size,data.data); 93 94 (void)(dbp->close)(dbp); 95 return; 96} 97 98int main (argc, argv) 99 int argc; 100 char *argv[]; 101{ 102 int ch; 103 int un = 0; 104 int clear = 0; 105 char *infile = NULL; 106 char *map = NULL; 107 char *domain = NULL; 108 char *infilename = NULL; 109 char *outfilename = NULL; 110 char *mastername = NULL; 111 int interdom = 0; 112 int secure = 0; 113 DB *dbp; 114 DBT key, data; 115 char buf[10240]; 116 char *keybuf, *datbuf; 117 FILE *ifp; 118 char hname[MAXHOSTNAMELEN + 2]; 119 120 while ((ch = getopt(argc, argv, "uhcbsd:i:o:m:")) != -1) { 121 switch(ch) { 122 case 'u': 123 un++; 124 break; 125 case 'c': 126 clear++; 127 break; 128 case 'b': 129 interdom++; 130 break; 131 case 's': 132 secure++; 133 break; 134 case 'd': 135 domain = optarg; 136 break; 137 case 'i': 138 infilename = optarg; 139 break; 140 case 'o': 141 outfilename = optarg; 142 break; 143 case 'm': 144 mastername = optarg; 145 break; 146 case 'h': 147 default: 148 usage(); 149 break; 150 } 151 } 152 153 argc -= optind; 154 argv += optind; 155 156 if (un) { 157 map = argv[0]; 158 if (map == NULL) 159 usage(); 160 unwind(map); 161 exit(0); 162 163 } 164 165 infile = argv[0]; 166 map = argv[1]; 167 168 if (infile == NULL || map == NULL) { 169 if (clear) 170 goto doclear; 171 usage(); 172 } 173 174 if (mastername == NULL) { 175 if (gethostname((char *)&hname, sizeof(hname)) == -1) 176 err(1, "gethostname() failed"); 177 mastername = (char *)&hname; 178 } 179 180 /* 181 * Note that while we can read from stdin, we can't 182 * write to stdout; the db library doesn't let you 183 * write to a file stream like that. 184 */ 185 186 if (!strcmp(infile, "-")) { 187 ifp = stdin; 188 } else { 189 if ((ifp = fopen(infile, "r")) == NULL) 190 err(1, "failed to open %s", infile); 191 } 192 193 if ((dbp = open_db(map, O_RDWR|O_EXLOCK|O_EXCL|O_CREAT)) == NULL) 194 err(1, "open_db(%s) failed", map); 195 196 if (interdom) { 197 key.data = "YP_INTERDOMAIN"; 198 key.size = sizeof("YP_INTERDOMAIN") - 1; 199 data.data = ""; 200 data.size = 0; 201 yp_put_record(dbp, &key, &data, 0); 202 } 203 204 if (secure) { 205 key.data = "YP_SECURE"; 206 key.size = sizeof("YP_SECURE") - 1; 207 data.data = ""; 208 data.size = 0; 209 yp_put_record(dbp, &key, &data, 0); 210 } 211 212 key.data = "YP_MASTER_NAME"; 213 key.size = sizeof("YP_MASTER_NAME") - 1; 214 data.data = mastername; 215 data.size = strlen(mastername); 216 yp_put_record(dbp, &key, &data, 0); 217 218 key.data = "YP_LAST_MODIFIED"; 219 key.size = sizeof("YP_LAST_MODIFIED") - 1; 220 snprintf(buf, sizeof(buf), "%lu", time(NULL)); 221 data.data = (char *)&buf; 222 data.size = strlen(buf); 223 yp_put_record(dbp, &key, &data, 0); 224 225 if (infilename) { 226 key.data = "YP_INPUT_FILE"; 227 key.size = sizeof("YP_INPUT_FILE") - 1; 228 data.data = infilename; 229 data.size = strlen(infilename); 230 yp_put_record(dbp, &key, &data, 0); 231 } 232 233 if (outfilename) { 234 key.data = "YP_OUTPUT_FILE"; 235 key.size = sizeof("YP_OUTPUT_FILE") - 1; 236 data.data = outfilename; 237 data.size = strlen(outfilename); 238 yp_put_record(dbp, &key, &data, 0); 239 } 240 241 if (domain) { 242 key.data = "YP_DOMAIN_NAME"; 243 key.size = sizeof("YP_DOMAIN_NAME") - 1; 244 data.data = domain; 245 data.size = strlen(domain); 246 yp_put_record(dbp, &key, &data, 0); 247 } 248 249 while(fgets((char *)&buf, sizeof(buf), ifp)) { 250 char *sep = NULL; 251 int rval; 252 253 /* NUL terminate */ 254 if ((sep = strchr(buf, '\n'))) 255 *sep = '\0'; 256 257 /* handle backslash line continuations */ 258 while(buf[strlen(buf) - 1] == '\\') { 259 fgets((char *)&buf[strlen(buf) - 1], 260 sizeof(buf) - strlen(buf), ifp); 261 if ((sep = strchr(buf, '\n'))) 262 *sep = '\0'; 263 } 264 265 /* find the separation between the key and data */ 266 if ((sep = strpbrk(buf, " \t")) == NULL) { 267 warnx("bad input -- no white space: %s", buf); 268 continue; 269 } 270 271 /* separate the strings */ 272 keybuf = (char *)&buf; 273 datbuf = sep + 1; 274 *sep = '\0'; 275 276 /* set datbuf to start at first non-whitespace character */ 277 while (*datbuf == ' ' || *datbuf == '\t') 278 datbuf++; 279 280 /* Check for silliness. */ 281 if (*keybuf == '+' || *keybuf == '-' || 282 *datbuf == '+' || *datbuf == '-') { 283 warnx("bad character at start of line: %s", buf); 284 continue; 285 } 286 287 if (strlen(keybuf) > YPMAXRECORD) { 288 warnx("key too long: %s", keybuf); 289 continue; 290 } 291 292 if (!strlen(keybuf)) { 293 warnx("no key -- check source file for blank lines"); 294 continue; 295 } 296 297 if (strlen(datbuf) > YPMAXRECORD) { 298 warnx("data too long: %s", datbuf); 299 continue; 300 } 301 302 key.data = keybuf; 303 key.size = strlen(keybuf); 304 data.data = datbuf; 305 data.size = strlen(datbuf); 306 307 if ((rval = yp_put_record(dbp, &key, &data, 0)) != YP_TRUE) { 308 switch(rval) { 309 case YP_FALSE: 310 warnx("duplicate key '%s' - skipping", keybuf); 311 break; 312 case YP_BADDB: 313 default: 314 err(1,"failed to write new record - exiting"); 315 break; 316 } 317 } 318 319 } 320 321 (void)(dbp->close)(dbp); 322 323doclear: 324 325 if (clear) { 326 char in = 0; 327 char *out = NULL; 328 int stat; 329 if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, 330 xdr_void, (void *)&in, 331 xdr_void, (void *)out)) != RPC_SUCCESS) { 332 warnx("failed to send 'clear' to local ypserv: %s", 333 clnt_sperrno((enum clnt_stat) stat)); 334 } 335 } 336 337 exit(0); 338} 339