1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
#
# Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
# Licensed under the GPL
#
package hppfs;
use Socket;
use IO::Select;
use strict;
sub new {
my $class = shift;
my $base = shift;
!defined($base) and $base = ".";
my $me = { files => { }, handles => { }, base => $base };
bless($me, $class);
return($me);
}
sub add {
my $me = shift;
while(@_){
my $file = shift;
my $handler = shift;
$me->{files}->{$file} = $handler;
}
}
sub prepare {
my $me = shift;
my $dir = shift;
my $file = shift;
my $full = $me->{base} . "/proc/$dir";
if(! -d $full){
unlink $full;
my $out = `mkdir -p $full 2>&1`;
$? and die "mkdir '$full' failed : $out";
}
my $out = `chmod 755 $full 2>&1`;
$? and die "chmod 755 $full failed : $out";
defined($file) and unlink "$full/$file";
return("$full/$file");
}
sub setup_sock {
my ($me, $file, undef, $mode) = @_;
my $full = $me->prepare($file, $mode);
my $sock = sockaddr_un($full);
!defined($sock) and die "sockaddr_un of '$sock' failed : $!";
!defined(socket(my $fh, AF_UNIX, SOCK_STREAM, 0)) and
die "socket failed : $!";
!defined(bind($fh, $sock)) and die "bind failed : $!";
my $out = `chmod 777 $full 2>&1`;
$? ne 0 and die "'chmod 777 $full' failed : $!";
!defined(listen($fh, 5)) and die "listen failed : $!";
$me->{select}->add(\*$fh);
$me->{handles}->{fileno(\*$fh)} = $file;
}
sub setup_remove {
my ($me, $file) = @_;
my $full = $me->prepare($file);
my $out = `touch $full/remove 2>&1`;
$? != 0 and die "touch $full/remove failed : $out";
}
sub handler {
my $me = shift;
$me->{select} = IO::Select->new();
foreach my $file (keys(%{$me->{files}})){
my $handler = $me->{files}->{$file};
if(ref($handler) eq "ARRAY"){
$me->setup_sock($file, @$handler);
}
elsif($handler eq "remove"){
$me->setup_remove($file);
}
else {
die "Bad handler for '$file'";
}
}
while(1){
my @ready = $me->{select}->can_read();
foreach my $sock (@ready){
my $file = $me->{handles}->{fileno($sock)};
!defined($file) and die "Couldn't map from socket to file";
!accept(CONN, $sock) and die "accept failed : $!";
my ($handler, $mode) = @{$me->{files}->{$file}};
(!defined($handler) || !defined($mode)) and
die "Couldn't map from file to handler";
my $output;
if($mode eq "rw"){
my $input = join("", <CONN>);
$output = $handler->($input);
}
else {
$output = $handler->();
}
print CONN $output;
close CONN;
}
}
}
1;
|