#! /bin/sh
##################################################################
# This script makes the apt cache directory (by default
# /var/cache/apt) and apt repository writable for a regular user, so it
# will not be required to run aptate as root.  It will do so by
# creating a special group for aptate (default group is apt).  As this 
# is only needed on the apt server this script should NOT be run on a 
# client system (except when the client is located on the server as well).
# The system settings are only modified after your confirmation.
# Run aptatemod after aptate has made 1 run as root, all necessary
# directories will be present and can be modified by aptatemod.
#
# As aptate can be instructed to download rpm packages via a network
# it is strongly adviced to run aptate from a regular user account.
# 
# File:           $RCSfile: aptatemod.in,v $
# Revision:       $Revision: 1.22 $
# Last change:    $Date: 2002/07/12 15:41:48 $
# Last change by: $Author: corsepiu $
#
# Send suggestions to: apt4rpm-devel@lists.sourceforge.net
# Homepage: http://apt4rpm.sourceforge.net
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program 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 General Public License for more details.
#
# For a copy of the GNU General Public License, visit
# http://www.gnu.org or write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##################################################################

#########################
###### FUNCTIONS ########
#########################
 
function usage()
################
{
   echo "$SHORTHELP"
   echo
   echo "$PRGNAME should be used to prepare the apt cache and repository"
   echo "environment for usage of aptate by a regular user."
   echo
   echo "  -g, --group <group>"
   echo "         Group to be added to the system (default: apt)."
   echo
   echo "  -h, --help"
   echo "         Short help."
   echo
   echo "  -H, --Help"
   echo "         Extended (this) help."
   echo
   echo "  -i, --info"
   echo "         Displays the group members for the group specified by -g." 
   echo
   echo "  -I, --Info"
   echo "         The extended version of -i.  The apt cache and repository"
   echo "         directory and group characteristics are listed as well."
   echo
   echo "  -q, --quiet"
   echo "         Progress messages are being suppressed."
   echo
   echo "  -u, --user <user>"
   echo "         User (default \$LOGNAME) to be added to the group specified by -g"
   echo "         (defaults to group apt if -g is not specified)."
   echo
   echo "  -v, --version"
   echo "         $PRGNAME version."
   echo
   echo "  -y, --force-yes"
   echo "         Answer "yes" when the permissions and group characteristics will"
   echo "         be altered.  Needed when $PRGNAME will be run from a cronjob."
   echo
   echo "Mail suggestions and bug reports to: apt4rpm-devel@lists.sourceforge.net."
   echo "Homepage: http://apt4rpm.sourceforge.net"
   exit
}
 
function upper()
################
{
   echo $1 | tr [a-z] [A-Z]
}

function dispinfo()
###################
{
  local USR

  grep "^$GROUP:" /etc/group >/dev/null; RETVAL=$?
  if [ $RETVAL -eq 0 ]
  then
    USR=$(grep "^$GROUP:" /etc/group | cut -d: -f4)
    echo "The following users are member of group \"$GROUP\"":
    echo "$USR"
  else
    echo "The group \"$GROUP\" has not been configured" >&2
  fi
}

function member_grp()
#####################
{
  local USR=$1

  # find the groups that the user of part of.
  egrep "[:,]${USR},|[:,]${USR}$" /etc/group | 
    cut -d: -f1 | tr "\012" "," | sed s+,$++
}

##################################
########## VARIABLES #############
##################################

PATH=$PATH:/usr/sbin

USER=$LOGNAME
GROUP=apt
DISPINFO=""
FORCEDYES=NO
readonly VERSN="0.64.2"
readonly PRGNAME=$(basename $0)
readonly SHORTHELP="Usage: $PRGNAME [-hHiIv -u <user> -g <group>]"
readonly APTCACHEDIR=/var/cache/apt


#############################
########## MAIN #############
#############################

# Note that we use `"$@"' to let each command-line parameter expand to a
# separate word. The quotes around `$@' are essential!
# We need TEMP as the `eval set --' would nuke the return value of getopt.
TEMP=$(getopt -o g:hHiIqu:vy \
  --long force-yes,group:,help,Help,info,Info,quiet,user:,version \
  -n $PRGNAME -- "$@")

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"

# define output streams
exec 3>&2

while true
do
  case $1 in
  -y|--force-yes) FORCEDYES=YES;;
  -g|--group)     GROUP=$2; shift ;;
  -h|--help)      echo "$SHORTHELP" >&2; exit ;;
  -H|--Help)      usage ;;
  -i|--info)      DISPINFO="NORMAL" ;;
  -I|--Info)      DISPINFO="EXTENDED" ;;
  -q|--quiet)	  exec 3>/dev/null ;;
  -u|--user)      USER=$2;  shift ;;
  -v|--version)   echo "$VERSN"; exit ;;
  --) shift ; break ;;
   *) echo "unknow argument \"$1\""; exit 1 ;;
  esac
  shift
done

if [ "$DISPINFO" = "NORMAL" ]; then
  dispinfo
  exit
fi

# need to get the TOPDIR value (copied from aptate)
unset CONFIG_FOUND
CONFIG_FILES="/etc/apt/aptate.conf $HOME/.aptate/aptate.conf"

for CONFIGFILE in $CONFIG_FILES; do
  if [ -f $CONFIGFILE ]; then
    . $CONFIGFILE
    CONFIG_FOUND="$CONFIG_FOUND $CONFIGFILE"
  fi
done

if [ -z "$CONFIG_FOUND" ]; then
    echo "No config file found!" >&2
    echo "(Searchlist: $CONFIG_FILES)" >&2
else
    for CONFIGFILE in $CONFIG_FOUND; do
       echo "Read config file: \"$CONFIGFILE\"" >&3
    done
fi

if [ "$DISPINFO" = "EXTENDED" ]; then
  dispinfo
  echo
  if [ -d "$APTCACHEDIR" ]; then
    echo "The apt cache directories have the following characteristics:"
    find $APTCACHEDIR -type d | xargs ls -ld | 
      awk '{ printf ("%s  %s  %s  %s\n", $1, $3, $4, $9)}'
  else
    echo "The apt cache directory \"$APTCACHEDIR\" has not been found"
  fi

  echo
  if [ -d "$TOPDIR" ]; then
    echo "The apt/rpm repository directories have the following characteristics:"
    ls -ld $TOPDIR $TOPDIR/apt $TOPDIR/update 2>/dev/null |
      awk '{ printf ("%s  %s  %s  %s\n", $1, $3, $4, $9)}'
  else
    echo "The apt/rpm repository directory \"$TOPDIR\" has not been found"
  fi
  exit
fi

grep "^$GROUP:" /etc/group >/dev/null; RETVAL=$?
if [ $RETVAL -ne 0 ]
then
  # only root can add groups to the system
  if [ $(id -u) -eq 0 ]
  then
    echo -e "Add group \"${GROUP}\" to the system? [Y/n]? \c"
    read ANSWER; ANSWER=$(upper $ANSWER)
    if [ "${ANSWER:=Y}" = "Y" ] || [ "$ANSWER" = "YES" ]; then
      groupadd ${GROUP} 2>/dev/null; RETVAL=$?
      if [ $RETVAL -eq 0 ]; then
        # root must be part of the group
        MEMBERGRP=$(member_grp root)
        usermod -G ${MEMBERGRP},$GROUP root; RETVAL=$?
        if [ ${RETVAL} -eq 0 ]; then
          echo "Added \"root\" to group $GROUP"
        fi
      else
        echo "error while adding group: \"$GROUP\"" >&2
        exit 4
      fi
    else
      # The user does not want to add the group
      exit
    fi
  else
    echo "$PRGNAME needs to be executed as root (consider using: su -c \"<command>\")" >&2
    exit 2
  fi
fi

grep "^$GROUP:" /etc/group | 
   egrep "[:,]${USER},|[:,]${USER}$" >/dev/null; RETVAL=$?

if [ $RETVAL -ne 0 ]
then
  # only root can add users to the group
  if [ $(id -u) -eq 0 ]
  then
    echo -e "Add user \"$USER\" to group \"$GROUP\" [Y/n]? \c"
    read ANSWER; ANSWER=$(upper $ANSWER)
    if [ "${ANSWER:=Y}" = "Y" ] || [ "$ANSWER" = "YES" ]; then
       MEMBERGRP=$(member_grp $USER)
       usermod -G ${MEMBERGRP},$GROUP $USER; RETVAL=$?
       if [ ${RETVAL} -eq 0 ]; then
         echo "Added user $USER to group $GROUP"
       fi
    else
       echo "Take care that the right user is added to group: \"$GROUP\""
       echo "by using e.g. usermod -G $GROUP <user>"
    fi
  else
    echo "$PRGNAME needs to be executed as root (consider using: su -c \"<command>\")" >&2
    exit 2
  fi
fi

if [ "$FORCEDYES" != "YES" ]; then
  echo "The permissions and group characteristics of the:"
  echo "- apt cache directories and files in: \"$APTCACHEDIR/\","
  echo "- rpm repository directories and files in: \"$TOPDIR/\" and"
  echo "- aptate configuration files in \"/etc/apt/\""
  echo "will now be altered.  The group will be made writable for group $GROUP."
  echo -e "Continue [Y/n]? \c"
  
  read ANSWER; ANSWER=$(upper $ANSWER)
fi

if [ "${ANSWER:=Y}" = "Y" ] || [ "$ANSWER" = "YES" ] || [ "$FORCEDYES" = "YES" ]
then

  if [ -d "$TOPDIR" ]
  then
    # only the current user and root can change the file permissions
    if [ -O "$TOPDIR" ] || [ $(id -u) -eq 0 ]
    then
      echo "Altering directory: $TOPDIR" >&3
      [ $(id -u) -eq 0 ] && chown root $TOPDIR
      chgrp $GROUP $TOPDIR
      chmod g+w $TOPDIR
    fi
  else
    echo "Directory $TOPDIR does no exist" >&2
  fi

  if [ $(id -u) -ne 0 ]
  then
    FINDARG="-user $LOGNAME"
  else
    FINDARG=""
  fi

  for DIR in $TOPDIR/update $TOPDIR/apt $APTCACHEDIR
  do
    if [ -d "$DIR" ]
    then
      echo "Altering directories and files in: $DIR" >&3

      for I in $(find $DIR ! -type l $FINDARG | xargs -l100)
      do
        if [ $(id -u) -eq 0 ]
        then
          chown root:$GROUP $I
        else
          chgrp $GROUP $I
        fi
        chmod g+rw,o+r $I
      done
    else
      # the update directory is not essential for the operation of apt
      if [ "$DIR" != "$TOPDIR/update" ]
      then
        echo "$PRGNAME: directory $DIR does no exist" >&2
      fi
    fi
  done
fi

