-
Notifications
You must be signed in to change notification settings - Fork 1
/
passwd.pl
115 lines (95 loc) · 2.77 KB
/
passwd.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
use strict;
use IPC::Open3;
use Irssi;
use Symbol;
my $passwords;
my $help_passwd = '
PASSWD <passwd_id> <command>
Replaces the string \'<password>\' with the password from passwd_id in command and executes the result.
The passwd_id\'s are defined in \'~/.irssi/passwd\' (or in the file specified by the setting config_file in the section passwd).
The format of the password file is \'passwd_id:command\\n\' where command writes the password to stdout
';
Irssi::settings_add_str('passwd', 'config_file', "$ENV{HOME}/.irssi/passwd");
passwd_init();
sub passwd_init {
my $cfg_file = Irssi::settings_get_str('config_file');
open my $handle, $cfg_file or return;
my %cfg;
while(<$handle>) {
my $line = $_;
if($line =~ /^\s*([a-zA-Z0-9_\-]+)\s*:(.*)$/) {
my $key = $1;
my $value = $2;
$value =~ s/^\s*//;
$cfg{$key} = $value;
next;
}
if($line =~ /^\s*$/) {
next;
}
Irssi::print("syntax error in file $cfg_file:$.", MSGLEVEL_CLIENTCRAP);
}
close $handle;
$passwords = \%cfg;
}
sub passwd_get_password {
my ($pw_key) = @_;
my ($stdin, $stdout, $stderr);
my $cmd = $passwords->{$pw_key};
if(!$cmd) {
Irssi::print("No command to get password $pw_key", MSGLEVEL_CLIENTCRAP);
return;
}
$stderr = gensym();
my $pid = open3($stdin, $stdout, $stderr, $cmd);
waitpid($pid, 0);
if($? != 0) {
my $error = join('', <$stderr>);
chomp($error);
Irssi::print("Couldn't get password: $error", MSGLEVEL_CLIENTCRAP);
return;
}
my $pw = join('', <$stdout>);
chomp($pw);
return $pw;
}
Irssi::signal_add_first('server connecting', sub {
my ($server, @rest) = @_;
if($server->{password} =~ /\<password:([a-zA-Z0-9]+)\>/) {
my $password = passwd_get_password($1);
$server->{password} =~ s/\<password:[a-zA-Z0-9]+\>/$password/;
Irssi::Server::connection_set_key($server, 'password', $server->{password});
}
Irssi::signal_continue($server, @rest);
});
Irssi::command_bind('passwd', sub {
my ($args) = @_;
my @argv = split(/ /, $args);
my $argc = @argv;
if($argc < 2) {
Irssi::print('Too few arguments', MSGLEVEL_CLIENTCRAP);
return;
}
my $cmd = join(' ', @argv[1..$argc-1]);
my $pw = passwd_get_password(@argv[0]);
$cmd =~ s/\<password\>/$pw/;
Irssi::command($cmd);
});
Irssi::command_bind('help', sub {
if($_[0] =~ /^\s*passwd\s*$/) {
Irssi::print($help_passwd, MSGLEVEL_CLIENTCRAP);
Irssi::signal_stop;
}
});
Irssi::signal_add_first('complete word', sub {
my ($strings, $window, $word, $linestart, $want_space) = @_;
return if $linestart ne '/passwd';
foreach my $key (keys %$passwords) {
my $sub = substr($key, 0, length($word));
if($sub eq $word) {
push(@$strings, $key);
$$want_space = 1;
}
}
Irssi::signal_stop;
});