|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T n
Length: 12668 (0x317c)
Types: TextFile
Names: »nntpxfer.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦cfd40dc56⟧ »EurOpenD3/news/nntp/nntp.1.5.8.tar.Z«
└─⟦2ec98eca6⟧
└─⟦this⟧ »xfer/nntpxfer.c«
#ifndef lint
static char * scsid = "@(#)$Header: nntpxfer.c,v 1.5 90/01/16 01:18:32 sob Exp $";
#endif
/*
* nntpxfer
*
* Connects to the specified nntp server, and transfers all new news
* since the last successful invocation.
*
* last successful invocation date and time are stored in a file at
* /usr/spool/news/nntp.<hostname> as
* groups YYMMDD HHMMSS distributions\n
* in case you need to edit it. You can also override this on
* the command line in the same format, in which case the file won't
* be updated.
*
* Brian Kantor, UCSD 1986
* (some bug fixes by ambar@athena.mit.edu)
* Modified to use NNTP distribution conf.h file and nntpxmit's get_tcp_conn.c
* subroutines so that nntpxfer could be used on more systems.
* Stan Barber, November 7, 1989 <sob@bcm.tmc.edu>
*
*/
#include "../common/conf.h"
#ifdef DEBUG
#undef SYSLOG
#endif
#include <sys/types.h>
#ifdef NDIR
#ifdef M_XENIX
#include <sys/ndir.h>
#else
#include <ndir.h>
#endif
#else
#include <sys/dir.h>
#endif
#ifdef USG
#include <time.h>
#else
#include <sys/time.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <setjmp.h>
#ifndef NONETDB
#include <netdb.h>
#endif
#include <signal.h>
#ifdef SYSLOG
#ifdef FAKESYSLOG
#include "../server/fakesyslog.h"
#else
#include <syslog.h>
#endif
#endif
#ifdef DBM
#include <dbm.h>
#endif
#ifdef NDBM
#include <ndbm.h>
#include <fcntl.h>
static DBM *db = NULL;
#endif
#ifndef TIMEOUT
#define TIMEOUT (30*60)
#endif
char *malloc();
char *strcpy();
char *strcat();
char *rindex();
long time();
u_long inet_addr();
extern int errno;
char *artlist[MAX_ARTICLES];
int server; /* stream socket to the nntp server */
FILE * rd_fp, * wr_fp;
int newart, dupart, misart;
char * Pname;
main(argc, argv)
int argc;
char *argv[];
{
FILE *dtfile; /* where last xfer date/time stored */
char buf[BUFSIZ];
char lastdate[16];
char distributions[BUFSIZ];
char dtname[128];
char newsgroups[BUFSIZ];
char lasttime[16];
int connected = 0; /* 1 = connected */
int i;
int omitupdate = 0; /* 1 = don't update datetime */
long clock;
long newdate, newtime;
struct tm *now;
Pname = ((Pname = rindex(argv[0], '/')) ? Pname + 1 : argv[0]);
/* OPTIONS
argv[1] MUST be the host name
argv[2-4] MAY be "newsgroups YYMMDD HHMMSS"
argv[5] MAY be distributions
(otherwise use 2-4/5 from the file
"/usr/spool/news/nntp.hostname")
*/
if (argc != 2 && argc != 5 && argc != 6)
{
(void) printf("Usage: %s host [groups YYMMDD HHMMSS [<dist>]]\n",
argv[0]);
exit(1);
}
if (argc > 2)
{
omitupdate++;
(void) strcpy(newsgroups, argv[2]);
(void) strcpy(lastdate, argv[3]);
(void) strcpy(lasttime, argv[4]);
(void) strcpy(distributions, "");
if (argc > 5)
(void) strcpy(distributions, argv[5]);
}
else
{
(void) sprintf(dtname, "%s/nntp.%s",SPOOLDIR,argv[1]);
dtfile = fopen(dtname, "r");
if (dtfile == (FILE *) 0)
{
(void) printf("%s not found; using * 860101 000000 \n",
dtname);
(void) strcpy(newsgroups, "*");
(void) strcpy(lastdate, "860101");
(void) strcpy(lasttime, "000000");
(void) strcpy(distributions, "");
}
else
{
if (fscanf(dtfile, "%s %s %s %s",
newsgroups, lastdate, lasttime, distributions) < 3)
{
(void) printf("%s invalid; using * 860101 000000\n",
dtname);
(void) strcpy(newsgroups, "*");
(void) strcpy(lastdate, "860101");
(void) strcpy(lasttime, "000000");
(void) strcpy(distributions, "");
}
(void) fclose(dtfile);
}
clock = time((long *)0);
now = gmtime(&clock);
newdate = (now->tm_year * 10000) +
((now->tm_mon + 1) * 100) + now->tm_mday;
newtime = (now->tm_hour * 10000) +
(now->tm_min * 100) + now->tm_sec;
#ifdef DEBUG
printf("server is %s\n",argv[1]);
printf("lastdate is %s\n",lastdate);
printf("lasttime is %s\n",lasttime);
printf("newsgroups is '%s'\n",newsgroups);
printf("distributions is '%s'\n",distributions);
#endif
}
#ifdef SYSLOG
#ifdef BSD_42
openlog("nntpxfer", LOG_PID);
#else
openlog("nntpxfer", LOG_PID, SYSLOG);
#endif
#endif
#ifdef DBM
if (dbminit(HISTORY_FILE) < 0)
{
#ifdef SYSLOG
syslog(LOG_ERR,"couldn't open history file: %m");
#else
perror("nntpxfer: couldn't open history file");
#endif
exit(1);
}
#endif
#ifdef NDBM
if ((db = dbm_open(HISTORY_FILE, O_RDONLY, 0)) == NULL)
{
#ifdef SYSLOG
syslog(LOG_ERR,"couldn't open history file: %m");
#else
perror("nntpxfer: couldn't open history file");
#endif
exit(1);
}
#endif
if ((server = get_tcp_conn(argv[1],"nntp")) < 0)
{
#ifdef SYSLOG
syslog(LOG_ERR,"could not open socket: %m");
#else
perror("nntpxfer: could not open socket");
#endif
exit(1);
}
if ((rd_fp = fdopen(server,"r")) == (FILE *) 0){
#ifdef SYSLOG
syslog(LOG_ERR,"could not fdopen socket: %m");
#else
perror("nntpxfer: could not fdopen socket");
#endif
exit(1);
}
#ifdef SYSLOG
syslog(LOG_DEBUG,"connected to nntp server at %s", argv[1]);
#endif
#ifdef DEBUG
printf("connected to nntp server at %s\n", argv[1]);
#endif
/*
* ok, at this point we're connected to the nntp daemon
* at the distant host.
*/
/* get the greeting herald */
(void) sockread(buf);
#ifdef DEBUG
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
#ifdef SYSLOG
syslog(LOG_NOTICE,"protocol error: got '%s'\n", buf);
#else
(void) printf("%s: protocol error: got '%s'\n", Pname,buf);
#endif
(void) close(server);
exit(1);
}
/* first, tell them we're a slave process to get priority */
sockwrite("SLAVE");
(void) sockread(buf);
#ifdef DEBUG
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
#ifdef SYSLOG
syslog(LOG_NOTICE,"protocol error: got '%s'", buf);
#else
(void) printf("%s: protocol error: got '%s'\n", Pname,buf);
#endif
(void) close(server);
exit(1);
}
/* now, ask for a list of new articles */
if (strlen(distributions))
(void) sprintf(buf,"NEWNEWS %s %s %s GMT <%s>",
newsgroups, lastdate, lasttime, distributions);
else
(void) sprintf(buf,"NEWNEWS %s %s %s GMT",
newsgroups, lastdate, lasttime);
sockwrite(buf);
(void) sockread(buf);
#ifdef DEBUG
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
#ifdef SYSLOG
syslog(LOG_NOTICE,"protocol error: got '%s'", buf);
#else
(void) printf("%s: protocol error: got '%s'\n", Pname,buf);
#endif
(void) close(server);
exit(1);
}
/* and here comes the list, terminated with a "." */
#ifdef DEBUG
(void) printf("data\n");
#endif
dupart = newart = 0;
while (1)
{
(void) sockread(buf);
if (!strcmp(buf,"."))
break;
if (wewant(buf))
{
if (newart > MAX_ARTICLES)
{
omitupdate++;
continue;
}
artlist[newart] = malloc((unsigned)(strlen(buf)+1));
(void) strcpy(artlist[newart], buf);
newart++;
}
else
dupart++;
}
#ifdef DEBUG
(void) printf(".\n%d new, %d dup articles\n", newart, dupart);
#endif
/* now that we know which articles we want, retrieve them */
for (i=0; i < newart; i++)
(void) artfetch(artlist[i]);
#ifdef DEBUG
(void) printf("%d missing articles\n", misart);
#endif
/* we're all done, so tell them goodbye */
sockwrite("QUIT");
(void) sockread(buf);
#ifdef DEBUG
(void) printf("%s\n", buf);
#endif
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
#ifdef SYSLOG
syslog(LOG_NOTICE,"error: got '%s'", buf);
#else
(void) printf("%s: error: got '%s'\n", Pname,buf);
#endif
(void) close(server);
exit(1);
}
(void) close(server);
/* do we want to update the timestamp file? */
if (!omitupdate)
{
(void) sprintf(buf, "%s %06d %06d %s\n",
newsgroups, newdate, newtime, distributions);
#ifdef DEBUG
(void) printf("updating %s:\n\t%s\n", dtname, buf);
#endif
dtfile = fopen(dtname, "w");
if (dtfile == (FILE *) 0)
{
perror(dtname);
exit(1);
}
(void) fputs(buf,dtfile);
(void) fclose(dtfile);
}
exit(0);
}
artfetch(articleid)
char *articleid;
{
int lines = 0;
char buf[BUFSIZ];
FILE *inews;
/* now, ask for the article */
(void) sprintf(buf,"ARTICLE %s", articleid);
sockwrite(buf);
(void) sockread(buf);
#ifdef DEBUG
(void) printf("%s\n", buf);
#endif
if (buf[0] == '4') /* missing article, just skipit */
{
misart++;
return(0);
}
if (buf[0] != '2') /* uh-oh, something's wrong! */
{
#ifdef SYSLOG
syslog(LOG_NOTICE,"protocol error: got '%s'", buf);
#else
(void) printf("%s: protocol error: got '%s'\n", Pname, buf);
#endif
(void) close(server);
exit(1);
}
#ifdef DEBUG
(void) printf("command: %s\n", RNEWS);
#endif
if ( (inews = popen(RNEWS, "w")) == (FILE *) 0)
{
perror(RNEWS);
exit(1);
}
/* and here comes the article, terminated with a "." */
#ifdef DEBUG
(void) printf("data\n");
#endif
while (1)
{
(void) sockread(buf);
if (buf[0] == '.' && buf[1] == '\0')
break;
lines++;
(void) strcat(buf,"\n");
(void) fputs(((buf[0] == '.') ? buf + 1 : buf),
inews);
}
#ifdef DEBUG
(void) printf(".\n%d lines\n", lines);
#endif
(void) fflush(inews);
(void) pclose(inews);
return(0);
}
static jmp_buf SFGstack;
static SIGRET
to_sfgets()
{
longjmp(SFGstack, 1);
}
int
sockread(buf)
char *buf;
{
int esave, rz;
char * ret;
if (setjmp(SFGstack)) {
(void) alarm(0); /* reset alarm clock */
(void) signal(SIGALRM, SIG_DFL);
#ifdef apollo
rd_fp->_flag |= _SIERR;
#else
rd_fp->_flag |= _IOERR; /* set stdio error */
#endif
#ifndef ETIMEDOUT
errno = EPIPE; /* USG doesn't have ETIMEDOUT */
#else
errno = ETIMEDOUT; /* connection timed out */
#endif
#ifdef SYSLOG
syslog(LOG_ERR,"nntpxfer: read error on server socket: %m");
#else
(void) perror("nntpxfer: read error on server socket");
#endif
(void) close(server);
exit(1);
}
(void) signal(SIGALRM, to_sfgets);
(void) alarm(TIMEOUT);
ret = fgets(buf, BUFSIZ, rd_fp);
esave = errno;
(void) alarm(0); /* reset alarm clock */
(void) signal(SIGALRM, SIG_DFL); /* reset SIGALRM */
errno = esave;
rz = strlen(buf);
buf[rz-2] = '\0';
if (ret == (char * ) 0) {
#ifdef SYSLOG
syslog(LOG_ERR,"nntpxfer: read error on server socket: %m");
#else
(void) perror("nntpxfer: read error on server socket");
#endif
(void) fclose(rd_fp);
exit(1);
}
return(0);
}
sockwrite(buf)
char *buf;
{
register int sz;
char buf2[BUFSIZ];
#ifdef DEBUG
(void) printf(">>> %s\n", buf);
#endif
(void) strcpy(buf2,buf);
(void) strcat(buf2,"\r\n");
sz = strlen(buf2);
if (write(server,buf2,sz) != sz)
{
#ifdef SYSLOG
syslog(LOG_ERR,"nntpxfer: write error on server socket");
#else
(void) printf("nntpxfer: write error on server socket\n");
#endif
(void) close(server);
exit(1);
}
}
int
wewant(articleid)
char *articleid;
{
#if defined(DBM) || defined(NDBM)
datum k, d;
#else
FILE *k;
char *histfile();
FILE *histfp; /* USG history file */
char line[BUFSIZ];
int len;
#endif
char id[BUFSIZ];
char *p;
/* remove any case sensitivity */
(void) strcpy(id, articleid);
p = id;
#ifndef CNEWS
while (*p)
{
if (isupper(*p))
*p = tolower(*p);
p++;
}
#endif
#if defined(DBM) || defined(NDBM)
k.dptr = id;
k.dsize = strlen(articleid) + 1;
#ifdef DBM
d = fetch(k);
#else
d = dbm_fetch(db, k);
#endif
if (d.dptr)
{
#ifdef DEBUG
(void) printf("dup: '%s'\n", articleid);
#endif
return(0);
}
#ifdef DEBUG
(void) printf("new: '%s'\n", articleid);
#endif
return(1);
#else
histfp = fopen(histfile(articleid), "r");
if (histfp == NULL)
{
#ifdef DEBUG
(void) printf("new: '%s'\n", articleid);
#endif
return(1);
}
len = strlen(articleid);
while (fgets(line, sizeof (line), histfp))
if (!strncmp(articleid, line, len))
break;
if (feof(histfp)) {
(void) fclose(histfp);
#ifdef DEBUG
(void) printf("new: '%s'\n", articleid);
#endif
return (1);
}
(void) fclose(histfp);
#ifdef DEBUG
(void) printf("dup: '%s' %s\n", articleid,line);
#endif
return(0);
#endif
}
#ifdef USGHIST
/*
** Generate the appropriate history subfile name
*/
char *
histfile(hline)
char *hline;
{
char chr; /* least significant digit of article number */
static char subfile[BUFSIZ];
chr = findhfdigit(hline);
sprintf(subfile, "%s.d/%c", HISTORY_FILE, chr);
return subfile;
}
findhfdigit(fn)
char *fn;
{
register char *p;
register int chr;
extern char * index();
p = index(fn, '@');
if (p != NULL && p > fn)
chr = *(p - 1);
else
chr = '0';
if (!isdigit(chr))
chr = '0';
return chr;
}
#endif
char *
errmsg(code)
int code;
{
extern int sys_nerr;
extern char *sys_errlist[];
static char ebuf[6+5+1];
if (code > sys_nerr || code < 0) {
(void) sprintf(ebuf, "Error %d", code);
return ebuf;
} else
return sys_errlist[code];
}