1use Irssi;
2use Irssi::TextUI;
3use strict;
4
5use vars qw($VERSION %IRSSI);
6
7$VERSION="0.2.6";
8%IRSSI = (
9	authors=> 'BC-bd',
10	contact=> 'bd@bc-bd.org',
11	name=> 'nact',
12	description=> 'Adds an item which displays the current network activity. Needs /proc/net/dev.',
13	sbitems=> 'nact',
14	license=> 'GPL v2 or later',
15	url=> 'https://bc-bd.org/svn/repos/irssi/trunk/',
16);
17
18#########
19# INFO
20###
21#
22#  Currently running on Linux, OpenBsd and FreeBsd.
23#
24#  Type this to add the item:
25#
26#    /statusbar window add nact
27#
28#  See
29#
30#    /help statusbar
31#
32#  for more help on how to custimize your statusbar.
33#  Add something like this to your theme file to customize to look of the item
34#
35#    nact_display = "$0%R>%n%_$1%_%G>%n$2";
36#
37#  where $0 is the input, $1 the device and $2 the output. To customize the
38#  outout of the /bw command add something like
39#
40#    nact_command = "$0)in:$1:out($2";
41#
42#  to your theme file.
43#
44##########
45# THEME
46####
47#
48# This is the complete list of parameters passed to the format:
49#
50#    $0: incomming rate
51#    $1: name of the device, eg. eth0
52#    $2: outgoing rate
53#    $3: total bytes received
54#    $4: total bytes sent
55#    $5: sum of $4 and $5
56#
57#########
58# TODO
59###
60#
61# Make this script work on other unices, For that i need some infos on where
62# to find the total amount of sent bytes on other systems. You may be so kind
63# as to send me the name of such a file and a sample output of it.
64#
65#   or
66#
67# you can be so kind as to send me a patch. Fort that _please_ check that you
68# do have the latest nact.pl and use these diff switches:
69#
70#   diff -uN nact.pl.new nact.pl.old
71#
72############
73# OPTIONS
74######
75#
76# /set nact_command <command>
77#   command: command to execute on /bw. example:
78#
79#     /set nact_command /say
80#
81# /set nact_devices <devices>
82#   devices: space seperated list of devices to display
83#
84# /set nact_interval <n>
85#   n: number of mili-seconds to wait before an update of the item
86#
87# /set nact_format <format>
88#   format: a format string like the one with sprintf. examples:
89#
90#     /set nact_format %d    no digits after the point at all
91#     /set nact_format %.3f  3 digits after the point
92#     /set nact_format %.5f  5 digits after the point
93#
94# /set nact_unit <n>
95#   n: set the unit to KiB, MiB, or GiB. examples:
96#
97#     /set nact_unit 0 calculate dynamically
98#     /set nact_unit 1 set to KiB/s
99#     /set nact_unit 2 set to MiB/s
100#     /set nact_unit 3 set to GiB/s
101#
102###
103################
104
105my $outString = "nact...";
106my $outCmd = "nact...";
107my (%in,%out,$timeout,$getBytes);
108
109sub getBytesLinux() {
110	my @list;
111	my $ignore = 2;
112
113	open(FID, "<", "/proc/net/dev");
114
115	while (<FID>) {
116		if ($ignore > 0) {
117			$ignore--;
118			next;
119		}
120
121		my $line = $_;
122		$line =~ s/[\s:]/ /g;
123		@list = split(" ", $line);
124		$in{$list[0]} = $list[1];
125		$out{$list[0]} = $list[9];
126	}
127
128	close (FID);
129}
130
131sub getBytesOBSD() {
132	my @list;
133
134	open(FID, "-|", "/usr/bin/netstat -nib");
135
136	while (<FID>) {
137		my $line = $_;
138		@list = split(" ", $line);
139		$in{$list[0]} = $list[4];
140		$out{$list[0]} = $list[5];
141	}
142
143	close (FID);
144}
145
146sub getBytesFBSD() {
147  my @list;
148  my $olddev="";
149
150  open(FID, "-|", "/usr/bin/netstat -nib");
151  while (<FID>) {
152    my $line = $_;
153    @list = split(" ", $line);
154    next if $list[0] eq $olddev;
155    $in{$list[0]} = $list[6];
156    $out{$list[0]} = $list[9];
157    $olddev=$list[0];
158  }
159
160  close (FID);
161}
162
163sub make_kilo($$$) {
164	my ($what,$format,$unit) = @_;
165	my ($effective);
166
167	# determine the effective unit, either from forcing, or from dynamically
168	# checking the size of the value
169	if ($unit == 0) {
170		if ($what >= 1024*1024*1024) {
171			$effective = 3
172		} elsif ($what >= 1024*1024) {
173			$effective = 2
174		} elsif ($what >= 1024) {
175			$effective = 1
176		} else {
177			$effective = 0;
178		}
179	} else {
180		$effective = $unit;
181	}
182
183	if ($effective >= 3) {
184			return sprintf($format."%s", $what/(1024*1024*1024), "G");
185	} elsif ($effective == 2) {
186			return sprintf($format."%s", $what/(1024*1024), "M");
187	} elsif ($effective == 1) {
188			return sprintf($format."%s", $what/(1024), "K");
189	} else {
190		return sprintf($format, $what);
191	}
192}
193
194sub sb_nact() {
195	my ($item, $get_size_only) = @_;
196
197	$item->default_handler($get_size_only, "{sb $outString}", undef, 1);
198}
199
200sub timeout_nact() {
201	my ($out,$char);
202	my $slice = Irssi::settings_get_int('nact_interval');
203	my $format = Irssi::settings_get_str('nact_format');
204	my $unit = Irssi::settings_get_int('nact_unit');
205	my $theme = Irssi::current_theme();
206	my %oldIn = %in;
207	my %oldOut = %out;
208
209	&$getBytes();
210
211	$out = "";
212	$outCmd = "";
213
214	foreach (split(" ", Irssi::settings_get_str('nact_devices'))) {
215		my $b_in = $in{$_};
216		my $b_out = $out{$_};
217		my $deltaIn = make_kilo(($b_in -$oldIn{$_})*1000/$slice,$format,$unit);
218		my $deltaOut = make_kilo(($b_out -$oldOut{$_})*1000/$slice,$format,$unit);
219		my $i = make_kilo($b_in,$format,$unit);
220		my $o = make_kilo($b_out,$format,$unit);
221		my $s = make_kilo($b_in +$b_out,$format,$unit);
222
223		$out .= Irssi::current_theme->format_expand(
224			"{nact_display $deltaIn $_ $deltaOut $i $o $s}",Irssi::EXPAND_FLAG_IGNORE_REPLACES);
225
226		$outCmd .= Irssi::current_theme->format_expand(
227			"{nact_command $deltaIn $_ $deltaOut $i $o $s}",Irssi::EXPAND_FLAG_IGNORE_REPLACES);
228	}
229
230	# perhaps this usage of $out as temp variable does fix those nasty
231	# display errors
232	$outString = $out;
233	Irssi::statusbar_items_redraw('nact');
234}
235
236sub nact_setup() {
237	my $slice = Irssi::settings_get_int('nact_interval');
238
239	Irssi::timeout_remove($timeout);
240
241	if ($slice < 10) {
242		Irssi::print("nact.pl, ERROR nact_interval must be greater than 10");
243		return;
244	}
245
246	$timeout = Irssi::timeout_add($slice, 'timeout_nact' , undef);
247}
248
249sub cmd_bw {
250	my ($data, $server, $witem) = @_;
251
252	if ($witem && ($witem->{type} eq "CHANNEL" || $witem->{type} eq "QUERY")) {
253		$witem->command(Irssi::settings_get_str('nact_command')." ".$outCmd);
254	} else {
255		Irssi::print("nact: command needs window of type channel or query.");
256	}
257}
258
259Irssi::command_bind('bw','cmd_bw');
260
261Irssi::signal_add('setup changed','nact_setup');
262
263# register our item
264Irssi::statusbar_item_register('nact', undef, 'sb_nact');
265
266# register our os independant settings
267Irssi::settings_add_int('misc', 'nact_interval', 10000);
268Irssi::settings_add_str('misc', 'nact_format', '%.0f');
269Irssi::settings_add_int('misc', 'nact_unit', 0);
270Irssi::settings_add_str('misc', 'nact_command', 'me looks at the gauges:');
271
272# os detection
273my $os = `uname`;
274if ($os =~ /Linux/) {
275	Irssi::print("nact.pl, running on Linux, using /proc/net/dev");
276	$getBytes = \&getBytesLinux;
277	Irssi::settings_add_str('misc', 'nact_devices', "eth0 lo");
278} elsif ($os =~ /OpenBSD/) {
279	Irssi::print("nact.pl, running on OpenBSD, using netstat -nbi");
280	$getBytes = \&getBytesOBSD;
281	Irssi::settings_add_str('misc', 'nact_devices', "tun0");
282} elsif ($os =~ /FreeBSD/) {
283  Irssi::print("nact.pl, running on FreeBSD, using netstat -nbi");
284  $getBytes = \&getBytesFBSD;
285  Irssi::settings_add_str('misc', 'nact_devices', "rl0");
286} else {
287	Irssi::print("nact.pl, sorry no support for OS:$os");
288	Irssi::print("nact.pl, If you know how to collect the needed data on your OS, mail me :)");
289	$os = "";
290}
291
292if ($os ne "") {
293	&$getBytes();
294	nact_setup();
295}
296
297################
298###
299# Changelog
300#
301# Version 0.2.5
302#  - added nact_command
303#  - added /bw
304#
305# Version 0.2.4
306#  - added FreeBSD support (by senneth)
307#
308# Version 0.2.3
309#  - stray ' ' in the item (reported by darix). Add a " " at the end of your
310#      nact_display if you have more than one interface listed.
311#
312# Version 0.2.2
313#  - added missing use Irssi::TextUI (reported by darix)
314#  - small parameter switch bug (reported by darix)
315#
316# Version 0.2.1
317#  - added total number of bytes sent/received
318#
319# Version 0.2.0
320#  - runs now from autorun/ on openbsd
321#  - changed nact_interval to mili-seconds
322#  - added nact_format, nact_unit
323#
324# Version 0.1.2
325#  - small typo in the docs
326#
327# Version 0.1.1
328#  - introduced multiple os support
329#  - added a theme thingie to make sascha happy ;)
330#
331# Version 0.1.0
332#  - initial release
333#
334###
335################
336