freedombone-utils-selector 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  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. save_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. 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}" "${available_variants_list[@]}"
  95. if [[ $? != 0 ]]; then
  96. available_variants_list+=("$variant_str")
  97. fi
  98. done
  99. done
  100. }
  101. function is_valid_variant {
  102. sys_type="$1"
  103. available_variants_list=()
  104. available_system_variants
  105. for variant_str in "${available_variants_list[@]}"
  106. do
  107. if [[ "$sys_type" == "$variant_str" ]]; then
  108. return "1"
  109. fi
  110. done
  111. return "0"
  112. }
  113. function show_available_variants {
  114. available_variants_list=()
  115. available_system_variants
  116. for variant_str in "${available_variants_list[@]}"
  117. do
  118. echo " $variant_str"
  119. done
  120. }
  121. # mark a given app as having been removed so that it doesn't get reinstalled on updates
  122. function remove_app {
  123. app_name=$1
  124. if [ ! -f $REMOVED_APPS_FILE ]; then
  125. touch $REMOVED_APPS_FILE
  126. fi
  127. if ! grep -Fxq "_${app_name}_" $REMOVED_APPS_FILE; then
  128. echo "_${app_name}_" >> $REMOVED_APPS_FILE
  129. fi
  130. }
  131. # returns 1 if an app has been marked as removed
  132. function app_is_removed {
  133. app_name="$1"
  134. if [ ! -f $REMOVED_APPS_FILE ]; then
  135. echo "0"
  136. return
  137. fi
  138. if ! grep -Fxq "_${app_name}_" $REMOVED_APPS_FILE; then
  139. echo "0"
  140. else
  141. echo "1"
  142. fi
  143. }
  144. # Allows an app to be reinstalled even if it was previously marked as being removed
  145. function reinstall_app {
  146. app_name=$1
  147. if [ ! -f $REMOVED_APPS_FILE ]; then
  148. return
  149. fi
  150. if [[ $(app_is_removed $app_name) == "1" ]]; then
  151. sed -i "/_${app_name}_/d" $REMOVED_APPS_FILE
  152. fi
  153. }
  154. # returns 1 if an app is installed
  155. function app_is_installed {
  156. app_name="$1"
  157. # Why does this secondary file exist, apart from COMPLETION_FILE ?
  158. # It's so that it is visible to unprivileged users from the user control panel
  159. INSTALLED_APPS_LIST=/usr/share/${PROJECT_NAME}/installed.txt
  160. if [ -f $INSTALLED_APPS_LIST ]; then
  161. if ! grep -Fxq "install_${app_name}" $INSTALLED_APPS_LIST; then
  162. echo "0"
  163. else
  164. echo "1"
  165. fi
  166. return
  167. fi
  168. # check the completion file to see if it was installed
  169. if [ ! -f $COMPLETION_FILE ]; then
  170. echo "0"
  171. return
  172. fi
  173. if ! grep -Fxq "install_${app_name}" $COMPLETION_FILE; then
  174. echo "0"
  175. else
  176. echo "1"
  177. fi
  178. }
  179. # called at the end of the install section of an app script
  180. function install_completed {
  181. if [ ! ${1} ]; then
  182. exit 673935
  183. fi
  184. echo "install_${1}" >> $COMPLETION_FILE
  185. }
  186. # populates an array of "0" or "1" for whether apps are installed
  187. function get_apps_installed {
  188. for a in "${APPS_AVAILABLE[@]}"
  189. do
  190. APPS_INSTALLED+=("$(app_is_installed $a)")
  191. done
  192. }
  193. # populates an array of installed app names
  194. function get_apps_installed_names {
  195. APPS_INSTALLED_NAMES=()
  196. for a in "${APPS_AVAILABLE[@]}"
  197. do
  198. if [[ $(app_is_installed $a) == "1" ]]; then
  199. APPS_INSTALLED_NAMES+=("$a")
  200. fi
  201. done
  202. }
  203. # detects what apps are available
  204. function detect_apps {
  205. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  206. APPS_AVAILABLE=()
  207. APPS_CHOSEN=()
  208. # for all the app scripts
  209. for filename in $FILES
  210. do
  211. app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
  212. item_in_array "${app_name}" "${APPS_AVAILABLE[@]}"
  213. if [[ $? != 0 ]]; then
  214. APPS_AVAILABLE+=("${app_name}")
  215. APPS_CHOSEN+=("0")
  216. fi
  217. done
  218. function_check get_apps_installed
  219. get_apps_installed
  220. get_apps_installed_names
  221. }
  222. # detects what apps are available and can be installed
  223. # If the variants list within an app script is an empty string then
  224. # it is considered to be too experimental to be installable
  225. function detect_installable_apps {
  226. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  227. APPS_AVAILABLE=()
  228. APPS_CHOSEN=()
  229. APPS_INSTALLED=()
  230. APPS_INSTALLED_NAMES=()
  231. function_check app_is_installed
  232. # for all the app scripts
  233. for filename in $FILES
  234. do
  235. app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
  236. item_in_array "${app_name}" "${APPS_AVAILABLE[@]}"
  237. if [[ $? != 0 ]]; then
  238. variants_list=$(app_variants $filename)
  239. # check for empty string
  240. if [ ${#variants_list} -gt 0 ]; then
  241. APPS_AVAILABLE+=("${app_name}")
  242. APPS_CHOSEN+=("0")
  243. APPS_INSTALLED+=("$(app_is_installed $app_name)")
  244. if [[ $(app_is_installed $app_name) == "1" ]]; then
  245. APPS_INSTALLED_NAMES+=("$app_name")
  246. fi
  247. fi
  248. fi
  249. done
  250. }
  251. # creates the APPS_AVAILABLE and APPS_CHOSEN arrays based on
  252. # the given variant name
  253. function choose_apps_for_variant {
  254. variant_name="$1"
  255. FILES=/usr/share/${PROJECT_NAME}/apps/${PROJECT_NAME}-app-*
  256. APPS_AVAILABLE=()
  257. APPS_CHOSEN=()
  258. # for all the app scripts
  259. for filename in $FILES
  260. do
  261. app_name=$(echo "${filename}" | awk -F '-app-' '{print $2}')
  262. item_in_array "${app_name}" "${APPS_AVAILABLE[@]}"
  263. if [[ $? != 0 ]]; then
  264. APPS_AVAILABLE+=("${app_name}")
  265. if grep -q "VARIANTS=" ${filename}; then
  266. variants_list=$(app_variants $filename)
  267. if [[ "${variants_list}" == 'all'* || \
  268. "${variants_list}" == "$variant_name "* || \
  269. "${variants_list}" == *" $variant_name "* || \
  270. "${variants_list}" == *" $variant_name" ]]; then
  271. if [[ $(app_is_removed ${a}) == "0" ]]; then
  272. APPS_CHOSEN+=("1")
  273. else
  274. APPS_CHOSEN+=("0")
  275. fi
  276. else
  277. APPS_CHOSEN+=("0")
  278. fi
  279. else
  280. APPS_CHOSEN+=("0")
  281. fi
  282. fi
  283. done
  284. function_check get_apps_installed
  285. get_apps_installed
  286. }
  287. # show a list of apps which have been chosen
  288. function list_chosen_apps {
  289. app_index=0
  290. for a in "${APPS_AVAILABLE[@]}"
  291. do
  292. if [[ ${APPS_CHOSEN[$app_index]} == "1" ]]; then
  293. echo $"${a}"
  294. fi
  295. app_index=$[app_index+1]
  296. done
  297. }
  298. function remove_apps {
  299. app_index=0
  300. for a in "${APPS_AVAILABLE[@]}"
  301. do
  302. if [[ ${APPS_INSTALLED[$app_index]} == "1" ]]; then
  303. if [[ ${APPS_CHOSEN[$app_index]} == "0" ]]; then
  304. echo $"Removing application: ${a}"
  305. app_load_variables ${a}
  306. remove_app ${a}
  307. remove_${a}
  308. echo $"${a} was removed"
  309. fi
  310. fi
  311. app_index=$[app_index+1]
  312. done
  313. update_installed_apps_list
  314. }
  315. function install_apps {
  316. is_interactive=$1
  317. # interactive install configuration for each app
  318. if [ ${is_interactive} ]; then
  319. app_index=0
  320. for a in "${APPS_AVAILABLE[@]}"
  321. do
  322. if [[ ${APPS_INSTALLED[$app_index]} == "0" ]]; then
  323. if [[ ${APPS_CHOSEN[$app_index]} == "1" ]]; then
  324. # interactively obtain settings for this app
  325. if [[ $(function_exists install_interactive_${a}) == "1" ]]; then
  326. install_interactive_${a}
  327. fi
  328. fi
  329. fi
  330. app_index=$[app_index+1]
  331. done
  332. fi
  333. # now install the apps
  334. app_index=0
  335. for a in "${APPS_AVAILABLE[@]}"
  336. do
  337. if [[ ${APPS_INSTALLED[$app_index]} == "0" ]]; then
  338. if [[ ${APPS_CHOSEN[$app_index]} == "1" ]]; then
  339. if [ ${is_interactive} ]; then
  340. # clears any removal indicator
  341. reinstall_app ${a}
  342. app_load_variables ${a}
  343. if [[ $(app_is_installed ${a}) == "1" ]]; then
  344. echo $"Upgrading application from interactive: ${a}"
  345. upgrade_${a}
  346. echo $"${a} was upgraded from interactive"
  347. else
  348. echo $"Installing application from interactive: ${a}"
  349. install_${a}
  350. app_save_variables ${a}
  351. install_completed ${a}
  352. echo $"${a} was installed from interactive"
  353. fi
  354. else
  355. # check if the app was removed
  356. if [[ $(app_is_removed ${a}) == "0" ]]; then
  357. app_load_variables ${a}
  358. if [[ $(app_is_installed ${a}) == "1" ]]; then
  359. echo $"Upgrading application: ${a}"
  360. upgrade_${a}
  361. echo $"${a} was upgraded"
  362. else
  363. echo $"Installing application: ${a}"
  364. install_${a}
  365. install_completed ${a}
  366. echo $"${a} was installed"
  367. fi
  368. else
  369. echo $"${a} has been removed and so will not be reinstalled"
  370. fi
  371. fi
  372. fi
  373. fi
  374. app_index=$[app_index+1]
  375. done
  376. update_installed_apps_list
  377. }
  378. # NOTE: deliberately no exit 0