Newsgroups: comp.os.linux.announce
From: Ken Pizzini <ken@halcyon.halcyon.com>
Subject: file descriptor device (/dev/fd)
Message-ID: <1993Apr21.074453.16916@klaava.Helsinki.FI>
Date: Wed, 21 Apr 1993 07:44:53 GMT
Approved: linux-announce@tc.cornell.edu (Lars Wirzenius)

Here is my implementation of the file-descriptor device.  Opens
of an instance of this device will return a dup(2) of the file
descriptor corresponding to the minor device number.  I mainly
use the /dev/stdin and /dev/stdout portions of this device, but
it was just as easy to implement the whole thing.

		--Ken Pizzini

#! /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 shell archive."
# Contents:  README filedev.4 filedev.c filedev.h fddev-patch
#   fddev-mknods
# Wrapped by ken@kenpiz on Tue Apr 20 23:37:08 1993
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(385 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThe /dev/fd/n devices name a dup(2) of the file-descriptor n.
XThese files are especially useful with programs that don't use
Xthe "-"  filename  convention  for stdin/stdout,  or even to
Xmake the command line clearer in cases where "-" is allowed.
X
XTo install:
X	cd /usr/src/linux
X	mv filedev.c kernel/chr_drv
X	mv filedev.h include/linux
X	sh fddev-patch
X	make dep
X	make
X	sh fddev-mknods
END_OF_FILE
if test 385 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'filedev.4' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'filedev.4'\"
else
echo shar: Extracting \"'filedev.4'\" \(1289 characters\)
sed "s/^X//" >'filedev.4' <<'END_OF_FILE'
X.TH filedev 4 "15 April 1993"
X.SH NAME
Xfiledev, fd, stdin, stdout, stderr \- file descriptor device
X.SH
XCONFIG \- Linux 0.99p8
XMajor device c 24
X.SH SYNOPSIS
X.BI /dev/fd/ n
X.br
X.B /dev/stdin
X.br
X.B /dev/stdout
X.br
X.B /dev/stderr
X.SH DESCRIPTION
XThe
X.BI /dev/fd/ n
Xdevices name a
X.IR dup (2)
Xof the file-descriptor
X.IR n .
X.B /dev/stdin
Xis a link to
X.BR /dev/fd/0 .
XLikewise,
X.B /dev/stdout
Xis a link to
X.B /dev/fd/1
Xand
X.BR /dev/stderr ,
Xis a link to
X.BR /dev/fd/2 .
XThese files are especially useful with programs that don't
Xuse the "-" filename convention for stdin/stdout, or even
Xto make the command line clearer in cases where "-" is allowed.
X.SH FILES
X.RI /dev/fd/ n
X.br
X/dev/stdin
X.br
X/dev/stdout
X.br
X/dev/stderr
X.SH "SEE ALSO"
X.IR dup (2).
X.SH DIAGNOSTICS
X.TP
X.B EACCES
Xattempt to open a read-only file descriptor for writing,
Xor a write-only file descriptor for reading.
X.TP
X.B ENODEV
Xminor device number does not correspond to a valid file
Xdescriptor.
X.SH BUGS
XThe designation "fd" collides with that of the floppy disk drivers.
X.SH AUTHOR
XWritten by Ken Pizzini (ken@halcyon.com).
XPlaced in the public domain.
X.SH HISTORY
XI recall having heard that Bell Labs introduced the /dev/fd
Xconcept in their Version 8 Unix\*R.
X.SH MOTTO
XLinux: Because a PC is a terrible thing to waste.
END_OF_FILE
if test 1289 -ne `wc -c <'filedev.4'`; then
    echo shar: \"'filedev.4'\" unpacked with wrong size!
fi
# end of 'filedev.4'
fi
if test -f 'filedev.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'filedev.c'\"
else
echo shar: Extracting \"'filedev.c'\" \(1484 characters\)
sed "s/^X//" >'filedev.c' <<'END_OF_FILE'
X/*
X * linux/kernel/chr_drv/filedev.c
X *
X * File Descriptor pseudo-device, by Ken Pizzini (ken@halcyon.com)
X * April 14, 1993
X * Placed in the Public Domain
X *
X * Returns a dup(2) of the file descriptor corresponding to
X * the minor device number.
X *
X */
X
X#include <linux/fs.h>
X#include <linux/sched.h>
X#include <linux/errno.h>
X#include <linux/filedev.h>
X
X/* from fs/fcntl.c: */
Xextern int sys_dup2(unsigned int, unsigned int);
X
X/* forward reference: */
Xextern struct file_operations filedev_fops;
X
Xstatic int
Xfiledev_open(struct inode * inode, struct file * file)
X{
X	unsigned int minor = MINOR(inode->i_rdev);
X	unsigned int my_fd;
X	int dup_status;
X
X	if (minor >= NR_OPEN)
X		return -ENODEV;
X	for (my_fd=0; my_fd<NR_OPEN; ++my_fd)
X		if (current->filp[my_fd] == file)
X			break;
X	if (my_fd >= NR_OPEN)
X		return -EBADF; /* actually, soft-panic time... */
X	if (file->f_mode > current->filp[minor]->f_mode) /* Should this be == ??? */
X		return -EACCES;
X	if ((dup_status = sys_dup2(minor, my_fd)) < 0)
X		return dup_status;
X	return 0;
X}
X
Xstatic struct file_operations filedev_fops = {
X	NULL,		/* seek */
X	NULL,		/* read */
X	NULL,		/* write */
X	NULL,		/* readdir */
X	NULL,		/* select */
X	NULL,		/* ioctl */
X	NULL,		/* mmap */
X	filedev_open,
X	NULL		/* release */
X};
X
X
Xlong
Xfiledev_init(long kmem_start)
X{
X	int err = register_chrdev(DEVFD_MAJOR, "filedev", &filedev_fops);
X	if (err)
X		printk("unable to get major %d for file descriptor device; err=%d\n", DEVFD_MAJOR, err);
X	return kmem_start;
X}
END_OF_FILE
if test 1484 -ne `wc -c <'filedev.c'`; then
    echo shar: \"'filedev.c'\" unpacked with wrong size!
fi
# end of 'filedev.c'
fi
if test -f 'filedev.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'filedev.h'\"
else
echo shar: Extracting \"'filedev.h'\" \(308 characters\)
sed "s/^X//" >'filedev.h' <<'END_OF_FILE'
X/*
X * linux/include/linux/devfd.h
X *
X * File Descriptor pseudo-device, by Ken Pizzini (ken@halcyon.com)
X * April 14, 1993
X * Placed in the Public Domain
X *
X */
X#ifndef _LINUX_DEVFD_H
X#define _LINUX_DEVFD_H
X
X#define DEVFD_MAJOR 24		/*major device number for fd device*/
X
Xextern long devfd_init(long);
X
X#endif
END_OF_FILE
if test 308 -ne `wc -c <'filedev.h'`; then
    echo shar: \"'filedev.h'\" unpacked with wrong size!
fi
# end of 'filedev.h'
fi
if test -f 'fddev-patch' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fddev-patch'\"
else
echo shar: Extracting \"'fddev-patch'\" \(525 characters\)
sed "s/^X//" >'fddev-patch' <<'END_OF_FILE'
X#!/bin/sh
X
Xcd kernel/chr_drv
X
X# I'm using this ad-hoc script instead of a patch file
X# because these file sections change a lot with individual's
X# device driver additions.  --KP
X
Xmv Makefile Makefile~
Xsed 's/atixlmouse.o/& \\\
X	filedev.o/' Makefile~ >Makefile
X
Xmv mem.c mem.c~
X# I'm using a character-class for the parenthesis because
X# some seds treat parenthesis specially, and some seds
X# treat \( and \) specially.
Xsed '/^	mem_start = mouse_init[(]mem_start[)];$/a\
X	mem_start = filedev_init(mem_start);
X' mem.c~ >mem.c
END_OF_FILE
if test 525 -ne `wc -c <'fddev-patch'`; then
    echo shar: \"'fddev-patch'\" unpacked with wrong size!
fi
chmod +x 'fddev-patch'
# end of 'fddev-patch'
fi
if test -f 'fddev-mknods' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fddev-mknods'\"
else
echo shar: Extracting \"'fddev-mknods'\" \(239 characters\)
sed "s/^X//" >'fddev-mknods' <<'END_OF_FILE'
X#!/bin/sh
X#make the /dev/fd/ entries
X
XFDMAJOR=24
XMAXFD=128
X
Xcd /dev
Xmkdir fd
X
Xumask 0
X
Xfd=0
Xwhile expr $fd \< $MAXFD >/dev/null; do
X	mknod fd/$fd c $FDMAJOR $fd
X	fd=`expr $fd + 1`
Xdone
X
Xln -s fd/0 stdin
Xln -s fd/1 stdout
Xln -s fd/2 stderr
END_OF_FILE
if test 239 -ne `wc -c <'fddev-mknods'`; then
    echo shar: \"'fddev-mknods'\" unpacked with wrong size!
fi
chmod +x 'fddev-mknods'
# end of 'fddev-mknods'
fi
echo shar: End of shell archive.
exit 0
