[PREVIOUS CHAPTER] [NEXT CHAPTER]

6 Fml Processes

    It is useful to customize FML if you know the fundamentals of ML
    servers. In this chapter we describe fml internals.

    6.1	Functions as  ML Server

    	mail comes via SMTP.
    		|
    	MTA e.g. sendmail receives it.
    	Here after we suppose MTA is sendmail.
    		|
    	sendmail scans /etc/aliases and runs programs after setuid().
    	sendmail runs and injects an in coming mail into the program.
    		|
    	sendmail -> fml.pl
    	Fml.pl reads and evaluates config.ph and runs.
    	It analyses the header,
    	authenticate the sender is a member or not.
    	Fml distributes a ML article by passing it to MTA.
    		|
    	MTA delivers a passed mail to ML members.

    It is enough to use "sed" for a filter and "sendmail" for delivery.
    If you expect a mailing list driver works for logging, spooling and a
    lot of commands to retrieve articles and so on, you need more
    elaborate programs. Fml provides a lot of functions described below.

    Fml provides, delivery, functions for a lot of commands, digest
    delivery and so on. fml.pl is a delivery program and also provides
    command functions.  Digest delivery (matome okuri) is another process.
    You must set up that cron executes msend.pl (digest delivery system)
    periodically.

    6.2	How "sendmail -> fml.pl" works

    How sendmail passes an in-coming mail to fml.pl? Here it is. Consider
    Elena Mailing list as one example below.

    Firstly sendmail scans /etc/aliases to find

    	Elena: :include:/usr/local/list/Elena
    	owner-Elena:fukachan

    For Elena ML, sendmail executes the content of /usr/local/list/Elena.
    The content of /usr/local/list/Elena is

    	"|/usr/local/fml/fml.pl /var/spool/ml/elena"

    This implies that sendmail passes mail to fml.pl via PIPE (pipe(2)).
    fml.pl receives mail via STDIN. fml.pl works with this input.

    fml.pl recognizes the first argument /var/spool/ml/elena as HOME
    directory of Elena ML. fml.pl reads /var/spool/ml/elena/config.ph and
    sets up Elena ML configurations.

    If you use command line options for fml.pl, please use like this.

    	"|/usr/local/fml/fml.pl /var/spool/ml/elena --ctladdr "

    Arbitrary order is available. fml.pl regards the first argument of
    directory as ML's HOME (e.g. location of config.ph).

    6.3	Order to search library files

    Consider elena ML again. fml.pl is kicked off like

    	/usr/local/fml/fml.pl /var/spool/ml/elena

    fml.pl extracts the directory path (/usr/local/fml) of fml.pl absolute
    path. It searches OS for executable and libraries in the following
    order

    	1   /var/spool/ml/elena
    	2   /usr/local/fml

    If the following arguments are given,

       "|/usr/local/fml/fml.pl /var/spool/ml/elena /usr/lib/uja /lib/aja"

    fml.pl searches OS for executable and libraries like this:

    	1   /var/spool/ml/elena
    	2   /var/spool/ml/etc/fml/
    	3   /usr/local/fml
    	4   /usr/lib/uja
    	5   /lib/uja

    6.4	Priority of configuration file search

    The evaluation order of configuration files is like this.
    "1" is most directive.

    	1 command line options (e.g. fml.pl --ctladdr)
    	2 sitedef.ph
    	3 config.ph
    	3 site_init.ph
    	5 fml defaults

    sitedef.ph and site_init.ph may be useful to be used as a common
    configuration file over mailing lists e.g. to set up command search
    path ,tar, gzip, ...

    fml (after 2.2.1) searchs sitedef.ph and site_init.ph in the following
    order:

    				Example
    	-----------------------------------------------
    	$DIR			/var/spool/ml/elena/
    	$ML_DIR/etc/fml/	/var/spool/ml/etc/fml/
    	$EXEC_DIR		/usr/local/fml/
    	perl standard path	@INC

    It shoule exist in common directory.

    	$ML_DIR/etc/fml/	/var/spool/ml/etc/fml/
    	$EXEC_DIR		/usr/local/fml/

    So it will be either of them. To avoid recnstructuing under
    /usr/local/fml in version up, the first location in fml 2.2.1 search
    path is $ML_DIR/etc/fml/.

    6.5	fml.pl process (first stage)

    fml.pl scans the input mail and splits up it and save them in

    	Header	$Envelope{'Header'}
    	Body	$Envelope{'Body'}

    In default fml.pl is not compatible with hml 1.6 (which is a mailing
    list server may be used only in Japanese). The following descriptions
    are of no means.

    If the mode is compatible with hml 1.6, fml.pl checks the body.  Even
    though fml.pl is not in the compatible mode, the check routine works
    but the result is not used.

    * checks the first $GUIDE_CHECK_LIMIT lines to find $GUIDE_KEYWORD.
      If found, FML sends back guide and do nothing except it.

    * fml.pl scans the first $COMMAND_CHECK_LIMIT to change the mode from
    distribution to command mode. The trap keyword is
    	^#(\s*\w+\s|^\#\s*\w+)
    	^#$CHADDR_KEYWORD

    In default

    	$GUIDE_KEYWORD  = "guide";
    	$CHADDR_KEYWORD = "chaddr|change-address|change";

    6.6	fml process (second stage)

    After parsing, fml.pl sets up %Envelope, locks into critical region.
    Under locked state, fml.pl main part works.

    6.7	fml process, lock and signal handling

    fml.pl uses flock(2) and alarm(3). It is standard technique on
    UNIX. On Micro$oft Windows NT4 with activestate perl, flock(2) works
    but alarm(3) does not work. We emulate it by Win32::Process. Under our
    NT4 alarm emulation, timeout equals to "end of process".

    sub Flock {

        &SetEvent($TimeOut{'flock'} || 3600, 'TimeOut') if $HAS_ALARM;
    	...

        # signal handling
        $SIG{'ALRM'} = 'TimeOut';
        $SIG{'INT'}  = $SIG{'QUIT'} = 'SignalLog';

    Flock timeout is defined by $TimeOut{'flock'}, default is 3600 seconds.

    When timeout occurs, fml.pl notifies it to the maintainer, logs it and
    exits.

    When flock(2) is not used, fml.pl uses link(2) based lock
    algorithm. If timeout, fml.pl notifies it and exits. Please see
    liblock.pl for more details.

    6.8	Event Scheduler

    fml.pl uses flock(2) and alarm(3). It is standard technique on
    UNIX. Software trap by alarm(3) maintains event scheduling inside FML.
    On Micro$oft Windows NT4 with activestate perl, flock(2) works but
    alarm(3) does not work. We emulate it by Win32::Process. The emulation
    is incomplete for the restriction of ntperl. We only enforce fml.pl
    exits if timeout.

    6.9	Another locking algorithm

    fml.pl provides two lock algorithms, flock(2) and link(2) based lock
    algorithm. In default fml.pl uses flock(2). flock(2) is used if

    	$USE_FLOCK    = 1; (default 1)

    link(2) based lock is used if

    	$USE_FLOCK    = 0;

    link(2) style lock is based on whether link(2) works or not.
    The lock file is

    	$LOCK_FILE

    The default lock file is $DIR/var/run/lockfile.v7

    	"$FP_VARRUN_DIR/lockfile.v7"

    This lock algorithm is not fault tolerant e.g. in sudden death of OS
    since the lock file is not removed. After the reboot, maintainer
    should remove left lock files.  Just after reboot, remove all files
    $FP_VARRUN_DIR/lockfile*. From this view, I recommends you that
    you should use the lock mechanism OS provides.

    	"$FP_VARRUN_DIR/lockfile.v7"

    Also in link(2) style, timeout is defined by $MAX_TIMEOUT. The mail is
    saved in var/log. fml.pl notifies it to the maintainer.

    FYI: flock(2)

    	$LOCK_SH                       = 1;
    	$LOCK_EX                       = 2;
    	$LOCK_NB                       = 4;
    	$LOCK_UN                       = 8;

         #include <sys/file.h>
         #define   LOCK_SH   1    /* shared lock */
         #define   LOCK_EX   2    /* exclusive lock */
         #define   LOCK_NB   4    /* don't block when locking */
         #define   LOCK_UN   8    /* unlock */

         int
         flock(int fd, int operation)

    See e.g. A. S. Tannenbaum, "Modern Operating Systems" for exclusive locks.

[PREVIOUS CHAPTER] [NEXT CHAPTER]