static void ForExec(void *valuep, void *argp) { char *value = (char *)valuep; For *arg = (For *)argp; BUFFER buf; /* Parse_FromString pushes stuff back, so we need to go over vars in reverse. */ if (arg->var == NULL) { arg->var = Lst_Last(&arg->vars); arg->text = Buf_Retrieve(&arg->buf); arg->freeold = false; } if (DEBUG(FOR)) (void)fprintf(stderr, "--- %s = %s\n", Var_LoopVarName(Lst_Datum(arg->var)), value); Buf_Init(&buf, arg->guess); Var_SubstVar(&buf, arg->text, Lst_Datum(arg->var), value); if (arg->freeold) free(arg->text); arg->text = Buf_Retrieve(&buf); arg->freeold = true; arg->var = Lst_Rev(arg->var); if (arg->var == NULL) Parse_FromString(arg->text, arg->lineno); }
/*- *----------------------------------------------------------------------- * Lst_AtEnd -- * Add a node to the end of the given list * * Input: * l List to which to add the datum * d Datum to add * * Results: * SUCCESS if life is good. * * Side Effects: * A new ListNode is created and added to the list. * *----------------------------------------------------------------------- */ ReturnStatus Lst_AtEnd(Lst l, void *d) { LstNode end; end = Lst_Last(l); return (Lst_InsertAfter(l, end, d)); }
/*- *----------------------------------------------------------------------- * Lst_EnQueue -- * Add the datum to the tail of the given list. * * Results: * SUCCESS or FAILURE as returned by Lst_InsertAfter. * * Side Effects: * the lastPtr field is altered all the time and the firstPtr field * will be altered if the list used to be empty. * *----------------------------------------------------------------------- */ ReturnStatus Lst_EnQueue(Lst l, void *d) { if (LstValid (l) == FALSE) { return (FAILURE); } return (Lst_InsertAfter(l, Lst_Last(l), d)); }
/*- *----------------------------------------------------------------------- * JobExec -- * Execute the shell for the given job. Called from JobStart * * Side Effects: * A shell is executed, outputs is altered and the Job structure added * to the job table. *----------------------------------------------------------------------- */ static void JobExec(Job *job) { pid_t cpid; /* ID of new child */ struct job_pid *p; int fds[4]; int *fdout = fds; int *fderr = fds+2; int i; banner(job, stdout); setup_engine(1); /* Create the pipe by which we'll get the shell's output. */ if (pipe(fdout) == -1) Punt("Cannot create pipe: %s", strerror(errno)); if (pipe(fderr) == -1) Punt("Cannot create pipe: %s", strerror(errno)); block_signals(); if ((cpid = fork()) == -1) { Punt("Cannot fork"); unblock_signals(); } else if (cpid == 0) { supervise_jobs = false; /* standard pipe code to route stdout and stderr */ close(fdout[0]); if (dup2(fdout[1], 1) == -1) Punt("Cannot dup2(outPipe): %s", strerror(errno)); if (fdout[1] != 1) close(fdout[1]); close(fderr[0]); if (dup2(fderr[1], 2) == -1) Punt("Cannot dup2(errPipe): %s", strerror(errno)); if (fderr[1] != 2) close(fderr[1]); /* * We want to switch the child into a different process family * so we can kill it and all its descendants in one fell swoop, * by killing its process family, but not commit suicide. */ (void)setpgid(0, getpid()); if (random_delay) if (!(nJobs == 1 && no_jobs_left())) usleep(random() % random_delay); setup_all_signals(SigHandler, SIG_DFL); unblock_signals(); /* this exits directly */ run_gnode_parallel(job->node); /*NOTREACHED*/ } else { supervise_jobs = true; job->pid = cpid; /* we set the current position in the buffers to the beginning * and mark another stream to watch in the outputs mask */ for (i = 0; i < 2; i++) prepare_pipe(&job->in[i], fds+2*i); } /* * Now the job is actually running, add it to the table. */ nJobs++; Lst_AtEnd(&runningJobs, job); if (job->flags & JOB_IS_EXPENSIVE) expensive_job = true; p = emalloc(sizeof(struct job_pid)); p->pid = cpid; Lst_AtEnd(&job_pids, p); job->p = Lst_Last(&job_pids); unblock_signals(); if (DEBUG(JOB)) { LstNode ln; (void)fprintf(stdout, "Running %ld (%s)\n", (long)cpid, job->node->name); for (ln = Lst_First(&job->node->commands); ln != NULL ; ln = Lst_Adv(ln)) fprintf(stdout, "\t%s\n", (char *)Lst_Datum(ln)); (void)fflush(stdout); } }