freedombone-utils-selector 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. #!/bin/bash
  2. #
  3. # .---. . .
  4. # | | |
  5. # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
  6. # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
  7. # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
  8. #
  9. # Freedom in the Cloud
  10. #
  11. # Functions for selecting which apps to install or remove
  12. #
  13. # License
  14. # =======
  15. #
  16. # Copyright (C) 2015-2016 Bob Mottram <bob@robotics.uk.to>
  17. #
  18. # This program is free software: you can redistribute it and/or modify
  19. # it under the terms of the GNU Affero General Public License as published by
  20. # the Free Software Foundation, either version 3 of the License, or
  21. # (at your option) any later version.
  22. #
  23. # This program is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. # GNU Affero General Public License for more details.
  27. #
  28. # You should have received a copy of the GNU Affero General Public License
  29. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  30. # Array containing names of available apps
  31. APPS_AVAILABLE=()
  32. # Array containing 1 or 0 indicating installed apps
  33. APPS_INSTALLED=()
  34. # Apps selected with checklist
  35. APPS_CHOSEN=()
  36. # A list of the names of installed apps
  37. APPS_INSTALLED_NAMES=()
  38. # file containing a list of removed apps
  39. REMOVED_APPS_FILE=/root/removed
  40. # Loads variables defined at the beginning of an app script
  41. function app_load_variables {
  42. app_name=$1
  43. var_name=${app_name}_variables
  44. if [ ! ${!var_name} ]; then
  45. return
  46. fi
  47. varname=${!var_name}
  48. for v in "${var_name[@]}"
  49. do
  50. read_config_param $v
  51. done
  52. }
  53. # Saves variables for a given app script
  54. function app_save_variables {
  55. app_name=$1
  56. var_name=${app_name}_variables
  57. if [ ! ${!var_name} ]; then
  58. return
  59. fi
  60. varname=${!var_name}
  61. for v in "${varname[@]}"
  62. do
  63. write_config_param $v "${!v}"
  64. done
  65. }
  66. # gets the variants list from an app script
  67. function app_variants {
  68. filename=$1
  69. variants_line=$(cat ${filename} | grep 'VARIANTS=')
  70. if [[ "$variants_line" == *"'"* ]]; then
  71. variants_list=$(echo "$variants_line" | awk -F '=' '{print $2}' | awk -F "'" '{print $2}')
  72. else
  73. variants_list=$(echo "$variants_line" | awk -F '=' '{print $2}' | awk -F '"' '{print $2}')
  74. fi
  75. echo "$variants_list"
  76. }
  77. # whether a given item is in an array
  78. function item_in_array {
  79. local e
  80. for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  81. return 1
  82. }
  83. # returns a list of available system variants
  84. # based upon the variants string in each app script
  85. function available_system_variants {
  86. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  87. new_available_variants_list=()
  88. for filename in $FILES
  89. do
  90. system_variants_list=$(app_variants $filename)
  91. variants_array=($system_variants_list)
  92. for variant_str in "${variants_array[@]}"
  93. do
  94. item_in_array "${variant_str}" "${new_available_variants_list[@]}"
  95. if [[ $? != 0 ]]; then
  96. new_available_variants_list+=("$variant_str")
  97. fi
  98. done
  99. done
  100. available_variants_list=($(sort <<<"${new_available_variants_list[*]}"))
  101. }
  102. function is_valid_variant {
  103. sys_type="$1"
  104. available_variants_list=()
  105. available_system_variants
  106. for variant_str in "${available_variants_list[@]}"
  107. do
  108. if [[ "$sys_type" == "$variant_str" ]]; then
  109. return "1"
  110. fi
  111. done
  112. return "0"
  113. }
  114. function show_available_variants {
  115. available_variants_list=()
  116. available_system_variants
  117. for variant_str in "${available_variants_list[@]}"
  118. do
  119. echo " $variant_str"
  120. done
  121. }
  122. # mark a given app as having been removed so that it doesn't get reinstalled on updates
  123. function remove_app {
  124. app_name=$1
  125. if [ ! -f $REMOVED_APPS_FILE ]; then
  126. touch $REMOVED_APPS_FILE
  127. fi
  128. if ! grep -Fxq "_${app_name}_" $REMOVED_APPS_FILE; then
  129. echo "_${app_name}_" >> $REMOVED_APPS_FILE
  130. fi
  131. }
  132. # returns 1 if an app has been marked as removed
  133. function app_is_removed {
  134. app_name="$1"
  135. if [ ! -f $REMOVED_APPS_FILE ]; then
  136. echo "0"
  137. return
  138. fi
  139. if ! grep -Fxq "_${app_name}_" $REMOVED_APPS_FILE; then
  140. echo "0"
  141. else
  142. echo "1"
  143. fi
  144. }
  145. # Allows an app to be reinstalled even if it was previously marked as being removed
  146. function reinstall_app {
  147. app_name=$1
  148. if [ ! -f $REMOVED_APPS_FILE ]; then
  149. return
  150. fi
  151. if [[ $(app_is_removed $app_name) == "1" ]]; then
  152. sed -i "/_${app_name}_/d" $REMOVED_APPS_FILE
  153. fi
  154. }
  155. # returns 1 if an app is installed
  156. function app_is_installed {
  157. app_name="$1"
  158. # Why does this secondary file exist, apart from COMPLETION_FILE ?
  159. # It's so that it is visible to unprivileged users from the user control panel
  160. INSTALLED_APPS_LIST=/usr/share/${PROJECT_NAME}/installed.txt
  161. if [ -f $INSTALLED_APPS_LIST ]; then
  162. if ! grep -Fxq "install_${app_name}" $INSTALLED_APPS_LIST; then
  163. echo "0"
  164. else
  165. echo "1"
  166. fi
  167. return
  168. fi
  169. # check the completion file to see if it was installed
  170. if [ ! -f $COMPLETION_FILE ]; then
  171. echo "0"
  172. return
  173. fi
  174. if ! grep -Fxq "install_${app_name}" $COMPLETION_FILE; then
  175. echo "0"
  176. else
  177. echo "1"
  178. fi
  179. }
  180. # called at the end of the install section of an app script
  181. function install_completed {
  182. if [ ! ${1} ]; then
  183. exit 673935
  184. fi
  185. echo "install_${1}" >> $COMPLETION_FILE
  186. }
  187. # populates an array of "0" or "1" for whether apps are installed
  188. function get_apps_installed {
  189. for a in "${APPS_AVAILABLE[@]}"
  190. do
  191. APPS_INSTALLED+=("$(app_is_installed $a)")
  192. done
  193. }
  194. # populates an array of installed app names
  195. function get_apps_installed_names {
  196. APPS_INSTALLED_NAMES=()
  197. for a in "${APPS_AVAILABLE[@]}"
  198. do
  199. if [[ $(app_is_installed $a) == "1" ]]; then
  200. APPS_INSTALLED_NAMES+=("$a")
  201. fi
  202. done
  203. }
  204. # detects what apps are available
  205. function detect_apps {
  206. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  207. APPS_AVAILABLE=()
  208. APPS_CHOSEN=()
  209. # for all the app scripts
  210. for filename in $FILES
  211. do
  212. app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
  213. item_in_array "${app_name}" "${APPS_AVAILABLE[@]}"
  214. if [[ $? != 0 ]]; then
  215. APPS_AVAILABLE+=("${app_name}")
  216. APPS_CHOSEN+=("0")
  217. fi
  218. done
  219. function_check get_apps_installed
  220. get_apps_installed
  221. get_apps_installed_names
  222. }
  223. # detects what apps are available and can be installed
  224. # If the variants list within an app script is an empty string then
  225. # it is considered to be too experimental to be installable
  226. function detect_installable_apps {
  227. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  228. APPS_AVAILABLE=()
  229. APPS_CHOSEN=()
  230. APPS_INSTALLED=()
  231. APPS_INSTALLED_NAMES=()
  232. function_check app_is_installed
  233. # for all the app scripts
  234. for filename in $FILES
  235. do
  236. app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
  237. item_in_array "${app_name}" "${APPS_AVAILABLE[@]}"
  238. if [[ $? != 0 ]]; then
  239. variants_list=$(app_variants $filename)
  240. # check for empty string
  241. if [ ${#variants_list} -gt 0 ]; then
  242. APPS_AVAILABLE+=("${app_name}")
  243. APPS_CHOSEN+=("0")
  244. APPS_INSTALLED+=("$(app_is_installed $app_name)")
  245. if [[ $(app_is_installed $app_name) == "1" ]]; then
  246. APPS_INSTALLED_NAMES+=("$app_name")
  247. fi
  248. fi
  249. fi
  250. done
  251. }
  252. # creates the APPS_AVAILABLE and APPS_CHOSEN arrays based on
  253. # the given variant name
  254. function choose_apps_for_variant {
  255. variant_name="$1"
  256. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  257. APPS_AVAILABLE=()
  258. APPS_CHOSEN=()
  259. # for all the app scripts
  260. for filename in $FILES
  261. do
  262. app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
  263. item_in_array "${app_name}" "${APPS_AVAILABLE[@]}"
  264. if [[ $? != 0 ]]; then
  265. APPS_AVAILABLE+=("${app_name}")
  266. if grep -q "VARIANTS=" ${filename}; then
  267. variants_list=$(app_variants $filename)
  268. if [[ "${variants_list}" == 'all'* || \
  269. "${variants_list}" == "$variant_name "* || \
  270. "${variants_list}" == *" $variant_name "* || \
  271. "${variants_list}" == *" $variant_name" ]]; then
  272. if [[ $(app_is_removed ${a}) == "0" ]]; then
  273. APPS_CHOSEN+=("1")
  274. else
  275. APPS_CHOSEN+=("0")
  276. fi
  277. else
  278. APPS_CHOSEN+=("0")
  279. fi
  280. else
  281. APPS_CHOSEN+=("0")
  282. fi
  283. fi
  284. done
  285. function_check get_apps_installed
  286. get_apps_installed
  287. }
  288. # show a list of apps which have been chosen
  289. function list_chosen_apps {
  290. app_index=0
  291. for a in "${APPS_AVAILABLE[@]}"
  292. do
  293. if [[ ${APPS_CHOSEN[$app_index]} == "1" ]]; then
  294. echo $"${a}"
  295. fi
  296. app_index=$[app_index+1]
  297. done
  298. }
  299. function remove_apps {
  300. app_index=0
  301. for a in "${APPS_AVAILABLE[@]}"
  302. do
  303. if [[ ${APPS_INSTALLED[$app_index]} == "1" ]]; then
  304. if [[ ${APPS_CHOSEN[$app_index]} == "0" ]]; then
  305. echo $"Removing application: ${a}"
  306. app_load_variables ${a}
  307. remove_app ${a}
  308. remove_${a}
  309. echo $"${a} was removed"
  310. fi
  311. fi
  312. app_index=$[app_index+1]
  313. done
  314. update_installed_apps_list
  315. }
  316. function install_apps {
  317. is_interactive=$1
  318. # interactive install configuration for each app
  319. if [ ${is_interactive} ]; then
  320. app_index=0
  321. for a in "${APPS_AVAILABLE[@]}"
  322. do
  323. if [[ ${APPS_INSTALLED[$app_index]} == "0" ]]; then
  324. if [[ ${APPS_CHOSEN[$app_index]} == "1" ]]; then
  325. # interactively obtain settings for this app
  326. if [[ $(function_exists install_interactive_${a}) == "1" ]]; then
  327. install_interactive_${a}
  328. fi
  329. fi
  330. fi
  331. app_index=$[app_index+1]
  332. done
  333. fi
  334. # now install the apps
  335. app_index=0
  336. for a in "${APPS_AVAILABLE[@]}"
  337. do
  338. if [[ ${APPS_INSTALLED[$app_index]} == "0" ]]; then
  339. if [[ ${APPS_CHOSEN[$app_index]} == "1" ]]; then
  340. if [ ${is_interactive} ]; then
  341. # clears any removal indicator
  342. reinstall_app ${a}
  343. app_load_variables ${a}
  344. if [[ $(app_is_installed ${a}) == "1" ]]; then
  345. echo $"Upgrading application from interactive: ${a}"
  346. upgrade_${a}
  347. echo $"${a} was upgraded from interactive"
  348. else
  349. echo $"Installing application from interactive: ${a}"
  350. install_${a}
  351. app_save_variables ${a}
  352. install_completed ${a}
  353. echo $"${a} was installed from interactive"
  354. fi
  355. else
  356. # check if the app was removed
  357. if [[ $(app_is_removed ${a}) == "0" ]]; then
  358. app_load_variables ${a}
  359. if [[ $(app_is_installed ${a}) == "1" ]]; then
  360. echo $"Upgrading application: ${a}"
  361. upgrade_${a}
  362. echo $"${a} was upgraded"
  363. else
  364. echo $"Installing application: ${a}"
  365. install_${a}
  366. app_save_variables ${a}
  367. install_completed ${a}
  368. echo $"${a} was installed"
  369. fi
  370. else
  371. echo $"${a} has been removed and so will not be reinstalled"
  372. fi
  373. fi
  374. fi
  375. fi
  376. app_index=$[app_index+1]
  377. done
  378. update_installed_apps_list
  379. }
  380. # NOTE: deliberately no exit 0