view src/outgoing.c @ 183:c912e8288164 noffle

[svn] * src/client.c: Only bail out of fetching multiple articles if the connection fails. If we do get a status from the upstream server note it and see what is reported for the next article. Otherwise failure to retrieve one article will cause all successive article fetches to fail even through they would succeed if tried. * src/lock.c: Fix assert in lazy locking. If another noffle signalled us to release the lock at the next close, and then repeats the signal so that it arrives during LOCK_closeDatabases, the signal handler was trying to close the databases again.
author bears
date Tue, 15 May 2001 13:07:53 +0100
parents 125d79c9e586
children fed1334d766b
line wrap: on
line source

/*
  outgoing.c

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

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

#include "outgoing.h"

#include <stdio.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.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 <unistd.h>
#include "configfile.h"
#include "log.h"
#include "util.h"
#include "portable.h"

struct Outgoing
{
    DIR *dir;
    Str serv;
} outgoing = { NULL, "" };

static void
fileOutgoing( Str file, const char *serv, const char *msgId )
{
    snprintf( file, MAXCHAR, "%s/outgoing/%s/%s",
              Cfg_spoolDir(), serv, msgId );
}

static void
createDir( const char *serv )
{
    Str dir;
    int r;

    snprintf( dir, MAXCHAR, "%s/outgoing/%s", Cfg_spoolDir(), serv );
    r = mkdir( dir, 0755 );
    if ( r != 0 )
        Log_dbg( "mkdir: %s", strerror( errno ) );
}

Bool
Out_add( const char *serv, const char *msgId, const DynStr *artTxt )
{
    Str file;
    FILE *f;

    fileOutgoing( file, serv, msgId );
    if ( ! ( f = fopen( file, "w" ) ) )
    {
        createDir( serv );
        if ( ! ( f = fopen( file, "w" ) ) )
        {
            Log_err( "Cannot open %s", file );
            return FALSE;
        }
    }
    fprintf( f, "%s", DynStr_str( artTxt ) );
    fclose( f );
    return TRUE;
}

Bool
Out_first( const char *serv, Str msgId, DynStr *artTxt )
{
    Str file;
    
    snprintf( file, MAXCHAR, "%s/outgoing/%s", Cfg_spoolDir(), serv );
    if ( ! ( outgoing.dir = opendir( file ) ) )
    {
        Log_dbg( "Cannot open %s", file );
        return FALSE;
    }
    Utl_cpyStr( outgoing.serv, serv );
    Out_next( NULL, NULL ); /* "."  */
    Out_next( NULL, NULL ); /* ".." */
    return Out_next( msgId, artTxt );
}

Bool
Out_next( Str msgId, DynStr *artTxt )
{
    struct dirent *d;
    FILE *f;
    Str file, line;

    ASSERT( outgoing.dir );
    if ( ! ( d = readdir( outgoing.dir ) ) )
    {
        closedir( outgoing.dir );
        outgoing.dir = NULL;
        return FALSE;
    }
    if ( artTxt == NULL )
        return ( d->d_name != NULL );
    fileOutgoing( file, outgoing.serv, d->d_name );
    if ( ! ( f = fopen( file, "r" ) ) )
    {
        Log_err( "Cannot open %s for read", file );
        return FALSE;
    }
    DynStr_clear( artTxt );
    while ( fgets( line, MAXCHAR, f ) )
        DynStr_app( artTxt, line );
    Utl_cpyStr( msgId, d->d_name );
    fclose( f );
    return TRUE;
}

void
Out_remove( const char *serv, const char *msgId )
{
    Str file;

    fileOutgoing( file, serv, msgId );
    if ( unlink( file ) != 0 )
        Log_err( "Cannot remove %s", file );
}

Bool
Out_find( const char *msgId, Str server )
{
    Str servdir;
    DIR *d;
    struct dirent *entry;
    Bool res;
    
    
    snprintf( servdir, MAXCHAR, "%s/outgoing", Cfg_spoolDir() );
    if ( ! ( d = opendir( servdir ) ) )
    {
        Log_dbg( "Cannot open %s", servdir );
        return FALSE;
    }

    readdir( d );	/* '.' */
    readdir( d );	/* '..' */

    res = FALSE;
    while ( ! res && ( entry = readdir( d ) ) != NULL )
    {
	Str file;
	struct stat s;

	fileOutgoing( file, entry->d_name, msgId );
	if ( stat( file, &s ) == 0 )
	{
	    res = TRUE;
	    Utl_cpyStr( server, entry->d_name );
	}
    }

    closedir( d );
    return res;
}