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
usage(char * errmsg)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
parse_parse_config(CFGFILE * cfg)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
parse_text_config(CFGFILE * cfg)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
dump_status(CFGFILE * cfg)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
dump_lockstat(CFGFILE * cfg)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
print_config(CFGFILE * cfg)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
make_new_config(const char * fileloc)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
dscfg_lintmain(int argc,char * argv[])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