/* UMSFix - Groupfix fuer UMS */

//+ Defines & Includes
#include    <dos/dos.h>
#include    <dos/dosextens.h>
#include    <dos/rdargs.h>
#include    <exec/exec.h>

#include    <clib/alib_protos.h>
#include    <clib/dos_protos.h>
#include    <clib/exec_protos.h>
#include    <clib/ums_protos.h>
 

#include    <stdio.h>
#include    <stdarg.h>
#include    <time.h>

#include    <pragmas/ums_pragmas.h>
 
#include    "libraries/UMS.h"
#include    "DLIB:UMSMatchConfigTags.c"
#include    "DLIB:UMSReadMsgTags.c"
#include    "DLIB:UMSWriteMsgTags.c"
#include    "DLIB:UMSReadConfigTags.c"
#include    "DLIB:UMSWriteConfigTags.c"
#include    "DLIB:UMSSearchTags.c"
#include    "DLIB:UMSSelectTags.c"

#define     STRING_LENGTH       60
#define     TIMESTRING_SIZE     20

#define     GROUPNODE_ID        100
#define     FORWARDGROUPNODE_ID 101

#define     FAIL                20

enum    long
{
    NAME,
    PASSWORD,
    SERVER,
    SUBSCRIBE,
    RD_Size
};

struct  GroupNode
{
    struct Node gn_Node;
    UBYTE       gn_Data[ STRING_LENGTH ];
};

struct  ForwardGroupNode
{
    struct Node fn_Node;
    ULONG       fn_Count;
    UBYTE       fn_Data[ STRING_LENGTH ];
};
//-
//+ Consts
const   char    *Version    = "$VER: UMSFix 1.1 (24.01.96)";

const   char    *RD_Template    =
{
    "N=NAME,"
    "P=PASSWORD,"
    "S=SERVER,"
    "SUBSCRIBE/S"
};

const   char    *ExtSubscribeVar    = "groupfix.subscribe";
const   char    *LocalSubscribeVar  = "IntuiNews.groups";

const   char    *DefaultRemoteName  = "Areafix";
//-
//+ Variables
char    LoginName[ STRING_LENGTH ];
char    LoginServer[ STRING_LENGTH ];
char    LoginPassword[ STRING_LENGTH ];
char    FileName[ STRING_LENGTH ];
char    FullGroupName[ STRING_LENGTH ];

char    *ConfigString;
char    *TempBuffer;

time_t  OTime;

struct  Library     *UMSBase        = NULL;

struct  RDArgs      *RD_Struct      = NULL;

struct  List    *MBGroupList        = NULL;
struct  List    *ForwardGroupList   = NULL;
struct  List    *LinkGroupList      = NULL;
struct  List    *AllLinksGroupList  = NULL;
struct  List    *SubscribeGroupList = NULL;

long    RD_Array[ RD_Size ];
long    TempSize;
long    LogLevel    = 5;
long    ReportLevel = 5;

UMSUserAccount  Account     = NULL;

BPTR    LogHandle           = NULL;
BPTR    TempHandle          = NULL;
BPTR    StdOutputHandle;

BOOL    Help;
BOOL    List;
BOOL    Query;

long    MsgNumber       = NULL;
long    MsgSize;
long    MsgID           = NULL;

char    *MsgFrom        = NULL;
char    *MsgFromAddr    = NULL;
char    *MsgSubject     = NULL;
char    *MsgText        = NULL;
char    *MsgGroup       = NULL;
char    *CfgUser        = NULL;
char    *LinkNetName    = NULL;
char    *LinkPassword   = NULL;

char    LinkName[ STRING_LENGTH ];
//-
//+ Declarations
struct Node *FindNameNoCase( struct List *, char *);

char *StrCmpNoCase( char *, char *);

BOOL AddGroup( char *, struct List *);
BOOL AddForwardGroup( char *, long, struct List *);
BOOL RemoveGroup( char *, struct List *);

void FPrintfLog( long, char *, ...);
//-

//+main()
main()
{
    Open_All();

    MaintainOrders();
    if( RD_Array[ SUBSCRIBE ]) MaintainGroups();

    Close_All( NULL);
} //-

//+Open_All()
Open_All()
{
    if( !( StdOutputHandle = Output()))
        Close_All( FAIL);

    if( !( UMSBase = ( struct Library *) OpenLibrary( "ums.library", 11L)))
    {
        FPuts( StdOutputHandle, "can`t open ums.library V11+!\n");
        Close_All( FAIL);
    }

    if( !( RD_Struct = ReadArgs( RD_Template, RD_Array, NULL)))
    {
        FPuts( StdOutputHandle, "required argument missing!\n");
        Close_All( FAIL);
    }

    if( RD_Array[ NAME ]) strncpy( LoginName, ( char *) RD_Array[ NAME ], STRING_LENGTH);
    else strcpy( LoginName, "Areafix");

    if( RD_Array[ PASSWORD ]) strncpy( LoginPassword, ( char *) RD_Array[ PASSWORD ], STRING_LENGTH);
    else LoginPassword[ 0 ] = 0x00;

    if( RD_Array[ SERVER ]) strncpy( LoginServer, ( char *) RD_Array[ SERVER ], STRING_LENGTH);
    else strcpy( LoginServer, "default");

    FPrintfLog( 9, "Name: %s Password: %s Server: %s", LoginName, LoginPassword, LoginServer);

    if(( Account = UMSRLogin( LoginServer, LoginName, LoginPassword)) <= NULL)
    {
        Account = NULL;
        FPutsLog( 1,  "can`t login!");
        Close_All( FAIL);
    }

    if( ConfigString = ReadUMSConfigTags( Account,          UMSTAG_CfgGlobalOnly, TRUE,
                                          UMSTAG_CfgName,   "groupfix.logfile",
                                          TAG_DONE))
    {
        if( !( LogHandle = Open( ConfigString, MODE_READWRITE)))
        {
            FPrintfLog( 3, "can`t open logfile: %s!", ConfigString);
        }
        else Seek( LogHandle, 0, OFFSET_END);

        FreeUMSConfig( Account, ConfigString);
        ConfigString = 0;
    }

    if( ConfigString = ReadUMSConfigTags( Account,          UMSTAG_CfgGlobalOnly, TRUE,
                                          UMSTAG_CfgName,   "groupfix.loglevel",
                                          TAG_DONE))
    {
        LogLevel = atol( ConfigString);

        FreeUMSConfig( Account, ConfigString);
        ConfigString = 0;
    }

    if( ConfigString = ReadUMSConfigTags( Account,          UMSTAG_CfgGlobalOnly, TRUE,
                                          UMSTAG_CfgName,   "groupfix.reportlevel",
                                          TAG_DONE))
    {
        ReportLevel = atol( ConfigString);

        FreeUMSConfig( Account, ConfigString);
        ConfigString = 0;
    }

    FPutsLog( 6,  "UMSFix start.");
} //-
//+Close_All( int ExitError)
Close_All( int ExitError)
{
    FPutsLog( 6,  "UMSFix end.");

    ClearGroupList( MBGroupList);
    ClearGroupList( LinkGroupList);
    ClearGroupList( AllLinksGroupList);
    ClearGroupList( SubscribeGroupList);

    if( LinkNetName)        FreeUMSConfig( Account, LinkNetName);
    if( LinkPassword)       FreeUMSConfig( Account, LinkPassword);

    if( RD_Struct)          FreeArgs( RD_Struct);

    if( Account)            UMSLogout( Account);

    if( LogHandle)          Close( LogHandle);

    if( UMSBase)            CloseLibrary( UMSBase);

    exit( ExitError);
} //-

//+MaintainOrders()
MaintainOrders()
{
    long    Count;
    long    AddrPartCount;

    char    *StartPointer;
    char    *EndPointer;
    char    *TempPointer;
    char    *Part2Pointer;

//+ select new mails to <LoginName>

    /* Clear flags 0, 1, 2 in the Msgbase */
    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          0,
                            UMSTAG_SelUnset,        ( 1L<<0) | ( 1L<<1) | ( 1L<<2),
                            TAG_DONE);

    UMSSelectTags( Account, UMSTAG_SelMask,  UMSUSTATF_ViewAccess |
                                             UMSUSTATF_PostPoned |
                                             UMSUSTATF_Old,
                            UMSTAG_SelMatch, UMSUSTATF_ViewAccess,

                            UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          ( 1L<<0),
                            UMSTAG_SelUnset,        0,
                            TAG_DONE);

    UMSSelectTags( Account, UMSTAG_WToName,         LoginName,
                            UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          ( 1L<<1),
                            UMSTAG_SelUnset,        0,
                            UMSTAG_SelQuick,        TRUE,
                            TAG_DONE);

    FPrintfLog( 8, "found %d mails to %s.",
    UMSSelectTags( Account, UMSTAG_SelReadLocal,    TRUE,
                            UMSTAG_SelMask,         ( 1L<<0) | ( 1L<<1),
                            UMSTAG_SelMatch,        ( 1L<<0) | ( 1L<<1),

                            UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          ( 1L<<2),
                            UMSTAG_SelUnset,        0,
                            UMSTAG_SelQuick,        TRUE,
                            TAG_DONE),
     LoginName);
//-
//+ msgsearchloop
    do
    {
//+       get new msg
        if( MsgNumber = UMSSearchTags( Account, UMSTAG_SearchLocal, TRUE,
                                                UMSTAG_SearchLast,  MsgNumber,
                                                UMSTAG_SearchMask,  ( 1L<<2),
                                                UMSTAG_SearchMatch, ( 1L<<2),
                                                TAG_DONE))
        {
            if( ReadUMSMsgTags( Account, UMSTAG_RMsgNum,     MsgNumber,
                                         UMSTAG_RFromName,   &MsgFrom,
                                         UMSTAG_RFromAddr,   &MsgFromAddr,
                                         UMSTAG_RSubject,    &MsgSubject,
                                         UMSTAG_RMsgText,    &MsgText,
                                         UMSTAG_RTextLength, &MsgSize,
                                         UMSTAG_RMsgID,      &MsgID,
                                         UMSTAG_RGroup,      &MsgGroup,
                                         TAG_DONE))
            {
                if( !( *MsgGroup))
                {
                    LogSpace();
//-
//+                   get linkdata
                    if( MsgFromAddr)
                    {
                        Count = 0x05;

                        AddrPartCount = 0x00;
                        TempPointer = MsgFromAddr;

                        strcpy( LinkName, "fido.");

                        while( *TempPointer && *TempPointer != '@')
                        {
                            if( isdigit( *TempPointer))
                            {
                                LinkName[ Count++ ] = *TempPointer++;
                            }
                            else
                            {
                                LinkName[ Count++ ] = '.';
                                TempPointer++;
                                AddrPartCount++;
                            }
                        }

                        if( AddrPartCount == 0x02)
                        {
                            LinkName[ Count++ ] = '.';
                            LinkName[ Count++ ] = '0';
                        }

                        LinkName[ Count] = 0x00;
                    }
                    else
                    {
                        strncpy( LinkName, MsgFrom, STRING_LENGTH);
                    }

                    LinkNetName = ReadUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                              UMSTAG_CfgName, "fido.netname",
                                                              TAG_DONE);

                    LinkPassword = ReadUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                               UMSTAG_CfgName, "PASSWORD",
                                                               TAG_DONE);

                    if( *MsgFromAddr)   FPrintfLog( 5, "%s <%s>.", MsgFrom, MsgFromAddr);
                    else                FPrintfLog( 5, "%s <local user>.", MsgFrom);

                    if( LinkNetName) FPutsLog( 8,  LinkNetName);
//-
//+                   check msg for orders
                    List    = FALSE;
                    Query   = FALSE;
                    Help    = FALSE;

                    if( GetLinkGroupList())
                    {
                        EndPointer = MsgText;

                        while( StartPointer = ( char *) FindNextChar( EndPointer))
                        {
                            if( EndPointer = ( char *) FindNextLine( StartPointer))
                            {
                                if(( TempPointer = ( char *) FindNextSpace( StartPointer)) >= EndPointer) TempPointer = EndPointer;
                                else *TempPointer = 0x00;

                                *EndPointer     = 0x00;
                                *FullGroupName  = 0x00;

                                switch( *StartPointer++)
                                {
                                    case '%' :
                                    {
                                        if( !( StrCmpNoCase( StartPointer, "LIST"))) List = TRUE;
                                        else {
                                        if( !( StrCmpNoCase( StartPointer, "AVAIL"))) List = TRUE;
                                        else {
                                        if( !( StrCmpNoCase( StartPointer, "HELP"))) Help = TRUE;
                                        else {
                                        if( !( StrCmpNoCase( StartPointer, "QUERY"))) Query = TRUE;
                                        else {
                                        if( TempPointer != EndPointer)
                                        {
                                            Part2Pointer = TempPointer + 1;

                                            if(( TempPointer = ( char *) FindNextSpace( Part2Pointer)) >= EndPointer) TempPointer = EndPointer;
                                            else *TempPointer = 0x00;

                                            if( !( StrCmpNoCase( StartPointer, "EXTRANETMAIL")))
                                            {
                                                if( !( StrCmpNoCase( Part2Pointer, "ON")))  SetExtraNetmail( TRUE);
                                                else
                                                if( !( StrCmpNoCase( Part2Pointer, "OFF"))) SetExtraNetmail( FALSE);
                                                else
                                                    FPrintfLog( 4, "Unknown EXTRANETMAIL command: %s.", Part2Pointer);
                                            }
                                            else if( !( StrCmpNoCase( StartPointer, "COMPRESSOR"))) SetArcCMD( Part2Pointer);
                                            else if( !( StrCmpNoCase( StartPointer, "RESCAN")))
                                            {
//+                                               RescanGroup
                                                if( LinkNetName)
                                                {
                                                    strncpy( FullGroupName, LinkNetName, STRING_LENGTH);
                                                    strcat( FullGroupName, ".");
                                                }
                                                strncat( FullGroupName, Part2Pointer, STRING_LENGTH - strlen( FullGroupName));

                                                UMSSelectTags( Account,
                                                               UMSTAG_SelWriteUser,   LinkName,
                                                               UMSTAG_SelUnset,       UMSUSTATF_Old,
                                                               UMSTAG_SelSet,         0,
                                                               UMSTAG_WGroup,         FullGroupName,
                                                               TAG_DONE);

                                                FPrintfLog( 6, "Rescanned: %s.", FullGroupName);
//-
                                            }
                                            else FPrintfLog( 4, "Unknown %% command: %s.", StartPointer);
                                        }
                                        else FPrintfLog( 4, "Unknown %% command: ",  StartPointer);
                                        }}}}
                                    }
                                    break;

                                    case '-' :
                                    {
//+                                       RemoveLinkGroup

                                        if( LinkNetName)
                                        {
                                            strncpy( FullGroupName, LinkNetName, STRING_LENGTH);
                                            strcat( FullGroupName, ".");
                                        }
                                        strncat( FullGroupName, StartPointer, STRING_LENGTH - strlen( FullGroupName));

                                        if( RemoveGroup( FullGroupName, LinkGroupList))
                                        {
                                            FPrintfLog( 6,  "removed: %s.",  FullGroupName);
                                        }
//-
                                    }
                                    break;

                                    default :
                                    {
//+                                       AddLinkGroup
                                        if(( *( StartPointer - 1)) != '+') StartPointer--;

                                        if( LinkNetName)
                                        {
                                            strncpy( FullGroupName, LinkNetName, STRING_LENGTH);
                                            strcat( FullGroupName, ".");
                                        }
                                        strncat( FullGroupName, StartPointer, STRING_LENGTH - strlen( FullGroupName));

                                        if( AddGroup( FullGroupName, LinkGroupList))
                                        {
                                            UMSSelectTags( Account,
                                                           UMSTAG_SelWriteUser,   LinkName,
                                                           UMSTAG_SelSet,         UMSUSTATF_Old,
                                                           UMSTAG_SelUnset,       0,
                                                           UMSTAG_WGroup,         FullGroupName,
                                                           TAG_DONE);


                                            FPrintfLog( 6, "added: %s.",  FullGroupName);
                                        }
//-
                                    }
                                    break;
                                }

                                *EndPointer = 0x20;
                            }
                        }
                        PutLinkGroupList();
                    }

                    if( Help)   SendHelp();
                    if( List)   SendList();
                    if( Query)  SendQuery();
//-
//+                   free resources
                    if( LinkNetName)
                    {
                        FreeUMSConfig( Account, LinkNetName);
                        LinkNetName = NULL;
                    }

                    if( LinkPassword)
                    {
                        FreeUMSConfig( Account, LinkPassword);
                        LinkPassword = NULL;
                    }

                    ClearGroupList( LinkGroupList);
                    LinkGroupList = NULL;
                    FreeUMSMsg( Account, MsgNumber);
                }
            }
        }
//-
    }
    while( MsgNumber);
//-
}
//-
//+ MaintainGroups()
MaintainGroups()
{
    char    *StartPointer;
    char    *EndPointer;
    char    *ConfigString;
    char    *Password;
    char    *RemoteAddress;
    char    *RemoteName;
    char    *RemoteCfgString;
    char    *SubscribeVar;
    char    *SubscribeCfgString;

    struct  Node    *ThisNode;
    struct  Node    *NextNode;

    long    NumNodes        = 0;
    long    ForwardDelay    = 5;

    BOOL    NewGroups;
    BOOL    AutoExpire  = FALSE;
    BOOL    NoForward   = FALSE;
    BOOL    NoSubscribe = FALSE;

    GetMBGroupList();
    GetForwardGroupList();
    GetAllLinksGroupList();

    if( AllLinksGroupList && MBGroupList)
    {
        if( SubscribeGroupList = AllocVec( sizeof( struct List), MEMF_CLEAR))
        {
            NewList( SubscribeGroupList);

            if( ConfigString = ReadUMSConfigTags( Account,
                                                  UMSTAG_CfgGlobalOnly, TRUE,
                                                  UMSTAG_CfgName, "groupfix.forwarddelay",
                                                  TAG_DONE))
            {
                ForwardDelay = atol( ConfigString);

                FreeUMSConfig( Account, ConfigString);
                ConfigString = 0;
            }

//+           find groups to subscribe
            ThisNode = ( struct Node *) ( AllLinksGroupList->lh_Head);

            while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
            {
                if( !( FindNameNoCase(( struct List *) MBGroupList, ThisNode->ln_Name)))
                {
                    FullGroupName[ 0 ] = '+';
                    strncpy( FullGroupName + 1, ThisNode->ln_Name, STRING_LENGTH - 1);

                    if( AddForwardGroup( FullGroupName, ForwardDelay, ForwardGroupList))
                        AddGroup( FullGroupName, SubscribeGroupList);
                }

                ThisNode = NextNode;
            }
//-
//+           find groups to desubscribe
            ThisNode = ( struct Node *) ( MBGroupList->lh_Head);

            while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
            {
                if( !( FindNameNoCase(( struct List *) AllLinksGroupList, ThisNode->ln_Name)))
                {
                    FullGroupName[ 0 ] = '-';
                    strncpy( FullGroupName + 1, ThisNode->ln_Name, STRING_LENGTH - 1);

                    if( AddForwardGroup( FullGroupName, ForwardDelay, ForwardGroupList))
                        AddGroup( FullGroupName, SubscribeGroupList);
                }

                ThisNode = NextNode;
            }
//-

//+           sort groups for uplinks and order them
            FPutsLog( 5,  "de-/subscribing new groups.");

            ThisNode = ( struct Node *) ( SubscribeGroupList->lh_Head);

            while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
            {
                ThisNode = NextNode;
                NumNodes++;
            }

            if( NumNodes)
            {
                if( TempBuffer = ( long *) AllocVec( NumNodes * STRING_LENGTH, MEMF_ANY|MEMF_CLEAR))
                {
                    if( ConfigString = ReadUMSConfigTags( Account,
                                                          UMSTAG_CfgGlobalOnly, TRUE,
                                                          UMSTAG_CfgName, "groupfix.remote",
                                                          TAG_DONE))
                    {
                        if( UMSMatchConfigTags( Account,
                                                UMSTAG_MatchGlobalOnly, TRUE,
                                                UMSTAG_MatchName,       "groupfix.autoexpire",
                                                UMSTAG_MatchString,     "yes",
                                                TAG_DONE))
                        {
                            FPutsLog( 8,  "  Autoexpire activated.");
                            AutoExpire = TRUE;
                        }

                        EndPointer = ConfigString;

                        while( StartPointer = ( char *) FindNextChar( EndPointer))
                        {
                            if( EndPointer = ( char *) FindNextSpace( StartPointer))
                            {
                                *EndPointer++ = 0x00;

                                FPrintfLog( 5, "  %s.", StartPointer);

//+                               filter groups & build msg
                                LinkNetName = ReadUMSConfigTags( Account,
                                                                 UMSTAG_CfgUser, StartPointer,
                                                                 UMSTAG_CfgName, "fido.netname",
                                                                 TAG_DONE);
                                NewGroups = FALSE;

                                if( UMSMatchConfigTags( Account,
                                                        UMSTAG_MatchUser,       StartPointer,
                                                        UMSTAG_MatchName,       "groupfix.noforward",
                                                        UMSTAG_MatchString,     "yes",
                                                        TAG_DONE))
                                {
                                    FPutsLog( 8,  "  Forwarding off.");
                                    NoForward = TRUE;
                                }
                                else NoForward = FALSE;

                                if( UMSMatchConfigTags( Account,
                                                        UMSTAG_MatchUser,       StartPointer,
                                                        UMSTAG_MatchName,       "groupfix.nosubscribe",
                                                        UMSTAG_MatchString,     "yes",
                                                        TAG_DONE))
                                {
                                    FPutsLog( 8,  "  Subscribe off.");
                                    NoSubscribe = TRUE;
                                }
                                else NoSubscribe = FALSE;

                                *TempBuffer = 0x00;
                                ThisNode = ( struct Node *) ( SubscribeGroupList->lh_Head);

                                while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
                                {
                                    if( UMSMatchConfigTags( Account,
                                                            UMSTAG_MatchUser, StartPointer,
                                                            UMSTAG_MatchName, "READACCESS",
                                                            UMSTAG_MatchString, ThisNode->ln_Name + 1,
                                                            TAG_DONE))
                                    {
                                        if( !( NoSubscribe))
                                        {
                                            FPrintfLog( 6, "    %s.", ThisNode->ln_Name);

                                            NewGroups = TRUE;

                                            strncat( TempBuffer, ThisNode->ln_Name, 1);

                                            if( LinkNetName) strcat( TempBuffer, StrCmpNoCase( ThisNode->ln_Name + 1, LinkNetName) + 1);
                                            else strcat( TempBuffer, ThisNode->ln_Name + 1);

                                            strcat( TempBuffer, "\n");
                                        }

                                        if(( *( ThisNode->ln_Name) == '-') && AutoExpire)
                                        UMSSelectTags( Account,
                                                       UMSTAG_SelWriteGlobal, TRUE,
                                                       UMSTAG_SelSet,         UMSGSTATF_Expired,
                                                       UMSTAG_SelUnset,       0,
                                                       UMSTAG_WGroup,         ThisNode->ln_Name + 1,
                                                       TAG_DONE);

                                        RemoveGroup( ThisNode->ln_Name, SubscribeGroupList);
                                        if( NoForward) RemoveGroup( ThisNode->ln_Name, ForwardGroupList);
                                    }

                                    ThisNode = NextNode;
                                }

                                if( LinkNetName)    FreeUMSConfig( Account, LinkNetName);
//-
//+                               send mail to other areafix
                                if( NewGroups)
                                {
                                    if( RemoteAddress = ReadUMSConfigTags( Account,
                                                                           UMSTAG_CfgUser, StartPointer,
                                                                           UMSTAG_CfgName, "fido.remoteaddress",
                                                                           TAG_DONE))
                                    {
                                        if( Password = ReadUMSConfigTags( Account,
                                                                          UMSTAG_CfgUser, StartPointer,
                                                                          UMSTAG_CfgName, "groupfix.password",
                                                                          TAG_DONE))
                                        {
                                            if( RemoteCfgString = ReadUMSConfigTags( Account,
                                                                                     UMSTAG_CfgUser, StartPointer,
                                                                                     UMSTAG_CfgName, "groupfix.groupfixname",
                                                                                     TAG_DONE))
                                            {
                                                RemoteName = RemoteCfgString;
                                            }
                                            else RemoteName = DefaultRemoteName;

                                            if( WriteUMSMsgTags( Account,
                                                                 UMSTAG_WFromName, "Sysop",
                                                                 UMSTAG_WToName,   RemoteName,
                                                                 UMSTAG_WToAddr,   RemoteAddress,
                                                                 UMSTAG_WSubject,  Password,
                                                                 UMSTAG_WMsgText,  TempBuffer,
                                                                 TAG_DONE))
                                            {
                                                FPutsLog( 7,  "  succeed.");
                                            }
                                            else FPutsLog( 3,  "  failed writing msg.");

                                            if( RemoteCfgString) FreeUMSConfig( Account, RemoteCfgString);

                                            FreeUMSConfig( Account, Password);
                                        }
                                        else FPutsLog( 4,  "  can't read password.");

                                        FreeUMSConfig( Account, RemoteAddress);
                                    }
                                    else FPutsLog( 4,  "  can't read remoteaddress.");
                                }
                                else FPutsLog( 6,  "  no groups to subscribe.");
//-
                            }
                        }

                        FreeUMSConfig( Account, ConfigString);
                    }
                    FreeVec( TempBuffer);

                    ThisNode = ( struct Node *) ( SubscribeGroupList->lh_Head);

                    if(( struct Node *) ( ThisNode->ln_Succ))
                    {
                        FPutsLog( 6,  "  no remote found:");

                        while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
                        {
                            FPrintfLog( 6, "  %s.", ThisNode->ln_Name);
                            ThisNode = NextNode;
                        }
                    }
                }
                else FPutsLog( 2,  "  out of memory.");
            }
            else FPutsLog( 6,  "no groups to subscribe.");
//-
        }
        else FPutsLog( 2,  "out of memory.");

//+       set remote grouplists
        FPutsLog( 5,  "updating exporter-grouplists.");

        ThisNode = ( struct Node *) ( AllLinksGroupList->lh_Head);

        while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
        {
            ThisNode = NextNode;
            NumNodes++;
        }

        if( NumNodes)
        {
            if( TempBuffer = ( long *) AllocVec( NumNodes * STRING_LENGTH, MEMF_ANY|MEMF_CLEAR))
            {
                if( ConfigString = ReadUMSConfigTags( Account,
                                                      UMSTAG_CfgGlobalOnly, TRUE,
                                                      UMSTAG_CfgName, "groupfix.remote",
                                                      TAG_DONE))
                {
                    EndPointer = ConfigString;

                    while( StartPointer = ( char *) FindNextChar( EndPointer))
                    {
                        if( EndPointer = ( char *) FindNextSpace( StartPointer))
                        {
                            *EndPointer++ = 0x00;

                            FPrintfLog( 6, "  %s.", StartPointer);

                            *TempBuffer = 0x00;
                            ThisNode = ( struct Node *) ( AllLinksGroupList->lh_Head);

                            while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
                            {
                                if( UMSMatchConfigTags( Account,
                                                        UMSTAG_MatchUser, StartPointer,
                                                        UMSTAG_MatchName, "READACCESS",
                                                        UMSTAG_MatchString, ThisNode->ln_Name,
                                                        TAG_DONE))
                                {
                                    FPrintfLog( 7, "    %s.", ThisNode->ln_Name);

                                    strcat( TempBuffer, ThisNode->ln_Name);
                                    strcat( TempBuffer, "\n");

                                    RemoveGroup( ThisNode->ln_Name, AllLinksGroupList);
                                }

                                ThisNode = NextNode;
                            }

                            if( SubscribeCfgString = ReadUMSConfigTags( Account,
                                                                        UMSTAG_CfgUser, StartPointer,
                                                                        UMSTAG_CfgName, "groupfix.groupsvar",
                                                                        TAG_DONE))
                            {
                                SubscribeVar = SubscribeCfgString;
                            }
                            else
                            {
                                SubscribeVar = ExtSubscribeVar;
                            }

                            if( !( WriteUMSConfigTags( Account,
                                                       UMSTAG_CfgUser, StartPointer,
                                                       UMSTAG_CfgName, SubscribeVar,
                                                       UMSTAG_CfgData, TempBuffer,
                                                       TAG_DONE)))
                            {
                                FPutsLog( 2, "  failed writing config.");
                            }

                            if( SubscribeCfgString) FreeUMSConfig( Account, SubscribeCfgString);
                        }
                    }
                    FreeUMSConfig( Account, ConfigString);
                }
                FreeVec( TempBuffer);

                ThisNode = ( struct Node *) ( AllLinksGroupList->lh_Head);

                if(( struct Node *) ( ThisNode->ln_Succ))
                {
                    FPutsLog( 6, "  no matching exporter found:");

                    while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
                    {
                        FPrintfLog( 6, "    %s.", ThisNode->ln_Name);
                        ThisNode = NextNode;
                    }
                }
            }
        }
        else FPutsLog( 5,  "no groups linked.");
//-
    }

    PutForwardGroupList();
}
//-

//+ Result = GetLinkGroupList()
GetLinkGroupList()
{
    char    *StartPointer;
    char    *EndPointer;

    char    *SubscribeCfgString;
    char    *SubscribeVar;

    BOOL    Result = TRUE;

    if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                   UMSTAG_CfgName, "groupfix.password",
                                                   TAG_DONE))
    {
        if( !( StrCmpNoCase( ConfigString, MsgSubject)))
        {
            FreeUMSConfig( Account, ConfigString);

            if( SubscribeCfgString = ReadUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                                     UMSTAG_CfgName, "groupfix.groupsvar",
                                                                     TAG_DONE))
            {
                SubscribeVar = SubscribeCfgString;
            }
            else
            {
                if( MsgFromAddr)    SubscribeVar = ExtSubscribeVar;
                else                SubscribeVar = LocalSubscribeVar;
            }

            if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                           UMSTAG_CfgName, SubscribeVar,
                                                           TAG_DONE))
            {
                if( LinkGroupList = AllocVec( sizeof( struct List), MEMF_CLEAR))
                {
                    NewList( LinkGroupList);

                    EndPointer = ConfigString;

                    while( StartPointer = ( char *) FindNextChar( EndPointer))
                    {
                        if( EndPointer = ( char *) FindNextSpace( StartPointer))
                        {
                            *EndPointer++ = 0x00;

                            AddGroup( StartPointer, LinkGroupList);
                        }
                    }
                }
                FreeUMSConfig( Account, ConfigString);
            }
            else
            {
                SendNoAccess();
                Result = FALSE;
            }

            if( SubscribeCfgString) FreeUMSConfig( Account, SubscribeCfgString);
        }
        else
        {
            FreeUMSConfig( Account, ConfigString);
            SendPWFailure();
            Result = FALSE;
        }
    }
    else
    {
        SendPWFailure();
        Result = FALSE;
    }

    return( Result);
}
//-
//+ GetAllLinksGroupList()
GetAllLinksGroupList()
{
    char    *GlobalConfigString;
    char    *GlobalStartPointer;
    char    *GlobalEndPointer;
    char    *LinkConfigString;
    char    *LinkStartPointer;
    char    *LinkEndPointer;

    char    *SubscribeVar;
    char    *SubscribeCfgString;
    char    *NetName;

    long    NetNameLen;

    if( GlobalConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgGlobalOnly, TRUE,
                                                         UMSTAG_CfgName,       "groupfix.users",
                                                         TAG_DONE))
    {
        if( AllLinksGroupList = AllocVec( sizeof( struct List), MEMF_CLEAR))
        {
            NewList( AllLinksGroupList);

            GlobalEndPointer = GlobalConfigString;

            while( GlobalStartPointer = ( char *) FindNextChar( GlobalEndPointer))
            {
                if( GlobalEndPointer = ( char *) FindNextSpace( GlobalStartPointer))
                {
                    *GlobalEndPointer++ = 0x00;

                    if( SubscribeCfgString = ReadUMSConfigTags( Account, UMSTAG_CfgUser, GlobalStartPointer,
                                                                         UMSTAG_CfgName, "groupfix.groupsvar",
                                                                         TAG_DONE))
                    {
                        SubscribeVar = SubscribeCfgString;
                    }
                    else
                    {
                        SubscribeVar = ExtSubscribeVar;
                    }

                    NetName = NULL;

                    if( UMSMatchConfigTags( Account,
                                            UMSTAG_MatchUser,       GlobalStartPointer,
                                            UMSTAG_MatchName,       "groupfix.stripnetname",
                                            UMSTAG_MatchString,     "yes",
                                            TAG_DONE))
                    {
                        if( NetName = ReadUMSConfigTags( Account, UMSTAG_CfgUser, GlobalStartPointer,
                                                                  UMSTAG_CfgName, "fido.netname",
                                                                  TAG_DONE))
                        {
                            NetNameLen = strlen( NetName);
                        }
                    }

                    if( LinkConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgUser, GlobalStartPointer,
                                                                       UMSTAG_CfgName, SubscribeVar,
                                                                       TAG_DONE))
                    {
                        LinkEndPointer = LinkConfigString;

                        while( LinkStartPointer = ( char *) FindNextChar( LinkEndPointer))
                        {
                            if( LinkEndPointer = ( char *) FindNextSpace( LinkStartPointer))
                            {
                                *LinkEndPointer++ = 0x00;

                                if( NetName) if( !( strnicmp( LinkStartPointer, NetName, NetNameLen))) LinkStartPointer += NetNameLen + 1;

                                AddGroup( LinkStartPointer, AllLinksGroupList);
                            }
                        }
                        FreeUMSConfig( Account, LinkConfigString);
                    }

                    if( NetName)            FreeUMSConfig( Account, NetName);
                    if( SubscribeCfgString) FreeUMSConfig( Account, SubscribeCfgString);
                }
            }
        }
        else FPutsLog( 2,  "out of memory.");

        FreeUMSConfig( Account, GlobalConfigString);
    }
    else FPutsLog( 5,  "no users - no work.");
}
//-
//+ GetMBGroupList()
GetMBGroupList()
{
    if( MBGroupList = AllocVec( sizeof( struct List), MEMF_CLEAR))
    {
        NewList( MBGroupList);

        UMSSelectTags( Account, UMSTAG_SelWriteLocal, TRUE,
                                UMSTAG_SelSet,        ( 1L<<0),
                                UMSTAG_SelUnset,      0,
                                TAG_DONE);

        while( MsgNumber = UMSSearchTags( Account, UMSTAG_SearchLocal, TRUE,
                                                   UMSTAG_SearchLast,  MsgNumber,
                                                   UMSTAG_SearchMask,  ( 1L<<0),
                                                   UMSTAG_SearchMatch, ( 1L<<0),
                                                   TAG_DONE))
        {
            if( ReadUMSMsgTags( Account, UMSTAG_RMsgNum,    MsgNumber,
                                         UMSTAG_RGroup,     &MsgGroup,
                                         TAG_DONE))
            {
                UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                        UMSTAG_SelQuick,        TRUE,
                                        UMSTAG_SelSet,          0,
                                        UMSTAG_SelUnset,        ( 1L<<0),
                                        UMSTAG_WGroup,          MsgGroup,
                                        TAG_DONE);

                AddGroup( MsgGroup, MBGroupList);

                FreeUMSMsg( Account, MsgNumber);
            }
        }
    }
}
//-
//+ GetForwardGroupList()
GetForwardGroupList()
{
    char    *StartPointer;
    char    *StringPointer;
    char    *EndPointer;

    long    Count;

    if( ForwardGroupList = AllocVec( sizeof( struct List), MEMF_CLEAR))
    {
        NewList( ForwardGroupList);

        if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgGlobalOnly, TRUE,
                                                       UMSTAG_CfgName,       "groupfix.forward",
                                                       TAG_DONE))
        {
            EndPointer = ConfigString;

            while( StartPointer = ( char *) FindNextChar( EndPointer))
            {
                if( EndPointer = ( char *) FindNextKomma( StartPointer))
                {
                    *EndPointer++ = 0x00;

                    StringPointer = StartPointer;

                    StartPointer = ( char *) FindNextChar( EndPointer);

                    if( EndPointer = ( char *) FindNextSpace( StartPointer))
                    {
                        *EndPointer++ = 0x00;

                        if(( Count = atol( StartPointer) - 1) > 0) AddForwardGroup( StringPointer, Count, ForwardGroupList);
                    }
                }
            }
            FreeUMSConfig( Account, ConfigString);
        }
    }
    else
    {
        FPuts( StdOutputHandle, "not enough memory.\n");
        Close_All( FAIL);
    }
}
//-

//+ PutLinkGroupList()
PutLinkGroupList()
{
    struct  Node    *ThisNode;
    struct  Node    *NextNode;

    long    NumNodes    = 1;

    char    *SubscribeCfgString;
    char    *SubscribeVar;

    if( LinkGroupList)
    {
        ThisNode = ( struct Node *) ( LinkGroupList->lh_Head);

        while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
        {
            ThisNode = NextNode;
            NumNodes++;
        }

        if( TempBuffer = ( long *) AllocVec( NumNodes * STRING_LENGTH, MEMF_ANY|MEMF_CLEAR))
        {
            ThisNode = ( struct Node *) ( LinkGroupList->lh_Head);

            while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
            {
                strcat( TempBuffer, ThisNode->ln_Name);
                strcat( TempBuffer, "\n");
                ThisNode = NextNode;
            }

            if( SubscribeCfgString = ReadUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                                 UMSTAG_CfgName, "groupfix.groupsvar",
                                                                 TAG_DONE))
            {
                SubscribeVar = SubscribeCfgString;
            }
            else
            {
                if( MsgFromAddr)    SubscribeVar = ExtSubscribeVar;
                else                SubscribeVar = LocalSubscribeVar;
            }

            if( !( WriteUMSConfigTags( Account, UMSTAG_CfgUser, LinkName,
                                                UMSTAG_CfgName, SubscribeVar,
                                                UMSTAG_CfgData, TempBuffer,
                                                TAG_DONE)))
            {
                FPutsLog( 2, "failed writing config.");
            }

            if( SubscribeCfgString) FreeUMSConfig( Account, SubscribeCfgString);
        }
        FreeVec( TempBuffer);
    }
}
//-
//+ PutForwardGroupList()
PutForwardGroupList()
{
    struct  ForwardGroupNode    *ThisNode;
    struct  ForwardGroupNode    *NextNode;

    long    NumNodes    = 1;
    long    BufferCount = 0x00;

    if( ForwardGroupList)
    {
        ThisNode = ( struct ForwardGroupNode *) ( ForwardGroupList->lh_Head);

        while( NextNode = ( struct ForwardGroupNode *) ( ThisNode->fn_Node.ln_Succ))
        {
            ThisNode = NextNode;
            NumNodes++;
        }

        if( TempBuffer = ( long *) AllocVec( NumNodes * STRING_LENGTH, MEMF_ANY|MEMF_CLEAR))
        {
            ThisNode = ( struct ForwardGroupNode *) ( ForwardGroupList->lh_Head);

            while( NextNode = ( struct ForwardGroupNode *) ( ThisNode->fn_Node.ln_Succ))
            {
                BufferCount = BufferCount + sprintf( &TempBuffer[ BufferCount ], "%s, %d\n", ThisNode->fn_Node.ln_Name, ThisNode->fn_Count);

                ThisNode = NextNode;
            }

            if( !( WriteUMSConfigTags( Account, UMSTAG_CfgGlobalOnly, TRUE,
                                                UMSTAG_CfgName,       "groupfix.forward",
                                                UMSTAG_CfgData,       TempBuffer,
                                                TAG_DONE)))
            {
                FPutsLog( 2,  "failed writing config.");
            }
        }
        FreeVec( TempBuffer);
    }
}
//-

//+ ClearGroupList( struct List *GroupList)
ClearGroupList( struct List *GroupList)
{
    struct  Node    *ThisNode;
    struct  Node    *NextNode;

    if( GroupList)
    {
        ThisNode = ( struct Node *) ( GroupList->lh_Head);

        while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
        {
            FreeVec( ThisNode);
            ThisNode = NextNode;
        }
        FreeVec( GroupList);
    }
}
//-

//+ BOOL AddGroup( char *GroupName, struct List *GroupList)
BOOL AddGroup( char *GroupName, struct List *GroupList)
{
    struct  GroupNode    *GroupNode;

    if( GroupList && GroupName)
    {
        if( !( FindNameNoCase((struct List *) GroupList, GroupName)))
        {
            if( GroupNode = AllocVec( sizeof( struct GroupNode), MEMF_ANY|MEMF_CLEAR))
            {
                strncpy( GroupNode->gn_Data, GroupName, STRING_LENGTH);
                GroupNode->gn_Node.ln_Name = GroupNode->gn_Data;
                GroupNode->gn_Node.ln_Type = GROUPNODE_ID;
                GroupNode->gn_Node.ln_Pri  = 0;

                AddTail(( struct List *) GroupList, ( struct Node *) GroupNode);

                return( TRUE);
            }
        }
    }
    return( FALSE);
}
//-
//+ BOOL AddForwardGroup( char *GroupName, long Count, struct List *GroupList)
BOOL AddForwardGroup( char *GroupName, long Count, struct List *GroupList)
{
    struct  ForwardGroupNode   *GroupNode;

    if( GroupList)
    {
        if( !( FindNameNoCase(( struct List *) GroupList, GroupName)))
        {
            if( GroupNode = AllocVec( sizeof( struct ForwardGroupNode), MEMF_ANY|MEMF_CLEAR))
            {
                strncpy( GroupNode->fn_Data, GroupName, STRING_LENGTH);
                GroupNode->fn_Count = Count;
                GroupNode->fn_Node.ln_Name = GroupNode->fn_Data;
                GroupNode->fn_Node.ln_Type = FORWARDGROUPNODE_ID;
                GroupNode->fn_Node.ln_Pri  = 0;

                AddTail(( struct List *) GroupList, ( struct Node *) GroupNode);

                return( TRUE);
            }
        }
    }
    return( FALSE);
}
//-

//+ BOOL RemoveGroup( char *GroupName, struct List *GroupList)
BOOL RemoveGroup( char *GroupName, struct List *GroupList)
{
    struct  Node    *GroupNode;

    if( GroupList)
    {
        if( GroupNode = FindNameNoCase(( struct List *) GroupList, GroupName))
        {
            Remove(( struct Node *) GroupNode);
            FreeVec( GroupNode);

            return( TRUE);
        }
    }

    return( FALSE);
}
//-

//+SendNoAccess()
SendNoAccess()
{
    FPutsLog( 5,  "    sending \"no access\"");

    SendFileCfgVar( "groupfix.noaccess", "No access.");
}
//-
//+SendPWFailure()
SendPWFailure()
{
    FPutsLog( 5,  "    sending \"password failure\"");

    SendFileCfgVar( "groupfix.pwfailure", "Password failure.");
}
//-
//+SendHelp()
SendHelp()
{
    FPutsLog( 6, "    sending helpfile");

    SendFileCfgVar( "groupfix.help", "Help to the Groupfix.");
}
//-
//+ SendList()
SendList()
{
    char    *FileCfgVar[ STRING_LENGTH ];

    FPutsLog( 6, "    sending list of available groups.");

    if( LinkNetName)
    {
        strcpy( FileCfgVar, "groupfix.groups.");
        strncat( FileCfgVar, LinkNetName, STRING_LENGTH - 16);
    }
    else
    {
        strcpy( FileCfgVar, "groupfix.groups.local");
    }

    SendFileCfgVar( FileCfgVar, "List of available groups.");
}
//-
//+ SendQuery()
SendQuery()
{
    struct  Node    *ThisNode;
    struct  Node    *NextNode;

    long    NumNodes = 1;

    FPutsLog( 6, "    sending list of active groups.");

    if( LinkGroupList)
    {
        ThisNode = ( struct Node *) ( LinkGroupList->lh_Head);

        while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
        {
            ThisNode = NextNode;
            NumNodes++;
        }

        if( TempBuffer = ( long *) AllocVec( NumNodes * STRING_LENGTH, MEMF_ANY|MEMF_CLEAR))
        {
            ThisNode = ( struct Node *) ( LinkGroupList->lh_Head);

            while( NextNode = ( struct Node *) ( ThisNode->ln_Succ))
            {
                strcat( TempBuffer, ThisNode->ln_Name);
                strcat( TempBuffer, "\n");
                ThisNode = NextNode;
            }

            if( WriteUMSMsgTags( Account,
                                 UMSTAG_WFromName, LoginName,
                                 UMSTAG_WToName,   MsgFrom,
                                 UMSTAG_WToAddr,   MsgFromAddr,
                                 UMSTAG_WSubject,  "List of connected groups.",
                                 UMSTAG_WMsgText,  TempBuffer,
                                 UMSTAG_WReferID,  MsgID,
                                 TAG_DONE))
            {
                FPutsLog( 7, "    succeed.");
            }
            else FPutsLog( 3, "    failed writing msg.");
        }
        else FPutsLog( 2, "    out of memory.");
        FreeVec( TempBuffer);
    }
    else FPutsLog( 7, "    no groups active.");
}
//-

//+ SetExtraNetmail( BOOL Option)
SetExtraNetmail( BOOL Option)
{
    if( MsgFromAddr)
    {
        if( Option)
        {
            FPutsLog( 6, "    Extranetmail: On");

            if( !( WriteUMSConfigTags( Account,
                                       UMSTAG_CfgUser, LinkName,
                                       UMSTAG_CfgName, "fido.arcmail",
                                       UMSTAG_CfgData, "yes",
                                       TAG_DONE)))
            {
                FPutsLog( 2, "    failed writing config.");
            }
        }
        else
        {
            FPutsLog( 6, "    Extranetmail: Off");

            if( !( WriteUMSConfigTags( Account,
                                       UMSTAG_CfgUser, LinkName,
                                       UMSTAG_CfgName, "fido.arcmail",
                                       UMSTAG_CfgData, "no",
                                       TAG_DONE)))
            {
                FPutsLog( 2, "    failed writing config.");
            }
        }
    }
}
//-
//+ SetArcCMD( char *Option)
SetArcCMD( char *Option)
{
    char    *ConfigString;
    char    ConfigVar[ STRING_LENGTH ] = "groupfix.arccmd.";

    if( MsgFromAddr)
    {
        if( *Option)
        {
            FPrintfLog( 6, "    Arctype: %s.", Option);

            strncat( ConfigVar, Option, STRING_LENGTH - sizeof( "groupfix.arccmd."));

            if( ConfigString = ReadUMSConfigTags( Account,
                                                  UMSTAG_CfgGlobalOnly, TRUE,
                                                  UMSTAG_CfgName, ConfigVar,
                                                  TAG_DONE))
            {
                if( !( WriteUMSConfigTags( Account,
                                           UMSTAG_CfgUser, LinkName,
                                           UMSTAG_CfgName, "fido.arccmd",
                                           UMSTAG_CfgData, ConfigString,
                                           TAG_DONE)))
                {
                    FPutsLog( 2,  "    failed writing config.");
                }

                FreeUMSConfig( Account, ConfigString);
            }
        }
    }
}
//-

//+ -Log-
//+ void FPutsLog( long Level, char *String)
FPutsLog( long Level, char *String)
{
    char *TimeString[ TIMESTRING_SIZE ];

    OTime = time( NULL);
    strftime( TimeString, TIMESTRING_SIZE, "%d-%b-%y %H:%M:%S  ", localtime( &OTime));

    if( Account > NULL) UMSVLog( Account, Level, String, NULL);

    if( Level <= LogLevel)
    {
        if( LogHandle)
        {
            FPuts( LogHandle, TimeString);
            FPuts( LogHandle, String);
            FPutC( LogHandle, 0x0a);
        }

        Flush( LogHandle);
    }

    if( Level <= ReportLevel)
    {
        FPuts( StdOutputHandle, TimeString);
        FPuts( StdOutputHandle, String);
        FPutC( StdOutputHandle, 0x0a);
    }
} //-
//+ void FPrintfLog( long Level, char *FString, ...)
void FPrintfLog( long Level, char *FString, ...)
{
    va_list Arguments;

    char    String[ 120 ];

    va_start( Arguments, FString);

    vsprintf( String, FString, Arguments);
    FPutsLog( Level, String);

    va_end( Arguments);
} //-

//+LogSpace()
LogSpace()
{
    if( LogHandle)
    {
        FPutC( LogHandle, 0x0a);
    }

    FPutC( StdOutputHandle, 0x0a);
}
//-
//-

//+SendFile( char *FileName, char *Subject)
SendFile( char *FileName, char *Subject)
{
    char    *TempBuffer = 0;
    BPTR    TempHandle  = 0;
    long    TempSize    = 0;

    if( FileName)
    {
        if( TempHandle = Open( FileName, MODE_OLDFILE))
        {
            Seek( TempHandle, 0, OFFSET_END);

            if( !( TempSize = Seek( TempHandle, 0, OFFSET_BEGINNING)))
                FPutsLog( 5, "warning: file is empty.");

            if( TempBuffer = ( long *) AllocVec( TempSize + 1, MEMF_ANY|MEMF_CLEAR))
            {
                if( TempSize != Read( TempHandle, TempBuffer, TempSize))
                    FPutsLog( 5, "warning: failed reading file.");
            }
            else FPutsLog( 5, "warning: failed allocating buffer.");
        }
        else FPutsLog( 5, "warning: failed opening file.");
    }
    else FPutsLog( 5, "warning: no file specified.");


    if( WriteUMSMsgTags( Account,
                         UMSTAG_WFromName, LoginName,
                         UMSTAG_WToName,   MsgFrom,
                         UMSTAG_WToAddr,   MsgFromAddr,
                         UMSTAG_WSubject,  Subject,
                         UMSTAG_WMsgText,  TempBuffer,
                         UMSTAG_WReferID,  MsgID,
                         TAG_DONE))
    {
        FPutsLog( 6,  "succeed.");
    }
    else FPutsLog( 4,  "failed writing msg.");

    if( TempBuffer) FreeVec( TempBuffer);
    if( TempHandle) Close( TempHandle);
}
//-

//+ SendFileCfgVar( char *FileNameCfgVar, char *Subject)
SendFileCfgVar( char *FileNameCfgVar, char *Subject)
{
    char    *ConfigString;

    ConfigString = ReadUMSConfigTags( Account,
                                      UMSTAG_CfgGlobalOnly, TRUE,
                                      UMSTAG_CfgName, FileNameCfgVar,
                                      TAG_DONE);

    SendFile( ConfigString, Subject);

    if( ConfigString) FreeUMSConfig( Account, ConfigString);
}
//-

//+ String = FindNextChar( const char *String)
FindNextChar( const char *String)
{
    if( String)
    {
        while( *String && isspace( *String)) String++;

        if( !( *String)) return( NULL);
    }
    return( String);
} //-
//+ String = FindNextSpace( const char *String)
FindNextSpace( const char *String)
{
    while( *String && ( !( isspace( *String)))) String++;

    if( !( *String)) return( NULL);
    
    return( String);
} //-
//+ String = FindNextLine( const char *String)
FindNextLine( const char *String)
{
    while( *String && *String != 0x0a && *String != 0x0d) String++;

    if( !( *String)) return( NULL);
    
    return( String);
} //-
//+ String = FindNextKomma( const char *String)
FindNextKomma( const char *String)
{
    while( *String && *String != ',') String++;

    if( !( *String)) return( NULL);
    
    return( String);
} //-

//+ char *Result = StrCmpNoCase( char *SrcString, char *DstString)
char *StrCmpNoCase( char *SrcString, char *DstString)
{
    while( tolower( *DstString) == tolower( *SrcString))
    {
        if( !( *SrcString)) return( FALSE);

        SrcString++;
        DstString++;
    }

    return( SrcString);
} //-
//+ struct Node *FindNameNoCase( struct List *List, char *String)
struct Node *FindNameNoCase( struct List *List, char *String)
{
    struct Node     *ThisNode;
    struct Node     *NextNode;

    if( ThisNode = List->lh_Head)
    {
        while( NextNode = ThisNode->ln_Succ)
        {
            if( !( StrCmpNoCase( ThisNode->ln_Name, String))) return( ThisNode);

            ThisNode = NextNode;
        }
    }

    return( FALSE);
}
//-
