home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / PL4019AS.ZIP / POPEN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-30  |  4.2 KB  |  220 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. /*
  28.  * Popen and pclose for MS-DOS
  29.  */
  30.  
  31.  
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <dir.h>
  35. #include <process.h>
  36.  
  37.  
  38. /*
  39.  * Possible actions on an popened file
  40.  */
  41. enum action {
  42.     delete,             /* Used for "r". Delete the tmp file */
  43.     execute                /* Used for "w". Execute the command. */
  44. };
  45.  
  46.  
  47. /*
  48.  * Linked list of things to do at the end of the program execution.
  49.  */
  50. struct todo {
  51.     FILE *f;            /* File we are working on (to fclose) */
  52.     const char *name;        /* Name of the file (to unlink) */
  53.     const char *command;        /* Command to execute */
  54.     enum action what;        /* What to do (execute or delete) */
  55.     struct todo *next;        /* Next structure */
  56. } *todolist;
  57.  
  58.  
  59.  
  60.  
  61. /* Clean up function */
  62. static int close_pipes(void);
  63.  
  64.  
  65. /*
  66.  * Add a file f running the command command on file name to the list
  67.  * of actions to be done at the end.  The action is specified in what.
  68.  * Return -1 on failure, 0 if ok.
  69.  */
  70. static int
  71. add(FILE *f, const char *command, const char *name, enum action what)
  72. {
  73.     struct todo    *p;
  74.  
  75.  
  76.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  77.         return -1;
  78.     p->f = f;
  79.     p->command = command;
  80.     p->name = name;
  81.     p->what = what;
  82.     p->next = todolist;
  83.     todolist = p;
  84.     return 0;
  85. }
  86.  
  87.  
  88. FILE *
  89. mypopen(const char *command, const char *t)
  90. {
  91.     char buff[128];
  92.     char fname[8];
  93.     char *tpath;
  94.     char *name, *tmp_path;
  95.     char sep = '\\';
  96.     FILE *f;
  97.     static init = 0;
  98.  
  99.  
  100.     if (!init)
  101.         if (atexit((void (*)())close_pipes) != 0)
  102.             return NULL;
  103.         else
  104.             init++;
  105.  
  106.     strcpy(fname,"PXXXXXX");
  107.     
  108.     if ((name = mktemp(fname)) == NULL)
  109.         return NULL;
  110.  
  111.     if ((tpath = malloc(64)) == NULL)
  112.         return NULL;
  113.  
  114.     if ((tmp_path = getenv("TMP")) != NULL) {
  115.         if (strchr(tmp_path,'/') != NULL)
  116.             sep = '/';
  117.         else
  118.             sep = '\\';
  119.         sprintf(tpath, "%s%c%s", tmp_path, sep, name);
  120.     } else
  121.         sprintf(tpath, "%s", name);
  122.  
  123.     name = tpath;
  124.  
  125.  
  126.     switch (*t) {
  127.     case 'r':
  128.         sprintf(buff, "%s >%s", command, name);
  129.         if (xsystem(buff) || (f = fopen(name, "r")) == NULL) {
  130.             free(name);
  131.             return NULL;
  132.         }
  133.         if (add(f, command, name, delete)) {
  134.             (void)fclose(f);
  135.             (void)unlink(name);
  136.             free(name);
  137.             return NULL;
  138.         }
  139.         return f;
  140.     case 'w':
  141.         if ((f = fopen(name, "w")) == NULL) {
  142.             free(name);
  143.             return NULL;
  144.         }
  145.         if (add(f, command, name, execute)) {
  146.             (void)fclose(f);
  147.             (void)unlink(name);
  148.             free(name);
  149.             return NULL;
  150.         }
  151.         return f;
  152.     default:
  153.         free(name);
  154.         return NULL;
  155.     }
  156. }
  157.  
  158.  
  159. int
  160. mypclose(FILE *f)
  161. {
  162.     struct todo *p, **prev;
  163.     char buff[256];
  164.     const char *name;
  165.     int status;
  166.  
  167.  
  168.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  169.         if (p->f == f) {
  170.             *prev = p->next;
  171.             name = p->name;
  172.             switch (p->what) {
  173.             case delete:
  174.                 free(p);
  175.                 if (fclose(f) == EOF) {
  176.                     (void)unlink(name);
  177.                     status = EOF;
  178.                 } else if (unlink(name) < 0)
  179.                     status = EOF;
  180.                 else
  181.                     status = 0;
  182.                 free((void*)name);
  183.                 return status;
  184.             case execute:
  185.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  186.                 free(p);
  187.                 if (fclose(f) == EOF) {
  188.                     (void)unlink(name);
  189.                     status = EOF;
  190.                 } else if (xsystem(buff)) {
  191.                     (void)unlink(name);
  192.                     status = EOF;
  193.                 } else if (unlink(name) < 0)
  194.                     status = EOF;
  195.                 else
  196.                     status = 0;
  197.                 free((void*)name);
  198.                 return status;
  199.             default:
  200.                 return EOF;
  201.             }
  202.         }
  203.     return EOF;
  204. }
  205.  
  206.  
  207. /*
  208.  * Clean up at the end.  Called by the onexit handler.
  209.  */
  210. static int
  211. close_pipes(void)
  212. {
  213.     struct todo    *p;
  214.  
  215.  
  216.     for (p = todolist; p; p = p->next)
  217.         (void)mypclose(p->f);
  218.     return 0;
  219. }
  220.