1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <stdio.h> 27 #include <sys/types.h> 28 #include <sys/wait.h> 29 #include <sys/vtoc.h> 30 #include <sys/stat.h> 31 #include <stdio.h> 32 #include <sys/mnttab.h> 33 #include <errno.h> 34 #include <limits.h> 35 #include <fcntl.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <stdlib.h> 39 #include <unistd.h> 40 #include <time.h> 41 42 #include <locale.h> 43 #include <langinfo.h> 44 #include <libintl.h> 45 #include <stdarg.h> 46 #include <netdb.h> 47 #include <ctype.h> 48 #include <assert.h> 49 50 #include <sys/nsctl/cfg_impl.h> 51 #include <sys/nsctl/cfg.h> 52 53 #include <sys/unistat/spcs_s.h> 54 #include <sys/unistat/spcs_s_u.h> 55 #include <sys/unistat/spcs_errors.h> 56 57 #ifdef DEBUG 58 #include <sys/nsctl/dsw.h> 59 #endif 60 61 #define DEFAULT_PARSER_LOC "/etc/dscfg_format" 62 63 int Cflg; 64 int Dflg; 65 int Lflg; 66 int aflg; 67 int iflg; 68 int lflg; 69 int nflg; 70 int pflg; 71 int rflg; 72 int sflg; 73 int uflg; 74 75 int verbose; 76 int noflags; 77 int errflg; 78 int mustcommit; 79 char *locname; /* config location from cfg_location */ 80 char *cmdname; 81 82 #define MAX_FILENAME 80 83 84 char output_file[MAX_FILENAME]; /* specified output file */ 85 char altroot[MAX_FILENAME]; /* specifed root location */ 86 char config_file[MAX_FILENAME]; /* specified configuration file */ 87 char input_file[MAX_FILENAME]; /* specified input file */ 88 char logical_host[MAX_FILENAME]; /* specified cluster node */ 89 char device_group[MAX_FILENAME]; /* specified device group name */ 90 91 #define IS_NOT_CLUSTER 1 92 #define IS_CLUSTER 2 93 94 void cfg_invalidate_hsizes(int, const char *); 95 static int check_cluster(); 96 97 void 98 usage(char *errmsg) 99 { 100 if (errmsg) 101 (void) fprintf(stderr, "%s: %s\n", cmdname, errmsg); 102 (void) fprintf(stderr, 103 gettext("dscfg \t\t\t\tDisplay location of " 104 "local configuration database\n")); 105 (void) fprintf(stderr, gettext("dscfg -l -s path\t\t" 106 "List contents of configuration database\n")); 107 (void) fprintf(stderr, gettext( 108 "\t\t\t\tlocated at path specified\n")); 109 (void) fprintf(stderr, gettext("dscfg -i\t\t\t" 110 "Initialize configuration database\n")); 111 (void) fprintf(stderr, 112 gettext("dscfg -i -p " 113 #ifdef DEBUG 114 "[-n] " 115 #endif 116 "/etc/dscfg_format\tFormat configuration database\n")); 117 (void) fprintf(stderr, 118 gettext("dscfg -a file\t\t\tRestore configuration " 119 "database from file\n")); 120 (void) fprintf(stderr, gettext("\t\t\t\tspecified\n")); 121 (void) fprintf(stderr, 122 gettext("dscfg -l\t\t\tList contents of configuration database" 123 "\n")); 124 (void) fprintf(stderr, 125 gettext("dscfg -L\t\t\tDisplay configuration database's\n")); 126 (void) fprintf(stderr, gettext("\t\t\t\tlock status\n")); 127 (void) fprintf(stderr, gettext("dscfg -h\t\t\tUsage message\n")); 128 if (check_cluster() != IS_NOT_CLUSTER) { 129 (void) fprintf(stderr, gettext("\nSun Cluster Usage\n")); 130 (void) fprintf(stderr, gettext("******************\n")); 131 (void) fprintf(stderr, 132 gettext("dscfg -s path\t\t\tSet cluster " 133 "configuration database at DID\n")); 134 (void) fprintf(stderr, gettext("\t\t\t\tpath specified\n")); 135 (void) fprintf(stderr, gettext("dscfg -D device_group\t\t" 136 "Check status of cluster device group\n")); 137 (void) fprintf(stderr, gettext("dscfg -C -\t\t\t" 138 "Display location of cluster configuration\n")); 139 (void) fprintf(stderr, gettext("\t\t\t\tdatabase\n")); 140 (void) fprintf(stderr, gettext("dscfg -l -s DID_device\t\tList " 141 "the contents of cluster configuration\n")); 142 (void) fprintf(stderr, gettext("\t\t\t\tdatabase\n")); 143 (void) fprintf(stderr, gettext("dscfg -C - -i\t\t\tInitialize " 144 "cluster configuration database\n")); 145 (void) fprintf(stderr, gettext("dscfg -C - -i -p " 146 "/etc/dscfg_format Format cluster configuration database\n")); 147 (void) fprintf(stderr, gettext("dscfg -C - -a file\t\t" 148 "Restore cluster configuration database from\n")); 149 (void) fprintf(stderr, gettext("\t\t\t\tfile specified\n")); 150 (void) fprintf(stderr, gettext("dscfg -C - -l\t\t\t" 151 "List contents of local configuration database\n")); 152 (void) fprintf(stderr, gettext("dscfg -C device_group -l\t" 153 "List configuration database by device group\n")); 154 (void) fprintf(stderr, gettext("dscfg -C \"-\" -l\t\t\t" 155 "List configuration database excluding\n")); 156 (void) fprintf(stderr, gettext("\t\t\t\tdevice groups\n")); 157 } 158 } 159 160 int 161 parse_parse_config(CFGFILE *cfg) 162 { 163 FILE *fp; 164 char inbuf[CFG_MAX_BUF]; 165 char *buff; 166 int rc; 167 168 /* 169 * Open parser config file, use default if none specified 170 */ 171 buff = (input_file[0]) ? input_file : DEFAULT_PARSER_LOC; 172 if ((fp = fopen(buff, "r")) == NULL) { 173 (void) fprintf(stderr, 174 gettext("parser config file (%s) not found\n"), buff); 175 return (-1); 176 } 177 178 /* 179 * start at begining of configration database 180 */ 181 cfg_rewind(cfg, CFG_SEC_ALL); 182 183 while (((buff = fgets(inbuf, (sizeof (inbuf) - 1), fp)) != NULL)) { 184 if (*buff == '#' || *buff == '%') 185 continue; 186 /* overwrite newline */ 187 buff[strlen(buff) - 1] = '\0'; 188 rc = cfg_update_parser_config(cfg, buff, CFG_PARSE_CONF); 189 if (rc < 0) { 190 (void) fprintf(stderr, 191 gettext("update parser config rc %d key %s\n"), 192 rc, buff); 193 (void) fclose(fp); 194 return (-1); 195 } 196 } 197 (void) fclose(fp); 198 return (1); 199 } 200 201 void 202 parse_text_config(CFGFILE *cfg) 203 { 204 FILE *fp; 205 char inbuf[CFG_MAX_BUF]; 206 char *buff; 207 char *key; 208 char *p; 209 int rc; 210 211 if ((fp = fopen(input_file, "r")) == NULL) { 212 (void) fprintf(stderr, 213 gettext("Unable to open text config %s\n"), 214 input_file); 215 exit(2); 216 } 217 bzero(inbuf, sizeof (inbuf)); 218 cfg_rewind(cfg, CFG_SEC_CONF); 219 while (((buff = fgets(inbuf, (sizeof (inbuf) - 1), fp)) != NULL)) { 220 if (*buff == '#') 221 continue; 222 /* overwrite newline */ 223 buff[strlen(buff) - 1] = '\0'; 224 key = strtok(buff, ":"); 225 if (!key) { 226 continue; 227 } 228 p = &buff[strlen(key)+2]; 229 while (*p && isspace(*p)) { 230 ++p; 231 } 232 if (!*p) { 233 continue; 234 } 235 rc = cfg_put_cstring(cfg, key, p, strlen(p)); 236 if (rc < 0) { 237 (void) fprintf(stderr, 238 gettext("update text config failed rc %d key %s"), 239 rc, buff); 240 return; 241 } 242 bzero(inbuf, sizeof (inbuf)); 243 } 244 (void) fclose(fp); 245 } 246 void 247 dump_status(CFGFILE *cfg) 248 { 249 cfp_t *cfp = FP_SUN_CLUSTER(cfg); 250 251 /* 252 * WARNING will robinson 253 * The following is using a non-exported internal interface 254 * to libcfg 255 * You may not use any of the following fields in MS software 256 */ 257 if (!locname) 258 exit(2); 259 if (!verbose) 260 (void) printf("%s\n", locname); 261 else { 262 #ifdef DEBUG 263 (void) printf(gettext("Configuration location: %s\n"), locname); 264 (void) printf( 265 gettext("Header info:\n\t\t\tmagic: %x\tstate: %x\n"), 266 cfp->cf_head->h_magic, cfp->cf_head->h_state); 267 (void) printf( 268 gettext("Parser section:\t\t" 269 "Start: %x\tsize: %d offset: %d\n"), 270 cfp->cf_mapped, cfp->cf_head->h_parsesize, 271 cfp->cf_head->h_parseoff); 272 (void) printf( 273 gettext("Config section:\t\t" 274 "Start: %x\tsize:%d\tacsize: %d\n"), 275 cfp->cf_head->h_cparse, cfp->cf_head->h_csize, 276 cfp->cf_head->h_acsize); 277 (void) printf("\t\t\tccopy1: %s\tccopy2: %s\n", 278 cfp->cf_head->h_ccopy1, 279 cfp->cf_head->h_ccopy2); 280 (void) printf( 281 gettext("Sequence:\t\tseq1: %d\t\tseq2: %d\n"), 282 cfp->cf_head->h_seq1, cfp->cf_head->h_seq2); 283 #endif 284 } 285 } 286 287 void 288 dump_lockstat(CFGFILE *cfg) 289 { 290 pid_t pid; 291 CFGLOCK lock; 292 char ps_str[1024]; 293 294 if (cfg_get_lock(cfg, &lock, &pid) == TRUE) { 295 (void) printf("%s %ld\n", 296 lock == CFG_RDLOCK ? 297 gettext("Read locked by process id") : 298 gettext("Write locked by process id"), 299 pid); 300 (void) sprintf(ps_str, "ps -p %ld", pid); 301 system(ps_str); 302 } else 303 (void) printf("%s\n", gettext("Not locked.")); 304 } 305 306 307 /* 308 * dump current configuration section to stdout 309 */ 310 311 void 312 print_config(CFGFILE *cfg) 313 { 314 time_t tloc = 0; 315 int set = 0; 316 char pconfig[CFG_MAX_BUF]; 317 char key[CFG_MAX_KEY]; 318 char buf[CFG_MAX_BUF]; 319 char *cp, pbuf[CFG_MAX_BUF]; 320 FILE *fp; 321 int rc; 322 int end; 323 324 (void) snprintf(pconfig, sizeof (pconfig), 325 "%s%s", altroot, DEFAULT_PARSER_LOC); 326 if ((fp = fopen(pconfig, "r")) == NULL) { 327 (void) fprintf(stderr, 328 gettext("dscfg: unable to open " 329 "parser configuration (%s): %s\n"), 330 pconfig, strerror(errno)); 331 exit(1); 332 } 333 334 (void) time(&tloc); 335 (void) printf(gettext("# Consolidated Dataservice Configuration\n")); 336 (void) printf(gettext("# Do not edit out whitespace or dashes\n")); 337 (void) printf(gettext("# File created on: %s"), ctime(&tloc)); 338 339 while (fgets(pbuf, (sizeof (pbuf) - 1), fp) != NULL) { 340 if (pbuf[0] == '#') { 341 /* comment */ 342 continue; 343 } 344 /* force a NULL terminator */ 345 pbuf[sizeof (pbuf) - 1] = '\0'; 346 347 if (pbuf[0] == '%') { 348 /* 349 * descriptive text 350 * - print it (with comment leader) and move on 351 */ 352 (void) printf("#%s", &pbuf[1]); 353 continue; 354 } 355 356 /* 357 * truncate the parser config in pbuf[] to just the tag 358 */ 359 cp = strchr(pbuf, '.'); 360 if (cp != NULL) { 361 *cp = '\0'; 362 } 363 364 set = 1; 365 /*CONSTCOND*/ 366 while (1) { 367 bzero(buf, CFG_MAX_BUF); 368 (void) snprintf(key, 369 sizeof (key), "%s.set%d", pbuf, set); 370 rc = cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF); 371 if (rc < 0) { 372 break; 373 } 374 /* trim trailing space if necessary */ 375 end = strlen(buf) - 1; 376 if (buf[end] == ' ') 377 buf[end] = '\0'; 378 379 (void) printf("%s:%s\n", pbuf, buf); 380 set++; 381 } 382 } 383 384 (void) fclose(fp); 385 } 386 387 int 388 make_new_config(const char *fileloc) 389 { 390 int fd; 391 int rc; 392 int skip; 393 394 char buf[CFG_MAX_BUF]; 395 /*CONSTCOND*/ 396 assert((sizeof (buf) % 512) == 0); 397 398 bzero(buf, CFG_MAX_BUF); 399 400 if ((fd = open(fileloc, O_RDWR | O_CREAT, 0640)) == -1) { 401 return (-1); 402 } 403 404 /* if this is a device, we may have to skip the vtoc */ 405 if ((skip = cfg_shldskip_vtoc(fd, fileloc)) == -1) { 406 (void) fprintf(stderr, 407 gettext("dscfg: unable to read vtoc on (%s)\n"), 408 fileloc); 409 return (-1); 410 } else if (skip) { 411 do { 412 rc = lseek(fd, CFG_VTOC_SKIP, SEEK_SET); 413 } while (rc == -1 && errno == EINTR); 414 415 if (rc == -1) { 416 (void) fprintf(stderr, gettext("dscfg: seek error")); 417 return (-1); 418 } 419 } 420 421 do { 422 rc = write(fd, buf, sizeof (buf)); 423 } while (rc == -1 && errno == EINTR); 424 425 close(fd); 426 427 return ((rc < 0) ? 0 : 1); 428 } 429 430 /* 431 * dscfg 432 * configure or return dataservice persistent configuration 433 * 434 * options 435 * -i initialize file for first time 436 * -l dump current configuration to stdout in ascii 437 * -a add 438 * -C node Set resource filter 439 * -p parser config specified input file 440 * -s set partition location or filename in default location 441 * -L print configuration lock status 442 * -u upgrade 443 * -r prepend bootdir to beginning of path for cfg_open 444 * no options status 445 * 446 * 447 */ 448 #ifdef lint 449 int 450 dscfg_lintmain(int argc, char *argv[]) 451 #else 452 int 453 main(int argc, char *argv[]) 454 #endif 455 { 456 CFGFILE *cfg; 457 extern char *optarg; 458 char *loc; 459 int offset = 0; 460 int rc; 461 char c; 462 int local; 463 int action_counts = 0; 464 465 bzero(input_file, sizeof (input_file)); 466 (void) setlocale(LC_ALL, ""); 467 (void) textdomain("dscfg"); 468 logical_host[0] = '\0'; 469 cmdname = argv[0]; 470 #ifdef DEBUG 471 while ((c = getopt(argc, argv, "a:C:dD:ilLp:r:s:hvn")) != EOF) { 472 #else 473 while ((c = getopt(argc, argv, "a:C:dD:ilLp:r:s:h")) != EOF) { 474 #endif 475 switch (c) { 476 case 'a': 477 aflg++; 478 strcpy(input_file, optarg); 479 mustcommit++; 480 action_counts++; 481 break; 482 case 'C': 483 Cflg++; 484 strcpy(logical_host, optarg); 485 if (logical_host && *logical_host == '-') 486 if (argc == 3) 487 action_counts++; 488 break; 489 case 'D': 490 Dflg++; 491 strcpy(device_group, optarg); 492 action_counts++; 493 break; 494 case 'i': 495 iflg++; 496 mustcommit++; 497 action_counts++; 498 break; 499 case 'l': 500 lflg++; 501 action_counts++; 502 break; 503 case 'L': 504 Lflg++; 505 action_counts++; 506 break; 507 case 'p': 508 pflg++; 509 strcpy(input_file, optarg); 510 mustcommit++; 511 break; 512 case 's': 513 sflg++; 514 strcpy(config_file, optarg); 515 action_counts++; 516 break; 517 case 'h': 518 usage(NULL); 519 exit(0); 520 /*NOTREACHED*/ 521 #ifdef DEBUG 522 case 'v': 523 verbose++; 524 action_counts++; 525 break; 526 #endif 527 #ifdef UPGRADE 528 case 'u': 529 uflg++; 530 action_counts++; 531 break; 532 #endif 533 534 case 'r': 535 rflg++; 536 strcpy(altroot, optarg); 537 break; 538 539 case 'n': 540 nflg++; 541 break; 542 543 default: 544 usage(NULL); 545 exit(1); 546 break; 547 }; 548 } 549 550 switch (action_counts) { 551 case 0: 552 if (argc > 1) { 553 if (pflg) 554 usage(gettext( 555 "-p option must be used in conjunction with -i")); 556 else 557 usage(gettext("must specify an action flag")); 558 exit(1); 559 } 560 break; 561 case 1: 562 break; 563 case 2: 564 if (lflg && sflg) 565 break; 566 else { 567 usage(gettext("too many action flags")); 568 exit(1); 569 break; 570 } 571 default: 572 usage(gettext("too many action flags")); 573 exit(1); 574 break; 575 } 576 577 if (argc == 1 || (argc == 2 && verbose) || (argc == 3 && (rflg|Cflg))) 578 noflags++; 579 580 if (Dflg) { 581 /* 582 * Determine if the value specified is a device group 583 * that is active on this node 584 */ 585 char *other_node; 586 if ((cfg_issuncluster() > 0) && (strlen(device_group) > 0)) { 587 local = cfg_dgname_islocal(device_group, &other_node); 588 if (local == 0) 589 (void) fprintf(stderr, gettext( 590 "Device group %s active on %s\n"), 591 device_group, other_node); 592 else if (local == 1) 593 (void) fprintf(stderr, gettext( 594 "Device group %s active on this node\n"), 595 device_group); 596 else 597 (void) fprintf(stderr, gettext( 598 "Device group %s not found\n"), device_group); 599 return (local); 600 } else { 601 (void) fprintf(stderr, gettext( 602 "dscfg -D is only allowed in " 603 "Sun Cluster OE\n")); 604 return (0); 605 } 606 } 607 608 if (sflg && !lflg) { 609 /* 610 * Only allow setting location on a non-sun cluster system 611 * if the cluster reference file is already present. 612 */ 613 struct stat dscfg_stat = {0}; 614 if (cfg_issuncluster() <= 0) { 615 if (stat(CFG_CLUSTER_LOCATION, &dscfg_stat) != 0) { 616 if (dscfg_stat.st_blocks == 0) { 617 (void) fprintf(stderr, gettext( 618 "dscfg -s is only allowed in " 619 "Sun Cluster OE\n")); 620 exit(1); 621 } 622 } 623 } 624 625 spcs_log("dscfg", NULL, gettext("dscfg -s %s"), config_file); 626 locname = cfg_location(config_file, CFG_LOC_SET_CLUSTER, 627 rflg ? altroot : NULL); 628 if (locname == NULL) { 629 (void) fprintf(stderr, gettext("dscfg: %s\n"), 630 cfg_error(NULL)); 631 exit(1); 632 } else 633 exit(0); 634 635 } else if (sflg && lflg) { 636 /* s used with l for temporarily peeking at a dscfg database */ 637 loc = config_file; 638 } else { 639 locname = cfg_location(NULL, 640 Cflg ? CFG_LOC_GET_CLUSTER : CFG_LOC_GET_LOCAL, 641 rflg ? altroot : NULL); 642 if (Cflg && (locname == NULL)) { 643 (void) fprintf(stderr, gettext( 644 "dscfg: cluster config not set: %s\n"), 645 cfg_error(NULL)); 646 return (1); 647 } 648 loc = rflg ? locname : NULL; 649 } 650 651 /* 652 * the following hack forces the configuration file to initialize 653 */ 654 if (iflg && !pflg) { 655 int fild; 656 int c; 657 char buf[CFG_MAX_BUF] = {0}; 658 cfp_t *cfp; 659 660 if (!nflg) { 661 (void) printf( 662 gettext("WARNING: This option will erase your " 663 "Availability Suite configuration\n")); 664 (void) printf( 665 gettext("Do you want to continue? (Y/N) [N] ")); 666 667 c = getchar(); 668 switch (c) { 669 case 'y': 670 case 'Y': break; 671 case 'n': 672 case 'N': 673 case '\n': 674 (void) fprintf(stderr, gettext( 675 "dscfg: configuration not initialized\n")); 676 exit(1); 677 default: 678 (void) fprintf(stderr, gettext( 679 "dscfg: %d is not a valid response\n"), c); 680 exit(1); 681 } 682 } 683 684 spcs_log("dscfg", NULL, gettext("dscfg -i")); 685 686 if ((cfg = cfg_open(loc)) == NULL) { 687 /* this is not a good config, or non-existent so.. */ 688 if (!make_new_config(locname)) { 689 (void) fprintf(stderr, gettext("dscfg: %s\n"), 690 cfg_error(NULL)); 691 exit(1); 692 } 693 if ((cfg = cfg_open(loc)) == NULL) { 694 (void) fprintf(stderr, gettext("dscfg: %s\n"), 695 cfg_error(NULL)); 696 exit(1); 697 } 698 } 699 700 /* 701 * Set cluster node if specified 702 */ 703 if (Cflg) 704 cfg_resource(cfg, logical_host); 705 706 if (cfg_is_cfg(cfg) != 1) { 707 if (!make_new_config(locname)) { 708 (void) fprintf(stderr, gettext("dscfg: unable " 709 " to create new config \n")); 710 exit(1); 711 } 712 } 713 714 if (!cfg_lock(cfg, CFG_WRLOCK)) { 715 (void) fprintf(stderr, gettext("dscfg: %s\n"), 716 cfg_error(NULL)); 717 exit(1); 718 } 719 720 cfp = FP_SUN_CLUSTER(cfg); 721 if ((fild = cfp->cf_fd) == 0) { 722 (void) fprintf(stderr, 723 gettext("dscfg: failure to access %s " 724 "configuration database: %s\n"), 725 (Cflg) ? gettext("cluster") : gettext("local"), 726 cfg_error(NULL)); 727 exit(1); 728 } 729 730 if (cfg_shldskip_vtoc(fild, locname) > 0) 731 offset += CFG_VTOC_SKIP; 732 733 lseek(fild, offset, SEEK_SET); 734 write(fild, buf, sizeof (buf)); 735 cfg_invalidate_hsizes(fild, locname); 736 737 cfg_close(cfg); 738 exit(0); 739 } 740 741 if (pflg && !iflg) { 742 usage(gettext("-p option must be used in conjunction with -i")); 743 exit(1); 744 745 } 746 747 if (uflg) { 748 char cmd[CFG_MAX_BUF]; 749 if (rflg) 750 (void) snprintf(cmd, sizeof (cmd), 751 "%s/usr/sbin/dscfg -r %s -l >" 752 " %s/var/tmp/.dscfg.bak", altroot, 753 altroot, altroot); 754 else 755 (void) snprintf(cmd, sizeof (cmd), 756 "/usr/sbin/dscfg -l >" 757 " /var/tmp/.dscfg.bak"); 758 759 if (system(cmd) != 0) { 760 (void) fprintf(stderr, 761 "dscfg: unable to create backup\n"); 762 exit(1); 763 } 764 765 if ((cfg = cfg_open(loc)) == NULL) { 766 (void) fprintf(stderr, gettext("dscfg: %s\n"), 767 cfg_error(NULL)); 768 exit(2); 769 } 770 771 if (!cfg_lock(cfg, CFG_UPGRADE)) { 772 (void) fprintf(stderr, 773 gettext("dscfg: upgrade failed\n")); 774 cfg_close(cfg); 775 exit(1); 776 } 777 778 cfg_close(cfg); 779 exit(0); 780 } 781 782 if ((cfg = cfg_open(loc)) == NULL) { 783 (void) fprintf(stderr, gettext("dscfg: %s\n"), cfg_error(NULL)); 784 exit(2); 785 } 786 787 /* 788 * Set cluster node if specified 789 */ 790 if (Cflg) 791 cfg_resource(cfg, logical_host); 792 793 if ((!pflg) && (!noflags)) { 794 if (cfg_is_cfg(cfg) != 1) { 795 (void) fprintf(stderr, 796 gettext("dscfg: %s\n"), cfg_error(NULL)); 797 cfg_close(cfg); 798 exit(1); 799 } 800 } 801 802 if (Lflg) { 803 dump_lockstat(cfg); 804 cfg_close(cfg); 805 exit(0); 806 } 807 808 if (noflags) { 809 dump_status(cfg); 810 cfg_close(cfg); 811 exit(0); 812 } 813 814 if (!cfg_lock(cfg, mustcommit? CFG_WRLOCK : CFG_RDLOCK)) { 815 (void) fprintf(stderr, gettext("cfg_lock: lock failed\n")); 816 cfg_close(cfg); 817 exit(1); 818 } 819 820 if (lflg) { 821 print_config(cfg); 822 cfg_close(cfg); 823 exit(0); 824 } 825 826 /* 827 * initialize configuration 828 */ 829 if (iflg) { 830 spcs_log("dscfg", NULL, gettext("dscfg -i -p %s"), input_file); 831 832 if (!pflg) { 833 (void) fprintf(stderr, 834 gettext("dscfg: cannot init without " 835 "parser configuration file\n")); 836 cfg_close(cfg); 837 exit(1); 838 } else if (parse_parse_config(cfg) < 0) { 839 (void) fprintf(stderr, gettext("dscfg: cannot load " 840 "parser configuration file\n")); 841 cfg_close(cfg); 842 exit(1); 843 } 844 } 845 846 /* 847 * read asci config file and write 848 */ 849 if (aflg) { 850 spcs_log("dscfg", NULL, gettext("dscfg -a %s"), input_file); 851 parse_text_config(cfg); 852 } 853 854 if (mustcommit) { 855 rc = cfg_commit(cfg); 856 if (rc < 0) { 857 int sev = 0; 858 (void) fprintf(stderr, gettext("dscfg: %s\n"), 859 cfg_error(&sev)); 860 if (sev == CFG_EFATAL) { 861 cfg_close(cfg); 862 exit(2); 863 } 864 } 865 } 866 867 cfg_close(cfg); 868 return (0); 869 } 870 871 static int 872 check_cluster() 873 { 874 static int is_cluster = -1; 875 int rc; 876 877 if (is_cluster != -1) 878 return (is_cluster); 879 rc = cfg_iscluster(); 880 if (rc > 0) { 881 is_cluster = IS_CLUSTER; 882 return (is_cluster); 883 } else if (rc == 0) { 884 is_cluster = IS_NOT_CLUSTER; 885 return (is_cluster); 886 } else { 887 (void) fprintf(stderr, 888 gettext("dscfg: unable to determin environment\n")); 889 /*NOTREACHED*/ 890 } 891 892 /* gcc */ 893 return (is_cluster); 894 }