ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhdisp.c
Revision: 3.51
Committed: Sun Mar 28 20:33:13 2004 UTC (20 years ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1, rad3R8
Changes since 3.50: +2 -2 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

# User Rev Content
1 gregl 3.1 #ifndef lint
2 schorsch 3.51 static const char RCSid[] = "$Id: rhdisp.c,v 3.50 2004/01/01 11:21:55 schorsch Exp $";
3 gregl 3.1 #endif
4     /*
5     * Holodeck display process.
6     */
7    
8 schorsch 3.47 #include <string.h>
9     #include <ctype.h>
10    
11 schorsch 3.50 #include "rterror.h"
12 gregl 3.1 #include "rholo.h"
13     #include "rhdisp.h"
14     #include "rhdriver.h"
15     #include "selcall.h"
16    
17 gregl 3.12 #ifndef VIEWHISTLEN
18 gregl 3.16 #define VIEWHISTLEN 4 /* number of remembered views */
19 gregl 3.12 #endif
20    
21 gwlarson 3.36 #ifndef FSIZDEF
22     #define FSIZDEF 0.125 /* default focus frame size */
23     #endif
24    
25 greg 3.43 #if defined(freebsd)
26     #define fbufcnt(f) ((f)->_r)
27     #elif defined(__GNUC__)
28 gwlarson 3.42 #define fbufcnt(f) ((f)->_IO_read_end - (f)->_IO_read_ptr)
29     #else
30     #define fbufcnt(f) ((f)->_cnt)
31     #endif
32    
33 gregl 3.1 HOLO *hdlist[HDMAX+1]; /* global holodeck list */
34    
35 gwlarson 3.38 char *hdgfn[HDMAX]; /* holodeck section geometry list */
36     char *hdpfn[HDMAX]; /* section portal list */
37 gwlarson 3.37
38 gregl 3.10 char cmdlist[DC_NCMDS][8] = DC_INIT;
39    
40 gregl 3.1 int imm_mode = 0; /* bundles are being delivered immediately */
41    
42 gregl 3.20 int do_outside = 0; /* render from outside sections */
43    
44 gwlarson 3.25 double eyesepdist = 1; /* eye separation distance */
45    
46 gregl 3.1 char *progname; /* global argv[0] */
47    
48 gregl 3.10 FILE *sstdin, *sstdout; /* server's standard input and output */
49 gregl 3.1
50 gregl 3.21 #ifdef DEBUG
51     extern time_t time();
52     static time_t tmodesw;
53     static time_t timm, tadd;
54     static long nimmrays, naddrays;
55     #endif
56    
57 gregl 3.10 #define RDY_SRV 01
58     #define RDY_DEV 02
59     #define RDY_SIN 04
60 gregl 3.1
61 schorsch 3.50 static int disp_wait(void);
62     static void add_holo(HDGRID *hdg, char *gfn, char *pfn);
63     static void disp_bundle(PACKHEAD *p);
64     static void new_view(register VIEW *v);
65     static void set_focus(char *args);
66     static int usr_input(void);
67     static void printview(void);
68 gregl 3.10
69 schorsch 3.50
70     int
71     main(
72     int argc,
73     char *argv[]
74     )
75 gregl 3.1 {
76 gregl 3.3 int rdy, inp, res = 0, pause = 0;
77 gregl 3.1
78     progname = argv[0];
79 gregl 3.10 if (argc < 3)
80 gregl 3.1 error(USER, "bad command line arguments");
81     /* open our device */
82     dev_open(argv[1]);
83 gregl 3.10 /* open server process i/o */
84     sstdout = fdopen(atoi(argv[2]), "w");
85     if (argc < 4 || (inp = atoi(argv[3])) < 0)
86     sstdin = NULL;
87     else
88     sstdin = fdopen(inp, "r");
89     /* set command error vector */
90     erract[COMMAND].pf = eputs;
91 gregl 3.21 #ifdef DEBUG
92     tmodesw = time(NULL);
93     #endif
94 gregl 3.1 /* enter main loop */
95     do {
96     rdy = disp_wait();
97 gregl 3.19 if (rdy & RDY_SRV) { /* process server result */
98     res = serv_result();
99     if (pause && res != DS_SHUTDOWN) {
100     serv_request(DR_ATTEN, 0, NULL);
101     while ((res = serv_result()) != DS_ACKNOW &&
102     res != DS_SHUTDOWN)
103     ;
104     }
105     }
106 gregl 3.10 if (rdy & RDY_DEV) { /* user input from driver */
107 gregl 3.3 inp = dev_input();
108 gregl 3.13 if (inp & DFL(DC_SETVIEW))
109     new_view(&odev.v);
110 gwlarson 3.37 else if (inp & DFL(DC_LASTVIEW))
111     new_view(NULL);
112     if (inp & DFL(DC_REDRAW))
113     imm_mode = beam_sync(1) > 0;
114 gregl 3.13 if (inp & DFL(DC_GETVIEW))
115 gregl 3.10 printview();
116 gwlarson 3.36 if (inp & DFL(DC_FOCUS))
117     set_focus(odev_args);
118 gregl 3.15 if (inp & DFL(DC_KILL)) {
119 gregl 3.14 serv_request(DR_KILL, 0, NULL);
120 gregl 3.15 pause = 0;
121     }
122 gregl 3.14 if (inp & DFL(DC_CLOBBER))
123     serv_request(DR_CLOBBER, 0, NULL);
124 gregl 3.15 if (inp & DFL(DC_RESTART)) {
125 gregl 3.14 serv_request(DR_RESTART, 0, NULL);
126 gregl 3.15 pause = 0;
127     }
128 gwlarson 3.32 if (inp & DFL(DC_RESUME)) {
129     serv_request(DR_NOOP, 0, NULL);
130     pause = 0;
131     }
132     if (inp & DFL(DC_PAUSE))
133     pause = 1;
134 gregl 3.13 if (inp & DFL(DC_QUIT))
135     serv_request(DR_SHUTDOWN, 0, NULL);
136 gregl 3.3 }
137 gwlarson 3.34 if (rdy & RDY_SIN && !imm_mode) /* user input from sstdin */
138 gregl 3.10 switch (usr_input()) {
139     case DC_PAUSE:
140     pause = 1;
141     break;
142     case DC_RESUME:
143     serv_request(DR_NOOP, 0, NULL);
144 gregl 3.15 /* fall through */
145     case DC_KILL:
146     case DC_RESTART:
147 gregl 3.10 pause = 0;
148     break;
149     }
150 gregl 3.1 } while (res != DS_SHUTDOWN);
151 gregl 3.21 #ifdef DEBUG
152     if (timm && nimmrays)
153     fprintf(stderr,
154     "%s: %.1f rays recalled/second (%ld rays total)\n",
155     progname, (double)nimmrays/timm, nimmrays);
156     if (tadd && naddrays)
157     fprintf(stderr,
158     "%s: %.1f rays calculated/second (%ld rays total)\n",
159     progname, (double)naddrays/tadd, naddrays);
160     #endif
161 gregl 3.1 /* all done */
162     quit(0);
163 schorsch 3.50 return 0; /* pro forma return */
164 gregl 3.1 }
165    
166    
167 schorsch 3.50 static int
168     disp_wait(void) /* wait for more input */
169 gregl 3.1 {
170     fd_set readset, errset;
171     int flgs;
172     int n;
173     /* see if we can avoid select call */
174 gwlarson 3.40 if (hdlist[0] == NULL)
175     return(RDY_SRV); /* initialize first */
176 gwlarson 3.30 flgs = 0; /* flag what's ready already */
177 gwlarson 3.42 if (imm_mode || fbufcnt(stdin) > 0)
178 gwlarson 3.30 flgs |= RDY_SRV;
179 gwlarson 3.42 if (sstdin != NULL && fbufcnt(sstdin) > 0)
180 gwlarson 3.30 flgs |= RDY_SIN;
181     if (odev.inpready)
182     flgs |= RDY_DEV;
183     if (flgs) /* got something? */
184     return(flgs);
185     if (dev_flush()) /* else flush output & check keyboard+mouse */
186 gregl 3.4 return(RDY_DEV);
187 gwlarson 3.30 /* if nothing, we need to call select */
188 gregl 3.1 FD_ZERO(&readset); FD_ZERO(&errset);
189     FD_SET(0, &readset);
190     FD_SET(0, &errset);
191     FD_SET(odev.ifd, &readset);
192     FD_SET(odev.ifd, &errset);
193 gregl 3.10 n = odev.ifd+1;
194     if (sstdin != NULL) {
195     FD_SET(fileno(sstdin), &readset);
196 gregl 3.23 FD_SET(fileno(sstdin), &errset);
197 gregl 3.10 if (fileno(sstdin) >= n)
198     n = fileno(sstdin) + 1;
199     }
200 gregl 3.1 n = select(n, &readset, NULL, &errset, NULL);
201     if (n < 0) {
202     if (errno == EINTR)
203     return(0);
204     error(SYSTEM, "select call failure in disp_wait");
205     }
206     if (FD_ISSET(0, &readset) || FD_ISSET(0, &errset))
207 gregl 3.4 flgs |= RDY_SRV;
208 gregl 3.1 if (FD_ISSET(odev.ifd, &readset) || FD_ISSET(odev.ifd, &errset))
209 gregl 3.4 flgs |= RDY_DEV;
210 gregl 3.23 if (sstdin != NULL && (FD_ISSET(fileno(sstdin), &readset) ||
211     FD_ISSET(fileno(sstdin), &errset)))
212 gregl 3.10 flgs |= RDY_SIN;
213 gregl 3.1 return(flgs);
214     }
215    
216    
217 schorsch 3.50 static void
218     add_holo( /* register a new holodeck section */
219     HDGRID *hdg,
220     char *gfn,
221     char *pfn
222     )
223 gregl 3.1 {
224     VIEW nv;
225 gregl 3.20 double d;
226 gregl 3.1 register int hd;
227    
228     for (hd = 0; hd < HDMAX && hdlist[hd] != NULL; hd++)
229     ;
230     if (hd >= HDMAX)
231     error(INTERNAL, "too many holodeck sections in add_holo");
232     hdlist[hd] = (HOLO *)malloc(sizeof(HOLO));
233     if (hdlist[hd] == NULL)
234     error(SYSTEM, "out of memory in add_holo");
235 schorsch 3.47 memcpy((void *)hdlist[hd], (void *)hdg, sizeof(HDGRID));
236 gregl 3.1 hdcompgrid(hdlist[hd]);
237 gwlarson 3.38 hdgfn[hd] = savestr(gfn);
238     hdpfn[hd] = pfn && *pfn ? savestr(pfn) : (char *)NULL;
239 gregl 3.1 if (hd)
240     return;
241     /* set initial viewpoint */
242 schorsch 3.48 nv = odev.v;
243 gregl 3.1 VSUM(nv.vp, hdlist[0]->orig, hdlist[0]->xv[0], 0.5);
244     VSUM(nv.vp, nv.vp, hdlist[0]->xv[1], 0.5);
245     VSUM(nv.vp, nv.vp, hdlist[0]->xv[2], 0.5);
246     fcross(nv.vdir, hdlist[0]->xv[1], hdlist[0]->xv[2]);
247     VCOPY(nv.vup, hdlist[0]->xv[2]);
248 gregl 3.20 if (do_outside) {
249     normalize(nv.vdir);
250     d = VLEN(hdlist[0]->xv[1]);
251     d += VLEN(hdlist[0]->xv[2]);
252     VSUM(nv.vp, nv.vp, nv.vdir, -d);
253     }
254 gregl 3.1 new_view(&nv);
255     }
256    
257    
258 schorsch 3.50 static void
259     disp_bundle( /* display a ray bundle */
260     register PACKHEAD *p
261     )
262 gregl 3.1 {
263     GCOORD gc[2];
264     FVECT ro, rd, wp;
265     double d;
266     register int i;
267     /* get beam coordinates */
268 schorsch 3.49 if ((p->hd < 0) | (p->hd >= HDMAX) || hdlist[p->hd] == NULL)
269 gregl 3.1 error(INTERNAL, "bad holodeck number in disp_bundle");
270     if (!hdbcoord(gc, hdlist[p->hd], p->bi))
271     error(INTERNAL, "bad beam index in disp_bundle");
272     /* display each ray */
273     for (i = p->nr; i--; ) {
274     hdray(ro, rd, hdlist[p->hd], gc, packra(p)[i].r);
275     d = hddepth(hdlist[p->hd], packra(p)[i].d);
276 gwlarson 3.29 if (d < .99*FHUGE) {
277     VSUM(wp, ro, rd, d); /* might be behind viewpoint */
278     dev_value(packra(p)[i].v, rd, wp);
279     } else
280     dev_value(packra(p)[i].v, rd, NULL);
281 gregl 3.1 }
282 gregl 3.21 #ifdef DEBUG
283     if (imm_mode) nimmrays += p->nr;
284     else naddrays += p->nr;
285     #endif
286 gregl 3.1 }
287    
288    
289 schorsch 3.50 static void
290     new_view( /* change view parameters */
291     register VIEW *v
292     )
293 gregl 3.1 {
294 gregl 3.12 static VIEW viewhist[VIEWHISTLEN];
295     static unsigned nhist;
296 gwlarson 3.24 VIEW *dv;
297 gwlarson 3.40 int i, res[2];
298 greg 3.46 int16 *slist;
299 gregl 3.1 char *err;
300 gregl 3.12 /* restore previous view? */
301     if (v == NULL) {
302 gregl 3.16 if (nhist > 1) /* get one before last setting */
303     nhist--;
304     else /* else go to end of list */
305     while (nhist < VIEWHISTLEN && viewhist[nhist].type)
306     nhist++;
307 gregl 3.12 v = viewhist + ((nhist-1)%VIEWHISTLEN);
308 gregl 3.17 } else
309     again:
310     if ((err = setview(v)) != NULL) {
311 gregl 3.12 error(COMMAND, err);
312     return;
313     }
314 gwlarson 3.37 if (!dev_view(v)) /* notify display driver */
315     goto again;
316 gregl 3.12 if (v->type == VT_PAR) {
317     error(COMMAND, "cannot handle parallel views");
318     return;
319     }
320 gwlarson 3.37 beam_init(odev.firstuse); /* compute new beam set */
321     for (i = 0; (dv = dev_auxview(i, res)) != NULL; i++) {
322     if ((slist = beam_view(dv, res[0], res[1])) == NULL) {
323 gwlarson 3.24 if (!nhist) {
324     error(COMMAND, "invalid starting view");
325     return;
326     }
327 schorsch 3.48 *v = *(viewhist + ((nhist-1)%VIEWHISTLEN));
328 schorsch 3.51 goto again; /* XXX overloading dev_section()? */
329 gwlarson 3.37 }
330     DCHECK(*slist < 0, WARNING, "no visible sections in new_view");
331 gwlarson 3.38 for ( ; *slist >= 0; slist++)
332     dev_section(hdgfn[*slist], hdpfn[*slist]);
333 gwlarson 3.37 }
334 gwlarson 3.38 dev_section(NULL,NULL); /* end section list */
335 gwlarson 3.37 dev_flush(); /* update display */
336 gwlarson 3.34 /* update server */
337 gwlarson 3.37 imm_mode = beam_sync(odev.firstuse) > 0;
338 gregl 3.12 /* record new view */
339     if (v < viewhist || v >= viewhist+VIEWHISTLEN) {
340 schorsch 3.48 *(viewhist + (nhist%VIEWHISTLEN)) = *v;
341 gregl 3.12 nhist++;
342     }
343 gregl 3.10 }
344    
345    
346 schorsch 3.50 static void
347     set_focus( /* set focus frame */
348     char *args
349     )
350 gwlarson 3.36 {
351     double hcent, vcent, hsiz, vsiz;
352     VIEW *dv, vwfocus;
353     int i, res[2];
354    
355     i = sscanf(args, "%lf %lf %lf %lf", &hcent, &vcent, &hsiz, &vsiz);
356     if (i < 2 || hcent < 0 || hcent > 1 || vcent < 0 || vcent > 1) {
357     beam_init(0); /* restore view */
358     for (i = 0; (dv = dev_auxview(i, res)) != NULL; i++)
359     beam_view(dv, res[0], res[1]);
360     beam_sync(0); /* update server */
361     return;
362     }
363     if (i < 4 || hsiz <= hcent || hsiz > 1 || vsiz <= vcent || vsiz > 1)
364     hsiz = vsiz = FSIZDEF; /* gave center only */
365     else {
366     hsiz -= hcent; hcent += 0.5*hsiz; /* gave min and max */
367     vsiz -= vcent; vcent += 0.5*vsiz;
368     }
369     beam_init(0); /* add basic views */
370     for (i = 0; (dv = dev_auxview(i, res)) != NULL; i++)
371     beam_view(dv, res[0]>>4, res[1]>>4);
372 schorsch 3.48 vwfocus = odev.v; /* add focus view */
373 gwlarson 3.36 switch (odev.v.type) {
374     case VT_PER:
375     vwfocus.horiz = 2.*180./PI*atan(
376     hsiz * tan(PI/180./2.*odev.v.horiz) );
377     vwfocus.vert = 2.*180./PI*atan(
378     vsiz * tan(PI/180./2.*odev.v.vert) );
379     break;
380     case VT_PAR:
381     case VT_ANG:
382     vwfocus.horiz = hsiz * odev.v.horiz;
383     vwfocus.vert = vsiz * odev.v.vert;
384     break;
385     case VT_HEM:
386     vwfocus.horiz = 2.*180./PI*asin(
387     hsiz * sin(PI/180./2.*odev.v.horiz) );
388     vwfocus.vert = 2.*180./PI*asin(
389     vsiz * sin(PI/180./2.*odev.v.vert) );
390     break;
391     case VT_CYL:
392     vwfocus.horiz = hsiz * odev.v.horiz;
393     vwfocus.vert = 2.*180./PI*atan(
394     vsiz * tan(PI/180./2.*odev.v.vert) );
395     break;
396     default:
397     error(INTERNAL, "bad view type in set_focus");
398     }
399     vwfocus.hoff = (odev.v.hoff + hcent - 0.5)/hsiz;
400     vwfocus.voff = (odev.v.voff + vcent - 0.5)/vsiz;
401     setview(&vwfocus);
402     beam_view(&vwfocus, (int)(3*odev.hres*hsiz)+100,
403     (int)(3*odev.vres*vsiz)+100);
404     beam_sync(0); /* update server */
405     }
406    
407    
408 schorsch 3.50 static int
409     usr_input(void) /* get user input and process it */
410 gregl 3.10 {
411     VIEW vparams;
412 gregl 3.23 char cmd[256];
413 gregl 3.10 register char *args;
414 gregl 3.11 register int i;
415 gregl 3.10
416 gregl 3.23 if (fgets(cmd, sizeof(cmd), sstdin) == NULL) {
417     fclose(sstdin);
418     sstdin = NULL;
419 gwlarson 3.26 return(-1);
420 gregl 3.23 }
421 gwlarson 3.31 if (*cmd == '\n')
422 gwlarson 3.26 return(DC_RESUME);
423 gregl 3.10 for (args = cmd; *args && !isspace(*args); args++)
424     ;
425     while (isspace(*args))
426     *args++ = '\0';
427 gregl 3.11 if (*args && args[i=strlen(args)-1] == '\n')
428     args[i] = '\0';
429     for (i = 0; i < DC_NCMDS; i++)
430     if (!strcmp(cmd, cmdlist[i]))
431 gregl 3.10 break;
432 gregl 3.11 if (i >= DC_NCMDS) {
433 gwlarson 3.26 dev_auxcom(cmd, args);
434 gregl 3.10 return(-1);
435     }
436 gregl 3.11 switch (i) {
437 gregl 3.10 case DC_SETVIEW: /* set the view */
438 schorsch 3.48 vparams = odev.v;
439 gregl 3.10 if (!sscanview(&vparams, args))
440     error(COMMAND, "missing view options");
441     else
442     new_view(&vparams);
443     break;
444     case DC_GETVIEW: /* print the current view */
445     printview();
446 gregl 3.12 break;
447     case DC_LASTVIEW: /* restore previous view */
448     new_view(NULL);
449 gwlarson 3.36 break;
450     case DC_FOCUS: /* set focus frame */
451     set_focus(args);
452 gregl 3.10 break;
453     case DC_PAUSE: /* pause the current calculation */
454     case DC_RESUME: /* resume the calculation */
455     /* handled in main() */
456 gregl 3.13 break;
457     case DC_REDRAW: /* redraw from server */
458 gwlarson 3.24 imm_mode = beam_sync(1) > 0;
459 gregl 3.22 dev_clear();
460 gregl 3.14 break;
461     case DC_KILL: /* kill rtrace process(es) */
462     serv_request(DR_KILL, 0, NULL);
463     break;
464     case DC_CLOBBER: /* clobber holodeck */
465     serv_request(DR_CLOBBER, 0, NULL);
466     break;
467     case DC_RESTART: /* restart rtrace */
468     serv_request(DR_RESTART, 0, NULL);
469 gregl 3.10 break;
470     case DC_QUIT: /* quit request */
471     serv_request(DR_SHUTDOWN, 0, NULL);
472     break;
473     default:
474     error(CONSISTENCY, "bad command id in usr_input");
475     }
476 gregl 3.11 return(i);
477 gregl 3.10 }
478    
479    
480 schorsch 3.50 static void
481     printview(void) /* print our current view to server stdout */
482 gregl 3.10 {
483     fputs(VIEWSTR, sstdout);
484     fprintview(&odev.v, sstdout);
485     fputc('\n', sstdout);
486     fflush(sstdout);
487 gregl 3.1 }
488    
489    
490 schorsch 3.50 extern int
491     serv_result(void) /* get next server result and process it */
492 gregl 3.1 {
493     static char *buf = NULL;
494     static int bufsiz = 0;
495     MSGHEAD msg;
496     /* read message header */
497     if (fread((char *)&msg, sizeof(MSGHEAD), 1, stdin) != 1)
498     goto readerr;
499     if (msg.nbytes > 0) { /* get the message body */
500     if (msg.nbytes > bufsiz) {
501     if (buf == NULL)
502     buf = (char *)malloc(bufsiz=msg.nbytes);
503     else
504 greg 3.44 buf = (char *)realloc((void *)buf,
505     bufsiz=msg.nbytes);
506 gregl 3.1 if (buf == NULL)
507     error(SYSTEM, "out of memory in serv_result");
508     }
509     if (fread(buf, 1, msg.nbytes, stdin) != msg.nbytes)
510     goto readerr;
511     }
512     switch (msg.type) { /* process results */
513     case DS_BUNDLE:
514     if (msg.nbytes < sizeof(PACKHEAD) ||
515     msg.nbytes != packsiz(((PACKHEAD *)buf)->nr))
516     error(INTERNAL, "bad display packet from server");
517     disp_bundle((PACKHEAD *)buf);
518     break;
519     case DS_ADDHOLO:
520 gwlarson 3.38 if (msg.nbytes < sizeof(HDGRID)+2)
521 gregl 3.1 error(INTERNAL, "bad holodeck record from server");
522 gwlarson 3.38 add_holo((HDGRID *)buf, buf+sizeof(HDGRID),
523     buf+sizeof(HDGRID)+strlen(buf+sizeof(HDGRID))+1);
524 gregl 3.20 break;
525     case DS_OUTSECT:
526     do_outside = 1;
527 gwlarson 3.28 goto noargs;
528 gwlarson 3.25 case DS_EYESEP:
529     if (msg.nbytes <= 1 || (eyesepdist = atof(buf)) <= FTINY)
530     error(INTERNAL, "bad eye separation from server");
531 gregl 3.1 break;
532     case DS_STARTIMM:
533     case DS_ENDIMM:
534 gwlarson 3.39 if (!(imm_mode = msg.type==DS_STARTIMM))
535     dev_flush();
536 gregl 3.21 #ifdef DEBUG
537 gwlarson 3.35 {
538 gregl 3.21 time_t tnow = time(NULL);
539 gwlarson 3.35 if (msg.type==DS_STARTIMM) tadd += tnow - tmodesw;
540     else timm += tnow - tmodesw;
541 gregl 3.21 tmodesw = tnow;
542     }
543     #endif
544 gwlarson 3.28 goto noargs;
545 gregl 3.1 case DS_ACKNOW:
546     case DS_SHUTDOWN:
547 gwlarson 3.28 goto noargs;
548 gregl 3.1 default:
549     error(INTERNAL, "unrecognized result from server process");
550     }
551     return(msg.type); /* return message type */
552 gwlarson 3.28 noargs:
553     if (msg.nbytes) {
554     sprintf(errmsg, "unexpected body with server message %d",
555     msg.type);
556     error(INTERNAL, errmsg);
557     }
558     return(msg.type);
559 gregl 3.1 readerr:
560     if (feof(stdin))
561     error(SYSTEM, "server process died");
562     error(SYSTEM, "error reading from server process");
563 schorsch 3.50 return -1;
564 gregl 3.1 }
565    
566    
567 schorsch 3.50 extern void
568     serv_request( /* send a request to the server process */
569     int type,
570     int nbytes,
571     char *p
572     )
573 gregl 3.1 {
574     MSGHEAD msg;
575     int m;
576 gwlarson 3.33 /* consistency checks */
577 gwlarson 3.37 DCHECK(nbytes < 0 || nbytes > 0 & p == NULL,
578     CONSISTENCY, "bad buffer handed to serv_request");
579 gregl 3.1 /* get server's attention for big request */
580     if (nbytes >= BIGREQSIZ-sizeof(MSGHEAD)) {
581     serv_request(DR_ATTEN, 0, NULL);
582     while ((m = serv_result()) != DS_ACKNOW)
583     if (m == DS_SHUTDOWN) /* the bugger quit on us */
584     quit(0);
585     }
586     msg.type = type; /* write and flush the message */
587     msg.nbytes = nbytes;
588     fwrite((char *)&msg, sizeof(MSGHEAD), 1, stdout);
589     if (nbytes > 0)
590     fwrite(p, 1, nbytes, stdout);
591     if (fflush(stdout) < 0)
592     error(SYSTEM, "write error in serv_request");
593 gregl 3.2 }
594    
595    
596 greg 3.43 void
597 schorsch 3.50 eputs( /* put error message to stderr */
598     register char *s
599     )
600 gregl 3.2 {
601     static int midline = 0;
602    
603     if (!*s)
604     return;
605     if (!midline++) { /* prepend line with program name */
606     fputs(progname, stderr);
607     fputs(": ", stderr);
608     }
609     fputs(s, stderr);
610     if (s[strlen(s)-1] == '\n') {
611     fflush(stderr);
612     midline = 0;
613     }
614 gregl 3.1 }
615    
616    
617 greg 3.43 void
618 schorsch 3.50 quit( /* clean up and exit */
619     int code
620     )
621 gregl 3.1 {
622 gwlarson 3.38 if (code)
623     exit(code);
624 gregl 3.1 if (odev.v.type)
625     dev_close();
626 gwlarson 3.38 exit(0);
627 gregl 3.1 }