⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 innxmit.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  $Revision: 1.14 $****  Transmit articles to remote site.*/#include "configdata.h"#include <stdio.h>#include <ctype.h>#include <errno.h>#include <signal.h>#include <setjmp.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <fcntl.h>#if	defined(DO_NEED_TIME)#include <time.h>#endif	/* defined(DO_NEED_TIME) */#include <sys/time.h>#include <sys/uio.h>#include "nntp.h"#include "paths.h"#include "logging.h"#include "libinn.h"#include "clibrary.h"#include "qio.h"#include "dbz.h"#include "macros.h"/***  Supported encoding schemes.*/typedef enum _MIMEXFERTYPE {    MTnotmime,    MTquotedprintable,    MTbase64} MIMEXFERTYPE;#define OUTPUT_BUFFER_SIZE	(16 * 1024)/*** Syslog formats - collected together so they remain consistent*/STATIC char	STAT1[] =	"%s stats offered %lu accepted %lu refused %lu rejected %lu";STATIC char	STAT2[] = "%s times user %.3f system %.3f elapsed %.3f";STATIC char	GOT_RESENDIT[] = "%s requeued %s %s";STATIC char	CANT_CONNECT[] = "%s connect failed %s";STATIC char	CANT_AUTHENTICATE[] = "%s authenticate failed %s";STATIC char	IHAVE_FAIL[] = "%s ihave failed %s";/***  Global variables.*/STATIC BOOL		AlwaysRewrite;STATIC BOOL		Debug;STATIC BOOL		DoRequeue = TRUE;STATIC BOOL		Purging;STATIC BOOL		Slavish;STATIC BOOL		STATprint;STATIC BOOL		Mime;STATIC MIMEXFERTYPE	MimeArticle = MTnotmime;STATIC char		*BATCHname;STATIC char		*BATCHtemp;STATIC char		*REMhost;STATIC double		STATbegin;STATIC double		STATend;STATIC FILE		*BATCHfp;STATIC int		FromServer;STATIC int		ToServer;STATIC QIOSTATE		*BATCHqp;STATIC SIGVAR		GotAlarm;STATIC SIGVAR		GotInterrupt;STATIC SIGVAR		JMPyes;STATIC jmp_buf		JMPwhere;STATIC char		*REMbuffer;STATIC char		*REMbuffptr;STATIC char		*REMbuffend;STATIC unsigned long	STATaccepted;STATIC unsigned long	STAToffered;STATIC unsigned long	STATrefused;STATIC unsigned long	STATrejected;/***  Find the history file entry for the Message-ID and return a file**  positioned at the third field.*/STATIC FILE *HistorySeek(MessageID)    char		*MessageID;{    static char		History[] = _PATH_HISTORY;    static FILE		*F;    register char	*p;    register char	*q;    register int	i;    datum		key;    datum		val;    OFFSET_T		offset;    /* Open the history file. */    if (F == NULL) {	if (dbminit(History) < 0) {	    (void)fprintf(stderr, "Can't set up \"%s\" database, %s\n",		    History, strerror(errno));	    exit(1);	}	if ((F = fopen(History, "r")) == NULL) {	    (void)fprintf(stderr, "Can't open \"%s\" for reading, %s\n",		    History, strerror(errno));	    exit(1);	}    }    /* Do the lookup. */    key.dsize = strlen(MessageID) + 1;    key.dptr = MessageID;    val = dbzfetch(key);    if (val.dptr == NULL || val.dsize != sizeof offset)	return NULL;    /* Get the seek offset, and seek. */    for (p = val.dptr, q = (char *)&offset, i = sizeof offset; --i >= 0; )	*q++ = *p++;    if (fseek(F, offset, SEEK_SET) == -1)	return NULL;    return F;}/***  Return TRUE if the history file has the article expired.*/STATIC BOOLExpired(MessageID)    char		*MessageID;{    register int	c;    register int	i;    register FILE	*F;    if ((F = HistorySeek(MessageID)) == NULL)	/* Assume the worst. */	return TRUE;    /* Move to the filename fields. */    for (i = 2; (c = getc(F)) != EOF && c != '\n'; )	if (c == HIS_FIELDSEP && --i == 0)	    break;    if (c != HIS_FIELDSEP)	return TRUE;    /* See if we get any filename before the end of the line. */    while ((c = getc(F)) != EOF && c != '\n')	if (!ISWHITE(c))	    /* Found non-whitespace; assume it's a filename. */	    return FALSE;    return TRUE;}/***  Flush and reset the site's output buffer.  Return FALSE on error.*/STATIC BOOLREMflush(){    int		i;    i = xwrite(ToServer, REMbuffer, (int)(REMbuffptr - REMbuffer));    REMbuffptr = REMbuffer;    return i < 0 ? FALSE : TRUE;}/***  Send a line to the server, adding the dot escape and \r\n.*/STATIC BOOLREMwrite(p, i)    register char	*p;    register int	i;{    static char		HDR[] = "Content-Transfer-Encoding:";    static char		COD[] =		"Content-Transfer-Encoding: quoted-printable\r\n";    register char	*dest;    int			size;    /* Buffer too full? */    if (REMbuffend - REMbuffptr < i + 3) {	if (!REMflush())	    return FALSE;	if (REMbuffend - REMbuffer < i + 3) {	    /* Line too long -- grow buffer. */	    size = i * 2;	    RENEW(REMbuffer, char, size);	    REMbuffend = &REMbuffer[size];	}    }    if (MimeArticle != MTnotmime)        if ((*p == 'C' && EQn(p, HDR, STRLEN(HDR)))         || ((*p == 'C' || *p == 'c') && caseEQn(p, HDR, STRLEN(HDR)))) {	    (void)memcpy((POINTER)REMbuffptr, (POINTER)COD, STRLEN(COD));	    REMbuffptr += STRLEN(COD);	    return TRUE;        }    /* Dot escape, text of the line, line terminator. */    if (*p == '.')	*REMbuffptr++ = '.';    if (i > MEMCPY_THRESHOLD) {	(void)memcpy((POINTER)REMbuffptr, (POINTER)p, (SIZE_T)i);	REMbuffptr += i;    }    else {	for (dest = REMbuffptr, i++; --i > 0; )	    *dest++ = *p++;	REMbuffptr = dest;    }    *REMbuffptr++ = '\r';    *REMbuffptr++ = '\n';    return TRUE;}/***  Send a line to the server, adding the dot escape and \r\n.*/STATIC BOOLREMwriteQuoted(p, i)    register char	*p;    register int	i;{    static char		HEXDIGITS[] = "0123456789ABCDEF";    register char	*dest;    register int	size;    register int	count;    register int	prev;    /* Buffer too full? */    if (REMbuffend - REMbuffptr < i + 3) {	if (!REMflush())	    return FALSE;	if (REMbuffend - REMbuffer < i + 3) {	    /* Line too long -- grow buffer. */	    size = i * 2;	    RENEW(REMbuffer, char, size);	    REMbuffend = &REMbuffer[size];	}    }    for (count = 0, prev = 255, dest = REMbuffptr, i++; --i > 0; ) {	if ((*p < 32 && *p != '\t')	 || *p == '='	 || *p >= 127	 || (count == 0 && *p =='.')) {	    *dest++ = '=';	    *dest++ = HEXDIGITS[*p >> 4];	    *dest++ = HEXDIGITS[*p & 0x0F];	    p++;	    count += 3;	    prev = 'A';	}	else {	    prev = *dest++ = *p++;	    count++;	}        if (count > 72) {	    *dest++ = '=';	    *dest++ = '\r';	    *dest++ = '\n';	    count = 0;	    prev = '\n';        }    }    if (prev == ' ' || prev == '\t')	*dest++ = '=';    REMbuffptr = dest;    *REMbuffptr++ = '\r';    *REMbuffptr++ = '\n';    return TRUE;}/***  Print transfer statistics, clean up, and exit.*/STATIC NORETURNExitWithStats(x)    int			x;{    static char		QUIT[] = "quit";    TIMEINFO		Now;    double		usertime;    double		systime;    if (!Purging) {	(void)REMwrite(QUIT, STRLEN(QUIT));	(void)REMflush();    }    (void)GetTimeInfo(&Now);    STATend = TIMEINFOasDOUBLE(Now);    if (GetResourceUsage(&usertime, &systime) < 0) {	usertime = 0;	systime = 0;    }    if (STATprint) {	(void)printf(STAT1,	    REMhost, STAToffered, STATaccepted, STATrefused, STATrejected);	(void)printf("\n");	(void)printf(STAT2, REMhost, usertime, systime, STATend - STATbegin);	(void)printf("\n");    }    syslog(L_NOTICE, STAT1,	REMhost, STAToffered, STATaccepted, STATrefused, STATrejected);    syslog(L_NOTICE, STAT2, REMhost, usertime, systime, STATend - STATbegin);    if (BATCHfp != NULL && unlink(BATCHtemp) < 0 && errno != ENOENT)	(void)fprintf(stderr, "Can't remove \"%s\", %s\n",		BATCHtemp, strerror(errno));    exit(x);    /* NOTREACHED */}/***  Close the batchfile and the temporary file, and rename the temporary**  to be the batchfile.*/STATIC voidCloseAndRename(){    /* Close the files, rename the temporary. */    QIOclose(BATCHqp);    if (ferror(BATCHfp)     || fflush(BATCHfp) == EOF     || fclose(BATCHfp) == EOF) {	(void)unlink(BATCHtemp);	(void)fprintf(stderr, "Can't close \"%s\", %s\n",		BATCHtemp, strerror(errno));	ExitWithStats(1);    }    if (rename(BATCHtemp, BATCHname) < 0) {	(void)fprintf(stderr, "Can't rename \"%s\", %s\n",		BATCHtemp, strerror(errno));	ExitWithStats(1);    }}/***  Requeue an article, opening the temp file if we have to.  If we get**  a file write error, exit so that the original input is left alone.*/STATIC voidRequeue(Article, MessageID)    char	*Article;    char	*MessageID;{    /* Temp file already open? */    if (BATCHfp == NULL) {	(void)mktemp(BATCHtemp);	if ((BATCHfp = fopen(BATCHtemp, "w")) == NULL) {	    (void)fprintf(stderr, "Can't open \"%s\", %s\n",		    BATCHtemp, strerror(errno));	    ExitWithStats(1);	}    }    /* Called only to get the file open? */    if (Article == NULL)	return;    if (MessageID != NULL)	(void)fprintf(BATCHfp, "%s %s\n", Article, MessageID);    else	(void)fprintf(BATCHfp, "%s\n", Article);    if (fflush(BATCHfp) == EOF || ferror(BATCHfp)) {	(void)fprintf(stderr, "Can't requeue \"%s\", %s\n",		Article, strerror(errno));	ExitWithStats(1);    }}/***  Requeue an article then copy the rest of the batch file out.*/STATIC voidRequeueRestAndExit(Article, MessageID)    char		*Article;    char		*MessageID;{    register char	*p;    if (!AlwaysRewrite     && STATaccepted == 0 && STATrejected == 0 && STATrefused == 0) {	(void)fprintf(stderr, "Nothing sent -- leaving batchfile alone.\n");	ExitWithStats(1);    }    (void)fprintf(stderr, "Rewriting batch file and exiting.\n");    Requeue(Article, MessageID);    for ( ; ; ) {	if ((p = QIOread(BATCHqp)) == NULL) {	    if (QIOerror(BATCHqp)) {		(void)fprintf(stderr, "Can't read \"%s\", %s\n",			BATCHname, strerror(errno));		ExitWithStats(1);	    }	    if (QIOtoolong(BATCHqp)) {		(void)fprintf(stderr, "Skipping long line in \"%s\".\n",			BATCHname);		(void)QIOread(BATCHqp);		continue;	    }	    /* Normal EOF. */	    break;	}	if (fprintf(BATCHfp, "%s\n", p) == EOF	 || ferror(BATCHfp)) {	    (void)fprintf(stderr, "Can't requeue \"%s\", %s\n",		    p, strerror(errno));	    ExitWithStats(1);	}    }    CloseAndRename();    ExitWithStats(1);}/***  Clean up the NNTP escapes from a line.*/STATIC char *REMclean(buff)    char	*buff;{    char	*p;    if ((p = strchr(buff, '\r')) != NULL)	*p = '\0';    if ((p = strchr(buff, '\n')) != NULL)	*p = '\0';    /* The dot-escape is only in text, not command responses. */    return buff;}/***  Read a line of input, with timeout.  Also handle \r\n-->\n mapping**  and the dot escape.  Return TRUE if okay, *or we got interrupted.**/STATIC BOOLREMread(start, size)    char		*start;    int			size;{    static int		count;    static char		buffer[BUFSIZ];    static char		*bp;    register char	*p;    register char	*q;    register char	*end;    struct timeval	t;    FDSET		rmask;    int			i;    char		c;    if (!REMflush())	return FALSE;    for (p = start, end = &start[size - 1]; ; ) {	if (count == 0) {	    /* Fill the buffer. */    Again:	    FD_ZERO(&rmask);	    FD_SET(FromServer, &rmask);	    t.tv_sec = 10 * 60;	    t.tv_usec = 0;	    i = select(FromServer + 1, &rmask, (FDSET *)NULL,			(FDSET *)NULL, &t);	    if (GotInterrupt)		return TRUE;	    if (i < 0) {		if (errno == EINTR)		    goto Again;		return FALSE;	    }	    if (i == 0 || !FD_ISSET(FromServer, &rmask))		return FALSE;	    count = read(FromServer, buffer, sizeof buffer);	    if (GotInterrupt)		return TRUE;	    if (count <= 0)		return FALSE;	    bp = buffer;	}	/* Process next character. */	count--;	c = *bp++;	if (c == '\n')	    break;	if (p < end)	    *p++ = c;    }    /* We know we got \n; if previous char was \r, turn it into \n. */    if (p > start && p < end && p[-1] == '\r')	p[-1] = '\n';    *p = '\0';    /* Handle the dot escape. */    if (*p == '.') {	if (p[1] == '\n' && p[2] == '\0')	    /* EOF. */	    return FALSE;	for (q = &start[1]; (*p++ = *q++) != '\0'; )	    continue;    }    return TRUE;}/***  Handle the interrupt.*/static voidInterrupted(Article, MessageID)    char	*Article;    char	*MessageID;{    (void)fprintf(stderr, "Interrupted\n");    RequeueRestAndExit(Article, MessageID);}/***  Send a whole article to the server.*/STATIC BOOLREMsendarticle(Article, MessageID, qp)    char		*Article;    char		*MessageID;    register QIOSTATE	*qp;{    static char		TERM[] = ".\r\n";    register char	*p;    register BOOL	ok;    register BOOL	InHeaders;    char		buff[NNTP_STRLEN];    for (InHeaders = TRUE; ; ) {	if ((p = QIOread(qp)) == NULL) {	    if (QIOerror(qp)) {		(void)fprintf(stderr, "Can't read \"%s\", %s\n",			Article, strerror(errno));		return FALSE;	    }	    if (QIOtoolong(qp)) {		(void)fprintf(stderr, "Line too long in \"%s\"\n", Article);		(void)QIOread(BATCHqp);		continue;	    }	    /* Normal EOF. */	    break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -