home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
479a.lha
/
barn_v2.01
/
source
/
ng.c
< prev
next >
Wrap
Text File
|
1991-02-10
|
11KB
|
406 lines
/*
* File Name: ng.c
* Project: BARN - Bah's Amiga ReadNews.
* Purpose: Defines functions related to newsgroup list.
* Functions: GetNewsRC, ReadNextMarker, PutNewsRC, DestroyNGList,
* NumberCovered, UpdateReadList, Mark.
* Author: Jeff Van Epps
* Created: 03 Sep 89
* Last Modified: 14 Nov 90
* Comments:
* History:
* 03 Sep 89/JVE Created.
* 21 Oct 90/JVE Moved UpdateReadList, Mark from arn.c to here where
* they belong.
* 14 Nov 90/JVE Made sure a marker for article 0 gets created if
* no other articles have been read.
*/
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <fcntl.h>
# include "standard.h"
# include "article.h"
# include "ng.h"
/****************************************************************************/
/* FUNCTION: GetNewsRC */
/* */
/* PURPOSE: Read/parse the .newsrc file. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* filename I Name of file containing read newsgroups info. */
/* */
/* RETURNS: */
/* */
/* COMMENTS: */
/* Parses lines from user's .newsrc file to see which articles in */
/* which newsgroups have already been read. */
/* */
/* HISTORY: */
/* 1. 03 Sep 89 Created. */
/* */
/****************************************************************************/
NG_INFO *GetNewsRC( filename )
char *filename;
{
NG_INFO *root = NULLP( NG_INFO ); /* points to start of ng list */
NG_INFO **ptr = &root; /* where to alloc next ng from */
MARKER **marker; /* where to alloc next marker from */
FILE *fp; /* pointer into .newsrc file */
char buf[BUFSIZ];
char *name; /* newsgroup name */
if ( ( fp = fopen( filename, "r" ) ) == NULLP( FILE ) )
perror( filename );
else
{
while ( fgets( buf, BUFSIZ, fp ) != NULLP( char ) )
{
if ( ( name = strtok( buf, " " ) ) == NULLP( char ) )
fprintf( stderr, "Bad line in %s: %s", filename, buf );
else
{
*ptr = (NG_INFO *) malloc( sizeof( NG_INFO ) );
(*ptr)->next = NULLP( NG_INFO );
(*ptr)->markers = NULLP( MARKER );
marker = &(*ptr)->markers;
while ( ReadNextMarker( &marker ) ) ;
(*ptr)->name = strdup( name );
ptr = &(*ptr)->next;
}
}
fclose( fp );
}
return root;
}
/****************************************************************************/
/* FUNCTION: ReadNextMarker */
/* */
/* PURPOSE: Parse next marker from line. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* marker I/O Pointer to pointer to next marker. */
/* */
/* RETURNS: */
/* TRUE Marker parsed. */
/* FALSE No marker parsed (end of input line). */
/* */
/* COMMENTS: */
/* markers = [ marker | marker + ',' + markers ] */
/* marker = [ XXX | XXX + '-' + YYY ] */
/* */
/* There may be a list of markers with each marker separated by a */
/* comma. Each marker may be either a single number or two numbers */
/* separated by a dash indicating an inclusive range. White space */
/* is not allowed anywhere. */
/* */
/* We assume that the string we are parsing has already been subject */
/* to a strtok() call so that we can just strtok(NULL,x) to continue */
/* parsing the same string. */
/* */
/* HISTORY: */
/* 1. 03 Sep 89 Created. */
/* */
/****************************************************************************/
ReadNextMarker( marker )
MARKER ***marker;
{
int rc = FALSE;
char *p, *q;
if ( ( p = strtok( NULLP( char ), "," ) ) != NULLP( char ) )
{
**marker = (MARKER *) malloc( sizeof( MARKER ) );
(**marker)->next = NULLP( MARKER );
(**marker)->from = atol( p );
if ( ( q = strchr( p, '-' ) ) != NULLP( char ) )
(**marker)->to = atol( ++q );
else
(**marker)->to = 0L;
*marker = &(**marker)->next;
rc = TRUE;
}
return rc;
}
/****************************************************************************/
/* FUNCTION: PutNewsRC */
/* */
/* PURPOSE: Write read article markers to .newsrc file. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* filename I Name of file to which to write .newsrc info. */
/* root I List of already read articles. */
/* */
/* RETURNS: none */
/* */
/* COMMENTS: */
/* Tries to save old .newsrc file as .newsrc.BAK before writing new */
/* one. */
/* */
/* HISTORY: */
/* 1. 03 Sep 89 Created. */
/* */
/****************************************************************************/
void PutNewsRC( filename, root )
char *filename;
NG_INFO *root;
{
char backup[BUFSIZ], temp[BUFSIZ];
FILE *fp;
MARKER *ptr;
sprintf( backup, "%s.BAK", filename );
(void) remove( backup );
if ( rename( filename, backup ) )
{
sprintf( temp, "rename(%s,%s)", filename, backup );
perror( temp );
}
else
{
if ( ( fp = fopen( filename, "a" ) ) == NULLP( FILE ) )
perror( filename );
else
{
while ( root != NULLP( NG_INFO ) )
{
fprintf( fp, "%s ", root->name );
for ( ptr = root->markers; ptr != NULLP( MARKER ); )
{
fprintf( fp, "%ld", ptr->from );
if ( ptr->to > 0L )
fprintf( fp, "-%ld", ptr->to );
if ( ptr = ptr->next )
fprintf( fp, "," );
}
fprintf( fp, "\n" );
root = root->next;
}
fclose( fp );
}
}
}
/****************************************************************************/
/* FUNCTION: DestroyNGList */
/* */
/* PURPOSE: Free memory taken by newsgroup list. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* root I Pointer to list of newsgroups. */
/* */
/* RETURNS: none */
/* */
/* COMMENTS: */
/* */
/* HISTORY: */
/* 1. 03 Sep 89 Created. */
/* */
/****************************************************************************/
void DestroyNGList( root )
NG_INFO *root;
{
MARKER *ptr, *tmp;
NG_INFO *next;
while ( root != NULLP( NG_INFO ) )
{
for ( ptr = root->markers; ptr != NULLP( MARKER ); ptr = tmp )
{
tmp = ptr->next;
free( ptr );
}
free( root->name );
next = root->next;
free( root );
root = next;
}
}
/****************************************************************************/
/* FUNCTION: NumberCovered */
/* */
/* PURPOSE: Check whether number is covered by markers. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* markers I Marker list. */
/* number I Number to be checked. */
/* */
/* RETURNS: */
/* TRUE If number is in list. */
/* FALSE If number is not in list. */
/* */
/* COMMENTS: */
/* Markers are assumed to be sorted low->high and non-overlapping. */
/* */
/* HISTORY: */
/* 1. 04 Sep 89 Created. */
/* */
/****************************************************************************/
NumberCovered( markers, number )
MARKER *markers;
long number;
{
int rc = FALSE;
while ( !rc && markers != NULLP( MARKER ) )
{
if ( markers->from > number )
break;
else if ( markers->from == number )
rc = TRUE;
else if ( markers->to >= number )
rc = TRUE;
markers = markers->next;
}
return rc;
}
/****************************************************************************/
/* FUNCTION: UpdateReadList */
/* */
/* PURPOSE: Update the list of articles read due to newly read ones. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* ng I/O List of read articles. */
/* new I List containing some newly read articles. */
/* */
/* RETURNS: none */
/* */
/* COMMENTS: */
/* Look for articles which are STILL unread, and make a list which */
/* marks everything except those. If nothing is left unread, the list */
/* should mark to the greater of the previously highest read article */
/* and the highest newly read article. */
/* */
/* HISTORY: */
/* 1. 04 Sep 89 Created. */
/* 2. 16 Dec 89 Fixed bug in last mark if last article unread. */
/* 3. 14 Nov 90 Make sure *something* gets marked, i.e. 0-0 if */
/* nothing else. */
/* */
/****************************************************************************/
void UpdateReadList( ng, new )
NG_INFO *ng;
ARTICLE_INFO *new;
{
long beginning, ending;
MARKER **where; /* where to allocate next marker */
MARKER *first = NULL; /* ptr to beginning of new marker list */
MARKER *ptr, *tmp;
for ( ptr = ng->markers; ptr != NULLP( MARKER ); ptr = tmp )
{
if ( ptr->to != 0L )
ending = ptr->to;
else
ending = ptr->from;
tmp = ptr->next;
free( ptr );
}
beginning = 1L;
where = &first;
for ( ; new != NULLP( ARTICLE_INFO ); new = new->next )
{
if ( ! new->beenread )
{
if ( new->number != beginning && beginning <= ending )
{
*where = Mark( beginning, new->number - 1L );
where = & (*where)->next;
}
beginning = new->number + 1L;
}
else if ( new->number > ending )
ending = new->number;
}
if ( beginning <= ending )
*where = Mark( beginning, ending );
/*
* If no markers have been created, create one for article # 0.
*/
if ( first == NULL )
*where = Mark( 0L, 0L );
ng->markers = first;
}
/****************************************************************************/
/* FUNCTION: Mark */
/* */
/* PURPOSE: Create a marker. */
/* */
/* INPUT PARAMETERS: */
/* NAME I/O DESCRIPTION */
/* ---- --- ----------- */
/* begin I From part of marker. */
/* end I To part of marker. */
/* */
/* RETURNS: */
/* (MARKER *) Pointer to new marker. */
/* */
/* COMMENTS: */
/* */
/* HISTORY: */
/* 1. 05 Sep 89 Created. */
/* */
/****************************************************************************/
MARKER *Mark( begin, end )
long begin, end;
{
MARKER *ptr;
ptr = (MARKER *) malloc( sizeof( MARKER ) );
ptr->from = begin;
if ( begin == end )
ptr->to = 0L;
else
ptr->to = end;
ptr->next = NULLP( MARKER );
return ptr;
}