ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/ranimate.c
(Generate patch)

Comparing ray/src/util/ranimate.c (file contents):
Revision 2.1 by greg, Fri Jan 12 12:16:17 1996 UTC vs.
Revision 2.2 by greg, Thu Jan 18 11:25:11 1996 UTC

# Line 9 | Line 9 | static char SCCSid[] = "$SunId$ LBL";
9   */
10  
11   #include "standard.h"
12 + #include <ctype.h>
13   #include <sys/types.h>
14   #include <sys/stat.h>
15   #include "view.h"
16   #include "vars.h"
17 + #include "netproc.h"
18                                  /* input variables */
19   #define HOST            0               /* rendering host machine */
20   #define RENDER          1               /* rendering options */
# Line 87 | Line 89 | char   rresopt[32];            /* rendering resolution options */
89   char    fresopt[32];            /* filter resolution options */
90   int     pfiltalways;            /* always use pfilt? */
91  
92 + struct pslot {
93 +        int     pid;                    /* process ID (0 if empty) */
94 +        int     fout;                   /* output frame number */
95 +        int     (*rcvf)();              /* recover function */
96 + }       *pslot;                 /* process slots */
97 + int     npslots;                /* number of process slots */
98 +
99 + int     lastpid;                /* ID of last completed background process */
100 + PSERVER *lastpserver;           /* last process server used */
101 +
102 + struct pslot    *findpslot();
103 +
104   VIEW    *getview();
105   char    *getexp();
106  
# Line 138 | Line 152 | char   *argv[];
152                                                  /* print variables */
153          if (explicate)
154                  printvars(stdout);
155 +                                                /* set up process servers */
156 +        sethosts();
157                                                  /* run animation */
158          animate();
159                                                  /* all done */
# Line 145 | Line 161 | char   *argv[];
161                  argv[i] = vval(NEXTANIM);       /* just change input file */
162                  if (!silent)
163                          printargs(argc, argv, stdout);
164 <                if (!noaction) {
165 <                        execvp(progname, argv);         /* pass to next */
150 <                        quit(1);                        /* shouldn't return */
151 <                }
164 >                execvp(progname, argv);         /* pass to next */
165 >                quit(1);                        /* shouldn't return */
166          }
167          quit(0);
168   userr:
# Line 222 | Line 236 | putastat()                     /* put out current status */
236          char    buf[256];
237          FILE    *fp;
238  
239 +        if (noaction)
240 +                return;
241          sprintf(buf, "%s/%s", vval(DIRECTORY), SFNAME);
242          if ((fp = fopen(buf, "w")) == NULL) {
243                  perror(buf);
# Line 263 | Line 279 | setdefaults()                  /* set default values */
279   {
280          char    buf[256];
281  
282 <        if (vdef(OCTREE) == vdef(ANIMATE)) {
282 >        if (vdef(ANIMATE)) {
283 >                vval(OCTREE) = NULL;
284 >                vdef(OCTREE) = 0;
285 >        } else if (!vdef(OCTREE)) {
286                  fprintf(stderr, "%s: either %s or %s must be defined\n",
287                                  progname, vnam(OCTREE), vnam(ANIMATE));
288                  quit(1);
# Line 272 | Line 291 | setdefaults()                  /* set default values */
291                  fprintf(stderr, "%s: %s undefined\n", progname, vnam(VIEWFILE));
292                  quit(1);
293          }
294 +        if (!vdef(HOST)) {
295 +                vval(HOST) = LHOSTNAME;
296 +                vdef(HOST)++;
297 +        }
298          if (!vdef(START)) {
299                  vval(START) = "1";
300                  vdef(START)++;
# Line 320 | Line 343 | setdefaults()                  /* set default values */
343   }
344  
345  
346 + sethosts()                      /* set up process servers */
347 + {
348 +        extern char     *iskip();
349 +        char    buf[256], *dir, *uname;
350 +        int     np;
351 +        register char   *cp;
352 +        int     i;
353 +
354 +        npslots = 0;
355 +        if (noaction)
356 +                return;
357 +        for (i = 0; i < vdef(HOST); i++) {      /* add each host */
358 +                dir = uname = NULL;
359 +                np = 1;
360 +                strcpy(cp=buf, nvalue(HOST, i));        /* copy to buffer */
361 +                cp = sskip(cp);                         /* skip host name */
362 +                while (isspace(*cp))
363 +                        *cp++ = '\0';
364 +                if (*cp) {                              /* has # processes? */
365 +                        np = atoi(cp);
366 +                        if ((cp = iskip(cp)) == NULL || (*cp && !isspace(*cp)))
367 +                                badvalue(HOST);
368 +                        while (isspace(*cp))
369 +                                cp++;
370 +                        if (*cp) {                      /* has directory? */
371 +                                dir = cp;
372 +                                cp = sskip(cp);                 /* skip dir. */
373 +                                while (isspace(*cp))
374 +                                        *cp++ = '\0';
375 +                                if (*cp) {                      /* has user? */
376 +                                        uname = cp;
377 +                                        if (*sskip(cp))
378 +                                                badvalue(HOST);
379 +                                }
380 +                        }
381 +                }
382 +                if (addpserver(buf, dir, uname, np) == NULL) {
383 +                        if (!nowarn)
384 +                                fprintf(stderr,
385 +                                        "%s: cannot execute on host \"%s\"\n",
386 +                                                progname, buf);
387 +                } else
388 +                        npslots += np;
389 +        }
390 +        if (npslots == 0) {
391 +                fprintf(stderr, "%s: no working process servers\n", progname);
392 +                quit(1);
393 +        }
394 +        pslot = (struct pslot *)calloc(npslots, sizeof(struct pslot));
395 +        if (pslot == NULL) {
396 +                perror("malloc");
397 +                quit(1);
398 +        }
399 + }
400 +
401 +
402   getradfile(rfname)              /* run rad and get needed variables */
403   char    *rfname;
404   {
# Line 406 | Line 485 | animate()                      /* run animation */
485                  astat.rnext = astat.fnext = astat.tnext = vint(START);
486          putastat();
487                                          /* render in batches */
488 <        while (astat.rnext <= vint(END)) {
488 >        while (astat.tnext <= vint(END)) {
489                  renderframes(frames_batch);
490                  filterframes();
491                  transferframes();
# Line 466 | Line 545 | int    nframes;
545                  }
546          }
547          if (vdef(ANIMATE))              /* wait for renderings to finish */
548 <                animwait(0);
548 >                bwait(0);
549          else {                          /* else if walk-through */
550                  fclose(fp);             /* close view file */
551                  walkwait(astat.rnext, lastframe, vfname);       /* walk it */
552                  unlink(vfname);         /* remove view file */
553          }
475        if (vdef(ARCHIVE))              /* archive results */
476                archive(astat.rnext, lastframe);
554          astat.rnext = i;                /* update status */
555          putastat();
556   }
# Line 494 | Line 571 | filterframes()                         /* catch up with filtering */
571                                          progname, i);
572                          quit(1);
573                  }
574 <                dofilt(i, vp, getexp(i));               /* filter frame */
574 >                dofilt(i, vp, getexp(i), 0);            /* filter frame */
575          }
576 <        filtwait(0);                    /* wait for filter processes */
576 >        bwait(0);                       /* wait for filter processes */
577 >        archive(astat.fnext, i-1);      /* archive originals */
578          astat.fnext = i;                /* update status */
579          putastat();
580   }
# Line 539 | Line 617 | animrend(frame, vp)                    /* start animation frame */
617   int     frame;
618   VIEW    *vp;
619   {
620 +        extern int      recover();
621          char    combuf[2048];
622          char    fname[128];
623  
# Line 546 | Line 625 | VIEW   *vp;
625          strcat(fname, ".unf");
626          if (access(fname, F_OK) == 0)
627                  return;
628 <        sprintf(combuf, "%s %d | rpict%s%s %s > %s", vval(ANIMATE), frame,
628 >        sprintf(combuf, "%s %d | rpict%s%s -w0 %s > %s", vval(ANIMATE), frame,
629                          rendopt, viewopt(vp), rresopt, fname);
630 <        if (runcom(combuf)) {
552 <                fprintf(stderr, "%s: error rendering frame %d\n",
553 <                                progname, frame);
554 <                quit(1);
555 <        }
630 >        bruncom(combuf, frame, recover);        /* run in background */
631   }
632  
633  
559 animwait(nwait)                         /* wait for renderings to finish */
560 int     nwait;
561 {
562        /* currently does nothing since parallel rendering not working */
563 }
564
565
634   walkwait(first, last, vfn)              /* walk-through frames */
635   int     first, last;
636   char    *vfn;
# Line 578 | Line 646 | char   *vfn;
646                                  close(open(combuf, O_RDONLY|O_CREAT, 0666));
647                          }
648                                          /* create command */
649 <        sprintf(combuf, "rpict%s ", rendopt);
649 >        sprintf(combuf, "rpict%s -w0 ", rendopt);
650          if (vint(INTERP) || atoi(vval(MBLUR)))
651                  sprintf(combuf+strlen(combuf), "-z %s.zbf ", vval(BASENAME));
652          sprintf(combuf+strlen(combuf), "-o %s.unf %s -S %d %s < %s",
653                          vval(BASENAME), rresopt, first, vval(OCTREE), vfn);
654 <        if (runcom(combuf)) {
655 <                fprintf(stderr,
656 <                "%s: error rendering walk-through frames %d through %d\n",
654 >                                        /* run in parallel */
655 >        if (pruncom(combuf, (last-first+1)/(vint(INTERP)+1))) {
656 >                fprintf(stderr, "%s: error rendering frames %d through %d\n",
657                                  progname, first, last);
658                  quit(1);
659          }
# Line 599 | Line 667 | char   *vfn;
667   }
668  
669  
670 + int
671   recover(frame)                          /* recover the specified frame */
672   int     frame;
673   {
674 +        static int      *rfrm;          /* list of recovered frames */
675 +        static int      nrfrms = 0;
676          char    combuf[2048];
677          char    fname[128];
678          register char   *cp;
679 <
679 >        register int    i;
680 >                                        /* check to see if recovered already */
681 >        for (i = nrfrms; i--; )
682 >                if (rfrm[i] == frame)
683 >                        return(0);
684 >                                        /* build command */
685          sprintf(fname, vval(BASENAME), frame);
686          if (vdef(ANIMATE))
687 <                sprintf(combuf, "%s %d | rpict%s",
687 >                sprintf(combuf, "%s %d | rpict%s -w0",
688                                  vval(ANIMATE), frame, rendopt);
689          else
690 <                sprintf(combuf, "rpict%s", rendopt);
690 >                sprintf(combuf, "rpict%s -w0", rendopt);
691          cp = combuf + strlen(combuf);
692          if (vint(INTERP) || atoi(vval(MBLUR))) {
693                  sprintf(cp, " -z %s.zbf", fname);
# Line 623 | Line 699 | int    frame;
699                  *cp++ = ' ';
700                  strcpy(cp, vval(OCTREE));
701          }
702 <        if (runcom(combuf)) {
703 <                fprintf(stderr, "%s: error recovering frame %d\n",
704 <                                progname, frame);
702 >        if (runcom(combuf))             /* run command */
703 >                return(1);
704 >                                        /* add frame to recovered list */
705 >        if (nrfrms)
706 >                rfrm = (int *)realloc((char *)rfrm, (nrfrms+1)*sizeof(int));
707 >        else
708 >                rfrm = (int *)malloc(sizeof(int));
709 >        if (rfrm == NULL) {
710 >                perror("malloc");
711                  quit(1);
712          }
713 +        rfrm[nrfrms++] = frame;
714 +        return(0);
715   }
716  
717  
718 < archive(first, last)                    /* archive finished renderings */
718 > int
719 > frecover(frame)                         /* recover filtered frame */
720 > int     frame;
721 > {
722 >        VIEW    *vp;
723 >        char    *ex;
724 >
725 >        vp = getview(frame);
726 >        ex = getexp(frame);
727 >        if (dofilt(frame, vp, ex, 2) && dofilt(frame, vp, ex, 1))
728 >                return(1);
729 >        return(0);
730 > }
731 >
732 >
733 > archive(first, last)                    /* archive and remove renderings */
734   int     first, last;
735   {
736 + #define RMCOML  (sizeof(rmcom)-1)
737 +        static char     rmcom[] = "rm -f";
738 +        int     offset = RMCOML;
739          char    combuf[10240];
638        int     offset;
740          struct stat     stb;
741          register char   *cp;
742          register int    i;
743  
744 <        strcpy(cp=combuf, vval(ARCHIVE));
745 <        while (*cp) cp++;
746 <        offset = cp - combuf;
744 >        if (noaction)
745 >                return;
746 >        if (vdef(ARCHIVE) && strlen(vval(ARCHIVE)) > offset)
747 >                offset = strlen(vval(ARCHIVE));
748 >        cp = combuf + offset;
749          *cp++ = ' ';                            /* make argument list */
750          for (i = first; i <= last; i++) {
751                  sprintf(cp, vval(BASENAME), i);
# Line 661 | Line 764 | int    first, last;
764          *--cp = '\0';
765          if (cp <= combuf + offset)              /* no files? */
766                  return;
767 <        if (runcom(combuf)) {                   /* run archive command */
768 <                fprintf(stderr,
767 >        if (vdef(ARCHIVE)) {                    /* run archive command */
768 >                i = strlen(vval(ARCHIVE));
769 >                strncpy(combuf+offset-i, vval(ARCHIVE), i);
770 >                if (runcom(combuf+offset-i)) {
771 >                        fprintf(stderr,
772                  "%s: error running archive command on frames %d through %d\n",
773 <                                progname, first, last);
774 <                quit(1);
773 >                                        progname, first, last);
774 >                        quit(1);
775 >                }
776          }
777 +                                                /* run remove command */
778 +        strncpy(combuf+offset-RMCOML, rmcom, RMCOML);
779 +        runcom(combuf+offset-RMCOML);
780 + #undef RMCOML
781   }
782  
783  
784 < dofilt(frame, vp, ep)                           /* filter frame */
784 > int
785 > dofilt(frame, vp, ep, rvr)                      /* filter frame */
786   int     frame;
787   VIEW    *vp;
788   char    *ep;
789 + int     rvr;
790   {
791 +        extern int      frecover();
792          char    fnbefore[128], fnafter[128];
793          char    combuf[1024], fname[128];
794          int     usepinterp, usepfilt;
795 <        int     frbefore, frafter, triesleft;
795 >        int     frseq[2];
796                                                  /* check what is needed */
797          usepinterp = atoi(vval(MBLUR));
798          usepfilt = pfiltalways | ep==NULL;
799                                                  /* compute rendered views */
800 <        frbefore = frame - ((frame-1) % (vint(INTERP)+1));
801 <        frafter = frbefore + vint(INTERP) + 1;
802 <        if (frafter > vint(END))
803 <                frafter = vint(END);
804 <        if (frafter == frame) {                 /* pfilt only */
805 <                frbefore = frafter;
800 >        frseq[0] = frame - ((frame-1) % (vint(INTERP)+1));
801 >        frseq[1] = frseq[0] + vint(INTERP) + 1;
802 >        if (frseq[1] > vint(END))
803 >                frseq[1] = vint(END);
804 >        if (frseq[1] == frame) {                        /* pfilt only */
805 >                frseq[0] = frseq[1];
806                  usepinterp = 0;                 /* update what's needed */
807                  usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1");
808 <                triesleft = 2;
695 <        } else if (frbefore == frame) {         /* no interpolation */
696 <                                                /* remove unneeded files */
697 <                if (frbefore-vint(INTERP)-1 >= 1) {
698 <                        sprintf(fname, vval(BASENAME), frbefore-vint(INTERP)-1);
699 <                        sprintf(combuf, "rm -f %s.unf %s.zbf", fname, fname);
700 <                        runcom(combuf);
701 <                }
808 >        } else if (frseq[0] == frame) {         /* no interpolation */
809                                                  /* update what's needed */
810 <                if (usepinterp)
704 <                        triesleft = 3;
705 <                else {
810 >                if (!usepinterp)
811                          usepfilt |= vflt(OVERSAMP)>1.01 || strcmp(ep,"1");
812 <                        triesleft = 2;
708 <                }
709 <        } else {                                /* interpolation needed */
812 >        } else                                  /* interpolation needed */
813                  usepinterp++;
814 <                triesleft = 3;
815 <        }
816 <        if (frafter >= astat.rnext) {           /* next batch unavailable */
817 <                frafter = frbefore;
818 <                if (triesleft > 2)
819 <                        triesleft = 2;
820 <        }
718 <        sprintf(fnbefore, vval(BASENAME), frbefore);
719 <        sprintf(fnafter, vval(BASENAME), frafter);
720 < tryit:                                          /* generate command */
814 >        if (frseq[1] >= astat.rnext)            /* next batch unavailable */
815 >                frseq[1] = frseq[0];
816 >        sprintf(fnbefore, vval(BASENAME), frseq[0]);
817 >        sprintf(fnafter, vval(BASENAME), frseq[1]);
818 >        if (rvr == 1 && recover(frseq[0]))      /* recover before frame? */
819 >                return(1);
820 >                                                /* generate command */
821          if (usepinterp) {                       /* using pinterp */
822 +                if (rvr == 2 && recover(frseq[1]))      /* recover after? */
823 +                        return(1);
824                  if (atoi(vval(MBLUR))) {
825                          FILE    *fp;            /* motion blurring */
826                          sprintf(fname, "%s/vw0", vval(DIRECTORY));
# Line 743 | Line 845 | tryit:                                         /* generate command */
845                          putc('\n', fp); fclose(fp);
846                          sprintf(combuf,
847          "(pmblur %s %d %s/vw0 %s/vw1; rm -f %s/vw0 %s/vw1) | pinterp -B",
848 <                                *sskip(vval(MBLUR)) ? sskip(vval(MBLUR)) : "1",
848 >                        *sskip(vval(MBLUR)) ? sskip2(vval(MBLUR),1) : "1",
849                                          atoi(vval(MBLUR)), vval(DIRECTORY),
850                                          vval(DIRECTORY), vval(DIRECTORY),
851                                          vval(DIRECTORY), vval(DIRECTORY));
# Line 751 | Line 853 | tryit:                                         /* generate command */
853                          strcpy(combuf, "pinterp");
854                  strcat(combuf, viewopt(vp));
855                  if (vbool(RTRACE))
856 <                        sprintf(combuf+strlen(combuf), " -ff -fr '%s %s'",
856 >                        sprintf(combuf+strlen(combuf), " -ff -fr '%s -w0 %s'",
857                                          rendopt, vval(OCTREE));
858                  if (vdef(PINTERP))
859                          sprintf(combuf+strlen(combuf), " %s", vval(PINTERP));
# Line 762 | Line 864 | tryit:                                         /* generate command */
864                                          fresopt, ep);
865                  sprintf(combuf+strlen(combuf), " %s.unf %s.zbf",
866                                  fnbefore, fnbefore);
867 <                if (frafter != frbefore)
867 >                if (frseq[1] != frseq[0])
868                           sprintf(combuf+strlen(combuf), " %s.unf %s.zbf",
869                                          fnafter, fnafter);
870                  if (usepfilt) {                 /* also pfilt */
# Line 778 | Line 880 | tryit:                                         /* generate command */
880                                  sprintf(combuf+strlen(combuf), " %s", fresopt);
881                  }
882          } else if (usepfilt) {                  /* pfilt only */
883 +                if (rvr == 2)
884 +                        return(1);
885                  if (vdef(PFILT))
886                          sprintf(combuf, "pfilt %s", vval(PFILT));
887                  else
# Line 789 | Line 893 | tryit:                                         /* generate command */
893                          sprintf(combuf+strlen(combuf), " %s %s.unf",
894                                          fresopt, fnbefore);
895          } else {                                /* else just check it */
896 +                if (rvr == 2)
897 +                        return(1);
898                  sprintf(combuf, "ra_rgbe -r %s.unf", fnbefore);
899          }
900                                                  /* output file name */
901          sprintf(fname, vval(BASENAME), frame);
902          sprintf(combuf+strlen(combuf), " > %s.pic", fname);
903 <        if (runcom(combuf))                     /* run filter command */
904 <                switch (--triesleft) {
905 <                case 2:                         /* try to recover frafter */
906 <                        recover(frafter);
801 <                        goto tryit;
802 <                case 1:                         /* try to recover frbefore */
803 <                        recover(frbefore);
804 <                        goto tryit;
805 <                default:                        /* we've really failed */
806 <                        fprintf(stderr,
807 <                        "%s: unrecoverable filtering error on frame %d\n",
808 <                                        progname, frame);
809 <                        quit(1);
810 <                }
903 >        if (rvr)                                /* in recovery */
904 >                return(runcom(combuf));
905 >        bruncom(combuf, frame, frecover);       /* else run in background */
906 >        return(0);
907   }
908  
909  
814 filtwait(nwait)                 /* wait for filtering processes to finish */
815 int     nwait;
816 {
817        /* currently does nothing since parallel filtering not working */
818 }
819
820
910   VIEW *
911   getview(n)                      /* get view number n */
912   int     n;
# Line 937 | Line 1026 | int    n;
1026   }
1027  
1028  
1029 < runcom(cs)                      /* run command */
1029 > struct pslot *
1030 > findpslot(pid)                  /* find or allocate a process slot */
1031 > int     pid;
1032 > {
1033 >        register struct pslot   *psempty = NULL;
1034 >        register int    i;
1035 >
1036 >        for (i = 0; i < npslots; i++) {         /* look for match */
1037 >                if (pslot[i].pid == pid)
1038 >                        return(pslot+i);
1039 >                if (psempty == NULL && pslot[i].pid == 0)
1040 >                        psempty = pslot+i;
1041 >        }
1042 >        return(psempty);                /* return emtpy slot (error if NULL) */
1043 > }
1044 >
1045 >
1046 > int
1047 > donecom(ps, pn, status)         /* clean up after finished process */
1048 > PSERVER *ps;
1049 > int     pn;
1050 > int     status;
1051 > {
1052 >        register PROC   *pp;
1053 >
1054 >        pp = ps->proc + pn;
1055 >        if (!silent) {                  /* echo command */
1056 >                if (ps->hostname[0])
1057 >                        printf("On %s:", ps->hostname);
1058 >                printf("\t%s\n", pp->com);
1059 >                fflush(stdout);
1060 >        }
1061 >        if (pp->elen) {                 /* pass errors */
1062 >                fputs(pp->errs, stderr);
1063 >                fflush(stderr);
1064 >                if (ps->hostname[0])
1065 >                        status = 1;     /* because rsh doesn't return status */
1066 >        }
1067 >        freestr(pp->com);               /* free command string */
1068 >        lastpid = pp->pid;              /* record PID for bwait() */
1069 >        lastpserver = ps;               /* record server for serverdown() */
1070 >        return(status);
1071 > }
1072 >
1073 >
1074 > int
1075 > serverdown()                    /* check status of last process server */
1076 > {
1077 >        if (pserverOK(lastpserver))     /* server still up? */
1078 >                return(0);
1079 >        delpserver(lastpserver);        /* else delete it */
1080 >        if (pslist == NULL) {
1081 >                fprintf(stderr, "%s: all process servers are down\n",
1082 >                                progname);
1083 >                quit(1);
1084 >        }
1085 >        return(1);
1086 > }
1087 >
1088 >
1089 > int
1090 > bruncom(com, fout, rf)          /* run a command in the background */
1091 > char    *com;
1092 > int     fout;
1093 > int     (*rf)();
1094 > {
1095 >        int     pid;
1096 >        register struct pslot   *psl;
1097 >
1098 >        if (noaction) {
1099 >                if (!silent)
1100 >                        printf("\t%s\n", com);  /* just echo it */
1101 >                return(0);
1102 >        }
1103 >                                        /* else start it when we can */
1104 >        while ((pid = startjob(NULL, savestr(com), donecom)) == -1)
1105 >                bwait(1);
1106 >        psl = findpslot(pid);           /* record info. in appropriate slot */
1107 >        psl->pid = pid;
1108 >        psl->fout = fout;
1109 >        psl->rcvf = rf;
1110 >        return(pid);
1111 > }
1112 >
1113 >
1114 > bwait(ncoms)                            /* wait for batch job(s) to finish */
1115 > int     ncoms;
1116 > {
1117 >        int     status;
1118 >        register struct pslot   *psl;
1119 >
1120 >        if (noaction)
1121 >                return;
1122 >        while ((status = wait4job(NULL, -1)) != -1) {
1123 >                psl = findpslot(lastpid);
1124 >                if (status) {           /* attempt recovery */
1125 >                        serverdown();   /* check server */
1126 >                        if (psl->rcvf == NULL || (*psl->rcvf)(psl->fout)) {
1127 >                                fprintf(stderr,
1128 >                                        "%s: error rendering frame %d\n",
1129 >                                                progname, psl->fout);
1130 >                                quit(1);
1131 >                        }
1132 >                }
1133 >                psl->pid = 0;           /* free process slot */
1134 >                if (!--ncoms)
1135 >                        return;         /* done enough */
1136 >        }
1137 > }
1138 >
1139 >
1140 > int
1141 > pruncom(com, maxcopies)         /* run a command in parallel over network */
1142 > char    *com;
1143 > int     maxcopies;
1144 > {
1145 >        int     retstatus = 0;
1146 >        int     status;
1147 >        register PSERVER        *ps;
1148 >
1149 >        if (noaction) {
1150 >                if (!silent)
1151 >                        printf("\t%s\n", com);  /* just echo */
1152 >                return(0);
1153 >        }
1154 >                                        /* start jobs on each server */
1155 >        for (ps = pslist; ps != NULL; ps = ps->next)
1156 >                while (maxcopies > 0 &&
1157 >                                startjob(ps, savestr(com), donecom) != -1) {
1158 >                        sleep(10);
1159 >                        maxcopies--;
1160 >                }
1161 >                                        /* wait for jobs to finish */
1162 >        while ((status = wait4job(NULL, -1)) != -1)
1163 >                if (status)
1164 >                        retstatus += !serverdown();     /* check server */
1165 >        return(retstatus);
1166 > }
1167 >
1168 >
1169 > runcom(cs)                      /* run a command locally and wait for it */
1170   char    *cs;
1171   {
1172          if (!silent)            /* echo it */

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines