/[baselayout]/branches/baselayout-1_12/sbin/runscript.sh
Gentoo

Contents of /branches/baselayout-1_12/sbin/runscript.sh

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1819 - (show annotations) (download) (as text)
Fri Jan 13 12:07:01 2006 UTC (8 years, 9 months ago) by uberlord
File MIME type: text/x-sh
File size: 17666 byte(s)
    Services that need a service which is inactive at boot are now scheduled
    to start when the inactive service starts, #118801.
1 #!/bin/bash
2 # Copyright 1999-2006 Gentoo Foundation
3 # Distributed under the terms of the GNU General Public License v2
4
5 # Common functions
6 [[ ${RC_GOT_FUNCTIONS} != "yes" ]] && source /sbin/functions.sh
7
8 # User must be root to run most script stuff (except status)
9 if [[ ${EUID} != 0 ]] && ! [[ $2 == "status" && $# -eq 2 ]] ; then
10 eerror "$0: must be root to run init scripts"
11 exit 1
12 fi
13
14 # State variables
15 svcpause="no"
16 svcrestart="no"
17
18 myscript="$1"
19 if [[ -L $1 && ! -L "/etc/init.d/${1##*/}" ]] ; then
20 myservice="$(readlink $1)"
21 else
22 myservice="$1"
23 fi
24
25 myservice="${myservice##*/}"
26 export SVCNAME="${myservice}"
27 mylevel="$(<${svcdir}/softlevel)"
28
29 svc_trap() {
30 trap 'eerror "ERROR: \"${myservice}\" caught an interrupt"; exit 1' \
31 INT QUIT TSTP
32 }
33
34 # Setup a default trap
35 svc_trap
36
37 # Functions to handle dependencies and services
38 [[ ${RC_GOT_SERVICES} != "yes" ]] && source "${svclib}/sh/rc-services.sh"
39 # Functions to control daemons
40 [[ ${RC_GOT_DAEMON} != "yes" ]] && source "${svclib}/sh/rc-daemon.sh"
41
42 # Set $IFACE to the name of the network interface if it is a 'net.*' script
43 if [[ ${myservice%%.*} == "net" && ${myservice##*.} != "${myservice}" ]] ; then
44 IFACE="${myservice##*.}"
45 NETSERVICE="yes"
46 else
47 IFACE=
48 NETSERVICE=
49 fi
50
51 # Source configuration files.
52 # (1) Source /etc/conf.d/net if it is a net.* service
53 # (2) Source /etc/conf.d/${myservice} to get initscript-specific
54 # configuration (if it exists).
55 # (3) Source /etc/rc.conf to pick up potentially overriding
56 # configuration, if the system administrator chose to put it
57 # there (if it exists).
58 if [[ ${NETSERVICE} == "yes" ]] ; then
59 conf="$(add_suffix /etc/conf.d/net)"
60 [[ -e ${conf} ]] && source "${conf}"
61 fi
62 conf="$(add_suffix /etc/conf.d/${myservice})"
63 [[ -e ${conf} ]] && source "${conf}"
64 conf="$(add_suffix /etc/rc.conf)"
65 [[ -e ${conf} ]] && source "${conf}"
66
67 # Call svc_quit if we abort AND we have obtained a lock
68 svcbegun=1
69 service_started "${myservice}"
70 svcstarted=$?
71 service_inactive "${myservice}"
72 svcinactive=$?
73 svc_quit() {
74 eerror "ERROR: \"${myservice}\" caught an interrupt"
75 if [[ ${svcbegun} == 0 ]] ; then
76 end_service "${myservice}"
77 svcbegun=1
78 fi
79 if service_inactive "${myservice}" || [[ ${svcinactive} == 0 ]] ; then
80 mark_service_inactive "${myservice}"
81 elif [[ ${svcstarted} == 0 ]] ; then
82 mark_service_started "${myservice}"
83 else
84 mark_service_stopped "${myservice}"
85 fi
86 exit 1
87 }
88
89 usage() {
90 local IFS="|"
91 myline="Usage: ${myservice} { $* "
92 echo
93 eerror "${myline}}"
94 eerror " ${myservice} without arguments for full help"
95 }
96
97 stop() {
98 # Return success so the symlink gets removed
99 return 0
100 }
101
102 start() {
103 eerror "ERROR: \"${myservice}\" does not have a start function."
104 # Return failure so the symlink doesn't get created
105 return 1
106 }
107
108 restart() {
109 svc_restart || return $?
110 }
111
112 status() {
113 # Dummy function
114 return 0
115 }
116
117 svc_schedule_restart() {
118 local service="$1"
119 if [[ ! -e "${svcdir}/restart/${service}" ]] \
120 || ! grep -q "^${myservice}$" "${svcdir}/restart/${service}" ; then
121 echo "${myservice}" >> "${svcdir}/restart/${service}"
122 fi
123 }
124
125 svc_stop() {
126 local x= mydep= mydeps= retval=0
127 local -a servicelist=()
128
129 # Do not try to stop if it had already failed to do so on runlevel change
130 if is_runlevel_stop && service_failed "${myservice}" ; then
131 return 1
132 fi
133
134 if service_stopped "${myservice}" ; then
135 ewarn "WARNING: ${myservice} has not yet been started."
136 return 0
137 fi
138
139 if ! mark_service_stopping "${myservice}" ; then
140 ewarn "WARNING: ${myservice} is already stopping."
141 return 0
142 fi
143 # Lock service starting too ...
144 mark_service_starting "${myservice}"
145
146 # Ensure that we clean up if we abort for any reason
147 trap "svc_quit" INT QUIT TSTP
148
149 begin_service "${myservice}"
150 svcbegun=$?
151
152 service_message "Stopping service ${myservice}"
153
154 if in_runlevel "${myservice}" "${BOOTLEVEL}" && \
155 [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" && \
156 ${SOFTLEVEL} != "single" ]] ; then
157 ewarn "WARNING: you are stopping a boot service."
158 fi
159
160 if [[ ${svcpause} != "yes" ]] ; then
161 if [[ ${NETSERVICE} == "yes" ]] ; then
162 # A net.* service
163 if in_runlevel "${myservice}" "${BOOTLEVEL}" || \
164 in_runlevel "${myservice}" "${mylevel}" ; then
165 # Only worry about net.* services if this is the last one running,
166 # or if RC_NET_STRICT_CHECKING is set ...
167 if ! is_net_up ; then
168 mydeps="net"
169 fi
170 fi
171
172 mydeps="${mydeps} ${myservice}"
173 else
174 mydeps="${myservice}"
175 fi
176 fi
177
178 # Save the IN_BACKGROUND var as we need to clear it for stopping depends
179 local ib_save="${IN_BACKGROUND}"
180 unset IN_BACKGROUND
181
182 for mydep in ${mydeps} ; do
183 for x in $(needsme "${mydep}") ; do
184 # Service not currently running, continue
185 if service_started "${x}" ; then
186 stop_service "${x}"
187 service_list=( "${service_list[@]}" "${x}" )
188 fi
189 done
190 done
191
192 for x in "${service_list[@]}" ; do
193 # We need to test if the service has been marked stopped
194 # as the fifo may still be around if called by custom code
195 # such as postup from a net script.
196 service_stopped "${mynetservice}" && continue
197
198 wait_service "${x}"
199 if ! service_stopped "${x}" ; then
200 retval=1
201 break
202 fi
203 done
204
205 IN_BACKGROUND="${ib_save}"
206
207 if [[ ${retval} != 0 ]] ; then
208 eerror "ERROR: problems stopping dependent services."
209 eerror " ${myservice} is still up."
210 else
211 # Now that deps are stopped, stop our service
212 (
213 exit() {
214 RC_QUIET_STDOUT="no"
215 eerror "DO NOT USE EXIT IN INIT.D SCRIPTS"
216 eerror "This IS a bug, please fix your broken init.d"
217 unset -f exit
218 exit $@
219 }
220 # Stop einfo/ebegin/eend from working as parallel messes us up
221 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes"
222 stop
223 )
224 retval=$?
225
226 # If a service has been marked inactive, exit now as something
227 # may attempt to start it again later
228 if service_inactive "${myservice}" ; then
229 svcinactive=0
230 [[ ${svcbegun} == 0 ]] && end_service "${myservice}" 0
231 return 0
232 fi
233 fi
234
235 if [[ ${retval} != 0 ]] ; then
236 # Did we fail to stop? create symlink to stop multible attempts at
237 # runlevel change. Note this is only used at runlevel change ...
238 is_runlevel_stop && mark_service_failed "${myservice}"
239
240 # If we are halting the system, do it as cleanly as possible
241 if [[ ${SOFTLEVEL} != "reboot" && ${SOFTLEVEL} != "shutdown" ]] ; then
242 if [[ ${svcinactive} == 0 ]] ; then
243 mark_service_inactive "${myservice}"
244 else
245 mark_service_started "${myservice}"
246 fi
247 fi
248
249 service_message "eerror" "FAILED to stop service ${myservice}!"
250 else
251 # If we're stopped from a daemon that sets ${IN_BACKGROUND} such as
252 # wpa_monitor when we mark as inactive instead of taking the down
253 svcstarted=1
254 if service_inactive "${myservice}" ; then
255 svcinactive=0
256 else
257 mark_service_stopped "${myservice}"
258 fi
259 service_message "Stopped service ${myservice}"
260 fi
261
262 if [[ ${svcbegun} == 0 ]] ; then
263 end_service "${myservice}" "${retval}"
264 svcbegun=1
265 fi
266
267 # Reset the trap
268 svc_trap
269
270 return "${retval}"
271 }
272
273 svc_start() {
274 local x= y= retval=0 startfail= startinactive=
275
276 # Do not try to start if i have done so already on runlevel change
277 if is_runlevel_start && service_failed "${myservice}" ; then
278 return 1
279 fi
280
281 if service_started "${myservice}" ; then
282 ewarn "WARNING: ${myservice} has already been started."
283 return 0
284 elif service_stopping "${myservice}" ; then
285 eerror "ERROR: please wait for ${myservice} to stop first."
286 return 1
287 elif service_inactive "${myservice}" ; then
288 if [[ ${IN_BACKGROUND} != "true" ]] ; then
289 ewarn "WARNING: ${myservice} has already been started."
290 return 0
291 fi
292 fi
293
294 if ! mark_service_starting "${myservice}" ; then
295 ewarn "WARNING: ${myservice} is already starting."
296 return 0
297 fi
298
299 # Ensure that we clean up if we abort for any reason
300 trap "svc_quit" INT QUIT TSTP
301
302 begin_service "${myservice}"
303 svcbegun=$?
304
305 service_message "Starting service ${myservice}"
306
307 # Save the IN_BACKGROUND var as we need to clear it for starting depends
308 local ib_save="${IN_BACKGROUND}"
309 unset IN_BACKGROUND
310
311 local startupservices="$(trace_dependencies $(ineed "${myservice}") \
312 $(valid_iuse ${myservice}))"
313 local netservices="$(dolisting "/etc/runlevels/${BOOTLEVEL}/net.*") \
314 $(dolisting "/etc/runlevels/${mylevel}/net.*")"
315 local startupnetservices=
316
317 # Start dependencies, if any.
318 # We don't handle "after" deps here as it's the job of rc to start them.
319 for x in ${startupservices} ; do
320 if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] && ! is_net_up ; then
321 for y in ${netservices} ; do
322 y="${y##*/}"
323 service_stopped "${y}" && start_service "${y}"
324 done
325 elif [[ ${x} != "net" ]] ; then
326 if service_stopped "${x}" ; then
327 start_service "${x}"
328 fi
329 fi
330 done
331
332 # We also wait for any services we're after to finish incase they
333 # have a "before" dep but we don't dep on them.
334 if is_runlevel_start ; then
335 startupservices="${startupservices} $(valid_iafter ${myservice})"
336 fi
337
338 # Wait for dependencies to finish.
339 for x in ${startupservices} ; do
340 if [[ ${x} == "net" && ${NETSERVICE} != "yes" ]] ; then
341 for y in ${netservices} ; do
342 y="${y##*/}"
343 # Don't wait if it's already been started
344 service_started "${y}" && continue
345 wait_service "${y}"
346 if ! service_started "${y}" ; then
347 # A 'need' dependency is critical for startup
348 if ineed -t "${myservice}" "${x}" >/dev/null ; then
349 if ! is_net_up ; then
350 if service_inactive "${y}" ; then
351 svc_schedule_restart "${y}"
352 startinactive="${y}"
353 else
354 startfail="${y}"
355 fi
356 break
357 fi
358 fi
359 fi
360 done
361 elif [[ ${x} != "net" ]] ; then
362 # Don't wait if it's already been started
363 service_started "${x}" && continue
364 wait_service "${x}"
365 if ! service_started "${x}" ; then
366 # A 'need' dependacy is critical for startup
367 if ineed -t "${myservice}" "${x}" >/dev/null ; then
368 if service_inactive "${x}" ; then
369 svc_schedule_restart "${x}"
370 startinactive="${x}"
371 else
372 startfail="${x}"
373 fi
374 break
375 fi
376 fi
377 fi
378 done
379
380 if [[ ${startfail} == "yes" ]] ; then
381 eerror "ERROR: Problem starting needed service ${startfail}."
382 eerror " ${myservice} was not started."
383 retval=1
384 elif [[ -n ${startinactive} ]] ; then
385 ewarn "WARNING: ${myservice} is scheduled to start when ${startinactive} has started."
386 retval=1
387 elif broken "${myservice}" ; then
388 eerror "ERROR: Some services needed are missing. Run"
389 eerror " './${myservice} broken' for a list of those"
390 eerror " services. ${myservice} was not started."
391 retval=1
392 else
393 IN_BACKGROUND="${ib_save}"
394 (
395 exit() {
396 RC_QUIET_STDOUT="no"
397 eerror "DO NOT USE EXIT IN INIT.D SCRIPTS"
398 eerror "This IS a bug, please fix your broken init.d"
399 unset -f exit
400 exit $@
401 }
402 # Stop einfo/ebegin/eend from working as parallel messes us up
403 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && RC_QUIET_STDOUT="yes"
404 start
405 )
406 retval=$?
407
408 # If a service has been marked inactive, exit now as something
409 # may attempt to start it again later
410 if service_inactive "${myservice}" ; then
411 svcinactive=0
412 [[ ${svcbegun} == 0 ]] && end_service "${myservice}" 1
413 return 1
414 fi
415 fi
416
417 if [[ ${retval} != 0 ]] ; then
418 # Remove link if service didn't start; but only if we're not booting
419 # If we're booting, we need to continue and do our best to get the
420 # system up.
421 if [[ ${SOFTLEVEL} != "${BOOTLEVEL}" ]] ; then
422 if [[ ${svcinactive} == 0 ]] ; then
423 mark_service_inactive "${myservice}"
424 else
425 mark_service_stopped "${myservice}"
426 fi
427 fi
428
429 if [[ -z ${startinactive} ]] ; then
430 is_runlevel_start && mark_service_failed "${myservice}"
431 service_message "eerror" "FAILED to start service ${myservice}!"
432 fi
433 else
434 svcstarted=0
435 mark_service_started "${myservice}"
436 service_message "Service ${myservice} started OK"
437 fi
438
439 if [[ ${svcbegun} == 0 ]] ; then
440 end_service "${myservice}" "${retval}"
441 svcbegun=1
442 fi
443
444 # Reset the trap
445 svc_trap
446
447 return "${retval}"
448 }
449
450 svc_restart() {
451 if ! service_stopped "${myservice}" ; then
452 svc_stop || return "$?"
453 fi
454 svc_start || return "$?"
455 }
456
457 svc_status() {
458 # The basic idea here is to have some sort of consistent
459 # output in the status() function which scripts can use
460 # as an generic means to detect status. Any other output
461 # should thus be formatted in the custom status() function
462 # to work with the printed " * status: foo".
463 local efunc="" state=""
464
465 # If we are effectively root, check to see if required daemons are running
466 # and update our status accordingly
467 [[ ${EUID} == 0 ]] && update_service_status "${myservice}"
468
469 if service_stopping "${myservice}" ; then
470 efunc="eerror"
471 state="stopping"
472 elif service_starting "${myservice}" ; then
473 efunc="einfo"
474 state="starting"
475 elif service_inactive "${myservice}" ; then
476 efunc="ewarn"
477 state="inactive"
478 elif service_started "${myservice}" ; then
479 efunc="einfo"
480 state="started"
481 else
482 efunc="eerror"
483 state="stopped"
484 fi
485 [[ ${RC_QUIET_STDOUT} != "yes" ]] \
486 && ${efunc} "status: ${state}"
487
488 status
489 # Return 0 if started, otherwise 1
490 [[ ${state} == "started" ]]
491 }
492
493 rcscript_errors="$(bash -n ${myscript} 2>&1)" || {
494 [[ -n ${rcscript_errors} ]] && echo "${rcscript_errors}" >&2
495 eerror "ERROR: \"${myscript}\" has syntax errors in it; aborting ..."
496 exit 1
497 }
498
499 # set *after* wrap_rcscript, else we get duplicates.
500 opts="start stop restart"
501
502 source "${myscript}"
503
504 # make sure whe have valid $opts
505 if [[ -z ${opts} ]] ; then
506 opts="start stop restart"
507 fi
508
509 svc_homegrown() {
510 local x arg="$1"
511 shift
512
513 # Walk through the list of available options, looking for the
514 # requested one.
515 for x in ${opts} ; do
516 if [[ ${x} == "${arg}" ]] ; then
517 if typeset -F "${x}" &>/dev/null ; then
518 # Run the homegrown function
519 "${x}"
520
521 return $?
522 fi
523 fi
524 done
525 x=""
526
527 # If we're here, then the function wasn't in $opts.
528 [[ -n $* ]] && x="/ $* "
529 eerror "ERROR: wrong args ( "${arg}" ${x})"
530 # Do not quote this either ...
531 usage ${opts}
532 exit 1
533 }
534
535 shift
536 if [[ $# -lt 1 ]] ; then
537 eerror "ERROR: not enough args."
538 usage ${opts}
539 exit 1
540 fi
541 for arg in $* ; do
542 case "${arg}" in
543 --quiet)
544 RC_QUIET_STDOUT="yes"
545 ;;
546 # We check this in functions.sh ...
547 # --nocolor)
548 # RC_NOCOLOR="yes"
549 # ;;
550 --verbose)
551 RC_VERBOSE="yes"
552 ;;
553 esac
554 done
555 for arg in $* ; do
556 case "${arg}" in
557 stop)
558 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
559 rm -f "${svcdir}/restart/${myservice}"
560 fi
561
562 # Stoped from the background - treat this as a restart so that
563 # stopped services come back up again when started.
564 if [[ ${IN_BACKGROUND} == "true" ]] ; then
565 rm -rf "${svcdir}/snapshot/$$"
566 mkdir -p "${svcdir}/snapshot/$$"
567 cp -pP "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
568 fi
569
570 svc_stop
571 retval="$?"
572
573 if [[ ${IN_BACKGROUND} == "true" ]] ; then
574 res=
575 for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
576 service_stopped "${x##*/}" && svc_schedule_restart "${x##*/}"
577 done
578 fi
579
580 exit "${retval}"
581 ;;
582 start)
583 svc_start
584 retval=$?
585 if ! is_runlevel_start && [[ -s "${svcdir}/restart/${myservice}" ]] ; then
586 for x in $(trace_dependencies $(< "${svcdir}/restart/${myservice}")) ; do
587 service_stopped "${x}" && start_service "${x}"
588 done
589 fi
590 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
591 rm -f "${svcdir}/restart/${myservice}"
592 fi
593 exit "${retval}"
594 ;;
595 needsme|ineed|usesme|iuse|broken)
596 trace_dependencies "-${arg}"
597 ;;
598 status)
599 svc_status
600 ;;
601 zap)
602 if [[ -e "${svcdir}/restart/${myservice}" ]] ; then
603 rm -f "${svcdir}/restart/${myservice}"
604 fi
605 if ! service_stopped "${myservice}" ; then
606 einfo "Manually resetting ${myservice} to stopped state."
607 mark_service_stopped "${myservice}"
608 fi
609 end_service "${myservice}"
610 ;;
611 restart)
612 svcrestart="yes"
613
614 # We don't kill child processes if we're restarting
615 # This is especically important for sshd ....
616 RC_KILL_CHILDREN="no"
617
618 # Create a snapshot of started services
619 rm -rf "${svcdir}/snapshot/$$"
620 mkdir -p "${svcdir}/snapshot/$$"
621 cp -pP "${svcdir}"/started/* "${svcdir}/snapshot/$$/"
622
623 # Simple way to try and detect if the service use svc_{start,stop}
624 # to restart if it have a custom restart() funtion.
625 if [[ -n $(egrep '^[[:space:]]*restart[[:space:]]*()' "/etc/init.d/${myservice}") ]] ; then
626 if [[ -z $(egrep 'svc_stop' "/etc/init.d/${myservice}") || \
627 -z $(egrep 'svc_start' "/etc/init.d/${myservice}") ]] ; then
628 echo
629 ewarn "Please use 'svc_stop; svc_start' and not 'stop; start' to"
630 ewarn "restart the service in its custom 'restart()' function."
631 ewarn "Run ${myservice} without arguments for more info."
632 echo
633 svc_restart
634 else
635 restart
636 fi
637 else
638 restart
639 fi
640
641 # Restart dependencies as well
642 if service_started "${myservice}" ; then
643 for x in $(trace_dependencies \
644 $(dolisting "${svcdir}/snapshot/$$/") ) ; do
645 if service_stopped "${x##*/}" ; then
646 start_service "${x##*/}"
647 fi
648 done
649 elif service_inactive "${myservice}" ; then
650 res=
651 for x in $(dolisting "${svcdir}/snapshot/$$/") ; do
652 if service_stopped "${x##*/}" ; then
653 res="${res}${x##*/} "
654 fi
655 done
656 [[ -n ${res} ]] && echo "${res}" > "${svcdir}/restart/${myservice}"
657 fi
658
659 # Wait for any services that may still be running ...
660 [[ ${RC_PARALLEL_STARTUP} == "yes" ]] && wait
661
662 rm -rf "${svcdir}/snapshot/$$"
663 svcrestart="no"
664 ;;
665 pause)
666 svcpause="yes"
667 svc_stop
668 svcpause="no"
669 ;;
670 --quiet|--nocolor)
671 ;;
672 help)
673 exec "${svclib}"/sh/rc-help.sh "${myscript}" help
674 ;;
675 *)
676 # Allow for homegrown functions
677 svc_homegrown ${arg}
678 ;;
679 esac
680 done
681
682 # vim:ts=4

Properties

Name Value
svn:eol-style native
svn:executable *
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.20