[net.bugs.4bsd] bad engineering on fopen with invalid modes

jpl@allegra.UUCP (John P. Linderman) (06/04/85)

Puzzle for 4.2BSD stdio users:
If you accidentally transpose the characters in the ``mode'' argument
to fopen (or freopen), like in the following program, what would you
expect to happen?  (Note the "+w" instead of "w+" on the fopen.)

    #include <stdio.h>

    main()
    {
	FILE *iop, *fopen();

	printf("fopen returned %x\n", iop = fopen("/etc/passwd", "+w"));
	if (iop == NULL) exit(1);
	printf("putc returns %d\n", putc('\n', iop));
	if (ferror(iop)) printf("Oops\n");
	printf("getc returns %d\n", getc(iop));
	if (ferror(iop)) printf("Oops\n");
    }

If you guessed that the open would fail, guess again.  The correct (??)
answer is that you get a FILE pointer flagged as open for writing,
based on a file descriptor opened for read only.  Probably not quite
what you had hoped for.  Of course, it isn't nice to pass garbage to
routines, but fopen is unnecessarily graceless.  Instead of assuming
that a mode that is neither 'w' nor 'a' MUST be 'r', it could easily
check, and let the open fail if the mode is bogus.  While we're at it,
fopen and freopen are nearly identical (was somebody getting paid by
the line for this code?).  fopen could simply be a macro:

#define fopen(file, mode) freopen(file, mode, (FILE *) NULL)

and then freopen could do the work of both routines by beginning

    if (iop != (FILE *) NULL) {
	(void) fclose(iop);
    } else {
	for (iop = _iob; ...
    }

Bonus points:  Which two modes does fdopen explicitly look for, and
to which mode will garbage default?

John P. Linderman  Department of Nonstandard I/O  allegra!jpl