summaryrefslogtreecommitdiff
path: root/fml/libexec
diff options
context:
space:
mode:
authorfukachan <fukachan>2001-01-19 12:54:13 +0000
committerfukachan <fukachan>2001-01-19 12:54:13 +0000
commit4377641665acbf1a4a83883241afe392e88ec112 (patch)
tree7ed8f24cd168c95d329bcaf2958b6a63feac6bfb /fml/libexec
downloadfml8-4377641665acbf1a4a83883241afe392e88ec112.tar.gz
fml8-4377641665acbf1a4a83883241afe392e88ec112.tar.bz2
fml8-4377641665acbf1a4a83883241afe392e88ec112.zip
Initial revision
Diffstat (limited to 'fml/libexec')
-rw-r--r--fml/libexec/Standalone.pm78
-rw-r--r--fml/libexec/boot.ja.html75
-rwxr-xr-xfml/libexec/fml121
-rwxr-xr-xfml/libexec/fmlwrapper103
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