[net.sources.bugs] bugfix for latest version of vn

andrew@munnari.oz (Andrew Mark Worsley) (01/12/87)

   turner@imagen writes about a problem that occurs when header lines
have a new line in them. This is legal and not handled by vn which if
the line does not have a ':' thinks it must be the body of the article and
stops processing header lines. On my system, 4.2BSD/Perkin Elmer 3240,
it would cause the number lines to be unset from zero which, when used in
determining the percentage of lines read, did a divide by zero - floating
exception ! Looking at the code I would have thought it would do the same
on any system if the printing of the headers was suppressed.

   I developed a patch that should handle the header lines extended over more
than one line, and follows below. It has worked here for 3 days. Also enclosed
is a patch that makes the default file for saving articles the
newsgroup.article_number e.g. net.sources.bugs.1234 . If you don't like this
edit it out. 
		------------- Header Line Patch ---------------
*** reader.c_old	Wed Jan  7 13:56:46 1987
--- reader.c	Wed Jan  7 16:23:43 1987
***************
*** 40,45
  static int Rlines;
  static int Hlines;
  
  #ifdef ADDRMUNGE
  static int Newaddr;
  #endif

--- 40,47 -----
  static int Rlines;
  static int Hlines;
  
+ char	*nfgets();
+ 
  #ifdef ADDRMUNGE
  static int Newaddr;
  #endif
***************
*** 199,209
  			** 1 line lookahead and empty line at beginning
  			** of article.
  			*/
! 			if (Headflag)
! 				percent = ((Rlines-2)*100)/(artlin+Hlines);
! 			else
! 				percent = ((Rlines-Hlines-2)*100)/artlin;
! 			sprintf (pstr,PAGE_MID,percent);
  		}
  		else
  		{

--- 201,214 -----
  			** 1 line lookahead and empty line at beginning
  			** of article.
  			*/
! 			if (artlin != 0) {
! 				if (Headflag)
! 					percent =
! 					((Rlines-2)*100)/(artlin+Hlines);
! 				else
! 					percent =((Rlines-Hlines-2)*100)/artlin;
! 				sprintf (pstr,PAGE_MID,percent);
! 			}
  		}
  		else
  		{
***************
*** 294,300
  	*dist = *mid = *from = *title = *ngrp = *flto = *reply = '\0';
  
  	/* for conditional is abnormal - expected exit is break */
! 	for (count = 0; count < HDR_LINES && fgets(buf,RECLEN-1,Fpread) != NULL; ++count)
  	{
  
  		/* reset position and bail out at first non-header line */

--- 299,305 -----
  	*dist = *mid = *from = *title = *ngrp = *flto = *reply = '\0';
  
  	/* for conditional is abnormal - expected exit is break */
! 	for (count = 0; count < HDR_LINES && nfgets(buf,RECLEN-1,Fpread) != NULL; ++count)
  	{
  
  		/* reset position and bail out at first non-header line */
***************
*** 899,902
  	else
  		*buf = '\0';
  	return(0.0);
  }

--- 904,951 -----
  	else
  		*buf = '\0';
  	return(0.0);
+ }
+ 
+ 
+ /*
+  * get the next header line unfolding it as necessary
+  */
+ char	*
+ nfgets(buf, size, fp)
+ char	*buf;
+ int	size;
+ FILE	*fp;
+ {
+ 	register 	int	c;
+ 
+ 	size--; /* space for the null */
+ 	while (!feof(fp)) {
+ 		if ((c = getc(fp)) == '\n') {
+ 			if ((c = getc(fp)) == '\t' || c == ' ')
+ 				continue;
+ 			ungetc(c, fp);
+ 			*buf++ = '\n';
+ 			*buf++ = '\0';
+ 			return (buf);
+ 		}
+ 		if (size-- > 0)
+ 			*buf++ = c;
+ 		if (c == '\r') {
+ 			if ((c = getc(fp)) != '\n') {
+ 				ungetc(c, fp);
+ 				continue;
+ 			}
+ 			if ((c = getc(fp)) != ' ' && c != '\t') {
+ 				*buf++ = '\0';
+ 				ungetc(c, fp);
+ 				return (buf);
+ 			}
+ 			buf--;
+ 			size++;
+ 			continue;
+ 		}
+ 	}
+ 
+ 	*buf++ = '\0';
+ 	return (NULL);
  }
	 ---------------- Save file name patch --------------------
*** vn.c.orig	Mon Jan  5 17:12:32 1987
--- vn.c	Mon Jan 12 11:23:04 1987
***************
*** 805,811 ****
--- 805,811 ----
  char *s;
  {
  	char *ptr, cmd [RECLEN], newfile [MAX_C+1], prompt[MAX_C];
!<	char *strtok(), *strpbrk(), *str_store();
  
  	for (ptr = s; (ptr = strpbrk(ptr, LIST_SEP)) != NULL; ++ptr)
  		*ptr = ' ';
---------------
  char *s;
  {
  	char *ptr, cmd [RECLEN], newfile [MAX_C+1], prompt[MAX_C];
!>	char *strtok(), *strpbrk(), *str_store(), *gsfile();
  
  	for (ptr = s; (ptr = strpbrk(ptr, LIST_SEP)) != NULL; ++ptr)
  		*ptr = ' ';
***************
*** 815,820 ****
--- 815,821 ----
---------------
  		dig_list (s);
  	if (*s != '\0')
  	{
+>		Savefile = gsfile();
  		sprintf (prompt,SAVFORM,Savefile);
  		user_str (newfile,prompt,1);
  		ptr = newfile;
***************
*** 1201,1204 ****
--- 1202,1221 ----
---------------
  		*rec = RECBIAS;
  		*hirec = Page.h.artnum + RECBIAS;
  	}
+>}
+>
+>/*
+> * generate default save filename
+> */
+>char	*
+>gsfile()
+>{
+> 	static	char	buf[RECLEN];
+>	register int	l;
+> 
+>	strncpy(buf, (Page.h.group)->nd_name, RECLEN);
+>	buf[RECLEN - 1] = '\0';
+>	if ((l = strlen(buf)) < RECLEN - 7)
+>		sprintf(buf + l, ".%d", Page.h.artnum);
+>	return (buf);
  }
*** reader.c_old	Mon Jan 12 10:36:15 1987
--- reader.c	Mon Jan 12 11:10:18 1987
***************
*** 457,465 ****
--- 457,466 ----
  */
  static saver ()
  {
!<	char *fn,cmd[RECLEN],*str_store(),*rprompt();
  
  	tty_set (SAVEMODE);
  	sprintf (cmd,SAVFORM,Savefile);
  	fn = rprompt(cmd,cmd);
  	if (fn != NULL)
---------------
  */
  static saver ()
  {
!>	char *fn,cmd[RECLEN],*str_store(),*rprompt(), *gsfile();
  
  	tty_set (SAVEMODE);
+>	Savefile = gsfile();
  	sprintf (cmd,SAVFORM,Savefile);
  	fn = rprompt(cmd,cmd);
  	if (fn != NULL)

bobm@rtech.UUCP (Bob Mcqueer) (01/13/87)

The continuation of header lines has recently been brought to my attention.
I've never seen it before, so I assume it is a relatively recent addition.
Yes, indeed, there is a problem if the "Lines:" header line can't be found,
and a protection against division by 0 should be added in any case.

Andrew's patch looks like the right idea.  Thanks.  I'll check it out for
the "official" copy.

You might also change the decision from "line contains ':'" to "line is
empty".  This is a quick fix which remedies the problems being discussed,
although only the first line of a multi-line header will be found.
I hadn't originally used this rule because I was worried about chopping
off lines of articles if the empty line was missing.

When I saw Andrew's article this morning, I was going to publish the
following change in reader.c:

205c205,217
< 				percent = ((Rlines-Hlines-2)*100)/artlin;
---
> 			{
> 				/*
> 				** protect against division by zero - artlin
> 				** shouldn't actually come up zero at this
> 				** point if "Lines:" header line was found
> 				** and was correct.  "999" will let user
> 				** know the percentage is obviously wrong.
> 				*/
> 				if (artlin > 0)
> 					percent = ((Rlines-Hlines-2)*100)/artlin;
> 				else
> 					percent = 999;
> 			}
301c313
< 		if (index(buf,':') == NULL)
---
> 		if (buf[0] == '\n')
-- 

Bob McQueer
{amdahl, sun, mtxinu, hoptoad, cpsc6a}!rtech!bobm