[comp.unix.wizards] /dev/stdin for 4.3?

prog@braggvax.arpa (05/13/87)

Hi folks,

This has probably already been asked (and answered) several times, but does
anyone have the code to put the /dev/stdin device in 4.3?

				Thanks

				Ted Nolan
				ted@braggvax.arpa

gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/13/87)

In article <7359@brl-adm.ARPA> prog@braggvax.arpa writes:
>This has probably already been asked (and answered) several times, but does
>anyone have the code to put the /dev/stdin device in 4.3?

This is almost trivial:
	1) Implement /dev/fd instead (general file descriptor device),
		using minor device to select the fd #.  Make /dev/stdin
		a link to /dev/fd/0, similarly for /dev/stdout etc.
	2) All you need is the open() entry, which should simply snarf
		up the process's corresponding file table index, just
		like a dup() except you don't allocate anything.
	3) read(), write(), select(), close(), etc. don't even have
		to know how you got the fd open.  (You'll be using the
		entries associated with the original non-/dev/fd open,
		so there need be no entries for these in the /dev/fd
		driver.)

I've seen several implementations but none this simple.

chris@mimsy.UUCP (Chris Torek) (05/14/87)

In article <5856@brl-smoke.ARPA> gwyn@brl-smoke.ARPA (Doug Gwyn) writes:
>[/dev/stdin] is almost trivial:
> 1) Implement /dev/fd instead (general file descriptor device) ....
> 2) All you need is the open() entry ... just like a dup() except
>	you don't allocate anything.
>I've seen several implementations but none this simple.

Ours was, until Fred decided that the semantics were a bit odd.
Now they are odder.  Consider:  A dup()ed file descriptor shares
a seek pointer with another; an open()ed file descriptor does not.
A dup()ed file descriptor shares its read/write access status with
another; an open()ed descriptor does not.  But if opening /dev/fd/n
duplicates file descriptor n, suddenly open()ed file descriptors
share seek pointers and access status.  In particular, this means
you cannot open /dev/fd/5 for reading if file descriptor 5 is
currently open only for writing.

Anyway, if the descriptor refers to an inode, it is easy enough
to re-open() it.  If it refers to a socket, it must be dup()ed, as
there is nothing to open.  I would say that this is an argument
in favour of always doing a dup(), but Fred insisted. . . .
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

gwyn@brl-smoke.UUCP (05/15/87)

In article <6679@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>A dup()ed file descriptor shares its read/write access status with
>another; an open()ed descriptor does not.  But if opening /dev/fd/n
>duplicates file descriptor n, suddenly open()ed file descriptors
>share seek pointers and access status.  In particular, this means
>you cannot open /dev/fd/5 for reading if file descriptor 5 is
>currently open only for writing.

I think this is perfectly acceptable for the /dev/fd device
semantics.  I think there should be an access check so that
the open() fails if you try to open for a mode not already
encompassed by the current fd, but that's all.

Norman tells me that the Nth (N >= 9) Edition UNIX now uses
the scheme I described.

dave@onfcanim.UUCP (05/18/87)

In article <5856@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
> [ discussing how to implement /dev/fd*, /dev/std{in,out,err} ]

>This is almost trivial:
>	1) Implement /dev/fd instead (general file descriptor device),
>		using minor device to select the fd #.  Make /dev/stdin
>		a link to /dev/fd/0, similarly for /dev/stdout etc.
>	2) All you need is the open() entry, which should simply snarf
>		up the process's corresponding file table index, just
>		like a dup() except you don't allocate anything.
>	3) read(), write(), select(), close(), etc. don't even have
>		to know how you got the fd open.  (You'll be using the
>		entries associated with the original non-/dev/fd open,
>		so there need be no entries for these in the /dev/fd
>		driver.)

I believe it's better to do the equivalent of a full dup(), returning
a newly-opened descriptor.  You still need only an open() entry,
but you have to alloc an ofile table slot and increment the reference
count on the file struct.

If you just pass back the old already-open descriptor, you have two
"names" for the same "object", though the program thinks they are
entirely distinct.  Closing the unit via one name causes the other
name to also become invalid, which may be rather surprising.
For example, consider the program fragment:

	outfile = fopen(argv[argc-1], "w");
	fwrite(stuff, sizeof stuff, 1, outfile);
	fclose(outfile);
	printf("status message");

If this is called with an argument of "/dev/stdout" in order to get its
output written to standard output, the fclose will actually close unit 1
and the last printf will never appear.  Dup()'ing the unit avoids this.

Now, you can also argue that a new file struct should be allocated too,
exactly the same as would happen if you really open()ed the same file
twice.  However, I think this less likely to cause trouble, and having
the two logically-separate units sharing the same seek pointer may
actually be useful sometimes.

m5@bobkat.UUCP (Mike McNally ) (05/18/87)

In article <7359@brl-adm.ARPA> prog@braggvax.arpa writes:
>
>This has probably already been asked (and answered) several times, but does
>anyone have the code to put the /dev/stdin device in 4.3?
>
>				Ted Nolan

I guess I'm just an ignorant BSD person.  Could somebody post an example
to provide a motivation for having /dev/stdin?  I know what it is, but 
I'm having trouble thinking of a situation in which I would want it.




-- 
Mike McNally, mercifully employed at Digital Lynx ---
    Where Plano Road the Mighty Flood of Forest Lane doth meet,
    And Garland fair, whose perfumed air flows soft about my feet...
uucp: {texsun,killer,infotel}!pollux!bobkat!m5 (214) 238-7474

gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/19/87)

In article <983@bobkat.UUCP> m5@bobkat.UUCP (Mike McNally (Man from Mars)) writes:
>I guess I'm just an ignorant BSD person.  Could somebody post an example
>to provide a motivation for having /dev/stdin?  I know what it is, but 
>I'm having trouble thinking of a situation in which I would want it.

That's simple: any place where the code is set up to deal with a filename
but you might prefer to use the output end of a pipe (for example).
	$ cmd | sort | troff header /dev/stdin trailer
Some commands give special meaning to "-" as a filename, but it is much
better to provide a general facility.

dhesi@bsu-cs.UUCP (Rahul Dhesi) (05/22/87)

In article <5872@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) 
explains the need for a /dev/stdin thus:
>           ....any place where the code is set up to deal with a filename
>but you might prefer to use the output end of a pipe (for example).
>	$ cmd | sort | troff header /dev/stdin trailer
>Some commands give special meaning to "-" as a filename, but it is much
>better to provide a general facility.

I see a potential problem here.  Programs that won't let you read from
standard input will frequently attempt to do seeks within the input
file.  So to anybody planning to implement /dev/stdin, I suggest adding
a buffering facility that allows seeks to within the buffered area.
Make the buffer size configurable at boot time if possible or better
still, let it be configurable for individual users when they log in.
(Can UNIX devices use non-kernel buffers dynamically?  I have no idea.)

In fact, pipes ought really to be extended to do dynamic buffering.
-- 
Rahul Dhesi         UUCP:  {ihnp4,seismo}!{iuvax,pur-ee}!bsu-cs!dhesi

gwyn@brl-smoke.ARPA (Doug Gwyn ) (05/23/87)

In article <684@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
-I see a potential problem here.  Programs that won't let you read from
-standard input will frequently attempt to do seeks within the input
-file.  So to anybody planning to implement /dev/stdin, I suggest adding
-a buffering facility that allows seeks to within the buffered area.
-Make the buffer size configurable at boot time if possible or better
-still, let it be configurable for individual users when they log in.
-(Can UNIX devices use non-kernel buffers dynamically?  I have no idea.)
-
-In fact, pipes ought really to be extended to do dynamic buffering.

I have to strongly disagree with this.  If you can't make a data object
that is inherently sequential act completely as a random-access object
(as you in fact can't in general), then there is no point in
implementing half-measures that add complexity and have dubious utility.

Actually, STDIO buffering suffices for a limited amount of this sort of
stuff on sequential objects.  X3J11 guarantees one character of pushback
on a text stream; implementors will in general have to arrange for two
look-aside pockets since scanf() conflicts with ungetc().

wedgingt@udenva.UUCP (Will Edgington) (06/01/87)

In article <15318@onfcanim.UUCP> dave@onfcanim.UUCP (Dave Martindale) writes:
> [ discussing how to implement /dev/fd*, /dev/std{in,out,err} ]
>
>I believe it's better to do the equivalent of a full dup(), returning
>a newly-opened descriptor.  You still need only an open() entry,
>but you have to alloc an ofile table slot and increment the reference
>count on the file struct.
>
>[...]
>
>Now, you can also argue that a new file struct should be allocated too,
>exactly the same as would happen if you really open()ed the same file
>twice.  However, I think this less likely to cause trouble,

Slightly !  If you really open it, think about what happens with
something like :

% cat /etc/passwd | 1and2 /dev/stdin /dev/stdin

where the program '1and2' takes one line from it's first argument,
prints it, 2 lines from it's second arg, prints them, and goes
back to one line from it's first arg (something like serial merging
of already sorted data) ...  You're trying to use the data from the
pipe *twice* !!!  Certainly, whoever's doing this will be mighty
surprised when he merely gets the password file as output (which is
what I *think* would happen).  Of course, since pipes are implemented
as sockets under BSD 4.[23] (I'm not sure about 4.1), you can't
open() it twice anyway.  Of course, doing the open() indirectly like
this may mean the kernel can't tell it's a socket until too late ...
In any case, the semantics are a MESS.

>and having
>the two logically-separate units sharing the same seek pointer may
>actually be useful sometimes.

Yes ...

While I'm here, I seem to remember something about file descriptor
drivers like this being security holes in certain cases.  Anyone
care to elaborate on this aspect (probably again) ?  I'm on the
Security mailing list, also, if you'd prefer to go that route
(in fact, the Security list's moderator is on another Univ. of
Denver site; his address is {hao,nbires}!udenva!isis!aburt).
-----
Will Edgington, Computing and Information Resources, University of Denver
System Administrator for udenva (== dueos), dutyche, duorion, dunike, ...
{{hplabs,seismo}!hao,ucbvax!nbires,boulder,cires,ssds}!udenva!wedgingt,
WEDGINGT@DUCAIR (BITNET), wedgingt@ccndu (CSN/CCN), ...
COMING SOON: wedgingt@du.edu (all nets)|"No two addresses are the same ..."

rbj@icst-cmr.arpa (Root Boy Jim) (06/01/87)

   From: Doug Gwyn  <gwyn@brl-smoke.arpa>
   In article <684@bsu-cs.UUCP> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
   -I see a potential problem here.  Programs that won't let you read from
   -standard input will frequently attempt to do seeks within the input
   -file.  So to anybody planning to implement /dev/stdin, I suggest adding
   -a buffering facility that allows seeks to within the buffered area.
   -Make the buffer size configurable at boot time if possible or better
   -still, let it be configurable for individual users when they log in.
   -(Can UNIX devices use non-kernel buffers dynamically?  I have no idea.)
   -
   -In fact, pipes ought really to be extended to do dynamic buffering.

   I have to strongly disagree with this.  If you can't make a data object
   that is inherently sequential act completely as a random-access object
   (as you in fact can't in general), then there is no point in
   implementing half-measures that add complexity and have dubious utility.

I have to be strongly ambivalent here. While I with Doug that half-baked
implementations that add little value are to be avoided, conceptually
the sequence "a | b" is equivalent to "a > file ; b < file", and I have
always thought that you should be able to seek relatively forward
on pipes or sequential devices as well. Of course, in the first case,
you can always use the temporary file if you need to. In the second,
separate code would have to be written.

However, I feel that Rahul has raised a valid point: a program might
have problems with the difference between "... | prog" versus
"prog /dev/stdin" or between "... | prog file1 - file2" versus
"... | prog file1 /dev/stdin file2". In the former cases, prog knows
to it is reading its stdin simply by its argv geometry. In the latter,
it must either pattern match the name "/dev/std{in,out,err}" or
"/dev/fd[0-9]*" (think regex, not glob), possibly without the "/dev/"
if /dev is the current directory, which is all more complex than "-";
or stat the file, which is probably the best thing to do in the first
place. But that adds another level of complexity to programs who
care whether a given file is seekable or not. Of course *any* given
filename could be unseekable, so we're no worse off than when we started.

It is conceivable that the difference might matter to some convolutedly
plumbed program (for example, doesn't csh save its std{in,out,err}
in fd's 17,18, & 19?), but I can't think of anything obvious.

Like Doug said, why do you think they call them sequential?

	(Root Boy) Jim Cottrell	<rbj@icst-cmr.arpa>
	National Bureau of Standards
	Flamer's Hotline: (301) 975-5688

	Yow!  Did something bad happen or am I in a drive-in movie??

chris@mimsy.UUCP (06/02/87)

>In article <5856@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>>...All you need is the open() entry, which should simply snarf
>>up the process's corresponding file table index, just
>>like a dup() except you don't allocate anything.

In article <15318@onfcanim.UUCP> dave@onfcanim.UUCP writes:
>I believe it's better to do the equivalent of a full dup(), returning
>a newly-opened descriptor.  You still need only an open() entry,
>but you have to alloc an ofile table slot and increment the reference
>count on the file struct.

All that is done for you by `open'; you need only discard the inode.
Specifically:

fdopen(dev, flag)
	dev_t dev;
	int flag;
{
	register struct file *fp, *wfp;
	int rwmode;

	fp = getf(u.u_r.r_val1);	/* never fails */
	if ((wfp = getf(minor(dev))) == NULL || fp == wfp)
		return (EBADF);
	rwmode = flag & (FREAD|FWRITE);
	if ((fp->f_flag & rwmode) != rwmode)
		return (EACCES);
	irele((struct inode *)fp->f_data);
	fp->f_count = 0;
	dupit(u.u_r.r_val1, wfp, u.u_pofile[minor(dev)]);
	return (0);
}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

jfh@killer.UUCP (06/04/87)

I have thought about putting this in my lowly Version 7 kernel, and I want
a few questions answered.

Assuming

	int	fd;
	struct	stat	stat1, stat2;

	fd = open ("/dev/stdin", 0);

do fstat (0, &stat1) and fstat (fd, &stat2) return the same thing?  What
if _after_ the open I do a freopen (stdin, ...) or a close (0) followed
by open (somefile)?  Does this still hold true?  If memory and understanding
serve me correctly, if in System V I close all my terminal files, do a
setpgrp() and open some new terminal file - then open /dev/tty, I get the
new tty.  But what happens if I open /dev/tty before all of the closes,
do the setpgrp(), and open a new tty?  Seems to me (from what I remember
last time I looked at the source) that /dev/tty points to the _new_ tty
after the open(), not the old one since the driver gets the controlling
tty from the U-page or something like that.  HELP ME PLEASE (send manual
pages in other words ...)

- John.		(Still working on a .signature in the Big D)

Disclaimer:  I didn't do it.  Honest.

mouse@mcgill-vision.UUCP (06/05/87)

In article <684@bsu-cs.UUCP>, dhesi@bsu-cs.UUCP (Rahul Dhesi) writes:
> In article <5872@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) 
> explains the need for a /dev/stdin thus:

>> ....any place where the code is set up to deal with a filename but
>> you might prefer to use the output end of a pipe (for example).

> I see a potential problem here.  Programs that won't let you read
> from standard input will frequently attempt to do seeks within the
> input file.

That's their problem. :-)

A program that expects to do seeks should ensure that the object can
seek, not just prohibit standard input.  Suppose you use gave it
/dev/tty?  There's something, on BSD at least, called fstat(), which
performs a stat() on the object pointed to by a file descriptor.  Even
better, maybe, would be to try a seek and die if it fails.

When I wrote a program that expected to seek, I just punted: ignore the
issue, and note in the documentation that it expects seeks to work!
(Yes, this is suboptimal.  To put it mildly.)

					der Mouse

				(mouse@mcgill-vision.uucp)

mouse@mcgill-vision.UUCP (06/05/87)

In article <15318@onfcanim.UUCP>, dave@onfcanim.UUCP (Dave Martindale) writes:
> In article <5856@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes:
>> [ discussing how to implement /dev/fd*, /dev/std{in,out,err} ]

>> This is almost trivial:
>> 1) Implement /dev/fd instead (general file descriptor device), using
>> minor device to select the fd #.  Make /dev/stdin a link to
>> /dev/fd/0, similarly for /dev/stdout etc.

Is this a SysV thing?  I was not aware of any way to make a device
which could be treated like a directory like that (/dev/fd/0).

> I believe it's better to do the equivalent of a full dup(), returning
> a newly-opened descriptor.  You still need only an open() entry, but
> you have to alloc an ofile table slot and increment the reference
> count on the file struct.

Here's how I did it:

% ls -l /dev/std*
crw-rw-rw-  1 mouse     64,   2 Mar 23 05:31 /dev/stderr
crw-rw-rw-  1 mouse     64,   0 Mar 23 05:31 /dev/stdin
crw-rw-rw-  1 mouse     64,   1 Mar 23 05:31 /dev/stdout
% 

machine/conf.c entry:

	stddevopen,	nodev,		nodev,		nodev,		/* 64 */
	nodev,		nulldev,	nulldev,	0,
	nodev,		nodev,

(notice, only the "open" slot has anything in it).

stddevopen(dev,mode)
dev_t dev;
int mode;
{
 int fd = minor(dev);
 int rfd = u.u_r.r_val1;

 if ((fd < 0) || (fd >= NOFILE))
  { return(EBADF);
  }
 if (u.u_ofile[fd] == NULL)
  { return(ENXIO);
  }
 if ((mode&FREAD) && !(u.u_ofile[fd]->f_flag&FREAD))
  { return(EACCES);
  }
 if ((mode&FWRITE) && !(u.u_ofile[fd]->f_flag&FWRITE))
  { return(EACCES);
  }
 u.u_ofile[rfd]->f_count --;
 u.u_ofile[rfd] = u.u_ofile[fd];
 u.u_pofile[rfd] = u.u_pofile[fd] & ~UF_EXCLOSE;
 u.u_ofile[fd]->f_count ++;
 return(0);
}

So there.  (stddevopen() is, functionally, just another interface to dup().)

Another use for /dev/std*:  in a csh script, how do you generate a
fixed message on the script's standard error?

sh -c 'echo this is the message 1>&2'

Ugly.  Unreadable by someone who doesn't know sh syntax.  Forks an
unnecessary sh process.

echo this is the message > /dev/stderr

Much better.  (Yes, I know sh is better for most scripts.)

					der Mouse

				(mouse@mcgill-vision.uucp)

chris@mimsy.UUCP (06/08/87)

In article <958@killer.UUCP> jfh@killer.UUCP (John Haugh) writes:
>Assuming
>
>	int	fd;
>	struct	stat	stat1, stat2;
>
>	fd = open ("/dev/stdin", 0);
>
>do fstat (0, &stat1) and fstat (fd, &stat2) return the same thing?

Doing

	int fd = open("/dev/stdin", 0);

is supposed to be exactly equivalent to doing

	int fd = dup(0);

so the answer is `yes'.  More specifically, opening /dev/fd/n
returns whatever dup(n) would return.  The only tricky thing about
this is that the open mode (0, 1, 2) must match (or subset) the
mode of the existing descriptor `n'.  If file descriptor 4 is open
for reading only, and you attempt an open("/dev/fd/4", 1), the fd
driver should reject this (return -1 from open) because, due to
the dup-style implementation, writes on the new descriptor would
fail, just as they would if you had written

	int cc, fd = dup(4);
	...
	cc = write(fd, ...);

>What if _after_ the open I do a freopen (stdin, ...) or a close (0)
>followed by open (somefile)?

Everything works as if you had done a `dup(0)'.  `fd' still refers
to whatever was open before; 0 refers to whatever is open now.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

chris@mimsy.UUCP (06/14/87)

In article <792@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse)
gives an implementation of the `open' routine for the /dev/fd/n driver.
His has an interesting bug.  Try `cat /dev/fd/3', or run the following
program:

	main()
	{
		int fd, cc;
		extern int errno;

		(void) close(2);
		fd = open("/dev/stderr", 1);
		if (fd != 2) {
			printf("did not get stderr: fd=%d, errno=%d\n", fd,
				errno);
			exit(0);
		}
		if ((cc = write(2, "odd", 3)) != 3)
			printf("wrote %d instead of 3, errno=%d\n", cc, errno);
		exit(0);
	}

The problem is that in

	int fd = minor(dev);
	int rfd = u.u_r.r_val1;

`fd' is then equal to `rfd', so all the permission checks pass, and then

	u.u_ofile[rfd]->f_count --;

sets f_count to zero;

	u.u_ofile[rfd] = u.u_ofile[fd];

is a no-op;

	u.u_pofile[rfd] = u.u_pofile[fd] & ~UF_EXCLOSE;

is also a no-op; and

	u.u_ofile[fd]->f_count ++;

sets f_count back to 1.  The `write' then calls nodev.

This should not in fact break anything, but is an interesting
loophole that is closed in Fred Blonder's version.

As to this:

>I was not aware of any way to make a device which could be treated
>like a directory like that (/dev/fd/0).

There is nothing special going on here.

	# mkdir /dev/fd
	# cd /dev/fd
	# major=64		# or whatever cdevsw slot you have used
	# nofile=`egrep NOFILE /usr/include/sys/param.h | awk '{print $3}'`
	# for i in `awk "END {for(i=0;i<$nofile;i++)print i}"</dev/null`; do
	> mknod $i c $major $i; done
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

stu@jpusa1.UUCP (Stu Heiss) (06/17/87)

Summary:

Expires:


In article <7036@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
-In article <792@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse)
-gives an implementation of the `open' routine for the /dev/fd/n driver.
-His has an interesting bug.
-This should not in fact break anything, but is an interesting
-loophole that is closed in Fred Blonder's version.
C'mon guys, don't leave us in the dark!  I was about to install Mouse's 'driver'
and don't recall seeing anything by Fred Blonder.  Give us a working driver, please.
This seems trivial for you kernal wizards.  Chris, Mouse, can you help?
--
Stu Heiss {gargoyle,ihnp4}!jpusa1!stu

mouse@mcgill-vision.UUCP (der Mouse) (06/26/87)

In article <302@jpusa1.UUCP>, stu@jpusa1.UUCP (Stu Heiss) writes:
> In article <7036@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>> In article <792@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse)
>> gives an implementation of the `open' routine for the /dev/fd/n
>> driver.  His has an interesting bug.

Indeed it does.  Thanks for catching that one, Chris.

>> This should not in fact break anything,

True, assuming you did in fact put nodev in the read and write slots of
the cdevsw entry.

> C'mon guys, don't leave us in the dark!  I was about to install
> Mouse's 'driver' and don't recall seeing anything by Fred Blonder.

Neither do I, for that matter, but I wasn't watching closely 'cause
I've already *got* such a driver.

> Give us a working driver, please.

Well, actually the original worked, it's just that one particular error
case wasn't being caught quite soon enough, and resulted in a
successful open() and then failing read()s and/or write()s.

> This seems trivial for you kernal wizards.  Chris, Mouse, can you
> help?

Once noticed, it is simple to fix.  (This patch also changes a NULL to
a 0, because I have quit trusting people responsible for C system
maintenence to define NULL correctly.  In this case, it's OK 'cause
this is rather BSD-specific, but it can't hurt anything.)

*** stdiodev.c=	Fri Nov 21 04:45:25 1986
--- stdiodev.c	Fri Jun 26 04:51:27 1987
***************
*** 19,25 ****
   if ((fd < 0) || (fd >= NOFILE))
    { return(EBADF);
    }
!  if (u.u_ofile[fd] == NULL)
    { return(ENXIO);
    }
   if ((mode&FREAD) && !(u.u_ofile[fd]->f_flag&FREAD))
--- 19,28 ----
   if ((fd < 0) || (fd >= NOFILE))
    { return(EBADF);
    }
!  if (fd == rfd)
!   { return(ENXIO);
!   }
!  if (u.u_ofile[fd] == 0)
    { return(ENXIO);
    }
   if ((mode&FREAD) && !(u.u_ofile[fd]->f_flag&FREAD))

					der Mouse

				(mouse@mcgill-vision.uucp)

arnold@emory.uucp (Arnold D. Robbins {EUCC}) (07/02/87)

I have Fred Blonder's original fd driver for 4.2 and will post it if there
is enough response (VIA MAIL!). However, I hereby announce that I am
working on an NFS version of this driver which I will post (if I get it
to work). Said version will include the original version inside ifdefs;
so if you think you can wait a while, both will be available.

(I'll trade ya two vnodes and an snode for an inode any day... :-)
-- 
Arnold Robbins
CSNET:	arnold@emory	BITNET:	arnold@emoryu1
ARPA:	arnold%emory.csnet@csnet-relay.arpa
UUCP:	{ akgua, decvax, gatech, sb1, sb6, sunatl }!emory!MTMTM w