#!/usr/local/bin/perl -w #-*- perl -*- # # Copyright (C) 2000-2001 Ken'ichi Fukamachi # All rights reserved. # # $Id: loader,v 1.2 2001/01/29 03:23:41 fukachan Exp $ # $FML$ # eval 'exec /usr/local/bin/perl -S $0 ${1+"$@"}' if $running_under_some_shell; use vars qw($MainCF $running_under_some_shell); use strict; use Carp; use Getopt::Long; # main configuration file for directory switch $MainCF = '/etc/fml/main.cf'; eval { &Bootstrap();}; if ($@) { print STDERR "Error: ", $@, "\n"; exit 1;} exit 0; # Firstly we load Standalone.pm which has main.cf parser(). BEGIN { use File::Basename; unshift(@INC, dirname($0)); require Standalone; } # Descriptions: top lebel bootstrap program # which load a dispather program (process_switch) # for process switch. The flow of execution follows: # libexec/loader -> # libexec/process_switch -> # FML::Process::Something # Arguments: none # XXX this program sees $0 # (program name, == argv[0] of C language) # Side Effects: switch to the real process # Return Value: none sub Bootstrap { # 1. main.cf exists and I can open it? -f $MainCF || die("cannot find ${MainCF}"); my $fh = new FileHandle $MainCF; defined($fh) || die("cannot find ${MainCF}"); # 2. pick up *.cf files to read and set them to @cf. # We pass it to fml_loader. # pass *.cf files to libexec/{distribute,command} # for example # @cf = ( /etc/fml/defaults/$VERSION/default_config.cf # /etc/fml/domains/$DOMAIN/config.cf # /var/spool/ml/elena/config.cf # ); my @cf = (); my %options = (); my $my_default_config = ''; my $ml_home_dir = ''; # e.g. /var/spool/ml/elena GetOptions(\%options, qw(ctladdr! debug! params=s -c=s) ); for (@ARGV) { if (-d $_) { $ml_home_dir = $_; push(@cf, "$_/config.cf") if -f "$_/config.cf"; } elsif (-f $_) { push(@cf, $_); } } # 2.1 o.k. try to load main.cf my $main_cf = Standalone::load_cf($options{'c'} || $MainCF, $options{'params'} ); my $libexec_dir = $main_cf->{ libexec_dir }; my $default_config = $my_default_config || $main_cf->{ default_config }; unshift(@cf, $default_config); # 3. reset @INC unshift(@INC, split(/\s+/, $main_cf->{ lib_dir })); unshift(@INC, split(/\s+/, $main_cf->{ local_lib_dir })); # 4. inspect my mode from $0 use File::Basename; my $myname = basename($0); # debug; if ($0 =~ /loader/) { use Data::Dumper; print Dumper( $main_cf ); sleep 3; } # 5. o.k. here we go! if (-f "$libexec_dir/process_switch") { my ($args, $pkg); $args = { fml_version => $main_cf->{ fml_version }, myname => $myname, ml_home_prefix => $main_cf->{ ml_home_prefix }, ml_home_dir => $ml_home_dir, cf_list => \@cf, options => \%options, }; # See libexec/process_switch on ProcessSwitch() require "$libexec_dir/process_switch"; $pkg = ProcessSwitch($args); # See FML::Process::Kernel module on ProcessStart() ProcessStart($pkg, $args); } else { croak("$libexec_dir/fml is not found."); } } =head1 NAME loader -- the wrapper which executes a real fml5 program. =head1 SYNOPSIS loader C<[-c main.cf]> C<[--debug]> C<[--ctladdr]> [ml_home_dir] =head1 DESCRIPTION The loader resolves fml version dependence. It checks /etc/fml/main.cf and prepare @INC for some fml version. The real process switch routine is dependent on fml version. C switches itself to a program specified by $0. C analyzes several conditions specified by main.cf, @INC and $0 et. al. The swithing is done in libexec/fml/$VERSION/process_switch. See C for more details on process switching. C<-c main.cf> main.cf alternative C<--debug> debug on. C<--ctladdr> execute fml/libexec/command. C<--params> --params 'key1=value1 key2=value2 ...' =cut