/*
* $Id: getarticles.c,v 1.3 2002/06/10 04:10:06 conrads Exp $
*/
#include <string.h>
#include <unistd.h>
#include "msuck.h"
#include "nntp.h"
extern FILE * sucklog;
extern CONNECTION local, remote;
static char artpath[PATH_MAX + 1];
/*
* feed an article to local server
*
* returns 0 on success, -1 on error
*/
static int
ihave(char *artpath, char *mess_id)
{
FILE * artfile;
char linebuf[MAXLINE + 1];
if ((artfile = fopen(artpath, "r")) == NULL)
{
perror("ihave(): can't open article file");
return -1;
}
if (connect_to_server("localhost", &local) <= 0)
{
fprintf(stderr, "ihave(): connection to local server failed\n");
fclose(artfile);
return -1;
}
fprintf(local.out, "ihave %s\r\n", mess_id);
if (fgets(linebuf, MAXLINE, local.in) == NULL)
{
perror("ihave(): read error on socket after IHAVE command");
close_server(local);
fclose(artfile);
return -1;
}
/* check response code */
if (strncmp(linebuf, NNTP_SENDIT, 3) != 0)
{
fprintf(stderr, "ihave(): unexpected reply to IHAVE from local server: %s\n", linebuf);
quit_server(local);
fclose(artfile);
return -1;
}
/* write article to local server */
while (!feof(artfile))
{
if (fgets(linebuf, MAXBUFF, artfile) == NULL)
break;
if (fputs(linebuf, local.out) == EOF)
{
perror("ihave(): error writing article to local server");
close_server(local);
fclose(artfile);
return -1;
}
}
if (fputs(".\r\n", local.out) == EOF)
{
perror("ihave(): error writing article to local server");
close_server(local);
fclose(artfile);
return -1;
}
fclose(artfile);
/* get result code */
if (fgets(linebuf, MAXLINE, local.in) == NULL)
{
perror("ihave(): read error on socket after sending article");
close_server(local);
return -1;
}
/* check response code */
if (strncmp(linebuf, NNTP_TOOKIT, 3) != 0)
{
fprintf(stderr, "ihave(): unexpected reply from local server after sending article: %s\n", linebuf);
quit_server(local);
return -1;
}
quit_server(local);
return 0;
}
/*
* Get a single article
*
* returns 1 on success, 0 on no such article, or -1 on error
*/
static int
getarticle(const char *group, const char *artnum)
{
FILE *artfile;
char buf[MAXBUFF + 1];
/* open the article file we're writing to */
snprintf(artpath, PATH_MAX, "/tmp/article.%s.%s", group, artnum);
if ((artfile = fopen(artpath, "w")) == NULL)
{
perror(artpath);
return -1;
}
fprintf(remote.out, "article %s\r\n", artnum);
if (fgets(buf, MAXBUFF, remote.in) == NULL)
{
perror("getarticle(): read error on socket after ARTICLE command");
fclose(artfile);
return -1;
}
/* should have gotten "220" article reply */
if (strncmp(buf, NNTP_ARTICLE_FOLLOWS, 3) != 0)
{
fprintf(stderr, "getarticle(): unexpected reply in %s to ARTICLE %s: %s\n", group, artnum, buf);
fclose(artfile);
return 0;
}
/* just read and write everything up to the terminating "." */
for (;;)
{
if (fgets(buf, MAXBUFF, remote.in) == NULL)
{
perror("getarticle(): read error on socket while reading article");
fclose(artfile);
return -1;
}
if (END_OF_OUTPUT(buf))
break;
if (fputs(buf, artfile) != 0)
{
perror("getarticle(): write error on article file");
fclose(artfile);
return -1;
}
}
fclose(artfile);
return 1;
}
/*
* Get all new articles in a group
*
* Returns the number actually fetched, or -1
*/
int
getarticles(const char *group, int numarts)
{
char artlistpath[PATH_MAX + 1];
FILE *artlist;
char artnum[MAXART + 1];
char mess_id[MAXLINE + 1];
char buf[MAXLINE + 1];
int numfetched = 0;
int count = 0;
int n;
/* open the articles list */
snprintf(artlistpath, PATH_MAX, ARTLIST_PATH_TEMPLATE, group);
if ((artlist = fopen(artlistpath, "r")) == NULL)
{
perror("getarticles(): can't open article list");
return -1;
}
fprintf(remote.out, "mode reader\r\n");
if (fgets(buf, MAXLINE, remote.in) == NULL)
{
perror("getarticles(): read error on socket after MODE READER command");
return -1;
}
/* should have gotten second server greeting */
if (strncmp(buf, NNTP_POSTOK, 3) != 0)
{
fprintf(stderr, "getarticles(): unexpected reply to MODE READER command: %s\n", buf);
return -1;
}
fprintf(remote.out, "group %s\r\n", group);
if (fgets(buf, MAXLINE, remote.in) == NULL)
{
perror("getarticles(): read error on socket after GROUP command");
return -1;
}
/* should have gotten group info */
if (strncmp(buf, NNTP_GROUPOK, 3) != 0)
{
fprintf(stderr, "getarticles(): unexpected reply to GROUP command: %s\n", buf);
return -1;
}
while (!feof(artlist))
{
if (fscanf(artlist, "%s %s\n", artnum, mess_id) != 2)
{
perror("getarticles(): read error on filtered articles list file");
fclose(artlist);
return -1;
}
/*
* It's possible that the article may have already been
* fetched by another process by now, so check one last time
* before we start fetching it
*/
if (connect_to_server("localhost", &local) <= 0)
{
fprintf(stderr, "getarticles(): connection to local server failed\n");
fclose(artlist);
return -1;
}
if (article_exists(group, artnum, mess_id) != 0)
{
fprintf(sucklog, "Article %s %s (%d of %d) in %s already exists\n",
artnum, mess_id, ++count, numarts, group);
quit_server(local);
continue;
}
quit_server(local);
fprintf(sucklog, "Getting article %s (%d of %d) in %s\n",
artnum, ++count, numarts, group);
if ((n = getarticle(group, artnum)) > 0)
{
if (ihave(artpath, mess_id) == 0)
++numfetched;
unlink(artpath);
}
else
{
--numfetched;
if (n == 0) /* probably just a "no such article"
* result */
{
continue;
}
if (n < 0) /* uh-oh! */
{
fclose(artlist);
unlink(artlistpath);
return -1;
}
}
}
fclose(artlist);
unlink(artlistpath);
return numfetched;
}
syntax highlighted by Code2HTML, v. 0.9.1