functions 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  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. if [ -n "${pidlist}" ]; then
  256. for pid in ${pidlist}
  257. do
  258. kill -"${RELOADSIG}" "${pid}" || failure="1"
  259. done
  260. (exit ${failure})
  261. evaluate_retval
  262. else
  263. boot_mesg "Process ${1} not running." ${WARNING}
  264. echo_warning
  265. fi
  266. }
  267. statusproc()
  268. {
  269. local pidfile=""
  270. local base=""
  271. local ret=""
  272. while true
  273. do
  274. case "${1}" in
  275. -p)
  276. pidfile="${2}"
  277. shift 2
  278. ;;
  279. -*)
  280. log_failure_msg "Unknown Option: ${1}"
  281. return 2
  282. ;;
  283. *)
  284. break
  285. ;;
  286. esac
  287. done
  288. if [ "${#}" != "1" ]; then
  289. shift 1
  290. log_failure_msg "Usage: statusproc [-p pidfile] pathname"
  291. return 2
  292. fi
  293. # Get the process basename
  294. base="${1##*/}"
  295. # This will ensure compatibility with previous LFS Bootscripts
  296. if [ -n "${PIDFILE}" ]; then
  297. pidfile="${PIDFILE}"
  298. fi
  299. # Is the process running?
  300. if [ -z "${pidfile}" ]; then
  301. pidofproc -s "${1}"
  302. else
  303. pidofproc -s -p "${pidfile}" "${1}"
  304. fi
  305. # Store the return status
  306. ret=$?
  307. if [ -n "${pidlist}" ]; then
  308. ${ECHO} -e "${INFO}${base} is running with Process"\
  309. "ID(s) ${pidlist}.${NORMAL}"
  310. else
  311. if [ -n "${base}" -a -e "/var/run/${base}.pid" ]; then
  312. ${ECHO} -e "${WARNING}${1} is not running but"\
  313. "/var/run/${base}.pid exists.${NORMAL}"
  314. else
  315. if [ -n "${pidfile}" -a -e "${pidfile}" ]; then
  316. ${ECHO} -e "${WARNING}${1} is not running"\
  317. "but ${pidfile} exists.${NORMAL}"
  318. else
  319. ${ECHO} -e "${INFO}${1} is not running.${NORMAL}"
  320. fi
  321. fi
  322. fi
  323. # Return the status from pidofproc
  324. return $ret
  325. }
  326. # The below functions are documented in the LSB-generic 2.1.0
  327. #*******************************************************************************
  328. # Function - pidofproc [-s] [-p pidfile] pathname
  329. #
  330. # Purpose: This function returns one or more pid(s) for a particular daemon
  331. #
  332. # Inputs: -p pidfile, use the specified pidfile instead of pidof
  333. # pathname, path to the specified program
  334. #
  335. # Outputs: return 0 - Success, pid's in stdout
  336. # return 1 - Program is dead, pidfile exists
  337. # return 2 - Invalid or excessive number of arguments,
  338. # warning in stdout
  339. # return 3 - Program is not running
  340. #
  341. # Dependencies: pidof, echo, head
  342. #
  343. # Todo: Remove dependency on head
  344. # This depreciates getpids
  345. # Test changes to pidof
  346. #
  347. #*******************************************************************************
  348. pidofproc()
  349. {
  350. local pidfile=""
  351. local lpids=""
  352. local silent=""
  353. pidlist=""
  354. while true
  355. do
  356. case "${1}" in
  357. -p)
  358. pidfile="${2}"
  359. shift 2
  360. ;;
  361. -s)
  362. # Added for legacy opperation of getpids
  363. # eliminates several '> /dev/null'
  364. silent="1"
  365. shift 1
  366. ;;
  367. -*)
  368. log_failure_msg "Unknown Option: ${1}"
  369. return 2
  370. ;;
  371. *)
  372. break
  373. ;;
  374. esac
  375. done
  376. if [ "${#}" != "1" ]; then
  377. shift 1
  378. log_failure_msg "Usage: pidofproc [-s] [-p pidfile] pathname"
  379. return 2
  380. fi
  381. if [ -n "${pidfile}" ]; then
  382. if [ ! -r "${pidfile}" ]; then
  383. return 3 # Program is not running
  384. fi
  385. lpids=`head -n 1 ${pidfile}`
  386. for pid in ${lpids}
  387. do
  388. if [ "${pid}" -ne "$$" -a "${pid}" -ne "${PPID}" ]; then
  389. kill -0 "${pid}" 2>/dev/null &&
  390. pidlist="${pidlist} ${pid}"
  391. fi
  392. if [ "${silent}" != "1" ]; then
  393. echo "${pidlist}"
  394. fi
  395. test -z "${pidlist}" &&
  396. # Program is dead, pidfile exists
  397. return 1
  398. # else
  399. return 0
  400. done
  401. else
  402. pidlist=`pidof -o $$ -o $PPID -x "$1"`
  403. if [ "${silent}" != "1" ]; then
  404. echo "${pidlist}"
  405. fi
  406. # Get provide correct running status
  407. if [ -n "${pidlist}" ]; then
  408. return 0
  409. else
  410. return 3
  411. fi
  412. fi
  413. if [ "$?" != "0" ]; then
  414. return 3 # Program is not running
  415. fi
  416. }
  417. # This will ensure compatibility with previous LFS Bootscripts
  418. getpids()
  419. {
  420. if [ -z "${PIDFILE}" ]; then
  421. pidofproc -s -p "${PIDFILE}" $@
  422. else
  423. pidofproc -s $@
  424. fi
  425. base="${1##*/}"
  426. }
  427. #*******************************************************************************
  428. # Function - loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]
  429. #
  430. # Purpose: This runs the specified program as a daemon
  431. #
  432. # Inputs: -f, run the program even if it is already running
  433. # -n nicelevel, specifies a nice level. See nice(1).
  434. # -p pidfile, uses the specified pidfile
  435. # pathname, pathname to the specified program
  436. # args, arguments to pass to specified program
  437. #
  438. # Outputs: return 0 - Success
  439. # return 2 - Invalid of excessive number of arguments,
  440. # warning in stdout
  441. # return 4 - Program or service status is unknown
  442. #
  443. # Dependencies: nice
  444. #
  445. # Todo: LSB says this should be called start_daemon
  446. # LSB does not say that it should call evaluate_retval
  447. # It checks for PIDFILE, which is deprecated.
  448. # Will be removed after BLFS 6.0
  449. # loadproc returns 0 if program is already running, not LSB compliant
  450. #
  451. #*******************************************************************************
  452. loadproc()
  453. {
  454. local pidfile=""
  455. local forcestart=""
  456. local nicelevel="10"
  457. # This will ensure compatibility with previous LFS Bootscripts
  458. if [ -n "${PIDFILE}" ]; then
  459. pidfile="${PIDFILE}"
  460. fi
  461. while true
  462. do
  463. case "${1}" in
  464. -f)
  465. forcestart="1"
  466. shift 1
  467. ;;
  468. -n)
  469. nicelevel="${2}"
  470. shift 2
  471. ;;
  472. -p)
  473. pidfile="${2}"
  474. shift 2
  475. ;;
  476. -*)
  477. log_failure_msg "Unknown Option: ${1}"
  478. return 2 #invalid or excess argument(s)
  479. ;;
  480. *)
  481. break
  482. ;;
  483. esac
  484. done
  485. if [ "${#}" = "0" ]; then
  486. log_failure_msg "Usage: loadproc [-f] [-n nicelevel] [-p pidfile] pathname [args]"
  487. return 2 #invalid or excess argument(s)
  488. fi
  489. if [ -z "${forcestart}" ]; then
  490. if [ -z "${pidfile}" ]; then
  491. pidofproc -s "${1}"
  492. else
  493. pidofproc -s -p "${pidfile}" "${1}"
  494. fi
  495. case "${?}" in
  496. 0)
  497. log_warning_msg "Unable to continue: ${1} is running"
  498. return 0 # 4
  499. ;;
  500. 1)
  501. log_warning_msg "Unable to continue: ${pidfile} exists"
  502. return 0 # 4
  503. ;;
  504. 3)
  505. ;;
  506. *)
  507. log_failure_msg "Unknown error code from pidofproc: ${?}"
  508. return 4
  509. ;;
  510. esac
  511. fi
  512. nice -n "${nicelevel}" "${@}"
  513. evaluate_retval # This is "Probably" not LSB compliant, but required to be compatible with older bootscripts
  514. return 0
  515. }
  516. #*******************************************************************************
  517. # Function - killproc [-p pidfile] pathname [signal]
  518. #
  519. # Purpose:
  520. #
  521. # Inputs: -p pidfile, uses the specified pidfile
  522. # pathname, pathname to the specified program
  523. # signal, send this signal to pathname
  524. #
  525. # Outputs: return 0 - Success
  526. # return 2 - Invalid of excessive number of arguments,
  527. # warning in stdout
  528. # return 4 - Unknown Status
  529. #
  530. # Dependencies: kill
  531. #
  532. # Todo: LSB does not say that it should call evaluate_retval
  533. # It checks for PIDFILE, which is deprecated.
  534. # Will be removed after BLFS 6.0
  535. #
  536. #*******************************************************************************
  537. killproc()
  538. {
  539. local pidfile=""
  540. local killsig=TERM # default signal is SIGTERM
  541. pidlist=""
  542. # This will ensure compatibility with previous LFS Bootscripts
  543. if [ -n "${PIDFILE}" ]; then
  544. pidfile="${PIDFILE}"
  545. fi
  546. while true
  547. do
  548. case "${1}" in
  549. -p)
  550. pidfile="${2}"
  551. shift 2
  552. ;;
  553. -*)
  554. log_failure_msg "Unknown Option: ${1}"
  555. return 2
  556. ;;
  557. *)
  558. break
  559. ;;
  560. esac
  561. done
  562. if [ "${#}" = "2" ]; then
  563. killsig="${2}"
  564. elif [ "${#}" != "1" ]; then
  565. shift 2
  566. log_failure_msg "Usage: killproc [-p pidfile] pathname [signal]"
  567. return 2
  568. fi
  569. # Is the process running?
  570. if [ -z "${pidfile}" ]; then
  571. pidofproc -s "${1}"
  572. else
  573. pidofproc -s -p "${pidfile}" "${1}"
  574. fi
  575. # If running, send the signal
  576. if [ -n "${pidlist}" ]; then
  577. for pid in ${pidlist}
  578. do
  579. kill -${killsig} ${pid} 2>/dev/null
  580. # Wait up to 3 seconds, for ${pid} to terminate
  581. case "${killsig}" in
  582. TERM|SIGTERM|KILL|SIGKILL)
  583. # sleep in 1/10ths of seconds and
  584. # multiply KILLDELAY by 10
  585. local dtime="${KILLDELAY}0"
  586. while [ "${dtime}" != "0" ]
  587. do
  588. kill -0 ${pid} 2>/dev/null || break
  589. sleep 0.1
  590. dtime=$(( ${dtime} - 1))
  591. done
  592. # If ${pid} is still running, kill it
  593. kill -0 ${pid} 2>/dev/null && kill -KILL ${pid} 2>/dev/null
  594. ;;
  595. esac
  596. done
  597. # Check if the process is still running if we tried to stop it
  598. case "${killsig}" in
  599. TERM|SIGTERM|KILL|SIGKILL)
  600. if [ -z "${pidfile}" ]; then
  601. pidofproc -s "${1}"
  602. else
  603. pidofproc -s -p "${pidfile}" "${1}"
  604. fi
  605. # Program was terminated
  606. if [ "$?" != "0" ]; then
  607. # Remove the pidfile if necessary
  608. if [ -f "${pidfile}" ]; then
  609. rm -f "${pidfile}"
  610. fi
  611. echo_ok
  612. return 0
  613. else # Program is still running
  614. echo_failure
  615. return 4 # Unknown Status
  616. fi
  617. ;;
  618. *)
  619. # Just see if the kill returned successfully
  620. evaluate_retval
  621. ;;
  622. esac
  623. else # process not running
  624. print_status warning not_running
  625. fi
  626. }
  627. #*******************************************************************************
  628. # Function - log_success_msg "message"
  629. #
  630. # Purpose: Print a success message
  631. #
  632. # Inputs: $@ - Message
  633. #
  634. # Outputs: Text output to screen
  635. #
  636. # Dependencies: echo
  637. #
  638. # Todo: logging
  639. #
  640. #*******************************************************************************
  641. log_success_msg()
  642. {
  643. ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
  644. ${ECHO} -e "${SET_COL}""${BRACKET}""[""${SUCCESS}"" OK ""${BRACKET}""]""${NORMAL}"
  645. return 0
  646. }
  647. #*******************************************************************************
  648. # Function - log_failure_msg "message"
  649. #
  650. # Purpose: Print a failure message
  651. #
  652. # Inputs: $@ - Message
  653. #
  654. # Outputs: Text output to screen
  655. #
  656. # Dependencies: echo
  657. #
  658. # Todo: logging
  659. #
  660. #*******************************************************************************
  661. log_failure_msg() {
  662. ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
  663. ${ECHO} -e "${SET_COL}""${BRACKET}""[""${FAILURE}"" FAIL ""${BRACKET}""]""${NORMAL}"
  664. return 0
  665. }
  666. #*******************************************************************************
  667. # Function - log_warning_msg "message"
  668. #
  669. # Purpose: print a warning message
  670. #
  671. # Inputs: $@ - Message
  672. #
  673. # Outputs: Text output to screen
  674. #
  675. # Dependencies: echo
  676. #
  677. # Todo: logging
  678. #
  679. #*******************************************************************************
  680. log_warning_msg() {
  681. ${ECHO} -n -e "${BOOTMESG_PREFIX}${@}"
  682. ${ECHO} -e "${SET_COL}""${BRACKET}""[""${WARNING}"" WARN ""${BRACKET}""]""${NORMAL}"
  683. return 0
  684. }
  685. # End $rc_base/init.d/functions