home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mntlib25.zoo / popen.c < prev    next >
C/C++ Source or Header  |  1991-10-20  |  3KB  |  115 lines

  1. /* popen(): open a file handle to a process. Works only under MiNT.
  2.  * Written by Eric R. Smith, based on the TOS version by Kai-Uwe Bloem.
  3.  */
  4.  
  5. #include    <stdio.h>
  6. #include    <stdlib.h>
  7. #include    <process.h>
  8. #include    <fcntl.h>
  9. #include    <string.h>
  10. #include    <errno.h>
  11. #include    <unistd.h>
  12.  
  13. __EXTERN int wait __PROTO((int *));
  14.  
  15. struct _pipe {
  16.     int    pid;        /* process id of child            */
  17.     FILE    *pfile;        /* created file descriptor        */
  18.     struct _pipe    *pnext;    /* next pipe in the list.        */
  19. };
  20.  
  21. static struct _pipe    *__pipes = NULL;    /* head of pipe list    */
  22.  
  23. FILE *popen(command, type)
  24. const char    *command, *type;
  25. {
  26.     struct _pipe *p;    /* the new pipe's list entry    */
  27.     int pipfd[2];        /* pipe file handles */
  28.     int savefd;        /* saved file descriptor for parent */
  29.     int kidfd;        /* file descriptor changed in child */
  30.                 /* 1 for "r", 0 for "w" */    
  31.  
  32.     char *shell;
  33.     FILE *pipefile = 0;
  34.     extern int __mint;
  35.  
  36.     if (__mint == 0) {
  37.         errno = EINVAL;
  38.         return (FILE *)0;
  39.     }
  40.  
  41.     shell = getenv("SHELL");
  42.     if (!shell)
  43.         shell = "sh";
  44.  
  45.     /* get space for the new pipe. If we can't get it then that's that */
  46.     p = (struct _pipe *) malloc(sizeof(struct _pipe));
  47.     if (p == NULL) return (FILE *)0;
  48.  
  49.     /* initialize the new pipe entry */
  50.     kidfd = (*type == 'r') ? 1 : 0;
  51.  
  52.     savefd = dup(kidfd);
  53.  
  54.     if (savefd < 0 || pipe(pipfd) != 0) {    /* can't create pipe?? */
  55.         free(p);
  56.         return (FILE *)0;
  57.     }
  58.  
  59.     dup2(pipfd[kidfd], kidfd);
  60.     close(pipfd[kidfd]);
  61.     p->pid = spawnlp(P_NOWAIT, shell, shell, "-c", command, (char *)0);
  62.     dup2(savefd, kidfd);
  63.     close(savefd);
  64.  
  65.     if (p->pid > 0) {    /* command ran all right */
  66.     /* note: 1-kidfd tells us which handle to use in the parent */
  67.         pipefile = fdopen(pipfd[1 - kidfd], type);
  68.     }
  69.  
  70.     if (pipefile) {
  71.         p->pfile = pipefile;
  72.         p->pnext = __pipes;
  73.         __pipes = p;
  74.     }
  75.     else {
  76.         free(p);
  77.     }
  78.     return pipefile;
  79. }
  80.  
  81. /* close a pipe created by popen().
  82.  */
  83. int pclose(fp)
  84. FILE    *fp;
  85. {
  86.     struct _pipe    *p,        /* the pipe's list element    */
  87.             *q;        /* predecessor of p in the list    */
  88.     int    status = -1;        /* return status of the command    */
  89.     int    pid;
  90.  
  91.     /* search the pipe list for a pipe matching the FILE descriptor    */
  92.     for (p = __pipes, q = NULL;  p && p->pfile != fp;  q = p, p = p->pnext);
  93.     if (p == NULL)        /* Never had a popen() for this file...    */
  94.         return status;    /* this pclose call makes no sense !    */
  95.  
  96.     fclose(p->pfile);    /* close the connection        */
  97.  
  98. /* now wait for the command to finish */
  99.  
  100.     do {
  101.         pid = wait(&status);
  102.     } while (pid >= 0 && pid != p->pid);
  103.  
  104.     /* remove the pipe from the list */
  105.     if (q)    /* not the first in the list, unlink it from previous pipe */
  106.         q->pnext = p->pnext;
  107.     else    /* first in the list, set new list head    */
  108.         __pipes = __pipes->pnext;
  109.  
  110.     /* Now free the pipe entry */
  111.     free(p);
  112.  
  113.     return status;
  114. }
  115.