home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / gnustuff / tos / gnulib / libsrc98.zoo / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-01  |  4.4 KB  |  143 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. #include    "lib.h"
  28.  
  29. struct _pipe {
  30.     char    pmode;        /* "r" or "w" to/from the pipe ?    */
  31.     char    *pcommand;    /* cmd to execute (only for "w")    */
  32.     int    pstat;        /* exit code of cmd (only for "r")    */
  33.     char    pname[32];    /* temp filename. 32 should be enough...*/
  34.     FILE    *pfile;        /* pipe identifier            */
  35.     struct _pipe    *pnext;    /* next pipe in the list.        */
  36.     };
  37.  
  38. static struct _pipe    *__pipes = NULL;    /* head of pipe list    */
  39.  
  40. /* open a pipe to the command argument in the mode given by the type string.
  41.  * If caller wants to read the pipe, redirect output and execute command,
  42.  * then open the temp file and return that. If caller wants to write to
  43.  * the pipe, create the temp file and return that.
  44.  */
  45. FILE *popen(command, type)
  46. const char    *command, *type;
  47. {
  48.     struct _pipe *p;    /* the new pipe's list entry    */
  49.  
  50.     /* get space for the new pipe. If we can't get it then that's that */
  51.     p = (struct _pipe *) malloc(sizeof(struct _pipe));
  52.     if (p == NULL) return (FILE *) NULL;
  53.  
  54.     /* initialize the new pipe entry */
  55.     p->pmode = *type;
  56.     p->pfile = (FILE *) NULL;
  57.     (void)tmpnam(p->pname);
  58.     /* make command line with appropriate re-direction */
  59.     if((p->pcommand = (char *)malloc(strlen(command)+strlen(p->pname)+4L))
  60.         == (char *)NULL)
  61.     {    /* no  mem */
  62.         free(p);
  63.         return (FILE *)NULL;
  64.     }
  65.     strcpy(p->pcommand, command);
  66.     strcat(p->pcommand, (p->pmode == 'r')? " >" : " <");
  67.     strcat(p->pcommand, p->pname);
  68.  
  69.     /* Everything has now been set up to really execute the pipe request */
  70.     switch(p->pmode)
  71.     {
  72.     case 'r':    /* reading */
  73.         /* execute the command, output redir. to tmp pipe file */
  74.         p->pstat = system(p->pcommand);
  75.         if (p->pstat < 0) {
  76.             unlink(p->pname);
  77.             return (FILE *)NULL;
  78.         }
  79.         p->pfile = fopen(p->pname,"r");    /* now open the pipe    */
  80.         break;
  81.     case 'w':    /* writing */
  82.         /* open tmp pipe file */
  83.         p->pfile = fopen(p->pname,"w"); /* open the pipe file    */
  84.         break;
  85.     }
  86.  
  87.     if (p->pfile)
  88.     {    /* pipe successfully established. Link it to the list    */
  89.         p->pnext = __pipes;
  90.         __pipes = p;
  91.         return p->pfile;
  92.     }
  93.     else
  94.     {    /* if there is no pipe identifier then throw it away    */
  95.         unlink(p->pname);
  96.         free(p->pcommand);
  97.         free(p);
  98.         return (FILE *) NULL;
  99.     }
  100. }
  101.  
  102. /* close a pipe created by popen(). If caller wanted to read the pipe, then
  103.  * just do the cleanup and return the command's status code. If caller wanted
  104.  * to write to the pipe, the work has just started. Close the tempfile, call
  105.  * the command with input redirected to the temp file and cleanup after that.
  106.  */
  107. int pclose(fp)
  108. FILE    *fp;
  109. {
  110.     struct _pipe    *p,        /* the pipe's list element    */
  111.             *q;        /* predecessor of p in the list    */
  112.     int    status = -1;        /* return status of the command    */
  113.  
  114.     /* search the pipe list for a pipe matching the FILE descriptor    */
  115.     for (p = __pipes, q = NULL;  p && p->pfile != fp;  q = p, p = p->pnext);
  116.     if (p == NULL)        /* Never had a popen() for this file...    */
  117.         return status;    /* this pclose call makes no sense !    */
  118.  
  119.     fclose(p->pfile);        /* close temp file        */
  120.     switch(p->pmode)
  121.     {
  122.     case 'w':    /* writing */
  123.         status = system(p->pcommand);    /* execute the command    */
  124.         break;
  125.     case 'r':    /* reading */
  126.         status = p->pstat;    /* just get status code        */
  127.         break;
  128.     }
  129.     unlink(p->pname);        /* temp file no longer needed    */
  130.  
  131.     /* remove the pipe from the list */
  132.     if (q)    /* not the first in the list, unlink it from previous pipe */
  133.         q->pnext = p->pnext;
  134.     else    /* first in the list, set new list head    */
  135.         __pipes = __pipes->pnext;
  136.  
  137.     /* Now free the pipe entry */
  138.     free(p->pcommand);
  139.     free(p);
  140.  
  141.     return status;
  142. }
  143.