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