1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
#!/bin/bash
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# Autore: Michele Furlan - email: michele.furlan(chiocciola)unipd.it - data: 3 magggio 2006 - versione 1.1

# Scopo dello script e' la centralizzazione su server della gestione degli account di utenti distribuiti
# in numerose postazioni client linux.
# Esegue nelle postazioni in rete che possono accedere ad una cartella condivisa (/nfs/root) in un server:
# creazione, cancellazione, cambio password e verifica delle utenze indicate dall amministratore
# in file di testo collocati nella cartella condivisa. Compie le medesime operazioni anche nel server,
# facendo il backup delle home degli utenti prima che essi vengano cancellati.
# Lo script puo' essere eseguito sia nel server che nei client, ma solo nel server si possono applicare tutte le opzioni

# opzioni della riga di comando accettate nel server - non importa l'ordine con cui vengono date:
# -c seguito da -all (crea account su tutte le postazioni) -c pos1 pos2 pos3 ... (crea sulle postazioni indicate)
# -d seguito da -all (cancella tutti) -c pos1 pos2 pos3 ... (cancella sulle postazioni indicate)
# -p seguito da -all (modifica la password utente su tutte le postazioni) -p pos1 pos2 pos3 ... (modifica sulle postazioni indicate)
# -t seguito da -all (testa la presenza degli utenti su tutte le postazioni) -t pos1 pos2 pos3 (testa sulle postazioni indicate)
# -v seguito da -all (genera una lista di account presenti nell insieme delle postazioni) -t pos1 pos2 pos3 (genera sulle postazioni indicate)
# la creazione della home directory dell'utente e pure l'account (o la su cancellazione) sul sever e'
# fatta quando si esprime esplicitamente anche l'opzione -s in aggiunta alle altre
# In un client lo script puo essere eseguito con le sole opzioni -c | -d | -p | -t | -v senza altri argomenti

# I seguenti file di testo devono essere collocati nella directory /nfs e consentirne l' accesso dalle postazioni client
# campi nel file di addusers.txt per la creazione utenti: "Login:Password:GroupName:FullName"
# campi nel file cambiapassword.txt per il cambio della password: "Login:Nuovapassword"
# campo nel file utenti.txt per la cancellazione o la verifica degli utenti: "Login"
# IMPORTANTE: la connessione alle postazioni amministrate avviene via ssh che deve essere configurato per l autologin di root.
# Un modo per abilitare l autologin sicuro consiste nel creare prima nel server con ssh-keygen le chiavi privata e pubblica di autenticazione
# e poi copiare la chiave pubblica ottenuta (id_rsa.pub, o id_dsa.pub) nelle postazioni in /root/.ssh/authorized_keys
#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

set +o verbose   # sopprime output prolisso
set +o "history" # disabilita la traccia della cronologia comandi
set -o noglob    # disabilita espansione pathname
set -o nounset   # segnala come errore variabili non dichiarate
ulimit -t 7200   # non piu di due ore in esecuzione
umask 0000

# +++ SEZIONE VARIABILI GLOBALI +++++++++++++++++++++++++++++++++++++++++++++++++++
declare -r nomeserver=chinfo1                    # specificare qui il solo nome del server privo di FQDN
declare -a -r elencopostazioni=(chinfo5 chinfo6 chinfo7 chinfo8 chinfo9 chinfo10 chinfo11 chinfo12 chinfo13 chinfo14 chinfo15 chinfo16 chinfo17 chinfo18)
declare -r f_home=/nfs/root/                     # directory con i file di gestione utenti, file di log e backup home utenti cancellati
declare -r f_userhome=/nfs                       # directory con le home degli utenti
declare -r f_backup=$f_home"backuphomeutenti"    # cartella contenente il backup delle home degli utenti
declare -r id_gruppo=500                         # id creazione gruppo appartenenza utente

# le seguenti variabili possono anche rimanere immodificate
declare -r s_command=$f_home"$(basename $0)"     # nome dello script
declare -r fileTo=$f_home"addusers.txt"          # file di input con i dati degli utenti da creare
declare -r f_in=$f_home"utenti.txt"              # file con gli utenti da cancellare o verificare
declare -r f_pass=$f_home"cambiapassword.txt"    # file contenente le nuove password per gli utenti
declare -r f_account=$f_home"accountpresenti.txt" # file con gli account globalmente rilevati

declare -r f_elim=$f_home"n_eliminazioni.txt"    # registro il numero delle postazioni in cui ha avuto successo l'eliminazione degli utenti
declare -r reportFile=$f_home"log_esito.txt"     # file di log con l'esito positivo delle elaborazioni
declare -r errorReport=$f_home"log_errori.txt"   # file di log con l'elenco degli errori rilevati
declare -r tempRecord="/tmp/REC_tmp_"${HOSTNAME}".txt"
declare -r tempAddusers=$f_home"tmpAddusers.txt"
declare -r f_null=/dev/null           # file scarico output comandi fittizio
eServer="NO"                          # esecuzione dello script anche nel server ?
isServer="NO"                         # e il server che esegue lo script ?
declare -a postazioni=()    # elenco postazioni specificate nella riga di comando da confrontare con elencopostazioni
declare -a opzioniriga=()   # opzioni riga comando
declare -i azione=0         # 1==cancella : 2==crea : 3==cambio password : 4==test : 0==non assegnata
declare i=; declare j=
# ++++++ FINE SEZIONE VARIABILI GLOBALI ++++++++++++++++++++++++++++++++++++++++++

 if [[ $(id -u 2>$f_null) -ne 0 ]]; then # solo root deve poter eseguire lo script
    echo "Errore: devi essere utente ROOT per eseguire lo script"
    exit 1  # uscita immediata dallo script
 fi

# ++++++++ INIZIO SEZIONE FUNZIONI ++++++++++++++++++++++++++++++++++++++++++++++++++++
rmfiletemp() {
   rm -f $tempAddusers &>$f_null # cancello file temporanei
   rm -f $tempRecord &>$f_null
   rm -f $f_elim &>$f_null
} # fine funzione cancellazione file temporanei

verificautenza() {
 local utente=""; local esistenti=0; local esaminati=0

if [[ ! -e $f_in ]]; then  # deve esistere il file di input contenente gli utenti da verificare
   echo "${HOSTNAME} $(date '+%e %B %Y %H:%M'): errore in verifica account, il file $f_in non esiste" >> $errorReport
   return 1  # ritorno codice di errore
fi

# preservo il descrittore standard input (0)
exec 8<&0
# stdin diventa il file $f1
exec 0<$f_in

 while read utente; do   # lettura dei record
    ((esaminati++))
    id -u ${utente} &>$f_null    # verifica esistenza dell'utente
    [[ $? -eq 0 ]] && ((esistenti++))     # conteggio utenti esistenti
 done  # fine ciclo while

# ripristino del descrittore stdin e  chiusura del descrittore 8
exec 0<&8; exec 8<&-
echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): account da verificare=$esaminati -- esistenti=$esistenti" >>$reportFile
return 0
} # fine funzione verifica utenza

cambiapassword() {
local utente=""; local f_change=0; local f_input=0    # definizione variabili locali
local f_err_change=0; local nome=""; local password=""; local posizione=0

if [[ ! -r $f_pass ]]; then  # deve esistere il file di input contenente le password da cambiare
   echo "- ${HOSTNAME} errore in modifica password: il file $f_pass non esiste" >> $errorReport
   return 1
fi

# preservo il descrittore standard input (0) - # stdin diventa il file $f_pass
exec 8<&0; exec 0<$f_pass

while read utente; do   # lettura dei record
 ((f_input++))          # contatore record utenti letti
 posizione=$(expr index "${utente}" :)  # 0 se non trovato il divisorio :

 if [[ $posizione -eq 0 ]]; then
    echo "- ${HOSTNAME} il file: $f_pass manca del campo divisiorio >:< in record $f_input" >>$errorReport
    return 1
 else
    nome=${utente:0:$posizione-1}
    if [[ ${#nome} -eq 0 ]]; then     # verifica lunghezza stringa nome utente
        echo "- ${HOSTNAME} il file $f_pass manca del campo utente in record: $f_input" >>$errorReport
        return 1
    else
        password=${utente:$posizione}
        if [[ ${#password} -eq 0 ]]; then
           echo "- ${HOSTNAME} il file $f_pass ha password vuota in record: $f_input" >>$errorReport
           return 1
        fi
    fi
 fi

 id -u "${nome}" &>$f_null # verifica esistenza dell'utente
 if [[ $? -eq 0 ]]; then  # procedo con il cambio della password
   (sleep 0.2;echo "${password}";sleep 0.2;echo "${password}") | passwd $nome &>$f_null
      if [[ $? -eq 0 ]]; then
          echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): password utente= $nome modificata" >>$reportFile
          ((f_change++))
      else
          echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): modifica password utente= $nome fallita, errore bash passwd" >>$errorReport
          return 1
      fi
 else
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): modifica password non eseguita perche utente= $nome inesistente" >>$errorReport
 fi
done  # fine ciclo while

# ripristino del descrittore stdin e chiusura del descrittore 8
exec 0<&8; exec 8<&-

nome=$(echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): utenti da modificare=$f_input -- utenti la cui password e stata modificata=$f_change")
echo $nome >>$reportFile
return 0
} # fine funzione cambia password

eseguibackup() {  # riceve come argomento il nome dell'utente
# Verifica esistenza cartella di backup ed eventuale sua creazione
local utente="$1"

 if [[ ! -d $f_backup ]]; then
     mkdir -p $f_backup &>$f_null
     if [[ $? -ne 0 ]]; then
        echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): cartella ${f_backup} non creata"  >>$errorReport
        return 1
     fi
 fi
 if [[ -d "${f_userhome}/${utente}" ]]; then
     tar --atime-preserve -P --preserve -cjf "${f_backup}/${utente}.tar.bz2" "${f_userhome}/${utente}" &>$f_null
      if [[ $? -eq 0 ]]; then
            echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): backup utente $utente eseguito" >> $reportFile
            # cancellazione home directory
            rm -r -f "${f_home}${utente}" &>$f_null
              if [[ $? -eq 0 ]]; then
                  echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): eliminata home ${f_home}${utente}" >> $reportFile
              else
                  echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): home ${f_home}${utente} non eliminata"  >>$errorReport
              fi
      else
            echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): utente ${utente} backup non riuscito"  >>$errorReport
            return 1   # se il backup fallisce errore grave e va considerato
      fi
 else
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): directory $f_userhome/$utente inesistente"  >>$errorReport
 fi
return 0 # successo
} # fine funzione esegui backup

eliminautenti() {
local utente=; local f_input=0; local f_err_deluser=0; local f_del=0

if [[ ! -r $f_in ]]; then  # deve esistere il file di input contenente gli utenti da cancellare
   echo "${HOSTNAME} $(date '+%e %B %Y %H:%M'): errore in cancellazione utenti, il file $f_in e inleggibile " >> $errorReport
   return 1
fi

if [[ -d /tmp ]]; then   # verifica esistenza directory
   cp -f -p /etc/passwd "/tmp/"${HOSTNAME}"_passwd" &>$f_null  # conservo i file cancellati
   cp -f -p /etc/shadow "/tmp/"${HOSTNAME}"_shadow" &>$f_null
fi

until ! read utente; do
 ((f_input++))              # contatore utenti letti
 id -u "${utente}" &>$f_null  # verifica esistenza dell'utente
 if [[ $? -eq 0 ]]; then
   if [[ $(id -u "${utente}" 2>$f_null) -gt 100 ]]; then  # non possono essere cancellati utenti con UID < 100 perche di sistema
      if [[ $eServer == "SI" ]]; then  # utente sul server
          eseguibackup "${utente}"     # occorre eseguire il backup della home con successo prima di poter eliminare un utente
            if [[ $? -eq 0 ]]; then
               userdel -r "${utente}" &>$f_null  # con l'opzione -r cancello sia l utente che la home
            else
               return 1
            fi
      else  # utente normale su una delle postazioni
          userdel "${utente}" &>$f_null
      fi    # fine if eServer
      if [[ $? -eq 0 ]]; then
          echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): utente ${utente} eliminato" >>$reportFile
          ((f_del++))
      else
          echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): cancellazione utente ${utente} fallita errore bash userdel" >>$errorReport
          ((f_err_deluser++))
      fi
   else
     echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): cancellazione utente ${utente} fallita errore UID < 100 userdel" >>$errorReport
     return 1
   fi  # fine if verifica uid utente
 else
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): cancellazione utente ${utente} non eseguita perche inesistente" >>$errorReport
      ((f_err_deluser++))
 fi
done < $f_in

echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): utenti da eliminare=$f_input -- utenti cancellati=$f_del -- errori userdel=$f_err_deluser" >>$reportFile
return 0  # successo
} # fine funzione eliminautenti

creazioneutenti() {  # funzione di creazione utenti
# Inizializzazione variabili locali
local recCount=0; local utenti_creati=0; local errorMsg=""; local errorFlag=n; local newPass=""; local Record=""
local name=""; local group=""; local password=""; local un=""; local usrid=""; local userid=""; local groupid=""

rmfiletemp # cancellazione file temporanei
  if [[ ! -f $fileTo ]]; then  # deve esistere il file di input contenente gli utenti
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): il file $fileTo non esiste" >> $errorReport
      return 1
  fi

# until loop fino ad esaurimento dei records nel file fileTo
until ! read Record; do
   ((recCount++)) # recCount == record esaminati
   errorFlag=n
# ogni linea esaminata nel loop va scritta in tempRecord per generare poi il nuovo file con gli id numerici degli utenti
   echo $Record > $tempRecord

# assignazione di ogni campo nel record estratto alle variabili
   if [[ $eServer == "NO" ]]; then   # non c'e' lo usrid nel fileTo quando si creano gli utenti sul server
      usrid=`cut -d: -f5 $tempRecord 2>$f_null`
   fi
      name=`cut -d: -f4 $tempRecord 2>$f_null`
      group=`cut -d: -f3 $tempRecord 2>$f_null`
      password=`cut -d: -f2 $tempRecord 2>$f_null`
      un=`cut -d: -f1 $tempRecord 2>$f_null`
# verifica presenza del campo gruppo
   if [[ ${#group} == 0 ]]; then
      errorFlag=y
      errorMsg="${errorMsg}- ${HOSTNAME}: campo gruppo non specificato nel record n. $recCount\n"
   else
      # verifica esistenza gruppo altrimenti viene creato
      cut -d: -f1 /etc/group 2>$f_null | grep -q -E -i -e ^"${group}"$ &>$f_null
      if [[ $? -ne 0 ]]; then                        # se non trovato creazione del gruppo
         groupadd -r $group -g $id_gruppo &>$f_null  # ID del gruppo - eventualmente modificarlo
         if [[ $? -ne 0 ]]; then
             echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): creazione gruppo= ${group} fallita errore bash groupadd" >>$errorReport
             return 1     # errore grave
         else
             echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): eseguita creazione gruppo ${group}" >>$reportFile
         fi
      fi
   fi # Fine if verifica presenza del campo gruppo

# Verifica presenza del campo nome utente il FullName
   if [[ ${#name} -eq 0 ]]; then
      errorFlag=y
      errorMsg="${errorMsg}- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): in file $fileTo campo nome completo non specificato nel record $recCount\n"
   fi
# Verifica presenza del campo username o login
   if [[ ${#un} -eq 0 ]]; then
      errorFlag=y
      errorMsg="${errorMsg}- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): in file $fileTo campo login non specificato nel record $recCount\n"
   fi
# Verifica prensenza del campo password
   if [[ ${#password} -eq 0 ]]; then   # non sono ammesse password vuote
      errorFlag=y
      errorMsg="${errorMsg}- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): in file $fileTo campo password non specificato nel record $recCount\n"
   fi
# Verifica prensenza del campo uid
   if [[ ${#usrid} -eq 0 && $eServer == "NO" ]]; then  # lo userid non esiste in creazione utente nel server
      errorFlag=y                                      # ma deve esistere quando creo gli account nei client
      errorMsg="${errorMsg}- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): in file $fileTo campo userid non specificato nel record $recCount\n"
   fi

   if [[ $errorFlag == y ]]; then
      echo -n -e "${errorMsg}" >> $errorReport
      return 1  # teminazione immediata della funzione con codice errore di ritorno
   else

# creazione della password criptata per il comando useradd
   newPass=$(openssl passwd -quiet -1 "${password}" 2>$f_null)  # password tipo md5
# l'utente viene creato se non esiste
   id -u "${un}" &>$f_null
   if [[ $? -ne 0 ]]; then
        useradd -D -b "${f_userhome}" -s /bin/bash &>$f_null    # impostazioni di creazione dell'utente
# -g imposta il gruppo, -u userid -non viene forzata la creazione della directory
     if [[ $eServer == "NO" ]]; then
        useradd -g $group -p "${newPass}" -c "${name}" -u $usrid "${un}" &>$f_null
     else # crea anche la home directory con l'opzione -m
        useradd -g $group -p "${newPass}" -c "${name}" -m "${un}" &>$f_null
     fi  # fine if creazione utente
# se il comando precedente e' andato a buon fine
   if [[ $? -eq 0 ]]; then   # conteggio utenti creati
      ((utenti_creati++))
      # ottengo userid e grroup id per ogni utente creato - verifica incrociata
      userid=`id -u $un 2>$f_null`
      groupid=`id -g $un 2>$f_null`
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): utente= $name:$un:$userid:$groupid: creato correttamente" >> $reportFile
      [[ $eServer == "SI" ]] &&  echo "$un:$password:$group:$name:$userid" >> $tempAddusers
   else
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): account= ${name}: creazione fallita errore useradd" >> $errorReport
      rmfiletemp
      return 1  # teminazione funzione con codice errore di ritorno - errore grave
   fi # fine if conteggio utenti creati
   else
      echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): utente= $name non creato perche gia presente" >> $errorReport
   fi # fine id utente >$f_null
   fi # fine if errorFlag
done < $fileTo

echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): creati $utenti_creati nuovi utenti su $recCount totali" >> $reportFile
     [[ $eServer == "SI" ]] && mv -f $tempAddusers $fileTo &>$f_null
rmfiletemp  # cancellazione file temporanei
return 0    # OK
} # fine funzione creazioneutenti

crealistaaccount() {
local riga=; local tmpFile=/tmp/listaccountlocali.txt; local f_inpass=/etc/passwd
local un=; local idutente=; local nomeFull=; local account_trovati=0; local recCount=0

  if [[ ! -f $f_account ]]; then
     touch $f_account &>$f_null
     if [[ $? -ne 0 ]]; then
        echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): il file $f_account non puo essere creato" >> $errorReport
        return 1
     fi
  fi
  if [[ -r $f_account && -w $f_account ]]; then
     cp -a -f $f_account $tmpFile &>$f_null      # opero sul file locale per velocizzare l esecuzione
       if [[ $? -ne 0 || ! -w $tmpFile ]]; then
          echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): errore di creazione file locale $tmpFile" >> $errorReport
          return 1
       fi
  fi

# until loop fino ad esaurimento dei records nel file fileTo
until ! read riga; do
  ((recCount++))
  echo $riga >$tempRecord

  nomeFull=$(cut -d: -f5 $tempRecord 2>$f_null)
  idutente=$(cut -d: -f3 $tempRecord 2>$f_null)
  un=$(cut -d: -f1 $tempRecord 2>$f_null)

  if [[ $idutente -ge 100 && ${#un} -ne 0 ]]; then   # non considero gli utenti di sistema
       # verifico che l'utente non sia gia presente
     cut -d: -f1 $tmpFile 2>$f_null | grep -q -E -i -e ^"${un}"$ &>$f_null
     if [[ $? -ne 0 ]]; then  # utente non trovato percio lo aggiungo alla lista
        ((account_trovati++))
        echo "${un}:${idutente}:${nomeFull}:${HOSTNAME}" >> $tmpFile
     fi
  fi
done < $f_inpass

echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): trovati $account_trovati nuovi account su $recCount totali in /etc/passwd" >> $reportFile
mv -f $tmpFile $f_account &>$f_null    # copio sul server
return 0  # successo in ogni caso - anche se errore mv
} # fine funzione crealistaaccount

onlinehelp() {
 local str=""
   if [[ $isServer == "SI" ]]; then
     str="\n$0 -c | -d | -p | -t | -v -s [-all] [postazione1 postazione2 ...]\n"   # in $0 nome dello script
     str="${str}  -c crea utenti da ${fileTo}\n"
     str="${str}  -d cancella utenti da ${f_in}\n"
     str="${str}  -p cambia la password degli utenti da ${f_pass}\n"
     str="${str}  -t verifica presenza account da ${f_in}\n"
     str="${str}  -v crea lista account in ${f_account}\n"
     str="${str}  -s include il server\n"
     str="${str}  -all agisce su tutte le postazioni\n"
     str="${str}  il server attuale e: ${nomeserver}\n"
     str="${str}  le postazioni amministrate sono: ${elencopostazioni[@]}\n"
   else  # opzioni valide in una postazione client
     str="\n$0  -c | -d | -p | -t | -v\n"   # in $0 nome dello script
     str="${str}  -c crea utenti da ${fileTo}\n"
     str="${str}  -d cancella utenti da ${f_in}\n"
     str="${str}  -p cambia la password degli utenti da ${f_pass}\n"
     str="${str}  -t verifica presenza account da ${f_in}\n"
     str="${str}  -v crea lista account in ${f_account}\n"
   fi
 echo -e -n "${str}\n"
}  # fine funzione onlinehelp

# la funzione preserva e verifica le opzioni della riga di comando impartite dall'amministratore nell'esecuzione dello script
esamerigacomando() {
 local k=
 for k in ${elencopostazioni[@]}; do
   if [[ "$1" == "$k" ]]; then
      postazioni[${#postazioni[*]}]="$1"   # si popola l'array con le postazioni da considerare
      return 0
   fi
 done
return 1
} # fine funzione esame riga comando

preservaopzioni() {
 for i in $(echo -n $1); do
     opzioniriga[${#opzioniriga[*]}]="$i"
 done
} # fine funzione preservaopzioni

rispostapostazioni() {  # verifica che le postazioni rispondano
 for i in ${postazioni[@]}; do
   ping -q -c 1 "${i}" &>$f_null
     if [[ $? -ne 0 ]]; then
         echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): la postazione= $i non risponde" >> $errorReport
         echo "La postazione $i non risponde - lo script in server $nomeserver non sara eseguito"
         return 1  # una delle postazioni non risponde
     fi
 done
return 0  # successo - valore di ritorno che serve alle elaborazioni successive
} # fine funzione rispostapostazioni

verificaserver() { # la funzione imposta la variabile eServer previo controllo hostname
  if [[ $(hostname -s) == $nomeserver ]]; then
      isServer="SI"
  else
      isServer="NO"
  fi
# verifica esistenza cartella $f_home - deve esistere perche' contiene script e file dati da interpretare e file log da scrivere
  if [[ ! -e $f_home || ! -w $f_home || ! -r $f_home ]]; then
      echo " - ${HOSTNAME} errore: deve esistere la cartella $f_home nel server $nomeserver com permessi r/w"
      exit 1  # teminazione immediata esecuzione script
  fi

  touch ${tempRecord} &>$f_null  # verifico la possibilita di leggere scrivere in /tmp
  if [[ $? -ne 0 || ! -w ${tempRecord} || ! -r ${tempRecord} ]]; then
     if [[ $isServer == "SI" ]]; then
        echo " - ${HOSTNAME}: errore di accesso in ${tempRecord}"
     else
        echo " - ${HOSTNAME}: errore di accesso in ${tempRecord}" >> $errorReport
     fi
  exit 1
  fi
rm -f "${tempRecord}" &>$f_null
} # fine funzione verificaserver

verificapostazione() { # solo le postazioni amministrate possono eseguire lo script
  if [[ $isServer == "NO" ]]; then
      for i in ${elencopostazioni[@]}; do
        if [[ "$(hostname -s)" == "$i" ]]; then
            return 0   # OK
        fi
      done
  else
     return 0 # OK continuo esecuzione script
  fi
echo " - ${HOSTNAME} $(date '+%e %B %Y %H:%M'): la postazione non appartiene a quelle amministrate" >> $errorReport
exit 1 # interruzione esecuzione script
} # fine funzione verificapostazione

verificapermessi() {
local f_nometest=$f_home"cancellami.txt"
  touch $f_nometest &>$f_null
    if [[ $? -ne 0 ]]; then
       echo " - ${HOSTNAME} creazione $f_nometest fallito"; exit 1
    fi
    if [[ ! -w $f_nometest ]]; then
       echo " - ${HOSTNAME} permesso scrittura $f_nometest fallito"; exit 1
    fi
    if [[ ! -r $f_nometest ]]; then
        echo " - ${HOSTNAME} permesso lettura $f_nometest fallito"; exit 1
    fi
  rm -f "$f_nometest" &>$f_null
return 0
} # fine funzione verifica permessi

errore_ssh() {
  echo "- $nomeserver $(date '+%e %B %Y %H:%M'): errore ssh di $2 in postazione= $1" >> $errorReport
  echo "- $nomeserver errore ssh in $1"
} # fine funzione errore_ssh

# ++++++++ FINE SEZIONE FUNZIONI ++++++++++++++++++++++++++++++++++++++++++
# ++++++++ INIZIO ELABORAZIONE ++++++++++++++++++++++++++++++++++++++++++++

preservaopzioni "$*"   # in $* ci sono tutti i parametri ricevuti dallo script dalla riga di comando
verificaserver
verificapermessi
verificapostazione

if [[ $# -eq 0 ]]; then  # devono essere indicate le opzioni di riga di comando
   onlinehelp
   exit 1   # l'esecuzione dello script deve interrompersi
fi

# scansione delle opzioni della riga di comando ed esecuzione delle azioni espresse
for i in ${opzioniriga[@]}; do
  case $i in
    -d) azione=1 ;;
    -c) azione=2 ;;
    -p) azione=3 ;;
    -t) azione=4 ;;
    -v) azione=5 ;;
    -s) if [[ $isServer == "SI" ]]; then
           eServer="SI"
        else
           eServer="NO"
        fi ;;
    -all) for j in ${elencopostazioni[@]}; do   # copia integrale delle postazioni predefinite
             postazioni[${#postazioni[*]}]="$j"
          done ;;
    *) # qui si verifica la presenza del nome delle postazioni
        esamerigacomando "$i"
         if [[ $? -eq 1 ]]; then
               echo "- ${HOSTNAME}: l'opzione $i non รจ una opzione valida"
               onlinehelp  # messaggio informatico
               exit 1      # termino l'esecuzione dello script
         fi ;;
  esac
done

# sezione azione da intraprendere +++++++++++++++++++++++++++++++
# prima di tutto si privilegia l'esecuzione delle azioni sul server
# azione  1==cancella : 2==crea : 3==cambio password: 4==test
case $azione in
     0) onlinehelp  # indefinita perche non sono state specificate le opzioni di comando
        exit 1 ;;
     1) if [[ $isServer == "NO" ]]; then  # prioritariamente gli utenti vanno eliminati nelle postazioni
           eliminautenti
           if [[ $? -eq 0 ]]; then        # tengo il conteggio delle postazioni in cui tutti gli utenti sono stati eliminati con successo
              if [[ -w $f_elim && -r $f_elim ]]; then   # verifica permesso lettura scrittura
                  echo -n $(expr $(cat $f_elim) + 1) >$f_elim  # +1 per successo
              else
                  echo -n 1 >$f_elim      # conteggio eliminazione eseguita con successo su una singola postazione
              fi
           fi
        else
           rm -f $f_elim &>$f_null
           if [[ 0 -ne ${#postazioni[@]} ]]; then
              rispostapostazioni   # esigo il contatto con tutte le postazioni designate
              if [[ $? -eq 0 ]]; then
                 for i in ${postazioni[@]}; do
                   echo "- cancellazione utenti in corso nella postazione: $i"
                   ssh -n -x -q -l root "$i" "bash $s_command -d" &>$f_null # connessione remota sicura ssh
                   [[ $? -ne 0 ]] && errore_ssh "$i" "cancellazione"
                 done
              else
                 exit 1  # e richiesta la risposta delle postazioni
              fi
           fi
        fi # fine if isServer
        if [[ $eServer == "SI" ]]; then
           echo "- cancellazione utenti in corso nel server $nomeserver"
           if [[ -f $f_elim && -r $f_elim ]]; then  # verifica che in tutte le postazioni gli utenti siano stati cancellati correttamente
              if [[ $(cat $f_elim) -eq ${#postazioni[*]} || ${#postazioni[*]} -eq 0 ]]; then
                  eliminautenti
                  if [[ $? -ne 0 ]]; then
                       echo "- $nomeserver $(date '+%e %B %Y %H:%M'): eliminazione utenti sul server fallita"
                       rm -f $f_elim &>$f_null; exit 1
                  fi
              else
                  echo "- $nomeserver: gli utenti nel server non saranno cancellati causa errore di eliminazione nelle postazioni"
              fi
           else
              eliminautenti  # elimino gli utenti nel server
              if [[ $? -ne 0 ]]; then
                 echo "- $nomeserver $(date '+%e %B %Y %H:%M'): eliminazione utenti sul server fallita"
                 rm -f $f_elim &>$f_null; exit 1
              fi
           fi
        fi
        { [[ $isServer == "SI" ]] && rm -f $f_elim &>$f_null; } ;;
     2) if [[ $eServer == "SI" || $isServer == "NO" ]]; then  # priorita di creazione utenti sul server
           creazioneutenti
           if [[ $? -ne 0 && $isServer == "SI" ]]; then
              echo "- errore nella creazione degli utenti nel server $nomeserver - script interrotto"
              echo "- esaminare il file $errorReport per la ricerca del tipo di errore"
              exit 1   # terminazione immediata
           fi
        fi
        if [[ 0 -ne ${#postazioni[*]} && $isServer == "SI" ]]; then # significa che lo script viene eseguito sul server
           rispostapostazioni   # esigo il contatto con tutte le postazioni designate
             if [[ $? -eq 0 ]]; then
                 for i in ${postazioni[@]}; do
                    echo "- creazione utenti in corso nella postazione: $i"
                    ssh -n -x -q -l root "$i" "bash $s_command -c" &>$f_null # connessione remota sicura ssh
                    [[ $? -ne 0 ]] && errore_ssh "$i" "creazione account"
                 done
             fi
        fi ;;
     3) if [[ $eServer == "SI" || $isServer == "NO" ]]; then
           cambiapassword
           if [[ $? -ne 0 && $isServer == "SI" ]]; then
              echo "- errore nel cambiamento delle password nel server $nomeserver - script interrotto"
              echo "- esaminare il file $errorReport per la ricerca del tipo di errore"
              exit 1  # terminazione immediata
           fi
        fi
        if [[ 0 -ne ${#postazioni[*]} && $isServer == "SI" ]]; then
           rispostapostazioni   # esigo il contatto con tutte le postazioni designate
           if [[ $? -eq 0 ]]; then
              for i in ${postazioni[@]}; do
                  echo "- cambiamento password utenti in corso nella postazione: $i"
                  ssh -n -x -q -l root "$i" "bash $s_command -p" &>$f_null # connessione remota sicura ssh
                  [[ $? -ne 0 ]] && errore_ssh "$i" "cambio password"
              done
           fi  # fine if verifica risposta postazioni
        fi ;;
     4) if [[ 0 -ne ${#postazioni[*]} && $isServer == "SI" ]]; then # mando prima in esecuzione nelle postazioni
           rispostapostazioni   # esigo il contatto con tutte le postazioni designate
           if [[ $? -eq 0 ]]; then
              for i in ${postazioni[@]}; do
                  echo "- $nomeserver verifica presenza account in corso nella postazione: $i"
                  ssh -n -x -q -l root "$i" "bash $s_command -t" &>$f_null # connessione remota sicura ssh
                  [[ $? -ne 0 ]] && errore_ssh "$i" "verifica presenza account"
              done
           fi  # fine if verifica risposta postazioni
        fi
        if [[ $eServer == "SI" || $isServer == "NO" ]]; then
           verificautenza
        fi ;;
     5) if [[ 0 -ne ${#postazioni[*]} && $isServer == "SI" ]]; then # mando prima in esecuzione nelle postazioni
           rispostapostazioni   # esigo il contatto con tutte le postazioni designate
           if [[ $? -eq 0 ]]; then
              for i in ${postazioni[@]}; do
                  echo "- $nomeserver creazione lista account in corso nella postazione: $i"
                  ssh -n -x -q -l root "$i" "bash $s_command -v" &>$f_null # connessione remota sicura ssh
                  [[ $? -ne 0 ]] && errore_ssh "$i" "creazione lista account"
              done
           fi  # fine if verifica risposta postazioni
        fi
        if [[ $eServer == "SI" || $isServer == "NO" ]]; then
           crealistaaccount
        fi ;;
     *) echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): nessuna azione eseguita" >> $errorReport ;;
esac

if [[ $isServer == "SI" ]]; then
   echo "- $nomeserver $(date '+%e %B %Y %H:%M'): esecuzione script completata con successo in $SECONDS secondi"
else
   echo "- ${HOSTNAME} $(date '+%e %B %Y %H:%M'): esecuzione script completata con successo in $SECONDS secondi" >> $reportFile
fi