#!/usr/bin/perl -w use strict; use POSIX qw(setsid); die "timegmstr broken" unless timegmstr(1087973256) eq "2004062306473600"; sub timegmstr { my ($sec, $min, $hour, $mday, $mon, $year) = gmtime(shift); $year += 1900; $mon += 1; return sprintf("%04d%02d%02d%02d%02d%02d00", $year, $mon, $mday, $hour, $min, $sec); } sub at_cops { return `strace -o /dev/shm/dbus.strace -s4096 -f dbus-send --system --print-reply --dest=org.freesmartphone.ogsmd /org/freesmartphone/GSM/Device org.freesmartphone.GSM.Debug.DebugCommand string:AT+COPS?\r\n`; } sub cops_ok { my ($cops) = @_; if ($cops =~ m/\+COPS: 0,[02],"([^"]*)"/) { my $oper = $1; if (length($oper) > 2) { return 1; } } return 0; } sub is_registered { for (my $i = 0; $i < 3; $i++) { my $cops = at_cops(); if (cops_ok($cops)) { return 1; } my $time = timegmstr(time()); system("cp /dev/shm/dbus.strace /dev/shm/dbus.strace.$time"); xlog("cops \"$cops\" not ok, saved /dev/shm/dbus.strace.$time"); sleep(3); } return 0; } sub xlog { my ($msg) = @_; #print(timegmstr(time()) . " $msg\n"); system("logger -t gsm-watchdog \"$msg\""); } sub dbg { my ($msg) = @_; #xlog("debug $msg"); } sub kill_gsm { xlog("kill_gsm"); system("/etc/init.d/ogsmd stop"); if (`ps -eo cmd | grep gsm0710mux[d]` ne "") { xlog("gsm017muxd did not die"); system("killall -9 gsm0710muxd"); sleep(2); if (`ps -eo cmd | grep gsm0710mux[d]` ne "") { xlog("gsm017muxd did not die with killall"); exit(1); } } if (`ps -eo cmd | grep framework[d]` ne "") { xlog("frameworkd did not die"); system("ps -eo pid,cmd | grep bin/framework[d] | sed \"s/[^0-9]//g\" | xargs kill -9"); sleep(4); if (`ps -eo cmd | grep framework[d]` ne "") { xlog("frameworkd did not die even after kill -9!"); exit(1); } } if (-e "/tmp/frameworkd.pid") { xlog("pid file was not removed"); system("rm /tmp/frameworkd.pid"); } system("echo 0 > /sys/class/i2c-adapter/i2c-0/0-0073/neo1973-pm-gsm.0/power_on"); system("echo 0 > /sys/class/i2c-adapter/i2c-0/0-0073/neo1973-pm-gsm.0/flowcontrolled"); system("kill -9 `cat /home/lindi/.answering-machine/pid`"); } sub start_gsm { xlog("start_gsm"); system("/etc/init.d/ogsmd start"); } sub wait_startup { xlog("wait_startup"); for (my $i = 0; $i < 30; $i++) { if (-e "/tmp/frameworkd.pid") { xlog("startup ok"); return; } sleep(1); } xlog("startup failed"); exit(1); } sub pid_file_fresh { my ($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, $atime, $mtime, $ctime, $blksize, $blocks) = stat("/tmp/frameworkd.pid"); if (!defined($mtime)) { return 0; } my $age = time() - $mtime; dbg("age $age"); if ($age < 2 * 60) { return 1; } return 0; } sub write_pid_file { my $pid = $$; my $fh; open($fh, ">/var/run/gsm-watchdog.pid") or die "Can't open pid file /var/run/gsm-watchdog.pid: $!"; print $fh "$pid\n"; close $fh; } sub daemonize { # stolen from http://perlmonks.thepen.com/41683.html chdir '/' or die "Can't chdir to /: $!"; open STDIN, '/dev/null' or die "Can't read /dev/null: $!"; open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!"; defined(my $pid = fork) or die "Can't fork: $!"; exit if $pid; setsid() or die "Can't start a new session: $!"; open STDERR, '>&STDOUT' or die "Can't dup stdout: $!"; } sub main { xlog("starting up"); daemonize(); write_pid_file(); xlog("startup done"); my $prev_reg = 0; for (;;) { dbg("starting new run"); my $reg = is_registered(); if (!$reg) { system("ledctrl --on-time 100 --off-time 1500 gta02-aux:red"); } if ($reg && !$prev_reg) { system("ledctrl --off gta02-aux:red"); } $prev_reg = $reg; if (!pid_file_fresh() && !$reg) { xlog("not registered"); kill_gsm(); start_gsm(); wait_startup(); } sleep(2*50); } } #print(is_registered()); main(); # only complain if we are unregistered for more than 4 minutes