#! /bin/sh
#set -xv
#=========================================================================
# Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved..
#
# Name - machine_grp.sh
#
# Purpose - 
#
# Note:  This script relies on other supporting scripts being in the
#        $GEMSTONE/bin
#
# $Id: machine_grp.sh,v 1.8 2008-01-09 22:50:52 stever Exp $
#
#=========================================================================

if [ "a$GEMSTONE" = "a" ]; then
  echo "ERROR: GemStone scripts require a GEMSTONE environment variable."
  echo "       Please set it to the directory where GemStone resides."
  exit 1
fi

# make sure of minimum path
PATH=:/bin:/usr/bin:/usr/ucb:/usr/etc:$PATH; export PATH

comid="machine_grp"             #   this script's name

. $GEMSTONE/bin/misc.sh


list444=/tmp/machine_grp$$_444
list555=/tmp/machine_grp$$_555
#defaultErrorControl
trap 'echo "${comid}[Error]:   ^C termination."; rm -f $list444 $list555; exit 1' 2     # SIGINT
trap 'echo "${comid}[Error]:   kill termination."; rm -f $list444 $list555; exit 1' 15     # SIGTERM
trap '' 1                                     # SIGHUP

usageStr="machine_grp.syntax:\
machine_grp <groupname> [-oowner] [-v] [-h]\n\n\
      groupname       - the name of the group that will own GemStone files.\n\
      -oowner         - (optional) name of the user who will own the GemStone\n\
                        files.\n\
      -v              - (optional) verbose output\n\n\
This script (1) creates any missing GemStone installation subdirectories,\n\
            (2) sets the group on all GemStone directories and files,\n\
            (3) sets default protection on all GemStone directories and files,\n\
        and (4) optionally sets the username on all GemStone directories and\n\
                files.\n\
You should login as the superuser on a machine\ that has privilege to execute\n\
mkdir, chgrp, chmod, and chown on the newly-installed files.\n"


giveHelp "$1" "$usageStr"

# maintanence symbols - see above 
groupname=""                            #   groupname is required argument
username=""                             #   optional username 
verbose=""

myusername="$USER"
if [ "$myusername" = "" ]; then
  myusername=`whoami 2>/dev/null`
fi
if [ "$myusername" = "" ]; then
  myusername=$LOGNAME
fi
if [ "$myusername" = "" ]; then
  myusername="user with id $UID"
fi

dir_prot="777"                          #   protection of $GEMSTONE/data
install_prot="755"                      #   <machine>_locXX, <machine>_grpXX

# banner this script
# say shell.banner $comid "`/bin/uname -n`" "`date`"
hName=`/bin/uname -n`
theDate=`date`
echo "${comid}[Info]:    $hName - $theDate "

machineGrpSyntax() {
        echo "Usage:"
        echo "machine_grp <groupname> [-oowner] [-v] [-h]"
        echo ""
        echo "      groupname       - the name of the group that will own GemStone files."
        echo "      -oowner         - (optional) name of the user who will own the GemStone"
        echo "                        files."
        echo "      -v              - (optional) verbose output"
        echo "This script (1) creates any missing GemStone installation subdirectories,"
        echo "            (2) sets the group on all GemStone directories and files,"
        echo "            (3) sets default protection on all GemStone directories and files,"
        echo "        and (4) optionally sets the username on all GemStone directories and"
        echo "                files."
        echo "You should login as the superuser on a machine that has privilege to execute"
        echo "mkdir, chgrp, chmod, and chown on the newly-installed files."
}

badSetugid() {
    # say  machine_grp.badsetugid , machine_grp.badsetgid 
    echo "machine_grp[Error]:    There seems to be a problem with setting the setuid"
    echo "           bit on files in this filesystem.  This could be an NFS mount"
    echo "           option or an OS problem.  You should investigate this."
}


# make sure of where we are
cd $GEMSTONE

# Process switches
getSwitches o:v "$*"
set -- $switches
username=$USER
while [ "x$1" != "x" ]
do
  switch="$1"
  shift
  case "$switch" in
    -o) username="$1" ; shift ;;
    --)  # Non-switch arguments
	if [ "x$1" != "x" ]; then
	   groupname="$1"
	   shift
	fi
	if [ "x$1" != "x" ]; then
	  # say shell.toomany $comid "$1"
          echo "${comid}[Error]:   Too many non-switch arguments $1 "
          exit 1
	fi
	break
	;;
    -v) verbose="yes" ;;
    *)  # say shell.peculiar $comid "$switch"
        echo "${comid}[Error]:    Peculiar argument  $switch  "
	# say machine_grp.syntax
	machineGrpSyntax
        exit 1
	;;
  esac
done
if [ "$groupname" = "" ]; then
  # say machine_grp.syntax
  machineGrpSyntax
  exit 1
fi

# you must be root
myEffectiveUid=`$GEMSTONE/install/getid -neu`
if [ $myEffectiveUid -ne 0 ]; then
  # might be a problem to do chown, for instance
  # say machine_grp.root
  echo "machine_grp[Warning]:  You may want to login as "root" to execute this script."
fi

# try 1st chmod and check it!
set_status="0"
# chmod $dir_prot . 1>/dev/null 2>/dev/null
chmod $dir_prot .
if [ "$?" != "0" ]; then
  # trouble with chmod
  # say machine_grp.chmod . $dir_prot
  echo "machine_grp[Error]:    cannot chmod to $dir_prot the file  .   "
  set_status="1"
fi

# try 1st chgrp and check it!  
# chgrp $groupname . 1>/dev/null 2>/dev/null
chgrp $groupname .
if [ "$?" != "0" ]; then
  # trouble with chgrp
  # say machine_grp.chgrp . $groupname
  echo "machine_grp[Error]:    cannot chgrp to $groupname the file  . "
  set_status="1"
fi

# try 1st chown and check it!
if [ "$username" != "" ]; then
#  chown $username . 1>/dev/null 2>/dev/null
  chown $username .
  if [ "$?" != "0" ]; then
    # trouble with chown
    # say machine_grp.chown . $username
    echo "machine_grp[Error]:    cannot chown to $username the file  .  "
    set_status="1"
  fi
fi

# verify that Setuid will work on this system.  There are a couple reasons
# why it may not.  One big one is if this directory is on an NFS mount
# that does not allow setuid operation. The verification will be
# "non-destruction".

oriRealUser=`$GEMSTONE/install/getid -ru`
oriRealGrp=`$GEMSTONE/install/getid -rg`
oriEffUser=`$GEMSTONE/install/getid -eu`
oriEffGrp=`$GEMSTONE/install/getid -eg`
if [ \( $oriRealUser != $oriEffUser \) \
    -o \( $oriRealGrp != $oriEffGrp \) ]; then
  # say machine_grp.badgetid "$getidout"
  echo "machine_grp[Error]:    INTERNAL ERROR: output of getid is bad:  $getidout  "
  set_status="1"
fi

if [ ! -f $GEMSTONE/install/getid ]; then
  echo "getid is not in $GEMSTONE/install.  Where is it?"
  # say machine_grp.skipcheck
  echo "machine_grp[Warning]:  Skipping check of setuid"
elif [ "`$GEMSTONE/install/getid -eu`" = "$username" \
     -o "`$GEMSTONE/install/getid -eg`" = "$groupname" ]; then
  echo "real and effective are equal, can't verify setuid"
  # say machine_grp.skipcheck
  echo "machine_grp[Warning]:  Skipping check of setuid"
else
  cp $GEMSTONE/install/getid ./getidx	# make a copy of getid

  # Does the script see who I am?  We'll just test the efficacy of getid
  # in returning the correct id.
  # There are two possible cases.  In the first, the user is logged in 
  # either as root or "him/herself".  In such a case, the $USER id will
  # be the same as that returned by getid.  In the second case, the user
  # has 'su'-ed to being root and the $USER varaible no longer reflects
  # the true user id (it will be the user id that initiated the 'su'.
  # Depending on the case, we must look at the test from different angles.

  if [ \( "$USER" != "root" \) ]; then
    if [ \( $oriRealUser != "root" \) -o \( $oriEffUser != "root" \) ]; then
      # say machine_grp.notroot "$oriRealUser" "$oriEffUser" "$USER"
      echo "machine_grp[Error]:    WARNING: you are not root:"
      echo "                       ruser=$oriRealUser euser=$oriEffUser USER=$USER "
      set_status="1"
    fi
  else
    if [ \( $oriRealUser != "$USER" \) -o \( $oriEffUser != "$USER" \) ]; then
      # say machine_grp.notroot "$oriRealUser" "$oriEffUser" "$USER"
      echo "machine_grp[Error]:    WARNING: you are not root:"
      echo "                       ruser=$oriRealUser euser=$oriEffUser USER=$USER "
      set_status="1"
    fi
  fi
      
  # Okay, change the owner/group of getid and give it setuid/gid permission
  chgrp $groupname "./getidx" 1>/dev/null 2>/dev/null
  if [ "$?" != "0" ]; then
    # trouble with chgrp
    # say machine_grp.chgrp "getid copy" $groupname
    echo "machine_grp[Error]:    cannot chgrp to $groupname the file  ./getidx  "
    set_status="1"
  fi

  chown $username "./getidx" 1>/dev/null 2>/dev/null
  if [ "$?" != "0" ]; then
    # trouble with chown
    # say machine_grp.chown "getid copy" $username
    echo "machine_grp[Error]:    cannot chown to $username the file  ./getidx   "
    set_status="1"
  fi

  chmod 6755 "./getidx" 1>/dev/null 2>/dev/null
  if [ "$?" != "0" ]; then
    # trouble with chmod
    # say machine_grp.chmod "getid copy" $dir_prot
    echo "machine_grp[Error]:    cannot chmod to 6755  the file   ./getidx   "
    set_status="1"
  fi

  # Execute getid again.  We'll then parse out the real & effective users
  newRealUser=`./getidx -ru`
  newRealGrp=`./getidx -rg`
  newEffUser=`./getidx -eu`
  newEffGrp=`./getidx -eg`

  if [ $oriRealUser != $newRealUser ]; then
    # Its still me, why does getid not think so...
    # badsetugid, badsetuid
    badSetugid
    echo "           In particular, the real user id should not change between"
    echo "           setuid and non-setuid executions."
    set_status="2"
  fi
  if [ $oriRealGrp != $newRealGrp ]; then
    # Its still me, why does getid not think so...
    # badsetugid, badsetgid
    badSetugid
    echo "           In particular, the real group id should not change between"
    echo "           setgid and non-setgid executions."
    set_status="2"
  fi
  if [ $oriEffUser = $newEffUser ]; then
    # Effective shouldn't be equal.  I'm different from owner
    # badsetugid, nosetuid
    badSetugid
    echo "           In particular, the effective user id should change between"
    echo "           setuid and non-setuid executions."
    set_status="2"
  fi
  if [ $oriEffGrp = $newEffGrp ]; then
    # Effective shouldn't be equal.  I'm different from owner
    # badsetugid, nosetgid
    badSetugid
    echo "           In particular, the effective group id should change between"
    echo "           setgid and non-setgid executions."
    set_status="2"
  fi
  if [ $newEffUser != $username ]; then
    # Effective user should be $username.
    # badsetugid, nosetuid2
    badSetugid
    echo "           In particular, the effective user id did not change to"
    echo "           $username   during setuid executions."
    set_status="2"
  fi
  if [ $newEffGrp != $groupname ]; then
    # Effective group should be $groupname
    # badsetugid, nosetgid2
    badSetugid
    echo "           In particular, the effective group id did not change to"
    echo "           $groupname    during setgid executions."
    set_status="2"
  fi

  # Clean up our mess of files and variables
  unset newRealUser newRealGrp newEffUser newEffGrp
  unset oriRealUser oriRealGrp oriEffUser oriEffGrp
  rm ./getidx
fi	# ! test -e $GEMSTONE/install/getid

if [ $set_status != "0" ]; then
  # Some kind of error occurred.  Based on the value of $set_status, we
  #  take differing actions
  if [ "$set_status" = "1" ]; then
    # Some type of error occurred that is likely one of privelege problems
    # bail out, ask user to try again as root
    # say machine_grp.nopriv $GEMSTONE
    echo "machine_grp[Error]:    please login as "root" on a machine with privilege"
    echo "                       to modify directory  $GEMSTONE "

    exit 1
  elif [ $set_status = "2" ] ; then
    # It appears that setuid privelege are not work for one reason or another.
    #  The user must be informed of the problem and likely causes.  He/She will
    #  then be asked if they wish to continue with privelege changes and fix
    #  the setuid problem themselves, or to forget doing privilege changes
    #  all together.
    # say machine_grp.warnsetuid
    echo " It appears that setuid is not operational.  This could be caused by an"
    echo " NFS mount with the 'nosetuid' option specified. It could also be a bug in"
    echo " your operating system.  You have one of two choices.  You can continue"
    echo " with the file protection operations.  In this case, you will have to fix"
    echo " the setuid problem later before GemStone will work properly.  Otherwise,"
    echo " you can choose not to perform the file protection operations and use some"
    echo " other method to give multiple users access to GemStone.  Note that"
    echo " installgs can be run again if you wish to install file protection later."
    echo ""
    echo "Do you wish to continue with the file protection operations? [y]"

    read fpoAnswer
    if [ \( "$fpoAnswer" = "no" \) -o \( "$fpoAnswer" = "No" \) \
	-o \( "$fpoAnswer" = "n" \) -o \( "$fpoAnswer" = "NO" \) ]; then
       # say machine_grp.skipsetuid
       echo "Skipping file protection operations."
       exit 1
    fi
  fi      # $set_status = 1
fi        # $set_status != 0

if [ ! -f $GEMSTONE/PACKING ]; then
  # say shell.needfil 
  echo "${comid}[Error]:   cannot find file  $GEMSTONE/PACKING"
  exit 1
fi

#set -xv

# bug10612:  make sure directories get their protections set
allDirs="`find . -type d -print`"
echo $allDirs | xargs chgrp $groupname
if [ $? -ne 0 ]; then
  # say machine_grp.chgrp $groupname "some directories"
  echo  "machine_grp[Error]:    cannot chgrp to $groupname all of the subdirectories "

fi
echo $allDirs | xargs chmod 555
if [ $? -ne 0 ]; then
  # say machine_grp.chmod 555 "some directories"
  echo "machine_grp[Error]:    cannot chmod to 555   all of the subdirectories "
fi
# here we add $GEMSTONE_LOCKBASE and its subdirectories (assuming correct perms were
# set previously) so that we can chown and chgrp them
allDirs="$allDirs $GEMSTONE_LOCKBASE $GEMSTONE_LOCKDIR $GEMSTONE_LOGDIR"
if [ "$username" != "" ]; then
  echo $allDirs | xargs chown $username
  if [ $? -ne 0 ]; then
    # say machine_grp.chown $username "some directories"
    echo "machine_grp[Error]:    cannot chown to $username  all of the subdirectories"
  fi
fi

rm -f $list444 $list555

cat  $GEMSTONE/PACKING | \
    while read encodedname filetype junk
do
  # while more file, prot, subdir info
  # Expand buried environment variables...
  filename=`eval echo "$encodedname"`

  if [ "x$filename" = "x" ]; then	# skip empty line
    continue
  fi

  case $filename in
  \!*) 
    continue ;;   # comment

  *)
    if [ "x$verbose" != "x" ]; then
      # say machine_grp.sayfil $filename
      echo "File $filename ... "
    fi
    if [ ! -f ${filename} ]; then
      # file is missing!
      # say machine_grp.nofil $filename
      echo "machine_grp[Warning]:  file  $filename   is missing."
      continue
    fi
    ;;
  esac

  case $filetype in
  obj)  echo $filename >> $list444 ;;
  exe)  echo $filename >> $list555 ;;
  lib)  echo $filename >> $list444 ;;
  dll)  echo $filename >> $list555 ;;
  text) echo $filename >> $list444 ;;
  bin)  echo $filename >> $list444 ;;
  dir)  echo $filename >> $list555 ;;
  script) echo $filename >> $list555 ;;
  *) # say machine_grp.weirdtype "$filetype"
     echo "INTERNAL ERROR:  unknown filetype $filetype in packing list."
     exit 1
     ;;
  esac
done

# set -xv

# say machine_grp.start
echo "machine_grp[Info]:     setting file characteristics..."
# now take care of GemStone file(s)...

# xargs on this machine since chgrp/chown is so slowwwww on some machines
cat $list444 $list555 | xargs chgrp $groupname 
if [ $? -ne 0 ]; then
  # say machine_grp.chgrp $groupname "some files"
  echo "machine_grp[Error]:    cannot chgrp to $groupname  some files"
fi
echo $GEMSTONE_LOCKBASE $GEMSTONE_LOCKDIR $GEMSTONE_LOGDIR | xargs chgrp $groupname
if [ $? -ne 0 ]; then
  echo "mchine_grp[Error]:    cannot chgrp to $groupname $GEMSTONE_LOCKBASE and "
  echo "                      subdirectories"
fi
cat $list444 | xargs chmod 444
if [ $? -ne 0 ]; then
  # say machine_grp.chmod 444 "some files"
  echo "machine_grp[Error]:    cannot chmod 444   some files"
fi
cat $list555 | xargs chmod 555
if [ $? -ne 0 ]; then
  # say machine_grp.chmod 555 "some files"
  echo "machine_grp[Error]:    cannot chmod 555   some files"
fi
if [ "$username" != "" ]; then
  cat $list444 $list555 | xargs chown $username
  if [ $? -ne 0 ]; then
    # say machine_grp.chown $username "some files"
    echo "machine_grp[Error]:    cannot chown $username   some files"
  fi
fi
rm -f $list444 $list555

# We need to change the permission bits on the 'whatis' database as well
#  as ownership.  Problem is, we don't know what the database is called.
#  Its either windex (seen on Sun machines) or whatis (gnu, and others?)
#  If either of the two exists, perform the necessary changes.  Other-
#  wise, skip the whole deal.
if [ -f $GEMSTONE/doc/whatis ]; then
  mandb=$GEMSTONE/doc/whatis
elif [ -f $GEMSTONE/doc/windex ]; then
  mandb=$GEMSTONE/doc/windex
else
  mandb=""
fi

if [ "x$mandb" != "x" ]; then
  chgrp $groupname $mandb
  if [ $? -ne 0 ]; then
    # say machine_grp.chgrp $groupname $mandb
    echo "machine_grp[Error]:    cannot chgrp $groupname $mandb "
  fi
  chmod 444 $mandb
  if [ $? -ne 0 ]; then
    # say machine_grp.chmod 444 $mandb
    echo "machine_grp[Error]:    cannot chmod 444  $mandb "
  fi
  if [ "$username" != "" ]; then
    chown $username $mandb
    if [ $? -ne 0 ]; then
      # say machine_grp.chown $username $mandb
      echo "machine_grp[Error]:    cannot chown $username  $mandb "
    fi
  fi
fi

# We also need to change the permissions of any files/directories that
#  were created during the "man database" build.  On SVR5 machines, this
#  could entail building 'cat' directories.
cd $GEMSTONE/doc
docFiles="`find . -print`"
echo $docFiles | xargs chgrp $groupname
if [ $? -ne 0 ]; then
  # say machine_grp.chgrp $groupname $GEMSTONE/doc
  echo "machine_grp[Error]:    cannot chgrp $groupname $GEMSTONE/doc "
fi
if [ "$username" != "" ]; then
  echo $docFiles | xargs chown $username
  if [ $? -ne 0 ]; then
    # say machine_grp.chown $username $GEMSTONE/doc
    echo "machine_grp[Error]:    cannot chown $username $GEMSTONE/doc "
  fi
fi

# We done altering things, so make the directory unwritable by 'me' again.
echo $docFiles | xargs chmod u-w
if [ $? -ne 0 ]; then
  # say machine_grp.chmod "u-w" $GEMSTONE/doc
  echo "machine_grp[Error]:    cannot chmod u-w  $GEMSTONE/doc "
fi

# echo "$comid[Info]:     completed - `date`" # all done 
exit 0 
