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

📄 art.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
    }}/***  We are going to reject an article, record the reason and**  and the article.  For now, this is just a placeholder.*//* ARGSUSED0 */STATIC voidARTreject(buff, article)    char	*buff;    BUFFER	*article;{}#if	defined(DO_VERIFY_CANCELS)/***  Verify if a cancel message is valid.  If the user posting the cancel**  matches the user who posted the article, return the list of filenames**  otherwise return NULL.*/STATIC char *ARTcancelverify(Data, MessageID)    ARTDATA		*Data;    char		*MessageID;{    register char	*files;    register char	*p;    register char	*local;    char		*head;    char		buff[SMBUF];    files = HISfilesfor(MessageID);    if ((head = ARTreadheader(files)) == NULL)	return NULL;    /* Get the author header. */    if ((local = HeaderFind(head, "Sender", 6)) == NULL     && (local = HeaderFind(head, "From", 4)) == NULL) {	syslog(L_ERROR, "%s bad_article %s checking cancel",	    LogName, MessageID);	return NULL;    }    HeaderCleanFrom(local);    /* Compare canonical forms. */    p = COPY(Data->Poster);    HeaderCleanFrom(p);    if (!EQ(local, p)) {	files = NULL;	(void)sprintf(buff, "\"%.50s\" wants to cancel %s by \"%.50s\"",		p, MaxLength(MessageID, MessageID), local);	ARTlog(Data, ART_REJECT, buff);    }    DISPOSE(p);    return files;}#endif	/* defined(DO_VERIFY_CANCELS) *//***  Process a cancel message.*//* ARGSUSED2 */voidARTcancel(Data, MessageID, Trusted)    ARTDATA		*Data;    char		*MessageID;    BOOL		Trusted;{    register char	*files;    register char	*p;    register BOOL	more;    STRING		save;    char		buff[SMBUF];    if (!HIShavearticle(MessageID)) {	/* Article hasn't arrived here, so write a fake entry using	 * most of the information from the cancel message. */#if	defined(DO_VERIFY_CANCELS)	if (!Trusted)	    return;#endif	/* defined(DO_VERIFY_CANCELS) */	save = Data->MessageID;	Data->MessageID = MessageID;	(void)HISwrite(Data, (char *)NULL);	Data->MessageID = save;	(void)sprintf(buff, "Cancelling %s", MessageID);	ARTlog(Data, ART_CANC, buff);	return;    }#if	defined(DO_VERIFY_CANCELS)    files = Trusted ? HISfilesfor(MessageID)		    : ARTcancelverify(Data, MessageID);#else    files = HISfilesfor(MessageID);#endif	/* !defined(DO_VERIFY_CANCELS) */    if (files == NULL)	return;    /* Get the files where the message is stored and and zap them. */    for ( ; *files; files = p + 1) {	/* Snip off next name, turn dots to slashes. */	for (p = files; ISWHITE(*p); p++)	    continue;	for (files = p; *p && *p != ' '; p++)	    if (*p == '.')		*p = '/';	more = *p == ' ';	if (more)	    *p = '\0';	/* Remove this file, go back for the next one if there's more. */	if (unlink(files) < 0 && errno != ENOENT)	    syslog(L_ERROR, "%s cant unlink %s %m", LogName, files);	if (!more)	    break;    }}/***  Process a control message.  Cancels are handled here, but any others**  are passed out to an external program in a specific directory that**  has the same name as the first word of the control message.*/STATIC voidARTcontrol(Data, Control)    ARTDATA		*Data;    char		*Control;{    static char		CTLBIN[] = _PATH_CONTROLPROGS;    register char	*p;    char		buff[SMBUF];    char		*av[6];    struct stat		Sb;    register char	c;    /* See if it's a cancel message. */    c = *Control;    if (c == 'c' && EQn(Control, "cancel", 6)) {	for (p = &Control[6]; ISWHITE(*p); p++)	    continue;	if (*p)	    ARTcancel(Data, p, FALSE);	return;    }    /* Nip off the first word into lowercase. */    for (p = Control; *p && !ISWHITE(*p); p++)	if (CTYPE(isupper, *p))	    *p = tolower(*p);    if (*p)	*p++ = '\0';    /* Treat the control message as a place to send the article, if     * the name is "safe" -- no slashes in the pathname. */    if (p - Control + STRLEN( _PATH_BADCONTROLPROG) >= SMBUF-4     || strchr(Control, '/') != NULL)	FileGlue(buff, CTLBIN, '/', _PATH_BADCONTROLPROG);    else {	FileGlue(buff, CTLBIN, '/', Control);	if (stat(buff, &Sb) < 0 || (Sb.st_mode & EXECUTE_BITS) == 0)	    FileGlue(buff, CTLBIN, '/', _PATH_BADCONTROLPROG);    }    /* If it's an ihave or sendme, check the site named in the message. */    if ((c == 'i' && EQ(Control, "ihave"))     || (c == 's' && EQ(Control, "sendme"))) {	while (ISWHITE(*p))	    p++;	if (*p == '\0') {	    syslog(L_NOTICE, "%s malformed %s no site %s",		    LogName, Control, Data->Name);	    return;	}	if (EQ(p, ARTpathme)) {	    /* Do nothing -- must have come from a replicant. */	    syslog(L_NOTICE, "%s %s_from_me %s",		Data->Feedsite, Control, Data->Name);	    return;	}	if (!SITEfind(p)) {	    if (c == 'i')		syslog(L_ERROR, "%s bad_ihave in %s",		    Data->Feedsite, Data->Newsgroups);	    else		syslog(L_ERROR, "%s bad_sendme dont feed %s",		    Data->Feedsite, Control, Data->Name);	    return;	}    }    /* Build the command vector and execute it. */    av[0] = buff;    av[1] = COPY(Data->Poster);    av[2] = COPY(Data->Replyto);    av[3] = Data->Name;    av[4] = (char *)Data->Feedsite;    av[5] = NULL;    HeaderCleanFrom(av[1]);    HeaderCleanFrom(av[2]);    if (Spawn(STDIN, (int)fileno(Errlog), (int)fileno(Errlog), av) < 0)	/* We know the strrchr below can't fail. */	syslog(L_ERROR, "%s cant spawn %s for %s %m",	    LogName, MaxLength(av[0], strrchr(av[0], '/')), Data->Name);    DISPOSE(av[1]);    DISPOSE(av[2]);}/***  Split a Distribution header, making a copy and skipping leading and**  trailing whitespace (which the RFC allows).*/STATIC voidDISTparse(list, Data)    register char	**list;    ARTDATA		*Data;{    static BUFFER	Dist;    register char	*p;    register char	*q;    register int	i;    register int	j;    /* Get space to store the copy. */    for (i = 0, j = 0; (p = list[i]) != NULL; i++)	j += 1 + strlen(p);    if (Dist.Data == NULL) {	Dist.Size = j;	Dist.Data = NEW(char, Dist.Size + 1);    }    else if (Dist.Size <= j) {	Dist.Size = j + 16;	RENEW(Dist.Data, char, Dist.Size + 1);    }    /* Loop over each element, skip and trim whitespace. */    for (q = Dist.Data, i = 0, j = 0; (p = list[i]) != NULL; i++) {	while (ISWHITE(*p))	    p++;	if (*p) {	    if (j)		*q++ = ',';	    for (list[j++] = p; *p && !ISWHITE(*p); )		*q++ = *p++;	    *p = '\0';	}    }    list[j] = NULL;    *q = '\0';    Data->Distribution = Dist.Data;    Data->DistributionLength = q - Dist.Data;}/***  A somewhat similar routine, except that this handles negated entries**  in the list and is used to check the distribution sub-field.*/STATIC BOOLDISTwanted(list, p)    register char	**list;    register char	*p;{    register char	*q;    register char	c;    register BOOL	sawbang;    for (sawbang = FALSE, c = *p; (q = *list) != NULL; list++)	if (*q == '!') {	    sawbang = TRUE;	    if (c == *++q && EQ(p, q))		return FALSE;	}	else if (c == *q && EQ(p, q))	    return TRUE;    /* If we saw any !foo's and didn't match, then assume they are all     * negated distributions and return TRUE, else return false. */    return sawbang;}/***  See if any of the distributions in the article are wanted by the site.*/STATIC BOOLDISTwantany(site, article)    char		**site;    register char	**article;{    for ( ; *article; article++)	if (DISTwanted(site, *article))	    return TRUE;    return FALSE;}/***  Sort an array of newsgroups for optimal disk access.  This may be**  of marginal benefit.*/STATIC voidARTsortfordisk(){    static NEWSGROUP	*save;    register NEWSGROUP	**ngptr;    if (save && GroupPointers[1] != NULL) {	/* If one of the groups we want to access is the group we last	 * wrote to, move it to the front of the list. */	for (ngptr = GroupPointers; *++ngptr; )	    if (*ngptr == save) {		*ngptr = GroupPointers[0];		GroupPointers[0] = save;		return;	    }    }    save = GroupPointers[0];}/***  Send the current article to all sites that would get it if the**  group were created.*/STATIC voidARTsendthegroup(name)    register char	*name;{    register SITE	*sp;    register int	i;    NEWSGROUP		*ngp;    for (ngp = NGfind(ARTctl), sp = Sites, i = nSites; --i >= 0; sp++)	if (sp->Name != NULL && SITEwantsgroup(sp, name)) {	    SITEmark(sp, ngp);	}}/*** Assign article numbers to the article and create the Xref line.** If we end up not being able to write the article, we'll get "holes"** in the directory and active file.*/STATIC voidARTassignnumbers(){    register char	*p;    register int	i;    register NEWSGROUP	*ngp;    p = &Xref.Data[Xref.Used];    for (i = 0; (ngp = GroupPointers[i]) != NULL; i++) {	/* If already went to this group (i.e., multiple groups are aliased	 * into it), then skip it. */	if (ngp->PostCount > 0)	    continue;	/* Bump the number. */	ngp->PostCount++;	ngp->Last++;	if (!FormatLong(ngp->LastString, (long)ngp->Last, ngp->Lastwidth)) {	    syslog(L_ERROR, "%s cant update_active %s", LogName, ngp->Name);	    continue;	}	ngp->Filenum = ngp->Last;	(void)sprintf(p, " %s:%lu", ngp->Name, ngp->Filenum);	p += strlen(p);    }    Xref.Used = p - Xref.Data;    Xref.Data[Xref.Used++] = '\n';}/***  Parse the data from the xreplic command and assign the numbers.**  This involves replacing the GroupPointers entries.*/STATIC voidARTreplic(Replic, CrossPostedp)    BUFFER		*Replic;    BOOL		*CrossPostedp;{    register char	*p;    register char	*q;    register char	*name;    register char	*next;    register NEWSGROUP	*ngp;    register int	i;    p = &Xref.Data[Xref.Used];    for (i = 0, name = Replic->Data; *name; name = next) {	/* Mark end of this entry and where next one starts. */	if ((next = strchr(name, ',')) != NULL)	    *next++ = '\0';	else	    next = "";	/* Split into news.group/# */	if ((q = strchr(name, '/')) == NULL) {	    syslog(L_ERROR, "%s bad_format %s", LogName, name);	    continue;	}	*q = '\0';	if ((ngp = NGfind(name)) == NULL) {	    syslog(L_ERROR, "%s bad_newsgroup %s", LogName, name);	    continue;	}	ngp->Filenum = atol(q + 1);	/* Update active file if we got a new high-water mark. */	if (ngp->Last < ngp->Filenum) {	    ngp->Last = ngp->Filenum;	    if (!FormatLong(ngp->LastString, (long)ngp->Last,		    ngp->Lastwidth)) {		syslog(L_ERROR, "%s cant update_active %s",		    LogName, ngp->Name);		continue;	    }	}	/* Mark that this group gets the article. */	ngp->PostCount++;	GroupPointers[i++] = ngp;	/* Turn news.group/# into news.group:#, append to Xref. */	*q = ':';	*p++ = ' ';	p += strlen(strcpy(p, name));    }    *CrossPostedp = i > 1 || AlwaysCrosspost;    Xref.Used = p - Xref.Data;    Xref.Data[Xref.Used++] = '\n';}/***  Return TRUE if a list of strings has a specific one.  This is a**  generic routine, but is used for seeing if a host is in the Path line.*/STATIC BOOLListHas(list, p)    register char	**list;    register char	*p;{    register char	*q;    register char	c;    for (c = *p; (q = *list) != NULL; list++)	if (c == *q && caseEQ(p, q))	    return TRUE;    return FALSE;}/***  Propagate an article to the sites have "expressed an interest."*/STATIC voidARTpropagate(Data, hops, hopcount, list)    ARTDATA		*Data;    char		**hops;    int			hopcount;    char		**list;{    register SITE	*sp;    register int	i;    register int	j;    register int	Groupcount;    register char	*p;    register SITE	*funnel;    register BUFFER	*bp;    /* Work out which sites should really get it. */    Groupcount = Data->Groupcount;    for (sp = Sites, i = nSites; --i >= 0; sp++) {	if (sp->Seenit || !sp->Sendit)	    continue;	sp->Sendit = FALSE;	if (sp->Master != NOSITE && Sites[sp->Master].Seenit)	    continue;	if (sp->MaxSize && sp->MaxSize < Data->SizeValue)	    /* Too big for the site. */	    continue;	if ((!sp->IgnorePath && ListHas(hops, sp->Name))	 || (sp->Hops && hopcount > sp->Hops)	 || (sp->Groupcount && Groupcount > sp->Groupcount))	    /* Site already saw the article; path too long; or too much	     * cross-posting. */	    continue;	if (list	 && sp->Distributions	 && !DISTwantany(sp->Distributions, list))	    /* Not in the site's desired list of distributions. */	    continue;	if (sp->DistRequired && list == NULL)	    /* Site requires Distribution header and there isn't one. */	    continue;	if (sp->Exclusions) {	    for (j = 0; (p = sp->Exclusions[j]) != NULL; j++)		if (ListHas(hops, p))		    break;	    if (p != NULL)		/* A host in the site's exclusion list was in the Path. */		continue;	}	/* Write that the site is getting it, and flag to send it. */	if (fprintf(Log, " %s", sp->Name) == EOF || ferror(Log)) {

⌨️ 快捷键说明

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