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

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

Changed all /var/run references to /run

  • Property mode set to 100644
File size: 17.6 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        # Message Log
135        if [ -z "${BOOTMESG}" ]
136        then
137                BOOTMESG="${1}"
138        else
139                BOOTMESG="${BOOTMESG} ${1}"
140        fi
141}
142
143boot_mesg_flush()
144{
145        # Reset STRING_LENGTH for next message
146        STRING_LENGTH="0"
147        if [ "$LOGGING" ]; then
148                boot_log "${BOOTMESG}${@}"
149                BOOTMESG=""
150        fi
151}
152
153boot_log()
154{
155        if [ "$LOGGING" ]; then
156                /bin/logger -p local2.info -t bootlog "${DISPLAYLOG} ${1}"
157        else
158                return 0
159        fi
160}
161
162echo_ok()
163{
164        if [ "$LCD_PROG" ]; then
165                if [ "$LCD_LINES" = "2" ]; then
166                        LCD_OUT2="[  OK  ]"
167                        $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
168                else
169                        LCD_OUT2="${LCD_OUT1:0:12} OK"
170                        $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
171                fi
172        fi
173        ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${SUCCESS}  OK  ${BRACKET}]"
174        ${ECHO} -e "${NORMAL}"
175        BOOTMESG="${BOOTMESG} [ OK ]"
176        boot_mesg_flush
177}
178
179echo_failure()
180{
181        if [ "$LCD_PROG" ]; then
182                if [ "$LCD_LINES" = "2" ]; then
183                        LCD_OUT2="[ FAIL  ]"
184                        $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
185                else
186                        LCD_OUT2="${LCD_OUT1:0:10} FAIL"
187                        $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
188                fi
189        fi
190        ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${FAILURE} FAIL ${BRACKET}]"
191        ${ECHO} -e "${NORMAL}"
192        BOOTMESG="${BOOTMESG} [ FAIL ]"
193        boot_mesg_flush
194}
195
196echo_warning()
197{
198        if [ "$LCD_PROG" ]; then
199                if [ "$LCD_LINES" = "2" ]; then
200                        LCD_OUT2="[ WARN  ]"
201                        $LCD_PROG "$LCD_OUT1" "$LCD_OUT2" > /dev/null 2>&1
202                else
203                        LCD_OUT2="${LCD_OUT1:0:10} WARN"
204                        $LCD_PROG "$LCD_OUT2" > /dev/null 2>&1
205                fi
206        fi
207        ${ECHO} -n -e "${CURS_UP}${SET_COL}${BRACKET}[${WARNING} WARN ${BRACKET}]"
208        ${ECHO} -e "${NORMAL}"
209        BOOTMESG="${BOOTMESG} [ WARN ]"
210        boot_mesg_flush
211}
212
213print_error_msg()
214{
215        echo_failure
216        # $i is inherited by the rc script
217        boot_log "\n\n${i} failed and exited with a return value of ${error_value}."
218        boot_mesg -n "FAILURE:\n\nYou should not be reading this error message.\n\n" ${FAILURE}
219        boot_mesg -n " It means that an unforeseen error took"
220        boot_mesg -n " place in ${i}, which exited with a return value of"
221        boot_mesg " ${error_value}.\n"
222        boot_mesg_flush
223        boot_mesg -n "If you're able to track this"
224        boot_mesg -n " error down to a bug in one of the files provided by"
225        boot_mesg -n " the CLFS book, please be so kind to inform us at"
226        boot_mesg " clfs-dev@cross-lfs.org.\n"
227        boot_mesg_flush
228        boot_mesg -n "Press Enter to continue..." ${INFO}
229        boot_mesg "" ${NORMAL}
230        read ENTER
231}
232
233check_script_status()
234{
235        # $i is inherited by the rc script
236        if [ ! -f ${i} ]; then
237                boot_mesg "${i} is not a valid symlink." ${WARNING}
238                echo_warning
239                continue
240        fi
241
242        if [ ! -x ${i} ]; then
243                boot_mesg "${i} is not executable, skipping." ${WARNING}
244                echo_warning
245                continue
246        fi
247}
248
249evaluate_retval()
250{
251        error_value="${?}"
252
253        if [ ${error_value} = 0 ]; then
254                echo_ok
255        else
256                echo_failure
257        fi
258
259        # This prevents the 'An Unexpected Error Has Occurred' from trivial
260        # errors.
261        return 0
262}
263
264print_status()
265{
266        if [ "${#}" = "0" ]; then
267                echo "Usage: ${0} {success|warning|failure}"
268                return 1
269        fi
270
271        case "${1}" in
272
273                success)
274                        echo_ok
275                        ;;
276
277                warning)
278                        # Leave this extra case in because old scripts
279                        # may call it this way.
280                        case "${2}" in
281                                running)
282                                        ${ECHO} -e -n "${CURS_UP}"
283                                        ${ECHO} -e -n "\\033[${STRING_LENGTH}G   "
284                                        boot_mesg "Already running." ${WARNING}
285                                        echo_warning
286                                        ;;
287                                not_running)
288                                        ${ECHO} -e -n "${CURS_UP}"
289                                        ${ECHO} -e -n "\\033[${STRING_LENGTH}G   "
290                                        boot_mesg "Not running." ${WARNING}
291                                        echo_warning
292                                        ;;
293                                not_available)
294                                        ${ECHO} -e -n "${CURS_UP}"
295                                        ${ECHO} -e -n "\\033[${STRING_LENGTH}G   "
296                                        boot_mesg "Not available." ${WARNING}
297                                        echo_warning
298                                        ;;
299                                *)
300                                        # This is how it is supposed to
301                                        # be called
302                                        echo_warning
303                                        ;;
304                        esac
305                ;;
306
307                failure)
308                        echo_failure
309                ;;
310
311        esac
312
313}
314
315reloadproc()
316{
317        local pidfile=""
318        local failure=0
319
320        while true
321        do
322                case "${1}" in
323                        -p)
324                                pidfile="${2}"
325                                shift 2
326                                ;;
327                        -*)
328                                log_failure_msg "Unknown Option: ${1}"
329                                return 2
330                                ;;
331                        *)
332                                break
333                                ;;
334                esac
335        done
336
337        if [ "${#}" -lt "1" ]; then
338                log_failure_msg "Usage: reloadproc [-p pidfile] pathname"
339                return 2
340        fi
341
342        # This will ensure compatibility with previous CLFS Bootscripts
343        if [ -n "${PIDFILE}" ]; then
344                pidfile="${PIDFILE}"
345        fi
346
347        # Is the process running?
348        if [ -z "${pidfile}" ]; then
349                pidofproc -s "${1}"
350        else
351                pidofproc -s -p "${pidfile}" "${1}"
352        fi
353
354        if [ -n "${pidlist}" ]; then
355                for pid in ${pidlist}
356                do
357                        kill -"${RELOADSIG}" "${pid}" || failure="1"
358                done
359
360                (exit ${failure})
361                evaluate_retval
362
363        else
364                boot_mesg "Process ${1} not running." ${WARNING}
365                echo_warning
366        fi
367}
368
369statusproc()
370{
371        local pidfile=""
372        local base=""
373        local ret=""
374
375        while true
376        do
377                case "${1}" in
378                        -p)
379                                pidfile="${2}"
380                                shift 2
381                                ;;
382                        -*)
383                                log_failure_msg "Unknown Option: ${1}"
384                                return 2
385                                ;;
386                        *)
387                                break
388                                ;;
389                esac
390        done
391
392        if [ "${#}" != "1" ]; then
393                shift 1
394                log_failure_msg "Usage: statusproc [-p pidfile] pathname"
395                return 2
396        fi
397
398        # Get the process basename
399        base="${1##*/}"
400
401        # This will ensure compatibility with previous CLFS Bootscripts
402        if [ -n "${PIDFILE}" ]; then
403                pidfile="${PIDFILE}"
404        fi
405
406        # Is the process running?
407        if [ -z "${pidfile}" ]; then
408                pidofproc -s "${1}"
409        else
410                pidofproc -s -p "${pidfile}" "${1}"
411        fi
412
413        # Store the return status
414        ret=$?
415
416        if [ -n "${pidlist}" ]; then
417                ${ECHO} -e "${INFO}${base} is running with Process"\
418                        "ID(s) ${pidlist}.${NORMAL}"
419        else
420                if [ -n "${base}" -a -e "/run/${base}.pid" ]; then
421                        ${ECHO} -e "${WARNING}${1} is not running but"\
422                                "/run/${base}.pid exists.${NORMAL}"
423                else
424                        if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
425                                ${ECHO} -e "${WARNING}${1} is not running"\
426                                        "but ${pidfile} exists.${NORMAL}"
427                        else
428                                ${ECHO} -e "${INFO}${1} is not running.${NORMAL}"
429                        fi
430                fi
431        fi
432
433        # Return the status from pidofproc
434        return $ret
435}
436
437# The below functions are documented in the LSB-generic 2.1.0
438
439#*******************************************************************************
440# Function - pidofproc [-s] [-p pidfile] pathname
441#
442# Purpose: This function returns one or more pid(s) for a particular daemon
443#
444# Inputs: -p pidfile, use the specified pidfile instead of pidof
445#         pathname, path to the specified program
446#
447# Outputs: return 0 - Success, pid's in stdout
448#          return 1 - Program is dead, pidfile exists
449#          return 2 - Invalid or excessive number of arguments,
450#                     warning in stdout
451#          return 3 - Program is not running
452#
453# Dependencies: pidof, echo, head
454#
455# Todo: Remove dependency on head
456#       This depreciates getpids
457#       Test changes to pidof
458#
459#*******************************************************************************
460pidofproc()
461{
462        local pidfile=""
463        local lpids=""
464        local silent=""
465        pidlist=""
466        while true
467        do
468                case "${1}" in
469                        -p)
470                                pidfile="${2}"
471                                shift 2
472                                ;;
473
474                        -s)
475                                # Added for legacy opperation of getpids
476                                # eliminates several '> /dev/null'
477                                silent="1"
478                                shift 1
479                                ;;
480                        -*)
481                                log_failure_msg "Unknown Option: ${1}"
482                                return 2
483                                ;;
484                        *)
485                                break
486                                ;;
487                esac
488        done
489
490        if [ "${#}" != "1" ]; then
491                shift 1
492                log_failure_msg "Usage: pidofproc [-s] [-p pidfile] pathname"
493                return 2
494        fi
495
496        if [ -n "${pidfile}" ]; then
497                if [ ! -r "${pidfile}" ]; then
498                        return 3 # Program is not running
499                fi
500
501                lpids=`head -n 1 ${pidfile}`
502                for pid in ${lpids}
503                do
504                        if [ "${pid}" -ne "$$" -a "${pid}" -ne "${PPID}" ]; then
505                                kill -0 "${pid}" 2>/dev/null &&
506                                pidlist="${pidlist} ${pid}"
507                        fi
508                       
509                        if [ "${silent}" != "1" ]; then
510                                echo "${pidlist}"
511                        fi
512
513                        test -z "${pidlist}" && 
514                        # Program is dead, pidfile exists
515                        return 1
516                        # else
517                        return 0
518                done
519
520        else
521                pidlist=`pidof -o $$ -o $PPID -x "$1"`
522                if [ "${silent}" != "1" ]; then
523                        echo "${pidlist}"
524                fi
525
526                # Get provide correct running status
527                if [ -n "${pidlist}" ]; then
528                        return 0
529                else
530                        return 3
531                fi
532
533        fi
534
535        if [ "$?" != "0" ]; then
536                return 3 # Program is not running
537        fi
538}
539
540# This will ensure compatibility with previous CLFS Bootscripts
541getpids()
542{
543        if [ -z "${PIDFILE}" ]; then
544                pidofproc -s -p "${PIDFILE}" $@
545        else
546                pidofproc -s $@
547        fi
548        base="${1##*/}"
549}
550
551#*******************************************************************************
552# Function - loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]
553#
554# Purpose: This runs the specified program as a daemon
555#
556# Inputs: -f, run the program even if it is already running
557#         -n nicelevel, specifies a nice level. See nice(1).
558#         -p pidfile, uses the specified pidfile
559#         pathname, pathname to the specified program
560#         args, arguments to pass to specified program
561#
562# Outputs: return 0 - Success
563#          return 2 - Invalid of excessive number of arguments,
564#                     warning in stdout
565#          return 4 - Program or service status is unknown
566#
567# Dependencies: nice
568#
569# Todo: LSB says this should be called start_daemon
570#       LSB does not say that it should call evaluate_retval
571#       It checks for PIDFILE, which is deprecated.
572#         Will be removed after BLFS 6.0
573#       loadproc returns 0 if program is already running, not LSB compliant
574#
575#*******************************************************************************
576loadproc()
577{
578        local pidfile=""
579        local forcestart=""
580        local nicelevel="10"
581
582# This will ensure compatibility with previous CLFS Bootscripts
583        if [ -n "${PIDFILE}" ]; then
584                pidfile="${PIDFILE}"
585        fi
586
587  while true
588        do
589                case "${1}" in
590                        -f)
591                                forcestart="1"
592                                shift 1
593                                ;;
594                        -n)
595                                nicelevel="${2}"
596                                shift 2
597                                ;;
598                        -p)
599                                pidfile="${2}"
600                                shift 2
601                                ;;
602                        -*)
603                                log_failure_msg "Unknown Option: ${1}"
604                                return 2 #invalid or excess argument(s)
605                                ;;
606                        *)
607                                break
608                                ;;
609                esac
610        done
611
612        if [ "${#}" = "0" ]; then
613                log_failure_msg "Usage: loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]"
614                return 2 #invalid or excess argument(s)
615        fi
616
617        if [ -z "${forcestart}" ]; then
618                if [ -z "${pidfile}" ]; then
619                        pidofproc -s "${1}"
620                else
621                        pidofproc -s -p "${pidfile}" "${1}"
622                fi
623
624                case "${?}" in
625                        0)
626                                log_warning_msg "Unable to continue: ${1} is running"
627                                return 0 # 4
628                                ;;
629                        1)
630                                log_warning_msg "Unable to continue: ${pidfile} exists"
631                                return 0 # 4
632                                ;;
633                        3)
634                                ;;
635                        *)
636                                log_failure_msg "Unknown error code from pidofproc: ${?}"
637                                return 4
638                                ;;
639                esac
640        fi
641
642        nice -n "${nicelevel}" "${@}"
643        evaluate_retval # This is "Probably" not LSB compliant, but required to be compatible with older bootscripts
644        return 0
645}
646
647#*******************************************************************************
648# Function - killproc  [-p pidfile] pathname [signal]
649#
650# Purpose:
651#
652# Inputs: -p pidfile, uses the specified pidfile
653#         pathname, pathname to the specified program
654#         signal, send this signal to pathname
655#
656# Outputs: return 0 - Success
657#          return 2 - Invalid of excessive number of arguments,
658#                     warning in stdout
659#          return 4 - Unknown Status
660#
661# Dependencies: kill, sleep
662#
663# Todo: LSB does not say that it should call evaluate_retval
664#       It checks for PIDFILE, which is deprecated.
665#         Will be removed after BLFS 6.0
666#
667#*******************************************************************************
668killproc()
669{
670        local pidfile=""
671        local killsig=TERM # default signal is SIGTERM
672        pidlist=""
673
674        # This will ensure compatibility with previous CLFS Bootscripts
675        if [ -n "${PIDFILE}" ]; then
676                pidfile="${PIDFILE}"
677        fi
678
679        while true
680        do
681                case "${1}" in
682                        -p)
683                                pidfile="${2}"
684                                shift 2
685                                ;;
686                        -*)
687                                log_failure_msg "Unknown Option: ${1}"
688                                return 2
689                                ;;
690                        *)
691                                break
692                                ;;
693                esac
694        done
695
696        if [ "${#}" = "2" ]; then
697                killsig="${2}"
698        elif [ "${#}" != "1" ]; then
699                shift 2
700                log_failure_msg "Usage: killproc  [-p pidfile] pathname [signal]"
701                return 2
702        fi
703
704        # Is the process running?
705        if [ -z "${pidfile}" ]; then
706                pidofproc -s "${1}"
707        else
708                pidofproc -s -p "${pidfile}" "${1}"
709        fi
710
711    # If running, send the signal
712    if [ -n "${pidlist}" ]; then
713        for pid in ${pidlist}
714        do
715                kill -${killsig} ${pid} 2>/dev/null
716
717                # Wait up to 3 seconds, for ${pid} to terminate
718                case "${killsig}" in
719                TERM|SIGTERM|KILL|SIGKILL)
720                        # sleep in 1/10ths of seconds and
721                        # multiply KILLDELAY by 10
722                        local dtime="${KILLDELAY}0"
723                        while [ "${dtime}" != "0" ]
724                        do
725                                kill -0 ${pid} 2>/dev/null || break
726                                sleep 0.1
727                                dtime=$(( ${dtime} - 1))
728                        done
729                        # If ${pid} is still running, kill it
730                        kill -0 ${pid} 2>/dev/null && kill -KILL ${pid} 2>/dev/null
731                        ;;
732                esac
733        done
734
735        # Check if the process is still running if we tried to stop it
736        case "${killsig}" in
737        TERM|SIGTERM|KILL|SIGKILL)
738                if [ -z "${pidfile}" ]; then
739                        pidofproc -s "${1}"
740                else
741                        pidofproc -s -p "${pidfile}" "${1}"
742                fi
743
744                # Program was terminated
745                if [ "$?" != "0" ]; then
746                        # Remove the pidfile if necessary
747                        if [ -f "${pidfile}" ]; then
748                                rm -f "${pidfile}"
749                        fi
750                        echo_ok
751                        return 0
752                else # Program is still running
753                        echo_failure
754                        return 4 # Unknown Status
755                fi
756                ;;
757        *)
758                # Just see if the kill returned successfully
759                evaluate_retval
760                ;;
761        esac
762    else # process not running
763        print_status warning not_running
764    fi
765}
766
767
768#*******************************************************************************
769# Function - log_success_msg "message"
770#
771# Purpose: Print a success message
772#
773# Inputs: $@ - Message
774#
775# Outputs: Text output to screen
776#
777# Dependencies: echo
778#
779# Todo: logging
780#
781#*******************************************************************************
782log_success_msg()
783{
784        ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
785        ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}""  OK  ""${BRACKET}""]""${NORMAL}"
786        return 0
787}
788
789#*******************************************************************************
790# Function - log_failure_msg "message"
791#
792# Purpose: Print a failure message
793#
794# Inputs: $@ - Message
795#
796# Outputs: Text output to screen
797#
798# Dependencies: echo
799#
800# Todo: logging
801#
802#*******************************************************************************
803log_failure_msg() {
804        ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
805        ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}"
806        return 0
807}
808
809#*******************************************************************************
810# Function - log_warning_msg "message"
811#
812# Purpose: print a warning message
813#
814# Inputs: $@ - Message
815#
816# Outputs: Text output to screen
817#
818# Dependencies: echo
819#
820# Todo: logging
821#
822#*******************************************************************************
823log_warning_msg() {
824        ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
825        ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}"
826        return 0
827}
828
829# End $rc_base/init.d/functions
Note: See TracBrowser for help on using the repository browser.