Subversion Repositories cms

Rev

Rev 11 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
11 gdo 1
#!/usr/bin/perl
2
# ---------------------------------------------------------------------- #
3
# Copyright: (C) 2002 Leader.IT S.r.l. <http://leader.it>
4
# Authors: Guido Brugnara <gdo@leader.it>
5
#
6
# $Revision: 16 $
7
# ---------------------------------------------------------------------- #
8
#
9
# richiamata da samba ad ogni connessione della share 'netlogon'
10
# tipicamente viene chiamata ad ogni connessione o quando l'utente
11
# dovesse accedervi manualmente
12
#
13
require 5.002;
16 gdo 14
open STDERR, ">>/var/log/samba_netlogon.log" || die "Errore [$!] apertura file '/var/log/samba_netlogon.log'\n";
11 gdo 15
 
16
$Mode = shift;
17
$User = shift;
18
$Group = shift;
19
$Luser = shift;
20
$Machine = shift; 
21
$IPmachine = shift; 
22
$Server = shift;
23
$Platform = shift; ## O.S. platform: Win95 Win2k ...
24
 
25
# flag installazione poweroff (alpha stage)
26
$inst_poweroff=0;
27
$reboot_poweroff=0;
28
 
29
# flag lancio vnc su tutti gli utenti
30
$startVnc = 1;
31
$startVncAll = 1;
32
$startVncDelay = 0;
33
$startBrowseDelay = 0;
34
 
35
# TIMEOUT controllo stato di Logon in 1/10 di secondi
36
$CheckTimeoutStart=1200;
37
$CheckTimeoutContinue=400;
38
 
39
# orario per i log
40
my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
41
my $time = sprintf("%04d/%02d/%02d %02d:%02d:%02d.%03d", 1900+$year, $mon+1, $mday, $hour, $min, $sec, $2);
42
 
43
my $DEBUG=1;
44
umask '0007';
45
use POSIX 'setsid';
46
use IO::Select;
47
use IO::Socket::INET;
48
 
49
my $samba_group = getgrnam('samba');
50
 
16 gdo 51
 
11 gdo 52
# =============================================================== SHARE
53
if($Machine eq $Server){
54
  # create share if not exist
55
  # usata per l'autenticazione di squid
56
  if( ! -d "/home/samba/machine/$IPmachine"){
57
    new_dir("/home/samba/machine/$IPmachine", 0750);
58
    symlink "/etc/samba/addons/proxyauth",  "/home/samba/machine/$IPmachine/proxyauth";
59
  }
60
  $DEBUG && warn "calling machine is server $Server\n";
61
  exit 0;
62
}
63
# create share if not exist
64
if( ! -d "/home/samba/machine/$IPmachine"){
65
  new_dir("/home/samba/machine/$IPmachine", 0750);
66
  new_dir("/home/samba/machine/$IPmachine/.system", 0750);
67
  symlink "/etc/samba/addons/config.reg", "/home/samba/machine/$IPmachine/.system/.config.reg";
68
  new_dir("/home/samba/machine/$IPmachine/.system/.logs", 0730);
69
}
70
 
71
# individuo indirizzo IP del Server
16 gdo 72
$NET=$IPmachine;
73
$NET=~s/\.(\d+)$/./;
74
open IFCONFIG, "ifconfig |";
75
while(<IFCONFIG>){
76
  ### inet addr:192.168.8.120  Bcast:192.168.8.255  Mask:255.255.255.0
77
  if(m/inet addr:(\d+\.\d+\.\d+\.\d+)\s+Bcast:$NET/){
78
    $IP_SERVER=$1;
11 gdo 79
    last;
16 gdo 80
  }  
11 gdo 81
}
16 gdo 82
close IFCONFIG;
83
($IP_SERVER) || die "No server IP on network $NET\n";
11 gdo 84
 
16 gdo 85
# individuo indirizzo IP del Server
86
#use Net::DNS;
87
#my $res = new Net::DNS::Resolver;
88
#my $query = $res->search($Server);
89
#if($query){
90
#  foreach my $rr ($query->answer) {
91
#    next unless $rr->type eq "A";
92
#    $IP_SERVER=$rr->address;
93
#    last;
94
#  }
95
#}else{
96
#  print STDERR "no dns\n";
97
#  die "query failed: ", $res->errorstring, "\n";
98
#}
99
 
11 gdo 100
# =============================================================== SQL CONNECTION
101
use DBI;
102
my $dbh = DBI->connect('dbi:Pg:dbname=cms;host=localhost', 'cms', 'cmsutil') || die "DBI Error open database: ".DBI::errstr."\n";
103
$dbh->{RaiseError} = 1;
104
$dbh->{InactiveDestroy} = 1;
105
$dbh->{AutoCommit} = 1;
106
$dbh->do('set DateStyle to SQL, EUROPEAN');
107
# =============================================================== LOAD DATA
108
my $sthloadip = $dbh->prepare("select pcname, pcstatus, usrid, id, osversion  from classlayout where pcip = ? and pcstatus != 'PCBLANK'");
109
my $sthloaduser = $dbh->prepare("select pcname, pcstatus, pcip from classlayout where usrid = ? and pcstatus != 'PCBLANK'");
110
my $sthuser = $dbh->prepare('select profile from usr where id=?');
111
my $sthipteacher = $dbh->prepare("select class.id as class,cl1.id as site,ipteacher from class,classlayout as cl1, classlayout as cl2 where ipteacher=cl1.pcip and cl1.id=cl2.id and cl2.pcip=?");
112
my $sthuserroom = $dbh->prepare("select class.id as class, classlayout.id as roomteacher, cl.id as room, classlayout.pcname as pcteacher, class.ipteacher as ipteacher from class,classlayout,usrclass,classlayout as cl where classlayout.pcip=class.ipteacher and class.id=usrclass.classid and usrclass.usrid=? and cl.pcip=? and (classlayout.id=cl.id or cl.id=class.classroompersistent)");
113
 
114
# =============================================================== UPDATE DATA
115
my $sthupdate = $dbh->prepare('update classlayout set pcname = ?, pcstatus = ?, usrid = ?, connect = ?  where pcip = ?');
116
my $sthstatus = $dbh->prepare('update classlayout set pcstatus = ? where pcip = ?');
117
my $sthosversion = $dbh->prepare('update classlayout set osversion = ? where pcip = ?');
118
 
119
sub copy_file($$$){
120
  my($source, $dest, $perm)=@_;
121
  # copio il file
122
  system 'cp', $source, $dest;
123
  chmod $perm, $dest;
124
  chown 0, $samba_group, $dest;
125
}
126
sub new_dir($$){
127
  my($name,$perm)=@_;
128
  mkdir $name;
129
  chmod $perm, $name;
130
  chown 0, $samba_group, $name;  
131
}
132
 
133
# delete previous file
134
my $LOG="/home/samba/machine/$IPmachine/.system/.logs/.$IPmachine.log";
135
if(-f $LOG){
136
  unlink $LOG;
137
}
138
my $STARTUP="/home/samba/machine/$IPmachine/.system/.startup.bat";
139
my $LOGON="/home/samba/machine/$IPmachine/.system/.logon.bat";
140
 
16 gdo 141
# if(-f $LOGON){
142
#    unlink $LOGON;
143
#  }
11 gdo 144
 
16 gdo 145
#  if(-f $STARTUP){
146
#    unlink $STARTUP;
147
#  }
11 gdo 148
 
149
my $OTU="/home/samba/machine/$IPmachine/.system/.otu.exe";
150
my $POWEROFF="/home/samba/machine/$IPmachine/.system/.poweroff.exe";
151
 
152
if( $Mode eq '-preexec'){
153
  $DEBUG && print STDERR "preexec $IPmachine $User $Machine $time $Platform\n";
154
  # link <group>.POL to CONFIG.POL
155
  my $configpol = "/home/samba/machine/$IPmachine/CONFIG.POL";
156
  unlink $configpol;
157
  if( -f "/etc/samba/addons/$User.pol"){
158
    symlink "/etc/samba/addons/$User.pol", $configpol; 
159
  }else{
160
    if( -f "/etc/samba/addons/$Group.pol"){
161
      symlink "/etc/samba/addons/$Group.pol", $configpol;
162
    }else{
163
      # standard CONFIG.POL
164
      symlink "/etc/samba/addons/config.pol", $configpol;
165
    }
166
  }
167
  # profilo utente
168
  $sthuser->execute($User);
169
  my($UserProfile) = $sthuser->fetchrow_array;
170
  $DEBUG && print STDERR "user '$User' with profile '$UserProfile'\n";
171
  # verifico se c'è già un utente connesso con lo stesso login
172
  $sthloadip->execute($IPmachine);
173
  my @rowip = $sthloadip->fetchrow_array;
174
  if(@rowip){
175
    my($pcname, $pcstatus, $usrid, $id, $osversion)=@rowip;
176
    # esiste il record
177
    if($usrid eq $User && $pcstatus eq 'PCLOGON' ){
178
      # utente gia connesso su quella stessa macchina
179
      $DEBUG && print STDERR "preexec: user $User already connected on same machine $pcname\n";
180
      exit;
181
    }else{
182
      if(lc $UserProfile eq 'student'){
183
        # verifico se l'utente è realmente connesso sul PC di indirizzo IP
184
        $sthloaduser->execute($User); # select pcname, pcstatus, pcip from classlayout where usrid = ?
185
        while(my @rowuser = $sthloaduser->fetchrow_array){
186
          my($pcname2, $pcstatus2, $pcip2)=@rowuser;
187
          if($pcip2 ne $IPmachine){
188
            # utente probabilmente gia allocato su altro PC
189
            # verifico se la connessione è ancora attiva
190
            my $newstatus = &status_machine($pcip2);
191
            # aggiorno il record relativo
192
            my $newuser = $User;
193
            if($newstatus ne 'PCLOGON' && $newstatus ne 'ERROR'){
194
              $sthupdate->execute($pcname2, $newstatus, '', undef, $pcip2);
195
            }
196
            if($newstatus eq 'PCLOGON'){
197
              $DEBUG && print STDERR "preexec: utente studente $User già connesso in $rowuser[0] ip:$pcip2\n";
198
              $sthupdate->execute($Machine, 'PCON', $User, $undef, $IPmachine);
199
              my $action='logoff';
200
              if($osversion =~ m/ 95| 98| Millennium/i){
201
                $action=undef;
202
              }
203
              &message_machine($IPmachine, $action, "utente studente $User già connesso su PC $pcname2");
204
              exit 1;
205
            }
206
          }
207
        }
208
      }  
209
      # aggiorno il record
210
      $sthupdate->execute($Machine, 'PCLOGIN', $User, $date.' '.$time, $IPmachine);
211
    }
212
  }else{
213
    # richiesta di connessione da host non riconosciuto
214
    if($Group ne 'admin'){
215
      # se la login è di un utente diverso da tecnico non accetto ...
216
      $DEBUG && print STDERR "preexec: richiesta connessione da host '$IPmachine' sconosciuto\n";
217
      $sthupdate->execute($Machine, 'PCON', $User, $undef, $IPmachine);
218
      exit 1;
219
    }
220
  }
221
  # verifico se l'utente studente connesso sta connettendosi nella stessa aula del docente oppure dall'aula permanente
222
  if(lc $UserProfile eq 'student'){
223
    # devo consultare le classi a cui appartiene l'utente e individuare la classe attiva di appartenenza
224
    # verifico che l'indirizzo IP sia nella stessa aula
225
    $sthuserroom->execute($User,$IPmachine);
226
    my @rowip = $sthuserroom->fetchrow_array;
227
    if(@rowip){
228
      my($class, $roomteacher, $room, $pcteacher, $ipteacher)=@rowip;
229
      $DEBUG && print STDERR "preexec: richiesta connessione utente $User da $IPmachine accettata ".
230
                             "(classe $class, aula $room; docente da pc $pcteacher:$ipteacher, aula $roomteacher)\n";
231
    }else{
232
      $DEBUG && print STDERR "preexec: richiesta connessione utente $User da $IPmachine rifiutata; nessuna classe attiva o persistente\n";
233
      exit 1;
234
    }
235
  }
16 gdo 236
  open LOG, ">$LOG" || die "Errore [$!] apertura file '$LOG'\n"; 
11 gdo 237
  close LOG;
238
  chmod 0660, $LOG;
239
  chown 0, $samba_group, $LOG;
240
 
241
  # creo file otu.exe per il controllo remoto e per avere un file aperto che occupi la share [netlogon]
242
  if( ! -f $OTU){
243
    # copio l'eseguibile otu.exe
244
    symlink "/opt/cms/lib/otu.exe", $OTU;
245
  }
246
  # creo/aggiorno il file di logon 
247
  # Windows XP non esegue lo startup indicato nelle policy; lo eseguo invece dallo script di logon
16 gdo 248
  open CMD, ">$LOGON" || die "Errore [$!] apertura file '$LOGON'\n";
11 gdo 249
#  print CMD "net use P: /HOME /YES\r\n";
250
  print CMD "net use H: \\\\$Server\\HOME /YES\r\n";
251
  print CMD "net use N: \\\\$Server\\NETLOGON /YES\r\n";
252
  if($Platform =~ m/Win2k/i ){
253
    print CMD "start N:\\.system\\.startup.bat\r\n";
254
    $startVnc=0; # disabilito il lancio di VNC dal Server
255
  }
256
  close CMD;
257
  # permessi file di logon
258
  chmod 0660, $LOGON;
259
  chown 0, $samba_group, $LOGON;
260
 
261
  # creo/aggiorno il file di startup che verrà eseguito dal PC client
16 gdo 262
  open CMD, ">$STARTUP" || die "Errore [$!] apertura file '$STARTUP'\n";;
11 gdo 263
  print CMD <<__CMD__;
264
\@ECHO OFF\r
265
REM net use N: \\\\$Server\\netlogon /YES\r
266
REM start N:\\.system\\.otu.exe -h 1 -p 50001 -a $IP_SERVER\r
267
REM net use P: /HOME /YES\r
268
REM net use S: \\\\$Server\\segreteria /YES\r
269
regedit /S N:\\.system\\.config.reg\r
270
ver >N:\\.system\\.logs\\.$IPmachine.log\r
271
__CMD__
272
  if($Platform !~ m/Win2k/i ){
273
    print CMD "net time \\\\$Server >>N:\\.system\\.logs\\.$IPmachine.log\r\n";
274
  }
275
  print CMD <<__CMD__;
276
if "\%OS\%" == "Windows_NT" goto NT\r
277
net config /Y >>N:\\.system\\.logs\\.$IPmachine.log\r
278
goto END\r
279
:NT\r
280
net config Workstation /Y >>N:\\.system\\.logs\\.$IPmachine.log\r
281
:END\r
282
REM echo logon $IPmachine $$ >>N:\\.system\\.logs\\.$IPmachine.log\r
283
__CMD__
284
  # riga che verrà intercettata nella fase finale del logon
285
  print CMD "echo logon $IPmachine $$ >>N:\\.system\\.logs\\.$IPmachine.log\r\n";
286
  if($inst_poweroff){
287
    # verifico se è attivo poweroff (utilizzato per controllare lo spegnimento o reboot del PC)
288
    # apertura connessione con il PC
289
    my $sock = IO::Socket::INET->new(PeerAddr => $IPmachine,
290
                                 PeerPort => 50000,   
291
                                 Proto    => 'tcp',  
292
                                 Timeout => 15 );
293
    if($sock){
294
      my $sel = new IO::Select($sock);
295
      # leggo il canale con un timeout di 5 secondi
296
      my @ready = $sel->can_read(5);
297
      if(@ready){
298
        my $sh = pop @ready;
299
        my $R = <$sh>;
300
        if($R =~ m/^201 Welcome to Poweroff 3\.0\.0\.12 created by Jorgen Bosman \(cms path\)$/i){
301
          print $sock "quit\n";
302
          my @ready = $sel->can_read(0.5);
303
        }
304
      }else{
305
        $DEBUG && print STDERR "Timeout error on poweroff port\n";
306
      }
307
      close($sock);
308
    }else{
309
      $DEBUG && print STDERR "no poweroff active\n";
310
      if( ! -f $POWEROFF){
311
        # copio l'eseguibile poweroff.exe
312
        symlink "/opt/cms/lib/poweroff.exe", $POWEROFF;
313
      }
314
      # provvedo all'installazione del servizio
315
      print CMD <<__CMD__;
316
echo install poweroff >>N:\\.system\\.logs\\.$IPmachine.log\r
317
REM start N:\\.system\\.poweroff.exe -allow_remote -notray -nocancel -force -remote_port 50000 -remote_pswd test -run -quiet -create_service >>N:\\.system\\.logs\\.$IPmachine.log\r
318
__CMD__
319
      if($reboot_poweroff){
320
        print CMD <<__CMD__;
321
start N:\\.system\\.poweroff.exe reboot -warn -msg "Reboot per installazione Controllo Classi" -force -warntime 10 -nocancel -scheduled -seconds 4 -quiet >>N:\\.system\\.logs\\.$IPmachine.log\r
322
__CMD__
323
      }
324
    }
325
  }
326
#
327
  $sthipteacher->execute($IPmachine);
328
  my @rowt = $sthipteacher->fetchrow_array;
329
  my($CLASSNAME, $SITE, $IP_TEACHER)=@rowt;
330
  $IP_TEACHER || ($IP_TEACHER='127.0.0.1');
331
  $listgroups = `/usr/bin/groups $User`;
332
  chomp $listgroups;
333
  $listgroups .= ' ';
334
  $listgroups =~ s/.*://;
335
  if(lc $UserProfile ne 'student'){
336
    # verifico che l'utente abbia il gruppo 'cupsadm'  
337
    if($listgroups !~ m/ cupsadm /){
338
      $listgroups =~ s/^\s+//;
339
      $listgroups=~s/ /,/g;
340
      $listgroups.='cupsadm';
341
      $DEBUG && warn "/usr/sbin/usermod -G '$listgroups' $User\n";
342
      `/usr/sbin/usermod -G '$listgroups' $User`;
343
    }
344
  }else{
345
    # verifico che lo studente non abbia il gruppo 'cupsadm'
346
    if($listgroups =~ m/ cupsadm /){
347
      $listgroups =~ s/ cupsadm //;
348
      $listgroups =~ s/^\s+//;
349
      $listgroups =~ s/\s+$//;
350
      $listgroups =~ s/ /,/g;
351
      $DEBUG && warn "/usr/sbin/usermod -G '$listgroups' $User\n";
352
      `/usr/sbin/usermod -G '$listgroups' $User`;
353
    }
354
  }
355
  # verifico se installare VNC e con quale autorizzazioni di accesso
356
  if($startVnc && ($startVncAll || lc $UserProfile eq 'student') ){
357
    $DEBUG && print STDERR "run VNC opened from $IP_TEACHER\n";
358
    # preparo la copia del file da lanciare
359
    my $VNC="/home/samba/machine/$IPmachine/.system/.vnc";
360
    if(! -d "$VNC"){
361
      symlink "/opt/cms/lib/vnc", "/home/samba/machine/$IPmachine/.system/.vnc";
362
    }
363
    # genero il file da caricare con regedit
16 gdo 364
    my $VNCFILE="/home/samba/machine/$IPmachine/.system/.vnc.reg";
365
    open VNC, ">$VNCFILE" || die "Errore [$!] apertura file '$VNCFILE'\n";;
11 gdo 366
    print VNC <<__VNC__;
367
REGEDIT4\r
368
\r
369
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ORL]\r
370
\r
371
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ORL\\VNC]\r
372
\r
373
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ORL\\VNC\\3.3.3]\r
374
\r
375
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ORL\\WinVNC3]\r
376
"AuthRequired"=dword:00000000\r
377
"AuthHosts"="-:+$IP_SERVER:+$IP_TEACHER"\r
378
\r
379
[HKEY_LOCAL_MACHINE\\SOFTWARE\\ORL\\WinVNC3\\Default]\r
380
"AllowProperties"=dword:00000001\r
381
"AllowShutdown"=dword:00000001\r
382
\r
383
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks]\r
384
\r
385
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs]\r
386
\r
387
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\CALC.EXE]\r
388
"use_GetUpdateRect"=dword:00000001\r
389
"use_Timer"=dword:00000000\r
390
"use_KeyPress"=dword:00000000\r
391
"use_LButtonUp"=dword:00000000\r
392
"use_Deferral"=dword:00000001\r
393
\r
394
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\CLOCK.EXE]\r
395
"use_GetUpdateRect"=dword:00000001\r
396
"use_Timer"=dword:00000001\r
397
"use_KeyPress"=dword:00000000\r
398
"use_Deferral"=dword:00000001\r
399
"use_LButtonUp"=dword:00000000\r
400
\r
401
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\explorer.exe]\r
402
"use_GetUpdateRect"=dword:00000001\r
403
"use_Timer"=dword:00000000\r
404
"use_KeyPress"=dword:00000001\r
405
"use_Deferral"=dword:00000001\r
406
"use_LButtonUp"=dword:00000000\r
407
\r
408
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\fpxpress.exe]\r
409
"use_GetUpdateRect"=dword:00000001\r
410
"use_Timer"=dword:00000000\r
411
"use_KeyPress"=dword:00000001\r
412
"use_Deferral"=dword:00000001\r
413
"use_LButtonUp"=dword:00000001\r
414
\r
415
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\Ide.exe]\r
416
"use_GetUpdateRect"=dword:00000001\r
417
"use_Timer"=dword:00000000\r
418
"use_KeyPress"=dword:00000001\r
419
"use_Deferral"=dword:00000001\r
420
"use_LButtonUp"=dword:00000001\r
421
\r
422
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\iexplore.exe]\r
423
"use_GetUpdateRect"=dword:00000001\r
424
"use_Timer"=dword:00000000\r
425
"use_KeyPress"=dword:00000001\r
426
"use_Deferral"=dword:00000001\r
427
"use_LButtonUp"=dword:00000001\r
428
\r
429
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\MSDEV.EXE]\r
430
"use_GetUpdateRect"=dword:00000001\r
431
"use_Timer"=dword:00000000\r
432
"use_KeyPress"=dword:00000000\r
433
"use_Deferral"=dword:00000001\r
434
"use_LButtonUp"=dword:00000001\r
435
\r
436
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\mspaint.exe]\r
437
"use_GetUpdateRect"=dword:00000001\r
438
"use_Timer"=dword:00000000\r
439
"use_KeyPress"=dword:00000001\r
440
"use_LButtonUp"=dword:00000001\r
441
"use_Deferral"=dword:00000001\r
442
\r
443
[HKEY_CURRENT_USER\\Software\\ORL\\VNCHooks\\Application_Prefs\\NOTEPAD.EXE]\r
444
"use_GetUpdateRect"=dword:00000001\r
445
"use_Timer"=dword:00000000\r
446
"use_KeyPress"=dword:00000001\r
447
"use_Deferral"=dword:00000001\r
448
"use_LButtonUp"=dword:00000001\r
449
__VNC__
450
    close VNC;
451
    chmod 0640, "/home/samba/machine/$IPmachine/.system/.vnc.reg";
452
    chown 0, $samba_group, "/home/samba/machine/$IPmachine/.system/.vnc.reg";
453
    print CMD "regedit /S N:\\.system\\.vnc.reg\r\n";
454
    if(!$startVncDelay){
455
      print CMD "start N:\\.system\\.vnc\\winvnc.exe -run\r\n";
456
    }
457
  }
458
  # se l'utente è un docente apro il browser sulla pagina di login dell'applicazione
459
  # non apro la pagina se il PC è Win2k (problemi rilevati su WinXP)
460
  if(!$startBrowseDelay && lc $UserProfile eq 'teacher' && $Platform !~ m/Win2k/i){
461
    print CMD "start http://$Server/cms/\r\n";
462
  }
463
  print CMD <<__CMD__;
464
echo . >>N:\\.system\\.logs\\.$IPmachine.log\r
465
start N:\\.system\\.otu.exe -h 1 -p 50001 -a $IP_SERVER\r
466
EXIT\r
467
__CMD__
468
  close CMD;
469
  chmod 0660, $STARTUP;
470
  chown 0, $samba_group, $STARTUP;
471
  # sgancio il processo padre e attendo il completamento del logon sul PC client
472
  open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
473
  open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
474
  defined(my $pid = fork) or die "Can't fork: $!";
475
  if($pid){
476
    # processo padre
477
    exit 0;
478
  }
479
  setsid or die "Can't start a new session: $!";
480
  $DEBUG && print STDERR "Fork\n";
481
  # mi preparo a monitorare il file di log
482
  open SYNC, "<$LOG";
483
  seek(SYNC, 0, 0);
484
  my $curpos;
485
  my $Count=$CheckTimeoutStart;
486
  my $os_ver;
487
  LOOP: while($Count--){
488
    for ($curpos = tell(SYNC); $_ = <SYNC>; $curpos = tell(SYNC)){
489
      chop;
490
      $Count=$CheckTimeoutContinue;
491
      $DEBUG && print STDERR "READ $_\n";
492
      # salto righe vuote
493
      next if(m/^\s*$/);
494
      if(!$os_ver){
495
        $os_ver=$_;
496
      }
497
      if(!$os_ver){
498
        $os_ver='';
499
      }
500
      if(m/^logon (.+) (\d+)/){
501
        my $IP=$1;
502
        my $PID=$2;
503
        $DEBUG && print STDERR "detect $IP $PID\n";
504
        # verifico che l'informazione registrata durante la fase 'reexec' corrisponda
505
        $sthloadip->execute($IPmachine);
506
        my @rowip = $sthloadip->fetchrow_array;
507
        if(@rowip && $rowip[1] eq 'PCLOGIN'){
508
          # il Client ha terminato l'esecuzione dello script di logon; posso aggiornare il database
509
          # cambiando lo stato  
510
          $sthstatus->execute('PCLOGON', $IPmachine);
511
          $sthosversion->execute($os_ver, $IPmachine);
512
        }else{
513
          # sequenza non corretta; non accetto la connessione
514
          $DEBUG && print STDERR "logon: sequenza non corretta, $rowip[1] != PCLOGIN\n";
515
          $sthstatus->execute('PCERR', $IPmachine);
516
        }
517
        # se l'utente è un docente apro il browser sulla pagina di login dell'applicazione
518
        if($startBrowseDelay && lc $UserProfile eq 'teacher'){
519
          select(undef, undef, undef, 4);
520
          $DEBUG && print STDERR "lancio http://$Server/cms/\n";
521
          my $err=&call_client($IPmachine, "start http://$Server/cms/");
522
          $DEBUG && print STDERR "start http://$Server/cms/ err=$err\n";
523
        }
524
        # lancio vnc in ritardo qualche secondo ...
525
        if($startVncDelay && $startVnc && ($startVncAll || lc $UserProfile eq 'student')){
526
          select(undef, undef, undef, 15);
527
          $DEBUG && print STDERR "lancio vnc\n";
528
          my $err=&call_client($IPmachine, "N:\\.system\\.vnc\\winvnc.exe -run"); 
529
          $DEBUG && print STDERR "winvnc.exe err=$err\n";
530
        }
531
#        unlink $STARTUP, $LOG, $OTU, $POWEROFF;
532
        exit;
533
      }
534
    }
535
    select(undef, undef, undef, 0.1);
536
    seek(SYNC, $curpos, 0);
537
  }
538
#  unlink $STARTUP, $LOG, $OTU, $POWEROFF; 
539
  $sthstatus->execute('PCTIMEOUT', $IPmachine);
540
  print STDERR "Timeout read logon for user=$User IP=$IPmachine\n";
541
  exit;
542
}elsif( $Mode eq '-postexec'){
543
  $DEBUG && print STDERR "postexec $IPmachine -1 $User $Machine $time $Platform\n";
544
  # il Client ha terminato l'uso della share [netlogon]; posso aggiornare il database
545
  $sthupdate->execute($Machine, 'PCON', $User, undef, $IPmachine);
546
}else{
547
 
548
  close LOG;
549
  exit 1; 
550
}
551
close LOG;
552
 
553
# esecuzione remota di comandi
554
sub call_client{
555
  my $host = shift;
556
  my $cmd = join(' ',@_);
557
  $cmd || ($cmd='-');
558
  $DEBUG && print STDERR  "call_client '$host' with [$cmd]\n";
559
  return 1 if(!$host);
560
  my $sock = IO::Socket::INET->new(PeerAddr => $host,
561
                                 PeerPort => 50001,   
562
                                 Proto    => 'tcp',  
563
                                 Timeout => 4 );     
564
 
565
  if(!$sock){
566
    $DEBUG && print STDERR "\topen sock ($!)";
567
    if($! eq 'Connection refused'){
568
      return 2;
569
    }elsif($! eq 'No route to host'){
570
      return 3;
571
    }elsif($! eq 'Operation now in progress'){
572
      return 4;
573
    }else{
574
      return 5;
575
    }
576
  }  
577
  my $sel = new IO::Select($sock);
578
  print $sock "$cmd\n";  
579
  # leggo il canale con un timeout di 2 secondi
580
  my @ready = $sel->can_read(4);
581
  if(!@ready){
582
    close($sock);
583
    return 6;    
584
  }
585
  my $sh = pop @ready;
586
  my $ret = <$sh>;
587
  chomp $ret;
588
  close($sock);
589
  return 7 if $ret !~ m/OK/;
590
  return 0;
591
}
592
 
593
# verifica lo stato della macchina
594
# PCOFF PCON PCLOGON
595
sub status_machine($){
596
  my $IP=shift;
597
  # per determinare lo stato della connessione mi affido alla risposta del programma otu.exe
598
  # installato sul PC client
599
  my $status = &call_client($IP);
600
  if($status == 4){
601
    # ritento una seconda volta
602
    $status = &call_client($IP);
603
  }
604
  if($status eq '0'){
605
    $status = 'PCLOGON';
606
  }elsif($status eq '2'){
607
    $status = 'PCON';
608
  }elsif($status eq '3'){
609
    $status = 'PCOFF';
610
  }elsif($status eq '4'){
611
    $status = 'PCOFF';
612
  }else{
613
    $status = 'ERROR';
614
  } 
615
  $DEBUG && print STDERR "status_machine($IP)=$status\n";
616
  return $status;
617
}   
618
 
619
# visualizza un messaggio sul PC remoto  
620
sub message_machine($$$){
621
  my($host, $action, $mess)=@_;
622
  my $simulate;
623
  if($action){
624
    $simulate='off';
625
  }else{
626
    $simulate='on';
627
    $action='logoff';
628
  }
629
  my $sock = IO::Socket::INET->new(PeerAddr => $host,
630
                                 PeerPort => 50000,   
631
                                 Proto    => 'tcp',
632
                                 Timeout => 10 );
633
  return if(!$sock);
634
  my @dialog = (
635
        '/^201 Welcome to Poweroff 3\.0\.0\.12 created by Jorgen Bosman \(cms path\)$/i',
636
        'password test',
637
        '/^250 OK$/i',
638
        "action $action",
639
        '/^250 OK$/i',
640
        "simulate $simulate",
641
        '/^250 OK$/i',
642
        'runprg off',
643
        '/^250 OK$/i',
644
        "message $mess",
645
        '/^250 OK$/i',
646
        'wait 0', 
647
        '/^250 OK$/i',
648
        'warning on',
649
        '/^250 OK$/i',
650
        'warntime 5',
651
        '/^250 OK$/i',
652
        'doit',
653
        '/^250 OK$/i',
654
        'quit','/.*/i',
655
  );
656
  my $sel = new IO::Select($sock);
657
  my $Count=0;
658
  for(;;){
659
    # leggo il canale con un timeout di 2 secondi
660
    my @ready = $sel->can_read(2);
661
    if(!@ready){
662
      die "Timeout read from host";
663
    }
664
 
665
    my $sh = pop @ready;
666
    my $ret = <$sh>;
667
    chomp $ret;
668
    $ret =~ s/\r$//;
669
    $DEBUG && print STDERR "GET[$ret]\n";
670
    my $test;
671
    eval '$test =( $ret =~ '.$dialog[$Count].')';
672
    if($@){
673
      die "Error eval[$Count]: $@";
674
    }
675
    if($test){
676
      $Count++;
677
      last if($Count >= @dialog);
678
      my $cmd;
679
      $cmd = $dialog[$Count];
680
      $DEBUG && print STDERR "PUT[".$cmd."]\n";
681
      print $sock $cmd."\n";
682
      $Count++;
683
    }else{
684
      die "\nError row $Count: '$ret' don't match '$dialog[$Count]'\n";
685
    }
686
    last if($Count >= @dialog);
687
  }
688
  close($sock); 
689
}