diff options
author | Timo Sirainen <cras@irssi.org> | 2002-03-10 21:28:38 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2002-03-10 21:28:38 +0000 |
commit | 03c71116e044fda9d99e827a4ffb0652d508abb5 (patch) | |
tree | df36506fb09ad6563feaf394a0a47728348cadd6 /scripts/dns.pl | |
parent | 1855e6cc5c84ec861bf1301c09841cb2fd9ad718 (diff) | |
download | irssi-03c71116e044fda9d99e827a4ffb0652d508abb5.zip |
added/removed some default scripts
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@2569 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'scripts/dns.pl')
-rw-r--r-- | scripts/dns.pl | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/scripts/dns.pl b/scripts/dns.pl new file mode 100644 index 00000000..612fab0e --- /dev/null +++ b/scripts/dns.pl @@ -0,0 +1,193 @@ +# /DNS <nick>|<host>|<ip> ... + +use Irssi; +use strict; +use Socket; +use POSIX; + +use vars qw($VERSION %IRSSI); +$VERSION = "2.1"; +%IRSSI = ( + authors => 'Timo Sirainen', + name => 'dns', + description => '/DNS <nick>|<host>|<ip> ...', + license => 'Public Domain', + changed => 'Sun Mar 10 23:23 EET 2002' +); + +my (%resolve_hosts, %resolve_nicks, %resolve_print); # resolve queues +my $userhosts; # number of USERHOSTs currently waiting for reply +my $lookup_waiting; # 1 if we're waiting a reply for host lookup + +# for the current host lookup +my ($print_server, $print_host, $print_name, @print_ips); +my ($input_skip_next, $input_query); + +my $pipe_tag; + +sub cmd_dns { + my ($nicks, $server) = @_; + return if !$nicks; + + # get list of nicks/hosts we want to know + my $tag = !$server ? undef : $server->{tag}; + my $ask_nicks = ""; + my $print_error = 0; + foreach my $nick (split(" ", $nicks)) { + $nick = lc($nick); + if ($nick =~ /[\.:]/) { + # it's an IP or hostname + $resolve_hosts{$nick} = $tag; + } else { + # it's nick + if (!$print_error && (!$server || !$server->{connected})) { + $print_error = 1; + Irssi::print("Not connected to server"); + } else { + $resolve_nicks{$nick} = 1; + $ask_nicks .= "$nick "; + } + } + } + + if ($ask_nicks ne "") { + # send the USERHOST query + $userhosts++; + $server->redirect_event('userhost', 1, $ask_nicks, 0, 'redir dns failure', { + 'event 302' => 'redir dns host', + '' => 'event empty' } ); + $server->send_raw("USERHOST :$nicks"); + } + + # ask the IPs/hostnames immediately + host_lookup() if (!$lookup_waiting); +} + +sub sig_failure { + Irssi::print("Error getting hostname for nick"); + %resolve_nicks = () if (--$userhosts == 0); +} + +sub sig_userhost { + my ($server, $data) = @_; + $data =~ s/^[^ ]* :?//; + my @hosts = split(/ +/, $data); + + # move resolve_nicks -> resolve_hosts + foreach my $host (@hosts) { + if ($host =~ /^([^=\*]*)\*?=.(.*)@(.*)/) { + my $nick = lc($1); + my $user = $2; + $host = lc($3); + + $resolve_hosts{$host} = $resolve_nicks{$nick}; + delete $resolve_nicks{$nick}; + $resolve_print{$host} = "[$nick!$user"."@"."$host]"; + } + } + + if (--$userhosts == 0 && %resolve_nicks) { + # unknown nicks - they didn't contain . or : so it can't be + # IP or hostname. + Irssi::print("Unknown nicks: ".join(' ', keys %resolve_nicks)); + %resolve_nicks = (); + } + + host_lookup() if (!$lookup_waiting); +} + +sub host_lookup { + return if (!%resolve_hosts); + + my ($host) = keys %resolve_hosts; + $print_server = $resolve_hosts{$host}; + + $print_host = undef; + $print_name = $resolve_print{$host}; + @print_ips = (); + + delete $resolve_hosts{$host}; + delete $resolve_print{$host}; + + $input_query = $host; + $input_skip_next = 0; + + # pipe is used to get the reply from child + my ($rh, $wh); + pipe($rh, $wh); + + # non-blocking host lookups with fork()ing + my $pid = fork(); + if (!defined($pid)) { + %resolve_hosts = (); + %resolve_print = (); + Irssi::print("Can't fork() - aborting"); + close($rh); close($wh); + return; + } + $lookup_waiting++; + + if ($pid > 0) { + # parent, wait for reply + close($wh); + Irssi::pidwait_add($pid); + $pipe_tag = Irssi::input_add(fileno($rh), INPUT_READ, \&pipe_input, $rh); + return; + } + + my $text; + eval { + # child, do the lookup + my $name = ""; + if ($host =~ /^[0-9\.]*$/) { + # ip -> host + $name = gethostbyaddr(inet_aton($host), AF_INET); + } else { + # host -> ip + my @addrs = gethostbyname($host); + if (@addrs) { + @addrs = map { inet_ntoa($_) } @addrs[4 .. $#addrs]; + $name = join (" ", @addrs); + } + } + + $print_name = $input_query if !$print_name; + if (!$name) { + $text = "No information for $print_name"; + } else { + $text = "$print_name: $name"; + } + }; + $text = $! if (!$text); + + eval { + # write the reply + print($wh $text); + close($wh); + }; + POSIX::_exit(1); +} + +sub pipe_input { + my $rh = shift; + my $text = <$rh>; + close($rh); + + Irssi::input_remove($pipe_tag); + $pipe_tag = -1; + + my $server = Irssi::server_find_tag($print_server); + if ($server) { + $server->print('', $text); + } else { + Irssi::print($text); + } + + $lookup_waiting--; + host_lookup(); +} + +Irssi::command_bind('dns', 'cmd_dns'); +Irssi::signal_add( { + 'redir dns failure' => \&sig_failure, + 'redir dns host' => \&sig_userhost } ); |