1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696 |
- #!/bin/bash
- #
- # .---. . .
- # | | |
- # |--- .--. .-. .-. .-.| .-. .--.--. |.-. .-. .--. .-.
- # | | (.-' (.-' ( | ( )| | | | )( )| | (.-'
- # ' ' --' --' -' - -' ' ' -' -' -' ' - --'
- #
- # Freedom in the Cloud
- #
- # Administrator control panel for the Freedombone system
- #
- # License
- # =======
- #
- # Copyright (C) 2015-2016 Bob Mottram <bob@robotics.uk.to>
- #
- # 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/>.
-
- PROJECT_NAME='freedombone'
-
- export TEXTDOMAIN=${PROJECT_NAME}-controlpanel
- export TEXTDOMAINDIR="/usr/share/locale"
-
- COMPLETION_FILE=$HOME/${PROJECT_NAME}-completed.txt
- SELECTED_USERNAME=
- SIP_CONFIGURATION_FILE=/etc/sipwitch.conf
- ADMIN_USER=
- UPGRADE_SCRIPT_NAME="${PROJECT_NAME}-upgrade"
- UPDATE_DATE_SCRIPT=/usr/bin/updatedate
-
- # Minimum number of characters in a password
- MINIMUM_PASSWORD_LENGTH=8
-
- # voip
- VOIP_PORT=64738
- VOIP_ONION_PORT=8095
-
- SSH_PORT=2222
-
- USB_DRIVE=sdb
- # get default USB from config file
- CONFIGURATION_FILE=/root/${PROJECT_NAME}.cfg
- if [ -f $CONFIGURATION_FILE ]; then
- if grep -q "USB_DRIVE=" $CONFIGURATION_FILE; then
- USB_DRIVE=$(cat $CONFIGURATION_FILE | grep "USB_DRIVE=" | awk -F '=' '{print $2}')
- if [[ $USB_DRIVE == *"dev"* ]]; then
- USB_DRIVE=$(echo ${USB_DRIVE} | awk -F '/' '{print $3}' | sed 's|1||g' | sed 's|2||g')
- fi
- fi
- if grep -q "SSH_PORT=" $CONFIGURATION_FILE; then
- SSH_PORT=$(cat $CONFIGURATION_FILE | grep "SSH_PORT=" | awk -F '=' '{print $2}')
- fi
- fi
-
- # Mirrors settings
- FRIENDS_MIRRORS_SERVER=
- FRIENDS_MIRRORS_SSH_PORT=2222
- FRIENDS_MIRRORS_PASSWORD=
- MY_MIRRORS_PASSWORD=
-
- function any_key {
- echo ' '
- read -n1 -r -p $"Press any key to continue..." key
- }
-
- function check_for_updates {
- if [ ! -f /etc/cron.weekly/$UPGRADE_SCRIPT_NAME ]; then
- dialog --title $"Check for updates" \
- --msgbox $"Upgrade script was not found" 6 40
- return
- fi
-
- clear
- . /etc/cron.weekly/$UPGRADE_SCRIPT_NAME
- any_key
- }
-
- function read_repo_servers {
- if [ -f $CONFIGURATION_FILE ]; then
- if grep -q "FRIENDS_MIRRORS_SERVER" $CONFIGURATION_FILE; then
- FRIENDS_MIRRORS_SERVER=$(grep "FRIENDS_MIRRORS_SERVER" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
- fi
- if grep -q "FRIENDS_MIRRORS_SSH_PORT" $CONFIGURATION_FILE; then
- FRIENDS_MIRRORS_SSH_PORT=$(grep "FRIENDS_MIRRORS_SSH_PORT" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
- fi
- if grep -q "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
- MY_MIRRORS_PASSWORD=$(grep "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
- fi
- if grep -q "FRIENDS_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
- FRIENDS_MIRRORS_PASSWORD=$(grep "FRIENDS_MIRRORS_PASSWORD" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
- fi
- fi
-
- if [ ! $FRIENDS_MIRRORS_SERVER ]; then
- return
- fi
- if [ ${#FRIENDS_MIRRORS_SERVER} -lt 2 ]; then
- return
- fi
-
- MAIN_COMMAND=/usr/local/bin/${PROJECT_NAME}
- if [ ! -f $MAIN_COMMAND ]; then
- MAIN_COMMAND=/usr/bin/${PROJECT_NAME}
- fi
-
- REPOS=($(cat ${MAIN_COMMAND} | grep "_REPO=\"" | uniq -u | sed 's|${PROJECT_NAME}|'"${PROJECT_NAME}"'|g'))
-
- for line in "${REPOS[@]}"
- do
- repo_name=$(echo "$line" | awk -F '=' '{print $1}')
- mirrors_name=$(echo "$repo_name" | sed "s|_REPO||g" | awk '{print tolower($0)}')
- friends_repo_url="ssh://mirrors@${FRIENDS_MIRRORS_SERVER}:${FRIENDS_MIRRORS_SSH_PORT}/home/mirrors/${mirrors_name}"
- ${repo_name}="${friends_repo_url}"
- done
- }
-
- function set_main_repo {
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Main Repository (Mirrors)" \
- --form $"If you do not wish to use the default repositories they can be obtained from mirrors on another ${PROJECT_NAME} server." 14 60 3 \
- $"URL:" 1 1 "$FRIENDS_MIRRORS_SERVER" 1 14 40 15 \
- $"SSH Port:" 2 1 "$FRIENDS_MIRRORS_SSH_PORT" 2 14 40 10000 \
- $"Password:" 3 1 "$FRIENDS_MIRRORS_PASSWORD" 3 14 40 10000 \
- 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- new_mirrors_url=$(cat $data | sed -n 1p)
- new_mirrors_ssh_port=$(cat $data | sed -n 2p)
- new_mirrors_password=$(cat $data | sed -n 3p)
-
- if [ ${#new_mirrors_url} -lt 2 ]; then
- return
- fi
- if [ ${#new_mirrors_ssh_port} -lt 1 ]; then
- return
- fi
- if [ ${#new_mirrors_password} -lt 10 ]; then
- dialog --title $"Main Repository" \
- --msgbox $'Mirrors password was too short. Should be at least 10 characters.' 6 40
- return
- fi
-
- if [[ $new_mirrors_url == *"."* ]]; then
- FRIENDS_MIRRORS_SERVER=$new_mirrors_url
- FRIENDS_MIRRORS_SSH_PORT=$new_mirrors_ssh_port
- FRIENDS_MIRRORS_PASSWORD=$new_mirrors_password
-
- if ! grep -q "FRIENDS_MIRRORS_SERVER" $CONFIGURATION_FILE; then
- echo "FRIENDS_MIRRORS_SERVER=$FRIENDS_MIRRORS_SERVER" >> $CONFIGURATION_FILE
- else
- sed -i "s|FRIENDS_MIRRORS_SERVER=.*|FRIENDS_MIRRORS_SERVER=$FRIENDS_MIRRORS_SERVER|g" $CONFIGURATION_FILE
- fi
-
- if ! grep -q "FRIENDS_MIRRORS_SSH_PORT" $CONFIGURATION_FILE; then
- echo "FRIENDS_MIRRORS_SSH_PORT=$FRIENDS_MIRRORS_SSH_PORT" >> $CONFIGURATION_FILE
- else
- sed -i "s|FRIENDS_MIRRORS_SSH_PORT=.*|FRIENDS_MIRRORS_SSH_PORT=$FRIENDS_MIRRORS_SSH_PORT|g" $CONFIGURATION_FILE
- fi
-
- if ! grep -q "FRIENDS_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
- echo "FRIENDS_MIRRORS_PASSWORD=$FRIENDS_MIRRORS_PASSWORD" >> $CONFIGURATION_FILE
- else
- sed -i "s|FRIENDS_MIRRORS_PASSWORD=.*|FRIENDS_MIRRORS_PASSWORD=$FRIENDS_MIRRORS_PASSWORD|g" $CONFIGURATION_FILE
- fi
-
- # re-read the repos
- read_repo_servers
-
- dialog --title $"Main Repository" \
- --msgbox $"Main repository set to $FRIENDS_MIRRORS_SERVER" 6 60
- fi
- }
-
- function add_user {
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Add new user" \
- --form "\n" 8 60 3 \
- $"Username:" 1 1 "" 1 28 16 15 \
- $"ssh public key (optional):" 2 1 "" 2 28 40 10000 \
- 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- new_user_username=$(cat $data | sed -n 1p)
- new_user_ssh_public_key=$(cat $data | sed -n 2p)
- if [ ${#new_user_username} -lt 2 ]; then
- dialog --title $"New username" \
- --msgbox $"No username was given" 6 40
- return
- fi
- if [[ "$new_user_username" == *" "* ]]; then
- dialog --title $"Invalid username" \
- --msgbox $"The username should not contain any spaces" 6 40
- return
- fi
- if [ ${#new_user_ssh_public_key} -lt 20 ]; then
- clear
- ${PROJECT_NAME}-adduser "$new_user_username"
- any_key
- else
- if [[ "$new_user_ssh_public_key" == "ssh-"* ]]; then
- clear
- ${PROJECT_NAME}-adduser "$new_user_username" "$new_user_ssh_public_key"
- any_key
- else
- dialog --title $"ssh public key" \
- --msgbox $"This does not look like an ssh public key" 6 40
- fi
- fi
- }
-
- function pad_string {
- echo -n -e "$1" | sed -e :a -e 's/^.\{1,25\}$/& /;ta'
- }
-
- function show_domains {
- DEFAULT_DOMAIN_NAME=$(cat $CONFIGURATION_FILE | grep "DEFAULT_DOMAIN_NAME=" | awk -F '=' '{print $2}')
-
- echo 'Domains'
- echo '======='
- echo ''
- echo -n -e "$(pad_string 'Name')"
- echo -n -e "$(pad_string 'ICANN')"
- echo -n -e "$(pad_string 'Tor')"
- echo ''
- echo '--------------------------------------------------------------------------'
- if grep -q "ssh onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'ssh')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'ssh onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "Email onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Email')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'Email onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "XMPP onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'XMPP')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'XMPP onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "VoIP onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'VoIP/Mumble')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'VoIP onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "SIP onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'SIP')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'SIP onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "IRC onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'IRC')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'IRC onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "tox onion domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Tox')"
- echo -n -e "$(pad_string ${DEFAULT_DOMAIN_NAME})"
- echo "$(cat ${COMPLETION_FILE} | grep 'tox onion domain' | awk -F ':' '{print $2}')"
- fi
- if grep -q "Wiki domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Wiki')"
- WIKIDOM=$(cat ${COMPLETION_FILE} | grep 'Wiki domain' | awk -F ':' '{print $2}')
- echo -n -e "$(pad_string ${WIKIDOM})"
- if [ -d /var/lib/tor/hidden_service_wiki ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_wiki/hostname)"
- fi
- echo ''
- fi
- if grep -q "Hubzilla domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Hubzilla')"
- HUBZILLADOM=$(cat ${COMPLETION_FILE} | grep 'Hubzilla domain' | awk -F ':' '{print $2}')
- echo -n -e "$(pad_string ${HUBZILLADOM})"
- if [ -d /var/lib/tor/hidden_service_hubzilla ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_hubzilla/hostname)"
- fi
- echo ''
- fi
- if grep -q "Blog domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Blog')"
- BLOGDOM=$(cat ${COMPLETION_FILE} | grep 'Blog domain' | awk -F ':' '{print $2}')
- echo -n -e "$(pad_string ${BLOGDOM})"
- if [ -d /var/lib/tor/hidden_service_blog ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_blog/hostname)"
- fi
- echo ''
- fi
- if grep -q "GNU Social domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'GNU Social')"
- GNUSOCIALDOM=$(cat ${COMPLETION_FILE} | grep 'GNU Social domain' | awk -F ':' '{print $2}')
- echo -n -e "$(pad_string ${GNUSOCIALDOM})"
- if [ -d /var/lib/tor/hidden_service_microblog ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_microblog/hostname)"
- fi
- echo ''
- fi
- if grep -q "Owncloud domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Owncloud')"
- OWNCLOUDDOM=$(cat ${COMPLETION_FILE} | grep 'Owncloud domain' | awk -F ':' '{print $2}')
- echo -n -e "$(pad_string ${OWNCLOUDDOM})"
- if [ -d /var/lib/tor/hidden_service_owncloud ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_owncloud/hostname)"
- fi
- echo ''
- fi
- if grep -q "Gogs domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'Gogs')"
- GOGSDOM=$(cat ${COMPLETION_FILE} | grep 'Gogs domain' | awk -F ':' '{print $2}')
- echo -n -e "$(pad_string ${GOGSDOM})"
- if [ -d /var/lib/tor/hidden_service_gogs ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_gogs/hostname)"
- fi
- echo ''
- fi
- if grep -q "RSS reader domain" $COMPLETION_FILE; then
- echo -n -e "$(pad_string 'RSS reader')"
- #RSSDOM=$(cat ${COMPLETION_FILE} | grep 'RSS reader domain' | awk -F ':' '{print $2}')
- RSSDOM='-'
- echo -n -e "$(pad_string ${RSSDOM})"
- if [ -d /var/lib/tor/hidden_service_ttrss ]; then
- echo -n "$(cat /var/lib/tor/hidden_service_ttrss/hostname)"
- fi
- echo ''
- fi
-
- echo ''
- }
-
- function show_users {
- echo 'Users'
- echo '====='
- echo ''
- echo -n -e "$(pad_string 'Name')"
- echo -n -e "$(pad_string 'SIP ext')"
- echo -n -e "$(pad_string 'Data')"
- echo ''
- echo '--------------------------------------------------------------------------'
- for d in /home/*/ ; do
- USRNAME=$(echo "$d" | awk -F '/' '{print $3}')
- if [[ $USRNAME != "git" && $USRNAME != "mirrors" ]]; then
- echo -n -e "$(pad_string ${USRNAME})"
- # get the SIP extension
- SIPEXT=
- while read ext; do
- if [[ $ext == *"user id"* ]]; then
- CURR_UID=$(echo "$ext" | awk -F '"' '{print $2}' | awk -F '"' '{print $1}')
- fi
- if [[ $ext == *"extension"* ]]; then
- if [[ $CURR_UID == $USRNAME ]]; then
- SIPEXT=$(echo "$ext" | awk -F '>' '{print $2}' | awk -F '<' '{print $1}')
- fi
- fi
- done < $SIP_CONFIGURATION_FILE
- if [ $SIPEXT ]; then
- echo -n -e "$(pad_string SIP:${SIPEXT})"
- else
- echo -n -e "$(pad_string '')"
- fi
-
- # size of the home directory
- echo "$(du -s -h /home/${USRNAME} | awk -F ' ' '{print $1}')"
- fi
- done
- echo ''
- }
-
- function show_mirrors_password {
- if [ ! /home/mirrors ]; then
- return
- fi
- if grep -q "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE; then
- MY_MIRRORS_PASSWORD=$(grep "MY_MIRRORS_PASSWORD" $CONFIGURATION_FILE | awk -F '=' '{print $2}')
- fi
- echo 'Local Mirrors'
- echo '============='
- echo ''
- echo -n "URL: "
- echo "$(cat ${COMPLETION_FILE} | grep 'ssh onion domain' | awk -F ':' '{print $2}')"
- echo "SSH Port: $SSH_PORT"
- echo "Password: $MY_MIRRORS_PASSWORD"
- echo ''
- }
-
- function show_about {
- clear
- show_domains
- show_mirrors_password
- show_users
- any_key
- }
-
- function select_user {
- SELECTED_USERNAME=
-
- users_array=($(ls /home))
-
- delete=(mirrors git)
- for del in ${delete[@]}
- do
- users_array=(${users_array[@]/$del})
- done
-
- i=0
- W=()
- name=()
- for u in ${users_array[@]}
- do
- i=$((i+1))
- W+=($i "$u")
- name+=("$u")
- done
-
- user_index=$(dialog --backtitle $"Freedombone Control Panel" --title $"Select User" --menu $"Select one of the following:" 24 40 17 "${W[@]}" 3>&2 2>&1 1>&3)
-
- if [ $? -eq 0 ]; then
- SELECTED_USERNAME="${name[$((user_index-1))]}"
- fi
- }
-
- function delete_user {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- if grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
- dialog --title $"Administrator user" \
- --msgbox $"You can't delete the administrator user" 6 40
- return
- fi
- clear
- ${PROJECT_NAME}-rmuser $SELECTED_USERNAME
- any_key
- }
-
- function configure_remote_backups {
- if ! grep -Fxq "Admin user:$ADMIN_USER" $COMPLETION_FILE; then
- dialog --title $"Administrator user" \
- --msgbox $"No Administrator user found. Check $COMPLETION_FILE" 6 40
- return
- fi
- if [ ${#ADMIN_USER} -lt 2 ]; then
- dialog --title $"Administrator user" \
- --msgbox $"Username not found" 6 40
- return
- fi
- if [ ! -d /home/$ADMIN_USER ]; then
- dialog --title $"Administrator user" \
- --msgbox $"Home directory not found" 6 40
- return
- fi
- ${PROJECT_NAME}-remote -u $ADMIN_USER
- if [ ! "$?" = "0" ]; then
- any_key
- fi
- }
-
- function change_password {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
-
- dialog --title $"Change password" \
- --passwordbox $"New password for user $SELECTED_USERNAME" 8 40 2> $data
- newpassword=$(<$data)
- if [ ${#newpassword} -lt ${MINIMUM_PASSWORD_LENGTH} ]; then
- dialog --title $"Change password" \
- --msgbox $"The password should be ${MINIMUM_PASSWORD_LENGTH} or more characters" 6 40
- return
- fi
-
- echo "$SELECTED_USERNAME:$newpassword"|chpasswd
-
- dialog --title $"Change password" \
- --msgbox $"Password for $SELECTED_USERNAME was changed" 6 40
- }
-
- function irc_set_global_password {
- dialog --title $"IRC Password" \
- --clear \
- --backtitle $"Freedombone Control Panel" \
- --passwordbox $"Password for all IRC users, or press Enter for no password" 10 50 2> $data
- sel=$?
- case $sel in
- 0)
- NEW_IRC_PASSWORD=$(<$data)
- sed -i "0,/RE/s/Password =.*/Password =$NEW_IRC_PASSWORD/" /etc/ngircd/ngircd.conf
- dialog --title $"IRC Password" \
- --msgbox $"The IRC password was changed" 6 40
- ;;
- esac
- }
-
- function change_ssh_public_key {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
-
- if grep -Fxq "Admin user:$SELECTED_USERNAME" $COMPLETION_FILE; then
- dialog --title $"Change ssh public key" \
- --backtitle $"Freedombone Control Panel" \
- --defaultno \
- --yesno $"\nThis is the administrator user.\n\nAre you sure you want to change the ssh public key for the administrator?" 10 60
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- fi
-
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Change ssh public key for $SELECTED_USERNAME" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $"Paste the ssh public key below" 8 60 2>$data
- sel=$?
- case $sel in
- 0)
- SSH_PUBLIC_KEY=$(<$data)
- if [ "$SSH_PUBLIC_KEY" ]; then
- if [ ${#SSH_PUBLIC_KEY} -gt 5 ]; then
- if [ -f "$SSH_PUBLIC_KEY" ]; then
- if [ ! -d /home/$SELECTED_USERNAME/.ssh ]; then
- mkdir /home/$SELECTED_USERNAME/.ssh
- fi
- cp $SSH_PUBLIC_KEY \
- /home/$SELECTED_USERNAME/.ssh/authorized_keys
- chown -R $SELECTED_USERNAME:$SELECTED_USERNAME \
- /home/$SELECTED_USERNAME/.ssh
- dialog --title $"Change ssh public key" \
- --msgbox $"ssh public key was installed" 6 40
- else
- if [[ "$SSH_PUBLIC_KEY" == "ssh-"* ]]; then
- if [ ! -d /home/$SELECTED_USERNAME/.ssh ]; then
- mkdir /home/$SELECTED_USERNAME/.ssh
- fi
- echo "$SSH_PUBLIC_KEY" > \
- /home/$SELECTED_USERNAME/.ssh/authorized_keys
- chown -R $SELECTED_USERNAME:$SELECTED_USERNAME \
- /home/$SELECTED_USERNAME/.ssh
- dialog --title $"Change ssh public key" \
- --msgbox $"ssh public key was installed" 6 40
- fi
- fi
- fi
- fi
- ;;
- esac
- }
-
- function remove_user_from_mailing_list {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- USER_MAILING_LISTS=$(cat "/home/$SELECTED_USERNAME/.procmailrc" | grep '\[' | grep '\]' | awk -F '\[' '{print $2}' | awk -F '\\' '{print $1}')
-
- i=0
- W=()
- list_name=()
- while read -r listname; do
- i=$((i+1))
- W+=($i "$listname")
- list_name+=("$listname")
- echo $listname
- done <<< "$USER_MAILING_LISTS"
-
- i=$((i+1))
- W+=($i $"Exit back to user mainenance")
-
- list_selected=$(dialog --default-item "$i" --backtitle $"Freedombone Control Panel" --title $"Remove a mailing list for $SELECTED_USERNAME" --menu $"Select one of the following:" 24 50 17 "${W[@]}" 3>&2 2>&1 1>&3)
-
- if [ $? -eq 0 ]; then # Exit with OK
- if [ ${list_selected} -ne ${i} ]; then
- remove_list_name="${list_name[$((list_selected-1))]}"
-
- # find the line number where the list is defined
- line_number=0
- i=0
- while read -r line
- do
- if [[ "$line" == *"\[${remove_list_name}\\]"* ]]; then
- line_number=${i}
- fi
- i=$((i+1))
- done < "/home/$SELECTED_USERNAME/.procmailrc"
-
- if [ ${line_number} -eq 0 ]; then
- # no match was found
- return
- fi
-
- # recreate the file
- if [ -f /home/${SELECTED_USERNAME}/.procmailrc_new ]; then
- rm /home/${SELECTED_USERNAME}/.procmailrc_new
- fi
- i=0
- clip=0
- while read -r line
- do
- i=$((i+1))
- if [ ${i} -gt $((line_number-1)) ]; then
- if [ ${clip} -eq 0 ]; then
- clip=1
- fi
- if [ ${clip} -eq 1 ]; then
- if [ ${i} -lt $((line_number+2)) ]; then
- continue
- else
- if [ ${#line} -lt 1 ]; then
- clip=2
- continue
- fi
- if [[ "$line" == ":"* || "$line" == "#"* ]]; then
- clip=2
- else
- continue
- fi
- fi
- fi
- fi
-
- echo "$line" >> /home/${SELECTED_USERNAME}/.procmailrc_new
-
- if [[ "$line" == *"\[${remove_list_name}\\]"* ]]; then
- line_number=${i}
- fi
- done < "/home/$SELECTED_USERNAME/.procmailrc"
- cp /home/${SELECTED_USERNAME}/.procmailrc_new /home/${SELECTED_USERNAME}/.procmailrc
- rm /home/${SELECTED_USERNAME}/.procmailrc_new
- chown ${SELECTED_USERNAME}:${SELECTED_USERNAME} /home/${SELECTED_USERNAME}/.procmailrc
- dialog --title $"Remove user from mailing list" \
- --msgbox $"${SELECTED_USERNAME} has been removed from ${remove_list_name}" 6 50
- fi
- fi
- }
-
- function add_to_mailing_list {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Subscribe $SELECTED_USERNAME to a mailing list" \
- --form $"You can either enter a subject or an email address\n" 11 68 4 \
- $"List folder name:" 1 1 "" 1 35 26 25 \
- $"Name between [] on subject line:" 2 1 "" 2 35 26 25 \
- $"List email address:" 3 1 "" 3 35 26 25 \
- $"Public:" 4 1 $"yes" 4 35 4 25 \
- 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- LIST_NAME=$(cat $data | sed -n 1p)
- LIST_SUBJECT=$(cat $data | sed -n 2p)
- LIST_EMAIL=$(cat $data | sed -n 3p)
- LIST_PUBLIC=$(cat $data | sed -n 4p)
-
- if [ ${#LIST_PUBLIC} -lt 1 ]; then
- LIST_PUBLIC='no'
- fi
- if [[ $LIST_PUBLIC == $'y' || $LIST_PUBLIC == $'Y' || $LIST_PUBLIC == $'true' || $LIST_PUBLIC == $'True' || $LIST_PUBLIC == $'yes' || $LIST_PUBLIC == $'Yes' || $LIST_PUBLIC == $'YES' ]]; then
- LIST_PUBLIC='yes'
- else
- LIST_PUBLIC='no'
- fi
- if [ ${#LIST_NAME} -lt 2 ]; then
- dialog --title $"Add mailing list" \
- --msgbox $"No mailing list name was given" 6 40
- return
- fi
- if [ ${#LIST_SUBJECT} -lt 2 ]; then
- if [ ${#LIST_EMAIL} -lt 2 ]; then
- dialog --title $"Add mailing list" \
- --msgbox $"No mailing list subject or address was given" 6 40
- return
- fi
- fi
- if [ ${#LIST_SUBJECT} -gt 1 ]; then
- ${PROJECT_NAME}-addlist -u $SELECTED_USERNAME -l "$LIST_NAME" \
- -s "$LIST_SUBJECT" --public $LIST_PUBLIC
- else
- if [[ "$LIST_EMAIL" != *"@"* || "$LIST_EMAIL" != *"."* ]]; then
- dialog --title $"Add mailing list" \
- --msgbox $"Unrecognised email address" 6 40
- return
- else
- ${PROJECT_NAME}-addlist -u $SELECTED_USERNAME -l "$LIST_NAME" \
- -e "$LIST_EMAIL" --public $LIST_PUBLIC
- fi
- fi
-
- dialog --title $"Add mailing list" \
- --msgbox $"$LIST_NAME list was added" 6 40
- }
-
- function email_rule {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Email rule for user $SELECTED_USERNAME" \
- --form "\n" 9 65 4 \
- $"When email arrives from address:" 1 1 "" 1 35 24 28 \
- $"Move to folder:" 2 1 "" 2 35 24 28 \
- $"Public:" 3 1 $"no" 3 35 4 25 \
- 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- RULE_EMAIL=$(cat $data | sed -n 1p)
- RULE_FOLDER=$(cat $data | sed -n 2p)
- RULE_PUBLIC=$(cat $data | sed -n 3p)
-
- if [ ${#RULE_PUBLIC} -lt 1 ]; then
- RULE_PUBLIC='no'
- fi
- if [[ $RULE_PUBLIC == $'y' || $RULE_PUBLIC == $'Y' || $RULE_PUBLIC == $'true' || $RULE_PUBLIC == $'True' || $RULE_PUBLIC == $'yes' || $RULE_PUBLIC == $'Yes' || $RULE_PUBLIC == $'YES' ]]; then
- RULE_PUBLIC='yes'
- else
- RULE_PUBLIC='no'
- fi
- if [ ${#RULE_EMAIL} -lt 2 ]; then
- dialog --title $"Add email rule" \
- --msgbox $"No email address was given" 6 40
- return
- fi
- if [ ${#RULE_FOLDER} -lt 2 ]; then
- dialog --title $"Add email rule" \
- --msgbox $"No folder name was given" 6 40
- return
- fi
- if [[ "$RULE_EMAIL" != *"@"* || "$RULE_EMAIL" != *"."* ]]; then
- dialog --title $"Add email rule" \
- --msgbox $"Unrecognised email address" 6 40
- return
- fi
-
- ${PROJECT_NAME}-addemail -u $SELECTED_USERNAME -e "$RULE_EMAIL" \
- -g "$RULE_FOLDER" --public $RULE_PUBLIC
- dialog --title $"Add email rule" \
- --msgbox $"Email rule for $RULE_EMAIL was added" 6 40
- }
-
- function block_unblock_email {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- blockstr=$"Block/Unblock email going to"
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title "$blockstr $SELECTED_USERNAME" \
- --form "\n" 8 65 3 \
- $"When email arrives from address:" 1 1 "" 1 35 24 28 \
- $"Block it:" 2 1 "yes" 2 35 4 4 \
- 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- BLOCK_EMAIL=$(cat $data | sed -n 1p)
- BLOCK=$(cat $data | sed -n 2p)
- if [ ${#BLOCK_EMAIL} -lt 2 ]; then
- dialog --title $"Block/Unblock an email" \
- --msgbox $"No email address was given" 6 40
- return
- fi
- if [[ "$BLOCK_EMAIL" != *"@"* || "$BLOCK_EMAIL" != *"."* ]]; then
- dialog --title $"Block/Unblock an email" \
- --msgbox $"Unrecognised email address" 6 40
- return
- fi
- if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
- ${PROJECT_NAME}-ignore -u $SELECTED_USERNAME -e "$BLOCK_EMAIL"
- dialog --title $"Block an email" \
- --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME blocked" 6 40
- else
- ${PROJECT_NAME}-unignore -u $SELECTED_USERNAME -e "$BLOCK_EMAIL"
- dialog --title $"Unblock an email" \
- --msgbox "Email from $BLOCK_EMAIL to $SELECTED_USERNAME unblocked" 6 40
- fi
- }
-
- function block_unblock_subject {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- blockstr=$"Block/Unblock email going to"
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title "$blockstr $SELECTED_USERNAME" \
- --form "\n" 8 70 3 \
- $"When email arrives with subject text:" 1 1 "" 1 40 24 28 \
- $"Block it:" 2 1 "yes" 2 40 4 4 \
- 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- BLOCK_SUBJECT=$(cat $data | sed -n 1p)
- BLOCK=$(cat $data | sed -n 2p)
- if [ ${#BLOCK_SUBJECT} -lt 2 ]; then
- dialog --title $"Block/Unblock an email" \
- --msgbox $"No subject was given" 6 40
- return
- fi
- if [[ $BLOCK == "y"* || $BLOCK == "Y"* ]]; then
- ${PROJECT_NAME}-ignore -u $SELECTED_USERNAME -t "$BLOCK_SUBJECT"
- dialog --title $"Block an email" \
- --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME blocked" 6 40
- else
- ${PROJECT_NAME}-unignore -u $SELECTED_USERNAME -t "$BLOCK_SUBJECT"
- dialog --title $"Unblock an email" \
- --msgbox "Email with subject $BLOCK_SUBJECT to $SELECTED_USERNAME unblocked" 6 40
- fi
- }
-
- function create_keydrive_master {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- dialog --title $"USB Master Keydrive" \
- --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
- clear
- ${PROJECT_NAME}-keydrive -u $SELECTED_USERNAME --master 'yes'
- any_key
- }
-
- function create_keydrive_fragment {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- dialog --title $"USB Fragment Keydrive" \
- --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
- clear
- ${PROJECT_NAME}-keydrive -u $SELECTED_USERNAME
- any_key
- }
-
- function backup_data {
- dialog --title $"Backup data to USB" \
- --msgbox $"Plug in a LUKS encrypted USB drive" 6 40
- clear
- echo ' '
- echo $'Enter the passphrase for your LUKS encrypted backup drive:'
- ${PROJECT_NAME}-backup-local
- any_key
- }
-
- function restore_from_usb {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Restore from USB backup" \
- --radiolist $"Choose an application to restore:" 30 70 27 \
- 1 $"Everything" on \
- 2 $"Return to the backup and restore menu" off \
- 3 $"Configuration files" off \
- 4 $"MariaDB settings" off \
- 5 $"Let's Encrypt account" off \
- 6 $"Mutt email client settings" off \
- 7 $"GPG keys" off \
- 8 $"Email processing rules" off \
- 9 $"Spam filtering rules" off \
- 10 $"Administrator's README file" off \
- 11 $"IPFS" off \
- 12 $"SSH keys" off \
- 13 $"User configuration files" off \
- 14 $"SSL/TLS certificates" off \
- 15 $"Personal settings" off \
- 16 $"Mailing List" off \
- 17 $"XMPP chat" off \
- 18 $"GNU Social" off \
- 19 $"Hubzilla" off \
- 20 $"Owncloud" off \
- 21 $"Gogs" off \
- 22 $"Wiki" off \
- 23 $"Blog" off \
- 24 $"CJDNS" off \
- 25 $"Email" off \
- 26 $"DLNA" off \
- 27 $"VoIP" off \
- 28 $"Tox" off 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) ${PROJECT_NAME}-restore-local $USB_DRIVE;;
- 2) return;;
- 3) ${PROJECT_NAME}-restore-local $USB_DRIVE configuration;;
- 4) ${PROJECT_NAME}-restore-local $USB_DRIVE mariadb;;
- 5) ${PROJECT_NAME}-restore-local $USB_DRIVE letsencrypt;;
- 6) ${PROJECT_NAME}-restore-local $USB_DRIVE mutt;;
- 7) ${PROJECT_NAME}-restore-local $USB_DRIVE gpg;;
- 8) ${PROJECT_NAME}-restore-local $USB_DRIVE procmail;;
- 9) ${PROJECT_NAME}-restore-local $USB_DRIVE spamassassin;;
- 10) ${PROJECT_NAME}-restore-local $USB_DRIVE readme;;
- 11) ${PROJECT_NAME}-restore-local $USB_DRIVE ipfs;;
- 12) ${PROJECT_NAME}-restore-local $USB_DRIVE ssh;;
- 13) ${PROJECT_NAME}-restore-local $USB_DRIVE userconfig;;
- 14) ${PROJECT_NAME}-restore-local $USB_DRIVE certs;;
- 15) ${PROJECT_NAME}-restore-local $USB_DRIVE personal;;
- 16) ${PROJECT_NAME}-restore-local $USB_DRIVE mailinglist;;
- 17) ${PROJECT_NAME}-restore-local $USB_DRIVE xmpp;;
- 18) ${PROJECT_NAME}-restore-local $USB_DRIVE gnusocial;;
- 19) ${PROJECT_NAME}-restore-local $USB_DRIVE hubzilla;;
- 20) ${PROJECT_NAME}-restore-local $USB_DRIVE owncloud;;
- 21) ${PROJECT_NAME}-restore-local $USB_DRIVE gogs;;
- 22) ${PROJECT_NAME}-restore-local $USB_DRIVE wiki;;
- 23) ${PROJECT_NAME}-restore-local $USB_DRIVE blog;;
- 24) ${PROJECT_NAME}-restore-local $USB_DRIVE cjdns;;
- 25) ${PROJECT_NAME}-restore-local $USB_DRIVE email;;
- 26) ${PROJECT_NAME}-restore-local $USB_DRIVE dlna;;
- 27) ${PROJECT_NAME}-restore-local $USB_DRIVE voip;;
- 28) ${PROJECT_NAME}-restore-local $USB_DRIVE tox;;
- esac
- done
- any_key
- }
-
- function restore_from_remote {
- remote_domain_name=$1
-
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Restore from ${remote_domain_name}" \
- --radiolist $"Choose an application to restore:" 30 70 27 \
- 1 $"Everything" on \
- 2 $"Return to the backup and restore menu" off \
- 3 $"Configuration files" off \
- 4 $"MariaDB settings" off \
- 5 $"Let's Encrypt account" off \
- 6 $"Mutt email client settings" off \
- 7 $"GPG keys" off \
- 8 $"Email processing rules" off \
- 9 $"Spam filtering rules" off \
- 10 $"Administrator's README file" off \
- 11 $"IPFS" off \
- 12 $"SSH keys" off \
- 13 $"User configuration files" off \
- 14 $"SSL/TLS certificates" off \
- 15 $"Personal settings" off \
- 16 $"Mailing List" off \
- 17 $"XMPP chat" off \
- 18 $"GNU Social" off \
- 19 $"Hubzilla" off \
- 20 $"Owncloud" off \
- 21 $"Gogs" off \
- 22 $"Wiki" off \
- 23 $"Blog" off \
- 24 $"CJDNS" off \
- 25 $"Email" off \
- 26 $"DLNA" off \
- 27 $"VoIP" off \
- 28 $"Tox" off 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) ${PROJECT_NAME}-restore-remote $remote_domain_name;;
- 2) return;;
- 3) ${PROJECT_NAME}-restore-remote $remote_domain_name configuration;;
- 4) ${PROJECT_NAME}-restore-remote $remote_domain_name mariadb;;
- 5) ${PROJECT_NAME}-restore-remote $remote_domain_name letsencrypt;;
- 6) ${PROJECT_NAME}-restore-remote $remote_domain_name mutt;;
- 7) ${PROJECT_NAME}-restore-remote $remote_domain_name gpg;;
- 8) ${PROJECT_NAME}-restore-remote $remote_domain_name procmail;;
- 9) ${PROJECT_NAME}-restore-remote $remote_domain_name spamassassin;;
- 10) ${PROJECT_NAME}-restore-remote $remote_domain_name readme;;
- 11) ${PROJECT_NAME}-restore-remote $remote_domain_name ipfs;;
- 12) ${PROJECT_NAME}-restore-remote $remote_domain_name ssh;;
- 13) ${PROJECT_NAME}-restore-remote $remote_domain_name userconfig;;
- 14) ${PROJECT_NAME}-restore-remote $remote_domain_name certs;;
- 15) ${PROJECT_NAME}-restore-remote $remote_domain_name personal;;
- 16) ${PROJECT_NAME}-restore-remote $remote_domain_name mailinglist;;
- 17) ${PROJECT_NAME}-restore-remote $remote_domain_name xmpp;;
- 18) ${PROJECT_NAME}-restore-remote $remote_domain_name gnusocial;;
- 19) ${PROJECT_NAME}-restore-remote $remote_domain_name hubzilla;;
- 20) ${PROJECT_NAME}-restore-remote $remote_domain_name owncloud;;
- 21) ${PROJECT_NAME}-restore-remote $remote_domain_name gogs;;
- 22) ${PROJECT_NAME}-restore-remote $remote_domain_name wiki;;
- 23) ${PROJECT_NAME}-restore-remote $remote_domain_name blog;;
- 24) ${PROJECT_NAME}-restore-remote $remote_domain_name cjdns;;
- 25) ${PROJECT_NAME}-restore-remote $remote_domain_name email;;
- 26) ${PROJECT_NAME}-restore-remote $remote_domain_name dlna;;
- 27) ${PROJECT_NAME}-restore-remote $remote_domain_name voip;;
- 28) ${PROJECT_NAME}-restore-remote $remote_domain_name tox;;
- esac
- done
- any_key
- }
-
- function restore_data {
- dialog --title $"Restore data from USB" \
- --msgbox $"Plug in your backup USB drive" 6 40
- clear
- echo ' '
- echo $'Enter the passphrase for your LUKS encrypted backup drive:'
- restore_from_usb
- }
-
- function restore_data_remote {
- if [ ! $ADMIN_USER ]; then
- dialog --title $"Restore data from remote server" \
- --msgbox $"Unknown admin user" 6 40
- return
- fi
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Restore from remote server" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $"Enter the domain name of the server from which you wish to restore" 8 60 2>$data
- sel=$?
- case $sel in
- 0)
- friend_server_domain_name=$(<$data)
-
- if [ ${#friend_server_domain_name} -lt 2 ]; then
- return
- fi
-
- if [[ $friend_server_domain_name != *"."* ]]; then
- dialog --title $"Remote server domain name" \
- --msgbox $"Invalid domain name" 6 40
- return
- fi
-
- restore_from_remote $friend_server_domain_name
- ;;
- esac
- }
-
- function ping_enable_disable {
- ping_str=$"\nDo you want to enable other systems to ping this machine?\n\nPing may be useful for diagnostic purposes, but for added security you may not want to enable it."
- enable_ping="no"
- dialog --title $"Enable Ping / ICMP" \
- --backtitle $"Freedombone Control Panel" \
- --defaultno \
- --yesno "$ping_str" 10 60
- sel=$?
- case $sel in
- 0) enable_ping="yes";;
- 255) return;;
- esac
-
- if [[ $enable_ping == "yes" ]]; then
- iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
- iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
- echo "0" > /proc/sys/net/ipv4/icmp_echo_ignore_all
- else
- iptables -D INPUT -p icmp --icmp-type echo-request -j ACCEPT
- iptables -D OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
- echo "1" > /proc/sys/net/ipv4/icmp_echo_ignore_all
- fi
- }
-
- function logging_on_off {
- logging="no"
- dialog --title $"Logging" \
- --backtitle $"Freedombone Control Panel" \
- --yesno $"\nDo you want to turn logging on?" 7 60
- sel=$?
- case $sel in
- 0) logging="yes";;
- 255) return;;
- esac
-
- clear
- echo ''
- echo $'This may take a few seconds. Please wait...'
- if [[ $logging == "no" ]]; then
- ${PROJECT_NAME}-logging off
- else
- ${PROJECT_NAME}-logging on
- fi
- }
-
- function restore_gpg_key {
- select_user
- if [ ! $SELECTED_USERNAME ]; then
- return
- fi
- restorestr=$"Restore GPG key for user"
- dialog --title "$restorestr $SELECTED_USERNAME" \
- --msgbox $"Plug in your USB keydrive" 6 40
- clear
- ${PROJECT_NAME}-recoverkey -u $SELECTED_USERNAME
- any_key
- }
-
- function security_settings {
- ${PROJECT_NAME}-sec
- any_key
- }
-
- function reset_tripwire {
- clear
- echo $'Resetting the Tripwire...'
- echo ' '
- echo '
-
- ' | reset-tripwire
- any_key
- }
-
- function hubzilla_renew_cert {
- dialog --title $"Renew SSL certificate" \
- --backtitle $"Freedombone Control Panel" \
- --yesno $"\nThis will renew a letsencrypt certificate. Select 'yes' to continue" 16 60
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- HUBZILLA_DOMAIN_NAME=$(cat $COMPLETION_FILE | grep "Hubzilla domain" | awk -F ':' '{print $2}')
- if [ ! -d /var/www/$HUBZILLA_DOMAIN_NAME/htdocs ]; then
- dialog --title $"Renew SSL certificate" \
- --msgbox $"Hubzilla install directory not found" 6 40
- return
- fi
- ${PROJECT_NAME}-renew-cert -h $HUBZILLA_DOMAIN_NAME -p 'letsencrypt'
- if [ ! "$?" = "0" ]; then
- any_key
- else
- dialog --title $"Renew SSL certificate" \
- --msgbox $"Hubzilla certificate has been renewed" 6 40
- fi
- }
-
- function hubzilla_channel_directory_server {
- if ! grep -q "Hubzilla domain" $COMPLETION_FILE; then
- dialog --title $"Hubzilla channel directory server" \
- --msgbox $"Hubzilla is not installed on this system" 6 40
- return
- fi
- HUBZILLA_DOMAIN_NAME=$(cat $COMPLETION_FILE | grep "Hubzilla domain" | awk -F ':' '{print $2}')
- if [ ! -d /var/www/$HUBZILLA_DOMAIN_NAME/htdocs ]; then
- dialog --title $"Hubzilla channel directory server" \
- --msgbox $"Hubzilla install directory not found" 6 40
- return
- fi
-
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Hubzilla channel directory server" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $"When you click on 'channel directory' this is where Hubzilla will obtain its list from" 8 60 2>$data
- sel=$?
- case $sel in
- 0)
- hubzilla_domain_server=$(<$data)
- if [[ $hubzilla_domain_server != *"."* ]]; then
- return
- fi
- if [[ $hubzilla_domain_server != "https"* ]]; then
- dialog --title $"Hubzilla channel directory server" \
- --msgbox $"Invalid domain - include the https://" 6 40
- return
- fi
- ./var/www/$HUBZILLA_DOMAIN_NAME/htdocs/util/config system directory_server $hubzilla_domain_server
- dialog --title $"Hubzilla channel directory server" \
- --msgbox $"Domain channel directory server changed to $hubzilla_domain_server" 6 40
- ;;
- esac
- }
-
- function format_drive {
- drive=
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Format a USB drive (LUKS encrypted)" \
- --radiolist $"Choose a drive:" 12 70 5 \
- 1 $"sda (Beaglebone Black)" off \
- 2 $"sdb" off \
- 3 $"sdc" off \
- 4 $"sdd" off \
- 5 $"Back to Backup and Restore menu" on 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- case $(cat $data) in
- 1) drive='sda';;
- 2) drive='sdb';;
- 3) drive='sdc';;
- 4) drive='sdd';;
- 5) return;;
- esac
-
- dialog --title $"Format USB drive" \
- --backtitle $"Freedombone Control Panel" \
- --defaultno \
- --yesno $"\nPlease confirm that you wish to format drive\n\n ${drive}\n\nAll current data on the drive will be lost, and you will be prompted to give a password used to encrypt the drive.\n\nDANGER: If you screw up here and format the wrong drive it's your own fault!" 16 60
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
-
- clear
- ${PROJECT_NAME}-format $drive
- any_key
- }
-
- function remove_backups {
- drive=
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Remove backups from a USB drive" \
- --radiolist $"Choose a drive:" 12 70 5 \
- 1 $"sda (Beaglebone Black)" off \
- 2 $"sdb" off \
- 3 $"sdc" off \
- 4 $"sdd" off \
- 5 $"Back to Backup and Restore menu" on 2> $data
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- case $(cat $data) in
- 1) drive='sda';;
- 2) drive='sdb';;
- 3) drive='sdc';;
- 4) drive='sdd';;
- 5) return;;
- esac
-
- dialog --title $"Remove backups from a USB drive" \
- --backtitle $"Freedombone Control Panel" \
- --defaultno \
- --yesno $"\nPlease confirm that you wish to remove backups from this drive\n\n ${drive}\n\nYou will not be able to recover them afterwards." 12 60
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
-
- clear
- ${PROJECT_NAME}-backup-local $drive remove
- any_key
- }
-
- function shut_down_system {
- dialog --title $"Power off the system" \
- --backtitle $"Freedombone Control Panel" \
- --defaultno \
- --yesno $"\nPlease confirm that you wish to power off the system.\n\nWARNING: to power on again you will need to have physical access to the hardware." 10 60
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- shutdown now
- }
-
- function restart_system {
- dialog --title $"Restart the system" \
- --backtitle $"Freedombone Control Panel" \
- --defaultno \
- --yesno $"\nPlease confirm that you wish to restart the system.\n\nWARNING: If you are using full disk encryption then you will need physical access to the hardware to type in the password" 10 60
- sel=$?
- case $sel in
- 1) return;;
- 255) return;;
- esac
- reboot
- }
-
- function change_system_name {
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Change the name of this system" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $'Enter a new name for this system on your local network\n\nIt will appear as newname.local' 10 60 2>$data
- sel=$?
- case $sel in
- 0) NEW_SYSTEM_NAME=$(<$data)
- if [ "$NEW_SYSTEM_NAME" ]; then
- if [ ${#NEW_SYSTEM_NAME} -gt 1 ]; then
- sed -i "s|host-name=.*|host-name=$NEW_SYSTEM_NAME|g" /etc/avahi/avahi-daemon.conf
- systemctl restart avahi-daemon
- if grep -q "host-name=$NEW_SYSTEM_NAME" /etc/avahi/avahi-daemon.conf; then
- dialog --title $"New local network name" \
- --msgbox $"The name of this system on your local network was changed successfully" 6 70
- fi
- fi
- fi
- ;;
- esac
- }
-
- function set_tls_time_source {
- TLS_DATE_SOURCE=$(cat /usr/bin/updatedate | grep "TIMESOURCE='" | awk -F '=' '{print $2}' | awk -F "'" '{print $2}')
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Set the TLS date/time source" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $"Enter a domain name to use as a TLS time source.\n\nFactors to consider when choosing a source are whether you wish that site to know that your system is 'alive' and also what might happen if an adversary were to try to mess with the date/time from that domain (i.e. how much blowback would there be)." 14 60 "$TLS_DATE_SOURCE" 2>$data
- sel=$?
- case $sel in
- 0) NEW_TLS_DATE_SOURCE=$(<$data)
- if [[ $NEW_TLS_DATE_SOURCE == *"."* && $NEW_TLS_DATE_SOURCE != *'/'* ]]; then
- if [[ $NEW_TLS_DATE_SOURCE != "http"* ]]; then
- sed -i "s|TIMESOURCE='.*|TIMESOURCE='${NEW_TLS_DATE_SOURCE}'|g" $UPDATE_DATE_SCRIPT
- else
- dialog --title $"Invalid domain name" \
- --msgbox $"Don't include the 'https'" 6 70
- fi
- else
- dialog --title $"Invalid domain name" \
- --msgbox $"That doesn't look like a domain name" 6 70
- fi
- ;;
- esac
- }
-
- function set_static_IP {
- STATIC_IP='192.168.1.60'
- STATIC_GATEWAY='192.168.1.1'
- NEW_STATIC_IP=
- NEW_STATIC_GATEWAY=
- if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
- STATIC_IP=$(cat /etc/network/interfaces | grep "address " | awk -F ' ' '{print $2}' | head -n 1)
- STATIC_GATEWAY=$(cat /etc/network/interfaces | grep "gateway " | awk -F ' ' '{print $2}' | head -n 1)
- fi
-
- # get the IP for the box
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Set a static local IP address" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $"In order to forward incoming internet traffic to this system most internet routers need to know a static local IP address to send the data to.\n\n
- Enter a static local IP address for this system.\n\nIt will typically be 192.168.1.x" 15 60 "$STATIC_IP" 2>$data
- sel=$?
- case $sel in
- 0) NEW_STATIC_IP=$(<$data)
- if [[ "$NEW_STATIC_IP" != *"."* ]]; then
- return
- fi
- if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
- if [[ "$NEW_STATIC_IP" != "$STATIC_IP" ]]; then
- sed -i "s|${STATIC_IP}|${NEW_STATIC_IP}|g" /etc/network/interfaces
- fi
- fi
- ;;
- esac
-
- # get the gateway
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --title $"Set the IP address of your internet router/modem" \
- --backtitle $"Freedombone Control Panel" \
- --inputbox $"Set the local IP address for your internet router or ADSL modem.\n\nIt will typically be 192.168.1.1, 192.168.1.254, or similar" 12 60 "$STATIC_GATEWAY" 2>$data
- sel=$?
- case $sel in
- 0) NEW_STATIC_GATEWAY=$(<$data)
- if [[ "$NEW_STATIC_GATEWAY" != *"."* ]]; then
- return
- fi
- if grep -q 'iface eth0 inet static' /etc/network/interfaces; then
- if [[ "$NEW_STATIC_GATEWAY" != "$STATIC_GATEWAY" ]]; then
- sed -i "s|${STATIC_GATEWAY}|${NEW_STATIC_GATEWAY}|g" /etc/network/interfaces
- fi
- return
- fi
- ;;
- esac
-
- if ! grep -q 'iface eth0 inet static' /etc/network/interfaces; then
- if [ "$NEW_STATIC_GATEWAY" && "$NEW_STATIC_IP" ]; then
- echo '# This file describes the network interfaces available on your system' > /etc/network/interfaces
- echo '# and how to activate them. For more information, see interfaces(5).' >> /etc/network/interfaces
- echo '' >> /etc/network/interfaces
- echo '# The loopback network interface' >> /etc/network/interfaces
- echo 'auto lo' >> /etc/network/interfaces
- echo 'iface lo inet loopback' >> /etc/network/interfaces
- echo '' >> /etc/network/interfaces
- echo '# The primary network interface' >> /etc/network/interfaces
- echo 'auto eth0' >> /etc/network/interfaces
- echo 'iface eth0 inet static' >> /etc/network/interfaces
- echo " address ${NEW_STATIC_IP}" >> /etc/network/interfaces
- echo ' netmask 255.255.255.0' >> /etc/network/interfaces
- echo " gateway ${NEW_STATIC_GATEWAY}" >> /etc/network/interfaces
- echo " dns-nameservers 213.73.91.35 85.214.20.141" >> /etc/network/interfaces
- echo '# Example to keep MAC address between reboots' >> /etc/network/interfaces
- echo '#hwaddress ether DE:AD:BE:EF:CA:FE' >> /etc/network/interfaces
- echo '' >> /etc/network/interfaces
- echo '# The secondary network interface' >> /etc/network/interfaces
- echo '#auto eth1' >> /etc/network/interfaces
- echo '#iface eth1 inet dhcp' >> /etc/network/interfaces
- echo '' >> /etc/network/interfaces
- echo '# WiFi Example' >> /etc/network/interfaces
- echo "#auto $WIFI_INTERFACE" >> /etc/network/interfaces
- echo "#iface $WIFI_INTERFACE inet dhcp" >> /etc/network/interfaces
- echo '# wpa-ssid "essid"' >> /etc/network/interfaces
- echo '# wpa-psk "password"' >> /etc/network/interfaces
- echo '' >> /etc/network/interfaces
- echo '# Ethernet/RNDIS gadget (g_ether)' >> /etc/network/interfaces
- echo '# ... or on host side, usbnet and random hwaddr' >> /etc/network/interfaces
- echo '# Note on some boards, usb0 is automaticly setup with an init script' >> /etc/network/interfaces
- echo '#iface usb0 inet static' >> /etc/network/interfaces
- echo '# address 192.168.7.2' >> /etc/network/interfaces
- echo '# netmask 255.255.255.0' >> /etc/network/interfaces
- echo '# network 192.168.7.0' >> /etc/network/interfaces
- echo '# gateway 192.168.7.1' >> /etc/network/interfaces
- fi
- fi
- }
-
- function menu_backup_restore {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Backup and Restore" \
- --radiolist $"Choose an operation:" 18 70 11 \
- 1 $"Backup data to USB drive" off \
- 2 $"Restore GPG key from USB keydrive" off \
- 3 $"Restore data from USB drive" off \
- 4 $"Configure remote backups" off \
- 5 $"Restore from remote backup" off \
- 6 $"Backup GPG key to USB (master keydrive)" off \
- 7 $"Backup GPG key to USB (fragment keydrive)" off \
- 8 $"Format a USB drive (LUKS encrypted)" off \
- 9 $"Remove backups from a USB drive" off \
- 10 $"Back to main menu" on 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) backup_data;;
- 2) restore_gpg_key;;
- 3) restore_data;;
- 4) configure_remote_backups;;
- 5) restore_data_remote;;
- 6) create_keydrive_master;;
- 7) create_keydrive_fragment;;
- 8) format_drive;;
- 9) remove_backups;;
- 10) break;;
- esac
- done
- }
-
- function menu_email {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Email Filtering Rules" \
- --radiolist $"Choose an operation:" 13 70 6 \
- 1 $"Add a user to a mailing list" off \
- 2 $"Remove a user from a mailing list" off \
- 3 $"Add an email rule" off \
- 4 $"Block/Unblock an email address" off \
- 5 $"Block/Unblock email with subject text" off \
- 6 $"Back to main menu" on 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) add_to_mailing_list;;
- 2) remove_user_from_mailing_list;;
- 3) email_rule;;
- 4) block_unblock_email;;
- 5) block_unblock_subject;;
- 6) break;;
- esac
- done
- }
-
- function menu_users {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Manage Users" \
- --radiolist $"Choose an operation:" 12 70 5 \
- 1 $"Add a user" off \
- 2 $"Delete a user" off \
- 3 $"Change user password" off \
- 4 $"Change user ssh public key" off \
- 5 $"Back to main menu" on 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) add_user;;
- 2) delete_user;;
- 3) change_password;;
- 4) change_ssh_public_key;;
- 5) break;;
- esac
- done
- }
-
- function menu_hubzilla {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Hubzilla" \
- --radiolist $"Choose an operation:" 13 70 4 \
- 1 $"Set channel directory server" off \
- 2 $"Renew SSL certificate" off \
- 3 $"Back to main menu" on 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) hubzilla_channel_directory_server;;
- 2) hubzilla_renew_cert;;
- 3) break;;
- esac
- done
- }
-
- function menu_media {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Media Menu" \
- --radiolist $"Choose an operation:" 13 70 3 \
- 1 $"Attach a drive containing playable media" off \
- 2 $"Remove a drive containing playable media" off \
- 3 $"Exit" on 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) remove-music
- attach-music;;
- 2) remove-music;;
- 3) break;;
- esac
- done
- }
-
- function menu_irc {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"IRC Menu" \
- --radiolist $"Choose an operation:" 13 70 3 \
- 1 $"Set a password for all IRC users" off \
- 2 $"Exit" on 2> $data
- sel=$?
- case $sel in
- 1) break;;
- 255) break;;
- esac
- case $(cat $data) in
- 1) irc_set_global_password;;
- 2) break;;
- esac
- done
- }
-
- function menu_top_level {
- while true
- do
- data=$(tempfile 2>/dev/null)
- trap "rm -f $data" 0 1 2 5 15
- dialog --backtitle $"Freedombone Control Panel" \
- --title $"Control Panel" \
- --radiolist $"Choose an operation:" 26 70 19 \
- 1 $"About this system" off \
- 2 $"Backup and Restore" off \
- 3 $"Reset Tripwire" off \
- 4 $"Logging on/off" off \
- 5 $"Ping enable/disable" off \
- 6 $"Manage Users" off \
- 7 $"Email Filtering Rules" off \
- 8 $"Security Settings" off \
- 9 $"Set the main repository (repo mirrors)" off \
- 10 $"Hubzilla" off \
- 11 $"Media menu" off \
- 12 $"IRC menu" off \
- 13 $"Change the name of this system" off \
- 14 $"Set the TLS date/time source" off \
- 15 $"Set a static local IP address" off \
- 16 $"Check for updates" off \
- 17 $"Power off the system" off \
- 18 $"Restart the system" off \
- 19 $"Exit" on 2> $data
- sel=$?
- case $sel in
- 1) exit 1;;
- 255) exit 1;;
- esac
- case $(cat $data) in
- 1) show_about;;
- 2) menu_backup_restore;;
- 3) reset_tripwire;;
- 4) logging_on_off;;
- 5) ping_enable_disable;;
- 6) menu_users;;
- 7) menu_email;;
- 8) security_settings;;
- 9) set_main_repo;;
- 10) menu_hubzilla;;
- 11) menu_media;;
- 12) menu_irc;;
- 13) change_system_name;;
- 14) set_tls_time_source;;
- 15) set_static_IP;;
- 16) check_for_updates;;
- 17) shut_down_system;;
- 18) restart_system;;
- 19) break;;
- esac
- done
- }
-
- if [ ! -f $COMPLETION_FILE ]; then
- echo $'This command should only be run on an installed Freedombone system'
- exit 1
- fi
-
- ADMIN_USER=$(cat $COMPLETION_FILE | grep "Admin user" | awk -F ':' '{print $2}')
- read_repo_servers
- menu_top_level
- clear
- cat /etc/motd
- exit 0
|