#!/bin/bash
# 
# Ultimo aggiornamento: 31 Luglio 2007
# by Spina <spina80@freemail.it>

# Crea archivi contenenti file di backup.
# -h per l'help

# Nome dello script
SCRIPT_NAME=backup.sh

# Stampa l'argomento $1 seguito dalle informazioni per eseguire l'help.
# Poi ritorna uno stato di uscita pari a $2
function _exit
{
    echo -e "${1}\n\n${SCRIPT_NAME} -h per maggiori informazioni.\n";
    exit $2;
}

# Stampa l'help dello script
function _help
{
  echo -en "Uso: ${SCRIPT_NAME} [ opzioni ] nome-speciale...\n"\
           "\nCrea archivi compressi .tgz (tar e gzip), contenenti file di backup.\n"\
           "\nnome-speciale puņ assumere i valori:"\
           "\n   Script\tCrea un archivio della directory \$HOME/Script,"\
           "\n\t\te se esiste, anche uno per la directory \$HOME/Script_\$HOSTNAME"\
           "\n   bin\t\tCrea un archivio della directory \$HOME/bin"\
           "\n   c\t\tCrea un archivio della directory \$HOME/Programmi/c"\
           "\n   clasess\tCrea un archivio della directory \$HOME/Programmi/classes"\
           "\n   cpp\t\tCrea un archivio della directory \$HOME/Programmi/cpp"\
           "\n   php\t\tCrea un archivio della directory \$HOME/Programmi/php"\
           "\n   src\t\tCrea un archivio della directory \$HOME/Programmi/src"\
           "\n   Symbolik\tCrea un archivio contenente tutti i link simbolici presenti"\
           "\n   \t\tnella home directory"\
           "\n   Config\tCrea un archivio dei file di configurazione utente host INDIPENDENT,"\
           "\n   \t\te uno per i file di configurazione utente host DIPENDENT"\
           "\n   System\tCrea un archivio dei file di configurazione di sistema"\
           "\n   \t\t( viene richiesta la password di root )\n"\
           "\nopzioni puņ assumere i valori:"\
           "\n   -a\t\tFa il backup di tutti i nomi speciali"\
           "\n   -u\t\tFa il backup dei nomi speciali: Script, bin, Config e Symbolik"\
           "\n   -p\t\tFa il backup dei nomi speciali: c, classes, cpp, php, src"\
           "\n   -s\t\tFa il backup del nome speciale System"\
           "\n   -h\t\tMostra questo aiuto ed esce\n\n"\
           "\nIl nome dell'archivio ha la forma generale di:"\
           "\n\t\$USER_nome-speciale_\$HOSTNAME_giorno_mese_anno.tgz\n"\
           "\n\$USER (valore della relativa variabile d'ambiente), viene aggiunta nel caso dei nomi speciali"\
           "\nche fanno parte dell'opzione -u."\
           "\n\$HOSTNAME (valore della relativa variabile d'ambiente), viene aggiunta nel caso di archivi host"\
           "\ndependent.\n"\
           "\nby Spina <spina80@freemail.it>\n"
}

# Controlla l'esistenza di tutti i programmi dati i loro nomi come argomento.
# Se un programma non viene trovato, allora, stampa il nome del o dei programmi mancanti ed esce.
# Si usa il programma which per controllare che esistono i programmi passati. Si assume che
# which sia in /bin/.
function _check_extern_program
{
    local error=0;
    local string_error;

    if [ ! -x /bin/which ]; then
	error=1;
	string_error="which : programma mancante.\n";
    else
	for progr in $@; do
	    if [[ $(which $progr 2>/dev/null) == "" ]];
		then
		let ++error;
		string_error=${string_error}"${progr} : programma mancante.\n";
	    fi
	done
    fi

    if (( $error )); then
	if (( $error == 1 )); then
	    string_error=${string_error}"\nIl programma mancante č necessario ";
	else
	    string_error=${string_error}"\nI programmi mancanti sono necessari ";
	fi
	string_error=${string_error}"per la corretta esecuzione dello script.";
	_exit "$string_error" 1;
    fi
}

# Controllo degli argomenti dello script in cerca di opzioni
enable getopts echo exit;

# Impostazione del separatore di campi al valore di default
IFS=$(echo -e " \n\t");

# Controllo dell'esistenza di tutti i programmi esterni ( quindi non comandi interni alla bash) usati
_check_extern_program tar basename dirname gzip;

while getopts :aupsh opzione; do
    case $opzione in 
	a) ${SCRIPT_NAME} c classes cpp php src bin Config Script System symbolik;;
	u) ${SCRIPT_NAME} bin Script Config symbolik;;
        p) ${SCRIPT_NAME} c classes cpp php src;;
        s) ${SCRIPT_NAME} System;;
	h) _help; exit;; 
	?) _exit "-${OPTARG} : Argomento non valido." 1;
    esac
done

# Shift degli argomenti in modo da avere $1 che punta al primo argomento che non č una opzione
while (( $OPTIND != 1 )); do
    shift;
    let --OPTIND;
done

function tarra
{
    local nome="$1";
    shift;
    
    # Mantengo l'iniziale / se si tratta di un backup di sistema
    [[ $nome == system* ]] && local _OPT=P;
    
    # Devo eseguire una bash o altrimenti non si ha l'espansione delle parentesi graffe
    bash -c "\tar -${_OPT}zcf '${apath}'/'${nome}'_`date +'%d_%m_%y'`.tgz $* 2>/dev/null";
}

# Qui vengono elencati i file di configurazione UTENTE INDIPENDENTI dall'host:
function user_Config_host_independent
{
    echo ".aliases .bash_profile .bashrc .emacs .filezilla/sitemanager.xml "\
        ".gqview/gqviewrc .inputrc .netrc .purple/{accounts.xml,blist.xml,prefs.xml,status.xm}"\
        ".sitecopyrc .ssh/{a,i}* .toprc .xinitrc .xlockrc .xsession";
}

# Qui vengono elencati i file di configurazione UTENTE DIPENDENTI dall'host:
function user_Config_host_dependent
{
    echo ".Xdefaults .aliases_${HOSTNAME} .conkyrc .icewm .mplayer .rhosts "\
         ".ssh/known_hosts .xinitrc_${HOSTNAME}";
}

# Qui vengono elencati i file di configurazione del SISTEMA INDIPENDENTI dall'host
function system_Config_host_independent
{
    echo "/etc/hosts.* /etc/inetd.conf /etc/inittab /etc/login.defs /etc/ntp.conf /etc/profile "\
        "/etc/profile.d/*.sh /etc/securetty";
}

# Qui vengono elencati i file di configurazione del SISTEMA DIPENDENTI dall'host
function system_Config_host_dependent
{
    echo "/etc/acpi/ /etc/aumixrc /etc/exports /etc/fstab /etc/hosts /etc/httpd/httpd.conf /etc/httpd/php.ini "\
         "/etc/HOSTNAME /etc/lilo.conf /etc/resolv.conf /etc/rsyncd.conf /etc/rc.d/rc.* "\
         "/etc/udev/rules.d/*${HOSTNAME}.rules /etc/X11/xorg.conf /etc/modprobe.d/ /etc/sudoers";
}

function symbolik_List
{
    for file in ${HOME}/*;
      do
      [ -L "$file" ] && \tar -rf "${apath}"/"${1}"_`date +"%d_%m_%y"` "${file#$HOME/}";
    done

    gzip -S ".tgz" "${apath}"/"${1}"_`date +"%d_%m_%y"`
}

apath="${PWD}";

for nome_speciale; do
    cd ${HOME};
    case $nome_speciale in
	cpp | classes | php | src | c | C) 
	    tarra "${nome_speciale}" "Programmi/${nome_speciale}"/
	    ;;
	bin) 
	    tarra "${USER}_bin" "${nome_speciale}"/
	    ;;
	Script | script)
	    tarra "${USER}_Script" "${nome_speciale}"/;
	    [ -d "Script_${HOSTNAME}" ] &&\
		tarra "${USER}_Script_${HOSTNAME}" "${nome_speciale}_${HOSTNAME}"/;
	    ;;
	Config | config) 
	    tarra "${USER}_Config" `user_Config_host_independent`;
	    tarra "${USER}_Config_${HOSTNAME}" `user_Config_host_dependent`;
	    ;;
	System | system) 
	    if (( $(id -u) != 0 )); then
		su -c "$0 system";
	    else
		tarra "system" `system_Config_host_independent`;
		tarra "system_${HOSTNAME}" `system_Config_host_dependent`;
	    fi
	    ;;
	Symbolik | symbolik) 
	    symbolik_List "${USER}_Symbolik"
	    ;;
	*) 
	    echo "ATTENZIONE: non posso fare il backup  di ${nome_speciale}/"
	    ;;
    esac
    cd "$apath";
done
