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