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