int cosystem(const char* cmd) { Coshell_t* co; Cojob_t* cj; int status; if (!cmd) return !eaccess(pathshell(), X_OK); if (!(co = coopen(NiL, CO_ANY, NiL))) return -1; if (cj = coexec(co, cmd, CO_SILENT, NiL, NiL, NiL)) cj = cowait(co, cj, -1); if (!cj) return -1; /* * synthesize wait() status from shell status * lack of synthesis is the standard's proprietary sellout */ status = cj->status; if (EXITED_TERM(status)) status &= ((1<<(EXIT_BITS-1))-1); else status = (status & ((1<<EXIT_BITS)-1)) << EXIT_BITS; return status; }
int block(int check) { register Cojob_t* cojob; register Joblist_t* job; Rule_t* r; int n; int clear = 0; int resume = 0; if (!state.coshell || !copending(state.coshell)) { if (jobs.intermediate) { /* * mark the jobs that must be generated */ n = 0; for (job = jobs.firstjob; job; job = job->next) if (job->target->must > ((unsigned int)(job->target->dynamic & D_intermediate) != 0)) { n = 1; break; } if (n) { /* * some intermediates must be generated */ error(2, "some intermediates must be generated"); } else { /* * accept missing intermediates */ while (job = jobs.firstjob) { if (error_info.trace || state.explain) error(state.explain ? 0 : -1, "cancelling %s action -- %s", job->target->name, job->status == INTERMEDIATE ? "intermediate not needed" : "missing intermediates accepted"); job->target->status = EXISTS; discard(job); } jobs.intermediate = 0; return 1; } } return 0; } for (;;) { state.waiting = 1; if ((cojob = cowait(state.coshell, check ? (Cojob_t*)state.coshell : (Cojob_t*)0, -1)) && (job = (Joblist_t*)cojob->local)) job->cojob = 0; if (trap()) { if (state.interpreter) clear = resume = 1; if (!cojob) continue; } state.waiting = 0; if (!cojob) { if (check) return 0; break; } if (r = getrule(external.jobdone)) { if (!jobs.tmp) jobs.tmp = sfstropen(); sfprintf(jobs.tmp, "%s %d %s %s", job->target->name, cojob->status, fmtelapsed(cojob->user, CO_QUANT), fmtelapsed(cojob->sys, CO_QUANT)); call(r, sfstruse(jobs.tmp)); } if (cojob->status) { if (n = !EXITED_TERM(cojob->status) || EXIT_CODE(cojob->status)) { if ((job->target->dynamic & D_hasafter) && hasafter(job->target, P_failure)) n = 0; error(n ? 2 : state.explain ? 0 : -1, "%s%s code %d making %s%s", n ? "*** " : null, ERROR_translate(NiL, NiL, NiL, EXITED_TERM(cojob->status) ? "termination" : "exit"), EXIT_CODE(cojob->status), job->target->name, (job->flags & CO_IGNORE) ? ERROR_translate(NiL, NiL, NiL, " ignored") : null); } if (!(job->flags & CO_IGNORE)) { job->flags |= CO_ERRORS; if (state.keepgoing || !n) { if (n) state.errors++; job->flags |= CO_KEEPGOING; } } if (state.interrupt || !(job->flags & (CO_IGNORE|CO_KEEPGOING))) clear = 1; } message((-3, "job: %s: interrupt=%d clear=%d status=%d flags=%08x", job->target->name, state.interrupt, clear, cojob->status, job->flags)); /* * job is done */ if (done(job, clear, cojob)) return 1; } if (resume) longjmp(state.resume.label, 1); if (!state.finish) { if (!copending(state.coshell)) { if (clear) finish(1); } else if (!state.interrupt) error(3, "lost contact with coshell"); } return 0; }