Path: isy!liuida!sunic!mcsun!uunet!cs.utexas.edu!rutgers!noao!bordeaux.kpno.noao.edu!jdavis From: jdavis@bordeaux.kpno.noao.edu (Jim Davis) Newsgroups: alt.sources Subject: /dev/fd - SunOS 4.1.1 /dev/fd device driver Message-ID: <1992Jul7.230900.25043@noao.edu> Date: 7 Jul 92 23:09:00 GMT Sender: news@noao.edu Followup-To: comp.sys.sun.misc Organization: National Optical Astronomy Observatories, Tucson AZ Lines: 517 Nntp-Posting-Host: bordeaux.kpno.noao.edu Archive-name: /dev/fd Submitted-by: jdavis@noao.edu (Jim Davis) Here is a /dev/fd device driver for SunOS 4.1.1. It's also available via anonymous ftp from gemini.tuc.noao.edu (140.252.1.11) in ~/pub/devfd.shar. The /dev/fd driver lets you access open file descriptors through the file system. For example, in the Bourne shell, $ cat /etc/motd >/dev/stdout | cmp /dev/stdin /etc/motd $ exec 7>&1; cat /etc/motd >/dev/fd/7 SunOS Release 4.1.1 (BURGUNDY-FD) #12: Tue Jun 2 19:07:16 MST 1992 $ cat /etc/motd | (exec 5>&0; cmp /dev/fd/5 /etc/rc.boot) /dev/fd/5 /etc/rc.boot differ: char 1, line 1 And in rc (after rebuilding with DEVFD defined), ; cmp <{cat /etc/motd} <{cat /etc/motd} ; cmp <{cat /etc/motd} <{cat /etc/rc.boot} /dev/fd/4 /dev/fd/5 differ: char 1, line 1 The driver is installed as a pseudo-device in your kernel. You don't need kernel source code for this, but you will need to reconfigure and rebuild your kernel. This /dev/fd driver is derived from the /dev/fd driver in the CSRG NET/2 sources and a /dev/fd driver for Ultrix that Boyd Roberts posted to comp.unix.wizards. I think the driver will work on 4.1.2 systems too, but I don't have access to the 4.1.2 sources to be sure. # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # README # devfd.c # devfd.4 # test-devfd.c # echo x - README sed 's/^X//' >README << 'END-of-README' XThis is a /dev/fd driver for SunOS 4.1.1. The driver lets you access open Xfile descriptors through the file system. X XThe driver is installed as a pseudo-device in your kernel. You don't need Xkernel source code for this, but you will need to reconfigure and rebuild Xyour kernel. X XCheck the value of NOFILE, the maximum number of open files per process, in X/usr/include/sys/param.h. If it isn't 256, change "255" in the instructions Xbelow to whatever NOFILE-1 is on your system. X XTo install the driver, copy devfd.c to /sys/sundev and add the line X Xsundev/devfd.c optional devfd device-driver X Xto the file /sys/`arch -k`/conf/files. X XAdd the line X Xpseudo-device devfd255 X Xto your kernel config file. Add X Xoptions DEVFDDEBUG X Xtoo, if you want to enable a debugging option. The comments in devfd.c Xexplain how the debugging option works. Edit /sys/sun/conf.c, adding X X#include "devfd.h" X#if NDEVFD > 0 Xint devfdopen(); X#else X#define devfdopen nodev X#endif X Xsomewhere before the cdevsw array entries, and find an unused major number Xentry in the cdevsw array itself. The "65" entry was available on my Xsystem. Edit the unused entry to read X X { X devfdopen, nodev, nodev, nodev, /*65*/ X nodev, nodev, nodev, 0, X 0, 0, X }, X XNow make the /dev/fd files. The minor device numbers range from 0 to 255, Xand the minor device number of /dev/fd/n is n. Set the modes to 666: X X# mkdir /dev/fd X# cd /dev/fd X# for i in `awk 'BEGIN { for (i=0; i<=255; i++) print i; exit}'` X> do X> /etc/mknod $i c 65 $i X> done X# chmod 666 * X XAfter the /dev/fd files are created, turn off write permission to the X/dev/fd directory itself. X XMake /dev/stdin a link to /dev/fd/0, /dev/stdout a link to /dev/fd/1, and X/dev/stderr a link to /dev/fd/2. X XRebuild your kernel and try it out! X Xtest-devfd.c is a simple test program to exercise the driver; check the Xdefinition of NDEVFD near the top of the file. Or just start typing. XBourne shell users can test the driver with commands like X X$ cat /etc/motd >/dev/stdout | cmp /dev/stdin /etc/motd X X$ exec 7>&1; cat /etc/motd >/dev/fd/7 XSunOS Release 4.1.1 (BURGUNDY-FD) #12: Tue Jun 2 19:07:16 MST 1992 X X$ cat /etc/motd | (exec 7>&0; cmp /dev/fd/7 /etc/rc.boot) X/dev/fd/7 /etc/rc.boot differ: char 1, line 1 X XRc installers can define DEVFD in config.h now. After rebuilding rc, try X X; cmp <{cat /etc/motd} <{cat /etc/motd} X X; cmp <{cat /etc/motd} <{cat /etc/rc.boot} X/dev/fd/4 /dev/fd/5 differ: char 1, line 1 X XCsh users... apparently the csh starts with file descriptor 16 open for Xstandard input (or is it 19?), 17 for standard output, and 18 for standard Xerror. So instead of X X% cat /etc/motd >/dev/stdout X/dev/stdout: Bad file number X Xyou have to resort to X X% cat /etc/motd >/dev/fd/17 XSunOS Release 4.1.1 (BURGUNDY-FD) #12: Tue Jun 2 19:07:16 MST 1992 X X-- XJim Davis | "May I be excused to FREAK OUT?" Xjdavis@noao.edu | -- Clarissa Darling END-of-README echo x - devfd.c sed 's/^X//' >devfd.c << 'END-of-devfd.c' X/* X * A /dev/fd driver for SunOS 4.1.1. Derived from the /dev/fd driver in the X * CSRG NET/2 sources (note first disclamer below) and a /dev/fd driver for X * Ultrix that Boyd Roberts posted to comp.unix.wizards (note second X * disclaimer below). X * X * Jim Davis (jdavis@noao.edu), June 1992. X */ X X/* X * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of X * California. All rights reserved. X * X * Redistribution and use in source and binary forms, with or without X * modification, are permitted provided that the following conditions are X * met: 1. Redistributions of source code must retain the above copyright X * notice, this list of conditions and the following disclaimer. 2. X * Redistributions in binary form must reproduce the above copyright notice, X * this list of conditions and the following disclaimer in the documentation X * and/or other materials provided with the distribution. 3. All advertising X * materials mentioning features or use of this software must display the X * following acknowledgement: This product includes software developed by the X * University of California, Berkeley and its contributors. 4. Neither the X * name of the University nor the names of its contributors may be used to X * endorse or promote products derived from this software without specific X * prior written permission. X * X * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY X * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE X * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR X * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR X * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER X * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X * SUCH DAMAGE. X */ X X/* X * Copyright 1991 Digital Equipment Corporation All Rights Reserved X * X * Permission to use, copy, and modify this software and its documentation is X * hereby granted only under the following terms and conditions. Both the X * above copyright notice and this permission notice must appear in all X * copies of the software, derivative works or modified versions, and any X * portions thereof, and both notices must appear in supporting X * documentation. X * X * Users of this software agree to the terms and conditions set forth herein, X * and hereby grant back to Digital a non-exclusive, unrestricted, X * royalty-free right and license under any changes, enhancements or X * extensions made to the core functions of the software, including but not X * limited to those affording compatibility with other hardware or software X * environments, but excluding applications which incorporate this software. X * Users further agree to use their best efforts to return to Digital any X * such changes, enhancements or extensions that they make and inform Digital X * of noteworthy uses of this software. Correspondence should be provided to X * Digital at: X * X * Director of Licensing Paris Research Laboratory Digital Equipment X * Corporation 85 Avenue Victor Hugo 92500 Rueil Malmaison France X * X * This software may be distributed (but not offered for sale or transferred X * for compensation) to third parties, provided such third parties agree to X * abide by the terms and conditions of this notice. X * X * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL X * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES X * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT X * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL X * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR X * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS X * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF X * THIS SOFTWARE. X */ X X#include "devfd.h" X#if NDEVFD > 0 X#include X#include X#include X X/* X * You can set up debugging by adding X * X * options DEVFDDEBUG X * X * to your kernel's config file. Then use adb to toggle devfddebug on or X * off in the kernel. devfddebug is off by default. X */ X X#ifdef DEVFDDEBUG Xint devfddebug = 0; X#define DEVFDDPRINT if (devfddebug > 0) printf X#endif X Xdevfdopen(dev, mode) X dev_t dev; X int mode; X{ X X struct file *fp, *wfp; X int fd, dfd; X X fd = u.u_r.r_val1; /* New file descriptor, from open/falloc */ X GETF(fp, fd); /* Associate it with new fp from falloc */ X dfd = minor(dev); /* File descriptor to dup */ X if (dfd > NDEVFD) X return (EBADF); X#ifdef DEVFDDEBUG X DEVFDDPRINT("/dev/fd/%d will be %d\n", dfd, fd); X#endif X /* X * If the to-be-dup'd fd number is greater than the allowed number of X * file descriptors, or the fd to be dup'd has already been closed, X * reject. Note, check for new == old is necessary as falloc could X * allocate an already closed to-be-dup'd descriptor as the new X * descriptor. X */ X X if (dfd >= u.u_rlimit[RLIMIT_NOFILE].rlim_cur || X (wfp = u.u_ofile[dfd]) == NULL || fp == wfp) X return (EBADF); X X /* X * Check that the mode the file is being opened for is a subset of the X * mode of the existing descriptor. X */ X X if (((mode & (FREAD | FWRITE)) | wfp->f_flag) != wfp->f_flag) X return (EACCES); X X /* dupit(fd, wfp, u.u_pofile[dfd]); */ X X u.u_ofile[fd] = wfp; X u.u_pofile[fd] = u.u_pofile[dfd] & ~UF_EXCLOSE; X wfp->f_count++; X if (fd > u.u_lastfile) X u.u_lastfile = fd; X X closef(fp); X return (0); X} X X#endif END-of-devfd.c echo x - devfd.4 sed 's/^X//' >devfd.4 << 'END-of-devfd.4' X.\" Copyright (c) 1990, 1991 The Regents of the University of California. X.\" All rights reserved. X.\" X.\" Redistribution and use in source and binary forms, with or without X.\" modification, are permitted provided that the following conditions X.\" are met: X.\" 1. Redistributions of source code must retain the above copyright X.\" notice, this list of conditions and the following disclaimer. X.\" 2. Redistributions in binary form must reproduce the above copyright X.\" notice, this list of conditions and the following disclaimer in the X.\" documentation and/or other materials provided with the distribution. X.\" 3. All advertising materials mentioning features or use of this software X.\" must display the following acknowledgement: X.\" This product includes software developed by the University of X.\" California, Berkeley and its contributors. X.\" 4. Neither the name of the University nor the names of its contributors X.\" may be used to endorse or promote products derived from this software X.\" without specific prior written permission. X.\" X.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND X.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE X.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE X.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE X.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL X.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS X.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) X.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT X.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY X.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF X.\" SUCH DAMAGE. X.\" X.\" @(#)fd.4 5.2 (Berkeley) 3/28/91 X.\" X.TH DEVFD 4 "28 March 1991" X.SH NAME X/dev/fd/#, /dev/stdin, /dev/stdout, /dev/stderr \- file descriptor files X.SH CONFIG X.B pseudo-device devfd\fIn\fP X.SH SYNOPSIS X.ft B X.nf X#include Xopen("/dev/fd/k", mode); X.SH DESCRIPTION XThe files X.I /dev/fd/0 Xthrough X.I /dev/fd/n Xrefer to file descriptors which can be accessed through the file Xsystem. XIf the file descriptor is open and the mode the file is being opened Xwith is a subset of the mode of the existing descriptor, the call: X.LP Xfd = open("/dev/fd/\fIk\fB", mode); X.LP Xand the call: X.LP Xfd = fcntl(\fIk\fB, F_DUPFD, 0); X.LP Xare equivalent. X.LP XOpening the files X.I /dev/stdin , X.I /dev/stdout Xand X.I /dev/stderr Xis equivalent to the following calls: X.LP X.nf Xfd = fcntl(0, F_DUPFD, 0); Xfd = fcntl(1, F_DUPFD, 0); Xfd = fcntl(2, F_DUPFD, 0); X.fi X.LP XFlags to the X.IR open (2) Xcall other than XO_RDONLY , XO_WRONLY Xand XO_RDWR Xare ignored. X.SH FILES X.nf X.ft B X/dev/fd/[0-(NOFILE-1)] X/dev/stdin X/dev/stdout X/dev/stderr X.fi X.ft R X.SH SEE ALSO X.IR tty (4) X.SH DIAGNOSTICS X/dev/fd/n: Bad file number X.LP XFile descriptor X.I n Xwasn't open before trying to open /dev/fd/n. X.LP X/dev/fd/n: Permission denied X.LP XRequested mode isn't a subset of the mode of the existing file descriptor. X.SH HISTORY XDerived from the /dev/fd driver in the CSRG NET/2 sources and a /dev/fd Xdriver for Ultrix that Boyd Roberts posted to comp.unix.wizards. END-of-devfd.4 echo x - test-devfd.c sed 's/^X//' >test-devfd.c << 'END-of-test-devfd.c' X/* X * Simple test program for /dev/fd. Tests opening and closing /def/fd/0, X * ..., /dev/fd/NDEVFD; spot checks that opening /dev/fd/k generates an EBADF X * error when file descriptor k isn't open, and spot checks that opening X * /dev/fd/k with a mode that isn't a subset of the mode of file descriptor k X * generates an EACCES error. X */ X X#include X#include X#include X#include X#include X Xextern char *mktemp(); Xchar template[] = "/tmp/BlatzoXXXXXX"; X X#define NDEVFD NOFILE-1 /* You have /dev/fd/0 thru /dev/fd/NDEVFD */ X Xmain() X{ X char buf[12]; /* Room for "/dev/fd/nnn" */ X char errbuf[100]; X char *tmpname; X int dfd; X int fd; X struct rlimit rlim; X X /* X * Try to open and close /dev/fd/0, ..., /dev/fd/NDEVFD. X */ X X printf("Testing opening and closing /dev/fd/0 through /dev/fd/%d... ", X NDEVFD); X fflush(stdout); X X if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { X perror("getrlimit"); X exit(1); X } X if (rlim.rlim_cur < NDEVFD + 1) X rlim.rlim_cur = NDEVFD + 1; X if (setrlimit(RLIMIT_NOFILE, &rlim) < 0) { X perror("setrlimit"); X exit(1); X } X for (fd = 0; fd <= NDEVFD; fd++) { X dup2(2, fd); X sprintf(buf, "/dev/fd/%d", fd); X sprintf(errbuf, "\nopening %s", buf); X if ((dfd = open(buf, O_RDWR)) < 0) { X perror(errbuf); X exit(1); X } X if (fd > 2) X close(fd); X sprintf(errbuf, "\nclosing %s", buf); X if (close(dfd) < 0) { X perror(errbuf); X exit(1); X } X } X printf("okay.\n"); X X /* X * Generate an EBADF error. X */ X X if (NDEVFD >= 3) { X printf("\nExpect a \"Bad file number\" error message next:\n\n"); X close(3); X sprintf(errbuf, "opening /dev/fd/3"); X if (open("/dev/fd/3", O_RDWR) < 0) X perror(errbuf); X } X /* X * Now generate an EACCES error. X */ X X if ((tmpname = mktemp(template)) == NULL) { X perror("mktemp"); X exit(1); X } X sprintf(errbuf, "opening %s", tmpname); X if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC)) < 0) { X perror(errbuf); X exit(1); X } X sprintf(errbuf, "chmod'ing %s", tmpname); X if (chmod(tmpname, 0444) < 0) { X perror(errbuf); X exit(1); X } X sprintf(buf, "/dev/fd/%d", fd); X sprintf(errbuf, "opening %s", buf); X printf("\nExpect a \"Permission denied\" error message next:\n\n"); X if ((dfd = open(buf, O_RDWR)) < 0) X perror(errbuf); X X unlink(tmpname); X X printf("\nDone.\n"); X exit(0); X} END-of-test-devfd.c exit -- Jim Davis | "Oh no. She used the three name call." jdavis@noao.edu | -- Clarissa (Marie) Darling