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

  1. /* popen.c
  2.  *
  3.  * Implementation of popen() / pclose for Atari ST (will eventually work for
  4.  * MSDOS too). The pipe is simulated by a temporary file. If caller wants to
  5.  * read the pipe, then execute the command in popen and return a descriptor
  6.  * to the output delivered by the command. If caller wants to write to the
  7.  * pipe, then preserve the callers output in a temp file and execute the
  8.  * command on pclose.
  9.  * Since it is necessary to keep some information from popen() up to the
  10.  * pclose(), we keep all opened pipes in a list and fill up the entries as
  11.  * needed. Pipes are identified by their FILE descriptor returned from the
  12.  * fopen() call.
  13.  *
  14.  * Revision 1.2, jrb 08-15-89    applied kai's diffs
  15.  *    gcc-lib's system() now does re-direction. Changes to
  16.  *    for re-direction stuff because of this.
  17.  *
  18.  * Revision 1.1, kub 05-23-89
  19.  * written 89/05/23 by Kai-Uwe Bloem (I5110401@DBSTU1.BITNET for now)
  20.  */
  21.  
  22. #include    <stdio.h>
  23. #include    <memory.h>
  24. #include    <fcntl.h>
  25. #include    <string.h>
  26. #include    <unistd.h>
  27.  
  28. struct _pipe {
  29.     char    pmode;        /* "r" or "w" to/from the pipe ?    */
  30.     char    *pcommand;    /* cmd to execute (only for "w")    */
  31.     int    pstat;        /* exit code of cmd (only for "r")    */
  32.     char    pname[32];    /* temp filename. 32 should be enough...*/
  33.     FILE    *pfile;        /* pipe identifier            */
  34.     struct _pipe    *pnext;    /* next pipe in the list.        */
  35.     };
  36.  
  37. static struct _pipe    *__pipes = NULL;    /* head of pipe list    */
  38.  
  39. /* open a pipe to the command argument in the mode given by the type string.
  40.  * If caller wants to read the pipe, redirect output and execute command,
  41.  * then open the temp file and return that. If caller wants to write to
  42.  * the pipe, create the temp file and return that.
  43.  */
  44. FILE *popen(command, type)
  45. const char    *command, *type;
  46. {
  47.     struct _pipe *p;    /* the new pipe's list entry    */
  48.  
  49.     /* get space for the new pipe. If we can't get it then that's that */
  50.     p = (struct _pipe *) malloc(sizeof(struct _pipe));
  51.     if (p == NULL) return (FILE *) NULL;
  52.  
  53.     /* initialize the new pipe entry */
  54.     p->pmode = *type;
  55.     p->pfile = (FILE *) NULL;
  56.     (void)tmpnam(p->pname);
  57.     /* make command line with appropriate re-direction */
  58.     if((p->pcommand = (char *)malloc(strlen(command)+strlen(p->pname)+4L))
  59.         == (char *)NULL)
  60.     {    /* no  mem */
  61.         free(p);
  62.         return (FILE *)NULL;
  63.     }
  64.     strcpy(p->pcommand, command);
  65.     strcat(p->pcommand, (p->pmode == 'r')? " >" : " <");
  66.     strcat(p->pcommand, p->pname);
  67.  
  68.     /* Everything has now been set up to really execute the pipe request */
  69.     switch(p->pmode)
  70.     {
  71.     case 'r':    /* reading */
  72.         /* execute the command, output redir. to tmp pipe file */
  73.         p->pstat = system(p->pcommand);
  74.         if (p->pstat < 0) {
  75.             unlink(p->pname);
  76.             return (FILE *)NULL;
  77.         }
  78.         p->pfile = fopen(p->pname,"r");    /* now open the pipe    */
  79.         break;
  80.     case 'w':    /* writing */
  81.         /* open tmp pipe file */
  82.         p->pfile = fopen(p->pname,"w"); /* open the pipe file    */
  83.         break;
  84.     }
  85.  
  86.     if (p->pfile)
  87.     {    /* pipe successfully established. Link it to the list    */
  88.         p->pnext = __pipes;
  89.         __pipes = p;
  90.         return p->pfile;
  91.     }
  92.     else
  93.     {    /* if there is no pipe identifier then throw it away    */
  94.         unlink(p->pname);
  95.         free(p->pcommand);
  96.         free(p);
  97.         return (FILE *) NULL;
  98.     }
  99. }
  100.  
  101. /* close a pipe created by popen(). If caller wanted to read the pipe, then
  102.  * just do the cleanup and return the command's status code. If caller wanted
  103.  * to write to the pipe, the work has just started. Close the tempfile, call
  104.  * the command with input redirected to the temp file and cleanup after that.
  105.  */
  106. int pclose(fp)
  107. FILE    *fp;
  108. {
  109.     struct _pipe    *p,        /* the pipe's list element    */
  110.             *q;        /* predecessor of p in the list    */
  111.     int    status = -1;        /* return status of the command    */
  112.  
  113.     /* search the pipe list for a pipe matching the FILE descriptor    */
  114.     for (p = __pipes, q = NULL;  p && p->pfile != fp;  q = p, p = p->pnext);
  115.     if (p == NULL)        /* Never had a popen() for this file...    */
  116.         return status;    /* this pclose call makes no sense !    */
  117.  
  118.     fclose(p->pfile);        /* close temp file        */
  119.     switch(p->pmode)
  120.     {
  121.     case 'w':    /* writing */
  122.         status = system(p->pcommand);    /* execute the command    */
  123.         break;
  124.     case 'r':    /* reading */
  125.         status = p->pstat;    /* just get status code        */
  126.         break;
  127.     }
  128.     unlink(p->pname);        /* temp file no longer needed    */
  129.  
  130.     /* remove the pipe from the list */
  131.     if (q)    /* not the first in the list, unlink it from previous pipe */
  132.         q->pnext = p->pnext;
  133.     else    /* first in the list, set new list head    */
  134.         __pipes = __pipes->pnext;
  135.  
  136.     /* Now free the pipe entry */
  137.     free(p->pcommand);
  138.     free(p);
  139.  
  140.     return status;
  141. }
  142.