chris@umcp-cs.UUCP (Chris Torek) (12/22/84)
: Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH all=FALSE if [ $1x = -ax ]; then all=TRUE fi /bin/echo 'Extracting Info' cat <<'Foo' >Info As promised, here is the fd driver for 4.2BSD. Beware: I just ripped out the 4.1 manual, so it's wrong. The code now doesn't just dup() the file, if it's an inode; it makes a whole new file pointer. (For sockets and any other descriptor types you may happen to have lying around, it still dup()s.) This isn't Fred's original code either; I reformatted it and removed a few "u.u_" assignments. Any bugs can probably be attributed to me. To install, put dev_fd.c in sys/sys, update conf/files, configure, make depend, and make. (I think.) dev_fd.c is a lot like tty_pty.c. By the way, we've found /dev/fd0 especially useful with soelim. Foo /bin/echo 'Extracting dev_fd.c' sed 's/^X//' <<'//go.sysin dd *' >dev_fd.c #ifndef lint static char rcsid[] = "@(#)$Header: /usr/sys/sys/RCS/dev_fd.c,v 1.1 84/12/01 21:38:17 chris Exp $"; #endif lint X/* * fd.c Fred Blonder - U of Maryland 11-Sep-1984 * * ``File Descriptor'' pseudo-device driver, rewritten for Berkeley 4.2. * * Opening minor device N opens the file (if any) connected to file-descriptor * N belonging to the calling process. Note that this driver consists of only * the ``open()'' routine, because all subsequent references to this file will * be direct to the other driver. */ #include "fd.h" #if NFD > 0 #include "../h/param.h" #include "../h/inode.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/errno.h" X/* * THIS CODE NEEDS CLEANING AS SOON AS ASSIGNMENTS TO u.u_* GO AWAY */ fdopen(dev, mode) dev_t dev; int mode; { struct file *fp, *wfp; struct inode *ip, *wip; int rwmode, error; /* * Note the horrid kludge here: u.u_r.r_val1 contains the value * of the new file descriptor, which has not been disturbed since * it was allocated. */ if ((fp = getf(u.u_r.r_val1)) == NULL) return (u.u_error); if ((wfp = getf(minor(dev))) == NULL) return (u.u_error); /* * We must explicitly test for this case because ufalloc() may * have allocated us the same file desriptor we are referring * to, if the proccess referred to an invalid (closed) descriptor. * Ordinarily this would be caught by getf(), but by the time we * reach this routine u_pofile[minor(dev)] could already be set * to point to our file struct. */ if (fp == wfp) return (EBADF); ip = (struct inode *)fp->f_data; /* * Fake a ``dup()'' sys call if it isn't an inode. */ if (wfp->f_type != DTYPE_INODE) { /* * Check that the mode the file is being opened * for is consistent with the mode of the existing * descriptor. This isn't as clean as it should be, * but this entire driver is a real kludge anyway. */ rwmode = mode & (FREAD|FWRITE); if ((fp->f_flag & rwmode) != rwmode) return (EACCES); /* Delete references to this pseudo-device. */ irele(ip); /* Chuck the inode. */ fp->f_count = 0; /* Chuck the file structure. */ /* Dup the file descriptor. */ dupit(u.u_r.r_val1, wfp, u.u_pofile[minor(dev)]); return (0); } error = 0; wip = (struct inode *)wfp->f_data; /* * I'm not sure that we really need to lock the inode here, * but why not be paranoid? */ ilock(wip); /* * Since we're opening a file again, we run through all the * permission checks so this can't be used as a loophole to * get access to a file we shouldn't have. (GROT) */ if (mode & FREAD && access(wip, IREAD)) goto bad; if (mode & (FWRITE|FTRUNC)) { if ((ip->i_mode&IFMT) == IFDIR) { error = EISDIR; goto bad; } if (access(wip, IWRITE)) goto bad; } /* * The file must always exist, so we don't even bother testing * for its presence. */ if ((mode & (FCREAT|FEXCL)) == (FCREAT|FEXCL)) { error = EEXIST; goto bad; } /* * This may not make any sense, but I'm paranoid and figure that * it's probably an error. */ if (mode & FTRUNC) { error = EBUSY; goto bad; } /* Call the device-specific open routine, if any. */ if ((error = openi(wip, mode)) != 0) goto bad; /* * Made it this far, now switch the inode pointers in the * file descriptors around, to make this file open refer * to the other file. */ irele(ip); /* We don't need this anymore. */ fp->f_data = (caddr_t)wip; wip->i_count++; iunlock(wip); return (0); bad: iunlock(wip); return (error); } #endif NFD > 0 //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 dev_fd.c /bin/echo -n ' '; /bin/ls -ld dev_fd.c fi /bin/echo 'Extracting fd.4' sed 's/^X//' <<'//go.sysin dd *' >fd.4 X.TH FD 4l "11-Jan-83 (U of Maryland)" X.UC 4 X.SH NAME fd \- ``file descriptor'' driver X.SH DESCRIPTION X.lg X.I Fd0 - X.I fd19 are special files that are symbolic names for a process's file descriptors. That is, opening the file: /dev/fd\fIN\fP is equivalent to doing the system call: dup(\fIN\fP). This can be used to force a program which opens files by name, to connect itself to open file descriptors (which you have thoughtfully provided) in weird and wonderful ways. A simple use would be to force a program which only accepts input from files, to read from its standard input. For instance: X.sp X.ti +10 cat /dev/fd0 X.sp produces the same result as: X.sp X.ti +10 cat - X.sp which would be useful if \fIcat\fP didn't use the ``-'' convention. X.sp The driver checks to see that the read/write mode you are attempting to open the file with, is compatible with the mode of the existing file descriptor. That is: if descriptor 5 is open for writing, you cannot open ``/dev/fd5'' for reading. X.SH AUTHOR Fred Blonder <fred@umcp-cs> X.SH FILES X/dev/fd* X.SH BUGS Since the driver fakes a ``dup'' system call rather than actually re-opening the file, the new descriptor is a copy of the dup-ed descriptor, and shares its properties. Specifically: it will have the same read/write mode as the dup-ed descriptor. If descriptor 0 is open for reading and writing, opening ``/dev/fd0'' for reading will return a writeable, as well as readable, file descriptor. Also: the descriptors share the same read/write pointer, so seeks, reads & writes on one will affect the other. X.sp While not a bug in the driver, use of these files can produce odd interactions with programs which don't expect to have their file descriptors surreptitiously aliased. //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 fd.4 /bin/echo -n ' '; /bin/ls -ld fd.4 fi -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland