📄 site.c
字号:
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 + -