diff options
| author | fukachan <fukachan> | 2005-07-27 12:21:35 +0000 |
|---|---|---|
| committer | fukachan <fukachan> | 2005-07-27 12:21:35 +0000 |
| commit | 02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1 (patch) | |
| tree | a1a9302fc1d5d74b41fe5659504c59501e2f5ab9 /fml/doc | |
| parent | 1a4284d5533f07c7b4828a5283281e95b8bd3f3e (diff) | |
| download | fml8-02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1.tar.gz fml8-02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1.tar.bz2 fml8-02f0eb5231edfb665704bd0cfd9bfbe5ec59fae1.zip | |
sync and translated.
Diffstat (limited to 'fml/doc')
| -rw-r--r-- | fml/doc/en/tutorial/internals/CURPROC.sgml | 16 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/PCB.sgml | 64 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/bootloader.sgml | 221 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/cgi.examples.sgml | 125 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/config.cf.sgml | 16 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/credential.sgml | 4 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/dbms.sgml | 28 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/directory.sgml | 49 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/language.sgml | 224 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/lock.sgml | 83 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/main.cf.sgml | 119 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/merge.sgml | 122 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/restriction.sgml | 202 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/struct.sgml | 29 | ||||
| -rw-r--r-- | fml/doc/en/tutorial/internals/userctl.sgml | 57 |
15 files changed, 1331 insertions, 28 deletions
diff --git a/fml/doc/en/tutorial/internals/CURPROC.sgml b/fml/doc/en/tutorial/internals/CURPROC.sgml index e6fc8f2b..8296e4c6 100644 --- a/fml/doc/en/tutorial/internals/CURPROC.sgml +++ b/fml/doc/en/tutorial/internals/CURPROC.sgml @@ -2,19 +2,24 @@ <screen> __parent_args => HASH { ARGV => ARRAY + ___shared_memory___ => HASH argv => ARRAY cf_list => ARRAY + curproc => FML::Process::Distribute fml_version main_cf => HASH module_info => HASH myname need_ml_name options => HASH + program_fullname program_name } __print_style => SCALAR +__start_time => SCALAR + article => HASH { body => Mail::Message header => FML::Header @@ -31,29 +36,38 @@ incoming_message => HASH { message => Mail::Message } +log_message_queue => FML::Log::Print::Simple + main_cf => HASH { - _hints + _hints => HASH config_dir debug default_command_line_option_config default_config_cf default_config_dir + default_cui_menu default_domain + default_gui_menu default_ml_home_prefix default_module_config default_paths_cf domain_default_config + domain_default_config_cf exec_prefix executable_prefix fml_group fml_owner fml_version + group_writable_config_dir lib_dir libexec_dir local_lib_dir + ml_home_prefix_maps prefix prefix_dir + primary_ml_home_prefix_map share_dir + site_default_config_cf virtual_maps } diff --git a/fml/doc/en/tutorial/internals/PCB.sgml b/fml/doc/en/tutorial/internals/PCB.sgml new file mode 100644 index 00000000..975bc3fa --- /dev/null +++ b/fml/doc/en/tutorial/internals/PCB.sgml @@ -0,0 +1,64 @@ +<para> +<screen> +module function category + <-- (get value) + --> (set value) +-------------------------------------------------------------------------------- +Error run --> error +Error finish <-- error +Fake set_emul_domain --> faker +Fake get_emul_domain <-- faker +Fake set_emul_ml_list --> faker +Fake get_emul_ml_list <-- faker +Fake set_emul_user_list --> faker +Fake get_emul_user_list <-- faker +Kernel sysflow_reopen_stderr_channel --> stderr +Kernel sysflow_reopen_stderr_channel --> stderr +Kernel sysflow_finalize_stderr_channel <-- stderr +Kernel sysflow_finalize_stderr_channel <-- stderr +Kernel sysflow_finalize_stderr_channel --> stderr +State current_process_set_ml_name <-- current_process +State current_process_get_ml_name <-- current_process +State restriction_state_set_deny_reason --> check_restrictions +State restriction_state_get_deny_reason <-- check_restrictions +State article_set_id --> article_message +State article_get_id <-- article_message +State command_context_set_ml_name --> process_command +State command_context_get_ml_name <-- process_command +State command_context_set_stop_process --> process_command +State command_context_get_stop_process <-- process_command +State command_context_set_normal_stop --> process_command +State command_context_get_normal_stop <-- process_command +State command_context_set_need_confirm --> process_command +State command_context_get_need_confirm <-- process_command +State command_context_set_admin_auth --> process_command +State command_context_get_admin_auth <-- process_command +State command_context_set_admin_password --> process_command +State command_context_get_admin_password <-- process_command +State command_context_set_try_admin_auth_request --> process_command +State command_context_reset_try_admin_auth_request --> process_command +State command_context_get_try_admin_auth_request <-- process_command +State filter_state_set_error --> filter_state +State filter_state_get_error <-- filter_state +State filter_state_spam_checker_set_error --> filter_state +State filter_state_spam_checker_get_error <-- filter_state +State filter_state_virus_checker_set_error --> filter_state +State filter_state_virus_checker_get_error <-- filter_state +State filter_state_set_tempfail_request --> filter_state +State filter_state_get_tempfail_request <-- filter_state +State smtp_server_state_set_error --> smtp_transaction +State smtp_server_state_get_error <-- smtp_transaction +State error_message_set_count <-- reply_message_count +State error_message_set_count --> reply_message_count +State error_message_get_count <-- reply_message_count +Utils incoming_message_set_cache_file_path --> incoming_message +Utils incoming_message_get_cache_file_path <-- incoming_message +Utils incoming_message_set_current_queue --> incoming_smtp_transaction +Utils incoming_message_get_current_queue <-- incoming_smtp_transaction +Utils set_language_hint --> language_hint +Utils get_language_hint <-- language_hint +Utils set_charset --> charset +Utils get_charset <-- charset +Utils get_charset <-- charset +</screen> +</para> diff --git a/fml/doc/en/tutorial/internals/bootloader.sgml b/fml/doc/en/tutorial/internals/bootloader.sgml new file mode 100644 index 00000000..e7c9d6b8 --- /dev/null +++ b/fml/doc/en/tutorial/internals/bootloader.sgml @@ -0,0 +1,221 @@ +<!-- + $FML: bootloader.sgml,v 1.13 2005/06/25 15:11:33 fukachan Exp $ +--> + + +<chapter id="bootloader"> + <title> + &fml8; boot loader to resolv version dependence dynamically + </title> + +<para> +&fml8; provides a boot loader to resolv version dependence dynamically. +For example, the loader boot straps &fml8; as follows: +<screen> +fml (libexec/distribute) boots like this ... + + functions class + ---------------------------------------- + + main::Bootstrap() libexec/loader + | + V + main::Bootstrap2() FML::Process::Switch + | + V + ProcessSwitch() FML::Process::Switch + | + | + | switch to ($obj = FML::Process:Distribute) + | + V + ProcessStart($obj,$args) FML::Process::Flow +</screen> +</para> + + +<sect1 id="bootloader.example.distribute"> + <title> + Case: distribution + </title> + +<para> +&fml8; loader boot straps like this in the case of distribution. +</para> + +<para> +/usr/local/libexec/fml/distributre (== /usr/local/libexec/fml/loader +in fact) reads /usr/local/etc/fml/main.cf and resolvers the version it +should use from $fml_version variable. Let $fml_version +current-20010501. The loader uses library perl modules under +/usr/local/lib/fml/current-20010501/. +</para> + +<para> +The loader resets @INC (perl include path). +It loads FML::Process::Switch and checks $0 (program name in process table). +The loader resolves from the name that the role is distribution. +It loads FML::Process::Distribute and switches to the class. +</para> + +<para> +The relation between program name and class (perl module) is defined +at /usr/local/etc/fml/defaults/$fml_version/modules file. +</para> + +<para> +FML::Process::Flow::ProcessStart() function drives these sequential +steps. ProcessStart() takes FML::Process::Distribute object as an +argument and drives the object. +</para> + +</sect1> + + +<sect1 id="bootloader.classes"> + <title> + FML::Process:: class structure + </title> + +<para> +<screen> +FML::Process::Distribute >-| +FML::Process::Command >-|-- FML::Process::Kernel +FML::Process::Mead >-| | + |-use-a FML::Parse + |-use-a FML::Config + |-use-a FML::Log + |-use-a ... SOMETHING ... +</screen> + +</para> +</sect1> + + +<sect1 id="bootloader.classes2"> + <title> + Modules in process execution + </title> + +<itemizedlist> + + <listitem> + <para> + libexec/loader (wrapper): + executes Bootstrap() runction. + libexec/distribute et.al. is a symlink(2) to this loader. + See under /usr/local/libexec/fml/ path. + </para> + </listitem> + + <listitem> + <itemizedlist> + <listitem> + <para> + reads /usr/local/etc/fml/main.cf and resolves $fml_version. + reset @INC by main.cf value. + Since default_config.cf is version dependent, + the loader should evaluate the file before it reads + ML specific configuration files. + </para> + </listitem> + + <listitem> + <para> + Evaluate @ARGV and resolves which ML specific configuration + files we need to load. + </para> + </listitem> + + <listitem> + <para> + load FML::Process::Switch class which is also version dependent. + </para> + + <itemizedlist> + <listitem> + <para> + The loader executes Bootstrap2() and ProcessSwitch() + to switch the context to each one such as + distribution, command mail et.al. + In this time, the loader knows the role + from $0 process name. + </para> + </listitem> + + <listitem> + <para> + Exapmle of Polymorphyism: + dynamic binding of module and creation of process + object in starting the process. + + FML::Process::Flow describes the flow of process + like this: +<screen> +$process = new FML::Process::SOMETHING; +$process->prepare($args); +$process->verify_request($args); +$process->run($args); +$process->finish($args); +</screen> + Each process should probide proper methods under + FML::Process:: class. + </para> + </listitem> + </itemizedlist> + </listitem> + </itemizedlist> + </listitem> +</itemizedlist> +</sect1> + + +<sect1 id="bootloader.resolv.mlxxx"> + <title> + Discussion: where function should resolve $ml_name and $ml_domain. + </title> + +<para> +Currently &fml8; resolves them in prepare() under FML::Process:: classes. +</para> + +<para> +Here is a part of background idea. +<screen> +main::Bootstrap() + + resoles $fml_version based on main.cf information. + + pass hints to some processes e.g. CGI. + CGI only + it should ignore invalid input. + $ml_name $and ml_domain is hard-coded in cgi scripts. + + +main::Bootstrap2() +ProcessSwitch() + + resolves the module, configuration files, library path and @INC. + + pass hints to some processes e.g. CGI. + CGI only + +ProcessStart($obj, $args) + + main process starts + + new + + prepare + resoles $ml_name and $ml_domain. + parse input from CGI using hints. + determine ml specific configuration files. + parse incoming message. + parse command line arguments. +</screen> +</para> + +</sect1> + + +</chapter> diff --git a/fml/doc/en/tutorial/internals/cgi.examples.sgml b/fml/doc/en/tutorial/internals/cgi.examples.sgml new file mode 100644 index 00000000..bf10702d --- /dev/null +++ b/fml/doc/en/tutorial/internals/cgi.examples.sgml @@ -0,0 +1,125 @@ +<!-- + $FML: cgi.examples.sgml,v 1.3 2005/06/25 15:11:33 fukachan Exp $ +--> + + +<sect1 id="cgi.internal.example.isa"> + <title> + CGI implementation: inheritance among CGI classes + </title> + +<para> +@ISA of config.cgi follow: +<screen> +FML::CGI::Menu FML::Process::CGI::Kernel FML::Process::CGI::Param +</screen> +In the case of thread.cgi, @ISA is +<screen> +FML::CGI::Thread FML::Process::CGI::Kernel FML::Process::CGI::Param +</screen> +</para> + +<para> +.cgi specific codes locate at FML::CGI:: class layer. +</para> + +<para> +FML::Process::CGI::Kernel provides the main part of CGI process +and CGI specific function run_cgi_XXX(). +If needed, FML::CGI:: class overloads this layer. +Currently, +the following methods in FML::Process::CGI::Kernel are not used. +<screen> +run_cgi_log +run_cgi_dummy +run_cgi_date +</screen> +</para> + +</sect1> + + +<sect1 id="cgi.internal.example.config.cgi"> + <title> + CGI Implementation: config.cgi + </title> + +<para> +@ISA of config.cgi is as follows: +<screen> +FML::CGI::Menu FML::Process::CGI::Kernel FML::Process::CGI::Param +</screen> +Let see processing of config.cgi below. +</para> + +<para> +config.cgi process object $curproc is a +FML::Process::CGI::Kernel class. +<screen> + new() + prepare() + verify_request() + run() + finish() +</screen> +is sequentially called from FML::Process::CGI::Kernel class. +</para> + +<para> +run() is important. run() executes the following methods sequentially. +<screen> + $curproc->html_start(); (FML::CGI::Menu) + $curproc->_drive_cgi_by_table(); (FML::Process::CGI::Kernel) + $curproc->html_end(); (FML::CGI::Menu) +</screen> +_drive_cgi_by_table() prepares the screen. +This function calls the main part of CGI. +</para> + +<para> +$curproc->_drive_cgi_by_table() +calles the following run_XXX() methods. +<screen> +run_cgi_main (FML::CGI::Menu) +</screen> +calls cgi_execute_command (FML::Process::CGI::Kernel) to +execute FML::Command::Admin::$COMMAND via FML::Command class. +This is the main part of command execution via CGI but +the screen creation is a role of another part. +</para> + +<para> +For example, consider subscribe an address via CGI. +run_cgi_main() executes the real process of subscription. +Instead run_cgi_menu() creates input menu. +Former calls FML::Command::Admin::subscribe::process() method, +latter calls FML::Command::Admin::subscribe::cgi_menu() method. +</para> + +<para> +There are several other run_cgi_XXX() methods. They are optional for +screen creation. +</para> + +<para> +The following run_cgi_XXX() uses the default method. +<screen> +run_cgi_title FML::Process::CGI::Kernel (show title) +run_cgi_options FML::Process::CGI::Kernel (show language selection) +</screen> +.cgi specific methods are as follows: +<screen> +run_cgi_navigator FML::CGI::Menu +run_cgi_help FML::CGI::Menu +run_cgi_command_help FML::CGI::Menu +run_cgi_menu FML::CGI::Menu +</screen> +</para> + +<para> +run_cgi_menu() executes +FML::Command::Admin::COMMAND::cgi_menu() +via cgi_execute_cgi_menu() method. +</para> + +</sect1> diff --git a/fml/doc/en/tutorial/internals/config.cf.sgml b/fml/doc/en/tutorial/internals/config.cf.sgml index 154c0db6..db55cee8 100644 --- a/fml/doc/en/tutorial/internals/config.cf.sgml +++ b/fml/doc/en/tutorial/internals/config.cf.sgml @@ -1,9 +1,9 @@ <!-- - $FML: config.cf.sgml,v 1.1 2003/07/27 01:29:28 fukachan Exp $ + $FML: config.cf.sgml,v 1.2 2003/08/03 05:28:48 fukachan Exp $ $jaFML: config.cf.sgml,v 1.11 2003/06/20 22:23:14 fukachan Exp $ --> -<chapter> +<chapter id="internal.config.cf"> <title> Configuration file: config.cf </title> @@ -21,13 +21,13 @@ You can customize each ML differently. </para> <para> -In the case of &fml4;, there are $DIR and config.ph in ML home -directory. This "config.ph" file is a perl script. +In the case of &fml4;, there is a config.ph in ML home directory, +$DIR (e.g. /var/spool/ml). This "config.ph" file is a perl script. </para> <para> There is a config.cf file in &fmldevel;, too. -But the format is diffrent. The format is like this: +But the format is different. The format is like this: <screen> variable = value </screen> @@ -35,6 +35,10 @@ variable = value It is similar to postfix or .ini files. </para> +<para> +It is similar to a perl module. You can write perl codes after =cut line. +</para> + <sect2> <title> @@ -128,7 +132,7 @@ since the last $a overwrites the previous one. <!-- ======================================= --> -<sect1> +<sect1 id="config.cf.format.extension"> <title> Extension to postfix style </title> diff --git a/fml/doc/en/tutorial/internals/credential.sgml b/fml/doc/en/tutorial/internals/credential.sgml index 825b345c..e771ea31 100644 --- a/fml/doc/en/tutorial/internals/credential.sgml +++ b/fml/doc/en/tutorial/internals/credential.sgml @@ -1,5 +1,5 @@ <!-- - $FML: credential.sgml,v 1.1 2003/07/29 12:13:54 fukachan Exp $ + $FML: credential.sgml,v 1.2 2003/08/03 05:28:48 fukachan Exp $ $jaFML: credential.sgml,v 1.3 2003/04/15 14:51:40 fukachan Exp $ --> @@ -14,7 +14,7 @@ User authentication is provided by methods of FML::Credential class. -<sect1> +<sect1 id="credential.implementation"> <title> Discussion: FML::Credential implementation </title> diff --git a/fml/doc/en/tutorial/internals/dbms.sgml b/fml/doc/en/tutorial/internals/dbms.sgml index c608bf9e..ae23be7e 100644 --- a/fml/doc/en/tutorial/internals/dbms.sgml +++ b/fml/doc/en/tutorial/internals/dbms.sgml @@ -1,5 +1,5 @@ <!-- - $FML: dbms.sgml,v 1.1 2003/07/29 12:13:54 fukachan Exp $ + $FML: dbms.sgml,v 1.2 2003/08/03 05:28:49 fukachan Exp $ $jaFML: dbms.sgml,v 1.5 2003/05/31 08:51:09 fukachan Exp $ --> @@ -9,6 +9,16 @@ </title> +<para> +This chapter describes how to handle persistent data. +You should use DBMS (DataBase Management System) for that data. +See +<link linkend="db.module"> +<xref linkend="db.module"> +</link> +on the internal use database. +</para> + <sect1 id="dbms.overview"> <title> Overview @@ -32,20 +42,4 @@ preprocessing module calling IO::Adapter should handle it. </sect1> -<sect1 id="dbms.todo"> - <title> - TODO - </title> - -<para> -Consider if methods are least set or not. -<link linkend="module.io.adapter"> -IO::Adapter -</link> -is enough minimum ? -</para> - -</sect1> - - </chapter> diff --git a/fml/doc/en/tutorial/internals/directory.sgml b/fml/doc/en/tutorial/internals/directory.sgml new file mode 100644 index 00000000..bee4dfd7 --- /dev/null +++ b/fml/doc/en/tutorial/internals/directory.sgml @@ -0,0 +1,49 @@ +<!-- + $FML: directory.sgml,v 1.6 2005/06/25 15:11:34 fukachan Exp $ +--> + + +<chapter id="directory"> + <title> + Directory + </title> + + +<sect1 id="directory.subdir.hier.level"> + <title> + Q: how recursively sub directory can be created ? + </title> + +<para> +The structore holding the html-ized article is as follows: +<screen> +200201/msg\d+.html +</screen> +</para> + +<para> +one sub-directory by default. +</para> + +<para> +Consider directory listing. +"ls" returns 1000 files soon, but 10000 files a little slowly. +</para> + +<para> +To accelerate listing, we should use sub-directory structure. +For example, each sub-directory holds 1000 files. +HTML 化されたファイルをおくサブディレクトリを 1000 ごとに用意すると、 +The structure such as "spool/sub/file" holds 10^6 ( million ) files +and +listing of it is fast. +</para> + +<para> +It must be enough to assume that 1 million articles for one ML. +</para> + +</sect1> + + +</chapter> diff --git a/fml/doc/en/tutorial/internals/language.sgml b/fml/doc/en/tutorial/internals/language.sgml new file mode 100644 index 00000000..dc4aa124 --- /dev/null +++ b/fml/doc/en/tutorial/internals/language.sgml @@ -0,0 +1,224 @@ +<!-- + $FML: language.sgml,v 1.3 2004/10/06 09:07:39 fukachan Exp $ +--> + + +<chapter id="language.preference"> + <title> + Language preference in processing + </title> + + +<sect1 id="language.preference.overview"> + <title> + Problems of language preference + </title> + +<para> +The simplest model is that we suppose we should return the japanese +message when the ML is configures as for Japanese. +This model needs the language of a ML is fixed. +This ML always returns the error message in Japanese. +</para> + +<para> +However, it is not proper to ignore Accept-Language: header field +since some Japanese people cannot read Japanese on the screen. +There may be invalid Accept-Language: field. +There are several problems. +</para> + +<para> +For example, if "Accept-Language: ja" is given, we can recognize the +language is "ja". However, how about the case Japanese send a mail +with the body content "help" (English) ? In that case we cannot +determine we should return the reply in us-ascii or iso-2022-jp. +For example, how about the following example ? +<screen> +Example: + +From: rudo@example.co.jp +Subject: help +mime-version: 1.0 +content-type: text/plain; charset=us-ascii + +help +</screen> +</para> + +<para> +We should return the English reply message based on charset +information since this message contains English only, so charset is +us-ascii. But this case we should return Japanese message since the +sender is a Japanese. So we should return the help message in both +English and Japanese if the ML is configures as Japanese +preferrable. If English is preferrable, the reply is English only. +</para> + +<para> +If Accept-Lanaguage: is specified, we prefer it. Even if the ML is +English preferrable (config: language_preference_order = en) and the +message with "Accept-Lanaguage: ja" is given, the ML returns the +Japanese help message. +&fml8; behaves like it. +</para> + +</sect1> + + +<sect1 id="language.preference.ml.ja"> + <title> + Japanese preferred ML + </title> + +<para> +language_preference_order variable controls the behaviour. +By default, an ML for Japanese is configures as +<screen> +language_preference_order = ja en +</screen> +&fml8; uses this hint. +</para> + + +<sect2> + <title> + Accept-Language: ja, en + </title> + +<para> +&fml8; returns the message only in Japanese. +</para> + +</sect2> + + +<sect2> + <title> + Accept-Language: en + </title> + +<para> +&fml8; returns the message only in English. +</para> + +</sect2> + + +<sect2> + <title> + no Accept-Language:, Content-Type: charset=iso-2022-jp + </title> + +<para> +&fml8; returns the message only in Japanese. +</para> + +</sect2> + + +<sect2> + <title> + no Accept-Language:, Content-Type: charset=us-ascii + </title> + +<para> +We cannot determine the language. +We should return the message in both English and Japanese. +</para> + +</sect2> + + +<sect2> + <title> + no Accept-Language:, no Content-Type: + </title> + +<para> +We cannot determine the language. +We should return the message in both English and Japanese. +</para> + +</sect2> + +</sect1> + + +<sect1 id="language.preference.ml.en"> + <title> + English preferred ML + </title> + +<para> +By default, a ML for English people is configured as +<screen> +language_preference_order = en +</screen> +&fml8; uses this hints. +</para> + + +<sect2> + <title> + Accept-Language: ja, en + </title> + +<para> +&fml8; returns the message only in Japanese. +</para> + +</sect2> + + +<sect2> + <title> + Accept-Language: en + </title> + +<para> +&fml8; returns the message only in English. +</para> + +</sect2> + + +<sect2> + <title> + no Accept-Language:, Content-Type: charset=iso-2022-jp + </title> + +<para> +&fml8; returns the message only in Japanese. +</para> + +</sect2> + + +<sect2> + <title> + no Accept-Language:, Content-Type: charset=us-ascii + </title> + +<para> +&fml8; returns the message only in English. +</para> + +</sect2> + + +<sect2> + <title> + no Accept-Language:, no Content-Type: + </title> + +<para> +&fml8; returns the message only in English. +</para> + +</sect2> + +</sect1> + + +</chapter> diff --git a/fml/doc/en/tutorial/internals/lock.sgml b/fml/doc/en/tutorial/internals/lock.sgml new file mode 100644 index 00000000..54b05194 --- /dev/null +++ b/fml/doc/en/tutorial/internals/lock.sgml @@ -0,0 +1,83 @@ +<!-- + $FML: lock.sgml,v 1.5 2005/06/25 15:11:34 fukachan Exp $ +--> + + +<chapter id="lock"> + <title> + Lock + </title> + +<para> +Synchronization among processes uses lock. +&fml8; provides flock(2) or lockf(2) based lock mechanism. +</para> + + +<sect1 id="lock.overview"> + <title> + Overview: lock + </title> + +<para> +After 2003/03, &fml8; provides more granular not giant lock. +</para> + +<para> +Each resource defines each lock channel name. +</para> + +<para> +For example, +Mail::Delivery related class accesses the member list. +It needs several locks. +</para> + +<para> +Mail::Delivery::SMTP needs lock of member list. +FML::Send and FML::Process::Delivery locks member list access +in callling Mail::Delivery::SMTP. +</para> + +<para> +Instead +Mail::Delivery::Queue just sees the mail queue. +The function can access the queue concurrently, also. +So this module does not need lock. +</para> + +<para> +Generally speaking, modules using maps require lock. +For example, +FML/Command/UserControl.pm and +FML/Command/Auth.pm +needs write lock, but +FML/Credential.pm +needs only read lock. +</para> + +<para> +It is useful if &fml8; provides reader writer lock. But it is not implemented. +Currently we attension we use short critical region. +</para> + +</sect1> + + +<sect1 id="lock.todo"> + <title> + TODO + </title> + +<para> +mutex lock in calling *_maps. +</para> + +<para> +READER WRITER LOCK in calling IO::Adapter. +</para> + +</sect1> + + +</chapter> diff --git a/fml/doc/en/tutorial/internals/main.cf.sgml b/fml/doc/en/tutorial/internals/main.cf.sgml new file mode 100644 index 00000000..43eaf7ef --- /dev/null +++ b/fml/doc/en/tutorial/internals/main.cf.sgml @@ -0,0 +1,119 @@ +<!-- + $FML: main.cf.sgml,v 1.10 2004/10/06 09:07:39 fukachan Exp $ +--> + + +<sect2 id="main.cf"> + <title> + Example: /usr/local/etc/fml/main.cf + </title> + +<para> +/usr/local/etc/fml/main.cf is not specific. +This is meta file to define fundamental variables +e.g. fml version, directory path et.al. +&fml8; loader reads them. +</para> + +<para> +The format of main.cf is same as other .cf files: +<footnote> +<para> +file extension corresponds to the format. +</para> +</footnote> +<screen> +variable = value +</screen> +style. + +<screen> +# +# $FML: main.cf.sgml,v 1.10 2004/10/06 09:07:39 fukachan Exp $ +# + +# fml version +# This is important +# Example: fml 8.0 +# fml-current YYYYMMDD +# fml-devel YYYYMMDD +fml_version = current-20020701 + +fml_owner = fml + +fml_group = fml + + +### +### DIRECTORIES +### + +# Example: /usr/local +prefix = /usr/local +exec_prefix = ${prefix} + +# $config_dir holds the global main configuration and +# several version-dependent default configurations +# Example: /usr/local/etc/fml +config_dir = /usr/local/etc/fml + +# Example: /usr/local/etc/fml/defaults/$fml_version +default_config_dir = $config_dir/defaults/$fml_version + +# defined for convenience, for example, we need this variable +# at include, include-ctl, which needs expansion of ../libexec/fml/fml.pl +# Example: /usr/local/libexec/fml +executable_prefix = ${exec_prefix}/libexec/fml + +# Example: /usr/local/libexec/fml/$fml_version +libexec_dir = ${exec_prefix}/libexec/fml/$fml_version + +# Example: /usr/local/lib/fml/$fml_version +lib_dir = ${exec_prefix}/lib/fml/$fml_version + +# Example: /usr/local/share/fml/$fml_version +share_dir = ${prefix}/share/fml/$fml_version + +# site local library location +# which is prepared but not used by fml itself +local_lib_dir = ${exec_prefix}/lib/fml/site_local + + +# ml's home directories +# $ml_home_dir (e.g. /var/spool/ml/elena ) is taken from loader's @ARGV. +# This is compatible with fml 4.0. +# Example: /var/spool/ml +default_ml_home_prefix = /var/spool/ml + + + +### +### CONFIGURATION FILES AND DEFAULT PARAMETERS +### + + +# default domain +default_domain = fml.org + + +# version dependent default_config.cf location +# whic holds +# Example: /usr/local/etc/fml/defaults/8.0/default_config.cf +default_config_cf = $default_config_dir/default_config.cf + + +# domain specific configurations +# Example: /usr/local/etc/fml/domains/fml.org/default_config.cf +domain_default_config = $config_dir/domains/$default_domain/config.cf + + +# virtual format: domain directory +# for example, +# fml.org /var/spool/ml/fml.org +# nuinui.net /var/spool/ml/nuinui.net +virtual_maps = $config_dir/virtual + +</screen> +</para> + +</sect2> diff --git a/fml/doc/en/tutorial/internals/merge.sgml b/fml/doc/en/tutorial/internals/merge.sgml new file mode 100644 index 00000000..100172f5 --- /dev/null +++ b/fml/doc/en/tutorial/internals/merge.sgml @@ -0,0 +1,122 @@ +<!-- + $FML: merge.sgml,v 1.3 2005/06/25 15:11:34 fukachan Exp $ +--> + + +<chapter id="merge.internal.to.fml8"> + <title> + Convert another ML system to &fml8; + </title> + + +<sect1 id="merge.internal.fml4to8"> + <title> + Implementation: &fml4; to &fml8; + </title> + +<sect2> + <title> + Case 1: /var/spool/ml/elena/ from &fml4; to &fml8; + </title> + +<para> +This conversion does the following steps in fact. +</para> + +<para> +1) install &fml8; firstly. In this case, add +/var/spool/ml/etc/mail/aliases into $alias_maps of postfix main.cf. +/var/spool/ml/etc/mail/aliases may be empty. +</para> + +<para> +2) run "makefml --force newml elena" to create several files &fml8; +needs. +</para> + +<para> +3) convert address lists in /var/spool/ml/elena to &fml8; style. +</para> + +<para> +3-1) +IO::Adapter ignores a line beginning with '^#' as a comment. +We should handle carefully it since +"actives" file contains ^# lines as "off" address. +</para> + +<para> +3-2) +s=skip (off) options is ignored. +It handles as "on". +</para> + +<para> +3-3) +m=... (digest) options is ignored. + +Also, "# address" is "off" in the case of &fml4; but ignored in the +case of &fml8;. We should warn it ? +</para> + +<para> +4) remove the corresponding entry of alias file +(/var/spool/ml/etc/fml/aliases) of &fml4; and rebuild .db. +</para> + +</sect2> + + +<sect2> + <title> + Case 2: convert the whole /var/spool/ml/ from &fml4; to &fml8; + </title> + +<para> +Apply case 1 for all ML's. +</para> + +<para> +If we can stop all ML's, it is easy to remove +/var/spool/ml/etc/fml/aliases of &fml4; firstly and apply case 1 steps. +stop MTA in migration. +</para> + +</sect2> + + +<sect2> + <title> + Discussion: use half and half of &fml4; and &fml8; softwares. + </title> + +<para> +(X-Sequence: fml-devel 389) +</para> + +<para> +How in half and half case. +</para> + +<para> +For example, site_init.ph or config.ph of &fml4; follows +<screen> +[fml4] + +push(@ACTIVE_LIST,"$DIR/recipients") if( -f "$DIR/recipients" ) ; +</screen> +instead in the case of &fml8; +site_default_config.cf or config.cf follows: +<screen> +[fml8] + +html_archive_dir = $ml_home_dir/htdocs +</screen> +</para> + +</sect2> + +</sect1> + + +</chapter> diff --git a/fml/doc/en/tutorial/internals/restriction.sgml b/fml/doc/en/tutorial/internals/restriction.sgml new file mode 100644 index 00000000..60731434 --- /dev/null +++ b/fml/doc/en/tutorial/internals/restriction.sgml @@ -0,0 +1,202 @@ +<!-- + $FML: restriction.sgml,v 1.9 2005/06/25 15:11:35 fukachan Exp $ +--> + + +<chapter id="restriction"> + <title> + Restrict input data + </title> + +<para> +&fml8; checks the input by regular expression FML::Restriction class +provides. +</para> + + +<sect1 id="restriction.overview"> + <title> + Overview: checks of input data + </title> + +<sect2> + <title> + Restriction for article posting + </title> + +<para> +Restrictions for article are ambiguous or too restrictive. In fact +FML::Restriction class does not provide restriction rules for article +posting. +</para> + +<para> +Instead FML::Filter filter system checks each line of content. +</para> + +</sect2> + + +<sect2> + <title> + Restrictions for command mail + </title> + +<para> +FML::Process::Command class parses each line of the command mail and +checks the input by regular expressions FML::Restriction::Command +provides. If the check is passed, &fml8; calls +FML::Command::{User,Admin}::COMMAND at the next step. +</para> + +</sect2> + + +<sect2> + <title> + CGI + </title> + +<para> +CGI programs can receive the input from HTTP via only safe_param_XXX() +method. +</para> + +<para> +It is expected that +safe_param_*() +and +try_cgi_*() +returns the safe value. +</para> + +<para> +These safe_param_XXX() functions checks the input by regular +expressions FML::Restriction::CGI provides (FML::Restriction::CGI +inherits FML::Restriction::Base). +</para> + +</sect2> + + +<sect2> + <title> + makefml / fml + </title> + +<para> +CUI runs on the shell. +It means he/she who runs CUI has priviledge to log in the mailing list +server. +So it does not check the input. +</para> + +<para> +Each module checks the input independetly in that case +though no checks by FML::Restriction at the entrance. +For example, "adduser" module checks whether the input address +is valid or not even in the case of CUI. +These restrictions are dependent command specific modules. +</para> + +</sect2> + +</sect1> + + +<sect1 id="restriction.class"> + <title> + FML::Restriction class + </title> + +<para> +ACLs for the input data and commands are found at FML::Restriction +class. +</para> + +<para> +For example, CGI modules use FML::Restriction::CGI class to check +if the input data matches the proper regular expression. +</para> + +<para> +Though FML::Restriction inherits FML::Restriction::Base class, +fundamentally each module should use FML::Restriction as object +composition. For example, use in the following way: +<screen> +use FML::Restriction::CGI; +$safe = new FML::Restriction::CGI; +my $allowed_regexp = $safe->param_regexp(); + +if ($value =~ /^$allowed_regexp{$key}$) { ... ok, do something ... ;} +</screen> +</para> + +</sect1> + + +<sect1 id="restrictioncgi.input.data"> + <title> + How CGI restricts the input + </title> + +<para> +CGI checks the input data by using FML::Restriction::CGI class. +</para> + +<para> +The input should be restricted by FML::Restriction class. +We should not use param() method provided by perl's CGI class. +Instead use safe_param_xxx() method always to get value. +</para> + +<para> +The following use may be allowed +<screen> +for my $dirty_buf (param()) { + ... check ... +} +</screen> +but we should not use raw param() call. +<screen> +param($dirtty_buf) +</screen> +Instead, use safe_param_key(). +<screen> +for my $key (param()) { + ... check ... + + if (key eq $key) { + value = safe_param_key() + } +} +</screen> +</para> + +</sect1> + + +<sect1> + <title> + Discussion: FML::Restriction is too restrictive ? + </title> + +<para> +FML::Restriction class allows a subset of RFC defined expression. +</para> + +<para> +RRC definition is too large. +It is too difficult to implement it ;-) +We restrict the expression a little. +</para> + +<para> +FML::Restriction::Command may be more granular but more granular +version is not implemented. +</para> + +</sect1> + + +</chapter> diff --git a/fml/doc/en/tutorial/internals/struct.sgml b/fml/doc/en/tutorial/internals/struct.sgml index ab4e7002..2d42b866 100644 --- a/fml/doc/en/tutorial/internals/struct.sgml +++ b/fml/doc/en/tutorial/internals/struct.sgml @@ -1,5 +1,5 @@ <!-- - $FML: struct.sgml,v 1.1 2003/07/28 10:41:30 fukachan Exp $ + $FML: struct.sgml,v 1.2 2003/08/03 05:28:49 fukachan Exp $ $jaFML: struct.sgml,v 1.2 2003/04/15 14:51:41 fukachan Exp $ --> @@ -9,7 +9,32 @@ </title> -&struct.curproc; +<sect1 id="structure.curproc"> + <title> + curproc object + </title> + +<para> +Example of FML::Process::Distribute object. +</para> + + &struct.curproc; + +</sect1> + + +<sect1 id="structure.pcb"> + <title> + PCB category list + </title> + +<para> +PCB category list, which contains module and function relation. +</para> + +&list.pcb; + +</sect1> </appendix> diff --git a/fml/doc/en/tutorial/internals/userctl.sgml b/fml/doc/en/tutorial/internals/userctl.sgml new file mode 100644 index 00000000..29bb95d5 --- /dev/null +++ b/fml/doc/en/tutorial/internals/userctl.sgml @@ -0,0 +1,57 @@ +<!-- + $FML: userctl.sgml,v 1.3 2004/10/06 09:07:40 fukachan Exp $ +--> + + +<chapter id="userctl"> + <title> + subscribe / unsubscribe + </title> + + +<sect1 id="userctl.deladd"> + <title> + which map subscribe/unsubscribe is operated to ? + </title> + +<para> +Subscribe/unsubscribe is operated to $primary_*map. +</para> + +<para> +For example, +subscription of remote administrators is operated into +both $primary_admin_member_map and $primary_admin_recipient_map. +unsubscription of remote administrators is operated into +both $primary_admin_member_map and $primary_admin_recipient_map. +</para> + +<para> +Why use primary_*_map ? +If we use admin_member_maps and admin_recipient_maps, it causes a problem. +</para> + +<para> +Subscription should be operated into one map. So we should operate it +into primary_*_map. +</para> + +<para> +Unsubscription must be same since xxx_maps is composed of different +privileged maps. +</para> + +<para> +For example, $member_maps is as follows. +It contais a list of member and a list of remote administrators. +<screen> +member_maps = $primary_member_map + $admin_member_maps +</screen> +So unsubscription operated for $member_maps may cause +unsubscription of remote administrators. It is wrong logic. +</para> + +</sect1> + +</chapter> |
