/*

    MM_TrackManager


    version 1.4


    Đ 1996 by Sebastian Bleikamp.
    All rights reserved.


--------\
History: ----------------------------------------------------------------
--------/

since ???:

    - send_msg works.
    - send_rrr works.


since 0.1:

    - crossnet works.
    - killempty works.
    - unknown domain works.


since 0.2:

    - changed whole configuration part again.
    - bad mails wonīt be deleted now, they will be moved to an
      badarea and marked as sent.
    - improved msg send function.
    - bounce works !
    - remap works !



since 0.3:

    - changed the main routine:
      The message base will be scanned two times now.
      This makes it a bit slower, but the new messages will be remapped, too.
    - Check_Address_Pattern() replaced by Check_Pattern(). Improves
      address checking.
    - implemented language patterns for different languages ...
    - improved crossnet: Msg. will only be sent if file is present.
    - improved send_msg: If no file is given, the original msg. text will
      be used as message body.


since 0.4:

    - the replace patterns work now.
    - extra fields added to make replace patterns work with REMAP.


since 0.5:

    - the config will now be read and compiled from the configfile.
      (I want more SPEED !!!)


since 1.0:

    - added a copy/forward function.
    - added email addresses for language checking.
    - several bugs fixed.
    - added TMīs own log for more information ... MMīs log became too large.


since 1.1:

    - fixed several smaller bugs.
    - added ToDo_Each function.
    - added ToDo_Once function.


since 1.2:

    - added NodeList check for receiver & sender.


since 1.4:

    - added Move function.

-----------------------------------------------------------------------------
*/

options cache
options failat 20

parse arg sysarguments


address 'MAILMANAGER'


call Check_Args()
call Init()
call Do_It()
call ByeBye('0,;')



exit 0





/*---------------------------------------------------------------------------*\
|*  Standart Functions:                                                      *|
\*---------------------------------------------------------------------------*/


Init:
    system.     = 0
    call MMLogInit()
    call MMLogHeader()
    call Config()
    call TMLogInit()

    MM_CRCFile system.cfg.cfgfile 'confcrc'
    if (confcrc~=system.cfg.cfgcrc) then do
        say
        say "***Warning: Configfile has changed !!!"
        say
        call TMLog('Warning: Configfile has been changed !,;1,;!')
    end

return


ByeBye: procedure expose system.
    parse arg ecode ',;' estring
    if estring~='' then do
        say estring
        call TMLog(estring',;0,;!')
        call MMLog(estring',;2')
    end
    call TMLogQuit()
    call MMLogFooter()
    call MMLogQuit()
    exit ecode
return


/* MMLog-Funktions: ---------------------------------------------------------*/

MMLogInit:
        system.prg.name         = 'MM_TrackManager'
        system.prg.ver          = '1.4'
        system.prg.id           = system.prg.name 'v'system.prg.ver
        system.prg.stdlev       = 3
        system.mm.logpre        = getclip('MM_LogPre')
        system.prg.logpre       = system.mm.logpre'|'
        call                    setclip('MM_LogPre', system.prg.logpre)
return

MMLogQuit:
        arg rc
        call setclip('MM_LogPre', system.mm.logpre)
        MM_CloseLog
exit rc

MMLogHeader: PROCEDURE Expose system.
        call MMLog(',;2,;/')
        call MMLog('***' system.prg.id 'started ***,;2,;+')
return

MMLogFooter: procedure Expose system.
        call MMLog(',;2,;|')
        call MMLog('***' system.prg.id 'ended ***,;2,;+')
        call MMLog(',;2,;\')
return

MMLog: procedure Expose system.
        parse arg text ',;' level ',;' pre
        tmp         = word('PRG MM', (pre~='')+1)
        text        = system.tmp.logpre || pre' 'text
        if level='' then level=system.prg.stdlev
        MM_WriteLog 'text' level
return


/* TM Log-Funktions: ---------------------------------------------------------*/

TMLogInit: procedure expose system.
    system.log.count=0
    call TMLog('*** '||system.prg.id||' opened. ***,;1,;/')
return

TMLogQuit: procedure expose system.
    call TMLog('*** '||system.prg.id||' closed. ***,;1,;\')
    MM_WriteStem system.log.logfile 'system.log' 'APPEND'
return

TMLog: procedure expose system.
    parse arg text ',;' level ',;' pre
    ltxt = date()||'  '||time()||'   '||pre||' '||text
    if (level='') then level=0
    if (level<=system.log.logclevel) then say ltxt
    if (level<=system.log.logflevel) then MM_AddToStem 'system.log' 'ltxt'
return


/*---------------------------------------------------------------------------*\
|*  Program Functions:                                                       *|
\*---------------------------------------------------------------------------*/


Check_Args: procedure expose system. sysarguments
    if (upper(word(sysarguments,1))='HELP') then do
        say
        say 'Usage:'
        say
        say 'rx MM_TrackManager.rexx'
        say ' - do your work, program !'
        say
        say 'rx MM_TrackManager.rexx CPLCFG <Configfile> <Programfile>'
        say ' - compile config from file <configfile> and write it to'
        say '   <programfile>.'
        say
        exit 0
    end
    else if (upper(word(sysarguments,1))='CPLCFG') then do
        system.cfg.cfgfile = word(sysarguments,2)
        system.cfg.prgfile = word(sysarguments,3)
        call Compile_Cfg()
        exit 0
    end
return



Do_It: procedure expose system.
    MM_GetAreas 'AreaList' 'MAIL'


/* Pass 1: Check. */

    do listarea = 0 to AreaList.count-1
        MM_SearchMsgs AreaList.listarea 'MsgList' '#?' '#?' '#?' '!SENT'
        do listmsg=0 to MsgList.count-1
            call Read_Msg_Info(AreaList.listarea||',;'||MsgList.listmsg)
            call TMLog('['||system.info.area||'/'||system.info.number||'] Msg. Info: '||system.info.fromwho||' -> '||system.info.towho||',;5,;|>')
            call Check_Domains()
            dom = system.info.fromdomain
            domb = system.info.todomain

            if ((system.info.ok=1)&(system.copy.count>0))                           then call Check_Copy()
            if ((system.info.ok=1)&(system.bounce.count>0))                         then call Check_Bounce()
            if ((system.info.ok=1)&(find(system.domain.dom.check,'KILLEMPTY')~=0))  then call Check_KillEmpty()
            if ((system.info.ok=1)&(find(system.domain.dom.check,'CROSSNET')~=0))   then call Check_Crossnet()
            if ((system.info.ok=1)&(find(system.domain.domb.check,'CHECKNLR')~=0))  then call Check_NL_Receiver()
            if ((system.info.ok=1)&(find(system.domain.dom.check,'CHECKNLS')~=0))   then call Check_NL_Sender()
            if ((system.info.ok=1)&(find(system.domain.dom.check,'RRR')~=0))        then call Check_RRR()
            if ((system.info.ok=1)&(system.todoe.count>0))                          then call Check_ToDo_Each()
            if ((system.info.ok=1)&(system.todoo.count>0))                          then call Check_ToDo_Once()

            if ((system.info.ok=1)&(system.move.count>0))                           then call Check_Move()

            if (system.info.ok=1) then call TMLog('['||system.info.area||'/'||system.info.number||'] Mail okay.,;5,;|')
            else call TMLog('['||system.info.area||'/'||system.info.number||'] Mail stopped.,;5,;|<')
        end
    end


/* Do ToDoOnce commands: */

call Do_ToDo_Once()

/* Pass 2: Remap. */
    
    if (system.remap.count>0) then do
        do listarea = 0 to AreaList.count-1
            MM_SearchMsgs AreaList.listarea 'MsgList' '#?' '#?' '#?' '!SENT'
            do listmsg=0 to MsgList.count-1
                call Read_Msg_Info(AreaList.listarea||',;'||MsgList.listmsg)
                call TMLog('['||system.info.area||'/'||system.info.number||'] Msg. Info: '||system.info.fromwho||' -> '||system.info.towho||',;5,;|')
                call Check_Remap()
            end
        end
    end
return


/*---------------------------------------------------------------------------*\
|*  Other Support Functions:                                                 *|
\*---------------------------------------------------------------------------*/

Read_Msg_Info: procedure expose system.
    parse arg system.info.area ',;' system.info.number
        MM_ReadMsg system.info.area system.info.number 'system.info.msg'
        if (rc~=0) then call ByeBye('100,;***Error: Unable to read message '||system.info.number||' in area "'||system.info.area||'" !')
        system.info.fromemail = ''
        do kludge=0 to system.info.msg.head.count-1
            if (pos('REPLYADDR',upper(word(system.info.msg.head.kludge,1)))~=0) then do
                parse var system.info.msg.head.kludge . ' ' system.info.fromemail
            end
        end
        system.info.toemail = ''
        do line=0 to system.info.msg.text.count-1
            if (word(upper(system.info.msg.text.line),1)='TO:') then do
                parse var system.info.msg.text.line . ' ' system.info.toemail
            end
        end
        if (system.info.fromemail~='') then system.info.fromwho=system.info.fromemail||' ('||system.info.msg.from||')'
        else system.info.fromwho=system.info.msg.from||' ('||system.info.msg.fromaddr||')'
        if (system.info.toemail~='') then system.info.towho=system.info.toemail||' ('||system.info.msg.to||')'
        else system.info.towho=system.info.msg.to||' ('||system.info.msg.toaddr||')'
        MM_GetNearestAddr system.info.msg.toaddr 'system.info.thissys'
        system.info.ok = 1
        call Get_Domains()
        call Get_Languages()
return


Do_BadMail: procedure expose system.
    call MMLog('['||system.info.area||'/'||system.info.number||'] Mail moved to badarea.')
    call TMLog('['||system.info.area||'/'||system.info.number||'] Mail stopped and moved to badarea.,;2,;|')
    newflags = 'SENT'
    MM_EditMsgFlags system.info.area system.info.number 'newflags'
    if (rc~=0) then ByeBye('100,;***Error: Unable to edit message ! ('||system.info.area||', '||system.info.number||')')
    MM_MoveMsg system.info.area system.info.number system.cfg.badarea
    if (rc~=0) then ByeBye('100,;***Error: Unable to move message ! ('||system.info.area||', '||system.info.number||' -> '||system.cfg.badarea||')')
    system.info.ok=0
return


Get_Domains: procedure expose system.
    i=0
    do while( (Check_Pattern(system.info.msg.fromaddr||',;'||system.domain.i.pattern)=0) & (i<system.domain.count)  )
        i=i+1
    end
    if (i<system.domain.count) then system.info.fromdomain=i
    else system.info.fromdomain = -1
    i=0
    do while( (Check_Pattern(system.info.msg.toaddr||',;'||system.domain.i.pattern)=0) & (i<system.domain.count)  )
        i=i+1
    end
    if (i<system.domain.count) then system.info.todomain=i
    else system.info.todomain = -1
return

Get_Languages: procedure expose system.
    i=0
    do while( ((Check_Pattern(system.info.msg.fromaddr||',;'||system.langpat.i.pattern)=0) | (Check_Pattern(system.info.fromemail||',;'||system.langpat.i.empattern)=0)) & (i<system.langpat.count)  )
        i=i+1
    end
    if (i<system.langpat.count) then system.info.fromlanguage=system.langpat.i.textset
    else system.info.fromlanguage = 0
    i=0
    do while( ((Check_Pattern(system.info.msg.toaddr||',;'||system.langpat.i.pattern)=0) | (Check_Pattern(system.info.toemail||',;'||system.langpat.i.empattern)=0)) & (i<system.langpat.count)  )
        i=i+1
    end
    if (i<system.langpat.count) then system.info.tolanguage=system.langpat.i.textset
    else system.info.tolanguage = 0
return



/*---------------------------------------------------------------------------*\
|*  Standard Check Functions:                                                *|
\*---------------------------------------------------------------------------*/

Check_Domains: procedure expose system.
    if system.info.fromdomain = '-1' then do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Senderīs domain unknown: "'||system.info.msg.fromaddr||'".,;3,;|')
        call Send_Msg(system.info.msg.to||',;'||system.info.msg.toaddr||',;'||system.info.toemail||',;'||system.info.area||',;'||Get_LanguageText('system.udom.text.from,;'||system.info.tolanguage)||',;'||Get_LanguageText('system.udom.subj.from,;'||system.info.tolanguage))
        call Do_BadMail()
    end
    if system.info.todomain = '-1' then do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Receiverīs domain unknown: "'||system.info.msg.toaddr||'".,;3,;|')
        call Send_Msg(system.info.msg.from||',;'||system.info.msg.fromaddr||',;'||system.info.fromemail||',;'||system.info.area||',;'||Get_LanguageText('system.udom.text.to,;'||system.info.fromlanguage)||',;'||Get_LanguageText('system.udom.subj.to,;'||system.info.fromlanguage))
        call Do_BadMail()
    end
return

Check_Crossnet: procedure expose system.
    if (system.info.fromdomain~=system.info.todomain) then do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Crossnet mail: '||system.info.msg.fromaddr||' -> '||system.info.msg.toaddr||',;3,;|')
        dom=system.info.fromdomain
        if (system.domain.dom.text.CNS.0~='') then call Send_Msg(system.info.msg.from||',;'||system.info.msg.fromaddr||',;'||system.info.fromemail||',;'||system.info.area||',;'||Get_LanguageText('system.domain.'||dom||'.text.CNS,;'||system.info.fromlanguage)||',;'||Get_LanguageText('system.domain.'||dom||'.subj.CNS,;'||system.info.fromlanguage))
        if (system.domain.dom.text.CNR.0~='') then call Send_Msg(system.info.msg.to||',;'||system.info.msg.toaddr||',;'||system.info.toemail||',;'||system.info.area||',;'||Get_LanguageText('system.domain.'||dom||'.text.CNR,;'||system.info.tolanguage)||',;'||Get_LanguageText('system.domain.'||dom||'.subj.CNR,;'system.info.tolanguage))
        call Do_BadMail()
    end
return


Check_RRR: procedure expose system.
    if ( (find(system.info.msg.flags,'RRR')~=0 ) & (find(system.info.msg.flags,'INTR')=0) ) then do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Sending RRR.,;4,;|')
        dom = system.info.fromdomain
        call Send_Msg(system.info.msg.from||',;'||system.info.msg.fromaddr||',;'||system.info.fromemail||',;'||system.info.area||',;'||Get_LanguageText('system.domain.'||dom||'.text.RRR,;'system.info.fromlanguage)||',;'||Get_LanguageText('system.domain.'||dom||'.subj.RRR,;'||system.info.fromlanguage))
    end
return


Check_KillEmpty: procedure expose system.
    check=0
    do i=0 to system.info.msg.text.count-1
        if (system.info.msg.text.i~='') then check=1
    end
    if (check=0) then do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Mail has an empty body.,;4,;|')
        Do_BadMail()
    end
return


Check_Bounce: procedure expose system.
    i=0
    do while((i<system.bounce.count)&(system.info.ok=1))
        check=1
        if (system.bounce.i.from~='#?')                   then check = (check & Check_Pattern(system.info.msg.from||',;'||system.bounce.i.from))
        if ((check=1)&(system.bounce.i.fromaddr~='#?'))   then check = (check & Check_Pattern(system.info.msg.fromaddr||',;'||system.bounce.i.fromaddr))
        if ((check=1)&(system.bounce.i.fromemail~='#?'))  then check = (check & Check_Pattern(system.info.fromemail||',;'||system.bounce.i.fromemail))
        if ((check=1)&(system.bounce.i.to~='#?'))         then check = (check & Check_Pattern(system.info.msg.to||',;'||system.bounce.i.to))
        if ((check=1)&(system.bounce.i.toaddr~='#?'))     then check = (check & Check_Pattern(system.info.msg.toaddr||',;'||system.bounce.i.toaddr))
        if ((check=1)&(system.bounce.i.toemail~='#?'))    then check = (check & Check_Pattern(system.info.toemail||',;'||system.bounce.i.toemail))
        if ((check=1)&(system.bounce.i.subject~='#?'))    then check = (check & Check_Pattern(system.info.msg.subj||',;'||system.bounce.i.subject))
        if ((check=1)&(system.bounce.i.text~='#?'))       then do
            Out.Count=0
            MM_SearchInStem 'system.info.msg.TEXT' 'Out' system.bounce.i.text 'NUM'
            if (out=0) then check=0
        end
        if (check=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Bouncing mail.,;3,;|')
            if (system.bounce.i.inform.text.0~='') then call Send_Msg(system.info.msg.from||',;'||system.info.msg.fromaddr||',;'||system.info.fromemail||',;'||system.info.area||',;'||Get_LanguageText('system.bounce.'||i||'.inform.text,;'||system.info.fromlanguage)||',;'||Get_LanguageText('system.bounce.'||i||'.inform.subj,;'||system.info.fromlanguage))
            call Do_BadMail()
        end
        i=i+1
    end
return


Check_Remap: procedure expose system.
    i=0
    do while(i<system.remap.count)
        check=1

        if            (system.remap.i.in.name~='#?')    then check = (check & Check_Pattern(system.info.msg.to||',;'||system.remap.i.in.name))
        if ((check=1)&(system.remap.i.in.addr~='#?'))   then check = (check & Check_Pattern(system.info.msg.toaddr||',;'||system.remap.i.in.addr))
        if ((check=1)&(system.remap.i.in.email~='#?'))  then check = (check & Check_Pattern(system.info.toemail||',;'||system.remap.i.in.email))

        if (check=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Remapping mail.,;3,;|')
            if (system.remap.i.inf.text.0~='') then call Send_Msg(system.info.msg.from||',;'||system.info.msg.fromaddr||',;'||system.info.fromemail||',;'||system.info.area||',;'||Get_LanguageText('system.remap.'||i||'.inf.text,;'||system.info.fromlanguage)||',;'||Get_LanguageText('system.remap.'||i||'.inf.subj,;'||system.info.fromlanguage))
            else do
                system.info.extra1 = system.info.msg.to
                system.info.extra2 = system.info.msg.toaddr
                system.info.extra3 = system.info.toemail
                system.info.extra4 = system.info.msg.subj
                if (system.remap.i.out.subj~='')  then system.info.msg.subj    = Replace_My_Patterns(Get_LanguageText('system.remap.'||i||'.out.subj,;'||system.info.tolanguage))
                if (system.remap.i.out.name~='')  then system.info.msg.to      = system.remap.i.out.name
                if (system.remap.i.out.addr~='')  then system.info.msg.toaddr  = system.remap.i.out.addr
                if (system.remap.i.out.email~='') then system.info.toemail     = system.remap.i.out.email
                call Edit_Msg(Get_LanguageText('system.remap.'||i||'.out.text,;'||system.info.tolanguage))
            end
        end
        i=i+1
    end
return


Check_Copy: procedure expose system.
    i=0
    do while(i<system.copy.count)
        check=1
        if            (system.copy.i.in.from.name~='#?')    then check = (check & Check_Pattern(system.info.msg.from||',;'||system.copy.i.in.from.name))
        if ((check=1)&(system.copy.i.in.from.addr~='#?'))   then check = (check & Check_Pattern(system.info.msg.fromaddr||',;'||system.copy.i.in.from.addr))
        if ((check=1)&(system.copy.i.in.from.email~='#?'))  then check = (check & Check_Pattern(system.info.fromemail||',;'||system.copy.i.in.from.email))
        if ((check=1)&(system.copy.i.in.to.name~='#?'))     then check = (check & Check_Pattern(system.info.msg.to||',;'||system.copy.i.in.to.name))
        if ((check=1)&(system.copy.i.in.to.addr~='#?'))     then check = (check & Check_Pattern(system.info.msg.toaddr||',;'||system.copy.i.in.to.addr))
        if ((check=1)&(system.copy.i.in.to.email~='#?'))    then check = (check & Check_Pattern(system.info.toemail||',;'||system.copy.i.in.to.email))
        if ((check=1)&(system.copy.i.in.subject~='#?'))     then check = (check & Check_Pattern(system.info.msg.subj||',;'||system.copy.i.in.subject))
        if ((check=1)&(system.copy.i.in.text~='#?'))        then do
            Out.Count=0
            MM_SearchInStem 'system.info.msg.TEXT' 'Out' system.copy.i.in.text 'NUM'
            if (out=0) then check=0
        end
        if (check=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Forwarding mail.,;4,;|')
            system.info.extra1 = system.info.msg.to
            system.info.extra2 = system.info.msg.toaddr
            system.info.extra3 = system.info.toemail
            system.info.extra4 = system.info.msg.subj
            call Send_Msg(system.copy.i.out.name||',;'||system.copy.i.out.addr||',;'||system.copy.i.out.email||',;'||system.info.area||',;'||system.copy.i.out.text||',;'||Replace_My_Patterns(system.copy.i.out.subj))
        end
        i=i+1
    end
return



Check_NL_Receiver: procedure expose system.
    MM_GetNodeListNode Get_Boss(system.info.msg.toaddr) 'nlstem'
    if (rc=4) then do
        dom = system.info.todomain
        call TMLog('['||system.info.area||'/'||system.info.number||'] Receiverīs node/boss "'||Get_Boss(system.info.msg.toaddr)||'" unknown.,;3,;|')
        if (system.domain.dom.text.NLR.0~='')                   then call Send_Msg(system.info.msg.from||',;'||system.info.msg.fromaddr||',;'||system.info.fromemail||',;'||system.info.area||',;'||Get_LanguageText('system.domain.'||dom||'.text.NLR,;'||system.info.fromlanguage)||',;'||Get_LanguageText('system.domain.'||dom||'.subj.NLR,;'||system.info.fromlanguage))
        if (find(upper(system.domain.dom.todo.NLR),'STOP')~=0)  then call Do_BadMail()
    end
    else do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Receiverīs node/boss "'||Get_Boss(system.info.msg.toaddr)||'" exists (system: "'||nlstem.SYSTEM||'", phone: "'||nlstem.PHONE||'").,;5,;|')
    end
return

Check_NL_Sender: procedure expose system.
    MM_GetNodeListNode Get_Boss(system.info.msg.fromaddr) 'nlstem'
    if (rc=4) then do
        dom = system.info.fromdomain
        call TMLog('['||system.info.area||'/'||system.info.number||'] Senderīs node/boss "'||Get_Boss(system.info.msg.fromaddr)||'" unknown.,;3,;|')
        if (system.domain.dom.text.NLS.0~='')                   then call Send_Msg(system.info.msg.to||',;'||system.info.msg.toaddr||',;'||system.info.toemail||',;'||system.info.area||',;'||Get_LanguageText('system.domain.'||dom||'.text.NLS,;'||system.info.tolanguage)||',;'||Get_LanguageText('system.domain.'||dom||'.subj.NLS,;'||system.info.tolanguage))
        if (find(upper(system.domain.dom.todo.NLS),'STOP')~=0)  then call Do_BadMail()
    end
    else do
        call TMLog('['||system.info.area||'/'||system.info.number||'] Senderīs node/boss "'||Get_Boss(system.info.msg.fromaddr)||'" exists (system: "'||nlstem.SYSTEM||'", phone: "'||nlstem.PHONE||'").,;5,;|')
    end
return



Check_ToDo_Each: procedure expose system.
    i=0
    do while(i<system.todoe.count)
        check=1
        if            (system.todoe.i.fromname~='#?')    then check = (check & Check_Pattern(system.info.msg.from||',;'||system.todoe.i.fromname))
        if ((check=1)&(system.todoe.i.fromaddr~='#?'))   then check = (check & Check_Pattern(system.info.msg.fromaddr||',;'||system.todoe.i.fromaddr))
        if ((check=1)&(system.todoe.i.fromemail~='#?'))  then check = (check & Check_Pattern(system.info.fromemail||',;'||system.todoe.i.fromemail))
        if ((check=1)&(system.todoe.i.toname~='#?'))     then check = (check & Check_Pattern(system.info.msg.to||',;'||system.todoe.i.toname))
        if ((check=1)&(system.todoe.i.toaddr~='#?'))     then check = (check & Check_Pattern(system.info.msg.toaddr||',;'||system.todoe.i.toaddr))
        if ((check=1)&(system.todoe.i.toemail~='#?'))    then check = (check & Check_Pattern(system.info.toemail||',;'||system.todoe.i.toemail))
        if ((check=1)&(system.todoe.i.msgsubj~='#?'))    then check = (check & Check_Pattern(system.info.msg.subj||',;'||system.todoe.i.msgsubj))
        if ((check=1)&(system.todoe.i.msgtext~='#?'))    then do
            Out.Count=0
            MM_SearchInStem 'system.info.msg.TEXT' 'Out' system.todoe.i.msgtext 'NUM'
            if (out=0) then check=0
        end
        if (check=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Executing ToDoEach command no.'||i||'.,;4,;|')
            address command Replace_My_Patterns(system.todoe.i.command)
            call TMLog('['||system.info.area||'/'||system.info.number||'] ToDoEach command no.'||i||' finished.,;4,;|')
        end
        i=i+1
    end
return

Check_ToDo_Once: procedure expose system.
    i=0
    do while(i<system.todoo.count)
        check=1
        if            (system.todoo.i.fromname~='#?')    then check = (check & Check_Pattern(system.info.msg.from||',;'||system.todoo.i.fromname))
        if ((check=1)&(system.todoo.i.fromaddr~='#?'))   then check = (check & Check_Pattern(system.info.msg.fromaddr||',;'||system.todoo.i.fromaddr))
        if ((check=1)&(system.todoo.i.fromemail~='#?'))  then check = (check & Check_Pattern(system.info.fromemail||',;'||system.todoo.i.fromemail))
        if ((check=1)&(system.todoo.i.toname~='#?'))     then check = (check & Check_Pattern(system.info.msg.to||',;'||system.todoo.i.toname))
        if ((check=1)&(system.todoo.i.toaddr~='#?'))     then check = (check & Check_Pattern(system.info.msg.toaddr||',;'||system.todoo.i.toaddr))
        if ((check=1)&(system.todoo.i.toemail~='#?'))    then check = (check & Check_Pattern(system.info.toemail||',;'||system.todoo.i.toemail))
        if ((check=1)&(system.todoo.i.msgsubj~='#?'))    then check = (check & Check_Pattern(system.info.msg.subj||',;'||system.todoo.i.msgsubj))
        if ((check=1)&(system.todoo.i.msgtext~='#?'))    then do
            Out.Count=0
            MM_SearchInStem 'system.info.msg.TEXT' 'Out' system.todoo.i.msgtext 'NUM'
            if (out=0) then check=0
        end
        if (check=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Marking for ToDoOnce command no.'||i||'.,;4,;|')
            system.todoo.i.doit = 1
        end
        i=i+1
    end
return


Do_ToDo_Once: procedure expose system.
    do i=0 to system.todoo.count-1
        if (system.todoo.i.doit=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Executing ToDoOnce command no.'||i||'.,;4,;|')
            address command system.todoo.i.command
            call TMLog('['||system.info.area||'/'||system.info.number||'] ToDoOnce command no.'||i||' finished.,;4,;|')
        end
    end
return


Check_Move: procedure expose system.
    /*
        Attention !
        Must be last command before new Scan !!!
    */
    i = 0
    do while(i<system.move.count)
        check=1
        if            (system.move.i.fromname~='#?')    then check = (check & Check_Pattern(system.info.msg.from||',;'||system.move.i.fromname))
        if ((check=1)&(system.move.i.fromaddr~='#?'))   then check = (check & Check_Pattern(system.info.msg.fromaddr||',;'||system.move.i.fromaddr))
        if ((check=1)&(system.move.i.fromemail~='#?'))  then check = (check & Check_Pattern(system.info.fromemail||',;'||system.move.i.fromemail))
        if ((check=1)&(system.move.i.toname~='#?'))     then check = (check & Check_Pattern(system.info.msg.to||',;'||system.move.i.toname))
        if ((check=1)&(system.move.i.toaddr~='#?'))     then check = (check & Check_Pattern(system.info.msg.toaddr||',;'||system.move.i.toaddr))
        if ((check=1)&(system.move.i.toemail~='#?'))    then check = (check & Check_Pattern(system.info.toemail||',;'||system.move.i.toemail))
        if ((check=1)&(system.move.i.msgsubj~='#?'))    then check = (check & Check_Pattern(system.info.msg.subj||',;'||system.move.i.msgsubj))
        if ((check=1)&(system.move.i.msgtext~='#?'))    then do
            Out.Count=0
            MM_SearchInStem 'system.info.msg.TEXT' 'Out' system.move.i.msgtext 'NUM'
            if (out=0) then check=0
        end
        if ((check=1)&(system.info.area=system.move.i.newarea)) then check=0
        if (check=1) then do
            call TMLog('['||system.info.area||'/'||system.info.number||'] Mail moved to area "'||system.move.i.newarea||'".,;4,;|')
            MM_MoveMsg system.info.area system.info.number system.move.i.newarea
            if (rc~=0) then ByeBye('100,;***Error: Unable to move message ! ('||system.info.area||', '||system.info.number||' -> '||system.move.i.newarea||')')
            system.info.ok = 0
        end
        i=i+1
    end
return


/*---------------------------------------------------------------------------*\
|*  Replace & Send Functions :                                               *|
\*---------------------------------------------------------------------------*/


Replace_String: procedure
    parse arg string ',;' rep ',;' by
    do while (pos(rep,string)~=0)
        interpret "parse var string pre '"rep"' post"
        string = pre||by||post
    end
return string


Replace_My_Patterns: procedure expose system.
    parse arg string

    fdom  = system.info.fromdomain
    tdom  = system.info.todomain
    flang = system.info.fromlanguage
    tlang = system.info.tolanguage


    string = Replace_String(string||',;'||'{SYSOP_NAME}'||',;'||system.cfg.sysop.name)
    string = Replace_String(string||',;'||'{SYSOP_ADDR}'||',;'||system.cfg.sysop.addr)
    string = Replace_String(string||',;'||'{SYSOP_EMAIL}'||',;'||system.cfg.sysop.email)

    string = Replace_String(string||',;'||'{PRG_NAME}'||',;'||system.prg.name)
    string = Replace_String(string||',;'||'{PRG_VER}'||',;'||vsystem.prg.ver)
    string = Replace_String(string||',;'||'{PRG_ID}'||',;'||system.prg.id)
    string = Replace_String(string||',;'||'{PRG_SYS}'||',;'||system.info.thissys)

    string = Replace_String(string||',;'||'{MSG_NUMBER}'||',;'||system.info.number)
    string = Replace_String(string||',;'||'{MSG_AREA}'||',;'||system.info.area)

    string = Replace_String(string||',;'||'{MSG_FROM}'||',;'||system.info.msg.from)
    string = Replace_String(string||',;'||'{MSG_FROMADDR}'||',;'||system.info.msg.fromaddr)
    string = Replace_String(string||',;'||'{MSG_FROMEMAIL}'||',;'||system.info.fromemail)
    string = Replace_String(string||',;'||'{MSG_FROMWHOM}'||',;'||system.info.fromwho)
    string = Replace_String(string||',;'||'{MSG_FROMNICK}'||',;'||word(system.info.msg.from,1))
    if (fdom~=-1) then string = Replace_String(string||',;'||'{MSG_FROMDOMAIN}'||',;'||system.domain.fdom.name)
                  else string = Replace_String(string||',;'||'{MSG_FROMDOMAIN}'||',;'||'??????')
    string = Replace_String(string||',;'||'{MSG_FROMLANGUAGE}'||',;'||system.language.flang)

    string = Replace_String(string||',;'||'{MSG_TO}'||',;'||system.info.msg.to)
    string = Replace_String(string||',;'||'{MSG_TOADDR}'||',;'||system.info.msg.toaddr)
    string = Replace_String(string||',;'||'{MSG_TOEMAIL}'||',;'||system.info.toemail)
    string = Replace_String(string||',;'||'{MSG_TOWHOM}'||',;'||system.info.towho)
    string = Replace_String(string||',;'||'{MSG_TONICK}'||',;'||word(system.info.msg.to,1))
    if (tdom~=-1) then string = Replace_String(string||',;'||'{MSG_TODOMAIN}'||',;'||system.domain.tdom.name)
                  else string = Replace_String(string||',;'||'{MSG_TODOMAIN}'||',;'||'??????')
    string = Replace_String(string||',;'||'{MSG_TOLANGUAGE}'||',;'||system.language.tlang)

    string = Replace_String(string||',;'||'{MSG_SUBJECT}'||',;'||system.info.msg.subj)
    string = Replace_String(string||',;'||'{MSG_DATE}'||',;'||system.info.msg.date)
    string = Replace_String(string||',;'||'{MSG_FLAGS}'||',;'||system.info.msg.flags)

    string = Replace_String(string||',;'||'{EXTRA1}'||',;'||system.info.extra1)
    string = Replace_String(string||',;'||'{EXTRA2}'||',;'||system.info.extra2)
    string = Replace_String(string||',;'||'{EXTRA3}'||',;'||system.info.extra3)
    string = Replace_String(string||',;'||'{EXTRA4}'||',;'||system.info.extra4)

/*  string = Replace_String(string||',;'||'{}'||',;'||system.info.) */

return string


Get_LanguageText: procedure expose system.
    parse arg stext ',;' lang
    interpret 'if ('||stext||'.'||lang||' ~= "") then newtext = '||stext||'.'||lang||';else newtext = '||stext||'.0'
return newtext


Send_Msg: procedure expose system.
    /*  to_name to_addr toemail msg_area msg_file msg_subj */
    parse arg to_name ',;' to_addr ',;' to_email ',;' msg_area ',;' msg_file ',;' msg_subj
    NewMsgStem.TEXT.count    = 0
    DummyStem.count=0

    if (to_email~='') then do
        DummyStem.0 = 'To: '||to_email
        DummyStem.1 = ''
        DummyStem.count = 2
    end

    if (msg_file~='') then do
        MM_ReadStem msg_file 'DummyStem' 'APPEND'
        if (rc~=0) then call ByeBye('100,;***Error: Unable to read file "'||msg_file||'" !')

        do i=0 to DummyStem.count-1
            if (word(DummyStem.i,1)='{TEXT}') then do
                if (word(DummyStem.i,2) ~= '') then do
                    k=(word(DummyStem.i,2))
                    if (k>system.info.msg.text.count) then k=system.info.msg.text.count
                end
                else k=system.info.msg.TEXT.count
                do j=0 to k-1
                    MM_AddToStem 'NewMsgStem.TEXT' 'system.info.msg.TEXT.'||j
                end
            end
            else do
                string = Replace_My_Patterns(DummyStem.i)
                MM_AddToStem 'NewMsgStem.TEXT' 'string'
            end
        end
        MM_WriteStem system.cfg.tempfile 'NewMsgStem.TEXT'
        if (rc~=0) then call ByeBye('100,;***Error: Unable to write to file "'||system.cfg.tempfile||'" !')
    end
    else do
        MM_WriteStem system.cfg.tempfile 'system.info.msg.TEXT'
        if (rc~=0) then call ByeBye('100,;***Error: Unable to write to file "'||system.cfg.tempfile||'" !')
    end
    

    NewMsgStem.TO       = to_name
    NewMsgStem.TOADDR   = to_addr
    NewMsgStem.FROM     = system.prg.id
    NewMsgStem.FROMADDR = ''
    NewMsgStem.SUBJ     = Replace_My_Patterns(msg_subj)
    NewMsgStem.FLAGS    = system.cfg.flags
    NewMsgStem.FILE     = system.cfg.tempfile
    MM_WriteMsg msg_area 'NewMsgStem'
    if (rc~=0) then call ByeBye('100,;***Error: Unable to write message to area "'||msg_area||'" !')
    MM_DeleteFile system.cfg.tempfile
    if (rc~=0) then call ByeBye('100,;***Error: Unable to delete file "'||system.cfg.tempfile||'" !')
return



Edit_Msg: procedure expose system.
    parse arg msg_file

    NewMsgStem. = 0
    DummyStem.count=0

    if (system.info.toemail~='') then do
        NewMsgStem.TEXT.0 = 'To: '||system.info.toemail
        NewMsgStem.TEXT.1 = ''
        NewMsgStem.TEXT.count = 2
    end

    if (msg_file~='') then do
        MM_ReadStem msg_file 'DummyStem'
        if (rc~=0) then call ByeBye('100,;***Error: Unable to read file "'||msg_file||'" !')
        do i=0 to DummyStem.count-1
            if (word(DummyStem.i,1)='{TEXT}') then do
                if (word(DummyStem.i,2) ~= '') then do
                    k=(word(DummyStem.i,2))
                    if (k>system.info.msg.text.count) then k=system.info.msg.text.count
                end
                else k=system.info.msg.TEXT.count
                if (word(upper(system.info.msg.TEXT.0),1)='TO:') then l=2
                else l=0
                do j=l to k-1
                    MM_AddToStem 'NewMsgStem.TEXT' 'system.info.msg.TEXT.'||j
                end
            end
            else do
                string = Replace_My_Patterns(DummyStem.i)
                MM_AddToStem 'NewMsgStem.TEXT' 'string'
            end
        end

    end
    else do
        if (word(upper(system.info.msg.TEXT.0),1)='TO:') then l=2
        else l=0
        do j=l to system.info.msg.text.count-1
            MM_AddToStem 'NewMsgStem.TEXT' 'system.info.msg.TEXT.'||j
        end
    end
    MM_WriteStem system.cfg.tempfile 'NewMsgStem.TEXT'
    if (rc~=0) then call ByeBye('100,;***Error: Unable to write to file "'||system.cfg.tempfile||'" !')

    NewMsgStem.TO       = system.info.msg.to
    NewMsgStem.TOADDR   = system.info.msg.toaddr
    NewMsgStem.FROM     = system.info.msg.from
    NewMsgStem.FROMADDR = system.info.msg.fromaddr
    NewMsgStem.SUBJ     = Replace_my_Patterns(system.info.msg.subj)
    NewMsgStem.FLAGS    = ''
    NewMsgStem.FILE     = system.cfg.tempfile
    MM_EditMsg system.info.area system.info.number 'NewMsgStem'
    if (rc~=0) then call ByeBye('100,;***Error: Unable to write message to area "'||msg_area||'" !')
    MM_DeleteFile system.cfg.tempfile
    if (rc~=0) then call ByeBye('100,;***Error: Unable to delete file "'||system.cfg.tempfile||'" !')
    call Read_Msg_Info(system.info.area||',;'||system.info.number)
return



Get_Boss: procedure
    parse arg zone ':' region '/' node '.' point '@' domain
return zone||':'||region||'/'||node||'.0@'||domain



/*---------------------------------------------------------------------------------------*\
|* Pattern Check procedures:                                                             *|
\*---------------------------------------------------------------------------------------*/

Check_Pattern: procedure
    parse arg In.0 ',;' pattern
    In.count=1; Out.count=0
    pattern = '"'||pattern||'"'
    MM_SearchInStem 'In' 'Out' pattern 'NUM'
return Out.count

Check_Address_Pattern: procedure
    parse arg addr_a ',;' addr_b
    parse var addr_a zone_a ':' region_a '/' node_a '.' point_a '@' domain_a
    parse var addr_b zone_b ':' region_b '/' node_b '.' point_b '@' domain_b
return ( Check_Pattern(zone_a',;'zone_b) & Check_Pattern(region_a',;'region_b) & Check_Pattern(node_a',;'node_b)  & Check_Pattern(point_a',;'point_b) & Check_Pattern(domain_a',;'domain_b) )




/*---------------------------------------------------------------------------------------*\
|* CFG procedures:                                                                       *|
\*---------------------------------------------------------------------------------------*/

AddToAddStem: procedure expose AddStem.
    parse arg string
    MM_AddToStem 'AddStem' 'string'
return


Compile_Cfg: procedure expose system.

    /* Init vars: */
    CfgStem.count = 0
    AddStem.count = 0; AddStem. = ''
    PrgStem.count = 0
    MM_ReadStem system.cfg.cfgfile 'CfgStem'
    if (rc~=0) then do; say "***Error: File "||system.cfg.cfgfile||" not found."; exit 0; end;

    conffile = system.cfg.cfgfile
    MM_CRCFile conffile 'confcrc'
    progfile = system.cfg.prgfile

    system. = ''
    system.language.count   = 0; languageadd    = -1
    system.langpat.count    = 0; langpatadd     = -1
    system.domain.count     = 0; domainadd      = -1
    system.bounce.count     = 0; bounceadd      = -1
    system.remap.count      = 0; remapadd       = -1
    system.copy.count       = 0; copyadd        = -1
    system.todoe.count      = 0; todoeadd       = -1
    system.todoo.count      = 0; todooadd       = -1
    system.move.count       = 0; moveadd        = -1


    /* Parse Config: */
    do i=0 to CfgStem.count-1
        parse var CfgStem.i pre '#' keyword ' ' post
        select
            when (pre~='')              then nop

            when (keyword='SYSOPNAME')  then system.cfg.sysop.name  = post
            when (keyword='SYSOPADDR')  then system.cfg.sysop.addr  = post
            when (keyword='SYSOPEMAIL') then system.cfg.sysop.email = post

            when (keyword='TEMPFILE')   then system.cfg.tempfile    = post
            when (keyword='BADAREA')    then system.cfg.badarea     = post
            when (keyword='STDFLAGS')   then system.cfg.flags       = post

            when (keyword='LOGFILE')    then system.log.logfile     = post
            when (keyword='LOGCLEVEL')  then system.log.logclevel   = post
            when (keyword='LOGFLEVEL')  then system.log.logflevel   = post

            when (keyword='LANGUAGE')   then do
                                        parse var post l ' ' str
                                        languageadd = l; if ((l+1)>system.language.count) then system.language.count=l+1
                                        system.language.l = str
                                        end
            when (keyword='LANGPAT')    then do
                                        parse var post l ' ' str
                                        langpatadd = langpatadd+1; system.langpat.count=langpatadd+1
                                        system.langpat.langpatadd.textset = l
                                        parse var str fadd ' ' eadd
                                        system.langpat.langpatadd.pattern = fadd
                                        system.langpat.langpatadd.empattern = eadd
                                        end

            when (keyword='UDTTEXT')    then do
                                        parse var post l ' ' str
                                        system.udom.text.to.l = str
                                        end
            when (keyword='UDTSUBJ')    then do
                                        parse var post l ' ' str
                                        system.udom.subj.to.l = str
                                        end
            when (keyword='UDFTEXT')    then do
                                        parse var post l ' ' str
                                        system.udom.text.from.l = str
                                        end
            when (keyword='UDFSUBJ')    then do
                                        parse var post l ' ' str
                                        system.udom.subj.from.l = str
                                        end


            when (keyword='DOMAIN')     then do
                                        domainadd=domainadd+1; system.domain.count=system.domain.count+1
                                        system.domain.domainadd.name = post
                                        end
            when (keyword='DPATTERN')   then system.domain.domainadd.pattern = post
            when (keyword='DCHECK')     then system.domain.domainadd.check = post
            when (keyword='DRRRTEXT')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.text.RRR.l = str
                                        end
            when (keyword='DRRRSUBJ')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.subj.RRR.l = str
                                        end
            when (keyword='DCNSTEXT')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.text.CNS.l = str
                                        end
            when (keyword='DCNSSUBJ')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.subj.CNS.l = str
                                        end
            when (keyword='DCNRTEXT')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.text.CNR.l = str
                                        end
            when (keyword='DCNRSUBJ')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.subj.CNR.l = str
                                        end
            when (keyword='DTODONLR')   then system.domain.domainadd.todo.NLR = post
            when (keyword='DNLRTEXT')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.text.NLR.l = str
                                        end
            when (keyword='DNLRSUBJ')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.subj.NLR.l = str
                                        end
            when (keyword='DTODONLS')   then system.domain.domainadd.todo.NLS = post
            when (keyword='DNLSTEXT')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.text.NLS.l = str
                                        end
            when (keyword='DNLSSUBJ')   then do
                                        parse var post l ' ' str
                                        system.domain.domainadd.subj.NLS.l = str
                                        end



            when (keyword='BOUNCE')     then do
                                        bounceadd=bounceadd+1; system.bounce.count=system.bounce.count+1
                                        end
            when (keyword='BFROMNAME')  then system.bounce.bounceadd.from = post
            when (keyword='BFROMADDR')  then system.bounce.bounceadd.fromaddr = post
            when (keyword='BFROMEMAIL') then system.bounce.bounceadd.fromemail = post
            when (keyword='BTONAME')    then system.bounce.bounceadd.to = post
            when (keyword='BTOADDR')    then system.bounce.bounceadd.toaddr = post
            when (keyword='BTOEMAIL')   then system.bounce.bounceadd.toemail = post
            when (keyword='BSUBJECT')   then system.bounce.bounceadd.subject = post
            when (keyword='BTEXT')      then system.bounce.bounceadd.text = post
            when (keyword='BINFTEXT')   then do
                                        parse var post l ' ' str
                                        system.bounce.bounceadd.inform.text.l = str
                                        end
            when (keyword='BINFSUBJ')   then do
                                        parse var post l ' ' str
                                        system.bounce.bounceadd.inform.subj.l = str
                                        end


            when (keyword='REMAP')      then do
                                        remapadd=remapadd+1; system.remap.count=system.remap.count+1
                                        end
            when (keyword='RINNAME')    then system.remap.remapadd.in.name = post
            when (keyword='RINADDR')    then system.remap.remapadd.in.addr = post
            when (keyword='RINEMAIL')   then system.remap.remapadd.in.email = post
            when (keyword='ROUTNAME')   then system.remap.remapadd.to = post
            when (keyword='ROUTADDR')   then system.remap.remapadd.toaddr = post
            when (keyword='ROUTEMAIL')  then system.remap.remapadd.toemail = post
            when (keyword='ROUTTEXT')   then do
                                        parse var post l ' ' str
                                        system.remap.remapadd.out.text.l = str
                                        end
            when (keyword='ROUTSUBJ')   then do
                                        parse var post l ' ' str
                                        system.remap.remapadd.out.subj.l = str
                                        end
            when (keyword='RINFTEXT')   then do
                                        parse var post l ' ' str
                                        system.remap.remapadd.inf.text.l = str
                                        end
            when (keyword='RINFSUBJ')   then do
                                        parse var post l ' ' str
                                        system.remap.remapadd.inf.subj.l = str
                                        end

            when (keyword='COPY')       then do
                                        copyadd=copyadd+1; system.copy.count=system.copy.count+1
                                        end
            when (keyword='CINFNAME')   then system.copy.copyadd.in.from.name  = post
            when (keyword='CINFADDR')   then system.copy.copyadd.in.from.addr  = post
            when (keyword='CINFEMAIL')  then system.copy.copyadd.in.from.email = post
            when (keyword='CINTNAME')   then system.copy.copyadd.in.to.name    = post
            when (keyword='CINTADDR')   then system.copy.copyadd.in.to.addr    = post
            when (keyword='CINTEMAIL')  then system.copy.copyadd.in.to.email   = post
            when (keyword='CINSUBJ')    then system.copy.copyadd.in.subject    = post
            when (keyword='CINTEXT')    then system.copy.copyadd.in.text       = post
            when (keyword='COUTNAME')   then system.copy.copyadd.out.name  = post
            when (keyword='COUTADDR')   then system.copy.copyadd.out.addr  = post
            when (keyword='COUTEMAIL')  then system.copy.copyadd.out.email = post
            when (keyword='COUTTEXT')   then system.copy.copyadd.out.text  = post
            when (keyword='COUTSUBJ')   then system.copy.copyadd.out.subj  = post

            when (keyword='TODOEACH')   then do
                                        todoeadd=todoeadd+1; system.todoe.count=system.todoe.count+1
                                        end
            when (keyword='TDEFNAME')   then system.todoe.todoeadd.fromname  = post
            when (keyword='TDEFADDR')   then system.todoe.todoeadd.fromaddr  = post
            when (keyword='TDEFEMAIL')  then system.todoe.todoeadd.fromemail = post
            when (keyword='TDETNAME')   then system.todoe.todoeadd.toname    = post
            when (keyword='TDETADDR')   then system.todoe.todoeadd.toaddr    = post
            when (keyword='TDETEMAIL')  then system.todoe.todoeadd.toemail   = post
            when (keyword='TDESUBJ')    then system.todoe.todoeadd.msgsubj   = post
            when (keyword='TDETEXT')    then system.todoe.todoeadd.msgtext   = post
            when (keyword='TDECOM')     then system.todoe.todoeadd.command   = post

            when (keyword='TODOONCE')   then do
                                        todooadd=todooadd+1; system.todoo.count=system.todoo.count+1
                                        end
            when (keyword='TDOFNAME')   then system.todoo.todooadd.fromname  = post
            when (keyword='TDOFADDR')   then system.todoo.todooadd.fromaddr  = post
            when (keyword='TDOFEMAIL')  then system.todoo.todooadd.fromemail = post
            when (keyword='TDOTNAME')   then system.todoo.todooadd.toname    = post
            when (keyword='TDOTADDR')   then system.todoo.todooadd.toaddr    = post
            when (keyword='TDOTEMAIL')  then system.todoo.todooadd.toemail   = post
            when (keyword='TDOSUBJ')    then system.todoo.todooadd.msgsubj   = post
            when (keyword='TDOTEXT')    then system.todoo.todooadd.msgtext   = post
            when (keyword='TDOCOM')     then system.todoo.todooadd.command   = post

            when (keyword='MOVE')       then do
                                        moveadd=moveadd+1; system.move.count=system.move.count+1
                                        end
            when (keyword='MOVEFNAME')  then system.move.moveadd.fromname  = post
            when (keyword='MOVEFADDR')  then system.move.moveadd.fromaddr  = post
            when (keyword='MOVEFEMAIL') then system.move.moveadd.fromemail = post
            when (keyword='MOVETNAME')  then system.move.moveadd.toname    = post
            when (keyword='MOVETADDR')  then system.move.moveadd.toaddr    = post
            when (keyword='MOVETEMAIL') then system.move.moveadd.toemail   = post
            when (keyword='MOVESUBJ')   then system.move.moveadd.msgsubj   = post
            when (keyword='MOVETEXT')   then system.move.moveadd.msgtext   = post
            when (keyword='MOVEAREA')   then system.move.moveadd.newarea   = post

            otherwise nop
        end
    end


    /* Write config: */

    call AddToAddStem(' ')
    call AddToAddStem(' ')
    call AddToAddStem('/*')
    call AddToAddStem('       This config was compiled from file '||conffile||'.')
    call AddToAddStem('*/')
    call AddToAddStem(' ')
    call AddToAddStem('Config: procedure expose system.')
    call AddToAddStem(' ')
    call AddToAddStem('  /* Sysop settings: */')
    call AddToAddStem('    system.cfg.sysop.name  = "'||system.cfg.sysop.name||'"')
    call AddToAddStem('    system.cfg.sysop.addr  = "'||system.cfg.sysop.addr||'"')
    call AddToAddStem('    system.cfg.sysop.email = "'||system.cfg.sysop.email||'"')

    call AddToAddStem('')
    call AddToAddStem('  /* Standard settings: */')
    call AddToAddStem('    system.cfg.tempfile    = "'||system.cfg.tempfile||'"')
    call AddToAddStem('    system.cfg.cfgfile     = "'||conffile||'"')
    call AddToAddStem('    system.cfg.cfgcrc      = "'||confcrc||'"')
    call AddToAddStem('    system.cfg.badarea     = "'||system.cfg.badarea||'"')
    call AddToAddStem('    system.cfg.flags       = "'||system.cfg.flags||'"')
    call AddToAddStem('    system.cfg.languages   = '||system.language.count)

    call AddToAddStem('')
    call AddToAddStem('  /* Standard settings: */')
    call AddToAddStem('    system.log.logfile     = "'||system.log.logfile||'"')
    call AddToAddStem('    system.log.logclevel   = '||system.log.logclevel)
    call AddToAddStem('    system.log.logflevel   = '||system.log.logflevel)

    call AddToAddStem('')
    call AddToAddStem('  /* Languages: */')
    call AddToAddStem('    system.language.count  = '||system.language.count)
    do i=0 to system.language.count-1
        call AddToAddStem('    system.language.'||i||' = "'||system.language.i||'"')
    end

    call AddToAddStem('')
    call AddToAddStem('  /* Language patterns: */')
    call AddToAddStem('    system.langpat.count  = '||system.langpat.count)
    do i=0 to system.langpat.count-1
        call AddToAddStem('    system.langpat.'||i||'.pattern   = "'||system.langpat.i.pattern||'"')
        call AddToAddStem('    system.langpat.'||i||'.empattern = "'||system.langpat.i.empattern||'"')
        call AddToAddStem('    system.langpat.'||i||'.textset   = '||system.langpat.i.textset)
    end

    call AddToAddStem('')
    call AddToAddStem('  /* Standard texts: */')
    do i=0 to system.language.count-1
        call AddToAddStem('    system.udom.text.from.'||i||' = "'||system.udom.text.from.i||'"')
        call AddToAddStem('    system.udom.subj.from.'||i||' = "'||system.udom.subj.from.i||'"')
        call AddToAddStem('    system.udom.text.to.'||i||'   = "'||system.udom.text.to.i||'"')
        call AddToAddStem('    system.udom.subj.to.'||i||'   = "'||system.udom.subj.to.i||'"')
    end

    call AddToAddStem(' ')
    call AddToAddStem('  /* Domains: */')
    call AddToAddStem('    system.domain.count = '||system.domain.count)
    do i=0 to system.domain.count-1
        call AddToAddStem('    system.domain.'||i||'.name       = "'||system.domain.i.name||'"')
        call AddToAddStem('    system.domain.'||i||'.pattern    = "'||system.domain.i.pattern||'"')
        call AddToAddStem('    system.domain.'||i||'.check      = "'||system.domain.i.check||'"')
        call AddToAddStem('    system.domain.'||i||'.todo.NLR   = "'||system.domain.i.todo.NLR||'"')
        call AddToAddStem('    system.domain.'||i||'.todo.NLS   = "'||system.domain.i.todo.NLS||'"')
        do j=0 to system.language.count-1
            call AddToAddStem('    system.domain.'||i||'.text.RRR.'||j||' = "'||system.domain.i.text.RRR.j||'"')
            call AddToAddStem('    system.domain.'||i||'.subj.RRR.'||j||' = "'||system.domain.i.subj.RRR.j||'"')
            call AddToAddStem('    system.domain.'||i||'.text.CNS.'||j||' = "'||system.domain.i.text.CNS.j||'"')
            call AddToAddStem('    system.domain.'||i||'.subj.CNS.'||j||' = "'||system.domain.i.subj.CNS.j||'"')
            call AddToAddStem('    system.domain.'||i||'.text.CNR.'||j||' = "'||system.domain.i.text.CNR.j||'"')
            call AddToAddStem('    system.domain.'||i||'.subj.CNR.'||j||' = "'||system.domain.i.subj.CNR.j||'"')
            call AddToAddStem('    system.domain.'||i||'.text.NLR.'||j||' = "'||system.domain.i.text.NLR.j||'"')
            call AddToAddStem('    system.domain.'||i||'.subj.NLR.'||j||' = "'||system.domain.i.subj.NLR.j||'"')
            call AddToAddStem('    system.domain.'||i||'.text.NLS.'||j||' = "'||system.domain.i.text.NLS.j||'"')
            call AddToAddStem('    system.domain.'||i||'.subj.NLS.'||j||' = "'||system.domain.i.subj.NLS.j||'"')
        end
    end

    call AddToAddStem(' ')
    call AddToAddStem('  /* Bounce: */')
    call AddToAddStem('    system.bounce.count = '||system.bounce.count)
    do i=0 to system.bounce.count-1
        call AddToAddStem('    system.bounce.'||i||'.from      = "'||system.bounce.i.from||'"')
        call AddToAddStem('    system.bounce.'||i||'.fromaddr  = "'||system.bounce.i.fromaddr||'"')
        call AddToAddStem('    system.bounce.'||i||'.fromemail = "'||system.bounce.i.fromemail||'"')
        call AddToAddStem('    system.bounce.'||i||'.to        = "'||system.bounce.i.to||'"')
        call AddToAddStem('    system.bounce.'||i||'.toaddr    = "'||system.bounce.i.toaddr||'"')
        call AddToAddStem('    system.bounce.'||i||'.toemail   = "'||system.bounce.i.toemail||'"')
        call AddToAddStem('    system.bounce.'||i||'.subject   = "'||system.bounce.i.subject||'"')
        call AddToAddStem('    system.bounce.'||i||'.text      = "'||system.bounce.i.text||'"')
        do j=0 to system.language.count-1
            call AddToAddStem('    system.bounce.'||i||'.inform.text.'||j||' = "'||system.11bounce.i.inform.text.j||'"')
            call AddToAddStem('    system.bounce.'||i||'.inform.subj.'||j||' = "'||system.bounce.i.inform.subj.j||'"')
        end
    end

    call AddToAddStem(' ')
    call AddToAddStem('  /* Remap: */')
    call AddToAddStem('    system.remap.count = '||system.remap.count)
    do i=0 to system.remap.count-1
        call AddToAddStem('    system.remap.'||i||'.in.name   = "'||system.remap.i.in.name||'"')
        call AddToAddStem('    system.remap.'||i||'.in.addr   = "'||system.remap.i.in.addr||'"')
        call AddToAddStem('    system.remap.'||i||'.in.email  = "'||system.remap.i.in.email||'"')
        call AddToAddStem('    system.remap.'||i||'.out.name  = "'||system.remap.i.out.name||'"')
        call AddToAddStem('    system.remap.'||i||'.out.addr  = "'||system.remap.i.out.addr||'"')
        call AddToAddStem('    system.remap.'||i||'.out.email = "'||system.remap.i.out.email||'"')
        do j=0 to system.language.count-1
            call AddToAddStem('    system.remap.'||i||'.out.text.'||j||' = "'||system.remap.i.out.text.j||'"')
            call AddToAddStem('    system.remap.'||i||'.out.subj.'||j||' = "'||system.remap.i.out.subj.j||'"')
            call AddToAddStem('    system.remap.'||i||'.inf.text.'||j||' = "'||system.remap.i.inf.text.j||'"')
            call AddToAddStem('    system.remap.'||i||'.inf.subj.'||j||' = "'||system.remap.i.inf.subj.j||'"')
        end
    end


    call AddToAddStem(' ')
    call AddToAddStem('  /* Copy: */')
    call AddToAddStem('    system.copy.count = '||system.copy.count)
    do i=0 to system.copy.count-1
        call AddToAddStem('    system.copy.'||i||'.in.from.name   = "'||system.copy.i.in.from.name||'"')
        call AddToAddStem('    system.copy.'||i||'.in.from.addr   = "'||system.copy.i.in.from.addr||'"')
        call AddToAddStem('    system.copy.'||i||'.in.from.email  = "'||system.copy.i.in.from.email||'"')
        call AddToAddStem('    system.copy.'||i||'.in.to.name     = "'||system.copy.i.in.to.name||'"')
        call AddToAddStem('    system.copy.'||i||'.in.to.addr     = "'||system.copy.i.in.to.addr||'"')
        call AddToAddStem('    system.copy.'||i||'.in.to.email    = "'||system.copy.i.in.to.email||'"')
        call AddToAddStem('    system.copy.'||i||'.in.subject     = "'||system.copy.i.in.subject||'"')
        call AddToAddStem('    system.copy.'||i||'.in.text        = "'||system.copy.i.in.text||'"')
        call AddToAddStem('    system.copy.'||i||'.out.name       = "'||system.copy.i.out.name||'"')
        call AddToAddStem('    system.copy.'||i||'.out.addr       = "'||system.copy.i.out.addr||'"')
        call AddToAddStem('    system.copy.'||i||'.out.email      = "'||system.copy.i.out.email||'"')
        call AddToAddStem('    system.copy.'||i||'.out.text       = "'||system.copy.i.out.text||'"')
        call AddToAddStem('    system.copy.'||i||'.out.subj       = "'||system.copy.i.out.subj||'"')
    end

    call AddToAddStem(' ')
    call AddToAddStem('  /* ToDoEach: */')
    call AddToAddStem('    system.todoe.count = '||system.todoe.count)
    do i=0 to system.todoe.count-1
        call AddToAddStem('    system.todoe.'||i||'.fromname    = "'||system.todoe.i.fromname||'"')
        call AddToAddStem('    system.todoe.'||i||'.fromaddr    = "'||system.todoe.i.fromaddr||'"')
        call AddToAddStem('    system.todoe.'||i||'.fromemail   = "'||system.todoe.i.fromemail||'"')
        call AddToAddStem('    system.todoe.'||i||'.toname      = "'||system.todoe.i.toname||'"')
        call AddToAddStem('    system.todoe.'||i||'.toaddr      = "'||system.todoe.i.toaddr||'"')
        call AddToAddStem('    system.todoe.'||i||'.toemail     = "'||system.todoe.i.toemail||'"')
        call AddToAddStem('    system.todoe.'||i||'.msgsubj     = "'||system.todoe.i.msgsubj||'"')
        call AddToAddStem('    system.todoe.'||i||'.msgtext     = "'||system.todoe.i.msgtext||'"')
        call AddToAddStem('    system.todoe.'||i||'.command     = "'||system.todoe.i.command||'"')
    end

    call AddToAddStem(' ')
    call AddToAddStem('  /* ToDoOnce: */')
    call AddToAddStem('    system.todoo.count = '||system.todoo.count)
    do i=0 to system.todoo.count-1
        call AddToAddStem('    system.todoo.'||i||'.fromname    = "'||system.todoo.i.fromname||'"')
        call AddToAddStem('    system.todoo.'||i||'.fromaddr    = "'||system.todoo.i.fromaddr||'"')
        call AddToAddStem('    system.todoo.'||i||'.fromemail   = "'||system.todoo.i.fromemail||'"')
        call AddToAddStem('    system.todoo.'||i||'.toname      = "'||system.todoo.i.toname||'"')
        call AddToAddStem('    system.todoo.'||i||'.toaddr      = "'||system.todoo.i.toaddr||'"')
        call AddToAddStem('    system.todoo.'||i||'.toemail     = "'||system.todoo.i.toemail||'"')
        call AddToAddStem('    system.todoo.'||i||'.msgsubj     = "'||system.todoo.i.msgsubj||'"')
        call AddToAddStem('    system.todoo.'||i||'.msgtext     = "'||system.todoo.i.msgtext||'"')
        call AddToAddStem('    system.todoo.'||i||'.command     = "'||system.todoo.i.command||'"')
    end

    call AddToAddStem(' ')
    call AddToAddStem('  /* Move: */')
    call AddToAddStem('    system.move.count = '||system.move.count)
    do i=0 to system.move.count-1
        call AddToAddStem('    system.move.'||i||'.fromname    = "'||system.move.i.fromname||'"')
        call AddToAddStem('    system.move.'||i||'.fromaddr    = "'||system.move.i.fromaddr||'"')
        call AddToAddStem('    system.move.'||i||'.fromemail   = "'||system.move.i.fromemail||'"')
        call AddToAddStem('    system.move.'||i||'.toname      = "'||system.move.i.toname||'"')
        call AddToAddStem('    system.move.'||i||'.toaddr      = "'||system.move.i.toaddr||'"')
        call AddToAddStem('    system.move.'||i||'.toemail     = "'||system.move.i.toemail||'"')
        call AddToAddStem('    system.move.'||i||'.msgsubj     = "'||system.move.i.msgsubj||'"')
        call AddToAddStem('    system.move.'||i||'.msgtext     = "'||system.move.i.msgtext||'"')
        call AddToAddStem('    system.move.'||i||'.newarea     = "'||system.move.i.newarea||'"')
    end

    call AddToAddStem(' ')
    call AddToAddStem('return')
    call AddToAddStem(' ')
    call AddToAddStem('/* EOF*/')


    MM_ReadStem progfile 'PrgStem'
    if (rc~=0) then do; say "***Error: File "||progfile||" not found."; exit 0; end;
    MM_WriteStem progfile||'.bak' 'PrgStem'
    if (rc~=0) then do; say "***Error: Unable to write to file "||progfile||".bak.."; exit 0; end;

    i=0
    do while((i<PrgStem.count)&(PrgStem.i~='/* *** BEGIN Config: *** */')); i=i+1; end
    if ((i<PrgStem.count)&(PrgStem.i='/* *** BEGIN Config: *** */')) then PrgStem.count = i+1

    MM_WriteStem progfile 'PrgStem'
    if (rc~=0) then do; say "***Error: Unable to write to file "||progfile||"."; exit 0; end;
    MM_WriteStem progfile 'AddStem' 'APPEND'
    if (rc~=0) then do; say "***Error: Unable to write to file "||progfile||"."; exit 0; end;

    say
    say "All done. Configfile "conffile" has been succesfully compiled."
    say "The programfile is "progfile"."
    exit 0

return


/*---------------------------------------------------------------------------------------*\
|* Config:                                                                               *|
\*---------------------------------------------------------------------------------------*/


/*****************************************************************************************/
/* DO NOT CHANGE ANYTHING BELOW THIS LINE !!! CONFIGURATION WILL BE DONE AUTOMATICALLY ! */
/*****************************************************************************************/

/* *** BEGIN Config: *** */
 
 
/*
       This config was compiled from file MM:Config/MM_TrackManager.cfg.
*/
 
Config: procedure expose system.

    call ByeBye("100,;Compile your own config first !")
 
return
 
/* EOF*/
