#!/usr/bin/ksh
#
# $Id: do_domaines.sh,v 1.6 2003/04/19 16:35:15 root Exp $
# ----------------------------------------------------------------------
# AlternC - Web Hosting System
# Copyright (C) 2002 by the AlternC Development Team.
# http://alternc.org/
# ----------------------------------------------------------------------
# Based on:
# Valentin Lacambre's web hosting softwares: http://altern.org/
# ----------------------------------------------------------------------
# LICENSE
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License (GPL)
# as published by the Free Software Foundation; either version 2
# 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.
#
# To read the license please visit http://www.gnu.org/copyleft/gpl.html
# ----------------------------------------------------------------------
# Original Author of file: Jerome Moinet for l'Autre Net - 14/12/2000
# Purpose of file: system level domain management
# ----------------------------------------------------------------------
#

# ####################################################################
# VARIABLES SETTINGS : 
# ####################################################################

umask 022

integer nb1
integer nb2
integer ORDRE

DOM_ROOT=/usr/lib/alternc/system
BIND2_ROOT=$DOM_ROOT/bind2
FIC_TMP=/tmp/domaines.tmp
FIC_TMP_SUB=/tmp/sub_domaines.tmp
FIC_LOCK=/var/run/alternc/cron.lock
FIC_LOG=/var/log/alternc/domaines.log
FIC_LOG_SUB=/var/log/alternc/sub_domaines.log
HTTP_DNS=/var/alternc/dns
HTML_HOME=/var/alternc/html
NAMED_HOME=/etc/bind
NAMED_ETC=${NAMED_HOME}
NAMED_MASTER=${NAMED_HOME}/master
NAMED_TPL=domaines.template
SLAVE_TPL=slave.template
SECONDARY_LIST=secondary.list
NAMED_MX_TPL=mx.template
NAMED_CONF=automatic.conf
RELOAD_NAMED=/etc/init.d/bind9
WEBMAIL_ROOT=/var/alternc/dns/redir/mail
DATA_ROOT=var/alternc

ACTION_INSERT=0
ACTION_UPDATE=1
ACTION_DELETE=2
TYPE_LOCAL=0
TYPE_URL=1
TYPE_IP=2
TYPE_WEBMAIL=3
SLAVE=2
OUI=1
NON=0

mail=/usr/bin/mail
wc=/usr/bin/wc
awk=/usr/bin/awk
echo=/bin/echo
cut=/usr/bin/cut
grep=/bin/grep
tail=/usr/bin/tail
head=/usr/bin/head
rm=/bin/rm
find=/usr/bin/find
cat=/bin/cat
sed=/bin/sed
mv=/bin/mv
ln=/bin/ln
date=/bin/date
printf=/usr/bin/printf
cp=/bin/cp
env=/usr/bin/env

# récupération des passwd et autres à partir d'un fichier externe :
FIC_CONF=/etc/alternc/local.sh
if [ -x "$FIC_CONF" ]
    then
    . $FIC_CONF
else
    echo "Le fichier de configuration ($FIC_CONF) est absent ou n'est pas exécutable."
    exit 1
fi

# On teste si les variables attendues sont renseignées :
for variable in MYSQL_DATABASE MYSQL_USER MYSQL_PASS ROOT_MAIL DEFAULT_MX DEFAULT_IP
do
	var=""
  var=`set | $grep $variable | $grep -v variable`
  var=`$echo $var | $cut -d"=" -f2`
  if [ -z "$var" ]
  then
    $echo "la variable \$$variable n'est pas renseignée."
		exit 1
  fi
done


WEBMAIL_ROOT=/$DATA_ROOT/bureau/admin/webmail/
DOM_ROOT=/$DATA_ROOT/exec/system
FIC_LOCK=/$DATA_ROOT/bureau/cron.lock
HTTP_DNS=/$DATA_ROOT/dns
HTML_HOME=/$DATA_ROOT/html
DEST_MAILS_ERREUR=$ROOT_MAIL

MYSQL_SELECT="/usr/bin/mysql -u${MYSQL_USER} -p${MYSQL_PASS} -Bs ${MYSQL_DATABASE} -e "
MYSQL_DELETE="/usr/bin/mysql -u${MYSQL_USER} -p${MYSQL_PASS} ${MYSQL_DATABASE} -e "


# ####################################################################
# FUNCTIONS :
# ####################################################################

#---------------
# A chaque modification du fichier named
# d'un domaine, on incrémente son serial.
# Le serial est de la forme YYYYYMMDDSS
# où SS est le numéro d'ordre dans la journée.
# On incrémente ce numéro d'ordre si la modif
# est du même jour que la précédente, sinon on
# met la date du jour avec 01 en numéro d'ordre.
# Prend le nom du fic de conf en argument.
#---------------
function incrementer_serial
{
    if [ -f "$1" ]
	then
	SERIAL=`$grep "serial" $1 | $grep -v "^serial" | $awk {'print $1'}`
	DATE=`$echo $SERIAL | $cut -c1-8`
	ORDRE=`$echo $SERIAL | $sed s/"$DATE"/""/g`
	DATE_JOUR=`$date +%Y%m%d`
	if [ $DATE = $DATE_JOUR ]
	    then
	    ORDRE=$ORDRE+1
	else
	    ORDRE=1
	    DATE=$DATE_JOUR
	fi
	NEW_SERIAL=$DATE`$printf "%.2d" $ORDRE`
	$cat $1 | $awk -v NEW_SERIAL=$NEW_SERIAL '{if ($3 =="serial") print "		"NEW_SERIAL "	; serial"; else print $0}' > $1.tmp
	$mv -f $1.tmp $1
    fi
}


#---------------
# Modification de l'ip d'un sous_domaine.
# dans la conf named.
# Prend domaine, ip et
# sous_domaine en arguments.
#---------------
function modifier_ip_sous_domaine
{
    if [ -f $NAMED_MASTER/$1 ]
	then
	nb1=`$wc -l $NAMED_MASTER/$1 | $awk {'print $1'}`
	if [ "$3" = "" ]
	    then
	    nb2=`$grep -n "^[ 	]*IN[ 	]*A[ 	]*" $NAMED_MASTER/$1 | $cut -d":" -f1`
	else
	    nb2=`$grep -n "^$3" $NAMED_MASTER/$1 | $cut -d":" -f1`
	fi
	if [ $nb2 -eq 0 ]
	    then
	    nb1=$nb1-1
	    nb2=1
	else
	    nb2=$nb1-$nb2
	    nb1=$nb1-$nb2-1
	fi
	$head -n$nb1 $NAMED_MASTER/$1 > $NAMED_MASTER/$1.tmp
	$cat $NAMED_MASTER/ip.template | $sed s/"@@SUB@@"/"$3"/ | $sed s/"@@IP@@"/"$2"/ >> $NAMED_MASTER/$1.tmp
	$tail -n$nb2 $NAMED_MASTER/$1 >> $NAMED_MASTER/$1.tmp
	$mv -f $NAMED_MASTER/$1.tmp $NAMED_MASTER/$1
    fi
}


#---------------
# Crée un sous-domaine au niveau disque,
# et dans les fichiers named.
# prend domaine, 
# type, valeur, sous-domaine en argument.
# Principe : la création est forcée,
# si le sub existe déjà, il est remplacé.
#---------------
function creer_sous_domaine
{
    DOM=$1
    TYP=$2
    VAL=$4
    SB=$3
    POINT="."
    if [ "$SB" = "" ]
	then
	POINT=""
	modifier_ip_sous_domaine $DOM $DEFAULT_IP 
    fi
    detruire_sous_domaine $DOM $SB
    if [ "$TYP" = "$TYPE_LOCAL" ]
	then
	# NOTE : ne pas virer le rm -f (le ln -sf est buggé)
	$rm -f ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
	$ln -s ${HTML_HOME}/${INITIALE_USER}/${USER}${VAL} ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
    fi
    if [ "$TYP" = "$TYPE_WEBMAIL" ]
        then
        # NOTE : ne pas virer le rm -f (le ln -sf est bugg?)
	$rm -f ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
	$ln -s ${WEBMAIL_ROOT} ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
    fi
    if [ "$TYP" = "$TYPE_URL" ]
	then

	mkdir -p ${HTTP_DNS}/redir/${INITIALE_DOM}/${SB}${POINT}${DOM}
	$echo "<?php Header (\"Location: ${VAL}\"); ?>" > ${HTTP_DNS}/redir/${INITIALE_DOM}/${SB}${POINT}${DOM}/index.php
        # NOTE : ne pas virer le rm -f (le ln -sf est buggé)
	$rm -f ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
	$ln -s ${HTTP_DNS}/redir/${INITIALE_DOM}/${SB}${POINT}${DOM} ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
    fi
    if [ "$TYP" = "$TYPE_IP" ]
	then
	$rm -f ${HTTP_DNS}/${INITIALE_DOM}/${SB}${POINT}${DOM}
	$rm -fr ${HTTP_DNS}/redir/${INITIALE_DOM}/${SB}${POINT}${DOM}
	modifier_ip_sous_domaine $DOM $VAL $SB
    fi
}

#---------------
# Destruction d'un
# sous-domaine
#---------------
function detruire_sous_domaine
{
    DOM=$1
    SB=$2
    if ! [ "$SB" = "" ]
	then
	if [ -f $NAMED_MASTER/$DOM.hosts ]
	    then
	    $grep -v "^$SB" $NAMED_MASTER/$DOM > $NAMED_MASTER/$DOM.tmp
	    $mv -f $NAMED_MASTER/$DOM.tmp $NAMED_MASTER/$DOM
	fi
    fi
    $rm -f ${HTTP_DNS}/${INITIALE_DOM}/${SB}.${DOM}
    $rm -fr ${HTTP_DNS}/redir/${INITIALE_DOM}/${SB}.${DOM}
    incrementer_serial $NAMED_MASTER/$DOM
}


#---------------
# création du fichier named
# si il n'existe pas.
# Prend le nom du domaine
# en argument.
#---------------
function creer_fic_named
{
    if ! [ -f $NAMED_MASTER/$1 ]
	then
	SERIAL=`$date +%Y%m%d`00
	$cat $NAMED_MASTER/$NAMED_TPL | $sed s/"@@DOMAINE@@"/${1}/g | $sed s/"@@SERIAL@@"/$SERIAL/g > $NAMED_MASTER/${1}
	$cp -f $NAMED_ETC/$NAMED_CONF $NAMED_ETC/$NAMED_CONF.prec
	$cat $NAMED_ETC/$NAMED_TPL | $sed s/"@@DOMAINE@@"/${1}/g >> $NAMED_ETC/$NAMED_CONF
	$cp -f $BIND2_ROOT/$SECONDARY_LIST $BIND2_ROOT/$SECONDARY_LIST.prec
	$cat $BIND2_ROOT/$NAMED_TPL | $sed s/"@@DOMAINE@@"/${1}/g >> $BIND2_ROOT/$SECONDARY_LIST
	RESTART_NAMED="true"
    fi
}


#---------------
# Destruction des fichiers
# de conf named pour
# un domaine
#---------------
function detruire_fic_named
{
    if [ -f $NAMED_MASTER/$1 ]
	then
	$rm -f $NAMED_MASTER/$1
	$cat $NAMED_ETC/$NAMED_CONF | $grep -v "\"$1\"" > $NAMED_ETC/$NAMED_CONF.tmp
	$cp -f $NAMED_ETC/$NAMED_CONF $NAMED_ETC/$NAMED_CONF.prec
	$mv -f $NAMED_ETC/$NAMED_CONF.tmp $NAMED_ETC/$NAMED_CONF
	$cat $BIND2_ROOT/$SECONDARY_LIST | $grep -v "\"$1\"" > $BIND2_ROOT/$SECONDARY_LIST.tmp
	$cp -f $BIND2_ROOT/$SECONDARY_LIST $BIND2_ROOT/$SECONDARY_LIST.prec
	$mv -f $BIND2_ROOT/$SECONDARY_LIST.tmp $BIND2_ROOT/$SECONDARY_LIST
    fi
}

#---------------
# Modification du champ mx.
# prend domaine et champ mx
# en arguments.
#---------------
function modifier_mx_domaine
{
    nb1=`$grep -n "MX" $NAMED_MASTER/${1} | $cut -d":" -f1`
    nb1=$nb1-1
    $head -n$nb1 $NAMED_MASTER/${1} > $NAMED_MASTER/${1}.tmp
    $cat $NAMED_MASTER/$NAMED_MX_TPL | $sed s/"@@MX@@"/${2}/g >> $NAMED_MASTER/${1}.tmp
    nb2=`$wc -l $NAMED_MASTER/${1} | $awk {'print $1'}`
    nb2=$nb2-$nb1-1
    $tail -n$nb2 $NAMED_MASTER/${1} >> $NAMED_MASTER/${1}.tmp
    $mv -f $NAMED_MASTER/${1}.tmp $NAMED_MASTER/${1}
    incrementer_serial $NAMED_MASTER/${1}
    RESTART_NAMED="true"
}


# ####################################################################
# Main program
# ####################################################################

#------------------------------------
# CALL WITH "do_domaines.sh --secondary"
# It rebuilds the secondary.list file.
if [ "$1" = "--secondary" ]
    then
    > $FIC_LOCK
    $rm -f $FIC_TMP
    echo "CALL --secondary, rebuilding secondary.list file." >> $FIC_LOG
    SQL_RES=`$MYSQL_SELECT "SELECT b.domaine INTO OUTFILE '$FIC_TMP' FROM domaines b WHERE b.gesdns=1;" 2>&1`  
    RES=$?
    if [ "$RES" != 0 ]
	then
	$echo `$date` >> $FIC_LOG
	$echo $SQL_RES >> $FIC_LOG
	$echo "`$date` : $DOM_ROOT/do_domaines.sh : erreur à l'exécution de la requête de sélection des domaines à traiter : $SQL_RES" | $mail -s "erreur requête dans do_domaines.sh" $DEST_MAILS_ERREUR
	$rm -f $FIC_LOCK >> $FIC_LOG 2>&1
	$rm -f $FIC_TMP >> $FIC_LOG 2>&1
	exit 1
    else
	# On traite les domaines
	$mv -f $BIND2_ROOT/$SECONDARY_LIST $BIND2_ROOT/$SECONDARY_LIST.prec
	for i in `$cat $FIC_TMP`
	  do
	  $cat $BIND2_ROOT/$NAMED_TPL | $sed s/"@@DOMAINE@@"/${i}/g >> $BIND2_ROOT/$SECONDARY_LIST
	done
    fi
    $rm -f $FIC_LOCK >> $FIC_LOG 2>&1
    $rm -f $FIC_TMP >> $FIC_LOG 2>&1
    echo "CALL --secondary END" >> $FIC_LOG
    exit 0
fi


# ------------------------------------------------------------
# CALL with NO argument : process pending domains / subdomains
# 
# si le cron précédent n'est pas
# terminé, on attend le suivant.
if [ -f $FIC_TMP ]
    then
    echo `$date` >> $FIC_LOG
    echo "ERREUR : cron précédent inachevé." >> $FIC_LOG
    $echo "`$date` : $DOM_ROOT/do_domaines.sh : cron précédent inachevé." | $mail -s "erreur do_domaines.sh" $DEST_MAILS_ERREUR
    exit 1
fi

> $FIC_LOCK

SQL_RES=`$MYSQL_SELECT "SELECT m.login,b.domaine,b.mx,b.gesdns,b.gesmx,b.action INTO OUTFILE '$FIC_TMP' FROM domaines_standby b INNER JOIN membres m ON m.uid=b.compte ORDER BY b.action;" 2>&1`
RES=$?

if [ "$RES" != 0 ]
    then
    $echo `$date` >> $FIC_LOG
    $echo $SQL_RES >> $FIC_LOG
    $echo "`$date` : $DOM_ROOT/do_domaines.sh : erreur à l'exécution de la requête de sélection des domaines à traiter : $SQL_RES" | $mail -s "erreur requête dans do_domaines.sh" $DEST_MAILS_ERREUR
    $rm -f $FIC_LOCK >> $FIC_LOG 2>&1
    $rm -f $FIC_TMP >> $FIC_LOG 2>&1
    $rm -f $FIC_TMP_SUB >> $FIC_LOG 2>&1
    exit 1
else
    SQL_RES=`$MYSQL_SELECT "SELECT m.login,b.domaine,b.sub,b.valeur,b.type,b.action INTO OUTFILE '$FIC_TMP_SUB' FROM sub_domaines_standby b INNER JOIN membres m ON m.uid=b.compte ORDER BY b.action desc;" 2>&1`
    RES=$?
    if [ "$RES" != 0 ]
	then
  	$echo `$date` >> $FIC_LOG
	$echo $SQL_RES >> $FIC_LOG
	$echo "`$date` : $DOM_ROOT/do_domaines.sh : erreur à l'exécution de la requête de sélection des sous-domaines à traiter : $SQL_RES" | $mail -s "erreur requête dans do_domaines.sh" $DEST_MAILS_ERREUR
	$rm -f $FIC_LOCK >> $FIC_LOG 2>&1
	$rm -f $FIC_TMP >> $FIC_LOG 2>&1
	$rm -f $FIC_TMP_SUB >> $FIC_LOG 2>&1
	exit 1
    else
	$rm -f $FIC_LOCK
	$MYSQL_DELETE "DELETE FROM domaines_standby;"
	$MYSQL_DELETE "DELETE FROM sub_domaines_standby;"
	RESTART_NAMED="false"
	# On traite les domaines
	$cat $FIC_TMP | $sed s/"	"/"@"/g > $FIC_TMP.tmp
	$mv -f $FIC_TMP.tmp $FIC_TMP
	if [ `$cat $FIC_TMP | $wc -l | $awk {'print $1'}` -gt 0 ]
	    then
	    $echo `$date` >> $FIC_LOG
	    $cat $FIC_TMP >> $FIC_LOG
	fi
	for i in `$cat $FIC_TMP`
	  do
	  USER=`$echo $i | $cut -d"@" -f1`
	  DOMAINE=`$echo $i | $cut -d"@" -f2`
	  MX=`$echo $i | $cut -d"@" -f3`
	  GESDNS=`$echo $i | $cut -d"@" -f4`
	  GESMX=`$echo $i | $cut -d"@" -f5`
	  ACTION=`$echo $i | $cut -d"@" -f6`
	  PASS=`$echo $i | $cut -d"@" -f7`
	  INITIALE_DOM=`$echo $DOMAINE | $awk '{z = split($0, intiale, "."); print substr(intiale[z - 1], 1, 1)}'`
	  INITIALE_USER=`$echo $USER | $awk {'print substr($1, 1, 1)'}`
	  if [ "$ACTION" = "$ACTION_INSERT" ]
	      then
              # création des liens symboliques par défaut :
              # NOTE : ne pas virer le rm -f (le ln -sf est buggé)
	      $rm -f ${HTTP_DNS}/${INITIALE_DOM}/$DOMAINE
	      $ln -s ${HTML_HOME}/${INITIALE_USER}/$USER ${HTTP_DNS}/${INITIALE_DOM}/$DOMAINE
	      $rm -f ${HTTP_DNS}/${INITIALE_DOM}/www.$DOMAINE
	      $ln -s ${HTML_HOME}/${INITIALE_USER}/$USER ${HTTP_DNS}/${INITIALE_DOM}/www.$DOMAINE
	      $rm -f ${HTTP_DNS}/${INITIALE_DOM}/mail.$DOMAINE
	      $ln -s ${WEBMAIL_ROOT} ${HTTP_DNS}/${INITIALE_DOM}/mail.$DOMAINE
	      if [ "$GESDNS" = "$OUI" ]
		  then
		  creer_fic_named $DOMAINE
	      fi
	  fi
	  if [ "$ACTION" = "$ACTION_UPDATE" ]
	      then
	      if [ "$GESDNS" = "$OUI" ]
		  then
		  creer_fic_named $DOMAINE
		  modifier_mx_domaine $DOMAINE $MX
	      else
		  detruire_fic_named $DOMAINE
	      fi
	  fi
	  if [ "$ACTION" = "$ACTION_DELETE" ]
	      then
	      detruire_fic_named $DOMAINE
              # suppression des liens symboliques :
	      $rm -f ${HTTP_DNS}/${INITIALE_DOM}/*.$DOMAINE
	      $rm -f ${HTTP_DNS}/${INITIALE_DOM}/$DOMAINE
	      $rm -fr ${HTTP_DNS}/redir/${INITIALE_DOM}/*.$DOMAINE
	      $rm -fr ${HTTP_DNS}/redir/${INITIALE_DOM}/$DOMAINE
	  fi
	  RESTART_NAMED="true"
	done
	# on traite les sous-domaines
	$cat $FIC_TMP_SUB | $sed s/"	"/"@"/g > $FIC_TMP_SUB.tmp
	$mv -f $FIC_TMP_SUB.tmp $FIC_TMP_SUB
	
	if [ `$cat $FIC_TMP_SUB | $wc -l | $awk {'print $1'}` -gt 0 ]
	    then
	    $echo `$date` >> $FIC_LOG_SUB
	    $cat $FIC_TMP_SUB >> $FIC_LOG_SUB
	fi
	for i in `$cat $FIC_TMP_SUB`
	  do
	  USER=`$echo $i | $cut -d"@" -f1`
	  DOMAINE=`$echo $i | $cut -d"@" -f2`
	  SUB=`$echo $i | $cut -d"@" -f3`
	  VALEUR=`$echo $i | $cut -d"@" -f4`
	  TYPE=`$echo $i | $cut -d"@" -f5`
	  ACTION=`$echo $i | $cut -d"@" -f6`
	  PASS=`$echo $i | $cut -d"@" -f7`
	  INITIALE_DOM=`$echo $DOMAINE | $awk '{z = split($0, intiale, "."); print substr(intiale[z - 1], 1, 1)}'`
	  INITIALE_USER=`$echo $USER | $awk {'print substr($1, 1, 1)'}`
	  if [ "$ACTION" = "$ACTION_UPDATE" -o "$ACTION" = "$ACTION_INSERT" ]
	      then
	      creer_sous_domaine "$DOMAINE" "$TYPE" "$SUB" "$VALEUR" 

	  fi	
	  if [ "$ACTION" = "$ACTION_DELETE" ]
	      then
	      detruire_sous_domaine $DOMAINE $SUB
	  fi
	  RESTART_NAMED="true"
	done
	if [ "$RESTART_NAMED" = "true" ]
	    then
	    $RELOAD_NAMED reload
	fi
	$rm -f $FIC_TMP_SUB >> $FIC_LOG 2>&1
	$rm -f $FIC_TMP >> $FIC_LOG 2>&1
    fi
fi	

	
