From 74f1e8037f6aa3c8e6b3351e3dbb5b6758a5e67e Mon Sep 17 00:00:00 2001 From: th33xitus <> Date: Fri, 22 May 2020 18:20:17 +0200 Subject: [PATCH] initial commit --- kiauh.sh | 761 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 761 insertions(+) create mode 100644 kiauh.sh diff --git a/kiauh.sh b/kiauh.sh new file mode 100644 index 0000000..af23f90 --- /dev/null +++ b/kiauh.sh @@ -0,0 +1,761 @@ +#!/bin/bash +clear +set -e + +### init color variables +green="\e[92m" +yellow="\e[93m" +red="\e[91m" +cyan="\e[96m" +default="\e[39m" + +### setup repos +KLIPPER_REPO=https://github.com/KevinOConnor/klipper.git +#DWC2FK_REPO=https://github.com/Stephan3/dwc2-for-klipper.git +DWC2FK_REPO=https://github.com/pluuuk/dwc2-for-klipper.git + +## setup some file and folder paths +KLIPPER_DIR=${HOME}/klipper +DWC2FK_DIR=${HOME}/dwc2-for-klipper +DWC2FK_SYSDIR=${HOME}/klippy-env/lib/python2.7/site-packages/tornado +DWC2_DIR=${HOME}/sdcard/dwc2 +BACKUP_DIR=${HOME}/backup +CFG_FILE=${HOME}/printer.cfg +KLIPPER_SYSFILE1=/etc/init.d/klipper +KLIPPER_SYSFILE2=/etc/default/klipper + +print_header(){ + echo -e "###################################################" + echo -e "## $(title_msg "> > > > > > > > > KIAUH < < < < < < < < <") ##" + echo -e "## $(title_msg "Klipper Installation And Update Helper") ##" + echo -e "## --------------------------------------------- ##" + echo -e "## Install, update and backup: ##" + echo -e "## Klipper | DWC2-for-Klipper | DWC2 web UI ##" + echo -e "## --------------------------------------------- ##" + echo -e "## by th33xitus ##" + echo -e "## credits to: lixxbox ##" + echo -e "###################################################" +} + +main_menu(){ + echo + echo -e "/=================================================\ " + echo -e "| $(title_msg "Please choose the action you want to perform:") |" + echo -e "|-------------------------------------------------|" + echo -e "| 0) Check system status |" + echo -e "| |" + echo -e "| 1) ${green}[Install]${default} 2) ${yellow}[Advanced]${default} 3) ${red}[Uninstall]${default} |" + echo -e "|------------------------+------------------------|" + echo -e "| Update | Backup |" + echo -e "|------------------------+------------------------|" + echo -e "| 4) Update all | 8) Backup all |" + echo -e "| 5) Klipper | 9) Klipper |" + echo -e "| 6) dwc2-for-klipper | 10) dwc2-for-klipper |" + echo -e "| 7) DWC2 | 11) DWC2 |" + echo -e "|------------------------+------------------------|" + echo -e "| $(warn_msg "Q) Quit") |" + echo -e "\=================================================/" + read -p "Perform action: " action; echo + action +} + +### declare some functions +warn_msg(){ + echo -e "${red}$1${default}" +} +status_msg(){ + echo -e "${yellow}## $1${default}" +} +confirm_msg(){ + echo -e "${green}>> $1${default}" +} +title_msg(){ + echo -e "${cyan}$1${default}" +} +get_date(){ + current_date=`date +"%Y-%m-%d_%H%M%S"` +} + +### checking for root +check_euid(){ + if [ "$EUID" -eq 0 ] + then + echo -e "/=================================================\ " + echo -e "| $(warn_msg "DON'T RUN THIS SCRIPT AS ROOT!") |" + echo -e "\=================================================/ "; exit 1 + fi +} + +### checking for existing installations on startup +start_check(){ + check_files + echo; status_msg "Klipper installation: $klipper_status" + echo; status_msg "DWC2 web UI installation: $dwc2_status" + echo; status_msg "DWC2-for-Klipper installation: $dwc2fk_status" +} +check_files(){ + if [[ -f $KLIPPER_SYSFILE1 && -f $KLIPPER_SYSFILE2 ]] + then + if [ -d $KLIPPER_DIR ] + then + klipper_status="${green}Found!${default}" + else + klipper_status="${yellow}Incomplete!${default}" + fi + else + klipper_status="${red}Not found!${default}" + fi + if [ -d $DWC2FK_SYSDIR ] + then + if [ -d $DWC2FK_DIR ] + then + dwc2fk_status="${green}Found!${default}" + else + dwc2fk_status="${yellow}Incomplete!${default}" + fi + else + dwc2fk_status="${red}Not found!${default}" + fi + if [ -d $DWC2_DIR/web ] + then + dwc2_status="${green}Found!${default}" + else + dwc2_status="${red}Not found!${default}" + fi +} + +### functions for writing to printer.cfg +write_printid_cfg(){ + echo + while true; do + read -p "Do you want to write this ID to your printer.cfg now? (Y/n): " yn + case "$yn" in + Y|y|Yes|yes|"") + backup_cfg + echo -e "\n#############################\n### AUTO CREATED by KIAUH ###\n#############################\n[mcu]\nserial: $usb_id" >> $CFG_FILE + echo; confirm_msg "Config written!" + break + ;; + N|n|No|no) + break + ;; + *) + echo; warn_msg "Unknown parameter: $yn" + esac + done +} +write_dwc2fk_cfg(){ + echo + while true; do + echo -n -e "Do you want to write the configuration example\nto your printer.cfg? (Y/n): " + read yn + case "$yn" in + Y|y|Yes|yes|"") + backup_cfg + echo -e "\n#############################\n### AUTO CREATED by KIAUH ###\n#############################\n[virtual_sdcard]\npath: ~/sdcard\n\n[web_dwc2]\n# optional - defaulting to Klipper\nprinter_name: Reiner Calmund\n# optional - defaulting to 127.0.0.1\nlisten_adress: 0.0.0.0\n# needed - use above 1024 as nonroot\nlisten_port: 4750\n#optional defaulting to dwc2/web. Its a folder relative to your virtual sdcard.\nweb_path: dwc2/web" >> $CFG_FILE + echo; confirm_msg "Config written!"; echo; break + ;; + N|n|No|no) + break + ;; + *) + warn_msg "Unknown parameter: $yn"; echo + esac + done +} + +### grab the printers id +get_usb_id(){ + echo; status_msg "Identifying the correct USB port ..." + warn_msg "Make sure your printer is the only USB device connected!" + usb_id=`ls /dev/serial/by-id/*` + if [ -L /dev/serial/by-id/* ] + then + echo; status_msg "The ID of your printer is:" + title_msg "$usb_id"; echo + else + echo; warn_msg "Could not retrieve ID!" + fi +} + +build_fw(){ + status_msg "--- Starting Klipper Firmware Configuration ---" + if [ -d $KLIPPER_DIR ] + then + cd $KLIPPER_DIR && make menuconfig + status_msg "Building firmware ..." + make clean && make && confirm_msg "Firmware built!" + else + warn_msg "Can not build firmware without a Klipper directory!" + fi +} + +flash_routine(){ + echo; status_msg "--- Flashing MCU ---" + echo + echo -e "/=================================================\ " + echo -e "| $(warn_msg "WARNING!") |" + echo -e "| $(warn_msg "Flashing a Smoothie based board for the first") |" + echo -e "| $(warn_msg "time with this script will certainly fail".) |" + echo -e "| This applies to boards like the BTT SKR V1.3 or |" + echo -e "| the newer SKR V1.4 and SKR V1.4 Turbo. You have |" + echo -e "| to copy the firmware file to the microSD card |" + echo -e "| manually and rename it to 'firmware.bin'. |" + echo -e "| You find the file in: ~/klipper/out/klipper.bin |" + echo -e "\=================================================/ " + echo + while true; do + read -p "Do you want to continue? (Y/n): " yn + case "$yn" in + Y|y|Yes|yes|"") + get_usb_id + write_printid_cfg + flash_mcu + break + ;; + N|n|No|no) break;; + *) warn_msg "Unknown parameter: $yn"; echo;; + esac + done +} + +flash_mcu(){ + echo; status_msg "Stopping Klipper service ..." + sudo service klipper stop && confirm_msg "Klipper service stopped!"; echo + if ! make flash FLASH_DEVICE="$usb_id"; + then + echo; warn_msg "Flashing failed!" + warn_msg "Please read the log above!" + else + echo; confirm_msg "Flashing successfull!" + fi + echo; status_msg "Starting Klipper service ..." + sudo service klipper start && confirm_msg "Klipper service started!"; echo +} + +### check system for service, dirs, files and updates +system_check(){ + echo + status_msg "--- Klipper service status:" + if systemctl is-active -q klipper + then + confirm_msg "Klipper service running!" + else + if [ ! -f $KLIPPER_SYSFILE1 ] + then + warn_msg "Klipper service not installed!" + else + warn_msg "Klipper service inactive!" + fi + fi + echo; status_msg "--- Klipper system files:" + if [[ -f $KLIPPER_SYSFILE1 && -f $KLIPPER_SYSFILE2 ]] + then + confirm_msg "Klipper system files found!" + else + warn_msg "No Klipper system files were found!" + warn_msg "Run the installer to create them." + fi + echo; status_msg "--- DWC2-for-Klipper system files:" + if [ -d $DWC2FK_SYSDIR ] + then + confirm_msg "DWC2-for-Klipper system files found!" + else + warn_msg "No DWC2-for-Klipper system files (Tornado 5.1.1)\nwere found! Run the installer to create them." + fi + echo; status_msg "--- Klipper update check:" + check_klipper_ver + if [ -d $KLIPPER_DIR ] + then + if [ "$klipper_local_ver" == "$klipper_remote_ver" ] + then + confirm_msg "Klipper is up to date!" + else + warn_msg "Klipper is outdated!" + fi + fi + echo; status_msg "--- DWC2-for-Klipper update check:" + check_dwc2fk_ver + if [ -d $DWC2FK_DIR ] + then + if [ "$dwc2fk_local_ver" == "$dwc2fk_remote_ver" ] + then + confirm_msg "DWC2-for-Klipper is up to date!" + else + warn_msg "DWC2-for-Klipper is outdated!" + fi + fi + echo; status_msg "--- DWC2 update check:" + check_dwc2_ver + if [ -d $DWC2_DIR ] + then + if [ "$dwc2_remote_ver" == "$dwc2_local_ver" ] + then + confirm_msg "DWC2 is up to date!" + else + warn_msg "DWC2 is outdated!" + fi + fi +} +### version checks +check_klipper_ver(){ + if [ -d $KLIPPER_DIR ] + then + cd $KLIPPER_DIR + git fetch -q + klipper_local_ver=`git rev-parse --short=8 HEAD` + klipper_remote_ver=`git rev-parse --short=8 origin/master` + echo -e "Local : $klipper_local_ver" + echo -e "Remote: $klipper_remote_ver" + else + warn_msg "No Klipper directory found!" + warn_msg "Run Klipper update to create it." + fi +} +check_dwc2fk_ver(){ + if [ -d $DWC2FK_DIR ] + then + cd $DWC2FK_DIR + git fetch -q + dwc2fk_local_ver=`git rev-parse --short=8 HEAD` + dwc2fk_remote_ver=`git rev-parse --short=8 origin/master` + echo -e "Local : $dwc2fk_local_ver" + echo -e "Remote: $dwc2fk_remote_ver" + else + warn_msg "No DWC2-for-Klipper directory found!" + warn_msg "Run DWC2-for-Klipper update to create it." + fi +} +check_dwc2_ver(){ + if [ -d $DWC2_DIR/web ] + then + if [ -f $DWC2_DIR/web/version ] + then + dwc2_local_ver=`head -n 1 $DWC2_DIR/web/version` + echo -e "Local : $dwc2_local_ver" + else + echo -e "Local : Can't read current version. Please update!" + fi + dwc2_remote_ver=`curl -s https://api.github.com/repositories/28820678/releases/latest | grep tag_name | cut -d'"' -f4` + echo -e "Remote: $dwc2_remote_ver" + else + warn_msg "No DWC2 directory found!" + warn_msg "Run DWC2 update to create it." + fi +} + +### install functions +inst_klipper(){ + if [[ -f $KLIPPER_SYSFILE1 || -f $KLIPPER_SYSFILE2 ]] + then + confirm_msg "Klipper is already installed!" + else + status_msg "--- Installing dependencies ---" + sudo apt update && sudo apt install git wget gzip tar build-essential libjpeg8-dev imagemagick libv4l-dev cmake -y + confirm_msg "Dependencies installed!" + echo; status_msg "--- Installing Klipper ---" + update_klipper + cd $KLIPPER_DIR/scripts + ./install-octopi.sh + if systemctl is-active -q klipper + then + confirm_msg "Klipper service running!" && confirm_msg "Klipper successfully installed!" + fi + echo + while true; do + read -p "Do you want to flash your MCU now? (Y/n): " yn; echo + case "$yn" in + Y|y|Yes|yes|"") + build_fw + flash_routine + break + ;; + N|n|No|no) break;; + *) warn_msg "Unknown parameter: $yn"; echo;; + esac + done + fi +} +inst_dwc2fk(){ + if [ -d $DWC2FK_SYSDIR ] + then + echo; confirm_msg "DWC2-for-Klipper system files (Tornado 5.1.1)\nare already installed!" + else + echo; status_msg "--- Installing DWC2-for-Klipper ---" + if [ $(systemctl is-active klipper) = "active" ] + then + echo; status_msg "Stopping Klipper service ..." + sudo systemctl stop klipper && confirm_msg "Klipper service stopped!"; echo + fi + echo; status_msg "Installing Tornado 5.1.1 ..." + cd ${HOME} + PYTHONDIR="${HOME}/klippy-env" + virtualenv ${PYTHONDIR} + ${PYTHONDIR}/bin/pip install tornado==5.1.1 && confirm_msg "Tornado 5.1.1 installed!" + update_dwc2fk && confirm_msg "DWC2-for-Klipper installed!" + write_dwc2fk_cfg + if [ $(systemctl is-active klipper) = "inactive" ] + then + echo; status_msg "Starting Klipper service ..." + sudo systemctl start klipper && confirm_msg "Klipper service running!" + fi + fi +} +inst_dwc2(){ + if [ -d $DWC2_DIR ] + then + echo; confirm_msg "DWC2 web UI is already installed!" + else + echo; status_msg "--- Installing DWC2 web UI ---" + update_dwc2 && confirm_msg "DWC2 web UI installed!" + fi +} +### update functions +update_full(){ + status_msg "Full update ..." + update_klipper && confirm_msg "Klipper updated!" + update_dwc2fk && confirm_msg "DWC2-for-Klipper updated!" + update_dwc2 && confirm_msg "DWC2 web UI updated!" +} +update_klipper(){ + echo; status_msg "--- Klipper Update ---" + if [ -f $KLIPPER_SYSFILE1 ] + then + echo; status_msg "Stopping Klipper service ..." + sudo systemctl stop klipper && confirm_msg "Klipper service stopped!";echo + fi + if [ -d $KLIPPER_DIR ] + then + get_date + mkdir -p $BACKUP_DIR/klipper-backup/"$current_date" + mv $KLIPPER_DIR $_ + fi + cd ${HOME} && git clone $KLIPPER_REPO + if [ -f $DWC2FK_DIR/web_dwc2.py ] + then + echo; status_msg "Creating necessary symlink ..." + ln -s $DWC2FK_DIR/web_dwc2.py $KLIPPER_DIR/klippy/extras/web_dwc2.py && confirm_msg "Symlink created!" + fi + if [ -f $KLIPPER_SYSFILE1 ] + then + echo; status_msg "Starting Klipper service ..." + sudo systemctl start klipper && confirm_msg "Klipper service started!" + fi +} +update_dwc2fk(){ + echo; status_msg "--- DWC2-for-Klipper Update ---" + if [ -d $DWC2FK_DIR ] + then + get_date + mkdir -p $BACKUP_DIR/dwc2fk-backup/"$current_date" + mv $DWC2FK_DIR $_ + fi + cd ${HOME} && git clone $DWC2FK_REPO + if [[ -d $KLIPPER_DIR/klippy/extras && ! -f $KLIPPER_DIR/klippy/extras/web_dwc2.py ]] + then + echo; status_msg "Creating necessary symlink ..." + ln -s $DWC2FK_DIR/web_dwc2.py $KLIPPER_DIR/klippy/extras/web_dwc2.py && confirm_msg "Symlink created!" + fi +} +update_dwc2(){ + echo; status_msg "--- DWC2 web UI Update ---" + get_url=`curl -s https://api.github.com/repositories/28820678/releases/latest | grep browser_download_url | cut -d'"' -f4` + if [ -d $DWC2_DIR/web ] + then + get_date + mkdir -p $BACKUP_DIR/dwc2-backup/"$current_date"/sdcard/dwc2/web/ + mv $DWC2_DIR/web/* $_ + else + mkdir -p $DWC2_DIR/web + fi + cd $DWC2_DIR/web + wget -q $get_url + unzip -q *.zip && for f_ in $(find . | grep '.gz');do gunzip ${f_};done + echo $get_url | cut -d/ -f8 > $DWC2_DIR/web/version + rm -rf DuetWebControl-SD.zip +} + +### backup functions +backup_msg(){ + status_msg "Running $1 backup ..." +} +backup_cfg(){ + if [ -f $CFG_FILE ] + then + get_date + cp $CFG_FILE $BACKUP_DIR/printer.cfg."$current_date".backup + fi +} +backup_full(){ + if [[ -d $KLIPPER_DIR && -d $DWC2FK_DIR && -d $DWC2_DIR ]] + then + backup_klipper_only && confirm_msg "Klipper done ..." + backup_dwc2fk_only && confirm_msg "dwc2-for-klipper done ..." + backup_dwc2_only && confirm_msg "DWC2 done ..." + else + warn_msg "Can not create full backup." + warn_msg "One or more directories not found!" + fi +} +backup_klipper_only(){ + if [ -d $KLIPPER_DIR ] + then + get_date + mkdir -p $BACKUP_DIR/klipper-backup/"$current_date" && cp -rf $KLIPPER_DIR $_ + else + warn_msg "Can not backup Klipper." + warn_msg "No Klipper directory found!" + fi +} +backup_dwc2fk_only(){ + if [ -d $DWC2FK_DIR ] + then + get_date + mkdir -p $BACKUP_DIR/dwc2fk-backup/"$current_date" && cp -rf $DWC2FK_DIR $_ + else + warn_msg "Can not backup dwc2-for-klipper." + warn_msg "No dwc2-for-klipper directory found!" + fi +} +backup_dwc2_only(){ + if [ -d $DWC2_DIR ] + then + get_date + mkdir -p $BACKUP_DIR/dwc2-backup/"$current_date" && cp -rf $DWC2_DIR $_ + else + warn_msg "Can not backup DWC2." + warn_msg "No DWC2 directory found!" + fi +} + +### remove functions +rm_klipper(){ + echo; warn_msg "Removing Klipper + klippy-env will make any\nDWC2-for-Klipper installation inoperable!" + while true; do + read -p "Do you really want to continue? (Y/n): " yn + case "$yn" in + Y|y|Yes|yes|"") + echo; status_msg "Removing Klipper ..." + echo; status_msg "Stopping Klipper service ..." + sudo service klipper stop && confirm_msg "Klipper service stopped!" + echo; status_msg "Removing Klipper from startup ..." + sudo update-rc.d -f klipper remove && confirm_msg "Removed!" + echo; status_msg "Removing Klipper service ..." + sudo rm -rf $KLIPPER_SYSFILE1 $KLIPPER_SYSFILE2 && confirm_msg "Removed!" + echo; status_msg "Removing Klipper files from system ..." + rm -rf $KLIPPER_DIR ${HOME}/klippy-env && confirm_msg "Removed!"; echo + break + ;; + N|n|No|no) break;; + *) warn_msg "Unknown parameter: $yn"; echo;; + esac + done +} +rm_dwc2fk(){ + echo; status_msg "Removing DWC2-for-Klipper..." + rm -rf $DWC2FK_DIR $DWC2_DIR $DWC2FK_SYSDIR && confirm_msg "Removed!" +} +rm_dwc2(){ + echo; status_msg "Removing DWC2 web UI..." + rm -rf $DWC2_DIR && confirm_msg "Removed!" +} + +### install menu +inst_menu(){ + echo + echo -e "/=================================================\ " + echo -e "| ${green} Welcome to the installation menu!${default} | " + echo -e "|-------------------------------------------------| " + echo -e "| You need this menu usually only for installing | " + echo -e "| to a completely fresh system or if you used the | " + echo -e "| uninstaller for Klipper or DWC2-for-Klipper. | " + echo -e "\=================================================/ " + echo + echo -e "What do you want to install?"; echo + echo "1) Install all" + echo "2) Klipper" + echo "3) DWC2-for-Klipper" + echo "4) DWC2 web UI" + echo + warn_msg "Q) Exit" + echo + while true; do + read -p "Please select: " choice; echo + case "$choice" in + 1) inst_klipper && inst_dwc2fk && inst_dwc2; break;; + 2) inst_klipper; break;; + 3) inst_dwc2fk; break;; + 4) inst_dwc2; break;; + Q|q) main_menu;; + *) warn_msg "Unknown parameter: $choice"; echo;; + esac + done + inst_menu +} + +### advanced menu +adv_menu(){ + echo + echo -e "/=================================================\ " + echo -e "| ${yellow}Welcome to the advanced menu!${default} | " + echo -e "|-------------------------------------------------| " + echo -e "| Before flashing or getting the printer ID make | " + echo -e "| sure that the printer is the only USB device | " + echo -e "| connected to your Raspberry Pi. | " + echo -e "\=================================================/ " + echo + echo -e "What do you want to do?"; echo + echo "1) Build Firmware" + echo "2) Flash MCU" + echo "3) Get printer ID" + echo "4) Write printer ID to printer.cfg" + echo -e "5) Write DWC2-for-klipper configuration\n example to printer.cfg" + echo + warn_msg "Q) Exit" + echo + while true; do + read -p "Please select: " choice; echo + case "$choice" in + 1) build_fw; break;; + 2) flash_routine; break;; + 3) get_usb_id; break;; + 4) get_usb_id && write_printid_cfg; break;; + 5) write_dwc2fk_cfg; break;; + Q|q) main_menu;; + *) warn_msg "Unknown parameter: $choice"; echo;; + esac + done + adv_menu +} + +### remove menu +rm_menu(){ + echo + echo -e "/=================================================\ " + echo -e "| ${red}Welcome to the uninstallation menu!${default} | " + echo -e "|-------------------------------------------------| " + echo -e "| $(warn_msg ">>> Warning <<<") | " + echo -e "| $(warn_msg "You are about to remove Klipper, all of its") | " + echo -e "| $(warn_msg "components and/or extensions!") | " + echo -e "| | " + echo -e "| Files and directories which remain untouched: | " + echo -e "| --> ~/printer.cfg | " + echo -e "| --> ~/backup | " + echo -e "| You need remove them manually if you wish so. | " + echo -e "\=================================================/ " + echo + echo -e "What do you want to remove?"; echo + echo "1) Remove all" + echo "2) Klipper (incl. klippy-env)" + echo "3) DWC2-for-Klipper" + echo "4) DWC2 web UI" + echo + warn_msg "Q) Exit" + echo + while true; do + read -p "Please select: " choice + case "$choice" in + 1) rm_klipper && rm_dwc2fk && rm_dwc2; break;; + 2) rm_klipper; break;; + 3) rm_dwc2fk; break;; + 4) rm_dwc2; break;; + Q|q) main_menu;; + *) warn_msg "Unknown parameter: $choice"; echo;; + esac + done + rm_menu +} + +action(){ + case "$action" in + 0) + clear + print_header + system_check + main_menu + ;; + 1) + clear + print_header + inst_menu + main_menu + ;; + 2) + clear + print_header + adv_menu + ;; + 3) + clear + print_header + rm_menu + ;; + 4) + clear + print_header + update_full + main_menu + ;; + 5) + clear + print_header + update_klipper + confirm_msg "Klipper updated!" + main_menu + ;; + 6) + clear + print_header + update_dwc2fk + confirm_msg "DWC2-for-Klipper updated!" + main_menu + ;; + 7) + clear + print_header + update_dwc2 + confirm_msg "DWC2 web UI updated!" + main_menu + ;; + 8) + clear + print_header + backup_msg "Full" + backup_full + main_menu + ;; + 9) + clear + print_header + backup_msg "Klipper" + backup_klipper_only + main_menu + ;; + 10) + clear + print_header + backup_msg "dwc2-for-klipper" + backup_dwc2fk_only + main_menu + ;; + 11) + clear + print_header + backup_msg "DWC2" + backup_dwc2_only + main_menu + ;; + Q|q) + confirm_msg "Happy printing! ...\n"; exit 1 + ;; + *) + warn_msg "Unknown parameter: $action" + main_menu + ;; + esac +} + +print_header +check_euid +start_check +main_menu \ No newline at end of file