281 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| ##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
 | |
| ## Gestion du fichier crontab
 | |
| ##@cooked nocomments
 | |
| ##@require base
 | |
| uprovide crontab
 | |
| urequire base
 | |
| 
 | |
| # Ajouter la ligne $1 au crontab de l'utilisateur $2
 | |
| # Le code de retour est 123 si la ligne est déjà présente
 | |
| function add_to_crontab() {
 | |
|     local -a crontab=(crontab ${2:+-u "$2"})
 | |
|     local current="$("${crontab[@]}" -l 2>/dev/null)"
 | |
|     local tmpfile
 | |
|     ac_set_tmpfile tmpfile
 | |
|     if [ -n "$current" ]; then
 | |
|         echo "$current" >"$tmpfile"
 | |
|     fi
 | |
|     local NL=$'\n'
 | |
|     if quietgrep -xF "$1$NL#$1" "$tmpfile"; then
 | |
|         ac_clean "$tmpfile"
 | |
|         return 123
 | |
|     else
 | |
|         echo "$1" >>"$tmpfile"
 | |
|         "${crontab[@]}" "$tmpfile"
 | |
|         ac_clean "$tmpfile"
 | |
|     fi
 | |
| }
 | |
| # Supprimer la ligne $1 du crontab de l'utilisateur $2
 | |
| # Le code de retour est 123 si la ligne a déjà été supprimée
 | |
| function remove_from_crontab() {
 | |
|     local -a crontab=(crontab ${2:+-u "$2"})
 | |
|     local current="$("${crontab[@]}" -l 2>/dev/null)"
 | |
|     local tmpfile
 | |
|     ac_set_tmpfile tmpfile
 | |
|     if [ -n "$current" ]; then
 | |
|         echo "$current" >"$tmpfile"
 | |
|     fi
 | |
|     local NL=$'\n'
 | |
|     if ! quietgrep -xF "$1$NL#$1" "$tmpfile"; then
 | |
|         ac_clean "$tmpfile"
 | |
|         return 123
 | |
|     else
 | |
|         grep -vxF "$1$NL#$1" "$tmpfile" | "${crontab[@]}" -
 | |
|         ac_clean "$tmpfile"
 | |
|     fi
 | |
| }
 | |
| # Désactiver la ligne $1 du crontab de l'utilisateur $2 en mettant '#' devant. Si
 | |
| # la ligne n'existe pas, elle est ajoutée mais commentée.
 | |
| # Le code de retour est 123 si la ligne est déjà désactivée
 | |
| function disable_in_crontab() {
 | |
|     local -a crontab=(crontab ${2:+-u "$2"})
 | |
|     local current="$("${crontab[@]}" -l 2>/dev/null)"
 | |
|     local tmpfile
 | |
|     ac_set_tmpfile tmpfile
 | |
|     if [ -n "$current" ]; then
 | |
|         echo "$current" >"$tmpfile"
 | |
|     fi
 | |
|     local NL=$'\n'
 | |
|     if ! quietgrep -xF "$1$NL#$1" "$tmpfile"; then
 | |
|         echo "#$1" >>"$tmpfile"
 | |
|         "${crontab[@]}" "$tmpfile"
 | |
|     elif quietgrep -xF "#$1" "$tmpfile"; then
 | |
|         ac_clean "$tmpfile"
 | |
|         return 123
 | |
|     else
 | |
|         <"$tmpfile" awkrun line="$1" '$0 == line { $0 = "#" $0 } { print }' | "${crontab[@]}" -
 | |
|         ac_clean "$tmpfile"
 | |
|     fi
 | |
| }
 | |
| # Activer la ligne $1 du crontab de l'utilisateur $2 en enlevant '#' devant. Si
 | |
| # la ligne n'existe pas, elle est ajoutée.
 | |
| # Le code de retour est 123 si la ligne est déjà activée
 | |
| function enable_in_crontab() {
 | |
|     local -a crontab=(crontab ${2:+-u "$2"})
 | |
|     local current="$("${crontab[@]}" -l 2>/dev/null)"
 | |
|     local tmpfile
 | |
|     ac_set_tmpfile tmpfile
 | |
|     if [ -n "$current" ]; then
 | |
|         echo "$current" >"$tmpfile"
 | |
|     fi
 | |
|     local NL=$'\n'
 | |
|     if ! quietgrep -xF "$1$NL#$1" "$tmpfile"; then
 | |
|         echo "$1" >>"$tmpfile"
 | |
|         "${crontab[@]}" "$tmpfile"
 | |
|     elif quietgrep -xF "$1" "$tmpfile"; then
 | |
|         ac_clean "$tmpfile"
 | |
|         return 123
 | |
|     else
 | |
|         <"$tmpfile" awkrun line="$1" '$0 == "#" line { sub(/^#/, "") } { print }' | "${crontab[@]}" -
 | |
|         ac_clean "$tmpfile"
 | |
|     fi
 | |
| }
 | |
| # Afficher la spécification crontab correspondant à l'heure courante
 | |
| function ctnow() {
 | |
|     date +"%-M %-H %-d %-m %u"
 | |
| }
 | |
| # Analyser STDIN qui contient des lignes au format crontab, et afficher des
 | |
| # commandes pour les lignes correspondant à la date courante.
 | |
| # Les commandes sont de la forme "export var=value" pour la définition d'une
 | |
| # variable, "__ctexec 'cmd'" pour exécuter la commande correspondante ou
 | |
| # "__cterror 'msg'" en cas d'erreur de syntaxe sur une ligne. Il faut bien
 | |
| # entendu définir les function __ctexec et __cterror.
 | |
| # Cette fonction s'utilise de cette manière:
 | |
| #     function __ctexec() { eval "$*"; }
 | |
| #     function __cterror() { die "$*"; }
 | |
| #     eval "$(ctresolve <crontab)"
 | |
| function ctresolve() {
 | |
|     local -a ctnow
 | |
|     eval "ctnow=($(ctnow))"
 | |
|     filter_conf | awkrun -f ctnow[@] '
 | |
| function ctmatch(ctval, ref,              parts, part, i, j, start, end, step, ok) {
 | |
|   ok = 0
 | |
|   split(ctval, parts, /,/)
 | |
|   for(i = 1; i <= length(parts); i++) {
 | |
|     part = parts[i]
 | |
|     start = -1; end = -1; step = 1
 | |
|     # extraire /step
 | |
|     pos = index(part, "/")
 | |
|     if (pos != 0) { 
 | |
|       step = substr(part, pos + 1) + 0
 | |
|       part = substr(part, 1, pos - 1)
 | |
|     }
 | |
|     # traiter start-end
 | |
|     pos = index(part, "-")
 | |
|     if (pos != 0) {
 | |
|       start = substr(part, 1, pos - 1) + 0
 | |
|       end = substr(part, pos + 1) + 0
 | |
|     } else {
 | |
|       start = part + 0
 | |
|       end = start
 | |
|     }
 | |
|     # tester si ça matche
 | |
|     #print "start=" start ", end=" end ", step=" step", ref=" ref #DEBUG
 | |
|     for (j = start; j <= end; j += step) {
 | |
|       if (j == ref) {
 | |
|         ok = 1
 | |
|         break
 | |
|       }
 | |
|     }
 | |
|     if (ok) break
 | |
|   }
 | |
|   return ok
 | |
| }
 | |
| 
 | |
| BEGIN {
 | |
|   refM = ctnow[1]; refH = ctnow[2]; refdom = ctnow[3]; refmon = ctnow[4]; refdow = ctnow[5]
 | |
|   ctref = refM " " refH " " refdom " " refmon " " refdow
 | |
|   print "##now: " ctref
 | |
| 
 | |
|   match_ctline = 0
 | |
|   match_indented = 0
 | |
| }
 | |
| 
 | |
| /^(export[ \t]+)?[a-zA-Z_][a-zA-Z0-9_]*[-+%#]=/ {
 | |
|   # manipulation de variables de type PATH
 | |
|   match($0, /^(export[ \t]+)?([a-zA-Z_][a-zA-Z0-9_]*)([-+%#])=(.*)$/, parts)
 | |
|   name = parts[2]
 | |
|   type = parts[3]
 | |
|   value = parts[4]
 | |
|   if (type == "+" || type == "%") {
 | |
|     print "uaddpath " value " " name
 | |
|   } else if (type == "#") {
 | |
|     print "uinspath " value " " name
 | |
|   } else if (type == "-") {
 | |
|     print "udelpath " value " " name
 | |
|   }
 | |
|   print "export " name
 | |
|   next
 | |
| }
 | |
| /^(export[ \t]+)?[a-zA-Z_][a-zA-Z0-9_]*=/ {
 | |
|   # spécification de variable
 | |
|   sub(/^export[ \t]+/, "", $0)
 | |
|   print "export " $0
 | |
|   next
 | |
| }
 | |
| /^\$.+/ {
 | |
|   # exécution de commande arbitraire
 | |
|   if ($0 ~ /^\$\{([ \t]*(#.*)?)?$/) {
 | |
|     # commande sur plusieurs lignes
 | |
|     getline
 | |
|     while ($0 !~ /^\$\}([ \t]*(#.*)?)?$/) {
 | |
|       print
 | |
|       if (getline <= 0) break
 | |
|     }
 | |
|   } else {
 | |
|     # commande sur une seule ligne
 | |
|     sub(/^\$/, "", $0)
 | |
|     print
 | |
|   }
 | |
|   next
 | |
| }
 | |
| /^[ \t]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+[ ]*[-0-9/*,]+/ {
 | |
|   # ligne de planification
 | |
|   M = $1; H = $2; dom = $3; mon = $4; dow = $5
 | |
|   sub(/^[ ]*[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]+[^ ]+[ ]*/, "", $0)
 | |
| 
 | |
|   if (!match_ctline) match_indented = 0
 | |
|   ctline = M " " H " " dom " " mon " " dow
 | |
| 
 | |
|   gsub(/\*/, "0-59", M)
 | |
|   Mok = ctmatch(M, refM)
 | |
| 
 | |
|   gsub(/\*/, "0-23", H)
 | |
|   Hok = ctmatch(H, refH)
 | |
| 
 | |
|   gsub(/\*/, "1-31", dom)
 | |
|   domok = ctmatch(dom, refdom)
 | |
| 
 | |
|   gsub(/\*/, "1-12", mon)
 | |
|   monok = ctmatch(mon, refmon)
 | |
| 
 | |
|   gsub(/\*/, "1-7", dow)
 | |
|   dowok = ctmatch(dow, refdow)
 | |
| 
 | |
|   if (Mok && Hok && monok && (domok || dowok)) {
 | |
|     print "##matches: " ctline
 | |
|     match_ctline = 1
 | |
|     match_indented = 1
 | |
|   }
 | |
| 
 | |
|   if (match_ctline && $0 != "") {
 | |
|     print "__ctexec " quote_value($0)
 | |
|     match_ctline = 0
 | |
|   }
 | |
|   next
 | |
| }
 | |
| /^[ \t]+/ {
 | |
|   if (match_indented) {
 | |
|     # il faut matcher les commandes indentees
 | |
|     sub(/^[ \t]+/, "", $0)
 | |
|     print "__ctexec " quote_value($0)
 | |
|   }
 | |
|   next
 | |
| }
 | |
| {
 | |
|   print "__cterror " quote_value("ligne de format incorrect: " $0)
 | |
| }
 | |
| '
 | |
| }
 | |
| 
 | |
| ## Préfixes
 | |
| 
 | |
| function get_default_crontabdir_prefix() {
 | |
|     if check_sysinfos -s darwin; then
 | |
|         if check_sysinfos -d 10.6+; then
 | |
|             echo /var/at/tabs
 | |
|         else
 | |
|             echo /var/cron/tabs
 | |
|         fi
 | |
|     elif check_sysinfos -s linux; then
 | |
|         if check_sysinfos -d debianlike; then
 | |
|             echo /var/spool/cron/crontabs
 | |
|         elif check_sysinfos -d redhatlike; then
 | |
|             echo /var/spool/cron
 | |
|         fi
 | |
|     fi
 | |
| }
 | |
| 
 | |
| __crontab_prefixes=
 | |
| function __compute_crontab_prefixes() {
 | |
|     [ -n "$__crontab_prefixes" ] && return
 | |
|     CRONTABDIR="${CRONTABDIR:-$(get_default_crontabdir_prefix)}"
 | |
|     __crontab_prefixes=1
 | |
| }
 | |
| 
 | |
| UTOOLS_PREFIXES=("${UTOOLS_PREFIXES[@]}" CRONTABDIR)
 | |
| 
 | |
| function compute_crontab_prefixes() {
 | |
|     __compute_crontab_prefixes
 | |
| }
 | |
| 
 | |
| function recompute_crontab_prefixes() {
 | |
|     __crontab_prefixes=
 | |
|     __compute_crontab_prefixes
 | |
| }
 | |
| 
 | |
| function get_CRONTABDIR_prefix() {
 | |
|     __compute_crontab_prefixes
 | |
|     echo "$CRONTABDIR"
 | |
| }
 |