amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (02/07/91)
Submitted-by: lordbah@amusing.bisco.kodak.COM (Jeff Van Epps)
Posting-number: Volume 91, Issue 006
Archive-name: news/barn-2.01/part01
I am submitting to comp.sources.amiga my program, "Bah's Amiga Read News".
(Originally I called it ARN, but there is already a newsreader out there
called ARN so I changed the name of mine).
Name: BARN
Version: 2.01
Description: Usenet newsreader for the Amiga.
Distribution: Source is freely distributable.
A replacement for Anews which comes with AmigaUUCP 1.03D -- should also
work with later versions of AmigaUUCP. The interface is modeled after
"rn" from the UNIX world. Follows subject threads, has kill files, a
built-in pager, etc.
Probably requires SAS C 5.10 or later to compile, as well as Henry Spencer's
regexp library.
--------------------------------------------------------------------
Jeff Van Epps amusing!lordbah@bisco.kodak.com
lordbah@cup.portal.com
sun!portal!cup.portal.com!lordbah
#!/bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 2)."
# Contents: Makefile article.c article.h barn.config configure.c
# configure.h kill.c kill.h ng.c ng.h raw.c reply.c reply.h
# screenstuff.h sendpacket.c standard.h trim.sksh variables.h
# Wrapped by tadguy@ab20 on Wed Feb 6 20:05:19 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(782 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCFLAGS = -c -O +filter +pure-strings +echo
X#CFLAGS = -c -g3 +filter +pure-strings +echo
XBARN_OBJS = arn.o article.o configure.o ng.o kill.o reply.o raw.o sendpacket.o
XCC = cc
X
X.c.o:
X $(CC) $(CFLAGS) $<
X
Xall: barn
X
Xbarn: $(BARN_OBJS)
X $(CC) $(BARN_OBJS) +catch -lregexp -o barn
X
Xtest: main.o article.o
X blink from lib:c.o+main.o+article.o to test lib lib:$(CC).lib lib:amiga.lib addsym
X
XInstall: barn
X copy barn uucp:c
X
Xarn.o: arn.c standard.h article.h ng.h kill.h configure.h variables.h reply.h screenstuff.h
X
Xarticle.o: article.c standard.h article.h configure.h variables.h
X
Xconfigure.o: configure.c standard.h configure.h
X
Xkill.o: kill.c standard.h article.h kill.h
X
Xng.o: ng.c standard.h article.h ng.h
X
Xreply.o: reply.c standard.h configure.h variables.h article.h reply.h
X
END_OF_FILE
if test 782 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
chmod +x 'Makefile'
# end of 'Makefile'
fi
if test -f 'article.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'article.c'\"
else
echo shar: Extracting \"'article.c'\" \(9465 characters\)
sed "s/^X//" >'article.c' <<'END_OF_FILE'
X/*
X * File Name: article.c
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Parse header fields in a news article.
X * Functions: ParseArticle, GetNextHeader, DumpArticle, DestroyArticle.
X * Author: Jeff Van Epps
X * Created: 02 Sep 89
X * Last Modified: 05 Jan 91
X * Comments:
X * History:
X * 02 Sep 89/JVE Created.
X * 28 Sep 89/JVE ParseArticle now stores position within file where
X * headers end and text begins in article->textpos.
X * 30 Dec 89/JVE Added "Sender:" to list of useful headers. This list
X * will go away when there is a config file to do same.
X * 18 Oct 90/JVE Use HDR_xxx defines instead of hardcoded strings.
X * Added GetHeader.
X * 21 Oct 90/JVE Don't end header search until blank line.
X * 05 Jan 91/JVE New "subject" field in article_info initialized to
X * a NULL pointer and set to point at the SUBJECT header
X * fieldvalue after all headers have been read.
X */
X
X# include <stdio.h>
X# include <stdlib.h>
X# include <string.h>
X# include "standard.h"
X# include "article.h"
X# include "configure.h"
X# include "variables.h"
X
X
X/****************************************************************************/
X/* FUNCTION: ParseArticle */
X/* */
X/* PURPOSE: Parses headers from article & creates article/header structs*/
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* filename I Name of file containing article. */
X/* */
X/* RETURNS: */
X/* (ARTICLE_INFO *) Pointer to newly allocated article structure. */
X/* NULLP(ARTICLE_INFO) Indication of failure. */
X/* */
X/* COMMENTS: */
X/* Assumes filename contains only digits and is same as article */
X/* number. */
X/* */
X/* HISTORY: */
X/* 1. 02 Sep 89 Created. */
X/* 2. 28 Sep 89 Added textpos to say where headers end. */
X/* */
X/****************************************************************************/
X
XARTICLE_INFO *ParseArticle( filename )
X
Xchar *filename;
X
X{
XFILE *fp;
Xlong id; /* article number (aka filename) */
XARTICLE_INFO *article; /* ptr to article information */
XHEADER_INFO **hdr; /* handle for header field allocation */
XHEADER_INFO *h;
X
Xif ( ( fp = fopen( filename, "r" ) ) == NULLP( FILE ) )
X {
X perror( filename );
X return NULLP( ARTICLE_INFO );
X }
Xelse if ( ( id = atol( filename ) ) <= 0 )
X {
X printf( "%s: Bad article number.\n", filename );
X return NULLP( ARTICLE_INFO );
X }
X
X/*
X * Initialize article info structure.
X */
X
Xarticle = (ARTICLE_INFO *) malloc( sizeof( ARTICLE_INFO ) );
Xarticle->number = id;
Xarticle->next = NULLP( ARTICLE_INFO );
Xarticle->headers = NULLP( HEADER_INFO );
Xarticle->beenread = FALSE;
Xarticle->textpos = 0L;
Xarticle->done = FALSE;
Xarticle->subject = NULLP( char );
X
X/*
X * Get all header fields.
X */
X
Xhdr = &article->headers;
Xwhile ( GetNextHeader( fp, &hdr ) )
X article->textpos = ftell( fp );
Xfclose( fp );
Xfor ( h = article -> headers; h != NULLP( HEADER_INFO ); h = h -> next )
X if ( strcmp( h -> fieldname, HDR_SUBJECT ) == 0 )
X {
X article -> subject = h -> fieldvalue;
X break;
X }
Xreturn article;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: GetNextHeader */
X/* */
X/* PURPOSE: Parses the next header field out of an article. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* fp I FILE pointer to file containing article. */
X/* hdr I/O Where to put pointer to newly allocated */
X/* HEADER_INFO structure if we allocate one. */
X/* */
X/* RETURNS: */
X/* TRUE Successfully parsed another header from article. */
X/* FALSE Failed/no more headers in article. */
X/* */
X/* COMMENTS: */
X/* Adjusts hdr when done so next call will set correct pointer. */
X/* BBS version terminates header search on a line without a colon, */
X/* or with a space before the colon. Usenet version terminates */
X/* header search on blank line, ignoring "malformed" header lines. */
X/* */
X/* HISTORY: */
X/* 1. 02 Sep 89 Created. */
X/* 2. 30 Dec 89 Added "Sender:" to list of useful headers. */
X/* 3. 21 Oct 90 Don't end header search until blank line. */
X/* */
X/****************************************************************************/
X
XGetNextHeader( fp, hdr )
X
XFILE *fp;
XHEADER_INFO ***hdr;
X
X{
Xint rc; /* return code from function */
Xchar buf[BUFSIZ]; /* holds input line from article */
Xchar *firstspace, *firstcolon, *data; /* for parsing */
X
Xif ( fgets( buf, BUFSIZ, fp ) == NULL )
X rc = FALSE;
Xelse
X {
X firstspace = strchr( buf, ' ' );
X firstcolon = strchr( buf, ':' );
X if ( ( firstcolon == NULL ) ||
X ( ( firstspace != NULL ) && ( firstspace < firstcolon ) ) )
X {
X if ( GetVar( VAR_BBS ) || strspn( buf, " \t\r\n" ) == strlen(buf) )
X rc = FALSE;
X else /* junk line, don't end header search */
X rc = TRUE;
X }
X else
X {
X *firstcolon = NULL; /* terminate fieldname string */
X# ifndef ARN_CONFIG
X/*
X * Until a useful way is found to restrict output to interesting headers,
X * use this kluge.
X *
X * Don't actually allocate a header struct because we're not interested in
X * other headers, but return TRUE so that we continue to try to get headers.
X */
X if ( strcmp( buf, HDR_FROM ) && strcmp( buf, HDR_SUBJECT ) &&
X strcmp( buf, HDR_DATE ) && strcmp( buf, HDR_SENDER ) &&
X strcmp( buf, HDR_TO ) )
X return TRUE;
X# endif
X firstcolon++; /* advance past colon/NULL to value string */
X data = firstcolon + strspn( firstcolon, " \t" ); /* skip white */
X data[strlen(data)-1] = NULL; /* remove trailing newline */
X
X /*
X * Allocate and fill a new header structure.
X */
X
X **hdr = (HEADER_INFO *) malloc( sizeof( HEADER_INFO ) );
X (**hdr)->fieldname = strdup( buf );
X (**hdr)->fieldvalue = strdup( data );
X (**hdr)->next = NULLP( HEADER_INFO );
X
X /*
X * Reset the hdr pointer so next call will continue chain correctly.
X */
X
X *hdr = &((**hdr)->next);
X rc = TRUE;
X }
X }
Xreturn rc;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: DumpArticle */
X/* */
X/* PURPOSE: Print article/header info for an article. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* article I Pointer to article structure to dump. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* Debugging function. */
X/* */
X/* HISTORY: */
X/* 1. 02 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
Xvoid DumpArticle( article )
X
XARTICLE_INFO *article;
X
X{
XHEADER_INFO *hdr;
X
Xprintf( "Article: %ld\n", article->number );
Xfor ( hdr = article->headers; hdr != NULLP( HEADER_INFO ); hdr = hdr->next )
X printf( "\t%s: %s\n", hdr->fieldname, hdr->fieldvalue );
Xprintf( "\n" );
X}
X
X
X/****************************************************************************/
X/* FUNCTION: DestroyArticle */
X/* */
X/* PURPOSE: Free all space taken by article/header structure. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* article I The article being destroyed. */
X/* */
X/* RETURNS: */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 02 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
Xvoid DestroyArticle( article )
X
XARTICLE_INFO *article;
X
X{
XHEADER_INFO *hdr, *tmp;
X
Xfor ( hdr = article->headers; hdr != NULLP( HEADER_INFO ); hdr = tmp )
X {
X free( hdr->fieldname );
X free( hdr->fieldvalue );
X tmp = hdr->next;
X free( hdr );
X }
Xfree( article );
X}
X
X
X/****************************************************************************/
X/* FUNCTION: GetHeader */
X/* */
X/* PURPOSE: Retrieve a specific header from a message. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* headers I List of headers. */
X/* name I Name of header to retrieve. */
X/* */
X/* RETURNS: */
X/* */
X/* COMMENTS: */
X/* Makes a local copy of the header value to be returned. Gets */
X/* overwritten each call. */
X/* */
X/* HISTORY: */
X/* 1. 18 Oct 90 Created. */
X/* */
X/****************************************************************************/
X
Xchar *GetHeader( headers, name )
X
XHEADER_INFO *headers;
Xchar *name;
X
X{
Xstatic char local[MAXLINE];
X
Xwhile ( headers )
X {
X if ( strcmp( headers -> fieldname, name ) == 0 )
X {
X strcpy( local, headers -> fieldvalue );
X return local;
X }
X headers = headers -> next;
X }
Xreturn (char *) NULL;
X}
END_OF_FILE
if test 9465 -ne `wc -c <'article.c'`; then
echo shar: \"'article.c'\" unpacked with wrong size!
fi
chmod +x 'article.c'
# end of 'article.c'
fi
if test -f 'article.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'article.h'\"
else
echo shar: Extracting \"'article.h'\" \(1949 characters\)
sed "s/^X//" >'article.h' <<'END_OF_FILE'
X/*
X * File Name: article.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Define structure holding info for each article.
X * Author: Jeff Van Epps
X * Created: 02 Sep 89
X * Last Modified: 06 Jan 91
X * Comments:
X * History:
X * 02 Sep 89/JVE Created.
X * 28 Sep 89/JVE Added textpos.
X * 18 Oct 90/JVE Added HDR_xxx defines.
X * 06 Jan 91/JVE Added subject pointer in article_info as a speed
X * optimization.
X */
X
X/*
X * Hold header information for an article. Example:
X *
X * fieldname="From" fieldvalue="foo@bar.com"
X * fieldname="Subject" fieldvalue="Care and Eating of Foo Bars"
X * etc.
X *
X */
X
Xtypedef struct header_info {
X char *fieldname; /* name of field (before :) */
X char *fieldvalue; /* text of field (after :) */
X struct header_info *next; /* next header in chain */
X } HEADER_INFO;
X
X/*
X * Information for each article.
X */
X
Xtypedef struct article_info {
X long number; /* article number within newsgroup */
X int beenread; /* has article been read? */
X long textpos; /* where headers end/text begins */
X int done; /* generic temporary marker */
X char *subject; /* points at value of Subject hdr */
X struct header_info *headers; /* top of header field chain */
X struct article_info *next; /* ptr to next article in newsgroup */
X } ARTICLE_INFO;
X
X/*
X * Defines for common header fields.
X */
X
X
X# define HDR_FROM "From"
X# define HDR_TO "To"
X# define HDR_CC "Cc"
X# define HDR_SUBJECT "Subject"
X# define HDR_SENDER "Sender"
X# define HDR_DATE "Date"
X
X/*
X * Declare functions.
X */
X
X# ifdef sun
X
XARTICLE_INFO *ParseArticle();
Xint GetNextHeader();
Xvoid DestroyArticle();
Xvoid DumpArticle();
Xchar *GetHeader();
X
X# else
X
XARTICLE_INFO *ParseArticle( char *filename );
Xint GetNextHeader( FILE *fp, HEADER_INFO ***hdr );
Xvoid DestroyArticle( ARTICLE_INFO *article );
Xvoid DumpArticle( ARTICLE_INFO *article );
Xchar *GetHeader( HEADER_INFO *headers, char *name );
X
X# endif
END_OF_FILE
if test 1949 -ne `wc -c <'article.h'`; then
echo shar: \"'article.h'\" unpacked with wrong size!
fi
chmod +x 'article.h'
# end of 'article.h'
fi
if test -f 'barn.config' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'barn.config'\"
else
echo shar: Extracting \"'barn.config'\" \(776 characters\)
sed "s/^X//" >'barn.config' <<'END_OF_FILE'
X# arn.config
X#
X# Configuration file for ARN
X
X# 'user' is username used when sending mail or followups
X
Xuser=lordbah
X
X# 'node' is the UUCP name of the machine we're running on
X
Xnode=amusing
X
X# 'domain' is used in constructing 'From:' line in mail. Thus:
X# From: $node!$user@$domain ($name)
X#
X# This might be specific to our setup, but that's too bad (for now).
X
Xdomain=bisco.kodak.com
X
X# 'name' used in headers.
X
Xname=Lord Bah
X
X# Your favorite editor used to edit replies and followups.
X
Xeditor=stevie
X
X# Name of file used as .newsrc
X
Xnewsrc=.newsrc
X
X# Name of KILL file. Must start with "KILL"!!
X
Xkill=KILL
X
X# Name of signature file to append to outgoing mail and articles.
X
Xsignature=uulib:.signature
X
X# Set "bbs" to anything when reading a BBS-type repository.
X
X#bbs=true
END_OF_FILE
if test 776 -ne `wc -c <'barn.config'`; then
echo shar: \"'barn.config'\" unpacked with wrong size!
fi
chmod +x 'barn.config'
# end of 'barn.config'
fi
if test -f 'configure.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'configure.c'\"
else
echo shar: Extracting \"'configure.c'\" \(4912 characters\)
sed "s/^X//" >'configure.c' <<'END_OF_FILE'
X/*
X * File Name: configure.c
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Configuration variable setting, retrieving.
X * Functions: Configure, SetVar, GetVar.
X * Author: Jeff Van Epps
X * Created: 20 Oct 90
X * Last Modified: 20 Oct 90
X * Comments:
X * Generic configuration file processor. Reads lines of the form:
X * var=value
X * from a specified configuration file and stores the names and values.
X * White space WILL be considered significant, so don't put any in there
X * unless you really want it. No '=' may appear anywhere else on the line.
X *
X * SetVar(name,value) changes an existing value or creates a new one.
X * GetVar(name) returns a pointer to the value of a variable.
X * Configure(filename) processes a configuration file.
X *
X * A line in the configuration file beginning with '#' is a comment.
X * Comment lines and blank lines are skipped.
X *
X * Currently implemented with static limits for name and value length as
X * well as number of possible variables.
X *
X * History:
X * 20 Oct 90/JVE Created.
X */
X
X# include <stdio.h>
X# include <string.h>
X# include "standard.h"
X# include "configure.h"
X
X# define MAX_VARS 20
X# define MAX_NAME_LEN 10
X# define MAX_VALUE_LEN 40
X
Xstatic struct {
X char name[MAX_NAME_LEN+1]; /* name of variable */
X char value[MAX_VALUE_LEN+1]; /* its value */
X } vars[MAX_VARS];
X
Xstatic int n_vars = 0;
X
X
X/****************************************************************************/
X/* FUNCTION: Configure */
X/* */
X/* PURPOSE: Parse ARN configuration file. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* config_file I Name of configuration file to use. */
X/* */
X/* RETURNS: */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 20 Oct 90 Created. */
X/* */
X/****************************************************************************/
X
Xvoid Configure( config_file )
X
Xchar *config_file;
X
X{
XFILE *fp;
Xchar s[MAXLINE], *name, *value;
X
Xif ( ( fp = fopen( config_file, "r" ) ) == NULL )
X {
X perror( config_file );
X exit( 1 );
X }
Xwhile ( fgets( s, MAXLINE, fp ) != NULL )
X {
X s[strlen(s)-1] = NULL; /* kill trailing newline */
X if ( s[0] != '\0' && s[0] != '#' ) /* skip blank and comment lines */
X {
X if ( ( name = strtok( s, "=" ) ) == NULL )
X fprintf( stderr, "Can't parse '%s'\n", s );
X else
X {
X value = strtok( NULL, "=" );
X (void) SetVar( name, value );
X }
X }
X }
Xfclose( fp );
X}
X
X
X/****************************************************************************/
X/* FUNCTION: SetVar */
X/* */
X/* PURPOSE: Set the value of a configuration variable. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* name I Variable name. */
X/* value I Variable value. */
X/* */
X/* RETURNS: */
X/* OK Successful. */
X/* ERROR Unsuccessful. */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 20 Oct 90 Created. */
X/* */
X/****************************************************************************/
X
XSetVar( name, value )
X
Xchar *name;
Xchar *value;
X
X{
Xint i;
X
Xif ( strlen( name ) > MAX_NAME_LEN )
X name[MAX_NAME_LEN-1] = NULL;
Xif ( strlen( value ) > MAX_VALUE_LEN )
X value[MAX_VALUE_LEN-1] = NULL;
Xfor ( i = 0; i < n_vars; i++ )
X if ( strcmp( vars[i].name, name ) == 0 )
X {
X strcpy( vars[i].value, value );
X return OK;
X }
Xif ( n_vars >= MAX_VARS )
X {
X fprintf( stderr, "Too many variables!\n" );
X return ERROR;
X }
Xstrcpy( vars[i].name, name );
Xstrcpy( vars[i].value, value );
Xn_vars++;
Xreturn OK;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: GetVar */
X/* */
X/* PURPOSE: Return value of configuration variable. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* name I Name of variable. */
X/* */
X/* RETURNS: */
X/* (char *) Pointer to value. */
X/* (char *) NULL No such variable known. */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 20 Oct 90 Created. */
X/* */
X/****************************************************************************/
X
Xchar *GetVar( name )
X
Xchar *name;
X
X{
Xint i;
X
Xfor ( i = 0; i < n_vars; i++ )
X if ( strcmp( vars[i].name, name ) == 0 )
X return vars[i].value;
Xreturn NULLP( char );
X}
END_OF_FILE
if test 4912 -ne `wc -c <'configure.c'`; then
echo shar: \"'configure.c'\" unpacked with wrong size!
fi
chmod +x 'configure.c'
# end of 'configure.c'
fi
if test -f 'configure.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'configure.h'\"
else
echo shar: Extracting \"'configure.h'\" \(575 characters\)
sed "s/^X//" >'configure.h' <<'END_OF_FILE'
X/*
X * File Name: configure.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Configuration variable setting, retrieving.
X * Author: Jeff Van Epps
X * Created: 20 Oct 90
X * Last Modified: 20 Oct 90
X * Comments:
X * For implementation limits, see configure.c.
X *
X * History:
X * 20 Oct 90/JVE Created.
X */
X
X# ifdef sun
X
Xextern void Configure();
Xextern int SetVar();
Xextern char * GetVar();
X
X# else /* amiga */
X
Xextern void Configure( char *config_file );
Xextern int SetVar( char *name, char *value );
Xextern char * GetVar( char *name );
X
X# endif /* sun/amiga */
END_OF_FILE
if test 575 -ne `wc -c <'configure.h'`; then
echo shar: \"'configure.h'\" unpacked with wrong size!
fi
chmod +x 'configure.h'
# end of 'configure.h'
fi
if test -f 'kill.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kill.c'\"
else
echo shar: Extracting \"'kill.c'\" \(6070 characters\)
sed "s/^X//" >'kill.c' <<'END_OF_FILE'
X/*
X * File Name: kill.c
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Defines functions related to kill list.
X * Functions: GetKillList, PutKillList, DestroyKillList.
X * Author: Jeff Van Epps
X * Created: 04 Sep 89
X * Last Modified: 22 Oct 90
X * Comments:
X * History:
X * 04 Sep 89/JVE Created.
X * 30 Dec 89/JVE Implemented GetKillList and PutKillList, which were
X * only stubbed previously.
X * 22 Oct 90/JVE Added regular expression capability in kill files.
X * A kill list is no longer just a list of HEADER_INFOs,
X * it now has its own structure.
X */
X
X# include <stdio.h>
X# include <stdlib.h>
X# include <string.h>
X# include <fcntl.h>
X# include <regexp.h>
X# include "standard.h"
X# include "article.h"
X# include "kill.h"
X
X
X/****************************************************************************/
X/* FUNCTION: GetKillList */
X/* */
X/* PURPOSE: Parse the kill file which applies to all newsgroups. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* filename I Name of kill file. */
X/* */
X/* RETURNS: */
X/* (KILL_INFO *) Pointer to start of kill list. */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 30 Dec 89 Created. */
X/* */
X/****************************************************************************/
X
XKILL_INFO *GetKillList( filename )
X
Xchar *filename;
X
X{
XKILL_INFO *root = NULLP( KILL_INFO );
XKILL_INFO **ptr;
XFILE *fp;
X
Xif ( ( fp = fopen( filename, "r" ) ) != NULLP( FILE ) )
X {
X ptr = &root;
X while ( GetNextKill( fp, &ptr ) ) ;
X fclose( fp );
X }
Xreturn root;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: PutKillList */
X/* */
X/* PURPOSE: Write back a kill list to specified file. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* filename I File in which to put kill list. */
X/* root I Pointer to start of kill list. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 30 Dec 89 Created. */
X/* */
X/****************************************************************************/
X
Xvoid PutKillList( filename, root )
X
Xchar *filename;
XKILL_INFO *root;
X
X{
XFILE *fp;
X
Xremove( filename );
Xif ( ( fp = fopen( filename, "a" ) ) != NULLP( FILE ) )
X {
X while ( root != NULLP( KILL_INFO ) )
X {
X fprintf( fp, "%s: %s\n", root->fieldname, root->fieldvalue );
X root = root->next;
X }
X fclose( fp );
X }
X}
X
X
X/****************************************************************************/
X/* FUNCTION: DestroyKillList */
X/* */
X/* PURPOSE: Release memory consumed by construction of kill list. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* root I Pointer to start of kill list. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 04 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
Xvoid DestroyKillList( root )
X
XKILL_INFO *root;
X
X{
XKILL_INFO *tmp;
X
Xfor ( ; root != NULLP( KILL_INFO ); root = tmp )
X {
X tmp = root->next;
X free( root -> fieldname );
X free( root -> fieldvalue );
X free( (char *) ( root -> pattern ) );
X free( root );
X }
X}
X
X/****************************************************************************/
X/* FUNCTION: GetNextKill */
X/* */
X/* PURPOSE: Parses the next kill entry from a kill file. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* fp I FILE pointer to file containing article. */
X/* hdr I/O Where to put pointer to newly allocated */
X/* KILL_INFO structure if we allocate one. */
X/* */
X/* RETURNS: */
X/* TRUE Successfully parsed another entry from file. */
X/* FALSE Failed/no more entries. */
X/* */
X/* COMMENTS: */
X/* Adjusts hdr when done so next call will set correct pointer. */
X/* */
X/* HISTORY: */
X/* 1. 22 Oct 90 Created from GetNextHeader. */
X/* */
X/****************************************************************************/
X
XGetNextKill( fp, hdr )
X
XFILE *fp;
XKILL_INFO ***hdr;
X
X{
Xint rc; /* return code from function */
Xchar buf[BUFSIZ]; /* holds input line from article */
Xchar *firstspace, *firstcolon, *data; /* for parsing */
X
Xif ( fgets( buf, BUFSIZ, fp ) == NULL )
X rc = FALSE;
Xelse
X {
X firstspace = strchr( buf, ' ' );
X firstcolon = strchr( buf, ':' );
X if ( ( firstcolon == NULL ) ||
X ( ( firstspace != NULL ) && ( firstspace < firstcolon ) ) )
X rc = FALSE;
X else
X {
X *firstcolon = NULL; /* terminate fieldname string */
X firstcolon++; /* advance past colon/NULL to value string */
X data = firstcolon + strspn( firstcolon, " \t" ); /* skip white */
X data[strlen(data)-1] = NULL; /* remove trailing newline */
X
X /*
X * Allocate and fill a new kill structure.
X */
X
X **hdr = (KILL_INFO *) malloc( sizeof( KILL_INFO ) );
X (**hdr)->fieldname = strdup( buf );
X (**hdr)->fieldvalue = strdup( data );
X (**hdr)->pattern = regcomp( data );
X if ( (**hdr) -> pattern == NULL )
X fprintf( stderr, "Bad kill pattern '%s'\n", data );
X (**hdr)->next = NULLP( KILL_INFO );
X
X /*
X * Reset the hdr pointer so next call will continue chain correctly.
X */
X
X *hdr = &((**hdr)->next);
X rc = TRUE;
X }
X }
Xreturn rc;
X}
END_OF_FILE
if test 6070 -ne `wc -c <'kill.c'`; then
echo shar: \"'kill.c'\" unpacked with wrong size!
fi
chmod +x 'kill.c'
# end of 'kill.c'
fi
if test -f 'kill.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'kill.h'\"
else
echo shar: Extracting \"'kill.h'\" \(918 characters\)
sed "s/^X//" >'kill.h' <<'END_OF_FILE'
X/*
X * File Name: kill.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Define kill structures.
X * Author: Jeff Van Epps
X * Created: 04 Sep 89
X * Last Modified: 22 Oct 90
X * Comments:
X * Include "regexp.h" before "kill.h".
X *
X * History:
X * 04 Sep 89/JVE Created.
X * 22 Oct 90/JVE New KILL_INFO structure includes regexp pattern.
X */
X
X/*
X * A kill list is a list of kill_info structures. An article matching any
X * kill structure will be "killed".
X */
X
Xtypedef struct kill_info {
X char *fieldname;
X char *fieldvalue;
X struct regexp *pattern;
X struct kill_info *next; /* ptr to next article in newsgroup */
X } KILL_INFO;
X
X/*
X * Function prototypes.
X */
X
X# ifdef sun
X
XKILL_INFO *GetKillList();
Xvoid PutKillList();
Xvoid DestroyKillList();
X
X# else
X
XKILL_INFO *GetKillList( char *filename );
Xvoid PutKillList( char *filename, KILL_INFO *root );
Xvoid DestroyKillList( KILL_INFO *root );
X
X# endif
END_OF_FILE
if test 918 -ne `wc -c <'kill.h'`; then
echo shar: \"'kill.h'\" unpacked with wrong size!
fi
chmod +x 'kill.h'
# end of 'kill.h'
fi
if test -f 'ng.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ng.c'\"
else
echo shar: Extracting \"'ng.c'\" \(11353 characters\)
sed "s/^X//" >'ng.c' <<'END_OF_FILE'
X/*
X * File Name: ng.c
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Defines functions related to newsgroup list.
X * Functions: GetNewsRC, ReadNextMarker, PutNewsRC, DestroyNGList,
X * NumberCovered, UpdateReadList, Mark.
X * Author: Jeff Van Epps
X * Created: 03 Sep 89
X * Last Modified: 14 Nov 90
X * Comments:
X * History:
X * 03 Sep 89/JVE Created.
X * 21 Oct 90/JVE Moved UpdateReadList, Mark from arn.c to here where
X * they belong.
X * 14 Nov 90/JVE Made sure a marker for article 0 gets created if
X * no other articles have been read.
X */
X
X# include <stdio.h>
X# include <stdlib.h>
X# include <string.h>
X# include <fcntl.h>
X# include "standard.h"
X# include "article.h"
X# include "ng.h"
X
X
X/****************************************************************************/
X/* FUNCTION: GetNewsRC */
X/* */
X/* PURPOSE: Read/parse the .newsrc file. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* filename I Name of file containing read newsgroups info. */
X/* */
X/* RETURNS: */
X/* */
X/* COMMENTS: */
X/* Parses lines from user's .newsrc file to see which articles in */
X/* which newsgroups have already been read. */
X/* */
X/* HISTORY: */
X/* 1. 03 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
XNG_INFO *GetNewsRC( filename )
X
Xchar *filename;
X
X{
XNG_INFO *root = NULLP( NG_INFO ); /* points to start of ng list */
XNG_INFO **ptr = &root; /* where to alloc next ng from */
XMARKER **marker; /* where to alloc next marker from */
XFILE *fp; /* pointer into .newsrc file */
Xchar buf[BUFSIZ];
Xchar *name; /* newsgroup name */
X
Xif ( ( fp = fopen( filename, "r" ) ) == NULLP( FILE ) )
X perror( filename );
Xelse
X {
X while ( fgets( buf, BUFSIZ, fp ) != NULLP( char ) )
X {
X if ( ( name = strtok( buf, " " ) ) == NULLP( char ) )
X fprintf( stderr, "Bad line in %s: %s", filename, buf );
X else
X {
X *ptr = (NG_INFO *) malloc( sizeof( NG_INFO ) );
X (*ptr)->next = NULLP( NG_INFO );
X (*ptr)->markers = NULLP( MARKER );
X marker = &(*ptr)->markers;
X while ( ReadNextMarker( &marker ) ) ;
X (*ptr)->name = strdup( name );
X ptr = &(*ptr)->next;
X }
X }
X fclose( fp );
X }
Xreturn root;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: ReadNextMarker */
X/* */
X/* PURPOSE: Parse next marker from line. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* marker I/O Pointer to pointer to next marker. */
X/* */
X/* RETURNS: */
X/* TRUE Marker parsed. */
X/* FALSE No marker parsed (end of input line). */
X/* */
X/* COMMENTS: */
X/* markers = [ marker | marker + ',' + markers ] */
X/* marker = [ XXX | XXX + '-' + YYY ] */
X/* */
X/* There may be a list of markers with each marker separated by a */
X/* comma. Each marker may be either a single number or two numbers */
X/* separated by a dash indicating an inclusive range. White space */
X/* is not allowed anywhere. */
X/* */
X/* We assume that the string we are parsing has already been subject */
X/* to a strtok() call so that we can just strtok(NULL,x) to continue */
X/* parsing the same string. */
X/* */
X/* HISTORY: */
X/* 1. 03 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
XReadNextMarker( marker )
X
XMARKER ***marker;
X
X{
Xint rc = FALSE;
Xchar *p, *q;
X
Xif ( ( p = strtok( NULLP( char ), "," ) ) != NULLP( char ) )
X {
X **marker = (MARKER *) malloc( sizeof( MARKER ) );
X (**marker)->next = NULLP( MARKER );
X (**marker)->from = atol( p );
X if ( ( q = strchr( p, '-' ) ) != NULLP( char ) )
X (**marker)->to = atol( ++q );
X else
X (**marker)->to = 0L;
X *marker = &(**marker)->next;
X rc = TRUE;
X }
Xreturn rc;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: PutNewsRC */
X/* */
X/* PURPOSE: Write read article markers to .newsrc file. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* filename I Name of file to which to write .newsrc info. */
X/* root I List of already read articles. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* Tries to save old .newsrc file as .newsrc.BAK before writing new */
X/* one. */
X/* */
X/* HISTORY: */
X/* 1. 03 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
Xvoid PutNewsRC( filename, root )
X
Xchar *filename;
XNG_INFO *root;
X
X{
Xchar backup[BUFSIZ], temp[BUFSIZ];
XFILE *fp;
XMARKER *ptr;
X
Xsprintf( backup, "%s.BAK", filename );
X(void) remove( backup );
Xif ( rename( filename, backup ) )
X {
X sprintf( temp, "rename(%s,%s)", filename, backup );
X perror( temp );
X }
Xelse
X {
X if ( ( fp = fopen( filename, "a" ) ) == NULLP( FILE ) )
X perror( filename );
X else
X {
X while ( root != NULLP( NG_INFO ) )
X {
X fprintf( fp, "%s ", root->name );
X for ( ptr = root->markers; ptr != NULLP( MARKER ); )
X {
X fprintf( fp, "%ld", ptr->from );
X if ( ptr->to > 0L )
X fprintf( fp, "-%ld", ptr->to );
X if ( ptr = ptr->next )
X fprintf( fp, "," );
X }
X fprintf( fp, "\n" );
X root = root->next;
X }
X fclose( fp );
X }
X }
X}
X
X
X/****************************************************************************/
X/* FUNCTION: DestroyNGList */
X/* */
X/* PURPOSE: Free memory taken by newsgroup list. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* root I Pointer to list of newsgroups. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 03 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
Xvoid DestroyNGList( root )
X
XNG_INFO *root;
X
X{
XMARKER *ptr, *tmp;
XNG_INFO *next;
X
Xwhile ( root != NULLP( NG_INFO ) )
X {
X for ( ptr = root->markers; ptr != NULLP( MARKER ); ptr = tmp )
X {
X tmp = ptr->next;
X free( ptr );
X }
X free( root->name );
X next = root->next;
X free( root );
X root = next;
X }
X}
X
X
X/****************************************************************************/
X/* FUNCTION: NumberCovered */
X/* */
X/* PURPOSE: Check whether number is covered by markers. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* markers I Marker list. */
X/* number I Number to be checked. */
X/* */
X/* RETURNS: */
X/* TRUE If number is in list. */
X/* FALSE If number is not in list. */
X/* */
X/* COMMENTS: */
X/* Markers are assumed to be sorted low->high and non-overlapping. */
X/* */
X/* HISTORY: */
X/* 1. 04 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
XNumberCovered( markers, number )
X
XMARKER *markers;
Xlong number;
X
X{
Xint rc = FALSE;
X
Xwhile ( !rc && markers != NULLP( MARKER ) )
X {
X if ( markers->from > number )
X break;
X else if ( markers->from == number )
X rc = TRUE;
X else if ( markers->to >= number )
X rc = TRUE;
X markers = markers->next;
X }
Xreturn rc;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: UpdateReadList */
X/* */
X/* PURPOSE: Update the list of articles read due to newly read ones. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* ng I/O List of read articles. */
X/* new I List containing some newly read articles. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* Look for articles which are STILL unread, and make a list which */
X/* marks everything except those. If nothing is left unread, the list */
X/* should mark to the greater of the previously highest read article */
X/* and the highest newly read article. */
X/* */
X/* HISTORY: */
X/* 1. 04 Sep 89 Created. */
X/* 2. 16 Dec 89 Fixed bug in last mark if last article unread. */
X/* 3. 14 Nov 90 Make sure *something* gets marked, i.e. 0-0 if */
X/* nothing else. */
X/* */
X/****************************************************************************/
X
Xvoid UpdateReadList( ng, new )
X
XNG_INFO *ng;
XARTICLE_INFO *new;
X
X{
Xlong beginning, ending;
XMARKER **where; /* where to allocate next marker */
XMARKER *first = NULL; /* ptr to beginning of new marker list */
XMARKER *ptr, *tmp;
X
Xfor ( ptr = ng->markers; ptr != NULLP( MARKER ); ptr = tmp )
X {
X if ( ptr->to != 0L )
X ending = ptr->to;
X else
X ending = ptr->from;
X tmp = ptr->next;
X free( ptr );
X }
Xbeginning = 1L;
Xwhere = &first;
Xfor ( ; new != NULLP( ARTICLE_INFO ); new = new->next )
X {
X if ( ! new->beenread )
X {
X if ( new->number != beginning && beginning <= ending )
X {
X *where = Mark( beginning, new->number - 1L );
X where = & (*where)->next;
X }
X beginning = new->number + 1L;
X }
X else if ( new->number > ending )
X ending = new->number;
X }
Xif ( beginning <= ending )
X *where = Mark( beginning, ending );
X/*
X * If no markers have been created, create one for article # 0.
X */
Xif ( first == NULL )
X *where = Mark( 0L, 0L );
Xng->markers = first;
X}
X
X
X/****************************************************************************/
X/* FUNCTION: Mark */
X/* */
X/* PURPOSE: Create a marker. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* begin I From part of marker. */
X/* end I To part of marker. */
X/* */
X/* RETURNS: */
X/* (MARKER *) Pointer to new marker. */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 05 Sep 89 Created. */
X/* */
X/****************************************************************************/
X
XMARKER *Mark( begin, end )
X
Xlong begin, end;
X
X{
XMARKER *ptr;
X
Xptr = (MARKER *) malloc( sizeof( MARKER ) );
Xptr->from = begin;
Xif ( begin == end )
X ptr->to = 0L;
Xelse
X ptr->to = end;
Xptr->next = NULLP( MARKER );
Xreturn ptr;
X}
X
END_OF_FILE
if test 11353 -ne `wc -c <'ng.c'`; then
echo shar: \"'ng.c'\" unpacked with wrong size!
fi
chmod +x 'ng.c'
# end of 'ng.c'
fi
if test -f 'ng.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'ng.h'\"
else
echo shar: Extracting \"'ng.h'\" \(1491 characters\)
sed "s/^X//" >'ng.h' <<'END_OF_FILE'
X/*
X * File Name: ng.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Define newsgroup structures.
X * Author: Jeff Van Epps
X * Created: 02 Sep 89
X * Last Modified: 21 Oct 90
X * History:
X * 02 Sep 89/JVE Created.
X * 21 Oct 90/JVE Added declarations for UpdateReadList, Mark.
X */
X
X/*
X * MARKER is used to mark either a single number or a range. If to==0,
X * from indicates the single number to be marked. Otherwise all numbers
X * between and including from and to should be marked.
X */
X
Xtypedef struct marker_info {
X long from, to; /* article numbers */
X struct marker_info *next; /* pointer to next marker record */
X } MARKER;
X
X/*
X * NG_INFO records names of newsgroups and which articles have been read
X * in each newsgroup.
X */
X
Xtypedef struct ng_info {
X char *name; /* name of newsgroup */
X MARKER *markers; /* ptr to list of article #s read */
X struct ng_info *next; /* ptr to next newsgroup in list */
X } NG_INFO;
X
X/*
X * Function prototypes.
X */
X
X# ifdef sun
X
XNG_INFO *GetNewsRC();
Xint ReadNextMarker();
Xvoid PutNewsRC();
Xvoid DestroyNGList();
Xint NumberCovered();
Xvoid UpdateReadList();
XMARKER * Mark();
X
X# else
X
XNG_INFO *GetNewsRC( char *filename );
Xint ReadNextMarker( MARKER ***marker );
Xvoid PutNewsRC( char *filename, NG_INFO *alreadyread );
Xvoid DestroyNGList( NG_INFO *alreadyread );
Xint NumberCovered( MARKER *marker, long number );
Xvoid UpdateReadList( NG_INFO *ng, ARTICLE_INFO *new );
XMARKER * Mark( long begin, long end );
X
X# endif
END_OF_FILE
if test 1491 -ne `wc -c <'ng.h'`; then
echo shar: \"'ng.h'\" unpacked with wrong size!
fi
chmod +x 'ng.h'
# end of 'ng.h'
fi
if test -f 'raw.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'raw.c'\"
else
echo shar: Extracting \"'raw.c'\" \(2268 characters\)
sed "s/^X//" >'raw.c' <<'END_OF_FILE'
X/*
X * raw.c
X *
X * This is a routine for setting a given stream to raw or cooked mode on the
X * Amiga . This is useful when you are using Lattice C to produce programs
X * that want to read single characters with the "getch()" or "fgetc" call.
X *
X * Written : 18-Jun-87 By Chuck McManis.
X */
X#include <exec/types.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <stdio.h>
X
X#include <ios1.h>
X#include <error.h>
X
Xextern int errno; /* The error variable */
X
X/*
X * Function raw() - Convert the specified file pointer to 'raw' mode. This
X * only works on TTY's and essentially keeps DOS from translating keys for
X * you, also (BIG WIN) it means getch() will return immediately rather than
X * wait for a return. You lose editing features though.
X */
Xlong
Xraw(fp)
X FILE *fp;
X
X{
X struct MsgPort *mp; /* The File Handle message port */
X struct FileHandle *afh;
X struct UFB *ufb;
X long Arg[1], res;
X
X ufb = (struct UFB *) chkufb(fileno(fp)); /* Step one, get the file
X * handle */
X afh = (struct FileHandle *) (ufb->ufbfh);
X
X if (!IsInteractive(afh)) { /* Step two, check to see if it's a console */
X errno = ENOTTY;
X return (-1);
X }
X /* Step three, get it's message port. */
X mp = ((struct FileHandle *) (BADDR(afh)))->fh_Type;
X Arg[0] = -1L;
X res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1); /* Put it in RAW: mode */
X if (res == 0) {
X errno = ENXIO;
X return (-1);
X }
X return (0);
X}
X
X/*
X * Function - cooked() this function returns the designate file pointer to
X * it's normal, wait for a <CR> mode. This is exactly like raw() except that
X * it sends a 0 to the console to make it back into a CON: from a RAW:
X */
X
Xlong
Xcooked(fp)
X FILE *fp;
X
X{
X struct MsgPort *mp; /* The File Handle message port */
X struct FileHandle *afh;
X struct UFB *ufb;
X long Arg[1], res;
X
X ufb = (struct UFB *) chkufb(fileno(fp));
X afh = (struct FileHandle *) (ufb->ufbfh);
X if (!IsInteractive(afh)) {
X errno = ENOTTY;
X return (-1);
X }
X mp = ((struct FileHandle *) (BADDR(afh)))->fh_Type;
X Arg[0] = 0;
X res = SendPacket(mp, ACTION_SCREEN_MODE, Arg, 1);
X if (res == 0) {
X errno = ENXIO;
X return (-1);
X }
X return (0);
X}
END_OF_FILE
if test 2268 -ne `wc -c <'raw.c'`; then
echo shar: \"'raw.c'\" unpacked with wrong size!
fi
chmod +x 'raw.c'
# end of 'raw.c'
fi
if test -f 'reply.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'reply.c'\"
else
echo shar: Extracting \"'reply.c'\" \(8860 characters\)
sed "s/^X//" >'reply.c' <<'END_OF_FILE'
X/*
X * File Name: reply.c
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Reply via email and post followup article functions.
X * Functions: Reply, Followup, IncludeArticle, Sign.
X * Author: Jeff Van Epps
X * Created: 21 Oct 90
X * Last Modified: 05 Jan 91
X * Comments:
X * History:
X * 21 Oct 90/JVE Created.
X * 14 Nov 90/JVE Post news by mailing article to inews@bisco rather
X * than <newsgroup>@ucbvax.berkeley.edu. Only mail the
X * article if the user saved his edit. Same for
X * email replies.
X * 05 Jan 91/JVE Use article->subject optimization.
X */
X
X# include <stdio.h>
X# include <stdlib.h>
X# include <string.h>
X# include <time.h>
X# include <sys/types.h>
X# include <sys/stat.h>
X# include "standard.h"
X# include "configure.h"
X# include "variables.h"
X# include "article.h"
X# include "reply.h"
X
X# ifdef sun
X
X# define DEFAULT_EDITOR "vi"
X# define TEMPFILE "/tmp/arnreply"
X
X# else /* not sun */
X
X# define DEFAULT_EDITOR "stevie"
X# define TEMPFILE "T:arnreply"
X
X# endif /* sun */
X
X
X/****************************************************************************/
X/* FUNCTION: Reply */
X/* */
X/* PURPOSE: Send a reply to a news article via mail. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* article I Article to reply to. */
X/* include I Include article in reply? */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 17 Oct 90 Created. */
X/* 2. 14 Nov 90 Do not invoke mailer if user has not edited. */
X/* */
X/****************************************************************************/
X
Xvoid Reply( article, include )
X
XARTICLE_INFO *article;
Xint include;
X
X{
XFILE *fp;
Xchar *from, *address, *editor, *hdr;
Xchar cmd[MAXLINE], temp[MAXLINE];
Xlong clock; /* current date & time */
Xint header_found = FALSE; /* parsed To: yet? */
Xstruct stat stats_before, stats_after;
X
Xremove( TEMPFILE );
Xif ( ( fp = fopen( TEMPFILE, "a" ) ) == NULL )
X {
X perror( TEMPFILE );
X return;
X }
Xtime( &clock );
Xfprintf( fp, "From %s %24.24s remote from %s\n", GetVar( VAR_USER),
X ctime( &clock ), GetVar( VAR_NODE ) );
Xfprintf( fp, "Date: %s", ctime( &clock ) );
Xfprintf( fp, "From: %s!%s@%s (%s)\n", GetVar( VAR_NODE ), GetVar( VAR_USER ),
X GetVar( VAR_DOMAIN ), GetVar( VAR_NAME ) );
X/*
X * Use everything after From: up to the first space.
X */
Xfrom = strtok( GetHeader( article -> headers, HDR_FROM ), " \n\r" );
Xfprintf( fp, "%s: %s\n", HDR_TO, from );
Xfprintf( fp, "%s: \n", HDR_CC );
Xfprintf( fp, "%s: %s\n\n", HDR_SUBJECT, article -> subject );
Xif ( include )
X IncludeArticle( article, fp );
XSign( fp );
Xfclose( fp );
X(void) stat( TEMPFILE, &stats_before );
Xif ( ( editor = GetVar( VAR_EDITOR ) ) == NULL )
X editor = DEFAULT_EDITOR;
Xsprintf( cmd, "%s %s", editor, TEMPFILE );
Xsystem( cmd );
X(void) stat( TEMPFILE, &stats_after );
Xif ( stats_after.st_mtime != stats_before.st_mtime )
X {
X if ( ( fp = fopen( TEMPFILE, "r" ) ) == NULL )
X {
X perror( TEMPFILE );
X return;
X }
X while ( ! header_found && fgets( temp, MAXLINE, fp ) != NULL )
X {
X if ( ( hdr = strtok( temp, ": " ) ) != NULL && strcmp( hdr, HDR_TO ) == 0 )
X header_found = TRUE;
X }
X if ( ! header_found )
X {
X printf( "Header messed!\n" );
X fclose( fp );
X return;
X }
X if ( ( address = strtok( NULL, " " ) ) == NULL )
X {
X printf( "No address given!\n" );
X fclose( fp );
X return;
X }
X fclose( fp );
X sprintf( cmd, "rmail <%s >NULL: %s", TEMPFILE, address );
X system( cmd );
X }
Xelse
X {
X printf( "File not modified. Mail not sent. Hit any key.\n" );
X getchar();
X }
Xremove( TEMPFILE );
X}
X
X/****************************************************************************/
X/* FUNCTION: Followup */
X/* */
X/* PURPOSE: Post news article as a reply to a news article. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* newsgroup I Name of newsgroup. */
X/* article I Article to followup. */
X/* include I Include article in reply? */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* Changed to send mail to inews@bisco. Newsgroup name is embedded */
X/* in the article. */
X/* */
X/* The newsgroup name has all dots or slashes turned into dashes, then */
X/* mail is sent to <modified newsgroup name>@ucbvax.berkeley.edu, */
X/* which is a gateway for posting. */
X/* */
X/* HISTORY: */
X/* 1. 17 Oct 90 Created. */
X/* 2. 14 Nov 90 Mail to bisco rather than Berkeley. Only */
X/* mail the article if it has been edited by user. */
X/* */
X/****************************************************************************/
X
Xvoid Followup( newsgroup, article, include )
X
Xchar *newsgroup;
XARTICLE_INFO *article;
Xint include;
X
X{
XFILE *fp;
Xchar *editor;
Xchar cmd[MAXLINE];
Xlong clock; /* current date & time */
Xstruct stat stats_before, stats_after;
X
Xremove( TEMPFILE );
Xif ( ( fp = fopen( TEMPFILE, "a" ) ) == NULL )
X {
X perror( TEMPFILE );
X return;
X }
Xtime( &clock );
Xfprintf( fp, "From %s %24.24s remote from %s\n", GetVar( VAR_USER ),
X ctime( &clock ), GetVar( VAR_NODE ) );
Xfprintf( fp, "Date: %s", ctime( &clock ) );
Xfprintf( fp, "From: %s!%s@%s (%s)\n", GetVar( VAR_NODE ), GetVar( VAR_USER ),
X GetVar( VAR_DOMAIN ), GetVar( VAR_NAME ) );
Xfprintf( fp, "%s: %s\n", HDR_SUBJECT, article -> subject );
Xfprintf( fp, "Newsgroups: %s\n", newsgroup );
Xfprintf( fp, "Followup-To: %s\n", newsgroup );
Xfprintf( fp, "Distribution: world\n" );
Xfprintf( fp, "Reply-To: %s!%s@%s\n", GetVar( VAR_NODE ), GetVar( VAR_USER ),
X GetVar( VAR_DOMAIN ) );
Xfprintf( fp, "\n" ); /* separate headers from body of article */
Xif ( include )
X IncludeArticle( article, fp );
XSign( fp );
Xfclose( fp );
X(void) stat( TEMPFILE, &stats_before );
Xif ( ( editor = GetVar( VAR_EDITOR ) ) == NULL )
X editor = DEFAULT_EDITOR;
Xsprintf( cmd, "%s %s", editor, TEMPFILE );
Xsystem( cmd );
X(void) stat( TEMPFILE, &stats_after );
Xif ( stats_after.st_mtime != stats_before.st_mtime )
X {
X sprintf( cmd, "rmail <%s >NULL: inews@bisco", TEMPFILE );
X system( cmd );
X }
Xelse
X {
X printf( "File not modified. Article not posted. Hit any key.\n" );
X getchar();
X }
Xremove( TEMPFILE );
X}
X
X
X/****************************************************************************/
X/* FUNCTION: IncludeArticle */
X/* */
X/* PURPOSE: Copy article text to file as an inclusion. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* article I Article being included. */
X/* output I File being written into. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* */
X/* HISTORY: */
X/* 1. 21 Oct 90 Created. */
X/* */
X/****************************************************************************/
X
Xvoid IncludeArticle( article, output )
X
XARTICLE_INFO *article;
XFILE *output;
X
X{
Xchar filename[MAXLINE];
Xchar s[MAXLINE];
XFILE *art;
X
Xsprintf( filename, "%ld", article -> number );
Xif ( ( art = fopen( filename, "r" ) ) == NULL )
X printf( "CAN'T OPEN ARTICLE FOR INCLUDE!\n" );
Xelse
X {
X fseek( art, article -> textpos, 0 );
X while ( fgets( s, MAXLINE, art ) != NULL )
X fprintf( output, "> %s", s );
X fclose( art );
X }
X}
X
X
X/****************************************************************************/
X/* FUNCTION: Sign */
X/* */
X/* PURPOSE: Append users .signature. */
X/* */
X/* INPUT PARAMETERS: */
X/* NAME I/O DESCRIPTION */
X/* ---- --- ----------- */
X/* output I File being written to. */
X/* */
X/* RETURNS: none */
X/* */
X/* COMMENTS: */
X/* There is no default .signature file. */
X/* */
X/* HISTORY: */
X/* 1. 21 Oct 90 Created. */
X/* */
X/****************************************************************************/
X
Xvoid Sign( output )
X
XFILE *output;
X
X{
XFILE *sig;
Xchar *sig_file; /* filename for .signature */
Xchar s[MAXLINE];
X
Xif ( ( sig_file = GetVar( VAR_SIGN ) ) != NULL &&
X ( sig = fopen( sig_file, "r" ) ) != NULL )
X {
X while ( fgets( s, MAXLINE, sig ) != NULL )
X fprintf( output, "%s", s );
X fclose( sig );
X }
X}
END_OF_FILE
if test 8860 -ne `wc -c <'reply.c'`; then
echo shar: \"'reply.c'\" unpacked with wrong size!
fi
chmod +x 'reply.c'
# end of 'reply.c'
fi
if test -f 'reply.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'reply.h'\"
else
echo shar: Extracting \"'reply.h'\" \(644 characters\)
sed "s/^X//" >'reply.h' <<'END_OF_FILE'
X/*
X * File Name: reply.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Reply and Followup functions.
X * Author: Jeff Van Epps
X * Created: 21 Oct 90
X * Last Modified: 21 Oct 90
X * Comments:
X * History:
X * 21 Oct 90/JVE Created.
X */
X
X# ifdef sun
X
Xextern void Reply();
Xextern void Followup();
Xextern void IncludeArticle();
Xextern void Sign();
X
X# else /* amiga */
X
Xextern void Reply( ARTICLE_INFO *article, int include );
Xextern void Followup( char *newsgroup, ARTICLE_INFO *article, int include );
Xextern void IncludeArticle( ARTICLE_INFO *article, FILE *output );
Xextern void Sign( FILE *output );
X
X# endif /* sun/amiga */
END_OF_FILE
if test 644 -ne `wc -c <'reply.h'`; then
echo shar: \"'reply.h'\" unpacked with wrong size!
fi
chmod +x 'reply.h'
# end of 'reply.h'
fi
if test -f 'screenstuff.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'screenstuff.h'\"
else
echo shar: Extracting \"'screenstuff.h'\" \(871 characters\)
sed "s/^X//" >'screenstuff.h' <<'END_OF_FILE'
X/*
X * File Name: screenstuff.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Screen attribute defines.
X * Author: Jeff Van Epps
X * Created: 06 Jan 91
X * Last Modified: 06 Jan 91
X * Comments:
X * If compiling on a Sun we try to use the System V version of the
X * curses library. On the Amiga we use ANSI sequences.
X *
X * History:
X * 06 Jan 91/JVE Created.
X */
X
X
X# ifdef sun
X
X# include <curses.h>
X# define Clear_Screen clear()
X# define UL_ON attron( A_UNDERLINE )
X# define UL_OFF attroff( A_UNDERLINE )
X# define INVERSE_ON attron( A_REVERSE )
X# define INVERSE_OFF attroff( A_REVERSE )
X
X# else /* not sun */
X
X# define Clear_Screen printf("\x1b[H\x1b[2J")
X# define UL_ON printf( "\x1b[4m" )
X# define UL_OFF printf( "\x1b[0m" )
X# define INVERSE_ON printf("\x9b\x37;38;40m")
X# define INVERSE_OFF printf("\x9b\x30;33;40m\033[0m")
X
X# endif /* sun */
END_OF_FILE
if test 871 -ne `wc -c <'screenstuff.h'`; then
echo shar: \"'screenstuff.h'\" unpacked with wrong size!
fi
chmod +x 'screenstuff.h'
# end of 'screenstuff.h'
fi
if test -f 'sendpacket.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sendpacket.c'\"
else
echo shar: Extracting \"'sendpacket.c'\" \(2093 characters\)
sed "s/^X//" >'sendpacket.c' <<'END_OF_FILE'
X/*
X * Sendpacket.c
X *
X * An invaluable addition to your Amiga.lib file. This code sends a packet the
X * given message port. This makes working around DOS lots easier.
X *
X * Note, I didn't write this, those wonderful folks at CBM did. I do suggest
X * however that you may wish to add it to Amiga.Lib, to do so, compile it and
X * say 'oml lib:amiga.lib -r sendpacket.o'
X */
X
X#include <exec/types.h>
X#include <exec/ports.h>
X#include <exec/memory.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X
X/*
X * Function - SendPacket written by Phil Lindsay, Carolyn Scheppner, and Andy
X * Finkel. This function will send a packet of the given type to the Message
X * Port supplied.
X */
X
Xlong
XSendPacket(pid, action, args, nargs)
X struct MsgPort *pid; /* process indentifier ... (handlers message
X * port ) */
X long action, /* packet type ... (what you want handler to
X * do ) */
X args[], /* a pointer to a argument list */
X nargs; /* number of arguments in list */
X{
X struct MsgPort *replyport;
X struct StandardPacket *packet;
X
X long count, *pargs, res1;
X
X replyport = (struct MsgPort *) CreatePort(NULL, 0);
X if (!replyport)
X return (0);
X
X /* Allocate space for a packet, make it public and clear it */
X packet = (struct StandardPacket *)
X AllocMem((long) sizeof(struct StandardPacket), MEMF_PUBLIC | MEMF_CLEAR);
X if (!packet) {
X DeletePort(replyport);
X return (0);
X }
X packet->sp_Msg.mn_Node.ln_Name = (char *) &(packet->sp_Pkt);
X packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
X packet->sp_Pkt.dp_Port = replyport;
X packet->sp_Pkt.dp_Type = action;
X
X /* copy the args into the packet */
X pargs = &(packet->sp_Pkt.dp_Arg1); /* address of first argument */
X for (count = 0; count < nargs; count++)
X pargs[count] = args[count];
X
X PutMsg(pid, packet); /* send packet */
X
X WaitPort(replyport);
X GetMsg(replyport);
X
X res1 = packet->sp_Pkt.dp_Res1;
X
X FreeMem(packet, (long) sizeof(struct StandardPacket));
X DeletePort(replyport);
X
X return (res1);
X}
END_OF_FILE
if test 2093 -ne `wc -c <'sendpacket.c'`; then
echo shar: \"'sendpacket.c'\" unpacked with wrong size!
fi
chmod +x 'sendpacket.c'
# end of 'sendpacket.c'
fi
if test -f 'standard.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'standard.h'\"
else
echo shar: Extracting \"'standard.h'\" \(535 characters\)
sed "s/^X//" >'standard.h' <<'END_OF_FILE'
X/*
X * File: standard.h
X * Purpose: Stuff I standardly use.
X * Functions:
X * Created: 25 Nov 1988
X * Last Modified: 19 Oct 1990
X * Comments:
X * History:
X * 19 Oct 90/JVE Added ifdef sun.
X */
X
X/*
X * NULL pointer to some type.
X */
X
X# define NULLP( typ ) ( (typ *) 0 )
X
X# undef ERROR
X# define ERROR ( -1 )
X# undef OK
X# define OK 0
X
X# undef TRUE
X# define TRUE 1
X# undef FALSE
X# define FALSE 0
X
X# define MAXLINE 255
X
X# ifdef sun
X
X/*
X * Delete file.
X */
X
X# define remove( x ) unlink( (x) )
X
X# endif
END_OF_FILE
if test 535 -ne `wc -c <'standard.h'`; then
echo shar: \"'standard.h'\" unpacked with wrong size!
fi
chmod +x 'standard.h'
# end of 'standard.h'
fi
if test -f 'trim.sksh' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'trim.sksh'\"
else
echo shar: Extracting \"'trim.sksh'\" \(199 characters\)
sed "s/^X//" >'trim.sksh' <<'END_OF_FILE'
X# Delete news articles over one day old.
Xlc:touch .news* arn.config trim.sksh
Xlc:touch save/*
Xfind uunews: -name "KILL*" -exec lc:touch "{}" ";"
Xfind uunews: -mtime +1 -type f -exec delete "{}" ";"
X
END_OF_FILE
if test 199 -ne `wc -c <'trim.sksh'`; then
echo shar: \"'trim.sksh'\" unpacked with wrong size!
fi
chmod +x 'trim.sksh'
# end of 'trim.sksh'
fi
if test -f 'variables.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'variables.h'\"
else
echo shar: Extracting \"'variables.h'\" \(635 characters\)
sed "s/^X//" >'variables.h' <<'END_OF_FILE'
X/*
X * File Name: variables.h
X * Project: BARN - Bah's Amiga ReadNews.
X * Purpose: Define names of configuration variables.
X * Author: Jeff Van Epps
X * Created: 20 Oct 90
X * Last Modified: 25 Nov 90
X * Comments:
X * History:
X * 20 Oct 90/JVE Created.
X * 25 Nov 90/JVE Added noscroll.
X */
X
X# define VAR_USER "user"
X# define VAR_NODE "node"
X# define VAR_DOMAIN "domain"
X# define VAR_EDITOR "editor"
X# define VAR_NAME "name"
X# define VAR_NEWSRC "newsrc"
X# define VAR_KILL "kill"
X# define VAR_SIGN "signature"
X# define VAR_BBS "bbs"
X# define VAR_LINES "lines"
X# define VAR_COLS "columns"
X# define VAR_NOSCROLL "noscroll"
END_OF_FILE
if test 635 -ne `wc -c <'variables.h'`; then
echo shar: \"'variables.h'\" unpacked with wrong size!
fi
chmod +x 'variables.h'
# end of 'variables.h'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked both archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.