#!/bin/sh
#
# $Id: start,v 1.221 2004/08/11 15:18:46 grubba Exp $

### If --silent-start is given as the first argument,
### nothing will be printed to stdout by the script.

if [ "x$1" = "x--silent-start" ] ; then
 SILENT_START="y"
 shift
fi

check_owner() {
   gargs=''

   if [ -w / ] ; then
     # Shall we change uid/gid?
     num=`grep --help 2>&1|grep gnu|wc -l`
     num=`echo $num`
     if [ x"$num" = x1 ] ; then
       gargs='-a'
     fi
     ugid=`grep $gargs "='User'>" $DIR/Global_Variables 2>/dev/null\
           | sed -e 's/.*<str>//' -e 's,</str>.*,,'`
     if [ ! x$ugid = x ] ; then
        dp "Doing uid change to $ugid"
        oifs="$IFS";IFS=':';set $ugid;IFS="$oifs"
	if [ ! "x$2" = x ]; then
	  ok=`ls -lgd . 2>/dev/null | grep "$2" |wc -l`
	  ok=`echo $ok`
	  if [ "x$ok" = x1 ] ; then
	    dp "The server directory is already readable by group $2"
	  else
	    ok=`ls -ngd . 2>/dev/null | grep "$2" |wc -l`
	    ok=`echo $ok`
	    if [ "x$ok" = x1 ] ; then
	      dp "The server directory is already readable by group $2"
	    else
	      chgrp -R "$2" .
	      chmod -R g+r  .
	    fi
	  fi
	fi
	change_owner "$1" "$2" "$DIR" "$VARDIR" "$LOGDIR"
     fi
   fi
}


# Breaks on linux when using symlinks.
dn="`dirname "$0"`"
case "$dn" in 
 ""|".")
  ;;
 *)
  # dp is not used here since we cannot source bin/functions before we
  # are in the correct directory, for quite obvious reasons...
  if [ ! "$dn" = "`pwd`" ]
  then
    echo "          : Changing current directory to '$dn' (now `pwd`)" >&2
    cd "$dn"
    echo "          : Got new directory as `pwd`" >&2
  fi
  ;;
esac

. bin/functions

# Can be set with '--config-dir=DIR'
DIR=../configurations
LOGDIR=../logs
FILES="default"
program=base_server/roxenloader.pike
VARDIR=../var
LOCALDIR=../local
SELF_TEST_DIR=etc/test

# Make LOCALDIR an absolute path
if test -d $LOCALDIR/.; then
  LOCALDIR="`cd $LOCALDIR; pwd`"
else :; fi

if test -d $VARDIR/.; then :; else
  dp "Creating directory $VARDIR"
  ./mkdir -p $VARDIR/ || exit 1
fi


pcdir="$VARDIR/`roxen_version`/precompiled/`uname -m | tr ' ' '_' `.`uname -r`"
old_roxen_defines="$pcdir/old_roxen_defines"
./mkdir -p "$pcdir" || exit 1
chmod 1777 "$pcdir"

# Default verbosity level.
verbose=1

# Do not default to using a relative path.
roxendir="`pwd`"

# No debug by default.
debug=-1

# Locate Pike binary.
find_pike

# Source environment
setup_environment

####### BEGIN ARGUMENT PARSING


DEFINES="$DEFINES -DRAM_CACHE"

# Thread enabling.
# FIXME: Ought to use case...esac.

# Enable threads (if available) on Solaris.
# Most other OS's have thread bugs that cause them or Roxen to crash.
if uname | grep 'SunOS' >/dev/null 2>&1; then
  if uname -r | grep '5\.[5-9]' >/dev/null 2>&1; then
    # FIXME: What about Solaris 10+ (SunOS 5.10+)?
#    if [ $verbose -gt 0 ] ; then
#      dp "Solaris 2.5 or later detected. Using threads by default."
#    fi
    DEFINES="$DEFINES -DENABLE_THREADS"
  fi
fi
# Darwin 1.4/5.x or later (Mac OS X 10.1 or newer) also uses threads.
if uname | grep 'Darwin' >/dev/null 2>&1; then
  if uname -r | grep '^1\.[4-9]' >/dev/null 2>&1; then
    DEFINES="$DEFINES -DENABLE_THREADS"
  elif uname -r | grep '^[5-9]' >/dev/null 2>&1; then
    DEFINES="$DEFINES -DENABLE_THREADS"
  fi
fi
# Also enabled on Linux.
if uname | grep 'Linux' >/dev/null 2>&1; then
  DEFINES="$DEFINES -DENABLE_THREADS"
fi

gdb=no
truss=

remove_dumped_passed=no
remove_old_dot_o_files () {
  dp "Removing old precompiled files ($1)"
  # This really cannot be done from here anymore -- pass on an option
  # to roxenloader instead.

  # Make sure that the argument isn't duplicated for every restart...
  if [ "x$remove_dumped_passed" = "xyes" ]; then :; else
    pass="$pass --remove-dumped"
    remove_dumped_passed=yes
  fi
}

## Parse all arguments.
## GNU-style, long options only, except for -D, simply passed on.
ARGS=""

setup_for_tests() {
    # Kill roxen mysql if it's running...
    if [ -f "$VARDIR/test_config/_mysql/mysql_pid" ] ; then
      kill `cat "$VARDIR/test_config/_mysql/mysql_pid"`
    fi
    self_test=y
    DEFINES="-DRUN_SELF_TEST -DSELF_TEST_DIR=\"$SELF_TEST_DIR\" $DEFINES"
    rm -rf "$VARDIR/test_config"*
    DIR="$VARDIR/test_config"
    if [ -f "$SELF_TEST_DIR/scripts/setup.pike" ] ; then
      $PIKE "$SELF_TEST_DIR/scripts/setup.pike" "$SELF_TEST_DIR" "$VARDIR"
    fi
    once=${once:-1}
    debug=1
    #remove_dumped=1
}

parse_args() {
 while [ ! c"$1" = "c" ] ; do
  case "$1" in
  -D*)
   DEFINES="$DEFINES $1"
  ;;
  -l*)
   ARGS="$ARGS $1"
  ;;
  --truss)
     truss="truss"
   ;;
  --truss-c)
     truss="truss -c"
   ;;
  --strace)
     truss="strace"
   ;;
  --log-dir=*)
   LOGDIR=`echo $1 | sed -e 's/--log-dir=//'`
  ;;
  --debug-log=*)
   DEBUGLOG=`echo $1 | sed -e's/--debug-log=//'`
  ;;
  --config-dir=*)
   DIR=`echo $1 | sed -e 's/--config-dir=//'`
   FILES=`echo $1 | sed -e's/--config-dir=//' -e's/\.//g' -e's./..g' -e 's.-..g'`
  ;;
  --pid-file=*)
   pidfile=`echo $1 | sed -e 's/--pid-file=//'`
  ;;
  '--with-security'|'--enable-security')
    DEFINES="$DEFINES -DSECURITY"
  ;;
  '--with-snmp-agent'|'--enable-snmp-agent')
    DEFINES="$DEFINES -DSNMP_AGENT"
  ;;

  '--debug'|'--with-debug'|'--enable-debug')
    debug=1
  ;;
  '--without-debug')
    debug=-1
  ;;
  '--module-debug'|'--with-module-debug'|'--enable-module-debug')
    debug=0
  ;;
  '--fd-debug'|'--with-fd-debug'|'--enable-fd-debug')
    DEFINES="-DFD_DEBUG $DEFINES"
  ;;
  '--strip-backslash'|'--without-backslash'|'--strip-back-slash')
    DEFINES="-DSTRIP_BSLASH $DEFINES"
  ;;
  '--offline')
    DEFINES="-DNO_DNS -DOFFLINE $DEFINES"
  ;;
  '--without-ram-cache'|'--disable-ram-cache')
    DEFINES="`echo $DEFINES | sed -e 's/-DRAM_CACHE//g'`"
  ;;
  '--without-ram-cache-stat'|'--disable-ram-cache-stat')
    DEFINES="`-DRAM_CACHE_ASUME_STATIC_CONTENT`"
  ;;
  '--dump-debug'|'--with-dump-debug'|'--enable-dump-debug')
    DEFINES="-DDUMP_DEBUG $DEFINES"
  ;;
  '--threads'|'--with-threads'|'--enable-threads')
    DEFINES="-DENABLE_THREADS $DEFINES"
  ;;
  '--no-threads'|'--without-threads'|'--disable-threads')
    DEFINES="`echo $DEFINES | sed -e 's/-DENABLE_THREADS//g'`"
  ;;
  '--with-profile'|'--profile')
    DEFINES="-DPROFILE $DEFINES"
  ;;
  '--with-file-profile'|'--file-profile')
    DEFINES="-DPROFILE -DFILE_PROFILE $DEFINES"
  ;;
  '--quiet'|'-q')
    verbose=0
  ;;
  '--verbose'|'-v')
    verbose=2
    debug=1
  ;;
  '--remove-dumped')
     remove_dumped=1;
  ;;

  '--once')
    once=${once:-1}
    debug=0
  ;;
# Misspelling --once might give undesirable results, so let's accept
# some "creative" spellings...  :-)
  '--onve'|'--onec'|'--onev'|'--ocne')
    once=${once:-1}
    debug=0
  ;;
  '--keep-mysql')
    keep_mysql=1
  ;;
  '--gdb')
    gdb=gdb
    once=2
    debug=0
  ;;
  '--program')
    program="$2"
    once=2
    passhelp=1
    shift
    shift
    # Pass any remaining arguments along to the program.
    while [ ! c"$1" = "c" ] ; do
      pass="$pass '`echo \"$1\" | sed -e \"s/'/'\\\"'\\\"'/g\"`'"
      shift
    done
    break
  ;;
  '--cd')
    cd_to="$2"
    # Use the absolute path...
    roxendir="`pwd`"
    once=${once:-1}
    shift
  ;;
  --debug-without=*|-r*|-d*|-t*|-l*|-w*|-a*|-p*|--*-debug*)
    # Argument passed along to Pike.
    ARGS="$ARGS $1"
  ;;
  -D*|-M*|-I*|-P*)
    # Argument passed along to Pike.
    DEFINES="$DEFINES \"$1\""
  ;;
  '--version')
   if [ "x$passhelp" = "x1" ] ; then
     pass="$pass --version"
   else
    if [ -f base_server/roxen.pike ]; then
      echo "Roxen WebServer `roxen_version`"
      exit 0
    else
      echo 'base_server/roxen.pike not found!'
      exit 1
    fi
   fi
  ;;
  --self-test-dir=*)
    SELF_TEST_DIR=`echo $1 | sed -e's/--self-test-dir=//'`
  ;;
  '--self-test')
    setup_for_tests
  ;;
  '--self-test-quiet')
    debug=-1
    SILENT_START=y
    do_pipe="| grep '  |'"
    setup_for_tests
  ;;
  '--self-test-verbose')
    pass="$pass --tests-verbose=1"
    setup_for_tests
  ;;
  '--help'|'-?')
   if [ "x$passhelp" = "x1" ] ; then
     pass="$pass --help"
   else
  sed -e "s/\\.B/`tput 'bold' 2>/dev/null`/g" -e "s/B\\./`tput 'sgr0' 2>/dev/null`/g" << EOF
.BThis command will start the Roxen WebServerB..

The environment variable .BROXEN_ARGSB. can be used to specify
the default arguments.

   .BArguments:B.

      .B--versionB.:                  Output version information.

      .B--help -?B.:                  This information.

      .B--offlineB.:                  Indicate that there is no network 
				  connection available. Disables DNS and some
				  other similar things.

      .B--remove-dumpedB.:            Remove all dumped code, thus forcing
                                  a recompile.

      .B--verbose -vB.:               Enable more verbose messages.

      .B--quiet -qB.:                 Disable most of the messages.

      .B--log-dir=DIRB.:              Set the log directory. Defaults to .B../logsB..

      .B--config-dir=DIRB.:           Use an alternate configuration directory.
				  Defaults to .B../configurationsB..

      .B--debug-log=FILEB.:           Use an alternate debuglog file.
				  Defaults to .B../logs/debug/B.configdirname.B.1B..

      .B--pid-file=FILEB.:            Store the Roxen and start script pids in this
				  file. Defaults to .B../configurations/_roxen_pidB..

      .B--silent-startB.:             Inhibits output to stdout. If used,
                                  this argument must be the first one.

      .B--strip-backslashB.:          Replace all \\ characters in URIs with /

      .B--without-ram-cacheB.:        Do not use a protocol level RAM cache to speed
				  things up. Saves RAM at the cost of speed.

      .B--without-ram-cache-statB.:   Disable the stat that is usually done
				  for files in the protocol cache to ensure that
				  they are not changed before they are sent.
                                  Improves performance at the cost of constant
                                  aggravation if the site is edited. Useful for
				  truly static sites.

      .B--with-threadsB.:             If threads are available, use them.

      .B--without-threadsB.:          Even if threads are enabled by default,
                                  disable them.

      .B--with-profileB.:             Store runtime profiling information on
				  a directory basis. This information is
 				  not saved on permanent storage, it is only
				  available until the next server restart
				  This will enable a new 'action' in the
				  administration interface

      .B--with-file-profileB.:        Like .B--with-profileB., but save information
                                  for each and every file.

      .B--self-testB.:                Runs a testsuite.
      .B--self-test-verboseB.:        Runs a testsuite, report all tests.
      .B--self-test-quietB.:          Runs a testsuite, only report errors.
      .B--self-test-dir=DIRB.:        Use this self test directory instead of
                                  the default .Betc/testB. directory.

      .B--onceB.:                     Run the server only once, in the foreground.
			   	  This is very useful when debugging. Implies
				  --module-debug.

      .B--keep-mysqlB.:               Do not shut down MySQL process when exiting
				  the start script. Useful during development
				  or any other scenario where the start script
				  is frequently terminated.

      .B--gdbB.:                      Run the server in gdb. Implies .B--onceB..

      .B--programB.:                  Start a different program with the Roxen
				  Pike. As an example,
                                  .B./start --program bin/install.pikeB. will
				  start the installation program normally
                                  started with .B./installB.

      .B--with-debugB.:               Enable debug

      .B--without-debugB.:            Disable all debug. This is the default.

      .B--module-debugB.:             Enable more internal debug checks to
                                  simplify debugging of Roxen modules.

      .B--fd-debugB.:                 Enable FD debug.

      .B--dump-debugB.:               Enable dump debug.

      .B--trussB.:                    (Solaris only). Run the server under
				  truss, shows .BallB. system calls. This is
				  extremely noisy, and is not intented for
				  anything but debug.

      .B--truss-cB.:                  (Solaris only). Run the server under
				  truss -c, shows times for all system calls
                                  on exit. This is not intented for anything
                                  but debug. Slows the server down.

      .B--with-snmp-agentB.:          Enable internal SNMP agent code.

  .BArguments passed to Pike:B.

       .B-DDEFINEB.:                  Define the symbol .BDEFINEB..

       .B-d<level>B.:                 Set the runtime Pike debug to level.
				  This only works if Pike is compiled
				  with debug (i.e. with --rtl-debug to
				  configure).

       .B-rtB.:                       Enable runtime typechecking.
				  Things will run more slowly, but it is very
                                  useful while developing code.

				  Enabled when starting Roxen with --debug

       .B-rTB.:                       Enable strict types.
				  Same as adding #pragma strict-types
				  to all files.

				  This enables more strict
				  type-checking, things that are
				  normally permitted (such as calling
				  a mixed value, or assigning a typed
				  object variable with an untyped
				  object) will generate warnings.

				  Useful for module and Roxen core
				  developers, but not so useful for
				  the occasional pike-script-writer.

				  Enabled when starting Roxen with --debug

       .B-s<size>B.:                  Set the stack size.

       .B-M<path>B.:                  Add the path to the Pike module path.

       .B-I<path>B.:                  Add the path to the Pike include path.

       .B-P<path>B.:                  Add the path to the Pike program path.

       .B-dtB.:                       Turn off tail recursion optimization.

       .B-tB.:                        Turn on Pike level tracing.

       .B-pB.:                        Turn on Pike profiling.

       .B-t<level>B.:                 Turn on more Pike tracing. This only
				  works if Pike is compiled with debug
				  (i.e. with --rtl-debug to configure).

       .B-a<level>B.:                 Turn on Pike assembler debug. This only
				  works if Pike is compiled with debug
				  (i.e. with --rtl-debug to configure).

       .B-wB.:                        Turn on Pike warnings.

  .BEnvironment variables:B.

     .BLANGB.:                        Used to determine the default locale
                                  in the administration interface and logs.
     .BROXEN_CONFIGDIRB.:             Same as .B--config-dir=... B.
     .BROXEN_PID_FILEB.:              Same as .B--pid-file=... B.
     .BROXEN_LANGB.:                  The default language for all language
		                  related tags. Defaults to 'en' for english.

EOF
    tput 'rmso' 2>/dev/null
    exit 0
    fi
   ;;
  *)
    pass="$pass '`echo \"$1\" | sed -e \"s/'/'\\\"'\\\"'/g\"`'"
   ;;
  esac
  shift
 done
}

if [ ! "X$ROXEN_ARGS" = "X" ]; then
  parse_args $ROXEN_ARGS
fi

parse_args "$@"

if [ "$once" = "" ]; then :; else
  # Once-mode.
  if [ "x$passhelp" = "x1" ]; then :; else
    # We're not using --program.
    # Pass --once along to roxenloader.
    pass="$pass --once=$once"
  fi
fi

# The work has already been done above, but the debug printout is better
# to have _after_ parse_args (consider --help and --version)

if [ ! "X$ROXEN_ARGS" = "X" ]; then
  if [ $verbose -gt 0 ]; then
    dp "Used $ROXEN_ARGS from ROXEN_ARGS."
  else :; fi
fi

if [ ! "X$pass" = "X" ] ; then set -- $pass ;fi


####### END ARGUMENT PARSING


####### BEGIN PIKE OPTIONS

# Roxen WebServer will create files as the initial user,
# which it expects to be able to read as the run-time user.
umask 022

if [ "x$PIKE_NO_DEFAULT_PATHS" = "x" ]; then
  # Pike default Master-program
  if [ "x$PIKE_MASTER" = "x" ]; then
    if [ -f lib/master.pike ]; then
      DEFINES="$DEFINES \"-m$roxendir/lib/master.pike\""
    elif [ -f lib/pike/master.pike ]; then
      DEFINES="$DEFINES \"-m$roxendir/lib/pike/master.pike\""
    fi
  else
    # This is useful when using several different Pikes.
    # Specify include and module paths with
    # PIKE_INCLUDE_PATH and PIKE_MODULE_PATH
    # they are handled automatically by the master,
    # so no need to do it here.
    DEFINES="$DEFINES \"-m$PIKE_MASTER\""
  fi
fi

# Extra module-path
#if [ -d etc/modules ]; then
  DEFINES="$DEFINES \"-M$roxendir/etc/modules\""
#fi

if [ -d "$LOCALDIR/pike_modules/." ]; then
  DEFINES="$DEFINES \"-M$LOCALDIR/pike_modules\""
fi

# Extra include-path
#if [ -d etc/include ]; then
  DEFINES="$DEFINES \"-I$roxendir/etc/include\""
#fi

if [ -d "$LOCALDIR/include/." ]; then
  DEFINES="$DEFINES \"-I$LOCALDIR/include\""
fi

# Extra include-path (2)
#if [ -d base_server ]; then
  DEFINES="$DEFINES \"-I$roxendir/base_server\""
#fi

if [ -d "$LOCALDIR/base_server/." ]; then
  DEFINES="$DEFINES \"-I$LOCALDIR/base_server\" \"-P$LOCALDIR/base_server\""
fi

# Extra program-path
DEFINES="$DEFINES \"-P`pwd`\""

# Support for adding local pike-modules
if [ -d "$LOCALDIR/etc/." ]; then
  # Extra module-path
  if [ -d "$LOCALDIR/etc/modules/." ]; then
    DEFINES="$DEFINES \"-M$LOCALDIR/etc/modules\""
  fi

  # Extra include-path
  if [ -d "$LOCALDIR/etc/include/." ]; then
    DEFINES="$DEFINES \"-I$LOCALDIR/etc/include\""
  fi

  # Extra program-path
  DEFINES="$DEFINES \"-P$LOCALDIR/etc\""
fi

# Extra kludge for HPUX
# HPUX doesn't like group 60001(nobody)
if uname | grep 'HP-UX' >/dev/null 2>&1; then
  if [ $verbose -gt 0 ]; then
    dp "WARNING: Applying kludge for HPUX. (see base_server/roxen.pike)"
  else :; fi
  DEFINES="$DEFINES -DHPUX_KLUDGE"
fi


case "x$debug" in
  "x"|"x0")
    DEBUG="-DMODULE_DEBUG "
    ARGS="$ARGS -w"
    ;;
  "x-1")
    DEBUG=""
    ;;
  "x1")
    DEBUG="-DDEBUG -DMODULE_DEBUG"
    ARGS="$ARGS -w"
    ;;
esac

DEFINES="$DEBUG $DEFINES"

####### END PIKE OPTIONS


#
# Some useful functions
#

cleanup_pid_file() {
  [ -z "$pidfile" ] || rm $pidfile
}

# NOTE: The following function needs to be reentrant.
signal_exit() {
  dp "Start script terminating."
  trap "" 2 15
  if [ "x$ROXEN_PID" != "x" ] && \
     kill -0 $ROXEN_PID 2>/dev/null; then
    kill $ROXEN_PID 2>/dev/null && wait $ROXEN_PID 2>/dev/null
    dp "Roxen WebServer shutdown."
    # FIXME: Consider exiting here.
  fi
  if [ "x$keep_mysql" = "x" ] ; then
    if [ -f $DIR/_mysql/mysql_pid ] ; then
      mysql_pid="`cat $DIR/_mysql/mysql_pid 2>/dev/null`"
      dp_no_nl "Shutting down MySQL."
      kill "$mysql_pid" 2>/dev/null
      # Give mysql 5 minutes to shut down.
      timer=""
      while [ -f "$DIR/_mysql/mysql_pid" -a \
	      "$timer" != "mmmmm" ] && \
	    kill -0 "$mysql_pid" 2>/dev/null; do
	sleep 2
	timer=`echo "x$timer" | sed -e 's/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/m/'`
	if [ "x$SILENT_START" != "xy" ]; then
	  # Progress indicator.
	  echo "." | tr -d '
' >&2
	fi
      done
      if [ "x$SILENT_START" != "xy" ]; then
	echo >&2
      fi
      if kill -0 "$mysql_pid" 2>/dev/null; then
        dp "Shutting down MySQL the hard way."
        kill -9 "$mysql_pid" 2>/dev/null
      fi
      if [ -f "$DIR/_mysql/mysql_pid" ] && \
	 [ "$mysql_pid" = "`cat $DIR/_mysql/mysql_pid`" ]; then
        rm -f "$DIR/_mysql/mysql_pid" 2>/dev/null
      fi
    fi
  fi
  dp "Start script terminated."
  exit 0
}

exit_fail() {
  exitcode=1
}

# This is a trick to get $ROXEN_PID and arguments containing spaces
# correct at the same time.
fork_roxen() {
  if [ $verbose -gt 0 ]; then
    dp "Server start command:"
    for arg
    do
      dp "    $arg"
    done
  fi
  "$@" &
  ROXEN_PID=$!
}

start_roxen() {
  check_owner
  raise_limit

  if [ x$remove_dumped = x1 ] ; then
    remove_old_dot_o_files "user request"
  fi
  if [ "x$DIR" != "x../configurations" ] ; then
    args="$DEFINES $ARGS $program --config-dir='`echo \"$DIR\" | sed -e \"s/'/'\\\"'\\\"'/g\"`' $pass"
  else
    args="$DEFINES $ARGS $program $pass"
  fi
  if [ x"$cd_to" != x ] ; then
    cd "$cd_to"
  fi
  if [ "x$gdb" = "xno" ]; then
    if [ "x$once" = "x" ]; then
      if [ $verbose -gt 0 ]; then
	dp "Executing $pike $args"|sed -e "s!`pwd`!.!g"
      fi
      eval "fork_roxen \"$pike\" $args 2>>\"${DEBUGLOG}.1\" 1>&2"
      dp "Roxen WebServer server pid $ROXEN_PID."
      wait $ROXEN_PID 2>/dev/null 1>&2
      exitcode="$?"
      ROXEN_PID=""
    else
      if [ "x$do_pipe" = "x" ] ; then
        if [ "x$once" = "x1" ]; then
	  eval "fork_roxen $truss \"$pike\" $args 2>&1"
	  wait $ROXEN_PID 2>/dev/null 1>&2
	  exitcode="$?"
	  ROXEN_PID=""
	else
	  eval "$truss \"$pike\" $args" 2>&1
	  exitcode="$?"
	fi
      else
        trap exit_fail 1
	eval "(eval \"$truss \\\"$pike\\\" $args\" || kill -1 $$) 2>&1  $do_pipe"
        exit $exitcode
      fi
    fi
  else
    echo >.gdbinit handle SIGPIPE nostop noprint pass
    echo >>.gdbinit handle SIGUSR1 nostop noprint pass
    echo >>.gdbinit handle SIGUSR2 nostop noprint pass
    echo >>.gdbinit handle SIGLWP nostop noprint pass
    if uname | grep 'Linux' >/dev/null 2>&1; then
      echo >>.gdbinit handle SIG38 nostop noprint pass
      echo >>.gdbinit handle SIG39 nostop noprint pass
    fi
    echo >>.gdbinit break debug_fatal
    echo >>.gdbinit break pike_gdb_breakpoint
    firstline=`head -1 "$pike" 2>/dev/null`
    if expr "x$firstline" : 'x#! */.*' >/dev/null; then
      # Looks like a script. gdb will not grok it, so we try passing
      # --gdb to it instead (which works in the special case of the
      # bin/pike script that is built by the top level Makefile in the
      # Pike source tree).
      dp "Executing $pike --gdb $args"
      eval "\"$pike\" --gdb $args"
    else
      dp "Executing gdb $pike $args"
      echo >>.gdbinit "run $args"
      gdb "$pike"
    fi
    rm .gdbinit
  fi
}


#
# Now do the stuff
#

trap signal_exit 2 15
trap "" 1

if [ "$program" = "base_server/roxenloader.pike" ] ; then
  # Starting a Roxen server. Fix the pid file.
  [ -z "$pidfile" ] && pidfile="${ROXEN_PID_FILE:-$DIR/_roxen_pid}"
  pass="$pass --pid-file='`echo \"$pidfile\" | sed -e \"s/'/'\\\"'\\\"'/g\"`'"
  # Avoid duplicate start scripts if we got a pid file.
  mypid=$$
  test -f "$pidfile" && {
    if read roxenpid && read scriptpid; then
      if kill -0 $scriptpid 2>/dev/null; then
	dp "According to the pid file $pidfile,"
	dp "there is already a start script running with pid $scriptpid. Specify "
	dp "another pid file with --pid-file if this is a different server."
	dp "Server not started."
	:
      elif kill -0 $roxenpid 2>/dev/null; then
	dp "According to the pid file $pidfile,"
	dp "there is already a server running with pid $roxenpid, but its start "
	dp "script seems to have died. You should shut it down and restart "
	dp "it, since it won't restart automatically. Server not started."
	:
      else false; fi
    else false; fi
  } < "$pidfile" && exit 1
  # Minor race here.
  { echo "x" && echo $mypid; } > "$pidfile"
  trap cleanup_pid_file 0
fi

PIKEVERSION="`\"$pike\" --version 2>&1|head -1`"
LS="`ls -lL \"$pike\" 2>/dev/null`"
LS="$LS `find etc/modules -ls 2>/dev/null`"
LS="$LS `find base_server -ls 2>/dev/null`"

VERSION_DATA="$PIKEVERSION   $DEFINES   $LS"

if [ "$program" = "base_server/roxenloader.pike" ] ; then
  if [ "`cat \"$old_roxen_defines\" 2>/dev/null`" != "$VERSION_DATA" ] ; then
    remove_old_dot_o_files "defines or Pike version changed"
  fi
  echo "$VERSION_DATA" > "$old_roxen_defines"
fi

if [ -z "$once" ] ; then
  if [ $verbose -gt 0 ]; then
    dp "Starting the Roxen WebServer."
  else :; fi
  if [ "x$DEBUGLOG" = "x" ] ; then
    DEBUGDIR="$LOGDIR/debug"
    DEBUGLOG="$DEBUGDIR/$FILES"
  else
    DEBUGDIR="`dirname "$DEBUGLOG"`"
  fi
  # This duplicate of the logdir creation code is needed, check the 
  # redirect below
  if [ ! -d "$DEBUGDIR" ] ; then
    if ./mkdir -p "$DEBUGDIR" 2>/dev/null; then :; else
      dp "Failed to create log directory $DEBUGDIR."
      exit 1
    fi
  fi
  if [ -f "bin/setup_nsr.pike" ]; then
    # Setup .nsr (Networker) files for the logfile directories.
    eval "\"$pike\" $DEFINES bin/setup_nsr.pike --logdir=\"$LOGDIR\" --debugdir=\"$DEBUGDIR\""
  fi
  if [ $verbose -gt 0 ]; then
    dp "Using configuration from $DIR"
    dp "Storing the debug log in ${DEBUGLOG}.1"
    dp "You can use the administration interface in the server to see debug info."
  else :; fi

  if (
    (
      # Minor race here wrt pid file cleanup.
      exec 3>&-
      trap signal_exit 2 15
      trap "" 1
      trap cleanup_pid_file 0

      while : ; do
	if test -d "$DEBUGDIR/."; then :; else
	  # Avoid infinite loop if the debug directory is deleted.
	  # Thanks to Emils Klotins <emils@dot.lv> for reporting it.
	  if ./mkdir -p "$DEBUGDIR" 2>/dev/null; then :; else
	    dp "Failed to create log directory $DEBUGDIR."
	    exit 1
	  fi
	fi

	dp "Server start at `date`"
	dp "Debug log in ${DEBUGLOG}.1"
	rotate "$DEBUGLOG"
	start_roxen

	if [ "$exitcode" -eq "0" ] ; then
	  # Clean shutdown.
	  dp "Roxen WebServer shutdown."
	  signal_exit
	  # Not reached, but...
	  exit 0
	fi
	if [ "$exitcode" -lt "0" ] ; then
	  # Signal death.
	  dp "Roxen WebServer died of signal $exitcode."
	else
         case "$exitcode" in
         100)
           dp "Changing Roxen WebServer version. Restarting."
	   # We need to clean up the pid file, since we're mentioned in it...
	   cleanup_pid_file
           cd .. && exec ./start "$@"
           dp 'Failed to spawn start script. -- Permission problem?'
           exit 1
           ;;
	 50)
	   dp "Failed to open any port. Shutdown."
	   keep_mysql=1
	   signal_exit
	   # Not reached, but...
	   exit 50
	   ;;
         *)
           dp "Roxen WebServer down with code $exitcode."
           ;;
         esac
	fi
	if [ -f "$LOCALDIR/restart_rc" ]; then
	  dp "Running $LOCALDIR/restart_rc..."
	  if /bin/sh "$LOCALDIR/restart_rc"; then :; else
	    dp "$LOCALDIR/restart_rc failed with code $?."
	  fi
	fi
	dp "Restarting..."
      done
    ) &
    # Minor race here wrt pid file contents.
    pid=$!
    trap "" 0
    [ -z "$pidfile" ] || { echo "x" && echo $pid; } > "$pidfile"
    dp "Forked start script, pid $pid." 2>&3
    dp "Start script pid $pid."
  ) 3>&2 </dev/null >"$DEBUGDIR/start_$FILES.output" 2>&1; then
    trap "" 0
    :
  else
    dp 'Failed to spawn subshell. -- Permission problem?'
    exit 1
  fi

  # Try to get rid of some fd's.
  # Some /bin/sh's have problems detaching otherwise.

  exec >/dev/null
  exec </dev/null
else
  start_roxen
  if [ "$once" = "1" -a "$exitcode" = "50" ]; then
    dp "Failed to open any port. Shutdown."
    keep_mysql=1
  fi
  signal_exit
fi

