#!/usr/bin/perl # SUMMARY: Daemon that is executed by /etc/acpi/x41tsdown.sh and # /etc/acpi/x41tsup.sh (ACPI events for Lenovo x41 tablet) to run # in the background and check periodically to see if the display # needs to be rotated, based on the hdaps orientation. # # Calls rotatetablet script (http://liken.otsoa.net/pub/x41t/rotatetablet) # By Saikat Guha (saikat AT cs.cornell.edu) and Liken Otsoa (liken AT otsoa.net) # # USAGE: orientd start|stop # # AUTHOR: Dave Clawson (david.scott.clawson AT gmail) use strict ; my $ORIENTATION = "/usr/local/bin/orient" ; my $pidfile = "/tmp/orientd.pid" ; my $orientation_file = "/tmp/orientation" ; if ( $ARGV[0] =~ /start/i ) { my $pid = read_pidfile( $pidfile ) ; if ( defined $pid && pid_is_alive( $pid ) ) { die "Daemon is already running as pid $pid . Quitting.\n" ; } my $newpid = fork ; if ( $newpid ) { # We're the parent. Write the pid of the child to the pid file # and quit write_pidfile( $pidfile, $newpid ) ; } else { # We're the child. Loop and check each second to see if our # orientation has changed. my $sleeptime = 1 ; while ( 1 ) { # Read the last orientation from the temp file. my $orientation = read_orientation( $orientation_file ) ; my $mode = `$ORIENTATION getmode` ; chomp $mode ; # If mode is -1, nothing to do. Sleep, next. if ( $mode == -1 ) { sleep $sleeptime ; next ; } # If mode is the same as last time, sleep, next. if ( $mode == $orientation ) { sleep $sleeptime ; next ; } sleep $sleeptime ; # Initially, I'd done this: # # system( "$ORIENTATION", "getmode" ) ; # $mode = $? ; # # So, either I'm crazy or the last Hardy update introduced a perl bug, # but $? was returning bizarre stuff. So, we capture the output instead. # Get the mode again. We don't want to be too hasty about swapping # modes too quickly. Give the user a chance to settle down. $mode = `$ORIENTATION getmode` ; chomp $mode ; if ( $mode != $orientation ) { # Okay, still different. Rotate it, give window manager a # few seconds. system( "/usr/local/bin/rotatetablet", $mode ) ; sleep 4 ; } else { next ; } write_orientation( $orientation_file, $mode ) ; sleep $sleeptime ; } } } elsif ( $ARGV[0] =~ /stop/i ) { my $pid = read_pidfile( $pidfile ) ; if ( defined $pid && pid_is_alive( $pid ) ) { kill 9, $pid ; sleep 1 ; if ( defined $pid && pid_is_alive( $pid ) ) { die "Couldn't kill $pid\n" ; } unlink $pidfile ; } } else { die "Must supply one of start|stop\n" ; } sub read_orientation { my ( $orientation_file ) = @_ ; # Let's assume that it's oriented normally if the file doesn't exist return 0 unless ( -f $orientation_file ) ; open( ORIENTATION, $orientation_file ) || die "Couldn't open $orientation_file $!\n" ; my $data = ; chomp $data ; $data =~ m/(\d+)/ ; my $orientation = $1 ; return $orientation ? $orientation : 0 ; } sub write_orientation { my ( $orientation_file, $orientation ) = @_ ; open( ORIENTATION, ">$orientation_file" ) || die "Couldn't open $orientation $!\n" ; print ORIENTATION $orientation ; close ORIENTATION ; } sub write_pidfile { my ( $pidfile, $pid ) = @_ ; $pid = $$ unless defined $pid ; open( PIDFILE, ">$pidfile" ) || die "Couldn't open $pidfile $!\n" ; print PIDFILE $pid ; close PIDFILE ; } sub read_pidfile { my ( $pidfile ) = @_ ; return undef unless ( -f $pidfile ) ; open( PIDFILE, $pidfile ) || die "Couldn't open $pidfile $!\n" ; my $data = ; chomp $data ; $data =~ m/(\d+)/ ; my $pid = $1 ; return $pid ? $pid : undef ; } sub pid_is_alive { my ( $pid ) = @_ ; use Proc::ProcessTable ; my $proc = new Proc::ProcessTable() ; map { return 1 if $_->{ 'pid' } eq $pid } @{ $proc->table } ; return undef ; }