From ab4148c0acd9918585eb35aed3192fcbfec03a11 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Mon, 13 Mar 2017 15:39:17 +0400 Subject: [PATCH 01/12] cgilsxml.py: nouvelles options --first-spec et all-specs --- lib/ulib/support/cgilsxml.py | 59 +++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/lib/ulib/support/cgilsxml.py b/lib/ulib/support/cgilsxml.py index b74b567..2b90bd6 100755 --- a/lib/ulib/support/cgilsxml.py +++ b/lib/ulib/support/cgilsxml.py @@ -179,7 +179,7 @@ class File: else: self.vars[name] = value def __repr__(self): return 'File<%s>' % (self.pf) -def find_files(basedir, filters): +def find_files(basedir, filters, spec_method='all'): basedir = path.abspath(basedir) files = [] deep_filters = [filter for filter in filters if filter.re_spec is not None and filter.deep_scan] @@ -190,11 +190,21 @@ def find_files(basedir, filters): # exception se produit try: file = File(dirpath, filename) except: continue - matched = False - allowed = False + matched1 = matched = False + allowed1 = allowed = False for filter in deep_filters: - matched = filter.match_fill(file, basedir) or matched - allowed = filter.match_allow(file) or allowed + if spec_method == 'all' or \ + (spec_method == 'first' and not matched): + matched1 = filter.match_fill(file, basedir) + else: + matched1 = False + matched = matched1 or matched + if spec_method == 'all' or \ + (spec_method == 'first' and matched and not allowed): + allowed1 = filter.match_allow(file) + else: + allowed1 = False + allowed = allowed1 or allowed if matched: pass elif allowed: file.dontlist = True else: continue @@ -207,11 +217,21 @@ def find_files(basedir, filters): try: file = File(basedir, name) except: continue if not file.isfile(): continue - matched = False - allowed = False + matched1 = matched = False + allowed1 = allowed = False for filter in simple_filters: - matched = filter.match_fill(file) or matched - allowed = filter.match_allow(file) or allowed + if spec_method == 'all' or \ + (spec_method == 'first' and not matched): + matched1 = filter.match_fill(file, basedir) + else: + matched1 = False + matched = matched1 or matched + if spec_method == 'all' or \ + (spec_method == 'first' and matched and not allowed): + allowed1 = filter.match_allow(file) + else: + allowed1 = False + allowed = allowed1 or allowed if matched: pass elif allowed: file.dontlist = True else: continue @@ -411,6 +431,7 @@ def run_cgilsxml(): charset = 'utf-8' default_content = ContentInfos() default_filter = Filter(r'(.*)') + env = dict(filters=[], filter=None) def add_spec(option, opt, value, parser, *args, **kw): if env['filter'] is not None: env['filters'].append(env['filter']) env['filter'] = Filter(spec=value) @@ -420,16 +441,16 @@ def run_cgilsxml(): def allow_spec(option, opt, value, parser, *args, **kw): if env['filter'] is None: env['filter'] = default_filter env['filter'].allow_spec(value) - def add_var(option, opt_str, value, parser, *args, **kw): + def add_var(option, opt, value, parser, *args, **kw): if env['filter'] is None: env['filter'] = default_filter env['filter'].add_var(value) - def set_group(option, opt_str, value, parser, *args, **kw): + def set_group(option, opt, value, parser, *args, **kw): if env['filter'] is None: env['filter'] = default_filter env['filter'].set_group(value) - def set_break_on(option, opt_str, value, parser, *args, **kw): + def set_break_on(option, opt, value, parser, *args, **kw): if env['filter'] is None: env['filter'] = default_filter env['filter'].set_break_on(value) - def set_content_disposition(option, opt_str, value, parser, *args, **kw): + def set_content_disposition(option, opt, value, parser, *args, **kw): if value in ('attachment', 'inline'): pass elif value == 'none': value = None else: @@ -441,15 +462,16 @@ def run_cgilsxml(): sys.exit(1) if env['filter'] is None: default_content.disposition = value else: env['filter'].force_disposition = value - def set_content_type(option, opt_str, value, parser, *args, **kw): + def set_content_type(option, opt, value, parser, *args, **kw): if env['filter'] is None: default_content.type = value else: env['filter'].force_type = value - def set_content_charset(option, opt_str, value, parser, *args, **kw): + def set_content_charset(option, opt, value, parser, *args, **kw): if env['filter'] is None: default_content.charset = value else: env['filter'].force_charset = value from optparse import OptionParser OP = OptionParser(usage=u"\n\t%prog [options] /path/to/dir", description=__doc__) + OP.set_defaults(spec_method='all') OP.add_option('-e', '--spec', dest='spec', action='callback', callback=add_spec, type='string', help=u"Spécifier l'expression régulière permettant de sélectionner les fichiers à lister. " + u"La correspondance est tentée sur le nom du fichier avec la fonction match(). " @@ -460,6 +482,10 @@ def run_cgilsxml(): + u"\n Il est possible de spécifier cette option plusieurs fois." + u"\n Note: TOUTES les expressions régulières sont testées par rapport au nom du fichier, et pour celles qui correspondent, les variables correspondantes sont définies. " + u"Il faut donc ordonner les expressions régulières de la plus générale à la plus spécifique, contrairement à ce qui se fait d'habitude.") + OP.add_option('--all-specs', dest='spec_method', action='store_const', const='all', + help=u"Avec l'option -e, tester toutes les expressions régulières dans l'ordre de définition. C'est le comportement par défaut.") + OP.add_option('--first-spec', dest='spec_method', action='store_const', const='first', + help=u"Avec l'option -e, arrêter à la première expression régulière qui correspond") OP.add_option('--glob', dest='pattern', action='callback', callback=add_glob, type='string', help=u"Comme --spec, mais en utilisant les patterns du shell *, ?, [seq], [!seq]. " + u"Si l'expression contient un caractère '/', la correspondance se fait sur le chemin complet du fichier avec le module glob. " @@ -533,7 +559,6 @@ def run_cgilsxml(): + u"Il est possible de spécifier plusieurs paramètres en les séparant par des virgules.") OP.add_option('-p', '--prefix', dest="prefix", help=u"Ajouter les paramètres supplémentaires spécifiés à /result/env/query_string.") - env = dict(filters=[], filter=None) o, args = OP.parse_args() filters = env['filters'] filter = env['filter'] @@ -577,7 +602,7 @@ def run_cgilsxml(): files = [] for basedir in args: - files.extend(find_files(basedir, filters)) + files.extend(find_files(basedir, filters, o.spec_method)) sortfunc = build_sortfunc(sortby) files = sort_files(files, sortfunc) fgroups = build_fgroups(files) From 37a2dce795ea2a9c57a6cc7c2aa0e61afa4c2a67 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 17 Mar 2017 20:41:34 +0400 Subject: [PATCH 02/12] =?UTF-8?q?apacheconfig=20-K:=20support=20de=20plus?= =?UTF-8?q?=20de=20patterns=20pour=20le=20fichier=20mod=C3=A8le?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apacheconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apacheconfig b/apacheconfig index 4003776..3795e2a 100755 --- a/apacheconfig +++ b/apacheconfig @@ -254,13 +254,13 @@ elif [ "$action" == new-site ]; then ssltempl= certstempl= wwwtempl= - array_from_lines templs "$(list_files "$templdir" "*SITE.conf")" + array_from_lines templs "$(list_files "$templdir" "*SITE*.conf")" [ ${#templs[*]} -gt 0 ] && clrtempl="${templs[0]}" - array_from_lines templs "$(list_files "$templdir" "*SITE.ssl.conf")" + array_from_lines templs "$(list_files "$templdir" "*SITE*.ssl.conf")" [ ${#templs[*]} -gt 0 ] && ssltempl="${templs[0]}" - array_from_lines templs "$(list_files "$templdir" "*SITE-certs.conf")" + array_from_lines templs "$(list_files "$templdir" "*SITE*-certs.conf")" [ ${#templs[*]} -gt 0 ] && certstempl="${templs[0]}" - array_from_lines templs "$(list_dirs "$templdir" "*SITE")" + array_from_lines templs "$(list_dirs "$templdir" "*SITE*")" [ ${#templs[*]} -gt 0 ] && wwwtempl="${templs[0]}" found= From 999fb7f78dcaa44f83bb2b00772163f04baf1d62 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Thu, 23 Mar 2017 12:15:27 +0400 Subject: [PATCH 03/12] bug --- apacheconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apacheconfig b/apacheconfig index 3795e2a..c55540b 100755 --- a/apacheconfig +++ b/apacheconfig @@ -212,7 +212,7 @@ elif [ "$action" == deploy -o "$action" == localhosts ]; then eend elif [ "$action" == localhosts ]; then etitle "Mise à jour de /etc/hosts" - apacheconfig_deploy_localhosts "$destdir" "$aac_certsdir" "$onesite" || die + apacheconfig_localhosts "$destdir" "$aac_certsdir" "$onesite" || die eend fi From f908e1ce1def999bbfc2cca435973b16c886dd79 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 24 Mar 2017 09:42:38 +0400 Subject: [PATCH 04/12] support de SITE_IP --- apacheconfig | 43 +++++++++++++++++++++++++++++++++++++++- lib/default/apacheconfig | 9 +++++++++ lib/ulib/apache.tools | 3 +++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/apacheconfig b/apacheconfig index c55540b..7f3dd83 100755 --- a/apacheconfig +++ b/apacheconfig @@ -273,6 +273,44 @@ elif [ "$action" == new-site ]; then die "$host n'est pas un nom d'hôte pleinement qualifié" fi + hostip= + for i in "$clrtempl" "$ssltempl"; do + [ -n "$i" -a -f "$templdir/$i" ] || continue + quietgrep SITE_IP "$templdir/$i" && { hostip=1; break; } + done + if [ -n "$hostip" ]; then + # Il y a un champ SITE_IP, il faut demander à l'utilisateur l'adresse ip + # correspondante + [[ "$host" == *.* ]] && hostdomain="${host#*.}" || hostdomain= + pri= + hostip= + i=0 + while [ $i -lt ${#PUBDOMAINS[*]} ]; do + if [ "${PUBDOMAINS[$i]}" == "$hostdomain" ]; then + pri="$VSPREFIX${host%$hostdomain}${PRIDOMAINS[$i]}" + resolv_ips ips "$pri" + if [ -n "$ips" ]; then + hostip="${ips[0]}" + break + fi + fi + i=$(($i + 1)) + done + if [ -z "$hostip" ]; then + pri="$VSPREFIX$host" + resolv_ips ips "$pri" + [ -n "$ips" ] && hostip="${ips[0]}" + fi + if [ -n "$pri" -a -n "$hostip" ]; then + enote "Correspondance automatique $host --> $pri" + read_value "Veuillez confirmer l'adresse IP d'écoute" hostip "$hostip" N + else + enote "Vous devez saisir l'adresse IP privée correspondant à $host" + read_value "Veuillez entrer l'adresse IP *privée* d'écoute" hostip "" N + fi + [ -n "$hostip" ] || ewarn "Vous avez choisi de ne pas spécifier d'adresse IP d'écoute. Il faudra corriger manuellement les fichiers générés" + fi + etitle "$host" hostname="${host%%.*}" clrconf="${clrtempl/SITE/$hostname}" @@ -283,7 +321,10 @@ elif [ "$action" == new-site ]; then mkdir -p "$destdir/certsconf" mkdir -p "$destdir/sites" - sedscript="\ + sedscript= + [ -n "$hostip" ] && sedscript="$sedscript +s/SITE_IP/$hostip/g" + sedscript="$sedscript s/SITE.TLD/$host/g s/SITE/$hostname/g" diff --git a/lib/default/apacheconfig b/lib/default/apacheconfig index 2007e83..c510e62 100644 --- a/lib/default/apacheconfig +++ b/lib/default/apacheconfig @@ -4,3 +4,12 @@ #DEFAULT_ADMIN=supervision-gdrsi@listes.univ-reunion.fr #DEFAULT_CERTSDIR=1507-renater #DEFAULT_CANAME=1507-DigiCertCA.crt + +# Valeurs des domaines publics et privés ainsi que préfixe pour les adresses de +# service. Chaque élément du tableau PUBDOMAINS doit avoir un correspondant dans +# le tableau PRIDOMAINS. +# Avec la configuration par défaut suivante, on considère que l'adresse +# privée correspondant à HOST.univ-reunion.fr est vs-HOST.univ.run +#PUBDOMAINS=(univ-reunion.fr) +#PRIDOMAINS=(univ.run) +#VSPREFIX=vs- diff --git a/lib/ulib/apache.tools b/lib/ulib/apache.tools index 792b039..bc2ef65 100644 --- a/lib/ulib/apache.tools +++ b/lib/ulib/apache.tools @@ -884,6 +884,9 @@ function apacheconfig_initvars() { DEFAULT_ADMIN=supervision-gdrsi@listes.univ-reunion.fr DEFAULT_CERTSDIR=1507-renater DEFAULT_CANAME=1507-DigiCertCA.crt + PUBDOMAINS=(univ-reunion.fr) + PRIDOMAINS=(univ.run) + VSPREFIX=vs- set_defaults apacheconfig TEMPLATE_NOWRITE_VARS=("${APACHECONFIG_TEMPLATE_NOWRITE_VARS[@]}") From f233ae1bca7cbb9da6d8ba9a129431b2bff6d97f Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 24 Mar 2017 15:06:40 +0400 Subject: [PATCH 05/12] support de l'option -p pour traiter les ligne de la forme #*ip:IP --- apacheconfig | 10 +++++++++- lib/ulib/apache.tools | 14 ++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apacheconfig b/apacheconfig index 7f3dd83..616d647 100755 --- a/apacheconfig +++ b/apacheconfig @@ -59,6 +59,11 @@ OPTIONS Lors du déploiement de la configuration, les valeurs des variables dynamiques sont remplacées dans les fichiers destination. Les arguments qui restent sont passés tels quels à apache_autoconf + -p, --fix-ip + Corriger les lignes de la forme '#*ip:IP' et les + remplacer par '' + Cela permet de déployer une version de production des fichiers de + configuration. -N, --network-config Mettre aussi à jour la configuration réseau. -r, --certsdir CERTSDIR @@ -101,6 +106,7 @@ destdir= nohideconfig=auto templateopt= FULLCONF= +fixip= netconf= aac_certsdir= bits= @@ -133,6 +139,7 @@ args=( -8,--jessie '$array_add TEMPLATECTL_VARS sysver=jessie' --bits: bits= -u,--update,--deploy action=deploy + -p,--fix-ip fixip=1 -N,--network-config netconf=1 -r:,--certsdir: aac_certsdir= --localhosts action=localhosts @@ -188,6 +195,7 @@ elif [ "$action" == deploy -o "$action" == localhosts ]; then args=( -d "$destdir" --$action + ${fixip:+--fix-ip} ${netconf:+--network-config} ${aac_certsdir:+-r "$aac_certsdir"} ${oneconf:+--one-conf "$oneconf"} @@ -208,7 +216,7 @@ elif [ "$action" == deploy -o "$action" == localhosts ]; then "$destdir" "$aac_certsdir" \ "$config" "$oneconf" "$onemodule" "$onesite" \ "$custom_sysinfos" "$sysname" "$sysdist" "$sysver" "$bits" \ - "$netconf" || die + "$netconf" "$fixip" || die eend elif [ "$action" == localhosts ]; then etitle "Mise à jour de /etc/hosts" diff --git a/lib/ulib/apache.tools b/lib/ulib/apache.tools index bc2ef65..68bdbdd 100644 --- a/lib/ulib/apache.tools +++ b/lib/ulib/apache.tools @@ -325,6 +325,7 @@ function apache_autoconf() { local sitesdir onesite cgibindir wwwdir certsconfdir rrdir onecms local sysname sysdist sysver bits local netconf destconfsdir a2xconf + local fixip local restart=1 parse_opts "${PRETTYOPTS[@]}" \ --help '$exit_with __display_apache_autoconf_help' \ @@ -349,6 +350,7 @@ function apache_autoconf() { -8,--jessie sysver=jessie \ --bits: bits= \ --network-config netconf=1 \ + --fix-ip fixip=1 \ @ args -- "$@" && set -- "${args[@]}" || die "$args" if [ -n "$sysname" -o -n "$sysdist" -o -n "$sysver" ]; then @@ -400,6 +402,10 @@ function apache_autoconf() { # valeur dans les fichiers local -a FILLVARS; local FILLSCRIPT FILLTEMP __apache_autoconf_fillxxx "$@" + if [ -n "$fixip" ]; then + FILLSCRIPT="$FILLSCRIPT +"'s/#\*ip:\(.*\)$//' + fi # Installation des packages système if [ -f "$confdir/syspkgs.conf" ]; then @@ -954,7 +960,7 @@ function apacheconfig_deploy() { local destdir="$1" certsdir="$2"; shift; shift local config="$1" oneconf="$2" onemodule="$3"; onesite="$4"; shift; shift; shift; shift local custom_sysinfos="$1" sysname="$2" sysdist="$3" sysver="$4" bits="$5"; shift; shift; shift; shift; shift - local netconf="$1"; shift + local netconf="$1" fixip="$2"; shift; shift local -a args args=(--ignore "$(basename -- "$config")") @@ -963,6 +969,7 @@ function apacheconfig_deploy() { [ -n "$onesite" ] && array_add args --one-site "$(basename -- "$onesite")" [ -n "$custom_sysinfos" ] && array_add args --sysname "$sysname" --sysdist "$sysdist" --sysver "$sysver" --bits "$bits" [ -n "$netconf" ] && array_add args --network-config + [ -n "$fixip" ] && array_add args --fix-ip array_add args "$destdir" "$certsdir" for __name in "${TEMPLATE_DYNAMIC_VARS[@]}"; do array_add args "$__name=${!__name}" @@ -973,8 +980,7 @@ function apacheconfig_deploy() { function apacheconfig_qs() { # fonction pour simplifier l'utilisation de apacheconfig_deploy pour un # répertoire spécifique - # $1=destdir $2=certsdir $3=netconf - local destdir="$1" certsdir="$2" netconf="$3" + # $1=destdir $2=certsdir $3=netconf $4=fixip local config modified destdir autocreate apacheconfig_initvars apacheconfig_loadconf "$1" @@ -982,7 +988,7 @@ function apacheconfig_qs() { "$destdir" "$2" \ "$config" "" "" "" \ "" "" "" "" "" \ - "$3" + "$3" "$4" } function apacheconfig_localhosts() { From a2480ec2694c52b2b9d6e0c689c73ba2d8a62683 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 24 Mar 2017 17:14:11 +0400 Subject: [PATCH 06/12] apacheconfig: *.conf matche aussi *.ssl.conf et *-certs.conf --- apacheconfig | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/apacheconfig b/apacheconfig index 616d647..bd3be56 100755 --- a/apacheconfig +++ b/apacheconfig @@ -262,14 +262,17 @@ elif [ "$action" == new-site ]; then ssltempl= certstempl= wwwtempl= - array_from_lines templs "$(list_files "$templdir" "*SITE*.conf")" - [ ${#templs[*]} -gt 0 ] && clrtempl="${templs[0]}" - array_from_lines templs "$(list_files "$templdir" "*SITE*.ssl.conf")" - [ ${#templs[*]} -gt 0 ] && ssltempl="${templs[0]}" - array_from_lines templs "$(list_files "$templdir" "*SITE*-certs.conf")" - [ ${#templs[*]} -gt 0 ] && certstempl="${templs[0]}" - array_from_lines templs "$(list_dirs "$templdir" "*SITE*")" - [ ${#templs[*]} -gt 0 ] && wwwtempl="${templs[0]}" + array_from_lines clrtempls "$(list_files "$templdir" "*SITE*.conf")" + array_from_lines ssltempls "$(list_files "$templdir" "*SITE*.ssl.conf")" + array_from_lines certstempls "$(list_files "$templdir" "*SITE*-certs.conf")" + for xtempl in "${ssltempls[@]}" "${certstempls[@]}"; do + array_del clrtempls "$xtempl" + done + [ ${#clrtempls[*]} -gt 0 ] && clrtempl="${clrtempls[0]}" + [ ${#ssltempls[*]} -gt 0 ] && ssltempl="${ssltempls[0]}" + [ ${#certstempls[*]} -gt 0 ] && certstempl="${certstempls[0]}" + array_from_lines wwwtempls "$(list_dirs "$templdir" "*SITE*")" + [ ${#wwwtempls[*]} -gt 0 ] && wwwtempl="${wwwtempls[0]}" found= for i in "$clrtempl" "$ssltempl" "$certstempl" "$wwwtempl"; do From 14c56673a16c843aab3e280319441d660659da35 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 24 Mar 2017 23:30:53 +0400 Subject: [PATCH 07/12] =?UTF-8?q?mssh:=20portage=20g=C3=A9n=C3=A9rique=20d?= =?UTF-8?q?e=20mfssh=20pour=20choisir=20l'ex=C3=A9cutable=20ssh=20en=20fon?= =?UTF-8?q?ction=20du=20r=C3=A9seau=20source=20et=20destination?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/completion.d/nutools | 2 +- lib/default/mssh | 22 +++++++ lib/profile.d/git-ssh.userconf | 4 ++ mssh | 107 +++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 lib/default/mssh create mode 100644 lib/profile.d/git-ssh.userconf create mode 100755 mssh diff --git a/lib/completion.d/nutools b/lib/completion.d/nutools index 527d07d..5cdc084 100644 --- a/lib/completion.d/nutools +++ b/lib/completion.d/nutools @@ -11,7 +11,7 @@ complete -F __nutools_host_completion -o default uinst ruinst runs rruns if __bash_completion_module_enabled ssh; then shopt -u hostcomplete - complete -F _ssh ussh cssh + complete -F _ssh ussh cssh mssh fi if __bash_completion_module_enabled umount; then diff --git a/lib/default/mssh b/lib/default/mssh new file mode 100644 index 0000000..84ca909 --- /dev/null +++ b/lib/default/mssh @@ -0,0 +1,22 @@ +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +# Réseaux +NETWORKS=( + ur # université de la réunion + ksct # ks.jclain.fr +) + +ur_INCLUDES=(10/8) +ur_EXCLUDES=(10.42/16) +ur_DOMAINS=(univ.run univ-reunion.fr) + +ksct_INCLUDES=(192.168.97/24) +ksct_EXCLUDES=() +ksct_DOMAINS=(ct) + +# Règles de la forme FROM:TO:SSH +RULES=( + :ksct:kssh + ur::ssh + :ur:fssh +) diff --git a/lib/profile.d/git-ssh.userconf b/lib/profile.d/git-ssh.userconf new file mode 100644 index 0000000..d887ff2 --- /dev/null +++ b/lib/profile.d/git-ssh.userconf @@ -0,0 +1,4 @@ +# -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 + +# Spécifier le client SSH à utiliser pour git +export GIT_SSH=mssh diff --git a/mssh b/mssh new file mode 100755 index 0000000..cd301e2 --- /dev/null +++ b/mssh @@ -0,0 +1,107 @@ +#!/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" +urequire DEFAULTS ipcalc + +if [ $# -eq 1 -a "$1" == "--help" ]; then + exit_with uecho "$scriptname: Faire une connexion ssh en utilisant l'exécutable approprié au réseau source et destination + +USAGE + $scriptname [user@]host" +fi + +# fonctions de support +function match_network() { + local ip="$1" network="$2" + local -a includes excludes domains + local spec + array_copy includes "${network}_INCLUDES" + array_copy excludes "${network}_EXCLUDES" + array_copy domains "${network}_DOMAINS" + + if ipcalc_checkip "$ip" >/dev/null; then + for spec in "${excludes[@]}"; do + if ipcalc_match "$ip" "$spec"; then + return 1 + fi + done + for spec in "${includes[@]}"; do + if ipcalc_match "$ip" "$spec"; then + return 0 + fi + done + else + for spec in "${domains[@]}"; do + [[ "$ip" == *."$spec" ]] && return 0 + done + fi + return 1 +} + +# paramètres de l'environnement +DO= +if [ "$1" == --debug ]; then + # Activer le mode DEBUG + shift + set_verbosity -D +elif [ "$1" == --trace ]; then + # Activer le mode DEBUG + shift + set_verbosity -D + TRACE=1 + DO=qvals +fi + +NETWORKS=() +RULES=() +set_defaults mssh + +# déterminer d'où l'on vient +from= +array_from_lines myips "$(ip addr | awk '$1 == "inet" { gsub(/\/.*/, "", $2); print $2 }')" +for network in "${NETWORKS[@]}"; do + for myip in "${myips[@]}"; do + if match_network "$myip" "$network"; then + from="$network" + break + fi + done + [ -n "$from" ] && break +done +edebug "FROM: ${from:-ANY} (${myips[*]})" + +# analyser la ligne de commande +vars="$("$scriptdir/ussh" --parse "$@")" || exit 1 + +[ -n "$TRACE" ] && echo "$vars" +eval "$vars" + +for userhost in "${hosts[@]}"; do + # déterminer où l'on veut aller + splituserhost "$userhost" user host + + to= + for network in "${NETWORKS[@]}"; do + if match_network "$host" "$network"; then + to="$network" + break + fi + done + edebug "TO: ${to:-ANY} ($host)" + + # Sélectionner la commande ssh à utiliser + found= + for rule in "${RULES[@]}"; do + splitfsep "$rule" : rfrom rule2 + splitfsep "$rule2" : rto rssh + if [ \( -z "$rfrom" -o "$from" == "$rfrom" \) -a \ + \( -z "$rto" -o "$to" == "$rto" \) ]; then + found=1 + $DO ${exec:+exec} "$rssh" "${options[@]}" "$userhost" "${args[@]}" + break + fi + done + if [ -z "$found" ]; then + $DO ${exec:+exec} "$ssh" "${options[@]}" "$userhost" "${args[@]}" + fi +done From 5061d4b6e400b17e53f6e846c206062939f51060 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Fri, 24 Mar 2017 23:41:00 +0400 Subject: [PATCH 08/12] =?UTF-8?q?bug=20dans=20les=20r=C3=A8gles=20par=20d?= =?UTF-8?q?=C3=A9faut=20de=20mssh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/default/mssh | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/default/mssh b/lib/default/mssh index 84ca909..79336fe 100644 --- a/lib/default/mssh +++ b/lib/default/mssh @@ -16,6 +16,7 @@ ksct_DOMAINS=(ct) # Règles de la forme FROM:TO:SSH RULES=( + ksct:ksct:ssh :ksct:kssh ur::ssh :ur:fssh From 42c6fa6218641b51ab7452fd4d964bcb459d161d Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sat, 25 Mar 2017 10:43:35 +0400 Subject: [PATCH 09/12] =?UTF-8?q?ne=20pas=20activer=20git-ssh.userconf=20p?= =?UTF-8?q?ar=20d=C3=A9faut?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/profile.d/git-ssh.userconf | 2 +- mssh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/profile.d/git-ssh.userconf b/lib/profile.d/git-ssh.userconf index d887ff2..62e2ca5 100644 --- a/lib/profile.d/git-ssh.userconf +++ b/lib/profile.d/git-ssh.userconf @@ -1,4 +1,4 @@ # -*- coding: utf-8 mode: sh -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8 # Spécifier le client SSH à utiliser pour git -export GIT_SSH=mssh +#export GIT_SSH=mssh diff --git a/mssh b/mssh index cd301e2..a69b3db 100755 --- a/mssh +++ b/mssh @@ -18,7 +18,7 @@ function match_network() { array_copy includes "${network}_INCLUDES" array_copy excludes "${network}_EXCLUDES" array_copy domains "${network}_DOMAINS" - + if ipcalc_checkip "$ip" >/dev/null; then for spec in "${excludes[@]}"; do if ipcalc_match "$ip" "$spec"; then From 2fb17f7402e993d2f61eddaadd5b9f782c4649a3 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Sun, 2 Apr 2017 19:09:51 +0400 Subject: [PATCH 10/12] =?UTF-8?q?impl=C3=A9menter=20dumpcsv=20--awk-map?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ulib/awk | 112 +++++++++++++++++++++++++++++++++++++++++++++----- lib/ulib/base | 6 +++ 2 files changed, 107 insertions(+), 11 deletions(-) diff --git a/lib/ulib/awk b/lib/ulib/awk index 5bbb596..c242e6b 100644 --- a/lib/ulib/awk +++ b/lib/ulib/awk @@ -1758,7 +1758,7 @@ function sortcsv() { LANG=C lsortcsv "$@"; } ################################################################################ __DUMPCSV_HELP="\ -Afficher les champs spécifiés pour traitement par le shell +Afficher les champs spécifiés pour traitement par le shell ou par awk -S, --skip-lines nblines Sauter nblines au début du flux @@ -1785,7 +1785,7 @@ Afficher les champs spécifiés pour traitement par le shell Spécifier le nom à utiliser pour afficher les en-têtes avec l'option -h -n, --name NAME - Spécifier le nom à utiliser pour les options -f, -a, -b + Spécifier le nom à utiliser pour les options -f, -a, -b, -w -f, --function Afficher les champs comme l'appel d'une fonction, e.g: dump value00 value01... @@ -1815,6 +1815,28 @@ Afficher les champs spécifiés pour traitement par le shell Le nom du tableau est fixé à 'values'. L'option -n permet de spécifier le nom de la fonction, qui vaut 'dump' par défaut. Avec -h le nom par défaut est 'dumph' +-w, --awk-map + Afficher les champs comme une fonction awk qui permet de rechercher une + valeur et d'afficher la valeur correspondante. L'option -n permet de + spécifier le nom de la fonction, qui vaut 'mapval' par défaut. +--wtype TYPE + Spécifier le type de fonction à générer avec l'option --awk-map. Le type par + défaut est 'value' + Avec le type 'value', la fonction générée est de la forme dump(inval). Cette + fonction prend en argument la valeur de la colonne spécifiée avec --wscol, + et si cette valeur est trouvée dans les données, retourner la valeur de la + colonne spécifiée avec --wrcol + Avec le type 'array', la fonction générée est de la forme dump(inval, outvs) + Cette fonction prend en argument la valeur de la colonne spécifiée avec + --wscol, et si cette valeur est trouvée dans les données, le tableau outvs + est rempli avec les donnée de la ligne correspondante. +--wscol SFIELD + Nom du champ qui est cherché par la fonction générée avec l'option --awk-map + La valeur par défaut est '1', c'est à dire le premier champ. +--wrcol RFIELD + Nom du champ dont la valeur est retournée par la fonction générée avec + l'option '--awk-map --wtype value' en cas de correspondance. + La valeur par défaut est '2', c'est à dire le deuxième champ. -v, --var Affiche les champ en initialisant des variables, e.g: names=(header0 header1) @@ -1838,6 +1860,7 @@ function ldumpcsv() { eval "$(utools_local)" local skip= parse_headers=1 keepf skipf show_headers local dump=function reset=1 name hname + local wtype wscol wrcol parse_opts "${PRETTYOPTS[@]}" \ -S:,--skip:,--skip-lines:,--skiplines: skip= \ -H,--parse-headers parse_headers=1 \ @@ -1852,6 +1875,10 @@ function ldumpcsv() { --reset reset=1 \ --no-reset reset= \ -b,--array-function dump=array-function \ + -w,--awk-map dump=awk-map \ + --wtype: wtype= \ + --wscol: wscol= \ + --wrcol: wrcol= \ -v,--var dump=var \ @ args -- "$@" && set -- "${args[@]}" || die "$args" @@ -1876,13 +1903,64 @@ function ldumpcsv() { case "$dump" in function|array-function) name=dump;; array) name=values;; + awk-map) name=mapval;; esac fi + case "${wtype:-value}" in + array|a) wtype=array;; + value|v) wtype=value;; + esac + [ -n "$wscol" ] || wscol=1 + [ -n "$wrcol" ] || wrcol=2 local -a fields fields=("$@") - awkcsv "${args[@]}" -v show_headers:int="$show_headers" -v hname="$hname" -v name="$name" -v dump="$dump" -v reset_values:int="$reset" -v fields[@] -e ' + awkcsv "${args[@]}" -v show_headers:int="$show_headers" \ + -v hname="$hname" -v name="$name" -v dump="$dump" \ + -v reset_values:int="$reset" -v fields[@] \ + -v wtype="$wtype" -v wscol="$wscol" -v wrcol="$wrcol" \ + -e ' +function init_fields() { + if (do_once("init_fields")) { + if (fields_count == 0) { + array_copy(fields, HEADERS) + fields_count = array_len(fields) + } + } +} +function before_awkmap(name, wtype) { + if (do_once("before_awkmap")) { + if (wtype == "value") { + print "function " name "(inval) {" + } else if (wtype == "array") { + print "function " name "(inval, outvs) {" + } + } +} +function awkmap(inval, outval, values, count, wtype, i) { + if (wtype == "value") { + print "if (inval == " qawk(inval) ") return " qawk(outval) + } else if (wtype == "array") { + print "if (inval == " qawk(inval) ") {" + print "delete outvs" + for (i = 1; i <= count; i++) { + print "outvs[" i "] = " qawk(values[i]) + } + print "return 1" + print "}" + } +} +function after_awkmap() { + if (do_once("after_awkmap")) { + if (wtype == "value") { + print "return \"\"" + } else if (wtype == "array") { + print "return 0" + } + print "}" + } +} function dump_values(name, values, dump) { if (dump == "function") { print qarr(values, name) @@ -1899,12 +1977,8 @@ function dump_values(name, values, dump) { } } } -function init_fields() { - if (do_once("init_fields")) { - if (fields_count == 0) { - array_copy(fields, HEADERS) - fields_count = array_len(fields) - } +function before_dump() { + if (do_once("before_dump")) { if (show_headers) { dump_values(hname, fields, dump == "var"? "array": dump) } @@ -1922,10 +1996,26 @@ function init_fields() { values[i] = get(fields[i]) i++ } - dump_values(name, values, dump) + + if (dump == "awk-map") { + before_awkmap(name, wtype) + if (wscol ~ /^[0-9]+$/) inval = geti(wscol) + else inval = get(wscol) + if (wrcol ~ /^[0-9]+$/) outval = geti(wrcol) + else outval = get(wrcol) + awkmap(inval, outval, values, fields_count, wtype) + } else { + before_dump() + dump_values(name, values, dump) + } } END { - init_fields() + if (dump == "awk-map") { + before_awkmap(name, wtype) + after_awkmap() + } else { + before_dump() + } }' -a '' } diff --git a/lib/ulib/base b/lib/ulib/base index 0c5c5c1..81b9878 100644 --- a/lib/ulib/base +++ b/lib/ulib/base @@ -1780,6 +1780,12 @@ function unquote_html(s) { gsub(/&/, "\\&", s) return s } +function qawk(s) { + gsub(/\\/, "\\\\", s) + gsub(/"/, "\\\"", s) + gsub(/\n/, "\\n", s) + return "\"" s "\"" +} function qval(s) {'" gsub(/'/, \"'\\\\''\", s) return \"'\" s \"'\" From a6160b308a723f0dbdcb711079d7d468f62ed840 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 4 Apr 2017 04:04:59 +0400 Subject: [PATCH 11/12] Init changelog & version 6.3.0 --- CHANGES.md | 14 ++++++++++++++ VERSION.txt | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 9151691..386e6c1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,17 @@ +## Version 6.3.0 du 04/04/2017-04:04 + +* `2fb17f7` implémenter dumpcsv --awk-map +* `42c6fa6` ne pas activer git-ssh.userconf par défaut +* `5061d4b` bug dans les règles par défaut de mssh +* `14c5667` mssh: portage générique de mfssh pour choisir l'exécutable ssh en fonction du réseau source et destination +* `a2480ec` apacheconfig: *.conf matche aussi *.ssl.conf et *-certs.conf +* `95aa12f` Intégration de la branche update-apacheconfig + * `f233ae1` support de l'option -p pour traiter les ligne de la forme #*ip:IP + * `f908e1c` support de SITE_IP +* `999fb7f` bug +* `37a2dce` apacheconfig -K: support de plus de patterns pour le fichier modèle +* `ab4148c` cgilsxml.py: nouvelles options --first-spec et all-specs + ## Version 6.2.0 du 13/03/2017-11:27 * `4a7b14b` ajouter un argument force à testupdated et testnewer diff --git a/VERSION.txt b/VERSION.txt index 6abaeb2..798e389 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -6.2.0 +6.3.0 From 396728a5d8590c6606ce9db888ad2c08d45cb3a4 Mon Sep 17 00:00:00 2001 From: Jephte Clain Date: Tue, 4 Apr 2017 04:05:32 +0400 Subject: [PATCH 12/12] maj ulib --- lib/ulib/.ulibver | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ulib/.ulibver b/lib/ulib/.ulibver index d1af94d..4081a1a 100644 --- a/lib/ulib/.ulibver +++ b/lib/ulib/.ulibver @@ -1 +1 @@ -014002000 +014003000