Intégration de la branche release-7.2.0
This commit is contained in:
		
						commit
						4b30a7815b
					
				
							
								
								
									
										25
									
								
								CHANGES.md
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								CHANGES.md
									
									
									
									
									
								
							| @ -1,3 +1,28 @@ | ||||
| ## Version 7.2.0 du 26/09/2017-17:01 | ||||
| 
 | ||||
| * `1e576da` multiconf: rajouter conf_upgrade() dans conf_auto() | ||||
| * `eeef48d` Intégration de la branche update-config | ||||
|   * `ea45055` implémentation simplifiée avec conf_upgrade() | ||||
|   * `efc60b3` description des modifications | ||||
| * `36eec4a` Intégration de la branche update-ufile | ||||
|   * `2afffef` ne pas implémenter la recherche automatique de fichier de configuration | ||||
|   * `6ec37f6` ufile: implémenter l'option -r | ||||
|   * `6e8c200` maj TODO | ||||
| * `cf629e6` uscrontab: support des oneshot vars | ||||
| * `a66c0c2` uscrontab: ajout des options -@, -H, -M | ||||
| * `52e838e` uwatch: ajouter les options -w et -p pour attendre la disparition d'un fichier ou d'un processus | ||||
| * `8ad2e4c` lftp ne supporte pas l'utilisation des guillemets | ||||
| * `7fb81a0` désactiver la vérification du certificat par défaut | ||||
| * `dbc3daa` multiconf: bug | ||||
| * `aff1c15` multiconf: support des variables de type path et compatibilité avec bash 4.3 | ||||
| * `8e17fb1` Intégration de la branche add-multiconf | ||||
|   * `a916180` ajouter conf_install pour installer les fichiers de configuration dans un répertoire standardisé | ||||
|   * `0372a5c` ufile charge les fichiers de ~/etc/ufile.d/ | ||||
|   * `7d1ec90` simplifier l'API | ||||
|   * `c988692` fin implémentation | ||||
|   * `72e0c36` maj doc | ||||
|   * `f472501` squelette initial | ||||
| 
 | ||||
| ## Version 7.1.0 du 10/09/2017-19:20 | ||||
| 
 | ||||
| * `f131e21` uwatch: ajout de l'option -r | ||||
|  | ||||
| @ -1 +1 @@ | ||||
| 7.1.0 | ||||
| 7.2.0 | ||||
|  | ||||
							
								
								
									
										13
									
								
								authftp
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								authftp
									
									
									
									
									
								
							| @ -28,6 +28,9 @@ OPTIONS | ||||
|     --tls | ||||
|         Indiquer que la connexion se fera en TLS. Implique --lftp puisque ncftp | ||||
|         ne le supporte pas. | ||||
|     --verify-certificate | ||||
|         Avec la connexion --tls, forcer la vérification du certificat, qui est | ||||
|         désactivée par défaut. | ||||
| 
 | ||||
| note: A cause d'une limitation de lftp, ce n'est pas possible de se connecter | ||||
| automatiquement avec lftp si le mot de passe contient une virgule. A cause de la | ||||
| @ -43,6 +46,7 @@ noproxy="$AUTHFTP_PROXY_DISABLED" | ||||
| lftp= | ||||
| options=() | ||||
| tls= | ||||
| verify_certificate=no | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -p,--proxy noproxy= \ | ||||
| @ -50,6 +54,7 @@ parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     -l,--lftp lftp=1 \ | ||||
|     -o:,--option: options \ | ||||
|     --tls tls=1 \ | ||||
|     --verify-certificate verify_certificate=yes \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| [ -n "$noproxy" -o -n "$AUTHFTP_PROXY_HOST" ] || die "AUTHFTP_PROXY_HOST doit être défini" | ||||
| @ -66,9 +71,13 @@ read_value -i "Entrez le chemin" path "$4" N | ||||
| 
 | ||||
| if [ -n "$lftp" ]; then | ||||
|     if [ -n "$noproxy" ]; then | ||||
|         exec lftp -u "$login,$password" "${options[@]}" "ftp://$host/$path" | ||||
|         exec lftp "${options[@]}" -e "\ | ||||
| set ssl:verify-certificate $verify_certificate | ||||
| open -u $login,$password ftp://$host/$path" | ||||
|     else | ||||
|         exec lftp -u "${login}@${my_login}@${host},${password}@${my_password}" "${options[@]}" "ftp://$AUTHFTP_PROXY_HOST/$path" | ||||
|         exec lftp "${options[@]}" -e "\ | ||||
| set ssl:verify-certificate $verify_certificate | ||||
| open -u ${login}@${my_login}@${host},${password}@${my_password} ftp://$AUTHFTP_PROXY_HOST/$path" | ||||
|     fi | ||||
| else | ||||
|     if [ -n "$noproxy" ]; then | ||||
|  | ||||
| @ -1,9 +1,5 @@ | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| 
 | ||||
| # Fichiers externes à inclure. Chacun de ces fichiers peut contenir des | ||||
| # définitions de fonctions et de la variables RULES | ||||
| INCLUDES=() | ||||
| 
 | ||||
| # Règles pour le classement des fichiers. Chaque règle est de la forme | ||||
| # pattern:destdir[:renamef] | ||||
| RULES=() | ||||
|  | ||||
| @ -111,7 +111,15 @@ function copy_update_ask() { | ||||
|     # Copier ou mettre à jour le fichier $1 vers le fichier $2. | ||||
|     # Si le fichier existe déjà, la différence est affichée, et une confirmation | ||||
|     # est demandée pour l'écrasement du fichier. | ||||
|     # si $1 commence par '-' alors on s'en sert comme option pour configurer le | ||||
|     # niveau d'interaction pour demander la confirmation. les paramètres sont | ||||
|     # alors décalés | ||||
|     # Retourner vrai si le fichier a été copié sans erreur. | ||||
|     local interopt=-c | ||||
|     if [[ "$1" == -* ]]; then | ||||
|         interopt="$1" | ||||
|         shift | ||||
|     fi | ||||
|     local src="$1" dest="$2" | ||||
| 
 | ||||
|     [ -d "$dest" ] && dest="$dest/$(basename -- "$src")" | ||||
| @ -119,10 +127,14 @@ function copy_update_ask() { | ||||
| 
 | ||||
|     [ -f "$dest" ] || copy_replace "$src" "$dest" | ||||
|     if testdiff "$src" "$dest"; then | ||||
|         diff -u "$dest" "$src" | ||||
|         if ask_yesno -c "Voulez-vous remplacer $(ppath "$dest") par la nouvelle version?" C; then | ||||
|         check_interaction "$interopt" && diff -u "$dest" "$src" | ||||
|         if ask_yesno "$interopt" "Voulez-vous remplacer $(ppath "$dest") par la nouvelle version?" C; then | ||||
|             copy_replace "$src" "$dest" "$3" | ||||
|             return $? | ||||
|         elif ! check_interaction "$interopt"; then | ||||
|             ewarn "Les mises à jours suivantes sont disponibles:" | ||||
|             diff -u "$dest" "$src" | ||||
|             ewarn "Le fichier $(ppath "$dest") n'a pas été mis à jour" | ||||
|         fi | ||||
|     fi | ||||
|     return 1 | ||||
|  | ||||
							
								
								
									
										307
									
								
								lib/ulib/multiconf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								lib/ulib/multiconf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,307 @@ | ||||
| ##@cooked comments # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| ## Gestion de fichiers de configuration et de répertoires de configuration | ||||
| ##@cooked nocomments | ||||
| uprovide multiconf | ||||
| urequire install | ||||
| 
 | ||||
| function conf_local() { | ||||
|     # afficher les commandes pour définir comme locales les variables utilisées | ||||
|     # par les fonctions conf_* | ||||
|     # cela permet d'utiliser ces fonctions à l'intérieur d'autres fonctions sans | ||||
|     # polluer l'espace de nom | ||||
|     echo "local -a __CONF_DESCS __CONF_ARRAY_VARS __CONF_PATH_VARS" | ||||
| } | ||||
| 
 | ||||
| function conf_auto() { | ||||
|     # charger la configuration pour l'outil $1 avec les variables $2..@ | ||||
|     # conf_init n'est appelé que si des variables sont spécifiées, ce qui permet | ||||
|     # d'appeler conf_init au préalable si une configuration spécifique doit être | ||||
|     # faite. | ||||
|     # Ainsi: | ||||
|     #     conf_auto NAME VARS... | ||||
|     # est équivalent à: | ||||
|     #     conf_init VARS... | ||||
|     #     conf_auto NAME | ||||
|     # est équivalent à: | ||||
|     #     conf_init VARS... | ||||
|     #     conf_find_files __CONF_FILES ~/etc/default/NAME.conf ~/etc/NAME.d/*.conf | ||||
|     #     conf_upgrade ~/etc/default/NAME.conf | ||||
|     #     conf_load_files "${__CONF_FILES[@]}" | ||||
|     # Pour supporter les scénarii où les fichiers de configuration sont ailleurs | ||||
|     # que dans ~/etc/default, l'argument NAME peut être un chemin: | ||||
|     #    conf_auto PATH/TO/NAME VARS... | ||||
|     # est équivalent à: | ||||
|     #     conf_init VARS... | ||||
|     #     conf_find_files __CONF_FILES PATH/TO/NAME.conf PATH/TO/NAME.d/*.conf | ||||
|     #     conf_upgrade PATH/TO/NAME.conf | ||||
|     #     conf_load_files "${__CONF_FILES[@]}" | ||||
|     local __name="$1"; shift | ||||
|     [ -n "$__name" ] || return 1 | ||||
|     [ $# -gt 0 ] && conf_init "$@" | ||||
|     local -a __CONF_FILES | ||||
|     if [[ "$__name" == */* ]]; then | ||||
|         conf_find_files __CONFS_FILES "$__name.conf" "$__name.d/*.conf" | ||||
|         [ $# -gt 0 ] && conf_upgrade "$__name.conf" | ||||
|     else | ||||
|         conf_find_files __CONFS_FILES "$HOME/etc/default/$__name.conf" "$HOME/etc/$__name.d/*.conf" | ||||
|         [ $# -gt 0 ] && conf_upgrade "$HOME/etc/default/$__name.conf" | ||||
|     fi | ||||
|     conf_load_files "${__CONFS_FILES[@]}" | ||||
| } | ||||
| 
 | ||||
| function conf_init() { | ||||
|     # définir les variables attendues lors du chargement des fichiers de | ||||
|     # configuration par conf_load_files() | ||||
|     # Si cette fonction n'a pas d'argument, le contenu du tableau CONFIG s'il | ||||
|     # est existe est utilisé | ||||
|     # par défaut, les variables sont en mode scalaire: la définition d'une | ||||
|     # variable écrase la valeur précédente. Avec l'option -a les variables sont | ||||
|     # en mode tableau: les nouvelles valeurs sont rajoutées à la fin du tableau. | ||||
|     # Avec l'option -p les variables sont en mode chemin: les nouvelles valeurs | ||||
|     # sont ajoutées si elles n'existe pas déjà avec le séparateur ':' | ||||
|     # dans l'exemple suivant: | ||||
|     #     conf_init NAME VALUE -a SRCDIRS DESTDIRS -p LIBPATH | ||||
|     # NAME et VALUE sont scalaires, SRCDIRS et DESTDIRS sont des tableaux et | ||||
|     # LIBPATH est de type chemin | ||||
|     # Les variables scalaires et chemin sont initialisées à la valeur vide ou à | ||||
|     # la valeur spécifiée e.g.: | ||||
|     #     conf_init VAR=value MYPATH=a:b:c | ||||
|     # Les variables tableaux sont toujours initialisées à la valeur vide | ||||
|     # L'option -s permet de revenir au mode scalaire | ||||
| 
 | ||||
|     # Note: il est possible d'associer une description à chaque variable ainsi | ||||
|     # qu'un en-tête, ce qui permet de construire le fichier de configuration ou | ||||
|     # de mettre à jour un fichier existant avec conf_upgrade(). Par exemple, les | ||||
|     # commandes suivantes: | ||||
|     #     CONFIG=( | ||||
|     #         "# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8" | ||||
|     #         "# configurer l'application" | ||||
|     #         -s | ||||
|     #         "NAME=payet//nom de l'administrateur" | ||||
|     #         "MAIL=admin@host.tld//mail de contact" | ||||
|     #         -a | ||||
|     #         "HOSTS//hôtes autorisés à se connecter" | ||||
|     #     ) | ||||
|     #     conf_init | ||||
|     # permettent de générer automatiquement le fichier de configuration suivant: | ||||
|     #     # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
|     #     # configurer l'application | ||||
|     # | ||||
|     #     # nom de l'administrateur | ||||
|     #     #NAME=payet | ||||
|     # | ||||
|     #     # mail de contact | ||||
|     #     #MAIL=admin@host.tld | ||||
|     # | ||||
|     #     # hôtes autorisés à se connecter | ||||
|     #     #HOSTS=() | ||||
|     __CONF_DESCS=() | ||||
|     __CONF_ARRAY_VARS=() | ||||
|     __CONF_PATH_VARS=() | ||||
|     local __type=scalar __initial=1 __prefix __var __desc | ||||
|     [ $# -eq 0 ] && is_array CONFIG && set -- "${CONFIG[@]}" | ||||
|     while [ $# -gt 0 ]; do | ||||
|         if [ -n "$__initial" ]; then | ||||
|             if [ "${1:0:1}" == "#" ]; then | ||||
|                 [ ${#__prefix} -gt 0 ] && __prefix="$__prefix"$'\n' | ||||
|                 __prefix="$__prefix$1" | ||||
|                 shift | ||||
|                 continue | ||||
|             else | ||||
|                 [ -n "$__prefix" ] && array_add __CONF_DESCS "$__prefix" | ||||
|                 __initial= | ||||
|             fi | ||||
|         fi | ||||
|         case "$1" in | ||||
|         -a|--array) __type=array;; | ||||
|         -p|--path) __type=path;; | ||||
|         -s|--scalar) __type=scalar;; | ||||
|         *) | ||||
|             array_add __CONF_DESCS "$1" | ||||
|             splitfsep "$1" // __var __desc | ||||
|             case "$__type" in | ||||
|             array) | ||||
|                 eval "${__var%%=*}=()" | ||||
|                 array_addu __CONF_ARRAY_VARS "${__var%%=*}" | ||||
|                 array_del __CONF_PATH_VARS "${__var%%=*}" | ||||
|                 ;; | ||||
|             path) | ||||
|                 setv "$__var" | ||||
|                 array_addu __CONF_PATH_VARS "${__var%%=*}" | ||||
|                 array_del __CONF_ARRAY_VARS "${__var%%=*}" | ||||
|                 ;; | ||||
|             scalar) | ||||
|                 setv "$__var" | ||||
|                 ;; | ||||
|             esac | ||||
|             ;; | ||||
|         esac | ||||
|         shift | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| function conf_load() { | ||||
|     # charger les fichiers de configuration spécifiés | ||||
|     #     conf_load SPECS... | ||||
|     # est équivalent à: | ||||
|     #     conf_find_files __CONF_FILES SPECS... | ||||
|     #     conf_load_files "${__CONF_FILES[@]}" | ||||
|     local -a __CONF_FILES | ||||
|     conf_find_files __CONFS_FILES "$@" | ||||
|     conf_load_files "${__CONFS_FILES[@]}" | ||||
| } | ||||
| 
 | ||||
| function conf_find_files() { | ||||
|     # initialiser le tableau $1 avec les fichiers de configuration correspondant | ||||
|     # aux arguments $2..@ | ||||
|     # - si on spécifie un fichier, il est pris tel quel s'il existe | ||||
|     # - si on spécifie un répertoire, tous les fichiers *.conf de ce répertoire | ||||
|     #   sont pris | ||||
|     # - si on spécifie un pattern e.g path/to/*.conf alors tous les fichiers | ||||
|     #   correspondant au pattern sont pris | ||||
|     # - sinon l'argument est ignoré | ||||
|     local __conf_dest="$1"; shift | ||||
|     local -a __conf_files | ||||
|     local __conf_spec __conf_dir __conf_wc | ||||
|     array_new "$__conf_dest" | ||||
|     for __conf_spec in "$@"; do | ||||
|         if [ -f "$__conf_spec" ]; then | ||||
|             array_add "$__conf_dest" "$__conf_spec" | ||||
|             continue | ||||
|         elif [ -d "$__conf_spec" ]; then | ||||
|             __conf_spec="$__conf_spec/*.conf" | ||||
|         fi | ||||
|         splitwcs "$__conf_spec" __conf_dir __conf_wc | ||||
|         array_lsfiles __conf_files "${__conf_dir:-.}" "$__conf_wc" | ||||
|         array_extend "$__conf_dest" __conf_files | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| function conf_load_files() { | ||||
|     # sourcer les fichiers spécifiés en faisant ce qui est nécessaire pour que | ||||
|     # les variables de __CONF_ARRAY_VARS soient correctement traitées. | ||||
|     local -a __conf_backups __conf_values | ||||
|     local __conf_file __conf_name __conf_i __conf_backup __conf_bn __conf_bv | ||||
|     for __conf_file in "$@"; do | ||||
|         # faire une copie de sauvegarde puis supprimer les variables tableaux | ||||
|         __conf_backups=() | ||||
|         for __conf_name in "${__CONF_ARRAY_VARS[@]}" "${__CONF_PATH_VARS[@]}"; do | ||||
|             __conf_backup="$(declare -p "$__conf_name" 2>/dev/null)" | ||||
|             if [ -z "$__conf_backup" ]; then | ||||
|                 __conf_backup="$__conf_name=" | ||||
|             else | ||||
|                 # faire une correction de l'expression parce que la commande | ||||
|                 # affichée par declare -p est différente entre bash 4.3 et bash | ||||
|                 # 4.4 pour les tableaux. soit le tableau array=(a b) | ||||
|                 # - bash 4.3 affiche      declare -a array='([0]="a" [1]="b")' | ||||
|                 # - bash 4.4 affiche      declare -a array=([0]="a" [1]="b") | ||||
|                 __conf_backup="${__conf_backup#declare }" | ||||
|                 __conf_bn="${__conf_backup%% *}" | ||||
|                 __conf_bv="${__conf_backup#* }" | ||||
|                 if [[ "$__conf_bn" == -*a* ]]; then | ||||
|                     __conf_bn="${__conf_bv%%=*}" | ||||
|                     __conf_bv="${__conf_bv#*=}" | ||||
|                     if [ "${__conf_bv:0:2}" == "'(" -a "${__conf_bv: -2:2}" == ")'" ]; then | ||||
|                         __conf_backup="$__conf_bn=$(eval "echo $__conf_bv")" | ||||
|                     else | ||||
|                         __conf_backup="$__conf_bn=$__conf_bv" | ||||
|                     fi | ||||
|                 else | ||||
|                     __conf_backup="$__conf_bv" | ||||
|                 fi | ||||
|             fi | ||||
|             __conf_backups=("${__conf_backups[@]}" "$__conf_backup") | ||||
|             unset "$__conf_name" | ||||
|         done | ||||
|         # charger le fichier | ||||
|         source "$__conf_file" | ||||
|         # puis restaurer les variables ou les fusionner avec une éventuelle nouvelle valeur | ||||
|         __conf_i=0 | ||||
|         for __conf_name in "${__CONF_ARRAY_VARS[@]}" "${__CONF_PATH_VARS[@]}"; do | ||||
|             __conf_backup="${__conf_backups[$__conf_i]}" | ||||
|             if [ -n "$(declare -p "$__conf_name" 2>/dev/null)" ]; then | ||||
|                 # la variable a été redéfinie, la fusionner avec la précédente valeur | ||||
|                 if array_contains __CONF_ARRAY_VARS "$__conf_name"; then | ||||
|                     array_copy __conf_values "$__conf_name" | ||||
|                     eval "$__conf_backup" | ||||
|                     array_extend "$__conf_name" __conf_values | ||||
|                 elif array_contains __CONF_PATH_VARS "$__conf_name"; then | ||||
|                     __conf_values="${!__conf_name}" | ||||
|                     eval "$__conf_backup" | ||||
|                     uaddpath "$__conf_values" "$__conf_name" | ||||
|                 fi | ||||
|             else | ||||
|                 # la variable n'a pas été redéfinie, restaurer la précédente valeur | ||||
|                 eval "$__conf_backup" | ||||
|             fi | ||||
|             __conf_i=$(($__conf_i + 1)) | ||||
|         done | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| function conf_install() { | ||||
|     # USAGE: conf_install DEST SRCS... | ||||
|     # installer les fichiers de SRCS dans le répertoire standardisé DEST | ||||
|     # ## destination | ||||
|     # - si DEST est un nom sans chemin, e.g NAME, alors la destination est | ||||
|     #   ~/etc/NAME.d | ||||
|     # - si DEST est un nom avec chemin, alors la valeur est prise telle quelle | ||||
|     #   comme destination, et le répertoire est créé le cas échéant. | ||||
|     # Si un fichier existe déjà dans la destination, afficher une demande de | ||||
|     # confirmation avant de l'écraser | ||||
|     # ## source | ||||
|     # - si SRC est un fichier, le prendre tel quel | ||||
|     # - si SRC est un répertoire, prendre tous les fichiers SRC/*.conf | ||||
|     # - si SRC est un pattern, prendre tous les fichiers correspondant | ||||
|     local -a srcs | ||||
|     local src dir wc | ||||
|     local dest="$1"; shift | ||||
|     [[ "$dest" == */* ]] || dest="$HOME/etc/$dest.d" | ||||
|     mkdir -p "$dest" || return 1 | ||||
|     for src in "$@"; do | ||||
|         if [ -f "$src" ]; then | ||||
|             srcs=("$src") | ||||
|         elif [ -d "$src" ]; then | ||||
|             array_lsfiles srcs "$src" "*.conf" | ||||
|         else | ||||
|             splitwcs "$src" dir wc | ||||
|             array_lsfiles srcs "$dir" "$wc" | ||||
|         fi | ||||
|         for src in "${srcs[@]}"; do | ||||
|             copy_update_ask -y "$src" "$dest" | ||||
|         done | ||||
|     done | ||||
| } | ||||
| 
 | ||||
| function conf_upgrade() { | ||||
|     # USAGE: conf_upgrade DEST VARS... | ||||
|     # Si les variables VARS... sont spécifiées, on appelle au préalable conf_init() | ||||
|     local dest="$1"; shift | ||||
|     if [ $# -gt 0 ]; then | ||||
|         eval "$(conf_local)" | ||||
|         conf_init "$@" | ||||
|     fi | ||||
|     local desc namevalue name value | ||||
|     # calculer le préfixe et initialiser le fichier le cas échéant | ||||
|     if [ ! -f "$dest" ]; then | ||||
|         local prefix | ||||
|         for desc in "${__CONF_DESCS[@]}"; do | ||||
|             [ "${desc:0:1}" == "#" ] && prefix="$desc" | ||||
|             break | ||||
|         done | ||||
|         [ ${#prefix} -gt 0 ] || prefix="# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8" | ||||
|         echo "$prefix" >"$dest" | ||||
|     fi | ||||
|     # vérifier la présence de chaque variable | ||||
|     for desc in "${__CONF_DESCS[@]}"; do | ||||
|         [ "${desc:0:1}" == "#" ] && continue | ||||
|         splitfsep "$desc" // namevalue desc | ||||
|         splitvar "$namevalue" name value | ||||
|         if ! grep -qE "^\s*#*(\s*export)?\s*$name=" "$dest"; then | ||||
|             echo >>"$dest" | ||||
|             [ -n "$desc" ] && echo "# $desc" >>"$dest" | ||||
|             echo -n "#" >>"$dest" | ||||
|             echo_setv "$name" "$value" >>"$dest" | ||||
|         fi | ||||
|     done | ||||
| } | ||||
							
								
								
									
										50
									
								
								ufile
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								ufile
									
									
									
									
									
								
							| @ -1,7 +1,7 @@ | ||||
| #!/bin/bash | ||||
| # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 | ||||
| source "$(dirname "$0")/lib/ulib/ulib" || exit 1 | ||||
| urequire DEFAULTS | ||||
| urequire DEFAULTS multiconf | ||||
| 
 | ||||
| function display_help() { | ||||
|     uecho "$scriptname: classer des fichiers selon certains règles | ||||
| @ -37,6 +37,7 @@ forme pattern:destdir[:renamef] | ||||
| 
 | ||||
| USAGE | ||||
|     $scriptname [options] <files...> | ||||
|     $scriptname [options] -r <files|dirs...> | ||||
| 
 | ||||
| OPTIONS | ||||
|     -c, --config CONFIG | ||||
| @ -56,6 +57,9 @@ OPTIONS | ||||
|         Toujours utiliser scp pour une copie distante. Par défaut s'il est | ||||
|         déterminé que l'hôte distant est en réalité l'hôte courant, alors la | ||||
|         copie est effectuée directement. | ||||
|     -r, --recursive | ||||
|         Classer récursivement tous les fichiers d'un répertoire. Sans cette | ||||
|         option, il n'est pas autorisé de fournir un répertoire comme argument. | ||||
|     -n, --fake | ||||
|         Afficher les opérations qui seraient faites | ||||
|     -l, --list | ||||
| @ -116,6 +120,7 @@ args=(% | ||||
|     --force-cp force_cp=1 | ||||
|     -S:,--ssh: SSH= | ||||
|     --force-scp force_scp=1 | ||||
|     -r,--recursive recursive=1 | ||||
|     -n,--fake fake=1 | ||||
|     -l,--list action=list | ||||
|     -e,--edit action=edit | ||||
| @ -126,8 +131,7 @@ parse_args "$@"; set -- "${args[@]}" | ||||
| 
 | ||||
| ## charger toutes les règles | ||||
| 
 | ||||
| RULES=() | ||||
| INCLUDES=() | ||||
| conf_init -a RULES | ||||
| if [ -n "$config" ]; then | ||||
|     if [ "$action" != edit ]; then | ||||
|         # le fichier doit exister, sauf en mode édition où il sera créé s'il | ||||
| @ -140,22 +144,11 @@ if [ -n "$config" ]; then | ||||
| else | ||||
|     set_defaults ufile | ||||
| fi | ||||
| array_copy rules RULES | ||||
| for include in "${INCLUDES[@]}"; do | ||||
|     if [ -f "$include" ]; then | ||||
|         RULES=() | ||||
|         source "$include" | ||||
|         array_extend rules RULES | ||||
|     else | ||||
|         ewarn "$include: fichier introuvable" | ||||
|     fi | ||||
| done | ||||
| array_copy RULES rules | ||||
| conf_load "$HOME/etc/ufile.d/*.conf" | ||||
| 
 | ||||
| ## actions particulières | ||||
| 
 | ||||
| if [ "$action" == list ]; then | ||||
|     echo "# $(echo_seta2 INCLUDES)" | ||||
|     array_to_lines RULES | ||||
|     exit 0 | ||||
| elif [ "$action" == edit ]; then | ||||
| @ -180,7 +173,7 @@ else | ||||
| fi | ||||
| 
 | ||||
| [ $# -gt 0 ] || die "Vous devez spécifier des fichiers à classer" | ||||
| [ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile" | ||||
| [ ${#RULES[*]} -gt 0 ] || die "Vous devez spécifier des règles pour le classement des fichiers dans ~/etc/default/ufile ou ~/etc/ufile.d/*.conf" | ||||
| 
 | ||||
| # vérifier les règles | ||||
| for rule in "${RULES[@]}"; do | ||||
| @ -194,13 +187,28 @@ for rule in "${RULES[@]}"; do | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| # faire la liste des fichiers | ||||
| files=() | ||||
| for file in "$@"; do | ||||
|     if [ -d "$file" -a -n "$recursive" ]; then | ||||
|         setx file=abspath "$file" | ||||
|         array_from_lines rfiles "$(find "$file" -type f)" | ||||
|         array_extendu files rfiles | ||||
|     elif [ -f "$file" ]; then | ||||
|         setx file=abspath "$file" | ||||
|         array_addu files "$file" | ||||
|     elif [ -n "$fake" ]; then | ||||
|         : # on est en mode fake, pas grave si le fichier n'est pas trouvé | ||||
|     elif [ -d "$file" ]; then | ||||
|         eerror "$file: est un répertoire. essayez avec -r" | ||||
|     else | ||||
|         eerror "$file: fichier introuvable. il sera ignoré" | ||||
|     fi | ||||
| done | ||||
| 
 | ||||
| # faire le classement effectif | ||||
| r= | ||||
| for file in "$@"; do | ||||
|     [ -f "$file" -o -n "$fake" ] || { | ||||
|         eerror "$file: fichier introuvable. il sera ignoré" | ||||
|         continue | ||||
|     } | ||||
| for file in "${files[@]}"; do | ||||
|     setx pf=abspath "$file" | ||||
|     setx dir=dirname -- "$pf" | ||||
|     setx filename=basename -- "$pf" | ||||
|  | ||||
							
								
								
									
										84
									
								
								uscrontab
									
									
									
									
									
								
							
							
						
						
									
										84
									
								
								uscrontab
									
									
									
									
									
								
							| @ -234,6 +234,9 @@ OPTIONS | ||||
|             $USCRONTAB_USERFILE | ||||
|         et chacun des fichiers du répertoire | ||||
|             $USCRONTAB_USERDIR | ||||
|     -N, --nop | ||||
|         Ne pas examiner la planification. Traiter uniquement l'option --osvar le | ||||
|         cas échéant. | ||||
|     -n, --fake | ||||
|         Afficher au lieu de les exécuter les commandes qui doivent être lancées | ||||
|     -P, --pause-for NBMINS | ||||
| @ -248,6 +251,9 @@ OPTIONS | ||||
|     -f, --force | ||||
|         Forcer l'exécution de la planification, même si elle a été mise en pause | ||||
|         avec l'option --pause | ||||
|     -v, --osvar NAME[=VALUE] | ||||
|         Définir une variable de type oneshot. Par défaut, VALUE vaut 1 si elle | ||||
|         n'est pas spécifiée. | ||||
| 
 | ||||
| OPTIONS AVANCEES | ||||
|     --lock LOCKFILE | ||||
| @ -286,6 +292,14 @@ OPTIONS AVANCEES | ||||
|         référence. Il faut respecter le format, sinon les résultats ne sont pas | ||||
|         garantis. Le mieux est de reprendre le résultat de l'option --show-ctnow | ||||
|         en le modifiant un peu si nécessaire. | ||||
|     -@, --hm H[:M] | ||||
|     -H, --h00 | ||||
|     -M, --h30 | ||||
|         Options pour simplifier l'utilisation de --force-ctnow. Supposons que | ||||
|         --show-ctnow affiche 'Y X day mon dow', alors: | ||||
|             -@ H:M  | est équivalent à  |  --force-ctnow 'M H day mon dow' | ||||
|             -H      |        ''         |  --force-ctnow '0 X day mon dow' | ||||
|             -M      |        ''         |  --force-ctnow '30 X day mon dow' | ||||
|     -G, --any-ctnow | ||||
|         Pour le développement ou des tests, lancer toutes les commandes dans | ||||
|         l'ordre sans tenir compte de l'heure de référence. Cette commande ne | ||||
| @ -345,8 +359,10 @@ lockfile=auto | ||||
| lockdelay= | ||||
| fake= | ||||
| continuous= | ||||
| force_ctnow= | ||||
| pause= | ||||
| force= | ||||
| osvars=() | ||||
| parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     --help '$exit_with display_help' \ | ||||
|     -A,--add,--install action=install \ | ||||
| @ -356,25 +372,50 @@ parse_opts "${PRETTYOPTS[@]}" \ | ||||
|     -a,--add action=add \ | ||||
|     -r,--remove action=remove \ | ||||
|     -l,--list action=list \ | ||||
|     -N,--nop action=nop \ | ||||
|     -n,--fake fake=1 \ | ||||
|     -P:,--pause-for: '$action=pause; set@ pause' \ | ||||
|     -p,--pause action=pause \ | ||||
|     -Y,--unpause action=unpause \ | ||||
|     -f,--force force=1 \ | ||||
|     -v:,--osvar: osvars \ | ||||
|     --lock: lockfile= \ | ||||
|     --lockdelay: lockdelay= \ | ||||
|     -c,--continuous continuous=1 \ | ||||
|     -k:,--stop: USCRONTAB_STOPEC= \ | ||||
|     --show-ctnow action=show-ctnow \ | ||||
|     --force-ctnow: __CTRESOLVE_CTNOW= \ | ||||
|     -@:,--hm: force_ctnow= \ | ||||
|     -H,--h00 force_ctnow=h00 \ | ||||
|     -M,--h30 force_ctnow=h30 \ | ||||
|     -G,--any-ctnow __CTRESOLVE_CTNOW="**ANY**" \ | ||||
|     @ args -- "$@" && set -- "${args[@]}" || die "$args" | ||||
| 
 | ||||
| uscrontab="$1"; shift | ||||
| 
 | ||||
| pausefile="$USCRONTAB_USERFILE.pauseuntil" | ||||
| now="$(awk 'BEGIN { print int(systime() / 60) * 60 }')" | ||||
| 
 | ||||
| # ne prendre le premier argument comme un fichier que s'il existe ou s'il n'est | ||||
| # pas de la forme *=* | ||||
| if [[ "$1" == *=* ]]; then | ||||
|     if [ -f "$1" ]; then | ||||
|         uscrontab="$1"; shift | ||||
|     fi | ||||
| else | ||||
|     uscrontab="$1"; shift | ||||
| fi | ||||
| 
 | ||||
| # écrire les variables oneshot | ||||
| for osvar in "${osvars[@]}"; do | ||||
|     if [[ "$osvar" == *=* ]]; then | ||||
|         splitvar "$osvar" name value | ||||
|     else | ||||
|         name="$osvar" | ||||
|         value=1 | ||||
|     fi | ||||
|     name="${name##*/}" # au cas où... | ||||
|     echo -n "$value" >"$USCRONTAB_USERFILE.$name.osvar" | ||||
| done | ||||
| 
 | ||||
| if [ "$action" == "pause" ]; then | ||||
|     [ -n "$pause" ] || pause=1440 | ||||
|     if [ "$pause" -lt 0 ]; then | ||||
| @ -436,10 +477,6 @@ 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 }')" | ||||
| @ -472,11 +509,18 @@ elif [ "$action" == "list" ]; then | ||||
|         etitle "$(ppath "$ctfile")" \ | ||||
|             cat "$ctfile" | ||||
|     done | ||||
| 
 | ||||
|     if check_pause "$pausefile" "$now"; then | ||||
|         ewarn "En pause. Réactiver avec $scriptname -Y" | ||||
|     fi | ||||
|     exit $r | ||||
| 
 | ||||
| elif [ "$action" == "show-ctnow" ]; then | ||||
|     ctnow "$now" | ||||
|     exit 0 | ||||
| 
 | ||||
| elif [ "$action" == "nop" ]; then | ||||
|     exit 0 | ||||
| fi | ||||
| 
 | ||||
| [ -z "$uscrontab" -o -f "$uscrontab" ] || die "$uscrontab: fichier introuvable" | ||||
| @ -569,7 +613,7 @@ elif [ "$action" == "run" ]; then | ||||
|         local cmd | ||||
|         cmd="${1%% *}" | ||||
|         case "$cmd" in | ||||
|         check_pidfile|remove_pidfile|elogto) return 1;; | ||||
|         check_pidfile|remove_pidfile|osvar|elogto) return 1;; | ||||
|         esac | ||||
|         return 0 | ||||
|     } | ||||
| @ -604,6 +648,21 @@ elif [ "$action" == "run" ]; then | ||||
|         die "$*" | ||||
|     } | ||||
| 
 | ||||
|     if [ -n "$force_ctnow" ]; then | ||||
|         ctnow=($(ctnow "$now")) | ||||
|         case "$force_ctnow" in | ||||
|         h00) ctnow[0]=0;; | ||||
|         h30) ctnow[0]=30;; | ||||
|         *) | ||||
|             force_ctnow="${force_ctnow//./:}" # autoriser H.M en plus de H:M | ||||
|             splitpair "$force_ctnow" h m | ||||
|             ctnow[0]="${m:-0}" | ||||
|             ctnow[1]="$h" | ||||
|             ;; | ||||
|         esac | ||||
|         __CTRESOLVE_CTNOW="${ctnow[*]}" | ||||
|     fi | ||||
| 
 | ||||
|     __ctscript="$(ctresolve <"$uscrontab")" | ||||
|     ec=0 | ||||
|     edebug "$__ctscript" | ||||
| @ -648,6 +707,17 @@ puis supprimez le cas échéant le fichier $pidfile" | ||||
|                 array_del __USCRONTAB_PIDFILES "$pidfile" | ||||
|             fi | ||||
|         } | ||||
|         function osvar() { | ||||
|             local __name __value | ||||
|             for __name in "$@"; do | ||||
|                 splitvar "$__name" __name __value | ||||
|                 if [ -f "$USCRONTAB_USERFILE.$__name.osvar" ]; then | ||||
|                     __value="$(<"$USCRONTAB_USERFILE.$__name.osvar")" | ||||
|                     rm "$USCRONTAB_USERFILE.$__name.osvar" | ||||
|                 fi | ||||
|                 _setv "$__name" "$__value" | ||||
|             done | ||||
|         } | ||||
| 
 | ||||
|         __ac_forgetall | ||||
|         # Si des variables sont spécifiées, les initialiser avant de lancer le | ||||
|  | ||||
							
								
								
									
										16
									
								
								uwatch
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								uwatch
									
									
									
									
									
								
							| @ -18,6 +18,10 @@ OPTIONS | ||||
|         Afficher un décompte depuis DURATION jusqu'à 0 puis terminer le script. | ||||
|         DURATION exprimé en secondes est le premier argument du script et vaut | ||||
|         par défaut ${DEFAULT_DURATION} soit $(($DEFAULT_DURATION / 60)) minutes. | ||||
|     -f, --wfile FILE | ||||
|         Arrêter dès que le fichier FILE n'existe plus | ||||
|     -p, --wpid PID | ||||
|         Arrêter dès que la processus PID n'existe plus | ||||
|     -u, --units | ||||
|         Avec l'option --count, afficher l'unité: sec., min. ou heures | ||||
|     -o, --offset NBSEC | ||||
| @ -42,6 +46,8 @@ DEFAULT_STEP=1 | ||||
| DEFAULT_DURATION=300 | ||||
| 
 | ||||
| what=time | ||||
| wfile= | ||||
| wpid= | ||||
| units= | ||||
| offset= | ||||
| step= | ||||
| @ -52,6 +58,8 @@ args=( | ||||
|     -t,--time what=time | ||||
|     -c,--count what=count | ||||
|     -r,--rcount what=rcount | ||||
|     -f:,--wfile: wfile= | ||||
|     -p:,--wpid: wpid= | ||||
|     -u,--units units=1 | ||||
|     -o:,--offset: offset= | ||||
|     -s:,--step: step= | ||||
| @ -112,5 +120,13 @@ while true; do | ||||
|         msg="$msg (jusqu'à $until)" | ||||
|     esac | ||||
|     echo -n $'\e[1G\e[K'"$prefix$msg$suffix" | ||||
|     if [ -n "$wfile" -a ! -f "$wfile" ]; then | ||||
|         echo | ||||
|         break | ||||
|     fi | ||||
|     if [ -n "$wpid" ] && ! kill -0 "$wpid" 2>/dev/null; then | ||||
|         echo | ||||
|         break | ||||
|     fi | ||||
|     sleep "$step" | ||||
| done | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user