#!/usr/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos72Q src/bos/usr/sbin/install/efixtools/epkg.sh 1.30.1.6 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2003,2019 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)32      1.30.1.6  src/bos/usr/sbin/install/efixtools/epkg.sh, cmdefix, bos72Q, q2019_23A6 6/3/19 10:15:22

#############################################################
## The following functions are included in this file and
## are listed in alphabetical order:
##
##   FAIL()
##   Qdriver()
##   Qorder()
##   ckNQ()
##   ck_epkg_flag_files()
##   cleanup()
##   edit_description()
##   epkg_getopts()
##   epkgtrap()
##   eval_qnext_flags() 
##   exportA()
##   getA4Q()
##   init_ecfile()
##   manage_hidden_paths()
##   pack_epkg()
##   perror()
##   pop_edir()
##   printH()
##   printQ()
##   print_prompt()
##   process_current_answers()
##   processA()
##   processPA()
##   read_previous_ecfile()
##   set_inst_work()
##   usage()
##   verify_config_rules()
##   write_ecfile()
##   GenSecFile() 	
#############################################################

########################################################################
## Function: eval_qnext_flags() Evaluates QNEXT based on supplied
##                              flags.
## Parameters: <QTYPE>
## Output: QNEXT
## Returns: 0 = ok, !0 = error
## Notes: (1) We don't want to answer any questions that are specified
##            with flags.
##        (2) This function also controls the order in which questions
##            are posed.
########################################################################
                                                                                
eval_qnext_flags()
{
   typeset ERROR='eval pmerror "eval_qnext_flags()"; return 1'
   typeset QTYPE="$1"
   typeset QNEXT
                                                                                
   [[ -z $QTYPE ]] && $ERROR
                                                                                
   case $QTYPE in

      EMORE|QFILES) 
         [[ $SIMPLEFILE -eq 1 ]] && QNEXT=EREBOOT || QNEXT=PREI 
         [[ $MOREOPT -eq 1 && $QNEXT = EREBOOT ]] && QNEXT=PKGLOCKS 
         ;;
      POSTR) 
         [[ $MOREOPT -eq 1 ]] && QNEXT=PKGLOCKS || QNEXT=EREBOOT 
         ;; 
      PKGLOCKS) #
         # We know MOREOPT is set
         QNEXT=SUPERSEDE
         ;; 
      SUPERSEDE) 
         # We know MOREOPT is set
         QNEXT=E2E_PREREQ 
         ;;
      E2E_PREREQ)
         # We know MOREOPT is set 
         QNEXT=EREBOOT
         ;;
      *) 
         $ERROR 
         ;; 

   esac

   [[ $QNEXT = PKGLOCKS && $lflag -eq 1 ]] && QNEXT=SUPERSEDE
   [[ $QNEXT = SUPERSEDE && $Sflag -eq 1 ]] && QNEXT=E2E_PREREQ
   [[ $QNEXT = E2E_PREREQ && $gflag -eq 1 ]] && QNEXT=EREBOOT 
   [[ $QNEXT = EREBOOT && $rflag -eq 1 ]] && QNEXT=APARREF
   [[ $QNEXT = APARREF && $aflag -eq 1 ]] && QNEXT=PREREQ
   [[ $QNEXT = PREREQ && $pflag -eq 1 ]] && QNEXT=EDESC
   [[ $QNEXT = EDESC && $dflag -eq 1 ]] && QNEXT=QEND
                                                                                
   [[ -n $QNEXT ]] && echo "$QNEXT" || $ERROR
                                                                                
   return 0
                                                                                
}  # end of eval_qnext_flags()

########################################################################
## Function: ck_epkg_flag_files()
## Parameters: <NONE>
## Returns: 0 = ok, !0 = error
########################################################################
                                                                                
ck_epkg_flag_files()
{
   typeset ERROR='eval return 1'
   typeset FILE
   typeset VAR
   typeset RC=0
   typeset ELIST
                                                                                
   for VAR in $IFILES ECFILE ; do
      eval FILE="$"$VAR

      if [[ -n $FILE && "$FILE" != "$NONE" ]]; then
         [[ $(isin "$FILE" "$ELIST") = "1" ]] && continue
         check_file_full $FILE && continue
         RC=1
         strcat -v ELIST -s "$FILE"
      fi
   done
      
   # Check for valid description file
   if [[ $A_EDESC = "$NONE" ]]; then
      perror 414  
      inc RC
   fi

   [[ $RC -eq 0 ]] && return 0
                                                                                
   $ERROR
                                                                                
}  # end of ck_epkg_flag_files()

########################################################################
## Function: verify_config_rules() Verfies all config files and other
##                                 rules as needed.
## Parameters: None.
## Returns: 0 = ok, !0 = error
## Note: Config file verification methods will issue their own messages.
########################################################################
                                                                                
verify_config_rules()
{
   typeset ERROR='eval RC=1'                # generic error
   typeset DERROR='eval perror 414; eval RC=1' # description file error  
   typeset RC=0                             # overall return code
 
############################################################
## If there are possible kernel files, make sure the
## BUILD_BOOT_IMAGE attribute is on. Attention notice only..
############################################################
                                                                                
   PB="" check_kernel_link
                                                                                
############################################################
## Check the prereq file if needed..
############################################################
                                                                                
   if [[ $A_PREREQ != "$NONE" ]]; then
      verify_prereq_file $A_PREREQ || $ERROR
   fi
                                                                                
############################################################
## Check the pkglocks file if needed..
############################################################
                                                                                
   if [[ $A_PKGLOCKS != "$NONE" ]]; then
      verify_pkglocks_file "$A_PKGLOCKS" || $ERROR
   fi

############################################################
## Check the supersede file if needed..
############################################################

   if [[ $A_SUPERSEDE != "$NONE" ]]; then
      verify_supersede_file "$A_SUPERSEDE" || $ERROR
   fi

############################################################
## Check efix to efix prereqs/xreq file if needed ...
############################################################

   if [[ $A_E2E_PREREQ != "$NONE" ]]; then
      verify_e2eprereq_file "$A_E2E_PREREQ" || $ERROR
   fi

############################################################
## Check for conflict between A_SUPERSEDE and A_E2E_PREREQ
############################################################

   if [[  $A_E2E_PREREQ != "$NONE" && $A_SUPERSEDE != "$NONE" ]]; then
      check_e2e_sup_conflict || $ERROR
   fi

############################################################
## Check that description file is valid,
############################################################

   if [[ $A_EDESC != "$NONE" ]]; then
      check_file_full $A_EDESC || $DERROR
   else
      $DERROR
   fi

############################################################
## Verify that all Concurrent Update variables are filled, 
## if any were given
############################################################

   EFCOUNT=1
   while [[ $EFCOUNT -le $GENUM ]]
   do
      if [[ ${A_ETYPE[$EFCOUNT]} -eq 3 ]]; then
         [[ -f ${CU_MODULE[$EFCOUNT]} && -n ${LDR_NAME[$EFCOUNT]} ]] || $DERROR
         [[ -n ${SB_BIN[$EFCOUNT]} ]] || $DERROR

         # make sure every sandbox binary supplied exists
         echo ${SB_BIN[$EFCOUNT]} | $TR : "\n" | while read SB_FILE  # IFS is set above before the loop
         do
            [[ -f $SB_FILE ]] || $DERROR
         done
      fi
      (( EFCOUNT = $EFCOUNT + 1 ))
   done

############################################################
## Either all files are TYPE=3, or none are TYPE=3
############################################################

   EFCOUNT=1
   TYPE3_COUNT=0

   while [[ $EFCOUNT -le $GENUM ]]
   do
      [[ ${A_ETYPE[$EFCOUNT]} -eq 3 ]] && (( TYPE3_COUNT = $TYPE3_COUNT + 1 ))
      (( EFCOUNT = $EFCOUNT + 1 ))
   done

   [[ $TYPE3_COUNT -ne $GENUM && $TYPE3_COUNT -ne 0 ]] && $DERROR

############################################################
## Done ! Be sure to return the right status.
############################################################

   # If RC=0, no errors detected :-) 
   [[ $RC -eq 0 ]] && return 0 

   # If we got here, then there is an error.
   return 1
                                                                                
}  # end of verify_config_rules()

#######################################################################
## Function: GenSecFile 
#######################################################################

GenSecFile()
{
	typeset ERROR='eval perror 36; return 1'
	typeset SIG_KEY=NULL
	typeset CERT_KEY=NULL
	typeset EFCOUNT=0


	/usr/bin/rm $EDIR/secfile.sec >/dev/null 2>&1	
	/usr/bin/rm $EDIR/secfile.lib.sec >/dev/null 2>&1
	touch $EDIR/secfile.sec $EDIR/tmp.sec_2.$$ $EDIR/tmp.sec_1.$$
	touch $EDIR/secfile.lib.sec $EDIR/tmp.sec_1.$$.lib.sec $EDIR/tmp.sec_2.$$.lib.sec 

	while [[ $EFCOUNT -lt $GENUM ]]; do
		# Increment EFCOUNT
		(( EFCOUNT = $EFCOUNT +1 )) || $ERROR

		# Safety valve for this loop
		if [[ $EFCOUNT -gt $MAXEFILES ]]; then
			pmerror "GenSecFile()"
			$ERROR
		fi

		# Set SHIP abspath
		A_ESHIP[$EFCOUNT]=$(abspath ${A_ESHIP[$EFCOUNT]}) || return 1

		# Generate the temperory sec sample file


		echo "${A_ESHIP[$EFCOUNT]}:\n\ttype = FILE\n\tsize =\n\tcert_tag =\
		\n\tsignature =\n\thash_value =\n\t" > $EDIR/tmp.sec.$$

		# Generate the hash, signature and certID for the object
	
		/usr/sbin/gensecattr -f $EDIR/tmp.sec.$$ -s ${SIG_KEY} -v\
		${CERT_KEY} -o $EDIR/tmp.sec_1.$$ >/dev/null 2>&1

		#replace the ship path with target path in sec file
		/usr/bin/sed "s+${A_ESHIP[$EFCOUNT]}+${A_ETARGET[$EFCOUNT]}+g" $EDIR/tmp.sec_1.$$ > $EDIR/tmp.sec_2.$$ 

		/usr/bin/sed "s+${A_ESHIP[$EFCOUNT]}+${A_ETARGET[$EFCOUNT]}+g" $EDIR/tmp.sec_1.$$.lib.sec > $EDIR/tmp.sec_2.$$.lib.sec 2>/dev/null

		#Generate the sec file
		/usr/bin/cat $EDIR/tmp.sec_2.$$ >> $EDIR/secfile.sec 2>/dev/null
		/usr/bin/cat $EDIR/tmp.sec_2.$$.lib.sec >> $EDIR/secfile.lib.sec 2>/dev/null

	done
	
	/usr/bin/rm $EDIR/tmp.sec.$$ >/dev/null 2>&1
	/usr/bin/rm $EDIR/tmp.sec_1.$$  $EDIR/tmp.sec_2.$$ >/dev/null 2>&1
	/usr/bin/rm $EDIR/tmp.sec_1.$$.lib.sec $EDIR/tmp.sec_2.$$.lib.sec >/dev/null 2>&1


	return 0
}

########################################################################
## Function: write_ecfile (Write Efix Control File)  
########################################################################

write_ecfile()
{
   typeset ERROR='eval perror 36; return 1'
   typeset WC=0
   typeset EFCOUNT=0
   typeset FIELD
   typeset VALUE
   typeset OD_TS_CMD="$OD -An -j4 -N4 -tu" # use od cmd to get timestamp

###########################################################
## Set INSTWORK.. based on the answers above.
###########################################################

   set_inst_work || return 1        

###########################################################
## Set VUID
###########################################################

   A_VUID=$($UNAME -m) 
   if [[ $? -ne 0 || -z $A_VUID ]]; then
      pmerror $UNAME
      $ERROR
   fi

   WC=${#A_VUID}

   A_VUID="$A_VUID$(timestamp RAW)" 
   if [[ $? -ne 0 || $WC -ge ${#A_VUID} ]]; then
      pmerror "timestamp()"
      $ERROR
   fi

###########################################################
## Set timestamp.
###########################################################

   GTS=$(timestamp DT) || $ERROR

###########################################################
## Re-calculate all sums, sizes, and package.
###########################################################

   while [[ $EFCOUNT -lt $GENUM ]]; do

      # Increment EFCOUNT
      (( EFCOUNT = $EFCOUNT +1 )) || $ERROR

      # Safety valve for this loop
      if [[ $EFCOUNT -gt $MAXEFILES ]]; then
         pmerror "write_ecfile()"
         $ERROR
      fi

      # Set SHIP abspath
      A_ESHIP[$EFCOUNT]=$(abspath ${A_ESHIP[$EFCOUNT]}) || return 1

      # Re-calculate the sum
      CKSUM[$EFCOUNT]=$(getfsum ${A_ESHIP[$EFCOUNT]}) || return 1

      # Re-calculate the size
      SZ[$EFCOUNT]=$(getfsize ${A_ESHIP[$EFCOUNT]}) || return 1

###########################################################
## Fill in timestamps for CU files
###########################################################
      if [[ ${A_ETYPE[$EFCOUNT]} -eq 3 ]]; then
	 # do a sanity check here, make sure vars are set if type 3, return otherwise
	 [[ -n ${CU_MODULE[$EFCOUNT]} && -n ${SB_BIN[$EFCOUNT]} ]] || return 1

	 # use OD_TS_CMD (od -An -j4 -N4 -tu <file>) to get timestamp
         TSTAMP[$EFCOUNT]=$($OD_TS_CMD ${CU_MODULE[$EFCOUNT]} | $AWK1)
         TGT_TS[$EFCOUNT]=$($OD_TS_CMD ${A_ESHIP[$EFCOUNT]} | $AWK1)

         echo ${SB_BIN[$EFCOUNT]} | $TR : "\n" | while read SB_FILE
         do
            [[ -n ${TGT_TS[$EFCOUNT]} ]] && TGT_TS[$EFCOUNT]="${TGT_TS[$EFCOUNT]}:"
            TGT_TS[$EFCOUNT]="${TGT_TS[$EFCOUNT]}$($OD_TS_CMD $SB_FILE | $AWK1)"
         done
      fi
   done

###########################################################
## Make sure all answers are set.
###########################################################

   process_current_answers || $ERROR   
   
###########################################################
## Print out ecfile before exiting.
###########################################################

   print_ecfile > $ECFILE || $ERROR

############################################################
## Reset ALIST in case it is stale.
############################################################

   > $ALIST

   echo "./ecfile" >> $ALIST || $ERROR
   
}  # write_ecfile()   

########################################################################
## Function: perror (Print Error)              
########################################################################

perror()
{
   ISERROR=1
   print_msg $@ >&2
   ISERROR=0

}  # end of perror()

########################################################################
## Function: set_inst_work (Set Install Work Size Variable)
########################################################################

set_inst_work()
{

   typeset FSIZE=0
   typeset TOTAL=32  # 32 512bb buffer
   typeset FILE   
   typeset ERROR='eval perror 69; return 1'
   
############################################################
## Get the total size for all of the installation control
## files (i.e. pre-install, post-install, prereq, desc,
## ..etc).  Assign that value to A_INSTWORK. 
############################################################

   for FILE in $IFILES; do
      eval FILE="$"$FILE
      [[ $FILE = $NONE || -z $FILE ]] && continue
      FSIZE=$(getfsize "$FILE") || $ERROR
      (( TOTAL = $TOTAL + $FSIZE )) || $ERROR
   done

   # Add 32 for ecfile (this is a little overkill)
   (( TOTAL = $TOTAL + 32 )) || $ERROR

   # We add a 10% buffer
   (( TOTAL = $TOTAL + ($TOTAL/20) )) || $ERROR
 
   # Make the assignment 
   A_INSTWORK="$TOTAL"

}  # end of set_inst_work()   

########################################################################
## Function: ckNQ (Check Next Question)        
########################################################################

ckNQ()
{
   typeset RC=0
   typeset QTYPE="$1"
   typeset FLAG
   typeset ERROR='eval pmerror "ckNQ"; FAIL'
   
   [[ -z $QTYPE ]] && $ERROR

############################################################
## Check if we are not asking a question that is answered
## by a flag.. this can happen if we back into a QORDER that
## was created without flags.
############################################################

   case $QTYPE in
      EREBOOT) [[ $rflag -eq 1 ]] && return 1;;
      APARREF) [[ $aflag -eq 1 ]] && return 1;;
       PREREQ) [[ $pflag -eq 1 ]] && return 1   
               [[ $SIMPLEFILE -eq 1 ]] && return 1;;
        EDESC) [[ $dflag -eq 1 ]] && return 1;;
      PREI|PRER|POSTI|POSTR) [[ $SIMPLEFILE -eq 1 ]] && return 1;;
   esac

   # All ok.
   return 0

}  # end of ckNQ

########################################################################
## Function: edit_description()  (Edit Description)
########################################################################

edit_description()
{

   typeset RC=0
   typeset PRESUM=0
   typeset POSTSUM=0
   typeset EPKGTPL=$HOME/epkg.desc.tpl

   # Make sure we have at least half a meg of space in $WORKDIR
   ck_exp_fs $WORKDIR 1024 || return 1
 
   # setup the editor executable to use. If they did not set  
   # their EDITOR variable then we default to "vi".

   [[ ! -x $EDITOR ]] && EDITOR=$VI

############################################################
## Setup the description file..
############################################################

   $RM -f $DES_BUF  

   if [[ -r $EPKGTPL && -f $EPKGTPL ]]; then
      $CP $EPKGTPL $DES_BUF > /dev/null 2>&1 || $RM -f $DES_BUF
   fi       
      

   if [[ ! -f $DES_BUF ]]; then

      $CAT <<- EOF > $DES_BUF
========================== EFIX DESCRIPTION =============================
Enter the EFIX description. Please include the symptoms that are fixed by
this EFIX, all additional install details, and any other information that
would be useful to the USER. Save and exit the editor to return to epkg.
=========================================================================
EOF

      PRESUM=$(getfsum $DES_BUF)

   fi


############################################################
## Edit the description..
############################################################ 

   $EDITOR $DES_BUF
   RC=$?

   if [[ $PRESUM -ne 0 ]]; then
       POSTSUM=$(getfsum $DES_BUF)
       # Check to make sure they changed the description template
       [[ $PRESUM -eq $POSTSUM ]] && RC=2
   fi
 
   if [[ $RC -ne 0 || ! -s $DES_BUF ]]; then
      print_msg 67 >&2
      return 1
   fi

   return 0
           
}  # end of edit_description()

########################################################################
## Function: process_current_answers()
########################################################################

process_current_answers()
{
   typeset VAR
   typeset EFCOUNT=0
   typeset ERROR='eval return 1'
   typeset IFILE_ERROR='eval perror 53 "$FIELD"; RC=1; continue'
   typeset RC=0
   typeset SHIP_FILE
   typeset FIELD VALUE
   typeset NSHIPFF=0  # number of ship files found in ecfile
   typeset OUT
   typeset BUF

   for VAR in $CVARS; do

      # Extract the current VALUE and run it through 
      # process_new_options.

      echo "$VAR" | IFS=: read FIELD VALUE
      eval OUT="$"$VALUE
      process_new_options "$FIELD" "OUT" "$OUT" || $ERROR

      # If the VALUE is an IFILE, then validate it.
      BUF=$(isin "$VALUE" "$IFILES") || $ERROR
      [[ $BUF -eq 0 || -z $OUT || $OUT = "$NONE" ]] && continue

      check_file_full $OUT || $IFILE_ERROR
      typeset OUT2=$(abspath $OUT) || $IFILE_ERROR
      eval $VALUE='$OUT2' || $IFILE_ERROR 

   done

   [[ $RC -ne 0 ]] && $ERROR

   [[ -z "$GENUM" || $GENUM -eq 0 ]] && return 0

   while [[ $EFCOUNT -lt $GENUM ]]; do

      inc EFCOUNT || $ERROR
      [[ $? -ne 0 || $EFCOUNT -gt MAXEFILES ]] && $ERROR 
     
      SHIP_FILE=${A_ESHIP[$EFCOUNT]}
 
      if [[ -z $SHIP_FILE ]]; then
         perror 350 $EFCOUNT
      else
         # increment "number of ship files found" variable
         inc NSHIPFF
      fi

   done 

   if [[ $NSHIPFF -lt $GENUM ]]; then
      perror 351 "$GENUM" "$NSHIPFF"
      return 1
   fi

   return 0

}  # end of process_current_answers()

########################################################################
## Function: epkgtrap()                                          
########################################################################

epkgtrap()
{
   trap '' 1 2 3 11 15
   typeset ANS=$1
   [[ -z $ANS ]] && ANS=2

   setcmd clear
   $CLEAR || pmerror $CLEAR

   while [[ $ANS -ne 0 && $ANS -ne 1 ]]; do
      $PB
      print_msg 63
      print_prompt
      read ANS
      [[ $ANS = "q!" ]] && FAIL
      [[ $ANS = "h!" ]] && printH QUIT
      isYorN $ANS  
      ANS=$?
   done

   if [[ $ANS -eq 1 ]]; then
      print_ecfile > $ECFILE 
      if [[ $? -ne 0 ]]; then
         pmerror "epkgtrap()"
         FAIL
      fi
      exit 0
   fi

   # they want to continue..  
   export ASKAGAIN=1
   return 0

}  # end of epkgtrap()

########################################################################
## Function: pack_epkg (Packup the EFIX archive)
########################################################################

pack_epkg()
{
   eval $SIGTRAP

   typeset ERROR="eval cd $OLDPWD; $RM -f $EIMAGE; perror 59; return 1"
   typeset RC=0
   typeset ABSBUF  # Buffer to hold absolute path name for EIMAGE

   # Announce what we are doing.   
   print_msg 60

############################################################
## Change into $EDIR and run a few checks.
############################################################

   check_dir $EDIR || $ERROR
   cd $EDIR || $ERROR
   check_file_full $ALIST || $ERROR
   [[ -z $EIMAGE ]] && $ERROR
   $RM -f $EIMAGE

############################################################
## Verify that we have the space to accomodate this EFIX.
## Note, we do not rely on compression to lower this amount.
## (This acts as a form of buffering).
## The minimal space we need is 32 512 byte blocks (or 16K).
############################################################

   typeset FILE         # File in ALIST
   typeset TOTAL=32     # Total size required in 512 bb (we start
                        # with a 16k buffer).
   typeset FSIZE=0      # File size for FILE


   for FILE in $($CAT $ALIST); do
      FSIZE=$(getfsize "$FILE") || $ERROR
      (( TOTAL = $TOTAL + $FSIZE ))
   done

   # We add a 10% buffer
   (( TOTAL = $TOTAL + ($TOTAL/10) ))

############################################################
## We execute a check to make sure we enough space in the
## filesystem that owns EDIR.
############################################################

   # Check/expand space.
   ck_exp_fs "$EDIR" "$TOTAL" || $ERROR

   # Hide the ship filepath
   manage_hidden_paths HIDE || $ERROR

############################################################
## OK, we should be ready at this point to work with TAR.
############################################################
   
   ($TAR -chf - $($CAT $ALIST); subshrc PUTRC) | $COMPRESS -f > $EIMAGE
   RC=$?

   # Replace ecfile in workdir to show paths
   manage_hidden_paths UNHIDE || $ERROR

############################################################
## Check for errors from above tar and compress.
############################################################

   (( RC = $RC + $(subshrc GETRC) ))
   [[ $RC -ne 0 ]] && $ERROR 
   check_file_full $EIMAGE  || $ERROR 

############################################################
## Get the absolute path of EFIX image file so we can give
## a complete message to the user.
############################################################

   EIMAGE=$(abspath $EIMAGE) || $ERROR

   cd $OLDPWD

   # done !
   return 0
 
}  # end of pack_epkg()

pop_edir()
{
   eval $SIGTRAP
   typeset BUF      # local buffer
   typeset FI       # local flat file index
   typeset SHIP   # local source variable
   typeset TARGET   # local target variable
   typeset RC       # local return code

   # Setup generic error 
   typeset ERROR="eval perror 52; return 1"

   # Announce our intentions..
   print_msg 64

############################################################
## Link in the install scripts and flat files.
############################################################

   for FI in $IFILES; do
     
      # Set TARGET 
      TARGET=$(conv_ifile_to_target "$FI") || $ERROR
      
      eval SHIP="$"$FI

      if [[ "$SHIP" = "$NONE" ]]; then
         [[  "$TARGET" != "prereq" ]] && continue

############################################################
## We need to do a little extra work here for the prereq 
## file.  We need to create a dummy prereq so that tar 
## does not fail in emgr. Note, we don't want to make two
## passes with tar.
############################################################

         echo "NO PREREQUISITES" > $DUMMY_PREREQ
         SHIP=$DUMMY_PREREQ

      fi

      # If value is NULL, then we have a problem
      if [[ -z $SHIP ]]; then
         perror 53 "$TARGET" 
         $ERROR
      fi
     
      # Check the file to make sure it is OK
      check_file $SHIP || $ERROR

      if [[ "$SHIP" != "$EDIR/$TARGET" ]]; then 
         $LN -sf $SHIP $EDIR/$TARGET || $ERROR  
      fi

      # Add the file link to backup list 
      echo "./$TARGET" >> $ALIST || $ERROR 
      
   done  # end of install scripts for loop

############################################################
## Link in the EFIX files.
############################################################

   typeset EFCOUNT=0      # local EFIX file counter
   typeset TENUM=$GENUM   # total number of EFIX files

   SHIP=""  # reset source just in case

   while [[ $EFCOUNT -lt $TENUM ]]; do
      # Safety valve for this loop
      if [[ $EFCOUNT -gt $MAXEFILES ]]; then
         pmerror "pop_edir()" 
         $ERROR   
      fi

      # Increment EFCOUNT
      (( EFCOUNT = $EFCOUNT + 1 ))

      SHIP=${A_ESHIP[$EFCOUNT]}

      # Check if this is a blank file
         if [[ -z $SHIP ]]; then
         perror 46 "$EFCOUNT" 
         $ERROR
      fi

############################################################
## Make sure the checksum is still valid. This is a little
## overkill, but better safe then sorry.
############################################################ 

      verifysum "$SHIP" "${CKSUM[$EFCOUNT]}" || $ERROR

      TARGET="EFILE$EFCOUNT"

      if [[ "$SHIP" != "$EDIR/$TARGET" ]]; then
         $LN -sf $SHIP $EDIR/$TARGET || $ERROR
      fi

      echo "./$TARGET" >> $ALIST || $ERROR    

############################################################
## If the EFIX_FILE has a Concurrent Update, then we need
## to save the CU_MODULE as well
############################################################

   if [[ ${A_ETYPE[$EFCOUNT]} -eq 3 ]]; then
      TARGET="CU$EFCOUNT"

      CU_FILE=${CU_MODULE[$EFCOUNT]}

      if [[ "$CU_FILE" != $EDIR/$TARGET ]]; then
         $LN -sf $CU_FILE $EDIR/$TARGET || $ERROR
      fi

      echo "./$TARGET" >> $ALIST || $ERROR
   fi

   done  # end of EFIX file while loop

#############################################################
## Adding the sec file
############################################################

	echo "./secfile.sec"   >> $ALIST
	echo "./secfile.lib.sec" >> $ALIST

############################################################
## Finally, add $ALIST to the backup list.
############################################################

   echo "./.alist" >> $ALIST || $ERROR
   
   return 0
   
}  # end of pop_edir()

########################################################################
## Function: manage_hidden_paths() < HIDE | UNHIDE >
########################################################################

manage_hidden_paths()
{
   eval $SIGTRAP

   typeset ERROR='eval pmerror "manage_hidden_paths()"; return 1'
   typeset ACTION=$1
   typeset FIELD
   typeset VALUE
   typeset VAR
   typeset HIDDEN_FILES="SHIP_FILE"
   typeset HSTRING="/HIDDEN/"
   typeset BUF
   
   # Check required options
   [[ "$ACTION" = "HIDE" || "$ACTION" = "UNHIDE" ]] || $ERROR

   # Handle UNHIDE here
   if [[ "$ACTION" = "UNHIDE" ]]; then
      # Replace ecfile
      [[ -s $ECFILE_B ]] || $ERROR
      $MV $ECFILE_B $ECFILE || $ERROR
      return 0
   fi

   # If we are here then this is a HIDE operation
   # Create list of variables that need hiding
                                                                                
   for VAR in $CVARS; do
      echo "$VAR" | IFS=: read FIELD VALUE
      BUF=$(isin "$VALUE" "$IFILES") || $ERROR
      [[ $BUF -eq 0 ]] && continue
      strcat -v HIDDEN_FILES -s "$FIELD" || $ERROR
   done
  
   #Space check for duplicating ecfile
   check_fdup_space $ECFILE  || $ERROR

   # Get unique name for backup ecfile
   ECFILE_B=$(print_uniq_iname $ECFILE)

   add_to_cleanup $ECFILE_B FILE || $ERROR

   # Copy the ecfile to its backup
   $CP $ECFILE $ECFILE_B || $ERROR

   # Change the fields in the ecfile
   $AWK -v "hstr=$HSTRING" -v "hid_files=$HIDDEN_FILES" ' BEGIN {
       split(hid_files, harray," ");
   }
   { # Main
       for (i in harray) {
           if ($0 ~ "^[ \t]*"harray[i]"=[ \t]*/") {
              split($0,str,"=");
              print str[1]"="hstr;
              next ;
           }
       }   # end of for
       print $0;
   }' $ECFILE_B > $ECFILE || $ERROR

   check_file_full $ECFILE || $ERROR

   return 0

} # end of manage_hidden_paths()
  
########################################################################
## Function: read_previous_ecfile() 
########################################################################

read_previous_ecfile()
{
   eval $SIGTRAP

##########################################################
## This function read a previous ECFILE. Notice we do not
## do much error checking at this point since the previous
## ECFILE may be incomplete. We will call read_ecfile 
## at some point (hopefully) to confirm all entries.
###########################################################

   typeset VAR        # local var index
   typeset EFCOUNT=0  # local efix file count
   typeset ERROR='eval perror 45; return 1'

###########################################################
## If ecfile does not exit, then just exit out.
###########################################################
   
   [[ ! -s $ECFILE ]] && return 0
   
   # Announce what we are doing
   print_msg 47 "$ECFILE"

###########################################################
## Get COMMON info (applies to entire EFIX).
###########################################################

   get_common_cvars || $ERROR

   # Check to make sure GENUM is set correctly
   isnum $GENUM 
   if [[ $? -ne 0 ]]; then
      perror 53 EFIX_FILES
      $ERROR
   fi

###########################################################
## If QNEXT or QORDER are blank, set them to QEND.
###########################################################

   [[ -z $QNEXT ]] && QNEXT="QEND"
   [[ -z $QORDER ]] && QORDER="QEND"

###########################################################
## Read all info specific to EFIX files.
###########################################################

   get_efile_vars || $ERROR

###########################################################
## We re-exec the epkg_getopts.. This is so any command
## line variables (i.e. variables specified with flags)
## overwrite variables in ecfile.
###########################################################

   epkg_getopts $MAINARGS || $ERROR

###########################################################
## Check the answers we have thus far ...
###########################################################

   process_current_answers || $ERROR

###########################################################
## Make sure we setup ECFILE in the central location..
###########################################################
   
   ECFILE=$(abspath $EDIR/ecfile) || $ERROR

   if [[ -f $ECFILE ]]; then
      $MV "$ECFILE" "$ECFILE.$(timestamp FULL)" || $ERROR        
   fi

   return 0

}  # end of read_previous_ecfile()

########################################################################
## Function: processPA  (Process previous answer).
########################################################################

processPA()
{
   typeset QTYPE="$1"
   typeset ENUM="$2"
   typeset IGNORE_QTYPES="EMORE QFILES"
   typeset Q
   typeset B
   PA="" # Init global PA
  
   for Q in $IGNORE_QTYPES; do
      [[ $Q = $QTYPE ]] && return 0
   done

   # Is it a COMMON attribute.. ?
   ANS=$(eval echo "$"A_$QTYPE)

   # If it is not COMMON, try EFILE specific
   [[ -z $ANS ]] && ANS=$(eval echo "$"{A_$QTYPE[$ENUM]})


###########################################################
## Handle any special cases.
###########################################################

   case "$QTYPE" in
      EREBOOT) 
      if [[ -n "$A_EREBOOT" && -n "$A_BUILD_BOOT_IMAGE" ]]; then

         B="$A_BUILD_BOOT_IMAGE"
        
         case "$A_EREBOOT" in
            $NO) [[ "$B" = "$NO" ]] && ANS=$NOREBOOT || ANS=$BBI_NO_REBOOT;;
           $YES) [[ "$B" = "$NO" ]] && ANS=$REBOOT_NO_BBI || ANS=$REBOOT_BBI;; 
              *) ANS="";;
         esac

         # Make sure B (alias for A_BUILD_BOOT_IMAGE) is set correctly
         [[ "$B" != "$NO" && "$B" != "$YES" ]] && ANS=""  

      else 

        ANS=""

      fi  # end of case $QTYPE in EREBOOT
      ;;
   esac

###########################################################
## Print the previous answer (if any).
###########################################################

   if [[ -n $ANS ]]; then
      print_msg 40 "$ANS" 
   fi

   PA="$ANS"
   return 0

}  # end of processPA()
 
########################################################################
## Function: init_ecfile (Init Efix Control File)
########################################################################

init_ecfile()
{
   typeset ANS=2 # local answer 
   typeset DATEOUT
   typeset RC=0
   typeset D_ECFILE
 
###########################################################
## Make sure that the E label is valid.
###########################################################

   if [[ ${#A_ELABEL} -gt $LABELMAX ]]; then
      perror 20 "$LABELMAX"
      return 1
   fi

   # Make sure WORKDIR is valid
   if [[ -f $WORKDIR ]]; then
      print_msg 41 "$WORKDIR"
      return 1
   fi

   $MKDIR -p $WORKDIR || {
      pmerror $MKDIR
      return 1
   }  

   WORKDIR=$(abspath $WORKDIR) || return 1

###########################################################
## Make sure that we have at least half a meg to work with
## in WORKDIR (1024 bb).
###########################################################

   ck_exp_fs $WORKDIR 1024 || return 1

   # Setup EDIR (control directory for this EFIX)
   export EDIR=$WORKDIR/$A_ELABEL

   if [[ -d $EDIR ]]; then
      print_msg 37 $EDIR 
   else
      print_msg 38 $EDIR 
      $MKDIR -p $EDIR || {           
         pmerror $MKDIR
         return 1
      }
   fi

############################################################
## Setup ALIST (this is the a archive list that will be
## used by pack_epkg and pop_edir. Also, set the default
## ecfile variable.
############################################################

   EDIR=$(abspath $EDIR) || return 1
   export ALIST=$EDIR/.alist
   D_ECFILE=$EDIR/ecfile

############################################################
## Init temp files.. these are WORKDIR dependent.
############################################################

   export MSG_BUF=$EDIR/.epkg.msg.buf.$$
   export DES_BUF="$EDIR/.epkg_desbuf."
   DES_BUF="$DES_BUF$(timestamp MDY).$$" || return 1
   export ERRTOKEN=$EDIR/.epkg.errtok.$$
   export ERR_BUF=$EDIR/.epkg.err.buf.$$
   export DUMMY_PREREQ=$EDIR/.epkg.dummy.prereq.$$

############################################################
## Setup archive image name.
############################################################

   export EIMAGE="$EDIR/$A_ELABEL.$(timestamp MDY).epkg.Z"

############################################################
## Setup the EFIX control file. If it already exists, we
## prompt the user to accept it (or not).
############################################################

   if [[ -z $ECFILE ]]; then
  
      ECFILE=$D_ECFILE    
   
   else                                 

############################################################
## ECFILE was specified (-e flag). 
############################################################

      ECFILE=$(abspath $ECFILE) || return 1

############################################################
## If ECFILE is good and not already in EDIR, then we copy 
## it to EDIR.
############################################################

      if [[ $D_ECFILE != $ECFILE ]]; then 
         if [[ -f $D_ECFILE ]]; then
            $MV "$D_ECFILE" "$D_ECFILE.$(timestamp FULL)" || return 1
         fi
         $CP $ECFILE $EDIR/ecfile  
         if [[ $? -ne 0 ]]; then 
            pmerror $CP 
            return 1
         fi
      fi

      return 0

   fi  # end of ECFILE was specified (-e flag).

############################################################
## Check if we need to reuse the old ecfile.
############################################################
    
   if [[ -f $ECFILE ]]; then

      [[ -n $USEOLDECF ]] && ANS=$USEOLDECF 

      while [[ $ANS -ne 0 && $ANS -ne 1 ]]; do
         if [[ $HELPMSG -eq 0 ]]; then
            print_msg 305
            HELPMSG=1
         fi

         $PB

         print_msg 39 $ECFILE
         print_prompt
         read ANS
         [[ "$ANS" = "h!" ]] && printH USEOLD
         [[ "$ANS" = "q!" ]] && exit 1 
         isYorN $ANS
         ANS=$?
      done 

      if [[ $ANS -eq 1 ]]; then
         # Make a copy of ecfile
         $CP "$ECFILE" "$ECFILE.$(timestamp FULL)" || return 1
         return 0
      fi

      $MV "$ECFILE" "$ECFILE.$(timestamp FULL)" || return 1
   fi

   return 0
          
} # end of init_ecfile()

########################################################################
## Function: Qorder
## This function takes an operation as the input and returns (prints)
## the pointer to the current question. Note: a QTYPE entry in QORDER
## means that we asked that Q and got an answer to it.
########################################################################

Qorder()
{

   typeset OPTION=""
   typeset OP=""
   typeset QTYPE=""
   typeset QNOW=""
   typeset QUIET=0

   while getopts ":o:a:q" OPTION; do
      case $OPTION in
         q) QUIET=1 ;;
         o) OP=$OPTARG ;;
         a) QTYPE=$OPTARG ;; 
      esac      
   done

   # valid OPs are LAST, FIRST, BACK, ADD, RESET, UPTO

   [[ -z $QORDER && $OP != "ADD" ]] && return 0

   case $OP in
      LAST)
         # This function prints the current pointer. It will always be
         # the last QTYPE in QORDER
         QPOINT=${QORDER##*" "} 
         ;;
      FIRST)
         # This function prints the first QTYPE in QORDER
         QPOINT=${QORDER%%" "*}
         ;;
      BACK)
         # This function moves the Q pointer back one and prints
         # the new pointer. We do some lite recursion here..

         QNOW=$(Qorder -o FIRST)

         if [[ "$QORDER" != "$QNOW" ]]; then                
            QORDER=${QORDER%" "*}
            QPOINT=${QORDER##*" "}
         else
            QORDER=""
            QPOINT=""
         fi
         ;;
      ADD)
         # This function adds QTYPE to QORDER.  We output QPOINT for
         # posterity.
         if [[ -z $QORDER ]]; then
            QORDER="$QTYPE"
         else
            QORDER="$QORDER $QTYPE"
         fi

         QPOINT=$QTYPE
         ;;
      RESET)
         export QORDER=""  # global Q order variable
         export QSTOP=0    # global Q spot variable
         return 0
         ;;
      UPTO) 
         export QORDER=${QORDER%%$QTYPE*}
         return 0
         ;;
       *)
         # The OP is not valid. Hopefully the user will never see this
         # error !
         pmerror "Qorder()" 
         return 1
         ;;
   esac

   [[ "$QUIET" -ne 1 ]] && echo "$QPOINT"

}  # end of Qorder()

########################################################################
## Function: print_prompt
########################################################################

print_prompt()
{
   echo "-> \c" 
   return 0
     
}  # end of print_prompt()

########################################################################
## Function: printH (print helps)
########################################################################

printH()
{
   typeset QTYPE="$1"
  
   case $QTYPE in
      ABSTRACT) print_msg 307;;
       PREI) print_msg 315 ;;
      POSTI) print_msg 316 ;; 
       PRER) print_msg 317 ;;
      POSTR) print_msg 318 ;;
    EREBOOT) print_msg 319 ;; 
     PREREQ) print_msg 421 ;;
      EDESC) print_msg 321 ;;
      ESHIP) print_msg 309 ;;
    ETARGET) print_msg 310 ;;
      ETYPE) print_msg 311 ;;
      EINST) print_msg 313 ;;
        ACL) print_msg 314 ;;
     AR_MEM) print_msg 312 ;;
     QFILES) print_msg 308 ;;
       QUIT) print_msg 323 ;;
     USEOLD) print_msg 322 ;;
    APARREF) print_msg 440 ;;
    LKU_CAPABLE) print_msg 476 ;;
   esac

   $PB
   print_msg 306
   $PB

   return 0

}  # end of printH()

########################################################################
## Function: exportA() exports passed in variable and value (the answers)
## Parameters: <VAR> <VAL>
## Output: Exports variable = value to enviroment
## Returns: 0 
########################################################################
exportA()
{
   typeset VAR="$1"
   typeset VAL="$2"
   typeset RC=0

   export $VAR="${VAL}"
   
   return $RC
}   # end of exportA()                                                                               

########################################################################
## Function: processA
## Returns: 0 = got answer, 1 = did not get answer, 2 - did not get
## answer and QORDER changed.
########################################################################

processA()
{
   typeset QTYPE="$1"
   typeset ENUM="$2"
   typeset ANS="$3"
   typeset RC

   # Single variable accept/reject
   reject="eval export A_$QTYPE=""; export QNEXT=""; return 1"
   accept="eval exportA A_$QTYPE \"\$ANS\"; return 0"

   # Array accept/reject
   A_accept="eval exportA A_$QTYPE[$ENUM] \"\$ANS\"; return 0"
   A_reject="eval export A_$QTYPE[$ENUM]=""; export QNEXT=""; return 1"

   case "$QTYPE" in 

      ABSTRACT) 
         # If answer is blank, ask again.. 
         [[ -z "$ANS" ]] && $reject
         # If the abstract answer is over 35 bytes, it is rejected.
         if [[ ${#ANS} -gt $ABSTRACTMAX ]]; then
            perror 27           
            $reject 
         fi 
         if [[ $SIMPLEFILE -eq 1 ]]; then
            GENUM=1
            QNEXT=ESHIP 
         else
            QNEXT=QFILES
         fi
         $accept  
         ;; # end of ABSTRACT

      QFILES)
         # If answer is blank, ask again..
         isYorN "$ANS"
         ANS=$?
         # If ANS is 1 (yes) or 0 (no), then we accept, else we reject
         if [[ $ANS -eq 1 ]]; then
            QNEXT=ESHIP
            (( GENUM = $GENUM + 1 ))
            $accept
         elif [[ $ANS -eq 0 ]]; then
            QNEXT=$(eval_qnext_flags $QTYPE) || $ERROR
            $accept
         fi
         $reject
         ;; # end of QFILES

      PREI) 
         QNEXT=POSTI
         [[ $ANS = $NONE ]] && $accept
         [[ -z $ANS ]] && $reject
         # At this point just do a check_file() on their input
         check_file_full $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept
         ;; # end of PREI

      PRER)
         QNEXT=POSTR
         [[ $ANS = $NONE ]] && $accept
         [[ -z $ANS ]] && $reject
         # At this point just do a check_file() on their input
         check_file_full $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept
         ;; # end of PRER

      POSTI)
         QNEXT=PRER    
         [[ $ANS = $NONE ]] && $accept
         [[ -z $ANS ]] && $reject
         # At this point just do a check_file() on their input
         check_file $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept
         ;; # end of POSTI

      POSTR)
         # set QNEXT 
         QNEXT=$(eval_qnext_flags $QTYPE) || $ERROR
         [[ $ANS = $NONE ]] && $accept
         [[ -z $ANS ]] && $reject
         # At this point just do a check_file() on their input
         check_file $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept

         ;; # end of POSTR

      SUPERSEDE)
         QNEXT=$(eval_qnext_flags $QTYPE) || $ERROR
         [[ -z $ANS ]] && $reject
         [[ $ANS = $NONE ]] && $accept
         # At this point just do a check_file() and abspath() on their input
         check_file_full $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept
         ;;  # end of SUPERSEDE

      E2E_PREREQ)
         QNEXT=$(eval_qnext_flags $QTYPE) || $ERROR
         [[ -z $ANS ]] && $reject
         [[ $ANS = $NONE ]] && $accept
         # At this point just do a check_file() and abspath() on their input
         check_file_full $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept
         ;;  # end of E2E_PREREQ

      PKGLOCKS)
         QNEXT=$(eval_qnext_flags $QTYPE) || $ERROR
         [[ $ANS = $NONE ]] && $accept
         # At this point just do a check_file() and abspath() on their input
         check_file_full $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept 
         ;;  # end of PKGLOCKS

      ESHIP)
         [[ -z "$ANS" ]] && $A_reject
         # At this point just do a check_file() on their input
         QNEXT=ETARGET
         check_file $ANS || $A_reject
         ANS=$(abspath $ANS) || $A_reject
         CKSUM[$ENUM]=$(getfsum $ANS) || $A_reject
         SZ[$ENUM]=$(getfsize $ANS) || $A_reject
         $A_accept
         ;; # end of ESHIP

      ETARGET)
         [[ -z "$ANS" ]] && $A_reject
       
         # Make sure that the target file starts with a "/".
         if [[ $ANS != "/"* ]]; then 
            print_msg 29 >&2
            $A_reject
         fi

         check_dup_targets "$ANS" "$NONE" "0" "$ENUM" || $A_reject

         QNEXT=ETYPE
         $A_accept
         ;; # end of ETARGET

      ETYPE) 
         QNEXT=EINST

         [[ -z "$ANS" ]] && $A_reject
         isnum "$ANS" 
         if [[ $? -ne 0 ]]; then
            perror 30             
            $A_reject 
         fi

         if [[ $ANS -ge 1 && $ANS -le $ETYPEMAX ]]; then

            # Is ar member processing required ?
            if [[ $ANS -eq $FLIBM ]]; then
               # There is an ar member
               QNEXT=AR_MEM
               $A_accept 
            else 
               # There is no ar member
               check_dup_targets "${A_ETARGET[$ENUM]}" "$NONE" "1" "$ENUM"
               [[ $? -ne 0 ]] && $A_reject
               A_AR_MEM[$ENUM]="$NONE"
               $A_accept
            fi

         else

            # bad answer
            perror 30
            $A_reject

         fi # end of if $ANS -ge 1 && $ANS -le $ETYPEMAX

         ;; # end of ETYPE
  
      AR_MEM) 
          QNEXT=EINST
          # We have to rely that the information they gave us is valid.
          if [[ -n "$ANS" ]]; then 
             check_dup_targets "${A_ETARGET[$ENUM]}" "$ANS" "1" "$ENUM" 
             [[ $? -ne 0 ]] && $A_reject || $A_accept
          fi

          $A_reject
          ;;
 
       ACL) 
         QNEXT=EMORE
         [[ -z "$ANS" ]] && $A_reject
         is_file_new $ENUM
         if [[ $? -eq 0 ]] && [[ $ANS = "DEFAULT" || $ANS = "$NONE" ]]; then
            perror 136
            $A_reject
         fi
         if [[ $ANS = $NONE || $ANS = "DEFAULT" ]]; then
            ANS="DEFAULT"
            $A_accept
         fi
         # Check to make sure they entered correct ACL format
         typeset a1 a2 a3
         echo "$ANS" | IFS=":" read a1 a2 a3
         unset IFS
         if [[ -n $a1 && -n $a2 && -n $a3 ]]; then
            isnum $a3 && $A_accept 
         fi
         # If we got here, then this is a reject.
         perror 134
         $A_reject 
         ;;  # end of ACL 
           
      EINST)
         [[ -z "$ANS" ]] && $A_reject
         isnum "$ANS" 
         if [[ $? -ne 0 ]]; then
            print_msg 30 >&2
            $A_reject 
         fi
         
         QNEXT=EMORE
         if [[ $ANS -ge 1 && $ANS -le $EINSTMAX ]]; then
            is_file_new "$ENUM" "$ANS" && {
               QNEXT=ACL
               A_ACL[$ENUM]=""
            }
            [[ $MOREOPT -eq 1 ]] && QNEXT=ACL
            [[ $QNEXT != ACL ]] && A_ACL[$ENUM]="DEFAULT"
            $A_accept
         fi
         print_msg 30 >&2
         $A_reject
         ;; # end of EINST

      EMORE)
         # If answer is blank, ask again..
         isYorN "$ANS"
         ANS=$?
         # If ANS is 1 (yes) or 0 (no), then we accept, else we reject
         if [[ $ANS -eq 1 ]]; then
            QNEXT=ESHIP
            (( GENUM = $GENUM + 1 ))
            $accept
         elif [[ $ANS -eq 0 ]]; then
            QNEXT=$(eval_qnext_flags $QTYPE) || $ERROR
            $accept
         fi
         $reject
         ;; # end of EMORE

      EREBOOT)
         isnum $ANS || $reject
        
         # We break the answer down into 2 variables 
         # One for EREBOOT and one for A_BUILD_BOOT_IMAGE 
         case $ANS in
            $NOREBOOT) ANS="no"; A_BUILD_BOOT_IMAGE="no" ;; 
            $REBOOT_BBI) ANS="yes"; A_BUILD_BOOT_IMAGE="yes" ;; 
            $REBOOT_NO_BBI) ANS="yes"; A_BUILD_BOOT_IMAGE="no" ;; 
            $BBI_NO_REBOOT) ANS="no"; A_BUILD_BOOT_IMAGE="yes";;
            *) $reject ;;
         esac

         print_line equals
         print_msg 477
         print_line equals
         QNEXT=LKU_CAPABLE
         $accept

         if [[ $aflag -eq 1  ]]; then
         [[ $SIMPLEFILE -eq 1  ]] && QNEXT=EDESC || QNEXT=PREREQ
         else
            QNEXT=APARREF
         fi

         [[ $QNEXT = "PREREQ" && $pflag -eq 1 ]] && QNEXT=EDESC
         [[ $QNEXT = "EDESC" && $dflag -eq 1 ]] && QNEXT=QEND

         $accept

         ;; # end of EREBOOT

      APARREF)
         if [[ $pflag -eq 1  ]]; then
            [[ $dflag -eq 1  ]] && QNEXT=QEND || QNEXT=EDESC
         else
            [[ $SIMPLEFILE -eq 1 ]] && QNEXT=EDESC || QNEXT=PREREQ
         fi

         [[ $QNEXT = "EDESC" && $dflag -eq 1 ]] && QNEXT=QEND

         #[[ $ANS = $NONE ]] && $accept
         [[ -z $ANS ]] && $reject
         # At this point do a check_file_full() and abspath() on their input
         check_file_full $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         verify_apar_info $ANS
         [[ $? -ge 2 ]] && $reject
         $accept

         ;; # end of APARREF

      PREREQ)
         [[ $dflag -eq 0  ]] && QNEXT=EDESC || QNEXT=QEND
         [[ $ANS = $NONE ]] && $accept
         [[ -z $ANS ]] && $reject
         # At this point just do a check_file() and abspath() on their input
         check_file $ANS || $reject
         ANS=$(abspath $ANS) || $reject
         $accept
         ;; # end of POSTI

      EDESC) 
         QNEXT=QEND    
 
         # If they passed in a file name lets look for it.
         if [[ -n $ANS && $ANS != $NONE ]]; then
            check_file_full $ANS || $reject
            ANS=$(abspath $ANS) || $reject
            if [[ $(getfsize $ANS) -gt $DESCMAX ]]; then
               perror 96 $DESCMAX
               $reject 
            fi
            $accept
         fi

         # If they want to edit, launch the editor
         if [[ $ANS = $NONE ]]; then
            edit_description || $reject
            ANS=$(abspath $DES_BUF) || $reject
            check_file_full $ANS || $reject
            if [[ $(getfsize $ANS) -gt $DESCMAX ]]; then
               # I doubt this would happen, but just in case
               perror 96 $DESCMAX
               $reject 
            fi

            $accept
         fi

         $reject

         ;;  # end of EDSEC

      LKU_CAPABLE)
         
         isYorN "$ANS"
         ANS=$?
         if [[ $ANS -eq 1 ]]; then
            ANS=$YES
         elif [[ $ANS -eq 0 ]]; then
            ANS=$NO
         elif [[ $ANS = "" ]]; then
            ANS=$YES
         else
            $reject
         fi

         if [[ $aflag -eq 1  ]]; then
            [[ $SIMPLEFILE -eq 1  ]] && QNEXT=EDESC || QNEXT=PREREQ
         else
            QNEXT=APARREF
         fi

         [[ $QNEXT = "PREREQ" && $pflag -eq 1 ]] && QNEXT=EDESC
         [[ $QNEXT = "EDESC" && $dflag -eq 1 ]] && QNEXT=QEND

         $accept

      ;; 
   esac

   return 1 # error 

}  # end of processA()
 
########################################################################
## Function: getA4Q   
########################################################################

getA4Q()
{
   typeset QTYPE="$1"
   typeset ANS # local answer
   typeset ENUM="$2"
   typeset GOODANS=0
   typeset SAFELOOP=1

###########################################################
## We loop the question until we get a verified answer.
## If they ask for help, we print help and ask the 
## question again. If there is something wrong with 
## the answer we ask the question again.. Note, 
## processA() does any conversions and sets the global
## "A_<QUESTION>" variable. 
########################################################### 

   QNEXT="" # Init QNEXT
   GQTYPE=$QTYPE

   while [[ $GOODANS -ne 1 ]]; do  

###########################################################
## Make sure that we are not entering a question that has
## been answered by a flag..
###########################################################
      
      ckNQ "$QTYPE"
      if [[ $? -ne 0 ]]; then
         if [[ $SIMPLEFILE -eq 1 ]]; then
            case $QTYPE in
               PREI|PRER|POSTI|POSTR) QTYPE=EREBOOT ;;
               PREREQ) QTYPE=EDESC ;;
            esac 
         fi
         [[ $QTYPE = EREBOOT && $rflag -eq 1 ]] && QTYPE=APARREF
         [[ $QTYPE = APARREF && $aflag -eq 1 ]] && QTYPE=PREREQ
         [[ $QTYPE = PREREQ && $pflag -eq 1 ]] && QTYPE=EDESC
         [[ $QTYPE = EDESC && $dflag -eq 1 ]] && QTYPE=QEND
         if [[ $QTYPE = "QEND" ]]; then
            QNEXT=QEND
            return 0
         fi
      fi

###########################################################
## Ask the question..
###########################################################

      PA="" # Init previous answer just in case.       
      printQ $QTYPE $ENUM
      read ANS

      if [[ $ASKAGAIN -eq 1 ]]; then
         ASKAGAIN=0
         $PB 
         continue
      fi

      case $ANS in
         "h!") # print help message
            printH "$QTYPE" "$ENUM"
            continue
            ;;
        "sq!") # Save and quit.
            print_ecfile > $ECFILE || FAIL
            exit $? 
            ;;
        "sh!") # escape to shell
            print_msg 387 epkg 2>&1
            /usr/bin/sh || pmerror /usr/bin/sh 
            continue 
            ;; 
         "q!") FAIL  # quit now, don't save ecfile
            ;;
         "b!") # go back to previous question
            # If this is the 1st question, just repeat it
            if [[ -z "$QORDER" ]]; then
               QNEXT=$QTYPE
               return 0  # back to Qdriver
            fi 
            
            QNEXT=$(Qorder -o LAST) 
            Qorder -q -o BACK

            # Make sure we have not backed up into a question
            # that is answered by a flag. 
            SAFELOOP=0
            while [[ $SAFELOOP -lt $MAXEFILES ]]; do
               ckNQ "$QNEXT" && break
               (( SAFELOOP = $SAFELOOP + 1 ))
               QNEXT=$(Qorder -o LAST)
               Qorder -q -o BACK
            done

            # If QNEXT is EMORE, but not PREI, then reduce GENUM
            # This is in the case that we are moving through
            # multiple files. 
            # If this is QNEXT and EFILES, then reduce GENUM
            # This is when we move from 1st file to original
            # QFILES

            if [[ $QNEXT = EMORE || $QNEXT = QFILES ]]; then
               [[ $QTYPE != PREI ]] && (( GENUM = $GENUM - 1 ))
               if [[ $SIMPLEFILE -eq 1 ]]; then
                  # Since we will never have PREI in SIMPLEFILE
                  # we add GENUM back.
                  case $QTYPE in EREBOOT|PREREQ|EDESC) 
                     (( GENUM = $GENUM + 1 ));; esac 
               fi
            fi

            return 0 # return control to Qdriver
            ;;
         "s!") # print what we have so far
            print_ecfile 
            $PB
            ;;
         ASKAGAIN) # ask the question again.
            ;;
         *) # Process the actual answer..
            # If PA is set, but ANS is not, then we use it.
            [[ -n $PA && -z $ANS ]] && ANS=$PA
            processA "$QTYPE" "$ENUM" "$ANS" && GOODANS=1
            # Check if we changed QORDER within processA
            [[ $? -eq 2 ]] && return 0;;
      esac

   done

   Qorder -q -o ADD -a "$QTYPE"
   return 0

}  # end of getA4Q 

########################################################################
## Function: Qdriver
########################################################################

Qdriver()
{

   trap 'epkgtrap' 1 2 3 11 15
   typeset ERROR='eval pmerror "Qdriver()"; return 1'

###########################################################
## If QNEXT is blank, set it to the first questions.   
###########################################################

   [[ -z $QNEXT ]] && QNEXT="ABSTRACT"
 
   while [[ -n $QNEXT && $QNEXT != "QEND" ]]; do

      if [[ $HELPMSG -eq 0 ]]; then
         print_msg 305
         HELPMSG=1
      fi 

      $PB
      # Ask the NEXT Q   
      getA4Q $QNEXT $GENUM || $ERROR  

   done            

   [[ $QNEXT = "QEND" ]] && GQTYPE=QEND

   return 0  

}  # end of Qdriver

########################################################################
## Function: usage  
########################################################################

usage()
{

   typeset USAGE

   USAGE="Usage epkg: Create fix package.
     epkg [-w <workdir>] [-a <APARref file>] [-p <prereq file>] 
     [-d <description file>] [-e <ecfile>] [-l <pkglocks>] 
     [-g <fix to fix prereq file>] [-S <supersede file>] [-u (y|n)] 
     [-r (y|n|o)] [-svX] [-T (y|n)] fixLabel

Flags:
   -w Alternate work directory.
   -a Specifies the file containing APAR reference numbers.
   -p Prereq file. A file that contains installp prerequisites.
   -d Description. File containing the fix description.
   -e Fix Control File. The file that dictates how the fix
      is to be constructed.
   -g Fix to Fix prerequisite file.
   -l Additional package locks file.
   -u Use existing ECFILE (Yes or No.)
   -r Fix reboot policy. 
   -s Simple Mode. No scripts or prereq file (unless -p is specified).
   -v Verbose questions. Asks more questions for extended options.
   -S Supersedes file.
   -X Automatic file system expansion.
   -T Fix test state."

   if [[ "$LANG" != "C" && "$LANG" != "en_US" && -x /usr/sbin/inuumsg ]] ||
      [[ $EMGR_FORCE_LOCPRINT = 1 ]]
   then
      /usr/sbin/inuumsg 831        
   else
      echo "$USAGE" >&2
   fi

   exit 1

}  # end of usage()

########################################################################
## Function: printQ
########################################################################

printQ()
{
   [ "$EPKG_PRINT_MSG_DBG" -ne 1 ] && set +x
   
   typeset Qmsg         # local question message
   typeset Q_OPT=$1     # local question option
   typeset k            # local index for loop var
   typeset i=0          # local counter
   typeset ENUM=$2      # Efix file number
   typeset MSG          # local message number

   case "$Q_OPT" in
      ABSTRACT) Qmsg=$(print_msg 2 $ABSTRACTMAX);;
      QFILES)   Qmsg=$(print_msg 3 );;
      PREI)     Qmsg=$(print_msg 4);;
      POSTI)    Qmsg=$(print_msg 5);;
        ACL)    is_file_new $ENUM && MSG=135 || MSG=133
                Qmsg=$(print_msg $MSG $ENUM)
                ;;
      ESHIP)    Qmsg=$(print_msg 6 $ENUM);;
      ETARGET)  Qmsg=$(print_msg 7 $ENUM);;

      ETYPE)    Qmsg=$(print_msg 8 "$ENUM"; 
                       echo "1) \c"; print_msg 9; 
                       echo "2) \c"; print_msg 10) ;; 

      EINST)    Qmsg=$(for k in 12 13 14 15 16 31 32 33 34 17; do 
                       [[ $i -gt 0 ]] && echo "$i) \c";
                       inc i;
                       print_msg $k $ENUM; done);;

      AR_MEM)   Qmsg=$(print_msg 237 "$ENUM" ${A_ETARGET[$ENUM]});;

      EMORE)    Qmsg=$(print_msg 18);;

      EREBOOT)  Qmsg=$(for k in 353 354 355 356 416; do
                       [[ $i -gt 0 ]] && echo "$i) \c";
                       inc i; 
                       print_msg $k; done);;

      EDESC)    Qmsg=$(print_msg 66);;
      PRER)     Qmsg=$(print_msg 42);;
      POSTR)    Qmsg=$(print_msg 43);;
      PREREQ)   Qmsg=$(print_msg 68);;
      PKGLOCKS) Qmsg=$(print_msg 359);;
     SUPERSEDE) Qmsg=$(print_msg 369);;
    E2E_PREREQ) Qmsg=$(print_msg 388);;
       APARREF) Qmsg=$(print_msg 439);;
    LKU_CAPABLE) Qmsg=$(print_msg 475);;

   esac
      
   if [[ -z $Qmsg ]]; then
      pmerror "printQ()" >&2 
      FAIL
   fi   


   echo "$Qmsg"
   processPA $Q_OPT $ENUM
   print_prompt $Q_OPT 

   return 0 

}  # end of printQ()

########################################################################
## Function: FAIL
########################################################################

FAIL()
{
   perror 25 
   cleanup FAIL 
   exit 1

}  # fail()

########################################################################
## Function: cleanup
########################################################################

cleanup()
{
   typeset CF=""

   $RM -f $MSG_BUF $ERRTOKEN $ERR_BUF $ALIST $DUMMY_PREREQ

   # Clean added files
   for CF in $ADD_CLEAN_FILE
   do
     $RM -f $CF
   done

   # Clean added dirs
   for CF in $ADD_CLEAN_DIR
   do
     $RMDIR $CF > /dev/null 2>&1
   done

   if [[ $1 = "FAIL" ]]; then
      $RM -f $EIMAGE
   fi

   return 0

}  # cleanup()

########################################################################
## Function: epkg_getopts()
########################################################################

epkg_getopts()
{
   typeset GETOPTSTR     # getopt string
   typeset i             # index
   typeset RC=0
   typeset ARGC=$#          
   typeset ARGS="$@"
   typeset LASTARG=${ARGS##*" "}
   typeset ENDVAR=""
   typeset ENDSTR="ENDING_GETOPT.$$"
 
   # If less then 1 argument, then usage error..          
   [[ $ARGC -lt 1 ]] && return 1
 
   # Strip off LASTARG and add -Z (end variable for args) 
   ARGS=${ARGS%"$LASTARG"}
   ARGS="$ARGS -Z $ENDSTR"

   # Go ahead and check A_ELABEL here, there is no reason to
   # run getopt if A_ELABEL is wrong. 

   A_ELABEL=$LASTARG
   [[ -z $A_ELABEL || $A_ELABEL = [-]* ]] && return 1
   vstrDS $A_ELABEL || return 1
   if [[ "$(toupper $A_ELABEL)" = "ALL" ]]; then
      perror 188 $A_ELABEL
      return 1
   fi

############################################################
## Init epkg flags..
############################################################

   export pflag=0
   export dflag=0
   export rflag=0
   export eflag=0
   export lflag=0
   export Sflag=0
   export gflag=0
   export Tflag=0
   export aflag=0
   export kflag=0
   export USEOLDECF=""
   export SIMPLFILE=0
   export EXP_REQUESTED=0 
   export MOREOPT=0

############################################################
## Set default "English" answers.
############################################################
  
   A_FIXTESTED="no"

############################################################
## Remove the last argument from ARGS.  This way we isolate
## A_ELABEL.
############################################################
   
   GETOPTSTR=":w:p:r:e:x:d:l:g:S:T:A:Z:u:k:svxXDa:"   # 99

   while getopts "$GETOPTSTR" OPTION $ARGS; do 
      RC=0 
      [[ $OPTARG = [-]* ]] && return 1

     case $OPTION in
         T) isYorN "$OPTARG"; RC=$?  # tested fix ?
            case $RC in
               0) A_FIXTESTED="no";;
               1) A_FIXTESTED="yes";;
               *) return 1;;
            esac
            Tflag=1;;
         A) abort_function "$OPTARG" ;;
         x) typeset -ft "$OPTARG" || $ERROR;;
         Z) ENDVAR=$OPTARG   
            [[ "$ENDVAR" != "$ENDSTR" ]] && return 1;;
         r) isYorN "$OPTARG"; RC=$?  # reboot required ?
            [[ $RC -ne 0 && $RC -ne 1 ]] && RC="$OPTARG"   

            case "$RC" in
               0) A_EREBOOT=$NO; A_BUILD_BOOT_IMAGE=$NO   ;;
               1) A_EREBOOT=$YES; A_BUILD_BOOT_IMAGE=$YES ;;
             "o") A_EREBOOT=$YES; A_BUILD_BOOT_IMAGE=$NO  ;; 
             "b") A_EREBOOT=$NO; A_BUILD_BOOT_IMAGE=$YES  ;;
               *) $ERROR
            esac

            rflag=1;; 
         w) export WORKDIR=$OPTARG;;  
         p) export A_PREREQ=$OPTARG   
            pflag=1;;
         u) isYorN "$OPTARG"; RC=$?   # Use old efix control file ?
            [[ $RC -eq 2 ]] && return 1 || USEOLDECF=$RC ;;
         d) export A_EDESC=$OPTARG   
            dflag=1;;
         D) set -x
            export DEBUG=1
            for i in $(typeset +f); do typeset -ft $i; done;;
         s) SIMPLEFILE=1   
            for i in PREI PRER POSTI POSTR PREREQ; do
               eval A_$i=$NONE       
            done;;
         e) export ECFILE=$OPTARG
            eflag=1;;
         X) EXP_REQUESTED=1;;
         v) MOREOPT=1;;
         l) export A_PKGLOCKS=$OPTARG 
            lflag=1;; 
         S) export A_SUPERSEDE=$OPTARG 
            Sflag=1;;
         g) export A_E2E_PREREQ=$OPTARG
            gflag=1;;
         a) export A_APARREF=$OPTARG
            aflag=1;;
         k) isYorN "$OPTARG"; RC=$?
            case $RC in
               0) A_LKU_CAPABLE=$NO;;
               1) A_LKU_CAPABLE=$YES;;
               *) return 1;;
            esac
            kflag=1;;
         *|\?) return 1;;
      esac

      (( FSUM = $pflag + $dflag + $eflag + $lflag + $Sflag ))

   done  # getops while loop

############################################################
## Check for valid syntax..
############################################################
   
   [[ "$ENDVAR" != "$ENDSTR" ]] && return 1

   return 0 
         
}  # end of epkg_getopts()

########################################################################
## MAIN Main main
########################################################################

eval $SIGTRAP
export EMGR=0
export EPKG=1
export ELIB="/usr/lib/instl/elib"
export EMGRLOG=0
export HELPMSG=0
export NOWARN=1
export QUIET=0

############################################################
## Load in ELIB
############################################################

. $ELIB || exit 1

############################################################
## If this is a LIBLOAD only, then we are done.
############################################################
                                                                                
  [[ $ELIB_LOAD_ONLY = "1" ]] && return 0

############################################################
## Capture the arguments specified for this command. 
############################################################

export MAINARGS="$@"

############################################################
## Check for debug flag in ARGS.
############################################################

check4debug "$MAINARGS" && set -x 

############################################################
## Initialize all variables.
############################################################

init_vars

############################################################
## Check syntax..
############################################################

epkg_getopts $MAINARGS || usage

############################################################
## Initialize all standard commands.  If this function 
## fails, we have to stop b/c we are missing one or more
## executables.
############################################################

init_pos_cmds || exit 1

############################################################
## Initialize system specific variables..  
############################################################

init_sys_vars || FAIL

############################################################
## Check for some errors upfront that got by the syntax.
############################################################

ck_epkg_flag_files || FAIL 

############################################################
## Initialize ecfile
############################################################

init_ecfile || FAIL

############################################################
## If there is an existing ECFILE, then we read it in..
############################################################


if [[ -s $ECFILE ]]; then
   read_previous_ecfile || FAIL 
fi

############################################################
## Set the version of this epkg (i.e. EPKG_VERSION)
############################################################

EPKG_VERSION=$EVERSION
 
############################################################
## Get answers to all unanswered questoins..
############################################################

Qdriver || FAIL

############################################################
## Generate the sec file for ifix objects and update the 
## TSD
###########################################################
GenSecFile || FAIL

############################################################
## Write out the EFIX control file. This function also
## calculates INSTWORK space requirements and VUID.
############################################################

write_ecfile || FAIL 

############################################################
## We need to make sure what we wrote was correct. We
## verify what we just wrote by reading it back.
############################################################

read_ecfile || FAIL   

############################################################
## Verify config rules.. that is all config files and 
## various rules.
############################################################

verify_config_rules || FAIL

############################################################
## At this point we should have all of our answers and
## the ecfile. Lets populate $EDIR.  
############################################################

pop_edir || FAIL 

############################################################
## Ok.. lets build the EFIX package.
############################################################

pack_epkg || FAIL 

print_msg 61 "$EIMAGE"

cleanup

# Done !
exit 0