summaryrefslogtreecommitdiff
path: root/news
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
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)
Notes
Notes: svn path=/head/; revision=114646
Diffstat (limited to 'news')
-rw-r--r--news/s-news/Makefile1
-rw-r--r--news/s-news/files/patch-active5
-rw-r--r--news/s-news/files/patch-config.h.in12
-rw-r--r--news/s-news/files/patch-configure11
-rw-r--r--news/s-news/files/patch-newfeed.in10
-rw-r--r--news/s-news/files/patch-nntpd.c247
-rw-r--r--news/s-news/files/patch-qnews.c95
-rw-r--r--news/s-news/files/patch-rnews.c453
8 files changed, 831 insertions, 3 deletions
diff --git a/news/s-news/Makefile b/news/s-news/Makefile
index bfe4285247c5..6e2043b7db0c 100644
--- a/news/s-news/Makefile
+++ b/news/s-news/Makefile
@@ -7,6 +7,7 @@
PORTNAME= s-news
PORTVERSION= 0.1.11
+PORTREVISION= 1
CATEGORIES= news
MASTER_SITES= http://www.lost.org.uk/
diff --git a/news/s-news/files/patch-active b/news/s-news/files/patch-active
new file mode 100644
index 000000000000..75fe5f3955a3
--- /dev/null
+++ b/news/s-news/files/patch-active
@@ -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 --git a/news/s-news/files/patch-config.h.in b/news/s-news/files/patch-config.h.in
new file mode 100644
index 000000000000..088da1f6fedd
--- /dev/null
+++ b/news/s-news/files/patch-config.h.in
@@ -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 --git a/news/s-news/files/patch-configure b/news/s-news/files/patch-configure
new file mode 100644
index 000000000000..90df458ec725
--- /dev/null
+++ b/news/s-news/files/patch-configure
@@ -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 --git a/news/s-news/files/patch-newfeed.in b/news/s-news/files/patch-newfeed.in
index 6c6a80bec0f7..afae71c81e85 100644
--- a/news/s-news/files/patch-newfeed.in
+++ b/news/s-news/files/patch-newfeed.in
@@ -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 --git a/news/s-news/files/patch-nntpd.c b/news/s-news/files/patch-nntpd.c
new file mode 100644
index 000000000000..fad8f1c7b773
--- /dev/null
+++ b/news/s-news/files/patch-nntpd.c
@@ -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 --git a/news/s-news/files/patch-qnews.c b/news/s-news/files/patch-qnews.c
new file mode 100644
index 000000000000..415cbed2c9a7
--- /dev/null
+++ b/news/s-news/files/patch-qnews.c
@@ -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 --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;
++}
++