Home | History | Annotate | Download | only in dscfg
      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 }
    895