flamethrower-0.1.8/0000755000000000000000000000000010366264761012730 5ustar rootrootflamethrower-0.1.8/utils/0000755000000000000000000000000010366264761014070 5ustar rootrootflamethrower-0.1.8/utils/install-N-sub.conf0000644000000000000000000000032107677461312017365 0ustar rootroot# # Used by ./util/install-N-sub during "make install" to substitute This for That # in files as they are being installed. # # This That INS_VERSION `cat VERSION` flamethrower-0.1.8/utils/install-N-sub0000755000000000000000000001500207720712620016434 0ustar rootroot#!/usr/bin/perl -w # # Substitutes one string for another in a set of files # # $Id: install-N-sub 41 2003-08-20 15:36:48Z brianfinley $ # # ================================================================ # # Description: # # This program substitutes one string for another string in a # set of files. What to substitute is based on the first argument # to the program. The rest of the arguments are files on which to # do the substitution. # # ================================================================ # # Substitution Code by: # Alan Bailey, bailey@mcs.anl.gov # # Other Code by: # Brian Elliott Finley (2003.05.12) # # ================================================================ # use strict; use Getopt::Long; use File::Basename; use File::Copy; use File::Path; (my $program = $0) =~ s:.*/::; my $VERSION = "0.1.1"; # set version information my $version_info = <<"EOF"; $program v$VERSION EOF # set help information my $help_info = $version_info . <<"EOF"; Usage: $program --config FILE [OPTION]... FILE... If --install and --dest are not specified, substitutions are applied to FILE(s) directly. If --install and --dest are specified, then FILE(s) are left alone where they reside, and substitutions are only made to the copies of FILE(s) as they are being installed. Options: (options can be presented in any order) --help Display this output. --version Display version and copyright information. --config FILE Substitution configuration file. Format is: KEY_STRING what_to_put_in_it's_place --install 'ARGS' Arguments to be passed to the install program. Example: --install '-m 755' See \"man install\" for details. --dest [FILE|DIR] Destination file or directory name. EOF # interpret command line options GetOptions( "help" => \my $help, "version" => \my $version, "config=s" => \my $config_file, "install=s" => \my $install_args, "dest=s" => \my $dest, ) or die qq($help_info); # if requested, print help information if($help) { print qq($help_info); exit 0; } # if requested, print version and copyright information if($version) { print qq($version_info); exit 0; } # if requested, print version and copyright information if(!$config_file) { print qq($help_info); exit 1; } # install and dest must both be specified, or we conservatively exit. if(($install_args) and (!$dest)) { print qq($help_info); exit 1; } if(($dest) and (!$install_args)) { print qq($help_info); exit 1; } my @files = @ARGV; if(! -r $config_file) { die "$program: Cannot read $config_file\n"; } my %subs = parse_config_file($config_file); if(($dest) and ($install_args)) { my @tmp_files; my $tmp_dir = "/tmp/.$program.$$"; if((! -d $dest) and (@files > 1)) { print "FATAL: You have multiple source files, but have specified one of the\n"; print " following as your destination:\n"; print " - a non-existent destination directory\n"; print " - a single destination file\n"; exit 1; } foreach my $file (@files) { # # get list of tmp file names # my $tmp_file = $tmp_dir . "/" . $file; push @tmp_files, $tmp_file; # # copy files into tmp dir # my $tmp_path = dirname($tmp_file); eval { mkpath($tmp_path) }; if ($@) { print "Couldn't create $tmp_path $@"; } copy($file, $tmp_path) or die("Couldn't copy $file to $tmp_path!"); } # # Do substitutions on the tmp_files # run_through_files(@tmp_files); foreach my $tmp_file (@tmp_files) { # # install file(s) # my $cmd = "install $install_args $tmp_file $dest"; !system($cmd) or die "$cmd failed!"; } rmtree($tmp_dir); } else { # # Do substitutions in place on source files. # run_through_files(@files); } exit(0); ################################################################################ # # Subroutines # ################################################################################ # # Take each file, run substitutions on each line of the file, # and writes the file back. # # Usage: run_through_files(@files); sub run_through_files { my @files = @_; my($write_it, $error); foreach my $file (@files) { $write_it = $error = 0; # Skip this file if it's not a text file. if(! -T $file) { print "$program skipping $file -- not text.\n"; next; } # Suck in this file... open OLDFILE, "<$file" || die "$program: Cannot open $file"; my @lines = ; close OLDFILE; # Check for matches foreach (@lines) { foreach my $string (keys %subs) { if(s/$string/$subs{$string}/g) { $write_it = 1; } } } # Write it if we need to. if($write_it) { open NEWFILE, ">$file" || die "$program: Cannot open $file"; foreach (@lines) { $error = !(print NEWFILE); } close NEWFILE; if($error) { print "Error writing $file\n"; } else { print "Updated $file\n"; } } } } # # Parses through the substitution file and puts all of the associations # into a hash, %subs # # Usage: my %subs = parse_config_file($config_file); sub parse_config_file { my $file = shift; my %subs; my $string; my $substitution; open FILE, "<$file" || die "$program: Cannot open $file for reading."; while () { chop; next if (/^\s*\#/); next if (/^\s*$/); if (/^\s*\"/) { s/^\s*\"([^\"]*)\"\s+//; $string = $1; } else { s/^\s*(\S*)\s+//; $string = $1; } if (/^\"/) { s/^\"(.*)\"//; $substitution = $1; } elsif (/^\`/) { s/^\`(.*)\`//; chomp($substitution = `$1`); # execute it } else { $substitution = $_; } $subs{$string} = $substitution; } close FILE; return %subs; } flamethrower-0.1.8/lib/0000755000000000000000000000000010366264761013476 5ustar rootrootflamethrower-0.1.8/lib/Flamethrower.pm0000755000000000000000000001021307677435426016504 0ustar rootroot# # "Flamethrower" # # Copyright (C) 2002 Bald Guy Software # Brian Elliott Finley # # $Id: Flamethrower.pm 24 2003-06-29 01:04:22Z brianfinley $ # package Flamethrower; ################################################################################ # # Subroutines in this module include: # # process_modules # read_config # which # # ################################################################################ use strict; use AppConfig qw(:argcount :expand); my $VERSION = 'INS_VERSION'; my $ft_config = AppConfig->new(); # Usage: Flamethrower->read_config($file); sub read_config { my ($class, $file) = (@_); my $ft_config = AppConfig->new( { CREATE => 1, GLOBAL => { ARGCOUNT => ARGCOUNT_ONE, DEFAULT => '', EXPAND => EXPAND_VAR, }, }, # No need to define any variables here, unless we come up with one # that has attributes, such as ARGCOUNT, that are different from # the GLOBAL default. # # Ie: #'my_other_var' => { ARGCOUNT => 2 }, 'modules' => { ARGCOUNT => ARGCOUNT_LIST }, 'start_flamethrower_daemon' => { ARGCOUNT => ARGCOUNT_ONE }, 'flamethrower_directory_portbase' => { ARGCOUNT => ARGCOUNT_ONE }, 'flamethrower_directory_dir' => { ARGCOUNT => ARGCOUNT_ONE }, 'flamethrower_state_dir' => { ARGCOUNT => ARGCOUNT_ONE }, 'min_clients' => { ARGCOUNT => ARGCOUNT_ONE }, 'max_wait' => { ARGCOUNT => ARGCOUNT_ONE }, 'min_wait' => { ARGCOUNT => ARGCOUNT_ONE }, 'async' => { ARGCOUNT => ARGCOUNT_ONE }, 'autostart' => { ARGCOUNT => ARGCOUNT_ONE }, 'blocksize' => { ARGCOUNT => ARGCOUNT_ONE }, 'broadcast' => { ARGCOUNT => ARGCOUNT_ONE }, 'fec' => { ARGCOUNT => ARGCOUNT_ONE }, 'interface' => { ARGCOUNT => ARGCOUNT_ONE }, 'log' => { ARGCOUNT => ARGCOUNT_ONE }, 'max_bitrate' => { ARGCOUNT => ARGCOUNT_ONE }, 'full_duplex' => { ARGCOUNT => ARGCOUNT_ONE }, 'mcast_addr' => { ARGCOUNT => ARGCOUNT_ONE }, 'mcast_all_addr' => { ARGCOUNT => ARGCOUNT_ONE }, 'min_slice_size' => { ARGCOUNT => ARGCOUNT_ONE }, 'slice_size' => { ARGCOUNT => ARGCOUNT_ONE }, 'pointopoint' => { ARGCOUNT => ARGCOUNT_ONE }, 'rexmit_hello_interval' => { ARGCOUNT => ARGCOUNT_ONE }, 'ttl' => { ARGCOUNT => ARGCOUNT_ONE }, 'nosync' => { ARGCOUNT => ARGCOUNT_ONE }, ); $ft_config->file($file); # # Get a list of specified modules (don't know how to make appconfig give # us this.) # open(FILE, "<$file") or die("Couldn't open $file"); while () { if (m/^[[:space:]]*\[.*\][[:space:]]*$/) { s/[[:space:]]+//g; s/\[//g; s/\]//g; $ft_config->modules($_); } } # # Be sure to include the flamethrower_directory in the list. # This allows us to make the buid_command subroutine more # generic, as $ft_config->get(${module}_dir) will work for # flamethrower_directory as well as all the "normal" modules. # $ft_config->modules('flamethrower_directory'); close(FILE); $::main::ft_config = $ft_config; } ## A pure perl which command # example: SystemImager::Common->which($file,$ENV{PATH}) || croak "$file not found in your path."; sub which { my ($class, $file, $path) = @_; foreach my $dir (split(/:/,$path)) { if(-x "$dir/$file") { return 1; } } return 0; } flamethrower-0.1.8/HOWTO0000644000000000000000000000041207700214046013535 0ustar rootrootFor now, please see the "HOWTO Use Flamethrower for Multicast Installs" section in the SystemImager manual. A stand-alone "Flamethrower HOWTO" will be along shortly. You can find the Official SystemImager manual here: http://www.systemimager.org/ Cheers, -Brian flamethrower-0.1.8/VERSION0000644000000000000000000000000610365306064013764 0ustar rootroot0.1.8 flamethrower-0.1.8/bin/0000755000000000000000000000000010366264761013500 5ustar rootrootflamethrower-0.1.8/bin/flamethrowerd0000755000000000000000000004632607756011207016276 0ustar rootroot#!/usr/bin/perl -w # # "Flamethrower" # # Copyright (C) 2003 Bald Guy Software # Brian Elliott Finley # # $Id: flamethrowerd 45 2003-11-17 00:12:55Z brianfinley $ # $0 = "flamethrowerd"; use strict; use File::stat; use Getopt::Long; use POSIX qw(setsid); use lib "/usr/lib/flamethrower"; use Flamethrower; use vars qw($config $ft_config $VERSION); # # Set some defaults # my $last_time = 0; my $conf_file = '/etc/flamethrower/flamethrower.conf'; my $pid_file = '/var/run/flamethrower-server.pid'; my $version_number = "INS_VERSION"; my $program_name = "flamethrowerd"; my $get_help = " Try \"$program_name -help\" for more options."; # # Command line options # # set version information my $version_info = <<"EOF"; $program_name (part of Flamethrower) version $version_number Copyright (C) 2003 Brian Elliott Finley This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. EOF # set help information my $help_info = $version_info . <<"EOF"; Usage: $program_name [OPTION]... -server HOSTNAME -image IMAGENAME Options: (options can be presented in any order) --help Display this output. --version Display version and copyright information. --config-file FILE Alternate config file location. Defaults to: $conf_file. --pid-file FILE Name of pid file. Defaults to: $pid_file. Download, report bugs, and make suggestions at: http://systemimager.org/support/ EOF # interpret command line options GetOptions( "help" => \my $help, "version" => \my $version, "config-file=s" => \$conf_file, "pid-file=s" => \$pid_file, ) or die qq($help_info); # if requested, print help information if($help) { print qq($help_info); exit 0; } # if requested, print version and copyright information if($version) { print qq($version_info); exit 0; } # Read the config file and update the directory read_config_file($conf_file); # Turn on in flamethrower.conf file to see debug output. my $debug; if ( lc $ft_config->debug() eq "on" ) { $debug = 1; print "Flamethrower debug output turned on\n" if($debug); } # Should we start up? if ( $ft_config->start_flamethrower_daemon() ne "yes" ) { exit 0; } # Warn if specified interface doesn't exist. my $interface = $ft_config->interface(); if (( ! -d "/proc/sys/net/ipv4/conf/$interface" ) and ( ! -d "/proc/sys/net/ipv6/conf/$interface" )) { print STDERR "\n\n"; print STDERR "FATAL: Interface $interface, as specified in your flamethrowerd.conf file,\n"; print STDERR " does not appear to be configured on this machine.\n"; print STDERR "\n"; exit 1; } my $file = "udp-sender"; unless( Flamethrower->which($file,$ENV{PATH}) ){ print ("Couldn't find $file in path: $ENV{PATH}\n"); print ("Please install udp-sender, then try again.\n"); exit 1; } &daemonize; while(1) { &main; sleep 2; } exit 0; ################################################################################ # # BEGIN subroutines # # Usage: my $cmd = build_udp_sender_cmd($module); sub build_udp_sender_cmd { my $module = shift; ############################################################################ # # Set vars for all options # ############################################################################ ############################################################################ # # Global settings # my $min_clients; if ( $ft_config->get("min_clients") ) { $min_clients = " --min-clients " . $ft_config->get("min_clients"); } my $max_wait; if ( $ft_config->get("max_wait") ) { $max_wait = " --max-wait " . $ft_config->get("max_wait"); } my $min_wait; if ( $ft_config->get("min_wait") ) { $min_wait = " --min-wait " . $ft_config->get("min_wait"); } my $async; if ( $ft_config->get("async") ) { if ( lc ($ft_config->get("async")) eq "on" ) { $async = " --async"; } } my $autostart; if ( $ft_config->get("autostart") ) { $autostart = " --autostart " . $ft_config->get("autostart"); } my $blocksize; if ( $ft_config->get("blocksize") ) { $blocksize = " --blocksize " . $ft_config->get("blocksize"); } my $broadcast; if ( $ft_config->get("broadcast") ) { if ( lc ($ft_config->get("broadcast")) eq "on" ) { $broadcast = " --broadcast"; } } my $fec; if ( $ft_config->get("fec") ) { $fec = " --fec " . $ft_config->get("fec"); } my $interface; if ( $ft_config->get("interface") ) { $interface = " --interface " . $ft_config->get("interface"); } my $log; if ( $ft_config->get("log") ) { $log = " --log " . $ft_config->get("log") . ".$module"; } my $max_bitrate; if ( $ft_config->get("max_bitrate") ) { $max_bitrate = " --max-bitrate " . $ft_config->get("max_bitrate"); } my $full_duplex; if ( $ft_config->get("full_duplex") ) { if ( lc ($ft_config->get("full_duplex")) eq "on" ) { $full_duplex = " --full-duplex"; } } my $mcast_addr; if ( $ft_config->get("mcast_addr") ) { $mcast_addr = " --mcast-addr " . $ft_config->get("mcast_addr"); } my $mcast_all_addr; if ( $ft_config->get("mcast_all_addr") ) { $mcast_all_addr = " --mcast-all-addr " . $ft_config->get("mcast_all_addr"); } my $min_slice_size; if ( $ft_config->get("min_slice_size") ) { $min_slice_size = " --min-slice-size " . $ft_config->get("min_slice_size"); } my $slice_size; if ( $ft_config->get("slice_size") ) { $slice_size = " --slice-size " . $ft_config->get("slice_size"); } my $pointopoint; if ( $ft_config->get("pointopoint") ) { if ( lc ($ft_config->get("pointopoint")) eq "on" ) { $pointopoint = " --pointopoint"; } } my $rexmit_hello_interval; if ( $ft_config->get("rexmit_hello_interval") ) { $rexmit_hello_interval = " --rexmit-hello-interval " . $ft_config->get("rexmit_hello_interval"); } my $ttl; if ( $ft_config->get("ttl") ) { $ttl = " --ttl " . $ft_config->get("ttl"); } # ############################################################################ ############################################################################ # # Module specific overrides # my $dir; if ( $ft_config->get("${module}_dir") ) { $dir = $ft_config->get("${module}_dir"); } my $portbase; if ( $ft_config->get("${module}_portbase") ) { $portbase = " --portbase " . $ft_config->get("${module}_portbase"); } if ($ft_config->varlist("${module}_async")) { if ( $ft_config->get("${module}_async") ) { if ( lc ($ft_config->get("${module}_async")) eq "on" ) { $async = " --async"; } } } if ($ft_config->varlist("${module}_ttl")) { if ( $ft_config->get("${module}_ttl") ) { $ttl = " --ttl " . $ft_config->get("${module}_ttl"); } } if ($ft_config->varlist("${module}_mcast_all_addr")) { if ( $ft_config->get("${module}_mcast_all_addr") ) { $mcast_all_addr = " --mcast-all-addr " . $ft_config->get("${module}_mcast_all_addr"); } } if ($ft_config->varlist("${module}_log")) { if ( $ft_config->get("${module}_log") ) { $log = " --log " . $ft_config->get("${module}_log"); } } if ($ft_config->varlist("${module}_interface")) { if ( $ft_config->get("${module}_interface") ) { $interface = " --interface " . $ft_config->get("${module}_interface"); } } # ############################################################################ # Build command # # GNU tar opts explained: # -B, --read-full-records / reblock as we read (for reading 4.2BSD pipes) # # -S, --sparse / handle sparse files efficiently # my $cmd = qq(udp-sender --pipe 'tar -B -S -cpf - -C $dir .'); #my $cmd = qq(udp-sender --pipe 'tar -czpf - -C $dir .'); $cmd .= $portbase if(defined $portbase); $cmd .= $min_clients if(defined $min_clients); $cmd .= $max_wait if(defined $max_wait); $cmd .= $min_wait if(defined $min_wait); $cmd .= $async if(defined $async); $cmd .= $autostart if(defined $autostart); $cmd .= $blocksize if(defined $blocksize); $cmd .= $broadcast if(defined $broadcast); $cmd .= $fec if(defined $fec); $cmd .= $interface if(defined $interface); $cmd .= $log if(defined $log); $cmd .= $max_bitrate if(defined $max_bitrate); $cmd .= $full_duplex if(defined $full_duplex); $cmd .= $mcast_addr if(defined $mcast_addr); $cmd .= $mcast_all_addr if(defined $mcast_all_addr); $cmd .= $min_slice_size if(defined $min_slice_size); $cmd .= $slice_size if(defined $slice_size); $cmd .= $pointopoint if(defined $pointopoint); $cmd .= $rexmit_hello_interval if(defined $rexmit_hello_interval); $cmd .= $ttl if(defined $ttl); return $cmd; } # Usage: update_directory(); sub update_directory { print "update_directory()\n" if ($debug); # Create our directory directory, if necessary. my $dir = $ft_config->get("flamethrower_directory_dir"); if ( ! -e $dir ) { mkdir("$dir", 0755) or die("Couddn't mkdir $dir!"); } unlink <$dir/*>; # Make sure our state directory exists, if necessary, and clean it up. $dir = $ft_config->get("flamethrower_state_dir"); if ( ! -e $dir ) { print "FATAL: Flamethrower state dir $dir doesn't exist!\n"; print "Please create it and restart flamethrowerd!\n"; exit 1; } unlink <$dir/*>; ############################################################################ # # Get list of explicitly specified portbase numbers so we don't # dynamically use one that already exists. # my %portbases = $ft_config->varlist('_portbase$'); # Be sure to include the flamethrower_directory port. $_ = $ft_config->get("flamethrower_directory_portbase"); $portbases{$_} = $_; # # Make the values the keys, so we can simply to an # if (defined()) in the module loop below. # foreach my $portbase (values %portbases) { # # Test to be sure portbase is an even number. # $_ = $portbase / 2; if (m/\./) { print qq(FATAL: portbases must be even numbers! Failed on "PORTBASE=$portbase"\n); print qq(Please check your config file.\n); exit 1; } $portbases{$portbase} = $portbase; } # ############################################################################ ############################################################################ # # Create the Flamethrower "directory" (sourceable files) for each module. # my $flamethrower_directory_dir = $ft_config->get("flamethrower_directory_dir"); my $modules = $ft_config->modules(); foreach my $module ( @$modules ) { # # Put directory information that is useful to clients in # sourceable files. # my $file = $flamethrower_directory_dir . "/" . $module; open(FILE, ">$file") or die("Couldn't open $file for writing!"); print FILE "MODULE=$module\n"; # DIR if ( ! defined($ft_config->get("${module}_dir")) ) { die("Please set DIR in flamethrower.conf for [$module]!"); } # PORTBASE my $portbase; if ($ft_config->varlist("${module}_portbase")) { # portbase is already set $portbase = $ft_config->get("${module}_portbase"); } else { # Start with flamethrower_directory_portbase + 2. $portbase = $ft_config->get("flamethrower_directory_portbase") + 2; # If that port is already in use, increment by two until we # get a free one. while ( defined($portbases{$portbase}) ) { $portbase += 2; } # Put it into module specific data structure $ft_config->set("${module}_portbase", $portbase); # Add our new portbase to the existing list. $portbases{$portbase} = $portbase; } print FILE "PORTBASE=$portbase\n"; # ASYNC my $async; if ($ft_config->varlist("${module}_async")) { # async is already set $async = $ft_config->get("${module}_async"); } else { # get it from global setting $async = $ft_config->get("async"); # Put it into module specific data structure $ft_config->set("${module}_async", $async); } print FILE "ASYNC=$async\n" if ($async); # TTL my $ttl; if ($ft_config->varlist("${module}_ttl")) { # ttl is already set $ttl = $ft_config->get("${module}_ttl"); } else { # May or may not be set # get it from global setting (if it exists) if ($ft_config->varlist("^ttl")) { $ttl = $ft_config->get("ttl"); # Put it into module specific data structure $ft_config->set("${module}_ttl", $ttl); } } print FILE "TTL=$ttl\n" if ($ttl); # MCAST_ALL_ADDR my $mcast_all_addr; if ($ft_config->varlist("${module}_mcast_all_addr")) { # mcast_all_addr is already set $mcast_all_addr = $ft_config->get("${module}_mcast_all_addr"); } else { # May or may not be set # get it from global setting (if it exists) if ($ft_config->varlist("^mcast_all_addr")) { $mcast_all_addr = $ft_config->get("mcast_all_addr"); # Put it into module specific data structure $ft_config->set("${module}_mcast_all_addr", $mcast_all_addr); } } print FILE "MCAST_ALL_ADDR=$mcast_all_addr\n" if ($mcast_all_addr); # NOSYNC my $nosync; if ($ft_config->varlist("${module}_nosync")) { # nosync is already set $nosync = $ft_config->get("${module}_nosync"); } else { # May or may not be set # get it from global setting (if it exists) if ($ft_config->varlist("^nosync")) { $nosync = $ft_config->get("nosync"); # Put it into module specific data structure $ft_config->set("${module}_nosync", $nosync); } } print FILE "NOSYNC=$nosync\n" if ($nosync); close(FILE); } # ############################################################################ } # Usage: main(); sub main { print "main()\n" if($debug); if(conf_file_updated($conf_file)) { read_config_file($conf_file); } my $dir = $ft_config->get("flamethrower_state_dir"); my $modules = $ft_config->modules(); foreach my $module ( @$modules ) { my $file = "${dir}/flamethrowerd.${module}.pid"; unless(-e "$file") { # In case this happens to get started *immediately* sleep 1; # after the cast() function does it's unlink, give # the child time to die. cast($module, $dir); } } } # Usage: record_pid($file, $pid); sub record_pid { my $file = shift; my $pid = shift; print "record_pid($file, $pid)\n" if($debug); open(FILE, ">$file") or die("Couldn't open $file!"); print FILE "$pid\n"; close(FILE); } # Usage: cast($module, $state_dir); sub cast { my $module = shift; my $state_dir = shift; my $parent_file = "${state_dir}/flamethrowerd.${module}.pid"; my $child_file = "${state_dir}/flamethrowerd.${module}.udp-sender.pid"; my $file; my $parent_pid; my $child_pid; print "cast($module, $state_dir)\n" if($debug); # Fork and cast if ($parent_pid = fork) { record_pid($parent_file, $parent_pid); } elsif (defined $parent_pid) { # send the forked child off setsid or die "Can't start a new session: $!"; print "casting $module\n" if($debug); my $cmd = build_udp_sender_cmd($module); print "cmd $cmd\n" if($debug); my $child_pid = open(SENDER, "$cmd|") or die "Couldn't fork: $cmd"; record_pid($child_file, $child_pid); while(){ print $_ if($debug); } close(SENDER); $file = $child_file; print " unlinking $file\n" if($debug); unlink($file) or die("Couldn't remove $file!\n"); $file = $parent_file; print " unlinking $file\n" if($debug); unlink($file) or die("Couldn't remove $file!\n"); exit 0; } else { die "Can't fork: $!\n"; } } # Usage: read_config_file($file); sub read_config_file { my $file = shift; Flamethrower->read_config($file) or die("Couldn't read $file!"); &update_directory; } # Usage: if(conf_file_updated($conf_file)) {}; sub conf_file_updated { my $file = shift; my $st = stat($file); my $this_time = $st->ctime; if($this_time ne $last_time) { print " $file updated\n" if($debug); $last_time = $this_time; return 1; } return undef; } # Usage: $SIG{CHLD} = \&REAPER; sub REAPER { $SIG{CHLD} = \&REAPER; my $waitedpid = wait; print STDERR " Process $waitedpid has exited.\n" if($debug); } # Usage: &daemonize; sub daemonize { chdir '/' or die "Can't chdir to /: $!"; # # Commenting out the line below allows the udp-senders to behave in the way # you would expect, by automatically starting according to the --min-client, # --min-wait, and --max-wait parameters. # #open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!" unless($debug); open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!" unless($debug); defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid or die "Can't start a new session: $!"; my $file = $pid_file; local *FILE; open(FILE,">$file") or die ("FATAL: Can't open file: $file\n"); print FILE "$$\n"; close(FILE); $SIG{CHLD} = \&REAPER; } # # END subroutines # ################################################################################ flamethrower-0.1.8/bin/flamethrower0000755000000000000000000002103407756263742016134 0ustar rootroot#!/usr/bin/perl -w # # "Flamethrower" # # Copyright (C) 2003 Brian Elliott Finley # # $Id: flamethrower 46 2003-11-18 00:29:22Z brianfinley $ # use strict; use File::Path; use Getopt::Long; use lib "/usr/lib/flamethrower"; use Flamethrower; use vars qw($config $ft_config $VERSION); # # Set some defaults # my $program_name = "flamethrower"; my $version_number = "INS_VERSION"; my $conf_file = '/etc/flamethrower/flamethrower.conf'; my $transport = "udp-receiver"; my $tmp_dir = "/tmp/.flamethrower.$$"; my $version_info = <<"EOF"; $program_name (part of Flamethrower) version $version_number Copyright (C) 2003 Brian Elliott Finley This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. EOF # set help information my $help_info = $version_info . <<"EOF"; Usage: $program_name [OPTION]... --module MODULE --directory DIRECTORY or: $program_name [OPTION]... --list Options: (options can be presented in any order) --help Display this output. --version Display version and copyright information. --verbose Be verbose. --config-file FILE Alternate config file location. Defaults to: $conf_file Note: SystemImager users try using: /etc/systemimager/flamethrower.conf --list List available modules on the Flamethrower server. --module MODULE Join a multicast to recieve an identical copy of MODULE in the directory specified by --directory. --directory DIRECTORY Local directory in which to place your copy of MODULE. --ttl TTL --async --nosync --mcast-all-addr ADDRESS --portbase PORTBASE PORTBASE for the Flamethrower directory. Download, report bugs, and make suggestions at: http://systemimager.org/support/ EOF # interpret command line options GetOptions( "help" => \my $help, "version" => \my $version, "verbose" => \my $verbose, "config-file=s" => \$conf_file, "list" => \my $list, "module=s" => \my $module, "directory=s" => \my $directory, "ttl=s" => \my $ttl, "async" => \my $async, "nosync" => \my $nosync, "mcast-all-addr=s" => \my $mcast_all_addr, "portbase=s" => \my $flamethrower_directory_portbase, ) or die qq($help_info); ################################################################################ # # process options # # if requested, print help information if($help) { print qq($help_info); exit 0; } # if requested, print version and copyright information if($version) { print qq($version_info); exit 0; } # Read the config file and update the directory Flamethrower->read_config($conf_file) or die("Couldn't read $conf_file!"); # Warn if specified interface doesn't exist. my $interface = $ft_config->interface(); if (( ! -d "/proc/sys/net/ipv4/conf/$interface" ) and ( ! -d "/proc/sys/net/ipv6/conf/$interface" )) { print STDERR "\n\n"; print STDERR "FATAL: Interface $interface, as specified in your flamethrowerd.conf file,\n"; print STDERR " does not appear to be configured on this machine.\n"; print STDERR "\n"; exit 1; } unless( Flamethrower->which( "$transport", $ENV{PATH} ) ) { print "I can't find $transport in your path:\n"; print " $ENV{PATH}\n"; print "Please be sure that you have the udpcast package installed.\n"; exit 1; } # # Take settings from conf file if not specified on the command line. # unless($ttl) { $ttl = $ft_config->get('ttl'); } unless($nosync) { $nosync = $ft_config->get('nosync'); } unless($async) { $async = $ft_config->get('async'); } unless($mcast_all_addr) { $mcast_all_addr = $ft_config->get('mcast_all_addr'); } unless($flamethrower_directory_portbase) { $flamethrower_directory_portbase = $ft_config->get('flamethrower_directory_portbase'); } if($list) { my $portbase = $flamethrower_directory_portbase; my $dir = $tmp_dir; print "Available modules:\n"; # show this first, so the user knows something is happening flamethrower_client('flamethrower_directory', $dir, $portbase, $interface, $mcast_all_addr, $async, $nosync, $ttl); opendir(DIR, "$dir") or die("Couldn't open dir $dir!"); while( defined($_ = readdir(DIR)) ) { print " $_\n" unless((m/^\.{1,2}$/o) or (m/^flamethrower_directory$/o)); } closedir(DIR); print "\n"; rmtree($dir) or print "WARNING: Couldn't remove temporary directory: $dir!\n"; } elsif(($module) and ($directory)) { # # Get directory info # my $portbase = $flamethrower_directory_portbase; my $dir = $tmp_dir; flamethrower_client('flamethrower_directory', $dir, $portbase, $interface, $mcast_all_addr, $async, $nosync, $ttl); # # read module info # my $file = "$dir/$module"; open(FILE, "<$file") or die("Couldn't open $file for reading!"); while() { chomp; next if(m/^MODULE=/o); my ($variable, $value) = split(/=/); $portbase = $value if($variable eq 'PORTBASE'); $async = $value if($variable eq 'ASYNC'); $ttl = $value if($variable eq 'TTL'); $mcast_all_addr = $value if($variable eq 'MCAST_ALL_ADDR'); # don't get log info from server -- let client decide # don't get interface from server -- let client decide # don't get nosync from server -- let client decide # don't get norespect from server -- just don't } close(FILE); rmtree($dir) or print "WARNING: Couldn't remove temporary directory: $dir!\n"; $dir = $directory; flamethrower_client($module, $dir, $portbase, $interface, $mcast_all_addr, $async, $nosync, $ttl); } else { print qq($help_info); exit 1; } exit 0; ######################################################################################### # # Subroutines # # # Usage: # # flamethrower_client($module, $dir, $portbase, $interface[, $mcast_all_addr, $async, $nosync, $ttl]); # sub flamethrower_client { my $module = shift; my $dir = shift; my $portbase = shift; my $interface = shift; my $mcast_all_addr = shift; my $async = shift; my $nosync = shift; my $ttl = shift; unless(-e $dir) { eval { mkpath("$dir", 0, 0700) }; if ($@) { die("Couldn't create temporary directory: $dir: $@"); } } ############################################################################ # # build command # my $udp_receiver_options = "--interface $interface"; $udp_receiver_options .= " --portbase $portbase"; if($ttl) { $udp_receiver_options .= " --ttl $ttl"; } if( "$nosync" eq "on" ) { $udp_receiver_options .= " --nosync"; } if( "$async" eq "on" ) { $udp_receiver_options .= " --async"; } if( $mcast_all_addr ) { $udp_receiver_options .= " --mcast-all-addr $mcast_all_addr"; } # # Which tar opts should we use? If our tar has --overwrite capability, use it. # Summary: busybox tar doesn't. Debian patched gnu tar does. We want # this option enabled to ensure proper directory permissions. -BEF- # my $tar_opts; if(`tar --help 2>&1 | grep overwrite`) { $tar_opts = '--overwrite -xp'; } else { $tar_opts = '-x'; } ############################################################################ # # initiate transfer # my $udp_cmd; my $tar_cmd; if($verbose) { $udp_cmd = "udp-receiver $udp_receiver_options --file /tmp/multicast.tar.$$"; $tar_cmd = "tar $tar_opts -C $dir -f /tmp/multicast.tar.$$"; } else { $udp_cmd = "udp-receiver $udp_receiver_options --file /tmp/multicast.tar.$$ 2>/dev/null"; $tar_cmd = "tar $tar_opts -C $dir -f /tmp/multicast.tar.$$"; } print "$udp_cmd\n" if($verbose); !system($udp_cmd) or die("FAILED: $tar_cmd"); print "$tar_cmd\n" if($verbose); !system($tar_cmd) or die("FAILED: $tar_cmd"); unlink("/tmp/multicast.tar.$$"); } # # which # # Usage: # which($file,$ENV{PATH}) || do stuff; # sub which { my $file = shift; my $path = shift; foreach my $dir (split(/:/,$path)) { if(-x "$dir/$file") { return 1; } } return 0; } flamethrower-0.1.8/etc/0000755000000000000000000000000010366264761013503 5ustar rootrootflamethrower-0.1.8/etc/init.d/0000755000000000000000000000000010366264761014670 5ustar rootrootflamethrower-0.1.8/etc/init.d/flamethrower-server0000755000000000000000000000346507664742734020641 0ustar rootroot#!/bin/sh # # "Flamethrower" # # Copyright (C) 2003 Bald Guy Software # Brian E. Finley # # $Id: flamethrower-server 14 2003-05-27 20:09:00Z brianfinley $ # # # Support for IRIX style chkconfig: # chkconfig: 2345 20 20 # description: The Flamethrower multicast daemon. # # # Support for LSB compliant init system: ### BEGIN INIT INFO # Provides: flamethrowerd # Required-Start: $network $syslog # Required-Stop: # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Short-Description: Daemon for multicast file distribution # Description: Daemon for multicast file distribution # ### END INIT INFO kill_em_all() { if [ -f $PPID_FILE ]; then kill `cat $PPID_FILE` rm -f $PPID_FILE fi if [ "`ls $STATE_DIR`" != "" ]; then for PID_FILE in `ls ${STATE_DIR}/*` do if [ -f $PID_FILE ]; then kill -9 `cat $PID_FILE` rm -f $PID_FILE echo -n "." fi done kill_em_all fi } PATH=/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin: PPID_FILE=/var/run/flamethrower-server.pid # STATE_DIR must match the setting in the flamethrower.conf file. STATE_DIR=/var/state/flamethrower case "$1" in start) if [ -e $PPID_FILE ]; then echo "PID file $PPID_FILE exists. Must be already running." exit 1 fi echo -n "Starting Flamethrower daemon: flamethrowerd" flamethrowerd --config-file /etc/flamethrower/flamethrower.conf --pid-file $PPID_FILE echo "." ;; stop) echo -n "Stopping Flamethrower daemon: flamethrowerd" kill_em_all echo ;; reload) echo "Not implemented." ;; force-reload|restart) sh $0 stop sh $0 start ;; *) echo "Usage: $0 {start|stop|restart}" exit 1 ;; esac exit 0 flamethrower-0.1.8/etc/flamethrower.conf0000755000000000000000000002572710365306064017061 0ustar rootroot# # "Flamethrower" # # Copyright (C) 2003 Bald Guy Software # # $Id: flamethrower.conf 56 2006-01-24 02:08:52Z bli $ # # NOTE: For additional details on many of these settings, see # "man udp-sender". # ################################################################################ # # GLOBAL SETTINGS # ################################################################################ # # Starts the flamethrower daemon to allow multicast installs. (no man # page entry) # START_FLAMETHROWER_DAEMON = yes # # Port number where the Flamethrower configuration database can be # found on the Flamethrower server. (this is a udp-sender portbase # entry) # FLAMETHROWER_DIRECTORY_PORTBASE = 9000 # # The network interface on the Flamethrower server that used to send out # the data. # INTERFACE = eth0 # # PERFORMANCE OPTION! # # Limits bandwidth used by udpcast. Particularly useful in asynchronous # mode, or else the sender may send too fast for the switch and/or # receiver to keep up. Bitrate may be expressed in bits per second # (--bitrate 5000000), kilobits per second ("--bitrate 5000k") or # megabits per second ("--bitrate 5M"). This is the raw bitrate, # including packet headers, forward error correction, retransmissions, # etc. Actual payload bitrate will be lower. # # Here are some defaults that we've found to be generally acceptable # based on the slowest network link between your clients and your # server. # # 1000 Mbit # MAX_BITRATE = 1000M # # 100 Mbit MAX_BITRATE = 20M # # PERFORMANCE OPTION! # # Use this option if you *know* all the connections between your clients # and server will be running full-duplex network. If you enable this # setting, and are not on a full-duplex network, you man experience a # significant performance hit. # # On high-latency WAN links, the full-duplex option can lead to # substantial performance improvements, because it allows udp-sender to # send more data while it is still waiting for the previous batch to get # acknowledged. # FULL_DUPLEX = off # # Number of clients that must connect before the casting begins. # Superceeded if --max-client-wait times out. Default is 1. # MIN_CLIENTS = 1 # # Initiate the cast after SEC seconds, even if the number of clients # specified by --min-clients have yet to connect. # MAX_WAIT = 10 # # Wait at least SEC seconds before initiating the cast, even if the # number of clients specified by --min-clients have already connected. # MIN_WAIT = 5 # # Do not open target (disk) in synchronous mode. Useful when dumping # to a mounted filesystem, rather than to a raw partition. # NOSYNC = on # # Turns ugly debug information on. Use if things aren't working and you # can't figure out why -- it may help. # DEBUG = off # # Directory where flamethrower will keep it's directory information (in # sourceable shell script format). # FLAMETHROWER_DIRECTORY_DIR = /var/lib/flamethrower # # Directory where flamethrower will keep it's state information. # FLAMETHROWER_STATE_DIR = /var/state/flamethrower # # Starts transmission after N retransmissions of hello packet, with- # out waiting for a key stroke. Useful for unattended operation, where # udp-sender is started from a cron-job for a broadcast/multi-cast at # a scheduled time. # #AUTOSTART = 15 # # Packet size. The default (and maximum) is 1456. # #BLOCKSIZE = 1456 # # Use Ethernet broadcast, rather than multicast. Useful if you have # Ethernet cards which don't support multicast. # # By default, "udpcast" uses multicast. This allows sending the data # only to those receivers that requested it. Ethernet cards of machines # which don't participate in the transmission automatically block out # the packets at the hardware level. Moreover, network switches are # able to selectively transmit the packets only to those network ports # to which receivers are connected. Both features thus allow a much # more efficient operation than broadcast. This option should only be # supplied on the sender. # BROADCAST = off # # Enables forward error correction. The goal of forward error # correction is to transmit redundant data, in order to make up for # packets lost in transit. Indeed, in unidirectional mode, the receivers # have no way of requesting retransmission of lost packets, thus the # only way to address packet loss is to include redundant information to # begin with. The algorithm is designed in such a way that if # redundant packets are transmitted, that those can be used to # compensate for the loss of any r packets in the same FEC group # (stripe). # # In order to increase robustness of the FEC algorithm against burst # packet losses, each slice is divided in interleave stripes. Each # stripe has stripesize blocks (if not specified, stripesize is cal- # culated by diving slice-size by interleave). For each stripe, # redundancy FEC packets are added. Stripes are organized in such a # fashion that consecutive packets belong to different stripes. This # way, we ensure that burst losses affect different stripes, rather than # using all FEC packets of a single stripe. # # Comments from udpcast creator, Alain: # Udpcast supports FEC (forward error correction) mode, which should # make it suitable for monodirectional (or high latency) communication. # # The way it works is that for n data packets, k "error correction" are # computed, and also transmitted. The protocol can then compute all data # packets using _any_ n packets (for instance n-3 data packets and 3 # error correction packets). Thus, no acknowlegments are needed. # # Just start the sender with the --fec and --async options. # # With FEC, you can tune udpcast for whatever reliability you need (just # increase number of redundant packets per slice, or decrease number of # data packets). If you expect packet losse to come in bursts, you may # use interleaving. # # Regards, # # Alain # # Now with all that said, it appears as though FEC must be used at this # point, in order for SystemImager's flamethrower client to work properly. # -BEF- # # This setting should be specified in the form of: # # STRIPESxREDUNDANCY/STRIPESIZE # FEC = 8x8/128 # # Asynchronous mode. Do not request confirmations from the receiver. # Best used together with forward error correction and bandwidth lim- # itation, or else the receiver will abort the reception as soon as it # misses a packet. When the receiver aborts the reception in such a # way, it will print a list of packets lost in the slice causing the # problem. You can use this list to tune the forward error correction # parameters. # #ASYNC = off # # Logs some stuff into file. Module specific data goes into # "$LOG/$module_name". # LOG = /var/log/flamethrower # # Uses the given address for multicasting the data. If not specified, # the program will automatically derive a multicast address from its own # IP (by keeping the last 27 bits of the IP and then prepending 232). # # This setting should be specified in the form of: # # AAA.BBB.CCC.DDD # #MCAST_ADDR # # Uses a non-standard multicast address for the control connection # (which is used by the sender and receivers to "find" each other). # This is not the address that is used to transfer the data. # # By default "mcast-all-addr" is the Ethernet broadcast address if "ttl" # is 1, and 224.0.0.1 otherwise. This setting should not be used except # in very special situations, such as when 224.0.0.1 cannot be used for # policy reasons. # # This setting should be specified in the form of: # # AAA.BBB.CCC.DDD (224.0.0.1) # #MCAST_ALL_ADDR # # Slice size (expressed in blocks). Explicitly declare slice size. # #SLICE_SIZE = 16 # # Minimum slice size (expressed in blocks). When dynamically adjusting # slice size, never use smaller slices than this. Ignored when # "FULL_DUPLEX = on". # #MIN_SLICE_SIZE = 16 # # Maximum slice size (expressed in blocks). When dynamically adjusting # slice size, never use slices larger than this. Ignored when # "FULL_DUPLEX = on". # #MAX_SLICE_SIZE = 1024 # # Point-to-point mode. Only a single receiver is allowed, but the data # will be directly send to this receiver (in unicast mode), rather than # using multicast or broadcast. If "ASYNC = off", and there happens to # be only one receiver, point-to-point is activated automatically. # # If "POINTOPOINT = off", then unicast will not be used even if there is # only one receiver. # #POINTOPOINT = off # # If set, re-broadcasts the HELLO packet used for initiating the casting # every N milliseconds. # # This option is useful, together with "ASYNC = on", because with async mode # the receiver won't send a connection request to the sender (and hence # won't get a connection reply). In async mode, the receivers get all # the information about the cast from from the HELLO packet, and are thus # particularly dependant on the reception of this packet, making # re-transmission useful. # # This option is also useful on networks where packet loss is so high, # that even with connection requests, sender and receiver would not find # each other otherwise. # # Defaults to "0", but is automatically adjusted to "1000" if # "ASYNC = on", unless a non-zero value is specified here. # #REXMIT_HELLO_INTERVAL = 0 # # Sets the time-to-live parameter for the multicast packets. Should # theoretically allow one to use multicast beyond the local network, but # has not been thoroughly tested. # # The value specified here is the number of networks to which the multicast # should extend. Each hop (through a router) decrements this value by # one (1). If a packet enters a router with a value of one (1), it gets # decremented to zero (0), and is dropped before it leaves that router. # # In other words, if this is set to one (the default), your multicast # packets won't leave your immediate network. # #TTL = 1 ################################################################################ # # MODULE SPECIFIC SETTINGS # # Note: # The following settings are required for each module: # # [module-name] # DIR = /path/to/my/modules/directory/ # # # The following per module settings are optional. See comments # in the section above for details on these settings: # # B - PORTBASE # (automatically determined by flamethrowerd at run time # if not specified) # B - ASYNC # B - TTL # B - MCAST_ALL_ADDR # # S - LOG # S - INTERFACE # # C - NOSYNC # # Legend: # # B - This option is used by both client and server. # C - This option is only used by the client. # S - This option is only used by the client. # # # Also Note: # This file should not be edited directly, as it is managed by # SystemImager and is dynamically created. If you need to make a # modification to a module_entry, # ################################################################################ # # Modules # flamethrower-0.1.8/Makefile.PL0000644000000000000000000000303010365306064014666 0ustar rootrootuse ExtUtils::MakeMaker; use Carp; my $install = "./utils/install-N-sub --config ./utils/install-N-sub.conf"; my $version = `cat VERSION`; chomp $version; sub MY::postamble { my $string = < flamethrower-$version.tar.bz2 install :: set_ver install_configs EOF } WriteMakefile( 'VERSION' => $version, 'NAME' => 'Flamethrower', 'EXE_FILES' => [qw(bin/flamethrowerd bin/flamethrower)], 'dist' => { 'CI' => 'cvs ci', 'RCS_LABEL' => 'cvs up', }, 'INSTALLSITELIB' => '$(PREFIX)/lib/flamethrower', ); flamethrower-0.1.8/COPYING0000755000000000000000000004312507700102442013754 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. flamethrower-0.1.8/CREDITS0000644000000000000000000000170007720523146013741 0ustar rootroot# # "Flamethrower" # # Copyright (C) 2003 Brian Elliott Finley # # This is at least a partial credits-file of people that have contributed # to the Flamethrower project. It is sorted by name and formatted to allow # easy grepping and beautification by scripts. The fields are: name (N), # email (E), web-address (W), PGP key ID and fingerprint (P), description (D), # and snail-mail address (S). # # If you are not listed here, but should be, please send me an entry for # yourself. -Brian # N: Carlos Arevalo E: carlos.arevalo@hp.com D: Testing N: Brian Elliott Finley E: brian@bgsw.net W: http://thefinleys.com/ P: 1024D/10F8EE52 3FF8 D096 0E0C D3F3 29B7 6518 D20B 1931 10F8 EE52 D: Creator, Primary Author, and Project Lead S: 1718 Ironwood Drive S: Naperville, IL 60565 S: USA N: Dann Frazier E: dannf@fc.hp.com D: Initial design N: Gary B. Skouson E: gary.skouson@pnl.gov D: Initial design D: udpcast code flamethrower-0.1.8/README0000644000000000000000000000217507700203002013570 0ustar rootroot# # "Flamethrower" # # Copyright (C) 2003 Brian Elliott Finley # # $Id: README 32 2003-07-01 03:54:42Z dannf $ # What it is: Flamethrower is intended to be an easy to use multicast file distribution system. It was created to add multicast install capabilities to SystemImager, but was designed to be fully functional as a stand-alone package. Notable characteristics: 1) Works with entire directory heirarchies of files, not just single files. 2) Uses a server configuration file that takes module entries that are similar to those used by rsyncd.conf. 3) Flamethrower is an on-demand system. The multicast of a module is initiated when a client connects, but waits MIN_WAIT (conf file) for other clients to connect. If other clients try to connect after a cast has been initiated, they simply wait until that cast has finished, and catch the next one when it begins. 4) The udpcast package is used as the multicast transport, and offers a gob and a half of tuning parameters. Using Flamethrower: See the HOWTO. flamethrower-0.1.8/flamethrower.spec0000644000000000000000000000375210365306064016302 0ustar rootroot%define name flamethrower %define version 0.1.8 %define release 1 %define prefix /usr Summary: Flamethrower Name: %name Version: %version Release: %release License: GPL URL: http://systemimager.org Group: Applications/System Source: %{name}-%{version}.tar.bz2 BuildArchitectures: noarch Requires: /usr/bin/perl, udpcast Vendor: http://sisuite.org Packager: SIS Devel Team Prefix: %prefix Buildroot: /tmp/%{name}-%{version}-root AutoReqProv: no %description Multicast file transfer utility. %prep %setup %build perl Makefile.PL make %install [ "$RPM_BUILD_ROOT" != "/" ] && rm -fr $RPM_BUILD_ROOT make install PREFIX=$RPM_BUILD_ROOT%{prefix} PERLPREFIX=$RPM_BUILD_ROOT%{prefix} CONFDIR=$RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT%{prefix}/lib/flamethrower/auto/ find $RPM_BUILD_ROOT%{prefix} -name perllocal.pod | xargs rm -f %files %defattr(-,root,root) %{prefix}/bin/flamethrower %{prefix}/bin/flamethrowerd %{prefix}/lib/flamethrower/* %doc HOWTO README COPYING CREDITS %config /etc/flamethrower/flamethrower.conf %config /etc/init.d/flamethrower-server %dir /var/lib/flamethrower %dir /var/state/flamethrower %post %preun %changelog * Mon Jan 16 2006 Bernard Li - Added %dir /var/lib/flamethrower * Sat Dec 24 2005 Bernard Li - Added PERLPREFIX such that building RPM on systems with newer perl (5.8.5?) works - PREFIX is needed for backward compatability - Find the correct perllocal.pod file to delete instead of hardcoding it * Wed Dec 14 2005 Bernard Li - 0.1.7 release - added directory /var/state/flamethrower needed for /etc/init.d script * Wed Nov 26 2003 Brian Finley - 0.1.6 release - simplify spec file * Thu Jul 03 2003 dann frazier - fix 765028 - stop using %dir macros for system dirs * Sun Jul 01 2003 dann frazier - first package - based on systeminstaller's .spec file.