#!/usr/bin/perl # usage: irclog.pl channel server port require 5.002; use strict; use Socket; my ($remote, $port, $iaddr, $paddr, $proto, $line); my $channel = shift; my $date; my $line; my @ilines; my $obuf = ''; my $ibuf = ''; my $tmp; my $quit = 0; my $readvec; my $writevec; my $nready; my $num_bytes; my $happy = 0; # send text (add to output queue) sub sock_send { $obuf .= shift; } sub min { my $a = shift; my $b = shift; if($a < $b) { return $a; } return $a; } sub date { my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime(time); return sprintf("%02d-%02d-%02d", $year % 100, $mon + 1, $mday); } $remote = shift || 'localhost'; $port = shift || 6667; # random port if ($port =~ /\D/) { $port = getservbyname($port, 'tcp'); } die "No port" unless $port; $iaddr = inet_aton($remote) || die "no host: $remote"; $paddr = sockaddr_in($port, $iaddr); $proto = getprotobyname('tcp'); socket(SOCK, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; connect(SOCK, $paddr) || die "connect: $!"; #open DLOG, ">log"; close STDIN; close STDOUT; close STDERR; sock_send("NICK herklog\r\nUSER herklogu 0 * :#c4th logs: http://jasonwoof.com/c4thlogs/\r\nJOIN #$channel\r\n"); $date = date; open LOG, ">>$channel/$date.txt" or exit 1; while(!$quit) { $readvec = ''; $writevec = ''; vec($readvec,fileno(SOCK),1) = 1; if($obuf ne '') { vec($writevec,fileno(SOCK),1) = 1; } else { $writevec = undef; } $nready = select($readvec, $writevec, undef, 180); if(!$nready) { # select timed out. This is not unusual, but we need to make # sure that we're still connected. After 3 minutes of # inactivity we send a ping. If we don't get a reply in another # 3 minutes, then we disconnect. if($happy) { # We _did_ recieve something 3 minutes ago, lets send a ping to make sure we're still connected. $happy = 0; sock_send("PING purplehatstre\n"); #syswrite(DLOG, "sending ping\n"); } else { # Not happy. We didn't recieve anything for 3 minutes after sending a ping. We must not really be connected. #syswrite(DLOG, "no ping reply\n"); $quit = 1; } } else { # data available on the socket for reading? if(vec($readvec, fileno(SOCK), 1)) { $happy = 1; $num_bytes = sysread(SOCK, $tmp, 2000); if($num_bytes == 0) { #syswrite(DLOG, "EOF\n"); $quit = 1; } $ibuf .= $tmp; #syswrite(DLOG, "recieved: $tmp\n"); # split our recived data into lines, leaving partial lines in $ibuf @ilines = split(/\r?\n/, $ibuf, -1); $ibuf = pop(@ilines); if(@ilines) { # be sure we're using the right logfile if($date ne date) { close LOG; $date = date; open LOG, ">>$channel/$date.txt" or exit 1; } foreach $line (@ilines) { if($line =~ s/^PING ([^ ]*).*$/$1/s) { # no sense in putting pings into the log. sock_send("PONG $line\r\n"); } elsif ($line =~ /^PONG/) { # don't log replies to our keep-alive pings } else { # everything else we log as is syswrite LOG, $line . "\n", 100000; #if($line =~ /quit$/) { # $quit = 1; #} } } } } # socket writeable? if(vec($writevec, fileno(SOCK), 1)) { $num_bytes = syswrite(SOCK, $obuf, min(2000, length($obuf))); #syswrite(DLOG, "wrote " . substr($obuf, 0, $num_bytes) . "\n"); $obuf = substr($obuf, $num_bytes); } } } close(SOCK); sleep 300; exit;