
<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://kb.speeddemosarchive.com/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
		<id>https://kb.speeddemosarchive.com/index.php?action=history&amp;feed=atom&amp;title=Amu-chan%2FSource%2Famu.pl</id>
		<title>Amu-chan/Source/amu.pl - Revision history</title>
		<link rel="self" type="application/atom+xml" href="https://kb.speeddemosarchive.com/index.php?action=history&amp;feed=atom&amp;title=Amu-chan%2FSource%2Famu.pl"/>
		<link rel="alternate" type="text/html" href="https://kb.speeddemosarchive.com/index.php?title=Amu-chan/Source/amu.pl&amp;action=history"/>
		<updated>2026-06-05T07:34:10Z</updated>
		<subtitle>Revision history for this page on the wiki</subtitle>
		<generator>MediaWiki 1.23.9</generator>

	<entry>
		<id>https://kb.speeddemosarchive.com/index.php?title=Amu-chan/Source/amu.pl&amp;diff=2582&amp;oldid=prev</id>
		<title>Njahnke: New page: &lt;pre&gt;&lt;nowiki&gt; #!/usr/bin/perl #nathan jahnke &lt;njahnke@gmail.com&gt;  ### ATASHI NO KOKORO, UNLOCK! ###  # Amu is distributed under the terms of the Gnu General Public License 3.0: # http://ww...</title>
		<link rel="alternate" type="text/html" href="https://kb.speeddemosarchive.com/index.php?title=Amu-chan/Source/amu.pl&amp;diff=2582&amp;oldid=prev"/>
				<updated>2008-10-12T05:37:49Z</updated>
		
		<summary type="html">&lt;p&gt;New page: &amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt; #!/usr/bin/perl #nathan jahnke &amp;lt;njahnke@gmail.com&amp;gt;  ### ATASHI NO KOKORO, UNLOCK! ###  # Amu is distributed under the terms of the Gnu General Public License 3.0: # http://ww...&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
#!/usr/bin/perl&lt;br /&gt;
#nathan jahnke &amp;lt;njahnke@gmail.com&amp;gt;&lt;br /&gt;
&lt;br /&gt;
### ATASHI NO KOKORO, UNLOCK! ###&lt;br /&gt;
&lt;br /&gt;
# Amu is distributed under the terms of the Gnu General Public License 3.0:&lt;br /&gt;
# http://www.gnu.org/licenses/gpl-3.0.txt&lt;br /&gt;
&lt;br /&gt;
#TODO&lt;br /&gt;
##delimiter is whatever the first character in a new queue is&lt;br /&gt;
##alternative jobs based on os&lt;br /&gt;
##encryption?&lt;br /&gt;
&lt;br /&gt;
use warnings;&lt;br /&gt;
use strict 'subs';&lt;br /&gt;
package amu;&lt;br /&gt;
&lt;br /&gt;
use IO::Socket;&lt;br /&gt;
use Sys::Hostname;&lt;br /&gt;
use Sys::HostIP;&lt;br /&gt;
use threads;&lt;br /&gt;
use threads::shared;&lt;br /&gt;
#use Thread::Queue;&lt;br /&gt;
use List::Util qw(shuffle);&lt;br /&gt;
use Cwd qw(abs_path);&lt;br /&gt;
&lt;br /&gt;
$myversion = 44;&lt;br /&gt;
$VERBOSE = 1;&lt;br /&gt;
$amudelim = &amp;quot;;&amp;quot;; #this currently delimits only jobs and their indices (keys as a hash) in the queue&lt;br /&gt;
$port = 56677;&lt;br /&gt;
$myip = Sys::HostIP-&amp;gt;ip;&lt;br /&gt;
$mypath = abs_path($0);&lt;br /&gt;
my %amustatus :shared = ();&lt;br /&gt;
&lt;br /&gt;
open(AMUPL,$mypath);&lt;br /&gt;
@amupl = &amp;lt;AMUPL&amp;gt;;&lt;br /&gt;
close(AMUPL);&lt;br /&gt;
&lt;br /&gt;
@remote_hosts = ();&lt;br /&gt;
if (-e &amp;quot;amu_remotehosts.txt&amp;quot;) {&lt;br /&gt;
	open(REMOTEHOSTS,&amp;quot;amu_remotehosts.txt&amp;quot;);&lt;br /&gt;
	while (&amp;lt;REMOTEHOSTS&amp;gt;) {&lt;br /&gt;
		chomp;&lt;br /&gt;
		if (($_ ne $myip) &amp;amp;&amp;amp; (!($_ =~ /^#/))) {&lt;br /&gt;
			push(@remote_hosts,$_) if $_;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	close(REMOTEHOSTS);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#intercept ctrl-c or kill from cli&lt;br /&gt;
$SIG{INT} = $SIG{TERM} = \&amp;amp;amushutdown;&lt;br /&gt;
$SIG{HUP} = \&amp;amp;amurestart;&lt;br /&gt;
&lt;br /&gt;
my %amuhash :shared = (); #it needs the my for some reason!?&lt;br /&gt;
{ #lock and load&lt;br /&gt;
	lock(%amuhash);&lt;br /&gt;
	$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;OK&amp;quot;;&lt;br /&gt;
	$amuhash{&amp;quot;VERSION&amp;quot;} = $myversion;&lt;br /&gt;
	$amuhash{&amp;quot;QUEUE&amp;quot;} = &amp;quot;&amp;quot;;&lt;br /&gt;
	$amuhash{&amp;quot;JOB&amp;quot;} = &amp;quot;&amp;quot;;&lt;br /&gt;
	$amuhash{&amp;quot;REMOTE_HOSTS&amp;quot;} = join(&amp;quot; &amp;quot;,@remote_hosts);&lt;br /&gt;
}&lt;br /&gt;
print &amp;quot;starting server_thread ...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
$server_thread = threads-&amp;gt;create(\&amp;amp;server_thread);&lt;br /&gt;
&lt;br /&gt;
#status updates every 5 seconds&lt;br /&gt;
print &amp;quot;starting status_threads_infinite_loop ...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
threads-&amp;gt;create(\&amp;amp;status_threads_infinite_loop);&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Amu version $myversion started successfully!\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
while ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /OK|QUEUEING|JANKEN|WORKING/) {&lt;br /&gt;
	#update @remote_hosts - don't want to have to lock %amuhash every time we contact people&lt;br /&gt;
	{&lt;br /&gt;
		lock(%amuhash);&lt;br /&gt;
		@remote_hosts = split(&amp;quot; &amp;quot;,$amuhash{&amp;quot;REMOTE_HOSTS&amp;quot;});&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /QUEUEING/) {&lt;br /&gt;
		print &amp;quot;entering status mode block QUEUEING\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		if ($amuhash{&amp;quot;QUEUE&amp;quot;} ne '') {&lt;br /&gt;
			#distribute the queue to all known other amus ... a lot will get it and ignore because they're already in QUEUEING mode but this will help ensure everyone gets it - BEFORE we claim a job&lt;br /&gt;
			threads-&amp;gt;create(\&amp;amp;status_threads, &amp;quot;DO &amp;quot;.$amuhash{&amp;quot;QUEUE&amp;quot;}, @remote_hosts)-&amp;gt;join();&lt;br /&gt;
			my $jobnum;&lt;br /&gt;
			if ($amuhash{&amp;quot;QUEUE&amp;quot;} ne '') { #check again to make sure our queue hasn't been emptied since we sent the queue to others&lt;br /&gt;
				{&lt;br /&gt;
					print &amp;quot;about to lock the hash...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
					lock(%amuhash);&lt;br /&gt;
					print &amp;quot;locked the hash\n&amp;quot; if $VERBOSE;&lt;br /&gt;
					my %jobs = split($amudelim,$amuhash{&amp;quot;QUEUE&amp;quot;});&lt;br /&gt;
					#pick random queue item&lt;br /&gt;
					my @joblist = (%jobs);&lt;br /&gt;
					$jobnum = int(rand(keys %jobs));&lt;br /&gt;
					$jobnum = $joblist[$jobnum*2];&lt;br /&gt;
					#claim it&lt;br /&gt;
					print &amp;quot;claiming job $jobnum\n&amp;quot; if $VERBOSE;&lt;br /&gt;
					$amuhash{&amp;quot;JOB&amp;quot;} = $jobnum;&lt;br /&gt;
					#and get ready to fight for it&lt;br /&gt;
					$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;JANKEN&amp;quot;;&lt;br /&gt;
				}&lt;br /&gt;
				#sleep 5;&lt;br /&gt;
				%objections = &amp;amp;status_threads(&amp;quot;CLAIM &amp;quot;.$jobnum, @remote_hosts);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		if ($amuhash{&amp;quot;STATUS&amp;quot;} ne &amp;quot;JANKEN&amp;quot;) { #no more jobs for us to do&lt;br /&gt;
			print &amp;quot;no more jobs for us to do\n&amp;quot; if $VERBOSE;&lt;br /&gt;
			lock(%amuhash);&lt;br /&gt;
			$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;OK&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	if ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /JANKEN/) {&lt;br /&gt;
		print &amp;quot;entering status mode block JANKEN\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		if (%objections) {&lt;br /&gt;
			foreach $evilhost (keys %objections) {&lt;br /&gt;
				last if $amuhash{&amp;quot;STATUS&amp;quot;} eq &amp;quot;QUEUEING&amp;quot;; #i've already lost&lt;br /&gt;
				#generate my random number&lt;br /&gt;
				$random = rand();&lt;br /&gt;
				$random =~ s/^0.//;&lt;br /&gt;
				{&lt;br /&gt;
					lock(%amuhash);&lt;br /&gt;
					$amuhash{&amp;quot;JANKEN&amp;quot;} = $random;&lt;br /&gt;
				}&lt;br /&gt;
				#broadcast&lt;br /&gt;
				print &amp;quot;asking for janken - job $amuhash{JOB}\n&amp;quot; if $VERBOSE;&lt;br /&gt;
				my @janken = &amp;amp;status_threads(&amp;quot;JANKEN&amp;quot;, $evilhost);&lt;br /&gt;
				if (@janken) { #did anyone play with me?&lt;br /&gt;
					if ($janken[1] &amp;gt; $random) { #i lost&lt;br /&gt;
						print &amp;quot;i lost at janken\n&amp;quot; if $VERBOSE;&lt;br /&gt;
						lock(%amuhash);&lt;br /&gt;
						my %jobs = split($amudelim,$amuhash{&amp;quot;QUEUE&amp;quot;});&lt;br /&gt;
						if (exists($jobs{$amuhash{&amp;quot;JOB&amp;quot;}})) {&lt;br /&gt;
							#give this job up&lt;br /&gt;
							delete($jobs{$amuhash{&amp;quot;JOB&amp;quot;}});&lt;br /&gt;
							$amuhash{&amp;quot;QUEUE&amp;quot;} = join($amudelim,%jobs);&lt;br /&gt;
						}&lt;br /&gt;
						print &amp;quot;trying to get another job; changing status back to QUEUEING ...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
						$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;QUEUEING&amp;quot;; #try to get another job&lt;br /&gt;
					} elsif ($janken[1] == $random) { #a tie&lt;br /&gt;
						print &amp;quot;a tie at janken!?\n&amp;quot; if $VERBOSE;&lt;br /&gt;
						redo;&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					print &amp;quot;no responses for janken\n&amp;quot; if $VERBOSE;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			{&lt;br /&gt;
				lock(%amuhash);&lt;br /&gt;
				undef $amuhash{&amp;quot;JANKEN&amp;quot;};&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		{&lt;br /&gt;
			lock(%amuhash);&lt;br /&gt;
			$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;WORKING&amp;quot; if $amuhash{&amp;quot;STATUS&amp;quot;} ne &amp;quot;QUEUEING&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	if ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /WORKING/) {&lt;br /&gt;
		print &amp;quot;entering status mode block WORKING\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		my ($jobnum, %jobs);&lt;br /&gt;
		{&lt;br /&gt;
			lock(%amuhash);&lt;br /&gt;
			%jobs = split($amudelim,$amuhash{&amp;quot;QUEUE&amp;quot;});&lt;br /&gt;
			$jobnum = $amuhash{&amp;quot;JOB&amp;quot;};&lt;br /&gt;
		}&lt;br /&gt;
		#run the command&lt;br /&gt;
		print &amp;quot;executing $jobs{$jobnum} ...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		system($jobs{$jobnum});&lt;br /&gt;
		#all dun&lt;br /&gt;
		{&lt;br /&gt;
			lock(%amuhash);&lt;br /&gt;
			my %jobs = split($amudelim,$amuhash{&amp;quot;QUEUE&amp;quot;});&lt;br /&gt;
			delete($jobs{$amuhash{&amp;quot;JOB&amp;quot;}});&lt;br /&gt;
			$amuhash{&amp;quot;QUEUE&amp;quot;} = join($amudelim,%jobs);&lt;br /&gt;
			$amuhash{&amp;quot;JOB&amp;quot;} = &amp;quot;&amp;quot;;&lt;br /&gt;
			$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;QUEUEING&amp;quot;;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	sleep 1;&lt;br /&gt;
}&lt;br /&gt;
sleep 15;&lt;br /&gt;
exec($mypath) if ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /RESTART/);&lt;br /&gt;
exit 0 if ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /SHUTDOWN/);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
sub version_check {&lt;br /&gt;
	print &amp;quot;Checking the network for a newer version of Amu ...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
	{&lt;br /&gt;
		lock(%amustatus);&lt;br /&gt;
		@knowngoodamus = (keys %amustatus);&lt;br /&gt;
	}&lt;br /&gt;
	%hostversions = &amp;amp;status_threads(&amp;quot;VERSION&amp;quot;, @knowngoodamus);&lt;br /&gt;
	foreach $amuversion (sort { $a &amp;lt; $b } keys %hostversions) {&lt;br /&gt;
		print &amp;quot;$amuversion : $hostversions{$amuversion}\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		if ($amuversion &amp;gt; $myversion) {&lt;br /&gt;
			&amp;amp;status_threads(&amp;quot;AMUPL&amp;quot;, $hostversions{$amuversion});&lt;br /&gt;
			last;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub status_threads_infinite_loop {&lt;br /&gt;
	while ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /OK|QUEUEING|JANKEN|WORKING/) {&lt;br /&gt;
		if ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /OK/) {&lt;br /&gt;
			{&lt;br /&gt;
				lock(%amuhash);&lt;br /&gt;
				@remote_hosts = split(&amp;quot; &amp;quot;,$amuhash{&amp;quot;REMOTE_HOSTS&amp;quot;});&lt;br /&gt;
			}&lt;br /&gt;
			@remote_hosts = shuffle(@remote_hosts);&lt;br /&gt;
			my ($status_thread) = threads-&amp;gt;create(\&amp;amp;status_threads, &amp;quot;STATUS&amp;quot;, @remote_hosts);&lt;br /&gt;
			my %foundamus = $status_thread-&amp;gt;join();&lt;br /&gt;
			{&lt;br /&gt;
				lock(%amustatus);&lt;br /&gt;
				%amustatus = %foundamus;&lt;br /&gt;
			}&lt;br /&gt;
			&amp;amp;version_check;&lt;br /&gt;
		}&lt;br /&gt;
		sleep 5;&lt;br /&gt;
	}&lt;br /&gt;
	print &amp;quot;status_threads_infinite_loop shutting down\n&amp;quot; if $VERBOSE;&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub status_threads {&lt;br /&gt;
	my $command = shift;&lt;br /&gt;
	my %threads;&lt;br /&gt;
	my %foundamus; #temporary hash to avoid locking the shared one while we build up responses&lt;br /&gt;
	foreach $remote_host (@_) {&lt;br /&gt;
		($threads{$remote_host}) = threads-&amp;gt;create(\&amp;amp;hostname_contact, $command, $remote_host);&lt;br /&gt;
	}&lt;br /&gt;
	foreach $remote_host (keys %threads) {&lt;br /&gt;
		@remote_response = $threads{$remote_host}-&amp;gt;join();&lt;br /&gt;
		if (defined $remote_response[2]) { #not an error&lt;br /&gt;
			if ($remote_response[1] =~ /AMUPL/) {&lt;br /&gt;
				shift(@remote_response); #kill the remote host&lt;br /&gt;
				shift(@remote_response); #kill the command&lt;br /&gt;
				for (@remote_response) { #make sure this is the entire amu.pl&lt;br /&gt;
					$amuplgood = 1 if m/^__END__/;&lt;br /&gt;
				}&lt;br /&gt;
				if ($amuplgood) {&lt;br /&gt;
					open(NEWAMUPL,&amp;quot;&amp;gt;$mypath&amp;quot;);&lt;br /&gt;
					for (@remote_response) { #and print the new script&lt;br /&gt;
						print NEWAMUPL;&lt;br /&gt;
					}&lt;br /&gt;
					close(NEWAMUPL);&lt;br /&gt;
					print &amp;quot;Upgraded to a new version of Amu! Restarting Amu in 15 seconds ...\n&amp;quot;;&lt;br /&gt;
					{&lt;br /&gt;
						lock(%amuhash);&lt;br /&gt;
						$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;RESTART&amp;quot;;&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			} elsif ($remote_response[1] =~ /VERSION/) {&lt;br /&gt;
				#backwards so that the version is the key and the host is the value: we want only one host - the first to reply - per version&lt;br /&gt;
				if (!(exists($foundamus{$remote_response[2]}))) {&lt;br /&gt;
					$foundamus{$remote_response[2]} = $remote_response[0];&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				$foundamus{$remote_response[0]} = $remote_response[2];&lt;br /&gt;
			}&lt;br /&gt;
		} else {&lt;br /&gt;
			#handle errors&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return %foundamus;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub hostname_contact {&lt;br /&gt;
	my $command = shift;&lt;br /&gt;
	my $remote_host = shift;&lt;br /&gt;
	my @retval = ($remote_host);&lt;br /&gt;
	print &amp;quot;trying $remote_host ...\n&amp;quot; if $VERBOSE;&lt;br /&gt;
	$| = 1 if $VERBOSE; #flush output buffer&lt;br /&gt;
	if (my $socket = IO::Socket::INET-&amp;gt;new(PeerAddr =&amp;gt; $remote_host,&lt;br /&gt;
					PeerPort =&amp;gt; $port,&lt;br /&gt;
					Proto    =&amp;gt; &amp;quot;tcp&amp;quot;,&lt;br /&gt;
					Type     =&amp;gt; SOCK_STREAM,&lt;br /&gt;
					Timeout  =&amp;gt; 5 )) {&lt;br /&gt;
		print $socket &amp;quot;AMU $command\n&amp;quot;;&lt;br /&gt;
		my @answer = &amp;lt;$socket&amp;gt;;&lt;br /&gt;
		print &amp;quot;contact with $remote_host\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		my $firstline = $answer[0];&lt;br /&gt;
		if ($firstline) {&lt;br /&gt;
			chomp($firstline);&lt;br /&gt;
			@remote_host_status = split(&amp;quot; &amp;quot;,$firstline);&lt;br /&gt;
			$SYNTAX_ERROR_BAD_ARGUMENT = &amp;quot;SYNTAX_ERROR_BAD_ARGUMENT&amp;quot;;&lt;br /&gt;
			if (($remote_host_status[0] =~ /AMU/) &amp;amp;&amp;amp; (defined $remote_host_status[1]) &amp;amp;&amp;amp; (defined $remote_host_status[2])) {&lt;br /&gt;
				if ($remote_host_status[1] =~ /STATUS/) {&lt;br /&gt;
					if ($remote_host_status[2] =~ /OK|QUEUEING|JANKEN|WORKING/) {&lt;br /&gt;
						push(@retval, $remote_host_status[1], $remote_host_status[2]);&lt;br /&gt;
					} else {&lt;br /&gt;
						push(@retval, $SYNTAX_ERROR_BAD_ARGUMENT);&lt;br /&gt;
					}&lt;br /&gt;
				} elsif ($remote_host_status[1] =~ /VERSION|CLAIM|JANKEN/) {&lt;br /&gt;
					if (defined $remote_host_status[2]) {&lt;br /&gt;
						push(@retval, $remote_host_status[1], join(&amp;quot; &amp;quot;,@remote_host_status[2..$#remote_host_status]));&lt;br /&gt;
					} else {&lt;br /&gt;
						push(@retval, $SYNTAX_ERROR_BAD_ARGUMENT);&lt;br /&gt;
					}&lt;br /&gt;
				} elsif ($remote_host_status[1] =~ /AMUPL/) {&lt;br /&gt;
					if ($remote_host_status[2] =~ m,#!/usr/bin/perl,) {&lt;br /&gt;
						push(@retval, $remote_host_status[1], $remote_host_status[2].&amp;quot;\n&amp;quot;);&lt;br /&gt;
						shift(@answer); #don't need the first line again&lt;br /&gt;
						push(@retval, @answer);&lt;br /&gt;
					} else {&lt;br /&gt;
						push(@retval, $SYNTAX_ERROR_BAD_ARGUMENT);&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					push(@retval, &amp;quot;SYNTAX_ERROR_BAD_COMMAND&amp;quot;);&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				push(@retval, &amp;quot;NOT_AMU&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		close($socket);&lt;br /&gt;
	} else {&lt;br /&gt;
		print &amp;quot;\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		push(@retval, &amp;quot;CONNECTION_REFUSED_OR_TIMED_OUT&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	return @retval;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub server_thread {&lt;br /&gt;
	$server = IO::Socket::INET-&amp;gt;new(LocalPort =&amp;gt; $port,&lt;br /&gt;
					Type      =&amp;gt; SOCK_STREAM,&lt;br /&gt;
					Reuse     =&amp;gt; 1,&lt;br /&gt;
					Listen    =&amp;gt; 10)&lt;br /&gt;
		or die &amp;quot;Couldn't be a tcp server on port $port : $@\n&amp;quot;;&lt;br /&gt;
		&lt;br /&gt;
	while ($amuhash{&amp;quot;STATUS&amp;quot;} =~ /OK|QUEUEING|JANKEN|WORKING/) {&lt;br /&gt;
		$client = $server-&amp;gt;accept();&lt;br /&gt;
		recv($client, $question, 1024, 0);&lt;br /&gt;
		chomp($question);&lt;br /&gt;
		print &amp;quot;$question\n&amp;quot; if $VERBOSE;&lt;br /&gt;
		@remote_question = split(&amp;quot; &amp;quot;,$question);&lt;br /&gt;
		if ($remote_question[0] =~ /AMU/) {&lt;br /&gt;
			lock(%amuhash);&lt;br /&gt;
			if (defined $amuhash{$remote_question[1]}) {&lt;br /&gt;
				print $client &amp;quot;AMU $remote_question[1] $amuhash{$remote_question[1]}\n&amp;quot;;&lt;br /&gt;
			} elsif ($remote_question[1] =~ /AMUPL/) {&lt;br /&gt;
				print $client &amp;quot;AMU $remote_question[1] &amp;quot;;&lt;br /&gt;
				for (@amupl) {&lt;br /&gt;
					print $client $_;&lt;br /&gt;
				}&lt;br /&gt;
				print $client &amp;quot;\n&amp;quot;; #just in case there's no carriage return at the end of amu.pl&lt;br /&gt;
			} elsif (($remote_question[1] =~ /HOSTS/) &amp;amp;&amp;amp; (defined $remote_question[2])) {&lt;br /&gt;
				print &amp;quot;received new host list\n&amp;quot; if $VERBOSE;&lt;br /&gt;
				my %newhosts = split(&amp;quot;;&amp;quot;,$remote_question[2]);&lt;br /&gt;
				$newhosts{$myip} = 1; #sign off that i have seen this list&lt;br /&gt;
				my @ignoranthosts;&lt;br /&gt;
				@remote_hosts = ();&lt;br /&gt;
				foreach $host (keys %newhosts) {&lt;br /&gt;
					push(@remote_hosts,$host) if $host ne $myip;&lt;br /&gt;
					if (!($newhosts{$host})) { #these haven't heard about the new host list yet&lt;br /&gt;
						print &amp;quot;$host hasn't yet heard about the new host list\n&amp;quot; if $VERBOSE;&lt;br /&gt;
						push(@ignoranthosts,$host);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
				$amuhash{&amp;quot;REMOTE_HOSTS&amp;quot;} = join(&amp;quot; &amp;quot;,@remote_hosts);&lt;br /&gt;
				&amp;amp;status_threads(&amp;quot;HOSTS &amp;quot;.join(&amp;quot;;&amp;quot;,%newhosts), @ignoranthosts);&lt;br /&gt;
			} elsif (($remote_question[1] =~ /DO/) &amp;amp;&amp;amp; ($amuhash{&amp;quot;STATUS&amp;quot;} eq &amp;quot;OK&amp;quot;) &amp;amp;&amp;amp; (defined $remote_question[2])) {&lt;br /&gt;
				my $remote_jobs = join(&amp;quot; &amp;quot;,@remote_question[2..$#remote_question]);&lt;br /&gt;
				print &amp;quot;new job queue '$remote_jobs' has arrived\n&amp;quot; if $VERBOSE;&lt;br /&gt;
				#new job queue has arrived&lt;br /&gt;
				$amuhash{&amp;quot;QUEUE&amp;quot;} = $remote_jobs;&lt;br /&gt;
				$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;QUEUEING&amp;quot;;&lt;br /&gt;
			} elsif (($remote_question[1] =~ /CLAIM/) &amp;amp;&amp;amp; ($amuhash{&amp;quot;QUEUE&amp;quot;} ne '') &amp;amp;&amp;amp; (defined $remote_question[2])) {&lt;br /&gt;
				my $remote_job = join(&amp;quot; &amp;quot;,@remote_question[2..$#remote_question]);&lt;br /&gt;
				if ($amuhash{&amp;quot;JOB&amp;quot;} eq $remote_job) {&lt;br /&gt;
					#no! that's my job!&lt;br /&gt;
					print &amp;quot;objecting to job $remote_job\n&amp;quot; if $VERBOSE;&lt;br /&gt;
					print $client &amp;quot;AMU &amp;quot;.join(&amp;quot; &amp;quot;,@remote_question[1..$#remote_question]).&amp;quot;\n&amp;quot;;&lt;br /&gt;
				} else {&lt;br /&gt;
					my %jobs = split($amudelim,$amuhash{&amp;quot;QUEUE&amp;quot;});&lt;br /&gt;
					if (exists($jobs{$remote_job})) {&lt;br /&gt;
						#since i have no objections about others claiming this job...&lt;br /&gt;
						print &amp;quot;deleting job $remote_job\n&amp;quot; if $VERBOSE;&lt;br /&gt;
						delete($jobs{$remote_job});&lt;br /&gt;
						$amuhash{&amp;quot;QUEUE&amp;quot;} = join($amudelim,%jobs);&lt;br /&gt;
					}&lt;br /&gt;
				}&lt;br /&gt;
			} else {&lt;br /&gt;
				#cool and spicy&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		close($client);&lt;br /&gt;
	}&lt;br /&gt;
	close($server);&lt;br /&gt;
	print &amp;quot;server_thread shutting down\n&amp;quot; if $VERBOSE;&lt;br /&gt;
	return;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub amurestart {&lt;br /&gt;
	{&lt;br /&gt;
		lock(%amuhash);&lt;br /&gt;
		$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;RESTART&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	&amp;amp;hostname_contact(&amp;quot;SHUTDOWN&amp;quot;,$myip); #to knock the server thread out of its infinite loop&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sub amushutdown {&lt;br /&gt;
	$| = 1;&lt;br /&gt;
	print &amp;quot;Shutting down in about 15 seconds ...&amp;quot;;&lt;br /&gt;
	{&lt;br /&gt;
		lock(%amuhash);&lt;br /&gt;
		$amuhash{&amp;quot;STATUS&amp;quot;} = &amp;quot;SHUTDOWN&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	&amp;amp;hostname_contact(&amp;quot;SHUTDOWN&amp;quot;,$myip); #to knock the server thread out of its infinite loop&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
__END__&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Njahnke</name></author>	</entry>

	</feed>