From 2b0aae2fc868670054a23914fd3ff1844bd97d53 Mon Sep 17 00:00:00 2001 From: Tim Pope Date: Sun, 29 May 2005 02:59:00 +0000 Subject: [PATCH] New away script --- perl/away-tpope | 284 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100755 perl/away-tpope diff --git a/perl/away-tpope b/perl/away-tpope new file mode 100755 index 0000000..e5b7479 --- /dev/null +++ b/perl/away-tpope @@ -0,0 +1,284 @@ +#!/usr/bin/perl -w +# $Id$ +# -*- perl -*- vim:set ft=perl sw=4 sts=4: + +use strict; +use vars qw(%state @ssh $last $pipe); +@ssh=("ssh","-a","-x","-oBatchmode=yes","-oSetupTimeOut=20"); +$pipe = "/tmp/.away-tpope"; + +my $arg=shift || ""; +daemonize() if ($arg eq "-d"); +daemon() if ($arg eq "-D"); + + +if($arg eq "activity" || $arg eq "away") { + if(exists($ARGV[0])) { + die "Daemon not running\n" unless (-p $pipe); + my $a = join(" ",@ARGV); + $a =~ s/^-c$//; + open FIFO, ">$pipe"; + print FIFO "$arg $a"; + } else { + $arg =~ s/^away$/customaway/; + load(); + print $state{$arg}."\n" if($state{$arg}); + } +} else { + exit 1; +} + +sub daemon { + open TMP, ">/tmp/.away-tpope.pid"; + print TMP "$$\n"; + close TMP; + load(); + $SIG{'INT'} = \&quit_handler; + $SIG{'TERM'} = \&quit_handler; + $SIG{'QUIT'} = \&quit_handler; + $SIG{'HUP'} = \&cycle; + die "Daemon already running\n" if (-r "/tmp/.tpope-away.pid"); + unless (-p $pipe) { + unlink $pipe; + system("mkfifo", $pipe); + } + cycle(); + $last=time; + while(1) { + main_loop(); + } +} + +sub daemonize { + chdir "/"; + my $pid=fork(); + if($pid) { + exit(0) + } + elsif(defined($pid)) { + daemon(); + } else { exit(1); } +} + +sub main_loop { + my $read=""; + eval { + local $SIG{ALRM} = sub { die "alarm\n" }; + alarm 1; + open FIFO, "<$pipe" and + $read = ; + alarm 0; + close FIFO; + }; + if($@) { + die unless $@ eq "alarm\n"; + close FIFO; + } + if($read) { + chomp $read; + $read =~ s/^([a-z]*)( |$)//; + my $c = $1 || ""; + if($c eq "activity") { + custom_activity($read); + } elsif($c eq "away") { + custom_away($read); + } else { + print "Unknown command: $c\n"; + } + } + if(time-$last >=300) { + local $SIG{'HUP'} = "IGNORE"; + cycle(); + $last=time; + } +} + +sub cycle { + do_schedule(); + do_hosts(); + do_phone(); + process_away(); + save(); + do_custom(); +} + +sub ping { + open(SOUT, ">&STDOUT"); + close(STDOUT); + my $ret=!(system('ping','-q','-c','1',shift)>>8); + open(STDOUT, ">&SOUT"); + close(SOUT); + return $ret; +} + +sub do_schedule { + my @now=localtime(time); + my $now=$now[3]*60+$now[2]; + + open(SCHEDULE, "today --category=school|"); + while() { + my ($begin, $end, $maxend); + next unless /(\d\d):(\d\d)-(\d\d):(\d\d) (.*)/; + my ($hs,$ms,$he,$me,$ev) = ($1, $2, $3, $4, $5); + $begin = $hs*60+$ms-25; + $maxend = $he*60+$me+5; + $end = ($begin+25)*3/4+($maxend-5)/4; + if($begin <= $now && $now < $end) { + $state{'class'} = $ev; + last; + } elsif ($state{'class'} eq $ev && $now > $maxend) { + $state{'class'} = ''; + } + } + close(SCHEDULE); + + + open(SCHEDULE, "today --category='!school !private'|"); + while() { + my ($begin, $end, $maxend); + next unless /(\d\d):(\d\d)-(\d\d):(\d\d) (.*)/; + my ($hs,$ms,$he,$me,$ev) = ($1, $2, $3, $4, $5); + $begin = $hs*60+$ms; + $maxend = $he*60+$me; + $end = ($begin)*3/4+($maxend)/4; + if($begin <= $now && $now < $end) { + $state{'schedule'} = $ev; + last; + } elsif ($state{'schedule'} eq $ev && $now > $maxend) { + $state{'schedule'} = ''; + } + } + close(SCHEDULE); +} + +sub do_hosts { + my @livehosts; + foreach my $host ("sarah", "homer", "lisa", "mona") { + push @livehosts, $host if(ping($host)); + } + my $alive = ""; + foreach my $host (@livehosts) { + $alive=$host unless(system(@ssh,$host, 'if pidof xscreensaver >/dev/null && DISPLAY=:0.0 xscreensaver-command -version >/dev/null 2>&1; then if DISPLAY=:0.0 xscreensaver-command -time 2>&1 |egrep "non-blanked|no saver status" >/dev/null; then true; else pid=`ps ax|egrep "[0-9]:[0-9][0-9] ssh marge .*(screen.*RR irc|Chat)"|sed -e "s/^ *//"|cut -d" " -f 1`; [ -f "$HOME/.irc.lock" -o -z "$pid" ] || kill $pid; false; fi; else false; fi') >> 8); + } + $state{'alive'} = $alive; +} + +sub do_phone { + my $phone; + if(!ping('mona')) { + $phone="unknown"; + } else { + my $last_slh=`@ssh mona cat .blue/last_slh 2>/dev/null`; + if(!$last_slh) { + $phone="unknown"; + } elsif (time-$last_slh < 600) { + $phone="present"; + } else { + $phone="absent"; + } + } + if($state{'phone'} eq 'absent' && $phone eq 'present') { + custom_away(""); + } +} + +sub process_away { + if ($state{'customaway'}) { + $state{'away'}=$state{'customaway'}; + } elsif ($state{'school'}) { + $state{'away'}="Class: ".$state{'school'}; + } elsif ($state{'schedule'}) { + $state{'away'}=$state{'schedule'}; + } elsif ($state{'alive'}) { + undef($state{'away'}); + } elsif ($state{'phone'} eq 'absent') { + $state{'away'}="Out"; + } elsif ($state{'phone'} ne 'absent') { + my @now=localtime; + if ($now[2] < 10) { + $state{'away'}="Sleeping"; + } else { + $state{'away'}="Away from keyboard"; + } + } +} + +sub custom_away { + if($_[0]) { + $state{'customaway'} = $_[0]; + } else { + undef $state{'customaway'}; + } + process_away(); + save(); +} + +sub custom_activity { + if($_[0]) { + $state{'activity'} = $_[0]; + } else { + undef $state{'activity'}; + } + save(); +} + +sub save { + if (defined($state{'activity'})) { + $state{'status'}=$state{'activity'}; + } elsif (defined($state{'away'})) { + $state{'status'}=$state{'away'}; + } elsif ($state{'alive'} eq "mona" || $state{'alive'} eq "homer") { + $state{'status'}="On desktop"; + } elsif ($state{'alive'} eq "lisa") { + $state{'status'}="On laptop"; + } elsif ($state{'alive'} eq "sarah") { + $state{'status'}="In bed"; + } + open CONF, '>' . $ENV{'HOME'} . "/.away-tpope" || die $!; + foreach my $k (keys %state) { + my $val=$state{$k}; + next unless($val); + $val =~ s/\n/\\n/g; + print CONF "$k=$val\n"; + } + close CONF; + if(defined($state{'activity'})) { + open TMP, '>' . $ENV{'HOME'} . "/.activity"; + print TMP $state{'activity'}."\n"; + close TMP; + } else { + unlink($ENV{'HOME'} . "/.activity"); + } + if(defined($state{'away'})) { + open TMP, '>' . $ENV{'HOME'} . "/.away"; + print TMP $state{'away'}."\n"; + close TMP; + } else { + unlink($ENV{'HOME'} . "/.away"); + } + open TMP, '>' . $ENV{'HOME'} . "/.status"; + print TMP $state{'status'}."\n"; + close TMP; +} + +sub load { + open CONF, '<' . $ENV{'HOME'} . "/.away-tpope" or return; + while(my $line=) { + $line =~ s/\\n/\n/g; + $line =~ s/^([^=]*)=//; + chomp $line; + $state{$1}=$line; + } + close CONF; +} + +sub quit_handler { + unlink $pipe; + unlink "/tmp/.away-tpope.pid"; + save(); + exit 0; +} + +sub do_custom { + system("away-actions &"); +} -- 2.30.2