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