home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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;
- }
-
-