#!/bin/bash # # Copyright (c) 2017 Igor Pecovnik, igor.pecovnik@gma**.com # # This file is licensed under the terms of the GNU General Public # License version 2. This program is licensed "as is" without any # warranty of any kind, whether express or implied. #-----------------------------------------------------------------------------------------------------------------------------------------# # check for root # if [[ $EUID != 0 ]]; then echo "Warning. This script requires root privileges. Exiting ..." sleep 2 exit fi #-----------------------------------------------------------------------------------------------------------------------------------------# # check if we have internet connection to install dependencies # echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1 if [[ $? -ne 0 ]]; then read -n 1 -s -p "Warning. Configurator can't work properly without internet connection. \ Press CTRL C to stop to stop or any key to ignore and continue." else [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' bc 2>/dev/null) != *ii* ]] && \ apt-get -qq -y --no-install-recommends install bc [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' expect 2>/dev/null) != *ii* ]] && \ apt-get -qq -y --no-install-recommends install expect [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' rcconf 2>/dev/null) != *ii* ]] && \ apt-get -qq -y --no-install-recommends install rcconf [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' dialog 2>/dev/null) != *ii* ]] && \ apt-get -qq -y --no-install-recommends install dialog [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' network-manager 2>/dev/null) != *ii* ]] && \ apt-get -qq -y --no-install-recommends install network-manager [[ $(dpkg-query -W -f='${db:Status-Abbrev}\n' sunxi-tools 2>/dev/null) != *ii* ]] && \ apt-get -qq -y --no-install-recommends install sunxi-tools fi #-----------------------------------------------------------------------------------------------------------------------------------------# # # show IP addresses # function get_ip_addresses() { local ips=() for f in /sys/class/net/*; do local intf=$(basename $f) # match only interface names starting with e (Ethernet), w (wireless), r (some Ralink drivers use ra format) if [[ $intf =~ ^[ewr].* ]]; then local tmp=$(ip -4 addr show dev $intf | awk '/inet/ {print $2}' | cut -d'/' -f1) # add both name and IP - can be informative but becomes ugly with long persistent/predictable device names #[[ -n $tmp ]] && ips+=("$intf: $tmp") # add IP only [[ -n $tmp ]] && ips+=("$tmp") fi done [[ -n "$ips" ]] && echo "at ${ips[@]}" } # get_ip_addresses #-----------------------------------------------------------------------------------------------------------------------------------------# # gather info about the board and start with loading menu # [[ -f /etc/armbian-release ]] && source /etc/armbian-release && ARMBIAN="Armbian $VERSION $IMAGE_TYPE"; DISTRO=$(lsb_release -is) DISTROID=$(lsb_release -sc) KERNELID=$(uname -r) WIFICONNECTED=$(nmcli -f NAME connection show --active | tail -n +2 | tail -1) BACKTITLE="Configuration utility, $ARMBIAN, https://www.armbian.com" TITLE="$BOARD_NAME " IPADDRESS=$(get_ip_addresses) dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nLoading Armbian configuration utility ... " 5 45 #-----------------------------------------------------------------------------------------------------------------------------------------# # # Check if something is running on port $1 and display info # check_port () { [[ -n $(netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".'$1'"') ]] && dialog --backtitle "$BACKTITLE" --title "Checking service" \ --msgbox "\nIt looks good.\n\nThere is $2 service on port $1" 9 52 } #-----------------------------------------------------------------------------------------------------------------------------------------# # # show disclaimer # function beta_disclaimer () { exec 3>&1 ACKNOWLEDGEMENT=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse --title "Warning" --clear \--radiolist "\n$1.\n \n" 12 56 7 "Yes, I understand" "" off 2>&1 1>&3) exec 3>&- } #-----------------------------------------------------------------------------------------------------------------------------------------# # # show description for MOTD files # function description { case $1 in *header*) echo "Big board logo and kernel info" ;; *sysinfo*) echo "Sysinfo - load, ip, memory, uptime, ..." ;; *tips*) echo "Shows tip of the day" ;; *updates*) echo "Display number of avaliable updates" ;; *armbian-config*) echo "Show command for system configuration" ;; *autoreboot-warn*) echo "Show warning when reboot is needed" ;; *) echo "" ;; esac } #-----------------------------------------------------------------------------------------------------------------------------------------# # edit hostapd parameters # function wlan_edit () { source /etc/hostapd.conf exec 3>&1 dialog --title "AP configuration" --backtitle "$BACKTITLE" --form "\nWPA2 enabled, \ advanced config: edit /etc/hostapd.conf\n " 12 58 0 \ "SSID:" 1 1 "$ssid" 1 31 22 0 \ "Password:" 2 1 "$wpa_passphrase" 2 31 22 0 \ "Channel:" 3 1 "$channel" 3 31 3 0 \ 2>&1 1>&3 | { read -r ssid;read -r wpa_passphrase;read -r channel if [[ $? = 0 ]]; then sed -i "s/^ssid=.*/ssid=$ssid/" /etc/hostapd.conf sed -i "s/^wpa_passphrase=.*/wpa_passphrase=$wpa_passphrase/" /etc/hostapd.conf sed -i "s/^channel=.*/channel=$channel/" /etc/hostapd.conf wpa_psk=$(wpa_passphrase $ssid $wpa_passphrase | grep '^[[:blank:]]*[^[:blank:]#;]' | grep psk | cut -d= -f2-) sed -i "s/^wpa_psk=.*/wpa_psk=$wpa_psk/" /etc/hostapd.conf fi } } #-----------------------------------------------------------------------------------------------------------------------------------------# # naming exceptions for packages # function exceptions () { TARGET_FAMILY=$LINUXFAMILY UBOOT_BRANCH=$TARGET_BRANCH # uboot naming is different case $BOARD in cubietruck | cubieboard2 | bananapipro | lamobo-r1 | orangepi | orangepimini | lime* | micro | pcduino3 | pcduino3nano) if [[ $TARGET_BRANCH == "default" ]]; \ then TARGET_FAMILY="sun7i"; TARGET_BRANCH=""; else TARGET_FAMILY="sunxi"; TARGET_BRANCH="-"$TARGET_BRANCH; fi ;; cubieboard | lime-a10 | pcduino2) if [[ $TARGET_BRANCH == "default" ]]; \ then TARGET_FAMILY="sun4i"; TARGET_BRANCH=""; else TARGET_FAMILY="sunxi"; TARGET_BRANCH="-"$TARGET_BRANCH; fi ;; *) if [[ $TARGET_BRANCH == "default" ]]; \ then TARGET_BRANCH=""; else TARGET_BRANCH="-"$TARGET_BRANCH; fi esac } #-----------------------------------------------------------------------------------------------------------------------------------------# # here we add wifi exceptions # function wlan_exceptions () { [[ -n "$(lsmod | grep -w dhd)" && $1 = "on" ]] && \ echo 'options dhd op_mode=2' >/etc/modprobe.d/ap6212.conf && rmmod dhd && modprobe dhd [[ -n "$(lsmod | grep -w dhd)" && $1 = "off" ]] && \ rm /etc/modprobe.d/ap6212.conf && rmmod dhd && modprobe dhd } #-----------------------------------------------------------------------------------------------------------------------------------------# # check if board has alternative kernels # function aval_kernel () { IFS=$'\r\n' GLOBIGNORE='*' AVAL_KERNEL=($(apt-cache search --names-only '^linux-'$(lsb_release -cs)'-root.*.'$BOARD'*' \ | grep -w "$BOARD " | sed 's/.*(\(.*\))/\1/' | awk '{print $1}' | grep -v "$BRANCH" )) local LIST=() for i in "${AVAL_KERNEL[@]}" do LIST+=( "${i[0]//[[:blank:]]/}" "" ) done LIST_LENGHT=$((${#LIST[@]}/2)); if [ "$LIST_LENGHT" -eq 1 ]; then TARGET_BRANCH=${AVAL_KERNEL[0]} else exec 3>&1 TARGET_BRANCH=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \ --title "Upgrade from $BRANCH to:" --clear --menu "" $((6+${LIST_LENGHT})) 40 15 "${LIST[@]}" 2>&1 1>&3) exec 3>&- fi } #-----------------------------------------------------------------------------------------------------------------------------------------# # search for wlan interfaces and provide a selection menu if there are more than one # function get_wlan_interface () { IFS=$'\r\n' GLOBIGNORE='*' WLAN_INTERFACES=($(nmcli dev status | grep wifi |awk '{print $1}')) local LIST=() for i in "${WLAN_INTERFACES[@]}" do LIST+=( "${i[0]//[[:blank:]]/}" "" ) done LIST_LENGHT=$((${#LIST[@]}/2)); if [ "$LIST_LENGHT" -eq 1 ]; then WIRELESS_ADAPTER=${WLAN_INTERFACES[0]} else exec 3>&1 WIRELESS_ADAPTER=$(dialog --nocancel --backtitle "$BACKTITLE" --no-collapse \ --title "Select interface" --clear --menu "" $((6+${LIST_LENGHT})) 30 15 "${LIST[@]}" 2>&1 1>&3) exec 3>&- fi } # search for BT devices and connect # function connect_bt_interface () { IFS=$'\r\n' GLOBIGNORE='*' dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nDiscovering Bluetooth devices ... " 5 37 BT_INTERFACES=($(hcitool scan | sed '1d')) local LIST=() for i in "${BT_INTERFACES[@]}" do local a=$(echo ${i[0]//[[:blank:]]/} | sed -e 's/^\(.\{17\}\).*/\1/') local b=${i[0]//$a/} local b=$(echo $b | sed -e 's/^[ \t]*//') LIST+=( "$a" "$b") done LIST_LENGHT=$((${#LIST[@]}/2)); if [ "$LIST_LENGHT" -eq 0 ]; then BT_ADAPTER=${WLAN_INTERFACES[0]} dialog --backtitle "$BACKTITLE" --title "Bluetooth" --msgbox "\nNo nearby Bluetooth devices were found!" 7 43 else exec 3>&1 BT_ADAPTER=$(dialog --backtitle "$BACKTITLE" --no-collapse --title "Select interface" \ --clear --menu "" $((6+${LIST_LENGHT})) 50 15 "${LIST[@]}" 2>&1 1>&3) exec 3>&- if [[ $BT_ADAPTER != "" ]]; then dialog --backtitle "$BACKTITLE" --title "Please wait" --infobox "\nConnecting to $BT_ADAPTER " 5 35 BT_EXEC=$(expect -c 'set prompt "#";set address '$BT_ADAPTER';spawn bluetoothctl;expect -re $prompt;send "disconnect $address\r";sleep 1;send "remove $address\r";sleep 1;expect -re $prompt;send "scan on\r";sleep 8;send "scan off\r";expect "Controller";send "trust $address\r";sleep 2;send "pair $address\r";sleep 2;send "connect $address\r";send_user "\nShould be paired now.\r";sleep 2;send "quit\r";expect eof') echo "$BT_EXEC" > /tmp/bt-connect-debug.log if [[ $(echo "$BT_EXEC" | grep "Connection successful" ) != "" ]]; then dialog --backtitle "$BACKTITLE" --title "Bluetooth" --msgbox "\nYour device is ready to use!" 7 32 else dialog --backtitle "$BACKTITLE" --title "Bluetooth" --msgbox "\nError connecting. Try again!" 7 32 fi fi fi } #-----------------------------------------------------------------------------------------------------------------------------------------# # menu for software # function submenu_software () { while true; do LIST=() [[ -f /usr/bin/softy ]] && LIST+=( "Softy" "3rd party applications installer" ) if [[ -n $(netstat -lnt | awk '$6 == "LISTEN" && $4 ~ ".'32032'"') ]]; then LIST+=( "USB redirector" "Disable USB devices sharing over Ethernet" ) else LIST+=( "USB redirector" "Enable USB devices sharing over Ethernet" ) fi [[ -f /usr/bin/h3consumption && "$LINUXFAMILY" = "sun8i" && "$BRANCH" = "default" ]] && \ LIST+=( "Consumption" "Control board consumption" ) [[ -f /usr/bin/armbianmonitor ]] && LIST+=( "Monitor" "Simple CLI monitoring" ) [[ -f /usr/bin/armbianmonitor ]] && LIST+=( "Diagnostics" "Send diagnostics" ) [[ -f /usr/bin/bin2fex && "$LINUXFAMILY" = sun*i && "$BRANCH" = "default" ]] && LIST+=( "Fexedit" "Board (fex) settings editor" ) if [[ -n $(dpkg -l | grep linux-headers) ]]; then LIST+=( "Headers" "Remove kernel headers" ); else LIST+=( "Headers" "Install kernel headers" ); fi [[ -f /usr/bin/h3disp && "$LINUXFAMILY" = "sun8i" && "$BRANCH" = "default" && \ -n $(bin2fex /dev/null | grep -w "hdmi_used = 1") ]] && LIST+=( "Display" "set the display resolution" ) # count number of menu items to adjust window sizee LISTLENGHT="$((11+${#LIST[@]}/2))" BOXLENGHT=${#LIST[@]} # display warning only we have wifi if [[ " ${LIST[*]} " == *" Hotspot "* ]]; then local disclaimer="\nNote: wireless networking in Linux is problematic. Our tools make it easy for some cases but can't enable AP on every random WiFi chip. If this tool fail, you are on your own.\n " else LISTLENGHT="$((6+${#LIST[@]}/2))" fi DIALOG_CANCEL=1 DIALOG_ESC=255 exec 3>&1 selection=$(dialog --backtitle "$BACKTITLE" --title "System and 3rd party software" --clear \ --cancel-label "Back" --menu "$disclaimer" $LISTLENGHT 70 $BOXLENGHT \ "${LIST[@]}" 2>&1 1>&3) exit_status=$? exec 3>&- [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break jobs "$selection" done } #-----------------------------------------------------------------------------------------------------------------------------------------# # menu for networking # function submenu_networking () { while true; do LIST=() if [[ -n $(service hostapd status | grep -w active | grep -w running) ]]; then [[ -n $(nmcli -f DEVICE,TYPE device status | grep wifi) ]] && LIST+=( "Hotspot" "Manage WiFi access point" ) else [[ -n $(nmcli -f DEVICE,TYPE device status | grep wifi) ]] && LIST+=( "WiFi" "Connect to wireless access point" ) [[ -n $(nmcli -f DEVICE,TYPE device status | grep wifi) ]] && LIST+=( "Hotspot" "Create WiFi access point" ) fi [[ $(hcitool dev | sed '1d') != "" && -n $(service bluetooth status | grep -w active | grep -w running) ]] && LIST+=( "Bluetooth" "Connect Bluetooth devices" ) LIST+=( "Network" "Edit network settings" ) # count number of menu items to adjust window sizee LISTLENGHT="$((11+${#LIST[@]}/2))" BOXLENGHT=${#LIST[@]} # display warning only we have wifi if [[ " ${LIST[*]} " == *" Hotspot "* ]]; then local disclaimer="\nNote: wireless networking in Linux is problematic. Our tools make it easy for some cases but can't enable AP on every random WiFi chip. If this tool fail, you are on your own.\n " else LISTLENGHT="$((6+${#LIST[@]}/2))" fi DIALOG_CANCEL=1 DIALOG_ESC=255 exec 3>&1 selection=$(dialog --backtitle "$BACKTITLE" --title "WiFI, BT, Hotspot" --clear \ --cancel-label "Back" --menu "$disclaimer" $LISTLENGHT 70 $BOXLENGHT \ "${LIST[@]}" 2>&1 1>&3) exit_status=$? exec 3>&- [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break jobs "$selection" done } #-----------------------------------------------------------------------------------------------------------------------------------------# # menu for settings # function submenu_settings () { while true; do LIST=() # check for display manager statuses LIST+=( "Timezone" "Change your timezone" ) [[ $(sed -n 's/^DEVNAME=//p' /sys/dev/block/$(mountpoint -d /)/uevent) == mmcblk* && -f /usr/sbin/nand-sata-install ]] && LIST+=( "Install" "Install to SATA, eMMC, NAND or USB" ) if [[ -n $(apt-mark showhold | grep -w "$BOARD") ]]; then LIST+=( "Unhold" "Un-Freeze kernel and board support packages" ) else LIST+=( "Hold" "Freeze kernel and board support packages" ) fi # check for display manager statuses DISPLAY_MANAGER=""; DESKTOP_INSTALLED="" [[ -n $(service lightdm status 2> /dev/null | grep -w active) ]] && DISPLAY_MANAGER="lightdm" [[ -n $(service nodm status 2> /dev/null | grep -w active) ]] && DISPLAY_MANAGER="nodm" [[ -d /etc/lightdm || -f /etc/default/nodm ]] && DESKTOP_INSTALLED="true" if [[ -n $DISPLAY_MANAGER ]]; then LIST+=( "Desktop" "Disable desktop" ) [[ $DISPLAY_MANAGER == 'nodm' ]] && LIST+=( "Lightdm" "Switch to standard login manager" ) [[ $DISPLAY_MANAGER == 'lightdm' ]] && LIST+=( "Nodm" "Switch to simple auto login manager" ) else LIST+=( "Desktop" "Enable desktop" ) fi if [[ $DESKTOP_INSTALLED ]]; then if [[ $(service xrdp status 2> /dev/null | grep -w active) ]]; then LIST+=( "RDP" "Disable remote desktop access from Windows" ) else LIST+=( "RDP" "Enable remote desktop access from Windows" ) fi fi [[ -n $(grep -w "#kernel.printk" /etc/sysctl.conf ) ]] && LIST+=( "Lowlevel" "Stop low-level messages on console" ) [[ -f /boot/armbianEnv.txt ]] && LIST+=( "Bootenv" "Edit boot environment" ) [[ -f /boot/boot.ini ]] && LIST+=( "Bootscript" "Edit boot script" ) LIST+=( "Services" "Toggle running services" ) [[ -d /boot/dtb/overlay && $LINUXFAMILY == sunxi && $BRANCH != default ]] && LIST+=( "Overlay" "Toggle board functions: UART, I2C, SPI, ..." ) LIST+=( "Welcome" "Toggle welcome screen items" ) if [[ -z $(apt-mark showhold | grep -w "$BOARD") ]]; then [[ -f /etc/apt/sources.list.d/armbian.list ]] && [[ -n $(grep -w apt /etc/apt/sources.list.d/armbian.list) ]] \ && LIST+=( "Nightly" "Switch to nightly builds" ) [[ -f /etc/apt/sources.list.d/armbian.list ]] && [[ -n $(grep -w beta /etc/apt/sources.list.d/armbian.list) ]] \ && LIST+=( "Stable" "Switch to stable builds" ) fi [[ $(apt-cache search --names-only '^linux-'$(lsb_release -cs)'-root.*.'$BOARD'' | sed 's/.*(\(.*\))/\1/' | awk '{print $1}' \ | wc -l) -gt 1 ]] && LIST+=( "Switch" "Switch to alternative kernels" ) if [[ "$DISTRO" == "Ubuntu" && "$(modinfo overlay > /dev/null 2>&1; echo $?)" == "0" ]]; then if [ -n "$(mount | grep -w tmpfs-root)" ]; then LIST+=( "Overlayroot" "Disable virtual read-only root filesystem" ) else LIST+=( "Overlayroot" "Enable virtual read-only root filesystem" ) fi fi # count number of menu items to adjust window sizee LISTLENGHT="$((11+${#LIST[@]}/2))" BOXLENGHT=${#LIST[@]} # display warning only we have wifi if [[ " ${LIST[*]} " == *" Hotspot "* ]]; then local disclaimer="\nNote: wireless networking in Linux is problematic. Our tools make it easy for some cases but can't enable AP on every random WiFi chip. If this tool fail, you are on your own.\n " else LISTLENGHT="$((6+${#LIST[@]}/2))" fi DIALOG_CANCEL=1 DIALOG_ESC=255 exec 3>&1 selection=$(dialog --backtitle "$BACKTITLE" --title "Board and system settings" --clear \ --cancel-label "Back" --menu "$disclaimer" $LISTLENGHT 70 $BOXLENGHT \ "${LIST[@]}" 2>&1 1>&3) exit_status=$? exec 3>&- [[ $exit_status == $DIALOG_CANCEL || $exit_status == $DIALOG_ESC ]] && clear && break jobs "$selection" done }