/*
 *	File Name:		kill.c
 *	Project:		BARN - Bah's Amiga ReadNews.
 *	Purpose:		Defines functions related to kill list.
 *	Functions:		GetKillList, PutKillList, DestroyKillList.
 *	Author:			Jeff Van Epps
 *	Created:		04 Sep 89
 *	Last Modified:	22 Oct 90
 *	Comments:
 *	History:
 *		04 Sep 89/JVE	Created.
 *		30 Dec 89/JVE	Implemented GetKillList and PutKillList, which were
 *						only stubbed previously.
 *		22 Oct 90/JVE	Added regular expression capability in kill files.
 *						A kill list is no longer just a list of HEADER_INFOs,
 *						it now has its own structure.
 */

# include	<stdio.h>
# include	<stdlib.h>
# include	<string.h>
# include	<fcntl.h>
# include	<regexp.h>
# include	"standard.h"
# include	"article.h"
# include	"kill.h"


/****************************************************************************/
/*	FUNCTION:	GetKillList													*/
/*																			*/
/*	PURPOSE:	Parse the kill file which applies to all newsgroups.		*/
/*																			*/
/*	INPUT PARAMETERS:														*/
/*		NAME		I/O		DESCRIPTION										*/
/*		----		---		-----------										*/
/*		filename	 I		Name of kill file.								*/
/*																			*/
/*	RETURNS:																*/
/*		(KILL_INFO *)	Pointer to start of kill list.						*/
/*																			*/
/*	COMMENTS:																*/
/*																			*/
/*	HISTORY:																*/
/*		1.	30 Dec 89		Created.										*/
/*																			*/
/****************************************************************************/

KILL_INFO	*GetKillList( filename )

char		*filename;

{
KILL_INFO	*root = NULLP( KILL_INFO );
KILL_INFO	**ptr;
FILE		*fp;

if ( ( fp = fopen( filename, "r" ) ) != NULLP( FILE ) )
	{
	ptr = &root;
	while ( GetNextKill( fp, &ptr ) ) ;
	fclose( fp );
	}
return root;
}


/****************************************************************************/
/*	FUNCTION:	PutKillList													*/
/*																			*/
/*	PURPOSE:	Write back a kill list to specified file.					*/
/*																			*/
/*	INPUT PARAMETERS:														*/
/*		NAME		I/O		DESCRIPTION										*/
/*		----		---		-----------										*/
/*		filename	 I		File in which to put kill list.					*/
/*		root		 I		Pointer to start of kill list.					*/
/*																			*/
/*	RETURNS: none															*/
/*																			*/
/*	COMMENTS:																*/
/*																			*/
/*	HISTORY:																*/
/*		1.	30 Dec 89		Created.										*/
/*																			*/
/****************************************************************************/

void PutKillList( filename, root )

char		*filename;
KILL_INFO	*root;

{
FILE		*fp;

remove( filename );
if ( ( fp = fopen( filename, "a" ) ) != NULLP( FILE ) )
	{
	while ( root != NULLP( KILL_INFO ) )
		{
		fprintf( fp, "%s: %s\n", root->fieldname, root->fieldvalue );
		root = root->next;
		}
	fclose( fp );
	}
}


/****************************************************************************/
/*	FUNCTION:	DestroyKillList												*/
/*																			*/
/*	PURPOSE:	Release memory consumed by construction of kill list.		*/
/*																			*/
/*	INPUT PARAMETERS:														*/
/*		NAME		I/O		DESCRIPTION										*/
/*		----		---		-----------										*/
/*		root		 I		Pointer to start of kill list.					*/
/*																			*/
/*	RETURNS: none															*/
/*																			*/
/*	COMMENTS:																*/
/*																			*/
/*	HISTORY:																*/
/*		1.	04 Sep 89		Created.										*/
/*																			*/
/****************************************************************************/

void DestroyKillList( root )

KILL_INFO		*root;

{
KILL_INFO		*tmp;

for ( ; root != NULLP( KILL_INFO ); root = tmp )
	{
	tmp = root->next;
	free( root -> fieldname );
	free( root -> fieldvalue );
	free( (char *) ( root -> pattern ) );
	free( root );
	}
}

/****************************************************************************/
/*	FUNCTION:	GetNextKill													*/
/*																			*/
/*	PURPOSE:	Parses the next kill entry from a kill file.				*/
/*																			*/
/*	INPUT PARAMETERS:														*/
/*		NAME		I/O		DESCRIPTION										*/
/*		----		---		-----------										*/
/*		fp			 I		FILE pointer to file containing article.		*/
/*		hdr			I/O		Where to put pointer to newly allocated			*/
/*							KILL_INFO structure if we allocate one.			*/
/*																			*/
/*	RETURNS:																*/
/*		TRUE	Successfully parsed another entry from file.				*/
/*		FALSE	Failed/no more entries.										*/
/*																			*/
/*	COMMENTS:																*/
/*		Adjusts hdr when done so next call will set correct pointer.		*/
/*																			*/
/*	HISTORY:																*/
/*		1.	22 Oct 90		Created from GetNextHeader.						*/
/*																			*/
/****************************************************************************/

GetNextKill( fp, hdr )

FILE			*fp;
KILL_INFO		***hdr;

{
int				rc;				/* return code from function */
char			buf[BUFSIZ];	/* holds input line from article */
char			*firstspace, *firstcolon, *data;	/* for parsing */

if ( fgets( buf, BUFSIZ, fp ) == NULL )
	rc = FALSE;
else
	{
	firstspace = strchr( buf, ' ' );
	firstcolon = strchr( buf, ':' );
	if ( ( firstcolon == NULL ) || 
	  ( ( firstspace != NULL ) && ( firstspace < firstcolon ) ) )
		rc = FALSE;
	else
		{
		*firstcolon = NULL;		/* terminate fieldname string */
		firstcolon++;			/* advance past colon/NULL to value string */
		data = firstcolon + strspn( firstcolon, " \t" );	/* skip white */
		data[strlen(data)-1] = NULL;	/* remove trailing newline */

		/*
		 *	Allocate and fill a new kill structure.
		 */

		**hdr = (KILL_INFO *) malloc( sizeof( KILL_INFO ) );
		(**hdr)->fieldname = strdup( buf );
		(**hdr)->fieldvalue = strdup( data );
		(**hdr)->pattern = regcomp( data );
		if ( (**hdr) -> pattern == NULL )
			fprintf( stderr, "Bad kill pattern '%s'\n", data );
		(**hdr)->next = NULLP( KILL_INFO );

		/*
		 *	Reset the hdr pointer so next call will continue chain correctly.
		 */

		*hdr = &((**hdr)->next);
		rc = TRUE;
		}
	}
return rc;
}
