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