aboutsummaryrefslogtreecommitdiff
path: root/trap_stdin.pl
diff options
context:
space:
mode:
authorB. Watson <urchlay@slackware.uk>2024-12-26 17:08:34 -0500
committerB. Watson <urchlay@slackware.uk>2024-12-26 17:08:34 -0500
commit9eed830f296dab257759f5276d0963467007aa6b (patch)
tree83d6225d248ec8d4026b514d8b9b248e6c0fce32 /trap_stdin.pl
downloadstupid-irssi-tricks-9eed830f296dab257759f5276d0963467007aa6b.tar.gz
initial commit
Diffstat (limited to 'trap_stdin.pl')
-rw-r--r--trap_stdin.pl114
1 files changed, 114 insertions, 0 deletions
diff --git a/trap_stdin.pl b/trap_stdin.pl
new file mode 100644
index 0000000..61e5c8e
--- /dev/null
+++ b/trap_stdin.pl
@@ -0,0 +1,114 @@
+#!/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<STDIN> (or from B<ARGV> via the B<E<lt>E<gt>> 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<kill> from another terminal), and probably also have to
+blindly type C<reset> 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 B<E<lt>E<gt>>. Example:
+
+ open my $fh, "<", $filename;
+ my $content = <>;
+
+The second line was I<intended> to be:
+
+ my $content = <$fh>;
+
+...but due to PEBKAC, the C<$fh> was left out (passive voice sucks:
+I<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<trap_stdin.pl> 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<trap_stdin.pl> doesn't actually B<use Irssi>. 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.