Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Jul 2004 10:45:23 +0300
From:      Andrey Slusar <vasallia@ukr.net>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   ports/69551: [MAINTAINER] news/s-news: added XPAT, locking of outgoing files, support supersedes and cancel messages
Message-ID:  <E1BodhD-000DNh-Cb@santinel.home.ua>
Resent-Message-ID: <200407250750.i6P7oGxL099060@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         69551
>Category:       ports
>Synopsis:       [MAINTAINER] news/s-news: added XPAT, locking of outgoing files, support supersedes and cancel messages
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-ports-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          maintainer-update
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jul 25 07:50:16 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Andrey Slusar
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
Santinel
>Environment:
System: FreeBSD santinel.home.ua 5.2-CURRENT FreeBSD 5.2-CURRENT #1: Tue Jul 20 16:55:39 EEST 2004 root@santinel.home.ua:/usr/obj/usr/src/sys/ANRAY i386
>Description:
	Added new files:
	files/patch-active
	files/patch-config.h.in
	files/patch-configure
	files/patch-nntpd.c
	files/patch-qnews.c
	files/patch-rnews.c

	Added lock outgoing files with flock, XPAT command, ability to handle 
	supersedes and cancel control messages.
>How-To-Repeat:
	
>Fix:
--- s-news.diff begins here ---
diff -ruN /usr/ports/news/s-news/Makefile s-news/Makefile
--- /usr/ports/news/s-news/Makefile	Sat Jul 17 22:11:03 2004
+++ s-news/Makefile	Sun Jul 25 04:46:56 2004
@@ -7,6 +7,7 @@
 
 PORTNAME=	s-news
 PORTVERSION=	0.1.11
+PORTREVISION=	1
 CATEGORIES=	news
 MASTER_SITES=	http://www.lost.org.uk/
 
diff -ruN /usr/ports/news/s-news/files/patch-active s-news/files/patch-active
--- /usr/ports/news/s-news/files/patch-active	Thu Jan  1 03:00:00 1970
+++ s-news/files/patch-active	Sun Jul 25 10:24:17 2004
@@ -0,0 +1,5 @@
+--- data/active	1998-09-06 14:11:15.000000000 +0100
++++ data/active	2002-09-08 12:51:26.000000000 +0100
+@@ -1 +1,2 @@
+ junk 0 1 y
++control.cancel 0 1 y
diff -ruN /usr/ports/news/s-news/files/patch-config.h.in s-news/files/patch-config.h.in
--- /usr/ports/news/s-news/files/patch-config.h.in	Thu Jan  1 03:00:00 1970
+++ s-news/files/patch-config.h.in	Sun Jul 25 10:24:21 2004
@@ -0,0 +1,12 @@
+--- config.h.in	2002-05-18 20:22:50.000000000 +0100
++++ config.h.in	2002-10-12 19:23:12.000000000 +0100
+@@ -55,6 +55,9 @@
+ /* Define if you have the <malloc.h> header file. */
+ #undef HAVE_MALLOC_H
+ 
++/* Define if you have the <sys/file.h> header file.  */
++#undef HAVE_SYS_FILE_H
++
+ /* Define if you have the <memory.h> header file. */
+ #undef HAVE_MEMORY_H
+ 
diff -ruN /usr/ports/news/s-news/files/patch-configure s-news/files/patch-configure
--- /usr/ports/news/s-news/files/patch-configure	Thu Jan  1 03:00:00 1970
+++ s-news/files/patch-configure	Sun Jul 25 10:24:26 2004
@@ -0,0 +1,11 @@
+--- configure	2002-05-18 20:25:00.000000000 +0100
++++ configure	2002-10-12 19:23:12.000000000 +0100
+@@ -2370,7 +2370,7 @@
+ 
+ fi
+ 
+-for ac_header in fcntl.h limits.h malloc.h syslog.h unistd.h
++for ac_header in fcntl.h limits.h malloc.h syslog.h unistd.h sys/file.h
+ do
+ as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ echo "$as_me:2376: checking for $ac_header" >&5
diff -ruN /usr/ports/news/s-news/files/patch-newfeed.in s-news/files/patch-newfeed.in
--- /usr/ports/news/s-news/files/patch-newfeed.in	Thu Jul 15 16:34:30 2004
+++ s-news/files/patch-newfeed.in	Sun Jul 25 04:42:16 2004
@@ -1,6 +1,6 @@
---- newfeed.in.old	Thu Jul 15 16:31:44 2004
-+++ newfeed.in	Thu Jul 15 16:33:15 2004
-@@ -52,7 +52,7 @@
+--- newfeed.in.orig	Sat Jun 29 21:29:49 2002
++++ newfeed.in	Sun Jul 25 04:40:59 2004
+@@ -52,9 +52,11 @@
  	umask $UMASK
  fi
  
@@ -8,4 +8,8 @@
 +if mkdir -p $SUCKDIR/$host
  then
  	echo junk >$SUCKDIR/$host/active-ignore
++	# Uncomment the following line if you don't want cancel messages to propagate
++	#echo control.cancel >>$SUCKDIR/$host/active-ignore
  	mkdir $SUCKDIR/$host/incoming
+ 
+ 	for opt in $options
diff -ruN /usr/ports/news/s-news/files/patch-nntpd.c s-news/files/patch-nntpd.c
--- /usr/ports/news/s-news/files/patch-nntpd.c	Thu Jan  1 03:00:00 1970
+++ s-news/files/patch-nntpd.c	Sun Jul 25 10:24:33 2004
@@ -0,0 +1,247 @@
+--- nntpd.c	Sat May 18 20:21:56 2002
++++ nntpd.c	Wed Aug 21 22:09:46 2002
+@@ -2,6 +2,7 @@
+  *  S-News version 0.1.9 - A Simple News Server
+  *  Copyright (C) 1998 Christopher John Purnell
+  *                     cjp@lost.org.uk
++ *  XPAT support added in 2002 by Tony Houghton <tony@realh.co.uk>
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -106,6 +107,7 @@
+ static void do_listgroup(char *);
+ static void do_xover(char *);
+ static void do_xhdr(char *);
++static void do_xpat(char *);
+ static void do_xpath(char *);
+ static void do_ihave(char *);
+ static void do_post(char *);
+@@ -239,6 +241,10 @@
+ 		{
+ 			do_xhdr(arg);
+ 		}
++		else if (!strcasecmp(line,"xpat"))
++		{
++			do_xpat(arg);
++		}
+ 		else if (!strcasecmp(line,"xover"))
+ 		{
+ 			do_xover(arg);
+@@ -811,10 +817,11 @@
+ 	printf(".\r\n");
+ }
+ 
++static char *xhdr_h[7] = { "Subject","From","Date","Message-ID",
++		      "References","Bytes","Lines" };
++
+ static void do_xhdr(char *arg)
+ {
+-	static char *h[7] = { "Subject","From","Date","Message-ID",
+-			      "References","Bytes","Lines" };
+ 	char *fmt,*cp;
+ 	unsigned char c;
+ 	int i;
+@@ -835,7 +842,7 @@
+ 	i = -1; fmt = "%u \r\n";
+ 	for (u=0; u<7; ++u)
+ 	{
+-		if (!strcasecmp(arg,h[u]))
++		if (!strcasecmp(arg,xhdr_h[u]))
+ 		{
+ 			fmt = ((i=u) < 5) ? "%u %s\r\n" : "%u %u\r\n";
+ 		}
+@@ -1118,6 +1125,7 @@
+ 		printf("ARTICLE   HEAD      BODY      STAT\r\n");
+ 		printf("GROUP     LIST      NEXT      LAST\r\n");
+ 		printf("LISTGROUP XHDR      XOVER     XPATH\r\n");
++		printf("XPAT      ");
+ 	}
+ 	if (canpost)
+ 	{
+@@ -1127,7 +1135,7 @@
+ 	{
+ 		printf("IHAVE     ");
+ 	}
+-	printf("HELP      QUIT\r\n.\r\n");
++	printf("\r\nHELP      QUIT\r\n.\r\n");
+ }
+ 
+ static int match_pat(char *pat,char *str)
+@@ -1533,3 +1541,177 @@
+ 
+ 	return str;
+ }
++
++static int match_pattern(const char *pat,const char *str)
++{
++	char c;
++
++	while ((c = *(pat++)))
++	{
++		switch (c)
++		{
++		case '*':
++			if (!*pat)
++				return (1);
++			while (*str)
++			{
++				if (match_pattern(pat,str))
++					return (1);
++				++str;
++			}
++			break;
++		case '?':
++			if (!*str)
++				return (0);
++			break;
++		case '[':
++			if (*str)
++			{
++				unsigned char rev,mat=0,l=0,h,u=*str;
++
++				if ((rev = (*pat=='^'?1:0)))
++					pat++;
++				if ((c=*pat)) do
++				{
++					pat++;
++					if (c=='-' && l && (h=*pat) && h!=']')
++					{
++						pat++;
++						if (u>=l && u<=h) mat=1;
++						l = 0;
++					}
++					else
++					{
++						if (u==c) mat=1;
++						l = c;
++					}
++				}
++				while ((c=*pat) && c!=']');
++				if (c)
++					++pat;
++				if (mat==rev)
++					return (0);
++			}
++			else
++				return (0);
++			break;
++		default:
++			if (*str!=c)
++				return (0);
++			break;
++		}
++		++str;
++	}
++
++	return (!*str);
++}
++
++static void do_xpat(char *arg)
++{
++	char *cp;
++	unsigned char c;
++	int i;
++	unsigned u,l;
++	char const **patterns = NULL;
++	size_t pat_size = 0;
++	size_t npats = 0;
++
++	if (check_read()) return;
++
++	if (!grp)
++	{
++		printf("412 no newsgroup has been selected\r\n");
++		return;
++	}
++
++	cp = arg;
++	while ((c=*(cp)) && !isspace(c)) cp++;
++	if (*cp) *(cp++) = '\0';
++
++	i = -1;
++	for (u=0; u<7; ++u)
++	{
++		if (!strcasecmp(arg,xhdr_h[u]))
++		{
++		//	fmt = ((i=u) < 5) ? "%u %s\r\n" : "%u %u\r\n";
++			i = u;
++		}
++	}
++	if (i == -1)
++	{
++		printf("501 header not in index\r\n");
++		return;
++	}
++
++	while ((c=*(cp)) && isspace(c)) cp++;
++	if (*cp)
++	{
++		u = strtoul(cp,&cp,10);
++		if (*cp == '-')
++		{
++			if (*(++cp)) l = strtoul(cp,&cp,10);
++			else l = grp->last;
++		}
++		else l = u;
++	}
++	else u = l = art;
++
++	if (!u)
++	{
++		printf("420 no article has been selected\r\n");
++		return;
++	}
++
++	patterns = malloc(sizeof(char const *));
++	pat_size = 1;
++	do
++	{
++		while (*cp && isspace(*cp)) ++cp;
++		if (*cp)
++		{
++			if (npats + 1 > pat_size)
++			{
++				patterns = realloc(patterns, (pat_size *= 2) *
++						sizeof(const char *));
++			}
++			patterns[npats++] = cp;
++			while (*cp && !isspace(*cp)) ++cp;
++			if (*cp) *(cp++) = 0;
++		}
++	} while (*cp);
++	if (!npats)
++	{
++		free(patterns);
++		printf("501 command syntax error\r\n");
++	}
++
++	printf("221 Header follows\r\n");
++	
++	while (u <= l)
++	{
++		struct overview *o;
++
++		if ((o = find_overview(u)))
++		{
++			size_t pat;
++			char matchnum[12];
++			char *match = i < 5 ? (&o->subject)[i] :
++				(sprintf(matchnum, "%u", ((unsigned *)
++							  (&o->subject))[i]),
++				 matchnum);
++
++			for (pat = 0; pat < npats; ++pat)
++			{
++				if (match_pattern(patterns[pat], match))
++				{
++					printf("%u %s\r\n", u, match);
++				}
++			}
++		}
++		++u;
++	}
++
++	printf(".\r\n");
++	free(patterns);
++}
++
diff -ruN /usr/ports/news/s-news/files/patch-qnews.c s-news/files/patch-qnews.c
--- /usr/ports/news/s-news/files/patch-qnews.c	Thu Jan  1 03:00:00 1970
+++ s-news/files/patch-qnews.c	Sun Jul 25 10:24:36 2004
@@ -0,0 +1,95 @@
+--- qnews.c	2002-05-18 20:21:42.000000000 +0100
++++ qnews.c	2002-10-12 19:23:55.000000000 +0100
+@@ -2,6 +2,8 @@
+  *  S-News version 0.1.9 - A Simple News Server
+  *  Copyright (C) 1998 Christopher John Purnell
+  *                     cjp@lost.org.uk
++ *  flock modification (c) 2002 Tony Houghton
++ *  		       tony@realh.co.uk
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -22,7 +24,13 @@
+ #include "config.h"
+ #endif
+ 
++#include <sys/types.h>
+ #include <sys/stat.h>
++#ifdef HAVE_SYS_FILE_H
++#include <sys/file.h>
++#endif
++#include <fcntl.h>
++
+ #ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+ #endif
+@@ -79,15 +87,37 @@
+ 			if (match_group(ptr->value,line,end))
+ 			{
+ 				FILE *fp;
++			#ifdef HAVE_SYS_FILE_H
++				int fd;
++			#endif
+ 
+ 				sprintf(file,CONFDIR"/suck/%s/outgoing",
+-					ptr->name);
++				    ptr->name);
+ 
+-				if (!(fp = fopen(file,"a")))
++			#ifdef HAVE_SYS_FILE_H
++				if ((fd = open(file,O_WRONLY|O_APPEND|O_CREAT,
++						0644)) == -1)
+ 				{
+-					perror(file);
+-					return (1);
++				    perror(file);
++				    return (1);
++				}
++				if (flock(fd,LOCK_EX) == -1)
++				{
++				    perror(file);
++				    return (1);
++				}
++				if (!(fp = fdopen(fd,"a")))
++				{
++				    perror(file);
++				    return (1);
+ 				}
++			#else
++                                if (!(fp = fopen(file,"a")))
++                                {
++                                        perror(file);
++                                        return (1);
++                                }
++			#endif
+ 
+ 				if (fputs(line,fp) < 0 ||
+ 				    fputc('\n',fp) < 0)
+@@ -103,6 +133,9 @@
+ 					return (1);
+ 				}
+ 
++				/* By commenting this break we can post to
++				 * multiple servers instead of stopping after
++				 * first match*/
+ 				break;
+ 			}
+ 		}
+@@ -204,7 +237,7 @@
+ 				return (0);
+ 			break;
+ 		case '[':
+-			if (str>=end)
++			if (str<end)
+ 			{
+ 				unsigned char rev,mat=0,l=0,h,u=*str;
+ 
+@@ -229,6 +262,8 @@
+ 				if (mat==rev)
+ 					return (0);
+ 			}
++			else
++				return (0);
+ 			break;
+ 		default:
+ 			if (str>=end || *str!=c)
diff -ruN /usr/ports/news/s-news/files/patch-rnews.c s-news/files/patch-rnews.c
--- /usr/ports/news/s-news/files/patch-rnews.c	Thu Jan  1 03:00:00 1970
+++ s-news/files/patch-rnews.c	Sun Jul 25 10:24:40 2004
@@ -0,0 +1,453 @@
+--- rnews.c	2002-05-18 20:21:26.000000000 +0100
++++ rnews.c	2002-09-08 12:50:41.000000000 +0100
+@@ -2,6 +2,8 @@
+  *  S-News version 0.1.9 - A Simple News Server
+  *  Copyright (C) 1998 Christopher John Purnell
+  *                     cjp@lost.org.uk
++ *  Supersedes/cancel modifications (C) 2002 Tony Houghton
++ *  		       tony@realh.co.uk
+  *
+  *  This program is free software; you can redistribute it and/or modify
+  *  it under the terms of the GNU General Public License as published by
+@@ -50,6 +52,8 @@
+ 
+ #include "snews.h"
+ 
++#define DEBLOG(a) /* fprintf a */
++
+ struct header
+ {
+ 	struct header *next;
+@@ -78,14 +82,23 @@
+ static FILE *open_lock(char *);
+ static int file_name(struct header *,char *,unsigned);
+ static GDBM_FILE open_history(char *,int);
++static int read_string(FILE *,char *,unsigned);
++static void delete_msg(const char *);
++static int whole_string(struct header_pointer *,char *,unsigned);
++static int read_line(FILE *,char *,unsigned);
++static int isolate_addr(char *);
+ 
+ static char *progname;
+ static char fqdn[BUFLEN];
+ static char msgid[BUFLEN];
+ static char article[BUFLEN];
++static char vsender[BUFLEN];
++static char cancel[BUFLEN];
+ static char queue=0,approved=0;
++static int cancel_only;
+ 
+ struct header junk = { 0, "junk", 0 };
++struct header control_cancel = { 0, "control.cancel", 0 };
+ 
+ int main(int argc,char **argv)
+ {
+@@ -95,6 +108,16 @@
+ 
+ 	set_ug_id();
+ 
++	/* For logging, remove this in release */
++	/*
++	i = open("/var/log/news/rnews", O_WRONLY|O_CREAT|O_APPEND, 0644);
++	if (i)
++	{
++	    close(2);
++	    dup2(i, 2);
++	}
++	*/
++
+ 	progname = argv[0];
+ 
+ 	if (get_fqdn())
+@@ -116,12 +139,18 @@
+ 		return (1);
+ 	}
+ 
++	cancel[0] = 0;
++	vsender[0] = 0;
++	cancel_only = 0;
++
+ 	if (!(hdr = read_header()))
+ 		return (1);
+ 
+ 	if (!(ngrp = parse_header(hdr)))
+ 		return (1);
+ 
++	DEBLOG((stderr, "Message-ID: %s\n", msgid));
++
+ 	if (!(fp = open_lock(CONFDIR"/active.n")))
+ 	{
+ 		perror(progname);
+@@ -130,8 +159,16 @@
+ 	
+ 	if (!(i = chk_article(msgid)))
+ 	{
+-		if (!(ngrp = update_active(CONFDIR"/active",CONFDIR"/active.n",
+-					  fp,ngrp)))
++		DEBLOG((stderr, "chk_article OK\n"));
++		if (cancel_only)
++		{
++			ngrp = update_active(CONFDIR"/active",
++					     CONFDIR"/active.n",
++					     fp,&control_cancel);
++			DEBLOG((stderr, "cancel_only, ngrp = %d\n", ngrp));
++		}
++		else if (!(ngrp = update_active(CONFDIR"/active",
++			    CONFDIR"/active.n",fp,ngrp)))
+ 		{
+ 			rewind(fp);
+ 			if (ftruncate(fileno(fp),0))
+@@ -144,8 +181,11 @@
+ 		i = !ngrp;
+ 	}
+ 
++	DEBLOG((stderr, "After chk_article and update_active, result = %d (0 is good)\n", i));
++
+ 	if (fclose(fp) || i || write_article(hdr,ngrp))
+ 	{
++		DEBLOG((stderr, "fclose || i || write_article failed\n"));
+ 		unlink(CONFDIR"/active.n");
+ 		return (1);
+ 	}
+@@ -158,6 +198,9 @@
+ 		return (1);
+ 	}
+ 
++	if (cancel[0])
++		delete_msg(cancel);
++
+ 	if (!queue) return (0);
+ 
+ 	execl(QNEWSPATH,QNEWSARG0,article,0);
+@@ -301,11 +344,79 @@
+ 			{
+ 				approved=1;
+ 			}
++			else if (!strncasecmp(hdr->line,"Sender:",7))
++			{
++				hp.hdr = hdr;
++				hp.ptr = hdr->line+7;
++				if (whole_string(&hp,vsender,BUFLEN)<=0)
++				{
++					fprintf(stderr,"%s: bad Sender\n",
++						progname);
++					return (0);
++				}
++				DEBLOG((stderr, "Found Sender: %s\n", vsender));
++			}
++			else if (!vsender[0] && !strncasecmp(hdr->line,"From:",5))
++			{
++				hp.hdr = hdr;
++				hp.ptr = hdr->line+5;
++				if (whole_string(&hp,vsender,BUFLEN)<=0)
++				{
++					fprintf(stderr,"%s: bad From\n",
++						progname);
++					return (0);
++				}
++				DEBLOG((stderr, "Found From: %s\n", vsender));
++			}
++			else if (!strncasecmp(hdr->line,"Supersedes:",11))
++			{
++				hp.hdr = hdr;
++				hp.ptr = hdr->line+11;
++				if (whole_string(&hp,cancel,BUFLEN)<=0)
++				{
++					fprintf(stderr,"%s: bad Supersedes\n",
++						progname);
++					return (0);
++				}
++				DEBLOG((stderr, "Found Supersedes: %s\n", cancel));
++			}
++			else if (!strncasecmp(hdr->line,"Control: cancel",15))
++			{
++				hp.hdr = hdr;
++				hp.ptr = hdr->line+15;
++				if (whole_string(&hp,cancel,BUFLEN)<=0)
++				{
++					fprintf(stderr,"%s: bad cancel\n",
++						progname);
++					return (0);
++				}
++				DEBLOG((stderr, "Found cancel: %s\n", cancel));
++				cancel_only = 1;
++			}
++			else if (!strncasecmp(hdr->line,"Also-Control: cancel",20))
++			{
++				hp.hdr = hdr;
++				hp.ptr = hdr->line+20;
++				if (whole_string(&hp,cancel,BUFLEN)<=0)
++				{
++					fprintf(stderr,"%s: bad cancel\n",
++						progname);
++					return (0);
++				}
++				DEBLOG((stderr, "Found also-cancel: %s\n", cancel));
++			}
+ 
+ 		}
+ 		hdr = hdr->next;
+ 	}
+ 
++	if (vsender[0])
++	{
++		int ires=isolate_addr(vsender);
++		DEBLOG((stderr,"vsender address = %s (result %d)\n",
++					vsender,ires));
++	}
++	
+ 	return (*msgid?ret:0);
+ }
+ 
+@@ -597,7 +708,10 @@
+ 	int ret;
+ 
+ 	if (!(dbf = open_history(CONFDIR"/history",GDBM_READER)))
++	{
++		DEBLOG((stderr, "chk_article: Couldn't open history\n"));
+ 		return (1);
++	}
+ 
+ 	key.dsize = strlen(key.dptr = id) + 1;
+ 
+@@ -605,6 +719,7 @@
+ 
+ 	gdbm_close(dbf);
+ 
++	DEBLOG((stderr, "chk_article: %s exists: %d\n", id, ret));
+ 	return (ret);
+ }
+ 
+@@ -642,3 +757,232 @@
+ 	}
+ 	return (dbf);
+ }
++
++/* Added by Tony Houghton <tony@realh.co.uk>, mostly copied from expire.c */
++
++static void delete_msg(const char *msgid)
++{
++	char buf[BUFLEN];
++	char sender[BUFLEN];
++	struct stat st;
++	FILE *fp;
++	GDBM_FILE dbf;
++	datum key,value;
++	char *file;
++
++	DEBLOG((stderr, "Deleting %s\n", msgid));
++	if (!(dbf = open_history(CONFDIR"/history",GDBM_READER)))
++		return;
++	key.dsize = strlen(key.dptr = (char *) msgid) + 1;
++	value = gdbm_fetch(dbf, key);
++	if ((file = value.dptr) == NULL)
++		return;
++	DEBLOG((stderr, "Filename is %s\n", file));
++	
++	if (!(fp = fopen(file,"r")))
++	{
++		if (errno != ENOENT)
++			perror(file);
++		free(file);
++		return;
++	}
++
++	if (fstat(fileno(fp),&st))
++	{
++		perror(file);
++		free(file);
++		return;
++	}
++
++	sender[0] = 0;
++	while (fgets(buf,6,fp))
++	{
++		if (!sender[0] && !strcasecmp(buf,"From:"))
++		{
++			if (read_line(fp,sender,BUFLEN) <= 0)
++			{
++				fclose(fp);
++				fprintf(stderr,"%s: bad From header\n",file);
++				free(file);
++				return;
++			}
++			DEBLOG((stderr, "From: %s\n", sender));
++		}
++		else if (!strcasecmp(buf,"Sende") && fgetc(fp) == 'r' &&
++			fgetc(fp) == ':')
++		{
++			if (read_line(fp,sender,BUFLEN) <= 0)
++			{
++				fclose(fp);
++				fprintf(stderr,"%s: bad Sender\n",file);
++				free(file);
++				return;
++			}
++			DEBLOG((stderr, "Sender: %s\n", sender));
++		}
++		else if (buf[0] == '\n')
++			break;
++	}
++	rewind(fp);
++	if (isolate_addr(sender) == -1)
++	{
++		fprintf(stderr,"Invalid sender, can't cancel\n");
++		free(file);
++		fclose(fp);
++		return;
++	}
++	DEBLOG((stderr,"Sender address = %s\n",sender));
++
++	if (strcasecmp(sender,vsender))
++	{
++		fprintf(stderr,"Wrong sender, can't cancel\n");
++		free(file);
++		fclose(fp);
++		return;
++	}
++
++	while (fgets(buf,6,fp))
++	{
++		char *cp;
++		int c;
++
++		if (strcasecmp(buf,"Xref:"))
++		{
++			if ((cp = strchr(buf,'\n')))
++			{
++				if (cp == buf) break;
++			}
++			else
++			{
++				while ((c = fgetc(fp)) != EOF && c != '\n');
++				if (c == EOF) break;
++			}
++		}
++		else
++		{
++			if ((read_string(fp,buf,BUFLEN) <= 0) ||
++			    strcasecmp(buf,fqdn))
++			{
++				fclose(fp);
++				fprintf(stderr,"%s: bad Xref line\n",file);
++				free(file);
++				return;
++			}
++
++			while ((c = read_string(fp,buf,BUFLEN)))
++			{
++				if (c < 0)
++				{
++					fclose(fp);
++					fprintf(stderr,"%s: bad Xref line\n",
++						file);
++					free(file);
++					return;
++				}
++
++				cp = buf;
++				while ((c = *cp))
++				{
++					if (c == '.' || c ==':')
++						*cp = '/';
++					++cp;
++				}
++
++				if (strcmp(file,buf) &&
++				    unlink(buf) && errno != ENOENT)
++				{
++					perror(buf);
++					fclose(fp);
++					free(file);
++					return;
++				}
++			}
++
++			break;
++		}
++	}
++	if (ferror(fp))
++	{
++		perror(file);
++		free(file);
++		fclose(fp);
++		return;
++	}
++
++	fclose(fp);
++	if (unlink(file))
++		perror(file);
++	free(file);
++}
++
++static int read_string(FILE *fp,char *str,unsigned len)
++{
++	int c;
++	unsigned i=0;
++
++	while ((c = fgetc(fp)) != EOF && c != '\n' && isspace(c));
++
++	while (c != EOF && !isspace(c))
++	{
++		str[i]=c;
++		if (++i>=len) return (-1);
++		c = fgetc(fp);
++	}
++	str[i]='\0';
++
++	return (i);
++}
++
++static int whole_string(struct header_pointer *hp,char *str,unsigned len)
++{
++        unsigned i=0;
++	unsigned char c;
++
++        while ((c = next_char(hp)) && isspace(c));
++
++        while (c && c != '\n')
++        {
++                str[i]=c;
++                if (++i>=len) return (-1);
++                c = next_char(hp);
++        }
++	str[i]='\0';
++
++        return (i);
++}
++ 
++static int read_line(FILE *fp,char *str,unsigned len)
++{
++	int c;
++	unsigned i=0;
++
++	while ((c = fgetc(fp)) != EOF && c != '\n' && isspace(c));
++
++	while (c != EOF && c != '\n')
++	{
++		str[i]=c;
++		if (++i>=len) return (-1);
++		c = fgetc(fp);
++	}
++	str[i]='\0';
++
++	return (i);
++}
++
++static int isolate_addr(char *str)
++{
++    char *at;
++    unsigned len;
++
++    if (!(at=strchr(str,'@')))
++	    return -1;
++    while (at != str && !isspace(*(at-1)) && *(at-1) != '<')
++	    --at;
++    for (len = 0;
++	 len <= strlen(at) && !isspace(at[len]) && at[len] !='>';
++	 ++len);
++    memmove(str,at,len);
++    str[len]=0;
++    return 0;
++}
++
--- s-news.diff ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E1BodhD-000DNh-Cb>