#!/usr/bin/env perl
# pyreg.pl: registry-style store that appears as a Unix directory tree (Perl version).
#
# Keys look like HKEY_CURRENT_USER\Software\MyApp and hold named values.
# The store lives in ~/.pyreg.json and is materialised as files under ~/pyreg/.
#
# Usage:
# pyreg.pl set <key> <name> <value>
# pyreg.pl setfile <key> <name> <file> store a script's source as a value
# pyreg.pl get <key> <name>
# pyreg.pl run <key> <name> run a stored script (.py .pl .sh)
# pyreg.pl list
# pyreg.pl mount
use strict;
use warnings;
use JSON::PP;
use File::Path qw(make_path);
use File::Spec;
use File::Temp qw(tempfile);
my $home = $ENV{HOME} or die "HOME not set\n";
my $store = "$home/.pyreg.json";
my $mount = "$home/pyreg";
my $json = JSON::PP->new->canonical->pretty;
sub load {
return {} unless -e $store;
open my $fh, '<', $store or die "cannot read $store: $!\n";
local $/;
my $data = <$fh>;
close $fh;
return decode_json($data);
}
sub save {
my ($reg) = @_;
open my $fh, '>', $store or die "cannot write $store: $!\n";
print $fh $json->encode($reg);
close $fh;
}
sub key_path {
my ($key) = @_;
(my $k = $key) =~ s{/}{\\}g;
my @parts = grep { length } split /\\/, $k;
die "invalid key\n" if grep { $_ eq '..' || $_ eq '.' } @parts;
return File::Spec->catdir(@parts);
}
sub do_mount {
my ($reg) = @_;
make_path($mount);
for my $key (sort keys %$reg) {
my $dir = File::Spec->catdir($mount, key_path($key));
make_path($dir);
for my $name (sort keys %{ $reg->{$key} }) {
next if $name =~ m{/} || $name eq '.' || $name eq '..';
my $path = "$dir/$name";
open my $fh, '>', $path or die "cannot write $path: $!\n";
print $fh $reg->{$key}{$name};
close $fh;
chmod 0755, $path if $name =~ /\.(py|pl|sh)$/;
}
}
print "mounted at $mount\n";
}
my ($cmd, @a) = @ARGV;
unless (defined $cmd) { print "usage: $0 set|setfile|get|run|list|mount ...\n"; exit 0; }
my $reg = load();
if ($cmd eq 'set' && @a == 3) {
$reg->{ $a[0] }{ $a[1] } = $a[2];
save($reg);
do_mount($reg);
}
elsif ($cmd eq 'setfile' && @a == 3) {
open my $fh, '<', $a[2] or die "cannot read $a[2]: $!\n";
local $/;
$reg->{ $a[0] }{ $a[1] } = <$fh>;
close $fh;
save($reg);
do_mount($reg);
}
elsif ($cmd eq 'get' && @a == 2) {
print $reg->{ $a[0] }{ $a[1] } // '', "\n";
}
elsif ($cmd eq 'run' && @a == 2) {
my $src = $reg->{ $a[0] }{ $a[1] };
die "no such value\n" unless defined $src;
my %interp = (py => 'python3', pl => 'perl', sh => 'bash');
my ($ext) = $a[1] =~ /\.(\w+)$/;
my $prog = $interp{ $ext // '' } or die "don't know how to run '$a[1]'\n";
my ($fh, $tmp) = tempfile(SUFFIX => ".$ext", UNLINK => 1);
print $fh $src;
close $fh;
system($prog, $tmp);
exit($? >> 8);
}
elsif ($cmd eq 'list') {
print $json->encode($reg);
}
elsif ($cmd eq 'mount') {
do_mount($reg);
}
else {
die "bad arguments; run with no arguments for usage\n";
}
No comments:
Post a Comment
no thanks
Note: Only a member of this blog may post a comment.