[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 #! /bin/bash 2 3 # NE PAS ÉDITER CE FICHIER !!! 4 5 6 # Voici les appels qui ont un sens pour ce script : 7 # logon xxx yyy zzz 8 # 9 # Avec : 10 # - xxx = "initialisation" ou "ouverture" ou "fermeture" 11 # - yyy = "true" ou "false" pour indiquer s'il doit y avoir tentative 12 # de mise à jour avoir le script distant. 13 # - zzz = "true" ou "false" pour indiquer si le script s'exécute lors d'une 14 # d'une phase d'initialisation qui correspond au démarrage du 15 # système (true) ou non (false). 16 17 18 19 # Le plus tôt possible dans le script, on procède aux redirections 20 # de stdout et de stderr. 21 PHASE="$1" 22 23 REP_SE3_LOCAL="/etc/se3" 24 REP_LOG_LOCAL="$REP_SE3_LOCAL/log" 25 26 # En fonction de l'argument PHASE, on redirige différemment 27 # la sortie standard et la sortie des erreurs du script. 28 case "$PHASE" in 29 30 "initialisation") 31 32 # On cherche d'abord à récupérer le nom absolu du script exécuté. 33 if echo "$0" | grep -q '^/'; then 34 # L'appel du script s'est fait via son nom absolu. 35 nom_absolu_script="$0" 36 else 37 rep=$(dirname "$0") 38 nom=$(basename "$0") 39 nom_absolu_script=$(cd "$rep"; pwd)"/$nom" 40 fi 41 42 # Ici on fait appel à un grep classique car aucune fonction 43 # n'est encore définie à ce stade du script. Mais ce n'est 44 # pas très grave car le motif ici est une chaîne de caractères 45 # sans surprise. 46 if echo "$nom_absolu_script" | grep -q -- "^$REP_SE3_LOCAL"; then 47 # Le script exécuté se trouve dans le répertoire local. 48 exec 1> "$REP_LOG_LOCAL/1.initialisation.log" 2>&1 49 else 50 # Sinon, c'est la version distante qui est exécutée 51 # et il vaut mieux rediriger la sortie dans un autre 52 # fichier, sans quoi le script distant va réécrire 53 # par dessus le log du script local. 54 exec 1> "$REP_LOG_LOCAL/1.initialisation_distant.log" 2>&1 55 fi 56 ;; 57 58 "ouverture") 59 exec 1> "$REP_LOG_LOCAL/2.ouverture.log" 2>&1 60 ;; 61 62 "fermeture") 63 exec 1> "$REP_LOG_LOCAL/3.fermeture.log" 2>&1 64 ;; 65 66 *) 67 # L'argument PHASE est incorrect, on arrête tout. 68 exit 1 69 ;; 70 71 esac 72 73 unset -v nom_absolu_script rep nom 74 75 76 77 78 79 80 81 ### LOGON_PERSO ### 82 83 84 85 86 87 88 ### LOGON_PARAM_FOND_ECRAN ### 89 90 91 92 93 94 95 ############################################################## 96 ############################################################## 97 ### ### 98 ### On passe à la définition de quelques fonctions utiles. ### 99 ### ### 100 ############################################################## 101 ############################################################## 102 103 104 105 # Fonction qui affiche la date du moment. 106 function afficher_date () 107 { 108 LC_ALL="$LOCALE_FRANCAISE" date '+%Y/%m/%d %Hh%Mmn%Ss (%A %d %b)' 109 } 110 111 112 113 # Fonction pour afficher des messages. 114 function afficher () 115 { 116 # On insère la date au niveau de chaque affichage. 117 echo "[$(afficher_date)] $@" # | fmt -w 65 118 } 119 120 121 122 # Cette fonction prend une chaîne en argument et teste si 123 # le nom en argument correspond à un login d'utilisateur local 124 # (c'est-à-dire qui se trouve dans /etc/passwd). Si c'est 125 # le cas la fonction s'exécute correctement en renvoyant 0, 126 # sinon elle renvoie 1. 127 function est_utilisateur_local () 128 { 129 if cat "/etc/passwd" | grep_debut_verbatim "$1:"; then 130 return 0 131 else 132 return 1 133 fi 134 } 135 136 137 138 # Donne la liste des répertoires qui sont point de montage 139 # sur le système. Attention, avec cette sortie, les caractères 140 # un peu spéciaux dans les noms sont exprimés sous la forme 141 # \NNN avec NNN le numéro ASCII du caractère sous la forme 142 # octale. 143 function donner_liste_montages () 144 { 145 cat "/proc/mounts" | cut -d ' ' -f 2 146 } 147 148 149 150 # Fonction qui permet de savoir si un répertoire, avec son chemin absolu, 151 # est bien un point de montage. Si c'est le cas la fonction s'exécute 152 # correctement en renvoyant 0 sinon elle renvoie 1. 153 # Le chemin absolu ne doit pas avoir de « / » à la fin. 154 # Par ailleurs cette commande ne fonctionnera que pour des noms de 155 # répertoires sans espace et sans caractère « spécial » au yeux du 156 # fichier /proc/mounts (par exemple « \ » est un caractère spécial, 157 # qui est représenté par \134 dans le fichier /proc/mounts sachant 158 # que 134 est le numéro ASCII du caractère « \ »). 159 # Mais en vérité je ne saurais donner une définition précise de ce qui 160 # est considéré comme caractère « spécial » dans ce fichier. 161 # Mais ce n'est pas grave car cette fonction devra être appelée avec 162 # en argument un nom de répertoire sans caractère « exotique », 163 # ça fait partie du contrat. Par exemple, la classe de caractères 164 # [-_a-z0-9] est constitué de caractères non spéciaux, il faudra 165 # se limiter à cette classe. 166 # 167 # Remarque : la commande mountpoint aurait pu sembler plus naturelle 168 # pour remplir cette tâche. Mais le souci, c'est que : 169 # 1. Si c'est un montage réseau et si le serveur est inaccessible 170 # alors la commande peut durer un certain temps. 171 # 2. On pourrait ajouter un timeout, mais dans ce cas si la commande 172 # dépasse ce timeout (parce que le serveur est inaccessible), la 173 # valeur de retour est autre que 0 et cela signifie que le 174 # répertoire n'est pas un point de montage alors que c'est 175 # en fait le cas. 176 function est_point_montage () 177 { 178 # $1 est le chemin absolu du répertoire. 179 if donner_liste_montages | grep_debut_fin_verbatim "$1"; then 180 return 0 181 else 182 return 1 183 fi 184 } 185 186 187 188 # Fonction qui supprime le répertoire de montage donné 189 # en argument sous la forme d'un chemin absolu. 190 # Si le répertoire n'existe pas alors la fonction ne fera 191 # rien, et ne provoquera pas d'erreur. 192 function nettoyer_un_rep_montage () 193 { 194 local f 195 local ff 196 f="$1" 197 198 shopt -s dotglob 199 200 for ff in "$f/"*; do 201 [ "$ff" = "$f/*" ] && continue 202 # Si c'est un point de montage (et donc aussi un répertoire), 203 # il faut d'abord procéder au démontage. 204 if est_point_montage "$ff"; then 205 umount "$ff" && rm -rf --one-file-system "$ff" 206 else 207 # Dans tous les autres cas, on peut supprimer directement. 208 rm -rf --one-file-system "$ff" 209 fi 210 done 211 212 # On peut ensuite effacer "$f" qui doit être vide en principe. 213 rm -rf --one-file-system "$f" 214 215 shopt -u dotglob 216 217 } 218 219 220 221 # Fonction qui démonte tous les répertoires (qui se trouvent dans REP_MONTAGE) 222 # de partages des utilisateurs non connectés au système, sans toucher 223 # à REP_NETLOGON. 224 function nettoyer_rep_montage () 225 { 226 local f 227 shopt -s dotglob 228 229 for f in "$REP_MONTAGE/_"*; do 230 # On itère sur tous les fichiers de la forme "$REP_MONTAGE/_xxx". 231 232 # On passe à l'itération suivante si f est égal à REP_NETLOGON 233 # (aucune chance à cause du caractère underscore mais on ne sait 234 # jamais) ou bien si f ne correspond à aucun fichier ce qui est 235 # possible si le * n'attrape rien, ou bien si ce n'est pas un 236 # répertoire. 237 [ "$f" = "$REP_NETLOGON" ] && continue 238 [ "$f" = "$REP_MONTAGE/*" ] && continue 239 [ ! -d "$f" ] && continue 240 241 local n 242 local nom 243 n=$(basename "$f") # "$n" sera de la forme "_xxx" 244 nom="${n#_}" # "$nom" sera de la forme "xxx" 245 246 # Si l'utilisateur est connecté, on passe. 247 est_connecte "$nom" && continue 248 249 # Enfin on efface le contenu du répertoire "$f". 250 nettoyer_un_rep_montage "$f" 251 252 done 253 254 shopt -u dotglob 255 } 256 257 258 259 # Fonction qui vide REP_TMP_LOCAL de son contenu. 260 function nettoyer_rep_tmp_local () 261 { 262 local f 263 shopt -s dotglob 264 for f in "$REP_TMP_LOCAL/"*; do 265 [ "$f" = "$REP_TMP_LOCAL/*" ] && continue 266 rm -rf "$f" 267 done 268 shopt -u dotglob 269 } 270 271 272 273 # Fonction qui efface les homes des utilisateurs non locaux et qui 274 # ne sont pas connectés au système. 275 function nettoyer_rep_home () 276 { 277 # On efface tous les home des utilisateurs non locaux (non connectés). 278 local f 279 shopt -s dotglob 280 for f in "/home/"*; do 281 [ "$f" = "/home/*" ] && continue 282 nom=$(basename "$f") 283 if est_utilisateur_local "$nom"; then 284 # Là, on garde le répertoire car c'est un utilisateur local. 285 true 286 else 287 # Sinon on supprime le home si celui-ci ne correspond pas 288 # à un utilisateur déjà connecté. Par ailleurs, on évite 289 # la suppression de "lost+found" qui est présent quand le 290 # répertoire /home est monté sur une partition séparée. 291 if [ "$nom" != "lost+found" ] && ! est_connecte "$nom"; then 292 # L'option --one-file-system est capitale, car sans cette 293 # option, si un lien symbolique se trouve dans le « /home » 294 # et s'il pointe vers un partage alors le contenu du 295 # partage est tout simplement effacé. 296 rm -fr --one-file-system "$f" 297 fi 298 fi 299 done 300 shopt -u dotglob 301 } 302 303 304 305 # Cette fonction va mettre à jour le profil local afin de 306 # copier le profil distant dans REP_SKEL_LOCAL. A priori, 307 # cette fonction sera appelée si et seulement si le profil 308 # distant a changé de version. 309 function mettre_a_jour_profil () 310 { 311 local version version_local exit_code 312 version=$(cat "$VERSION_SKEL") 313 version_local=$(cat "$VERSION_SKEL_LOCAL") 314 afficher "Mise à jour du profil par défaut local." \ 315 "Le contenu du fichier .VERSION du profil distant est" \ 316 "<citation> $version </citation>." 317 if [ ! -d "$REP_SKEL_LOCAL" ]; then 318 mkdir -p "$REP_SKEL_LOCAL" 319 chown "root:" "$REP_SKEL_LOCAL" 320 fi 321 322 # On oublie cp qui, apparemment, peut planter quand il 323 # fait des copies qui passent par le réseau (ce qui est 324 # le cas ici). Et perso, j'ai constaté ce bug avec un 325 # message du genre « cp: skipping file ... as it was 326 # replaced while being copied ». Ceci étant, je n'ai 327 # pas réussi à reproduire le bug, alors je ne sais plus. 328 #rm -fr --one-file-system "$REP_SKEL_LOCAL" 329 #cp -r "$REP_SKEL" "$REP_SE3_LOCAL" 330 331 # Pas de chose dans le genre « --modify-window=20 » car il 332 # vaut mieux que des copies en trop soient faites plutôt 333 # qu'il y ait certaines copies non faites. 334 # L'option --bwlimit indique une limite de téléchargement 335 # en KiloBytes/s. Ici on a 2048 KB/s soit 2 Mo/s. 336 if rsync -rtxh --links --delete --bwlimit=2048 "$REP_SKEL" "$REP_SE3_LOCAL" 337 then 338 # La commande rsync s'est bien passée. 339 exit_code=0 340 else 341 sleep 0.5 342 # La commande rsync a planté, il faut remettre le fichier 343 # .VERISON local dans son état initial. 344 exit_code=1 345 cat "$version_local" > "$VERSION_SKEL_LOCAL" 346 fi 347 348 chown -R "root:" "$REP_SKEL_LOCAL" 349 # On met des droits cohérents sur les fichiers et les répertoires. 350 find "$REP_SKEL_LOCAL" -type f -exec chmod u=rw,g=rw,o='',u-s,g-s,o-t '{}' \; 351 find "$REP_SKEL_LOCAL" -type d -exec chmod u=rwx,g=rwx,o='',u-s,g-s,o-t '{}' \; 352 sync 353 354 return "$exit_code" 355 } 356 357 358 359 # Met à jour le script de logon local. A priori cette fonction sera 360 # appelée si et seulement le script de logon local est différent (au 361 # sens de la commande diff) de la version distante sur le serveur. 362 function mettre_a_jour_logon () 363 { 364 if [ ! -d "$REP_BIN_LOCAL" ]; then 365 mkdir -p "$REP_BIN_LOCAL" 366 chown "root:" "$REP_BIN_LOCAL" 367 chmod "700" "$REP_BIN_LOCAL" 368 fi 369 370 # On met à jour le script de logon en lançant une tâche en arrière plan. 371 afficher "Le déroulement de la mise à jour du script de logon sera écrit" \ 372 "dans le fichier \"0.maj_logon.log\"." 373 { 374 afficher_date 375 376 # On attend que le script local ne soit lu par aucun processus 377 # afin qu'il soit disponible pour être réécrit. 378 local compteur 379 compteur="1" 380 while fuser "$LOGON_SCRIPT_LOCAL" >/dev/null 2>&1; do 381 sleep 0.5 382 if [ "$compteur" -ge "40" ]; then 383 # Au bout de 40 x 0.5 = 20 secondes on abandonne la mise à jour. 384 afficher "Mise à jour du script de logon local abandonnée" \ 385 "car celui-ci semble toujours lu par un processus" \ 386 "alors que le temps d'attente maximum est dépassé." 387 return 1 388 fi 389 compteur=$((compteur+1)) 390 done 391 392 # On crée une sauvegarde de la version locale du script de logon. 393 if cp -a "$LOGON_SCRIPT_LOCAL" "$LOGON_SCRIPT_LOCAL.SAVE" && \ 394 diff -q "$LOGON_SCRIPT_LOCAL" "$LOGON_SCRIPT_LOCAL.SAVE" >/dev/null 2>&1 395 then 396 # On a une sauvegarde de la version locale qui est fiable. 397 # On peut alors tenter la mise à jour du script de logon local. 398 # Une dernière fois, on vérifie que le script local est 399 # bien disponible, juste avant de le réécrire. 400 if ! fuser "$LOGON_SCRIPT_LOCAL" >/dev/null 2>&1 && \ 401 cp "$LOGON_SCRIPT" "$LOGON_SCRIPT_LOCAL" && \ 402 diff -q "$LOGON_SCRIPT" "$LOGON_SCRIPT_LOCAL" >/dev/null 2>&1 403 then 404 # La mise à jour a fonctionné. 405 chown "root:" "$LOGON_SCRIPT_LOCAL" 406 chmod "700" "$LOGON_SCRIPT_LOCAL" 407 afficher "Mise à jour du script de logon local réussie." 408 [ -e "$LOGON_SCRIPT_LOCAL.SAVE" ] && rm -f "$LOGON_SCRIPT_LOCAL.SAVE" 409 return 0 410 else 411 # La mise à jour n'a pas fonctionné, il faut alors 412 # restaurer la sauvegarde. 413 [ -e "$LOGON_SCRIPT_LOCAL" ] && rm -f "$LOGON_SCRIPT_LOCAL" 414 mv "$LOGON_SCRIPT_LOCAL.SAVE" "$LOGON_SCRIPT_LOCAL" 415 chown "root:" "$LOGON_SCRIPT_LOCAL" 416 chmod "700" "$LOGON_SCRIPT_LOCAL" 417 afficher "La mise à jour du script de logon local a échoué." \ 418 "La version locale actuelle a été restaurée en attendant" \ 419 "une prochaine tentative de mise à jour." 420 return 1 421 fi 422 else 423 # Si la création de la sauvegarde de la version locale a échoué 424 # alors on supprime la sauvegarde si elle existe et on ne fait 425 # plus rien. 426 [ -e "$LOGON_SCRIPT_LOCAL.SAVE" ] && rm -f "$LOGON_SCRIPT_LOCAL.SAVE" 427 afficher "Erreur lors de sauvegarde de la version locale du" \ 428 "script de logon. Pas de mise à jour de script." 429 return 1 430 fi 431 } > "$REP_LOG_LOCAL/0.maj_logon.log" 2>&1 & 432 # Tout ça se fait en arrière plan pour que le script continue son exécution. 433 # On ne sait pas vraiment à quel moment cette tâche en arrière 434 # plan va se lancer donc il vaut mieux rediriger la sortie 435 # standard et la sortie des erreurs vers un fichier à part. 436 } 437 438 439 440 # Cette fonction crée un lien symbolique "/le/lien_symb" qui pointe vers un 441 # répertoire "/le/rep" et fait de "user" le propriétaire de ce fichier lien 442 # symbolique. 443 # creer_lien_symb "/le/rep" "/le/lien_symb" "user" 444 function creer_lien_symb () 445 { 446 # $1 est le répertoire vers lequel pointe le lien. 447 # $2 est le chemin absolu du fichier lien symbolique. 448 # $3 est le propriétaire du fichier lien symbolique. 449 ln -s "$1" "$2" 450 # L'option permet de changer les propriétaires 451 # sur le lien symbolique lui-même car par défaut 452 # sinon c'est un changement sur la cible qui s'opère. 453 chown --no-dereference "$3:" "$2" 454 } 455 456 457 458 # Cette fonction tente de monter REP_NETLOGON s'il ne l'est 459 # pas déjà et renvoie 0 si ça marche, 1 sinon. 460 function monter_netlogon () 461 { 462 local n 463 local c 464 465 n=$(donner_liste_montages | grep -c -- "^$REP_NETLOGON$") 466 c="1" 467 468 # Si n >= 1, le montage est fait, mais ce n'est pas pour autant qu'il 469 # est valide. J'ai déjà vu des cas comme ça. On va donc vérifier 470 # que le script de logon distant (par exemple) est bien lisible. 471 if [ "$n" -ge 1 ]; then 472 if ! timeout "--signal=SIGTERM" 2s test -r "$LOGON_SCRIPT"; then 473 # Le montage est incorrect car le fichier de logon distant 474 # n'est pas accessible. Du coup, on démonte netlogon pour 475 # repartir sur de nouvelles bases et retenter un montage 476 # ci-dessous. 477 while [ ! "$n" -eq 0 ]; do 478 # Pas de timeout nécessaire car en principe un umount est 479 # instantané quel que soit l'état du serveur de partages. 480 umount "$REP_NETLOGON" 481 sleep 0.25 # On ne sait jamais. 482 n=$(donner_liste_montages | grep -c -- "^$REP_NETLOGON$") 483 done 484 fi 485 fi 486 487 while [ ! "$n" -eq 1 ] && [ "$c" -le 4 ] ; do 488 if [ "$n" -eq 0 ]; then 489 timeout "--signal=SIGTERM" 2s \ 490 mount -t cifs "$CHEMIN_PARTAGE_NETLOGON" "$REP_NETLOGON" -o ro,guest,"$OPTIONS_MOUNT_CIFS_BASE" 491 else 492 # différent de 1 et de 0, ça veut dire que n > 1. 493 # Cas qui ne devrait pas se produire, mais sait-on jamais. 494 # Ici il faut démonter une fois REP_NETLOGON. 495 umount "$REP_NETLOGON" 496 fi 497 sleep 0.5 498 n=$(donner_liste_montages | grep -c -- "^$REP_NETLOGON$") 499 c=$((c+1)) 500 done 501 502 if [ "$n" -eq 1 ]; then 503 # Montage réussi. 504 return 0 505 else 506 # Montage pas réussi 507 return 1 508 fi 509 } 510 511 512 513 # Cette fonction tente de monter un partage CIFS (comme par exemple 514 # le partage « Classes » du Se3). Le premier paramètre est le chemin 515 # du partage CIFS et le deuxième paramètre est le répertoire servant 516 # de point de montage. Le troisième paramètre, s'il existe, permet 517 # d'ajouter des options de montage en plus de celles par défaut. 518 function monter_partage_cifs () 519 { 520 # 10 secondes avant le timeout du montage, ça fait beaucoup 521 # mais pour l'instant, le Se3 n'étant pas bien adapté aux 522 # clients Linux (aux montages CIFS pour être plus précis), 523 # lors par exemple d'un montage d'un /home via CIFS, 524 # le script connexion.sh sur le Se3 est exécuté avant que 525 # le montage ne soit accepté (preexec dans smb.conf) et 526 # il a tendance à durer un peu hélas. 527 local options 528 # Les options par défaut. 529 options="$OPTIONS_MOUNT_CIFS_BASE" 530 if [ -n "$3" ]; then 531 # Des options supplémentaires sont spécifiées, 532 # on les ajoute à la liste. 533 options="$3,$options" 534 fi 535 timeout "--signal=SIGTERM" 10s mount -t cifs "$1" "$2" -o "$options" 536 } 537 538 539 540 # Affiche une petite fenêtre signalant une erreur. 541 # Le premier argument correspond au titre de la fenêtre et 542 # les suivants sont concaténés (avec un espace pour faire la jointure) 543 # afin de former le message d'erreur contenu dans la fenêtre. 544 function afficher_fenetre_erreur () 545 { 546 local titre 547 local message 548 549 titre="$1" 550 551 # On mange le premier argument. 552 shift 1 553 554 # Avec les arguments restants, on forme le message. 555 local m 556 for m in "$@"; do 557 message="$message $m" 558 done 559 # On enlève l'espace au début. 560 message="${message# }" 561 562 # Attention d'appeler zenity avec une locale adaptée. 563 LC_ALL="$LOCALE_FRANCAISE" zenity --error --title "$titre" --text "$message" 564 } 565 566 567 568 # Fonction qui retourne la valeur 0 si le login donné en deuxième argument 569 # appartient au groupe donné en premier argument et retourne la valeur 1 sinon. 570 # Exemples d'appels : 571 # appartient_au_groupe Eleves hugov 572 # appartient_au groupe Profs hugov 573 # La recherche est insensible à la casse. 574 function appartient_au_groupe () 575 { 576 # $1 = le groupe 577 # $2 = le login 578 local n 579 # On cherche à afficher la liste des DN des entrées de l'OU Groups 580 # qui possèdent un attribut memberUid égal à "$2". 581 n=$(timeout "--signal=SIGTERM" 4s ldapsearch -xLLL -h "$SE3" -b "cn=$1,ou=Groups,$BASE_DN" "(memberUid=$2)" "dn" | wc -l) 582 if [ "$n" -eq "0" ]; then 583 # n = 0 signifie que la recherche n'a donné aucun résultat et 584 # donc le compte n'appartient pas au groupe. 585 return 1 586 else 587 # Sinon, la recherche a donné un résultat et donc le compte 588 # appartient au groupe. 589 return 0 590 fi 591 } 592 593 594 595 # Fonction qui retourne la valeur 0 si le nom de machine donné en 596 # deuxième argument appartient au nom de parc donné en premier argument 597 # et retourne la valeur 1 sinon. 598 # Exemple d'appel : 599 # appartient_au_parc CDI S121-PC04 600 # La recherche est insensible à la casse. 601 function appartient_au_parc () 602 { 603 # $1 = le parc 604 # $2 = le nom de machine 605 local n 606 n=$(timeout "--signal=SIGTERM" 4s ldapsearch -xLLL -h "$SE3" -b "cn=$1,ou=Parcs,$BASE_DN" "(member=cn=$2,ou=Computers,$BASE_DN)" "dn" | wc -l) 607 if [ "$n" -eq "0" ]; then 608 # n = 0 signifie que la recherche n'a donné aucun résultat et 609 # donc la machine n'appartient pas au parc. 610 return 1 611 else 612 # Sinon, la recherche a donné un résultat et donc la machine 613 # appartient au parc. 614 return 0 615 fi 616 } 617 618 619 620 # Cette fonction affiche la liste des groupes qui contiennent le 621 # compte dont le login est donné en paramètre. Le format d'affichage 622 # est de la forme « une ligne par nom de groupe ». Un exemple 623 # typique d'appel de la fonction : 624 # liste_groupes=$(afficher_liste_groupes "hugov") 625 function afficher_liste_groupes () 626 { 627 # $1 = le login 628 # Recherche dans l'OU Groups de tous les dn des entrées qui 629 # possèdent un attribut memberUid égal "$1". 630 timeout "--signal=SIGTERM" 4s ldapsearch -xLLL -h "$SE3" -b "ou=Groups,$BASE_DN" "(memberUid=$1)" "dn" \ 631 | awk 'BEGIN { RS="\0" } { gsub("\n ", ""); print $0 }' \ 632 | awk '$0 ~ /^dn: / { print $2 }' \ 633 | sed -r 's/^cn=([^,]+),.*$/\1/g' 634 # Avec le premier awk, on prend la sortie de la recherche dans son 635 # ensemble (RS="\0") et on remplace "\n " par "" car, dans une 636 # recherche LDAP, une ligne trop longue est cassée et la suite de 637 # la ligne est indentée sur un espace. Avec cette substitution, 638 # les lignes trop longues ne sont pas cassées. 639 # 640 # Avec le second awk, étant donné qu'on a des lignes soit vides, 641 # soit de la forme "dn: <le-dn-du-groupe>". On affiche alors seulement 642 # les lignes non vides et on affiche uniquement la partie située 643 # après l'espace. 644 # 645 # Avec sed, on récupère uniquement le nom du groupe. 646 } 647 648 649 650 # Cette fonction affiche la liste des parcs qui contiennent la 651 # machine dont le nom est donné en paramètre. Le format d'affichage 652 # est de la forme « une ligne par nom de machine ». Un exemple 653 # typique d'appel de la fonction : 654 # liste_parcs=$(afficher_liste_parcs "S121-HP-04") 655 function afficher_liste_parcs () 656 { 657 # $1 = le nom de machine 658 # Recherche dans l'OU Parcs de tous les dn des entrées qui 659 # possèdent un attribut member égal "cn=$1,ou=Computers,$BASE_DN". 660 timeout "--signal=SIGTERM" 4s ldapsearch -xLLL -h "$SE3" -b "ou=Parcs,$BASE_DN" "(member=cn=$1,ou=Computers,$BASE_DN)" "dn" \ 661 | awk 'BEGIN { RS="\0" } { gsub("\n ", ""); print $0 }' \ 662 | awk '$0 ~ /^dn: / { print $2 }' \ 663 | sed -r 's/^cn=([^,]+),.*$/\1/g' 664 # Avec le premier awk, on prend la sortie de la recherche dans son 665 # ensemble (RS="\0") et on remplace "\n " par "" car, dans une 666 # recherche LDAP, une ligne trop longue est cassée et la suite de 667 # la ligne est indentée sur un espace. Avec cette substitution, 668 # les lignes trop longues ne sont pas cassées. 669 # 670 # Avec le second awk, étant donné qu'on a des lignes soit vides, 671 # soit de la forme "dn: <le-dn-d-un-parc>". On affiche alors seulement 672 # les lignes non vides et on affiche uniquement la partie située 673 # après l'espace. 674 # 675 # Avec sed, on récupère uniquement le nom du parc. 676 } 677 678 679 680 # Une liste (de la forme un item par ligne) étant donnée, la fonction 681 # renvoie 0 si le paramètre est dedans, 1 sinon. La recherche est 682 # sensible à la casse, c'est-à-dire que 683 # « est_dans_liste "$liste" "un_item" », et 684 # « est_dans_liste "$liste" "UN_ITEM" » ne renverront pas 685 # forcément la même valeur. 686 function est_dans_liste () 687 { 688 # $1 = la liste 689 # $2 = le nom à tester 690 if echo "$1" | grep_debut_fin_verbatim "$2"; then 691 return 0 692 else 693 return 1 694 fi 695 } 696 697 698 699 # Fonction qui se charge de lancer les exécutables « unefois ». 700 function lancer_unefois () 701 { 702 if test -e "$REP_UNEFOIS/PAUSE"; then 703 # Si le fichier PAUSE est présent alors on ne fait rien. 704 # et on s'arrête. 705 return 0 706 fi 707 708 if test -e "$REP_UNEFOIS/BLACKOUT"; then 709 # Si le fichier BLACKOUT est présent alors on supprime 710 # tous les exécutables dans REP_UNEFOIS_LOCAL. 711 local f 712 for f in "$REP_UNEFOIS_LOCAL/"*; do 713 [ "$f" = "$REP_UNEFOIS_LOCAL/*" ] && continue 714 rm -rf "$f" 715 done 716 # Et on arrête tout. 717 return 0 718 fi 719 720 # Dans cette situation (pas de fichier PAUSE ni de fichier 721 # BLACKOUT), il faut copier les « unefois » distants 722 # dont le nom n'existe pas en local et les exécuter. 723 724 local d 725 local regex 726 727 shopt -s dotglob 728 for d in "$REP_UNEFOIS/"*; do 729 [ "$d" = "$REP_UNEFOIS/*" ] && continue 730 if [ -d "$d" ]; then 731 732 parc="$(echo ${d##*/})" 733 if appartient_au_parc $parc $NOM_HOTE; then 734 lancer_unefois_dans_repertoire "$d" 735 fi 736 737 regex=$(basename "$d") 738 if echo "$NOM_HOTE" | grep -Eiq -- "$regex"; then 739 lancer_unefois_dans_repertoire "$d" 740 fi 741 fi 742 done 743 shopt -u dotglob 744 } 745 746 747 748 # Fonction qui se charge de l'installation des pilotes d'imprimantes 749 function lancer_parc () 750 { 751 for p in "$REP_LANCEPARC/"*; do 752 [ "$p" = "$REP_LANCEPARC/*" ] && continue 753 parc="$(echo ${p##*/})" 754 echo "$p" 755 echo "$parc" 756 if [ "$parc" = "_TousLesPostes" ]; then 757 for script in $p/*.sh; do 758 [ "$script" = "$p/*.sh" ] && continue 759 echo "on lance $script" 760 /bin/bash $script 761 done 762 fi 763 if appartient_au_parc $parc $NOM_HOTE; then 764 # [ -e $REP_LANCEPARC/$parc.sh ] && $REP_LANCEPARC/$parc.sh 765 for script in $p/*.sh; do 766 [ "$script" = "$p/*.sh" ] && continue 767 echo "on lance $script" 768 /bin/bash $script 769 done 770 fi 771 done 772 } 773 774 775 776 777 # Cette fonction lance tous les scripts unefois situés dans le 778 # répertoire dont le chemin absolu doit être donné en paramètre 779 # (sans / à la fin). 780 function lancer_unefois_dans_repertoire () 781 { 782 783 # $1 = le chemin absolu du répertoire. 784 785 local nom_local 786 local nom_distant 787 788 for nom_distant in "$1/"*".unefois"; do 789 790 [ "$nom_distant" = "$1/*.unefois" ] && continue 791 [ ! -f "$nom_distant" ] && continue 792 793 nom_local="$REP_UNEFOIS_LOCAL/"$(basename "$nom_distant") 794 795 if ! test -e "$nom_local"; then 796 # Si le « unefois » distant n'existe pas en local 797 # alors on le copie en local et on le lance. 798 799 # À ce stade, j'ai vu des plantages de la commande cp du 800 # genre « cp: ignore le fichier « /xxx/yyy » car il a été 801 # remplacé durant la copie », alors que ce n'est pas le 802 # cas. Ça semble être plus ou moins un bug... 803 if cp "$nom_distant" "$nom_local" && \ 804 diff -q "$nom_distant" "$nom_local" >/dev/null 2>&1 805 then 806 chmod u+x "$nom_local" 807 # L'exécutable « unefois » est lancé en arrière plan. 808 "$nom_local" > "$nom_local.log" 2>&1 & 809 else 810 # Si la copie en local n'a pas bien fonctionné, 811 # on ne lance pas l'exécutable et on supprime 812 # sa version locale si elle existe afin qu'il y 813 # ait tentative d'exécution la prochaine fois. 814 test -e "$nom_local" && rm -rf "$nom_local" 815 afficher "Échec de la copie de $nom_distant en local." \ 816 "L'exécutable ne sera pas lancé. Il y aura" \ 817 "tentative au prochain démarrage du système." 818 fi 819 fi 820 done 821 } 822 823 824 825 # Fonction qui permet d'activer le pavé numérique. Cette fonction 826 # s'exécute à la fin du script et peut prendre un argument optionnel 827 # qui est le délai d'attente entre la fin du script et le lancement 828 # de l'activation du pavé numérique. Si l'argument est absent, par 829 # défaut le délai est de 1 seconde. 830 function activer_pave_numerique () 831 { 832 local commande 833 834 if [ "$ARCHITECTURE" = "x86_64" ]; then 835 # On est sur du 64 bits. 836 commande="$REP_BIN_LOCAL/activer_pave_numerique_x86_64" 837 else 838 # Sinon, on est a priori sur du 32 bits. 839 commande="$REP_BIN_LOCAL/activer_pave_numerique_i386" 840 fi 841 842 local delai 843 844 if echo "$1" | grep -Eq -- '^[0-9]+$'; then 845 delai="$1" 846 else 847 delai="1" 848 fi 849 850 executer_a_la_fin "$delai" "$commande" 851 } 852 853 854 855 # Fonction qui renvoie 0 si l'argument correspond à un login 856 # d'un compte connecté au système, et renvoie 1 sinon. 857 function est_connecte () 858 { 859 860 ### ---%<------%<------%<------%<------%<------%<------%<------%<--- 861 ### Sans doute depuis une mise à jour, ce problème ne semble plus 862 ### être d'actualité. 863 # Sur Precise, pour des raisons que j'ignore, la commande who ne 864 # liste aucune session graphique ouverte. Du coup, je n'ai pas 865 # trouvé mieux que de bricoler un truc basé sur la commande ps 866 # avec la recherche de la chaîne unity. C'est bien dommage, 867 # mais je n'ai pas trouvé mieux. 868 ###if [ "$NOM_DE_CODE" = "precise" ]; then 869 ### if ps -u "$1" -U "$1" | awk '{ if (NR>0) print $4 }' | grep -q '^unity'; then 870 ### return 0 871 ### else 872 ### return 1 873 ### fi 874 ###fi 875 ### ---%<------%<------%<------%<------%<------%<------%<------%<--- 876 877 # Sinon, dans le cas général, on va utiliser la commande who. 878 # $1 est une chaîne représentant un login. 879 if who | cut -d ' ' -f 1 | grep_debut_fin_verbatim "$1"; then 880 return 0 881 else 882 return 1 883 fi 884 } 885 886 887 888 # Fonction qui affiche le nombre d'utilisateurs différents 889 # sont sont connectés au système. 890 function afficher_nombre_utilisateurs_connectes () 891 { 892 ### ---%<------%<------%<------%<------%<------%<------%<------%<--- 893 ### Sans doute depuis une mise à jour, ce problème ne semble plus 894 ### être d'actualité. 895 # Pour les mêmes raisons que celles expliquées dans la fonction 896 # est_connecte, dans le cas de la distribution Precise, je n'ai 897 # rien trouvé de mieux que cet immonde bricolage avec ps. 898 ###if [ "$NOM_DE_CODE" = "precise" ]; then 899 ### ps aux | awk '/ [u]nity/ { print $1, $11 }' | cut -d' ' -f'1' | sort | uniq | wc -l 900 ### return 0 901 ###fi 902 ### ---%<------%<------%<------%<------%<------%<------%<------%<--- 903 904 # Sinon, dans le cas général, on va utiliser la commande who. 905 who | cut -d' ' -f'1' | sort | uniq | wc -l 906 } 907 908 909 910 # Fonction qui permet de monter le partage avec les droits de l'utilisateur 911 # qui se connecte. Le premier argument est le chemin UNC du partage. Le 912 # deuxième argument est le nom du répertoire qui sera créé dans 913 # "$REP_MONTAGE_UTILISATEUR/" et qui sera le point de montage du partage. 914 # Les arguments suivants correspondent aux chemins absolus des liens 915 # symboliques qui seront créés et qui pointeront vers le point de 916 # montage. 917 # Le montage se fait via une authentification 918 # sachant que c'est le fichier CREDENTIALS qui contient le login 919 # et le mot de passe sous la forme : 920 # --%<----%<----%<----%<----%<----%<----%<-- 921 # username=toto 922 # password=le-mot-de-passe 923 # --%<----%<----%<----%<----%<----%<----%<-- 924 function monter_partage () 925 { 926 # Si on n'est pas pendant la phase d'ouverture, on abandonne. 927 [ "$PHASE" != "ouverture" ] && return 1 928 929 local partage 930 local nom_repertoire 931 932 partage="$1" 933 nom_repertoire="$2" 934 935 if [ -z "$partage" ] || [ -z "$nom_repertoire" ]; then 936 # Les arguments ne sont pas correctement renseignés. 937 afficher_fenetre_erreur "Problème" \ 938 "Erreur lors de l'appel de la fonction \"monter_partage\". Au moins" \ 939 "un des deux arguments est vide." 940 return 1 941 fi 942 943 if ! echo "$nom_repertoire" | grep -Eiq '^[-_a-z0-9]+$'; then 944 # Le nom du répertoire futur point de montage comporte des 945 # caractères illicites. 946 afficher_fenetre_erreur "Problème" \ 947 "Erreur lors de l'appel de la fonction \"monter_partage\". Le" \ 948 "nom du répertoire de montage (le deuxième argument de la fonction)" \ 949 "contient des caractères illicites. Le nom de ce répertoire doit" \ 950 "être constitué uniquement des caractères a-z, A-Z, du tiret (-)" \ 951 "et du tiret-bas (_)." 952 return 2 953 fi 954 955 local point_de_montage 956 957 point_de_montage="$REP_MONTAGE_UTILISATEUR/$nom_repertoire" 958 959 if [ -e "$point_de_montage" ]; then 960 # Le répertoire de point de montage correspond à un nom 961 # de fichier déjà existant. 962 afficher_fenetre_erreur "Problème" \ 963 "Erreur lors de l'appel de la fonction \"monter_partage\". Le" \ 964 "répertoire de montage \"$nom_repertoire\" correspond à un nom" \ 965 "de fichier déjà existant." 966 return 3 967 fi 968 969 mkdir "$point_de_montage" 970 971 # Par défaut, la commande mount.cifs tente d'utiliser le port 445 d'abord 972 # pour contacter le serveur. Mais dans ce cas la variable de substitution 973 # %m utilisée dans les fichiers smb*.conf du serveur et qui est censée 974 # être remplacée par le nom (netbios) du client est alors remplacée par 975 # son adresse IP. Avec l'option « port=139 », la variable %m sera bien 976 # remplacée par le nom (netbios) du client. En principe, l'option suivante 977 # « netbiosname=... », qui indique le nom (netbios) du client à envoyer au 978 # serveur, n'est pas nécessaire mais on la met quand même histoire 979 # d'enfoncer le clou encore un peu. 980 monter_partage_cifs "$partage" "$point_de_montage" \ 981 "credentials=$CREDENTIALS,uid=$LOGIN,gid=lcs-users,port=139,netbiosname=$NOM_HOTE" 982 if [ "$?" != "0" ]; then 983 # Ici, il y a un problème réseau. 984 afficher_fenetre_erreur "Problème" \ 985 "Erreur lors de l'appel de la fonction \"monter_partage\"." \ 986 "Impossible de monter le partage \"$partage\"." 987 return 4 988 fi 989 990 # On « mange » les arguments $1 et $2. 991 shift 2 992 993 # S'il n'y a pas d'autre argument... 994 if [ "$#" = "0" ]; then 995 # ... alors pas de création de lien symbolique. 996 return 0 997 fi 998 999 # Création des liens symboliques. 1000 local lien 1001 for lien in "$@"; do 1002 # Si le lien correspond à un fichier qui existe déjà, on passe. 1003 [ -e "$lien" ] && continue 1004 # Si le lien ne se trouve pas dans le home de l'utilisateur, on passe. 1005 ! echo "$lien" | grep_debut_verbatim "$REP_HOME/" && continue 1006 creer_lien_symb "$point_de_montage" "$lien" "$LOGIN" 1007 done 1008 } 1009 1010 1011 1012 # Fonction qui permet de créer des liens symboliques appartenant 1013 # à l'utilisateur qui se connecte. Le premier argument est le 1014 # fichier (au sens large, ça peut être un répertoire) vers lequel 1015 # pointent les liens et les arguments suivants (autant qu'on veut) 1016 # sont les chemins absolus des liens symboliques à créer. 1017 # Si jamais la cible n'est pas un chemin absolu, alors la 1018 # fonction considère que le chemin absolu de la cible est 1019 # "$REP_MONTAGE_UTILISATEUR/$cible". 1020 function creer_lien () 1021 { 1022 # Si on n'est pas pendant la phase d'ouverture, on abandonne. 1023 [ "$PHASE" != "ouverture" ] && return 1 1024 1025 local cible 1026 cible="$1" 1027 1028 # On teste si la cible est un chemin absolu (ie commence par un /). 1029 if ! echo "$cible" | grep -q '^/'; then 1030 # La cible n'est pas un chemin absolu, on complète le chemin 1031 # pour en faire un chemin absolu. 1032 cible="$REP_MONTAGE_UTILISATEUR/$cible" 1033 fi 1034 1035 # On « mange » l'argument $1. 1036 shift 1 1037 1038 # S'il n'y a pas d'autre argument, c'est qu'il y a une erreur... 1039 if [ "$#" = "0" ]; then 1040 # ... alors pas de création de lien symbolique. 1041 return 1 1042 fi 1043 1044 # Création des liens symboliques. 1045 local lien 1046 for lien in "$@"; do 1047 # Si le lien correspond à un fichier qui existe déjà, on passe. 1048 [ -e "$lien" ] && continue 1049 # Si le lien ne se trouve pas dans le home de l'utilisateur, on passe. 1050 ! echo "$lien" | grep_debut_verbatim "$REP_HOME/" && continue 1051 creer_lien_symb "$cible" "$lien" "$LOGIN" 1052 done 1053 } 1054 1055 1056 1057 # Fonction qui lit son entrée standard et qui attend un unique argument 1058 # (une chaîne de caractères). Elle renvoie 0 si la chaîne donnée en argument 1059 # se trouve en début de ligne d'au moins une ligne de l'entrée standard et 1060 # renvoie 1 sinon. Attention, la chaîne donnée en argument n'est pas vue 1061 # comme une regex mais comme une « chaîne brute », ie les caractères 1062 # habituellement spéciaux pour une regex ne le sont pas et représentent 1063 # eux-même (le point représente le point et pas un caractère quelconque). 1064 grep_debut_verbatim () 1065 { 1066 local motif n debut 1067 1068 motif="$1" 1069 1070 # Le nombre de caractères du motif. 1071 n=${#motif}; 1072 1073 # L'option -r est indispensable car sans elle la chaîne 'a\aa' 1074 # deviendrait 'aaa' une fois passée dans le filtre read. 1075 while read -r; do 1076 # On coupe la ligne à n caractères maximum. 1077 debut=${REPLY:0:$n} 1078 1079 # On compare le début de ligne avec le motif. 1080 if [ "$debut" = "$motif" ]; then 1081 return 0 1082 fi 1083 done 1084 1085 # Si on arrive ici, cela veut dire que le motif n'a jamais 1086 # été trouvé en début de ligne. Du coup, on renvoie 1. 1087 return 1 1088 } 1089 1090 1091 1092 # Fonction identique à la précédente sauf qu'elle renvoie 0 uniquement 1093 # si la chaîne donnée en argument correspond exactement à au moins une 1094 # ligne complète de l'entrée standard. 1095 grep_debut_fin_verbatim () 1096 { 1097 local motif 1098 1099 motif="$1" 1100 1101 # L'option -r est indispensable car sans elle la chaîne 'a\aa' 1102 # deviendrait 'aaa' une fois passée dans le filtre read. 1103 while read -r; do 1104 # On compare la ligne avec le motif. 1105 if [ "$REPLY" = "$motif" ]; then 1106 return 0 1107 fi 1108 done 1109 1110 # Si on arrive ici, cela veut dire que le motif n'a jamais 1111 # été trouvé dans une ligne. Du coup, on renvoie 1. 1112 return 1 1113 } 1114 1115 1116 1117 # Fonction qui permet d'afficher la variable d'environnement 1118 # DBUS_SESSION_BUS_ADDRESS de l'utilisateur toto qui ouvre une session afin 1119 # de pouvoir ensuite exécuter en tant que toto certaines commandes 1120 # impossibles à exécuter sans cette variable d'environnement. 1121 # On lancera alors la commande ainsi : 1122 # DBUS_SESSION_BUS_ADDRESS="$(afficher_adresse_bus)" sudo -Eu "$LOGIN" commande 1123 # Attention, le temps pour exécuter cette fonction est indéterminé et surtout 1124 # la fonction ne se terminera qu'une fois l'ouverture de session achevée (car 1125 # c'est apparemment seulement une fois l'ouverture de session achevée que le 1126 # fichier dans lequel on récupère la variable d'environnement est créé). Donc 1127 # il faudra TOUJOURS lancer la fonction dans un sous-shell ainsi « { ... } & », 1128 # sans quoi on risque de bloquer le script de logon. 1129 function afficher_adresse_bus () 1130 { 1131 local n compteur 1132 1133 n=$(\ls "$REP_HOME/.dbus/session-bus/" 2> /dev/null | wc -l) 1134 compteur=1 1135 1136 # On attend que le fichier dans "$REP_HOME/.dbus/session-bus/ soit 1137 # créé lors de l'ouverture de session. 1138 while [ "$n" != "1" ]; do 1139 sleep 0.2 1140 n=$(\ls "$REP_HOME/.dbus/session-bus/" 2> /dev/null | wc -l) 1141 compteur=$((compteur+1)) 1142 if [ "$compteur" -ge "100" ]; then 1143 # Au bout d'un certain nombre de tentatives on abandonne. 1144 # Important pour éviter une boucle infinie. 1145 return 1 1146 fi 1147 done 1148 1149 # On récupère et on affiche la valeur de la variable d'environnement 1150 # DBUS_SESSION_BUS_ADDRESS trouvée dans le fichier qui vient d'être créé. 1151 grep "^DBUS_SESSION_BUS_ADDRESS=" "$REP_HOME/.dbus/session-bus/"* | cut -d"=" -f"2-" 1152 } 1153 1154 1155 1156 # Fonction, utilisable uniquement lors de l'ouverture de session, qui 1157 # prend comme premier argument le chemin absolu d'un fichier et 1158 # comme deuxième argument le chemin absolu d'une image qui sera 1159 # l'icône associé au fichier. Le chemin du fichier dont on veut changer 1160 # l'icône doit forcément se trouver dans "$REP_HOME". 1161 # 1162 # Rq: bien que la commande gvfs-set-attribute existe sous XUbuntu, 1163 # celle-ci semble sans effet. Apparemment, sous XUbuntu, impossible 1164 # de faire de changement d'icône. 1165 function changer_icone () 1166 { 1167 # Cette partie sera lancée via un « & » et donc dans un sous-shell d'après 1168 # la page man de bash. 1169 { 1170 # Si on n'est pas pendant la phase d'ouverture, on abandonne. 1171 [ "$PHASE" != "ouverture" ] && return 1 1172 1173 # Si le fichier cible ne se trouve pas dans le home de l'utilisateur, 1174 # on abandonne. 1175 ! echo "$1" | grep_debut_verbatim "$REP_HOME/" && return 1 1176 1177 # Si le fichier image n'existe pas, on abandonne. 1178 [ ! -f "$2" ] && return 1 1179 1180 # On récupère la variable d'environnement « adresse bus ». 1181 local valeur 1182 valeur=$(afficher_adresse_bus) 1183 if [ "$valeur" = "" ]; then 1184 # Si la valeur récupérée est vide, on abandonne. 1185 exit 1 1186 fi 1187 1188 # On change l'attribut concernant l'icône du fichier. 1189 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1190 gvfs-set-attribute -t string "$1" "metadata::custom-icon" "file://$2" 1191 1192 # Sur le bureau, pour que l'affichage se mette à jour, il faut faire 1193 # un touch sur le fichier avec l'option « --no-dereference », sinon 1194 # c'est la cible du lien symbolique qui est visée et non le lien 1195 # symbolique lui-même. 1196 touch --no-dereference "$1" 1197 1198 } > "/dev/null" 2>&1 & 1199 # Ce sous-processus pourra être lancé à plusieurs reprises et, 1200 # sans la redirection ci-dessus, tous les sous-processus écriraient 1201 # plus ou moins en même temps sur un même fichier de log ce 1202 # qui pourrait donner un résultat imprévisible sur le fichier 1203 # de log. Le plus sage est de rediriger les deux sorties de 1204 # ce bout de code dans /dev/null. Ce n'est pas très grave, ce 1205 # n'est pas une partie critique. 1206 } 1207 1208 1209 1210 # Cette fonction change le papier peint de l'utilisateur qui se 1211 # connecte lors de l'ouverture de session. Elle prend 1 argument qui doit 1212 # être le chemin absolu du fichier image (un accès à ce fichier en lecture 1213 # pour l'utilisateur suffit). 1214 function changer_papier_peint () 1215 { 1216 # Cette partie sera lancée via un « & » et donc dans un sous-shell d'après 1217 # la page man de bash. 1218 { 1219 # Si on n'est pas pendant la phase d'ouverture, on abandonne. 1220 [ "$PHASE" != "ouverture" ] && return 1 1221 1222 # Si le fichier image n'existe pas, on abandonne. 1223 [ ! -f "$1" ] && return 1 1224 1225 # On récupère la variable d'environnement « adresse bus ». 1226 local valeur 1227 valeur=$(afficher_adresse_bus) 1228 if [ "$valeur" = "" ]; then 1229 # Si la valeur récupérée est vide, on abandonne. 1230 exit 1 1231 fi 1232 1233 # La commande pour changer de papier peint dépend de l'environnement 1234 # de bureau utilisé. Comment connaître l'environnement de bureau 1235 # utilisé par le compte qui se connecte ? Je pensais utiliser des 1236 # choses comme « if ps -u "$LOGIN" | grep -q unity; then » mais hélas 1237 # pour des raisons de timing ça ne fonctionne pas. La commande ps 1238 # ne renvoie pas (encore) de processus unity* alors que l'utilisateur 1239 # courant se connecte pourtant avec Unity. On pourrait résoudre ce 1240 # problème de timing avec la commande sleep mais ça n'est pas 100% 1241 # fiable : quel argument donner à sleep dans ce cas ? Du coup, on 1242 # va se contenter de lancer la commande pour chacun des 1243 # environnements de bureau pris en charge, pour peu que la commande 1244 # en question existe sur le système. Le résultat sera garanti et je 1245 # pense que la charge processeur supplémentaire due aux commandes 1246 # inutiles sera négligeable. 1247 1248 # Sur Unity. 1249 if which gsettings > /dev/null; then 1250 # Il est hautement probable que l'utilisateur soit sur Unity. 1251 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1252 gsettings set org.gnome.desktop.background picture-options stretched 1253 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1254 gsettings set org.gnome.desktop.background picture-uri "file://$1" 1255 fi 1256 1257 # Sur Xfce. 1258 if which xfconf-query > /dev/null; then 1259 # Il est hautement probable que l'utilisateur soit sur Xfce. 1260 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1261 xfconf-query --create -c xfce4-desktop -p /backdrop/screen0/monitor0/image-style -s "3" -t int # la valeur correspond à "stretched" 1262 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1263 xfconf-query -c xfce4-desktop -p /backdrop/screen0/monitor0/image-path -s "$1" 1264 fi 1265 1266 # Sur Gnome. 1267 if which gconftool-2 > /dev/null; then 1268 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1269 gconftool-2 --set /desktop/gnome/background/picture_options --type string stretched 1270 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" \ 1271 gconftool-2 --set /desktop/gnome/background/picture_filename --type string "$1" 1272 fi 1273 1274 # Sur LXDE. 1275 if which pcmanfm > /dev/null; then 1276 DBUS_SESSION_BUS_ADDRESS="$valeur" sudo -Eu "$LOGIN" pcmanfm --set-wallpaper="$1" --wallpaper-mode=center 1277 fi 1278 1279 } > "/dev/null" 2>&1 & 1280 } 1281 1282 1283 1284 # Fonction qui lance, à la fin de l'exécution du script, une commande 1285 # quelconque. Le premier argument est le délai en secondes entre la fin 1286 # de l'exécution du script et le début du lancement de la commande. 1287 # Les arguments suivants correspondent à la commande à lancer avec ses 1288 # paramètres. Si le script est trop long à se terminer (plus précisément, 1289 # si la fonction executer_a_la_fin doit attendre que le script se termine 1290 # plus de 30 secondes) alors la commande ne sera pas lancée. 1291 # Attention, la sortie standard et la sortie des erreurs seront 1292 # redirigées vers /dev/null afin qu'il n'y ait pas d'écritures 1293 # simultanées sur les fichiers de log. 1294 function executer_a_la_fin () 1295 { 1296 # Tout sera lancé dans un sous-shell à cause du « & » à la fin. 1297 { 1298 local compteur 1299 compteur="1" 1300 # Tant que le script de logon local est lu par un processus 1301 # et donc qu'a priori il est en cours d'exécution, on attend. 1302 while fuser "$LOGON_SCRIPT_LOCAL" >/dev/null 2>&1; do 1303 sleep 0.5 1304 if [ "$compteur" -ge "60" ]; then 1305 # Au bout de 30 secondes, si ce n'est toujours 1306 # pas fini, on abandonne. 1307 return 1 1308 fi 1309 compteur=$((compteur+1)) 1310 done 1311 1312 sleep "$1" # petit délai avant de commencer. 1313 1314 # On « mange » $1. 1315 shift 1 1316 1317 # Et on lance la commande avec ses arguments. 1318 "$@" 1319 1320 } > "/dev/null" 2>&1 & 1321 } 1322 1323 1324 1325 ###################################### 1326 ###################################### 1327 ### ### 1328 ### Les arguments passés au script ### 1329 ### ### 1330 ###################################### 1331 ###################################### 1332 1333 # Variable déjà affectée afin de rediriger les sorties stdout stderr 1334 # dans des fichiers, dès le début du script. 1335 #PHASE="$1" 1336 1337 if [ -z "$2" ]; then 1338 # Si "$2" est vide alors par défaut il y a tentative de MAJ. 1339 TENTATIVE_DE_MAJ="true" 1340 else 1341 TENTATIVE_DE_MAJ="$2" # avec "$2" qui doit valoir true ou false. 1342 fi 1343 1344 DEMARRAGE="$3" 1345 1346 if [ "$DEMARRAGE" != "true" ]; then 1347 # Par défaut, cette variable, qui indique si le script s'exécute 1348 # lors du démarrage, est sur false. La fonction "initialisation" 1349 # se chargera de mettre cette variable sur true le cas échéant (en 1350 # se basant sur le montage ou non de REP_TMP_LOCAL). 1351 DEMARRAGE=false 1352 fi 1353 1354 1355 1356 # On met dès le départ et une bonne fois pour toute 1357 # la date du moment dans le fichier de log. 1358 afficher_date 1359 1360 set -x 1361 1362 1363 1364 1365 1366 ############################################# 1367 ############################################# 1368 ### ### 1369 ### Réglage des variables d'environnement ### 1370 ### ### 1371 ############################################# 1372 ############################################# 1373 1374 # Pour avoir des sorties les plus simples possibles, c'est-à-dire 1375 # en anglais avec des caractères 100% ASCII. 1376 export LC_ALL="C" 1377 1378 # Du coup, on utilisera la locale française au coup par coup. 1379 # Celle-ci, il n'est pas nécessaire de l'exporter. 1380 LOCALE_FRANCAISE="fr_FR.utf8" 1381 1382 # Réglage du PATH. 1383 export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" 1384 1385 1386 1387 1388 1389 1390 ######################################################## 1391 ######################################################## 1392 ### ### 1393 ### Définitions des variables globales et exports de ### 1394 ### certaines variables et fonctions ### 1395 ### ### 1396 ######################################################## 1397 ######################################################## 1398 1399 1400 ############################################# 1401 ### Définitions de variables « globales » ### 1402 ############################################# 1403 1404 # Variables liées au Se3. 1405 SE3="__SE3__" 1406 BASE_DN="__BASE_DN__" 1407 SERVEUR_NTP="__SERVEUR_NTP__" 1408 NOM_PARTAGE_NETLOGON="netlogon-linux" 1409 CHEMIN_PARTAGE_NETLOGON="//$SE3/$NOM_PARTAGE_NETLOGON" 1410 1411 # Variables liées à l'hôte. 1412 NOM_HOTE=$(hostname) 1413 NOM_DE_CODE=$(lsb_release --codename | cut -f 2) 1414 ARCHITECTURE=$(uname -m) 1415 1416 MAX_UTILISATEURS_CONNECTES="4" 1417 1418 # Apparemment, l'option serverino permet d'éviter des erreurs obscures 1419 # lors de copies avec la commande cp (notamment avec les exécutables 1420 # *.unfois), alors qu'avec l'option noserverino j'avais rencontré 1421 # ces erreurs obscures. 1422 OPTIONS_MOUNT_CIFS_BASE="nobrl,serverino,iocharset=utf8,sec=ntlmv2" 1423 1424 # Noms de fichiers ou de répertoires locaux au client. 1425 #REP_SE3_LOCAL="/etc/se3" # Déjà affectée en début de script. 1426 REP_BIN_LOCAL="$REP_SE3_LOCAL/bin" 1427 REP_TMP_LOCAL="$REP_SE3_LOCAL/tmp" 1428 #REP_LOG_LOCAL="$REP_SE3_LOCAL/log" # Déjà affectée en début de script. 1429 REP_SKEL_LOCAL="$REP_SE3_LOCAL/skel" 1430 REP_UNEFOIS_LOCAL="$REP_SE3_LOCAL/unefois" 1431 LOGON_SCRIPT_LOCAL="$REP_BIN_LOCAL/logon" 1432 VERSION_SKEL_LOCAL="$REP_SKEL_LOCAL/.VERSION" 1433 CREDENTIALS="$REP_TMP_LOCAL/credentials" 1434 REP_MONTAGE="/mnt" 1435 1436 # Noms de fichiers ou de répertoires du Se3 accessibles par le client 1437 # via le montage du partage NOM_PARTAGE_NETLOGON du Se3. 1438 REP_NETLOGON="$REP_MONTAGE/netlogon" 1439 LOGON_SCRIPT="$REP_NETLOGON/bin/logon" 1440 REP_SKEL="$REP_NETLOGON/distribs/$NOM_DE_CODE/skel" 1441 VERSION_SKEL="$REP_SKEL/.VERSION" 1442 REP_UNEFOIS="$REP_NETLOGON/unefois" 1443 REP_LANCEPARC="$REP_NETLOGON/lanceparc" 1444 1445 1446 #################################################################################### 1447 ### Définitions de variables « globales » valables uniquement lors d'une session ### 1448 #################################################################################### 1449 if [ "$PHASE" = "ouverture" ] || [ "$PHASE" = "fermeture" ]; then 1450 1451 LOGIN="$LOGNAME" 1452 REP_MONTAGE_UTILISATEUR="$REP_MONTAGE/_$LOGIN" 1453 REP_HOME="/home/$LOGIN" 1454 NOM_COMPLET_LOGIN=$(getent passwd "$LOGIN" | cut -d':' -f5 | cut -d',' -f1) 1455 1456 if [ "$PHASE" = "ouverture" ]; then 1457 # La requête LDAP ne sera faite qu'au moment de l'ouverture de session. 1458 if ! est_utilisateur_local "$LOGIN" ; then 1459 LISTE_GROUPES_LOGIN=$(afficher_liste_groupes "$LOGIN") 1460 fi 1461 fi 1462 1463 fi 1464 1465 1466 ############################################################################ 1467 ### On exporte certaines variables « globales » pour les scripts unefois ### 1468 ############################################################################ 1469 1470 export SE3 1471 export BASE_DN 1472 export NOM_HOTE 1473 export NOM_DE_CODE 1474 export ARCHITECTURE 1475 export REP_BIN_LOCAL # Seulement parce que la fonction activer_pave_numerique l'utilise. 1476 1477 # Les variables LOGIN, NOM_COMPLET_LOGIN, LISTE_GROUPES_LOGIN seront utilisables 1478 # dans les fonctions ouverture_perso et fermeture_perso, mais un export 1479 # ne sert à rien pour ces variables car elles n'ont pas de sens dans 1480 # les scripts unefois. 1481 1482 # Quant à la variable DEMARRAGE, pas d'export non plus car dans un script 1483 # unefois elle vaudra toujours true, puisque les scripts unefois ne sont 1484 # lancés qu'au démarrage du système. 1485 1486 1487 ############################################################################ 1488 ### On exporte certaines fonctions « globales » pour les scripts unefois ### 1489 ############################################################################ 1490 1491 export -f appartient_au_groupe 1492 export -f appartient_au_parc 1493 export -f afficher_liste_groupes 1494 export -f afficher_liste_parcs 1495 export -f est_dans_liste 1496 export -f activer_pave_numerique 1497 export -f est_utilisateur_local 1498 export -f est_connecte 1499 1500 1501 1502 1503 1504 ################################################################################ 1505 ################################################################################ 1506 ### ### 1507 ### Définitions des trois fonctions de base appelées à des instants ### 1508 ### différents par la machine clientes : ### 1509 ### ### 1510 ### - "initialisation" qui sera appelée juste avant l'affichage de ### 1511 ### la fenêtre de connexion, c'est-à-dire au moment du ### 1512 ### démarrage et après chaque fermeture de session. ### 1513 ### ### 1514 ### - "ouverture" qui sera appelée au moment de ### 1515 ### l'ouverture de session de l'utilisateur, juste après ### 1516 ### l'authentification de celui-ci. ### 1517 ### ### 1518 ### - "fermeture" qui sera appelée au moment de la fermeture ### 1519 ### de session de l'utilisateur. ### 1520 ### ### 1521 ################################################################################ 1522 ################################################################################ 1523 1524 1525 1526 function initialisation () 1527 { 1528 nettoyer_rep_tmp_local 1529 1530 # On attend un petit peu car, sur Precise par exemple, les processus de 1531 # l'utilisateur qui vient de fermer sa session sont encore en vie si 1532 # bien que, aux yeux du script de logon, l'utilisateur est encore 1533 # connecté et le nettoyage est alors incomplet. 1534 sleep 1 1535 1536 nettoyer_rep_montage 1537 nettoyer_rep_home 1538 1539 local n 1540 local message 1541 n=$(afficher_nombre_utilisateurs_connectes) 1542 if [ "$n" -ge "$MAX_UTILISATEURS_CONNECTES" ]; then 1543 message="Trop de sessions n'ont pas été fermées. Le système va" 1544 message="$message redémarrer ce qui provoquera la fermeture" 1545 message="$message de toutes les sessions en suspens." 1546 LC_ALL="$LOCALE_FRANCAISE" zenity \ 1547 --info "Trop de sessions non fermées" \ 1548 --text "$message" --timeout 10 1549 reboot && exit 1550 fi 1551 1552 if ! mountpoint -q "$REP_TMP_LOCAL"; then 1553 # REP_TMP_LOCAL n'est pas monté, donc c'est le démarrage du système, 1554 # il faut donc modifier la variable DEMARRAGE. 1555 DEMARRAGE=true 1556 mount -t tmpfs -o size=100k tmpfs "$REP_TMP_LOCAL" 1557 fi 1558 1559 if monter_netlogon; then 1560 # Montage réussi ou bien il avait été effectué auparavant. 1561 # Donc le contenu n'est pas forcément lisible (le service 1562 # Samba entre temps est peut être tombé en panne). 1563 1564 # Tentative de MAJ de LOGON_SCRIPT. 1565 if $TENTATIVE_DE_MAJ \ 1566 && timeout "--signal=SIGTERM" 2s test -r "$LOGON_SCRIPT" \ 1567 && ! diff -q "$LOGON_SCRIPT_LOCAL" "$LOGON_SCRIPT" >/dev/null 2>&1 1568 then 1569 # On exécute le script distant avec l'argument empêchant une MAJ 1570 # et en signalant, avec la variable DEMARRAGE, si l'on est pendant 1571 # le démarrage du système ou non. En effet, si c'est le script 1572 # de logon distant qui est lancé, alors REP_TMP_LOCAL est 1573 # sans doute déjà monté cela ne sera plus un critère pour savoir 1574 # si l'on est pendant le démarrage du système. 1575 "$LOGON_SCRIPT" "initialisation" false "$DEMARRAGE" 1576 # Si le script distant s'est effectué sans erreur (typiquement il 1577 # ne possède pas d'erreur de syntaxe), alors on lance la mise à 1578 # jour. 1579 if [ "$?" = "0" ]; then 1580 mettre_a_jour_logon 1581 else 1582 afficher "Attention, a priori le script de logon distant n'est pas correct." \ 1583 "Pas de mise à jour effectuée en local." 1584 fi 1585 # Inutile de continuer le script, on vient d'exécuter une fois 1586 # sa version à jour (celle du serveur) au complet. Alors on sort. 1587 exit 0 1588 fi 1589 1590 # Tentative de MAJ du profil et lancements des « unefois ». 1591 if timeout "--signal=SIGTERM" 2s test -r "$VERSION_SKEL"; then 1592 if ! diff -q "$VERSION_SKEL_LOCAL" "$VERSION_SKEL" >/dev/null 2>&1; then 1593 mettre_a_jour_profil 1594 fi 1595 # Puisque le serveur semble accessible, on tente d'accéder à 1596 # REP_UNEFOIS, dans le cas où l'on est dans une phase d'initialisation 1597 # qui correspond à un démarrage. 1598 if "$DEMARRAGE" && timeout "--signal=SIGTERM" 2s test -d "$REP_UNEFOIS"; then 1599 lancer_unefois 1600 fi 1601 1602 # Idem ci-dessus pour le répertoire lance-parc 1603 1604 if timeout "--signal=SIGTERM" 2s test -d "$REP_LANCEPARC"; then 1605 lancer_parc 1606 fi 1607 fi 1608 1609 fi 1610 1611 # Si jamais le répertoire ".dbus" existe déjà dans le profil par défaut 1612 # local, il faut le supprimer car il devra être généré à la volée au 1613 # moment de l'ouverture de session dans le home de l'utilisateur qui 1614 # se connecte. En effet, ce répertoire contiendra alors un fichier 1615 # qui permettra de connaître la valeur de la variable 1616 # DBUS_SESSION_BUS_ADDRESS de la session en cours. Si on ne prend pas 1617 # la précaution de supprimer ce répertoire dans le profil local maintenant, 1618 # on risque de récupérer alors la valeur de cette variable pour une 1619 # ancienne session, et toutes les fonctions qui dépendent de cette 1620 # variable risqueront de ne pas marcher. 1621 if [ -e "$REP_SKEL_LOCAL/.dbus" ]; then 1622 afficher "Suppression du répertoire .dbus/ dans le profil local." 1623 rm -fr --one-file-system "$REP_SKEL_LOCAL/.dbus" 1624 fi 1625 1626 initialisation_perso 1> "$REP_LOG_LOCAL/1.initialisation_perso.log" 2>&1 1627 1628 exit 0 1629 } 1630 1631 1632 function ouverture () 1633 { 1634 # Quoi qu'il arrive, à la fin du script lors de l'ouverture, on 1635 # nettoie le répertoire temporaire local. 1636 trap nettoyer_rep_tmp_local EXIT 1637 1638 # Dans cette fonction, on peut faire usage de $LOGIN 1639 # qui est le login de l'utilisateur courant. 1640 1641 if est_utilisateur_local "$LOGIN" ; then 1642 # On ne fait rien et on arrête le script. 1643 exit 0 1644 fi 1645 1646 # Mise en place du home de l'utilisateur qui n'est pas un 1647 # utilisateur local ici. 1648 if [ -e "$REP_HOME" ]; then 1649 rm -fr --one-file-system "$REP_HOME" 1650 fi 1651 mkdir -p "$REP_HOME/Bureau" 1652 1653 # On copie tout le contenu de REP_SKEL_LOCAL dans le HOME_LOCAL. 1654 shopt -s dotglob 1655 local f 1656 for f in "$REP_SKEL_LOCAL/"*; do 1657 cp -r "$f" "$REP_HOME" 1658 done 1659 shopt -u dotglob 1660 1661 # Ajustement des droits sur le home. 1662 chown -R "$LOGIN:" "$REP_HOME" 1663 # On rend les fichiers *.desktop exécutables pour l'utilisateur au cas où... 1664 for f in "$REP_HOME/Bureau/"*".desktop"; do 1665 [ "$f" = "$REP_HOME/Bureau/*.desktop" ] && continue 1666 chmod u+x "$f" 1667 done 1668 chmod 700 "$REP_HOME" 1669 sync 1670 1671 # Après la création du home de l'utilisateur, on attend un peu. 1672 # En effet, j'ai constaté empiriquement que, sur Precise par exemple, 1673 # sans ce laps de temps les réglages inscrits dans le profil 1674 # (notamment dans le répertoire "~/.config/") n'étaient pas 1675 # systématiquement pris en compte par l'environnement de bureau. 1676 sleep 1 1677 1678 # Maintenant, il faut procéder aux montages des partages CIFS. 1679 # Pour commencer, il faut attendre la création du fichier CREDENTIALS. 1680 local c 1681 c="1" 1682 while ! test -r "$CREDENTIALS" && [ "$c" -le 4 ]; do 1683 # Tant que le fichier n'est pas accessible en lecture, on attend un peu. 1684 sleep 0.5 1685 c=$((c+1)) # pour éviter une boucle infinie, après 4 tentatives, on sort de la boucle. 1686 done 1687 1688 # Si c vaut 5, c'est qu'il a été impossible de lire le fichier CREDENTIALS 1689 # et donc que les montages seront impossibles. Dans ce cas, il vaut mieux 1690 # sortir et ne pas tenter les-dits montages. 1691 if [ "$c" -eq "5" ]; then 1692 afficher_fenetre_erreur "Problème" \ 1693 "Le montage des partages de l'utilisateur sont impossibles car" \ 1694 "le fichier \"CREDENTIALS\" est inaccessible." 1695 exit 1 1696 fi 1697 1698 if [ -e "$REP_MONTAGE_UTILISATEUR" ]; then 1699 # Le répertoire existe déjà ce qui n'est pas normal. 1700 # Du coup, on nettoie le répertoire de montage, étant 1701 # donné qu'il sera créé juste après. 1702 nettoyer_un_rep_montage "$REP_MONTAGE_UTILISATEUR" 1703 fi 1704 1705 # On crée le répertoire où seul LOGIN pourra se rendre. 1706 mkdir "$REP_MONTAGE_UTILISATEUR" 1707 chown "$LOGIN:" "$REP_MONTAGE_UTILISATEUR" 1708 chmod "700" "$REP_MONTAGE_UTILISATEUR" 1709 1710 # C'est dans la fonction ouverture_perso que les montages seront 1711 # effectués pour que l'administrateur puisse les gérer comme 1712 # bon lui semble. 1713 ouverture_perso 1> "$REP_LOG_LOCAL/2.ouverture_perso.log" 2>&1 1714 1715 # Surtout, on détruit immédiatement le fichier CREDENTIALS contenu 1716 # dans le répertoire temporaire local. En principe, c'est fait 1717 # automatiquement grâce à la fonction trap ci-dessus, mais on 1718 # rajoute une couche au cas où... 1719 nettoyer_rep_tmp_local 1720 1721 exit 0 1722 } 1723 1724 1725 1726 function fermeture () 1727 { 1728 # Dans cette fonction, on peut faire usage de $LOGIN 1729 # qui est le login de l'utilisateur courant. 1730 1731 if est_utilisateur_local "$LOGIN" ; then 1732 # On ne fait rien et on arrête le script. 1733 exit 0 1734 fi 1735 1736 # Par mesure de sécurité, avant le nettoyage, on débarrasse le 1737 # /home des liens symboliques qui pointent vers des partages. 1738 # Il y en a à la racine du /home et sur le « Bureau ». 1739 1740 # Le « ! -name '.gvfs' » permet d'éviter une petite erreur lors 1741 # de la commande « find » quand on est sous Ubuntu. 1742 find "$REP_HOME" -maxdepth 1 ! -name '.gvfs' -type l -exec rm -f '{}' \; 1743 find "$REP_HOME/Bureau" -maxdepth 1 -type l -exec rm -f '{}' \; 1744 1745 fermeture_perso 1> "$REP_LOG_LOCAL/3.fermeture_perso.log" 2>&1 1746 1747 exit 0 1748 } 1749 1750 1751 # Dans logon, les variables SE3 et BASE_DN sont definies 1752 function genere_fond_ecran() { 1753 1754 if [ -z "$LOGIN" ] 1755 then 1756 # La variable LOGIN n'est pas définie. On arrête là. 1757 return 1 1758 fi 1759 1760 # Quelques parametres 1761 dossier_base_fond="$REP_NETLOGON/fond_ecran" 1762 dossier_dest_fond=/tmp 1763 ext=jpg 1764 1765 t=$(which convert) 1766 if [ -z "$t" ]; then 1767 echo "La generation de fond d'ecran necessite l'installation d'imagemagick cote client." 1768 else 1769 # Menage 1770 if [ -e "${dossier_dest_fond}/fond_ecran_$LOGIN.$ext" ]; then 1771 rm -f "${dossier_dest_fond}/fond_ecran_$LOGIN.$ext" 1772 fi 1773 1774 # Recuperation des parametres generaux 1775 parametres_generation_fonds 1776 1777 if [ -n "$prefixe" ]; then 1778 1779 if [ "$LOGIN" = "admin" ]; then 1780 t=$(grep "function parametres_fond_ecran_admin()" $REP_BIN_LOCAL/logon) 1781 if [ -n "$t" ]; then 1782 parametres_fond_ecran_admin 1783 if [ "$generation_fonds_ecran" = "actif" ]; then 1784 annotation_fond_ecran_admin 1785 1786 temoin="admin" 1787 classe="Admins" 1788 fi 1789 fi 1790 else 1791 if est_dans_liste "$LISTE_GROUPES_LOGIN" "overfill"; then 1792 t=$(grep "function parametres_fond_ecran_overfill()" $REP_BIN_LOCAL/logon) 1793 if [ -n "$t" ]; then 1794 parametres_fond_ecran_overfill 1795 if [ "$generation_fonds_ecran" = "actif" ]; then 1796 annotation_fond_ecran_overfill 1797 1798 temoin="overfill" 1799 classe="" 1800 fi 1801 fi 1802 fi 1803 1804 # Pour les profs on outrepasse les parametres overfill 1805 if est_dans_liste "$LISTE_GROUPES_LOGIN" "Profs"; then 1806 t=$(grep "function parametres_fond_ecran_Profs()" $REP_BIN_LOCAL/logon) 1807 if [ -n "$t" ]; then 1808 parametres_fond_ecran_Profs 1809 if [ "$generation_fonds_ecran" = "actif" ]; then 1810 annotation_fond_ecran_Profs 1811 1812 temoin="Profs" 1813 classe="Profs" 1814 fi 1815 fi 1816 fi 1817 1818 if [ -z "$temoin" ]; then 1819 # Utilisateur non prof... -> eleves ou administratifs? 1820 if est_dans_liste "$LISTE_GROUPES_LOGIN" "Eleves"; then 1821 # Utilisateur eleve 1822 # Dans le cas d'un eleve, le groupe Classe est prioritaire (pour l'image) sur le groupe eleves. 1823 #classe=$(ldapsearch -xLLL -h "$SE3" -b "ou=Groups,$BASE_DN" "(&(memberuid=$LOGIN)(cn=Classe*))" cn | grep "^cn: " | sed -e "s/^cn: //"|head -n1) 1824 #classe=$(echo "$LISTE_GROUPES_LOGIN" | sed -rn 's/^Classe_(.*)$/\1/p') 1825 # Les fonctions sont formatees 1826 # en annotation_fond_ecran_admin, 1827 # annotation_fond_ecran_<groupe>,... 1828 # mais si un admin cree une classe 'Classe_admin', et qu'on vire le prefixe 'Classe_', on va avoir une collision de noms. 1829 classe=$(echo "$LISTE_GROUPES_LOGIN" | grep "^Classe_" |head -n1) 1830 if [ ! -z "$classe" ]; then 1831 # PROBLEME AVEC CA... IL NE DOIT PAS ETRE POSSIBLE D APPELER UNE TELLE FONCTION 1832 # Il semble que si... 1833 t=$(grep "function parametres_fond_ecran_$classe()" $REP_BIN_LOCAL/logon) 1834 if [ -n "$t" ]; then 1835 parametres_fond_ecran_$classe 1836 if [ "$generation_fonds_ecran" = "actif" ]; then 1837 annotation_fond_ecran_$classe 1838 1839 temoin="$classe" 1840 classe="$classe" 1841 fi 1842 fi 1843 fi 1844 1845 if [ -z "$temoin" ]; then 1846 t=$(grep "function parametres_fond_ecran_Eleves()" $REP_BIN_LOCAL/logon) 1847 if [ -n "$t" ]; then 1848 parametres_fond_ecran_Eleves 1849 if [ "$generation_fonds_ecran" = "actif" ]; then 1850 annotation_fond_ecran_Eleves 1851 1852 temoin="Eleves" 1853 fi 1854 fi 1855 fi 1856 else 1857 1858 if est_dans_liste "$LISTE_GROUPES_LOGIN" "Administratifs"; then 1859 # Utilisateur membre de: Administratifs 1860 t=$(grep "function parametres_fond_ecran_Administratifs()" $REP_BIN_LOCAL/logon) 1861 if [ -n "$t" ]; then 1862 parametres_fond_ecran_Administratifs 1863 if [ "$generation_fonds_ecran" = "actif" ]; then 1864 annotation_fond_ecran_Administratifs 1865 1866 temoin="Administratifs" 1867 classe="Administratifs" 1868 fi 1869 fi 1870 fi 1871 fi 1872 fi 1873 fi 1874 1875 if [ -n "$temoin" ]; then 1876 # Generation avec les parametres... 1877 1878 # Passage de variable: 1879 base=$temoin 1880 if [ "$base" == "admin" ]; then 1881 orig="Adminse3" 1882 else 1883 orig="$base" 1884 fi 1885 1886 # Generation du fond commun s'il n'existe pas: 1887 if [ ! -e "${dossier_base_fond}/$orig.jpg" ]; then 1888 convert -size ${largeur}x${hauteur} gradient:${couleur1}-${couleur2} jpeg:${dossier_dest_fond}/$orig.jpg 1889 else 1890 cp ${dossier_base_fond}/$orig.jpg ${dossier_dest_fond}/ 1891 fi 1892 1893 #=============================================================== 1894 # Generation de la chaine des infos a afficher: 1895 chaine="" 1896 if [ "$annotation_nom" = "1" ]; then 1897 nom_prenom=$NOM_COMPLET_LOGIN 1898 chaine=$(echo "$nom_prenom" | tr "'ÂÄÀÁÃÄÅÇÊËÈÉÎÏÌÍÑÔÖÒÓÕ¦ÛÜÙÚݾ´áàâäãåçéèêëîïìíñôöðòóõ¨ûüùúýÿ¸" "_AAAAAAACEEEEIIIINOOOOOSUUUUYYZaaaaaaceeeeiiiinoooooosuuuuyyz" | sed -e "s|[^A-Za-z_ -]||g" | sed -e "s|Æ|AE|g" | sed -e "s|¼|OE|g" | sed -e "s|æ|ae|g" | sed -e "s|½|oe|g") 1899 fi 1900 1901 if [ "$annotation_classe" = "1" ]; then 1902 if [ -z "$classe" ]; then 1903 # Cas d'un eleve dans le groupe overfill: 1904 #classe=$(ldapsearch -xLLL -h "$SE3" -b "ou=Groups,$BASE_DN" "(&(memberUid=$LOGIN)(cn=Classe_*))" cn | grep "^cn: " | sed -e "s/^cn: //"|head -n1) 1905 #classe=$(echo "$LISTE_GROUPES_LOGIN" | sed -rn 's/^Classe_(.*)$/\1/p') 1906 classe=$(echo "$LISTE_GROUPES_LOGIN" | grep "^Classe_" |head -n1) 1907 fi 1908 1909 if [ -z "$classe" ]; then 1910 if est_dans_liste "$LISTE_GROUPES_LOGIN" "Profs"; then 1911 classe="Profs" 1912 elif est_dans_liste "$LISTE_GROUPES_LOGIN" "Administratifs"; then 1913 classe="Administratifs" 1914 fi 1915 fi 1916 1917 if [ ! -z "$classe" ]; then 1918 if [ -n "${chaine}" ]; then 1919 chaine="$chaine ($classe)" 1920 else 1921 chaine="$classe" 1922 fi 1923 fi 1924 fi 1925 1926 # Generation de l'image: 1927 if [ -n "$couleur_txt" ]; then 1928 convert -fill ${couleur_txt} -pointsize $taille_police -draw "gravity North text 0,0 '$chaine'" ${dossier_dest_fond}/$orig.jpg ${prefix}${dossier_dest_fond}/fond_ecran_$LOGIN.$ext 1929 else 1930 cp ${dossier_dest_fond}/$orig.jpg ${dossier_dest_fond}/fond_ecran_$LOGIN.$ext 1931 fi 1932 1933 fi 1934 fi 1935 1936 if [ -e /tmp/fond_ecran_${LOGIN}.jpg ]; then 1937 changer_papier_peint /tmp/fond_ecran_${LOGIN}.jpg 1938 fi 1939 fi 1940 } 1941 1942 1943 1944 function supprimer_fond_ecran() { 1945 1946 if [ -z "$LOGIN" ] 1947 then 1948 # La variable LOGIN n'est pas définie. On arrête là. 1949 return 1 1950 fi 1951 1952 if [ -e /tmp/fond_ecran_${LOGIN}.jpg ]; then 1953 rm -f /tmp/fond_ecran_${LOGIN}.jpg 1954 fi 1955 } 1956 1957 1958 1959 1960 ################################################################################ 1961 ################################################################################ 1962 ### ### 1963 ### Fin des définitions de fonctions et autres variables. ### 1964 ### Suivant le paramètre $1 (qui s'appelle $PHASE dans le script) qui est ### 1965 ### passé à ce script, c'est une des quatre fonctions de base qui sera ### 1966 ### appelée. ### 1967 ### ### 1968 ################################################################################ 1969 ################################################################################ 1970 1971 1972 1973 case "$PHASE" in 1974 1975 "initialisation") 1976 initialisation 1977 ;; 1978 1979 "ouverture") 1980 ouverture 1981 ;; 1982 1983 "fermeture") 1984 fermeture 1985 ;; 1986 1987 *) 1988 # On ne fait rien de spécial 1989 true 1990 ;; 1991 1992 esac 1993 1994 1995 1996 exit 0 1997 # Fin du script 1998 ################################################################################ 1999 2000 2001
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Mar 17 22:47:18 2015 | Cross-referenced by PHPXref 0.7.1 |