/* UMSExpire - Expire 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       79
#define     TIMESTRING_SIZE     20

#define     GROUPNODE_ID        100
#define     EXPIREGROUPNODE_ID  101

#define     FAIL                20

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

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

struct  ExpireGroupNode
{
    struct Node en_Node;
    ULONG       en_Count;
    UBYTE       en_Data[ STRING_LENGTH + 1 ];
};
//-
//+ Consts
const   char    *Version        = "$VER: UMSExpire 0.1 (13.05.95)";
const   char    *LogName        = "Log:UMSExpire.log";

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

const   char    *LocalSubscribeVar = "IntuiNews.groups";

//-
//+ Variables

char    TimeString[ TIMESTRING_SIZE + 1 ];
char    LoginName[ STRING_LENGTH + 1 ];
char    LoginServer[ STRING_LENGTH + 1 ];
char    LoginPassword[ STRING_LENGTH + 1 ];

char    *ConfigString;
char    *NewsVar;
char    *GroupsVar;

time_t  OTime;

struct  Library     *UMSBase        = NULL;

struct  RDArgs      *RD_Struct      = NULL;

struct  List    *MBGroupList        = NULL;
struct  List    *UserList           = NULL;

struct DateStamp    DStamp;

long    RD_Array[ RD_Size ];
long    TempSize;
long    TempLong;
long    MsgNumber   = NULL;

UMSUserAccount  Account     = NULL;

BPTR    LogHandle           = NULL;
BPTR    StdOutputHandle;

char    *MsgGroup       = NULL;

char    NextUser[ STRING_LENGTH + 1 ];
char    LinkName[ STRING_LENGTH + 1 ];

struct  GroupNode   *ThisNode;
struct  GroupNode   *NextNode;
struct  ExpireGroupNode *ThisENode;
struct  ExpireGroupNode *NextENode;

long    SelectedMessages;
long    SelectedNews;

char    *StartPointer;
char    *EndPointer;

//-

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

    FPrintfLog( "Found %lu messages in your messagebase \x22%s\x22.",
    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          ( 1L<<7),
                            UMSTAG_SelUnset,        0,
                            TAG_DONE),
    LoginServer);

    FPrintfLog( "Keeping %lu archived messages.",
    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          0,
                            UMSTAG_SelUnset,        ( 1L<<7),
                            UMSTAG_SelMask,         UMSUSTATF_Archive,
                            UMSTAG_SelMatch,        UMSUSTATF_Archive,
                            TAG_DONE));

//+ expire mail
    LogSpace();
    FPrintfLog( "Checking mails:" );
    LogSpace();
//+ global
    if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgGlobalOnly,    TRUE,
                                                   UMSTAG_CfgName,          "expire.mail",
                                                   TAG_DONE))
    {
        UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                UMSTAG_SelSet,          0,
                                UMSTAG_SelUnset,        ( 1L<<1) | ( 1L<<2),
                                TAG_DONE);

        UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                UMSTAG_SelSet,          ( 1L<<1),
                                UMSTAG_SelUnset,        0,
                                UMSTAG_SelDate,         ( DStamp.ds_Days - atol( ConfigString) + 1) * 24 * 60 * 60,
                                TAG_DONE);

        TempLong =
        UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                UMSTAG_SelSet,          ( 1L<<2),
                                UMSTAG_SelUnset,        0,
                                UMSTAG_WGroup,          "",
                                TAG_DONE);

        FPrintfLog( "    Keeping %3lu of %3lu mails global, %lu days.",
        UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                UMSTAG_SelReadLocal,    TRUE,
                                UMSTAG_SelSet,          0,
                                UMSTAG_SelUnset,        ( 1L<<7),
                                UMSTAG_SelMask,         ( 1L<<1) | ( 1L<<2),
                                UMSTAG_SelMatch,        ( 1L<<1) | ( 1L<<2),
                                TAG_DONE),
        TempLong,
        atol( ConfigString));
        LogSpace();

        FreeUMSConfig( Account, ConfigString);
    }
    else
    {
        FPutsLog( "Missing expire.mail!");
        Close_All( FAIL);
    }
//-
//+ local
    if( UserList)
    {
        ThisNode = ( struct GroupNode *) ( UserList->lh_Head);

        while( NextNode = ( struct GroupNode *) ( ThisNode->gn_Node.ln_Succ))
        {
            chkabort();

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

            UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                    UMSTAG_SelReadGlobal,   TRUE,
                                    UMSTAG_SelSet,          ( 1L<<3),
                                    UMSTAG_SelUnset,        0,
                                    UMSTAG_WGroup,          "",
                                    TAG_DONE);


            if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgUser,  ThisNode->gn_Node.ln_Name,
                                                           UMSTAG_CfgName,  "expire.mail",
                                                           TAG_DONE))
            {
                UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                        UMSTAG_SelSet,          0,
                                        UMSTAG_SelUnset,        ( 1L<<1) | (1L<<2),
                                        TAG_DONE);

                UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                        UMSTAG_SelReadUser,     ThisNode->gn_Node.ln_Name,
                                        UMSTAG_SelSet,          ( 1L<<1),
                                        UMSTAG_SelUnset,        0,
                                        UMSTAG_SelMask,         UMSUSTATF_ViewAccess |
                                                                UMSUSTATF_ReadAccess,
                                        UMSTAG_SelMatch,        UMSUSTATF_ViewAccess |
                                                                UMSUSTATF_ReadAccess,
                                        TAG_DONE);

                UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                        UMSTAG_SelReadGlobal,   TRUE,
                                        UMSTAG_SelSet,          ( 1L<<2),
                                        UMSTAG_SelUnset,        0,
                                        UMSTAG_SelDate,         ( DStamp.ds_Days - atol( ConfigString) + 1) * 24 * 60 * 60,
                                        TAG_DONE);

                FPrintfLog( "    Keeping %4lu of %4lu mails from user \x22%s\x22, %lu days.",
                UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                        UMSTAG_SelReadLocal,    TRUE,
                                        UMSTAG_SelSet,          0,
                                        UMSTAG_SelUnset,        ( 1L<<7),
                                        UMSTAG_SelMask,         ( 1L<<1) | ( 1L<<2) | ( 1L<<3),
                                        UMSTAG_SelMatch,        ( 1L<<1) | ( 1L<<2) | ( 1L<<3),
                                        TAG_DONE),
                UMSSelectTags( Account, UMSTAG_SelReadLocal,    TRUE,
                                        UMSTAG_SelSet,          0,
                                        UMSTAG_SelUnset,        0,
                                        UMSTAG_SelMask,         ( 1L<<1) | ( 1L<<3),
                                        UMSTAG_SelMatch,        ( 1L<<1) | ( 1L<<3),
                                        TAG_DONE),
                ThisNode->gn_Node.ln_Name,
                atol( ConfigString));

                FreeUMSConfig( Account, ConfigString);
            }

            ThisNode = NextNode;
        }
    }
//-
//-
//+ expire news
    LogSpace();
    FPrintfLog( "Checking news:" );
    LogSpace();
//+ global
    if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgGlobalOnly,    TRUE,
                                                   UMSTAG_CfgName,          "expire.news",
                                                   TAG_DONE))
    {
        FPrintfLog( "    Building global grouplist with %lu days.", atol( ConfigString));
        GetMBGroupList( atol( ConfigString));
        LogSpace();

        FreeUMSConfig( Account, ConfigString);
    }
    else
    {
        FPutsLog( "Missing expire.news!");
        Close_All( FAIL);
    }
//-
//+ local
    if( UserList)
    {
        ThisNode = ( struct GroupNode *) ( UserList->lh_Head);

        while( NextNode = ( struct GroupNode *) ( ThisNode->gn_Node.ln_Succ))
        {
            chkabort();

            if( NewsVar = ReadUMSConfigTags( Account, UMSTAG_CfgUser,  ThisNode->gn_Node.ln_Name,
                                                      UMSTAG_CfgName,  "expire.news",
                                                      TAG_DONE))
            {
                if( GroupsVar = ReadUMSConfigTags( Account, UMSTAG_CfgUser,  ThisNode->gn_Node.ln_Name,
                                                            UMSTAG_CfgName,  "groupfix.groupsvar",
                                                            TAG_DONE))
                {
                    if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgUser,  ThisNode->gn_Node.ln_Name,
                                                                   UMSTAG_CfgName,  GroupsVar,
                                                                   TAG_DONE))
                    {
                        FPrintfLog( "    Adding groups from user \x22%s\x22 to grouplist, %lu days.", ThisNode->gn_Node.ln_Name, atol( NewsVar));

                        EndPointer = ConfigString;

                        while( StartPointer = ( char *) FindNextChar( EndPointer))
                        {
                            chkabort();

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

//                                Str2Upper( StartPointer);

                                AddExpireGroup( StartPointer, MBGroupList, atol( NewsVar));
                            }
                        }
                        FreeUMSConfig( Account, ConfigString);
                    }
                    else NormalGroupsExpire( ThisNode->gn_Node.ln_Name, atol( NewsVar));

                    FreeUMSConfig( Account, GroupsVar);
                }
                else NormalGroupsExpire( ThisNode->gn_Node.ln_Name, atol( NewsVar));

                FreeUMSConfig( Account, NewsVar);
            }

            ThisNode = NextNode;
        }
    }
//-
//-
//+ grouplistexpire
    if( MBGroupList)
    {
        LogSpace();
        FPutsLog( "Checking grouplist:");
        LogSpace();

        ThisENode = ( struct ExpireGroupNode *) ( MBGroupList->lh_Head);

        while( NextENode = ( struct ExpireGroupNode *) ( ThisENode->en_Node.ln_Succ))
        {
            chkabort();

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

            TempLong =
            UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                    UMSTAG_SelSet,          ( 1L<<1),
                                    UMSTAG_SelUnset,        0,
                                    UMSTAG_WGroup,          ThisENode->en_Node.ln_Name,
                                    TAG_DONE);

            UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                    UMSTAG_SelSet,          ( 1L<<2),
                                    UMSTAG_SelUnset,        0,
                                    UMSTAG_SelDate,         ( DStamp.ds_Days - ThisENode->en_Count + 1) * 24 * 60 * 60,
                                    TAG_DONE);

            FPrintfLog( "    Keeping %6lu of %6lu news in area \x22%s\x22, %lu days. %lu news left.",
            UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                    UMSTAG_SelReadLocal,    TRUE,
                                    UMSTAG_SelSet,          0,
                                    UMSTAG_SelUnset,        ( 1L<<7),
                                    UMSTAG_SelMask,         ( 1L<<1) | ( 1L<<2),
                                    UMSTAG_SelMatch,        ( 1L<<1) | ( 1L<<2),
                                    TAG_DONE),
            TempLong,
            ThisENode->en_Node.ln_Name,
            ThisENode->en_Count,
            UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                    UMSTAG_SelReadLocal,    TRUE,
                                    UMSTAG_SelSet,          0,
                                    UMSTAG_SelUnset,        0,
                                    UMSTAG_SelMask,         ( 1L<<7),
                                    UMSTAG_SelMatch,        ( 1L<<7),
                                    TAG_DONE));

            ThisENode = NextENode;
        }
//-
//+ expire
        SelectedMessages =
        UMSSelectTags( Account, UMSTAG_SelWriteGlobal,  TRUE,
                                UMSTAG_SelReadLocal,    TRUE,
                                UMSTAG_SelSet,          UMSGSTATF_Expired,
                                UMSTAG_SelUnset,        0,
                                UMSTAG_SelMask,         ( 1L<<7),
                                UMSTAG_SelMatch,        ( 1L<<7),
                                TAG_DONE);

        UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                UMSTAG_SelReadLocal,    TRUE,
                                UMSTAG_SelSet,          0,
                                UMSTAG_SelUnset,        ( 1L<<7),
                                UMSTAG_WGroup,          "",
                                TAG_DONE);

        SelectedNews =
        UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                                UMSTAG_SelReadLocal,    TRUE,
                                UMSTAG_SelSet,          0,
                                UMSTAG_SelUnset,        0,
                                UMSTAG_SelMask,         ( 1L<<7),
                                UMSTAG_SelMatch,        ( 1L<<7),
                                TAG_DONE);

        LogSpace();
        FPrintfLog( "Expired %lu messages, %lu news, %lu mails.", SelectedMessages, SelectedNews, SelectedMessages - SelectedNews);
//-
    }
    else
    {
        FPutsLog( "No grouplist, can't expire!");
        Close_All( FAIL);
    }

    Close_All( NULL);
} //-

//+ C_Break()
C_Break()
{
    FPutsLog( "UserBreak!");

    Close_All( FAIL);
} //-
//+Open_All()
Open_All()
{
    onbreak( C_Break);

    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( !( LogHandle = Open( LogName, MODE_READWRITE)))
    {
        FPuts( StdOutputHandle, "can`t open logfile!\n");
        Close_All( FAIL);
    }

    if( !( DateStamp( &DStamp)))
    {
        Close_All( FAIL);
    }

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

    Seek( LogHandle, 0, OFFSET_END);

    FPutsLog( "Starting expire...");

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

    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");

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

    GetUserList();
} //-
//+Close_All( int ExitError)
Close_All( int ExitError)
{
    FPutsLog( "...finished.");
    LogSpace();

    ClearGroupList( MBGroupList);
    ClearGroupList( UserList);

    if( RD_Struct)          FreeArgs( RD_Struct);

    if( Account)            UMSLogout( Account);

    if( LogHandle)          Close( LogHandle);

    if( UMSBase)            CloseLibrary( UMSBase);

    exit( ExitError);
} //-

//+ NormalGroupsExpire( char *UserName, long Days)
NormalGroupsExpire( char *UserName, long Days)
{
    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          0,
                            UMSTAG_SelUnset,        ( 1L<<1) | ( 1L<<2),
                            TAG_DONE);

    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelReadUser,     UserName,
                            UMSTAG_SelSet,          ( 1L<<1),
                            UMSTAG_SelUnset,        0,
                            UMSTAG_SelMask,         UMSUSTATF_ViewAccess |
                                                    UMSUSTATF_ReadAccess,
                            UMSTAG_SelMatch,        UMSUSTATF_ViewAccess |
                                                    UMSUSTATF_ReadAccess,
                            TAG_DONE);

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

    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelSet,          ( 1L<<2),
                            UMSTAG_SelUnset,        0,
                            UMSTAG_SelDate,         ( DStamp.ds_Days - Days + 1) * 24 * 60 * 60,
                            TAG_DONE);

    FPrintfLog( "    Keeping %6lu of %6lu news from user \x22%s\x22, %lu days.",
    UMSSelectTags( Account, UMSTAG_SelWriteLocal,   TRUE,
                            UMSTAG_SelReadLocal,    TRUE,
                            UMSTAG_SelSet,          0,
                            UMSTAG_SelUnset,        ( 1L<<7),
                            UMSTAG_SelMask,         ( 1L<<1) | ( 1L<<2),
                            UMSTAG_SelMatch,        ( 1L<<1) | ( 1L<<2),
                            TAG_DONE),
    UMSSelectTags( Account, UMSTAG_SelReadLocal,    TRUE,
                            UMSTAG_SelSet,          0,
                            UMSTAG_SelUnset,        0,
                            UMSTAG_SelMask,         ( 1L<<1),
                            UMSTAG_SelMatch,        ( 1L<<1),
                            TAG_DONE),
    UserName,
    Days);
} //-

//+ GetMBGroupList( long Days)
GetMBGroupList( long Days)
{
    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);

                AddExpireGroup( MsgGroup, MBGroupList, Days);

                FreeUMSMsg( Account, MsgNumber);
            }
        }
    }
} //-
//+ GetUserList()
GetUserList()
{
    if( UserList = AllocVec( sizeof( struct List), MEMF_CLEAR))
    {
        NewList( UserList);

        do
        {
            if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgGlobalOnly, TRUE,
                                                           UMSTAG_CfgNextUser, NextUser,
                                                           TAG_DONE))
            {
                strncpy( NextUser, ConfigString, STRING_LENGTH);
                NextUser[ STRING_LENGTH ] = 0x00;
                AddGroup( NextUser, UserList);

                FreeUMSConfig( Account, ConfigString);
            }
        }
        while( ConfigString);

        NextUser[ 0 ] = 0x00;

        do
        {
            if( ConfigString = ReadUMSConfigTags( Account, UMSTAG_CfgGlobalOnly, TRUE,
                                                           UMSTAG_CfgNextExporter, NextUser,
                                                           TAG_DONE))
            {
                strncpy( NextUser, ConfigString, STRING_LENGTH);
                NextUser[ STRING_LENGTH ] = 0x00;
                RemoveGroup( NextUser, UserList);

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

//+ 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);
    }
} //-

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

//    Str2Upper( GroupName);

    if( GroupList && GroupName)
    {
        if( !( FindName(( struct List *) GroupList, GroupName)))
        {
            if( GroupNode = AllocVec( sizeof( struct GroupNode), MEMF_ANY|MEMF_CLEAR))
            {
                strncpy( GroupNode->gn_Data, GroupName, STRING_LENGTH);
                GroupNode->gn_Data[ STRING_LENGTH ] = 0x00;
                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);
            }
        }
    }
} //-
//+ AddExpireGroup( char *GroupName, struct List *GroupList, long Count)
AddExpireGroup( char *GroupName, struct List *GroupList, long Count)
{
    struct  ExpireGroupNode   *GroupNode;

    if( GroupName)
    {
//        Str2Upper( GroupName);

        if( GroupList)
        {
            if( GroupNode = FindName(( struct List *) GroupList, GroupName))
            {
                if( GroupNode->en_Count < Count)
                    GroupNode->en_Count = Count;
            }
            else
            {
                if( GroupNode = AllocVec( sizeof( struct ExpireGroupNode), MEMF_ANY|MEMF_CLEAR))
                {
                    strncpy( GroupNode->en_Data, GroupName, STRING_LENGTH);
                    GroupNode->en_Data[ STRING_LENGTH ] = 0x00;
                    GroupNode->en_Count = Count;
                    GroupNode->en_Node.ln_Name = GroupNode->en_Data;
                    GroupNode->en_Node.ln_Type = EXPIREGROUPNODE_ID;
                    GroupNode->en_Node.ln_Pri  = 0;

                    AddTail(( struct List *) GroupList, ( struct Node *) GroupNode);
                }
            }
        }
    }
}
//-

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

//    Str2Upper( GroupName);

    if( GroupList)
    {
        if( GroupNode = FindName(( struct List *) GroupList, GroupName))
        {
            Remove(( struct Node *) GroupNode);
            FreeVec( GroupNode);
        }
    }
}
//-

//+GetTime()
GetTime()
{
    OTime = time( NULL);
    strftime( TimeString, TIMESTRING_SIZE, "%d-%b-%y %H:%M:%S  ", localtime( &OTime));
} //-
//+ LogSpace()
LogSpace()
{
    FPutC( StdOutputHandle, 0x0a);
    FPutC( LogHandle, 0x0a);
} //-
//+FPutsLog( char *String)
FPutsLog( char *String)
{
    GetTime();
    FPuts( StdOutputHandle, TimeString);
    FPuts( StdOutputHandle, String);
    FPutC( StdOutputHandle, 0x0a);
    FPuts( LogHandle, TimeString);
    FPuts( LogHandle, String);
    FPutC( LogHandle, 0x0a);
} //-
//+ FPrintfLog( char *FString, ...)
FPrintfLog( char *FString, ...)
{
    va_list Arguments;

    char    String[ 220 ];

    va_start( Arguments, FString);

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

    va_end( Arguments);
} //-

//+ 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);
} //-

//+Str2Upper( char *String)
Str2Upper( char *String)
{
    while( *String != 0x0a && *String != 0x00)
    {
        *String = toupper( *String);
        String++;
    }
    *String = 0x00;
} //-
//+ Result = StrCmpNoCase( char *SrcString, char *DstString)
StrCmpNoCase( char *SrcString, char *DstString)
{
    long    Count = 0;

    while( *SrcString != 0x00 && *DstString != 0x00 && tolower( *DstString) == tolower( *SrcString))
    {
        SrcString++;
        DstString++;
        Count++;
    }

    if( *SrcString == *DstString)
        return( FALSE);
    else
        return( Count);
} //-
