# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ##@inc[../../legacy/sysinc/base # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # base: fonctions et variables de base pour utilisation sous Linux. requière # l'utilisation de bash ##@provide sysinc/basevars # === Variables diverses === # répertoire temporaire export TMPDIR="${TMPDIR:-${TMP:-${TEMP:-/tmp}}}" # BASEHOST est le nom d'hote *sans* domaine export BASEHOST="${HOSTNAME%%.*}" # FQDNHOST est le nom d'hote avec le domaine if [ "$BASEHOST" != "$HOSTNAME" ]; then export FQDNHOST="$HOSTNAME" else export FQDNHOST="$HOSTNAME.$(dnsdomainname)" fi # emplacement du script courant scriptname="$(basename -- "$0")" scriptdir="$(cd "$(dirname -- "$0")"; pwd)" script="$scriptdir/$scriptname" # fonction pour charger automatiquement /etc/default/$name et ~/etc/default/$name function set_defaults() { local __f __s for __f in "$@"; do __s= if [ -r "/etc/default/$__f" ]; then source "/etc/default/$__f" __s=1 fi if [ -r "$HOME/etc/default/$__f" ]; then source "$HOME/etc/default/$__f" __s=1 fi if [ -z "$__s" ]; then # si pas de fichier dans ~/etc/default ni dans /etc/default, lire # $scriptdir/lib/default/$scriptname en dernier lieu if [ -r "$scriptdir/lib/default/$__f" ]; then source "$scriptdir/lib/default/$__f" fi fi done } # === diverses fonctions === function is_yes() { # retourner vrai si $1 est une valeur "oui" [ "$1" == "o" -o "$1" == "O" -o "$1" == "oui" -o "$1" == "OUI" ] && return 0 [ "$1" == "y" -o "$1" == "Y" -o "$1" == "yes" -o "$1" == "YES" ] && return 0 [ "$1" == "v" -o "$1" == "V" -o "$1" == "vrai" -o "$1" == "VRAI" ] && return 0 [ "$1" == "t" -o "$1" == "T" -o "$1" == "true" -o "$1" == "TRUE" ] && return 0 [ "$1" == "1" ] && return 0 return 1 } function is_no() { # retourner vrai si $1 est une valeur "non" [ "$1" == "n" -o "$1" == "N" -o "$1" == "non" -o "$1" == "NON" ] && return 0 [ "$1" == "no" -o "$1" == "NO" ] && return 0 [ "$1" == "f" -o "$1" == "F" -o "$1" == "faux" -o "$1" == "FAUX" ] && return 0 [ "$1" == "false" -o "$1" == "FALSE" ] && return 0 [ "$1" == "0" ] && return 0 return 1 } # retourner le premier caractère de la chaine $1 function first_char() { echo "${1:0:1}"; } # retourner le dernier caractère de la chaine $1 function last_char() { echo "${1:$((-1)):1}"; } # retourner tous les caractères de la chaine $1, excepté le dernier function first_chars() { echo "${1:0:$((${#1}-1))}"; } # retourner tous les caractères de la chaine $1, excepté le premier function last_chars() { echo "${1:1}"; } # Tester si le premier caractère de la chaine $1 est $2 function first_char_is() { test "${1:0:1}" = "$2"; } # Tester si le dernier caractère de la chaine $1 est $2 function last_char_is() { test "${1:$((-1)):1}" = "$2"; } # Tester si la chaine $1 commence par le wildcard $2 function beginswith() { eval 'test "${1#'"$(quote_arg "$2")"'}" != "$1"'; } # Tester si la chaine $1 se termine par le wildcard $2 function endswith() { eval 'test "${1%'"$(quote_arg "$2")"'}" != "$1"'; } # Dans la chaine $1, remplacer \ par \\, " par \" et $ par \$, et l'afficher function quote_arg() { local s s="${1//\\/\\\\}" s="${s//\"/\\\"}" s="${s//$/\\$}" echo "$s" ## ou: #echo "$1" | awk '{ gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); gsub(/\$/, "\\$"); print }' } # Dans une chaine lue sur stdin, remplacer \ par \\, " par \" et $ par \$ et # l'afficher function quote_string() { awk '{ gsub(/\\/, "\\\\"); gsub(/"/, "\\\""); gsub(/\$/, "\\$"); print }' ##ou: #quote_arg "`cat`" ## mais cet dernière version est très lente sur un gros fichier } # Dans la chaine $1, remplacer '%' par '%25', '+' par '%2B', '&' par '%26', '=' par '%3D', ' ' par '+' function quote_formvalue() { local s="$1" s="${s//\%/%25}" s="${s//+/%2B}" s="${s//&/%26}" s="${s//=/%3D}" s="${s// /+}" echo "$s" } # Afficher le nombre de lignes d'un fichier function get_nblines() { [ -f "$1" ] && sed -ne '$=' "$1" || echo 0 } # générer un fichier temporaire et retourner son nom function mktempf() { mktemp "${1:-"$TMPDIR/tmp.XXXXXX"}" } # générer un répertoire temporaire et retourner son nom function mktempd() { mktemp -d "${1:-"$TMPDIR/tmp.XXXXXX"}" } # Créer le répertoire correspondant à un fichier function mkdirof() { mkdir -p "$(dirname "$1")" } # dans la chaine $1, remplacer \ par \\ et " par \", et l'afficher. ceci est # utile pour quoter des valeur à insérer dans un script awk function quote_awk() { local s s="${1//\\\\/\\\\}" s="${s//\"/\\\"}" echo "$s" } # tester si gawk est disponible function require_gawk() { local OENC="$UTF8" if [ -n "$__legacy_awk__" ]; then ewarn "Cette fonction requière gnuawk" return 1 fi return 0 } # lancer awk en essayant d'émuler des fonctionnalités de gnuawk (comme l'option # -v et la fonction gensub (XXX à faire)) function uawk() { if [ -z "$__legacy_awk__" ]; then awk "$@" else # essayer d'émuler l'option -v local script='BEGIN {' local done= while [ -n "$1" ]; do case "$1" in --) shift done=1 ;; -v) shift local name=${1%%=*} local value=${1:$((${#name} + 1))} if [ "$value" == "" ]; then # valeur vide script="$script $name = \"\"" elif [ "${value//[0-9]*/}" == "" ]; then # valeur numérique script="$script $name = $value" else # valeur alphanumérique script="$script $name = \"$(quote_awk "$value")\"" fi ;; -*) #ewarn "option non reconnue: $1" ;; *) done=1 ;; esac [ -n "$done" ] && break shift done script="$script } $1" shift awk "$script" "$@" fi } # Retourner la commande permettant de donner à la variable ${!1} la valeur $2 function set_var_cmd() { echo "$1=\"$(quote_arg "$2")\""; } # donner à la variable ${!1} la valeur $2 function set_var() { eval "$1=\"$(quote_arg "$2")\""; } # donner à la variable ${!1} la valeur $2. on assume que les valeur sont déjà # quotées comme il faut function set_var_literal() { eval "$1=$2"; } # copier en gardant le maximum de propriétés function cp_a() { /bin/cp -a "$@"; } # copier récursivement, en suivant les liens symboliques function cp_R() { /bin/cp -pR "$@"; } # supprimer les fichiers dont on donne éventuellement la liste function rm_maybe() { local parse_opts=1 arg rm for arg in "$@"; do # chercher s'il y a un argument autre que des options if [ -n "$parse_opts" ]; then if [ "$arg" == "--" ]; then parse_opts= elif [[ "$arg" == "-*" ]]; then continue elif [ -n "$arg" ]; then rm=1 break fi elif [ -n "$arg" ]; then rm=1 break fi done [ -n "$rm" ] && /bin/rm "$@" } # lister les fichiers ou répertoires du répertoire $1, un par ligne function list_all() { # $1=un répertoire dont le contenu doit être listé # $2..@=un ensemble de patterns pour le listage local curdir="$(pwd)" local b="${1:-.}"; shift cd "$b" 2>/dev/null || return eval "/bin/ls -1d ${*:-*} 2>/dev/null" cd "$curdir" } # lister les fichiers du répertoire $1, un par ligne function list_files() { # $1=un répertoire dont le contenu doit être listé. # $2..@=un ensemble de patterns pour le listage local f local curdir="$(pwd)" local b="${1:-.}"; shift cd "$b" 2>/dev/null || return eval "/bin/ls -1d ${*:-*} 2>/dev/null" | while read f; do [ -f "$f" ] && echo "$f" done cd "$curdir" } # lister les répertoires du répertoire $1, un par ligne function list_dirs() { # $1=un répertoire dont le contenu doit être listé. # $2..@=un ensemble de patterns pour le listage local f local curdir="$(pwd)" local b="${1:-.}"; shift cd "$b" 2>/dev/null || return eval "/bin/ls -1d ${*:-*} 2>/dev/null" | while read f; do [ -d "$f" ] && echo "$f" done cd "$curdir" } # copier un fichier dans un répertoire, ou le contenu d'un répertoire dans un # autre répertoire, que le répertoire source soit un lien symbolique ou # non. Cette fonction existe parce que le comportement de "cp_a src dest" n'est # pas consistant selon les plateformes, surtout si src est un lien symbolique # sur un répertoire: parfois on copie le lien, parfois on copie le contenu du # répertoire, parfois on copie le répertoire... function cpdir() { # $1=src, $2=dest, $3=method (cp_a par défaut) local src="$1" dest="$2" method="${3:-cp_a}" if [ -d "$src" ]; then # si c'est un répertoire, traitement particulier # tout d'abord, s'assurer que la destination existe if [ ! -d "$dest" ]; then mkdir -p "$dest" fi # ensuite on fait la copie local prevdir="$(pwd)" dest="$(abspath "$dest")" # XXX abspath défini dans functions! cd "$src" if [ -n "$(/bin/ls -a1)" ]; then # copier les fichiers [ -n "$(/bin/ls -1)" ] && "$method" * "$dest" # ne pas oublier les fichiers cachés... local i for i in .*; do [ "$i" == "." -o "$i" == ".." ] && continue "$method" "$i" "$dest" done fi cd "$prevdir" else # sinon, on assume que c'est un fichier if [ -f "$dest" ]; then # copie du fichier avec remplacement "$method" "$src" "$dest" elif [ -d "$dest" ]; then # copie du fichier dans le répertoire "$method" "$src" "$dest" else # Copie du fichier avec le nom $dest mkdirof "$dest" "$method" "$src" "$dest" fi fi } # transformer les fins de ligne en LF function nl2lf() { if [ -n "$1" -a "$1" != "-" ]; then tr -d '\r' <"$1" >"$1.tmp.$$" && /bin/mv "$1.tmp.$$" "$1" [ -f "$1.tmp.$$" ] && /bin/rm -f "$1.tmp.$$" else tr -d '\r' fi } # transformer les fins de ligne en CRLF function _nl2crlf() { tr -d '\r' | awk '{print $0 "\r"}' } function nl2crlf() { if [ -n "$1" -a "$1" != "-" ]; then _nl2crlf <"$1" >"$1.tmp.$$" && /bin/mv "$1.tmp.$$" "$1" [ -f "$1.tmp.$$" ] && /bin/rm -f "$1.tmp.$$" else _nl2crlf fi } # tester la présence d'un pattern dans un fichier function quietgrep() { grep -q "$@"; } # tester si deux fichiers sont identiques function quietdiff() { diff -q "$@" >&/dev/null; } # tester si deux fichiers sont identiques/différents function testsame() { quietdiff "$@"; } function testdiff() { ! quietdiff "$@"; } # test si $2 n'existe pas ou si $1 est plus récent que $2 function testnewer() { test ! -e "$2" -o "$1" -nt "$2"; } # afficher tous les processus avec le maximum d'informations function ps_all() { ps -axww; } # tester l'existence d'un programme dans le PATH function progexists() { test -n "$1" -a -x "$(which "$1" 2>/dev/null)"; } # tester si on est root function is_root() { test `id -u` -eq 0; } # sourcer un fichier s'il existe function source_ifexists() { if [ -f "$1" ]; then source "$1" || die; fi; } # s'endormir pour une très petite période de temps function little_sleep { LC_NUMERIC=C sleep 0.1; } # tester si un programme dont on donne le PID tourne function is_running() { test -n "$(ps -o pid -p "$1" | grep -v PID)"; } # afficher des chemins "jolis" function ppath() { # Dans un chemin *absolu*, remplacer "$HOME" par "~" et "$(pwd)/" par "", # afin que le chemin soit plus facile à lire. Le répertoire courant est # spécifié par $2 ou $(pwd) si $2 est vide local path="$1" cwd="$2" # essayer de normaliser le chemin if [ -d "$path" ]; then path="$(cd "$path"; pwd)" elif [ -f "$path" ]; then path="$(cd "$(dirname "$path")"; pwd)/$(basename "$path")" else : # chemin inexistant, on espère que le chemin est bien formé fi if [ -z "$2" ]; then cwd="$(pwd)" fi [ "$path" = "$cwd" ] && path="." [ "$cwd" != "/" -a "$cwd" != "$HOME" ] && path="${path/#$cwd\//}" path="${path/#$HOME/~}" echo "$path" } # un équivalent de basename écris en bash. note: le cas $1=/ n'est pas traité correctement function bname() { local bn="${1%%/}" bn="${p##*/}" [ -n "$2" ] && bn="${p%%$2}" echo "$bn" } # un équivalent de dirname écris en bash function dname() { local dn="${1%%/}" case "$dn" in */*) dn="${dn%/*}" ;; *) dn="." ;; esac echo "$dn" } # sed qui modifie le fichier en place. pour compatibilité avec d'autres # plateformes (cf system_caps), cette version ne devrait être appelée que de # cette manière:: # sedi "script" [files...] # toute autre utilisation fonctionnerait sur Linux mais pas sur MacOS X ou SunOS function sedi() { sed -i "$@" } # run_as: fonction pour relancer le script courant afin qu'il tourne avec les # droits d'un autre user (typiquement root). Attention! cette fonction ne teste # pas avec si on est déjà ce user. Il y a donc un risque de boucle infinie si on # ne teste pas le user courant. function run_as() { # Lancer cette fonction avec les arguments du script en cours. Par exemple:: # run_as root "$@" # Si $2=--noexec, on n'utilise pas la fonction exec, ce qui fait que la # fonction retourne. Sinon, on peut considérer que cette fonction ne # retourne jamais local OENC="$UTF8" local user="${1:-root}"; shift local exec_maybe=exec if [ "$1" = "--noexec" ]; then exec_maybe= shift fi # on peut spécifer localement le niveau de verbosité local VERBOSITY="$VERBOSITY" INTERACTION="$INTERACTION" set_verbosity "$1" && shift estep "Lancement du script sur $HOSTNAME en tant que $user" if is_yes "$UTOOLS_USES_SU" || ! progexists sudo; then einfo "Entrez le mot de passe de root" $exec_maybe su "$user" -c "${BASH:-/bin/sh} \"$0\" $*" else einfo "Entrez le mot de passe de $USER (si nécessaire)" if [ "$user" == "root" ]; then $exec_maybe sudo "${BASH:-/bin/sh}" "$0" "$@" else local args="$*" args="${args//|/\\|}" args="${args///\\>}" args="${args//;/\\;}" $exec_maybe sudo su "$user" -c "${BASH:-/bin/sh} \"$0\" $args" fi fi } # run_as_root: fonction pour relancer le script courant afin qu'il tourne en # root. Attention! cette fonction ne teste pas avec is_root si on est déjà en # root ou non. Ne pas appeler cette fonction si is_root est vrai, on risque une # boucle infinie. function run_as_root() { run_as root "$@" } # === fonctions pour contrôler l'encoding en sortie et en entrée === LATIN1=iso-8859-1 LATIN9=iso-8859-15 UTF8=utf-8 if ! progexists iconv; then function iconv() { cat; } fi function __lang_encoding() { local lang="$(<<<"$LANG" awk '{ print tolower($0) }')" case "$lang" in fr_fr@euro) echo "iso-8859-15";; fr_fr) echo "iso-8859-1";; *.utf-8) echo "utf-8";; *) ;; esac } function __norm_encoding() { awk '{ enc = tolower($0) gsub(/^latin$/, "latin1", enc) gsub(/^latin1$/, "iso-8859-1", enc) gsub(/^latin9$/, "iso-8859-15", enc) gsub(/[-_]/, "", enc) if (enc == "iso8859" || enc == "iso88591" || enc == "8859" || enc == "88591") print "iso-8859-1" else if (enc == "iso885915" || enc == "885915") print "iso-8859-15" else if (enc == "utf8") print "utf-8" else print $0 }' <<<"$1" } function __init_encoding() { local DEFAULT_ENCODING="$(__lang_encoding)" [ -n "$DEFAULT_ENCODING" ] || DEFAULT_ENCODING=utf-8 [ -n "$UTOOLS_OUTPUT_ENCODING" ] || UTOOLS_OUTPUT_ENCODING="$DEFAULT_ENCODING" UTOOLS_OUTPUT_ENCODING="$(__norm_encoding "$UTOOLS_OUTPUT_ENCODING")" [ -n "$UTOOLS_INPUT_ENCODING" ] || UTOOLS_INPUT_ENCODING="$UTOOLS_OUTPUT_ENCODING" UTOOLS_INPUT_ENCODING="$(__norm_encoding "$UTOOLS_INPUT_ENCODING")" [ -n "$UTOOLS_EDITOR_ENCODING" ] || UTOOLS_EDITOR_ENCODING="$UTOOLS_INPUT_ENCODING" UTOOLS_EDITOR_ENCODING="$(__norm_encoding "$UTOOLS_EDITOR_ENCODING")" IENC="$UTOOLS_INPUT_ENCODING" OENC="$UTOOLS_OUTPUT_ENCODING" } __init_encoding function tooenc() { local src="$1" from="${2:-$OENC}" to="${3:-$UTOOLS_OUTPUT_ENCODING}" if [ "$from" == "$to" ]; then echo "$src" else iconv -f "$from" -t "$to" <<<"$src" fi } function uecho() { tooenc "$*"; } function tooenc_() { local src="$1" from="${2:-$OENC}" to="${3:-$UTOOLS_OUTPUT_ENCODING}" if [ "$from" == "$to" ]; then echo_ "$src" else echo_ "$src" | iconv -f "$from" -t "$to" fi } function uecho_() { tooenc_ "$*"; } function toienc() { local var_="$1" to_="${2:-$IENC}" from_="${3:-$UTOOLS_INPUT_ENCODING}" if [ "$from_" != "$to_" ]; then set_var "$var_" "$(iconv -f "$from_" -t "$to_" <<<"${!1}")" fi } function uread() { local var_ [ $# == 0 ] && set -- REPLY read "$@" for var_ in "$@"; do [ -z "$var_" -o "${var_:0:1}" == "-" ] && continue # ignorer les options toienc "$var_" done } function stooenc() { local from="${1:-$OENC}" to="${2:-$UTOOLS_OUTPUT_ENCODING}" if [ "$from" == "$to" ]; then cat else iconv -f "$from" -t "$to" fi } function stoolatin1() { stooenc "iso-8859-1"; } function stoolatin9() { stooenc "iso-8859-15"; } function stooutf8() { stooenc "utf-8"; } function stoienc() { local to="${1:-$IENC}" from="${2:-$UTOOLS_INPUT_ENCODING}" if [ "$from" == "$to" ]; then cat else iconv -f "$from" -t "$to" fi } function stoilatin1() { stoienc "iso-8859-1"; } function stoilatin9() { stoienc "iso-8859-15"; } function stoiutf8() { stoienc "utf-8"; } # === fonctions pour contrôler l'affichage et l'interaction utilisateur === # ces fonctions n'affiche le message que si le niveau de "verbosité" est # suffisant: # 4=afficher les messages de debug; 3=afficher les message informatifs; # 2=afficher les warnings et les notes; 1=afficher les erreurs # 0=ne rien afficher # niveau de "verbosité". on commence par défaut à 3 MIN_VERBOSITY=0 DEF_VERBOSITY=3 MAX_VERBOSITY=4 export VERBOSITY="${VERBOSITY:-$DEF_VERBOSITY}" # niveau d'interaction. MIN_INTERACTION=0 DEF_INTERACTION=2 MAX_INTERACTION=3 export INTERACTION="${INTERACTION:-$DEF_INTERACTION}" function set_verbosity() { # Configurer le niveau de verbosité ou d'interaction en fonction de la # valeur de $1. Retourner 0 si l'argument a été utilisé, 1 sinon # $2 est la valeur d'un préfixe pour reconnaitre des options courtes # supplémentaires. Par défaut, les options suivantes sont reconnues: -c, -q, # -v, -Q, -D, ... Si le préfixe est -v par exemple, les options reconnues # seront -vc, -vq, -vv, -vQ, -vD, ... *en plus* de -c, -q, -v, -Q, -D, ... local retval=0 local enable_fake_arg= local prefix="-" if [ "$1" = "--enable-fake-arg" ]; then shift enable_fake_arg=1 fi [ -n "$2" ] && prefix="$2" case "$1" in # Ne changer, ni le niveau de verbosité, ni le niveau d'interaction, mais # seulement si --enable-fake-arg a été activé # Cette option permet à ask_yesno() et read_value() de spécifier les # messages qui doivent être affichés dans le niveau par défaut de # verbosité/interaction -c|"${prefix}c"|--default) [ -n "$enable_fake_arg" ] || retval=1 ;; # Configurer le niveau de verbosité en fonction de l'argument: -q le # diminue, -Q le met au minimum, -v l'augmente, -D le met au maximum -q|"${prefix}q"|--quiet) [ $VERBOSITY -gt $MIN_VERBOSITY ] && VERBOSITY=$(($VERBOSITY - 1)) ;; -v|"${prefix}v"|--verbose) [ $VERBOSITY -lt $MAX_VERBOSITY ] && VERBOSITY=$(($VERBOSITY + 1)) ;; -Q|"${prefix}Q"|--very-quiet) VERBOSITY=$MIN_VERBOSITY ;; -D|"${prefix}D"|--debug) VERBOSITY=$MAX_VERBOSITY ;; # Configurer le niveau d'interaction en fonction de l'argument: -b le met au # minimum, -y le diminue, -i l'augmente -b|"${prefix}b"|--batch) # niveau d'interaction minimum INTERACTION=$MIN_INTERACTION ;; -y|"${prefix}y"|--automatic) # Dimininuer le niveau d'interaction [ $INTERACTION -gt $MIN_INTERACTION ] && INTERACTION=$(($INTERACTION - 1)) ;; -i|"${prefix}i"|--interactive) # Augmenter le niveau d'interaction. Augmenter aussi le niveau de verbosité [ $INTERACTION -lt $MAX_INTERACTION ] && INTERACTION=$(($INTERACTION + 1)) ;; *) retval=1 ;; esac return $retval } function check_verbosity() { # Teste si le niveau de verbosité/interaction courant est suffisant pour une # opération dont le niveau est donné par $1 # Par exemple, 'check_verbosity -y' ne retourne vrai que si le niveau # d'interaction courant est supérieur ou égal à ($DEF_INTERACTION - 1). Cela # permet d'afficher un message ou d'effectuer une opération si on est au # moins en mode automatic (par contre, en mode batch, l'opération ne sera # pas effectué # De même 'check_verbosity -v' ne retourne vrai que si le niveau de # verbosité courant est supérieur ou égal à ($DEF_VERBOSITY+1). Cela permet # de n'afficher un message que si l'on est en mode verbose par exemple. # 'check_verbosity -c' retourne toujours vrai # Si $1 n'est pas un argument valide pour set_verbosity, alors on teste le # niveau de verbosité ou d'interaction par défaut. si $2!="", alors on teste # si le niveau de verbosité courant est supérieur à $2. Si $3!="", alors on # teste sur le niveau d'interaction est supérieur à $3 # Si le premier argument est --action, alors on affiche "shift", "return", # ou ":" suivant l'action à effectuer. Sinon, retourner 0 si le niveau est # correct (Si $2="" et $3="", l'argument a été interprété et il faut faire # un shift. Sinon l'argument a peut-être été interprété. On ne sait pas # alors, sauf si on spécifie --action, s'il faut faire un shift ou non), 1 # si le niveau n'est pas correct, mais l'argument $1 a été interprété (donc # il faut faire un shift) et 2 si l'argument n'est pas correct (n'a pas été # interprété) local verbosity="$VERBOSITY" interaction="$INTERACTION" local VERBOSITY="$DEF_VERBOSITY" INTERACTION="$DEF_INTERACTION" local action= if [ "$1" = "--action" ]; then shift action=1 fi if set_verbosity --enable-fake-arg "$1"; then shift if [ $interaction -ne $INTERACTION -a $interaction -ge $INTERACTION ] || [ $verbosity -ne $VERBOSITY -a $verbosity -ge $VERBOSITY ] || [ $interaction -eq $INTERACTION -a $verbosity -eq $VERBOSITY ]; then [ -n "$action" ] && echo shift return 0 else [ -n "$action" ] && echo return return 1 fi else if [ -n "$2" ] && [ "$verbosity" -gt "$2" ]; then [ -n "$action" ] && echo : return 0 # ce cas n'est pas équivalent à celui ci-dessus (pas de shift à faire!) elif [ -n "$3" ] && [ "$interaction" -gt "$3" ]; then [ -n "$action" ] && echo : return 0 # ce cas n'est pas équivalent à celui ci-dessus (pas de shift à faire!) else [ -n "$action" ] && echo return return 2 fi fi } function echo_() { echo -n "$*"; } # Couleurs tty -s <&1 && NO_COLORS= || NO_COLORS=1 function get_color() { [ -n "$NO_COLORS" ] && return [ -z "$*" ] && set RESET echo_ $'\e[' local sep while [ -n "$1" ]; do [ -n "$sep" ] && echo_ ";" case "$1" in z|RESET) echo_ "0";; o|BLACK) echo_ "30";; r|RED) echo_ "31";; g|GREEN) echo_ "32";; y|YELLOW) echo_ "33";; b|BLUE) echo_ "34";; m|MAGENTA) echo_ "35";; c|CYAN) echo_ "36";; w|WHITE) echo_ "37";; DEFAULT) echo_ "39";; O|BLACK_BG) echo_ "40";; R|RED_BG) echo_ "41";; G|GREEN_BG) echo_ "42";; Y|YELLOW_BG) echo_ "43";; B|BLUE_BG) echo_ "44";; M|MAGENTA_BG) echo_ "45";; C|CYAN_BG) echo_ "46";; W|WHITE_BG) echo_ "47";; DEFAULT_BG) echo_ "49";; @|BOLD) echo_ "1";; -|FAINT) echo_ "2";; _|UNDERLINED) echo_ "4";; ~|REVERSE) echo_ "7";; n|NORMAL) echo_ "22";; esac sep=1 shift done echo_ "m" } COULEUR_ROUGE="$(get_color RED BOLD)" COULEUR_VERTE="$(get_color GREEN BOLD)" COULEUR_JAUNE="$(get_color YELLOW BOLD)" COULEUR_BLEUE="$(get_color BLUE BOLD)" COULEUR_BLANCHE="$(get_color WHITE BOLD)" COULEUR_NORMALE="$(get_color RESET)" # tester le niveau de "verbosité" ou d'interaction function is_quiet() { [ $VERBOSITY -lt $DEF_VERBOSITY ]; } function is_verbose() { ! is_quiet; } function is_interactive() { [ $INTERACTION -ge $DEF_INTERACTION ]; } function is_automatic() { [ $INTERACTION -lt $DEF_INTERACTION ]; } function is_batch() { [ $INTERACTION -eq $MIN_INTERACTION ]; } # afficher une erreur *sur stderr* function display_error() { [ $VERBOSITY -gt 0 ]; } function eerror() { eval `check_verbosity --action "$1" 0` echo_ "${COULEUR_ROUGE}error:${COULEUR_NORMALE} " 1>&2 tooenc "$*" 1>&2 } # afficher un warning ou une note *sur stderr* function display_warning() { [ $VERBOSITY -gt 1 ]; } function ewarn() { eval `check_verbosity --action "$1" 1` echo_ "${COULEUR_JAUNE}warning:${COULEUR_NORMALE} " 1>&2 tooenc "$*" 1>&2 } function enote() { eval `check_verbosity --action "$1" 1` echo_ "${COULEUR_VERTE}note:${COULEUR_NORMALE} " 1>&2 tooenc "$*" 1>&2 } # afficher une information function display_info() { [ $VERBOSITY -gt 2 ]; } function etitle() { eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_BLANCHE}>>> " tooenc_ "$*" echo " <<<${COULEUR_NORMALE}" } function esubtitle() { eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_BLANCHE}*** " tooenc_ "$*" echo "${COULEUR_NORMALE}" } function eimportant() { eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_ROUGE}important:${COULEUR_NORMALE} " tooenc "$*" } function eattention() { eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_JAUNE}attention:${COULEUR_NORMALE} " tooenc "$*" } function ecomment() { eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_VERTE}commentaire:${COULEUR_NORMALE} " tooenc "$*" } function einfo() { eval `check_verbosity --action "$1" 2` tooenc "$*" } function einfon() { eval `check_verbosity --action "$1" 2` tooenc_ "$*" } # afficher un message de debug function is_debug() { [ $VERBOSITY -gt 3 ]; } function edebug() { eval `check_verbosity --action "$1" 3` echo_ "${COULEUR_BLANCHE}debug:${COULEUR_NORMALE} " tooenc "$*" } function edebugn() { eval `check_verbosity --action "$1" 3` echo_ "${COULEUR_BLANCHE}debug:${COULEUR_NORMALE} " tooenc_ "$*" } # Fonctions d'affichage pour suivre la progression d'opérations function estep() { # Une opération entière eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_BLANCHE}*${COULEUR_NORMALE} " tooenc "$*" } function estepn() { # Une opération entière eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_BLANCHE}*${COULEUR_NORMALE} " tooenc_ "$*" } function ebegin() { # Le début d'une opération eval `check_verbosity --action "$1" 2` echo_ "${COULEUR_BLANCHE}*${COULEUR_NORMALE} " tooenc_ "$*" echo_ ":" utools_ESTATUS_=0 utools_edot_first_=1 } function edot() { # Une étape d'une opération commencée par ebegin, matérialisée par un "." # Si l'argument est un fichier, utiliser -f pour que "$HOME" et "$(pwd)/" # soient remplacés respectivement par "~" et "" (afin que les chemins soient # plus courts) # Si l'argument est un commentaire, utiliser -m pour le spécifier. -w # indique que l'argument est un warning: un x jaune est affiché, avec le # message associé si on est en mode debug. # Sinon, l'argument est un status. 0 affiche un ".", sinon on affiche un "x" local status=$? local warn= color= if [ -n "$utools_edot_first_" ]; then # au premier dot, afficher un espace d'abord echo_ " " utools_edot_first_= fi eval `check_verbosity --action "$1" 2` if is_debug; then local msg paths path if [ "$1" = "-f" ]; then # chemins shift for path in "$@"; do paths="${paths:+$paths,}$(ppath "$path")" done msg="$paths" elif [ "$1" = "-m" -o "$1" = "-w" ]; then # message [ "$1" = "-w" ] && warn=1 # message de warning shift msg="$(tooenc "$*")" else # status [ -n "$1" ] && status="$1" fi [ "$utools_ESTATUS_" -eq 0 -a "$status" -ne 0 ] && utools_ESTATUS_="$status" if [ "$status" -eq 0 -a -z "$warn" ]; then echo_ "${msg:+ }.${msg:+($msg)}" else color="$COULEUR_ROUGE" [ -n "$warn" ] && color="$COULEUR_JAUNE" echo_ "${msg:+ }${color}x${COULEUR_NORMALE}${msg:+($msg)}" fi else if [ "$1" = "-f" -o "$1" = "-m" -o "$1" = "-w" ]; then [ "$1" = "-w" ] && warn=1 # message de warning shift else [ -n "$1" ] && status="$1" fi [ "$utools_ESTATUS_" -eq 0 -a "$status" -ne 0 ] && utools_ESTATUS_="$status" if [ "$status" -eq 0 -a -z "$warn" ]; then echo_ "." else color="$COULEUR_ROUGE" [ -n "$warn" ] && color="$COULEUR_JAUNE" echo_ "${color}x${COULEUR_NORMALE}" fi fi } function ewait() { # Une étape d'un opération commencée par ebegin, matérialisée par des "+" # qui s'affichent tant que le processus de PID $1 tourne # à utiliser de cette manière: # ebegin "lancement de cmd" # cmd & # ewait $! # eend local action status action="$(check_verbosity --action "$1" 2)" status=$? # le status de check_verbosity if [ "$action" == "return" ]; then # # ne rien afficher, mais attendre quand même que le processus s'arrête [ $status -eq 1 ] && shift local pid="$1" [ -n "$pid" ] && wait "$pid" return fi eval "$action" if [ -n "$utools_edot_first_" ]; then # au premier dot, afficher un espace d'abord echo_ " " utools_edot_first_= fi local pid="$1" local count=2 # attendre 2 secondes avant de commencer à afficher des "+" [ -z "$pid" ] && return little_sleep # certains processus retournent tout de suite while is_running "$pid"; do sleep 1 if [ $count -gt 0 ]; then count=$(($count - 1)) else echo_ "+" fi done echo_ "." # terminer par un "." } function eend() { # la fin d'une opération commencée par ebegin local status=0 eval `check_verbosity --action "$1" 2` [ -n "$1" ] && status="$1" [ "$utools_ESTATUS_" -eq 0 -a "$status" -ne 0 ] && utools_ESTATUS_="$status" if [ "$utools_ESTATUS_" -eq 0 ]; then echo " ${COULEUR_VERTE}ok${COULEUR_NORMALE}" else echo " ${COULEUR_ROUGE}error${COULEUR_NORMALE}" fi status=$utools_ESTATUS_ unset utools_ESTATUS_ return $status } # Arrêter le script avec un message d'erreur function die() { [ -n "$*" ] && eerror "$@"; exit 1; } # === Nom du système === export SYSTEM_NAME="`uname -s`" beginswith "$SYSTEM_NAME" CYGWIN && SYSTEM_NAME=Cygwin beginswith "$SYSTEM_NAME" MINGW32 && SYSTEM_NAME=Mingw export SYSTEM_MACHINE="`uname -m`" if [ "$SYSTEM_NAME" == "Linux" ]; then if [ -f /etc/debian_version ]; then LINUX_FLAVOUR=debian elif [ -f /etc/gentoo-release ]; then LINUX_FLAVOUR=gentoo elif [ -f /etc/redhat-release ]; then LINUX_FLAVOUR=redhat else LINUX_FLAVOUR= fi if [ "$SYSTEM_MACHINE" == "x86_64" ]; then SYSTEM_BITS=64 else SYSTEM_BITS=32 fi elif [ "$SYSTEM_NAME" == "Darwin" ]; then MACOSX_VERSION="$(grep -A 1 CFBundleShortVersionString /System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Resources/version.plist | grep string | sed 's/.*//g s/<\/string>.*$//g')" MACOSX_NAME=UNSUPPORTED if beginswith "$MACOSX_VERSION" 10.5; then MACOSX_NAME=LEOPARD elif beginswith "$MACOSX_VERSION" 10.4; then MACOSX_NAME=TIGER fi SYSTEM_BITS= fi # === vérifications === [ -d "$TMPDIR" ] || ewarn "TMPDIR ($TMPDIR) n'existe pas" ##@inc]../../legacy/sysinc/base __MAKE_SYSTEM_CAPS__="$(dirname "$0")/../../legacy/system_caps" ##@inc[../../legacy/sysinc/system_caps # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 ##@require base # system_caps: Déterminer les capacités du syteme sur lequel nous tournons. Ces # scripts sont prévus pour adapter un système non Linux pour qu'il fonctionne a # peu près comme Linux. Les fonctions de base qui doivent être adaptées le sont # en fonction du système sur lequel on tourne. Il suffit d'inclure ce fichier # pour bénéficier des nouvelles fonctionnalités # note: sous Linux, ces scripts sont essentiellement un no-op __SYSTEM_CAPS_COMPUTED__= if [ -z "$__MAKE_SYSTEM_CAPS__" -a -z "$__FORCE_COMPUTE_SYSTEM_CAPS__" -a -f "@@dest@@/legacy/system_caps" ]; then source "@@dest@@/legacy/system_caps" fi unset __FORCE_COMPUTE_SYSTEM_CAPS__ if [ -z "$__SYSTEM_CAPS_COMPUTED__" ]; then if [ -n "$__MAKE_SYSTEM_CAPS__" ]; then >"$__MAKE_SYSTEM_CAPS__" fi function __define_and_eval__() { if [ -n "$__MAKE_SYSTEM_CAPS__" ]; then echo "$1" >>"$__MAKE_SYSTEM_CAPS__" fi eval "$1" } function __verify_system__() { # Vérifier que le système est supporté local OENC="$UTF8" local system for system in Linux SunOS Darwin Cygwin Mingw unsupported; do [ "$system" = "$SYSTEM_NAME" ] && break [ "$system" = "unsupported" ] && die "$SYSTEM_NAME: Système non supporté" done } __verify_system__; unset -f __verify_system__ function __get_which_caps__() { [ "$SYSTEM_NAME" = "Linux" ] && return # Obtenir les capacités de which: certaines implémentations affichent "no x # in ..." sur stdout au lieu de l'afficher sur stderr local OENC="$UTF8" local tmpout="$TMPDIR/which_test.$$.out" local tmperr="$TMPDIR/which_test.$$.err" which __une_appli_qui_existe_pas__ >"$tmpout" 2>"$tmperr" if [ -s "$tmpout" ]; then __legacy_which__=1 # legacy elif [ -s "$tmperr" ]; then : # cas normal else __legacy_which__=2 # MacOSX 10.5 fi /bin/rm -f "$tmpout" /bin/rm -f "$tmperr" if [ "$__legacy_which__" == 1 ]; then local grep="${grep:-`which grep 2>&1`}" if [ -x "$grep" ]; then __define_and_eval__ 'function progexists() { test -n "$1" -a -z "$(which "$1" 2>&1 | '"$grep"' "^no $1")"; }' else die "grep est requis pour l'implémentation de progexists() sur ce système" fi elif [ "$__legacy_which__" == 2 ]; then __define_and_eval__ 'function progexists() { which "$1" >&/dev/null; }' fi } __get_which_caps__; unset -f __get_which_caps__ function __set_prog_func__() { # Tester la présence d'un programme sur le système en cours, et si # le programme doit être accedé avec un chemin absolu, créer une # fonction du nom de ce programme qui pourra être utilisée pour # appeler ce programme. # $1 == nom de la fonction a créer. Il s'agit géneralement du nom du # programme, mais ce n'est pas une obligation. # $2 == nom à afficher si le programme n'est pas trouvé. Le message # affiché sera de la forme "Ce script requière $2....". Si cette # valeur est non vide, le programme *doit exister* sinon le script # se termine. Si la valeur est "-", alors il s'agit de $1. # $3..$n == chemins dans lesquels il faut chercher le programme. Si # la valeur est "-", on teste si le programme est disponible dans le # path. local OENC="$UTF8" local prog="$1"; shift local req="$1"; shift if [ -z "$prog" ]; then die "USAGE: __set_prog_func__ prog_func req? path [paths...]" fi if [ -n "${!prog}" ]; then # Si une variable de ce nom est deja definie, on assume qu'il # s'agit du chemin vers le programme __define_and_eval__ 'function '"$prog"'() { '"${!prog}"' "$@"; }' return 0 fi local found= while [ -n "$1" ]; do local path="$1"; shift if [ "$path" = "--legacy" ]; then # Declarer que les programmes qui suivent sont "legacy" __define_and_eval__ 'export __legacy_'"$prog"'__=1' continue fi if [ "${path#/}" = "$path" ] && progexists "$path"; then # Si on donne un nom de programme, et que ce programme se # trouve dans le path, l'adopter avec son chemin absolu if [ "$path" != "$prog" ]; then path="$(type -p "$path")" __define_and_eval__ 'function '"$prog"'() { "'"$path"'" "$@"; }' fi found=1 break fi if [ "$path" = "-" ] && progexists "$prog"; then # pas la peine de creer une fonction, la commande existe # deja avec ce nom-la dans le path found=1 break fi if [ -d "$path" ]; then path="$path/$prog"; fi if [ -d "$path" ]; then continue; fi if [ -x "$path" ]; then __define_and_eval__ 'function '"$prog"'() { "'"$path"'" "$@"; }' found=1 break fi done if [ -z "$found" -a -n "$req" ]; then if [ "$req" = "-" ]; then req="$prog"; fi die "Ce script requière $req Si ce programme est installé, faites export $prog=/path/to/$prog et relancez ce script" fi test -n "$found" } function __get_tools_path_and_caps__() { [ "$SYSTEM_NAME" = "Linux" ] && return # Obtenir l'emplacement d'outils standards, tels que: # cp, awk, grep, diff, tar, ps, date local system # cp for system in SunOS Darwin; do [ "$SYSTEM_NAME" = "$system" ] && __define_and_eval__ 'export __legacy_cp__=1' done [ -n "$__legacy_cp__" ] && __define_and_eval__ 'function cp_a() { /bin/cp -pR "$@"; }' # awk if [ "$SYSTEM_NAME" = "SunOS" ]; then __set_prog_func__ awk "gawk or nawk" \ gawk \ /usr/sfw/bin/gawk \ /opt/sfw/bin/gawk \ --legacy nawk \ /usr/bin/nawk elif [ "$SYSTEM_NAME" = "Darwin" ]; then # note: gensub() n'est supporté que sur gnuawk # si __legacy_awk__ est défini, on sait que cette fonction n'est pas # disponible __set_prog_func__ awk "gawk or nawk" \ gawk \ /sw/bin/gawk \ /sw/bin/awk \ --legacy /usr/bin/awk fi # grep if [ "$SYSTEM_NAME" = "SunOS" ]; then __set_prog_func__ grep - \ ggrep \ /usr/sfw/bin/ggrep \ /opt/sfw/bin/ggrep \ --legacy /usr/bin/grep fi if [ -n "$__legacy_grep__" ]; then __define_and_eval__ 'function quietgrep() { grep "$@" >&/dev/null; }' fi # diff if [ "$SYSTEM_NAME" = "SunOS" ]; then __set_prog_func__ diff - \ gdiff \ /usr/sfw/bin/gdiff \ /opt/sfw/bin/gdiff \ --legacy /usr/bin/diff fi if [ -n "$__legacy_diff__" ]; then __define_and_eval__ 'function quietdiff() { diff "$@" >&/dev/null; }' fi # tar if [ "$SYSTEM_NAME" = "SunOS" ]; then __set_prog_func__ tar - \ gtar \ /usr/sfw/bin/gtar \ /opt/sfw/bin/gtar \ --legacy /usr/bin/tar elif [ "$SYSTEM_NAME" = "Darwin" ]; then __set_prog_func__ tar - \ gnutar gtar \ /sw/bin/gtar \ --legacy /usr/bin/tar fi # ps if [ "$SYSTEM_NAME" = "SunOS" ]; then __set_prog_func__ ps - \ /usr/ucb/ps \ --legacy /usr/bin/ps __set_prog_func__ legacyps - \ /usr/bin/ps __define_and_eval__ 'function is_running() { test -n "$(legacyps -o pid -p "$1" | grep -v PID)"; }' fi if [ -n "$__legacy_ps__" ]; then __define_and_eval__ 'function ps_all() { ps -ef; }' fi # sleep if [ "$SYSTEM_NAME" = "SunOS" -o "$SYSTEM_NAME" = "Darwin" ]; then __define_and_eval__ 'function little_sleep() { n=1000; while [ $n -gt 0 ]; do n=$(($n - 1)); done; }' fi # date if [ "$SYSTEM_NAME" = "SunOS" ]; then __set_prog_func__ date - \ gdate \ /usr/sfw/bin/gdate \ /opt/sfw/bin/gdate \ --legacy /usr/bin/date elif [ "$SYSTEM_NAME" = "Darwin" ]; then __set_prog_func__ date - \ --legacy /bin/date fi # readlink if ! progexists readlink; then __define_and_eval__ 'function readlink() { if [ -L "$1" ]; then /bin/ls -ld "$1" | awk '"'"'{print $11'"'"'}; fi; }' fi # mktemp if ! progexists mktemp; then __define_and_eval__ 'function mktemp() { make_tempfile "$@"; }' fi # curl/wget (pour dumpurl) if ! progexists curl; then if [ "$SYSTEM_NAME" = "SunOS" ]; then if __set_prog_func__ curl "" /usr/local/bin/curl; then __define_and_eval__ 'export __curl_EXISTS__=1' fi fi fi if ! progexists wget; then if [ "$SYSTEM_NAME" = "SunOS" ]; then if __set_prog_func__ wget "" /usr/sfw/bin/wget /opt/sfw/bin/wget; then __define_and_eval__ 'export __wget_EXISTS__=1' fi fi fi # is_root if [ "$SYSTEM_NAME" = "SunOS" ]; then __define_and_eval__ 'function is_root() { id | quietgrep "uid=0"; }' elif [ "$SYSTEM_NAME" = "Cygwin" -o "$SYSTEM_NAME" = "Mingw" ]; then # on assume que sur ces systèmes, l'utilisateur est maitre à bord. __define_and_eval__ 'function is_root() { true; }' fi # sedi if [ "$SYSTEM_NAME" = "Darwin" ]; then __define_and_eval__ 'function __1sedi() { local script="$1" input="$2" if sed -i.bak "$script" "$input"; then /bin/rm -f "$input.bak" fi } function sedi() { local script="$1" input shift for input in "$@"; do __1sedi "$script" "$input" done }' elif [ "$SYSTEM_NAME" = "SunOS" ]; then __define_and_eval__ 'function __1sedi() { local script="$1" input="$2" if sed "$script" "$input" >"$input.out.$$"; then chmod "$(/bin/ls -l "$input" | awk '\''function oct(mod) { value = 0 if (substr(mod, 1, 1) == "r") value = value + 4 if (substr(mod, 2, 1) == "w") value = value + 2 if (substr(mod, 3, 1) == "x") value = value + 1 return value } { print oct(substr($1, 2, 3)) oct(substr($1, 5, 3)) oct(substr($1, 8, 3)) }'\'')" "$input.out.$$" /bin/mv -f "$input.out.$$" "$input" fi } function sedi() { local script="$1" input shift for input in "$@"; do __1sedi "$script" "$input" done }' fi # parse_date if [ "$SYSTEM_NAME" = "Darwin" ]; then function __pd_isleap() { # tester si l'année $1 est bissextile [ $(($1 % 4)) -eq 0 -a \( $(($1 % 100)) -ne 0 -o $(($1 % 400)) -eq 0 \) ] } function __pd_fix_month() { # soit $1 le nom d'une variable contenant une année, et $2 le nom d'une # variable contenant un mois, normaliser les valeurs de ces variables, en # ajustant si nécessaire les valeurs. local __pdfm_y="${!1}" __pdfm_m="${!2}" let __pdfm_m=$__pdfm_m-1 while [ $__pdfm_m -gt 11 ]; do let __pdfm_m=$__pdfm_m-12 let __pdfm_y=$__pdfm_y+1 done while [ $__pdfm_m -lt 0 ]; do let __pdfm_m=$__pdfm_m+12 let __pdfm_y=$__pdfm_y-1 done let __pdfm_m=$__pdfm_m+1 eval "$1=$__pdfm_y; $2=$__pdfm_m" } __PD_MONTHDAYS=(0 31 28 31 30 31 30 31 31 30 31 30 31) function __pd_monthdays() { # calculer le nombre de jours du mois $2 de l'année $1 local y="$1" m="$2" mds __pd_fix_month y m mds="${__PD_MONTHDAYS[$m]}" [ "$m" -eq 2 ] && __pd_isleap "$y" && let mds=$mds+1 echo $mds } function __pd_fix_day() { # soit $1 le nom d'une variable contenant une année, $2 le nom d'une # variable contenant un mois et $3 le nom d'une variable contenant un jour, # normaliser les valeurs de ces variables, en ajustant si nécessaire les # valeurs. cette fonction assume que la valeur de $2 est déjà corrigée avec # __pd_fix_month local __pdfd_y="${!1}" __pdfd_m="${!2}" __pdfd_d="${!3}" __pdfd_mds let __pdfd_d=$__pdfd_d-1 let __pdfd_mds=$(__pd_monthdays $__pdfd_y $__pdfd_m) while [ $__pdfd_d -gt $(($__pdfd_mds-1)) ]; do let __pdfd_d=$__pdfd_d-$__pdfd_mds let __pdfd_m=$__pdfd_m+1 __pd_fix_month __pdfd_y __pdfd_m let __pdfd_mds=$(__pd_monthdays $__pdfd_y $__pdfd_m) done while [ $__pdfd_d -lt 0 ]; do let __pdfd_m=$__pdfd_m-1 __pd_fix_month __pdfd_y __pdfd_m let __pdfd_d=$__pdfd_d-$(__pd_monthdays $__pdfd_y $__pdfd_m) done let __pdfd_d=$__pdfd_d+1 eval "$1=$__pdfd_y; $2=$__pdfd_m; $3=$__pdfd_d" } function __pd_fix_date() { # soit $1 le nom d'une variable contenant une année, $2 le nom d'une # variable contenant un mois et $3 le nom d'une variable contenant un jour, # normaliser les valeurs de ces variables, en ajustant si nécessaire les # valeurs. local __pdf_y="${!1}" __pdf_m="${!2}" __pdf_d="${!3}" } function parse_date() { local value="$1" type="${2:-date}" local d m y # date courante eval "$(date +%d/%m/%Y | awk -F/ '{ print "d=" $1 "; m=" $2 "; y=" $3 }')" if [ "${value#+}" != "$value" ]; then # ajouter $1 jours d="$(($d+${value#+}))" else # parser une nouvelle date, en complétant avec les informations de la # date du jour eval "$(<<<"$value" awk -F/ "BEGIN { dn=$dn; mn=$mn; yn=$yn }"' { d = $1 + 0; if (d < 1) d = dn + 0; m = $2 + 0; if (m < 1) m = mn + 0; if ($3 == "") y = yn + 0; else { y = $3 + 0; if (y < 100) y = y + 2000; } print "d=" d "; m=" m "; y=" y }')" fi # ensuite corriger les champs si nécessaire __pd_fix_month y m __pd_fix_day y m d # enfin formater la date selon les volontés de l'utilisateur case "$type" in d|date) awk "BEGIN { d=$d; m=$m; y=$y; "'printf "%02i/%02i/%04i\n", d, m, y }' ;; l|ldap) awk "BEGIN { d=$d; m=$m; y=$y; "'printf "%04i%02i%02i000000+0400\n", y, m, d }' ;; esac } fi } __get_tools_path_and_caps__ unset -f __set_prog_func__ __get_tools_path_and_caps__ __define_and_eval__ "__SYSTEM_CAPS_COMPUTED__=1" unset -f __define_and_eval__ fi ##@inc]../../legacy/sysinc/system_caps