[net.bugs] Unusual failure of ranlib

friesen@psivax.UUCP (Stanley Friesen) (11/22/84)

<>

	We have run into an unusual, and frustrating error in ranlib.
We are using it in conjunction with make and ar to maintain a series
of archives being shared by several users.  Periodically it will choke
on an existing archive with the following message:

ranlib: arname(__.SYMDEF): old format .o file

Once it has done so it will continue to choke on that archive.
Deleting __.SYMDEF from the archive and re-making it works, but ranlib
procedes to choke again next time it is used.  Also following this
the program nm fails with a similar error message. I have been unable
to determine the conditions under which this behavior is initiated.

P.S. One archive which exhibited this behavior for awhile has cleared up.?

kre@munnari.OZ (Robert Elz) (11/24/84)

In article <152@psivax.UUCP> friesen@psivax.UUCP (Stanley Friesen) writes:
| 
| 	We have run into an unusual, and frustrating error in ranlib.
| We are using it in conjunction with make and ar to maintain a series
| of archives being shared by several users.  Periodically it will choke
| on an existing archive with the following message:
| 
| ranlib: arname(__.SYMDEF): old format .o file
| 
| Once it has done so it will continue to choke on that archive.
| Deleting __.SYMDEF from the archive and re-making it works, but ranlib
| procedes to choke again next time it is used.  Also following this
| the program nm fails with a similar error message. I have been unable
| to determine the conditions under which this behavior is initiated.
| 
| P.S. One archive which exhibited this behavior for awhile has cleared up.?

The problem occurs when the number of entry points in the archive
just happens to make the first word of the __.SYMDEF file be 0408.
(This is calculated as (num of entry points) * sizeof(struct ranlib)).

Unfortunately, there is no simple fix, without changing ranlib and ld
and breaking all existing ranlib'd libraries, and we know how much people
complain whenever something has to change to fix a bug :-)

The "work around it" kludge is simply to add a new entry point
to the archive (most easily done by adding a dummy file, that
is never going to be used, as ...

	/* ranlib_bug.c */
	_d_u_m_m_y_() {}

which, while ugly, will change the number of entry points).  Worst
of this "solution" is that should another entry point be deleted,
then the problem will simply occur again (solution now is to delete
the dummy entry ....).

A better fix would be to simply to add a real magic number at the
start of __.SYMDEF files (then ld could check that, and not simply
rely on the name __.SYMDEF in the archive), but I will leave that
for Berkeley to do sometime, so they will have to suffer all the
abuse from people who relied on the old behaviour.  They are used to it!

Robert Elz					decvax!mulga!kre

chris@umcp-cs.UUCP (Chris Torek) (11/25/84)

Why not simply special-case the code in ``ld'' and ``ranlib'' for the
name ``__.SYMDEF'', since it is already a special case?  (In other words,
ignore its apparent magic number.)
-- 
(This line accidently left nonblank.)

In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690
UUCP:	{seismo,allegra,brl-bmd}!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@maryland

berry@zinfandel.UUCP (Berry Kercheval) (11/28/84)

In article <1336@umcp-cs.UUCP> chris@umcp-cs.UUCP (Chris Torek) writes:

>Why not simply special-case the code in ``ld'' and ``ranlib'' for the
>name ``__.SYMDEF'', since it is already a special case?  (In other words,
>ignore its apparent magic number.)


That is exactly what I did on our 4.1 (and other random) systems.

``ld'' is already special cased (at least ours was).
here is a diff for ``ranlib''.  It's long, because I added a bunch of 
comments while I was tracking down this problem.  The #define is
called BETH_FIX after Beth Stonebraker, who stumbled upon the problem.

--
Berry Kercheval		Zehntel Inc.	(ihnp4!zehntel!zinfandel!berry)
(415)932-6900

##############################CUT HERE##############################

*** ranlib.c.old	Wed May 18 15:04:34 1983
--- ranlib.c		Wed May 18 14:55:11 1983
***************
*** 7,12
  static	char sccsid[] = "@(#)ranlib.c 4.3 4/26/81";
  /*
   * ranlib - create table of contents for archive; string table version
   */
  #include <sys/types.h>
  #include <ar.h>

--- 1,13 -----
  static	char sccsid[] = "@(#)ranlib.c 4.3 4/26/81";
  /*
   * ranlib - create table of contents for archive; string table version
+  *
+  * 18 May 1983 BBK -- Comments added 
+  *
+  * 		      Special case added:  DO NOT try to extract the symbol
+  *		      table from a file named "__.SYMDEF" even if it DOES
+  *		      start with a valid magic number. Enabled with #define
+  *		      BETH_FIX.
   */
  #define BETH_FIX
  
***************
*** 8,13
  /*
   * ranlib - create table of contents for archive; string table version
   */
  #include <sys/types.h>
  #include <ar.h>
  #include <ranlib.h>

--- 9,16 -----
   *		      start with a valid magic number. Enabled with #define
   *		      BETH_FIX.
   */
+ #define BETH_FIX
+ 
  #include <sys/types.h>
  #include <ar.h>
  #include <ranlib.h>
***************
*** 15,22
  #include <a.out.h>
  #include <stdio.h>
  
! struct	ar_hdr	archdr;
! #define	OARMAG 0177545
  long	arsize;
  struct	exec	exp;
  FILE	*fi, *fo;

--- 18,27 -----
  #include <a.out.h>
  #include <stdio.h>
  
! struct	ar_hdr	archdr;			/* storage for header at each element
! 					 * of the archive 
! 					 */
! #define	OARMAG 0177545			/* magic number of old-style archive */
  long	arsize;
  struct	exec	exp;			/* header on each a.out (or .o?) file */
  FILE	*fi, *fo;			/* input and output stream pointers */
***************
*** 18,26
  struct	ar_hdr	archdr;
  #define	OARMAG 0177545
  long	arsize;
! struct	exec	exp;
! FILE	*fi, *fo;
! long	off, oldoff;
  long	atol(), ftell();
  #define TABSZ	5000
  struct	ranlib tab[TABSZ];

--- 23,31 -----
  					 */
  #define	OARMAG 0177545			/* magic number of old-style archive */
  long	arsize;
! struct	exec	exp;			/* header on each a.out (or .o?) file */
! FILE	*fi, *fo;			/* input and output stream pointers */
! long	off, oldoff;			/* set by nextel() as side effect */
  long	atol(), ftell();
  #define TABSZ	5000
  struct	ranlib tab[TABSZ];		/* table of symbols */
***************
*** 23,30
  long	off, oldoff;
  long	atol(), ftell();
  #define TABSZ	5000
! struct	ranlib tab[TABSZ];
! int	tnum;
  #define	STRTABSZ	75000
  char	tstrtab[STRTABSZ];
  int	tssiz;

--- 28,35 -----
  long	off, oldoff;			/* set by nextel() as side effect */
  long	atol(), ftell();
  #define TABSZ	5000
! struct	ranlib tab[TABSZ];		/* table of symbols */
! int	tnum;				/* number of elements in table */
  #define	STRTABSZ	75000
  char	tstrtab[STRTABSZ];		/* table of strings for symbol names */
  int	tssiz;				/* current size of string table */
***************
*** 26,33
  struct	ranlib tab[TABSZ];
  int	tnum;
  #define	STRTABSZ	75000
! char	tstrtab[STRTABSZ];
! int	tssiz;
  char	*strtab;
  int	ssiz;
  int	new;

--- 31,38 -----
  struct	ranlib tab[TABSZ];		/* table of symbols */
  int	tnum;				/* number of elements in table */
  #define	STRTABSZ	75000
! char	tstrtab[STRTABSZ];		/* table of strings for symbol names */
! int	tssiz;				/* current size of string table */
  char	*strtab;
  int	ssiz;
  int	new;
***************
*** 40,48
  	char cmdbuf[BUFSIZ];
  	char magbuf[SARMAG+1];
  
! 	--argc;
! 	while(argc--) {
! 		fi = fopen(*++argv,"r");
  		if (fi == NULL) {
  			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
  			continue;

--- 45,53 -----
  	char cmdbuf[BUFSIZ];
  	char magbuf[SARMAG+1];
  
! 	--argc;					/* skip argv[0] */
! 	while(argc--) {				/* foreach archive... */
! 		fi = fopen(*++argv,"r");	/* open next archive file */
  		if (fi == NULL) {
  			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
  			continue;
***************
*** 47,55
  			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
  			continue;
  		}
! 		off = SARMAG;
! 		fread(magbuf, 1, SARMAG, fi);
! 		if (strncmp(magbuf, ARMAG, SARMAG)) {
  			if (*(int *)magbuf == OARMAG)
  				fprintf(stderr, "old format ");
  			else

--- 52,62 -----
  			fprintf(stderr, "ranlib: cannot open %s\n", *argv);
  			continue;
  		}
! 		off = SARMAG;			/* archive proper starts after
! 						 * "magic" header */
! 		fread(magbuf, 1, SARMAG, fi);	/* read "magic" header */
! 		if (strncmp(magbuf, ARMAG, SARMAG)) {	/* is this really an
! 							 * archive? */
  			if (*(int *)magbuf == OARMAG)
  				fprintf(stderr, "old format ");
  			else
***************
*** 57,65
  			fprintf(stderr, "archive: %s\n", *argv);
  			continue;
  		}
! 		fseek(fi, 0L, 0);
! 		new = tnum = 0;
! 		if (nextel(fi) == 0) {
  			fclose(fi);
  			continue;
  		}

--- 64,76 -----
  			fprintf(stderr, "archive: %s\n", *argv);
  			continue;
  		}
! 		fseek(fi, 0L, 0);	/* back to beginning */
! 		new = tnum = 0;		/* initially 0 elements in table.
! 					 * new really doesn't need to be
! 					 * initiallized since it is set in 
! 					 * fixsize before use anyway */
! 
! 		if (nextel(fi) == 0) {	/* advance to first element */
  			fclose(fi);
  			continue;
  		}
***************
*** 63,69
  			fclose(fi);
  			continue;
  		}
! 		do {
  			long o;
  			register n;
  			struct nlist sym;

--- 74,80 -----
  			fclose(fi);
  			continue;
  		}
! 		do {			/* keep going until no more elements */
  			long o;
  			register n;
  			struct nlist sym;
***************
*** 68,73
  			register n;
  			struct nlist sym;
  
  			fread((char *)&exp, 1, sizeof(struct exec), fi);
  			if (N_BADMAG(exp))
  				continue;

--- 79,86 -----
  			register n;
  			struct nlist sym;
  
+ 			/* read a.out header */
+ 
  			fread((char *)&exp, 1, sizeof(struct exec), fi);
  			if (N_BADMAG(exp))
  				continue;		/* not a.out format */
***************
*** 70,75
  
  			fread((char *)&exp, 1, sizeof(struct exec), fi);
  			if (N_BADMAG(exp))
  				continue;
  			if (exp.a_syms == 0) {
  				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);

--- 83,94 -----
  
  			fread((char *)&exp, 1, sizeof(struct exec), fi);
  			if (N_BADMAG(exp))
+ 				continue;		/* not a.out format */
+ #ifdef BETH_FIX
+ 			/* DON'T try to get symbols from the ToC!!! */
+ 
+ 			if(strncmp(archdr.ar_name, tempnm,
+ 			    sizeof (archdr.ar_name)) == 0)
  				continue;
  #endif BETH_FIX
  			if (exp.a_syms == 0) {
***************
*** 71,76
  			fread((char *)&exp, 1, sizeof(struct exec), fi);
  			if (N_BADMAG(exp))
  				continue;
  			if (exp.a_syms == 0) {
  				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
  				continue;

--- 90,96 -----
  			if(strncmp(archdr.ar_name, tempnm,
  			    sizeof (archdr.ar_name)) == 0)
  				continue;
+ #endif BETH_FIX
  			if (exp.a_syms == 0) {
  				fprintf(stderr,
  				   "ranlib: warning: %s(%s): no symbol table\n",
***************
*** 72,78
  			if (N_BADMAG(exp))
  				continue;
  			if (exp.a_syms == 0) {
! 				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
  				continue;
  			}
  			o = N_STROFF(exp) - sizeof (struct exec);

--- 92,100 -----
  				continue;
  #endif BETH_FIX
  			if (exp.a_syms == 0) {
! 				fprintf(stderr,
! 				   "ranlib: warning: %s(%s): no symbol table\n",
! 				   *argv, archdr.ar_name);
  				continue;
  			}
  
***************
*** 75,80
  				fprintf(stderr, "ranlib: warning: %s(%s): no symbol table\n", *argv, archdr.ar_name);
  				continue;
  			}
  			o = N_STROFF(exp) - sizeof (struct exec);
  			if (ftell(fi)+o+sizeof(ssiz) >= off) {
  				fprintf(stderr, "ranlib: %s(%s): old format .o file\n", *argv, archdr.ar_name);

--- 97,107 -----
  				   *argv, archdr.ar_name);
  				continue;
  			}
+ 
+ 			/* calculate offset of symbol table relative to 
+ 			 * beginning of data in a.out-format file
+ 			 */
+ 
  			o = N_STROFF(exp) - sizeof (struct exec);
  
  			/* ssiz is an int...
***************
*** 76,81
  				continue;
  			}
  			o = N_STROFF(exp) - sizeof (struct exec);
  			if (ftell(fi)+o+sizeof(ssiz) >= off) {
  				fprintf(stderr, "ranlib: %s(%s): old format .o file\n", *argv, archdr.ar_name);
  				exit(1);

--- 103,114 -----
  			 */
  
  			o = N_STROFF(exp) - sizeof (struct exec);
+ 
+ 			/* ssiz is an int...
+ 			 * off is now (after the nextel() call) the offset of 
+ 			 * NEXT element in the file.
+ 			 */
+ 
  			if (ftell(fi)+o+sizeof(ssiz) >= off) {
  				fprintf(stderr,
  				    "ranlib: %s(%s): old format .o file\n",
***************
*** 77,83
  			}
  			o = N_STROFF(exp) - sizeof (struct exec);
  			if (ftell(fi)+o+sizeof(ssiz) >= off) {
! 				fprintf(stderr, "ranlib: %s(%s): old format .o file\n", *argv, archdr.ar_name);
  				exit(1);
  			}
  			fseek(fi, o, 1);

--- 110,118 -----
  			 */
  
  			if (ftell(fi)+o+sizeof(ssiz) >= off) {
! 				fprintf(stderr,
! 				    "ranlib: %s(%s): old format .o file\n",
! 				    *argv, archdr.ar_name);
  				exit(1);
  			}
  			fseek(fi, o, 1);
***************
*** 112,117
  		} while(nextel(fi));
  		new = fixsize();
  		fclose(fi);
  		fo = fopen(tempnm, "w");
  		if(fo == NULL) {
  			fprintf(stderr, "can't create temporary\n");

--- 147,155 -----
  		} while(nextel(fi));
  		new = fixsize();
  		fclose(fi);
+ 
+ 		/* write table of contents into temp file */
+ 
  		fo = fopen(tempnm, "w");
  		if(fo == NULL) {
  			fprintf(stderr, "can't create temporary\n");
***************
*** 124,129
  		fwrite(&tssiz, 1, sizeof (tssiz), fo);
  		fwrite(tstrtab, tssiz, 1, fo);
  		fclose(fo);
  		if(new)
  			sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm);
  		else

--- 162,169 -----
  		fwrite(&tssiz, 1, sizeof (tssiz), fo);
  		fwrite(tstrtab, tssiz, 1, fo);
  		fclose(fo);
+ 
+ 		/* archive it into the first place in the archive file. */
  		if(new)
  			sprintf(cmdbuf, "ar rlb %s %s %s\n",
  				firstname, *argv, tempnm);
***************
*** 125,131
  		fwrite(tstrtab, tssiz, 1, fo);
  		fclose(fo);
  		if(new)
! 			sprintf(cmdbuf, "ar rlb %s %s %s\n", firstname, *argv, tempnm);
  		else
  			sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm);
  		if(system(cmdbuf))

--- 165,172 -----
  
  		/* archive it into the first place in the archive file. */
  		if(new)
! 			sprintf(cmdbuf, "ar rlb %s %s %s\n",
! 				firstname, *argv, tempnm);
  		else
  			sprintf(cmdbuf, "ar rl %s %s\n", *argv, tempnm);
  		if(system(cmdbuf))
***************
*** 132,137
  			fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf);
  		else
  			fixdate(*argv);
  		unlink(tempnm);
  	}
  	exit(0);

--- 173,179 -----
  			fprintf(stderr, "ranlib: ``%s'' failed\n", cmdbuf);
  		else
  			fixdate(*argv);
+ #ifndef DEBUG
  		unlink(tempnm);
  #endif DEBUG
  	}
***************
*** 133,138
  		else
  			fixdate(*argv);
  		unlink(tempnm);
  	}
  	exit(0);
  }

--- 175,181 -----
  			fixdate(*argv);
  #ifndef DEBUG
  		unlink(tempnm);
+ #endif DEBUG
  	}
  	exit(0);
  }
***************
*** 137,143
  	exit(0);
  }
  
! nextel(af)
  FILE *af;
  {
  	register r;

--- 180,195 -----
  	exit(0);
  }
  
! /*
!  * nextel() -- go to next element of archive 
!  *	arg:		stream pointer of archive file 
!  *	returns:	0 for EOF on arch. or error
!  * 			1 for success
!  *	side-effect:	set off to offset of NEXT element
!  *			set oldoff to "current" offset
!  */
! 
! nextel(af)	/* sets oldoff and off as side effect */
  FILE *af;
  {
  	register r;
***************
*** 144,149
  	register char *cp;
  
  	oldoff = off;
  	fseek(af, off, 0);
  	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
  	if (r != sizeof(struct ar_hdr))

--- 196,204 -----
  	register char *cp;
  
  	oldoff = off;
+ 
+ 		/* goto current offset and read arch header */
+ 
  	fseek(af, off, 0);
  	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
  	if (r != sizeof(struct ar_hdr))
***************
*** 148,154
  	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
  	if (r != sizeof(struct ar_hdr))
  		return(0);
! 	for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
  		if (*cp == ' ')
  			*cp = '\0';
  	arsize = atol(archdr.ar_size);

--- 203,215 -----
  	r = fread((char *)&archdr, 1, sizeof(struct ar_hdr), af);
  	if (r != sizeof(struct ar_hdr))
  		return(0);
! 
! 		/* zap all blanks in name */
! 
! 	for (cp=archdr.ar_name;
! 	     cp < & archdr.ar_name[sizeof(archdr.ar_name)];
! 	     cp++)
! 	{
  		if (*cp == ' ')
  			*cp = '\0';
  	}
***************
*** 151,157
  	for (cp=archdr.ar_name; cp < & archdr.ar_name[sizeof(archdr.ar_name)]; cp++)
  		if (*cp == ' ')
  			*cp = '\0';
! 	arsize = atol(archdr.ar_size);
  	if (arsize & 1)
  		arsize++;
  	off = ftell(af) + arsize;

--- 212,220 -----
  	{
  		if (*cp == ' ')
  			*cp = '\0';
! 	}
! 	arsize = atol(archdr.ar_size);		/* compute size of this arch
! 						 * element */
  	if (arsize & 1)
  		arsize++;			/* make it even */
  	off = ftell(af) + arsize;		/* compute offset of next
***************
*** 153,160
  			*cp = '\0';
  	arsize = atol(archdr.ar_size);
  	if (arsize & 1)
! 		arsize++;
! 	off = ftell(af) + arsize;
  	return(1);
  }
  

--- 216,224 -----
  	arsize = atol(archdr.ar_size);		/* compute size of this arch
  						 * element */
  	if (arsize & 1)
! 		arsize++;			/* make it even */
! 	off = ftell(af) + arsize;		/* compute offset of next
! 						 * element */
  	return(1);
  }
  
***************
*** 158,163
  	return(1);
  }
  
  stash(s)
  	struct nlist *s;
  {

--- 222,239 -----
  	return(1);
  }
  
+ /*
+  * stash() -- stash this symbol for the ToC
+  *
+  * arg:		symbol table entry
+  * returns:	1 on table overflow
+  * 		falls out bottom on success
+  * side-effect: symbol offset and name size saved in tab[]
+  *		name saved in tstrtab
+  *		tnum incremented
+  *		tssiz incremented by size of symbol name
+  */
+ 
  stash(s)
  	struct nlist *s;
  {
***************
*** 178,183
  	tnum++;
  }
  
  fixsize()
  {
  	int i;

--- 254,270 -----
  	tnum++;
  }
  
+ /*
+  * fixdate() --
+  * args:	none
+  * returns:	new (see side effect)
+  * side-effect: set new to 1 if there is no ToC in the archive; 0 if there
+  *			is already one
+  *		set firstname[] to name of first element if there was no ToC
+  *		fixes up file offsets in ToC to compensate for the size of the
+  *			ToC at the head of the archive.
+  */
+ 
  fixsize()
  {
  	int i;
***************
*** 183,189
  	int i;
  	off_t offdelta;
  
! 	if (tssiz&1)
  		tssiz++;
  	offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) +
  	    sizeof (tssiz) + tssiz;

--- 270,276 -----
  	int i;
  	off_t offdelta;
  
! 	if (tssiz&1)		/* word-align */
  		tssiz++;
  	offdelta = sizeof(archdr) + sizeof (tnum) + 
  	    tnum * sizeof(struct ranlib) +
***************
*** 185,191
  
  	if (tssiz&1)
  		tssiz++;
! 	offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) +
  	    sizeof (tssiz) + tssiz;
  	off = SARMAG;
  	nextel(fi);

--- 272,279 -----
  
  	if (tssiz&1)		/* word-align */
  		tssiz++;
! 	offdelta = sizeof(archdr) + sizeof (tnum) + 
! 	    tnum * sizeof(struct ranlib) +
  	    sizeof (tssiz) + tssiz;
  	off = SARMAG;		/* go back to the beginning */
  	nextel(fi);		/* get next (i.e. first) element in archive */
***************
*** 187,194
  		tssiz++;
  	offdelta = sizeof(archdr) + sizeof (tnum) + tnum * sizeof(struct ranlib) +
  	    sizeof (tssiz) + tssiz;
! 	off = SARMAG;
! 	nextel(fi);
  	if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) {
  		new = 0;
  		offdelta -= sizeof(archdr) + arsize;

--- 275,288 -----
  	offdelta = sizeof(archdr) + sizeof (tnum) + 
  	    tnum * sizeof(struct ranlib) +
  	    sizeof (tssiz) + tssiz;
! 	off = SARMAG;		/* go back to the beginning */
! 	nextel(fi);		/* get next (i.e. first) element in archive */
! 
! 	/* if the name of the first element is tempnm, then clear new and
! 	 * fix offdelta; else set new and save the name in firstname[] for
! 	 * later use by the ar command we will fork
! 	 */
! 
  	if(strncmp(archdr.ar_name, tempnm, sizeof (archdr.ar_name)) == 0) {
  		new = 0;
  		offdelta -= sizeof(archdr) + arsize;
***************
*** 196,201
  		new = 1;
  		strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name));
  	}
  	for(i=0; i<tnum; i++)
  		tab[i].ran_off += offdelta;
  	return(new);

--- 290,301 -----
  		new = 1;
  		strncpy(firstname, archdr.ar_name, sizeof(archdr.ar_name));
  	}
+ 
+ 	/*
+ 	 * fix up the offsets in the table (I am not sure why they do this,
+ 	 * but it seems to work
+ 	 */
+ 
  	for(i=0; i<tnum; i++)
  		tab[i].ran_off += offdelta;
  
***************
*** 198,203
  	}
  	for(i=0; i<tnum; i++)
  		tab[i].ran_off += offdelta;
  	return(new);
  }
  

--- 298,304 -----
  
  	for(i=0; i<tnum; i++)
  		tab[i].ran_off += offdelta;
+ 
  	return(new);
  }
  

-- 
Berry Kercheval		Zehntel Inc.	(ihnp4!zehntel!zinfandel!berry)
(415)932-6900