#!/bin/sh
# Tcl sees the next lines as an assignment to variable `kludge'.
# For sh, the two shifts cancel the effect of the set, and then we
# run scotty on this script.

set kludge { $*
    shift
    shift
    if test -x ../scotty ; then
      exec ../scotty -nf $0 $*
    else
      exec scotty -nf $0 $*
    fi
}

##
## Copyright (c) 1993 St. Schoek
##                    TU Braunschweig, Germany
##                    Institute for Operating Systems and Computer Networks
##
## Permission to use, copy, modify, and distribute this
## software and its documentation for any purpose and without
## fee is hereby granted, provided that this copyright
## notice appears in all copies.  The University of Braunschweig
## makes no representations about the suitability of this
## software for any purpose.  It is provided "as is" without
## express or implied warranty.
##

##
## VERAENDERUNGEN:
##		
##	
##    		   
## 		  
##
##

##
## ATTENTION!! The following definition gets replaced from the 
## install target of the Makefile. See main for more details.
##

set ETC_DIR /usr/local/etc

## some global variables not configured by argv; see proc main

set slave_list       ""
set to_socket        ""
set trouble_result   ""
set write_data_error 0
set sample_control_timestamp "0000 000"

##
## writes error-msg to stderr
## this proc can be used when modifying and debugging the tool
##

proc scottyerror { msg } { 
    global errorInfo

    puts stderr "$msg\n$errorInfo"
}

##
## Delete an element from a list.
##

proc ldelete {list element} {
    upvar $list mylist
    set result ""
    foreach e $mylist {
        if {$e != $element} { lappend result $e }
    }
    return $result
}

##
## Test if the argument is a real number.
##

proc isnumber {num} {
    return [expr [catch {expr $num+1}] ? 0 : 1]
}

##
## Start the server side. Create a control socket 
## 

proc start_control_daemon {} {
    global server_port
    global control_socket
    global start_time
    global to_history

    set run 1
    while {$run} {
	if {![info exists control_socket]} {
	    if {[catch {tcp listen $server_port} control_socket]} {
		unset control_socket
		sleep 10
	    } else {
		set run 0
	    }
	}
    }
    ## set the global start_time used also by info_list
    set start_time [getdate]
    ## create the correct filenames for this day
    set_file_name
    lappend to_history "socket created at $start_time"
    ## handle the first connect attempts from other tools
    addinput -read $control_socket handle_connection
}

## 
## procedures for direkt communication (reading, writing, controlling socket
##  and stdout)
##
##
## proc checks the sockets for requests
## if control_socket is the socket, a connection will be build
## the handle is given to scotty by addinput to check if messages are coming
##

proc handle_connection {} {
    global slave_list
    global user
    global control_socket
    global to_history
    global to_socket
    
    ## get the current time
    set start_time [getdate]
    ## create a handle for reading, writing etc on the socket
    set socket [tcp accept $control_socket]
    addinput -read $socket "read_socket $socket"
    ## append handle to handle_list
    lappend slave_list $socket
    set user($socket,name) unknown
    set user($socket,datum) $start_time
    ## wait a little
    sleep 1
    ## tell the user that we get his connect inquiry
    catch {puts $socket "ok accepted"; flush $socket}
    lappend to_history "connection from [lindex [tcp info $socket] 2] on \
                        $socket at $start_time"
}

##
## proc reads request from handle if there is a request from slave 
## and parses the request
##

proc read_socket {req_socket} {
    global to_history
    global to_socket
    global socket

    set socket $req_socket
    if {$socket == ""} { return }
    # read from socket and check which things are requested by the slave
    if {[catch {gets $socket} request]} {
	## we can not read from the handle, so write a message and close
        ## the connection 
 	lappend to_history "error read_socket: gets on $socket failed"
	write_history
	close_connection $socket slave
	return
    }
    if {[eof $socket]} {
	## eof is read, so close the connection
	lappend to_history "eof from $socket"
	write_history
	close_connection $socket slave
	return
    }
    if {$request == ""} {
	## some connnections (HP) send unnormal chars so realize them 
	set socket ""
	return
    }
    ## now parse the message
    if {[catch {set len [llength $request]}]} {
	catch {puts $socket "error {syntax error in command-string}"
	    flush $socket}
	set socket ""
	return
    }

    if {$len > 3} {
	catch {puts $socket "error {syntax error in command-string}"
	    flush $socket}
	set socket ""
	return
    }
    set cmd     [lindex $request 0]
    set cmd_add [lindex $request 1]
    set arg     [lindex $request 2]
    ## give the message arguments to process to call the correct procedures
    ## to work with them
    process $cmd $cmd_add $request $arg
    ## after the work is done, write the result to the handle
    write_socket
    ## write a message to the history if necessary
    write_history
}

##
## write the result to the requesting handle
##

proc write_socket {} {
    global slave_list
    global to_socket
    global to_history
    global socket

    if {$socket == ""} { return }
    # we check here, because it is possible
    # that one of them is empty
    if {$to_socket == ""} { 
	set to_socket error
    }
    if {$slave_list == ""} { 
	set socket ""
	set to_socket ""
	return 
    }
    while {$to_socket != ""} {
	set message [lindex $to_socket 0]
	set to_socket [ldelete to_socket $message]
	if {[catch {puts $socket $message; flush $socket} res]} {
	    lappend to_history "error write_socket: $res"
	    close_connection $socket slave
	    puts stdout "nothing to write"
	}
    }
    set socket ""
}

##
## Proc Writes Everything From to_history to the historyfile
## 

proc write_history {} {
    global user
    global slave_list
    global to_history
    global history_file

    if {![info exists to_history]} { return }
    while {$to_history != ""} {
	if {[catch {open $history_file a} filehandle]} {
	    lappend to_history "error write_history: $filehandle"
	    return
	}
     	set message [lindex $to_history 0]
        if {[catch {puts $filehandle $message; flush $filehandle} result]} {
	    lappend to_history "error write_history: $result"
	    catch {close $filehandle}
	    return
	}
	catch {close $filehandle}
        set to_history [ldelete to_history $message]
    }
}

##
## procedures to react to commands appearing on socket
##
##
##
## parse the handle requests and call the correct corresponding procedures
##

proc process {cmd cmd_add result arg} {
    global socket
    global to_socket
    global user
    global slave_list
    global to_history
    
    case $cmd in {
	{error} {
	    error_mess_handling $cmd_add [list $arg]
	    return
	}
	{data} {
	    prepare_data $cmd_add $arg
	    return
	}
	{data_info} {
	    send_config_data $cmd_add
	    return
	}
	{data_info_old} {
	    read_old_configs $cmd_add
	    return
	}
	{data_old_tag} {
	    send_old_data_control $cmd_add
	    return
	}
	{data_insert_tag} {
	    insert_tag $cmd_add
	    return
	}
	{data_delete_tag} {
	    delete_tag $cmd_add
	    return
	}
	{data_reset_tag} {
	    clear_send_table
	    return
	}
	{limit_info} {
	    limit_info_list $cmd_add $arg
	    return
	}
	{limit_insert_req} {
	    insert_limit_req $cmd_add 
	    return
	}
	{limit_delete_req} {
	    delete_limit_req $cmd_add 
	    return
	}
	{limit_set_warn} {
	    set_warn $cmd_add
	    return
	}
	{limit_set} {
	    set_limit $cmd_add
	    return
	}
	{limit_delete_tag} {
	    delete_limit $cmd_add
	    return
	}
	{name} {
	    insert_name $cmd_add 
	    return
	}
	{info} {
	    info_list $cmd_add
	    return
	}
	{close_connect} {
	    close_connection $socket $cmd_add
	    return
	}
	{q quit close} {
	    close_connection $socket slave
	    return
	}
	{kill_monitor} {
	    kill_monitor $socket
	    return
	}
	{message} {
	    send_message $cmd_add $arg
	    return
	}
	{default} {
	    lappend to_history "error process: do not know command $cmd"
	    lappend to_socket "error $cmd"
	    return
	}
    }
    lappend to_socket "error $result"
    lappend to_history "error process: unknown command in request $cmd \
                        with $cmd_add"
}

##
## error handling 
## parse the incoming error-messages and write a message to the historyfile
##

proc error_mess_handling {cmd_add info} { 
    global socket
    global user 
    global to_socket
    global to_history

    set datum [getdate]
    if {![info exists user($socket,name)]} {
	set name unknown
    } else {
	set name $user($socket,name)
    }
    lappend to_history "error: $name $cmd_add $info $datum"
    lappend to_socket "ok error"
    return
}

##
## proc starts all needed tools
##

proc start_tools {} {
    global sample_control_table
    global sample_control_count
    global server_port
    global start_dir
    global to_history
    
    if {[info exists sample_control_count]} {
	for {set i 0} {$i <= $sample_control_count} {incr i} {
	    ## check if we must start the tool
	    if {$sample_control_table($i,status) != "waiting_for_ok"} {
		continue
	    }
	    ## start tool and set the variables
	    set header    $sample_control_table($i,header)
	    set tool_name $sample_control_table($i,tool_name) 

	    ## set the argv for the tools
	    set tool_argv "$server_port $tool_name $start_dir"

	    if {[info exists sample_control_table($i,nodes)]} {
		if {[catch {exec $header $tool_argv &}  \
		     jobnr]}  {
		    set message "can not start tool $jobnr [getdate]"
		    lappend to_history "error start_tools: $message"
		    set sample_control_table($i,status) not_started
		    set sample_control_table($i,pid) -1
		    continue
		}
		set sample_control_table($i,status) waiting_for_data
		set sample_control_table($i,pid) $jobnr
		lappend to_history "start tool \
                                    $header $tool_name \
                                    at [getdate] with jobid $jobnr"
	    } else {
		## the tool has no measurments to do
		## so do not start the tool
		set message "no need to start tool $header $tool_name \
                             [getdate]" 
		lappend to_history "error start_tools: $message"
		set sample_control_table($i,status) not_started
		set sample_control_table($i,pid) -1
		continue
	    }
	} 
    }
}

##
## insert name-strings in control_tables
## and set the status of tools 
## if a tool is sending its name send back to the tool
## the names of the hosts that shall be measured by the tool
##

proc insert_name {name} {
    global socket
    global user
    global sample_control_table
    global sample_control_count
    global to_history
    global to_socket
    
    if {$user($socket,name) != "unknown"} { 
	lappend to_socket "error name"
	return 
    }
    if {$name == ""} {
	lappend to_socket "error name"
	return
    }
    ## search the name in the tools list
    for {set i 0} {$i <= $sample_control_count} {incr i} {
	if {($sample_control_table($i,tool_name) == $name)} {
	    set found 0
	    if {($sample_control_table($i,status) == "waiting_for_data") \
		|| ($sample_control_table($i,status) == "not_started") } {
		    set sample_control_table($i,socket) $socket
		    set sample_control_table($i,status) running
		    set sample_control_table($i,time) [getdate]
		    ## confirm name command and send the actual measurement
		    ## variables
		    set res "ok var_data"
		    lappend res $sample_control_table($i,nodes)
		    lappend to_socket $res
		    lappend to_history "name $name inserted [getdate]"
		    set user($socket,name) $name
		    set found 1
		    return
		}
	    if {!$found} {
		lappend to_socket "ok close"
		return
	    }
	}
    }
    ## we have a normal user name
    set user($socket,name) $name
    lappend to_socket "ok name" 
    lappend to_history "name $name inserted [getdate]"
    return 
}

##
## proc creates an info-list of slaves_sockets, names, connections, tools and
## their machinenames etc.
##

proc info_list {arg} {
    global slave_list
    global sample_control_count
    global sample_control_table
    global to_socket
    global user
    global start_time

    if {($arg != "tools") && ($arg != "monitor")} { 
	lappend to_socket "error info failed"
	lappend to_history "error info failed at [getdate]"
	return
    }
    ## info about the measurement tools
    if {$arg == "tools"} {
	if {![info exists sample_control_count]} { set res "" }
	lappend res " "
	lappend res "CONFIGURATION of measurement AGENTS:"
	for {set i 0} {$i <= $sample_control_count} {incr i} {
	    lappend res "Measurement agent: $sample_control_table($i,header) \
                         Agents name: $sample_control_table($i,tool_name) \
                         state: $sample_control_table($i,status)"
	    if {[info exists sample_control_table($i,nodes)]} {
		lappend res "interfaces and variables measured by agent:"
		lappend res [format "%10s %15s %7s %15s" \
			     device variablenname periode variablenident]
		foreach elem $sample_control_table($i,nodes) {
		    set host [lindex $elem 0]
		    foreach var_elem [lindex $elem 1] {
			set varname [lindex $var_elem 0]
			set periode [lindex $var_elem 1]
			set tag     [lindex $var_elem 2] 
			lappend res [format "%10s %15s %7d %15s" \
                                    $host $varname $periode $tag]
		    }
		}
	    } else {
		lappend res "no variables to measure"
	    }
	}
	lappend res " "
	lappend to_socket [list result info $res]
	return
    }
    ## info request for monitor config and connections
    ## 
    lappend res " "
    lappend res "CONFIGURATION of MONITOR"
    foreach elem [write_monitor_config] {
	lappend res $elem
    }
    lappend res " "
    lappend res "CONNECTIONS to MONITOR"
    lappend res "  machine    user               on since"
    foreach slave $slave_list {
	set ip [lindex [tcp info $slave] 2]
	if {[catch {nslook $ip} machine_name]} {
	    set machine_name "unknown"
	}
	set machine_name [lindex $machine_name 0]
	if {![info exists user($slave,name)]} {
	    set name unknown
	} else 	{
	    set name $user($slave,name)
	}
	if {![info exists user($slave,datum)]} {
	    set datum unknown
	} else 	{
	    set datum $user($slave,datum)
	}
	lappend res [format "%10s  %16s  %20s" \
			$machine_name $name $datum]
    }
    lappend res " "
    lappend to_socket [list result info $res]  
}

##
## proc writes all global variables to socket, special info-list about all 
## important variables of the tool
##

proc write_monitor_config {} {
    global server_port
    
    global slave_list 
    global user
    global socket
    
    global sample_control_table
    global sample_control_count
    global variable_control_table
    global variable_control_count
    global node_table
    global node_count
    global limit_tags_list
    global tag_count
    global variable_send_table
    global variable_send_count
    global trouble_result
    
    global history_file
    global config_file
    global variable_file
    global file_names_file
    global header_file
    global data_file
    
    global to_history
    global to_socket
    global file_names
    
    if {[info exists server_port]} {
	lappend res "port: $server_port"
    } 
    if {[info exists start_time]} {
	lappend res "starttime: $start_time"
    }
    if {[info exists slave_list]} {
	lappend res "current number of connections: [llength $slave_list]"
    }
    if {[info exists sample_control_count]} {
	set count 0
	for {set i 0} {$i <= $sample_control_count} {incr i} {
	    if {$sample_control_table($i,status) == "running"} {
		set count [expr {$count + 1}]
	    }
	}
	lappend res "current running measurement agents: $count"
    } 
    if {[info exists variable_control_count]} {
	lappend res "current known variables:\
                     [expr {$variable_control_count + 1}]"
    }
    if {[info exists node_count]} {
	lappend res "current measurement interfaces:\
                     [expr {$node_count + 1}]"
    }
    if {[info exists tag_count]} {
	lappend res "current measurement variables:\
                     [expr {$tag_count + 1}]"
    }
    if {[info exists limit_tags_list]} {
	lappend res "number of variables with limit control:\
                     [llength $limit_tags_list]"
    } else {
	lappend res "number of variables with limit control: none"
    }
    if {[info exists variable_send_count]} {
	set count 0
	for {set i 0} {$i <= $variable_send_count} {incr i} {
	    set count [expr {$count + [llength $variable_send_table($i,tag)]}]
	}
	lappend res "request for current data: $count"
	lappend res "request for current data from\
                     [expr {$variable_send_count + 1}] user."
    } else {
	lappend res "request for current data: none"
    }
    if {[info exists trouble_result]} {
	lappend res "number of not sent data to data_file:\
                     [llength $trouble_result]"
    } else {
	lappend res "number of not sent data to data_file: 0"
    }
    return $res
}

##
## proc writes to every connected socket a message, but not to the
## measurement tools 
## this can be used in interactive mode to send messages to the connected users
##

proc send_message {option message} {
    global sample_control_table
    global sample_control_count
    global slave_list
    global user
    global to_history
    global to_socket
    global socket
    
    if {$message == ""} { 
	## nothing has to be sent
	lappend to_history "message call without message"
	lappend to_socket "ok message"
	return
    }
    if {($option != "all") && ($option != "server")} {
	## options are wrong 
	lappend to_socket "error send_message failed"
	lappend to_history "error: send_message $option message from\
                            $socket failed [getdate]"
	return
    }
    lappend result_message $message
    ## send a broadcast message to all connections
    if {$option == "all"} {
	foreach slave $slave_list {
	    if {$slave == $socket} { continue }
	    if {[info exists user($slave,name)]} {
		## search the other names for tools
		## tools do not get any messages
		for {set i 0} {$i <= $sample_control_count} {incr i} {
		    if {$user($slave,name) == \
                                     $sample_control_table($i,tool_name)} {
			set found 1
			break
		    }
		}
		if {[info exists found]} { 
		    catch {unset found}
		    continue
		}
		set name $user($slave,name)
	    } else {
		set name unknown
	    }
	    catch {puts $slave "result message $result_message";flush $slave}
	    lappend to_history "broadcast message to $name:\
                                $result_message at [getdate]"
	}
    } else { 
	## message is only adressed to the server
	lappend to_history "message from $socket at [getdate] $result_message"
    }
    lappend to_socket "ok message"
}

##
## closes a/some connection to user or tools
##

proc close_connection {list_slaves arg} {
    global socket
    global to_socket
    global to_history
    global sample_control_count
    global sample_control_table 
    global slave_list
    global user
    
    
    if {$list_slaves == ""} { return }
    if {$arg == ""} { 
	lappend to_socket "error close {no arguments}"
	return
    }
    if {(($arg != "tools") && ($arg != "slave"))} {
	lappend to_socket "error close {wrong arguments}"
	return	
    } 
    ## we must search the toolhandles in the slavelist
    ## so get the slave_list
    if {$arg == "tools"} {
	set list_slaves $slave_list
	lappend to_history "cmd to kill agents from $user($socket,name)\
                          [getdate]"
	set close_tools 0
    }
    ## try to close the connection to all requested tools
    foreach slave $list_slaves {   

	set start_time [getdate]

	if {![info exists user($slave,name)]} {
	    set name "unknown"
	} else {
	    set name $user($slave,name)
	}
	## we must close connections of tools ??
	if {$arg == "tools"} {
	    ## correct call of close_connect for tools
	    for {set i 0} {$i <= $sample_control_count} {incr i} {
		if {$name == $sample_control_table($i,tool_name)} {
		    set found 1
		    set close_tools 1
		    reset_tool $slave norestart
		    lappend to_socket "ok close_tools"
		    break
		}
	    }
	    if {![info exists found]} { continue }
	    catch {unset found}
	} else {
	    ## command was invoked by the daemon, because of an unexpected
	    ## mistake with the connection to a tool
	    for {set i 0} {$i <= $sample_control_count} {incr i} {
		if {$name == $sample_control_table($i,tool_name)} {
		    reset_tool $slave restart
		    lappend to_history "$slave reset at [getdate]"
		    return
		}
	    }
	}
	lappend to_history "connection closed to $name $slave at $start_time"
	catch {puts $slave "ok close"; flush $slave}
	set slave_list [ldelete slave_list $slave]
	catch {removeinput $slave}
	catch {tcp shutdown $slave all}
	catch {tcp close $slave}
	catch {unset user($slave,name); unset user($slave,datum)}
	catch {unset slave}
    }
    if {$arg != "tools"} {
	set socket ""
    } else {
	if {!$close_tools} {
	    lappend to_socket "error close {no agents}"
	}
    }
}
    
##
## proc resets a tool after we can not read or write to tool or
## if we want to close a tool, to reset the variables
##

proc reset_tool {socket restart} {
    global user
    global slave_list
    global sample_control_table
    global sample_control_count
    
    if {[info exists sample_control_count]} {
	for {set i 0} {$i <= $sample_control_count} {incr i} {
	    if {![info exists sample_control_table($i,socket)]} { continue } 
	    set tool_socket $sample_control_table($i,socket)
	    if {$tool_socket == $socket} {
		catch {unset user($socket,name)}
		catch {unset user($socket,datum)}
		catch {unset sample_control_table($i,socket)}
		catch {unset sample_control_table($i,time)}
		catch {unset sample_control_table($i,pid)}
		if {$restart == "restart"} {
		    set sample_control_table($i,status) waiting_for_ok
		} else {
		    set sample_control_table($i,status) waiting_for_data
		}
		set slave_list [ldelete slave_list $socket]
		catch {removeinput $socket}
		break
	    }
	}
	if {$restart == "restart"} {
	    start_tools
	}
    }
}
    
##
## try to shutdown and kill monitor
##

proc kill_monitor {socket} {
    global slave_list
    global user
    global control_socket
    global to_socket
    global to_history
    
    if {$socket != ""} {
	if {![info exists user($socket,name)]} {
	    set name "unknown"
	} else {
	    set name $user($socket,name)
	}
	lappend to_history "incoming kill request from slave $name [getdate]"
	if {[llength $slave_list] > 1} {
	    lappend to_socket "error kill"
	    lappend to_history "kill request from slave failed"
	    return   
	}
	if {[lsearch $slave_list $socket] == -1} {
	    lappend to_socket "error kill"
	    lappend to_history "$socket not allowed to kill monitor"
	    return
	}
	catch {puts $socket "ok kill"; flush $socket}
	lappend to_history "request to kill monitor accepted"
    }
    close_connection $socket slave
    catch {removeinput $control_socket}
    catch {unset control_socket}
    set slave_list ""
    set to_socket ""
    write_history
    exit
}

##
##
## procedures to handle the configuration when starting the controllserver
## and tools
##
##

##
## reads the congfig_file and call other scripts
## check if the configurationfiles are existing
## call then the procedures to read the configuration
##

proc read_config {} {
    global to_history
    global config_file
    global variable_file 
    
    if {![file exists $variable_file]} {
	lappend to_history "$variable_file not found"
	write_history
	exit
    }
    if {![file exists $config_file]} {
	lappend to_history "$config_file not found"
	write_history
	exit
    }
    read_variable_file
    control_tables 
    sort_control_tables [read_config_file]
    create_header_file
}

##
## parse a list of variables and insert them into a list
## read the variables of .variables
##

proc read_variable_file {} {
    global variable_file
    global variable_control_table
    global variable_control_count
    global to_history

    set line_count 0
    if {[catch {open $variable_file r} filehandle]} {
	lappend to_history "$variable_file not found"
	write_history
	exit
    }
    catch {set line [string trimleft [gets $filehandle]]}
    incr line_count
    while {![eof $filehandle]} {
	if {(($line != "") && ([string index $line 0] != "\#"))} {
	    if {[llength $line] < 6} {
		lappend to_history "error: syntax error in\
                                        $variable_file line $line_count"
	    } else {
		if {![info exists variable_control_count]} {
		    set variable_control_count 0
		} else {
		    incr variable_control_count 
		} 
		set var_name  [lindex $line 0]
		set measure   [lindex $line 1]
		set bw_sort   [lindex $line 2]
		set procedure [lindex $line 3]
		set tool      [lindex $line 4]
		set tool_name [lindex $line 5]
		set variable_control_table($variable_control_count,name) \
		    $var_name
		set variable_control_table($variable_control_count,measure) \
		    $measure
		set variable_control_table($variable_control_count,bw-sort) \
		    $bw_sort 
		set variable_control_table($variable_control_count,procedure) \
		    $procedure
		set variable_control_table($variable_control_count,tool) \
		    $tool
		set variable_control_table($variable_control_count,tool_name) \
		    $tool_name
	    }
	}
	catch {gets $filehandle line}
	incr line_count
    }
    catch {close $filehandle}
    if {![info exists variable_control_count]} {
	lappend to_history "error: syntax error in $variable_file"
	write_history
	exit
    }
}

##
## read the interface config data and return it 
##

proc read_config_file {} {
    global to_history
    global config_file  
    
    set line_count 0
    if {[catch {open $config_file r} filehandle]} {
	lappend to_history "$config_file not found"
	write_history
	exit
    }
    catch {set line [string trimleft [gets $filehandle]]}
    incr line_count
    while {![eof $filehandle]} {
	if {(($line != "") && ([string index $line 0] != "\#"))} {
	    if {([llength $line] != 4)} {
		lappend to_history "error: syntax error in\
                                        $config_file in line $line_count"
	    } else {
		lappend interface_data $line
	    }
	}
	catch {gets $filehandle line}
	incr line_count
    }
    catch {close $filehandle}
    if {![info exists interface_data]} {
	lappend to_history "error: syntax error in $config_file"
	write_history
	exit
    }
    return $interface_data
}

##
## proc sets the values of the control_tables
##

proc control_tables {} {
    global sample_control_table
    global sample_control_count
    global variable_control_table
    global variable_control_count
    
    set time [getdate]
    ## search in variable_table for the toolnames and insert them
    ## in sample_control_table
    ## if they do not exist
    for {set i 0} {$i <= $variable_control_count} {incr i} {
	set header    $variable_control_table($i,tool)
	set tool_name $variable_control_table($i,tool_name)
	if {![info exists sample_control_count]} {
	    set sample_control_count 0
	    set sample_control_table($sample_control_count,header) $header
	    set sample_control_table($sample_control_count,tool_name) \
				     $tool_name
	    set sample_control_table($sample_control_count,time) $time
	    set sample_control_table($sample_control_count,status) \
                                                            waiting_for_ok
	    set variable_control_table($i,sample_control_id) 0
	    continue
	} else {
	    for {set j 0} {$j <= $sample_control_count} {incr j} {
		set tool $variable_control_table($i,tool)
		set tool_name $variable_control_table($i,tool_name) 
		if {$sample_control_table($j,tool_name) == $tool_name} {
		    set found 1
		    break
		} else {
		    set found 0
		}
	    }
	    if {!$found} {
		incr sample_control_count
		set sample_control_table($sample_control_count,header) $header
		set sample_control_table($sample_control_count,tool_name) \
					 $tool_name
		set sample_control_table($sample_control_count,time) $time
		set sample_control_table($sample_control_count,status) \
                                                             waiting_for_ok
		set j $sample_control_count
	    }
	}
	set variable_control_table($i,sample_control_id) $j
    }
}

##
## parse a list of nodes for reachability and create a structure for all nodes
## and their variables
##

proc parse_nodes {list} {
    global to_history
    global node_table
    global node_count
    
    set res ""
    set found 0
    foreach elem $list {
	set found 0
	set host      [lindex $elem 0]
	set network   [lindex $elem 1]
	set prototype [lindex $elem 2]
	set variables [lindex $elem 3]
	if {[info exists node_count]} {
	    for {set i 0} {$i <= $node_count} {incr i} {
		if {$node_table($i,name) == $host} {
		    set found 1
		    break
		}
	    }
	}
	set ip $host
	if {[regexp "^\[0-9\]+\.\[0-9\]+\.\[0-9\]+\.\[0-9\]+$" $host] == 0} {
	    if {[catch {nslook $host} ip]==1} {
		set list [ldelete list $elem]
		if {$list == ""} {
		    lappend to_history "error parse_nodes: no interfaces \
                                        known by server"
		    write_history
		    exit
		}
		lappend to_history "error parse_nodes: do not know \
                                    node_ip_adress $elem"
		continue
	    }
	}
	if {$found} { 
	    foreach var_elem $variables {
		lappend node_table($i,vars) $var_elem 
	    }
	    continue 
	}
	if {![info exists node_count]} { 
	    set node_count 0
	} else {
	    incr node_count
	}
	set node_table($node_count,name) $host
	set node_table($node_count,network) $network
	set node_table($node_count,prototype) $prototype
	set node_table($node_count,ip) $ip
	set node_table($node_count,vars) $variables
	set node_table($node_count,time) [getdate]
    }
}

##
## proc arrange the variable_table, sample_control_table and the interface_data
##

proc sort_control_tables {interface_data} {
    global sample_control_table
    global sample_control_count
    global tag_count 
    global variable_control_table
    global variable_control_count
    global limit_tags_list
    global limits
    global node_table
    global node_count
    global to_history

    ## check all values, get ip etc. 
    parse_nodes $interface_data
    ## search the toolname for the variables in node_table
    ## and insert the variables and hostname in sample_control_table
    for {set i 0} {$i <= $node_count} {incr i} {
	set host $node_table($i,name)
	set ip   $node_table($i,ip)
	## get varname
	foreach elem $node_table($i,vars) {
	    set found 0
	    ## check var_name and var_periode for consistency
	    ## if periode is a number and var_name is a known variable
	    set var_name    [lindex [split [lindex $elem 0] .] 0]
	    set var_periode [lindex $elem 1]
	    ## check if periode is a multiple of 60 and a number
	    if {(![isnumber $var_periode]) || \
               ([expr {$var_periode % 60}] != "0") || ($var_periode <= "0")}  {
		lappend to_history "error: $host $elem periode var_periode \
                                    is no number or a multiple of 60"
		set node_table($i,vars) [ldelete node_table($i,vars) $elem]
		continue
	    } 
	    ##
	    ## check if we must control limits
	    ## insert them in limit structures
	    ##
	    if {[llength $elem] == 3} {
		set limit_values [lindex $elem 2]
		set limit_found 0
		## wrong number of arguments
		if {[llength $limit_values] == 3} {
		    set limit_value [lindex $limit_values 0]
		    set hyst_value  [lindex $limit_values 1]
		    set limit_count  [lindex $limit_values 2]
		    ## check if values are digits
		    ## we don not check if the limitvalue is greater than the
		    ## hystvalue because this is one responsibility
		    if {([isnumber $limit_value]) && ($limit_value > "0")} {
			if {([isnumber $limit_count]) && \
                            ($limit_count >= "0")} {
			    if {(([isnumber $limit_value]) && \
                                ($limit_value > "0") && 
				([isnumber $hyst_value]) && \
                                ($hyst_value > "0"))} {
				set limit_found 1
			    }
			}
		    }
		    
		}
	    }
	    
	    for {set j 0} {$j <= $variable_control_count} {incr j} {
		## get sample_control_id
		## and set the tag_id for the host_variable
		if {$variable_control_table($j,name) == $var_name} {
		    ## read the corresponding id from sample_control_table
		    set sample_id $variable_control_table($j,sample_control_id)
		    ## read the corresponding measure-procedure of the variable
		    set proc_name $variable_control_table($j,procedure)
		    ## set tag_count and tag of each variable and host
		    if {![info exists tag_count]} {
			set tag_count 0
		    } else {
			incr tag_count
		    }
		    set tag var_id.$tag_count

		    lappend variable_control_table($j,tags) $tag
		    set node_table($i,vars) [ldelete node_table($i,vars) $elem]

		    ## append tag, if we have limits, to limit_list
		    ## and set pointer to the other control_tables
		    if {[info exists limit_found]} {
			if {$limit_found} {
			    lappend limit_tags_list      $tag
			    set limits($tag,value)       $limit_value
			    set limits($tag,hyst_value)  $hyst_value
			    set limits($tag,alarm_count) $limit_count
			    set limits($tag,count)       $limit_count
			    set limits($tag,sample)      $sample_id
			    set limits($tag,name)        [lindex $elem 0]
			    set limits($tag,node)        $i
			    set limits($tag,exceed)      ""
			    set limits($tag,warn)        0
			    set elem [ldelete elem $limit_values]
			} else {
			    lappend to_history "error: $elem limit_value is\
                                                no number or < 0"
			}
			catch {unset limit_found}
		    }
		    ## append the new variables description also to the 
		    ## node_table
		    lappend elem $tag
		    ## append the measure-proc-name to the node_table 
		    lappend elem $proc_name

		    lappend node_table($i,vars) $elem
		    ## set sample_control_table
		    lappend sample_control_table($sample_id,nodes)\
                            "$host [list $elem] $ip"
		    set found 1
		    break
                } 
	    }
	    ## variable is not defined in .variable_file
	    if {!$found} {
		lappend to_history "error: variable not found"
		set node_table($i,vars) [ldelete node_table($i,vars) $elem]
	    }
	}
    }
    ## sort all variables and hosts of one toolinscription of
    ## sample_control_table
    ## and create a list with one hostname and all corresponding varnames to 
    ## that host
    unset j
    for {set i 0} {$i <= $sample_control_count} {incr i} {
	## go through all tools
	if {![info exists sample_control_table($i,nodes)]} { 
	    set sample_control_table($i,status) not_running
	    continue 
	}
	## take all host, until here they have only one variable in their list
	## example: {host1 {var0}} {host1 {var1}} {host2 {var0}}
	## after sorting:
	## example: {host1 {{var0} {var1}}} {host2 {{var0}}}
	foreach elem $sample_control_table($i,nodes) {
	    set host [lindex $elem 0]
	    set vars [lindex $elem 1]
	    set ip   [lindex $elem 2]
	    set found 0
	    if {![info exists j]} {set j 0}
	    ## set first element
	    if {![info exists res($j,name)]} {
		set res($j,name) $host
		lappend res($j,vars) $vars
		set res($j,ip) $ip
	    } else {
		## is there already an host in res
		for {set k 0} {$k <= $j} {incr k} {
		    ## if so, append the variable to the other
		    if {$res($k,name) == $host} {
			set found 1
			lappend res($k,vars) $vars
			break
		    }
		}
		## if not, create a new entry
		if {!$found} {
		    incr j
		    set res($j,name) $host
		    lappend res($j,vars) $vars
		    set res($j,ip) $ip
		}
	    }
	}
	## create a list of all elements of the res array
	for {set k 0} {$k <= $j} {incr k} {
	    lappend res1 $res($k,vars)
	    lappend result "$res($k,name) $res1 $res($k,ip)"
	    unset res($k,name)
	    unset res($k,vars)
	    unset res($k,ip)
	    set res1 ""
	}
	set sample_control_table($i,nodes) ""
	set sample_control_table($i,nodes) $result
	set result ""
	unset j
    }
}

##
## procedures to handle the data transfers from measurementtools to server
## 
##
##

##
## prepare data from tools for calculating
## this is the minprocedure for collecting the data
## the procedure checks if it must call the aggregationtool, it checks if
## the collected data is in the right interval
## it calls the other procedures to check limits and so on
##

proc prepare_data {cmd_add data_list} {
    global sample_control_table
    global sample_control_count
    global sample_control_timestamp
    global variable_send_table
    global variable_send_count
    global limit_tags_list
    global limits
    global trouble_result
    global user
    global socket
    global to_socket
    global to_history
    
    if {![info exists user($socket,name)]} {
	lappend to_history "error prepare_data: unknown user is \
                            transfering data [getdate]"
	lappend to_socket  "error {you do not have access to this command}"
	return
    }

    for {set i 0} {$i <= $sample_control_count} {incr i} {
	if {$user($socket,name) == $sample_control_table($i,tool_name)} { 
	    set found 1	
	    break
	}
    }
    if {![info exists found]} {
	set message "unknown user $user($socket,name) is \
                     transfering data [getdate]"
	lappend to_history "error prepare_data: $message"
	lappend to_socket  "error {you do not have access to this command}"
	return
    }
    catch {unset found}

    if {$cmd_add != "values"} {
	set dat "$user($socket,name) [getdate]" 
	lappend to_history "prepare data request with wrong arguments \
                            from $dat"
	lappend to_socket "error data {wrong arguments}"
	return
    }
    ## compare, if there is a new day 
    ## if yes, set new filenames
    set len [llength $data_list]
    set timestamp [lindex $data_list [expr {$len - 1}]]

    set data_list [ldelete data_list $timestamp]

    set hh [lindex [split [lindex $timestamp 3] :] 0]
    set min  [lindex [split [lindex $timestamp 3] :] 1]
    set data_time [lindex [split [expr {[expr {$hh * 3600}] + \
                                                  [expr {$min * 60}]}] .] 0]
    
    ## set synchro variable for write_raw_data
    ## and call the write-procedures, the limitsend-procedures and
    ## the datasend-procedure
    ## the after command is used to wait for data sended by other tools
    if {$data_time > [lindex $sample_control_timestamp 0]} {
	## the first tool is sending data
    	set sample_control_timestamp "$data_time"
	lappend sample_control_timestamp $timestamp
        after 30000 write_raw_data
	after 30000 send_raw_data
	after 30000 send_limit_data
    } else {
	if {$data_time < [lindex $sample_control_timestamp 0]} { 
	    if {$hh == "00"} {
		## do we have midnight ??
		## test if we are changing the day
		set old_time [lindex $sample_control_timestamp 1]
		set old_hh [lindex [split [lindex $old_time 3] :] 0]
		lappend to_history "testing in prepare data: changing \ 
                                    the day?? [getdate]"
		if {$old_hh == "23"} {
		    ## we are changing the day
		    lappend to_history "we are changing the day!! [getdate]"
		    set sample_control_timestamp "$data_time"
		    lappend sample_control_timestamp $timestamp
		    after 30000 write_raw_data
		    after 30000 send_raw_data
		    after 30000 send_limit_data
		}
	    }
	}
    }
    ## only if we are in the same intervall, append results to control_table
    if {$data_time == [lindex $sample_control_timestamp 0]} { 
	for {set i 0} {$i <= $sample_control_count} {incr i} {
	    if {[info exists sample_control_table($i,socket)]} {
		if {$sample_control_table($i,socket) != $socket} { continue }
		set sample_control_table($i,res) $data_list
		set sample_control_table($i,timestamp) $data_time
	    }
	}
    }
    ## check, if we have limits to control
    ## check if we must send data to other sockets
    if {[info exists variable_send_count] || [info exists limit_tags_list]} {
	set send  0
	set limit 0
	if {[info exists variable_send_count]} { set send 1 }
	if {[info exists limit_tags_list]} { set limit 1 }
	foreach elem $data_list {
	    set var_tag [lindex $elem 0]
	    if {$limit} {
		if {[lsearch $limit_tags_list $var_tag] != -1} {
		    prepare_limit $elem $timestamp
		}
	    }
	    if {$send} {
		for {set i 0} {$i <= $variable_send_count} {incr i} {
		    set found [lsearch $variable_send_table($i,tag) $var_tag]
		    if {$found == -1} {continue}
		    lappend variable_send_table($i,res) $elem
		}
	    }
	}
    }
}

##
## proc compares the measured values with the limit values
## and creates an alarm if necessary
##

proc prepare_limit {elem timestamp} {
    global limit_tags_list
    global limits
    global limit_file
    global node_table
    global to_history
    
    set tag   [lindex $elem 0]
    set value [lindex $elem 1]

    if {!$limits($tag,warn)} {
	## we have not send an alarm for this tag
	if {$value < $limits($tag,value)} {
	    ## check if we can reset the values 
	    if {$value > $limits($tag,hyst_value)} { return }
	    #3 yes reset the values
	    set limits($tag,alarm_count) $limits($tag,count)
	    set limits($tag,exceed) ""
	    return 
	}
	## a limitvalue is exceeded
	#$ set the values
	incr limits($tag,alarm_count) -1
	set limits($tag,exceed) [list $timestamp $value]
	if {$limits($tag,alarm_count) <= 0} {
	    ## the limitwarnperiode is reached
	    ## send a message to syslog
	    ## create an entry in the sendlimitlist
	    set limits($tag,warn) 1
	    set limits($tag,alarm_count) $limits($tag,count)
	    set host     $node_table($limits($tag,node),name) 
	    set var_name $limits($tag,name)
	    
	    set message "LIMIT OVERFLOW: $host $var_name reached: \
                        $value $timestamp " 
	    syslog LOG_DEBUG $message
	    if {[catch {open $limit_file a} filehandle]} {
		lappend to_history "error write_limit_data: $filehandle"
		return
	    }
	    set message "$timestamp $tag critical: $limits($tag,value) \
                             reached: $value periode: $limits($tag,count)"
	    catch {puts $filehandle $message; flush $filehandle}
	    catch {close $filehandle}
	}
    } else {
	## we have send an alarm for this variable
	## check if we can reset the values
	if {$value > $limits($tag,hyst_value)} { return }
	## reset the values
	set limits($tag,alarm_count) $limits($tag,count)
	set limits($tag,warn) 0
	set limits($tag,exceed) ""
	
	set host     $node_table($limits($tag,node),name) 
	set var_name $limits($tag,name)

	set message "LIMIT UNCRITICAL: $host $var_name reached:\
                     $value $timestamp " 
	syslog LOG_DEBUG $message
	if {[catch {open $limit_file a} filehandle]} {
	    lappend to_history "error write_limit_data: $filehandle"
	    return
	}
	set message "$timestamp $tag uncritical: $limits($tag,hyst_value)\
                             reached: $value"
	catch {puts $filehandle $message; flush $filehandle}
	catch {close $filehandle}
    }
    return
}

##
## proc sends raw_data to requesting sockets
##

proc send_raw_data {} {
    global sample_control_timestamp
    global variable_send_table
    global variable_send_count
    global to_history
       
    if {![info exists sample_control_timestamp]} { return }
    set timestamp [lindex $sample_control_timestamp 1]
    ## check if we must send data to other sockets
    if {[info exists variable_send_count]} {
	for {set i 0} {$i <= $variable_send_count} {incr i} {
	    set result "result data_tag_now"
	    lappend res $timestamp 
	    if {[info exists variable_send_table($i,res)]} { 
		lappend res $variable_send_table($i,res)
		unset variable_send_table($i,res)
	    } 
	    lappend result $res
	    if {[llength $res] > 1} {
		set socket $variable_send_table($i,socket)
		if {[catch {puts $socket $result; flush $socket} result]} {
		    set message "can not send data $socket [getdate]"
		    lappend to_history "error prepare: $message"
		    reset_send_table $variable_send_table($i,socket) all ""
		    catch {close_connection $socket slave}
		}
	    }
	    set res "" 
	    if {![info exists variable_send_count]} {
		break
	    }
	}
    }
}

##
## proc writes data to the rawdata file
##

proc write_raw_data {} {
    global sample_control_table
    global sample_control_count
    global sample_control_timestamp
    global data_file
    global write_data_error
    global trouble_result

    if {![info exists sample_control_timestamp]} {
    	return
    }
    for {set i 0} {$i <= $sample_control_count} {incr i} {
        if {![info exists sample_control_table($i,res)]} { continue }
        if {[lindex $sample_control_timestamp 0] == \
                                       $sample_control_table($i,timestamp)} {
	    foreach elem $sample_control_table($i,res) {
		lappend res $elem
	    }
        }
        catch {unset sample_control_table($i,timestamp)}
        catch {unset sample_control_table($i,res)}
    }
    if {![info exists res]} { return }
    if {$res != ""} {
	lappend result [lindex $sample_control_timestamp 1]
	lappend result $res
	lappend trouble_result $result
    }
    ## now write data to datafile
    if {[catch {open $data_file a} filehandle]} {
	if {$write_data_error == 0} {
	    lappend to_history "error write_raw_data: $filehandle"
	}
	set write_data_error 1
    } else {
	foreach elem $trouble_result {
	    if {[catch {puts $filehandle $elem; flush $filehandle } error]} {
		lappend to_history "error write_raw_data: $error [getdate]"
		break
	    }
	    set trouble_result [ldelete trouble_result $elem]
	}
	set res ""
        catch {close $filehandle}
        set write_data_error 0
    }
}


##
## proc sends the limit data to involved sockets
##

proc send_limit_data {} {
    global limit_tags_list
    global limits
    global limit_send_sockets
    global limit_send_table 
    global to_history


    if {![info exists limit_tags_list]} { return }
    if {![info exists limit_send_sockets]} { return }
    foreach socket $limit_send_sockets {
	set res ""
	if {![info exists limit_send_table($socket,tags)]} { continue } 
	foreach tag $limit_send_table($socket,tags) {
	    if {![info exists limits($tag,exceed)]} { 
		catch {unset limit_send_table($socket,$tag,warn)}
		set limit_send_table($socket,tags) \
                             [ldelete limit_send_table($socket,tags) $tag] 
		continue 
	    }
	    if {!$limit_send_table($socket,$tag,warn)} { continue }
	    if {!$limits($tag,warn)} { continue } 
	    if {$limit_send_table($socket,$tag,alarm)} { continue }
	    lappend res "$tag $limits($tag,exceed)"
	    set limit_send_table($socket,$tag,alarm) 1 
	}
	if {$res == ""} { continue }
	set header [list result limit_request_now $res]
	if {[catch {puts $socket $header; flush $socket}]} {
	    set message "can not send data $socket [getdate]"
	    lappend to_history "error send_limit_data: $message"
	    foreach elem $limit_send_table($socket,tags) {
		catch {unset limit_send_table($socket,tags)}
		catch {unset limit_send_table($socket,$elem,warn)}
		catch {unset limit_send_table($socket,$elem,alarm)}
	    }
	    set limit_send_sockets [ldelete limit_send_sockets $socket] 
	    if {$limit_send_sockets != ""} { continue }
	    catch {unset limit_send_sockets}
	    return
	}
	set res ""	    
    }
}

##
## procedures concerning the statistic tools
## check times, create filenames, write data corresponding to the data-files
## set limits or write them to sockets
##
##
## prove if we have midnight, if so start statistic calulation
##

proc time_check {} {
    global file_names_file
    global file_names
    global to_history

    set timestamp [getdate]
    set day_secs 86400
    set hh [lindex [split [lindex $timestamp 3] :] 0]
    set min [lindex [split [lindex $timestamp 3] :] 1]
    set sec [lindex [split [lindex $timestamp 3] :] 2] 
    set secs [expr {($hh * 3600) + ($min * 60) + $sec}]
    if {([lindex [split [lindex $timestamp 3] :] 0] == "00") && \
	([lindex [split [lindex $timestamp 3] :] 1] <= "15")} {
	    if {[catch {exec rm $file_names_file} mess]} {
		lappend to_history "error time_check: can not \
                                    delete $file_names_file $mess"
	    }
	    if {[catch {open $file_names_file a} filehandle]} {
		lappend to_history "error time_check: can not open \
                                    $file_names_file"
	    }
	    catch {puts $filehandle $file_names; flush $filehandle}
	    catch {close $filehandle}
	    after 40000 set_file_name
	    after 40000 create_header_file
	    after 50000 start_statistic 
    }
    set wait_secs [expr {round(($day_secs - $secs) * 1000)}]
    lappend to_history "set waittime for timecheck to $wait_secs"
    after $wait_secs time_check
}

##
## proc starts the statistic tool
##

proc start_statistic {} {
    global to_history
    global start_dir
    
    lappend to_history "starting aggreg_netguard at [getdate]"
    if {[catch {exec aggreg_netguard $start_dir &} jobnr]} {
	lappend to_history "error start_statistic: can  not start \
                            aggreg_netguard $jobnr"
    } 
}

##
## set the file names for the label and data files
## 

proc set_file_name {} {
    global header_file
    global data_file
    global stat_file
    global to_history
    global orig_header_file
    global orig_data_file
    global orig_stat_file 
    global file_names

    set file_names ""
    set extension 0
    set start_time [getdate]
    set year_index [expr {[llength $start_time]} - 1]
    set day "[lindex $start_time $year_index].[lindex $start_time \
              1].[lindex $start_time 2]"
    set header_file "$orig_header_file$day"
    set data_file   "$orig_data_file$day"
    lappend file_names "$header_file $data_file"   
    if {[file exists $header_file]} {
	set header_file1 $header_file
	set data_file1   $data_file
	while {[file exists $header_file]} {
	    incr extension
	    set header_file "$header_file1-$extension"
	    set data_file   "$data_file1-$extension"
	    lappend file_names "$header_file $data_file"    
	}
    }
    if {$extension == 0} { 
	set stat_file "$orig_stat_file$day"
    } else {
	set stat_file "$orig_stat_file$day-$extension"
    }
    lappend to_history "set_file_name created new file names [getdate]"
}

##
## create the headers of the data_files
##

proc create_header_file {} {
    global node_table
    global node_count
    global header_file
    global data_file
    global stat_file
    global variable_control_count
    global variable_control_table
    global to_history
    
    if {![info exists node_table]} {
	return
    }
    if {[catch {open $header_file a} filehandle]} {
	lappend to_history "error create_header_file: while opening headerfile"
	write_history
	return
    }
    set time [getdate]
    puts $filehandle "BEGIN_LABEL_SECTION"
    puts $filehandle "\n  BEGIN_INTERVAL"
    puts $filehandle "    $time"
    puts $filehandle "  CORRESPONDING DATA-FILE"
    puts $filehandle "    $data_file"  
    puts $filehandle "  CORRESPONDING STATISTIC-FILE"
    puts $filehandle "    $stat_file"
    puts $filehandle "\nEND_LABEL_SECTION"
    puts $filehandle "\nBEGIN_DEVICE_SECTION"
    for {set i 0} {$i <= $node_count} {incr i} {
	puts $filehandle "  DEVICE          $node_table($i,name)"
	puts $filehandle "  PROTOTYPE       $node_table($node_count,prototype)"
	puts $filehandle "  PROTOTYPE-ADDRESS  $node_table($i,ip)"
	puts $filehandle "  CORRESPONDING_VARIABLES"
	puts $filehandle [format "    %12s %7s %11s %11s %7s" \
                      variablename periode internal_id measurement bw-sort]
	foreach varelem $node_table($i,vars) {
	    set varname [lindex $varelem 0]
	    set varperi [lindex $varelem 1]
	    set varid   [lindex $varelem 2]
	    for {set j 0} {$j <= $variable_control_count} {incr j} {
		if {$variable_control_table($j,name) == [lindex $varelem 0]} {
		    set var_meas $variable_control_table($j,measure)
		    set var_bw   $variable_control_table($j,bw-sort)
		    break
		}
	    }
	    puts $filehandle [format "    %12s %7s %11s %11s %7s" \
                    $varname $varperi $varid $var_meas $var_bw]
        }
    }
    puts $filehandle "END_DEVICE_SECTION"
    catch {close $filehandle}
}

##
## sends the header_file contents  of the current day or of n other day
##  specified in arg
##

proc send_config_data {arg} {
    global sample_control_table
    global sample_control_count
    global variable_send_table
    global variable_send_count 
    global socket
    global to_history
    global to_socket
 
    case $arg in {
	{now} {
	    set res ""
	    if {[info exists sample_control_count]} {
		## look inthe sample control table and send all nodes
		## inscriptions
		## to requesting socket
		for {set i 0} {$i <= $sample_control_count} {incr i} {
		    if {[info exists sample_control_table($i,nodes)]} {
			foreach elem $sample_control_table($i,nodes) {
			    lappend res $elem
			}
		    }
		}
	    } 
	    if {$res == ""} {
		set res no_config_now
	    }
	    set result "result data_info_now"
	    lappend result $res
	    lappend to_socket $result
	    return
	}
	{tag} {
	    set found 0
	    if {[info exists variable_send_count]} {
		for {set i 0} {$i <= $variable_send_count} {incr i} {
		    if {$variable_send_table($i,socket) == $socket} {
			set result "result data_info_tag"
			lappend result $variable_send_table($i,tag)
			lappend to_socket $result
			set found 1
			break
		    }
		}
	    }
	    if {!$found} {
		lappend to_socket "result data_info_tag no_tags"
	    }
	    return
	}
	{default} {
	    lappend to_socket "error data_info {arguments missing}"
	    return
	}
    }
}

##
## procedure insert a tag inscription into array
##

proc insert_tag {arg} {
    global variable_control_table
    global variable_control_count
    global variable_send_table
    global variable_send_count
    global tag_count
    global socket
    global to_socket
    
    if {$arg == ""} {
	lappend to_socket "error data_request {insert failed}"
	return
    }
    if {![info exists tag_count]} {
	lappend to_socket "error data_request {insert failed}"
	return
    }
    if {![info exists tag_count]} {
	lappend to_socket "error data_request {insert failed}"
	return
    }
    foreach elem $arg {
	set insert 0
	for {set i 0} {$i <= $variable_control_count} {incr i} {
	    if {![info exists variable_control_table($i,tags)]} { continue }
	    if {[lsearch $variable_control_table($i,tags) $elem] == -1} \
                        { continue }
	    if {[info exists variable_send_count]} {
		for {set j 0} {$j <= $variable_send_count} {incr j} {
		    if {$socket == $variable_send_table($j,socket)} {
			if {[lsearch $variable_send_table($j,tag) \
                             $elem] == -1} {
			    lappend variable_send_table($j,tag) $elem
			    set insert 1
			    break
			}  else {
			    set insert 1
			    break
			}
		    }
		} 
		if {!$insert} {
		    incr variable_send_count 
		    set variable_send_table($variable_send_count,socket) \
                        $socket
		    set variable_send_table($variable_send_count,tag) $elem
		    set insert 1
		}
	    } else {
		set insert 1
		set variable_send_count 0
		set variable_send_table($variable_send_count,socket) $socket
		set variable_send_table($variable_send_count,tag) $elem
	    }
	    lappend to_socket "ok data_request"
	    break
	}
	if {!$insert} {
	    set res "error data_request"
	    lappend res "insert tag $elem failed"
	    lappend to_socket $res
	}
    }
}

##
## deletes a tag entry in variable_send_table
##

proc delete_tag {arg} {
    global variable_send_count
    global socket
    global to_socket

    if {![info exists variable_send_count]} { 
	lappend to_socket "error data_request {delete failed}"
	return
    }
    if {$arg == ""} {
	lappend to_socket "error data_request {delete failed}"
	return
    }
    if {![reset_send_table $socket tags $arg]} {
	lappend to_socket "error data_request {delete failed}"
    } else {
	lappend to_socket "ok data_request"
    }
}

##
##
##

proc clear_send_table {} {
    global variable_send_count
    global socket
    global to_socket

    if {![info exists variable_send_count]} { 
	lappend to_socket "error data_request {reset failed}"
	return
    }
    if {![reset_send_table $socket all ""]} {
	lappend to_socket "error data_request {reset failed}"
    } else {
	lappend to_socket "ok data_request"
    }
}

##
## proc sets variable_send_table
##

proc reset_send_table {socket option tag_arg} {
    global variable_send_table
    global variable_send_count
    global to_history
    
    set res 0
    if {![info exists variable_send_count]} { return $res }
    if {($option != "all") && ($option != "tags")} { return $res }
    for {set i 0} {$i <= $variable_send_count} {incr i} {
	if {![info exists variable_send_table($i,socket)]} { continue }
	if {$socket != $variable_send_table($i,socket)} { continue }
	if {$i == $variable_send_count} {
	    if {$option == "tags"} {
		foreach tag_elem $tag_arg {
		    foreach tag_table_elem $variable_send_table($i,tag) {
			if {$tag_elem == $tag_table_elem} {
			    set res 1
			    set tmp [ldelete variable_send_table($i,tag) \
                                     $tag_elem]
			    set variable_send_table($i,tag) $tmp
			} 
		    }
		}
		set len [llength $variable_send_table($i,tag)]
		if {$len != 0} { break }
	    }
	    catch {unset variable_send_table($i,res)}
	    catch {unset variable_send_table($i,socket)}
	    catch {unset variable_send_table($i,tag)}
	    if {$variable_send_count != 0} {
		set variable_send_count [expr {$variable_send_count - 1}]
	    } else {
		catch {unset variable_send_count}
	    }
	} else {
	    if {$option == "tags"} {
		foreach tag_elem $tag_arg {
		    foreach tag_table_elem $variable_send_table($i,tag) {
			if {$tag_elem == $tag_table_elem} {
			    set tmp [ldelete variable_send_table($i,tag) \
                                    $tag_elem] 
			    set variable_send_table($i,tag) $tmp
			} 
		    }
		}
		set len [llength $variable_send_table($i,tag)]
		if {$len != 0} { set res 1; break }
	    }
	    catch {set variable_send_table($i,res) \
                   $variable_send_table($variable_send_count,res)}
	    set variable_send_table($i,socket) \
                $variable_send_table($variable_send_count,socket)
	    set variable_send_table($i,tag) \
                $variable_send_table($variable_send_count,tag)
	    catch {unset variable_send_table($variable_send_count,res)}
	    catch {unset variable_send_table($variable_send_count,socket)}
	    catch {unset variable_send_table($variable_send_count,tag)}
	    set variable_send_count [expr {$variable_send_count - 1}]
	    set res 1
	}	
	if {$option == "all"} { set res 1 }
	break
    }
    return $res
} 

##
## proc reads the directory of the headerfiles and the contents of the
##  headerfiles for later data requests
##

proc read_old_configs {time} {
    global to_history
    global to_socket
    global data_dir

    if {[catch {glob -nocomplain $data_dir/*} directory]} {
	lappend to_history "error read_old_configs: $directory [getdate]"
	lappend to_socket "error data_old_tag {read_old_configs failed}"
	return
    }
    set header_filename     "header-file-$time"
    set header_filename_ext "header-file-$time-"
    foreach file_name $directory {
	set file_name [file tail $file_name]
	## filter the first filenamecontent
	if {($file_name == $header_filename) || \
            ([string first $header_filename_ext $file_name] != -1)} {
	    lappend old_header_files $file_name
	}
    }
    if {![info exists old_header_files]} {
	lappend to_history "read_old_configs do not find any header-files"
	lappend to_socket "error data_old_tag {read_old_configs failed}"
	return	
    }
    set result [read_header_data $old_header_files]
    if {$result == ""} {
	lappend to_socket "error data_old_tag {read_old_configs failed}"
	lappend to_history "error: read_old_configs no header files found"
	return
    }
    set res_mess "result data_info_old"
    lappend res_mess $result
    lappend to_socket $res_mess
}

##
## proc reads values from header_files
##

proc read_header_data {headerfilenames} {
    global data_dir

    foreach filename $headerfilenames {
	set filename "$data_dir/$filename"
	if {[catch {open $filename r} filehandle]} {
	    lappend to_history "error: $filehandle"
	    return 
	}
	if {[catch {gets $filehandle} line]} {
	    catch {close $filehandle}
	    lappend to_history "error: $line"
	    return 
	}
	
	set day [lindex [split [string trimleft $filename] -] 2]
	set ext "-[lindex [split [string trimleft $filename] -] 3]"
	
	if {$ext == "-"} {
	    set ext ""
	}
	set data_file_ext "$day$ext"
	while {![eof $filehandle]} {
	    if {[lindex $line 0] == "DEVICE"} {
		set host [lindex $line 1]
	    }
	    if {[lindex $line 0] == "BEGIN_INTERVAL"} {
		if {[catch {gets $filehandle} line]} {
		    catch {close $filehandle}
		    lappend to_history "error: $line"
		    return
		}
		set interval_start [string trimleft $line]
	    }
	    if {[catch {gets $filehandle} line]} {
		catch {close $filehandle}
		lappend to_history "error: $line"
		return
	    }
	    if {[lindex $line 0] == "variablename"} {
		if {[catch {gets $filehandle} line]} {
		    catch {close $filehandle}
		    lappend to_history "error: $line"
		    return
		}
		while {(![eof $filehandle]) && ([lindex $line 0] != "DEVICE") \
		       && ([lindex $line 0] != "END_DEVICE_SECTION") } {
			set found 0
			if {$line != ""} {
			    set var_name [lindex $line 0]
			    set periode  [lindex $line 1]
			    set var_id   [lindex $line 2]
			    
			    if {![info exists old_variable_count]} {
				set old_variable_count 0
			    } else {
				## search in existing contents of table for
				## inscription with
				## the same var_name and var_id
				if {$filename != [lindex $headerfilenames 0]} {
				    for {set i 0} {$i <= \
                                         $old_variable_count} {incr i} {
					set host1  \
                                               $old_variable_table($i,host)
					set var_name1 \
                                               $old_variable_table($i,var_name)
					set var_id1 \
                                               $old_variable_table($i,var_id)
					set periode1 \
                                               $old_variable_table($i,periode)
					if {($host1 == $host) && \
                                            ($var_name1 == $var_name) && \
					    ($var_id1 == $var_id) && \
                                            ($periode1 == $periode)} {
		lappend old_variable_table($i,starttime) $interval_start
		lappend old_variable_table($i,data_file_ext) $data_file_ext
						set found 1
						break
					    }
				    }
				}
				if {!$found} {
				    incr old_variable_count
				}
			    }
			    
			    if {!$found} {
				set j $old_variable_count
				set old_variable_table($j,host)     $host
				set old_variable_table($j,var_name) $var_name
				set old_variable_table($j,var_id)   $var_id
		lappend old_variable_table($j,starttime) $interval_start
		                set old_variable_table($j,periode)  $periode
		set old_variable_table($j,data_file_ext) $data_file_ext
				unset j
			    }
			}
			if {[catch {gets $filehandle} line]} {
			    catch {close $filehandle}
			    lappend to_history "error: $line"
			    return
			}
		    }
	    }
	}
	catch {close $filehandle}
    }
    for {set i 0} {$i <= $old_variable_count} {incr i} {
	set res $old_variable_table($i,host)
	lappend res $old_variable_table($i,var_name)
	lappend res $old_variable_table($i,var_id)
	lappend res $old_variable_table($i,periode)
	lappend res $old_variable_table($i,starttime)
	lappend res $old_variable_table($i,data_file_ext)
	lappend result $res
    }
    return $result
}

##
## 
## 
##

proc send_old_data_control {cmd_arg} {
    global data_dir
    global file_control_table
    global file_control_count
    global to_socket
    global to_history
    
    if {[info exists file_control_count]} {
	for {set i 0} {$i <= $file_control_count} {incr i} {
	    catch {unset file_control_table($i,name)}
	    catch {unset file_control_table($i,varids)}
	    catch {unset file_control_table($i,res)}
	    catch {unset file_control_table($i,ext)}    
	}
	catch {unset file_control_count}
    }
    set filter_arg [lindex $cmd_arg 0]
    set varid_list [lindex $cmd_arg 1]    
    if {($filter_arg == "") || ($varid_list == "")} {
       	lappend to_history "error data_old_tag: no arguments given"
        lappend to_socket "error data_old_tag {no arguments given}"
        return
    }
    ##
    ## checks the contents of request
    ##
    set date          [lindex $filter_arg 0]
    set kind_data     [lindex $filter_arg 1]
    set kind_interval [lindex $filter_arg 2]
    set error 0

    case $kind_interval in {
	{-1} {
	    if {$kind_data != "raw"} {
		set error 1
	    }
	}
	{15-min} {
	    if {[lsearch "total average 1-min-peak" $kind_data] == -1} {
		set error 1
	    }
	}
	{1-hour} {
      if {[lsearch "total average 1-min-peak 15-min-peak" $kind_data] == -1} {
		set error 1
	    }
	}
	{24-hour} {
	    set tmp "total average 1-min-peak 15-min-peak 1h-peak" 
            if {[lsearch $tmp $kind_data] == -1}  {
		set error 1
	    }
	}	
    }

    if {$error != 0} {
	lappend to_history "error data_old_tag: wrong kind_interval <-> \
                            kind_data"
	lappend to_socket "error data_old_tag {wrong kind_interval <-> \
                            kind_data}"
	return
    }

    foreach elem $varid_list {
        set varid [lindex $elem 0]
        set data_file_ext [lindex $elem 1]
	foreach data_ext_elem $data_file_ext {
	    if {[lindex [split $data_ext_elem -] 0] != $date} {
		lappend to_history "error data_old_tag: wrong date <-> \
                                    file.ext"
		lappend to_socket  "error data_old_tag {wrong date <-> \
                                    file.ext}"
		return		
	    }
	    if {[lindex $filter_arg 1] == "raw"} {
		set data_file_name "$data_dir/raw-data-$data_ext_elem"
            } else {
		set data_file_name "$data_dir/statistical-data-$data_ext_elem"
            }
	    if {![info exists file_control_count]} {
		set file_control_count 0
		set found 0
	    } else {
		##
    	    	## look if we already have the filename in structure
		##
		for {set i 0} {$i <= $file_control_count} {incr i} {
		    set filename1 $file_control_table($i,name)
		    if {$filename1 == $data_file_name} {
			## we have found the filename in the structure
			lappend file_control_table($i,varids) $varid
			set found 1
            	        break
		    } else {
			set found 0
		    }
    	        }
		if {!$found} {
		    incr file_control_count
		}
	    }
    	    if {!$found} {
		set file_control_table($file_control_count,name) \
                                       $data_file_name
    	        set file_control_table($file_control_count,varids) $varid
                set file_control_table($file_control_count,ext) $data_ext_elem
	    }
        }
    }
    if {![info exists file_control_count]} { 
	lappend to_socket "error data_old_tag failed"
	lappend to_history "error data_old_tag failed"
	return
    }
    read_old_data $filter_arg
    ## sort the result in requested varid order
    ## send data
    send_old_data $varid_list
    ## reset all structures
    if {[info exists file_control_count]} {
	for {set i 0} {$i <= $file_control_count} {incr i} {
	    catch {unset file_control_table($i,name)}
	    catch {unset file_control_table($i,varids)}
	    catch {unset file_control_table($i,res)}
	    catch {unset file_control_table($i,ext)}
	}
    }
    catch {unset file_control_count}
}

##
## proc reads the old data using file_control_table and filterargs
##

proc read_old_data {filter_list} {
    global file_control_table
    global file_control_count
    global to_history
    
    set filter [lindex $filter_list 2]
    if {$filter == "15-min"} { set timetick 900 }
    if {$filter == "1-hour"} { set timetick 3600 }
    if {$filter == "24-hour"} { set timetick 86400 }

    set kind_data [lindex $filter_list 1]

    for {set i 0} {$i <= $file_control_count} {incr i} {
    	## try to open file
    	set filename $file_control_table($i,name)
	if {![file exists $filename]} {
            set message "can not find $filename for reading old data"
	    lappend to_history "error_read old_data $message"
            continue
        }
        if {[catch {open $filename r} filehandle]} {
            lappend to_history "error read_old_data $filehandle"
            continue
        }
        ## try to read lines from file and filter the values from the varids
        if {[catch {gets $filehandle} line]} {
            lappend to_history "error read_old_data $line"
	    catch {close $filehandle}
            continue
        }
	while {![eof $filehandle]} {
            set line_values ""
            set timestamp [lindex $line 0]
            case $filter in {
		{-1} {
		    ## we are scanning a raw data file
		    set line_values [lindex $line 1]
		    set timestamp [lindex $timestamp 3]
            	}
		{15-min 1-hour 24-hour} {
		    if  {[lindex [lindex $line 1] 0] == $timetick} {
			set line_values [lindex [lindex $line 1] 1]
		    }
		}
            }
            ## if we have not found filterargs in line read new line
	    if {$line_values == ""} {
		if {[catch {gets $filehandle} line]} {
		    lappend to_history "error read_old_data $line"
		    catch {close $filehandle}
		    break
		}
                continue
	    }
            ## we have found filterargs in line
            ## search the varids in the read list
            set data_file_varids $file_control_table($i,varids)
	    foreach elem $line_values {
               	## test, if we find a varid we are looking for
		set varid1 [lindex $elem 0]
                if {[lsearch $data_file_varids $varid1] == -1} {
		    continue
                }
		case $kind_data in {
		    {raw} {
			set value [lindex $elem 1]
            	    }
                    {total} {
			set value [lindex $elem 9]
                    }
		    {average} {
			set value [lindex $elem 3]
		    }
                    {1-min-peak} {
			set value ""
			lappend value "[lindex $elem 5] [lindex $elem 7]"
		    }
		    {15-min-peak} {
			set value ""
			lappend value "[lindex $elem 11] [lindex $elem 13]" 
		    }
		    {1h-peak} {
			set value ""
			lappend value "[lindex $elem 15] [lindex $elem 17]"
		    }
		    {default} {
			set value -99
		    }
                }
                lappend file_control_table($i,res) "$timestamp $varid1 $value"
            }
	    if {[catch {gets $filehandle} line]} {
       	    	lappend to_history "error read_old_data $line"
		catch {close $filehandle}
                break
            }
        }
	catch {close $filehandle}
    }
}

##
## proc sorts all results in oder of the timestamps and varids
##      and sends them to socket
##

proc send_old_data {varid_list} {
    global to_socket
    global to_history
    global file_control_table
    global file_control_count
    
    
    if {[info exists file_control_count]} {
      	for {set i 0} {$i <= $file_control_count} {incr i} {
	    set varids ""
	    if {![info exists file_control_table($i,res)]} { continue }
	    set varids $file_control_table($i,varids)
	    foreach res_elem $file_control_table($i,res) {
            	set varid [lindex $res_elem 1]
		set res ""
                if {[lsearch $varids $varid] != -1} {
		    lappend res [lindex $res_elem 0]
		    lappend res [lindex $res_elem 2]
		    lappend result($varid) $res
                } else {
		    lappend to_history "error send_old_data: var_id is not \
                                        requested"
                }
            }
            set res ""
            foreach elem $varids {
		if {[catch {lappend res $result($elem)} error]} {
		    lappend res ""
		}
                catch {unset result($elem)}
            }
            set result1     $file_control_table($i,ext)
            lappend result1 $varids
            lappend result1 $res
	    
            set res ""
            lappend res_old_data $result1
            set result1 ""
            set varids  ""
	}
	if {![info exists res_old_data]} {
	    lappend to_socket "error data_old_tag failed" 
	    lappend to_history "error data_old_tag failed" 
	    return
	}
        set message "result data_tag_old"
        lappend message $res_old_data
        lappend to_socket $message
    }
}

##
## proc sends info about limits to the req. socket
##

proc limit_info_list {cmd_add cmd_arg} {
    global limit_send_sockets
    global limit_send_table
    global limit_tags_list
    global limits
    global sample_control_table
    global variable_control_table
    global node_table
    global to_socket
    global socket
    
    if {![info exists limit_tags_list]} {
	lappend to_socket "result limit_info_all {{Sorry, no limit infos\
                           available.}}"
	return
    }
    if {[lsearch {info tag all} $cmd_add] == -1} {
        lappend to_socket "error limit_info {wrong argument}"
        return
    }
    set result ""
    if {$cmd_add == "all"} {
	set cmd_add limit_info_all
	lappend result " "
	lappend result "Variables with limit overflow:"
	lappend result [format "%15s %15s %11s %14s %s" host variable \
                                limit-value measured-value time] 
	foreach elem $limit_tags_list {
	    set host  $node_table($limits($elem,node),name)
	    set var   $limits($elem,name)
	    set value $limits($elem,value)
	    if {[info exists limits($elem,exceed)]} {
		set exceed $limits($elem,exceed) 
		set time [lindex $exceed 0]
		set exc_value [lindex $exceed 1]
	    }
	    lappend result [format "%15s %15s %11s %14s %s" $host $var \
                                   $value $exc_value $time]
	}
    }
    if {$cmd_add == "tag"} {
	set cmd_add limit_info_tag
	foreach elem $cmd_arg {
	    if {[lsearch $limit_tags_list $elem] == -1} { continue }
	    set res $elem
	    if {[info exists limits($elem,exceed)]} {
		lappend res $limits($elem,exceed)
	    }
	    lappend result $res
	}
    }
    if {$cmd_add == "info"} {
	set cmd_add limit_info_now 
	lappend result " "
	lappend result "Variables with limit-control:"
	lappend result [format "%15s %15s %11s %10s %12s %7s %7s" host \
                 variable limit-value limit-hyst warn-periode request warning] 
        foreach elem $limit_tags_list {
	    set host  $node_table($limits($elem,node),name)
	    set var   $limits($elem,name)
	    set tag   $elem
	    set value $limits($elem,value)
	    set hyst  $limits($elem,hyst_value)
	    set warn_period $limits($elem,count)
	    set req  no
	    set warn no
	    if {[info exists limit_send_table($socket,tags)]} {
		if {[lsearch $limit_send_table($socket,tags) $tag] != -1} {
		    set req yes
		    if {$limit_send_table($socket,$elem,warn)} {
			set warn yes
		    }
		}
	    } 
	    lappend result [format "%15s %15s %11s %10s %12s %7s %7s" $host \
                            $var $value $hyst $warn_period $req $warn]
        }
    }
    lappend to_socket [list result $cmd_add $result]
}

##
## proc insert the socket to where the limit data should be sent
##

proc insert_limit_req {cmd_add} {
    global limit_tags_list
    global limits
    global limit_send_sockets
    global limit_send_table
    global to_socket
    global socket

    if {![info exists limit_tags_list]} {
         lappend to_socket "error limit_request {insert failed}"
         return
    }
    set done 0
    foreach elem $cmd_add {
	if {[lsearch $limit_tags_list $elem] == -1} { continue }
	if {![info exists limit_send_sockets]} {
	    lappend limit_send_sockets $socket
	    set done 1
	} else { 
	    if {[lsearch $limit_send_sockets $socket] == -1} {
		lappend limit_send_sockets $socket
		set done 1
	    }
	}
	if {![info exists limit_send_table($socket,tags)]} {
	    lappend limit_send_table($socket,tags) $elem
	    set limit_send_table($socket,$elem,warn) 1
	    set limit_send_table($socket,$elem,alarm) 0
	    set done 1
	} else {
	    if {[lsearch $limit_send_table($socket,tags) $elem] == -1} {
		lappend limit_send_table($socket,tags) $elem
	    }
	    set limit_send_table($socket,$elem,warn) 1
	    set limit_send_table($socket,$elem,alarm) 0
	    set done 1
	}
    }
    if {$done} {
	lappend to_socket "ok limit_request"
	return
    }
    lappend to_socket "error limit_request {insert failed}"
}

##
## proc deletes an entry in limit control list
##

proc delete_limit {cmd_add} {
    global limit_tags_list
    global limits
    global limit_send_table
    global limit_send_sockets
    global to_socket

    if {![info exists limit_tags_list]} {
	lappend to_socket "result limit_request {no_limits}"
	return
    }
    if {$cmd_add == ""} {
	lappend to_socket "error limit_request {delete failed}"
	return
    }
    if {$cmd_add == "all"} {
	foreach elem limit_tags_list {
	    catch {unset limits($elem,sample)}
	    catch {unset limits($elem,name)}
	    catch {unset limits($elem,node)}
	    catch {unset limits($elem,exceed)}
	    catch {unset limits($elem,value)}
	    catch {unset limits($elem,warn)}
	    catch {unset limits($elem,hyst_value)}
	    catch {unset limits($elem,count)}
	    catch {unset limits($elem,alarm_count)}
	}
	if {[info exists limit_send_sockets]} {
	    foreach elem $limit_send_sockets {
		if {![info exists limit_send_table($elem,tags)]} { continue }
		foreach tag_elem $limit_send_table($elem,tags) {
		    catch {unset limit_send_table($elem,$tag_elem,warn)}
		    catch {unset limit_send_table($elem,$tag_elem,alarm)}
		}
		catch {unset limit_send_table($elem,tags)}
	    }	
	    catch {unset limit_send_sockets}
	}
	lappend to_socket "ok limit_request"
	catch { unset limit_tags_list }
	return
    }
    set found 0
    foreach elem $cmd_add {
        if {[lsearch $limit_tags_list $elem] == -1} { continue }
        set found 1
        catch {unset limits($elem,sample)}
        catch {unset limits($elem,name)}
        catch {unset limits($elem,node)}
        catch {unset limits($elem,exceed)}
	catch {unset limits($elem,value)}
	catch {unset limits($elem,warn)}
	catch {unset limits($elem,hyst_value)}
	catch {unset limits($elem,count)}
	catch {unset limits($elem,alarm_count)}
	
	set limit_tags_list [ldelete limit_tags_list $elem]
	if {[info exists limit_send_sockets]} {
	    foreach socket_elem $limit_send_sockets {
		if {![info exists limit_send_table($socket_elem,tags)]} \
                    { continue }
	       if {[lsearch $limit_send_table($socket_elem,tags) $elem] == -1} 
                    { continue } 
		catch {unset limit_send_table($socket_elem,$tag_elem,warn)}
		catch {unset limit_send_table($socket_elem,$tag_elem,alarm)}
		set limit_send_table($socket_elem,tags) \
                    [ldelete limit_send_table($socket_elem,tags) $elem]
		if {$limit_send_table($socket_elem,tags) != ""} { continue }
		catch {unset limit_send_table($socket_elem,tags)}
		set limit_send_sockets \
                    [ldelete limit_send_sockets $socket_elem]
	    }	
	    if {$limit_send_sockets != ""} { continue }
	    catch {unset limit_send_sockets}
	} 
    }
    if {$found} {
	if {$limit_tags_list == ""} { unset limit_tags_list }
        lappend to_socket "ok limit_request"
        return
    }
    lappend to_socket "error limit_request {delete failed}"
}

##
## proc sets the limits of tags
##

proc set_limit {cmd_add} {
    global limit_tags_list
    global limits
    global to_socket
    global variable_control_table
    global variable_control_count
    global node_count
    global node_table
    global tag_count

    if {$cmd_add == ""} {
	lappend to_socket "error limit_request {set failed}"
	return
    }
    foreach elem $cmd_add {
	set error 0
	if {([lindex [split [lindex $elem 0] .] 1] < 0) || \
            ([lindex [split [lindex $elem 0] .] 1] >= $tag_count)} {
	    set cmd_add [ldelete cmd_add $elem]
	    continue
	}
	if {[lindex [split [lindex $elem 0] .] 0] != "var_id"} { continue }
	if {[llength $elem] != 4} {
	    set cmd_add [ldelete cmd_add $elem]
	    continue 
	}
	if {![isnumber [lindex $elem 1]]} { set error 1 }
	if {![isnumber [lindex $elem 2]]} { set error 1 }
	if {![isnumber [lindex $elem 3]]} { set error 1 }

	if {$error} {
	    set cmd_add [ldelete cmd_add $elem]
	    continue 
	}
	set error 0
	if {![info exists limit_tags_list]} {
	    lappend limit_tags_list [lindex $elem 0]
	    continue
	}
	if {[lsearch $limit_tags_list [lindex $elem 0]] != -1} { continue }
	lappend limit_tags_list [lindex $elem 0]
    }
    if {$cmd_add == ""} {
	lappend to_socket "error limit_request {set failed}"
	return
    }
    set res 0
    foreach elem $cmd_add {
	set tag [lindex $elem 0]
	if {[lsearch $limit_tags_list $tag] == -1} { continue }
	for {set i 0} {$i <= $variable_control_count} {incr i} {
	    if {![info exists variable_control_table($i,tags)]} { continue }
	    if {[lsearch $variable_control_table($i,tags) $tag] == -1} \
               { continue }
	    set limits($tag,sample) \
                       $variable_control_table($i,sample_control_id)
	    set limits($tag,value)       [lindex $elem 1]
	    set limits($tag,hyst_value)  [lindex $elem 2]
	    set limits($tag,count)       [lindex $elem 3] 
	    set limits($tag,alarm_count) [lindex $elem 3]
	    set limits($tag,exceed) ""
	    set limits($tag,warn) 0
	    set res 1
	    break
	}
	if {$res == 0} { continue }
	set found 0
	for {set j 0} {$j <= $node_count} {incr j} {
	    foreach node_elem $node_table($j,vars) {
		if {[lindex $node_elem 2] != $tag} { continue }
		set limits($tag,node) $j
		set limits($tag,name) [lindex $node_elem 0]
		set found 1
		break
	    }
	    if {$found == 1} { break }
	}
    }
    if {$res != 0} {
	lappend to_socket "ok limit_request"
	return
    }
    lappend to_socket "error limit_request {set failed}"
}

##
## proc sets the warn variable of the requested variable for the socket

proc set_warn {cmd_add} {
    global limit_tags_list
    global limits
    global limit_send_sockets
    global limit_send_table 
    global socket
    global to_history
    global to_socket
    
    if {![info exists limit_tags_list]} {
	lappend to_socket "error limit_request {set_warn failed}"
	return
    } 
    if {![info exists limit_send_sockets]} {
	lappend to_socket "error limit_request {set_warn failed}"
	return
    }
    if {[lsearch $limit_send_sockets $socket] == -1} {
	lappend to_socket "error limit_request {set_warn failed}"
	return
    }
    if {![info exists limit_send_table($socket,tags)]} {
	lappend to_socket "error limit_request {set_warn failed}"
	return
    }
    if {$cmd_add == ""} {
	lappend to_socket "error limit_request {set_warn failed}"
	return
    }   
    if {$cmd_add == "all"} {
	foreach elem $limit_send_table($socket,tags) {
	    if {$limit_send_table($socket,$elem,warn)} {
		set limit_send_table($socket,$elem,warn) 0
		continue
	    }
	    set limit_send_table($socket,$elem,warn) 1
	}
	lappend to_socket "ok limit_request"
	return
    }
    set done 0  
    foreach elem $cmd_add {
	if {[lsearch $limit_send_table($socket,tags) $elem] == -1} { continue }
	set done 1
	if {$limit_send_table($socket,$elem,warn)} {
	    set limit_send_table($socket,$elem,warn) 0
	    continue
	}
	set limit_send_table($socket,$elem,warn) 1
    }
    if {!$done} {
	lappend to_socket "error limit_request {set_warn failed}"
	return
    }
    lappend to_socket "ok limit_request"
}

##
## proc dletes an existing limt_insert_request
##

proc delete_limit_req {cmd_add} {
    global limit_tags_list
    global limits
    global limit_send_sockets
    global limit_send_table 
    global socket
    global to_history
    global to_socket
    
    if {![info exists limit_tags_list]} {
	lappend to_socket "result limit_request {delete_req failed}"
	return
    } 
    if {![info exists limit_send_sockets]} {
	lappend to_socket "result limit_request {delete_req failed}"
	return
    }
    if {[lsearch $limit_send_sockets $socket] == -1} {
	lappend to_socket "result limit_request {delete_req failed}"
	return
    }
    if {![info exists limit_send_table($socket,tags)]} {
	lappend to_socket "result limit_request {delete_req failed}"
	return
    }
    if {$cmd_add == ""} {
	lappend to_socket "result limit_request {delete_req failed}"
	return
    }   
    set done 0
    if {$cmd_add == "all"} {
	set cmd_add $limit_send_table($socket,tags)
    }
    foreach elem $cmd_add {
	if {[lsearch $limit_send_table($socket,tags) $elem] == -1} { continue }
	set done 1
	catch {unset limit_send_table($socket,$elem,warn)}
	set limit_send_table($socket,tags) \
            [ldelete limit_send_table($socket,tags) $elem]
	if {$limit_send_table($socket,tags) != ""} { continue }
	catch {unset limit_send_table($socket,tags)}
	set limit_send_sockets [ldelete limit_send_sockets $socket]
	if {$limit_send_sockets == ""} {
	    catch {unset limit_send_sockets}
	}
    }
    if {$done} { 
	lappend to_socket "ok limit_request"
	return
    } 
    lappend to_socket "result limit_request {delete_req failed}"
}

###############################################################################
########################   main procedure               #######################
###############################################################################
##
## Start the monitordaemon, create job to accept connections and
## to check if incoming requests are a command or a request for
## connection
##

proc main {} {
    global argv
    global env ETC_DIR
    global server_port
    global start_dir
    
    global data_dir
    global history_file  
    global config_file 
    global variable_file 
    global orig_header_file 
    global orig_data_file
    global orig_stat_file
    global limit_file   
    global file_names_file

    ## ATTENTION!! Here we adjust the PATH variable of the environment
    ## to take care of ETC_DIR as configured in the Makefile

    if {[info exists env(PATH)]} {
	set env(PATH) $ETC_DIR:$env(PATH)
    } else {
	set env(PATH) $ETC_DIR
    }

    ## set some global variables by using argv
    
    if {[llength $argv] != 2} {
	puts stderr "Usage: netguard port dir"
	flush stderr
	exit
    }

    set server_port [lindex $argv 0]
    set start_dir   [lindex $argv 1]

    set data_dir         "$start_dir/data"	
    if {![file isdirectory $data_dir]} {
	exec mkdir -p $data_dir
    }
    set history_file     "$start_dir/netguard.log"
    set config_file      "$start_dir/config"
    set variable_file    "$start_dir/variables"
    set limit_file       "$start_dir/limit-data"
    set file_names_file  "$start_dir/statconf" 

    set orig_header_file "$data_dir/header-file-"
    set orig_data_file   "$data_dir/raw-data-" 
    set orig_stat_file   "$data_dir/statistical-data-"

    ## end of configuration by argv

    start_control_daemon
    read_config
    start_tools
    time_check
    write_history
}

main
