/* * $Id: getarticles.c,v 1.3 2002/06/10 04:10:06 conrads Exp $ */ #include #include #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; }