#!/usr/bin/perl -w # # This program hopefully stores and manages all kinds of plain text files. # All inserted items are stored in .xml library. All items are also # tagged with various tags, which provides sorting, searching and other # via using this tags. # On second stance, this program creates 2 directories, from/where are # files restored from xml. Obviously is one directory populated with # executable files and is in $PATH environment variable, contains # user defined functions, aliases for commands and other macros. # # Copyright (C) 2008 nettezzaumana # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # # Author: nettezzaumana # # Thanks to all my favourite heavy_metal bands #-------------------------------------------------------- # Includes Section: use strict; use Getopt::Long; use XML::Generator; use IO::File; use File::stat; use File::Spec; use Time::localtime; our($EXECUTION_DIR, $PLAINTEXT_DIR, $LIB_FILE, $INTERNAL_EDITOR, @USER_INPUT, $NUM_ARGS); #-------------------------------------------------------- # Global Variables Section: # defines a directory, from where will be launched executables. # defines directory, where will be stored plain text. # it is possible, to give a hard parameter, e.g: # $EXECUTION_DIR = /home/userprogs; $EXECUTION_DIR = $ENV{'HOME'}."/bin"; $PLAINTEXT_DIR = $ENV{'HOME'}."/plain"; # same as above. There is defined main libfile $LIB_FILE = $ENV{'HOME'}."/.my_funcs.xml"; # enter full path to wanted editor e.g. # $INTERNAL_EDITOR = /usr/bin/nano; # note, that if you wish to use a 'which' command # you NEED to 'chomp' a trailing new line.. chomp($INTERNAL_EDITOR = `which vi`); #-------------------------------------------------------- # Funct Section: sub tell_me_version { # !! Here is stored version info !! print << 'EOT'; func_creator version 0.9-alfa.1 EOT exit 0; }; sub tell_me_usage { print << 'EOT'; Usage: plain2xml [command] plain2xml [action] [options] Commands: -V, --version :: print version of this program. -h, -?, --help :: show this message. -W, --why :: print some speeches about this program, which may hopefully explain you, why you can't live longer without this enhancement :) There is also described, how it works. -gpl, --license :: print license of this program. Expectable content of GPL. -S, --settings :: print global settings. Actions: -a , --add :: add new item. Name for it is necessary. Then need at least specify target file. Options: --if , --infile :: Path to file to add. --meta :: metadata in form: "opt1=?,opt2=?" EOT exit 0; }; sub tell_me_why { print << 'EOT'; This program serves such a manager of user defined scripts, commands and other macros. Main target why use this program is simple :: you could store all your scripts and shortcuts for commands in one file and in case of change (or crash) your system, you will be able to restore all of this things with easy and fast method. This program requires only one thing :: system with accessible perl interpret and your minimal invention when install or run first time. Note, that this program does not do any syntax check. It will add and use items exactly same as you pass them to this program. So, how it works? EOT exit 0; }; sub show_me_gpl { system('man gpl'); exit 0; }; sub show_me_settings { print "execution directory: ".$EXECUTION_DIR."\n"; print "plain-text directory: ".$PLAINTEXT_DIR."\n"; print "library file: ".$LIB_FILE."\n"; print "internal editor: ".$INTERNAL_EDITOR."\n"; exit 0; }; # Build array to write, uses snoop_file(). Returns @XML_ITEM # .xml item has 5 levels: # in 1st is stored only name of item and is named "item". # in 2nd is stored fetched info about file and is named "file". # in 3rd are stored user metadata about item and is named "meta". # 4th contains editable description in plain-text form and is named "description". # 5th contains content of item and is named "body". sub create_item { my($DATE, $USERNAME, $TYPE, $USER_CLASS); my(@DESCRIPTION); # Base info $USERNAME = $ENV{'USER'}; chomp($DATE = `date +%Y:%m:%d-%H:%M:%S`); my $ITEM_NAME = $_[0]; my %SNOOPED = snoop_file($_[1]); # fetch some info about file my @BODY = read_file($_[1]); # fill content of file into @BODY if($_[2]) { my @META = $_[2]; @META = split(/,/,join(',',@META)); foreach(@META) { if($_ =~ s/^class=//) { $USER_CLASS = $_; } elsif($_ =~ s/^type=//) { $TYPE = $_; } else { print "unsupported option: $_\n"; next; }; }; }; $TYPE = 'omitted' if not $TYPE; $USER_CLASS = 'omitted' if not $USER_CLASS; # build array my $array = XML::Generator->new(':pretty'); my @XML_ITEM = $array->item(({ name => "$ITEM_NAME" }), $array->file(({ source => $SNOOPED{"source"}, owner => $SNOOPED{"uid"}, group => $SNOOPED{"gid"}, perm => $SNOOPED{"mode"}, 'time' => $SNOOPED{"timestamp"} }), $array->meta(({ added => "$DATE", user => "$USERNAME", type => "$TYPE" , class => "$USER_CLASS" }), $array->description("@DESCRIPTION"), $array->body("@BODY") ))); return(@XML_ITEM); }; sub test_input_file { my $ITEM = "@_"; die "file does not exist.\n" if not (-e $ITEM); die "it is not plain text file.\n" if not (-T $ITEM); die "you have no read permissions.\n" if not (-r $ITEM); }; sub test_new_item_name { my $ITEM = "@_"; die "length of name of new item must be at least 4 characters\n" if not (length($ITEM) > "3"); }; # fetch base fileinfo :: # returns hash %INPUT_FILE contains info about owner, gid, source and perms of item. sub snoop_file { my $ITEM = "@_"; my %INPUT_FILE = ( "source" => 'unknown', "uid" => 'unknown', "gid" => 'unknown', "mode" => 'unknown', "timestamp" => 'unknown', ); my $sx = stat($ITEM); $INPUT_FILE{"source"} = File::Spec->rel2abs($ITEM); $INPUT_FILE{"uid"} = $sx->uid; $INPUT_FILE{"gid"} = $sx->gid; $INPUT_FILE{"mode"} = sprintf "%04o", $sx->mode & 07777; $INPUT_FILE{"timestamp"} = ctime($sx->mtime); return(%INPUT_FILE); }; # returns @CONTENT_OF_FILE, contains content of file :D.. sub read_file { my $ITEM = "@_"; my @CONTENT_OF_FILE; my $file = new IO::File; if($file->open("<$ITEM")) { @CONTENT_OF_FILE = <$file>; $file->close; } else { print "unexpected error while opening $ITEM\n"; exit 1; }; return(@CONTENT_OF_FILE); }; # End Funct Section.. #-------------------------------------------------------- # Script Body.. @USER_INPUT = @ARGV; $NUM_ARGS = @USER_INPUT; if(!@USER_INPUT) { print << 'EOT'; This script expects at least one parameter. Try '-h' for help. Exiting now.. EOT exit 1; }; # Parse @ARGV my($version, $help, $why, $license, $settings, $new_item, $meta_data, $input_file); #Getopt::Long::Configure("bundling", "no_ignore_case", "no_auto_abbrev"); Getopt::Long::Configure("gnu_getopt", "no_auto_abbrev", "no_ignore_case_always"); GetOptions( "version|V" => \$version, "help|?|h" => \$help, "why|W" => \$why, "GPL|license" => \$license, "settings|S" => \$settings, "add|a=s" => \$new_item, "meta=s" => \$meta_data, "infile|if=s" => \$input_file, ) || die "bad options\n"; # printable infos, after done, program is exited tell_me_version() if $version; tell_me_usage() if $help; tell_me_why() if $why; show_me_gpl() if $license; show_me_settings if $settings; if($new_item && $input_file && !$meta_data) { test_input_file("$input_file"); test_new_item_name("$new_item"); # main action, if all correct print create_item("$new_item", "$input_file"); print "\n"; } elsif($new_item && $input_file && $meta_data) { test_input_file("$input_file"); test_new_item_name("$new_item"); # main action, if all correct print create_item("$new_item", "$input_file", "$meta_data"); print "\n"; } elsif($new_item && !$input_file) { print "missing target to add\n"; exit 1; } elsif(!$new_item && $input_file || $meta_data) { die "missing name for item and file to import" if(!$input_file); die "missing name for new item\n"; }; #-------------------------------------------------------- # Necessary ending method: print "all done\n"; exit 0;