#!/bin/sh
#
#  This library is part of the Firebird project
#
#  This library is free software; you can redistribute it and/or
#  modify it under the terms of the GNU Lesser General Public
#  License as published by the Free Software Foundation; either
#  version 2.1 of the License, or (at your option) any later version.
#  You may obtain a copy of the Licence at
#  http://www.gnu.org/licences/lgpl.html
#  
#  As a special exception this file can also be included in modules
#  with other source code as long as that source code has been 
#  released under an Open Source Initiative certificed licence.  
#  More information about OSI certification can be found at: 
#  http://www.opensource.org 
#  
#  This module is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public Licence for more details.
#  
#  This module was created by members of the firebird development 
#  team.  All individual contributions remain the Copyright (C) of 
#  those individuals and all rights are reserved.  Contributors to 
#  this file are either listed below or can be obtained from a CVS 
#  history command.
# 
#   Created by:  Mark O'Donohue <mark.odonohue@ludwig.edu.au>
# 
#   Contributor(s):
#  
# 
#   $Id: postinstall.sh.in,v 1.10.2.12 2005/10/26 14:31:40 alexpeshkoff Exp $
# 

# The post install script for Firebird Classic


#------------------------------------------------------------------------
# Prompt for response, store result in Answer

Answer=""

AskQuestion() {
    Test=$1
    DefaultAns=$2
    echo -n "${1}"
    Answer="$DefaultAns"
    read Answer
}


#------------------------------------------------------------------------
# add a service line in the (usually) /etc/services or /etc/inetd.conf file
# Here there are three cases, not found         => add service line,
#                             found & different => ask user to check
#                             found & same      => do nothing
#                             

replaceLineInFile() {
    FileName=$1
    newLine=$2
    oldLine=$3

    if [ -z "$oldLine" ] 
      then
        echo "$newLine" >> $FileName

    elif [ "$oldLine" != "$newLine"  ]
      then
        echo ""
        echo "--- Warning ----------------------------------------------"
        echo ""
        echo "    In file $FileName found line: "
        echo "    $oldLine"
        echo "    Which differs from the expected line:"
        echo "    $newLine"
        echo ""

#        AskQuestion "Press return to update file or ^C to abort install"

        cat $FileName | grep -v "$oldLine" > ${FileName}.tmp
        mv ${FileName}.tmp $FileName
        echo "$newLine" >> $FileName
        echo "Updated."

    fi
}

#------------------------------------------------------------------------
#  Detect Distribution.

detectDistro() {

    # it's not provided...
    if [ -z "$linuxDistro"  ]
    then
	if [ -e /etc/SuSE-release  ]
	then
	    # SuSE
	    linuxDistro="SuSE"
	elif [ -e /etc/mandrake-release ]
	then
	    # Mandrake
	    linuxDistro="MDK"
	elif [ -e /etc/debian_version ]
	then
	    # Debian
	    linuxDistro="Debian"
	elif [ -e /etc/gentoo-release ]
	then
	    # Debian
	    linuxDistro="Gentoo"
	elif [ -e /etc/rc.d/init.d/functions ]
	then
	    # very likely Red Hat
	    linuxDistro="RH"
	elif [ -d /etc/rc.d/init.d ]
	then
	    # generic Red Hat
	    linuxDistro="G-RH"
	elif [ -d /etc/init.d ]
	then
	    # generic SuSE
	    linuxDistro="G-SuSE"
	fi
    fi
}

#------------------------------------------------------------------------
#  Add new user and group


addFirebirdUser() {

    testStr=`grep firebird /etc/group`

    if [ -z "$testStr" ]; then
        groupadd firebird
    fi

    testStr=`grep firebird /etc/passwd`
    if [ -z "$testStr" ]; then
        useradd -M -d $FBRootDir -s /bin/bash \
            -c "Firebird Database Administrator" -g firebird firebird 
    fi
}


#------------------------------------------------------------------------
#  Delete new user and group


deleteFirebirdUser() {

    userdel firebird
 #   groupdel firebird

}


#------------------------------------------------------------------------
#  changeXinetdServiceUser
#  Change the run user of the xinetd service
#  ex is used in place of ed, since at least on one mandrake release ed
#  was not installed, but ex seems to always be installed MOD 7-Nov-2002

changeXinetdServiceUser() {

    InitFile=/etc/xinetd.d/firebird
    if [ -f $InitFile ] 
      then
        ex -s $InitFile <<EOF
/	user	/s/=.*\$/= $RunUser/g
w
q
EOF
    fi
}

#------------------------------------------------------------------------
#  Update inetd service entry
#  This just adds/replaces the service entry line

updateInetdEntry() {

    FileName=/etc/inetd.conf
    newLine="gds_db  stream  tcp     nowait.30000      $RunUser $FBBin/fb_inet_server fb_inet_server # Firebird Database Remote Server"
    oldLine=`grep "^gds_db" $FileName`

    replaceLineInFile "$FileName" "$newLine" "$oldLine"
}

#------------------------------------------------------------------------
#  Update xinetd service entry

updateXinetdEntry() {

    InitFile=/etc/xinetd.d/firebird
    cp $FBRootDir/misc/firebird.xinetd $InitFile
    chown root:root $InitFile
    chmod o=rw,go=r $InitFile
    changeXinetdServiceUser
}


#------------------------------------------------------------------------
#  Update inetd service entry 
#  Check to see if we have xinetd installed or plain inetd.  Install differs
#  for each of them.

updateInetdServiceEntry() {

    if [ -d /etc/xinetd.d ] 
      then
        updateXinetdEntry
    else
        updateInetdEntry
    fi

}




#------------------------------------------------------------------------
# Write new password to the @prefix@/SYSDBA.password file

writeNewPassword() {

    NewPasswd=$1

    echo "# Firebird generated password for user SYSDBA is: " > $DBAPasswordFile
    echo "" >> $DBAPasswordFile

    echo "ISC_USER=sysdba" >> $DBAPasswordFile
    echo "ISC_PASSWD=$NewPasswd" >> $DBAPasswordFile
    echo "" >> $DBAPasswordFile

    if [ $NewPasswd = "masterkey" ]
      then
        echo "# for install on `hostname` at time `date`" >> $DBAPasswordFile
        echo "# You should change this password at the earliest oportunity" >> $DBAPasswordFile
      else 
        echo "# generated on `hostname` at time `date`" >> $DBAPasswordFile
    fi
    echo "" >> $DBAPasswordFile
    echo "# Your password can be changed to a more suitable one using the" >> $DBAPasswordFile
    echo "# @prefix@/bin/changeDBAPassword.sh script" >> $DBAPasswordFile

    echo "" >> $DBAPasswordFile
    chmod u=r,go= $DBAPasswordFile


    # Only if we have changed the password from the default do we need
    # to update the entry in the database

    if [ $NewPasswd != "masterkey" ]
      then
        $FBBin/gsec -user sysdba -password masterkey <<EOF
modify sysdba -pw $NewPasswd
EOF
    fi
}


#------------------------------------------------------------------------
#  Generate new sysdba password - this routine is used only in the 
#  rpm file not in the install acript.


generateNewDBAPassword() {

    DBAPasswordFile=$FBRootDir/SYSDBA.password

    # openssl generates random data.
    if [ -f /usr/bin/openssl ]
      then
        # We generate 20 random chars, strip any '/''s and get the first 8
        NewPasswd=`openssl rand -base64 20 | tr -d '/' | cut -c1-8`
    fi

    # mkpasswd is a bit of a hassle, but check to see if it's there
    if [ -z "$NewPasswd" ]
      then
        if [ -f /usr/bin/mkpasswd ]
          then
            NewPasswd=`/usr/bin/mkpasswd -l 8`
        fi
    fi


    # So we failed to generate a new password, so keep the original 
    # installed one.

    if [ -z "$NewPasswd" ]
      then
        NewPasswd="masterkey"
    fi

    writeNewPassword $NewPasswd

}

#------------------------------------------------------------------------
#  Change sysdba password - this routine is interactive and is only 
#  used in the install shell script not the rpm one.


askUserForNewDBAPassword() {

    NewPasswd=""

    while [ -z "$NewPasswd" ]
      do
# If using a generated password
#         DBAPasswordFile=$FBRootDir/SYSDBA.password
#         NewPasswd=`mkpasswd -l 8`
#         echo "Password for SYSDBA on `hostname` is : $NewPasswd" > $DBAPasswordFile
#         chmod ga-rwx $DBAPasswordFile

          AskQuestion "Please enter new password for SYSDBA user: "
          NewPasswd=$Answer
          if [ ! -z "$NewPasswd" ]
            then

             $FBBin/gsec -user sysdba -password masterkey <<EOF
modify sysdba -pw $NewPasswd
EOF
              echo ""
              #writeNewPassword $NewPasswd
          fi
          
      done
}


#------------------------------------------------------------------------
#  Change sysdba password - this routine is interactive and is only 
#  used in the install shell script not the rpm one.

#  On some systems the mkpasswd program doesn't appear and on others
#  there is another mkpasswd which does a different operation.  So if
#  the specific one isn't available then keep the original password.


changeDBAPassword() {

    if [ -z "$InteractiveInstall" ]
      then      
        generateNewDBAPassword      
      else
        askUserForNewDBAPassword
    fi
}


#------------------------------------------------------------------------
#  fixFilePermissions
#  Change the permissions to restrict access to server programs to 
#  firebird group only.  This is MUCH better from a saftey point of 
#  view than installing as root user, even if it requires a little 
#  more work.


fixFilePermissions() {

    # Turn other access off.
    chmod -R o= $FBRootDir


    # Now fix up the mess.

    # fix up directories 
    for i in `find $FBRootDir -print`
    do
        FileName=$i
        if [ -d $FileName ]
        then
            chmod o=rx $FileName
        fi
    done


    cd $FBBin


    # set up the defaults for bin
    for i in `ls`
      do
         chmod ug=rx,o=  $i
    done

    # User can run these programs, they need to talk to server though.
    # and they cannot actually create a database.
     

    chmod a=rx isql 
    chmod a=rx qli
    
    # SUID is still needed for group direct access.  General users
    # cannot run though.
    for i in fb_lock_mgr gds_drop fb_inet_server
    do
        if [ -f $i ]
          then
            chmod ug=rx,o= $i
            chmod ug+s $i
        fi
    done


    cd $FBRootDir

    # Fix lock files
    for i in isc_init1 isc_lock1 isc_event1 
      do
        FileName=$i.`hostname`
        chmod ug=rw,o= $FileName
      done


    chmod ug=rw,o= firebird.log

	chmod u=rw,go=r aliases.conf
	chmod u=rw,go=r firebird.conf
    chmod a=r firebird.msg
    chmod a=r README
    chmod a=r help/help.fdb
    chmod ug=rw,o= security.fdb

    # Set a default of read all files in includes

	for i in include lib UDF intl misc
	  do
	      
        cd $i
        for j in `ls`
          do
            chmod a=r  $j
          done

        cd ..
      done

    # fix up permissions for loadable plugins
    chmod ug=rx,o= intl/fbintl UDF/fbudf.so UDF/ib_udf.so
    
    # Set a default of read all files in examples

    cd examples

    for i in `ls`
      do
         chmod a=r  $i
    done

    # make examples db's writable by group
    for i in `find . -name '*.fdb' -print`
      do
        chmod ug=rw,o= $i
      done

}


#------------------------------------------------------------------------
#  fixFilePermissionsForRoot
#  This sets the file permissions up to what you need if you are
#  running the server as root user.  I hope to remove this mode
#  of running before the next version, since it's security level
#  is absolutely woeful.
#  
#  The main difference between fixFIlePermissionsRoot and fixFilePermissions
#  is that non root assumes you must be a member of the group to access most 
#  of the files, wheras root user install gives world writable permission to
#  the installation.


fixFilePermissionsRoot() {

    # Turn other access off.
    chmod -R o= $FBRootDir

    # Now fix up the mess.

    # fix up directories 
    for i in `find $FBRootDir -print`
    do
        FileName=$i
        if [ -d $FileName ]
        then
            chmod o=rx $FileName
        fi
    done


    cd $FBBin


    # set up the defaults for bin
    for i in `ls`
      do
         chmod o=rx  $i
    done

    
    # SUID is still needed for group direct access.  General users
    # cannot run though.
    for i in fb_lock_mgr gds_drop fb_inet_server
    do
      if [ -f $i ]
        then
          chmod ug+s $i
      fi
    done


    cd $FBRootDir

    # Set a default of read all files in includes

	for i in include lib UDF intl misc
	  do
	      
        cd $i
        for j in `ls`
          do
            chmod a=r  $j
          done

        cd ..
      done

    # Fix lock files
    for i in isc_init1 isc_lock1 isc_event1 
      do
        FileName=$i.`hostname`
        chmod a=rw $FileName
      done


    chmod a=rw firebird.log

	chmod a=r aliases.conf
	chmod a=r firebird.conf
    chmod a=r firebird.msg
    chmod a=r README
    chmod a=r help/help.fdb
    chmod a=rw security.fdb

    # fix up permissions for loadable plugins
    chmod a=rx intl/fbintl UDF/fbudf.so UDF/ib_udf.so

    # Set a default of read all files in examples

    cd examples

    for i in `ls`
      do
         chmod a=r  $i
    done

    # make examples db's writable by group
    for i in `find . -name '*.gdb' -print`
      do
        chmod a=rw $i
      done


}

#------------------------------------------------------------------------
# UpdateHostsDotEquivFile
# The /etc/hosts.equiv file is needed to allow local access for super server
# from processes on the machine to port 3050 on the local machine.
# The two host names that are needed there are 
# localhost.localdomain and whatever hostname returns.

UpdateHostsDotEquivFile() {

    hostEquivFile=/etc/hosts.equiv

    if [ ! -f $hostEquivFile ]
      then
        touch $hostEquivFile
        chown root:root $hostEquivFile
        chmod u=rw,go=r $hostEquivFile
    fi

    newLine="localhost.localdomain"
    oldLine=`grep "$newLine" $hostEquivFile`
    replaceLineInFile "$hostEquivFile" "$newLine" "$oldLine"

    newLine="`hostname`"
    oldLine=`grep "$newLine" $hostEquivFile`
    replaceLineInFile "$hostEquivFile" "$newLine" "$oldLine"
    
}


#------------------------------------------------------------------------
#  buildUninstallFile
#  This will work only for the .tar.gz install and it builds an
#  uninstall shell script.  The RPM system takes care of it's own.


buildUninstallFile() {

    cd $origDir

    if [ ! -f manifest.txt ]  # Only do this if we are a .tar.gz install
      then
        return
    fi

    cp manifest.txt $FBRootDir/misc

    cp -r scripts $FBRootDir/misc/
    cp scripts/tarMainUninstall.sh $FBRootDir/bin/uninstall.sh
}

#------------------------------------------------------------------------
#  resetXinitdServer
#  Check for both inetd and xinetd, only one will actually be running.
#  depending upon your system.

resetInetdServer() {

    if [ -f /var/run/inetd.pid ]
      then
        kill -HUP `cat /var/run/inetd.pid`
    fi

    if [ -f /var/run/xinetd.pid ]
      then
        kill -USR2 `cat /var/run/xinetd.pid`
    fi
}


#------------------------------------------------------------------------
#  createLinksForBackCompatibility
#  Create links for back compatibility to InterBase and Firebird1.0 
#  linked systems.

createLinksForBackCompatibility() {

    # These two links are required for compatibility with existing ib programs
    # If the program had been linked with libgds.so then this link is required
    # to ensure it loads the fb equivalent.  Eventually these should be 
    # optional and in a seperate rpm install.  MOD 7-Nov-2002.

    # There are two options for classic for libgds.so :
    #  1) The multithreaded client only libfbclient.so
    #  or
    #  2) The direct connect (but not threadsafe) classic libfbembeded.so
    #
    # libfbclient should be the prefered option unless you need to connect
    # in an embedded mode.  However the default for install of classic 
    # is left for libgds.so -> libfbembed.so since that is compatible to 
    # the existing behaviour of previous installs. (There is also a 
    # script installed to allow the user to change the option) MOD 23-Dec-2003


    #newLibrary=$FBRootDir/lib/libfbclient.so
    newLibrary=$FBRootDir/lib/libfbembed.so

    # Remove if only a link
    if [ -L @libdir@/libgds.so ]
      then
        rm -f @libdir@/libgds.so
    fi

    if [ ! -e @libdir@/libgds.so ]
      then
        ln -s $newLibrary @libdir@/libgds.so
    fi

    # Remove if only a link
    if [ -L @libdir@/libgds.so.0 ]
      then
        rm -f @libdir@/libgds.so.0
    fi

    if [ ! -e @libdir@/libgds.so.0 ]
      then
        ln -s $newLibrary @libdir@/libgds.so.0
    fi


}


    

#= Main Post ===============================================================



    # Detect which linux distro we are installing on
    detectDistro

    # Make sure the links are in place 
    if  [ -z "$FirebirdInstallPrefix" ]
       then
        FirebirdInstallPrefix=@prefix@
    fi

    origDir=`pwd`

    FBRootDir=$FirebirdInstallPrefix
    FBBin=$FBRootDir/bin
#    RunUser=root
    RunUser=firebird


    # Update /etc/services

    # The \n is needed, some /etc/services files are missing a trailing
    # line feed - MOD 7-Nov-2002
    FileName=/etc/services
    newLine="gds_db          3050/tcp  # Firebird SQL Database Remote Protocol"
    oldLine=`grep "^gds_db" $FileName`
    if [ -z "$oldLine" ]
      then
        echo "" >> $FileName
        echo $newLine >> $FileName
        echo "" >> $FileName
    #    replaceLineInFile "$FileName" "$newLine" "$oldLine"
    fi

    UpdateHostsDotEquivFile

    # add Firebird user
    if [ $RunUser = "firebird" ]
      then
        addFirebirdUser
    fi


    # Create Lock files
    cd $FBRootDir

    for i in isc_init1 isc_lock1 isc_event1 
      do
        FileName=$i.`hostname`
        touch $FileName
      done

    # Create log
    touch firebird.log


    # Update ownership and SUID bits for programs.
    chown -R $RunUser.$RunUser $FBRootDir

    if [ "$RunUser" = "root" ]
      then
        fixFilePermissionsRoot
    else
        fixFilePermissions
    fi

    createLinksForBackCompatibility

    buildUninstallFile

    # Update the /etc/inetd.conf or xinetd entry
    updateInetdServiceEntry


    # Get inetd to reread new init files.
    resetInetdServer


    cd $FBRootDir
    
    # Change sysdba password
    changeDBAPassword
    #keepOrigDBAPassword



