home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / gnu / libsrc87 / pipe.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-30  |  5.7 KB  |  166 lines

  1. #include <fcntl.h>
  2. #include <stat.h>
  3. #include <types.h>
  4. #include <errno.h>
  5. #include <stdlib.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #define __MINT__
  9. #include <mintbind.h>
  10.  
  11.  
  12. extern int __mint;
  13.  
  14. #if defined(DEBUG)
  15. #  include <stdio.h>
  16. #endif
  17.  
  18. #ifndef _COMPILER_H
  19. #  include <compiler.h>
  20. #endif
  21. __EXTERN char *tmpnam __PROTO((char *buf));
  22.  
  23. /**
  24.  ** (sjk)++ These routines simulate a eunchs pipe() call using temporary 
  25.  **         files. A linked list of type *_pipe is kept as to allow as 
  26.  **         many open pipes as there are valid file descriptors. The only 
  27.  **         problem is that the pipe is initiallialy opened for writing, 
  28.  **         and all output must be done to the pipe, then call pipeclose(fd);
  29.  **         and it sets up the pipe for reading. After all input is done, 
  30.  **         call pipeclose(fd) again and this will close the pipe and delete
  31.  **         the temporary file that the pipe created.
  32.  **    
  33.  **/
  34.  
  35. struct _pipe { char p_name[40];
  36.            char flag;               /* "r"-->read, "w"-->write */
  37.            int  file_des;
  38.            struct _pipe *next;
  39.              };
  40. static struct _pipe *__pipes = NULL;
  41. static int del_list (struct _pipe *);
  42.  
  43. __EXTERN int pipeclose __PROTO((int fd));
  44. extern int (*pipeclose_p) __PROTO((int fd));
  45.  
  46. /*---------------------------------------------------------------------------*/
  47. /* Make a pipe, open the tempory file, set it up for writing, add the pipe   */
  48. /* descriptor to our linked list of pipes, and return.                       */
  49. /*---------------------------------------------------------------------------*/
  50. int pipe(fildes)
  51. int fildes[2];
  52. { int       fd; 
  53.   char name[40];
  54.   struct _pipe *p;
  55.  
  56.   tmpnam(name);                              /* Make a temporary file name. */
  57.   
  58.   /*----------------------------------------------*/
  59.   /* Open the pipe for reading and writing.       */
  60.   /*----------------------------------------------*/
  61.   fd = open(name,O_CREAT | O_TRUNC | O_RDWR | O_PIPE, 0644); 
  62.  
  63. #if defined(DEBUG)
  64.   fprintf(stderr,"opened pipe - fd : %d.\n",fd);
  65. #endif
  66.  
  67.   if (fd < 0)
  68. #if defined(DEBUG)
  69.     fprintf(stderr,"fd returns : %d! PIPE(%s) failed.\n",fd, name);
  70. #else
  71.     /* nothing */;
  72. #endif
  73.   else 
  74.     { /*------------------------------------------*/
  75.       /* Get a pipe description block and         */
  76.       /* put in the (1)file name,                 */
  77.       /*            (2)file descriptor,           */
  78.       /*            (3)file mode = "w".           */
  79.       /*------------------------------------------*/
  80.       /*-------------------------------------------------------------------*/
  81.       p = (struct _pipe *)malloc(sizeof (struct _pipe)); 
  82.       strcpy(p->p_name,name);           /* fill in name.                   */  
  83.       p->flag = 'w';                    /* initially for write.            */
  84.       p->file_des = fd;                 /* fill in the pipe descriptor.    */
  85.       if(!__pipes)
  86.     pipeclose_p = pipeclose;    /* patch in addr of close routine  */
  87.       /*-------------------------------------------------------------------*/
  88.       p->next = __pipes;                /* Link to our list of open pipes. */
  89.       __pipes     = p;
  90.       /*-------------------------------------------------------------------*/ 
  91.       fildes[0] = fildes[1] = fd;       /* we fill in fildes[].            */
  92.       if (__mint)
  93.     (void) Fcntl(fd,0L,2);          /* Make fd shared across Pexecs()  */
  94.     }
  95.   return(fd);                           /* Return the file descriptor.     */
  96. }
  97.  
  98. /*---------------------------------------------------------------------*/
  99. /* close a pipe, if the pipe was open for writing, set it to a read    */
  100. /* read pipe, and lseek to the begining of the pipe. if it was open    */
  101. /* for reading then close the pipe, delete the temporary file, and     */
  102. /* remove the pipe descriptor from the __pipes linked list.            */
  103. /*---------------------------------------------------------------------*/
  104. int
  105. pipeclose(fd)
  106. int fd;
  107. {  struct _pipe *p;
  108.    int    ifd;
  109.    for (p=__pipes; p; p=p->next)
  110.     { if (fd == p->file_des) 
  111.        { 
  112. #if defined(DEBUG)
  113.         fprintf(stderr,"Deleting pipe - mode : %c, fd : %d\n",p->flag,fd);
  114. #endif
  115.         if (p->flag == 'r') 
  116.       { int res;
  117.         ifd = __OPEN_INDEX(fd);
  118.             __open_stat[ifd].pipe = 0;            /* So close wont recurse */
  119.         res = close(fd);
  120.         unlink(p->p_name);                     /* Delete it.            */
  121.             del_list(p);                           /* delete from the list. */
  122.             return(res);                               
  123.           }
  124.         else 
  125.         if (p->flag =='w')
  126.           { p->flag = 'r';                         /* now make it read.     */
  127.             lseek(p->file_des,0,SEEK_SET);         /* read from the start.  */
  128.             return(0);
  129.           }
  130.       }
  131.     }
  132. #if defined(DEBUG)
  133.    fprintf(stderr,"attempt to close nonexistant pipe.\n");
  134. #endif
  135.    return(-1);
  136. }
  137.  
  138. /*---------------------------------------------------------------------*/
  139. /* delete a pipe descriptor from our list of pipes rooted ar __pipes.  */
  140. /*---------------------------------------------------------------------*/
  141. static int del_list(p)
  142. struct _pipe *p;
  143. { struct _pipe *q,*r;
  144.   
  145.   if (p == __pipes)                      /* Is it the first element?    */
  146.     { __pipes = p->next; 
  147.       free(p);
  148.       return(0);
  149.     }
  150.   else 
  151.     { r = __pipes->next; q = __pipes;    /* No it is interior.           */
  152.       for (; r; r = r->next)
  153.         { if (r == p)
  154.            { q->next = r->next;              /* pass over it.   */
  155.              free(r);                        /* free its space. */
  156.              return(0);                      /* go home.        */
  157.        }
  158.           q = r;                        /* update trailing pointer.    */
  159.     }
  160.     }
  161. #if defined(DEBUG)
  162.   fprintf(stderr,"Attempt to delete a nonexisting pipe form list (__pipes).");
  163. #endif
  164.   return(-1);
  165. }
  166.