1554 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1554 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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 255
 | |
| urequire DEFAULTS ldif prefixes ldap
 | |
| 
 | |
| ################################################################################
 | |
| # Fonctions utilitaire
 | |
| 
 | |
| function split_cmds() {
 | |
|     # splitter la commande $2 sur l'un des caractères $3...$*, et mettre le
 | |
|     # résultat dans le tableau $1. Par défaut, splitter sur //
 | |
|     local __sc_dest="$1" __sc_cmds="$2"; shift 2
 | |
|     [ -n "$*" ] || set -- "//"
 | |
|     local -a __sc_seps=("$@")
 | |
|     local __sc_sep __sc_cmd __sc_arg __sc_foundsep __sc_addtocmd
 | |
| 
 | |
|     __sc_foundsep=
 | |
|     for __sc_sep in "${__sc_seps[@]}"; do
 | |
|         if [ "$__sc_cmds" == "$__sc_sep" -o "${__sc_cmds%$__sc_sep}" != "$__sc_cmds" ]; then
 | |
|             __sc_foundsep=1
 | |
|             break
 | |
|         fi
 | |
|     done
 | |
|     [ -n "$__sc_foundsep" ] || __sc_cmds="$__sc_cmds ${__sc_seps[0]}"
 | |
|     eval "set -- $__sc_cmds"
 | |
| 
 | |
|     array_new "$__sc_dest"
 | |
|     __sc_cmd= # commande actuelle
 | |
|     for __sc_arg in "$@"; do
 | |
|         __sc_addtocmd=1
 | |
|         __sc_foundsep=
 | |
|         for __sc_sep in "${__sc_seps[@]}"; do
 | |
|             if [ "$__sc_arg" == "$__sc_sep" ]; then
 | |
|                 __sc_addtocmd=
 | |
|                 __sc_foundsep=1
 | |
|                 break
 | |
|             elif [ "${__sc_arg%$__sc_sep}" != "$__sc_arg" ]; then
 | |
|                 __sc_arg="${__sc_arg%$__sc_sep}"
 | |
|                 __sc_foundsep=1
 | |
|                 break
 | |
|             fi
 | |
|         done
 | |
|         if [ -n "$__sc_addtocmd" ]; then
 | |
|             __sc_cmd="${__sc_cmd:+$__sc_cmd }$(quoted_arg "$__sc_arg")"
 | |
|             __sc_arg=
 | |
|         fi
 | |
|         if [ -n "$__sc_foundsep" ]; then
 | |
|             array_add "$__sc_dest" "$__sc_cmd"
 | |
|             __sc_cmd=
 | |
|         fi
 | |
|     done
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| # Variables
 | |
| 
 | |
| compute_ldap_prefixes
 | |
| 
 | |
| LDAPCONF="$(expand_prefix LDAPCONFDIR)/ldap.conf"
 | |
| VARIABLES=(WSMODE WSAPPEND
 | |
|     PROFILE LDAPURI SUFFIX BINDDN PASSWORD SEARCHBASE FILTER ATTRS
 | |
|     UNCUT_ON_LOAD CUT_ON_SAVE
 | |
|     DECODE_ON_LOAD ENCODE_ON_SAVE ENCODE_ATTRS
 | |
|     OUTPUT
 | |
|     EXIT_ON_ERROR EXITCODE LINES DEBUG)
 | |
| SPECIAL_VARIABLES=(PLAIN LDIF APPEND SEARCHBASE_EXACT)
 | |
| PROTECTED_VARIABLES=()
 | |
| 
 | |
| # valeurs par défaut
 | |
| WSMODE=ldif
 | |
| WSAPPEND=
 | |
| ATTRS=()
 | |
| UNCUT_ON_LOAD=true
 | |
| CUT_ON_SAVE=true
 | |
| DECODE_ON_LOAD=true
 | |
| ENCODE_ON_SAVE=true
 | |
| ENCODE_ATTRS=(userPassword)
 | |
| EXITCODE=0
 | |
| 
 | |
| AUTOPRINT=1
 | |
| INTERACTIVE=auto
 | |
| EXIT_ON_ERROR=auto
 | |
| SKIPCOUNT=
 | |
| LASTCMD=
 | |
| EDITLAST=
 | |
| 
 | |
| function eval_cmdline() {
 | |
|     # analyser la ligne $1. ce peut-être une commande ou une suite de commande
 | |
|     # séparés par //, qui forment un seul groupe.
 | |
|     local -a cmds
 | |
|     local origcmd
 | |
| 
 | |
|     local cmd="$1"
 | |
| 
 | |
|     # La commande en cours va peut-être modifier la valeur de DEBUG. En
 | |
|     # faire une sauvegarde avant
 | |
|     local __DEBUG="$DEBUG"
 | |
| 
 | |
|     if [ "${cmd#$}" != "$cmd" ]; then
 | |
|         # avec $, on exécute la commande littérale
 | |
|         is_yes "$__DEBUG" && set -x
 | |
|         if ! eval "${cmd#$}"; then
 | |
|             is_yes "$EXIT_ON_ERROR" && exit 255
 | |
|         fi
 | |
|         is_yes "$__DEBUG" && set +x
 | |
|         LASTCMD="$origcmd"
 | |
|         continue
 | |
|     fi
 | |
| 
 | |
|     # sinon, ce sont des commandes de uldap
 | |
|     origcmd="$cmd"
 | |
|     split_cmds cmds "$cmd" "//" # splitter les commandes sur //
 | |
|     for cmd in "${cmds[@]}"; do
 | |
|         if eval "set -- $cmd"; then
 | |
|             cmdalias "$1" cmd; shift
 | |
|             set -- "${cmd[@]}" "$@"
 | |
|             cmd="$1"; shift
 | |
|             if [ "$cmd" == "last" ]; then
 | |
|                 EDITLAST=1
 | |
|             else
 | |
|                 cmd="uldap_$cmd"
 | |
|                 is_yes "$__DEBUG" && set -x
 | |
|                 if ! "$cmd" "$@"; then
 | |
|                     is_yes "$EXIT_ON_ERROR" && exit 255
 | |
|                 fi
 | |
|                 is_yes "$__DEBUG" && set +x
 | |
|                 LASTCMD="$origcmd"
 | |
|             fi
 | |
|         else
 | |
|             eerror "$cmd: erreur de syntaxe"
 | |
|             is_yes "$EXIT_ON_ERROR" && exit 255
 | |
|         fi
 | |
|     done
 | |
| }
 | |
| 
 | |
| function set_values() {
 | |
|     local varcmd name uname lname value
 | |
|     local s=0
 | |
|     for varcmd in "$@"; do
 | |
|         if [[ "$varcmd" == *=* ]]; then
 | |
|             name="${varcmd%%=*}"
 | |
|             value="${varcmd#$name=}"
 | |
|         else
 | |
|             name="$varcmd"
 | |
|             value=
 | |
|         fi
 | |
|         uname="$(awk '{print toupper($0)}' <<<"$name")"
 | |
|         lname="$(awk '{print tolower($0)}' <<<"$name")"
 | |
| 
 | |
|         if array_contains VARIABLES "$uname" || array_contains SPECIAL_VARIABLES "$uname"; then
 | |
|             "set_$lname" "$value" || s=1
 | |
|         elif ! array_contains PROTECTED_VARIABLES "$name"; then
 | |
|             set_var "$name" "$value"
 | |
|         else
 | |
|             s=1
 | |
|         fi
 | |
|     done
 | |
|     return $s
 | |
| }
 | |
| 
 | |
| function set_exit_on_error() {
 | |
|     is_yes "$1" && EXIT_ON_ERROR=true || EXIT_ON_ERROR=false
 | |
| }
 | |
| 
 | |
| function set_wsmode() {
 | |
|     case "$1" in
 | |
|     plain|ldif|mod) WSMODE="$1";;
 | |
|     *) return 1;;
 | |
|     esac
 | |
| }
 | |
| 
 | |
| function set_plain() {
 | |
|     set_wsmode plain
 | |
| }
 | |
| 
 | |
| function set_ldif() {
 | |
|     set_wsmode ldif
 | |
| }
 | |
| 
 | |
| function set_wsappend() {
 | |
|     is_yes "$1" && WSAPPEND=true || WSAPPEND=false
 | |
| }
 | |
| 
 | |
| function set_append() {
 | |
|     set_wsappend true
 | |
| }
 | |
| 
 | |
| function set_profile() {
 | |
|     local profile="$1"
 | |
|     if ! array_contains PROFILES "$profile"; then
 | |
|         local profile_alias
 | |
|         for profile_alias in "${PROFILE_ALIASES[@]}"; do
 | |
|             if [ "${profile_alias%%:*}" == "$profile" ]; then
 | |
|                 profile="${profile_alias#*:}"
 | |
|                 break
 | |
|             fi
 | |
|         done
 | |
|         array_contains PROFILES "$profile" || return 1
 | |
|     fi
 | |
|     PROFILE="$profile"
 | |
|     local -a profile_values
 | |
|     array_copy profile_values "${PROFILE//-/_}_PROFILE"
 | |
|     set_values ldapuri= suffix= binddn= password= searchbase= "${profile_values[@]}"
 | |
| 
 | |
|     if [ -z "$SUFFIX" -a -n "$LDAPURI" ]; then
 | |
|         local suffix
 | |
|         suffix="$(get_suffix "$LDAPURI")" || return 1
 | |
|         set_suffix "$suffix"
 | |
|     fi
 | |
|     [ -n "$SEARCHBASE" ] || set_searchbase "$SUFFIX"
 | |
|     return 0
 | |
| }
 | |
| function set_ldapuri() {
 | |
|     LDAPURI="$1"
 | |
|     local proto host port
 | |
|     if ! split_ldapuri "$LDAPURI" proto host port; then
 | |
|         LDAPURI=
 | |
|         return 1
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| function set_suffix() {
 | |
|     [ -n "$BINDDN" ] && BINDDN="$(reldn "$BINDDN")"
 | |
|     SEARCHBASE="$(reldn "$SEARCHBASE")"
 | |
|     SUFFIX="$1"
 | |
|     [ -n "$BINDDN" ] && BINDDN="$(absdn "$BINDDN")"
 | |
|     SEARCHBASE="$(absdn "$SEARCHBASE")"
 | |
| }
 | |
| function set_binddn() {
 | |
|     local auth="$1"
 | |
|     if ! array_contains AUTH_PROFILES "$auth"; then
 | |
|         local auth_alias
 | |
|         for auth_alias in "${AUTH_ALIASES[@]}"; do
 | |
|             if [ "${auth_alias%%:*}" == "$auth" ]; then
 | |
|                 auth="${auth_alias#*:}"
 | |
|                 break
 | |
|             fi
 | |
|         done
 | |
|     fi
 | |
|     if array_contains AUTH_PROFILES "$auth"; then
 | |
|         local -a auth_values
 | |
|         local auth_value
 | |
|         array_copy auth_values "${auth//-/_}_AUTH"
 | |
|         BINDDN=
 | |
|         set_values password=
 | |
|         for auth_value in "${auth_values[@]}"; do
 | |
|             if [[ "$auth_value" == binddn=* ]]; then
 | |
|                 auth="${auth_value#binddn=}"
 | |
|                 if [ -z "$auth" -o "$auth" == "anonymous" ]; then
 | |
|                     BINDDN=
 | |
|                 else
 | |
|                     BINDDN="$(absdn "$auth")"
 | |
|                 fi
 | |
|             else
 | |
|                 set_values "$auth_value"
 | |
|             fi
 | |
|         done
 | |
|     elif [ -z "$auth" -o "$auth" == "anonymous" ]; then
 | |
|         BINDDN=
 | |
|     else
 | |
|         BINDDN="$(absdn "$auth")"
 | |
|     fi
 | |
| }
 | |
| function set_password() {
 | |
|     PASSWORD="$1"
 | |
| }
 | |
| function set_searchbase_exact() {
 | |
|     SEARCHBASE="$1"
 | |
| }
 | |
| function set_searchbase() {
 | |
|     set_searchbase_exact "$(absdn "$1")"
 | |
| }
 | |
| function set_filter() {
 | |
|     FILTER="$1"
 | |
| }
 | |
| function set_attrs() {
 | |
|     array_split ATTRS "$1"
 | |
| }
 | |
| function set_uncut_on_load() {
 | |
|     is_yes "$1" && UNCUT_ON_LOAD=true || UNCUT_ON_LOAD=false
 | |
| }
 | |
| function set_cut_on_save() {
 | |
|     is_yes "$1" && CUT_ON_SAVE=true || CUT_ON_SAVE=false
 | |
| }
 | |
| function set_decode_on_load() {
 | |
|     is_yes "$1" && DECODE_ON_LOAD=true || DECODE_ON_LOAD=false
 | |
| }
 | |
| function set_encode_on_save() {
 | |
|     is_yes "$1" && ENCODE_ON_SAVE=true || ENCODE_ON_SAVE=false
 | |
| }
 | |
| function set_encode_attrs() {
 | |
|     array_split ENCODE_ATTRS "$1"
 | |
| }
 | |
| function set_output() {
 | |
|     OUTPUT="$1"
 | |
| }
 | |
| function set_lines() {
 | |
|     LINES="$1"
 | |
| }
 | |
| function set_debug() {
 | |
|     is_yes "$1" && DEBUG=true || DEBUG=false
 | |
| }
 | |
| 
 | |
| ac_set_tmpfile TMPFILE # espace de travail temporaire
 | |
| ac_set_tmpfile WSFILE # espace de travail courant
 | |
| # le contenu de l'espace de travail est-il formatté pour ldapmodify? Dans ce
 | |
| # cas, aucune opération de transformation n'a à lui être appliquée
 | |
| WSFILES=()
 | |
| WSSTACK=()
 | |
| 
 | |
| function clear_wsfiles() {
 | |
|     local wsfile
 | |
|     for wsfile in "${WSFILES[@]}"; do
 | |
|         rm "$wsfile"
 | |
|     done
 | |
|     WSFILES=()
 | |
|     WSSTACK=()
 | |
|     WSMODE=ldif
 | |
| }
 | |
| function __push() {
 | |
|     local __varcmd __name
 | |
|     for __name in "$@"; do
 | |
|         __varcmd="${__varcmd:+$__varcmd
 | |
| }$(set_var_cmd "$__name" "${!__name}")"
 | |
|     done
 | |
|     WSSTACK=("${WSSTACK[@]}" "$__varcmd")
 | |
| }
 | |
| function __pop() {
 | |
|     eval "$(last_value WSSTACK)"
 | |
|     array_del_last WSSTACK
 | |
| }
 | |
| function push_wsfile() {
 | |
|     WSFILES=("${WSFILES[@]}" "$WSFILE")
 | |
|     __push WSMODE WSAPPEND UNCUT_ON_LOAD CUT_ON_SAVE DECODE_ON_LOAD ENCODE_ON_SAVE ENCODE_ATTRS
 | |
|     ac_set_tmpfile WSFILE
 | |
| }
 | |
| function pop_wsfile() {
 | |
|     if [ -n "${WSFILES[*]}" ]; then
 | |
|         rm "$WSFILE"
 | |
|         WSFILE="$(last_value WSFILES)"
 | |
|         array_del_last WSFILES
 | |
|         __pop
 | |
|     fi
 | |
| }
 | |
| function peek_wsfile() {
 | |
|     last_value WSFILES
 | |
| }
 | |
| function has_wsfiles() {
 | |
|     [ -n "${WSFILES[*]}" ]
 | |
| }
 | |
| function count_wsfiles() {
 | |
|     echo "${#WSFILES[*]}"
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| # Commandes
 | |
| 
 | |
| COMMANDS=(help set last profile auth clear load save print alias cd
 | |
|     list ldapsearch transform sed awk grep format sort edit diff
 | |
|     ldapmodify ldapadd ldapdelete
 | |
|     undo quit)
 | |
| 
 | |
| COMMANDS_HELP="\
 | |
|     \$ cmd
 | |
|         Passer directement une commande au shell.
 | |
|     set [options] [var=value...]
 | |
|         Changer des options ou des variables. set sans argument affiche la liste
 | |
|         des variables définies.
 | |
|     [set] plain
 | |
|         Passer en mode 'plain': indiquer que l'espace de travail contient des
 | |
|         données brutes. Les pré-traitements et post-traitements (uncut_on_load,
 | |
|         decode_on_load, encode_on_save, cut_on_save) ne sont pas appliqués sur
 | |
|         cet espace de travail
 | |
|     [set] ldif
 | |
|         Passer en mode 'ldif': indiquer que l'espace de travail contient des
 | |
|         données ldif. Les pré-traitements et post-traitements sont appliqués
 | |
|         normalement sur cet espace de travail
 | |
|     [set] append
 | |
|         Pour certaines opérations, spécifier si le résultat de la *prochaine*
 | |
|         opération remplace le contenu de l'espace de travail courant (par
 | |
|         défaut), ou si le résultat est ajouté à la fin.
 | |
|     last
 | |
|         Afficher en mode édition la dernière commande. Cette commande n'est
 | |
|         fonctionnelle qu'avec une version de bash >=4.x
 | |
|     profile name
 | |
|         Choisir le profil 'name'. Equivalent à 'set profile=name'. Sans
 | |
|         argument, afficher la liste des profils valides.
 | |
|     auth anonymous|binddn [password]
 | |
|         Spécifier le compte à utiliser pour se connecter. Equivalent à
 | |
|         'set binddn=binddn; set password=password'
 | |
|     clear [-k]
 | |
|         Vider l'espace de travail et passer en mode 'plain'.
 | |
|         Avec l'option -k, supprimer aussi tout l'historique d'annulation.
 | |
|     load [-k] input
 | |
|         Charger un fichier dans l'espace de travail. Si l'extension du fichier
 | |
|         est .ldif, passer en mode 'ldif'
 | |
|         En mode append, rajouter le contenu du fichier à l'espace de travail,
 | |
|         puis repasser en mode replace.
 | |
|         Le code de retour est 0 si le fichier a été chargé, 1 sinon.
 | |
|     save [-a] output
 | |
|         Sauvegarder l'espace de travail dans un fichier.
 | |
|         Avec l'option -a, rajouter au fichier au lieu de l'écraser
 | |
|     print
 | |
|         Afficher l'espace de travail
 | |
|     alias a=rdn...
 | |
|         Définir un alias pour la commande cd. 'a' est l'alias, 'rdn' est le dn
 | |
|         correspondant, exprimé par rapport à \$suffix. Sans argument, afficher
 | |
|         la liste des aliases définis.
 | |
|     cd rdn
 | |
|         Changer searchbase. Par défaut, il s'agit d'un rdn relatif à \$searchbase
 | |
|         - Certains aliases sont supportés: .. pour l'objet parent, ~ pour
 | |
|           \$suffix, / pour la racine. 'cd' sans argument équivaut à 'cd ~'
 | |
|         - Si le dn commence par '~/', il s'agit d'un rdn relatif à \$suffix.
 | |
|         - Si le dn commence par /, searchbase reçoit la valeur rdn sans
 | |
|           modifications (sauf bien sûr enlever le '/' de tête si nécessaire). Il
 | |
|           faut alors que ce soit un dn absolu.
 | |
|     ls [-b searchbase] [filter [attrs...]]
 | |
|     search [-b searchbase] [filter [attrs...]]
 | |
|         Utiliser ldapsearch pour faire la recherche, et copier le résultat dans
 | |
|         l'espace de travail. 'ls' est équivalent à 'search -s one'. Si ce n'est
 | |
|         pas déjà le cas, passer en mode 'ldif'.
 | |
|         L'option -b prend une valeur avec la même syntaxe que la commande cd,
 | |
|         sauf que les alias ne sont pas supportés. En particulier, la valeur est
 | |
|         relative au \$searchbase courant. Pour faire une recherche par rapport à
 | |
|         \$suffix, il faut utiliser la syntaxe ~/searchbase.
 | |
|         En mode append, rajouter le résultat de la recherche à l'espace de
 | |
|         travail, puis repasser en mode replace.
 | |
|         Le code de retour est 1 si aucun enregistrement n'a été trouvé, sinon
 | |
|         le code de retour est celui de la commande ldapsearch.
 | |
|     cut Couper les lignes trop longues. Cette action est en principe effectuée
 | |
|         automatiquement lors de la sauvegarde. Il n'est pas conseillé
 | |
|         d'appliquer des méthodes de transformation après avoir utilisé cette
 | |
|         action.
 | |
|     uncut
 | |
|         Fusionner les lignes coupées. Cette action est en principe effectuée
 | |
|         automatiquement lors du chargement ou après la recherche.
 | |
|     encode [attrs...]
 | |
|         Encoder en base64 les valeurs des attributs mentionnés.
 | |
|     decode [attrs...]
 | |
|         Décoder les valeurs des attributs mentionnés si nécessaire (c'est à dire
 | |
|         s'ils sont encodés en base64)
 | |
|     keepattr attrs...
 | |
|         Garder uniquement les lignes des attributs mentionnés. Ensuite,
 | |
|         supprimer les objets ayant uniquement la ligne dn: (en d'autres termes,
 | |
|         keepattr sans argument supprime *tout* l'espace de travail)
 | |
|     keepval attr patterns...
 | |
|         Pour l'attribut attr, garder uniquement les lignes pour lesquelles les
 | |
|         valeurs correspondent aux expressions régulières. Les autres attributs
 | |
|         ne sont pas modifiés. Ensuite, supprimer les objets ayant uniquement la
 | |
|         ligne dn:
 | |
|     exclude attrs...
 | |
|         Supprimer les lignes des attributs mentionnés. Ensuite, supprimer les
 | |
|         objets ayant uniquement la ligne dn:
 | |
|     excludeval attr patterns...
 | |
|         Pour l'attribut attr, supprimer les lignes pour lesquelles les
 | |
|         valeurs correspondent aux expressions régulières. Les autres attributs
 | |
|         ne sont pas modifiés. Ensuite, supprimer les objets ayant uniquement la
 | |
|         ligne dn:
 | |
|     keepvalentry attr patterns...
 | |
|         Pour l'attribut attr, vérifier si *au moins une* valeur correspond à
 | |
|         l'une des expressions régulières. Si c'est le cas, garder l'entrée
 | |
|         entière, sinon supprimer l'entrée.
 | |
|     excludevalentry attr patterns...
 | |
|         Pour l'attribut attr, vérifier si *aucune* des valeurs ne correspond à
 | |
|         l'une des expressions régulières. Si c'est le cas, garder l'entrée
 | |
|         entière, sinon supprimer l'entrée.
 | |
|     setval attr values...
 | |
|         Remplacer toutes les valeurs de l'attribut attr par les valeurs
 | |
|         spécifiées.
 | |
|     addval attr values...
 | |
|         Ajouter un nouvel attribut avec les valeurs spécifiées. Si l'attribut
 | |
|         existe déjà, les nouvelles valeurs sont ajoutées à la fin.
 | |
|     sed args
 | |
|         Modifier l'espace de travail avec le résultat de la commande sed.
 | |
|         note: aucun argument n'est filtré, mais il ne faut pas utiliser les
 | |
|         options de sed qui provoquent la modification en place du fichier,
 | |
|         comme par exemple l'option -i
 | |
|     awk args
 | |
|         Modifier l'espace de travail avec le résultat de la commande awk.
 | |
|     grep args
 | |
|         Modifier l'espace de travail avec le résultat de la commande grep.
 | |
|     format [options] attrs...
 | |
|         Formater l'espace de travail en données tabulaires, et passer en mode
 | |
|         'plain'.
 | |
|         --show-headers
 | |
|             Afficher les en-têtes
 | |
|         -F FSEP
 | |
|             Spécifier le séparateur pour les attributs. Par défaut, il s'agit du
 | |
|             caractère de tabulation.
 | |
|         -R VSEP
 | |
|             Spécifier le séparateur pour les valeurs des attributs. Par défaut, il
 | |
|             s'agit du point-virgule ';'
 | |
|         -e  Retourner les valeurs comme des variables shell. Les options -F et -R
 | |
|             sont ignorées. Les attributs multivalués sont écrits sous forme de
 | |
|             tableaux. Par exemple:
 | |
|                 attributes=('mail' 'givenName')
 | |
|                 index=0
 | |
|                 mail='user@domain.fr'
 | |
|                 givenName=('peter' 'gabriel')
 | |
|         --bc
 | |
|             Dans le mode -e, spécifier une commande à insérer avant le premier
 | |
|             enregistrement. Quand cette commande est lancée, index==-1
 | |
|         -c  Dans le mode -e, spécifier une commande à insérer après chaque
 | |
|             enregistrement
 | |
|         --ec
 | |
|             Dans le mode -e, spécifier une commande à insérer après le dernier
 | |
|             enregistrement
 | |
|     sort [args]
 | |
|         Modifier l'espace de travail avec le résultat de la commande sort.
 | |
|     edit
 | |
|         Lancer un éditeur pour modifier l'espace de travail.
 | |
|     diff [options]
 | |
|         Afficher les différences entre l'espace de travail et la version
 | |
|         précédente
 | |
|     ifok cmd
 | |
|     iferror cmd
 | |
|         Si le dernier code de retour est 0 (resp. !=0), lancer la commande cmd
 | |
|     skip n
 | |
|         Sauter les n prochaines commandes. A utiliser avec ifok et iferror
 | |
|     undo
 | |
|         Annuler la dernière modification effectuée sur l'espace de travail
 | |
| 
 | |
| Les directives suivantes prennent le contenu de l'espace de travail, et le
 | |
| transforment en une suite de commandes de modifications pour ldapmodify:
 | |
| 
 | |
|     A   Créer un objet de toutes pièces avec les attributs donnés et leurs
 | |
|         valeurs.
 | |
|     a   Ajouter les valeurs spécifiée à l'attribut
 | |
|     r   Remplacer les valeurs de l'attribut par celles spécifiées
 | |
|     d   Supprimer les valeurs spécifiées de l'attribut
 | |
|     D   Supprimer l'attribut
 | |
|     delentry
 | |
|         Supprimer l'objet
 | |
|     ldapmodify
 | |
|         Utiliser ldapmodify pour modifier les objets sur le serveur. Il faut
 | |
|         utiliser au préalable l'une des méthodes de transformation parmi A, a,
 | |
|         r, d, D, delentry.
 | |
|         Le code de retour est celui de la commande ldapmodify.
 | |
|     ldapadd
 | |
|         Utiliser ldapadd pour créer les objets situés dans l'espace de travail.
 | |
|         Le code de retour est celui de la commande ldapadd.
 | |
|     ldapdelete
 | |
|         Utiliser ldapdelete pour supprimer la liste des dns situés dans l'espace
 | |
|         de travail.
 | |
|         Le code de retour est celui de la commande ldapdelete.
 | |
| 
 | |
| Notes:
 | |
| - les expressions régulières sont celles reconnues par awk.
 | |
| - pour spécifier plusieurs actions sur une même ligne, les séparer par //
 | |
| - le code de retour est 0 si ok, 255 si une erreur s'est produite (erreur de
 | |
|   syntaxe, de connexion, de lecture/écriture de fichier, etc.). sinon, les
 | |
|   opérations ldap{search,modify,delete,add} ont leur code de retour respectifs"
 | |
| 
 | |
| function cmdalias() {
 | |
|     # soit le nom de la commande $1, mettre dans le tableau $2(=cmd) la forme
 | |
|     # canonique de la commande, avec ses arguments éventuels
 | |
|     local cmdalias_="$1" cmdname_="${2:-cmd}"
 | |
|     local -a cmdvals_=("$cmdalias_")
 | |
|     case "$cmdalias_" in
 | |
|     h|help) cmdvals_=(help);;
 | |
|     set) cmdvals_=(set);;
 | |
|     plain) cmdvals_=(set wsmode=plain);;
 | |
|     ldif) cmdvals_=(set wsmode=ldif);;
 | |
|     append) cmdvals_=(set wsappend=true);;
 | |
|     l|last) cmdvals_=(last);;
 | |
|     profile) cmdvals_=(profile);;
 | |
|     auth) cmdvals_=(auth);;
 | |
|     clear) cmdvals_=(clear);;
 | |
|     L|load) cmdvals_=(load);;
 | |
|     S|save) cmdvals_=(save);;
 | |
|     p|print) cmdvals_=(print);;
 | |
|     alias) cmdvals_=(alias);;
 | |
|     cd) cmdvals_=(cd);;
 | |
|     ls|list|dir) cmdvals_=(list);;
 | |
|     f|find|s|search|ldapsearch) cmdvals_=(ldapsearch);;
 | |
|     cut) cmdvals_=(transform cut);;
 | |
|     uncut) cmdvals_=(transform uncut);;
 | |
|     enc|encode) cmdvals_=(transform encode);;
 | |
|     dec|decode) cmdvals_=(transform decode);;
 | |
|     av|addval) cmdvals_=(transform addval);;
 | |
|     rv|replval|sv|setval) cmdvals_=(transform replval);;
 | |
|     k|keep|keepattr) cmdvals_=(transform keepattr);;
 | |
|     K|kv|keepval) cmdvals_=(transform keepval);;
 | |
|     x|exclude|excludeattr) cmdvals_=(transform excludeattr);;
 | |
|     kve|keepvalentry) cmdvals_=(transform keepvalentry);;
 | |
|     xve|excludevalentry) cmdvals_=(transform excludevalentry);;
 | |
|     dv|delval|X|xv|excludeval) cmdvals_=(transform excludeval);;
 | |
|     xempty|excludeempty) cmdvals_=(transform excludeempty);;
 | |
|     sed) cmdvals_=(sed);;
 | |
|     awk) cmdvals_=(awk);;
 | |
|     grep) cmdvals_=(grep);;
 | |
|     format) cmdvals_=(format);;
 | |
|     sort) cmdvals_=(sort);;
 | |
|     e|edit) cmdvals_=(edit);;
 | |
|     A|modaddattr) cmdvals_=(transform modaddattr);;
 | |
|     a|ma|modadd|modaddval) cmdvals_=(transform modaddval);;
 | |
|     r|mr|modrepl|modreplval) cmdvals_=(transform modreplval);;
 | |
|     d|md|moddel|moddelval) cmdvals_=(transform moddelval);;
 | |
|     D|moddelattr) cmdvals_=(transform moddelattr);;
 | |
|     delentry|moddelentry) cmdvals_=(transform moddelentry);;
 | |
|     mod|modify|ldapmodify|commit|ci) cmdvals_=(ldapmodify);;
 | |
|     ldapadd) cmdvals_=(ldapadd);;
 | |
|     ldapdelete) cmdvals_=(ldapdelete);;
 | |
|     ifok) cmdvals_=(ifok);;
 | |
|     iferror) cmdvals_=(iferror);;
 | |
|     skip) cmdvals_=(skip);;
 | |
|     u|undo|revert) cmdvals_=(undo);;
 | |
|     q|exit|quit) cmdvals_=(quit);;
 | |
|     esac
 | |
|     set_array "$cmdname_" @ "${cmdvals_[@]}"
 | |
| }
 | |
| 
 | |
| function uldap_help() {
 | |
|     <<<"$COMMANDS_HELP" sed 's/^    //'
 | |
| }
 | |
| 
 | |
| function uldap_set() {
 | |
|     local args varcmd name lname uname
 | |
|     local -a varcmds values
 | |
|     if parse_opts \
 | |
|         -C: '$varcmds=("${varcmds[@]}" profile="$value_")' \
 | |
|         -H: '$varcmds=("${varcmds[@]}" ldapuri="$value_")' \
 | |
|         -D: '$varcmds=("${varcmds[@]}" binddn="$value_")' \
 | |
|         -w: '$varcmds=("${varcmds[@]}" password="$value_")' \
 | |
|         -b: '$varcmds=("${varcmds[@]}" searchbase="$value_")' \
 | |
|         --nu '$varcmds=("${varcmds[@]}" uncut_on_load=false)' \
 | |
|         --nc '$varcmds=("${varcmds[@]}" cut_on_save=false)' \
 | |
|         -u '$varcmds=("${varcmds[@]}" uncut_on_load=true cut_on_save=true)' \
 | |
|         --nd '$varcmds=("${varcmds[@]}" decode_on_load= encode_on_save=)' \
 | |
|         -d '$varcmds=("${varcmds[@]}" decode_on_load=true encode_on_save=true encode_attrs="userPassword")' \
 | |
|         -e '$varcmds=("${varcmds[@]}" exit_on_error=true)' \
 | |
|         --ne '$varcmds=("${varcmds[@]}" exit_on_error=false)' \
 | |
|         @ args -- "$@"; then
 | |
|         varcmds=("${varcmds[@]}" "${args[@]}")
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     set -- "${varcmds[@]}"
 | |
|     if [ -n "$*" ]; then
 | |
|         for varcmd in "$@"; do
 | |
|             if [[ "$varcmd" == *=* ]]; then
 | |
|                 name="${varcmd%%=*}"
 | |
|                 value="${varcmd#$name=}"
 | |
|             else
 | |
|                 name="$varcmd"
 | |
|                 value=
 | |
|             fi
 | |
|             case "$name" in
 | |
|             profile)
 | |
|                 if set_profile "$value"; then
 | |
|                     estep "Sélection du profil $(get_color g)$value$(get_color z)${SEARCHBASE:+ avec le dn de base $(get_color g)$SUFFIX$(get_color z)}"
 | |
|                     if [ -z "$LDAPURI" ]; then
 | |
|                         estep "Chargement des valeurs de $LDAPCONF"
 | |
|                         set_ldapuri "$(<"$LDAPCONF" grep '^URI' | sed 's/^URI  *//g')"
 | |
|                         set_suffix "$(<"$LDAPCONF" grep '^BASE' | sed 's/^BASE  *//g')"
 | |
|                     fi
 | |
|                     if [ -z "$LDAPURI" ]; then
 | |
|                         ewarn "Ce profil ne définit pas de serveur ldap, et aucun serveur n'a été défini dans $LDAPCONF"
 | |
|                     fi
 | |
|                 else
 | |
|                     eerror "Profil invalide ou erreur de connexion: $value"
 | |
|                     return 1
 | |
|                 fi
 | |
|                 ;;
 | |
|             *)
 | |
|                 if ! set_values "$varcmd"; then
 | |
|                     eerror "variable inconnue ou valeur invalide: $varcmd"
 | |
|                     return 1
 | |
|                 fi
 | |
|                 ;;
 | |
|             esac
 | |
|         done
 | |
|     else
 | |
|         for name in "${VARIABLES[@]}"; do
 | |
|             uname="$(awk '{print toupper($0)}' <<<"$name")"
 | |
|             lname="$(awk '{print tolower($0)}' <<<"$name")"
 | |
|             array_copy values "$uname"
 | |
|             echo "$lname = ${values[*]}"
 | |
|         done
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_profile() {
 | |
|     if [ -n "$*" ]; then
 | |
|         uldap_set profile="$1"
 | |
|         return $?
 | |
|     else
 | |
|         local profile profile_value profile_values
 | |
|         for profile in "${PROFILES[@]}"; do
 | |
|             echo_ "$profile"
 | |
|             array_copy profile_values "${profile//-/_}_PROFILE"
 | |
|             for profile_value in "${profile_values[@]}"; do
 | |
|                 if [ "${profile_value#ldapuri=}" != "$profile_value" ]; then
 | |
|                     echo_ $'\t'"${profile_value#ldapuri=}"
 | |
|                 elif [ "${profile_value#binddn=}" != "$profile_value" ]; then
 | |
|                     echo_ $'\t'"[${profile_value#binddn=}]"
 | |
|                 fi
 | |
|             done
 | |
|             echo
 | |
|         done
 | |
|         return 0
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_auth() {
 | |
|     if [ -n "$*" ]; then
 | |
|         set_values binddn="$1" ${2:+password="$2"}
 | |
|         return 0
 | |
|     else
 | |
|         local auth auth_value auth_values
 | |
|         for auth in "${AUTH_PROFILES[@]}"; do
 | |
|             echo_ "$auth"
 | |
|             array_copy auth_values "${auth//-/_}_AUTH"
 | |
|             for auth_value in "${auth_values[@]}"; do
 | |
|                 if [ "${auth_value#binddn=}" != "$auth_value" ]; then
 | |
|                     echo_ $'\t'"${auth_value#binddn=}"
 | |
|                 fi
 | |
|             done
 | |
|             echo
 | |
|         done
 | |
|         return 0
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_clear() {
 | |
|     local args clear
 | |
|     if parse_opts \
 | |
|         -k clear \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     estep "Vidage de l'espace de travail"
 | |
|     if [ -n "$clear" ]; then
 | |
|         clear_wsfiles
 | |
|         >"$WSFILE"
 | |
|     else
 | |
|         push_wsfile
 | |
|     fi
 | |
|     set_wsmode plain
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function __after_load() {
 | |
|     if [ "$WSMODE" == "ldif" ]; then
 | |
|         is_yes "$UNCUT_ON_LOAD" && __transform --nopush uncut_lines
 | |
|         is_yes "$DECODE_ON_LOAD" && __transform --nopush tl_decode "$(def_match_attr)"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_load() {
 | |
|     # par défaut, on reset -u et -d, mais si on spécifie une des options, les honorer
 | |
|     local args clear
 | |
|     local -a options
 | |
|     if parse_opts \
 | |
|         -k clear \
 | |
|         --nu '$array_add options --nu' \
 | |
|         --nc '$array_add options --nc' \
 | |
|         -u '$array_add options -u' \
 | |
|         --nd '$array_add options --nd' \
 | |
|         -d '$array_add options -d' \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
|     [ -z "${options[*]}" ] && options=(-u -d)
 | |
|     uldap_set "${options[@]}"
 | |
| 
 | |
|     local input="${1:-$OUTPUT}"
 | |
|     if [ -f "$input" ]; then
 | |
|         estep "Chargement depuis $input..."
 | |
| 
 | |
|         if [ -n "$clear" ]; then
 | |
|             clear_wsfiles
 | |
|             >"$WSFILE"
 | |
|         elif [ -s "$WSFILE" ]; then
 | |
|             push_wsfile
 | |
|             is_yes "$WSAPPEND" && cat "$(peek_wsfile)" >"$WSFILE"
 | |
|         fi
 | |
|         set_values WSAPPEND=false
 | |
| 
 | |
|         cat "$input" >>"$WSFILE" || return
 | |
|         set_values output="$input"
 | |
| 
 | |
|         if [ "${input%.ldif}" != "$input" ]; then
 | |
|             set_wsmode ldif
 | |
|         else
 | |
|             set_wsmode plain
 | |
|         fi
 | |
| 
 | |
|         __after_load
 | |
|         __show_summary
 | |
|     else
 | |
|         eerror "$input: fichier introuvable"
 | |
|         EXITCODE=1
 | |
|         return 1
 | |
|     fi
 | |
|     EXITCODE=0
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function __before_save() {
 | |
|     if [ "$WSMODE" == "ldif" ]; then
 | |
|         is_yes "$ENCODE_ON_SAVE" && __transform --nopush tl_encode "$(def_match_attr "${ENCODE_ATTRS[@]}")"
 | |
|         is_yes "$CUT_ON_SAVE" && __transform --nopush cut_lines
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_save() {
 | |
|     local args append
 | |
|     if parse_opts \
 | |
|         -a append \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     set_values output="${1:-$OUTPUT}"
 | |
|     if [ -n "$OUTPUT" ]; then
 | |
|         estep "Enregistrement de $OUTPUT..."
 | |
|         __before_save
 | |
|         if [ -n "$append" ]; then
 | |
|             cat "$WSFILE" >>"$OUTPUT" || return
 | |
|         else
 | |
|             cat "$WSFILE" >"$OUTPUT" || return
 | |
|         fi
 | |
|         __after_load
 | |
|     else
 | |
|         eerror "Vous devez spécifier un fichier avec la commande save"
 | |
|         return 1
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function __head() {
 | |
|     # afficher le fichier $1 en le coupant à $LINES
 | |
|     local file="$1"
 | |
|     local nblines="$(<"$file" wc -l)" maxlines="${LINES:-24}"
 | |
|     let maxlines=$maxlines-7
 | |
|     [ $maxlines -gt 1 ] || maxlines=5
 | |
|     head -n "$maxlines" <"$file"
 | |
|     if [ $nblines -gt $maxlines ]; then
 | |
|         eecho "$(get_color y)... $(($nblines - $maxlines)) lignes restantes$(get_color z)"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function __show_summary() {
 | |
|     # Afficher un extrait de $wsfile en mode interactif
 | |
|     [ -n "$INTERACTIVE" ] && __head "$WSFILE"
 | |
| }
 | |
| 
 | |
| function uldap_print() {
 | |
|     cat "$WSFILE"
 | |
|     if [ -n "$INTERACTIVE" -a "$WSMODE" == "ldif" ]; then
 | |
|         local nbdn="$(<"$WSFILE" grep '^dn:' | wc -l)"
 | |
|         enote "$nbdn objet(s) trouvé(s)"
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_alias() {
 | |
|     local alias name searchbase
 | |
|     local -a tmparray
 | |
|     if [ -n "$*" ]; then
 | |
|         for alias in "$@"; do
 | |
|             if [[ "$alias" == *=* ]]; then
 | |
|                 name="${alias%%=*}"
 | |
|                 searchbase="${alias#$name=}"
 | |
|                 # supprimer l'ancien alias
 | |
|                 tmparray=()
 | |
|                 for alias in "${SEARCHBASE_ALIASES[@]}"; do
 | |
|                     if [ "${alias%%:*}" != "$name" ]; then
 | |
|                         array_add tmparray "$alias"
 | |
|                     fi
 | |
|                 done
 | |
|                 array_copy SEARCHBASE_ALIASES tmparray
 | |
|                 # ajouter le nouvel alias
 | |
|                 if [ -n "$searchbase" ]; then
 | |
|                     array_add SEARCHBASE_ALIASES "$name:$searchbase"
 | |
|                 fi
 | |
|             else
 | |
|                 eerror "$alias: Vous devez utiliser la syntaxe 'alias name=searchbase'"
 | |
|             fi
 | |
|         done
 | |
|     else
 | |
|         for alias in "${SEARCHBASE_ALIASES[@]}"; do
 | |
|             name="${alias%%:*}"
 | |
|             searchbase="${alias#$name:}"
 | |
|             echo "alias $name='$searchbase'"
 | |
|         done
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_cd() {
 | |
|     local args exact
 | |
|     if parse_opts \
 | |
|         -p exact \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local dn="$1"
 | |
| 
 | |
|     # corriger les expansions éventuelles du shell
 | |
|     if [ "$dn" == "$HOME" ]; then
 | |
|         dn="~"
 | |
|     elif [ "${dn#$HOME}" != "$dn" ]; then
 | |
|         dn="~${dn#$HOME}"
 | |
|     fi
 | |
| 
 | |
|     # étendre les aliases
 | |
|     local alias
 | |
|     for alias in "${SEARCHBASE_ALIASES[@]}"; do
 | |
|         name="${alias%%:*}"
 | |
|         if [ "$dn" == "$name" ]; then
 | |
|             # les aliases sont exprimés par rapport à $suffix
 | |
|             dn="/$(absdn "${alias#$name:}")"
 | |
|             break
 | |
|         fi
 | |
|     done
 | |
|     if [ -z "$dn" -o "$dn" == "/" -o "$dn" == "~" -o "$dn" == ".." ]; then
 | |
|         # arguments spéciaux
 | |
|         :
 | |
|     elif ! [[ "$dn" == *=* ]]; then
 | |
|         # sinon, il faut que ce soit un rdn
 | |
|         eerror "Alias ou dn invalide: $dn"
 | |
|         return 1
 | |
|     fi
 | |
|     [ -z "$dn" ] && dn="~"
 | |
| 
 | |
|     if [ -n "$exact" ]; then
 | |
|         set_values searchbase_exact="$dn"
 | |
|     elif [ "$dn" == ".." ]; then
 | |
|         if [ "${SEARCHBASE#*,}" != "$SEARCHBASE" ]; then
 | |
|             set_values searchbase_exact="${SEARCHBASE#*,}"
 | |
|         else
 | |
|             set_values searchbase_exact=
 | |
|         fi
 | |
|     else
 | |
|         set_values searchbase_exact="$(rabsdn "$dn")"
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_list() {
 | |
|     if [ -z "$SEARCHBASE" -o \
 | |
|         \( "$SEARCHBASE" != "$SUFFIX" -a "${SEARCHBASE%,$SUFFIX}" == "$SEARCHBASE" \) ]; then
 | |
|         uldap_ldapsearch "$@"
 | |
|     else
 | |
|         uldap_ldapsearch -s one "$@"
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_ldapsearch() {
 | |
|     if [ -z "$SEARCHBASE" -a -z "$*" ]; then
 | |
|         set -- '' objectClass supportedLDAPVersion namingContexts
 | |
|     fi
 | |
| 
 | |
|     local args nop cont debug deref tls scope
 | |
|     local usearchbase lsearchbase="$SEARCHBASE" lfilter lattrs
 | |
|     if parse_opts \
 | |
|         -n nop \
 | |
|         -c cont \
 | |
|         -d: debug= \
 | |
|         -s: scope= \
 | |
|         -a: deref= \
 | |
|         -Z tls \
 | |
|         -b: usearchbase= \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     if [ -n "$usearchbase" ]; then
 | |
|         lsearchbase="$(rabsdn "$usearchbase")"
 | |
|     elif [ -z "$lsearchbase" -o \
 | |
|         \( "$lsearchbase" != "$SUFFIX" -a "${lsearchbase%,$SUFFIX}" == "$lsearchbase" \) ]; then
 | |
|         # avec SEARCHBASE="" ou non relatif à $SUFFIX, le scope est par défaut base
 | |
|         [ -n "$scope" ] || scope=base
 | |
|     fi
 | |
| 
 | |
|     lfilter="${1:-${FILTER:-objectClass=*}}"; shift
 | |
|     [[ "$lfilter" == \(*\) ]] || lfilter="($lfilter)"
 | |
|     if [ -n "$*" ]; then
 | |
|         lattrs=("$@")
 | |
|     else
 | |
|         lattrs=("${ATTRS[@]}")
 | |
|     fi
 | |
| 
 | |
|     local -a lsargs=(ldapsearch -LLL -x ${LDAPURI:+-H "$LDAPURI"} ${tls:+-Z}
 | |
|         ${nop:+-n} ${cont:+-c} ${debug:+-d "$debug"} ${scope:+-s "$scope"}
 | |
|         ${deref:+-a "$deref"} -b "$lsearchbase")
 | |
|     local msg="${lsargs[*]}"
 | |
|     if [ -n "$BINDDN" ]; then
 | |
|         lsargs=("${lsargs[@]}" -D "$BINDDN" -w "$PASSWORD")
 | |
|         msg="$msg -D $BINDDN -w ****"
 | |
|     fi
 | |
| 
 | |
|     estep "$msg $lfilter ${lattrs[*]}"
 | |
|     if [ -s "$WSFILE" ]; then
 | |
|         push_wsfile
 | |
|         is_yes "$WSAPPEND" && cat "$(peek_wsfile)" >"$WSFILE"
 | |
|     fi
 | |
|     set_values WSAPPEND=false
 | |
|     "${lsargs[@]}" "$lfilter" "${lattrs[@]}" >>"$WSFILE"
 | |
|     EXITCODE=$?
 | |
|     if [ $EXITCODE -eq 0 ]; then
 | |
|         # ok seulement s'il y a un résultat
 | |
|         [ -s "$WSFILE" ] && EXITCODE=0 || EXITCODE=1
 | |
|     else
 | |
|         return 1
 | |
|     fi
 | |
|     set_wsmode ldif
 | |
|     __after_load
 | |
|     __show_summary
 | |
| 
 | |
|     # affichage du nombre d'objets
 | |
|     local nbdn="$(<"$WSFILE" grep '^dn:' | wc -l)"
 | |
|     [ -n "$INTERACTIVE" ] && enote "$nbdn objet(s) trouvé(s)"
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function __transform() {
 | |
|     # appliquer la transformation $1 au fichier $WSFILE en utilisant $TMPFILE
 | |
|     local push=1
 | |
|     if [ "$1" == "--nopush" ]; then
 | |
|         shift
 | |
|         push=
 | |
|     fi
 | |
|     cat "$WSFILE" >"$TMPFILE"
 | |
|     [ -n "$push" ] && push_wsfile
 | |
|     "$@" <"$TMPFILE" >"$WSFILE"
 | |
| }
 | |
| 
 | |
| function __check_wsmode() {
 | |
|     if [ "$WSMODE" == "mod" ]; then
 | |
|         eerror "L'espace de travail est formatté pour ldapmodify. Vous ne devriez plus y appliquer de tranformation"
 | |
|         return 1
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_transform() {
 | |
|     local action="$1"; shift
 | |
|     case "$action" in
 | |
|     cut)
 | |
|         __transform cut_lines
 | |
|         ;;
 | |
|     uncut)
 | |
|         __transform uncut_lines
 | |
|         ;;
 | |
|     decode)
 | |
|         __transform tl_decode "$(def_match_attr "$@")"
 | |
|         ;;
 | |
|     encode)
 | |
|         __transform tl_encode "$(def_match_attr "$@")"
 | |
|         set_values encode_attrs="$*" encode_on_save=false
 | |
|         ;;
 | |
|     addval)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_addval "$@"
 | |
|         __transform --nopush ensure_complete_objects
 | |
|         ;;
 | |
|     replval)
 | |
|         __check_wsmode || return
 | |
|         local match_attr="$(def_match_attr "$1")"; shift
 | |
|         __transform tl_replval "$match_attr" "$@"
 | |
|         __transform --nopush ensure_complete_objects
 | |
|         ;;
 | |
|     keepattr)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_keepattr "$(def_match_attr dn "$@")"
 | |
|         __transform --nopush ensure_complete_objects
 | |
|         ;;
 | |
|     keepval)
 | |
|         __check_wsmode || return
 | |
|         local match_attr="$(def_match_attr "$1")"; shift
 | |
|         __transform tl_keepval "$match_attr" "$(def_match_value "$@")"
 | |
|         __transform --nopush ensure_complete_objects
 | |
|         ;;
 | |
|     excludeattr)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_excludeattr "$(def_match_attr "$@")"
 | |
|         __transform --nopush ensure_complete_objects
 | |
|         ;;
 | |
|     excludeval)
 | |
|         __check_wsmode || return
 | |
|         local match_attr="$(def_match_attr "$1")"; shift
 | |
|         __transform tl_excludeval "$match_attr" "$(def_match_value "$@")"
 | |
|         __transform --nopush ensure_complete_objects
 | |
|         ;;
 | |
|     excludevalentry)
 | |
|         __check_wsmode || return
 | |
|         local match_attr="$(def_match_attr "$1")"; shift
 | |
|         __transform tl_excludevalentry "$match_attr" "$(def_match_value "$@")"
 | |
|         __transform --nopush delete_marked_objects
 | |
|         ;;
 | |
|     keepvalentry)
 | |
|         __check_wsmode || return
 | |
|         local match_attr="$(def_match_attr "$1")"; shift
 | |
|         __transform tl_keepvalentry "$match_attr" "$(def_match_value "$@")"
 | |
|         __transform --nopush delete_marked_objects
 | |
|         ;;
 | |
|     excludeempty)
 | |
|         __check_wsmode || return
 | |
|         __transform ensure_complete_objects
 | |
|         ;;
 | |
|     modaddattr)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_addattr
 | |
|         set_wsmode mod
 | |
|         ;;
 | |
|     modaddval)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_modifyattr add
 | |
|         set_wsmode mod
 | |
|         ;;
 | |
|     modreplval)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_modifyattr replace
 | |
|         set_wsmode mod
 | |
|         ;;
 | |
|     moddelval)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_modifyattr delete
 | |
|         set_wsmode mod
 | |
|         ;;
 | |
|     moddelattr)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_deleteattr
 | |
|         set_wsmode mod
 | |
|         ;;
 | |
|     moddelentry)
 | |
|         __check_wsmode || return
 | |
|         __transform tl_deleteentry
 | |
|         set_wsmode mod
 | |
|         ;;
 | |
|     *)
 | |
|         eerror "$action: type de transformation incorrect"
 | |
|         return 1
 | |
|         ;;
 | |
|     esac
 | |
|     __show_summary
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_sed() {
 | |
|     __transform sed "$@"
 | |
|     set_wsmode plain
 | |
|     __show_summary
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_awk() {
 | |
|     __transform awk "$@" || return
 | |
|     set_wsmode plain
 | |
|     __show_summary
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_grep() {
 | |
|     __transform grep "$@"
 | |
|     set_wsmode plain
 | |
|     __show_summary
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_format() {
 | |
|     __transform tl_format "$@"
 | |
|     set_wsmode plain
 | |
|     __show_summary
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_sort() {
 | |
|     __transform sort "$@"
 | |
|     set_wsmode plain
 | |
|     __show_summary
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_edit() {
 | |
|     cat "$WSFILE" >"$TMPFILE"
 | |
|     "${EDITOR:-vi}" "$TMPFILE"
 | |
|     if testdiff "$WSFILE" "$TMPFILE"; then
 | |
|         ac_set_tmpfile diff
 | |
|         diff -U1 "$WSFILE" "$TMPFILE" |
 | |
|         awk 'NR==1 { $2="previous" } NR==2 { $2="current" } {print}' >"$diff"
 | |
|         __head "$diff"
 | |
|         rm -f "$diff"
 | |
| 
 | |
|         push_wsfile
 | |
|         cat "$TMPFILE" >"$WSFILE"
 | |
|     else
 | |
|         enote "Aucune modification effectuée"
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_diff() {
 | |
|     if has_wsfiles; then
 | |
|         local orig="$(peek_wsfile)"
 | |
|         if [ -n "$*" ]; then
 | |
|             diff "$@" "$orig" "$WSFILE"
 | |
|         else
 | |
|             diff -U1 "$orig" "$WSFILE" |
 | |
|             awk 'NR==1 { $2="previous" } NR==2 { $2="current" } {print}'
 | |
|         fi
 | |
|     else
 | |
|         enote "Aucune différence détectée"
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_ldapmodify() {
 | |
|     if [ "$WSMODE" != "mod" ]; then
 | |
|         ewarn "L'espace de travail n'a pas été traité avec l'une des méthodes de transformation A, a, r, d, D, delentry"
 | |
|         if [ -n "$INTERACTIVE" ]; then
 | |
|             ask_yesno "Voulez-vous néanmoins utiliser ldapmodify?" N || return
 | |
|         fi
 | |
|     fi
 | |
| 
 | |
|     local args nop cont debug verbose tls
 | |
|     if parse_opts \
 | |
|         -n nop \
 | |
|         -c cont \
 | |
|         -d: debug= \
 | |
|         -v verbose \
 | |
|         -Z tls \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local -a lsargs=(ldapmodify -x ${LDAPURI:+-H "$LDAPURI"} ${tls:+-Z}
 | |
|         ${nop:+-n} ${cont:+-c} ${debug:+-d "$debug"} ${verbose:+-v})
 | |
|     local msg="${lsargs[*]}"
 | |
|     if [ -n "$BINDDN" ]; then
 | |
|         lsargs=("${lsargs[@]}" -D "$BINDDN" -w "$PASSWORD")
 | |
|         msg="$msg -D $BINDDN -w ****"
 | |
|     fi
 | |
| 
 | |
|     estep "$msg"
 | |
|     "${lsargs[@]}" -f "$WSFILE"
 | |
|     EXITCODE=$?
 | |
|     return $EXITCODE
 | |
| }
 | |
| 
 | |
| function uldap_ldapadd() {
 | |
|     local args nop cont debug verbose tls
 | |
|     if parse_opts \
 | |
|         -n nop \
 | |
|         -c cont \
 | |
|         -d: debug= \
 | |
|         -v verbose \
 | |
|         -Z tls \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local -a lsargs=(ldapadd -x ${LDAPURI:+-H "$LDAPURI"} ${tls:+-Z}
 | |
|         ${nop:+-n} ${cont:+-c} ${debug:+-d "$debug"} ${verbose:+-v})
 | |
|     local msg="${lsargs[*]}"
 | |
|     if [ -n "$BINDDN" ]; then
 | |
|         lsargs=("${lsargs[@]}" -D "$BINDDN" -w "$PASSWORD")
 | |
|         msg="$msg -D $BINDDN -w ****"
 | |
|     fi
 | |
| 
 | |
|     estep "$msg"
 | |
|     "${lsargs[@]}" -f "$WSFILE"
 | |
|     EXITCODE=$?
 | |
|     return $EXITCODE
 | |
| }
 | |
| 
 | |
| function uldap_ldapdelete() {
 | |
|     local args nop cont debug verbose recursive tls
 | |
|     if parse_opts \
 | |
|         -n nop \
 | |
|         -c cont \
 | |
|         -d: debug= \
 | |
|         -v verbose \
 | |
|         -r recursive \
 | |
|         -Z tls \
 | |
|         @ args -- "$@"; then
 | |
|         set -- "${args[@]}"
 | |
|     else
 | |
|         eerror "$args"
 | |
|         return 1
 | |
|     fi
 | |
| 
 | |
|     local -a lsargs=(ldapdelete -x ${LDAPURI:+-H "$LDAPURI"} ${tls:+-Z}
 | |
|         ${nop:+-n} ${cont:+-c} ${debug:+-d "$debug"} ${verbose:+-v}
 | |
|         ${recursive:+-r})
 | |
|     local msg="${lsargs[*]}"
 | |
|     if [ -n "$BINDDN" ]; then
 | |
|         lsargs=("${lsargs[@]}" -D "$BINDDN" -w "$PASSWORD")
 | |
|         msg="$msg -D $BINDDN -w ****"
 | |
|     fi
 | |
| 
 | |
|     if [ -n "$*" ]; then
 | |
|         if [ -n "$INTERACTIVE" ]; then
 | |
|             ewarn "Vous êtes sur le point du supprimer ${recursive:+DE FACON RECURSIVE }les objets suivants: $*"
 | |
|             ask_yesno "Etes-vous sûr de vouloir continuer?" N || return
 | |
|             estep "$msg $*"
 | |
|         fi
 | |
|         "${lsargs[@]}" "$@"
 | |
|         EXITCODE=$?
 | |
|     else
 | |
|         if [ -n "$INTERACTIVE" ]; then
 | |
|             __show_summary
 | |
|             ewarn "Vous êtes sur le point de supprimer ${recursive:+DE FACON RECURSIVE }les DNs de l'espace de travail (un par ligne)"
 | |
|             ask_yesno "Etes-vous sûr de vouloir continuer?" N || return
 | |
|             estep "$msg"
 | |
|         fi
 | |
|         "${lsargs[@]}" -f "$WSFILE"
 | |
|         EXITCODE=$?
 | |
|     fi
 | |
|     return $EXITCODE
 | |
| }
 | |
| 
 | |
| function uldap_undo() {
 | |
|     if has_wsfiles; then
 | |
|         pop_wsfile
 | |
|         __show_summary
 | |
|     fi
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_ifok() {
 | |
|     if [ "$EXITCODE" -eq 0 ]; then
 | |
|         eval_cmdline "$(quoted_args "$@")"
 | |
|     else
 | |
|         return 0
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_iferror() {
 | |
|     if [ "$EXITCODE" -ne 0 ]; then
 | |
|         eval_cmdline "$(quoted_args "$@")"
 | |
|     else
 | |
|         return 0
 | |
|     fi
 | |
| }
 | |
| 
 | |
| function uldap_skip() {
 | |
|     let SKIPCOUNT="${1:-1}"
 | |
|     [ $SKIPCOUNT -eq 0 ] && SKIPCOUNT=
 | |
|     return 0
 | |
| }
 | |
| 
 | |
| function uldap_quit() {
 | |
|     exit "$EXITCODE"
 | |
| }
 | |
| 
 | |
| ################################################################################
 | |
| # Shell
 | |
| 
 | |
| function display_help() {
 | |
|     uecho "$scriptname: Shell pour accéder à un serveur ldap
 | |
| 
 | |
| USAGE
 | |
|     $scriptname [options]
 | |
| 
 | |
| OPTIONS
 | |
|     -C profile
 | |
|         Sélectionner un profil de connexion. Par défaut, si l'option -H n'est
 | |
|         pas spécifiée, le premier profil est sélectionné.
 | |
|     -x  Ne pas tenter de faire une connexion sur le profil par défaut si aucun
 | |
|         profil n'est sélectionné.
 | |
|     -f script
 | |
|         Lire les commandes depuis le script spécifié.
 | |
|     -n  Avec un script donné en ligne de commande ou lu depuis un fichier, ne pas
 | |
|         ajouter automatiquement la commande print à la fin
 | |
|     -i  Si un script est spécifié, passer en mode interactif après l'exécution
 | |
|         du script.
 | |
|     -e  Forcer l'arrêt du script si une erreur se produit. C'est l'option par
 | |
|         défaut pour un script spécifié avec -f.
 | |
|     -l input.ldif
 | |
|         Charger le fichier input.ldif comme espace de travail initial
 | |
|     -H ldapuri
 | |
|     -D binddn
 | |
|     -w password
 | |
|     -b searchbase
 | |
|     -v var=value
 | |
| 
 | |
| COMMANDES
 | |
| $COMMANDS_HELP"
 | |
| }
 | |
| 
 | |
| PROFILES=(default)
 | |
| default_PROFILE=(filter="(objectClass=*)" attrs="")
 | |
| set_defaults uldap
 | |
| 
 | |
| AUTOPROFILE=1
 | |
| parse_opts + "${PRETTYOPTS[@]}" \
 | |
|     --help '$exit_with display_help' \
 | |
|     -C: lprofile \
 | |
|     -x AUTOPROFILE= \
 | |
|     -f: lscriptfile \
 | |
|     -n AUTOPRINT= \
 | |
|     -i INTERACTIVE=1 \
 | |
|     -e lexit_on_error \
 | |
|     -l: loutput \
 | |
|     -H: lldapuri \
 | |
|     -D: lbinddn \
 | |
|     -w: lpassword \
 | |
|     -b: lsearchbase \
 | |
|     -v: varcmds \
 | |
|     @ args -- "$@" && set -- "${args[@]}" || die "$args"
 | |
| 
 | |
| [ -n "$lexit_on_error" ] && set_values exit_on_error=true
 | |
| 
 | |
| # choix du profil
 | |
| if [ -n "$lprofile" ]; then
 | |
|     # un profil spécifique
 | |
|     if ! uldap_set profile="$lprofile"; then
 | |
|         is_yes "$EXIT_ON_ERROR" && exit 255
 | |
|     fi
 | |
| elif [ -z "$lldapuri" -a -n "$AUTOPROFILE" ]; then
 | |
|     # choisir le profil par défaut
 | |
|     if ! uldap_set profile="${PROFILES[0]}"; then
 | |
|         is_yes "$EXIT_ON_ERROR" && exit 255
 | |
|     fi
 | |
| fi
 | |
| if [ -n "$lldapuri" ]; then
 | |
|     # augmenter le profil des paramètres de la ligne de commande
 | |
|     if ! uldap_set ldapuri="$lldapuri" ${lbinddn:+binddn="$lbinddn"} ${lpassword:+password="$lpassword"}; then
 | |
|         is_yes "$EXIT_ON_ERROR" && exit 255
 | |
|     fi
 | |
| fi
 | |
| [ -n "$lsearchbase" ] && set_values searchbase="$lsearchbase"
 | |
| 
 | |
| # définitions de variables
 | |
| for varcmd in "${varcmds[@]}"; do
 | |
|     set_values "$varcmd" || eerror "impossible de spécifier la valeur de ${varcmd%%=*}"
 | |
| done
 | |
| 
 | |
| # script
 | |
| lcmds=()
 | |
| if [ -n "$*" ]; then
 | |
|     [ "$INTERACTIVE" == auto ] && INTERACTIVE= || AUTOPRINT=
 | |
|     INTERACTIVE_AFTER_CMDS="$INTERACTIVE"
 | |
|     INTERACTIVE=
 | |
|     [ "$EXIT_ON_ERROR" == auto ] && set_values exit_on_error=true
 | |
|     # splitter sur les lignes
 | |
|     array_from_lines lcmds "$(quoted_args "$@")"
 | |
|     [ -n "$AUTOPRINT" ] && array_add lcmds print
 | |
| elif [ -n "$lscriptfile" ]; then
 | |
|     [ -f "$lscriptfile" ] || die "$lscriptfile: fichier introuvable"
 | |
|     [ "$INTERACTIVE" == auto ] && INTERACTIVE= || AUTOPRINT=
 | |
|     INTERACTIVE_AFTER_CMDS="$INTERACTIVE"
 | |
|     INTERACTIVE=
 | |
|     [ "$EXIT_ON_ERROR" == auto ] && set_values exit_on_error=true
 | |
|     # splitter sur les lignes
 | |
|     array_from_lines lcmds "$(<"$lscriptfile" filter_comment -m)"
 | |
|     [ -n "$AUTOPRINT" ] && array_add lcmds print
 | |
| elif [ "$INTERACTIVE" == auto ]; then
 | |
|     isatty && INTERACTIVE=1 || INTERACTIVE=
 | |
| fi
 | |
| [ "$EXIT_ON_ERROR" == auto ] && set_values exit_on_error=
 | |
| 
 | |
| function run_cmds() {
 | |
|     # lancer toutes les commandes qui sont dans le tableau $1
 | |
|     local -a __rc_cmds
 | |
|     local cmd
 | |
| 
 | |
|     array_copy __rc_cmds "${1:-cmds}"
 | |
|     for cmd in "${__rc_cmds[@]}"; do
 | |
|         # sauter éventuellement des commandes
 | |
|         [ "$SKIPCOUNT" == "0" ] && SKIPCOUNT=
 | |
|         if [ -n "$SKIPCOUNT" ]; then
 | |
|             let SKIPCOUNT=$SKIPCOUNT-1
 | |
|             continue
 | |
|         fi
 | |
| 
 | |
|         eval_cmdline "$cmd"
 | |
|     done
 | |
| }
 | |
| 
 | |
| # espace de travail initial
 | |
| [ -n "$loutput" ] && uldap_load "$loutput"
 | |
| 
 | |
| # commandes non interactives
 | |
| if [ -n "${lcmds[*]}" ]; then
 | |
|     run_cmds lcmds
 | |
|     INTERACTIVE="$INTERACTIVE_AFTER_CMDS"
 | |
| fi
 | |
| 
 | |
| # commandes interactives
 | |
| if [ -n "$INTERACTIVE" ]; then
 | |
|     while true; do
 | |
|         # construire le prompt
 | |
|         prompt=
 | |
|         tmp="$(reldn "$BINDDN")"
 | |
|         prompt="$prompt${tmp:+[$tmp]}"
 | |
|         prompt="$prompt$(get_color y)"
 | |
|         if [ -n "$LDAPURI" ]; then
 | |
|             split_ldapuri "$LDAPURI" proto host port || break
 | |
|             if [ -n "$host" ]; then
 | |
|                 if [ "$proto" != "ldap" -a "$proto" != "ldaps" ]; then
 | |
|                     prompt="$prompt$proto://"
 | |
|                 fi
 | |
|                 prompt="$prompt$host"
 | |
|                 if [ -n "$port" -a "$port" != "389" ]; then
 | |
|                     prompt="$prompt:$port"
 | |
|                 fi
 | |
|             else
 | |
|                 prompt="$prompt(default)"
 | |
|             fi
 | |
|         else
 | |
|             prompt="${prompt}(default)"
 | |
|         fi
 | |
|         prompt="$prompt$(get_color z)"
 | |
|         tmp="$(pdn "$SEARCHBASE")"
 | |
|         [ -n "$FILTER" -o -n "$ATTRS" ] && tmp="$tmp?$ATTRS??$FILTER"
 | |
|         prompt="$prompt${tmp:+ $tmp}"
 | |
|         eecho "$prompt"
 | |
| 
 | |
|         # lire la commande
 | |
|         prompt="$WSMODE"
 | |
|         has_wsfiles && prompt="$prompt$(count_wsfiles)"
 | |
|         read -p "$prompt> " ${EDITLAST:+-i "$LASTCMD"} -e cmds || break
 | |
|         EDITLAST=
 | |
|         [ -n "$cmds" ] || continue
 | |
| 
 | |
|         # lancer les commandes
 | |
|         run_cmds cmds
 | |
|     done
 | |
|     echo
 | |
| fi
 | |
| 
 | |
| exit "$EXITCODE"
 | 
