#! /usr/bin/perl -w

# Copyright (C) 2010 by Dirk Krause
# All rights reserved.
# 
# Redistribution and use in source and binary forms,
# with or without modification, are permitted provided
# that the following conditions are met:
# 
# * Redistributions of source code must retain the above
#   copyright notice, this list of conditions and the
#   following disclaimer.
# * Redistributions in binary form must reproduce the above 
#   opyright notice, this list of conditions and the following
#   disclaimer in the documentation and/or other materials
#   provided with the distribution.
# * Neither the name of the Dirk Krause nor the names of
#   contributors may be used to endorse or promote
#   products derived from this software without specific
#   prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED.
# IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.

# ##### Begin configuration section
#
#

my $configurationfilename = "/etc/USRLOCAL/hostsadm/hostsadm.conf";

#
#
# ##### End configuration section

use DBI;
use DKrause::Application;
use DKrause::BitMatrix;
use DKrause::LaTeXEncoder;

my $convert_text_to_latin = 0;

my $exval = 1;

# Constant factors for calculations with IP address parts
my $f1; my $f2; my $f3;

my $confobj = { 'debug' => 2};
my $textobj = { 'de'	=> 0};
my $latexencoder = undef;
my $currenttimestr = "2007-01-09";

#	0
#	1	error
#	2	warning
#	3	info
#	4	progress
#	5	debug
sub debugmsg
{
  my $l = 0;
  my $t;
  if($#_ > -1) {
    $l = shift;
    if($#_ > -1) {
      if($confobj->{'debug'} >= $l)  {
        print "hostsadm:";
	if($l == 1) {
          print " ERROR:";
	} else {
	  if($l == 2) {
	    print " Warning:";
	  } else {
	    if($l == 5) {
	      print " Debug:";
	    }
	  }
	}
	while($#_ > -1) {
	  $t = shift @_;
	  if(defined($t)) {
	    print " $t";
	  } else {
	    print " <<<undefined>>>";
	  }
	} print "\n";
      } else {
        while($#_ > -1) { shift @_; }
      }
    }
  }
}

use haconfig;
use hatext;

my $do_check = 1;
my $do_hosts = 0;
my $do_licenses = 0;

my %vlansbyname;
my %aliasesbyname;
my %networksbyname;
my %ddspeedbyname;
my %buildingsbyname;
my %patchesbyname;
my %netgroupsbyname;		my @netgroupsbynumber;	my $numnetgroups = 0;
my %ngdepsbypk;
my %dhcpclassesbyname;
my %dhcppoolsbypk;
my %dhcpgroupsbyname;
my %dhcpoptionsbypk;
my %computersbyname;		my @computersbynumber;	my $numcomputers = 0;
my %swmanufacturersbyname;
my %swproductsbyname;		my @swproductsbynumber;	my $numswproducts = 0;
my %swresellersbyname;
my %licensetypesbyname;
my %licensesbypk;		my $licensesbynumber;	my $numlicenses = 0;
my %usersbyname;		my @usersbynumber;	my $numusers = 0;

my @vlanskeys = (
  "vl_s", "vl_l"
);

my @aliaseskeys = (
  "al_s", "co_s"
);

my @networkskeys = (
  "nw_ip", "nw_ma", "nw_gw", "nw_bc", "vl_s"
);
my @ddspeedkeys = (
  "sp_s", "sp_l"
);
my @gebaeudekeys = (
  "gb_s", "gb_l", "gb_a1", "gb_a2", "gb_a3", "gb_a4", "gb_plz", "gb_ort"
);
my @datendosenkeys = (
  "dd_n", "sp_s", "vl_s", "gb_s", "dd_r"
);
my @userskeys = (
  "us_s", "us_t", "us_sn", "us_fn", "us_em", "us_ko", "us_se"
);
my @netgroupskeys = (
  "ng_s", "ng_l"
);
my @ngdepskeys = (
  "nd_pk", "nd_p", "nd_c"
);
my @dhcpclasseskeys = (
  "dc_s", "dc_d", "nw_ip"
);
my @dhcppoolskeys = (
  "dp_pk", "dp_st", "dp_en", "nw_ip", "dp_al", "dp_dn", "dc_s"
);
my @dhcpgroupskeys = (
  "dg_s", "dg_l", "nw_ip"
);
my @dhcpoptionskeys = (
  "do_pk", "do_sc", "do_sn", "do_n", "do_v"
);
my @computerskeys = (
  "co_s", "co_ip", "dc_s", "dg_s", "co_mc", "dd_n", "gb_s",
  "co_r", "co_in", "co_dd", "co_ff", "co_hi", "co_sn",
  "us_s", "ng_s", "co_co", "co_ex", "co_gu"
);
my @swmanufacturerskeys = (
  "sm_s", "sm_l"
);
my @swproductskeys = (
  "sw_s", "sw_l", "sm_s"
);
my @swresellerskeys = (
  "sr_s", "sr_l", "sr_a1", "sr_a2", "sr_a3", "sr_a4", "sr_plz", "sr_ort"
);
my @licensetypeskeys = (
  "lt_s", "lt_l", "lt_i"
);
my @licenseskeys = (
  "li_pk", "li_on", "sw_s", "us_s", "co_s", "lt_s", "li_no", "sr_s",
  "li_dd", "li_nd", "li_di", "li_ni"
);
my @startoftable = (
"\\begin{longtable}{rllll}",
"\\endfirsthead",
"\\endhead",
"\\endfoot",
"\\endlastfoot"
);

sub read_command_line_options($)
{
  my $cmdline = shift;		# array reference
  my @args = @$cmdline;		# command line as an array
  my $o;			# one element
  while($#args > -1) {
    $o = shift @args;
    if($o =~ /\-(.*)/o) {
      $o = $1;
      if($o =~ /[Hh]([Oo]([Ss]([Tt]([Ss])?)?)?)?/o) {
        $do_hosts = 1;
      } else {
        if($o =~ /[Ll]([Ii]([Cc]([Ee]([Nn]([Ss]([Ee]([Ss])?)?)?)?)?)?)?/o) {
	  $do_licenses = 1;
	} else {
	  debugmsg(1, "Unknown option \"-$o\"!");
	}
      }
    } else {
      $configurationfilename = $o;
    }
  }
}

sub show_configuration()
{
  my $h = $confobj->{'dbhost'};
  my $d = $confobj->{'dbname'};
  my $u = $confobj->{'dbuser'};
  my $p = $confobj->{'dbpass'};
  my $ch = $confobj->{'cohosts'};
  my $ce = $confobj->{'coethers'};
  if(!defined($h)) { $h = "<<<undefined>>>"; }
  if(!defined($d)) { $d = "<<<undefined>>>"; }
  if(!defined($u)) { $u = "<<<undefined>>>"; }
  if(!defined($p)) { $p = "<<<undefined>>>"; }
  else { $p = "<<<found>>>"; }
  debugmsg(5, "Host:      $h");
  debugmsg(5, "Database:  $d");
  debugmsg(5, "User name: $u");
  debugmsg(5, "Password:  $p");
  debugmsg(5, "Hosts c:   $ch");
  debugmsg(5, "Ethers c:  $ce");
}

sub error_execute($)
{
  my $s = shift;
  debugmsg(1, "Failed to execute SQL statement\n\t\"$s\"!");
}

sub error_prepare($)
{
  my $s = shift;
  debugmsg(1, "Failed to prepare SQL statement\n\t\"$s\"!");
}

# dbh
# SQL statement
# hash reference
# array reference (hash keys)

sub read_one_table($$$$)
{
  my $dbh = shift;
  my $sqlstatement = shift;
  my $hashref = shift;
  my $arrayref = shift;
  my $newentry;
  my $i;
  my $k;
  my $l;
  my @ak = @$arrayref;
  my $sth = $dbh->prepare($sqlstatement);
  if($sth) {
    if($sth->execute()) {
      while($ref = $sth->fetchrow_hashref()) {
        $newentry = {};
	for($i = 0; $i <= $#ak; $i++) {
	  $k = $ak[$i];
	  $newentry->{"$k"} = undef;
	}
	for($i = 0; $i <= $#ak; $i++) {
	  $k = $ak[$i];
	  if(exists($ref->{"$k"})) {
	    if(defined($ref->{"$k"})) {
	      $l = $ref->{"$k"};
	      $l = "$l";
	      if($l =~ /\S/o) {
		chomp $l;
	        $newentry->{"$k"} = $l;
	      }
	    }
	  }
	}
	$k = $ak[0];
	if(exists($ref->{"$k"})) {
	  if(defined($ref->{"$k"})) {
	    $k = $ref->{"$k"};
	    $$hashref{"$k"} = $newentry;
	  }
	}
      }
    } else {
      $exval = 1; error_execute($sqlstatement);
    }
    $sth->finish();
  } else {
    $exval = 1; error_prepare($sqlstatement);
  }
}

sub read_data()
{
  my $dbh = undef;
  my $sth = undef;
  my $ref = undef;
  my $s = undef;
  my $h = $confobj->{'dbhost'};
  my $d = $confobj->{'dbname'};
  my $u = $confobj->{'dbuser'};
  my $p = $confobj->{'dbpass'};
  my $v1 = undef; my $v2 = undef; my $v3 = undef; my $v4 = undef; my $v5 = undef;
  my $v6 = undef; my $v7 = undef; my $v8 = undef; my $v9 = undef; my $v10 = undef;
  debugmsg(4, "Reading input data (start)");
  if(defined($h) && defined($d) && defined($u) && defined($p)) {
    $dbh = DBI->connect("dbi:mysql:database=$d;host=$h", "$u", "$p");
    if($dbh) {
      # so far, so fine
      $exval = 0;
      # vlans: vl_s, vl_l
      debugmsg(4, "Reading VLAN table (start)");
      read_one_table(
        $dbh, "SELECT * FROM vlans",
	\%vlansbyname, \@vlanskeys
      );
      debugmsg(4, "Reading VLAN table (finished)");
      # networks: nw_ip, nw_ma, nw_gw, nw_bc, vl_s
      debugmsg(4, "Reading network table (start)");
      read_one_table(
        $dbh, "SELECT * FROM networks",
	\%networksbyname, \@networkskeys
      );
      debugmsg(4, "Reading network table (finished)");
      # ddspeed: sp_s, sp_l
      debugmsg(4, "Reading patch speed table (start)");
      read_one_table(
        $dbh, "SELECT * FROM ddspeed",
	\%ddspeedbyname, \@ddspeedkeys
      );
      debugmsg(4, "Reading patch speed table (finished)");
      # gebaeude gb_s, gb_l, gb_a1, gb_a2, gb_a3, gb_a4, gb_plz, gb_ort
      debugmsg(4, "Reading buildings table (start)");
      read_one_table(
        $dbh, "SELECT * FROM buildings",
	\%buildingsbyname, \@gebaeudekeys
      );
      debugmsg(4, "Reading buildings table (finished)");
      # datendosen: dd_n, sp_s, vl_s, gb_s
      debugmsg(4, "Reading network patches table (start)");
      read_one_table(
        $dbh, "SELECT * FROM patches",
	\%patchesbyname, \@datendosenkeys
      );
      debugmsg(4, "Reading network patches table (finished)");
      # users: us_s, us_t, us_sn, us_fn, us_em, us_ko, us_se
      debugmsg(4, "Reading users table (start)");
      read_one_table(
        $dbh, "SELECT * FROM users",
	\%usersbyname, \@userskeys
      );
      debugmsg(4, "Reading users table (finished)");
      # netgroups: ng_s, ng_l
      debugmsg(4, "Reading netgroups table (start)");
      read_one_table(
        $dbh, "SELECT * FROM netgroups",
	\%netgroupsbyname, \@netgroupskeys
      );
      debugmsg(4, "Reading netgroups table (finished)");
      # ngdeps: nd_pk, nd_p, nd_c
      debugmsg(4, "Reading netgroup dependencies table (start)");
      read_one_table(
        $dbh, "SELECT * FROM ngdeps",
	\%ngdepsbypk, \@ngdepskeys
      );
      debugmsg(4, "Reading netgroup dependencies table (finished)");
      # dhcpclasses: dc_s, dc_d
      debugmsg(4, "Reading DHCP classes table (start)");
      read_one_table(
        $dbh, "SELECT * FROM dhcpclasses",
	\%dhcpclassesbyname, \@dhcpclasseskeys
      );
      debugmsg(4, "Reading DHCP classes table (finished)");
      # dhcppools: dp_pk, dp_st, dp_en, nw_ip, dp_al, dp_dn, dc_s
      debugmsg(4, "Reading DHCP pools table (start)");
      read_one_table(
        $dbh, "SELECT * FROM dhcppools",
	\%dhcppoolsbypk, \@dhcppoolskeys
      );
      debugmsg(4, "Reading DHCP pools table (finished)");
      # dhcpgroups: dg_s, dg_l, nw_ip
      debugmsg(4, "Reading DHCP groups table (start)");
      read_one_table(
        $dbh, "SELECT * FROM dhcpgroups",
	\%dhcpgroupsbyname, \@dhcpgroupskeys
      );
      debugmsg(4, "Reading DHCP groups table (finished)");
      # dhcpoptions: do_pk, do_sc, do_sn, do_n, do_v
      debugmsg(4, "Reading DHCP options table (start)");
      read_one_table(
        $dbh, "SELECT * FROM dhcpoptions",
	\%dhcpoptionsbypk, \@dhcpoptionskeys
      );
      debugmsg(4, "Reading DHCP options table (finished)");
      debugmsg(4, "Reading aliases table (start)");
      read_one_table(
        $dbh, "SELECT * FROM aliases",
	\%aliasesbyname, \@aliaseskeys
      );
      debugmsg(4, "Reading aliases table (finished)");
      # computers: co_s, co_ip, dc_s, dg_s, co_mc, dd_n, gb_s, co_r,
      #            co_in, co_dd, co_ff, co_hi, co_sn, us_s, ng_s,
      #            co_co, co_ex
      debugmsg(4, "Reading computers table (start)");
      read_one_table(
        $dbh, "SELECT * FROM computers",
	\%computersbyname, \@computerskeys
      );
      debugmsg(4, "Reading computers table (finished)");

      if($do_licenses) {
	# swmanufacturers: sm_s, sm_l
	debugmsg(4, "Reading software manufacturers table (start)");
	read_one_table(
	  $dbh, "SELECT * FROM swmanufacturers",
	\%swmanufacturersbyname, \@swmanufacturerskeys
	);
	debugmsg(4, "Reading software manufacturers table (finished)");
	# swproducts: sp_s, sp_l, sm_s
	debugmsg(4, "Reading software products table (start)");
	read_one_table(
	  $dbh, "SELECT * FROM swproducts",
	\%swproductsbyname, \@swproductskeys
	);
	debugmsg(4, "Reading software products table (finished)");
	# swresellers: sr_s, sr_l, sr_a1, sr_a2, sr_a3, sr_a4, sr_plz, sr_ort
	debugmsg(4, "Reading software resellers table (start)");
	read_one_table(
	  $dbh, "SELECT * FROM swresellers",
	\%swresellersbyname, \@swresellerskeys
	);
	debugmsg(4, "Reading software resellers table (finished)");
	# licensetypes: lt_s, lt_l, lt_i
	debugmsg(4, "Reading license types table (start)");
	read_one_table(
	  $dbh, "SELECT * FROM licensetypes",
	  \%licensetypesbyname, \@licensetypeskeys
	);
	debugmsg(4, "Reading license types table (finished)");
	# licenses: li_pk, li_on, sp_s, us_s, co_s, lt_s, li_no, sr_s, li_dd,
	#           li_nd, li_di, li_ni
	debugmsg(4, "Reading licenses table (start)");
	read_one_table(
	  $dbh, "SELECT * FROM licenses",
	\%licensesbypk, \@licenseskeys
	);
	debugmsg(4, "Reading licenses table (finished)");
      }

      # disconnect from database
      $dbh->disconnect();
    } else {
     # ##### ERROR: Failed to connect to database
    }
  } else {
    # ##### ERROR: At least one configuration option missing
  }
  debugmsg(4, "Reading input data (finished)");
}

sub check_ip_parts($$$$) {
  my $back = 0;
  my $u1 = shift; my $u2 = shift; my $u3 = shift; my $u4 = shift;
  if((0 <= $u1) && ($u1 <= 255)) {
    if((0 <= $u2) && ($u2 <= 255)) {
      if((0 <= $u3) && ($u3 <= 255)) {
        if((0 <= $u4) && ($u4 <= 255)) {
	  $back = 1;
	}
      }
    }
  }
  return $back;
}

sub numeric_to_ip($)
{
  my $u1; my $u2; my $u3; my $u4;
  $u4 = shift;
  $u1 = $u4 / $f1;
  $u4 = $u4 % $f1;
  $u2 = $u4 / $f2;
  $u4 = $u4 % $f2;
  $u3 = $u4 / $f3;
  $u4 = $u4 % $f3;
  my $back = "$u1.$u2.$u3.$u4";
  return $back;
}

sub create_gateway($)
{
  my $r = shift;
  my $u1; my $u2; my $u3; my $u4;
  $u4 = $r->{'nip'};
  $u1 = $u4 / $f1;
  $u4 = $u4 % $f1;
  $u2 = $u4 / $f2;
  $u4 = $u4 % $f2;
  $u3 = $u4 / $f3;
  $u4 = $u4 % $f3;
  $u4++;
  $r->{'nw_gw'} = "$u1.$u2.$u3.$u4";
}

sub create_broadcast($)
{
  my $r = shift;
  my $i = $r->{'nip'};
  my $m = $r->{'nma'};
  my $b = ($i & $m) | (~$m);
  $r->{'nw_bc'} = numeric_to_ip($b);
}

sub check_networks()
{
  my $k; my $r; my $v; my $n; my $ok;
  my $u1; my $u2; my $u3; my $u4;
  # networks
  #	create numeric IP
  #	create numeric mask
  #	create numeric gateway
  #	create numeric broadcast
  #	check vl_s
  foreach $k (keys %networksbyname) {
    $ok = 0;
    $r = $networksbyname{"$k"};
    if(exists($r->{'nw_ip'})) {
      $v = $r->{'nw_ip'};
      debugmsg(4, "Checking IP network $v.");
      if($v =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
        $u1 = $1; $u2 = $2; $u3 = $3; $u4 = $4;
	if(check_ip_parts($u1, $u2, $u3, $u4)) {
	  $r->{'nip'} = $f1 * $u1 + $f2 * $u2 + $f3 * $u3 + $u4;
	  if(exists($r->{'nw_ma'})) {
	    $v = $r->{'nw_ma'};
	    if(!defined($v)) {
	    debugmsg(
	     2,
	     "TABLE metworks ENTRY $k: Missing netmask, assuming 255.255.255.0!"
	    );
	    $r->{'nw_ma'} = "255.255.255.0";
	    $v = "255.255.255.0";
	    }
	  } else {
	    debugmsg(
	     2,
	     "TABLE metworks ENTRY $k: Missing netmask, assuming 255.255.255.0!"
	    );
	    $r->{'nw_ma'} = "255.255.255.0";
	    $v = "255.255.255.0";
	  }
          if($v =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
	    $u1 = $1; $u2 = $2; $u3 = $3; $u4 = $4;
	    if(check_ip_parts($u1, $u2, $u3, $u4)) {
	      $r->{'nma'} = $f1 * $u1 + $f2 * $u2 + $f3 * $u3 + $u4;
	      if(exists($r->{'nw_gw'})) {
	        if(!defined($r->{'nw_gw'})) {
		  create_gateway($r);
		}
	      } else {
	        create_gateway($r);
	      }
	      $v = $r->{'nw_gw'};
	      debugmsg(5, "Checking gateway $v.");
	      if($v =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
	        $u1 = $1; $u2 = $2; $u3 = $3; $u4 = $4;
		if(check_ip_parts($u1, $u2, $u3, $u4)) {
		  $r->{'numeric_ga'} = $f1 * $u1 + $f2 * $u2 + $f3 * $u3 + $u4;
		  if(exists($r->{'nw_bc'})) {
		    if(!defined($r->{'nw_bc'})) {
		      create_broadcast($r);
		    }
		  } else {
		    create_broadcast($r);
		  }
		  $v = $r->{'nw_bc'};
		  debugmsg(5, "Checking broadcast address $v.");
		  if($v =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		    $u1 = $1; $u2 = $2; $u3 = $3; $u4 = $4;
		    if(check_ip_parts($u1, $u2, $u3, $u4)) {
		      $r->{'numeric_bc'} =
		      $f1 * $u1 + $f2 * $u2 + $f3 * $u3 + $u4;
		      $ok = 1;
		    } else {
		    debugmsg(
		      1,
		      "TABLE networks ENTRY $k: Illegal broadcast address $v!"
		    );
		    }
		  } else {
		    debugmsg(
		      1,
		      "TABLE networks ENTRY $k: Illegal broadcast address $v!"
		    );
		  }
		} else {
		  debugmsg(
		    1,
		    "TABLE networks ENTRY $k: Illegal gateway $v!"
		  );
		}
	      } else {
	        debugmsg(
		  1,
		  "TABLE networks ENTRY $k: Illegal gateway $v!"
		);
	      }
	    } else {
	      debugmsg(1, "TABLE networks ENTRY $k: Illegal IP netmask $v!");
	    }
	  } else {
	    debugmsg(1, "TABLE networks ENTRY $k: Illegal IP netmask $v!");
	  }
	} else {
	  debugmsg(1, "TABLE networks ENTRY $k: Illegal IP address $v!");
	}
      }
    }
    if(!$ok) {
      $exval = 1;
    }
  }
}

sub check_datendosen()
{
  my $k; my $r; my $v;
  debugmsg(4, "Checking network patches (start)");
  # datendosen
  #	check sp_s
  #	check vl_s
  #	check gb_s
  foreach $k (keys %patchesbyname) {
    $r = $patchesbyname{"$k"};
    if(exists($r->{'sp_s'})) {
      if(defined($r->{'sp_s'})) {
        $v = $r->{'sp_s'};
	if(!exists($ddspeedbyname{"$v"})) {
	  debugmsg(2, "TABLE datendosen ENTRY $k: Invalid speed setting \"$v\"!");
	}
      } else {
	debugmsg(2, "TABLE datendosen ENTRY $k: No speed setting!");
      }
    } else {
      debugmsg(2, "TABLE datendosen ENTRY $k: No speed setting!");
    }
    if(exists($r->{'vl_s'})) {
      if(defined($r->{'vl_s'})) {
        $v = $r->{'vl_s'};
	if(!exists($vlansbyname{"$v"})) {
	  debugmsg(2, "TABLE datendosen ENTRY $k: Invalid VLAN \"$v\"!");
	}
      } else {
        debugmsg(2, "TABLE datendosen ENTRY $k: No VLAN specified!");
      }
    } else {
      debugmsg(2, "TABLE datendosen ENTRY $k: No VLAN specified!");
    }
    if(exists($r->{'gb_s'})) {
      if(defined($r->{'gb_s'})) {
        $v = $r->{'gb_s'};
	if(!exists($buildingsbyname{"$v"})) {
	  debugmsg(2, "TABLE datendosen ENTRY $k: Invalid building \"$v\"!");
	}
      } else {
        debugmsg(2, "TABLE datendosen ENTRY $k: No building specified!");
      }
    } else {
      debugmsg(2, "TABLE datendosen ENTRY $k: No building specified!");
    }
    if(exists($r->{'dd_r'})) {
      if(!defined($r->{'dd_r'})) {
        debugmsg(2, "TABLE datendosen ENTRY $k: No room specified!");
      }
    } else {
      debugmsg(2, "TABLE datendosen ENTRY $k: No room specified!");
    }
  }
  debugmsg(4, "Checking network patches (finished)");
}


sub check_ngdeps()
{
  my $k; my $r; my $v;
  # ngdeps
  #	check nd_p
  #	check nd_c
  debugmsg(4, "Checking netgroup dependencies (start)");
  foreach $k (sort { $a <=> $b } (keys %ngdepsbypk)) {
    $r = $ngdepsbypk{"$k"};
    if(exists($r->{'nd_p'})) {
      if(defined($r->{'nd_p'})) {
        $v = $r->{'nd_p'};
        if(!exists($netgroupsbyname{"$v"})) {
	debugmsg(1, "TABLE ngdeps ENTRY $k: Invalid parent netgroup \"$v\"!");
	$exval = 1;
	}
      } else {
        debugmsg(1, "TABLE ngdeps ENTRY $k: Missing parent netgroup!");
	$exval = 1;
      }
    } else {
      debugmsg(1, "TABLE ngdeps ENTRY $k: Missing parent netgroup!");
      $exval = 1;
    }
    if(exists($r->{'nd_c'})) {
      if(defined($r->{'nd_c'})) {
        $v = $r->{'nd_c'};
        if(!exists($netgroupsbyname{"$v"})) {
	debugmsg(1, "TABLE ngdeps ENTRY $k: Invalid child netgroup \"$v\"!");
	$exval = 1;
	}
      } else {
        debugmsg(1, "TABLE ngdeps ENTRY $k: Missing child netgroup!");
	$exval = 1;
      }
    } else {
      debugmsg(1, "TABLE ngdeps ENTRY $k: Missing child netgroup!");
      $exval = 1;
    }
  }
  debugmsg(4, "Checking netgroup dependencies (finished)");
}

sub check_dhcppools()
{
  my $k; my $r; my $v; my $al = 0; my $dn = 1;
  # dhcppools
  #	check nw_ip
  #	check dc_s if dp_al==0 and dp_dn==1
  debugmsg(4, "Checking DHCP pools (start)");
  foreach $k (sort { $a <=> $b } (keys %dhcppoolsbypk)) {
    $r = $dhcppoolsbypk{"$k"};
    if(exists($r->{'nw_ip'})) {
      if(defined($r->{'nw_ip'})) {
        $v = $r->{'nw_ip'};
        if(!exists($networksbyname{"$v"})) {
	  debugmsg(1, "TABLE dhcppools ENTRY $k: Invalid network \"$v\"!");
	  $exval = 1;
	}
      } else {
        debugmsg(1, "TABLE dhcppools ENTRY $k: Missing network!");
	$exval = 1;
      }
    } else {
      debugmsg(1, "TABLE dhcppools ENTRY $k: Missing network!");
      $exval = 1;
    }
    if(exists($r->{'dp_al'})) {
      if(defined($r->{'dp_al'})) {
        $al = $r->{'dp_al'};
      }
    }
    if(exists($r->{'dp_dn'})) {
      if(defined($r->{'dp_dn'})) {
        $dn = $r->{'dp_dn'};
      }
    }
    if(($al == 0) && ($dn == 1)) {
      if(exists($r->{'dc_s'})) {
        if(defined($r->{'dc_s'})) {
          $v = $r->{'dc_s'};
          if(!exists($dhcpclassesbyname{"$v"})) {
	    debugmsg(1, "TABLE dhcppools ENTRY $k: Invalid DHCP class \"$v\"!");
	    $exval = 1;
	  }
        } else {
          debugmsg(1, "TABLE dhcppools ENTRY $k: Missing DHCP class!");
	  $exval = 1;
        }
      } else {
        debugmsg(1, "TABLE dhcppools ENTRY $k: Missing DHCP class!");
	$exval = 1;
      }
    }
  }
  debugmsg(4, "Checking DHCP pools (finished)");
}

sub check_dhcpgroups()
{
  my $k; my $r; my $v;
  # dhcpgrups
  #	check nw_ip
  foreach $k (keys %dhcpgroupsbyname) {
    $r = $dhcpgroupsbyname{"$k"};
    if(exists($r->{'nw_ip'})) {
      $v = $r->{'nw_ip'};
      if(defined($v)) {
        if(!exists($networksbyname{"$v"})) {
	  debugmsg(1, "TABLE dhcpgroups ENTRY $k: Invalid network \"$k\"!");
	  $exval = 1;
	}
      } else {
        debugmsg(1, "TABLE dhcpgroups ENTRY $k: Missing network!");
	$exval = 1;
      }
    } else {
      debugmsg(1, "TABLE dhcpgroups ENTRY $k: Missing network!");
      $exval = 1;
    }
  }
}

sub check_hosts()
{
  # hosts
  #	check dc_s if not null
  #	check dg_s if not null
  #	check dd_n		(warning only)
  #	check gb_s		(warning only)
  #	check us_s		(warning only)
  #	check ng_s
  #	check whether entry is expired
  my $k; my $r; my $v; my $t; my $havedhcpclass;
  my $u1; my $u2; my $u3; my $u4;
  my $isguest;
  foreach $k (keys %computersbyname) {
    $r = $computersbyname{"$k"};
    $r->{'done'} = 0;
    $r->{'nip'} = 0;
    $isguest = 0;
    if(exists($r->{'co_ip'})) {
      if(defined($r->{'co_ip'})) {
        if($r->{'co_ip'} =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
	  $u1 = $1; $u2 = $2; $u3 = $3; $u4 = $4;
	  $r->{'nip'} = $f1 * $u1 + $f2 * $u2 + $f3 * $u3 + $u4;
	}
      }
    }
    if(exists($r->{'co_gu'})) {
      if(defined($r->{'co_gu'})) {
        if($r->{'co_gu'} != 0) {
	  $isguest = 1;
	}
      }
    }
    $havedhcpclass = 0;
    if(exists($r->{'ng_s'})) {
      $t = $r->{'ng_s'};
      if(defined($t)) {
        chomp $t;
	while($t =~ /^(\S+)\s(.*)$/o) {
	  $v = $1; $t = $2;
	  if(!exists($netgroupsbyname{"$v"})) {
	    debugmsg(2, "TABLE computers ENTRY $k: Invalid netgroup \"$v\"!");
	    $netgroupsbyname{"$v"} = {
	      'ng_s'	=> "$v",
	      'ng_l'	=> '-',
	      'anno'	=> $numnetgroups
	    };
	    $netgroupsbynumber[$numnetgroups] = $netgroupsbyname{"$v"};
	    $numnetgroups++;
	  }
	}
	$v = $t;
	if(!exists($netgroupsbyname{"$v"})) {
	  debugmsg(2, "TABLE computers ENTRY $k: Invalid netgroup \"$v\"!");
	  $netgroupsbyname{"$v"} = {
	    'ng_s'	=> "$v",
	    'ng_l'	=> '-',
	    'anno'	=> $numnetgroups
	  };
	  $netgroupsbynumber[$numnetgroups] = $netgroupsbyname{"$v"};
	  $numnetgroups++;
	}
      }
    }
    if(exists($r->{'dc_s'})) {
      $v = $r->{'dc_s'};
      if(defined($v)) {
        if(exists($dhcpclassesbyname{"$v"})) {
	  $havedhcpclass = 1;
	  if(exists($r->{'co_mc'})) {
	    if(defined($r->{'co_mc'})) {
	      if($r->{'co_mc'} =~ /[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]/o) {
	        $dhcpclassesbyname{"$v"}->{'used'} = 1;
	      }
	    }
	  }
	}
      }
    }
    if(exists($r->{'us_s'})) {
      $v = $r->{'us_s'};
      if(defined($v)) {
        if(!exists($usersbyname{"$v"})) {
	  debugmsg(1, "TABLE computers ENTRY $k: Invalid owner \"$v\"!");
	  $exval = 1;
	}
      } else {
        if(!$havedhcpclass) {
	  if(!$isguest) {
            debugmsg(1, "TABLE computers ENTRY $k: Missing owner!");
	    $exval = 1;
	  }
	}
      }
    } else {
      if(!$havedhcpclass) {
        if(!$isguest) {
          debugmsg(1, "TABLE computers ENTRY $k: Missing owner!");
          $exval = 1;
	}
      }
    }
    if(exists($r->{'dc_s'})) {
      $v = $r->{'dc_s'};
      if(defined($v)) {
        if(!exists($dhcpclassesbyname{"$v"})) {
	  debugmsg(1, "TABLE computers ENTRY $k: Invalid DHCP class \"$v\"!");
	  $exval = 1;
	}
      }
    }
    if(exists($r->{'dg_s'})) {
      $v = $r->{'dg_s'};
      if(defined($v)) {
        if(!exists($dhcpgroupsbyname{"$v"})) {
	  debugmsg(1, "TABLE computers ENTRY $k: Invalid DHCP group \"$v\"!");
	  $exval = 1;
	}
      }
    }
    if(exists($r->{'dd_n'})) {
      $v = $r->{'dd_n'};
      if(defined($v)) {
        if(!exists($patchesbyname{"$v"})) {
	debugmsg(1, "TABLE computers ENTRY $k: Invalid network patch \"$v\"!");
	}
      } else {
        if(!$isguest) {
	  if(!$havedhcpclass) {
            debugmsg(2, "TABLE computers ENTRY $k: Missing network patch!");
	  }
	}
      }
    } else {
      if(!$isguest) {
        if(!$havedhcpclass) {
          debugmsg(2, "TABLE computers ENTRY $k: Missing network patch!");
	}
      }
    }
    if(exists($r->{'gb_s'})) {
      $v = $r->{'gb_s'};
      if(defined($v)) {
        if(!exists($buildingsbyname{"$v"})) {
	  debugmsg(1, "TABLE computers ENTRY $k: Invalid building \"$v\"!");
	}
      } else {
        if((!$isguest) && (!$havedhcpclass)) {
          debugmsg(2, "TABLE computers ENTRY $k: Missing building!");
	}
      }
    } else {
      if((!$isguest) && (!$havedhcpclass)) {
        debugmsg(2, "TABLE computers ENTRY $k: Missing building!");
      }
    }
    $r->{'ex'} = 0;
    if(exists($r->{'co_ex'})) {
      if(defined($r->{'co_ex'})) {
        if($r->{'co_ex'} =~ /\d\d\d\d\-\d\d\-\d\d/o) {
	  if("$currenttimestr" gt $r->{'co_ex'}) {
	    $r->{'ex'} = 1;
	    debugmsg(2, "Expired omputer: \"$k\"!");
	  }
	}
      }
    }
  }
}

sub check_licenses()
{
  # licenses
  #	check sw_s
  #	check us_s
  #	check co_s
  #	check lt_s
  #	check sr_s if not null
  my $k; my $r; my $v;
  foreach $k (sort { $a <=> $b } (keys %licensesbypk)) {
    $r = $licensesbypk{"$k"};
    if(exists($r->{'sw_s'})) {
      $v = $r->{'sw_s'};
      if(defined($v)) {
        if(!exists($swproductsbyname{"$v"})) {
	  debugmsg(
	    1,
	    "TABLE licenses ENTRY $k: Invalid software product \"$v\"!"
	  );
	  $exval = 1;
	}
      } else {
        debugmsg(1, "TABLE licenses ENTRY $k: Missing software product!");
	$exval = 1;
      }
    } else {
      debugmsg(1, "TABLE licenses ENTRY $k: Missing software product!");
      $exval = 1;
    }
    if(exists($r->{'us_s'})) {
      $v = $r->{'us_s'};
      if(defined($v)) {
        if(!exists($usersbyname{"$v"})) {
	  debugmsg(1, "TABLE licenses ENTRY $k: Invalid user name \"$v\"!");
	  $exval = 1;
	}
      }
    }
    if(exists($r->{'co_s'})) {
      $v = $r->{'co_s'};
      if(defined($v)) {
        if($v =~ /\S+/o) {
          if(!exists($computersbyname{"$v"})) {
	    debugmsg(1, "TABLE licenses ENTRY $k: Invalid computer name \"$v\"!");
	    $exval = 1;
	  }
	}
      }
    }
    if(exists($r->{'lt_s'})) {
      $v = $r->{'lt_s'};
      if(defined($v)) {
        if(!exists($licensetypesbyname{"$v"})) {
	  debugmsg(1, "TABLE licenses ENTRY $k: Invalid license type \"$v\"!");
	  $exval = 1;
	}
      } else {
        debugmsg(1, "TABLE licenses ENTRY $k: Missing license type!");
	$exval = 1;
      }
    } else {
      debugmsg(1, "TABLE licenses ENTRY $k: Missing license type!");
      $exval = 1;
    }
    if(exists($r->{'sr_s'})) {
      $v = $r->{'sr_s'};
      if(defined($v)) {
        if(!exists($swresellersbyname{"$v"})) {
	  debugmsg(
	    1, "TABLE licenses ENTRY $k: Invalid software reseller \"$v\"!"
	  );
	  $exval = 1;
	}
      }
    }
  }
}

sub annotate_netgroups()
{
  my $k; my $r;
  foreach $k (sort (keys %netgroupsbyname)) {
    $r = $netgroupsbyname{"$k"};
    $netgroupsbynumber[$numnetgroups] = $r;
    $r->{'anno'} = $numnetgroups;
    $numnetgroups++;
  }
}

sub annotate_hosts()
{
  my $k; my $r;
  foreach $k (sort {
      # start of sort function
      # included here for re-use of regexes
      my $back = 0;
      my $ha; my $hb;
      my $ia; my $ib;
      my $ua1; my $ua2; my $ua3; my $ua4;
      my $ub1; my $ub2; my $ub3; my $ub4;
      if(exists($computersbyname{"$a"})) {
        if(exists($computersbyname{"$b"})) {
          $ha = $computersbyname{"$a"};
          $hb = $computersbyname{"$b"};
          if(defined($ha)) {
            if(defined($hb)) {
	      if(exists($ha->{'co_ip'})) {
	        if(exists($hb->{'co_ip'})) {
	          $ia = $ha->{'co_ip'};
	          $ib = $hb->{'co_ip'};
	          if(defined($ia)) {
	            if(defined($ib)) {
		      if($ia =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		        $ua1 = $1; $ua2 = $2; $ua3 = $3; $ua4 = $4;
		        if($ib =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		          $ub1 = $1; $ub2 = $2; $ub3 = $3; $ub4 = $4;
		          if($ua1 > $ub1) {
		            $back = 1;
		          } else {
		            if($ua1 < $ub1) {
			      $back = -1;
			    } else {
			      if($ua2 > $ub2) {
			        $back = 1;
			      } else {
			        if($ua2 < $ub2) {
			          $back = -1;
			        } else {
			          if($ua3 > $ub3) {
			            $back = 1;
			          } else {
			            if($ua3 < $ub3) {
				      $back = -1;
				    } else {
				      if($ua4 > $ub4) {
				        $back = 1;
				      } else {
				        if($ua4 < $ub4) {
				          $back = -1;
				        }
				      }
				    }
			          }
			        }
			      }
			    }
		          }
		        } else {
		          $back = -1;
			  debugmsg(5, "COMPARISON: IP for $a usable, but IP for $b unusable");
		        }
		      } else {
		        if($ib =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		          $back = 1;
			  debugmsg(5, "COMPARISON: IP for $a unusable, but IP for $b usable");
		        }
		      }
		    } else {
		      $back = -1;
		      debugmsg(5, "COMPARISON: IP for $a defined, but IP for $b undefined");
		    }
	          } else {
	            if(defined($ib)) {
		      $back = 1;
		      debugmsg(5, "COMPARISON: IP for $a undefined, but IP for $b defined");
		    }
	          }
	        } else {
	          $back = -1;
		  debugmsg(5, "COMPARISON: IP for $a, but no IP for $b");
	        }
	      } else {
	        if(exists($hb->{'co_ip'})) {
	          $back = 1;
		  debugmsg(5, "COMPARISON: No IP for $a, but IP for $b");
	        }
	      }
	    } else {
	      $back = -1;
	      debugmsg(5, "COMPARISON: computersbyname($a) defined, but ...($b) undefined");
	    }
          } else {
            if(defined($hb)) {
	      $back = 1;
	      debugmsg(5, "COMPARISON: computersbyname($a) undefined, but ...($b) defined");
	    }
          }
        } else {
          $back = -1;
	  debugmsg(5, "COMPARISON: computersbyname($a), but no computersbyname($b)");
        }
      } else {
        if(exists($computersbyname{"$b"})) {
          $back = 1;
	  debugmsg(5, "COMPARISON: No computersbyname($a), but computersbyname($b)");
        }
      }
      if($back == 0) {
        debugmsg(5, "COMPARISON: No result yet, comparing host names");
        if("$a" gt "$b") {
	  $back = 1;
	} else {
	  $back = -1;
	}
      }
      if($back > 0) {
        debugmsg(5, "COMPARISON: $a > $b");
      } else {
        if($back < 0) {
	  debugmsg(5, "COMPARISON: $a < $b");
	} else {
	  debugmsg(5, "COMPARISON: $a = $b");
	}
      }
      $back;
      # end of sort function
  } (keys %computersbyname)) {
    $r = $computersbyname{"$k"};
    $computersbynumber[$numcomputers] = $r;
    $r->{'anno'} = $numcomputers;
    $numcomputers++;
  }
}

sub mark_used()
{
  my $hi; my $hr; my $hk; my $ip; my $nw; my $vl; my $dc; my $nwk;
  for($hi = 0; $hi < $numcomputers; $hi++) {
    $hr = $computersbynumber[$hi];
    $hk = $hr->{'co_s'};
    $hr->{'used'} = 0;
  }
  foreach $hk (keys %vlansbyname) {
    $hr = $vlansbyname{"$hk"};
    $hr->{'used'} = 0;
  }
  foreach $hk (keys %networksbyname) {
    $hr = $networksbyname{"$hk"};
    $hr->{'used'} = 0;
  }
  foreach $hk (keys %dhcpclassesbyname) {
    $hr = $dhcpclassesbyname{"$hk"};
    $hr->{'used'} = 0;
  }
  for($hi = 0; $hi < $numcomputers; $hi++) {
    $hr = $computersbynumber[$hi];
    $hk = $hr->{'co_s'};
    if(exists($hr->{'co_mc'})) {
    if(defined($hr->{'co_mc'})) {
      $ip = undef;
      if(exists($hr->{'co_ip'})) {
        $ip = $hr->{'co_ip'};
      }
      if(defined($ip)) {
        foreach $nwk (keys %networksbyname) {
	  $nw = $networksbyname{"$nwk"};
	  if((($hr->{'nip'}) & ($nw->{'nma'})) == (($nw->{'nip'}) & ($nw->{'nma'}))) {
	    $nw->{'used'} = 1;
	    if(exists($nw->{'vl_s'})) {
	      if(defined($nw->{'vl_s'})) {
	        $vl = $nw->{'vl_s'};
		if(exists($vlansbyname{"$vl"})) {
		  $vl = $vlansbyname{"$vl"};
		  $vl->{'used'} = 1;
		}
	      }
	    }
	  }
	}
      } else {
        if(exists($hr->{'dc_s'})) {
	if(defined($hr->{'dc_s'})) {
	  $dc = $hr->{'dc_s'};
	  if(exists($dhcpclassesbyname{"$dc"})) {
	    $dc = $dhcpclassesbyname{"$dc"};
	    $dc->{'used'} = 1;
	    if(exists($dc->{'nw_ip'})) {
	    if(defined($dc->{'nw_ip'})) {
	      $nw = $dc->{'nw_ip'};
	      if(exists($networksbyname{"$nw"})) {
	        $nw = $networksbyname{"$nw"};
		$nw->{'used'} = 1;
		if(exists($nw->{'vl_s'})) {
		if(defined($nw->{'vl_s'})) {
		  $vl = $nw->{'vl_s'};
		  if(exists($vlansbyname{"$vl"})) {
		    $vl = $vlansbyname{"$vl"};
		    $vl->{'used'} = 1;
		  }
		}
		}
	      }
	    }
	    }
	  }
	}
	}
      }
    }
    }
  }
}

sub annotate_users()
{
  my $k;
  foreach $k (sort {
    my $back = 0;
    my $ua; my $ub;
    if(exists($usersbyname{"$a"})) {
      if(exists($usersbyname{"$b"})) {
        $ua = $usersbyname{"$a"};
	$ub = $usersbyname{"$b"};
	if(exists($ua->{'us_fn'})) {
	  if(exists($ub->{'us_fn'})) {
	    if($ua->{'us_fn'} gt $ub->{'us_fn'}) {
	      $back = 1;
	    } else {
	      $back = -1;
	    }
	  } else {
	    $back = 1;
	  }
	} else {
	  if(exists($ub->{'us_fn'})) {
	    $back = -1;
	  }
	}
      } else {
        $back = 1;
      }
    } else {
      if(exists($usersbyname{"$b"})) {
        $back = -1;
      }
    }
    $back;
  } (keys %usersbyname)) {
    $usersbynumber[$numusers] = $usersbyname{"$k"};
    $usersbyname{"$k"}->{'anno'} = $numusers++;
  }
}

sub annotate_licenses()
{
  my $p; my $i; my $k; my $l;
  my $cn;	# computer name
  my $co;	# computer owner
  my $us;	# user name
  # Enumerate software products
  foreach $p ( sort {
    my $back = 0;
    my $ra = undef; my $rb = undef;
    my $ma = undef; my $mb = undef;
    my $na = undef; my $nb = undef;
    if(exists($swproductsbyname{"$a"})) {
      if(exists($swproductsbyname{"$b"})) {
        $ra = $swproductsbyname{"$a"};
        $rb = $swproductsbyname{"$b"};
        # by manufacturers
	if(exists($ra->{'sm_s'})) {
	  if(exists($rb->{'sm_s'})) {
	    $ma = $ra->{'sm_s'}; $mb = $rb->{'sm_s'};
	    if(defined($ma)) {
	      if(defined($mb)) {
	        if($ma =~ /\S/o) {
		  if($mb =~ /\S/o) {
		    if("$ma" ne "-") {
		      if("$mb" ne "-") {
		        if(exists($swmanufacturersbyname{"$ma"})) {
			  if(exists($swmanufacturersbyname{"$mb"})) {
			    $ma = $swmanufacturersbyname{"$ma"};
			    $mb = $swmanufacturersbyname{"$mb"};
			    if(exists($ma->{'sm_l'})) {
			      if(exists($mb->{'sm_l'})) {
			        $na = $ma->{'sm_l'};
				$nb = $mb->{'sm_l'};
				if(defined($na)) {
				  if(defined($nb)) {
				    if("$na" gt "$nb") {
				      $back = 1;
				    } else {
				      if("$na" lt "$nb") {
				        $back = -1;
				      }
				    }
				  } else {
				    $back = 1;
				  }
				} else {
				  if(defined($nb)) { $back = -1; }
				}
			      } else {
			        $back = 1;
			      }
			    } else {
			      if(exists($mb->{'sm_l'})) { $back = -1; }
			    }
			  } else {
			    $back = 1;
			  }
			} else {
			  if(exists($swproductsbyname{"$mb"})) { $back = -1; }
			}
		      } else {
		        $back = 1;
		      }
		    } else {
		      if("$mb" ne "-") { $back = -1; }
		    }
		  } else {
		    $back = 1;
		  }
		} else {
		  if($mb =~ /\S/o) { $back = -1; }
		}
	      } else {
	        $back = 1;
	      }
	    } else {
	      if(defined($mb)) { $back = -1; }
	    }
	  } else {
	    $back = 1;
	  }
	} else {
	  if(exists($rb->{'sm_s'})) {
	    $back = -1;
	  }
	}
        # by product name if necessary
        if($back == 0) {
	  if(exists($ra->{'sw_l'})) {
	    if(exists($rb->{'sw_l'})) {
	      $na = $ra->{'sw_l'};
	      $nb = $rb->{'sw_l'};
	      if("$na" gt "$nb") {
	        $back = 1;
	      } else {
	        if("$na" lt "$nb") {
		  $back = -1;
		}
	      }
	    } else {
	      $back = 1;
	    }
	  } else {
	    if(exists($rb->{'sw_l'})) { $back = -1; }
	  }
	  if($back == 0) {
	    if("$a" gt "$b") {
	      $back = 1;
	    } else {
	      if("$a" lt "$b") {
	        $back = -1;
	      }
	    }
	  }
        }
      } else {
        $back = 1;
      }
    } else {
      if(exists($swproductsbyname{"$b"})) {
        $back = -1;
      }
    }
    return $back;
  } (keys %swproductsbyname) )
  {
    $swproductsbynumber[$numswproducts] = $swproductsbyname{"$p"};
    $numswproducts += 1;
  }
  foreach $p (sort {
    my $back = 0;
    my $ra = undef; my $rb = undef;
    my $pa = undef; my $pb = undef;
    my $ma = undef; my $mb = undef;
    my $na = undef; my $nb = undef;
    $ra = $licensesbypk{"$a"};
    $rb = $licensesbypk{"$b"};
    if(exists($ra->{'sw_s'})) {
      if(exists($rb->{'sw_s'})) {
        $pa = $ra->{'sw_s'}; $pb = $rb->{'sw_s'};
	if(defined($pa)) {
	  if(defined($pb)) {
	    if(exists($swproductsbyname{"$pa"})) {
	      if(exists($swproductsbyname{"$pb"})) {
	        $pa = $swproductsbyname{"$pa"}; $pb = $swproductsbyname{"$pb"};
		if(exists($pa->{'sm_s'})) {
		  if(exists($pb->{'sm_s'})) {
		    $ma = $pa->{'sm_s'}; $mb = $pb->{'sm_s'};
		    if(defined($ma)) {
		      if(defined($mb)) {
		        if(exists($swmanufacturersbyname{"$ma"})) {
			  if(exists($swmanufacturersbyname{"$mb"})) {
			    $ma = $swmanufacturersbyname{"$ma"};
			    $mb = $swmanufacturersbyname{"$mb"};
			    if(exists($ma->{'sm_l'})) {
			      if(exists($mb->{'sm_l'})) {
			        $na = $ma->{'sm_l'}; $nb = $mb->{'sm_l'};
				if(defined($na)) {
				  if(defined($nb)) {
				    if("$na" gt "$nb") {
				      $back = 1;
				    } else {
				      if("$na" lt "$nb") {
				        $back = -1;
				      }
				    }
				  } else { $back = 1; }
				} else {
				  if(defined($nb)) { $back = -1; }
				}
			      } else { $back = 1; }
			    } else {
			      if(exists($mb->{'sm_l'})) { $back = -1; }
			    }
			  } else { $back = 1; }
			} else {
			  if(exists($swmanufacturersbyname{"$mb"})) {
			    $back = -1;
			  }
			}
		      } else { $back = 1; }
		    } else {
		      if(defined($mb)) { $back = -1; }
		    }
		  } else { $back = 1; }
		} else {
		  if(exists($pb->{'sm_s'})) { $back = -1; }
		}
		if($back == 0) {
		 if(exists($pa->{'sw_l'})) {
		   if(exists($pb->{'sw_l'})) {
		     $na = $pa->{'sw_l'}; $nb = $pb->{'sw_l'};
		     if(defined($na)) {
		       if(defined($nb)) {
		         if("$na" gt "$nb") {
			   $back = 1;
			 } else {
			   if("$na" lt "$nb") {
			     $back = -1;
			   }
			 }
		       } else { $back = 1; }
		     } else {
		       if(defined($nb)) { $back = -1; }
		     }
		   } else { $back = 1; }
		 } else {
		   if(exists($pb->{'sw_l'})) { $back = -1; }
		 }
		}
	      } else { $back = 1; }
	    } else {
	      if(exists($swproductsbyname{"$pb"})) { $back = -1; }
	    }
	  } else { $back = 1; }
	} else {
	  if(defined($pb)) { $back = -1; }
	}
      } else {
        $back = 1;
      }
    } else {
      if(exists($rb->{'sw_s'})) {
        $back = -1;
      }
    }
    if($back == 0) {
      if($a > $b) { $back = 1; } else { $back = -1; }
    }
    return $back;
  } (keys %licensesbypk)) {
    $licensesbynumber[$numlicenses] = $licensesbypk{"$p"};
    $numlicenses++;
  }
  # Mark all users as 'has no license'
  foreach $i (keys %usersbyname) {
    $p = $usersbyname{"$i"};
    $p->{'hl'} = 0;
  }
  # Mark all computers as 'has no license'
  for($i = 0; $i < $numcomputers; $i++) {
    $p = $computersbynumber[$i];
    $p->{'hl'} = 0;
  }
  # Mark all licenses as 'has no computer or user'
  foreach $i (keys %licensesbypk) {
    $p = $licensesbypk{"$i"};
    $p->{'hl'} = 0;
  }
  # inspect all licenses
  foreach $p (@licensesbynumber) {
    $k = 0;
    $cn = undef; $co = undef; $us = undef;
    if(exists($p->{'co_s'})) {
      $cn = $p->{'co_s'};
      if(defined($cn)) {
      if($cn =~ /\S/o) {
      if("$cn" eq "-") {
        $cn = undef;
      } else {
        if(exists($computersbyname{"$cn"})) {
	  $l = $computersbyname{"$cn"};
	  if(exists($l->{'us_s'})) {
	    $co = $l->{'us_s'};
	    if(defined($co)) {
	    if($co =~ /\S/o) {
	    if("$co" eq "-") {
	      $co = undef;
	    } else {
	      if(!exists($usersbyname{"$co"})) {
	        $co = undef;
	      }
	    }
	    } else { $co = undef; }
	    }
	  }
	} else {
	  $cn = undef;
	}
      }
      } else { $cn = undef; }
      }
    }
    if(exists($p->{'us_s'})) {
      $us = $p->{'us_s'};
      if(defined($us)) {
        if($us =~ /\S/o) {
	  if("$us" eq "-") {
	    $us = undef;
	  }
	} else { $us = undef; }
      }
    }
    if(defined($us)) {
      if(defined($cn)) {
        if(defined($co)) {
	  if("$us" eq "$co") {
	    $k = 1;
	  } else {
	    $k = 3;
	  }
	} else {
	  $k = 1;
	}
      } else {
        $k = 2;
      }
    } else {
      if(defined($cn)) {
        if(defined($co)) {
	  $k = 1;
	} else {
	  $k = 4;
	}
      } else {
        $k = 0;
      }
    }
    $p->{'hl'} = $k;
  }
}

sub attach_aliases_to_hosts()
{
  my $i;	# running number to traverse computersbynumber
  my $r;	# current computer (alias target) reference
  my $c;	# current computer (alias target) name
  my $found;	# number of aliases for the current target
  my $array;	# array reference, lists all aliases for current target
  my $k;	# key to traverse aliasesbyname
  my $v;	# value from aliasesbyname
  for($i = 0; $i < $numcomputers; $i++) {
    $r = $computersbynumber[$i];
    $r->{'aliases_list'} = undef;
    $r->{'aliases_found'} = 0;
    if(exists($r->{'co_s'})) {
      $c = $r->{'co_s'};
      if(defined($c)) {
        $found = 0;
	$array = ();
	foreach $k (keys %aliasesbyname) {
	  $v = $aliasesbyname{"$k"};
	  if(exists($v->{'co_s'})) {
	    if(defined($v->{'co_s'})) {
	      $n = $v->{'co_s'};
	      if("$c" eq "$n") {
	        print "FOUND ALIAS $k = $c\n";
		$array->[$found] = "$k";
		$found++;
	      }
	    }
	  }
	}
	if($found > 0) {
	  $r->{'aliases_list'} = $array;
	  $r->{'aliases_found'} = $found;
	}
      }
    }
  }
}

sub do_the_check()
{
  debugmsg(4, "Running consistency check (start)");
  annotate_users();
  annotate_hosts();
  annotate_netgroups();
  attach_aliases_to_hosts();
  check_networks();
  check_datendosen();
  check_ngdeps();
  check_dhcppools();
  # Checking not necessary, a group with the same name
  # can occur in different networks and uses the same
  # options in all networks
  # check_dhcpgroups();
  check_hosts();
  mark_used();
  if($do_licenses) {
    annotate_licenses();
    check_licenses();
  }
  $exval = 0;	# ##### remove this, this deactivates error-checking
  debugmsg(4, "Running consistency check (finished)");
}

sub compare_hosts_by_ip
{
  my $back = 0;
  my $ha; my $hb;
  my $ia; my $ib;
  my $ua1; my $ua2; my $ua3; my $ua4;
  my $ub1; my $ub2; my $ub3; my $ub4;
  if(exists($computersbyname{"$a"})) {
    if(exists($computersbyname{"$b"})) {
      $ha = $computersbyname{"$a"};
      $hb = $computersbyname{"$b"};
      if(defined($ha)) {
        if(defined($hb)) {
	  if(exists($ha->{'co_ip'})) {
	    if(exists($hb->{'co_ip'})) {
	      $ia = $ha->{'co_ip'};
	      $ib = $hb->{'co_ip'};
	      if(defined($ia)) {
	        if(defined($ib)) {
		  if($ia =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		    $ua1 = $1; $ua2 = $2; $ua3 = $3; $ua4 = $4;
		    if($ib =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		      $ub1 = $1; $ub2 = $2; $ub3 = $3; $ub4 = $4;
		      if($ua1 > $ub1) {
		        $back = 1;
		      } else {
		        if($ua1 < $ub1) {
			  $back = -1;
			} else {
			  if($ua2 > $ub2) {
			    $back = 1;
			  } else {
			    if($ua2 < $ub2) {
			      $back = -1;
			    } else {
			      if($ua3 > $ub3) {
			        $back = 1;
			      } else {
			        if($ua3 < $ub3) {
				  $back = -1;
				} else {
				  if($ua4 > $ub4) {
				    $back = 1;
				  } else {
				    if($ua4 < $ub4) {
				      $back = -1;
				    }
				  }
				}
			      }
			    }
			  }
			}
		      }
		    } else {
		      $back = 1;
		    }
		  } else {
		    if($ib =~ /^\s*(\d+)\.(\d+)\.(\d+)\.(\d+)/o) {
		      $back = -1;
		    }
		  }
		} else {
		  $back = 1;
		}
	      } else {
	        if(defined($ib)) {
		  $back = -1;
		}
	      }
	    } else {
	      $back = 1;
	    }
	  } else {
	    if(exists($hb->{'co_ip'})) {
	      $back = -1;
	    }
	  }
	} else {
	  $back = 1;
	}
      } else {
        if(defined($hb)) {
	  $back = -1;
	}
      }
    } else {
      $back = 1;
    }
  } else {
    if(exists($computersbyname{"$b"})) {
      $back = -1;
    }
  }
  if($back == 0) {
    $back = $a <=> $b;
  }
  return $back;
}

sub write_hosts()
{
  my $fn = $confobj->{'outdir'} . "/hosts";
  my $fnf = 0;		# full name first
  my $ddn = undef;	# DNS domain name
  my $i;		# running number
  my $r;		# reference to host
  my $k;		# host name
  my $ip;		# ip address
  my $v;		# value
  my $isfirst;
  my $numaliases;	# total number of aliases;
  my $currentalias;	# used in for loop
  my $arrayaliases;	# array reference
  if(open(OUTPUT, ">$fn")) {
    print OUTPUT "127.0.0.1\tlocalhost\tloopback\n";
    if($confobj->{'cohosts'}) {
      print OUTPUT "\n";
    }
    for($i = 0; $i < $numcomputers; $i++) {
      $r = $computersbynumber[$i];
      $k = $r->{'co_s'};
      $fnf = 0; $ddn = undef;
      if(exists($r->{'co_ip'})) {
        $ip = $r->{'co_ip'};
	if(defined($ip)) {
	  if($ip =~ /^\s*(\d+\.\d+\.\d+\.\d+)/o) {
	    $ip = $1;
	    if($confobj->{'cohosts'}) {
	      if(exists($r->{'co_co'})) {
	        $v = $r->{'co_co'};
		if(defined($v)) {
		  if($v =~ /^\s*(\S.*\S)\s*$/o) {
		    $v = $1;
		    print OUTPUT "# $v\n";
		  }
		}
	      }
	    }
	    print OUTPUT "$ip\t";
	    if(length($ip) < 8) { print OUTPUT "\t"; }
	    if(exists($r->{'co_dd'})) {
	      $v = $r->{'co_dd'};
	      if(defined($v)) {
	        if($v =~ /(\S+)/o) {
		  $ddn = $1;
		  if(exists($r->{'co_ff'})) {
		    $v = $r->{'co_ff'};
		    if(defined($v)) {
		      if($v =~ /(\d+)/o) {
		        $fnf = $1;
			$fnf = 0 + $fnf;
		      }
		    }
		  }
		}
	      }
	    }
	    if(defined($ddn) && ($fnf > 0)) {
	      print OUTPUT "$k.$ddn ";
	    }
	    print OUTPUT "$k";
	    if(exists($r->{'aliases_found'})) {
	      $numaliases = $r->{'aliases_found'};
	      if(exists($r->{'aliases_list'})) {
	        $arrayaliases = $r->{'aliases_list'};
		if(defined($arrayaliases)) {
		  for($currentalias = 0; $currentalias < $numaliases; $currentalias++) {
		    print OUTPUT " " . $arrayaliases->[$currentalias];
		  }
		}
	      }
	    }
	    print OUTPUT "\n";
	    if($confobj->{'cohosts'}) { 
	      print OUTPUT "\n";
	    }
	  }
	}
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to open file \"$fn\"!");
  }
}

sub write_ethers_file_by_name($)
{
  my $fn = shift;
  my $i; my $k; my $r; my $ip; my $et; my $v;
  my $hn;
  $fn = $confobj->{'outdir'} . $fn;
  if(open(OUTPUT, ">$fn")) {
    for($i = 0; $i < $numcomputers; $i++) {
      $r = $computersbynumber[$i];
      $k = $r->{'co_s'};
      $ip = undef; $et = undef; $hn = undef;
      if(exists($r->{'co_ip'})) {
        $v = $r->{'co_ip'};
	if(defined($v)) {
	  if($v =~ /^\s*(\d+\.\d+\.\d+\.\d+)/o) {
	    $ip = $1;
	  }
	}
      }
      if(exists($r->{'co_s'})) {
        $v = $r->{'co_s'};
	if(defined($v)) {
	  $hn = $v;
	}
      }
      if(exists($r->{'co_mc'})) {
        $v = $r->{'co_mc'};
	if(defined($v)) {
	  if($v =~ /^\s*([01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f])/o) {
	    $et = $1;
	  }
	}
      }
      if(defined($ip) && defined($et) && defined($hn)) {
        if($confobj->{'coethers'}) {
	  print OUTPUT "# $k";
	  if(exists($r->{'co_co'})) {
	    $v = $r->{'co_co'};
	    if(defined($v)) {
	      if($v =~ /^\s*(\S.*\S)\s*$/o) {
	        $v = $1;
		print OUTPUT ": $v";
	      }
	    }
	  }
	  print OUTPUT "\n";
	}
	print OUTPUT "$et\t$hn\n";
	if($confobj->{'coethers'}) {
	  print OUTPUT "\n";
	}
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write to file $fn!");
    $exval = 1;
  }
}

sub write_ethers_file($$)
{
  my $fn = shift;
  my $turned = shift;
  my $i; my $k; my $r; my $ip; my $et; my $v;
  $fn = $confobj->{'outdir'} . $fn;
  if(open(OUTPUT, ">$fn")) {
    for($i = 0; $i < $numcomputers; $i++) {
      $r = $computersbynumber[$i];
      $k = $r->{'co_s'};
      $ip = undef; $et = undef;
      if(exists($r->{'co_ip'})) {
        $v = $r->{'co_ip'};
	if(defined($v)) {
	  if($v =~ /^\s*(\d+\.\d+\.\d+\.\d+)/o) {
	    $ip = $1;
	  }
	}
      }
      if(exists($r->{'co_mc'})) {
        $v = $r->{'co_mc'};
	if(defined($v)) {
	  if($v =~ /^\s*([01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f])/o) {
	    $et = $1;
	  }
	}
      }
      if(defined($ip) && defined($et)) {
        if($confobj->{'coethers'}) {
	  print OUTPUT "# $k";
	  if(exists($r->{'co_co'})) {
	    $v = $r->{'co_co'};
	    if(defined($v)) {
	      if($v =~ /^\s*(\S.*\S)\s*$/o) {
	        $v = $1;
		print OUTPUT ": $v";
	      }
	    }
	  }
	  print OUTPUT "\n";
	}
        if($turned) {
	  print OUTPUT "$ip\t";
	  if(length($ip) < 8) { print OUTPUT "\t"; }
	  print OUTPUT "$et\n";
	} else {
	  print OUTPUT "$et\t$ip\n";
	}
	if($confobj->{'coethers'}) {
	  print OUTPUT "\n";
	}
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write to file $fn!");
    $exval = 1;
  }
}


sub write_ethers()
{
  write_ethers_file_by_name("/ethers");
  write_ethers_file("/ethers-ip", 0);
  write_ethers_file("/ethers-byip", 1);
}

sub write_netgroups_ldif($$$$)
{
  my $bmd = shift; my $bmi = shift;
  my $bmn = shift; my $bmni = shift;
  my $i; my $j; my $k; my $isfirst;
  my $ng; my $h; my $ip; my $ddn; my $ngn; my $ngd;
  my $b = $confobj->{'ldapbase'};
  my $fn = $confobj->{'outdir'} . "/netgroup.ldif";
  debugmsg(4, "Writing netgroups file (start)");
  if(open(OUTPUT, ">$fn")) {
    for($i = 0; $i < $numnetgroups; $i++) {
      $ng = $netgroupsbynumber[$i];
      $ngn = $ng->{'ng_s'};
      $ngd = undef;
      if(exists($n->{'ng_l'})) {
        $ngd = $n->{'ng_l'};
      }
      $isfirst = 1;
      for($j = 0; $j < $numcomputers; $j++) {
	if(($bmd->get($i, $j)) || ($bmi->get($i, $j))) {
          $h = $computersbynumber[$j];
	  $k = $h->{'co_s'};
	  if(exists($h->{'co_ip'})) {
	    if(exists($h->{'co_dd'})) {
	      $ip = $h->{'co_ip'};
	      $ddn =$h->{'co_dd'};
	      if(defined($ip) && defined($ddn)) {
	        if($isfirst) {
		  print OUTPUT "dn: cn=$ngn,ou=netgroup,$b\n";
		  print OUTPUT "objectClass: top\n";
		  print OUTPUT "objectClass: nisNetgroup\n";
		  print OUTPUT "cn: $ngn\n";
		  if(defined($ngd)) {
		    if($ngd =~ /\S/o) {
		      chomp $ngd;
		      print OUTPUT "description: $ngd\n";
		    }
		  }
		}
		$isfirst = 0;
		print OUTPUT "nisNetgroupTriple: ($k,,$ddn)\n";
		print OUTPUT "nisNetgroupTriple: ($k.$ddn,,$ddn)\n";
		print OUTPUT "nisNetgroupTriple: ($ip,,$ddn)\n";
	      }
	    }
	  }
	}
      }
      if(!$isfirst) {
        print OUTPUT "\n";
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write netgroup.ldif!");
  }
  debugmsg(4, "Writing netgroups file (finished)");
}

# netgroup = x
# host = y

# parent = x
# child = y

sub fill_matrices($$$$)
{
  my $bmd = shift; my $bmi = shift;
  my $bmn = shift; my $bmni = shift;
  my $i; my $r; my $v; my $n; my $ngref; my $k;
  for($i = 0; $i < $numcomputers; $i++) {
    $r = $computersbynumber[$i];
    $k = $r->{'co_s'};
    if($r->{'co_ip'}) {
      $v = $r->{'co_ip'};
      if(defined($v)) {
        if($v =~ /^\s*\d+\.\d+\.\d+\.\d+/o) {
	  if(exists($r->{'ng_s'})) {
	    $v = $r->{'ng_s'};
	    if(defined($v)) {
	      chomp $v;
	      while($v =~ /(\S+)\s+(\S.*)/o) {
	        $n = $1; $v = $2;
		if(exists($netgroupsbyname{"$n"})) {
		  $ngref = $netgroupsbyname{"$n"};
		  $bmd->set($ngref->{'anno'}, $r->{'anno'});
		  $bmi->set($ngref->{'anno'}, $r->{'anno'});
		} else {
		  debugmsg(1, "Netgroup $n does not exist!");
		  $exval = 1;
		}
	      }
	      if(exists($netgroupsbyname{"$v"})) {
	        $ngref = $netgroupsbyname{"$v"};
		$bmd->set($ngref->{'anno'}, $r->{'anno'});
		$bmi->set($ngref->{'anno'}, $r->{'anno'});
	      } else {
	        debugmsg(1, "Netgroup $v does not exist!");
		$exval = 1;
	      }
	    }
	  }
	}
      }
    }
  }
  foreach $k (keys %ngdepsbypk) {
    $r = $ngdepsbypk{"$k"};
    $n = undef; $k = undef;
    if(exists($r->{'nd_p'})) {
      $v = $r->{'nd_p'};
      if(defined($v)) {
        if($v =~ /\S+/o) {
	  chomp $v;
	  if(exists($netgroupsbyname{"$v"})) {
	    $n = $netgroupsbyname{"$v"};
	    $n = $n->{'anno'};
	  } else {
	    debugmsg(1, "Netgroup $v not found!");
	    $exval = 1;
	  }
	}
      }
    }
    if(exists($r->{'nd_c'})) {
      $v = $r->{'nd_c'};
      if(defined($v)) {
        if($v =~ /\S+/o) {
	  chomp $v;
	  if(exists($netgroupsbyname{"$v"})) {
	    $k = $netgroupsbyname{"$v"};
	    $k = $k->{'anno'};
	  } else {
	    debugmsg(1, "Netgroup $v not found!");
	    $exval = 1;
	  }
	}
      }
    }
    if(defined($n) && defined($k)) {
      $bmn->set($n, $k);
      $bmni->set($n, $k);
    }
  }
}

# sub expand_matrices($$$$)
# {
#   my $bmd = shift; my $bmi = shift;
#   my $bmn = shift; my $bmni = shift;
#   my $i;	# netgroup
#   my $j;	# computer
#   my $k;	# test result after loop
#   my $l;	# netgroup in test loop
#   $bmni->expand();
#   for($i = 0; $i < $numnetgroups; $i++) {
#     for($j = 0; $j < $numcomputers; $j++) {
#       if(!($bmi->get($i, $j))) {
#         $k = 0;
# 	for($l = 0; $l < $numnetgroups; $l++) {
# 	  if($bmi->get($l, $j)) {
# 	    if($bmni->get($i, $l)) {
# 	      $k = 1; $l = $numnetgroups;
# 	    }
# 	  }
# 	}
# 	if($k) {
# 	  $bmi->set($i, $j);
# 	}
#       }
#     }
#   }
# }

sub expand_matrices($$$$)
{
  my $bmd = shift; my $bmi = shift;
  my $bmn = shift; my $bmni = shift;
  my $i; my $j; my $k;
  $bmni->expand();
  for($i = 0; $i < $numnetgroups; $i++) {
    for($j = 0; $j < $numcomputers; $j++) {
      if($bmd->get($i,$j)) {
        $bmi->set($i, $j);
        for($k = 0; $k < $numnetgroups; $k++) {
	  if($bmni->get($k, $i)) {
	    $bmi->set($k, $j);
	  }
	}
      }
    }
  }
  my $inbmd = 0; my $inbmi = 0; my $inbmn = 0; my $inbmni = 0;
  for($i = 0; $i < $numnetgroups; $i++) {
    for($j = 0; $j < $numcomputers; $j++) {
      if($bmd->get($i, $j)) {
        $inbmd++;
      }
      if($bmi->get($i, $j)) {
        $inbmi++;
      }
    }
    for($j = 0; $j < $numnetgroups; $j++) {
      if($bmn->get($i, $j)) {
        $inbmn++;
      }
      if($bmni->get($i, $j)) {
        $inbmni++;
      }
    }
  }
  debugmsg(2, "bmd=$inbmd bmi=$inbmi bmn=$inbmn bmni=$inbmni.");
}

sub lstr($)
{
  my $back = shift;
  if(defined($latexencoder)) {
    $back = $latexencoder->convert($back);
  } else {
    $back =~ s/_/\\textunderline{}/g;
    $back =~ s/#/\\#/g;
    $back =~ s/{/\\{/g;
    $back =~ s/}/\\}/g;
    $back =~ s/\$/\\textdollar{}/g;
  }
  return $back;
}

sub get_full_user_name($)
{
  my $u = shift;
  my $back = undef;
  my $t = undef; my $s = undef; my $f = undef;
  if(exists($u->{'us_t'})) {
    $t = $u->{'us_t'};
    if(defined($t)) {
      chomp $t;
      if("$t" eq "") {
        $t = undef;
      }
    }
  }
  if(exists($u->{'us_sn'})) {
    $s = $u->{'us_sn'};
    if(defined($s)) {
      chomp $s;
      if("$s" eq "") {
        $s = undef;
      }
    }
  }
  if(exists($u->{'us_fn'})) {
    $f = $u->{'us_fn'};
    if(defined($f)) {
      chomp $f;
      if("$f" eq "") {
        $f = undef;
      }
    }
  }
  if(exists($u->{'us_s'})) {
    $back = $u->{'us_s'};
  }
  if(defined($f)) {
    $back = $f;
    if(defined($s)) {
      $back = "$s $back";
    }
    if(defined($t)) {
      $back = "$t $back";
    }
  }
  return $back;
}

sub write_netdocu($$$$)
{
  my $bmd = shift; my $bmi = shift;
  my $bmn = shift; my $bmni = shift;
  my $preamble;
  my $fn = $confobj->{'outdir'} . "/netdocu.tex";
  my $i; my $j; my $k; my $r; my $u;
  my $have_a_host; my $print_this_host;
  my $full_user_name; my $short_user_name;
  my $havedata; my $dhcpcref; my $gb; my $ngref;
  my $aliasesfound; my $aliaseslist; my $aliasno;
  if(open(OUTPUT, ">$fn")) {
    # preamble
    $preamble = $textobj->get_latex_preamble();
    foreach $k (@$preamble) {
      print OUTPUT "$k\n";
    }
    # HOSTS
    for($i = 0; $i < $numcomputers; $i++) {
      $r = $computersbynumber[$i];
      $r->{'shown_in_documentation'} = 0;
    }
    print OUTPUT "\\section{" . $textobj->get(0) . "}\n";
    for($i = 0; $i <= $numusers; $i++) {
      $u = undef;
      $have_a_host = 0;
      $full_user_name = undef; $short_user_name = undef;
      if($i < $numusers) {
        $u = $usersbynumber[$i];
	$full_user_name = get_full_user_name($u);
	if(exists($u->{'us_fn'})) {
	  $short_user_name = $u->{'us_fn'};
	  if(defined($short_user_name)) {
	    chomp $short_user_name;
	    if("$short_user_name" eq "") {
	      $short_user_name = undef;
	    }
	  }
	}
      } else {
        $full_user_name = $textobj->get(22);
      }
      for($j = 0; $j < $numcomputers; $j++) {
        $r = $computersbynumber[$j];
	$print_this_host = 0;
	if($i < $numusers) {
	  if(exists($u->{'us_s'})) {
	  if(defined($u->{'us_s'})) {
	  if($u->{'us_s'} =~ /\S/o) {
	  if($u->{'us_s'} ne "-") {
	    if(exists($r->{'us_s'})) {
	    if(defined($r->{'us_s'})) {
	    if($r->{'us_s'} =~ /\S/o) {
	      if($r->{'us_s'} eq $u->{'us_s'}) {
	        $print_this_host = 1;
	      }
	    }
	    }
	    }
	  }
	  }
	  }
	  }
	} else {
	  if($r->{'shown_in_documentation'} == 0) {
	    $print_this_host = 1;
	  }
	}
	if($print_this_host) {
	  if(exists($r->{'co_nn'})) {
	  if(defined($r->{'co_nn'})) {
	  if($r->{'co_nn'}) {
	    $print_this_host = 0;
	  }
	  }
	  }
	}
	if($print_this_host) {
	  if(!$have_a_host) {
	    if(defined($full_user_name)) {
	      print OUTPUT "\\subsection";
	      if(defined($short_user_name)) {
	        print OUTPUT "[" . lstr($short_user_name) . "]";
	      }
	      print OUTPUT "{" . lstr($full_user_name) . "}";
	      print OUTPUT "\\label{sec:h-" . $r->{'anno'} . "}\n";
	      $have_a_host = 1;

	    }
	  }
	  if($i == $numusers) {
	    $full_user_name = undef;
	  }
	  print OUTPUT "\\subsubsection{" . lstr($r->{'co_s'}) . "}";
	  print OUTPUT "\\index{Hosts!" . lstr($r->{'co_s'}) . "}\n";
	  # Overview
	  print OUTPUT "\\paragraph{" . $textobj->get(2) . "}~\\\\*[0.5em]\n";
	  print OUTPUT "\\begin{tabular}{ll}\n";
	  print OUTPUT $textobj->get(3) . "&";
	  if(defined($full_user_name)) {
	    print OUTPUT $full_user_name;
	  } else {
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	  }
	  print OUTPUT "\\\\\n";
	  # Verwendungszweck
	  print OUTPUT $textobj->get(5) . "&";
	  $havedata = 0;
	  if(exists($r->{'co_co'})) {
	    if(defined($r->{'co_co'})) {
	      if($r->{'co_co'} =~ /\S/o) {
	        print OUTPUT lstr($r->{'co_co'});
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	  }
	  print OUTPUT "\\\\\n";
	  # Aufstellungsort (Gebaeude und Raum)
	  print OUTPUT $textobj->get(6) . "&";
	  $havedata = 0;
	  if(exists($r->{'gb_s'})) {
	    if(defined($r->{'gb_s'})) {
	      $gb = $r->{'gb_s'};
	      if(exists($buildingsbyname{"$gb"})) {
	        $gb = $buildingsbyname{"$gb"};
	        print OUTPUT lstr($gb->{'gb_l'});
	        $havedata = 1;
	      }
	    }
	  }
	  if(exists($r->{'co_r'})) {
	    if(defined($r->{'co_r'})) {
	      if($r->{'co_r'} =~ /\S/o) {
	        if($havedata) {
	          print OUTPUT ", ";
	        } $havedata = 1;
	        print OUTPUT lstr($r->{'co_r'});
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	  }
	  print OUTPUT "\\\\\n";
	  # Inventarnummer
	  print OUTPUT $textobj->get(7) . "&";
	  $havedata = 0;
	  if(exists($r->{'co_in'})) {
	    if(defined($r->{'co_in'})) {
	      if($r->{'co_in'} =~ /\S/o) {
	        print OUTPUT lstr($r->{'co_in'});
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	  }
	  print OUTPUT "\\\\\n";
	  # Seriennummer
	  print OUTPUT $textobj->get(8) . "&";
	  $havedata = 0;
	  if(exists($r->{'co_sn'})) {
	    if(defined($r->{'co_sn'})) {
	      if($r->{'co_sn'} =~ /\S/o) {
	        print OUTPUT lstr($r->{'co_sn'});
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	  }
	  print OUTPUT "\\\\\n";
	  # Host-ID falls vorhanden
	  if(exists($r->{'co_hi'})) {
	    if(defined($r->{'co_hi'})) {
	      if($r->{'co_hi'} =~ /\S/o) {
	        print OUTPUT $textobj->get(9) . "&" . lstr($r->{'co_hi'}) . "\\\\\n";
	      }
	    }
	  }
	  print OUTPUT "\\end{tabular}\\\\*[0.5em]\n";
	  # Network
	  print OUTPUT "\\paragraph{" . $textobj->get(10) . "}~\\\\*[0.5em]\n";
	  print OUTPUT "\\begin{tabular}{lll}\n";
	  # Aliases (if any)
	  if(exists($r->{'aliases_found'})) {
	    $aliasesfound = $r->{'aliases_found'};
	    if($aliasesfound > 0) {
	      if(exists($r->{'aliases_list'})) {
	        $aliaseslist = $r->{'aliases_list'};
		if(defined($aliaseslist)) {
		  for($aliasno = 0; $aliasno < $aliasesfound; $aliasno++) {
		    print OUTPUT $textobj->get(35). "&";
		    print OUTPUT "\\multicolumn{2}{l}{";
		    print OUTPUT lstr($aliaseslist->[$aliasno]);
		    print OUTPUT "}\\\\\n";
		  }
		}
	      }
	    }
	  }
	  # IP-Adresse
	  print OUTPUT $textobj->get(11) . "&";
	  $havedata = 0;
	  if(exists($r->{'co_ip'})) {
	    if(defined($r->{'co_ip'})) {
	      if($r->{'co_ip'} =~ /\S/o) {
	        print OUTPUT "\\multicolumn{2}{l}{";
	        print OUTPUT $r->{'co_ip'};
	        print OUTPUT "}";
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\multicolumn{2}{l}{";
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	  }
	  print OUTPUT "\\\\\n";
	  # DNS-Domain
	  print OUTPUT $textobj->get(17) . "&";
	  $havedata = 0;
	  if(exists($r->{'co_dd'})) {
	    if(defined($r->{'co_dd'})) {
	      if($r->{'co_dd'} =~ /\S/o) {
	        print OUTPUT "\\multicolumn{2}{l}{";
	        print OUTPUT lstr($r->{'co_dd'});
	        print OUTPUT "}";
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\multicolumn{2}{l}{";
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	  }
	  print OUTPUT "\\\\\n";
	  # MAC-Adresse
	  print OUTPUT $textobj->get(12) . "&";
	  $havedata = 0;
	  if(exists($r->{'co_mc'})) {
	    if(defined($r->{'co_mc'})) {
	      if($r->{'co_mc'} =~ /\S/o) {
	        print OUTPUT "\\multicolumn{2}{l}{";
	        print OUTPUT $r->{'co_mc'};
	        print OUTPUT "}";
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\multicolumn{2}{l}{";
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	  }
	  print OUTPUT "\\\\\n";
	  # Datendose
	  print OUTPUT $textobj->get(13) . "&";
	  $havedata = 0;
	  if(exists($r->{'dd_n'})) {
	    if(defined($r->{'dd_n'})) {
	      if($r->{'dd_n'} =~ /\S/o) {
	        print OUTPUT "\\multicolumn{2}{l}{";
	        print OUTPUT lstr($r->{'dd_n'});
	        print OUTPUT "}";
	        $havedata = 1;
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\multicolumn{2}{l}{";
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	  }
	  print OUTPUT "\\\\\n";
	  # DHCP-Klasse
	  print OUTPUT $textobj->get(14) . "&";
	  $havedata = 0;
	  if(exists($r->{'dc_s'})) {
	    if(defined($r->{'dc_s'})) {
	      if($r->{'dc_s'} =~ /\S/o) {
	        print OUTPUT lstr($r->{'dc_s'});
	        $havedata = 1;
	        print OUTPUT "&";
	        $dhcpcref = $r->{'dc_s'};
	        if(exists($dhcpclassesbyname{"$dhcpcref"})) {
	          $dhcpcref = $dhcpclassesbyname{"$dhcpcref"};
		  if(exists($dhcpcref->{'dc_d'})) {
		    if(defined($dhcpcref->{'dc_d'})) {
		      if($dhcpcref->{'dc_d'} =~ /\S/o) {
		        print OUTPUT lstr($dhcpcref->{'dc_d'});
		      }
		    }
		  }
	        }
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\multicolumn{2}{l}{";
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	  }
	  print OUTPUT "\\\\\n";
	  # DHCP-Gruppe
	  print OUTPUT $textobj->get(15) . "&";
	  $havedata = 0;
	  if(exists($r->{'dg_s'})) {
	    if(defined($r->{'dg_s'})) {
	      if($r->{'dg_s'} =~ /\S/o) {
	        print OUTPUT lstr($r->{'dg_s'});
	        $havedata = 1;
	        print OUTPUT "&";
	        $dhcpcref = $r->{'dg_s'};
	        if(exists($dhcpgroupsbyname{"$dhcpcref"})) {
	          $dhcpcref = $dhcpgroupsbyname{"$dhcpcref"};
		  if(exists($dhcpcref->{'dg_l'})) {
		    if(defined($dhcpcref->{'dg_l'})) {
		      if($dhcpcref->{'dg_l'} =~ /\S/o) {
		        print OUTPUT lstr($dhcpcref->{'dg_l'});
		      }
		    }
		  }
	        }
	      }
	    }
	  }
	  if(!$havedata) {
	    print OUTPUT "\\multicolumn{2}{l}{";
	    print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	  }
	  print OUTPUT "\\\\\n";
	  print OUTPUT "\\end{tabular}\\\\*[0.5em]\n";
	  # Netgroups
	  $havedata = 0;
	  for($l = 0; $l < $numnetgroups; $l++) {
	    if($bmd->get($l, $j)) {
	      $ngref = $netgroupsbynumber[$l];
	      if(!$havedata) {
	        print OUTPUT "\\paragraph{" . $textobj->get(18) . "}~\\\\*[0.5em]\n";
		print OUTPUT "\\begin{tabular}{ll}\n";
		$havedata = 1;
	      }
	      if(exists($ngref->{'ng_s'})) {
	      if(defined($ngref->{'ng_s'})) {
	        print OUTPUT "\\textbf{" . lstr($ngref->{'ng_s'}) . "}";
	      }
	      }
	      print OUTPUT "&";
	      if(exists($ngref->{'ng_l'})) {
	      if(defined($ngref->{'ng_l'})) {
	        print OUTPUT lstr($ngref->{'ng_l'});
	      }
	      }
	      print OUTPUT "\\\\\n";
	    }
	  }
	  if($havedata) {
	    for($l = 0; $l < $numnetgroups; $l++) {
	      if(($bmi->get($l, $j)) && (!($bmd->get($l, $j)))) {
	        $ngref = $netgroupsbynumber[$l];
	        if(exists($ngref->{'ng_s'})) {
	        if(defined($ngref->{'ng_s'})) {
	          print OUTPUT lstr($ngref->{'ng_s'});
	        }
	        }
	        print OUTPUT "&";
	        if(exists($ngref->{'ng_l'})) {
	        if(defined($ngref->{'ng_l'})) {
	          print OUTPUT lstr($ngref->{'ng_l'});
	        }
	        }
	        print OUTPUT "\\\\\n";
	      }
	    }
	    print OUTPUT "\\end{tabular}\\\\*[0.5em]\n";
	  }
	  print OUTPUT "\\vfill\n\\clearpage\n";
	  $r->{'shown_in_documentation'} = 1;
	}
      }
    }
    # Hosts alphabetically
    $isfirst = 1;
    foreach $k (sort (keys %computersbyname)) {
      $r = $computersbyname{"$k"};
    }


    # NETGROUPS
    print OUTPUT "\\section{" . $textobj->get(1) . "}\n";
    for($i = 0; $i < $numnetgroups; $i++) {
      $ngref = $netgroupsbynumber[$i];
      print OUTPUT "\\subsection{" . lstr($ngref->{'ng_s'}) . "}";
      print OUTPUT "\\label{sec:n-" . $ngref->{'anno'} . "}";
      print OUTPUT "\\index{Netgroup!" . lstr($ngref->{'ng_s'}) . "}\n";
      if(exists($ngref->{'ng_l'})) {
      if(defined($ngref->{'ng_l'})) {
      if($ngref->{'ng_l'} =~ /\S/o) {
        print OUTPUT lstr($ngref->{'ng_l'}) . "\\\\*[0.5em]\n";
      }
      }
      }
      # parents
      $havedata = 0;
      for($j = 0; $j < $numnetgroups; $j++) {
        if($bmn->get($j, $i)) {
	  if(!$havedata) {
	    print OUTPUT "\\subsubsection{" . $textobj->get(19) . "}\n";
	    print OUTPUT "\\begin{longtable}{ll}\n";
	    print OUTPUT "\\endfirsthead\n";
	    print OUTPUT "\\endhead\n";
	    print OUTPUT "\\endfoot\n";
	    print OUTPUT "\\endlastfoot\n";
	  }
	  $havedata = 1;
	  $u = $netgroupsbynumber[$j];
	  if(exists($u->{'ng_s'})) {
	  if(defined($u->{'ng_s'})) {
	  if($u->{'ng_s'}) {
	    print OUTPUT "\\textbf{" . lstr($u->{'ng_s'}) . "}";
	  }
	  }
	  }
	  print OUTPUT "&";
	  if(exists($u->{'ng_l'})) {
	  if(defined($u->{'ng_l'})) {
	  if($u->{'ng_l'} =~ /\S/o) {
	    print OUTPUT lstr($u->{'ng_l'});
	  }
	  }
	  }
	  print OUTPUT "\\\\\n";
	}
      }
      if($havedata) {
        for($j = 0; $j < $numnetgroups; $j++) {
          if(($bmni->get($j, $i)) && (!($bmn->get($j, $i)))) {
	    $u = $netgroupsbynumber[$j];
	    if(exists($u->{'ng_s'})) {
	    if(defined($u->{'ng_s'})) {
	    if($u->{'ng_s'}) {
	      print OUTPUT lstr($u->{'ng_s'});
	    }
	    }
	    }
	    print OUTPUT "&";
	    if(exists($u->{'ng_l'})) {
	    if(defined($u->{'ng_l'})) {
	    if($u->{'ng_l'} =~ /\S/o) {
	      print OUTPUT lstr($u->{'ng_l'});
	    }
	    }
	    }
	    print OUTPUT "\\\\\n";
	  }
        }
        print OUTPUT "\\end{longtable}\n";
      }
      # children
      $havedata = 0;
      for($j = 0; $j < $numnetgroups; $j++) {
        if($bmn->get($i, $j)) {
	  if(!$havedata) {
	    print OUTPUT "\\subsubsection{" . $textobj->get(20) . "}\n";
	    print OUTPUT "\\begin{longtable}{ll}\n";
	    print OUTPUT "\\endfirsthead\n";
	    print OUTPUT "\\endhead\n";
	    print OUTPUT "\\endfoot\n";
	    print OUTPUT "\\endlastfoot\n";
	  }
	  $havedata = 1;
	  $u = $netgroupsbynumber[$j];
	  if(exists($u->{'ng_s'})) {
	  if(defined($u->{'ng_s'})) {
	  if($u->{'ng_s'}) {
	    print OUTPUT "\\textbf{" . lstr($u->{'ng_s'}) . "}";
	  }
	  }
	  }
	  print OUTPUT "&";
	  if(exists($u->{'ng_l'})) {
	  if(defined($u->{'ng_l'})) {
	  if($u->{'ng_l'} =~ /\S/o) {
	    print OUTPUT lstr($u->{'ng_l'});
	  }
	  }
	  }
	  print OUTPUT "\\\\\n";
	}
      }
      if($havedata) {
        for($j = 0; $j < $numnetgroups; $j++) {
          if(($bmni->get($i, $j)) && (!($bmn->get($i, $j)))) {
	    $u = $netgroupsbynumber[$j];
	    if(exists($u->{'ng_s'})) {
	    if(defined($u->{'ng_s'})) {
	    if($u->{'ng_s'}) {
	      print OUTPUT lstr($u->{'ng_s'});
	    }
	    }
	    }
	    print OUTPUT "&";
	    if(exists($u->{'ng_l'})) {
	    if(defined($u->{'ng_l'})) {
	    if($u->{'ng_l'} =~ /\S/o) {
	      print OUTPUT lstr($u->{'ng_l'});
	    }
	    }
	    }
	    print OUTPUT "\\\\\n";
	  }
        }
        print OUTPUT "\\end{longtable}\n";
      }
      # hosts
      $havedata = 0;
      for($j = 0; $j < $numcomputers; $j++) {
        $u = $computersbynumber[$j];
	if($bmd->get($i, $j)) {
	  if(!$havedata) {
	    print OUTPUT "\\subsubsection{" . $textobj->get(21) . "}\n";
	    print OUTPUT "\\begin{longtable}{ll}\n";
	    print OUTPUT "\\endfirsthead\n";
	    print OUTPUT "\\endhead\n";
	    print OUTPUT "\\endfoot\n";
	    print OUTPUT "\\endlastfoot\n";
	  } $havedata = 1;
	  print OUTPUT "\\textbf{" . lstr($u->{'co_s'}) . "}";
	  print OUTPUT "&";
	  if(exists($u->{'co_co'})) {
	  if(defined($u->{'co_co'})) {
	  if($u->{'co_co'} =~ /\S/o) {
	    print OUTPUT lstr($u->{'co_co'});
	  }
	  }
	  }
	  print OUTPUT "\\\\\n";
	}
      }
      for($j = 0; $j < $numcomputers; $j++) {
        $u = $computersbynumber[$j];
	if(($bmi->get($i, $j)) && (!($bmd->get($i, $j)))) {
	  if(!$havedata) {
	    print OUTPUT "\\subsubsection{" . $textobj->get(21) . "}\n";
	    print OUTPUT "\\begin{longtable}{ll}\n";
	    print OUTPUT "\\endfirsthead\n";
	    print OUTPUT "\\endhead\n";
	    print OUTPUT "\\endfoot\n";
	    print OUTPUT "\\endlastfoot\n";
	  } $havedata = 1;
	  print OUTPUT lstr($u->{'co_s'});
	  print OUTPUT "&";
	  if(exists($u->{'co_co'})) {
	  if(defined($u->{'co_co'})) {
	  if($u->{'co_co'} =~ /\S/o) {
	    print OUTPUT lstr($u->{'co_co'});
	  }
	  }
	  }
	  print OUTPUT "\\\\\n";
	}
      }
      if($havedata) {
        print OUTPUT "\\end{longtable}\n";
      }
      print OUTPUT "\\vfill\\clearpage\n";
    }
    # postamble
    $preamble = $textobj->get_latex_postamble();
    foreach $k (@$preamble) {
      print OUTPUT "$k\n";
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write \"$fn\"!");
  }
}

sub write_old_netdocu($$$$)
{
  my $bmd = shift; my $bmi = shift;
  my $bmn = shift; my $bmni = shift;
  my $r; my $exclude_from_docu; my $u; my $found;
  my $havedata; my $gb; my $preamble; my $k;
  my $i; my $j;
  debugmsg(4, "Write network documentation (start)");
  my $fn = $confobj->{'outdir'} . "/netdocu.tex";
  if(open(OUTPUT, ">$fn")) {
    # preamble
    $preamble = $textobj->get_latex_preamble();
    foreach $k (@$preamble) {
      print OUTPUT "$k\n";
    }
    # Hosts section
    print OUTPUT "\\section{" . $textobj->get(0) . "}\n";
    for($k = 0; $k < $numcomputers; $k++) {
      $r = $computersbynumber[$k];
      $exclude_from_docu = 0;
      if(exists($r->{'co_nn'})) {
        if(defined($r->{'co_nn'})) {
	  if($r->{'co_nn'}) {
	    $exclude_from_docu = 1;
	  }
	}
      }
      if(!$exclude_from_docu) {
        print OUTPUT "\\subsection{" . lstr($r->{'co_s'}) . "}";
	print OUTPUT "\\label{sec:h-" . $r->{'anno'} . "}\n";
	print OUTPUT "\\subsubsection{" . $textobj->get(2) . "}\n";
	print OUTPUT "\\begin{tabular}{ll}\n";
	# Name
	print OUTPUT $textobj->get(3) . "&";
	$found = 0;
	$havedata = 0;
	if(exists($r->{'us_s'})) {
	  if(defined($r->{'us_s'})) {
	    $u = $r->{'us_s'};
	    if(exists($usersbyname{"$u"})) {
	      $u = $usersbyname{"$u"};
	      if(exists($u->{'us_t'})) {
	        if(defined($u->{'us_t'})) {
	          if($u->{'us_t'} =~ /\S/o) {
	            print OUTPUT lstr($u->{'us_t'});
		    $havedata = 1;
	          }
	        }
	      }
	      if(exists($u->{'us_sn'})) {
	        if(defined($u->{'us_sn'})) {
	          if($u->{'us_sn'} =~ /\S/o) {
	            if($havedata) {
		      print OUTPUT " ";
		    } $havedata = 1;
		    print OUTPUT lstr($u->{'us_sn'});
	          }
	        }
	      }
	      if(exists($u->{'us_fn'})) {
	        if(defined($u->{'us_fn'})) {
	          if($u->{'us_fn'} =~ /\S/o) {
	            if($havedata) {
		      print OUTPUT " ";
		    } $havedata = 1;
		    print OUTPUT lstr($u->{'us_fn'});
	          }
	        }
	      }
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	}
	print OUTPUT "\\\\\n";
	# Verwendungszweck
	print OUTPUT $textobj->get(5) . "&";
	$havedata = 0;
	if(exists($r->{'co_co'})) {
	  if(defined($r->{'co_co'})) {
	    if($r->{'co_co'} =~ /\S/o) {
	      print OUTPUT lstr($r->{'co_co'});
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	}
	print OUTPUT "\\\\\n";
	# Aufstellungsort (Gebaeude und Raum)
	print OUTPUT $textobj->get(6) . "&";
	$havedata = 0;
	if(exists($r->{'gb_s'})) {
	  if(defined($r->{'gb_s'})) {
	    $gb = $r->{'gb_s'};
	    if(exists($buildingsbyname{"$gb"})) {
	      $gb = $buildingsbyname{"$gb"};
	      print OUTPUT lstr($gb->{'gb_l'});
	      $havedata = 1;
	    }
	  }
	}
	if(exists($r->{'co_r'})) {
	  if(defined($r->{'co_r'})) {
	    if($r->{'co_r'} =~ /\S/o) {
	      if($havedata) {
	        print OUTPUT ", ";
	      } $havedata = 1;
	      print OUTPUT lstr($r->{'co_r'});
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	}
	print OUTPUT "\\\\\n";
	# Inventarnummer
	print OUTPUT $textobj->get(7) . "&";
	$havedata = 0;
	if(exists($r->{'co_in'})) {
	  if(defined($r->{'co_in'})) {
	    if($r->{'co_in'} =~ /\S/o) {
	      print OUTPUT lstr($r->{'co_in'});
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	}
	print OUTPUT "\\\\\n";
	# Seriennummer
	print OUTPUT $textobj->get(8) . "&";
	$havedata = 0;
	if(exists($r->{'co_sn'})) {
	  if(defined($r->{'co_sn'})) {
	    if($r->{'co_sn'} =~ /\S/o) {
	      print OUTPUT lstr($r->{'co_sn'});
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}";
	}
	print OUTPUT "\\\\\n";
	# Host-ID falls vorhanden
	if(exists($r->{'co_hi'})) {
	  if(defined($r->{'co_hi'})) {
	    if($r->{'co_hi'} =~ /\S/o) {
	      print OUTPUT $textobj->get(9) . "&" . lstr($r->{'co_hi'}) . "\\\\\n";
	    }
	  }
	}
	print OUTPUT "\\end{tabular}\n";
	# NETZWERK
	print OUTPUT "\\subsubsection{" . $textobj->get(10) . "}\n";
	print OUTPUT "\\begin{tabular}{lll}\n";
	# IP-Adresse
	print OUTPUT $textobj->get(11) . "&";
	$havedata = 0;
	if(exists($r->{'co_ip'})) {
	  if(defined($r->{'co_ip'})) {
	    if($r->{'co_ip'} =~ /\S/o) {
	      print OUTPUT "\\multicolumn{2}{l}{";
	      print OUTPUT $r->{'co_ip'};
	      print OUTPUT "}";
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\multicolumn{2}{l}{";
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	}
	print OUTPUT "\\\\\n";
	# DNS-Domain
	print OUTPUT $textobj->get(17) . "&";
	$havedata = 0;
	if(exists($r->{'co_dd'})) {
	  if(defined($r->{'co_dd'})) {
	    if($r->{'co_dd'} =~ /\S/o) {
	      print OUTPUT "\\multicolumn{2}{l}{";
	      print OUTPUT lstr($r->{'co_dd'});
	      print OUTPUT "}";
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\multicolumn{2}{l}{";
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	}
	print OUTPUT "\\\\\n";
	# MAC-Adresse
	print OUTPUT $textobj->get(12) . "&";
	$havedata = 0;
	if(exists($r->{'co_mc'})) {
	  if(defined($r->{'co_mc'})) {
	    if($r->{'co_mc'} =~ /\S/o) {
	      print OUTPUT "\\multicolumn{2}{l}{";
	      print OUTPUT $r->{'co_mc'};
	      print OUTPUT "}";
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\multicolumn{2}{l}{";
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	}
	print OUTPUT "\\\\\n";
	# Datendose
	print OUTPUT $textobj->get(13) . "&";
	$havedata = 0;
	if(exists($r->{'dd_n'})) {
	  if(defined($r->{'dd_n'})) {
	    if($r->{'dd_n'} =~ /\S/o) {
	      print OUTPUT "\\multicolumn{2}{l}{";
	      print OUTPUT lstr($r->{'dd_n'});
	      print OUTPUT "}";
	      $havedata = 1;
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\multicolumn{2}{l}{";
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	}
	print OUTPUT "\\\\\n";
	# DHCP-Klasse
	print OUTPUT $textobj->get(14) . "&";
	$havedata = 0;
	if(exists($r->{'dc_s'})) {
	  if(defined($r->{'dc_s'})) {
	    if($r->{'dc_s'} =~ /\S/o) {
	      print OUTPUT lstr($r->{'dc_s'});
	      $havedata = 1;
	      print OUTPUT "&";
	      $j = $r->{'dc_s'};
	      if(exists($dhcpclassesbyname{"$j"})) {
	        $j = $dhcpclassesbyname{"$j"};
		if(exists($j->{'dc_l'})) {
		  if(defined($j->{'dc_l'})) {
		    if($j->{'dc_l'} =~ /\S/o) {
		      print OUTPUT lstr($j->{'dc_l'});
		    }
		  }
		}
	      }
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\multicolumn{2}{l}{";
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	}
	print OUTPUT "\\\\\n";
	# DHCP-Gruppe
	print OUTPUT $textobj->get(15) . "&";
	$havedata = 0;
	if(exists($r->{'dg_s'})) {
	  if(defined($r->{'dg_s'})) {
	    if($r->{'dg_s'} =~ /\S/o) {
	      print OUTPUT lstr($r->{'dg_s'});
	      $havedata = 1;
	      print OUTPUT "&";
	      $j = $r->{'dg_s'};
	      if(exists($dhcpgroupsbyname{"$j"})) {
	        $j = $dhcpgroupsbyname{"$j"};
		if(exists($j->{'dg_l'})) {
		  if(defined($j->{'dg_l'})) {
		    if($j->{'dg_l'} =~ /\S/o) {
		      print OUTPUT lstr($j->{'dg_l'});
		    }
		  }
		}
	      }
	    }
	  }
	}
	if(!$havedata) {
	  print OUTPUT "\\multicolumn{2}{l}{";
	  print OUTPUT "\\textit{" . $textobj->get(4) . "}}";
	}
	print OUTPUT "\\\\\n";
	# Ablaufdatum
	if(exists($r->{'co_ex'})) {
	  if(defined($r->{'co_ex'})) {
	    if($r->{'co_ex'} =~ /\S/o) {
	      print OUTPUT $textobj->get(16) . "&" ;
	      print OUTPUT "\\multicolumn{2}{l}{" . lstr($r->{'co_ex'});
	      print OUTPUT "}\\\\\n";
	      $havedata = 1;
	    }
	  }
	}
	print OUTPUT "\\\\\n";
	print OUTPUT "\\end{tabular}\n";
	# NETZGRUPPEN
	$havedata = 0;
	for($i = 0; $i < $numnetgroups; $i++) {
	  if($bmd->get($i, $k)) {
	    $j = $netgroupsbynumber[$i];
	    if(exists($j->{'ng_s'})) {
	      if(defined($j->{'ng_s'})) {
	        if($j->{'ng_s'} =~ /\S/o) {
	          if(!$havedata) {
	            print OUTPUT "\\subsubsection{" . $textobj->get(18) . "}\n";
	            print OUTPUT "\\begin{tabular}{ll}\n";
	            $havedata = 1;
	          }
		  print OUTPUT "\\textbf{" . lstr($j->{'ng_s'}) . "}&";
		  if(exists($j->{'ng_l'})) {
		    if(defined($j->{'ng_l'})) {
		      if($j->{'ng_l'} =~ /\S/o) {
		        print OUTPUT lstr($j->{'ng_l'});
		      }
		    }
		  }
		  print OUTPUT "\\\\\n";
	        }
	      }
	    }
	  }
	}
	for($i = 0; $i < $numnetgroups; $i++) {
	  if(($bmi->get($i, $k)) && (!($bmd->get($i, $k)))) {
	    $j = $netgroupsbynumber[$i];
	    if(exists($j->{'ng_s'})) {
	      if(defined($j->{'ng_s'})) {
	        if($j->{'ng_s'} =~ /\S/o) {
	          if(!$havedata) {
	            print OUTPUT "\\subsubsection{" . $textobj->get(18) . "}\n";
	            print OUTPUT "\\begin{tabular}{ll}\n";
	            $havedata = 1;
	          }
		  print OUTPUT lstr($j->{'ng_s'}) . "&";
		  if(exists($j->{'ng_l'})) {
		    if(defined($j->{'ng_l'})) {
		      if($j->{'ng_l'} =~ /\S/o) {
		        print OUTPUT lstr($j->{'ng_l'});
		      }
		    }
		  }
		  print OUTPUT "\\\\\n";
	        }
	      }
	    }
	  }
	}
	if($havedata) {
	  print OUTPUT "\\end{tabular}\n";
	}
	print OUTPUT "\\clearpage\n";
      }
    }
    # Netgroups section
    print OUTPUT "\\section{" . $textobj->get(1) . "}\n";
    for($i = 0; $i < $numnetgroups; $i++) {
      $r = $netgroupsbynumber[$i];
      $k = $r->{'ng_s'};
      print OUTPUT "\\subsection{" . lstr($k) . "}";
      print OUTPUT "\\label{sec:n-" . $i . "}\n";
      if(exists($r->{'ng_l'})) {
        $u = $r->{'ng_l'};
	if(defined($u)) {
	  if($u =~ /\S/o) {
	    print OUTPUT lstr($u) . "\n";
	  }
	}
      }
      $havedata = 0;
      for($j = 0; $j < $numnetgroups; $j++) {
        if($j != $i) {
	  if($bmn->get($j, $i)) {
	    if(!$havedata) {
	      print OUTPUT "\\subsubsection{" . $textobj->get(19) . "}\n";
	      print OUTPUT "\\begin{tabular}{ll}\n";
	      $havedata = 1;
	    }
	    $u = $netgroupsbynumber[$j];
	    print OUTPUT "\\textbf{" . lstr($u->{'ng_s'}) . "}&";
	    if(exists($u->{'ng_l'})) {
	      $u = $u->{'ng_l'};
	      if(defined($u)) {
	        if($u =~ /\S/o) {
		  print OUTPUT lstr($u);
		}
	      }
	    }
	    print OUTPUT "\\\\\n";
	  }
	}
      }
      if($havedata) {
        for($j = 0; $j < $numnetgroups; $j++) {
          if($j != $i) {
	    if((!($bmn->get($j, $i))) && ($bmni->get($j, $i))) {
	      $u = $netgroupsbynumber[$j];
	      print OUTPUT "\\textbf{" . lstr($u->{'ng_s'}) . "}&";
	      if(exists($u->{'ng_l'})) {
	        $u = $u->{'ng_l'};
	        if(defined($u)) {
	          if($u =~ /\S/o) {
		    print OUTPUT lstr($u);
		  }
	        }
	      }
	      print OUTPUT "\\\\\n";
	    }
	  }
        }
        print OUTPUT "\\end{tabular}\n";
      }
      $havedata = 0;
      for($j = 0; $j < $numnetgroups; $j++) {
        if($j != $i) {
	  if($bmn->get($i, $j)) {
	    if(!$havedata) {
	      print OUTPUT "\\subsubsection{" . $textobj->get(20) . "}\n";
	      print OUTPUT "\\begin{tabular}{ll}\n";
	      $havedata = 1;
	    }
	    $u = $netgroupsbynumber[$j];
	    print OUTPUT "\\textbf{" . lstr($u->{'ng_s'}) . "}&";
	    if(exists($u->{'ng_l'})) {
	      $u = $u->{'ng_l'};
	      if(defined($u)) {
	        if($u =~ /\S/o) {
		  print OUTPUT lstr($u);
		}
	      }
	    }
	    print OUTPUT "\\\\\n";
	  }
	}
      }
      if($havedata) {
        for($j = 0; $j < $numnetgroups; $j++) {
          if($j != $i) {
	    if((!($bmn->get($i, $j))) && ($bmni->get($i, $j))) {
	      $u = $netgroupsbynumber[$j];
	      print OUTPUT "\\textbf{" . lstr($u->{'ng_s'}) . "}&";
	      if(exists($u->{'ng_l'})) {
	        $u = $u->{'ng_l'};
	        if(defined($u)) {
	          if($u =~ /\S/o) {
		    print OUTPUT lstr($u);
		  }
	        }
	      }
	      print OUTPUT "\\\\\n";
	    }
	  }
        }
        print OUTPUT "\\end{tabular}\n";
      }
      $havedata = 0;
      for($j = 0; $j < $numcomputers; $j++) {
        $r = $computersbynumber[$j];
	$k = $r->{'co_s'};
	if($bmd->get($i, $j)) {
	  if(!$havedata) {
	    print OUTPUT "\\subsubsection{" . $textobj->get(21) . "}\n";
	    print OUTPUT "\\begin{longtable}{ll}\n";
	    print OUTPUT "\\endfirsthead\n";
	    print OUTPUT "\\endhead\n";
	    print OUTPUT "\\endfoot\n";
	    print OUTPUT "\\endlastfoot\n";
	    $havedata = 1;
	  }
	  print OUTPUT "\\textbf{" . lstr($k) . "}&";
	  if(exists($r->{'co_co'})) {
	    $k = $r->{'co_co'};
	    if(defined($k)) {
	      if($k =~ /\S/o) {
	        print OUTPUT lstr($k);
	      }
	    }
	  }
	  print OUTPUT "\\\\\n";
	}
      }
      for($j = 0; $j < $numcomputers; $j++) {
        $r = $computersbynumber[$j];
	$k = $r->{'co_s'};
	if(($bmi->get($i, $j)) && (!($bmd->get($i, $j)))) {
	  if(!$havedata) {
	    print OUTPUT "\\subsubsection{" . $textobj->get(21) . "}\n";
	    print OUTPUT "\\begin{longtable}{ll}\n";
	    print OUTPUT "\\endfirsthead\n";
	    print OUTPUT "\\endhead\n";
	    print OUTPUT "\\endfoot\n";
	    print OUTPUT "\\endlastfoot\n";
	    $havedata = 1;
	  }
	  print OUTPUT lstr($k) . "&";
	  if(exists($r->{'co_co'})) {
	    $k = $r->{'co_co'};
	    if(defined($k)) {
	      if($k =~ /\S/o) {
	        print OUTPUT lstr($k);
	      }
	    }
	  }
	  print OUTPUT "\\\\\n";
	}
      }
      if($havedata) {
        print OUTPUT "\\end{longtable}\n";
      }




      print OUTPUT "\\clearpage\n";
    }
    # postamble
    $preamble = $textobj->get_latex_postamble();
    foreach $k (@$preamble) {
      print OUTPUT "$k\n";
    }
    close(OUTPUT);
  }
  debugmsg(4, "Write network documentation (finished)");
}

sub write_hosts_ldif()
{
  my $i; my $k; my $ip; my $b;
  my $fn = $confobj->{'outdir'} . "/hosts.ldif";
  my $fnf = 0; my $ddn = undef; my $aliasno;
  if(open(OUTPUT, ">$fn")) {
    $b = $confobj->{'ldapbase'};
    for($i = 0; $i < $numcomputers; $i++) {
      $r = $computersbynumber[$i];
      $k = $r->{'co_s'};
      $ip = undef;
      $fnf = 0;
      $ddn = undef;
      if(exists($r->{'co_ip'})) {
        $ip = $r->{'co_ip'};
	if(defined($ip)) {
	  if($ip =~ /^\s*(\d+\.\d+\.\d+\.\d+)/o) {
	    $ip = $1;
	    print OUTPUT "dn: cn=$k+ipHostNumber=$ip,ou=hosts,$b\n";
	    print OUTPUT "objectClass: top\n";
	    print OUTPUT "objectClass: device\n";
	    print OUTPUT "objectClass: ipHost\n";
	    print OUTPUT "cn: $k\n";
	    if(exists($r->{'co_dd'})) {
	      $ddn = $r->{'co_dd'};
	      if(defined($ddn)) {
	        if(exists($r->{'co_ff'})) {
		  $fnf = $r->{'co_ff'};
		  if(defined($fnf)) {
		    $fnf = 0 + $fnf;
		    if($fnf > 0) {
		      print OUTPUT "cn: $k." . $ddn . "\n";
		    }
		  }
		}
	      }
	    }
	    if(exists($r->{'aliases_found'})) {
	      $fnf = $r->{'aliases_found'};
	      if(defined($fnf)) {
	        if($fnf > 0) {
		  if(exists($r->{'aliases_list'})) {
		    $ddn = $r->{'aliases_list'};
		    if(defined($ddn)) {
		      for($aliasno = 0; $aliasno  < $fnf; $aliasno++) {
		        print OUTPUT "cn: " . $ddn->[$aliasno] . "\n";
		      }
		    }
		  }
		}
	      }
	    }
	    print OUTPUT "ipHostNumber: $ip\n";
	    if(exists($r->{'co_co'})) {
	      $ip = $r->{'co_co'};
	      if(defined($ip)) {
	        if($ip =~ /\S/o) {
		  print OUTPUT "description: $ip\n";
		}
	      }
	    }
	    print OUTPUT "\n";
	  }
	}
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write hosts.ldif!");
  }
}

sub write_ethers_ldif()
{
  my $i; my $r; my $k; my $ip; my $mac;
  my $b = $confobj->{'ldapbase'};
  my $fn = $confobj->{'outdir'} . "/ethers.ldif";
  if(open(OUTPUT, ">$fn")) {
    for($i = 0; $i < $numcomputers; $i++) {
      $r = $computersbynumber[$i];
      $k = $r->{'co_s'};
      if(exists($r->{'co_ip'})) {
        $ip = $r->{'co_ip'};
	if(defined($ip)) {
	  if($ip =~ /^\s*(\d+\.\d+\.\d+\.\d+)\s*$/o) {
	    $ip = $1;
	    if(exists($r->{'co_mc'})) {
	      $mac = $r->{'co_mc'};
	      if(defined($mac)) {
	        if($mac =~ /^\s*([01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f]:[01-9A-Fa-f][01-9A-Fa-f])\s*$/o) {
	          $mac = $1;
		  print OUTPUT "dn: cn=$k,ou=ethers,$b\n";
		  print OUTPUT "objectClass: top\n";
		  print OUTPUT "objectClass: device\n";
		  print OUTPUT "objectClass: ieee802Device\n";
		  print OUTPUT "cn: $k\n";
		  print OUTPUT "macAddress: $mac\n\n";
	        }
	      }
	    }
	  }
	}
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write ethers.ldif!");
  }
}

sub write_networks_ldif()
{
  my $k; my $r; my $ip; my $ma; my $x;
  my $b = $confobj->{'ldapbase'};
  my $fn = $confobj->{'outdir'} . "/networks.ldif";
  if(open(OUTPUT, ">$fn")) {
    foreach $k (keys %networksbyname) {
      $r = $networksbyname{"$k"};
      if(exists($r->{'nw_ma'})) {
        $ma = $r->{'nw_ma'};
	if(defined($ma)) {
	  if($ma =~ /^\s*(\d+\.\d+\.\d+\.\d+)\s*$/o) {
	    $ma = $1;
	    $x = $k;
	    $x =~ s/\./\-/g;
	    $x = "mynet-$x";
	    print OUTPUT "dn: ipNetworkNumber=$k,ou=networks,$b\n";
	    print OUTPUT "cn: $x\n";
	    print OUTPUT "objectClass: top\n";
	    print OUTPUT "objectClass: ipNetwork\n";
	    print OUTPUT "ipnetworknumber: $k\n";
	    print OUTPUT "ipnetmasknumber: $ma\n\n";
	  }
	}
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write networks.ldif!");
  }
}

sub write_dhcpd_conf()
{
  my $dhcpok; my $dhcpov;
  my $dhcpcln; my $dhcpclv;
  my $hk; my $hr; my $hi;
  my $ip; my $mac; my $v;
  my $vlk; my $vlr;
  my $snk; my $snv;
  my $dgk; my $dgv;
  my $dpk; my $dpv; my $havepool;
  my $isfirst;
  my $dc;
  my $must_print_this_host;
  my $fn = $confobj->{'outdir'} . "/dhcpd.conf";
  if(open(OUTPUT, ">$fn")) {
    # write options
    foreach $dhcpok (keys %dhcpoptionsbypk) {
      $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
      if($dhcpov->{'do_sc'} eq 'server') {
        $v = $dhcpov->{'do_n'};
        if("$v" =~ /option\:(.*)/o) {
	  print OUTPUT "option\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
	} else {
	  if($dhcpov->{'do_n'} eq 'authorative') {
	    print OUTPUT "authorative;\n";
	  } else {
	    print OUTPUT "" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
	  }
	}
      }
    }
    print OUTPUT "\n";
    # write DHCP classes
    foreach $dhcpcln (sort (keys %dhcpclassesbyname)) {
      $dhcpclv = $dhcpclassesbyname{"$dhcpcln"};
      if($dhcpclv->{'used'}) {
        if($confobj->{'codhcpd'}) {
	  if(exists($dhcpclv->{'dc_d'})) {
	    if(defined($dhcpclv->{'dc_d'})) {
	      if($dhcpclv->{'dc_d'} =~ /\S/o) {
	        print OUTPUT "# " . $dhcpclv->{'dc_d'} . "\n";
	      }
	    }
	  }
	}
        print OUTPUT "class \"$dhcpcln\" { match hardware; }\n";
	if($confobj->{'codhcpd'}) {
	  print OUTPUT "\n";
	}
	for($hi = 0; $hi < $numcomputers; $hi++) {
	  $hr = $computersbynumber[$hi];
	  if($hr->{'ex'} == 0) {
	    $hk = $hr->{'co_s'};
	    $ip = undef; $mac = undef;
	    if(exists($hr->{'dc_s'})) {
	      $v = $hr->{'dc_s'};
	      if(defined($v)) {
	        if("$v" eq "$dhcpcln") {
	          if(exists($hr->{'co_ip'})) {
		    $v = $hr->{'co_ip'};
		    if(defined($v)) {
		      if("$v" =~ /\d+\.\d+\.\d+\.\d+/o) {
		        $ip = $v;
		      }
		    }
		  }
		  if(exists($hr->{'co_mc'})) {
		    $v = $hr->{'co_mc'};
		    if(defined($v)) {
		      if("$v" =~ /[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]\:[01-9A-Fa-f][01-9A-Fa-f]/o) {
		        $mac = $v;
		      }
		    }
		  }
		  if(defined($mac) && (!defined($ip))) {
		    print OUTPUT "# " . $hr->{'co_s'} . "\n";
		    print OUTPUT "subclass \"$dhcpcln\" 1:$mac;";
		    if($confobj->{'codhcpd'}) {
		      print OUTPUT "\n";
		    }
		    print OUTPUT "\n";
		  }
	        }
	      }
	    }
	  }
	}
	print OUTPUT "\n";
      }
    }
    # write vlans
    foreach $vlk (sort (keys %vlansbyname)) {
      $vlr = $vlansbyname{"$vlk"};
      if($vlr->{'used'}) {
        $vln = $vlr->{'vl_s'};
	if($confobj->{'codhcpd'}) {
	  if(exists($vlr->{'vl_l'})) {
	    if(defined($vlr->{'vl_l'})) {
	      if($vlr->{'vl_l'} =~ /\S/o) {
	        print OUTPUT "# " . $vlr->{'vl_l'} . "\n";
	      }
	    }
	  }
	}
        print OUTPUT "shared-network vlan-$vln\n{\n";
        print OUTPUT "\t# VLAN $vln options\n";
        foreach $dhcpok (keys %dhcpoptionsbypk) {
          $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
          if($dhcpov->{'do_sc'} eq 'vlan') {
            if(exists($dhcpov->{'do_sn'})) {
  	    $v = $dhcpov->{'do_sn'};
  	    if(defined($v)) {
  	      if("$v" eq "$vln") {
                  $v = $dhcpov->{'do_n'};
                  if("$v" =~ /option\:(.*)/o) {
  	          print OUTPUT "\toption\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
  	        } else {
  	          print OUTPUT "\t" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
  	        }
  	      }
  	    }
  	  }
          }
        }
        print OUTPUT "\n";
        # write subnets
        foreach $snk (sort (keys %networksbyname)) {
        $snv = $networksbyname{"$snk"};
  	if(exists($snv->{'vl_s'})) {
  	  if(defined($snv->{'vl_s'})) {
  	    if($snv->{'vl_s'} eq "$vlk") {
              if($snv->{'used'}) {
    	      if(exists($snv->{'nw_ma'})) {
    	        if(1) {		# check result
    	        if(defined($snv->{'nw_ma'})) {
    		if(exists($snv->{'nw_gw'})) {
    		if(defined($snv->{'nw_gw'})) {
    		if(exists($snv->{'nw_bc'})) {
    		if(defined($snv->{'nw_bc'})) {
    		  print OUTPUT "\tsubnet $snk netmask " . $snv->{'nw_ma'} . "\n\t{\n";
    		  # write subnet options
    		  print OUTPUT "\t\toption routers\t\t\t" . $snv->{'nw_gw'} . ";\n";
    		  print OUTPUT "\t\toption subnet-mask\t\t" . $snv->{'nw_ma'} . ";\n";
    		  print OUTPUT "\t\toption broadcast-address\t" . $snv->{'nw_bc'} . ";\n";
                  foreach $dhcpok (keys %dhcpoptionsbypk) {
                    $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
                    if($dhcpov->{'do_sc'} eq 'network') {
                    if(exists($dhcpov->{'do_sn'})) {
    	              $v = $dhcpov->{'do_sn'};
    	              if(defined($v)) {
    	                if("$v" eq "$snk") {
                          $v = $dhcpov->{'do_n'};
                          if("$v" =~ /option\:(.*)/o) {
    	                    print OUTPUT "\t\toption\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                  } else {
    	                    print OUTPUT "\t\t" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                  }
    	                }
    	              }
    	            }
                    }
                  }
    		  print OUTPUT "\n";
    		  $havepool = 0;
    		  foreach $dpk (sort (keys %dhcppoolsbypk)) {
    		    $dpv = $dhcppoolsbypk{"$dpk"};
    		    if(exists($dpv->{'nw_ip'})) {
    		    if(defined($dpv->{'nw_ip'})) {
    		    if($dpv->{'nw_ip'} eq "$snk") {
    		    if(exists($dpv->{'dp_st'})) {
    		    if(defined($dpv->{'dp_st'})) {
    		    if(exists($dpv->{'dp_en'})) {
    		    if(defined($dpv->{'dp_en'})) {
    		      $havepool = 1;
    		      print OUTPUT "\t\tpool\n\t\t{\n";
    		      print OUTPUT "\t\t\trange " . $dpv->{'dp_st'} . " " . $dpv->{'dp_en'} . ";\n";
    		      if($dpv->{'dp_al'}) {
    		        print OUTPUT "\t\t\tallow unknown clients;\n";
    			foreach $dhcpcln (keys %dhcpclassesbyname) {
    			  print OUTPUT "\t\t\tdeny members of \"$dhcpcln\";\n";
    			}
    		      } else {
    		        if($dpv->{'dp_dn'}) {
    			  if(exists($dpv->{'dc_s'})) {
    			    if(defined($dpv->{'dc_s'})) {
    			      print OUTPUT "\t\t\tdeny unknown clients;\n";
    			      print OUTPUT "\t\t\tallow members of \"" . $dpv->{'dc_s'} . "\";\n";
    			    }
    			  }
    			}
    		      }
                      foreach $dhcpok (keys %dhcpoptionsbypk) {
                        $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
                        if($dhcpov->{'do_sc'} eq 'pool') {
                          if(exists($dhcpov->{'do_sn'})) {
    	                    $v = $dhcpov->{'do_sn'};
    	                    if(defined($v)) {
    	                      if("$v" eq "$dpk") {
                                    $v = $dhcpov->{'do_n'};
                                    if("$v" =~ /option\:(.*)/o) {
    	                          print OUTPUT "\t\t\toption\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                        } else {
    	                          print OUTPUT "\t\t\t" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                        }
    	                      }
    	                    }
    	                  }
                        }
                      }
    		      print OUTPUT "\t\t}\n";
    		    }
    		    }
    		    }
    		    }
    		    }
    		    }
    		    }
    		  }
		  # print hosts in groups
    		  foreach $dgk (sort (keys %dhcpgroupsbyname)) {
    		    $dgv = $dhcpgroupsbyname{"$dgk"};
    		    $isfirst = 1;
    		    for($hi = 0; $hi < $numcomputers; $hi++) {
    		      $hr = $computersbynumber[$hi];
    		      $hk = $hr->{'co_s'};
    		      if($hr->{'done'} == 0) {
		        $must_print_this_host = 0;
		        $ip = undef;
			if(exists($hr->{'co_ip'})) {
			  $ip = $hr->{'co_ip'};
			  if(defined($ip)) {
			    if($hr->{'nip'} > 0) {
			      if((($hr->{'nip'}) & ($snv->{'nma'})) == (($snv->{'nip'}) & ($snv->{'nma'}))) {
			        $must_print_this_host = 1;
			      }
			    }
			  }
			}
			if(!defined($ip)) {
			  if(exists($hr->{'dc_s'})) {
			    $dc = $hr->{'dc_s'};
			    if(defined($dc)) {
			      if(exists($dhcpclassesbyname{"$dc"})) {
			        $dc = $dhcpclassesbyname{"$dc"};
				if(exists($dc->{'nw_ip'})) {
				  if(defined($dc->{'nw_ip'})) {
				    $dc = $dc->{'nw_ip'};
				    if("$dc" eq "$snk") {
				      $must_print_this_host = 1;
				    }
				  }
				}
			      }
			    }
			  }
			}
			if($hr->{'ex'} != 0) { $must_print_this_host = 0; }
			if($must_print_this_host) {
			  if(exists($hr->{'co_mc'})) {
			  if(defined($hr->{'co_mc'})) {
			    if(exists($hr->{'dg_s'})) {
			    if(defined($hr->{'dg_s'})) {
			      if($hr->{'dg_s'} eq "$dgk") {
    			        if($isfirst) {
    				  print OUTPUT "\t\tgroup\n\t\t{";
				  if($confobj->{'codhcpd'}) {
				    if(exists($dgv->{'dg_l'})) {
				      if(defined($dgv->{'dg_l'})) {
				        if($dgv->{'dg_l'} =~ /\S/o) {
					  print OUTPUT " # " . $dgv->{'dg_l'};
					}
				      }
				    }
				  }
				  print OUTPUT "\n";
                                  foreach $dhcpok (keys %dhcpoptionsbypk) {
                                    $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
                                    if($dhcpov->{'do_sc'} eq 'group') {
                                      if(exists($dhcpov->{'do_sn'})) {
    	                                $v = $dhcpov->{'do_sn'};
    	                                if(defined($v)) {
    	                                  if("$v" eq "$dgk") {
                                            $v = $dhcpov->{'do_n'};
                                            if("$v" =~ /option\:(.*)/o) {
    	                                      print OUTPUT "\t\t\toption\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                                    } else {
    	                                      print OUTPUT "\t\t\t" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                                    }
    	                                  }
    	                                }
    	                              }
                                    }
                                  }
    				} $isfirst = 0;
				$hr->{'done'} = 1;
    				print OUTPUT "\t\t\thost $hk\n\t\t\t{";
				if($confobj->{'codhcpd'}) {
				  if(exists($hr->{'co_co'})) {
				    if(defined($hr->{'co_co'})) {
				      print OUTPUT " # " . $hr->{'co_co'};
				    }
				  }
				}
				print OUTPUT "\n";
				if(exists($hr->{'co_ip'})) {
				if(defined($hr->{'co_ip'})) {
    				  print OUTPUT "\t\t\t\tfixed-address " . $hr->{'co_ip'} . ";\n";
				}
				}
    				print OUTPUT "\t\t\t\thardware ethernet " . $hr->{'co_mc'} . ";\n";
    				print OUTPUT "\t\t\t\toption host-name \"$hk\";\n";
                                foreach $dhcpok (keys %dhcpoptionsbypk) {
                                  $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
                                  if($dhcpov->{'do_sc'} eq 'host') {
                                    if(exists($dhcpov->{'do_sn'})) {
    	                              $v = $dhcpov->{'do_sn'};
    	                              if(defined($v)) {
    	                                if("$v" eq "$hk") {
                                          $v = $dhcpov->{'do_n'};
                                          if("$v" =~ /option\:(.*)/o) {
    	                                    print OUTPUT "\t\t\toption\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                                  } else {
    	                                    print OUTPUT "\t\t\t" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                                  }
    	                                }
    	                              }
    	                            }
                                  }
                                }
    				print OUTPUT "\t\t\t}\n";
			      }
			    }
			    }
			  }
			  }
			}
    		      }
    		    }
    		    if(!$isfirst) {
    		      print OUTPUT "\t\t}\n";
    		    }
    		  }
		  # print hosts not belonging to a group
    		  $isfirst = 1;
    		  for($hi = 0; $hi < $numcomputers; $hi++) {
    		    $hr = $computersbynumber[$hi];
    		    $hk = $hr->{'co_s'};
		    if($hr->{'done'} == 0) {
		      $must_print_this_host = 0; $ip = undef;
		      if(exists($hr->{'co_ip'})) { $ip = $hr->{'co_ip'};
		      if(defined($ip)) {
		        if($hr->{'nip'} > 0) {
			  if((($hr->{'nip'}) & ($snv->{'nma'})) == (($snv->{'nip'}) & ($snv->{'nma'}))) {
			    $must_print_this_host = 1;
			  }
			}
		      }
		      }
		      if(!defined($ip)) {
		        if(exists($hr->{'dc_s'})) { $dc = $hr->{'dc_s'};
			if(defined($dc)) {
			  if(exists($dhcpclassesbyname{"$dc"})) {
			    $dc = $dhcpclassesbyname{"$dc"};
			    if(exists($dc->{'nw_ip'})) { $dc = $dc->{'nw_ip'};
			    if(defined($dc)) {
			      if("$dc" eq "$snk") {
			        $must_print_this_host = 1;
			      }
			    }
			    }
			  }
			}
			}
		      }
		      if($hr->{'ex'} != 0) { $must_print_this_host = 0; }
		      if($must_print_this_host) {
		        if(exists($hr->{'co_mc'})) {
		          if(defined($hr->{'co_mc'})) {
    			        if($isfirst) {
    				  print OUTPUT "\t\tgroup\n\t\t{\n";
    				} $isfirst = 0;
				$hr->{'done'} = 1;
    				print OUTPUT "\t\t\thost $hk\n\t\t\t{";
				if($confobj->{'codhcpd'}) {
				  if(exists($hr->{'co_co'})) {
				    if(defined($hr->{'co_co'})) {
				      print OUTPUT " # " . $hr->{'co_co'};
				    }
				  }
				}
				print OUTPUT "\n";
				if(defined($ip)) {
    				  print OUTPUT "\t\t\t\tfixed-address " . $hr->{'co_ip'} . ";\n";
				}
    				print OUTPUT "\t\t\t\thardware ethernet " . $hr->{'co_mc'} . ";\n";
    				print OUTPUT "\t\t\t\toption host-name \"$hk\";\n";
                                foreach $dhcpok (keys %dhcpoptionsbypk) {
                                  $dhcpov = $dhcpoptionsbypk{"$dhcpok"};
                                  if($dhcpov->{'do_sc'} eq 'host') {
                                    if(exists($dhcpov->{'do_sn'})) {
    	                              $v = $dhcpov->{'do_sn'};
    	                              if(defined($v)) {
    	                                if("$v" eq "$hk") {
                                          $v = $dhcpov->{'do_n'};
                                          if("$v" =~ /option\:(.*)/o) {
    	                                    print OUTPUT "\t\t\toption\t" . $1 . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                                  } else {
    	                                    print OUTPUT "\t\t\t" . $dhcpov->{'do_n'} . "\t" . $dhcpov->{'do_v'} . ";\n";
    	                                  }
    	                                }
    	                              }
    	                            }
                                  }
                                }
    				print OUTPUT "\t\t\t}\n";
		          }
		        }
		      }
		    }
		  }
    		  if(!$isfirst) {
    		    print OUTPUT "\t\t}\n";
    		  }
    		  print OUTPUT "\t}\n\n";
    		}
    		}
    		}
    		}
    		}
    		}
    	      }
	      }
  	    }
  	  }
  	}
        }
        print OUTPUT "}\n\n";
      }
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write dhcpd.conf!");
    $exval = 1;
  }
}

sub write_hosts_files()
{
  debugmsg(4, "Writing hosts files (start)");
  write_hosts();
  write_ethers();
  write_dhcpd_conf();
  {
    my $bmhngdirect = undef;
    my $bmhngindirect = undef;
    my $bmng = undef;
    my $bmngi = undef;
    $bmhngdirect = DKrause::BitMatrix::new($numnetgroups, $numcomputers);
    $bmhngindirect = DKrause::BitMatrix::new($numnetgroups, $numcomputers);
    $bmng = DKrause::BitMatrix::new($numnetgroups, $numnetgroups);
    $bmngi = DKrause::BitMatrix::new($numnetgroups, $numnetgroups);
    if(($bmhngdirect) && ($bmhngindirect) && ($bmng) && ($bmngi)) {
      fill_matrices($bmhngdirect, $bmhngindirect, $bmng, $bmngi);
      expand_matrices($bmhngdirect, $bmhngindirect, $bmng, $bmngi);
      write_hosts_ldif();
      write_ethers_ldif();
      write_networks_ldif();
      write_netgroups_ldif($bmhngdirect, $bmhngindirect, $bmng, $bmngi);
      write_netdocu($bmhngdirect, $bmhngindirect, $bmng, $bmngi);
    } else {
      debugmsg(1, "Not enough memory for bit matrices!");
      $exval = 1;
    }
  }
  debugmsg(4, "Writing hosts files (finished)");
}

sub get_license_component($$)
{
  my $lir = shift;
  my $num = shift;
  my $back = undef;
  my $l;
  if(defined($lir)) {
    if($num == 4) {
      if(exists($lir->{'li_no'})) {
        $back = $lir->{'li_no'};
      }
    } else {
    if($num == 3) {
      if(exists($lir->{'li_ni'})) {
        $back = $lir->{'li_ni'};
      }
    } else {
    if($num == 2) {
      if(exists($lir->{'li_di'})) {
        $back = $lir->{'li_di'};
      }
    } else {
    if($num == 1) {
      if(exists($lir->{'li_nd'})) {
        $back = $lir->{'li_nd'};
      }
    } else {
    if($num == 0) {
      if(exists($lir->{'li_dd'})) {
        $back = $lir->{'li_dd'};
      }
    } else {
    if($num == 5) {
      if(exists($lir->{'lt_s'})) {
        $l = $lir->{'lt_s'};
	if(defined($l)) {
	  if(exists($licensetypesbyname{"$l"})) {
	    $l = $licensetypesbyname{"$l"};
	    if(exists($l->{'lt_l'})) {
	      $back = $l->{'lt_l'};
	    }
	  }
	}
      }
    } else {
    if($num == 6) {	# order number
      if(exists($lir->{'li_on'})) {
        $back = $lir->{'li_on'};
      }
    } else {
    }
    }
    }
    }
    }
    }
    }
  }
  if(defined($back)) {
    chomp $back;
    if("$back" eq "") {
      $back = undef;
    }
  }
  return $back;
}

sub write_license_report()
{
  my $preamble; my $k;
  my $lipk;		# license primary key
  my $lir;		# license reference
  my $swn;		# software product number
  my $swr;		# software product reference
  my $smn;		# software manufacturer name
  my $smr;		# software manufacturer reference
  my $sectionprinted;	# section was printed
  my $ssprinted;	# subsection was printed
  my $sssprinted;	# subsubsection was printed
  my $mpsection;	# must print section
  my $mpss;		# must print subsection
  my $mpsss;		# must print subsubsection
  my $tableopen;	# a longtable is open
  my $manulong;		# manufacturer long name
  my $proglong;		# program long name
  my $deld;		# delivery date
  my $deln;		# delivery number
  my $invd;		# invoice date
  my $invn;		# invoice number
  my $lino;		# license notes
  my $lity;		# license type
  my $linu;		# number of clients (places)
  my $userno;		# number of current user
  my $userr;		# current user reference
  my $conu;		# current computer number
  my $comr;		# current computer reference
  my $fullusername;	# full user name
  my $shortusername;	# short user name
  my $orderno;		# order number
  debugmsg(4, "Writing license report (start)");
  my $fn = $confobj->{'outdir'} . "/licenses.tex";
  if(open(OUTPUT, ">$fn")) {
    # preamble
    $preamble = $textobj->get_latex_preamble_2();
    foreach $k (@$preamble) {
      print OUTPUT "$k\n";
    }
    # PART I:   By user, PC, manufacturer and software
    print OUTPUT "\\part{" . $textobj->get(23) . "}\\clearpage\n";
    # print OUTPUT $textobj->get(27);
    # Bestand
    # section: Bestand
    # subsection: Hersteller
    # subsubsection: Produkt
    $sectionprinted = 0; $ssprinted = undef; $sssprinted = undef;
    $tableopen = 0;
    foreach $lir (@licensesbynumber) {
      if($lir->{'hl'} == 0) {
        $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
	$manulong = '?'; $proglong = '?';
	$mpsection = 1; $mpss = 1; $mpsss = 1;
	$deld = undef; $deln = undef; $invd = undef;
	$invn = undef; $lino = undef; $lity = undef;
	$linu = 1;
	if(exists($lir->{'sw_s'})) {
	  $swn = $lir->{'sw_s'};
	  if(defined($swn)) {
	    if(exists($swproductsbyname{"$swn"})) {
	      $swr = $swproductsbyname{"$swn"};
	      $proglong = $swr->{'sw_l'};
	      if(defined($proglong)) {
		chomp $proglong;
		if("$proglong" eq "") {
		  $proglong = '?';
		}
	      } else { $proglong = '?'; }
	      if(exists($swr->{'sm_s'})) {
	        $smn = $swr->{'sm_s'};
		if(defined($smn)) {
		  if(exists($swmanufacturersbyname{"$smn"})) {
		    $smr = $swmanufacturersbyname{"$smn"};
		    if(exists($smr->{'sm_l'})) {
		      $manulong = $smr->{'sm_l'};
		      if(defined($manulong)) {
		        chomp $manulong;
			if("$manulong" eq "") {
			  $manulong = '?';
			}
		      } else { $manulong = '?'; }
		    }
		  } else {
		    $smn = '?';
		  }
		} else { $smn = '?'; }
	      }
	    } else { $swn = '?'; }
	  } else { $swn = '?'; }
	}
        if($sectionprinted) {
	  $mpsection = 0;
	}
	if($mpsection) {
	  $sectionprinted = 1; $ssprinted = undef; $sssprinted = undef;
	  if($tableopen) {
	    print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	  }
	  print OUTPUT "\\section[";
	  print OUTPUT $textobj->get(26);
	  print OUTPUT "]{";
	  print OUTPUT $textobj->get(25);
	  print OUTPUT "}\n";
	  print OUTPUT $textobj->get(27);
	}
	if(defined($ssprinted)) {
	  if("$ssprinted" eq "$manulong") {
	    $mpss = 0;
	  }
	}
	if($mpss) {
	  $sssprinted = undef;
	  if($tableopen) {
	    print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	  }
	  $ssprinted = $manulong;
	  if(!$mpsection) {
	    print OUTPUT "\\clearpage\n";
	  }
	  print OUTPUT "\\subsection{";
	  print OUTPUT lstr($manulong);
	  print OUTPUT "}\n";
	}
	if(defined($sssprinted)) {
	  if("$sssprinted" eq "$proglong") {
	    $mpsss = 0;
	  }
	}
	if($mpsss) {
	  if($tableopen) {
	    print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	  }
	  $sssprinted = $proglong;
	  print OUTPUT "\\subsubsection{";
	  print OUTPUT lstr($proglong);
	  print OUTPUT "}\n";
	  print OUTPUT "$swn\\\\\n";
	}
	# print table entry for license
	if(!$tableopen) {
	  foreach $k (@startoftable) {
	    print OUTPUT "$k\n";
	  }
	  $tableopen = 1;
	}
	$deld = get_license_component($lir, 0);
	$deln = get_license_component($lir, 1);
	$invd = get_license_component($lir, 2);
	$invn = get_license_component($lir, 3);
	$lino = get_license_component($lir, 4);
	$lity = get_license_component($lir, 5);
	$orderno = get_license_component($lir, 6);
	print OUTPUT $lir->{'li_pk'} . "&";
        print OUTPUT "\\multicolumn{4}{l}{";
	if(defined($orderno)) {
	  print OUTPUT lstr($orderno);
	}
	print OUTPUT "}\\\\*\n";
	print OUTPUT "&\\multicolumn{4}{l}{";
	if(defined($lity)) {
	  print OUTPUT lstr($lity);
	}
	print OUTPUT "}";
	if(defined($deld) || defined($deln) || defined($invd) 
	   || defined($invn) || defined($lino))
	{
	  print OUTPUT "\\\\*\n";
	  if(defined($deld) || defined($deln) || defined($invd)
	     || defined($invn))
	  {
	    print OUTPUT "&";
	    if(defined($deld)) {
	      print OUTPUT lstr($deld);
	    }
	    print OUTPUT "&";
	    if(defined($deln)) {
	      print OUTPUT lstr($deln);
	    }
	    print OUTPUT "&";
	    if(defined($invd)) {
	      print OUTPUT lstr($invd);
	    }
	    print OUTPUT "&";
	    if(defined($invn)) {
	      print OUTPUT lstr($invn);
	    }
	    if(defined($lino)) {
	      print OUTPUT "\\\\*\n";
	    } else {
	      print OUTPUT "\\\\[0.5em]\n";
	    }
	  }
	  if(defined($lino)) {
	    print OUTPUT "&\\multicolumn{4}{l}{";
	    print OUTPUT lstr($lino);
	    print OUTPUT "}\\\\[0.5em]\n";
	  }
	} else {
	  print OUTPUT "\\\\[0.5em]\n";
	}
      }
    }
    if($tableopen) {
      print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
    }

    # Einzelne Mitarbeiter, geordnet nach PCs
    # section: user name
    # subsection: computer name
    # subsubsection: Software manufacturer
    $sectionprinted = "-"; $ssprinted = undef; $sssprinted = undef;
    $tableopen = 0;
    foreach $userr (@usersbynumber) {
      $fullusername = get_full_user_name($userr);
      debugmsg(4, "Writing license information for $fullusername");
      $shortusername = undef;
      $sectionprinted = 0;
      if(exists($userr->{'us_fn'})) {
        $shortusername = $userr->{'us_fn'};
      }
      if(exists($userr->{'us_s'})) {
      if(defined($userr->{'us_s'})) {
      if($userr->{'us_s'} ne '-') {
        foreach $comr (@computersbynumber) {
	  $ssprinted = 0;
	  if(exists($comr->{'co_s'})) {
	  if(defined($comr->{'co_s'})) {
	  if($comr->{'co_s'} ne '-') {
	  if(exists($comr->{'us_s'})) {
	  if(defined($comr->{'us_s'})) {
	  if($comr->{'us_s'} eq $userr->{'us_s'}) {
	    debugmsg(4, "Writing license information for computer", $comr->{'co_s'});
	    $sssprinted = undef;
	    $tableopen = 0;
	    foreach $lir (@licensesbynumber) {
	      if(($lir->{'hl'} == 1) || ($lir->{'hl'} == 3)) {
	        if($lir->{'co_s'} eq $comr->{'co_s'}) {
		  $k = 0;
	          $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
		  $manulong = '?'; $proglong = '?';
		  $mpsection = 1; $mpss = 1; $mpsss = 1;
		  $deld = undef; $deln = undef; $invd = undef;
		  $invn = undef; $lino = undef; $lity = undef;
		  $linu = 1;
	          if(exists($lir->{'sw_s'})) {
	            $swn = $lir->{'sw_s'};
	            if(defined($swn)) {
	              if(exists($swproductsbyname{"$swn"})) {
	                $swr = $swproductsbyname{"$swn"};
	                $proglong = $swr->{'sw_l'};
	                if(defined($proglong)) {
		          chomp $proglong;
		          if("$proglong" eq "") {
		            $proglong = '?';
		          }
	                } else { $proglong = '?'; }
	                if(exists($swr->{'sm_s'})) {
	                  $smn = $swr->{'sm_s'};
		          if(defined($smn)) {
		            if(exists($swmanufacturersbyname{"$smn"})) {
		              $smr = $swmanufacturersbyname{"$smn"};
		              if(exists($smr->{'sm_l'})) {
		                $manulong = $smr->{'sm_l'};
		                if(defined($manulong)) {
		                  chomp $manulong;
			          if("$manulong" eq "") {
			            $manulong = '?';
			          }
		                } else { $manulong = '?'; }
		              }
		            } else {
		              $smn = '?';
		            }
		          } else { $smn = '?'; }
	                }
	              } else { $swn = '?'; }
	            } else { $swn = '?'; }
	          }
		  if($sectionprinted) {
		    $mpsection = 0;
		  }
		  if($mpsection) {
		    if($tableopen) {
		      print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
		    }
		    $sectionprinted = 1;
		    $k = 1;
		    print OUTPUT "\\clearpage\n\\section";
		    if(defined($shortusername)) {
		      print OUTPUT "[$shortusername]";
		    }
		    if(defined($fullusername)) {
		      print OUTPUT "{$fullusername}\n";
		    } else {
		      print OUTPUT "{" . $userr->{'us_s'} . "}\n";
		    }
		  }
		  if($ssprinted) {
		    $mpss = 0;
		  }
		  if($mpss) {
		    if($tableopen) {
		      print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
		    }
		    if(!$k) {
		      print OUTPUT "\\clearpage\n";
		    }
		    print OUTPUT "\\subsection[";
		    print OUTPUT lstr($comr->{'co_s'});
		    print OUTPUT "]{";
		    print OUTPUT lstr($comr->{'co_s'});
		    if(exists($comr->{'co_co'})) {
		      $conu = $comr->{'co_co'};
		      if(defined($conu)) {
		        chomp $conu;
			if("$conu" ne "") {
			  print OUTPUT " - " . lstr($conu);
			}
		      }
		      $conu = undef;
		    }
		    print OUTPUT "}\n";
		    $ssprinted = 1;
		  }
		  if(defined($sssprinted)) {
		    if("$sssprinted" eq "$manulong") {
		      $mpsss = 0;
		    }
		  }
		  if($mpsss) {
		    if($tableopen) {
		      print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
		    }
		    print OUTPUT "\\subsubsection{";
		    print OUTPUT lstr($manulong);
		    print OUTPUT "}\n";
		    $sssprinted = $manulong;
		  }
		  # print the license
		  if(!$tableopen) {
		    $tableopen = 1;
		    foreach $k (@startoftable) {
		      print OUTPUT "$k\n";
		    }
		    $k = 0;
		  }
	          $deld = get_license_component($lir, 0);
	          $deln = get_license_component($lir, 1);
	          $invd = get_license_component($lir, 2);
	          $invn = get_license_component($lir, 3);
	          $lino = get_license_component($lir, 4);
	          $lity = get_license_component($lir, 5);
	          $orderno = get_license_component($lir, 6);
		  print OUTPUT "\\multicolumn{5}{l}{";
		  print OUTPUT lstr($proglong);
		  print OUTPUT "}\\\\*\n";
		  print OUTPUT "\\(\\qquad\\)&\\multicolumn{4}{l}{";
		  if(defined($swn)) {
		    print OUTPUT lstr($swn);
		  }
		  print OUTPUT "}\\\\*\n";
		  print OUTPUT "&\\multicolumn{1}{l}{";
		  print OUTPUT $lir->{'li_pk'};
		  print OUTPUT "}";
		  print OUTPUT "&\\multicolumn{3}{r}{";
		  if(defined($orderno)) {
		    print OUTPUT lstr($orderno);
		  }
		  print OUTPUT "}\\\\*\n";

		  print OUTPUT "&\\multicolumn{4}{l}{";
		  if(defined($lity)) {
		    print OUTPUT lstr($lity);
		  }
		  print OUTPUT "}";
		  if($lir->{'hl'} == 3) {
		    print OUTPUT "\\\\\*\n";
		    print OUTPUT "&\\emph{";
		    print OUTPUT lstr($lir->{'us_s'});
		    print OUTPUT "}&\\multicolumn{3}{l}{\\emph{";
		    print OUTPUT lstr(get_full_user_name($usersbyname{$lir->{'us_s'}}));
		    print OUTPUT "}}";
		  }
		  if(defined($deld) || defined($deln) || defined($invd)
		     || defined($invn) || defined($lino))
		  {
		    print OUTPUT "\\\\*\n";
		    if(defined($deld) || defined($deln) || defined($invd)
		       || defined($invn))
		    {
		      print OUTPUT "&";
		      if(defined($deld)) {
		        print OUTPUT lstr($deld);
		      }
		      print OUTPUT "&";
		      if(defined($deln)) {
		        print OUTPUT lstr($deln);
		      }
		      print OUTPUT "&";
		      if(defined($invd)) {
		        print OUTPUT lstr($invd);
		      }
		      print OUTPUT "&";
		      if(defined($invn)) {
		        print OUTPUT lstr($invn);
		      }
		      if(defined($lino)) {
		        print OUTPUT "\\\\*\n";
		      } else {
		        print OUTPUT "\\\\[0.5em]\n";
		      }
		    }
		    if(defined($lino)) {
		      print OUTPUT "&\\multicolumn{4}{l}{";
		      print OUTPUT lstr($lino);
		      print OUTPUT "}\\\\[0.5em]\n";
		    }
		  } else {
		    print OUTPUT "\\\\[0.5em]\n";
		  }

		}
	      }
	    }
	    if($tableopen) {
	      print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	    }
	    debugmsg(
	      4,
	      "Finished writing license information for computer",
	      $comr->{'co_s'}
	    );
	  }
	  }
	  }
	  }
	  }
	  }
	}
	# Licenses assigned to users but not yet assigned to a computer
	$ssprinted = 0; $sssprinted = undef;
	foreach $lir (@licensesbynumber) {
	  if($lir->{'hl'} == 2) {
	  if($lir->{'us_s'} eq $userr->{'us_s'}) {
            $k = 0;
            $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
            $manulong = '?'; $proglong = '?';
            $mpsection = 1; $mpss = 1; $mpsss = 1;
            $deld = undef; $deln = undef; $invd = undef;
            $invn = undef; $lino = undef; $lity = undef;
            $linu = 1;
            if(exists($lir->{'sw_s'})) {
              $swn = $lir->{'sw_s'};
              if(defined($swn)) {
                if(exists($swproductsbyname{"$swn"})) {
                  $swr = $swproductsbyname{"$swn"};
                  $proglong = $swr->{'sw_l'};
                  if(defined($proglong)) {
                    chomp $proglong;
                    if("$proglong" eq "") {
                      $proglong = '?';
                    }
                  } else { $proglong = '?'; }
                  if(exists($swr->{'sm_s'})) {
                    $smn = $swr->{'sm_s'};
                    if(defined($smn)) {
                      if(exists($swmanufacturersbyname{"$smn"})) {
                        $smr = $swmanufacturersbyname{"$smn"};
                        if(exists($smr->{'sm_l'})) {
                          $manulong = $smr->{'sm_l'};
                          if(defined($manulong)) {
                            chomp $manulong;
                            if("$manulong" eq "") {
                              $manulong = '?';
                            }
                          } else { $manulong = '?'; }
                        }
                      } else {
                        $smn = '?';
                      }
                    } else { $smn = '?'; }
                  }
                } else { $swn = '?'; }
              } else { $swn = '?'; }
            }
	    if($sectionprinted) {
	      $mpsection = 0;
	    }
	    if($mpsection) {
	      if($tableopen) {
	        print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	      }
	      $sectionprinted = 1;
	      $k = 1;
	      print OUTPUT "\\clearpage\n\\section";
	      if(defined($shortusername)) {
	        print OUTPUT "[$shortusername]";
	      }
	      if(defined($fullusername)) {
	        print OUTPUT "{$fullusername}\n";
	      } else {
	        print OUTPUT "{" . $userr->{'us_s'} . "}\n";
	      }
	    }
	    if($ssprinted) {
	      $mpss = 0;
	    }
	    if($mpss) {
	      if($tableopen) {
	        print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	      }
	      if(!$k) {
	        print OUTPUT "\\clearpage\n";
	      }
	      print OUTPUT "\\subsection[";
	      print OUTPUT $textobj->get(29);
	      print OUTPUT "]{";
	      print OUTPUT $textobj->get(28);
	      print OUTPUT "}\n";
	      $ssprinted = 1;
	    }
	    if(defined($sssprinted)) {
	      if("$sssprinted" eq "$manulong") {
	        $mpsss = 0;
	      }
	    }
	    if($mpsss) {
	      if($tableopen) {
	        print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	      }
	      $sssprinted = $manulong;
	      print OUTPUT "\\subsubsection{";
	      print OUTPUT lstr($manulong);
	      print OUTPUT "}\n";
	    }
	    # print OUTPUT "\% " . $userr->{'us_s'} . " $manulong $proglong\n";
	    # write table entry for license

	    if(!$tableopen) {
	      foreach $k (@startoftable) {
	        print OUTPUT "$k\n";
	      }
	      $tableopen = 1;
	    }
	    $deld = get_license_component($lir, 0);
	    $deln = get_license_component($lir, 1);
	    $invd = get_license_component($lir, 2);
	    $invn = get_license_component($lir, 3);
	    $lino = get_license_component($lir, 4);
	    $lity = get_license_component($lir, 5);
	    $orderno = get_license_component($lir, 6);
	    print OUTPUT "\\multicolumn{5}{l}{";
	    print OUTPUT lstr($proglong);
	    print OUTPUT "}\\\\*\n";
	    print OUTPUT "\\(\\qquad\\)&\\multicolumn{4}{l}{";
	    print OUTPUT lstr($swn);
	    print OUTPUT "}\\\\*\n";
	    print OUTPUT "&" . $lir->{'li_pk'} . "&";
            print OUTPUT "\\multicolumn{3}{l}{";
	    if(defined($orderno)) {
	      print OUTPUT lstr($orderno);
	    }
	    print OUTPUT "}\\\\*\n";
	    print OUTPUT "&\\multicolumn{4}{l}{";
	    if(defined($lity)) {
	      print OUTPUT lstr($lity);
	    }
	    print OUTPUT "}";
	    if(defined($deld) || defined($deln) || defined($invd) 
	       || defined($invn) || defined($lino))
	    {
	      print OUTPUT "\\\\*\n";
	      if(defined($deld) || defined($deln) || defined($invd)
	         || defined($invn))
	      {
	        print OUTPUT "&";
	        if(defined($deld)) {
	          print OUTPUT lstr($deld);
	        }
	        print OUTPUT "&";
	        if(defined($deln)) {
	          print OUTPUT lstr($deln);
	        }
	        print OUTPUT "&";
	        if(defined($invd)) {
	          print OUTPUT lstr($invd);
	        }
	        print OUTPUT "&";
	        if(defined($invn)) {
	          print OUTPUT lstr($invn);
	        }
	        if(defined($lino)) {
	          print OUTPUT "\\\\*\n";
	        } else {
	          print OUTPUT "\\\\[0.5em]\n";
	        }
	      }
	      if(defined($lino)) {
	        print OUTPUT "&\\multicolumn{4}{l}{";
	        print OUTPUT lstr($lino);
	        print OUTPUT "}\\\\[0.5em]\n";
	      }
	    } else {
	      print OUTPUT "\\\\[0.5em]\n";
	    }
	  }
	  }
	}
	if($tableopen) {
	  print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	}
	# Licenses at other user's PCs
	$ssprinted = 0;
	$sssprinted = undef;
	$tableopen = 0;
	foreach $lir (@licensesbynumber) {
	  if($lir->{'hl'} == 3) {
	  if($lir->{'us_s'} eq $userr->{'us_s'}) {
            $k = 0;
            $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
            $manulong = '?'; $proglong = '?';
            $mpsection = 1; $mpss = 1; $mpsss = 1;
            $deld = undef; $deln = undef; $invd = undef;
            $invn = undef; $lino = undef; $lity = undef;
            $linu = 1;
            if(exists($lir->{'sw_s'})) {
              $swn = $lir->{'sw_s'};
              if(defined($swn)) {
                if(exists($swproductsbyname{"$swn"})) {
                  $swr = $swproductsbyname{"$swn"};
                  $proglong = $swr->{'sw_l'};
                  if(defined($proglong)) {
                    chomp $proglong;
                    if("$proglong" eq "") {
                      $proglong = '?';
                    }
                  } else { $proglong = '?'; }
                  if(exists($swr->{'sm_s'})) {
                    $smn = $swr->{'sm_s'};
                    if(defined($smn)) {
                      if(exists($swmanufacturersbyname{"$smn"})) {
                        $smr = $swmanufacturersbyname{"$smn"};
                        if(exists($smr->{'sm_l'})) {
                          $manulong = $smr->{'sm_l'};
                          if(defined($manulong)) {
                            chomp $manulong;
                            if("$manulong" eq "") {
                              $manulong = '?';
                            }
                          } else { $manulong = '?'; }
                        }
                      } else {
                        $smn = '?';
                      }
                    } else { $smn = '?'; }
                  }
                } else { $swn = '?'; }
              } else { $swn = '?'; }
            }
	    if($sectionprinted) {
	      $mpsection = 0;
	    }
	    if($mpsection) {
	      if($tableopen) {
	        print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	      }
	      $ssprinted = 0; $sssprinted = undef;
	      $sectionprinted = 1;
	      $k = 1;
	      print OUTPUT "\\clearpage\n\\section";
	      if(defined($shortusername)) {
	        print OUTPUT "[$shortusername]";
	      }
	      if(defined($fullusername)) {
	        print OUTPUT "{$fullusername}\n";
	      } else {
	        print OUTPUT "{" . $userr->{'us_s'} . "}\n";
	      }
	    }
	    if($ssprinted) {
	      $mpss = 0;
	    }
	    if($mpss) {
	      if($tableopen) {
	        print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	      }
	      $sssprinted = undef;
	      $ssprinted = 1;
	      print OUTPUT "\\subsection{";
	      print OUTPUT $textobj->get(32);
	      print OUTPUT "}\n";
	      print OUTPUT lstr($fullusername);
	      print OUTPUT $textobj->get(33);
	      print OUTPUT "\n";
	    }
	    if(defined($sssprinted)) {
	      if("$sssprinted" eq "$manulong") {
	        $mpsss = 0;
	      }
	    }
	    if($mpsss) {
	      if($tableopen) {
	        print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
	      }
	      print OUTPUT "\\subsubsection{";
	      print OUTPUT lstr($manulong);
	      print OUTPUT "}\n";
	      $sssprinted = $manulong;
	    }
	    # print license
	    if(!$tableopen) {
	      foreach $k (@startoftable) {
	        print OUTPUT "$k\n";
	      }
	      $tableopen = 1;
	    }
	    $deld = get_license_component($lir, 0);
	    $deln = get_license_component($lir, 1);
	    $invd = get_license_component($lir, 2);
	    $invn = get_license_component($lir, 3);
	    $lino = get_license_component($lir, 4);
	    $lity = get_license_component($lir, 5);
	    $orderno = get_license_component($lir, 6);
	    print OUTPUT "\\multicolumn{5}{l}{";
	    print OUTPUT lstr($proglong);
	    print OUTPUT "}\\\\*\n";
	    print OUTPUT "\\(\\qquad\\)&\\multicolumn{4}{l}{";
	    print OUTPUT lstr($swn);
	    print OUTPUT "}\\\\*\n";
	    print OUTPUT "&" . $lir->{'li_pk'} . "&";
            print OUTPUT "\\multicolumn{3}{l}{";
	    if(defined($orderno)) {
	      print OUTPUT lstr($orderno);
	    }
	    print OUTPUT "}\\\\*\n";
	    print OUTPUT "&\\multicolumn{4}{l}{";
	    if(defined($lity)) {
	      print OUTPUT lstr($lity);
	    }
	    print OUTPUT "}";
	    if(exists($lir->{'co_s'})) {
	      $comr = $lir->{'co_s'};
	      if(defined($comr)) {
	        chomp $comr;
		if("$comr" ne "") {
		  if(exists($computersbyname{"$comr"})) {
		    $comr = $computersbyname{"$comr"};
		    print OUTPUT "\\\\*\n";
		    print OUTPUT "&" . lstr($comr->{'co_s'});
		    print OUTPUT "&\\multicolumn{3}{l}{";
		    if(exists($comr->{'co_co'})) {
		      $conu = $comr->{'co_co'};
		      if(defined($conu)) {
		        chomp $conu;
			if("$conu" ne "") {
			  print OUTPUT lstr($conu);
			}
		      }
		    }
		    print OUTPUT "}";
		    if(exists($comr->{'us_s'})) {
		      $conu = $comr->{'us_s'};
		      if(defined($conu)) {
		        chomp $conu;
			if("$conu" ne "") {
			  if(exists($usersbyname{"$conu"})) {
			    $conu = $usersbyname{"$conu"};
			    print OUTPUT "\\\\*\n&";
			    print OUTPUT lstr($conu->{'us_s'});
			    print OUTPUT "&\\multicolumn{3}{l}{";
			    $conu = get_full_user_name($conu);
			    if(defined($conu)) {
			      chomp $conu;
			      if("$conu" ne "") {
			        print OUTPUT lstr($conu);
			      }
			    }
			    print OUTPUT "}";
			  }
			}
		      }
		    }
		  }
		}
	      }
	    }
	    if(defined($deld) || defined($deln) || defined($invd) 
	       || defined($invn) || defined($lino))
	    {
	      print OUTPUT "\\\\*\n";
	      if(defined($deld) || defined($deln) || defined($invd)
	         || defined($invn))
	      {
	        print OUTPUT "&";
	        if(defined($deld)) {
	          print OUTPUT lstr($deld);
	        }
	        print OUTPUT "&";
	        if(defined($deln)) {
	          print OUTPUT lstr($deln);
	        }
	        print OUTPUT "&";
	        if(defined($invd)) {
	          print OUTPUT lstr($invd);
	        }
	        print OUTPUT "&";
	        if(defined($invn)) {
	          print OUTPUT lstr($invn);
	        }
	        if(defined($lino)) {
	          print OUTPUT "\\\\*\n";
	        } else {
	          print OUTPUT "\\\\[0.5em]\n";
	        }
	      }
	      if(defined($lino)) {
	        print OUTPUT "&\\multicolumn{4}{l}{";
	        print OUTPUT lstr($lino);
	        print OUTPUT "}\\\\[0.5em]\n";
	      }
	    } else {
	      print OUTPUT "\\\\[0.5em]\n";
	    }
	  }
	  }
	}
	if($tableopen) { print OUTPUT "\\end{longtable}\n"; $tableopen = 0; }
      }
      }
      }
      debugmsg(4, "Finished writing license information for $fullusername");
    }
    # sonstige PCs
    # section: PCs unbekannter Nutzer
    # subsection: Hersteller
    # subsubsection: Produkt
    $sectionprinted = 0; $ssprinted = undef; $sssprinted = undef;
    $tableopen = 0;
    foreach $lir (@licensesbynumber) {
      if($lir->{'hl'} == 4) {
        $k = 0;
        $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
        $manulong = '?'; $proglong = '?';
        $mpsection = 1; $mpss = 1; $mpsss = 1;
        $deld = undef; $deln = undef; $invd = undef;
        $invn = undef; $lino = undef; $lity = undef;
        $linu = 1;
        if(exists($lir->{'sw_s'})) {
          $swn = $lir->{'sw_s'};
          if(defined($swn)) {
            if(exists($swproductsbyname{"$swn"})) {
              $swr = $swproductsbyname{"$swn"};
              $proglong = $swr->{'sw_l'};
              if(defined($proglong)) {
                chomp $proglong;
                if("$proglong" eq "") {
                  $proglong = '?';
                }
              } else { $proglong = '?'; }
              if(exists($swr->{'sm_s'})) {
                $smn = $swr->{'sm_s'};
                if(defined($smn)) {
                  if(exists($swmanufacturersbyname{"$smn"})) {
                    $smr = $swmanufacturersbyname{"$smn"};
                    if(exists($smr->{'sm_l'})) {
                      $manulong = $smr->{'sm_l'};
                      if(defined($manulong)) {
                        chomp $manulong;
                        if("$manulong" eq "") {
                          $manulong = '?';
                        }
                      } else { $manulong = '?'; }
                    }
                  } else {
                    $smn = '?';
                  }
                } else { $smn = '?'; }
              }
            } else { $swn = '?'; }
          } else { $swn = '?'; }
        }
        if($sectionprinted) {
          $mpsection = 0;
        }
        if($mpsection) {
          if($tableopen) {
            print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
          }
          $ssprinted = 0; $sssprinted = undef;
          $sectionprinted = 1;
          $k = 1;
          print OUTPUT "\\clearpage\n\\section{";
	  print OUTPUT $textobj->get(34);
	  print OUTPUT "}\n";
        }
        if(defined($ssprinted)) {
	  if("$ssprinted" eq "$manulong") {
            $mpss = 0;
	  }
        }
        if($mpss) {
          if($tableopen) {
            print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
          }
          $sssprinted = undef;
          $ssprinted = $manulong;
          print OUTPUT "\\subsection{";
          print OUTPUT lstr($manulong);
          print OUTPUT "}\n";
          print OUTPUT "\n";
        }
        if(defined($sssprinted)) {
          if("$sssprinted" eq "$proglong") {
            $mpsss = 0;
          }
        }
        if($mpsss) {
          if($tableopen) {
            print OUTPUT "\\end{longtable}\n"; $tableopen = 0;
          }
          print OUTPUT "\\subsubsection{";
          print OUTPUT lstr($proglong);
          print OUTPUT "}\n";
	  print OUTPUT lstr($swn) . "\\\\[0.5em]\n";
	  $sssprinted = $proglong;
        }
        # print license
        if(!$tableopen) {
          foreach $k (@startoftable) {
            print OUTPUT "$k\n";
          }
          $tableopen = 1;
        }
        $deld = get_license_component($lir, 0);
        $deln = get_license_component($lir, 1);
        $invd = get_license_component($lir, 2);
        $invn = get_license_component($lir, 3);
        $lino = get_license_component($lir, 4);
        $lity = get_license_component($lir, 5);
        $orderno = get_license_component($lir, 6);
        print OUTPUT "\\multicolumn{5}{l}{";
        print OUTPUT lstr($proglong);
        print OUTPUT "}\\\\*\n";
        print OUTPUT "\\(\\qquad\\)&" . $lir->{'li_pk'} . "&";
        print OUTPUT "\\multicolumn{3}{l}{";
        if(defined($orderno)) {
          print OUTPUT lstr($orderno);
        }
        print OUTPUT "}\\\\*\n";
        print OUTPUT "&\\multicolumn{4}{l}{";
        if(defined($lity)) {
          print OUTPUT lstr($lity);
        }
        print OUTPUT "}";
        if(exists($lir->{'co_s'})) {
          $comr = $lir->{'co_s'};
          if(defined($comr)) {
            chomp $comr;
            if("$comr" ne "") {
              if(exists($computersbyname{"$comr"})) {
                $comr = $computersbyname{"$comr"};
                print OUTPUT "\\\\*\n";
                print OUTPUT "&" . lstr($comr->{'co_s'});
                print OUTPUT "&\\multicolumn{3}{l}{";
                if(exists($comr->{'co_co'})) {
                  $conu = $comr->{'co_co'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      print OUTPUT lstr($conu);
                    }
                  }
                }
                print OUTPUT "}";
                if(exists($comr->{'us_s'})) {
                  $conu = $comr->{'us_s'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      if(exists($usersbyname{"$conu"})) {
                        $conu = $usersbyname{"$conu"};
                        print OUTPUT "\\\\*\n&";
                        print OUTPUT lstr($conu->{'us_s'});
                        print OUTPUT "&\\multicolumn{3}{l}{";
                        $conu = get_full_user_name($conu);
                        if(defined($conu)) {
                          chomp $conu;
                          if("$conu" ne "") {
                            print OUTPUT lstr($conu);
                          }
                        }
                        print OUTPUT "}";
                      }
                    }
                  }
                }
              }
            }
          }
        }
        if(defined($deld) || defined($deln) || defined($invd) 
           || defined($invn) || defined($lino))
        {
          print OUTPUT "\\\\*\n";
          if(defined($deld) || defined($deln) || defined($invd)
             || defined($invn))
          {
            print OUTPUT "&";
            if(defined($deld)) {
              print OUTPUT lstr($deld);
            }
            print OUTPUT "&";
            if(defined($deln)) {
              print OUTPUT lstr($deln);
            }
            print OUTPUT "&";
            if(defined($invd)) {
              print OUTPUT lstr($invd);
            }
            print OUTPUT "&";
            if(defined($invn)) {
              print OUTPUT lstr($invn);
            }
            if(defined($lino)) {
              print OUTPUT "\\\\*\n";
            } else {
              print OUTPUT "\\\\[0.5em]\n";
            }
          }
          if(defined($lino)) {
            print OUTPUT "&\\multicolumn{4}{l}{";
            print OUTPUT lstr($lino);
            print OUTPUT "}\\\\[0.5em]\n";
          }
        } else {
          print OUTPUT "\\\\[0.5em]\n";
        }
      }
    }
    if($tableopen) { print OUTPUT "\\end{longtable}\n"; $tableopen = 0; }
    # PART II:  By manufacturer and product
    print OUTPUT "\\clearpage\n";
    print OUTPUT "\\part[" . $textobj->get(31);
    print OUTPUT "]{" . $textobj->get(30) . "}\n\\clearpage\n";
    $tableopen = 0;
    $sectionprinted = undef; $ssprinted = undef;
    foreach $lir (@licensesbynumber) {
      $k = 0;
      $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
      $manulong = '?'; $proglong = '?';
      $mpsection = 1; $mpss = 1; $mpsss = 1;
      $deld = undef; $deln = undef; $invd = undef;
      $invn = undef; $lino = undef; $lity = undef;
      $linu = 1;
      if(exists($lir->{'sw_s'})) {
        $swn = $lir->{'sw_s'};
        if(defined($swn)) {
          if(exists($swproductsbyname{"$swn"})) {
            $swr = $swproductsbyname{"$swn"};
            $proglong = $swr->{'sw_l'};
            if(defined($proglong)) {
              chomp $proglong;
              if("$proglong" eq "") {
                $proglong = '?';
              }
            } else { $proglong = '?'; }
            if(exists($swr->{'sm_s'})) {
              $smn = $swr->{'sm_s'};
              if(defined($smn)) {
                if(exists($swmanufacturersbyname{"$smn"})) {
                  $smr = $swmanufacturersbyname{"$smn"};
                  if(exists($smr->{'sm_l'})) {
                    $manulong = $smr->{'sm_l'};
                    if(defined($manulong)) {
                      chomp $manulong;
                      if("$manulong" eq "") {
                        $manulong = '?';
                      }
                    } else { $manulong = '?'; }
                  }
                } else {
                  $smn = '?';
                }
              } else { $smn = '?'; }
            }
          } else { $swn = '?'; }
        } else { $swn = '?'; }
      }
      if(defined($sectionprinted)) {
        if("$sectionprinted" eq "$manulong") {
	  $mpsection = 0;
	}
      }
      if($mpsection) {
        if($tableopen) { print OUTPUT "\\end{longtable}\n"; $tableopen = 0; }
	print OUTPUT "\\section{";
	print OUTPUT lstr($manulong);
	print OUTPUT "}\n";
	$sectionprinted = $manulong;
	$ssprinted = undef;
      }
      if(defined($ssprinted)) {
        if("$ssprinted" eq "$proglong") {
	  $mpss = 0;
	}
      }
      if($mpss) {
        if($tableopen) { print OUTPUT "\\end{longtable}\n"; $tableopen = 0; }
	print OUTPUT "\\subsection{";
	print OUTPUT lstr($proglong);
	print OUTPUT "}\n";
	$ssprinted = $proglong;
	print OUTPUT lstr($swn) . "\\\\[0.5em]\n";
      }
      # print license
      if(!$tableopen) {
        foreach $k (@startoftable) {
          print OUTPUT "$k\n";
        }
        $tableopen = 1;
      }
      $deld = get_license_component($lir, 0);
      $deln = get_license_component($lir, 1);
      $invd = get_license_component($lir, 2);
      $invn = get_license_component($lir, 3);
      $lino = get_license_component($lir, 4);
      $lity = get_license_component($lir, 5);
      $orderno = get_license_component($lir, 6);
      print OUTPUT $lir->{'li_pk'} . "&\\multicolumn{4}{l}{";
      if(defined($orderno)) {
        print OUTPUT lstr($orderno);
      }
      print OUTPUT "}\\\\*\n";
      print OUTPUT "\\(\\qquad\\)&\\multicolumn{4}{l}{";
      if(defined($lity)) {
        print OUTPUT lstr($lity);
      }
      print OUTPUT "}";
      if($lir->{'hl'} == 0) {
        # License available for assignment to user and computer
	print OUTPUT "\\\\*\n&\\multicolumn{4}{l}{";
	print OUTPUT $textobj->get(26);
	print OUTPUT "}";
      } else {
      if(($lir->{'hl'} == 1) || ($lir->{'hl'} == 3)) {
        # License assigned to PC, owner of PC known
        if(exists($lir->{'co_s'})) {
          $comr = $lir->{'co_s'};
          if(defined($comr)) {
            chomp $comr;
            if("$comr" ne "") {
              if(exists($computersbyname{"$comr"})) {
                $comr = $computersbyname{"$comr"};
                print OUTPUT "\\\\*\n";
                print OUTPUT "&" . lstr($comr->{'co_s'});
                print OUTPUT "&\\multicolumn{3}{l}{";
                if(exists($comr->{'co_co'})) {
                  $conu = $comr->{'co_co'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      print OUTPUT lstr($conu);
                    }
                  }
                }
                print OUTPUT "}";
                if(exists($comr->{'us_s'})) {
                  $conu = $comr->{'us_s'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      if(exists($usersbyname{"$conu"})) {
                        $conu = $usersbyname{"$conu"};
                        print OUTPUT "\\\\*\n&";
                        print OUTPUT lstr($conu->{'us_s'});
                        print OUTPUT "&\\multicolumn{3}{l}{";
                        $conu = get_full_user_name($conu);
                        if(defined($conu)) {
                          chomp $conu;
                          if("$conu" ne "") {
                            print OUTPUT lstr($conu);
                          }
                        }
                        print OUTPUT "}";
		        if($lir->{'hl'} == 3) {
		          if(exists($lir->{'us_s'})) {
			    $conu = $lir->{'us_s'};
			    if(defined($conu)) {
			      chomp $conu;
			      if("$conu" ne "") {
			        if(exists($usersbyname{"$conu"})) {
			          $conu = $usersbyname{"$conu"};
				  print OUTPUT "\\\\*\n&\\emph{";
				  print OUTPUT lstr($conu->{'us_s'});
				  print OUTPUT "}&\\multicolumn{3}{l}{\\emph{";
				  $conu = get_full_user_name($conu);
				  if(defined($conu)) {
				    chomp $conu;
				    if("$conu" ne "") {
				      print OUTPUT lstr($conu);
				    }
				  }
				  print OUTPUT "}}";
			        }
			      }
			    }
			  }
		        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      } else {
      if($lir->{'hl'} == 2) {
        # Only user name of license owner known
	if(exists($lir->{'us_s'})) {
	  $conu = $lir->{'us_s'};
	  if(defined($conu)) {
	    chomp $conu;
	    if("$conu" ne "") {
	      if(exists($usersbyname{"$conu"})) {
	        $conu = $usersbyname{"$conu"};
		print OUTPUT "\\\\*\n&\\multicolumn{4}{l}{";
		print OUTPUT $textobj->get(28);
		print OUTPUT "}\\\\*\n&";
		print OUTPUT lstr($conu->{'us_s'});
		print OUTPUT "&\\multicolumn{3}{l}{";
		$conu = get_full_user_name($conu);
		if(defined($conu)) {
		  chomp $conu;
		  if("$conu" ne "") {
		    print OUTPUT lstr($conu);
		  }
		}
		print OUTPUT "}";
	      }
	    }
	  }
	}
      } else {
      if($lir->{'hl'} == 4) {
        # Name of computer known but no owner
        if(exists($lir->{'co_s'})) {
          $comr = $lir->{'co_s'};
          if(defined($comr)) {
            chomp $comr;
            if("$comr" ne "") {
              if(exists($computersbyname{"$comr"})) {
                $comr = $computersbyname{"$comr"};
                print OUTPUT "\\\\*\n";
                print OUTPUT "&" . lstr($comr->{'co_s'});
                print OUTPUT "&\\multicolumn{3}{l}{";
                if(exists($comr->{'co_co'})) {
                  $conu = $comr->{'co_co'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      print OUTPUT lstr($conu);
                    }
                  }
                }
                print OUTPUT "}";
              }
            }
          }
        }
      } else {
        # Must not happen
      }
      }
      }
      }
      if(defined($deld) || defined($deln) || defined($invd) 
         || defined($invn) || defined($lino))
      {
        print OUTPUT "\\\\*\n";
        if(defined($deld) || defined($deln) || defined($invd)
           || defined($invn))
        {
          print OUTPUT "&";
          if(defined($deld)) {
            print OUTPUT lstr($deld);
          }
          print OUTPUT "&";
          if(defined($deln)) {
            print OUTPUT lstr($deln);
          }
          print OUTPUT "&";
          if(defined($invd)) {
            print OUTPUT lstr($invd);
          }
          print OUTPUT "&";
          if(defined($invn)) {
            print OUTPUT lstr($invn);
          }
          if(defined($lino)) {
            print OUTPUT "\\\\*\n";
          } else {
            print OUTPUT "\\\\[0.5em]\n";
          }
        }
        if(defined($lino)) {
          print OUTPUT "&\\multicolumn{4}{l}{";
          print OUTPUT lstr($lino);
          print OUTPUT "}\\\\[0.5em]\n";
        }
      } else {
        print OUTPUT "\\\\[0.5em]\n";
      }
    }
    if($tableopen) { print OUTPUT "\\end{longtable}\n"; $tableopen = 0; }
    # PART III: By date
    print OUTPUT "\\clearpage\n";
    print OUTPUT "\\part{" . $textobj->get(24) . "}\\clearpage\n";
    print OUTPUT "\\clearpage\n";
    $tableopen = 0;
    foreach $lipk (sort { $a <=> $b } (keys  %licensesbypk)) {
      $lir = $licensesbypk{"$lipk"};
      $k = 0;
      $swn = '?'; $swr = undef; $smn = '?'; $smr = undef;
      $manulong = '?'; $proglong = '?';
      $mpsection = 1; $mpss = 1; $mpsss = 1;
      $deld = undef; $deln = undef; $invd = undef;
      $invn = undef; $lino = undef; $lity = undef;
      $linu = 1;
      if(exists($lir->{'sw_s'})) {
        $swn = $lir->{'sw_s'};
        if(defined($swn)) {
          if(exists($swproductsbyname{"$swn"})) {
            $swr = $swproductsbyname{"$swn"};
            $proglong = $swr->{'sw_l'};
            if(defined($proglong)) {
              chomp $proglong;
              if("$proglong" eq "") {
                $proglong = '?';
              }
            } else { $proglong = '?'; }
            if(exists($swr->{'sm_s'})) {
              $smn = $swr->{'sm_s'};
              if(defined($smn)) {
                if(exists($swmanufacturersbyname{"$smn"})) {
                  $smr = $swmanufacturersbyname{"$smn"};
                  if(exists($smr->{'sm_l'})) {
                    $manulong = $smr->{'sm_l'};
                    if(defined($manulong)) {
                      chomp $manulong;
                      if("$manulong" eq "") {
                        $manulong = '?';
                      }
                    } else { $manulong = '?'; }
                  }
                } else {
                  $smn = '?';
                }
              } else { $smn = '?'; }
            }
          } else { $swn = '?'; }
        } else { $swn = '?'; }
      }
      # print license
      if(!$tableopen) {
        foreach $k (@startoftable) {
          print OUTPUT "$k\n";
        }
        $tableopen = 1;
      }
      $deld = get_license_component($lir, 0);
      $deln = get_license_component($lir, 1);
      $invd = get_license_component($lir, 2);
      $invn = get_license_component($lir, 3);
      $lino = get_license_component($lir, 4);
      $lity = get_license_component($lir, 5);
      $orderno = get_license_component($lir, 6);
      print OUTPUT "\\multicolumn{5}{l}{";
      print OUTPUT lstr($proglong);
      print OUTPUT "}\\\\*\n";
      print OUTPUT "\\(\\qquad\\)&\\multicolumn{4}{l}{";
      print OUTPUT lstr($swn);
      print OUTPUT "}\\\\*\n";
      print OUTPUT "&" . $lir->{'li_pk'} . "&";
      print OUTPUT "\\multicolumn{3}{l}{";
      if(defined($orderno)) {
        print OUTPUT lstr($orderno);
      }
      print OUTPUT "}\\\\*\n";
      print OUTPUT "&\\multicolumn{4}{l}{";
      if(defined($lity)) {
        print OUTPUT lstr($lity);
      }
      print OUTPUT "}";
      if($lir->{'hl'} == 0) {
        # License available for assignment to user and computer
	print OUTPUT "\\\\*\n&\\multicolumn{4}{l}{";
	print OUTPUT $textobj->get(26);
	print OUTPUT "}";
      } else {
      if(($lir->{'hl'} == 1) || ($lir->{'hl'} == 3)) {
        # License assigned to PC, owner of PC known
        if(exists($lir->{'co_s'})) {
          $comr = $lir->{'co_s'};
          if(defined($comr)) {
            chomp $comr;
            if("$comr" ne "") {
              if(exists($computersbyname{"$comr"})) {
                $comr = $computersbyname{"$comr"};
                print OUTPUT "\\\\*\n";
                print OUTPUT "&" . lstr($comr->{'co_s'});
                print OUTPUT "&\\multicolumn{3}{l}{";
                if(exists($comr->{'co_co'})) {
                  $conu = $comr->{'co_co'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      print OUTPUT lstr($conu);
                    }
                  }
                }
                print OUTPUT "}";
                if(exists($comr->{'us_s'})) {
                  $conu = $comr->{'us_s'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      if(exists($usersbyname{"$conu"})) {
                        $conu = $usersbyname{"$conu"};
                        print OUTPUT "\\\\*\n&";
                        print OUTPUT lstr($conu->{'us_s'});
                        print OUTPUT "&\\multicolumn{3}{l}{";
                        $conu = get_full_user_name($conu);
                        if(defined($conu)) {
                          chomp $conu;
                          if("$conu" ne "") {
                            print OUTPUT lstr($conu);
                          }
                        }
                        print OUTPUT "}";
		        if($lir->{'hl'} == 3) {
		          if(exists($lir->{'us_s'})) {
			    $conu = $lir->{'us_s'};
			    if(defined($conu)) {
			      chomp $conu;
			      if("$conu" ne "") {
			        if(exists($usersbyname{"$conu"})) {
			          $conu = $usersbyname{"$conu"};
				  print OUTPUT "\\\\*\n&\\emph{";
				  print OUTPUT lstr($conu->{'us_s'});
				  print OUTPUT "}&\\multicolumn{3}{l}{\\emph{";
				  $conu = get_full_user_name($conu);
				  if(defined($conu)) {
				    chomp $conu;
				    if("$conu" ne "") {
				      print OUTPUT lstr($conu);
				    }
				  }
				  print OUTPUT "}}";
			        }
			      }
			    }
			  }
		        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      } else {
      if($lir->{'hl'} == 2) {
        # Only user name of license owner known
	if(exists($lir->{'us_s'})) {
	  $conu = $lir->{'us_s'};
	  if(defined($conu)) {
	    chomp $conu;
	    if("$conu" ne "") {
	      if(exists($usersbyname{"$conu"})) {
	        $conu = $usersbyname{"$conu"};
		print OUTPUT "\\\\*\n&\\multicolumn{4}{l}{";
		print OUTPUT $textobj->get(28);
		print OUTPUT "}\\\\*\n&";
		print OUTPUT lstr($conu->{'us_s'});
		print OUTPUT "&\\multicolumn{3}{l}{";
		$conu = get_full_user_name($conu);
		if(defined($conu)) {
		  chomp $conu;
		  if("$conu" ne "") {
		    print OUTPUT lstr($conu);
		  }
		}
		print OUTPUT "}";
	      }
	    }
	  }
	}
      } else {
      if($lir->{'hl'} == 4) {
        # Name of computer known but no owner
        if(exists($lir->{'co_s'})) {
          $comr = $lir->{'co_s'};
          if(defined($comr)) {
            chomp $comr;
            if("$comr" ne "") {
              if(exists($computersbyname{"$comr"})) {
                $comr = $computersbyname{"$comr"};
                print OUTPUT "\\\\*\n";
                print OUTPUT "&" . lstr($comr->{'co_s'});
                print OUTPUT "&\\multicolumn{3}{l}{";
                if(exists($comr->{'co_co'})) {
                  $conu = $comr->{'co_co'};
                  if(defined($conu)) {
                    chomp $conu;
                    if("$conu" ne "") {
                      print OUTPUT lstr($conu);
                    }
                  }
                }
                print OUTPUT "}";
              }
            }
          }
        }
      } else {
        # Must not happen
      }
      }
      }
      }
      if(defined($deld) || defined($deln) || defined($invd) 
         || defined($invn) || defined($lino))
      {
        print OUTPUT "\\\\*\n";
        if(defined($deld) || defined($deln) || defined($invd)
           || defined($invn))
        {
          print OUTPUT "&";
          if(defined($deld)) {
            print OUTPUT lstr($deld);
          }
          print OUTPUT "&";
          if(defined($deln)) {
            print OUTPUT lstr($deln);
          }
          print OUTPUT "&";
          if(defined($invd)) {
            print OUTPUT lstr($invd);
          }
          print OUTPUT "&";
          if(defined($invn)) {
            print OUTPUT lstr($invn);
          }
          if(defined($lino)) {
            print OUTPUT "\\\\*\n";
          } else {
            print OUTPUT "\\\\[0.5em]\n";
          }
        }
        if(defined($lino)) {
          print OUTPUT "&\\multicolumn{4}{l}{";
          print OUTPUT lstr($lino);
          print OUTPUT "}\\\\[0.5em]\n";
        }
      } else {
        print OUTPUT "\\\\[0.5em]\n";
      }
    }
    if($tableopen) { print OUTPUT "\\end{longtable}\n"; $tableopen = 0; }
    # postamble
    $preamble = $textobj->get_latex_postamble2();
    foreach $k (@$preamble) {
      print OUTPUT "$k\n";
    }
    close(OUTPUT);
  } else {
    debugmsg(1, "Failed to write file \"$fn\"!");
  }
  debugmsg(4, "Writing license report (finished)");
}

sub convert_utf8_to_latin()
{
  my $k; my $r;
  my $uref = DKrause::DecodeUTF8::new();
  # vlans
  #   vl_l
  foreach $k (keys %vlansbyname) {
    $r = $vlansbyname{"$k"};
    if(exists($r->{'vl_l'})) {
    if(defined($r->{'vl_l'})) {
      $r->{'vl_l'} = $uref->decode($r->{'vl_l'});
    }
    }
  }
  # ddspeed
  #    sp_l
  foreach $k (keys %ddspeedbyname) {
    $r = $ddspeedbyname{"$k"};
    if(exists($r->{'sp_l'})) {
    if(defined($r->{'sp_l'})) {
      $r->{'sp_l'} = $uref->decode($r->{'sp_l'});
    }
    }
  }
  # buildings
  #  gb_l, a1, a2, a3, a4, ort#
  foreach $k (keys %buildingsbyname) {
    $r = $buildingsbyname{"$k"};
    if(exists($r->{'gb_l'})) {
    if(defined($r->{'gb_l'})) {
      $r->{'gb_l'} = $uref->decode($r->{'gb_l'});
    }
    }
    if(exists($r->{'gb_a1'})) {
    if(defined($r->{'gb_a1'})) {
      $r->{'gb_a1'} = $uref->decode($r->{'gb_a1'});
    }
    }
    if(exists($r->{'gb_a2'})) {
    if(defined($r->{'gb_a2'})) {
      $r->{'gb_a2'} = $uref->decode($r->{'gb_a2'});
    }
    }
    if(exists($r->{'gb_a3'})) {
    if(defined($r->{'gb_a3'})) {
      $r->{'gb_a3'} = $uref->decode($r->{'gb_a3'});
    }
    }
    if(exists($r->{'gb_a4'})) {
    if(defined($r->{'gb_a4'})) {
      $r->{'gb_a4'} = $uref->decode($r->{'gb_a4'});
    }
    }
    if(exists($r->{'gb_ort'})) {
    if(defined($r->{'gb_ort'})) {
      $r->{'gb_ort'} = $uref->decode($r->{'gb_ort'});
    }
    }
  }
  # users
  #  us_t, sn, fn, ko, s3
  foreach $k (keys %usersbyname) {
    $r = $usersbyname{"$k"};
    if(exists($r->{'us_t'})) {
    if(defined($r->{'us_t'})) {
      $r->{'us_t'} = $uref->decode($r->{'us_t'});
    }
    }
    if(exists($r->{'us_sn'})) {
    if(defined($r->{'us_sn'})) {
      $r->{'us_sn'} = $uref->decode($r->{'us_sn'});
    }
    }
    if(exists($r->{'us_fn'})) {
    if(defined($r->{'us_fn'})) {
      $r->{'us_fn'} = $uref->decode($r->{'us_fn'});
    }
    }
    if(exists($r->{'us_ko'})) {
    if(defined($r->{'us_ko'})) {
      $r->{'us_ko'} = $uref->decode($r->{'us_ko'});
    }
    }
    if(exists($r->{'us_se'})) {
    if(defined($r->{'us_se'})) {
      $r->{'us_se'} = $uref->decode($r->{'us_se'});
    }
    }
  }
  # netgroups
  #  ng_l
  foreach $k (keys %netgroupsbyname) {
    $r = $netgroupsbyname{"$k"};
    if(exists($r->{'ng_l'})) {
    if(defined($r->{'ng_l'})) {
      $r->{'ng_l'} = $uref->decode($r->{'ng_l'});
    }
    }
  }
  # dhcpclasses
  #  dc_d
  foreach $k (keys %dhcpclassesbyname) {
    $r = $dhcpclassesbyname{"$k"};
    if(exists($r->{'dc_d'})) {
    if(defined($r->{'dc_d'})) {
      $r->{'dc_d'} = $uref->decode($r->{'dc_d'});
    }
    }
  }
  # dhcpdgroups
  #  dg_l
  foreach $k (keys %dhcpgroupsbyname) {
    $r = $dhcpgroupsbyname{"$k"};
    if(exists($r->{'dg_l'})) {
    if(defined($r->{'dg_l'})) {
      $r->{'dg_l'} = $uref->decode($r->{'dg_l'});
    }
    }
  }
  # computers
  #  co_co
  foreach $k (keys %computersbyname) {
    $r = $computersbyname{"$k"};
    if(exists($r->{'co_co'})) {
    if(defined($r->{'co_co'})) {
      $r->{'co_co'} = $uref->decode($r->{'co_co'});
    }
    }
  }
  # swmanufacturers
  #  sm_l
  foreach $k (keys %swmanufacturersbyname) {
    $r = $swmanufacturersbyname{"$k"};
    if(exists($r->{'sm_l'})) {
    if(defined($r->{'sm_l'})) {
      $r->{'sm_l'} = $uref->decode($r->{'sm_l'});
    }
    }
  }
  # swproducts
  #  sw_l
  foreach $k (keys %swproductsbyname) {
    $r = $swproductsbyname{"$k"};
    if(exists($r->{'sw_l'})) {
    if(defined($r->{'sw_l'})) {
      $r->{'sw_l'} = $uref->decode($r->{'sw_l'});
    }
    }
  }
  # swreserllers
  #  sr_l, a1, a2, a3, a4, ort
  foreach  $k (keys %swresellersbyname) {
    $r = $swresellersbyname{"$k"};
    if(exists($r->{'sr_l'})) {
    if(defined($r->{'sr_l'})) {
      $r->{'sr_l'} = $uref->decode($r->{'sr_l'});
    }
    }
    if(exists($r->{'sr_a1'})) {
    if(defined($r->{'sr_a1'})) {
      $r->{'sr_a1'} = $uref->decode($r->{'sr_a1'});
    }
    }
    if(exists($r->{'sr_a2'})) {
    if(defined($r->{'sr_a2'})) {
      $r->{'sr_a2'} = $uref->decode($r->{'sr_a2'});
    }
    }
    if(exists($r->{'sr_a3'})) {
    if(defined($r->{'sr_a3'})) {
      $r->{'sr_a3'} = $uref->decode($r->{'sr_a3'});
    }
    }
    if(exists($r->{'sr_a4'})) {
    if(defined($r->{'sr_a4'})) {
      $r->{'sr_a4'} = $uref->decode($r->{'sr_a4'});
    }
    }
    if(exists($r->{'sr_ort'})) {
    if(defined($r->{'sr_ort'})) {
      $r->{'sr_ort'} = $uref->decode($r->{'sr_ort'});
    }
    }
  }
  # licensetypes
  #  lt_l
  foreach $k (keys %licensetypesbyname) {
    $r = $licensetypesbyname{"$k"};
    if(exists($r->{'lt_l'})) {
    if(defined($r->{'lt_l'})) {
      $r->{'lt_l'} = $uref->decode($r->{'lt_l'});
    }
    }
  }
  # licenses
  #  li_on, li_no, 
  foreach $k (keys %licensesbypk) {
    $r = $licensesbypk{"$k"};
    if(exists($r->{'li_on'})) {
    if(defined($r->{'li_on'})) {
      $r->{'li_on'} = $uref->decode($r->{'li_on'});
    }
    }
    if(exists($r->{'li_no'})) {
    if(defined($r->{'li_no'})) {
      $r->{'li_no'} = $uref->decode($r->{'li_no'});
    }
    }
  }
}

sub set_latex_encoder()
{
  my $app = DKrause::Application::new("hostsadm", "hostsadm", "/etc", 0, 0);
  my $d = $app->getPreference("/dir/shared", 0);
  if(!defined($d)) {
    $d = "/usr/local/share";
  }
  $d = "$d/uc2lat-t";
  $latexencoder = DKrause::LaTeXEncoder::new($d);
}

sub get_current_date()
{
  my @l; my $cday; my $cmon; my $cyear;
  @l = localtime(time());
  $cday = $l[3];
  $cmon = $l[4];
  $cyear = $l[5] + 1900;
  $currenttimestr = sprintf("%04d-%02d-%02d", $cyear, $cmon, $cday);
}



# Get the current date
get_current_date();
# Check environment for UTF-8
if(exists$ENV{'LANG'}) {
  if(defined($ENV{'LANG'})) {
    if($ENV{'LANG'} =~ /.*\.[Uu][Tt][Ff]\-8/o) {
      $convert_text_to_latin = 0;
    }
  }
}
# Set up some constant factors
$f3 = 256; $f2 = $f3 * 256; $f1 = $f2 * 256;
# Process command line arguments
read_command_line_options(\@ARGV);
# Read configuration file
$confobj = haconfig->new($configurationfilename);
$textobj = hatext->new($confobj->{'doclang'});
set_latex_encoder();
if($confobj->{'debug'} >= 5) {
  show_configuration();
}
# Read data from database
read_data();
if($confobj->{'decutf-8'}) {
  convert_utf8_to_latin();
}
# Checks and output
if($exval == 0) {
  do_the_check();
  if($exval == 0) {
    if($do_hosts) { write_hosts_files(); }
    if($do_licenses) { write_license_report(); }
  }
}

exit($exval);

