root/alternc/branches/larpoux-unstable/src/update_domains.sh

Revision 828, 15.3 kB (checked in by joe, 3 years ago)

Les scripts sont maintenant éxécutables (avec svn:executable).

  • Property svn:executable set to *
Line 
1 #!/bin/sh
2 #
3 # $Id: do_domaines.sh,v 1.31 2005/08/29 19:21:31 anarcat Exp $
4 # ----------------------------------------------------------------------
5 # AlternC - Web Hosting System
6 # Copyright (C) 2002 by the AlternC Development Team.
7 # http://alternc.org/
8 # ----------------------------------------------------------------------
9 # Based on:
10 # Valentin Lacambre's web hosting softwares: http://altern.org/
11 # ----------------------------------------------------------------------
12 # LICENSE
13 #
14 # This program is free software; you can redistribute it and/or
15 # modify it under the terms of the GNU General Public License (GPL)
16 # as published by the Free Software Foundation; either version 2
17 # of the License, or (at your option) any later version.
18 #
19 # This program is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23 #
24 # To read the license please visit http://www.gnu.org/copyleft/gpl.html
25 # ----------------------------------------------------------------------
26 # Original Author of file: Jerome Moinet for l'Autre Net - 14/12/2000
27 # Purpose of file: system level domain management
28 # ----------------------------------------------------------------------
29 #
30
31 PATH=/sbin:/bin:/usr/sbin:/usr/bin
32
33 set -e
34
35 umask 022
36
37 ########################################################################
38 # Constants & Preliminary checks
39 #
40
41 CONFIG_FILE="/etc/alternc/local.sh"
42
43 DOMAIN_LOG_FILE="/var/log/alternc/update_domains.log"
44 DATA_ROOT="/var/alternc"
45
46 NAMED_TEMPLATE="/etc/bind/templates/named.template"
47 ZONE_TEMPLATE="/etc/bind/templates/zone.template"
48
49 ACTION_INSERT=0
50 ACTION_UPDATE=1
51 ACTION_DELETE=2
52 TYPE_LOCAL=0
53 TYPE_URL=1
54 TYPE_IP=2
55 TYPE_WEBMAIL=3
56 YES=1
57
58 if [ ! -x "/usr/bin/get_account_by_domain" ]; then
59     echo "You have to install alternc-admintools: "
60     echo "    apt-get update ; apt-get install alternc-admintools"
61     exit 1
62 fi
63
64 if [ ! -r "$CONFIG_FILE" ]; then
65     echo "Can't access $CONFIG_FILE."
66     exit 1
67 fi
68
69 . "$CONFIG_FILE"
70
71 if [ -z "$MYSQL_HOST" -o -z "$MYSQL_DATABASE" -o -z "$MYSQL_USER" -o \
72      -z "$MYSQL_PASS" -o -z "$DEFAULT_MX" -o -z "$PUBLIC_IP" ]; then
73     echo "Bad configuration. Please use:"
74     echo "   dpkg-reconfigure alternc"
75     exit 1
76 fi
77
78 if [ -f "$LOCK_FILE" ]; then
79     echo "`date` $0: last cron unfinished or stale lock file." |
80         tee -a "$DOMAIN_LOG_FILE" >&2
81     exit 1
82 fi
83
84 NAMED_CONF_FILE="$DATA_ROOT/bind/automatic.conf"
85 ZONES_DIR="$DATA_ROOT/bind/zones"
86 APACHECONF_DIR="$DATA_ROOT/apacheconf"
87 OVERRIDE_PHP_FILE="$APACHECONF_DIR/override_php.conf"
88 WEBMAIL_DIR="$DATA_ROOT/bureau/admin/webmail"
89 LOCK_FILE="$DATA_ROOT/bureau/cron.lock"
90 HTTP_DNS="$DATA_ROOT/dns"
91 HTML_HOME="$DATA_ROOT/html"
92
93 MYSQL_SELECT="mysql -h${MYSQL_HOST} -u${MYSQL_USER}
94                     -p${MYSQL_PASS} -Bs ${MYSQL_DATABASE}"
95 MYSQL_DELETE="mysql -h${MYSQL_HOST} -u${MYSQL_USER}
96                     -p${MYSQL_PASS} ${MYSQL_DATABASE}"
97
98 ########################################################################
99 # Functions
100 #
101
102 print_domain_letter() {
103     local domain="$1"
104
105     local letter=`echo "$domain" | awk '{z=split($NF, a, ".") ; print substr(a[z-1], 1, 1)}'`
106     if [ -z "$letter" ]; then
107       letter="_"
108     fi
109     echo $letter
110 }
111
112 print_user_letter() {
113     local user="$1"
114
115     echo "$user" | awk '{print substr($1, 1, 1)}'
116 }
117
118 add_to_php_override() {
119     local fqdn="$1"
120     local escaped_fqdn=`echo "$fqdn" | sed 's/\([\*|\.]\)/\\\\\1/g'`
121
122     if ! grep -q "^${escaped_fqdn}$" "$CHANGED_PHP_OVERRIDES_TMP_FILE"; then
123         echo "$fqdn" >> "$CHANGED_PHP_OVERRIDES_TMP_FILE"
124     fi
125 }
126
127 add_to_named_reload() {
128     local domain="$1"
129     local escaped_domain=`echo "$domain" | sed -e 's/\./\\\./g'`
130
131     if [ "domain" = "all" ] || grep -q "^all$" "$RELOAD_ZONES_TMP_FILE"; then
132         echo "all" > "$RELOAD_ZONES_TMP_FILE"
133     else
134         if ! grep -q "^${escaped_domain}$" "$RELOAD_ZONES_TMP_FILE"; then
135             echo "$domain" >> "$RELOAD_ZONES_TMP_FILE"
136         fi
137     fi
138 }
139
140 # we assume that the serial line contains the "serial string", eg.:
141 #                 2005012703      ; serial
142 #
143 # returns 1 if file isn't readable
144 # returns 2 if we can't find the serial number
145 # returns 3 if a tempfile can't be created
146 increment_serial() {
147     local domain="$1"
148     local zone_file="$ZONES_DIR/$domain"
149     local current_serial
150     local new_serial
151     local date
152     local revision
153     local today
154
155     if [ ! -f "$zone_file" ]; then
156         return 1
157     fi
158
159     # the assumption is here
160     current_serial=`awk '/^..*serial/ {print $1}' < "$zone_file"` || return 2
161     if [ -z "$current_serial" ]; then
162         return 2
163     fi
164
165     date=`echo $current_serial | cut -c1-8`
166     revision=`echo $current_serial | sed s/"${date}0\?"/""/g`
167     today=`date +%Y%m%d`
168     # increment the serial number only if the date hasn't changed
169     if [ "$current_date" = "$today" ] ; then
170         revision=$(($revision + 1))
171     else
172         revision=1
173         date=$today
174     fi
175     new_serial="$date`printf '%.2d' $revision`"
176
177     # replace serial number
178     cp -a -f "$zone_file" "$zone_file.$$"
179     awk -v "NEW_SERIAL=$new_serial" \
180         '{if ($3 == "serial")
181              print "            "NEW_SERIAL "   ; serial"
182           else
183              print $0}' < "$zone_file" > "$zone_file.$$"
184     mv -f "$zone_file.$$" "$zone_file"
185
186     add_to_named_reload "$domain"
187
188     return 0
189 }
190
191 change_host_ip() {
192     local domain="$1"
193     local zone_file="$ZONES_DIR/$domain"
194     local ip="$2"
195     local host="$3"
196     local pattern
197     local a_line
198
199     if [ -z "$host" ]; then
200         host="@"
201     fi
202     a_line="$host       IN      A       $ip"
203     pattern="^$host[[:space:]]*IN[[:space:]]*A[[:space:]]*.*\$"
204     if [ ! -f "$zone_file" ]; then
205         echo "Should change $host.$domain, but can't find $zone_file."
206         return 1
207     fi
208     if grep -q "$pattern" "$zone_file"; then
209         cp -a -f "$zone_file" "$zone_file.$$"
210         sed "s/$pattern/$a_line/" < "$zone_file" > "$zone_file.$$"
211         mv "$zone_file.$$" "$zone_file"
212     else
213         echo "$a_line" >> "$zone_file"
214     fi
215     add_to_named_reload "$domain"
216 }
217
218 add_host() {
219     local domain="$1"
220     local host_type="$2"
221     local host="$3"
222     local value="$4"
223     local user="$5"
224     local domain_letter=`print_domain_letter "$domain"`
225     local user_letter=`print_user_letter "$user"`
226     local ip
227     local fqdn
228     local vhost_directory
229        
230     delete_host "$domain" "$host"
231
232     if [ "$host" = "@" ]; then
233         change_host_ip "$domain" "$PUBLIC_IP"
234         fqdn="$domain"
235     else
236         if [ "$host_type" = "$TYPE_IP" ]; then
237             ip="$value"
238         else
239             ip="$PUBLIC_IP"
240         fi
241         change_host_ip "$domain" "$ip" "$host"
242         fqdn="${host}.${domain}"
243     fi
244
245     vhost_directory="${HTTP_DNS}/${domain_letter}/${fqdn}"
246     htaccess_directory="${HTTP_DNS}/redir/${domain_letter}/${fqdn}"
247
248     case "$host_type" in
249       $TYPE_LOCAL)
250         ln -snf "${HTML_HOME}/${user_letter}/${user}${value}" \
251                 "$vhost_directory"
252         ;;
253
254       $TYPE_WEBMAIL)
255         ln -snf "${WEBMAIL_DIR}" "$vhost_directory"
256         ;;
257
258       $TYPE_URL)
259         mkdir -p "$htaccess_directory"
260         (echo "RewriteEngine on"
261          echo "RewriteRule (.*) ${value}/\$1 [R,L]"
262         ) > "$htaccess_directory/.htaccess"
263         ln -snf "$htaccess_directory" "$vhost_directory"
264         ;;
265        
266       $TYPE_IP)
267         rm -f "$vhost_directory"
268         rm -rf "$htaccess_directory/.htaccess"
269         ;;
270
271       *)
272         echo "Unknow type code: $type" >> "$DOMAIN_LOG_FILE"
273         ;;
274     esac
275 }
276
277 delete_host() {
278     local domain="$1"
279     local host="$2"
280     local domain_letter=`print_domain_letter "$domain"`
281     local fqdn
282     local escaped_host
283     local escaped_fqdn
284    
285     if [ "$host" = "@" -o -z "$host" ]; then
286         fqdn="$domain"
287         escaped_host=""
288     else
289         fqdn="$host.$domain"
290         escaped_host=`echo "$host" | sed 's/\([\*|\.]\)/\\\\\1/g'`
291     fi
292
293     if [ -f "$ZONES_DIR/$domain" ] ; then
294         cp -a -f "$ZONES_DIR/$domain" "$ZONES_DIR/$domain.$$"
295         sed -e "/^$escaped_host[[:space:]]*IN[[:space:]]*A[[:space:]]/d" \
296             < "$ZONES_DIR/$domain" > "$ZONES_DIR/$domain.$$"
297         mv "$ZONES_DIR/$domain.$$" "$ZONES_DIR/$domain"
298         increment_serial "$domain"
299         add_to_named_reload "$domain"
300     fi
301
302     rm -f "$APACHECONF_DIR/$domain_letter/$fqdn"
303
304     escaped_fqdn=`echo "$fqdn" | sed 's/\([\*|\.]\)/\\\\\1/g'`
305
306     cp -a -f "$OVERRIDE_PHP_FILE" "$OVERRIDE_PHP_FILE.$$"
307     sed -e "/\/${escaped_fqdn}\$/d" \
308         < "$OVERRIDE_PHP_FILE" > "$OVERRIDE_PHP_FILE.$$"
309     mv "$OVERRIDE_PHP_FILE.$$" "$OVERRIDE_PHP_FILE"
310
311     rm -f "$HTTP_DNS/$domain_letter/$fqdn"
312     rm -rf "$HTTP_DNS/redir/$domain_letter/$fqdn"
313 }
314
315
316 init_zone() {
317     local domain="$1"
318     local escaped_domain=`echo "$domain" | sed -e 's/\./\\\./g'`
319     local zone_file="$ZONES_DIR/$domain"
320     local serial
321
322     if [ ! -f "$zone_file" ]; then
323         serial=`date +%Y%m%d`00
324         sed -e "s/@@DOMAINE@@/$domain/g;s/@@SERIAL@@/$serial/g" \
325             < "$ZONE_TEMPLATE" > "$zone_file"
326         chgrp bind "$zone_file"
327         chmod 640  "$zone_file"
328     fi
329     if ! grep -q "\"$escaped_domain\"" "$NAMED_CONF_FILE"; then
330         cp -a -f "$NAMED_CONF_FILE" "$NAMED_CONF_FILE".prec
331         sed -e "s/@@DOMAINE@@/$domain/g" \
332                 < "$NAMED_TEMPLATE" >> "$NAMED_CONF_FILE"
333         add_to_named_reload "all"
334     fi
335 }
336
337 remove_zone() {
338     local domain="$1"
339     local escaped_domain=`echo "$domain" | sed -e 's/\./\\\./g'`
340     local zone_file="$ZONES_DIR/$domain"
341
342     if [ -f "$zone_file" ]; then
343         rm -f "$zone_file"
344     fi
345
346     if grep -q "\"$escaped_domain\"" "$NAMED_CONF_FILE"; then
347         cp -a -f "$NAMED_CONF_FILE" "$NAMED_CONF_FILE.prec"
348         cp -a -f "$NAMED_CONF_FILE" "$NAMED_CONF_FILE.$$"
349         # That's for multi-line template
350         #sed -e "/^zone \"$escaped_domain\"/,/^};/d" \
351         # That's for one-line template
352         grep -v "^zone \"$escaped_domain\"" \
353             < "$NAMED_CONF_FILE" > "$NAMED_CONF_FILE.$$"
354         mv -f "$NAMED_CONF_FILE.$$" "$NAMED_CONF_FILE"
355         add_to_named_reload "all"
356     fi
357 }
358
359 change_mx() {
360     local domain="$1"
361     local mx="$2"
362     local zone_file="$ZONES_DIR/$domain"
363     local pattern="^@*[[:space:]]*IN[[:space:]]*MX[[:space:]]*[[:digit:]]*[[:space:]].*\$"
364     local mx_line="@    IN      MX      5       $mx."
365
366     # aller chercher le numéro de la ligne MX
367     # XXX: comportement inconnu si plusieurs matchs ou MX commenté
368     if grep -q "$pattern" "$zone_file"; then
369         cp -a -f "$zone_file" "$zone_file.$$"
370         sed -e "s/$pattern/$mx_line/" < "$zone_file" > "$zone_file.$$"
371         mv "$zone_file.$$" "$zone_file"
372     else
373         echo "$mx_line" >> "$zone_file"
374     fi
375
376     increment_serial "$domain"
377     add_to_named_reload "$domain"
378 }
379
380
381 ########################################################################
382 # Main
383 #
384
385 # Init
386
387 touch "$LOCK_FILE"
388 DOMAINS_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
389 HOSTS_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
390 RELOAD_ZONES_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
391 CHANGED_PHP_OVERRIDES_TMP_FILE=`mktemp -t alternc.update_domains.XXXXXX`
392
393 cleanup() {
394     rm -f "$LOCK_FILE" "$DOMAINS_TMP_FILE" "$HOSTS_TMP_FILE"
395     rm -f "$RELOAD_ZONES_TMP_FILE" "$CHANGED_PHP_OVERRIDES_TMP_FILE"
396     exit 0
397 }
398
399 trap cleanup 1 2 15
400
401 # Query database
402
403 cat << EOF | $MYSQL_SELECT | tail -n '+1' > "$DOMAINS_TMP_FILE"
404 SELECT membres.login,
405        domaines_standby.domaine,
406        domaines_standby.mx,
407        domaines_standby.gesdns,
408        domaines_standby.gesmx,
409        domaines_standby.action
410   FROM domaines_standby
411        INNER JOIN membres membres
412                ON membres.uid = domaines_standby.compte
413  ORDER BY domaines_standby.action
414 EOF
415
416 cat << EOF | $MYSQL_SELECT | tail -n '+1' > "$HOSTS_TMP_FILE"
417 SELECT membres.login,
418        sub_domaines_standby.domaine,
419        if (sub_domaines_standby.sub = '', '@', sub_domaines_standby.sub),
420        if (sub_domaines_standby.valeur = '', 'NULL',
421                                              sub_domaines_standby.valeur),
422        sub_domaines_standby.type,
423        sub_domaines_standby.action
424   FROM sub_domaines_standby
425        INNER JOIN membres membres
426                ON membres.uid = sub_domaines_standby.compte
427  ORDER BY sub_domaines_standby.action desc
428 EOF
429
430 # Handle domain updates
431
432 if [ "`wc -l < $DOMAINS_TMP_FILE`" -gt 0 ]; then
433     echo `date` >> $DOMAIN_LOG_FILE
434     cat "$DOMAINS_TMP_FILE" >> $DOMAIN_LOG_FILE
435 fi
436
437 # We need to tweak the IFS as $MYSQL_SELECT use tabs to separate fields
438 OLD_IFS="$IFS"
439 IFS="   "
440 cat "$DOMAINS_TMP_FILE" |
441 while read user domain mx are_we_dns are_we_mx action; do
442     IFS="$OLD_IFS"
443
444     DOMAIN_LETTER=`print_domain_letter "$domain"`
445     USER_LETTER=`print_user_letter "$user"`
446
447     add_to_php_override "$domain"
448     add_to_php_override "www.$domain"
449
450     case "$action" in
451       $ACTION_INSERT)
452         # default symlinks
453         ln -snf "${HTML_HOME}/${USER_LETTER}/$user" \
454                 "${HTTP_DNS}/${DOMAIN_LETTER}/$domain"
455         ln -snf "${HTML_HOME}/${USER_LETTER}/$user" \
456                 "${HTTP_DNS}/${DOMAIN_LETTER}/www.$domain"
457         ln -snf "${WEBMAIL_DIR}" "${HTTP_DNS}/${DOMAIN_LETTER}/mail.$domain"
458                        
459         if [ "$are_we_dns" = "$YES" ] ; then
460             init_zone "$domain"
461             change_host_ip "$domain" "$PUBLIC_IP"
462             change_host_ip "$domain" "$PUBLIC_IP" www
463             change_host_ip "$domain" "$PUBLIC_IP" mail
464         fi
465         ;;
466
467       $ACTION_UPDATE)
468         if [ "$are_we_dns" = "$YES" ] ; then
469             init_zone "$domain"
470             change_mx "$domain" "$mx"
471         else
472             remove_zone "$domain"
473         fi
474         ;;
475
476       $ACTION_DELETE)
477         remove_zone "$domain"
478
479         # remove symlinks
480         rm -f "${HTTP_DNS}/${DOMAIN_LETTER}/"*".$domain"
481         rm -f "${HTTP_DNS}/${DOMAIN_LETTER}/$domain"
482         rm -rf "${HTTP_DNS}/redir/${DOMAIN_LETTER}/"*".$domain"
483         rm -rf "${HTTP_DNS}/redir/${DOMAIN_LETTER}/$domain"
484         ;;
485
486       *)
487         echo "Unknown action code: $action" >> "$DOMAIN_LOG_FILE"
488         ;;
489     esac
490
491     IFS="       "
492 done
493 IFS="$OLD_IFS"
494
495 # Handle hosts update
496
497 if [ "`wc -l < $HOSTS_TMP_FILE`" -gt 0 ] ; then
498     echo `date` >> $DOMAIN_LOG_FILE
499     cat "$HOSTS_TMP_FILE" >> $DOMAIN_LOG_FILE
500 fi
501
502 OLD_IFS="$IFS"
503 IFS="   "
504 cat "$HOSTS_TMP_FILE" |
505 while read user domain host value type action; do
506     IFS="$OLD_IFS"
507
508     if [ "$host" = "@" ]; then
509         FQDN="$domain"
510     else
511         FQDN="$host.$domain"
512     fi
513     if [ "$type" != "$TYPE_IP" ]; then
514         add_to_php_override "$FQDN"
515     fi
516
517     case "$action" in
518       $ACTION_UPDATE | $ACTION_INSERT)
519         add_host "$domain" "$type" "$host" "$value" "$user"
520         ;;
521
522       $ACTION_DELETE)
523         delete_host "$domain" "$host"
524         ;;
525
526       *)
527         echo "Unknown action code: $action" >> "$DOMAIN_LOG_FILE"
528         ;;
529     esac
530
531     IFS="       "
532 done
533 IFS="$OLD_IFS"
534
535 # Update PHP overrides (basedir protection)
536 for domain in `cat "$CHANGED_PHP_OVERRIDES_TMP_FILE"`; do
537     /usr/lib/alternc/basedir_prot.sh "$domain" >> "$DOMAIN_LOG_FILE"
538 done
539
540 # Reload configuration for named and apache
541
542 RELOAD_ZONES=`cat "$RELOAD_ZONES_TMP_FILE"`
543 if [ ! -z "$RELOAD_ZONES" ]; then
544     if [ "$RELOAD_ZONES" = "all" ]; then
545         rndc reload
546     else
547         for zone in $RELOAD_ZONES; do
548             rndc reload "$zone"
549         done
550     fi
551     apachectl graceful >> "$DOMAIN_LOG_FILE"
552 fi
553
554 # Cleanup
555
556 echo "DELETE FROM domaines_standby" | $MYSQL_DELETE
557 echo "DELETE FROM sub_domaines_standby" | $MYSQL_DELETE
558
559 cleanup
560
561 # vim: et sw=4
562
Note: See TracBrowser for help on using the browser.