]> git.pld-linux.org Git - projects/rc-scripts.git/blobdiff - lib/functions
Quote filename when checking. Without that * is expanded causing problems.
[projects/rc-scripts.git] / lib / functions
index 56cab8051812f76851c20bf7fd4e7767a7ba5ba5..97169811610f84961e5a01a6524f54f8e30d7a9f 100644 (file)
@@ -53,9 +53,6 @@ CRESMAN="$GREEN"      # "Resource Manager" color
 CHARS=""               # Characters displayed on the beginning of show line
 CCHARS="$NORMAL"       # Color of these characters (look at /etc/sysconfig/init-colors.gentoo example)
 
-# save from env, set by /sbin/service
-env_upstart=$USE_UPSTART
-
 # Source configuration if available - may override default values
 [ -r /etc/sysconfig/init-colors ] && . /etc/sysconfig/init-colors
 [ -r /etc/sysconfig/system ] && . /etc/sysconfig/system
@@ -72,8 +69,6 @@ else
        unset RC_FEDORA || :
 fi
 
-[ "$env_upstart" ] && USE_UPSTART=$env_upstart
-
 if [ -z "$VSERVER" -o "$VSERVER" = "detect" ]; then
        {
                while read _f _ctx; do
@@ -93,16 +88,27 @@ if [ -z "$VSERVER_ISOLATION_NET" -o "$VSERVER_ISOLATION_NET" = "detect" ]; then
        VSERVER_ISOLATION_NET=no
        if [ "$VSERVER" = "yes" ]; then
                if [ -f /proc/self/nsproxy ]; then
+                       # older kernels
                        {
                                while read _t _data; do
                                        [ "$_t" = "net:" ] && break
                                done < /proc/self/nsproxy
                        } 2> /dev/null
+                       if [ "${_data##*\(}" = "I)" ]; then
+                               VSERVER_ISOLATION_NET=yes
+                       fi
+               elif [ -f /proc/self/ninfo ]; then
+                       # newer kernels
+                       {
+                               while read _t _data; do
+                                       [ "$_t" = "NCaps:" ] && break
+                               done < /proc/self/ninfo
+                       } 2> /dev/null
+                       if [ "${_t}" = "NCaps:" ]; then
+                               VSERVER_ISOLATION_NET=yes
+                       fi
                else
-                       # assume old kernel mode
-                       VSERVER_ISOLATION_NET=yes
-               fi
-               if [ "${_data##*\(}" = "I)" ]; then
+                       # assume (very?) old kernel mode
                        VSERVER_ISOLATION_NET=yes
                fi
                unset _f _data
@@ -163,8 +169,7 @@ is_empty_file() {
 
 # returns OK if $1 contains $2
 strstr() {
-       local a=$2
-       [ "${1#*$a*}" = "$1" ] && return 1
+       [ "${1#*$2*}" = "$1" ] && return 1
        return 0
 }
 
@@ -177,12 +182,12 @@ apply_sysctl() {
 
        local file
        for file in /usr/lib/sysctl.d/*.conf; do
-               [ -f /run/sysctl.d/${file##*/} ] && continue
-               [ -f /etc/sysctl.d/${file##*/} ] && continue
+               [ -f "/run/sysctl.d/${file##*/}" ] && continue
+               [ -f "/etc/sysctl.d/${file##*/}" ] && continue
                test -f "$file" && sysctl -q -e -p "$file"
        done
        for file in /run/sysctl.d/*.conf; do
-               [ -f /etc/sysctl.d/${file##*/} ] && continue
+               [ -f "/etc/sysctl.d/${file##*/}" ] && continue
                test -f "$file" && sysctl -q -e -p "$file"
        done
        for file in /etc/sysctl.d/*.conf; do
@@ -493,6 +498,9 @@ checkpid() {
 # (note: some processes like named are chrooted but run outside chroot)
 # - do nothing inside vserver
 filter_chroot() {
+       # no pids, exit early
+       [ $# -eq 0 ] && return
+
        # filter by pid namespace if such dir exists for current process
        # we do filter in containers as stacked containers are possible with LXC
        if [ -d /proc/$$/ns ]; then
@@ -620,16 +628,90 @@ _daemon_set_ulimits() {
        done
 }
 
+# inner function used by daemon().
+# do not call this directly, as it expects variables being inherited.
+# also it expects to be called from subshell as it exports env.
+# it expects options parsed by daemon() and command to be executed in "$@".
+_daemon_exec() {
+       local prog=""
+       umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK};
+       export USER=root HOME=/tmp TMPDIR=/tmp
+
+       nice=${nice:-$DEFAULT_SERVICE_RUN_NICE_LEVEL}
+       nice=${nice:-0}
+
+       # make nice level absolute, not to be dependant of nice level of shell where service started
+       nice=$(($nice - $(nice)))
+
+       if [ "$closefds" = 1 ]; then
+               exec 1>&-
+               exec 2>&-
+               exec 0<&-
+       elif [ "$redirfds" = 1 ]; then
+               exec 1>/dev/null
+               exec 2>/dev/null
+               exec 0</dev/null
+       else
+               exec 2>&1
+               exec 0</dev/null
+       fi
+
+       if is_no "$RC_LOGGING"; then
+               prog=$1; shift
+               if [ ! -x $prog ]; then
+                       logger -t rc-scripts -p daemon.debug "daemon: Searching PATH for $prog, consider using full path in initscript"
+                       local a o=$IFS
+                       IFS=:
+                       for a in $PATH; do
+                               if [ -x $a/$prog ]; then
+                                       prog=$a/$prog
+                                       break
+                               fi
+                       done
+                       IFS=$o
+               fi
+               set -- "$prog" "$@"
+
+               # use setsid to detach from terminal,
+               # NOTE: setsid needs to be "outer" program
+               # otherwise start-stop-daemon would capture the setsid pid not the actual program
+
+               prog=$1; shift
+               /usr/bin/setsid \
+               /sbin/start-stop-daemon -q --start \
+                       --nicelevel $nice \
+                       ${pidfile:+--pidfile $pidfile} \
+                       ${makepid:+--make-pidfile} \
+                       ${user:+--chuid $user} \
+                       ${chdir:+--chdir "$chdir"} \
+                       ${fork:+--background} \
+                       ${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \
+                       --exec "$prog" \
+                       -- "$@"
+       else
+               if [ "$fork" = "1" ]; then
+                       export PIDFILE="/dev/null"
+                       if [ "$makepid" ] && [ "$pidfile" ]; then
+                               export PIDFILE="$pidfile"
+                       fi
+                       set -- /lib/rc-scripts/makepid "$@"
+                       set -- /usr/bin/setsid "$@"
+               fi
+               if [ -n "$user" -a "$user" != "root" ]; then
+                       set -- /bin/runuser -u "$user" -- "$@"
+               fi
+
+               nice -n $nice initlog -c "$*" 2>&1 </dev/null
+       fi
+}
+
 # A function to start a program (now it's useful on read-only filesystem too)
 daemon() {
-       local errors="" prog="" end="" waitname="" waittime=""
+       local errors="" waitname="" waittime=0
        local exit_code=0
        local nice=$SERVICE_RUN_NICE_LEVEL
        local fork user closefds redirfds pidfile makepid chdir=/
 
-       # NOTE: if you wonder how the shellish (by syntax) $prog works in ssd mode,
-       # then the answer is: it totally ignores $prog and uses "$@" itself.
-
        while [ $# -gt 0 ]; do
                case $1 in
                '')
@@ -647,7 +729,6 @@ daemon() {
                        ;;
                --fork)
                        fork=1
-                       end='&'
                        ;;
                --chdir)
                        shift
@@ -678,6 +759,8 @@ daemon() {
                        ;;
                --makepid)
                        makepid=1
+                       # makepid implies fork
+                       fork=1
                        ;;
                -*|+*)
                        nice=$1
@@ -690,19 +773,6 @@ daemon() {
                esac
                shift
        done
-       if [ -n "$user" -a "$user" != "root" ]; then
-               prog="/bin/su $user -s /bin/sh -c \""
-       fi
-       if [ "$fork" = "1" ]; then
-               prog="/usr/bin/setsid ${prog:-sh -c \"}"
-       fi
-       # If command to execute ends with quotation mark, add remaining
-       # arguments and close quotation.
-       if [ "$prog" != "${prog%\"}" ]; then
-               prog="$prog $*$end\""
-       else
-               prog="$prog $*$end"
-       fi
 
        _daemon_set_ulimits
 
@@ -713,69 +783,11 @@ daemon() {
        busy
        cd $chdir
        [ -n "$SERVICE_CPUSET" ] && is_yes "$CPUSETS" && echo $$ > "/dev/cpuset/${SERVICE_CPUSET}/tasks"
-       if errors=$(
-               umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK};
-               export USER=root HOME=/tmp TMPDIR=/tmp
-
-               nice=${nice:-$DEFAULT_SERVICE_RUN_NICE_LEVEL}
-               nice=${nice:-0}
-
-               # make nice level absolute, not to be dependant of nice level of shell where service started
-               nice=$(($nice - $(nice)))
-
-               if [ "$closefds" = 1 ]; then
-                       exec 1>&-
-                       exec 2>&-
-                       exec 0>&-
-               elif [ "$redirfds" = 1 ]; then
-                       exec 1>/dev/null
-                       exec 2>/dev/null
-                       exec 0>/dev/null
-               else
-                       exec 2>&1
-               fi
-
-               if is_no "$RC_LOGGING"; then
-                       prog=$1; shift
-                       if [ ! -x $prog ]; then
-                               logger -t rc-scripts -p daemon.debug "daemon: Searching PATH for $prog, consider using full path in initscript"
-                               local a o=$IFS
-                               IFS=:
-                               for a in $PATH; do
-                                       if [ -x $a/$prog ]; then
-                                               prog=$a/$prog
-                                               break
-                                       fi
-                               done
-                               IFS=$o
-                       fi
-                       /sbin/start-stop-daemon -q --start \
-                               --nicelevel $nice \
-                               ${pidfile:+--pidfile $pidfile} \
-                               ${makepid:+--make-pidfile} \
-                               ${user:+--chuid $user} \
-                               ${chdir:+--chdir "$chdir"} \
-                               ${fork:+--background} \
-                               ${waitname:+--name $waitname} \
-                               ${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \
-                               --exec "$prog" \
-                               -- ${1:+"$@"}
-               else
-                       nice -n $nice initlog -c "$prog" 2>&1 </dev/null
-               fi
-               ); then
-
-               if [ -n "$waitname" -a -n "$waittime" ]; then
-                       # Save basename.
-                       base=${waitname##*/}
-                       # Find pid.
-                       pid=$(pidofproc "$waitname" "$pidfile")
-                       [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile")
-                       i=0
-                       while [ "$i" -lt "$waittime" ]; do
-                               i=$((i + 1))
-                               checkpid $pid && sleep 1 || break
-                       done
+       if errors=$(_daemon_exec "$@"); then
+               # wait for process (or pidfile) to be created
+               if [ "$waittime" -gt 0 ]; then
+                       # waitname can be empty, as if pidfile is in use, it is not relevant
+                       waitproc "$waittime" "$waitname" "$pidfile"
                fi
                log_success "$1 startup"
                ok
@@ -788,6 +800,28 @@ daemon() {
        return $exit_code
 }
 
+# wait (in seconds) for process (or pidfile) to be created
+# example: waitproc 30 httpd /var/run/httpd.pid
+waitproc() {
+       local waittime=$1 procname=$2 pidfile=$3
+       local pid
+       local now=$(date +%s)
+       local maxtime=$(($now + $waittime))
+
+       if [ -z "$procname" -a -z "$pidfile" ]; then
+               msg_usage "waitproc: procname or pidfile must be specified"
+               return 2
+       fi
+
+       while [ "$(date +%s)" -lt "$maxtime" ]; do
+               pid=$(pidofproc "$procname" "$pidfile")
+               [ -n "$pid" ] && break
+
+               # start-stop-daemon uses same delay
+               usleep 20000
+       done
+}
+
 # A function to stop a program.
 killproc() {
        local notset killlevel base pid pidfile result delay=3 try
@@ -833,16 +867,25 @@ killproc() {
        # works only with pidfile
        if is_no "$RC_LOGGING" && [ "$pidfile" ]; then
                local sig=${killlevel:--TERM} retry
-               # retry only if signal is not specified,
+               # do not retry if signal is specified,
                # as otherwise impossible to send HUP if process pid stays in pidfile.
-               if [ "${killlevel+set}" = "set" ]; then
+               # however, do retry if --waitfortime was specified
+               if [ "${killlevel+set}" = "set" ] && [ -z "$waittime" ]; then
                        # if we send HUP it's ok if process does not die
                        retry="--oknodo"
                else
-                       retry="--retry ${sig#-}/10/${sig#-}/60/KILL/10"
+                       local waitretry
+                       : ${waittime=10}
+                       : ${waitretry=$(($waittime * 2))}
+
+                       # 1. kill with $sig, wait $delay
+                       # 2. kill with $sig, wait $waittime
+                       # 3. kill with KILL, wait $waitretry
+                       retry="--retry ${sig#-}/${delay}/${sig#-}/${waittime}/KILL/${waitretry}"
                fi
                /sbin/start-stop-daemon -q --stop \
                        $retry \
+                       ${waitname:+--name $waitname} \
                        -s ${sig#-} \
                        ${pidfile:+--pidfile $pidfile}
                result=$?
@@ -957,14 +1000,17 @@ pidofproc() {
                *) pidfile="/var/run/$pidfile";;
        esac
        if [ -f "${pidfile}" ]; then
-               local p pid=""
+               local p
                for p in $(< "${pidfile}"); do
                        [ -z "$(echo "$p" | awk '{gsub(/[0-9]/,"");print;}')" ] && pid="$pid $p"
                done
        fi
 
-       # Next try "pidof"
-       [ -z "$pid" ] && pidof -o $$ -o $PPID -o %PPID -x "$1"
+       # Next try "pidof" if pidfile is not specified
+       if [ -z "$pid" ] && [ -z "$2" ]; then
+               pid=$(pidof -o $$ -o $PPID -o %PPID -x "$1")
+       fi
+
        pid=$(filter_chroot $pid)
        echo $pid
 }
@@ -1289,239 +1335,32 @@ rc_gettext_init() {
 }
 
 use_upstart () {
-       # True when upstart-event-based boot should be used
-       is_yes "$USE_UPSTART" && return 0
-       is_no "$USE_UPSTART" && return 1
-       if [ ! -x /sbin/initctl ] ; then
-               USE_UPSTART="no"
-               return 1
-       fi
-       local cmdline=$(cat /proc/cmdline 2>/dev/null)
-       if strstr "$cmdline" "pld.no-upstart" ; then
-               USE_UPSTART="no"
-               return 1
-       else
-               USE_UPSTART="yes"
-               return 0
-       fi
+       return 1
 }
-
 emit () {
-       # emit upstart signal
-       # only when 'upstart' boot is enabled
-       use_upstart || return 0
-       /sbin/initctl emit "$@"
+       return 0
 }
-
 is_upstart_task() {
-       # Return 0 if the given service is an upstart task.
-       grep -q '^task' "/etc/init/$1.conf"
+       return 1
 }
 is_upstart_running() {
-       # Return 0 if the given service is running via upstart
-       initctl status "$1" 2>/dev/null | grep -q running
+       return 1
 }
 upstart_start() {
-       local service=$1
-       if is_upstart_running "${service}"; then
-               msg_already_running "$service"
-               return 0
-       fi
-
-       msg_starting "${service}"
-       if errors=$(/sbin/initctl start ${service} 2>&1) ; then
-               ok
-               return 0
-       else
-               fail
-               echo "$errors" >&2
-               return 1
-       fi
+       return 1
 }
 upstart_stop() {
-       local service=$1
-       if ! is_upstart_running "${service}"; then
-               msg_not_running "$name"
-               return 0
-       fi
-       msg_stopping "${service}"
-       if errors=$(/sbin/initctl stop ${service}) ; then
-               ok
-               return 0
-       else
-               fail
-               echo "$errors" >&2
-               return 1
-       fi
+       return 1
 }
 upstart_reload() {
-       local service=$1
-       if ! is_upstart_running "${service}" && ! is_upstart_task "${service}" ; then
-               return 0
-       fi
-       msg_reloading "${service}"
-       if errors=$(/sbin/initctl reload ${service}) ; then
-               ok
-               return 0
-       else
-               fail
-               echo "$errors" >&2
-               return 1
-       fi
+       return 0
 }
 upstart_status() {
-       # get service status
-       # should be compliant with
-       # http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
-       local service=$1
-       local status
-       if is_upstart_task "${service}" ; then
-               # we probably should have a way to handle task status
-               return 0
-       fi
-       if ! status=$(/sbin/initctl status "${service}") ; then
-               # program or service status is not known
-               return 4
-       fi
-       if strstr "$status" "running" ; then
-               # program is running or service is OK
-               echo "$status"
-               return 0
-       else
-               # program is not running
-               echo "$status"
-               return 3
-       fi
-       # TODO: other statuses
+       return 1
 }
-
 _upstart_controlled() {
-       # If the service is to be handled by upstart
-       # execute the start/stop/etc. commands the upstart way
-       if ! use_upstart; then
-               return 0
-       fi
-       local script=$1
-       shift
-       local command=$1
-       [ $# -gt 0 ] && shift
-       local name=$(basename "$script")
-       if [ ! -f /etc/init/${name}.conf ] ; then
-               return 0
-       fi
-       local commands
-       local extra_commands
-       local has_configtest
-       if [ "$1" = "--except" ] ; then
-               shift
-               commands="$*"
-               for cmd in $commands ; do
-                       if [ "$command" = "$cmd" ] ; then
-                               return 0
-                       fi
-                       case "$cmd" in
-                               start|stop|status|reload|restart|try-restart|force-reload)
-                                       ;;
-                               configtest)
-                                       has_configtest=yes
-                                       extra_commands="|$cmd"
-                                       ;;
-                               *)
-                                       extra_commands="|$cmd"
-                                       ;;
-                       esac
-               done
-       elif [ -n "$*" ] ; then
-               commands="$*"
-               local cmd
-               local found=0
-               # is there a better way
-               for cmd in $commands ; do
-                       if [ "$command" = "$cmd" ] ; then
-                               found=1
-                               break;
-                       fi
-               done
-               if [ $found = 0 ] ; then
-                       # let the script handle it
-                       return 0
-               fi
-       fi
-       case "$command" in
-               start)
-                       upstart_start $name
-                       exit $?
-                       ;;
-               stop)
-                       upstart_stop $name
-                       exit $?
-                       ;;
-               status)
-                       upstart_status $name
-                       exit $?
-                       ;;
-               restart)
-                       if is_yes "$has_configtest" ; then
-                               "$script" configtest || exit 1
-                       fi
-                       upstart_stop $name
-                       upstart_start $name
-                       exit $?
-                       ;;
-               try-restart)
-                       if ! is_upstart_running "$name" ; then
-                               exit 0
-                       fi
-                       if is_yes "$has_configtest" ; then
-                               "$script" configtest || exit 1
-                       fi
-                       upstart_stop $name
-                       upstart_start $name
-                       exit $?
-                       ;;
-               reload)
-                       if is_yes "$has_configtest" ; then
-                               "$script" configtest || exit 1
-                       fi
-                       if is_upstart_task "$name" ; then
-                               nls "$command not implemented for $name"
-                               exit 3
-                       else
-                               upstart_reload "$name"
-                               exit $?
-                       fi
-                       ;;
-               force-reload)
-                       if is_yes "$has_configtest" ; then
-                               "$script" configtest || exit 1
-                       fi
-                       if is_upstart_task "$name" ; then
-                               upstart_stop "$name"
-                               upstart_start "$name"
-                               exit $?
-                       else
-                               upstart_reload "$name"
-                               exit $?
-                       fi
-                       ;;
-               *)
-                       msg_usage "$0 {start|stop|restart|reload|force-reload|status$extra_commands}"
-                       exit 3
-                       ;;
-       esac
-       return 1 # should not happen
+       return 0
 }
-
-# Usage:
-#      somewhere at the begining of init script:
-#     upstart_controlled
-#              - to pass implement all upstart commands via initctl
-#                 start, stop, status, restart, reload and force_reload
-#                are implemented
-#     upstart_controlled command...
-#              - to pass handle only specific commands the upstart way
-#                 and leave the rest to the script
-#
 alias upstart_controlled='_upstart_controlled $0 "$@"'
 
 rc_gettext_init
This page took 0.127649 seconds and 4 git commands to generate.