Moved more code to lib/ (conffile-related functions, parseini. Added dup helper, using new modular vservers-related functions shared for all helpers.
rdiff ninjahelper bugfixes:
used to expand '*' in default source directories
the "Cancel" buttons used to have a weird behaviour... at least
+ code refactor: moved to lib/ some code that has to be shared between
+ backupninja and ninjahelper
+ added duplicity ninjahelper
version 0.9.1 -- November 05 2005
rearranged source so that it is relocatable with autotools
-HANDLERS = dup dup.helper maildir mysql.helper rdiff sys \
- makecd makecd.helper \
- parseini rdiff.helper sys.helper ldap pgsql sh trac \
+HANDLERS = dup dup.helper maildir mysql.helper rdiff sys makecd makecd.helper \
+ rdiff.helper sys.helper ldap pgsql sh trac \
ldap.helper mysql pgsql.helper svn
-
EXTRA_DIST = Makefile.am $(HANDLERS)
dist_pkgdata_DATA = $(HANDLERS)
sysconfdir = @sysconfdir@
target_alias = @target_alias@
HANDLERS = dup dup.helper maildir mysql.helper rdiff sys \
- makecd makecd.helper \
- parseini rdiff.helper sys.helper ldap pgsql sh trac \
- ldap.helper mysql pgsql.helper svn
+ makecd makecd.helper rdiff.helper sys.helper \
+ ldap pgsql sh trac ldap.helper mysql pgsql.helper svn
EXTRA_DIST = Makefile.am $(HANDLERS)
dist_pkgdata_DATA = $(HANDLERS)
}
do_dup_src() {
- host_or_vservers_chooser
+ host_or_vservers_chooser "$dup_title"
[ $? = 0 ] || return 1
case $host_or_vservers in
'host')
+++ /dev/null
-#
-# parseini --- parses 'ini' style configuration files.
-#
-# Usage:
-# awk -f parseini S=<section> P=<param> <ini file>
-#
-# if section is an empty string, then we use the default section
-#
-# example ini file:
-#
-# fruit = apple
-# fruit = pear
-# multiline = this is a multiline \
-# parameter
-#
-# # this is a comment
-#
-# [colors]
-# red = yes
-# green = no
-# blue = maybe
-#
-# [ocean]
-# fish = red
-# fish = blue
-#
-# example usage:
-# > awk -f parseini S=ocean P=fish testfile.ini
-# would return:
-# red
-# blue
-#
-
-BEGIN {
- readlines = 1
- implied = 1
-}
-
-# remove lines starting with #, but not #!
-/^#[^!]/ {next}
-
-# skip blank
-/^[ \r\t]*$/ {next}
-
-# we want to read the lines of the matched section
-# and disable for other sections
-/^\[.+\][ \r\t]*$/ {
- continueline = 0
- if (S && implied) {
- nline = 0
- implied = 0
- }
- if (S && match($0, "^\\[" S "\\][ \n]*")) {
- # we found the section, so start reading.
- readlines = 1
- }
- else {
- # no section, so stop reading lines
- if (readlines) readlines = 0
- }
- next
-}
-
-# when reading, store lines.
-
-{
- if (!readlines) next
- line[nline++] = $0
- if ($0 ~ /\\[ \r\t]*$/)
- continueline = 1
- else
- continueline = 0
-}
-
-# process the read lines lines, matching parameters
-
-END {
- # if section is set but implied is still true
- # then we never found the section, so use everything
- if (S && implied) {
- nline = 0
- }
-
- # if have P then find P in read lines and get values
- if (P) {
- MATCH = "^[ \r\t]*" P "[ \r\t]*="
- continueline = 0
- for (x = 0; x < nline; ++x) {
- v = line[x]
- if (continueline) {
- sub(/[ \r\t]+$/, "", v)
- if (v ~ /\\$/) {
- v = substr(v, 1, length(v)-1)
- sub(/[ \r\t]+$/, "", v)
- }
- if (v) value[nvalue++] = v
- }
- else if (v ~ MATCH) {
- sub(MATCH, "", v)
- sub(/^[ \r\t]+/, "", v)
- sub(/[ \r\t]+$/, "", v)
- if (v ~ /\\$/) {
- continueline = 1
- v = substr(v, 1, length(v)-1)
- sub(/[ \r\t]+$/, "", v)
- }
- if (v) value[nvalue++] = v
- }
- }
- # copy parameter definition to output array
- nline = nvalue
- for (x = 0; x < nvalue; ++x)
- line[x] = value[x]
- }
-
- # trim all leading & trailing whitespace;
- # except for leading whitespace in continuation lines,
-
- for (x = 0; x < nline; ++x) {
- sub(/^[ \r\t]+/, "", line[x])
- sub(/[ \r\t]+$/, "", line[x])
- }
-
- # output the final result
- for (x = 0; x < nline; ++x)
- print line[x]
-
- if (nline) exit 0
- else exit 1
-}
-EXTRALIBS = easydialog tools
-CLEANFILES = $(EXTRALIBS)
-dist_pkglib_DATA = $(EXTRALIBS)
-EXTRA_DIST = easydialog.in tools.in
+EXTRA_DIST = easydialog.in parseini.in tools.in
+
+GENERATED_FILES = easydialog parseini tools
+
+dist_pkglib_DATA = $(GENERATED_FILES)
+
+CLEANFILES = $(GENERATED_FILES)
edit = sed \
-e "s,@BASH\@,$(BASH),g"
-easydialog: easydialog.in
+easydialog: #easydialog.in
rm -f easydialog
$(edit) easydialog.in > easydialog
-tools: tools.in
+parseini: #parseini.in
+ rm -f parseini
+ $(edit) parseini.in > parseini
+
+tools: #tools.in
rm -f tools
$(edit) tools.in > tools
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
-EXTRALIBS = easydialog tools
-CLEANFILES = $(EXTRALIBS)
-dist_pkglib_DATA = $(EXTRALIBS)
-EXTRA_DIST = easydialog.in tools.in
+EXTRA_DIST = easydialog.in parseini.in tools.in
+GENERATED_FILES = easydialog parseini tools
+dist_pkglib_DATA = $(GENERATED_FILES)
+CLEANFILES = $(GENERATED_FILES)
edit = sed \
-e "s,@BASH\@,$(BASH),g"
uninstall-dist_pkglibDATA uninstall-info-am
-easydialog: easydialog.in
+easydialog: #easydialog.in
rm -f easydialog
$(edit) easydialog.in > easydialog
-tools: tools.in
+parseini: #parseini.in
+ rm -f parseini
+ $(edit) parseini.in > parseini
+
+tools: #tools.in
rm -f tools
$(edit) tools.in > tools
# Tell versions [3.59,3.63) of GNU make to not export all variables.
--- /dev/null
+#
+# parseini --- parses 'ini' style configuration files.
+#
+# Usage:
+# awk -f parseini S=<section> P=<param> <ini file>
+#
+# if section is an empty string, then we use the default section
+#
+# example ini file:
+#
+# fruit = apple
+# fruit = pear
+# multiline = this is a multiline \
+# parameter
+#
+# # this is a comment
+#
+# [colors]
+# red = yes
+# green = no
+# blue = maybe
+#
+# [ocean]
+# fish = red
+# fish = blue
+#
+# example usage:
+# > awk -f parseini S=ocean P=fish testfile.ini
+# would return:
+# red
+# blue
+#
+
+BEGIN {
+ readlines = 1
+ implied = 1
+}
+
+# remove lines starting with #, but not #!
+/^#[^!]/ {next}
+
+# skip blank
+/^[ \r\t]*$/ {next}
+
+# we want to read the lines of the matched section
+# and disable for other sections
+/^\[.+\][ \r\t]*$/ {
+ continueline = 0
+ if (S && implied) {
+ nline = 0
+ implied = 0
+ }
+ if (S && match($0, "^\\[" S "\\][ \n]*")) {
+ # we found the section, so start reading.
+ readlines = 1
+ }
+ else {
+ # no section, so stop reading lines
+ if (readlines) readlines = 0
+ }
+ next
+}
+
+# when reading, store lines.
+
+{
+ if (!readlines) next
+ line[nline++] = $0
+ if ($0 ~ /\\[ \r\t]*$/)
+ continueline = 1
+ else
+ continueline = 0
+}
+
+# process the read lines lines, matching parameters
+
+END {
+ # if section is set but implied is still true
+ # then we never found the section, so use everything
+ if (S && implied) {
+ nline = 0
+ }
+
+ # if have P then find P in read lines and get values
+ if (P) {
+ MATCH = "^[ \r\t]*" P "[ \r\t]*="
+ continueline = 0
+ for (x = 0; x < nline; ++x) {
+ v = line[x]
+ if (continueline) {
+ sub(/[ \r\t]+$/, "", v)
+ if (v ~ /\\$/) {
+ v = substr(v, 1, length(v)-1)
+ sub(/[ \r\t]+$/, "", v)
+ }
+ if (v) value[nvalue++] = v
+ }
+ else if (v ~ MATCH) {
+ sub(MATCH, "", v)
+ sub(/^[ \r\t]+/, "", v)
+ sub(/[ \r\t]+$/, "", v)
+ if (v ~ /\\$/) {
+ continueline = 1
+ v = substr(v, 1, length(v)-1)
+ sub(/[ \r\t]+$/, "", v)
+ }
+ if (v) value[nvalue++] = v
+ }
+ }
+ # copy parameter definition to output array
+ nline = nvalue
+ for (x = 0; x < nvalue; ++x)
+ line[x] = value[x]
+ }
+
+ # trim all leading & trailing whitespace;
+ # except for leading whitespace in continuation lines,
+
+ for (x = 0; x < nline; ++x) {
+ sub(/^[ \r\t]+/, "", line[x])
+ sub(/[ \r\t]+$/, "", line[x])
+ }
+
+ # output the final result
+ for (x = 0; x < nline; ++x)
+ print line[x]
+
+ if (nline) exit 0
+ else exit 1
+}
#!@BASH@
+# This file contains functions shared between ninjahelper and backupninja.
+
+#####################################################
+## MISC FUNCTIONS
#
# create a temporary file in a secure way.
echo $tempfile
}
+#####################################################
+## CONFIG-FILE RELATED FUNCTIONS
+
+function setfile() {
+ CURRENT_CONF_FILE=$1
+}
+
+function setsection() {
+ CURRENT_SECTION=$1
+}
+
+#
+# sets a global var with name equal to $1
+# to the value of the configuration parameter $1
+# $2 is the default.
+#
+function getconf() {
+ CURRENT_PARAM=$1
+ ret=`awk -f $libdirectory/parseini S=$CURRENT_SECTION P=$CURRENT_PARAM $CURRENT_CONF_FILE`
+ # if nothing is returned, set the default
+ if [ "$ret" == "" -a "$2" != "" ]; then
+ ret="$2"
+ fi
+ # replace * with %, so that it is not globbed.
+ ret="${ret//\\*/__star__}"
+
+ # this is weird, but single quotes are needed to
+ # allow for returned values with spaces. $ret is still expanded
+ # because it is in an 'eval' statement.
+ eval $1='$ret'
+}
let "msgcount += 1"
}
-function setfile() {
- CURRENT_CONF_FILE=$1
-}
-
-function setsection() {
- CURRENT_SECTION=$1
-}
-
-
-#
-# sets a global var with name equal to $1
-# to the value of the configuration parameter $1
-# $2 is the default.
-#
-
-function getconf() {
- CURRENT_PARAM=$1
- ret=`awk -f $scriptdir/parseini S=$CURRENT_SECTION P=$CURRENT_PARAM $CURRENT_CONF_FILE`
- # if nothing is returned, set the default
- if [ "$ret" == "" -a "$2" != "" ]; then
- ret="$2"
- fi
-
- # replace * with %, so that it is not globbed.
- ret="${ret//\\*/__star__}"
-
- # this is weird, but single quotes are needed to
- # allow for returned values with spaces. $ret is still expanded
- # because it is in an 'eval' statement.
- eval $1='$ret'
-}
-
#
# enforces very strict permissions on configuration file $file.
#
echo "" > $bufferfile
echo_debug_msg=1
(
- . $scriptdir/$suffix $file
+ . $scriptdirectory/$suffix $file
) 2>&1 | (
while read a; do
echo $a >> $bufferfile
fatal "Configuration file $conffile not found."
fi
-# find $scriptdir
-scriptdir=`grep scriptdirectory $conffile | awk '{print $3}'`
-if [ -z "$scriptdir" ]; then
- if [ -d "@datadir@" ]; then
- scriptdir="@datadir@"
- else
- echo "Could not find entry 'scriptdirectory' in $conffile"
- fatal "Could not find entry 'scriptdirectory' in $conffile"
- fi
-else
- if [ ! -d "$scriptdir" ]; then
- echo "Script directory $scriptdir not found."
- fatal "Script directory $scriptdir not found."
- fi
-fi
-
-# find $libdir
-libdir=`grep libdirectory $conffile | awk '{print $3}'`
-if [ -z "$libdir" ]; then
+# find $libdirectory
+libdirectory=`grep '^libdirectory' $conffile | awk '{print $3}'`
+if [ -z "$libdirectory" ]; then
if [ -d "@libdir@" ]; then
- libdir="@libdir@"
+ libdirectory="@libdir@"
else
echo "Could not find entry 'libdirectory' in $conffile."
fatal "Could not find entry 'libdirectory' in $conffile."
fi
else
- if [ ! -d "$libdir" ]; then
- echo "Lib directory $libdir not found."
- fatal "Lib directory $libdir not found."
+ if [ ! -d "$libdirectory" ]; then
+ echo "Lib directory $libdirectory not found."
+ fatal "Lib directory $libdirectory not found."
fi
fi
+# include shared functions
+. $libdirectory/tools
+
setfile $conffile
# get global config options (second param is the default)
getconf configdirectory @CFGDIR@/backup.d
+getconf scriptdirectory @datadir@
getconf reportemail
getconf reportsuccess yes
getconf reportwarning yes
fatal "Configuration directory '$configdirectory' not found."
fi
-# include shared functions
-. $libdir/tools
-
[ -f "$logfile" ] || touch $logfile
if [ "$UID" != "0" ]; then
continue
fi
- if [ -e "$scriptdir/$suffix" ]; then
+ if [ -e "$scriptdirectory/$suffix" ]; then
process_action $file $suffix
else
error "Can't process file '$file': no handler script for suffix '$suffix'"
## menu for the wizards
##
donew() {
+ unset host_or_vservers
+ unset vservers_chooser_vsnames
listBegin "new action menu" "select an action to create"
listItem return "return to main menu"
for data in $HELPERS; do
done
}
+#####################################################
+## VSERVERS RELATED FUNCTIONS
+
+##
+## If vservers are not enabled, exit silently and set host_or_vservers to 'host'.
+## Else, have the user choose the target he/she wants to perform the backup on:
+## - host system only
+## - some vservers only
+## - both the host system and some vservers
+## Sets, respectively, $host_or_vservers to 'host', 'vservers', or 'both'
+## $host_or_vservers is unset when a new helper is run.
+## Returns 1 if cancelled.
+##
+host_or_vservers_chooser() {
+ local title=$1
+ # exit silently if vservers are not enabled
+ if [ "$vservers" != "yes" ]; then
+ host_or_vservers='host'
+ return
+ fi
+ # if there is one, set the previously chosen item as the default
+ [ -n "$host_or_vservers" ] && setDefault $host_or_vservers
+ menuBox "$title - src" "Do you want to operate on the host system and/or on vservers?" \
+ "host" "Host system only" \
+ "vservers" "Vservers only" \
+ "both" "Host system and Vservers"
+ [ $? = 0 ] || return 1
+ case $REPLY in
+ "host")
+ host_or_vservers='host'
+ ;;
+ "vservers")
+ host_or_vservers='vservers'
+ ;;
+ "both")
+ host_or_vservers='both'
+ ;;
+ esac
+}
+
+##
+## If the argument is the name of a vserver selected for backup (in
+## $vservers_chooser_vsnames), echoes 'on' and returns 0.
+## Else, echoes 'off' and returns 1.
+##
+vserver_is_selected() {
+ local vserver=$1
+ local vserver_is_selected=1
+ local i
+ for i in $vservers_chooser_vsnames ; do
+ [ "$vserver" == "$i" ] && vserver_is_selected=0
+ done
+ if [ $vserver_is_selected = 0 ]; then
+ echo on
+ else
+ echo off
+ fi
+ return $vserver_is_selected
+}
+
+##
+## Have the user choose among "all vservers" and a not-empty subset of these.
+## Sets global $vservers_chooser_vsnames variable to "all" or to a
+## space-separated name list.
+## Depends on host_or_vservers() to have already run.
+## $vservers_chooser_vsnames is unset when a new helper is run.
+## Returns 1 if cancelled.
+##
+vservers_chooser() {
+ local title=$1
+ local i=
+ [ -n "$VROOTDIR" ] || (msgBox "warning" "VROOTDIR is not set in $conffile and could not be guessed."; return 1)
+ [ -d "$VROOTDIR" ] || (msgBox "warning" "VROOTDIR ($VROOTDIR) does not exist."; return 1)
+
+ booleanBox "$title" "Do you want to backup all vservers?" ` [ -z "$vservers_chooser_vsnames" -o "$vservers_chooser_vsnames" == "all" ] || echo no`
+ if [ $? = 0 ]; then
+ vservers_chooser_vsnames="all"
+ else
+ # choose among the existing vservers
+ local vserver=
+ local vserver_was_selected=
+ REPLY=
+ while [ -z "$REPLY" ]; do
+ listBegin "$title" "Choose at least one Linux-Vserver to backup:"
+ # list existing vservers, preselecting the previously selected ones
+ for vserver in `ls $VROOTDIR | grep -E -v "lost+found|ARCHIVES"`; do
+ listItem "$vserver" "Backup $vserver vserver" `vserver_is_selected $vserver`
+ done
+ listDisplay checklist
+ [ $? = 0 ] || return 1
+ done
+ # remove quotes around each vserver name
+ vservers_chooser_vsnames=`echo $REPLY | tr -d '"'`
+ fi
+}
+
#####################################################
## begin program
done
fi
+# bootstrap
conffile="@CFGDIR@/backupninja.conf"
if [ ! -r "$conffile" ]; then
echo "Configuration file $conffile not found."
exit 1
fi
-# find $scriptdir
-scriptdir=`grep scriptdirectory $conffile | awk '{print $3}'`
-if [ -z "$scriptdir" ]; then
- if [ -d "@datadir@" ]; then
- scriptdir="@datadir@"
- else
- echo "Could not find entry 'scriptdirectory' in $conffile"
- exit 1
- fi
-else
- if [ ! -d "$scriptdir" ]; then
- echo "Script directory $scriptdir not found."
- exit 1
- fi
-fi
-
-# find $libdir
-libdir=`grep libdirectory $conffile | awk '{print $3}'`
-if [ -z "$libdir" ]; then
+# find $libdirectory
+libdirectory=`grep '^libdirectory' $conffile | awk '{print $3}'`
+if [ -z "$libdirectory" ]; then
if [ -d "@libdir@" ]; then
- libdir="@libdir@"
+ libdirectory="@libdir@"
else
echo "Could not find entry 'libdirectory' in $conffile."
exit 1
fi
else
- if [ ! -d "$libdir" ]; then
- echo "Lib directory $libdir not found."
+ if [ ! -d "$libdirectory" ]; then
+ echo "Lib directory $libdirectory not found."
exit 1
fi
fi
-configdirectory=`grep configdirectory $conffile | awk '{print $3}'`
-if [ ! -n "$configdirectory" ]; then
- echo "Cound not find entry 'configdirectory' in $conffile"
- exit 1
-fi
-if [ ! -d "$configdirectory" ]; then
- echo "Configuration directory $configdirectory not found."
- exit 1
-fi
-
-. $libdir/easydialog
+# include shared functions
+. $libdirectory/easydialog
+. $libdirectory/tools
+# am I running as root?
if [ "$UID" != "0" ]; then
- msgBox "warning" "ninjahelper must be run by root!"
+ msgBox "warning" "$0 must be run by root!"
exit 1
fi
+# get global config options (second param is the default)
+setfile $conffile
+getconf configdirectory @CFGDIR@/backup.d
+getconf scriptdirectory @datadir@
+getconf vservers no
+getconf VSERVERINFO /usr/sbin/vserver-info
+getconf VSERVER /usr/sbin/vserver
+getconf VROOTDIR `if [ -f "$VSERVERINFO" ]; then $VSERVERINFO info SYSINFO |grep vserver-Rootdir | awk '{print $2}'; fi`
+
# load all the helpers
HELPERS=""
-for file in `find $scriptdir -follow -name '*.helper'`; do
+for file in `find $scriptdirectory -follow -name '*.helper'`; do
check_perms $file
. $file
done