#!/usr/bin/perl -w package TrapStdin; sub TIEHANDLE { my $class = shift; my $fh; bless \$fh, $class } sub READLINE { my (undef, $file, $line) = caller; warn "Irssi scripts can't read from STDIN or ARGV at $file line $line.\n"; return undef; } sub READ { goto &READLINE; } package main; tie *TRAP, 'TrapStdin'; *ARGV = *STDIN = *TRAP; #### rest of this file is documentation. the doc is a lot longer than #### the code, sorry about that. =pod =encoding utf8 =head1 NAME trap_stdin.pl - catch attempts to read from standard input in an irssi perl script. =head1 SYNOPSIS # from shell: cp trap_stdin.pl ~/.irssi/scripts/autorun/ # if irssi was already running, load manually: /script load trap_stdin =head1 DESCRIPTION This script is intended for script developers. The Perl scripting interface to irssi doesn't support reading from B (or from B via the BE> operator). Attempts to do so cause irssi to freeze: it stops responding to either the keyboard or incoming IRC traffic. Eventually, the IRC server will disconnect the client, since it's no longer responding to PING messages, but the user will have to kill the client manually (e.g. using C from another terminal), and probably also have to blindly type C to fix the terminal afterwards. The problem is, the script is trying to read from the terminal, but the terminal has already been "taken over" by irssi itself. The read blocks, waiting for input it will never receive. It's easy to avoid this: just don't try to read from standard input in your scripts. Problem solved? Well, it would be, but... The author of this script has an unfortunate tendency to forget the filehandle when using BE>. Example: open my $fh, "<", $filename; my $content = <>; The second line was I to be: my $content = <$fh>; ...but due to PEBKAC, the C<$fh> was left out (passive voice sucks: I screwed up and left it out). Attempting to run the broken code causes irssi to lock up, with no indication what the problem is. Although the code is wrong, the penalty for this trivial mistake is harsh. With B loaded, the erroneous code will instead cause a warning, and irssi will continue executing normally. The warning looks like: Irssi scripts can't read from STDIN or ARGV at *FILE* line *LINE*. =head1 NOTES All loaded scripts are affected by this. It shouldn't have any effect on scripts that already work correctly, since they already don't try to read from standard input (or else they wouldn't work correctly). B doesn't actually B. It also doesn't stay isolated to its own package namespace: it works by reassigning the global C<*STDIN> and C<*ARGV> globs to a tied filehandle. Unlike a normal irssi script, the changes made by this one will stay active even if the script is unloaded. If we didn't care about getting an irssi-specific warning, the script could have just been: undef *ARGV; undef *STDIN; =head1 AUTHOR B. Watson (urchlay@slackware.uk), aka Urchlay on Libera. =head1 LICENSE Licensed under the WTFPL. See http://www.wtfpl.net/txt/copying/ for details.