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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.13 static const char RCSid[] = "$Id: devcomm.c,v 2.12 2004/03/30 16:13:01 schorsch Exp $";
3 greg 1.1 #endif
4     /*
5     * devcomm.c - communication routines for separate drivers.
6     *
7 greg 2.6 * External symbols declared in driver.h
8     */
9    
10 greg 2.7 #include "copyright.h"
11 greg 2.9
12 schorsch 2.12 #include <sys/types.h>
13     #include <sys/wait.h> /* XXX platform specific */
14    
15 greg 2.10 #include "platform.h"
16 greg 1.10 #include "standard.h"
17 greg 1.1 #include "driver.h"
18 greg 2.2
19 greg 1.1 #ifndef DEVPATH
20     #define DEVPATH getenv("PATH") /* device search path */
21     #endif
22    
23 schorsch 2.12 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 greg 1.1
40 greg 1.12 struct driver comm_driver = {
41 greg 1.1 comm_close, comm_clear, comm_paintr, comm_getcur,
42 greg 1.12 comm_comout, comm_comin, comm_flush
43 greg 1.1 };
44    
45    
46 greg 2.3 static struct driver *
47 schorsch 2.12 final_connect(void) /* verify and initialize connection */
48 greg 2.3 {
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 gregl 2.5 erract[COMMAND].pf = comm_comout;
57     if (erract[WARNING].pf != NULL)
58     erract[WARNING].pf = comm_comout;
59 greg 2.3 return(&comm_driver);
60     }
61    
62    
63 schorsch 2.12 extern struct driver *
64     slave_init( /* run rview in slave mode */
65     char *dname,
66     char *id
67     )
68 greg 2.3 {
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 schorsch 2.12 extern struct driver *
77     comm_init( /* set up and execute driver */
78     char *dname,
79     char *id
80     )
81 greg 1.1 {
82 greg 2.6 char *dvcname;
83 greg 1.1 int p1[2], p2[2];
84 greg 1.7 char pin[16], pout[16];
85     /* find driver program */
86 greg 2.6 if ((dvcname = getpath(dname, DEVPATH, X_OK)) == NULL) {
87 gregl 2.5 eputs(dname);
88     eputs(": not found\n");
89 greg 1.1 return(NULL);
90     }
91 greg 2.8 #ifdef RHAS_FORK_EXEC
92 greg 1.7 /* open communication pipes */
93 greg 1.1 if (pipe(p1) == -1 || pipe(p2) == -1)
94     goto syserr;
95 greg 2.11 if ((devchild = fork()) == 0) { /* fork driver process */
96 greg 1.1 close(p1[1]);
97     close(p2[0]);
98 greg 1.7 sprintf(pin, "%d", p1[0]);
99     sprintf(pout, "%d", p2[1]);
100 greg 2.6 execl(dvcname, dname, pin, pout, id, 0);
101     perror(dvcname);
102 greg 1.1 _exit(127);
103     }
104     if (devchild == -1)
105     goto syserr;
106     close(p1[0]);
107     close(p2[1]);
108 greg 2.13 /*
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 greg 1.1 if ((devout = fdopen(p1[1], "w")) == NULL)
115     goto syserr;
116     if ((devin = fdopen(p2[0], "r")) == NULL)
117     goto syserr;
118 greg 2.3 return(final_connect()); /* verify initialization */
119 greg 1.1 syserr:
120 greg 1.7 perror(dname);
121 greg 1.1 return(NULL);
122 greg 2.8
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 greg 1.1 }
131    
132    
133 greg 2.6 static void
134 schorsch 2.12 comm_close(void) /* done with driver */
135 greg 1.1 {
136     int pid;
137    
138 gregl 2.5 erract[COMMAND].pf = NULL; /* reset error vectors */
139     if (erract[WARNING].pf != NULL)
140     erract[WARNING].pf = wputs;
141 greg 1.1 fclose(devout);
142     fclose(devin);
143 greg 2.3 if (devchild < 0)
144     return;
145 greg 1.1 while ((pid = wait(0)) != -1 && pid != devchild)
146     ;
147     }
148    
149    
150 greg 2.6 static void
151 schorsch 2.12 comm_clear( /* clear screen */
152     int xres,
153     int yres
154     )
155 greg 1.1 {
156     putc(COM_CLEAR, devout);
157 greg 1.8 putw(xres, devout);
158     putw(yres, devout);
159 greg 1.1 fflush(devout);
160     }
161    
162    
163 greg 2.6 static void
164 schorsch 2.12 comm_paintr( /* paint a rectangle */
165     COLOR col,
166     int xmin,
167     int ymin,
168     int xmax,
169     int ymax
170     )
171 greg 1.1 {
172     putc(COM_PAINTR, devout);
173 greg 1.10 fwrite((char *)col, sizeof(COLOR), 1, devout);
174 greg 1.8 putw(xmin, devout);
175     putw(ymin, devout);
176     putw(xmax, devout);
177     putw(ymax, devout);
178 greg 1.12 }
179    
180    
181 greg 2.6 static void
182 schorsch 2.12 comm_flush(void) /* flush output to driver */
183 greg 1.12 {
184     putc(COM_FLUSH, devout);
185     fflush(devout);
186 greg 1.13 if (getc(devin) != COM_FLUSH)
187     reply_error("flush");
188 greg 1.17 getstate();
189 greg 1.1 }
190    
191    
192     static int
193 schorsch 2.12 comm_getcur( /* get and return cursor position */
194     int *xp,
195     int *yp
196     )
197 greg 1.1 {
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 greg 1.8 *xp = getw(devin);
206     *yp = getw(devin);
207 greg 1.1 return(c);
208     }
209    
210    
211 greg 2.6 static void
212 schorsch 2.12 comm_comout( /* print string to command line */
213     char *str
214     )
215 greg 1.1 {
216     putc(COM_COMOUT, devout);
217     myputs(str, devout);
218 greg 1.18 if (str[strlen(str)-1] == '\n')
219     fflush(devout);
220 greg 1.1 }
221    
222    
223 greg 2.6 static void
224 schorsch 2.12 comm_comin( /* read string from command line */
225     char *buf,
226     char *prompt
227     )
228 greg 1.1 {
229     putc(COM_COMIN, devout);
230 greg 1.11 if (prompt == NULL)
231     putc(0, devout);
232     else {
233     putc(1, devout);
234     myputs(prompt, devout);
235     }
236 greg 1.1 fflush(devout);
237     if (getc(devin) != COM_COMIN)
238     reply_error("comin");
239     mygets(buf, devin);
240 greg 1.17 getstate();
241 greg 1.1 }
242    
243    
244 greg 2.6 static void
245 schorsch 2.12 mygets( /* get string from file (with nul) */
246     register char *s,
247     register FILE *fp
248     )
249 greg 1.1 {
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 greg 2.6 static void
260 schorsch 2.12 myputs( /* put string to file (with nul) */
261     register char *s,
262     register FILE *fp
263     )
264 greg 1.1 {
265     do
266     putc(*s, fp);
267     while (*s++);
268     }
269    
270    
271 greg 2.6 static void
272 schorsch 2.12 reply_error( /* what should we do here? */
273     char *routine
274     )
275 greg 1.1 {
276 gregl 2.5 eputs(routine);
277     eputs(": driver reply error\n");
278 greg 1.1 quit(1);
279 greg 1.17 }
280    
281    
282 greg 2.6 static void
283 schorsch 2.12 getstate(void) /* get driver state variables */
284 greg 1.17 {
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 greg 1.1 }