lilalo
changeset 0:18b21f6918f0
Initial revision
author | devi |
---|---|
date | Sun May 22 16:29:55 2005 +0300 (2005-05-22) |
parents | |
children | ff93ad94d73b 787e9f11de51 |
files | .lm.swo .lm.swp .tarball FILES INSTALL README TODO labmaker.conf lm lm-install lm-report lm-ssh share/freebsd.ico share/google.ico share/labmaker.css share/opennet.ico share/ug.xsl taillast.pl ug2db |
line diff
1.1 Binary file .lm.swo has changed
2.1 Binary file .lm.swp has changed
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/.tarball Sun May 22 16:29:55 2005 +0300 3.3 @@ -0,0 +1,11 @@ 3.4 +INSTALL 3.5 +lm-install 3.6 +lm-report 3.7 +lm-report.conf 3.8 +Makefile 3.9 +.tarball 3.10 +freebsd.ico 3.11 +google.ico 3.12 +opennet.ico 3.13 +labmaker.css 3.14 +
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/FILES Sun May 22 16:29:55 2005 +0300 4.3 @@ -0,0 +1,26 @@ 4.4 +lm - labmaker's frontend 4.5 + Отвечает за инсталляцию lm-агшентов, сбор данных для журналов, 4.6 + вызов lm-report для генерирования журналов и т.д. 4.7 + 4.8 +lm-install - инсталлирует labmaker на машину. 4.9 + Должен вызываться для тех пользователей, где необходимо вести запись 4.10 + журналов действий 4.11 + 4.12 +lm-report - генератор отчётов labmaker 4.13 + 4.14 +lm-ssh - expect-скрипт, предназначенный для автоматический инсталляции 4.15 + labmaker на удалённую машину посредством ssh. Автоматически 4.16 + вводит пароль и отвечает 'yes' на вопрос об открытх ключах 4.17 + хоста 4.18 + 4.19 +taillast.pl - показать хвост последнего изменённого журнала lm 4.20 +ug2db - сконвертировать из UG Labmaker XML в DocBook XML 4.21 + 4.22 +labmaker.conf - конфигурационный файл программ lm и lm-report 4.23 +share/ - файлы иконок, картинок, стилей 4.24 + 4.25 +FILES - список файлов в дистрибутиве LabMaker 4.26 +INSTALL - описание процедуры инсталляции 4.27 +README - информация о программе 4.28 +TODO - список вещей, которые нужно сделать 4.29 +
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/INSTALL Sun May 22 16:29:55 2005 +0300 5.3 @@ -0,0 +1,9 @@ 5.4 +Инсталляция LabMaker 5.5 + 5.6 +1. Проинсталлировать все необходимые модули Perl 5.7 +2. Выполнить lm-install, указав в качестве параметров 5.8 + имена домашних каталогов пользователей, для которых 5.9 + должны вестись журналы 5.10 +3. Использовать lm-report для генерирования журналов 5.11 + 5.12 +
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/TODO Sun May 22 16:29:55 2005 +0300 6.3 @@ -0,0 +1,42 @@ 6.4 +TODO LIST 6.5 + 6.6 +lm-report: 6.7 + 6.8 +general: Отметка фрагментов + якоря из командной строки 6.9 + 6.10 +user: Поддержка su и sudo 6.11 +diff: FIX не показывать плавающий бокс 6.12 +фрагменты: отмечать фрагменты для комментирования 6.13 +html: управление деталями 6.14 +html: навести порядок в css 6.15 + 6.16 +web: индекс активности 6.17 +web: централизованный доступ 6.18 +web: периодическое обновление 6.19 +web: информация о лабе 6.20 + 6.21 + 6.22 + 6.23 +lm: 6.24 + ls [[user@]host] 6.25 + list [[user@]host] 6.26 + показывает список ведщихся журналов 6.27 + cat журнал 6.28 + show журнал 6.29 + показывает заданный журнал 6.30 + 6.31 + <журнал> указывается в форме console@host 6.32 + 6.33 + 6.34 + save host 6.35 + сохраняет журналы указанной машины 6.36 + 6.37 + 6.38 + do выполнение команды 6.39 + + стандартный набор команд (в т.ч. инсталляция) 6.40 + 6.41 +DONE 6.42 + 6.43 +xml: поддержка формата xml 6.44 +html: заполлзающие блоки (ИСКЛЮЧЕНО) 6.45 +general: Конфигурация через файл и командную строку
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/labmaker.conf Sun May 22 16:29:55 2005 +0300 7.3 @@ -0,0 +1,4 @@ 7.4 +## Specify configurable parameters here 7.5 +## in form 7.6 +## variable = value 7.7 +#terminal_width=100
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/lm Sun May 22 16:29:55 2005 +0300 8.3 @@ -0,0 +1,494 @@ 8.4 +#!/usr/bin/perl 8.5 + 8.6 + 8.7 +use strict; 8.8 +use Inline::Files; 8.9 +use Data::Dumper; 8.10 +use Switch; 8.11 +use XML::Simple; 8.12 +use Getopt::Long; 8.13 + 8.14 +our $XMLClass; 8.15 +our $XMLCourse; 8.16 +our @Labs; 8.17 + 8.18 +our %Machines; # Machines list from class.xml 8.19 +our @SelectedMachines; # Machines list given as the command line argument 8.20 + 8.21 +our $Config_File = "labmaker.conf"; 8.22 +our %Config = ( 8.23 + "show_host" => "no", 8.24 + 8.25 + # Каталоги 8.26 + "path_labmaker" => "/var/labmaker/", 8.27 + "path_classes" => "/var/labmaker/classes/", 8.28 + "lablogs_path" => "/var/labmaker/lablogs/", 8.29 + "courses_path" => "/var/labmaker/courses/", 8.30 + "outpath" => "/var/labmaker/out/", 8.31 + 8.32 + # Файлы 8.33 + "runfile" => "lm.run", 8.34 + "logfile" => "lm.log", 8.35 + 8.36 + "class" => "class", # Имя файла класса 8.37 + "class_suffix" => ".xml", # Cуффикс файла класса 8.38 + 8.39 + "sshkey" => "$ENV{HOME}/.ssh/id_dsa.pub", 8.40 + "lmssh" => "./lm-ssh", 8.41 + "lminstall" => "./lm-install", 8.42 + "ssh_user" => "r", 8.43 +); 8.44 + 8.45 +our %Run = ( 8.46 + "lab" => "" 8.47 +); 8.48 + 8.49 +our %Scripts; 8.50 + 8.51 +sub load_class; 8.52 +sub load_config; 8.53 +sub load_course; 8.54 +sub load_scripts; 8.55 + 8.56 +sub lm_next; 8.57 +sub lm_prev; 8.58 +sub lm_start; 8.59 +sub lm_stop; 8.60 +sub lm_set; 8.61 +sub lm_do; 8.62 +sub lm_report; 8.63 +sub lm_show_hosts; 8.64 +sub lm_show_labs; 8.65 + 8.66 +sub load_run; 8.67 +sub save_run; 8.68 +sub print_log; 8.69 +sub print_usage_info; 8.70 +sub main(); 8.71 + 8.72 +main(); 8.73 + 8.74 +sub main() 8.75 +{ 8.76 + binmode STDOUT, ":utf8"; 8.77 + 8.78 + if (! @ARGV) { 8.79 + print_usage_info(); 8.80 + exit(0); 8.81 + } 8.82 + 8.83 + load_config; 8.84 + load_run; 8.85 + load_scripts; 8.86 + load_class; 8.87 + load_course; 8.88 + 8.89 + my $arg = join " ", @ARGV; 8.90 + 8.91 + # Getting @SelectedMachines if any 8.92 + if ($arg =~ s/@(.*?)\s//) { 8.93 + my $machines = $1; 8.94 + my @list = split /,/, $machines; 8.95 + for my $interval (@list) { 8.96 + my ($first, $last) = split /-/, $interval; 8.97 + 8.98 + push @SelectedMachines, $first; 8.99 + while ($first < $last) { 8.100 + push @SelectedMachines, ++$first; 8.101 + } 8.102 + } 8.103 + } 8.104 + 8.105 + # Choose command to do 8.106 + switch ($arg) { 8.107 + case "next" { lm_next } 8.108 + case "prev" { lm_prev } 8.109 + case /set / { $arg =~ /set (.*)/; lm_set $1 } 8.110 + case "report" { lm_report } 8.111 + case "start" { lm_start } 8.112 + case "stop" { lm_stop } 8.113 + case "show hosts" { lm_show_hosts } 8.114 + case "show labs" { lm_show_labs } 8.115 + case /do / { $arg =~ /do (.*)/; lm_do "$1" } 8.116 + else { print_usage_info() } 8.117 + } 8.118 + save_run; 8.119 + exit(0); 8.120 +} 8.121 + 8.122 +sub load_scripts 8.123 +{ 8.124 + local $/; 8.125 + $_=<SCRIPTS>; 8.126 + %Scripts = ("empty-element", split (/###(.*)\n/)); 8.127 + delete($Scripts{"empty-element"}); 8.128 +} 8.129 + 8.130 +sub load_config 8.131 +{ 8.132 + my %file_config; 8.133 + my %argv_config; 8.134 + #read_config_file(\%file_config, $Config_File); 8.135 + GetOptions(\%argv_config, map "$_=s", keys %Config); 8.136 + %Config = (%Config, %file_config, %argv_config); 8.137 +} 8.138 + 8.139 +sub load_course 8.140 +{ 8.141 + $XMLCourse = XMLin($Config{"courses_path"}.$XMLClass->{"course"}.".xml", ForceArray => 1 ) 8.142 + or die "Can't open file of the course ",$XMLClass->{"course"}," [with .xml extension]\n"; 8.143 +# print Dumper($XMLCourse); 8.144 + for my $lab (@{$XMLCourse->{"module"}}) { 8.145 + push @Labs, $lab->{"code"}; 8.146 + } 8.147 +} 8.148 + 8.149 +sub load_class 8.150 +{ 8.151 + my $classfile = 8.152 + $Config{"path_classes"}."/".$Config{"class"}.$Config{"class_suffix"}; 8.153 + $XMLClass = XMLin($classfile , ForceArray => [ 'student' ] ) 8.154 + or die "Can't open file of the class ",$classfile,"\n"; 8.155 + 8.156 + for my $student (@{$XMLClass->{"student"}}) { 8.157 + $Machines{$student->{"host"}} = { 8.158 + "name" => "$student->{firstname} $student->{surname}", 8.159 + "user" => "$student->{user}", 8.160 + "student" => $student, 8.161 + } 8.162 + } 8.163 +# print Dumper($XMLClass); 8.164 +# print Dumper(\%Machines); 8.165 +} 8.166 + 8.167 + 8.168 +sub lm_next 8.169 +{ 8.170 + for(my $i=0; $i<=$#Labs; $i++){ 8.171 + if ( $Labs[$i] eq $Run{"lab"} ) { 8.172 + if ($i < $#Labs) { 8.173 + lm_set($Labs[$i+1]); 8.174 + return ; 8.175 + } else { 8.176 + die "Lab ", $Run{"lab"}, " is the last. Switch to next lab is impossible" 8.177 + } 8.178 + } 8.179 + 8.180 + } 8.181 + die "Lab ", $Run{"lab"}, " not found. Don't know which is next" 8.182 +} 8.183 + 8.184 +sub lm_prev 8.185 +# Switch to previous lab 8.186 +{ 8.187 + for(my $i=0; $i<=$#Labs; $i++){ 8.188 + if ( $Labs[$i] eq $Run{"lab"} ) { 8.189 + if ($i > 0) { 8.190 + lm_set($Labs[$i-1]); 8.191 + return ; 8.192 + } else { 8.193 + die "Lab ", $Run{"lab"}, " is the first. Switch to previous lab is impossible" 8.194 + } 8.195 + } 8.196 + 8.197 + } 8.198 + die "Lab ", $Run{"lab"}, " not found. Don't know which is previous" 8.199 +} 8.200 + 8.201 +sub lm_set 8.202 +# Switch to $_[0] lab 8.203 +# FIXME 8.204 +{ 8.205 + my $lab = shift; 8.206 + print "Current lab is $lab\n"; 8.207 + $Run{"lab"} = "$lab"; 8.208 + lm_do "setlab", $lab; 8.209 +} 8.210 + 8.211 + 8.212 +sub lm_start 8.213 +# Start new training day 8.214 +{ 8.215 + print_log(`date`." STARTED\n"); 8.216 + if ($Run{"lab"}) { 8.217 + lm_next; 8.218 + } 8.219 + else 8.220 + { 8.221 + # First lab in the course 8.222 + lm_set($Labs[0]); 8.223 + } 8.224 +} 8.225 + 8.226 +sub lm_stop 8.227 +# Stop this training day 8.228 +{ 8.229 + print_log(`date`." STOPPED\n"); 8.230 +} 8.231 + 8.232 + 8.233 +sub lm_show_hosts 8.234 +# Show hosts used to run a commands 8.235 +{ 8.236 + my $i=1; 8.237 + for my $m (sort keys %Machines) { 8.238 + if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) { 8.239 + print "($i)","\t",$m,"\t",$Machines{$m}->{"name"},"\n"; 8.240 + } 8.241 + $i++; 8.242 + } 8.243 +} 8.244 + 8.245 +sub lm_show_labs 8.246 +# Show hosts used to run a commands 8.247 +{ 8.248 + my $i=1; 8.249 + for my $lab (@Labs) { 8.250 + print $lab; 8.251 + print "*" if $lab eq $Run{"lab"}; 8.252 + print "\n"; 8.253 + } 8.254 +} 8.255 + 8.256 +sub lm_do 8.257 +# Do the $_[0] command on all of the hosts 8.258 +{ 8.259 + my $command = shift; 8.260 + my $arg = join " ", @_; 8.261 + my $i=1; 8.262 + for my $m (sort keys %Machines) { 8.263 + if (!@SelectedMachines || grep $_ eq $i, @SelectedMachines) { 8.264 + print "$m:\n" if $Config{"show_host"} =~ /y/i; 8.265 + 8.266 + my %myenv = ( %Config, 8.267 + host => $m, 8.268 + dirs => "/root /home/".$Machines{$m}->{"user"}, 8.269 + lablogs => $Config{"lablogs_path"}."/". 8.270 + $XMLClass->{"course"}."/". 8.271 + $XMLClass->{"date"}."/". 8.272 + "$m", 8.273 + lab => $arg, 8.274 + 8.275 + email => $Machines{$m}->{"student"}->{"email"}, 8.276 + company => $Machines{$m}->{"student"}->{"company"}, 8.277 + center => $XMLClass->{"center"}, 8.278 + course => $XMLClass->{"course"}, 8.279 + date => $XMLClass->{"date"}, 8.280 + name => $Machines{$m}->{"name"}, 8.281 + coursepath => $XMLCourse->{"path"}, 8.282 + 8.283 + ); 8.284 + if (grep { $_ eq $command} keys %Scripts) { 8.285 + $_=$Scripts{"$command"}; 8.286 + s/\$(\w+)/$myenv{$1}/ge; 8.287 + open(SHELL, "|/bin/sh -s"); 8.288 + binmode SHELL, ":utf8"; 8.289 + print SHELL $_; 8.290 + close (SHELL); 8.291 + } 8.292 + else { 8.293 + my $res = `ssh $Config{"ssh_user"}\@$m $command`; 8.294 + if ($res) { 8.295 + my $count = ($res =~ s/(^)/$m: /mg); 8.296 + print $res; 8.297 + print "\n" if ($count > 1); 8.298 + } 8.299 + } 8.300 + } 8.301 + $i++; 8.302 + } 8.303 +} 8.304 + 8.305 + 8.306 +sub lm_report 8.307 +{ 8.308 + 8.309 + print "Not implemented yet\n"; 8.310 + exit(1); 8.311 + 8.312 +=cut comment 8.313 + 8.314 +Дальше идут скрипты, код которых нужно реализовать здесь. 8.315 +Как минимум. 8.316 + 8.317 +=cut 8.318 + 8.319 + my $lm_script_make_report_web = <<'SCRIPT'; 8.320 + 8.321 +#!/bin/sh 8.322 + 8.323 +####cd /home/devi/lm 8.324 +./lm do copy-lablogs 8.325 +##./lm-report --input /home/murk/.labmaker --output /var/www/lm/murk.html 8.326 +##exit 8.327 + 8.328 +COURSE=ug-h 8.329 +DATE=2005-04-25 8.330 +SUFF=".linux.nt" 8.331 +#MACHINES="m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15" 8.332 +#MACHINES="m1 m2 m3 m4 m5 m6 m7 f1 f2 f3 f4 f5" 8.333 +MACHINES="m01 m02 m03 m04 m05 m06 m07 m08" 8.334 +#MACHINES="m1" 8.335 +USERS="user root" 8.336 +WEBDIR=/var/www/lm 8.337 + 8.338 +for u in $USERS 8.339 + do 8.340 + for m in $MACHINES 8.341 + do 8.342 + e=utf-8 8.343 + [ "${m##f}" = "$m" ] || e=koi8-r 8.344 + #e=koi8-r 8.345 + mkdir -p $WEBDIR/$DATE/$m 8.346 + cp share/*.ico share/*.css $WEBDIR/$m 8.347 + #echo Processing Lablogs/$COURSE/$DATE/$m$SUFF/$u/ 8.348 + ./lm-report\ 8.349 + --input Lablogs/$COURSE/$DATE/$m$SUFF/$u/ \ 8.350 + --diffs "Lablogs/$COURSE/$DATE/$m$SUFF/$u/ Lablogs/$COURSE/$DATE/$m$SUFF/root/"\ 8.351 + --output /var/www/lm/$DATE/$m/$u.html \ 8.352 + --encoding $e 8.353 + done 8.354 + done 8.355 + 8.356 + 8.357 +SCRIPT 8.358 + 8.359 + my $lm_script_make_report_all = <<'SCRIPT'; 8.360 + 8.361 +#!/bin/sh 8.362 +WEBDIR=/var/www/lm 8.363 + 8.364 +find . -type d -maxdepth 5 -mindepth 5 |\ 8.365 + while read dir 8.366 + do 8.367 + subdir=${dir##Lablogs/} 8.368 + e=utf-8 8.369 + echo $dir | grep -qi bsd && e=koi8-r 8.370 + echo $dir | grep -qi /f && e=koi8-r 8.371 + 8.372 + mkdir -p $WEBDIR/${subdir%/*} 8.373 + cp share/*.ico share/*.css $WEBDIR/${subdir%/*} 8.374 + #echo Processing Lablogs/$COURSE/$DATE/$m$SUFF/$u/ 8.375 + ./lm-report\ 8.376 + --input $dir \ 8.377 + --diffs "${dir%/user}/root $dir"\ 8.378 + --output $WEBDIR/$subdir.html \ 8.379 + --encoding $e 8.380 + done 8.381 + 8.382 +SCRIPT 8.383 +} 8.384 + 8.385 +sub load_run 8.386 +{ 8.387 + my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"}; 8.388 + open (RUN, $runfile) 8.389 + or return; 8.390 + while (<RUN>) { 8.391 + chomp; 8.392 + my ($var, $val) = split /\s+/,$_,2; 8.393 + $Run{$var}=$val; 8.394 + } 8.395 + close (RUN); 8.396 +} 8.397 + 8.398 +sub save_run 8.399 +{ 8.400 + my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"}; 8.401 + open (RN, "$runfile") 8.402 + or die "Can't save running state to $runfile"; 8.403 + for my $var (keys %Run) { 8.404 + print RN $var,"\t",$Run{$var},"\n"; 8.405 + } 8.406 + close (RN); 8.407 +} 8.408 + 8.409 +sub print_log 8.410 +{ 8.411 + my $logfile = $Config{"path_labmaker"}."/".$Config{"path_logfile"}; 8.412 + open (LOG, ">>$logfile") 8.413 + or die "Can't open logfile $logfile for writing"; 8.414 + print LOG @_; 8.415 + close (LOG); 8.416 +} 8.417 + 8.418 + 8.419 +sub print_usage_info 8.420 +{ 8.421 + print "Usage:\n\n\t$0 [host-list] command\n"; 8.422 + while (<USAGE>) { 8.423 + print $_; 8.424 + } 8.425 +} 8.426 + 8.427 +__USAGE__ 8.428 + 8.429 +Commands: 8.430 + 8.431 + next -- next lab 8.432 + prev -- prev lab 8.433 + set LAB -- set current lab to LAB 8.434 + start -- start this day training 8.435 + stop -- stop this day training 8.436 + show hosts -- show available hosts in the class 8.437 + show labs -- show available labs in the course 8.438 + do COMMAND -- do specified command on the hosts of hostlist 8.439 + report -- generate XML/HTML reports 8.440 + 8.441 + 8.442 +do commands: 8.443 + 8.444 + install [PROFILE] -- install profile 8.445 + 8.446 +Host list: 8.447 + 8.448 + @N -- machine N 8.449 + @N1-N2 -- all of the machines from N1 to N2 8.450 + @N1,N2,N3 -- machine N1, N2 and N3 8.451 + 8.452 + N* is numbers or domain names of the machines. 8.453 + 8.454 + If host list is not specified, 8.455 + command is executed on all of the machines 8.456 + 8.457 + 8.458 + 8.459 +__SCRIPTS__ 8.460 +###install 8.461 +cat $sshkey | $lmssh $ssh_user@$host /bin/sh -c '"mkdir -p ~/.ssh; cat >>~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys"' 8.462 + 8.463 +###install-lm 8.464 +cat $lminstall | ssh $ssh_user@$host /bin/sh -s $dirs 8.465 + 8.466 +###copy-lablogs 8.467 +for i in $dirs 8.468 +do 8.469 + mkdir -p $lablogs/${i##*/} 8.470 + scp -q $ssh_user@$host:${i}/.labmaker/* $lablogs/${i##*/} 8.471 +done 8.472 + 8.473 +###setlab 8.474 +for i in $dirs 8.475 +do 8.476 + echo $lab | ssh $ssh_user@$host "cat > "${i}"/.labmaker/lab" 8.477 +done 8.478 + 8.479 +###makeout 8.480 +common=$course-$date 8.481 +personal=$course-$date-$email 8.482 +mkdir -p $outpath/${common}/{Lablogs,Docs} 8.483 +mkdir -p $outpath/${personal}/{Course,Files} 8.484 +cd $outpath/${personal} 8.485 +ln -s ../${common}/Lablogs . 8.486 +ln -s ../${common}/Docs . 8.487 +cd ~- 8.488 +export UG_PERSONAL=${PWD}/$outpath/${personal}/Course 8.489 +export UG_CENTER="$center" 8.490 +export UG_COURSE="$course" 8.491 +export UG_DATE="$date" 8.492 +export UG_STUDENT="$name" 8.493 +export UG_COMPANY="$company" 8.494 +cd $coursepath; make personal; cd ~- 8.495 + 8.496 +###watch 8.497 +cat taillast.pl | ssh $ssh_user@$host perl - /root/.labmaker
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/lm-install Sun May 22 16:29:55 2005 +0300 9.3 @@ -0,0 +1,227 @@ 9.4 +#!/bin/sh 9.5 + 9.6 +# Use -d to deinstall labmaker 9.7 +# You can specify directory list to install LabMaker as command line parameters 9.8 +# or set it in $users_to_install variable 9.9 + 9.10 +# CONFIGURABLE SECTION start 9.11 +#users_to_install="/home/your-user-here /root" 9.12 +# CONFIGURABLE SECTION stop 9.13 + 9.14 +first_lab=T1 9.15 +editors_to_install='/bin/vi /usr/bin/vi /usr/bin/vim /bin/ee /usr/bin/ee /usr/bin/pico /usr/bin/nano /usr/local/bin/vim' 9.16 +temp_file=/tmp/lm-install-$$ 9.17 +arg=$@ 9.18 + 9.19 +show_usage() 9.20 +{ 9.21 + cat << USAGE 9.22 + 9.23 +$0 [-d] path... 9.24 + 9.25 + * Use -d to deinstall labmaker 9.26 + * You can specify directory list to install LabMaker as command line parameters 9.27 + or set it in \$users_to_install variable in the script 9.28 + 9.29 +Example: 9.30 + 9.31 + Command 9.32 + # $0 /root /home/user 9.33 + installs labmaker to /root and /home/user directories 9.34 + 9.35 +USAGE 9.36 +} 9.37 + 9.38 +install_to_profile() 9.39 +{ 9.40 + profile=$1 9.41 + cat $profile \ 9.42 + | sed '/LabMaker:START/,/LabMaker:END/ d' \ 9.43 + > $temp_file 9.44 + cat <<'LM_bash_profile' >> $temp_file 9.45 + # LabMaker:START 9.46 + #LMHOME=~/.labmaker 9.47 + #mkdir -p ${LMHOME} 9.48 + #TTY=`tty` 9.49 + #flush="-f" 9.50 + #exec script $flush -q $LMHOME/${TTY##*/}-$$.script 9.51 + # LabMaker:END 9.52 +LM_bash_profile 9.53 + cat $temp_file > $profile 9.54 + rm $temp_file 9.55 +} 9.56 + 9.57 +uninstall_from_profile() 9.58 +{ 9.59 + profile=$1 9.60 + cat $profile \ 9.61 + | sed '/LabMaker:START/,/LabMaker:END/ d' \ 9.62 + > $temp_file 9.63 + cat $temp_file > $profile 9.64 + rm $temp_file 9.65 +} 9.66 + 9.67 +install_to_bashrc() 9.68 +{ 9.69 + profile=$1 9.70 + cat $profile \ 9.71 + | sed '/LabMaker:START/,/LabMaker:END/ d' \ 9.72 + > $temp_file 9.73 + cat <<'LM_bash_profile' >> $temp_file 9.74 + # LabMaker:START 9.75 + TTY=`tty` 9.76 + 9.77 + this_term=`w | grep "${TTY##/dev/}" | awk '{print $8;}'` 9.78 + # freeBSD: 9.79 + this_term=`w | grep "${TTY##/dev/tty}" | awk '{print $6;}'` 9.80 + if [ -n "$this_term" ] && echo $this_term | grep -qv script 9.81 + then 9.82 + LMHOME=~/.labmaker 9.83 + mkdir -p ${LMHOME} 9.84 + flush="-f" #linux 9.85 + flush="-t 0" #freebsd 9.86 + exec script $flush -q $LMHOME/${TTY##*/}-$$.script 9.87 + fi 9.88 + PS1='\[` a="$?"; 9.89 + HIDDEN=$([ "$a" = 0 ] || echo -n ^"$a")$(echo -n _${UID}_)$(echo -n _$$_)$(date\ 9.90 + +"%j$(cat ~/.labmaker/lab 2>/dev/null) %H:%M:%S"); 9.91 + echo $HIDDEN`\033[50D\033[K\][\u@\h:\W]\$ ' 9.92 + # LabMaker:END 9.93 +LM_bash_profile 9.94 + cat $temp_file > $profile 9.95 + rm $temp_file 9.96 +} 9.97 + 9.98 +uninstall_from_bashrc() 9.99 +{ 9.100 + profile=$1 9.101 + cat $profile \ 9.102 + | sed '/LabMaker:START/,/LabMaker:END/ d' \ 9.103 + > $temp_file 9.104 + cat $temp_file > $profile 9.105 + rm $temp_file 9.106 +} 9.107 + 9.108 +install_editor() 9.109 +{ 9.110 +editor=$1 9.111 +[ -e $editor.orig ] && cp $editor.orig $editor 9.112 +cp $editor $editor.orig 9.113 +cat <<'editor_wrapper' | sed "s@EDITOR@$editor@" > $editor 9.114 +#!/bin/sh 9.115 + 9.116 +LMHOME=~/.labmaker 9.117 +if [ "${1#-}" = "$1" -a -d "$LMHOME" ] 9.118 +then 9.119 + LAB=`cat $LMHOME/lab` 9.120 + TIME="`date +%j${LAB}_%H:%M:%S`" 9.121 + DIR="" 9.122 + [ "${1#/}" = "$1" ] && DIR=$PWD/ 9.123 + DIFFNAME=$PPID_${TIME}_`echo $DIR$1| sed s@_@__@ | sed 's@/@_@g'`.diff 9.124 + tmp="/tmp/lm-saved-$$" 9.125 + touch $1 9.126 + cp -- "$1" $tmp 2> /dev/null 9.127 + EDITOR.orig "$@" || ERR=1 9.128 + diff $tmp $1 > $LMHOME/$DIFFNAME 2> /dev/null 9.129 + rm $tmp 2> /dev/null 9.130 + if [ "$ERR" = 1 ] 9.131 + then 9.132 + false 9.133 + else 9.134 + true 9.135 + fi 9.136 +else 9.137 + exec EDITOR.orig "$@" 9.138 +fi 9.139 +editor_wrapper 9.140 + 9.141 +} 9.142 + 9.143 + 9.144 +uninstall_editor() 9.145 +{ 9.146 + editor=$1 9.147 + [ -e $editor.orig ] && mv $editor.orig $editor 9.148 +} 9.149 + 9.150 +if [ "$1" != "-d" ] 9.151 +then 9.152 + # INSTALLING LM 9.153 + if [ $# -gt 0 ] 9.154 + then 9.155 + users_to_install="$*" 9.156 + fi 9.157 + 9.158 + if [ -z "$users_to_install" ] 9.159 + then 9.160 + show_usage 9.161 + exit 9.162 + fi 9.163 + 9.164 + for user in $users_to_install 9.165 + do 9.166 + home=$user # fix this! 9.167 + mkdir -p $home/.labmaker 9.168 + echo $first_lab > $home/.labmaker/lab 9.169 + chown -R ${user##*/} $home/.labmaker 9.170 + 9.171 + if [ ! -e $home/.bash_profile ] 9.172 + then 9.173 + echo '. ~/.bashrc' >> ~/.bash_profile 9.174 + fi 9.175 + [ -e $home/.bash_profile ] \ 9.176 + && install_to_profile $home/.bash_profile \ 9.177 + && echo LabMaker is installed to $home/.bash_profile 9.178 + 9.179 + [ -e $home/.profile ] && install_to_profile $home/.profile \ 9.180 + && install_to_profile $home/.profile \ 9.181 + && echo LabMaker is installed to $home/.profile 9.182 + 9.183 + touch $home/.bashrc 9.184 + [ -e $home/.bashrc ] && install_to_bashrc $home/.bashrc \ 9.185 + && install_to_bashrc $home/.bashrc \ 9.186 + && echo LabMaker is installed to $home/.bashrc 9.187 + done 9.188 + 9.189 + for editor in $editors_to_install 9.190 + do 9.191 + [ -e $editor ] \ 9.192 + && install_editor $editor \ 9.193 + && echo LabMaker is installed to $editor 9.194 + done 9.195 +else 9.196 +# UNINSTALLING LM 9.197 + shift 9.198 + users_to_install="$*" 9.199 + for user in $users_to_install 9.200 + do 9.201 + home=$user 9.202 + mkdir -p $home/.labmaker 9.203 + echo $first_lab > $home/.labmaker/lab 9.204 + chown -R ${user##*/} $home/.labmaker 9.205 + 9.206 + if [ ! -e $home/.bash_profile ] 9.207 + then 9.208 + echo '. ~/.bashrc' >> ~/.bash_profile 9.209 + fi 9.210 + [ -e $home/.bash_profile ] \ 9.211 + && uninstall_from_profile $home/.bash_profile \ 9.212 + && echo LabMaker is uninstalled from $home/.bash_profile 9.213 + 9.214 + [ -e $home/.profile ] && uninstall_from_profile $home/.profile \ 9.215 + && uninstall_from_profile $home/.profile \ 9.216 + && echo LabMaker is uninstalled from $home/.profile 9.217 + 9.218 + touch $home/.bashrc 9.219 + [ -e $home/.bashrc ] && uninstall_from_bashrc $home/.bashrc \ 9.220 + && uninstall_from_bashrc $home/.bashrc \ 9.221 + && echo LabMaker is uninstalled from $home/.bashrc 9.222 + done 9.223 + 9.224 + for editor in $editors_to_install 9.225 + do 9.226 + [ -e $editor ] \ 9.227 + && uninstall_editor $editor \ 9.228 + && echo LabMaker is uninstalled from $editor 9.229 + done 9.230 +fi
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/lm-report Sun May 22 16:29:55 2005 +0300 10.3 @@ -0,0 +1,912 @@ 10.4 +#!/usr/bin/perl -w 10.5 + 10.6 +# 10.7 +# (c) Igor Chubin, imchubin@mail.ru, 2004 10.8 +# 10.9 + 10.10 +use strict; 10.11 +use Getopt::Long; 10.12 +use Term::VT102; 10.13 +use Text::Iconv; 10.14 +use Data::Dumper; 10.15 + 10.16 +our $Config_File = "labmaker.conf"; 10.17 +our %Config = ( 10.18 + "skip_empty" => "yes", 10.19 + "skip_interrupted" => "no", 10.20 + "skip_wrong" => "no", 10.21 + "editors" => ["vi", "pico", "ee", "vim"], 10.22 + "pagers" => ["more", "less", "zmore", "zless", "info", 10.23 + "man", "mc", "trafshow", "screen", "cfdisk", 10.24 + "trafshow-bsd", "yes", "lynx", "links", "centericq" 10.25 + ], 10.26 + "terminal" => ["mc"], 10.27 + "suppress_editors" => "yes", 10.28 + "suppress_pagers" => "yes", 10.29 + "suppress_terminal" => "yes", 10.30 + 10.31 + "terminal_width" => 100, 10.32 + "terminal_height" => 100, 10.33 + "verbose" => "yes", 10.34 + 10.35 + "head_lines" => 5, 10.36 + "tail_lines" => 5, 10.37 + "skip_text" => "...", 10.38 + "show_time" => "yes", 10.39 + "show_diffs" => "yes", 10.40 + "show_comments" => "yes", 10.41 + 10.42 + "input" => "/root/.labmaker", 10.43 + "diffs" => "", 10.44 + "input_mask" => "*.script", 10.45 + "encoding" => "utf-8", 10.46 + 10.47 + "output" => "/var/www/lm/reportINDEX.html", 10.48 + #"output" => "report.xml", 10.49 + "output_mask" => "INDEX", 10.50 + "output_format" => "html", 10.51 + 10.52 + "signature" => "#lm:", 10.53 + "from" => "", 10.54 + "to" => "", 10.55 + "lab" => "", 10.56 + "keywords" => "linux command", 10.57 + "files_keywords" => "linux file", 10.58 + 10.59 + comment_width => "300", 10.60 + time_width => "60", 10.61 + 10.62 + ); 10.63 + 10.64 +our @Command_Lines; 10.65 +our @Command_Lines_Index; 10.66 +our @Diffs; 10.67 + 10.68 +our %Commands_Stat; # Statistics about commands usage 10.69 +our %Files_Stat; # Statistics about commands usage 10.70 + 10.71 +our %Search_Machines = ( 10.72 + "google" => { "query" => "http://www.google.com/search?q=" , 10.73 + "icon" => "google.ico" }, 10.74 + "freebsd" => { "query" => "http://www.freebsd.org/cgi/man.cgi?query=", 10.75 + "icon" => "freebsd.ico" }, 10.76 + "linux" => { "query" => "http://man.he.net/?topic=", 10.77 + "icon" => "linux.ico"}, 10.78 + "opennet" => { "query" => "http://www.opennet.ru/search.shtml?words=", 10.79 + "icon" => "opennet.ico"}, 10.80 + "local" => { "query" => "http://www.freebsd.org/cgi/man.cgi?query=", 10.81 + "icon" => "freebsd.ico" }, 10.82 + 10.83 + ); 10.84 + 10.85 +our %Elements_Visibility = ( 10.86 + "note" => "замечания", 10.87 + "diff" => "редактор", 10.88 + "time" => "время", 10.89 + "ttychange" => "терминал", 10.90 + "wrong_output wrong_cline wrong_root_output wrong_root_cline" 10.91 + => "команды с ошибками", 10.92 + "interrupted_output interrupted_cline interrupted_root_output interrupted_root_cline" 10.93 + => "прерванные команды", 10.94 + "tab_completion_output tab_completion_cline" 10.95 + => "продолжение с помощью tab" 10.96 +); 10.97 + 10.98 + 10.99 +sub load_diff_files 10.100 +{ 10.101 + my @pathes = @_; 10.102 + 10.103 + for my $path (@pathes) { 10.104 + my $template = "*.diff"; 10.105 + my @files = <$path/$template>; 10.106 + my $i=0; 10.107 + for my $file (@files) { 10.108 + my %diff; 10.109 + 10.110 + $diff{"path"}=$path; 10.111 + $diff{"uid"}="SET THIS"; 10.112 + 10.113 +# Сейчас UID определяется из названия каталога 10.114 +# откуда берутся diff-файлы 10.115 +# Это неправильно 10.116 +# 10.117 +# ВАРИАНТ: 10.118 +# К файлам жураналам должны прилагаться ситемны файлы, 10.119 +# мз которых и будет определяться соответствие 10.120 +# имён пользователей их uid'ам 10.121 +# 10.122 + $diff{"uid"} = 0 if $path =~ m@/root/@; 10.123 + 10.124 + $diff{"bind_to"}=""; 10.125 + $diff{"time_range"}=-1; 10.126 + 10.127 + next if not $file=~m@/(D?[0-9][0-9]?[0-9]?)[^/]*?([0-9]*):([0-9]*):?([0-9]*)@; 10.128 + $diff{"day"}=$1 || ""; 10.129 + $diff{"hour"}=$2; 10.130 + $diff{"min"}=$3; 10.131 + $diff{"sec"}=$4 || 0; 10.132 + 10.133 + $diff{"index"}=$i; 10.134 + 10.135 + print "diff loaded: $diff{day} $diff{hour}:$diff{min}:$diff{sec}\n"; 10.136 + 10.137 + local $/; 10.138 + open (F, "$file") 10.139 + or return "Can't open file $file ($_[0]) for reading"; 10.140 + my $text = <F>; 10.141 + if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i) { 10.142 + my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8"); 10.143 + $text = $converter->convert($text); 10.144 + } 10.145 + close(F); 10.146 + $diff{"text"}=$text; 10.147 + #print "$file loaded ($diff{day})\n"; 10.148 + 10.149 + push @Diffs, \%diff; 10.150 + $i++; 10.151 + } 10.152 + } 10.153 +} 10.154 + 10.155 + 10.156 +sub bind_diff 10.157 +{ 10.158 +# my $path = shift; 10.159 +# my $pid = shift; 10.160 +# my $day = shift; 10.161 +# my $lab = shift; 10.162 + 10.163 + print "Trying to bind diff...\n"; 10.164 + 10.165 + my $cl = shift; 10.166 + my $hour = $cl->{"hour"}; 10.167 + my $min = $cl->{"min"}; 10.168 + my $sec = $cl->{"sec"}; 10.169 + 10.170 + my $min_dt = 10000; 10.171 + 10.172 + for my $diff (@Diffs) { 10.173 + # Check here date, time and user 10.174 + next if ($diff->{"day"} && $cl->{"day"} && ($cl->{"day"} ne $diff->{"day"})); 10.175 + #next if (!$diff->{"uid"} && $cl->{"euid"} != $diff->{"uid"}); 10.176 + 10.177 + my $dt=($diff->{"hour"}-$hour)*3600 +($diff->{"min"}-$min)*60 + ($diff->{"sec"}-$sec); 10.178 + if ($dt >0 && $dt < $min_dt && ($diff->{"time_range"} <0 || $dt < $diff->{"time_range"})) { 10.179 + print "Approppriate diff found: dt=$dt\n"; 10.180 + if ($diff->{"bind_to"}) { 10.181 + undef $diff->{"bind_to"}->{"diff"}; 10.182 + }; 10.183 + $diff->{"time_range"}=$dt; 10.184 + $diff->{"bind_to"}=$cl; 10.185 + 10.186 + $cl->{"diff"} = $diff->{"index"}; 10.187 + $min_dt = $dt; 10.188 + } 10.189 + 10.190 + } 10.191 +} 10.192 + 10.193 + 10.194 +sub extract_from_cline 10.195 +# Разобрать командную строку $_[1] и возвратить хэш, содержащий 10.196 +# номер первого появление команды в строке: 10.197 +# команда => первая позиция 10.198 +{ 10.199 + my $what = $_[0]; 10.200 + my $cline = $_[1]; 10.201 + my @lists = split /\;/, $cline; 10.202 + 10.203 + 10.204 + my @commands = (); 10.205 + for my $list (@lists) { 10.206 + push @commands, split /\|/, $list; 10.207 + } 10.208 + 10.209 + my %commands; 10.210 + my %files; 10.211 + my $i=0; 10.212 + for my $command (@commands) { 10.213 + $command =~ /\s*(\S+)\s*(.*)/; 10.214 + if ($1 && $1 eq "sudo" ) { 10.215 + $commands{"$1"}=$i++; 10.216 + $command =~ s/\s*sudo\s+//; 10.217 + } 10.218 + $command =~ /\s*(\S+)\s*(.*)/; 10.219 + if ($1 && !defined $commands{"$1"}) { 10.220 + $commands{"$1"}=$i++; 10.221 + }; 10.222 + if ($2) { 10.223 + my $args = $2; 10.224 + my @args = split (/\s+/, $args); 10.225 + for my $a (@args) { 10.226 + $files{"$a"}=$i++ 10.227 + if !defined $files{"$a"}; 10.228 + }; 10.229 + 10.230 + 10.231 + } 10.232 + } 10.233 + 10.234 + if ($what eq "commands") { 10.235 + return %commands; 10.236 + } else { 10.237 + return %files; 10.238 + } 10.239 + 10.240 +} 10.241 + 10.242 +sub load_command_lines 10.243 +{ 10.244 + my $lab_scripts_path = $_[0]; 10.245 + my $lab_scripts_mask = $_[1]; 10.246 + 10.247 + my $cline_re_base = qq' 10.248 + (?:\\^?([0-9]*C?)) # exitcode 10.249 + (?:_([0-9]+)_)? # uid 10.250 + (?:_([0-9]+)_) # pid 10.251 + (...?) # day 10.252 + (..) # lab 10.253 + \\s # space separator 10.254 + ([0-9][0-9]):([0-9][0-9]):([0-9][0-9]) # time 10.255 + .\\[50D.\\[K # killing symbols 10.256 + (.*?([\$\#]\\s?)) # prompt 10.257 + (.*) # command line 10.258 + '; 10.259 + #my $cline_re = qr/$cline_re_base(?:$cline_re_base|$)/x; 10.260 + #my $cline_re = qr/(?:$cline_re_base)*$cline_re_base$/x; 10.261 + my $cline_re = qr/$cline_re_base/sx; 10.262 + my $cline_re1 = qr/$cline_re_base\x0D/sx; 10.263 + my $cline_re2 = qr/$cline_re_base$/sx; 10.264 + 10.265 + my $vt = Term::VT102->new ( 'cols' => $Config{"terminal_width"}, 10.266 + 'rows' => $Config{"terminal_height"}); 10.267 + my $cline_vt = Term::VT102->new ('cols' => $Config{"terminal_width"}, 10.268 + 'rows' => $Config{"terminal_height"}); 10.269 + 10.270 + my $converter = Text::Iconv->new($Config{"encoding"}, "utf-8") 10.271 + if ($Config{"encoding"} && $Config{"encoding"} !~ /^utf-8$/i); 10.272 + 10.273 + print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/; 10.274 + 10.275 + my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>; 10.276 + my $file; 10.277 + my $files_number = $#lab_scripts; 10.278 + my $ii = 0; 10.279 + my $skip_info; 10.280 + 10.281 + my $commandlines_loaded =0; 10.282 + my $commandlines_processed =0; 10.283 + 10.284 + for $file (@lab_scripts){ 10.285 + #printf "\t%i %3.2f\n", $ii, (100*$ii++/$files_number) if $Config{"verbose"} =~ /y/; 10.286 + 10.287 + open (FILE, "$file"); 10.288 + binmode FILE; 10.289 + $file =~ m@.*/(.*?)-.*@; 10.290 + 10.291 + my $tty = $1; 10.292 + my $first_pass = 1; 10.293 + my %cl; 10.294 + my $last_output_length=0; 10.295 + while (<FILE>) { 10.296 + $commandlines_processed++; 10.297 + # time 10.298 + 10.299 + if (/[0-9][0-9]:[0-9][0-9]:[0-9][0-9].\[[0-9][0-9]D.\[K/ && m/$cline_re/) { 10.300 + s/.*\x0d(?!\x0a)//; 10.301 + # print "!!!",$_,"!!!\n"; 10.302 + # next; 10.303 + # while (m/$cline_re1/gs) { 10.304 + # } 10.305 + m/$cline_re2/gs; 10.306 + 10.307 + $commandlines_loaded++; 10.308 + $last_output_length=0; 10.309 + 10.310 + # Previous command 10.311 + my %last_cl = %cl; 10.312 + my $err = $1 || ""; 10.313 + 10.314 + # Parse new command 10.315 + $cl{"uid"} = $2; 10.316 + $cl{"euid"} = $cl{"uid"}; # Если в команде обнаружится sudo, euid поменяем на 0 10.317 + $cl{"pid"} = $3; 10.318 + $cl{"day"} = $4; 10.319 + $cl{"lab"} = $5; 10.320 + $cl{"hour"} = $6; 10.321 + $cl{"min"} = $7; 10.322 + $cl{"sec"} = $8; 10.323 + $cl{"fullprompt"} = $9; 10.324 + $cl{"prompt"} = $10; 10.325 + $cl{"raw_cline"} = $11; 10.326 + 10.327 + $cl{"err"} = 0; 10.328 + $cl{"output"} = ""; 10.329 + $cl{"tty"} = $tty; 10.330 + 10.331 + $cline_vt->process($cl{"raw_cline"}."\n"); 10.332 + $cl{"cline"} = $cline_vt->row_plaintext (1); 10.333 + $cl{"cline"} =~ s/\s*$//; 10.334 + $cline_vt->reset(); 10.335 + 10.336 + my %commands = extract_from_cline("commands", $cl{"cline"}); 10.337 + $cl{"euid"}=0 if defined $commands{"sudo"}; 10.338 + my @comms = sort { $commands{$a} cmp $commands{$b} } keys %commands; 10.339 + $cl{"last_command"} = $comms[$#comms] || ""; 10.340 + 10.341 + if ( 10.342 + $Config{"suppress_editors"} =~ /^y/i 10.343 + && grep ($_ eq $cl{"last_command"}, @{$Config{"editors"}}) || 10.344 + $Config{"suppress_pagers"} =~ /^y/i 10.345 + && grep ($_ eq $cl{"last_command"}, @{$Config{"pagers"}}) || 10.346 + $Config{"suppress_terminal"}=~ /^y/i 10.347 + && grep ($_ eq $cl{"last_command"}, @{$Config{"terminal"}}) 10.348 + ) { 10.349 + $cl{"suppress_output"} = "1"; 10.350 + } 10.351 + else { 10.352 + $cl{"suppress_output"} = "0"; 10.353 + 10.354 + } 10.355 + $skip_info = 0; 10.356 + 10.357 + 10.358 + print " ",$cl{"last_command"}; 10.359 + 10.360 + # Processing previous command line 10.361 + if ($first_pass) { 10.362 + $first_pass = 0; 10.363 + next; 10.364 + } 10.365 + 10.366 + # Error code 10.367 + $last_cl{"err"}=$err; 10.368 + $last_cl{"err"}=130 if $err eq "^C"; 10.369 + 10.370 + if (grep ($_ eq $last_cl{"last_command"}, @{$Config{"editors"}})) { 10.371 + bind_diff(\%last_cl); 10.372 + } 10.373 + 10.374 + # Output 10.375 + if (!$last_cl{"suppress_output"} || $last_cl{"err"}) { 10.376 + for (my $i=0; $i<$Config{"terminal_height"}; $i++) { 10.377 + my $line= $vt->row_plaintext($i); 10.378 + next if !defined ($line) || $line =~ /^\s*$/; 10.379 + $line =~ s/\s*$//; 10.380 + $last_cl{"output"} .= $line."\n"; 10.381 + } 10.382 + } 10.383 + else { 10.384 + $last_cl{"output"}= ""; 10.385 + } 10.386 + 10.387 + $vt->reset(); 10.388 + 10.389 + 10.390 + # Classifying the command line 10.391 + 10.392 + 10.393 + # Save 10.394 + if (!$Config{"lab"} || $cl{"lab"} eq $Config{"lab"}) { 10.395 + # Changing encoding 10.396 + for (keys %last_cl) { 10.397 + $last_cl{$_} = $converter->convert($last_cl{$_}) 10.398 + if ($Config{"encoding"} && 10.399 + $Config{"encoding"} !~ /^utf-8$/i); 10.400 + } 10.401 + push @Command_Lines, \%last_cl; 10.402 + } 10.403 + next; 10.404 + } 10.405 + $last_output_length+=length($_); 10.406 + #if (!$cl{"suppress_output"} || $last_output_length < 5000) { 10.407 + if ($last_output_length < 5000) { 10.408 + #print "(",length($_),")" if (length($_) > 2000) ; 10.409 + $vt->process("$_"."\n") 10.410 + } 10.411 + else 10.412 + { 10.413 + if (!$skip_info) { 10.414 + print "($cl{last_command})"; 10.415 + $skip_info = 1; 10.416 + } 10.417 + } 10.418 + } 10.419 + close(FILE); 10.420 + 10.421 + } 10.422 + if ($Config{"verbose"} =~ /y/) { 10.423 + print "...finished." ; 10.424 + print "Lines loaded: $commandlines_processed\n"; 10.425 + print "Command lines: $commandlines_loaded\n"; 10.426 + } 10.427 +} 10.428 + 10.429 +sub search_by 10.430 +{ 10.431 + my $sm = shift; 10.432 + my $topic = shift; 10.433 + $topic =~ s/ /+/; 10.434 + 10.435 + return "<a href='". $Search_Machines{$sm}->{"query"}."$topic'><img width='16' height='16' src='". 10.436 + $Search_Machines{$sm}->{"icon"}."' border='0'/></a>"; 10.437 +} 10.438 + 10.439 +sub make_comment 10.440 +{ 10.441 + my $commands = $_[0]; 10.442 + my $files = $_[1]; 10.443 + chomp $commands; 10.444 + chomp $files; 10.445 + return if (!$commands && !$files); 10.446 + 10.447 + my $comment=""; 10.448 + 10.449 + # Commands 10.450 + for my $command (split /\s+/,$commands) { 10.451 + $command =~ s/'//g; 10.452 + my $description=""; 10.453 + eval { $description=`mywi-client '$command'`; } ; 10.454 + $description = join ("<br>\n", grep(/\([18]\)/, split(/\n/, $description))); 10.455 + $description =~ s/.*?-//; 10.456 + next if $description =~ /^\s*$/; 10.457 + 10.458 + my $query=$command." ".$Config{"keywords"}; 10.459 + $query =~ s/\ /+/g; 10.460 + my $search= search_by("opennet",$query). 10.461 + search_by("local",$command). 10.462 + search_by("google",$query); 10.463 + 10.464 + $comment .= "<tr><td class='note_title'>$command</td>". 10.465 + "<td class='note_search'>$search</td>". 10.466 + "</tr><tr><td width='100%' colspan='2' class='note_text'>". 10.467 + "$description</td></tr><tr/>"; 10.468 + } 10.469 + 10.470 + # Files 10.471 + for my $file (split /\s+/,$files) { 10.472 + $file =~ s@.*/@@; 10.473 + $file =~ s/'//g; 10.474 + next if $file =~ /^\s*$/; 10.475 + next if $file =~ /^-/; 10.476 + 10.477 + my $description=`mywi '$file'`; 10.478 + $description = join ("<br>\n", grep(/\(5\)/, split(/\n/, $description))); 10.479 + next if $description =~ /^\s*$/; 10.480 + 10.481 + my $query=$file." ".$Config{"files_keywords"}; 10.482 + $query =~ s/\ /+/g; 10.483 + my $search= search_by("opennet",$query). 10.484 + search_by("local",$file). 10.485 + search_by("google",$query); 10.486 + 10.487 + $comment .= "<tr><td class='note_title'>$file</td>". 10.488 + "<td class='note_search'>$search</td>". 10.489 + "</tr><tr><td width='100%' colspan='2' class='note_text'>". 10.490 + "$description</td></tr><tr/>"; 10.491 + } 10.492 + 10.493 + 10.494 + return $comment; 10.495 +} 10.496 + 10.497 +sub printq 10.498 +{ 10.499 + my $TO = shift; 10.500 + my $text = join "", @_; 10.501 + $text =~ s/&/&/g; 10.502 + $text =~ s/</</g; 10.503 + $text =~ s/>/>/g; 10.504 + print $TO $text; 10.505 +} 10.506 + 10.507 + 10.508 +sub sort_command_lines 10.509 +{ 10.510 + print "Sorting command lines...\n" if $Config{"verbose"} =~ /y/; 10.511 + 10.512 + # Sort Command_Lines 10.513 + # Write Command_Lines to Command_Lines_Index 10.514 + 10.515 + my @index; 10.516 + for (my $i=0;$i<=$#Command_Lines;$i++) { 10.517 + $index[$i]=$i; 10.518 + } 10.519 + 10.520 + @Command_Lines_Index = sort { 10.521 + $Command_Lines[$index[$a]]->{"day"} cmp $Command_Lines[$index[$b]]->{"day"} || 10.522 + $Command_Lines[$index[$a]]->{"hour"} <=> $Command_Lines[$index[$b]]->{"hour"} || 10.523 + $Command_Lines[$index[$a]]->{"min"} <=> $Command_Lines[$index[$b]]->{"min"} || 10.524 + $Command_Lines[$index[$a]]->{"sec"} <=> $Command_Lines[$index[$b]]->{"sec"} 10.525 + } @index; 10.526 + 10.527 + print "...finished\n" if $Config{"verbose"} =~ /y/; 10.528 + 10.529 +} 10.530 + 10.531 +sub process_command_lines 10.532 +{ 10.533 + my $lab_scripts_path = $_[0]; 10.534 + 10.535 + for my $i (@Command_Lines_Index) { 10.536 + 10.537 + my $cl = \$Command_Lines[$i]; 10.538 + @{${$cl}->{"new_commands"}} =(); 10.539 + @{${$cl}->{"new_files"}} =(); 10.540 + $$cl->{"class"} = ""; 10.541 + 10.542 + if ($$cl->{"err"}) { 10.543 + $$cl->{"class"}="wrong"; 10.544 + $$cl->{"class"}="interrupted" 10.545 + if ($$cl->{"err"} eq 130); 10.546 + } 10.547 + if (!$$cl->{"euid"}) { 10.548 + $$cl->{"class"}.="_root"; 10.549 + } 10.550 + 10.551 +#tab# my @tab_words=split /\s+/, $$cl->{"output"}; 10.552 +#tab# my $last_word= $$cl->{"cline"} =~ /(\S*)$/; 10.553 +#tab# $last_word =~ s@.*/@@; 10.554 +#tab# my $this_is_tab=1; 10.555 +#tab# 10.556 +#tab# if ($last_word && @tab_words >2) { 10.557 +#tab# for my $tab_words (@tab_words) { 10.558 +#tab# if ($tab_words !~ /^$last_word/) { 10.559 +#tab# $this_is_tab=0; 10.560 +#tab# last; 10.561 +#tab# } 10.562 +#tab# } 10.563 +#tab# } 10.564 +#tab# $$cl->{"class"}="tab" if $this_is_tab; 10.565 + 10.566 + 10.567 + if ( !$$cl->{"err"}) { 10.568 + # Command does not contain mistakes 10.569 + 10.570 + my %commands = extract_from_cline("commands", ${$cl}->{"cline"}); 10.571 + my %files = extract_from_cline("files", ${$cl}->{"cline"}); 10.572 + 10.573 + # Searching for new commands only 10.574 + for my $command (keys %commands) { 10.575 + if (!defined $Commands_Stat{$command}) { 10.576 + push @{$$cl->{new_commands}}, $command; 10.577 + } 10.578 + $Commands_Stat{$command}++; 10.579 + } 10.580 + 10.581 + for my $file (keys %files) { 10.582 + if (!defined $Files_Stat{$file}) { 10.583 + push @{$$cl->{new_files}}, $file; 10.584 + } 10.585 + $Files_Stat{$file}++; 10.586 + } 10.587 + } 10.588 + } 10.589 + 10.590 +} 10.591 + 10.592 +sub print_command_lines 10.593 +{ 10.594 + my $output_filename=$_[0]; 10.595 + my $format = $Config{"output_format"}; 10.596 + 10.597 + open(OUT, ">", $output_filename) 10.598 + or die "Can't open $output_filename for writing\n"; 10.599 + 10.600 + 10.601 + 10.602 + if ($format eq "html") { 10.603 + # vvvv HTML Header 10.604 + print OUT <<HEADER; 10.605 + <html> 10.606 + <head> 10.607 + <meta content='text/html; charset=utf-8' http-equiv='Content-Type' /> 10.608 + <link rel='stylesheet' href='labmaker.css' type='text/css'/> 10.609 + </head> 10.610 + <body> 10.611 + <script> 10.612 + function getElementsByClassName(Class_Name) 10.613 + { 10.614 + var Result=new Array(); 10.615 + var All_Elements=document.all || document.getElementsByTagName('*'); 10.616 + for (i=0; i<All_Elements.length; i++) 10.617 + if (All_Elements[i].className==Class_Name) 10.618 + Result.push(All_Elements[i]); 10.619 + return Result; 10.620 + } 10.621 + function ShowHide (name) 10.622 + { 10.623 + elements=getElementsByClassName(name); 10.624 + for(i=0; i<elements.length; i++) 10.625 + if (elements[i].style.display == "none") 10.626 + elements[i].style.display = ""; 10.627 + else 10.628 + elements[i].style.display = "none"; 10.629 + //if (elements[i].style.visibility == "hidden") 10.630 + // elements[i].style.visibility = "visible"; 10.631 + //else 10.632 + // elements[i].style.visibility = "hidden"; 10.633 + } 10.634 + function filter_by_output(text) 10.635 + { 10.636 + 10.637 + var jjj=0; 10.638 + 10.639 + elements=getElementsByClassName('command'); 10.640 + for(i=0; i<elements.length; i++) { 10.641 + subelems = elements[i].getElementsByTagName('pre'); 10.642 + for(j=0; j<subelems.length; j++) { 10.643 + if (subelems[j].className = 'output') { 10.644 + var str = new String(subelems[j].nodeValue); 10.645 + if (jjj != 1) { 10.646 + alert(str); 10.647 + jjj=1; 10.648 + } 10.649 + if (str.indexOf(text) >0) 10.650 + subelems[j].style.display = "none"; 10.651 + else 10.652 + subelems[j].style.display = ""; 10.653 + 10.654 + } 10.655 + 10.656 + } 10.657 + } 10.658 + 10.659 + } 10.660 + </script> 10.661 +HEADER 10.662 + print OUT "<table class='visibility_form'><tr><td><form>\n"; 10.663 + for my $element (keys %Elements_Visibility) 10.664 + { 10.665 + my @e = split /\s+/, $element; 10.666 + my $showhide = join "", map { "ShowHide('$_');" } @e ; 10.667 + print OUT "<input type='checkbox' name='$e[0]' onclick=\"$showhide\" checked>", 10.668 + $Elements_Visibility{$element}, 10.669 + "</input><br>\n"; 10.670 + } 10.671 + #print OUT "<input type='text' size='10' name=\"by_command\"/>". 10.672 + #"<input type='button' value='фильтр по командам' onclick=\"filter_by_command()\"/> <br>\n"; 10.673 + #print OUT "<input type='text' size='10' name=\"by_output\"/>". 10.674 + #"<input type='button' value='фильтр по результату' ". 10.675 + #"onclick=\"filter_by_output(this.form.by_output.value)\"/> <br>\n"; 10.676 + 10.677 + print OUT "</form></td></tr></table>\n"; 10.678 + print OUT "<table width='100%'>\n"; 10.679 + # ^^^^ HTML Header 10.680 + } 10.681 + else { 10.682 + # XML Header 10.683 + print OUT "<script>\n" 10.684 + } 10.685 + 10.686 + my $cl; 10.687 + my $last_tty=""; 10.688 + my $in_range=0; 10.689 + for my $i (@Command_Lines_Index) { 10.690 + 10.691 + $cl = $Command_Lines[$i]; 10.692 + 10.693 + if ($Config{"from"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"from"}/) { 10.694 + $in_range=1; 10.695 + next; 10.696 + } 10.697 + if ($Config{"to"} && $cl->{"cline"} =~ /$Config{"signature"}\s*$Config{"to"}/) { 10.698 + $in_range=0; 10.699 + next; 10.700 + } 10.701 + next if ($Config{"from"} && $Config{"to"} && !$in_range) 10.702 + || 10.703 + ($Config{"skip_empty"} =~ /^y/i && $cl->{"cline"} =~ /^\s*$/ ) 10.704 + || 10.705 + ($Config{"skip_wrong"} =~ /^y/i && $cl->{"err"} != 0) 10.706 + || 10.707 + ($Config{"skip_interrupted"} =~ /^y/i && $cl->{"err"} == 130); 10.708 + 10.709 + my @new_commands=@{$cl->{"new_commands"}}; 10.710 + my @new_files=@{$cl->{"new_files"}}; 10.711 + 10.712 + my $cl_class="cline"; 10.713 + my $out_class="output"; 10.714 + if ($cl->{"class"}) { 10.715 + $cl_class = $cl->{"class"}."_".$cl_class; 10.716 + $out_class = $cl->{"class"}."_".$out_class; 10.717 + } 10.718 + 10.719 + my $output=""; 10.720 + if ($Config{"head_lines"} || $Config{"tail_lines"}) { 10.721 + # Partialy output 10.722 + my @lines = split '\n', $cl->{"output"}; 10.723 + # head 10.724 + my $mark=1; 10.725 + for (my $i=0; $i<= $#lines && $i < $Config{"head_lines"}; $i++) { 10.726 + $output .= $lines[$i]."\n"; 10.727 + } 10.728 + # tail 10.729 + my $start=$#lines-$Config{"tail_lines"}+1; 10.730 + if ($start < 0) { 10.731 + $start=0; 10.732 + $mark=0; 10.733 + } 10.734 + if ($start < $Config{"head_lines"}) { 10.735 + $start=$Config{"head_lines"}; 10.736 + $mark=0; 10.737 + } 10.738 + $output .= $Config{"skip_text"}."\n" if $mark; 10.739 + for (my $i=$start; $i<= $#lines; $i++) { 10.740 + $output .= $lines[$i]."\n"; 10.741 + } 10.742 + } 10.743 + else { 10.744 + # Full output 10.745 + $output .= $cl->{"output"}; 10.746 + } 10.747 + $output .= "^C\n" if ($cl->{"err"} eq "130"); 10.748 + 10.749 + 10.750 +# Printing out 10.751 + 10.752 + # <command> 10.753 + print OUT $format eq "html" 10.754 + ? "<tr class='command'>\n" 10.755 + : "\n<action time='$cl->{hour}:$cl->{min}:$cl->{sec}' tty='$cl->{tty}'>\n"; 10.756 + 10.757 + 10.758 + if ($format eq "html") { 10.759 + # CONSOLE CHANGE 10.760 + if ( $last_tty ne $cl->{"tty"}) { 10.761 + print OUT "<td colspan='6'><table><tr><td class='ttychange' width='140' align='center'>",$cl->{"tty"},"</td><td/></tr></table></td></tr><tr>"; 10.762 + $last_tty=$cl->{"tty"}; 10.763 + } 10.764 + 10.765 + # TIME 10.766 + if ($Config{"show_time"} =~ /^y/i) { 10.767 + print OUT "<td valign='top' class='time' width='$Config{time_width}'><pre>", 10.768 + $cl->{"hour"}, ":", $cl->{"min"}, ":", $cl->{"sec"}, 10.769 + "</td>"; 10.770 + } else { 10.771 + print OUT "<td width='0'/>" 10.772 + } 10.773 + } 10.774 + 10.775 + # COMMAND 10.776 + 10.777 + 10.778 + if ($format eq "html") { 10.779 + print OUT "<td class='script'>\n"; 10.780 + print OUT "<pre class='$cl_class'>\n"; 10.781 + my $cline = $cl->{"cline"}; 10.782 + $cline =~ s/\n//; 10.783 + printq(\*OUT,$cl->{"prompt"},$cl->{"cline"}); 10.784 +# printq(\*OUT,"(sudo ".$cl->{"last_command"}.")\n") if !$cl->{"euid"}; 10.785 + print OUT "</pre>\n"; 10.786 + } 10.787 + else { 10.788 + print OUT "<line class='$cl_class'>\n"; 10.789 + print OUT "<prompt>"; 10.790 + printq(\*OUT,$cl->{"prompt"}); 10.791 + print OUT "</prompt>"; 10.792 + print OUT "<command>"; 10.793 + printq(\*OUT,$cl->{"cline"}); 10.794 + print OUT "</command>"; 10.795 + print OUT "\n</line>\n"; 10.796 + } 10.797 + 10.798 + my $last_command = $cl->{"last_command"}; 10.799 + if (!( 10.800 + $Config{"suppress_editors"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"editors"}}) || 10.801 + $Config{"suppress_pagers"} =~ /^y/i && grep ($_ eq $last_command, @{$Config{"pagers"}}) || 10.802 + $Config{"suppress_terminal"}=~ /^y/i && grep ($_ eq $last_command, @{$Config{"terminal"}}) 10.803 + )) { 10.804 + 10.805 + if ($format eq "html") { 10.806 + print OUT "<pre class='$out_class'>"; 10.807 + printq(\*OUT,$output); 10.808 + print OUT "</pre>\n"; 10.809 + } 10.810 + else { 10.811 + print OUT "<output class='$out_class'>\n"; 10.812 + printq(\*OUT,$output); 10.813 + print OUT "</output>\n"; 10.814 + } 10.815 + } 10.816 + 10.817 + # DIFF 10.818 + if ( $Config{"show_diffs"} =~ /^y/i && $cl->{"diff"}) { 10.819 + if ($format eq "html") { 10.820 + #print Dumper(%{$cl->{"diff"}}); 10.821 + print OUT "<table><tr><td width='5'/><td class='diff'><pre>"; 10.822 + printq(\*OUT,${$Diffs[$cl->{"diff"}]}{"text"}); 10.823 + print OUT "</pre></td></tr></table>"; 10.824 + } 10.825 + else { 10.826 + print OUT "<diff>\n"; 10.827 + printq(\*OUT,${$Diffs[$cl->{"diff"}]}{"text"}); 10.828 + print OUT "</diff>\n"; 10.829 + } 10.830 + } 10.831 + 10.832 + # COMMENT 10.833 + if ( $Config{"show_comments"} =~ /^y/i) { 10.834 + my $comment = make_comment(join(" ",@new_commands), join (" ",@new_files)); 10.835 + if ($comment) { 10.836 + if ($format eq "html") { 10.837 + print OUT "<table width='$Config{comment_width}'>". 10.838 + "<tr><td width='5'/><td>"; 10.839 + print OUT "<table class='note' width='100%'>"; 10.840 + print OUT $comment; 10.841 + print OUT "</table>\n"; 10.842 + print OUT "</td></tr></table>"; 10.843 + } 10.844 + # else { 10.845 + # print OUT "<comment>"; 10.846 + # printq(\*OUT,$comment); 10.847 + # print OUT "</comment>"; 10.848 + # } 10.849 + } 10.850 + } 10.851 + 10.852 + if ($format eq "html") { 10.853 + print OUT "</td>\n"; 10.854 + print OUT "</tr>\n"; 10.855 + } 10.856 + else { 10.857 + print OUT "</action>\n"; 10.858 + } 10.859 + 10.860 + } 10.861 + if ($format eq "html") { 10.862 + print OUT "</table>\n"; 10.863 + print OUT "</body>\n"; 10.864 + print OUT "</html>\n"; 10.865 + } 10.866 + else { 10.867 + print OUT "</script>\n"; 10.868 + } 10.869 + close(OUT); 10.870 +} 10.871 + 10.872 +sub read_config_file 10.873 +{ 10.874 + my $config = $_[0]; 10.875 + my $filename = $_[1]; 10.876 + open(CONFIG, "$filename") 10.877 + or return; 10.878 + while (<CONFIG>) { 10.879 + s/#.*//; 10.880 + next if /^\s*$/; 10.881 + my ($var, $val) = split /\s*=\s*/, $_, 2; 10.882 + $var =~ s/\s*//; 10.883 + $config->{$var} = $val; 10.884 + } 10.885 + close(CONFIG); 10.886 +} 10.887 + 10.888 +$| = 1; 10.889 + 10.890 +my %file_config; 10.891 +my %argv_config; 10.892 +read_config_file(\%file_config, $Config_File); 10.893 +GetOptions(\%argv_config, map "$_=s", keys %Config); 10.894 +%Config = (%Config, %file_config, %argv_config); 10.895 + 10.896 + 10.897 +my $i=0; 10.898 + 10.899 +for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) 10.900 +{ 10.901 + load_diff_files($lab_log); 10.902 +} 10.903 + 10.904 +for my $lab_log (split /\s+/, $Config{"input"}) 10.905 +{ 10.906 + my $tofile=$Config{"output"}; 10.907 + $tofile =~ s/$Config{"output_mask"}/$i/; 10.908 + #load_diff_files($lab_log); 10.909 + load_command_lines($lab_log, $Config{"input_mask"}); 10.910 + sort_command_lines; 10.911 + process_command_lines($lab_log); 10.912 + print_command_lines($tofile); 10.913 + $i++; 10.914 +} 10.915 +
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/lm-ssh Sun May 22 16:29:55 2005 +0300 11.3 @@ -0,0 +1,31 @@ 11.4 +#!/bin/sh 11.5 +#\ 11.6 +exec expect -- "$0" ${1+"$@"} 11.7 +eval spawn ssh $argv 11.8 +set timeout 1 11.9 +expect { 11.10 + eof { 11.11 + } 11.12 + "(yes/no)? " { 11.13 + send "yes\n" 11.14 + exp_continue 11.15 + } 11.16 + assword: { 11.17 + send "rootpass\n" 11.18 + } 11.19 + timeout { 11.20 + interact -nobuffer 11.21 + } 11.22 +} 11.23 +expect { 11.24 + eof { 11.25 + } 11.26 + assword: { 11.27 + send "rootpass\n" 11.28 + } 11.29 + 11.30 + timeout { 11.31 + interact -nobuffer 11.32 + } 11.33 +} 11.34 +
12.1 Binary file share/freebsd.ico has changed
13.1 Binary file share/google.ico has changed
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/share/labmaker.css Sun May 22 16:29:55 2005 +0300 14.3 @@ -0,0 +1,89 @@ 14.4 +.cline,.wrong_cline,.interrupted_cline,.output,.wrong_output,.interrupted_output,.tab_cline, ._root_cline,.wrong_root_cline,.interrupted_root_cline,._root_output,.wrong_root_output,.interrupted_root_output,.tab_root_cline 14.5 + { 14.6 + margin : 0px 0px 0px 0px; 14.7 + padding : 0px 0px 0px 10px; 14.8 + vertical-align : top; 14.9 + } 14.10 +.cline,.wrong_cline,.interrupted_cline,.tab_cline,._root_cline,.wrong_root_cline,.interrupted_root_cline,.tab_root_cline 14.11 + { font-weight : bold; } 14.12 +.wrong_output,.wrong_root_output 14.13 + { color : #cc6666; } 14.14 +.interrupted_output,.interrupted_root_output 14.15 + { color : #aaaaaa; } 14.16 +.wrong_cline, .wrong_root_cline 14.17 + { color : #ee7777; } 14.18 +.interrupted_cline, .interrupted_root_cline 14.19 + { color : #777777; } 14.20 + 14.21 +._root_cline,.wrong_root_cline,.interrupted_root_cline,._root_output,.wrong_root_output,.interrupted_root_output,.tab_root_cline 14.22 + { 14.23 + border-left : #ff0000 solid thin; 14.24 + 14.25 + } 14.26 + 14.27 +.note { 14.28 + color : black; 14.29 + background : #d8fcff; 14.30 + margin : 12px 12px 12px 12px; 14.31 + padding : 6px 6px 6px 6px; 14.32 + border-style : dashed; 14.33 + border-width : thin; 14.34 + border-color : #a8eaff; 14.35 + vertical-align : top; 14.36 +} 14.37 + 14.38 +.note_title,.note_text,.note_search 14.39 + { 14.40 + color : black; 14.41 + margin : 0px 0px 0px 0px; 14.42 + padding : 0px 0px 0px 0px; 14.43 + vertical-align : top; 14.44 + } 14.45 +.note_title { font-family : sans-serif; } 14.46 +.note_text { font-size : 80%; } 14.47 +.note_search { text-align : right; } 14.48 + 14.49 + 14.50 +.diff { 14.51 + color : black; 14.52 + background : #fdffcd; 14.53 + margin : 16px 16px 16px 16px; 14.54 + padding : 6px 6px 6px 6px; 14.55 + border-style : dashed; 14.56 + border-width : thin; 14.57 +} 14.58 + 14.59 +.ttychange { 14.60 + color : #9a9a9a; 14.61 + background : #e7e7e7; 14.62 + margin : 0px 0px 0px 0px; 14.63 + padding : 0px 0px 0px 0px; 14.64 + vertical-align : top; 14.65 + font-family : monospace; 14.66 +} 14.67 + 14.68 +.time { 14.69 + color : #999999; 14.70 + margin : 0px 0px 0px 0px; 14.71 + padding : 0px 10px 0px 0px; 14.72 + vertical-align : top; 14.73 + font-size : 80%; 14.74 + vertical-align : top; 14.75 + /* border-right : #9a9a9a solid thin; */ 14.76 +} 14.77 + 14.78 +.script { 14.79 + margin : 0px 0px 0px 0px; 14.80 + padding : 0px 0px 0px 0px; 14.81 + vertical-align : top; 14.82 +} 14.83 + 14.84 +.visibility_form { 14.85 + color : #9a9a9a; 14.86 + background : #e7e7e7; 14.87 + margin : 0px 0px 0px 0px; 14.88 + padding : 0px 0px 0px 0px; 14.89 + vertical-align : top; 14.90 + font-size : 80%; 14.91 + font-family : sans-serif; 14.92 +}
15.1 Binary file share/opennet.ico has changed
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/share/ug.xsl Sun May 22 16:29:55 2005 +0300 16.3 @@ -0,0 +1,41 @@ 16.4 +<?xml version="1.0" encoding="UTF-8"?> 16.5 + 16.6 +<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 16.7 + 16.8 +<xsl:output method="html" 16.9 + encoding="UTF-8" 16.10 + indent="yes"/> 16.11 + 16.12 +<!-- 16.13 +XSLT ug TO docbook 16.14 +Igor Chubin, 16.15 +Wed Dec 29 17:23:43 EET 2004 16.16 +--> 16.17 + 16.18 + 16.19 +<xsl:template match='script'> 16.20 +<sect1> 16.21 + <xsl:apply-templates/> 16.22 +</sect1> 16.23 +</xsl:template> 16.24 + 16.25 +<xsl:template match="action"> 16.26 +<screen role="command"><xsl:text> 16.27 +</xsl:text> 16.28 + <emphasis role="cline"><xsl:value-of select="line/prompt"/> 16.29 + <xsl:value-of select="line/command"/></emphasis> 16.30 + <xsl:value-of select="output"/> 16.31 +</screen> 16.32 + <xsl:apply-templates select="diff"/> 16.33 +</xsl:template> 16.34 + 16.35 +<xsl:template match="diff"><xsl:text> 16.36 +</xsl:text> 16.37 +<screen role="diff"> 16.38 + <xsl:value-of select="."/> 16.39 +</screen> 16.40 +</xsl:template> 16.41 + 16.42 + 16.43 +</xsl:stylesheet> 16.44 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/taillast.pl Sun May 22 16:29:55 2005 +0300 17.3 @@ -0,0 +1,8 @@ 17.4 +#!/usr/bin/perl 17.5 + 17.6 +for $d (@ARGV) { 17.7 + push @d, glob("$d/*"); 17.8 +} 17.9 +@{f} = sort { (stat(${a}))[9] <=> (stat(${b}))[9] } (@d); 17.10 +print "tail -f ${f[$#f]}\n"; 17.11 +__END__