#!/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: ## 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: ## 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 ) 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: ## 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_" 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 ] [-a ] [-p ] [-d ] [-e ] [-l ] [-g ] [-S ] [-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