⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 job.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		    if (job->node != lastNode) {			printf (targFmt, job->node->name);			lastNode = job->node;		    }		    printf ("%s\n", cp);		}		fflush (stdout);	    }	    if (i < max - 1) {		/* shift the remaining characters down */		memcpy ( job->outBuf, &job->outBuf[i + 1], max - (i + 1));		job->curPos = max - (i + 1);			    } else {		/*		 * We have written everything out, so we just start over		 * from the start of the buffer. No copying. No nothing.		 */		job->curPos = 0;	    }	}	if (finish) {	    /*	     * If the finish flag is true, we must loop until we hit	     * end-of-file on the pipe. This is guaranteed to happen eventually	     * since the other end of the pipe is now closed (we closed it	     * explicitly and the child has exited). When we do get an EOF,	     * finish will be set FALSE and we'll fall through and out.	     */	    goto end_loop;	}    } else {	/*	 * We've been called to retrieve the output of the job from the	 * temporary file where it's been squirreled away. This consists of	 * opening the file, reading the output line by line, being sure not	 * to print the noPrint line for the shell we used, then close and	 * remove the temporary file. Very simple.	 *	 * Change to read in blocks and do FindSubString type things as for	 * pipes? That would allow for "@echo -n..."	 */	oFILE = fopen (job->outFile, "r");	if (oFILE != (FILE *) NULL) {	    printf ("Results of making %s:\n", job->node->name);	    while (fgets (inLine, sizeof(inLine), oFILE) != NULL) {		register char	*cp, *ecp, *endp;		cp = inLine;		endp = inLine + strlen(inLine);		if (endp[-1] == '\n') {		    *--endp = '\0';		}		if (commandShell->noPrint) {		    ecp = Str_FindSubstring(cp, commandShell->noPrint);		    while (ecp != (char *)NULL) {			if (cp != ecp) {			    *ecp = '\0';			    /*			     * The only way there wouldn't be a newline after			     * this line is if it were the last in the buffer.			     * however, since the non-printable comes after it,			     * there must be a newline, so we don't print one.			     */			    printf ("%s", cp);			}			cp = ecp + commandShell->noPLen;			if (cp != endp) {			    /*			     * Still more to print, look again after skipping			     * the whitespace following the non-printable			     * command....			     */			    cp++;			    while (*cp == ' ' || *cp == '\t' || *cp == '\n') {				cp++;			    }			    ecp = Str_FindSubstring(cp, commandShell->noPrint);			} else {			    break;			}		    }		}		/*		 * There's still more in that thar buffer. This time, though,		 * we know there's no newline at the end, so we add one of		 * our own free will.		 */		if (*cp != '\0') {		    printf ("%s\n", cp);		}	    }	    fclose (oFILE);	    (void) unlink (job->outFile);	}    }    fflush(stdout);}/*- *----------------------------------------------------------------------- * Job_CatchChildren -- *	Handle the exit of a child. Called from Make_Make. * * Results: *	none. * * Side Effects: *	The job descriptor is removed from the list of children. * * Notes: *	We do waits, blocking or not, according to the wisdom of our *	caller, until there are no more children to report. For each *	job, call JobFinish to finish things off. This will take care of *	putting jobs on the stoppedJobs queue. * *----------------------------------------------------------------------- */voidJob_CatchChildren (block)    Boolean	  block;    	/* TRUE if should block on the wait. */{    int    	  pid;	    	/* pid of dead child */    register Job  *job;	    	/* job descriptor for dead child */    LstNode       jnode;    	/* list element for finding job */    union wait	  status;   	/* Exit/termination status */    /*     * Don't even bother if we know there's no one around.     */    if (nLocal == 0) {	return;    }        while ((pid = wait3((int *)&status, (block?0:WNOHANG)|WUNTRACED,			(struct rusage *)0)) > 0)    {	if (DEBUG(JOB))	    printf("Process %d exited or stopped.\n", pid);	    	jnode = Lst_Find (jobs, (ClientData)pid, JobCmpPid);	if (jnode == NILLNODE) {	    if (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) {		jnode = Lst_Find(stoppedJobs, (ClientData)pid, JobCmpPid);		if (jnode == NILLNODE) {		    Error("Resumed child (%d) not in table", pid);		    continue;		}		job = (Job *)Lst_Datum(jnode);		(void)Lst_Remove(stoppedJobs, jnode);	    } else {		Error ("Child (%d) not in table?", pid);		continue;	    }	} else {	    job = (Job *) Lst_Datum (jnode);	    (void)Lst_Remove (jobs, jnode);	    nJobs -= 1;	    if (jobFull && DEBUG(JOB)) {		printf("Job queue is no longer full.\n");	    }	    jobFull = FALSE;	    nLocal -= 1;	}	JobFinish (job, status);    }}/*- *----------------------------------------------------------------------- * Job_CatchOutput -- *	Catch the output from our children, if we're using *	pipes do so. Otherwise just block time until we get a *	signal (most likely a SIGCHLD) since there's no point in *	just spinning when there's nothing to do and the reaping *	of a child can wait for a while.  * * Results: *	None  * * Side Effects: *	Output is read from pipes if we're piping. * ----------------------------------------------------------------------- */voidJob_CatchOutput (){    int           	  nfds;    struct timeval	  timeout;    fd_set           	  readfds;    register LstNode	  ln;    register Job   	  *job;#ifdef RMT_WILL_WATCH    int	    	  	  pnJobs;   	/* Previous nJobs */#endif    fflush(stdout);#ifdef RMT_WILL_WATCH    pnJobs = nJobs;    /*     * It is possible for us to be called with nJobs equal to 0. This happens     * if all the jobs finish and a job that is stopped cannot be run     * locally (eg if maxLocal is 0) and cannot be exported. The job will     * be placed back on the stoppedJobs queue, Job_Empty() will return false,     * Make_Run will call us again when there's nothing for which to wait.     * nJobs never changes, so we loop forever. Hence the check. It could     * be argued that we should sleep for a bit so as not to swamp the     * exportation system with requests. Perhaps we should.     *     * NOTE: IT IS THE RESPONSIBILITY OF Rmt_Wait TO CALL Job_CatchChildren     * IN A TIMELY FASHION TO CATCH ANY LOCALLY RUNNING JOBS THAT EXIT.     * It may use the variable nLocal to determine if it needs to call     * Job_CatchChildren (if nLocal is 0, there's nothing for which to     * wait...)     */    while (nJobs != 0 && pnJobs == nJobs) {	Rmt_Wait();    }#else    if (usePipes) {	readfds = outputs;	timeout.tv_sec = SEL_SEC;	timeout.tv_usec = SEL_USEC;	if ((nfds = select (FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout)) < 0)	{	    return;	} else {	    if (Lst_Open (jobs) == FAILURE) {		Punt ("Cannot open job table");	    }	    while (nfds && (ln = Lst_Next (jobs)) != NILLNODE) {		job = (Job *) Lst_Datum (ln);		if (FD_ISSET(job->inPipe, &readfds)) {		    JobDoOutput (job, FALSE);		    nfds -= 1;		}	    }	    Lst_Close (jobs);	}    }#endif /* RMT_WILL_WATCH */}/*- *----------------------------------------------------------------------- * Job_Make -- *	Start the creation of a target. Basically a front-end for *	JobStart used by the Make module. * * Results: *	None. * * Side Effects: *	Another job is started. * *----------------------------------------------------------------------- */voidJob_Make (gn)    GNode   *gn;{    (void)JobStart (gn, 0, (Job *)NULL);}/*- *----------------------------------------------------------------------- * Job_Init -- *	Initialize the process module * * Results: *	none * * Side Effects: *	lists and counters are initialized *----------------------------------------------------------------------- */voidJob_Init (maxproc, maxlocal)    int           maxproc;  /* the greatest number of jobs which may be			     * running at one time */    int	    	  maxlocal; /* the greatest number of local jobs which may			     * be running at once. */{    GNode         *begin;     /* node for commands to do at the very start */    sprintf (tfile, "/tmp/make%05d", getpid());    jobs =  	  Lst_Init (FALSE);    stoppedJobs = Lst_Init(FALSE);    maxJobs = 	  maxproc;    maxLocal = 	  maxlocal;    nJobs = 	  0;    nLocal = 	  0;    jobFull = 	  FALSE;    aborting = 	  0;    errors = 	  0;    lastNode =	  NILGNODE;    if (maxJobs == 1) {	/*	 * If only one job can run at a time, there's no need for a banner,	 * no is there?	 */	targFmt = "";    } else {	targFmt = TARG_FMT;    }        if (shellPath == (char *) NULL) {	/*	 * The user didn't specify a shell to use, so we are using the	 * default one... Both the absolute path and the last component	 * must be set. The last component is taken from the 'name' field	 * of the default shell description pointed-to by commandShell.	 * All default shells are located in _PATH_DEFSHELLDIR.	 */	shellName = commandShell->name;	shellPath = str_concat (_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);    }    if (commandShell->exit == (char *)NULL) {	commandShell->exit = "";    }    if (commandShell->echo == (char *)NULL) {	commandShell->echo = "";    }    /*     * Catch the four signals that POSIX specifies if they aren't ignored.     * JobPassSig will take care of calling JobInterrupt if appropriate.     */    if (signal (SIGINT, SIG_IGN) != SIG_IGN) {	signal (SIGINT, JobPassSig);    }    if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {	signal (SIGHUP, JobPassSig);    }    if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) {	signal (SIGQUIT, JobPassSig);    }    if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {	signal (SIGTERM, JobPassSig);    }    /*     * There are additional signals that need to be caught and passed if     * either the export system wants to be told directly of signals or if     * we're giving each job its own process group (since then it won't get     * signals from the terminal driver as we own the terminal)     */#if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP)    if (signal (SIGTSTP, SIG_IGN) != SIG_IGN) {	signal (SIGTSTP, JobPassSig);    }    if (signal (SIGTTOU, SIG_IGN) != SIG_IGN) {	signal (SIGTTOU, JobPassSig);    }    if (signal (SIGTTIN, SIG_IGN) != SIG_IGN) {	signal (SIGTTIN, JobPassSig);    }    if (signal (SIGWINCH, SIG_IGN) != SIG_IGN) {	signal (SIGWINCH, JobPassSig);    }#endif        begin = Targ_FindNode (".BEGIN", TARG_NOCREATE);    if (begin != NILGNODE) {	JobStart (begin, JOB_SPECIAL, (Job *)0);	while (nJobs) {	    Job_CatchOutput();#ifndef RMT_WILL_WATCH	    Job_CatchChildren (!usePipes);#endif /* RMT_WILL_WATCH */	}    }    postCommands = Targ_FindNode (".END", TARG_CREATE);}/*- *----------------------------------------------------------------------- * Job_Full -- *	See if the job table is full. It is considered full if it is OR *	if we are in the process of aborting OR if we have *	reached/exceeded our local quota. This prevents any more jobs *	from starting up. * * Results: *	TRUE if the job table is full, FALSE otherwise * Side Effects: *	None. *----------------------------------------------------------------------- */BooleanJob_Full (){    return (aborting || jobFull);}/*- *----------------------------------------------------------------------- * Job_Empty -- *	See if the job table is empty.  Because the local concurrency may *	be set to 0, it is possible for the job table to become empty, *	while the list of stoppedJobs remains non-empty. In such a case, *	we want to restart as many jobs as we can. * * Results: *	TRUE if it is. FALSE if it ain't. * * Side Effects: *	None. * * ----------------------------------------------------------------------- */BooleanJob_Empty (){    if (nJobs == 0) {	if (!Lst_IsEmpty(stoppedJobs) && !aborting) {	    /*	     * The job table is obviously not full if it has no jobs in	     * it...Try and restart the stopped jobs.	     */	    jobFull = FALSE;	    while (!jobFull && !Lst_IsEmpty(stoppedJobs)) {		JobRestart((Job *)Lst_DeQueue(stoppedJobs));	    }	    return(FALSE);	} else {	    return(TRUE);	}    } else {	return(FALSE);    }}/*- *----------------------------------------------------------------------- * JobMatch

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -