debian-config-jobs 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758
  1. #!/bin/bash
  2. #
  3. #
  4. # Copyright (c) 2017 Igor Pecovnik, igor.pecovnik@gma**.com
  5. #
  6. # This file is licensed under the terms of the GNU General Public
  7. # License version 2. This program is licensed "as is" without any
  8. # warranty of any kind, whether express or implied.
  9. [[ -n ${SUDO_USER} ]] && SUDO="sudo "
  10. function jobs ()
  11. {
  12. # Shows box with loading ...
  13. #
  14. dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nLoading ${selection,,} submodule ... " 5 $((26+${#selection}))
  15. unset selection
  16. case $1 in
  17. #-------------------------------------------------------------------------------------------------------------------------------------#
  18. # Application installer
  19. #
  20. "Softy" )
  21. [[ -f softy ]] && ./softy || softy
  22. ;;
  23. # Remove BT
  24. #
  25. "BT remove" )
  26. if ! is_package_manager_running; then
  27. debconf-apt-progress -- apt-get -y remove bluetooth bluez bluez-tools
  28. check_if_installed xserver-xorg && debconf-apt-progress -- apt-get -y remove pulseaudio-module-bluetooth blueman
  29. debconf-apt-progress -- apt -y -qq autoremove
  30. fi
  31. ;;
  32. # Enabling BT
  33. #
  34. "BT install" )
  35. if ! is_package_manager_running; then
  36. debconf-apt-progress -- apt-get -y install bluetooth bluez bluez-tools
  37. check_if_installed xserver-xorg && debconf-apt-progress -- apt-get -y --no-install-recommends install pulseaudio-module-bluetooth blueman
  38. fi
  39. ;;
  40. # Removing IR
  41. #
  42. "Remove IR" )
  43. if ! is_package_manager_running; then
  44. debconf-apt-progress -- apt-get -y remove lirc
  45. debconf-apt-progress -- apt -y -qq autoremove
  46. fi
  47. ;;
  48. # Enabling IR
  49. #
  50. "IR" )
  51. if ! is_package_manager_running; then
  52. debconf-apt-progress -- apt-get -y --no-install-recommends install lirc
  53. fi
  54. ;;
  55. # Sharing USB ports
  56. #
  57. "USB redirector" )
  58. if [[ -n $(netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".'32032'"') ]]; then
  59. [[ -f /usr/local/usb-redirector/uninstall.sh ]] && /usr/local/usb-redirector/uninstall.sh uninstall
  60. rm -f /usr/local/bin/usbclnt
  61. else
  62. TARGET_BRANCH=$BRANCH
  63. exceptions "$BRANCH"
  64. IFS='.' read -a array <<< $(uname -r)
  65. [[ -z $(dpkg -l | grep linux-headers) ]] && debconf-apt-progress -- apt-get -y \
  66. install linux-headers${TARGET_BRANCH}-${TARGET_FAMILY}
  67. if (( "${array[0]}" == "4" )) && (( "${array[1]}" >= "1" )); then
  68. rm -rf /usr/src/usb-redirector-linux-arm-gnueabi
  69. wget -qO- https://www.incentivespro.com/usb-redirector-linux-arm-gnueabi.tar.gz | tar xz -C /usr/src
  70. cd /usr/src/usb-redirector-linux-arm-gnueabi/
  71. else
  72. rm -rf /usr/src/usb-redirector-linux-arm-eabi
  73. wget -qO- https://raw.githubusercontent.com/armbian/build/master/packages/blobs/usb-redirector/usb-redirector-old.tgz \
  74. | tar xz -C /usr/src
  75. cd /usr/src/usb-redirector-linux-arm-eabi/
  76. fi
  77. ./installer.sh install
  78. sleep 3
  79. check_port "32032" "USB Redirector"
  80. fi
  81. ;;
  82. # Simple CLI monitoring
  83. #
  84. "Monitor" )
  85. clear
  86. orangepimonitor -m
  87. sleep 2
  88. ;;
  89. # SBC-becn
  90. #
  91. "Benchmarking" )
  92. if [[ ! -f /usr/local/bin/sbc-bench ]]; then
  93. wget -q -O /usr/local/bin/sbc-bench https://gitee.com/leeboby/sbc-bench/raw/master/sbc-bench.sh
  94. if [[ -z "$(command -v git)" ]]; then
  95. sudo apt-get update
  96. sudo apt-get install -y git
  97. fi
  98. chmod +x /usr/local/bin/sbc-bench
  99. fi
  100. sbc-bench
  101. echo ""
  102. read -n 1 -s -p "Press any key to continue"
  103. ;;
  104. # Send diagnostics
  105. #
  106. "Diagnostics" )
  107. clear
  108. orangepimonitor -u
  109. echo ""
  110. read -n 1 -s -p "Press any key to continue"
  111. ;;
  112. # Control board consumption
  113. #
  114. "Consumption" )
  115. clear
  116. h3consumption
  117. echo -e "\nType \e[92m${SUDO}${0##*/}\e[0m to get back\n"
  118. exit
  119. ;;
  120. # Board (fex) settings editor
  121. #
  122. "Fexedit" )
  123. exec 3>&1
  124. monitor=$(dialog --print-maxsize 2>&1 1>&3)
  125. exec 3>&-
  126. mon_x=$(echo $monitor | awk '{print $2}' | sed 's/,//')
  127. mon_y=$(echo $monitor | awk '{print $3}' | sed 's/,//')
  128. TEMP=$(mktemp -d || exit 1)
  129. trap "rm -rf \"${TEMP}\" ; exit 0" 0 1 2 3 15
  130. bin2fex /boot/script.bin ${TEMP}/tempfex.txt >/dev/null 2>&1
  131. dialog --title "Edit u-boot environment" \
  132. --ok-label "Save" --no-collapse --editbox ${TEMP}/tempfex.txt $mon_y 0 2> ${TEMP}/tempfex.out
  133. [[ $? = 0 ]] && fex2bin ${TEMP}/tempfex.out /boot/script.bin
  134. ;;
  135. #
  136. # Install kernel headers
  137. #
  138. "Headers_install" )
  139. if ! is_package_manager_running; then
  140. if [[ -f /etc/orangepi-release ]]; then
  141. INSTALL_PKG="linux-headers-${BRANCH}-${LINUXFAMILY}";
  142. else
  143. INSTALL_PKG="linux-headers-$(uname -r | sed 's/'-$(dpkg --print-architecture)'//')";
  144. fi
  145. debconf-apt-progress -- apt-get -y install ${INSTALL_PKG}
  146. fi
  147. ;;
  148. #
  149. # Remove kernel headers
  150. #
  151. "Headers_remove" )
  152. if ! is_package_manager_running; then
  153. REMOVE_PKG="linux-headers-*"
  154. if [[ -n $(dpkg -l | grep linux-headers) ]]; then
  155. debconf-apt-progress -- apt-get -y purge ${REMOVE_PKG}
  156. rm -rf /usr/src/linux-headers*
  157. else
  158. debconf-apt-progress -- apt-get -y install ${INSTALL_PKG}
  159. fi
  160. # cleanup
  161. apt clean
  162. debconf-apt-progress -- apt -y autoremove
  163. fi
  164. ;;
  165. #
  166. # Install kernel source
  167. #
  168. "Source_install" )
  169. if ! is_package_manager_running; then
  170. if [[ -z $scripted ]]; then
  171. LIST=()
  172. for pkg in $SOURCE_PKG_LIST
  173. do
  174. LIST+=( "$pkg" "" )
  175. done
  176. exec 3>&1
  177. selection=$(dialog --backtitle "$BACKTITLE" --title "Kernel install" --clear --cancel-label "Back" \
  178. --menu "Choose kernel version" 12 70 ${#LIST[@]} "${LIST[@]}" 2>&1 1>&3)
  179. exit_status=$?
  180. exec 3>&-
  181. [[ $exit_status == 1 || $exit_status == 255 ]] && clear
  182. else
  183. selection=$(echo $SOURCE_PKG_LIST | awk '{ print $NF }')
  184. fi
  185. PACKAGE=$(echo "$selection" | sed "s/-current//" | sed "s/-dev//" | sed "s/-legacy//")
  186. if [[ -n $PACKAGE ]]; then
  187. debconf-apt-progress -- apt-get -y install ${selection}
  188. mkdir -p /usr/src/$PACKAGE
  189. (pv -n /usr/src/$PACKAGE".tar.xz" | xz -d -T0 - | tar xf - -C /usr/src/$PACKAGE ) 2>&1 | dialog --colors --backtitle "$BACKTITLE" --title " Please wait! " --gauge "\nDecompressing kernel sources to /usr/src/$PACKAGE" 8 80
  190. xz -d /usr/src/*config.xz --stdout > /usr/src/$PACKAGE/.config
  191. rm /usr/src/$PACKAGE".tar.xz" /usr/src/*config.xz
  192. apt clean
  193. debconf-apt-progress -- apt-get -y purge linux-source*
  194. debconf-apt-progress -- apt -y autoremove
  195. if [[ -z $scripted ]]; then
  196. dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " Kernel source " --clear --msgbox "\nYou will find pre-configured kernel sources in /usr/src/$PACKAGE" 7 72
  197. fi
  198. else
  199. dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nLoading software submodule ... " 5 34
  200. fi
  201. fi
  202. ;;
  203. #
  204. # Remove kernel source
  205. #
  206. "Source_remove" )
  207. if ! is_package_manager_running; then
  208. if [[ -z $scripted ]]; then
  209. LIST=()
  210. for pkg in $SOURCE_PKG_LIST_INSTALLED
  211. do
  212. LIST+=( "$pkg" "" )
  213. done
  214. exec 3>&1
  215. selection=$(dialog --backtitle "$BACKTITLE" --title "Kernel remove" --clear --cancel-label "Back" \
  216. --menu "Choose kernel version" 12 70 ${#LIST[@]} "${LIST[@]}" 2>&1 1>&3)
  217. exit_status=$?
  218. exec 3>&-
  219. [[ $exit_status == 1 || $exit_status == 255 ]] && clear
  220. else
  221. selection=$(echo $SOURCE_PKG_LIST_INSTALLED | awk '{ print $NF }')
  222. fi
  223. if [[ -n $selection ]]; then
  224. PACKAGE="linux-source-$(echo $selection | sed 's/[-|(|[:alpha:]|(|[:space:]|(|/]//g')-${BRANCH}-${LINUXFAMILY}"
  225. if ls $selection 1> /dev/null 2>&1; then
  226. debconf-apt-progress -- apt-get -y purge $PACKAGE
  227. debconf-apt-progress -- apt -y autoremove
  228. apt clean
  229. dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nRemoving $selection ... " 5 72
  230. rm -r $selection
  231. fi
  232. if [[ -z $scripted ]]; then
  233. dialog --colors --backtitle "$BACKTITLE" --no-collapse --title " Kernel source " --clear --msgbox "\n$selection removed" 7 72
  234. fi
  235. else
  236. dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nLoading software submodule ... " 5 34
  237. fi
  238. fi
  239. ;;
  240. # Toggle mini and full firmware
  241. #
  242. "Full"|"Mini" )
  243. if ! is_package_manager_running; then
  244. debconf-apt-progress -- apt-get -y purge orangepi-firmware* # workaround since pkg replace doesn't work properly
  245. debconf-apt-progress -- apt-get -y install orangepi-firmware$(echo -"${1,,}" | sed 's/-mini//')
  246. fi
  247. ;;
  248. # Set the display resolution
  249. #
  250. "Display" )
  251. # show display modes menu
  252. if [[ -f /usr/bin/h3disp ]]; then
  253. # h3 boards
  254. get_h3modes
  255. dialog --title " Display output type " --colors --help-button --help-label "Cancel" --no-label "DVI" --yes-label "HDMI" \
  256. --backtitle "$BACKTITLE" --yesno "\nIn case you use an HDMI-to-DVI converter choose DVI!" 7 57
  257. output_type=$?
  258. if [[ $output_type = 0 || $output_type = 1 ]]; then
  259. if [[ $output_type = 0 ]]; then
  260. display_cmd="h3disp -m $SCREEN_RESOLUTION";
  261. else
  262. display_cmd="h3disp -m $SCREEN_RESOLUTION -d";
  263. fi
  264. fi
  265. elif [[ "$LINUXFAMILY" = odroidc* || "$LINUXFAMILY" = odroidn2 ]]; then
  266. get_odroidmodes
  267. display_cmd="sed -i \"s/^setenv m .*/# &/\" /boot/boot.ini;sed -i '/setenv m \"$SCREEN_RESOLUTION\"/s/^# //g' /boot/boot.ini";
  268. # odroid n2
  269. display_cmd='sed -i "s/^setenv hdmimode .*/setenv hdmimode \"$SCREEN_RESOLUTION\"/" /boot/boot.ini; sed -i "s/^setenv display_autodetect .*/setenv display_autodetect \"false\"/" /boot/boot.ini';
  270. else
  271. # a20 boards
  272. get_a20modes
  273. display_cmd="sed -i \"s/^disp_mode=.*/disp_mode=$SCREEN_RESOLUTION/\" /boot/orangepiEnv.txt";
  274. fi
  275. dialog --title " Display resolution " --colors --no-label "Cancel" --backtitle "$BACKTITLE" --yesno \
  276. "\nSwitching to \Z1$SCREEN_RESOLUTION\Z0 and reboot?" 7 42
  277. if [[ $? = 0 ]]; then
  278. eval $display_cmd > /dev/null
  279. reboot
  280. fi
  281. ;;
  282. #-------------------------------------------------------------------------------------------------------------------------------------#
  283. #-------------------------------------------------------------------------------------------------------------------------------------#
  284. #-------------------------------------------------------------------------------------------------------------------------------------#
  285. # Select dynamic or edit static IP address
  286. #
  287. "IP" )
  288. select_interface
  289. # check if we have systemd networking in action
  290. SYSTEMDNET=$(service systemd-networkd status | grep -w active | grep -w running)
  291. dialog --title " IP address assignment " --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" \
  292. --yes-label "DHCP" --no-label "Static" --yesno \
  293. "\n\Z1DHCP:\Z0 automatic IP assignment by your router or DHCP server\n\n\Z1Static:\Z0 manually fixed IP address" 9 70
  294. exitstatus=$?;
  295. # dynamic
  296. if [[ $exitstatus = 0 ]]; then
  297. if [[ -n $SYSTEMDNET ]]; then
  298. filename="/etc/systemd/network/10-${SELECTED_ADAPTER}.network"
  299. if [[ -f $filename ]]; then
  300. sed -i '/Network/,$d' $filename
  301. echo -e "[Network]" >>$filename
  302. echo -e "DHCP=ipv4" >>$filename
  303. fi
  304. else
  305. if [[ -n $(LC_ALL=C nmcli device status | grep $SELECTED_ADAPTER ) ]]; then
  306. nmcli connection delete uuid $(LC_ALL=C nmcli -f UUID,DEVICE connection show | grep $SELECTED_ADAPTER | awk '{print $1}') >/dev/null 2>&1
  307. nmcli con add con-name "Orange Pi ethernet" type ethernet ifname $SELECTED_ADAPTER >/dev/null 2>&1
  308. nmcli con up "Orange Pi ethernet" >/dev/null 2>&1
  309. else
  310. create_if_config "$SELECTED_ADAPTER" "$SELECTED_ADAPTER" "dynamic" > /etc/network/interfaces
  311. fi
  312. fi
  313. fi
  314. # static
  315. if [[ $exitstatus = 1 ]]; then
  316. create_if_config "$SELECTED_ADAPTER" "$SELECTED_ADAPTER" "fixed" > /dev/null
  317. if [[ -n $SYSTEMDNET ]]; then
  318. systemd_ip_editor "${SELECTED_ADAPTER}"
  319. else
  320. if [[ -n $(LC_ALL=C nmcli device status | grep $SELECTED_ADAPTER ) ]]; then
  321. nm_ip_editor "$SELECTED_ADAPTER"
  322. else
  323. ip_editor "$SELECTED_ADAPTER" "$SELECTED_ADAPTER" "/etc/network/interfaces"
  324. fi
  325. fi
  326. fi
  327. ;;
  328. # Start network performance daemon
  329. #
  330. "Iperf3" )
  331. #
  332. if pgrep -x "iperf3" > /dev/null
  333. then
  334. pkill iperf3
  335. else
  336. iperf3 -s -D
  337. fi
  338. ;;
  339. # Toggle IPv6
  340. #
  341. "IPV6" )
  342. #
  343. sed -i --follow-symlinks '/^net.ipv6.conf*/d' /etc/sysctl.d/99-sysctl.conf
  344. if [ -f "/etc/apt/apt.conf.d/99force-ipv4" ]; then
  345. rm /etc/apt/apt.conf.d/99force-ipv4
  346. echo 'net.ipv6.conf.all.disable_ipv6 = 0' >> /etc/sysctl.d/99-sysctl.conf
  347. echo 'net.ipv6.conf.default.disable_ipv6 = 0' >> /etc/sysctl.d/99-sysctl.conf
  348. echo 'net.ipv6.conf.lo.disable_ipv6 = 0' >> /etc/sysctl.d/99-sysctl.conf
  349. else
  350. echo 'Acquire::ForceIPv4 "true";' > /etc/apt/apt.conf.d/99force-ipv4
  351. echo 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.d/99-sysctl.conf
  352. echo 'net.ipv6.conf.default.disable_ipv6 = 1' >> /etc/sysctl.d/99-sysctl.conf
  353. echo 'net.ipv6.conf.lo.disable_ipv6 = 1' >> /etc/sysctl.d/99-sysctl.conf
  354. fi
  355. sysctl -p > /dev/null
  356. ;;
  357. # Connect to wireless access point
  358. #
  359. "WiFi" )
  360. # disable AP mode on certain adapters
  361. wlan_exceptions "off"
  362. [[ "$reboot_module" == true ]] && dialog --backtitle "$BACKTITLE" --title " Warning " --msgbox "\nReboot is required for this adapter to switch to STA mode" 7 62 && reboot
  363. nmtui-connect
  364. ;;
  365. # Connect to 3G/4G network
  366. #
  367. "LTE" )
  368. if ! is_package_manager_running; then
  369. if [[ $LTE_MODEM == *online* ]]; then
  370. dialog --title " LTE modem is connected " --colors --backtitle "$BACKTITLE" --yes-label "Back" --no-label "Disconnect" --yesno "\n\Z1Disconnect:\Z0 kill mobile connection\n\n" 7 42
  371. [[ $? = 1 ]] && lte "$LTE_MODEM_ID" "off"
  372. else
  373. dialog --title " LTE modem is disconnected " --colors --backtitle "$BACKTITLE" --yes-label "Back" --no-label "Connect" --yesno "\n\Z1Connect:\Z0 dial mobile connection\n\n" 7 42
  374. [[ $? = 1 ]] && lte "$LTE_MODEM_ID" "on"
  375. fi
  376. fi
  377. ;;
  378. # Connect to wireless access point
  379. #
  380. "Clear" )
  381. # remove managed interfaces
  382. systemctl daemon-reload
  383. nmcli con delete $(nmcli --fields NAME,UUID,TYPE con | grep wifi | awk '{print $2}')
  384. sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  385. sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  386. rm -f /etc/network/interfaces.d/orangepi.ap.*
  387. rm -f /etc/dnsmasq.conf
  388. systemctl stop dnsmasq
  389. systemctl disable dnsmasq
  390. iptables -t nat -D POSTROUTING 1 >/dev/null 2>&1
  391. systemctl stop orangepi-restore-iptables.service
  392. systemctl disable orangepi-restore-iptables.service
  393. rm -f /etc/iptables.ipv4.nat
  394. rm -f /var/run/hostapd/* >/dev/null 2>&1
  395. reload-nety
  396. ;;
  397. # Create WiFi access point
  398. #
  399. "Hotspot" )
  400. if ! is_package_manager_running; then
  401. systemctl daemon-reload
  402. CURRENT_UUID=$(LC_ALL=C nmcli -f DEVICE,TYPE,STATE device status | grep -w " wifi " | grep -w " disconnected")
  403. if [[ -n $(service hostapd status | grep -w active | grep -w running) ]]; then
  404. if [[ -n $HOSTAPDBRIDGE ]]; then
  405. dialog --title " Hostapd service is running " --colors --backtitle "$BACKTITLE" --help-button \
  406. --help-label "Cancel" --yes-label "Stop and reboot" --no-label "Edit" --yesno \
  407. "\n\Z1Stop:\Z0 stop and reboot\n\n\Z1Edit:\Z0 change basic parameters: SSID, password and channel" 9 70
  408. else
  409. dialog --title " Hostapd service is running " --colors --backtitle "$BACKTITLE" --help-button \
  410. --help-label "Cancel" --yes-label "Stop" --no-label "Edit" --yesno \
  411. "\n\Z1Stop:\Z0 stop providing Access Point\n\n\Z1Edit:\Z0 change basic parameters: SSID, password and channel" 9 70
  412. fi
  413. exitstatus=$?;
  414. if [[ $exitstatus = 0 ]]; then
  415. dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nDisabling hotspot. Please wait!" 5 35
  416. sed -i "s/^DAEMON_CONF=.*/DAEMON_CONF=/" /etc/init.d/hostapd
  417. # disable DNS
  418. systemctl daemon-reload
  419. systemctl disable dnsmasq.service >/dev/null 2>&1
  420. ifdown $WIRELESS_ADAPTER 2> /dev/null
  421. rm -f /etc/network/interfaces.d/orangepi.ap.*
  422. rm -f /etc/dnsmasq.conf
  423. iptables -t nat -D POSTROUTING 1 >/dev/null 2>&1
  424. rm -f /etc/iptables.ipv4.nat
  425. systemctl stop orangepi-restore-iptables.service
  426. systemctl disable orangepi-restore-iptables.service
  427. rm -f /var/run/hostapd/* >/dev/null 2>&1
  428. sed -i '/^iptables/ d' /etc/rc.local
  429. sed -i '/^service dnsmasq/ d' /etc/rc.local
  430. sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  431. sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  432. iptables -F
  433. # reload services
  434. reload-nety
  435. [[ -n $HOSTAPDBRIDGE ]] && reboot
  436. fi
  437. if [[ $exitstatus = 1 ]]; then wlan_edit; reload-nety "reload"; fi
  438. elif [[ -z $CURRENT_UUID ]]; then
  439. dialog --title " Info " --backtitle "$BACKTITLE" --no-collapse --msgbox "\nAll wireless connections are in use." 7 40
  440. else
  441. # check for low quality drivers and combinations
  442. check_and_warn
  443. # remove interfaces from managed list
  444. if [[ -f /etc/NetworkManager/conf.d/10-ignore-interfaces.conf ]]; then
  445. sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  446. sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  447. fi
  448. # clear current settings
  449. rm -f /etc/network/interfaces.d/orangepi.ap.nat
  450. rm -f /etc/network/interfaces.d/orangepi.ap.bridge
  451. service networking restart
  452. service network-manager restart >/dev/null 2>&1
  453. service NetworkManager restart >/dev/null 2>&1
  454. { for ((i = 0 ; i <= 100 ; i+=20)); do sleep 1; echo $i; done } | dialog --title " Initializing wireless adapters " --colors --gauge "" 5 50 0
  455. # start with basic config
  456. if grep -q "^## IEEE 802.11ac" /etc/hostapd.conf; then sed '/## IEEE 802.11ac\>/,/^## IEEE 802.11ac\>/ s/.*/#&/' -i /etc/hostapd.conf; fi
  457. if grep -q "^## IEEE 802.11a" /etc/hostapd.conf; then sed '/## IEEE 802.11a\>/,/^## IEEE 802.11a\>/ s/.*/#&/' -i /etc/hostapd.conf; fi
  458. if grep -q "^## IEEE 802.11n" /etc/hostapd.conf; then sed '/## IEEE 802.11n/,/^## IEEE 802.11n/ s/.*/#&/' -i /etc/hostapd.conf; fi
  459. sed -i "s/^channel=.*/channel=5/" /etc/hostapd.conf
  460. service network-manager reload >/dev/null 2>&1
  461. service NetworkManager reload >/dev/null 2>&1
  462. # change special adapters to AP mode
  463. wlan_exceptions "on"
  464. # check for WLAN interfaces
  465. get_wlan_interface
  466. # add interface to unmanaged list
  467. if [[ -f /etc/NetworkManager/conf.d/10-ignore-interfaces.conf ]]; then
  468. [[ -z $(grep -w unmanaged-devices= /etc/NetworkManager/conf.d/10-ignore-interfaces.conf) ]] && sed '$ s/$/,/' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  469. sed '$ s/$/'"interface-name:$WIRELESS_ADAPTER"'/' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  470. else
  471. echo "[keyfile]" > /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  472. echo "unmanaged-devices=interface-name:$WIRELESS_ADAPTER" >> /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  473. fi
  474. service network-manager reload >/dev/null 2>&1
  475. service NetworkManager reload >/dev/null 2>&1
  476. # display dialog
  477. dialog --colors --backtitle "$BACKTITLE" --title "Please wait" --infobox \
  478. "\nWireless adapter: \Z1${WIRELESS_ADAPTER}\Z0\n\nProbing nl80211 hostapd driver compatibility." 7 50
  479. #debconf-apt-progress -- apt-get --reinstall -o Dpkg::Options::="--force-confnew" -y -qq --no-install-recommends install hostapd
  480. # change to selected interface
  481. sed -i "s/^interface=.*/interface=$WIRELESS_ADAPTER/" /etc/hostapd.conf
  482. # add hostapd.conf to services
  483. sed -i "s/^DAEMON_CONF=.*/DAEMON_CONF=\/etc\/hostapd.conf/" /etc/init.d/hostapd
  484. # check both options
  485. # add allow cli access if not exists. temporally
  486. if ! grep -q "ctrl_interface" /etc/hostapd.conf; then
  487. echo "" >> /etc/hostapd.conf
  488. echo "ctrl_interface=/var/run/hostapd" >> /etc/hostapd.conf
  489. echo "ctrl_interface_group=0" >> /etc/hostapd.conf
  490. fi
  491. #
  492. check_advanced_modes
  493. #
  494. if [[ -n "$hostapd_error" ]]; then
  495. dialog --colors --backtitle "$BACKTITLE" --title "Please wait" --infobox \
  496. "\nWireless adapter: \Z1${WIRELESS_ADAPTER}\Z0\n\nProbing Realtek hostapd driver compatibility." 7 50
  497. debconf-apt-progress -- apt-get --reinstall -o Dpkg::Options::="--force-confnew" -y -qq --no-install-recommends install hostapd-realtek
  498. # change to selected interface
  499. sed -i "s/^interface=.*/interface=$WIRELESS_ADAPTER/" /etc/hostapd.conf
  500. # add allow cli access if not exists. temporally
  501. if ! grep -q "ctrl_interface" /etc/hostapd.conf; then
  502. echo "ctrl_interface=/var/run/hostapd" >> /etc/hostapd.conf
  503. echo "ctrl_interface_group=0" >> /etc/hostapd.conf
  504. fi
  505. #
  506. check_advanced_modes
  507. #
  508. fi
  509. if [[ -n "$hostapd_error" ]]; then
  510. dialog --backtitle "$BACKTITLE" --title "Warning" \
  511. --infobox "\nWireless adapter: $WIRELESS_ADAPTER\n\nNo compatible hostapd driver found." 7 39
  512. sed -i "s/^DAEMON_CONF=.*/DAEMON_CONF=/" /etc/init.d/hostapd
  513. # remove interfaces from managed list
  514. sed 's/interface-name:wl.*//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  515. sed 's/,$//' -i /etc/NetworkManager/conf.d/10-ignore-interfaces.conf
  516. systemctl daemon-reload;service hostapd restart
  517. fi
  518. # let's remove bridge out for this simple configurator
  519. #
  520. # dialog --title " Choose Access Point mode for $WIRELESS_ADAPTER " --colors --backtitle "$BACKTITLE" --no-label "Bridge" \
  521. # --yes-label "NAT" --yesno "\n\Z1NAT:\Z0 with own DHCP server, out of your primary network\n\
  522. # \n\Z1Bridge:\Z0 wireless clients will use your routers DHCP server" 9 70
  523. # response=$?
  524. #
  525. # let's remove bridge out for this simple configurator
  526. response=0
  527. # create interfaces file if not exits
  528. [[ ! -f /etc/network/interfaces ]] && echo "source /etc/network/interfaces.d/*" > /etc/network/interfaces
  529. # select default interfaces if there is more than one
  530. select_default_interface
  531. NETWORK_CONF="/etc/network/interfaces"
  532. case $response in
  533. # bridge
  534. 1)
  535. TEMP_CONF="/etc/network/interfaces.d/orangepi.ap.bridge"
  536. sed -i 's/.bridge=.*/bridge=br0/' /etc/hostapd.conf
  537. if [[ $DEFAULT_ADAPTER == "br0" ]]; then NEW_DEFAULT_ADAPTER="eth0"; else NEW_DEFAULT_ADAPTER="$DEFAULT_ADAPTER"; fi
  538. echo -e "#bridged wireless for hostapd by orangepi-config\n" > $TEMP_CONF
  539. echo -e "auto lo br0\niface lo inet loopback" >> $TEMP_CONF
  540. echo -e "\nauto $NEW_DEFAULT_ADAPTER\nallow-hotplug $NEW_DEFAULT_ADAPTER\niface $NEW_DEFAULT_ADAPTER inet manual" >> $TEMP_CONF
  541. echo -e "\nauto $WIRELESS_ADAPTER\nallow-hotplug $WIRELESS_ADAPTER\niface $WIRELESS_ADAPTER inet manual\n" >> $TEMP_CONF
  542. create_if_config "$DEFAULT_ADAPTER" "br0" >> $TEMP_CONF
  543. echo -e "\nbridge_ports $NEW_DEFAULT_ADAPTER $WIRELESS_ADAPTER" >> $TEMP_CONF
  544. ;;
  545. # NAT
  546. 0)
  547. TEMP_CONF="/etc/network/interfaces.d/orangepi.ap.nat"
  548. # install dnsmas and iptables
  549. if [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' dnsmasq 2>/dev/null) != "*ii*" ]]; then
  550. debconf-apt-progress -- apt-get -qq -y --no-install-recommends install dnsmasq;
  551. systemctl enable dnsmasq
  552. fi
  553. echo -e "# orangepi NAT hostapd\nallow-hotplug $WIRELESS_ADAPTER\niface $WIRELESS_ADAPTER inet static " > $TEMP_CONF
  554. echo -e "\taddress 172.24.1.1\n\tnetmask 255.255.255.0\n\tnetwork 172.24.1.0\n\tbroadcast 172.24.1.255" >> $TEMP_CONF
  555. # create new configuration
  556. echo "interface=$WIRELESS_ADAPTER # Use interface $WIRELESS_ADAPTER" > /etc/dnsmasq.conf
  557. echo "listen-address=172.24.1.1 # Explicitly specify the address to listen on" >> /etc/dnsmasq.conf
  558. echo "bind-interfaces # Bind to the interface to make sure we aren't sending \
  559. things elsewhere" >> /etc/dnsmasq.conf
  560. echo "server=8.8.8.8 # Forward DNS requests to Google DNS" >> /etc/dnsmasq.conf
  561. echo "domain-needed # Don't forward short names" >> /etc/dnsmasq.conf
  562. echo "bogus-priv # Never forward addresses in the non-routed address spaces" \
  563. >> /etc/dnsmasq.conf
  564. echo "dhcp-range=172.24.1.50,172.24.1.150,12h # Assign IP addresses between 172.24.1.50 and 172.24.1.150 with \
  565. a 12 hour lease time" >> /etc/dnsmasq.conf
  566. # - Enable IPv4 forwarding
  567. sed -i "/net.ipv4.ip_forward=/c\net.ipv4.ip_forward=1" /etc/sysctl.conf
  568. echo 1 > /proc/sys/net/ipv4/ip_forward
  569. # Clear iptables
  570. iptables-save | awk '/^[*]/ { print $1 } /^:[A-Z]+ [^-]/ { print $1 " ACCEPT" ; } /COMMIT/ { print $0; }' | iptables-restore
  571. if [[ ${DISTRIBUTION_CODENAME} == buster ]]; then
  572. echo 1 | update-alternatives --config iptables > /dev/null
  573. fi
  574. # - Apply iptables
  575. iptables -t nat -A POSTROUTING -o $DEFAULT_ADAPTER -j MASQUERADE
  576. iptables -A FORWARD -i $DEFAULT_ADAPTER -o $WIRELESS_ADAPTER -m state --state RELATED,ESTABLISHED -j ACCEPT
  577. iptables -A FORWARD -i $WIRELESS_ADAPTER -o $DEFAULT_ADAPTER -j ACCEPT
  578. # - Save IP tables, applied during ifup in /etc/network/interfaces.
  579. iptables-save > /etc/iptables.ipv4.nat
  580. sed -i 's/^bridge=.*/#&/' /etc/hostapd.conf
  581. #sed -e 's/exit 0//g' -i /etc/rc.local
  582. # workaround if hostapd is too slow
  583. #echo "service dnsmasq start" >> /etc/rc.local
  584. #echo "iptables-restore < /etc/iptables.ipv4.nat" >> /etc/rc.local
  585. #echo "exit 0" >> /etc/rc.local
  586. systemctl stop orangepi-restore-iptables.service
  587. systemctl disable orangepi-restore-iptables.service
  588. cat <<-EOF > /etc/systemd/system/orangepi-restore-iptables.service
  589. [Unit]
  590. Description="Restore IP tables"
  591. [Timer]
  592. OnBootSec=20Sec
  593. [Service]
  594. Type=oneshot
  595. ExecStart=/sbin/iptables-restore /etc/iptables.ipv4.nat
  596. [Install]
  597. WantedBy=sysinit.target
  598. EOF
  599. systemctl enable orangepi-restore-iptables.service
  600. ;;
  601. 3)exit;;
  602. 255) exit;;
  603. esac
  604. dialog --backtitle "$BACKTITLE" --title " Please wait " --infobox "\nEnabling hotspot. Please wait!" 5 34
  605. #
  606. # only for bridged connection we need to check and reboot. tdlr check if it can be done on the fly
  607. HOSTAPDBRIDGE=$(cat /etc/hostapd.conf 2> /dev/null | grep -w "^bridge=br0")
  608. if [[ -n $HOSTAPDBRIDGE ]]; then
  609. dialog --title "Manually adjust network configuration if needed" --backtitle "$BACKTITLE" \
  610. --ok-label "Reboot to apply new settings" --no-collapse --editbox $TEMP_CONF 30 0 2> $TEMP_CONF".tmp"
  611. response=$?
  612. if [[ $response = 0 ]]; then
  613. mv $TEMP_CONF".tmp" $TEMP_CONF
  614. #reboot
  615. fi
  616. else
  617. ifdown $WIRELESS_ADAPTER 2> /dev/null
  618. sleep 2
  619. ifup $WIRELESS_ADAPTER 2> /dev/null
  620. echo "nameserver 8.8.8.8" > /etc/resolvconf/resolv.conf.d/base
  621. [[ "$reboot_module" == true ]] && dialog --backtitle "$BACKTITLE" --title " Warning " --msgbox "\nReboot is required for this adapter to switch to AP mode" 7 61 && reboot
  622. # reload services
  623. reload-nety "reload"
  624. fi
  625. fi
  626. fi
  627. ;;
  628. # Manage Softether VPN
  629. #
  630. "VPN" )
  631. VPNDIR="/usr/local/vpnclient/"
  632. function vpn_reconfigure ()
  633. {
  634. if [[ -f /etc/server.vpn ]]; then
  635. ${VPNDIR}vpnclient stop >/dev/null 2>&1
  636. ${VPNDIR}vpnclient start >/dev/null 2>&1
  637. # purge old settings
  638. ${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Connection Setting Name" | cut -d "|" -f 2 | sed 's/^/"/;s/$/"/' | xargs /usr/local/vpnclient/vpncmd /client localhost /cmd accountdisconnect >/dev/null 2>&1
  639. ${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Connection Setting Name" | cut -d "|" -f 2 | sed 's/^/"/;s/$/"/' | xargs /usr/local/vpnclient/vpncmd /client localhost /cmd accountdelete >/dev/null 2>&1
  640. # import new
  641. ${VPNDIR}vpncmd /client localhost /cmd accountimport //etc//server.vpn >/dev/null 2>&1
  642. # reload to connect
  643. ${VPNDIR}vpnclient stop >/dev/null 2>&1
  644. ${VPNDIR}vpnclient start >/dev/null 2>&1
  645. [[ $? = 0 ]] && dialog --backtitle "$BACKTITLE" --title " VPN " --msgbox "\nConfiguration was successfully imported!" 7 43
  646. fi
  647. }
  648. function get_numbers {
  649. EXCLUDE=$(ip neigh | grep vpn_se | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.' | head -1)
  650. ADAPTER=$(ip -4 route ls | grep default | grep -Po '(?<=dev )(\S+)' | grep -v vpn_se | head -1)
  651. IP=$(ip route | grep $ADAPTER | grep default | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
  652. VPNSERVERIP=$(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Server" |grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
  653. SUBNET=$(ifconfig vpn_se | grep 'inet addr:' | grep -v '127.0.0.1' | cut -d: -f2 | awk '{ print $1}' | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}')
  654. GW=$(ip neigh | grep vpn_se | grep $SUBNET | grep -o '[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}' | head -1)
  655. }
  656. function raise_dev {
  657. i=0;
  658. while [[ -z "$TEMP" && $i<5 ]]; do
  659. TEMP=$(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep Status | grep Connected)
  660. sleep 1
  661. i=$((i+1))
  662. done
  663. dhclient vpn_se
  664. }
  665. if pgrep -x "vpnclient" > /dev/null
  666. then
  667. ${VPNDIR}vpnclient stop >/dev/null 2>&1
  668. ${VPNDIR}vpnclient start >/dev/null 2>&1
  669. if [[ -z $(${VPNDIR}vpncmd /client localhost /cmd nicList | grep Enabled) ]]; then
  670. ${VPNDIR}vpncmd /client localhost /cmd niccreate se >/dev/null 2>&1
  671. fi
  672. if [[ -z $(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep "VPN Server") ]]; then
  673. dialog --backtitle "$BACKTITLE" --no-label " Cancel " --yes-label " Import " --title " VPN " --yesno "\nA VPN configuration was not found.\n\nPlace valid file at /etc/server.vpn" 9 45
  674. if [[ $? = 0 && -f /etc/server.vpn ]]; then
  675. ${VPNDIR}vpncmd /client localhost /cmd accountimport //etc//server.vpn >/dev/null 2>&1
  676. ${VPNDIR}vpnclient stop >/dev/null 2>&1
  677. ${VPNDIR}vpnclient start >/dev/null 2>&1
  678. [[ $? = 0 ]] && dialog --backtitle "$BACKTITLE" --title " VPN " --msgbox "\nConfiguration was successfully imported!" 7 43
  679. fi
  680. fi
  681. # raise devices
  682. raise_dev
  683. if [[ -n $(${VPNDIR}vpncmd /client localhost /cmd accountlist | grep Status | grep Connected) ]]; then
  684. get_numbers
  685. echo "ip route add $VPNSERVERIP via $IP dev $ADAPTER"
  686. echo "ip route del default"
  687. echo "ip route add default via $GW dev vpn_se"
  688. read
  689. dialog --title "VPN client is connected to $VPNSERVERIP" --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" --yes-label "Stop" --no-label " Import " --yesno "\n\Z1Stop: \Z0 stop\n\n\Z1Import:\Z0 import new config from /etc/orangepi.vpn" 9 70
  690. fi
  691. response=$?
  692. if [[ $response = 0 ]]; then
  693. get_numbers
  694. echo "ip route del $VPNSERVERIP"
  695. echo "ip route del default"
  696. echo "ip route add default via $IP dev $ADAPTER"
  697. read
  698. dialog --backtitle "$BACKTITLE" --nocancel --nook --infobox "\nClosing VPN connection" 5 27
  699. ${VPNDIR}vpnclient stop >/dev/null 2>&1
  700. fi
  701. else
  702. dialog --title "VPN client is disconnected" --colors --backtitle "$BACKTITLE" --help-button --help-label "Cancel" --yes-label "Connect" --no-label " Import " --yesno "\n\Z1Connect:\Z0 Connect with your VPN server \n\n\Z1Import:\Z0 import new config from /etc/orangepi.vpn" 9 70
  703. response=$?
  704. if [[ $response = 0 ]]; then
  705. ${VPNDIR}vpnclient start >/dev/null 2>&1
  706. # raise devices
  707. raise_dev
  708. get_numbers
  709. echo "ip route add $VPNSERVERIP via $IP dev $ADAPTER"
  710. echo "ip route del default"
  711. echo "ip route add default via $GW dev vpn_se"
  712. read
  713. fi
  714. [[ $response = 1 ]] && vpn_reconfigure
  715. fi
  716. ;;
  717. # Connect to Bluetooth
  718. #
  719. "BT discover" )
  720. dialog --backtitle "$BACKTITLE" --title " Bluetooth " --msgbox "\nVerify that your Bluetooth device is discoverable!" 7 54
  721. connect_bt_interface
  722. ;;
  723. # Edit network settings
  724. #
  725. "Advanced" )
  726. dialog --backtitle "$BACKTITLE" --title " Edit ifupdown network configuration /etc/network/interfaces" --no-collapse \
  727. --ok-label "Save" --editbox /etc/network/interfaces 30 0 2> /etc/network/interfaces.out
  728. [[ $? = 0 ]] && mv /etc/network/interfaces.out /etc/network/interfaces && reload-nety "reload"
  729. ;;
  730. # Remove automatic wifi conections
  731. #
  732. "Forget" )
  733. LC_ALL=C nmcli --fields UUID,TIMESTAMP-REAL,TYPE con show | grep wifi | awk '{print $1}' | while read line; \
  734. do nmcli con delete uuid $line; done > /dev/null
  735. ;;
  736. #-------------------------------------------------------------------------------------------------------------------------------------#
  737. #-------------------------------------------------------------------------------------------------------------------------------------#
  738. #-------------------------------------------------------------------------------------------------------------------------------------#
  739. # Change timezone
  740. #
  741. "Timezone" )
  742. dpkg-reconfigure tzdata
  743. ;;
  744. # Change locales
  745. #
  746. "Locales" )
  747. dpkg-reconfigure locales
  748. source /etc/default/locale
  749. sed -i "s/^LANGUAGE=.*/LANGUAGE=$LANG/" /etc/default/locale
  750. export LANGUAGE=$LANG
  751. ;;
  752. # Change keyboard
  753. #
  754. "Keyboard" )
  755. dpkg-reconfigure keyboard-configuration
  756. setupcon
  757. ;;
  758. # Change Hostname
  759. #
  760. "Hostname" )
  761. hostname_current=$(cat /etc/hostname)
  762. hostname_new=$(\
  763. dialog --no-cancel --title " Change hostname " --backtitle "$BACKTITLE" --inputbox "\nType new hostname\n " 10 50 $hostname_current \
  764. 3>&1 1>&2 2>&3 3>&- \
  765. )
  766. if [[ $? = 0 && -n $hostname_new ]]; then
  767. sed -i "s/$hostname_current/$hostname_new/g" /etc/hosts
  768. sed -i "s/$hostname_current/$hostname_new/g" /etc/hostname
  769. hostname $hostname_new
  770. systemctl restart systemd-logind.service
  771. dialog --title " Info " --backtitle "$BACKTITLE" --no-collapse --msgbox "\nYou need to logout to make the changes effective." 7 53
  772. fi
  773. ;;
  774. # Bash
  775. #
  776. "BASH" )
  777. # change shell for root
  778. chsh -s /bin/bash
  779. add_choose_user
  780. if [ -n "$CHOSEN_USER" ]; then
  781. chsh -s /bin/bash $CHOSEN_USER
  782. fi
  783. # cleanup
  784. rm -rf /etc/oh-my-zsh /etc/skel/.zshrc /etc/skel/.oh-my-zsh
  785. rm -rf /root/{.zshrc,.oh-my-zsh}
  786. # and for selected normal user
  787. add_choose_user
  788. if [ -n "$CHOSEN_USER" ]; then
  789. rm -rf /home/$CHOSEN_USER/{.zshrc,.oh-my-zsh}
  790. fi
  791. # change shell for future users
  792. sed -i "s/^SHELL=.*/SHELL=\/bin\/bash/" /etc/default/useradd
  793. # remove crontab
  794. crontab -l | grep -v oh-my | crontab -
  795. if [[ -z $scripted ]]; then
  796. dialog --backtitle "$BACKTITLE" --title "Info" --colors --msgbox "\nYour default shell was switched to: \Z1BASH\Z0\n\nPlease logout & login from this session!" 9 47
  797. fi
  798. ;;
  799. # ZSH
  800. #
  801. "ZSH" )
  802. if ! is_package_manager_running; then
  803. if ! check_if_installed zsh ; then
  804. debconf-apt-progress -- apt-get update
  805. debconf-apt-progress -- apt-get install -y zsh tmux git
  806. fi
  807. rm -rf /etc/oh-my-zsh
  808. git clone --quiet https://github.com/robbyrussell/oh-my-zsh.git /etc/oh-my-zsh
  809. cp /etc/oh-my-zsh/templates/zshrc.zsh-template /etc/skel/.zshrc
  810. mkdir -p /etc/skel/.oh-my-zsh/cache
  811. # change shell for future users
  812. sed -i "s/^SHELL=.*/SHELL=\/usr\/bin\/zsh/" /etc/default/useradd
  813. # we have common settings
  814. sed -i "s/^export ZSH=.*/export ZSH=\/etc\/oh-my-zsh/" /etc/skel/.zshrc
  815. # user cache
  816. sed -i "/^export ZSH=.*/a export ZSH_CACHE_DIR=~\/.oh-my-zsh\/cache" /etc/skel/.zshrc
  817. # define theme
  818. sed -i 's/^ZSH_THEME=.*/ZSH_THEME="risto"/' /etc/skel/.zshrc
  819. # disable prompt while update
  820. sed -i 's/# DISABLE_UPDATE_PROMPT="true"/DISABLE_UPDATE_PROMPT="true"/g' /etc/skel/.zshrc
  821. # define default plugins
  822. sed -i 's/^plugins=.*/plugins=(git git-extras debian tmux screen history extract colorize web-search docker)/' /etc/skel/.zshrc
  823. # change shell for root
  824. chsh -s $(grep /zsh$ /etc/shells | tail -1)
  825. # copy cache directory
  826. cp -R --attributes-only /etc/skel/.oh-my-zsh /root/.oh-my-zsh
  827. cp /etc/skel/.zshrc /root/.zshrc
  828. # and for selected normal user
  829. add_choose_user
  830. if [ -n "$CHOSEN_USER" ]; then
  831. chsh -s $(grep /zsh$ /etc/shells | tail -1) $CHOSEN_USER
  832. # copy cache directory
  833. cp -R --attributes-only /etc/skel/.oh-my-zsh /home/$CHOSEN_USER/.oh-my-zsh
  834. cp /etc/skel/.zshrc /home/$CHOSEN_USER/.zshrc
  835. chown -R ${CHOSEN_USER}:${CHOSEN_USER} /home/${CHOSEN_USER}/{.zshrc,.oh-my-zsh}
  836. fi
  837. # add a cronjob to update oh-my-zsh once per month
  838. (crontab -l 2>/dev/null; echo "0 0 1 * * cd /etc/oh-my-zsh ; git pull origin master >/dev/null 2>/dev/null") | crontab -
  839. if [[ -z $scripted ]]; then
  840. dialog --backtitle "$BACKTITLE" --title "Info" --colors --msgbox "\nYour default shell was switched to: \Z1ZSH\Z0\n\nPlease logout & login from this session!" 9 47
  841. fi
  842. fi
  843. ;;
  844. # Firmware update
  845. #
  846. "Firmware" )
  847. if ! is_package_manager_running; then
  848. clear
  849. exec 3>&1
  850. monitor=$(dialog --print-maxsize 2>&1 1>&3)
  851. exec 3>&-
  852. mon_x=$(echo $monitor | awk '{print $2}' | sed 's/,//');mon_x=$(( $mon_x / 2 ))
  853. mon_y=$(echo $monitor | awk '{print $3}' | sed 's/,//');
  854. if [[ -z $scripted ]]; then
  855. dialog --title " Update " --backtitle "$BACKTITLE" --no-label "No" --yesno "\nDo you want to update board firmware?" 7 41
  856. fi
  857. if [[ $? -eq 0 ]]; then
  858. debconf-apt-progress -- apt-get update
  859. debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" -y upgrade
  860. [[ -z $scripted ]] && \
  861. dialog --title " Firmware update " --colors --no-label "No" --backtitle "$BACKTITLE" --yesno \
  862. "\nFirmware has been updated. Reboot? " 7 39
  863. if [[ $? -eq 0 ]]; then reboot; fi
  864. fi
  865. fi
  866. ;;
  867. # Install to SATA, eMMC, NAND or USB
  868. #
  869. "Install" )
  870. nand-sata-install
  871. ;;
  872. # Freeze and unfreeze kernel and board support packages
  873. #
  874. "Freeze" | "Defreeze" )
  875. if ! is_package_manager_running; then
  876. if [[ -z $scripted ]]; then dialog --title " Updating " --backtitle "$BACKTITLE" --yes-label "$1" --no-label "Cancel" --yesno \
  877. "\nDo you want to ${1,,} Orange Pi firmware updates?" 7 54
  878. fi
  879. if [[ $? -eq 0 ]]; then
  880. unset PACKAGE_LIST
  881. # basic packages
  882. check_if_installed linux-u-boot-${BOARD}-${BRANCH} && PACKAGE_LIST+=" linux-u-boot-${BOARD}-${BRANCH}"
  883. check_if_installed linux-image-${BRANCH}-${LINUXFAMILY} && PACKAGE_LIST+=" linux-image-${BRANCH}-${LINUXFAMILY}"
  884. check_if_installed linux-dtb-${BRANCH}-${LINUXFAMILY} && PACKAGE_LIST+=" linux-dtb-${BRANCH}-${LINUXFAMILY}"
  885. check_if_installed linux-headers-${BRANCH}-${LINUXFAMILY} && PACKAGE_LIST+=" linux-headers-${BRANCH}-${LINUXFAMILY}"
  886. # new BSP
  887. check_if_installed orangepi-${LINUXFAMILY} && PACKAGE_LIST+=" orangepi-${LINUXFAMILY}"
  888. check_if_installed orangepi-${BOARD} && PACKAGE_LIST+=" orangepi-${BOARD}"
  889. check_if_installed orangepi-${DISTROID} && PACKAGE_LIST+=" orangepi-${DISTROID}"
  890. check_if_installed orangepi-${DISTROID}-desktop-xfce && PACKAGE_LIST+=" orangepi-${DISTROID}-desktop-xfce"
  891. check_if_installed orangepi-firmware && PACKAGE_LIST+=" orangepi-firmware"
  892. check_if_installed orangepi-firmware-full && PACKAGE_LIST+=" orangepi-firmware-full"
  893. local words=( $PACKAGE_LIST )
  894. local command="unhold"
  895. IFS=" "
  896. [[ $1 == "Freeze" ]] && local command="hold"
  897. for word in $PACKAGE_LIST; do apt-mark $command $word; done | dialog --backtitle "$BACKTITLE" --title "Packages ${1,,}" --progressbox $((${#words[@]}+2)) 64
  898. fi
  899. fi
  900. ;;
  901. # Switch to other kernel versions
  902. "Other")
  903. if ! is_package_manager_running; then
  904. other_kernel_version
  905. fi
  906. ;;
  907. # Enable or disable desktop
  908. #
  909. "Desktop" )
  910. if [[ -n $DISPLAY_MANAGER ]]; then
  911. dialog --title " Desktop is enabled and running " --backtitle "$BACKTITLE" \
  912. --yes-label "Stop" --no-label "Cancel" --yesno "\nDo you want to stop and disable this service?" 7 50
  913. exitstatus=$?;
  914. if [[ $exitstatus = 0 ]]; then
  915. function stop_display()
  916. {
  917. bash -c "service lightdm stop >/dev/null 2>&1
  918. systemctl disable lightdm.service >/dev/null 2>&1
  919. service nodm stop >/dev/null 2>&1
  920. systemctl disable nodm.service >/dev/null 2>&1"
  921. }
  922. if xhost >& /dev/null ; then
  923. stop_display &
  924. else
  925. stop_display
  926. fi
  927. fi
  928. else
  929. if ! is_package_manager_running; then
  930. # remove nodm and install lightdm = backward compatibility
  931. [[ -n $(dpkg -l | grep nodm) ]] && debconf-apt-progress -- apt-get -y purge nodm
  932. [[ -z $(dpkg -l | grep lightdm) ]] && debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confold" -y --no-install-recommends install lightdm-gtk-greeter lightdm
  933. if [[ -n $DESKTOP_INSTALLED ]]; then
  934. dialog --title " Display manager " --backtitle "$BACKTITLE" --yesno "\nDo you want to enable autologin?" 7 36
  935. exitstatus=$?;
  936. if [[ $exitstatus = 0 ]]; then
  937. add_choose_user
  938. if [ -n "$CHOSEN_USER" ]; then
  939. mkdir -p /etc/lightdm/lightdm.conf.d
  940. echo "[Seat:*]" > /etc/lightdm/lightdm.conf.d/22-orangepi-autologin.conf
  941. echo "autologin-user=$CHOSEN_USER" >> /etc/lightdm/lightdm.conf.d/22-orangepi-autologin.conf
  942. echo "autologin-user-timeout=0" >> /etc/lightdm/lightdm.conf.d/22-orangepi-autologin.conf
  943. echo "user-session=xfce" >> /etc/lightdm/lightdm.conf.d/22-orangepi-autologin.conf
  944. ln -s /lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service >/dev/null 2>&1
  945. service lightdm start >/dev/null 2>&1
  946. fi
  947. else
  948. rm /etc/lightdm/lightdm.conf.d/22-orangepi-autologin.conf >/dev/null 2>&1
  949. ln -s /lib/systemd/system/lightdm.service /etc/systemd/system/display-manager.service >/dev/null 2>&1
  950. service lightdm start >/dev/null 2>&1
  951. fi
  952. # kill this bash script after desktop is up and if executed on console
  953. [[ $(tty | sed -e "s:/dev/::") == tty* ]] && kill -9 $$
  954. fi
  955. fi
  956. fi
  957. ;;
  958. "Default" )
  959. configure_desktop "--install-recommends"
  960. ;;
  961. "RDP" )
  962. if [[ -n $(service xrdp status | grep -w active) ]]; then
  963. systemctl stop xrdp.service >/dev/null 2>&1
  964. systemctl disable xrdp.service >/dev/null 2>&1
  965. else
  966. if ! is_package_manager_running; then
  967. debconf-apt-progress -- apt-get -y install xrdp vnc4server xorgxrdp
  968. systemctl enable xrdp.service >/dev/null 2>&1
  969. systemctl start xrdp.service >/dev/null 2>&1
  970. dialog --title "Info" --backtitle "$BACKTITLE" --nocancel --no-collapse --pause \
  971. "\nRemote graphical login to $BOARD_NAME using Microsoft Remote Desktop Protocol (RDP) is enabled." 11 57 3
  972. fi
  973. fi
  974. ;;
  975. "Thunderbird" )
  976. if ! check_if_installed thunderbird then ; then
  977. debconf-apt-progress -- apt-get -y install thunderbird
  978. else
  979. debconf-apt-progress -- apt-get -y purge thunderbird
  980. fi
  981. ;;
  982. "Gimp" )
  983. if ! check_if_installed gimp then ; then
  984. debconf-apt-progress -- apt-get -y install gimp
  985. else
  986. debconf-apt-progress -- apt-get -y purge gimp
  987. fi
  988. ;;
  989. "Libre" )
  990. debconf-apt-progress -- apt-get -y purge libreoffice*
  991. ;;
  992. "Writer" )
  993. pkg_install="libreoffice-writer libreoffice-style-tango"
  994. if [[ "$DISTROID" == "xenial" ]]; then pkg_install+=" libreoffice-gtk"; else pkg_install+=" libreoffice-gtk2"; fi
  995. debconf-apt-progress -- apt-get -y install $pkg_install
  996. ;;
  997. "Suite" )
  998. pkg_install="libreoffice libreoffice-style-tango"
  999. if [[ "$DISTROID" == "xenial" ]]; then pkg_install+=" libreoffice-gtk"; else pkg_install+=" libreoffice-gtk2"; fi
  1000. debconf-apt-progress -- apt-get -y install $pkg_install
  1001. ;;
  1002. # Stop low-level messages on console
  1003. #
  1004. "Lowlevel" )
  1005. dialog --title " Kernel messages " --backtitle "$BACKTITLE" --help-button \
  1006. --help-label "Yes & reboot" --yes-label "Yes" --no-label "Cancel" --yesno "\nStop low-level messages on console?" 7 64
  1007. exitstatus=$?;
  1008. [[ $exitstatus = 0 ]] && sed -i 's/^#kernel.printk\(.*\)/kernel.printk\1/' /etc/sysctl.conf
  1009. [[ $exitstatus = 2 ]] && sed -i 's/^#kernel.printk\(.*\)/kernel.printk\1/' /etc/sysctl.conf && reboot
  1010. ;;
  1011. # CPU speed and governor
  1012. #
  1013. "CPU" )
  1014. POLICY="policy0"
  1015. [[ $(grep -c '^processor' /proc/cpuinfo) -gt 4 ]] && POLICY="policy4"
  1016. [[ ! -d /sys/devices/system/cpu/cpufreq/policy4 ]] && POLICY="policy0"
  1017. generic_select "$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_available_frequencies)" "Select minimum CPU speed"
  1018. MIN_SPEED=$PARAMETER
  1019. generic_select "$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_available_frequencies)" "Select maximum CPU speed" "$PARAMETER"
  1020. MAX_SPEED=$PARAMETER
  1021. generic_select "$(cat /sys/devices/system/cpu/cpufreq/$POLICY/scaling_available_governors)" "Select CPU governor"
  1022. GOVERNOR=$PARAMETER
  1023. if [[ -n $MIN_SPEED && -n $MAX_SPEED && -n $GOVERNOR ]]; then
  1024. dialog --colors --title " Apply and save changes " --backtitle "$BACKTITLE" --yes-label "OK" --no-label "Cancel" --yesno \
  1025. "\nCPU frequency will be within \Z1$(($MIN_SPEED / 1000))\Z0 and \Z1$(($MAX_SPEED / 1000)) MHz\Z0. The governor \Z1$GOVERNOR\Z0 will decide which speed to use within this range." 9 58
  1026. if [[ $? -eq 0 ]]; then
  1027. sed -i "s/MIN_SPEED=.*/MIN_SPEED=$MIN_SPEED/" /etc/default/cpufrequtils
  1028. sed -i "s/MAX_SPEED=.*/MAX_SPEED=$MAX_SPEED/" /etc/default/cpufrequtils
  1029. sed -i "s/GOVERNOR=.*/GOVERNOR=$GOVERNOR/" /etc/default/cpufrequtils
  1030. systemctl restart cpufrequtils
  1031. sync
  1032. fi
  1033. fi
  1034. ;;
  1035. "Avahi")
  1036. if ! is_package_manager_running; then
  1037. if check_if_installed avahi-daemon ; then
  1038. service avahi-daemon stop
  1039. debconf-apt-progress -- apt-get -y purge avahi-daemon
  1040. else
  1041. debconf-apt-progress -- apt-get -y install avahi-daemon
  1042. [[ -f /usr/share/doc/avahi-daemon/examples/sftp-ssh.service ]] && cp /usr/share/doc/avahi-daemon/examples/sftp-ssh.service /etc/avahi/services/
  1043. [[ -f /usr/share/doc/avahi-daemon/examples/ssh.service ]] && cp /usr/share/doc/avahi-daemon/examples/ssh.service /etc/avahi/services/
  1044. service avahi-daemon restart
  1045. fi
  1046. fi
  1047. ;;
  1048. # Edit boot environment
  1049. #
  1050. "Bootenv" )
  1051. dialog --title " Edit u-boot environment " --ok-label "Save" \
  1052. --no-collapse --editbox /boot/orangepiEnv.txt 30 0 2> /boot/orangepiEnv.txt.out
  1053. [[ $? = 0 ]] && mv /boot/orangepiEnv.txt.out /boot/orangepiEnv.txt
  1054. sync
  1055. ;;
  1056. # Edit boot script
  1057. #
  1058. "Bootscript" )
  1059. if [[ -f /boot/boot.ini ]]; then
  1060. dialog --title " Edit boot.ini script " --ok-label "Save" \
  1061. --no-collapse --editbox /boot/boot.ini 30 0 2> /boot/boot.ini.out
  1062. [[ $? = 0 ]] && mv /boot/boot.ini.out /boot/boot.ini
  1063. fi
  1064. ;;
  1065. # Toggle overlay items
  1066. #
  1067. "Hardware" )
  1068. # check if user agree to enter this area
  1069. CHANGES="false"
  1070. while true; do
  1071. overlay_prefix=$(cat /boot/orangepiEnv.txt | grep overlay_prefix | sed 's/overlay_prefix=//g')
  1072. TARGET_BRANCH=$BRANCH
  1073. exceptions "$BRANCH"
  1074. MOTD=()
  1075. LINES=()
  1076. LIST_CONST=-3
  1077. j=0
  1078. DIALOG_CANCEL=1
  1079. DIALOG_ESC=255
  1080. while read line
  1081. do
  1082. STATUS=$([[ -n $(cat /boot/orangepiEnv.txt | grep overlays | grep -w ${line}) ]] && echo "on")
  1083. DESC=$(description "$line")
  1084. MOTD+=( "$line" "$DESC" "$STATUS")
  1085. LINES[ $j ]=$line
  1086. (( j++ ))
  1087. done < <(ls -1 ${OVERLAYDIR}/${overlay_prefix}*.dtbo | sed 's/^.*\('${overlay_prefix}'.*\)/\1/g' | sed 's/'${overlay_prefix}'-//g' | sed 's/.dtbo//g' )
  1088. exec 3>&1
  1089. selection=$(dialog --backtitle "$BACKTITLE" --colors --title "Toggle hardware configuration" --clear --cancel-label \
  1090. "Back" --ok-label "Save" --checklist "\nUse \Z1<space>\Z0 to toggle functions and save them. Exit when you are done.\n " \
  1091. 0 0 0 "${MOTD[@]}" 2>&1 1>&3)
  1092. exit_status=$?
  1093. exec 3>&-
  1094. case $exit_status in
  1095. $DIALOG_ESC)
  1096. break
  1097. ;;
  1098. 0)
  1099. CHANGES="true"
  1100. newoverlays="$(echo "$selection" | sed "s|[^ ]* *|&|g")"
  1101. sed -i "s/^overlays=.*/overlays=$newoverlays/" /boot/orangepiEnv.txt
  1102. if ! grep -q "overlays" /boot/orangepiEnv.txt; then echo "overlays=$newoverlays" >> /boot/orangepiEnv.txt; fi
  1103. if [[ -z $newoverlays ]]; then sed -i "/^overlays/d" /boot/orangepiEnv.txt; fi
  1104. sync
  1105. ;;
  1106. 1)
  1107. if [[ "$CHANGES" == "true" ]]; then
  1108. dialog --title " Applying changes " --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1109. --no-label "Cancel" --yesno "\nReboot to enable new features?" 7 34
  1110. if [[ $? = 0 ]]; then reboot; else break; fi
  1111. else
  1112. break
  1113. fi
  1114. ;;
  1115. esac
  1116. done
  1117. ;;
  1118. # Change to other mirrors
  1119. #
  1120. "Mirror" )
  1121. IFS=$'\r\n'
  1122. GLOBIGNORE='*'
  1123. LIST_CONST=3
  1124. BEFORE="$(cat /etc/apt/sources.list.d/orangepi.list | sed 's/http/\nhttp/g' | grep ^http | sed 's/\(^http[^ <]*\)\(.*\)/\1/g' | sed 's/https\?:\/\///')"
  1125. BEFORE_DESC=$(description "${BEFORE}")
  1126. PREFIX="$(echo $BEFORE | cut -f1 -d".")"
  1127. AVAL_MIRROR=()
  1128. if [[ $PREFIX == beta ]]; then
  1129. AVAL_MIRROR=("beta.orangepi.com" "mirrors.netix.net/orangepi/apt/")
  1130. else
  1131. AVAL_MIRROR+=("apt.orangepi.com" "mirrors.tuna.tsinghua.edu.cn/orangepi/" "mirrors.netix.net/orangepi/apt/" "mirrors.dotsrc.org/orangepi-apt/")
  1132. fi
  1133. local LIST=()
  1134. for i in "${AVAL_MIRROR[@]}"
  1135. do
  1136. DESC=$(description "${i[0]}")
  1137. [[ "${i[0]}" != "$BEFORE" ]] && LIST+=( "${i[0]//[[:blank:]]/}" "$DESC" )
  1138. done
  1139. LIST_LENGTH=$(($LIST_CONST+${#LIST[@]}/2));
  1140. if [ "$LIST_LENGTH" -le 3 ]; then
  1141. TARGET_MIRROR=${AVAL_MIRROR[0]}
  1142. dialog --backtitle "$BACKTITLE" --title "Please wait" --colors --msgbox "\nThere are no mirrors available!" 7 35
  1143. else
  1144. exec 3>&1
  1145. TARGET_MIRROR=$(dialog --cancel-label "Cancel" --backtitle "$BACKTITLE" --no-collapse \
  1146. --title "Change repository location" --colors --clear --menu "\nfrom \Z1$BEFORE_DESC\Z0 to:\n " $((6+${LIST_LENGTH})) 60 15 "${LIST[@]}" 2>&1 1>&3)
  1147. exitstatus=$?;
  1148. exec 3>&-
  1149. fi
  1150. if [[ $exitstatus == 0 ]]; then
  1151. sed -i "s~$BEFORE~$TARGET_MIRROR~" /etc/apt/sources.list.d/orangepi.list
  1152. dialog --backtitle "$BACKTITLE" --title "Info" --colors --msgbox "\nOrange Pi package repository was switched to:\n\n\Z1$TARGET_MIRROR\Z0" 9 47
  1153. fi
  1154. ;;
  1155. # Toggle welcome screen items
  1156. #
  1157. "Welcome" )
  1158. while true; do
  1159. HOME="/etc/update-motd.d/"
  1160. MOTD=()
  1161. LINES=()
  1162. LIST_CONST=9
  1163. j=0
  1164. DIALOG_CANCEL=1
  1165. DIALOG_ESC=255
  1166. while read line
  1167. do
  1168. STATUS=$([[ -x ${HOME}${line} ]] && echo "on")
  1169. DESC=$(description "$line")
  1170. MOTD+=( "$line" "$DESC" "$STATUS")
  1171. LINES[ $j ]=$line
  1172. (( j++ ))
  1173. done < <(ls -1 $HOME)
  1174. LISTLENGTH="$(($LIST_CONST+${#MOTD[@]}/3))"
  1175. exec 3>&1
  1176. selection=$(dialog --backtitle "$BACKTITLE" --title "Toggle motd executing scripts" --clear --cancel-label \
  1177. "Back" --ok-label "Save" --checklist "\nChoose what you want to enable or disable:\n " \
  1178. $LISTLENGTH 80 15 "${MOTD[@]}" 2>&1 1>&3)
  1179. exit_status=$?
  1180. exec 3>&-
  1181. case $exit_status in
  1182. $DIALOG_CANCEL | $DIALOG_ESC)
  1183. break
  1184. ;;
  1185. 0)
  1186. chmod -x ${HOME}*
  1187. chmod +x $(echo "$selection" | sed "s|[^ ]* *|${HOME}&|g")
  1188. ;;
  1189. esac
  1190. done
  1191. ;;
  1192. # Toggle sshd options
  1193. #
  1194. "SSH" )
  1195. if ! is_package_manager_running; then
  1196. while true; do
  1197. if ! check_if_installed libpam-google-authenticator ; then
  1198. debconf-apt-progress -- apt-get -y install libpam-google-authenticator
  1199. fi
  1200. if ! check_if_installed qrencode ; then
  1201. debconf-apt-progress -- apt-get -y install qrencode
  1202. fi
  1203. DIALOG_CANCEL=2
  1204. DIALOG_ESC=255
  1205. LIST_CONST=9
  1206. WINDOW_SIZE=21
  1207. # variables cleanup
  1208. PermitRootLogin="";
  1209. PubkeyAuthentication="";
  1210. PasswordAuthentication="";
  1211. PhoneAuthentication=""
  1212. MergeParameter="";
  1213. ExtraDesc="";
  1214. Buttons="--no-cancel --ok-label "Save" --help-button --help-label Cancel"
  1215. # read values
  1216. [[ $(grep "^PermitRootLogin" /etc/ssh/sshd_config | awk '{print $2}') == "yes" ]] && PermitRootLogin="on"
  1217. [[ $(grep "^@include common-auth" /etc/pam.d/sshd | awk '{print $2}') == "common-auth" ]] && PasswordAuthentication="on"
  1218. [[ $(grep "^PubkeyAuthentication" /etc/ssh/sshd_config | awk '{print $2}') == "yes" ]] && PubkeyAuthentication="on"
  1219. [[ -n $(grep "pam_google_authenticator.so" /etc/pam.d/sshd) ]] && PhoneAuthentication="on"
  1220. # create menu
  1221. MOTD=( "PermitRootLogin" "Allow root login" "$PermitRootLogin" )
  1222. MOTD+=( "PasswordAuthentication" "Password login" "$PasswordAuthentication" )
  1223. MOTD+=( "PubkeyAuthentication" "SSH key login" "$PubkeyAuthentication" )
  1224. MOTD+=( "PhoneAuthentication" "Google two-step authentication with one-time passcode" "$PhoneAuthentication" )
  1225. Buttons="--no-cancel --ok-label "Save" --help-button --help-label Cancel"
  1226. if [[ $PhoneAuthentication == "on" ]]; then
  1227. Buttons="--cancel-label Generate-token --ok-label "Save" --help-button --help-label Cancel"
  1228. ExtraDesc="\n\Z1Note:\Z0 Two-step verification token is identical for all users on the system.\n \n"
  1229. LIST_CONST=11
  1230. if [[ -f ~/.google_authenticator ]]; then
  1231. Buttons="--cancel-label New-token --ok-label "Save" --help-button --help-label Cancel --extra-button --extra-label Show-token"
  1232. fi
  1233. fi
  1234. LISTLENGTH="$((${#MOTD[@]}/3))"
  1235. HEIGHT="$((LISTLENGTH + $LIST_CONST))"
  1236. exec 3>&1
  1237. selection=$(dialog --colors $Buttons --backtitle "$BACKTITLE" --title " Toggle sshd options " --clear --checklist \
  1238. "\nChoose what you want to enable or disable:\n $ExtraDesc" $HEIGHT 0 $LISTLENGTH "${MOTD[@]}" 2>&1 1>&3)
  1239. exit_status=$?
  1240. exec 3>&-
  1241. case $exit_status in
  1242. $DIALOG_CANCEL | $DIALOG_ESC)
  1243. break
  1244. ;;
  1245. 0)
  1246. # read values, adjust config and restart service
  1247. my_array=($selection)
  1248. for((n=0;n<${#MOTD[@]};n++)); do
  1249. if (( $(($n % 3 )) == 0 )); then
  1250. # generic options if any
  1251. if [[ " ${my_array[*]} " == *" ${MOTD[$n]} "* ]]; then
  1252. sed -i "s/^#\?${MOTD[$n]}.*/${MOTD[$n]} yes/" /etc/ssh/sshd_config
  1253. else
  1254. sed -i "s/^#\?${MOTD[$n]}.*/${MOTD[$n]} no/" /etc/ssh/sshd_config
  1255. fi
  1256. if [[ $n -eq 0 ]]; then
  1257. # phone
  1258. if [[ " ${my_array[*]} " == *" PhoneAuthentication "* ]]; then
  1259. MergeParameter="keyboard-interactive"
  1260. sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/" /etc/ssh/sshd_config
  1261. sed -i -n '/password updating/{p;:a;N;/@include common-password/!ba;s/.*\n/auth required pam_google_authenticator.so nullok\n/};p' /etc/pam.d/sshd
  1262. else
  1263. MergeParameter=""
  1264. sed -i '/^auth required pam_google_authenticator.so nullok/ d' /etc/pam.d/sshd
  1265. sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/" /etc/ssh/sshd_config
  1266. fi
  1267. # password
  1268. if [[ " ${my_array[*]} " == *" PasswordAuthentication "* ]]; then
  1269. MergeParameter="password keyboard-interactive"
  1270. sed -i "s/^#\?PasswordAuthentication.*/PasswordAuthentication yes/" /etc/ssh/sshd_config
  1271. sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/" /etc/ssh/sshd_config
  1272. sed -i "s/^\#@include common-auth/\@include common-auth/" /etc/pam.d/sshd
  1273. else
  1274. sed -i "s/^#\?PasswordAuthentication.*/PasswordAuthentication no/" /etc/ssh/sshd_config
  1275. #sed -i "s/^#\?ChallengeResponseAuthentication.*/ChallengeResponseAuthentication no/" /etc/ssh/sshd_config
  1276. sed -i "s/^\@include common-auth/\#@include common-auth/" /etc/pam.d/sshd
  1277. fi
  1278. # pubkey
  1279. if [[ " ${my_array[*]} " == *" PubkeyAuthentication "* ]]; then
  1280. MergeParameter="publickey keyboard-interactive "
  1281. sed -i "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/" /etc/ssh/sshd_config
  1282. else
  1283. sed -i "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication no/" /etc/ssh/sshd_config
  1284. fi
  1285. if [[ " ${my_array[*]} " == *" PubkeyAuthentication "* && " ${my_array[*]} " == *" PhoneAuthentication "* ]]; then
  1286. MergeParameter="publickey,password publickey,keyboard-interactive"
  1287. sed -i "s/^#\?PubkeyAuthentication.*/PubkeyAuthentication yes/" /etc/ssh/sshd_config
  1288. fi
  1289. fi
  1290. fi
  1291. done
  1292. if [[ -z $MergeParameter ]]; then
  1293. sed -i '/^AuthenticationMethods.*/ d' /etc/ssh/sshd_config
  1294. else
  1295. sed -i '/^AuthenticationMethods.*/ d' /etc/ssh/sshd_config
  1296. sed -i -n '/and ChallengeResponseAuthentication to/{p;:a;N;/UsePAM yes/!ba;s/.*\n/AuthenticationMethods '"$MergeParameter"'\n/};p' /etc/ssh/sshd_config
  1297. fi
  1298. # reload sshd
  1299. systemctl restart sshd.service
  1300. ;;
  1301. 3)
  1302. display_qr_code
  1303. ;;
  1304. 1)
  1305. dialog --colors --title " \Z1Warning\Z0 " --backtitle "$BACKTITLE" --yes-label "Generate" --no-label "No" --yesno "\nWhen you generate new token you have to scan it with your mobile device again.\n\nUnderstand?" 10 48
  1306. if [[ $? = 0 ]]; then
  1307. google-authenticator -t -d -f -r 3 -R 30 -W -q
  1308. google_token_allusers
  1309. display_qr_code
  1310. fi
  1311. ;;
  1312. esac
  1313. done
  1314. fi
  1315. ;;
  1316. # Switch to daily builds
  1317. #
  1318. "Nightly" )
  1319. if ! is_package_manager_running; then
  1320. [[ -z $scripted ]] &&
  1321. dialog --colors --title " \Z1Warning\Z0 " --backtitle "$BACKTITLE" --yes-label "Yes" \
  1322. --no-label "No" --yesno \
  1323. "\nYou are switching to an untested auto-build repository which might break your system.\n\nContinue?" 10 48
  1324. if [[ $? = 0 || -n $scripted ]]; then
  1325. sed -i 's/^deb http:\/\/[^ ]*/deb http:\/\/beta.armbian.com/' /etc/apt/sources.list.d/armbian.list
  1326. reload_bsp $branch
  1327. fi
  1328. fi
  1329. ;;
  1330. # Switch to stable builds
  1331. #
  1332. "Stable" )
  1333. if ! is_package_manager_running; then
  1334. [[ -z $scripted ]] &&
  1335. dialog --colors --title " \Z1Warning\Z0 " --backtitle "$BACKTITLE" --yes-label "Yes" \
  1336. --no-label "No" --yesno \
  1337. "\nYou are switching to a stable repository where you will receive future updates.\n\nContinue?" 9 44
  1338. if [[ $? = 0 || -n $scripted ]]; then
  1339. sed -i 's/^deb http:\/\/beta/deb http:\/\/apt/' /etc/apt/sources.list.d/armbian.list
  1340. reload_bsp $branch
  1341. fi
  1342. fi
  1343. ;;
  1344. # Switch to alternative configurations
  1345. #
  1346. "DTB" )
  1347. if ! is_package_manager_running; then
  1348. aval_dtbs
  1349. if [[ $exitstatus = 0 ]]; then
  1350. BOX_LENGTH=$((${#TARGET_BOARD}+28));
  1351. dialog --title "Switching board config" --backtitle "$BACKTITLE" --yes-label "Reboot" --no-label "Cancel" --yesno "\nReboot to $TARGET_BOARD settings?" 7 $BOX_LENGTH
  1352. if [[ $? = 0 ]]; then
  1353. sed -i "s/^fdt_file=.*/fdt_file=$TARGET_BOARD/" /boot/orangepiEnv.txt 2> /dev/null && grep -q "fdt_file=$TARGET_BOARD" /boot/orangepiEnv.txt 2> /dev/null || echo "fdt_file=$TARGET_BOARD" >> /boot/orangepiEnv.txt
  1354. [[ "$LINUXFAMILY" = odroidxu4 ]] && sed -i "s/^fdt_file/board_name/" /boot/orangepiEnv.txt && sed -i "s/^BOARD_NAME.*/BOARD_NAME=\"Odroid ${TARGET_BOARD^^}\"/" /etc/orangepi-release
  1355. reboot;
  1356. fi
  1357. fi
  1358. fi
  1359. ;;
  1360. # Toggle virtual read-only root filesystem
  1361. #
  1362. "Overlayroot" )
  1363. #if ! is_package_manager_running; then
  1364. # if [[ -n $(mount | grep -w overlay | grep -v chromium) ]]; then
  1365. # dialog --title " Root overlay " --backtitle "$BACKTITLE" --yes-label "Disable" \
  1366. # --no-label "Cancel" \
  1367. # --yesno "\nYour system is already virtual read-only.\n\nDo you want to disable this feature and reboot?" 9 60
  1368. # [[ $? = 0 ]] && overlayroot-chroot sed -i "s/^overlayroot=.*/overlayroot=\"\"/" /etc/overlayroot.conf && \
  1369. # overlayroot-chroot rm /etc/update-motd.d/97-overlayroot && reboot
  1370. # else
  1371. # debconf-apt-progress -- apt-get -o Dpkg::Options::="--force-confnew" -y --no-install-recommends install overlayroot
  1372. # echo '#!/bin/bash' > /etc/update-motd.d/97-overlayroot
  1373. # echo 'if [ -n "$(mount | grep -w tmpfs-root)" ]; then \
  1374. # echo -e "[\e[0m \e[1mremember: your system is in virtual read only mode\e[0m ]\n";fi' >> /etc/update-motd.d/97-overlayroot
  1375. # chmod +x /etc/update-motd.d/97-overlayroot
  1376. # dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1377. # --no-label "Cancel" --yesno "\nEnable virtual read-only root and reboot." 7 45
  1378. # [[ ! -f /etc/overlayroot.conf ]] && cp /etc/overlayroot.conf.dpkg-new /etc/overlayroot.conf
  1379. # [[ $? = 0 ]] && sed -i "s/^overlayroot=.*/overlayroot=\"tmpfs\"/" /etc/overlayroot.conf && reboot
  1380. # fi
  1381. #fi
  1382. CONFIG_FILE="/etc/overlayroot.conf"
  1383. if findmnt -n -o SOURCE / | grep -q "overlayroot"; then
  1384. CONFIG_FILE="/media/root-ro/etc/overlayroot.conf"
  1385. OVERLAY_ACTIVE=1
  1386. else
  1387. if ! is_package_manager_running; then
  1388. if ! dpkg -l | grep -q "overlayroot"; then
  1389. debconf-apt-progress -- apt-get update
  1390. if [[ "$DISTROID" == "bookworm" ]]; then
  1391. cat <<-'EOF' > /usr/share/initramfs-tools/hooks/custom
  1392. cp /bin/grep "${DESTDIR}"/bin
  1393. cp /bin/mount "${DESTDIR}"/bin
  1394. cp /lib/aarch64-linux-gnu/libmount.so.1 "${DESTDIR}"/lib
  1395. EOF
  1396. chmod +x /usr/share/initramfs-tools/hooks/custom
  1397. export PATH=$PATH:/usr/sbin
  1398. update-initramfs -u > /dev/null 2>&1
  1399. fi
  1400. apt -y install overlayroot > /dev/null 2>&1
  1401. [[ ! $? == 0 ]] && apt remove --purge -y overlayroot >/dev/null 2>&1 && return
  1402. fi
  1403. else
  1404. return
  1405. fi
  1406. OVERLAY_ACTIVE=0
  1407. fi
  1408. CURRENT_MODE="none"
  1409. CURRENT_DEVICE="N/A"
  1410. if grep -q '^overlayroot="tmpfs"' "$CONFIG_FILE" 2>/dev/null; then
  1411. CURRENT_MODE="tmpfs"
  1412. elif grep -q '^overlayroot="device:dev=' "$CONFIG_FILE" 2>/dev/null; then
  1413. CURRENT_MODE="block"
  1414. CURRENT_DEVICE=$(grep -oP '(?<=overlayroot="device:dev=).*?(?=")' "$CONFIG_FILE")
  1415. elif grep -q '^overlayroot=""' "$CONFIG_FILE" 2>/dev/null; then
  1416. CURRENT_MODE="none"
  1417. fi
  1418. ALL_PARTITIONS=$(lsblk -lnp -o NAME,TYPE | awk '$2=="part" {print $1}' | grep -E '/dev/(mmcblk|nvme|sd)')
  1419. MOUNTED_PARTITIONS=$(findmnt -n -o SOURCE)
  1420. ROOT_SOURCE=$(findmnt -n -o SOURCE /)
  1421. [[ $OVERLAY_ACTIVE == "1" ]] && ROOT_SOURCE=$(findmnt -n -o SOURCE /media/root-ro)
  1422. ROOT_DEVICE=${ROOT_SOURCE%%p*}
  1423. ROOT_PARTITION=${ROOT_SOURCE##*p}
  1424. MENU_OPTIONS=()
  1425. for PART in $ALL_PARTITIONS; do
  1426. if ! grep -q "$PART" <<< "$MOUNTED_PARTITIONS"; then
  1427. DEVICE_NAME=$(echo "$PART" | sed -E 's/p[0-9]+$//')
  1428. PARTITION_NUMBER=$(echo "$PART" | grep -o '[0-9]*$')
  1429. if [[ "$DEVICE_NAME" == "$ROOT_DEVICE" && "$PARTITION_NUMBER" -gt "$ROOT_PARTITION" ]]; then
  1430. MENU_OPTIONS+=("$PART" "Available partition")
  1431. elif [[ "$DEVICE_NAME" != "$ROOT_DEVICE" ]]; then
  1432. MENU_OPTIONS+=("$PART" "Available partition")
  1433. fi
  1434. fi
  1435. done
  1436. NEW_PART="${ROOT_DEVICE}p$((ROOT_PARTITION + 1))"
  1437. if ! grep -q "$NEW_PART" <<< "$ALL_PARTITIONS"; then
  1438. MENU_OPTIONS+=("$NEW_PART" "Potential new partition (p$((ROOT_PARTITION + 1)))")
  1439. fi
  1440. MENU_ITEMS=(
  1441. "none" "disable overlayroot $( [ "$CURRENT_MODE" = "none" ] && echo "(active)" )"
  1442. "tmpfs" "tmpfs mode $( [ "$CURRENT_MODE" = "tmpfs" ] && echo "(active)" )"
  1443. "block" "block device mode $( [ "$CURRENT_MODE" = "block" ] && echo "(active: $CURRENT_DEVICE)" )"
  1444. )
  1445. CHOICE=$(dialog --clear --title "Overlayroot Configuration" --default-item "$CURRENT_MODE" \
  1446. --menu "\nChoose the storage mode:" 12 60 3 "${MENU_ITEMS[@]}" 3>&1 1>&2 2>&3)
  1447. clear
  1448. if [ "$OVERLAY_ACTIVE" -eq 1 ]; then
  1449. #echo "Remounting /media/root-ro as read-write..."
  1450. mount -o remount,rw /media/root-ro
  1451. fi
  1452. case "$CHOICE" in
  1453. "none")
  1454. sed -i "s/^overlayroot=.*/overlayroot=\"\"/" "$CONFIG_FILE"
  1455. if ! grep -q "overlayroot" "$CONFIG_FILE"; then echo "overlayroot=\"\"" >> "$CONFIG_FILE"; fi
  1456. dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1457. --no-label "Cancel" --yesno "\nDisable overlayroot and reboot." 7 45
  1458. [[ $? == 0 ]] && reboot
  1459. ;;
  1460. "tmpfs")
  1461. sed -i "s/^overlayroot=.*/overlayroot=\"$CHOICE\"/" "$CONFIG_FILE"
  1462. if ! grep -q "overlayroot" "$CONFIG_FILE"; then echo "overlayroot=$CHOICE" >> "$CONFIG_FILE"; fi
  1463. dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1464. --no-label "Cancel" --yesno "\nEnable overlayroot and reboot." 7 45
  1465. [[ $? == 0 ]] && reboot
  1466. ;;
  1467. "block")
  1468. if [ ${#MENU_OPTIONS[@]} -eq 0 ]; then
  1469. DEVICE=$(dialog --inputbox "No available partitions detected.\nEnter a block device path manually:" 10 50 "/dev/mmcblk0p2" 3>&1 1>&2 2>&3)
  1470. else
  1471. DEVICE=$(dialog --menu "Select a block device for storage:" 10 60 5 "${MENU_OPTIONS[@]}" 3>&1 1>&2 2>&3)
  1472. fi
  1473. clear
  1474. if [ -n "$DEVICE" ]; then
  1475. sed -i "s|^overlayroot=.*|overlayroot=\"device:dev=$DEVICE\"|" "$CONFIG_FILE"
  1476. if ! grep -q "overlayroot" "$CONFIG_FILE"; then echo "overlayroot=\"device:dev=$DEVICE\"" >> "$CONFIG_FILE"; fi
  1477. sync
  1478. #echo "Overlayroot set to block device mode using $DEVICE."
  1479. if [ "$DEVICE" = "$NEW_PART" ]; then
  1480. if [[ -b "$DEVICE" ]]; then
  1481. if [[ "$(lsblk -no FSTYPE $DEVICE)" != "ext4" ]]; then
  1482. dialog --yesno "Warning: format $DEVICE as ext4? This will erase all data." 10 50
  1483. [[ $? -eq 0 ]] && yes|mkfs.ext4 "$DEVICE"
  1484. dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1485. --no-label "Cancel" --yesno "\nEnable overlayroot and reboot." 7 45
  1486. [[ $? == 0 ]] && reboot
  1487. else
  1488. dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1489. --no-label "Cancel" --yesno "\nEnable overlayroot and reboot." 7 45
  1490. [[ $? == 0 ]] && reboot
  1491. fi
  1492. return
  1493. fi
  1494. dialog --yesno "Warning: Creating a new partition ($DEVICE) may destroy existing data." 10 50
  1495. [[ ! $? -eq 0 ]] && return
  1496. rootfs_size=$(df -BM | grep ^/dev | head -1 | awk '{print $3}' | tr -cd '[0-9]. \n')
  1497. sdsize=$(bc -l <<< "scale=0; ((($rootfs_size * 2) / 1 + 0) / 4 + 1) * 4")
  1498. #echo "sdsize: $sdsize"
  1499. rootsource=$ROOT_SOURCE
  1500. rootdevice=${rootsource%p*}
  1501. partitions=${rootsource##*p}
  1502. lastsector=$(fdisk -l ${rootdevice} |grep "Disk ${rootdevice}" |awk '{print $7}')
  1503. lastsector=$(( $lastsector - 1024 ))
  1504. startfrom=$(fdisk -l ${rootdevice} |grep ${rootsource} |awk '{print $2}')
  1505. partend=$(fdisk -l ${rootdevice} |grep ${rootsource} |awk '{print $3}')
  1506. new_part_size=$(($sdsize * 1024 * 1024 / 512))
  1507. new_partend=$((${new_part_size} + ${startfrom} -1))
  1508. new_partstart=$((${new_partend}+1))
  1509. LOOP=$(losetup -f)
  1510. losetup ${LOOP} ${rootsource}
  1511. e2fsck -f -y ${LOOP}
  1512. resize2fs ${LOOP} $((${new_part_size} / 8))
  1513. (echo d; echo $partitions; echo n; echo p; echo ; echo $startfrom; echo $new_partend ; echo w;)| fdisk $rootdevice
  1514. (echo n; echo p; echo ;echo $new_partstart; echo $lastsector; echo w;)| fdisk $rootdevice
  1515. e2fsck -f -y ${LOOP}
  1516. yes |mkfs.ext4 $DEVICE
  1517. sync
  1518. losetup -d ${LOOP}
  1519. dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1520. --no-label "Cancel" --yesno "\nEnable overlayroot and reboot." 7 45
  1521. [[ $? == 0 ]] && reboot
  1522. else
  1523. #if [[ "$(lsblk -no FSTYPE /dev/sda2)" != "ext4" ]]; then
  1524. dialog --yesno "Warning: format $DEVICE as ext4? This will erase all data." 10 50
  1525. [[ $? -eq 0 ]] && yes|mkfs.ext4 "$DEVICE"
  1526. dialog --title "Root overlay" --backtitle "$BACKTITLE" --yes-label "Reboot" \
  1527. --no-label "Cancel" --yesno "\nEnable overlayroot and reboot." 7 45
  1528. [[ $? == 0 ]] && reboot
  1529. #fi
  1530. fi
  1531. else
  1532. :
  1533. fi
  1534. ;;
  1535. *)
  1536. :
  1537. ;;
  1538. esac
  1539. sync
  1540. ;;
  1541. esac
  1542. [[ -n $scripted ]] && exit
  1543. }