#
# initscript   Executed by init(8) for every program it
#              wants to spawn like this:
#
#              /bin/sh /etc/initscript <id> <level> <action> <process>
#
# Set ulimits from sysconfig
# (c) garloff@suse.de, 1996, 2003, 2008
# License: Artistic

# Set umask to safe level, and set ulimits
umask 022
PATH=/bin:/sbin:/usr/bin:/usr/sbin
export PATH
unset HARGS SARGS SARGS2 RC

# Call with LIMIT BASE
# if BASE is not set, then LIMIT will be treated as absolute value,
# otherwise as percentage of BASE.
# Return value in RC
calc_limit()
{
  local lim
  unset RC
  if test "$1" = "0" -o -z "$1"; then
    return 1
  else
    if test "$1" = "unlimited" -o "${1:0:1}" = "@" -o -z "$2"; then
      RC="${1#@}"
    else
      lim=$((($2+99)/100*$1))
      let lim-=$((lim%4))
      RC="$lim"
    fi
    #echo "(\"$1\" \"$2\" \"$3\" -> \"$RC\""
    return 0
  fi
}

#Call with option character (without H/S), HARDLIMIT, SOFTLIMIT, BASE
set_limit()
{
  local currsoft
  local currhard
  local newhard
  local newsoft
  currsoft=`ulimit -S"$1"`
  currhard=`ulimit -H"$1"`
  calc_limit "$2" "$4" && newhard="$RC"
  calc_limit "$3" "$4" && newsoft="$RC"
  if [ "$currsoft" == "unlimited" ] || [ -z "$newhard" ] || [[ "$newhard" != "unlimited" && "$newhard" -lt "$currsoft" ]]; then
    #For newhard less than currsoft, set softlimit first
    test -z "$newsoft" || ulimit -S"$1" $newsoft
    test -z "$newhard" || ulimit -H"$1" $newhard
  else
    # if newsoft > currhard and all other cases
    test -z "$newhard" || ulimit -H"$1" $newhard
    test -z "$newsoft" || ulimit -S"$1" $newsoft
  fi
  unset RC
}

get_mem()
{
  TOT=0; LOANEDTOT=0
  # Get loaned memory if running CMO
  if test -r /sys/devices/system/cmm/cmm0/loaned_kb; then
    LOANEDTOT=`cat /sys/devices/system/cmm/cmm0/loaned_kb`
  fi
  if test -r /proc/meminfo; then
  # Get memory & swap sizes to evaluate the percentages
    MEMTOT=0; SWPTOT=0
    while read tag num unit; do
      case $tag in
        MemTotal:)
	  MEMTOT=$num
	  ;;
        SwapTotal:)
	  SWPTOT=$num
	  ;;
      esac
    done < /proc/meminfo
    TOT=$(($MEMTOT+$SWPTOT+$LOANEDTOT))
  fi
}

if test -r /etc/sysconfig/ulimit; then
  . /etc/sysconfig/ulimit
  # Max CPU time (not recommended)
  set_limit "t" "$HARDCPULIMIT" "$SOFTCPULIMIT"
  # File descriptors
  set_limit "n" "$HARDFDLIMIT" "$SOFTFDLIMIT"
  # Core files (0 makes sense here!)
  test -z "$HARDCORELIMIT" || ulimit -Hc "$HARDCORELIMIT"
  test -z "$SOFTCORELIMIT" || ulimit -Sc "$SOFTCORELIMIT"
  # File sizes
  set_limit "f" "$HARDFILESIZELIMIT" "$SOFTFILESIZELIMIT"
  # User processes
  set_limit "u" "$HARDPROCESSLIMIT" "$SOFTPROCESSLIMIT"

  # Memory dependent limits
  get_mem
  if test $TOT != 0; then

    # SINGLE process limits to prevent a process from killing the machine
    # by making it go OOM

    # Maximum No more than VIRTUALLIMIT % of all virtual memory
    set_limit "v" "$HARDVIRTUALLIMIT" "$SOFTVIRTUALLIMIT" "$TOT"
    # Maximum resident size is $RESIDENTLIMIT % of physical RAM
    set_limit "m" "$HARDRESIDENTLIMIT" "$SOFTRESIDENTLIMIT" "$MEMTOT"
    # Limit locked mem to $LOCKLIMIT % of phys RAM
    set_limit "l" "$HARDLOCKLIMIT" "$SOFTLOCKLIMIT" "$MEMTOT"
    # Optional: Limit stack and data segment sizes ($STACKLIMIT, $DATALIMIT)
    set_limit "s" "$HARDSTACKLIMIT" "$SOFTSTACKLIMIT" "$MEMTOT"
    # Data seg size
    set_limit "d" "$HARDDATALIMIT" "$SOFTDATALIMIT" "$MEMTOT"
  fi
  unset TOT MEMTOT SWPTOT
fi
# cleanup environment
unset calc_limit set_limit get_mem

# Execute the program.
eval exec "$4"
