# ulib/base

## `setyesval`
~~~
mettre la valeur normalisée de la valeur "oui" de $2 dans la variable $1
~~~
## `normyesval`
~~~
remplacer la valeur de la variable $1 par la valeur normalisée de sa valeur "oui"
Si $2 est non vide, prendre cette valeur plutôt que la valeur de la variable $1
~~~
## `normyesvals`
~~~
remplacer les valeur des variables $1..* par les valeurs normalisées
respectives de leur valeur "oui"
~~~
## `quote_in`
~~~
Comme quote_arg pour une chaine lue sur stdin
~~~
## `quote_sin`
~~~
Pour la chaine lue sur stdin, remplacer ' par '\''. Cela permet de protéger une
chaine à mettre entre quotes
~~~
## `quote_sarg`
~~~
Dans la chaine $1, remplacer ' par '\''. Cette fonction utilise quote_sin,
puisque le shell a des difficultés à faire le rechercher/remplacer approprié
~~~
## `quoted_sarg`
~~~
Dans la chaine $1, remplacer ' par '\'', et afficher la chaine entourée de
quotes
~~~
## `quoted_sargs`
~~~
Comme quoted_sarg, mais tous les arguments sont quotés et affichés entourés de
quotes, ce qui permet de construire des arguments d'une ligne de commande
~~~
## `set_array_cmd`
~~~
Afficher la commande permettant d'initialiser le tableau $1 avec les valeurs:
soit du tableau $2, soit de $3..$n si $2=="@"
S'il n'y a que l'argument $1, alors afficher la commande permettant de
recréer le tableau $1
~~~
## `set_array`
~~~
Soit $1 un tableau à créer. Si $2=="@", créer le tableau $1 avec les valeurs
$3..$n. Sinon, créer le tableau $1 avec les valeurs du tableau $2.
Cette fonction n'existe que comme un pendant de set_var(), mais le véritable
intérêt est la fonction set_array_cmd(). cf array_copy() pour une version plus
efficace de la copie de tableaux
~~~
## `array_count`
~~~
retourner le nombre d'éléments du tableau $1
~~~
## `array_isempty`
~~~
tester si le tableau $1 est vide
~~~
## `array_new`
~~~
créer un tableau vide dont le nom est $1
~~~
## `array_add`
~~~
ajouter les valeurs $2..@ au tableau dont le nom est $1
~~~
## `array_ins`
~~~
insérer les valeurs $2..@ au début du tableau dont le nom est $1
~~~
## `array_del`
~~~
supprimer *les* valeurs $2 du tableau dont le nom est $1
~~~
## `array_addu`
~~~
ajouter la valeur $2 au tableau dont le nom est $1, si la valeur n'y est pas
déjà. Retourner vrai si la valeur a été ajoutée
~~~
## `array_set`
## `array_insu`
~~~
insérer la valeur $2 au début du tableau tableau dont le nom est $1, si la
valeur n'y est pas déjà. Retourner vrai si la valeur a été ajoutée.
~~~
## `array_fillrange`
~~~
Initialiser le tableau $1 avec les nombres de $2(=1) à $3(=10) avec un step de $4(=1)
~~~
## `array_eq`
~~~
tester l'égalité des tableaux $1 et $2
~~~
## `array_contains`
~~~
tester si le tableau dont le nom est $1 contient la valeur $2
~~~
## `array_icontains`
~~~
tester si le tableau dont le nom est $1 contient la valeur $2, sans tenir
compte de la casse
~~~
## `array_find`
~~~
si le tableau $1 contient la valeur $2, retourner l'index de la valeur. Si le
tableau $3 est spécifié, retourner la valeur à l'index dans ce tableau
~~~
## `array_reverse`
~~~
Inverser l'ordre des élément du tableau $1
~~~
## `array_replace`
~~~
dans le tableau $1, remplacer toutes les occurences de $2 par $3..*
~~~
## `array_each`
~~~
Pour chacune des valeurs 'v' du tableau $1, appeler la fonction $2 avec les
arguments '$v $3..$n'
~~~
## `array_map`
~~~
Pour chacune des valeurs 'v' du tableau $1, appeler la fonction $2 avec les
arguments '$v $3..$n', et remplacer la valeur par le résultat de la fonction
~~~
## `first_value`
~~~
retourner la première valeur du tableau $1
~~~
## `last_value`
~~~
retourner la dernière valeur du tableau $1
~~~
## `array_copy`
~~~
copier le contenu du tableau $2 dans le tableau $1
~~~
## `array_copy_firsts`
~~~
copier tous les valeurs du tableau $2(=$1) dans le tableau $1, excepté la dernière
~~~
## `array_del_last`
## `array_copy_lasts`
~~~
copier tous les valeurs du tableau $2(=$1) dans le tableau $1, excepté la première
~~~
## `array_del_first`
## `array_extend`
~~~
ajouter le contenu du tableau $2 au tableau $1
~~~
## `array_extendu`
~~~
ajouter chacune des valeurs du tableau $2 au tableau $1, si ces valeurs n'y
sont pas déjà. Retourner vrai si au moins une valeur a été ajoutée
~~~
## `array_extend_firsts`
~~~
ajouter toutes les valeurs du tableau $2 dans le tableau $1, excepté la dernière
~~~
## `array_extend_lasts`
~~~
ajouter toutes les valeurs du tableau $2 dans le tableau $1, excepté la première
~~~
## `array_xsplit`
~~~
créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
par $3, qui vaut ':' par défaut).
~~~
## `array_split`
~~~
créer le tableau $1 avec chaque élément de $2 (un ensemble d'éléments séparés
par $3, qui vaut ':' par défaut). Les éléments vides sont ignorés. par exemple
"a::b" est équivalent à "a:b"
~~~
## `array_from_path`
## `array_from_xlines`
~~~
créer le tableau $1 avec chaque ligne de $2.
~~~
## `array_from_lines`
~~~
créer le tableau $1 avec chaque ligne de $2. Les lignes vides sont ignorés.
~~~
## `array_join`
~~~
afficher le contenu du tableau dont le nom est $1 sous forme d'une liste de
valeurs séparées par $2 (par défaut, une virgule)
Si $1=="@", alors les éléments du tableaux sont les arguments de la fonction à
partir de $3
Si $1!="@" et que le tableau est vide, afficher $3
Si $1!="@", $4 et $5 sont des préfixes et suffixes à rajouter à chaque élément
~~~
## `array_mapjoin`
~~~
map le tableau $1 avec la fonction $2, puis afficher le résultat en séparant
chaque élément par $3. Les arguments et la sémantique sont les mêmes que pour
array_join en tenant compte de l'argument supplémentaire $2 qui est la
fonction pour array_map (les autres arguments sont décalés en conséquence)
~~~
## `array_to_lines`
~~~
afficher le tableau dont le nom est $1 sous forme de lignes
~~~
## `array_to_path`
~~~
afficher le tableau dont le nom est $1 sous forme d'une liste de chemins
séparés par ':')
~~~
## `array_fix_paths`
~~~
Corriger les valeurs du tableau $1. Les valeurs contenant le séparateur
$2(=':') sont séparées en plusieurs valeurs. Par exemple avec le tableau
input=(a b:c), le résultat est input=(a b c)
~~~
## `get_date_rfc822`
## `get_date_fr`
## `get_time_fr`
## `parse_date`
## `udelpath`
~~~
supprimer le chemin $1 de $2(=PATH)
~~~
## `uaddpath`
~~~
Ajouter le chemin $1 à la fin, dans $2(=PATH), s'il n'y existe pas déjà
~~~
## `uinspathm`
~~~
Ajouter le chemin $1 au début, dans $2(=PATH), s'il n'y existe pas déjà
~~~
## `uinspath`
~~~
S'assurer que le chemin $1 soit au début de $2(=PATH)
~~~
## `withpath`
~~~
tester si le chemin est relatif à . ou à .., ou est absolu. i.e 'withpath a/b'
renvoie faux alors que 'withpath ./a/b' renvoie vrai
~~~
## `withext`
~~~
tester si le fichier a une extension
~~~
## `normpath`
~~~
normaliser le chemin $1, qui est soit absolu, soit relatif à $2 (qui vaut
$(pwd) par défaut)
~~~
## `abspath`
~~~
Retourner un chemin absolu vers $1. Si $2 est non nul et si $1 est un chemin
relatif, alors $1 est exprimé par rapport à $2, sinon il est exprimé par
rapport au répertoire courant.
Si le chemin n'existe pas, il n'est PAS normalisé. Sinon, les meilleurs
efforts sont faits pour normaliser le chemin.
~~~
## `parentdirs`
~~~
Obtenir la liste de tous les parents du répertoire $2 dans le tableau $1, du
répertoire $2 vers la racine. Si $3 commence par 'r' (comme reverse), l'ordre
est inversé: le tableau contient les répertoire de la racine vers $2.
~~~
## `ppath`
~~~
Dans un chemin *absolu*, remplacer "$HOME" par "~" et "$(pwd)/" par "", afin
que le chemin soit plus facile à lire. Le répertoire courant est spécifié par
$2 ou $(pwd) si $2 est vide
~~~
## `relpath`
~~~
Afficher le chemin relatif de $1 par rapport à $2. Si $2 n'est pas spécifié,
on prend le répertoire courant. Si $1 ou $2 ne sont pas des chemins absolus,
il sont transformés en chemins absolus par rapport à $3. Si $1==$2, retourner
une chaine vide
~~~
## `relpathx`
~~~
Comme relpath, mais pour un chemin vers un exécutable qu'il faut lancer:
s'assurer qu'il y a une spécification de chemin, e.g. ./script
~~~
## `withinpath`
~~~
Tester si le chemin absolu $2 se trouve dans le chemin absolu "$1" (appelée
barrière). Soit un chemin P, on considère que P est dans P. Si ce comportement
n'est pas souhaité, $3(=N) doit valoir O, auquel cas P est dans Q implique que
P != Q.
~~~
## `safe_abspath`
~~~
Afficher le chemin absolu de $1, par rapport à $2, si et seulement si le
chemin résultat ne se trouve pas en dehors de la barrière $3. Si $2 n'est pas
spécifié, prendre le répertoire courant. S'il est relatif, l'exprimer par
rapport au répertoire courant. Si $3 est relatif, l'exprimer par rapport à $2.
Si le chemin résultat est sité en dehors de la barrière, ne rien afficher et
retourner un code d'erreur.
Si le chemin $1 n'existe pas, il n'est PAS normalisé. Sinon, les meilleurs
efforts sont faits pour normaliser le chemin résultat.
~~~
## `safe_relpath`
~~~
Afficher le chemin relatif de $1 par rapport à $2 si et seulement si le chemin
résultat ne se trouve pas en dehors de la barrière $3. Si $2 n'est pas
spécifié, prendre le répertoire courant. S'il est relatif, l'exprimer par
rapport au répertoire courant. Si $3 est relatif, l'exprimer par rapport à $2.
Si le chemin résultat est sité en dehors de la barrière, ne rien afficher et
retourner un code d'erreur.
~~~
## `splitwcs`
~~~
Découper un nom de chemin $1 entre la partie sans wildcards, qui est placée dans
la variables $2(=basedir), et la partie avec wildcards, qui est placée dans la
variable $3(=filespec)
~~~
## `deref`
~~~
Retourner un chemin absolu vers le fichier $1, dans lequel toutes les
composantes "lien symbolique" ont été supprimées.
DEPRECATED: Cette fonction est dépréciée. Utiliser à la place readlinkm()
~~~
## `readlinka`
~~~
Afficher un chemin absolu vers la destination du fichier $1. Si $1 n'est pas
un lien, afficher simplement le chemin du fichier
~~~
## `readlinkm`
~~~
Retourner un chemin absolu vers le fichier $1, dans lequel toutes les
composantes "lien symbolique" ont été supprimées. Il n'est pas requis que les
composantes du chemin existent.
~~~
## `path_if_test`
~~~
afficher un chemin si le fichier $2 existe (en utilisant l'opérateur $1) dans
l'un des chemins absolus $4..n. si $3==relative, afficher le chemin relatif,
sinon le chemin absolu. note: $3 peut être de la forme relative:path, auquel
cas le chemin affiché est exprimé relativement à path
~~~
## `update_link`
~~~
mettre à jour le lien $2 pour qu'il pointe vers le fichier $1
~~~
## `update_links`
~~~
Mettre à jour les liens $2..@ pour qu'ils pointent vers la nouvelle
destination $1
~~~
## `move_link`
~~~
Déplacer le lien $1 vers $2, et mettre à jour la destination du lien si
elle est exprimée de façon relative
Si $1 n'est pas un lien, le déplacer normalement avec mv
~~~
## `copy_link`
~~~
Copier le lien $1 vers $2, et mettre à jour la destination du lien si
elle est exprimée de façon relative
Si $1 n'est pas un lien, le copier normalement avec cp
~~~
## `array_find_links`
~~~
Chercher dans le répertoire $3 (qui est par défaut le répertoire courant)
les liens vers le fichier $2, et ajouter leurs chemins absolus dans le
tableau $1
~~~
## `list_links`
~~~
Chercher dans le répertoire $2 les liens vers le fichier $1, et les
afficher, un par ligne.
~~~
## `move_file`
~~~
Déplacer le fichier $1 vers $2, et mettre à jour les liens $3..@ pour
qu'ils pointent vers la nouvelle destination
~~~
## `get_nblines`
~~~
Afficher le nombre de lignes d'un fichier
~~~
## `mktempf`
~~~
générer un fichier temporaire et retourner son nom
~~~
## `mktempd`
~~~
générer un répertoire temporaire et retourner son nom
~~~
## `mkdirof`
~~~
Créer le répertoire correspondant à un fichier
~~~
## `cp_a`
~~~
copier des fichiers en gardant le maximum de propriétés
~~~
## `cp_R`
~~~
copier des fichiers récursivement, en suivant les liens symboliques
~~~
## `quietgrep`
~~~
tester la présence d'un pattern dans un fichier
~~~
## `quietdiff`
~~~
tester si deux fichiers sont identiques
~~~
## `testsame`
~~~
tester si deux fichiers sont identiques/différents
~~~
## `testdiff`
## `testupdated`
~~~
test si $2 n'existe pas ou si $1 est différent de $2
~~~
## `testnewer`
~~~
test si $2 n'existe pas ou si $1 est plus récent que $2
~~~
## `ps_all`
~~~
afficher tous les processus avec le maximum d'informations
~~~
## `progexists`
~~~
tester l'existence d'un programme dans le PATH
~~~
## `has_python`
~~~
tester la présence de python
~~~
## `has_gawk`
~~~
tester la présence de gnuawk
~~~
## `is_root`
~~~
tester si on est root
~~~
## `source_ifexists`
~~~
sourcer un fichier s'il existe
~~~
## `is_running`
~~~
tester si un programme dont on donne le PID tourne
~~~
## `sedi`
~~~
Lancer sed sur un fichier en le modifiant en place
~~~
## `csort`
~~~
Lancer sort avec LANG=C pour éviter les problèmes avec la locale. en effet,
avec LANG!=C, sort utilise les règles de la locale pour le tri, et par
exemple, avec LANG=fr_FR.UTF-8, la locale indique que les ponctuations doivent
être ignorées.
~~~
## `lsort`
## `cgrep`
~~~
Lancer grep avec LANG=C pour éviter les problèmes avec la locale. cf csort
pour une explication.
~~~
## `lgrep`
## `csed`
~~~
Lancer sed avec LANG=C pour éviter les problèmes avec la locale. cf csort pour
une explication.
~~~
## `lsed`
## `cawk`
~~~
Lancer awk avec LANG=C pour éviter les problèmes avec la locale. cf csort pour
une explication.
~~~
## `lawk`
## `cdiff`
~~~
Lancer diff avec LANG=C pour éviter les problèmes avec la locale. cf csort
pour une explication.
~~~
## `ldiff`
## `fix_mode`
~~~
Si le fichier $1 n'est pas writable, le rendre writable temporairement. Si
nécessaire, le fichier est créé.
Cette fonction s'utilise de cette façon:
mode="$(fix_mode file)"
...
unfix_mode file "$mode"
~~~
## `unfix_mode`
~~~
Restaurer le mode $2 du fichier $1 traité par fix_mode
~~~
## `get_mode`
~~~
Obtenir le mode du fichier $1, en le créant si nécessaire. A utiliser avec
unfix_mode pour restaurer le mode d'un fichier qui a été traité avec un
fichier temporaire intermédiaire
~~~
## `rm_maybe`
~~~
Supprimer les fichiers dont on donne la liste. Si aucun fichier n'est
spécifié, cette fonction est un NOP
~~~
## `cpdir`
~~~
copier un fichier dans un répertoire, ou le contenu d'un répertoire dans un
autre répertoire, que le répertoire source soit un lien symbolique ou
non. Cette fonction existe parce que le comportement de "cp_a src dest" n'est
pas consistant selon les plateformes, surtout si src est un lien symbolique
sur un répertoire: parfois on copie le lien, parfois on copie le contenu du
répertoire, parfois on copie le répertoire...
La copie est faite avec rsync si possible. Les options du tableau
__CPDIR_RSYNC_ARGS sont rajoutées aux options standard de rsync.
~~~
## `cpnovcs`
~~~
copier le fichier/répertoire $1 *dans* le *répertoire* $2 avec rsync. Les
options du tableau __CPNOVCS_RSYNC_ARGS sont rajoutées aux options standard
de rsync.
Si $1 est un répertoire, la copie est faite en ignorant les sous-répertoires
de VCS (.svn, CVS). En ce qui concerne les répertoire de VCS, git aussi est
supporté, mais uniquement s'il est à la racine du transfert.
Si $1 se termine par un '/', c'est le contenu du répertoire qui est copié, pas
le répertoire lui-même. Si rsync n'est pas trouvé sur le système, alors on
fait une copie standard qui inclue les répertoires de VCS.
~~~
## `cpvcs`
~~~
comme cpnovcs, mais ne pas ignorer les répertoires de VCS
~~~
## `cpdirnovcs`
~~~
Le pendant de cpdir, mais en ignorant les sous-répertoires de VCS: copier le
contenu du répertoire $1 dans le répertoire $2
~~~
## `doinplace`
~~~
Filtrer le fichier $1 à travers la commande $2..$*, puis remplacer le fichier
s'il n'y a pas eu d'erreur. Retourner le code d'erreur de la commande. Si $1
n'est pas spécifié ou vaut -, filtrer l'entrée standard vers la sortie
standard.
La variante doinplacef remplace le fichier quelque soit le code de retour de
la commande. A utiliser avec des commandes comme grep qui peuvent retourner
FAUX s'ils ne trouvent pas le motif
~~~
## `doinplacef`
## `stripnl`
~~~
Supprimer les caractères de fin de ligne de la chaine en entrée
~~~
## `nl2lf`
## `nl2crlf`
## `nl2cr`
## `list_all`
~~~
Lister les fichiers ou répertoires du répertoire $1, un par ligne
Les répertoires . et .. sont enlevés de la liste
$1=un répertoire dont le contenu doit être listé
$2..@=un ensemble de patterns pour le listage
~~~
## `list_files`
~~~
Lister les fichiers du répertoire $1, un par ligne
$1=un répertoire dont le contenu doit être listé.
$2..@=un ensemble de patterns pour le listage
~~~
## `list_dirs`
~~~
Lister les répertoires du répertoire $1, un par ligne
Les répertoires . et .. sont enlevés de la liste
$1=un répertoire dont le contenu doit être listé.
$2..@=un ensemble de patterns pour le listage
~~~
## `array_lsall`
~~~
Lister les fichiers avec `list_all $2 $3...`, et les mettre dans le
tableau $1. Le tableau contient les chemins complets, par seulement les
noms comme avec list_all
~~~
## `array_lsdirs`
~~~
Lister les fichiers avec `list_dirs $2 $3...`, et les mettre dans le
tableau $1. Le tableau contient les chemins complets, par seulement les
noms comme avec list_dirs
~~~
## `array_lsfiles`
~~~
Lister les fichiers avec `list_files $2 $3...`, et les mettre dans le
tableau $1. Le tableau contient les chemins complets, par seulement les
noms comme avec list_files
~~~
## `filter_empty`
~~~
Filtrer l'entrée standard en enlevant les lignes vides
~~~
## `filter_vcspath`
~~~
L'entrée standard étant une liste de chemins, filtrer les fichiers et
répertoire qui ont un rapport avec subversion ou git
~~~
## `merge_contlines`
~~~
Avec les lignes lues sur stdin, fusionner celles qui se terminent par \ avec
les suivantes.
~~~
## `filter_comment`
~~~
Filtrer un fichier de configuration lu sur stdin en enlevant les commentaires
et les lignes vides.
Avec $1==-m, fusionner les lignes qui se terminent par \ avec les suivantes
Comme filter_conf(), les commentaires doivent être sur une ligne à part.
Contrairement à filter_conf, il n'est pas nécessaire que le caractère '#' soit
en début de ligne: il peut apparaitre après des espaces et des tabulations. De
même, une ligne qui ne contient que des espaces et des tabulations est
considérée comme vide.
~~~
## `filter_conf`
~~~
filtrer un fichier de configuration lu sur stdin en enlevant les commentaires
et les lignes vides. Une ligne n'est considérée commentaire que si '#' est un
première position. Utiliser filter_comment() si les commentaire peuvent
commencer par des caractères espace et tabulation.
Si $1==-m, fusionner les lignes qui se terminent par \ avec les suivantes
~~~
## `is_archive`
~~~
tester si l'extension d'un fichier indique que c'est une archive
~~~
## `extract_archive`
~~~
Extraire le contenu de l'archive $1 dans le répertoire ${2:-.}
~~~
## `get_archive_basename`
~~~
Obtenir le nom de base de l'archive $1
~~~
## `get_archive_appname`
~~~
Obtenir le nom probable de l'application ou du framework contenu dans
l'archive $1, e.g:
get_archive_versionsuffix app-0.1.tgz
--> app
~~~
## `get_archive_versionsuffix`
~~~
Obtenir la valeur probable de la version de l'application ou du framework
contenu dans l'archive $1, avec le caractère de séparation, e.g:
get_archive_versionsuffix app-0.1.tgz
--> -0.1
~~~
## `get_archive_version`
~~~
Obtenir la valeur probable de la version de l'application ou du framework
contenu dans l'archive $1, e.g:
get_archive_versionsuffix app-0.1.tgz
--> 0.1
~~~
## `dump_usernames`
~~~
Placer dans le tableau $1 la liste des utilisateurs du système
Cette implémentation consulte /etc/passwd et liste tous les utilisateurs dont
le homedir se trouve dans /home, et dont l'uid est >=500
~~~
## `resolv_ips`
~~~
Placer dans le tableau $1(=ips) la liste des adresses ip correspondant à
l'hôte $2. La résolution est effectuée avec la commande host.
~~~
## `resolv_hosts`
~~~
Placer dans le tableau $1(=hosts) la liste des hôtes correspondant à
l'adresse ip $2. La résolution est effectuée avec la commande host.
~~~
## `runscript_as`
~~~
Utiliser bash pour lancer le script $2 avec les arguments $3..$n afin qu'il
tourne avec les droits d'un autre user $1(=root). Si $2=exec, utiliser exec
pour lancer le script et ses arguments qui commencent à partir de $3, ce qui
fait que cette fonction ne retourne pas.
Attention! cette fonction ne teste pas avec si on est déjà le user $1. Il y a
donc un risque de boucle infinie si on ne teste pas le user courant.
~~~
## `runscript_as_root`
~~~
Utiliser bash pour lancer le script $1 avec les arguments $2..$* avec les
droits de root. Si on est déjà en root, le script est simplement lancé. Sinon,
utiliser runscript_as pour lancer le script avec les droits de root.
~~~
## `run_as`
~~~
Relancer le script courant afin qu'il tourne avec les droits d'un autre user
$1(=root)
Attention! cette fonction ne teste pas avec si on est déjà ce user. Il y a
donc un risque de boucle infinie si on ne teste pas le user courant.
Il faut lancer cette fonction avec les arguments du script en cours. Par
exemple::
run_as root "$@"
Si $2=--noexec, on n'utilise pas la fonction exec, ce qui fait que la fonction
retourne. Sinon, on peut considérer que cette fonction ne retourne jamais
~~~
## `run_as_root`
~~~
relancer le script courant afin qu'il tourne en root si on est pas en déjà
root. Sinon, cette fonction est un nop.
~~~
## `check_user`
~~~
Vérifier si le user courant est l'un des users $1..*
~~~
## `ensure_user`
~~~
Vérifier si le user courant est l'un des users $1..N où N est la position du
premier "--". Si ce n'est pas le cas et que l'on est root, relancer le script
avec ce user grâce à la fonction run_as()
Retourner 1 si ce n'était pas le bon user. Retourner 10 si ce n'était pas le
bon user et que l'on n'est pas root (donc impossible à priori de relancer le
script avec le bon user). Retourner 11 si l'utilisateur a choisi de ne pas
lancer le script avec le bon utilisateur
A utiliser de cette manière:
if ensure_user users... -- args; then
# ... on est avec le bon user; faire les opérations
else
# ... ce code n'est exécuté que si une erreur s'est produite, ou si ce
# n'était pas le bon user et que l'option --noexec est utilisée
fi
~~~
## `check_hostname`
~~~
Vérifier si le hostname courant est l'un des hôtes $1..*
localhost matche toujours
~~~
## `check_userhostname`
~~~
Vérifier si le hostname et éventuellement le user courant sont l'un des
arguments $1..*
Chaque argument est de la forme [user@]host, mais le test ne tient compte que
du nom de l'hôte, sans tenir compte du domaine. Si le user n'est pas spécifié,
le test ne porte que sur hostname.
~~~
## `ensure_hostname`
~~~
Vérifier si le hostname et le user courant sont l'un des arguments $1..*
Chaque argument est de la forme [user@]host, mais le test ne tient compte que
du nom de l'hôte, sans tenir compte du domaine.
Si user est spécifié:
- Si on est sur le bon hôte mais pas le bon user, ensure_user est lancé avec
l'argument approprié pour relancer le script
Si l'argument était de la forme userhost:path, le répertoire courant est
changé avant de lancer le script avec le bon utilisateur.
Sinon (si user n'est pas spécifié):
- Si on n'est pas sur le bon hôte, après confirmation le script est lancé avec
ssh sur l'hôte distant avec le user spécifié (qui vaut par défaut root). Ce
script DOIT exister sur l'hôte distant avec le même chemin.
Si l'argument était de la forme userhost:path, le répertoire courant distant
est changé avant de lancer le script
Si on est avec le bon user sur le bon hôte, le répertoire courant n'est jamais
changé.
Retourner 1 si ce n'était pas le bon user. Retourner 10 si ce n'était pas le
bon user et que l'on n'est pas root (donc impossible à priori de relancer le
script avec le bon user). Retourner 11 si l'utilisateur a choisi de ne pas
lancer le script sur l'hôte distant. Retourner 12 si une erreur s'est produite
avec ssh.
A utiliser de cette manière:
if ensure_hostname user@host... -- args; then
# ... on est [avec le bon user] sur le bon hôte; faire les opérations
else
# ... ce code n'est exécuté que si une erreur s'est produite, ou si ce
# n'était pas le bon user et que l'option --noexec est utilisée
fi
~~~
## `sqvals`
## `quoted_values`
## `formatcsv`
## `awkdef`
~~~
Afficher un script à insérer au début d'un script awk. Ce script définit dans
une section BEGIN{} les variables donnés en arguments, et avec l'option -f,
des fonctions utiles. Si une valeur ne ressemble pas à une définition de
variable, l'analyse des variables s'arrête et le reste des arguments est
inséré tel quel. Cette fonction peut être utilisée de cette manière:
awk "$(awkdef -f var=value... 'script awk')"
Normalement, les variables définies sont scalaires, avec une syntaxe de la
forme var[:type]=value. type peut valoir str ou int, pour forcer le type de la
variable créée dans awk.
Il est possible d'utiliser la syntaxe awk_array[@]=bash_array ou array[@] (qui
est équivalente à array[@]=array) pour initialiser le tableau awk_array, qui
contiendra toute les valeurs du tableau nommé bash_array, avec les indices de
1 à N, N étant le nombre d'éléments du tableau bash_array. La variable
awk_array_count est aussi initialisée, et contient le nombre d'éléments du
tableau
La syntaxe "awk_array[@]=<\n..." permet de spécifier les valeurs du tableau,
une par ligne, e.g:
$'values[@]=<\nvalue1\nvalue2'
pour un tableau values qui contiendra deux valeurs: value1 et value2
Avec l'option -f, des fonctions supplémentaires sont définies. Elles sont
décrites dans le module awk.
~~~
## `lawkrun`
~~~
wrapper pour lancer awk avec un script préparé par awkdef. Les définitions et
les arguments sont séparés par --, e.g.
awkrun var0=value0 var1=value1 script -- input0 input1
~~~
## `cawkrun`
## `awkrun`
## `lf_trylock`
~~~
USAGE
lf_trylock [-h max_hours] /path/to/lockfile
OPTIONS
lockfile
fichier qui doit contenir le verrou
-h max_hours
Nombre d'heures (par défaut 4) au bout duquel afficher stale
Sinon, afficher locked
Retourne 0 si le verrou a été placé correctement. Il ne faut pas oublier de
supprimer le fichier. Le mieux est de le faire supprimer automatiquement par
autoclean:
lockfile=...
case "$(lf_trylock "$lockfile")" in
locked) ...;;
stale) ...;;
esac
autoclean "$lockfile"
Sinon, retourner 1 et afficher l'une des deux valeurs suivantes:
- stale si le verrou a déjà été placé, depuis au moins max_hours heures
- locked si le verrou a déjà été placé
- retry si une erreur s'est produite pendant la pose du verrou ou sa
lecture. Cela peut se produire si les droits ne sont pas suffisants pour
écrire dans le répertoire destination, ou si le fichier a été supprimé
avant sa lecture (race-condition). Dans ce dernier cas, reessayer permettra
d'acquérir le verrou
~~~
## `pidfile_set`
~~~
USAGE
pidfile_set [-p pid] /path/to/pidfile
OPTIONS
pidfile
fichier qui doit contenir le pid du script
-p pid
spécifier le pid. par défaut, utiliser $$
-r  si pidfile existe mais que le processus ne tourne plus, faire
comme si le fichier n'existe pas.
Retourner 0 si le pid a été correctement écrit dans le fichier. Ce fichier
sera supprimé automatiquement en fin de script
Retourner 1 si le fichier existe déjà et que le processus est en train de
tourner.
Retourner 2 si le fichier existe déjà mais que le processus ne tourne plus.
Retourner 10 si autre erreur grave s'est produite (par exemple, s'il manque le
chemin vers pidfile, ou si le fichier n'est pas accessible en écriture.)
~~~
## `pidfile_check`
~~~
USAGE
pidfile_check /path/to/pidfile
OPTIONS
pidfile
fichier qui doit contenir le pid d'un processus
Cette fonction permet de vérifier si le processus associé à un fichier de pid
est en train de tourner.
Retourner 0 si le fichier de pid existe et que le process du pid spécifié est
en train de tourner. Retourner 1 sinon.
Retourner 10 si erreur grave s'est produite (par exemple, s'il manque le
chemin vers pidfile, ou si le fichier n'est pas accessible en lecture.)
~~~
## `page_maybe`
~~~
Utiliser less, si possible, pour afficher le flux en entrée. Si le terminal
n'est pas interactif ou si le nombre de lignes en entrée est inférieur au
nombre de lignes du terminal, afficher simplement le flux.
Les arguments de cette fonction sont passés à less
~~~
## `utools_local`
~~~
Afficher les commandes pour rendre locales certaines variables en fonction des
arguments:
- opts rend locale args, pour utiliser parse_opts() à l'intérieur d'une
fonction.
- verbosity et interaction rendent respectivement locales __verbosity et
__interaction. Ceci est utile pour pouvoir appeler sans risque de pollution
de l'environnement une fonction qui utilise parse_opts() avec les
définitions de PRETTYOPTS.
Si aucun arguments n'est fourni, toutes les définitions sont affichées.
~~~
## `stdredir`
~~~
Lancer la commande $4..@ en redirigeant stdin depuis $1, stdout vers $2,
stderr vers $3. Si $1 est vide ou vaut /dev/stdin, la redirection n'est
pas faite. Si $2 est vide ou vaut /dev/stdout, la redirection n'est pas
faite. Si $3 est vide ou vaut /dev/stderr, la redirection n'est pas faite.
Cette fonction existe parce que sur certaines versions de bash, il semble
que les redirections /dev/std* ne sont pas traitées de façon particulière.
De plus, sur des technologies telles que OpenVZ, les chemins /dev/std* ne
sont pas créés (parce que /proc/self/fd/* n'est pas accessible). Donc,
dans de rares cas où le script tourne sur OpenVZ avec une version de bash
qui est buggée, la redirection n'est pas faite correctement.
~~~
## `isatty`
~~~
tester si STDOUT n'est pas une redirection
~~~
## `in_isatty`
~~~
tester si STDIN n'est pas une redirection
~~~
## `out_isatty`
~~~
tester si STDOUT n'est pas une redirection
~~~
## `err_isatty`
~~~
tester si STDERR n'est pas une redirection
~~~
## `die`
## `die_unless`
~~~
Afficher $-1 et quitter le script avec die() si la commande $1..-2 retourne
FAUX
~~~
## `eerror_unless`
~~~
Afficher $-1 avec eerror() et retourner $? si la commande $1..-2 retourne FAUX
~~~
## `die_if`
~~~
Afficher $-1 et quitter le script avec die() si la commande $1..-2 retourne
VRAI
~~~
## `eerror_if`
~~~
Afficher $-1 avec eerror() et retourner le code d'erreur 1 si la commande
$1..-2 retourne VRAI
~~~
## `noerror`
~~~
lancer la commande "$@" et masquer son code de retour
~~~
## `noout`
~~~
lancer la commande "$@" en supprimant sa sortie standard
~~~
## `noerr`
~~~
lancer la commande "$@" en supprimant sa sortie d'erreur
~~~
## `tooenc`
~~~
Transformer la valeur $1 de l'encoding $2(=$OENC) vers l'encoding de sortie
$3=($UTOOLS_OUTPUT_ENCODING)
~~~
## `uecho`
## `tooenc_`
~~~
Transformer la valeur $1 de l'encoding $2(=$OENC) vers l'encoding de sortie
$3=($UTOOLS_OUTPUT_ENCODING)
~~~
## `uecho_`
## `toienc`
~~~
Transformer la valeur $1 de $2(=$IENC) vers l'encoding d'entrée
$3(=$UTOOLS_INPUT_ENCODING)
~~~
## `uread`
~~~
Lire une valeur sur stdin et la placer dans la variable $1. On assume que la
valeur en entrée est encodée dans l'encoding d'entrée par défaut
~~~
## `stooenc`
~~~
Transformer la valeur lue sur stdin de $OENC vers l'encoding de sortie par
défaut ($UTOOLS_OUTPUT_ENCODING)
~~~
## `stoienc`
~~~
Transformer la valeur lue sur stdin de $IENC vers l'encoding d'entrée par
défaut ($UTOOLS_INPUT_ENCODING)
~~~
## `elogto`
~~~
Activer UTOOLS_EDATE et rediriger STDOUT et STDERR vers le fichier $1
Si deux fichiers sont spécifiés, rediriger STDOUT vers $1 et STDERR vers $2
Si aucun fichier n'est spécifié, ne pas faire de redirection
Si la redirection est activée, forcer l'utilisation de l'encoding UTF8
Si UTOOLS_ELOG_OVERWRITE=1, alors le fichier en sortie est écrasé. Sinon, les
lignes en sortie lui sont ajoutées
~~~
## `set_verbosity`
## `set_interaction`
## `show_error`
~~~
tester respectivement si on doit afficher les messages d'erreur,
d'avertissement, d'information, de debug
~~~
## `show_warn`
## `show_info`
## `show_verbose`
## `show_debug`
## `check_verbosity`
## `get_verbosity_option`
## `check_interaction`
## `is_interaction`
## `get_interaction_option`
## `eflush`
~~~
Afficher les messages en attente
~~~
## `eclearp`
~~~
Supprimer les message en attente
~~~
## `eerror`
~~~
Afficher un message d'erreur
~~~
## `ewarn`
~~~
Afficher un message d'avertissement
~~~
## `enote`
~~~
Afficher un message d'information de même niveau qu'un avertissement
~~~
## `ebanner`
~~~
Afficher un message très important encadré, puis attendre 5 secondes
~~~
## `eimportant`
~~~
Afficher un message très important
~~~
## `eattention`
~~~
Afficher un message important
~~~
## `einfo`
~~~
Afficher un message d'information
~~~
## `eecho`
~~~
Afficher un message d'information sans préfixe
~~~
## `eecho_`
## `edebug`
~~~
Afficher un message de debug
~~~
## `trace`
~~~
Afficher la commande $1..@, la lancer, puis afficher son code d'erreur si une
erreur se produit
~~~
## `trace_error`
~~~
Lancer la commande $1..@, puis afficher son code d'erreur si une erreur se
produit. La différence avec trace() est que la commande n'est affichée que si
une erreur se produit.
~~~
## `etitle`
~~~
Afficher le titre $1, qui est le début éventuel d'une section. Les section
imbriquées sont affichées indentées. La section n'est pas terminée, et il faut
la terminer explicitement avec eend, sauf dans certains cas précis:
- Si $2..$* est spécifié, c'est une commande. Lancer la commande dans le
contexte de la section. Puis, la section est automatiquement terminée sauf si
l'option -s est spécifiée, auquel cas la section reste ouverte. Si l'option -p
est spécifiée, eclearp() est appelé pour purger les messages en attente
- Dans le cas contraire, l'option -s est ignorée: la section doit toujours
être terminée explicitement.
La fonction etitled() est comme etitle(), mais le titre n'est pas affiché
immédiatement. L'affichage effectif est effectué dès qu'une fonction e* est
utilisée. Ceci permet, avec la fonction eclearp(), de ne pas afficher de titre
pour une section vide.
~~~
## `etitled`
## `estep`
~~~
Afficher la description d'une opération. Cette fonction est particulièrement
appropriée dans le contexte d'un etitle.
Les variantes e (error), w (warning), n (note), i (info) permettent d'afficher
des couleurs différentes, mais toutes sont du niveau info.
~~~
## `estepe`
## `estepw`
## `estepn`
## `estepi`
## `estep_`
## `estepe_`
## `estepw_`
## `estepn_`
## `estepi_`
## `ebegin`
~~~
Afficher le message $1, qui décrit le début d'une opération. Cette fonction
débute une section, qu'il faut terminer avec eend.
Si $2..$* est spécifié, c'est une commande. Lancer la commande dans le
contexte de la section. Puis, la section est terminée automatiquement, sauf si
l'option -s est spécifiée, auquel cas la section reste ouverte.
~~~
## `edot`
~~~
Afficher une étape d'une opération, matérialisée par un point '.' ou une
croix 'x' en cas de succès ou d'erreur. Cette fonction est particulièrement
appropriée dans le contexte d'un ebegin.
~~~
## `edotw`
~~~
Afficher un avertissement comme étape d'une opération, matérialisée par une
lettre 'w' (typiquement de couleur jaune). Cette fonction est particulièrement
appropriée dans le contexte d'un ebegin.
~~~
## `ewait`
~~~
Afficher les étapes d'une opération qui dure, matérialisées par des '+' toutes
les secondes tant que le processus $1 tourne.
A utiliser de cette manière:
ebegin "msg"
cmd &
ewait $!
eend
~~~
## `eend`
~~~
Terminer une section.
Avec l'option -c, remettre à zéro toutes les informations de section
Si la section en cours est un ebegin, afficher la fin de l'opération: [ok] ou
[error] en fonction du code de retour de la dernière commande (ou de $1 si
cette valeur est donnée)
Si la section en cours est un etitle, marquer la fin de la section concernée
par le titre.
~~~
## `elinedots`
~~~
Afficher un message comme avec ebegin "$1", puis afficher un point '.' pour
chaque ligne lue sur stdin. Cela permet de suivre une opération. En mode
DEBUG, afficher la ligne affichée plutôt qu'un point.
Si $2..$* sont spécifiés, lancer la commande et suivre sa sortie. Ainsi,
'elinedots msg cmd args' est un raccourci pour 'cmd args | elinedots msg'
~~~
## `ask_yesno`
~~~
Afficher le message $1 suivi de [oN] ou [On] suivant que $2 vaut O ou N, puis
lire la réponse. Retourner 0 si la réponse est vrai, 1 sinon.
Si $1 est une option, elle est utilisée avec check_interaction pour savoir si
on est en mode interactif ou non. A ce moment-là, les valeurs sont décalées
($2=message, $3=default)
Si $2 vaut C, la valeur par défaut est N si on est interactif, O sinon
Si $2 vaut X, la valeur par défaut est O si on est interactif, N sinon
~~~
## `ask_any`
~~~
Afficher le message $1 suivi du texte "[$2]" (qui vaut par défaut +Oq), puis
lire la réponse. Les lettres de la chaine de format $2 sont numérotées de 0 à
$((${#2} - 1)). Le code de retour est le numéro de la lettre qui a été
sélectionnée. Cette fonction est une généralisation de ask_yesno() pour
n'importe quel ensemble de lettres.
La première lettre en majuscule est la lettre sélectionnée par défaut.
La lettre O matche toutes les lettres qui signifient oui: o, y, 1, v, t
La lettre N matche toutes les lettres qui signifient non: n, f, 0
Il y a des raccourcis:
+O --> On
+N --> oN
+C --> oN si on est en mode interactif, On sinon
+X --> On si on est en mode interactifn oN sinon
Si $1 est une option, elle est utilisée avec check_interaction pour savoir si
on est en mode interactif ou non. A ce moment-là, les valeurs sont décalées
($2=message, $3=format)
~~~
## `read_value`
~~~
Afficher le message $1 suivi de la valeur par défaut [$3] si elle est non
vide, puis lire la valeur donnée par l'utilisateur. Cette valeur doit être non
vide si $4(=O) est vrai. La valeur saisie est placée dans la variable
$2(=value)
Si $1 est une option, elle est utilisée avec check_interaction pour savoir si
on est en mode interactif ou non. A ce moment-là, les valeurs sont décalées
($2=message, $3=variable, $4=default, $5=required)
En mode non interactif, c'est la valeur par défaut qui est sélectionnée. Si
l'utilisateur requière que la valeur soit non vide et que la valeur par défaut
est vide, afficher un message d'erreur et retourner faux
read_password() est comme read_value(), mais la valeur saisie n'est pas
affichée, ce qui la rend appropriée pour la lecture d'un mot de passe.
~~~
## `read_password`
## `simple_menu`
~~~
Afficher un menu simple dont les éléments sont les valeurs du tableau
$2(=options). L'option choisie est placée dans la variable $1(=option)
-t TITLE: spécifier le titre du menu
-m YOUR_CHOICE: spécifier le message d'invite pour la sélection de l'option
-d DEFAULT: spécifier l'option par défaut. Par défaut, prendre la valeur
actuelle de la variable $1(=option)
~~~
## `actions_menu`
~~~
Afficher un menu dont les éléments sont les valeurs du tableau $4(=options),
et une liste d'actions tirées du tableau $3(=actions). L'option choisie est
placée dans la variable $2(=option). L'action choisie est placée dans la
variable $1(=action)
Un choix est saisi sous la forme [action]num_option
-t TITLE: spécifier le titre du menu
-m OPT_YOUR_CHOICE: spécifier le message d'invite pour la sélection de
l'action et de l'option
-M ACT_YOUR_CHOICE: spécifier le message d'invite dans le cas où aucune option
n'est disponible. Dans ce cas, seules les actions vides sont possibles.
-e VOID_ACTION: spécifier qu'une action est vide, c'est à dire qu'elle ne
requière pas d'être associée à une option. Par défaut, la dernière action
est classée dans cette catégorie puisque c'est l'action "quitter"
-d DEFAULT_ACTION: choisir l'action par défaut. par défaut, c'est la première
action.
-q QUIT_ACTION: choisir l'option "quitter" qui provoque la sortie du menu sans
choix. par défaut, c'est la dernière action.
-o DEFAULT_OPTION: choisir l'option par défaut. par défaut, prendre la valeur
actuelle de la variable $2(=option)
~~~
## `autoclean`
~~~
Ajouter $1..$n à la liste des fichiers à supprimer à la fin du programme
~~~
## `ac_cleanall`
~~~
Supprimer *tous* les fichiers temporaires gérés par autoclean tout de suite.
~~~
## `ac_clean`
~~~
Supprimer les fichier temporaires $1..$* si et seulement s'ils ont été générés
par ac_set_tmpfile ou ac_set_tmpdir
~~~
## `ac_set_tmpfile`
~~~
Créer un fichier temporaire avec le motif $2, l'ajouter à la liste des
fichiers à supprimer en fin de programme, et mettre sa valeur dans la
variable $1
En mode debug, si ($5 est vide ou ${!5} est une valeur vraie), et si $3 n'est
pas vide, prendre ce fichier au lieu de générer un nouveau fichier
temporaire. Si $4==keep, ne pas écraser le fichier $3 s'il existe.
~~~
## `ac_set_tmpdir`
~~~
Créer un répertoire temporaire avec le motif $2, l'ajouter à la liste des
fichiers à supprimer en fin de programme, et mettre sa valeur dans la
variable $1
En mode debug, si ($4 est vide ou ${!4} est une valeur vraie), et si $3 n'est
pas vide, prendre ce nom de répertoire au lieu de créer un nouveau répertoire
temporaire
~~~
## `debug_tee`
~~~
En mode debug, passer le flux à travers la commande 'tee "$@"'. Sinon, le flux
est passé inchangé.
~~~
## `get_user_defaults_file`
~~~
Afficher le chemin vers le fichier utilisateur à éditer pour qu'il soit chargé
par 'set_defaults $1'. Ce fichier n'existe pas forcément; il faut peut-être le
créer.
~~~
## `get_defaults_files`
~~~
Initialiser le tableau $1(=defaults) avec la liste des fichiers qui seraient
chargés par la commande 'set_defaults $2..N'
~~~
## `set_defaults`
~~~
Pour chaque argument, sourcer /etc/default/$arg *et* (en priorité
~/etc/default.$HOSTNAME/$arg ou à défaut ~/etc/default/$arg) si ceux-ci
existent. *Sinon*, lire $scriptdir/lib/default/$arg si ce fichier existe
~~~
## `myhost`
~~~
Afficher le nom d'hôte pleinement qualifié, en faisant appel à la commande
hostname. Par comparaison, $MYHOST est fourni par bash.
~~~
## `myhostname`
~~~
Afficher le nom d'hôte sans domaine, en faisant appel à la commande
hostname. Par comparaison, $MYHOSTNAME est fourni par bash.
~~~

-*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary