view src/fetch.c @ 53:9f3a4eccce32 noffle

[svn] Use numbers for sections. Added using Noffle as a maillist newsgroup gateway.
author enz
date Mon, 08 May 2000 17:52:14 +0100
parents 2842f50feb55
children 125d79c9e586
line wrap: on
line source

/*
  fetch.c

  $Id: fetch.c 49 2000-05-05 21:45:56Z uh1763 $
*/

#if HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include "fetch.h"
#include <errno.h>
#include <time.h>
#include <signal.h>
#include "client.h"
#include "configfile.h"
#include "content.h"
#include "dynamicstring.h"
#include "fetchlist.h"
#include "request.h"
#include "group.h"
#include "log.h"
#include "outgoing.h"
#include "protocol.h"
#include "pseudo.h"
#include "util.h"

struct Fetch
{
    Bool ready;
    Str serv;
} fetch = { FALSE, "" };

static Bool
connectToServ( const char *name )
{
    Log_inf( "Fetch from '%s'", name );
    if ( ! Client_connect( name ) )
    {
        Log_err( "Could not connect to %s", name );
        return FALSE;
    }
    return TRUE;
}

void
Fetch_getNewGrps( void )
{
    time_t t;
    Str file;

    ASSERT( fetch.ready );
    snprintf( file, MAXCHAR, "%s/groupinfo.lastupdate", Cfg_spoolDir() );
    if ( ! Utl_getStamp( &t, file ) )
    {
        Log_err( "Cannot read %s. Please run noffle --query groups", file );
        return;
    }
    Log_inf( "Updating groupinfo" );
    Client_getNewgrps( &t );
    Utl_stamp( file );
}

void
Fetch_getNewArts( const char *name, FetchMode mode )
{
    int next, first, last, oldLast;

    if ( ! Client_changeToGrp( name ) )
    {
        Log_err( "Could not change to group %s", name );
        return;
    }
    Cont_read( name );
    Client_rmtFirstLast( &first, &last );
    next = Grp_rmtNext( name );
    oldLast = Cont_last();
    if ( next == last + 1 )
    {
        Log_inf( "No new articles in %s", name );
        Cont_write();
        Grp_setFirstLast( name, Cont_first(), Cont_last() );
        return;
    }
    if ( first == 0 && last == 0 )
    {
        Log_inf( "No articles in %s", name );
        Cont_write();
        Grp_setFirstLast( name, Cont_first(), Cont_last() );
        return;
    }
    if ( next > last + 1 )
    {
        Log_err( "Article number inconsistent (%s rmt=%lu-%lu, next=%lu)",
                 name, first, last, next );
        Pseudo_cntInconsistent( name, first, last, next );
    }
    else if ( next < first )
    {
        Log_inf( "Missing articles (%s first=%lu next=%lu)",
                 name, first, next );
        Pseudo_missArts( name, first, next );
    }
    else
        first = next;
    if ( last - first > Cfg_maxFetch() )
    {
        Log_ntc( "Cutting number of overviews to %lu", Cfg_maxFetch() );
        first = last - Cfg_maxFetch() + 1;
    }
    Log_inf( "Getting remote overviews %lu-%lu for group %s",
             first, last, name );
    Client_getOver( first, last, mode );
    Cont_write();
    Grp_setFirstLast( name, Cont_first(), Cont_last() );
}

void
Fetch_updateGrps( void )
{
    FetchMode mode;
    int i, size;
    const char* name;

    ASSERT( fetch.ready );
    Fetchlist_read();
    size = Fetchlist_size();
    for ( i = 0; i < size; ++i )
    {
        Fetchlist_element( &name, &mode, i );
        if ( strcmp( Grp_serv( name ), fetch.serv ) == 0 )
            Fetch_getNewArts( name, mode );
    }
}

void
Fetch_getReq_( void )
{
    Str msgId;
    DynStr *list;
    const char *p;
    int count = 0;

    ASSERT( fetch.ready );
    Log_dbg( "Retrieving articles marked for download" );
    list = new_DynStr( 10000 );
    if ( Req_first( fetch.serv, msgId ) )
        do
        {
            DynStr_appLn( list, msgId );
            if ( ++count % 20 == 0 ) /* Send max. 20 ARTICLE cmds at once */
            {
                p = DynStr_str( list );
                Client_retrieveArtList( p );
                while ( ( p = Utl_getLn( msgId, p ) ) )
                    Req_remove( fetch.serv, msgId );
                DynStr_clear( list );
            }
        }
        while ( Req_next( msgId ) );
    p = DynStr_str( list );
    Client_retrieveArtList( p );
    while ( ( p = Utl_getLn( msgId, p ) ) )
        Req_remove( fetch.serv, msgId );
    del_DynStr( list );
}

void
Fetch_postArts( void )
{
    DynStr *s;
    Str msgId, cmd, errStr, sender;
    int ret;
    const char *txt;
    FILE *f;
    sig_t lastHandler;

    s = new_DynStr( 10000 );
    if ( Out_first( fetch.serv, msgId, s ) )
    {
        Log_inf( "Posting articles" );
        do
        {
            txt = DynStr_str( s );
            Out_remove( fetch.serv, msgId );
            if ( ! Client_postArt( msgId, txt, errStr ) )
            {
                Utl_cpyStr( sender, Cfg_mailTo() );
                if ( strcmp( sender, "" ) == 0
                     && ! Prt_searchHeader( txt, "SENDER", sender )
                     && ! Prt_searchHeader( txt, "X-NOFFLE-X-SENDER",
                                            sender ) /* see server.c */
                     && ! Prt_searchHeader( txt, "FROM", sender ) )
                    Log_err( "Article %s has no From/Sender/X-Sender field",
                             msgId );
                else
                {
                    Log_ntc( "Return article to '%s' by mail", sender );
                    snprintf( cmd, MAXCHAR,
                              "mail -s '[ NOFFLE: Posting failed ]' '%s'",
                              sender );
                    lastHandler = signal( SIGPIPE, SIG_IGN );
                    f = popen( cmd, "w" );
                    if ( f == NULL )
                        Log_err( "Invocation of '%s' failed (%s)", cmd,
                                 strerror( errno ) );
                    else
                    {
                        fprintf( f,
                                 "\t[ NOFFLE: POSTING OF ARTICLE FAILED ]\n"
                                 "\n"
                                 "\t[ The posting of your article failed. ]\n"
                                 "\t[ Reason of failure at remote server: ]\n"
                                 "\n"
                                 "\t[ %s ]\n"
                                 "\n"
                                 "\t[ Full article text has been appended. ]\n"
                                 "\n"
                                 "%s"
                                 ".\n",
                                 errStr, txt );
                        ret = pclose( f );
                        if ( ret != EXIT_SUCCESS )
                            Log_err( "'%s' exit value %d", cmd, ret );
                        signal( SIGPIPE, lastHandler );
                    }
                }
            }
        }
        while ( Out_next( msgId, s ) );
    }
    del_DynStr( s );
}

Bool
Fetch_init( const char *serv )
{
    if ( ! connectToServ( serv ) )
        return FALSE;
    Utl_cpyStr( fetch.serv, serv );
    fetch.ready = TRUE;
    return TRUE;
}

void
Fetch_close()
{
    Client_disconnect();
    fetch.ready = FALSE;
    Log_inf( "Fetch from '%s' finished", fetch.serv );
}