[net.sources] 4.2 driver for /dev/stdin

peachey@sask.UUCP (Darwyn Peachey) (06/18/85)

----------

Last week at the Usenix Conference in Portland, Oregon, Rob Pike of Bell Labs
mentioned the pseudo-device "/dev/stdin" implemented in UNIX 8th Edition
(research version 8).  An open of /dev/stdin returns a file descriptor which
is a duplicate of file descriptor 0.  This is valuable, because programs
which normally read from a user-specified file can be made to read standard
input without special options or checking for a file name "-" as has been
done by many utilities in the past.  The user may simply specify "/dev/stdin"
as the input file.  Note that this is different from "/dev/tty", since
standard input may come from a pipe, or be redirected using the "<" shell
operator.

The notion of "/dev/stdin" appealed to me so much that I wrote the following
4.2 BSD device driver to implement it.  The "devfd" driver duplicates a file
descriptor corresponding to the minor device number of the devfd device.  Our
system has "/dev/stdin", "/dev/stdout", and "/dev/stderr" with minor device
numbers 0, 1, and 2 respectively.  We also have "/dev/fdXX", for XX ranging
from 0 to NOFILE-1 (/dev/fd0, /dev/fd1, and /dev/fd2 are links to /dev/stdin,
/dev/stdout, and /dev/stderr).  All of these devices are owned by root with
protection mode 0666 (crw-rw-rw-).

The driver requires no changes to 4.2 BSD kernel code, except for the
configuration information in machine/conf.c and conf/files. Clearer and cleaner
implementations are probably possible if you don't mind modifying other
source files (copen in sys_syscalls.c and openi in ufs_inode.c).

If you install the driver in your system, I'd like to hear about your
experiences, good and bad.

					Darwyn Peachey
					Computer Science Research Lab
					University of Saskatchewan
					Saskatoon, Canada S7N 0W0
					(306) 966-4909
				{ihnp4,alberta,utcsri}!sask!kimnovax!peachey


------------------------- installation instructions ---------------------
Installation of the driver consists of the following steps:
1. place the devfd.c file in /sys/sys/devfd.c
2. add the following line (indented for clarity) to /sys/conf/files
	sys/devfd.c		optional devfd
3. edit /sys/machine/conf.c to look like the following:
	...
	#include "devfd.h"
	#if NDEVFD > 0
	int devfdopen();
	#else
	#define devfdopen nodev
	#endif
	...
	struct cdevsw cdevsw[] =
	{
	...
		/* "devfd" pseudo-device driver */
		devfdopen,	nodev,	nodev,	nodev,	/* 34 */
		nodev,		nodev,	nodev,	0,
		seltrue,	nodev,
	...
	};

Note that although "devfd" is entry number 34 in our cdevsw, you may need
to use a different cdevsw entry in your system.
4. add the following line to your machine config file, e.g. /sys/conf/KIMNOVAX
	pseudo-device		devfd
5. run /etc/config MACHINE in /sys/conf (e.g. /etc/config KIMNOVAX).
6. chdir to /sys/MACHINE (e.g. /sys/KIMNOVAX) and run "make depend", then
"make vmunix".  Move vmunix to /newvmunix and reboot to try it out.
7. After booting the new kernel, create device inodes in /dev, e.g.
	/etc/mknod /dev/stdin c 34 0
	chmod 0666 /dev/stdin
-------------------------- devfd.c --------------------------------------
#include "devfd.h"
#if NDEVFD > 0
#include	"../h/param.h"
#include	"../h/dir.h"
#include	"../h/file.h"
#include	"../h/inode.h"
#include	"../h/user.h"

/*
 * 4.2 BSD pseudo-device driver for the "devfd" device.  An attempt to
 * open this device returns a file descriptor which is a "duplicate" of
 * the open file descriptor corresponding to the minor device number of the
 * particular filedesc device opened.  For example, the device /dev/stdin
 * is a devfd device with minor device 0.  Opening /dev/stdin returns
 * a duplicate of file descriptor 0, equivalent to dup(0).  The open mode
 * must be the same as the mode of the file descriptor being duplicated,
 * except that a read/write file descriptor can be duped for just read or
 * just write.
 *
 * The idea of "/dev/stdin" originated in Bell Labs UNIX 8th Edition
 * (research version 8) and was described by Rob Pike at the Summer 1985
 * Usenix Conference in Portland.  We use the names "/dev/stdin",
 * "/dev/stdout", and "/dev/stderr" for minor devices 0,1, and 2, as well
 * as the names "/dev/fdXX" for XX ranging from 0 to NOFILE-1.
 * The protection mode of the device inodes should be 0666.
 *
 * "devfd" driver written 16-Jun-85 by Darwyn Peachey, Computer Science
 * Research Lab, University of Saskatchewan, Saskatoon, Canada S7N 0W0
 * Phone: (306) 966-4909   UUCP: ihnp4!sask!kimnovax!peachey
 */

devfdopen(dev, mode)
	dev_t dev;
	int mode;
{
	register int fd, oldfd;
	register struct file *fp;

	/*
	 * Luckily, the new fd is still in u.u_r.r_val1 from the call to
	 * falloc(kern_descrip.c) done by copen(ufs_syscalls.c).
	 */
	fd = u.u_r.r_val1;
	if (fd < 0 || fd >= NOFILE)	/* something terrible has happened */
		return (EINVAL);

	/* validate minor device number */
	oldfd = minor(dev);
	if (oldfd < 0 || oldfd >= NOFILE || fd == oldfd
	  || (fp = u.u_ofile[oldfd]) == NULL)
		return (EBADF);

	/* check open mode "mode" versus mode of descriptor being duped */
	if ((mode & (fp->f_flag & (FREAD|FWRITE))) != (mode & (FREAD|FWRITE)))
		return (EACCES);

	/* release the file structure allocated for the opening of devfd */
	if ((fp = u.u_ofile[fd]) != NULL) {	/* should always be true */
		u.u_ofile[fd] = NULL;
		if (fp->f_data)
			irele((struct inode *)(fp->f_data));
		fp->f_count = 0;
	}

	/* duplicate the oldfd */
	fp = u.u_ofile[fd] = u.u_ofile[oldfd];
	u.u_pofile[fd] = u.u_pofile[oldfd];
	fp->f_count++;
	return (0);
}
#endif

mark@tove.UUCP (Mark Weiser) (06/24/85)

Sigh.  We have had this at Maryland in for form of /dev/fdxx (xx=0-20) for
more than a year, under both 4.1 and 4.2.  We even sent the source
to net.sources at least once.  Fred Blonder did it.  Net.sources and 
net.unix-wizards ought to help folks not reinvent the wheel, but 
not if people forget, don't give credit, or just don't keep up.
	-mark
-- 
Spoken: Mark Weiser 	ARPA:	mark@maryland	Phone: +1-301-454-7817
CSNet:	mark@umcp-cs 	UUCP:	{seismo,allegra}!umcp-cs!mark
USPS: Computer Science Dept., University of Maryland, College Park, MD 20742