ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/devcomm.c
Revision: 2.13
Committed: Mon Sep 20 16:26:58 2004 UTC (19 years, 7 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1, rad3R8, rad3R9
Changes since 2.12: +7 -1 lines
Log Message:
Added close-on-exec flag to pipes to prevent possible deadlocks

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: devcomm.c,v 2.12 2004/03/30 16:13:01 schorsch Exp $";
3 #endif
4 /*
5 * devcomm.c - communication routines for separate drivers.
6 *
7 * External symbols declared in driver.h
8 */
9
10 #include "copyright.h"
11
12 #include <sys/types.h>
13 #include <sys/wait.h> /* XXX platform specific */
14
15 #include "platform.h"
16 #include "standard.h"
17 #include "driver.h"
18
19 #ifndef DEVPATH
20 #define DEVPATH getenv("PATH") /* device search path */
21 #endif
22
23 FILE *devin, *devout;
24 int devchild;
25
26 static struct driver * final_connect(void);
27 static void mygets(char *s, FILE *fp);
28 static void myputs(char *s, FILE *fp);
29 static void reply_error(char *routine);
30 static void getstate(void);
31
32 static dr_closef_t comm_close;
33 static dr_clearf_t comm_clear;
34 static dr_paintrf_t comm_paintr;
35 static dr_getcurf_t comm_getcur;
36 static dr_comoutf_t comm_comout;
37 static dr_cominf_t comm_comin;
38 static dr_flushf_t comm_flush;
39
40 struct driver comm_driver = {
41 comm_close, comm_clear, comm_paintr, comm_getcur,
42 comm_comout, comm_comin, comm_flush
43 };
44
45
46 static struct driver *
47 final_connect(void) /* verify and initialize connection */
48 {
49 putw(COM_SENDM, devout);
50 fflush(devout);
51 if (getw(devin) != COM_RECVM)
52 return(NULL);
53 /* get driver parameters */
54 getstate();
55 /* set error vectors */
56 erract[COMMAND].pf = comm_comout;
57 if (erract[WARNING].pf != NULL)
58 erract[WARNING].pf = comm_comout;
59 return(&comm_driver);
60 }
61
62
63 extern struct driver *
64 slave_init( /* run rview in slave mode */
65 char *dname,
66 char *id
67 )
68 {
69 devchild = -1; /* we're the slave here */
70 devout = stdout; /* use standard input */
71 devin = stdin; /* and standard output */
72 return(final_connect()); /* verify initialization */
73 }
74
75
76 extern struct driver *
77 comm_init( /* set up and execute driver */
78 char *dname,
79 char *id
80 )
81 {
82 char *dvcname;
83 int p1[2], p2[2];
84 char pin[16], pout[16];
85 /* find driver program */
86 if ((dvcname = getpath(dname, DEVPATH, X_OK)) == NULL) {
87 eputs(dname);
88 eputs(": not found\n");
89 return(NULL);
90 }
91 #ifdef RHAS_FORK_EXEC
92 /* open communication pipes */
93 if (pipe(p1) == -1 || pipe(p2) == -1)
94 goto syserr;
95 if ((devchild = fork()) == 0) { /* fork driver process */
96 close(p1[1]);
97 close(p2[0]);
98 sprintf(pin, "%d", p1[0]);
99 sprintf(pout, "%d", p2[1]);
100 execl(dvcname, dname, pin, pout, id, 0);
101 perror(dvcname);
102 _exit(127);
103 }
104 if (devchild == -1)
105 goto syserr;
106 close(p1[0]);
107 close(p2[1]);
108 /*
109 * Close write stream on exec to avoid multiprocessing deadlock.
110 * No use in read stream without it, so set flag there as well.
111 */
112 fcntl(p1[1], F_SETFD, FD_CLOEXEC);
113 fcntl(p2[0], F_SETFD, FD_CLOEXEC);
114 if ((devout = fdopen(p1[1], "w")) == NULL)
115 goto syserr;
116 if ((devin = fdopen(p2[0], "r")) == NULL)
117 goto syserr;
118 return(final_connect()); /* verify initialization */
119 syserr:
120 perror(dname);
121 return(NULL);
122
123 #else /* ! RHAS_FORK_EXEC */
124
125 eputs(dname);
126 eputs(": no fork/exec\n");
127 return(NULL);
128
129 #endif /* ! RHAS_FORK_EXEC */
130 }
131
132
133 static void
134 comm_close(void) /* done with driver */
135 {
136 int pid;
137
138 erract[COMMAND].pf = NULL; /* reset error vectors */
139 if (erract[WARNING].pf != NULL)
140 erract[WARNING].pf = wputs;
141 fclose(devout);
142 fclose(devin);
143 if (devchild < 0)
144 return;
145 while ((pid = wait(0)) != -1 && pid != devchild)
146 ;
147 }
148
149
150 static void
151 comm_clear( /* clear screen */
152 int xres,
153 int yres
154 )
155 {
156 putc(COM_CLEAR, devout);
157 putw(xres, devout);
158 putw(yres, devout);
159 fflush(devout);
160 }
161
162
163 static void
164 comm_paintr( /* paint a rectangle */
165 COLOR col,
166 int xmin,
167 int ymin,
168 int xmax,
169 int ymax
170 )
171 {
172 putc(COM_PAINTR, devout);
173 fwrite((char *)col, sizeof(COLOR), 1, devout);
174 putw(xmin, devout);
175 putw(ymin, devout);
176 putw(xmax, devout);
177 putw(ymax, devout);
178 }
179
180
181 static void
182 comm_flush(void) /* flush output to driver */
183 {
184 putc(COM_FLUSH, devout);
185 fflush(devout);
186 if (getc(devin) != COM_FLUSH)
187 reply_error("flush");
188 getstate();
189 }
190
191
192 static int
193 comm_getcur( /* get and return cursor position */
194 int *xp,
195 int *yp
196 )
197 {
198 int c;
199
200 putc(COM_GETCUR, devout);
201 fflush(devout);
202 if (getc(devin) != COM_GETCUR)
203 reply_error("getcur");
204 c = getc(devin);
205 *xp = getw(devin);
206 *yp = getw(devin);
207 return(c);
208 }
209
210
211 static void
212 comm_comout( /* print string to command line */
213 char *str
214 )
215 {
216 putc(COM_COMOUT, devout);
217 myputs(str, devout);
218 if (str[strlen(str)-1] == '\n')
219 fflush(devout);
220 }
221
222
223 static void
224 comm_comin( /* read string from command line */
225 char *buf,
226 char *prompt
227 )
228 {
229 putc(COM_COMIN, devout);
230 if (prompt == NULL)
231 putc(0, devout);
232 else {
233 putc(1, devout);
234 myputs(prompt, devout);
235 }
236 fflush(devout);
237 if (getc(devin) != COM_COMIN)
238 reply_error("comin");
239 mygets(buf, devin);
240 getstate();
241 }
242
243
244 static void
245 mygets( /* get string from file (with nul) */
246 register char *s,
247 register FILE *fp
248 )
249 {
250 register int c;
251
252 while ((c = getc(fp)) != EOF)
253 if ((*s++ = c) == '\0')
254 return;
255 *s = '\0';
256 }
257
258
259 static void
260 myputs( /* put string to file (with nul) */
261 register char *s,
262 register FILE *fp
263 )
264 {
265 do
266 putc(*s, fp);
267 while (*s++);
268 }
269
270
271 static void
272 reply_error( /* what should we do here? */
273 char *routine
274 )
275 {
276 eputs(routine);
277 eputs(": driver reply error\n");
278 quit(1);
279 }
280
281
282 static void
283 getstate(void) /* get driver state variables */
284 {
285 fread((char *)&comm_driver.pixaspect,
286 sizeof(comm_driver.pixaspect), 1, devin);
287 comm_driver.xsiz = getw(devin);
288 comm_driver.ysiz = getw(devin);
289 comm_driver.inpready = getw(devin);
290 }