[comp.bugs.sys5] Bug in pg - doesn't close directories

david@wolfen.cc.uow.oz (David E. A. Wilson) (07/10/89)

Description:
	When pg encounters a directory in its argument list it prints
out a message to that effect and moves on to the next argument.
Unfortunately it does not close the directory and eventually runs
out of file descriptors.

Repeat-by:
	Give pg more directories than the system allows open fd's.
(64 should be enough on any system). The first N will have the message:

	pg: filename is a directory

while the remainder will have:

	filename: Too many open files

Systems affected:
	Probably all using AT&T source. I have found the bug in
A/UX 1.1b (Mac II), Dynix 2.0v2 (Sequent Symmetry),
SunOS 4.0.3b (Sparcstation 1) and OSx4.4c (Pyramid 90xe).

ccea3@rivm.UUCP (Adri Verhoef) (07/12/89)

>	Give pg more directories than the system allows open fd's.
>The first N will have the message:

>	pg: filename is a directory

>while the remainder will have:

>	filename: Too many open files

Right, only my systems say:

	filename: Invalid argument

>Systems affected:
>	Probably all using AT&T source. I have found the bug in
>A/UX 1.1b (Mac II), Dynix 2.0v2 (Sequent Symmetry),
>SunOS 4.0.3b (Sparcstation 1) and OSx4.4c (Pyramid 90xe).

Add:
 Uniq V.3.0 (*VAX*), AT&T V.2.0.5 (3b2/*)

guy@auspex.auspex.com (Guy Harris) (07/13/89)

>	When pg encounters a directory in its argument list it prints
>out a message to that effect and moves on to the next argument.
>Unfortunately it does not close the directory and eventually runs
>out of file descriptors.

It's even worse than that.  First of all, its check for "is this a
directory" is wrong - S_IFDIR is *NOT* a flag bit, it's a value for a
bit field, so the proper test is "(statb.st_mode & S_IFMT) == S_IFDIR",
not "(statb.st_mode & S_IFDIR)" - and second of all, it won't close the
descriptor if some other tests fail, either.

A fix to the S5R3.1 version:

*** pg.c.orig	Wed Jul 12 10:23:31 1989
--- pg.c	Wed Jul 12 10:33:37 1989
***************
*** 914,919 ****
--- 914,920 ----
  	struct stat stbuf;
  	register FILE *f;
  	int fd;
+ 	int f_was_opened;
  
  	pipe_in = 0;
  	if (strcmp(fs,"-") == 0) {
***************
*** 923,928 ****
--- 924,930 ----
  			rewind(tmp_fin);
  			f = tmp_fin;
  		}
+ 		f_was_opened = 0;
  	}
  	else {
  		if ((f=fopen(fs, "r")) == (FILE *)NULL) {
***************
*** 930,951 ****
  			perror(fs);
  			return ((FILE *)NULL);
  		}
  	}
  	if (fstat(fileno(f), &stbuf) == -1) {
  		(void) fflush(stdout);
  		perror(fs);
  		return ((FILE *)NULL);
  	}
! 	if (stbuf.st_mode & S_IFDIR) {
  		(void) fprintf(stderr,"pg: %s is a directory\n",fs);
  		return ((FILE *)NULL);
  	}
! 	if (stbuf.st_mode & S_IFREG) {
  		if (f == stdin)		/* It may have been read from */
  			rewind(f);	/* already, and not reopened  */
  	}
  	else {
  		if (f != stdin) {
  			(void) fprintf(stderr,"pg: special files only handled as standard input\n");
  			return((FILE *)NULL);
  		}
--- 932,960 ----
  			perror(fs);
  			return ((FILE *)NULL);
  		}
+ 		f_was_opened = 1;
  	}
  	if (fstat(fileno(f), &stbuf) == -1) {
+ 		if (f_was_opened)
+ 			(void) fclose(f);
  		(void) fflush(stdout);
  		perror(fs);
  		return ((FILE *)NULL);
  	}
! 	if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
! 		if (f_was_opened)
! 			(void) fclose(f);
  		(void) fprintf(stderr,"pg: %s is a directory\n",fs);
  		return ((FILE *)NULL);
  	}
! 	if ((stbuf.st_mode & S_IFMT) == S_IFREG) {
  		if (f == stdin)		/* It may have been read from */
  			rewind(f);	/* already, and not reopened  */
  	}
  	else {
  		if (f != stdin) {
+ 			if (f_was_opened)
+ 				(void) fclose(f);
  			(void) fprintf(stderr,"pg: special files only handled as standard input\n");
  			return((FILE *)NULL);
  		}

bt455s39@uhccux.uhcc.hawaii.edu (Carmen Hardina) (07/14/89)

Yes, the problem also exist in the SCO XENIX 2.3.1 pg binary.  I just
tried it and basically got the same error messages with the addition
of a kernel warning error.  Let's see, update #2000?  :-)

					--Carmen


-- 
Carmen Maria Hardina, University of Hawaii at Manoa...
UUCP: {uunet,ucbvax,dcdwest}!ucsd!nosc!uhccux!bt455s39
ARPA: uhccux!bt455s39@nosc.MIL BITNET: bt455s39@uhccux
INET: bt455s39@uhccux.UHCC.HAWAII.EDU <-- It may work.

det@hawkmoon.MN.ORG (Derek E. Terveer) (07/23/89)

In article <5941@wolfen.cc.uow.oz>, david@wolfen.cc.uow.oz (David E. A. Wilson) writes:
> Repeat-by:
> 	Give pg more directories than the system allows open fd's.
> (64 should be enough on any system). The first N will have the message:
> 	pg: filename is a directory
> while the remainder will have:
> 	filename: Too many open files

I'm running microport System V/386 3.0e (sys V R3.0) and i get an invalid
argument instead:

$ mkdir /tmp/$$; cd /tmp/$$
$ for i in $(iota 1 64); do mkdir $i; done
$ pg *
pg: 1 is a directory
pg: 10 is a directory
	etc..
pg: 24 is a directory
pg: 25 is a directory
26: Invalid argument
27: Invalid argument
28: Invalid argument

	etc...
-- 
Derek Terveer 	    det@hawkmoon.MN.ORG || ..!uunet!rosevax!elric!hawkmoon!det
		    w(612)681-6986   h(612)789-8643

"A proper king is crowned" -- Thomas B. Costain