home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1626 / dup.c next >
C/C++ Source or Header  |  1990-12-28  |  3KB  |  106 lines

  1. /*
  2.     $Header: /aware0/src/dup/dup.c,v 1.2 90/07/26 12:55:44 sw Exp $
  3. */
  4.  
  5. #include <sys/param.h>
  6. #include <sys/types.h>
  7. #include <sys/sysmacros.h>
  8. #include <sys/dir.h>
  9. #include <sys/file.h>
  10. #include <sys/inode.h>
  11. #include <sys/signal.h>
  12. #include <sys/errno.h>
  13. #include <sys/user.h>
  14.  
  15. /*
  16.     4.2 BSD pseudo-device driver for the "fd" device.  An attempt to
  17.     open this device returns a file descriptor which is a "duplicate"
  18.     of the open file descriptor corresponding to the minor device
  19.     number of the particular filedesc device opened.  For example, the
  20.     device /dev/stdin is a fd device with minor device 0.  Opening
  21.     /dev/stdin returns a duplicate of file descriptor 0, equivalent to
  22.     fd(0).  The open mode must be the same as the mode of the file
  23.     descriptor being duplicated, except that a read/write file
  24.     descriptor can be duped for just read or just write.
  25.  
  26.     The idea of "/dev/stdin" originated in Bell Labs UNIX 8th Edition
  27.     (research version 8) and was described by Rob Pike at the Summer
  28.     1985 Usenix Conference in Portland.  We use the names
  29.     "/dev/stdin", "/dev/stdout", and "/dev/stderr" for minor devices
  30.     0,1, and 2, as well as the names "/dev/fdXX" for XX ranging from 0
  31.     to NOFILE-1.  The protection mode of the device inodes should be
  32.     0666.
  33.  
  34.     "fd" driver written 16-Jun-85 by Darwyn Peachey, Computer Science
  35.     Research Lab, University of Saskatchewan, Saskatoon, Canada S7N
  36.     0W0 Phone: (306) 966-4909 UUCP: ihnp4!sask!kimnovax!peachey
  37.  
  38.     Suitably adapted to System V/386 rel.  3.2 by Piercarlo Grandi,
  39.     July 1990.  Name changed to "dup" to avoid conflict with the
  40.     floppy disc driver.
  41. */
  42.  
  43. dupopen(dev,mode)
  44.     dev_t                   dev;
  45.     int                     mode;
  46. {
  47.     register int            fd,oldfd;
  48.     register struct file    *fp,*oldfp;
  49.  
  50.     /*
  51.         Here we rely on the current file descriptor being still in
  52.     u.u_r.r_val1, where it has been put by openi() to be returned
  53.     to the user as the result of the open(2) call. Horrible kludge.
  54.     */
  55.  
  56.     /*
  57.     The current file descriptor must be valid.
  58.     */
  59.  
  60.     fd = u.u_r.r_reg.r_val1;
  61.     if (fd < 0 || fd >= NOFILE)    /* something terrible has happened */
  62.     return EINVAL;
  63.  
  64.     /*
  65.     The old file descriptor must be valid and different from the
  66.     current one.
  67.     */
  68.  
  69.     oldfd = minor(dev);
  70.     if (oldfd < 0 || oldfd >= NOFILE || fd == oldfd)
  71.     return EBADF;
  72.  
  73.     /*
  74.     The old file descriptor must point to some file struct, and the
  75.     old open mode must be a superset of the current one.
  76.     */
  77.  
  78.     oldfp = u.u_ofile[oldfd];
  79.     if (oldfp == NULL)
  80.     return EBADF;
  81.  
  82.     if ((mode & (oldfp->f_flag & (FREAD|FWRITE))) != (mode & (FREAD|FWRITE)))
  83.     return EACCES;
  84.  
  85.     /*
  86.     The current file pointer can now be thrown away.
  87.     */
  88.  
  89.     fp = u.u_ofile[fd];
  90.     if (fp != NULL) /* otherwise something terrible has happened */
  91.     {
  92.     u.u_ofile[fd] = NULL;
  93.     if (fp->f_inode) iput(fp->f_inode);
  94.     fp->f_count = 0;
  95.     }
  96.  
  97.     /*
  98.     The old file pointer becomes the current one as well.
  99.     */
  100.  
  101.     u.u_pofile[fd] = u.u_pofile[oldfd];
  102.     (u.u_ofile[fd] = oldfp)->f_count++;
  103.  
  104.     return 0;
  105. }
  106.