home *** CD-ROM | disk | FTP | other *** search
- /*
- $Header: /aware0/src/dup/dup.c,v 1.2 90/07/26 12:55:44 sw Exp $
- */
-
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/sysmacros.h>
- #include <sys/dir.h>
- #include <sys/file.h>
- #include <sys/inode.h>
- #include <sys/signal.h>
- #include <sys/errno.h>
- #include <sys/user.h>
-
- /*
- 4.2 BSD pseudo-device driver for the "fd" 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 fd device with minor device 0. Opening
- /dev/stdin returns a duplicate of file descriptor 0, equivalent to
- fd(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.
-
- "fd" 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
-
- Suitably adapted to System V/386 rel. 3.2 by Piercarlo Grandi,
- July 1990. Name changed to "dup" to avoid conflict with the
- floppy disc driver.
- */
-
- dupopen(dev,mode)
- dev_t dev;
- int mode;
- {
- register int fd,oldfd;
- register struct file *fp,*oldfp;
-
- /*
- Here we rely on the current file descriptor being still in
- u.u_r.r_val1, where it has been put by openi() to be returned
- to the user as the result of the open(2) call. Horrible kludge.
- */
-
- /*
- The current file descriptor must be valid.
- */
-
- fd = u.u_r.r_reg.r_val1;
- if (fd < 0 || fd >= NOFILE) /* something terrible has happened */
- return EINVAL;
-
- /*
- The old file descriptor must be valid and different from the
- current one.
- */
-
- oldfd = minor(dev);
- if (oldfd < 0 || oldfd >= NOFILE || fd == oldfd)
- return EBADF;
-
- /*
- The old file descriptor must point to some file struct, and the
- old open mode must be a superset of the current one.
- */
-
- oldfp = u.u_ofile[oldfd];
- if (oldfp == NULL)
- return EBADF;
-
- if ((mode & (oldfp->f_flag & (FREAD|FWRITE))) != (mode & (FREAD|FWRITE)))
- return EACCES;
-
- /*
- The current file pointer can now be thrown away.
- */
-
- fp = u.u_ofile[fd];
- if (fp != NULL) /* otherwise something terrible has happened */
- {
- u.u_ofile[fd] = NULL;
- if (fp->f_inode) iput(fp->f_inode);
- fp->f_count = 0;
- }
-
- /*
- The old file pointer becomes the current one as well.
- */
-
- u.u_pofile[fd] = u.u_pofile[oldfd];
- (u.u_ofile[fd] = oldfp)->f_count++;
-
- return 0;
- }
-