DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T n

⟦5d391d5d6⟧ TextFile

    Length: 10668 (0x29ac)
    Types: TextFile
    Names: »nntpxfer.c«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦5cced586a⟧ »EurOpenD3/news/nntp/nntp.1.5.7.tar.Z« 
        └─⟦7340f105e⟧ 
            └─⟦this⟧ »./xfer/nntpxfer.c« 

TextFile

/*
 * 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"

#include <sys/types.h>
#ifdef NDIR
#include <ndir.h>
#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>
#ifndef NONETDB
#include <netdb.h>
#endif
#include <signal.h>

#ifdef DBM
#include <dbm.h>
#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 */
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) strcpy(dtname, "/usr/spool/news/nntp.");
		(void) strcat(dtname, argv[1]);
		dtfile = fopen(dtname, "r");
		if (dtfile == NULL)
			{
			(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
	(void) printf("newsgroups = '%s'\n", newsgroups);
	(void) printf("date = '%s'\n", lastdate);
	(void) printf("time = '%s'\n", lasttime);
	(void) printf("distributions = '%s'\n", distributions);
	(void) printf("now is = %06d %06d\n", newdate, newtime);
#endif

#ifdef DBM
	if (dbminit(HISTORY_FILE) < 0)
		{
		perror("couldn't open history file");
		exit(1);
		}
#endif
	if ((server = get_tcp_conn(argv[1],"nntp")) < 0) 
		{
		perror("could not open socket");
		exit(1);
		}

#ifdef DEBUG
	(void) 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! */
		{
		(void) printf("protocol error: got '%s'\n", buf);
		(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! */
		{
		(void) printf("protocol error: got '%s'\n", buf);
		(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! */
		{
		(void) printf("protocol error: got '%s'\n", buf);
		(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! */
		{
		(void) printf("error: got '%s'\n", buf);
		(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 == NULL)
			{
			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! */
		{
		(void) printf("protocol error: got '%s'\n", buf);
		(void) close(server);
		exit(1);
		}
#ifdef DEBUG
	(void) printf("command: %s\n", RNEWS);
#endif
	if ( (inews = popen(RNEWS, "w")) == NULL)
		{
		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);
        }

int
sockread(buf)
char *buf;
	{
	char c;
	int j = 0;
#ifdef BSD43
	fd_set rf;
#else BSD43
	int rf;
#endif BSD43
#ifndef EXCELAN
	struct timeval tv;
#endif
	int r;
	char *p = buf;

	while ( 1 )
		{
#ifndef EXCELAN
		tv.tv_sec = 1800;	/* 15 minutes */
		tv.tv_usec = 0L;
#ifdef BSD43
		FD_ZERO(&rf);
		FD_SET(server, &rf);
		r = select(20, (fd_set *)&rf, (fd_set *)0, (fd_set *)&rf, &tv);#else BSD43
		rf = 1 << server;
		r = select(20, (int *)&rf, (int *)0, (int *)&rf, &tv);
#endif BSD43
#else
		rf = 1 << server;
		r = select(20, (long *)&rf, (long *)0, 110000L);
#endif
		if (r < 0)
			{
			if (errno == EINTR)
				continue;
			perror("getsock select");
			exit(1);
			}
		if (r == 0)
			{
			printf("read timed out.\n");
			exit(1);
			}
		if (read (server,&c,1) <= 0)
			break;

		/* mask off any chance parity bits */
		*p = c & 0x7f;

		/* look for end of line (== LF) */
		if (c == 0x0a)
			{
			if (j > 0 && *(p-1) == 0x0d)
				*(p-1) = '\0';
			else
				*p = '\0';
			return(strlen(buf));
			}
		j++; p++;
		}
	perror("sockread");
	(void) close(server);
	exit(1);
	/* NOTREACHED */
	}

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)
		{
		(void) printf("write error on server socket\n");
		(void) close(server);
		exit(1);
		}
	}

int
wewant(articleid)
char *articleid;
	{
#ifdef DBM
	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
#ifdef DBM
	k.dptr = id;
	k.dsize = strlen(articleid) + 1;

	d = fetch(k);

	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
}

char *
errmsg(n)
register int	n;
{
	extern	int	sys_nerr;
	extern 	char	*sys_errlist[];

	return((n >= 0 && n < sys_nerr) ? sys_errlist[n] : "unknown error");
}

#ifndef DBM
/*
** 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;

	p = index(fn, '@');
	if (p != NULL && p > fn)
		chr = *(p - 1);
	else
		chr = '0';
	if (!isdigit(chr))
		chr = '0';
	return chr;
}
#endif