]> git.pld-linux.org Git - projects/rc-scripts.git/blob - lib/functions
Fedora compat: fix echo_success and echo_failure formatting
[projects/rc-scripts.git] / lib / functions
1 #!/bin/sh - keep it for file(1) to get bourne shell script result
2 # functions     This file contains functions to be used by most or all
3 #               shell scripts in the /etc/rc.d/init.d directory.
4 #
5 # $Id$
6 #
7 # Author:       Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
8 # Hacked by:    Greg Galloway and Marc Ewing
9 # Modified for PLD Linux by:
10 #               Marek Obuchowicz <elephant@pld-linux.org>
11 #               Arkadiusz Miśkiewicz <misiek@pld-linux.org>
12 #               Michał Kochanowicz <mkochano@pld-linux.org>
13 #               Łukasz Pawelczyk <havner@pld-linux.org>
14
15 # First set up a default search path.
16 export PATH="/sbin:/usr/sbin:/bin:/usr/bin"
17
18 # Set defaults
19 if [ -z "$COLUMNS" -o -z "$LINES" ]; then
20         _setterm() {
21                 set -- $(stty size 2>/dev/null)
22                 LINES=${LINES:-$1}
23                 COLUMNS=${COLUMNS:-$2}
24         }
25         _setterm
26         unset _setterm
27 fi
28 [ -z "$LINES" ] || [ "$LINES" -le 0 ] && LINES=40
29 [ -z "$COLUMNS" ] || [ "$COLUMNS" -le 0 ] && COLUMNS=80
30 export LINES COLUMNS
31 INIT_COL=$((COLUMNS - 13))
32
33 # Set colors
34 RED=1
35 GREEN=2
36 YELLOW=3
37 BLUE=4
38 MAGENTA=5
39 CYAN=6
40 WHITE=7
41 NORMAL=15
42 # Bold definition (second parameter to termput setaf)
43 BOLD=1
44 NOBOLD=0
45 # Default colors
46 CBRACKETS="$CYAN"       # brackets [ ] color
47 CDONE="$GREEN"          # DONE and WORK color
48 CBUSY="$MAGENTA"        # BUSY color
49 CFAIL="$RED"            # FAIL and DIED color
50 CPOWEREDBY="$CYAN"      # "Powered by" color
51 CPLD="$GREEN"           # "PLD Linux Distribution" color
52 CI="$RED"               # Capital I color (press I to enter interactive startup)
53 CRESMAN="$GREEN"        # "Resource Manager" color
54 CHARS=""                # Characters displayed on the beginning of show line
55 CCHARS="$NORMAL"        # Color of these characters (look at /etc/sysconfig/init-colors.gentoo example)
56
57 # save from env, set by /sbin/service
58 env_upstart=$USE_UPSTART
59
60 # Source configuration if available - may override default values
61 [ -r /etc/sysconfig/init-colors ] && . /etc/sysconfig/init-colors
62 [ -r /etc/sysconfig/system ] && . /etc/sysconfig/system
63 [ -r /etc/sysconfig/bootsplash ] && . /etc/sysconfig/bootsplash
64
65 # if initscript is invoked via bash, enable RedHat/Fedora compatibility
66 # RC_FEDORA is "set" if enabled and "unset" when not, but it's "value" is always empty
67 # this is useful for inline constructs
68 if [ "${BASH_VERSION+set}" = "set" ]; then
69         RC_LOGGING=yes
70         FASTRC=no
71         RC_FEDORA=
72 else
73         unset RC_FEDORA || :
74 fi
75
76 [ "$env_upstart" ] && USE_UPSTART=$env_upstart
77
78 if [ -z "$VSERVER" -o "$VSERVER" = "detect" ]; then
79         {
80                 while read _f _ctx; do
81                         [ "$_f" = "VxID:" -o "$_f" = "s_context:" ] && break
82                 done </proc/self/status
83         } 2>/dev/null
84         if [ -z "$_ctx" -o "$_ctx" = "0" ]; then
85                 VSERVER=no
86         else
87                 VSERVER=yes
88         fi
89         unset _f _ctx
90 fi
91
92 # VSERVER_ISOLATION_NET = isolation only inside of vserver guests
93 if [ -z "$VSERVER_ISOLATION_NET" -o "$VSERVER_ISOLATION_NET" = "detect" ]; then
94         VSERVER_ISOLATION_NET=no
95         if [ "$VSERVER" = "yes" ]; then
96                 if [ -f /proc/self/nsproxy ]; then
97                         {
98                                 while read _t _data; do
99                                         [ "$_t" = "net:" ] && break
100                                 done < /proc/self/nsproxy
101                         } 2> /dev/null
102                 else
103                         # assume old kernel mode
104                         VSERVER_ISOLATION_NET=yes
105                 fi
106                 if [ "${_data##*\(}" = "I)" ]; then
107                         VSERVER_ISOLATION_NET=yes
108                 fi
109                 unset _f _data
110         fi
111 fi
112
113 # we need to know in functions if we were called from a terminal
114 if [ -z "$ISATTY" ]; then
115         [ -t ] && ISATTY=yes || ISATTY=no
116         export ISATTY
117 fi
118
119 is_yes() {
120         # Test syntax
121         if [ $# = 0 ]; then
122                 msg_usage " is_yes {value}"
123                 return 2
124         fi
125
126         # Check value
127         case "$1" in
128         yes|Yes|YES|true|True|TRUE|on|On|ON|Y|y|1)
129                 # true returns zero
130                 return 0
131                 ;;
132         *)
133                 # false returns one
134                 return 1
135                 ;;
136         esac
137 }
138
139 is_no() {
140         # Test syntax
141         if [ $# = 0 ]; then
142                 msg_usage " is_no {value}"
143                 return 2
144         fi
145
146         case "$1" in
147         no|No|NO|false|False|FALSE|off|Off|OFF|N|n|0)
148                 # true returns zero
149                 return 0
150                 ;;
151         *)
152                 # false returns one
153                 return 1
154                 ;;
155         esac
156 }
157
158 # checks if file is empty
159 # empty lines and lines beginning with hash are ignored
160 is_empty_file() {
161         [ -s "$1" ] || return 0
162         grep -vqE "^(#|[[:blank:]]*$)" "$1" && return 1 || return 0
163 }
164
165 # returns OK if $1 contains $2
166 strstr() {
167         local a=$2
168         [ "${1#*$a*}" = "$1" ] && return 1
169         return 0
170 }
171
172 if is_yes "$FASTRC" || is_yes "$IN_SHUTDOWN"; then
173         RC_LOGGING=no
174 fi
175
176 if is_no "$RC_LOGGING"; then
177         initlog() {
178                 RESULT=0
179                 while [ "$1" != "${1##-}" ]; do
180                         case $1 in
181                         -c)
182                                 shift
183                                 $1
184                                 RESULT=$?
185                                 break
186                                 ;;
187                         *)
188                                 shift
189                                 ;;
190                         esac
191                 done
192                 return $RESULT
193         }
194 fi
195
196 kernelver() {
197         local _x _y _z v v1 old_IFS ver
198         {
199                 read _x _y v _z
200                 old_IFS=$IFS
201                 # strip _* or -* from versions like: "2.6.25_vanilla-1", "2.6.25-1"
202                 IFS='_-'
203                 set -- $v
204                 v1=${1}
205                 IFS='.'
206                 set -- $v1
207                 IFS=$old_IFS
208
209                 ver=${3}
210                 while [ ${#ver} -lt 3 ]; do ver="0$ver"; done
211                 ver="$2$ver"
212                 while [ ${#ver} -lt 6 ]; do ver="0$ver"; done
213                 ver="$1$ver"
214                 while [ ${#ver} -lt 9 ]; do ver="0$ver"; done
215                 echo $ver
216         } < /proc/version
217 }
218
219 kernelverser() {
220         local _x _y _z v v1 old_IFS ver
221         {
222                 read _x _y v _z
223                 old_IFS=$IFS
224                 # strip _* or -* from versions like: "2.6.25_vanilla-1", "2.6.25-1"
225                 IFS='_-'
226                 set -- $v
227                 v1=${1}
228                 IFS='.'
229                 set -- $v1
230                 IFS=$old_IFS
231                 ver=$2
232                 while [ ${#ver} -lt 3 ]; do ver="0$ver"; done
233                 ver="$1$ver"
234                 while [ ${#ver} -lt 6 ]; do ver="0$ver"; done
235                 echo $ver
236         } </proc/version
237 }
238
239 kernelvermser() {
240         local _x _y _z v v1 old_IFS ver
241         {
242                 read _x _y v _z
243                 old_IFS=$IFS
244                 # strip _* or -* from versions like: "2.6.25_vanilla-1", "2.6.25-1"
245                 IFS='_-'
246                 set -- $v
247                 v1=${1}
248                 IFS='.'
249                 set -- $v1
250                 IFS=$old_IFS
251                 ver="$1"
252                 while [ ${#ver} -lt 3 ]; do ver="0$ver"; done
253                 echo $ver
254         } </proc/version
255 }
256
257 # Colors workaround
258 termput() {
259         is_yes "$ISATTY" || return
260
261         if is_yes "$FASTRC" || is_no "$TPUT"; then
262                 case "$1" in
263                 hpa)
264                         echo -ne "\033[$(($2+1))G"
265                         ;;
266                 cuu*)
267                         echo -ne "\033[${2}A"
268                         ;;
269                 el)
270                         echo -ne "\033[0K"
271                         ;;
272                 setaf)
273                         local ISBOLD
274                         if [ -n "$3" ]; then
275                                 ISBOLD="$3"
276                         else
277                                 ISBOLD="$NOBOLD";
278                         fi
279                         is_yes "$COLOR_INIT" && echo -ne "\033[${ISBOLD};3${2}m"
280                         ;;
281                 op)
282                         termput setaf $NORMAL
283                         ;;
284                 esac
285         else
286                 case "$1" in
287                 hpa | cuu* | el)
288                         tput "$@"
289                         ;;
290                 setaf)
291                         if [ "$3" = "1" ]; then tput bold; else tput sgr0; fi
292                         is_yes "$COLOR_INIT" && tput setaf "$2"
293                         ;;
294                 op)
295                         termput setaf $NORMAL
296                         ;;
297                 esac
298         fi
299 }
300
301 if [ ! -x /bin/printf ]; then
302         # printf equivalent
303         # FIXME: buggy when single or double quotes in message!
304         printf() {
305                 local text m
306                 text="$1"
307                 shift
308                 if [ $# -gt 0 ]; then
309                         m="$1"
310                         shift
311                         while [ $# -gt 0 ]; do
312                                 m="$m\",\"$1"
313                                 shift
314                         done
315                 fi
316                 awk "BEGIN {printf \"$text\", \"$m\"; }"
317         }
318 fi
319
320 # National language support function
321 nls() {
322         local msg_echo nls_domain text message
323         msg_echo='\n'
324         nls_domain="$NLS_DOMAIN"
325         while [ "$1" != "${1##-}" ]; do
326                 case "$1" in
327                 --nls-domain)
328                         shift
329                         nls_domain="$1"
330                         shift
331                         ;;
332                 -n)
333                         msg_echo=''
334                         shift
335                         ;;
336                 esac
337         done
338         message="$1"
339         shift
340
341         # empty message, so we return --misiek
342         if [ -z "$message" ]; then
343                 echo -en "$msg_echo"
344                 return
345         fi
346
347         if is_yes "$GETTEXT"; then
348                 message=$(TEXTDOMAINDIR="/etc/sysconfig/locale" gettext -e --domain="${nls_domain:-rc-scripts}" "$message")
349         fi
350
351         printf "$message" "$@"
352         echo -en "$msg_echo"
353 }
354
355 rc_splash() {
356         local action="$1"
357
358         if ! is_no "$BOOT_SPLASH" && ! is_yes "$VSERVER"; then
359                 [ -x /bin/splash ] && /bin/splash "$action"
360         fi
361
362         : $((progress++))
363 }
364
365 msg_network_down() {
366         nls "ERROR: Networking is down. %s can't be run." "$1" >&2
367 }
368
369 msg_starting() {
370         show "Starting %s service" "$1"
371 }
372
373 msg_already_running() {
374         nls "%s service is already running." "$1"
375 }
376
377 msg_stopping() {
378         show "Stopping %s service" "$1"
379 }
380
381 msg_not_running() {
382         nls "%s service is not running." "$1"
383 }
384
385 msg_reloading() {
386         show "Reloading %s service" "$1"
387 }
388
389 msg_usage() {
390         nls "Usage: %s" "$*"
391 }
392
393 # Some functions to handle PLD Linux-style messages
394 show() {
395         local text len
396
397         if is_no "$FASTRC" && is_yes "$GETTEXT"; then
398                 text=$(nls -n "$@")
399         else
400                 text=$(printf "$@")
401         fi
402         len=${#text}
403         while [ $((len++)) -lt $INIT_COL ]; do
404                 text="$text."
405         done
406         if [ -n "$CHARS" ]; then
407                 termput setaf $CCHARS
408                 echo -n "$CHARS"
409                 termput op
410         fi
411         echo -n "$text"
412 }
413
414 deltext() {
415         termput hpa $INIT_COL
416 }
417
418 # Displays message in square brackests ("[ DONE ]"). Takes two arguments.
419 # First is the text to display, second is color number to use (argument to
420 # tput setaf). If second argument is not given, default (2, green) will be
421 # used).
422 progress() {
423         local COLOR
424         if [ -n "$2" ]; then
425                 COLOR="$2"
426         else
427                 COLOR="$CDONE"
428         fi
429         deltext
430         echo -n "$(termput setaf $CBRACKETS)[$(termput setaf $COLOR) $(nls --nls-domain rc-scripts "$1") $(termput setaf $CBRACKETS)]$(termput op)"
431 }
432
433 busy() {
434         echo -n "$_busy"
435 }
436
437 ok() {
438         echo -ne "$_ok${RC_FEDORA+\r}${RC_FEDORA-\n}"
439 }
440
441 started() {
442         echo "$_started"
443 }
444
445 fail() {
446         echo -ne "$_fail${RC_FEDORA+\r}${RC_FEDORA-\n}"
447         return 1
448 }
449
450 died() {
451         echo "$_died"
452         return 1
453 }
454
455 # Check if $pid (could be plural) are running
456 checkpid() {
457         while [ "$1" ]; do
458                 [ -d "/proc/$1" ] && return 0
459                 shift
460         done
461         return 1
462 }
463
464 # - outside chroot get only those processes, which are outside chroot.
465 # - inside chroot get only those processes, which are inside chroot.
466 # - don't filter out pids which do not have corresponding running processes (process died etc)
467 # (note: some processes like named are chrooted but run outside chroot)
468 # - do nothing inside vserver
469 filter_chroot() {
470         if is_yes "$VSERVER"; then
471                 echo $@
472                 return
473         fi
474         if [ $# -lt 1 -o ! -d /proc/1 ]; then
475                 echo $@
476                 return
477         fi
478         local root_dir good_pids="" good_add_pid
479         for root_pid in $@; do
480                 root_dir=$(resolvesymlink /proc/${root_pid}/root)
481                 if [ -n "$root_dir" ]; then
482                         good_add_pid=1
483                         if [ -n "${SYSTEM_CHROOTS}" ]; then
484                                 for r_dir in ${SYSTEM_CHROOTS}; do
485                                         echo "$root_dir" | grep -q "^${r_dir}" && good_add_pid=0
486                                 done
487                         fi
488                         [ "$good_add_pid" -eq 1 ] && good_pids="$good_pids $root_pid"
489                 elif [ ! -d "/proc/$root_pid" ]; then
490                         good_pids="$good_pids $root_pid"
491                 fi
492         done
493         echo $good_pids
494 }
495
496 # Usage:
497 # run_cmd Message command_to_run
498 # run_cmd -a Message command_to_run
499 # run_cmd --user "username" "Message" command_to_run
500 run_cmd() {
501         local force_err=0 exit_code=0 errors user
502         while [ $# -gt 0 ]; do
503                 case "$1" in
504                 -a)
505                         force_err=1
506                         ;;
507                 --user)
508                         shift
509                         user=$1
510                         ;;
511                 *)
512                         break
513                 esac
514                 shift
515         done
516
517         local message=$1; shift
518         show "$message"; busy
519
520         if errors=$(
521                 cd /
522                 export HOME=/tmp TMPDIR=/tmp
523                 if is_no "$RC_LOGGING"; then
524                         ${user:+setuidgid -s $user} "$@" 2>&1
525                 else
526                         ${user:+setuidgid -s $user} initlog -c "$*" 2>&1
527                 fi
528                 ); then
529                 ok
530                 log_success "$1 $message"
531         else
532                 fail
533                 log_failed "$1 $message"
534                 exit_code=1
535         fi
536         [ -n "$errors" ] && [ $exit_code -eq 1 -o $force_err -eq 1 ] && echo "$errors"
537         return $exit_code
538 }
539
540 _daemon_set_ulimits() {
541         local opt val ksh=${KSH_VERSION:+1}
542         set -- ${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS}
543         while [ $# -gt 0 ]; do
544                 opt=$1
545                 val=$2
546                 if [ "$ksh" ]; then
547                         case "$opt" in
548                         -Hu)
549                                 opt=-Hp
550                         ;;
551                         -Su)
552                                 opt=-Sp
553                         ;;
554                         -u)
555                                 opt=-p
556                         ;;
557                         esac
558                 fi
559                 ulimit $opt $val
560                 shift 2
561         done
562 }
563
564 # A function to start a program (now it's useful on read-only filesystem too)
565 daemon() {
566         local errors="" prog="" end="" waitname="" waittime=""
567         local exit_code=0
568         local nice=$SERVICE_RUN_NICE_LEVEL
569         local fork user closefds redirfds pidfile makepid chdir=/
570
571         # NOTE: if you wonder how the shellish (by syntax) $prog works in ssd mode,
572         # then the answer is: it totally ignores $prog and uses "$@" itself.
573
574         while [ $# -gt 0 ]; do
575                 case $1 in
576                 '')
577                 msg_usage " daemon [--check] [--user user] [--fork] [--chdir directory] [--closefds] [--redirfds] [--waitforname procname] [--waitfortime seconds] [--pidfile file] [--makepid] [+/-nicelevel] {program} <program args>"
578                         return 2
579                         ;;
580                 --check)
581                         # for compatibility with redhat/mandrake
582                         nls "warning: --check option is ignored!"
583                         shift
584                         ;;
585                 --user)
586                         shift
587                         user=$1
588                         ;;
589                 --fork)
590                         fork=1
591                         end='&'
592                         ;;
593                 --chdir)
594                         shift
595                         chdir=$1
596                         ;;
597                 --closefds)
598                         closefds=1
599                         ;;
600                 --redirfds)
601                         redirfds=1
602                         ;;
603                 --waitforname)
604                         shift
605                         waitname="$1"
606                         ;;
607                 --waitfortime)
608                         shift
609                         waittime="$1"
610                         ;;
611                 --pidfile=?*)
612                         pidfile="${1#--pidfile=}"
613                         case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac
614                         ;;
615                 --pidfile)
616                         shift
617                         pidfile="$1"
618                         case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac
619                         ;;
620                 --makepid)
621                         makepid=1
622                         ;;
623                 -*|+*)
624                         nice=$1
625                         shift
626                         break
627                         ;;
628                 *)
629                         break
630                         ;;
631                 esac
632                 shift
633         done
634         if [ -n "$user" -a "$user" != "root" ]; then
635                 prog="/bin/su $user -s /bin/sh -c \""
636         fi
637         if [ "$fork" = "1" ]; then
638                 prog="/usr/bin/setsid ${prog:-sh -c \"}"
639         fi
640         # If command to execute ends with quotation mark, add remaining
641         # arguments and close quotation.
642         if [ "$prog" != "${prog%\"}" ]; then
643                 prog="$prog $*$end\""
644         else
645                 prog="$prog $*$end"
646         fi
647
648         _daemon_set_ulimits
649
650         [ -z "$DEFAULT_SERVICE_UMASK" ] && DEFAULT_SERVICE_UMASK=022
651         [ -z "$DEFAULT_SERVICE_RUN_NICE_LEVEL" ] && DEFAULT_SERVICE_RUN_NICE_LEVEL=0
652
653         # And start it up.
654         busy
655         cd $chdir
656         [ -n "$SERVICE_CPUSET" ] && is_yes "$CPUSETS" && echo $$ > "/dev/cpuset/${SERVICE_CPUSET}/tasks"
657         if errors=$(
658                 umask ${SERVICE_UMASK:-$DEFAULT_SERVICE_UMASK};
659                 export USER=root HOME=/tmp TMPDIR=/tmp
660
661                 nice=${nice:-$DEFAULT_SERVICE_RUN_NICE_LEVEL}
662                 nice=${nice:-0}
663
664                 # make nice level absolute, not to be dependant of nice level of shell where service started
665                 nice=$(($nice - $(nice)))
666
667                 if [ "$closefds" = 1 ]; then
668                         exec 1>&-
669                         exec 2>&-
670                         exec 0>&-
671                 elif [ "$redirfds" = 1 ]; then
672                         exec 1>/dev/null
673                         exec 2>/dev/null
674                         exec 0>/dev/null
675                 else
676                         exec 2>&1
677                 fi
678
679                 if is_no "$RC_LOGGING"; then
680                         prog=$1; shift
681                         if [ ! -x $prog ]; then
682                                 logger -t rc-scripts -p daemon.debug "daemon: Searching PATH for $prog, consider using full path in initscript"
683                                 local a o=$IFS
684                                 IFS=:
685                                 for a in $PATH; do
686                                         if [ -x $a/$prog ]; then
687                                                 prog=$a/$prog
688                                                 break
689                                         fi
690                                 done
691                                 IFS=$o
692                         fi
693                         /sbin/start-stop-daemon -q --start \
694                                 --nicelevel $nice \
695                                 ${pidfile:+--pidfile $pidfile} \
696                                 ${makepid:+--make-pidfile} \
697                                 ${user:+--chuid $user} \
698                                 ${chdir:+--chdir "$chdir"} \
699                                 ${fork:+--background} \
700                                 ${waitname:+--name $waitname} \
701                                 ${SERVICE_DROPCAPS:+--dropcap $SERVICE_DROPCAPS} \
702                                 --exec "$prog" \
703                                 -- ${1:+"$@"}
704                 else
705                         nice -n $nice initlog -c "$prog" 2>&1 </dev/null
706                 fi
707                 ); then
708
709                 if [ -n "$waitname" -a -n "$waittime" ]; then
710                         # Save basename.
711                         base=${waitname##*/}
712                         # Find pid.
713                         pid=$(pidofproc "$waitname" "$pidfile")
714                         [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile")
715                         i=0
716                         while [ "$i" -lt "$waittime" ]; do
717                                 i=$((i + 1))
718                                 checkpid $pid && sleep 1 || break
719                         done
720                 fi
721                 log_success "$1 startup"
722                 ok
723         else
724                 exit_code=1
725                 fail
726                 log_failed "$1 startup"
727                 [ -n "$errors" ] && echo >&2 "$errors"
728         fi
729         return $exit_code
730 }
731
732 # A function to stop a program.
733 killproc() {
734         local notset killlevel base pid pidfile result delay=3 try
735         # Test syntax.
736         if [ $# = 0 ]; then
737                 msg_usage " killproc [--pidfile|-p PIDFILE] [-d DELAY] {program} [-SIGNAME]"
738                 return 2
739         fi
740
741         while [ "$1" != "${1##-}" ]; do
742                 case $1 in
743                 -d)
744                         delay="$2"
745                         shift 2
746                         ;;
747                 --pidfile|-p)
748                         pidfile="$2"
749                         case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac
750                         shift 2
751                         ;;
752                 --waitforname)
753                         waitname="$2"
754                         shift 2
755                         ;;
756                 --waitfortime)
757                         waittime="$2"
758                         shift 2
759                         ;;
760                 esac
761         done
762
763         busy
764
765         local notset=0
766         # check for second arg to be kill level
767         if [ -n "$2" ]; then
768                 killlevel=$2
769         else
770                 notset=1
771         fi
772
773         # experimental start-stop-daemon based killing.
774         # works only with pidfile
775         if is_no "$RC_LOGGING" && [ "$pidfile" ]; then
776                 local sig=${killlevel:--TERM} retry
777                 # retry only if signal is not specified,
778                 # as otherwise impossible to send HUP if process pid stays in pidfile.
779                 if [ "${killlevel+set}" = "set" ]; then
780                         # if we send HUP it's ok if process does not die
781                         retry="--oknodo"
782                 else
783                         retry="--retry ${sig#-}/10/${sig#-}/60/KILL/10"
784                 fi
785                 /sbin/start-stop-daemon -q --stop \
786                         $retry \
787                         -s ${sig#-} \
788                         ${pidfile:+--pidfile $pidfile}
789                 result=$?
790                 if [ "$result" -eq 0 ]; then
791                         ok
792                 else
793                         fail
794                 fi
795                 return $result
796         fi
797
798
799         # Save basename.
800         base=${1##*/}
801
802         # Find pid.
803         pid=$(pidofproc "$1" "$pidfile")
804         [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile")
805
806         # Kill it.
807         if [ -n "$pid" -a "$pid" != "$$" ] && checkpid $pid 2>&1; then
808                 if [ "$notset" = "1" ]; then
809                         if checkpid $pid 2>&1; then
810                                 # TERM first, then KILL if not dead
811                                 kill -TERM $pid
812                                 usleep 50000
813
814                                 try=0
815                                 while [ $try -lt $delay ]; do
816                                         checkpid $pid || break
817                                         sleep 1
818                                         try=$((try+1))
819                                 done
820                                 if checkpid $pid; then
821                                         # XXX: SIGKILL is sent already on 4th second!
822                                         # HARMFUL for example to mysqld (which is already workarounded)
823                                         kill -KILL $pid
824                                         usleep 50000
825                                 fi
826                         fi
827                         checkpid $pid
828                         result=$?
829                         if [ "$result" -eq 0 ]; then
830                                 fail
831                                 log_failed "$1 shutdown"
832                         else
833                                 ok
834                                 log_success "$1 shutdown"
835                         fi
836                         result=$(( ! $result ))
837                 else
838                         # use specified level only
839                         if checkpid $pid > /dev/null 2>&1; then
840                                 kill $killlevel $pid
841                                 result=$?
842                                 if [ "$result" -eq 0 ]; then
843                                         ok
844                                         log_success "$1 got $killlevel"
845                                 else
846                                         result=7
847                                         fail
848                                         log_failed "$1 didn't get $killlevel"
849                                 fi
850                         else
851                                 result=7
852                                 died
853                                 log_failed "$1 shutdown"
854                         fi
855                 fi
856         else
857                 died
858                 log_failed "$1 shutdown"
859                 result=7
860         fi
861
862         if [ -n "$waitname" -a -n "$waittime" ]; then
863                 # Save basename.
864                 base=${waitname##*/}
865                 # Find pid.
866                 pid=$(pidofproc "$waitname" "$pidfile")
867                 [ -z "$pid" ] && pid=$(pidofproc "$base" "$pidfile")
868                 i=0
869                 while [ "$i" -lt "$waittime" ]; do
870                         i=$(( i + 1 ))
871                         checkpid $pid && sleep 1 || break
872                 done
873         fi
874
875         # Remove pid file if any.
876         if [ "$notset" = "1" ]; then
877                 rm -f /var/run/${base}.pid
878         fi
879
880         return $result
881 }
882
883 # A function to find the pid of a program.
884 pidofproc() {
885         local pid pidfile base=${1##*/}
886         pidfile="$base.pid"
887         [ -n "$2" ] && pidfile="$2"
888
889         # Test syntax.
890         if [ $# = 0 ]; then
891                 msg_usage " pidofproc {program}"
892                 return 2
893         fi
894
895         # First try pidfile or "/var/run/*.pid"
896         case "$pidfile" in
897                 /*)pidfile="${pidfile}";;
898                 *) pidfile="/var/run/$pidfile";;
899         esac
900         if [ -f "${pidfile}" ]; then
901                 local p pid=""
902                 for p in $(< "${pidfile}"); do
903                         [ -z "$(echo "$p" | awk '{gsub(/[0-9]/,"");print;}')" ] && pid="$pid $p"
904                 done
905         fi
906
907         # Next try "pidof"
908         [ -z "$pid" ] && pidof -o $$ -o $PPID -o %PPID -x "$1"
909         pid=$(filter_chroot "$pid")
910         echo $pid
911 }
912
913 # status [--pidfile PIDFILE] {subsys} [{daemon}]"
914 status() {
915         local pid subsys daemon cpuset_msg pidfile
916         if [ "$1" = "--pidfile" -o "$1" = "-p" ]; then
917                 pidfile=$2
918                 case "$pidfile" in /*);; *) pidfile="/var/run/$pidfile";; esac
919                 shift 2
920         fi
921
922         subsys=$1
923         daemon=${2:-$subsys}
924
925         # Test syntax.
926         if [ $# = 0 ]; then
927                 msg_usage " status [--pidfile PIDFILE] {subsys} [{daemon}]"
928                 return 2
929         fi
930
931         # if pidfile specified, pid must be there
932         if [ "$pidfile" ]; then
933                 [ -f "$pidfile" ] && read pid < $pidfile
934                 # filter_chroot does not filter out dead pids, so this extra check, see t/status-pidfile.sh
935                 if [ ! -d "/proc/$pid" ]; then
936                         pid=
937                 fi
938         else
939                 pid=$(pidof -o $$ -o $PPID -o %PPID -x $daemon)
940         fi
941         pid=$(filter_chroot "$pid")
942
943         if [ "$pid" ]; then
944                 cpuset_msg="..."
945                 if [ -n "$SERVICE_CPUSET" ] && is_yes "$CPUSETS"; then
946                         if grep -q "$pid" "/dev/cpuset/${SERVICE_CPUSET}/tasks"; then
947                                 cpuset_msg=$(nls " in cpuset %s..." "$SERVICE_CPUSET")
948                         else
949                                 cpuset_msg=$(nls " outside of configured cpuset %s..." "$SERVICE_CPUSET")
950                         fi
951                 fi
952                 nls "%s (pid %s) is running%s" "$daemon" "$pid" "$cpuset_msg"
953                 return 0
954         fi
955
956         # Next try "/var/run/*.pid" files; if pidfile is not set
957         local base=${daemon##*/}
958         if [ -z "$pidfile" -a -f /var/run/${base}.pid ]; then
959                 read pid < /var/run/${base}.pid
960                 pid=$(filter_chroot "$pid")
961                 if [ "$pid" ]; then
962                         nls "%s dead but pid file (%s) exists" "$subsys" /var/run/${base}.pid
963                         return 1
964                 fi
965         fi
966
967         # See if /var/lock/subsys/$subsys exists
968         if [ -f /var/lock/subsys/$subsys ]; then
969                 nls "daemon %s dead but subsys (%s) locked" "$daemon" "$subsys"
970                 return 2
971         fi
972         nls "%s is stopped" "$subsys"
973         return 3
974 }
975
976 # Confirm whether we really want to run this service
977 confirm() {
978         local answer
979         nls -n "Start service %s (Y)es/(N)o/(C)ontinue? [Y] " "$1"
980         read answer
981         case $answer in
982         y|Y|t|T|j|J|"")
983                 return 0
984                 ;;
985         c|C|k|K|w|W)
986                 return 2
987                 ;;
988         n|N)
989                 return 1
990                 ;;
991         *)
992                 confirm $1
993                 return $?
994                 ;;
995         esac
996 }
997
998 # module is needed (ie. is requested, is available and isn't loaded already)
999 is_module() {
1000         # module name without .o at end
1001         if ! lsmod | grep -q "$1"; then
1002                 if ls -1R /lib/modules/$(uname -r)/ 2> /dev/null | grep -q "^${1}.\(\|k\)o\(\|.gz\)"; then
1003                         # true
1004                         return 0
1005                 fi
1006         fi
1007         # false
1008         return 1
1009 }
1010
1011 _modprobe() {
1012         local parsed single die args foo result
1013         parsed=no
1014         while is_no "$parsed"; do
1015                 case "$1" in
1016                 "single")
1017                         single=yes
1018                         shift
1019                         ;;
1020                 "die")
1021                         die=yes
1022                         shift
1023                         ;;
1024                 -*)
1025                         args="$args $1"
1026                         shift
1027                         ;;
1028                 *)
1029                         parsed=yes
1030                         ;;
1031                 esac
1032         done
1033         if is_yes "${single}"; then
1034                 foo="$@"
1035                 show "Loading %s kernel module(s)" "$foo"
1036                 busy
1037         fi
1038         if [ -x /sbin/modprobe ]; then
1039                 /sbin/modprobe -s $args "$@"
1040                 result=$?
1041         else
1042                 deltext; fail
1043                 result=1
1044         fi
1045         if is_yes "${single}"; then
1046                 deltext
1047                 if [ $result = "0" ]; then
1048                         is_yes "$single" && ok
1049                 else
1050                         fail
1051                         if is_yes "$die"; then
1052                                 nls "Could not load %s kernel module(s)" "$@"
1053                                 exit 1
1054                         fi
1055                 fi
1056         fi
1057 }
1058
1059 if is_no "$RC_LOGGING"; then
1060         log_success() {
1061                 :
1062         }
1063
1064         log_failed() {
1065                 :
1066         }
1067 else
1068         log_success() {
1069                 initlog -n $0 -s "$1 $2" -e 1
1070         }
1071
1072         log_failed() {
1073                 initlog -n $0 -s "$1 $2" -e 2
1074         }
1075 fi
1076
1077 # Check if any flavor of portmapper is running
1078 check_portmapper() {
1079         if [ -x /usr/sbin/rpcinfo ]; then
1080                 if /usr/sbin/rpcinfo -p localhost >/dev/null 2>/dev/null; then
1081                         return 0
1082                 else
1083                         return 1
1084                 fi
1085         elif [ -z "$(pidof portmap)" -a -z "$(pidof rpcbind)" ]; then
1086                 return 1
1087         fi
1088         return 0
1089 }
1090
1091 # is_fsmounted fstype mntpoint
1092 # Check if filesystem fstype is mounted on mntpoint
1093 is_fsmounted() {
1094         local fstype=$1
1095         local mntpoint=$2
1096
1097         [ -n "$fstype" -a -n "$mntpoint" ] || return 1
1098
1099         if [ -r /proc/mounts ]; then
1100                 grep -qE "[[:blank:]]$mntpoint[[:blank:]]+$fstype[[:blank:]]" /proc/mounts
1101                 return $?
1102         else
1103                 if [ "$(stat -L -f -c %T $mntpoint 2>/dev/null)" = "$fstype" ]; then
1104                         return 0
1105                 else
1106                         return 1
1107                 fi
1108         fi
1109 }
1110
1111 # __umount_loop awk_program fstab_file first_msg retry_msg umount_args
1112 # awk_program should process fstab_file and return a list of fstab-encoded
1113 # paths; it doesn't have to handle comments in fstab_file.
1114 __umount_loop() {
1115         local remaining sig=
1116         local retry=3 count
1117
1118         remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r)
1119         while [ -n "$remaining" -a "$retry" -gt 0 ]; do
1120                 if [ "$retry" -eq 3 ]; then
1121                         run_cmd "$3" fstab-decode umount $5 $remaining
1122                 else
1123                         run_cmd "$4" fstab-decode umount $5 $remaining
1124                 fi
1125                 count=4
1126                 remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r)
1127                 while [ "$count" -gt 0 ]; do
1128                         [ -z "$remaining" ] && break
1129                         count=$(($count-1))
1130                         usleep 500000
1131                         remaining=$(LC_ALL=C awk "/^#/ {next} $1" "$2" | sort -r)
1132                 done
1133                 [ -z "$remaining" ] && break
1134                 fstab-decode /bin/fuser -k -m $sig $remaining >/dev/null
1135                 sleep 3
1136                 retry=$(($retry -1))
1137                 sig=-9
1138         done
1139 }
1140
1141 # Similar to __umount loop above, specialized for loopback devices
1142 __umount_loopback_loop() {
1143         local remaining devremaining sig=
1144         local retry=3
1145
1146         remaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts)
1147         devremaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $1}' /proc/mounts)
1148         while [ -n "$remaining" -a "$retry" -gt 0 ]; do
1149                 if [ "$retry" -eq 3 ]; then
1150                         run_cmd "Unmounting loopback filesystems: " \
1151                                 fstab-decode umount $remaining
1152                 else
1153                         run_cmd "Unmounting loopback filesystems (retry):" \
1154                                 fstab-decode umount $remaining
1155                 fi
1156                 for dev in $devremaining ; do
1157                         losetup $dev > /dev/null 2>&1 && \
1158                                 run_cmd "Detaching loopback device $dev: " \
1159                                 losetup -d $dev
1160                 done
1161                 remaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts)
1162                 devremaining=$(awk '$1 ~ /^\/dev\/loop/ && $2 != "/" {print $1}' /proc/mounts)
1163                 [ -z "$remaining" ] && break
1164                 fstab-decode /bin/fuser -k -m $sig $remaining >/dev/null
1165                 sleep 3
1166                 retry=$(($retry -1))
1167                 sig=-9
1168         done
1169 }
1170
1171 rc_cache_init() {
1172         # If we have cachefile, use it.
1173         # If we don't, create memory variables and try to save silently,
1174         local cachefile='/var/cache/rc-scripts/msg.cache'
1175
1176         local term
1177         if is_yes "$ISATTY"; then
1178                 term=$TERM
1179         else
1180                 term=dumb
1181         fi
1182
1183         # We create $check variable which is used to invalidate the cache.
1184         # The $check contains user locale and terminal.
1185         local check="$term.$LC_MESSAGES.$INIT_COL"
1186
1187         if [ -f "$cachefile" -a "$cachefile" -nt /etc/sysconfig/system -a "$cachefile" -nt /etc/sysconfig/init-colors ]; then
1188                 if . "$cachefile" 2>/dev/null; then
1189                         if [ "$check" = "$_check" ]; then
1190                                 return
1191                         fi
1192                 fi
1193         fi
1194
1195         # primitive caching
1196         _busy=$(progress "BUSY" "$CBUSY")
1197         _ok=$(progress "DONE")
1198         _started=$(progress "WORK")
1199         _fail=$(progress "FAIL" "$CFAIL")
1200         _died=$(progress "DIED" "$CFAIL")
1201
1202         # we don't use heredoc, as ksh attempts to create tempfile then
1203         (> "$cachefile" ) 2>/dev/null || return
1204         echo "_busy='$_busy';" >> "$cachefile"
1205         echo "_ok='$_ok';" >> "$cachefile"
1206         echo "_started='$_started';" >> "$cachefile"
1207         echo "_fail='$_fail';" >> "$cachefile"
1208         echo "_died='$_died';" >> "$cachefile"
1209         echo "_check='$check';" >> "$cachefile"
1210 }
1211
1212 rc_gettext_init() {
1213         if [ -z "$GETTEXT" ]; then
1214                 if [ -x /bin/gettext -o -x /usr/bin/gettext ]; then
1215                         GETTEXT=yes
1216                 else
1217                         GETTEXT=no
1218                 fi
1219         fi
1220
1221         if [ -z "$TPUT" ]; then
1222                 if [ -d /usr/share/terminfo ] && [ -x /usr/bin/tput -o -x /bin/tput ]; then
1223                         TPUT=yes
1224                         # check if we are on proper terminal
1225                         tput longname >/dev/null 2>&1 || TPUT=no
1226                 else
1227                         TPUT=no
1228                 fi
1229         fi
1230 }
1231
1232 use_upstart () {
1233         # True when upstart-event-based boot should be used
1234         is_yes "$USE_UPSTART" && return 0
1235         is_no "$USE_UPSTART" && return 1
1236         if [ ! -x /sbin/initctl ] ; then
1237                 USE_UPSTART="no"
1238                 return 1
1239         fi
1240         local cmdline=$(cat /proc/cmdline 2>/dev/null)
1241         if strstr "$cmdline" "pld.no-upstart" ; then
1242                 USE_UPSTART="no"
1243                 return 1
1244         else
1245                 USE_UPSTART="yes"
1246                 return 0
1247         fi
1248 }
1249
1250 emit () {
1251         # emit upstart signal
1252         # only when 'upstart' boot is enabled
1253         use_upstart || return 0
1254         /sbin/initctl emit "$@"
1255 }
1256
1257 is_upstart_task() {
1258         # Return 0 if the given service is an upstart task.
1259         grep -q '^task' "/etc/init/$1.conf"
1260 }
1261 is_upstart_running() {
1262         # Return 0 if the given service is running via upstart
1263         initctl status "$1" 2>/dev/null | grep -q running
1264 }
1265 upstart_start() {
1266         local service=$1
1267         if is_upstart_running "${service}"; then
1268                 msg_already_running "$service"
1269                 return 0
1270         fi
1271
1272         msg_starting "${service}"
1273         if errors=$(/sbin/initctl start ${service} 2>&1) ; then
1274                 ok
1275                 return 0
1276         else
1277                 fail
1278                 echo "$errors" >&2
1279                 return 1
1280         fi
1281 }
1282 upstart_stop() {
1283         local service=$1
1284         if ! is_upstart_running "${service}"; then
1285                 msg_not_running "$name"
1286                 return 0
1287         fi
1288         msg_stopping "${service}"
1289         if errors=$(/sbin/initctl stop ${service}) ; then
1290                 ok
1291                 return 0
1292         else
1293                 fail
1294                 echo "$errors" >&2
1295                 return 1
1296         fi
1297 }
1298 upstart_reload() {
1299         local service=$1
1300         if ! is_upstart_running "${service}" && ! is_upstart_task "${service}" ; then
1301                 return 0
1302         fi
1303         msg_reloading "${service}"
1304         if errors=$(/sbin/initctl reload ${service}) ; then
1305                 ok
1306                 return 0
1307         else
1308                 fail
1309                 echo "$errors" >&2
1310                 return 1
1311         fi
1312 }
1313 upstart_status() {
1314         # get service status
1315         # should be compliant with
1316         # http://refspecs.freestandards.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/iniscrptact.html
1317         local service=$1
1318         local status
1319         if is_upstart_task "${service}" ; then
1320                 # we probably should have a way to handle task status
1321                 return 0
1322         fi
1323         if ! status=$(/sbin/initctl status "${service}") ; then
1324                 # program or service status is not known
1325                 return 4
1326         fi
1327         if strstr "$status" "running" ; then
1328                 # program is running or service is OK
1329                 echo "$status"
1330                 return 0
1331         else
1332                 # program is not running
1333                 echo "$status"
1334                 return 3
1335         fi
1336         # TODO: other statuses
1337 }
1338
1339 _upstart_controlled() {
1340         # If the service is to be handled by upstart
1341         # execute the start/stop/etc. commands the upstart way
1342         if ! use_upstart; then
1343                 return 0
1344         fi
1345         local script=$1
1346         shift
1347         local command=$1
1348         [ $# -gt 0 ] && shift
1349         local name=$(basename "$script")
1350         if [ ! -f /etc/init/${name}.conf ] ; then
1351                 return 0
1352         fi
1353         local commands
1354         local extra_commands
1355         local has_configtest
1356         if [ "$1" = "--except" ] ; then
1357                 shift
1358                 commands="$*"
1359                 for cmd in $commands ; do
1360                         if [ "$command" = "$cmd" ] ; then
1361                                 return 0
1362                         fi
1363                         case "$cmd" in
1364                                 start|stop|status|reload|restart|try-restart|force-reload)
1365                                         ;;
1366                                 configtest)
1367                                         has_configtest=yes
1368                                         extra_commands="|$cmd"
1369                                         ;;
1370                                 *)
1371                                         extra_commands="|$cmd"
1372                                         ;;
1373                         esac
1374                 done
1375         elif [ -n "$*" ] ; then
1376                 commands="$*"
1377                 local cmd
1378                 local found=0
1379                 # is there a better way
1380                 for cmd in $commands ; do
1381                         if [ "$command" = "$cmd" ] ; then
1382                                 found=1
1383                                 break;
1384                         fi
1385                 done
1386                 if [ $found = 0 ] ; then
1387                         # let the script handle it
1388                         return 0
1389                 fi
1390         fi
1391         case "$command" in
1392                 start)
1393                         upstart_start $name
1394                         exit $?
1395                         ;;
1396                 stop)
1397                         upstart_stop $name
1398                         exit $?
1399                         ;;
1400                 status)
1401                         upstart_status $name
1402                         exit $?
1403                         ;;
1404                 restart)
1405                         if is_yes "$has_configtest" ; then
1406                                 "$script" configtest || exit 1
1407                         fi
1408                         upstart_stop $name
1409                         upstart_start $name
1410                         exit $?
1411                         ;;
1412                 try-restart)
1413                         if ! is_upstart_running "$name" ; then
1414                                 exit 0
1415                         fi
1416                         if is_yes "$has_configtest" ; then
1417                                 "$script" configtest || exit 1
1418                         fi
1419                         upstart_stop $name
1420                         upstart_start $name
1421                         exit $?
1422                         ;;
1423                 reload)
1424                         if is_yes "$has_configtest" ; then
1425                                 "$script" configtest || exit 1
1426                         fi
1427                         if is_upstart_task "$name" ; then
1428                                 nls "$command not implemented for $name"
1429                                 exit 3
1430                         else
1431                                 upstart_reload "$name"
1432                                 exit $?
1433                         fi
1434                         ;;
1435                 force-reload)
1436                         if is_yes "$has_configtest" ; then
1437                                 "$script" configtest || exit 1
1438                         fi
1439                         if is_upstart_task "$name" ; then
1440                                 upstart_stop "$name"
1441                                 upstart_start "$name"
1442                                 exit $?
1443                         else
1444                                 upstart_reload "$name"
1445                                 exit $?
1446                         fi
1447                         ;;
1448                 *)
1449                         msg_usage "$0 {start|stop|restart|reload|force-reload|status$extra_commands}"
1450                         exit 3
1451                         ;;
1452         esac
1453         return 1 # should not happen
1454 }
1455
1456 # Usage:
1457 #       somewhere at the begining of init script:
1458 #     upstart_controlled
1459 #               - to pass implement all upstart commands via initctl
1460 #                 start, stop, status, restart, reload and force_reload
1461 #                 are implemented
1462 #     upstart_controlled command...
1463 #               - to pass handle only specific commands the upstart way
1464 #                 and leave the rest to the script
1465 #
1466 alias upstart_controlled='_upstart_controlled $0 "$@"'
1467
1468 rc_gettext_init
1469 rc_cache_init
1470
1471 #/*
1472 # * Local variables:
1473 # * mode: sh
1474 # * indent-tabs-mode: notnil
1475 # * End:
1476 # *
1477 # */
This page took 0.263078 seconds and 4 git commands to generate.