# HG changeset patch
# User devi
# Date 1131355489 -7200
# Node ID 098664cf339c4cf7874688843d14af469fcdde81
# Parent  916661a893356fe3a1c4a4aa8c837eca4b85bd17
Выполнены шаги 4,5 в плане N05 по построению распределённой системы lilalo.
Шаг <6> в настоящее время не является необходимым.


Введено понятие сеанса.
Сеансом считается процедура работы с системой, начинающаяся с регистрации
в ней и зазаканчивающаяся разрегистрацией, и сопровождающаяся ведением одного
файла скрипта.
Одновременно с созданием скрипта (.script) создаётся соответствующий ему
файл с информацией о сеансе (.info).
Каждый сеанс имеет уникальный в пределах хоста идентификатор,
~local_session_id~, который впоследствии позволяет определить,
какие команды относятся к какому сеансу.

Добавлен backend-сервер, который получает данные от агентов и записывает
из в backend (в настойщий момент - в XML-файл).
Данные передаются по tcp-соединениям.
(Одновременно может работать несколько серверов.
Блокировка файла при записи пока что не выполняется ОСТОРОЖНО!!!!!!)

Агент периодически пытается отправить backend-серверу содержимое своего кэш-файла,
и если ему это удаётся, кэш файл очищается -- данные теперь хранятся в backend'е.

Взаимодействие агентов, backend-сервера и frontend'а
сейчас выполнеятся так:


          +-------+
          |       |
          | cache |
          |       |
          +-^---+-+
            |   |
	    . ^ v            . ^^ .      +---------+      . ^^ .
	  /       \  tcp   /        \    |         |    /        \  CGI
	 (  agent  )----->( backend- )-->| backend |-->( frontend )----->
	  \       /        \ сервер /    |         |    \        /
	    ' . '            ' .. '      +---------+      ' .. '
              ^
              |
         +----+----+
         |         |
         |*.script |
         | *.info  |
         |         |
         +---------+

l3-frontend:
	Теперь может выдавать результат работы на стандартный поток вывода.
	Вместо имени файла нужно указать символ -

Добавлены файлы:

	l3-backend	-	backend-сервер
	l3-cgi		-	CGI-обвязка для l3-frontend'а

Новые конфигурационные параметры:
	frontend_css		Путь к файлу CSS, используемому в HTML-странице, которую генерирует frontend
	frontend_google_ico	Путь к иконке google
	frontend_linux_ico	Путь к иконке linux
	frontend_freebsd_ico	Путь к иконке freebsd
	frontend_opennet_ico	Путь к иконке opennet
	frontend_local_ico	Путь к иконке локальной документации

	backend_address		IP-адрес интерфейса, на котором работает backend-сервер
	backend_port		Порт, который слушает backend-сервер
	backend_pidfile		Путь к файлу, который хранит идентификатор процесса backend-сервера
	backend_datafile	Путь к файлу хранилищу (файлу backend)

diff -r 916661a89335 -r 098664cf339c l3-agent
--- a/l3-agent	Thu Nov 03 17:53:03 2005 +0200
+++ b/l3-agent	Mon Nov 07 11:24:49 2005 +0200
@@ -10,6 +10,7 @@
 use Text::Iconv;
 use Data::Dumper;
 use Time::Local 'timelocal_nocheck';
+use IO::Socket;
 
 use lib ".";
 use l3config;
@@ -18,6 +19,7 @@
 our @Command_Lines;
 our @Command_Lines_Index;
 our @Diffs;
+our %Sessions;
 
 our %Commands_Stat;		# Statistics about commands usage
 our %Files_Stat;		# Statistics about commands usage
@@ -44,7 +46,7 @@
 
 sub save_cache_stat;
 sub load_cache_stat;
-
+sub print_session;
 
 sub load_diff_files
 {
@@ -224,22 +226,50 @@
 		
 	print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/;
 
-	my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>;
 	my $file;
-	my $files_number = $#lab_scripts;
-	my $ii = 0;
 	my $skip_info;
 
 	my $commandlines_loaded =0;
 	my $commandlines_processed =0;
 
+	my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>;
 	for $file (@lab_scripts){
-		#printf "\t%i %3.2f\n", $ii, (100*$ii++/$files_number) if $Config{"verbose"} =~ /y/;
 		
 		# Пропускаем файл, если он не изменялся со времени нашего предудущего прохода
 		my $size = (stat($file))[7];
 		next if ($Script_Files{$file} && $Script_Files{$file}->{size} && $Script_Files{$file}->{size} >= $size);
 
+
+		my $local_session_id;
+		# Начальное значение идентификатора текущего сеанса определяем из имени скрипта
+		# Впоследствии оно может быть уточнено
+		$file =~ /.*\/(.*)\.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 = <SESSION>;
+				close(SESSION);
+
+				for my $session_data ($data =~ m@<session>(.*?)</session>@sg) {
+					my %session;
+					while ($session_data =~ m@<([^>]*?)>(.*?)</\1>@sg) {
+						$session{$1} = $2;
+					}
+					$local_session_id = $session{"local_session_id"} if $session{"local_session_id"};
+					$Sessions{$session_id}=\%session;
+				}
+
+				#Загруженную информацию сразу же отправляем в поток
+				print_session($Config{cache}, $local_session_id);
+			}
+		}
+		
 		open (FILE, "$file");
 		binmode FILE;
 		
@@ -278,7 +308,8 @@
 
 =cut 
 
-ТАБЛИЦА КОМАНД
+Атрибуты cline
+Список полей, характеризующих командную строку
 
 	uid
 		Идентификатор пользователя
@@ -338,6 +369,7 @@
 		Текстовый комментарий к команде.
 		Может генерироваться из самого лога с помощью команд
 			#^ Комментарий  
+			#= Комментарий
 			#v Комментарий
 		в том случае, если для комментирования достаточно одной строки,
 		или с помощью команд
@@ -348,9 +380,11 @@
 		В последнем случае комментарий может содержать 
 		заголовок, абзацы и несложное форматирование.
 
-		Символ ^ или v после знака комментария # обозначает,
+		Символы ^, v или = после знака комментария # обозначает,
 		к какой команде относится комментарий:
-		к предыдущей (^) или последующей (v)
+		к предыдущей (^), последующей (v)
+		или это общий комментарий по тексту, не относящийся непосредственно
+		ни к одной из них (=)
 
 	err 
 		Код завершения командной строки
@@ -397,22 +431,22 @@
 		
 		1 - версия использующаяся в lilalo
 		
-	raw_file (*)
+	raw_file
 		Имя файла, в котором находится бинарное представление журнала.
 		Может содержать ключевое слово HERE, 
 		обозначающее что бинарное представление хранится
 		непосредственно в базе данных в атрибуте raw_data
 
-	raw_start (*)
+	raw_start
 		Начало блока командной строки в файле бинарного представления
 	
-	raw_output_start (*)
+	raw_output_start
 		Начало блока вывода
 	
-	raw_end (*)
+	raw_end
 		Конец блока командной строки в файле бинарного представления
 
-	raw_cline (*)
+	raw_cline
 		Необработанная командная строка (без приглашения) в бинарном виде
 	
 	raw_data (*)
@@ -425,11 +459,12 @@
 	
 	Информация о сеансах
 
-
+		(см. lm-install)
 
 
 =cut
 
+				$cl{"local_session_id"} = $local_session_id;
 				# Parse new command 
 				$cl{"uid"} = $3;
 				$cl{"euid"} = $cl{"uid"};	# Если в команде обнаружится sudo, euid поменяем на 0
@@ -751,6 +786,7 @@
 
 		# Начинаем вывод команды
 		print OUT "<command>\n";
+		print OUT "<local_session_id>",$cl->{session_id},"</local_session_id>\n";
 		print OUT "<time>",$cl->{time},"</time>\n";
 		print OUT "<raw_start>",$cl->{raw_start},"</raw_start>\n";
 		print OUT "<raw_output_start>",$cl->{raw_output_start},"</raw_output_start>\n";
@@ -789,7 +825,54 @@
 
 	#print OUT "</livelablog>\n";
 	close(OUT);
-	save_cache_stat();
+}
+
+sub print_session
+{
+	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 "<session>\n";
+	my %session = %{$Sessions{$local_session_id}};
+	for my $key (keys %session) {
+		print OUT "<$key>".$session{$key}."</$key>\n"
+	}
+	print OUT "</session>\n";
+	close(OUT);
+}
+
+sub send_cache
+{
+	`logger "step 0"`;
+	`logger "step 1"`;
+
+	# Если в кэше что-то накопилось, 
+	# попытаемся отправить это на сервер
+	#
+	my $cache_was_sent=0;
+	
+	if (open(CACHE, $Config{cache})) {
+		local $/;
+		my $cache = <CACHE>;
+		close(CACHE);
+
+		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;
 }
 
 sub save_cache_stat
@@ -805,6 +888,7 @@
 {
 	if (open (CACHE, "$Config{cache_stat}")) {
 		while(<CACHE>) {
+			chomp;
 			my ($f, $size, $tell) = split /\t/;
 			$Script_Files{$f}->{size} = $size;
 			$Script_Files{$f}->{tell} = $tell;
@@ -813,65 +897,6 @@
 	};
 }
 
-=cut
-sub print_command_lines2
-{
-	my $output_filename=$_[0];
-	open(OUT, ">", $output_filename)
-		or die "Can't open $output_filename for writing\n";
-
-
-	print OUT <<OUT;
-<log>
-OUT
-
-	my $cl;
-	for my $i (@Command_Lines_Index) {
-
-		
-		$cl = $Command_Lines[$i];
-
-
-# Printing out
-		print OUT <<OUT;
-	<command>
-		<day>$cl->{day}</day>
-		<hour>$cl->{hour}</hour>
-		<min>$cl->{min}</min>
-		<sec>$cl->{sec}</sec>
-		<tty>$cl->{tty}</tty>
-		<uid>$cl->{uid}</uid>
-		<euid>$cl->{euid}</euid>
-		<prompt>$cl->{prompt}</prompt>
-		<cline>$cl->{cline}</cline>
-		<status>$cl->{err}</cline>
-		<output>
-$cl->{output}</output>
-	</command>
-OUT
-	}
-
-	for my $diff (@Diffs) {
-
-		print OUT <<OUT;
-	<diff>
-		<path>$diff->{path}</path>
-		<uid>$diff->{uid}</uid>
-		<day>$diff->{day}</day>
-		<hour>$diff->{hour}</hour>
-		<min>$diff->{min}</min>
-		<sec>$diff->{sec}</sec>
-		<text>
-$diff->{text}</text>
-	</diff>
-OUT
-	}
-
-	print OUT <<OUT;
-</log>
-OUT
-}
-=cut
 
 main();
 
@@ -882,73 +907,85 @@
 
 sub main
 {
-$| = 1;
 
-init_variables();
-init_config();
+	$| = 1;
 
-for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) {
-	load_diff_files($lab_log);
-}
+	init_variables();
+	init_config();
 
-if ($Config{"mode"} ne "daemon") {
-	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 = <PIDFILE>;
-		close(PIDFILE);
-		if ( ! -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}. " : $!";
+	for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) {
+		load_diff_files($lab_log);
+	}
+
+	if ($Config{"mode"} ne "daemon") {
+
+=cut
+	В нормальном режиме работы нужно
+	считать скрипты, обработать их и записать
+	результат выполнения в результриующий файл.
+	После этого завершить работу.
+=cut
+		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 = <PIDFILE>;
+			close(PIDFILE);
+			if ( ! -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}. " : $!";
+			}
+			else {
+				print "l3-agent is already running\n";
+				exit(0);
+			}
 		}
-		else {
-			print "l3-agent is already running\n";
-			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);
+
+			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: $!";
+
+			$0 = $Config{"l3-agent"};
+			
+			$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
 		}
+		while (not $Killed) {
+			@Command_Lines = ();
+			@Command_Lines_Index = ();
+			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};
 	}
-	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);
-
-		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: $!";
-
-		$0 = $Config{"l3-agent"};
-		
-		$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
-	}
-	while (not $Killed) {
-		@Command_Lines = ();
-		@Command_Lines_Index = ();
-		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"});
-		}
-		sleep($Config{"daemon_sleep_interval"} || 1);
-	}
-	
-	unlink $Config{agent_pidfile};
-}
 
 }
 
diff -r 916661a89335 -r 098664cf339c l3-backend
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/l3-backend	Mon Nov 07 11:24:49 2005 +0200
@@ -0,0 +1,106 @@
+#!/usr/bin/perl
+
+use strict;
+use lib '.';
+use l3config;
+use IO::Socket;
+use POSIX qw(:sys_wait_h);
+
+sub main;
+
+main();
+
+sub REAPER {
+	1 until (-1 == waitpid(-1, WNOHANG));
+	$SIG{CHLD} = \&REAPER;
+}
+
+sub process_was_killed
+{
+	# Здесь должна быть красивая процедура 
+	# завершения демона
+	unlink $Config{backend_pidfile};
+	exit(0);
+}
+
+sub main {
+	init_config();
+
+
+	# Проверяем, возможно демон уже запущен
+	# Если он работает, просто завершаемся
+	if (open(PIDFILE, $Config{backend_pidfile})) {
+		my $pid = <PIDFILE>;
+		close(PIDFILE);
+		if ( ! -e "/proc/$pid" || !`grep $Config{"l3-backend"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`) {
+			print "Removing stale pidfile\n";
+			unlink $Config{backend_pidfile}
+				or die "Can't remove stale pidfile ". $Config{backend_pidfile}. " : $!";
+		}
+		else {
+			print "l3-backend is already running\n";
+			exit(0);
+		}
+	}
+
+	# Уходим в background, если необходимо
+	if ($Config{detach} =~ /^y/i) {
+		#$Config{verbose} = "no";
+		my $pid = fork;
+		exit if $pid;
+		die "Couldn't fork: $!" unless defined ($pid);
+
+		open(PIDFILE, ">", $Config{backend_pidfile})
+			or die "Can't open pidfile ". $Config{backend_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: $!"
+		}
+
+		POSIX::setsid()
+			or die "Can't start a new session: $!";
+
+		$0 = $Config{"l3-backend"};
+		
+		$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
+	}
+
+	# Открываем сетевой сокет и слушаем
+	my $server = IO::Socket::INET->new(
+			LocalPort 	=> $Config{backend_port},
+			Type		=> SOCK_STREAM,
+			Reuse		=> 1,
+			Listen		=> 10 );
+	
+	if (!$server) {
+		die "Couldn't bind to socket ".$Config{backend_port}."\n";
+	}
+
+	$SIG{CHLD} = 'IGNORE';
+
+	# При получении новых соединенений,
+	# порождаем дочерние процессы
+	while (my $client = $server->accept()) {
+		my $pid;
+		next if $pid = fork;
+		die "fork: $!" unless defined $pid;
+
+		# Это наш ответвлённый клиент
+		close($server);
+
+		# Считываем данные и передаём их в точку получения
+		open(OUT, ">>", $Config{"backend_datafile"});
+		select OUT; $|=1;
+		while(<$client>) {
+			print OUT $_;
+		}
+		close(OUT);
+	} 
+	continue {
+		# Наш родитель
+		close ($client);
+	}
+}
diff -r 916661a89335 -r 098664cf339c l3-cgi
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/l3-cgi	Mon Nov 07 11:24:49 2005 +0200
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use strict;
+use CGI qw(:standard);
+
+my $value = param('PARAM');
+
+print header(
+		-charset => "utf-8", 
+		);
+chdir("/home/devi/cvs/lilalo");
+open (FRONTEND, "./l3-frontend --output - |");
+while (<FRONTEND>) {
+	print;
+}
+close(FRONTEND);
+
diff -r 916661a89335 -r 098664cf339c l3-frontend
--- a/l3-frontend	Thu Nov 03 17:53:03 2005 +0200
+++ b/l3-frontend	Mon Nov 07 11:24:49 2005 +0200
@@ -29,7 +29,7 @@
 	init_variables();
 	init_config();
 
-	load_command_lines_from_xml($Config{"cache"});
+	load_command_lines_from_xml($Config{"backend_datafile"});
 	print_command_lines($Config{"output"});
 }
 
@@ -334,7 +334,7 @@
 	<html>
 	<head>
 	<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
-	<link rel='stylesheet' href='labmaker.css' type='text/css'/>
+	<link rel='stylesheet' href='$Config{frontend_css}' type='text/css'/>
 	</head>
 	<body>
 	<script>
@@ -372,10 +372,15 @@
 
 	$Result{"header"} .= "</form></td></tr></table>\n";
 
-	open(OUT, ">", $output_filename)
-		or die "Can't open $output_filename for writing\n";
-	print OUT $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
-	close(OUT);
+	if ($output_filename eq "-") {
+		print $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
+	}
+	else {
+		open(OUT, ">", $output_filename)
+			or die "Can't open $output_filename for writing\n";
+		print OUT $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
+		close(OUT);
+	}
 }
 
 
diff -r 916661a89335 -r 098664cf339c l3config.pm
--- a/l3config.pm	Thu Nov 03 17:53:03 2005 +0200
+++ b/l3config.pm	Mon Nov 07 11:24:49 2005 +0200
@@ -46,6 +46,12 @@
 		#"output"			=>	"report.xml",
 		"output_mask"			=>	"INDEX",
 		"output_format"			=>	"html",
+		"frontend_css"			=>	"/l3/l3.css",
+		"frontend_google_ico"		=>	"/l3/google.ico",
+		"frontend_linux_ico"		=>	"/l3/linux.ico",
+		"frontend_freebsd_ico"		=>	"/l3/freebsd.ico",
+		"frontend_opennet_ico"		=>	"/l3/opennet.ico",
+		"frontend_local_ico"		=>	"/l3/freebsd.ico",
 
 		"signature"			=>	"#lm:",
 		"from"				=>	"",
@@ -62,7 +68,13 @@
 		"detach"			=>	"yes",
 		"agent_pidfile"			=> 	"$ENV{HOME}/.labmaker/l3-agent.pid",
 
+		"backend_address"		=>	"127.0.0.1",
+		"backend_port"			=> 	"18030",
+		"backend_pidfile"		=> 	"/tmp/l3-backend.pid",
+		"backend_datafile"		=> 	"/tmp/backend.xml",
+
 		"l3-agent"			=>	"l3-agent", 
+		"l3-backend"			=>	"l3-backend", 
 		
 		"course-name" => "", 
 		"course-code" => "", 
diff -r 916661a89335 -r 098664cf339c lm-install
--- a/lm-install	Thu Nov 03 17:53:03 2005 +0200
+++ b/lm-install	Mon Nov 07 11:24:49 2005 +0200
@@ -68,31 +68,54 @@
 		| sed '/LabMaker:START/,/LabMaker:END/ d' \
 		> $temp_file
 	cat <<'LM_bash_profile' >> $temp_file
-	# LabMaker:START
-	TTY=`tty` 
+# LabMaker:START
+LMHOME=~/.labmaker
+mkdir -p ${LMHOME}
 
-	uname -a | grep -qi bsd && bsd=yes
+uname -a | grep -qi bsd && bsd=yes
+flush="-f"			#linux
+[ -n "$bsd" ] && flush="-t 0"	#freebsd
 
-	this_term=`w | grep "${TTY##/dev/}" | awk '{print $8;}'`
-	# freeBSD: 
-	[ -n "$bsd" ] && this_term=`w | grep "${TTY##/dev/tty}" | awk '{print $6;}'`
+tty=`tty` 
+this_term=`w | grep "${tty##/dev/}" | awk '{print $8;}'`
+# freeBSD: 
+[ -n "$bsd" ] && this_term=`w | grep "${tty##/dev/tty}" | awk '{print $6;}'`
 
 
+export PS1='\[`	
+	a="$?";
+	HIDDEN=$([ "$a" = 0 ] || echo -n ^"$a")$(echo -n _${UID}_)$(echo -n _$$_)$(date\
+		+"%j$(cat ${LMHOME}/lab 2>/dev/null) %H:%M:%S");
+	echo $HIDDEN`\033[50D\033[K\][\u@\h:\W]\$ '
 
-	LMHOME=~/.labmaker
-	mkdir -p ${LMHOME}
-	flush="-f"	#linux
-	[ -n "$bsd" ] && flush="-t 0"	#freebsd
-	export PS1='\[`	a="$?";
-		HIDDEN=$([ "$a" = 0 ] || echo -n ^"$a")$(echo -n _${UID}_)$(echo -n _$$_)$(date\
-			+"%j$(cat ~/.labmaker/lab 2>/dev/null) %H:%M:%S");
-		echo $HIDDEN`\033[50D\033[K\][\u@\h:\W]\$ '
+if [ -n "$this_term" ] && echo $this_term | grep -qv script
+then	
+	session_id=${tty##*/}-$$
+	parent=`cat /proc/$PPID/cmdline 2> /dev/null`
+	system=`uname -rs`
+	login_from=`who | grep "${tty##/dev/}" | awk '{print $6;}' | tr -d '()'`
+	[ -n "$bsd" ] && login_from="" #FIXME!
+	start_time=`date +%s`
+	hostname=`hostname -f`
 
-	if [ -n "$this_term" ] && echo $this_term | grep -qv script
-	then	
-		exec script $flush -q $LMHOME/${TTY##*/}-$$.script
-	fi
-	# LabMaker:END 
+	cat <<INFO > $LMHOME/${session_id}.info
+<session>
+<session_id>$session_id</session_id>
+<hostname>$hostname</hostname>
+<user>$USER</user>
+<login_from>$login_from</login_from>
+<tty>$tty</tty>
+<system>$system</system>
+<parent>$parent</parent>
+<ppid>$PPID</ppid>
+<pid>$$</pid>
+<start_time>$start_time</start_time>
+</session>
+INFO
+
+	exec script $flush -q $LMHOME/${session_id}.script
+fi
+# LabMaker:END 
 LM_bash_profile
 	cat $temp_file > $profile
 	rm $temp_file