shell dot on steroids https://pagure.io/shellfu

sfembed 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #!/bin/bash
  2. #shellcheck disable=SC1090
  3. . "$(sfpath)" || exit 3
  4. shellfu import pretty
  5. #
  6. usage() {
  7. mkusage "$@" "[options] SCRIPT" \
  8. -- \
  9. "Run SCRIPT, see what it would load and print its 'portable'" \
  10. "version, ie. with those modules embedded inside." \
  11. -o \
  12. "-v enable verbose output" \
  13. "-d enable debugging output" \
  14. -- \
  15. "WARNING: sfembed is highly experimental, probably dangerous and" \
  16. "does not always work (namely, if module loading is dynamic)." \
  17. -- \
  18. "Calling sfembed WILL RUN provided SCRIPT (with no arguments);" \
  19. "currently that's how it finds out what the SCRIPT would need."
  20. }
  21. chk_applicable() {
  22. #
  23. # Check if script file is properly formed
  24. #
  25. # Not all scripts are applicable for embedding. Check
  26. # if the file is usable.
  27. #
  28. :
  29. #TODO: for starters, file must only contain shellfu header, imports, main() and nothing else
  30. }
  31. mkbody() {
  32. debug -v ScriptFullPath
  33. mkhead || return $?
  34. mkmodules || return $?
  35. mkpayload || return $?
  36. mkfoot || return $?
  37. }
  38. mkmodules() {
  39. #
  40. # Print each module body w/ header
  41. #
  42. local modlist=__shellfu_embed__modlist
  43. local Module
  44. local ModuleHash
  45. (
  46. SHELLFU_EMBEDTMP="$modlist" "$ScriptFullPath" >&2
  47. )
  48. #shellcheck disable=SC2030
  49. awk '!x[$0]++' "$modlist" \
  50. | while read -r Module;
  51. do
  52. ModuleHash=$(md5sum "$Module")
  53. think "appending: $Module"
  54. mkmodule "$Module"
  55. done
  56. }
  57. mkpayload() {
  58. cat "$ScriptFullPath"
  59. }
  60. mkfoot() {
  61. echo "#"
  62. echo "# end of shellfu-embedded shell script"
  63. echo "#"
  64. }
  65. #shellcheck disable=SC2031
  66. mkmodule() {
  67. #
  68. # Print single module body
  69. #
  70. echo "#"
  71. echo "# begin module: $ModuleHash"
  72. echo "#"
  73. echo
  74. cat "$Module"
  75. echo
  76. echo "#"
  77. echo "# end module: $ModuleHash"
  78. echo "#"
  79. echo
  80. }
  81. mkhead() {
  82. #
  83. # Print header of the final script
  84. #
  85. echo "#!/bin/bash"
  86. echo "#"
  87. echo "# shellfu embedded: $ScriptFullPath"
  88. echo "# shellfu version: $SHELLFU_VERSION"
  89. echo "#"
  90. echo
  91. echo "# neuter any shellfu and sfpath calls"
  92. echo "shellfu() { :; }"
  93. echo "sfpath() { echo /dev/null; }"
  94. #FIXME: assumes that shellfu and sfpath are not installed
  95. # I.e. beats the use case when embedding is done to
  96. # avoid conflict.
  97. echo
  98. }
  99. do_embed() {
  100. local tmp # temporary dir to run in
  101. local es=0 # exit status of this function
  102. local ScriptFullPath # full path to script to embed in
  103. tmp=$(mktemp -d -t shellfu_embed.XXXXXXXX)
  104. ScriptFullPath=$(readlink -f "$Script")
  105. pushd "$tmp" >/dev/null
  106. mkbody; es=$?
  107. popd >/dev/null
  108. rm -r "$tmp"
  109. return $es
  110. }
  111. main() {
  112. local Script # script to embed libraries into
  113. #shellcheck disable=SC2034
  114. while true; do case "$1" in
  115. -d) PRETTY_DEBUG=true; shift ;;
  116. -v) PRETTY_VERBOSE=true; shift ;;
  117. -*) usage -w "unknown argument: $1" ;;
  118. *) break ;;
  119. esac done
  120. Script="$1"
  121. test -n "$Script" || usage -w "no SCRIPT?"
  122. test -f "$Script" || die "no such file: $Script"
  123. test -r "$Script" || die "cannot read: $Script"
  124. chk_applicable "$Script" || die "not applicable for embedding: $Script"
  125. debug -v Script
  126. do_embed
  127. }
  128. main "$@"