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","-qq");
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++ ) {
118 $last=int(time/60)*60;
123 open(SOUT, ">&STDOUT");
125 my $ret=!(system('ping','-q','-c','1',shift)>>8);
126 open(STDOUT, ">&SOUT");
133 my $now=$now[2]*60+$now[1];
136 open(SCHEDULE, "today --category=school|");
138 my ($begin, $end, $maxend);
139 next unless /(\d\d):(\d\d)-(\d\d):(\d\d) (.*)/;
140 my ($hs,$ms,$he,$me,$ev) = ($1, $2, $3, $4, $5);
142 $begin = $hs*60+$ms-10;
143 $maxend = $he*60+$me+10;
144 $end = ($begin+10)*3/4+($maxend-10)/4;
145 if($begin <= $now && $now < $end) {
146 $state{'class'} = $ev;
147 internal_out("School");
150 } elsif($begin-35<=$now && $now<$end && $state{'phone'} eq "absent") {
151 internal_out("School");
152 } elsif (($state{'class'}||'') eq $ev) {
154 undef $state{'class'}
155 if ($now > $maxend || $state{'phone'} eq "present");
159 undef $state{'class'} unless ($familiar);
161 open(SCHEDULE, "today --category='!school !private'|");
164 my ($begin, $end, $maxend);
165 next unless /(\d\d):(\d\d)-(\d\d):(\d\d) (.*)/;
166 my ($hs,$ms,$he,$me,$ev) = ($1, $2, $3, $4, $5);
169 $maxend = $he*60+$me;
170 $end = ($begin)*3/4+($maxend)/4;
171 if($begin <= $now && $now < $end) {
172 $state{'schedule'} = $ev;
175 } elsif (($state{'schedule'}||'') eq $ev) {
177 undef $state{'schedule'}
178 if ($now > $maxend || $state{'phone'} eq "present");
182 undef $state{'schedule'} unless ($familiar);
186 if(-r ($ENV{'HOME'} . "/.chat")) {
187 open TMP, $ENV{'HOME'} . "/.chat";
188 my $chat = join ("", <TMP>);
191 $state{'chat'} = $chat;
193 undef $state{'chat'};
198 if(($state{'chat'}||'') eq "jmwaller") {
199 internal_out("Work",3*60*60);
200 } elsif(($state{'chat'}||'') =~ /^tpope-\d+$/) {
201 internal_out("Work",3*60*60);
202 } elsif(($state{'chat'}||'') eq "accd") {
203 #internal_out("School",30*60);
208 my (@check) = ("tobias", "lucille", "lindsay", "buster");
209 my (@uphosts, @livehosts, $host, $hostlist);
210 if(($_[0] || 0) == 1) {
211 $hostlist=$state{'hosts'};
212 $hostlist=~s/0\S* ?//g;
213 @livehosts = split / /, $hostlist;
216 foreach $host (@check) {
217 push @uphosts, $host if(ping($host));
219 foreach $host (@uphosts) {
220 if(is_alive($host)) {
221 push @livehosts,$host;
222 $hostlist="$host $hostlist";
224 $hostlist="0$host $hostlist";
228 $state{'hosts'}=$hostlist;
230 if(scalar @livehosts == 0) {
231 $state{'alive'} = '';
232 } elsif(scalar @livehosts > 1 && $state{'chat'}) {
233 foreach $host (@livehosts) {
234 if ($host eq $state{'chat'}) {
235 $state{'alive'} = $host;
240 $state{'alive'}=$livehosts[0];
246 local $SIG{ALRM} = sub { die "alarm\n" };
248 $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 michael .*(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);
253 die unless $@ eq "alarm\n";
260 if(!ping('tobias')) {
263 my $last_slh=`@ssh tobias cat .blue/last_slh 2>/dev/null`;
266 } elsif (time-$last_slh < 540) {
272 if(($state{'phone'}||"") ne 'present' && $phone eq 'present') {
276 $state{'phone'} = $phone;
280 open TMP, "upsc milhouse\@localhost 2>/dev/null|";
284 if(/status: (.*)/i) {
294 if ($state{'customawayexp'} && $state{'customawayexp'}<time);
296 if ($state{'customoutexp'} && $state{'customoutexp'}<time);
298 if ($state{'internaloutexp'} && $state{'internaloutexp'}<time);
300 if ($state{'customactivityexp'} && $state{'customactivityexp'}<time);
301 if (exists($state{'customactivity'})) {
302 $state{'activity'}=$state{'customactivity'};
303 } elsif ($state{'ups'} eq 'OB' || $state{'ups'} eq 'LB') {
304 $state{'activity'}="Power outage";
306 undef $state{'activity'};
308 if ($state{'customout'} && $state{'phone'} eq 'absent') {
309 $state{'away'}=$state{'customout'};
310 } elsif ($state{'customaway'}) {
311 $state{'away'}=$state{'customaway'};
312 } elsif ($state{'schedule'}) {
313 $state{'away'}=$state{'schedule'};
314 } elsif ($state{'phone'} ne 'present' && $state{'class'}) {
315 $state{'away'}="Class: ".$state{'class'};
316 } elsif ($state{'internalout'} && $state{'phone'} eq 'absent') {
317 $state{'away'}=$state{'internalout'};
318 } elsif ($state{'alive'}) {
319 undef($state{'away'});
320 } elsif ($state{'phone'} eq 'absent') {
321 $state{'away'}="Out";
322 } elsif ($state{'phone'} ne 'absent') {
324 if (0 <= $now[2] && $now[2] < 7) {
325 $state{'away'}="Sleeping";
327 $state{'away'}="Away from keyboard";
333 return undef unless($_[0]);
335 if($host eq "phone") {
340 } elsif($host eq "chat") {
345 } elsif($state{'hosts'} =~ /0$host/ && is_alive($_[0])) {
346 $state{'hosts'} =~ s/0$host/$host/;
351 } elsif($state{'hosts'} =~ /(?!0)$host/ && ! is_alive($_[0])) {
352 $state{'hosts'} =~ s/1?$host/0$host/;
361 $state{'customaway'} = $_[0];
362 $state{'customawayexp'} = time+48*60*60;
364 undef $state{'customaway'};
365 undef $state{'customawayexp'};
373 $state{'customout'} = $_[0];
374 $state{'customoutexp'} = time+14*24*60*60;
376 undef $state{'customout'};
377 undef $state{'customoutexp'};
385 $state{'internalout'} = $_[0];
386 $state{'internaloutexp'} = time+($_[1]||150*60);
388 undef $state{'internalout'};
389 undef $state{'internaloutexp'};
395 sub custom_activity {
397 $state{'customactivity'} = $_[0];
398 $state{'customactivityexp'} = time+12*60*60;
400 undef $state{'customactivity'};
401 undef $state{'customactivityexp'};
408 if (defined($state{'activity'})) {
409 $state{'status'}=$state{'activity'};
410 } elsif (defined($state{'away'})) {
411 $state{'status'}=$state{'away'};
412 } elsif ($state{'alive'} eq "tobias" || $state{'alive'} eq "lucille") {
413 $state{'status'}="On desktop";
414 } elsif ($state{'alive'} eq "lindsay") {
415 $state{'status'}="On laptop";
416 } elsif ($state{'alive'} eq "buster") {
417 $state{'status'}="In bed";
419 open CONF, '>' . $ENV{'HOME'} . "/.away-tpope" || die $!;
420 foreach my $k (keys %state) {
425 print CONF "$k=\"$val\"\n";
428 if(defined($state{'activity'})) {
429 open TMP, '>' . $ENV{'HOME'} . "/.activity";
430 print TMP $state{'activity'}."\n";
433 unlink($ENV{'HOME'} . "/.activity");
435 if(defined($state{'away'})) {
436 open TMP, '>' . $ENV{'HOME'} . "/.away";
437 print TMP $state{'away'}."\n";
440 unlink($ENV{'HOME'} . "/.away");
442 open TMP, '>' . $ENV{'HOME'} . "/.status";
443 print TMP $state{'status'}."\n";
448 open CONF, '<' . $ENV{'HOME'} . "/.away-tpope" or return;
449 undef $state{'customactivity'};
450 undef $state{'customaway'};
451 undef $state{'customout'};
452 undef $state{'internalout'};
453 while(my $line=<CONF>) {
457 $line =~ s/^([^=]*)="?//;
468 sub restart_handler {
471 unlink "/tmp/.away-tpope.pid";
473 exec($0,$arg) || die $!;
474 print "Restarting $0 $arg...\n";
479 unlink "/tmp/.away-tpope.pid";
485 system("away-actions &");