]> git.pld-linux.org Git - projects/rc-scripts.git/blob - rc.d/init.d/functions
- umount CIFS on network stop
[projects/rc-scripts.git] / rc.d / init.d / functions
1 # functions     This file contains functions to be used by most or all
2 #               shell scripts in the /etc/init.d directory.
3 #
4 # $Id$
5 #
6 # Author:       Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
7 # Hacked by:    Greg Galloway and Marc Ewing
8 # Modified for PLD by:
9 #               Marek Obuchowicz <elephant@pld-linux.org>
10 #               Arkadiusz Mi¶kiewicz <misiek@pld-linux.org>
11 #               Micha³ Kochanowicz <mkochano@pld-linux.org>
12
13 # First set up a default search path.
14 export PATH="/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin"
15
16 # Set defaults
17 INIT_COL=67
18
19 # Source configuration if available - may override default values
20 [ -r /etc/sysconfig/system ] && . /etc/sysconfig/system
21 [ -r /etc/sysconfig/bootsplash ] && . /etc/sysconfig/bootsplash
22
23 [ -z "$COLUMNS" ] && COLUMNS=80
24
25 is_yes()
26 {
27         # Test syntax
28         if [ $# = 0 ] ; then
29                 msg_usage " is_yes {value}"
30                 return 2
31         fi
32
33         # Check value
34         case "$1" in
35           yes|Yes|YES|true|True|TRUE|on|On|ON|Y|y|1)
36                 # true returns zero
37                 return 0
38                 ;;
39           *)
40                 # false returns one
41                 return 1
42                 ;;
43         esac
44 }
45
46 is_no()
47 {
48         # Test syntax
49         if [ $# = 0 ] ; then
50                 msg_usage " is_no {value}"
51                 return 2
52         fi
53
54         case "$1" in
55           no|No|NO|false|False|FALSE|off|Off|OFF|N|n|0)
56                 # true returns zero
57                 return 0
58                 ;;
59           *)
60                 # false returns one
61                 return 1
62                 ;;
63         esac
64 }
65
66 if is_yes "$FASTRC"; then
67         INIT_DOTS=$(awk "BEGIN{for(\$i=0;\$i<$INIT_COL;\$i++)printf(\".\");}")
68         initlog()
69         {
70                 RESULT=0
71                 while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do
72                         case $1 in
73                                 -c)
74                                         shift
75                                         $1
76                                         RESULT=$?
77                                         break
78                                         ;;
79                                  *)
80                                         shift
81                                         ;;
82                         esac
83                 done
84                 return $RESULT
85         }
86 fi
87
88 kernelver()
89 {
90         awk '{split($3,v,"."); printf("%03d%03d%03d\n", v[1],v[2],v[3]);}' /proc/version
91 }
92
93 kernelverser()
94 {
95         awk '{split($3,v,"."); printf("%03d%03d\n", v[1],v[2]);}' /proc/version
96 }
97
98 kernelvermser()
99 {
100         awk '{split($3,v,"."); printf("%03d\n", v[1]);}' /proc/version
101 }
102
103 # Colors workaround
104 termput()
105 {
106         if is_yes "$FASTRC" || [ ! -d /usr/share/terminfo ] || \
107            [ ! -x /usr/bin/tput -a ! -x /bin/tput ]; then
108                 case "$1" in
109                   hpa)
110                         echo -ne "\033[$(($2+1))G"
111                         ;;
112                   cuu*)
113                         echo -ne "\033[${2}A"
114                         ;;
115                   el)
116                         echo -ne "\033[0K"
117                         ;;
118                   setaf)
119                         is_yes "$COLOR_INIT" && echo -ne "\033[0;3${2}m"
120                         ;;
121                   op)
122                         termput setaf 9
123                         ;;
124                 esac
125         else
126                 # check if we are on proper terminal
127                 tput longname > /dev/null 2>&1 || return
128
129                 case "$1" in
130                   hpa | cuu* | el)
131                         tput "$@"
132                         ;;
133                   setaf)
134                         is_yes "$COLOR_INIT" && tput "$@"
135                         ;;
136                   op)
137                         tput setaf 9
138                         ;;
139                 esac
140         fi
141 }
142
143 # printf equivalent
144 printf_()
145 {
146         typeset text m
147         text="$1" ;
148         shift ;
149         if [ $# -gt 0 ]; then
150                 m="$1";
151                 shift;
152                 while [ $# -gt 0 ]; do
153                         m="$m\",\"$1" ;
154                         shift ;
155                 done
156         fi
157         awk "BEGIN {printf \"$text\", \"$m\"; }"
158 }
159
160 # National language support function
161 nls()
162 {
163         typeset msg_echo old_nls_domain text message
164         msg_echo='\n'
165         old_nls_domain="$NLS_DOMAIN"
166         # parse command line
167         # don't use -o instead || here - this will break ksh --misiek
168         while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do
169                 case "$1" in
170                   --nls-domain)
171                         shift
172                         NLS_DOMAIN="$1"
173                         shift
174                         ;;
175                   -n)
176                         msg_echo=''
177                         shift
178                         ;;
179                 esac
180         done
181         message="$1"
182         shift
183         # empty message, so we return --misiek
184         if [ -z "$message" ]; then
185                 NLS_DOMAIN="$old_nls_domain"
186                 echo -en "$msg_echo"
187                 return
188         fi
189
190         if is_yes "$FASTRC"; then
191                 printf "$message" "$@"
192         elif [ -x /bin/gettext -o -x /usr/bin/gettext ]; then
193                 text=$(TEXTDOMAINDIR="/etc/sysconfig/locale" gettext -e --domain="${NLS_DOMAIN:-rc-scripts}" "$message")
194                 printf_ "$text" "$@"
195         else
196                 printf_ "$message" "$@"
197         fi
198
199         echo -en "$msg_echo"
200         NLS_DOMAIN="$old_nls_domain"
201 }
202
203 rc_splash()
204 {
205         typeset action
206
207         action="$1"
208
209         if ! is_no "$BOOT_SPLASH"; then
210                 [ -x /bin/splash ] && /bin/splash "$action"
211         fi
212
213         : $((progress++))
214 }
215
216 msg_network_down()
217 {
218         nls "ERROR: Networking is down. %s can't be run." "$1" >&2
219 }
220
221 msg_starting()
222 {
223         show "Starting %s service" "$1"
224 }
225
226 msg_already_running()
227 {
228         nls "%s service is already running." "$1"
229 }
230
231 msg_stopping()
232 {
233         show "Stopping %s service" "$1"
234 }
235
236 msg_not_running()
237 {
238         nls "%s service is not running." "$1"
239 }
240
241 msg_reloading()
242 {
243         show "Reloading %s service" "$1"
244 }
245
246 msg_usage()
247 {
248         nls "Usage: %s" "$*"
249 }
250
251 # Some functions to handle PLD-style messages
252 show()
253 {
254         typeset text
255
256         if is_yes "$FASTRC"; then
257                 echo -n "$INIT_DOTS"
258                 termput hpa 0
259                 printf "$@"
260                 termput hpa $INIT_COL
261         else
262                 text=$(nls "$@")
263                 echo -n "$text"
264                 awk "BEGIN { for (j=length(\"$text\"); j<$INIT_COL; j++) printf \".\" }"
265         fi
266 }
267
268 # Displays message in square brackests ("[ DONE ]"). Takes two arguments.
269 # First is the text to display, second is color number to use (argument to
270 # tput setaf). If second argument is not given, default (2, green) will be
271 # used).
272 progress()
273 {
274         typeset COLOR
275         if [ -n "$2" ]; then COLOR="$2"; else COLOR="2"; fi
276         deltext
277         echo -n "$(termput setaf 6)[$(termput setaf "$COLOR") $(nls --nls-domain rc-scripts "$1") $(termput setaf 6)]$(termput op)"
278 }
279
280 busy()
281 {
282         progress "BUSY" 5
283 }
284
285 ok()
286 {
287         progress "DONE"
288         echo
289 }
290
291 started()
292 {
293         progress "WORK"
294         echo
295 }
296
297 fail()
298 {
299         progress "FAIL" 1
300         echo
301         return 1
302 }
303
304 died()
305 {
306         progress "DIED" 1
307         echo
308         return 1
309 }
310
311 deltext()
312 {
313         termput hpa $INIT_COL
314 }
315
316 # Check if $pid (could be plural) are running
317 checkpid()
318 {
319         while [ "$1" ]; do
320                 [ -d "/proc/$1" ] && return 0
321                 shift
322         done
323         return 1
324 }
325
326 # outside chroot get only thsese processes which are outside chroot.
327 # inside chroot get only these processes which are inside of chroot.
328 # (note: some processes like named are chrooted but run outside chroot)
329 filter_chroot()
330 {
331         if [ $# -lt 1 -o ! -d /proc/1 ] ; then
332                 echo $@
333                 return
334         fi
335         good_pids=""
336         for root_pid in $@; do
337                 root_dir=$(resolvesymlink /proc/${root_pid}/root)
338                 if [ -n "$root_dir" ]; then
339                         good_add_pid=1
340                         if [ -n "${SYSTEM_CHROOTS}" ]; then
341                                 for r_dir in ${SYSTEM_CHROOTS}; do
342                                         echo "$root_dir" | grep -q "^${r_dir}" && good_add_pid=0
343                                 done
344                         fi
345                         [ "$good_add_pid" -eq 1 ] && good_pids="$good_pids $root_pid"
346                 fi
347         done
348         echo $good_pids
349 }
350
351 # Usage run_cmd Message command_to_run
352 run_cmd()
353 {
354         typeset exit_code errors message force_err
355         typeset -i force_err=0
356         typeset -i exit_code=0
357         case "$1" in
358           -a)
359                 force_err=1
360                 shift
361                 ;;
362         esac
363         message=$1
364         show "$message"; busy
365         shift
366         if errors=$(HOME=/tmp TMPDIR=/tmp initlog -c "$*" 2>&1); then
367                 ok
368                 log_success "$1 $message"
369         else
370                 fail
371                 log_failed "$1 $message"
372                 exit_code=1
373         fi
374         [ -n "$errors" ] && [ $exit_code -eq 1 -o $force_err -eq 1 ] && echo "$errors"
375         return $exit_code
376 }
377
378 # A function to start a program (now it's useful on read-only filesystem too)
379 daemon()
380 {
381         typeset errors="" prog="" limits=""
382         typeset -i exit_code=0
383         [ -z "$DEFAULT_SERVICE_RUN_NICE_LEVEL" ] && DEFAULT_SERVICE_RUN_NICE_LEVEL=0
384         # "-u unlimited" (-p for ksh) to make sure daemons will be able to fork.
385         # "-c 0" to make sure it doesn't core dump anywhere; while this could mask
386         # problems with the daemon, it also closes some security problems.
387         # Users' limits are set via pam_limits.
388         [ -z "$DEFAULT_SERVICE_LIMITS" ] && DEFAULT_SERVICE_LIMITS_HARD="-u unlimited -c 0"
389         # Test syntax. Don't use -o instead || here - this will break ksh --misiek
390         while [ "$1" != "${1##-}" ] || [ "$1" != "${1##+}" ]; do
391                 case $1 in
392                   '')
393                         msg_usage " daemon [--user user] [--fork] [+/-nicelevel] {program}"
394                         return 2
395                         ;;
396                   --check)
397                         # for compatibility with redhat/mandrake
398                         nls "warning: --check option is ignored!"
399                         shift
400                         shift
401                         ;;
402                   --user)
403                         shift
404                         [ "$1" != "root" ] && prog="/bin/su $1 -s /bin/sh -c \""
405                         shift
406                         ;;
407         --fork)
408          prog="/usr/bin/setsid sh -c \""
409          end='&'
410          shift
411          ;;
412                   -*|+*) SERVICE_RUN_NICE_LEVEL=$1
413                         shift;;
414                 esac
415         done
416         # If command to execute ends with quotation mark, add remaining
417         # arguments and close quotation.
418         if [ "$prog" != "${prog%\"}" ]; then
419                 prog="$prog $*$end\""
420         else
421                 prog="$prog $*$end"
422         fi
423
424         if [ -n "$KSH_VERSION" ]; then
425                 limits="`echo "${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS}" | awk '/-Su/ {sub(/-Su/,"-Sp");} /-Hu/ {sub(/-Hu/,"-Hp");} /-u/ {sub(/-u/,"-p");} {print;}'`"
426         elif [ -n "$ZSH_VERSION" ]; then
427                 limits="${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS}"
428         elif [ -n "$BASH_VERSION" ]; then
429                 limits="${SERVICE_LIMITS:-$DEFAULT_SERVICE_LIMITS}"
430 #       elif [ -n "`$SH -c 'echo ${.sh.version}' 2>/dev/null`" ]; then
431         fi
432
433         [ -n "$limits" ] && eval `echo "$limits" | awk 'BEGIN {RS="[\n-]";} !/^ *$/ { printf("ulimit -%s ;", $0); }'`
434
435         # And start it up.
436         busy
437         if errors=$(USER=root HOME=/tmp TMPDIR=/tmp nice -n ${SERVICE_RUN_NICE_LEVEL:-$DEFAULT_SERVICE_RUN_NICE_LEVEL} initlog -c "$prog" 2>&1); then
438                 log_success "$1 startup"
439                 ok
440         else
441                 exit_code=1
442                 fail
443                 log_failed "$1 startup"
444                 [ -n "$errors" ] && echo "$errors"
445         fi
446         return $exit_code
447 }
448
449 # A function to stop a program.
450 killproc()
451 {
452         typeset notset killlevel base pid result
453         # Test syntax.
454         if [ $# = 0 ]; then
455                 msg_usage " killproc {program} [signal]"
456                 return 2
457         fi
458
459         busy
460
461         typeset -i notset=0
462         # check for second arg to be kill level
463         if [ -n "$2" ] ; then
464                 killlevel=$2
465         else
466                 notset=1
467                 killlevel="-9"
468         fi
469
470         # Save basename.
471         base=$(basename "$1")
472
473         # Find pid.
474         pid=$(pidofproc "$1")
475         [ -z "$pid" ] && pid=$(pidofproc "$base")
476
477         # Kill it.
478         if [ -n "$pid" -a "$pid" != "$$" ] && checkpid $pid 2>&1 ; then
479                 if [ "$notset" = "1" ] ; then
480                         if checkpid $pid 2>&1; then
481                                 # TERM first, then KILL if not dead
482                                 kill -TERM $pid
483                                 usleep 100000
484                                 if checkpid $pid && sleep 1 &&
485                                         checkpid $pid && sleep 3 &&
486                                         checkpid $pid; then
487                                         kill -KILL $pid
488                                         usleep 100000
489                                 fi
490                         fi
491                         checkpid $pid
492                         result=$?
493                         if [ "$result" -eq 0 ]; then
494                                 fail
495                                 log_failed "$1 shutdown"
496                         else
497                                 ok
498                                 log_success "$1 shutdown"
499                         fi
500                         result=$(( ! $result ))
501                 else
502                         # use specified level only
503                         if checkpid $pid > /dev/null 2>&1; then
504                                 kill $killlevel $pid
505                                 result=$?
506                                 if [ "$result" -eq 0 ]; then
507                                         ok
508                                         log_success "$1 got $killlevel"
509                                 else
510                                         result=7
511                                         fail
512                                         log_failed "$1 didn't get $killlevel"
513                                 fi
514                         else
515                                 result=7
516                                 died
517                                 log_failed "$1 shutdown"
518                         fi
519                 fi
520         else
521                 died
522                 log_failed "$1 shutdown"
523                 result=7
524         fi
525
526         # Remove pid file if any.
527         if [ "$notset" = "1" ]; then
528                 rm -f /var/run/${base}.pid
529         fi
530
531         return $result
532 }
533
534 # A function to find the pid of a program.
535 pidofproc()
536 {
537         typeset pid base
538         base=$(basename "$1")
539
540         # Test syntax.
541         if [ $# = 0 ] ; then
542                 msg_usage " pidofproc {program}"
543                 return 2
544         fi
545
546         # First try "/var/run/*.pid" files
547         if [ -f /var/run/${base}.pid ] ; then
548                 typeset line p pid
549                 pid=
550                 read line < /var/run/${base}.pid
551                 for p in $line; do
552                         [ -z "$(echo "$p" | awk '{gsub(/[0-9]/,"");print;}')" ] && pid="$pid $p"
553                 done
554         fi
555
556         # Next try "pidof"
557         [ -z "$pid" ] && pidof -o $$ -o $PPID -o %PPID -x "$1"
558         pid=$(filter_chroot "$pid")
559         echo $pid
560 }
561
562 status()
563 {
564         typeset base pid subsys daemon
565         subsys=$1
566         daemon=${2:-$subsys}
567         base=$(basename $daemon)
568
569         # Test syntax.
570         if [ $# = 0 ] ; then
571                 msg_usage " status {subsys} [{daemon}]"
572                 return 2
573         fi
574
575         # First try "pidof"
576         pid=$(pidof -o $$ -o $PPID -o %PPID -x $daemon)
577         pid=$(filter_chroot "$pid")
578
579         if [ "$pid" != "" ]; then
580                 nls "%s (pid %s) is running..." "$daemon" "$pid"
581                 return 0
582 #       else
583 #               pid=`ps ax | awk 'BEGIN { prog=ARGV[1]; ARGC=1 }
584 #                    { if ((prog == $5) || (("(" prog ")") == $5) ||
585 #                         (("[" prog "]") == $5) ||
586 #                         ((prog ":") == $5)) { print $1 ; exit 0 } }' $1`
587 #               if [ "$pid" != "" ]; then
588 #                       nls "%s (pid %s) is running..." "$daemon" "$pid"
589 #                       return 0
590 #               fi
591         fi
592
593         # Next try "/var/run/*.pid" files
594         if [ -f /var/run/${base}.pid ]; then
595                 read pid < /var/run/${base}.pid
596                 pid=$(filter_chroot "$pid")
597                 if [ "$pid" != "" ]; then
598                         nls "%s dead but pid file exists" "$subsys"
599                         return 1
600                 fi
601         fi
602
603         # See if /var/lock/subsys/$subsys exists
604         if [ -f /var/lock/subsys/$subsys ]; then
605                 nls "%s dead but subsys locked" "$subsys"
606                 return 2
607         fi
608         nls "%s is stopped" "$subsys"
609         return 3
610 }
611
612 # Confirm whether we really want to run this service
613 confirm() {
614         typeset answer
615         nls -n "Start service %s (Y)es/(N)o/(C)ontinue? [Y] " "$1"
616         read answer
617         case $answer in
618           y|Y|t|T|j|J|"")
619                 return 0
620                 ;;
621           c|C|k|K|w|W)
622                 return 2
623                 ;;
624           n|N)
625                 return 1
626                 ;;
627           *)
628                 confirm $1
629                 return $?
630                 ;;
631         esac
632 }
633
634 # module is needed (ie. is requested, is available and isn't loaded already)
635 is_module()
636 {
637         # module name without .o at end
638         if ! (lsmod | grep -q "$1"); then
639                 if (ls -R /lib/modules/$(uname -r)/ 2> /dev/null | grep -q "${1}.\(\|k\)o\(\|.gz\)"); then
640                         # true
641                         return 0
642                 fi
643         fi
644         # false
645         return 1
646 }
647
648 _modprobe()
649 {
650         typeset parsed single die args foo result
651         parsed=no
652         while is_no "$parsed" ; do
653                 case "$1" in
654                   "single")
655                         single=yes
656                         shift
657                         ;;
658                   "die")
659                         die=yes
660                         shift
661                         ;;
662                   -*)
663                         args="$args $1"
664                         shift
665                         ;;
666                   *)
667                         parsed=yes
668                         ;;
669                 esac
670         done
671         if is_yes "${single}" ; then
672                 foo="$@"
673                 show "Loading %s kernel module(s)" "$foo"
674                 busy
675         fi
676         if [ -x /sbin/modprobe ] ; then
677                 /sbin/modprobe -s $args "$@"
678                 result=$?
679         else
680                 deltext ; fail
681                 result=1
682         fi
683         if is_yes "${single}" ; then
684                 deltext
685                 if [ $result == "0" ] ; then
686                         is_yes "$single" && ok
687                 else
688                         fail
689                         if is_yes "$die" ; then
690                                 nls "Could not load %s kernel module(s)" "$@"
691                                 exit 1
692                         fi
693                 fi
694         fi
695 }
696
697 log_success ()
698 {
699         initlog -n $0 -s "$1 $2" -e 1
700 }
701
702 log_failed ()
703 {
704         initlog -n $0 -s "$1 $2" -e 2
705 }
706
707 # RedHat/Mandrake specific functions
708 action () { STRING=$1; shift; run_cmd "$STRING" "$*"; }
709 success () { return 0; }
710 failure () { return 1; }
711
712 # TO BE REMOVED IN AC. --ankry
713 msg_Network_Down () { msg_network_down "$*"; }
714 msg_Already_Running () { msg_already_running "$*"; }
715 msg_Not_Running () { msg_not_running "$*"; }
716 msg_Usage () { msg_usage "$*"; }
717
718 #/*
719 # * Local variables:
720 # * mode: sh
721 # * indent-tabs-mode: notnil
722 # * End:
723 # *
724 # */
725 # vi: syntax=sh:shiftwidth=8:
This page took 0.378747 seconds and 4 git commands to generate.