--- ray/src/util/rad.c 2003/06/30 14:59:13 2.65 +++ ray/src/util/rad.c 2004/03/26 21:36:19 2.76 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rad.c,v 2.65 2003/06/30 14:59:13 schorsch Exp $"; +static const char RCSid[] = "$Id: rad.c,v 2.76 2004/03/26 21:36:19 schorsch Exp $"; #endif /* * Executive program for oconv, rpict and pfilt @@ -8,12 +8,24 @@ static const char RCSid[] = "$Id: rad.c,v 2.65 2003/06 #include "standard.h" #include +#include #include "platform.h" +#include "rtprocess.h" #include "view.h" #include "paths.h" #include "vars.h" +#ifdef _WIN32 + #define DELCMD "del" + #define RENAMECMD "rename" +#else + #define DELCMD "rm -f" + #define RENAMECMD "mv" + #include + #include +#endif + /* variables (alphabetical by name) */ #define AMBFILE 0 /* ambient file name */ #define DETAIL 1 /* level of scene detail */ @@ -80,7 +92,6 @@ char overfile[] = NULL_DEVICE; char overfile[] = "overture.unf"; #endif -extern time_t time(); time_t scenedate; /* date of latest scene or object file */ time_t octreedate; /* date of octree */ @@ -96,22 +107,62 @@ int nowarn = 0; /* no warnings */ int explicate = 0; /* explicate variables */ int silent = 0; /* do work silently */ int touchonly = 0; /* touch files only */ -int noaction = 0; /* don't do anything */ +int nprocs = 1; /* maximum executing processes */ int sayview = 0; /* print view out */ -char *rvdevice = NULL; /* rview output device */ +char *rvdevice = NULL; /* rvu output device */ char *viewselect = NULL; /* specific view only */ int overture = 0; /* overture calculation needed */ +int children_running = 0; /* set negative in children */ + char *progname; /* global argv[0] */ char *rifname; /* global rad input file name */ char radname[PATH_MAX]; /* root Radiance file name */ +#define inchild() (children_running < 0) -main(argc, argv) -int argc; -char *argv[]; +static void rootname(char *rn, char *fn); +static time_t checklast(char *fnames); +static char * newfname(char *orig, int pred); +static void checkfiles(void); +static void getoctcube(double org[3], double *sizp); +static void setdefaults(void); +static void oconv(void); +static char * addarg(char *op, char *arg); +static void oconvopts(char *oo); +static void mkillumopts(char *mo); +static void checkambfile(void); +static double ambval(void); +static void renderopts(char *op, char *po); +static void lowqopts(char *op, char *po); +static void medqopts(char *op, char *po); +static void hiqopts(char *op, char *po); +static void xferopts(char *ro); +static void pfiltopts(char *po); +static int matchword(char *s1, char *s2); +static char * specview(char *vs); +static char * getview(int n, char *vn); +static int myprintview(char *vopts, FILE *fp); +static void rvu(char *opts, char *po); +static void rpict(char *opts, char *po); +static int touch(char *fn); +static int runcom(char *cs); +static int rmfile(char *fn); +static int mvfile(char *fold, char *fnew); +static int next_process(void); +static void wait_process(int all); +static void finish_process(void); +static void badvalue(int vc); +static void syserr(char *s); + + +int +main( + int argc, + char *argv[] +) { char ropts[512]; char popts[64]; @@ -125,8 +176,13 @@ char *argv[]; silent++; break; case 'n': - noaction++; + nprocs = 0; break; + case 'N': + nprocs = atoi(argv[++i]); + if (nprocs < 0) + nprocs = 0; + break; case 't': touchonly++; break; @@ -151,6 +207,9 @@ char *argv[]; if (i >= argc) goto userr; rifname = argv[i]; + /* check command-line options */ + if ((nprocs > 1) & (viewselect != NULL)) + nprocs = 1; /* assign Radiance root file name */ rootname(radname, rifname); /* load variable values */ @@ -179,24 +238,28 @@ char *argv[]; renderopts(ropts, popts); xferopts(ropts); if (rvdevice != NULL) - rview(ropts, popts); + rvu(ropts, popts); else rpict(ropts, popts); quit(0); userr: fprintf(stderr, -"Usage: %s [-w][-s][-n][-t][-e][-V][-v view][-o dev] rfile [VAR=value ..]\n", +"Usage: %s [-w][-s][-n|-N npr][-t][-e][-V][-v view][-o dev] rfile [VAR=value ..]\n", progname); quit(1); + return 1; /* pro forma return */ } -rootname(rn, fn) /* remove tail from end of fn */ -register char *rn, *fn; +static void +rootname( /* remove tail from end of fn */ + register char *rn, + register char *fn +) { char *tp, *dp; - for (tp = NULL, dp = rn; *rn = *fn++; rn++) + for (tp = NULL, dp = rn; (*rn = *fn++); rn++) if (ISDIRSEP(*rn)) dp = rn; else if (*rn == '.') @@ -206,9 +269,10 @@ register char *rn, *fn; } -time_t -checklast(fnames) /* check files and find most recent */ -register char *fnames; +static time_t +checklast( /* check files and find most recent */ + register char *fnames +) { char thisfile[PATH_MAX]; time_t thisdate, lastdate = 0; @@ -228,10 +292,11 @@ register char *fnames; } -char * -newfname(orig, pred) /* create modified file name */ -char *orig; -int pred; +static char * +newfname( /* create modified file name */ + char *orig, + int pred +) { register char *cp; register int n; @@ -253,7 +318,8 @@ int pred; } -checkfiles() /* check for existence and modified times */ +static void +checkfiles(void) /* check for existence and modified times */ { time_t objdate; @@ -288,18 +354,20 @@ checkfiles() /* check for existence and modified tim } -getoctcube(org, sizp) /* get octree bounding cube */ -double org[3], *sizp; +static void +getoctcube( /* get octree bounding cube */ + double org[3], + double *sizp +) { - extern FILE *popen(); static double oorg[3], osiz = 0.; double min[3], max[3]; char buf[1024]; FILE *fp; register int i; - if (osiz <= FTINY) - if (noaction && fdate(oct1name) < + if (osiz <= FTINY) { + if (!nprocs && fdate(oct1name) < (scenedate>illumdate?scenedate:illumdate)) { /* run getbbox */ sprintf(buf, "getbbox -w -h %s", @@ -334,11 +402,13 @@ double org[3], *sizp; } pclose(fp); } + } org[0] = oorg[0]; org[1] = oorg[1]; org[2] = oorg[2]; *sizp = osiz; } -setdefaults() /* set default values for unassigned var's */ +static void +setdefaults(void) /* set default values for unassigned var's */ { double org[3], lim[3], size; char buf[128]; @@ -395,7 +465,8 @@ setdefaults() /* set default values for unassigned v } -oconv() /* run oconv and mkillum if necessary */ +static void +oconv(void) /* run oconv and mkillum if necessary */ { static char illumtmp[] = "ilXXXXXX"; char combuf[PATH_MAX], ocopts[64], mkopts[64]; @@ -427,11 +498,11 @@ oconv() /* run oconv and mkillum if necessary */ } if (oct1name == vval(OCTREE)) /* no mkillum? */ oct1date = octreedate > matdate ? octreedate : matdate; - if (oct1date >= octreedate & oct1date >= matdate - & oct1date >= illumdate) /* all done */ + if ((oct1date >= octreedate) & (oct1date >= matdate) + & (oct1date >= illumdate)) /* all done */ return; /* make octree0 */ - if (oct0date < scenedate | oct0date < illumdate) { + if ((oct0date < scenedate) | (oct0date < illumdate)) { if (touchonly && oct0date) touch(oct0name); else { /* build command */ @@ -497,19 +568,23 @@ oconv() /* run oconv and mkillum if necessary */ } -char * -addarg(op, arg) /* add argument and advance pointer */ -register char *op, *arg; +static char * +addarg( /* add argument and advance pointer */ +register char *op, +register char *arg +) { *op = ' '; - while (*++op = *arg++) + while ( (*++op = *arg++) ) ; return(op); } -oconvopts(oo) /* get oconv options */ -register char *oo; +static void +oconvopts( /* get oconv options */ + register char *oo +) { /* BEWARE: This may be called via setdefaults(), so no assumptions */ @@ -519,8 +594,10 @@ register char *oo; } -mkillumopts(mo) /* get mkillum options */ -register char *mo; +static void +mkillumopts( /* get mkillum options */ + register char *mo +) { /* BEWARE: This may be called via setdefaults(), so no assumptions */ @@ -530,7 +607,8 @@ register char *mo; } -checkambfile() /* check date on ambient file */ +static void +checkambfile(void) /* check date on ambient file */ { time_t afdate; @@ -538,16 +616,17 @@ checkambfile() /* check date on ambient file */ return; if (!(afdate = fdate(vval(AMBFILE)))) return; - if (oct1date > afdate) + if (oct1date > afdate) { if (touchonly) touch(vval(AMBFILE)); else rmfile(vval(AMBFILE)); + } } -double -ambval() /* compute ambient value */ +static double +ambval(void) /* compute ambient value */ { if (vdef(EXPOSURE)) { if (vval(EXPOSURE)[0] == '+' || vval(EXPOSURE)[0] == '-') @@ -559,11 +638,15 @@ ambval() /* compute ambient value */ if (vlet(ZONE) == 'I') return(.01); badvalue(ZONE); + return 0; /* pro forma return */ } -renderopts(op, po) /* set rendering options */ -char *op, *po; +static void +renderopts( /* set rendering options */ + char *op, + char *po +) { switch(vscale(QUALITY)) { case LOW: @@ -579,9 +662,11 @@ char *op, *po; } -lowqopts(op, po) /* low quality rendering options */ -register char *op; -char *po; +static void +lowqopts( /* low quality rendering options */ + register char *op, + char *po +) { double d, org[3], siz[3]; @@ -591,7 +676,7 @@ char *po; &siz[0], &org[1], &siz[1], &org[2], &siz[2]) != 6) badvalue(ZONE); siz[0] -= org[0]; siz[1] -= org[1]; siz[2] -= org[2]; - if (siz[0] <= FTINY | siz[1] <= FTINY | siz[2] <= FTINY) + if ((siz[0] <= FTINY) | (siz[1] <= FTINY) | (siz[2] <= FTINY)) badvalue(ZONE); getoctcube(org, &d); d *= 3./(siz[0]+siz[1]+siz[2]); @@ -599,19 +684,19 @@ char *po; case LOW: po = addarg(po, "-ps 16"); op = addarg(op, "-dp 64"); - sprintf(op, " -ar %d", (int)(4*d)); + sprintf(op, " -ar %d", (int)(8*d)); op += strlen(op); break; case MEDIUM: po = addarg(po, "-ps 8"); op = addarg(op, "-dp 128"); - sprintf(op, " -ar %d", (int)(8*d)); + sprintf(op, " -ar %d", (int)(16*d)); op += strlen(op); break; case HIGH: po = addarg(po, "-ps 4"); op = addarg(op, "-dp 256"); - sprintf(op, " -ar %d", (int)(16*d)); + sprintf(op, " -ar %d", (int)(32*d)); op += strlen(op); break; } @@ -628,28 +713,30 @@ char *po; overture = 0; switch (vscale(VARIABILITY)) { case LOW: - op = addarg(op, "-aa .4 -ad 64"); + op = addarg(op, "-aa .3 -ad 256"); break; case MEDIUM: - op = addarg(op, "-aa .3 -ad 128"); + op = addarg(op, "-aa .25 -ad 512"); break; case HIGH: - op = addarg(op, "-aa .25 -ad 256"); + op = addarg(op, "-aa .2 -ad 1024"); break; } op = addarg(op, "-as 0"); d = ambval(); sprintf(op, " -av %.2g %.2g %.2g", d, d, d); op += strlen(op); - op = addarg(op, "-lr 3 -lw .02"); + op = addarg(op, "-lr 6 -lw .01"); if (vdef(RENDER)) op = addarg(op, vval(RENDER)); } -medqopts(op, po) /* medium quality rendering options */ -register char *op; -char *po; +static void +medqopts( /* medium quality rendering options */ + register char *op, + char *po +) { double d, org[3], siz[3], asz; @@ -659,7 +746,7 @@ char *po; &siz[0], &org[1], &siz[1], &org[2], &siz[2]) != 6) badvalue(ZONE); siz[0] -= org[0]; siz[1] -= org[1]; siz[2] -= org[2]; - if (siz[0] <= FTINY | siz[1] <= FTINY | siz[2] <= FTINY) + if ((siz[0] <= FTINY) | (siz[1] <= FTINY) | (siz[2] <= FTINY)) badvalue(ZONE); getoctcube(org, &d); asz = (siz[0]+siz[1]+siz[2])/3.; @@ -668,7 +755,7 @@ char *po; case LOW: po = addarg(po, vbool(PENUMBRAS) ? "-ps 4" : "-ps 8"); op = addarg(op, "-dp 256"); - sprintf(op, " -ar %d", (int)(8*d)); + sprintf(op, " -ar %d", (int)(16*d)); op += strlen(op); sprintf(op, " -ms %.2g", asz/20.); op += strlen(op); @@ -676,7 +763,7 @@ char *po; case MEDIUM: po = addarg(po, vbool(PENUMBRAS) ? "-ps 3" : "-ps 6"); op = addarg(op, "-dp 512"); - sprintf(op, " -ar %d", (int)(16*d)); + sprintf(op, " -ar %d", (int)(32*d)); op += strlen(op); sprintf(op, " -ms %.2g", asz/40.); op += strlen(op); @@ -684,7 +771,7 @@ char *po; case HIGH: po = addarg(po, vbool(PENUMBRAS) ? "-ps 2" : "-ps 4"); op = addarg(op, "-dp 1024"); - sprintf(op, " -ar %d", (int)(32*d)); + sprintf(op, " -ar %d", (int)(64*d)); op += strlen(op); sprintf(op, " -ms %.2g", asz/80.); op += strlen(op); @@ -696,7 +783,7 @@ char *po; else op = addarg(op, "-ds .3"); op = addarg(op, "-dt .1 -dc .5 -dr 1 -sj .7 -st .1"); - if (overture = vint(INDIRECT)) { + if ( (overture = vint(INDIRECT)) ) { sprintf(op, " -ab %d", overture); op += strlen(op); } @@ -707,27 +794,29 @@ char *po; overture = 0; switch (vscale(VARIABILITY)) { case LOW: - op = addarg(op, "-aa .25 -ad 196 -as 0"); + op = addarg(op, "-aa .2 -ad 329 -as 42"); break; case MEDIUM: - op = addarg(op, "-aa .2 -ad 400 -as 64"); + op = addarg(op, "-aa .15 -ad 800 -as 128"); break; case HIGH: - op = addarg(op, "-aa .15 -ad 768 -as 196"); + op = addarg(op, "-aa .1 -ad 1536 -as 392"); break; } d = ambval(); sprintf(op, " -av %.2g %.2g %.2g", d, d, d); op += strlen(op); - op = addarg(op, "-lr 6 -lw .002"); + op = addarg(op, "-lr 8 -lw .002"); if (vdef(RENDER)) op = addarg(op, vval(RENDER)); } -hiqopts(op, po) /* high quality rendering options */ -register char *op; -char *po; +static void +hiqopts( /* high quality rendering options */ + register char *op, + char *po +) { double d, org[3], siz[3], asz; @@ -737,7 +826,7 @@ char *po; &siz[0], &org[1], &siz[1], &org[2], &siz[2]) != 6) badvalue(ZONE); siz[0] -= org[0]; siz[1] -= org[1]; siz[2] -= org[2]; - if (siz[0] <= FTINY | siz[1] <= FTINY | siz[2] <= FTINY) + if ((siz[0] <= FTINY) | (siz[1] <= FTINY) | (siz[2] <= FTINY)) badvalue(ZONE); getoctcube(org, &d); asz = (siz[0]+siz[1]+siz[2])/3.; @@ -746,7 +835,7 @@ char *po; case LOW: po = addarg(po, vbool(PENUMBRAS) ? "-ps 1" : "-ps 8"); op = addarg(op, "-dp 1024"); - sprintf(op, " -ar %d", (int)(16*d)); + sprintf(op, " -ar %d", (int)(32*d)); op += strlen(op); sprintf(op, " -ms %.2g", asz/40.); op += strlen(op); @@ -754,7 +843,7 @@ char *po; case MEDIUM: po = addarg(po, vbool(PENUMBRAS) ? "-ps 1" : "-ps 5"); op = addarg(op, "-dp 2048"); - sprintf(op, " -ar %d", (int)(32*d)); + sprintf(op, " -ar %d", (int)(64*d)); op += strlen(op); sprintf(op, " -ms %.2g", asz/80.); op += strlen(op); @@ -762,7 +851,7 @@ char *po; case HIGH: po = addarg(po, vbool(PENUMBRAS) ? "-ps 1" : "-ps 3"); op = addarg(op, "-dp 4096"); - sprintf(op, " -ar %d", (int)(64*d)); + sprintf(op, " -ar %d", (int)(128*d)); op += strlen(op); sprintf(op, " -ms %.2g", asz/160.); op += strlen(op); @@ -783,13 +872,13 @@ char *po; overture = 0; switch (vscale(VARIABILITY)) { case LOW: - op = addarg(op, "-aa .15 -ad 256 -as 0"); + op = addarg(op, "-aa .125 -ad 512 -as 64"); break; case MEDIUM: - op = addarg(op, "-aa .125 -ad 512 -as 256"); + op = addarg(op, "-aa .1 -ad 1536 -as 768"); break; case HIGH: - op = addarg(op, "-aa .08 -ad 1024 -as 512"); + op = addarg(op, "-aa .075 -ad 4096 -as 2048"); break; } d = ambval(); @@ -801,8 +890,10 @@ char *po; } -xferopts(ro) /* transfer options if indicated */ -char *ro; +static void +xferopts( /* transfer options if indicated */ + char *ro +) { int fd, n; register char *cp; @@ -832,8 +923,10 @@ char *ro; } -pfiltopts(po) /* get pfilt options */ -register char *po; +static void +pfiltopts( /* get pfilt options */ + register char *po +) { *po = '\0'; if (vdef(EXPOSURE)) { @@ -853,8 +946,11 @@ register char *po; } -matchword(s1, s2) /* match white-delimited words */ -register char *s1, *s2; +static int +matchword( /* match white-delimited words */ + register char *s1, + register char *s2 +) { while (isspace(*s1)) s1++; while (isspace(*s2)) s2++; @@ -865,9 +961,10 @@ register char *s1, *s2; } -char * -specview(vs) /* get proper view spec from vs */ -register char *vs; +static char * +specview( /* get proper view spec from vs */ + register char *vs +) { static char vup[7][12] = {"-vu 0 0 -1","-vu 0 -1 0","-vu -1 0 0", "-vu 0 0 1", "-vu 1 0 0","-vu 0 1 0","-vu 0 0 1"}; @@ -885,7 +982,7 @@ register char *vs; upax = 1-'X'+UPPER(vval(UP)[1]); else upax = 1-'X'+vlet(UP); - if (upax < 1 | upax > 3) + if ((upax < 1) | (upax > 3)) badvalue(UP); if (vval(UP)[0] == '-') upax = -upax; @@ -908,7 +1005,7 @@ register char *vs; zpos = -1; vs++; } viewtype = 'v'; - if (*vs == 'v' | *vs == 'l' | *vs == 'a' | *vs == 'h' | *vs == 'c') + if((*vs == 'v') | (*vs == 'l') | (*vs == 'a') | (*vs == 'h') | (*vs == 'c')) viewtype = *vs++; cp = viewopts; if ((!*vs || isspace(*vs)) && (xpos|ypos|zpos)) { /* got one! */ @@ -989,10 +1086,11 @@ register char *vs; } -char * -getview(n, vn) /* get view n, or NULL if none */ -int n; -char *vn; /* returned view name */ +static char * +getview( /* get view n, or NULL if none */ + int n, + char *vn /* returned view name */ +) { register char *mv; @@ -1019,7 +1117,7 @@ char *vn; /* returned view name */ return(specview(viewselect)); /* standard view? */ } mv = nvalue(VIEWS, n); /* use view n */ - if (vn != NULL & mv != NULL) { + if ((vn != NULL) & (mv != NULL)) { register char *mv2 = mv; if (*mv2 != '-') while (*mv2 && !isspace(*mv2)) @@ -1030,13 +1128,15 @@ char *vn; /* returned view name */ } -printview(vopts) /* print out selected view */ -register char *vopts; +static int +myprintview( /* print out selected view */ + register char *vopts, + FILE *fp +) { VIEW vwr; char buf[128]; register char *cp; -again: if (vopts == NULL) return(-1); #ifdef _WIN32 @@ -1045,22 +1145,25 @@ again: goto again; } #endif - copystruct(&vwr, &stdview); + vwr = stdview; sscanview(&vwr, cp=vopts); /* set initial options */ while ((cp = strstr(cp, "-vf ")) != NULL && *atos(buf, sizeof(buf), cp += 4)) { viewfile(buf, &vwr, NULL); /* load -vf file */ sscanview(&vwr, cp); /* reset tail */ } - fputs(VIEWSTR, stdout); - fprintview(&vwr, stdout); /* print full spec. */ - fputc('\n', stdout); + fputs(VIEWSTR, fp); + fprintview(&vwr, fp); /* print full spec. */ + fputc('\n', fp); return(0); } -rview(opts, po) /* run rview with first view */ -char *opts, *po; +static void +rvu( /* run rvu with first view */ + char *opts, + char *po +) { char *vw; char combuf[PATH_MAX]; @@ -1068,29 +1171,34 @@ char *opts, *po; if (touchonly || (vw = getview(0, NULL)) == NULL) return; if (sayview) - printview(vw); - sprintf(combuf, "rview %s%s%s -R %s ", vw, po, opts, rifname); + myprintview(vw, stdout); + sprintf(combuf, "rvu %s%s%s -R %s ", vw, po, opts, rifname); if (rvdevice != NULL) sprintf(combuf+strlen(combuf), "-o %s ", rvdevice); if (vdef(EXPOSURE)) sprintf(combuf+strlen(combuf), "-pe %s ", vval(EXPOSURE)); strcat(combuf, oct1name); if (runcom(combuf)) { /* run it */ - fprintf(stderr, "%s: error running rview\n", progname); + fprintf(stderr, "%s: error running rvu\n", progname); quit(1); } } -rpict(opts, po) /* run rpict and pfilt for each view */ -char *opts, *po; +static void +rpict( /* run rpict and pfilt for each view */ + char *opts, + char *po +) { char combuf[PATH_MAX]; char rawfile[PATH_MAX], picfile[PATH_MAX]; char zopt[PATH_MAX+4], rep[PATH_MAX+16], res[32]; + char rppopt[128], *pfile = NULL; char pfopts[128]; char vs[32], *vw; int vn, mult; + FILE *fp; time_t rfdt, pfdt; /* get pfilt options */ pfiltopts(pfopts); @@ -1132,11 +1240,17 @@ char *opts, *po; else badvalue(REPORT); } - /* do each view */ - vn = 0; + /* set up parallel rendering */ + if ((nprocs > 1) & (!vdef(ZFILE))) { + strcpy(rppopt, "-S 1 -PP pfXXXXXX"); + pfile = rppopt+9; + if (mktemp(pfile) == NULL) + pfile = NULL; + } + vn = 0; /* do each view */ while ((vw = getview(vn++, vs)) != NULL) { if (sayview) - printview(vw); + myprintview(vw, stdout); if (!vs[0]) sprintf(vs, "%d", vn); sprintf(picfile, "%s_%s.pic", vval(PICTURE), vs); @@ -1160,11 +1274,19 @@ char *opts, *po; touch(picfile); continue; } + if (next_process()) { /* parallel running? */ + if (pfile != NULL) + sleep(20); + continue; + } + /* XXX Remember to call finish_process() */ /* build rpict command */ - if (rfdt >= oct1date) /* recover */ + if (rfdt >= oct1date) { /* recover */ sprintf(combuf, "rpict%s%s%s%s -ro %s %s", rep, po, opts, zopt, rawfile, oct1name); - else { + if (runcom(combuf)) /* run rpict */ + goto rperror; + } else { if (overture) { /* run overture calculation */ sprintf(combuf, "rpict%s %s%s -x 64 -y 64 -ps 1 %s > %s", @@ -1181,14 +1303,27 @@ char *opts, *po; #endif } sprintf(combuf, "rpict%s %s %s%s%s%s %s > %s", - rep, vw, res, po, opts, zopt, - oct1name, rawfile); + rep, vw, res, po, opts, + zopt, oct1name, rawfile); + if (pfile != NULL && inchild()) { + /* rpict persistent mode */ + if (!silent) + printf("\t%s\n", combuf); + sprintf(combuf, "rpict%s %s %s%s%s %s > %s", + rep, rppopt, res, po, opts, + oct1name, rawfile); + fflush(stdout); + fp = popen(combuf, "w"); + if (fp == NULL) + goto rperror; + myprintview(vw, fp); + if (pclose(fp)) + goto rperror; + } else { /* rpict normal mode */ + if (runcom(combuf)) + goto rperror; + } } - if (runcom(combuf)) { /* run rpict */ - fprintf(stderr, "%s: error rendering view %s\n", - progname, vs); - quit(1); - } if (!vdef(RAWFILE) || strcmp(vval(RAWFILE),vval(PICTURE))) { /* build pfilt command */ if (mult > 1) @@ -1197,7 +1332,7 @@ char *opts, *po; else sprintf(combuf, "pfilt%s %s > %s", pfopts, rawfile, picfile); - if (runcom(combuf)) { /* run pfilt */ + if (runcom(combuf)) { /* run pfilt */ fprintf(stderr, "%s: error filtering view %s\n\t%s removed\n", progname, vs, picfile); @@ -1211,16 +1346,34 @@ char *opts, *po; mvfile(rawfile, combuf); } else rmfile(rawfile); + finish_process(); /* exit if child */ } + wait_process(1); /* wait for children to finish */ + if (pfile != NULL) { /* clean up rpict persistent mode */ + int pid; + fp = fopen(pfile, "r"); + if (fp != NULL) { + if (fscanf(fp, "%*s %d", &pid) != 1 || + kill(pid, 1) < 0) + unlink(pfile); + fclose(fp); + } + } + return; +rperror: + fprintf(stderr, "%s: error rendering view %s\n", progname, vs); + quit(1); } -touch(fn) /* update a file */ -char *fn; +static int +touch( /* update a file */ + char *fn +) { if (!silent) printf("\ttouch %s\n", fn); - if (noaction) + if (!nprocs) return(0); #ifdef notused if (access(fn, F_OK) == -1) /* create it */ @@ -1231,48 +1384,133 @@ char *fn; } -runcom(cs) /* run command */ -char *cs; +static int +runcom( /* run command */ + char *cs +) { if (!silent) /* echo it */ printf("\t%s\n", cs); - if (noaction) + if (!nprocs) return(0); fflush(stdout); /* flush output and pass to shell */ return(system(cs)); } -rmfile(fn) /* remove a file */ -char *fn; +static int +rmfile( /* remove a file */ + char *fn +) { if (!silent) -#ifdef _WIN32 - printf("\tdel %s\n", fn); -#else - printf("\trm -f %s\n", fn); -#endif - if (noaction) + printf("\t%s %s\n", DELCMD, fn); + if (!nprocs) return(0); return(unlink(fn)); } -mvfile(fold, fnew) /* move a file */ -char *fold, *fnew; +static int +mvfile( /* move a file */ + char *fold, + char *fnew +) { if (!silent) -#ifdef _WIN32 - printf("\trename %s %s\n", fold, fnew); -#else - printf("\tmv %s %s\n", fold, fnew); -#endif - if (noaction) + printf("\t%s %s %s\n", RENAMECMD, fold, fnew); + if (!nprocs) return(0); return(rename(fold, fnew)); } +#ifdef RHAS_FORK_EXEC +static int +next_process(void) /* fork the next process (max. nprocs) */ +{ + int child_pid; + + if (nprocs <= 1) + return(0); /* it's us or no one */ + if (inchild()) { + fprintf(stderr, "%s: internal error 1 in next_process()\n", + progname); + quit(1); + } + if (children_running >= nprocs) + wait_process(0); /* wait for someone to finish */ + fflush(stdout); + child_pid = fork(); /* split process */ + if (child_pid == 0) { /* we're the child */ + children_running = -1; + return(0); + } + if (child_pid > 0) { /* we're the parent */ + ++children_running; + return(1); + } + fprintf(stderr, "%s: warning -- fork() failed\n", progname); + return(0); +} + +static void +wait_process( /* wait for process(es) to finish */ + int all +) +{ + int ourstatus = 0; + int pid, status; + + if (all) + all = children_running; + else if (children_running > 0) + all = 1; + while (all-- > 0) { + pid = wait(&status); + if (pid < 0) + syserr(progname); + status = status>>8 & 0xff; + --children_running; + if (status != 0) { /* child's problem is our problem */ + if ((ourstatus == 0) & (children_running > 0)) + fprintf(stderr, "%s: waiting for remaining processes\n", + progname); + ourstatus = status; + all = children_running; + } + } + if (ourstatus != 0) + quit(ourstatus); /* bad status from child */ +} +#else /* ! RHAS_FORK_EXEC */ +static int +next_process(void) +{ + return(0); /* cannot start new process */ +} +static void +wait_process(all) +int all; +{ + (void)all; /* no one to wait for */ +} +int +kill(pid, sig) /* win|unix_process.c should also wait and kill */ +int pid, sig; +{ + return 0; +} +#endif /* ! RHAS_FORK_EXEC */ + +static void +finish_process(void) /* exit a child process */ +{ + if (!inchild()) + return; /* in parent -- noop */ + exit(0); +} + #ifdef _WIN32 setenv(vname, value) /* set an environment variable */ char *vname, *value; @@ -1293,8 +1531,10 @@ char *vname, *value; #endif -badvalue(vc) /* report bad variable value and exit */ -int vc; +static void +badvalue( /* report bad variable value and exit */ + int vc +) { fprintf(stderr, "%s: bad value for variable '%s'\n", progname, vnam(vc)); @@ -1302,8 +1542,10 @@ int vc; } -syserr(s) /* report a system error and exit */ -char *s; +static void +syserr( /* report a system error and exit */ + char *s +) { perror(s); quit(1);