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

📄 site.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  $Revision: 1.34 $****  Routines to implement site-feeding.  Mainly working with channels to**  do buffering and determine what to send.*/#include "innd.h"#define SITEmovetohead(sp_) \    if (SITEhead != sp_) { \	if (SITEtail == sp_) { \	    SITEtail = sp_->Prev; \	    SITEtail->Next = NULL; \	} \	else { \	    if (sp_->Prev) \		sp_->Prev->Next = sp_->Next; \	    if (sp_->Next) \		sp_->Next->Prev = sp_->Prev; \	} \	sp_->Prev = NULL; \	sp_->Next = SITEhead->Next; \	SITEhead->Prev = sp_; \	SITEhead = sp_; \    } \    elseSTATIC int	SITEcount;STATIC SITE	*SITEhead;STATIC SITE	*SITEtail;STATIC char	SITEshell[] = _PATH_SH;/***  Called when input is ready to read.  Shouldn't happen.*//* ARGSUSED0 */STATIC FUNCTYPESITEreader(cp)    CHANNEL	*cp;{    syslog(L_ERROR, "%s internal SITEreader", LogName);}/***  Called when write is done.  No-op.*//* ARGSUSED0 */STATIC FUNCTYPESITEwritedone(cp)    CHANNEL	*cp;{}/***  Make a site start spooling.*/STATIC BOOLSITEspool(sp, cp)    register SITE	*sp;    CHANNEL		*cp;{    int			i;    char		buff[SPOOLNAMEBUFF];    char		*name;    name = sp->SpoolName;    i = open(name, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE);    if (i < 0 && errno == EISDIR) {	FileGlue(buff, sp->SpoolName, '/', "togo");	name = buff;	i = open(buff, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE);    }    if (i < 0) {	IOError("site batch file");	syslog(L_ERROR, "%s cant open %s %m", sp->Name, name);	sp->Channel = NULL;	return FALSE;    }    if (AmRoot)	xchown(name);    if (cp) {	cp->fd = i;	return TRUE;    }    sp->Channel = CHANcreate(i, CTfile, CSwriting, SITEreader, SITEwritedone);    if (sp->Channel == NULL) {	syslog(L_ERROR, "%s cant channel %m", sp->Name);	(void)close(i);	return FALSE;    }    WCHANset(sp->Channel, "", 0);    sp->Spooling = TRUE;    sp->Process = -1;    return TRUE;}/***  Find the oldest "file feed" site and buffer it.*/STATIC voidSITEbufferoldest(){    register SITE	*sp;    register BUFFER	*bp;    register BUFFER	*out;    /* Go backwards and find the oldest file. */    for (sp = SITEtail; sp; sp = sp->Prev)	if (sp->Type == FTfile)	    break;    if (sp == NULL) {	syslog(L_ERROR, "%s internal no oldest site found", LogName);	return;    }    /* Write out what we can. */    (void)WCHANflush(sp->Channel);    /* Get a buffer for the site. */    sp->Buffered = TRUE;    bp = &sp->Buffer;    bp->Used = 0;    bp->Left = 0;    if (bp->Size == 0) {	bp->Size = sp->Flushpoint;	bp->Data = NEW(char, bp->Size);    }    else {	bp->Size = sp->Flushpoint;	RENEW(bp->Data, char, bp->Size);    }    /* If there's any unwritten data, copy it. */    out = &sp->Channel->Out;    if (out->Left)	BUFFset(bp, &out->Data[out->Used], out->Left);    /* Now close the original channel. */    CHANclose(sp->Channel, sp->Name);    SITEcount--;}/***  Check if we need to write out the site's buffer.  If we're buffered**  or the feed is backed up, this gets a bit complicated.*/STATIC voidSITEflushcheck(sp, bp)    register SITE	*sp;    register BUFFER	*bp;{    register int	i;    register CHANNEL	*cp;    /* If we're buffered, and we hit the flushpoint, do an LRU. */    if (sp->Buffered) {	if (bp->Used < sp->Flushpoint)	    return;	if (SITEcount > MaxOutgoing)	    SITEbufferoldest();	if (!SITEsetup(sp) || sp->Buffered) {	    syslog(L_ERROR, "%s cant unbuffer %m", sp->Name);	    return;	}	WCHANsetfrombuffer(sp->Channel, bp);	WCHANadd(sp->Channel);    }    if (PROCneedscan)	PROCscan();    /* Handle buffering. */    cp = sp->Channel;    i = cp->Out.Left;    if (i < sp->StopWriting)	WCHANremove(cp);    if ((sp->StartWriting == 0 || i > sp->StartWriting)     && !CHANsleeping(cp))	WCHANadd(cp);    /* If we're a channel that's getting big, see if we need to spool. */    if (sp->Type == FTfile || sp->StartSpooling == 0 || i < sp->StartSpooling)	return;    if (!SITEspool(sp, (CHANNEL *)NULL)) {	syslog(L_ERROR, "%s overflow %d bytes", sp->Name, i);	return;    }    syslog(L_ERROR, "%s spooling %d bytes", sp->Name, i);    WCHANsetfrombuffer(sp->Channel, &cp->Out);    WCHANadd(sp->Channel);    CHANclose(cp, CHANname(cp));}/***  Send a control line to an exploder.*/voidSITEwrite(sp, text)    register SITE	*sp;    STRING		text;{    static char		PREFIX[] = { EXP_CONTROL, '\0' };    register BUFFER	*bp;    if (sp->Buffered)	bp = &sp->Buffer;    else {	if (sp->Channel == NULL)	    return;	bp = &sp->Channel->Out;    }    BUFFappend(bp, PREFIX, STRLEN(PREFIX));    BUFFappend(bp, text, (int)strlen(text));    BUFFappend(bp, "\n", 1);    WCHANadd(sp->Channel);}/***  Send the desired data about an article down a channel.*/STATIC voidSITEwritefromflags(sp, Data)    register SITE	*sp;    ARTDATA		*Data;{    static char		ITEMSEP[] = " ";    static char		NL[] = "\n";    register char	*p;    register BOOL	Dirty;    register BUFFER	*bp;    register SITE	*spx;    register int	i;    if (sp->Buffered)	bp = &sp->Buffer;    else {	/* This should not happen, but if we tried to spool and failed,	 * e.g., because of a bad F param for this site, we can get	 * into this state.  We already logged a message so give up. */	if (sp->Channel == NULL)	    return;	bp = &sp->Channel->Out;    }    for (Dirty = FALSE, p = sp->FileFlags; *p; p++) {	switch (*p) {	default:	    syslog(L_ERROR, "%s internal SITEwritefromflags %c", sp->Name, p);	    continue;	case FEED_BYTESIZE:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Size, Data->SizeLength);	    break;	case FEED_FULLNAME:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, SPOOL, SPOOLlen);	    BUFFappend(bp, "/", 1);	    BUFFappend(bp, Data->Name, Data->NameLength);	    break;	case FEED_HDR_DISTRIB:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Distribution, Data->DistributionLength);	    break;	case FEED_HDR_NEWSGROUP:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Newsgroups, Data->NewsgroupsLength);	    break;	case FEED_HEADERS:	    if (Dirty)		BUFFappend(bp, NL, STRLEN(NL));	    BUFFappend(bp, Data->Headers->Data, Data->Headers->Left);	    break;	case FEED_OVERVIEW:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Overview->Data, Data->Overview->Left);	    break;	case FEED_REPLIC:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Replic, Data->ReplicLength);	    break;	case FEED_TIMERECEIVED:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->TimeReceived, Data->TimeReceivedLength);	    break;	case FEED_MESSAGEID:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->MessageID, Data->MessageIDLength);	    break;	case FEED_FNLNAMES:	    if (sp->FNLnames.Data) {		/* Funnel; write names of our sites that got it. */		if (Dirty)		    BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));		BUFFappend(bp, sp->FNLnames.Data, sp->FNLnames.Used);	    }	    else {		/* Not funnel; write names of all sites that got it. */		for (spx = Sites, i = nSites; --i >= 0; spx++)		    if (spx->Sendit) {			if (Dirty)			    BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));			BUFFappend(bp, spx->Name, spx->NameLength);			Dirty = TRUE;		    }	    }	    break;	case FEED_NAME:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Name, Data->NameLength);	    break;	case FEED_NEWSGROUP:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    if (sp->ng)		BUFFappend(bp, sp->ng->Name, sp->ng->NameLength);	    else		BUFFappend(bp, "?", 1);	    break;	case FEED_SITE:	    if (Dirty)		BUFFappend(bp, ITEMSEP, STRLEN(ITEMSEP));	    BUFFappend(bp, Data->Feedsite, Data->FeedsiteLength);	    break;	}	Dirty = TRUE;    }    if (Dirty) {	BUFFappend(bp, "\n", 1);	SITEflushcheck(sp, bp);    }}/***  Send one article to a site.*/voidSITEsend(sp, Data)    register SITE	*sp;    ARTDATA		*Data;{    register int	i;    register char	*p;    char		*temp;    char		buff[BUFSIZ];    STRING		argv[MAX_BUILTIN_ARGV];    int			fd;    switch (sp->Type) {    default:	syslog(L_ERROR, "%s internal SITEsend type %d", sp->Name, sp->Type);	break;    case FTlogonly:	break;    case FTfunnel:	syslog(L_ERROR, "%s funnel_send", sp->Name);	break;    case FTfile:	if (SITEcount > MaxOutgoing)	    SITEmovetohead(sp);	/* FALLTHROUGH */    case FTchannel:    case FTexploder:	SITEwritefromflags(sp, Data);	break;    case FTprogram:	/* Set up the argument vector. */	if (sp->FNLwantsnames) {	    i = strlen(sp->Param) + sp->FNLnames.Used;	    if (i + strlen(Data->Name) >= sizeof buff) {		syslog(L_ERROR, "%s toolong need %d for %s",		    sp->Name, i + strlen(Data->Name), Data->Name);		break;	    }	    temp = NEW(char, i + 1);	    p = strchr(sp->Param, '*');	    *p = '\0';	    (void)strcpy(temp, sp->Param);	    (void)strcat(temp, sp->FNLnames.Data);	    (void)strcat(temp, &p[1]);	    *p = '*';	    (void)sprintf(buff, temp, Data->Name);	    DISPOSE(temp);	}	else	    (void)sprintf(buff, sp->Param, Data->Name);	if (NeedShell(buff, argv, ENDOF(argv))) {	    argv[0] = SITEshell;	    argv[1] = "-c";	    argv[2] = buff;	    argv[3] = NULL;	}	/* Feed the article on standard input. */	fd = open(Data->Name, O_RDONLY);	if (fd < 0) {	    /* Unlikely, but we could check if the article is cross-posted	     * and try it under other names... */	    syslog(L_ERROR, "%s cant open %s %m", sp->Name, Data->Name);	    fd = 0;	}	/* Start the process. */	i = Spawn(fd, (int)fileno(Errlog), (int)fileno(Errlog), argv);	if (i >= 0)	    (void)PROCwatch(i, -1);	if (fd != 0)	    (void)close(fd);	break;    }}/***  The channel was sleeping because we had to spool our output to**  a file.  Flush and restart.*/STATIC FUNCTYPESITEspoolwake(cp)    CHANNEL	*cp;{    SITE	*sp;    int		*ip;    ip = CAST(int*, cp->Argument);    sp = &Sites[*ip];    DISPOSE(cp->Argument);    cp->Argument = NULL;    if (sp->Channel != cp) {	syslog(L_ERROR, "%s internal SITEspoolwake %s got %d, not %d",	    LogName, sp->Name, cp->fd, sp->Channel->fd);        return;    }    syslog(L_NOTICE, "%s spoolwake", sp->Name);    SITEflush(sp, TRUE);}/***  Start up a process for a channel, or a spool to a file if we can't.**  Create a channel for the site to talk to.*/STATIC BOOLSITEstartprocess(sp)    SITE		*sp;{    register int	i;    STRING		argv[MAX_BUILTIN_ARGV];    char		*process;    int			*ip;    int			pan[2];    /* Create a pipe. */    if (pipe(pan) < 0) {	syslog(L_ERROR, "%s cant pipe %m", sp->Name);	return FALSE;    }    CloseOnExec(pan[PIPE_WRITE], TRUE);    /* Set up the argument vector. */    process = COPY(sp->Param);    if (NeedShell(process, argv, ENDOF(argv))) {	argv[0] = SITEshell;	argv[1] = "-c";	argv[2] = process;

⌨️ 快捷键说明

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