CfgTie::TieGeneric - A generic hash that automatically binds others


CfgTie documentation Contained in the CfgTie distribution.

Index


Code Index:

NAME

Top

CfgTie::TieGeneric -- A generic hash that automatically binds others

SYNOPSIS

Top

This is an associative array that automatially ties other configuration hashes

DESCRIPTION

Top

This is a tie to bring other ties together automatically so you, the busy programmer and/or system administrator, don't have to. The related Perl module is not loaded unless it is needed at runtime.

        my %gen;
        tie %gen, 'CfgTie::TieGeneric';

Primary, or well-known, keys

env

This refers directly to the ENV hash.

group
mail

This is a special key. It forms a hash, with subkeys. See below for more information

net

This is a special key. It forms a hash with additional subkeys. See below for more details.

user

This is a link to the TieUser module (CfgTie::TieUser).

Composite

Composite primary keys are just like absolute file paths. For example, if you wanted to do something like this:

        my %lusers = $gen{'user'};
        my $Favorite_User = $lusers{'mygirl'};

You could just do:

        my $Favorite_User = $gen{'/users/mygirl'};

others...

These are the things automatically included in. This will be described below.

Subkeys for mail

aliases

CfgTie::TieAliases

Subkeys for net

host

CfgTie::TieHost

service

CfgTie::TieServ

protocol

CfgTie::TieProto

addr

CfgTie::TieNet

How other ties are automatically bound

Other keys are automatically (if it all possible) brought in using the following procedure:

1. If it is something already linked to it, that thingy is automatically returned (of course).
2. If the key is simple, like AABot, we will try to use AABot; If that works we will tie it and return the results.
3. If the key is more complex, like /OS3/Config, we will try to see if OS3 is already tied (and try to tie it, like above, if not). If that works, we will just look up Config in that hash. If it does not work, we will try to use and tie OS3::Config, OS3::TieConfig, and OS3::ConfigTie. If any of those work, we return the results.
4. Otherwise, undef will be returned.

See Also

Top

CfgTie::TieAliases, CfgTie::TieGroup, CfgTie::TieHost, CfgTie::TieMTab, CfgTie::TieNamed, CfgTie::TieNet, CfgTie::TiePh, CfgTie::TieProto, CfgTie::TieRCService, CfgTie::TieRsrc, CfgTie::TieServ, CfgTie::TieShadow, CfgTie::TieUser

Author

Top

Randall Maas (mailto:randym@acm.org, http://www.hamline.edu/~rcmaas/)


CfgTie documentation Contained in the CfgTie distribution.

#!/usr/bin/perl -w
#Copyright 1998-2001, Randall Maas.  All rights reserved.  This program is free
#software; you can redistribute it and/or modify it under the same terms as
#PERL itself.

package CfgTie::TieGeneric;
use Secure::File;
use vars qw($VERSION @ISA);
use AutoLoader 'AUTOLOAD';
$VERSION='0.41';

# These are the builtins that we always add to the global arena...

# This forms the abstract tie for the net sub-hash
my $net_builtins ={host=>['CfgTie::TieHost'],
      service=>['CfgTie::TieServ'],
      protocol=>['CfgTie::TieProto'],
      addr    =>['CfgTie::TieNet']
    };

# This forms the abstract tie for the mail sub-hash
my $mail_builtins={aliases=>['CfgTie::TieAliases']};

my $builtins =
     {
        user => ['CfgTie::TieUser'],
        group =>['CfgTie::TieGroup'],
#        env =>  \%main'ENV,
        mail => ['CfgTie::TieGeneric', $mail_builtins],
        net =>  ['CfgTie::TieGeneric', $net_builtins], 
        runlevel=>['CfgTie::TieRCService'],
     };

use CfgTie::TieGroup;
use CfgTie::TieServ;
use CfgTie::TieProto;
use CfgTie::TieNet;
use CfgTie::TieHost;
@ISA=qw(CfgTie::TieGroup CfgTie::TieServ  CfgTie::TieProto
	CfgTie::TieNet  CfgTie::TieHost AutoLoader);
1;
__END__


sub TIEHASH
{
   my ($self,$BuildIns) =@_;
   if (!defined $BuildIns) {$BuildIns = $builtins;}
   my $node = {builtins => $BuildIns};
   return bless $node, $self;
}
sub new {TIEHASH(@_);}

my $Node_Separator = '/';

sub EXISTS
{
   my ($self,$key)=@_;

   if (!defined $key) {return 0;}

   #if the $key has a separator in it, check the cache.
   if (exists $self->{Cache}->{$key})   {return 1;}

   # Check to see if it is already mapped in, and overrides ours
   if (exists $self->{Contents}->{$key}) {return 1;}

   #At this point, it is not mapped in.
   #Try to automagically add it in..
   #First try to use a builtin if possible
   if (exists $self->{builtins}->{$key}) {return 1;}

   #recursively try to find it...
   my ($LeftKey, $RightKey);
   if ($key =~ /^(.*)\/([^\/]+)$/)
     {$LeftKey=$1; $RightKey=$2;}
    else
     {
        #Finally try to mount the thingy
        eval "use $key";
        tie %{$self->{Contents}->{$key}}, $key;
	return exists $self->{Contents}->{$key};
     }
   if (!EXISTS($self, $LeftKey)) {return 0;}

   # stick it in the quick look up cache
   my $X = FETCH($self, $LeftKey);
   $self->{Cache}->{$key} = $X->{$RightKey};
   return 1;
}

sub FETCH
{
   my ($self,$key)=@_;
   if (!EXISTS($self,$key)) {return;}
   #If we fully cached the long key, get already
   if (!exists $self->{Contents}->{$key})
     {
        my ($A,$B) = @{$self->{builtins}->{$key}};

        #load the perl module
        eval "use $A";

        #Tie in the key
        tie %{$self->{Contents}->{$key}}, $A,$B;
     }
   if (exists $self->{Cache}->{$key}) {return $self->{Cache}->{$key};}
   #Try to get the local thing first
   if (exists $self->{Contents}->{$key}) {return $self->{Contents}->{$key};}
   return undef;
}

sub HTML($)
{
   my $self=shift;
   my $A='';
   for (my $I=FIRSTKEY($self); $I; $I=NEXTKEY($self,$I))
    {
       $A.="<tr>".CfgTie::Cfgfile::td("<a href=\"$I\">$I</a>")."</tr>";
    }
   CfgTie::Cfgfile::table('Directory',$A,1);
}

sub FIRSTKEY
{
   my $self = shift;
   my $a = keys %{$self->{Contents}};

   my $b = scalar each %{$self->{Contents}};
   if ($b) {return $b;}

   #Scan thru the builtins
   my $c = keys %{$self->{builtins}};
   return scalar each %{$self->{builtins}};
}

sub NEXTKEY
{
   my $self = shift;
   my $lastkey=shift;
   my $a = scalar each %{$self->{Contents}};
   if ($a) {return $a;}

   if (exists $self->{Contents}->{$lastkey})
     {
        #Prime it with a psuedo FIRSTKEY
        my $b = keys %{$self->{builtins}};
     }

   while (($a) = each %{$self->{builtins}})
    {
       if (!exists $self->{Contents}->{$a})
         {return $a;}
    }
   return $a;
}