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

📄 site.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	argv[3] = NULL;    }    /* Fork a child. */    i = Spawn(pan[PIPE_READ], (int)fileno(Errlog), (int)fileno(Errlog), argv);    if (i > 0) {	sp->pid = i;	sp->Spooling = FALSE;	sp->Process = PROCwatch(i, sp - Sites);	(void)close(pan[PIPE_READ]);	sp->Channel = CHANcreate(pan[PIPE_WRITE],			sp->Type == FTchannel ? CTprocess : CTexploder,			CSwriting, SITEreader, SITEwritedone);	DISPOSE(process);	return TRUE;    }    DISPOSE(process);    /* Error.  Switch to spooling. */    syslog(L_ERROR, "%s spooling", sp->Name);    (void)close(pan[PIPE_WRITE]);    (void)close(pan[PIPE_READ]);    if (!SITEspool(sp, (CHANNEL *)NULL))	return FALSE;    /* We'll try to restart the channel later. */    syslog(L_ERROR, "%s cant spawn spooling %m", sp->Name);    ip = NEW(int, 1);    *ip = sp - Sites;    SCHANadd(sp->Channel, (time_t)(Now.time + CHANNEL_RETRY_TIME),	(POINTER)NULL, SITEspoolwake, (POINTER)ip);    return TRUE;}/***  Set up a site for internal buffering.*/STATIC voidSITEbuffer(sp)    register SITE	*sp;{    register BUFFER	*bp;    sp->Buffered = TRUE;    sp->Channel = NULL;    bp = &sp->Buffer;    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);    }    BUFFset(bp, "", 0);    syslog(L_NOTICE, "%s buffered", sp->Name);}/***  Set up a site's feed.  This means opening a file or channel if needed.*/BOOLSITEsetup(sp)    register SITE	*sp;{    int			fd;    switch (sp->Type) {    default:	syslog(L_ERROR, "%s internal SITEsetup %d",	    sp->Name, sp->Type);	return FALSE;    case FTfunnel:    case FTlogonly:    case FTprogram:	/* Nothing to do here. */	break;    case FTfile:	SITEcount++;	if (SITEcount > MaxOutgoing)	    SITEbuffer(sp);	else {	    sp->Buffered = FALSE;	    fd = open(sp->Param, O_APPEND | O_CREAT | O_WRONLY, BATCHFILE_MODE);	    if (fd < 0) {		if (errno == EMFILE) {		    SITEbuffer(sp);		    break;		}		IOError("site file");		syslog(L_NOTICE, "%s cant open %s %m", sp->Name, sp->Param);		return FALSE;	    }	    if (AmRoot)		xchown(sp->Param);	    sp->Channel = CHANcreate(fd, CTfile, CSwriting,			    SITEreader, SITEwritedone);	    syslog(L_NOTICE, "%s opened %s", sp->Name, CHANname(sp->Channel));	    WCHANset(sp->Channel, "", 0);	}	break;    case FTchannel:    case FTexploder:	if (!SITEstartprocess(sp))	    return FALSE;	syslog(L_NOTICE, "%s spawned %s", sp->Name, CHANname(sp->Channel));	WCHANset(sp->Channel, "", 0);	WCHANadd(sp->Channel);	break;    }    return TRUE;}/***  A site's channel process died; restart it.*/voidSITEprocdied(sp, process, pp)    SITE	*sp;    int		process;    PROCESS	*pp;{    syslog(pp->Status ? L_ERROR : L_NOTICE, "%s exit %d elapsed %ld pid %ld",	sp->Name ? sp->Name : "?", pp->Status,	(pp->Collected - pp->Started) / 60L, (long)pp->Pid);    if (sp->Process != process || sp->Name == NULL)	/* We already started a new process for this channel	 * or this site has been dropped. */	return;    if (sp->Channel != NULL)	CHANclose(sp->Channel, CHANname(sp->Channel));    sp->Working = SITEsetup(sp);    if (!sp->Working) {	syslog(L_ERROR, "%s cant restart %m", sp->Name);	return;    }    syslog(L_NOTICE, "%s restarted", sp->Name);}/***  A channel is about to be closed; see if any site cares.*/voidSITEchanclose(cp)    register CHANNEL	*cp;{    register int	i;    register SITE	*sp;    int			*ip;    for (i = nSites, sp = Sites; --i >= 0; sp++)	if (sp->Channel == cp) {	    /* Found the site that has this channel.  Start that	     * site spooling, copy any data that might be pending,	     * and arrange to retry later. */	    if (!SITEspool(sp, (CHANNEL *)NULL)) {		syslog(L_ERROR, "%s loss %d bytes", sp->Name, i);		return;	    }	    WCHANsetfrombuffer(sp->Channel, &cp->Out);	    WCHANadd(sp->Channel);	    ip = NEW(int, 1);	    *ip = sp - Sites;	    SCHANadd(sp->Channel, (time_t)(Now.time + CHANNEL_RETRY_TIME),		(POINTER)NULL, SITEspoolwake, (POINTER)ip);	    break;	}}/***  Flush any pending data waiting to be sent.*/voidSITEflush(sp, Restart)    register SITE	*sp;    BOOL		Restart;{    register CHANNEL	*cp;    register BUFFER	*out;    if (sp->Name == NULL)	return;    SITEforward(sp, "flush");    switch (sp->Type) {    default:	syslog(L_ERROR, "%s internal SITEflush %d", sp->Name, sp->Type);	return;    case FTlogonly:    case FTprogram:    case FTfunnel:	/* Nothing to do here. */	return;    case FTchannel:    case FTexploder:	/* If spooling, close the file right now. */	if (sp->Spooling && (cp = sp->Channel) != NULL) {	    (void)WCHANflush(cp);	    CHANclose(cp, CHANname(cp));	    sp->Channel = NULL;	}	break;    case FTfile:	break;    }    /* We're only dealing with files and channels now. */    if ((cp = sp->Channel) != NULL)	(void)WCHANflush(cp);    /* Restart the site, copy any pending data. */    if (Restart) {	if (!SITEsetup(sp))	    syslog(L_ERROR, "%s cant restart %m", sp->Name);	else if (cp != NULL) {	    if (sp->Buffered) {		/* SITEsetup had to buffer us; save any residue. */		out = &sp->Channel->Out;	        if (out->Left)		    BUFFset(&sp->Buffer, &out->Data[out->Used], out->Left);	    }	    else		WCHANsetfrombuffer(sp->Channel, &cp->Out);	}    }    else if (cp != NULL && cp->Out.Left) { 	if (sp->Type == FTfile || sp->Spooling) {	    /* Can't flush a file?  Hopeless. */ 	    syslog(L_ERROR, "%s dataloss %d", sp->Name, cp->Out.Left); 	    return; 	} 	/* Must be a working channel; spool and retry. */	syslog(L_ERROR, "%s spooling %d bytes", sp->Name, cp->Out.Left); 	if (SITEspool(sp, cp))	    SITEflush(sp, FALSE); 	return;    }    /* Close the old channel if it was open. */    if (cp != NULL) {        /* Make sure we have no dangling pointers to it. */	if (!Restart)	    sp->Channel = NULL;	CHANclose(cp, sp->Name);	if (sp->Type == FTfile)	    SITEcount--;    }}/***  Flush all sites.*/voidSITEflushall(Restart)    BOOL	Restart;{    register int	i;    register SITE	*sp;    for (i = nSites, sp = Sites; --i >= 0; sp++)	if (sp->Name)	    SITEflush(sp, Restart);}/***  Run down the site's pattern list and see if it wants the specified**  newsgroup.*/BOOLSITEwantsgroup(sp, name)    register SITE	*sp;    register char	*name;{    register BOOL	match;    register BOOL	subvalue;    register char	*pat;    register char	**argv;    match = SUB_DEFAULT;    if (ME.Patterns) {	for (argv = ME.Patterns; (pat = *argv++) != NULL; ) {	    subvalue = *pat != SUB_NEGATE;	    if (!subvalue)		pat++;	    if (wildmat(name, pat))		match = subvalue;	}    }    for (argv = sp->Patterns; (pat = *argv++) != NULL; ) {	subvalue = *pat != SUB_NEGATE;	if (!subvalue)	    pat++;	if (wildmat(name, pat))	    match = subvalue;    }    return match;}/***  Find a site.*/SITE *SITEfind(p)    char	*p;{    register int	i;    register SITE	*sp;    for (i = nSites, sp = Sites; --i >= 0; sp++)	if (sp->Name && caseEQ(p, sp->Name))	    return sp;    return NULL;}/***  Find the next site that matches this site.*/SITE *SITEfindnext(p, sp)    char		*p;    register SITE	*sp;{    register SITE	*end;    for (sp++, end = &Sites[nSites]; sp < end; sp++)	if (sp->Name && caseEQ(p, sp->Name))	    return sp;    return NULL;}/***  Close a site down.*/voidSITEfree(sp)    register SITE	*sp;{    register SITE	*s;    register int	new;    register int	i;    if (sp->Channel) {	CHANclose(sp->Channel, CHANname(sp->Channel));	sp->Channel = NULL;    }    sp->Name = NULL;    if (sp->Process > 0) {	/* Kill the backpointer so PROCdied won't call us. */	PROCunwatch(sp->Process);	sp->Process = -1;    }    if (sp->Entry) {	DISPOSE(sp->Entry);	sp->Entry = NULL;    }    if (sp->Param) {	DISPOSE(sp->Param);	sp->Param = NULL;    }    if (sp->SpoolName) {	DISPOSE(sp->SpoolName);	sp->SpoolName = NULL;    }    if (sp->Patterns) {	DISPOSE(sp->Patterns);	sp->Patterns = NULL;    }    if (sp->Exclusions) {	DISPOSE(sp->Exclusions);	sp->Exclusions = NULL;    }    if (sp->Distributions) {	DISPOSE(sp->Distributions);	sp->Distributions = NULL;    }    if (sp->Buffer.Data) {	DISPOSE(sp->Buffer.Data);	sp->Buffer.Data = NULL;	sp->Buffer.Size = 0;    }    if (sp->FNLnames.Data) {	DISPOSE(sp->FNLnames.Data);	sp->FNLnames.Data = NULL;	sp->FNLnames.Size = 0;    }    /* If this site was a master, find a new one. */    if (sp->IsMaster) {	for (new = NOSITE, s = Sites, i = nSites; --i >= 0; s++)	    if (&Sites[s->Master] == sp)		if (new == NOSITE) {		    s->Master = NOSITE;		    s->IsMaster = TRUE;		    new = s - Sites;		}		else		    s->Master = new;	sp->IsMaster = FALSE;    }}/***  If a site is an exploder or funnels into one, forward a command**  to it.*/voidSITEforward(sp, text)    register SITE	*sp;    char		*text;{    register SITE	*fsp;    register char	*p;    char		buff[SMBUF];    fsp = sp;    if (sp->Name == NULL || fsp->Name == NULL)	return;    if (fsp->Funnel != NOSITE)	fsp = &Sites[fsp->Funnel];    if (fsp->Type == FTexploder) {	(void)strcpy(buff, text);	if (fsp != sp && fsp->FNLwantsnames) {	    p = buff + strlen(buff);	    *p++ = ' ';	    (void)strcpy(p, sp->Name);	}	SITEwrite(fsp, buff);    }}/***  Drop a site.*/voidSITEdrop(sp)    SITE		*sp;{    SITEforward(sp, "drop");    SITEflush(sp, FALSE);    SITEfree(sp);    sp->Name = NULL;    SITElinkall();}/***  Put all the feeds into a doubly-linked list.*/voidSITElinkall(){    register SITE	*sp;    if (nSites < 2)	return;    SITEhead = &Sites[0];    SITEtail = &Sites[nSites - 1];    for (sp = SITEhead; ++sp < SITEtail; )	sp[-1].Next = sp[1].Prev = sp;    SITEhead->Prev = NULL;    if (SITEhead->Next)	SITEhead->Next->Prev = SITEhead;    SITEtail->Next = NULL;    if (SITEtail->Prev)	SITEtail->Prev->Next = SITEtail;}

⌨️ 快捷键说明

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