#!/bin/perl -w
# $Id: killplum 81 2003-03-22 16:39:56Z tach $
# copyright (c)1998-1999 Yoshinori Hasegawa <hasegawa@madoka.org>

$NAME = 'plum';

if ($] < 5) {
  foreach $inc (@INC) {
    if (-r "$inc/sys/socket.ph") {
      eval 'require "sys/socket.ph"';
      $SOCKET = "$inc/sys/socket.ph" unless $@;
      last;
    }
    if (-r "$inc/socket.ph") {
      eval 'require "socket.ph"';
      $SOCKET = "$inc/socket.ph" unless $@;
      last;
    }
  }
} else {
  eval 'use Socket';
  $SOCKET = 'Socket.pm' unless $@;
}

$NIL = $;;

$NOTRAILING = &'list('004', '215', '221', '324', '341', '367', 'mode');

$IRCPORT = 6667;
$SOCKADDR = 'S n N x8';

$PROTO = (getprotobyname('tcp'))[2];

$AF_INET = eval '&AF_INET' || 2;
$PF_INET = eval '&PF_INET' || 2;
$SOCK_STREAM = eval '&SOCK_STREAM' || 1;

$'rin = '';

$handle = 0;

&main(@ARGV);

sub main {
  local(@args) = @_;
  local($path);
  if ($0 =~ /^(.*)[\\\/][^\\\/]*$/) {
    $path =  "$1/..";
  } else {
    $path = '..';
  }
  &load("$path/$NAME.conf") if -r "$path/$NAME.conf";
  &load("$NAME.conf") if -r "$NAME.conf";
  foreach $user (@args) {
    &load("$path/$NAME-$user.conf") if -r "$path/$NAME-$user.conf";
    &load("$NAME-$user.conf") if -r "$NAME-$user.conf";
  }
}

sub load {
  local($file) = @_;
  local($line, $var, $arg, $host, $pass, $name, $port);
  open(FILE, $file) || return;
  while (defined($line = <FILE>)) {
    $line =~ s/^\s+//;
    next if $line =~ /^[\#\;]/;
    $line =~ tr/\r\n//d;
    next unless $line;
    $line =~ s/\s+$//;
    if (!($line =~ /^[\+\-\=]\s*(\S+)/)) {
      if ((($var, $arg) = split(/\s*\:\s*/, $line, 2)) == 2) {
        if ($var eq 'plum.client') {
          ($host, $pass) = split(/\s+/, $arg, 2);
          ($name, $port) = split(/\:/, $host, 2);
          $port = $IRCPORT unless $port;
          &exit($port, $pass || '');
        }
      }
    }
  }
  close(FILE);
}

sub exit {
  local($port, $pass) = @_;
  local($no);
  if ($no = &'connect("127.0.0.1", $port)) {
    &print($no, &'build('', 'PASS', $pass));
    &print($no, &'build('', 'NICK', $NAME));
    &print($no, &'build('', 'USER', $NAME, '*', '*', $NAME));
    &print($no, &'build('', 'EXIT', $NAME));
  }
}

sub print {
  local($no, $str) = @_;
  local($socket);
  $socket = $'socket[$no];
  print $socket $str;
}

sub 'build {
  local($prefix, $cmd, @params) = @_;
  local($trailing);
  return '' unless $cmd;
  if (@params) {
    $trailing = pop(@params) || '';
    if (&'exist($NOTRAILING, "\L$cmd\E")) {
      push(@params, "$trailing ");
    } else {
      push(@params, ":$trailing");
    }
  } else {
    @params = ();
  }
  unshift(@params, $cmd);
  unshift(@params, ":$prefix") if $prefix;
  return join(' ', @params) . "\r\n";
}

sub 'exist {
  local($list, @items) = @_;
  return 0 unless $list;
  $list .= $NIL;
  foreach $item (@items) {
    return 1 if index("\L$list\E", $NIL . "\L$item\E" . $NIL) != -1;
  }
  return 0;
}

sub 'list {
  local(@array) = @_;
  return join($NIL, '', @array);
}

sub 'connect {
  local($host, $port) = @_;
  local($serverno, $socket, $ip, @addr, $name);
  if ($host =~ /^\d+$/) {
    $ip = $host;
  } elsif ($host =~ /^[\d\.]+$/) {
    @addr = split(/\./, $host);
    $ip = unpack('N', pack('C4', @addr, 0, 0, 0));
  } else {
    $ip = unpack('N', (gethostbyname($host))[4] || "\0\0\0\0");
  }
  return 0 unless $ip;
  $socket = '\'S' . ++$handle;
  socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0;
  $name = pack($SOCKADDR, $AF_INET, $port, $ip);
  connect($socket, $name) || return 0;
  binmode($socket);
  $serverno = fileno($socket);
  vec($'rin, $serverno, 1) = 1;
  $'socket[$serverno] = $socket;
  select((select($socket), $| = 1)[0]);
  return $serverno;
}
