home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trash / part02 / fd.c next >
Encoding:
C/C++ Source or Header  |  1992-03-22  |  5.3 KB  |  345 lines

  1. #include    <fcntl.h>
  2. #include    <errno.h>
  3. #include    <stdio.h>
  4. #include    "nels.h"
  5.  
  6. /*
  7.  * A unix process has a limited, usually small number of
  8.  * file descriptors available to it.
  9.  * A simulator for such a process which also uses file
  10.  * descriptors itself, must stop the simulated process
  11.  * from interfering with the simulator's file descriptors
  12.  * but otherwise maintain as normal a set of file descriptors
  13.  * for use by the process as possible.
  14.  * The routines in this file attempt to accomplish this.
  15.  */
  16.  
  17. #define    FD_CLOSED        ((fd_t)-1)
  18. #define    NFDOHEAD        2
  19.  
  20. #define    fd_valid_fd(fd)        ((fd) >= 0 && (fd) < nfiles)
  21.  
  22. typedef int            fd_t;
  23.  
  24. extern int            setobuf();
  25.  
  26. extern int            errno;
  27. extern FILE            *outfp;
  28.  
  29. static int            nfiles        = -1;
  30. static fd_t            *map;    /* map: simfd -> realfd    */
  31. static int            fdoverhead[NFDOHEAD];
  32.  
  33. int
  34. fd_hold()
  35. {
  36.     int    i;
  37.  
  38.     for (i = 0; i < nels(fdoverhead); i++)
  39.     {
  40.         if ((fdoverhead[i] = open("/dev/null", O_RDONLY)) == -1)
  41.         {
  42.             vcouldnot("open(\"/dev/null\", O_RDONLY)");
  43.             return -1;
  44.         }
  45.  
  46.         if (fcntl(fdoverhead[i], F_SETFD, 1) == -1)
  47.         {
  48.             vcouldnot("fcntl(%d, F_SETFD, 1)", fdoverhead[i]);
  49.             (void)close(fdoverhead[i]);
  50.             return -1;
  51.         }
  52.     }
  53.  
  54.     return 0;
  55. }
  56.  
  57. int
  58. fd_release()
  59. {
  60.     int    i;
  61.  
  62.     for (i = 0; i < nels(fdoverhead); i++)
  63.     {
  64.         if (fdoverhead[i] != -1)
  65.         {
  66.             (void)close(fdoverhead[i]);
  67.             fdoverhead[i] = -1;
  68.         }
  69.     }
  70.  
  71.     return 0;
  72. }
  73.  
  74. #if    0
  75. static
  76. void
  77. fd_dump()
  78. {
  79.     int    fd;
  80.  
  81.     fprintf(outfp, "map (%d):", fileno(outfp));
  82.     for (fd = 0; fd < nfiles; fd++)
  83.     {
  84.         if (map[fd] == FD_CLOSED)
  85.             continue;
  86.  
  87.         if (map[fd] == fd)
  88.             continue;
  89.  
  90.         fprintf(outfp, " %d->%d", fd, map[fd]);
  91.     }
  92.     fprintf(outfp, "\n");
  93.     fflush(outfp);
  94. }
  95. #endif    /* 0 */
  96.  
  97. /*
  98.  * Initialise our file descriptor map.
  99.  * We record all file descriptors that
  100.  * we have inherited at birth.
  101.  * fd_init() must be called before the
  102.  * simulator starts opening any files for its own
  103.  * internal use.
  104.  * 'outfd' != -1 iff the output file descriptor
  105.  * has been explicitly passed to us via a
  106.  * command line argument.
  107.  */
  108. int
  109. fd_init(outfd)
  110. int    outfd;
  111. {
  112.     int    fd;
  113.  
  114.     if ((nfiles = ulimit(4, 0)) == -1)
  115.     {
  116.         couldnot("get descriptor table size");
  117.         return -1;
  118.     }
  119.  
  120.     if ((map = (fd_t *)malloc(sizeof(fd_t) * nfiles)) == (fd_t *)0)
  121.     {
  122.         couldnot("allocate %d bytes for descriptor table map", sizeof(fd_t) * nfiles);
  123.         return -1;
  124.     }
  125.  
  126.     for (fd = 0; fd < nfiles; fd++)
  127.     {
  128.         if (fcntl(fd, F_GETFD, 0) == -1)
  129.         {
  130.             if (errno != EBADF)
  131.             {
  132.                 couldnot("interpret error returned by fcntl(%d, F_GETFD, ..)", fd);
  133.                 return -1;
  134.             }
  135.             errno = 0;
  136.  
  137.             map[fd] = FD_CLOSED;
  138.         }
  139.         else
  140.             map[fd] = fd;
  141.     }
  142.  
  143.     if (outfd != -1)
  144.         map[outfd] = FD_CLOSED;
  145.  
  146.     if (fd_hold() == -1)
  147.         return -1;
  148.  
  149.     return 0;
  150. }
  151.  
  152. int
  153. fd_sort()
  154. {
  155.     int    sim_outfd;
  156.     int    real_outfd;
  157.     int    fd;
  158.     fd_t    *rmap;
  159.  
  160. #if    0
  161.     fd_dump();
  162. #endif    /* 0 */
  163.  
  164.     if (fd_release() == -1)
  165.         return -1;
  166.  
  167.     if ((rmap = (fd_t *)malloc(sizeof(fd_t) * nfiles)) == (fd_t *)0)
  168.     {
  169.         vcouldnot("allocate %d bytes for reverse descriptor table map", sizeof(fd_t) * nfiles);
  170.         return -1;
  171.     }
  172.  
  173.     fflush(outfp);
  174.     if ((sim_outfd = fd_open(fileno(outfp))) == -1)
  175.         return -1;
  176.  
  177.     for (fd = 0; fd < nfiles; fd++)
  178.         rmap[fd] = FD_CLOSED;
  179.  
  180.     for (fd = 0; fd < nfiles; fd++)
  181.     {
  182.         if (map[fd] != FD_CLOSED)
  183.             rmap[map[fd]] = fd;
  184.     }
  185.  
  186.     for (fd = 0; fd < nfiles; fd++)
  187.     {
  188.         if (rmap[fd] == fd)
  189.             continue;
  190.  
  191.         if (rmap[fd] != FD_CLOSED)
  192.         {
  193.             int    newfd;
  194.  
  195.             if ((newfd = dup(fd)) == -1)
  196.             {
  197.                 vcouldnot("dup(%d)", fd);
  198.                 return -1;
  199.             }
  200.             rmap[newfd] = rmap[fd];
  201.             map[rmap[fd]] = newfd;
  202.             if (close(fd) == -1)
  203.             {
  204.                 vcouldnot("close(%d)", fd);
  205.                 return -1;
  206.             }
  207.             rmap[fd] = FD_CLOSED;
  208.         }
  209.  
  210.         if (map[fd] == FD_CLOSED)
  211.             continue;
  212.  
  213.         if (dup2(map[fd], fd) == -1)
  214.         {
  215.             vcouldnot("dup2(%d, %d)", map[fd], fd);
  216.             return -1;
  217.         }
  218.  
  219.         rmap[fd] = fd;
  220.         if (close(map[fd]) == -1)
  221.         {
  222.             vcouldnot("close(%d)", map[fd]);
  223.             return -1;
  224.         }
  225.         rmap[map[fd]] = FD_CLOSED;
  226.         map[fd] = fd;
  227.     }
  228.  
  229.     real_outfd = map[sim_outfd];
  230.  
  231.     if (real_outfd != fileno(outfp))
  232.     {
  233.         FILE    *newoutfp;
  234.  
  235.         if ((newoutfp = fdopen(real_outfd, "a")) == (FILE *)0)
  236.         {
  237.             vcouldnot("fdopen(%d, \"a\")", real_outfd);
  238.             return -1;
  239.         }
  240.         (void)fclose(outfp);
  241.         outfp = newoutfp;
  242.  
  243.         if (setobuf() == -1)
  244.             return -1;
  245.     }
  246.  
  247.     (void)fd_close(sim_outfd);
  248.  
  249.     (void)free((char *)rmap);
  250.  
  251.     if (fd_hold() == -1)
  252.         return -1;
  253.  
  254. #if    0
  255.     fd_dump();
  256. #endif    /* 0 */
  257.  
  258.     return 0;
  259. }
  260.  
  261. /*
  262.  * Given a good, real file descriptor,
  263.  * return a simulated file descriptor and
  264.  * mark it as allocated.
  265.  */
  266. int
  267. fd_open(real_fd)
  268. int    real_fd;
  269. {
  270.     int    sim_fd;
  271.  
  272.     for (sim_fd = 0; sim_fd < nfiles; sim_fd++)
  273.     {
  274.         if (map[sim_fd] == FD_CLOSED)
  275.         {
  276.             map[sim_fd] = real_fd;
  277.             return sim_fd;
  278.         }
  279.     }
  280.  
  281.     vcouldnot("open real file descriptor %d: internal error: ran out of simulated file descriptors", real_fd);
  282.     return -1;
  283. }
  284.  
  285. /*
  286.  * Given a good, real file descriptor,
  287.  * and an unallocated simulated file descriptor,
  288.  * mark it as allocated.
  289.  */
  290. void
  291. fd_dopen(real_fd, sim_fd)
  292. int    real_fd;
  293. int    sim_fd;
  294. {
  295.     map[sim_fd] = real_fd;
  296. }
  297.  
  298. /*
  299.  * Unmap a simulated file descriptor.
  300.  */
  301. int
  302. fd_close(sim_fd)
  303. int    sim_fd;
  304. {
  305.     if (fd_valid_fd(sim_fd))
  306.         map[sim_fd] = FD_CLOSED;
  307.  
  308.     return 0;
  309. }
  310.  
  311. /*
  312.  * Return the current mapping for a simulated
  313.  * file descriptor, or -1 if it is not mapped.
  314.  */
  315. int
  316. fd_lookup(sim_fd)
  317. int    sim_fd;
  318. {
  319.     if (fd_valid_fd(sim_fd) == 0)
  320.         return -1;
  321.  
  322.     if (map[sim_fd] == FD_CLOSED)
  323.         return -1;
  324.  
  325.     return map[sim_fd];
  326. }
  327.  
  328. int
  329. fd_invalid(sim_fd)
  330. int    sim_fd;
  331. {
  332.     if (fd_valid_fd(sim_fd))
  333.         return 0;
  334.  
  335.     errno = EBADF;
  336.  
  337.     return 1;
  338. }
  339.  
  340. int
  341. fd_nfiles()
  342. {
  343.     return nfiles;
  344. }
  345.