3 # -*- perl -*- vim:set ft=perl sw=4 sts=4:
6 use vars qw(%state @ssh $last $pipe $arg $slow);
7 @ssh=("ssh","-a","-x","-oBatchmode=yes","-oSetupTimeOut=20");
8 $pipe = "/tmp/.away-tpope";
11 daemonize() if ($arg eq "-d");
12 daemon() if ($arg eq "-D");
15 if($arg eq "activity" || $arg eq "away" || $arg eq "out" || $arg eq "check") {
16 if(exists($ARGV[0])) {
17 die "Daemon not running\n" unless (-p $pipe);
18 my $a = join(" ",@ARGV);
24 print $state{$arg}."\n" if($state{$arg});
31 die "Daemon already running?\n" if (-e "/tmp/.away-tpope.pid");
32 open TMP, ">/tmp/.away-tpope.pid";
36 $SIG{'INT'} = \&quit_handler;
37 $SIG{'TERM'} = \&quit_handler;
38 $SIG{'QUIT'} = \&quit_handler;
39 $SIG{'HUP'} = \&hup_handler;
40 $SIG{'USR2'} = \&restart_handler;
41 die "Daemon already running\n" if (-r "/tmp/.tpope-away.pid");
44 system("mkfifo", $pipe);
61 elsif(defined($pid)) {
69 local $SIG{ALRM} = sub { die "alarm\n" };
71 open FIFO, "<$pipe" and
77 die unless $@ eq "alarm\n";
82 $read =~ s/^([a-z]*)( |$)//;
84 if($c eq "activity") {
85 custom_activity($read);
86 } elsif($c eq "away") {
88 } elsif($c eq "out") {
90 } elsif($c eq "check") {
93 print "Unknown command: $c\n";
96 if(time-$last >= 240) {
102 local $SIG{'HUP'} = sub {$last = 1};
104 if((!$last) || $slow++ ) {
117 $last=int(time/60)*60;
122 open(SOUT, ">&STDOUT");
124 my $ret=!(system('ping','-q','-c','1',shift)>>8);
125 open(STDOUT, ">&SOUT");
132 my $now=$now[2]*60+$now[1];
135 open(SCHEDULE, "today --category=school|");
137 my ($begin, $end, $maxend);
138 next unless /(\d\d):(\d\d)-(\d\d):(\d\d) (.*)/;
139 my ($hs,$ms,$he,$me,$ev) = ($1, $2, $3, $4, $5);
141 $begin = $hs*60+$ms-25;
142 $maxend = $he*60+$me+10;
143 $end = ($begin+25)*3/4+($maxend-10)/4;
144 if($begin <= $now && $now < $end) {
145 $state{'class'} = $ev;
148 } elsif (($state{'class'}||'') eq $ev) {
150 undef $state{'class'}
151 if ($now > $maxend || $state{'phone'} eq "present");
155 undef $state{'class'} unless ($familiar);
158 open(SCHEDULE, "today --category='!school !private'|");
161 my ($begin, $end, $maxend);
162 next unless /(\d\d):(\d\d)-(\d\d):(\d\d) (.*)/;
163 my ($hs,$ms,$he,$me,$ev) = ($1, $2, $3, $4, $5);
166 $maxend = $he*60+$me;
167 $end = ($begin)*3/4+($maxend)/4;
168 if($begin <= $now && $now < $end) {
169 $state{'schedule'} = $ev;
172 } elsif (($state{'schedule'}||'') eq $ev) {
174 undef $state{'schedule'}
175 if ($now > $maxend || $state{'phone'} eq "present");
179 undef $state{'schedule'} unless ($familiar);
183 if(-r ($ENV{'HOME'} . "/.chat")) {
184 open TMP, $ENV{'HOME'} . "/.chat";
185 my $chat = join ("", <TMP>);
188 $state{'chat'} = $chat;
190 undef $state{'chat'};
195 my (@check) = ("mona", "lisa", "homer", "sarah");
196 my (@uphosts, @livehosts, $host, $hostlist);
197 if(($_[0] || 0) == 1) {
198 $hostlist=$state{'hosts'};
199 $hostlist=~s/0\S* ?//g;
200 @livehosts = split / /, $hostlist;
203 foreach $host (@check) {
204 push @uphosts, $host if(ping($host));
206 foreach $host (@uphosts) {
207 if(is_alive($host)) {
208 push @livehosts,$host;
209 $hostlist="$host $hostlist";
211 $hostlist="0$host $hostlist";
215 $state{'hosts'}=$hostlist;
217 if(scalar @livehosts == 0) {
218 $state{'alive'} = '';
219 } elsif(scalar @livehosts > 1 && $state{'chat'}) {
220 foreach $host (@livehosts) {
221 if ($host eq $state{'chat'}) {
222 $state{'alive'} = $host;
227 $state{'alive'}=$livehosts[0];
233 local $SIG{ALRM} = sub { die "alarm\n" };
235 $ret=!(system(@ssh,shift, '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);
240 die unless $@ eq "alarm\n";
250 my $last_slh=`@ssh mona cat .blue/last_slh 2>/dev/null`;
253 } elsif (time-$last_slh < 540) {
259 if($state{'phone'} ne 'present' && $phone eq 'present') {
262 $state{'phone'} = $phone;
266 open TMP, "upsc milhouse\@localhost|";
270 if(/status: (.*)/i) {
280 if ($state{'customawayexp'} && $state{'customawayexp'}<time);
282 if ($state{'customoutexp'} && $state{'customoutexp'}<time);
284 if ($state{'customactivityexp'} && $state{'customactivityexp'}<time);
285 if ($state{'customactivity'}) {
286 $state{'activity'}=$state{'customactivity'};
287 } elsif ($state{'ups'} eq 'OB' || $state{'ups'} eq 'LB') {
288 $state{'activity'}="Power outage";
290 undef $state{'activity'};
292 if ($state{'customout'} && $state{'phone'} eq 'absent') {
293 $state{'away'}=$state{'customout'};
294 } elsif ($state{'customaway'}) {
295 $state{'away'}=$state{'customaway'};
296 } elsif ($state{'schedule'}) {
297 $state{'away'}=$state{'schedule'};
298 } elsif ($state{'phone'} ne 'present' && $state{'class'}) {
299 $state{'away'}="Class: ".$state{'class'};
300 } elsif ($state{'alive'}) {
301 undef($state{'away'});
302 } elsif ($state{'phone'} eq 'absent') {
303 $state{'away'}="Out";
304 } elsif ($state{'phone'} ne 'absent') {
306 if (1 <= $now[2] && $now[2] < 9) {
307 $state{'away'}="Sleeping";
309 $state{'away'}="Away from keyboard";
315 return undef unless($_[0]);
317 if($host eq "phone") {
322 } elsif($host eq "chat") {
327 } elsif($state{'hosts'} =~ /0$host/ && is_alive($_[0])) {
328 $state{'hosts'} =~ s/0$host/$host/;
333 } elsif($state{'hosts'} =~ /(?!0)$host/ && ! is_alive($_[0])) {
334 $state{'hosts'} =~ s/1?$host/0$host/;
343 $state{'customaway'} = $_[0];
344 $state{'customawayexp'} = time+48*60*60;
346 undef $state{'customaway'};
347 undef $state{'customawayexp'};
355 $state{'customout'} = $_[0];
356 $state{'customoutexp'} = time+14*24*60*60;
358 undef $state{'customout'};
359 undef $state{'customoutexp'};
365 sub custom_activity {
367 $state{'customactivity'} = $_[0];
368 $state{'customactivityexp'} = time+12*60*60;
370 undef $state{'customactivity'};
371 undef $state{'customactivityexp'};
378 if (defined($state{'activity'})) {
379 $state{'status'}=$state{'activity'};
380 } elsif (defined($state{'away'})) {
381 $state{'status'}=$state{'away'};
382 } elsif ($state{'alive'} eq "mona" || $state{'alive'} eq "homer") {
383 $state{'status'}="On desktop";
384 } elsif ($state{'alive'} eq "lisa") {
385 $state{'status'}="On laptop";
386 } elsif ($state{'alive'} eq "sarah") {
387 $state{'status'}="In bed";
389 open CONF, '>' . $ENV{'HOME'} . "/.away-tpope" || die $!;
390 foreach my $k (keys %state) {
395 print CONF "$k=\"$val\"\n";
398 if(defined($state{'activity'})) {
399 open TMP, '>' . $ENV{'HOME'} . "/.activity";
400 print TMP $state{'activity'}."\n";
403 unlink($ENV{'HOME'} . "/.activity");
405 if(defined($state{'away'})) {
406 open TMP, '>' . $ENV{'HOME'} . "/.away";
407 print TMP $state{'away'}."\n";
410 unlink($ENV{'HOME'} . "/.away");
412 open TMP, '>' . $ENV{'HOME'} . "/.status";
413 print TMP $state{'status'}."\n";
418 open CONF, '<' . $ENV{'HOME'} . "/.away-tpope" or return;
419 while(my $line=<CONF>) {
423 $line =~ s/^([^=]*)="?//;
434 sub restart_handler {
437 unlink "/tmp/.away-tpope.pid";
439 exec($0,$arg) || die $!;
440 print "Restarting $0 $arg...\n";
445 unlink "/tmp/.away-tpope.pid";
451 system("away-actions &");