home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
s
/
slurp103.zip
/
ARTICLES.C
next >
Wrap
C/C++ Source or Header
|
1992-12-20
|
8KB
|
338 lines
/*
* articles - handle retrieval and batching of articles
*
* Copyright (C) 1992 Stephen Hebditch. All rights reserved.
* TQM Communications, BCM Box 225, London, WC1N 3XX.
* steveh@orbital.demon.co.uk +44 836 825962
*
* See README for more information and disclaimers
*
* This file provides a set of routines to retrieve articles from the
* remote NNTP server and add to a batch of articles being piped to
* the local news system via rnews.
*
* 1.00 31 Sep 92 SH Adapted from nntpxfer-e code.
* 1.00 27 Nov 92 SH Pipe batches to rnews instead of creating in
* the in.coming directory, so can be used with INN.
* 1.01 4 Dec 92 SH Print line before it is sent to server when
* debugging is on.
* 1.03 15 Dec 92 SH Minor tidy-ups, plus fixed flushing of tfp
* whenever it was once opened.
*
*/
#include "slurp.h"
static int first_article = TRUE;/* first article to be requested */
static char artbuf [COPYSIZE]; /* temp storage for article in memory */
static char *endart = artbuf; /* points to just past end of article */
static int incore = TRUE; /* article in memory, not temp file */
static FILE *tfp = NULL; /* temporary file descriptor */
static struct batch_file
{
FILE *file; /* file descriptor of rnews pipe */
size_t size; /* size of current batch */
int arts; /* number of articles in current batch */
} batch = { NULL, 0, 0 };
static void new_batch ();
static void read_article ();
static void batch_article ();
static void fetch_article ();
static void get_article ();
static void request_article (char *msgid);
static void traverse_tree ();
/*
* new_batch - Determines if there is enough room for the batch on the
* disk containing the news spool directories. If there is, then a pipe
* is opened to rnews and the batch variable initialised with the
* details.
*/
static void
new_batch ()
{
/* Make sure there is enough room for batch */
#ifdef MINFREE
if (!space (MINFREE))
{
log_msg ("new_batch: Not enough space for incoming batch");
exit (5);
}
#endif MINFREE
/* Open a pipe to rnews for the batch */
if ((batch.file = popen (RNEWS, "w")) == NULL)
log_sys ("new_batch: Can't open pipe to %s", RNEWS);
}
/*
* read_article - Read an article into artbuf or, if too large, into a
* temporary file from the currently open NNTP server socket, reading up
* to the end-of-article marker, a '.' on a single line. If it is stored
* in memory, then incore will be TRUE, otherwise it will be FALSE and the
* temporary file name will be stored in tempfile.
*/
static void
read_article ()
{
char *realline;
char line [NNTP_STRLEN];
int lines = 0;
int len;
incore = TRUE;
endart = artbuf;
/* Read in the article */
for (;;)
{
if (get_server (line, sizeof (line)))
exit (1);
/* Dot on its own means article end reached */
if (!strcmp (line, "."))
break;
/* remove hidden dot if present and add a newline */
realline = (line [0] == '.' ? line + 1 : line);
(void) strcat (realline, "\n");
/* Article is currently stored in memory */
if (incore)
{
/* If no room in artbuf, open tempfile and copy article there */
len = strlen (realline);
if ((endart + len + 1) > (artbuf + sizeof (artbuf)))
{
if ((tfp = tmpfile ()) == NULL)
log_sys ("read_article: Can't create temporary file");
(void) fwrite (artbuf, 1, endart - artbuf, tfp);
if (ferror (tfp))
log_sys ("read_article: Can't write to tempfile");
(void) fputs (realline, tfp);
if (ferror (tfp))
log_sys ("read_article: Can't write to tempfile");
incore = FALSE;
}
else
{
/* If fits, append realline to artbuf at endart */
(void) strcpy (endart, realline);
endart += len;
}
}
/* Already writing article to temp file */
else
{
(void) fputs (realline, tfp);
if (ferror (tfp))
log_sys ("read_article: Can't write to tempfile");
}
lines++;
}
/* Article successfully read in */
if (debug_flag)
(void) fprintf (stderr, "-> %d lines\n", lines);
}
/* batch_article - Append "#! rnews <count>" and the article from artbuf
* or temporary file to the batch file.
*/
static void
batch_article ()
{
size_t bytes = 0;
size_t size = 0;
/* Find article size */
if (incore)
size = endart - artbuf;
else
size = ftell (tfp);
totalsize += size;
batch.size += size;
batch.arts++;
/* Print the article header */
(void) fprintf (batch.file, "#! rnews %ld %s\n", size, hostname);
/* Copy the article to the batch file */
if (incore)
{
(void) fwrite (artbuf, 1, size, batch.file);
if (ferror (batch.file))
log_sys ("batch_article: Can't write to %s", RNEWS);
}
else
{
rewind (tfp);
while ((bytes = fread (artbuf, 1, sizeof (artbuf), tfp)) > 0)
{
(void) fwrite (artbuf, 1, bytes, batch.file);
if (ferror (batch.file))
log_sys ("batch_article: Can't write to %s", RNEWS);
}
(void) fclose (tfp);
}
}
/*
* fetch_article - Retrieve an article from the currently open NNTP
* server socket which has already been requested. The article is written
* to the end of the current batch. If there is not already a batch
* then a new pipe to rnews for the batch will be opened. If the current
* batch is too large or has too many articles then the pipe will be
* closed so that the batch may be submitted to the news system.
*/
static void
fetch_article ()
{
/* Open a new batch if required */
if (batch.file == NULL)
new_batch ();
/* Read in article */
read_article ();
/* Add it to the batch */
batch_article ();
/* Submit batch if ready */
if ((batch.arts >= BATCHARTSMAX) || (batch.size > BATCHSIZEMAX))
enqueue_batch ();
}
/*
* get_article
*/
static void
get_article ()
{
char status [NNTP_STRLEN];
/* Read status line from server */
if (get_server (status, sizeof (status)))
exit (1);
if (debug_flag)
(void) fprintf (stderr, "-> %s\n", status);
switch (atoi (status))
{
/* If missing, then add to missing list */
case ERR_NOART:
misart++;
newart--;
return;
/* If present, then fetch and add to batch */
case OK_ARTICLE:
fetch_article ();
break;
/* Otherwise must be a protocol error */
default:
log_msg ("get_article: NNTP protocol error: got '%s'", status);
exit (4);
}
}
/*
* request_article - Request an article with specified id from the server
*/
static void
request_article (char *msgid)
{
char request [NNTP_STRLEN];
(void) sprintf (request, "ARTICLE %s", msgid);
if (debug_flag)
(void) fprintf (stderr, "<- %s\n", request);
put_server (request);
}
/*
* traverse_tree - Traverse the tree requesting and getting each article
*/
static void
traverse_tree (struct mnode *p)
{
if (p != NULL)
{
traverse_tree (p->left);
request_article (p->msgid);
#ifdef SPEEDUP
if (!first_article)
#endif
get_article ();
#ifdef SPEEDUP
else
first_article = FALSE;
#endif
traverse_tree (p->right);
}
}
/*
* get_articles - Get the articles from the server whose message ids
* were previously collected with do_newnews.
*/
void
get_articles ()
{
traverse_tree (root);
#ifdef SPEEDUP
get_article ();
#endif
}
/*
* enqueue_batch - Close the currently open pipe to rnews (if it is open)
* thereby submitting the batch to the news system.
*/
void
enqueue_batch ()
{
/* Return if there is no currently open batch */
if (batch.file == NULL)
return;
/* Close the batch file */
if (pclose (batch.file))
log_sys ("enqueue_batch: Can't close pipe to %s", RNEWS);
/* Reset the batch descriptor for a new batch */
batch.file = NULL;
batch.size = 0;
batch.arts = 0;
}
/* END-OF-FILE */