# HG changeset patch # User devi # Date 1138226453 -7200 # Node ID c4bea959dbb1302df7bb744533cc47b6ad03db13 # Parent 440d12c122d5d174ad077c6f100e3856479416be Beautyfication of l3-agent code. Many lines were erased. Need to be tested diff -r 440d12c122d5 -r c4bea959dbb1 README --- a/README Sat Jan 21 19:09:34 2006 +0200 +++ b/README Thu Jan 26 00:00:53 2006 +0200 @@ -0,0 +1,154 @@ +АТРИБУТЫ cline +СПИСОК ПОЛЕЙ, ХАРАКТЕРИЗУЮЩИХ КОМАНДНУЮ СТРОКУ + + uid + Идентификатор пользователя + + tty + Идентификатор терминала, на котором была вызвана команда + + pid + PID-процесса командного интерпретатора, + в котором была вызвана команда + + lab + лабораторная работа, к которой относится команда. + Идентификатор текущей лабораторной работы + хранится в файле ~/.labmaker/lab + + pwd (!) + текущий каталог, из которого была вызвана команда + + day + время вызова, день + В действительности здесь хранится не время вызова команды, + а с момента появления приглашения командного интерпретатора + для ввода команды + + + hour + время вызова, час + + min + время вызова, минута + + sec + время вызова, секунда + + time (!) + время вызова команды в Unix-формате. + Предпочтительнее использовать этот формат чем hour:min:sec, + использовавшийся в Labmaker + + fullprompt + Приглашение командной строки + + prompt + Сокращённое приглашение командной строки + + cline + Командная строка + + output + Результат выполнения команды + + diff + Указатель на ассоциированный с командой diff + + note (!) + Текстовый комментарий к команде. + Может генерироваться из самого лога с помощью команд + #^ Комментарий + #= Комментарий + #v Комментарий + в том случае, если для комментирования достаточно одной строки, + или с помощью команд + cat > /dev/null #^ Заголовок + Текст + ^D + в том случае, если комментарий развёрнутый. + В последнем случае комментарий может содержать + заголовок, абзацы и несложное форматирование. + + Символы ^, v или = после знака комментария # обозначает, + к какой команде относится комментарий: + к предыдущей (^), последующей (v) + или это общий комментарий по тексту, не относящийся непосредственно + ни к одной из них (=) + + err + Код завершения командной строки + + histnum (!) + Номер команды в истории командного интерпретатора + + status (!) + Является ли данная команда вызванной (r), запомненной (s) + или это подсказка completion (c). + + Команды, которые были вызваны и обработаны интерпретатором + имеют состояние "r". К таким командам относится большинство + команд вводимых в интерпретатор. + + Если команда набрана, но вызывать её по какой-либо причине + не хочется (например, команда может быть не полной, вредоносной + или просто бессмысленной в текущих условиях), + её можно сбросить с помощью комбинации клавиш Ctrl-C + (не путайте с прерыванием работающей команды! здесь она даже + не запускается!). + В таком случае она не выполняется, но попадает в журнал + со статусом "s". + + Если команда появилась в журнале благодаря автопроолжению + -- когда было показано несколько вариантов -- + она имеет статус "c". + + euid + Идентификатор пользователя от имени которого будет + выполняться команда. + Может отличаться от реального uid в том случае, + если вызывается с помощью sudo + + + version (!) + Версия lilalo-prompt использовавшаяся при записи + команды. + + 0 - версия использовавшая в labmaker. + Отсутствует информация о текущем каталоге и номере в истории. + Информация о версии также не указана в приглашении. + + + 1 - версия использующаяся в lilalo + + raw_file + Имя файла, в котором находится бинарное представление журнала. + Может содержать ключевое слово HERE, + обозначающее что бинарное представление хранится + непосредственно в базе данных в атрибуте raw_data + + raw_start + Начало блока командной строки в файле бинарного представления + + raw_output_start + Начало блока вывода + + raw_end + Конец блока командной строки в файле бинарного представления + + raw_cline + Необработанная командная строка (без приглашения) в бинарном виде + + raw_data (*) + Бинарное представление команды и результатов её выполнения + + + + +ТАБЛИЦА SESSION + + Информация о сеансах + + (см. lm-install) + + diff -r 440d12c122d5 -r c4bea959dbb1 l3-agent --- a/l3-agent Sat Jan 21 19:09:34 2006 +0200 +++ b/l3-agent Thu Jan 26 00:00:53 2006 +0200 @@ -1,7 +1,7 @@ #!/usr/bin/perl -w # -# (c) Igor Chubin, imchubin@mail.ru, 2004-2005 +# (c) Igor Chubin, igor@chub.in, 2004-2006 # @@ -24,26 +24,22 @@ our %Diffs; our %Sessions; -our %Commands_Stat; # Statistics about commands usage -our %Files_Stat; # Statistics about commands usage +our %Script_Files; # Информация о позициях в скрипт-файлах, + # до которых уже выполнен разбор + # и информация о времени модификации файла + # $Script_Files{$file}->{size} + # $Script_Files{$file}->{tell} -our %Script_Files; # Информация о позициях в скрипт-файлах, - # до которых уже выполнен разбор - # и информация о времени модификации файла - # $Script_Files{$file}->{size} - # $Script_Files{$file}->{tell} - -our $Killed =0; # В режиме демона -- процесс получил сигнал о завершении +our $Killed =0; # В режиме демона -- процесс получил сигнал о завершении sub init_variables; sub main; sub load_diff_files; sub bind_diff; -sub extract_from_cline; +sub extract_commands_from_cline; sub load_command_lines; sub sort_command_lines; -sub process_command_lines; sub print_command_lines; sub printq; @@ -53,20 +49,20 @@ sub load_diff_files { - my @pathes = @_; - - for my $path (@pathes) { - my $template = "*.diff"; - my @files = <$path/$template>; - my $i=0; - for my $file (@files) { + my @pathes = @_; + + for my $path (@pathes) { + my $template = "*.diff"; + my @files = <$path/$template>; + my $i=0; + for my $file (@files) { - next if defined($Diffs{$file}); - - my %diff; - - $diff{"path"}=$path; - $diff{"uid"}="SET THIS"; + next if defined($Diffs{$file}); + + my %diff; + + $diff{"path"}=$path; + $diff{"uid"}="SET THIS"; # Сейчас UID определяется из названия каталога # откуда берутся diff-файлы @@ -77,634 +73,381 @@ # мз которых и будет определяться соответствие # имён пользователей их uid'ам # - $diff{"uid"} = 0 if $path =~ m@/root/@; - - $diff{"bind_to"}=""; - $diff{"time_range"}=-1; - - next if not $file=~m@/(D?[0-9][0-9]?[0-9]?)[^/]*?([0-9]*):([0-9]*):?([0-9]*)@; - $diff{"day"}=$1 || ""; - $diff{"hour"}=$2; - $diff{"min"}=$3; - $diff{"sec"}=$4 || 0; - - $diff{"index"}=$i; + $diff{"uid"} = 0 if $path =~ m@/root/@; + + $diff{"bind_to"}=""; + $diff{"time_range"}=-1; + + next if not $file=~m@/(D?[0-9][0-9]?[0-9]?)[^/]*?([0-9]*):([0-9]*):?([0-9]*)@; + $diff{"day"}=$1 || ""; + $diff{"hour"}=$2; + $diff{"min"}=$3; + $diff{"sec"}=$4 || 0; + + $diff{"index"}=$i; - print "diff loaded: $diff{day} $diff{hour}:$diff{min}:$diff{sec}\n"; - - local $/; - open (F, "$file") - or return "Can't open file $file ($_[0]) for reading"; - my $text = ; - if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i) { - my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8"); - $text = $converter->convert($text); - } - close(F); - $diff{"text"}=$text; - #print "$file loaded ($diff{day})\n"; + print "diff loaded: $diff{day} $diff{hour}:$diff{min}:$diff{sec}\n"; + + local $/; + open (F, "$file") + or return "Can't open file $file ($_[0]) for reading"; + my $text = ; + if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i) { + my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8"); + $text = $converter->convert($text); + } + close(F); + $diff{"text"}=$text; + #print "$file loaded ($diff{day})\n"; - #push @Diffs, \%diff; - $Diffs{$file} = \%diff; - $i++; - } - } + #push @Diffs, \%diff; + $Diffs{$file} = \%diff; + $i++; + } + } } sub bind_diff { -# my $path = shift; -# my $pid = shift; -# my $day = shift; -# my $lab = shift; +# my $path = shift; +# my $pid = shift; +# my $day = shift; +# my $lab = shift; - print "Trying to bind diff...\n"; + print "Trying to bind diff...\n"; - my $cl = shift; - my $hour = $cl->{"hour"}; - my $min = $cl->{"min"}; - my $sec = $cl->{"sec"}; + my $cl = shift; + my $hour = $cl->{"hour"}; + my $min = $cl->{"min"}; + my $sec = $cl->{"sec"}; - my $min_dt = 10000; + my $min_dt = 10000; - for my $diff_key (keys %Diffs) { - my $diff = $Diffs{$diff_key}; - # Check here date, time and user - next if ($diff->{"day"} && $cl->{"day"} && ($cl->{"day"} ne $diff->{"day"})); - #next if (!$diff->{"uid"} && $cl->{"euid"} != $diff->{"uid"}); - - my $dt=($diff->{"hour"}-$hour)*3600 +($diff->{"min"}-$min)*60 + ($diff->{"sec"}-$sec); - if ($dt >0 && $dt < $min_dt && ($diff->{"time_range"} <0 || $dt < $diff->{"time_range"})) { - print "Approppriate diff found: dt=$dt\n"; - if ($diff->{"bind_to"}) { - undef $diff->{"bind_to"}->{"diff"}; - }; - $diff->{"time_range"}=$dt; - $diff->{"bind_to"}=$cl; + for my $diff_key (keys %Diffs) { + my $diff = $Diffs{$diff_key}; + # Check here date, time and user + next if ($diff->{"day"} && $cl->{"day"} && ($cl->{"day"} ne $diff->{"day"})); + #next if (!$diff->{"uid"} && $cl->{"euid"} != $diff->{"uid"}); + + my $dt=($diff->{"hour"}-$hour)*3600 +($diff->{"min"}-$min)*60 + ($diff->{"sec"}-$sec); + if ($dt >0 && $dt < $min_dt && ($diff->{"time_range"} <0 || $dt < $diff->{"time_range"})) { + print "Approppriate diff found: dt=$dt\n"; + if ($diff->{"bind_to"}) { + undef $diff->{"bind_to"}->{"diff"}; + }; + $diff->{"time_range"}=$dt; + $diff->{"bind_to"}=$cl; - #$cl->{"diff"} = $diff->{"index"}; - $cl->{"diff"} = $diff_key; - $min_dt = $dt; - } - - } + $cl->{"diff"} = $diff_key; + $min_dt = $dt; + } + } } -sub extract_from_cline +sub extract_commands_from_cline # Разобрать командную строку $_[1] и возвратить хэш, содержащий # номер первого появление команды в строке: -# команда => первая позиция +# команда => первая позиция { - my $what = $_[0]; - my $cline = $_[1]; - my @lists = split /\;/, $cline; - - - my @commands = (); - for my $list (@lists) { - push @commands, split /\|/, $list; - } + my $cline = $_[0]; + my @lists = split /\;/, $cline; + + + my @commands = (); + for my $list (@lists) { + push @commands, split /\|/, $list; + } - my %commands; - my %files; - my $i=0; - for my $command (@commands) { - $command =~ /\s*(\S+)\s*(.*)/; - if ($1 && $1 eq "sudo" ) { - $commands{"$1"}=$i++; - $command =~ s/\s*sudo\s+//; - } - $command =~ /\s*(\S+)\s*(.*)/; - if ($1 && !defined $commands{"$1"}) { - $commands{"$1"}=$i++; - }; - if ($2) { - my $args = $2; - my @args = split (/\s+/, $args); - for my $a (@args) { - $files{"$a"}=$i++ - if !defined $files{"$a"}; - }; - - - } - } - - if ($what eq "commands") { - return %commands; - } else { - return %files; - } - + my %commands; + my %files; + my $i=0; + for my $command (@commands) { + $command =~ /\s*(\S+)\s*(.*)/; + if ($1 && $1 eq "sudo" ) { + $commands{"$1"}=$i++; + $command =~ s/\s*sudo\s+//; + } + $command =~ /\s*(\S+)\s*(.*)/; + if ($1 && !defined $commands{"$1"}) { + $commands{"$1"}=$i++; + }; + } + return %commands; } sub load_command_lines { - my $lab_scripts_path = $_[0]; - my $lab_scripts_mask = $_[1]; + my $lab_scripts_path = $_[0]; + my $lab_scripts_mask = $_[1]; - my $cline_re_base = qq' - ( - (?:\\^?([0-9]*C?)) # exitcode - (?:_([0-9]+)_)? # uid - (?:_([0-9]+)_) # pid - (...?) # day - (.?.?) # lab - \\s # space separator - ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) # time - .\\[50D.\\[K # killing symbols - (.*?([\$\#]\\s?)) # prompt - (.*) # command line - ) - '; - #my $cline_re = qr/$cline_re_base(?:$cline_re_base|$)/x; - #my $cline_re = qr/(?:$cline_re_base)*$cline_re_base$/x; - my $cline_re = qr/$cline_re_base/sx; - my $cline_re1 = qr/$cline_re_base\x0D/sx; - my $cline_re2 = qr/$cline_re_base$/sx; + my $cline_re_base = qq' + ( + (?:\\^?([0-9]*C?)) # exitcode + (?:_([0-9]+)_)? # uid + (?:_([0-9]+)_) # pid + (...?) # day + (.?.?) # lab + \\s # space separator + ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) # time + .\\[50D.\\[K # killing symbols + (.*?([\$\#]\\s?)) # prompt + (.*) # command line + ) + '; + #my $cline_re = qr/$cline_re_base(?:$cline_re_base|$)/x; + #my $cline_re = qr/(?:$cline_re_base)*$cline_re_base$/x; + my $cline_re = qr/$cline_re_base/sx; + my $cline_re1 = qr/$cline_re_base\x0D/sx; + my $cline_re2 = qr/$cline_re_base$/sx; - my $vt = Term::VT102->new ( 'cols' => $Config{"terminal_width"}, - 'rows' => $Config{"terminal_height"}); - my $cline_vt = Term::VT102->new ('cols' => $Config{"terminal_width"}, - 'rows' => $Config{"terminal_height"}); + my $vt = Term::VT102->new ( 'cols' => $Config{"terminal_width"}, + 'rows' => $Config{"terminal_height"}); + my $cline_vt = Term::VT102->new ('cols' => $Config{"terminal_width"}, + 'rows' => $Config{"terminal_height"}); - my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8") - if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i); - - print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/; + my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8") + if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i); + + print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/; - my $file; - my $skip_info; + my $file; + my $skip_info; - my $commandlines_loaded =0; - my $commandlines_processed =0; + my $commandlines_loaded =0; + my $commandlines_processed =0; - my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>; - for $file (@lab_scripts){ - - # Пропускаем файл, если он не изменялся со времени нашего предудущего прохода - my $size = (stat($file))[7]; - next if ($Script_Files{$file} && $Script_Files{$file}->{size} && $Script_Files{$file}->{size} >= $size); + my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>; + for $file (@lab_scripts){ + # Пропускаем файл, если он не изменялся со времени нашего предудущего прохода + my $size = (stat($file))[7]; + next if ($Script_Files{$file} && $Script_Files{$file}->{size} && $Script_Files{$file}->{size} >= $size); - my $local_session_id; - # Начальное значение идентификатора текущего сеанса определяем из имени скрипта - # Впоследствии оно может быть уточнено - $file =~ m@.*/([^/]*)\.script$@; - $local_session_id = $1; - #Если файл только что появился, - #пытаемся найти и загрузить информацию о соответствующей ему сессии - if (!$Script_Files{$file}) { - my $session_file = $file; - $session_file =~ s/\.script/.info/; - if (open(SESSION, $session_file)) { - local $/; - my $data = ; - close(SESSION); + my $local_session_id; + # Начальное значение идентификатора текущего сеанса определяем из имени скрипта + # Впоследствии оно может быть уточнено + $file =~ m@.*/([^/]*)\.script$@; + $local_session_id = $1; - for my $session_data ($data =~ m@(.*?)@sg) { - my %session; - while ($session_data =~ m@<([^>]*?)>(.*?)@sg) { - $session{$1} = $2; - } - $local_session_id = $session{"local_session_id"} if $session{"local_session_id"}; - $Sessions{$local_session_id}=\%session; - } + #Если файл только что появился, + #пытаемся найти и загрузить информацию о соответствующей ему сессии + if (!$Script_Files{$file}) { + my $session_file = $file; + $session_file =~ s/\.script/.info/; + if (open(SESSION, $session_file)) { + local $/; + my $data = ; + close(SESSION); - #Загруженную информацию сразу же отправляем в поток - print_session($Config{cache}, $local_session_id); - } - } - - open (FILE, "$file"); - binmode FILE; - - # Переходим к тому месту, где мы окончили разбор - seek (FILE, $Script_Files{$file}->{tell}, 0) if $Script_Files{$file}->{tell}; - $Script_Files{$file}->{size} = $size; - $Script_Files{$file}->{tell} = 0 unless $Script_Files{$file}->{tell}; + for my $session_data ($data =~ m@(.*?)@sg) { + my %session; + while ($session_data =~ m@<([^>]*?)>(.*?)@sg) { + $session{$1} = $2; + } + $local_session_id = $session{"local_session_id"} if $session{"local_session_id"}; + $Sessions{$local_session_id}=\%session; + } + #Загруженную информацию сразу же отправляем в поток + print_session($Config{cache}, $local_session_id); + } + } - $file =~ m@.*/(.*?)-.*@; - - my $tty = $1; - my $first_pass = 1; - my %cl; - my $last_output_length=0; - while () { - - $commandlines_processed++; - # time + open (FILE, "$file"); + binmode FILE; - next if s/^Script started on.*?\n//s; + # Переходим к тому месту, где мы окончили разбор + seek (FILE, $Script_Files{$file}->{tell}, 0) if $Script_Files{$file}->{tell}; + $Script_Files{$file}->{size} = $size; + $Script_Files{$file}->{tell} = 0 unless $Script_Files{$file}->{tell}; - if (/[0-9][0-9]:[0-9][0-9]:[0-9][0-9].\[[0-9][0-9]D.\[K/ && m/$cline_re/) { - s/.*\x0d(?!\x0a)//; - # print "!!!",$_,"!!!\n"; - # next; - # while (m/$cline_re1/gs) { - # } - m/$cline_re2/gs; + $file =~ m@.*/(.*?)-.*@; - $commandlines_loaded++; - $last_output_length=0; + my $tty = $1; + my $first_pass = 1; + my %cl; + my $last_output_length=0; + while () { + $commandlines_processed++; - # Previous command - my %last_cl = %cl; - my $err = $2 || ""; + next if s/^Script started on.*?\n//s; + if (/[0-9][0-9]:[0-9][0-9]:[0-9][0-9].\[[0-9][0-9]D.\[K/ && m/$cline_re/) { + s/.*\x0d(?!\x0a)//; + m/$cline_re2/gs; -=cut + $commandlines_loaded++; + $last_output_length=0; -Атрибуты cline -Список полей, характеризующих командную строку + # Previous command + my %last_cl = %cl; + my $err = $2 || ""; - uid - Идентификатор пользователя - - tty - Идентификатор терминала, на котором была вызвана команда + $cl{"local_session_id"} = $local_session_id; + # Parse new command + $cl{"uid"} = $3; + $cl{"euid"} = $cl{"uid"}; # Если в команде обнаружится sudo, euid поменяем на 0 + $cl{"pid"} = $4; + $cl{"day"} = $5; + $cl{"lab"} = $6; + $cl{"hour"} = $7; + $cl{"min"} = $8; + $cl{"sec"} = $9; + $cl{"fullprompt"} = $10; + $cl{"prompt"} = $11; + $cl{"raw_cline"} = $12; - pid - PID-процесса командного интерпретатора, - в котором была вызвана команда - - lab - лабораторная работа, к которой относится команда. - Идентификатор текущей лабораторной работы - хранится в файле ~/.labmaker/lab + { + use bytes; + $cl{"raw_start"} = tell (FILE) - length($1); + $cl{"raw_output_start"} = tell FILE; + } + $cl{"raw_file"} = $file; - pwd (!) - текущий каталог, из которого была вызвана команда + $cl{"err"} = 0; + $cl{"output"} = ""; + $cl{"tty"} = $tty; - day - время вызова, день - В действительности здесь хранится не время вызова команды, - а с момента появления приглашения командного интерпретатора - для ввода команды - - - hour - время вызова, час - - min - время вызова, минута - - sec - время вызова, секунда - - time (!) - время вызова команды в Unix-формате. - Предпочтительнее использовать этот формат чем hour:min:sec, - использовавшийся в Labmaker - - fullprompt - Приглашение командной строки - - prompt - Сокращённое приглашение командной строки + $cline_vt->process($cl{"raw_cline"}."\n"); + $cl{"cline"} = $cline_vt->row_plaintext (1); + $cl{"cline"} =~ s/\s*$//; + $cline_vt->reset(); - cline - Командная строка - - output - Результат выполнения команды - - diff - Указатель на ассоциированный с командой diff - - note (!) - Текстовый комментарий к команде. - Может генерироваться из самого лога с помощью команд - #^ Комментарий - #= Комментарий - #v Комментарий - в том случае, если для комментирования достаточно одной строки, - или с помощью команд - cat > /dev/null #^ Заголовок - Текст - ^D - в том случае, если комментарий развёрнутый. - В последнем случае комментарий может содержать - заголовок, абзацы и несложное форматирование. + my %commands = extract_commands_from_cline($cl{"cline"}); + $cl{"euid"}=0 if defined $commands{"sudo"}; + my @comms = sort { $commands{$a} cmp $commands{$b} } keys %commands; + $cl{"last_command"} = $comms[$#comms] || ""; - Символы ^, v или = после знака комментария # обозначает, - к какой команде относится комментарий: - к предыдущей (^), последующей (v) - или это общий комментарий по тексту, не относящийся непосредственно - ни к одной из них (=) + if ( + $Config{"suppress_editors"} =~ /^y/i + && grep ($_ eq $cl{"last_command"}, @{$Config{"editors"}}) + || $Config{"suppress_pagers"} =~ /^y/i + && grep ($_ eq $cl{"last_command"}, @{$Config{"pagers"}}) + || $Config{"suppress_terminal"}=~ /^y/i + && grep ($_ eq $cl{"last_command"}, @{$Config{"terminal"}}) + ) { + $cl{"suppress_output"} = "1"; + } + else { + $cl{"suppress_output"} = "0"; + } + $skip_info = 0; - err - Код завершения командной строки - - histnum (!) - Номер команды в истории командного интерпретатора - - status (!) - Является ли данная команда вызванной (r), запомненной (s) - или это подсказка completion (c). - - Команды, которые были вызваны и обработаны интерпретатором - имеют состояние "r". К таким командам относится большинство - команд вводимых в интерпретатор. - Если команда набрана, но вызывать её по какой-либо причине - не хочется (например, команда может быть не полной, вредоносной - или просто бессмысленной в текущих условиях), - её можно сбросить с помощью комбинации клавиш Ctrl-C - (не путайте с прерыванием работающей команды! здесь она даже - не запускается!). - В таком случае она не выполняется, но попадает в журнал - со статусом "s". - - Если команда появилась в журнале благодаря автопроолжению - -- когда было показано несколько вариантов -- - она имеет статус "c". - - euid - Идентификатор пользователя от имени которого будет - выполняться команда. - Может отличаться от реального uid в том случае, - если вызывается с помощью sudo + print " ",$cl{"last_command"}; - - version (!) - Версия lilalo-prompt использовавшаяся при записи - команды. + # Processing previous command line + if ($first_pass) { + $first_pass = 0; + next; + } - 0 - версия использовавшая в labmaker. - Отсутствует информация о текущем каталоге и номере в истории. - Информация о версии также не указана в приглашении. - - - 1 - версия использующаяся в lilalo - - raw_file - Имя файла, в котором находится бинарное представление журнала. - Может содержать ключевое слово HERE, - обозначающее что бинарное представление хранится - непосредственно в базе данных в атрибуте raw_data + # Error code + $last_cl{"raw_end"} = $cl{"raw_start"}; + $last_cl{"err"}=$err; + $last_cl{"err"}=130 if $err eq "^C"; - raw_start - Начало блока командной строки в файле бинарного представления - - raw_output_start - Начало блока вывода - - raw_end - Конец блока командной строки в файле бинарного представления + if (grep ($_ eq $last_cl{"last_command"}, @{$Config{"editors"}})) { + bind_diff(\%last_cl); + } - raw_cline - Необработанная командная строка (без приглашения) в бинарном виде - - raw_data (*) - Бинарное представление команды и результатов её выполнения + # Output + if (!$last_cl{"suppress_output"} || $last_cl{"err"}) { + for (my $i=0; $i<$Config{"terminal_height"}; $i++) { + my $line= $vt->row_plaintext($i); + next if !defined ($line) ; #|| $line =~ /^\s*$/; + $line =~ s/\s*$//; + $line .= "\n" unless $line =~ /^\s*$/; + $last_cl{"output"} .= $line; + } + } + else { + $last_cl{"output"}= ""; + } + $vt->reset(); - -ТАБЛИЦА SESSION - - Информация о сеансах + # Classifying the command line - (см. lm-install) + # Save + if (!$Config{"lab"} || $cl{"lab"} eq $Config{"lab"}) { + # Changing encoding + for (keys %last_cl) { + next if /raw/; + $last_cl{$_} = $converter->convert($last_cl{$_}) + if ($Config{"encoding"} && + $Config{"encoding"} !~ /^utf-8$/i); + } + push @Command_Lines, \%last_cl; -=cut + # Сохранение позиции в файле, до которой выполнен + # успешный разбор + $Script_Files{$file}->{tell} = $last_cl{raw_end}; + } + next; + } + $last_output_length+=length($_); + #if (!$cl{"suppress_output"} || $last_output_length < 5000) { + if ($last_output_length < 50000) { + $vt->process("$_"."\n") + } + else + { + if (!$skip_info) { + print "($cl{last_command})"; + $skip_info = 1; + } + } + } + close(FILE); - $cl{"local_session_id"} = $local_session_id; - # Parse new command - $cl{"uid"} = $3; - $cl{"euid"} = $cl{"uid"}; # Если в команде обнаружится sudo, euid поменяем на 0 - $cl{"pid"} = $4; - $cl{"day"} = $5; - $cl{"lab"} = $6; - $cl{"hour"} = $7; - $cl{"min"} = $8; - $cl{"sec"} = $9; - $cl{"fullprompt"} = $10; - $cl{"prompt"} = $11; - $cl{"raw_cline"} = $12; - - { - use bytes; - $cl{"raw_start"} = tell (FILE) - length($1); - $cl{"raw_output_start"} = tell FILE; - } - $cl{"raw_file"} = $file; - - $cl{"err"} = 0; - $cl{"output"} = ""; - $cl{"tty"} = $tty; - - $cline_vt->process($cl{"raw_cline"}."\n"); - $cl{"cline"} = $cline_vt->row_plaintext (1); - $cl{"cline"} =~ s/\s*$//; - $cline_vt->reset(); - - my %commands = extract_from_cline("commands", $cl{"cline"}); - $cl{"euid"}=0 if defined $commands{"sudo"}; - my @comms = sort { $commands{$a} cmp $commands{$b} } keys %commands; - $cl{"last_command"} = $comms[$#comms] || ""; - - if ( - $Config{"suppress_editors"} =~ /^y/i - && grep ($_ eq $cl{"last_command"}, @{$Config{"editors"}}) || - $Config{"suppress_pagers"} =~ /^y/i - && grep ($_ eq $cl{"last_command"}, @{$Config{"pagers"}}) || - $Config{"suppress_terminal"}=~ /^y/i - && grep ($_ eq $cl{"last_command"}, @{$Config{"terminal"}}) - ) { - $cl{"suppress_output"} = "1"; - } - else { - $cl{"suppress_output"} = "0"; - - } - $skip_info = 0; - - - print " ",$cl{"last_command"}; - - # Processing previous command line - if ($first_pass) { - $first_pass = 0; - next; - } - - # Error code - $last_cl{"raw_end"} = $cl{"raw_start"}; - $last_cl{"err"}=$err; - $last_cl{"err"}=130 if $err eq "^C"; - - if (grep ($_ eq $last_cl{"last_command"}, @{$Config{"editors"}})) { - bind_diff(\%last_cl); - } - - # Output - if (!$last_cl{"suppress_output"} || $last_cl{"err"}) { - for (my $i=0; $i<$Config{"terminal_height"}; $i++) { - my $line= $vt->row_plaintext($i); - next if !defined ($line) ; #|| $line =~ /^\s*$/; - $line =~ s/\s*$//; - $line .= "\n" unless $line =~ /^\s*$/; - $last_cl{"output"} .= $line; - } - } - else { - $last_cl{"output"}= ""; - } - - $vt->reset(); - - - # Classifying the command line - - - # Save - if (!$Config{"lab"} || $cl{"lab"} eq $Config{"lab"}) { - # Changing encoding - for (keys %last_cl) { - next if /raw/; - $last_cl{$_} = $converter->convert($last_cl{$_}) - if ($Config{"encoding"} && - $Config{"encoding"} !~ /^utf-8$/i); - } - push @Command_Lines, \%last_cl; - - # Сохранение позиции в файле, до которой выполнен - # успешный разбор - $Script_Files{$file}->{tell} = $last_cl{raw_end}; - } - next; - } - $last_output_length+=length($_); - #if (!$cl{"suppress_output"} || $last_output_length < 5000) { - if ($last_output_length < 50000) { - #print "(",length($_),")" if (length($_) > 2000) ; - $vt->process("$_"."\n") - } - else - { - if (!$skip_info) { - print "($cl{last_command})"; - $skip_info = 1; - } - } - } - close(FILE); - - } - if ($Config{"verbose"} =~ /y/) { - print "...finished." ; - print "Lines loaded: $commandlines_processed\n"; - print "Command lines: $commandlines_loaded\n"; - } + } + if ($Config{"verbose"} =~ /y/) { + print "...finished." ; + print "Lines loaded: $commandlines_processed\n"; + print "Command lines: $commandlines_loaded\n"; + } } + +sub sort_command_lines +{ + print "Sorting command lines...\n" if $Config{"verbose"} =~ /y/; + + # Sort Command_Lines + # Write Command_Lines to Command_Lines_Index + + my @index; + for (my $i=0;$i<=$#Command_Lines;$i++) { + $index[$i]=$i; + } + + @Command_Lines_Index = sort { + $Command_Lines[$index[$a]]->{"day"} cmp $Command_Lines[$index[$b]]->{"day"} || + $Command_Lines[$index[$a]]->{"hour"} <=> $Command_Lines[$index[$b]]->{"hour"} || + $Command_Lines[$index[$a]]->{"min"} <=> $Command_Lines[$index[$b]]->{"min"} || + $Command_Lines[$index[$a]]->{"sec"} <=> $Command_Lines[$index[$b]]->{"sec"} + } @index; + + print "...finished\n" if $Config{"verbose"} =~ /y/; + +} + sub printq { - my $TO = shift; - my $text = join "", @_; - $text =~ s/&/&/g; - $text =~ s//>/g; - print $TO $text; -} - - -sub sort_command_lines -{ - print "Sorting command lines...\n" if $Config{"verbose"} =~ /y/; - - # Sort Command_Lines - # Write Command_Lines to Command_Lines_Index - - my @index; - for (my $i=0;$i<=$#Command_Lines;$i++) { - $index[$i]=$i; - } - - @Command_Lines_Index = sort { - $Command_Lines[$index[$a]]->{"day"} cmp $Command_Lines[$index[$b]]->{"day"} || - $Command_Lines[$index[$a]]->{"hour"} <=> $Command_Lines[$index[$b]]->{"hour"} || - $Command_Lines[$index[$a]]->{"min"} <=> $Command_Lines[$index[$b]]->{"min"} || - $Command_Lines[$index[$a]]->{"sec"} <=> $Command_Lines[$index[$b]]->{"sec"} - } @index; - - print "...finished\n" if $Config{"verbose"} =~ /y/; - -} - -sub process_command_lines -{ - for my $i (@Command_Lines_Index) { - - my $cl = \$Command_Lines[$i]; - @{${$cl}->{"new_commands"}} =(); - @{${$cl}->{"new_files"}} =(); - $$cl->{"class"} = ""; - - if ($$cl->{"err"}) { - $$cl->{"class"}="wrong"; - $$cl->{"class"}="interrupted" - if ($$cl->{"err"} eq 130); - } - if (!$$cl->{"euid"}) { - $$cl->{"class"}.="_root"; - } - -#tab# my @tab_words=split /\s+/, $$cl->{"output"}; -#tab# my $last_word= $$cl->{"cline"} =~ /(\S*)$/; -#tab# $last_word =~ s@.*/@@; -#tab# my $this_is_tab=1; -#tab# -#tab# if ($last_word && @tab_words >2) { -#tab# for my $tab_words (@tab_words) { -#tab# if ($tab_words !~ /^$last_word/) { -#tab# $this_is_tab=0; -#tab# last; -#tab# } -#tab# } -#tab# } -#tab# $$cl->{"class"}="tab" if $this_is_tab; - - - if ( !$$cl->{"err"}) { - # Command does not contain mistakes - - my %commands = extract_from_cline("commands", ${$cl}->{"cline"}); - my %files = extract_from_cline("files", ${$cl}->{"cline"}); - - # Searching for new commands only - for my $command (keys %commands) { - if (!defined $Commands_Stat{$command}) { - push @{$$cl->{new_commands}}, $command; - } - $Commands_Stat{$command}++; - } - - for my $file (keys %files) { - if (!defined $Files_Stat{$file}) { - push @{$$cl->{new_files}}, $file; - } - $Files_Stat{$file}++; - } - } - - #if ($$cl->{cline}=~ /#\^(.*)/) { - # my $j=$i-1; - # $j-- while ($j >=0 && $Command_Lines[$j]->{tty} ne $$cl->{tty}); - # $Command_Lines[$j]->{note_title}="Замечание"; - # $Command_Lines[$j]->{note}="$1"; - #} - } - + my $TO = shift; + my $text = join "", @_; + $text =~ s/&/&/g; + $text =~ s//>/g; + print $TO $text; } @@ -712,218 +455,190 @@ Вывести результат обработки журнала. =cut - sub print_command_lines { - my $output_filename=$_[0]; - my $mode = ">"; - $mode =">>" if $Config{mode} eq "daemon"; - open(OUT, $mode, $output_filename) - or die "Can't open $output_filename for writing\n"; + my $output_filename=$_[0]; + my $mode = ">"; + $mode =">>" if $Config{mode} eq "daemon"; + open(OUT, $mode, $output_filename) + or die "Can't open $output_filename for writing\n"; + my $cl; + my $in_range=0; + for my $i (@Command_Lines_Index) { + $cl = $Command_Lines[$i]; - #print OUT "\n"; + if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) { + $in_range=1; + next; + } + if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) { + $in_range=0; + next; + } + next if ($Config{"from"} && $Config{"to"} && !$in_range) + || + ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) + || + ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) + || + ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); + + # Вырезаем из вывода только нужное количество строк - my $cl; - my $in_range=0; - for my $i (@Command_Lines_Index) { - $cl = $Command_Lines[$i]; + my $output=""; + if ($Config{"head_lines"} || $Config{"tail_lines"}) { + # Partialy output + my @lines = split '\n', $cl->{"output"}; + # head + my $mark=1; + for (my $i=0; $i<= $#lines && $i < $Config{"cache_head_lines"}; $i++) { + $output .= $lines[$i]."\n"; + } + # tail + my $start=$#lines-$Config{"cache_tail_lines"}+1; + if ($start < 0) { + $start=0; + $mark=0; + } + if ($start < $Config{"cache_head_lines"}) { + $start=$Config{"cache_head_lines"}; + $mark=0; + } + $output .= $Config{"skip_text"}."\n" if $mark; + for (my $i=$start; $i<= $#lines; $i++) { + $output .= $lines[$i]."\n"; + } + } + else { + # Full output + $output .= $cl->{"output"}; + } - if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) { - $in_range=1; - next; - } - if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) { - $in_range=0; - next; - } - next if ($Config{"from"} && $Config{"to"} && !$in_range) - || - ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) - || - ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) - || - ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); - - my @new_commands=@{$cl->{"new_commands"}}; - my @new_files=@{$cl->{"new_files"}}; + # Совместимость с labmaker - my $cl_class="cline"; - my $out_class="output"; - if ($cl->{"class"}) { - $cl_class = $cl->{"class"}."_".$cl_class; - $out_class = $cl->{"class"}."_".$out_class; - } + # Переводим в секунды Эпохи + # В labmaker'е данные хранились в неудобной форме: hour, min, sec, day of year + # Информация о годе отсутствовала + # Её можно внести: + # Декабрь 2004 год; остальные -- 2005 год. - # Вырезаем из вывода только нужное количество строк + my $year = 2005; + #$year = 2004 if ( $cl->{day} > 330 ); + $year = $Config{year} if $Config{year}; + # timelocal( $sec, $min, $hour, $mday,$mon,$year); + $cl->{time} = timelocal_nocheck($cl->{sec},$cl->{min},$cl->{hour},$cl->{day},0,$year); - my $output=""; - if ($Config{"head_lines"} || $Config{"tail_lines"}) { - # Partialy output - my @lines = split '\n', $cl->{"output"}; - # head - my $mark=1; - for (my $i=0; $i<= $#lines && $i < $Config{"cache_head_lines"}; $i++) { - $output .= $lines[$i]."\n"; - } - # tail - my $start=$#lines-$Config{"cache_tail_lines"}+1; - if ($start < 0) { - $start=0; - $mark=0; - } - if ($start < $Config{"cache_head_lines"}) { - $start=$Config{"cache_head_lines"}; - $mark=0; - } - $output .= $Config{"skip_text"}."\n" if $mark; - for (my $i=$start; $i<= $#lines; $i++) { - $output .= $lines[$i]."\n"; - } - } - else { - # Full output - $output .= $cl->{"output"}; - } - #$output .= "^C\n" if ($cl->{"err"} eq "130"); + # Начинаем вывод команды + print OUT "\n"; + for my $element (qw( + local_session_id + time + raw_start + raw_output_start + raw_end + raw_file + tty + uid + err + last_command + )) { + next unless $cl->{"$element"}; + print OUT "<$element>".$cl->{$element}."\n"; + } + for my $element (qw( + prompt + cline + note + note_title + )) { + next unless $cl->{"$element"}; + print OUT "<$element>"; + printq(\*OUT,$cl->{"$element"}); + print OUT "\n"; + } + print OUT ""; + printq(\*OUT,$output); + print OUT "\n"; + if ($cl->{"diff"}) { + print OUT ""; + printq(\*OUT,${$Diffs{$cl->{"diff"}}}{"text"}); + print OUT "\n"; + } + print OUT "\n"; - # Совместимость с labmaker + } - # Переводим в секунды Эпохи - # В labmaker'е данные хранились в неудобной форме: hour, min, sec, day of year - # Информация о годе отсутствовала - # Её можно внести: - # Декабрь 2004 год; остальные -- 2005 год. - - my $year = 2005; - #$year = 2004 if ( $cl->{day} > 330 ); - $year = $Config{year} if $Config{year}; - # timelocal( $sec, $min, $hour, $mday,$mon,$year); - $cl->{time} = timelocal_nocheck($cl->{sec},$cl->{min},$cl->{hour},$cl->{day},0,$year); - - - # Начинаем вывод команды - print OUT "\n"; - print OUT "",$cl->{local_session_id},"\n"; - print OUT "\n"; - print OUT "",$cl->{raw_start},"\n"; - print OUT "",$cl->{raw_output_start},"\n"; - print OUT "",$cl->{raw_end},"\n"; - print OUT "",$cl->{raw_file},"\n"; - print OUT "",$cl->{tty},"\n"; - print OUT "",$cl->{uid},"\n"; - print OUT "",$out_class,"\n"; - print OUT "",$cl->{err},"\n"; - print OUT ""; - printq(\*OUT,,$cl->{"prompt"}); - print OUT ""; - print OUT ""; - printq(\*OUT,$cl->{"cline"}); - print OUT "\n"; - print OUT "",$cl->{"last_command"},"\n"; - if (@new_commands) { - print OUT ""; - printq(\*OUT, join (" ", @new_commands)); - print OUT ""; - } - if (@new_files) { - print OUT ""; - printq(\*OUT, join (" ", @new_files)); - print OUT ""; - } - print OUT ""; - printq(\*OUT,$output); - print OUT "\n"; - if ($cl->{"diff"}) { - print OUT ""; - printq(\*OUT,${$Diffs{$cl->{"diff"}}}{"text"}); - print OUT "\n"; - } - if ($cl->{"note"}) { - print OUT ""; - printq(\*OUT,$cl->{"note"}); - print OUT "\n"; - } - if ($cl->{"note_title"}) { - print OUT ""; - printq(\*OUT,$cl->{"note_title"}); - print OUT "\n"; - } - print OUT "\n"; - - } - - #print OUT "\n"; - close(OUT); + close(OUT); } sub print_session { - my $output_filename = $_[0]; - my $local_session_id = $_[1]; - return if not defined($Sessions{$local_session_id}); + my $output_filename = $_[0]; + my $local_session_id = $_[1]; + return if not defined($Sessions{$local_session_id}); - open(OUT, ">>", $output_filename) - or die "Can't open $output_filename for writing\n"; - print OUT "\n"; - my %session = %{$Sessions{$local_session_id}}; - for my $key (keys %session) { - print OUT "<$key>".$session{$key}."\n" - } - print OUT "\n"; - close(OUT); + open(OUT, ">>", $output_filename) + or die "Can't open $output_filename for writing\n"; + print OUT "\n"; + my %session = %{$Sessions{$local_session_id}}; + for my $key (keys %session) { + print OUT "<$key>".$session{$key}."\n" + } + print OUT "\n"; + close(OUT); } sub send_cache { - # Если в кэше что-то накопилось, - # попытаемся отправить это на сервер - # - my $cache_was_sent=0; - - if (open(CACHE, $Config{cache})) { - local $/; - my $cache = ; - close(CACHE); + # Если в кэше что-то накопилось, + # попытаемся отправить это на сервер + # + my $cache_was_sent=0; + + if (open(CACHE, $Config{cache})) { + local $/; + my $cache = ; + close(CACHE); - my $socket = IO::Socket::INET->new( - PeerAddr => $Config{backend_address}, - PeerPort => $Config{backend_port}, - proto => "tcp", - Type => SOCK_STREAM - ); + my $socket = IO::Socket::INET->new( + PeerAddr => $Config{backend_address}, + PeerPort => $Config{backend_port}, + proto => "tcp", + Type => SOCK_STREAM + ); - if ($socket) { - print $socket $cache; - close($socket); - $cache_was_sent = 1; - } - } - return $cache_was_sent; + if ($socket) { + print $socket $cache; + close($socket); + $cache_was_sent = 1; + } + } + return $cache_was_sent; } sub save_cache_stat { - open (CACHE, ">$Config{cache_stat}"); - for my $f (keys %Script_Files) { - print CACHE "$f\t",$Script_Files{$f}->{size},"\t",$Script_Files{$f}->{tell},"\n"; - } - close(CACHE); + open (CACHE, ">$Config{cache_stat}"); + for my $f (keys %Script_Files) { + print CACHE "$f\t",$Script_Files{$f}->{size},"\t",$Script_Files{$f}->{tell},"\n"; + } + close(CACHE); } sub load_cache_stat { - if (open (CACHE, "$Config{cache_stat}")) { - while() { - chomp; - my ($f, $size, $tell) = split /\t/; - $Script_Files{$f}->{size} = $size; - $Script_Files{$f}->{tell} = $tell; - } - close(CACHE); - }; + if (open (CACHE, "$Config{cache_stat}")) { + while() { + chomp; + my ($f, $size, $tell) = split /\t/; + $Script_Files{$f}->{size} = $size; + $Script_Files{$f}->{tell} = $tell; + } + close(CACHE); + }; } @@ -931,102 +646,102 @@ sub process_was_killed { - $Killed = 1; + $Killed = 1; } sub main { - $| = 1; + $| = 1; - init_variables(); - init_config(); + init_variables(); + init_config(); - if ($Config{"mode"} ne "daemon") { + if ($Config{"mode"} ne "daemon") { =cut - В нормальном режиме работы нужно - считать скрипты, обработать их и записать - результат выполнения в результриующий файл. - После этого завершить работу. + В нормальном режиме работы нужно + считать скрипты, обработать их и записать + результат выполнения в результирующий файл. + После этого завершить работу. =cut - for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { - load_diff_files($lab_log); - } - load_command_lines($Config{"input"}, $Config{"input_mask"}); - sort_command_lines; - process_command_lines; - print_command_lines($Config{"cache"}); - } - else { - if (open(PIDFILE, $Config{agent_pidfile})) { - my $pid = ; - close(PIDFILE); - if ($^O eq 'linux' && $pid &&(! -e "/proc/$pid" || !`grep $Config{"l3-agent"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`)) { - print "Removing stale pidfile\n"; - unlink $Config{agent_pidfile} - or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; - } - elsif ($^O eq 'freebsd' && $pid && `ps axo uid,pid,command | grep '$<\\s*$pid\\s*$Config{"l3-agent"}' 2> /dev/null`) { - print "Removing stale pidfile\n"; - unlink $Config{agent_pidfile} - or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; - } - elsif ($^O eq 'linux' || $^O eq 'freebsd' ) { - print "l3-agent is already running: pid=$pid; pidfile=$Config{agent_pidfile}\n"; - exit(0); - } - else { - print "Unknown operating system"; - exit(0); - } - } - if ($Config{detach} =~ /^y/i) { - #$Config{verbose} = "no"; - my $pid = fork; - exit if $pid; - die "Couldn't fork: $!" unless defined ($pid); + for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { + load_diff_files($lab_log); + } + load_command_lines($Config{"input"}, $Config{"input_mask"}); + sort_command_lines; + #process_command_lines; + print_command_lines($Config{"cache"}); + } + else { + if (open(PIDFILE, $Config{agent_pidfile})) { + my $pid = ; + close(PIDFILE); + if ($^O eq 'linux' && $pid &&(! -e "/proc/$pid" || !`grep $Config{"l3-agent"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`)) { + print "Removing stale pidfile\n"; + unlink $Config{agent_pidfile} + or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; + } + elsif ($^O eq 'freebsd' && $pid && `ps axo uid,pid,command | grep '$<\\s*$pid\\s*$Config{"l3-agent"}' 2> /dev/null`) { + print "Removing stale pidfile\n"; + unlink $Config{agent_pidfile} + or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!"; + } + elsif ($^O eq 'linux' || $^O eq 'freebsd' ) { + print "l3-agent is already running: pid=$pid; pidfile=$Config{agent_pidfile}\n"; + exit(0); + } + else { + print "Unknown operating system"; + exit(0); + } + } + if ($Config{detach} =~ /^y/i) { + #$Config{verbose} = "no"; + my $pid = fork; + exit if $pid; + die "Couldn't fork: $!" unless defined ($pid); - open(PIDFILE, ">", $Config{agent_pidfile}) - or die "Can't open pidfile ". $Config{agent_pidfile}. " for wrting: $!"; - print PIDFILE $$; - close(PIDFILE); + open(PIDFILE, ">", $Config{agent_pidfile}) + or die "Can't open pidfile ". $Config{agent_pidfile}. " for wrting: $!"; + print PIDFILE $$; + close(PIDFILE); - for my $handle (*STDIN, *STDOUT, *STDERR) { - open ($handle, "+<", "/dev/null") - or die "can't reopen $handle to /dev/null: $!" - } + for my $handle (*STDIN, *STDOUT, *STDERR) { + open ($handle, "+<", "/dev/null") + or die "can't reopen $handle to /dev/null: $!" + } - POSIX::setsid() - or die "Can't start a new session: $!"; + POSIX::setsid() + or die "Can't start a new session: $!"; - $0 = $Config{"l3-agent"}; - - $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed; - } - while (not $Killed) { - @Command_Lines = (); - @Command_Lines_Index = (); - for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { - load_diff_files($lab_log); - } - load_cache_stat(); - load_command_lines($Config{"input"}, $Config{"input_mask"}); - if (@Command_Lines) { - sort_command_lines; - process_command_lines; - print_command_lines($Config{"cache"}); - } - save_cache_stat(); - if (-e $Config{cache} && (stat($Config{cache}))[7]) { - send_cache() && unlink($Config{cache}); - } - sleep($Config{"daemon_sleep_interval"} || 1); - } - - unlink $Config{agent_pidfile}; - } + $0 = $Config{"l3-agent"}; + + $SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed; + } + while (not $Killed) { + @Command_Lines = (); + @Command_Lines_Index = (); + for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) { + load_diff_files($lab_log); + } + load_cache_stat(); + load_command_lines($Config{"input"}, $Config{"input_mask"}); + if (@Command_Lines) { + sort_command_lines; + process_command_lines; + print_command_lines($Config{"cache"}); + } + save_cache_stat(); + if (-e $Config{cache} && (stat($Config{cache}))[7]) { + send_cache() && unlink($Config{cache}); + } + sleep($Config{"daemon_sleep_interval"} || 1); + } + + unlink $Config{agent_pidfile}; + } } diff -r 440d12c122d5 -r c4bea959dbb1 l3-frontend --- a/l3-frontend Sat Jan 21 19:09:34 2006 +0200 +++ b/l3-frontend Thu Jan 26 00:00:53 2006 +0200 @@ -771,7 +771,22 @@ -

Журнал лабораторных работ

+ + + + + + + + +

Журнал лабораторных работ

HEADER if ( $course_student || $course_trainer