blob: 195e7ee014c0224277859d758628ed087d46f318 [file] [log] [blame]
#!/bin/bash
#-------------------------------------------------------------------------------
#Created by helmuthdu mailto: helmuthdu[at]gmail[dot]com
#Contribution: flexiondotorg
#-------------------------------------------------------------------------------
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program. If not, see <http://www.gnu.org/licenses/>.
#-------------------------------------------------------------------------------
# Run this script after your first boot with archlinux (as root)
#VARIABLES {{{
checklist=( 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 )
# COLORS {{{
Bold=$(tput bold)
Underline=$(tput sgr 0 1)
Reset=$(tput sgr0)
# Regular Colors
Red=$(tput setaf 1)
Green=$(tput setaf 2)
Yellow=$(tput setaf 3)
Blue=$(tput setaf 4)
Purple=$(tput setaf 5)
Cyan=$(tput setaf 6)
White=$(tput setaf 7)
# Bold
BRed=${Bold}$(tput setaf 1)
BGreen=${Bold}$(tput setaf 2)
BYellow=${Bold}$(tput setaf 3)
BBlue=${Bold}$(tput setaf 4)
BPurple=${Bold}$(tput setaf 5)
BCyan=${Bold}$(tput setaf 6)
BWhite=${Bold}$(tput setaf 7)
#}}}
# PROMPT {{{
prompt1="Enter your option: "
prompt2="Enter n° of options (ex: 1 2 3 or 1-3): "
prompt3="You have to manual enter the following commands, then press ${BYellow}ctrl+d${Reset} or type ${BYellow}exit${Reset}:"
#}}}
# EDITOR {{{
AUTOMATIC_MODE=0
if [[ -f /usr/bin/vim ]]; then
EDITOR="vim"
elif [[ -z $EDITOR ]]; then
EDITOR="nano"
fi
#}}}
# DESKTOP ENVIRONMENT
CINNAMON=0
GNOME=0
KDE=0
# ARCHITECTURE
ARCHI=`uname -m`
UEFI=0
# AUR PACKAGE
AUR=`echo -e "(${BPurple}aur${Reset})"`
#CURRENT DIRECTORY
AUI_DIR=`pwd`
MOUNTPOINT="/mnt"
# VERBOSE MODE
[[ $1 == -v || $1 == --verbose ]] && VERBOSE_MODE=1 || VERBOSE_MODE=0
# LOG FILE
LOG="${AUI_DIR}/`basename ${0}`_error.log"
[[ -f $LOG ]] && rm -f $LOG
PKG_MANAGER="pacman"
PKG=""
PKG_FAIL="${AUI_DIR}/`basename ${0}`_pkg_fail_list.log"
[[ -f $PKG_FAIL ]] && rm -f $PKG_FAIL
# CONNECTION CHECK
XPINGS=0
#MISC
SPIN="/-\|"
AUTOMATIC_MODE=0
#}}}
#COMMON FUNCTIONS {{{
error_msg() { #{{{
local MSG="${1}"
echo -e "${MSG}"
exit 1
} #}}}
cecho() { #{{{
echo -e "$1"
echo -e "$1" >>"$LOG"
tput sgr0;
} #}}}
ncecho() { #{{{
echo -ne "$1"
echo -ne "$1" >>"$LOG"
tput sgr0
} #}}}
spinny() { #{{{
echo -ne "\b${SPIN:i++%${#SPIN}:1}"
} #}}}
progress() { #{{{
ncecho " ";
while true; do
kill -0 $pid 2> /dev/null;
if [[ $? == 0 ]]; then
spinny
sleep 0.25
else
ncecho "\b\b";
wait $pid
retcode=$?
echo -ne "$pid's retcode: $retcode" >> $LOG
if [[ $retcode == 0 ]] || [[ $retcode == 255 ]]; then
cecho success
else
cecho failed
echo -e "$PKG" >> $PKG_FAIL
tail -n 15 $LOG
read -p "ERROR! Continue install [y/N]?" OPTION
[[ $OPTION != y ]] && exit 1
fi
break
fi
done
} #}}}
check_boot_system() { # {{{
if [[ "$(cat /sys/class/dmi/id/sys_vendor)" == 'Apple Inc.' ]] || [[ "$(cat /sys/class/dmi/id/sys_vendor)" == 'Apple Computer, Inc.' ]]; then
modprobe -r -q efivars || true # if MAC
else
modprobe -q efivars # all others
fi
if [[ -d "/sys/firmware/efi/vars/" ]]; then
UEFI=1
echo "UEFI Mode detected"
else
UEFI=0
echo "BIOS Mode detected"
fi
}
#}}}
check_root() { #{{{
if [[ "$(id -u)" != "0" ]]; then
error_msg "ERROR! You must execute the script as the 'root' user."
fi
} #}}}
check_user() { #{{{
if [[ "$(id -u)" == "0" ]]; then
error_msg "ERROR! You must execute the script as a normal user."
fi
} #}}}
check_archlinux() { #{{{
if [[ ! -e /etc/arch-release ]]; then
error_msg "ERROR! You must execute the script on Arch Linux."
fi
} #}}}
check_hostname() { #{{{
if [[ `echo ${HOSTNAME} | sed 's/ //g'` == "" ]]; then
error_msg "ERROR! Hostname is not configured."
fi
} #}}}
check_pacman_blocked() { #{{{
if [[ -f /var/lib/pacman/db.lck ]]; then
error_msg "ERROR! Pacman is blocked. \nIf not running remove /var/lib/pacman/db.lck."
fi
} #}}}
check_domainname() { #{{{
DOMAINNAME=`echo ${HOSTNAME} | cut -d'.' -f2- | sed 's/ //g'`
# Hmm, still no domain name. Keep looking...
if [[ "${DOMAINNAME}" == "" ]]; then
DOMAINNAME=`grep domain /etc/resolv.conf | sed 's/domain //g' | sed 's/ //g'`
fi
# OK, give up.
if [[ "${DOMAINNAME}" == "" ]]; then
error_msg "ERROR! Domain name is not configured."
fi
} #}}}
check_connection(){ #{{{
XPINGS=$(( $XPINGS + 1 ))
ping_gw() {
IP_ADDR=`ip r | grep default | cut -d ' ' -f 3`
[[ -z $IP_ADDR ]] && IP_ADDR="8.8.8.8"
ping -q -w 1 -c 1 ${IP_ADDR} > /dev/null && return 1 || return 0
}
WIRED_DEV=`ip link | grep enp | awk '{print $2}'| sed 's/://'`
WIRELESS_DEV=`ip link | grep wlp | awk '{print $2}'| sed 's/://'`
if ping_gw; then
print_warning "ERROR! Connection not Found."
print_info "Network Setup"
conn_type_list=("Wired Automatic" "Wired Manual" "Wireless")
PS3="$prompt1"
select CONNECTION_TYPE in "${conn_type_list[@]}"; do
case "$REPLY" in
1)
systemctl start dhcpcd@${WIRED_DEV}.service
break
;;
2)
systemctl stop dhcpcd@${WIRED_DEV}.service
read -p "IP Address: " IP_ADDR
read -p "Submask: " SUBMASK
read -p "Gateway: " GATEWAY
ip link set ${WIRED_DEV} up
ip addr add ${IP_ADDR}/${SUBMASK} dev ${WIRED_DEV}
ip route add default via ${GATEWAY}
$EDITOR /etc/resolv.conf
break
;;
3)
ip link set ${WIRELESS_DEV} up
wifi-menu ${WIRELESS_DEV}
break
;;
*)
invalid_option
;;
esac
done
if [[ $XPINGS -gt 2 ]]; then
print_warning "Can't establish connection. exiting..."
exit 1
fi
check_connection
fi
} #}}}
check_vga() { #{{{
# Determine video chipset - only Intel, ATI and nvidia are supported by this script"
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Detecting video chipset "
if [[ -n $(dmidecode --type 1 | grep VirtualBox) ]]; then
cecho Virtualbox
VIDEO_DRIVER="virtualbox"
elif [[ -f /sys/kernel/debug/dri/0/vbios.rom ]]; then
cecho Nvidia
read_input_text "Install NVIDIA proprietary driver" $PROPRIETARY_DRIVER
if [[ $OPTION == y ]]; then
VIDEO_DRIVER="nvidia"
else
VIDEO_DRIVER="nouveau"
fi
elif [[ -f /sys/kernel/debug/dri/0/i915_capabilities ]]; then
cecho Intel
VIDEO_DRIVER="intel"
elif [[ -f /sys/kernel/debug/dri/0/radeon_pm_info || -f /sys/kernel/debug/dri/0/radeon_sa_info ]]; then
cecho AMD/ATI
read_input_text "Install ATI proprietary driver" $PROPRIETARY_DRIVER
if [[ $OPTION == y ]]; then
VIDEO_DRIVER="catalyst"
else
VIDEO_DRIVER="ati"
fi
else
cecho VESA
VIDEO_DRIVER="vesa"
fi
OPTION="y"
[[ $VIDEO_DRIVER == intel || $VIDEO_DRIVER == vesa ]] && read -p "Confirm video driver: $VIDEO_DRIVER [Y/n]" OPTION
if [[ $OPTION == n ]]; then
read -p "Type your video driver [ex: sis, fbdev, modesetting]: " VIDEO_DRIVER
fi
} #}}}
read_input() { #{{{
if [[ $AUTOMATIC_MODE -eq 1 ]]; then
OPTION=$1
else
read -p "$prompt1" OPTION
fi
} #}}}
read_input_text() { #{{{
if [[ $AUTOMATIC_MODE -eq 1 ]]; then
OPTION=$2
else
read -p "$1 [y/N]: " OPTION
echo ""
fi
OPTION=`echo "$OPTION" | tr '[:upper:]' '[:lower:]'`
} #}}}
read_input_options() { #{{{
local line
local packages
if [[ $AUTOMATIC_MODE -eq 1 ]]; then
array=("$1")
else
read -p "$prompt2" OPTION
array=("$OPTION")
fi
for line in ${array[@]/,/ }; do
if [[ ${line/-/} != $line ]]; then
for ((i=${line%-*}; i<=${line#*-}; i++)); do
packages+=($i);
done
else
packages+=($line)
fi
done
OPTIONS=("${packages[@]}")
} #}}}
print_line() { #{{{
printf "%$(tput cols)s\n"|tr ' ' '-'
} #}}}
print_title() { #{{{
clear
print_line
echo -e "# ${Bold}$1${Reset}"
print_line
echo ""
} #}}}
print_info() { #{{{
#Console width number
T_COLS=`tput cols`
echo -e "${Bold}$1${Reset}\n" | fold -sw $(( $T_COLS - 18 )) | sed 's/^/\t/'
} #}}}
print_warning() { #{{{
#Console width number
T_COLS=`tput cols`
echo -e "${BRed}$1${Reset}\n" | fold -sw $(( $T_COLS - 1 ))
} #}}}
start_module() { #{{{
modprobe $1
} #}}}
add_module() { #{{{
#check if the number of arguments is less then 2
for MODULE in $1; do
[[ $# -lt 2 ]] && MODULE_NAME="$MODULE" || MODULE_NAME="$2";
echo "$MODULE" >> /etc/modules-load.d/$MODULE_NAME.conf
start_module "$MODULE"
done
} #}}}
add_repository() { #{{{
REPO=${1}
URL=${2}
CHECK_REPO=`grep -F "${REPO}" /etc/pacman.conf`
if [[ -z $CHECK_REPO ]]; then
echo -e "\n[${REPO}]\nSigLevel = Optional TrustAll\nServer = ${URL}" >> /etc/pacman.conf
system_update
fi
} #}}}
add_line() { #{{{
ADD_LINE=${1}
FILEPATH=${2}
CHECK_LINE=`grep -F "${ADD_LINE}" ${FILEPATH}`
[[ -z $CHECK_LINE ]] && echo "${ADD_LINE}" >> ${FILEPATH}
} #}}}
replace_line() { #{{{
SEARCH=${1}
REPLACE=${2}
FILEPATH=${3}
FILEBASE=`basename ${3}`
sed -e "s/${SEARCH}/${REPLACE}/" ${FILEPATH} > /tmp/${FILEBASE} 2>"$LOG"
if [[ ${?} -eq 0 ]]; then
mv /tmp/${FILEBASE} ${FILEPATH}
else
cecho "failed: ${SEARCH} - ${FILEPATH}"
fi
} #}}}
update_early_modules() { #{{{
local NEW_MODULE=${1}
local OLD_ARRAY=`egrep ^MODULES= /etc/mkinitcpio.conf`
if [[ -n ${NEW_MODULE} ]]; then
# Determine if the new module is already listed.
_EXISTS=`echo ${OLD_ARRAY} | grep ${NEW_MODULE}`
if [ $? -eq 1 ]; then
source /etc/mkinitcpio.conf
if [[ -z ${MODULES} ]]; then
NEW_MODULES="${NEW_MODULE}"
else
NEW_MODULES="${MODULES} ${NEW_MODULE}"
fi
replace_line "MODULES=\"${MODULES}\"" "MODULES=\"${NEW_MODULES}\"" /etc/mkinitcpio.conf
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Rebuilding init "
mkinitcpio -p linux >>"$LOG" 2>&1 &
pid=$!;progress $pid
fi
fi
} #}}}
is_package_installed() { #{{{
#check if a package is already installed
for PKG in $1; do
pacman -Q $PKG &> /dev/null && return 0;
done
return 1
} #}}}
checkbox() { #{{{
#display [X] or [ ]
[[ "$1" -eq 1 ]] && echo -e "${BBlue}[${Reset}${Bold}X${BBlue}]${Reset}" || echo -e "${BBlue}[ ${BBlue}]${Reset}";
} #}}}
checkbox_package() { #{{{
#check if [X] or [ ]
is_package_installed "$1" && checkbox 1 || checkbox 0
} #}}}
aui_download_packages() { #{{{
for PKG in $1; do
#exec command as user instead of root
su - ${USER_NAME} -c "
[[ ! -d aui_packages ]] && mkdir aui_packages
cd aui_packages
curl -o $PKG.tar.gz https://aur.archlinux.org/packages/${PKG:0:2}/$PKG/$PKG.tar.gz
tar zxvf $PKG.tar.gz
rm $PKG.tar.gz
cd $PKG
makepkg -csi --noconfirm
"
done
} #}}}
aur_package_install() { #{{{
su - ${USER_NAME} -c "sudo -v"
#install package from aur
for PKG in $1; do
if ! is_package_installed "${PKG}" ; then
if [[ $AUTOMATIC_MODE -eq 1 ]]; then
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Installing ${AUR} ${Bold}${PKG}${Reset} "
su - ${USER_NAME} -c "${AUR_PKG_MANAGER} --noconfirm -S ${PKG}" >>"$LOG" 2>&1 &
pid=$!;progress $pid
else
su - ${USER_NAME} -c "${AUR_PKG_MANAGER} -S ${PKG}"
fi
else
if [[ $VERBOSE_MODE -eq 0 ]]; then
cecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Installing ${AUR} ${Bold}${PKG}${Reset} success"
else
echo -e "Warning: ${PKG} is up to date --skipping"
fi
fi
done
} #}}}
package_install() { #{{{
#install packages using pacman
if [[ $AUTOMATIC_MODE -eq 1 || $VERBOSE_MODE -eq 0 ]]; then
for PKG in ${1}; do
PKG_REPO=`pacman -Sp --print-format %r ${PKG} | uniq | sed '1!d'`
case $PKG_REPO in
"core")
PKG_REPO="${BRed}${PKG_REPO}${Reset}"
;;
"extra")
PKG_REPO="${BYellow}${PKG_REPO}${Reset}"
;;
"community")
PKG_REPO="${BGreen}${PKG_REPO}${Reset}"
;;
"multilib")
PKG_REPO="${BCyan}${PKG_REPO}${Reset}"
;;
esac
if ! is_package_installed "${PKG}" ; then
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Installing (${PKG_REPO}) ${Bold}${PKG}${Reset} "
$PKG_MANAGER -S --noconfirm --needed ${PKG} >>"$LOG" 2>&1 &
pid=$!;progress $pid
else
cecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Installing (${PKG_REPO}) ${Bold}${PKG}${Reset} exists "
fi
done
else
$PKG_MANAGER -S --needed ${1}
fi
} #}}}
package_remove() { #{{{
#remove package
for PKG in ${1}; do
if is_package_installed "${PKG}" ; then
if [[ $AUTOMATIC_MODE -eq 1 || $VERBOSE_MODE -eq 0 ]]; then
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Removing ${Bold}${PKG}${Reset} "
pacman -Rcsn --noconfirm ${PKG} >>"$LOG" 2>&1 &
pid=$!;progress $pid
else
pacman -Rcsn ${PKG}
fi
fi
done
} #}}}
system_upgrade() { #{{{
local MODIFY=`stat /var/lib/pacman/sync | egrep ^Modify | cut -d':' -f2 | cut -d' ' -f2`
local TODAY=`date +%Y-%m-%d`
if [[ ${MODIFY} != ${TODAY} ]]; then
pacman -Syu ${1}
fi
} #}}}
system_update() { #{{{
if [[ $VERBOSE_MODE -eq 0 ]]; then
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Updating packages "
$PKG_MANAGER -Syy >>"$LOG" 2>&1 &
pid=$!;progress $pid
else
$PKG_MANAGER -Syy $1
fi
} #}}}
npm_install() { #{{{
#install packages using pacman
npm install -g $1
} #}}}
contains_element() { #{{{
#check if an element exist in a string
for e in "${@:2}"; do [[ $e == $1 ]] && break; done;
} #}}}
config_xinitrc() { #{{{
#create a xinitrc file in home user directory
cp -fv /etc/skel/.xinitrc /home/${USER_NAME}/
echo -e "exec $1" >> /home/${USER_NAME}/.xinitrc
chown -R ${USER_NAME}:users /home/${USER_NAME}/.xinitrc
} #}}}
invalid_option() { #{{{
print_line
echo "Invalid option. Try another one."
pause_function
} #}}}
pause_function() { #{{{
print_line
if [[ $AUTOMATIC_MODE -eq 0 ]]; then
read -e -sn 1 -p "Press any key to continue..."
fi
} #}}}
menu_item() { #{{{
#check if the number of arguments is less then 2
[[ $# -lt 2 ]] && PACKAGE_NAME="$1" || PACKAGE_NAME="$2";
#list of chars to remove from the package name
CHARS_TO_REMOVE=("Ttf-" "-bzr" "-hg" "-svn" "-git" "-stable" "-icon-theme" "Gnome-shell-theme-" "Gnome-shell-extension-");
#remove chars from package name
for CHARS in ${CHARS_TO_REMOVE[@]}; do PACKAGE_NAME=`echo ${PACKAGE_NAME^} | sed 's/'$CHARS'//'`; done
#display checkbox and package name
echo -e "$(checkbox_package "$1") ${Bold}$PACKAGE_NAME${Reset}"
} #}}}
mainmenu_item() { #{{{
echo -e "$(checkbox "$1") ${Bold}$2${Reset}"
} #}}}
elihw() { #{{{
[[ $OPT == b || $OPT == d ]] && break;
} #}}}
add_user_to_group() { #{{{
local _USER=${1}
local _GROUP=${2}
if [[ -z ${_GROUP} ]]; then
error_msg "ERROR! 'add_user_to_group' was not given enough parameters."
fi
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} Adding ${Bold}${_USER}${Reset} to ${Bold}${_GROUP}${Reset} "
gpasswd -a ${_USER} ${_GROUP} >>"$LOG" 2>&1 &
pid=$!;progress $pid
} #}}}
system_ctl() { #{{{
local ACTION=${1}
local OBJECT=${2}
ncecho " ${BBlue}[${Reset}${Bold}X${BBlue}]${Reset} systemctl ${ACTION} ${OBJECT} "
systemctl ${ACTION} ${OBJECT} >> "$LOG" 2>&1
pid=$!;progress $pid
}
#}}}
arch_chroot() { #{{{
arch-chroot $MOUNTPOINT /bin/bash -c "${1}"
}
#}}}
setkeymap() { #{{{
local keymaps=(`localectl list-keymaps`)
PS3="(shift+pgup/pgdown) $prompt1"
echo "Select keymap:"
select KEYMAP in "${keymaps[@]}"; do
if contains_element "$KEYMAP" "${keymaps[@]}"; then
break
else
invalid_option
fi
done
}
#}}}
setlocale() { #{{{
local locale_list=(`cat /etc/locale.gen | grep _ | sed 's/\..*$//' | sed '/@/d' | awk '{print $1}' | uniq | sed 's/#//g'`);
PS3="$prompt1"
echo "Select locale:"
select LOCALE in "${locale_list[@]}"; do
if contains_element "$LOCALE" "${locale_list[@]}"; then
LOCALE_8859="${LOCALE} ISO-8859"
LOCALE_UTF8="${LOCALE}.UTF-8"
break
else
invalid_option
fi
done
}
#}}}
settimezone() { #{{{
local zone=(`timedatectl list-timezones | sed 's/\/.*$//' | uniq`);
PS3="$prompt1"
echo "Select zone:"
select ZONE in "${zone[@]}"; do
if contains_element "$ZONE" "${zone[@]}"; then
local subzone=(`timedatectl list-timezones | grep ${ZONE} | sed 's/^.*\///'`)
PS3="$prompt1"
echo "Select subzone:"
select SUBZONE in "${subzone[@]}"; do
if contains_element "$SUBZONE" "${subzone[@]}"; then
break
else
invalid_option
fi
done
break
else
invalid_option
fi
done
} #}}}
#}}}