ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimate.c
Revision: 2.40
Committed: Mon Jul 21 22:30:19 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.39: +5 -4 lines
Log Message:
Eliminated copystruct() macro, which is unnecessary in ANSI.
Reduced ambiguity warnings for nested if/if/else clauses.

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 schorsch 2.40 static const char RCSid[] = "$Id: ranimate.c,v 2.39 2003/06/30 14:59:13 schorsch Exp $";
3 greg 2.1 #endif
4     /*
5     * Radiance animation control program
6 greg 2.29 *
7     * The main difference between this program and ranimove is that
8     * we have many optimizations here for camera motion in static
9     * environments, calling rpict and pinterp on multiple processors,
10     * where ranimove puts its emphasis on object motion, and does
11     * not use any external programs for image generation.
12     *
13     * See the ranimate(1) man page for further details.
14     */
15    
16 greg 2.31 #include "copyright.h"
17 greg 2.1
18 greg 2.2 #include <ctype.h>
19 greg 2.1 #include <sys/stat.h>
20 schorsch 2.39
21     #include "standard.h"
22     #include "paths.h"
23 greg 2.1 #include "view.h"
24     #include "vars.h"
25 greg 2.2 #include "netproc.h"
26 greg 2.29 /* default blur samples */
27     #ifndef DEF_NBLUR
28     #define DEF_NBLUR 5
29     #endif
30 greg 2.10 /* default remote shell */
31     #ifdef _AUX_SOURCE
32     #define REMSH "remsh"
33     #else
34     #define REMSH "rsh"
35     #endif
36 gwlarson 2.27 /* input variables (alphabetical by name) */
37     #define ANIMATE 0 /* animation command */
38     #define ARCHIVE 1 /* archiving command */
39     #define BASENAME 2 /* output image base name */
40     #define DIRECTORY 3 /* working (sub)directory */
41     #define DISKSPACE 4 /* how much disk space to use */
42     #define END 5 /* ending frame number */
43     #define EXPOSURE 6 /* how to compute exposure */
44     #define HOST 7 /* rendering host machine */
45     #define INTERP 8 /* # frames to interpolate */
46 greg 2.29 #define MBLUR 9 /* motion blur parameters */
47 gwlarson 2.27 #define NEXTANIM 10 /* next animation file */
48     #define OCTREE 11 /* octree file name */
49     #define OVERSAMP 12 /* # times to oversample image */
50     #define PFILT 13 /* pfilt options */
51     #define PINTERP 14 /* pinterp options */
52     #define RENDER 15 /* rendering options */
53     #define RESOLUTION 16 /* desired final resolution */
54     #define RIF 17 /* rad input file */
55     #define RSH 18 /* remote shell script or program */
56     #define RTRACE 19 /* use rtrace with pinterp? */
57     #define START 20 /* starting frame number */
58     #define TRANSFER 21 /* frame transfer command */
59     #define VIEWFILE 22 /* animation frame views */
60 greg 2.1
61 greg 2.10 int NVARS = 23; /* total number of variables */
62 greg 2.1
63     VARIABLE vv[] = { /* variable-value pairs */
64 gwlarson 2.27 {"ANIMATE", 2, 0, NULL, onevalue},
65     {"ARCHIVE", 2, 0, NULL, onevalue},
66     {"BASENAME", 3, 0, NULL, onevalue},
67 greg 2.1 {"DIRECTORY", 3, 0, NULL, onevalue},
68 gwlarson 2.27 {"DISKSPACE", 3, 0, NULL, fltvalue},
69 greg 2.1 {"END", 2, 0, NULL, intvalue},
70 gwlarson 2.27 {"EXPOSURE", 3, 0, NULL, onevalue},
71     {"host", 4, 0, NULL, NULL},
72     {"INTERPOLATE", 3, 0, NULL, intvalue},
73     {"MBLUR", 2, 0, NULL, onevalue},
74 greg 2.1 {"NEXTANIM", 3, 0, NULL, onevalue},
75 gwlarson 2.27 {"OCTREE", 3, 0, NULL, onevalue},
76 greg 2.5 {"OVERSAMPLE", 2, 0, NULL, fltvalue},
77 gwlarson 2.27 {"pfilt", 2, 0, NULL, catvalues},
78     {"pinterp", 2, 0, NULL, catvalues},
79     {"render", 3, 0, NULL, catvalues},
80 greg 2.1 {"RESOLUTION", 3, 0, NULL, onevalue},
81 gwlarson 2.27 {"RIF", 3, 0, NULL, onevalue},
82 greg 2.10 {"RSH", 3, 0, NULL, onevalue},
83 gwlarson 2.27 {"RTRACE", 2, 0, NULL, boolvalue},
84     {"START", 2, 0, NULL, intvalue},
85     {"TRANSFER", 2, 0, NULL, onevalue},
86     {"VIEWFILE", 2, 0, NULL, onevalue},
87 greg 2.1 };
88    
89     #define SFNAME "STATUS" /* status file name */
90    
91     struct {
92     char host[64]; /* control host name */
93     int pid; /* control process id */
94     char cfname[128]; /* control file name */
95     int rnext; /* next frame to render */
96     int fnext; /* next frame to filter */
97     int tnext; /* next frame to transfer */
98     } astat; /* animation status */
99    
100     char *progname; /* our program name */
101     char *cfname; /* our control file name */
102    
103     int nowarn = 0; /* turn warnings off? */
104     int silent = 0; /* silent mode? */
105     int noaction = 0; /* take no action? */
106    
107 greg 2.10 char *remsh; /* remote shell program/script */
108 greg 2.21 char rendopt[2048]; /* rendering options */
109 greg 2.1 char rresopt[32]; /* rendering resolution options */
110     char fresopt[32]; /* filter resolution options */
111     int pfiltalways; /* always use pfilt? */
112    
113 greg 2.7 char arcargs[10240]; /* files to archive */
114     char *arcfirst, *arcnext; /* pointers to first and next argument */
115    
116 greg 2.2 struct pslot {
117     int pid; /* process ID (0 if empty) */
118     int fout; /* output frame number */
119     int (*rcvf)(); /* recover function */
120     } *pslot; /* process slots */
121     int npslots; /* number of process slots */
122    
123 greg 2.4 #define phostname(ps) ((ps)->hostname[0] ? (ps)->hostname : astat.host)
124    
125 greg 2.2 struct pslot *findpslot();
126    
127 greg 2.18 PSERVER *lastpserver; /* last process server with error */
128    
129 greg 2.1 VIEW *getview();
130 gwlarson 2.25 char *getexp(), *dirfile();
131 greg 2.29 int getblur();
132 greg 2.1
133 greg 2.29 extern time_t time();
134 greg 2.1
135 greg 2.12
136 greg 2.1 main(argc, argv)
137     int argc;
138     char *argv[];
139     {
140     int explicate = 0;
141     int i;
142    
143     progname = argv[0]; /* get arguments */
144     for (i = 1; i < argc && argv[i][0] == '-'; i++)
145     switch (argv[i][1]) {
146     case 'e': /* print variables */
147     explicate++;
148     break;
149     case 'w': /* turn off warnings */
150     nowarn++;
151     break;
152     case 's': /* silent mode */
153     silent++;
154     break;
155     case 'n': /* take no action */
156     noaction++;
157     break;
158     default:
159     goto userr;
160     }
161     if (i != argc-1)
162     goto userr;
163     cfname = argv[i];
164     /* load variables */
165     loadvars(cfname);
166 greg 2.22 /* check variables */
167     checkvalues();
168 greg 2.1 /* did we get DIRECTORY? */
169     checkdir();
170     /* check status */
171     if (getastat() < 0) {
172     fprintf(stderr, "%s: exiting\n", progname);
173     quit(1);
174     }
175     /* pfilt always if options given */
176     pfiltalways = vdef(PFILT);
177     /* load RIF if any */
178     if (vdef(RIF))
179     getradfile(vval(RIF));
180     /* set defaults */
181     setdefaults();
182     /* print variables */
183     if (explicate)
184     printvars(stdout);
185 greg 2.2 /* set up process servers */
186     sethosts();
187 greg 2.1 /* run animation */
188     animate();
189     /* all done */
190     if (vdef(NEXTANIM)) {
191     argv[i] = vval(NEXTANIM); /* just change input file */
192     if (!silent)
193     printargs(argc, argv, stdout);
194 greg 2.11 if ((argv[0] = getpath(progname,getenv("PATH"),X_OK)) == NULL)
195     fprintf(stderr, "%s: command not found\n", progname);
196     else
197     execv(progname, argv);
198     quit(1);
199 greg 2.1 }
200     quit(0);
201     userr:
202     fprintf(stderr, "Usage: %s [-s][-n][-w][-e] anim_file\n", progname);
203     quit(1);
204     }
205    
206    
207     getastat() /* check/set animation status */
208     {
209 greg 2.12 char sfname[256];
210 greg 2.1 FILE *fp;
211    
212 greg 2.12 sprintf(sfname, "%s/%s", vval(DIRECTORY), SFNAME);
213     if ((fp = fopen(sfname, "r")) == NULL) {
214 greg 2.1 if (errno != ENOENT) {
215 greg 2.12 perror(sfname);
216 greg 2.1 return(-1);
217     }
218     astat.rnext = astat.fnext = astat.tnext = 0;
219     goto setours;
220     }
221     if (fscanf(fp, "Control host: %s\n", astat.host) != 1)
222     goto fmterr;
223     if (fscanf(fp, "Control PID: %d\n", &astat.pid) != 1)
224     goto fmterr;
225     if (fscanf(fp, "Control file: %s\n", astat.cfname) != 1)
226     goto fmterr;
227     if (fscanf(fp, "Next render: %d\n", &astat.rnext) != 1)
228     goto fmterr;
229     if (fscanf(fp, "Next filter: %d\n", &astat.fnext) != 1)
230     goto fmterr;
231     if (fscanf(fp, "Next transfer: %d\n", &astat.tnext) != 1)
232     goto fmterr;
233     fclose(fp);
234     if (astat.pid != 0) { /* thinks it's still running */
235 greg 2.9 if (strcmp(myhostname(), astat.host)) {
236 greg 2.1 fprintf(stderr,
237     "%s: process %d may still be running on host %s\n",
238     progname, astat.pid, astat.host);
239     return(-1);
240     }
241     if (kill(astat.pid, 0) != -1 || errno != ESRCH) {
242     fprintf(stderr, "%s: process %d is still running\n",
243     progname, astat.pid);
244     return(-1);
245     }
246     /* assume it is dead */
247     }
248 greg 2.20 if (strcmp(cfname, astat.cfname) && astat.pid != 0) { /* other's */
249 greg 2.1 fprintf(stderr, "%s: unfinished job \"%s\"\n",
250     progname, astat.cfname);
251     return(-1);
252     }
253 greg 2.12 /* check control file mods. */
254     if (!nowarn && fdate(cfname) > fdate(sfname))
255     fprintf(stderr,
256     "%s: warning - control file modified since last run\n",
257     progname);
258 greg 2.1 setours: /* set our values */
259 greg 2.9 strcpy(astat.host, myhostname());
260 greg 2.1 astat.pid = getpid();
261     strcpy(astat.cfname, cfname);
262     return(0);
263     fmterr:
264     fprintf(stderr, "%s: format error in status file \"%s\"\n",
265 greg 2.12 progname, sfname);
266 greg 2.1 fclose(fp);
267     return(-1);
268     }
269    
270    
271     putastat() /* put out current status */
272     {
273     char buf[256];
274     FILE *fp;
275    
276 greg 2.2 if (noaction)
277     return;
278 greg 2.1 sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME);
279     if ((fp = fopen(buf, "w")) == NULL) {
280     perror(buf);
281     quit(1);
282     }
283     fprintf(fp, "Control host: %s\n", astat.host);
284     fprintf(fp, "Control PID: %d\n", astat.pid);
285     fprintf(fp, "Control file: %s\n", astat.cfname);
286     fprintf(fp, "Next render: %d\n", astat.rnext);
287     fprintf(fp, "Next filter: %d\n", astat.fnext);
288     fprintf(fp, "Next transfer: %d\n", astat.tnext);
289     fclose(fp);
290     }
291    
292    
293     checkdir() /* make sure we have our directory */
294     {
295     struct stat stb;
296    
297     if (!vdef(DIRECTORY)) {
298     fprintf(stderr, "%s: %s undefined\n",
299     progname, vnam(DIRECTORY));
300     quit(1);
301     }
302     if (stat(vval(DIRECTORY), &stb) == -1) {
303     if (errno == ENOENT && mkdir(vval(DIRECTORY), 0777) == 0)
304     return;
305     perror(vval(DIRECTORY));
306     quit(1);
307     }
308     if (!(stb.st_mode & S_IFDIR)) {
309     fprintf(stderr, "%s: not a directory\n", vval(DIRECTORY));
310     quit(1);
311     }
312     }
313    
314    
315     setdefaults() /* set default values */
316     {
317 greg 2.10 extern char *atos();
318 greg 2.19 int decades;
319 greg 2.1 char buf[256];
320    
321 greg 2.2 if (vdef(ANIMATE)) {
322     vval(OCTREE) = NULL;
323     vdef(OCTREE) = 0;
324     } else if (!vdef(OCTREE)) {
325 greg 2.1 fprintf(stderr, "%s: either %s or %s must be defined\n",
326     progname, vnam(OCTREE), vnam(ANIMATE));
327     quit(1);
328     }
329     if (!vdef(VIEWFILE)) {
330     fprintf(stderr, "%s: %s undefined\n", progname, vnam(VIEWFILE));
331     quit(1);
332     }
333 greg 2.2 if (!vdef(HOST)) {
334     vval(HOST) = LHOSTNAME;
335     vdef(HOST)++;
336     }
337 greg 2.1 if (!vdef(START)) {
338     vval(START) = "1";
339     vdef(START)++;
340     }
341     if (!vdef(END)) {
342 greg 2.5 sprintf(buf, "%d", countviews()+vint(START)-1);
343 greg 2.1 vval(END) = savqstr(buf);
344     vdef(END)++;
345     }
346 greg 2.5 if (vint(END) < vint(START)) {
347     fprintf(stderr, "%s: ending frame less than starting frame\n",
348     progname);
349     quit(1);
350     }
351 greg 2.1 if (!vdef(BASENAME)) {
352 greg 2.19 decades = (int)log10((double)vint(END)) + 1;
353     if (decades < 3) decades = 3;
354     sprintf(buf, "%s/frame%%0%dd", vval(DIRECTORY), decades);
355 greg 2.1 vval(BASENAME) = savqstr(buf);
356     vdef(BASENAME)++;
357     }
358     if (!vdef(RESOLUTION)) {
359     vval(RESOLUTION) = "640";
360     vdef(RESOLUTION)++;
361     }
362     if (!vdef(OVERSAMP)) {
363     vval(OVERSAMP) = "2";
364     vdef(OVERSAMP)++;
365     }
366     if (!vdef(INTERP)) {
367     vval(INTERP) = "0";
368     vdef(INTERP)++;
369     }
370     if (!vdef(MBLUR)) {
371     vval(MBLUR) = "0";
372     vdef(MBLUR)++;
373     }
374     if (!vdef(RTRACE)) {
375     vval(RTRACE) = "F";
376     vdef(RTRACE)++;
377     }
378     if (!vdef(DISKSPACE)) {
379     if (!nowarn)
380     fprintf(stderr,
381     "%s: warning - no %s setting, assuming 100 Mbytes available\n",
382     progname, vnam(DISKSPACE));
383     vval(DISKSPACE) = "100";
384     vdef(DISKSPACE)++;
385     }
386 greg 2.10 if (!vdef(RSH)) {
387     vval(RSH) = REMSH;
388     vdef(RSH)++;
389     }
390     /* locate remote shell program */
391     atos(buf, sizeof(buf), vval(RSH));
392     if ((remsh = getpath(buf, getenv("PATH"), X_OK)) != NULL)
393     remsh = savqstr(remsh);
394     else
395     remsh = vval(RSH); /* will generate error if used */
396    
397 greg 2.1 /* append rendering options */
398     if (vdef(RENDER))
399     sprintf(rendopt+strlen(rendopt), " %s", vval(RENDER));
400     }
401    
402    
403 greg 2.2 sethosts() /* set up process servers */
404     {
405     extern char *iskip();
406     char buf[256], *dir, *uname;
407     int np;
408     register char *cp;
409     int i;
410    
411     npslots = 0;
412     if (noaction)
413     return;
414     for (i = 0; i < vdef(HOST); i++) { /* add each host */
415     dir = uname = NULL;
416     np = 1;
417     strcpy(cp=buf, nvalue(HOST, i)); /* copy to buffer */
418     cp = sskip(cp); /* skip host name */
419     while (isspace(*cp))
420     *cp++ = '\0';
421     if (*cp) { /* has # processes? */
422     np = atoi(cp);
423     if ((cp = iskip(cp)) == NULL || (*cp && !isspace(*cp)))
424     badvalue(HOST);
425     while (isspace(*cp))
426     cp++;
427     if (*cp) { /* has directory? */
428     dir = cp;
429     cp = sskip(cp); /* skip dir. */
430     while (isspace(*cp))
431     *cp++ = '\0';
432     if (*cp) { /* has user? */
433     uname = cp;
434     if (*sskip(cp))
435     badvalue(HOST);
436     }
437     }
438     }
439     if (addpserver(buf, dir, uname, np) == NULL) {
440     if (!nowarn)
441     fprintf(stderr,
442     "%s: cannot execute on host \"%s\"\n",
443     progname, buf);
444     } else
445     npslots += np;
446     }
447     if (npslots == 0) {
448     fprintf(stderr, "%s: no working process servers\n", progname);
449     quit(1);
450     }
451     pslot = (struct pslot *)calloc(npslots, sizeof(struct pslot));
452     if (pslot == NULL) {
453     perror("malloc");
454     quit(1);
455     }
456     }
457    
458    
459 greg 2.7 getradfile(rfargs) /* run rad and get needed variables */
460     char *rfargs;
461 greg 2.1 {
462     static short mvar[] = {OCTREE,PFILT,RESOLUTION,EXPOSURE,-1};
463     char combuf[256];
464     register int i;
465     register char *cp;
466 gregl 2.23 char *pippt;
467 greg 2.1 /* create rad command */
468     sprintf(rendopt, " @%s/render.opt", vval(DIRECTORY));
469     sprintf(combuf,
470     "rad -v 0 -s -e -w %s OPTFILE=%s | egrep '^[ \t]*(NOMATCH",
471 greg 2.7 rfargs, rendopt+2);
472 greg 2.1 cp = combuf;
473 gregl 2.23 while (*cp) {
474     if (*cp == '|') pippt = cp;
475     cp++;
476     } /* match unset variables */
477 greg 2.1 for (i = 0; mvar[i] >= 0; i++)
478     if (!vdef(mvar[i])) {
479     *cp++ = '|';
480     strcpy(cp, vnam(mvar[i]));
481     while (*cp) cp++;
482 gregl 2.23 pippt = NULL;
483 greg 2.1 }
484 gregl 2.23 if (pippt != NULL)
485 schorsch 2.39 strcpy(pippt, "> " NULL_DEVICE); /* nothing to match */
486 gregl 2.23 else {
487     sprintf(cp, ")[ \t]*=' > %s/radset.var", vval(DIRECTORY));
488     cp += 11; /* point to file name */
489     }
490 gwlarson 2.28 system(combuf); /* ignore exit code */
491 gregl 2.23 if (pippt == NULL) { /* load variables and remove file */
492     loadvars(cp);
493     unlink(cp);
494     }
495 greg 2.1 }
496    
497    
498     animate() /* run animation */
499     {
500     int xres, yres;
501     float pa, mult;
502     int frames_batch;
503     register int i;
504     double d1, d2;
505     /* compute rpict resolution */
506     i = sscanf(vval(RESOLUTION), "%d %d %f", &xres, &yres, &pa);
507     mult = vflt(OVERSAMP);
508     if (i == 3) {
509 greg 2.16 sprintf(rresopt, "-x %d -y %d -pa %.3f", (int)(mult*xres),
510 greg 2.1 (int)(mult*yres), pa);
511 greg 2.16 sprintf(fresopt, "-x %d -y %d -pa %.3f", xres, yres, pa);
512 greg 2.1 } else if (i) {
513     if (i == 1) yres = xres;
514     sprintf(rresopt, "-x %d -y %d", (int)(mult*xres),
515     (int)(mult*yres));
516     sprintf(fresopt, "-x %d -y %d -pa 1", xres, yres);
517     } else
518     badvalue(RESOLUTION);
519     /* consistency checks */
520     if (vdef(ANIMATE)) {
521     if (vint(INTERP)) {
522     if (!nowarn)
523     fprintf(stderr,
524     "%s: resetting %s=0 for animation\n",
525     progname, vnam(INTERP));
526     vval(INTERP) = "0";
527     }
528 greg 2.29 if (strcmp(vval(MBLUR),"0")) { /* can't handle this */
529 greg 2.1 if (!nowarn)
530     fprintf(stderr,
531     "%s: resetting %s=0 for animation\n",
532     progname, vnam(MBLUR));
533     vval(MBLUR) = "0";
534     }
535     }
536     /* figure # frames per batch */
537     d1 = mult*xres*mult*yres*4; /* space for orig. picture */
538 greg 2.29 if ((i=vint(INTERP)) || getblur(NULL) > 1)
539 greg 2.13 d1 += mult*xres*mult*yres*sizeof(float); /* Z-buffer */
540 greg 2.1 d2 = xres*yres*4; /* space for final picture */
541     frames_batch = (i+1)*(vflt(DISKSPACE)*1048576.-d1)/(d1+i*d2);
542     if (frames_batch < i+2) {
543     fprintf(stderr, "%s: insufficient disk space allocated\n",
544     progname);
545     quit(1);
546     }
547 greg 2.7 /* initialize archive argument list */
548 gwlarson 2.25 i = vdef(ARCHIVE) ? strlen(vval(ARCHIVE))+132 : 132;
549 greg 2.7 arcnext = arcfirst = arcargs + i;
550 greg 2.1 /* initialize status file */
551     if (astat.rnext == 0)
552     astat.rnext = astat.fnext = astat.tnext = vint(START);
553     putastat();
554     /* render in batches */
555 greg 2.2 while (astat.tnext <= vint(END)) {
556 greg 2.1 renderframes(frames_batch);
557     filterframes();
558     transferframes();
559     }
560     /* mark status as finished */
561     astat.pid = 0;
562     putastat();
563     /* close open files */
564     getview(0);
565     getexp(0);
566     }
567    
568    
569     renderframes(nframes) /* render next nframes frames */
570     int nframes;
571     {
572     static char vendbuf[16];
573     VIEW *vp;
574     FILE *fp = NULL;
575     char vfname[128];
576     int lastframe;
577     register int i;
578    
579     if (astat.tnext < astat.rnext) /* other work to do first */
580     return;
581     /* create batch view file */
582     if (!vdef(ANIMATE)) {
583     sprintf(vfname, "%s/anim.vf", vval(DIRECTORY));
584     if ((fp = fopen(vfname, "w")) == NULL) {
585     perror(vfname);
586     quit(1);
587     }
588     }
589     /* bound batch properly */
590     lastframe = astat.rnext + nframes - 1;
591     if ((lastframe-1) % (vint(INTERP)+1)) /* need even interval */
592     lastframe += vint(INTERP)+1 - ((lastframe-1)%(vint(INTERP)+1));
593     if (lastframe > vint(END)) /* check for end */
594     lastframe = vint(END);
595     /* render each view */
596     for (i = astat.rnext; i <= lastframe; i++) {
597     if ((vp = getview(i)) == NULL) {
598     if (!nowarn)
599     fprintf(stderr,
600     "%s: ran out of views before last frame\n",
601     progname);
602     sprintf(vval(END)=vendbuf, "%d", i-1);
603     lastframe = i - 1;
604     break;
605     }
606     if (vdef(ANIMATE)) /* animate frame */
607     animrend(i, vp);
608     else { /* else record it */
609     fputs(VIEWSTR, fp);
610     fprintview(vp, fp);
611     putc('\n', fp);
612     }
613     }
614     if (vdef(ANIMATE)) /* wait for renderings to finish */
615 greg 2.2 bwait(0);
616 greg 2.1 else { /* else if walk-through */
617     fclose(fp); /* close view file */
618     walkwait(astat.rnext, lastframe, vfname); /* walk it */
619     unlink(vfname); /* remove view file */
620     }
621     astat.rnext = i; /* update status */
622     putastat();
623     }
624    
625    
626     filterframes() /* catch up with filtering */
627     {
628     VIEW *vp;
629     register int i;
630    
631     if (astat.tnext < astat.fnext) /* other work to do first */
632     return;
633     /* filter each view */
634 greg 2.38 for (i = astat.fnext; i < astat.rnext; i++)
635     dofilt(i, 0);
636    
637 greg 2.2 bwait(0); /* wait for filter processes */
638 greg 2.7 archive(); /* archive originals */
639 greg 2.1 astat.fnext = i; /* update status */
640     putastat();
641     }
642    
643    
644     transferframes() /* catch up with picture transfers */
645     {
646 gwlarson 2.25 char combuf[10240], *fbase;
647 greg 2.1 register char *cp;
648     register int i;
649    
650     if (astat.tnext >= astat.fnext) /* nothing to do, yet */
651     return;
652     if (!vdef(TRANSFER)) { /* no transfer function -- leave 'em */
653     astat.tnext = astat.fnext;
654     putastat(); /* update status */
655     return;
656     }
657 gwlarson 2.25 strcpy(combuf, "cd "); /* start transfer command */
658     fbase = dirfile(cp = combuf+3, vval(BASENAME));
659     if (*cp) {
660     while (*++cp) ;
661     *cp++ = ';'; *cp++ = ' ';
662     } else
663     cp = combuf;
664     strcpy(cp, vval(TRANSFER));
665     while (*cp) cp++;
666 greg 2.1 /* make argument list */
667     for (i = astat.tnext; i < astat.fnext; i++) {
668     *cp++ = ' ';
669 gwlarson 2.25 sprintf(cp, fbase, i);
670 greg 2.1 while (*cp) cp++;
671     strcpy(cp, ".pic");
672     cp += 4;
673     }
674     if (runcom(combuf)) { /* transfer frames */
675     fprintf(stderr, "%s: error running transfer command\n",
676     progname);
677     quit(1);
678     }
679     astat.tnext = i; /* update status */
680     putastat();
681     }
682    
683    
684     animrend(frame, vp) /* start animation frame */
685     int frame;
686     VIEW *vp;
687     {
688 greg 2.2 extern int recover();
689 greg 2.1 char combuf[2048];
690     char fname[128];
691    
692     sprintf(fname, vval(BASENAME), frame);
693     strcat(fname, ".unf");
694     if (access(fname, F_OK) == 0)
695     return;
696 greg 2.2 sprintf(combuf, "%s %d | rpict%s%s -w0 %s > %s", vval(ANIMATE), frame,
697 greg 2.1 rendopt, viewopt(vp), rresopt, fname);
698 greg 2.2 bruncom(combuf, frame, recover); /* run in background */
699 greg 2.1 }
700    
701    
702     walkwait(first, last, vfn) /* walk-through frames */
703     int first, last;
704     char *vfn;
705     {
706 greg 2.29 double blurf;
707     int nblur = getblur(&blurf);
708 greg 2.1 char combuf[2048];
709 greg 2.29 register char *inspoint;
710 greg 2.1 register int i;
711    
712     if (!noaction && vint(INTERP)) /* create dummy frames */
713     for (i = first; i <= last; i++)
714     if (i < vint(END) && (i-1) % (vint(INTERP)+1)) {
715     sprintf(combuf, vval(BASENAME), i);
716     strcat(combuf, ".unf");
717     close(open(combuf, O_RDONLY|O_CREAT, 0666));
718     }
719     /* create command */
720 greg 2.35 sprintf(combuf, "rpict%s%s -w0", rendopt,
721     viewopt(getview(first>1 ? first-1 : 1)));
722 greg 2.29 inspoint = combuf;
723     while (*inspoint) inspoint++;
724     if (nblur) {
725     sprintf(inspoint, " -pm %.3f", blurf/nblur);
726     while (*inspoint) inspoint++;
727     }
728     if (nblur > 1 || vint(INTERP)) {
729     sprintf(inspoint, " -z %s.zbf", vval(BASENAME));
730     while (*inspoint) inspoint++;
731     }
732     sprintf(inspoint, " -o %s.unf %s -S %d",
733 greg 2.4 vval(BASENAME), rresopt, first);
734 greg 2.29 while (*inspoint) inspoint++;
735 greg 2.4 sprintf(inspoint, " %s < %s", vval(OCTREE), vfn);
736 greg 2.2 /* run in parallel */
737 greg 2.7 i = (last-first+1)/(vint(INTERP)+1);
738     if (i < 1) i = 1;
739     if (pruncom(combuf, inspoint, i)) {
740 greg 2.2 fprintf(stderr, "%s: error rendering frames %d through %d\n",
741 greg 2.1 progname, first, last);
742     quit(1);
743     }
744     if (!noaction && vint(INTERP)) /* remove dummy frames */
745     for (i = first; i <= last; i++)
746     if (i < vint(END) && (i-1) % (vint(INTERP)+1)) {
747     sprintf(combuf, vval(BASENAME), i);
748     strcat(combuf, ".unf");
749     unlink(combuf);
750     }
751     }
752    
753    
754 greg 2.2 int
755 greg 2.1 recover(frame) /* recover the specified frame */
756     int frame;
757     {
758 greg 2.2 static int *rfrm; /* list of recovered frames */
759     static int nrfrms = 0;
760 greg 2.29 double blurf;
761     int nblur = getblur(&blurf);
762 greg 2.1 char combuf[2048];
763     char fname[128];
764     register char *cp;
765 greg 2.2 register int i;
766     /* check to see if recovered already */
767     for (i = nrfrms; i--; )
768     if (rfrm[i] == frame)
769     return(0);
770     /* build command */
771 greg 2.1 sprintf(fname, vval(BASENAME), frame);
772     if (vdef(ANIMATE))
773 greg 2.2 sprintf(combuf, "%s %d | rpict%s -w0",
774 greg 2.1 vval(ANIMATE), frame, rendopt);
775     else
776 greg 2.2 sprintf(combuf, "rpict%s -w0", rendopt);
777 greg 2.29 cp = combuf;
778     while (*cp) cp++;
779     if (nblur) {
780     sprintf(cp, " -pm %.3f", blurf/nblur);
781     while (*cp) cp++;
782     }
783     if (nblur > 1 || vint(INTERP)) {
784 greg 2.1 sprintf(cp, " -z %s.zbf", fname);
785     while (*cp) cp++;
786     }
787     sprintf(cp, " -ro %s.unf", fname);
788     while (*cp) cp++;
789     if (!vdef(ANIMATE)) {
790     *cp++ = ' ';
791     strcpy(cp, vval(OCTREE));
792     }
793 greg 2.2 if (runcom(combuf)) /* run command */
794     return(1);
795     /* add frame to recovered list */
796     if (nrfrms)
797 greg 2.32 rfrm = (int *)realloc((void *)rfrm, (nrfrms+1)*sizeof(int));
798 greg 2.2 else
799     rfrm = (int *)malloc(sizeof(int));
800     if (rfrm == NULL) {
801     perror("malloc");
802 greg 2.1 quit(1);
803     }
804 greg 2.2 rfrm[nrfrms++] = frame;
805     return(0);
806 greg 2.1 }
807    
808    
809 greg 2.2 int
810     frecover(frame) /* recover filtered frame */
811     int frame;
812     {
813 greg 2.38 if (dofilt(frame, 2) && dofilt(frame, 1))
814 greg 2.2 return(1);
815     return(0);
816     }
817    
818    
819 greg 2.7 archive() /* archive and remove renderings */
820 greg 2.1 {
821 greg 2.2 #define RMCOML (sizeof(rmcom)-1)
822     static char rmcom[] = "rm -f";
823 gwlarson 2.25 char basedir[128];
824     int dlen, alen;
825     register int j;
826 greg 2.1
827 greg 2.7 if (arcnext == arcfirst)
828     return; /* nothing to do */
829 gwlarson 2.25 dirfile(basedir, vval(BASENAME));
830     dlen = strlen(basedir);
831 greg 2.2 if (vdef(ARCHIVE)) { /* run archive command */
832 gwlarson 2.25 alen = strlen(vval(ARCHIVE));
833     if (dlen) {
834     j = alen + dlen + 5;
835     strncpy(arcfirst-j, "cd ", 3);
836     strncpy(arcfirst-j+3, basedir, dlen);
837     (arcfirst-j)[dlen+3] = ';'; (arcfirst-j)[dlen+4] = ' ';
838     } else
839     j = alen;
840     strncpy(arcfirst-alen, vval(ARCHIVE), alen);
841     if (runcom(arcfirst-j)) {
842 greg 2.7 fprintf(stderr, "%s: error running archive command\n",
843     progname);
844 greg 2.2 quit(1);
845     }
846 greg 2.1 }
847 gwlarson 2.25 if (dlen) {
848     j = RMCOML + dlen + 5;
849     strncpy(arcfirst-j, "cd ", 3);
850     strncpy(arcfirst-j+3, basedir, dlen);
851     (arcfirst-j)[dlen+3] = ';'; (arcfirst-j)[dlen+4] = ' ';
852     } else
853     j = RMCOML;
854 greg 2.2 /* run remove command */
855 greg 2.7 strncpy(arcfirst-RMCOML, rmcom, RMCOML);
856 gwlarson 2.25 runcom(arcfirst-j);
857 greg 2.7 arcnext = arcfirst; /* reset argument list */
858 greg 2.2 #undef RMCOML
859 greg 2.1 }
860    
861    
862 greg 2.2 int
863 greg 2.38 dofilt(frame, rvr) /* filter frame */
864 greg 2.1 int frame;
865 greg 2.2 int rvr;
866 greg 2.1 {
867 greg 2.2 extern int frecover();
868 greg 2.6 static int iter = 0;
869 greg 2.29 double blurf;
870     int nblur = getblur(&blurf);
871 greg 2.38 VIEW *vp = getview(frame);
872     char *ep = getexp(frame);
873 gwlarson 2.25 char fnbefore[128], fnafter[128], *fbase;
874 greg 2.6 char combuf[1024], fname0[128], fname1[128];
875 greg 2.7 int usepinterp, usepfilt, nora_rgbe;
876 greg 2.2 int frseq[2];
877 greg 2.1 /* check what is needed */
878 greg 2.38 if (vp == NULL) {
879     fprintf(stderr,
880     "%s: unexpected error reading view for frame %d\n",
881     progname, frame);
882     quit(1);
883     }
884     if (ep == NULL) {
885     fprintf(stderr,
886     "%s: unexpected error reading exposure for frame %d\n",
887     progname, frame);
888     quit(1);
889     }
890 greg 2.29 usepinterp = (nblur > 1);
891 greg 2.1 usepfilt = pfiltalways | ep==NULL;
892 greg 2.7 if (ep != NULL && !strcmp(ep, "1"))
893     ep = "+0";
894     nora_rgbe = strcmp(vval(OVERSAMP),"1") || ep==NULL ||
895     *ep != '+' || *ep != '-' || !isint(ep);
896 greg 2.1 /* compute rendered views */
897 greg 2.2 frseq[0] = frame - ((frame-1) % (vint(INTERP)+1));
898     frseq[1] = frseq[0] + vint(INTERP) + 1;
899 gwlarson 2.25 fbase = dirfile(NULL, vval(BASENAME));
900 greg 2.2 if (frseq[1] > vint(END))
901     frseq[1] = vint(END);
902     if (frseq[1] == frame) { /* pfilt only */
903     frseq[0] = frseq[1];
904 greg 2.1 usepinterp = 0; /* update what's needed */
905 greg 2.7 usepfilt |= nora_rgbe;
906     } else if (frseq[0] == frame) { /* no interpolation needed */
907     if (!rvr && frame > 1+vint(INTERP)) { /* archive previous */
908     *arcnext++ = ' ';
909 gwlarson 2.25 sprintf(arcnext, fbase, frame-vint(INTERP)-1);
910 greg 2.7 while (*arcnext) arcnext++;
911     strcpy(arcnext, ".unf");
912     arcnext += 4;
913 greg 2.13 if (usepinterp || vint(INTERP)) { /* and Z-buf */
914 greg 2.7 *arcnext++ = ' ';
915 gwlarson 2.25 sprintf(arcnext, fbase, frame-vint(INTERP)-1);
916 greg 2.7 while (*arcnext) arcnext++;
917     strcpy(arcnext, ".zbf");
918     arcnext += 4;
919     }
920     }
921     if (!usepinterp) /* update what's needed */
922     usepfilt |= nora_rgbe;
923 greg 2.2 } else /* interpolation needed */
924 greg 2.1 usepinterp++;
925 greg 2.2 if (frseq[1] >= astat.rnext) /* next batch unavailable */
926     frseq[1] = frseq[0];
927     sprintf(fnbefore, vval(BASENAME), frseq[0]);
928     sprintf(fnafter, vval(BASENAME), frseq[1]);
929     if (rvr == 1 && recover(frseq[0])) /* recover before frame? */
930     return(1);
931     /* generate command */
932 greg 2.1 if (usepinterp) { /* using pinterp */
933 greg 2.2 if (rvr == 2 && recover(frseq[1])) /* recover after? */
934     return(1);
935 greg 2.29 if (nblur > 1) { /* with pmblur */
936 greg 2.6 sprintf(fname0, "%s/vw0%c", vval(DIRECTORY),
937     'a'+(iter%26));
938     sprintf(fname1, "%s/vw1%c", vval(DIRECTORY),
939     'a'+(iter%26));
940 gwlarson 2.25 if (!noaction) {
941     FILE *fp; /* motion blurring */
942     if ((fp = fopen(fname0, "w")) == NULL) {
943     perror(fname0); quit(1);
944     }
945     fputs(VIEWSTR, fp);
946     fprintview(vp, fp);
947     putc('\n', fp); fclose(fp);
948     if ((vp = getview(frame+1)) == NULL) {
949     fprintf(stderr,
950     "%s: unexpected error reading view for frame %d\n",
951     progname, frame+1);
952     quit(1);
953     }
954     if ((fp = fopen(fname1, "w")) == NULL) {
955     perror(fname1); quit(1);
956     }
957     fputs(VIEWSTR, fp);
958     fprintview(vp, fp);
959     putc('\n', fp); fclose(fp);
960 greg 2.1 }
961     sprintf(combuf,
962 greg 2.30 "(pmblur %.3f %d %s %s; rm -f %s %s) | pinterp -B -a",
963 greg 2.29 blurf, nblur,
964 greg 2.6 fname0, fname1, fname0, fname1);
965     iter++;
966 greg 2.1 } else /* no blurring */
967     strcpy(combuf, "pinterp");
968     strcat(combuf, viewopt(vp));
969     if (vbool(RTRACE))
970 greg 2.2 sprintf(combuf+strlen(combuf), " -ff -fr '%s -w0 %s'",
971 greg 2.21 rendopt+1, vval(OCTREE));
972 greg 2.1 if (vdef(PINTERP))
973     sprintf(combuf+strlen(combuf), " %s", vval(PINTERP));
974     if (usepfilt)
975     sprintf(combuf+strlen(combuf), " %s", rresopt);
976     else
977 greg 2.33 sprintf(combuf+strlen(combuf), " -a %s -e %s",
978 greg 2.1 fresopt, ep);
979     sprintf(combuf+strlen(combuf), " %s.unf %s.zbf",
980     fnbefore, fnbefore);
981 greg 2.2 if (frseq[1] != frseq[0])
982 greg 2.1 sprintf(combuf+strlen(combuf), " %s.unf %s.zbf",
983     fnafter, fnafter);
984     if (usepfilt) { /* also pfilt */
985     if (vdef(PFILT))
986     sprintf(combuf+strlen(combuf), " | pfilt %s",
987     vval(PFILT));
988     else
989     strcat(combuf, " | pfilt");
990     if (ep != NULL)
991     sprintf(combuf+strlen(combuf), " -1 -e %s %s",
992     ep, fresopt);
993     else
994     sprintf(combuf+strlen(combuf), " %s", fresopt);
995     }
996     } else if (usepfilt) { /* pfilt only */
997 greg 2.2 if (rvr == 2)
998     return(1);
999 greg 2.1 if (vdef(PFILT))
1000     sprintf(combuf, "pfilt %s", vval(PFILT));
1001     else
1002     strcpy(combuf, "pfilt");
1003     if (ep != NULL)
1004     sprintf(combuf+strlen(combuf), " -1 -e %s %s %s.unf",
1005     ep, fresopt, fnbefore);
1006     else
1007     sprintf(combuf+strlen(combuf), " %s %s.unf",
1008     fresopt, fnbefore);
1009     } else { /* else just check it */
1010 greg 2.2 if (rvr == 2)
1011     return(1);
1012 greg 2.7 sprintf(combuf, "ra_rgbe -e %s -r %s.unf", ep, fnbefore);
1013 greg 2.1 }
1014     /* output file name */
1015 greg 2.6 sprintf(fname0, vval(BASENAME), frame);
1016     sprintf(combuf+strlen(combuf), " > %s.pic", fname0);
1017 greg 2.2 if (rvr) /* in recovery */
1018     return(runcom(combuf));
1019     bruncom(combuf, frame, frecover); /* else run in background */
1020     return(0);
1021 greg 2.1 }
1022    
1023    
1024     VIEW *
1025     getview(n) /* get view number n */
1026     int n;
1027     {
1028     static FILE *viewfp = NULL; /* view file pointer */
1029     static int viewnum = 0; /* current view number */
1030     static VIEW curview = STDVIEW; /* current view */
1031     char linebuf[256];
1032    
1033     if (n == 0) { /* signal to close file and clean up */
1034     if (viewfp != NULL) {
1035     fclose(viewfp);
1036     viewfp = NULL;
1037     viewnum = 0;
1038 schorsch 2.40 curview = stdview;
1039 greg 2.1 }
1040     return(NULL);
1041     }
1042 gwlarson 2.24 if (viewfp == NULL) { /* open file */
1043 greg 2.1 if ((viewfp = fopen(vval(VIEWFILE), "r")) == NULL) {
1044     perror(vval(VIEWFILE));
1045     quit(1);
1046     }
1047 gwlarson 2.24 } else if (n > 0 && n < viewnum) { /* rewind file */
1048 greg 2.8 if (viewnum == 1 && feof(viewfp))
1049     return(&curview); /* just one view */
1050 greg 2.1 if (fseek(viewfp, 0L, 0) == EOF) {
1051     perror(vval(VIEWFILE));
1052     quit(1);
1053     }
1054 schorsch 2.40 curview = stdview;
1055 greg 2.1 viewnum = 0;
1056     }
1057 gwlarson 2.24 if (n < 0) { /* get next view */
1058     register int c = getc(viewfp);
1059     if (c == EOF)
1060     return((VIEW *)NULL); /* that's it */
1061     ungetc(c, viewfp);
1062     n = viewnum + 1;
1063     }
1064 greg 2.1 while (n > viewnum) { /* scan to desired view */
1065     if (fgets(linebuf, sizeof(linebuf), viewfp) == NULL)
1066 greg 2.15 return(viewnum==1 ? &curview : (VIEW *)NULL);
1067 greg 2.1 if (isview(linebuf) && sscanview(&curview, linebuf) > 0)
1068     viewnum++;
1069     }
1070     return(&curview); /* return it */
1071     }
1072    
1073    
1074     int
1075     countviews() /* count views in view file */
1076     {
1077 gwlarson 2.24 int n;
1078 greg 2.1
1079 gwlarson 2.24 if (getview(n=1) == NULL)
1080     return(0);
1081     while (getview(-1) != NULL)
1082 greg 2.1 n++;
1083     return(n);
1084     }
1085    
1086    
1087     char *
1088     getexp(n) /* get exposure for nth frame */
1089     int n;
1090     {
1091     extern char *fskip();
1092     static char expval[32];
1093     static FILE *expfp = NULL;
1094     static long *exppos;
1095     static int curfrm;
1096     register char *cp;
1097    
1098     if (n == 0) { /* signal to close file */
1099     if (expfp != NULL) {
1100     fclose(expfp);
1101 greg 2.29 free((void *)exppos);
1102 greg 2.1 expfp = NULL;
1103     }
1104     return(NULL);
1105 greg 2.14 } else if (n > vint(END)) /* request past end (error?) */
1106     return(NULL);
1107 greg 2.1 if (!vdef(EXPOSURE)) /* no setting (auto) */
1108     return(NULL);
1109     if (isflt(vval(EXPOSURE))) /* always the same */
1110     return(vval(EXPOSURE));
1111     if (expfp == NULL) { /* open exposure file */
1112     if ((expfp = fopen(vval(EXPOSURE), "r")) == NULL) {
1113     fprintf(stderr,
1114     "%s: cannot open exposure file \"%s\"\n",
1115     progname, vval(EXPOSURE));
1116     quit(1);
1117     }
1118     curfrm = vint(END) + 1; /* init lookup tab. */
1119     exppos = (long *)malloc(curfrm*sizeof(long *));
1120     if (exppos == NULL) {
1121     perror(progname);
1122     quit(1);
1123     }
1124     while (curfrm--)
1125     exppos[curfrm] = -1L;
1126     curfrm = 0;
1127     }
1128     /* find position in file */
1129     if (n-1 != curfrm && n != curfrm && exppos[n-1] >= 0 &&
1130     fseek(expfp, exppos[curfrm=n-1], 0) == EOF) {
1131     fprintf(stderr, "%s: seek error on exposure file\n", progname);
1132     quit(1);
1133     }
1134     while (n > curfrm) { /* read exposure */
1135     if (exppos[curfrm] < 0)
1136     exppos[curfrm] = ftell(expfp);
1137     if (fgets(expval, sizeof(expval), expfp) == NULL) {
1138     fprintf(stderr, "%s: too few exposures\n",
1139     vval(EXPOSURE));
1140     quit(1);
1141     }
1142     curfrm++;
1143     cp = fskip(expval); /* check format */
1144 greg 2.14 if (cp != NULL)
1145     while (isspace(*cp))
1146     *cp++ = '\0';
1147     if (cp == NULL || *cp) {
1148 greg 2.1 fprintf(stderr,
1149     "%s: exposure format error on line %d\n",
1150     vval(EXPOSURE), curfrm);
1151     quit(1);
1152     }
1153     }
1154     return(expval); /* return value */
1155     }
1156    
1157    
1158 greg 2.2 struct pslot *
1159     findpslot(pid) /* find or allocate a process slot */
1160     int pid;
1161     {
1162     register struct pslot *psempty = NULL;
1163     register int i;
1164    
1165     for (i = 0; i < npslots; i++) { /* look for match */
1166     if (pslot[i].pid == pid)
1167     return(pslot+i);
1168     if (psempty == NULL && pslot[i].pid == 0)
1169     psempty = pslot+i;
1170     }
1171     return(psempty); /* return emtpy slot (error if NULL) */
1172     }
1173    
1174    
1175     int
1176     donecom(ps, pn, status) /* clean up after finished process */
1177     PSERVER *ps;
1178     int pn;
1179     int status;
1180     {
1181     register PROC *pp;
1182 greg 2.18 register struct pslot *psl;
1183 greg 2.2
1184     pp = ps->proc + pn;
1185 greg 2.3 if (pp->elen) { /* pass errors */
1186 greg 2.2 if (ps->hostname[0])
1187 greg 2.3 fprintf(stderr, "%s: ", ps->hostname);
1188     fprintf(stderr, "Error output from: %s\n", pp->com);
1189 greg 2.2 fputs(pp->errs, stderr);
1190     fflush(stderr);
1191     if (ps->hostname[0])
1192     status = 1; /* because rsh doesn't return status */
1193     }
1194 greg 2.18 lastpserver = NULL;
1195     psl = findpslot(pp->pid); /* check for bruncom() slot */
1196     if (psl->pid) {
1197     if (status) {
1198     if (psl->rcvf != NULL) /* attempt recovery */
1199     status = (*psl->rcvf)(psl->fout);
1200     if (status) {
1201     fprintf(stderr,
1202     "%s: error rendering frame %d\n",
1203     progname, psl->fout);
1204     quit(1);
1205     }
1206     lastpserver = ps;
1207     }
1208     psl->pid = 0; /* free process slot */
1209     } else if (status)
1210     lastpserver = ps;
1211 greg 2.2 freestr(pp->com); /* free command string */
1212     return(status);
1213     }
1214    
1215    
1216     int
1217     serverdown() /* check status of last process server */
1218     {
1219 greg 2.18 if (lastpserver == NULL || !lastpserver->hostname[0])
1220     return(0);
1221 greg 2.2 if (pserverOK(lastpserver)) /* server still up? */
1222     return(0);
1223     delpserver(lastpserver); /* else delete it */
1224     if (pslist == NULL) {
1225     fprintf(stderr, "%s: all process servers are down\n",
1226     progname);
1227     quit(1);
1228     }
1229     return(1);
1230     }
1231    
1232    
1233     int
1234     bruncom(com, fout, rf) /* run a command in the background */
1235     char *com;
1236     int fout;
1237     int (*rf)();
1238     {
1239     int pid;
1240     register struct pslot *psl;
1241    
1242 greg 2.5 if (noaction) {
1243     if (!silent)
1244     printf("\t%s\n", com); /* echo command */
1245 greg 2.2 return(0);
1246 greg 2.5 }
1247 greg 2.18 com = savestr(com); /* else start it when we can */
1248     while ((pid = startjob(NULL, com, donecom)) == -1)
1249 greg 2.2 bwait(1);
1250 greg 2.5 if (!silent) { /* echo command */
1251 greg 2.3 PSERVER *ps;
1252     int psn = pid;
1253 greg 2.4 ps = findjob(&psn);
1254 greg 2.5 printf("\t%s\n", com);
1255 greg 2.4 printf("\tProcess started on %s\n", phostname(ps));
1256 greg 2.3 fflush(stdout);
1257     }
1258 greg 2.2 psl = findpslot(pid); /* record info. in appropriate slot */
1259     psl->pid = pid;
1260     psl->fout = fout;
1261     psl->rcvf = rf;
1262     return(pid);
1263     }
1264    
1265    
1266     bwait(ncoms) /* wait for batch job(s) to finish */
1267     int ncoms;
1268     {
1269     int status;
1270    
1271     if (noaction)
1272     return;
1273     while ((status = wait4job(NULL, -1)) != -1) {
1274 greg 2.18 serverdown(); /* update server status */
1275     if (--ncoms == 0)
1276     break; /* done enough */
1277 greg 2.2 }
1278     }
1279    
1280    
1281     int
1282 greg 2.4 pruncom(com, ppins, maxcopies) /* run a command in parallel over network */
1283     char *com, *ppins;
1284 greg 2.2 int maxcopies;
1285     {
1286     int retstatus = 0;
1287 greg 2.3 int hostcopies;
1288 greg 2.18 char buf[10240], *com1, *s;
1289 greg 2.2 int status;
1290 greg 2.17 int pfd;
1291     register int n;
1292 greg 2.2 register PSERVER *ps;
1293    
1294 greg 2.3 if (!silent)
1295 greg 2.6 printf("\t%s\n", com); /* echo command */
1296 greg 2.3 if (noaction)
1297 greg 2.2 return(0);
1298 greg 2.3 fflush(stdout);
1299 greg 2.2 /* start jobs on each server */
1300 greg 2.3 for (ps = pslist; ps != NULL; ps = ps->next) {
1301     hostcopies = 0;
1302 greg 2.4 if (maxcopies > 1 && ps->nprocs > 1 && ppins != NULL) {
1303 greg 2.17 strcpy(com1=buf, com); /* build -PP command */
1304 greg 2.4 sprintf(com1+(ppins-com), " -PP %s/%s.persist",
1305     vval(DIRECTORY), phostname(ps));
1306 greg 2.36 unlink(com1+(ppins-com)+5);
1307 greg 2.4 strcat(com1, ppins);
1308 greg 2.17 } else
1309 greg 2.4 com1 = com;
1310 greg 2.18 while (maxcopies > 0) {
1311     s = savestr(com1);
1312     if (startjob(ps, s, donecom) != -1) {
1313     sleep(20);
1314     hostcopies++;
1315     maxcopies--;
1316     } else {
1317     freestr(s);
1318     break;
1319     }
1320 greg 2.2 }
1321 greg 2.3 if (!silent && hostcopies) {
1322     if (hostcopies > 1)
1323     printf("\t%d duplicate processes", hostcopies);
1324     else
1325     printf("\tProcess");
1326 greg 2.4 printf(" started on %s\n", phostname(ps));
1327 greg 2.3 fflush(stdout);
1328     }
1329     }
1330 greg 2.2 /* wait for jobs to finish */
1331     while ((status = wait4job(NULL, -1)) != -1)
1332 greg 2.18 retstatus += status && !serverdown();
1333 greg 2.17 /* terminate parallel rpict's */
1334 greg 2.18 for (ps = pslist; ps != NULL; ps = ps->next) {
1335     sprintf(buf, "%s/%s.persist", vval(DIRECTORY), phostname(ps));
1336 greg 2.17 if ((pfd = open(buf, O_RDONLY)) >= 0) {
1337     n = read(pfd, buf, sizeof(buf)-1); /* get PID */
1338     buf[n] = '\0';
1339     close(pfd);
1340     for (n = 0; buf[n] && !isspace(buf[n]); n++)
1341     ;
1342     /* terminate */
1343     sprintf(buf, "kill -ALRM %d", atoi(buf+n));
1344 greg 2.18 wait4job(ps, startjob(ps, buf, NULL));
1345 greg 2.17 }
1346     }
1347 greg 2.2 return(retstatus);
1348     }
1349    
1350    
1351     runcom(cs) /* run a command locally and wait for it */
1352 greg 2.1 char *cs;
1353     {
1354     if (!silent) /* echo it */
1355     printf("\t%s\n", cs);
1356     if (noaction)
1357     return(0);
1358     fflush(stdout); /* flush output and pass to shell */
1359     return(system(cs));
1360     }
1361    
1362    
1363     rmfile(fn) /* remove a file */
1364     char *fn;
1365     {
1366     if (!silent)
1367 schorsch 2.37 #ifdef _WIN32
1368 greg 2.1 printf("\tdel %s\n", fn);
1369     #else
1370     printf("\trm -f %s\n", fn);
1371     #endif
1372     if (noaction)
1373     return(0);
1374     return(unlink(fn));
1375     }
1376    
1377    
1378     badvalue(vc) /* report bad variable value and exit */
1379     int vc;
1380     {
1381     fprintf(stderr, "%s: bad value for variable '%s'\n",
1382     progname, vnam(vc));
1383     quit(1);
1384 gwlarson 2.25 }
1385    
1386    
1387     char *
1388     dirfile(df, path) /* separate path into directory and file */
1389     char *df;
1390     register char *path;
1391     {
1392     register int i;
1393     int psep;
1394    
1395     for (i = 0, psep = -1; path[i]; i++)
1396     if (path[i] == '/')
1397     psep = i;
1398 schorsch 2.40 if (df != NULL) {
1399 gwlarson 2.25 if (psep == 0) {
1400     df[0] = '/';
1401     df[1] = '\0';
1402     } else if (psep > 0) {
1403     strncpy(df, path, psep);
1404     df[psep] = '\0';
1405     } else
1406     df[0] = '\0';
1407 schorsch 2.40 }
1408 gwlarson 2.25 return(path+psep+1);
1409 greg 2.29 }
1410    
1411    
1412     int
1413     getblur(double *bf) /* get # blur samples (and fraction) */
1414     {
1415     double blurf;
1416     int nblur;
1417     char *s;
1418    
1419     if (!vdef(MBLUR)) {
1420     if (bf != NULL)
1421     *bf = 0.0;
1422     return(0);
1423     }
1424     blurf = atof(vval(MBLUR));
1425     if (blurf < 0.0)
1426     blurf = 0.0;
1427     if (bf != NULL)
1428     *bf = blurf;
1429     if (blurf <= FTINY)
1430     return(0);
1431     s = sskip(vval(MBLUR));
1432     if (!*s)
1433     return(DEF_NBLUR);
1434     nblur = atoi(s);
1435     if (nblur <= 0)
1436     return(1);
1437     return(nblur);
1438 greg 2.1 }