functions 16 KB

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