diff --git a/CHANGES.txt b/CHANGES.txt index b578179..88a05c0 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,10 @@ +## Version 2.18.0 du 27/10/2015-12:05 + +434403a Intégration de la branche uscrontab +2118885 uscrontab: possibilité de mettre en pause sans modifier les planifications en cours +0eeee20 awkrun: renommer les fonctions quote_* +18691c8 upassword: maj doc et support des commentaires pour le mode batch + ## Version 2.17.2 du 26/09/2015-12:25 1837a0c pxs: corriger xget, xcopy, xmove pour utiliser directement git annex sync diff --git a/VERSION.txt b/VERSION.txt index 94dc0ec..cf86907 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -2.17.2 +2.18.0 diff --git a/lib/ulib/.ulibver b/lib/ulib/.ulibver index bfd92c5..882d40e 100644 --- a/lib/ulib/.ulibver +++ b/lib/ulib/.ulibver @@ -1 +1 @@ -009004000 +009005000 diff --git a/lib/ulib/awk b/lib/ulib/awk index 3d705cf..15bb948 100644 --- a/lib/ulib/awk +++ b/lib/ulib/awk @@ -28,33 +28,68 @@ pour un tableau values qui contiendra deux valeurs: value1 et value2 Les fonctions suivantes sont définies: -quote_value(s) - quoter une valeur pour le shell. la valeur est entourée de quotes, e.g: - quote_value(\"here, \\\"there\\\" and 'everywhere'.\") - --> 'here, \"there\" and '\\''everywhere'\\''.' +num(s) + si s ne contient que des chiffres, retourner la valeur numérique associée, + sinon retournée la valeur inchangée -quoted_values() +ord(s) + retourner le code ASCII du premier caractère de la chaine s. seuls les codes + de 32 à 127 sont supportés + +hex(i) + retourner la représentation hexadécimale du nombre i + +qhtml(s) + remplacer respectivement dans la chaine s les valeurs &, \", > et < par + &, ", > et < + L'alias quote_html(s) existe pour compatibilité + +unquote_html(s) + faire le contraire de qhtml(s) + +qval(s) + quoter une valeur pour le shell. la valeur est entourée de quotes, e.g: + qval(\"here, \\\"there\\\" and 'everywhere'.\") + --> 'here, \"there\" and '\\''everywhere'\\''.' + L'alias quote_value(s) existe pour compatibilité + +qsval(s) + comme qval() mais ajouter un espace avant la valeur quotée. ceci permet de + construire facilement une ligne de commande, e.g.: + print \"mycmd\" qsval(arg1) qsval(arg2) + +qvals() quoter les valeurs \$1..\$NF pour les passer comme argument sur la ligne de commande avec eval. e.g.: - print \"mycmd \" quoted_values() + print \"mycmd \" qvals() La ligne qui est affichée pourra être évaluée avec eval dans le shell. + L'alias quoted_values(s) existe pour compatibilité -quote_subrepl(s) +qsvals(s) + comme qvals() mais ajouter un espace avant la valeur quotée. ceci permet de + construire facilement une ligne de commande, e.g.: + print \"mycmd\" qsvals() + +qsubrepl(s) quoter une valeur pour l'argument r des fonctions sub() et gsub(). Les caractères suivants sont mis en échappement: \\ & + L'alias quote_subrepl(s) existe pour compatibilité -quote_grep(s) +qgrep(s) quoter une valeur pour un pattern *simple* de grep. Les caractères suivants sont mis en échappement: \\ . [ ^ \$ * + L'alias quote_grep(s) existe pour compatibilité -quote_egrep(s) +qegrep(s) quoter une valeur pour un pattern *étendu* de grep. Les caractères suivants sont mis en échappement: \\ . [ ^ \$ ? + * ( ) | { + L'alias quote_egrep(s) existe pour compatibilité -quote_sql(s) +qsql(s) quoter une valeur pour un script sql. la valeur est entourée de quotes, e.g: quote_sql(\"hello'there\") --> 'hello''there' + L'alias quote_sql(s) existe pour compatibilité unquote_mysqlcsv(s) Analyser une valeur exportée de MySQL avec mysqlcsv. Les transformations diff --git a/lib/ulib/base b/lib/ulib/base index d369ed6..596411f 100644 --- a/lib/ulib/base +++ b/lib/ulib/base @@ -1848,13 +1848,14 @@ function hex(i, s) { if (length(s) < 2) s = "0" s return s } -function quote_html(s) { +function qhtml(s) { gsub(/&/, "\\&", s) gsub(/"/, "\\"", s) gsub(/>/, "\\>", s) gsub(/", s) @@ -1862,11 +1863,15 @@ function unquote_html(s) { gsub(/&/, "\\&", s) return s } -function quote_value(s) {'" +function qval(s) {'" gsub(/'/, \"'\\\\''\", s) return \"'\" s \"'\" "'} -function quoted_values( i, line) { +function quote_value(s) { return qval(s) } +function qsval(s) { + return " " qval(s) +} +function qvals( i, line) { line = "" for (i = 1; i <= NF; i++) { if (i > 1) line = line " " @@ -1874,27 +1879,36 @@ function quoted_values( i, line) { } return line } -function quote_regexp(s) { +function quoted_values() { return qvals() } +function qsvals() { + return " " qvals() +} +function qregexp(s) { gsub(/[[\\.^$*+?()|{]/, "\\\\&", s) return s } -function quote_subrepl(s) { +function quote_regexp(s) { return qregexp(s) } +function qsubrepl(s) { gsub(/\\/, "\\\\", s) gsub(/&/, "\\\\&", s) return s } -function quote_grep(s) { +function quote_subrepl(s) { return qsubrepl(s) } +function qgrep(s) { gsub(/[[\\.^$*]/, "\\\\&", s) return s } -function quote_egrep(s) { +function quote_grep(s) { return qgrep(s) } +function qegrep(s) { gsub(/[[\\.^$*+?()|{]/, "\\\\&", s) return s } -function quote_sql(s) {'" +function quote_egrep(s) { return qegrep(s) } +function qsql(s) {'" gsub(/'/, \"''\", s) return \"'\" s \"'\" "'} +function quote_sql(s) { return qsql(s) } function unquote_mysqlcsv(s) { gsub(/\\n/, "\n", s) gsub(/\\t/, "\t", s) diff --git a/lib/ulib/crontab b/lib/ulib/crontab index 93ac289..9ff5747 100644 --- a/lib/ulib/crontab +++ b/lib/ulib/crontab @@ -92,7 +92,12 @@ function enable_in_crontab() { } # Afficher la spécification crontab correspondant à l'heure courante function ctnow() { - date +"%-M %-H %-d %-m %u" + #date +"%-M %-H %-d %-m %u" + if [ -n "$1" ]; then + echo "$1" | awk '{ print strftime("%-M %-H %-d %-m %u", $0) }' + else + awk 'BEGIN { print strftime("%-M %-H %-d %-m %u", systime()) }' + fi } __CTRESOLVE_CTNOW="" # Analyser STDIN qui contient des lignes au format crontab, et afficher des diff --git a/upassword b/upassword index 9d4f1de..b6e9df7 100755 --- a/upassword +++ b/upassword @@ -4398,7 +4398,7 @@ public class upassword { /** * Vérifier que le mot de spécifié est de qualité. - * + * * @return null si le mot de passe est correct. Sinon, retourner un message qui indique ce * qui ne va pas. */ @@ -4868,6 +4868,7 @@ public class upassword { + "\n upassword -f aeskeyfile -s" + "\n upassword -f aeskeyfile -e clear" + "\n upassword -f aeskeyfile -d crypted" + + "\n upassword --batch" + "\n\nOPTIONS" + "\n -p, --hash-password" + "\n Crypter un mot de passe (option par défaut). Si le mot de passe en clair" @@ -4890,7 +4891,32 @@ public class upassword { + "\n Spécifier le fichier contenant la clé AES. Cette option est obligatoire" + "\n avec les options -G, -s, -e et -d" + "\n --shell" - + "\n Afficher les valeurs pour évaluation par le shell"); + + "\n Afficher les valeurs pour évaluation par le shell" + + "\n\nMODE BATCH" + + "\nUtiliser l'option --batch active le mode batch. Dans ce mode, chaque ligne est" + + "\nun ensemble d'arguments, comme si on avait lancé le script à plusieurs reprises." + + "\nL'analyseur est limité: le découpage des arguments est fait sur les espaces." + + "\nLes lignes commençant par # sont ignorées." + + "\nSi une ligne commence par --batch-after, alors cette ligne est affichée après" + + "\nchaque résultat. Ceci permet de générer un script qui peut être évalué." + + "\n\nVoici un exemple:" + + "\n upassword --batch <= 2 && arg.substring(0, 2).equals("-j")) + || arg.equals("--clear-is-codetu")) { int shift = 1; if (arg.equals("-j") || arg.equals("--clear-is-codetu")) { if (args.length > i + 1) { @@ -4931,7 +4958,8 @@ public class upassword { } else if (arg.equals("-d") || arg.equals("--aes-decrypt")) { action = EAction.AES_DECRYPT; i++; - } else if (arg.substring(0, 2).equals("-f") || arg.equals("--aes-keyfile")) { + } else if ((arg.length() >= 2 && arg.substring(0, 2).equals("-f")) + || arg.equals("--aes-keyfile")) { int shift = 1; if (arg.equals("-f") || arg.equals("--aes-keyfile")) { if (args.length > i + 1) { @@ -5171,10 +5199,15 @@ public class upassword { while (true) { String line = br.readLine(); if (line == null) break; - if (line.startsWith(AFTER_COMMAND)) { + if (line.startsWith("#")) { + // Ignorer + } else if (line.startsWith(AFTER_COMMAND)) { after = line.substring(AFTER_COMMAND_STRIP); } else { - upassword.run(SPACES.split(line)); + line = line.trim(); + if (line.equals("")) args = new String[0]; + else args = SPACES.split(line); + upassword.run(args); if (after != null) println(after); } } diff --git a/uscrontab b/uscrontab index 05cfe5a..06a9092 100755 --- a/uscrontab +++ b/uscrontab @@ -236,6 +236,18 @@ OPTIONS $USCRONTAB_USERDIR -n, --fake Afficher au lieu de les exécuter les commandes qui doivent être lancées + -P, --pause-for NBMINS + Désactiver les planifications pendant NBMINS minutes. Utiliser -1 pour + désactiver les planifications sans limite de durée. Pendant la période + de pause, toutes les invocations de uscrontab n'ont aucun effet, sauf si + on utilise l'option --force + -Y, --unpause + Réactiver les planifications après une mise en pause + -p, --pause + Désactiver les planifications pendant 1 journée. Equivalent à -P 1440 + -f, --force + Forcer l'exécution de la planification, même si elle a été mise en pause + avec l'option --pause OPTIONS AVANCEES --lock LOCKFILE @@ -298,6 +310,21 @@ function get_usercrontab() { fi } +function check_pause() { + # retourner 0 si on est en pause + local pauseuntil pausefile="$pausefile" now="$2" + if [ -f "$pausefile" ]; then + pauseuntil="$(<"$pausefile")" + if [ -z "$pauseuntil" ]; then + # pause sans limitation de durée + return 0 + elif [ "$pauseuntil" -gt "$now" ]; then + return 0 + fi + fi + return 1 +} + USCRONTAB_CTLINE="* * * * * $script" USCRONTAB_LOCKDELAY=8 USCRONTAB_STOPEC=101 @@ -312,6 +339,8 @@ lockfile=auto lockdelay= fake= continuous= +pause= +force= parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with display_help' \ -A,--add,--install action=install \ @@ -322,6 +351,10 @@ parse_opts "${PRETTYOPTS[@]}" \ -r,--remove action=remove \ -l,--list action=list \ -n,--fake fake=1 \ + -P:,--pause-for: '$action=pause; set@ pause' \ + -p,--pause action=pause \ + -Y,--unpause action=unpause \ + -f,--force force=1 \ --lock: lockfile= \ --lockdelay: lockdelay= \ -c,--continuous continuous=1 \ @@ -332,7 +365,28 @@ parse_opts "${PRETTYOPTS[@]}" \ uscrontab="$1"; shift -if [ "$action" == "edit" ]; then +pausefile="$USCRONTAB_USERFILE.pauseuntil" +now="$(awk 'BEGIN { print int(systime() / 60) * 60 }')" + +if [ "$action" == "pause" ]; then + [ -n "$pause" ] || pause=1440 + if [ "$pause" -lt 0 ]; then + pauseuntil= + else + pauseuntil=$(($now + $pause * 60)) + fi + echo "$pauseuntil" >"$pausefile" || die + enote "Désactivation des planifications pour $pause minute(s)" + exit 0 + +elif [ "$action" == "unpause" ]; then + if [ -f "$pausefile" ]; then + rm "$pausefile" || die + enote "Réactivation des planifications" + fi + exit 0 + +elif [ "$action" == "edit" ]; then if [ -z "$uscrontab" ]; then basedir="$(dirname "$USCRONTAB_USERFILE")" [ -d "$basedir" ] || die "$basedir: ce répertoire n'existe pas. Vérifiez l'installation de nutools" @@ -375,6 +429,10 @@ elif [ "$action" == "remove" ]; then exit 0 elif [ "$action" == "list" ]; then + if check_pause "$pausefile" "$now"; then + ewarn "En pause. Réactiver avec $scriptname -Y" + fi + if [ -n "$uscrontab" ]; then uscrontab="$(abspath "$uscrontab")" array_from_lines ctfiles "$(crontab -l 2>/dev/null | awkrun script="$script" uscrontab="$uscrontab" '$6 == script && $7 == uscrontab { print $7 }')" @@ -394,9 +452,9 @@ elif [ "$action" == "list" ]; then array_del ctfiles "#GENERIC" set_usercrontabs usercrontabs array_extend ctfiles usercrontabs - ewarn "planification générique désactivée. Vous pouvez la réactiver avec $scriptname -A" + ewarn "Planification générique désactivée. Vous pouvez la réactiver avec $scriptname -A" elif [ ${#ctfiles[*]} -eq 0 ]; then - einfo "aucune planification en cours" + einfo "Aucune planification en cours" set_usercrontabs ctfiles fi fi @@ -410,7 +468,7 @@ elif [ "$action" == "list" ]; then exit $r elif [ "$action" == "show-ctnow" ]; then - ctnow + ctnow "$now" exit 0 fi @@ -432,6 +490,17 @@ elif [ "$action" == "uninstall" ]; then fi elif [ "$action" == "run" ]; then + if [ -n "$force" ]; then + # ne pas tenir compte de l'état de pause + : + elif check_pause "$pausefile" "$now"; then + ewarn "En pause. Réactiver avec $scriptname -Y" + ac_clean "$lockfile" + exit 0 + elif [ -f "$pausefile" ]; then + rm "$pausefile" + fi + if [ -n "$uscrontab" ]; then default_lockfile="/var/run/$scriptname$uscrontab.lock" else