# -*- 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