view src/fetch.c @ 58:b4e6f7f96135 noffle

[svn] Add some intermediate variables for easier debugging in needsMark(). It seems that thread mode is sometimes not working. Changed some variable types and used some casts to avoid compiler warnings about signedness. In general, int should be used for parameters for allowing a signedness assertion in the function.
author enz
date Fri, 12 May 2000 17:52:07 +0100
parents 125d79c9e586
children adf0af5152f7
line wrap: on
line source

/*
  fetch.c

  $Id: fetch.c 60 2000-05-09 22:28:38Z uh1763 $
*/

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

#include <stdio.h>
#include "fetch.h"
#include <errno.h>

#if TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif

#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"
#include "portable.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 );
}