[comp.unix.i386] File descriptor cloner

pcg@cs.aber.ac.uk (Piercarlo Grandi) (07/26/90)

It's really bonanza time for the audience of comp.unix.i386 :-). Here
enclosed you will find the source for a System V/386 implementation of
the driver (originated in Unix edition 8) that allows you to name stdin
stdout and stderr (and any other file descriptor for the current
process) as pseudo devices in /dev, thus enabling programs that only
operate on path names to be used in a pipe too.

Notice that this driver will have the effect of a dup(2), not of a
second open on the given file descriptor's inode.

I will put here my usual disclaimer that I have forgotten to write for
the parallel port driver:

	This work is the result of personal research activity with the
	use of my time, facilities, funding and resources exclusively.
	In no way the University College of Wales has aided or supported
	this work, nor supplied any funding or resources for its
	performance, nor it is in any way related to research or other
	activities of the University College of Wales.

I want however to thank them for providing network access, and therefore
the ability to do this posting.

------------------------ cut here --------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  MANIFEST Makefile Master Name Node README System dup.c
# Wrapped by su@aware on Thu Jul 26 15:14:38 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo '
   Copyright 1990 Piercarlo Grandi. All rights reserved.

   This shar archive contains free software; you can redistribute it
   and/or modify it under the terms of the GNU General Public License as
   published by the Free Software Foundation; either version 1, or
   (at your option) any later version.

   As a special case, the driver contained herein may be incorporated
   in any OS kernel, whether the GNU General Public License applies to
   it or not.

   This driver is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You may have received a copy of the GNU General Public License
   along with this driver; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
'
echo 4
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(585 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis driver is a System V adaptation of an equivalent driver for 4.2BSD.
XThe original idea appeared in Version 8 Unix.
X
XWhen a process opens minor device N of this driver it get a file descriptor
Xwhich is a duplicate of its own file descriptor N, as if a dup(2) call had
Xbeen effected.
X
XThis is most useful to make it possible to redirect to the standard input
Xoutput and error streams programs that require a named file as operand. For
Xexample, something like
X
X	cp /etc/passwd /dev/stdout | wc
X
Xwill work as intended (this particular example may not be very useful, but
Xothers are).
X
END_OF_FILE
if test 585 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(362 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Makefile                   1	
X Master                     1	
X Name                       1	
X Node                       1	
X README                     1	
X System                     1	
X dup.c                      1	
END_OF_FILE
if test 362 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(171 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCONF		=/etc/conf/bin/
XCC		=cc
XCFLAGS		=-O -DINKERNEL
X
XDriver.o:	dup.o;			ln $? $@
X
Xinstall:	Driver.o Master System Node Name
X	$(CONF)idinstall -keu dup
X	$(CONF)idmknod -s
END_OF_FILE
if test 171 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'Master' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Master'\"
else
echo shar: Extracting \"'Master'\" \(26 characters\)
sed "s/^X//" >'Master' <<'END_OF_FILE'
Xdup	o	cio	dup	0	55	1	1	-1
END_OF_FILE
if test 26 -ne `wc -c <'Master'`; then
    echo shar: \"'Master'\" unpacked with wrong size!
fi
# end of 'Master'
fi
if test -f 'Name' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Name'\"
else
echo shar: Extracting \"'Name'\" \(40 characters\)
sed "s/^X//" >'Name' <<'END_OF_FILE'
Xdup File descriptor dup(2) clone driver
END_OF_FILE
if test 40 -ne `wc -c <'Name'`; then
    echo shar: \"'Name'\" unpacked with wrong size!
fi
# end of 'Name'
fi
if test -f 'Node' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Node'\"
else
echo shar: Extracting \"'Node'\" \(44 characters\)
sed "s/^X//" >'Node' <<'END_OF_FILE'
Xdup	stdin	c	0
Xdup	stdout	c	1
Xdup	stderr	c	2
END_OF_FILE
if test 44 -ne `wc -c <'Node'`; then
    echo shar: \"'Node'\" unpacked with wrong size!
fi
# end of 'Node'
fi
if test -f 'System' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'System'\"
else
echo shar: Extracting \"'System'\" \(22 characters\)
sed "s/^X//" >'System' <<'END_OF_FILE'
Xdup	Y	1	0	0	0	0	0	0	0
END_OF_FILE
if test 22 -ne `wc -c <'System'`; then
    echo shar: \"'System'\" unpacked with wrong size!
fi
# end of 'System'
fi
if test -f 'dup.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'dup.c'\"
else
echo shar: Extracting \"'dup.c'\" \(3118 characters\)
sed "s/^X//" >'dup.c' <<'END_OF_FILE'
X/*
X    $Header: /aware0/src/dup/dup.c,v 1.2 90/07/26 12:55:44 sw Exp $
X*/
X
X#include <sys/param.h>
X#include <sys/types.h>
X#include <sys/sysmacros.h>
X#include <sys/dir.h>
X#include <sys/file.h>
X#include <sys/inode.h>
X#include <sys/signal.h>
X#include <sys/errno.h>
X#include <sys/user.h>
X
X/*
X    4.2 BSD pseudo-device driver for the "fd" device.  An attempt to
X    open this device returns a file descriptor which is a "duplicate"
X    of the open file descriptor corresponding to the minor device
X    number of the particular filedesc device opened.  For example, the
X    device /dev/stdin is a fd device with minor device 0.  Opening
X    /dev/stdin returns a duplicate of file descriptor 0, equivalent to
X    fd(0).  The open mode must be the same as the mode of the file
X    descriptor being duplicated, except that a read/write file
X    descriptor can be duped for just read or just write.
X
X    The idea of "/dev/stdin" originated in Bell Labs UNIX 8th Edition
X    (research version 8) and was described by Rob Pike at the Summer
X    1985 Usenix Conference in Portland.  We use the names
X    "/dev/stdin", "/dev/stdout", and "/dev/stderr" for minor devices
X    0,1, and 2, as well as the names "/dev/fdXX" for XX ranging from 0
X    to NOFILE-1.  The protection mode of the device inodes should be
X    0666.
X
X    "fd" driver written 16-Jun-85 by Darwyn Peachey, Computer Science
X    Research Lab, University of Saskatchewan, Saskatoon, Canada S7N
X    0W0 Phone: (306) 966-4909 UUCP: ihnp4!sask!kimnovax!peachey
X
X    Suitably adapted to System V/386 rel.  3.2 by Piercarlo Grandi,
X    July 1990.  Name changed to "dup" to avoid conflict with the
X    floppy disc driver.
X*/
X
Xdupopen(dev,mode)
X    dev_t                   dev;
X    int                     mode;
X{
X    register int            fd,oldfd;
X    register struct file    *fp,*oldfp;
X
X    /*
X        Here we rely on the current file descriptor being still in
X	u.u_r.r_val1, where it has been put by openi() to be returned
X	to the user as the result of the open(2) call. Horrible kludge.
X    */
X
X    /*
X	The current file descriptor must be valid.
X    */
X
X    fd = u.u_r.r_reg.r_val1;
X    if (fd < 0 || fd >= NOFILE)	/* something terrible has happened */
X	return EINVAL;
X
X    /*
X	The old file descriptor must be valid and different from the
X	current one.
X    */
X
X    oldfd = minor(dev);
X    if (oldfd < 0 || oldfd >= NOFILE || fd == oldfd)
X	return EBADF;
X
X    /*
X	The old file descriptor must point to some file struct, and the
X	old open mode must be a superset of the current one.
X    */
X
X    oldfp = u.u_ofile[oldfd];
X    if (oldfp == NULL)
X	return EBADF;
X
X    if ((mode & (oldfp->f_flag & (FREAD|FWRITE))) != (mode & (FREAD|FWRITE)))
X	return EACCES;
X
X    /*
X	The current file pointer can now be thrown away.
X    */
X
X    fp = u.u_ofile[fd];
X    if (fp != NULL) /* otherwise something terrible has happened */
X    {
X	u.u_ofile[fd] = NULL;
X	if (fp->f_inode) iput(fp->f_inode);
X	fp->f_count = 0;
X    }
X
X    /*
X	The old file pointer becomes the current one as well.
X    */
X
X    u.u_pofile[fd] = u.u_pofile[oldfd];
X    (u.u_ofile[fd] = oldfp)->f_count++;
X
X    return 0;
X}
END_OF_FILE
if test 3118 -ne `wc -c <'dup.c'`; then
    echo shar: \"'dup.c'\" unpacked with wrong size!
fi
# end of 'dup.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
--
Piercarlo "Peter" Grandi           | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcsun!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk