home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 0 / 0981 < prev    next >
Internet Message Format  |  1990-12-28  |  4KB

  1. From: zmact61@doc.ic.ac.uk (D Spinellis)
  2. Newsgroups: comp.lang.c,comp.sys.ibm.pc.programmer,alt.sources
  3. Subject: Re: popen()
  4. Message-ID: <1669@gould.doc.ic.ac.uk>
  5. Date: 5 Mar 90 09:35:40 GMT
  6.  
  7. In article <90061.202350CMH117@psuvm.psu.edu> CMH117@psuvm.psu.edu (Charles Hannum) writes:
  8. >
  9. >popen() cannot be implemented under DOS.
  10.  
  11. /*
  12.  * popen, pclose functions for MS DOS 
  13.  *
  14.  * (C) Copyright 1988, 1990 Diomidis Spinellis. All rights reserved. 
  15.  *
  16.  * Redistribution and use in source and binary forms are permitted
  17.  * provided that the above copyright notice and this paragraph are
  18.  * duplicated in all such forms and that any documentation,
  19.  * advertising materials, and other materials related to such
  20.  * distribution and use acknowledge that the software was developed
  21.  * by Diomidis Spinellis.
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  23.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  24.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25.  *
  26.  */
  27.  
  28. #include <stddef.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <process.h>
  32.  
  33. /*
  34.  * Possible actions on an popened file
  35.  */
  36. enum action {
  37.     delete,             /* Used for "r". Delete the tmp file */
  38.     execute                /* Used for "w". Execute the command. */
  39. };
  40.  
  41. /*
  42.  * Linked list of things to do at the end of the program execution.
  43.  */
  44. static struct todo {
  45.     FILE *f;            /* File we are working on (to fclose) */
  46.     const char *name;        /* Name of the file (to unlink) */
  47.     const char *command;        /* Command to execute */
  48.     enum action what;        /* What to do (execute or delete) */
  49.     struct todo *next;        /* Next structure */
  50. } *todolist;
  51.  
  52.  
  53. /* Clean up function */
  54. static int close_pipes(void);
  55.  
  56. /*
  57.  * Add a file f running the command command on file name to the list
  58.  * of actions to be done at the end.  The action is specified in what.
  59.  * Return -1 on failure, 0 if ok.
  60.  */
  61. static int
  62. add(FILE *f, const char *command, const char *name, enum action what)
  63. {
  64.     struct todo    *p;
  65.  
  66.     if ((p = (struct todo *) malloc(sizeof(struct todo))) == NULL)
  67.         return -1;
  68.     p->f = f;
  69.     p->command = command;
  70.     p->name = name;
  71.     p->what = what;
  72.     p->next = todolist;
  73.     todolist = p;
  74.     return 0;
  75. }
  76.  
  77. FILE *
  78. popen(const char *command, const char *t)
  79. {
  80.     char buff[256];
  81.     char *name;
  82.     FILE *f;
  83.     static init = 0;
  84.  
  85.     if (!init)
  86.         if (onexit(close_pipes) == NULL)
  87.             return NULL;
  88.         else
  89.             init++;
  90.  
  91.     if ((name = tempnam(getenv("TMP"), "pp")) == NULL)
  92.         return NULL;
  93.  
  94.     switch (*t) {
  95.     case 'r':
  96.         sprintf(buff, "%s >%s", command, name);
  97.         if (system(buff) || (f = fopen(name, "r")) == NULL) {
  98.             free(name);
  99.             return NULL;
  100.         }
  101.         if (add(f, command, name, delete)) {
  102.             (void)fclose(f);
  103.             (void)unlink(name);
  104.             free(name);
  105.             return NULL;
  106.         }
  107.         return f;
  108.     case 'w':
  109.         if ((f = fopen(name, "w")) == NULL) {
  110.             free(name);
  111.             return NULL;
  112.         }
  113.         if (add(f, command, name, execute)) {
  114.             (void)fclose(f);
  115.             (void)unlink(name);
  116.             free(name);
  117.             return NULL;
  118.         }
  119.         return f;
  120.     default:
  121.         free(name);
  122.         return NULL;
  123.     }
  124. }
  125.  
  126. int
  127. pclose(FILE *f)
  128. {
  129.     struct todo *p, **prev;
  130.     char buff[256];
  131.     const char *name;
  132.     int status;
  133.  
  134.     for (p = todolist, prev = &todolist; p; prev = &(p->next), p = p->next)
  135.         if (p->f == f) {
  136.             *prev = p->next;
  137.             name = p->name;
  138.             switch (p->what) {
  139.             case delete:
  140.                 free(p);
  141.                 if (fclose(f) == EOF) {
  142.                     (void)unlink(name);
  143.                     status = EOF;
  144.                 } else if (unlink(name) < 0)
  145.                     status = EOF;
  146.                 else
  147.                     status = 0;
  148.                 free(name);
  149.                 return status;
  150.             case execute:
  151.                 (void)sprintf(buff, "%s <%s", p->command, p->name);
  152.                 free(p);
  153.                 if (system(buff)) {
  154.                     (void)unlink(name);
  155.                     status = EOF;
  156.                 } else if (fclose(f) == EOF) {
  157.                     (void)unlink(name);
  158.                     status = EOF;
  159.                 } else if (unlink(name) < 0)
  160.                     status = EOF;
  161.                 else
  162.                     status = 0;
  163.                 free(name);
  164.                 return status;
  165.             default:
  166.                 return EOF;
  167.             }
  168.         }
  169.     return EOF;
  170. }
  171.  
  172. /*
  173.  * Clean up at the end.  Called by the onexit handler.
  174.  */
  175. static int
  176. close_pipes(void)
  177. {
  178.     struct todo    *p;
  179.  
  180.     for (p = todolist; p; p = p->next)
  181.         (void)pclose(p->f);
  182.     return 0;
  183. }
  184. --
  185. Diomidis Spinellis                  Internet:                 dds@cc.ic.ac.uk
  186. Department of Computing             UUCP:                    ...!ukc!iccc!dds
  187. Imperial College                    JANET:                    dds@uk.ac.ic.cc
  188. London SW7 2BZ                      #include "/dev/tty"
  189.