/*  swinstall.c -- The swbis swinstall utility.  */
/*
   Copyright (C) 2004, 2005, 2006 Jim Lowe
   All Rights Reserved.
  
   COPYING TERMS AND CONDITIONS:
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2, or (at your option)
   any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */

#define FILENEEDDEBUG 1
#undef FILENEEDDEBUG
#include "swuser_config.h"
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "vplob.h"
#include "swlib.h"
#include "usgetopt.h"
#include "ugetopt_help.h"
#include "swinstall.h"
#include "swparse.h"
#include "swfork.h"
#include "swgp.h"
#include "swssh.h"
#include "progressmeter.h"
#include "swevents.h"
#include "swicol.h"
#include "swutillib.h"
#include "swmain.h"

#define PROGNAME		"swinstall"
#define SW_UTILNAME		PROGNAME
#define SWPARSE_AT_LEVE		0
#define SWPROG_VERSION 		SWINSTALL_VERSION
#define VERBOSE_LEVEL2		2
#define VERBOSE_LEVEL3		3
#define LCEXIT(arg)		lc_exit(__FILE__, __LINE__, arg)
#define LC_RAISE(arg)		lc_raise(__FILE__, __LINE__, arg)

#define LOCAL_RSH_BIN 			"rsh"
#define REMOTE_RSH_BIN 			"rsh"
#define LOCAL_SSH_BIN 			"ssh"
#define REMOTE_SSH_BIN 			"ssh"

#define WOPT_LAST				197
#define MAX_CONTROL_MESG_LEN			2000
#define SWC_PID_ARRAY_LEN			30

#define SWINSTALL_DO_SOURCE_CTL_MESSAGE	(swinstall_mode && local_stdin == 0)
#define SWBIS_SWINSTALL_SOURCE_CTL_ARCHIVE	"130 source is from archive"
#define SWBIS_SWINSTALL_SOURCE_CTL_DIRECTORY "140 source is from directory"
#define DEFAULT_PUMP_DELAY	10111000	/* 1/100th sec */
#define DEFAULT_BURST_ADJUST	72000		/* similar to OpenSSH rcvd adjust ??? */
		
static int g_stdout_testfd = -1;
static int g_fail_loudly = -1; 	/* Set to 0 to turn off failure messages. */
static int g_verboseG = 1;  	/* Default posix verbosity. */
static int g_signal_flag = 0;
static int g_t_efd = -1;
static int g_s_efd = -1;
static pid_t g_logger_pid;
static int g_swevent_fd = -1;

static FILE * vstderr;
static STROB * gbuf = NULL;
static char * CHARTRUE = "True";
static char * CHARFALSE = (char*)NULL;
static char progName[] = PROGNAME;
static pid_t g_pid_array[SWC_PID_ARRAY_LEN + SWC_PID_ARRAY_LEN];
static int g_status_array[SWC_PID_ARRAY_LEN];
static int g_targetfd_array[SWC_TARGET_FD_ARRAY_LEN];
static int g_selectfd_array[SWC_TARGET_FD_ARRAY_LEN];

static struct timespec g_io_req;
static SHCMD * g_target_kmd = (SHCMD*)NULL;
static SHCMD * g_source_kmd = (SHCMD*)NULL;
static SHCMD * g_killcmd = (SHCMD*)NULL;
static int g_pid_array_len = 0;
static int g_nullfd;
static int g_stderr_fd;
static int * g_target_fdar;
static int * g_source_fdar;
static char * g_fork_pty 		= SWFORK_PTY;
static char * g_fork_pty2 		= SWFORK_PTY2;
static char * g_fork_pty_none		= SWFORK_NO_PTY;
static sigset_t g_fork_defaultmask;
static sigset_t g_fork_blockmask;
static sigset_t g_currentmask;
static int g_do_progressmeter = 0;
static struct swEvents * g_evnt = eventsArray;
static struct sw_logspec g_logspec = {-1, 0, -1/* FIXME this is also fail_loudly */};
static int g_loglevel = 0;
static int g_meter_fd = STDOUT_FILENO;
static XFORMAT * g_xformat = NULL;
static int g_swi_event_fd;
static SWUTIL * g_swutil;

int get_stderr_fd(void);

static
void
gf_xformat_close(XFORMAT * xformat)
{
	if (xformat) xformat_close(xformat);
	g_xformat = NULL;
}

/* static */
int
get_stderr_fd(void)
{
	return g_stderr_fd;
}

static
void
shutdown_logger(int signum)
{
	int status;	
	if (kill(g_logger_pid, signum) < 0) {
		fprintf(stderr, "%s: kill(2): %s\n",
			swlib_utilname_get(), strerror(errno));
	}
	if (g_swevent_fd >= 0) close(g_swevent_fd);
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
			&g_logspec, get_stderr_fd(), 
			"waitpid() on logger_pid [%d]\n", g_logger_pid);
	waitpid(g_logger_pid, &status, 0);
	close(g_t_efd);
	close(g_s_efd);
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
			&g_logspec, get_stderr_fd(), 
			"finished waitpid() on logger_pid [%d]\n", g_logger_pid);
}

static
void
set_stderr_fd(int fd)
{
	g_stderr_fd = fd;
	swutil_set_stderr_fd(g_swutil, fd);
}

#include "pax_commands.h"

static
int
is_option_true(char * s)
{
	if (!s || strcasecmp(s, CHARTRUE)) return 0;
	return 1;  
}

static
void 
lc_raise(char * file, int line, int signo)
{
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(), 
				"raising signal %d at %s:%d\n",
						signo, file, line);
	g_signal_flag = signo;
	raise(signo);
}

static
void 
lc_exit(char * file, int line, int status)
{
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(), 
				"exiting at %s:%d with value %d\n",
							file, line, status);
	exit(status);
}

static 
void 
version_string(FILE * fp)
{
	fprintf(fp,  
"%s (swbis) version " SWINSTALL_VERSION "\n",
		progName);
}

static
void 
version_info(FILE * fp)
{
	version_string(fp);
	/* fprintf(fp,  "\n"); */
	swc_copyright_info(fp);
}

static
int 
usage(FILE * fp, 
		char * pgm, 
		struct option  lop[], 
		struct ugetopt_option_desc helpdesc[])
{
	
fprintf(fp, "%s",
"swinstall installs a directory or serial archive\n"
"to a target location.  The source and target may be different hosts.\n"
"A source distribution must be a valid posix package.\n"
);
	
	fprintf(fp, "%s",
"\n"
"Usage: swinstall [-p] [-r] [-f file] [-s source] [-x option=value]\\\n"
"      [-X options_file] [-W option[=value]] [-t targetfile] [-c catalog]\\\n"
"      [impl_specific_options] [software_selections][@target]\n"
);

fprintf(fp, "%s",
"\n"
"Options:\n"
);
	ugetopt_print_help(fp, pgm, lop, helpdesc);

fprintf(fp , "%s",
"\n"
"Implementation Extension Options:\n"
"       Syntax : -W option[=option_argument] [-W ...]\n"
"           or   -W option[=option_argument],option...\n"
"           or   --option[=option_argument]\n"
"   noop       Legal option with no effect\n"
"   show-options  Show the extended options and exit\n"
"   show-options-files   Show the options files that will be parsed.\n"
"   pax-command={tar|pax|star|gtar}\n"
"   pax-read-command={tar|pax|star|gtar}\n"
"   local-pax-read-command={tar|pax|star|gtar}\n"
"   remote-pax-read-command={tar|pax|star|gtar}\n"
"              pax  = \"pax -r\"\n"
"              star = \"star xpUf -\"\n"
"              tar  = \"tar xpf -\"\n"
"              gtar = \"tar xpf - --overwrite\"\n"
"   pax-write-command={tar|pax|star|gtar}\n"
"   local-pax-write-command={tar|pax|star|swbistar}\n"
"   remote-pax-write-command={tar|pax|star|swbistar}\n"
"              pax  = \"pax -w\"\n"
"              star = \"star cf - -H ustar\"\n"
"              tar  = \"tar cf -\"\n"
"              gtar = \"gtar cf -\"\n"
"              swbistar = \"" SWBISLIBEXECDIR "/swbis/swbistar\"\n"
" 	The default is \"tar\"\n"
"   no-pty      Disable pseudo-tty allocation.\n"
"   remote-shell=NAME  NAME is the client \"rsh\" or \"ssh\"(default).\n"
"   quiet-progress      disable progress bar.\n"
"   show-progress-bar   enable progress bar.\n"
"   no-defaults  Do not read any defaults files.\n"
"   no-remote-kill  Do not execute a kill command. Normally a kill command\n"
"               is issued when signals TERM, PIPE, and INT are received for\n"
"               targets where nhops > 1.\n"
"   no-getconf  Don't use the getconf utility to set the PATH variable on the\n"
"               target host. This sets the remote command to be '/bin/sh -s'\n"
"               instead of the default \"PATH=`getconf PATH` sh -s\"\n"
"   use-getconf  This causes getconf to be used.  Opposite to --no-getconf.\n"
"   progress-bar-fd={1|2}  1 (stdout) is the default\n"
"   shell-command={posix|sh|bash|ksh}  posix is the default\n"
"   allow-rpm   Allow installation of RPM format packages.\n"
"   preview-tar-file=FILE  Writes the actual fileset archive to FILE.\n"
"   ssh-options=options  Single letter ssh options. e.g. --ssh-options=1\n"
"   debug-events  Show the internal events listing to stderr\n"
"   pump-delay1=NANOSECONDS Adds delay every burst adjust bytes.\n"
"                           Default is 1/100th sec for 2-hop targets.\n"
"   burst-adjust=SIZE  default is 72000 (for 2-hop targets)\n"
"   to-stdout   write the payload to stdout in the form of a tar archive\n"
"\n"
);

fprintf(fp, "%s",
"\n"
"Target Syntax:\n"
);

	fprintf(fp, "%s",
"   software_selections   Refer to the software objects (products, filesets)\n"
"                         on which to be operated. (Not yet implemented)\n"
"   target    Refers to the software_collection where the software\n"
"             selections are to be applied.\n"
"             Target follows syntax of Section 4.1.4.2 (Source and Target\n"
"             Specification and Logic) summarized as follows:\n"
"\n"
"       target : HOST_CHARACTER_STRING ':' PATHNAME_CHARACTER_STRING\n"
"              | HOST_CHARACTER_STRING ':'\n"
"              | HOST_CHARACTER_STRING \n"
"              | PATHNAME_CHARACTER_STRING \n"
"              ; \n"
"\n"
"       PATHNAME_CHARACTER_STRING must be an absolute path unless the\n"
"                                 target has a HOST_CHARACTER_STRING\n"
"                                 in which case it may be a relative path.\n"
"       HOST_CHARACTER_STRING is an IP or hostname or '-'\n"
"          NOTE: A '-' indicating standard output is an implementation\n"
"                    extension.\n"
);

fprintf(fp , "%s",
"\n"
"Implementation Extension Target Syntax:\n"
"    Syntax:\n"
"    %start   xtarget    # the Implementation Extension Target\n"
"    xtarget   : xtarget DELIM sshtarget\n"
"              | sshtarget\n"
"              ; \n"
"    sshtarget : user '@' target\n"
"              | target\n"
"              | user '@'\n"
"    DELIM     : @@\n"
"\n"
);

fprintf(fp, "%s",
"\n"
"Posix Extended Options:\n"
"        File : <libdir>/swbis/swdefaults\n"
"               ~/.swdefaults\n"
"        Override values in defaults file.\n"
"        Command Line Syntax : -x option=option_argument [-x ...]\n"
"            or : -x \"option=option_argument  ...\"\n"
"   allow_downdate              = false      # Not Implemented\n"
"   allow_incompatible          = false      # Not Implemented\n"
"   ask                         = false      # Not Implemented\n"
"   autoreboot                  = false      # Not Implemented\n"
"   autorecover                 = false      # Not Implemented\n"
"   autoselect_dependencies     = false      # Not Implemented\n"
"   defer_configure             = false      # Not Implemented\n"
"   distribution_source_directory   = -	     # Stdin\n"
"   enforce_dependencies        = false      # Not Implemented\n"
"   enforce_locatable           = false      # Not Implemented\n"
"   enforce_scripts             = false      # Not Implemented\n"
"   enforce_dsa                 = false      # Not Implemented\n"
"   installed_software_catalog  = var/lib/swbis/catalog\n"
"   logfile                     = /var/log/swinstall.log\n"
"   loglevel                    = 0\n"
"   reinstall                   = false      # Not Implemented\n"
"   select_local		= false      # Not Implemented\n"
"   verbose			= 1\n"
"\n"
"Swbis Extended Options:\n"
"        File : <libdir>/swbis/swbisdefaults\n"
"               ~/.swbis/swbisdefaults\n"
"        Command Line Syntax : -x option=option_argument\n"
"  swinstall.swbis_no_getconf		 = false # getconf is used\n"
"  swinstall.swbis_shell_command	 = posix\n"
"  swinstall.swbis_no_remote_kill	 = false\n"
"  swinstall.swbis_quiet_progress_bar       = true\n"
"  swinstall.swbis_local_pax_write_command  = pax\n"
"  swinstall.swbis_remote_pax_write_command = pax\n"
"  swinstall.swbis_local_pax_read_command   = pax\n"
"  swinstall.swbis_remote_pax_read_command  = pax\n"
"  swinstall.swbis_enforce_sig              = false\n"
"  swinstall.swbis_enforce_file_md5         = false\n"
"  swinstall.swbis_allow_rpm                = false\n"
"  swinstall.swbis_remote_shell_client	    = ssh\n"
"  swinstall.swbis_install_volatile	    = true\n"
"  swinstall.swbis_volatile_newname	    =   # empty string\n"
"\n"
"Examples:\n"
"  Verbosely preview the installed files:\n"
"     swinstall -p -x verbose=5\n"
"  Install a package to three hosts\n"
"     swinstall @ host1 host2 host3\n"
"  Use some extension features to translate an RPM:\n"
"     swinstall -p -s - --allow-rpm -x verbose=1 --preview-tar-file=- | tar tvf -\n"
"  Use some extension features to write the archive to be installed:\n"
"  to stdout:\n"
"     swinstall --to-stdout -s - | tar tvf -\n"
" or  swinstall -s - @- | tar tvf -\n"
);


fprintf(fp , "%s", "\n");
	version_string(fp);
	fprintf(fp , "\n%s", 
        "Report bugs to " REPORT_BUGS "\n");
	return 0;
}

static
char *
get_pax_read_command(char * keyid, int verbose_level, 
			int keep, char * paxdefault)
{
	int i = 0;
	char * id;
	struct g_pax_read_command * readcmd;
	
	if (! keyid) return NULL;

	if (strlen(keyid) == 0) {
		return get_pax_read_command(
				DEFAULT_PAX_R, 
				verbose_level, keep, DEFAULT_PAX_R);
	}
	readcmd = &(g_pax_read_commands[i]);
	id = readcmd->idM;
	while (id) {
		if (strcmp(keyid, id) == 0) {
			if (keep) return readcmd->keep_commandM;
			if (verbose_level == 0) return readcmd->commandM;
			return readcmd->verbose_commandM;
		}
		i++;
		readcmd = &(g_pax_read_commands[i]);
		id = readcmd->idM;
	}
	return get_pax_read_command(paxdefault, 
				verbose_level, keep, DEFAULT_PAX_R);
}

static
char *
get_pax_write_command(char * keyid, char * paxdefault)
{
	int i = 0;
	char * id;
	struct g_pax_write_command * writecmd;

	if (! keyid) return NULL;
	
	if (strlen(keyid) == 0) {
		return get_pax_write_command(DEFAULT_PAX_W, 
						DEFAULT_PAX_W);
	}
	writecmd = &(g_pax_write_commands[i]);
	id = writecmd->idM;
	while (id) {
		if (strcmp(keyid, id) == 0) return writecmd->commandM;
		i++;
		writecmd = &(g_pax_write_commands[i]);
		id = writecmd->idM;
	}
	return get_pax_write_command(paxdefault, 
					DEFAULT_PAX_W);
}

static
int
sw_exitval(int count, int suc)
{
	if (suc && count == suc) return 0;
	if (suc && count) return 2;
	if (suc == 0) return 1;
	swlib_doif_writef(g_verboseG, g_fail_loudly,
			&g_logspec, get_stderr_fd(),
			"abnormal exit\n");
	return 255;
}

static
void
tty_raw_ctl(int c)
{
	static int g = 0;
	if (c == 0) {
		g = 0;
	} else if (c == 1) {
		g = 1;
	} else {
		if (g) {
		g = 0;
		if (swlib_tty_raw(STDIN_FILENO) < 0)
			swlib_doif_writef(g_verboseG, g_fail_loudly, 
				&g_logspec, get_stderr_fd(), "tty_raw error");
		}
	}
}

static
void
safe_sig_handler(int signum)
{
	switch(signum) {
		case SIGTERM:
			if (g_do_progressmeter) alarm(0);
			swlib_doif_writef(g_verboseG,
					SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(), 
							"Caught SIGTERM\n");
			g_signal_flag = signum;
			break;
		case SIGINT:
			if (g_do_progressmeter) alarm(0);
			swlib_doif_writef(g_verboseG,
				SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(), 
						"Caught SIGINT\n");
			g_signal_flag = signum;
			break;
		case SIGPIPE:
			if (g_do_progressmeter) alarm(0);
			swlib_doif_writef(g_verboseG,
				SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(), 
						"Caught SIGPIPE\n");
			g_signal_flag = signum;
			break;
	}
}

static
void
main_sig_handler(int signum)
{
	int fd;
	int loggersig = SIGABRT;
	switch(signum) {
		case SIGTERM:
		case SIGINT:
		case SIGPIPE:
			swlib_doif_writef(g_verboseG,
				SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(),
					"Executing handler for signal %d.\n",
					 signum);
			g_signal_flag = 0;
			if (g_do_progressmeter) alarm(0);
			swgp_signal_block(SIGTERM, (sigset_t *)NULL);
			swgp_signal_block(SIGINT, (sigset_t *)NULL);
			/* swgp_signal_block(SIGPIPE, (sigset_t *)NULL); */
			swlib_tty_atexit();
			fd = g_target_fdar[0]; if (fd >= 0) close(fd);
			fd = g_target_fdar[1]; if (fd >= 0) close(fd);
			fd = g_source_fdar[0]; if (fd >= 0) close(fd);
			fd = g_source_fdar[1]; if (fd >= 0) close(fd);
			gf_xformat_close(g_xformat);
			swlib_kill_all_pids(g_pid_array + SWC_PID_ARRAY_LEN, 
						g_pid_array_len, 
						SIGTERM, 
						g_verboseG);
			swlib_wait_on_all_pids(g_pid_array, 
						g_pid_array_len, 
						g_status_array, 
						0, 
						g_verboseG);
			shutdown_logger(loggersig);
			switch(signum) {
				case SIGTERM:
				case SIGINT:
					/* FIXME per spec */
					LCEXIT(SW_FAILED_ALL_TARGETS); 
					break;
			}
			break;
	}
}

static
void
check_for_current_signals(int lineno, int signum,
			int verbose_level, char * no_remote_kill)
{
	switch(signum) {
		case SIGTERM:
		case SIGPIPE:
		case SIGINT:
			swlib_doif_writef(g_verboseG,
				SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(),
			"check_for_current_signals: line=%d Got signal %d.\n",
					 	lineno, signum);
			swgp_signal_block(SIGTERM, (sigset_t *)NULL);
			swgp_signal_block(SIGINT, (sigset_t *)NULL);
			swgp_signal_block(SIGPIPE, (sigset_t *)NULL);
			if (!is_option_true(no_remote_kill)) {
				swc_do_run_kill_cmd((SHCMD*)(NULL), 
						g_target_kmd, 
						g_source_kmd, 
						verbose_level);
			} else {
				swlib_doif_writef(g_verboseG, 
						SWC_VERBOSE_IDB,
						&g_logspec, get_stderr_fd(),
			"check_for_current_signals:  not running kill cmds.\n");
			}
			main_sig_handler(signum);
			break;
	}
}

static
void
set_boolean_x_option(struct extendedOptions * opta, 
		enum eOpts nopt, 
		char * arg, 
		char ** optionp)
{
	if (strcasecmp(arg, "true") == 0) {
		*optionp = "true";
	} else {
		*optionp = "false";
	}
	set_opta(opta, nopt, *optionp);
}

static
int
swc_write_source_copy_script(
	int ofd, 
	char * sourcepath, 
	int do_get_file_type, 
	int vlv,
	int delaytime,
	int nhops,
	char * pax_write_command_key,
	char * hostname,
	char * blocksize
	)
{
	int ret;
	char * dirname, *path;
	char * pax_write_command;
	STROB * buffer, *opt1, *opt2;
	STROB * subsh, *subsh2;
	STROB * tmp;
	STROB * tmp1;
	STROB * tmp2;
	STROB * set_vx;
	STROB * to_devnull;

	/*
	 * error for source script is >0
	 */
	if (strstr(sourcepath, "..") == sourcepath) { return 1; }
	if (strstr(sourcepath, "../")) { return 1; }
	if (swlib_is_sh_tainted_string(sourcepath)) { return 1; }
	/*
	 * Squash the trailing slash.
	 */
	swlib_squash_double_slash(sourcepath);
	if (strlen(sourcepath) > 1) {
		if (sourcepath[strlen(sourcepath) - 1] == '/' ) {
			sourcepath[strlen(sourcepath) - 1] = '\0';
		}
	}

	buffer = strob_open(1);
	to_devnull = strob_open(10);
	opt1 = strob_open(1);
	opt2 = strob_open(1);
	set_vx = strob_open(10);
	tmp = strob_open(10);
	tmp1 = strob_open(10);
	tmp2 = strob_open(10);
	subsh = strob_open(10);
	subsh2 = strob_open(10);

	if (vlv >= SWC_VERBOSE_SWIDB) {
		strob_strcpy(set_vx, "set -vx\n");
	}
	
	if (vlv <= SWC_VERBOSE_4) {
		strob_strcpy(to_devnull, "2>/dev/null");
	}
	
	swlib_dirname(tmp, sourcepath);
	dirname = strdup(strob_str(tmp));

	swlib_basename(tmp, sourcepath);
	path = strdup(strob_str(tmp));

	if (do_get_file_type) {
		if (strchr(path, '\n') || 
			strlen(path) > MAX_CONTROL_MESG_LEN - 
				strlen(SWBIS_SWINSTALL_SOURCE_CTL_ARCHIVE ":")
		) {
			/*
			 * Too long, or path Contains a newline char.
			 */
			return 1;
		}
		/*
		 * this is the control message.
		 */
		strob_sprintf(opt1, 0, 
		"echo " SWBIS_SWINSTALL_SOURCE_CTL_ARCHIVE ": %s",
			path
			);
		strob_sprintf(opt2, 0, 
		"echo " SWBIS_SWINSTALL_SOURCE_CTL_DIRECTORY ": %s",
			 path
			);
	}
	
	pax_write_command = get_pax_write_command(pax_write_command_key,
						DEFAULT_PAX_W);

	if (swlib_is_sh_tainted_string(path)) { return 1; }
	if (swlib_is_sh_tainted_string(dirname)) { return 1; }

	if (
		strcmp(path, "/") == 0 &&
		strcmp(dirname, "/") == 0
	) {
		free(path);
		path = strdup(".");	
	}

	strob_sprintf(tmp1, 0, "%s", path),
	strob_sprintf(tmp2, 0, "%s", sourcepath),
	ret = swlib_writef(ofd, buffer, 	
		"echo " SWBIS_TARGET_CTL_MSG_125 ": " KILL_PID "\n"
		"%s\n"
		"%s"
		"%s"
		"blocksize=\"%s\"\n"
		"dirname=\"%s\"\n"
		"path=\"%s\"\n"
		"sourcepath=\"%s\"\n"
		"sw_retval=0\n"
		"sb__delaytime=%d\n"

		"if test -d \"$dirname\"; then\n"
		"	cd \"$dirname\"\n"
		"	sw_retval=$?\n"
		"	case $sw_retval in\n"
		"	0)\n"
		"	if test -d \"$path\" -a -r \"$path\"; then\n"
				"\t\t%s\n"
				"\t\t%s\n"
				"\t\t%s\n"
		"		%s \"$path\"\n"
		"		sw_retval=$?\n"
				"\t\t%s\n"
		"	elif test -e \"$path\" -a -r \"$path\"; then\n"
				"\t\t%s\n"
				"\t\t%s\n"
				"\t\t%s\n"
		"		dd ibs=\"$blocksize\" obs=512 if=\"$path\" %s;\n"
		"		sw_retval=$?\n"
				"\t\t%s\n"
		"	else\n"
				"\t\t%s\n"
				"\t\t%s\n"
		"		sw_retval=1\n"
		"	fi\n"
		"	;;\n"
		"	*)\n"
			"\t\t%s\n"
			"\t\t%s\n"
		"	;;\n"
		"	esac\n"

		"elif test -e \"$sourcepath\" -a -r \"$sourcepath\"; then\n"
			"\t%s\n"
			"\t%s\n"
			"\t%s\n"
		"	dd ibs=\"$blocksize\" obs=512 if=\"$sourcepath\" %s;\n"
		"	sw_retval=$?\n"
			"\t%s\n"

		"else\n"
			"\t%s\n"
			"\t%s\n"
		"	sw_retval=1\n"
		"fi\n"

		"if test \"$sw_retval\" != \"0\"; then\n"
		"	 sb__delaytime=0;\n"
		"fi\n"
		"sleep \"$sb__delaytime\"\n"
		"%s\n"
		"%s\n"
			,
		SEVENT(2, vlv, SW_SESSION_BEGINS, ""),
		swicol_subshell_marks(subsh, "source", 'L', nhops, vlv),	
		strob_str(set_vx),
		blocksize,
		dirname,
		path,
		sourcepath,
		delaytime,
		strob_str(opt2),
		SEVENT(1, -1, SW_SOURCE_ACCESS_BEGINS, ""),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_BEGINS, ""),
		pax_write_command,
		SEVENT(2, vlv, SW_SOURCE_ACCESS_ENDS, "status=0"),
		strob_str(opt1),
		SEVENT(1, -1, SW_SOURCE_ACCESS_BEGINS, ""),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_BEGINS, ""),
		strob_str(to_devnull),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_ENDS, "status=0"),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_ERROR, strob_str(tmp1)),
		SEVENT(1, -1, SW_SOURCE_ACCESS_ERROR, strob_str(tmp1)),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_ERROR, strob_str(tmp1)),
		SEVENT(1, -1, SW_SOURCE_ACCESS_ERROR, strob_str(tmp1)),
		strob_str(opt1),
		SEVENT(1, -1, SW_SOURCE_ACCESS_BEGINS, ""),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_BEGINS, ""),
		strob_str(to_devnull),
		SEVENT(2, vlv, SW_SOURCE_ACCESS_ENDS, "status=0"),
		SEVENT(2, vlv,  SW_SOURCE_ACCESS_ERROR, strob_str(tmp2)),
		SEVENT(1, -1, SW_SOURCE_ACCESS_ERROR, strob_str(tmp2)),
		SEVENT(2, vlv, SW_SESSION_ENDS, "status=$sw_retval"),
		swicol_subshell_marks(subsh2, "source", 'R', nhops, vlv)
		);

	free(path);
	free(dirname);
	strob_close(tmp);
	strob_close(tmp1);
	strob_close(tmp2);
	strob_close(buffer);
	strob_close(opt1);
	strob_close(opt2);
	strob_close(set_vx);
	strob_close(to_devnull);
	strob_close(subsh);
	strob_close(subsh2);
	/*
	 * 0 is OK
	 * !0 is error
	 */
	return !(ret > 0);
}

static
int
read_target_ctl_message(int fd, STROB * control_message, 
				int vlevel, char * loc)
{
	int n;
	char c[2];
	int count = 0;

	strob_strcpy(control_message, "");
	c[1] = '\0';
	n = read(fd, (void*)&c, 1);
	if (n == 1) count++;
	while (n == 1 && c[0] != '\n' && count < MAX_CONTROL_MESG_LEN) {
		strob_strcat(control_message, c);
		n = read(fd, (void*)&c, 1);
		if (n == 1) count ++;
	}
	swlib_doif_writef(vlevel, SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(),
		"%s control message: %s\n", 
			loc, strob_str(control_message));
	if (n == 1 && count == 1) { 
		return 0;
	} else if (n == 1 && count < MAX_CONTROL_MESG_LEN) {
		return count;
	} else {
		return -1;
	}
}

static
int
get_catalog_path(STROB * control_message,
	char * installed_software_catalog)
{
	char * s;
	char * p;
	char * isc;

	s = strstr(strob_str(control_message),
		SWBIS_TARGET_CTL_MSG_128);
	if (!s) return -2;
	s = strchr(strob_str(control_message), ':');
	if (!s) return -3;
	s++;
	while(*s == ' ') s++;
	while(*s == '/') s++;

	if (*installed_software_catalog == '/')
		isc = installed_software_catalog + 1;
	else
		isc = installed_software_catalog;

	if (strstr(s, isc) != s) {
		return -4;
	}

	p = strob_str(control_message);
	memmove(p, s, strlen(s) + 1);
	return 0;
}

static
char *
get_target_script_pid(STROB * control_message)
{
	char *s;
	char *p;
	char *ed;
	char *ret;

	s = strob_str(control_message);
	p = strstr(s, SWBIS_TARGET_CTL_MSG_125);
	if (!p)
		return (char*)NULL;
	if (p != s)
		return (char*)NULL;
	p+=strlen(SWBIS_TARGET_CTL_MSG_125);
	if (*p != ':')
		return (char*)NULL;
	p++;
	if (*p != ' ')
		return (char*)NULL;
	p++;
	ret = strdup(p);
	if ((ed=strpbrk(ret, "\n\r"))) *ed = '\0';
	return ret;
}

static
int
read_catalog_ctl_message(int fd,
	STROB * control_message, 
	int vlevel, 
	char * loc,
	char * installed_software_catalog)
{
	int ret = 0;
	strob_strcpy(control_message, "");

	while(ret >= 0 &&
		strstr(strob_str(control_message),
			SWBIS_TARGET_CTL_MSG_128) == (char*)NULL
	) {
		ret = read_target_ctl_message(fd,
					control_message,
					vlevel,
					loc);
	}
	if (ret < 0) {
		return ret;
	} 
	ret = get_catalog_path(control_message, installed_software_catalog);
	return ret;
}

static
int
read_start_ctl_message(int fd, 
	STROB * control_message, 
	STRAR * tramp_list, 
	int vlevel, 
	char ** pscript_pid, 
	char * loc)
{
	int ret = 0;
	strob_strcpy(control_message, "");

	while(ret >= 0 &&
		strstr(strob_str(control_message), SWBIS_TARGET_CTL_MSG_125) == 
							(char*)NULL
	) {
			ret = read_target_ctl_message(fd, 
						control_message, 
						vlevel, 
						loc);
			if (ret >= 0 && strob_strlen(control_message))
				strar_add(tramp_list, 
					strob_str(control_message));
	}
	if (ret < 0) {
		return ret;
	} 
	*pscript_pid = get_target_script_pid(control_message);
	if (*pscript_pid == (char*)NULL) {
		/*
		 * allow this to be OK, A NetBSD PATH=`getconf PATH` sh
		 * did not support $PPID. Use of the PPID is only needed for
		 * multiple ssh-hops, and maybe it shouldn't be needed at all.
		 */
		ret = 0;
	} else {
		swlib_doif_writef(vlevel, SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(),
			"remote script pid: %s\n", *pscript_pid);
		
	}
	return ret;
}

static
pid_t
run_target_script(
		int target_pipe,
		char * source_path,
		char * target_path,
		STROB * source_control_message,
		int keep_old_files,
		int nhops,
		char * pax_read_command_key,
		sigset_t *fork_blockmask,
		sigset_t *fork_defaultmask,
		char * hostname,
		char * blocksize,
		SWI_DISTDATA * distdata,
		char * installed_software_catalog,
		int opt_preview,
		char * sh_dash_s,
		int alt_catalog_root
		) 
{
	pid_t write_pid;

	write_pid = swndfork(fork_blockmask, fork_defaultmask);
	if (write_pid == 0) {
		int ret_target = 1;
		/*
		 * Write the target scripts.
		 */
		ret_target = swinstall_write_target_install_script(
			target_pipe, 
			target_path,
			source_control_message,
			source_path, 
			SWC_SCRIPT_SLEEP_DELAY, 
			keep_old_files, 
			nhops, 
			g_verboseG,
			pax_read_command_key,
			hostname,
			blocksize,
			distdata,
			installed_software_catalog,
			opt_preview,
			sh_dash_s, alt_catalog_root, &g_logspec);
		/*
		 * 0 OK
		 * >0 is error
		 */
		if (ret_target < 0) ret_target = 2;
		_exit(ret_target);
	} else if (write_pid < 0) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec, get_stderr_fd(),
			"fork error : %s\n", strerror(errno));
	}
	return write_pid;
}

static
pid_t
run_source_script(
		int swinstall_mode, 
		int local_stdin, 
		int source_pipe,
		char * source_path,
		int nhops,
		char * pax_write_command_key,
		sigset_t *fork_blockmask,
		sigset_t *fork_defaultmask,
		char * hostname,
		char * blocksize
		) 
{
	pid_t write_pid;

	if ((swinstall_mode == 0 || local_stdin)) {
		/*
		* fork not required.
		*/
		return 0;
	}

	write_pid = swndfork(fork_blockmask, fork_defaultmask);
	if (write_pid == 0) {
		int ret_source = 0;
		/*
		 * Write the source scripts.
		 */
		if (swinstall_mode && local_stdin == 0) {
			/*
			* If source is remote.
			*/
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
					&g_logspec, get_stderr_fd(), 
					"running source script.\n");
			ret_source = swc_write_source_copy_script(
				source_pipe, 
				source_path,
				SWINSTALL_DO_SOURCE_CTL_MESSAGE,
				g_verboseG, 
				SWC_SCRIPT_SLEEP_DELAY, 
				nhops, 
				pax_write_command_key,
				hostname,
				blocksize);
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
					&g_logspec, get_stderr_fd(), 
				"Source script finished return value=%d.\n",
								ret_source);

		} else {
			swlib_doif_writef(g_verboseG, g_fail_loudly, 
							&g_logspec, get_stderr_fd(),
					"Unexpected Dead code excpeption\n");
			swlib_doif_writef(g_verboseG,
					SWC_VERBOSE_IDB2, &g_logspec, get_stderr_fd(), 
		"NOT running source script in child, exiting with %d.\n",
								ret_source);
			LCEXIT(1);
		}
		/*
		 * 0 is OK
		 * !0 is error
		 */
		_exit(ret_source);
	} else if (write_pid < 0) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec, get_stderr_fd(),
			"fork error : %s\n", strerror(errno));
	}
	return write_pid;
}

static
int
do_install(
	SWI * swi,
	int target_fd1,
	int target_fd2,
	unsigned long int * pstatbytes,
	int do_progressmeter,
	int source_file_size,
	char * target_path,
	char * working_arg,
	VPLOB * swspecs,
	SWI_DISTDATA * distdata,
	char * catalog_path,
	int opt_preview,
	char * pax_read_command_key,
	int keep_old_files,
	int alt_catalog_root,
	int event_fd,
	struct extendedOptions * opta)
{
	int format;
	int ret;
	int sfd;
	XFORMAT * xformat;
	void (*alarm_handler)(int) = NULL;
	char * pax_read_command;

	if (do_progressmeter) {
		swgp_signal_block(SIGALRM, (sigset_t *)NULL);
		alarm_handler = update_progress_meter;
	}

	xformat = swi->xformatM;
	format = xformat_get_format(xformat);
	sfd = target_fd1;

	pax_read_command = swc_get_pax_read_command(g_pax_read_commands,
				pax_read_command_key, 
				g_verboseG >= SWC_VERBOSE_3, 
				keep_old_files, DEFAULT_PAX_R);

	swi->distdataM = distdata;
	ret = swinstall_arfinstall(swi, sfd, target_fd2, 0,
			&g_signal_flag, target_path, catalog_path,
			swspecs, SWI_SECTION_BOTH,
			g_stdout_testfd, opt_preview, pax_read_command_key,
			alt_catalog_root, event_fd, opta, &g_logspec,
			keep_old_files, do_progressmeter ? pstatbytes : NULL);

	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, &g_logspec,
			get_stderr_fd(),
			"do_install: finished swinstall_arfinstall\n");

	return ret;
}

static
int 
wait_on_script(pid_t write_pid, char * location)
{
	/*
	 * wait on the write_script process and check for errors.
	 */
	pid_t ret;
	int status;
	ret = waitpid(write_pid, &status, 0);
	if (ret < 0) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec, get_stderr_fd(),
			"%s scripts waitpid : %s\n", 
			location, strerror(errno));
		return -1;
	}
	if (WIFEXITED(status)) {
		return (int)(WEXITSTATUS(status));
	} else {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec,
			get_stderr_fd(),
			"%s script had abnormal exit.\n", 
			location);
		return -2;
	}
}

static
void
do_preview(
	FILE * fver,
	int fverfd, 
	char * working_arg,
	STROB * source_control_message,
	int local_stdin,
	int source_nhops,
	char * source_path,
	char * cl_source_target,
	char * source_fork_type,
	int target_nhops,
	char * target_path,
	char * cl_target_target,
	char * target_fork_type,
	char * pax_read_command_key,
	SHCMD * target_sshcmd0,
	SHCMD * target_kill_sshcmd0,
	SHCMD * source_sshcmd0,
	SHCMD * source_kill_sshcmd0,
	int DELAY,
	int wopt_keep_old_files,
	char * wopt_blocksize,
	int use_no_getconf,
	char * pax_write_command_key,
	int target_loop_count,
	int swinstall_mode,
	char * wopt_shell_command,
	STRAR * target_cmdlist,
	STRAR * source_cmdlist,
	SWI_DISTDATA * distdata,
	char * installed_software_catalog,
	char * sh_dash_s, int alt_catalog_root,
	char * source_terminal_host, char * target_terminal_host)
{
	if (
		cl_source_target[strlen(cl_source_target) - 1]
		== '/'
	)
	{
		strob_strcpy(source_control_message, 
			SWBIS_SWINSTALL_SOURCE_CTL_DIRECTORY
			);
	} else {
		strob_strcpy(source_control_message, 
			SWBIS_SWINSTALL_SOURCE_CTL_ARCHIVE
			);
	}
	fprintf(fver, "<> Preview Mode\n");
	fprintf(fver, "<> local_stdin = %d\n", local_stdin);
	if (target_loop_count == 0) {
	fprintf(fver, "<> Source Preview:\n");
	fprintf(fver, "<> Source: soc spec: [%s]\n",
			cl_source_target);
	fprintf(fver, "<> Source: nhops: %d\n", source_nhops);
	fprintf(fver, "<> Source: path: [%s]\n", source_path);
	fprintf(fver, "<> Source: fork type: %s\n", source_fork_type);
	fprintf(fver, "<> Source: pax_write_command: %s\n", 
			get_pax_write_command(pax_write_command_key, 
					DEFAULT_PAX_W));
	fprintf(fver, "<> Source: Command Args: ");
	fflush(fver);
	swc_do_preview_cmd("<> Source: Kill Command Args: ", fver,
		source_path, 
		source_sshcmd0, 
		source_kill_sshcmd0, 
		cl_source_target, 
		source_cmdlist, 
		source_nhops,
		target_loop_count == 0,
		use_no_getconf, wopt_shell_command);
	fflush(fver);
	fprintf(fver, "<> Source: command ends here:\n");
	fprintf(fver, "<> Source: script starts here:\n");
	fflush(fver);
	if (local_stdin == 0) {
		swc_write_source_copy_script(
			fverfd, 
			source_path,
			SWINSTALL_DO_SOURCE_CTL_MESSAGE,
			g_verboseG, 
			DELAY, 
			source_nhops, 
			pax_write_command_key, 
			source_terminal_host,
			wopt_blocksize
			);
	}
	fflush(fver);
	fprintf(fver, "<> Source: End of Source script:\n");
	fprintf(fver, "<> Source: End of Source Preview\n");
	}
	fprintf(fver, "<> Target Preview\n");
	fprintf(fver, "<> Target: soc spec : [%s]\n", working_arg);
	fprintf(fver, "<> Target: nhops: %d\n", target_nhops);
	fprintf(fver, "<> Target: path: [%s]\n", target_path);
	fprintf(fver, "<> Target: source is %s\n",
			strob_str(source_control_message));
	fprintf(fver, "<> Target: fork type: %s\n", target_fork_type);
	fprintf(fver, "<> Target: pax_read_command: %s\n", 
			swc_get_pax_read_command(g_pax_read_commands,
				pax_read_command_key, 
				g_verboseG >= SWC_VERBOSE_3, 
				wopt_keep_old_files, DEFAULT_PAX_R));
	fprintf(fver, "<> Target: Command Args: ");
	fflush(fver);
	swc_do_preview_cmd("<> Target: Kill Command Args: ", fver,
		target_path, 
		target_sshcmd0,
		target_kill_sshcmd0,
		cl_target_target,
		target_cmdlist,
		target_nhops, 1,
		use_no_getconf, wopt_shell_command);
	fflush(fver);
	fprintf(fver, "<> Target: script starts here:\n");
	fflush(fver);
	if (distdata->did_part1M) {
		swinstall_write_target_install_script(
			fverfd, 
			target_path, 
			source_control_message, 
			source_path, 
			DELAY, 
			wopt_keep_old_files, 	
			target_nhops, 
			g_verboseG,
			pax_read_command_key,
			target_terminal_host,
			wopt_blocksize, distdata,
			installed_software_catalog,
			0 /*opt_preview*/, sh_dash_s,
			alt_catalog_root, &g_logspec);
	}
	fflush(fver);
	fprintf(fver, "<> Target: End of Target script:\n");
	fprintf(fver, "<> Target: End of Target Preview\n");
	fprintf(fver, "<> End of Preview Mode\n");
	fflush(fver);
}

/*
 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
        Main Program
 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
*/

int
main(int argc, char **argv)
{
	int c;
	int ret;
	int tmpret;
	int optret = 0;
	int source_fdar[3];
	int target_fdar[3];
	int source_stdio_fdar[3];
	int target_stdio_fdar[3];
	int swi_event_fd = -1;
	int save_stdio_fdar[3];
	int targetlist_fd = -1;
	int e_argc = 1;
	int w_argc = 1;
	int main_optind = 0;
	int opt_loglevel = 0;
	int target_nhops;
	int source_nhops;
	int is_source_local_regular_file = 0;
	int opt_alt_catalog_root = 0;
	int num_remains;
	int do_to_stdout = 0;
	char * tmp_s;
	pid_t ss_pid = 0;
	pid_t ts_pid = 0;
	pid_t target_write_pid = 0;
	pid_t source_write_pid = 0;
	pid_t * pid_array = g_pid_array;
	int   * status_array = g_status_array;
	int * p_pid_array_len = &g_pid_array_len;
	pid_t target_pump_pid = 0;
	pid_t source_pump_pid = 0;
	int swinstall_mode = 1;
	int wopt_pump_delay1 = -1;
	int wopt_burst_adjust = DEFAULT_BURST_ADJUST;  /* sort is similar to rcvd adjust size in openssh */
	char * wopt_shell_command = (char*)(NULL);
	char * sh_dash_s;
	int wopt_no_defaults = 0;
	int wopt_no_pty = 0;
	int wopt_pty = 0;
	int wopt_kill_hop_threshhold = 2;  /* 2 */
	int wopt_debug_events= 0;
	char * wopt_enforce_file_md5 = (char*)NULL;
	char * wopt_enforce_sig = (char*)NULL;
	char * wopt_allow_rpm = (char*)NULL;
	char * wopt_install_volatile = (char*)CHARTRUE;
	char * wopt_volatile_newname = (char*)(NULL);
	char * wopt_no_getconf = (char*)NULL;
	char * wopt_no_remote_kill = (char*)NULL;
	char * wopt_quiet_progress_bar = (char*)CHARTRUE;
	char * wopt_show_progress_bar = (char*)NULL;
	char * optionname;
	char * wopt_ssh_options = (char*)NULL;
	int is_seekable = 0;
	int  optionEnum;
	int vofd;
	int wopt_with_hop_pids = 1;
	int devel_no_fork_optimization = 1;
	int local_stdin = 0;
	int do_extension_options_via_goto = 0;
	int tmp_status;
	int fverfd;
	int target_loop_count = 0;
	int target_success_count = 0;
	int * p_do_progressmeter;
	int make_master_raw = 1;
	int is_local_stdin_seekable = 0;
	int nullfd;
	int opt_preview = 0;
	int testnum = 0;
	int retval = 0;
	int source_file_size;
	int target_file_size;
	unsigned long int statbytes;
	int target_array_index = 0;
	int select_array_index = 0;
	int stdin_in_use = 0;
	int use_no_getconf;
	int swevent_fd = STDOUT_FILENO;
	struct extendedOptions * opta = optionsArray;
	struct termios	*login_orig_termiosP = NULL;
	struct winsize	*login_sizeP = NULL;
	
	char * xcmd;
	char * wopt_blocksize = "5120";
	char * wopt_show_options = NULL;
	char * wopt_show_options_files = NULL;
	char * wopt_pty_fork_type = NULL;
	int  wopt_keep_old_files = 0;
	char * eopt_allow_downdate;
	char * eopt_allow_incompatible;
	char * eopt_ask;
	char * eopt_autoreboot;
	char * eopt_autorecover;
	char * eopt_defer_configure;
	char * eopt_autoselect_dependencies;
	char * eopt_distribution_source_directory;
	char * eopt_installed_software_catalog;
	char * eopt_enforce_dependencies;
	char * eopt_enforce_locatable;
	char * eopt_enforce_scripts;
	char * eopt_enforce_dsa;
	char * eopt_logfile;
	char * eopt_loglevel;
	char * eopt_reinstall;
	char * eopt_select_local;
	char * eopt_verbose;
	char * opt_distribution_target_directory = "/";
	char * tty_opt = NULL;
	char * source_fork_type;
	char * target_fork_type;
	char * pty_fork_type = g_fork_pty2;
	char * source_script_pid = (char*)NULL;
	char * target_script_pid = (char*)NULL;
	char * tmpcharp = (char*)NULL;
	char * selections_filename = (char*)NULL;
	char * exoption_arg;
	char * exoption_value;
	char * soc_spec_target = (char*)NULL;
	char * soc_spec_source = (char*)NULL;
	char * cl_target_target = (char*)NULL;
	char * xcl_target_target = (char*)NULL;
	char * xcl_source_target = (char*)NULL;
	char * cl_target_selections = (char*)NULL;
	char * cl_source_target = (char*)NULL;
	char * cl_source_selections = (char*)NULL;
	char * target_path = (char*)NULL;

	char * pax_read_command_key = (char*)NULL;
	char * pax_write_command_key = (char*)NULL;
	char * wopt_local_pax_write_command = (char*)NULL;
	char * wopt_remote_pax_write_command = (char*)NULL;
	char * wopt_local_pax_read_command = (char*)NULL;
	char * wopt_remote_pax_read_command = (char*)NULL;
	char * working_arg = (char*)NULL;
	char * current_arg = (char*)NULL;
	char * opt_option_files = (char*)NULL;
	char * system_defaults_files = (char*)NULL;
	char * source_path = (char*)NULL;
	char * target_terminal_host = (char*)NULL;
	char * source_terminal_host = (char*)NULL;
	char cwd[1024];
	char * remote_shell_command = REMOTE_SSH_BIN;
	char * remote_shell_path;

	SWI_DISTDATA  * distdataO;
	STRAR * target_cmdlist;
	STRAR * source_cmdlist;
	STRAR * target_tramp_list;
	STRAR * source_tramp_list;
	VPLOB * swspecs;
	STROB * tmp;
	STROB * source_control_message;
	STROB * target_control_message;
	STROB * target_start_message;
	STROB * source_start_message;
	STROB * target_catalog_message;
	STROB * source_access_message;
	STROB * source_line_buf;
	STROB * target_line_buf;
	STROB * tmpcommand;
	CPLOB * w_arglist;
	CPLOB * e_arglist;
	SWI * swi = (SWI*)NULL;
	SHCMD * target_sshcmd[2];
	SHCMD * source_sshcmd[2];
	SHCMD * kill_sshcmd[2];
	SHCMD * target_kill_sshcmd[2];
	SHCMD * source_kill_sshcmd[2];
	FILE * fver;
	sigset_t * fork_blockmask;
	sigset_t * fork_defaultmask;
	sigset_t * currentmask;
	SWUTIL * swutil;
	
	struct option main_long_options[] =
             {
		{"selections-file", 1, 0, 'f'},
		{"alternate-catalog-root", 0, 0, 'r'},
		{"preview", 0, 0, 'p'},
		{"block-size", 1, 0, 'b'},
		{"target-file", 1, 0, 't'},
		{"source", 1, 0, 's'},
		{"defaults-file", 1, 0, 'X'},
		{"verbose", 0, 0, 'v'},
		{"extension-option", 1, 0, 'W'},
		{"extended-option", 1, 0, 'x'},
		{"version", 0, 0, 'V'},
		{"help", 0, 0, '\012'},
		{"noop", 0, 0, 154},
		{"show-options", 0, 0, 158},
		{"show-options-files", 0, 0, 159},
		{"no-pty", 0, 0, 162},
		{"pty-fork-version", 1, 0, 163},
		{"testnum", 1, 0, 164},
		{"pty", 0, 0, 169},
		{"keep-old-files", 0, 0, 170},
		{"remote-shell", 1, 0, 172},
		{"quiet-progress", 0, 0, 173},
		{"local-pax-write-command", 1, 0, 175},
		{"remote-pax-write-command", 1, 0, 176},
		{"pax-write-command", 1, 0, 177},
		{"remote-pax-read-command", 1, 0, 178},
		{"local-pax-read-command", 1, 0, 179},
		{"pax-read-command", 1, 0, 180},
		{"no-defaults", 0, 0, 181},
		{"pax-command", 1, 0, 182},
		{"show-progress-bar", 0, 0, 183},
		{"no-remote-kill", 0, 0, 184},
		{"no-getconf", 0, 0, 185},
		{"use-getconf", 0, 0, 186},
		{"progress-bar-fd", 1, 0, 187},
		{"shell-command", 1, 0, 188},
		{"preview-tar-file", 1, 0, 189},
		{"enforce-sig", 0, 0, 190},
		{"enforce-file-md5", 0, 0, 191},
		{"allow-rpm", 0, 0, 192},
		{"pump-delay1", 1, 0, 193},
		{"burst-adjust", 1, 0, 194},
		{"ssh-options", 1, 0, 195},
		{"debug-events", 0, 0, 196},
		{"to-stdout", 0, 0, 197},
		{0, 0, 0, 0}
             };

	struct option posix_extended_long_options[] =
             {
		{"allow_downdate", 	1, 0, 210},
		{"allow_incompatible", 	1, 0, 211},
		{"ask", 		1, 0, 212},
		{"autoreboot", 		1, 0, 213},
		{"autorecover", 	1, 0, 214},
		{"autoselect_dependencies", 	1, 0, 231},
		{"distribution_source_directory", 1, 0, 232},
		{"enforce_dependencies", 	1, 0, 233},
		{"enforce_dsa", 		1, 0, 234},
		{"logfile", 			1, 0, 235},
		{"loglevel", 			1, 0, 202},
		{"reinstall", 			1, 0, 203},
		{"select_local", 		1, 0, 204},
		{"verbose", 			1, 0, 206},
		{"enforce_locatable", 		1, 0, 215},
		{"enforce_scripts", 		1, 0, 216},
		{"installed_software_catalog",	1, 0, 217},
		{"swbis_no_getconf", 		1, 0, 218},
		{"swbis_shell_command", 	1, 0, 219},
		{"swbis_no_remote_kill", 	1, 0, 220},
		{"swbis_quiet_progress_bar", 	1, 0, 221},
		{"swbis_local_pax_write_command", 1, 0, 222},
		{"swbis_remote_pax_write_command", 1, 0, 223},
		{"swbis_local_pax_read_command", 1, 0, 224},
		{"swbis_remote_pax_read_command", 1, 0, 225},
		{"swbis_enforce_sig", 		1, 0, 226},
		{"swbis_enforce_file_md5", 	1, 0, 227},
		{"swbis_allow_rpm", 		1, 0, 228},
		{"swbis_install_volatile", 	1, 0, 229},
		{"swbis_volatile_newname", 	1, 0, 230},
               {0, 0, 0, 0}
             };

	struct option impl_extensions_long_options[] =
             {
		{"block-size", 1, 0, 'b'},
		{"noop", 0, 0, 154},
		{"show-options", 0, 0, 158},
		{"show-options-files", 0, 0, 159},
		{"no-pty", 0, 0, 162},
		{"pty-fork-version", 1, 0, 163},
		{"testnum", 1, 0, 164},
		{"pty", 0, 0, 169},
		{"keep-old-files", 0, 0, 170},
		{"remote-shell", 1, 0, 172},
		{"quiet-progress", 0, 0, 173},
		{"local-pax-write-command", 1, 0, 175},
		{"remote-pax-write-command", 1, 0, 176},
		{"pax-write-command", 1, 0, 177},
		{"remote-pax-read-command", 1, 0, 178},
		{"local-pax-read-command", 1, 0, 179},
		{"pax-read-command", 1, 0, 180},
		{"no-defaults", 0, 0, 181},
		{"pax-command", 1, 0, 182},
		{"show-progress-bar", 0, 0, 183},
		{"no-remote-kill", 0, 0, 184},
		{"no-getconf", 0, 0, 185},
		{"use-getconf", 0, 0, 186},
		{"progress-bar-fd", 1, 0, 187},
		{"shell-command", 1, 0, 188},
		{"preview-tar-file", 1, 0, 189},
		{"enforce-sig", 0, 0, 190},
		{"enforce-file-md5", 0, 0, 191},
		{"allow-rpm", 0, 0, 192},
		{"pump-delay1", 1, 0, 193},
		{"burst-adjust", 1, 0, 194},
		{"ssh-options", 1, 0, 195},
		{"debug-events", 0, 0, 196},
		{"to-stdout", 0, 0, WOPT_LAST},
		{0, 0, 0, 0}
             };
	
	struct option std_long_options[] =
             {
		{"selections-file", 1, 0, 'f'},
		{"preview", 0, 0, 'p'},
		{"installed-software", 0, 0, 'r'},
		{"target-file", 1, 0, 't'},
		{"source", 1, 0, 's'},
		{"extended-option", 1, 0, 'x'},
		{"defaults-file", 1, 0, 'X'},
		{"extension-option", 1, 0, 'W'},
		{"verbose", 0, 0, 'v'},
		{"block-size", 1, 0, 'b'},
		{"version", 0, 0, 'V'},
		{"help", 0, 0, '\012'},
               {0, 0, 0, 0}
             };
       
	struct ugetopt_option_desc main_help_desc[] =
             {
	{"", "FILE","Take software selections from FILE."},
	{"", "", "Preview only by showing information to stdout"},
	{"", "", "causes swinstall to operate on installed software\n"
	"          located at an alternate root."},
	{"", "FILE", "Specify a FILE containing a list of targets."
	},
	{"", "source", "Specify the file, directory, or '-' for stdin.\n"
	"                     source may have target syntax."
	},
	{"", "option=value", "Specify posix extended option."},
	{"", "FILE[ FILE2 ...]", "Specify files that override \n"
	"        system option defaults. Specify empty string to disable \n"
	"        option file reading."
	},
	{"", "option[=value]", "Specify implementation extension option."},
	{"verbose", "",  "same as '-x verbose=2'\n"
	"     (implementation extension).\n"
	"     -v  is level 2, -vv is level 3,... etc.\n"
	"         level 0: silent on stdout and stderr.\n"
	"         level 1: fatal and warning messages to stderr.\n"
	"     -v  level 2: level 1 plus a progress bar.\n"
	"     -vv level 3: level 2 plus script stderr.\n"
	"     -vvv level 4: level 3 plus events.\n"
	"     -vvvv level 5: level 4 plus events.\n"
	"     -vvvvv level 6: level 5 plus set shell -vx option.\n"
	"     -vvvvvv level 7 and higher: level 6 plus debugging messages.\n"
	},
	{"block-size", "N", "specify block size N octets, 0<N<=32256\n"
	"          default size is 5120. (implementation extension)."},
	{"version", "", "Show version information to stdout. (impl. extension)."},
	{"help", "", "Show this help to stdout (impl. extension)."},
	{0, 0, 0}
	};

	/*
	 *  = = = = = = = = = = = = = = = = = = = = = = = = = 
	 *  = = = = = = = = = = = = = = = = = = = = = = = = = 
	 *  End of Decalarations.
	 *  = = = = = = = = = = = = = = = = = = = = = = = = = 
	 *  = = = = = = = = = = = = = = = = = = = = = = = = = 
	 */

	/*
	 * open the sw utility object, pile all paramater that
	 * cry out to be global into this object so that they are
	 * contained.
	 */

	swutil = swutil_open();
	g_swutil = swutil;

	g_logspec.logfdM = -1;
	g_logspec.loglevelM = 0;
	g_logspec.fail_loudlyM = -1;
	set_stderr_fd(STDERR_FILENO);
	swlib_utilname_set(progName);
	swgp_check_fds();
	p_do_progressmeter = &g_do_progressmeter;

	g_targetfd_array[0] = -1;
	statbytes = 0;
	fork_defaultmask = &g_fork_defaultmask;
	fork_blockmask = &g_fork_blockmask;
	currentmask = &g_currentmask;
	sigemptyset(currentmask);
	sigemptyset(fork_blockmask);
	sigaddset(fork_blockmask, SIGALRM);
	sigemptyset(fork_defaultmask);
	sigaddset(fork_defaultmask, SIGINT);
	sigaddset(fork_defaultmask, SIGPIPE);
	
	source_line_buf = strob_open(10);
	target_line_buf = strob_open(10);

	
	vstderr = stderr;
	gbuf = strob_open(100);
	nullfd = open("/dev/null", O_RDWR, 0);
	if (nullfd < 0) { 
		swlib_doif_writef(g_verboseG, g_fail_loudly,
			&g_logspec, get_stderr_fd(), "Can't open /dev/null\n");
		LCEXIT(1); 
	}
	g_nullfd = nullfd;

	g_target_fdar = target_fdar;
	g_source_fdar = source_fdar;

	target_fdar[0] = -1;
	target_fdar[1] = -1;
	target_fdar[2] = -1;
	source_fdar[0] = -1;
	source_fdar[1] = -1;
	source_fdar[2] = -1;

	source_stdio_fdar[0] = (STDIN_FILENO);
	source_stdio_fdar[1] = (STDOUT_FILENO);
	source_stdio_fdar[2] = (STDERR_FILENO);

	target_stdio_fdar[0] = (STDIN_FILENO);
	target_stdio_fdar[1] = (STDOUT_FILENO);
	target_stdio_fdar[2] = (STDERR_FILENO);

	save_stdio_fdar[0] = dup(STDIN_FILENO);
	save_stdio_fdar[1] = dup(STDOUT_FILENO);
	save_stdio_fdar[2] = dup(STDERR_FILENO);

	swc0_create_parser_buffer();
	
	target_sshcmd[1] = (SHCMD*)NULL;
	source_sshcmd[1] = (SHCMD*)NULL;
	kill_sshcmd[1] = (SHCMD*)NULL;
	target_kill_sshcmd[1] = (SHCMD*)NULL;
	source_kill_sshcmd[1] = (SHCMD*)NULL;
	
	kill_sshcmd[0] = (SHCMD*)NULL;
	source_sshcmd[0] = shcmd_open();
	target_sshcmd[0] = (SHCMD*)NULL;
	target_kill_sshcmd[0] = shcmd_open();
	source_kill_sshcmd[0] = shcmd_open();
		

	tmp = strob_open(10);		/* General use String object. */
	tmpcommand = strob_open(10);
	w_arglist = cplob_open(1);	/* Pointer list object. */
	e_arglist = cplob_open(1);	/* Pointer list object. */

	initExtendedOption();

	if (getcwd(cwd, sizeof(cwd) - 1) == NULL) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec, get_stderr_fd(), 
			"%s\n", strerror(errno));
		LCEXIT(1);
	}
	cwd[sizeof(cwd) - 1] = '\0';

	/*
	* Set the compiled-in defaults for the extended options.
	*/
	eopt_allow_downdate		= "false";
	eopt_allow_incompatible		= "false";
	eopt_ask			= "false";
	eopt_autoreboot			= "false";
	eopt_autorecover		= "false";
	eopt_autoselect_dependencies	= "false";
	eopt_defer_configure		= "false";
	eopt_distribution_source_directory = "-";
	eopt_enforce_dependencies	= "false";
	eopt_enforce_locatable		= "false";
	eopt_enforce_scripts		= "false";
	eopt_enforce_scripts		= "false";
	eopt_enforce_dsa		= "false";
	eopt_installed_software_catalog = "var/lib/swbis/catalog/";
	eopt_logfile			= "/var/log/swinstall.log";
	eopt_loglevel			= "0";
	eopt_reinstall			= "false";
	eopt_select_local		= "false";
	eopt_verbose			= "1";

	wopt_no_getconf			= "false";
	wopt_no_remote_kill		= "false";
	wopt_quiet_progress_bar		= "true";
	wopt_shell_command		= "posix";
	wopt_local_pax_write_command 	= "pax";
	wopt_remote_pax_write_command 	= "pax";
	wopt_local_pax_read_command 	= "pax";
	wopt_remote_pax_read_command 	= "pax";
	wopt_enforce_sig		= "false";
	wopt_enforce_file_md5		= "false";
	wopt_allow_rpm			= "false";
	wopt_install_volatile		= "true";

	wopt_show_options = NULL;
	wopt_show_options_files = NULL;

	set_opta_initial(opta, SW_E_allow_downdate, eopt_allow_downdate);
	set_opta_initial(opta, SW_E_allow_incompatible, eopt_allow_incompatible);
	set_opta_initial(opta, SW_E_ask, eopt_ask);
	set_opta_initial(opta, SW_E_autoreboot, eopt_autoreboot);
	set_opta_initial(opta, SW_E_autorecover, eopt_autorecover);
	set_opta_initial(opta, SW_E_autoselect_dependencies, 
					eopt_autoselect_dependencies);
	set_opta_initial(opta, SW_E_distribution_source_directory, 
					eopt_distribution_source_directory);
	set_opta_initial(opta, SW_E_enforce_dependencies, 
					eopt_enforce_dependencies);
	set_opta_initial(opta, SW_E_enforce_locatable, eopt_enforce_locatable);
	set_opta_initial(opta, SW_E_enforce_scripts, eopt_enforce_scripts);
	set_opta_initial(opta, SW_E_enforce_dsa, eopt_enforce_dsa);
	set_opta_initial(opta, SW_E_installed_software_catalog, eopt_installed_software_catalog);
	set_opta_initial(opta, SW_E_logfile, eopt_logfile);
	set_opta_initial(opta, SW_E_loglevel, eopt_loglevel);
	set_opta_initial(opta, SW_E_reinstall, eopt_reinstall);
	set_opta_initial(opta, SW_E_select_local, eopt_select_local);
	set_opta_initial(opta, SW_E_verbose, eopt_verbose);

	set_opta_initial(opta, SW_E_swbis_no_getconf, wopt_no_getconf);
	set_opta_initial(opta, SW_E_swbis_shell_command, wopt_shell_command);
	set_opta_initial(opta, SW_E_swbis_remote_shell_client, remote_shell_command);
	set_opta_initial(opta, SW_E_swbis_no_remote_kill, wopt_no_remote_kill);
	set_opta_initial(opta, SW_E_swbis_quiet_progress_bar,
					wopt_quiet_progress_bar);
	set_opta_initial(opta, SW_E_swbis_local_pax_write_command,
					wopt_local_pax_write_command);
	set_opta_initial(opta, SW_E_swbis_remote_pax_write_command,
					wopt_remote_pax_write_command);
	set_opta_initial(opta, SW_E_swbis_local_pax_read_command,
					wopt_local_pax_read_command);
	set_opta_initial(opta, SW_E_swbis_remote_pax_read_command,
					wopt_remote_pax_read_command);
	set_opta_initial(opta, SW_E_swbis_enforce_sig, wopt_enforce_sig);
	set_opta_initial(opta, SW_E_swbis_enforce_file_md5, wopt_enforce_file_md5);
	set_opta_initial(opta, SW_E_swbis_allow_rpm, wopt_allow_rpm);
	set_opta_initial(opta, SW_E_swbis_install_volatile, wopt_install_volatile);
	set_opta_initial(opta, SW_E_swbis_volatile_newname, wopt_volatile_newname);

	cplob_add_nta(w_arglist, strdup(argv[0]));
	cplob_add_nta(e_arglist, strdup(argv[0]));

	while (1) {
		int option_index = 0;

		c = ugetopt_long(argc, argv, "b:f:t:prVvs:X:x:W:", 
					main_long_options, &option_index);
		if (c == -1) break;

		switch (c) {
		case 'p':
			opt_preview = 1;
			break;
		case 'r':
			opt_alt_catalog_root = 1;
			break;
		case 'v':
			g_verboseG++;
			eopt_verbose = (char*)malloc(12);
			snprintf(eopt_verbose, 12, "%d", g_verboseG);
			eopt_verbose[11] = '\0';
			set_opta(opta, SW_E_verbose, eopt_verbose);
			break;
		case 'f':
			if (swc_process_swoperand_file(swutil,
				"selections", optarg, &stdin_in_use,
				&select_array_index, g_selectfd_array))
			{
				LCEXIT(1);
			}
			break;
		case 'b':
			wopt_blocksize = strdup(optarg);
			{
				int n;
				char * t = wopt_blocksize;
				while (*t) {
					if (!isdigit((int)(*t))) {
						fprintf(stderr,
						"illegal block size\n");
						exit(1);	
					}
					t++;
				}
				n = swlib_atoi(wopt_blocksize, NULL);
				if (n <= 0 || n > 32256) {
					fprintf(stderr,
					"illegal block size\n");
					exit(1);	
				}
			}
			break;
		case 't':
			/*
			 * Process the target file
			 */
			if (swc_process_swoperand_file(swutil,
				"target", optarg, &stdin_in_use,
				&target_array_index, g_targetfd_array))
			{
				LCEXIT(1);
			}
			break;
		case 's':
			soc_spec_source = strdup(optarg);
			if (*soc_spec_source != '@') {
				strob_strcpy(tmp, "@");
				/*  The following three lines were a bug
				if (strchr(soc_spec_source, ':') == NULL) {
					 strob_strcat(tmp, ":");
				}
				*/
				strob_strcat(tmp, soc_spec_source);
				soc_spec_source = strdup(strob_str(tmp));
			}
			SWLIB_ALLOC_ASSERT(soc_spec_source != NULL);
			break;

		case 'W':
			swc0_process_w_option(tmp, w_arglist, optarg, &w_argc);
			break;
		case 'x':
			exoption_arg = strdup(optarg);
			SWLIB_ALLOC_ASSERT(exoption_arg != NULL);
			/*
			 * 
			 *  Parse the extended option and add to pointer list
			 *  for later processing.
			 * 
			 */
			{
				char * np;
				char * t;
				STROB * etmp = strob_open(10);
				
				t = strob_strtok(etmp, exoption_arg, " ");
				while (t) {
					exoption_value = strchr(t,'=');
					if (!exoption_value) {
						swlib_doif_writef(g_verboseG, 
							g_fail_loudly, 
							&g_logspec, get_stderr_fd(),
						"invalid extended arg : %s\n", 
							optarg);
						_exit(1);
					}
					np = exoption_value;
					*exoption_value = '\0';
					exoption_value++;
					/*
					 * 
					 *  Now add the option and value to 
					 *  the arg list.
					 * 
					 */
					strob_strcpy(tmp, "--");
					strob_strcat(tmp, t);
					strob_strcat(tmp, "=");
					strob_strcat(tmp, exoption_value);
					cplob_add_nta(e_arglist, 
						strdup(strob_str(tmp)));
					e_argc++;

					*np = '=';
					t = strob_strtok(etmp, NULL, " ");
				}
				/*
				*  setExtendedOption(optarg, exoption_value);
				*/
				strob_close(etmp);
			}
			break;
		case 'X':
			if (opt_option_files) {
				opt_option_files = (char*)realloc(
						(void*)opt_option_files,
						strlen(opt_option_files) \
						+ strlen(optarg) + 2);
				strcat(opt_option_files, " ");
				strcat(opt_option_files, optarg);
			} else {
				opt_option_files = strdup(optarg);
			}
			break;
               case 'V':
			version_info(stdout);
			LCEXIT(0);
		 	break;
               case '\012':
			usage(stdout, 
				argv[0], 
				std_long_options, 
				main_help_desc);
			LCEXIT(0);
		 	break;
               case '?':
			swlib_doif_writef(g_verboseG,
				g_fail_loudly, &g_logspec, get_stderr_fd(),
				"Try `swinstall --help' for more information.\n");
			LCEXIT(1);
		 	break;
               default:
			if (c >= 154 && c <= WOPT_LAST) { 
				/*
				 *  This provides the ablility to specify 
				 *  extension options by using the 
				 *  --long-option syntax (i.e. without using 
				 *  the -Woption syntax) .
				 */
				do_extension_options_via_goto = 1;
				goto gotoExtensionOptions;
gotoStandardOptions:
				;
			} else {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
					&g_logspec, get_stderr_fd(),
					"invalid args.\n");
		 		LCEXIT(1);
			}
			break;
               }
	}

	main_optind = optind;

	optind = 1;
	optarg =  NULL;
		
	while (1) {
		int e_option_index = 0;
		c = ugetopt_long (e_argc, 
				cplob_get_list(e_arglist), 
				"", 
				posix_extended_long_options, 
				&e_option_index);
		if (c == -1) break;
		
		switch (c) {
		
		case 231:
			set_boolean_x_option(opta, 
				SW_E_autoselect_dependencies, 
				optarg, 
				&eopt_autoselect_dependencies);
			break;
		case 232:
			eopt_distribution_source_directory = strdup(optarg);
			set_opta(opta, 
				SW_E_distribution_source_directory, 
				eopt_distribution_source_directory);
			SWLIB_ALLOC_ASSERT
				(eopt_distribution_source_directory != NULL);
			break;
		case 233:
			set_boolean_x_option(opta, 
				SW_E_enforce_dependencies, 
				optarg, 
				&eopt_enforce_dependencies);
			break;

		case 234:
			set_boolean_x_option(opta, 
				SW_E_enforce_dsa, 
				optarg, 
				&eopt_enforce_dsa);
			break;
		case 235:
			eopt_logfile = strdup(optarg);
			set_opta(opta, SW_E_logfile, eopt_logfile);
			SWLIB_ALLOC_ASSERT(eopt_logfile != NULL);
			break;

		case 202:
			eopt_loglevel = strdup(optarg);
			opt_loglevel = swlib_atoi(optarg, NULL);
			g_loglevel = opt_loglevel;
			g_logspec.loglevelM = opt_loglevel;
			set_opta(opta, SW_E_loglevel, eopt_loglevel);
			SWLIB_ALLOC_ASSERT(eopt_loglevel != NULL);
			break;

		case 203:
			set_boolean_x_option(opta, 
					SW_E_recopy, 
					optarg, 
					&eopt_reinstall);
			break;
		case 204:
			set_boolean_x_option(opta, 
				SW_E_select_local, 
				optarg, 
				&eopt_select_local);
			break;
		case 206:
			eopt_verbose = strdup(optarg);
			g_verboseG = swlib_atoi(eopt_verbose, NULL);
			set_opta(opta, SW_E_verbose, eopt_verbose);
			break;
		case 210:
			eopt_allow_downdate = strdup(optarg);
			set_opta(opta, SW_E_allow_downdate, eopt_allow_downdate);
			break;
		case 211:
			eopt_allow_incompatible = strdup(optarg);
			set_opta(opta, SW_E_allow_incompatible, eopt_allow_incompatible);
			break;
		case 212:
			eopt_ask = strdup(optarg);
			set_opta(opta, SW_E_ask, eopt_ask);
			break;
		case 213:
			eopt_autoreboot = strdup(optarg);
			set_opta(opta, SW_E_autoreboot, eopt_autoreboot);
			break;
		case 214:
			eopt_autorecover = strdup(optarg);
			set_opta(opta, SW_E_autorecover, eopt_autorecover);
			break;
		case 215:
			eopt_enforce_locatable = strdup(optarg);
			set_opta(opta, SW_E_enforce_locatable, eopt_enforce_locatable);
			break;
		case 216:
			eopt_enforce_scripts = strdup(optarg);
			set_opta(opta, SW_E_enforce_scripts, eopt_enforce_scripts);
			break;
		case 217:
			eopt_installed_software_catalog = strdup(optarg);
			set_opta(opta, SW_E_installed_software_catalog, eopt_installed_software_catalog);
			break;
		case 218:
		case 219:
		case 220:
		case 221:
		case 222:
		case 223:
		case 224:
		case 225:
		case 226:
		case 227:
		case 228:
		case 229:
		case 230:
			optionname = getLongOptionNameFromValue(posix_extended_long_options , c);
			SWLIB_ASSERT(optionname != NULL);
			optionEnum = getEnumFromName(optionname, opta);
			SWLIB_ASSERT(optionEnum > 0);
			set_opta(opta, optionEnum, optarg);
			break;
		default:
			swlib_doif_writef(g_verboseG,
				g_fail_loudly, &g_logspec, get_stderr_fd(),
				"error processing extended option\n");
			swlib_doif_writef(g_verboseG,
				g_fail_loudly, &g_logspec, get_stderr_fd(),
				"Try `swinstall --help' for more information.\n");
		 	LCEXIT(1);
               break;
               }
	}
	optind = 1;
	optarg =  NULL;

	/*
	 * 
	 *  Now run the Implementation extension options (-W) through getopt.
	 * 
	 */
	while (1) {
		int w_option_index = 0;
		c = ugetopt_long(w_argc, 
				cplob_get_list(w_arglist), 
				"", 
				impl_extensions_long_options, 
				&w_option_index);
		if (c == -1) break;
	
gotoExtensionOptions:    /* Goto, Uhhg... */
		switch (c) {
		case 'b':
			wopt_blocksize = strdup(optarg);
			{
				int n;
				char * t = wopt_blocksize;
				while (*t) {
					if (!isdigit((int)*t)) {
						fprintf(stderr,
						"illegal block size\n");
						exit(1);	
					}
					t++;
				}
				n = swlib_atoi(wopt_blocksize, NULL);
				if (n <= 0 || n > 32256) {
					fprintf(stderr,
					"illegal block size\n");
					exit(1);	
				}
			}
			break;
		case 154:
			break;
		case 158:
			wopt_show_options = CHARTRUE;
			break;
		case 159:
			wopt_show_options_files = CHARTRUE;
			break;
		case 162: /* No pty */
			wopt_pty_fork_type = g_fork_pty_none;
			wopt_no_pty = 1;
			break;
		case 163:
			if (strcmp(optarg, g_fork_pty2) == 0) {
				pty_fork_type = g_fork_pty2;
			} else if (strcmp(optarg, g_fork_pty) == 0) {
				pty_fork_type = g_fork_pty;
			} else {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
					&g_logspec, get_stderr_fd(),
					"invalid option arg : [%s]\n", optarg);
				LCEXIT(1);
			}
			break;
		case 164:
			/*
			 * Development testing controls.
			 */
			testnum = swlib_atoi(optarg, NULL);
			if (testnum == 10) {
				devel_no_fork_optimization = 1;
			} else if (testnum == 11) {
				wopt_with_hop_pids = 1;
			}
			break;
		case 169: /* Pty */
			wopt_pty_fork_type = g_fork_pty2;
			pty_fork_type = g_fork_pty2;
			wopt_pty = 1;
			break;
		case 170:
			wopt_keep_old_files = 1;
			break;
		case 172:
			remote_shell_command = strdup(optarg);
			set_opta(opta, SW_E_swbis_remote_shell_client, remote_shell_command);
			break;
		case 173:
			wopt_quiet_progress_bar = CHARTRUE;
			set_opta(opta, SW_E_swbis_quiet_progress_bar, CHARTRUE);
			break;
		case 176:
			wopt_remote_pax_write_command = strdup(optarg);
			xcmd = get_pax_write_command(
				wopt_remote_pax_write_command, (char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
					&g_logspec, get_stderr_fd(),
					"illegal pax write command: %s \n", 
					wopt_remote_pax_write_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_remote_pax_write_command,
						wopt_remote_pax_write_command);
			break;
		case 175:
			wopt_local_pax_write_command = strdup(optarg);
			xcmd = get_pax_write_command(
					wopt_local_pax_write_command,
							 (char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
					&g_logspec, get_stderr_fd(),
					"illegal pax write command: %s \n",
						wopt_local_pax_write_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_local_pax_write_command,
					wopt_local_pax_write_command);
			break;
		case 177:
			wopt_local_pax_write_command = strdup(optarg);
			wopt_remote_pax_write_command = strdup(optarg);
			xcmd = get_pax_write_command(
					wopt_local_pax_write_command,
							(char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly,
					&g_logspec, get_stderr_fd(),
					"illegal pax write command: %s \n",
						wopt_local_pax_write_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_local_pax_write_command,  
						wopt_local_pax_write_command);
			set_opta(opta, SW_E_swbis_remote_pax_write_command,  
						wopt_local_pax_write_command);
			break;
		case 178:
			wopt_remote_pax_read_command = strdup(optarg);
			xcmd = swc_get_pax_read_command(g_pax_read_commands,
					wopt_remote_pax_read_command,
						 0, 0, (char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly,
					&g_logspec, get_stderr_fd(),
					"illegal pax read command: %s \n",
						wopt_remote_pax_read_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_remote_pax_read_command,
						wopt_remote_pax_read_command);
			break;
		case 179:
			wopt_local_pax_read_command = strdup(optarg);
			xcmd = swc_get_pax_read_command(g_pax_read_commands,
						wopt_local_pax_read_command, 
							0, 0, (char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
						&g_logspec, get_stderr_fd(),
					"illegal pax read command: %s \n", 
						wopt_local_pax_read_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_local_pax_read_command,  
						wopt_local_pax_read_command);
			break;
		case 180:
			wopt_local_pax_read_command = strdup(optarg);
			wopt_remote_pax_read_command = strdup(optarg);
			xcmd = swc_get_pax_read_command(g_pax_read_commands,
						wopt_local_pax_read_command,
							0, 0, (char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
					&g_logspec, get_stderr_fd(),
					"illegal pax read command: %s \n",
					wopt_local_pax_read_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_local_pax_read_command,
						wopt_local_pax_read_command);
			set_opta(opta, SW_E_swbis_remote_pax_read_command,
						wopt_local_pax_read_command);
			break;
		case 181:
			wopt_no_defaults = 1;
			break;
		case 182:
			wopt_local_pax_read_command = strdup(optarg);
			wopt_remote_pax_read_command = strdup(optarg);
			wopt_local_pax_write_command = strdup(optarg);
			wopt_remote_pax_write_command = strdup(optarg);
			xcmd = swc_get_pax_read_command(g_pax_read_commands,
						wopt_local_pax_read_command,
							0, 0, (char*)NULL);
			if (xcmd == NULL) {
				swlib_doif_writef(g_verboseG, g_fail_loudly,
					&g_logspec, get_stderr_fd(),
					"illegal pax read command: %s \n",
					wopt_local_pax_read_command);
				LCEXIT(1);
			}
			set_opta(opta, SW_E_swbis_local_pax_read_command,
						wopt_local_pax_read_command);
			set_opta(opta, SW_E_swbis_remote_pax_read_command,
						wopt_local_pax_read_command);
			set_opta(opta, SW_E_swbis_local_pax_write_command,
						wopt_local_pax_write_command);
			set_opta(opta, SW_E_swbis_remote_pax_write_command,
						wopt_local_pax_write_command);
			break;
		case 183:
			wopt_show_progress_bar = CHARTRUE;
			wopt_quiet_progress_bar = CHARFALSE;
			set_opta(opta, SW_E_swbis_quiet_progress_bar, "false");
			break;
		case 184:
			wopt_no_remote_kill = CHARTRUE;
			set_opta(opta, SW_E_swbis_no_remote_kill, "true");
			break;
		case 185:
			wopt_no_getconf = CHARTRUE;
			set_opta(opta, SW_E_swbis_no_getconf, "true");
			break;
		case 186:
			wopt_no_getconf = CHARFALSE;
			set_opta(opta, SW_E_swbis_no_getconf, "false");
			break;
		case 187:
			g_meter_fd = swlib_atoi(optarg, NULL);
			if (g_meter_fd != 1 && g_meter_fd != 2) {
				g_meter_fd = 1;
			}
			break;
		case 188:
			wopt_shell_command = strdup(optarg);
			if (
				strcmp(wopt_shell_command, "bash") &&
				strcmp(wopt_shell_command, "sh") &&
				strcmp(wopt_shell_command, "ksh") &&
				strcmp(wopt_shell_command, "ash") &&
				strcmp(wopt_shell_command, "posix")
			) {
				swlib_doif_writef(g_verboseG, g_fail_loudly,
					&g_logspec, get_stderr_fd(),
					"illegal shell command: %s \n",
					wopt_shell_command);
				exit(1);
			}
			set_opta(opta, SW_E_swbis_shell_command, wopt_shell_command);
			break;
		case 189:
			if (strcmp(optarg, "-") == 0) {
				g_stdout_testfd = STDOUT_FILENO;
			} else {
				g_stdout_testfd = open(optarg, O_RDWR|O_CREAT|O_TRUNC, 640);
			}
			break;
		case 190:
			wopt_enforce_sig = CHARTRUE;
			set_opta(opta, SW_E_swbis_enforce_sig, "true");
			break;
		case 191:
			wopt_enforce_file_md5 = CHARTRUE;
			set_opta(opta, SW_E_swbis_enforce_file_md5, "true");
			break;
		case 192:
			wopt_allow_rpm = CHARTRUE;
			set_opta(opta, SW_E_swbis_allow_rpm, "true");
			break;
		case 193:
			wopt_pump_delay1 = swlib_atoi(optarg, NULL);
			break;
		case 194:
			wopt_burst_adjust = swlib_atoi(optarg, NULL);
 			*swlib_burst_adjust_p() = wopt_burst_adjust;
			break;
		case 195:
			wopt_ssh_options = strdup(optarg);
			break;
		case 196:
			wopt_debug_events = 1;
			break;
		case WOPT_LAST:
			do_to_stdout = 1;
			break;
		default:
			swlib_doif_writef(g_verboseG, g_fail_loudly,
					&g_logspec, get_stderr_fd(),
		"error processing implementation extension option : %s\n",
				cplob_get_list(w_arglist)[w_option_index]);
		 	exit(1);
		break;
		}
		if (do_extension_options_via_goto == 1) {
			do_extension_options_via_goto = 0;
			goto gotoStandardOptions;
		}
	}

	optind = main_optind;

	system_defaults_files = initialize_options_files_list(NULL);

	/*
	 * = = = = = = = = = = = = = = =
	 *  Show the options to stdout.
	 * = = = = = = = = = = = = = = =
	 */
	if (wopt_show_options_files) { 
		parse_options_files(opta, 
			system_defaults_files, 
			progName, 1 /* not req'd */,  1 /* show_only */);
		parse_options_files(opta, 
			opt_option_files, 
			progName,
		 	1 /* not req'd */,  1 /* show_only */);
		LCEXIT(0);
	}

	/*
	 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
	 *  Read the system defaults files and home directory copies
	 *  if HOME is set.
	 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
	 */
	if (wopt_no_defaults == 0) {
		optret += parse_options_files(opta, 
			system_defaults_files, 
			progName, 
			0 /* not req'd */,  0 /* not show_only */);
		if (optret) {
			swlib_doif_writef(g_verboseG, g_fail_loudly,
						&g_logspec, get_stderr_fd(),
						"defaults file error\n");
			LCEXIT(1);
		}
	}
	
	if (wopt_pump_delay1 > 0) {
 		*swlib_get_io_req_p() = &g_io_req;
		g_io_req.tv_sec = 0;
		g_io_req.tv_nsec = wopt_pump_delay1;
	}

	/*
	 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
	 *  Read the defaults files given with the -X option.
	 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
	 */
	optret += parse_options_files(opta, 
		opt_option_files, 
		progName, 	
		1 /* req'd */, 0 /* not show_only */);
	if (optret) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, 
				&g_logspec, get_stderr_fd(),
				"defaults file error\n");
		LCEXIT(1);
	}

	/*
	 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
	 *  Reset the option values to pick up the values from 
	 *  the defaults file(s).
	 * = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
	 */

	eopt_allow_downdate = get_opta(opta, SW_E_allow_downdate);
	eopt_allow_incompatible = get_opta(opta, SW_E_allow_incompatible);
	eopt_ask = get_opta(opta, SW_E_ask);
	eopt_autoreboot = get_opta(opta, SW_E_autoreboot);
	eopt_autorecover = get_opta(opta, SW_E_autorecover);
	eopt_autoselect_dependencies	= get_opta(opta, SW_E_autoselect_dependencies);
	eopt_defer_configure	= get_opta(opta, SW_E_defer_configure);
	eopt_distribution_source_directory = get_opta(opta, 
					SW_E_distribution_source_directory);
	eopt_enforce_dependencies	= get_opta(opta, SW_E_enforce_dependencies);
	eopt_enforce_locatable		= get_opta(opta, SW_E_enforce_locatable);
	eopt_enforce_scripts		= get_opta(opta, SW_E_enforce_scripts);
	eopt_enforce_dsa		= get_opta(opta, SW_E_enforce_dsa);
	eopt_installed_software_catalog = get_opta(opta, SW_E_installed_software_catalog);
	eopt_logfile			= get_opta(opta, SW_E_logfile);
	eopt_loglevel			= get_opta(opta, SW_E_loglevel);
			g_loglevel = swlib_atoi(eopt_loglevel, NULL);
			opt_loglevel = g_loglevel;
			g_logspec.loglevelM = opt_loglevel;
	eopt_reinstall			= get_opta(opta, SW_E_reinstall);
	eopt_select_local		= get_opta(opta, SW_E_select_local);
	eopt_verbose			= get_opta(opta, SW_E_verbose);
		g_verboseG = swlib_atoi(eopt_verbose, NULL);
	
	wopt_no_remote_kill		= swbisoption_get_opta(opta, 
							SW_E_swbis_no_remote_kill);
	wopt_no_getconf			= swbisoption_get_opta(opta, 
							SW_E_swbis_no_getconf);
	wopt_shell_command		= swbisoption_get_opta(opta, 
							SW_E_swbis_shell_command);
	remote_shell_command		= swbisoption_get_opta(opta, 
							SW_E_swbis_remote_shell_client);
	wopt_quiet_progress_bar		= swbisoption_get_opta(opta, 
						SW_E_swbis_quiet_progress_bar);
	wopt_local_pax_write_command	= swbisoption_get_opta(opta, 	
					SW_E_swbis_local_pax_write_command);
	wopt_remote_pax_write_command	= swbisoption_get_opta(opta, 
					SW_E_swbis_remote_pax_write_command);
	wopt_local_pax_read_command	= swbisoption_get_opta(opta, 
						SW_E_swbis_local_pax_read_command);
	wopt_remote_pax_read_command	= swbisoption_get_opta(opta, 
						SW_E_swbis_remote_pax_read_command);

	if (wopt_show_options) { 
		swextopt_writeExtendedOptions(STDOUT_FILENO, opta, SWC_I);
		if (g_verboseG > 4) {
			debug_writeBooleanExtendedOptions(STDOUT_FILENO, opta);
		}
		LCEXIT(0);
	}

	if (strcasecmp(wopt_shell_command, "posix") == 0) {
		sh_dash_s = "sh -s";
	} else if (strcasecmp(wopt_shell_command, "bash") == 0) {
		sh_dash_s = "bash -s";
	} else if (strcasecmp(wopt_shell_command, "sh") == 0) {
		sh_dash_s = "sh -s";
	} else if (strcasecmp(wopt_shell_command, "ash") == 0) {
		sh_dash_s = "ash -s";
	} else if (strcasecmp(wopt_shell_command, "ksh") == 0) {
		sh_dash_s = "ksh -s";
	} else {
		sh_dash_s = "sh -s";
	}
	
	if (wopt_show_progress_bar) wopt_quiet_progress_bar = (char*)NULL;

	remote_shell_path = shcmd_find_in_path(getenv("PATH"), 
						remote_shell_command);

	use_no_getconf = is_option_true(wopt_no_getconf);	

	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 * set up the options for the '--to-stdout' option
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */
	if (do_to_stdout) {
		opt_preview = 1;
		g_verboseG = 1;
		g_stdout_testfd = STDOUT_FILENO;
		wopt_allow_rpm = CHARTRUE;
		set_opta(opta, SW_E_swbis_allow_rpm, "true");
	}

	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *   Configure the standard I/O usages.
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */

	fver = vstderr;
	fverfd = STDERR_FILENO;
	
	if (g_verboseG == 0 && opt_preview == 0) {
		fver = fopen("/dev/null", "r+");
		if (!fver) LCEXIT(1);
		vstderr = fver;
		fverfd = nullfd;
		dup2(nullfd, STDOUT_FILENO);
		dup2(nullfd, STDERR_FILENO);
	}

	if (g_verboseG >= SWC_VERBOSE_7) {
		swlib_set_verbose_level(g_verboseG);
	}
	
	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *   Set up the logger spec
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */
	swc_initialize_logspec(&g_logspec, eopt_logfile, g_loglevel);
	
	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *   Set the terminal setting and ssh tty option.
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */
	
	tty_opt = "-T";
	login_orig_termiosP = NULL;
	login_sizeP = NULL;
	
	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *        Set the signal handlers.
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */

	swgp_signal(SIGINT, safe_sig_handler);
	swgp_signal(SIGPIPE, safe_sig_handler);
	swgp_signal(SIGTERM, safe_sig_handler);

	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *           Process the source spec.
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */

	ret = swextopt_combine_directory(tmp,
			soc_spec_source,
			eopt_distribution_source_directory);
	if (ret) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec, get_stderr_fd(),
		"software source specification ambiguous or not valid: %s\n", soc_spec_source);
		LCEXIT(1);
	}

	if (soc_spec_source) {
		free(soc_spec_source);
		soc_spec_source = strdup(strob_str(tmp));
	}

	if (opt_preview) swssh_deactivate_sanity_check();
	swc_parse_soc_spec(
		soc_spec_source, 
		&cl_source_selections, 
		&xcl_source_target
		);

	if (cl_source_selections) {
		swlib_doif_writef(g_verboseG, g_fail_loudly, &g_logspec, get_stderr_fd(),
		"software selection feature for the source is ambiguous: %s\n", soc_spec_source);
		LCEXIT(1);
	}

	if (xcl_source_target == NULL) {
		cl_source_target = eopt_distribution_source_directory;
	} else {
		cl_source_target = xcl_source_target;
	}
			
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, &g_logspec, get_stderr_fd(), 
				"source spec: %s\n", cl_source_target);

	source_nhops = swssh_parse_target(source_sshcmd[0],
				source_kill_sshcmd[0],
				cl_source_target,
				remote_shell_path,
				remote_shell_command,
				&tmpcharp,
				&source_terminal_host,
				tty_opt, wopt_with_hop_pids, wopt_ssh_options);
	SWLIB_ASSERT(source_nhops >= 0);

	source_path = swc_validate_targetpath(
				source_nhops, 
				tmpcharp, 
				eopt_distribution_source_directory, cwd);
	SWLIB_ASSERT(source_path != NULL);

	if (source_nhops >= 1 && strcmp(source_path, "-") == 0) {
		swlib_doif_writef(g_verboseG, g_fail_loudly,
			&g_logspec, get_stderr_fd(),
			"remote stdin is not supported\n");
		LCEXIT(1);
	}

	if (strcmp(source_path, "-") == 0) { 
		if (stdin_in_use) {
			swlib_doif_writef(g_verboseG, g_fail_loudly, 
				&g_logspec, get_stderr_fd(),
				"invalid usage of stdin\n");
			LCEXIT(1);
		}
		local_stdin = 1; 
	}

	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *      Set the Serial archive write command.
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */

	if (pax_write_command_key == (char*)NULL) {
		if (source_nhops < 1) {
			pax_write_command_key = wopt_local_pax_write_command;
		} else {
			pax_write_command_key = wopt_remote_pax_write_command;
		}		
	}

	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *          Process the Software Selections
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */

	swspecs = vplob_open(); /* List object containing list of SWVERID objects */
	ret = 0;
	if (argv[optind]) {
		if (*(argv[optind]) != '@') {
			/*
			* Must be a software selection.
			*/
			ret = swc_process_selection_args(swspecs, argv, argc, &optind);
		}
	}

	if (ret) {
		/*
		 * Software selection error
		 */
		swlib_doif_writef(g_verboseG, g_fail_loudly, 
			&g_logspec, get_stderr_fd(),
				"error processing selections\n");
		LCEXIT(sw_exitval(target_loop_count, target_success_count));
	}

	if (vplob_get_nstore(swspecs) > 0)
	{
		/*
		 * Software selections not supported yet.
		 */
		char * xx = malloc(101);
		swlib_doif_writef(g_verboseG, g_fail_loudly, 
			&g_logspec, get_stderr_fd(),
		"software selections not implemented: %s\n", swverid_print((SWVERID*)(vplob_val(swspecs, 0)), xx, 100));
			LCEXIT(sw_exitval(target_loop_count, 
					target_success_count));
	}

	/*
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 *           Loop over the targets.
	 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
	 */

   	current_arg = swc_get_next_target(argv, argc, &optind, 
						g_targetfd_array, 
					opt_distribution_target_directory,
						&num_remains);
	while (current_arg) {
		/* if (target_loop_count) shutdown_logger(); */
		distdataO = swi_distdata_create();
		swgp_signal(SIGINT, safe_sig_handler);
		swgp_signal(SIGPIPE, safe_sig_handler);
		swgp_signal(SIGTERM, safe_sig_handler);
		statbytes = 0;
		retval = 0;
		target_tramp_list = strar_open();
		source_tramp_list = strar_open();
		target_sshcmd[0] = shcmd_open();
		target_cmdlist = strar_open();
		source_cmdlist = strar_open();
		source_control_message = strob_open(10);
		target_control_message = strob_open(10);
		target_start_message = strob_open(10);
		target_catalog_message = strob_open(10);
		source_start_message = strob_open(10);
		source_access_message = strob_open(10);
		cl_target_target = NULL;
		cl_target_selections = NULL;
		working_arg = strdup(current_arg);

		/*  Target Spec --- 
		 *   Parse the target sofware_selections and targets.
		 */

		soc_spec_target = strdup(working_arg);
		if (target_loop_count == 0) {
			swc_parse_soc_spec(
				soc_spec_target, 
				&cl_target_selections, 
				&xcl_target_target
				);
			if (xcl_target_target == NULL) {
				cl_target_target = strdup(opt_distribution_target_directory);
			} else {
				cl_target_target = strdup(xcl_target_target);
			}

			/*
			 * Selections are not supported here.  They are applied
			 * globally and processed before entering the target processing
			 * loop.
			 */
			if (cl_target_selections) {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
				&g_logspec, get_stderr_fd(),
			"software selection not valid when specified with a specific target.\n");
				LCEXIT(sw_exitval(target_loop_count, 
						target_success_count));
			}
		} else {
			/*
			 * subsequext args are targets, the same
			 * software selection applies.
			 */
			if (do_to_stdout) {
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
				&g_logspec, get_stderr_fd(),
				"invalid use\n");
				LCEXIT(sw_exitval(target_loop_count, 
						target_success_count));

			}
			cl_target_target = strdup(soc_spec_target);
		}

		if (strcmp(cl_target_target, "-") == 0) {
			/*
			 * Here the user gave the target as "@-"
			 * this should be the same as "--to-stdout"
			 */
			do_to_stdout = 1;
			cl_target_target = strdup("/");
			opt_preview = 1;
			g_verboseG = 1;
			g_stdout_testfd = STDOUT_FILENO;
			wopt_allow_rpm = CHARTRUE;
			set_opta(opta, SW_E_swbis_allow_rpm, "true");
		}

		target_nhops = swssh_parse_target(target_sshcmd[0],
				target_kill_sshcmd[0],
				cl_target_target,
				remote_shell_path,
				remote_shell_command,
				&tmpcharp,
				&target_terminal_host,
				tty_opt, wopt_with_hop_pids,
				wopt_ssh_options);
		SWLIB_ASSERT(target_nhops >= 0);

		if (target_nhops > 1 && wopt_pump_delay1 < 0) {
 			*swlib_get_io_req_p() = &g_io_req;
			g_io_req.tv_sec = 0;
			g_io_req.tv_nsec = DEFAULT_PUMP_DELAY;
		}
	
		if (xcl_target_target == NULL && target_nhops >= 1 && 
					strcmp(cl_target_target, "-") == 0) {
			/*
			 * writing to stdout on a remote host is not supported.
			 * Reset the the default target
			 */
			cl_target_target = strdup(".");
		}

		target_path = swc_validate_targetpath(
					target_nhops, 
					tmpcharp, 
					opt_distribution_target_directory, cwd);
		SWLIB_ASSERT(target_path != NULL);

		if (strcmp(target_path, "-") == 0 && target_nhops >= 1) {
			/*
			 * This is a useless mode, all it does is echo
			 * keystrokes through the ssh pipeline, I can't
			 * think of any practical usefullness.
			 *
			 * Run /bin/cat on the remote host.
			 *  e.g.    swinstall @localhost
			 * 
			 */
			swlib_doif_writef(g_verboseG, g_fail_loudly, 
						&g_logspec, get_stderr_fd(),
						"invalid target spec\n");
			LCEXIT(sw_exitval(target_loop_count, 
						target_success_count));
		}

		g_swevent_fd = swevent_fd;

		/*
		 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
		 *   Establish the logger process and stderr redirection.
		 * ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
		 */
		if (target_loop_count == 0) {
			g_logger_pid = swc_fork_logger(source_line_buf,
					target_line_buf, get_stderr_fd(),
					swevent_fd, &g_logspec, &g_s_efd, &g_t_efd,
					g_verboseG, /*NULL*/ &swi_event_fd);
		}

		g_swi_event_fd = swi_event_fd;
		target_stdio_fdar[2] = g_t_efd;
		source_stdio_fdar[2] = g_s_efd;
		swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
				&g_logspec, get_stderr_fd(), 
				"logger_pid is %d\n", g_logger_pid);

		swlib_doif_writef(g_verboseG, SWC_VERBOSE_3, 
			&g_logspec, swevent_fd,
			"SWBIS_TARGET_BEGINS for %s\n", current_arg);
	
		if (target_nhops && source_nhops) {
			/*
			 * disallow remote source *and* target if either is
			 * a double hop.  But allow it if both are single
			 * hops.
			 */
			if (target_nhops + source_nhops >= 3) {
			swlib_doif_writef(g_verboseG, g_fail_loudly, 
				&g_logspec, get_stderr_fd(),
		"simultaneous remote source and target is not supported.\n");
				LCEXIT(sw_exitval(target_loop_count, 
						target_success_count));
			}
		}	

		/*
		 * Set the fork type according to usage mode and user options.  
		 * Only use pty when required.
		 * If nhops is 1 then pty use seems not to be required.
		 */
		if ((target_nhops + source_nhops) == 1) {
			/*
			 * pseudo tty not needed
			 */
			if (wopt_pty) {
				pty_fork_type = g_fork_pty2;
			} else {
				pty_fork_type = g_fork_pty_none;
			}
		}

		if (source_nhops == 0 || wopt_no_pty || source_nhops > 1) {
			source_fork_type = g_fork_pty_none;
			if (wopt_pty_fork_type) 
				source_fork_type = wopt_pty_fork_type;
		} else {
			source_fork_type = pty_fork_type;
			if (wopt_pty_fork_type) 
				source_fork_type = wopt_pty_fork_type;
		}

		if (target_nhops == 0 || 
				wopt_no_pty || 
					target_nhops > 1) {
			target_fork_type = g_fork_pty_none;
			if (wopt_pty_fork_type) 
				target_fork_type = wopt_pty_fork_type;
		} else {
			target_fork_type = pty_fork_type;
			if (wopt_pty_fork_type) 
				target_fork_type = wopt_pty_fork_type;
		}
		if (target_nhops && source_nhops) {
			target_fork_type = g_fork_pty_none;
			source_fork_type =  g_fork_pty_none;
		}

		check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);

		if (pax_read_command_key == (char*)NULL) {
			if (target_nhops < 1) {
				pax_read_command_key = 
					wopt_local_pax_read_command;
			} else {
				pax_read_command_key = 
					wopt_remote_pax_read_command;
			}		
		}

		/*
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 *   Do the real install.
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 */
		swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, &g_logspec, get_stderr_fd(), 
				"target_fork_type : %s\n",
					target_fork_type);
		swlib_doif_writef(g_verboseG,
				SWC_VERBOSE_IDB2, &g_logspec, get_stderr_fd(), 
					"source_fork_type : %s\n",
					source_fork_type);

		/*
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 * Make the source piping.
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 */
		check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);
		if (local_stdin == 0) {
			/*
			 * Remote Source
			 */
			ss_pid = swc_run_ssh_command(
				source_sshcmd,
				source_cmdlist,
				source_path,
				opt_preview,
				source_nhops,
				source_fdar,
				source_stdio_fdar,
				login_orig_termiosP,
				login_sizeP, 
				&source_pump_pid, 
				source_fork_type, 
				make_master_raw, 
				(sigset_t*)fork_blockmask, 
				devel_no_fork_optimization,
				g_verboseG,
				&source_file_size,
				use_no_getconf,
				&is_source_local_regular_file,
				wopt_shell_command,
				get_stderr_fd(),
				&g_logspec);
			check_for_current_signals(__LINE__, g_signal_flag, 
						g_verboseG, 
						wopt_no_remote_kill);
			/* fprintf(stderr,"XABC200511  HERE %d\n", __LINE__); */

			if (is_source_local_regular_file) {
				if (lseek(source_fdar[0],
						(off_t)0, SEEK_SET) != 0) {
					swlib_doif_writef(g_verboseG, g_fail_loudly, 
						&g_logspec, get_stderr_fd(),
				"lseek internal error on stdio_fdar[0]\n");
					retval = 1;
					goto TARGET1;
				}
			} else {
				/* fprintf(stderr,"XABC200511  HERE %d %d\n", __LINE__, num_remains); */
				if (num_remains > 1) {
					/*
					* Can't have multiple targets unless
					* the source file is seekable.
					*/
					swlib_doif_writef(g_verboseG, g_fail_loudly, 
						&g_logspec, get_stderr_fd(),
				"multiple targets require the source to be a regular file.\n");
					retval = 1;
					goto TARGET1;
				}
			}

			if (ss_pid < 0) {
				/*
				 * Fatal
				 */		
				LCEXIT(sw_exitval(
					target_loop_count, 
					target_success_count));
			}

			if (ss_pid > 0) { 
				swc_record_pid(ss_pid, 
					g_pid_array, 
					&g_pid_array_len, 
					g_verboseG);
			}

			if (source_pump_pid > 0) {
				/*
				 * This is the child of slave 
				 * pty process, zero if there 
				 * isn't one.
				 */
				swc_record_pid(source_pump_pid, 
					g_pid_array, 
					&g_pid_array_len, 
					g_verboseG);
			}
			
			if (isatty(source_fdar[0])) {
				if (swlib_tty_raw(source_fdar[0]) < 0) {
					swlib_doif_writef(g_verboseG, 
						g_fail_loudly, 
						&g_logspec, get_stderr_fd(),
					"tty_raw error : source_fdar[0]\n");
					LCEXIT(
					sw_exitval(target_loop_count, 
						target_success_count));
				}
			}
		} else {
			/*
			 * here is the source piping for local stdin.
			 */ 
			ss_pid = 0;
			source_fdar[0] = source_stdio_fdar[0];
			source_fdar[1] = source_stdio_fdar[1];
			source_fdar[2] = source_stdio_fdar[2];

			if (target_loop_count > 0) {
				dup2(save_stdio_fdar[0], source_fdar[0]);
				is_local_stdin_seekable = 
					(lseek(source_fdar[0],
						(off_t)0,
						SEEK_CUR) >= 0);
				if (is_local_stdin_seekable) {
					if (lseek(source_fdar[0],
							0, SEEK_SET) != 0) {
						swlib_doif_writef(g_verboseG,
							g_fail_loudly,
							&g_logspec, get_stderr_fd(),
					"lseek internal error on source_fdar[0]\n");
						retval = 1;
						goto TARGET1;
					} else {
						;
					}
				} else {
					/*
					 * can't have multiple targets when the
					 * source is not not seekable
					 */
					swlib_doif_writef(g_verboseG,
						g_fail_loudly,
						&g_logspec, get_stderr_fd(),
						"source is not seekable,"
						" multiple targets not allowed\n");
					retval = 1;
					goto TARGET1;
				}
			}
		}

		if (is_local_stdin_seekable  || is_source_local_regular_file) {
			is_seekable = 1;
		} else {
			is_seekable = 0;
		}

		/*
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 * Write the source script.
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 */
		source_write_pid = run_source_script(
					swinstall_mode, 
				local_stdin || is_source_local_regular_file,
					source_fdar[1],
					source_path,
					source_nhops, 
					pax_write_command_key,
					fork_blockmask,
					fork_defaultmask,
					source_terminal_host,
					wopt_blocksize
					);
		check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG,
					wopt_no_remote_kill);

		if (source_write_pid > 0) {
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, 
				&g_logspec, get_stderr_fd(), 
				"waiting on source script pid\n");
			/*
		 	 * ==========================
			 * Wait on the source script.
			 * ==========================
			 */
			if ((ret=wait_on_script(source_write_pid, 
						"source")) != 0) {
				/*
			 	 * ====================================
				 * non zero is error for source script.
				 * ====================================
				 */
				swlib_doif_writef(g_verboseG, 
					g_fail_loudly, &g_logspec, get_stderr_fd(),
				"write_scripts waitpid : exit value = %d\n",
					ret );
				check_for_current_signals(__LINE__, g_signal_flag, 
						g_verboseG, 
						wopt_no_remote_kill);
				LCEXIT(
					sw_exitval(target_loop_count,	
						target_success_count));
			}
				
			swlib_doif_writef(g_verboseG, 
				SWC_VERBOSE_IDB, 
				&g_logspec, get_stderr_fd(), 
				"wait() on source script succeeded.\n");

			/*
			 * ===================================
			 * Read the start message and the pid
			 * ===================================
			 */
			if (read_start_ctl_message(
				source_fdar[0], 
				source_start_message,
				source_tramp_list,
				g_verboseG,
				&source_script_pid, "source") 
				< 0
			) 
			{
				/*
				 * start message failed.
				 */
				LC_RAISE(SIGTERM);
				check_for_current_signals(__LINE__,
					g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);
				swlib_doif_writef(g_verboseG, 1, 
					&g_logspec, get_stderr_fd(),
					"read_start_ctl_message error"
					" (loc=start)\n");
				LCEXIT(sw_exitval(
					target_loop_count, 
					target_success_count));
			}
			
			if (source_nhops >= wopt_kill_hop_threshhold) {
				/*
				 * Construct the remote kill vector.
				 */
				g_killcmd = NULL;
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
					&g_logspec, get_stderr_fd(), 
				"Running swc_construct_newkill_vector\n");
				if ((ret=swc_construct_newkill_vector(
					source_kill_sshcmd[0], 
					source_nhops,
					source_tramp_list, 
					source_script_pid, 
					g_verboseG)) < 0) 
				{
					source_kill_sshcmd[0] = NULL;
					swlib_doif_writef(g_verboseG, 
							g_fail_loudly, 
							&g_logspec, get_stderr_fd(),
					"source kill command not constructed"
					"(ret=%d), maybe a shell does not "
					"have PPID.\n", ret);
				}
				g_source_kmd = source_kill_sshcmd[0];
			}
			check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);

			/*
			 * ===================================
			 * Read the leading control message from the 
			 * output of the source script.
			 * This is how the target script knows to
			 * create a file or directory archive.
			 * ===================================
			 */
			if ( SWINSTALL_DO_SOURCE_CTL_MESSAGE ) {
				/*
				* Read the control message 
				* from the remote source.
				*/
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
					&g_logspec, get_stderr_fd(),
				"reading source script control messages\n"
								);

				if (read_target_ctl_message(
					source_fdar[0], 
					source_control_message,
					g_verboseG, "source") < 0) 
				{
					swlib_doif_writef(g_verboseG, 
						SWC_VERBOSE_IDB,
							&g_logspec, get_stderr_fd(),
						"read_target_ctl_message error"
						" (loc=source_start)\n");
					main_sig_handler(SIGTERM);
					LCEXIT(sw_exitval(
						target_loop_count,
						target_success_count));
				}
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
					&g_logspec, get_stderr_fd(),
					"Got source control message [%s]\n",
					strob_str(source_control_message));
			} else {
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, 
				&g_logspec, get_stderr_fd(), 
				"No source control message expected\n");
			}

			/*
			 * ===================================
			 * Read the SW_SOURCE_ACCESS_BEGIN or
			 * the SW_SOURCE_ACCESS_ERROR message
			 * ===================================
			 */	

			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
				&g_logspec, get_stderr_fd(),
				"reading source script access messages\n");
			if (read_target_ctl_message(
				source_fdar[0], 
				source_access_message,
				g_verboseG, "source") < 0
			) 
			{
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, 
						&g_logspec, get_stderr_fd(),
					"read_target_ctl_message error"
					" (loc=source_access)\n");
				main_sig_handler(SIGTERM);
				shutdown_logger(SIGABRT);
				LCEXIT(sw_exitval(
					target_loop_count,
					target_success_count));
			}
			
			/*
			 * =================================
			 * Analyze the source event.
			 * =================================
			 */	
			if ((ret=swevent_get_value(
					g_evnt, 
					strob_str(source_access_message))) != 
					SW_SOURCE_ACCESS_BEGINS) 
			{
				/*
				* Source access error.
				*/
				swlib_doif_writef(g_verboseG, 1, 
					&g_logspec, get_stderr_fd(),
					"source access error: ret=%d :%s\n",
					ret, 
					strob_str(source_access_message));
				main_sig_handler(SIGTERM);
				shutdown_logger(SIGABRT);
				LCEXIT(sw_exitval(
					target_loop_count,
					target_success_count));
			}
		} else if (source_write_pid == 0) {
			/* 
			 * ====================================
			 * fork did not happen.
			 * This is Normal, source script not required. 
			 * ====================================
			 */
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
				&g_logspec, get_stderr_fd(), 
				"No fork required for source control script\n"
				);
		} else {
			/*
			 * error
			 */
			swlib_doif_writef(g_verboseG, 1, &g_logspec, get_stderr_fd(),
				"fatal internal error. fork error.\n");
			main_sig_handler(SIGTERM);
			shutdown_logger(SIGABRT);
			LCEXIT(sw_exitval(
					target_loop_count, 
					target_success_count));
		}
		
		if (opt_preview && g_verboseG >= SWC_VERBOSE_8) {
			do_preview(
				fver, fverfd, 
				working_arg, source_control_message,
				local_stdin, 
				source_nhops, source_path,
				cl_source_target, source_fork_type,
				target_nhops, target_path,
				cl_target_target, target_fork_type,
				pax_read_command_key, target_sshcmd[0],
				target_kill_sshcmd[0], source_sshcmd[0],
				source_kill_sshcmd[0], SWC_SCRIPT_SLEEP_DELAY,
				wopt_keep_old_files, wopt_blocksize,
				use_no_getconf, pax_write_command_key,
				target_loop_count, swinstall_mode,
				wopt_shell_command, target_cmdlist,
				source_cmdlist, distdataO,
				eopt_installed_software_catalog,
				sh_dash_s, opt_alt_catalog_root,
				source_terminal_host, target_terminal_host);
		}

		/*
		 * ===================================
		 * Decode the package catalog section
		 * ===================================
		 */
		if (swi) {
			xformat_close(swi->xformatM);
			swi_delete(swi);
			if (uxfio_lseek(source_fdar[0], 0, SEEK_SET) != 0) {
				fprintf(stderr, "%s: uxfio_lseek error: %s : %d\n",
					swlib_utilname_get(),  __FILE__, __LINE__);
				exit(2);
			}
		}

		E_DEBUG("into do_decode");
		swgp_signal(SIGINT, main_sig_handler);
		swi = swi_create();
		SWLIB_ASSERT(swi != NULL);
		ret = swi_do_decode(swi, swutil, g_nullfd,
			dup(source_fdar[0]),
			target_path,
			source_path,
			swspecs,
			target_terminal_host,
			opta,
			is_seekable,
			wopt_debug_events, g_verboseG, &g_logspec);
		g_xformat = swi->xformatM;
		E_DEBUG("out of do_decode");

		if (ret) {
			swlib_doif_writef(g_verboseG,
				g_fail_loudly,
				&g_logspec, get_stderr_fd(),
				"error decoding source\n");
			main_sig_handler(SIGTERM);
			shutdown_logger(SIGABRT);
			LCEXIT(sw_exitval(
				target_loop_count, 
				target_success_count));
		}

		swi->sh_dash_sM = strdup(sh_dash_s);
		swi->dash_rM = opt_alt_catalog_root;
		swi->swi_pkgM->target_pathM = strdup(target_path);
		swi->swi_pkgM->installed_software_catalogM = strdup(
				get_opta(opta, SW_E_installed_software_catalog));

		if (swlib_check_clean_path(swi->swi_pkgM->target_pathM)) {
			SWLIB_FATAL("tainted path");
		}

		if (swlib_check_clean_path(swi->swi_pkgM->installed_software_catalogM)) {
			SWLIB_FATAL("tainted path");
		}
		
		/*
		 * FIXME, eventually need to support a catalog location that is
		 * outside of the target path
		 */
		swlib_squash_all_leading_slash(swi->swi_pkgM->installed_software_catalogM);

		swicol_set_targetpath(swi->swicolM, target_path);
		swicol_set_delaytime(swi->swicolM, SWC_SCRIPT_SLEEP_DELAY);
		swicol_set_nhops(swi->swicolM, target_nhops);
		swicol_set_verbose_level(swi->swicolM, g_verboseG);


		/* fprintf(stderr, "JL catalog length = %d\n", swi->swi_pkgM->catalog_lengthM); 
		*/

		/*
		 * ==========================================
		 * Get the product tag(s) and revision(s) and
		 * other metadata needed by the target script
		 * ==========================================
		 */
		if (distdataO->did_part1M == 0) {
			retval = swi_distdata_resolve(swi, distdataO,
						1 /*enforce swinstall policy*/);
			if (retval) {
				swlib_doif_writef(g_verboseG,
					g_fail_loudly,
					&g_logspec, get_stderr_fd(),
			"error decoding source INDEX file: swbis_code=%d\n",
					retval);
				LCEXIT(sw_exitval(
					target_loop_count, 
					target_success_count));
	
			}
			distdataO->did_part1M = 1;
		}


		/*
		 * ++++++++++++++++++++++++++++++++++ 
		 * Make the target piping.
		 * ++++++++++++++++++++++++++++++++++ 
		 */
		check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);
		ts_pid = swc_run_ssh_command(
			target_sshcmd,
			target_cmdlist,
			target_path,
			opt_preview,
			target_nhops,
			target_fdar,
			target_stdio_fdar,
			login_orig_termiosP,
			login_sizeP, 
			&target_pump_pid,
			target_fork_type, 
			make_master_raw, 
			(sigset_t*)fork_blockmask,
			0 /*devel_no_fork_optimization*/,
			g_verboseG,
			&target_file_size,
			use_no_getconf,
			(int*)(NULL),
			wopt_shell_command,
			get_stderr_fd(),
			&g_logspec);
		check_for_current_signals(__LINE__, g_signal_flag,
					g_verboseG,
					wopt_no_remote_kill);
		if (ts_pid < 0) {
			swlib_doif_writef(g_verboseG, 
				g_fail_loudly, 
				&g_logspec, get_stderr_fd(),
				"fork error : %s\n", strerror(errno));
			shutdown_logger(SIGABRT);
			LCEXIT(sw_exitval(target_loop_count, 
					target_success_count));
		}
		if (ts_pid)
			swc_record_pid(ts_pid, g_pid_array,
				&g_pid_array_len,
				g_verboseG);

		if (target_pump_pid > 0) {
			/*
			 * ================
			 * This is the child of slave pty process, 
			 * zero if there isn't one.
			 * ================
			 */
			swc_record_pid(target_pump_pid,
					g_pid_array,
					&g_pid_array_len, 
					g_verboseG);
		}

		if (isatty(target_fdar[0])) {
			if (swlib_tty_raw(target_fdar[0]) < 0) {
				swlib_doif_writef(g_verboseG, 
						g_fail_loudly,	
						&g_logspec, get_stderr_fd(),
				"tty_raw error : target_fdar[0]\n");
				shutdown_logger(SIGABRT);
				LCEXIT(sw_exitval(
					target_loop_count,
					target_success_count));
			}
		}
		/*
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 * Write the target script.
		 * +++++++++++++++++++++++++++++++++++++++++++++++++ 
		 */
		target_write_pid = run_target_script(
					target_fdar[1],
					source_path,
					target_path,
					source_control_message,
					wopt_keep_old_files, 
					target_nhops,
					pax_read_command_key,
					fork_blockmask,
					fork_defaultmask,
					target_terminal_host,
					wopt_blocksize,
					distdataO,
					eopt_installed_software_catalog,
					opt_preview,
					sh_dash_s, opt_alt_catalog_root
					);
		check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);

		if (target_write_pid > 0) {
			/*
			 * ==========================
			 * Wait on the target script.
			 * ==========================
			 */
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB,
						&g_logspec, get_stderr_fd(), 
					"waiting on target script pid\n");
			if ((ret=wait_on_script( target_write_pid,
							"target")) != 0) {
				/*
				 * ================================
				 * zero is error for target script.
				 * ================================
				 */
				swlib_doif_writef(g_verboseG, 
					g_fail_loudly, &g_logspec, get_stderr_fd(),
					"write_scripts waitpid : exit value"
					" = %d which is an error.\n",
						 ret );
				LC_RAISE(SIGTERM);
				check_for_current_signals(__LINE__, g_signal_flag, 
							g_verboseG, 
							wopt_no_remote_kill);
				shutdown_logger(SIGABRT);
				LCEXIT(sw_exitval(
						target_loop_count, 
						target_success_count));
			}
			if (ret == 0) {
				/*
				 * ================
				 * Normal exit, OK
				 * ================
				 */
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2,
					&g_logspec, get_stderr_fd(), 
					"OK: target script returned %d\n", ret);
			} else {
				/*
				 * =====
				 * Error
				 * =====
				 */
				swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2,
					&g_logspec, get_stderr_fd(), 
					"Error: target script returned %d\n", ret);
			}
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, 
				&g_logspec, get_stderr_fd(), 
				"wait() on target script succeeded.\n");

			/*
			 * ===============================
			 * read the start control message.
			 * ===============================
			 */
			ret = read_start_ctl_message(
				target_fdar[0], 
				target_start_message, 
				target_tramp_list,
				g_verboseG,
				&target_script_pid, "target");
			if (ret < 0) {
				/*
				 * ==================================
				 * Read of the start message failed.
				 * ==================================
				 */

				/*
				 * This is (may be) the failure path for ssh authentication
				 * failure.
				 */
		
				/*
				 * See if the ssh command has finished.
				 */
				if (waitpid(ts_pid, &tmp_status, WNOHANG) > 0) {
					/*
					 * Store the result in the status array.
					 */
					SWLIB_ASSERT(
						swlib_update_pid_status(ts_pid, tmp_status,
							pid_array, status_array, *p_pid_array_len) == 0);
				}
				if (WIFEXITED(tmp_status)) {
					/*
					 * This is the exit status of ssh (or rsh)
					 */
					tmpret = WEXITSTATUS(tmp_status);
					swlib_doif_writef(g_verboseG, SWC_VERBOSE_1,
						&g_logspec, get_stderr_fd(),
						"SW_AGENT_INITIALIZATION_FAILED for target %s: status=%d\n",
						current_arg,
						tmpret);
				} else {
					swlib_doif_writef(g_verboseG, SWC_VERBOSE_1,
						&g_logspec, get_stderr_fd(),
						"SW_INTERNAL_ERROR for target %s in file %s at line %d\n",
						current_arg, __FILE__, __LINE__);
				}
				/*
				 * Continue with next target.
				 */
				goto ENTER_WITH_FAILURE;
			}

			/*
			 * ===============================
			 * read catalog path message,
			 * either 128 or 508
			 * ===============================
			 */
			ret = read_catalog_ctl_message(
				target_fdar[0],
				target_catalog_message,
				g_verboseG,
				"catalog",
				eopt_installed_software_catalog);
			if (ret < 0) {
				/*
				 * ==================================
				 * error message
				 * ==================================
				 */
				swlib_doif_writef(g_verboseG, g_fail_loudly, 
					&g_logspec, get_stderr_fd(),
					"catalog path analysis for target %s: ret=%d\n",
					current_arg,
					ret);
				/*
				 * This is the exit path for failed remote 
				 * connection, shunt this to the loop end to 
				 * support continuation of the target list.
				 */
				goto ENTER_WITH_FAILURE;
			}

			/*
			 * Continue with installation.
			 * The script should now determine the catalog path.
			 */

			/*
			 * Get the uname attributes from the target host.
			 */
			vofd = target_fdar[1];
			if (swinstall_get_utsname_attributes(swi, vofd, swi_event_fd)) {
				SWLIB_ASSERT(0);
			}

			if (target_nhops >= wopt_kill_hop_threshhold /*2*/ ) {
				/*
				 * ==============================
				 * Construct the clean-up command 
				 * to shutdown remote script.
				 * ==============================
				 */ 
				g_killcmd = NULL;
				if ((ret=swc_construct_newkill_vector(
					target_kill_sshcmd[0], 
					target_nhops,
					target_tramp_list, 
					target_script_pid, 
					g_verboseG)) < 0) 
				{
					target_kill_sshcmd[0] = NULL;
					swlib_doif_writef(g_verboseG, 
						g_fail_loudly, 
						&g_logspec, get_stderr_fd(),
				"target kill command not constructed (ret=%d)"
				", maybe a shell does not have PPID.\n",
								ret);
				}
				g_target_kmd = target_kill_sshcmd[0];
			}
			swi->swi_pkgM->catalog_entryM = strdup(strob_str(target_catalog_message));
			if (swlib_check_clean_path(swi->swi_pkgM->catalog_entryM)) {
				swlib_doif_writef(g_verboseG, g_fail_loudly,
					&g_logspec, get_stderr_fd(),
					"fatal internal error. target script"
					" catalog entry path error\n");
				shutdown_logger(SIGABRT);
				LCEXIT(sw_exitval(
					target_loop_count, 
					target_success_count));
			}
		} else {
			/*
			 * error
			 */
			swlib_doif_writef(g_verboseG, g_fail_loudly,
				&g_logspec, get_stderr_fd(),
				"fatal internal error. target script"
				" fork error target_write_pid=%d\n", target_write_pid);
			shutdown_logger(SIGABRT);
			LCEXIT(sw_exitval(
				target_loop_count, 
				target_success_count));
		}

		check_for_current_signals(__LINE__, g_signal_flag, 
				g_verboseG, 
				wopt_no_remote_kill);

		if (ts_pid && 
			waitpid(ts_pid, &tmp_status, WNOHANG) > 0) {
			shutdown_logger(SIGABRT);
			LCEXIT(sw_exitval(
				target_loop_count, 
				target_success_count));
		}
				
		if (
			(isatty(g_meter_fd)) &&
			((
			g_verboseG >= 2 &&
			is_option_true(wopt_quiet_progress_bar) == 0
			) || 
			(
			g_verboseG >= 1 &&
			is_option_true(wopt_show_progress_bar) == 1
			))
		) {
			*p_do_progressmeter = 1;
		}

		if (g_verboseG >= SWC_VERBOSE_8) {
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
				&g_logspec, get_stderr_fd(),
				"target_fdar[0] = %d\n", target_fdar[0]);
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
				&g_logspec, get_stderr_fd(),
				"target_fdar[1] = %d\n", target_fdar[1]);
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
				&g_logspec, get_stderr_fd(),
				"target_fdar[2] = %d\n", target_fdar[2]);
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
				&g_logspec, get_stderr_fd(),
				"source_fdar[0] = %d\n", source_fdar[0]);
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
				&g_logspec, get_stderr_fd(),
				"source_fdar[1] = %d\n", source_fdar[1]);
			swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB2, 
				&g_logspec, get_stderr_fd(),
				"source_fdar[2] = %d\n", source_fdar[2]);
		}
			
		tty_raw_ctl(2);
		ret = 0;

		if (strstr(strob_str(source_control_message), 
			"SW_SOURCE_ACCESS_ERROR :") != 
			(char*)NULL) {
			/*
			 * Error
			 */	
			swlib_doif_writef(g_verboseG, 
				g_fail_loudly, &g_logspec, get_stderr_fd(),
				"SW_SOURCE_ACCESS_ERROR : []\n"
				);
			shutdown_logger(SIGABRT);
			LCEXIT(sw_exitval(
				target_loop_count, 
				target_success_count));
		}

		check_for_current_signals(__LINE__, g_signal_flag, 
				g_verboseG, 
				wopt_no_remote_kill);
		/*
		 * --------------------------------------
		 *  Install it.
		 * --------------------------------------
		 */
		
		if (g_verboseG >= SWC_VERBOSE_7) {
			tmp_s = swi_dump_string_s(swi, "swinstall: (SWI*)");
			fprintf(fver, "%s\n", tmp_s);
		}

		ret = do_install(
			swi,
			target_fdar[1],
			g_t_efd,
		 	&statbytes,
		 	*p_do_progressmeter,
		 	source_file_size,
			target_path,
		 	working_arg,
			swspecs,
			distdataO,
			strob_str(target_catalog_message),
			opt_preview,
			pax_read_command_key,
			wopt_keep_old_files,
			opt_alt_catalog_root,
			swi_event_fd,
			opta);
		if (ret) retval++;
		
		check_for_current_signals(__LINE__, g_signal_flag,
				 g_verboseG,
				wopt_no_remote_kill);

ENTER_WITH_FAILURE:

		if (kill_sshcmd[0]) {
			shcmd_close(kill_sshcmd[0]);
			kill_sshcmd[0] = (SHCMD*)NULL;
		}

		if (target_kill_sshcmd[0]) {
			shcmd_close(target_kill_sshcmd[0]);
			target_kill_sshcmd[0] = (SHCMD*)NULL;
		}

		if (source_kill_sshcmd[0]) {
			shcmd_close(source_kill_sshcmd[0]);
			source_kill_sshcmd[0] = (SHCMD*)NULL;
		}

		/*
		 * Now close down.
		 */
		check_for_current_signals(__LINE__, g_signal_flag, 
					g_verboseG, 
					wopt_no_remote_kill);
		close(target_fdar[0]);
		if (target_fdar[1] != STDOUT_FILENO) 
			close(target_fdar[1]);
		if (source_fdar[0] != STDIN_FILENO)
			close(source_fdar[0]);
		if (source_fdar[1] != STDOUT_FILENO)
			close(source_fdar[1]);

		swlib_wait_on_all_pids(
				pid_array, 
				*p_pid_array_len, 
				status_array, 0 /*waitpid flags*/, 
				g_verboseG - 2);

		if (retval == 0) {
			retval = swc_analyze_status_array(pid_array,
						*p_pid_array_len, 
						status_array,
						g_verboseG - 2);
		}
		if (retval == 0 && ret ) retval++;
		/*
		 * Now re-Initialize.
		 */
		*p_pid_array_len = 0;

		if (soc_spec_target) free(soc_spec_target);
		soc_spec_target = NULL;

		if (working_arg) free(working_arg);
		working_arg = NULL;

		if (cl_target_target) free(cl_target_target);
		cl_target_target = NULL;
		
		if (cl_target_selections) free(cl_target_selections);
		cl_target_selections = NULL;

		if (target_path) free(target_path);
		target_path = NULL;

		/* End real copy, not a preview */
TARGET1:
		g_pid_array_len = 0;

		check_for_current_signals(__LINE__, g_signal_flag, 
						g_verboseG, 
						wopt_no_remote_kill);
		strar_close(target_tramp_list);
		strar_close(source_tramp_list);
		shcmd_close(target_sshcmd[0]);
		strar_close(target_cmdlist);
		strar_close(source_cmdlist);
		strob_close(source_control_message);
		strob_close(target_control_message);
		strob_close(target_start_message);
		strob_close(target_catalog_message);
		strob_close(source_start_message);
		strob_close(source_access_message);

		if (source_script_pid) free(source_script_pid);
		source_script_pid = NULL;
		if (target_script_pid) free(target_script_pid);
		target_script_pid = NULL;

		target_loop_count++;
		if (retval == 0) target_success_count++;
		swlib_doif_writef(g_verboseG, SWC_VERBOSE_3, &g_logspec, retval ? get_stderr_fd() : swevent_fd,
			"SWBIS_TARGET_ENDS for %s: status=%d\n",
						current_arg,
						retval);
		check_for_current_signals(__LINE__, g_signal_flag, 
						g_verboseG, 
						wopt_no_remote_kill);
		free(current_arg);
   		current_arg = swc_get_next_target(argv, 
						argc, 
						&optind, 
						g_targetfd_array,
					opt_distribution_target_directory, &num_remains);
	} /* target loop */
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, 
			&g_logspec, get_stderr_fd(), "Finished processing targets\n");
	if (targetlist_fd >= 0) close(targetlist_fd);
	swlib_doif_writef(g_verboseG, SWC_VERBOSE_IDB, &g_logspec, get_stderr_fd(), 
		"exiting at %s:%d with value %d\n",
		__FILE__, __LINE__,
		sw_exitval(target_loop_count, target_success_count));

	swlib_doif_writef(g_verboseG, SWC_VERBOSE_6, 
			&g_logspec, get_stderr_fd(), "SWI_NORMAL_EXIT: status=%d\n",
		sw_exitval(target_loop_count, target_success_count));

	if (	do_to_stdout &&
		sw_exitval(target_loop_count, target_success_count) == 0
	) {
		/*
		 * Write the NUL trailer blocks for the --to-stdout mode
		 */
		swinstall_lib_write_trailer_blocks(STDOUT_FILENO, 2);
	}

	swutil_close(swutil);
	shutdown_logger(SIGTERM);
	return(sw_exitval(target_loop_count, target_success_count));	
}
