#! /usr/bin/perl -w
# My personal script to manage to NWS familly of daemons.
# Contrary to the upstream provided scripts, it does not
#  try to manage all the machines on the net. It only
#  manage the scripts on the locale machine, but it does
#  it well. It has a conffile (usually /etc/nws.conf),
#  in which you can set a great lot of things.
# To manage the whole net, it is easy to do scripts like
#  the next one to pass a command to each site :
#
#--BEGIN
##! /bin/sh
## To be run as cron table on only on machine
#
#machines="<space separed list of your machines>"
#for n in `echo $machines` ; do
#  cmd="rsh $n /path/to/nws_setup $@";
#  echo " $cmd";
#  system($cmd);
#  echo;
#done;
#--END
#
# Copyright (C) 1999 Free Software Foundation, Inc.
# Martin Quinson (martin.quinson::loria.fr), 2000,2001,2002,2005.
# Distributed under the GPL Licence. 
#

# TODO: 
#  - Searching the bin path after parsing the config file, we wouldn't 
#    have to hardcode the name of binaries
#  - What if all binaries are not in the same directory?
#  - for now, logpath and statpath are the first writable dir from 
#    hardcoded lists. Need for a better tests?
#  - Allow being in several groups
#  - check that handling of empty value in config file is correct
#  - generalize the skills

use strict;
use POSIX qw(setsid setuid); #to fork daemons
use IO::Handle; #just to flush...

my $conffile=""; # Where to read the args from
my $progname = $0; $progname= $& if $progname =~ m,[^/]+$,;

#
# Parse command line
#
my $verbose=0; # do I have to tell my life to user or should I shut up ?
my $gdb_attach=0;
my $whereconf="/etc/nws.conf $ENV{HOME}/.nws.conf $ENV{HOME}/etc/nws.conf /usr/local/etc/nws.conf";

my $opt;
for ($opt = shift @ARGV; $opt =~ /^--?(.*)$/; $opt = shift @ARGV) {
    my $optname = $1;
    if ($optname =~ /gdb/) {
	$gdb_attach = 1;
    } elsif ($optname =~ /verbose/ || $optname =~ /^v$/) {
	$verbose = 1;
    } elsif ($optname =~ /conffile/ || $optname =~ /^c$/) {
	$whereconf= shift @ARGV;
    } else {
	die "Unknown option: $opt\n";
    }
}
unshift @ARGV,$opt;


#
# Search the conffile
# 
my $i;

foreach $i (split(/\s+/,$whereconf)) {
    if (("$conffile" eq "")&&(-s $i)) {
	$conffile=$i;
    }
}
if (-z "$conffile") {
    die ("$progname: Can't find my conffile ! I've searched in :\n  $whereconf\n  Please create one, or edit the script !\n");
}

sub empty {
    my $aze=shift;
    return 1 unless (defined $aze);
    return 1 unless ($aze =~ m,\S,);
    return 0;
}

#####################
# Read all the args #
#####################

# Who am I ?
my $hostname; # this machine
my $my_group=undef; # Group of which this machine is member
my $wanted_uid=""; # the user ID we should be running under

# Meta configuration
my ($possible_actions,$possible_infos,$possible_skills,
    $possible_parts,$possible_stop);
my %howto; # $howto{cat}{part} is the cmd to exec to $cat'ing $part
           #  Valid value to cat are: start, stop and test
my %skills; # keys=name of skills to run;values=args for them FIXME?

# Content of config file
my %config; # actual value of each variable


# What should I do here ?
my $start_part; # ordoned list of parts to start
my $stop_part; # idem, to stop

# FIXME: Old cruft ? 
# my $ctrl_host; #the prog to check the daemons
my $start_activity; #the prog to check the skills


##
## Get a variable from the configuration file, or from the provided
##  defaults. Defaults may content several possibilities, separated by '||'
##  Each part can be '$ENV{"something"}' or a fixed string.
##
sub arg {
    my $name=shift;
    my $defaults=shift;

    my $line; # to read the conffile

    my $global=undef; # where to put any global corresponding
    my $group=undef;  # where to put setting for my group
    my $partic=undef; # where to put any setting for this particular machine
    my $res;
    
    ##
    ## Parse conf file
    ## 
    open FILE,"$conffile" ||
	die "$progname: Error: can't open the conffile `$conffile'\n";
    while (<FILE>) {
	chomp;
	while ((s/\\$//) && ($_ .= <FILE>)){}
	s/#.*$//;
	next unless /^$name/;
	chomp;
	if (/^$name\s*\(.*?$hostname[^\)]*\)\s*=\s*(.*?)\s*$/) {
	    warn "$progname: Warning: `$name' is set several times for $hostname in `$conffile'\n" 
		if (defined $partic);
	    $partic=$1;
	}
	if (defined $my_group && $my_group && 
	    /^$name\s*\(.*?$my_group[^\)]*\)\s*=\s*(.*?)\s*$/) {
	    warn "$progname: Warning: `$name' is set several times for group $my_group in `$conffile'\n" 
		if (defined $group);
	    $group=$1;
	}
	if (/^$name\s*=\s*(.*?)\s*$/) {
	    warn "$progname: Warning: `$name' is set several times in `$conffile'\n"
		if (defined $global);
	    $global=$1;
	}
    }
    close FILE;
    ##
    ## Get value from what was parsed if possible
    ##
    $res=$partic;
    $res=$group unless (defined $res);
    $res=$global unless (defined $res);

    ## 
    ## Handle defaults
    ##
    if ($defaults) {
	foreach my $defaultpart (split(/\|\|/,$defaults)) {
	    unless (defined($res)) {
		if ($defaultpart =~ /\$ENV\{([^\}]*)\}/) {
		    $res=$ENV{$1} || undef;
		} else {
		    $res=$defaultpart;
		}
	    }
	}
    }
    
    if ($res) {
	my $home="$ENV{HOME}";
	$res =~ s/^~\//$home/;
    }
    return $res;
}


#########################################
### the main function to get the args ###
#########################################
sub read_all_the_args {
    my $dol='$'; # to ease some regular expressions

    ##
    ## Parse the meta-configuration (at the end of this file):
    ##  definition of NWS parts and how to run them 
    ##

    my %legal_data_value; # what value can be found in the data part
    my %var_defaults; # defaults of each variable

    while (<DATA>) {
	chomp;
	while ((s/\\$//) && ($_ .= <DATA>) && chomp){}
	s/#.*$//;
	next if /^$/;
	die "unparsable metaconfiguration data: $_" 
	    unless (m/^(([^=[:blank:]])*)\s*?=\s*(.*)$/);
	my ($var,$val)=($1,$3);
	# Get info about what is allowed in the rest
	if      ($var =~ /^possible_parts$/) { $possible_parts  = $val;
	} elsif ($var =~ /^possible_stop$/) {  $possible_stop   = $val;
        } elsif ($var =~ /^possible_skills/) { $possible_skills = $val;
        } elsif ($var =~ /^possible_actions/) {$possible_actions= $val;
        } elsif ($var =~ /^possible_infos/) {  $possible_infos  = $val;

        # learn how to handle all parts, and which variables are needed for
        #   that (no other variable will be allowed in config file)
        } elsif ($var =~ /^([^_]*)_(.*)$/ 
		 && (grep {$_ eq $1} split(/ /,$possible_actions))
		 && (grep {$_ eq $2} split(/ /,$possible_parts))) {
	    $howto{$1}{$2}="$val";
	    foreach (split(/ +/,$val)) {
		while (s/^([^$dol]*\$)//) {
		    s/([-_a-zA-Z0-9]*)//;
		    $legal_data_value{$1}=1;
		}
 	    }

	# learn about infos on parts, and which variables are needed for
        #   that (no other variable will be allowed in config file)
        } elsif ($var =~ /^([^_]*)_(.*)$/ 
		 && (grep {$_ eq $1} split(/ /,$possible_parts))
		 && (grep {$_ eq $2} split(/ /,$possible_infos))) {
	    $legal_data_value{$var}=1; # these are always legal
	    $var_defaults{$var}=$val;
	    
	} elsif ($legal_data_value{$var}) {
	    $var_defaults{$var}=$val;
	} else {
	    print "Unparsable metaconfig line: $var=$val\n";
	}
    } 

    ##
    ## search the hostname
    ##

    my $host=`hostname`;
    chomp($host);
    # search the good domainname executable
    my $domainname="";
    if ((-f "/usr/bin/domainname")
	&& system("/usr/bin/domainname 2>&1 >/dev/null")) {
	$domainname="/usr/bin/domainname";
    } elsif ((-f "/bin/dnsdomainname")
	     && system("/bin/dnsdomainname 2>&1 >/dev/null")) {
	$domainname="/bin/dnsdomainname";
    } else {
	warn "Warning : unable to find the domainname\n" if $verbose;
    }
    if ("$domainname" ne "") {
	$hostname=`$domainname 2>/dev/null`;
	if ("$hostname" eq "") {
	    $hostname="$host";
	} else {
	    $hostname="$host.$hostname";
	}
    } else {
	$hostname="$host";
    }
    chomp($hostname);
    my $old_name = $hostname;
    # Get the verbosity from the config file
    $verbose ||= arg("verbose","0");
    $hostname=arg("hostname","$hostname");
    if ($hostname eq $old_name) {
	warn("DEBUG: My name is $hostname\n") if $verbose;
    } else {
	warn("My name is $hostname (was $old_name)\n") if $verbose;
    }
    $config{'hostname'}="$hostname";

    ##
    ## Drop priviledges as soon as possible
    ##
    $wanted_uid=arg("uid") || "";
    if (length($wanted_uid)) {
       POSIX::setuid($wanted_uid) || die "Cannot setuid($wanted_uid). Either run this as root or remove the uid configuration variable";
    }

    ##
    ## Am I member of a group ?
    ## 
    $my_group=arg("group") || "";    

    ##
    ## Search the bin path 
    ##
    my $bin_path="";
    foreach my $pathpart (split(':',$ENV{PATH})) {
	if (-x "$pathpart/nws_sensor" &&
	    -x "$pathpart/nws_nameserver" &&
	    -x "$pathpart/nws_memory" &&
	    -x "$pathpart/nws_ctrl" &&
	    (-x "$pathpart/nws_start_activity"|| -x "$pathpart/start_activity")) {
	    $bin_path=$pathpart;
	    last;
	} 
    }
    unless ($bin_path =~ /\W/) {
	die "Unable to find the nws binaries in your PATH. Please fix it.\n";
    }
    $config{'bin_path'}="$bin_path";
    
    # 
    # Search the log path
    #
    my $log_path="";
    my $path_test=(arg("log_path")||"")." /var/log/nws $ENV{HOME}/var/log/nws $ENV{HOME}/var/log/ /tmp";
    LOGPATH: foreach my $pathpart (split(" ",$path_test)) {
	if (-w "$pathpart") {
	    $log_path=$pathpart;
	    last;
	}
    }
    if (-z $log_path) {
	die "Unable to write logs to either $path_test. Please fix it\n";
    }
    $config{'log_path'}="$log_path";

    #
    # Search the state path
    #
    my $state_path="";
    $path_test=(arg("state_path")||"")." /var/state/nws $ENV{HOME}/var/state/nws $ENV{HOME}/var/state $log_path /tmp";
    LOGPATH: foreach my $pathpart (split(" ",$path_test)) {
	if (-w "$pathpart") {
	    $state_path=$pathpart;
	    last;
	}
    }
    if (-z $state_path) {
	die "Unable to write stat to either $path_test. Please fix it\n";
    }
    $config{'state_path'}="$state_path";

    # The rest is to ensure compatibility with upstream binaries 
    #  whose name where not prefixed with 'nws_' by me.
    if (-x "$bin_path/nws_start_activity") {
	$start_activity="$bin_path/nws_start_activity";
    } else { # must exist since we tested it for bin_path
	$start_activity="$bin_path/start_activity";
    }

    ##
    ## And now, read the args for all parts
    ##  We search in the config file, and what we search was parsed from
    ##  the end of this file.
    ##
    foreach my $var (sort keys %legal_data_value) {
#	printf "var=%s ; defaults=%s ; preset value=%s\n",
#  	  ($var ? $var:"UNDEF"),
#	  ($var_defaults{$var} ? $var_defaults{$var}:"UNDEF"),
#	  ($config{$var} ? $config{$var} : "UNDEF");
	$config{$var}=arg($var,$var_defaults{$var})
	    unless (defined $config{$var});
    }
#    foreach my $var (sort keys %config) {
#	print "$var=".($config{$var}||"***** UNDEF *****")."\n";
#    }

    ## 
    ## Ok, we can now rewrite the variables, to remove all reference to 
    ##  other variables in variable body ($a=AZE;$b=$a.$a)->($a=AZE;$b=AZE.AZE)
    ##
    my $errmsg_undef = "Error: '%s' is undef. The config file must provide a value.\n";

    foreach my $var (sort keys %config) {
	my $dol = '$';
#	print STDERR "Look at $var=".($config{$var}||"***** UNDEF *****")."\n";
	die sprintf ($errmsg_undef,$var) unless (defined $config{$var});
	while ($config{$var} =~ m/^([^$dol]*?)\$([-_a-zA-Z0-9]*)(.*)$/) {
	    die sprintf ($errmsg_undef,$2) unless (defined $config{$2} || length($2)==0);
	    $config{$var} = $1.(length($2)?$config{$2}:"").$3;
	}
    }
    
    ##
    ## Rewrite start, test, stop command lines.
    ## 
    foreach my $part (split(/ /,$possible_parts)) {
	foreach my $cat (split(/ /,$possible_actions)) {
	    die "Error in meta-configuration: Dunno how to $cat $part\n"
		unless ($howto{$cat}{$part});
	    while ($howto{$cat}{$part} =~ m/^([^$dol]*?)\$([-_a-zA-Z0-9]*)(.*)$/) {
		die sprintf ($errmsg_undef,$2) unless (defined $config{$2});
		$howto{$cat}{$part} = $1.$config{$2}.$3;
	    }	    
	}
    }
    ##
    ## Check that all info is defined
    ##
    foreach my $part (split(/ /,$possible_parts)) {
	foreach my $info (split(/ /,$possible_infos)) {
	    warn "Error in meta-configuration: info '$info' not present for '$part'.\n"
		unless defined $config{$part.'_'.$info};
	}
    }
    ##
    ## Read the args about the skills
    ##

    # read it
    my $skills=arg("skills");

    # verify it
    if (defined $skills) {
	foreach my $j (split(/\s+/,$skills)) {
	    my $good="no";
	    foreach $i (split(/\s+/,$possible_skills)) {
		$good="yes" if ($i eq $j);
	    }
	    ($good eq "yes") || 
		die "$progname: Error: Skill `$j' unknown.\n";
	    
	    # read the args of skills
	    $skills{$j}=arg("skill.$j");
	    unless (defined $skills{$j}) {
		$skills{$j}="";
	    }
#	printf "args of $j=${skills{$j}}\n";
	}
    }
}

#
# read and verify part_to_run
#

sub verify_part {
    #read it
    my $part_to_run=shift;
    $part_to_run=arg("part_to_run") unless (defined($part_to_run));

    die "Nothing to do (part_to_run is empty)\n"
	unless (defined($part_to_run) && $part_to_run);
    #verify it
    foreach my $j (split(/\s+/,$part_to_run)) {
	my $good="no";
	foreach $i (split(/\s+/,$possible_parts)) {
	    $good="yes" if ($j =~ /^$i(:[0-9]*)?$/);
	}
	($good eq "yes") || 
	    die "$progname: Error: I don't know the part `$j' of NWS.\n";
    }

    # sort it
    $start_part="";
    foreach $i (split(/\s+/,$possible_parts)) {
	$start_part="$start_part $1" if ($part_to_run=~ m,($i(:[0-9]*)?),);
    }

    $stop_part="";
    foreach $i (split(/\s+/,$possible_stop)) {
	$stop_part="$stop_part $1" if ($part_to_run=~ m,($i(:[0-9]*)?),);
    }    

    # trim it
    $start_part=~ s/^\s*(.*?)\s*$/$1/;
    $stop_part=~ s/^\s*(.*?)\s*$/$1/;
}

sub launch_skills {
    my $cmd;
    return 0 unless ($start_part =~ m,sensor,);
    sleep(5); # Make sure the sensor had enough time to start
    SKILL: foreach my $i (sort keys %skills) {
#	printf "  (re)launch the $i skill: ";
#	$cmd="$start_activity -F start $name{sensor} $i ${skills{$i}} ";
	$cmd="$start_activity -F $config{sensor_name} skillName:$i ${skills{$i}} ";
#	printf ("\n(Launch the skill with `$cmd')\n");
	if (system($cmd)){
	    # system returns "does something go wrong ?"
#	    if (system("$start_activity restart $name{sensor} $i ${skills{$i}} 1>/dev/null")) {
		printf "failed.\n";
		next SKILL;
#	    }
	}
#	printf "done.\n";
    }
}

sub fork_and_exec {
    my $cmd=shift;
    my $pid=fork;
    (defined $pid) || printf "Can't fork: $!\n";
    if ($pid) {
	#father
	printf("Forked to exec '$cmd'\n") if $verbose;
	if ($gdb_attach) {
	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid");
	}
    } else {
	#child
	setsid  (defined $	    printf("\n\nAttaching gdb to pid $pid");
	    exec split (' ',"gdb --pid $pid")