installJRMC 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813
  1. #!/usr/bin/env bash
  2. # Install JRiver Media Center and associated services
  3. # See installJRMC --help or printHelp() below
  4. #
  5. # Copyright (c) 2021-2023 Bryan C. Roessler
  6. # This software is released under the Apache License.
  7. # https://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # TODO (v1.1)
  10. # 1. Interactive mode
  11. # 2. Additional containerization (createrepo and rpmbuild)
  12. # 3. Tests
  13. #
  14. # BUGS
  15. # 1. No createrepo on Mint
  16. shopt -s extglob
  17. declare -g SCRIPTVERSION="1.0-dev"
  18. declare -g BOARDURL="https://yabb.jriver.com/interact/index.php/board,76.0.html" # MC30
  19. declare -g DEBIANBASE="buster"
  20. declare -g MCVERSION_HARDCODE="30.0.83"
  21. printHelp() {
  22. debug "Running: ${FUNCNAME[0]}"
  23. cat <<-'EOF'
  24. USAGE:
  25. installJRMC [[OPTION] [VALUE]]...
  26. If no options (excluding -d or --debug) are provided installJRMC defaults to '--install repo'.
  27. OPTIONS
  28. --install, -i repo|local
  29. repo: Install MC from repository, updates are handled by the system package manager
  30. local: Build and install MC package locally from official source release
  31. --build[=suse|fedora|centos]
  32. Build RPM from source DEB but do not install
  33. Optionally, specify a target distro for cross-building (ex. --build=suse, note the '=')
  34. --compat
  35. Build/install MC locally without minimum dependency version requirements
  36. --mcversion VERSION
  37. Specify the MC version, ex. "30.0.83" (default: latest version)
  38. --arch VERSION
  39. Specify the MC architecture, ex. "amd64", "arm64", etc (default: host architecture)
  40. --outputdir PATH
  41. Generate rpmbuild output in this directory (default: ./output)
  42. --restorefile RESTOREFILE
  43. Restore file location for automatic license registration
  44. --betapass PASSWORD
  45. Enter beta team password for access to beta builds
  46. --service, -s SERVICE
  47. See SERVICES section below for a list of possible services to install
  48. --service-type user|system
  49. Starts services at boot (system) or at user login (user) (default: per service, see SERVICES)
  50. --container, -c CONTAINER (TODO: Under construction)
  51. See CONTAINERS section below for a list of possible services to install
  52. --createrepo[=suse|fedora|centos]
  53. Build rpm, copy to webroot, and run createrepo.
  54. Use in conjunction with --build=TARGET for crossbuilding repos
  55. Optionally, specify a target distro for non-native repo (ex. --createrepo=fedora, note the '=')
  56. --createrepo-webroot PATH
  57. Specify the webroot directory to install the repo (default: /var/www/jriver)
  58. --createrepo-user USER
  59. Specify the web server user if it differs from $USER
  60. --uninstall, -u
  61. Uninstall JRiver MC, remove services, containers, and firewall rules (does not remove library files)
  62. --yes, -y, --auto
  63. Always assume yes for questions
  64. --version, -v
  65. Print this script version and exit
  66. --debug, -d
  67. Print debug output
  68. --help, -h
  69. Print help dialog and exit
  70. SERVICES
  71. jriver-mediaserver (default --service-type=user)
  72. Enable and start a mediaserver systemd service (requires an existing X server)
  73. jriver-mediacenter (user)
  74. Enable and start a mediacenter systemd service (requires an existing X server)
  75. jriver-x11vnc (user)
  76. Enable and start x11vnc for the local desktop (requires an existing X server)
  77. Usually combined with jriver-mediaserver or jriver-mediacenter services
  78. --vncpass and --display are optional (see below)
  79. jriver-xvnc (system)
  80. Enable and start a new Xvnc session running JRiver Media Center
  81. --vncpass PASSWORD
  82. Set the vnc password for x11vnc/Xvnc access. If no password is set, installJRMC
  83. will either use existing password stored in $HOME/.vnc/jrmc_passwd or use no password
  84. --display DISPLAY
  85. Display to use for x11vnc/Xvnc (default: The current display (x11vnc) or the
  86. current display incremented by 1 (Xvnc))
  87. jriver-createrepo (system)
  88. Install hourly service to build latest MC RPM and run createrepo
  89. CONTAINERS (TODO: Under construction)
  90. mediacenter-xvnc
  91. createrepo
  92. EOF
  93. }
  94. #######################################
  95. # Helpers
  96. #######################################
  97. debug() { (( DEBUG )) && echo "Debug: $*"; }
  98. err() { echo "Error: $*" >&2; }
  99. askOk() {
  100. declare response
  101. (( YES_SWITCH )) && return 0
  102. read -r -p "$* [y/N]: " response
  103. [[ ${response,,} =~ ^(yes|y)$ ]]
  104. }
  105. execute() {
  106. if debug "$*"; then
  107. "$@"
  108. else
  109. "$@" &>/dev/null
  110. fi
  111. }
  112. #######################################
  113. # Perform OS detection and fallback
  114. # Generate OS-specific functions
  115. #######################################
  116. init() {
  117. debug "Running: ${FUNCNAME[0]}"
  118. declare -g ID RPM_MGR ARCH
  119. declare -ga PKG_INSTALL PKG_REMOVE PKG_UPDATE PKG_QUERY
  120. echo "Starting installJRMC"
  121. (( DEBUG )) || echo "To enable debugging output, use --debug or -d"
  122. if [[ -e /etc/os-release ]]; then
  123. source "/etc/os-release"
  124. else
  125. err "/etc/os-release not found"
  126. err "Your OS is unsupported"
  127. printHelp
  128. exit 1
  129. fi
  130. # Detect architecture and translate to MC convention
  131. # Override with user input with getopt
  132. ARCH=$(uname -m)
  133. case $ARCH in
  134. x86_64)
  135. ARCH="amd64"
  136. ;;
  137. esac
  138. debug "Detected host platform: $ID $VERSION_ID $ARCH"
  139. # normalize ID and set distro-specific vars
  140. case $ID in
  141. debian|arch)
  142. ;;
  143. centos|fedora)
  144. if hash dnf &>/dev/null; then
  145. RPM_MGR="dnf"
  146. elif hash yum &>/dev/null; then
  147. RPM_MGR="yum"
  148. fi
  149. ;;
  150. rhel)
  151. ID="centos"
  152. ;;
  153. linuxmint|neon|*ubuntu*)
  154. ID="ubuntu"
  155. ;;
  156. *suse*)
  157. ID="suse"
  158. ;;
  159. raspbian)
  160. ID="debian"
  161. ;;
  162. *)
  163. err "Autodetecting distro, this is unreliable and --compat may be required"
  164. if hash dnf &>/dev/null; then
  165. ID="fedora"
  166. RPM_MGR="dnf"
  167. elif hash yum &>/dev/null; then
  168. ID="centos"
  169. RPM_MGR="yum"
  170. COMPAT_SWITCH=1
  171. elif hash apt-get &>/dev/null; then
  172. ID="ubuntu"
  173. elif hash pacman &>/dev/null; then
  174. ID="arch"
  175. else
  176. err "OS detection failed!"
  177. askOk "Continue with manual installation?" || exit 1
  178. ID="unknown"
  179. REPO_INSTALL_SWITCH=0
  180. BUILD_SWITCH=1
  181. LOCAL_INSTALL_SWITCH=1
  182. fi
  183. esac
  184. [[ $ID != "unknown" ]] && debug "Using host platform: $ID $VERSION_ID"
  185. # Abstract distro-specific package manager commands
  186. case $ID in
  187. fedora|centos)
  188. PKG_INSTALL=(execute sudo "$RPM_MGR" install -y)
  189. PKG_REMOVE=(execute sudo "$RPM_MGR" remove -y)
  190. PKG_UPDATE=(execute sudo "$RPM_MGR" makecache)
  191. PKG_QUERY=(rpm -q)
  192. PKG_INSTALL_LOCAL(){ installMCRPM; }
  193. ;;
  194. debian|ubuntu)
  195. PKG_INSTALL=(execute sudo apt-get -f install -y -q0)
  196. PKG_REMOVE=(execute sudo apt-get remove --auto-remove -y -q0)
  197. PKG_UPDATE=(execute sudo apt-get update -y -q0)
  198. PKG_QUERY=(dpkg -s)
  199. PKG_INSTALL_LOCAL(){ installMCDEB; }
  200. ;;
  201. suse)
  202. PKG_INSTALL=(execute sudo zypper --gpg-auto-import-keys --non-interactive --quiet install --force --no-confirm)
  203. PKG_REMOVE=(execute sudo zypper --non-interactive --quiet remove --clean-deps)
  204. PKG_UPDATE=(execute sudo zypper --non-interactive --quiet refresh jriver)
  205. PKG_QUERY=(rpm -q)
  206. PKG_INSTALL_LOCAL(){ installMCRPM; }
  207. ;;
  208. arch)
  209. PKG_INSTALL=(execute sudo pacman -Sy --noconfirm)
  210. PKG_REMOVE=(execute sudo pacman -Rs --noconfirm)
  211. PKG_UPDATE=(execute sudo pacman -Syy)
  212. PKG_QUERY=(sudo pacman -Qs)
  213. PKG_INSTALL_LOCAL(){ installMCARCH; }
  214. ;;
  215. unknown)
  216. PKG_INSTALL=(:)
  217. PKG_REMOVE=(:)
  218. PKG_UPDATE=(:)
  219. PKG_QUERY=(:)
  220. PKG_INSTALL_LOCAL(){ installMCGENERIC; }
  221. esac
  222. }
  223. #######################################
  224. # Parses user input and sets sensible defaults
  225. #######################################
  226. parseInput() {
  227. debug "Running: ${FUNCNAME[0]}"
  228. declare -g BUILD_SWITCH REPO_INSTALL_SWITCH COMPAT_SWITCH TEST_SWITCH
  229. declare -g LOCAL_INSTALL_SWITCH CREATEREPO_SWITCH UNINSTALL_SWITCH
  230. declare -g YES_SWITCH USER_VERSION_SWITCH USER_ARCH
  231. declare -g RESTOREFILE BETAPASS SERVICE_TYPE
  232. declare -g VNCPASS USER_DISPLAY
  233. declare -ga SERVICES CONTAINERS
  234. declare long_opts short_opts input
  235. # Defaults
  236. declare -g BUILD_TARGET="$ID"
  237. declare -g REPO_TARGET="$ID"
  238. declare -g CREATEREPO_USER="$USER"
  239. declare -g SCRIPTDIR=; SCRIPTDIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
  240. declare -g OUTPUTDIR="$SCRIPTDIR/output"
  241. declare -g CREATEREPO_WEBROOT="/var/www/jriver"
  242. declare -g USER="${SUDO_USER:-$USER}"
  243. declare -g HOME; HOME=$(getent passwd "$USER" | cut -d: -f6)
  244. if [[ $# -eq 0 ]] ||
  245. [[ $# -eq 1 && " $1 " =~ ^( --debug | -d | -y | --yes )$ ]] &&
  246. [[ $ID != "unknown" ]]; then
  247. REPO_INSTALL_SWITCH=1
  248. elif [[ $# -eq 1 && " $1 " =~ ^( --compat )$ ]]; then
  249. BUILD_SWITCH=1
  250. LOCAL_INSTALL_SWITCH=1
  251. fi
  252. long_opts="install:,build::,outputdir:,mcversion:,restorefile:,betapass:,"
  253. long_opts+="service-type:,service:,services:,"
  254. long_opts+="version,debug,verbose,help,uninstall,tests,"
  255. long_opts+="createrepo::,createrepo-webroot:,createrepo-user:,"
  256. long_opts+="vncpass:,display:,container:,compat,arch:,yes,auto"
  257. short_opts="+i:vb::dhus:c:"
  258. # Reset DEBUG and catch with getopt
  259. declare -g DEBUG=0
  260. if input=$(getopt -o $short_opts -l $long_opts -- "$@"); then
  261. eval set -- "$input"
  262. while true; do
  263. case $1 in
  264. --install|-i)
  265. shift
  266. case $1 in
  267. local|rpm)
  268. BUILD_SWITCH=1
  269. LOCAL_INSTALL_SWITCH=1
  270. ;;
  271. repo|remote)
  272. REPO_INSTALL_SWITCH=1
  273. ;;
  274. esac
  275. ;;
  276. --build|-b)
  277. BUILD_SWITCH=1
  278. shift && BUILD_TARGET="$1"
  279. ;;
  280. --outputdir)
  281. shift && OUTPUTDIR="$1"
  282. ;;
  283. --mcversion)
  284. shift
  285. MCVERSION="$1"
  286. USER_VERSION_SWITCH=1
  287. ;;
  288. --arch)
  289. shift
  290. USER_ARCH="$1"
  291. ;;
  292. --restorefile)
  293. shift && RESTOREFILE="$1"
  294. ;;
  295. --betapass)
  296. shift && BETAPASS="$1"
  297. ;;
  298. --service-type)
  299. shift && SERVICE_TYPE="$1"
  300. ;;
  301. --service|-s|--services)
  302. shift && SERVICES+=("$1")
  303. ;;
  304. --createrepo)
  305. BUILD_SWITCH=1
  306. CREATEREPO_SWITCH=1
  307. shift && REPO_TARGET="$1"
  308. ;;
  309. --createrepo-webroot)
  310. shift && CREATEREPO_WEBROOT="$1"
  311. ;;
  312. --createrepo-user)
  313. shift && CREATEREPO_USER="$1"
  314. ;;
  315. --vncpass)
  316. shift && VNCPASS="$1"
  317. ;;
  318. --display)
  319. shift && USER_DISPLAY="$1"
  320. ;;
  321. --compat)
  322. COMPAT_SWITCH=1
  323. ;;
  324. --container|-c)
  325. shift && CONTAINERS+=("$1")
  326. ;;
  327. --yes|-y|--auto)
  328. YES_SWITCH=1
  329. ;;
  330. --version|-v)
  331. echo "Version: $SCRIPTVERSION"
  332. exit 0
  333. ;;
  334. --debug|-d|--verbose)
  335. DEBUG=1
  336. ;;
  337. --help|-h)
  338. printHelp
  339. exit
  340. ;;
  341. --uninstall|-u)
  342. UNINSTALL_SWITCH=1
  343. ;;
  344. --tests)
  345. TEST_SWITCH=1
  346. ;;
  347. --)
  348. shift
  349. break
  350. ;;
  351. esac
  352. shift
  353. done
  354. else
  355. err "Incorrect options provided"
  356. printHelp && exit 1
  357. fi
  358. }
  359. #######################################
  360. # Uses several methods to determine the latest JRiver MC version
  361. # TODO but how to determine build distro `$DEBIANBASE=buster`?
  362. #######################################
  363. setMCVersion() {
  364. debug "Running: ${FUNCNAME[0]}"
  365. declare -g MCVERSION_SOURCE MVERSION MCPKG MCRPM
  366. declare cnt
  367. # User input
  368. if (( USER_VERSION_SWITCH )) &&
  369. [[ $MCVERSION =~ ([0-9]+.[0-9]+.[0-9]+) ]]; then
  370. MCVERSION_SOURCE="user input"
  371. # Containerized package manager
  372. elif installPackage --silent buildah &&
  373. hash buildah &>/dev/null &&
  374. cnt=$(buildah from --quiet debian:$DEBIANBASE-slim) &>/dev/null &&
  375. buildah run "$cnt" -- bash -c \
  376. "echo 'deb [trusted=no arch=amd64,i386,armhf,arm64] http://dist.jriver.com/latest/mediacenter/ $DEBIANBASE main' > /etc/apt/sources.list 2>&1" &>/dev/null &&
  377. buildah run "$cnt" -- bash -c \
  378. "apt update --allow-insecure-repositories &>/dev/null" &>/dev/null &&
  379. MCVERSION=$(buildah run "$cnt" -- apt-cache policy mediacenter?? | grep Candidate | awk '{print $2}' | sort -V | tail -n1) &>/dev/null &&
  380. [[ $MCVERSION =~ ([0-9]+.[0-9]+.[0-9]+) ]]; then
  381. MCVERSION_SOURCE="containerized package manager"
  382. buildah rm "$cnt" &>/dev/null
  383. # Webscrape
  384. elif installPackage wget && MCVERSION=$(wget -qO- "$BOARDURL" | grep -o "[0-9][0-9]\.[0-9]\.[0-9]\+" | head -n 1) &&
  385. [[ $MCVERSION =~ ([0-9]+.[0-9]+.[0-9]+) ]]; then
  386. MCVERSION_SOURCE="webscrape"
  387. # Hardcoded
  388. else
  389. declare -g MCVERSION="$MCVERSION_HARDCODE"
  390. MCVERSION_SOURCE="hardcoded or MCVERSION env"
  391. err "Warning! Using hardcoded version number"
  392. fi
  393. MVERSION="${MCVERSION%%.*}"
  394. MCPKG="mediacenter$MVERSION"
  395. MCRPM="$OUTPUTDIR/RPMS/x86_64/mediacenter$MVERSION-$MCVERSION.x86_64.rpm"
  396. if [[ $MCVERSION_SOURCE == "user input" ]]; then
  397. # Append explicit package version when user provides --mcversion
  398. case $ID in
  399. fedora|centos|suse)
  400. MCPKG+="-$MCVERSION"
  401. ;;
  402. debian|ubuntu)
  403. MCPKG+="=$MCVERSION"
  404. ;;
  405. esac
  406. fi
  407. echo "Using MC version $MCVERSION determined by $MCVERSION_SOURCE"
  408. [[ $MCVERSION_SOURCE == "user input" ]] || echo "To override, use --mcversion"
  409. debug "MVERSION: $MVERSION, MCVERSION: $MCVERSION, MCPKG: $MCPKG, MCRPM: $MCRPM"
  410. }
  411. #######################################
  412. # Installs a package using the system package manager
  413. # Arguments:
  414. # One or more package names
  415. # Options:
  416. # --no-install-check: Do not check if package is already installed
  417. # --no-gpg-check: Disable GPG checks for RPM based distros
  418. # --allow-downgrades: Useful for installing specific MC versions
  419. # --silent, -s: Do not print errors (useful for optional packages)
  420. #######################################
  421. installPackage() {
  422. debug "Running: ${FUNCNAME[0]}" "$@"
  423. declare -a pkg_array install_flags
  424. declare long_opts input pkg
  425. declare no_install_check allow_downgrades silent refresh no_gpg_check
  426. declare -A pkg_aliases
  427. long_opts="no-install-check,allow-downgrades,no-gpg-check,refresh,silent"
  428. if input=$(getopt -o +s -l "$long_opts" -- "$@"); then
  429. eval set -- "$input"
  430. while true; do
  431. case $1 in
  432. --no-install-check)
  433. no_install_check=1
  434. ;;
  435. --allow-downgrades)
  436. allow_downgrades=1
  437. ;;
  438. --no-gpg-check)
  439. no_gpg_check=1
  440. ;;
  441. --refresh)
  442. refresh=1
  443. ;;
  444. --silent|-s)
  445. silent=1
  446. ;;
  447. --)
  448. shift
  449. break
  450. ;;
  451. esac
  452. shift
  453. done
  454. else
  455. err "Incorrect options provided"
  456. exit 1
  457. fi
  458. # Package aliases
  459. case $ID in
  460. debian|ubuntu)
  461. pkg_aliases["rpm-build"]="rpm"
  462. pkg_aliases["createrepo_c"]="createrepo"
  463. pkg_aliases["tigervnc-server"]="tigervnc-standalone-server"
  464. ;;
  465. esac
  466. # Filter installed packages
  467. for pkg in "$@"; do
  468. if [[ -v pkg_aliases[$pkg] ]]; then
  469. debug "Aliasing $pkg to ${pkg_aliases[$pkg]}"
  470. pkg=${pkg_aliases[$pkg]}
  471. fi
  472. if (( no_install_check )) ||
  473. ! (hash "$pkg" &>/dev/null ||
  474. "${PKG_QUERY[@]}" "$pkg" &>/dev/null); then
  475. pkg_array+=("$pkg")
  476. else
  477. debug "$pkg already installed, skipping installation"
  478. fi
  479. done
  480. # Generate distro-specific install flags
  481. case $ID in
  482. debian|ubuntu)
  483. (( allow_downgrades )) && install_flags+=(--allow-downgrades)
  484. ;;
  485. fedora|centos)
  486. (( allow_downgrades )) && install_flags+=(--allowerasing)
  487. (( no_gpg_check )) && install_flags+=(--nogpgcheck)
  488. (( refresh )) && install_flags+=(--refresh)
  489. ;;
  490. suse)
  491. (( no_gpg_check )) &&
  492. install_flags+=(--allow-unsigned-rpm)
  493. ;;
  494. esac
  495. # Install packages from package array
  496. if [[ ${#pkg_array[@]} -ge 1 ]]; then
  497. if ! "${PKG_INSTALL[@]}" "${install_flags[@]}" "${pkg_array[@]}"; then
  498. (( silent )) || err "Failed to install ${pkg_array[*]}. Attempting to continue"
  499. return 1
  500. fi
  501. fi
  502. return 0
  503. }
  504. #######################################
  505. # Installs mesa-va-drivers-freeworld
  506. #######################################
  507. installMesa() {
  508. debug "Running: ${FUNCNAME[0]}"
  509. # Currently only necessary in Fedora/CentOS
  510. case $ID in
  511. fedora|centos)
  512. if ! "${PKG_QUERY[@]}" mesa-va-drivers-freeworld &>/dev/null; then
  513. if "${PKG_QUERY[@]}" mesa-va-drivers &>/dev/null; then
  514. if ! execute sudo dnf swap -y \
  515. mesa-va-drivers \
  516. mesa-va-drivers-freeworld; then
  517. err "Package swap failed!"
  518. return 1
  519. fi
  520. else
  521. "${PKG_INSTALL[@]}" mesa-va-drivers-freeworld
  522. fi
  523. fi
  524. ;;
  525. esac
  526. }
  527. #######################################
  528. # Installs JRiver Media Center from a remote repository
  529. #######################################
  530. installMCFromRepo() {
  531. debug "Running: ${FUNCNAME[0]}"
  532. case $ID in
  533. fedora|centos)
  534. sudo bash -c "cat <<-EOF > /etc/yum.repos.d/jriver.repo
  535. [jriver]
  536. name=JRiver Media Center repo by BryanC
  537. baseurl=https://repos.bryanroessler.com/jriver
  538. gpgcheck=0
  539. EOF"
  540. ;;
  541. debian|ubuntu)
  542. declare repo_dir="/etc/apt/sources.list.d"
  543. [[ -d $repo_dir ]] || execute sudo mkdir -p "$repo_dir"
  544. # Remove existing MC repositories
  545. sudo rm -rf "$repo_dir"/mediacenter*.list
  546. installPackage wget
  547. sudo bash -c "cat <<-EOF > $repo_dir/jriver.list
  548. deb [trusted=yes arch=amd64,i386,armhf,arm64] http://dist.jriver.com/latest/mediacenter/ $DEBIANBASE main
  549. EOF"
  550. wget -qO- "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" |
  551. sudo tee /etc/apt/trusted.gpg.d/jriver.asc &>/dev/null
  552. ;;
  553. *)
  554. err "An MC repository for $ID is not yet available"
  555. err "Use --install local to install MC on $ID"
  556. return 1
  557. ;;
  558. esac
  559. if ! "${PKG_UPDATE[@]}"; then
  560. err "Package update failed!"
  561. return 1
  562. fi
  563. # Install mesa-va-drivers-freeworld separately from the RPM using dnf swap
  564. installMesa
  565. if ! installPackage \
  566. --no-install-check \
  567. --allow-downgrades \
  568. --no-gpg-check \
  569. "$MCPKG"; then
  570. err "Package install failed!"
  571. return 1
  572. fi
  573. }
  574. #######################################
  575. # Acquires the source DEB package from JRiver
  576. #######################################
  577. acquireDeb() {
  578. debug "Running: ${FUNCNAME[0]}"
  579. declare -g MCDEB="$OUTPUTDIR/SOURCES/MediaCenter-$MCVERSION-${USER_ARCH:-$ARCH}.deb"
  580. debug "MCDEB=$MCDEB"
  581. # If deb file already exists, skip download
  582. if [[ -f $MCDEB ]]; then
  583. echo "Using existing DEB: $MCDEB"
  584. return 0
  585. fi
  586. if [[ -v BETAPASS ]] &&
  587. echo "Checking beta repo for DEB package" && execute wget -q -O "$MCDEB" \
  588. "https://files.jriver.com/mediacenter/channels/v$MVERSION/beta/$BETAPASS/MediaCenter-$MCVERSION-${USER_ARCH:-$ARCH}.deb"; then
  589. echo "Found!"
  590. elif echo "Checking latest repo for DEB package" && execute wget -q -O "$MCDEB" \
  591. "https://files.jriver.com/mediacenter/channels/v$MVERSION/latest/MediaCenter-$MCVERSION-${USER_ARCH:-$ARCH}.deb"; then
  592. echo "Found!"
  593. elif echo "Checking test repo for DEB package" && execute wget -q -O "$MCDEB" \
  594. "https://files.jriver.com/mediacenter/test/MediaCenter-$MCVERSION-${USER_ARCH:-$ARCH}.deb"; then
  595. echo "Found!"
  596. else
  597. err "Cannot find DEB file"
  598. exit 1
  599. fi
  600. if [[ -f $MCDEB ]]; then
  601. echo "Downloaded MC $MCVERSION DEB to $MCDEB"
  602. else
  603. err "Downloaded DEB file missing or corrupted"
  604. exit 1
  605. fi
  606. }
  607. #######################################
  608. # Creates a SPEC file and builds the RPM from the source DEB using rpmbuild
  609. #######################################
  610. buildRPM() {
  611. debug "Running: ${FUNCNAME[0]}"
  612. declare i rpmbuild_cmd
  613. declare -a requires recommends
  614. # skip rebuilding the rpm if it already exists
  615. if [[ -f $MCRPM ]]; then
  616. echo "$MCRPM already exists. Skipping build step"
  617. return 0
  618. fi
  619. # Load deb dependencies into array
  620. IFS=',' read -ra requires <<< "$(dpkg-deb -f "$MCDEB" Depends)"
  621. IFS=',' read -ra recommends <<< "$(dpkg-deb -f "$MCDEB" Recommends)"
  622. # Clean up formatting
  623. requires=("${requires[@]%%|*}")
  624. requires=("${requires[@]/?:/}")
  625. requires=("${requires[@]# }")
  626. requires=("${requires[@]% }")
  627. requires=("${requires[@]//\(/}")
  628. requires=("${requires[@]//)/}")
  629. recommends=("${recommends[@]%%|*}")
  630. recommends=("${recommends[@]/?:/}")
  631. recommends=("${recommends[@]# }")
  632. recommends=("${recommends[@]% }")
  633. recommends=("${recommends[@]//\(/}")
  634. recommends=("${recommends[@]//)/}")
  635. # Translate package names
  636. case $BUILD_TARGET in
  637. fedora|centos)
  638. requires=("${requires[@]/libc6/glibc}")
  639. requires=("${requires[@]/libasound2/alsa-lib}")
  640. requires=("${requires[@]/libuuid1/libuuid}")
  641. requires=("${requires[@]/libx11-6/libX11}")
  642. requires=("${requires[@]/libxext6/libXext}")
  643. requires=("${requires[@]/libxcb1/libxcb}")
  644. requires=("${requires[@]/libxdmcp6/libXdmcp}")
  645. requires=("${requires[@]/libstdc++6/libstdc++}")
  646. requires=("${requires[@]/libgtk-3-0/gtk3}")
  647. requires=("${requires[@]/libgl1/mesa-libGL}")
  648. requires=("${requires[@]/libpango-1.0-0/pango}")
  649. requires=("${requires[@]/libpangoft2-1.0-0/pango}")
  650. requires=("${requires[@]/libpangox-1.0-0/pango}")
  651. requires=("${requires[@]/libpangoxft-1.0-0/pango}")
  652. requires=("${requires[@]/libnss3/nss}")
  653. requires=("${requires[@]/libnspr4/nspr}")
  654. requires=("${requires[@]/libgomp1/libgomp}")
  655. requires=("${requires[@]/libfribidi0/fribidi}")
  656. requires=("${requires[@]/libfontconfig1/fontconfig}")
  657. requires=("${requires[@]/libfreetype6/freetype}")
  658. requires=("${requires[@]/libharfbuzz0b/harfbuzz}")
  659. requires=("${requires[@]/libgbm1/mesa-libgbm}")
  660. requires=("${requires[@]/libva2/libva}")
  661. requires=("${requires[@]/libepoxy0/libepoxy}")
  662. requires=("${requires[@]/liblcms2-2/lcms2}")
  663. requires=("${requires[@]/libvulkan1/vulkan-loader}")
  664. requires=("${requires[@]/libepoxy0/libepoxy}")
  665. requires=("${requires[@]/python/python3}")
  666. recommends+=(mesa-va-drivers-freeworld)
  667. ;;
  668. suse)
  669. requires=("${requires[@]/libc6/glibc}")
  670. requires=("${requires[@]/libasound2/alsa-lib}")
  671. requires=("${requires[@]/libx11-6/libX11-6}")
  672. requires=("${requires[@]/libxext6/libXext6}")
  673. requires=("${requires[@]/libxdmcp6/libXdmcp6}")
  674. requires=("${requires[@]/libgtk-3-0/gtk3}")
  675. requires=("${requires[@]/libgl1/Mesa-libGL1}")
  676. requires=("${requires[@]/libpango-1.0-0/pango}")
  677. requires=("${requires[@]/libpangoft2-1.0-0/pango}")
  678. requires=("${requires[@]/libpangox-1.0-0/pango}")
  679. requires=("${requires[@]/libpangoxft-1.0-0/pango}")
  680. requires=("${requires[@]/libnss3/mozilla-nss}")
  681. requires=("${requires[@]/libnspr4/mozilla-nspr}")
  682. requires=("${requires[@]/libfribidi0/fribidi}")
  683. requires=("${requires[@]/libfontconfig1/fontconfig}")
  684. requires=("${requires[@]/libfreetype6*/freetype}") # Remove minimum version specifier
  685. requires=("${requires[@]/libharfbuzz0b/libharfbuzz0}")
  686. for i in "${!requires[@]}"; do
  687. [[ ${requires[$i]} == "mesa-vulkan-drivers" ]] && unset -v 'requires[i]'
  688. done
  689. recommends+=(libvulkan_intel)
  690. recommends+=(libvulkan_radeon)
  691. ;;
  692. esac
  693. # Convert array to newline delim'd string (for heredoc)
  694. printf -v requires "Requires: %s\n" "${requires[@]}"
  695. printf -v recommends "Recommends: %s\n" "${recommends[@]}"
  696. # Strip last newline
  697. requires="${requires%?}"
  698. recommends="${recommends%?}"
  699. if (( COMPAT_SWITCH )); then
  700. # Strip minimum versions
  701. requires=$(echo "$requires" | awk -F" " 'NF == 4 {print $1 " " $2} NF != 4 {print $0}')
  702. fi
  703. # Create spec file
  704. cat <<-EOF > "$OUTPUTDIR/SPECS/mediacenter.spec"
  705. Name: mediacenter$MVERSION
  706. Version: $MCVERSION
  707. Release: 1
  708. Summary: JRiver Media Center
  709. Group: Applications/Media
  710. Source0: http://files.jriver.com/mediacenter/channels/v$MVERSION/latest/MediaCenter-$MCVERSION-${USER_ARCH:-$ARCH}.deb
  711. BuildArch: x86_64
  712. %define _rpmfilename %%{ARCH}/%%{NAME}-%%{version}.%%{ARCH}.rpm
  713. AutoReq: 0
  714. $requires
  715. $recommends
  716. Conflicts: MediaCenter
  717. Provides: mediacenter$MVERSION
  718. License: Copyright 1998-2023, JRiver, Inc. All rights reserved. Protected by U.S. patents #7076468 and #7062468
  719. URL: http://www.jriver.com/
  720. %define __provides_exclude_from ^%{_libdir}/jriver/.*/.*\\.so.*$
  721. %description
  722. Media Center is more than a world class player.
  723. %global __os_install_post %{nil}
  724. %prep
  725. %build
  726. %install
  727. dpkg -x %{S:0} %{buildroot}
  728. %post -p /sbin/ldconfig
  729. %postun -p /sbin/ldconfig
  730. %files
  731. %{_bindir}/mediacenter$MVERSION
  732. %{_libdir}/jriver
  733. %{_datadir}
  734. %exclude %{_datadir}/applications/media_center_packageinstaller_$MVERSION.desktop
  735. /etc/security/limits.d/*
  736. EOF
  737. # Run rpmbuild
  738. echo "Building MC $MCVERSION RPM, this may take awhile"
  739. rpmbuild_cmd=(
  740. rpmbuild
  741. --define="%_topdir $OUTPUTDIR"
  742. --define="%_libdir /usr/lib"
  743. -bb
  744. "$OUTPUTDIR/SPECS/mediacenter.spec"
  745. )
  746. if execute "${rpmbuild_cmd[@]}" && [[ -f $MCRPM ]] ; then
  747. echo "Build successful. The RPM file is located at: $MCRPM"
  748. else
  749. err "Build failed"
  750. # For automation, let's remove the source DEB and reaquire it on next
  751. # run after failure in case it is corrupted or buggy
  752. [[ -f $MCDEB ]] && echo "Removing source DEB" && rm -f "$MCDEB"
  753. exit 1
  754. fi
  755. }
  756. #######################################
  757. # Installs Media Center DEB package and optional compatability fixes
  758. #######################################
  759. installMCDEB() {
  760. debug "Running: ${FUNCNAME[0]}"
  761. if (( COMPAT_SWITCH )); then
  762. declare extract_dir && extract_dir="$(mktemp -d)"
  763. pushd "$extract_dir" &>/dev/null || return
  764. execute ar x "$MCDEB"
  765. execute tar xJf "control.tar.xz"
  766. # Remove minimum version specifiers from control file
  767. sed -i 's/ ([^)]*)//g' "control"
  768. sed -i 's/([^)]*)//g' "control" # TODO MC DEB package error
  769. [[ $ID == "ubuntu" && ${VERSION_ID%.*} -le 16 ]] &&
  770. sed -i 's/libva2/libva1/g' "control"
  771. execute tar -cJf "control.tar.xz" "control" "postinst"
  772. declare -g MCDEB="${MCDEB/.deb/.compat.deb}"
  773. execute ar rcs "$MCDEB" "debian-binary" "control.tar.xz" "data.tar.xz"
  774. popd &>/dev/null || return
  775. execute rm -rf "$extract_dir"
  776. fi
  777. installPackage \
  778. --no-install-check \
  779. --no-gpg-check \
  780. --allow-downgrades \
  781. "$MCDEB"
  782. }
  783. #######################################
  784. # Installs Media Center RPM package
  785. #######################################
  786. installMCRPM() {
  787. debug "Running: ${FUNCNAME[0]}"
  788. # Install mesa-va-freeworld separately from the RPM for dnf swap
  789. installMesa
  790. installPackage --no-install-check --no-gpg-check --allow-downgrades "$MCRPM"
  791. }
  792. #######################################
  793. # Installs Media Center manually
  794. #######################################
  795. installMCGENERIC() {
  796. debug "Running: ${FUNCNAME[0]}"
  797. declare -a raw_files
  798. echo "Using raw installation method!"
  799. declare extract_dir && extract_dir="$(mktemp -d)"
  800. pushd "$extract_dir" &>/dev/null || return
  801. execute ar x "$MCDEB"
  802. execute tar xJf "control.tar.xz"
  803. echo "You must install the following dependencies manually:"
  804. grep -i "Depends:" control
  805. readarray -t raw_files < <(tar xJvf data.tar.xz)
  806. # Output to log file
  807. for f in "${raw_files[@]/#./}"; do
  808. echo "$f" >> "$SCRIPTDIR/.uninstall"
  809. done
  810. #echo "${raw_files[@]/#./}" >> "$SCRIPTDIR/.uninstall"
  811. # Manually install files
  812. for f in "${raw_files[@]}"; do
  813. execute sudo cp -a "$f" "${f/#./}"
  814. done
  815. popd &>/dev/null || return
  816. execute rm -rf "$extract_dir"
  817. return 0
  818. }
  819. #######################################
  820. # Installs local Media Center PKGBUILD
  821. #######################################
  822. installMCARCH() {
  823. debug "Running: ${FUNCNAME[0]}"
  824. [[ -d $OUTPUTDIR/PKGBUILD ]] || execute mkdir -p "$OUTPUTDIR/PKGBUILD"
  825. cat <<-EOF > "$OUTPUTDIR/PKGBUILD/mediacenter.pkgbuild"
  826. pkgname=mediacenter$MVERSION
  827. pkgver=$MCVERSION
  828. pkgrel=1
  829. pkgdesc="The Most Comprehensive Media Software"
  830. arch=('x86_64')
  831. url="http://www.jriver.com/"
  832. license=('custom')
  833. depends=('alsa-lib' 'gcc-libs' 'libx11' 'libxext' 'libxcb' 'libxau' 'libxdmcp' 'util-linux' 'libxext' 'gtk3')
  834. optdepends=(
  835. 'mesa-libgl: nouveau video support'
  836. 'nvidia-libgl: nvidia video support'
  837. 'nvidia-utils: nvidia vulkan support'
  838. 'vulkan-intel: intel vulkan support'
  839. 'vulkan-radeon: amd vulkan support'
  840. 'vorbis-tools: ogg vorbis support'
  841. 'musepack-tools: musepack support'
  842. )
  843. source=("http://files.jriver.com/mediacenter/channels/v$MVERSION/latest/MediaCenter-$MCVERSION-${USER_ARCH:-$ARCH}.deb")
  844. package() {
  845. cd "\$srcdir"
  846. bsdtar xf data.tar.xz -C "\$pkgdir"
  847. }
  848. EOF
  849. pushd "$OUTPUTDIR/PKGBUILD" &>/dev/null || return
  850. if ! execute makepkg \
  851. --install \
  852. --syncdeps \
  853. --clean \
  854. --cleanbuild \
  855. --skipinteg \
  856. --force \
  857. --noconfirm \
  858. -p mediacenter.pkgbuild; then
  859. echo "makepkg failed"
  860. exit 1
  861. fi
  862. popd &>/dev/null || return
  863. }
  864. #######################################
  865. # Copy the RPM to createrepo-webroot and runs createrepo as the createrepo-user
  866. #######################################
  867. runCreaterepo() {
  868. debug "Running: ${FUNCNAME[0]}"
  869. declare -a cr_cmd
  870. installPackage createrepo_c
  871. # If the webroot does not exist, create it
  872. if [[ ! -d $CREATEREPO_WEBROOT ]]; then
  873. if ! execute sudo -u "$CREATEREPO_USER" mkdir -p "$CREATEREPO_WEBROOT"; then
  874. if ! ( execute sudo mkdir -p "$CREATEREPO_WEBROOT" &&
  875. execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT" ); then
  876. err "Could not create the createrepo-webroot path!"
  877. err "Make sure that the webroot $CREATEREPO_WEBROOT is writeable by user $CREATEREPO_USER"
  878. err "Or change the repo ownership with --createrepo-user"
  879. return 1
  880. fi
  881. fi
  882. fi
  883. # Copy built rpms to webroot
  884. if ! ( execute sudo cp -nf "$MCRPM" "$CREATEREPO_WEBROOT" &&
  885. execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT" ); then
  886. err "Could not copy $MCRPM to $CREATEREPO_WEBROOT"
  887. return 1
  888. fi
  889. # Run createrepo
  890. cr_cmd=(sudo -u "$CREATEREPO_USER" createrepo -q "$CREATEREPO_WEBROOT")
  891. [[ -d $CREATEREPO_WEBROOT/repodata ]] && cr_cmd+=(--update)
  892. if ! execute "${cr_cmd[@]}"; then
  893. cr_cmd=(sudo createrepo -q "$CREATEREPO_WEBROOT")
  894. [[ -d $CREATEREPO_WEBROOT/repodata ]] && cr_cmd+=(--update)
  895. if ! (execute "${cr_cmd[@]}" &&
  896. execute sudo chown -R "$CREATEREPO_USER:$CREATEREPO_USER" "$CREATEREPO_WEBROOT"); then
  897. err "createrepo failed"
  898. return 1
  899. fi
  900. fi
  901. }
  902. #######################################
  903. # Symlink certificates if they do not exist in default location
  904. #######################################
  905. symlinkCerts() {
  906. debug "Running: ${FUNCNAME[0]}"
  907. declare mc_cert_link="/usr/lib/jriver/MC$MVERSION/ca-certificates.crt"
  908. declare target_cert f
  909. declare -a source_certs=(
  910. "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem"
  911. "/var/lib/ca-certificates/ca-bundle.pem")
  912. target_cert=$(readlink -f "$mc_cert_link")
  913. [[ -f $target_cert ]] && return 0
  914. for f in "${source_certs[@]}"; do
  915. if [[ -f $f ]]; then
  916. if ! execute ln -fs "$f" "$mc_cert_link"; then
  917. err "Symlinking certificate failed"
  918. return 1
  919. fi
  920. break
  921. fi
  922. done
  923. }
  924. #######################################
  925. # Restore the mjr license file from RESTOREFILE or other common locations
  926. #######################################
  927. restoreLicense() {
  928. debug "Running: ${FUNCNAME[0]}"
  929. declare f newest
  930. # Glob mjr files from common directories
  931. shopt -s nullglob
  932. declare -a mjrfiles=(
  933. "$SCRIPTDIR"/*.mjr
  934. "$OUTPUTDIR"/*.mjr
  935. "$HOME"/[dD]ownloads/*.mjr
  936. "$HOME"/[dD]ocuments/*.mjr
  937. )
  938. shopt -u nullglob
  939. if [[ ${#mjrfiles[@]} -gt 0 ]]; then
  940. debug "mjrfiles=(${mjrfiles[*]})"
  941. # Sort globbed files by time, newest first
  942. newest=${mjrfiles[0]}
  943. for f in "${mjrfiles[@]}"; do
  944. if [[ -f $f && $f -nt $newest ]]; then
  945. newest=$f
  946. fi
  947. done
  948. debug "Latest mjrfile: $newest"
  949. for f in "$RESTOREFILE" "$newest"; do
  950. if [[ -f $f ]]; then
  951. if execute "mediacenter$MVERSION" "/RestoreFromFile" "$f"; then
  952. return 0
  953. fi
  954. fi
  955. done
  956. fi
  957. }
  958. #######################################
  959. # Opens ports using the system firewall tool
  960. # Arguments:
  961. # 1. Service name
  962. # 2. List of ports in firewall-cmd format
  963. #######################################
  964. openFirewall() {
  965. debug "Running: ${FUNCNAME[0]}" "$@"
  966. declare port
  967. declare service="$1"
  968. shift
  969. declare -a f_ports=("$@") # for firewall-cmd
  970. declare u_ports="$*"
  971. declare u_ports="${u_ports// /|}" # concatenate
  972. u_ports="${u_ports//-/\:}" # for ufw
  973. if hash firewall-cmd &>/dev/null; then
  974. if ! sudo firewall-cmd --get-services | grep -q "$service"; then
  975. execute sudo firewall-cmd --permanent "--new-service=$service"
  976. execute sudo firewall-cmd --permanent "--service=$service" "--set-description=$service" installed by installJRMC
  977. execute sudo firewall-cmd --permanent "--service=$service" "--set-short=$service"
  978. for port in "${f_ports[@]}"; do
  979. execute sudo firewall-cmd --permanent "--service=$service" "--add-port=$port"
  980. done
  981. execute sudo firewall-cmd --add-service "$service" --permanent
  982. execute sudo firewall-cmd --reload
  983. fi
  984. elif hash ufw &>/dev/null; then
  985. sudo bash -c "cat <<-EOF > /etc/ufw/applications.d/$service
  986. [$service]
  987. title=$service
  988. description=$service installed by installJRMC
  989. ports=$u_ports
  990. EOF"
  991. execute sudo ufw app update "$service"
  992. execute sudo ufw allow "$service"
  993. else
  994. echo "Warning: Install firewall-cmd or ufw to open firewall ports"
  995. return 1
  996. fi
  997. }
  998. #######################################
  999. # Create the xvnc or x11vnc password file
  1000. # Arguments:
  1001. # Service type (xvnc, x11vnc)
  1002. #######################################
  1003. setVNCPass() {
  1004. debug "Running: ${FUNCNAME[0]}"
  1005. declare vncpassfile="$HOME/.vnc/jrmc_passwd"
  1006. [[ -d ${vncpassfile%/*} ]] || execute mkdir -p "${vncpassfile%/*}"
  1007. if [[ -f $vncpassfile ]]; then
  1008. if [[ ! -v VNCPASS ]]; then
  1009. err "Refusing to overwrite existing $vncpassfile with an empty password"
  1010. err "Remove existing $vncpassfile or use --vncpass ''"
  1011. return 1
  1012. else
  1013. execute rm -f "$vncpassfile"
  1014. fi
  1015. fi
  1016. if [[ -v VNCPASS ]]; then
  1017. if [[ $1 == "xvnc" ]]; then
  1018. echo "$VNCPASS" | vncpasswd -f > "$vncpassfile"
  1019. elif [[ $1 == "x11vnc" ]]; then
  1020. execute x11vnc -storepasswd "$VNCPASS" "$vncpassfile"
  1021. fi
  1022. return $?
  1023. else
  1024. declare -g NOVNCAUTH=1
  1025. fi
  1026. }
  1027. #######################################
  1028. # Set display and port variables
  1029. #######################################
  1030. setDisplayVars() {
  1031. debug "Running: ${FUNCNAME[0]}"
  1032. declare -g DISPLAY DISPLAYNUM NEXT_DISPLAY
  1033. # Check USER_DISPLAY, else environment DISPLAY, else set to :0
  1034. DISPLAY="${USER_DISPLAY:-${DISPLAY:-:0}}"
  1035. DISPLAYNUM="${DISPLAY#*:}" # strip prefix
  1036. DISPLAYNUM="${DISPLAYNUM%%.*}" # strip suffix
  1037. # Increment each time we run this
  1038. if (( NEXT_DISPLAYNUM )); then
  1039. declare -g NEXT_DISPLAYNUM=$(( NEXT_DISPLAYNUM + 1 ))
  1040. else
  1041. declare -g NEXT_DISPLAYNUM=$(( DISPLAYNUM + 1 ))
  1042. fi
  1043. declare -g NEXT_DISPLAY=":$NEXT_DISPLAYNUM"
  1044. }
  1045. #######################################
  1046. # Create associated service variables based on service name
  1047. # Arguments
  1048. # Pre-defined service name
  1049. #######################################
  1050. setServiceVars() {
  1051. debug "Running: ${FUNCNAME[0]}" "$*"
  1052. declare -g SERVICE_NAME SERVICE_FNAME TIMER_NAME TIMER_FNAME
  1053. declare -g USER_STRING DISPLAY_STRING GRAPHICAL_TARGET
  1054. declare -ga RELOAD ENABLE DISABLE IS_ENABLED IS_ACTIVE
  1055. declare -a systemctl_prefix
  1056. declare service_name="$1"
  1057. declare service_type="${2:-${SERVICE_TYPE:-system}}"
  1058. declare service_dir="/usr/lib/systemd/$service_type"
  1059. if [[ $USER == "root" && $service_type == "user" ]]; then
  1060. err "Trying to install user service as root"
  1061. err "Use --service-type service and/or execute installJRMC as non-root user"
  1062. return 1
  1063. fi
  1064. if [[ $service_type == "system" ]]; then
  1065. systemctl_prefix=(sudo systemctl)
  1066. GRAPHICAL_TARGET="graphical.target"
  1067. elif [[ $service_type == "user" ]]; then
  1068. systemctl_prefix=(systemctl --user)
  1069. GRAPHICAL_TARGET="default.target"
  1070. fi
  1071. # systemctl commands
  1072. RELOAD=(execute "${systemctl_prefix[@]}" daemon-reload)
  1073. ENABLE=(execute "${systemctl_prefix[@]}" enable --now)
  1074. DISABLE=(execute "${systemctl_prefix[@]}" disable --now)
  1075. IS_ENABLED=(execute "${systemctl_prefix[@]}" is-enabled -q)
  1076. IS_ACTIVE=(execute "${systemctl_prefix[@]}" is-active -q)
  1077. [[ -d $service_dir ]] || execute sudo mkdir -p "$service_dir"
  1078. # TODO Ubuntu needs these in the service file, fedora (and others?) do not
  1079. case $ID in
  1080. ubuntu|debian)
  1081. DISPLAY_STRING="Environment=DISPLAY=$DISPLAY"
  1082. DISPLAY_STRING+=$'\n'"Environment=XAUTHORITY=$XAUTHORITY"
  1083. ;;
  1084. *)
  1085. DISPLAY_STRING=""
  1086. ;;
  1087. esac
  1088. if [[ $SERVICE_TYPE == "system" && $USER != "root" ]]; then
  1089. SERVICE_FNAME="$service_dir/$service_name@.service"
  1090. TIMER_FNAME="$service_dir/$service_name@.timer"
  1091. SERVICE_NAME="$service_name@$USER.service"
  1092. TIMER_NAME="$service_name@$USER.timer"
  1093. USER_STRING="User=%I"
  1094. else
  1095. SERVICE_NAME="$service_name.service"
  1096. TIMER_NAME="$service_name.timer"
  1097. SERVICE_FNAME="$service_dir/$SERVICE_NAME"
  1098. TIMER_FNAME="$service_dir/${TIMER_NAME}"
  1099. USER_STRING=""
  1100. fi
  1101. }
  1102. #######################################
  1103. # Starts and enables (at startup) a JRiver Media Center service
  1104. # Arguments:
  1105. # Passes arguments as startup options to /usr/bin/mediacenter??
  1106. #######################################
  1107. service_jriver-mediacenter() {
  1108. debug "Running: ${FUNCNAME[0]}"
  1109. setServiceVars "${FUNCNAME[0]##*_}" "user"
  1110. sudo bash -c "cat <<-EOF > $SERVICE_FNAME
  1111. [Unit]
  1112. Description=JRiver Media Center $MVERSION
  1113. After=$GRAPHICAL_TARGET
  1114. [Service]
  1115. $USER_STRING
  1116. $DISPLAY_STRING
  1117. Type=simple
  1118. Environment=DISPLAY=$DISPLAY
  1119. Environment=XAUTHORITY=$XAUTHORITY
  1120. ExecStart=/usr/bin/mediacenter$MVERSION $*
  1121. Restart=always
  1122. RestartSec=10
  1123. KillSignal=SIGHUP
  1124. TimeoutStopSec=30
  1125. [Install]
  1126. WantedBy=$GRAPHICAL_TARGET
  1127. EOF"
  1128. openFirewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
  1129. "${RELOAD[@]}" &&
  1130. "${ENABLE[@]}" "$SERVICE_NAME"
  1131. }
  1132. #######################################
  1133. # Starts and enables (at startup) a JRiver Media Server service
  1134. #######################################
  1135. service_jriver-mediaserver() {
  1136. debug "Running: ${FUNCNAME[0]}"
  1137. setServiceVars "${FUNCNAME[0]##*_}" "user"
  1138. service_jriver-mediacenter "/MediaServer"
  1139. }
  1140. #######################################
  1141. # Starts and enables (at startup) JRiver Media Center in a new Xvnc session
  1142. # TODO https://github.com/TigerVNC/tigervnc/blob/master/unix/vncserver/HOWTO.md
  1143. #######################################
  1144. service_jriver-xvnc() {
  1145. debug "Running: ${FUNCNAME[0]}"
  1146. setServiceVars "${FUNCNAME[0]##*_}" "system"
  1147. setDisplayVars
  1148. declare -a start_cmd
  1149. declare -g PORT=$(( NEXT_DISPLAYNUM + 5900 ))
  1150. installPackage tigervnc-server
  1151. setVNCPass xvnc
  1152. start_cmd=(
  1153. /usr/bin/vncserver "$NEXT_DISPLAY"
  1154. -geometry 1440x900
  1155. -alwaysshared
  1156. -autokill
  1157. -xstartup "/usr/bin/mediacenter$MVERSION"
  1158. )
  1159. if (( NOVNCAUTH )); then
  1160. start_cmd+=(
  1161. -name "jriver$NEXT_DISPLAY"
  1162. -SecurityTypes None
  1163. )
  1164. else
  1165. start_cmd+=(
  1166. -rfbauth "$HOME/.vnc/jrmc_passwd"
  1167. )
  1168. fi
  1169. sudo bash -c "cat <<-EOF > $SERVICE_FNAME
  1170. [Unit]
  1171. Description=Remote desktop service (VNC)
  1172. After=multi-user.target
  1173. [Service]
  1174. Type=forking
  1175. $USER_STRING
  1176. ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill $NEXT_DISPLAY &>/dev/null || :'
  1177. ExecStart=${start_cmd[*]}
  1178. ExecStop=/usr/bin/vncserver -kill $NEXT_DISPLAY
  1179. Restart=always
  1180. [Install]
  1181. WantedBy=multi-user.target
  1182. EOF"
  1183. "${RELOAD[@]}"
  1184. if ! "${ENABLE[@]}" "$SERVICE_NAME"; then
  1185. err "vncserver failed to start on DISPLAY $NEXT_DISPLAY"
  1186. err "Incrementing DISPLAY and retrying"
  1187. service_jriver-xvnc
  1188. return
  1189. else
  1190. echo "Xvnc running on localhost:$PORT"
  1191. openFirewall "jriver-xvnc" "$PORT/tcp"
  1192. openFirewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
  1193. fi
  1194. return 0
  1195. }
  1196. #######################################
  1197. # Starts and enables (at startup) x11vnc screen sharing for the local desktop
  1198. #######################################
  1199. service_jriver-x11vnc() {
  1200. debug "Running: ${FUNCNAME[0]}"
  1201. setServiceVars "${FUNCNAME[0]##*_}" "user"
  1202. setDisplayVars
  1203. declare -a start_cmd
  1204. declare -g PORT=$(( DISPLAYNUM + 5900 ))
  1205. installPackage x11vnc
  1206. setVNCPass x11vnc
  1207. # If .Xauthority file is missing, generate a dummy for x11vnc -auth guess
  1208. if [[ ! -f $HOME/.Xauthority ]]; then
  1209. [[ $XDG_SESSION_TYPE == "wayland" ]] &&
  1210. askOk "Unsupported Wayland session detected for x11vnc, continue?" || return 1
  1211. touch "$HOME/.Xauthority"
  1212. xauth generate "$DISPLAY" . trusted
  1213. xauth add "$HOST$DISPLAY" . "$(xxd -l 16 -p /dev/urandom)"
  1214. fi
  1215. start_cmd=(
  1216. /usr/bin/x11vnc
  1217. -display "$DISPLAY"
  1218. -noscr
  1219. -auth guess
  1220. -forever
  1221. -bg
  1222. )
  1223. if (( NOVNCAUTH )); then
  1224. start_cmd+=(-nopw)
  1225. else
  1226. start_cmd+=(-rfbauth "$HOME/.vnc/jrmc_passwd")
  1227. fi
  1228. sudo bash -c "cat <<-EOF > $SERVICE_FNAME
  1229. [Unit]
  1230. Description=x11vnc
  1231. After=$GRAPHICAL_TARGET
  1232. [Service]
  1233. $USER_STRING
  1234. Type=forking
  1235. Environment=DISPLAY=$DISPLAY
  1236. ExecStart=${start_cmd[*]}
  1237. Restart=always
  1238. RestartSec=10
  1239. [Install]
  1240. WantedBy=$GRAPHICAL_TARGET
  1241. EOF"
  1242. openFirewall "jriver-x11vnc" "$PORT/tcp"
  1243. "${RELOAD[@]}" &&
  1244. "${ENABLE[@]}" "$SERVICE_NAME" &&
  1245. echo "x11vnc running on localhost:$PORT"
  1246. }
  1247. #######################################
  1248. # Starts and enables (at startup) an hourly service to build the latest version of
  1249. # JRiver Media Center RPM from the source DEB and create/update an RPM repository
  1250. #######################################
  1251. service_jriver-createrepo() {
  1252. debug "Running: ${FUNCNAME[0]}"
  1253. if [[ $CREATEREPO_USER != "$USER" ]]; then
  1254. USER="root" setServiceVars "${FUNCNAME[0]##*_}" "system"
  1255. else
  1256. setServiceVars "${FUNCNAME[0]##*_}" "system"
  1257. fi
  1258. sudo bash -c "cat <<-EOF > $SERVICE_FNAME
  1259. [Unit]
  1260. Description=Builds JRiver Media Center RPM, moves it to the repo dir, and runs createrepo
  1261. [Service]
  1262. $USER_STRING
  1263. ExecStart=$SCRIPTDIR/installJRMC --outputdir $OUTPUTDIR --createrepo=$REPO_TARGET --createrepo-webroot $CREATEREPO_WEBROOT --createrepo-user $CREATEREPO_USER
  1264. [Install]
  1265. WantedBy=multi-user.target
  1266. EOF"
  1267. sudo bash -c "cat <<-EOF > $TIMER_FNAME
  1268. [Unit]
  1269. Description=Run JRiver MC rpmbuild hourly
  1270. [Timer]
  1271. OnCalendar=hourly
  1272. Persistent=true
  1273. [Install]
  1274. WantedBy=timers.target
  1275. EOF"
  1276. "${RELOAD[@]}" &&
  1277. "${ENABLE[@]}" "$TIMER_NAME"
  1278. }
  1279. #######################################
  1280. # CONTAINERS
  1281. #######################################
  1282. # container_jriver-createrepo() {
  1283. # :
  1284. # }
  1285. # container_jriver-xvnc() {
  1286. # :
  1287. # }
  1288. # container_jriver-mediacenter() {
  1289. # installPackage buildah podman
  1290. # if ! CNT=$(buildah from debian:$DEBIANBASE-slim); then
  1291. # echo "Bad base image for container, skipping"
  1292. # return 1
  1293. # fi
  1294. # brc() { buildah run "$CNT" bash -c "$*"; }
  1295. # brc "add-pkg gnupg2 libxss1 wmctrl xdotool ca-certificates inotify-tools libgbm1 ffmpeg"
  1296. # # Install JRiver
  1297. # brc "
  1298. # add-pkg ca-certificates gnupg &&
  1299. # add-pkg --virtual build-dependencies wget &&
  1300. # wget -qO- http://dist.jriver.com/mediacenter@jriver.com.gpg.key | tee /etc/apt/trusted.gpg.d/jriver.asc &&
  1301. # wget -O /etc/apt/sources.list.d/mediacenter${MVERSION}.list http://dist.jriver.com/latest/mediacenter/mediacenter${MVERSION}.list &&
  1302. # apt update &&
  1303. # add-pkg mediacenter${MVERSION} &&
  1304. # del-pkg build-dependencies
  1305. # "
  1306. # buildah config "$CNT" \
  1307. # --author "bryanroessler@gmail.com" \
  1308. # --label maintainer="$MAINTAINER" \
  1309. # --env TZ="$TZ" \
  1310. # --workingdir /app \
  1311. # --cmd "mediacenter$MVERSION"
  1312. # # EXPOSE 5800 5900 52100 52101 52199 1900/udp
  1313. # podman_create_cmd=(
  1314. # podman create
  1315. # --name "mediacenter$MVERSION"
  1316. # )
  1317. # podman_create_cmd+=(-v "$HOME/.jriver:/root/.jriver")
  1318. # podman_create_cmd+=(-v "$DOWNLOAD_ROOT:/downloads:z")
  1319. # podman_create_cmd+=(-v "$MONITOR_ROOT/nzbs:/nzbs")
  1320. # podman_create_cmd+=(-p "${CONTAINER[HOST_PORT]}:${CONTAINER[CONTAINER_PORT]}")
  1321. # # mkcdirs() {
  1322. # # declare dir
  1323. # # for dir in "$@"; do
  1324. # # if [[ ! -d "$dir" ]]; then
  1325. # # if ! mkdir -p "$dir"; then
  1326. # # err "Could not create directory $dir, check your permissions"
  1327. # # fi
  1328. # # fi
  1329. # # if ! chcon -t container_file_t -R "$dir"; then
  1330. # # err "Could not set container_file_t attribute for $dir, check your permissions"
  1331. # # fi
  1332. # # done
  1333. # # }
  1334. # # mkcdirs "$HOME/.jriver"
  1335. # brc sh -s <<-EOF
  1336. # wget -q "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" -O- | apt-key add - &>/dev/null
  1337. # EOF
  1338. # brc wget "http://dist.jriver.com/latest/mediacenter/mediacenter$MVERSION.list" -O "/etc/apt/sources.list.d/mediacenter$MVERSION.list"
  1339. # brc apt update -y -q0
  1340. # brc add-pkg "mediacenter$MVERSION"
  1341. # brc del-pkg .build-deps
  1342. # }
  1343. #######################################
  1344. # Detects if MC is installed on btrfs and disables CoW
  1345. #######################################
  1346. disableCoW() {
  1347. debug "Running: ${FUNCNAME[0]}"
  1348. declare dir
  1349. declare mc_system_path="/usr/lib/jriver"
  1350. declare mc_user_path="$HOME/.jriver"
  1351. for dir in "$mc_system_path" "$mc_user_path"; do
  1352. [[ -d $dir ]] || execute mkdir -p "$dir"
  1353. if [[ $(stat -f -c %T "$dir") == "btrfs" ]] &&
  1354. ! lsattr -d "$dir" | cut -f1 -d" " | grep -q C &&
  1355. execute sudo chattr +C "$dir"; then
  1356. echo "Disabled btrfs CoW for $dir directory"
  1357. fi
  1358. done
  1359. }
  1360. #######################################
  1361. # Migrate major versions
  1362. #######################################
  1363. migrateLibrary() {
  1364. debug "Running: ${FUNCNAME[0]}"
  1365. declare mc_user_path="$HOME/.jriver"
  1366. declare current_config_path="$mc_user_path/Media Center $MVERSION"
  1367. declare previous_config_path="$mc_user_path/Media Center $(( MVERSION - 1 ))"
  1368. if [[ ! -d $current_config_path ]] &&
  1369. [[ -d $previous_config_path ]] &&
  1370. mkdir -p "$current_config_path"; then
  1371. echo "Migrating $previous_config_path to $current_config_path"
  1372. cp -fa "$previous_config_path"/* "$current_config_path"
  1373. fi
  1374. }
  1375. #######################################
  1376. # Completely uninstalls MC, services, and firewall rules
  1377. #######################################
  1378. uninstall() {
  1379. debug "Running: ${FUNCNAME[0]}"
  1380. declare service unit f i
  1381. echo "Stopping and removing all Media Center services"
  1382. for service in $(compgen -A "function" "service"); do
  1383. service="${service##service_}"
  1384. for i in user system; do
  1385. setServiceVars "$service" "$i";
  1386. for unit in "$SERVICE_NAME" "$TIMER_NAME"; do
  1387. if "${IS_ACTIVE[@]}" "$unit" ||
  1388. "${IS_ENABLED[@]}" "$unit"; then
  1389. "${DISABLE[@]}" "$unit"
  1390. fi
  1391. done
  1392. for f in "$SERVICE_FNAME" "$TIMER_FNAME"; do
  1393. [[ -f $f ]] &&
  1394. execute sudo rm -f "$f"
  1395. done
  1396. "${RELOAD[@]}"
  1397. unset f
  1398. done
  1399. for f in /etc/systemd/system/jriver-*; do
  1400. execute sudo rm -f "$f"
  1401. done
  1402. unset f
  1403. done
  1404. echo "Removing repo files"
  1405. sudo rm -rf \
  1406. "/etc/yum.repos.d/jriver.repo" \
  1407. /etc/apt/sources.list.d/{jriver,mediacenter}*.list # also remove legacy repo files
  1408. if [[ $ID == "suse" ]]; then
  1409. execute sudo zypper --non-interactive removerepo jriver
  1410. fi
  1411. echo "Removing firewall rules"
  1412. if hash firewall-cmd &>/dev/null; then
  1413. execute sudo firewall-cmd --permanent --remove-service=jriver
  1414. execute sudo firewall-cmd --permanent --delete-service=jriver
  1415. execute sudo firewall-cmd --reload
  1416. elif hash ufw &>/dev/null; then
  1417. execute sudo ufw delete allow jriver
  1418. [[ -f "/etc/ufw/applications.d/jriver" ]] &&
  1419. execute sudo rm -f /etc/ufw/applications.d/jriver
  1420. fi
  1421. echo "Uninstalling JRiver Media Center package"
  1422. if "${PKG_REMOVE[@]}" "$MCPKG"; then
  1423. echo "JRiver Media Center has been completely uninstalled"
  1424. echo "To remove your MC library: rm -rf $HOME/.jriver"
  1425. elif [[ $? -eq 100 ]]; then
  1426. err "JRiver Media Center package '$MCPKG' is not present and was not uninstalled"
  1427. else
  1428. err "Could not remove Media Center package"
  1429. fi
  1430. if [[ -f $SCRIPTDIR/.uninstall ]]; then
  1431. echo "Removing files from .uninstall log"
  1432. while read -r p; do
  1433. [[ -d $p ]] && execute sudo rm -rf "$p"
  1434. done < "$SCRIPTDIR/.uninstall"
  1435. mv "$SCRIPTDIR/.uninstall" "$SCRIPTDIR/.uninstall.bk"
  1436. fi
  1437. }
  1438. tests() {
  1439. # To test on Mint/16.04: sudo apt install -y spice-vdagent ca-certificates git; export GIT_SSL_NO_VERIFY=1
  1440. : # TODO
  1441. }
  1442. main() {
  1443. debug "Running: ${FUNCNAME[0]} $*"
  1444. init
  1445. parseInput "$@"
  1446. debug "Debugging on"
  1447. debug "installJRMC version: $SCRIPTVERSION"
  1448. if ((TEST_SWITCH)); then
  1449. echo "Running tests, all other options are skipped"
  1450. tests
  1451. exit
  1452. fi
  1453. setMCVersion
  1454. if (( UNINSTALL_SWITCH )); then
  1455. if askOk "Do you really want to uninstall JRiver Media Center?"; then
  1456. uninstall
  1457. else
  1458. echo "Uninstall canceled"
  1459. fi
  1460. exit
  1461. fi
  1462. # Install external repos
  1463. case $ID in
  1464. ubuntu)
  1465. if ! grep ^deb /etc/apt/sources.list|grep -q universe; then
  1466. echo "Adding universe repository"
  1467. if ! execute sudo add-apt-repository -y universe; then
  1468. err "Adding universe repository failed"
  1469. fi
  1470. fi
  1471. ;;
  1472. centos)
  1473. if ! hash dpkg &>/dev/null; then
  1474. echo "Adding EPEL repository"
  1475. installPackage epel-release
  1476. fi
  1477. if ! "${PKG_QUERY[@]}" rpmfusion-free-release &>/dev/null; then
  1478. installPackage --no-install-check \
  1479. "https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
  1480. fi
  1481. ;;
  1482. fedora)
  1483. if ! "${PKG_QUERY[@]}" rpmfusion-free-release &>/dev/null; then
  1484. installPackage --no-install-check \
  1485. "https://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$VERSION_ID.noarch.rpm"
  1486. fi
  1487. ;;
  1488. esac
  1489. if (( REPO_INSTALL_SWITCH )); then
  1490. echo "Installing JRiver Media Center from remote repository"
  1491. if installMCFromRepo; then
  1492. echo "JRiver Media Center installed successfully from repo"
  1493. symlinkCerts
  1494. migrateLibrary
  1495. restoreLicense
  1496. openFirewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
  1497. disableCoW
  1498. else
  1499. err "JRiver Media Center installation from repo failed"
  1500. return 1
  1501. fi
  1502. fi
  1503. if (( BUILD_SWITCH )) && [[ $ID != "arch" ]]; then
  1504. installPackage "wget"
  1505. [[ -d $OUTPUTDIR/SOURCES ]] || execute mkdir -p "$OUTPUTDIR/SOURCES"
  1506. acquireDeb
  1507. if [[ $BUILD_TARGET =~ (centos|fedora|suse) ]]; then
  1508. installPackage "dpkg" "rpm-build"
  1509. [[ -d $OUTPUTDIR/SPECS ]] || mkdir -p "$OUTPUTDIR/SPECS"
  1510. buildRPM
  1511. fi
  1512. fi
  1513. if (( LOCAL_INSTALL_SWITCH )); then
  1514. if PKG_INSTALL_LOCAL; then
  1515. echo "JRiver Media Center installed successfully from local package"
  1516. else
  1517. err "JRiver Media Center local package installation failed"
  1518. return 1
  1519. fi
  1520. symlinkCerts
  1521. migrateLibrary
  1522. restoreLicense
  1523. openFirewall "jriver-mediacenter" "52100-52200/tcp" "1900/udp"
  1524. disableCoW
  1525. fi
  1526. if (( CREATEREPO_SWITCH )); then
  1527. if runCreaterepo; then
  1528. echo "Successfully updated repo"
  1529. else
  1530. err "Repo creation failed"
  1531. fi
  1532. fi
  1533. if [[ ${#SERVICES[@]} -gt 0 ]]; then
  1534. declare service
  1535. for service in "${SERVICES[@]}"; do
  1536. if ! "service_$service"; then
  1537. if [[ $? -eq 127 ]]; then
  1538. err "Service $service does not exist, check service name"
  1539. else
  1540. err "Failed to create $service service"
  1541. fi
  1542. else
  1543. echo "Started and enabled $service service"
  1544. fi
  1545. done
  1546. unset service
  1547. fi
  1548. # for _container in "${CONTAINERS[@]}"; do
  1549. # if ! "_container_$_container"; then
  1550. # if [[ $? -eq 127 ]]; then
  1551. # err "Container $_container does not exist, check container name"
  1552. # else
  1553. # err "Failed to create container: $_container"
  1554. # fi
  1555. # fi
  1556. # done
  1557. }
  1558. # Roughly turn debugging on, reparse in getInput() with getopt
  1559. [[ " $* " =~ ( --debug | -d ) ]] && declare -g DEBUG=1
  1560. main "$@"