Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
Lst_ForEach(gn->commands, JobPrintCommand, job);
JobStart(gn, flags, previous)    GNode         *gn;	      /* target to create */    int	  	   flags;      /* flags for the job to override normal ones.			       * e.g. JOB_SPECIAL or JOB_IGNDOTS */    Job 	  *previous;  /* The previous Job structure for this node,			       * if any. */{    register Job  *job;       /* new job descriptor */    char	  *argv[4];   /* Argument vector to shell */    Boolean	  cmdsOK;     /* true if the nodes commands were all right */    Boolean 	  local;      /* Set true if the job was run locally */    Boolean 	  noExec;     /* Set true if we decide not to run the job */    int	          tfd;	      /* where to stash those pesky commands */    if (previous != NULL) {	previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);	job = previous;    } else {	job = (Job *) emalloc(sizeof(Job));	if (job == NULL) {	    Punt("JobStart out of memory");	}	flags |= JOB_FIRST;    }    job->node = gn;    job->tailCmds = NULL;    /*     * Set the initial value of the flags for this job based on the global     * ones and the node's attributes... Any flags supplied by the caller     * are also added to the field.     */    job->flags = 0;    if (Targ_Ignore(gn)) {	job->flags |= JOB_IGNERR;    }    if (Targ_Silent(gn)) {	job->flags |= JOB_SILENT;    }    job->flags |= flags;    /*     * Check the commands now so any attributes from .DEFAULT have a chance     * to migrate to the node     */    if (!compatMake && job->flags & JOB_FIRST) {	cmdsOK = Job_CheckCommands(gn, Error);    } else {	cmdsOK = TRUE;    }    /*     * If the -n flag wasn't given, we open up OUR (not the child's)     * temporary file to stuff commands in it. The thing is rd/wr so we don't     * need to reopen it to feed it to the shell. If the -n flag *was* given,     * we just set the file to be stdout. Cute, huh?     */    if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) {	/*	 * We're serious here, but if the commands were bogus, we're	 * also dead...	 */	if (!cmdsOK) {	    DieHorribly();	}	(void) strcpy(tfile, TMPPAT);	if ((tfd = mkstemp(tfile)) == -1)	    Punt("Cannot create temp file: %s", strerror(errno));	job->cmdFILE = fdopen(tfd, "w+");	eunlink(tfile);	if (job->cmdFILE == NULL) {	    close(tfd);	    Punt("Could not open %s", tfile);	}	(void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1);	/*	 * Send the commands to the command file, flush all its buffers then	 * rewind and remove the thing.	 */	noExec = FALSE;	/*	 * used to be backwards; replace when start doing multiple commands	 * per shell.	 */	if (compatMake) {	    /*	     * Be compatible: If this is the first time for this node,	     * verify its commands are ok and open the commands list for	     * sequential access by later invocations of JobStart.	     * Once that is done, we take the next command off the list	     * and print it to the command file. If the command was an	     * ellipsis, note that there's nothing more to execute.	     */	    if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){		cmdsOK = FALSE;	    } else {		LstNode	ln = Lst_Next(gn->commands);		if ((ln == NULL) ||		    JobPrintCommand((ClientData) Lst_Datum(ln),				    (ClientData) job))		{		    noExec = TRUE;		    Lst_Close(gn->commands);		}		if (noExec && !(job->flags & JOB_FIRST)) {		    /*		     * If we're not going to execute anything, the job		     * is done and we need to close down the various		     * file descriptors we've opened for output, then		     * call JobDoOutput to catch the final characters or		     * send the file to the screen... Note that the i/o streams		     * are only open if this isn't the first job.		     * Note also that this could not be done in		     * Job_CatchChildren b/c it wasn't clear if there were		     * more commands to execute or not...		     */		    JobClose(job);		}	    }	} else {	    /*	     * We can do all the commands at once. hooray for sanity	     */	    numCommands = 0;	    Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);	    /*	     * If we didn't print out any commands to the shell script,	     * there's not much point in executing the shell, is there?	     */	    if (numCommands == 0) {		noExec = TRUE;	    }	}    } else if (noExecute) {	/*	 * Not executing anything -- just print all the commands to stdout	 * in one fell swoop. This will still set up job->tailCmds correctly.	 */	if (lastNode != gn) {	    MESSAGE(stdout, gn);	    lastNode = gn;	}	job->cmdFILE = stdout;	/*	 * Only print the commands if they're ok, but don't die if they're	 * not -- just let the user know they're bad and keep going. It	 * doesn't do any harm in this case and may do some good.	 */	if (cmdsOK) {	    Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);	}	/*	 * Don't execute the shell, thank you.	 */	noExec = TRUE;    } else {	/*	 * Just touch the target and note that no shell should be executed.	 * Set cmdFILE to stdout to make life easier. Check the commands, too,	 * but don't die if they're no good -- it does no harm to keep working	 * up the graph.	 */	job->cmdFILE = stdout;    	Job_Touch(gn, job->flags&JOB_SILENT);	noExec = TRUE;    }    /*     * If we're not supposed to execute a shell, don't.     */    if (noExec) {	/*	 * Unlink and close the command file if we opened one	 */	if (job->cmdFILE != stdout) {	    if (job->cmdFILE != NULL)		(void) fclose(job->cmdFILE);	} else {	     (void) fflush(stdout);	}	/*	 * We only want to work our way up the graph if we aren't here because	 * the commands for the job were no good.	 */	if (cmdsOK) {	    if (aborting == 0) {		if (job->tailCmds != NULL) {		    Lst_ForEachFrom(job->node->commands, job->tailCmds,				    JobSaveCommand,				   (ClientData)job->node);		}		Make_Update(job->node);	    }	    free((Address)job);	    return(JOB_FINISHED);	} else {	    free((Address)job);	    return(JOB_ERROR);	}    } else {	(void) fflush(job->cmdFILE);    }    /*     * Set up the control arguments to the shell. This is based on the flags     * set earlier for this job.     */    JobMakeArgv(job, argv);    /*     * If we're using pipes to catch output, create the pipe by which we'll     * get the shell's output. If we're using files, print out that we're     * starting a job and then set up its temporary-file name.     */    if (!compatMake || (job->flags & JOB_FIRST)) {	if (usePipes) {	    int fd[2];	    if (pipe(fd) == -1)		Punt("Cannot create pipe: %s", strerror(errno));	    job->inPipe = fd[0];	    job->outPipe = fd[1];	    (void) fcntl(job->inPipe, F_SETFD, 1);	    (void) fcntl(job->outPipe, F_SETFD, 1);	} else {	    (void) fprintf(stdout, "Remaking `%s'\n", gn->name);  	    (void) fflush(stdout);	    (void) strcpy(job->outFile, TMPPAT);	    if ((job->outFd = mkstemp(job->outFile)) == -1)		Punt("Cannot create temp file: %s", strerror(errno));	    (void) fcntl(job->outFd, F_SETFD, 1);	}    }#ifdef REMOTE    if (!(gn->type & OP_NOEXPORT) && !(runLocalFirst && nLocal < maxLocal)) {#ifdef RMT_NO_EXEC	local = !Rmt_Export(shellPath, argv, job);#else	local = !Rmt_Begin(shellPath, argv, job->node);#endif /* RMT_NO_EXEC */	if (!local) {	    job->flags |= JOB_REMOTE;	}    } else#endif	local = TRUE;    if (local && (((nLocal >= maxLocal) &&	!(job->flags & JOB_SPECIAL) &&#ifdef REMOTE	(!(gn->type & OP_NOEXPORT) || (maxLocal != 0))#else	(maxLocal != 0)#endif	)))    {	/*	 * The job can only be run locally, but we've hit the limit of	 * local concurrency, so put the job on hold until some other job	 * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END)	 * may be run locally even when the local limit has been reached	 * (e.g. when maxLocal == 0), though they will be exported if at	 * all possible. In addition, any target marked with .NOEXPORT will	 * be run locally if maxLocal is 0.	 */	jobFull = TRUE;	if (DEBUG(JOB)) {	   (void) fprintf(stdout, "Can only run job locally.\n");	   (void) fflush(stdout);	}	job->flags |= JOB_RESTART;	Lst_AtEnd(stoppedJobs, (ClientData)job);    } else {	if ((nLocal >= maxLocal) && local) {	    /*	     * If we're running this job locally as a special case (see above),	     * at least say the table is full.	     */	    jobFull = TRUE;	    if (DEBUG(JOB)) {		(void) fprintf(stdout, "Local job queue is full.\n");		(void) fflush(stdout);	    }	}	JobExec(job, argv);    }    return(JOB_RUNNING);}