summaryrefslogtreecommitdiff
path: root/news/s-news/files/patch-rnews.c
diff options
context:
space:
mode:
authorPav Lucistnik <pav@FreeBSD.org>2004-07-25 11:45:43 +0000
committerPav Lucistnik <pav@FreeBSD.org>2004-07-25 11:45:43 +0000
commitb2c122033361ea44c81be713f7d8b1c8f7638e46 (patch)
treea50f89bebed9fbb0e4e709cb66b83715c8004be3 /news/s-news/files/patch-rnews.c
parentAdd a knob WITHOUT_PERL_64BITINT. This is primarily intended for those (diff)
- Add lock outgoing files with flock, XPAT command, ability to handle
supersedes and cancel control messages. PR: ports/69551 Submitted by: Andrey Slusar <vasallia@ukr.net> (maintainer)
Diffstat (limited to '')
-rw-r--r--news/s-news/files/patch-rnews.c453
1 files changed, 453 insertions, 0 deletions
diff --git a/news/s-news/files/patch-rnews.c b/news/s-news/files/patch-rnews.c
new file mode 100644
index 000000000000..5682144682b7
--- /dev/null
+++ b/news/s-news/files/patch-rnews.c
@@ -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;
++}
++