lilalo
changeset 62:c4bea959dbb1
Beautyfication of l3-agent code. Many lines were erased. Need to be tested
author | devi |
---|---|
date | Thu Jan 26 00:00:53 2006 +0200 (2006-01-26) |
parents | 440d12c122d5 |
children | 1864df6ccbfe |
files | README l3-agent l3-frontend |
line diff
1.1 --- a/README Sat Jan 21 19:09:34 2006 +0200 1.2 +++ b/README Thu Jan 26 00:00:53 2006 +0200 1.3 @@ -0,0 +1,154 @@ 1.4 +АТРИБУТЫ cline 1.5 +СПИСОК ПОЛЕЙ, ХАРАКТЕРИЗУЮЩИХ КОМАНДНУЮ СТРОКУ 1.6 + 1.7 + uid 1.8 + Идентификатор пользователя 1.9 + 1.10 + tty 1.11 + Идентификатор терминала, на котором была вызвана команда 1.12 + 1.13 + pid 1.14 + PID-процесса командного интерпретатора, 1.15 + в котором была вызвана команда 1.16 + 1.17 + lab 1.18 + лабораторная работа, к которой относится команда. 1.19 + Идентификатор текущей лабораторной работы 1.20 + хранится в файле ~/.labmaker/lab 1.21 + 1.22 + pwd (!) 1.23 + текущий каталог, из которого была вызвана команда 1.24 + 1.25 + day 1.26 + время вызова, день 1.27 + В действительности здесь хранится не время вызова команды, 1.28 + а с момента появления приглашения командного интерпретатора 1.29 + для ввода команды 1.30 + 1.31 + 1.32 + hour 1.33 + время вызова, час 1.34 + 1.35 + min 1.36 + время вызова, минута 1.37 + 1.38 + sec 1.39 + время вызова, секунда 1.40 + 1.41 + time (!) 1.42 + время вызова команды в Unix-формате. 1.43 + Предпочтительнее использовать этот формат чем hour:min:sec, 1.44 + использовавшийся в Labmaker 1.45 + 1.46 + fullprompt 1.47 + Приглашение командной строки 1.48 + 1.49 + prompt 1.50 + Сокращённое приглашение командной строки 1.51 + 1.52 + cline 1.53 + Командная строка 1.54 + 1.55 + output 1.56 + Результат выполнения команды 1.57 + 1.58 + diff 1.59 + Указатель на ассоциированный с командой diff 1.60 + 1.61 + note (!) 1.62 + Текстовый комментарий к команде. 1.63 + Может генерироваться из самого лога с помощью команд 1.64 + #^ Комментарий 1.65 + #= Комментарий 1.66 + #v Комментарий 1.67 + в том случае, если для комментирования достаточно одной строки, 1.68 + или с помощью команд 1.69 + cat > /dev/null #^ Заголовок 1.70 + Текст 1.71 + ^D 1.72 + в том случае, если комментарий развёрнутый. 1.73 + В последнем случае комментарий может содержать 1.74 + заголовок, абзацы и несложное форматирование. 1.75 + 1.76 + Символы ^, v или = после знака комментария # обозначает, 1.77 + к какой команде относится комментарий: 1.78 + к предыдущей (^), последующей (v) 1.79 + или это общий комментарий по тексту, не относящийся непосредственно 1.80 + ни к одной из них (=) 1.81 + 1.82 + err 1.83 + Код завершения командной строки 1.84 + 1.85 + histnum (!) 1.86 + Номер команды в истории командного интерпретатора 1.87 + 1.88 + status (!) 1.89 + Является ли данная команда вызванной (r), запомненной (s) 1.90 + или это подсказка completion (c). 1.91 + 1.92 + Команды, которые были вызваны и обработаны интерпретатором 1.93 + имеют состояние "r". К таким командам относится большинство 1.94 + команд вводимых в интерпретатор. 1.95 + 1.96 + Если команда набрана, но вызывать её по какой-либо причине 1.97 + не хочется (например, команда может быть не полной, вредоносной 1.98 + или просто бессмысленной в текущих условиях), 1.99 + её можно сбросить с помощью комбинации клавиш Ctrl-C 1.100 + (не путайте с прерыванием работающей команды! здесь она даже 1.101 + не запускается!). 1.102 + В таком случае она не выполняется, но попадает в журнал 1.103 + со статусом "s". 1.104 + 1.105 + Если команда появилась в журнале благодаря автопроолжению 1.106 + -- когда было показано несколько вариантов -- 1.107 + она имеет статус "c". 1.108 + 1.109 + euid 1.110 + Идентификатор пользователя от имени которого будет 1.111 + выполняться команда. 1.112 + Может отличаться от реального uid в том случае, 1.113 + если вызывается с помощью sudo 1.114 + 1.115 + 1.116 + version (!) 1.117 + Версия lilalo-prompt использовавшаяся при записи 1.118 + команды. 1.119 + 1.120 + 0 - версия использовавшая в labmaker. 1.121 + Отсутствует информация о текущем каталоге и номере в истории. 1.122 + Информация о версии также не указана в приглашении. 1.123 + 1.124 + 1.125 + 1 - версия использующаяся в lilalo 1.126 + 1.127 + raw_file 1.128 + Имя файла, в котором находится бинарное представление журнала. 1.129 + Может содержать ключевое слово HERE, 1.130 + обозначающее что бинарное представление хранится 1.131 + непосредственно в базе данных в атрибуте raw_data 1.132 + 1.133 + raw_start 1.134 + Начало блока командной строки в файле бинарного представления 1.135 + 1.136 + raw_output_start 1.137 + Начало блока вывода 1.138 + 1.139 + raw_end 1.140 + Конец блока командной строки в файле бинарного представления 1.141 + 1.142 + raw_cline 1.143 + Необработанная командная строка (без приглашения) в бинарном виде 1.144 + 1.145 + raw_data (*) 1.146 + Бинарное представление команды и результатов её выполнения 1.147 + 1.148 + 1.149 + 1.150 + 1.151 +ТАБЛИЦА SESSION 1.152 + 1.153 + Информация о сеансах 1.154 + 1.155 + (см. lm-install) 1.156 + 1.157 +
2.1 --- a/l3-agent Sat Jan 21 19:09:34 2006 +0200 2.2 +++ b/l3-agent Thu Jan 26 00:00:53 2006 +0200 2.3 @@ -1,7 +1,7 @@ 2.4 #!/usr/bin/perl -w 2.5 2.6 # 2.7 -# (c) Igor Chubin, imchubin@mail.ru, 2004-2005 2.8 +# (c) Igor Chubin, igor@chub.in, 2004-2006 2.9 # 2.10 2.11 2.12 @@ -24,26 +24,22 @@ 2.13 our %Diffs; 2.14 our %Sessions; 2.15 2.16 -our %Commands_Stat; # Statistics about commands usage 2.17 -our %Files_Stat; # Statistics about commands usage 2.18 +our %Script_Files; # Информация о позициях в скрипт-файлах, 2.19 + # до которых уже выполнен разбор 2.20 + # и информация о времени модификации файла 2.21 + # $Script_Files{$file}->{size} 2.22 + # $Script_Files{$file}->{tell} 2.23 2.24 -our %Script_Files; # Информация о позициях в скрипт-файлах, 2.25 - # до которых уже выполнен разбор 2.26 - # и информация о времени модификации файла 2.27 - # $Script_Files{$file}->{size} 2.28 - # $Script_Files{$file}->{tell} 2.29 - 2.30 -our $Killed =0; # В режиме демона -- процесс получил сигнал о завершении 2.31 +our $Killed =0; # В режиме демона -- процесс получил сигнал о завершении 2.32 2.33 sub init_variables; 2.34 sub main; 2.35 2.36 sub load_diff_files; 2.37 sub bind_diff; 2.38 -sub extract_from_cline; 2.39 +sub extract_commands_from_cline; 2.40 sub load_command_lines; 2.41 sub sort_command_lines; 2.42 -sub process_command_lines; 2.43 sub print_command_lines; 2.44 sub printq; 2.45 2.46 @@ -53,20 +49,20 @@ 2.47 2.48 sub load_diff_files 2.49 { 2.50 - my @pathes = @_; 2.51 - 2.52 - for my $path (@pathes) { 2.53 - my $template = "*.diff"; 2.54 - my @files = <$path/$template>; 2.55 - my $i=0; 2.56 - for my $file (@files) { 2.57 + my @pathes = @_; 2.58 + 2.59 + for my $path (@pathes) { 2.60 + my $template = "*.diff"; 2.61 + my @files = <$path/$template>; 2.62 + my $i=0; 2.63 + for my $file (@files) { 2.64 2.65 - next if defined($Diffs{$file}); 2.66 - 2.67 - my %diff; 2.68 - 2.69 - $diff{"path"}=$path; 2.70 - $diff{"uid"}="SET THIS"; 2.71 + next if defined($Diffs{$file}); 2.72 + 2.73 + my %diff; 2.74 + 2.75 + $diff{"path"}=$path; 2.76 + $diff{"uid"}="SET THIS"; 2.77 2.78 # Сейчас UID определяется из названия каталога 2.79 # откуда берутся diff-файлы 2.80 @@ -77,634 +73,381 @@ 2.81 # мз которых и будет определяться соответствие 2.82 # имён пользователей их uid'ам 2.83 # 2.84 - $diff{"uid"} = 0 if $path =~ m@/root/@; 2.85 - 2.86 - $diff{"bind_to"}=""; 2.87 - $diff{"time_range"}=-1; 2.88 - 2.89 - next if not $file=~m@/(D?[0-9][0-9]?[0-9]?)[^/]*?([0-9]*):([0-9]*):?([0-9]*)@; 2.90 - $diff{"day"}=$1 || ""; 2.91 - $diff{"hour"}=$2; 2.92 - $diff{"min"}=$3; 2.93 - $diff{"sec"}=$4 || 0; 2.94 - 2.95 - $diff{"index"}=$i; 2.96 + $diff{"uid"} = 0 if $path =~ m@/root/@; 2.97 + 2.98 + $diff{"bind_to"}=""; 2.99 + $diff{"time_range"}=-1; 2.100 + 2.101 + next if not $file=~m@/(D?[0-9][0-9]?[0-9]?)[^/]*?([0-9]*):([0-9]*):?([0-9]*)@; 2.102 + $diff{"day"}=$1 || ""; 2.103 + $diff{"hour"}=$2; 2.104 + $diff{"min"}=$3; 2.105 + $diff{"sec"}=$4 || 0; 2.106 + 2.107 + $diff{"index"}=$i; 2.108 2.109 - print "diff loaded: $diff{day} $diff{hour}:$diff{min}:$diff{sec}\n"; 2.110 - 2.111 - local $/; 2.112 - open (F, "$file") 2.113 - or return "Can't open file $file ($_[0]) for reading"; 2.114 - my $text = <F>; 2.115 - if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i) { 2.116 - my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8"); 2.117 - $text = $converter->convert($text); 2.118 - } 2.119 - close(F); 2.120 - $diff{"text"}=$text; 2.121 - #print "$file loaded ($diff{day})\n"; 2.122 + print "diff loaded: $diff{day} $diff{hour}:$diff{min}:$diff{sec}\n"; 2.123 + 2.124 + local $/; 2.125 + open (F, "$file") 2.126 + or return "Can't open file $file ($_[0]) for reading"; 2.127 + my $text = <F>; 2.128 + if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i) { 2.129 + my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8"); 2.130 + $text = $converter->convert($text); 2.131 + } 2.132 + close(F); 2.133 + $diff{"text"}=$text; 2.134 + #print "$file loaded ($diff{day})\n"; 2.135 2.136 - #push @Diffs, \%diff; 2.137 - $Diffs{$file} = \%diff; 2.138 - $i++; 2.139 - } 2.140 - } 2.141 + #push @Diffs, \%diff; 2.142 + $Diffs{$file} = \%diff; 2.143 + $i++; 2.144 + } 2.145 + } 2.146 } 2.147 2.148 2.149 sub bind_diff 2.150 { 2.151 -# my $path = shift; 2.152 -# my $pid = shift; 2.153 -# my $day = shift; 2.154 -# my $lab = shift; 2.155 +# my $path = shift; 2.156 +# my $pid = shift; 2.157 +# my $day = shift; 2.158 +# my $lab = shift; 2.159 2.160 - print "Trying to bind diff...\n"; 2.161 + print "Trying to bind diff...\n"; 2.162 2.163 - my $cl = shift; 2.164 - my $hour = $cl->{"hour"}; 2.165 - my $min = $cl->{"min"}; 2.166 - my $sec = $cl->{"sec"}; 2.167 + my $cl = shift; 2.168 + my $hour = $cl->{"hour"}; 2.169 + my $min = $cl->{"min"}; 2.170 + my $sec = $cl->{"sec"}; 2.171 2.172 - my $min_dt = 10000; 2.173 + my $min_dt = 10000; 2.174 2.175 - for my $diff_key (keys %Diffs) { 2.176 - my $diff = $Diffs{$diff_key}; 2.177 - # Check here date, time and user 2.178 - next if ($diff->{"day"} && $cl->{"day"} && ($cl->{"day"} ne $diff->{"day"})); 2.179 - #next if (!$diff->{"uid"} && $cl->{"euid"} != $diff->{"uid"}); 2.180 - 2.181 - my $dt=($diff->{"hour"}-$hour)*3600 +($diff->{"min"}-$min)*60 + ($diff->{"sec"}-$sec); 2.182 - if ($dt >0 && $dt < $min_dt && ($diff->{"time_range"} <0 || $dt < $diff->{"time_range"})) { 2.183 - print "Approppriate diff found: dt=$dt\n"; 2.184 - if ($diff->{"bind_to"}) { 2.185 - undef $diff->{"bind_to"}->{"diff"}; 2.186 - }; 2.187 - $diff->{"time_range"}=$dt; 2.188 - $diff->{"bind_to"}=$cl; 2.189 + for my $diff_key (keys %Diffs) { 2.190 + my $diff = $Diffs{$diff_key}; 2.191 + # Check here date, time and user 2.192 + next if ($diff->{"day"} && $cl->{"day"} && ($cl->{"day"} ne $diff->{"day"})); 2.193 + #next if (!$diff->{"uid"} && $cl->{"euid"} != $diff->{"uid"}); 2.194 + 2.195 + my $dt=($diff->{"hour"}-$hour)*3600 +($diff->{"min"}-$min)*60 + ($diff->{"sec"}-$sec); 2.196 + if ($dt >0 && $dt < $min_dt && ($diff->{"time_range"} <0 || $dt < $diff->{"time_range"})) { 2.197 + print "Approppriate diff found: dt=$dt\n"; 2.198 + if ($diff->{"bind_to"}) { 2.199 + undef $diff->{"bind_to"}->{"diff"}; 2.200 + }; 2.201 + $diff->{"time_range"}=$dt; 2.202 + $diff->{"bind_to"}=$cl; 2.203 2.204 - #$cl->{"diff"} = $diff->{"index"}; 2.205 - $cl->{"diff"} = $diff_key; 2.206 - $min_dt = $dt; 2.207 - } 2.208 - 2.209 - } 2.210 + $cl->{"diff"} = $diff_key; 2.211 + $min_dt = $dt; 2.212 + } 2.213 + } 2.214 } 2.215 2.216 2.217 -sub extract_from_cline 2.218 +sub extract_commands_from_cline 2.219 # Разобрать командную строку $_[1] и возвратить хэш, содержащий 2.220 # номер первого появление команды в строке: 2.221 -# команда => первая позиция 2.222 +# команда => первая позиция 2.223 { 2.224 - my $what = $_[0]; 2.225 - my $cline = $_[1]; 2.226 - my @lists = split /\;/, $cline; 2.227 - 2.228 - 2.229 - my @commands = (); 2.230 - for my $list (@lists) { 2.231 - push @commands, split /\|/, $list; 2.232 - } 2.233 + my $cline = $_[0]; 2.234 + my @lists = split /\;/, $cline; 2.235 + 2.236 + 2.237 + my @commands = (); 2.238 + for my $list (@lists) { 2.239 + push @commands, split /\|/, $list; 2.240 + } 2.241 2.242 - my %commands; 2.243 - my %files; 2.244 - my $i=0; 2.245 - for my $command (@commands) { 2.246 - $command =~ /\s*(\S+)\s*(.*)/; 2.247 - if ($1 && $1 eq "sudo" ) { 2.248 - $commands{"$1"}=$i++; 2.249 - $command =~ s/\s*sudo\s+//; 2.250 - } 2.251 - $command =~ /\s*(\S+)\s*(.*)/; 2.252 - if ($1 && !defined $commands{"$1"}) { 2.253 - $commands{"$1"}=$i++; 2.254 - }; 2.255 - if ($2) { 2.256 - my $args = $2; 2.257 - my @args = split (/\s+/, $args); 2.258 - for my $a (@args) { 2.259 - $files{"$a"}=$i++ 2.260 - if !defined $files{"$a"}; 2.261 - }; 2.262 - 2.263 - 2.264 - } 2.265 - } 2.266 - 2.267 - if ($what eq "commands") { 2.268 - return %commands; 2.269 - } else { 2.270 - return %files; 2.271 - } 2.272 - 2.273 + my %commands; 2.274 + my %files; 2.275 + my $i=0; 2.276 + for my $command (@commands) { 2.277 + $command =~ /\s*(\S+)\s*(.*)/; 2.278 + if ($1 && $1 eq "sudo" ) { 2.279 + $commands{"$1"}=$i++; 2.280 + $command =~ s/\s*sudo\s+//; 2.281 + } 2.282 + $command =~ /\s*(\S+)\s*(.*)/; 2.283 + if ($1 && !defined $commands{"$1"}) { 2.284 + $commands{"$1"}=$i++; 2.285 + }; 2.286 + } 2.287 + return %commands; 2.288 } 2.289 2.290 sub load_command_lines 2.291 { 2.292 - my $lab_scripts_path = $_[0]; 2.293 - my $lab_scripts_mask = $_[1]; 2.294 + my $lab_scripts_path = $_[0]; 2.295 + my $lab_scripts_mask = $_[1]; 2.296 2.297 - my $cline_re_base = qq' 2.298 - ( 2.299 - (?:\\^?([0-9]*C?)) # exitcode 2.300 - (?:_([0-9]+)_)? # uid 2.301 - (?:_([0-9]+)_) # pid 2.302 - (...?) # day 2.303 - (.?.?) # lab 2.304 - \\s # space separator 2.305 - ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) # time 2.306 - .\\[50D.\\[K # killing symbols 2.307 - (.*?([\$\#]\\s?)) # prompt 2.308 - (.*) # command line 2.309 - ) 2.310 - '; 2.311 - #my $cline_re = qr/$cline_re_base(?:$cline_re_base|$)/x; 2.312 - #my $cline_re = qr/(?:$cline_re_base)*$cline_re_base$/x; 2.313 - my $cline_re = qr/$cline_re_base/sx; 2.314 - my $cline_re1 = qr/$cline_re_base\x0D/sx; 2.315 - my $cline_re2 = qr/$cline_re_base$/sx; 2.316 + my $cline_re_base = qq' 2.317 + ( 2.318 + (?:\\^?([0-9]*C?)) # exitcode 2.319 + (?:_([0-9]+)_)? # uid 2.320 + (?:_([0-9]+)_) # pid 2.321 + (...?) # day 2.322 + (.?.?) # lab 2.323 + \\s # space separator 2.324 + ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) # time 2.325 + .\\[50D.\\[K # killing symbols 2.326 + (.*?([\$\#]\\s?)) # prompt 2.327 + (.*) # command line 2.328 + ) 2.329 + '; 2.330 + #my $cline_re = qr/$cline_re_base(?:$cline_re_base|$)/x; 2.331 + #my $cline_re = qr/(?:$cline_re_base)*$cline_re_base$/x; 2.332 + my $cline_re = qr/$cline_re_base/sx; 2.333 + my $cline_re1 = qr/$cline_re_base\x0D/sx; 2.334 + my $cline_re2 = qr/$cline_re_base$/sx; 2.335 2.336 - my $vt = Term::VT102->new ( 'cols' => $Config{"terminal_width"}, 2.337 - 'rows' => $Config{"terminal_height"}); 2.338 - my $cline_vt = Term::VT102->new ('cols' => $Config{"terminal_width"}, 2.339 - 'rows' => $Config{"terminal_height"}); 2.340 + my $vt = Term::VT102->new ( 'cols' => $Config{"terminal_width"}, 2.341 + 'rows' => $Config{"terminal_height"}); 2.342 + my $cline_vt = Term::VT102->new ('cols' => $Config{"terminal_width"}, 2.343 + 'rows' => $Config{"terminal_height"}); 2.344 2.345 - my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8") 2.346 - if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i); 2.347 - 2.348 - print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/; 2.349 + my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8") 2.350 + if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i); 2.351 + 2.352 + print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/; 2.353 2.354 - my $file; 2.355 - my $skip_info; 2.356 + my $file; 2.357 + my $skip_info; 2.358 2.359 - my $commandlines_loaded =0; 2.360 - my $commandlines_processed =0; 2.361 + my $commandlines_loaded =0; 2.362 + my $commandlines_processed =0; 2.363 2.364 - my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>; 2.365 - for $file (@lab_scripts){ 2.366 - 2.367 - # Пропускаем файл, если он не изменялся со времени нашего предудущего прохода 2.368 - my $size = (stat($file))[7]; 2.369 - next if ($Script_Files{$file} && $Script_Files{$file}->{size} && $Script_Files{$file}->{size} >= $size); 2.370 + my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>; 2.371 + for $file (@lab_scripts){ 2.372 2.373 + # Пропускаем файл, если он не изменялся со времени нашего предудущего прохода 2.374 + my $size = (stat($file))[7]; 2.375 + next if ($Script_Files{$file} && $Script_Files{$file}->{size} && $Script_Files{$file}->{size} >= $size); 2.376 2.377 - my $local_session_id; 2.378 - # Начальное значение идентификатора текущего сеанса определяем из имени скрипта 2.379 - # Впоследствии оно может быть уточнено 2.380 - $file =~ m@.*/([^/]*)\.script$@; 2.381 - $local_session_id = $1; 2.382 2.383 - #Если файл только что появился, 2.384 - #пытаемся найти и загрузить информацию о соответствующей ему сессии 2.385 - if (!$Script_Files{$file}) { 2.386 - my $session_file = $file; 2.387 - $session_file =~ s/\.script/.info/; 2.388 - if (open(SESSION, $session_file)) { 2.389 - local $/; 2.390 - my $data = <SESSION>; 2.391 - close(SESSION); 2.392 + my $local_session_id; 2.393 + # Начальное значение идентификатора текущего сеанса определяем из имени скрипта 2.394 + # Впоследствии оно может быть уточнено 2.395 + $file =~ m@.*/([^/]*)\.script$@; 2.396 + $local_session_id = $1; 2.397 2.398 - for my $session_data ($data =~ m@<session>(.*?)</session>@sg) { 2.399 - my %session; 2.400 - while ($session_data =~ m@<([^>]*?)>(.*?)</\1>@sg) { 2.401 - $session{$1} = $2; 2.402 - } 2.403 - $local_session_id = $session{"local_session_id"} if $session{"local_session_id"}; 2.404 - $Sessions{$local_session_id}=\%session; 2.405 - } 2.406 + #Если файл только что появился, 2.407 + #пытаемся найти и загрузить информацию о соответствующей ему сессии 2.408 + if (!$Script_Files{$file}) { 2.409 + my $session_file = $file; 2.410 + $session_file =~ s/\.script/.info/; 2.411 + if (open(SESSION, $session_file)) { 2.412 + local $/; 2.413 + my $data = <SESSION>; 2.414 + close(SESSION); 2.415 2.416 - #Загруженную информацию сразу же отправляем в поток 2.417 - print_session($Config{cache}, $local_session_id); 2.418 - } 2.419 - } 2.420 - 2.421 - open (FILE, "$file"); 2.422 - binmode FILE; 2.423 - 2.424 - # Переходим к тому месту, где мы окончили разбор 2.425 - seek (FILE, $Script_Files{$file}->{tell}, 0) if $Script_Files{$file}->{tell}; 2.426 - $Script_Files{$file}->{size} = $size; 2.427 - $Script_Files{$file}->{tell} = 0 unless $Script_Files{$file}->{tell}; 2.428 + for my $session_data ($data =~ m@<session>(.*?)</session>@sg) { 2.429 + my %session; 2.430 + while ($session_data =~ m@<([^>]*?)>(.*?)</\1>@sg) { 2.431 + $session{$1} = $2; 2.432 + } 2.433 + $local_session_id = $session{"local_session_id"} if $session{"local_session_id"}; 2.434 + $Sessions{$local_session_id}=\%session; 2.435 + } 2.436 2.437 + #Загруженную информацию сразу же отправляем в поток 2.438 + print_session($Config{cache}, $local_session_id); 2.439 + } 2.440 + } 2.441 2.442 - $file =~ m@.*/(.*?)-.*@; 2.443 - 2.444 - my $tty = $1; 2.445 - my $first_pass = 1; 2.446 - my %cl; 2.447 - my $last_output_length=0; 2.448 - while (<FILE>) { 2.449 - 2.450 - $commandlines_processed++; 2.451 - # time 2.452 + open (FILE, "$file"); 2.453 + binmode FILE; 2.454 2.455 - next if s/^Script started on.*?\n//s; 2.456 + # Переходим к тому месту, где мы окончили разбор 2.457 + seek (FILE, $Script_Files{$file}->{tell}, 0) if $Script_Files{$file}->{tell}; 2.458 + $Script_Files{$file}->{size} = $size; 2.459 + $Script_Files{$file}->{tell} = 0 unless $Script_Files{$file}->{tell}; 2.460 2.461 - if (/[0-9][0-9]:[0-9][0-9]:[0-9][0-9].\[[0-9][0-9]D.\[K/ && m/$cline_re/) { 2.462 - s/.*\x0d(?!\x0a)//; 2.463 - # print "!!!",$_,"!!!\n"; 2.464 - # next; 2.465 - # while (m/$cline_re1/gs) { 2.466 - # } 2.467 - m/$cline_re2/gs; 2.468 + $file =~ m@.*/(.*?)-.*@; 2.469 2.470 - $commandlines_loaded++; 2.471 - $last_output_length=0; 2.472 + my $tty = $1; 2.473 + my $first_pass = 1; 2.474 + my %cl; 2.475 + my $last_output_length=0; 2.476 + while (<FILE>) { 2.477 + $commandlines_processed++; 2.478 2.479 - # Previous command 2.480 - my %last_cl = %cl; 2.481 - my $err = $2 || ""; 2.482 + next if s/^Script started on.*?\n//s; 2.483 2.484 + if (/[0-9][0-9]:[0-9][0-9]:[0-9][0-9].\[[0-9][0-9]D.\[K/ && m/$cline_re/) { 2.485 + s/.*\x0d(?!\x0a)//; 2.486 + m/$cline_re2/gs; 2.487 2.488 -=cut 2.489 + $commandlines_loaded++; 2.490 + $last_output_length=0; 2.491 2.492 -Атрибуты cline 2.493 -Список полей, характеризующих командную строку 2.494 + # Previous command 2.495 + my %last_cl = %cl; 2.496 + my $err = $2 || ""; 2.497 2.498 - uid 2.499 - Идентификатор пользователя 2.500 - 2.501 - tty 2.502 - Идентификатор терминала, на котором была вызвана команда 2.503 + $cl{"local_session_id"} = $local_session_id; 2.504 + # Parse new command 2.505 + $cl{"uid"} = $3; 2.506 + $cl{"euid"} = $cl{"uid"}; # Если в команде обнаружится sudo, euid поменяем на 0 2.507 + $cl{"pid"} = $4; 2.508 + $cl{"day"} = $5; 2.509 + $cl{"lab"} = $6; 2.510 + $cl{"hour"} = $7; 2.511 + $cl{"min"} = $8; 2.512 + $cl{"sec"} = $9; 2.513 + $cl{"fullprompt"} = $10; 2.514 + $cl{"prompt"} = $11; 2.515 + $cl{"raw_cline"} = $12; 2.516 2.517 - pid 2.518 - PID-процесса командного интерпретатора, 2.519 - в котором была вызвана команда 2.520 - 2.521 - lab 2.522 - лабораторная работа, к которой относится команда. 2.523 - Идентификатор текущей лабораторной работы 2.524 - хранится в файле ~/.labmaker/lab 2.525 + { 2.526 + use bytes; 2.527 + $cl{"raw_start"} = tell (FILE) - length($1); 2.528 + $cl{"raw_output_start"} = tell FILE; 2.529 + } 2.530 + $cl{"raw_file"} = $file; 2.531 2.532 - pwd (!) 2.533 - текущий каталог, из которого была вызвана команда 2.534 + $cl{"err"} = 0; 2.535 + $cl{"output"} = ""; 2.536 + $cl{"tty"} = $tty; 2.537 2.538 - day 2.539 - время вызова, день 2.540 - В действительности здесь хранится не время вызова команды, 2.541 - а с момента появления приглашения командного интерпретатора 2.542 - для ввода команды 2.543 - 2.544 - 2.545 - hour 2.546 - время вызова, час 2.547 - 2.548 - min 2.549 - время вызова, минута 2.550 - 2.551 - sec 2.552 - время вызова, секунда 2.553 - 2.554 - time (!) 2.555 - время вызова команды в Unix-формате. 2.556 - Предпочтительнее использовать этот формат чем hour:min:sec, 2.557 - использовавшийся в Labmaker 2.558 - 2.559 - fullprompt 2.560 - Приглашение командной строки 2.561 - 2.562 - prompt 2.563 - Сокращённое приглашение командной строки 2.564 + $cline_vt->process($cl{"raw_cline"}."\n"); 2.565 + $cl{"cline"} = $cline_vt->row_plaintext (1); 2.566 + $cl{"cline"} =~ s/\s*$//; 2.567 + $cline_vt->reset(); 2.568 2.569 - cline 2.570 - Командная строка 2.571 - 2.572 - output 2.573 - Результат выполнения команды 2.574 - 2.575 - diff 2.576 - Указатель на ассоциированный с командой diff 2.577 - 2.578 - note (!) 2.579 - Текстовый комментарий к команде. 2.580 - Может генерироваться из самого лога с помощью команд 2.581 - #^ Комментарий 2.582 - #= Комментарий 2.583 - #v Комментарий 2.584 - в том случае, если для комментирования достаточно одной строки, 2.585 - или с помощью команд 2.586 - cat > /dev/null #^ Заголовок 2.587 - Текст 2.588 - ^D 2.589 - в том случае, если комментарий развёрнутый. 2.590 - В последнем случае комментарий может содержать 2.591 - заголовок, абзацы и несложное форматирование. 2.592 + my %commands = extract_commands_from_cline($cl{"cline"}); 2.593 + $cl{"euid"}=0 if defined $commands{"sudo"}; 2.594 + my @comms = sort { $commands{$a} cmp $commands{$b} } keys %commands; 2.595 + $cl{"last_command"} = $comms[$#comms] || ""; 2.596 2.597 - Символы ^, v или = после знака комментария # обозначает, 2.598 - к какой команде относится комментарий: 2.599 - к предыдущей (^), последующей (v) 2.600 - или это общий комментарий по тексту, не относящийся непосредственно 2.601 - ни к одной из них (=) 2.602 + if ( 2.603 + $Config{"suppress_editors"} =~ /^y/i 2.604 + && grep ($_ eq $cl{"last_command"}, @{$Config{"editors"}}) 2.605 + || $Config{"suppress_pagers"} =~ /^y/i 2.606 + && grep ($_ eq $cl{"last_command"}, @{$Config{"pagers"}}) 2.607 + || $Config{"suppress_terminal"}=~ /^y/i 2.608 + && grep ($_ eq $cl{"last_command"}, @{$Config{"terminal"}}) 2.609 + ) { 2.610 + $cl{"suppress_output"} = "1"; 2.611 + } 2.612 + else { 2.613 + $cl{"suppress_output"} = "0"; 2.614 + } 2.615 + $skip_info = 0; 2.616 2.617 - err 2.618 - Код завершения командной строки 2.619 - 2.620 - histnum (!) 2.621 - Номер команды в истории командного интерпретатора 2.622 - 2.623 - status (!) 2.624 - Является ли данная команда вызванной (r), запомненной (s) 2.625 - или это подсказка completion (c). 2.626 - 2.627 - Команды, которые были вызваны и обработаны интерпретатором 2.628 - имеют состояние "r". К таким командам относится большинство 2.629 - команд вводимых в интерпретатор. 2.630 2.631 - Если команда набрана, но вызывать её по какой-либо причине 2.632 - не хочется (например, команда может быть не полной, вредоносной 2.633 - или просто бессмысленной в текущих условиях), 2.634 - её можно сбросить с помощью комбинации клавиш Ctrl-C 2.635 - (не путайте с прерыванием работающей команды! здесь она даже 2.636 - не запускается!). 2.637 - В таком случае она не выполняется, но попадает в журнал 2.638 - со статусом "s". 2.639 - 2.640 - Если команда появилась в журнале благодаря автопроолжению 2.641 - -- когда было показано несколько вариантов -- 2.642 - она имеет статус "c". 2.643 - 2.644 - euid 2.645 - Идентификатор пользователя от имени которого будет 2.646 - выполняться команда. 2.647 - Может отличаться от реального uid в том случае, 2.648 - если вызывается с помощью sudo 2.649 + print " ",$cl{"last_command"}; 2.650 2.651 - 2.652 - version (!) 2.653 - Версия lilalo-prompt использовавшаяся при записи 2.654 - команды. 2.655 + # Processing previous command line 2.656 + if ($first_pass) { 2.657 + $first_pass = 0; 2.658 + next; 2.659 + } 2.660 2.661 - 0 - версия использовавшая в labmaker. 2.662 - Отсутствует информация о текущем каталоге и номере в истории. 2.663 - Информация о версии также не указана в приглашении. 2.664 - 2.665 - 2.666 - 1 - версия использующаяся в lilalo 2.667 - 2.668 - raw_file 2.669 - Имя файла, в котором находится бинарное представление журнала. 2.670 - Может содержать ключевое слово HERE, 2.671 - обозначающее что бинарное представление хранится 2.672 - непосредственно в базе данных в атрибуте raw_data 2.673 + # Error code 2.674 + $last_cl{"raw_end"} = $cl{"raw_start"}; 2.675 + $last_cl{"err"}=$err; 2.676 + $last_cl{"err"}=130 if $err eq "^C"; 2.677 2.678 - raw_start 2.679 - Начало блока командной строки в файле бинарного представления 2.680 - 2.681 - raw_output_start 2.682 - Начало блока вывода 2.683 - 2.684 - raw_end 2.685 - Конец блока командной строки в файле бинарного представления 2.686 + if (grep ($_ eq $last_cl{"last_command"}, @{$Config{"editors"}})) { 2.687 + bind_diff(\%last_cl); 2.688 + } 2.689 2.690 - raw_cline 2.691 - Необработанная командная строка (без приглашения) в бинарном виде 2.692 - 2.693 - raw_data (*) 2.694 - Бинарное представление команды и результатов её выполнения 2.695 + # Output 2.696 + if (!$last_cl{"suppress_output"} || $last_cl{"err"}) { 2.697 + for (my $i=0; $i<$Config{"terminal_height"}; $i++) { 2.698 + my $line= $vt->row_plaintext($i); 2.699 + next if !defined ($line) ; #|| $line =~ /^\s*$/; 2.700 + $line =~ s/\s*$//; 2.701 + $line .= "\n" unless $line =~ /^\s*$/; 2.702 + $last_cl{"output"} .= $line; 2.703 + } 2.704 + } 2.705 + else { 2.706 + $last_cl{"output"}= ""; 2.707 + } 2.708 2.709 + $vt->reset(); 2.710 2.711 2.712 - 2.713 -ТАБЛИЦА SESSION 2.714 - 2.715 - Информация о сеансах 2.716 + # Classifying the command line 2.717 2.718 - (см. lm-install) 2.719 2.720 + # Save 2.721 + if (!$Config{"lab"} || $cl{"lab"} eq $Config{"lab"}) { 2.722 + # Changing encoding 2.723 + for (keys %last_cl) { 2.724 + next if /raw/; 2.725 + $last_cl{$_} = $converter->convert($last_cl{$_}) 2.726 + if ($Config{"encoding"} && 2.727 + $Config{"encoding"} !~ /^utf-8$/i); 2.728 + } 2.729 + push @Command_Lines, \%last_cl; 2.730 2.731 -=cut 2.732 + # Сохранение позиции в файле, до которой выполнен 2.733 + # успешный разбор 2.734 + $Script_Files{$file}->{tell} = $last_cl{raw_end}; 2.735 + } 2.736 + next; 2.737 + } 2.738 + $last_output_length+=length($_); 2.739 + #if (!$cl{"suppress_output"} || $last_output_length < 5000) { 2.740 + if ($last_output_length < 50000) { 2.741 + $vt->process("$_"."\n") 2.742 + } 2.743 + else 2.744 + { 2.745 + if (!$skip_info) { 2.746 + print "($cl{last_command})"; 2.747 + $skip_info = 1; 2.748 + } 2.749 + } 2.750 + } 2.751 + close(FILE); 2.752 2.753 - $cl{"local_session_id"} = $local_session_id; 2.754 - # Parse new command 2.755 - $cl{"uid"} = $3; 2.756 - $cl{"euid"} = $cl{"uid"}; # Если в команде обнаружится sudo, euid поменяем на 0 2.757 - $cl{"pid"} = $4; 2.758 - $cl{"day"} = $5; 2.759 - $cl{"lab"} = $6; 2.760 - $cl{"hour"} = $7; 2.761 - $cl{"min"} = $8; 2.762 - $cl{"sec"} = $9; 2.763 - $cl{"fullprompt"} = $10; 2.764 - $cl{"prompt"} = $11; 2.765 - $cl{"raw_cline"} = $12; 2.766 - 2.767 - { 2.768 - use bytes; 2.769 - $cl{"raw_start"} = tell (FILE) - length($1); 2.770 - $cl{"raw_output_start"} = tell FILE; 2.771 - } 2.772 - $cl{"raw_file"} = $file; 2.773 - 2.774 - $cl{"err"} = 0; 2.775 - $cl{"output"} = ""; 2.776 - $cl{"tty"} = $tty; 2.777 - 2.778 - $cline_vt->process($cl{"raw_cline"}."\n"); 2.779 - $cl{"cline"} = $cline_vt->row_plaintext (1); 2.780 - $cl{"cline"} =~ s/\s*$//; 2.781 - $cline_vt->reset(); 2.782 - 2.783 - my %commands = extract_from_cline("commands", $cl{"cline"}); 2.784 - $cl{"euid"}=0 if defined $commands{"sudo"}; 2.785 - my @comms = sort { $commands{$a} cmp $commands{$b} } keys %commands; 2.786 - $cl{"last_command"} = $comms[$#comms] || ""; 2.787 - 2.788 - if ( 2.789 - $Config{"suppress_editors"} =~ /^y/i 2.790 - && grep ($_ eq $cl{"last_command"}, @{$Config{"editors"}}) || 2.791 - $Config{"suppress_pagers"} =~ /^y/i 2.792 - && grep ($_ eq $cl{"last_command"}, @{$Config{"pagers"}}) || 2.793 - $Config{"suppress_terminal"}=~ /^y/i 2.794 - && grep ($_ eq $cl{"last_command"}, @{$Config{"terminal"}}) 2.795 - ) { 2.796 - $cl{"suppress_output"} = "1"; 2.797 - } 2.798 - else { 2.799 - $cl{"suppress_output"} = "0"; 2.800 - 2.801 - } 2.802 - $skip_info = 0; 2.803 - 2.804 - 2.805 - print " ",$cl{"last_command"}; 2.806 - 2.807 - # Processing previous command line 2.808 - if ($first_pass) { 2.809 - $first_pass = 0; 2.810 - next; 2.811 - } 2.812 - 2.813 - # Error code 2.814 - $last_cl{"raw_end"} = $cl{"raw_start"}; 2.815 - $last_cl{"err"}=$err; 2.816 - $last_cl{"err"}=130 if $err eq "^C"; 2.817 - 2.818 - if (grep ($_ eq $last_cl{"last_command"}, @{$Config{"editors"}})) { 2.819 - bind_diff(\%last_cl); 2.820 - } 2.821 - 2.822 - # Output 2.823 - if (!$last_cl{"suppress_output"} || $last_cl{"err"}) { 2.824 - for (my $i=0; $i<$Config{"terminal_height"}; $i++) { 2.825 - my $line= $vt->row_plaintext($i); 2.826 - next if !defined ($line) ; #|| $line =~ /^\s*$/; 2.827 - $line =~ s/\s*$//; 2.828 - $line .= "\n" unless $line =~ /^\s*$/; 2.829 - $last_cl{"output"} .= $line; 2.830 - } 2.831 - } 2.832 - else { 2.833 - $last_cl{"output"}= ""; 2.834 - } 2.835 - 2.836 - $vt->reset(); 2.837 - 2.838 - 2.839 - # Classifying the command line 2.840 - 2.841 - 2.842 - # Save 2.843 - if (!$Config{"lab"} || $cl{"lab"} eq $Config{"lab"}) { 2.844 - # Changing encoding 2.845 - for (keys %last_cl) { 2.846 - next if /raw/; 2.847 - $last_cl{$_} = $converter->convert($last_cl{$_}) 2.848 - if ($Config{"encoding"} && 2.849 - $Config{"encoding"} !~ /^utf-8$/i); 2.850 - } 2.851 - push @Command_Lines, \%last_cl; 2.852 - 2.853 - # Сохранение позиции в файле, до которой выполнен 2.854 - # успешный разбор 2.855 - $Script_Files{$file}->{tell} = $last_cl{raw_end}; 2.856 - } 2.857 - next; 2.858 - } 2.859 - $last_output_length+=length($_); 2.860 - #if (!$cl{"suppress_output"} || $last_output_length < 5000) { 2.861 - if ($last_output_length < 50000) { 2.862 - #print "(",length($_),")" if (length($_) > 2000) ; 2.863 - $vt->process("$_"."\n") 2.864 - } 2.865 - else 2.866 - { 2.867 - if (!$skip_info) { 2.868 - print "($cl{last_command})"; 2.869 - $skip_info = 1; 2.870 - } 2.871 - } 2.872 - } 2.873 - close(FILE); 2.874 - 2.875 - } 2.876 - if ($Config{"verbose"} =~ /y/) { 2.877 - print "...finished." ; 2.878 - print "Lines loaded: $commandlines_processed\n"; 2.879 - print "Command lines: $commandlines_loaded\n"; 2.880 - } 2.881 + } 2.882 + if ($Config{"verbose"} =~ /y/) { 2.883 + print "...finished." ; 2.884 + print "Lines loaded: $commandlines_processed\n"; 2.885 + print "Command lines: $commandlines_loaded\n"; 2.886 + } 2.887 } 2.888 2.889 2.890 2.891 + 2.892 +sub sort_command_lines 2.893 +{ 2.894 + print "Sorting command lines...\n" if $Config{"verbose"} =~ /y/; 2.895 + 2.896 + # Sort Command_Lines 2.897 + # Write Command_Lines to Command_Lines_Index 2.898 + 2.899 + my @index; 2.900 + for (my $i=0;$i<=$#Command_Lines;$i++) { 2.901 + $index[$i]=$i; 2.902 + } 2.903 + 2.904 + @Command_Lines_Index = sort { 2.905 + $Command_Lines[$index[$a]]->{"day"} cmp $Command_Lines[$index[$b]]->{"day"} || 2.906 + $Command_Lines[$index[$a]]->{"hour"} <=> $Command_Lines[$index[$b]]->{"hour"} || 2.907 + $Command_Lines[$index[$a]]->{"min"} <=> $Command_Lines[$index[$b]]->{"min"} || 2.908 + $Command_Lines[$index[$a]]->{"sec"} <=> $Command_Lines[$index[$b]]->{"sec"} 2.909 + } @index; 2.910 + 2.911 + print "...finished\n" if $Config{"verbose"} =~ /y/; 2.912 + 2.913 +} 2.914 + 2.915 sub printq 2.916 { 2.917 - my $TO = shift; 2.918 - my $text = join "", @_; 2.919 - $text =~ s/&/&/g; 2.920 - $text =~ s/</</g; 2.921 - $text =~ s/>/>/g; 2.922 - print $TO $text; 2.923 -} 2.924 - 2.925 - 2.926 -sub sort_command_lines 2.927 -{ 2.928 - print "Sorting command lines...\n" if $Config{"verbose"} =~ /y/; 2.929 - 2.930 - # Sort Command_Lines 2.931 - # Write Command_Lines to Command_Lines_Index 2.932 - 2.933 - my @index; 2.934 - for (my $i=0;$i<=$#Command_Lines;$i++) { 2.935 - $index[$i]=$i; 2.936 - } 2.937 - 2.938 - @Command_Lines_Index = sort { 2.939 - $Command_Lines[$index[$a]]->{"day"} cmp $Command_Lines[$index[$b]]->{"day"} || 2.940 - $Command_Lines[$index[$a]]->{"hour"} <=> $Command_Lines[$index[$b]]->{"hour"} || 2.941 - $Command_Lines[$index[$a]]->{"min"} <=> $Command_Lines[$index[$b]]->{"min"} || 2.942 - $Command_Lines[$index[$a]]->{"sec"} <=> $Command_Lines[$index[$b]]->{"sec"} 2.943 - } @index; 2.944 - 2.945 - print "...finished\n" if $Config{"verbose"} =~ /y/; 2.946 - 2.947 -} 2.948 - 2.949 -sub process_command_lines 2.950 -{ 2.951 - for my $i (@Command_Lines_Index) { 2.952 - 2.953 - my $cl = \$Command_Lines[$i]; 2.954 - @{${$cl}->{"new_commands"}} =(); 2.955 - @{${$cl}->{"new_files"}} =(); 2.956 - $$cl->{"class"} = ""; 2.957 - 2.958 - if ($$cl->{"err"}) { 2.959 - $$cl->{"class"}="wrong"; 2.960 - $$cl->{"class"}="interrupted" 2.961 - if ($$cl->{"err"} eq 130); 2.962 - } 2.963 - if (!$$cl->{"euid"}) { 2.964 - $$cl->{"class"}.="_root"; 2.965 - } 2.966 - 2.967 -#tab# my @tab_words=split /\s+/, $$cl->{"output"}; 2.968 -#tab# my $last_word= $$cl->{"cline"} =~ /(\S*)$/; 2.969 -#tab# $last_word =~ s@.*/@@; 2.970 -#tab# my $this_is_tab=1; 2.971 -#tab# 2.972 -#tab# if ($last_word && @tab_words >2) { 2.973 -#tab# for my $tab_words (@tab_words) { 2.974 -#tab# if ($tab_words !~ /^$last_word/) { 2.975 -#tab# $this_is_tab=0; 2.976 -#tab# last; 2.977 -#tab# } 2.978 -#tab# } 2.979 -#tab# } 2.980 -#tab# $$cl->{"class"}="tab" if $this_is_tab; 2.981 - 2.982 - 2.983 - if ( !$$cl->{"err"}) { 2.984 - # Command does not contain mistakes 2.985 - 2.986 - my %commands = extract_from_cline("commands", ${$cl}->{"cline"}); 2.987 - my %files = extract_from_cline("files", ${$cl}->{"cline"}); 2.988 - 2.989 - # Searching for new commands only 2.990 - for my $command (keys %commands) { 2.991 - if (!defined $Commands_Stat{$command}) { 2.992 - push @{$$cl->{new_commands}}, $command; 2.993 - } 2.994 - $Commands_Stat{$command}++; 2.995 - } 2.996 - 2.997 - for my $file (keys %files) { 2.998 - if (!defined $Files_Stat{$file}) { 2.999 - push @{$$cl->{new_files}}, $file; 2.1000 - } 2.1001 - $Files_Stat{$file}++; 2.1002 - } 2.1003 - } 2.1004 - 2.1005 - #if ($$cl->{cline}=~ /#\^(.*)/) { 2.1006 - # my $j=$i-1; 2.1007 - # $j-- while ($j >=0 && $Command_Lines[$j]->{tty} ne $$cl->{tty}); 2.1008 - # $Command_Lines[$j]->{note_title}="Замечание"; 2.1009 - # $Command_Lines[$j]->{note}="$1"; 2.1010 - #} 2.1011 - } 2.1012 - 2.1013 + my $TO = shift; 2.1014 + my $text = join "", @_; 2.1015 + $text =~ s/&/&/g; 2.1016 + $text =~ s/</</g; 2.1017 + $text =~ s/>/>/g; 2.1018 + print $TO $text; 2.1019 } 2.1020 2.1021 2.1022 @@ -712,218 +455,190 @@ 2.1023 Вывести результат обработки журнала. 2.1024 =cut 2.1025 2.1026 - 2.1027 sub print_command_lines 2.1028 { 2.1029 - my $output_filename=$_[0]; 2.1030 - my $mode = ">"; 2.1031 - $mode =">>" if $Config{mode} eq "daemon"; 2.1032 - open(OUT, $mode, $output_filename) 2.1033 - or die "Can't open $output_filename for writing\n"; 2.1034 + my $output_filename=$_[0]; 2.1035 + my $mode = ">"; 2.1036 + $mode =">>" if $Config{mode} eq "daemon"; 2.1037 + open(OUT, $mode, $output_filename) 2.1038 + or die "Can't open $output_filename for writing\n"; 2.1039 2.1040 2.1041 + my $cl; 2.1042 + my $in_range=0; 2.1043 + for my $i (@Command_Lines_Index) { 2.1044 + $cl = $Command_Lines[$i]; 2.1045 2.1046 - #print OUT "<livelablog>\n"; 2.1047 + if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) { 2.1048 + $in_range=1; 2.1049 + next; 2.1050 + } 2.1051 + if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) { 2.1052 + $in_range=0; 2.1053 + next; 2.1054 + } 2.1055 + next if ($Config{"from"} && $Config{"to"} && !$in_range) 2.1056 + || 2.1057 + ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) 2.1058 + || 2.1059 + ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) 2.1060 + || 2.1061 + ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); 2.1062 + 2.1063 + # Вырезаем из вывода только нужное количество строк 2.1064 2.1065 - my $cl; 2.1066 - my $in_range=0; 2.1067 - for my $i (@Command_Lines_Index) { 2.1068 - $cl = $Command_Lines[$i]; 2.1069 + my $output=""; 2.1070 + if ($Config{"head_lines"} || $Config{"tail_lines"}) { 2.1071 + # Partialy output 2.1072 + my @lines = split '\n', $cl->{"output"}; 2.1073 + # head 2.1074 + my $mark=1; 2.1075 + for (my $i=0; $i<= $#lines && $i < $Config{"cache_head_lines"}; $i++) { 2.1076 + $output .= $lines[$i]."\n"; 2.1077 + } 2.1078 + # tail 2.1079 + my $start=$#lines-$Config{"cache_tail_lines"}+1; 2.1080 + if ($start < 0) { 2.1081 + $start=0; 2.1082 + $mark=0; 2.1083 + } 2.1084 + if ($start < $Config{"cache_head_lines"}) { 2.1085 + $start=$Config{"cache_head_lines"}; 2.1086 + $mark=0; 2.1087 + } 2.1088 + $output .= $Config{"skip_text"}."\n" if $mark; 2.1089 + for (my $i=$start; $i<= $#lines; $i++) { 2.1090 + $output .= $lines[$i]."\n"; 2.1091 + } 2.1092 + } 2.1093 + else { 2.1094 + # Full output 2.1095 + $output .= $cl->{"output"}; 2.1096 + } 2.1097 2.1098 - if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) { 2.1099 - $in_range=1; 2.1100 - next; 2.1101 - } 2.1102 - if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) { 2.1103 - $in_range=0; 2.1104 - next; 2.1105 - } 2.1106 - next if ($Config{"from"} && $Config{"to"} && !$in_range) 2.1107 - || 2.1108 - ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) 2.1109 - || 2.1110 - ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) 2.1111 - || 2.1112 - ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); 2.1113 - 2.1114 - my @new_commands=@{$cl->{"new_commands"}}; 2.1115 - my @new_files=@{$cl->{"new_files"}}; 2.1116 + # Совместимость с labmaker 2.1117 2.1118 - my $cl_class="cline"; 2.1119 - my $out_class="output"; 2.1120 - if ($cl->{"class"}) { 2.1121 - $cl_class = $cl->{"class"}."_".$cl_class; 2.1122 - $out_class = $cl->{"class"}."_".$out_class; 2.1123 - } 2.1124 + # Переводим в секунды Эпохи 2.1125 + # В labmaker'е данные хранились в неудобной форме: hour, min, sec, day of year 2.1126 + # Информация о годе отсутствовала 2.1127 + # Её можно внести: 2.1128 + # Декабрь 2004 год; остальные -- 2005 год. 2.1129 2.1130 - # Вырезаем из вывода только нужное количество строк 2.1131 + my $year = 2005; 2.1132 + #$year = 2004 if ( $cl->{day} > 330 ); 2.1133 + $year = $Config{year} if $Config{year}; 2.1134 + # timelocal( $sec, $min, $hour, $mday,$mon,$year); 2.1135 + $cl->{time} = timelocal_nocheck($cl->{sec},$cl->{min},$cl->{hour},$cl->{day},0,$year); 2.1136 2.1137 - my $output=""; 2.1138 - if ($Config{"head_lines"} || $Config{"tail_lines"}) { 2.1139 - # Partialy output 2.1140 - my @lines = split '\n', $cl->{"output"}; 2.1141 - # head 2.1142 - my $mark=1; 2.1143 - for (my $i=0; $i<= $#lines && $i < $Config{"cache_head_lines"}; $i++) { 2.1144 - $output .= $lines[$i]."\n"; 2.1145 - } 2.1146 - # tail 2.1147 - my $start=$#lines-$Config{"cache_tail_lines"}+1; 2.1148 - if ($start < 0) { 2.1149 - $start=0; 2.1150 - $mark=0; 2.1151 - } 2.1152 - if ($start < $Config{"cache_head_lines"}) { 2.1153 - $start=$Config{"cache_head_lines"}; 2.1154 - $mark=0; 2.1155 - } 2.1156 - $output .= $Config{"skip_text"}."\n" if $mark; 2.1157 - for (my $i=$start; $i<= $#lines; $i++) { 2.1158 - $output .= $lines[$i]."\n"; 2.1159 - } 2.1160 - } 2.1161 - else { 2.1162 - # Full output 2.1163 - $output .= $cl->{"output"}; 2.1164 - } 2.1165 - #$output .= "^C\n" if ($cl->{"err"} eq "130"); 2.1166 2.1167 + # Начинаем вывод команды 2.1168 + print OUT "<command>\n"; 2.1169 + for my $element (qw( 2.1170 + local_session_id 2.1171 + time 2.1172 + raw_start 2.1173 + raw_output_start 2.1174 + raw_end 2.1175 + raw_file 2.1176 + tty 2.1177 + uid 2.1178 + err 2.1179 + last_command 2.1180 + )) { 2.1181 + next unless $cl->{"$element"}; 2.1182 + print OUT "<$element>".$cl->{$element}."</$element>\n"; 2.1183 + } 2.1184 + for my $element (qw( 2.1185 + prompt 2.1186 + cline 2.1187 + note 2.1188 + note_title 2.1189 + )) { 2.1190 + next unless $cl->{"$element"}; 2.1191 + print OUT "<$element>"; 2.1192 + printq(\*OUT,$cl->{"$element"}); 2.1193 + print OUT "</$element>\n"; 2.1194 + } 2.1195 + print OUT "<output>"; 2.1196 + printq(\*OUT,$output); 2.1197 + print OUT "</output>\n"; 2.1198 + if ($cl->{"diff"}) { 2.1199 + print OUT "<diff>"; 2.1200 + printq(\*OUT,${$Diffs{$cl->{"diff"}}}{"text"}); 2.1201 + print OUT "</diff>\n"; 2.1202 + } 2.1203 + print OUT "</command>\n"; 2.1204 2.1205 - # Совместимость с labmaker 2.1206 + } 2.1207 2.1208 - # Переводим в секунды Эпохи 2.1209 - # В labmaker'е данные хранились в неудобной форме: hour, min, sec, day of year 2.1210 - # Информация о годе отсутствовала 2.1211 - # Её можно внести: 2.1212 - # Декабрь 2004 год; остальные -- 2005 год. 2.1213 - 2.1214 - my $year = 2005; 2.1215 - #$year = 2004 if ( $cl->{day} > 330 ); 2.1216 - $year = $Config{year} if $Config{year}; 2.1217 - # timelocal( $sec, $min, $hour, $mday,$mon,$year); 2.1218 - $cl->{time} = timelocal_nocheck($cl->{sec},$cl->{min},$cl->{hour},$cl->{day},0,$year); 2.1219 - 2.1220 - 2.1221 - # Начинаем вывод команды 2.1222 - print OUT "<command>\n"; 2.1223 - print OUT "<local_session_id>",$cl->{local_session_id},"</local_session_id>\n"; 2.1224 - print OUT "<time>",$cl->{time},"</time>\n"; 2.1225 - print OUT "<raw_start>",$cl->{raw_start},"</raw_start>\n"; 2.1226 - print OUT "<raw_output_start>",$cl->{raw_output_start},"</raw_output_start>\n"; 2.1227 - print OUT "<raw_end>",$cl->{raw_end},"</raw_end>\n"; 2.1228 - print OUT "<raw_file>",$cl->{raw_file},"</raw_file>\n"; 2.1229 - print OUT "<tty>",$cl->{tty},"</tty>\n"; 2.1230 - print OUT "<uid>",$cl->{uid},"</uid>\n"; 2.1231 - print OUT "<out_class>",$out_class,"</out_class>\n"; 2.1232 - print OUT "<err>",$cl->{err},"</err>\n"; 2.1233 - print OUT "<prompt>"; 2.1234 - printq(\*OUT,,$cl->{"prompt"}); 2.1235 - print OUT "</prompt>"; 2.1236 - print OUT "<cline>"; 2.1237 - printq(\*OUT,$cl->{"cline"}); 2.1238 - print OUT "</cline>\n"; 2.1239 - print OUT "<last_command>",$cl->{"last_command"},"</last_command>\n"; 2.1240 - if (@new_commands) { 2.1241 - print OUT "<new_commands>"; 2.1242 - printq(\*OUT, join (" ", @new_commands)); 2.1243 - print OUT "</new_commands>"; 2.1244 - } 2.1245 - if (@new_files) { 2.1246 - print OUT "<new_files>"; 2.1247 - printq(\*OUT, join (" ", @new_files)); 2.1248 - print OUT "</new_files>"; 2.1249 - } 2.1250 - print OUT "<output>"; 2.1251 - printq(\*OUT,$output); 2.1252 - print OUT "</output>\n"; 2.1253 - if ($cl->{"diff"}) { 2.1254 - print OUT "<diff>"; 2.1255 - printq(\*OUT,${$Diffs{$cl->{"diff"}}}{"text"}); 2.1256 - print OUT "</diff>\n"; 2.1257 - } 2.1258 - if ($cl->{"note"}) { 2.1259 - print OUT "<note>"; 2.1260 - printq(\*OUT,$cl->{"note"}); 2.1261 - print OUT "</note>\n"; 2.1262 - } 2.1263 - if ($cl->{"note_title"}) { 2.1264 - print OUT "<note_title>"; 2.1265 - printq(\*OUT,$cl->{"note_title"}); 2.1266 - print OUT "</note_title>\n"; 2.1267 - } 2.1268 - print OUT "</command>\n"; 2.1269 - 2.1270 - } 2.1271 - 2.1272 - #print OUT "</livelablog>\n"; 2.1273 - close(OUT); 2.1274 + close(OUT); 2.1275 } 2.1276 2.1277 sub print_session 2.1278 { 2.1279 - my $output_filename = $_[0]; 2.1280 - my $local_session_id = $_[1]; 2.1281 - return if not defined($Sessions{$local_session_id}); 2.1282 + my $output_filename = $_[0]; 2.1283 + my $local_session_id = $_[1]; 2.1284 + return if not defined($Sessions{$local_session_id}); 2.1285 2.1286 - open(OUT, ">>", $output_filename) 2.1287 - or die "Can't open $output_filename for writing\n"; 2.1288 - print OUT "<session>\n"; 2.1289 - my %session = %{$Sessions{$local_session_id}}; 2.1290 - for my $key (keys %session) { 2.1291 - print OUT "<$key>".$session{$key}."</$key>\n" 2.1292 - } 2.1293 - print OUT "</session>\n"; 2.1294 - close(OUT); 2.1295 + open(OUT, ">>", $output_filename) 2.1296 + or die "Can't open $output_filename for writing\n"; 2.1297 + print OUT "<session>\n"; 2.1298 + my %session = %{$Sessions{$local_session_id}}; 2.1299 + for my $key (keys %session) { 2.1300 + print OUT "<$key>".$session{$key}."</$key>\n" 2.1301 + } 2.1302 + print OUT "</session>\n"; 2.1303 + close(OUT); 2.1304 } 2.1305 2.1306 sub send_cache 2.1307 { 2.1308 - # Если в кэше что-то накопилось, 2.1309 - # попытаемся отправить это на сервер 2.1310 - # 2.1311 - my $cache_was_sent=0; 2.1312 - 2.1313 - if (open(CACHE, $Config{cache})) { 2.1314 - local $/; 2.1315 - my $cache = <CACHE>; 2.1316 - close(CACHE); 2.1317 + # Если в кэше что-то накопилось, 2.1318 + # попытаемся отправить это на сервер 2.1319 + # 2.1320 + my $cache_was_sent=0; 2.1321 + 2.1322 + if (open(CACHE, $Config{cache})) { 2.1323 + local $/; 2.1324 + my $cache = <CACHE>; 2.1325 + close(CACHE); 2.1326 2.1327 - my $socket = IO::Socket::INET->new( 2.1328 - PeerAddr => $Config{backend_address}, 2.1329 - PeerPort => $Config{backend_port}, 2.1330 - proto => "tcp", 2.1331 - Type => SOCK_STREAM 2.1332 - ); 2.1333 + my $socket = IO::Socket::INET->new( 2.1334 + PeerAddr => $Config{backend_address}, 2.1335 + PeerPort => $Config{backend_port}, 2.1336 + proto => "tcp", 2.1337 + Type => SOCK_STREAM 2.1338 + ); 2.1339 2.1340 - if ($socket) { 2.1341 - print $socket $cache; 2.1342 - close($socket); 2.1343 - $cache_was_sent = 1; 2.1344 - } 2.1345 - } 2.1346 - return $cache_was_sent; 2.1347 + if ($socket) { 2.1348 + print $socket $cache; 2.1349 + close($socket); 2.1350 + $cache_was_sent = 1; 2.1351 + } 2.1352 + } 2.1353 + return $cache_was_sent; 2.1354 } 2.1355 2.1356 sub save_cache_stat 2.1357 { 2.1358 - open (CACHE, ">$Config{cache_stat}"); 2.1359 - for my $f (keys %Script_Files) { 2.1360 - print CACHE "$f\t",$Script_Files{$f}->{size},"\t",$Script_Files{$f}->{tell},"\n"; 2.1361 - } 2.1362 - close(CACHE); 2.1363 + open (CACHE, ">$Config{cache_stat}"); 2.1364 + for my $f (keys %Script_Files) { 2.1365 + print CACHE "$f\t",$Script_Files{$f}->{size},"\t",$Script_Files{$f}->{tell},"\n"; 2.1366 + } 2.1367 + close(CACHE); 2.1368 } 2.1369 2.1370 sub load_cache_stat 2.1371 { 2.1372 - if (open (CACHE, "$Config{cache_stat}")) { 2.1373 - while(<CACHE>) { 2.1374 - chomp; 2.1375 - my ($f, $size, $tell) = split /\t/; 2.1376 - $Script_Files{$f}->{size} = $size; 2.1377 - $Script_Files{$f}->{tell} = $tell; 2.1378 - } 2.1379 - close(CACHE); 2.1380 - }; 2.1381 + if (open (CACHE, "$Config{cache_stat}")) { 2.1382 + while(<CACHE>) { 2.1383 + chomp; 2.1384 + my ($f, $size, $tell) = split /\t/; 2.1385 + $Script_Files{$f}->{size} = $size; 2.1386 + $Script_Files{$f}->{tell} = $tell; 2.1387 + } 2.1388 + close(CACHE); 2.1389 + }; 2.1390 } 2.1391 2.1392 2.1393 @@ -931,102 +646,102 @@ 2.1394 2.1395 sub process_was_killed 2.1396 { 2.1397 - $Killed = 1; 2.1398 + $Killed = 1; 2.1399 } 2.1400 2.1401 sub main 2.1402 { 2.1403 2.1404 - $| = 1; 2.1405 + $| = 1; 2.1406 2.1407 - init_variables(); 2.1408 - init_config(); 2.1409 + init_variables(); 2.1410 + init_config(); 2.1411 2.1412 2.1413 - if ($Config{"mode"} ne "daemon") { 2.1414 + if ($Config{"mode"} ne "daemon") { 2.1415 2.1416 =cut 2.1417 - В нормальном режиме работы нужно 2.1418 - считать скрипты, обработать их и записать 2.1419 - результат выполнения в результриующий файл. 2.1420 - После этого завершить работу. 2.1421 + В нормальном режиме работы нужно 2.1422 + считать скрипты, обработать их и записать 2.1423 + результат выполнения в результирующий файл. 2.1424 + После этого завершить работу. 2.1425 =cut 2.1426 - for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { 2.1427 - load_diff_files($lab_log); 2.1428 - } 2.1429 - load_command_lines($Config{"input"}, $Config{"input_mask"}); 2.1430 - sort_command_lines; 2.1431 - process_command_lines; 2.1432 - print_command_lines($Config{"cache"}); 2.1433 - } 2.1434 - else { 2.1435 - if (open(PIDFILE, $Config{agent_pidfile})) { 2.1436 - my $pid = <PIDFILE>; 2.1437 - close(PIDFILE); 2.1438 - if ($^O eq 'linux' && $pid &&(! -e "/proc/$pid" || !`grep $Config{"l3-agent"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`)) { 2.1439 - print "Removing stale pidfile\n"; 2.1440 - unlink $Config{agent_pidfile} 2.1441 - or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; 2.1442 - } 2.1443 - elsif ($^O eq 'freebsd' && $pid && `ps axo uid,pid,command | grep '$<\\s*$pid\\s*$Config{"l3-agent"}' 2> /dev/null`) { 2.1444 - print "Removing stale pidfile\n"; 2.1445 - unlink $Config{agent_pidfile} 2.1446 - or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; 2.1447 - } 2.1448 - elsif ($^O eq 'linux' || $^O eq 'freebsd' ) { 2.1449 - print "l3-agent is already running: pid=$pid; pidfile=$Config{agent_pidfile}\n"; 2.1450 - exit(0); 2.1451 - } 2.1452 - else { 2.1453 - print "Unknown operating system"; 2.1454 - exit(0); 2.1455 - } 2.1456 - } 2.1457 - if ($Config{detach} =~ /^y/i) { 2.1458 - #$Config{verbose} = "no"; 2.1459 - my $pid = fork; 2.1460 - exit if $pid; 2.1461 - die "Couldn't fork: $!" unless defined ($pid); 2.1462 + for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { 2.1463 + load_diff_files($lab_log); 2.1464 + } 2.1465 + load_command_lines($Config{"input"}, $Config{"input_mask"}); 2.1466 + sort_command_lines; 2.1467 + #process_command_lines; 2.1468 + print_command_lines($Config{"cache"}); 2.1469 + } 2.1470 + else { 2.1471 + if (open(PIDFILE, $Config{agent_pidfile})) { 2.1472 + my $pid = <PIDFILE>; 2.1473 + close(PIDFILE); 2.1474 + if ($^O eq 'linux' && $pid &&(! -e "/proc/$pid" || !`grep $Config{"l3-agent"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`)) { 2.1475 + print "Removing stale pidfile\n"; 2.1476 + unlink $Config{agent_pidfile} 2.1477 + or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; 2.1478 + } 2.1479 + elsif ($^O eq 'freebsd' && $pid && `ps axo uid,pid,command | grep '$<\\s*$pid\\s*$Config{"l3-agent"}' 2> /dev/null`) { 2.1480 + print "Removing stale pidfile\n"; 2.1481 + unlink $Config{agent_pidfile} 2.1482 + or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; 2.1483 + } 2.1484 + elsif ($^O eq 'linux' || $^O eq 'freebsd' ) { 2.1485 + print "l3-agent is already running: pid=$pid; pidfile=$Config{agent_pidfile}\n"; 2.1486 + exit(0); 2.1487 + } 2.1488 + else { 2.1489 + print "Unknown operating system"; 2.1490 + exit(0); 2.1491 + } 2.1492 + } 2.1493 + if ($Config{detach} =~ /^y/i) { 2.1494 + #$Config{verbose} = "no"; 2.1495 + my $pid = fork; 2.1496 + exit if $pid; 2.1497 + die "Couldn't fork: $!" unless defined ($pid); 2.1498 2.1499 - open(PIDFILE, ">", $Config{agent_pidfile}) 2.1500 - or die "Can't open pidfile ". $Config{agent_pidfile}. " for wrting: $!"; 2.1501 - print PIDFILE $$; 2.1502 - close(PIDFILE); 2.1503 + open(PIDFILE, ">", $Config{agent_pidfile}) 2.1504 + or die "Can't open pidfile ". $Config{agent_pidfile}. " for wrting: $!"; 2.1505 + print PIDFILE $$; 2.1506 + close(PIDFILE); 2.1507 2.1508 - for my $handle (*STDIN, *STDOUT, *STDERR) { 2.1509 - open ($handle, "+<", "/dev/null") 2.1510 - or die "can't reopen $handle to /dev/null: $!" 2.1511 - } 2.1512 + for my $handle (*STDIN, *STDOUT, *STDERR) { 2.1513 + open ($handle, "+<", "/dev/null") 2.1514 + or die "can't reopen $handle to /dev/null: $!" 2.1515 + } 2.1516 2.1517 - POSIX::setsid() 2.1518 - or die "Can't start a new session: $!"; 2.1519 + POSIX::setsid() 2.1520 + or die "Can't start a new session: $!"; 2.1521 2.1522 - $0 = $Config{"l3-agent"}; 2.1523 - 2.1524 - $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed; 2.1525 - } 2.1526 - while (not $Killed) { 2.1527 - @Command_Lines = (); 2.1528 - @Command_Lines_Index = (); 2.1529 - for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { 2.1530 - load_diff_files($lab_log); 2.1531 - } 2.1532 - load_cache_stat(); 2.1533 - load_command_lines($Config{"input"}, $Config{"input_mask"}); 2.1534 - if (@Command_Lines) { 2.1535 - sort_command_lines; 2.1536 - process_command_lines; 2.1537 - print_command_lines($Config{"cache"}); 2.1538 - } 2.1539 - save_cache_stat(); 2.1540 - if (-e $Config{cache} && (stat($Config{cache}))[7]) { 2.1541 - send_cache() && unlink($Config{cache}); 2.1542 - } 2.1543 - sleep($Config{"daemon_sleep_interval"} || 1); 2.1544 - } 2.1545 - 2.1546 - unlink $Config{agent_pidfile}; 2.1547 - } 2.1548 + $0 = $Config{"l3-agent"}; 2.1549 + 2.1550 + $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed; 2.1551 + } 2.1552 + while (not $Killed) { 2.1553 + @Command_Lines = (); 2.1554 + @Command_Lines_Index = (); 2.1555 + for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { 2.1556 + load_diff_files($lab_log); 2.1557 + } 2.1558 + load_cache_stat(); 2.1559 + load_command_lines($Config{"input"}, $Config{"input_mask"}); 2.1560 + if (@Command_Lines) { 2.1561 + sort_command_lines; 2.1562 + process_command_lines; 2.1563 + print_command_lines($Config{"cache"}); 2.1564 + } 2.1565 + save_cache_stat(); 2.1566 + if (-e $Config{cache} && (stat($Config{cache}))[7]) { 2.1567 + send_cache() && unlink($Config{cache}); 2.1568 + } 2.1569 + sleep($Config{"daemon_sleep_interval"} || 1); 2.1570 + } 2.1571 + 2.1572 + unlink $Config{agent_pidfile}; 2.1573 + } 2.1574 2.1575 } 2.1576
3.1 --- a/l3-frontend Sat Jan 21 19:09:34 2006 +0200 3.2 +++ b/l3-frontend Thu Jan 26 00:00:53 2006 +0200 3.3 @@ -771,7 +771,22 @@ 3.4 <script> 3.5 $Html_JavaScript 3.6 </script> 3.7 - <h1>Журнал лабораторных работ</h1> 3.8 + 3.9 +<!-- vvv Tigra Hints vvv --> 3.10 +<script language="JavaScript" src="/tigra/hints.js"></script> 3.11 +<script language="JavaScript" src="/tigra/hints_cfg.js"></script> 3.12 +<style> 3.13 +/* a class for all Tigra Hints boxes, TD object */ 3.14 + .hintsClass 3.15 + {text-align: center; font-family: Verdana, Arial, Helvetica; padding: 0px 0px 0px 0px;} 3.16 +/* this class is used by Tigra Hints wrappers */ 3.17 + .row 3.18 + {background: white;} 3.19 +</style> 3.20 +<!-- ^^^ Tigra Hints ^^^ --> 3.21 + 3.22 + 3.23 + <h1 onmouseover="myHint.show('1')" onmouseout="myHint.hide()">Журнал лабораторных работ</h1> 3.24 HEADER 3.25 if ( $course_student 3.26 || $course_trainer