#!/usr/bin/perl -w
#
# run multiple squids.
#  If the command line options are for starting up and listening on a
#  socket, first opening a socket for them to share with squid -I.
#  If either one results in an error exit code, return the first error code.
# Writtten by Dave Dykstra, July 2007
#
use strict;
use Socket;
use IO::Handle;
use Fcntl;

if ($#ARGV < 2) {
  print STDERR "Usage: multisquid squidpath squidconfdir numsquids http_port [squid_args ...]\n";
  exit 2;
}

my $squidpath = shift(@ARGV);
my $squidconfdir = shift(@ARGV);
my $numsquids = shift(@ARGV);
my $port = shift(@ARGV);
my $proto = getprotobyname('tcp');

if (!(($#ARGV >= 0) && (($ARGV[0] eq "-k") || ($ARGV[0] eq "-z")))) {
  #open the socket for both squids to listen on if not doing an
  # operation that doesn't use the socket (that is, -k or -z)
  close STDIN;
  my $fd;
  socket($fd, PF_INET, SOCK_STREAM, $proto)	|| die "socket: $!";
  setsockopt($fd, SOL_SOCKET, SO_REUSEADDR, 1)    || die "setsockopt: $!";
  bind($fd, sockaddr_in($port, INADDR_ANY))	|| die "bind of port $port: $!";
}

my $childn;
for ($childn = 0; $childn < $numsquids; $childn++) {
  if (fork() == 0) {
    exec "$squidpath -f $squidconfdir/.squid-$childn.conf -I @ARGV" || die "exec: $!";
  }
  # get them to start at different times so they're identifiable by squidclient
  sleep 2;
}

my $exitcode = 0;
while(wait() > 0) {
  if (($? != 0) && ($exitcode == 0)) {
    # Take the first non-zero exit code and ignore the others.
    # exit expects a byte, but the exit code from wait() has signal
    #  numbers in low byte and exit code in high byte.  Combine them.
    $exitcode = ($? >> 8) | ($? & 255);
  }
}

exit $exitcode;
