diff options
| author | fukachan <fukachan> | 2001-01-19 12:54:13 +0000 |
|---|---|---|
| committer | fukachan <fukachan> | 2001-01-19 12:54:13 +0000 |
| commit | 4377641665acbf1a4a83883241afe392e88ec112 (patch) | |
| tree | 7ed8f24cd168c95d329bcaf2958b6a63feac6bfb /fml/libexec | |
| download | fml8-4377641665acbf1a4a83883241afe392e88ec112.tar.gz fml8-4377641665acbf1a4a83883241afe392e88ec112.tar.bz2 fml8-4377641665acbf1a4a83883241afe392e88ec112.zip | |
Initial revision
Diffstat (limited to 'fml/libexec')
| -rw-r--r-- | fml/libexec/Standalone.pm | 78 | ||||
| -rw-r--r-- | fml/libexec/boot.ja.html | 75 | ||||
| -rwxr-xr-x | fml/libexec/fml | 121 | ||||
| -rwxr-xr-x | fml/libexec/fmlwrapper | 103 |
4 files changed, 377 insertions, 0 deletions
diff --git a/fml/libexec/Standalone.pm b/fml/libexec/Standalone.pm new file mode 100644 index 00000000..efabc7bf --- /dev/null +++ b/fml/libexec/Standalone.pm @@ -0,0 +1,78 @@ +#-*- perl -*- +# +# Copyright (C) 2001 Ken'ichi Fukamachi +# All rights reserved. This program is free software; you can +# redistribute it and/or modify it under the same terms as Perl itself. +# +# $Id$ +# $FML$ +# + + +package Standalone; + +use strict; +use Carp; + +# Descriptions: load "key = value" style configuration. +# It is available to use the following style. +# key = value1 value2 +# value3 +# XXX This file is non-Object Oriented style but +# XXX this is minimum module used in standalone program. +# Arguments: $file +# Side Effects: none +# Return Value: reference to configuration hash +sub load_cf +{ + my ($file) = @_; + my $config = {}; + + use FileHandle; + my $fh = new FileHandle $file; + + if (defined $fh) { + my $curkey; + while (<$fh>) { + next if /^\#/; + chop; + + if (/^([A-Za-z]\w+)\s+=\s*(.*)/) { + my ($key, $value) = ($1, $2); + $curkey = $key; + $config->{$key} = $value; + } + if (/^\s+(.*)/) { + $config->{ $curkey } .= " ". $1; + } + } + $fh->close; + } + else { + croak("Error: cannot open $file"); + } + + _expand_variables( $config ); + return $config; +} + + +# Descriptions: expand $var to the value of $var. +# Arguments: $ref_to_config +# Side Effects: rewrite the given $config +# Return Value: none +sub _expand_variables +{ + my ($config) = @_; + + # expand $xxx style variables + no strict 'refs'; + for my $x (keys %$config) { $$x = $config->{ $x };} + for (keys %$config) { + $config->{ $_ } =~ s/\$([a-z_]+)/${$1}/g; + } +} + + + +1; diff --git a/fml/libexec/boot.ja.html b/fml/libexec/boot.ja.html new file mode 100644 index 00000000..2694eedd --- /dev/null +++ b/fml/libexec/boot.ja.html @@ -0,0 +1,75 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> +<HTML> +<HEAD> +<TITLE> +net/fml ブートの仕方 +</TITLE> +<META http-equiv="Content-Type" + content="text/html; charset=EUC-JP"> +</HEAD> + +<BODY BGCOLOR="#E6E6FA"> +<!-- ================== body =========================================== --> + +<UL> + <LI> libexec/fmlwrapper (wrapper) + <BR> + Bootstrap() を起動する。 + <UL> + <LI> /etc/fml/main.cf を読み込む。 + 読み込むと fml のバージョンが分かる。 + + <LI> @ARGV を評価し、 + どの config.cf 群をロードすればいいのかを準備する。 + default_config.cf はバージョン依存であるので、 + ここで評価することに注意。 + + <LI> libexec/fml ( バージョン依存 )ファイルを + ロードし、 + <UL> + <LI> + ProcessSwitch() を実行して、配送用、コマンドモード用 + プログラム/プロセスなどへ制御を移す(分岐する)。 + + <LI> + $0 から自分の名前を知り、 + どのプロセスへ分岐すればいいのかを判断する。 + + <LI>(ポリモーフィズム) + ダイナミックバインディングし、 + プロセスオブジェクトを生成する( fork(2) という意味ではない)。 + そして、プロセスをスタートさせる。 + + 具体的には + <PRE> + $process = new FML::Process::なにか; + $process->run() + </PRE> + を実行する。 + + </UL> +</UL> + +<PRE> +fmlwrapper (uses) Standalone.pm + | + * 動的にライブラリ(バージョン情報を含む)を選択する + 例: /usr/local/lib/fml/5.000/ほえ/ほえ.pm + | + fml + * 動的にクラスをバインディングしつつ、プロセススタートする。 + 実際のコードは $process->run() などとなるが、書き下すと + このようになるだろう。 + + FML::Process::Distribute->run() | + FML::Process::Command->run() |-(uses)-> FML::Process::Kernel + FML::Process::Mead->run() | | + |- FML::Parse + |- FML::Config + |- FML::Log + |- ... その他 ... +</PRE> + +<!-- =================================================================== --> +</BODY> +</HTML> diff --git a/fml/libexec/fml b/fml/libexec/fml new file mode 100755 index 00000000..cdc342f5 --- /dev/null +++ b/fml/libexec/fml @@ -0,0 +1,121 @@ +#!/usr/local/bin/perl -w +#-*- perl -*- +# +# Copyright (C) 2000 Ken'ichi Fukamachi +# All rights reserved. +# +# $FML$ +# + +package FML; + +use vars qw($debug); +use strict; +use Carp; + + +# Descriptions: top level process switch +# 1. initialize processes and load configurations from *.cf +# switch to each process according with $0 and @ARGV. +# 2. parse the incoming message(mail) +# 3. start the main transaction +# lock, execute main routine, unlock +# 4. inform error messages, clean up and more ... +# Arguments: $args +# XXX non OO interface +# Side Effects: process running :-) +# Return Value: none +sub main::ProcessSwitch +{ + my ($args) = @_; + + # 1. create process + my $pkg = _package_we_use($args); + eval qq{ require $pkg; }; # XXX require() needs bare words. + $pkg->import(); # fake to use() method. + my $process = $pkg->new($args); # create a new process object + + # 2. parse the incoming message (e.g. STDIN) + $process->prepare($args); + + # 3. start main transaction + $process->run($args); + + # 4. closing the process + $process->finish($args); +} + + +# Descriptions: determine package we need and require() it if needed. +# Arguments: $args +# XXX non OO interface +# Side Effects: +# Return Value: FML::Process::SOMETHING process object +sub _package_we_use +{ + my ($args) = @_; + my $name = $args->{ myname }; + my $pkg = ''; + + if ($name eq 'fml.pl' || $name eq 'distribute') { + $pkg = 'FML::Process::Distribute'; + } + elsif (( $name eq 'fml.pl' && $args->{ options }->{ ctladdr }) || + $name eq 'command') { + $pkg = 'FML::Process::Command'; + } + elsif ($name eq 'fmlserv') { + $pkg = 'FML::Process::Fmlserv'; + } + elsif ($name eq 'mead') { + $pkg = 'FML::Process::Mead'; + } +} + + + +=head1 NAME + +fml -- net/fml switch programs + +=head1 SYNOPSIS + + fml + +=head1 DESCRIPTION + +libexec/fml.pl, the wrapper, executes this program. For example, The +incoming mail to elena@fml.org kicks off libexec/distribute via +libexec/fml.pl, whereas mail to elena-ctl@fml.org kicks off +libexec/command finally. + + incoming_mail => + elena@fml.org => fml.pl => libexec/distribute + elena-ctl@fml.org => fml.pl => libexec/command + elena-admin@fml.org => forwarded to administrator(s) + OR + => libexec/mead + +C<-d> + debug on. + +=head1 FLOW AROUND COMPONENTS + + | <=> FML::BaseSystem + | load configuration files + | start logging service + | + | STDIN => FML::Parse + | $CurProc->{'incoming_mail'} <= + | $CurProc->{'credential'} + | + | (lock) + | prepare article + | $CurProc->{'article'} is spooled in. + | $CurProc->{'article'} <=> Service::SMTP + | (unlock) + V + +=cut + +1; diff --git a/fml/libexec/fmlwrapper b/fml/libexec/fmlwrapper new file mode 100755 index 00000000..33e0d8f1 --- /dev/null +++ b/fml/libexec/fmlwrapper @@ -0,0 +1,103 @@ +#!/usr/local/bin/perl -w +#-*- perl -*- +# +# Copyright (C) 2000-2001 Ken'ichi Fukamachi +# All rights reserved. +# +# $Id$ +# $FML$ +# + +use vars qw($MainCF); +use strict; +use Carp; + +# main configuration file for directory switch +$MainCF = '/etc/fml/main.cf'; + +eval { &Bootstrap();}; +if ($@) { print STDERR "Error: ", $@, "\n";} + +exit 0; + + +BEGIN { + use File::Basename; + unshift(@INC, dirname($0)); + require Standalone; +} + + +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}"); + + # 1.1 o.k. try to load main.cf + my $config = Standalone::load_cf($MainCF); + my $libexec_dir = $config->{ libexec_dir }; + my $default_config = $config->{ default_config }; + + # 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 = ($default_config); + my %optargs = (); + for (@ARGV) { + if ($_ eq '--ctladdr') { + $optargs{ ctladdr } = 1; + } + elsif (-d $_) { + push(@cf, "$_/config.cf") if -f "$_/config.cf"; + } + elsif (-f $_) { + push(@cf, "$_"); + } + } + + # 3. reset @INC + use lib qw( $config->{ local_lib_dir } $config->{ lib_dir }); + + # 4. inspect my mode from $0 + use File::Basename; + my $myname = basename($0); + + # 5. o.k. here we go! + require "$libexec_dir/fml"; + ProcessSwitch( + { + main_config => $config, + cf_list => \@cf, + myname => $myname, + options => \%optargs, + }); +} + + +=head1 NAME + +fml.pl -- wrapper which executes the real fml5 programs. + +=head1 SYNOPSIS + +fml.pl C<[-d]> C<[--ctladdr]> $mail_list_address + +=head1 DESCRIPTION + +C<$mail_list_address> + Hmm,,,? + +C<-d> + debug on. + +C<--ctladdr> + execute fml/libexec/command. + +=cut |
