home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / LES177AS.ZIP / POPEN.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-11  |  3.4 KB  |  148 lines

  1. /*
  2.  * popen, pclose functions for MS DOS
  3.  *
  4.  * (C) Copyright 1988, 1990 Diomidis Spinellis. All rights reserved. 
  5.  *
  6.  * Redistribution and use in source and binary forms are permitted
  7.  * provided that the above copyright notice and this paragraph are
  8.  * duplicated in all such forms and that any documentation,
  9.  * advertising materials, and other materials related to such
  10.  * distribution and use acknowledge that the software was developed
  11.  * by Diomidis Spinellis.
  12.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  13.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  14.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  15.  *
  16.  */
  17.  
  18. #include <stddef.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <process.h>
  22.  
  23. /*
  24.  * Possible actions on an popened file
  25.  */
  26. enum action {
  27.     delete,             /* Used for "r". Delete the tmp file */
  28.     execute                /* Used for "w". Execute the command. */
  29. };
  30.  
  31. /*
  32.  * Linked list of things to do at the end of the program execution.
  33.  */
  34. static struct todo {
  35.     FILE *f;            /* File we are working on (to fclose) */
  36.     const char *name;        /* Name of the file (to unlink) */
  37.     const char *command;        /* Command to execute */
  38.     enum action what;        /* What to do (execute or delete) */
  39.     struct todo *next;        /* Next structure */
  40. } *todolist;
  41.  
  42. /*
  43.  * Add a file f running the command command on file name to the list
  44.  * of actions to be done at the end.  The action is specified in what.
  45.  * Return -1 on failure, 0 if ok.
  46.  */
  47. static int
  48. add(FILE *f, const char *command, const char *name, enum action what)
  49. {
  50.     struct todo    *p;
  51.  
  52.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  53.         return -1;
  54.     p->f = f;
  55.     p->command = command;
  56.     p->name = name;
  57.     p->what = what;
  58.     p->next = todolist;
  59.     todolist = p;
  60.     return 0;
  61. }
  62.  
  63. FILE *
  64. popen(const char *command, const char *t)
  65. {
  66.     char buff[256];
  67.     char *name;
  68.     FILE *f;
  69.  
  70.     if ((name = tmpnam(getenv(NULL))) == NULL)
  71.         return NULL;
  72.  
  73.     switch (*t) {
  74.     case 'r':
  75.         sprintf(buff, "%s >%s", command, name);
  76.         if (system(buff) || (f = fopen(name, "r")) == NULL) {
  77.             free(name);
  78.             return NULL;
  79.         }
  80.         if (add(f, command, name, delete)) {
  81.             (void)fclose(f);
  82.             (void)unlink(name);
  83.             free(name);
  84.             return NULL;
  85.         }
  86.         return f;
  87.     case 'w':
  88.         if ((f = fopen(name, "w")) == NULL) {
  89.             free(name);
  90.             return NULL;
  91.         }
  92.         if (add(f, command, name, execute)) {
  93.             (void)fclose(f);
  94.             (void)unlink(name);
  95.             free(name);
  96.             return NULL;
  97.         }
  98.         return f;
  99.     default:
  100.         free(name);
  101.         return NULL;
  102.     }
  103. }
  104.  
  105. int
  106. pclose(FILE *f)
  107. {
  108.     struct todo *p, **prev;
  109.     char buff[256];
  110.     const char *name;
  111.     int status;
  112.  
  113.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  114.         if (p->f == f) {
  115.             *prev = p->next;
  116.             name = p->name;
  117.             switch (p->what) {
  118.             case delete:
  119.                 free(p);
  120.                 if (fclose(f) == EOF) {
  121.                     (void)unlink(name);
  122.                     status = EOF;
  123.                 } else if (unlink(name) < 0)
  124.                     status = EOF;
  125.                 else
  126.                     status = 0;
  127.                 return status;
  128.             case execute:
  129.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  130.                 free(p);
  131.                 if (system(buff)) {
  132.                     (void)unlink(name);
  133.                     status = EOF;
  134.                 } else if (fclose(f) == EOF) {
  135.                     (void)unlink(name);
  136.                     status = EOF;
  137.                 } else if (unlink(name) < 0)
  138.                     status = EOF;
  139.                 else
  140.                     status = 0;
  141.                 return status;
  142.             default:
  143.                 return EOF;
  144.             }
  145.         }
  146.     return EOF;
  147. }
  148.