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 }