#!/usr/bin/perl
# sysinfo-dg 1.1 - sysinfo@dgl.cx - http://dgl.cx/
# Released under the GNU GPL v2 or later
#This script is mostly my own work but some ideas where taken from /sinfo by
#Laurens Buhler and Alain van Acker. Please leave this credit in the script and
#if you edit it and think the change is worthwhile tell me and i may add it into
#
#Modified by DocTrax anno 2004
#Fixed some errors and added version support for Kanotix
#Do never remove this announcement and the link to my website, as described in GNU GPL v2!
#

package SYSINFODG;
use strict;
use vars qw/$colour $graphs $graphs2 $colour2 $style/;
my $scriptname = "sysinfo-dg";
my $scriptversion = "1.1-DocTrax_1.47";
IRC::register( $scriptname." ".$scriptversion , $scriptversion , "" , "");
IRC::add_command_handler("sysinfo", "SYSINFODG::sysinfo");
IRC::add_command_handler("sysinfohelpen", "SYSINFODG::sysinfohelpen");
IRC::add_command_handler("sysinfohelp", "SYSINFODG::sysinfohelp");
IRC::add_command_handler("sysinfoself", "SYSINFODG::sysinfoself");
IRC::add_command_handler("si", "SYSINFODG::sysinfo");
IRC::add_command_handler("sis", "SYSINFODG::sysinfoself");
IRC::print( chr(3) . "2,8" . $scriptname . "\t" . $scriptversion . " is loaded ..." . chr(3)) unless $pressure::COMMAND==1;
IRC::print( chr(3) . "2,8Der Befehl /sysinfohelp schreibt die deutsche Hilfe." . chr(3)) unless $pressure::COMMAND==1;
IRC::print( chr(3) . "2,8Type /sysinfohelpen to get English help!" . chr(3)) unless $pressure::COMMAND==1;
IRC::print( chr(3) . "2,8This script is based on sysinfo-dg 1.1 and modified by DocTrax http://www.hintzundkunz.cjb.net/ " . chr(3)) unless $pressure::COMMAND==1;

sub sysinfohelpen
{
	IRC::print( chr(3) . "2,8=== Some examples for using this script ===" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo\t-> the plain command to print the sysinfo" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo -cg\t-> the option c means color and g means that graphs are being printed" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo os\t-> prints only the operating system information" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo os cpu\t-> prints the operating system information and the cpu information" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo full\t-> prints all available information" . chr(3));
	IRC::print( chr(3) . "2,8/si\t-> is an alias for /sysinfo" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfoself\t-> can be used like /sysinfo but prints the info non public." . chr(3));
	IRC::print( chr(3) . "2,8/sis\t-> is an alias for /sysinfoself" . chr(3));
	IRC::print( chr(3) . "2,8See the README file shipped with this script fpr further help." . chr(3));
	IRC::print( chr(3) . "2,8Report bugs at http://hintzundkunz.cjb.net to DocTrax-sysinfo -- Have fun!" . chr(3));
	return 1;
}

sub sysinfohelp
{
	IRC::print( chr(3) . "2,8=== Einige Beispiele zur Benutzung: ===" . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo\t-> Das ist das einfachste Kommando." . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo -cg\t-> Man kann die Optionen c f�r Farbe und g f�r Grafiken hinzuf�gen." . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo os\t-> Das schreibt nur die Betriebssystemversion." . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo os cpu\t-> Das schreibt die Betriebssystemversion und die Prozessorinfo." . chr(3));
	IRC::print( chr(3) . "2,8/sysinfo full\t-> Das schreibt alles." . chr(3));
	IRC::print( chr(3) . "2,8/si\t-> Das ist das selbe wie /sysinfo." . chr(3));
	IRC::print( chr(3) . "2,8/sysinfoself\t-> Das wird wie /sysinfo benutzt, schreibt aber nicht �ffentlich." . chr(3));
	IRC::print( chr(3) . "2,8/sis\t-> Das ist das selbe wie /sysinfoself." . chr(3));
	IRC::print( chr(3) . "2,8Noch mehr Informationen stehen in der README Datei." . chr(3));
	IRC::print( chr(3) . "2,8Fehler kann man auf http://hintzundkunz.cjb.net an DocTrax-sysinfo melden. -- Viel Spass!" . chr(3));
	return 1;
}

sub sysinfo
{
	my $tmp = &tprocessing(@_);
	IRC::command $tmp if ($tmp);
	return 1;
}

sub sysinfoself
{
	my $tmp = &tprocessing(@_);
	IRC::print( $tmp ) if ($tmp);
	return 1;
}

sub tprocessing
{
	($colour,$graphs,$graphs2,$colour2,$style) = undef;
	my @options = split(/ /,$_[0]);
	my $netkeys= netkeys();
	$netkeys =~ s/\s{2,}/ /;
	$netkeys =~ s/\s$//;
	($colour,$graphs,$graphs2,$colour2,$style) = &parseoptions( $netkeys , @options );
	my %info = &infocreate();
	my $tmp;
	for(split(/ /,$style))
	{
		$tmp .= &ircbit( $_ , $info{$_} ) . " | ";
	}
      $tmp .= chr(3) . $colour2. "\[" .chr(3) .$scriptname." ".$scriptversion .chr(3) . $colour2 . "\]" . chr(3);
	$tmp =~ s/ $//;
	return $tmp;
}

sub parseoptions
{
	my($netkeys,@options) = @_;
	($colour,$graphs,$graphs2,$colour2,$style) = undef;
	my $tmp = shift(@options) if $options[0] =~ /^\-/;
	my $style = "";
	$tmp =~ s/^\-//;
	for(split //,$tmp)
	{
		if($_ eq "c")
		{
			$tmp =~ /c(\d+)/;
			$colour = $1;
			if(!$colour)
			{
				$colour = 12;
			}
		}
		elsif($_ eq "g")
		{
			$tmp =~ /g(\d+)/;
			$graphs = $1;
			if(!$graphs)
			{
				$graphs = 8;
			}
		}
		elsif($_ eq "G")
		{
			$tmp =~ /G(\d+)/;
			$graphs2 = $1;
		}
		elsif($_ eq "C")
		{
			$tmp =~ /C(\d+)/;
			$colour2 = $1;
		}
	}
	if(!defined $colour2 && defined $colour)
	{
		$colour2 = 3;
	}
	if(defined $graphs && !defined $graphs2)
	{
		$graphs2 = 8;
	}
	if($options[1])
	{
		foreach (@options)
		{
			if ( $_ =~ m/host|os|up|cpu|chipset|cache|mem|users|load|procs|swap|disk|video|sound|tvcard|opengl|ethernet|xchat/ )
			{
				$style = join(" ",@options);
			}
			if ( ( $netkeys =~ m/$_/i ) && ( $_ =~ m/^\w+$/i ) )
			{
				$style .= $_ . " ";
			}
		}
		if (! $style)
		{
			$style = "os up cpu chipset video opengl xchat";
		}
	}
	elsif($options[0])
	{
		if($options[0] eq "std")
		{
			$style = "os up cpu batt chipset mem video opengl xchat";
		}
		elsif($options[0] eq "bigger")
		{
			$style = "os up cpu chipset cache mem load procs disk video opengl xchat";
		}
		elsif($options[0] eq "full")
		{
			$style = "host os up cpu batt chipset cache mem users load procs swap disk video opengl sound tvcard xchat ethernet" . $netkeys;
		}
		elsif($options[0] eq "net")
		{
			$style = "ethernet". $netkeys;
		}
		elsif($options[0] eq "uptime")
		{
			$style = "os up";
		}
		elsif($options[0] eq "use")
		{
			$style = "mem swap disk";
		}
		elsif($options[0] eq "host")
		{
			$style = "host";
		}
		elsif($options[0] eq "up")
		{
			$style = "up";
		}
		elsif($options[0] eq "os")
		{
			$style = "os";
		}
		elsif($options[0] eq "mem")
		{
			$style = "mem";
		}
		elsif($options[0] eq "cpu")
		{
			$style = "cpu";
		}
		elsif($options[0] eq "disk")
		{
			$style = "disk";
		}
		elsif($options[0] eq "video")
		{
			$style = "video";
		}
		elsif($options[0] eq "cache")
		{
			$style = "cache";
		}
		elsif($options[0] eq "users")
		{
			$style = "users";
		}
		elsif($options[0] eq "swap")
		{
			$style = "swap";
		}
		elsif($options[0] eq "procs")
		{
			$style = "procs";
		}
		elsif($options[0] eq "ethernet")
		{
			$style = "ethernet";
		}
		elsif($options[0] eq "chipset")
		{
			$style = "chipset";
		}
		elsif($options[0] eq "tvcard")
		{
			$style = "tvcard";
		}
		elsif($options[0] eq "sound")
		{
			$style = "sound";
		}
		elsif($options[0] eq "xchat")
		{
			$style = "xchat";
		}
		elsif($options[0] eq "batt")
		{
			$style = "batt";
		}
		elsif($options[0] eq "opengl")
		{
			$style = "opengl";
		}
		else
		{
			$style = "os up cpu chipset video opengl xchat batt";
		}
		if ( ( $netkeys =~ m/$options[0]/i ) && ( $options[0] =~ m/^\w+$/i ) )
		{
			$style = $options[0];
		}
	}
	else
	{
		$style = "os up cpu chipset video opengl xchat";
	}
	return($colour,$graphs,$graphs2,$colour2,$style);
}

sub netkeys
{
	my %netinfo = &netinfo();
	my $netkeys = " ";
	for(keys %netinfo)
	{
		$netkeys .= $_ . " " ;
	}
	return $netkeys;
}

sub openglinfo
{
	my($OpenGLVendor,$OpenGLcard,$OpenGLversion);
	for (`glxinfo`)
	{
		if($_ =~ m/^.*OpenGL\svendor\sstring:\s(.+)$/i)
		{
			$OpenGLVendor = $1;
		}
		elsif($_ =~ m/^.*OpenGL\srenderer\sstring:\s(.+)$/i)
		{
			$OpenGLcard = $1;
		}
		elsif($_ =~ m/^.*OpenGL\sversion\sstring:\s(.+)$/i)
		{
			$OpenGLversion = $1;
		}
	}
	return ($OpenGLVendor,$OpenGLcard,$OpenGLversion);
}

sub infocreate
{
	my($hostname,$uname,$procs,$thermal,$battery) = &basicinfo();
	my($distro) = &distro();
	my($uptime,$users,$loadavg) = &uptime();
	my($memsize,$memfree) = &meminfo();
	my($swapsize,$swapfree) = &swapinfo();
	my($cpumodel,$cpumhz,$cpucache,$bogomips) = &cpuinfo();
	my %netinfo = &netinfo();
	my($disktotal,$diskused,$hddtype) = &df();
	my($videocard,$ethernet,$chipset,$tvcard,$sound) = &pciinfo();
	my($OpenGLVendor,$OpenGLcard,$OpenGLversion) = &openglinfo();
	my($screenres,$screendepth);
	($screenres,$screendepth) = &screenres() if $ENV{DISPLAY};
	my $xchatversion = "Version: ".&xchat();
	my %infos = (
		'os' => "$uname - $distro",
		'up' => $uptime,
		'cpu' => $cpumodel.", ". $cpumhz ." MHz (".$bogomips." bogomips)",
		'cache' => $cpucache,
		'mem' => sprintf("%.2f", ($memsize-$memfree)) . "/". sprintf("%.2f", $memsize)." MB (" . &percent(($memsize-$memfree),$memsize) . ")",
		'host' => $hostname,
		'users' => $users,
		'load' => $loadavg,
		'procs' => $procs,
		'swap' => sprintf("%.2f", ($swapsize-$swapfree)) . "/". sprintf("%.2f", $swapsize) ." MB (" . &percent(($swapsize-$swapfree),$swapsize) . ")",
		'disk' => sprintf("%.2f", $diskused)."/".sprintf("%.2f", $disktotal)." MB (" . &percent($diskused,$disktotal) . ") (".$hddtype.")",
		'video' => $videocard." at ".$screenres." (".$screendepth." bits)",
		'ethernet' => $ethernet,
		'chipset' => $chipset,
		'tvcard' => $tvcard,
		'sound' => $sound,
		'xchat' => $xchatversion,
		'opengl' => $OpenGLcard. ' powered by ' . $OpenGLVendor .' with driver '.$OpenGLversion
	);
	$infos{'cpu'} .= $thermal if ($thermal);
	$infos{'batt'} = $battery if ($battery);
	my $netkeys = " ";
	for(keys %netinfo)
	{
		$infos{$_}	= "in: ". $netinfo{$_}{in} ." MB, out: ". $netinfo{$_}{out} ." MB";
		$netkeys .= $_ . " " ;
	}
	return %infos ;
}

sub ircbit
{
	my($name,$text) = @_;
	if ($text)
	{
		if($colour)
		{
			$name = " " . $name if $name =~ /^\d/;
			$text = " " . $text if $text =~ /^\d/;
			return chr(3) . $colour . $name . chr(3) . $colour2. "\[" .chr(3) . $text .chr(3) . $colour2 . "\]" . chr(3);
		}
		else
		{
			return $name . "\[" . $text ."\]";
		}
	}
	else
	{
		return undef;
	}
}

sub percent
{
	my $percent = 0.00;
	if ( ($_[1] == 0.00) && ($_[0] == 0) )
	{
		$percent = 0.00;
	}
	else
	{
		if ( ($_[1] == 0.00) && ($_[0] != 0) )
		{
			$percent = 100.00;
		}
		else
		{
			$percent = sprintf("%.1f",(($_[0]/$_[1] )*100));
		}
	}
	if($graphs)
	{
		my $tmp = "[";
		for(1..10)
		{
			if($_ > sprintf("%.0f",$percent / 10))
			{
				$tmp .= "-" if !defined $colour;
				$tmp .= chr(3) . $graphs2."-" if defined $colour;
			}
			else
			{
				$tmp .= "|" if !defined $colour;
				$tmp .= chr(3) . $graphs."|" if defined $colour;
			}
		}
		$tmp .= chr(3) . "]";
		return $percent . "% " . $tmp;
	}
	return $percent . "%";
}

sub uptime
{
	my $uptimeinfo = `uptime`;
	if ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up\s+(\d+)\s+day.?\W\s+(\d+):(\d+)\W\s+(\d+)\s+\w+\W\s+\w+\s+\w+\W\s+(\d+).(\d+)/igx)
	{
		return($2 . " days, " . $3 . " hours, " . $4 . " minutes", $5, "$6.$7");
	}
	elsif ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up+\s+(\d+):(\d+)\W\s+(\d+)\s+\w+\W\s+\w+\s+\w+\W\s+(\d+).(\d+)/igx)
	{
		return($2. " hours, " . $3 . " minutes", $4, "$5.$6");
	}
	elsif ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up\s+(\d+)\s+day.?\W\s+(\d+)\s+min\W\s+(\d+)\s+\w+\W\s+\w+\s+\w+\W\s+(\d+).(\d+)/igx)
	{
		return($2 ." days, ". $3 . " minutes", $4, "$5.$6");
	}
	elsif ($uptimeinfo =~ /^\s+(\d+:\d+\w+|\d+:\d+:\d+)\s+up+\s+(\d+)\s+min\W\s+(\d+)\s+\w+\W\s+\w+\s+\w+\W\s+(\d+).(\d+)/igx)
	{
		return($2 . " minutes", $3, "$4.$5");
	}
	return undef;
}

sub meminfo
{
	my($memsize,$memfree);
	open(MEMINFO, "/proc/meminfo") or return undef;
	while(<MEMINFO>)
	{
		chomp;
		if(/^MemTotal:\s+(\d+)/)
		{
			$memsize = sprintf("%.2f",$1/1024);
		}
		elsif(/^MemFree:\s+(\d+)/)
		{
			$memfree = sprintf("%.2f",$1/1024);
		}
	}
	close(MEMINFO);
	return($memsize,$memfree);
}

sub swapinfo
{
	my($swapsize,$swapused);
	open(SWAPINFO, "/proc/swaps");
	while(<SWAPINFO>)
	{
		chomp;
		next if !/^\//;
		/\S+\s+\S+\s+(\S+)\s+(\S+)/;
		$swapsize += $1;
		$swapused += $2;
	}
	close(SWAPINFO);
	my $swapfree = sprintf("%.2f",($swapsize - $swapused) / 1024);
	$swapsize = sprintf("%.2f", $swapsize / 1024);
	return($swapsize,$swapfree);
}

sub netinfo
{
	my %netinfo;
	open(NETINFO, "/proc/net/dev") or return undef;
	while(<NETINFO>)
	{
		if ( $_ =~ m/^.*?([a-z0-9]+)\:\s*(\d+)\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d+\s*\d*\s*(\d+)\s*[\d\s]*$/i )
		{
			$netinfo{$1}{in} = sprintf("%.2f", $2 / 1048576) unless ( ($1 =~ m/sit/i) || ($1 =~ m/lo/i) );
			$netinfo{$1}{out} = sprintf("%.2f", $3 / 1048576)  unless ( ($1 =~ m/sit/i) || ($1 =~ m/lo/i) );
		}
	}
	close(NETINFO);
	return %netinfo;
}

sub distro
{
	my $distro;
	if(-f "/etc/coas")
	{
		$distro = firstline("/etc/coas");
	}
	elsif(-f "/etc/environment.corel")
	{
		$distro = firstline("/etc/environment.corel");
	}
	elsif((-f "/etc/debian_version") && (-f "/etc/lsb-release"))
	{
		$distro = $distro = "Debian ".firstline("/etc/debian_version")." - ".lsbrelease("/etc/lsb-release")." ( http://www.ubuntu.com )";
	}
	elsif( (-f "/etc/debian_version") && (-f "/etc/kanotix-version") )
	{
		$distro = "Debian ".firstline("/etc/debian_version")." - Kanotix ".firstline("/etc/kanotix-version")." ( http://www.kanotix.com )";
	}
	elsif( (-f "/etc/debian_version") && (-f "/etc/sidux-version") )
	{
		$distro = "Debian ".firstline("/etc/debian_version")." - Sidux ".firstline("/etc/sidux-version")." ( http://www.sidux.com )";
	}
	elsif ( (-f "/etc/knoppix-version") && (-f "/etc/debian_version") )
	{
		$distro = "Debian ".firstline("/etc/debian_version")." - ".firstline("/etc/knoppix-version")." ( http://www.knopper.net )";
	}
	elsif( (-f "/etc/debian_version") && !(-f "/etc/kanotix-version") && !(-f "/etc/knoppix-version")  )
	{
		$distro = "Debian ".firstline("/etc/debian_version");
	}
	elsif(-f "/etc/mandrake-release")
	{
		$distro = firstline("/etc/mandrake-release");
	}
	elsif(-f "/etc/SuSE-release")
	{
		$distro = firstline("/etc/SuSE-release");
	}
	elsif(-f "/etc/turbolinux-release")
	{
		$distro = firstline("/etc/turbolinux-release");
	}
	elsif(-f "/etc/slackware-release")
	{
		$distro = firstline("/etc/slackware-release");
	}
	elsif(-f "/etc/redhat-release")
	{
		$distro = firstline("/etc/redhat-release");
	}
	elsif(-f "/etc/gentoo-release")
	{
		$distro = firstline("/etc/gentoo-release");
	}
	elsif(-f "/etc/gentoo-release")
	{
		$distro = firstline("/etc/zenwalk-version");
	}
	else
	{
		$distro = 'Unknown Distro';
	}
	return $distro;
}

sub xchat
{
	my $version = IRC::get_info(0);
	return $version;
}

sub df
{
	my($disktotal,$diskused,$mainhd);
	for(`df`)
	{
		chomp;
		next if !/^\/dev\/\S+/;
		next if /(cd|cdrom|fd|floppy)/;
		next if /^df/;
		/^(\S+)\s+(\S+)\s+(\S+)/;
		$mainhd = $1 if !defined $mainhd;
		next if not defined $1 or not defined $2;
		$disktotal += $2;
		$diskused += $3;
	}
	$disktotal = sprintf("%.2f",$disktotal / 1024);
	$diskused = sprintf("%.2f",$diskused / 1024);
	$mainhd =~ s/\/dev\/([a-z]+)\d+/$1/;
	my $hddtype = firstline("/proc/ide/$mainhd/model");
	return($disktotal,$diskused,$hddtype);
}

sub basicinfo
{
	my ($hostname,$sysinfo,$procs,$thermal,$battery);
	chomp($hostname = `hostname`);
	chomp($sysinfo = `uname -sr`);
	$thermal=0;
	for (`mbmon -c1`)
	{
		if ( $_ =~ m/^Temp.=\s+(\S+),\s+(\S+),\s+(\S+);.*$/ )
		{
			my $g = 0.0;
			$g = sprintf("%.1f",$1) if ($g < sprintf("%.1f",$1));
			$g = sprintf("%.1f",$2) if ($g < sprintf("%.1f",$2));
			$g = sprintf("%.1f",$3) if ($g < sprintf("%.1f",$3));
			$thermal = " at ". $g . "�C";
		}
	}
	if (! $thermal )
	{
		chomp($thermal = `acpi --thermal`);
		if ( $thermal =~ m/^.*?Thermal 1: ok,\s(.*?)\sdegrees\s.*$/ )
		{
			$thermal = " at ". $1 . "�C";
		}
		else
		{
			$thermal = 0;
		}
	}
	chomp($battery = `acpi --battery`);
	if ( $battery =~ m/^.*?Battery 1: / )
	{
		$battery =~ s/^.*?Battery 1: //;
	}
	else
	{
		$battery = 0;
	}
	opendir(PROC, "/proc");
	$procs = scalar grep(/^\d/,readdir PROC);
	return($hostname,$sysinfo,$procs,$thermal,$battery);
}

sub cpuinfo
{
	my($cpumodel,$cpusmp,$cpumhz,$cpucache,$bogomips);
	open(CPUINFO, "/proc/cpuinfo") or return undef;
	while(<CPUINFO>)
	{
		if(/^model name\s+\:\s+(.*?)$/)
		{
			if(defined $cpumodel)
			{
				if(defined $cpusmp)
				{
					$cpusmp++;
				}
				else
				{
					$cpusmp=2;
				}
			}
			else
			{
				$cpumodel = $1;
			}
		}
		elsif(/^cpu MHz\s+:\s+([\d\.]*)/)
		{
			$cpumhz = $1;
		}
		elsif(/^cache size\s+:\s+(.*)/)
		{
			$cpucache = $1;
		}
		elsif(/^bogomips\s+:\s+([\d\.]*)/)
		{
			$bogomips += $1;
		}
	}
	$cpumodel .= " SMP ($cpusmp processors)" if defined $cpusmp;
	return($cpumodel,$cpumhz,$cpucache,$bogomips);
}

sub pciinfo
{
	my($videocard,$ethernet,$chipset,$tvcard,$sound);
	#open(PCI, "/proc/pci") or return undef;
	for(`lspci`)
	{
		chomp;
		if(/VGA compatible controller: (.*?)$/)
		{
			$videocard = $1;
		}
		elsif(/Ethernet controller: (.*?)$/)
		{
			$ethernet = $1;
		}
		elsif(/Host bridge: (.*?)$/)
		{
			$chipset = $1;
		}
		elsif(/Multimedia video controller: (.*?)$/)
		{
			$tvcard = $1;
		}
		elsif(/Multimedia audio controller: (.*?)$/)
		{
			$sound = $1;
		}
	}
	close(PCI);
	return($videocard,$ethernet,$chipset,$tvcard,$sound);
}

sub screenres
{
	my ($res,$depth);
	for(`xdpyinfo`)
	{
		if(/\s+dimensions:\s+(\S+)/)
		{
			$res = $1;
		}
		elsif(/\s+depth:\s+(\S+)/)
		{
			$depth = $1;
		}
	}
	return($res,$depth);
}

sub firstline
{
	my $file = shift;
	open(FILE, "$file") or return undef;
	chomp(my $line = <FILE>);
	close(FILE);
	return $line;
}

sub lsbrelease
{
	my ($version,$codename,$dist);
	my $file = shift;
	open(FILE, "$file") or return undef;
	while(<FILE>)
	{
		chomp;
		if(/^DISTRIB_RELEASE=(.*)$/i)
		{
			$version = $1;
		}
		elsif(/^DISTRIB_CODENAME=(.*)/i)
		{
			$codename = $1;
		}
		elsif(/^DISTRIB_ID=(.*)/i)
		{
			$dist = $1;
		}
	}
	close(FILE);
	return $dist . " " . $version. " " . $codename;
}
