App-PerlXLock

 view release on metacpan or  search on metacpan

lib/App/PerlXLock.pm  view on Meta::CPAN

use strict;
use warnings;
use base 'Exporter';
our @EXPORT  = qw(main_loop);

BEGIN {
   use constant PLOCK_PASSWORD => $ENV{PLOCK_PASSWORD};
}

sub detect_x11 {
   my $pkg = `pkg-config --cflags --libs x11`;
   if($? != 0){
      die "Could not detect x11 using pkg-config (perhaps you are missing libx11)";
   }
   return $pkg;
}

use App::PerlXLock::Inline C => Config => LIBS => detect_x11();
use App::PerlXLock::Inline C => "DATA";

my @buffer;
my @windows;
my @screens;


sub lock_all {
    my $d = shift();
    for ( 0 .. screen_count($d) - 1 ) {
        push( @screens, $_ );
        push( @windows, open_lock( $d, $_ ) );
    }
}

sub has_shadow {
    -e "/etc/shadow";
}

sub shadow_readable {
    -r "/etc/shadow";
}

sub password_accessible {
    PLOCK_PASSWORD || ( has_shadow() && shadow_readable() );
}

sub check_event {
    my $ev = read_event( $_[0] );
    $ev > 0 ? push( @buffer, chr($ev) ) : undef;
}

sub check_password {
    my $pw = shift;
    defined( PLOCK_PASSWORD ) && return(PLOCK_PASSWORD eq $pw);
    check_unix_password($pw) == 0;
}

sub main_loop {
    my $d = open_connection();
    lock_all($d);
    grab_keyboard( $d, 0 );
    my $locked = 1;
    while ($locked) {
        check_event($d);
        if ( $buffer[-1] && $buffer[-1] eq "\n" ) {
            pop(@buffer);
            if ( password_accessible() ) {
                for my $n ( 0 .. $#buffer ) {
                    if ( check_password( join( "", @buffer[ $n .. $#buffer ] ) ) ) {
                        $locked = 0;
                    }
                }
            }
            else {
                $locked = 0;
            }
            @buffer = ();
        }
    }
    unlock_all($d);
    ungrab_keyboard($d);
    close_connection($d);
}

sub unlock_all {
    my $d = shift;
    destroy_window( $d, $_ ) for (@windows);
}

unless ( PLOCK_PASSWORD ) {
    has_shadow()
      || print "/etc/shadow does not exist. Xlock is not password protected.\n";
    shadow_readable
      || print "No permissions to read /etc/shadow. Xlock is not password protected.\n";
}

1;

__DATA__
__C__

#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <shadow.h>
#include <crypt.h>

SV *open_connection(){
    Display *display;
    SV *d_sv;
    SV *d_sv_ref;
    display = XOpenDisplay(NULL);
    if (display == NULL){
        croak("Could not open X display connection.");
    }
    d_sv = newSViv((IV)display);
    d_sv_ref = newRV_noinc(d_sv);
    return d_sv_ref;
}

void close_connection(SV* display){
    XCloseDisplay((Display *)SvIV(SvRV(display)));
}

void destroy_window(SV *display, int window){
    XDestroyWindow((Display *)SvIV(SvRV(display)), window);
}

int screen_count(SV *display){
    return XScreenCount((Display *)SvIV(SvRV(display)));
}

int close_window(SV *display, int window){



( run in 1.658 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )