home *** CD-ROM | disk | FTP | other *** search
/ ftp.muug.mb.ca / 2014.06.ftp.muug.mb.ca.tar / ftp.muug.mb.ca / pub / src / perl / msdos / popen.c < prev    next >
C/C++ Source or Header  |  1992-04-11  |  4KB  |  185 lines

  1. /* $RCSfile: popen.c,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:52 $
  2.  *
  3.  *    (C) Copyright 1988, 1990 Diomidis Spinellis.
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    popen.c,v $
  9.  * Revision 4.0.1.1  91/06/07  11:22:52  lwall
  10.  * patch4: new copyright notice
  11.  * 
  12.  * Revision 4.0  91/03/20  01:34:50  lwall
  13.  * 4.0 baseline.
  14.  * 
  15.  * Revision 3.0.1.2  90/08/09  04:04:42  lwall
  16.  * patch19: various MSDOS and OS/2 patches folded in
  17.  * 
  18.  * Revision 3.0.1.1  90/03/27  16:11:57  lwall
  19.  * patch16: MSDOS support
  20.  * 
  21.  * Revision 1.1  90/03/18  20:32:20  dds
  22.  * Initial revision
  23.  *
  24.  */
  25.  
  26. /*
  27.  * Popen and pclose for MS-DOS
  28.  */
  29.  
  30. #include <stdlib.h>
  31. #include <stdio.h>
  32. #include <process.h>
  33.  
  34. /*
  35.  * Possible actions on an popened file
  36.  */
  37. enum action {
  38.     delete,             /* Used for "r". Delete the tmp file */
  39.     execute                /* Used for "w". Execute the command. */
  40. };
  41.  
  42. /*
  43.  * Linked list of things to do at the end of the program execution.
  44.  */
  45. static struct todo {
  46.     FILE *f;            /* File we are working on (to fclose) */
  47.     const char *name;        /* Name of the file (to unlink) */
  48.     const char *command;        /* Command to execute */
  49.     enum action what;        /* What to do (execute or delete) */
  50.     struct todo *next;        /* Next structure */
  51. } *todolist;
  52.  
  53.  
  54. /* Clean up function */
  55. static int close_pipes(void);
  56.  
  57. /*
  58.  * Add a file f running the command command on file name to the list
  59.  * of actions to be done at the end.  The action is specified in what.
  60.  * Return -1 on failure, 0 if ok.
  61.  */
  62. static int
  63. add(FILE *f, const char *command, const char *name, enum action what)
  64. {
  65.     struct todo    *p;
  66.  
  67.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  68.         return -1;
  69.     p->f = f;
  70.     p->command = command;
  71.     p->name = name;
  72.     p->what = what;
  73.     p->next = todolist;
  74.     todolist = p;
  75.     return 0;
  76. }
  77.  
  78. FILE *
  79. mypopen(const char *command, const char *t)
  80. {
  81.     char buff[256];
  82.     char *name;
  83.     FILE *f;
  84.     static init = 0;
  85.  
  86.     if (!init)
  87.         if (onexit(close_pipes) == NULL)
  88.             return NULL;
  89.         else
  90.             init++;
  91.  
  92.     if ((name = tempnam((char*)NULL, "pp")) == NULL)
  93.         return NULL;
  94.  
  95.     switch (*t) {
  96.     case 'r':
  97.         sprintf(buff, "%s >%s", command, name);
  98.         if (system(buff) || (f = fopen(name, "r")) == NULL) {
  99.             free(name);
  100.             return NULL;
  101.         }
  102.         if (add(f, command, name, delete)) {
  103.             (void)fclose(f);
  104.             (void)unlink(name);
  105.             free(name);
  106.             return NULL;
  107.         }
  108.         return f;
  109.     case 'w':
  110.         if ((f = fopen(name, "w")) == NULL) {
  111.             free(name);
  112.             return NULL;
  113.         }
  114.         if (add(f, command, name, execute)) {
  115.             (void)fclose(f);
  116.             (void)unlink(name);
  117.             free(name);
  118.             return NULL;
  119.         }
  120.         return f;
  121.     default:
  122.         free(name);
  123.         return NULL;
  124.     }
  125. }
  126.  
  127. int
  128. mypclose(FILE *f)
  129. {
  130.     struct todo *p, **prev;
  131.     char buff[256];
  132.     const char *name;
  133.     int status;
  134.  
  135.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  136.         if (p->f == f) {
  137.             *prev = p->next;
  138.             name = p->name;
  139.             switch (p->what) {
  140.             case delete:
  141.                 free(p);
  142.                 if (fclose(f) == EOF) {
  143.                     (void)unlink(name);
  144.                     status = EOF;
  145.                 } else if (unlink(name) < 0)
  146.                     status = EOF;
  147.                 else
  148.                     status = 0;
  149.                 free((void*)name);
  150.                 return status;
  151.             case execute:
  152.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  153.                 free(p);
  154.                 if (fclose(f) == EOF) {
  155.                     (void)unlink(name);
  156.                     status = EOF;
  157.                 } else if (system(buff)) {
  158.                     (void)unlink(name);
  159.                     status = EOF;
  160.                 } else if (unlink(name) < 0)
  161.                     status = EOF;
  162.                 else
  163.                     status = 0;
  164.                 free((void*)name);
  165.                 return status;
  166.             default:
  167.                 return EOF;
  168.             }
  169.         }
  170.     return EOF;
  171. }
  172.  
  173. /*
  174.  * Clean up at the end.  Called by the onexit handler.
  175.  */
  176. static int
  177. close_pipes(void)
  178. {
  179.     struct todo    *p;
  180.  
  181.     for (p = todolist; p; p = p->next)
  182.         (void)mypclose(p->f);
  183.     return 0;
  184. }
  185.