#!/bin/sh
#
# $Source: /home/alb/afbackup/afbackup-3.5.1pl2/RCS/postinstall,v $
# $Id: postinstall,v 1.1 2004/07/08 20:34:48 alb Exp alb $
#

#
# This script can be used as postinstall, preremove and checkinstall
# script in Solaris-2 packages
#

PASSWDFILE=/etc/passwd
INETDCONF=/etc/inetd.conf
SERVICES=/etc/services
xinetdfile="/etc/xinetd.conf"

TMPFILE=/tmp/inst.afbackup.$$

/bin/rm -f $TMPFILE
if [ -f $TMPFILE ] ; then
  echo "ERROR: tempfile $TMPFILE could not be removed." >&2
  exit 2
fi

PROGNAME=`basename $0`

ps -uxawwww >/dev/null 2>&1
if [ $? -eq 0 ] ; then
  ps -uxawwww 2>&1 | egrep -i 'bad.*syntax.*bogus' >/dev/null
  if [ $? -eq 0 ] ; then
    PSALL="ps uxawwww"
  else
    PSALL="ps -uxawwww"
  fi
else
  ps uxawwww >/dev/null 2>&1
  if [ $? -eq 0 ] ; then
    PSALL="ps uxawwww"
  else
    PSALL="ps -ef"
  fi
fi

use_xinetd=no
if [ -f /etc/xinetd.conf ] ; then
  $PSALL | grep -v grep | grep xinetd >/dev/null 2>&1
  if [ $? -eq 0 ] ; then
    use_xinetd=yes
  fi
fi

resolv(){
  FN="$1"

  if [ ! -f "$FN" ] ; then
    echo "$FN"
    return 0
  fi

  while [ `ls -l "$FN"|cut -c1` = l ] ; do
    SYML=`/bin/ls -l "$FN" | sed 's/^.*->[ 	]*//g'`

    if [ _`echo "$SYML" | cut -c1` != _/ ] ; then
      FN=`dirname "$FN"`/"$SYML"
    else
      FN="$SYML"
    fi
  done

  echo $FN
}

for f in PASSWDFILE INETDCONF SERVICES xinetdfile ; do
  eval $f'=`resolv $'"$f"'`'
done

#
# get xinetd entry stanza
#
get_xinetd_entry(){
  sed -n '/^\([ 	]\)\?service[	 ][	 ]*'"$1"'\([	 ].*\)\?/,/^[	 ]*[}][	 ]*/ p' "$2"
}
#
# get xinetd param value
#
get_xinetd_param(){
  sed -n '/^\([ 	]\)\?service[	 ][	 ]*'"$1"'\([	 ].*\)\?/,/^[	 ]*[}][	 ]*/ p' "$3"|grep '^[ 	]*'"$2"'[ 	]*=[ 	]*'|sed 's/^[^=]*=[	 ]*//g'
}
#
# remove named xinetd entry from data stream
#
strip_xinetd_entry(){
  sed '/^\([ 	]\)\?service[	 ][	 ]*'"$1"'\([	 ].*\)\?/,/^[	 ]*[}][	 ]*/ d' "$2"
}
#
# combine empty lines to one empty line
#
comb_empty_lines(){
  awk 'BEGIN{s = 0;}{if(NF == 0){if(s == 0)print; s = 1}else{s = 0; print}}'
}

#
# check and add services
#
check_add_service(){
  CHECKONLY=no
  if [ _"$1" = _-n ] ; then
    CHECKONLY=yes
    shift
  fi

  SNAME="$1"
  PROT="`echo $2|tr A-Z a-z`"
  PORTNUM=`echo $PROT|cut -d/ -f1`
  TRANSP=`echo $PROT|cut -d/ -f2`

  egrep "^[ 	]*($SNAME[ 	][ 	]*$PROT|[^ 	][^ 	]*[ 	][ 	]*$PROT.*[ 	]$SNAME)([ 	].*)?$" $SERVICES >/dev/null
  if [ $? -eq 0 ] ; then
    for P in `grep "^[ 	]*($SNAME[ 	][ 	]*[1-9][0-9]*/[tT][Cc][Pp]|[^ 	][^ 	]*[ 	][ 	]*[1-9][0-9]*/[tT][Cc][Pp].*[ 	]$SNAME)([ 	].*)?$" $SERVICES|awk '{print $2}'` ; do
      PN=`echo $P|cut -d/ -f1`
      TP=`echo $P|cut -d/ -f2`
      if [ "$TP" = "$TRANSP" -a "$PN" != "$PORTNUM" ] ; then
	echo "ERROR: Services entry exists with wrong port specification." >&2
	exit 3
      fi
    done

    return 0
  fi

  if [ $CHECKONLY = yes ] ; then
    return 0
  fi

  awk '{print $2}' $SERVICES | egrep -i '^'"$PROT"'$' >/dev/null
  if [ $? -eq 0 ] ; then
    SERVLINE=`egrep '^[ 	]*[^ 	][^ 	]*[ 	][ 	]*'"$PORTNUM/"'[tT][Cc][Pp]([ 	].*)?$' $SERVICES`
    SERVLINENO=`egrep -n '^[ 	]*[^ 	][^ 	]*[ 	][ 	]*'"$PORTNUM/"'[tT][Cc][Pp]([ 	].*)?$' $SERVICES | sed 's/:.*$//g'`
    COMMENT=`echo "$SERVLINE"|grep '#'|sed 's/^[^#]*#/	#/g'`
    THEBEEF=`echo "$SERVLINE"|sed 's/[ 	]*#.*$//g'`
    TMPFILE=/etc/services_add_tmp.$$
    /bin/rm -f $TMPFILE
    if [ -f $TMPFILE ] ; then
      echo "ERROR: Cannot remove file $TMPFILE" >&2
      exit 14
    fi
    cp $SERVICES $TMPFILE
    if [ $? -ne 0 ] ; then
      echo "ERROR: Cannot make copy of file $SERVICES" >&2
      exit 13
    fi
    awk '{if(NR == '"$SERVLINENO"') printf "%s '"$SNAME"'%s\n","'"$THEBEEF"'","'"$COMMENT"'"; else print $0}' $SERVICES > $TMPFILE
    NDIFFS1=`diff $SERVICES $TMPFILE|grep '^< '|wc -l`
    NDIFFS2=`diff $SERVICES $TMPFILE|grep '^> '|wc -l`
    if [ $NDIFFS1 -ne 1 -o $NDIFFS2 -ne 1 ] ; then
      echo "ERROR: Cannot modify $SERVICES correctly" >&2
      /bin/rm -f $TMPFILE
      exit 15
    fi

    /bin/mv $TMPFILE $SERVICES
    return 0
  fi

  echo "$SNAME	$PROT" >> $SERVICES
}

#
# check and remove services
#
check_rm_service(){
  SNAME="$1"
  PROT="`echo $2|tr A-Z a-z`"
  PORTNUM=`echo $PROT|cut -d/ -f1`

  egrep "^[ 	]*($SNAME[ 	][ 	]*$PROT|[^ 	][^ 	]*[ 	][ 	]*$PROT.*[ 	]$SNAME)([ 	].*)?$" $SERVICES >/dev/null
  if [ $? -ne 0 ] ; then
    return 0
  fi

  egrep -v "^[ 	]*($SNAME[ 	][ 	]*$PROT|[^ 	][^ 	]*[ 	][ 	]*$PROT.*[ 	]$SNAME)([ 	].*)?$" $SERVICES > $SERVICES.new.$$
  N1=`diff $SERVICES $SERVICES.new.$$ | grep '^[<>]' | wc -l`
  N2=`diff $SERVICES $SERVICES.new.$$ | grep -v '^[<>]' | wc -l`
  if [ $N1 -ne 1 -o $N2 -ne 1 ] ; then
    echo "ERROR: Removing entry from $SERVICES failed." >&2
    exit 11
  fi

  /bin/mv $SERVICES.new.$$ $SERVICES
}

#
# check and add user
#
check_add_user(){
  CHECKONLY=no
  if [ _"$1" = _-n ] ; then
    CHECKONLY=yes
    shift
  fi

  USERNAME="$1"
  USERID="$2"
  GROUPID="$3"

  grep "^$USERNAME:[^:]*:$USERID:" $PASSWDFILE >/dev/null
  if [ $? -eq 0 ] ; then
    return 0
  fi

  grep "^$USERNAME:" $PASSWDFILE >/dev/null
  if [ $? -eq 0 ] ; then
    UID=`grep "^$USERNAME:" $PASSWDFILE|cut -d: -f3`
    echo "ERROR: User entry exists with wrong UID $UID." >&2
    exit 6
  fi

  grep "^[^:]*:[^:]*:$USERID:" $PASSWDFILE >/dev/null
  if [ $? -eq 0 ] ; then
    U=`grep "^[^:]*:[^:]*:$USERID:" $PASSWDFILE|cut -d: -f1`
    echo "ERROR: User entry with UID $USERID exists: $U." >&2
    exit 7
  fi

  if [ $CHECKONLY = yes ] ; then
    return 0
  fi

  NEW_ENTRY="$USERNAME:*:$USERID:$GROUPID:Backup Server:/usr/local/afbackup/server:"

  if [ `grep '^+' $PASSWDFILE|wc -l` -gt 0 ] ; then
    awk 'BEGIN{p=1}{if($1 ~ /^[+]/){if(p) print ne; p=0} print}' "ne=$NEW_ENTRY" $PASSWDFILE > $PASSWDFILE.new.$$
    /bin/rm -f $TMPFILE
    N1=`diff $PASSWDFILE $PASSWDFILE.new.$$ | grep '^[<>]' | wc -l`
    N2=`diff $PASSWDFILE $PASSWDFILE.new.$$ | grep -v '^[<>]' | wc -l`
    if [ $N1 -ne 1 -o $N2 -ne 1 ] ; then
	echo "ERROR: Removing entry from $PASSWDFILE failed." >&2
	exit 12
    fi
    /bin/mv $PASSWDFILE.new.$$ $PASSWDFILE
    return $?
  fi

  echo "$NEW_ENTRY" >> $PASSWDFILE
}

#
# check and remove user
#
check_rm_user(){
  USERNAME="$1"
  USERID="$2"

  grep "^$USERNAME:[^:]*:$USERID:" $PASSWDFILE >/dev/null
  if [ $? -ne 0 ] ; then
    return 0
  fi

  grep -v "^$USERNAME:[^:]*:$USERID:" $PASSWDFILE > $PASSWDFILE.new.$$
  N1=`diff $PASSWDFILE $PASSWDFILE.new.$$ | grep '^[<>]' | wc -l`
  N2=`diff $PASSWDFILE $PASSWDFILE.new.$$ | grep -v '^[<>]' | wc -l`
  if [ $N1 -ne 1 -o $N2 -ne 1 ] ; then
    echo "ERROR: Removing entry from $PASSWDFILE failed." >&2
    exit 11
  fi

  /bin/mv $PASSWDFILE.new.$$ $PASSWDFILE
}

#
# check and add (x)inetd entry
#
check_add_inetd(){
  CHECKONLY=no
  if [ _"$1" = _-n ] ; then
    CHECKONLY=yes
    shift
  fi

  SERVNAME="$1"
  SOCKTYPE="$2"
  PROT="$3"
  FLAGS="$4"
  USERNAME="$5"
  PROGRAM="$6"

  if [ $use_xinetd = no ] ; then
    grep "^$SERVNAME[ 	][ 	]*$SOCKTYPE[ 	][ 	]*$PROT[ 	]" $INETDCONF >/dev/null
    if [ $? -eq 0 ] ; then
      ENTRY=`grep "^$SERVNAME[ 	][ 	]*$SOCKTYPE[ 	][ 	]*$PROT[ 	]" $INETDCONF | sed 's/[ 	][ 	]*/ /g'`
      if [ "$ENTRY" != "$SERVNAME $SOCKTYPE $PROT $FLAGS $USERNAME $PROGRAM" ] ; then
	echo "ERROR: Entry for service $SERVNAME exists, but is wrong." >&2
	exit 9
      else
	return 0
      fi
    fi
  else
    if [ _"$FLAGS" = _wait ] ; then
	WAITYESNO=yes
    else
	WAITYESNO=no
    fi
    SERVER_ARGS=`echo "$PROGRAM"|awk 'BEGIN{sep="";}{for(i=2;i<=NF;i++){printf "%s%s",sep,$i;sep=" "}}'`
    SERVERPROG=`echo "$PROGRAM" | awk '{print $1}'`

    if [ `get_xinetd_entry $SERVNAME $xinetdfile | wc -l` -gt 0 ] ; then
      server="`get_xinetd_param $SERVNAME server $xinetdfile`"
      server_args="`get_xinetd_param $SERVNAME server_args $xinetdfile`"
      server_args_=`echo "$server_args"|sed 's/[	 ][ 	]*/ /g'`
      username="`get_xinetd_param $SERVNAME user $xinetdfile`"
      prot="`get_xinetd_param $SERVNAME protocol $xinetdfile`"
      wait="`get_xinetd_param $SERVNAME wait $xinetdfile`"
      sockt="`get_xinetd_param $SERVNAME socket_type $xinetdfile`"
      flags="`get_xinetd_param $SERVNAME flags $xinetdfile`"
      test _"$server" = _"$SERVERPROG" \
	&& test _"$server_args_" = _"$SERVER_ARGS" \
	&& test _"$username" = _"$USERNAME" \
	&& test _"$sockt" = _"$SOCKTYPE" \
	&& test _"$wait" = _$WAITYESNO \
	&& test  _"$prot" = _"$PROT" \
	&& test `echo "$flags" | egrep '^(.* )?REUSE( .*$)?' |wc -l` -gt 0 \
	&& test `echo "$flags" | egrep '^(.* )?NAMEINARGS( .*$)?' | wc -l` -gt 0
      if [ $? -ne 0 ] ; then
	echo "ERROR: Entry for service $SERVNAME exists in $xinetdfile, but is wrong." >&2
	exit 9
      else
	return 0
      fi
    fi
  fi

  if [ $CHECKONLY = yes ] ; then
    return 0
  fi

  if [ $use_xinetd = no ] ; then
    echo "$SERVNAME	$SOCKTYPE	$PROT	$FLAGS	$USERNAME	$PROGRAM" >> $INETDCONF
  else
    cut -c10- >> $xinetdfile << EOF
       > 
       > service $SERVNAME
       > {
       >         flags           = REUSE NAMEINARGS
       >         socket_type     = $SOCKTYPE
       >         protocol        = $PROT
       >         wait            = $WAITYESNO
       >         user            = $USERNAME
       >         server          = $SERVERPROG
       >         server_args     = $SERVER_ARGS
       > }
EOF

  fi
}

#
# check and remove inetd entry
#
check_rm_inetd(){
  SERVNAME="$1"
  SOCKTYPE="$2"
  PROT="$3"

  if [ $use_xinetd = no ] ; then
    grep "^$SERVNAME[ 	][ 	]*$SOCKTYPE[ 	][ 	]*$PROT[ 	]" $INETDCONF >/dev/null
    if [ $? -ne 0 ] ; then
      return 0
    fi

    grep -v "^$SERVNAME[ 	][ 	]*$SOCKTYPE[ 	][ 	]*$PROT[ 	]" $INETDCONF > $INETDCONF.new.$$
    N1=`diff $INETDCONF $INETDCONF.new.$$ | grep '^[<>]' | wc -l`
    N2=`diff $INETDCONF $INETDCONF.new.$$ | grep -v '^[<>]' | wc -l`
    if [ $N1 -ne 1 -o $N2 -ne 1 ] ; then
      echo "ERROR: Removing entry from $INETDCONF failed." >&2
      exit 11
    fi

    /bin/mv $INETDCONF.new.$$ $INETDCONF
  else
    if [ `get_xinetd_entry $SERVNAME $xinetdfile | wc -l` -lt 1 ] ; then
	return 0
    fi

    strip_xinetd_entry "$SERVNAME" $xinetdfile | comb_empty_lines > $xinetdfile.new
## this is too heavy to check
#    diff $xinetdfile $xinetdfile.new | egrep '^<[ 	]*[^ 	]' >/dev/null
#    if [ $? -eq 0 ] ; then
#      echo "ERROR: Removing entry from $INETDCONF failed." >&2
#      exit 11
#    fi

    /bin/mv $xinetdfile.new $xinetdfile
  fi
}


if echo "$PROGNAME" | egrep '^(postinstall|checkinstall|prereq)' >/dev/null ; then
  CHECKFLAG=""
  if echo "$PROGNAME" | egrep '^(checkinstall|prereq)' >/dev/null ; then
    CHECKFLAG="-n"
  fi

  check_add_inetd $CHECKFLAG afbackup stream tcp nowait root "/usr/local/afbackup/server/bin/afserver /usr/local/afbackup/server/bin/afserver /usr/local/afbackup/server/etc/backup.conf" \
   && check_add_inetd $CHECKFLAG afmbackup stream tcp wait root "/usr/local/afbackup/server/bin/afmserver /usr/local/afbackup/server/bin/afmserver /usr/local/afbackup/server/etc/backup.conf"
  if [ $? -ne 0 ] ; then
    echo "ERROR: Could not add entry to $INETDCONF" >&2
    exit 10
  fi

  check_add_user $CHECKFLAG backup 2988 14
  if [ $? -ne 0 ] ; then
    echo "ERROR: Could not add entry to $PASSWDFILE" >&2
    exit 8
  fi

  check_add_service $CHECKFLAG afbackup 2988/tcp \
   && check_add_service $CHECKFLAG afmbackup 2989/tcp
  if [ $? -ne 0 ] ; then
    echo "ERROR: Could not create entry to $SERVICES" >&2
    exit 5
  fi
fi
if [ $PROGNAME = preremove ] ; then
  check_rm_inetd afbackup stream tcp \
   && check_rm_inetd afmbackup stream tcp
  if [ $? -ne 0 ] ; then
    echo "WARNING: Could not remove entry from $INETDCONF" >&2
  fi

  check_rm_user backup 2988
  if [ $? -ne 0 ] ; then
    echo "WARNING: Could not remove entry from $PASSWDFILE" >&2
  fi

  check_rm_service afbackup 2988/tcp \
   && check_rm_service afmbackup 2989/tcp
  if [ $? -ne 0 ] ; then
    echo "WARNING: Could not remove entry from $SERVICES" >&2
  fi
fi

echo "$PROGNAME" | egrep '^(checkinstall|prereq)' >/dev/null
if [ $? -ne 0 ] ; then
  if [ $use_xinetd = no ] ; then
    PID=`$PSALL|grep -v grep|egrep '[ 	/]inetd([ 	].*)?$'|awk '{print $2}'`
    if [ _"$PID" != _ ] ; then
      kill -HUP $PID
    else
      echo "WARNING: No (x)inetd running. Remote start will not work." >&2
    fi
  else
    PID=`$PSALL|grep -v grep|egrep '[ 	/]xinetd([ 	].*)?$'|awk '{print $2}'`
    if [ _"$PID" != _ ] ; then
      kill -USR2 $PID
    else
      echo "WARNING: No (x)inetd running. Remote start will not work." >&2
    fi
  fi
fi
