#include #include #include #include #include #include #include #define __MINT__ #include extern int __mint; #if defined(DEBUG) # include #endif #ifndef _COMPILER_H # include #endif __EXTERN char *tmpnam __PROTO((char *buf)); /** ** (sjk)++ These routines simulate a eunchs pipe() call using temporary ** files. A linked list of type *_pipe is kept as to allow as ** many open pipes as there are valid file descriptors. The only ** problem is that the pipe is initiallialy opened for writing, ** and all output must be done to the pipe, then call pipeclose(fd); ** and it sets up the pipe for reading. After all input is done, ** call pipeclose(fd) again and this will close the pipe and delete ** the temporary file that the pipe created. ** **/ struct _pipe { char p_name[40]; char flag; /* "r"-->read, "w"-->write */ int file_des; struct _pipe *next; }; static struct _pipe *__pipes = NULL; static int del_list (struct _pipe *); __EXTERN int pipeclose __PROTO((int fd)); extern int (*pipeclose_p) __PROTO((int fd)); /*---------------------------------------------------------------------------*/ /* Make a pipe, open the tempory file, set it up for writing, add the pipe */ /* descriptor to our linked list of pipes, and return. */ /*---------------------------------------------------------------------------*/ int pipe(fildes) int fildes[2]; { int fd; char name[40]; struct _pipe *p; tmpnam(name); /* Make a temporary file name. */ /*----------------------------------------------*/ /* Open the pipe for reading and writing. */ /*----------------------------------------------*/ fd = open(name,O_CREAT | O_TRUNC | O_RDWR | O_PIPE, 0644); #if defined(DEBUG) fprintf(stderr,"opened pipe - fd : %d.\n",fd); #endif if (fd < 0) #if defined(DEBUG) fprintf(stderr,"fd returns : %d! PIPE(%s) failed.\n",fd, name); #else /* nothing */; #endif else { /*------------------------------------------*/ /* Get a pipe description block and */ /* put in the (1)file name, */ /* (2)file descriptor, */ /* (3)file mode = "w". */ /*------------------------------------------*/ /*-------------------------------------------------------------------*/ p = (struct _pipe *)malloc(sizeof (struct _pipe)); strcpy(p->p_name,name); /* fill in name. */ p->flag = 'w'; /* initially for write. */ p->file_des = fd; /* fill in the pipe descriptor. */ if(!__pipes) pipeclose_p = pipeclose; /* patch in addr of close routine */ /*-------------------------------------------------------------------*/ p->next = __pipes; /* Link to our list of open pipes. */ __pipes = p; /*-------------------------------------------------------------------*/ fildes[0] = fildes[1] = fd; /* we fill in fildes[]. */ if (__mint) (void) Fcntl(fd,0L,2); /* Make fd shared across Pexecs() */ } return(fd); /* Return the file descriptor. */ } /*---------------------------------------------------------------------*/ /* close a pipe, if the pipe was open for writing, set it to a read */ /* read pipe, and lseek to the begining of the pipe. if it was open */ /* for reading then close the pipe, delete the temporary file, and */ /* remove the pipe descriptor from the __pipes linked list. */ /*---------------------------------------------------------------------*/ int pipeclose(fd) int fd; { struct _pipe *p; int ifd; for (p=__pipes; p; p=p->next) { if (fd == p->file_des) { #if defined(DEBUG) fprintf(stderr,"Deleting pipe - mode : %c, fd : %d\n",p->flag,fd); #endif if (p->flag == 'r') { int res; ifd = __OPEN_INDEX(fd); __open_stat[ifd].pipe = 0; /* So close wont recurse */ res = close(fd); unlink(p->p_name); /* Delete it. */ del_list(p); /* delete from the list. */ return(res); } else if (p->flag =='w') { p->flag = 'r'; /* now make it read. */ lseek(p->file_des,0,SEEK_SET); /* read from the start. */ return(0); } } } #if defined(DEBUG) fprintf(stderr,"attempt to close nonexistant pipe.\n"); #endif return(-1); } /*---------------------------------------------------------------------*/ /* delete a pipe descriptor from our list of pipes rooted ar __pipes. */ /*---------------------------------------------------------------------*/ static int del_list(p) struct _pipe *p; { struct _pipe *q,*r; if (p == __pipes) /* Is it the first element? */ { __pipes = p->next; free(p); return(0); } else { r = __pipes->next; q = __pipes; /* No it is interior. */ for (; r; r = r->next) { if (r == p) { q->next = r->next; /* pass over it. */ free(r); /* free its space. */ return(0); /* go home. */ } q = r; /* update trailing pointer. */ } } #if defined(DEBUG) fprintf(stderr,"Attempt to delete a nonexisting pipe form list (__pipes)."); #endif return(-1); }