[net.unix] dup2 simulator

guy@rlgvax.UUCP (Guy Harris) (03/10/84)

This question comes up periodically (how to simulate the old V7 "dup2"
system call under USG UNIX (System III, System V, etc.)), so here's the
trick.

"dup2" is sort of an early version of "fcntl(F_DUPFD)".  The main
difference is that it closes the file descriptor to be dup'ed to before
duping it, so that it guarantees (assuming no errors) that the resulting
file descriptor will, indeed, be the one asked for.

So:

/*
 * From DUP(2), 4.1BSD manual:
 *
 * "fildes" is a file descriptor referring to an open file, and "fildes2"
 * is a non-negative integer less than the maximum value allowed for file
 * descriptors (approximately 19).  "Dup2" causes "fildes2" to refer to the
 * same file as "fildes".  If "fildes2" already referred to an open file,
 * it is closed first.
 */
#include <fcntl.h>

int
dup2(fildes, fildes2)
int fildes;
int fildes2;
{
#ifdef PARANOID
	/*
	 * To be completely technically correct, if "fildes" is not a valid
	 * file descriptor, "dup2" fails *without* closing "fildes2".  So
	 * we can check if we really want to be paranoid.
	 *
	 * We do this check by doing an "fstat" on "fildes" into a "stat"
	 * buffer, and if the "fstat" returns -1 with "errno" set to EBADF,
	 * we bail out immediately, returning -1.
	 */
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
	extern int errno;
	struct stat statb;

	if (fstat(fildes, &statb) < 0 && errno == EBADF)
		return(-1);
#endif
	if (close(fildes2) < 0)
		return(-1);
	return(fcntl(fildes, F_DUPFD, fildes2));
}

	Guy Harris
	{seismo,ihnp4,allegra}!rlgvax!guy

gwyn%brl-vld@sri-unix.UUCP (03/12/84)

From:      Doug Gwyn (VLD/VMB) <gwyn@brl-vld>

Your dup(2) emulation incorrectly returns an error indication if
fildes2 is not open.  The close(fildes2) return value should not
be tested:
	(void)close(fildes2);

gwyn%brl-vld@sri-unix.UUCP (03/12/84)

From:      Doug Gwyn (VLD/VMB) <gwyn@brl-vld>

Your dup2() emulation incorrectly returns an error indication if
fildes2 is not open.  The close() return value should be ignored:
	(void)close(fildes2);