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