Пример #1
0
extern void
persistfile(	/* open persist file and lock it */
    char	*pfn
)
{
    persistfd = open(pfn, O_WRONLY|O_CREAT|O_EXCL, 0644);
    if (persistfd >= 0) {
        persistfname = pfn;
        pflock(1);
        return;
    }
    /* file exists -- switch to i/o process */
    persistfd = open(pfn, O_RDWR);
    if (persistfd < 0) {
        sprintf(errmsg, "cannot open persist file \"%s\"", pfn);
        error(SYSTEM, errmsg);
    }
    pflock(1);
    io_process();	/* never returns */
}
Пример #2
0
extern void
pfhold(void)		/* holding pattern for idle rendering process */
{
    rsighandler_t	*oldalrm;
    char	buf[512];
    register int	n;
    /* close input and output descriptors */
    close(0);
    close(1);
    if (errfile == NULL)
        close(2);
    /* create named pipes for input and output */
    if (mkfifo(mktemp(strcpy(inpname,TEMPLATE)), 0600) < 0)
        goto createrr;
    if (mkfifo(mktemp(strcpy(outpname,TEMPLATE)), 0600) < 0)
        goto createrr;
    if (errfile == NULL &&
            mkfifo(mktemp(strcpy(errname,TEMPLATE)), 0600) < 0)
        goto createrr;
    sprintf(buf, "%s %d\n%s\n%s\n%s\n", progname, getpid(),
            inpname, outpname, errname);
    n = strlen(buf);
    if (write(persistfd, buf, n) < n)
        error(SYSTEM, "error writing persist file");
    lseek(persistfd, (off_t)0, SEEK_SET);
    /* wait TIMELIM for someone to signal us */
    got_io = 0;
    signal(SIGIO, sig_io);
    oldalrm = signal(SIGALRM, sig_alrm);
    alarm(TIMELIM);
    pflock(0);			/* unlock persist file for attach */
    while (!got_io)
        pause();		/* wait for attach */
    alarm(0);			/* turn off alarm */
    signal(SIGALRM, oldalrm);
    signal(SIGIO, SIG_DFL);
    pflock(1);			/* grab persist file back */
    /* someone wants us; reopen stdin and stdout */
    close(0);
    if (open(inpname, O_RDONLY) != 0)
        error(INTERNAL, "unexpected stdin file number");
    clearerr(stdin);
    close(1);
    if (open(outpname, O_WRONLY) != 1)
        error(INTERNAL, "unexpected stdout file number");
    sleep(3);		/* give them a chance to open their pipes */
    if (errname[0]) {
        close(2);
        if (open(errname, O_WRONLY) != 2)
            error(INTERNAL, "unexpected stderr file number");
        unlink(errname);
        errname[0] = '\0';
    }
    unlink(inpname);
    inpname[0] = '\0';
    unlink(outpname);
    outpname[0] = '\0';
    return;
createrr:
    error(SYSTEM, "cannot create named pipes in pfhold");
}
Пример #3
0
extern void
io_process(void)		/* just act as go-between for actual process */
{
    register char	*cp;
    register int	nr, n;
    char	buf[BUFSIZ], *pfin, *pfout, *pferr;
    int	pid, nfds;
    int	fdout, fderr = -1;
    int	status = 0;
    fd_set	readfds, excepfds;
    /* load persist file */
    n = 40;
    while ((nr = read(persistfd, buf, sizeof(buf)-1)) == 0) {
        if (!n--)
            error(USER, "unattended persist file?");
        pflock(0);
        sleep(3+(3*getpid()+random())%13);	/* wait until ready */
        pflock(1);
    }
    if (nr < 0)
        error(SYSTEM, "error reading persist file");
#ifndef _WIN32 /* XXX we need a replacement for that one */
    ftruncate(persistfd, (off_t)0L);	/* truncate persist file */
#endif
    pfdetach();			/* close & release persist file */
    buf[nr] = '\0';			/* parse what we got */
    if ((cp = strchr(buf, ' ')) == NULL)
        goto formerr;
    *cp++ = '\0';
    if ((pid = atoi(cp)) <= 0)
        goto formerr;
    if ((cp = strchr(cp, '\n')) == NULL)
        goto formerr;
    pfin = ++cp;
    if ((cp = strchr(cp, '\n')) == NULL)
        goto formerr;
    *cp++ = '\0';
    pfout = cp;
    if ((cp = strchr(cp, '\n')) == NULL)
        goto formerr;
    *cp++ = '\0';
    pferr = cp;
    if ((cp = strchr(cp, '\n')) == NULL)
        goto formerr;
    *cp++ = '\0';
    if (cp-buf != nr)
        goto formerr;
    if (strcmp(buf, progname)) {
        sprintf(errmsg, "persist file for %s, not %s", buf, progname);
        error(USER, errmsg);
    }
    /* wake up rendering process */
    if (kill(pid, SIGIO) < 0)
        error(SYSTEM, "cannot signal rendering process in io_process");
    /* fork child feeder process */
    pid = fork();
    if (pid < 0)
        error(SYSTEM, "fork failed in io_process");
    if (pid == 0) {			/* feeder loop */
        int	fdin;
        close(1);		/* open input pipe */
        if ((fdin = open(pfin, O_WRONLY)) < 0)
            error(SYSTEM, "cannot open feed pipe in io_process");
        /* renderer stdin */
        while ((nr = read(0, cp=buf, sizeof(buf))) > 0) {
            do {
                if ((n = write(fdin, cp, nr)) <= 0)
                    goto writerr;
                cp += n;
            } while ((nr -= n) > 0);
        }
        if (nr < 0)
            goto readerr;
        _exit(0);
    }
    close(0);
    /* open output pipes, in order */
    if ((fdout = open(pfout, O_RDONLY)) < 0)
        error(SYSTEM, "cannot open output pipe in io_process");
    if (pferr[0] && (fderr = open(pferr, O_RDONLY)) < 0)
        error(SYSTEM, "cannot open error pipe in io_process");
    for ( ; ; ) {			/* eater loop */
        FD_ZERO(&readfds);
        FD_ZERO(&excepfds);
        nfds = 0;
        if (fdout >= 0) {
            FD_SET(fdout, &readfds);
            FD_SET(fdout, &excepfds);
            nfds = fdout+1;
        }
        if (fderr >= 0) {
            FD_SET(fderr, &readfds);
            FD_SET(fderr, &excepfds);
            nfds = fderr+1;
        }
        if (nfds == 0)
            break;			/* all done, exit */
        if (select(nfds, &readfds, NULL, &excepfds, NULL) < 0)
            error(SYSTEM, "error in select call in io_process");
        /* renderer stderr */
        if (fderr >= 0 && (FD_ISSET(fderr, &readfds) ||
                           FD_ISSET(fderr, &excepfds))) {
            nr = read(fderr, cp=buf, sizeof(buf));
            if (nr < 0)
                goto readerr;
            if (nr == 0) {
                close(fderr);
                /* close(2);	don't close stderr! */
                fderr = -1;
            } else {
                cp[nr] = '\0';	/* deduce status if we can */
                n = strlen(progname);
                if (!strncmp(cp, progname, n) &&
                        cp[n++] == ':' &&
                        cp[n++] == ' ') {
                    register struct erract	*ep;
                    for (ep = erract; ep < erract+NERRS;
                            ep++)
                        if (ep->pre[0] &&
                                !strncmp(cp+n, ep->pre,
                                         strlen(ep->pre))) {
                            status = ep->ec;
                            break;
                        }
                }
                do {		/* write message */
                    if ((n = write(2, cp, nr)) <= 0)
                        goto writerr;
                    cp += n;
                } while ((nr -= n) > 0);
            }
        }
        /* renderer stdout */
        if (fdout >= 0 && (FD_ISSET(fdout, &readfds) ||
                           FD_ISSET(fdout, &excepfds))) {
            nr = read(fdout, cp=buf, sizeof(buf));
            if (nr < 0)
                goto readerr;
            if (nr == 0) {		/* EOF */
                close(fdout);
                close(1);
                fdout = -1;
            } else
                do {		/* write it all */
                    if ((n = write(1, cp, nr)) <= 0)
                        goto writerr;
                    cp += n;
                } while ((nr -= n) > 0);
        }
    }
    kill(pid, SIGTERM);	/* no more process to feed, so... */
    waitpid(pid, 0, 0);	/* wait for feeder process */
    _exit(status);
formerr:
    error(USER, "format error in persist file");
readerr:
    error(SYSTEM, "read error in io_process");
writerr:
    error(SYSTEM, "write error in io_process");
}
Пример #4
0
int
main(int  argc, char  *argv[])
{
#define	 check(ol,al)		if (argv[i][ol] || \
				badarg(argc-i-1,argv+i+1,al)) \
				goto badopt
#define	 bool(olen,var)		switch (argv[i][olen]) { \
				case '\0': var = !var; break; \
				case 'y': case 'Y': case 't': case 'T': \
				case '+': case '1': var = 1; break; \
				case 'n': case 'N': case 'f': case 'F': \
				case '-': case '0': var = 0; break; \
				default: goto badopt; }
	char  *err;
	char  *recover = NULL;
	char  *outfile = NULL;
	char  *zfile = NULL;
	int  loadflags = ~IO_FILES;
	int  seqstart = 0;
	int  persist = 0;
	int  duped1 = -1;
	int  rval;
	int  i;
					/* record start time */
	tstart = time((time_t *)NULL);
					/* global program name */
	progname = argv[0] = fixargv0(argv[0]);
					/* option city */
	for (i = 1; i < argc; i++) {
						/* expand arguments */
		while ((rval = expandarg(&argc, &argv, i)) > 0)
			;
		if (rval < 0) {
			sprintf(errmsg, "cannot expand '%s'", argv[i]);
			error(SYSTEM, errmsg);
		}
		if (argv[i] == NULL || argv[i][0] != '-')
			break;			/* break from options */
		if (!strcmp(argv[i], "-version")) {
			puts(VersionID);
			quit(0);
		}
		if (!strcmp(argv[i], "-defaults") ||
				!strcmp(argv[i], "-help")) {
			printdefaults();
			quit(0);
		}
		rval = getrenderopt(argc-i, argv+i);
		if (rval >= 0) {
			i += rval;
			continue;
		}
		rval = getviewopt(&ourview, argc-i, argv+i);
		if (rval >= 0) {
			i += rval;
			continue;
		}
						/* rpict options */
		switch (argv[i][1]) {
		case 'v':				/* view file */
			if (argv[i][2] != 'f')
				goto badopt;
			check(3,"s");
			rval = viewfile(argv[++i], &ourview, NULL);
			if (rval < 0) {
				sprintf(errmsg,
				"cannot open view file \"%s\"",
						argv[i]);
				error(SYSTEM, errmsg);
			} else if (rval == 0) {
				sprintf(errmsg,
					"bad view file \"%s\"",
						argv[i]);
				error(USER, errmsg);
			}
			break;
		case 'p':				/* pixel */
			switch (argv[i][2]) {
			case 's':				/* sample */
				check(3,"i");
				psample = atoi(argv[++i]);
				break;
			case 't':				/* threshold */
				check(3,"f");
				maxdiff = atof(argv[++i]);
				break;
			case 'j':				/* jitter */
				check(3,"f");
				dstrpix = atof(argv[++i]);
				break;
			case 'a':				/* aspect */
				check(3,"f");
				pixaspect = atof(argv[++i]);
				break;
			case 'm':				/* motion */
				check(3,"f");
				mblur = atof(argv[++i]);
				break;
			case 'd':				/* aperture */
				check(3,"f");
				dblur = atof(argv[++i]);
				break;
			default:
				goto badopt;
			}
			break;
		case 'x':				/* x resolution */
			check(2,"i");
			hresolu = atoi(argv[++i]);
			break;
		case 'y':				/* y resolution */
			check(2,"i");
			vresolu = atoi(argv[++i]);
			break;
		case 'S':				/* slave index */
			check(2,"i");
			seqstart = atoi(argv[++i]);
			break;
		case 'o':				/* output file */
			check(2,"s");
			outfile = argv[++i];
			break;
		case 'z':				/* z file */
			check(2,"s");
			zfile = argv[++i];
			break;
		case 'r':				/* recover file */
			if (argv[i][2] == 'o') {		/* +output */
				check(3,"s");
				outfile = argv[i+1];
			} else
				check(2,"s");
			recover = argv[++i];
			break;
		case 't':				/* timer */
			check(2,"i");
			ralrm = atoi(argv[++i]);
			break;
#ifdef  PERSIST
		case 'P':				/* persist file */
			if (argv[i][2] == 'P') {
				check(3,"s");
				persist = PARALLEL;
			} else {
				check(2,"s");
				persist = PERSIST;
			}
			persistfile(argv[++i]);
			break;
#endif
		case 'w':				/* warnings */
			rval = erract[WARNING].pf != NULL;
			bool(2,rval);
			if (rval) erract[WARNING].pf = wputs;
			else erract[WARNING].pf = NULL;
			break;
		case 'e':				/* error file */
			check(2,"s");
			errfile = argv[++i];
			break;
		default:
			goto badopt;
		}
	}
	err = setview(&ourview);	/* set viewing parameters */
	if (err != NULL)
		error(USER, err);
					/* initialize object types */
	initotypes();
					/* initialize urand */
	if (rand_samp) {
		srandom((long)time(0));
		initurand(0);
	} else {
		srandom(0L);
		initurand(2048);
	}
					/* set up signal handling */
	sigdie(SIGINT, "Interrupt");
#ifdef SIGHUP
	sigdie(SIGHUP, "Hangup");
#endif
	sigdie(SIGTERM, "Terminate");
#ifdef SIGPIPE
	sigdie(SIGPIPE, "Broken pipe");
#endif
#ifdef SIGALRM
	sigdie(SIGALRM, "Alarm clock");
#endif
#ifdef	SIGXCPU
	sigdie(SIGXCPU, "CPU limit exceeded");
	sigdie(SIGXFSZ, "File size exceeded");
#endif
					/* open error file */
	if (errfile != NULL) {
		if (freopen(errfile, "a", stderr) == NULL)
			quit(2);
		fprintf(stderr, "**************\n*** PID %5d: ",
				getpid());
		printargs(argc, argv, stderr);
		putc('\n', stderr);
		fflush(stderr);
	}
#ifdef	NICE
	nice(NICE);			/* lower priority */
#endif
					/* get octree */
	if (i == argc)
		octname = NULL;
	else if (i == argc-1)
		octname = argv[i];
	else
		goto badopt;
	if (seqstart > 0 && octname == NULL)
		error(USER, "missing octree argument");
					/* set up output */
#ifdef  PERSIST
	if (persist) {
		if (recover != NULL)
			error(USER, "persist option used with recover file");
		if (seqstart <= 0)
			error(USER, "persist option only for sequences");
		if (outfile == NULL)
		duped1 = dup(fileno(stdout));	/* don't lose our output */
		openheader();
	} else
#endif
	if (outfile != NULL)
		openheader();
#ifdef	_WIN32
	SET_FILE_BINARY(stdout);
	if (octname == NULL)
		SET_FILE_BINARY(stdin);
#endif
	readoct(octname, loadflags, &thescene, NULL);
	nsceneobjs = nobjects;

	if (loadflags & IO_INFO) {	/* print header */
		printargs(i, argv, stdout);
		printf("SOFTWARE= %s\n", VersionID);
	}

	marksources();			/* find and mark sources */

	setambient();			/* initialize ambient calculation */

#ifdef  PERSIST
	if (persist) {
		fflush(stdout);
		if (outfile == NULL) {		/* reconnect stdout */
			dup2(duped1, fileno(stdout));
			close(duped1);
		}
		if (persist == PARALLEL) {	/* multiprocessing */
			preload_objs();		/* preload scene */
			shm_boundary = (char *)malloc(16);
			strcpy(shm_boundary, "SHM_BOUNDARY");
			while ((rval=fork()) == 0) {	/* keep on forkin' */
				pflock(1);
				pfhold();
				tstart = time((time_t *)NULL);
				ambsync();		/* load new values */
			}
			if (rval < 0)
				error(SYSTEM, "cannot fork child for persist function");
			pfdetach();		/* parent will run then exit */
		}
	}
runagain:
	if (persist) {
		if (outfile == NULL)			/* if out to stdout */
			dupheader();			/* send header */
		else					/* if out to file */
			duped1 = dup(fileno(stdout));	/* hang onto pipe */
	}
#endif
					/* batch render picture(s) */
	rpict(seqstart, outfile, zfile, recover);
					/* flush ambient file */
	ambsync();
#ifdef  PERSIST
	if (persist == PERSIST) {	/* first run-through */
		if ((rval=fork()) == 0) {	/* child loops until killed */
			pflock(1);
			persist = PCHILD;
		} else {			/* original process exits */
			if (rval < 0)
				error(SYSTEM, "cannot fork child for persist function");
			pfdetach();		/* parent exits */
		}
	}
	if (persist == PCHILD) {	/* wait for a signal then go again */
		if (outfile != NULL)
			close(duped1);		/* release output handle */
		pfhold();
		tstart = time((time_t *)NULL);	/* reinitialize */
		raynum = nrays = 0;
		goto runagain;
	}
#endif
	quit(0);

badopt:
	sprintf(errmsg, "command line error at '%s'", argv[i]);
	error(USER, errmsg);
	return 1; /* pro forma return */

#undef	check
#undef	bool
}