--- old/usr/src/cmd/avs/dsw/iiadm.c	Fri Jul 27 15:35:32 2018
+++ /dev/null	Fri Jul 27 15:07:21 2018
@@ -1,4377 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <sys/types.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <values.h>
-#include <locale.h>
-#include <langinfo.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/wait.h>
-#include <strings.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <math.h>
-#include <sys/param.h>
-#include <sys/mnttab.h>
-#include <nsctl.h>
-#include <netdb.h>
-#include <search.h>
-
-#include <sys/nsctl/cfg.h>
-#include <sys/nsctl/nsc_hash.h>
-
-#include <sys/unistat/spcs_s.h>
-#include <sys/unistat/spcs_s_u.h>
-#include <sys/unistat/spcs_errors.h>
-#include <sys/nsctl/dsw.h>
-#include <sys/nsctl/dsw_dev.h>		/* for bit map header format */
-
-#include <sys/nskernd.h>
-
-typedef struct mstcount_s {
-	int count;
-} mstcount_t;
-typedef struct shdvol_s {
-	char master[ DSW_NAMELEN ];
-} shdvol_t;
-typedef struct grptag_s {
-	char ctag[ DSW_NAMELEN ];
-} grptag_t;
-hash_node_t **volhash = NULL;
-
-#define	DSW_TEXT_DOMAIN	"II"
-
-#include <dlfcn.h>
-#define	RDC_LIB "/usr/lib/librdc.so.1"
-static int (*self_check)(char *);
-
-/*
- * Support for the special cluster tag "local" to be used with -C in a
- * cluster for local volumes.
- */
-#define	II_LOCAL_TAG	"local"
-
-#define	II_NOT_CLUSTER	1
-#define	II_CLUSTER	2
-#define	II_CLUSTER_LCL	3
-
-static char *cfg_cluster_tag = NULL;
-static CFGFILE *cfg = NULL;
-
-void sigterm(int sig);
-
-#define	SD_BIT_CLR(bmap, bit)		(bmap &= ~(1 << bit))
-#define	SD_BIT_ISSET(bmap, bit)		((bmap & (1 << bit)) != 0)
-
-#define	MAX_LINE_SIZE 256	/* maximum characters per line in config file */
-#define	MAX_GROUPS 1024		/* maximum number of groups to support */
-#define	MAX_CLUSTERS 1024	/* maximum number of resource groups */
-
-unsigned long	bm_size;		/* size in bytes of bitmap */
-unsigned long	bm_actual;		/* original number of bits in bitmap */
-int	debug = 0;
-
-int	dsw_fd;
-
-#define	LD_II		0x00000001
-#define	LD_DSVOLS	0x00000002
-#define	LD_SVOLS	0x00000004
-#define	LD_SHADOWS	0x00000008
-
-static int reload_vols = 0;
-static int config_locked = 0;
-static int last_lock;
-
-/*
- * names for do_copy() flags.
- */
-
-enum	copy_update {Copy = 0, Update};
-enum	copy_direction {ToShadow = 0, ToMaster};
-enum	copy_wait {WaitForStart = 0, WaitForEnd};
-
-char	*cmdnam;
-
-unsigned char	*allocate_bitmap(char *);
-void		usage(char *);
-void		enable(char *, char *, char *, char *);
-int		disable(char *);
-void		bitmap_op(char *, int, int, int, int);
-void		print_status(dsw_config_t *, int);
-int		abort_copy(char *);
-int		reset(char *);
-int		overflow(char *);
-void		iiversion(void);
-int		wait_for_copy(char *);
-int		export(char *);
-void		list_volumes(void);
-void		dsw_error(char *, spcs_s_info_t *);
-void		InitEnv();
-static void	check_dg_is_local(char *dgname);
-static int	check_resource_group(char *volume);
-static int	check_diskgroup(char *path, char *result);
-static int	check_cluster();
-static void	unload_ii_vols();
-static void	load_ii_vols(CFGFILE *);
-static int	perform_autosv();
-static int	is_exported(char *);
-static void	conform_name(char **);
-static void	do_attach(dsw_config_t *);
-static int	ii_lock(CFGFILE *, int);
-static void	verify_groupname(char *grp, int testDash);
-
-void	dsw_list_clusters(char *);
-void	dsw_enable(int, char **);
-void	dsw_disable(int, char **);
-void	dsw_copy_to_shadow(int, char **);
-void	dsw_update_shadow(int, char **);
-void	dsw_copy_to_master(int, char **);
-void	dsw_update_master(int, char **);
-void	dsw_abort_copy(int, char **);
-void	dsw_display_status(int, char **);
-void	dsw_display_bitmap(int, char **);
-void	dsw_reset(int, char **);
-void	dsw_overflow(int, char **);
-void	dsw_version(int, char **);
-void	dsw_wait(int, char **);
-void	dsw_list_volumes(int, char **);
-void	dsw_list_group_volumes();
-void	dsw_export(int, char **);
-void	dsw_import(int, char **);
-void	dsw_join(int, char **);
-void	dsw_attach(int, char **);
-void	dsw_detach(int, char **);
-void	dsw_params(int, char **);
-void	dsw_olist(int, char **);
-void	dsw_ostat(int, char **);
-void	dsw_move_2_group(int, char **);
-void	dsw_list_groups();
-void	check_iishadow(char *);
-
-extern char *optarg;
-extern int optind, opterr, optopt;
-
-int	Aflg;
-int	Cflg;
-int	CLflg;
-int	Dflg;
-int	Eflg;
-int	Iflg;
-int	Jflg;
-int	Lflg;
-int	Oflg;
-int	Pflg;
-int	Qflg;
-int	Rflg;
-int	aflg;
-int	bflg;
-int	cflg;
-int	dflg;
-int	eflg;
-int	fflg;
-int	gflg;
-int	gLflg;
-int	hflg;
-int	iflg;
-int	lflg;
-int	mflg;
-int	nflg;
-int	pflg;
-int	uflg;
-int	vflg;
-int	wflg;
-
-int	errflg;
-#ifdef DEBUG
-const char single_opts[] =
-	"a:b:c:d:e:f:g:hilmnpu:vw:A:C:D:E:I:J:LO:PQ:R:";
-#else
-/* no b or f flags */
-const char single_opts[] = "a:c:d:e:g:hilmnpu:vw:A:C:D:E:I:J:LO:PQ:R:";
-#endif
-const char group_opts[] = "ac:de:ilmnpu:wA:C:DELPR";
-const char *opt_list = single_opts;
-
-char	buf[CFG_MAX_BUF];
-char	key[CFG_MAX_KEY];
-char	last_overflow[DSW_NAMELEN];
-int	setnumber;
-char	*group_name;
-char	**group_volumes;
-enum copy_direction direction;
-char	*param_delay, *param_unit;
-char	*overflow_file;
-
-#ifdef lint
-int
-iiadm_lintmain(int argc, char *argv[])
-#else
-int
-main(int argc, char *argv[])
-#endif
-{
-	int c;
-	int actions = 0;
-	int ac;
-	char *av[1024];
-
-	InitEnv();
-
-	(void) memset(av, 0, sizeof (av));
-	cmdnam = argv[0];
-	while ((c = getopt(argc, argv, opt_list)) != EOF)
-		switch (c) {
-		case 'c':
-			cflg++;
-			actions++;
-			if (strcmp(optarg, "m") == 0) {
-				av[0] = "copy_to_master";
-				direction = ToMaster;
-			} else if (strcmp(optarg, "s") == 0) {
-				av[0] = "copy_to_shadow";
-				direction = ToShadow;
-			} else {
-				errflg ++;
-				usage(gettext(
-					"must specify m or s with -c"));
-			}
-			ac = 2;
-			break;
-		case 'd':
-			dflg++;
-			actions++;
-			av[0] = "disable";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'e':
-			eflg++;
-			actions++;
-			av[0] = "enable";
-			if (strcmp(optarg, "ind") == 0)
-				av[4] = "independent";
-			else if (strcmp(optarg, "dep") == 0)
-				av[4] = "dependent";
-			else {
-				errflg ++;
-				usage(gettext(
-					"must specify ind or dep with -e"));
-			}
-			ac = 1;
-			break;
-		case 'g':
-			gflg++;
-			opt_list = group_opts;
-			group_name = optarg;
-			if (group_name && *group_name == '-') {
-				gLflg = (strcmp("-L", group_name) == 0);
-				if (gLflg)
-					actions++;
-			}
-			verify_groupname(group_name, !gLflg);
-			break;
-		case 'h':
-			hflg++;
-			actions++;
-			break;
-		case 'u':
-			uflg++;
-			actions++;
-			if (strcmp(optarg, "m") == 0) {
-				av[0] = "update_master";
-				direction = ToMaster;
-			} else if (strcmp(optarg, "s") == 0) {
-				av[0] = "update_shadow";
-				direction = ToShadow;
-			} else {
-				errflg ++;
-				usage(gettext(
-					"must specify m or s with -u"));
-			}
-			ac = 2;
-			break;
-		case 'i':
-			iflg++;
-			actions++;
-			av[0] = "display_status";
-			break;
-		case 'l':
-			lflg++;
-			actions++;
-			av[0] = "list_config";
-			ac = 1;
-			break;
-		case 'm':
-			mflg++;
-			actions++;
-			av[0] = "move_to_group";
-			ac = 1;
-			break;
-		case 'n':
-			nflg++;
-			break;
-		case 'p':
-			pflg++;
-			break;
-		case 'b':
-			bflg++;
-			actions++;
-			av[0] = "display_bitmap";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'a':
-			aflg++;
-			actions++;
-			av[0] = "abort_copy";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'v':
-			vflg++;
-			actions++;
-			av[1] = "version";
-			ac = 1;
-			break;
-		case 'w':
-			wflg++;
-			actions++;
-			av[0] = "wait";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'A':
-			Aflg++;
-			actions++;
-			av[0] = "attach";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'C':
-			Cflg++;
-			cfg_cluster_tag = optarg;
-			if (cfg_cluster_tag && *cfg_cluster_tag == '-') {
-				CLflg = (strcmp("-L", cfg_cluster_tag) == 0);
-				if (CLflg)
-					actions++;
-			}
-			break;
-		case 'D':
-			Dflg++;
-			actions++;
-			av[0] = "detach";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'O':
-			Oflg++;
-			actions++;
-			av[0] = "overflow";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'R':
-			Rflg++;
-			actions++;
-			av[0] = "reset";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'E':
-			Eflg++;
-			actions++;
-			av[0] = "export";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'I':
-			Iflg++;
-			actions++;
-			av[0] = "import";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'J':
-			Jflg++;
-			actions++;
-			av[0] = "join";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case 'P':
-			Pflg++;
-			actions++;
-			av[0] = "parameter";
-			ac = 1;
-			break;
-		case 'L':
-			Lflg++;
-			actions++;
-			/* If -g group -L, force error */
-			if (group_name) actions++;
-			av[0] = "LIST";
-			ac = 1;
-			break;
-		case 'Q':
-			Qflg++;
-			actions++;
-			av[0] = "query";
-			av[1] = optarg;
-			ac = 2;
-			break;
-		case '?':
-			errflg++;
-			break;
-		}
-	if (hflg) {
-		usage(NULL);
-		exit(0);
-		}
-
-	if (errflg)
-		usage(gettext("unrecognized argument"));
-	switch (actions) {
-		case 0:
-			if (argc > 1)
-				usage(gettext("must specify an action flag"));
-
-			/* default behavior is to list configuration */
-			lflg++; av[0] = "list_config"; ac = 1;
-			break;
-		case 1:
-			break;
-		default:
-			usage(gettext("too many action flags"));
-			break;
-	}
-
-	if (gflg && (Iflg || Jflg || Oflg || Qflg))
-		usage(gettext("can't use a group with this option"));
-	if (!gflg && (mflg))
-		usage(gettext("must use a group with this option"));
-
-	/*
-	 * Open configuration file.
-	 */
-	if ((cfg = cfg_open(NULL)) == NULL) {
-		perror("unable to access configuration");
-		exit(2);
-	}
-
-	/*
-	 * Set write locking (CFG_WRLOCK) for:
-	 *	iiadm -e (enable)
-	 * 	iiadm -d (disable)
-	 *	iiadm -A (attach overflow)
-	 *	iiadm -D (detach overflow)
-	 *	iiadm -g grp -m volume (move volume into group)
-	 *	iiadm -E (export shadow [needs to update dsvol section])
-	 *	iiadm -I (import shadow [ditto])
-	 *	iiadm -J (join shadow [ditto])
-	 * read locking (CFG_RDLOCK) for all other commands
-	 */
-	last_lock = (eflg || dflg || mflg || Aflg || Dflg || Eflg || Iflg ||
-	    Jflg)? CFG_WRLOCK : CFG_RDLOCK;
-	if (!cfg_lock(cfg, last_lock)) {
-		perror("unable to lock configuration");
-		exit(2);
-	}
-	config_locked = 1;
-
-	/*
-	 * If we are in a cluster, set or derive a valid disk group
-	 */
-	switch (check_cluster()) {
-	case II_CLUSTER:
-		/*
-		 * If in a Sun Cluster, can't Import an II shadow
-		 * Must be done as -C local
-		 */
-		if (Iflg)
-			dsw_error(gettext(
-				"-I (import) only allowed as -C local"), NULL);
-		/*FALLTHRU*/
-	case II_CLUSTER_LCL:
-		/*
-		 * If a cluster tag was specified or derived, set it
-		 */
-		if (CLflg) {
-			dsw_list_clusters(argv[optind]);
-			cfg_close(cfg);
-			exit(0);
-		} else {
-			cfg_resource(cfg, cfg_cluster_tag);
-		}
-		break;
-	case II_NOT_CLUSTER:
-		if (cfg_cluster_tag != NULL)
-			dsw_error(gettext(
-			    "-C is valid only in a Sun Cluster"), NULL);
-		break;
-	default:
-		dsw_error(gettext(
-		    "Unexpected return from check_cluster()"), NULL);
-	}
-
-	/* preload the ii config */
-	load_ii_vols(cfg);
-	reload_vols |= LD_II;
-
-	if (eflg) {
-		if (argc - optind != 3)
-			usage(gettext("must specify 3 volumes with -e"));
-		av[1] = argv[optind++];
-		av[2] = argv[optind++];
-		av[3] = argv[optind++];
-		ac = 5;
-		dsw_enable(ac, av);
-	} else if (dflg) {
-		dsw_disable(ac, av);
-	} else if (uflg) {
-		if (argv[optind] == NULL && group_name == NULL)
-			usage(gettext("must specify volume with -u"));
-		for (c = 1; argv[optind] != NULL; optind++)
-			av[c++] = argv[optind];
-		av[c] = NULL;
-
-		if (direction == ToMaster)
-			dsw_update_master(ac, av);
-		else
-			dsw_update_shadow(ac, av);
-	} else if (iflg) {
-		if (argv[optind]) {
-			av[1] = argv[optind];
-			ac = 2;
-		} else
-			ac = 1;
-		dsw_display_status(ac, av);
-	} else if (bflg) {
-		dsw_display_bitmap(ac, av);
-	} else if (cflg) {
-		if (argv[optind] == NULL && group_name == NULL)
-			usage(gettext("must specify volume with -c"));
-		for (c = 1; argv[optind] != NULL; optind++)
-			av[c++] = argv[optind];
-		av[c] = NULL;
-
-		if (direction == ToMaster)
-			dsw_copy_to_master(ac, av);
-		else
-			dsw_copy_to_shadow(ac, av);
-	} else if (aflg) {
-		dsw_abort_copy(ac, av);
-	} else if (Eflg) {
-		dsw_export(ac, av);
-	} else if (Iflg) {
-		if (argc - optind != 1)
-			usage(gettext("must specify 2 volumes with -I"));
-		av[2] = argv[optind++];
-		ac = 3;
-		dsw_import(ac, av);
-	} else if (Aflg) {
-		if (group_name) {
-			if (argc - optind != 0)
-				usage(gettext("must specify overflow volume " \
-				"when using groups with -A"));
-			ac = 2;
-		} else {
-			if (argc - optind != 1)
-				usage(gettext("specify 2 volumes with -A"));
-			ac = 3;
-			av[2] = argv[optind++];
-		}
-		dsw_attach(ac, av);
-	} else if (Dflg) {
-		dsw_detach(ac, av);
-	} else if (Jflg) {
-		if (argc - optind != 1)
-			usage(gettext("must specify 2 volumes with -J"));
-		av[2] = argv[optind++];
-		ac = 3;
-		dsw_join(ac, av);
-	} else if (Pflg) {
-		if (argc - optind == ((group_name) ? 0 : 1)) {
-			av[1] = argv[optind++];
-			ac = (group_name) ? 0 : 2;
-		} else if (argc - optind == ((group_name) ? 2 : 3)) {
-			av[1] = argv[optind++];
-			av[2] = argv[optind++];
-			av[3] = argv[optind++];
-			ac = (group_name) ? 2 : 4;
-		} else
-			usage(gettext(
-				"must specify delay, unit and shadow with -P"));
-		dsw_params(ac, av);
-	} else if (Oflg) {
-		dsw_overflow(ac, av);
-	} else if (Rflg) {
-		dsw_reset(ac, av);
-	} else if (vflg) {
-		dsw_version(ac, av);
-	} else if (wflg) {
-		dsw_wait(ac, av);
-	} else if (lflg) {
-		if ((gflg) && (!group_name))
-			dsw_list_group_volumes();
-		else
-			dsw_list_volumes(ac, av);
-	} else if (Lflg) {
-		dsw_olist(ac, av);
-	} else if (gLflg) {
-		dsw_list_groups();
-	} else if (Qflg) {
-		dsw_ostat(ac, av);
-	} else if (mflg) {
-		if (argc - optind < 1)
-			usage(gettext("must specify one or more volumes"));
-		for (c = 1; argv[optind] != NULL; optind++)
-			av[c++] = argv[optind];
-		av[c] = NULL;
-		dsw_move_2_group(ac, av);
-	}
-	if (cfg)
-		cfg_close(cfg);
-
-	exit(0);
-	return (0);
-}
-
-static int
-ii_lock(CFGFILE *cfg, int locktype)
-{
-	last_lock = locktype;
-	return (cfg_lock(cfg, locktype));
-}
-
-static int
-do_ioctl(int fd, int cmd, void *arg)
-{
-	int unlocked = 0;
-	int rc;
-	int save_errno;
-
-	if (config_locked) {
-		switch (cmd) {
-		case DSWIOC_ENABLE:
-		case DSWIOC_RESUME:
-		case DSWIOC_SUSPEND:
-		case DSWIOC_COPY:
-		case DSWIOC_BITMAP:
-		case DSWIOC_DISABLE:
-		case DSWIOC_SHUTDOWN:
-		case DSWIOC_ABORT:
-		case DSWIOC_RESET:
-		case DSWIOC_OFFLINE:
-		case DSWIOC_WAIT:
-		case DSWIOC_ACOPY:
-		case DSWIOC_EXPORT:
-		case DSWIOC_IMPORT:
-		case DSWIOC_JOIN:
-		case DSWIOC_COPYP:
-		case DSWIOC_OATTACH:
-		case DSWIOC_ODETACH:
-		case DSWIOC_SBITSSET:
-		case DSWIOC_CBITSSET:
-		case DSWIOC_SEGMENT:
-		case DSWIOC_MOVEGRP:
-		case DSWIOC_CHANGETAG:
-			cfg_unlock(cfg);
-			unlocked = 1;
-			break;
-
-		case DSWIOC_STAT:
-		case DSWIOC_VERSION:
-		case DSWIOC_LIST:
-		case DSWIOC_OCREAT:
-		case DSWIOC_OLIST:
-		case DSWIOC_OSTAT:
-		case DSWIOC_OSTAT2:
-		case DSWIOC_LISTLEN:
-		case DSWIOC_OLISTLEN:
-		case DSWIOC_CLIST:
-		case DSWIOC_GLIST:
-			break;
-
-		default:
-			(void) fprintf(stderr,
-			    "cfg locking needs to be set for %08x\n", cmd);
-			exit(1);
-			break;
-		}
-	}
-	if (unlocked) {
-		/* unload vol hashes */
-		if (reload_vols & LD_II)
-			unload_ii_vols();
-		if (reload_vols & LD_SHADOWS)
-			cfg_unload_shadows();
-		if (reload_vols & LD_DSVOLS)
-			cfg_unload_dsvols();
-		if (reload_vols & LD_SVOLS)
-			cfg_unload_svols();
-	}
-	rc = ioctl(fd, cmd, arg);
-	save_errno = errno;
-	if (config_locked && unlocked) {
-		(void) cfg_lock(cfg, last_lock);
-	}
-	if (unlocked) {
-		/* reload vol hashes */
-		if (reload_vols & LD_SVOLS)
-			(void) cfg_load_svols(cfg);
-		if (reload_vols & LD_DSVOLS)
-			(void) cfg_load_dsvols(cfg);
-		if (reload_vols & LD_SHADOWS)
-			(void) cfg_load_shadows(cfg);
-		if (reload_vols & LD_II)
-			load_ii_vols(cfg);
-	}
-
-	errno = save_errno;
-	return (rc);
-}
-
-static int
-get_dsw_config(int setno, dsw_config_t *parms)
-{
-	char buf[CFG_MAX_BUF];
-	char key[CFG_MAX_KEY];
-
-	bzero(parms, sizeof (dsw_config_t));
-	(void) snprintf(key, sizeof (key), "ii.set%d.master", setno);
-	if (cfg_get_cstring(cfg, key, parms->master_vol, DSW_NAMELEN) < 0)
-		return (-1);
-
-	(void) snprintf(key, sizeof (key), "ii.set%d.shadow", setno);
-	(void) cfg_get_cstring(cfg, key, parms->shadow_vol, DSW_NAMELEN);
-
-	(void) snprintf(key, sizeof (key), "ii.set%d.bitmap", setno);
-	(void) cfg_get_cstring(cfg, key, parms->bitmap_vol, DSW_NAMELEN);
-
-	(void) snprintf(key, sizeof (key), "ii.set%d.mode", setno);
-	(void) cfg_get_cstring(cfg, key, buf, sizeof (buf));
-	if (strcmp(buf, "I") == 0)
-		parms->flag |= DSW_GOLDEN;
-
-	(void) snprintf(key, sizeof (key), "ii.set%d.overflow", setno);
-	(void) cfg_get_cstring(cfg, key, last_overflow, DSW_NAMELEN);
-
-	(void) snprintf(key, sizeof (key), "ii.set%d.group", setno);
-	(void) cfg_get_cstring(cfg, key, parms->group_name, DSW_NAMELEN);
-
-	(void) snprintf(key, sizeof (key), "ii.set%d.cnode", setno);
-	(void) cfg_get_cstring(cfg, key, parms->cluster_tag, DSW_NAMELEN);
-	return (0);
-}
-
-static int
-find_next_cf_line(char *volume, int next)
-{
-	dsw_config_t cf_line;
-
-	for (setnumber = next; get_dsw_config(setnumber, &cf_line) == 0;
-	    setnumber++) {
-		if (strncmp(volume, cf_line.master_vol, DSW_NAMELEN) == 0 ||
-		    strncmp(volume, cf_line.shadow_vol, DSW_NAMELEN) == 0 ||
-		    strncmp(volume, cf_line.bitmap_vol, DSW_NAMELEN) == 0)
-			return (1);
-	}
-	return (0);
-}
-int
-find_any_cf_line(char *volume)
-{
-	return (find_next_cf_line(volume, 1));
-}
-
-static int
-find_next_shadow_line(char *volume, int next)
-{
-	dsw_config_t cf_line;
-
-	for (setnumber = next; get_dsw_config(setnumber, &cf_line) == 0;
-	    setnumber++) {
-		if (strncmp(volume, cf_line.shadow_vol, DSW_NAMELEN) == 0)
-			return (1);
-	}
-	return (0);
-}
-int
-find_shadow_line(char *volume)
-{
-	return (find_next_shadow_line(volume, 1));
-}
-
-/*
- * this function is designed to be called once, subsequent calls won't
- * free memory allocated by earlier invocations.
- */
-char *
-get_overflow_list()
-{
-	dsw_aioctl_t *acopy_args;
-	int rc, num;
-
-	num = do_ioctl(dsw_fd, DSWIOC_OLISTLEN, NULL);
-	if (num < 0)
-		dsw_error(gettext("Can't get overflow list length"), NULL);
-
-	acopy_args = malloc(sizeof (dsw_aioctl_t) + num * DSW_NAMELEN);
-	if (acopy_args == NULL)
-		dsw_error(gettext("Can't get memory for list enquiry"), NULL);
-
-	acopy_args->count = num;
-	acopy_args->flags = 0;
-	acopy_args->status = spcs_s_ucreate();
-
-	rc = do_ioctl(dsw_fd, DSWIOC_OLIST, acopy_args);
-	if (rc == -1)
-		dsw_error(gettext("Overflow list access failure"),
-		    &acopy_args->status);
-	else
-		acopy_args->shadow_vol[DSW_NAMELEN*acopy_args->count] = NULL;
-
-	return (acopy_args->shadow_vol);
-}
-
-/*
- * this function is designed to be called once, subsequent calls won't
- * free memory allocated by earlier invocations.
- */
-
-int
-find_group_members(char *group)
-{
-	int nmembers = 0;
-	int vector_len = 0;
-
-	group_volumes = NULL;
-	for (setnumber = 1; /*CSTYLED*/; setnumber++) {
-		(void) snprintf(key, sizeof (key), "ii.set%d.group", setnumber);
-		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
-			break;
-
-		if (strcmp(group, buf))
-			continue;
-
-		(void) snprintf(key, sizeof (key), "ii.set%d.shadow",
-		    setnumber);
-		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
-			break;
-
-		if (nmembers >= vector_len) {
-			vector_len += 10;
-			group_volumes = realloc(group_volumes, (1+vector_len) *
-			    sizeof (char *));
-		}
-		group_volumes[nmembers] = strdup(buf);
-		nmembers++;
-	}
-	if (group_volumes)
-		group_volumes[nmembers] = NULL;	/* terminate list */
-	return (nmembers);
-}
-
-static int
-find_next_matching_cf_line(
-	char *volume, dsw_config_t *conf, dsw_ioctl_t *io, int next)
-{
-	dsw_config_t config;
-
-	if (!find_next_cf_line(volume, next)) {
-		return (0);
-	}
-
-	if (conf == NULL)
-		conf = &config;
-	(void) get_dsw_config(setnumber, conf);
-	if (io) {
-		(void) strlcpy(io->shadow_vol, conf->shadow_vol, DSW_NAMELEN);
-	}
-	return (1);
-}
-
-int
-find_matching_cf_line(char *volume, dsw_config_t *conf, dsw_ioctl_t *io)
-{
-	return (find_next_matching_cf_line(volume, conf, io, 1));
-}
-
-int
-find_shadow_config(char *volume, dsw_config_t *conf, dsw_ioctl_t *io)
-{
-	dsw_config_t *c, cf;
-
-	if (io) {
-		bzero(io, sizeof (dsw_ioctl_t));
-	}
-	c = conf ? conf : &cf;
-	setnumber = 1;
-	/* perform action for each line of the stored config file */
-	for ((void) snprintf(key, sizeof (key), "ii.set%d.shadow", setnumber);
-	    cfg_get_cstring(cfg, key, c->shadow_vol, DSW_NAMELEN) >= 0;
-	    (void) snprintf(key, sizeof (key), "ii.set%d.shadow",
-	    ++setnumber)) {
-		if (strncmp(volume, c->shadow_vol, DSW_NAMELEN) == 0) {
-			(void) get_dsw_config(setnumber, c);
-
-			if (check_resource_group(c->bitmap_vol)) {
-				setnumber = 0;
-				continue;
-			}
-
-			switch (check_cluster()) {
-			case II_CLUSTER:
-				if ((cfg_cluster_tag) &&
-				    (strcmp(cfg_cluster_tag, c->cluster_tag)))
-					continue;
-				break;
-			case II_CLUSTER_LCL:
-				if (strlen(c->cluster_tag))
-					continue;
-				break;
-			}
-
-			if (io) {
-				(void) strlcpy(io->shadow_vol, c->shadow_vol,
-				    DSW_NAMELEN);
-			}
-			return (1);
-		}
-	}
-	return (0);
-}
-
-void
-add_cfg_entry(dsw_config_t *parms)
-{
-	/* insert the well-known fields first */
-	(void) snprintf(buf, sizeof (buf), "%s %s %s %s",
-	    parms->master_vol, parms->shadow_vol, parms->bitmap_vol,
-	    (parms->flag & DSW_GOLDEN) ? "I" : "D");
-
-	if (cfg_put_cstring(cfg, "ii", buf, strlen(buf)) >=  0) {
-		/* if we have a group name, add it */
-		if (group_name) {
-			if (find_any_cf_line(parms->shadow_vol)) {
-				(void) sprintf(buf, "ii.set%d.group",
-				    setnumber);
-				if (cfg_put_cstring(cfg, buf,
-				    group_name, strlen(group_name)) < 0)
-					perror("cfg_put_cstring");
-			}
-			else
-				perror("cfg_location");
-		}
-
-		/* commit the record */
-		(void) cfg_commit(cfg);
-	}
-	else
-		perror("cfg_put_string");
-}
-
-void
-remove_iiset(int setno, char *shadow, int shd_exp)
-{
-	mstcount_t *mdata;
-	shdvol_t *sdata;
-	char sn[CFG_MAX_BUF];
-
-	if (perform_autosv()) {
-		if (volhash) {
-			unload_ii_vols();
-		}
-		load_ii_vols(cfg);
-		if (cfg_load_dsvols(cfg) < 0 || cfg_load_svols(cfg) < 0) {
-			dsw_error(gettext("Unable to parse config file"), NULL);
-		}
-
-		sdata = (shdvol_t *)nsc_lookup(volhash, shadow);
-		if (sdata) {
-			/*
-			 * Handle the normal cases of disabling a set that is
-			 * not an imported shadow volume
-			 */
-			if (strcmp(sdata->master, II_IMPORTED_SHADOW)) {
-				/*
-				 * Handle multiple-shadows of single master
-				 */
-				mdata = (mstcount_t *)
-				    nsc_lookup(volhash, sdata->master);
-				if ((mdata) && (mdata->count == 1)) {
-					if (cfg_vol_disable(cfg, sdata->master,
-					    cfg_cluster_tag, "ii") < 0)
-						dsw_error(gettext(
-						    "SV disable of master "
-						    "failed"),
-						    NULL);
-				}
-			}
-
-			/*
-			 * Handle disk group name of different shadow
-			 */
-			if (shd_exp) {
-				/*
-				 * If shadow is exported, then do nothing
-				 */
-				/*EMPTY*/;
-			} else if (cfg_cluster_tag &&
-			    strcmp(cfg_cluster_tag, "") &&
-			    cfg_dgname(shadow, sn, sizeof (sn)) &&
-			    strlen(sn) &&
-			    strcmp(sn, cfg_cluster_tag)) {
-					/* reload disk group volumes */
-					cfg_resource(cfg, sn);
-					cfg_unload_dsvols();
-					cfg_unload_svols();
-					(void) cfg_load_dsvols(cfg);
-					(void) cfg_load_svols(cfg);
-					if (cfg_vol_disable(cfg, shadow, sn,
-					    "ii") < 0) {
-						dsw_error(gettext(
-						    "SV disable of shadow "
-						    "failed"),
-						    NULL);
-					}
-					cfg_resource(cfg, cfg_cluster_tag);
-			} else {
-				if (cfg_vol_disable(cfg, shadow,
-				    cfg_cluster_tag, "ii") < 0)
-					dsw_error(gettext(
-					    "SV disable of shadow failed"),
-					    NULL);
-			}
-		}
-		cfg_unload_svols();
-		cfg_unload_dsvols();
-		unload_ii_vols();
-		reload_vols &= ~(LD_SVOLS | LD_DSVOLS | LD_II);
-	}
-
-	(void) sprintf(key, "ii.set%d", setno);
-	if (cfg_put_cstring(cfg, key, NULL, 0) < 0) {
-		perror("cfg_put_cstring");
-	}
-	(void) cfg_commit(cfg);
-}
-
-/*
- * determine if we are running in a Sun Cluster Environment
- */
-int
-check_cluster()
-{
-	static int is_cluster = -1;
-	int rc;
-#ifdef DEBUG
-	char *cdebug = getenv("II_SET_CLUSTER");
-#endif
-
-	/*
-	 * If this routine was previously called, just return results
-	 */
-	if (is_cluster != -1)
-		return (is_cluster);
-
-	/*
-	 * See if Sun Cluster was installed on this node
-	 */
-#ifdef DEBUG
-	if (cdebug) rc = atoi(cdebug);
-	else
-#endif
-	rc = cfg_iscluster();
-	if (rc > 0) {
-		/*
-		 * Determine if user specified -C local
-		 */
-		if ((cfg_cluster_tag == NULL) ||
-		    (strcmp(cfg_cluster_tag, II_LOCAL_TAG))) {
-			/*
-			 * We're in a Sun Cluster, and no "-C local"
-			 */
-			is_cluster = II_CLUSTER;
-		} else {
-			/*
-			 * We're in a Sun Cluster, but "-C local" was specified
-			 */
-			is_cluster = II_CLUSTER_LCL;
-			cfg_cluster_tag = "";
-		}
-		return (is_cluster);
-	} else if (rc == 0) {
-		/*
-		 * Not in a Sun Cluster
-		 */
-		is_cluster = II_NOT_CLUSTER;
-		return (is_cluster);
-	} else {
-		dsw_error(gettext("unable to ascertain environment"), NULL);
-		/*NOTREACHED*/
-	}
-
-	/* gcc */
-	return (is_cluster);
-}
-
-/*
- * Determine if we need to set a cfg_resource based on this volume
- */
-static int
-check_resource_group(char *volume)
-{
-	char diskgroup[CFG_MAX_BUF];
-
-	/*
-	 * If we are in a cluster, attempt to derive a new resource group
-	 */
-
-#ifdef DEBUG
-	if (getenv("II_SET_CLUSTER") || (check_cluster() == II_CLUSTER)) {
-#else
-	if (check_cluster() == II_CLUSTER) {
-#endif
-		if (check_diskgroup(volume, diskgroup)) {
-			if (cfg_cluster_tag == NULL) {
-				cfg_cluster_tag = strdup(diskgroup);
-				if (cfg_cluster_tag == NULL)
-					dsw_error(gettext(
-					"Memory allocation failure"), NULL);
-				cfg_resource(cfg, cfg_cluster_tag);
-				return (1);
-			} else {
-				/*
-				 * Check dgname and cluster tag from -C are
-				 * the same.
-				 */
-				if (strcmp(diskgroup, cfg_cluster_tag) != 0) {
-					char error_buffer[128];
-					(void) snprintf(error_buffer,
-					    sizeof (error_buffer),
-					    gettext("-C (%s) does not match "
-					    "disk group name (%s) for %s"),
-					    cfg_cluster_tag, diskgroup, volume);
-					spcs_log("ii", NULL, error_buffer);
-					dsw_error(error_buffer, NULL);
-				}
-			}
-		} else if (cfg_cluster_tag == NULL)
-			dsw_error(gettext(
-			    "Point-in-Time Copy volumes, that are not "
-			    "in a device group which has been "
-			    "registered with SunCluster, "
-			    "require usage of \"-C\""), NULL);
-	}
-	return (0);
-}
-
-static void
-check_dg_is_local(char *dgname)
-{
-	char error_buffer[128];
-	char *othernode;
-	int rc;
-
-	/*
-	 * check where this disk service is mastered
-	 */
-	rc = cfg_dgname_islocal(dgname, &othernode);
-	if (rc < 0) {
-		(void) snprintf(error_buffer, sizeof (error_buffer),
-		    gettext("Unable to find disk service:%s"), dgname);
-		dsw_error(error_buffer, NULL);
-	} else if (rc == 0) {
-		(void) snprintf(error_buffer, sizeof (error_buffer),
-		    gettext("disk service, %s, is active on node \"%s\"\n"
-		    "Please re-issue the command on that node"), dgname,
-		    othernode);
-		dsw_error(error_buffer, NULL);
-	}
-}
-
-/*
- * Carry out cluster based checks for a specified volume, or just
- * global options.
- */
-static int
-check_diskgroup(char *path, char *result)
-{
-	char dgname[CFG_MAX_BUF];
-	char error_buffer[128];
-
-#ifdef DEBUG
-	char *override = getenv("II_CLUSTER_TAG");
-	if (override) {
-		(void) strcpy(result, override);
-		return (1);
-	}
-#endif
-	/*
-	 * Check on path name, a returned NULL dgname is valid
-	 */
-	if (cfg_dgname(path, dgname, sizeof (dgname)) == NULL) {
-		(void) snprintf(error_buffer, sizeof (error_buffer), gettext(
-		    "unable to determine disk group name for %s"), path);
-		dsw_error(error_buffer, NULL);
-	}
-	if (strcmp(dgname, "") == 0)
-		return (0);
-
-	/*
-	 * See if disk group is local to this node
-	 */
-	check_dg_is_local(dgname);
-
-	/*
-	 * Copy dgname into result
-	 */
-	(void) strcpy(result, dgname);
-	return (1);
-}
-
-/*
- * sigterm (): traps specified signal , usually termination one
- */
-void
-sigterm(int sig)
-{
-	spcs_log("ii", NULL, gettext("%s received signal %d"), cmdnam, sig);
-	exit(1);
-}
-
-/*
- * sigchild; reap child and collect status.
- */
-
-volatile pid_t	dead_child;
-int	dead_stat;
-
-/*ARGSUSED*/
-void
-sigchild(int sig)
-{
-	dead_child = wait(&dead_stat);
-}
-
-/*
- * InitEnv(): initializes environment
- */
-void
-InitEnv()
-{
-	(void) setlocale(LC_ALL, "");
-	(void) textdomain(DSW_TEXT_DOMAIN);
-
-#ifndef DEBUG
-	(void) sigset(SIGHUP, sigterm);
-	(void) sigset(SIGINT, sigterm);
-	(void) sigset(SIGQUIT, sigterm);
-	(void) sigset(SIGILL, sigterm);
-	(void) sigset(SIGEMT, sigterm);
-	(void) sigset(SIGABRT, sigterm);
-	(void) sigset(SIGFPE, sigterm);
-	(void) sigset(SIGBUS, sigterm);
-	(void) sigset(SIGSEGV, sigterm);
-	(void) sigset(SIGTERM, sigterm);
-	(void) sigset(SIGPWR, sigterm);
-	(void) sigset(SIGSTOP, sigterm);
-	(void) sigset(SIGTSTP, sigterm);
-#endif
-
-	dsw_fd = open(DSWDEV, O_RDONLY);
-	if (dsw_fd < 0) {
-		perror(DSWDEV);
-		exit(1);
-	}
-
-	(void) setsid();
-}
-
-/*
- * print an error message, followed by decoded errno then exit.
- */
-void
-dsw_error(char *str, spcs_s_info_t *status)
-{
-	char *sp;
-
-	(void) fprintf(stderr, "%s: %s:\n", cmdnam, str);
-	if (status == NULL) {
-		/* deflect ESRCH */
-		if (ESRCH == errno) {
-			sp = "Set/volume not found";
-		} else {
-			sp = strerror(errno);
-		}
-		(void) fprintf(stderr, "%s\n", sp ? sp : "");
-	} else {
-		spcs_s_report(*status, stderr);
-		spcs_s_ufree(status);
-	}
-	if (cfg)
-		cfg_close(cfg);
-	exit(2);
-}
-
-
-#undef size
-
-void
-free_bitmap(unsigned char *bitmap)
-{
-	free(bitmap);
-}
-
-
-int
-get_bitmap(master_volume, shd_bitmap, copy_bitmap, size)
-	char		*master_volume;
-	unsigned char	*shd_bitmap;
-	unsigned char	*copy_bitmap;
-	unsigned long	size;
-{
-	dsw_bitmap_t parms;
-
-	(void) strlcpy(parms.shadow_vol, master_volume, DSW_NAMELEN);
-	parms.shd_bitmap = shd_bitmap;
-	parms.shd_size = size;
-	parms.copy_bitmap = copy_bitmap;
-	parms.copy_size = size;
-
-	return (do_ioctl(dsw_fd, DSWIOC_BITMAP, &parms));
-}
-
-unsigned char *
-allocate_bitmap(char *shadow_volume)
-{
-	unsigned char	*shd_bitmap;
-	unsigned char	*copy_bitmap;
-	unsigned char	*p;
-	unsigned char	*q;
-	int		i;
-	dsw_stat_t	args;
-	int		stat_flags;
-
-	(void) strlcpy(args.shadow_vol, shadow_volume, DSW_NAMELEN);
-
-	args.status = spcs_s_ucreate();
-	if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1)
-		dsw_error(gettext("Stat failed"), &args.status);
-
-	stat_flags = args.stat;
-	if (stat_flags & DSW_BMPOFFLINE)
-		return (NULL);
-
-	bm_size = args.size;
-	bm_size = (bm_size + DSW_SIZE-1) / DSW_SIZE;
-	bm_actual = bm_size;
-	bm_size = (bm_size + DSW_BITS-1) / DSW_BITS;
-	spcs_s_ufree(&args.status);
-
-	p = shd_bitmap = (unsigned char *) malloc(bm_size);
-	if (!shd_bitmap) {
-		perror(gettext("malloc bitmap"));
-		return (NULL);
-	}
-
-	q = copy_bitmap = (unsigned char *) malloc(bm_size);
-	if (!copy_bitmap) {
-		perror(gettext("malloc bitmap"));
-		free(shd_bitmap);
-		return (NULL);
-	}
-
-	(void) memset(shd_bitmap, 0, bm_size);
-	(void) memset(copy_bitmap, 0, bm_size);
-
-	if (get_bitmap(shadow_volume, shd_bitmap, copy_bitmap, bm_size) < 0) {
-		free(copy_bitmap);
-		free(shd_bitmap);
-		return (NULL);
-	}
-
-	/*
-	 * "or" the copy and shadow bitmaps together to return a composite
-	 * bitmap that contains the total set of differences between the
-	 * volumes.
-	 */
-	for (i = bm_size; i-- > 0; /*CSTYLED*/)
-		*p++ |= *q++;
-
-	free(copy_bitmap);
-
-	return (shd_bitmap);
-}
-
-/*
- * print usage message and exit.
- */
-void
-usage(char *why)
-{
-	if (why) {
-		(void) fprintf(stderr, "%s: %s\n", cmdnam, why);
-
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\nBrief summary:"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-e {ind|dep} master_vol shadow_vol "
-		    "bitmap_vol"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-[cu {s|m}] volume_set"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-i all"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-[adDEilPRw] volume_set"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-g group_name [options]"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-C cluster_tag [options]"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-[hilLv]"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-[IJ] volume_set bitmap"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-A overflow_vol volume_set"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-[OQ] overflow_vol"));
-		(void) fprintf(stderr, "%s\n",
-		    gettext("\t-P {delay} {units} volume_set"));
-
-		/* assume we came here due to a user mistake */
-		exit(1);
-		/* NOTREACHED */
-	} else {
-
-		(void) fprintf(stdout, "%s\n",
-		    gettext("Point-in-Time Copy Administrator CLI options"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("Usage summary:"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-e ind m s b\tenable independent master shadow "
-		    "bitmap"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-e dep m s b\tenable dependent master shadow "
-		    "bitmap"));
-		if (check_cluster() == II_CLUSTER)
-			(void) fprintf(stdout, "%s\n",
-			    gettext("\t-ne ind m s b\tenable exportable master "
-			    "shadow bitmap"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-d v\t\tdisable volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-u s v\t\tupdate shadow volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-u m v\t\tupdate master volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-c s v\t\tcopy to shadow volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-c m v\t\tcopy to master volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-a v\t\tabort copy volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-w v\t\twait volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-i v\t\tdisplay volume status"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-i all\t\tdisplay all volume status"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-l\t\tlist all volumes"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-R v\t\treset volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-A o v\t\tattach overflow to volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-D v\t\tdetach overflow from volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-L\t\tlist all overflow volumes"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-O o\t\tinitialize overflow"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-Q o\t\tquery status of overflow"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-E v\t\texport shadow volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-I v b\t\timport volume bitmap"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-J v b\t\tjoin volume bitmap"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-P d u v\tset copy delay/units for volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-P v\t\tget copy delay/units for volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-C tag\t\tcluster resource tag"));
-#ifdef DEBUG
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-b v\t\tdisplay bitmap volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-f f\t\tuse private configuration file"));
-#endif
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-v\t\tprint software versions"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-n\t\tperform action without question"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-p [-c|-u] {m|s}"
-		    "enable PID locking on copy or update"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-p -w v\t\tdisable PID locking"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-h\t\tiiadm usage summary"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\nUsage summary for options that support "
-		    "grouping (-g g):"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -e ind m s b group enable independent "
-		    "master shadow bitmap"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -e dep m s b group enable dependent "
-		    "master shadow bitmap"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -d\t\tdisable group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -u s\tupdate shadow for all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -u m\tupdate master for all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -c s\tcopy to shadow for all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -c m\tcopy to master for all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -a\t\tabort copy for all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -w\t\twait for all volumes in group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -i\t\tdisplay status of all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -l\t\tlist all volumes in group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g -L\t\tlist all groups"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -m v v\tmove one or more volumes into "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g \"\" -m v\tremove volume from group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -R\t\treset all volumes in group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -A o\tattach overflow to all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -D\t\tdetach overflow from all volumes in "
-		    "group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -E\t\texport shadow volume for all "
-		    "volumes in group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -P d u\tset copy delay/units for all "
-		    "volumes in group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\t-g g -P\t\tget copy delay/units for all "
-		    "volumes in group"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\nLegend summary:"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tind\t\tindependent volume set"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tdep\t\tdependent volume set"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tall\t\tall configured volumes"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tm\t\tmaster volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\ts\t\tshadow volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tv\t\tshadow volume (reference name)"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\to\t\toverflow volume"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tb\t\tbitmap volume"));
-#ifdef DEBUG
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tf\t\tconfiguration file name"));
-#endif
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\td\t\tdelay tick interval"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tu\t\tunit size"));
-		(void) fprintf(stdout, "%s\n",
-		    gettext("\tg\t\tgroup name"));
-
-		/* assume we came here because user request help text */
-		exit(0);
-		/* NOTREACHED */
-	}
-
-}
-
-static  char    yeschr[MAX_LINE_SIZE + 2];
-static  char    nochr[MAX_LINE_SIZE + 2];
-
-static int
-yes(void)
-{
-	int	i, b;
-	char	ans[MAX_LINE_SIZE + 1];
-
-	for (i = 0; /*CSTYLED*/; i++) {
-		b = getchar();
-		if (b == '\n' || b == '\0' || b == EOF) {
-			if (i < MAX_LINE_SIZE)
-				ans[i] = 0;
-			break;
-		}
-		if (i < MAX_LINE_SIZE)
-			ans[i] = b;
-	}
-	if (i >= MAX_LINE_SIZE) {
-		i = MAX_LINE_SIZE;
-		ans[MAX_LINE_SIZE] = 0;
-	}
-	if ((i == 0) || (strncmp(yeschr, ans, i))) {
-		if (strncmp(nochr, ans, i) == 0)
-			return (0);
-		else if (strncmp(yeschr, ans, i) == 0)
-			return (1);
-		else {
-			(void) fprintf(stderr, "%s %s/%s\n",
-			    gettext("You have to respond with"),
-			    yeschr, nochr);
-			return (2);
-		}
-	}
-	return (1);
-}
-
-static int
-convert_int(char *str)
-{
-	int result, rc;
-	char *buf;
-
-	buf = (char *)calloc(strlen(str) + 256, sizeof (char));
-	rc = sscanf(str, "%d%s", &result, buf);
-
-	if (rc != 1) {
-		(void) sprintf(buf, gettext("'%s' is not a valid number"), str);
-		/* dsw_error calls exit which frees 'buf' */
-		errno = EINVAL;
-		dsw_error(buf, NULL);
-	}
-	free(buf);
-
-	return (result);
-}
-
-void
-check_action(char *will_happen)
-{
-	int answer;
-
-	if (nflg || !isatty(fileno(stdin)))
-		return;
-	(void) strncpy(yeschr, nl_langinfo(YESSTR), MAX_LINE_SIZE + 1);
-	(void) strncpy(nochr, nl_langinfo(NOSTR), MAX_LINE_SIZE + 1);
-
-	/*CONSTCOND*/
-	while (1) {
-		(void) printf("%s %s/%s ", will_happen, yeschr, nochr);
-		answer = yes();
-		if (answer == 1 || answer == 0)
-			break;
-	}
-	if (answer == 1)
-		return;
-	exit(1);
-}
-
-enum	child_event {Status, CopyStart};
-
-/*
- * Wait for child process to get to some state, where some state may be:
- *
- *	Status		Set up the shadow enough so that it responds
- *			to status requests.
- *	CopyStart	Start copy/update operations.
- */
-
-int
-child_wait(pid_t child, enum child_event event, char *volume)
-{
-	dsw_stat_t	args;
-	int rc;
-
-	(void) strlcpy(args.shadow_vol, volume, DSW_NAMELEN);
-
-	for (; dead_child != child; (void) sleep(1)) {
-
-		/* poll shadow group with a status ioctl() */
-		args.status = spcs_s_ucreate();
-		errno = 0;
-		rc = do_ioctl(dsw_fd, DSWIOC_STAT, &args);
-
-		spcs_s_ufree(&args.status);
-
-		if (event == Status) {
-			/* keep polling while we fail with DSW_ENOTFOUND */
-			if (rc != -1 || errno != DSW_ENOTFOUND)
-				return (0);
-		} else {
-			/* event == CopyStart */
-			if (rc == -1) {
-				return (1);	/* something wrong */
-			}
-			if (args.stat & DSW_COPYINGP)
-				return (0);	/* copying underway */
-		}
-	}
-	/* child died */
-	if (WIFEXITED(dead_stat))
-		return (WEXITSTATUS(dead_stat));
-	else
-		return (1);
-}
-
-int
-mounted(char *t)
-{
-	int	rdsk;
-	int	i;
-	FILE	*mntfp;
-	struct mnttab mntref;
-	struct mnttab mntent;
-	char	target[DSW_NAMELEN];
-	char	*s;
-
-	rdsk = i = 0;
-	for (s = target; i < DSW_NAMELEN && (*s = *t++); i++) {
-		if (*s == 'r' && rdsk == 0)
-			rdsk = 1;
-		else
-			s++;
-	}
-	*s = '\0';
-
-	mntref.mnt_special = target;
-	mntref.mnt_mountp = NULL;
-	mntref.mnt_fstype = NULL;
-	mntref.mnt_mntopts = NULL;
-	mntref.mnt_time = NULL;
-
-	if ((mntfp = fopen("/etc/mnttab", "r")) == NULL) {
-		dsw_error(gettext("Can not check volume against mount table"),
-		    NULL);
-	}
-	if (getmntany(mntfp, &mntent, &mntref) != -1) {
-		/* found something before EOF */
-		(void) fclose(mntfp);
-		return (1);
-	}
-	(void) fclose(mntfp);
-	return (0);
-}
-
-void
-enable(char *master_volume, char *shadow_volume,
-	char *bitmap_volume, char *copy_type)
-{
-	dsw_config_t parms;
-	dsw_ioctl_t temp;
-	char	*p;
-	int	rc;
-	pid_t	child;
-	spcs_s_info_t *sp_info;
-	struct stat mstat, sstat, bstat;
-	char	mst_dg[DSW_NAMELEN] = {0};
-	char	shd_dg[DSW_NAMELEN] = {0};
-	char	bmp_dg[DSW_NAMELEN] = {0};
-	int	mvol_enabled;
-	char	*altname;
-	grptag_t *gdata;
-
-	bzero(&parms, sizeof (dsw_config_t));
-
-	if (strcmp(copy_type, "independent") == 0 ||
-	    strcmp(copy_type, gettext("independent")) == 0)
-		parms.flag = DSW_GOLDEN;
-	else if (strcmp(copy_type, "dependent") == 0 ||
-	    strcmp(copy_type, gettext("dependent")) == 0)
-		parms.flag = 0;
-	else
-		dsw_error(gettext("don't understand shadow type"), NULL);
-
-	/* validate volume names */
-	if (perform_autosv()) {
-		if (cfg_load_svols(cfg) < 0 || cfg_load_dsvols(cfg) < 0 ||
-		    cfg_load_shadows(cfg) < 0) {
-			dsw_error(gettext("Unable to parse config file"), NULL);
-		}
-		load_ii_vols(cfg);
-		reload_vols = LD_SVOLS | LD_DSVOLS | LD_SHADOWS | LD_II;
-
-		/* see if it's been used before under a different name */
-		conform_name(&master_volume);
-		conform_name(&shadow_volume);
-		rc = cfg_get_canonical_name(cfg, bitmap_volume, &altname);
-		if (rc < 0) {
-			dsw_error(gettext("Unable to parse config file"), NULL);
-		}
-		if (rc) {
-			errno = EBUSY;
-			dsw_error(gettext("Bitmap in use"), NULL);
-		}
-	}
-
-	/*
-	 * If not local, determine disk group names for volumes in II set
-	 */
-	switch (check_cluster()) {
-	case II_CLUSTER:
-		/*
-		 * Check if none or all volumes are in a disk group
-		 */
-		rc = 0;
-		if (check_diskgroup(master_volume, mst_dg)) rc++;
-		if (check_diskgroup(shadow_volume, shd_dg)) rc++;
-		if (check_diskgroup(bitmap_volume, bmp_dg)) rc++;
-		if ((rc != 0) && (rc != 3))
-			dsw_error(gettext(
-			    "Not all Point-in-Time Copy volumes are "
-			    "in a disk group"), NULL);
-
-		/*
-		 * If volumes are not in a disk group, but are in a
-		 * cluster, then "-C <tag>", must be set
-		 */
-		if (rc == 0 && cfg_cluster_tag == NULL)
-			dsw_error(gettext(
-			    "Point-in-Time Copy volumes, that are not "
-			    "in a device group which has been "
-			    "registered with SunCluster, "
-			    "require usage of \"-C\""), NULL);
-
-		/*
-		 * the same disk group
-		 * If -n, plus mst_dg==bmp_dg, then allow E/I/J in SunCluster
-		 */
-		if ((strcmp(mst_dg, bmp_dg)) ||
-		    (strcmp(mst_dg, shd_dg) && (!nflg)))
-			dsw_error(gettext(
-			    "Volumes are not in same disk group"), NULL);
-
-		/*
-		 * Can never enable the same shadow twice, regardless of
-		 * exportable shadow device group movement
-		 */
-		if (find_shadow_line(shadow_volume))
-			dsw_error(gettext(
-			    "Shadow volume is already configured"), NULL);
-
-		/*
-		 * Groups cannot span multiple clusters
-		 */
-		if (group_name && perform_autosv()) {
-			gdata = (grptag_t *)nsc_lookup(volhash, group_name);
-			if (gdata &&
-			    strncmp(gdata->ctag, mst_dg, DSW_NAMELEN) != 0) {
-				errno = EINVAL;
-				dsw_error(gettext("Group contains sets not "
-				    "in the same cluster resource"), NULL);
-			}
-		}
-
-		/*
-		 * Check cluster tag and bitmap disk group
-		 * set latter if different
-		 */
-		if (check_resource_group(bitmap_volume)) {
-			/*
-			 * Unload and reload in the event cluster tag has
-			 * changed
-			 */
-			if (perform_autosv()) {
-				unload_ii_vols();
-				cfg_unload_shadows();
-				cfg_unload_dsvols();
-				cfg_unload_svols();
-				if (cfg_load_svols(cfg) < 0 ||
-				    cfg_load_dsvols(cfg) < 0 ||
-				    cfg_load_shadows(cfg) < 0) {
-					dsw_error(gettext(
-					    "Unable to parse config "
-					    "file"), NULL);
-				}
-				load_ii_vols(cfg);
-			}
-		}
-		/*
-		 * Copy cluster name into config
-		 */
-		(void) strncpy(parms.cluster_tag, cfg_cluster_tag, DSW_NAMELEN);
-		break;
-
-	case II_CLUSTER_LCL:
-		/* ensure that the -C local won't interfere with the set */
-		if (group_name && perform_autosv()) {
-			gdata = (grptag_t *)nsc_lookup(volhash, group_name);
-			if (gdata) {
-				if (strlen(gdata->ctag) != 0) {
-					errno = EINVAL;
-					dsw_error(gettext("Unable to put set "
-					    "into -C local and specified "
-					    "group"), NULL);
-				}
-			}
-		}
-		break;
-	}
-
-	/*
-	 * If we've got a group name, add it into the config
-	 */
-	if (group_name) {
-		(void) strncpy(parms.group_name, group_name, DSW_NAMELEN);
-	}
-
-	/*
-	 * Determine accessability of volumes
-	 */
-	if (stat(master_volume, &mstat) != 0)
-		dsw_error(gettext(
-		    "Unable to access master volume"), NULL);
-	if (!S_ISCHR(mstat.st_mode))
-		dsw_error(gettext(
-		    "Master volume is not a character device"), NULL);
-	/* check the shadow_vol hasn't be used as SNDR secondary vol */
-	check_iishadow(shadow_volume);
-	if (stat(shadow_volume, &sstat) != 0)
-		dsw_error(gettext(
-		    "Unable to access shadow volume"), NULL);
-	if (!S_ISCHR(sstat.st_mode))
-		dsw_error(gettext(
-		    "Shadow volume is not a character device"), NULL);
-	if (mounted(shadow_volume)) {
-		errno = EBUSY;
-		dsw_error(gettext(
-		    "Shadow volume is mounted, unmount it first"), NULL);
-	}
-	if (mstat.st_rdev == sstat.st_rdev) {
-		errno = EINVAL;
-		dsw_error(gettext(
-		    "Master and shadow are the same device"), NULL);
-	}
-	if (stat(bitmap_volume, &bstat) != 0) {
-		dsw_error(gettext("Unable to access bitmap"), NULL);
-	}
-	if (!S_ISCHR(bstat.st_mode))
-		dsw_error(gettext(
-		    "Bitmap volume is not a character device"), NULL);
-	if (S_ISCHR(bstat.st_mode)) {
-		if (mstat.st_rdev == bstat.st_rdev) {
-			errno = EINVAL;
-			dsw_error(gettext(
-			    "Master and bitmap are the same device"), NULL);
-		} else if (sstat.st_rdev == bstat.st_rdev) {
-			errno = EINVAL;
-			dsw_error(gettext(
-			    "Shadow and bitmap are the same device"), NULL);
-		}
-	}
-
-	(void) strncpy(parms.master_vol, master_volume, DSW_NAMELEN);
-	(void) strncpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
-	(void) strncpy(parms.bitmap_vol, bitmap_volume, DSW_NAMELEN);
-	errno = 0;
-	parms.status = spcs_s_ucreate();
-
-	/*
-	 * Check that none of the member volumes forms part of another
-	 * InstantImage group.
-	 *
-	 * -- this check has been removed; it is done in the kernel instead
-	 * -- PJW
-	 */
-
-	/*
-	 * Check against overflow volumes
-	 */
-	for (p = get_overflow_list(); *p != NULL; p += DSW_NAMELEN) {
-		if (strncmp(master_volume, p, DSW_NAMELEN) == 0)
-			dsw_error(gettext(
-			    "Master volume is already an overflow volume"),
-			    NULL);
-		else if (strncmp(shadow_volume, p, DSW_NAMELEN) == 0)
-			dsw_error(gettext(
-			    "Shadow volume is already an overflow volume"),
-			    NULL);
-		else if (strncmp(bitmap_volume, p, DSW_NAMELEN) == 0)
-			dsw_error(gettext(
-			    "Bitmap volume is already an overflow volume"),
-			    NULL);
-	}
-
-	/*
-	 * Make sure that the shadow volume is not already configured
-	 */
-	if (find_shadow_config(shadow_volume, NULL, &temp))
-		dsw_error(gettext(
-		    "Shadow volume is already configured"), NULL);
-	if (perform_autosv()) {
-		/*
-		 * parse the dsvol entries to see if we need to place
-		 * the master or shadow under SV control
-		 */
-		if (nsc_lookup(volhash, master_volume) == NULL) {
-			if (cfg_vol_enable(cfg, master_volume, cfg_cluster_tag,
-			    "ii") < 0) {
-				dsw_error(
-				    gettext("Cannot enable master volume"),
-				    NULL);
-			}
-			mvol_enabled = 1;
-		} else {
-			mvol_enabled = 0;
-		}
-		if (nsc_lookup(volhash, shadow_volume) == NULL) {
-			if (nflg) {
-				cfg_resource(cfg, shd_dg);
-				rc = cfg_vol_enable(cfg, shadow_volume,
-				    shd_dg, "ii");
-				cfg_resource(cfg, cfg_cluster_tag);
-			} else {
-				rc = cfg_vol_enable(cfg, shadow_volume,
-				    cfg_cluster_tag, "ii");
-			}
-			if (rc < 0) {
-				if (mvol_enabled) {
-					if (cfg_vol_disable(cfg,
-					    master_volume, cfg_cluster_tag,
-					    "ii") < 0)
-						dsw_error(gettext(
-						    "SV disable of master "
-						    "failed"),
-						    NULL);
-				}
-				dsw_error(
-				    gettext("Cannot enable shadow volume"),
-				    NULL);
-			}
-		}
-		unload_ii_vols();
-		cfg_unload_shadows();
-		cfg_unload_dsvols();
-		cfg_unload_svols();
-		reload_vols = 0;
-	}
-
-	add_cfg_entry(&parms);
-	cfg_unlock(cfg);
-	config_locked = 0;
-
-	(void) sigset(SIGCHLD, sigchild);
-	switch (child = fork()) {
-
-	case (pid_t)-1:
-		dsw_error(gettext("Unable to fork"), NULL);
-		break;
-
-	case 0:
-		rc = do_ioctl(dsw_fd, DSWIOC_ENABLE, &parms);
-		if (rc == -1 && errno != DSW_EABORTED && errno != DSW_EIO) {
-			/*
-			 * Failed to enable shadow group, log problem and remove
-			 * the shadow group from the config file.
-			 */
-			spcs_log("ii", &parms.status,
-			    gettext("Enable failed %s %s %s (%s)"),
-			    master_volume, shadow_volume, bitmap_volume,
-			    parms.flag & DSW_GOLDEN ?
-			    "independent" : "dependent");
-
-			if (!ii_lock(cfg, CFG_WRLOCK) ||
-			    !find_shadow_config(shadow_volume, NULL, &temp)) {
-				dsw_error(gettext(
-				    "Enable failed, can't tidy up cfg"),
-				    &parms.status);
-			}
-			config_locked = 1;
-			remove_iiset(setnumber, shadow_volume, 0);
-			dsw_error(gettext("Enable failed"), &parms.status);
-		}
-
-		if (rc == -1)
-			sp_info = &parms.status;
-		else
-			sp_info = NULL;
-		spcs_log("ii", sp_info, gettext("Enabled %s %s %s (%s)"),
-		    master_volume, shadow_volume, bitmap_volume,
-		    parms.flag & DSW_GOLDEN ? "independent" : "dependent");
-		spcs_s_ufree(&parms.status);
-		break;
-
-	default:
-		exit(child_wait(child, Status, shadow_volume));
-		break;
-	}
-}
-
-int
-reset(char *volume)
-{
-	dsw_ioctl_t args;
-	dsw_config_t parms;
-	int	rc;
-	int	wait_loc;
-	pid_t	child = (pid_t)0;
-	enum copy_wait wait_action;
-	spcs_s_info_t *stat;
-	dsw_stat_t prev_stat;
-	int stat_flags;
-	static int unlocked = 0;
-	int	do_enable = 0;
-	char	key[CFG_MAX_KEY];
-	char	optval[CFG_MAX_BUF];
-	unsigned int flags;
-
-	wait_action = WaitForStart;
-
-	if (unlocked && !ii_lock(cfg, CFG_RDLOCK)) {
-		dsw_error(gettext("Unable to set locking on the configuration"),
-		    NULL);
-	}
-	config_locked = 1;
-	if (!find_shadow_config(volume, &parms, &args))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-
-	cfg_unlock(cfg);
-	config_locked = 0;
-	unlocked = 1;
-
-	spcs_log("ii", NULL, gettext("Start reset %s"), volume);
-	(void) strlcpy(prev_stat.shadow_vol, volume, DSW_NAMELEN);
-	prev_stat.status = spcs_s_ucreate();
-	if (do_ioctl(dsw_fd, DSWIOC_STAT, &prev_stat) == -1) {
-		/* set is suspended, so we do the enable processing instead */
-		do_enable = 1;
-
-		/* first check to see whether the set was offline */
-		(void) snprintf(key, CFG_MAX_KEY, "ii.set%d.options",
-		    setnumber);
-		if (!ii_lock(cfg, CFG_RDLOCK)) {
-			dsw_error(gettext("Unable to set locking on the "
-			    "configuration"), NULL);
-		}
-		config_locked = 1;
-		unlocked = 0;
-		if (cfg_get_single_option(cfg, CFG_SEC_CONF, key,
-		    NSKERN_II_BMP_OPTION, optval, CFG_MAX_BUF) < 0) {
-			dsw_error(gettext("unable to read config file"), NULL);
-		}
-		cfg_unlock(cfg);
-		config_locked = 0;
-		unlocked = 1;
-		(void) sscanf(optval, "%x", &flags);
-		if ((flags & DSW_OFFLINE) == 0) {
-			/* set wasn't offline - don't reset */
-			dsw_error(gettext("Set not offline, will not reset"),
-			    NULL);
-		}
-		parms.status = spcs_s_ucreate();
-		stat = &parms.status;
-		stat_flags = DSW_BMPOFFLINE;
-	} else {
-		args.status = spcs_s_ucreate();
-		stat = &args.status;
-		stat_flags = prev_stat.stat;
-	}
-	spcs_s_ufree(&prev_stat.status);
-
-	if (wait_action == WaitForStart)
-		(void) sigset(SIGCHLD, sigchild);
-
-	switch (child = fork()) {
-
-	case (pid_t)-1:
-		dsw_error(gettext("Unable to fork"), NULL);
-		break;
-
-	case 0:
-		if (do_enable) {
-			rc = do_ioctl(dsw_fd, DSWIOC_ENABLE, &parms);
-		} else {
-			rc = do_ioctl(dsw_fd, DSWIOC_RESET, &args);
-		}
-		if (rc == -1 && errno != DSW_EABORTED && errno != DSW_EIO) {
-			spcs_log("ii", stat, gettext("Fail reset %s"), volume);
-			dsw_error(gettext("Reset shadow failed"), stat);
-		}
-		/* last_overflow is set during find_shadow_config */
-		if (strlen(last_overflow) > 0 &&
-		    (stat_flags & (DSW_SHDOFFLINE | DSW_BMPOFFLINE)) != 0) {
-			/* reattach it */
-			(void) strncpy(parms.bitmap_vol, last_overflow,
-			    DSW_NAMELEN);
-			do_attach(&parms);
-		}
-		spcs_log("ii", stat, gettext("Finish reset %s"), volume);
-		spcs_s_ufree(stat);
-
-		exit(0);
-		break;
-	default:
-		if (wait_action == WaitForStart) {
-			rc = child_wait(child, CopyStart, args.shadow_vol);
-		} else { /* wait_action == WaitForEnd */
-			wait_loc = 0;
-			(void) wait(&wait_loc);
-			if (WIFEXITED(wait_loc) && (WEXITSTATUS(wait_loc) == 0))
-				rc = 0;
-			else
-				rc = -1;
-		}
-		break;
-	}
-	/* if successful, remove flags entry from options field */
-	if (rc >= 0) {
-		if (!ii_lock(cfg, CFG_WRLOCK)) {
-			dsw_error(gettext("Unable to set locking on the "
-			    "configuration"), NULL);
-		}
-		config_locked = 1;
-		if (!find_shadow_config(volume, &parms, &args)) {
-			dsw_error(gettext("Volume is not in a Point-in-Time "
-			    "Copy group"), NULL);
-		}
-		(void) snprintf(key, CFG_MAX_KEY, "ii.set%d.options",
-		    setnumber);
-		if (cfg_del_option(cfg, CFG_SEC_CONF, key, NSKERN_II_BMP_OPTION)
-		    < 0) {
-			dsw_error(gettext("Update of config failed"), NULL);
-		}
-		(void) cfg_commit(cfg);
-		cfg_unlock(cfg);
-		config_locked = 0;
-	}
-
-	return (rc);
-}
-
-int
-overflow(char *volume)
-{
-	dsw_ioctl_t args;
-	int	rc;
-	spcs_s_info_t *stat;
-
-	check_action(gettext("Initialize this overflow volume?"));
-	if (find_matching_cf_line(volume, NULL, &args))
-		dsw_error(gettext("Volume is part of a Point-in-Time Copy "
-		    "group"), NULL);
-	args.status = spcs_s_ucreate();
-	(void) strncpy(args.shadow_vol, volume, DSW_NAMELEN);
-	rc = do_ioctl(dsw_fd, DSWIOC_OCREAT, &args);
-	if (rc == -1) {
-		spcs_log("ii", &args.status,
-		    gettext("Create overflow failed %s"), volume);
-		dsw_error(gettext("Create overflow failed"), &args.status);
-	}
-	if (rc == -1)
-		stat = &args.status;
-	else
-		stat = NULL;
-	spcs_log("ii", stat, gettext("Create overflow succeeded %s"), volume);
-	spcs_s_ufree(&args.status);
-
-	return (0);
-}
-
-void
-bitmap_op(char *master_volume, int print_bitmap, int bitmap_percent, int used,
-    int is_compact)
-{
-	unsigned char *bitmap;
-	char *name;
-	int i, x, y;
-	unsigned j;
-	unsigned long n;
-	unsigned long percent;
-
-	bitmap = allocate_bitmap(master_volume);
-	if (bitmap == NULL)
-		return;
-
-	if (bitmap_percent) {
-		/* count the number of bits set in bitmap */
-		for (i = n = 0; i < bm_size; i++)
-			for (j = (unsigned)bitmap[i]; j; j &= j -1)
-				n++;
-		if (is_compact)
-			(void) printf(gettext("Chunks in map: %d used: %d\n"),
-			    used, n);
-		if (bm_actual < 100) {
-			percent = 0;
-		} else {
-			percent = (n * 100) / bm_actual;
-		}
-		(void) printf(gettext("Percent of bitmap set: %u\n"), percent);
-		percent = percent/100;
-		/* distinguish between 0.0000% and 0.n% of bitmap set */
-		if (percent < 1)
-			(void) printf("\t(%s)\n", n > 0 ?
-			    gettext("bitmap dirty") : gettext("bitmap clean"));
-	}
-
-	if (print_bitmap) {
-		name = strrchr(master_volume, '/');
-		if (name++ == NULL)
-		name = master_volume;
-		i = bm_size * 8;
-		x = (int)ceil(sqrt((double)i));
-		x += (8 - (x % 8));	/* round up to nearest multiple of 8 */
-		y = i / x;
-		if (y * x < i)
-			y++;
-		(void) printf("#define bm%s_width %d\n#define bm%s_height %d\n",
-		    name, x, name, y);
-		(void) printf("#define bm%s_x_hot 0\n#define bm%s_y_hot 0\n",
-		    name, name);
-		(void) printf("static char bm%s_bits[] = {\n", name);
-		for (i = 0; i < bm_size; i++) {
-			if (i % 12 == 0)
-				(void) printf("\n");
-			(void) printf("0x%02x, ", bitmap[i]);
-		}
-		y = x * y;
-		for (; i < y; i++) {
-			if (i % 12 == 0)
-				(void) printf("\n");
-			(void) printf("0x00, ");
-		}
-		(void) printf("\n};\n");
-	}
-
-	free_bitmap(bitmap);
-}
-
-static int
-validate_group_names(char **vol_list, char *group)
-{
-	ENTRY item, *found;
-	int i, rc, count;
-	dsw_aioctl_t *group_list;
-	char *ptr;
-
-	if (group == NULL || *group == NULL) {
-		/* no group set, just count volume list */
-		for (i = 0; *vol_list++ != NULL; i++)
-			;
-		return (i);
-	}
-
-	if ((count = do_ioctl(dsw_fd, DSWIOC_LISTLEN, NULL)) < 0)
-		dsw_error("DSWIOC_LISTLEN", NULL);
-
-	group_list = malloc(sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
-	if (group_list == NULL)
-		dsw_error(gettext("Failed to allocate memory"), NULL);
-
-	bzero(group_list, sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
-	group_list->count = count;
-	group_list->flags = 0;
-	group_list->status = spcs_s_ucreate();
-	(void) strncpy(group_list->shadow_vol, group, DSW_NAMELEN);
-
-	rc = do_ioctl(dsw_fd, DSWIOC_GLIST, group_list);
-	if (rc < 0)
-		dsw_error(gettext("Group list access failure"),
-		    &group_list->status);
-
-	group_list->shadow_vol[DSW_NAMELEN * group_list->count] = '\0';
-
-	/* create hash and enter all volumes into it */
-	if (hcreate(group_list->count) == 0)
-		dsw_error(gettext("Failed to allocate memory"), NULL);
-	ptr = group_list->shadow_vol;
-	count = group_list->count;
-	i = 0;
-	while (i < count) {
-		ptr[ DSW_NAMELEN - 1 ] = '\0';
-		item.key = ptr;
-		item.data = (void *) 0;
-		(void) hsearch(item, ENTER);
-		++i;
-		ptr += DSW_NAMELEN;
-	}
-
-	/* now compare the volume list with the hash */
-	for (i = 0; vol_list[ i ]; i++) {
-		item.key = vol_list[ i ];
-		found = hsearch(item, FIND);
-		if (!found)
-			dsw_error(gettext("Group config does not match kernel"),
-			    NULL);
-		if (found->data != (void *) 0)
-			dsw_error(gettext("Duplicate volume specified"), NULL);
-		found->data = (void *) 1;
-	}
-	if (i != count)
-		dsw_error(gettext("Group config does not match kernel"), NULL);
-
-	/* everything checks out */
-	free(group_list);
-	hdestroy();
-
-	return (count);
-}
-
-int
-do_acopy(char **vol_list, enum copy_update update_mode,
-		enum copy_direction direction)
-{
-	dsw_aioctl_t *acopy_args;
-	dsw_ioctl_t copy_args;
-	dsw_config_t parms;
-	dsw_stat_t	stat_s;
-	int	i;
-	int	rc;
-	int	n_vols;
-	char	*t;
-	char	buf[1024];
-	char	*sp;
-	char	*ppid;
-
-	n_vols = validate_group_names(vol_list, group_name);
-
-	acopy_args = calloc(sizeof (dsw_aioctl_t) + n_vols * DSW_NAMELEN, 1);
-	if (acopy_args == NULL)
-		dsw_error(gettext("Too many volumes given for update"), NULL);
-
-	acopy_args->count = n_vols;
-
-	acopy_args->flags = 0;
-
-	if (update_mode == Update)
-		acopy_args->flags |= CV_BMP_ONLY;
-	if (direction == ToMaster)
-		acopy_args->flags |= CV_SHD2MST;
-	if (pflg) {
-		acopy_args->flags |= CV_LOCK_PID;
-#ifdef DEBUG
-		ppid = getenv("IIADM_PPID");
-		if (ppid) {
-			acopy_args->pid = atoi(ppid);
-			(void) fprintf(stderr, "(using %s for ppid)\n", ppid);
-		} else {
-			acopy_args->pid = getppid();
-		}
-#else
-		acopy_args->pid = getppid();
-#endif
-	}
-
-	for (i = 0; i < n_vols; i++) {
-		if (!find_shadow_config(vol_list[i], &parms, &copy_args))
-			dsw_error(gettext("Volume is not in a Point-in-Time "
-			    "group"), NULL);
-		if (direction == ToMaster) {
-			t = parms.master_vol;
-		} else {
-			t = parms.shadow_vol;
-		}
-
-		if (mounted(t)) {
-			errno = EBUSY;
-			dsw_error(gettext("Target of copy/update is mounted, "
-			    "unmount it first"), NULL);
-		}
-
-		(void) strlcpy(stat_s.shadow_vol, parms.shadow_vol,
-		    DSW_NAMELEN);
-		stat_s.status = spcs_s_ucreate();
-		rc = do_ioctl(dsw_fd, DSWIOC_STAT, &stat_s);
-		spcs_s_ufree(&stat_s.status);
-		if (rc == -1) {
-			(void) sprintf(buf,
-			    gettext("Shadow group %s is suspended"),
-			    vol_list[i]);
-			dsw_error(buf, NULL);
-		}
-
-		if (stat_s.stat & DSW_COPYINGP) {
-			(void) fprintf(stderr, "%s: %s\n", cmdnam,
-			    gettext("Copy already in progress"));
-			exit(1);
-		}
-	}
-	acopy_args->status = spcs_s_ucreate();
-	for (i = 0; i < n_vols; i++) {
-		spcs_log("ii", NULL, gettext("Atomic %s %s %s"),
-		    update_mode == Update ? gettext("update") : gettext("copy"),
-		    vol_list[i],
-		    direction == ToMaster ?  gettext("from shadow") :
-		    gettext("to shadow"));
-	}
-	if (group_name == NULL || *group_name == NULL) {
-		sp = acopy_args->shadow_vol;
-		for (i = 0; i < n_vols; i++, sp += DSW_NAMELEN)
-			(void) strncpy(sp, vol_list[i], DSW_NAMELEN);
-	} else {
-		(void) strncpy(acopy_args->shadow_vol, group_name, DSW_NAMELEN);
-		acopy_args->flags |= CV_IS_GROUP;
-	}
-	rc = do_ioctl(dsw_fd, DSWIOC_ACOPY, acopy_args);
-	if (rc == -1) {
-		i = acopy_args->count;
-		if (i < 0 || i >= n_vols) {
-			spcs_log("ii", NULL, gettext("Atomic update failed"));
-			(void) sprintf(buf, gettext("Update failed"));
-		} else {
-			spcs_log("ii", NULL,
-			    gettext("Atomic update of %s failed"),
-			    vol_list[acopy_args->count]);
-			(void) sprintf(buf, gettext("Update of %s failed"),
-			    vol_list[acopy_args->count]);
-		}
-		dsw_error(buf, &(acopy_args->status));
-	}
-	return (rc);
-}
-
-int
-do_copy(char **vol_list, enum copy_update update_mode,
-		enum copy_direction direction, enum copy_wait wait_action)
-{
-	dsw_ioctl_t copy_args;
-	dsw_config_t parms;
-	dsw_stat_t	stat_s;
-	int	rc;
-	int	wait_loc;
-	char	*t;
-	char	*volume;
-	pid_t	child = (pid_t)0;
-	char	*ppid;
-
-	if (vol_list[0] && vol_list[1])
-		return (do_acopy(vol_list, update_mode, direction));
-
-	volume = vol_list[0];
-	if (!find_shadow_config(volume, &parms, &copy_args))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-
-	cfg_unlock(cfg);
-	config_locked = 0;
-	copy_args.flags = 0;
-
-	if (update_mode == Update)
-		copy_args.flags |= CV_BMP_ONLY;
-	if (direction == ToMaster) {
-		copy_args.flags |= CV_SHD2MST;
-		t = parms.master_vol;
-	} else {
-		t = parms.shadow_vol;
-	}
-	if (pflg) {
-		copy_args.flags |= CV_LOCK_PID;
-#ifdef DEBUG
-		ppid = getenv("IIADM_PPID");
-		if (ppid) {
-			copy_args.pid = atoi(ppid);
-			(void) fprintf(stderr, "(using %s for ppid)\n", ppid);
-		} else {
-			copy_args.pid = getppid();
-		}
-#else
-		copy_args.pid = getppid();
-#endif
-	}
-
-	if (mounted(t)) {
-		errno = EBUSY;
-		dsw_error(gettext("Target of copy/update is mounted, "
-		    "unmount it first"), NULL);
-	}
-
-	(void) strlcpy(stat_s.shadow_vol, copy_args.shadow_vol, DSW_NAMELEN);
-	stat_s.status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_STAT, &stat_s);
-	spcs_s_ufree(&stat_s.status);
-	if (rc == -1)
-		dsw_error(gettext("Shadow group suspended"), NULL);
-
-	if (stat_s.stat & DSW_COPYINGP) {
-		(void) fprintf(stderr, "%s: %s\n", cmdnam,
-		    gettext("Copy already in progress"));
-		exit(1);
-	}
-
-	copy_args.status = spcs_s_ucreate();
-	spcs_log("ii", NULL, gettext("Start %s %s %s"),
-	    update_mode == Update ? gettext("update") : gettext("copy"),
-	    volume,
-	    direction == ToMaster ?  gettext("from shadow") :
-	    gettext("to shadow"));
-
-	if (wait_action == WaitForStart)
-		(void) sigset(SIGCHLD, sigchild);
-	switch (child = fork()) {
-
-	case (pid_t)-1:
-		dsw_error(gettext("Unable to fork"),
-		    NULL);
-		break;
-
-	case 0:
-		rc = do_ioctl(dsw_fd, DSWIOC_COPY, &copy_args);
-		if (rc == -1) {
-			spcs_log("ii", &copy_args.status,
-			    gettext("Fail %s %s %s"),
-			    update_mode == Update ?
-			    gettext("update") : gettext("copy"),
-			    volume,
-			    direction == ToMaster ?
-			    gettext("from shadow") : gettext("to shadow"));
-			dsw_error(gettext("Copy failed"), &copy_args.status);
-		}
-		spcs_s_ufree(&copy_args.status);
-		spcs_log("ii", NULL, gettext("Finish %s %s %s"),
-		    update_mode == Update ? gettext("update") : gettext("copy"),
-		    volume,
-		    direction == ToMaster ?  gettext("from shadow") :
-		    gettext("to shadow"));
-
-		exit(0);
-		break;
-	default:
-		if (wait_action == WaitForStart) {
-			rc = child_wait(child, CopyStart, copy_args.shadow_vol);
-		} else { /* wait_action == WaitForEnd */
-			wait_loc = 0;
-			(void) wait(&wait_loc);
-			if (WIFEXITED(wait_loc) && (WEXITSTATUS(wait_loc) == 0))
-				rc = 0;
-			else
-				rc = 1;
-		}
-		break;
-	}
-	return (rc);
-}
-
-void
-print_status(dsw_config_t *conf, int in_config)
-{
-	dsw_stat_t args;
-	int	stat_flags;
-	static int need_sep = 0;
-	time_t tmp_time;
-
-	if (need_sep++ > 0)
-		(void) printf("--------------------------------------"
-		    "----------------------------------------\n");
-	(void) strlcpy(args.shadow_vol, conf->shadow_vol, DSW_NAMELEN);
-	if (in_config) {
-		(void) printf("%s: %s\n",
-		    conf->master_vol, gettext("(master volume)"));
-		(void) printf("%s: %s\n",
-		    conf->shadow_vol, gettext("(shadow volume)"));
-		(void) printf("%s: %s\n",
-		    conf->bitmap_vol, gettext("(bitmap volume)"));
-	}
-
-	/*
-	 * Do special checking on the status of this volume in a Sun Cluster
-	 */
-	if (check_cluster() == II_CLUSTER) {
-		char dgname[CFG_MAX_BUF], *other_node;
-
-		if (cfg_dgname(conf->bitmap_vol, dgname, sizeof (dgname))) {
-			if (strlen(dgname)) {
-				int rc = cfg_dgname_islocal(dgname,
-				    &other_node);
-
-				if (rc < 0) {
-					(void) printf(gettext(
-					    "Suspended on this node, "
-					    "not active elsewhere\n"));
-					return;
-				} else if (rc == 0) {
-					(void) printf(gettext(
-					    "Suspended on this node, "
-					    "active on %s\n"), other_node);
-					return;
-				}
-			}
-		}
-	}
-
-	args.status = spcs_s_ucreate();
-	if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1) {
-
-		/* Handle Not found or not in config */
-		if (errno != DSW_ENOTFOUND || !in_config)
-			dsw_error(gettext("Stat failed"), &args.status);
-
-		/* Just suspend */
-		(void) printf(gettext("Suspended.\n"));
-		return;
-	}
-
-	if (args.overflow_vol[0] != '\0')
-		(void) printf("%s: %s\n", args.overflow_vol,
-		    gettext("(overflow volume)"));
-
-	if (conf->group_name[0] != '\0')
-		(void) printf(gettext("Group name: %s\n"),
-		    conf->group_name);
-
-	if (conf->cluster_tag[0] != '\0')
-		(void) printf(gettext("Cluster tag: %s\n"),
-		    conf->cluster_tag);
-
-	stat_flags = args.stat;
-	spcs_s_ufree(&args.status);
-	if (stat_flags & DSW_GOLDEN)
-		(void) printf(gettext("Independent copy"));
-	else
-		(void) printf(gettext("Dependent copy"));
-
-	if (stat_flags & DSW_TREEMAP)
-		(void) printf(gettext(", compacted shadow space"));
-
-	if (stat_flags & DSW_COPYINGP)
-		(void) printf(gettext(", copy in progress"));
-	else if (stat_flags & DSW_COPYING)
-		(void) printf(gettext(", copy not active"));
-
-	if (stat_flags & DSW_COPYINGM)
-		(void) printf(gettext(", copying master to shadow"));
-
-	if (stat_flags & DSW_COPYINGS)
-		(void) printf(gettext(", copying shadow to master"));
-
-	if (stat_flags & DSW_COPYINGX)
-		(void) printf(gettext(", abort of copy requested"));
-
-	if (stat_flags & DSW_MSTOFFLINE)
-		(void) printf(gettext(", master volume offline"));
-
-	if (stat_flags & DSW_SHDOFFLINE)
-		(void) printf(gettext(", shadow volume offline"));
-
-	if (stat_flags & DSW_BMPOFFLINE)
-		(void) printf(gettext(", bitmap volume offline"));
-
-	if (stat_flags & DSW_OVROFFLINE)
-		(void) printf(gettext(", overflow volume offline"));
-
-	if (stat_flags & DSW_SHDEXPORT)
-		(void) printf(gettext(", shadow volume exported"));
-
-	if (stat_flags & DSW_SHDIMPORT)
-		(void) printf(gettext(", shadow volume imported"));
-
-	if (stat_flags & DSW_OVERFLOW)
-		(void) printf(gettext(", out of space"));
-
-	if (stat_flags & DSW_VOVERFLOW)
-		(void) printf(gettext(", spilled into overflow volume"));
-	(void) printf("\n");
-
-	tmp_time = args.mtime;
-	if (tmp_time != 0)
-		(void) printf("%s %s", gettext("Latest modified time:"),
-		    ctime(&tmp_time));
-	else
-		(void) printf("%s\n", gettext("Latest modified time: unknown"));
-
-	(void) printf("%s %8llu\n", gettext("Volume size:"), args.size);
-	if (args.shdsize != 0) {
-		(void) printf("%s %lld %s %lld\n",
-		    gettext("Shadow chunks total:"), args.shdsize,
-		    gettext("Shadow chunks used:"), args.shdused);
-	}
-	bitmap_op(args.shadow_vol, 0, 1, 0, 0);
-}
-
-int
-abort_copy(char *volume)
-{
-	dsw_ioctl_t args;
-
-	if (!find_shadow_config(volume, NULL, &args))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-	args.status = spcs_s_ucreate();
-	if (do_ioctl(dsw_fd, DSWIOC_ABORT, &args)  == -1)
-		dsw_error(gettext("Abort failed"), &args.status);
-	spcs_log("ii", NULL, gettext("Abort %s"), args.shadow_vol);
-	spcs_s_ufree(&args.status);
-	return (0);
-}
-
-void
-iiversion()
-{
-	dsw_version_t args;
-
-	args.status = spcs_s_ucreate();
-	if (do_ioctl(dsw_fd, DSWIOC_VERSION, &args)  == -1)
-		dsw_error(gettext("Version failed"), &args.status);
-	spcs_s_ufree(&args.status);
-#ifdef DEBUG
-	(void) printf(gettext("Point in Time Copy version %d.%d.%d.%d\n"),
-	    args.major, args.minor, args.micro, args.baseline);
-#else
-	if (args.micro) {
-		(void) printf(gettext("Point in Time Copy version %d.%d.%d\n"),
-		    args.major, args.minor, args.micro);
-	} else {
-		(void) printf(gettext("Point in Time Copy version %d.%d\n"),
-		    args.major, args.minor);
-	}
-#endif
-}
-
-void
-list_volumes()
-{
-	dsw_list_t args;
-	int i, set, found;
-	dsw_config_t *lp;
-	ENTRY item, *ip;
-	dsw_config_t parms;
-
-	if ((i = do_ioctl(dsw_fd, DSWIOC_LISTLEN, &args)) == -1)
-		dsw_error("DSWIOC_LISTLEN", NULL);
-
-	args.status = spcs_s_ucreate();
-	args.list_used = 0;
-	args.list_size = i + 4;
-	lp = args.list = (dsw_config_t *)
-	    malloc(args.list_size * sizeof (dsw_config_t));
-
-	if (args.list == NULL)
-		dsw_error(gettext("Failed to allocate memory"), NULL);
-	if (do_ioctl(dsw_fd, DSWIOC_LIST, &args)  == -1)
-		dsw_error(gettext("List failed"), &args.status);
-	spcs_s_ufree(&args.status);
-
-	/* make a hashtable */
-	if (args.list_used > 0) {
-		if (hcreate(args.list_used) == 0) {
-			dsw_error(gettext("Failed to allocate memory"), NULL);
-			/*NOTREACHED*/
-		}
-	}
-
-	/* populate the hashtable */
-	for (i = 0; i < args.list_used; i++, lp++) {
-		item.key = lp->shadow_vol;
-		item.data = (char *)lp;
-		if (hsearch(item, ENTER) == NULL) {
-			dsw_error(gettext("Failed to allocate memory"), NULL);
-			/*NOTREACHED*/
-		}
-	}
-
-	/* perform action for each line of the stored config file */
-	for (set = 1; get_dsw_config(set, &parms) == 0; set++) {
-
-		/* Are there any II sets configured on this node? */
-		if (args.list_used > 0) {
-			item.key = parms.shadow_vol;
-
-			/* Is this volume configured on this node? */
-			if (ip = hsearch(item, FIND)) {
-
-				/* Handle Imported Shadows */
-				/* LINTED alignment of cast ok */
-				lp = (dsw_config_t *)ip->data;
-				if (strcmp(parms.master_vol,
-				    II_IMPORTED_SHADOW))
-					found = !(lp->flag & DSW_SHDIMPORT);
-				else
-					found = (lp->flag & DSW_SHDIMPORT);
-			}
-			else
-				found = FALSE;
-		}
-		else
-			found = FALSE;
-
-		if ((cfg_cluster_tag) &&
-		    strcmp(cfg_cluster_tag, parms.cluster_tag))
-			continue;
-
-		if ((group_name) && strcmp(group_name, parms.group_name))
-			continue;
-
-		(void) printf("%s %.*s %.*s %.*s%s\n",
-		    (parms.flag & DSW_GOLDEN) ? "ind" : "dep",
-		    DSW_NAMELEN, parms.master_vol,
-		    DSW_NAMELEN, parms.shadow_vol,
-		    DSW_NAMELEN, parms.bitmap_vol,
-		    found ? "" : gettext(" (suspended)"));
-	}
-	hdestroy();
-	free(args.list);
-}
-
-int
-wait_for_copy(char *volume)
-{
-	dsw_ioctl_t parms;
-	int rc;
-	static int unlocked = 0;
-	char *ppid;
-
-	if (unlocked && !ii_lock(cfg, CFG_RDLOCK)) {
-		dsw_error(gettext("Unable to set locking on the configuration"),
-		    NULL);
-	}
-	config_locked = 1;
-	if (!find_shadow_config(volume, NULL, &parms))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-	cfg_unlock(cfg);
-	config_locked = 0;
-	unlocked = 1;
-
-	parms.status = spcs_s_ucreate();
-	if (pflg) {
-#ifdef DEBUG
-		ppid = getenv("IIADM_PPID");
-		if (ppid) {
-			parms.pid = atoi(ppid);
-			(void) fprintf(stderr, "(using %s for ppid)\n", ppid);
-		} else {
-			parms.pid = (nflg) ? -1 : getppid();
-		}
-#else
-		parms.pid = (nflg) ? -1 : getppid();
-#endif
-		parms.flags |= CV_LOCK_PID;
-	}
-
-	rc = do_ioctl(dsw_fd, DSWIOC_WAIT, &parms);
-	if (rc == -1)
-		dsw_error(gettext("Wait failed"), &parms.status);
-	spcs_s_ufree(&parms.status);
-	return (0);
-}
-
-int
-export(char *volume)
-{
-	dsw_ioctl_t parms;
-	dsw_config_t conf;
-	char *old_ctag, dgname[DSW_NAMELEN];
-	int rc;
-
-	if (!find_shadow_config(volume, &conf, &parms))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-	if (mounted(volume))
-		dsw_error(gettext("Can't export a mounted volume"), NULL);
-
-	/* If this is an exportable shadow in the cluster, change ctag */
-	if (strlen(conf.cluster_tag) &&
-	    (cfg_dgname(volume, dgname, sizeof (dgname)))) {
-		old_ctag = cfg_cluster_tag;
-		cfg_resource(cfg, cfg_cluster_tag = strdup(dgname));
-	} else	old_ctag = NULL;
-
-	if (cfg_load_dsvols(cfg) < 0 || cfg_load_shadows(cfg) < 0) {
-		dsw_error(gettext("Unable to parse config file"), NULL);
-	}
-	reload_vols = LD_DSVOLS | LD_SHADOWS;
-	conform_name(&volume);
-
-	spcs_log("ii", NULL, gettext("Export %s"), volume);
-	parms.status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_EXPORT, &parms);
-	if (rc == -1)
-		dsw_error(gettext("Export failed"), &parms.status);
-	if (perform_autosv()) {
-		if (cfg_vol_disable(cfg, volume, cfg_cluster_tag, "ii") < 0) {
-			dsw_error(gettext("SV-disable failed"), NULL);
-		}
-		(void) cfg_commit(cfg);
-	}
-
-	/* restore old cluster tag, if changed */
-	if (old_ctag != NULL)
-		cfg_resource(cfg, cfg_cluster_tag = old_ctag);
-
-	spcs_s_ufree(&parms.status);
-	return (0);
-}
-
-int
-detach(char *volume)
-{
-	dsw_ioctl_t parms;
-	int rc;
-
-	if (!find_shadow_config(volume, NULL, &parms))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-	parms.status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_ODETACH, &parms);
-	if (rc == 0) {
-		/* remove overflow from cfg line */
-		(void) sprintf(key, "ii.set%d.overflow", setnumber);
-		if (cfg_put_cstring(cfg, key, "-", 1) < 0) {
-				perror("cfg_put_cstring");
-		}
-		(void) cfg_commit(cfg);
-	} else {
-		spcs_log("ii", NULL, gettext("Detach of overflow %s failed"),
-		    parms.shadow_vol);
-		dsw_error(gettext("Failed to detach overflow volume"),
-		    &parms.status);
-	}
-	return (rc);
-}
-
-static void
-can_disable(char *vol)
-{
-	dsw_stat_t args;
-
-	if (mounted(vol)) {
-		(void) strlcpy(args.shadow_vol, vol, DSW_NAMELEN);
-		args.status = spcs_s_ucreate();
-		if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) != -1 &&
-		    (args.stat & DSW_GOLDEN) == 0) {
-			errno = EBUSY;
-			dsw_error(gettext("Shadow Volume is currently mounted "
-			    "and dependent on the master volume"), NULL);
-		}
-		spcs_s_ufree(&args.status);
-	}
-}
-
-static void
-clean_up_after_failed_disable(dsw_ioctl_t *parms)
-{
-	char **p;
-	dsw_stat_t args;
-
-	for (p = group_volumes; *p; p++) {
-		(void) strlcpy(args.shadow_vol, *p, DSW_NAMELEN);
-		args.status = spcs_s_ucreate();
-		if (do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1) {
-			/* set was successfully disabled */
-			if (find_shadow_config(*p, NULL, NULL))
-				remove_iiset(setnumber, *p, 0);
-		}
-		spcs_s_ufree(&args.status);
-	}
-
-	dsw_error(gettext("Some sets in the group failed to disable"),
-	    &parms->status);
-}
-
-int
-dsw_group_or_single_disable(int argc, char *argv[])
-{
-	int rc = 0;
-	char **p;
-	dsw_ioctl_t parms;
-	int flags = 0;
-	dsw_config_t conf;
-	int shd_exported = 0;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-
-	if (group_name) {
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		for (p = group_volumes; *p; p++) {
-			can_disable(*p);
-		}
-
-		(void) strncpy(parms.shadow_vol, group_name, DSW_NAMELEN);
-		if (*group_name)
-			flags = CV_IS_GROUP;
-	} else {
-		if (!find_shadow_config(argv[1], &conf, &parms)) {
-			dsw_error(gettext("Volume is not in a Point-in-Time "
-			    "Copy group"), NULL);
-		}
-
-		can_disable(argv[1]);
-		flags = 0;
-	}
-
-	if (group_name && !*group_name) {
-		/* user typed iiadm -g "" -d */
-		for (p = group_volumes; *p; p++) {
-			parms.status = spcs_s_ucreate();
-			parms.flags = flags;
-			(void) strncpy(parms.shadow_vol, *p, DSW_NAMELEN);
-			rc = do_ioctl(dsw_fd, DSWIOC_DISABLE, &parms);
-			if (rc == -1 && errno != DSW_ENOTFOUND)
-				dsw_error(gettext("Disable failed"),
-				    &parms.status);
-			if (!find_shadow_config(*p, NULL, NULL))
-				dsw_error(gettext("Volume is not in a Point-in"
-				    "-Time Copy group"), &parms.status);
-			remove_iiset(setnumber, *p, 0);
-			spcs_s_ufree(&parms.status);
-			spcs_log("ii", NULL, gettext("Disabled %s"),
-			    parms.shadow_vol);
-		}
-	} else {
-		if (is_exported(conf.shadow_vol)) {
-			shd_exported = 1;
-		}
-		if ((strcmp(conf.master_vol, II_IMPORTED_SHADOW) == 0) &&
-		    is_exported(conf.shadow_vol)) {
-			dsw_error(gettext(
-			"Imported shadow not disabled"), NULL);
-		}
-
-		parms.status = spcs_s_ucreate();
-		parms.flags = flags;
-		rc = do_ioctl(dsw_fd, DSWIOC_DISABLE, &parms);
-		if (rc == -1 && errno != DSW_ENOTFOUND) {
-			if (errno == DSW_EDISABLE) {
-				/*
-				 * one or more sets within the group
-				 * couldn't disable
-				 */
-				clean_up_after_failed_disable(&parms);
-			} else {
-				dsw_error(gettext("Disable failed"),
-				    &parms.status);
-			}
-		}
-		spcs_log("ii", NULL, gettext("Disabled %s"), parms.shadow_vol);
-	}
-
-
-	if (group_name && *group_name) {
-		for (p = group_volumes; *p; p++) {
-			if (!find_shadow_config(*p, NULL, NULL)) {
-				/* argh! */
-				(void) fprintf(stderr,
-				    gettext("Volume '%s' is not "
-				    "in a Point-in-Time Copy group"), *p);
-			} else {
-				remove_iiset(setnumber, *p, 0);
-			}
-		}
-	} else if (!group_name) {
-		if (!find_shadow_config(argv[1], NULL, NULL)) {
-			/* argh! */
-			dsw_error(gettext("Volume is not in a Point-in-Time "
-			    "Copy group"), NULL);
-		}
-
-		remove_iiset(setnumber, argv[1], shd_exported);
-	}
-
-	return (0);
-}
-
-int
-dsw_group_or_single_op(int argc, char *argv[], int (*op)(char *))
-{
-	int rc = 0;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-
-	if (group_name) {
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		for (; *group_volumes; group_volumes++)
-			rc |= (*op)(*group_volumes);
-	} else {
-		rc = (*op)(argv[1]);
-	}
-	return (rc);
-}
-
-void
-dsw_list_clusters(char *cluster)
-{
-	dsw_aioctl_t *acopy_args;
-	int rc, i, count;
-	char *ptr;
-
-	if ((count = do_ioctl(dsw_fd, DSWIOC_LISTLEN, NULL)) < 0)
-		dsw_error("DSWIOC_LISTLEN", NULL);
-
-	acopy_args = malloc(sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
-	if (acopy_args == NULL)
-		dsw_error(gettext("Can't get memory for list enquiry"), NULL);
-
-	bzero(acopy_args, sizeof (dsw_aioctl_t) + count * DSW_NAMELEN);
-	acopy_args->count = count;
-	acopy_args->flags = 0;
-	acopy_args->status = spcs_s_ucreate();
-	if (cluster)
-		(void) strncpy(acopy_args->shadow_vol, cluster, DSW_NAMELEN);
-
-	rc = do_ioctl(dsw_fd, DSWIOC_CLIST, acopy_args);
-	if (rc == -1)
-		dsw_error(gettext("Cluster list access failure"),
-		    &acopy_args->status);
-
-	acopy_args->shadow_vol[DSW_NAMELEN*acopy_args->count] = NULL;
-
-	if (cluster) {
-		(void) printf(gettext("Sets in cluster resource group %s:\n"),
-		    cluster);
-	} else {
-		(void) printf(
-		    gettext("Currently configured resource groups\n"));
-	}
-	for (i = 0, ptr = acopy_args->shadow_vol; *ptr &&
-	    i < acopy_args->count; i++, ptr += DSW_NAMELEN) {
-		(void) printf("  %-64.64s\n", ptr);
-	}
-}
-
-void
-dsw_enable(int argc, char *argv[])
-{
-	if (argc != 5)
-		usage(gettext("Incorrect number of arguments"));
-
-	enable(argv[1], argv[2], argv[3], argv[4]);
-	exit(0);
-}
-
-
-void
-dsw_disable(int argc, char *argv[])
-{
-	(void) dsw_group_or_single_disable(argc, argv);
-	exit(0);
-}
-
-
-void
-dsw_copy_to_shadow(int argc, char *argv[])
-{
-	char	**volume_list;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-	if (group_name == NULL)
-		volume_list = ++argv;
-	else {
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		volume_list = group_volumes;
-	}
-
-	exit(do_copy(volume_list, Copy, ToShadow, WaitForStart));
-}
-
-
-void
-dsw_update_shadow(int argc, char *argv[])
-{
-	char	**volume_list;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-	if (group_name == NULL)
-		volume_list = ++argv;
-	else {
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		volume_list = group_volumes;
-	}
-
-	exit(do_copy(volume_list, Update, ToShadow, WaitForStart));
-}
-
-
-void
-dsw_copy_to_master(int argc, char *argv[])
-{
-	char	**volume_list;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-	if (group_name == NULL) {
-		volume_list = ++argv;
-		check_action(gettext("Overwrite master with shadow volume?"));
-	} else {
-		check_action(gettext("Overwrite every"
-		    " master in this group with its shadow volume?"));
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		volume_list = group_volumes;
-	}
-
-	exit(do_copy(volume_list, Copy, ToMaster, WaitForStart));
-}
-
-
-void
-dsw_update_master(int argc, char *argv[])
-{
-	char	**volume_list;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-	if (group_name == NULL) {
-		volume_list = ++argv;
-		check_action(gettext("Overwrite master with shadow volume?"));
-	} else {
-		check_action(gettext("Overwrite every"
-		    " master in this group with its shadow volume?"));
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		volume_list = group_volumes;
-	}
-
-	exit(do_copy(volume_list, Update, ToMaster, WaitForStart));
-}
-
-
-void
-dsw_abort_copy(int argc, char *argv[])
-{
-	exit(dsw_group_or_single_op(argc, argv, abort_copy));
-}
-
-
-void
-dsw_display_status(int argc, char *argv[])
-{
-	dsw_config_t parms;
-	int	in_config;
-
-	if (argc != 2 && argc != 1)
-		usage(gettext("Incorrect number of arguments"));
-
-	/* "iiadm -i" and "iiadm -i all" are equivalent */
-	if (argc == 2 && strcmp("all", argv[1]) != 0) {
-		in_config = find_shadow_config(argv[1], &parms, NULL);
-		if (!in_config) {
-			(void) printf(gettext(
-			    "Volume is not in configuration file\n"), NULL);
-			(void) fflush(stdout);
-			(void) strlcpy(parms.shadow_vol, argv[1], DSW_NAMELEN);
-		}
-		print_status(&parms, in_config);
-	} else if (group_name) {
-		if (find_group_members(group_name) < 1)
-			dsw_error(gettext("Group does not exist or "
-			    "has no members"), NULL);
-		for (; *group_volumes; group_volumes++) {
-			in_config = find_shadow_config(*group_volumes,
-			    &parms, NULL);
-			if (in_config)
-				print_status(&parms, in_config);
-		}
-	} else {
-		/* perform action for each line of the stored config file */
-		for (setnumber = 1;
-		    !get_dsw_config(setnumber, &parms); setnumber++) {
-			switch (check_cluster()) {
-			case II_CLUSTER:
-				if ((cfg_cluster_tag) &&
-				    (strcmp(cfg_cluster_tag,
-				    parms.cluster_tag)))
-					continue;
-				break;
-			case II_CLUSTER_LCL:
-				if (strlen(parms.cluster_tag))
-					continue;
-				break;
-			}
-			print_status(&parms, 1);
-		}
-	}
-	exit(0);
-}
-
-void
-dsw_display_bitmap(int argc, char *argv[])
-{
-	dsw_config_t parms;
-	int	in_config;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-
-	in_config = find_shadow_config(argv[1], &parms, NULL);
-	if (!in_config) {
-		(void) printf(gettext(
-		    "Volume is not in configuration file\n"), NULL);
-		(void) fflush(stdout);
-		(void) strlcpy(parms.master_vol, argv[1], DSW_NAMELEN);
-	}
-
-	bitmap_op(parms.shadow_vol, 1, 0, 0, 0);
-	exit(0);
-}
-
-
-/*ARGSUSED*/
-void
-dsw_version(int argc, char *argv[])
-{
-	iiversion();
-	exit(0);
-}
-
-void
-dsw_reset(int argc, char *argv[])
-{
-	exit(dsw_group_or_single_op(argc, argv, reset));
-}
-
-void
-dsw_overflow(int argc, char *argv[])
-{
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-
-	exit(overflow(argv[1]));
-}
-
-void
-dsw_wait(int argc, char *argv[])
-{
-	exit(dsw_group_or_single_op(argc, argv, wait_for_copy));
-}
-
-/*ARGSUSED*/
-void
-dsw_list_volumes(int argc, char *argv[])
-{
-	if (argc != 1)
-		usage(gettext("Incorrect number of arguments"));
-
-	list_volumes();
-	exit(0);
-}
-
-void
-dsw_export(int argc, char *argv[])
-{
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-
-	exit(dsw_group_or_single_op(argc, argv, export));
-}
-
-void
-dsw_detach(int argc, char *argv[])
-{
-	(void) dsw_group_or_single_op(argc, argv, detach);
-	exit(0);
-}
-
-void
-import(char *shadow_volume, char *bitmap_volume)
-{
-	dsw_config_t parms = {0};
-	int rc = 0;
-	char	shd_dg[DSW_NAMELEN];
-	char	bmp_dg[DSW_NAMELEN];
-
-	/*
-	 * If importing a shadow volume and the shadow volume is already
-	 * configured, we only support this if we are in a Sun Cluster
-	 * and the current user specified a cluster tag of -C local
-	 */
-	if (find_shadow_config(shadow_volume, &parms, NULL)) {
-		dsw_error(gettext("Can't import volume on same node"), NULL);
-	}
-
-	switch (check_cluster()) {
-	case II_CLUSTER:
-	case II_CLUSTER_LCL:
-		(void) check_resource_group(shadow_volume);
-		if (cfg_cluster_tag) { /* check all volumes are in same dg */
-			if (cfg_dgname(shadow_volume, shd_dg, DSW_NAMELEN)
-			    == NULL)
-				dsw_error(gettext("Shadow volume not in a"
-				    " disk group"), NULL);
-			if (cfg_dgname(bitmap_volume, bmp_dg, DSW_NAMELEN)
-			    == NULL)
-				dsw_error(gettext("Bitmap volume not in a"
-				    " disk group"), NULL);
-			if (strcmp(bmp_dg, shd_dg) != 0)
-				dsw_error(gettext("Bitmap volume not in"
-				    " same disk group as shadow set members"),
-				    NULL);
-		}
-		break;
-	case II_NOT_CLUSTER:
-		/* do nothing */
-		break;
-	default:
-		dsw_error(gettext(
-		    "Unexpected return from check_cluster()"), NULL);
-	}
-
-	/* Local configuration volumes */
-	if (cfg_load_dsvols(cfg) < 0 || cfg_load_shadows(cfg) < 0) {
-		dsw_error(gettext("Unable to parse config file"), NULL);
-	}
-
-	reload_vols = LD_DSVOLS | LD_SHADOWS;
-	conform_name(&shadow_volume);
-	(void) strcpy(parms.master_vol, II_IMPORTED_SHADOW);
-	(void) strlcpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
-	(void) strlcpy(parms.bitmap_vol, bitmap_volume, DSW_NAMELEN);
-	parms.flag = DSW_GOLDEN;
-
-	spcs_log("ii", NULL, gettext("Import %s %s"),
-	    parms.shadow_vol, parms.bitmap_vol);
-	parms.status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_IMPORT, &parms);
-	if (rc == -1) {
-		spcs_log("ii", NULL, gettext("Import failed %s %s"),
-		    parms.shadow_vol, parms.bitmap_vol);
-		dsw_error(gettext("Import failed"), &parms.status);
-	}
-	if (perform_autosv()) {
-		if (cfg_vol_enable(cfg, shadow_volume, cfg_cluster_tag, "ii")
-		    < 0) {
-			dsw_error(gettext("SV-enable failed"), NULL);
-		}
-		/* cfg_commit is called by add_cfg_entry below */
-	}
-	spcs_s_ufree(&parms.status);
-	add_cfg_entry(&parms);
-}
-
-void
-dsw_import(int argc, char *argv[])
-{
-	if (argc != 3)
-		usage(gettext("Incorrect number of arguments"));
-	import(argv[1], argv[2]);
-
-	exit(0);
-}
-
-void
-join(char *shadow_volume, char *bitmap_file)
-{
-	dsw_ioctl_t shd;
-	dsw_config_t conf;
-	dsw_bitmap_t parms;
-	int rc = 0;
-	int size;
-	FILE *bmpfp;
-	uchar_t *shd_bitmap = 0;
-	ii_header_t header;
-	char dgname[DSW_NAMELEN];
-
-	if (!find_shadow_config(shadow_volume, &conf, &shd))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-
-	/* If this is an exportable shadow in the cluster, change ctag */
-	if (strlen(conf.cluster_tag) &&
-	    (cfg_dgname(shadow_volume, dgname, sizeof (dgname))))
-		cfg_resource(cfg, cfg_cluster_tag = strdup(dgname));
-
-	if (cfg_load_dsvols(cfg) < 0 || cfg_load_shadows(cfg) < 0) {
-		dsw_error(gettext("Unable to parse config file"), NULL);
-	}
-	reload_vols = LD_DSVOLS | LD_SHADOWS;
-	conform_name(&shadow_volume);
-
-	if ((bmpfp = fopen(bitmap_file, "r")) == NULL) {
-		perror(bitmap_file);
-		(void) fprintf(stderr,
-		    gettext("Can't open imported bitmap volume\n"));
-		exit(1);
-	}
-
-	if (fread(&header, sizeof (header), 1, bmpfp) != 1) {
-		(void) fprintf(stderr,
-		    gettext("Can't read imported bitmap volume\n"));
-		exit(1);
-	}
-
-	/* See if this is a bitmap header */
-	switch (header.ii_magic) {
-	case DSW_DIRTY:		/* A copy of a enable bitmap volume */
-	case DSW_CLEAN:
-		check_action(gettext("Use the never imported bitmap?"));
-		break;
-	case DSW_INVALID:	/* A valid diskable secondary bitmap */
-		break;
-	default:
-		(void) fprintf(stderr,
-		    gettext("Secondary bitmap is not a valid bitmap volume\n"));
-		exit(1);
-	}
-
-	size = FBA_SIZE(header.ii_copyfba - header.ii_shdfba);
-	if ((shd_bitmap = malloc(size)) == NULL) {
-		perror("malloc");
-		exit(1);
-	}
-
-	if (fseek(bmpfp, FBA_SIZE(header.ii_shdfba), SEEK_SET)) {
-		perror("fseek");
-		exit(1);
-	}
-
-	if (fread(shd_bitmap, 1, size, bmpfp) != size) {
-		(void) fprintf(stderr,
-		    gettext("Can't read imported bitmap volume\n"));
-		exit(1);
-	}
-
-	(void) fclose(bmpfp);
-
-	(void) strlcpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
-	parms.shd_bitmap = shd_bitmap;
-	parms.shd_size = size;
-	parms.copy_bitmap = NULL;
-	parms.copy_size = 0;
-
-	spcs_log("ii", NULL, gettext("Join %s %s"),
-	    parms.shadow_vol, bitmap_file);
-	parms.status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_JOIN, &parms);
-	if (rc == -1) {
-		spcs_log("ii", NULL, gettext("Join failed %s %s"),
-		    parms.shadow_vol, bitmap_file);
-		dsw_error(gettext("Join failed"), &parms.status);
-	}
-	if (perform_autosv()) {
-		rc = cfg_vol_enable(cfg, shadow_volume, cfg_cluster_tag, "ii");
-		if (rc < 0) {
-			dsw_error(gettext("SV-enable failed"), NULL);
-		}
-		(void) cfg_commit(cfg);
-	}
-	spcs_s_ufree(&parms.status);
-}
-
-int
-params(char *shadow_volume)
-{
-	char *delay = param_delay;
-	char *unit = param_unit;
-	dsw_copyp_t parms;
-	int rc = 0;
-	int get = 0;
-	int new_delay;
-	int new_unit;
-
-	(void) strlcpy(parms.shadow_vol, shadow_volume, DSW_NAMELEN);
-	if (delay == NULL || unit == NULL) {
-		get = 1;
-		parms.copy_delay = -1;
-		parms.copy_unit = -1;
-	} else {
-		new_delay = parms.copy_delay = convert_int(delay);
-		new_unit = parms.copy_unit = convert_int(unit);
-	}
-
-	parms.status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_COPYP, &parms);
-	if (rc == -1) {
-		(void) fprintf(stderr,
-		    gettext("Parameter ranges are delay(%d - %d), "
-		    "units(%d - %d)\n"), MIN_THROTTLE_DELAY, MAX_THROTTLE_DELAY,
-		    MIN_THROTTLE_UNIT, MAX_THROTTLE_UNIT);
-		dsw_error(gettext("Set Copy Parameters failed"), &parms.status);
-	}
-	if (!get)
-		spcs_log("ii", NULL, gettext("Changed copy parameters %s from "
-		    "%d %d to %d %d"), parms.shadow_vol, parms.copy_delay,
-		    parms.copy_unit, new_delay, new_unit);
-	else
-		(void) printf(gettext("volume: %s\ncopy delay: %d\ncopy unit:"
-		    " %d\n"), parms.shadow_vol, parms.copy_delay,
-		    parms.copy_unit);
-	spcs_s_ufree(&parms.status);
-	return (0);
-}
-
-static void
-do_attach(dsw_config_t *parms)
-{
-	dsw_config_t io;
-	int rc;
-	int check = 0;
-
-	spcs_log("ii", NULL, gettext("Attach %s %s"),
-	    parms->shadow_vol, parms->bitmap_vol);
-	parms->status = spcs_s_ucreate();
-	rc = do_ioctl(dsw_fd, DSWIOC_OATTACH, parms);
-	if (rc == -1) {
-		check = 1;
-		/* if overflow() fails, it calls dsw_error to exit */
-		(void) overflow(parms->bitmap_vol);
-	}
-	spcs_s_ufree(&parms->status);
-	if (check == 1) {
-		if (!find_shadow_config(parms->shadow_vol, &io, NULL))
-			dsw_error(
-			    gettext("Volume is not in a Point-in-Time Copy "
-			    "group"), NULL);
-		(void) strlcpy(io.bitmap_vol, parms->bitmap_vol, DSW_NAMELEN);
-		io.status = spcs_s_ucreate();
-		if (do_ioctl(dsw_fd, DSWIOC_OATTACH, &io) == -1) {
-			spcs_log("ii", NULL, gettext("Attach failed %s %s"),
-			    io.shadow_vol, parms->bitmap_vol);
-			dsw_error(gettext("Attach failed"), &io.status);
-		}
-		spcs_s_ufree(&io.status);
-	}
-}
-
-int
-attach(char *shadow_volume)
-{
-	dsw_config_t parms;
-	dsw_stat_t args;
-	char	shd_dg[DSW_NAMELEN];
-	char	ovr_dg[DSW_NAMELEN];
-
-	switch (check_cluster()) {
-	case II_CLUSTER:
-	case II_CLUSTER_LCL:
-		(void) check_resource_group(shadow_volume);
-		if (cfg_cluster_tag) { /* check all volumes are in same dg */
-			if (cfg_dgname(shadow_volume, shd_dg, DSW_NAMELEN)
-			    == NULL)
-				dsw_error(gettext("Shadow volume not in a"
-				    " disk group"), NULL);
-			if (cfg_dgname(overflow_file, ovr_dg, DSW_NAMELEN)
-			    == NULL)
-				dsw_error(gettext("Overflow volume not in a"
-				    " disk group"), NULL);
-			if (strcmp(ovr_dg, shd_dg) != 0)
-				dsw_error(gettext("Overflow volume not in"
-				    " same disk group as shadow set members"),
-				    NULL);
-		}
-		break;
-	case II_NOT_CLUSTER:
-		/* do nothing */
-		break;
-	default:
-		dsw_error(gettext(
-		    "Unexpected return from check_cluster()"), NULL);
-	}
-
-	/* assure that the overflow_file is not an II volume */
-	if (find_any_cf_line(overflow_file))
-		dsw_error(gettext(
-		    "Overflow volume is already in a Point-in-Time Copy "
-		    "group"), NULL);
-
-	/* use find_shadow_config() to find setnumber */
-	if (!find_shadow_config(shadow_volume, &parms, NULL))
-		dsw_error(gettext("Volume is not in a Point-in-Time Copy "
-		    "group"), NULL);
-
-	/* can only attach an overflow volume to dependent, compact shadow */
-	(void) strlcpy(args.shadow_vol, shadow_volume, DSW_NAMELEN);
-
-	args.status = spcs_s_ucreate();
-	if ((do_ioctl(dsw_fd, DSWIOC_STAT, &args) == -1) ||
-	    !(args.stat & DSW_TREEMAP))
-		dsw_error(gettext("Not a compact dependent shadow"), NULL);
-
-	/* bitmap_vol is overloaded */
-	(void) strlcpy(parms.bitmap_vol, overflow_file, DSW_NAMELEN);
-
-	do_attach(&parms);
-
-	/* add overflow to cfg line */
-	(void) sprintf(key, "ii.set%d.overflow", setnumber);
-	if (cfg_put_cstring(cfg, key, overflow_file,
-	    strlen(overflow_file)) < 0) {
-		perror("cfg_put_cstring");
-	}
-	(void) cfg_commit(cfg);
-	return (0);
-}
-
-void
-dsw_join(int argc, char *argv[])
-{
-	if (argc != 3)
-		usage(gettext("Incorrect number of arguments"));
-
-	join(argv[1], argv[2]);
-	exit(0);
-}
-
-void
-dsw_params(int argc, char *argv[])
-{
-	if (argc != 4 && argc != 2 && argc != 0)
-		usage(gettext("Incorrect number of arguments"));
-
-	if ((argc == 4) || (argc == 2)) {
-		param_delay = argv[1];
-		param_unit = argv[2];
-		if (argc == 4) {
-			argv[1] = argv[3];
-			argv[2] = NULL;
-		}
-	}
-	exit(dsw_group_or_single_op(2, argv, params));
-}
-
-/*ARGSUSED*/
-void
-dsw_attach(int argc, char *argv[])
-{
-	overflow_file = argv[1];
-	argv[1] = argv[2];
-	(void) dsw_group_or_single_op(2, argv, attach);
-	exit(0);
-}
-
-/*ARGSUSED*/
-void
-dsw_olist(int argc, char *argv[])
-{
-	char	*sp, *overflow_list, **vol;
-	int	count, i;
-	ENTRY	item, *found;
-	char	key[ CFG_MAX_KEY ], buf[ CFG_MAX_BUF ];
-
-	overflow_list = get_overflow_list();
-
-	/* count entries */
-	count = 0;
-	for (sp = overflow_list; *sp; sp += DSW_NAMELEN) {
-		++count;
-	}
-
-	/* create hash (adding room for suspended overflow volumes) */
-	if (hcreate(count + 1024) == 0) {
-		dsw_error(gettext("Out of memory creating lookup table"), NULL);
-		/*NOTREACHED*/
-	}
-
-	if (count > 0) {
-		/* create memory to store copy of list */
-		vol = (char **)calloc(count, sizeof (char *));
-		if (!vol) {
-			dsw_error(
-			    gettext("Out of memory creating lookup table"),
-			    NULL);
-			/*NOTREACHED*/
-		}
-
-		/* fill hash */
-		for (i = 0, sp = overflow_list; *sp; sp += DSW_NAMELEN, i++) {
-
-			/* make copy of string */
-			vol[ i ] = (char *)malloc(DSW_NAMELEN + 1);
-			(void) strlcpy(vol[ i ], sp, DSW_NAMELEN);
-
-			item.key = vol[ i ];
-			item.data = (char *)0;
-			(void) hsearch(item, ENTER);
-		}
-	}
-
-	/* loop through config file entries */
-	i = 0;
-	cfg_rewind(cfg, CFG_SEC_CONF);
-
-	/*CONSTCOND*/
-	while (1) {
-		++i;
-		(void) snprintf(key, CFG_MAX_KEY, "ii.set%d.overflow", i);
-		if (cfg_get_cstring(cfg, key, buf, CFG_MAX_BUF) < 0) {
-			break;
-		}
-
-		/* has this set got an overflow volume? */
-		if (!*buf) {
-			continue;
-		}
-
-		/* look up overflow in hash */
-		item.key = buf;
-		if (count > 0 && (found = hsearch(item, FIND)) != NULL) {
-			if (0 == (int)found->data) {
-				(void) printf("%s\n", buf);
-				found->data = (char *)1;
-				(void) hsearch(*found, ENTER);
-			}
-		} else {
-			/* must be part of a suspended set */
-			(void) printf("%s (attached to suspended set)\n", buf);
-			item.key = buf;
-			item.data = (char *)1;
-			(void) hsearch(item, ENTER);
-		}
-	}
-
-	exit(0);
-}
-
-void
-dsw_ostat(int argc, char *argv[])
-{
-	dsw_ostat_t	args;
-	int	stat_flags;
-
-	if (argc != 2)
-		usage(gettext("Incorrect number of arguments"));
-
-	(void) strlcpy(args.overflow_vol, argv[1], DSW_NAMELEN);
-
-	args.status = spcs_s_ucreate();
-	if (do_ioctl(dsw_fd, DSWIOC_OSTAT2, &args) == -1)
-		dsw_error(gettext("Stat failed"), &args.status);
-	spcs_s_ufree(&args.status);
-
-	if ((args.hversion >= 1) && (args.hmagic == II_OMAGIC)) {
-		stat_flags = args.flags;
-		if (stat_flags & IIO_CNTR_INVLD)
-			(void) printf(gettext("Clean shutdown of volume "
-			"sets associated with overflow volume "
-			"did not occur.\n"
-			"Overflow counters will be inconsistent "
-			"until new point-in-time(s) are taken.\n"));
-	}
-	(void) printf(gettext("Total number of attached shadows: %d\n"),
-	    args.drefcnt);
-	(void) printf(gettext("Number of currently attached shadows: %d\n"),
-	    args.crefcnt);
-	(void) printf(gettext("Total number of chunks: %lld\n"), args.nchunks);
-	(void) printf(gettext("Number of chunks ever allocated: %lld\n"),
-	    args.used);
-	(void) printf(gettext("Number of used chunks: %lld\n"),
-	    (args.nchunks - args.unused));
-	(void) printf(gettext("Number of unused chunks: %lld\n"), args.unused);
-	exit(0);
-}
-
-/*ARGSUSED*/
-void
-dsw_move_2_group(int argc, char *argv[])
-{
-	dsw_config_t parms;
-	dsw_movegrp_t movegrp;
-	grptag_t *gdata;
-	int waserr = 0;
-
-	/* handle move to NULL group, or group of all spaces or tabs */
-	(void) strncpy(movegrp.new_group, group_name, DSW_NAMELEN);
-	if ((strlen(group_name) == 0) || (strcspn(group_name, " \t") == 0)) {
-		group_name = "-";
-		bzero(movegrp.new_group, DSW_NAMELEN);
-		gdata = NULL;
-	} else {
-		/* get the ctag for this group (if any) */
-		gdata = (grptag_t *)nsc_lookup(volhash, group_name);
-	}
-
-	movegrp.status = spcs_s_ucreate();
-
-	for (++argv; *argv; argv++) {
-		if (!find_shadow_config(*argv, &parms, NULL))
-			dsw_error(gettext("Volume is not in a Point-in-Time "
-			    "Copy group"), NULL);
-
-		/* ensure the ctag matches the group */
-		if (gdata && *gdata->ctag) {
-			if (strncmp(parms.cluster_tag, gdata->ctag,
-			    DSW_NAMELEN) != 0) {
-				(void) fprintf(stderr, "%s: %s %s %s\n", cmdnam,
-				    gettext("unable to move set"), *argv,
-				    gettext("into new group - cluster "
-				    "resource mismatch"));
-				waserr = 1;
-				continue;
-			}
-		}
-
-		/* move the set in the kernel */
-		(void) strncpy(movegrp.shadow_vol, parms.shadow_vol,
-		    DSW_NAMELEN);
-		if (do_ioctl(dsw_fd, DSWIOC_MOVEGRP, &movegrp) < 0)
-			dsw_error(gettext("Failed to move group in kernel"),
-			    NULL);
-
-		/* now update the config */
-		(void) sprintf(key, "ii.set%d.group", setnumber);
-		if (cfg_put_cstring(cfg, key, group_name,
-		    strlen(group_name)) < 0) {
-			perror("cfg_put_cstring");
-		}
-		(void) cfg_commit(cfg);
-	}
-	spcs_s_ufree(&movegrp.status);
-	cfg_close(cfg);
-	exit(waserr);
-}
-
-void
-dsw_list_groups()
-{
-	FILE *pfp;
-
-	if ((pfp = popen("/usr/bin/sort -u", "w")) == NULL) {
-		dsw_error(gettext("Can't open sort program"), NULL);
-	}
-
-	(void) fflush(stdout);
-	for (setnumber = 1; /*CSTYLED*/; setnumber++) {
-		(void) snprintf(key, sizeof (key), "ii.set%d.group", setnumber);
-		if (cfg_get_cstring(cfg, key, buf, sizeof (buf)) < 0)
-			break;
-
-		/* skip if shadow set is not in any group */
-		if (strcmp(buf, "") == 0)
-			continue;
-		(void) fprintf(pfp, "%s\n", buf);
-	}
-	(void) pclose(pfp);
-}
-
-void
-dsw_list_group_volumes()
-{
-	FILE *pfp;
-
-	if (find_group_members(group_name) < 1)
-		dsw_error(gettext("Group does not exist or has no members"),
-		    NULL);
-
-	if ((pfp = popen("/usr/bin/sort -u", "w")) == NULL) {
-		dsw_error(gettext("Can't open sort program"), NULL);
-	}
-
-	(void) fflush(stdout);
-	for (; *group_volumes; group_volumes++)
-		(void) fprintf(pfp, "%s\n", *group_volumes);
-	(void) pclose(pfp);
-}
-
-static void
-load_ii_vols(CFGFILE *cfg)
-{
-	int set, entries;
-	char *mst, *shd, *buf, **entry;
-	char *ctag, *group;
-	mstcount_t *mdata;
-	shdvol_t *sdata;
-	grptag_t *gdata;
-	static int whinged = 0;
-
-	if (volhash) {
-		return;
-	}
-
-	volhash = nsc_create_hash();
-	cfg_rewind(cfg, CFG_SEC_CONF);
-	entries = cfg_get_section(cfg, &entry, "ii");
-	for (set = 1; set <= entries; set++) {
-		buf = entry[set - 1];
-
-		/* grab master volume name */
-		mst = strtok(buf, " ");
-		if (!mst) {
-			free(buf);
-			break;
-		}
-
-		/* grab shadow, group & cnode fields */
-		shd = strtok(NULL, " ");
-		(void) strtok(NULL, " ");	/* bitmap */
-		(void) strtok(NULL, " ");	/* mode */
-		(void) strtok(NULL, " ");	/* overflow */
-		ctag = strtok(NULL, " ");	/* cnode */
-		(void) strtok(NULL, " ");	/* options */
-		group = strtok(NULL, " ");	/* group */
-
-		/* Fix optional tags */
-		if (ctag)
-			ctag += strspn(ctag, "-");
-		if (group)
-			group += strspn(group, "-");
-
-		/* If cluster tags don't match, skip record */
-		if ((cfg_cluster_tag && strcmp(ctag, cfg_cluster_tag)) ||
-		    (!cfg_cluster_tag && strlen(ctag))) {
-			free(buf);
-			continue;
-		}
-
-		/* master volume, may be duplicates */
-		mdata = (mstcount_t *)nsc_lookup(volhash, mst);
-		if (mdata) {
-			++mdata->count;
-		} else {
-			mdata = (mstcount_t *)malloc(sizeof (mstcount_t));
-			mdata->count = 1;
-			(void) nsc_insert_node(volhash, mdata, mst);
-		}
-
-		/* grab shadow volume name */
-		sdata = (shdvol_t *)malloc(sizeof (shdvol_t));
-		(void) strncpy(sdata->master, mst, DSW_NAMELEN);
-		(void) nsc_insert_node(volhash, sdata, shd);
-
-		/* No need to continue if no groups or ctags */
-		if (!group || !*group || !ctag || !*ctag) {
-			free(buf);
-			continue;
-		}
-
-		gdata = (grptag_t *)nsc_lookup(volhash, group);
-		if (gdata) {
-			/* group already exists - check ctag */
-			if (*ctag &&
-			    (strncmp(ctag, gdata->ctag, DSW_NAMELEN) != 0)) {
-				if (!whinged) {
-					(void) printf(gettext(
-					    "Warning: multiple "
-					    "cluster resource groups "
-					    "defined within a single "
-					    "I/O group\n"));
-					whinged = 1;
-				}
-			}
-		} else {
-			gdata = (grptag_t *)malloc(sizeof (grptag_t));
-			(void) strncpy(gdata->ctag, ctag, DSW_NAMELEN);
-			(void) nsc_insert_node(volhash, gdata, group);
-		}
-
-		free(buf);
-	}
-
-	/* free up any leftovers */
-	while (set < entries)
-		free(entry[set++]);
-	if (entries)
-		free(entry);
-}
-
-static void
-unload_ii_vols()
-{
-	nsc_remove_all(volhash, free);
-	volhash = 0;
-}
-
-static int
-perform_autosv()
-{
-	static int result;
-	static int calculated = 0;
-	int rc;
-
-#ifdef DEBUG
-	if (getenv("II_SET_CLUSTER"))
-		return (1);
-#endif
-
-	if (calculated) {
-		return (result);
-	}
-
-	/*
-	 * we only perform auto-sv if we're in a sun cluster or if
-	 * we're on a standalone system.  I.e. we don't do auto-sv on Harry
-	 */
-	rc = check_cluster();
-
-	if (II_NOT_CLUSTER == rc) {
-		result = 1;
-	} else {
-		result = cfg_issuncluster();
-	}
-
-	calculated = 1;
-	return (result);
-}
-
-/*
- * Returns true if set has had the shadow volume exported.
- * Returns false if shadow volume is not exported, or set is suspended.
- */
-static int
-is_exported(char *set)
-{
-	dsw_stat_t args;
-	int rc;
-
-	(void) strlcpy(args.shadow_vol, set, DSW_NAMELEN);
-	args.status = spcs_s_ucreate();
-
-	rc = do_ioctl(dsw_fd, DSWIOC_STAT, &args);
-	spcs_s_ufree(&args.status);
-
-	if (-1 == rc) {
-		/* set must be suspended, or being disabled */
-		return (0);
-	}
-
-	return ((args.stat & DSW_SHDEXPORT) == DSW_SHDEXPORT);
-}
-
-static void
-conform_name(char **path)
-{
-	char *cfgname;
-	int rc = cfg_get_canonical_name(cfg, *path, &cfgname);
-
-	if (rc < 0) {
-		dsw_error(gettext("Unable to parse config file"), NULL);
-	}
-	if (rc) {
-		(void) printf("  '%s'\n%s\n  '%s'\n", *path,
-		    gettext("is currently configured as"), cfgname);
-		check_action(gettext("Perform operation with indicated volume"
-		    " name?"));
-		*path = cfgname;
-		/*
-		 * NOTE: *path ought to be deallocated ('free(*path)') after
-		 * we're done with it, but since this routine is called just
-		 * before we exit, it doesn't really matter
-		 */
-	}
-}
-
-/*
- * verify_groupname(char *, int);
- *
- * Check the group name for the following rules:
- *	1. The name does not start with a '-'
- *	2. The name does not contain any space characters as defined by
- *	   isspace(3C).
- * If either of these rules are broken, error immediately. The check for a
- * leading dash can be skipped if the 'testDash' argument is false. This is to
- * allow for the '-g -L' functionality.
- *
- */
-static void
-verify_groupname(char *grp, int testDash)
-{
-	int i;
-
-	if (testDash && grp[0] == '-') {
-		errno = EINVAL;
-		dsw_error(gettext("group name cannot start with a '-'"), NULL);
-	}
-
-	for (i = 0; grp[i] != '\0'; i++) {
-		if (isspace(grp[i])) {
-			errno = EINVAL;
-			dsw_error(gettext("group name cannot contain a space"),
-			    NULL);
-		}
-	}
-}
-
-void
-check_iishadow(char *shadow_vol) {
-	int i;
-	int entries;
-	char **entry;
-	char *shost;
-	char *svol;
-	char *buf;
-	void *librdc;
-
-	/*
-	 * See if librdc is around
-	 * If not, we can just return
-	 */
-	if (librdc = dlopen(RDC_LIB, RTLD_LAZY | RTLD_GLOBAL))
-		self_check = (int (*)(char *)) dlsym(librdc, "self_check");
-	else {
-		return;
-	}
-
-	entry = NULL;
-	entries = cfg_get_section(cfg, &entry, "sndr");
-	for (i = 0; i < entries; i++) {
-		buf = entry[i];
-
-		(void) strtok(buf, " ");	/* phost */
-		(void) strtok(NULL, " ");	/* primary */
-		(void) strtok(NULL, " ");	/* pbitmap */
-		shost = strtok(NULL, " ");	/* shost */
-		svol = strtok(NULL, " ");	/* secondary */
-
-		if (self_check(shost) && (strcmp(shadow_vol, svol) == 0)) {
-			free(buf);
-			if (entries)
-				free(entry);
-			errno = EINVAL;
-			dsw_error(gettext(
-			    "shadow volume is in use as SNDR secondary volume"),
-			    NULL);
-		}
-		free(buf);
-	}
-
-	(void) dlclose(librdc);
-	if (entries)
-		free(entry);
-}
