#!/bin/sh
# Copyright 06/01/04  Sun Microsystems, Inc. All Rights Reserved.
#
# pragma ident  "@(#)es-backup-common	1.12 04/06/01 Sun Microsystems"
#

get_package_param() {
    pkg=$1
    param=$2
    /usr/bin/pkginfo -qi $pkg >/dev/null 2>&1
    if [ $? -eq 0 ] ; then
        value=`/usr/bin/pkgparam $pkg $param`
        return 0
    fi
    value=""
    return 1
}

# This functions verifies if currently database
# is in ARCHIVELOG mode or NOARCHIVELOG mode.

validate_archivelog_mode () {
 
    start_db noexit
     if [ $? -ne 0 ]; then
        echolog "It appears the database is corrupt. Proceeding with database recovery."
        # Assume the database was in the archivelog mode. We have no choice
        return 0
    fi

    sqlout=/tmp/sqlout.$$
    /usr/bin/rm -f $sqlout

    /usr/bin/su - $SMCORAU -c ". $BASEDIR/sbin/es-common.sh; set_db_env; . $BASEDIR/lib/sbin/db-common.sh; set_db_password; 
    $SQLPLUS -s /nolog <<EOF
        connect $SYS_LOGIN/$SYSPWD as sysdba
        set pagesize 0
        set heading off
        set echo off
        set feedback off
        set termout off
        spool $sqlout
        select log_mode from v\\\$database;
EOF " >> $LOGFILE 2>&1

    if [ $? -ne 0 ] ; then
       echolog 'Unable to retrieve log mode from Sun Management Center database'
       /usr/bin/rm -f $sqlout
       return 1
    else
       LOG_MODE=`/usr/bin/grep '^' $sqlout | /usr/bin/grep -v SQL | /usr/bin/cut -f1 -d" "`

       if [ "$LOG_MODE" != "ARCHIVELOG" ]; then
          echolog "Database is not in the archivelog mode."
          echolog "Please enable archivelog mode before re-attemting requested task."
          /usr/bin/rm -f $sqlout
          return 1
       fi   
    fi
    /usr/bin/rm -f $sqlout

    return 0
}

#
# initialize the following variables:
#
# - SUNMC_VERSION
# - PRM_VERSION
# - SUNMC_DBFILE
# - ESCOM_VERSION
# - ESCOM_BASEDIR
# - ESTBL_BASEDIR
# - ESDRG_VERSION
#
# - SYS_LOGIN
# - SYS_PASSWD
# - ORA_DATADIR
# - ORA_INITFILE
#
# - METAFILE
# - CFGFILE
# - DUMPFILE
# - DBBAKFILE
#

set_backup_common() {

    #
    # get the SunMC version (i.e. 3.0 or 3.5)
    #
    get_package_param SUNWescom VERSION
    if [ $? -ne 0 ] ; then
        echolog "Sun Management Center package \\\(SUNWescom\\\) is not installed"
        return 1
    fi

    ESCOM_VERSION=$value
    SUNMC_VERSION=`/bin/echo "$value" | /usr/bin/awk '{ print substr($1,0,3) }'`

    get_package_param SUNWescom BASEDIR
    ESCOM_BASEDIR=$value

    get_package_param SUNWestbl BASEDIR
    if [ $? -ne 0 ] ; then
        echolog "Sun Management Center package \\\(SUNWestbl\\\) is not installed"
        return 1
    fi
    ESTBL_BASEDIR=$value

    get_package_param SUNWesdrg VERSION
    ESDRG_VERSION=$value
    PRM_VERSION=`/bin/echo "$value" | /usr/bin/cut -f1 -d,`
    if [ "$PRM_VERSION" != "" ] ; then
        PRM_EXISTS=1
        PRM_SCHEMA_OWNER=report
    fi

    #
    # set various version specific variables
    #

    . ${BASEDIR}/lib/sbin/db-common.sh

    set_db_password

    if [ "$SUNMC_VERSION" = "3.0" ]; then

        DB_USERS="sunmc sunmcu"
        DB_SCHEMA_OWNER=sunmc

        ORA_INITFILE=$ORACLE_HOME/admin/$ORACLE_SID/pfile/initSunMC30.ora
        ORA_DATADIR=SUNWsymon/SunMCDB02
        ORA_CTRLFILES="$ORA_DATADIR/oradata/SunMC30/*.ctl $ORA_DATADIR/oradata/SunMC30/redo*"
        ORA_EVENTDIR=$ORA_DATADIR/eventmgr

        SUNMC_DBFILE=$VAROPTDIR/cfg/dbase.cfg 
        DB_CRINST_SH=$ESCOM_BASEDIR/SUNWsymon/sbin/db-crinst.sh
        SQLPLUS=$ORACLE_HOME/bin/sqlplus
        DBVERIFY=$ORACLE_HOME/bin/dbv

    elif [ "$SUNMC_VERSION" = "3.5" ]; then

        DB_USERS="sunmc sunmc_owner"
        DB_SCHEMA_OWNER=sunmc_owner

        ORA_INITFILE=$ORACLE_HOME/admin/$ORACLE_SID/pfile/initSunMC.ora
        ORA_DATADIR=db
        ORA_CTRLFILES="$ORA_DATADIR/oradata/SunMC/*.ctl $ORA_DATADIR/oradata/SunMC/redo*"
        ORA_EVENTDIR=$ORA_DATADIR/eventmgr

        SUNMC_DBFILE=$BASEDIR/db/cfg/dbadmin.cfg
        DB_CRINST_SH=$ESCOM_BASEDIR/SUNWsymon/lib/sbin/db-crinst.sh
        SQLPLUS=$ORACLE_HOME/bin/sqlplus
        DBVERIFY=$ORACLE_HOME/bin/dbv

    else
        echolog 'Unsupported Sun Management Center version: $2' "$SUNMC_VERSION"
        return 1
    fi

    if [ ! -f "$SUNMC_DBFILE" ]; then
        echolog 'Database configuration $2 file not found' "$SUNMC_DBFILE"
        return 1
    fi

    METAFILE=SUNMC_BAK.meta
    DB_PERMS_FILE=data/sysperms.sql

    return 0
}
#db_runSql  $sql $username $passwd $outfile
# DESCRIPTION: runs any SQL (not PL/SQL) statement passed in
#
# Returns: 0 - success
#          1 - error sqlplus
#
db_runSql () {
    sql="$1"; username=$2; passwd=$3; outfile=$4
    $ORACLE_HOME/bin/sqlplus -s ${username}/${passwd}<<-EOF>$outfile 2>/dev/null
        set verify off;
        set echo off;
        set serveroutput on;
        set heading off;
        set feedback off;
        set pagesize 1024;
        $sql;
EOF
    retstat=$?
    [ $retstat -ne 0 ] && return 1
    return 0
}

#db_checkErr $outfile $logfile
# DESCRIPTION: checks an outfile for any flagrant ORACLE errors
#
#  Returns:  0 - success
#            1 - failure
#
db_checkErr () {
    outfile=$1; logfile=$2

    error=`/usr/bin/egrep -n "ORA-|PLS-|SP2-" $outfile | /usr/bin/egrep -v "ORA-01434|ORA-00942|ORA-04043|ORA-01418|ORA-02443|ORA-0001|ORA-01918" | /usr/bin/head -1 | /usr/bin/cut -d: -f1`
    if [ "$error" -gt 0 ]; then
        numlines=`/usr/bin/wc -l $outfile | /usr/bin/awk '{print $1}'`
        offset=`/usr/bin/expr $numlines - $error`

        echolog 'Database error occurred.'
        echologverbose "Oracle Error: Start..."
        /usr/bin/tail -${offset} $outfile >>$logfile
        echologverbose "Oracle Error: End"
        return 1
    fi

    return 0

}


# db_runSqlSpool $sql $spool $type $login $passwd $log_file
# DESCRIPTION: spools any sql/PlSql output to a given file
#    NOTE: type = SQL or type = PL/SQL
#
# Returns:  0 - success
#           1 - error running sql/PlSql command
#           2 - error spooling to $spool file
#
db_runSqlSpool () {
    sql="$1"; spool="$2"; type=$3; login=$4; passwd=$5; log_file=$6
    [ $type != "SQL" -a $type != "PL/SQL" ] && return 3

    tmp_file="/tmp/tmp-sqlspool.$$"
    /usr/bin/rm -f $tmp_file

    if [ $type = "SQL" ];then
        db_runSql "$sql" $login $passwd $tmp_file
        db_checkErr $tmp_file $log_file
        if [ $? -ne 0 ];then
            echologverbose 'Error encountered running SQL $2' "$sql"
            /usr/bin/rm -f $tmp_file
            return 1
        fi
    else
        db_runPlSql "$sql" $login $passwd $tmp_file
        db_checkErr $tmp_file $log_file
        if [ $? -ne 0 ];then
            echologverbose 'Error encountered running PL/SQL $2' "$sql"
            /usr/bin/rm -f $tmp_file
            return 1
        fi
    fi

    /usr/bin/cp $tmp_file $spool
    if [ $? -ne 0 ];then
        echologverbose 'Error encountered spooling file: $2' "$spool"
        /usr/bin/rm -f $tmp_file
        return 2
    fi

    /usr/bin/rm -f $tmp_file
    return 0
}
# setup_backup_format $formatnum
setup_backup_format () {
    format=$1
    if [ "$format" -eq 1 ] ; then
        CFGFILE=data/cfgfiles.tar
        DBBAKFILE=data/db.tar
    elif [ "$format" -eq 2  -o "$format" -eq 4 ] ; then
        CFGFILE=data/cfgfiles.tar
        DUMPFILE=data/sunmc.dmp
    elif [ "$format" -eq 3 ]; then
        CFGFILE=data/cfgfiles.tar
    else
        echolog 'Internal error: unknown backup format $2' "$format"
        exit 1
    fi
    return 0
}

stop_SunMC() {
    $BASEDIR/sbin/es-stop -A
    if [ $? -ne 0 ] ; then
        echolog "Failed to stop Sun Management Center"
        return 1
    fi
    return 0
}

start_SunMC() {
    $BASEDIR/sbin/es-start -A
    if [ $? -ne 0 ] ; then
        echolog "Failed to start Sun Management Center"
        return 1
    fi
    return 0
}
# Argument $1 is to avoid exit in case there is a media failure
start_db() {
    NOEXIT="$1"
    if [ -z "$DB_UP" -o "$DB_UP" -eq 0 ]; then
        echolog 'Starting database...'
        /usr/bin/su - $SMCORAU -c $BASEDIR/sbin/db-start
        if [ $? -ne 0 ] ; then
            echolog "Failed to start Sun Management Center database"
            if [ -z "$NOEXIT" ]; then
            print_failure_and_exit 1
            else
            return $retcode
            fi
        fi
        DB_UP=1
    fi
    return 0
}
# Argument $1 is to avoid exit in case there is a media failure
shutdown_db() {
     NOEXIT="$1"
    if [ -z "$DB_UP" -o "$DB_UP" -eq 1 ]; then
        echolog 'Stopping database...'
        /usr/bin/su - $SMCORAU -c $BASEDIR/sbin/db-stop
        if [ $? -ne 0 ] ; then
            echolog "Failed to stop Sun Management Center database"
            if [ -z "$NOEXIT" ]; then
            print_failure_and_exit 1
            else
            return $retcode
            fi 
        fi
        DB_UP=0
    fi
    return 0
}
# Greenline behaves strangely when datafiles and control files are gone
# It disables the sunmcdatabase service but does not stop processes.
# Need to kill processes forcefully

kill_db() {
    if [ -x /usr/bin/svcprop ] && [ "$OSNAME" = "SunOS" ] ;then
        /usr/bin/su - $SMCORAU -c $BASEDIR/sbin/db-stop
        kill_ora_processes
        release_shm_sems "$SMCORAU" "$SMCORAG"
    fi
}

clean_subdirs() {
    dir=$1
    if [ "$dir" = "/" ] ; then
        echolog 'Cannot remove /.'
        return 1
    fi
    /usr/bin/rm -rf $dir/*
}

# NOTE: clean_subdirs_smc()
#                cleans recursively
# directory trees by removing all
# the files,links to other files
# and empty directories.
# Links to other directories will not be
# removed.
#
clean_subdirs_smc() {
   dir=$1
   if [ "$dir" = "/" ] ; then
        echolog 'Cannot remove /.'
        return 1
   fi

   for directory in `/usr/bin/ls -F $dir` ; do
      dir_ident=`echo $directory|/usr/bin/nawk '{ print substr($0, length($0)) }'`
      if [ "$dir_ident" = "@" ] ; then
         linked_elem=`echo $directory|/usr/bin/nawk '{ print substr($0, 1, length($0)-1) }'`
         if [ -d "${dir}/${linked_elem}" ] ; then
              ( clean_subdirs_smc "${dir}/${linked_elem}" )
         else
              /usr/bin/rm -f "${dir}/${linked_elem}"
         fi
      elif [ "$dir_ident" = "/" ]; then
       ( clean_subdirs_smc "${dir}/${directory}" )
        /usr/bin/rmdir -p "${dir}/${directory}" 2>/dev/null
      else
        /usr/bin/rm -f "${dir}/${directory}"
      fi
   done
 
  return 0
}

#
# NOTE: should improve this check to account for more than just the first 8
# characters of the process name.
#
check_process_conflicts () {
    name=$1

    pids=`/usr/bin/ps -ef -o pid,args | /usr/bin/egrep $name | /usr/bin/egrep -v $$ | /usr/bin/awk '{print $1}' `
    if [ "$pids" != "" ]; then
        name8=`/bin/echo $name | /usr/bin/awk '{print substr($1,0,7)}'`
        count=`/usr/bin/ps -p "$pids" -o fname | /usr/bin/egrep $name8 | /usr/bin/wc -l`
        if [ "$count" -gt 0 ]; then
            return 1
        fi
    fi

    return 0
}

#
# inputs: $1 - base name
#         $2 - number of elements
#
# output: names - list of names, i.e. "baseaa baseab baseac ..."
#
get_split_names () {

    name=$1
    num=$2

    ALPHABET="a b c d e f g h i j k l m n o p q r s t u v w x y z"

    names=""
    n=1
    for i in $ALPHABET
    do
        for j in $ALPHABET
        do
            for k in $ALPHABET
            do
                if [ "$n" -gt "$num" ]; then
                    break 3
                fi
                names="$names ${name}${i}${j}${k}"
                n=`expr $n + 1`
            done
        done
    done
    return 0
}

# create_pipe pipename
create_pipe () {
    pipe=$1
    /usr/bin/rm -f $pipe     2>/dev/null 1>&2
    /usr/sbin/mknod $pipe p  2>/dev/null 1>&2
    if [ $? -ne 0 ] ; then
        /usr/bin/rm -f $pipe 2>/dev/null 1>&2
        echolog 'Could not create pipe'
        return 1
    fi

    return 0
}

# scan_dbv_log $logfile $associated_dbf_file
# Scan DBVERIFY logfile to see if verification was successful.
scan_dbv_log () {
    dbvlog=$1
    dbf_file=$2

    /usr/bin/egrep '^DBV-[0-9]+:' $dbvlog >/dev/null 2>&1
    if [ $? -ne 1 ] ; then
        echolog 'Database verification utility errors occurred:'
        /usr/bin/egrep '^DBV-[0-9]+:' $dbvlog | /usr/bin/tee -a $LOGFILE 2>&1
        echolog 'Database verification utility failed.'
        return 1
    fi

    num_errors=`/usr/bin/egrep '^(Total Pages Failing|Total Pages Marked Corrupt)' $dbvlog | /usr/bin/egrep -v ':[ ]*0[ ]*$' | /usr/bin/wc -l`
    if [ "$num_errors" -gt 0 ] ; then
        echolog 'Problems were found in the database file $2.' "$dbf_file"
        return 1
    fi

    return 0
}


