source: bootscripts-standard/clfs/init.d/functions @ 7355219

Last change on this file since 7355219 was 7355219, checked in by Chris Staub <chris@…>, 16 years ago

killproc function uses sleep

  • Property mode set to 100644
File size: 17.4 KB
Line 
1#!/bin/bash
2########################################################################
3# Begin $rc_base/init.d/functions
4#
5# Description : Run Level Control Functions
6#
7# Authors     : Gerard Beekmans - gerard@linuxfromscratch.org
8#
9# Version     : 00.00
10#
11# Notes       : With code based on Matthias Benkmann's simpleinit-msb
12#               http://winterdrache.de/linux/newboot/index.html
13#
14########################################################################
15
16if [ -e /etc/sysconfig/lcd ]; then
17        if [ -e /dev/lcd ]; then
18                source /etc/sysconfig/lcd
19        fi
20fi
21
22if [ -e /etc/sysconfig/bootscripts ]; then
23        source /etc/sysconfig/bootscripts
24fi
25
26## Environmental setup
27# Setup default values for environment
28umask 022
29export PATH="/bin:/usr/bin:/sbin:/usr/sbin"
30
31# Signal sent to running processes to refresh their configuration
32RELOADSIG="HUP"
33
34# Number of seconds between STOPSIG and FALLBACK when stopping processes
35KILLDELAY="3"
36
37## Screen Dimensions
38# Find current screen size
39if [ -z "${COLUMNS}" ]; then
40        COLUMNS=$(stty size)
41        COLUMNS=${COLUMNS##* }
42fi
43
44# When using remote connections, such as a serial port, stty size returns 0
45if [ "${COLUMNS}" = "0" ]; then 
46        COLUMNS=80
47fi
48
49## Measurements for positioning result messages
50COL=$((${COLUMNS} - 8))
51WCOL=$((${COL} - 2))
52
53## Provide an echo that supports -e and -n
54# If formatting is needed, $ECHO should be used
55case "`echo -e -n test`" in
56        -[en]*)
57                ECHO=/bin/echo
58                ;;
59        *)
60                ECHO=echo
61                ;;
62esac
63
64## Set Cursor Position Commands, used via $ECHO
65SET_COL="\\033[${COL}G"      # at the $COL char
66SET_WCOL="\\033[${WCOL}G"    # at the $WCOL char
67CURS_UP="\\033[1A\\033[0G"   # Up one line, at the 0'th char
68
69## Set color commands, used via $ECHO
70# Please consult `man console_codes for more information
71# under the "ECMA-48 Set Graphics Rendition" section
72#
73# Warning: when switching from a 8bit to a 9bit font,
74# the linux console will reinterpret the bold (1;) to
75# the top 256 glyphs of the 9bit font.  This does
76# not affect framebuffer consoles
77NORMAL="\\033[0;39m"         # Standard console grey
78SUCCESS="\\033[1;32m"        # Success is green
79WARNING="\\033[1;33m"        # Warnings are yellow
80FAILURE="\\033[1;31m"        # Failures are red
81INFO="\\033[1;36m"           # Information is light cyan
82BRACKET="\\033[1;34m"        # Brackets are blue
83
84STRING_LENGTH="0"   # the length of the current message
85
86#*******************************************************************************
87# Function - boot_mesg()
88#
89# Purpose:      Sending information from bootup scripts to the console
90#
91# Inputs:       $1 is the message
92#               $2 is the colorcode for the console
93#
94# Outputs:      Standard Output
95#
96# Dependencies: - sed for parsing strings.
97#               - grep for counting string length.
98#               
99# Todo:         
100#*******************************************************************************
101boot_mesg()
102{
103        local ECHOPARM=""
104
105        if [ "$LCD_PROG" ]; then
106                LCD_OUT1="${1:0:$LCD_CHAR}"
107                $LCD_PROG "$LCD_OUT1" > /dev/null 2>&1
108        fi
109
110        while true
111        do
112                case "${1}" in
113                        -n)
114                                ECHOPARM=" -n "
115                                shift 1
116                                ;;
117                        -*)
118                                echo "Unknown Option: ${1}"
119                                return 1
120                                ;;
121                        *)
122                                break
123                                ;;
124                esac
125        done
126
127        ## Figure out the length of what is to be printed to be used
128        ## for warning messages.
129        STRING_LENGTH=$((${#1} + 1))
130
131        # Print the message to the screen
132        ${ECHO} ${ECHOPARM} -e "${2}${1}"
133       
134}
135
136boot_mesg_flush()
137{
138        # Reset STRING_LENGTH for next message
139        STRING_LENGTH="0"
140        if [ "$LOGGING" ]; then
141                boot_log "${BOOTMESG}${@}"
142        fi
143}
144
145boot_log()
146{
147        if [ "$LOGGING" ]; then
148                /bin/logger -p local2.info -t bootlog "${DISPLAYLOG} ${1}"
149        else
150                return 0
151        fi
152}
153
154echo_ok()
155{
156        if [ "$LCD_PROG" ]; then
157                if [ "$LCD_LINES" = "2" ]; then
158                        LCD_OUT2="[  OK  ]"
159                        $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
160                else
161                        LCD_OUT2="${LCD_OUT1:0:12} OK"
162                        $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
163                fi
164        fi
165        ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS}  OK  ${BRACKET}]"
166        ${ECHO} -e "${NORMAL}"
167        boot_mesg_flush
168}
169
170echo_failure()
171{
172        if [ "$LCD_PROG" ]; then
173                if [ "$LCD_LINES" = "2" ]; then
174                        LCD_OUT2="[ FAIL  ]"
175                        $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
176                else
177                        LCD_OUT2="${LCD_OUT1:0:10} FAIL"
178                        $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
179                fi
180        fi
181        ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]"
182        ${ECHO} -e "${NORMAL}"
183        boot_mesg_flush
184}
185
186echo_warning()
187{
188        if [ "$LCD_PROG" ]; then
189                if [ "$LCD_LINES" = "2" ]; then
190                        LCD_OUT2="[ WARN  ]"
191                        $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
192                else
193                        LCD_OUT2="${LCD_OUT1:0:10} WARN"
194                        $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
195                fi
196        fi
197        ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]"
198        ${ECHO} -e "${NORMAL}"
199        boot_mesg_flush
200}
201
202print_error_msg()
203{
204        echo_failure
205        # $i is inherited by the rc script
206        boot_log "\n\n${i} failed and exited with a return value of ${error_value}."
207        boot_mesg -n "FAILURE:\n\nYou should not be reading this error message.\n\n" ${FAILURE}
208        boot_mesg -n " It means that an unforeseen error took"
209        boot_mesg -n " place in ${i}, which exited with a return value of"
210        boot_mesg " ${error_value}.\n"
211        boot_mesg_flush
212        boot_mesg -n "If you're able to track this"
213        boot_mesg -n " error down to a bug in one of the files provided by"
214        boot_mesg -n " the CLFS book, please be so kind to inform us at"
215        boot_mesg " clfs-dev@cross-lfs.org.\n"
216        boot_mesg_flush
217        boot_mesg -n "Press Enter to continue..." ${INFO}
218        boot_mesg "" ${NORMAL}
219        read ENTER
220}
221
222check_script_status()
223{
224        # $i is inherited by the rc script
225        if [ ! -f ${i} ]; then
226                boot_mesg "${i} is not a valid symlink." ${WARNING}
227                echo_warning
228                continue
229        fi
230
231        if [ ! -x ${i} ]; then
232                boot_mesg "${i} is not executable, skipping." ${WARNING}
233                echo_warning
234                continue
235        fi
236}
237
238evaluate_retval()
239{
240        error_value="${?}"
241
242        if [ ${error_value} = 0 ]; then
243                echo_ok
244        else
245                echo_failure
246        fi
247
248        # This prevents the 'An Unexpected Error Has Occurred' from trivial
249        # errors.
250        return 0
251}
252
253print_status()
254{
255        if [ "${#}" = "0" ]; then
256                echo "Usage: ${0} {success|warning|failure}"
257                return 1
258        fi
259
260        case "${1}" in
261
262                success)
263                        echo_ok
264                        ;;
265
266                warning)
267                        # Leave this extra case in because old scripts
268                        # may call it this way.
269                        case "${2}" in
270                                running)
271                                        ${ECHO} -e -n "${CURS_UP}"
272                                        ${ECHO} -e -n "\\033[${STRING_LENGTH}G   "
273                                        boot_mesg "Already running." ${WARNING}
274                                        echo_warning
275                                        ;;
276                                not_running)
277                                        ${ECHO} -e -n "${CURS_UP}"
278                                        ${ECHO} -e -n "\\033[${STRING_LENGTH}G   "
279                                        boot_mesg "Not running." ${WARNING}
280                                        echo_warning
281                                        ;;
282                                not_available)
283                                        ${ECHO} -e -n "${CURS_UP}"
284                                        ${ECHO} -e -n "\\033[${STRING_LENGTH}G   "
285                                        boot_mesg "Not available." ${WARNING}
286                                        echo_warning
287                                        ;;
288                                *)
289                                        # This is how it is supposed to
290                                        # be called
291                                        echo_warning
292                                        ;;
293                        esac
294                ;;
295
296                failure)
297                        echo_failure
298                ;;
299
300        esac
301
302}
303
304reloadproc()
305{
306        local pidfile=""
307        local failure=0
308
309        while true
310        do
311                case "${1}" in
312                        -p)
313                                pidfile="${2}"
314                                shift 2
315                                ;;
316                        -*)
317                                log_failure_msg "Unknown Option: ${1}"
318                                return 2
319                                ;;
320                        *)
321                                break
322                                ;;
323                esac
324        done
325
326        if [ "${#}" -lt "1" ]; then
327                log_failure_msg "Usage: reloadproc [-p pidfile] pathname"
328                return 2
329        fi
330
331        # This will ensure compatibility with previous CLFS Bootscripts
332        if [ -n "${PIDFILE}" ]; then
333                pidfile="${PIDFILE}"
334        fi
335
336        # Is the process running?
337        if [ -z "${pidfile}" ]; then
338                pidofproc -s "${1}"
339        else
340                pidofproc -s -p "${pidfile}" "${1}"
341        fi
342
343        if [ -n "${pidlist}" ]; then
344                for pid in ${pidlist}
345                do
346                        kill -"${RELOADSIG}" "${pid}" || failure="1"
347                done
348
349                (exit ${failure})
350                evaluate_retval
351
352        else
353                boot_mesg "Process ${1} not running." ${WARNING}
354                echo_warning
355        fi
356}
357
358statusproc()
359{
360        local pidfile=""
361        local base=""
362        local ret=""
363
364        while true
365        do
366                case "${1}" in
367                        -p)
368                                pidfile="${2}"
369                                shift 2
370                                ;;
371                        -*)
372                                log_failure_msg "Unknown Option: ${1}"
373                                return 2
374                                ;;
375                        *)
376                                break
377                                ;;
378                esac
379        done
380
381        if [ "${#}" != "1" ]; then
382                shift 1
383                log_failure_msg "Usage: statusproc [-p pidfile] pathname"
384                return 2
385        fi
386
387        # Get the process basename
388        base="${1##*/}"
389
390        # This will ensure compatibility with previous CLFS Bootscripts
391        if [ -n "${PIDFILE}" ]; then
392                pidfile="${PIDFILE}"
393        fi
394
395        # Is the process running?
396        if [ -z "${pidfile}" ]; then
397                pidofproc -s "${1}"
398        else
399                pidofproc -s -p "${pidfile}" "${1}"
400        fi
401
402        # Store the return status
403        ret=$?
404
405        if [ -n "${pidlist}" ]; then
406                ${ECHO} -e "${INFO}${base} is running with Process"\
407                        "ID(s) ${pidlist}.${NORMAL}"
408        else
409                if [ -n "${base}" -a -e "/var/run/${base}.pid" ]; then
410                        ${ECHO} -e "${WARNING}${1} is not running but"\
411                                "/var/run/${base}.pid exists.${NORMAL}"
412                else
413                        if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
414                                ${ECHO} -e "${WARNING}${1} is not running"\
415                                        "but ${pidfile} exists.${NORMAL}"
416                        else
417                                ${ECHO} -e "${INFO}${1} is not running.${NORMAL}"
418                        fi
419                fi
420        fi
421
422        # Return the status from pidofproc
423        return $ret
424}
425
426# The below functions are documented in the LSB-generic 2.1.0
427
428#*******************************************************************************
429# Function - pidofproc [-s] [-p pidfile] pathname
430#
431# Purpose: This function returns one or more pid(s) for a particular daemon
432#
433# Inputs: -p pidfile, use the specified pidfile instead of pidof
434#         pathname, path to the specified program
435#
436# Outputs: return 0 - Success, pid's in stdout
437#          return 1 - Program is dead, pidfile exists
438#          return 2 - Invalid or excessive number of arguments,
439#                     warning in stdout
440#          return 3 - Program is not running
441#
442# Dependencies: pidof, echo, head
443#
444# Todo: Remove dependency on head
445#       This depreciates getpids
446#       Test changes to pidof
447#
448#*******************************************************************************
449pidofproc()
450{
451        local pidfile=""
452        local lpids=""
453        local silent=""
454        pidlist=""
455        while true
456        do
457                case "${1}" in
458                        -p)
459                                pidfile="${2}"
460                                shift 2
461                                ;;
462
463                        -s)
464                                # Added for legacy opperation of getpids
465                                # eliminates several '> /dev/null'
466                                silent="1"
467                                shift 1
468                                ;;
469                        -*)
470                                log_failure_msg "Unknown Option: ${1}"
471                                return 2
472                                ;;
473                        *)
474                                break
475                                ;;
476                esac
477        done
478
479        if [ "${#}" != "1" ]; then
480                shift 1
481                log_failure_msg "Usage: pidofproc [-s] [-p pidfile] pathname"
482                return 2
483        fi
484
485        if [ -n "${pidfile}" ]; then
486                if [ ! -r "${pidfile}" ]; then
487                        return 3 # Program is not running
488                fi
489
490                lpids=`head -n 1 ${pidfile}`
491                for pid in ${lpids}
492                do
493                        if [ "${pid}" -ne "$$" -a "${pid}" -ne "${PPID}" ]; then
494                                kill -0 "${pid}" 2>/dev/null &&
495                                pidlist="${pidlist} ${pid}"
496                        fi
497                       
498                        if [ "${silent}" != "1" ]; then
499                                echo "${pidlist}"
500                        fi
501
502                        test -z "${pidlist}" && 
503                        # Program is dead, pidfile exists
504                        return 1
505                        # else
506                        return 0
507                done
508
509        else
510                pidlist=`pidof -o $$ -o $PPID -x "$1"`
511                if [ "${silent}" != "1" ]; then
512                        echo "${pidlist}"
513                fi
514
515                # Get provide correct running status
516                if [ -n "${pidlist}" ]; then
517                        return 0
518                else
519                        return 3
520                fi
521
522        fi
523
524        if [ "$?" != "0" ]; then
525                return 3 # Program is not running
526        fi
527}
528
529# This will ensure compatibility with previous CLFS Bootscripts
530getpids()
531{
532        if [ -z "${PIDFILE}" ]; then
533                pidofproc -s -p "${PIDFILE}" $@
534        else
535                pidofproc -s $@
536        fi
537        base="${1##*/}"
538}
539
540#*******************************************************************************
541# Function - loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]
542#
543# Purpose: This runs the specified program as a daemon
544#
545# Inputs: -f, run the program even if it is already running
546#         -n nicelevel, specifies a nice level. See nice(1).
547#         -p pidfile, uses the specified pidfile
548#         pathname, pathname to the specified program
549#         args, arguments to pass to specified program
550#
551# Outputs: return 0 - Success
552#          return 2 - Invalid of excessive number of arguments,
553#                     warning in stdout
554#          return 4 - Program or service status is unknown
555#
556# Dependencies: nice
557#
558# Todo: LSB says this should be called start_daemon
559#       LSB does not say that it should call evaluate_retval
560#       It checks for PIDFILE, which is deprecated.
561#         Will be removed after BLFS 6.0
562#       loadproc returns 0 if program is already running, not LSB compliant
563#
564#*******************************************************************************
565loadproc()
566{
567        local pidfile=""
568        local forcestart=""
569        local nicelevel="10"
570
571# This will ensure compatibility with previous CLFS Bootscripts
572        if [ -n "${PIDFILE}" ]; then
573                pidfile="${PIDFILE}"
574        fi
575
576  while true
577        do
578                case "${1}" in
579                        -f)
580                                forcestart="1"
581                                shift 1
582                                ;;
583                        -n)
584                                nicelevel="${2}"
585                                shift 2
586                                ;;
587                        -p)
588                                pidfile="${2}"
589                                shift 2
590                                ;;
591                        -*)
592                                log_failure_msg "Unknown Option: ${1}"
593                                return 2 #invalid or excess argument(s)
594                                ;;
595                        *)
596                                break
597                                ;;
598                esac
599        done
600
601        if [ "${#}" = "0" ]; then
602                log_failure_msg "Usage: loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]"
603                return 2 #invalid or excess argument(s)
604        fi
605
606        if [ -z "${forcestart}" ]; then
607                if [ -z "${pidfile}" ]; then
608                        pidofproc -s "${1}"
609                else
610                        pidofproc -s -p "${pidfile}" "${1}"
611                fi
612
613                case "${?}" in
614                        0)
615                                log_warning_msg "Unable to continue: ${1} is running"
616                                return 0 # 4
617                                ;;
618                        1)
619                                log_warning_msg "Unable to continue: ${pidfile} exists"
620                                return 0 # 4
621                                ;;
622                        3)
623                                ;;
624                        *)
625                                log_failure_msg "Unknown error code from pidofproc: ${?}"
626                                return 4
627                                ;;
628                esac
629        fi
630
631        nice -n "${nicelevel}" "${@}"
632        evaluate_retval # This is "Probably" not LSB compliant, but required to be compatible with older bootscripts
633        return 0
634}
635
636#*******************************************************************************
637# Function - killproc  [-p pidfile] pathname [signal]
638#
639# Purpose:
640#
641# Inputs: -p pidfile, uses the specified pidfile
642#         pathname, pathname to the specified program
643#         signal, send this signal to pathname
644#
645# Outputs: return 0 - Success
646#          return 2 - Invalid of excessive number of arguments,
647#                     warning in stdout
648#          return 4 - Unknown Status
649#
650# Dependencies: kill, sleep
651#
652# Todo: LSB does not say that it should call evaluate_retval
653#       It checks for PIDFILE, which is deprecated.
654#         Will be removed after BLFS 6.0
655#
656#*******************************************************************************
657killproc()
658{
659        local pidfile=""
660        local killsig=TERM # default signal is SIGTERM
661        pidlist=""
662
663        # This will ensure compatibility with previous CLFS Bootscripts
664        if [ -n "${PIDFILE}" ]; then
665                pidfile="${PIDFILE}"
666        fi
667
668        while true
669        do
670                case "${1}" in
671                        -p)
672                                pidfile="${2}"
673                                shift 2
674                                ;;
675                        -*)
676                                log_failure_msg "Unknown Option: ${1}"
677                                return 2
678                                ;;
679                        *)
680                                break
681                                ;;
682                esac
683        done
684
685        if [ "${#}" = "2" ]; then
686                killsig="${2}"
687        elif [ "${#}" != "1" ]; then
688                shift 2
689                log_failure_msg "Usage: killproc  [-p pidfile] pathname [signal]"
690                return 2
691        fi
692
693        # Is the process running?
694        if [ -z "${pidfile}" ]; then
695                pidofproc -s "${1}"
696        else
697                pidofproc -s -p "${pidfile}" "${1}"
698        fi
699
700    # If running, send the signal
701    if [ -n "${pidlist}" ]; then
702        for pid in ${pidlist}
703        do
704                kill -${killsig} ${pid} 2>/dev/null
705
706                # Wait up to 3 seconds, for ${pid} to terminate
707                case "${killsig}" in
708                TERM|SIGTERM|KILL|SIGKILL)
709                        # sleep in 1/10ths of seconds and
710                        # multiply KILLDELAY by 10
711                        local dtime="${KILLDELAY}0"
712                        while [ "${dtime}" != "0" ]
713                        do
714                                kill -0 ${pid} 2>/dev/null || break
715                                sleep 0.1
716                                dtime=$(( ${dtime} - 1))
717                        done
718                        # If ${pid} is still running, kill it
719                        kill -0 ${pid} 2>/dev/null && kill -KILL ${pid} 2>/dev/null
720                        ;;
721                esac
722        done
723
724        # Check if the process is still running if we tried to stop it
725        case "${killsig}" in
726        TERM|SIGTERM|KILL|SIGKILL)
727                if [ -z "${pidfile}" ]; then
728                        pidofproc -s "${1}"
729                else
730                        pidofproc -s -p "${pidfile}" "${1}"
731                fi
732
733                # Program was terminated
734                if [ "$?" != "0" ]; then
735                        # Remove the pidfile if necessary
736                        if [ -f "${pidfile}" ]; then
737                                rm -f "${pidfile}"
738                        fi
739                        echo_ok
740                        return 0
741                else # Program is still running
742                        echo_failure
743                        return 4 # Unknown Status
744                fi
745                ;;
746        *)
747                # Just see if the kill returned successfully
748                evaluate_retval
749                ;;
750        esac
751    else # process not running
752        print_status warning not_running
753    fi
754}
755
756
757#*******************************************************************************
758# Function - log_success_msg "message"
759#
760# Purpose: Print a success message
761#
762# Inputs: $@ - Message
763#
764# Outputs: Text output to screen
765#
766# Dependencies: echo
767#
768# Todo: logging
769#
770#*******************************************************************************
771log_success_msg()
772{
773        ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
774        ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}""  OK  ""${BRACKET}""]""${NORMAL}"
775        return 0
776}
777
778#*******************************************************************************
779# Function - log_failure_msg "message"
780#
781# Purpose: Print a failure message
782#
783# Inputs: $@ - Message
784#
785# Outputs: Text output to screen
786#
787# Dependencies: echo
788#
789# Todo: logging
790#
791#*******************************************************************************
792log_failure_msg() {
793        ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
794        ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}"
795        return 0
796}
797
798#*******************************************************************************
799# Function - log_warning_msg "message"
800#
801# Purpose: print a warning message
802#
803# Inputs: $@ - Message
804#
805# Outputs: Text output to screen
806#
807# Dependencies: echo
808#
809# Todo: logging
810#
811#*******************************************************************************
812log_warning_msg() {
813        ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
814        ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}"
815        return 0
816}
817
818# End $rc_base/init.d/functions
Note: See TracBrowser for help on using the repository browser.