#!/sbin/sh
#
# (c)Copyright 1997 Hewlett-Packard Co.,  All Rights Reserved.
# $Header: /ignite/cold_fusion/src/server_admin/save_config 10.43 1998/06/10 16:19:35 hmgr Exp $
# $Revision: 10.43 $
#

PATH=/usr/bin:/usr/sbin:/sbin
unset LANG

#
# Function to print out usage statement to stderr.
# 
# Optional argument is a string to be printed first to stderr.
#

usage()
{
    [[ $# -eq 1 ]] && print -u2 -- $command: $1
    print -u2 "Usage: $command [ -f <config_file>] [<vg> ...] [/dev/dsk/<name> ...]"
    exit 1
}

#
# Function to print out fatal error message to stderr.
#
# Optional argument is string to be printed first to stderr.
#
# Any temporary files left laying around are deleted.
#

fatal()
{
    [[ $# -eq 1 ]] && print -u2 -- $command: error - $1
    rm -f $config_temp_file $vgdisplay_temp_file
    rm -f $lvdisplay_temp_file $mount_temp_file
    rm -f $tunefs_temp_file $ifconfig_temp_file
    rm -f $netstat_temp_file $swapinfo_temp_file
    rm -f $lvlnboot_temp_file $mkfs_temp_file
    rm -f $whole_disk_temp_file $ioscan_temp_file
    rm -f $pvg_disks_temp_file $all_disks_temp_file
    exit 2
}

#
# Function to print out a warning message
#
# Argument is string to be printed first to stderr.
#

warning()
{
    print -u2 -- $command: warning - $1
    return 0
}

#
# Function to map a disk to a path (i.e. /dev/dsk/c1t60 to 52.6.0)
#
# Argument is a block device file
#
# This is the same algorithm used in bootsys_prep.  It takes care of the
# differences in output of lssf between SCSI and HPFL disks.
#
# If neither of these are found, issue fatal error
#

disk_to_path()
{
    hw_path=""
    hw_path=$(lssf $1 | 
              awk 'BEGIN { p="unknown" }
                         { for(x=1; x< NF; x++) if ($x == "address") p=$(x+1)}
                     END { print p }')
    if [[ $hw_path = "unknown" ]]
    then
        fatal "unknown disk type for $1, not SCSI or HPFL"
    fi
    echo $hw_path
    return
}

#
# Function to check if a disk is part of a volume grouop
#
# Argument is disk device file name
#
# Outputs 0 if disk is in a volume group, 1 otherwise
#

is_disk_in_vg()
{
    # Check to see if disk is part of VG

    vgdisplay -v 2>/dev/null | grep "PV Name" |
    while read x y disk trash
    do
        if [[ $1 = $disk ]]
        then
	    echo 0
            return
        fi
    done
    echo 1
}

#
# Function to process one volume group.  It appends all the data to the
# temporary config file.
#
# Argument is a vg name (e.g. vg00)
#

process_volume_group()
{
    # Cache away information on volume group

    vgdisplay -v $1 >$vgdisplay_temp_file 2>/dev/null

    # If vgdisplay fails, exit with an error message

    if [[ $? -ne 0 ]]
    then
	fatal "vgdisplay -v $1 returned non-zero status"
    fi

    # Print out header information

    print -u4 "\tvolume_group \"$1\" {"

    # Print information from vgdisplay

    max_phy_extents=$(grep "^Max PE per PV" $vgdisplay_temp_file | awk ' { print $5 } ' )
    print -u4 "\t\tmax_physical_extents=$max_phy_extents"
    max_log_vols=$(grep "^Max LV" $vgdisplay_temp_file | awk ' { print $3 } ' )
    print -u4 "\t\tmax_logical_vols=$max_log_vols"
    max_phy_vols=$(grep "^Max PV" $vgdisplay_temp_file | awk ' { print $3 } ' )
    print -u4 "\t\tmax_physical_vols=$max_phy_vols"
    physical_extent_size=$(grep "^PE Size" $vgdisplay_temp_file | awk ' { print $4 } ' )
    print -u4 "\t\tphysical_extent_size=$physical_extent_size"

    # Print minor number

    minor_number=$(ls -l /dev/$1/group | awk ' { print substr($6,3,2) } ' )
    print -u4 "\t\tminor_number=0x$minor_number"

    # See if the volume group has any physical volume groups

    num_pvg=$(grep "Total PVG" $vgdisplay_temp_file | awk ' { print $3 } ' )

    if [[ $num_pvg -eq 0 ]]
    then

        # There are no physical volume groups. Loop through all the physical
        # volumes in the volume group

        grep "PV Name" $vgdisplay_temp_file |
        while read x y disk trash
        do

	    # Check whether disk was specified on command line as well

	    d=0
	    while [[ $d -lt $num_disk_list ]]
	    do
	        if [[ $disk = ${disk_list[$d]} ]]
	        then
		    fatal "cannot have $disk as argument as it is part of $1 volume group"
	        fi
	        (( d += 1 ))
	    done

	    # Print out physical volume disks. Take care of _hp_root_disk

	    if [[ $disk = $root_disk ]]
	    then
	        print -u4 "\t\tphysical_volume disk[_hp_root_disk] {"
	        print -u4 "\t\t} # end pv_options"
	    else
	        print -u4 "\t\tphysical_volume disk[$(disk_to_path $disk)] {"
	        print -u4 "\t\t} # end pv_options"
	    fi
        done

    else

	# There are physical volume groups
	in_pvg=0
	rm -f $pvg_disks_temp_file

	while read pvg name data
	do
	    if [[ "$pvg" = "PVG" && "$name" = "Name" ]]
	    then
		if [[ $in_pvg -eq 1 ]]
		then
	            print -u4 "\t\t} # end physical_volume group \"$pvg_name\""
		    in_pvg=0
		fi
		in_pvg=1
		pvg_name=$data
	        print -u4 "\t\tphysical_volume group \"$pvg_name\" {"
	    elif [[ $in_pvg -eq 1 && "$pvg" = "PV" && "$name" = "Name" ]]
	    then
	        # Check whether disk was specified on command line as well

	        d=0
	        while [[ $d -lt $num_disk_list ]]
	        do
	            if [[ $data = ${disk_list[$d]} ]]
	            then
		        fatal "cannot have $disk as argument as it is part of $1 volume group"
	            fi
	            (( d += 1 ))
	        done

	        # Print out physical volume disks. Take care of _hp_root_disk

		echo $data >> $pvg_disks_temp_file
	        if [[ $data = $root_disk ]]
	        then
	            print -u4 "\t\t\tphysical_volume disk[_hp_root_disk] {"
	            print -u4 "\t\t\t} # end pv_options"
	        else
	            print -u4 "\t\t\tphysical_volume disk[$(disk_to_path $data)] {"
	            print -u4 "\t\t\t} # end pv_options"
	        fi
	    fi
	done < $vgdisplay_temp_file
	print -u4 "\t\t} # end physical_volume group \"$pvg_name\""

	# See if there are any disks in the volume group which were not
	# part of a physical volume group

	grep "PV Name" $vgdisplay_temp_file | awk ' { print $3 } ' |
	sort -u -o $all_disks_temp_file
	sort -o $pvg_disks_temp_file $pvg_disks_temp_file
	cmp -s $pvg_disks_temp_file $all_disks_temp_file
	if [[ $? -ne 0 ]]
	then
	    comm -13 $pvg_disks_temp_file $all_disks_temp_file |
	    while read disk
	    do
	        # Check whether disk was specified on command line as well

	        d=0
	        while [[ $d -lt $num_disk_list ]]
	        do
	            if [[ $disk = ${disk_list[$d]} ]]
	            then
		        fatal "cannot have $disk as argument as it is part of $1 volume group"
	            fi
	            (( d += 1 ))
	        done

	        # Print out physical volume disks. Take care of _hp_root_disk

	        if [[ $disk = $root_disk ]]
	        then
	            print -u4 "\t\tphysical_volume disk[_hp_root_disk] {"
	            print -u4 "\t\t} # end pv_options"
	        else
	            print -u4 "\t\tphysical_volume disk[$(disk_to_path $disk)] {"
	            print -u4 "\t\t} # end pv_options"
	        fi
	    done
	fi
	rm -f $pvg_disks_temp_file $all_disks_temp_file

    fi

    # Loop through all the logical volumes in volume group

    grep "LV Name" $vgdisplay_temp_file |
    while read x y vg trash
    do

	# Print out logical volume header

	vg_name=$(dirname $vg)
	lvol_name=$(basename $vg)
	print -u4 "\t\tlogical_volume \"$lvol_name\" {"

	# Print out logical volume information. Use fstyp to determine
	# volume group usage.  Swap, dump and unused partitions will
	# return a "unknown_fstyp (no matches)" message

	vg_usage=$(fstyp $vg 2>&1)
	if [[ $vg_usage = "hfs" ]]
	then

	    # Note: fstyp will return hfs even if filesystem on logical
	    # volume is unmounted.  First see if it's mounted.

	    grep -q $vg $mount_temp_file
	    if [[ $? -eq 0 ]]
	    then

		# The filesystem on this volume group is actually mounted

		print -u4 "\t\t\tusage=HFS"

		# Use tunefs and mkfs to gather data on HFS logical volume

		tunefs -v $vg > $tunefs_temp_file
		mkfs -F hfs -m $vg > $mkfs_temp_file

		# Print out HFS logical volume information. Since the
		# sector size is DEV_BSIZE (1K) just use KB as units

		size=$(awk ' { print $(NF - 8) } ' $mkfs_temp_file )
		print -u4 "\t\t\tsize=${size}KB"
		mount_point=$(grep "$vg " $mount_temp_file | awk ' { print $2 } ' )
		print -u4 "\t\t\tmount_point=\"$mount_point\""
		minfree=$(awk ' { print $(NF - 2) } ' $mkfs_temp_file )
		print -u4 "\t\t\tminfree=${minfree}"
		file_length=$(awk ' { print $4 } ' $mkfs_temp_file )
		if [[ "$file_length" = "-S" ]]
		then
		    print -u4 "\t\t\tfile_length=SHORT"
		elif [[ "$file_length" = "-L" ]]
		then
		    print -u4 "\t\t\tfile_length=LONG"
		else
		    fatal "unable to determine file system length"
		fi
		blksize=$(awk ' { print $(NF - 5) } ' $mkfs_temp_file )
		print -u4 "\t\t\tblksize=${blksize}"
		fragsize=$(awk ' { print $(NF - 4) } ' $mkfs_temp_file )
		print -u4 "\t\t\tfragsize=${fragsize}"
		ncpg=$(awk ' { print $(NF - 3) } ' $mkfs_temp_file )
		print -u4 "\t\t\tncpg=${ncpg}"
		nbpi=$(awk ' { print $NF } ' $mkfs_temp_file )
		print -u4 "\t\t\tnbpi=${nbpi}"
		rotdelay_ms=$(grep rotdelay $tunefs_temp_file | awk ' { print $4 } ')
		rotdelay=${rotdelay_ms%ms}
		print -u4 "\t\t\trotational_delay=${rotdelay}"
		if [[ -x /usr/sbin/fsadm && $(uname -r) > "B.10.10" ]]
		then
		    # Use fsadm to check largefiles setting on block
		    # device file for HFS
		    vg_part=$(dirname $vg)
		    lvol_part=$(basename $vg)
		    rvg=${vg_part}/r${lvol_part}
		    nolargefiles=$(fsadm -F hfs $rvg 2>/dev/null | grep supports | grep nolargefiles)
		    if [[ -n $nolargefiles ]]
		    then
		        print -u4 "\t\t\tlargefiles=FALSE"
		    else
		        print -u4 "\t\t\tlargefiles=TRUE"
		    fi
		fi
		rm -f $tunefs_temp_file $mkfs_temp_file
	    else

		# Logical volume has an umounted HFS file system on it

		warning "$vg has an unmounted HFS filesystem on it"
		print -u4 "\t\t\tusage=Unused"
		size=$(lvdisplay $vg | grep "LV Size" | awk ' { print $4 } ' )
		print -u4 "\t\t\tsize=${size}MB"

	    fi
	elif [[ $vg_usage = "unknown_fstyp (no matches)" ]]
	then

	# Check to see if this is a swap partition

	    lvlnboot -v $vg_name > $lvlnboot_temp_file
	    grep -q "$vg$" $swapinfo_temp_file
	    if [[ $? -eq 0 ]]
	    then

		# Now check to see if it's also a dump partition

	        grep $vg_name $lvlnboot_temp_file | grep -q "^Boot"
	        if [[ $? -eq 0 ]]
	        then
	            grep $lvol_name $lvlnboot_temp_file | grep -q "^Dump:"
	            if [[ $? -eq 0 ]]
	            then
	                print -u4 "\t\t\tusage=SWAP_DUMP"
	            else
	                print -u4 "\t\t\tusage=SWAP"
		    fi
	        else
	            print -u4 "\t\t\tusage=SWAP"
		fi

		# Print out swap or swap_dump logical volume information

		size=$(grep "$vg$" $swapinfo_temp_file | awk ' { print $2 } ' )
		print -u4 "\t\t\tsize=${size}KB"

	    else

		# Check to see if this is just a dump partition.
		# Otherwise it is unused.  This can happen when a lvol
		# is too small for swapon to accept for example.

	        grep $vg_name $lvlnboot_temp_file | grep -q "^Boot"
	        if [[ $? -eq 0 ]]
	        then
	            grep $lvol_name $lvlnboot_temp_file | grep -q "^Dump:"
	            if [[ $? -eq 0 ]]
	            then
	                print -u4 "\t\t\tusage=DUMP"
	            else
		        print -u4 "\t\t\tusage=Unused"
		    fi
	        else
		    print -u4 "\t\t\tusage=Unused"
		fi

		size=$(lvdisplay $vg | grep "LV Size" | awk ' { print $4 } ' )
		print -u4 "\t\t\tsize=${size}MB"

	    fi
	elif [[ $vg_usage = "vxfs" ]]
	then

	    # Note: fstyp will return vxfs even if filesystem on logical
	    # volume is unmounted.  First see if it's mounted.

	    grep -q $vg $mount_temp_file
	    if [[ $? -eq 0 ]]
	    then

		# The filesystem on this volume group is actually mounted

		print -u4 "\t\t\tusage=VxFS"

		# Use mkfs to gather data on VxFS logical volume.  Since
		# the sector size is DEV_BSIZE (1K) just use KB as units

		size=$(mkfs -F vxfs -m $vg | awk ' { print $NF } ' )
		print -u4 "\t\t\tsize=${size}KB"
		mount_point=$(grep "$vg " $mount_temp_file | awk ' { print $2 } ' )
		print -u4 "\t\t\tmount_point=\"$mount_point\""
		if [[ -x /usr/sbin/fsadm && $(uname -r) > "B.10.10" ]]
		then
		    # Use fsadm to check largefiles setting on character
		    # device file for VxFS
		    vg_part=$(dirname $vg)
		    lvol_part=$(basename $vg)
		    rvg=${vg_part}/r${lvol_part}
		    nolargefiles=$(fsadm -F vxfs $rvg 2>/dev/null | grep nolargefiles)
		    if [[ -n $nolargefiles ]]
		    then
			print -u4 "\t\t\tlargefiles=FALSE"
		    else
			print -u4 "\t\t\tlargefiles=TRUE"
		    fi
		fi
	    else

	        # Logical volume has an umounted VxFS file system on it

	        warning "$vg has an unmounted VxFS filesystem on it"
	        print -u4 "\t\t\tusage=Unused"
	        size=$(lvdisplay $vg | grep "LV Size" | awk ' { print $4 } ' )
	        print -u4 "\t\t\tsize=${size}MB"

	    fi
	else
		
	    # Error if partition is not either HFS, swap, dump, VxFS
	    # or unused

	    fatal "cannot determine lv \"$vg\" usage via fstyp"
	fi

	# Use lvdisplay to gather more information on logical volume.
	# Print out information.

	bad_block=$(lvdisplay -v $vg | tee $lvdisplay_temp_file | grep "Bad block" | awk ' { print $3 } ' )
	if [[ $bad_block = "off" ]]
	then
	    print -u4 "\t\t\tbad_block_relocate=false"
	elif [[ $bad_block = "on" ]]
	then
	    print -u4 "\t\t\tbad_block_relocate=true"
	else
	    fatal "cannot determine bad_block_relocate"
	fi
	contiguous=$(grep "Allocation" $lvdisplay_temp_file | awk ' { print $2 } ' )
	if [[ $contiguous != +(*contiguous*) ]]
	then
	    print -u4 "\t\t\tcontiguous_allocation=false"
	elif [[ $contiguous = +(*contiguous*) ]]
	then
	    print -u4 "\t\t\tcontiguous_allocation=true"
	else
	    fatal "cannot determine contiguous_allocation"
	fi
	stripes=$(grep "Stripes" $lvdisplay_temp_file | awk ' { print $2 } ' )
	print -u4 "\t\t\tstripes=$stripes"
	stripe_size=$(grep "Stripe Size" $lvdisplay_temp_file | awk ' { print $4 } ' )
	print -u4 "\t\t\tstripe_size=${stripe_size}KB"
	grep "^[ ]*/dev/dsk" $lvdisplay_temp_file |
	while read pvdisk trash
	do
	    if [[ $pvdisk = $root_disk ]]
	    then
	        print -u4 "\t\t\tdisk[_hp_root_disk]"
            else
                print -u4 "\t\t\tdisk[$(disk_to_path $pvdisk)]"
            fi
	done
	rm -f $lvdisplay_temp_file
	print -u4 "\t\t} # end logical_volume"
    done
    print -u4 "\t} # end volume_group \"$1\""
    rm -f $vgdisplay_temp_file
}

#
# Function to process one disk.  It appends all the data to the
# temporary config file.
#
# Argument is block device file name for that disk
#

process_disk()
{

    # Check to see if disk is part of VG

    if [[ $(is_disk_in_vg $1) -eq 0 ]]
    then
        fatal "cannot process $1 separately as it is part of a volume group"
    fi

    # Check to make sure it's a block special file

    if [[ ! -b $1 ]]
    then
	fatal "$1 is not a block special file"
    fi

    # Check to see if device actually exists according to ioscan

    grep -q $1 $ioscan_temp_file
    if [[ $? -ne 0 ]]
    then
	fatal "no disk device at $1"
    fi

    # Print out partitioned_disk header

    print -u4 "\tpartitioned_disk {"

    # Print out physical volume disk. Take care of _hp_root_disk

    if [[ $1 = $root_disk ]]
    then
	print -u4 "\t\tphysical_volume disk[_hp_root_disk] {"
	print -u4 "\t\t} # end pv_options"
    else
	print -u4 "\t\tphysical_volume disk[$(disk_to_path $1)] {"
	print -u4 "\t\t} # end pv_options"
    fi

    # Check if this partition is mounted

    # Using tunefs is needed in case of /dev/root is the device where
    # / is mounted.  It works for all HFS file systems.  However it
    # doesn't work for vxfs.  So if mount_point is null after this
    # command returns, try to look for the mount point instead.

    mount_point=$(tunefs -v $1 2>/dev/null | grep "^super block" | awk ' { print $NF } ')

    # If it was vxfs, this will succeed.

    if [[ -z $mount_point ]]
    then
	mount_point=$(grep "$1 " $mount_temp_file | awk ' { print $2 } ')
    fi

    if [[ -n $mount_point ]]
    then
	print -u4 "\t\tfs_partition {"

	# Since this is a mounted partition, use fstyp to determine 
	# whether it is HFS or VxFS

	fs_usage=$(fstyp $1 2>/dev/null)
	if [[ $fs_usage = "hfs" ]]
	then
	    print -u4 "\t\t\tusage=HFS"

	    # Use tunefs and mkfs to gather data on HFS logical volume

	    tunefs -v $1 > $tunefs_temp_file
	    mkfs -F hfs -m $1 > $mkfs_temp_file

	    # Print out HFS logical volume information. Since the
	    # sector size is DEV_BSIZE (1K) just use KB as units

	    size=$(awk ' { print $(NF - 8) } ' $mkfs_temp_file )
	    print -u4 "\t\t\tsize=${size}KB"
	    print -u4 "\t\t\tmount_point=\"${mount_point}\""
	    minfree=$(awk ' { print $(NF - 2) } ' $mkfs_temp_file )
	    print -u4 "\t\t\tminfree=${minfree}"
	    file_length=$(awk ' { print $4 } ' $mkfs_temp_file )
	    if [[ "$file_length" = "-S" ]]
	    then
		print -u4 "\t\t\tfile_length=SHORT"
	    elif [[ "$file_length" = "-L" ]]
	    then
		print -u4 "\t\t\tfile_length=LONG"
	    else
		fatal "unable to determine file system length"
	    fi
	    blksize=$(awk ' { print $(NF - 5) } ' $mkfs_temp_file )
	    print -u4 "\t\t\tblksize=${blksize}"
	    fragsize=$(awk ' { print $(NF - 4) } ' $mkfs_temp_file )
	    print -u4 "\t\t\tfragsize=${fragsize}"
	    ncpg=$(awk ' { print $(NF - 3) } ' $mkfs_temp_file )
	    print -u4 "\t\t\tncpg=${ncpg}"
	    nbpi=$(awk ' { print $NF } ' $mkfs_temp_file )
	    print -u4 "\t\t\tnbpi=${nbpi}"
	    rotdelay_ms=$(grep rotdelay $tunefs_temp_file | awk ' { print $4 } ')
	    rotdelay=${rotdelay_ms%ms}
	    print -u4 "\t\t\trotational_delay=${rotdelay}"
	    rm -f $tunefs_temp_file $mkfs_temp_file
	elif [[ $fs_usage = "vxfs" ]]
	then
	    print -u4 "\t\t\tusage=VxFS"

	    # Use mkfs to gather data on VxFS logical volume.  Since
	    # the sector size is DEV_BSIZE (1K) just use KB as units

	    fs_size=$(mkfs -F vxfs -m $1 | awk ' { print $NF } ' )
	    print -u4 "\t\t\tsize=${fs_size}KB"
	    print -u4 "\t\t\tmount_point=\"${mount_point}\""
	else
		
	    # Error if partition is not either HFS or VxFS

	    fatal "cannot determine fs usage via fstyp"
	fi
	print -u4 "\t\t} # end fs_options"
    fi

    # Check if this disk has a swap partition

    swap_size=$(grep $1 $swapinfo_temp_file | awk ' { print $2 } ')
    if [[ -n $swap_size ]]
    then

	# Print out swap partition information

	print -u4 "\t\tswap_partition {"
	print -u4 "\t\t\tusage=SWAP"

	# Round swap size down to nearest megabyte to avoid rounding up
	# problem later

	(( swap_size = ( swap_size / 1024 ) * 1024 ))
	print -u4 "\t\t\tsize=${swap_size}KB"
	print -u4 "\t\t} # end swap_options"
    fi
    print -u4 "\t} # end partitioned_disk"

    # If the disk was neither mounted nor had swap, bomb out

    if [[ -z $mount_point && -z $swap_size ]]
    then
	fatal "disk at $1 has neither file system nor swap"
    fi
}

#
# Function to write out all system and networking information.
#

process_system_networking()
{
    # Use uname to determine system name

    print -u4 "final system_name=\"$(uname -n)\""

    # Loop through all the LAN devices on system

    lanscan | grep "^[0-9]" | while read lanpath mac inst state landev trash
    do

	# Check to see if this is an active LAN device

	ifconfig $landev >/dev/null 2>&1
	if [[ $? -ne 0 ]]
	then
	    continue
	fi

	# Determine and print networking information from ifconfig

	ip_addr=$(ifconfig $landev | grep inet | tee $ifconfig_temp_file | awk ' { print $2 } ')

	if [[ -z $ip_addr ]]
	then
	    continue
	fi

	print -u4 "final ip_addr[\"${lanpath}\"]=\"${ip_addr}\""
	netmask=$(awk ' { print $4 } ' $ifconfig_temp_file )
	print -u4 "final netmask[\"${lanpath}\"]=\"0x${netmask}\""
	broadcast=$(awk ' { print $6 } ' $ifconfig_temp_file )
	print -u4 "final broadcast_addr[\"${lanpath}\"]=\"${broadcast}\""
	rm -f $ifconfig_temp_file

    done

    # Get default route information from netstat -rn

    route_gateway=$(netstat -rn | grep default | tee $netstat_temp_file | awk ' { print $2 } ' )
    print -u4 "final route_gateway[0]=\"${route_gateway}\""
    route_destination=$(awk ' { print $1 } ' $netstat_temp_file )
    print -u4 "final route_destination[0]=\"${route_destination}\""
    rm -f $netstat_temp_file

    # State that all this information is NOT temporary.

    print -u4 "is_net_info_temporary=FALSE"

}

#
# Function to determine root_disk, root_grp_disk and root_grp_striped
#

find_root_disk()
{
    root_grp_disks=0
    root_grp_striped=0
    root_disk=$(grep " / " $mount_temp_file | awk ' { print $1 } ' )
    if [[ ( $root_disk = ${root_disk#/dev/dsk} ) && ( $root_disk != "/dev/root" ) ]]
    then
	# LVM is assumed now
        if [[ -f /etc/lvmtab ]]
        then
	    root_vol_grp=$(dirname $root_disk)
            root_disk=$(lvlnboot -v $root_vol_grp | tee $lvlnboot_temp_file | grep "^Root:" | awk ' { print $4 } ' )
            if [[ -n $root_disk ]]
	    then
	        root_grp_disks=$(grep "/dev/dsk" $lvlnboot_temp_file | grep "([[:digit:]/.]*)" | wc -l )
	        vgdisplay -v $(grep "Definitions" $lvlnboot_temp_file |
		    awk ' { print substr($6,1,length($6) - 1) } ' ) |
		    grep "LV Name" | awk ' { print $3 } ' |
	        while read lvol
	        do
	            lvdisplay $lvol | grep "Stripes"
                done |
	        while read s num
	        do
	            if [[ $num -gt 0 ]]
	            then
		        root_grp_striped=1
		        break
	            fi
	        done
            fi
	else
            root_disk=
        fi
    fi
}

#
# Main section of save_config
#

#
# Set constants
#

DEFAULT_CONFIG_FILE=/var/opt/ignite/local/config.recovery
CONFIG_TEMP_FILE=/var/tmp/config.tmp
LVLNBOOT_TEMP_FILE=/var/tmp/lvlnboot.tmp
VGDISPLAY_TEMP_FILE=/var/tmp/vgdisplay.tmp
LVDISPLAY_TEMP_FILE=/var/tmp/lvdisplay.tmp
MOUNT_TEMP_FILE=/var/tmp/mount.tmp
TUNEFS_TEMP_FILE=/var/tmp/tunefs.tmp
IFCONIG_TEMP_FILE=/var/tmp/ifconfig.tmp
NETSTAT_TEMP_FILE=/var/tmp/netstat.tmp
SWAPINFO_TEMP_FILE=/var/tmp/swapinfo.tmp
MKFS_TEMP_FILE=/var/tmp/mkfs.tmp
WHOLE_DISK_TEMP_FILE=/var/tmp/whole.disk.tmp
IOSCAN_TEMP_FILE=/var/tmp/ioscan.tmp
PVG_DISKS_TEMP_FILE=/var/tmp/pvgdisks.tmp
ALL_DISKS_TEMP_FILE=/var/tmp/alldisks.tmp

#
# Set variables
#

everything=0
config_file=$DEFAULT_CONFIG_FILE
config_temp_file=$CONFIG_TEMP_FILE
vgdisplay_temp_file=$VGDISPLAY_TEMP_FILE
lvdisplay_temp_file=$LVDISPLAY_TEMP_FILE
mount_temp_file=$MOUNT_TEMP_FILE
tunefs_temp_file=$TUNEFS_TEMP_FILE
ifconfig_temp_file=$IFCONIG_TEMP_FILE
netstat_temp_file=$NETSTAT_TEMP_FILE
swapinfo_temp_file=$SWAPINFO_TEMP_FILE
lvlnboot_temp_file=$LVLNBOOT_TEMP_FILE
mkfs_temp_file=$MKFS_TEMP_FILE
whole_disk_temp_file=$WHOLE_DISK_TEMP_FILE
ioscan_temp_file=$IOSCAN_TEMP_FILE
pvg_disks_temp_file=$PVG_DISKS_TEMP_FILE
all_disks_temp_file=$ALL_DISKS_TEMP_FILE
command=$(basename $0)

# Number of arguments for vgs and disks.

num_vg_list=0
num_disk_list=0

# Flag for -f option

fflag=0

# Check arguments using getopts

while getopts :f: option
do
     case $option in
	 f)
	     if [[ $fflag -eq 1 ]]
	     then
		  usage "-f option allowed only once"
	     fi
	     config_file=$OPTARG
	     fflag=1;;
	 \?)
	     usage "unknown option -$OPTARG";;
	 :)
	     usage "missing argument for -$OPTARG option";;
     esac
done

# If -f argument is not -, check out status of output file

if [[ "$config_file" != "-" ]]
then

# Try to create config file directory if it doesn't exist.

   config_dir=$(dirname $config_file)
   if [[ ! -d $config_dir ]]
   then
       mkdir -p $config_dir
       if [[ $? -ne 0 ]]
       then
	   fatal "cannot make directory $config_dir"
       fi
   fi

# Check to see if config is a directory. This is an error condition.

   if [[ -d $config_file ]]
   then
       fatal "$config_file cannot be a directory, it must be a file"
   fi

# Set up file descriptor 4 (referenced to $config_temp_file) for use as 
# output destination for all print commands.

   rm -f $config_temp_file
   touch $config_temp_file
   exec 4>$config_temp_file

else

# Set up file descriptor 4 (referenced to stdout) for use as 
# output destination for all print commands.

   exec 4>&1

fi

shift $((OPTIND -1))

# If no arguments are present now, look at all vgs and disks; otherwise
# process arguments and determine whether they are vgs or disks.  Store
# names in vg_list and disk_list arrays as appropriate.

if [[ $# -eq 0 ]]
then
    everything=1
else
    while [[ $# -gt 0 ]]
    do

	# Check if argument has a leading / character

	if [[ ${1} = ${1#/} ]]
	then

	    # Store argument in volume group list

	    vg_list[$num_vg_list]=$1
	    ((num_vg_list += 1))
	else

	    # Store argument in disk list

	    disk_list[$num_disk_list]=$1
	    ((num_disk_list += 1))
	fi
	shift 1
    done
fi

# Set cfg and _hp_cfg_detail_level

print -u4 cfg \"HP-UX System Recovery\"=TRUE
print -u4 _hp_saved_detail_level=\"vfph\"

# Print out variable assignments separator

print -u4 "#\n# Variable assignments\n#"

# Cache output from mount and swapinfo commands.  Only deal with hfs and
# vxfs file systems from mount (exclude cdfs).

mount -lp | grep -E "hfs|vxfs" > $mount_temp_file
swapinfo -d > $swapinfo_temp_file
ioscan -C disk -fn > $ioscan_temp_file

# Determine _hp_root_disk

find_root_disk

# If the root disk is /dev/root, then try to find equivalent in /dev

if [[ $root_disk = "/dev/root" ]]
then

    # Look in /dev for disk that matches /dev/root

    major=$(ls -lL /dev/root | awk ' { print $5 } ' )
    minor=$(ls -lL /dev/root | awk ' { print $6 } ' )

    # Loop through files in /dev to find one that matches

    find /dev -type b | grep -v /dev/root | xargs ls -l |
    grep -v "^total" | while read line
    do
        dmajor=$(echo $line | awk ' { print $5 } ' )
        if [[ $dmajor = $major ]]
        then
            dminor=$(echo $line | awk ' { print $6 } ' )
            if [[ $dminor = $minor ]]
            then
                ddisk=$(echo $line | awk ' { print $NF } ' )
                root_disk=$ddisk
                break
            fi
        fi
    done

    if [[ $root_disk = "/dev/root" ]]
    then
        fatal "root disk cannot be /dev/root"
    fi
fi
root_hardware_path=$(disk_to_path $root_disk)
print -u4 "init _hp_root_disk=\"$root_hardware_path\""

# If a root disk cannot be determined, give up

if [[ -z $root_disk ]]
then
    fatal "cannot determine root disk"
fi

# Print out _hp_root_grp_disks

print -u4 "init _hp_root_grp_disks=$root_grp_disks"

# Print out _hp_root_grp_striped

if [[ $root_grp_striped -eq 0 ]]
then
    print -u4 "init _hp_root_grp_striped=\"NO\""
else
    print -u4 "init _hp_root_grp_striped=\"YES\""
fi

# Determine _hp_pri_swap

grep -q $root_disk $swapinfo_temp_file
if [[ $? -eq 0 ]]
then
    pri_swap_size=$(grep $root_disk $swapinfo_temp_file | awk ' { print $2 } ' )

    # Round down whole disk swap size to nearest MB
    (( pri_swap_size = ( pri_swap_size / 1024 ) * 1024 ))

else
    # Root disk not found in swapinfo file.  See if this is LVM

    if [[ -f /etc/lvmtab ]]
    then
        pri_swap_vg=$(grep "Definitions" $lvlnboot_temp_file | awk ' { print substr($6,1,length($6) - 1) } ' )
        if [[ -n $pri_swap_vg ]]
        then
            pri_swap_vol=$(grep "Swap:" $lvlnboot_temp_file | awk ' { print $2 } ' )
            pri_swap_size=$(grep "$pri_swap_vg/$pri_swap_vol$" $swapinfo_temp_file | awk ' { print $2 } ' )
        fi
    else
	# Use first line in swapinfo file
	pri_swap_size=$(awk '/^dev/ { print $2 ; quit } ' $swapinfo_temp_file )
	pri_swap_dev=$(awk '/^dev/ { print $NF ; quit } ' $swapinfo_temp_file )
        if [[ $pri_swap_dev != ${pri_swap_dev#/dev/dsk} ]]
	then
            (( pri_swap_size = ( pri_swap_size / 1024 ) * 1024 ))
	fi
    fi
fi

if [[ -z $pri_swap_size ]]
then
    fatal "cannot determine primary swap size"
fi
print -u4 init _hp_pri_swap=${pri_swap_size}KB

# Set _hp_disk_layout

print -u4 init _hp_disk_layout=\"HP-UX save_config layout\"

# Print out disk and filesystems separator

print -u4 "#\n# Disk and Filesystems\n#"
print -u4 _hp_disk_layout+={\"HP-UX save_config layout\"}
print -u4 "(_hp_disk_layout==\"HP-UX save_config layout\") {"
print -u4 "\t# Disk/Filesystem Layout:"

# Print out VGs/disks as necessary

if [[ $everything -eq 1 ]]
then

    # Process all volume groups

    if [[ -f /etc/lvmtab ]]
    then
	vgdisplay 2>/dev/null | grep "^VG Name" | awk ' { print $3 } ' |
	while read vol_group trash
	do
	    process_volume_group ${vol_group#/dev/}
	done
    fi

    # Determine all disk used by mounted filesystems and swap partitions

    grep "/dev/dsk/" $mount_temp_file | awk ' { print $1 } ' - > $whole_disk_temp_file

    # This is in case root_disk was originally /dev/root

    if [[ $root_disk != ${root_disk#/dev/dsk} && $(is_disk_in_vg $root_disk) -eq 1 ]]
    then
	echo $root_disk >> $whole_disk_temp_file
    fi

    grep "/dev/dsk/" $swapinfo_temp_file | awk ' { print $NF } ' - >> $whole_disk_temp_file

    # Sort them out and get rid of any duplicates and process all disks

    sort -u $whole_disk_temp_file |
    while read disk_name
    do
	process_disk $disk_name
    done
    rm -f $whole_disk_temp_file

else

    # If any volume groups were given on command line process them

    if [[ $num_vg_list -gt 0 ]]
    then
	i=0
	while [[ $i -lt $num_vg_list ]]
	do
	    process_volume_group ${vg_list[$i]}
	    (( i += 1 ))
	done
    fi

    # If any disks were given on command line process them

    if [[ $num_disk_list -gt 0 ]]
    then
	i=0
	while [[ $i -lt $num_disk_list ]]
	do
	    process_disk ${disk_list[$i]}
	    (( i += 1 ))
	done
    fi
fi

print -u4 "} # end \"HP-UX save_config layout\""

# Print out instance numbers

ioscan -kf | awk ' BEGIN { Op = "=" }
			 { if ($1=="bc")
                             next;
		           if (NR>2)
			   {
		             printf "hw_instance_num %s %s \"%s\" %d\n", Op, $3, $1, $2 ;
			     Op = "+="
                           } 
		         } ' >&4 2>/dev/null

# Print out release variable

print -u4 "release=\"$(uname -r)\""

# Print out System/Networking Parameters header

print -u4 "#\n# System/Networking Parameters\n#"

process_system_networking

# Close file descriptor 4

exec 4>&-

# Clean up files

rm -f $mount_temp_file $swapinfo_temp_file $ioscan_temp_file $lvlnboot_temp_file

# Now that config file is complete, save away old one if it exists, and
# copy temporary file to real one if the file was not "-".

if [[ "$config_file" != "-" ]]
then
    saved_config_file=${config_file}.prev
    if [[ -f $config_file ]]
    then
        rm -f $saved_config_file
        cp $config_file $saved_config_file
    fi
    mv $config_temp_file $config_file
fi

exit 0
