job.c revision 138916
11590Srgrimes/* 294589Sobrien * Copyright (c) 1988, 1989, 1990, 1993 394589Sobrien * The Regents of the University of California. All rights reserved. 45814Sjkh * Copyright (c) 1988, 1989 by Adam de Boor 51590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 61590Srgrimes * All rights reserved. 71590Srgrimes * 81590Srgrimes * This code is derived from software contributed to Berkeley by 91590Srgrimes * Adam de Boor. 101590Srgrimes * 111590Srgrimes * Redistribution and use in source and binary forms, with or without 121590Srgrimes * modification, are permitted provided that the following conditions 131590Srgrimes * are met: 141590Srgrimes * 1. Redistributions of source code must retain the above copyright 151590Srgrimes * notice, this list of conditions and the following disclaimer. 161590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171590Srgrimes * notice, this list of conditions and the following disclaimer in the 181590Srgrimes * documentation and/or other materials provided with the distribution. 191590Srgrimes * 3. All advertising materials mentioning features or use of this software 201590Srgrimes * must display the following acknowledgement: 211590Srgrimes * This product includes software developed by the University of 221590Srgrimes * California, Berkeley and its contributors. 231590Srgrimes * 4. Neither the name of the University nor the names of its contributors 241590Srgrimes * may be used to endorse or promote products derived from this software 251590Srgrimes * without specific prior written permission. 261590Srgrimes * 271590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 281590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 291590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 301590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 311590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 321590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 331590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 341590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 351590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 361590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 371590Srgrimes * SUCH DAMAGE. 3862833Swsanchez * 3962833Swsanchez * @(#)job.c 8.2 (Berkeley) 3/19/94 401590Srgrimes */ 411590Srgrimes 4262833Swsanchez#include <sys/cdefs.h> 4394587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/job.c 138916 2004-12-16 16:14:16Z harti $"); 441590Srgrimes 4535483Simp#ifndef OLD_JOKE 46103503Sjmallett#define OLD_JOKE 0 4735483Simp#endif /* OLD_JOKE */ 4835483Simp 491590Srgrimes/*- 501590Srgrimes * job.c -- 511590Srgrimes * handle the creation etc. of our child processes. 521590Srgrimes * 531590Srgrimes * Interface: 541590Srgrimes * Job_Make Start the creation of the given target. 551590Srgrimes * 561590Srgrimes * Job_CatchChildren Check for and handle the termination of any 571590Srgrimes * children. This must be called reasonably 581590Srgrimes * frequently to keep the whole make going at 591590Srgrimes * a decent clip, since job table entries aren't 601590Srgrimes * removed until their process is caught this way. 611590Srgrimes * Its single argument is TRUE if the function 621590Srgrimes * should block waiting for a child to terminate. 631590Srgrimes * 641590Srgrimes * Job_CatchOutput Print any output our children have produced. 651590Srgrimes * Should also be called fairly frequently to 661590Srgrimes * keep the user informed of what's going on. 671590Srgrimes * If no output is waiting, it will block for 681590Srgrimes * a time given by the SEL_* constants, below, 691590Srgrimes * or until output is ready. 701590Srgrimes * 711590Srgrimes * Job_Init Called to intialize this module. in addition, 721590Srgrimes * any commands attached to the .BEGIN target 731590Srgrimes * are executed before this function returns. 741590Srgrimes * Hence, the makefile must have been parsed 751590Srgrimes * before this function is called. 761590Srgrimes * 771590Srgrimes * Job_Full Return TRUE if the job table is filled. 781590Srgrimes * 791590Srgrimes * Job_Empty Return TRUE if the job table is completely 801590Srgrimes * empty. 811590Srgrimes * 821590Srgrimes * Job_ParseShell Given the line following a .SHELL target, parse 831590Srgrimes * the line as a shell specification. Returns 841590Srgrimes * FAILURE if the spec was incorrect. 851590Srgrimes * 8694594Sobrien * Job_Finish Perform any final processing which needs doing. 871590Srgrimes * This includes the execution of any commands 881590Srgrimes * which have been/were attached to the .END 891590Srgrimes * target. It should only be called when the 901590Srgrimes * job table is empty. 911590Srgrimes * 921590Srgrimes * Job_AbortAll Abort all currently running jobs. It doesn't 931590Srgrimes * handle output or do anything for the jobs, 941590Srgrimes * just kills them. It should only be called in 951590Srgrimes * an emergency, as it were. 961590Srgrimes * 971590Srgrimes * Job_CheckCommands Verify that the commands for a target are 981590Srgrimes * ok. Provide them if necessary and possible. 991590Srgrimes * 1001590Srgrimes * Job_Touch Update a target without really updating it. 1011590Srgrimes * 1021590Srgrimes * Job_Wait Wait for all currently-running jobs to finish. 1031590Srgrimes */ 1041590Srgrimes 1051590Srgrimes#include <sys/types.h> 1061590Srgrimes#include <sys/stat.h> 1071590Srgrimes#include <sys/file.h> 1081590Srgrimes#include <sys/time.h> 109107447Sru#ifdef USE_KQUEUE 110104475Sphk#include <sys/event.h> 111107447Sru#endif 1121590Srgrimes#include <sys/wait.h> 11394506Scharnier#include <err.h> 11494506Scharnier#include <errno.h> 1155814Sjkh#include <fcntl.h> 1161590Srgrimes#include <stdio.h> 1171590Srgrimes#include <string.h> 1185814Sjkh#include <signal.h> 11980381Ssheldonh#include <unistd.h> 12094506Scharnier#include <utime.h> 1211590Srgrimes#include "make.h" 1221590Srgrimes#include "hash.h" 1231590Srgrimes#include "dir.h" 1241590Srgrimes#include "job.h" 1251590Srgrimes#include "pathnames.h" 1261590Srgrimes 127137202Sharti#define STATIC static 128137202Sharti 1291590Srgrimes/* 1308874Srgrimes * error handling variables 1311590Srgrimes */ 1321590Srgrimesstatic int errors = 0; /* number of errors reported */ 1331590Srgrimesstatic int aborting = 0; /* why is the make aborting? */ 134103503Sjmallett#define ABORT_ERROR 1 /* Because of an error */ 135103503Sjmallett#define ABORT_INTERRUPT 2 /* Because it was interrupted */ 136103503Sjmallett#define ABORT_WAIT 3 /* Waiting for jobs to finish */ 1371590Srgrimes 13818730Ssteve/* 13918730Ssteve * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file 14018730Ssteve * is a char! So when we go above 127 we turn negative! 14118730Ssteve */ 142138232Sharti#define FILENO(a) ((unsigned)fileno(a)) 1431590Srgrimes 1441590Srgrimes/* 1451590Srgrimes * post-make command processing. The node postCommands is really just the 1461590Srgrimes * .END target but we keep it around to avoid having to search for it 1471590Srgrimes * all the time. 1481590Srgrimes */ 1491590Srgrimesstatic GNode *postCommands; /* node containing commands to execute when 1501590Srgrimes * everything else is done */ 1511590Srgrimesstatic int numCommands; /* The number of commands actually printed 1521590Srgrimes * for a target. Should this number be 1531590Srgrimes * 0, no shell will be executed. */ 1541590Srgrimes 1551590Srgrimes/* 1561590Srgrimes * Return values from JobStart. 1571590Srgrimes */ 158103503Sjmallett#define JOB_RUNNING 0 /* Job is running */ 159103503Sjmallett#define JOB_ERROR 1 /* Error in starting the job */ 160103503Sjmallett#define JOB_FINISHED 2 /* The job is already finished */ 161103503Sjmallett#define JOB_STOPPED 3 /* The job is stopped */ 1621590Srgrimes 1631590Srgrimes/* 16468898Skris * tfile is used to build temp file names to store shell commands to 165138232Sharti * execute. 16668898Skris */ 16768898Skrisstatic char tfile[sizeof(TMPPAT)]; 16868898Skris 16968898Skris/* 1701590Srgrimes * Descriptions for various shells. 1711590Srgrimes */ 172138228Shartistatic const DEF_SHELL_STRUCT(CShell, const) shells[] = { 1731590Srgrimes /* 1741590Srgrimes * CSH description. The csh can do echo control by playing 1751590Srgrimes * with the setting of the 'echo' shell variable. Sadly, 1761590Srgrimes * however, it is unable to do error control nicely. 1771590Srgrimes */ 1781590Srgrimes{ 1791590Srgrimes "csh", 180136841Sru TRUE, "unset verbose", "set verbose", "unset verbose", 13, 1811590Srgrimes FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", 1821590Srgrimes "v", "e", 1831590Srgrimes}, 1841590Srgrimes /* 1851590Srgrimes * SH description. Echo control is also possible and, under 1861590Srgrimes * sun UNIX anyway, one can even control error checking. 1871590Srgrimes */ 1881590Srgrimes{ 1891590Srgrimes "sh", 1901590Srgrimes TRUE, "set -", "set -v", "set -", 5, 19118730Ssteve TRUE, "set -e", "set +e", 19218730Ssteve#ifdef OLDBOURNESHELL 1931590Srgrimes FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", 19418730Ssteve#endif 1951590Srgrimes "v", "e", 1961590Srgrimes}, 1971590Srgrimes /* 19864739Sgreen * KSH description. The Korn shell has a superset of 19964739Sgreen * the Bourne shell's functionality. 20064739Sgreen */ 20164739Sgreen{ 20264739Sgreen "ksh", 20364739Sgreen TRUE, "set -", "set -v", "set -", 5, 20464739Sgreen TRUE, "set -e", "set +e", 20564739Sgreen "v", "e", 20664739Sgreen}, 2071590Srgrimes}; 208138079Shartistatic Shell *commandShell = NULL; /* this is the shell to which we pass 209138079Sharti * all commands in the Makefile. It is 210138079Sharti * set by the Job_ParseShell function */ 211138079Shartichar *shellPath = NULL, /* full pathname of executable image */ 212138079Sharti *shellName = NULL; /* last component of shell */ 2131590Srgrimes 2141590Srgrimes 2151590Srgrimesstatic int maxJobs; /* The most children we can run at once */ 21618730SsteveSTATIC int nJobs; /* The number of children currently running */ 217138916Sharti 218138916Sharti/* The structures that describe them */ 219138916ShartiSTATIC Lst jobs = Lst_Initializer(jobs); 220138916Sharti 22118730SsteveSTATIC Boolean jobFull; /* Flag to tell when the job table is full. It 2221590Srgrimes * is set TRUE when (1) the total number of 223137572Sphk * running jobs equals the maximum allowed */ 224104475Sphk#ifdef USE_KQUEUE 225104475Sphkstatic int kqfd; /* File descriptor obtained by kqueue() */ 226104475Sphk#else 2271590Srgrimesstatic fd_set outputs; /* Set of descriptors of pipes connected to 2281590Srgrimes * the output channels of children */ 2291590Srgrimes#endif 2301590Srgrimes 23118730SsteveSTATIC GNode *lastNode; /* The node for which output was most recently 2321590Srgrimes * produced. */ 23318730SsteveSTATIC char *targFmt; /* Format string to use to head output from a 2341590Srgrimes * job when it's not the most-recent job heard 2351590Srgrimes * from */ 2361590Srgrimes 237137202Sharti#define TARG_FMT "--- %s ---\n" /* Default format */ 238137202Sharti#define MESSAGE(fp, gn) \ 239138232Sharti fprintf(fp, targFmt, gn->name); 24018730Ssteve 2411590Srgrimes/* 242137252Sharti * When JobStart attempts to run a job but isn't allowed to 243137252Sharti * or when Job_CatchChildren detects a job that has 244137252Sharti * been stopped somehow, the job is placed on the stoppedJobs queue to be run 2458874Srgrimes * when the next job finishes. 246138916Sharti * 247138916Sharti * Lst of Job structures describing jobs that were stopped due to 248138916Sharti * concurrency limits or externally 2491590Srgrimes */ 250138916ShartiSTATIC Lst stoppedJobs = Lst_Initializer(stoppedJobs); 2511590Srgrimes 252137606SphkSTATIC int fifoFd; /* Fd of our job fifo */ 253137606SphkSTATIC char fifoName[] = "/tmp/make_fifo_XXXXXXXXX"; 254137606SphkSTATIC int fifoMaster; 2551590Srgrimes 256137605Shartistatic sig_atomic_t interrupted; 257137605Sharti 258137605Sharti 2591590Srgrimes#if defined(USE_PGRP) && defined(SYSV) 26018730Ssteve# define KILL(pid, sig) killpg(-(pid), (sig)) 2611590Srgrimes#else 2621590Srgrimes# if defined(USE_PGRP) 26318730Ssteve# define KILL(pid, sig) killpg((pid), (sig)) 2641590Srgrimes# else 26518730Ssteve# define KILL(pid, sig) kill((pid), (sig)) 2661590Srgrimes# endif 2671590Srgrimes#endif 2681590Srgrimes 26918730Ssteve/* 27018730Ssteve * Grmpf... There is no way to set bits of the wait structure 27118730Ssteve * anymore with the stupid W*() macros. I liked the union wait 27218730Ssteve * stuff much more. So, we devise our own macros... This is 27318730Ssteve * really ugly, use dramamine sparingly. You have been warned. 27418730Ssteve */ 275103503Sjmallett#define W_SETMASKED(st, val, fun) \ 27618730Ssteve { \ 277138232Sharti int sh = (int)~0; \ 27818730Ssteve int mask = fun(sh); \ 27918730Ssteve \ 28018730Ssteve for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ 28118730Ssteve continue; \ 28218730Ssteve *(st) = (*(st) & ~mask) | ((val) << sh); \ 28318730Ssteve } 28418730Ssteve 285103503Sjmallett#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) 286103503Sjmallett#define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) 28718730Ssteve 28818730Ssteve 28992921Simpstatic int JobCondPassSig(void *, void *); 29092921Simpstatic void JobPassSig(int); 29192921Simpstatic int JobPrintCommand(void *, void *); 29292921Simpstatic int JobSaveCommand(void *, void *); 29392921Simpstatic void JobClose(Job *); 29492921Simpstatic void JobFinish(Job *, int *); 29592921Simpstatic void JobExec(Job *, char **); 29692921Simpstatic void JobMakeArgv(Job *, char **); 29792921Simpstatic void JobRestart(Job *); 29892921Simpstatic int JobStart(GNode *, int, Job *); 29992921Simpstatic char *JobOutput(Job *, char *, char *, int); 30092921Simpstatic void JobDoOutput(Job *, Boolean); 301138228Shartistatic Shell *JobMatchShell(const char *); 30292921Simpstatic void JobInterrupt(int, int); 30392921Simpstatic void JobRestartJobs(void); 3041590Srgrimes 305137605Sharti/* 306137605Sharti * JobCatchSignal 307137605Sharti * 308137605Sharti * Got a signal. Set global variables and hope that someone will 309137605Sharti * handle it. 310137605Sharti */ 311137605Shartistatic void 312137605ShartiJobCatchSig(int signo) 313137605Sharti{ 314137605Sharti 315137605Sharti interrupted = signo; 316137605Sharti} 317137605Sharti 3181590Srgrimes/*- 3191590Srgrimes *----------------------------------------------------------------------- 3201590Srgrimes * JobCondPassSig -- 321137252Sharti * Pass a signal to a job if USE_PGRP is defined. 3221590Srgrimes * 3231590Srgrimes * Results: 3241590Srgrimes * === 0 3251590Srgrimes * 3261590Srgrimes * Side Effects: 3271590Srgrimes * None, except the job may bite it. 3281590Srgrimes * 3291590Srgrimes *----------------------------------------------------------------------- 3301590Srgrimes */ 3311590Srgrimesstatic int 332104696SjmallettJobCondPassSig(void *jobp, void *signop) 3331590Srgrimes{ 334138264Sharti Job *job = jobp; 335138232Sharti int signo = *(int *)signop; 336137202Sharti 337137252Sharti DEBUGF(JOB, ("JobCondPassSig passing signal %d to child %d.\n", 338137252Sharti signo, job->pid)); 3391590Srgrimes KILL(job->pid, signo); 340138232Sharti return (0); 3411590Srgrimes} 3421590Srgrimes 3431590Srgrimes/*- 3441590Srgrimes *----------------------------------------------------------------------- 3451590Srgrimes * JobPassSig -- 346137252Sharti * Pass a signal on to all local jobs if 3471590Srgrimes * USE_PGRP is defined, then die ourselves. 3481590Srgrimes * 3491590Srgrimes * Results: 3501590Srgrimes * None. 3511590Srgrimes * 3521590Srgrimes * Side Effects: 3531590Srgrimes * We die by the same signal. 3548874Srgrimes * 3551590Srgrimes *----------------------------------------------------------------------- 3561590Srgrimes */ 3571590Srgrimesstatic void 358104696SjmallettJobPassSig(int signo) 3591590Srgrimes{ 36018730Ssteve sigset_t nmask, omask; 36118730Ssteve struct sigaction act; 3628874Srgrimes 363137605Sharti sigemptyset(&nmask); 364137605Sharti sigaddset(&nmask, signo); 365137605Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 366137605Sharti 367103545Sjmallett DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo)); 368138916Sharti Lst_ForEach(&jobs, JobCondPassSig, &signo); 3691590Srgrimes 3701590Srgrimes /* 3711590Srgrimes * Deal with proper cleanup based on the signal received. We only run 3721590Srgrimes * the .INTERRUPT target if the signal was in fact an interrupt. The other 3731590Srgrimes * three termination signals are more of a "get out *now*" command. 3741590Srgrimes */ 3751590Srgrimes if (signo == SIGINT) { 37618730Ssteve JobInterrupt(TRUE, signo); 3771590Srgrimes } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) { 37818730Ssteve JobInterrupt(FALSE, signo); 3791590Srgrimes } 3808874Srgrimes 3811590Srgrimes /* 3821590Srgrimes * Leave gracefully if SIGQUIT, rather than core dumping. 3831590Srgrimes */ 3841590Srgrimes if (signo == SIGQUIT) { 38538520Scracauer signo = SIGINT; 3861590Srgrimes } 3878874Srgrimes 3881590Srgrimes /* 3891590Srgrimes * Send ourselves the signal now we've given the message to everyone else. 3901590Srgrimes * Note we block everything else possible while we're getting the signal. 3911590Srgrimes * This ensures that all our jobs get continued when we wake up before 3921590Srgrimes * we take any other signal. 393137605Sharti * XXX this comment seems wrong. 3941590Srgrimes */ 39518730Ssteve act.sa_handler = SIG_DFL; 39618730Ssteve sigemptyset(&act.sa_mask); 39718730Ssteve act.sa_flags = 0; 39818730Ssteve sigaction(signo, &act, NULL); 3991590Srgrimes 400138232Sharti DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n", 401138232Sharti ~0 & ~(1 << (signo - 1)))); 402138232Sharti signal(signo, SIG_DFL); 4031590Srgrimes 404138232Sharti KILL(getpid(), signo); 40518730Ssteve 4065814Sjkh signo = SIGCONT; 407138916Sharti Lst_ForEach(&jobs, JobCondPassSig, &signo); 4081590Srgrimes 40918730Ssteve sigprocmask(SIG_SETMASK, &omask, NULL); 410138232Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 41118730Ssteve act.sa_handler = JobPassSig; 41218730Ssteve sigaction(signo, &act, NULL); 4131590Srgrimes} 4141590Srgrimes 4151590Srgrimes/*- 4161590Srgrimes *----------------------------------------------------------------------- 4171590Srgrimes * JobCmpPid -- 4181590Srgrimes * Compare the pid of the job with the given pid and return 0 if they 4191590Srgrimes * are equal. This function is called from Job_CatchChildren via 4201590Srgrimes * Lst_Find to find the job descriptor of the finished job. 4211590Srgrimes * 4221590Srgrimes * Results: 4231590Srgrimes * 0 if the pid's match 4241590Srgrimes * 4251590Srgrimes * Side Effects: 4261590Srgrimes * None 4271590Srgrimes *----------------------------------------------------------------------- 4281590Srgrimes */ 4291590Srgrimesstatic int 430138561ShartiJobCmpPid(const void *job, const void *pid) 4311590Srgrimes{ 432138264Sharti 433138561Sharti return (*(const int *)pid - ((const Job *)job)->pid); 4341590Srgrimes} 4351590Srgrimes 4361590Srgrimes/*- 4371590Srgrimes *----------------------------------------------------------------------- 4381590Srgrimes * JobPrintCommand -- 4391590Srgrimes * Put out another command for the given job. If the command starts 4401590Srgrimes * with an @ or a - we process it specially. In the former case, 4411590Srgrimes * so long as the -s and -n flags weren't given to make, we stick 4421590Srgrimes * a shell-specific echoOff command in the script. In the latter, 4431590Srgrimes * we ignore errors for the entire job, unless the shell has error 4441590Srgrimes * control. 4451590Srgrimes * If the command is just "..." we take all future commands for this 4461590Srgrimes * job to be commands to be executed once the entire graph has been 4471590Srgrimes * made and return non-zero to signal that the end of the commands 4481590Srgrimes * was reached. These commands are later attached to the postCommands 44994594Sobrien * node and executed by Job_Finish when all things are done. 4501590Srgrimes * This function is called from JobStart via Lst_ForEach. 4511590Srgrimes * 4521590Srgrimes * Results: 4531590Srgrimes * Always 0, unless the command was "..." 4541590Srgrimes * 4551590Srgrimes * Side Effects: 4561590Srgrimes * If the command begins with a '-' and the shell has no error control, 4571590Srgrimes * the JOB_IGNERR flag is set in the job descriptor. 4581590Srgrimes * If the command is "..." and we're not ignoring such things, 4591590Srgrimes * tailCmds is set to the successor node of the cmd. 4601590Srgrimes * numCommands is incremented if the command is actually printed. 4611590Srgrimes *----------------------------------------------------------------------- 4621590Srgrimes */ 4631590Srgrimesstatic int 464104696SjmallettJobPrintCommand(void *cmdp, void *jobp) 4651590Srgrimes{ 4661590Srgrimes Boolean noSpecials; /* true if we shouldn't worry about 4671590Srgrimes * inserting special commands into 4681590Srgrimes * the input stream. */ 4691590Srgrimes Boolean shutUp = FALSE; /* true if we put a no echo command 4701590Srgrimes * into the command file */ 4711590Srgrimes Boolean errOff = FALSE; /* true if we turned error checking 4721590Srgrimes * off before printing the command 4731590Srgrimes * and need to turn it back on */ 4741590Srgrimes char *cmdTemplate; /* Template to use when printing the 4751590Srgrimes * command */ 4761590Srgrimes char *cmdStart; /* Start of expanded command */ 477138512Sharti LstNode *cmdNode; /* Node for replacing the command */ 478138264Sharti char *cmd = cmdp; 479138264Sharti Job *job = jobp; 4801590Srgrimes 48118730Ssteve noSpecials = (noExecute && !(job->node->type & OP_MAKE)); 4821590Srgrimes 48318730Ssteve if (strcmp(cmd, "...") == 0) { 4848874Srgrimes job->node->type |= OP_SAVE_CMDS; 4851590Srgrimes if ((job->flags & JOB_IGNDOTS) == 0) { 486138916Sharti job->tailCmds = Lst_Succ(Lst_Member(&job->node->commands, cmd)); 487138232Sharti return (1); 4881590Srgrimes } 489138232Sharti return (0); 4901590Srgrimes } 4911590Srgrimes 492103508Sjmallett#define DBPRINTF(fmt, arg) \ 493103545Sjmallett DEBUGF(JOB, (fmt, arg)); \ 494138232Sharti fprintf(job->cmdFILE, fmt, arg); \ 495138232Sharti fflush(job->cmdFILE); 4961590Srgrimes 4971590Srgrimes numCommands += 1; 4981590Srgrimes 4991590Srgrimes /* 5001590Srgrimes * For debugging, we replace each command with the result of expanding 5011590Srgrimes * the variables in the command. 5021590Srgrimes */ 503138916Sharti cmdNode = Lst_Member(&job->node->commands, cmd); 50418730Ssteve cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE); 505138264Sharti Lst_Replace(cmdNode, cmdStart); 5061590Srgrimes 5071590Srgrimes cmdTemplate = "%s\n"; 5081590Srgrimes 5091590Srgrimes /* 510132839Sharti * Check for leading @', -' or +'s to control echoing, error checking, 511132839Sharti * and execution on -n. 5121590Srgrimes */ 513132839Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 514132839Sharti switch (*cmd) { 515132839Sharti 516132839Sharti case '@': 51760569Swill shutUp = DEBUG(LOUD) ? FALSE : TRUE; 518132839Sharti break; 519132839Sharti 520132839Sharti case '-': 5211590Srgrimes errOff = TRUE; 522132839Sharti break; 523132839Sharti 524132839Sharti case '+': 525132839Sharti if (noSpecials) { 526132839Sharti /* 527132839Sharti * We're not actually exececuting anything... 528132839Sharti * but this one needs to be - use compat mode just for it. 529132839Sharti */ 530132839Sharti Compat_RunCommand(cmdp, job->node); 531132839Sharti return (0); 532132839Sharti } 533132839Sharti break; 5341590Srgrimes } 5351590Srgrimes cmd++; 5361590Srgrimes } 5371590Srgrimes 538138232Sharti while (isspace((unsigned char)*cmd)) 5391590Srgrimes cmd++; 5401590Srgrimes 5411590Srgrimes if (shutUp) { 54218730Ssteve if (!(job->flags & JOB_SILENT) && !noSpecials && 5431590Srgrimes commandShell->hasEchoCtl) { 54418730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 5451590Srgrimes } else { 5461590Srgrimes shutUp = FALSE; 5471590Srgrimes } 5481590Srgrimes } 5491590Srgrimes 5501590Srgrimes if (errOff) { 55118730Ssteve if ( !(job->flags & JOB_IGNERR) && !noSpecials) { 5521590Srgrimes if (commandShell->hasErrCtl) { 5531590Srgrimes /* 5541590Srgrimes * we don't want the error-control commands showing 5551590Srgrimes * up either, so we turn off echoing while executing 5561590Srgrimes * them. We could put another field in the shell 5571590Srgrimes * structure to tell JobDoOutput to look for this 5581590Srgrimes * string too, but why make it any more complex than 5591590Srgrimes * it already is? 5601590Srgrimes */ 56118730Ssteve if (!(job->flags & JOB_SILENT) && !shutUp && 5621590Srgrimes commandShell->hasEchoCtl) { 56318730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 56418730Ssteve DBPRINTF("%s\n", commandShell->ignErr); 56518730Ssteve DBPRINTF("%s\n", commandShell->echoOn); 5661590Srgrimes } else { 56718730Ssteve DBPRINTF("%s\n", commandShell->ignErr); 5681590Srgrimes } 5691590Srgrimes } else if (commandShell->ignErr && 57018730Ssteve (*commandShell->ignErr != '\0')) 5711590Srgrimes { 5721590Srgrimes /* 5731590Srgrimes * The shell has no error control, so we need to be 5741590Srgrimes * weird to get it to ignore any errors from the command. 5751590Srgrimes * If echoing is turned on, we turn it off and use the 5761590Srgrimes * errCheck template to echo the command. Leave echoing 5771590Srgrimes * off so the user doesn't see the weirdness we go through 5781590Srgrimes * to ignore errors. Set cmdTemplate to use the weirdness 5791590Srgrimes * instead of the simple "%s\n" template. 5801590Srgrimes */ 58118730Ssteve if (!(job->flags & JOB_SILENT) && !shutUp && 5821590Srgrimes commandShell->hasEchoCtl) { 58318730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 58418730Ssteve DBPRINTF(commandShell->errCheck, cmd); 5851590Srgrimes shutUp = TRUE; 5861590Srgrimes } 5871590Srgrimes cmdTemplate = commandShell->ignErr; 5881590Srgrimes /* 5891590Srgrimes * The error ignoration (hee hee) is already taken care 5901590Srgrimes * of by the ignErr template, so pretend error checking 5911590Srgrimes * is still on. 5921590Srgrimes */ 5931590Srgrimes errOff = FALSE; 5941590Srgrimes } else { 5951590Srgrimes errOff = FALSE; 5961590Srgrimes } 5971590Srgrimes } else { 5981590Srgrimes errOff = FALSE; 5991590Srgrimes } 6001590Srgrimes } 6018874Srgrimes 60218730Ssteve DBPRINTF(cmdTemplate, cmd); 6038874Srgrimes 6041590Srgrimes if (errOff) { 6051590Srgrimes /* 6061590Srgrimes * If echoing is already off, there's no point in issuing the 6071590Srgrimes * echoOff command. Otherwise we issue it and pretend it was on 6081590Srgrimes * for the whole command... 6091590Srgrimes */ 610138264Sharti if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl) { 61118730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 6121590Srgrimes shutUp = TRUE; 6131590Srgrimes } 61418730Ssteve DBPRINTF("%s\n", commandShell->errCheck); 6151590Srgrimes } 6161590Srgrimes if (shutUp) { 61718730Ssteve DBPRINTF("%s\n", commandShell->echoOn); 6181590Srgrimes } 619138232Sharti return (0); 6201590Srgrimes} 6211590Srgrimes 6221590Srgrimes/*- 6231590Srgrimes *----------------------------------------------------------------------- 6241590Srgrimes * JobSaveCommand -- 6251590Srgrimes * Save a command to be executed when everything else is done. 6261590Srgrimes * Callback function for JobFinish... 6271590Srgrimes * 6281590Srgrimes * Results: 6291590Srgrimes * Always returns 0 6301590Srgrimes * 6311590Srgrimes * Side Effects: 6321590Srgrimes * The command is tacked onto the end of postCommands's commands list. 6331590Srgrimes * 6341590Srgrimes *----------------------------------------------------------------------- 6351590Srgrimes */ 6361590Srgrimesstatic int 637104696SjmallettJobSaveCommand(void *cmd, void *gn) 6381590Srgrimes{ 639138232Sharti 640138264Sharti cmd = Var_Subst(NULL, cmd, gn, FALSE); 641138916Sharti Lst_AtEnd(&postCommands->commands, cmd); 642138232Sharti return (0); 6431590Srgrimes} 6441590Srgrimes 64518730Ssteve 6461590Srgrimes/*- 6471590Srgrimes *----------------------------------------------------------------------- 64818730Ssteve * JobClose -- 64918730Ssteve * Called to close both input and output pipes when a job is finished. 65018730Ssteve * 65118730Ssteve * Results: 65218730Ssteve * Nada 65318730Ssteve * 65418730Ssteve * Side Effects: 65518730Ssteve * The file descriptors associated with the job are closed. 65618730Ssteve * 65718730Ssteve *----------------------------------------------------------------------- 65818730Ssteve */ 65918730Sstevestatic void 660104696SjmallettJobClose(Job *job) 66118730Ssteve{ 662138232Sharti 66318730Ssteve if (usePipes) { 664137202Sharti#if !defined(USE_KQUEUE) 66518730Ssteve FD_CLR(job->inPipe, &outputs); 66618730Ssteve#endif 66718730Ssteve if (job->outPipe != job->inPipe) { 668138232Sharti close(job->outPipe); 66918730Ssteve } 67018730Ssteve JobDoOutput(job, TRUE); 671138232Sharti close(job->inPipe); 67218730Ssteve } else { 673138232Sharti close(job->outFd); 67418730Ssteve JobDoOutput(job, TRUE); 67518730Ssteve } 67618730Ssteve} 67718730Ssteve 67818730Ssteve/*- 67918730Ssteve *----------------------------------------------------------------------- 6801590Srgrimes * JobFinish -- 6811590Srgrimes * Do final processing for the given job including updating 6821590Srgrimes * parents and starting new jobs as available/necessary. Note 6831590Srgrimes * that we pay no attention to the JOB_IGNERR flag here. 6841590Srgrimes * This is because when we're called because of a noexecute flag 6851590Srgrimes * or something, jstat.w_status is 0 and when called from 6861590Srgrimes * Job_CatchChildren, the status is zeroed if it s/b ignored. 6871590Srgrimes * 6881590Srgrimes * Results: 6891590Srgrimes * None 6901590Srgrimes * 6911590Srgrimes * Side Effects: 6921590Srgrimes * Some nodes may be put on the toBeMade queue. 6931590Srgrimes * Final commands for the job are placed on postCommands. 6941590Srgrimes * 6951590Srgrimes * If we got an error and are aborting (aborting == ABORT_ERROR) and 6961590Srgrimes * the job list is now empty, we are done for the day. 6971590Srgrimes * If we recognized an error (errors !=0), we set the aborting flag 6981590Srgrimes * to ABORT_ERROR so no more jobs will be started. 6991590Srgrimes *----------------------------------------------------------------------- 7001590Srgrimes */ 7011590Srgrimes/*ARGSUSED*/ 7021590Srgrimesstatic void 703104696SjmallettJobFinish(Job *job, int *status) 7041590Srgrimes{ 70518730Ssteve Boolean done; 7061590Srgrimes 70718730Ssteve if ((WIFEXITED(*status) && 70818730Ssteve (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) || 70918730Ssteve (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT))) 7101590Srgrimes { 7111590Srgrimes /* 7121590Srgrimes * If it exited non-zero and either we're doing things our 7131590Srgrimes * way or we're not ignoring errors, the job is finished. 7141590Srgrimes * Similarly, if the shell died because of a signal 7151590Srgrimes * the job is also finished. In these 7161590Srgrimes * cases, finish out the job's output before printing the exit 7171590Srgrimes * status... 7181590Srgrimes */ 71918730Ssteve JobClose(job); 7201590Srgrimes if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 721138232Sharti fclose(job->cmdFILE); 7221590Srgrimes } 7231590Srgrimes done = TRUE; 72418730Ssteve } else if (WIFEXITED(*status)) { 7251590Srgrimes /* 7261590Srgrimes * Deal with ignored errors in -B mode. We need to print a message 7271590Srgrimes * telling of the ignored error as well as setting status.w_status 7281590Srgrimes * to 0 so the next command gets run. To do this, we set done to be 72918730Ssteve * TRUE if in -B mode and the job exited non-zero. 73018730Ssteve */ 73118730Ssteve done = WEXITSTATUS(*status) != 0; 73218730Ssteve /* 73318730Ssteve * Old comment said: "Note we don't 7341590Srgrimes * want to close down any of the streams until we know we're at the 73518730Ssteve * end." 73618730Ssteve * But we do. Otherwise when are we going to print the rest of the 73718730Ssteve * stuff? 7381590Srgrimes */ 73918730Ssteve JobClose(job); 7401590Srgrimes } else { 7411590Srgrimes /* 7421590Srgrimes * No need to close things down or anything. 7431590Srgrimes */ 7441590Srgrimes done = FALSE; 7451590Srgrimes } 7468874Srgrimes 7471590Srgrimes if (done || 74818730Ssteve WIFSTOPPED(*status) || 74918730Ssteve (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) || 7501590Srgrimes DEBUG(JOB)) 7511590Srgrimes { 7521590Srgrimes FILE *out; 7538874Srgrimes 75418730Ssteve if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 7551590Srgrimes /* 7561590Srgrimes * If output is going to a file and this job is ignoring 7571590Srgrimes * errors, arrange to have the exit status sent to the 7581590Srgrimes * output file as well. 7591590Srgrimes */ 76018730Ssteve out = fdopen(job->outFd, "w"); 76194582Sobrien if (out == NULL) 76294582Sobrien Punt("Cannot fdopen"); 7631590Srgrimes } else { 7641590Srgrimes out = stdout; 7651590Srgrimes } 7661590Srgrimes 76718730Ssteve if (WIFEXITED(*status)) { 768103545Sjmallett DEBUGF(JOB, ("Process %d exited.\n", job->pid)); 76918730Ssteve if (WEXITSTATUS(*status) != 0) { 7701590Srgrimes if (usePipes && job->node != lastNode) { 77118730Ssteve MESSAGE(out, job->node); 7721590Srgrimes lastNode = job->node; 7731590Srgrimes } 774138232Sharti fprintf(out, "*** Error code %d%s\n", 77518730Ssteve WEXITSTATUS(*status), 77618730Ssteve (job->flags & JOB_IGNERR) ? "(ignored)" : ""); 7771590Srgrimes 7781590Srgrimes if (job->flags & JOB_IGNERR) { 77918730Ssteve *status = 0; 7801590Srgrimes } 7811590Srgrimes } else if (DEBUG(JOB)) { 7821590Srgrimes if (usePipes && job->node != lastNode) { 78318730Ssteve MESSAGE(out, job->node); 7841590Srgrimes lastNode = job->node; 7851590Srgrimes } 786138232Sharti fprintf(out, "*** Completed successfully\n"); 7871590Srgrimes } 78818730Ssteve } else if (WIFSTOPPED(*status)) { 789103545Sjmallett DEBUGF(JOB, ("Process %d stopped.\n", job->pid)); 7901590Srgrimes if (usePipes && job->node != lastNode) { 79118730Ssteve MESSAGE(out, job->node); 7921590Srgrimes lastNode = job->node; 7931590Srgrimes } 794138232Sharti fprintf(out, "*** Stopped -- signal %d\n", 795137252Sharti WSTOPSIG(*status)); 7961590Srgrimes job->flags |= JOB_RESUME; 797138916Sharti Lst_AtEnd(&stoppedJobs, job); 798138232Sharti fflush(out); 7991590Srgrimes return; 80018730Ssteve } else if (WTERMSIG(*status) == SIGCONT) { 8011590Srgrimes /* 8021590Srgrimes * If the beastie has continued, shift the Job from the stopped 8031590Srgrimes * list to the running one (or re-stop it if concurrency is 8041590Srgrimes * exceeded) and go and get another child. 8051590Srgrimes */ 806137252Sharti if (job->flags & (JOB_RESUME|JOB_RESTART)) { 8071590Srgrimes if (usePipes && job->node != lastNode) { 80818730Ssteve MESSAGE(out, job->node); 8091590Srgrimes lastNode = job->node; 8101590Srgrimes } 811138232Sharti fprintf(out, "*** Continued\n"); 8121590Srgrimes } 81318730Ssteve if (!(job->flags & JOB_CONTINUING)) { 814103545Sjmallett DEBUGF(JOB, ("Warning: process %d was not continuing.\n", job->pid)); 81518730Ssteve#ifdef notdef 81618730Ssteve /* 81718730Ssteve * We don't really want to restart a job from scratch just 81818730Ssteve * because it continued, especially not without killing the 81918730Ssteve * continuing process! That's why this is ifdef'ed out. 82018730Ssteve * FD - 9/17/90 82118730Ssteve */ 8221590Srgrimes JobRestart(job); 82318730Ssteve#endif 8241590Srgrimes } 82518730Ssteve job->flags &= ~JOB_CONTINUING; 826138916Sharti Lst_AtEnd(&jobs, job); 82718730Ssteve nJobs += 1; 828137252Sharti DEBUGF(JOB, ("Process %d is continuing locally.\n", job->pid)); 82918730Ssteve if (nJobs == maxJobs) { 83018730Ssteve jobFull = TRUE; 831103545Sjmallett DEBUGF(JOB, ("Job queue is full.\n")); 83218730Ssteve } 833138232Sharti fflush(out); 83418730Ssteve return; 8351590Srgrimes } else { 8361590Srgrimes if (usePipes && job->node != lastNode) { 83718730Ssteve MESSAGE(out, job->node); 8381590Srgrimes lastNode = job->node; 8391590Srgrimes } 840138232Sharti fprintf(out, "*** Signal %d\n", WTERMSIG(*status)); 8411590Srgrimes } 8421590Srgrimes 843138232Sharti fflush(out); 8441590Srgrimes } 8451590Srgrimes 8461590Srgrimes /* 8471590Srgrimes * Now handle the -B-mode stuff. If the beast still isn't finished, 8481590Srgrimes * try and restart the job on the next command. If JobStart says it's 8491590Srgrimes * ok, it's ok. If there's an error, this puppy is done. 8501590Srgrimes */ 851138564Sharti if (compatMake && WIFEXITED(*status) && 852138564Sharti Lst_Succ(job->node->compat_command) != NULL) { 85318730Ssteve switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { 85418730Ssteve case JOB_RUNNING: 85518730Ssteve done = FALSE; 85618730Ssteve break; 85718730Ssteve case JOB_ERROR: 85818730Ssteve done = TRUE; 85918730Ssteve W_SETEXITSTATUS(status, 1); 86018730Ssteve break; 86118730Ssteve case JOB_FINISHED: 86218730Ssteve /* 86318730Ssteve * If we got back a JOB_FINISHED code, JobStart has already 86418730Ssteve * called Make_Update and freed the job descriptor. We set 86518730Ssteve * done to false here to avoid fake cycles and double frees. 86618730Ssteve * JobStart needs to do the update so we can proceed up the 86718730Ssteve * graph when given the -n flag.. 86818730Ssteve */ 86918730Ssteve done = FALSE; 87018730Ssteve break; 871104108Sjmallett default: 872104108Sjmallett break; 8731590Srgrimes } 8741590Srgrimes } else { 8751590Srgrimes done = TRUE; 8761590Srgrimes } 8771590Srgrimes 8788874Srgrimes 8791590Srgrimes if (done && 8801590Srgrimes (aborting != ABORT_ERROR) && 8811590Srgrimes (aborting != ABORT_INTERRUPT) && 88218730Ssteve (*status == 0)) 8831590Srgrimes { 8841590Srgrimes /* 8851590Srgrimes * As long as we aren't aborting and the job didn't return a non-zero 8861590Srgrimes * status that we shouldn't ignore, we call Make_Update to update 8871590Srgrimes * the parents. In addition, any saved commands for the node are placed 8881590Srgrimes * on the .END target. 8891590Srgrimes */ 89069527Swill if (job->tailCmds != NULL) { 891138916Sharti Lst_ForEachFrom(&job->node->commands, job->tailCmds, 892138264Sharti JobSaveCommand, job->node); 8931590Srgrimes } 8941590Srgrimes job->node->made = MADE; 89518730Ssteve Make_Update(job->node); 89669531Swill free(job); 89718730Ssteve } else if (*status != 0) { 8981590Srgrimes errors += 1; 89969531Swill free(job); 9001590Srgrimes } 9011590Srgrimes 90218730Ssteve JobRestartJobs(); 9031590Srgrimes 9041590Srgrimes /* 9051590Srgrimes * Set aborting if any error. 9061590Srgrimes */ 9071590Srgrimes if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) { 9081590Srgrimes /* 9091590Srgrimes * If we found any errors in this batch of children and the -k flag 9101590Srgrimes * wasn't given, we set the aborting flag so no more jobs get 9111590Srgrimes * started. 9121590Srgrimes */ 9131590Srgrimes aborting = ABORT_ERROR; 9141590Srgrimes } 9158874Srgrimes 91668898Skris if ((aborting == ABORT_ERROR) && Job_Empty()) 9171590Srgrimes /* 9181590Srgrimes * If we are aborting and the job table is now empty, we finish. 9191590Srgrimes */ 92018730Ssteve Finish(errors); 9211590Srgrimes} 9221590Srgrimes 9231590Srgrimes/*- 9241590Srgrimes *----------------------------------------------------------------------- 9251590Srgrimes * Job_Touch -- 9261590Srgrimes * Touch the given target. Called by JobStart when the -t flag was 927104696Sjmallett * given. Prints messages unless told to be silent. 9281590Srgrimes * 9291590Srgrimes * Results: 9301590Srgrimes * None 9311590Srgrimes * 9321590Srgrimes * Side Effects: 9331590Srgrimes * The data modification of the file is changed. In addition, if the 9341590Srgrimes * file did not exist, it is created. 9351590Srgrimes *----------------------------------------------------------------------- 9361590Srgrimes */ 9371590Srgrimesvoid 938104696SjmallettJob_Touch(GNode *gn, Boolean silent) 9391590Srgrimes{ 9401590Srgrimes int streamID; /* ID of stream opened to do the touch */ 94118730Ssteve struct utimbuf times; /* Times for utime() call */ 9421590Srgrimes 943138264Sharti if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) { 9441590Srgrimes /* 9451590Srgrimes * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets 9461590Srgrimes * and, as such, shouldn't really be created. 9471590Srgrimes */ 9481590Srgrimes return; 9491590Srgrimes } 9508874Srgrimes 9511590Srgrimes if (!silent) { 952138232Sharti fprintf(stdout, "touch %s\n", gn->name); 953138232Sharti fflush(stdout); 9541590Srgrimes } 9551590Srgrimes 9561590Srgrimes if (noExecute) { 9571590Srgrimes return; 9581590Srgrimes } 9591590Srgrimes 9601590Srgrimes if (gn->type & OP_ARCHV) { 96118730Ssteve Arch_Touch(gn); 9621590Srgrimes } else if (gn->type & OP_LIB) { 96318730Ssteve Arch_TouchLib(gn); 9641590Srgrimes } else { 9651590Srgrimes char *file = gn->path ? gn->path : gn->name; 9661590Srgrimes 96718730Ssteve times.actime = times.modtime = now; 96818730Ssteve if (utime(file, ×) < 0){ 96918730Ssteve streamID = open(file, O_RDWR | O_CREAT, 0666); 9701590Srgrimes 9711590Srgrimes if (streamID >= 0) { 9721590Srgrimes char c; 9731590Srgrimes 9741590Srgrimes /* 9751590Srgrimes * Read and write a byte to the file to change the 9761590Srgrimes * modification time, then close the file. 9771590Srgrimes */ 9781590Srgrimes if (read(streamID, &c, 1) == 1) { 979138232Sharti lseek(streamID, (off_t)0, SEEK_SET); 980138232Sharti write(streamID, &c, 1); 9811590Srgrimes } 9828874Srgrimes 983138232Sharti close(streamID); 98418730Ssteve } else { 985138232Sharti fprintf(stdout, "*** couldn't touch %s: %s", 98618730Ssteve file, strerror(errno)); 987138232Sharti fflush(stdout); 98818730Ssteve } 9891590Srgrimes } 9901590Srgrimes } 9911590Srgrimes} 9921590Srgrimes 9931590Srgrimes/*- 9941590Srgrimes *----------------------------------------------------------------------- 9951590Srgrimes * Job_CheckCommands -- 9968874Srgrimes * Make sure the given node has all the commands it needs. 9971590Srgrimes * 9981590Srgrimes * Results: 9991590Srgrimes * TRUE if the commands list is/was ok. 10001590Srgrimes * 10011590Srgrimes * Side Effects: 10021590Srgrimes * The node will have commands from the .DEFAULT rule added to it 10031590Srgrimes * if it needs them. 10041590Srgrimes *----------------------------------------------------------------------- 10051590Srgrimes */ 10061590SrgrimesBoolean 1007104696SjmallettJob_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 10081590Srgrimes{ 1009138232Sharti 1010138916Sharti if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && 10111590Srgrimes (gn->type & OP_LIB) == 0) { 10121590Srgrimes /* 10131590Srgrimes * No commands. Look for .DEFAULT rule from which we might infer 10148874Srgrimes * commands 10151590Srgrimes */ 1016138916Sharti if ((DEFAULT != NULL) && !Lst_IsEmpty(&DEFAULT->commands)) { 10175814Sjkh char *p1; 10181590Srgrimes /* 10191590Srgrimes * Make only looks for a .DEFAULT if the node was never the 10201590Srgrimes * target of an operator, so that's what we do too. If 10211590Srgrimes * a .DEFAULT was given, we substitute its commands for gn's 10221590Srgrimes * commands and set the IMPSRC variable to be the target's name 10231590Srgrimes * The DEFAULT node acts like a transformation rule, in that 10241590Srgrimes * gn also inherits any attributes or sources attached to 10251590Srgrimes * .DEFAULT itself. 10261590Srgrimes */ 10271590Srgrimes Make_HandleUse(DEFAULT, gn); 102818730Ssteve Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn); 1029105826Sjmallett free(p1); 103018730Ssteve } else if (Dir_MTime(gn) == 0) { 10311590Srgrimes /* 10321590Srgrimes * The node wasn't the target of an operator we have no .DEFAULT 10331590Srgrimes * rule to go on and the target doesn't already exist. There's 10341590Srgrimes * nothing more we can do for this branch. If the -k flag wasn't 10351590Srgrimes * given, we stop in our tracks, otherwise we just don't update 10368874Srgrimes * this node's parents so they never get examined. 10371590Srgrimes */ 103818730Ssteve static const char msg[] = "make: don't know how to make"; 103918730Ssteve 10401590Srgrimes if (gn->type & OP_OPTIONAL) { 1041138232Sharti fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); 1042138232Sharti fflush(stdout); 10431590Srgrimes } else if (keepgoing) { 1044138232Sharti fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); 1045138232Sharti fflush(stdout); 1046138232Sharti return (FALSE); 10471590Srgrimes } else { 104835483Simp#if OLD_JOKE 104935483Simp if (strcmp(gn->name,"love") == 0) 105035483Simp (*abortProc)("Not war."); 105135483Simp else 105235483Simp#endif 105335483Simp (*abortProc)("%s %s. Stop", msg, gn->name); 1054138232Sharti return (FALSE); 10551590Srgrimes } 10561590Srgrimes } 10571590Srgrimes } 1058138232Sharti return (TRUE); 10591590Srgrimes} 10601590Srgrimes 10611590Srgrimes/*- 10621590Srgrimes *----------------------------------------------------------------------- 10631590Srgrimes * JobExec -- 10641590Srgrimes * Execute the shell for the given job. Called from JobStart and 10651590Srgrimes * JobRestart. 10661590Srgrimes * 10671590Srgrimes * Results: 10681590Srgrimes * None. 10691590Srgrimes * 10701590Srgrimes * Side Effects: 10711590Srgrimes * A shell is executed, outputs is altered and the Job structure added 10721590Srgrimes * to the job table. 10731590Srgrimes * 10741590Srgrimes *----------------------------------------------------------------------- 10751590Srgrimes */ 10761590Srgrimesstatic void 1077104696SjmallettJobExec(Job *job, char **argv) 10781590Srgrimes{ 10791590Srgrimes int cpid; /* ID of new child */ 10808874Srgrimes 10811590Srgrimes if (DEBUG(JOB)) { 10821590Srgrimes int i; 10838874Srgrimes 1084137252Sharti DEBUGF(JOB, ("Running %s\n", job->node->name)); 1085103545Sjmallett DEBUGF(JOB, ("\tCommand: ")); 108618730Ssteve for (i = 0; argv[i] != NULL; i++) { 1087103545Sjmallett DEBUGF(JOB, ("%s ", argv[i])); 10881590Srgrimes } 1089103545Sjmallett DEBUGF(JOB, ("\n")); 10901590Srgrimes } 10918874Srgrimes 10921590Srgrimes /* 10931590Srgrimes * Some jobs produce no output and it's disconcerting to have 10941590Srgrimes * no feedback of their running (since they produce no output, the 10951590Srgrimes * banner with their name in it never appears). This is an attempt to 10961590Srgrimes * provide that feedback, even if nothing follows it. 10971590Srgrimes */ 10981590Srgrimes if ((lastNode != job->node) && (job->flags & JOB_FIRST) && 109918730Ssteve !(job->flags & JOB_SILENT)) { 110018730Ssteve MESSAGE(stdout, job->node); 11011590Srgrimes lastNode = job->node; 11021590Srgrimes } 11038874Srgrimes 110418730Ssteve if ((cpid = vfork()) == -1) { 110518730Ssteve Punt("Cannot fork"); 11061590Srgrimes } else if (cpid == 0) { 11071590Srgrimes 1108137606Sphk if (fifoFd >= 0) 1109137606Sphk close(fifoFd); 11101590Srgrimes /* 11111590Srgrimes * Must duplicate the input stream down to the child's input and 11121590Srgrimes * reset it to the beginning (again). Since the stream was marked 11131590Srgrimes * close-on-exec, we must clear that bit in the new input. 11141590Srgrimes */ 111518730Ssteve if (dup2(FILENO(job->cmdFILE), 0) == -1) 111618730Ssteve Punt("Cannot dup2: %s", strerror(errno)); 1117138232Sharti fcntl(0, F_SETFD, 0); 1118138232Sharti lseek(0, (off_t)0, SEEK_SET); 11198874Srgrimes 11201590Srgrimes if (usePipes) { 11211590Srgrimes /* 11221590Srgrimes * Set up the child's output to be routed through the pipe 11231590Srgrimes * we've created for it. 11241590Srgrimes */ 112518730Ssteve if (dup2(job->outPipe, 1) == -1) 112618730Ssteve Punt("Cannot dup2: %s", strerror(errno)); 11271590Srgrimes } else { 11281590Srgrimes /* 11291590Srgrimes * We're capturing output in a file, so we duplicate the 11301590Srgrimes * descriptor to the temporary file into the standard 11311590Srgrimes * output. 11321590Srgrimes */ 113318730Ssteve if (dup2(job->outFd, 1) == -1) 113418730Ssteve Punt("Cannot dup2: %s", strerror(errno)); 11351590Srgrimes } 11361590Srgrimes /* 11371590Srgrimes * The output channels are marked close on exec. This bit was 11381590Srgrimes * duplicated by the dup2 (on some systems), so we have to clear 11391590Srgrimes * it before routing the shell's error output to the same place as 11401590Srgrimes * its standard output. 11411590Srgrimes */ 1142138232Sharti fcntl(1, F_SETFD, 0); 114318730Ssteve if (dup2(1, 2) == -1) 114418730Ssteve Punt("Cannot dup2: %s", strerror(errno)); 11451590Srgrimes 11461590Srgrimes#ifdef USE_PGRP 11471590Srgrimes /* 11481590Srgrimes * We want to switch the child into a different process family so 11491590Srgrimes * we can kill it and all its descendants in one fell swoop, 11501590Srgrimes * by killing its process family, but not commit suicide. 11511590Srgrimes */ 115218730Ssteve# if defined(SYSV) 1153138232Sharti setsid(); 115418730Ssteve# else 1155138232Sharti setpgid(0, getpid()); 115618730Ssteve# endif 115718730Ssteve#endif /* USE_PGRP */ 11588874Srgrimes 1159138232Sharti execv(shellPath, argv); 11601590Srgrimes 1161138232Sharti write(STDERR_FILENO, "Could not execute shell\n", 116218730Ssteve sizeof("Could not execute shell")); 116318730Ssteve _exit(1); 11641590Srgrimes } else { 11651590Srgrimes job->pid = cpid; 11661590Srgrimes 11671590Srgrimes if (usePipes && (job->flags & JOB_FIRST) ) { 11681590Srgrimes /* 11691590Srgrimes * The first time a job is run for a node, we set the current 11701590Srgrimes * position in the buffer to the beginning and mark another 11711590Srgrimes * stream to watch in the outputs mask 11721590Srgrimes */ 1173104475Sphk#ifdef USE_KQUEUE 1174104475Sphk struct kevent kev[2]; 1175104475Sphk#endif 11761590Srgrimes job->curPos = 0; 11778874Srgrimes 1178137202Sharti#if defined(USE_KQUEUE) 1179104475Sphk EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job); 1180104475Sphk EV_SET(&kev[1], job->pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, 1181104475Sphk NOTE_EXIT, 0, NULL); 1182104475Sphk if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) { 1183104475Sphk /* kevent() will fail if the job is already finished */ 1184128500Sgreen if (errno != EINTR && errno != EBADF && errno != ESRCH) 1185104475Sphk Punt("kevent: %s", strerror(errno)); 1186104475Sphk } 11871590Srgrimes#else 11881590Srgrimes FD_SET(job->inPipe, &outputs); 1189137202Sharti#endif /* USE_KQUEUE */ 11901590Srgrimes } 11911590Srgrimes 1192137252Sharti if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1193138232Sharti fclose(job->cmdFILE); 1194137252Sharti job->cmdFILE = NULL; 11951590Srgrimes } 11961590Srgrimes } 11971590Srgrimes 11981590Srgrimes /* 11991590Srgrimes * Now the job is actually running, add it to the table. 12001590Srgrimes */ 12011590Srgrimes nJobs += 1; 1202138916Sharti Lst_AtEnd(&jobs, job); 12031590Srgrimes if (nJobs == maxJobs) { 12041590Srgrimes jobFull = TRUE; 12051590Srgrimes } 12061590Srgrimes} 12071590Srgrimes 12081590Srgrimes/*- 12091590Srgrimes *----------------------------------------------------------------------- 12101590Srgrimes * JobMakeArgv -- 12111590Srgrimes * Create the argv needed to execute the shell for a given job. 12121590Srgrimes * 12138874Srgrimes * 12141590Srgrimes * Results: 12151590Srgrimes * 12161590Srgrimes * Side Effects: 12171590Srgrimes * 12181590Srgrimes *----------------------------------------------------------------------- 12191590Srgrimes */ 12201590Srgrimesstatic void 1221104696SjmallettJobMakeArgv(Job *job, char **argv) 12221590Srgrimes{ 12231590Srgrimes int argc; 12241590Srgrimes static char args[10]; /* For merged arguments */ 12258874Srgrimes 12261590Srgrimes argv[0] = shellName; 12271590Srgrimes argc = 1; 12281590Srgrimes 12291590Srgrimes if ((commandShell->exit && (*commandShell->exit != '-')) || 12301590Srgrimes (commandShell->echo && (*commandShell->echo != '-'))) 12311590Srgrimes { 12321590Srgrimes /* 12331590Srgrimes * At least one of the flags doesn't have a minus before it, so 12341590Srgrimes * merge them together. Have to do this because the *(&(@*#*&#$# 12351590Srgrimes * Bourne shell thinks its second argument is a file to source. 12361590Srgrimes * Grrrr. Note the ten-character limitation on the combined arguments. 12371590Srgrimes */ 1238138232Sharti sprintf(args, "-%s%s", 12391590Srgrimes ((job->flags & JOB_IGNERR) ? "" : 12401590Srgrimes (commandShell->exit ? commandShell->exit : "")), 12411590Srgrimes ((job->flags & JOB_SILENT) ? "" : 12421590Srgrimes (commandShell->echo ? commandShell->echo : ""))); 12431590Srgrimes 12441590Srgrimes if (args[1]) { 12451590Srgrimes argv[argc] = args; 12461590Srgrimes argc++; 12471590Srgrimes } 12481590Srgrimes } else { 12491590Srgrimes if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 12501590Srgrimes argv[argc] = commandShell->exit; 12511590Srgrimes argc++; 12521590Srgrimes } 12531590Srgrimes if (!(job->flags & JOB_SILENT) && commandShell->echo) { 12541590Srgrimes argv[argc] = commandShell->echo; 12551590Srgrimes argc++; 12561590Srgrimes } 12571590Srgrimes } 125818730Ssteve argv[argc] = NULL; 12591590Srgrimes} 12601590Srgrimes 12611590Srgrimes/*- 12621590Srgrimes *----------------------------------------------------------------------- 12631590Srgrimes * JobRestart -- 12648874Srgrimes * Restart a job that stopped for some reason. 12651590Srgrimes * 12661590Srgrimes * Results: 12671590Srgrimes * None. 12681590Srgrimes * 12691590Srgrimes * Side Effects: 12701590Srgrimes * jobFull will be set if the job couldn't be run. 12711590Srgrimes * 12721590Srgrimes *----------------------------------------------------------------------- 12731590Srgrimes */ 12741590Srgrimesstatic void 1275104696SjmallettJobRestart(Job *job) 12761590Srgrimes{ 127718730Ssteve 1278137252Sharti if (job->flags & JOB_RESTART) { 12791590Srgrimes /* 12801590Srgrimes * Set up the control arguments to the shell. This is based on the 12811590Srgrimes * flags set earlier for this job. If the JOB_IGNERR flag is clear, 12821590Srgrimes * the 'exit' flag of the commandShell is used to cause it to exit 12831590Srgrimes * upon receiving an error. If the JOB_SILENT flag is clear, the 12841590Srgrimes * 'echo' flag of the commandShell is used to get it to start echoing 12858874Srgrimes * as soon as it starts processing commands. 12861590Srgrimes */ 12871590Srgrimes char *argv[4]; 12888874Srgrimes 12891590Srgrimes JobMakeArgv(job, argv); 12908874Srgrimes 1291103545Sjmallett DEBUGF(JOB, ("Restarting %s...", job->node->name)); 1292137572Sphk if (((nJobs >= maxJobs) && !(job->flags & JOB_SPECIAL))) { 129318730Ssteve /* 1294137202Sharti * Can't be exported and not allowed to run locally -- put it 1295137202Sharti * back on the hold queue and mark the table full 129618730Ssteve */ 1297137202Sharti DEBUGF(JOB, ("holding\n")); 1298138916Sharti Lst_AtFront(&stoppedJobs, (void *)job); 1299137202Sharti jobFull = TRUE; 1300137202Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1301137202Sharti return; 1302137202Sharti } else { 1303137202Sharti /* 1304137202Sharti * Job may be run locally. 1305137202Sharti */ 1306137202Sharti DEBUGF(JOB, ("running locally\n")); 130718730Ssteve } 13081590Srgrimes JobExec(job, argv); 13091590Srgrimes } else { 13101590Srgrimes /* 13111590Srgrimes * The job has stopped and needs to be restarted. Why it stopped, 13121590Srgrimes * we don't know... 13131590Srgrimes */ 1314103545Sjmallett DEBUGF(JOB, ("Resuming %s...", job->node->name)); 1315137572Sphk if (((nJobs < maxJobs) || 131618730Ssteve ((job->flags & JOB_SPECIAL) && 1317137572Sphk (maxJobs == 0))) && 131818730Ssteve (nJobs != maxJobs)) 13191590Srgrimes { 13201590Srgrimes /* 1321137252Sharti * If we haven't reached the concurrency limit already (or the 1322137572Sphk * job must be run and maxJobs is 0), it's ok to resume it. 13231590Srgrimes */ 13241590Srgrimes Boolean error; 132518730Ssteve int status; 13268874Srgrimes 1327137202Sharti error = (KILL(job->pid, SIGCONT) != 0); 13281590Srgrimes 13291590Srgrimes if (!error) { 13301590Srgrimes /* 13311590Srgrimes * Make sure the user knows we've continued the beast and 13321590Srgrimes * actually put the thing in the job table. 13331590Srgrimes */ 13341590Srgrimes job->flags |= JOB_CONTINUING; 133518730Ssteve W_SETTERMSIG(&status, SIGCONT); 133618730Ssteve JobFinish(job, &status); 13378874Srgrimes 13381590Srgrimes job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 1339103545Sjmallett DEBUGF(JOB, ("done\n")); 13401590Srgrimes } else { 13411590Srgrimes Error("couldn't resume %s: %s", 13421590Srgrimes job->node->name, strerror(errno)); 134318730Ssteve status = 0; 134418730Ssteve W_SETEXITSTATUS(&status, 1); 134518730Ssteve JobFinish(job, &status); 13461590Srgrimes } 13471590Srgrimes } else { 13481590Srgrimes /* 13491590Srgrimes * Job cannot be restarted. Mark the table as full and 13501590Srgrimes * place the job back on the list of stopped jobs. 13511590Srgrimes */ 1352103545Sjmallett DEBUGF(JOB, ("table full\n")); 1353138916Sharti Lst_AtFront(&stoppedJobs, (void *)job); 13541590Srgrimes jobFull = TRUE; 1355103545Sjmallett DEBUGF(JOB, ("Job queue is full.\n")); 13561590Srgrimes } 13571590Srgrimes } 13581590Srgrimes} 13591590Srgrimes 13601590Srgrimes/*- 13611590Srgrimes *----------------------------------------------------------------------- 13621590Srgrimes * JobStart -- 13631590Srgrimes * Start a target-creation process going for the target described 13648874Srgrimes * by the graph node gn. 13651590Srgrimes * 13661590Srgrimes * Results: 13671590Srgrimes * JOB_ERROR if there was an error in the commands, JOB_FINISHED 13681590Srgrimes * if there isn't actually anything left to do for the job and 13691590Srgrimes * JOB_RUNNING if the job has been started. 13701590Srgrimes * 13711590Srgrimes * Side Effects: 13721590Srgrimes * A new Job node is created and added to the list of running 13731590Srgrimes * jobs. PMake is forked and a child shell created. 13741590Srgrimes *----------------------------------------------------------------------- 13751590Srgrimes */ 13761590Srgrimesstatic int 1377104696SjmallettJobStart(GNode *gn, int flags, Job *previous) 13781590Srgrimes{ 137994584Sobrien Job *job; /* new job descriptor */ 13801590Srgrimes char *argv[4]; /* Argument vector to shell */ 13811590Srgrimes Boolean cmdsOK; /* true if the nodes commands were all right */ 13821590Srgrimes Boolean noExec; /* Set true if we decide not to run the job */ 138356151Skris int tfd; /* File descriptor for temp file */ 13841590Srgrimes 1385137605Sharti if (interrupted) { 1386137605Sharti JobPassSig(interrupted); 1387137605Sharti return (JOB_ERROR); 1388137605Sharti } 138918730Ssteve if (previous != NULL) { 1390137252Sharti previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT); 13911590Srgrimes job = previous; 13921590Srgrimes } else { 1393138264Sharti job = emalloc(sizeof(Job)); 13941590Srgrimes flags |= JOB_FIRST; 13951590Srgrimes } 13961590Srgrimes 13971590Srgrimes job->node = gn; 139869527Swill job->tailCmds = NULL; 13991590Srgrimes 14001590Srgrimes /* 14011590Srgrimes * Set the initial value of the flags for this job based on the global 14021590Srgrimes * ones and the node's attributes... Any flags supplied by the caller 14031590Srgrimes * are also added to the field. 14041590Srgrimes */ 14051590Srgrimes job->flags = 0; 140618730Ssteve if (Targ_Ignore(gn)) { 14071590Srgrimes job->flags |= JOB_IGNERR; 14081590Srgrimes } 140918730Ssteve if (Targ_Silent(gn)) { 14101590Srgrimes job->flags |= JOB_SILENT; 14111590Srgrimes } 14121590Srgrimes job->flags |= flags; 14131590Srgrimes 14141590Srgrimes /* 14151590Srgrimes * Check the commands now so any attributes from .DEFAULT have a chance 14161590Srgrimes * to migrate to the node 14171590Srgrimes */ 141818730Ssteve if (!compatMake && job->flags & JOB_FIRST) { 14191590Srgrimes cmdsOK = Job_CheckCommands(gn, Error); 14201590Srgrimes } else { 14211590Srgrimes cmdsOK = TRUE; 14221590Srgrimes } 14238874Srgrimes 14241590Srgrimes /* 14251590Srgrimes * If the -n flag wasn't given, we open up OUR (not the child's) 14261590Srgrimes * temporary file to stuff commands in it. The thing is rd/wr so we don't 14271590Srgrimes * need to reopen it to feed it to the shell. If the -n flag *was* given, 14281590Srgrimes * we just set the file to be stdout. Cute, huh? 14291590Srgrimes */ 14301590Srgrimes if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 14311590Srgrimes /* 14321590Srgrimes * We're serious here, but if the commands were bogus, we're 14331590Srgrimes * also dead... 14341590Srgrimes */ 14351590Srgrimes if (!cmdsOK) { 14361590Srgrimes DieHorribly(); 14371590Srgrimes } 14388874Srgrimes 1439138232Sharti strcpy(tfile, TMPPAT); 144068898Skris if ((tfd = mkstemp(tfile)) == -1) 144168898Skris Punt("Cannot create temp file: %s", strerror(errno)); 144268898Skris job->cmdFILE = fdopen(tfd, "w+"); 144368898Skris eunlink(tfile); 144418730Ssteve if (job->cmdFILE == NULL) { 144568898Skris close(tfd); 144668898Skris Punt("Could not open %s", tfile); 14471590Srgrimes } 1448138232Sharti fcntl(FILENO(job->cmdFILE), F_SETFD, 1); 14491590Srgrimes /* 14501590Srgrimes * Send the commands to the command file, flush all its buffers then 14511590Srgrimes * rewind and remove the thing. 14521590Srgrimes */ 14531590Srgrimes noExec = FALSE; 14541590Srgrimes 14551590Srgrimes /* 14561590Srgrimes * used to be backwards; replace when start doing multiple commands 14571590Srgrimes * per shell. 14581590Srgrimes */ 14591590Srgrimes if (compatMake) { 14601590Srgrimes /* 14611590Srgrimes * Be compatible: If this is the first time for this node, 14621590Srgrimes * verify its commands are ok and open the commands list for 14631590Srgrimes * sequential access by later invocations of JobStart. 14641590Srgrimes * Once that is done, we take the next command off the list 14651590Srgrimes * and print it to the command file. If the command was an 14661590Srgrimes * ellipsis, note that there's nothing more to execute. 14671590Srgrimes */ 1468138564Sharti if (job->flags & JOB_FIRST) 1469138916Sharti gn->compat_command = Lst_First(&gn->commands); 1470138564Sharti else 1471138564Sharti gn->compat_command = Lst_Succ(gn->compat_command); 14728874Srgrimes 1473138564Sharti if (gn->compat_command == NULL || 1474138564Sharti JobPrintCommand(Lst_Datum(gn->compat_command), job)) 1475138564Sharti noExec = TRUE; 1476138564Sharti 1477138564Sharti if (noExec && !(job->flags & JOB_FIRST)) { 1478138564Sharti /* 1479138564Sharti * If we're not going to execute anything, the job 1480138564Sharti * is done and we need to close down the various 1481138564Sharti * file descriptors we've opened for output, then 1482138564Sharti * call JobDoOutput to catch the final characters or 1483138564Sharti * send the file to the screen... Note that the i/o streams 1484138564Sharti * are only open if this isn't the first job. 1485138564Sharti * Note also that this could not be done in 1486138564Sharti * Job_CatchChildren b/c it wasn't clear if there were 1487138564Sharti * more commands to execute or not... 1488138564Sharti */ 1489138564Sharti JobClose(job); 14901590Srgrimes } 14911590Srgrimes } else { 14921590Srgrimes /* 14931590Srgrimes * We can do all the commands at once. hooray for sanity 14941590Srgrimes */ 14951590Srgrimes numCommands = 0; 1496138916Sharti Lst_ForEach(&gn->commands, JobPrintCommand, job); 14978874Srgrimes 14981590Srgrimes /* 14991590Srgrimes * If we didn't print out any commands to the shell script, 15001590Srgrimes * there's not much point in executing the shell, is there? 15011590Srgrimes */ 15021590Srgrimes if (numCommands == 0) { 15031590Srgrimes noExec = TRUE; 15041590Srgrimes } 15051590Srgrimes } 15061590Srgrimes } else if (noExecute) { 15071590Srgrimes /* 15081590Srgrimes * Not executing anything -- just print all the commands to stdout 15091590Srgrimes * in one fell swoop. This will still set up job->tailCmds correctly. 15101590Srgrimes */ 15111590Srgrimes if (lastNode != gn) { 151218730Ssteve MESSAGE(stdout, gn); 15131590Srgrimes lastNode = gn; 15141590Srgrimes } 15151590Srgrimes job->cmdFILE = stdout; 15161590Srgrimes /* 15171590Srgrimes * Only print the commands if they're ok, but don't die if they're 15181590Srgrimes * not -- just let the user know they're bad and keep going. It 15191590Srgrimes * doesn't do any harm in this case and may do some good. 15201590Srgrimes */ 15211590Srgrimes if (cmdsOK) { 1522138916Sharti Lst_ForEach(&gn->commands, JobPrintCommand, job); 15231590Srgrimes } 15241590Srgrimes /* 15251590Srgrimes * Don't execute the shell, thank you. 15261590Srgrimes */ 15271590Srgrimes noExec = TRUE; 15281590Srgrimes } else { 15291590Srgrimes /* 15301590Srgrimes * Just touch the target and note that no shell should be executed. 15311590Srgrimes * Set cmdFILE to stdout to make life easier. Check the commands, too, 15321590Srgrimes * but don't die if they're no good -- it does no harm to keep working 15331590Srgrimes * up the graph. 15341590Srgrimes */ 15351590Srgrimes job->cmdFILE = stdout; 1536138264Sharti Job_Touch(gn, job->flags & JOB_SILENT); 15371590Srgrimes noExec = TRUE; 15381590Srgrimes } 15391590Srgrimes 15401590Srgrimes /* 15418874Srgrimes * If we're not supposed to execute a shell, don't. 15421590Srgrimes */ 15431590Srgrimes if (noExec) { 15441590Srgrimes /* 15451590Srgrimes * Unlink and close the command file if we opened one 15461590Srgrimes */ 15471590Srgrimes if (job->cmdFILE != stdout) { 154818730Ssteve if (job->cmdFILE != NULL) 1549138232Sharti fclose(job->cmdFILE); 15501590Srgrimes } else { 1551138232Sharti fflush(stdout); 15521590Srgrimes } 15531590Srgrimes 15541590Srgrimes /* 15551590Srgrimes * We only want to work our way up the graph if we aren't here because 15561590Srgrimes * the commands for the job were no good. 15571590Srgrimes */ 15581590Srgrimes if (cmdsOK) { 15591590Srgrimes if (aborting == 0) { 156069527Swill if (job->tailCmds != NULL) { 1561138916Sharti Lst_ForEachFrom(&job->node->commands, job->tailCmds, 1562138264Sharti JobSaveCommand, job->node); 15631590Srgrimes } 156436621Sbde job->node->made = MADE; 15651590Srgrimes Make_Update(job->node); 15661590Srgrimes } 156769531Swill free(job); 15681590Srgrimes return(JOB_FINISHED); 15691590Srgrimes } else { 157069531Swill free(job); 15711590Srgrimes return(JOB_ERROR); 15721590Srgrimes } 15731590Srgrimes } else { 1574138232Sharti fflush(job->cmdFILE); 15751590Srgrimes } 15761590Srgrimes 15771590Srgrimes /* 15781590Srgrimes * Set up the control arguments to the shell. This is based on the flags 15791590Srgrimes * set earlier for this job. 15801590Srgrimes */ 15811590Srgrimes JobMakeArgv(job, argv); 15821590Srgrimes 15831590Srgrimes /* 15841590Srgrimes * If we're using pipes to catch output, create the pipe by which we'll 15851590Srgrimes * get the shell's output. If we're using files, print out that we're 158650145Shoek * starting a job and then set up its temporary-file name. 15871590Srgrimes */ 158818730Ssteve if (!compatMake || (job->flags & JOB_FIRST)) { 15891590Srgrimes if (usePipes) { 15901590Srgrimes int fd[2]; 1591138232Sharti 159218730Ssteve if (pipe(fd) == -1) 159318730Ssteve Punt("Cannot create pipe: %s", strerror(errno)); 15941590Srgrimes job->inPipe = fd[0]; 15951590Srgrimes job->outPipe = fd[1]; 1596138232Sharti fcntl(job->inPipe, F_SETFD, 1); 1597138232Sharti fcntl(job->outPipe, F_SETFD, 1); 15981590Srgrimes } else { 1599138232Sharti fprintf(stdout, "Remaking `%s'\n", gn->name); 1600138232Sharti fflush(stdout); 1601138232Sharti strcpy(job->outFile, TMPPAT); 160250145Shoek if ((job->outFd = mkstemp(job->outFile)) == -1) 160350145Shoek Punt("cannot create temp file: %s", strerror(errno)); 1604138232Sharti fcntl(job->outFd, F_SETFD, 1); 16051590Srgrimes } 16061590Srgrimes } 16071590Srgrimes 1608137572Sphk if ((nJobs >= maxJobs) && !(job->flags & JOB_SPECIAL) && (maxJobs != 0)) { 16091590Srgrimes /* 1610137252Sharti * We've hit the limit of concurrency, so put the job on hold until 1611137252Sharti * some other job finishes. Note that the special jobs (.BEGIN, 1612137252Sharti * .INTERRUPT and .END) may be run even when the limit has been reached 1613137572Sphk * (e.g. when maxJobs == 0). 16141590Srgrimes */ 16151590Srgrimes jobFull = TRUE; 16168874Srgrimes 1617103545Sjmallett DEBUGF(JOB, ("Can only run job locally.\n")); 16181590Srgrimes job->flags |= JOB_RESTART; 1619138916Sharti Lst_AtEnd(&stoppedJobs, job); 16201590Srgrimes } else { 1621137572Sphk if (nJobs >= maxJobs) { 16221590Srgrimes /* 16231590Srgrimes * If we're running this job locally as a special case (see above), 16241590Srgrimes * at least say the table is full. 16251590Srgrimes */ 16261590Srgrimes jobFull = TRUE; 1627103545Sjmallett DEBUGF(JOB, ("Local job queue is full.\n")); 16281590Srgrimes } 16291590Srgrimes JobExec(job, argv); 16301590Srgrimes } 1631138232Sharti return (JOB_RUNNING); 16321590Srgrimes} 16331590Srgrimes 163418730Sstevestatic char * 1635104696SjmallettJobOutput(Job *job, char *cp, char *endp, int msg) 163618730Ssteve{ 163794584Sobrien char *ecp; 163818730Ssteve 163918730Ssteve if (commandShell->noPrint) { 1640106106Sjmallett ecp = strstr(cp, commandShell->noPrint); 164118730Ssteve while (ecp != NULL) { 164218730Ssteve if (cp != ecp) { 164318730Ssteve *ecp = '\0'; 164418730Ssteve if (msg && job->node != lastNode) { 164518730Ssteve MESSAGE(stdout, job->node); 164618730Ssteve lastNode = job->node; 164718730Ssteve } 164818730Ssteve /* 164918730Ssteve * The only way there wouldn't be a newline after 165018730Ssteve * this line is if it were the last in the buffer. 165118730Ssteve * however, since the non-printable comes after it, 165218730Ssteve * there must be a newline, so we don't print one. 165318730Ssteve */ 1654138232Sharti fprintf(stdout, "%s", cp); 1655138232Sharti fflush(stdout); 165618730Ssteve } 165718730Ssteve cp = ecp + commandShell->noPLen; 165818730Ssteve if (cp != endp) { 165918730Ssteve /* 166018730Ssteve * Still more to print, look again after skipping 166118730Ssteve * the whitespace following the non-printable 166218730Ssteve * command.... 166318730Ssteve */ 166418730Ssteve cp++; 166518730Ssteve while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 166618730Ssteve cp++; 166718730Ssteve } 1668106106Sjmallett ecp = strstr(cp, commandShell->noPrint); 166918730Ssteve } else { 1670138232Sharti return (cp); 167118730Ssteve } 167218730Ssteve } 167318730Ssteve } 1674138232Sharti return (cp); 167518730Ssteve} 167618730Ssteve 16771590Srgrimes/*- 16781590Srgrimes *----------------------------------------------------------------------- 16791590Srgrimes * JobDoOutput -- 16801590Srgrimes * This function is called at different times depending on 16811590Srgrimes * whether the user has specified that output is to be collected 16821590Srgrimes * via pipes or temporary files. In the former case, we are called 16831590Srgrimes * whenever there is something to read on the pipe. We collect more 16841590Srgrimes * output from the given job and store it in the job's outBuf. If 16851590Srgrimes * this makes up a line, we print it tagged by the job's identifier, 16861590Srgrimes * as necessary. 16871590Srgrimes * If output has been collected in a temporary file, we open the 16881590Srgrimes * file and read it line by line, transfering it to our own 16891590Srgrimes * output channel until the file is empty. At which point we 16901590Srgrimes * remove the temporary file. 16911590Srgrimes * In both cases, however, we keep our figurative eye out for the 16921590Srgrimes * 'noPrint' line for the shell from which the output came. If 16931590Srgrimes * we recognize a line, we don't print it. If the command is not 16941590Srgrimes * alone on the line (the character after it is not \0 or \n), we 16951590Srgrimes * do print whatever follows it. 16961590Srgrimes * 16971590Srgrimes * Results: 16981590Srgrimes * None 16991590Srgrimes * 17001590Srgrimes * Side Effects: 17011590Srgrimes * curPos may be shifted as may the contents of outBuf. 17021590Srgrimes *----------------------------------------------------------------------- 17031590Srgrimes */ 170418730SsteveSTATIC void 1705104696SjmallettJobDoOutput(Job *job, Boolean finish) 17061590Srgrimes{ 17071590Srgrimes Boolean gotNL = FALSE; /* true if got a newline */ 170818730Ssteve Boolean fbuf; /* true if our buffer filled up */ 170994584Sobrien int nr; /* number of bytes read */ 171094584Sobrien int i; /* auxiliary index into outBuf */ 171194584Sobrien int max; /* limit for i (end of current data) */ 17121590Srgrimes int nRead; /* (Temporary) number of bytes read */ 17131590Srgrimes 17141590Srgrimes FILE *oFILE; /* Stream pointer to shell's output file */ 17151590Srgrimes char inLine[132]; 17161590Srgrimes 17171590Srgrimes if (usePipes) { 17181590Srgrimes /* 17191590Srgrimes * Read as many bytes as will fit in the buffer. 17201590Srgrimes */ 17211590Srgrimesend_loop: 172218730Ssteve gotNL = FALSE; 172318730Ssteve fbuf = FALSE; 17248874Srgrimes 172518730Ssteve nRead = read(job->inPipe, &job->outBuf[job->curPos], 17261590Srgrimes JOB_BUFSIZE - job->curPos); 1727137605Sharti /* 1728137605Sharti * Check for interrupt here too, because the above read may block 1729137605Sharti * when the child process is stopped. In this case the interrupt 1730137605Sharti * will unblock it (we don't use SA_RESTART). 1731137605Sharti */ 1732137605Sharti if (interrupted) 1733137605Sharti JobPassSig(interrupted); 1734137605Sharti 17351590Srgrimes if (nRead < 0) { 1736103545Sjmallett DEBUGF(JOB, ("JobDoOutput(piperead)")); 17371590Srgrimes nr = 0; 17381590Srgrimes } else { 17391590Srgrimes nr = nRead; 17401590Srgrimes } 17411590Srgrimes 17421590Srgrimes /* 17431590Srgrimes * If we hit the end-of-file (the job is dead), we must flush its 17441590Srgrimes * remaining output, so pretend we read a newline if there's any 17451590Srgrimes * output remaining in the buffer. 17461590Srgrimes * Also clear the 'finish' flag so we stop looping. 17471590Srgrimes */ 17481590Srgrimes if ((nr == 0) && (job->curPos != 0)) { 17491590Srgrimes job->outBuf[job->curPos] = '\n'; 17501590Srgrimes nr = 1; 17511590Srgrimes finish = FALSE; 17521590Srgrimes } else if (nr == 0) { 17531590Srgrimes finish = FALSE; 17541590Srgrimes } 17558874Srgrimes 17561590Srgrimes /* 17571590Srgrimes * Look for the last newline in the bytes we just got. If there is 17581590Srgrimes * one, break out of the loop with 'i' as its index and gotNL set 17598874Srgrimes * TRUE. 17601590Srgrimes */ 17611590Srgrimes max = job->curPos + nr; 17621590Srgrimes for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 17631590Srgrimes if (job->outBuf[i] == '\n') { 17641590Srgrimes gotNL = TRUE; 17651590Srgrimes break; 17661590Srgrimes } else if (job->outBuf[i] == '\0') { 17671590Srgrimes /* 17681590Srgrimes * Why? 17691590Srgrimes */ 17701590Srgrimes job->outBuf[i] = ' '; 17711590Srgrimes } 17721590Srgrimes } 17738874Srgrimes 17741590Srgrimes if (!gotNL) { 17751590Srgrimes job->curPos += nr; 17761590Srgrimes if (job->curPos == JOB_BUFSIZE) { 17771590Srgrimes /* 17781590Srgrimes * If we've run out of buffer space, we have no choice 17798874Srgrimes * but to print the stuff. sigh. 17801590Srgrimes */ 178118730Ssteve fbuf = TRUE; 17821590Srgrimes i = job->curPos; 17831590Srgrimes } 17841590Srgrimes } 178518730Ssteve if (gotNL || fbuf) { 17861590Srgrimes /* 17871590Srgrimes * Need to send the output to the screen. Null terminate it 17881590Srgrimes * first, overwriting the newline character if there was one. 17891590Srgrimes * So long as the line isn't one we should filter (according 179072645Sasmodai * to the shell description), we print the line, preceded 17911590Srgrimes * by a target banner if this target isn't the same as the 17921590Srgrimes * one for which we last printed something. 17931590Srgrimes * The rest of the data in the buffer are then shifted down 17948874Srgrimes * to the start of the buffer and curPos is set accordingly. 17951590Srgrimes */ 17961590Srgrimes job->outBuf[i] = '\0'; 17971590Srgrimes if (i >= job->curPos) { 179818730Ssteve char *cp; 17991590Srgrimes 180018730Ssteve cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE); 18011590Srgrimes 18021590Srgrimes /* 18031590Srgrimes * There's still more in that thar buffer. This time, though, 18041590Srgrimes * we know there's no newline at the end, so we add one of 18051590Srgrimes * our own free will. 18061590Srgrimes */ 18071590Srgrimes if (*cp != '\0') { 18081590Srgrimes if (job->node != lastNode) { 180918730Ssteve MESSAGE(stdout, job->node); 18101590Srgrimes lastNode = job->node; 18111590Srgrimes } 1812138232Sharti fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); 1813138232Sharti fflush(stdout); 18141590Srgrimes } 18151590Srgrimes } 18161590Srgrimes if (i < max - 1) { 18171590Srgrimes /* shift the remaining characters down */ 1818138232Sharti memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); 18191590Srgrimes job->curPos = max - (i + 1); 18208874Srgrimes 18211590Srgrimes } else { 18221590Srgrimes /* 18231590Srgrimes * We have written everything out, so we just start over 18241590Srgrimes * from the start of the buffer. No copying. No nothing. 18251590Srgrimes */ 18261590Srgrimes job->curPos = 0; 18271590Srgrimes } 18281590Srgrimes } 18291590Srgrimes if (finish) { 18301590Srgrimes /* 18311590Srgrimes * If the finish flag is true, we must loop until we hit 183218730Ssteve * end-of-file on the pipe. This is guaranteed to happen 183318730Ssteve * eventually since the other end of the pipe is now closed 183418730Ssteve * (we closed it explicitly and the child has exited). When 183518730Ssteve * we do get an EOF, finish will be set FALSE and we'll fall 183618730Ssteve * through and out. 18371590Srgrimes */ 18381590Srgrimes goto end_loop; 18391590Srgrimes } 18401590Srgrimes } else { 18411590Srgrimes /* 18421590Srgrimes * We've been called to retrieve the output of the job from the 18431590Srgrimes * temporary file where it's been squirreled away. This consists of 18441590Srgrimes * opening the file, reading the output line by line, being sure not 18451590Srgrimes * to print the noPrint line for the shell we used, then close and 18461590Srgrimes * remove the temporary file. Very simple. 18471590Srgrimes * 18481590Srgrimes * Change to read in blocks and do FindSubString type things as for 18491590Srgrimes * pipes? That would allow for "@echo -n..." 18501590Srgrimes */ 185118730Ssteve oFILE = fopen(job->outFile, "r"); 185218730Ssteve if (oFILE != NULL) { 1853138264Sharti fprintf(stdout, "Results of making %s:\n", job->node->name); 1854138264Sharti fflush(stdout); 185518730Ssteve while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 185694584Sobrien char *cp, *endp, *oendp; 18571590Srgrimes 18581590Srgrimes cp = inLine; 185918730Ssteve oendp = endp = inLine + strlen(inLine); 18601590Srgrimes if (endp[-1] == '\n') { 18611590Srgrimes *--endp = '\0'; 18621590Srgrimes } 186318730Ssteve cp = JobOutput(job, inLine, endp, FALSE); 18641590Srgrimes 18651590Srgrimes /* 18661590Srgrimes * There's still more in that thar buffer. This time, though, 18671590Srgrimes * we know there's no newline at the end, so we add one of 18681590Srgrimes * our own free will. 18691590Srgrimes */ 1870138232Sharti fprintf(stdout, "%s", cp); 1871138232Sharti fflush(stdout); 187218730Ssteve if (endp != oendp) { 1873138232Sharti fprintf(stdout, "\n"); 1874138232Sharti fflush(stdout); 18751590Srgrimes } 18761590Srgrimes } 1877138264Sharti fclose(oFILE); 1878138264Sharti eunlink(job->outFile); 18791590Srgrimes } 18801590Srgrimes } 18811590Srgrimes} 18821590Srgrimes 18831590Srgrimes/*- 18841590Srgrimes *----------------------------------------------------------------------- 18851590Srgrimes * Job_CatchChildren -- 18861590Srgrimes * Handle the exit of a child. Called from Make_Make. 18871590Srgrimes * 18881590Srgrimes * Results: 18891590Srgrimes * none. 18901590Srgrimes * 18911590Srgrimes * Side Effects: 18921590Srgrimes * The job descriptor is removed from the list of children. 18931590Srgrimes * 18941590Srgrimes * Notes: 18951590Srgrimes * We do waits, blocking or not, according to the wisdom of our 18961590Srgrimes * caller, until there are no more children to report. For each 18971590Srgrimes * job, call JobFinish to finish things off. This will take care of 18981590Srgrimes * putting jobs on the stoppedJobs queue. 18991590Srgrimes * 19001590Srgrimes *----------------------------------------------------------------------- 19011590Srgrimes */ 19021590Srgrimesvoid 1903104696SjmallettJob_CatchChildren(Boolean block) 19041590Srgrimes{ 19051590Srgrimes int pid; /* pid of dead child */ 190694584Sobrien Job *job; /* job descriptor for dead child */ 1907138512Sharti LstNode *jnode; /* list element for finding job */ 190818730Ssteve int status; /* Exit/termination status */ 19091590Srgrimes 19101590Srgrimes /* 19111590Srgrimes * Don't even bother if we know there's no one around. 19121590Srgrimes */ 1913137572Sphk if (nJobs == 0) { 19141590Srgrimes return; 19151590Srgrimes } 19168874Srgrimes 1917137606Sphk for (;;) { 1918138232Sharti pid = waitpid((pid_t)-1, &status, (block ? 0 : WNOHANG) | WUNTRACED); 1919137606Sphk if (pid <= 0) 1920137606Sphk break; 1921103545Sjmallett DEBUGF(JOB, ("Process %d exited or stopped.\n", pid)); 19221590Srgrimes 1923138916Sharti jnode = Lst_Find(&jobs, &pid, JobCmpPid); 19241590Srgrimes 192569527Swill if (jnode == NULL) { 192618730Ssteve if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { 1927138916Sharti jnode = Lst_Find(&stoppedJobs, &pid, JobCmpPid); 192869527Swill if (jnode == NULL) { 19291590Srgrimes Error("Resumed child (%d) not in table", pid); 19301590Srgrimes continue; 19311590Srgrimes } 1932138264Sharti job = Lst_Datum(jnode); 1933138916Sharti Lst_Remove(&stoppedJobs, jnode); 19341590Srgrimes } else { 193518730Ssteve Error("Child (%d) not in table?", pid); 19361590Srgrimes continue; 19371590Srgrimes } 19381590Srgrimes } else { 1939138264Sharti job = Lst_Datum(jnode); 1940138916Sharti Lst_Remove(&jobs, jnode); 19411590Srgrimes nJobs -= 1; 1942137606Sphk if (fifoFd >= 0 && maxJobs > 1) { 1943137606Sphk write(fifoFd, "+", 1); 1944137606Sphk maxJobs--; 1945137606Sphk if (nJobs >= maxJobs) 1946137606Sphk jobFull = TRUE; 1947137606Sphk else 1948137606Sphk jobFull = FALSE; 1949137606Sphk } else { 1950137606Sphk DEBUGF(JOB, ("Job queue is no longer full.\n")); 1951137606Sphk jobFull = FALSE; 1952137606Sphk } 19531590Srgrimes } 19541590Srgrimes 195518730Ssteve JobFinish(job, &status); 19561590Srgrimes } 1957137605Sharti if (interrupted) 1958137605Sharti JobPassSig(interrupted); 19591590Srgrimes} 19601590Srgrimes 19611590Srgrimes/*- 19621590Srgrimes *----------------------------------------------------------------------- 19631590Srgrimes * Job_CatchOutput -- 19641590Srgrimes * Catch the output from our children, if we're using 19651590Srgrimes * pipes do so. Otherwise just block time until we get a 1966138232Sharti * signal(most likely a SIGCHLD) since there's no point in 19671590Srgrimes * just spinning when there's nothing to do and the reaping 19688874Srgrimes * of a child can wait for a while. 19691590Srgrimes * 19701590Srgrimes * Results: 19718874Srgrimes * None 19721590Srgrimes * 19731590Srgrimes * Side Effects: 19741590Srgrimes * Output is read from pipes if we're piping. 19751590Srgrimes * ----------------------------------------------------------------------- 19761590Srgrimes */ 19771590Srgrimesvoid 1978137606SphkJob_CatchOutput(int flag) 19791590Srgrimes{ 19801590Srgrimes int nfds; 1981104475Sphk#ifdef USE_KQUEUE 1982104475Sphk#define KEV_SIZE 4 1983104475Sphk struct kevent kev[KEV_SIZE]; 1984104475Sphk int i; 1985104475Sphk#else 19861590Srgrimes struct timeval timeout; 19871590Srgrimes fd_set readfds; 1988138512Sharti LstNode *ln; 198994584Sobrien Job *job; 1990104475Sphk#endif 19911590Srgrimes 1992138232Sharti fflush(stdout); 19931590Srgrimes 19941590Srgrimes if (usePipes) { 1995104475Sphk#ifdef USE_KQUEUE 1996104475Sphk if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) { 1997128500Sgreen if (errno != EINTR) 1998128500Sgreen Punt("kevent: %s", strerror(errno)); 1999137605Sharti if (interrupted) 2000137605Sharti JobPassSig(interrupted); 2001104475Sphk } else { 2002104475Sphk for (i = 0; i < nfds; i++) { 2003104475Sphk if (kev[i].flags & EV_ERROR) { 2004104475Sphk warnc(kev[i].data, "kevent"); 2005104475Sphk continue; 2006104475Sphk } 2007104475Sphk switch (kev[i].filter) { 2008104475Sphk case EVFILT_READ: 2009104475Sphk JobDoOutput(kev[i].udata, FALSE); 2010104475Sphk break; 2011104475Sphk case EVFILT_PROC: 2012104475Sphk /* Just wake up and let Job_CatchChildren() collect the 2013104475Sphk * terminated job. */ 2014104475Sphk break; 2015104475Sphk } 2016104475Sphk } 2017104475Sphk } 2018104475Sphk#else 20191590Srgrimes readfds = outputs; 20201590Srgrimes timeout.tv_sec = SEL_SEC; 20211590Srgrimes timeout.tv_usec = SEL_USEC; 2022137606Sphk if (flag && jobFull && fifoFd >= 0) 2023137606Sphk FD_SET(fifoFd, &readfds); 20241590Srgrimes 2025138264Sharti nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL, 2026138264Sharti (fd_set *)NULL, &timeout); 2027137606Sphk if (nfds <= 0) { 2028138232Sharti if (interrupted) 2029137605Sharti JobPassSig(interrupted); 20301590Srgrimes return; 2031137606Sphk } 2032137606Sphk if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) { 2033137606Sphk if (--nfds <= 0) 2034137606Sphk return; 2035137606Sphk } 2036138916Sharti for (ln = Lst_First(&jobs); nfds != 0 && ln != NULL; ln = Lst_Succ(ln)){ 2037138264Sharti job = Lst_Datum(ln); 2038137606Sphk if (FD_ISSET(job->inPipe, &readfds)) { 2039137606Sphk JobDoOutput(job, FALSE); 2040137606Sphk nfds -= 1; 20411590Srgrimes } 20421590Srgrimes } 2043104475Sphk#endif /* !USE_KQUEUE */ 20441590Srgrimes } 20451590Srgrimes} 20461590Srgrimes 20471590Srgrimes/*- 20481590Srgrimes *----------------------------------------------------------------------- 20491590Srgrimes * Job_Make -- 20501590Srgrimes * Start the creation of a target. Basically a front-end for 20511590Srgrimes * JobStart used by the Make module. 20521590Srgrimes * 20531590Srgrimes * Results: 20541590Srgrimes * None. 20551590Srgrimes * 20561590Srgrimes * Side Effects: 20571590Srgrimes * Another job is started. 20581590Srgrimes * 20591590Srgrimes *----------------------------------------------------------------------- 20601590Srgrimes */ 20611590Srgrimesvoid 2062104696SjmallettJob_Make(GNode *gn) 20631590Srgrimes{ 2064138232Sharti 2065138232Sharti JobStart(gn, 0, NULL); 20661590Srgrimes} 20671590Srgrimes 2068138079Sharti/* 2069138079Sharti * JobCopyShell: 2070138079Sharti * 2071138079Sharti * Make a new copy of the shell structure including a copy of the strings 2072138079Sharti * in it. This also defaults some fields in case they are NULL. 2073138079Sharti * 2074138079Sharti * The function returns a pointer to the new shell structure otherwise. 2075138079Sharti */ 2076138079Shartistatic Shell * 2077138079ShartiJobCopyShell(const Shell *osh) 2078138079Sharti{ 2079138079Sharti Shell *nsh; 2080138079Sharti 2081138079Sharti nsh = emalloc(sizeof(*nsh)); 2082138079Sharti nsh->name = estrdup(osh->name); 2083138079Sharti 2084138079Sharti if (osh->echoOff != NULL) 2085138079Sharti nsh->echoOff = estrdup(osh->echoOff); 2086138079Sharti else 2087138079Sharti nsh->echoOff = NULL; 2088138079Sharti if (osh->echoOn != NULL) 2089138079Sharti nsh->echoOn = estrdup(osh->echoOn); 2090138079Sharti else 2091138079Sharti nsh->echoOn = NULL; 2092138079Sharti nsh->hasEchoCtl = osh->hasEchoCtl; 2093138079Sharti 2094138079Sharti if (osh->noPrint != NULL) 2095138079Sharti nsh->noPrint = estrdup(osh->noPrint); 2096138079Sharti else 2097138079Sharti nsh->noPrint = NULL; 2098138079Sharti nsh->noPLen = osh->noPLen; 2099138079Sharti 2100138079Sharti nsh->hasErrCtl = osh->hasErrCtl; 2101138079Sharti if (osh->errCheck == NULL) 2102138079Sharti nsh->errCheck = estrdup(""); 2103138079Sharti else 2104138079Sharti nsh->errCheck = estrdup(osh->errCheck); 2105138079Sharti if (osh->ignErr == NULL) 2106138079Sharti nsh->ignErr = estrdup("%s"); 2107138079Sharti else 2108138079Sharti nsh->ignErr = estrdup(osh->ignErr); 2109138079Sharti 2110138079Sharti if (osh->echo == NULL) 2111138079Sharti nsh->echo = estrdup(""); 2112138079Sharti else 2113138079Sharti nsh->echo = estrdup(osh->echo); 2114138079Sharti 2115138079Sharti if (osh->exit == NULL) 2116138079Sharti nsh->exit = estrdup(""); 2117138079Sharti else 2118138079Sharti nsh->exit = estrdup(osh->exit); 2119138079Sharti 2120138079Sharti return (nsh); 2121138079Sharti} 2122138079Sharti 2123138079Sharti/* 2124138079Sharti * JobFreeShell: 2125138079Sharti * 2126138079Sharti * Free a shell structure and all associated strings. 2127138079Sharti */ 2128138079Shartistatic void 2129138079ShartiJobFreeShell(Shell *sh) 2130138079Sharti{ 2131138079Sharti 2132138079Sharti if (sh != NULL) { 2133138079Sharti free(sh->name); 2134138079Sharti free(sh->echoOff); 2135138079Sharti free(sh->echoOn); 2136138079Sharti free(sh->noPrint); 2137138079Sharti free(sh->errCheck); 2138138079Sharti free(sh->ignErr); 2139138079Sharti free(sh->echo); 2140138079Sharti free(sh->exit); 2141138079Sharti free(sh); 2142138079Sharti } 2143138079Sharti} 2144138079Sharti 2145136840Sruvoid 2146136840SruShell_Init(void) 2147136840Sru{ 2148138079Sharti 2149138079Sharti if (commandShell == NULL) 2150138228Sharti commandShell = JobMatchShell(shells[DEFSHELL].name); 2151138079Sharti 2152136840Sru if (shellPath == NULL) { 2153136840Sru /* 2154136840Sru * The user didn't specify a shell to use, so we are using the 2155136840Sru * default one... Both the absolute path and the last component 2156136840Sru * must be set. The last component is taken from the 'name' field 2157136840Sru * of the default shell description pointed-to by commandShell. 2158136840Sru * All default shells are located in _PATH_DEFSHELLDIR. 2159136840Sru */ 2160136840Sru shellName = commandShell->name; 2161136840Sru shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH); 2162136840Sru } 2163136840Sru} 2164136840Sru 21651590Srgrimes/*- 21661590Srgrimes *----------------------------------------------------------------------- 21671590Srgrimes * Job_Init -- 2168137572Sphk * Initialize the process module, given a maximum number of jobs. 21691590Srgrimes * 21701590Srgrimes * Results: 21711590Srgrimes * none 21721590Srgrimes * 21731590Srgrimes * Side Effects: 21741590Srgrimes * lists and counters are initialized 21751590Srgrimes *----------------------------------------------------------------------- 21761590Srgrimes */ 21771590Srgrimesvoid 2178137572SphkJob_Init(int maxproc) 21791590Srgrimes{ 21801590Srgrimes GNode *begin; /* node for commands to do at the very start */ 2181137606Sphk const char *env; 2182137605Sharti struct sigaction sa; 21831590Srgrimes 2184138232Sharti fifoFd = -1; 2185137606Sphk env = getenv("MAKE_JOBS_FIFO"); 2186137606Sphk 2187137606Sphk if (env == NULL && maxproc > 1) { 2188137606Sphk /* 2189137606Sphk * We did not find the environment variable so we are the leader. 2190137606Sphk * Create the fifo, open it, write one char per allowed job into 2191137606Sphk * the pipe. 2192137606Sphk */ 2193137606Sphk mktemp(fifoName); 2194137606Sphk if (!mkfifo(fifoName, 0600)) { 2195137606Sphk fifoFd = open(fifoName, O_RDWR | O_NONBLOCK, 0); 2196137606Sphk if (fifoFd >= 0) { 2197137606Sphk fifoMaster = 1; 2198137606Sphk fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2199137606Sphk env = fifoName; 2200137606Sphk setenv("MAKE_JOBS_FIFO", env, 1); 2201137606Sphk while (maxproc-- > 0) { 2202137606Sphk write(fifoFd, "+", 1); 2203137606Sphk } 2204138264Sharti /* The master make does not get a magic token */ 2205137606Sphk jobFull = TRUE; 2206137606Sphk maxJobs = 0; 2207137606Sphk } else { 2208137606Sphk unlink(fifoName); 2209137606Sphk env = NULL; 2210137606Sphk } 2211137606Sphk } 2212137606Sphk } else if (env != NULL) { 2213137606Sphk /* 2214137606Sphk * We had the environment variable so we are a slave. 2215137606Sphk * Open fifo and give ourselves a magic token which represents 2216137606Sphk * the token our parent make has grabbed to start his make process. 2217137606Sphk * Otherwise the sub-makes would gobble up tokens and the proper 2218137610Sceri * number of tokens to specify to -j would depend on the depth of 2219137610Sceri * the tree and the order of execution. 2220137606Sphk */ 2221137606Sphk fifoFd = open(env, O_RDWR, 0); 2222137606Sphk if (fifoFd >= 0) { 2223137606Sphk fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2224137606Sphk maxJobs = 1; 2225137606Sphk jobFull = FALSE; 2226137606Sphk } 2227137606Sphk } 2228137606Sphk if (fifoFd <= 0) { 2229137606Sphk maxJobs = maxproc; 2230137606Sphk jobFull = FALSE; 2231137606Sphk } else { 2232137606Sphk } 2233138232Sharti nJobs = 0; 22341590Srgrimes 2235138232Sharti aborting = 0; 2236138232Sharti errors = 0; 22371590Srgrimes 2238138232Sharti lastNode = NULL; 22391590Srgrimes 2240137606Sphk if ((maxJobs == 1 && fifoFd < 0) || beVerbose == 0) { 22411590Srgrimes /* 22421590Srgrimes * If only one job can run at a time, there's no need for a banner, 22431590Srgrimes * no is there? 22441590Srgrimes */ 22451590Srgrimes targFmt = ""; 22461590Srgrimes } else { 22471590Srgrimes targFmt = TARG_FMT; 22481590Srgrimes } 22498874Srgrimes 2250136840Sru Shell_Init(); 22511590Srgrimes 22521590Srgrimes /* 22531590Srgrimes * Catch the four signals that POSIX specifies if they aren't ignored. 2254137605Sharti * JobCatchSignal will just set global variables and hope someone 2255137605Sharti * else is going to handle the interrupt. 22561590Srgrimes */ 2257137605Sharti sa.sa_handler = JobCatchSig; 2258137605Sharti sigemptyset(&sa.sa_mask); 2259137605Sharti sa.sa_flags = 0; 2260137605Sharti 226118730Ssteve if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 2262138232Sharti sigaction(SIGINT, &sa, NULL); 22631590Srgrimes } 226418730Ssteve if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 2265138232Sharti sigaction(SIGHUP, &sa, NULL); 22661590Srgrimes } 226718730Ssteve if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 2268138232Sharti sigaction(SIGQUIT, &sa, NULL); 22691590Srgrimes } 227018730Ssteve if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 2271138232Sharti sigaction(SIGTERM, &sa, NULL); 22721590Srgrimes } 22731590Srgrimes /* 22741590Srgrimes * There are additional signals that need to be caught and passed if 22751590Srgrimes * either the export system wants to be told directly of signals or if 22761590Srgrimes * we're giving each job its own process group (since then it won't get 22771590Srgrimes * signals from the terminal driver as we own the terminal) 22781590Srgrimes */ 2279137202Sharti#if defined(USE_PGRP) 228018730Ssteve if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { 2281138232Sharti sigaction(SIGTSTP, &sa, NULL); 22821590Srgrimes } 228318730Ssteve if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { 2284138232Sharti sigaction(SIGTTOU, &sa, NULL); 22851590Srgrimes } 228618730Ssteve if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { 2287138232Sharti sigaction(SIGTTIN, &sa, NULL); 22881590Srgrimes } 228918730Ssteve if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { 2290138232Sharti sigaction(SIGWINCH, &sa, NULL); 22911590Srgrimes } 22921590Srgrimes#endif 22938874Srgrimes 2294104475Sphk#ifdef USE_KQUEUE 2295104475Sphk if ((kqfd = kqueue()) == -1) { 2296104475Sphk Punt("kqueue: %s", strerror(errno)); 2297104475Sphk } 2298104475Sphk#endif 2299104475Sphk 230018730Ssteve begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); 23011590Srgrimes 230269527Swill if (begin != NULL) { 2303138264Sharti JobStart(begin, JOB_SPECIAL, (Job *)NULL); 23041590Srgrimes while (nJobs) { 2305137606Sphk Job_CatchOutput(0); 230618730Ssteve Job_CatchChildren(!usePipes); 23071590Srgrimes } 23081590Srgrimes } 230918730Ssteve postCommands = Targ_FindNode(".END", TARG_CREATE); 23101590Srgrimes} 23111590Srgrimes 23121590Srgrimes/*- 23131590Srgrimes *----------------------------------------------------------------------- 23141590Srgrimes * Job_Full -- 23151590Srgrimes * See if the job table is full. It is considered full if it is OR 23161590Srgrimes * if we are in the process of aborting OR if we have 23171590Srgrimes * reached/exceeded our local quota. This prevents any more jobs 23181590Srgrimes * from starting up. 23191590Srgrimes * 23201590Srgrimes * Results: 23211590Srgrimes * TRUE if the job table is full, FALSE otherwise 23221590Srgrimes * Side Effects: 23231590Srgrimes * None. 23241590Srgrimes *----------------------------------------------------------------------- 23251590Srgrimes */ 23261590SrgrimesBoolean 2327104696SjmallettJob_Full(void) 23281590Srgrimes{ 2329137606Sphk char c; 2330137606Sphk int i; 2331137606Sphk 2332137606Sphk if (aborting) 2333138232Sharti return (aborting); 2334137606Sphk if (fifoFd >= 0 && jobFull) { 2335137606Sphk i = read(fifoFd, &c, 1); 2336137606Sphk if (i > 0) { 2337137606Sphk maxJobs++; 2338137606Sphk jobFull = FALSE; 2339137606Sphk } 2340137606Sphk } 2341138232Sharti return (jobFull); 23421590Srgrimes} 23431590Srgrimes 23441590Srgrimes/*- 23451590Srgrimes *----------------------------------------------------------------------- 23461590Srgrimes * Job_Empty -- 23471590Srgrimes * See if the job table is empty. Because the local concurrency may 23481590Srgrimes * be set to 0, it is possible for the job table to become empty, 23491590Srgrimes * while the list of stoppedJobs remains non-empty. In such a case, 23501590Srgrimes * we want to restart as many jobs as we can. 23511590Srgrimes * 23521590Srgrimes * Results: 23531590Srgrimes * TRUE if it is. FALSE if it ain't. 23541590Srgrimes * 23551590Srgrimes * Side Effects: 23561590Srgrimes * None. 23571590Srgrimes * 23581590Srgrimes * ----------------------------------------------------------------------- 23591590Srgrimes */ 23601590SrgrimesBoolean 2361104696SjmallettJob_Empty(void) 23621590Srgrimes{ 23631590Srgrimes if (nJobs == 0) { 2364138916Sharti if (!Lst_IsEmpty(&stoppedJobs) && !aborting) { 23651590Srgrimes /* 23661590Srgrimes * The job table is obviously not full if it has no jobs in 23671590Srgrimes * it...Try and restart the stopped jobs. 23681590Srgrimes */ 23691590Srgrimes jobFull = FALSE; 237018730Ssteve JobRestartJobs(); 2371138232Sharti return (FALSE); 23721590Srgrimes } else { 2373138232Sharti return (TRUE); 23741590Srgrimes } 23751590Srgrimes } else { 2376138232Sharti return (FALSE); 23771590Srgrimes } 23781590Srgrimes} 23791590Srgrimes 23801590Srgrimes/*- 23811590Srgrimes *----------------------------------------------------------------------- 23821590Srgrimes * JobMatchShell -- 23831590Srgrimes * Find a matching shell in 'shells' given its final component. 23841590Srgrimes * 23851590Srgrimes * Results: 2386138334Sharti * A pointer to a freshly allocated Shell structure with a copy 2387138228Sharti * of the static structure or NULL if no shell with the given name 2388138228Sharti * is found. 23891590Srgrimes * 23901590Srgrimes * Side Effects: 23911590Srgrimes * None. 23921590Srgrimes * 23931590Srgrimes *----------------------------------------------------------------------- 23941590Srgrimes */ 23951590Srgrimesstatic Shell * 2396138228ShartiJobMatchShell(const char *name) 23971590Srgrimes{ 2398138228Sharti const struct CShell *sh; /* Pointer into shells table */ 2399138228Sharti struct Shell *nsh; 24001590Srgrimes 2401138334Sharti for (sh = shells; sh < shells + sizeof(shells) / sizeof(shells[0]); sh++) 2402138334Sharti if (strcmp(sh->name, name) == 0) 2403138334Sharti break; 24041590Srgrimes 2405138334Sharti if (sh == shells + sizeof(shells) / sizeof(shells[0])) 2406138228Sharti return (NULL); 2407138228Sharti 2408138228Sharti /* make a copy */ 2409138228Sharti nsh = emalloc(sizeof(*nsh)); 2410138228Sharti 2411138334Sharti nsh->name = estrdup(sh->name); 2412138334Sharti nsh->echoOff = estrdup(sh->echoOff); 2413138334Sharti nsh->echoOn = estrdup(sh->echoOn); 2414138334Sharti nsh->hasEchoCtl = sh->hasEchoCtl; 2415138334Sharti nsh->noPrint = estrdup(sh->noPrint); 2416138334Sharti nsh->noPLen = sh->noPLen; 2417138334Sharti nsh->hasErrCtl = sh->hasErrCtl; 2418138334Sharti nsh->errCheck = estrdup(sh->errCheck); 2419138334Sharti nsh->ignErr = estrdup(sh->ignErr); 2420138334Sharti nsh->echo = estrdup(sh->echo); 2421138334Sharti nsh->exit = estrdup(sh->exit); 2422138228Sharti 2423138228Sharti return (nsh); 24241590Srgrimes} 24251590Srgrimes 24261590Srgrimes/*- 24271590Srgrimes *----------------------------------------------------------------------- 24281590Srgrimes * Job_ParseShell -- 24291590Srgrimes * Parse a shell specification and set up commandShell, shellPath 24301590Srgrimes * and shellName appropriately. 24311590Srgrimes * 24321590Srgrimes * Results: 24331590Srgrimes * FAILURE if the specification was incorrect. 24341590Srgrimes * 24351590Srgrimes * Side Effects: 24361590Srgrimes * commandShell points to a Shell structure (either predefined or 24371590Srgrimes * created from the shell spec), shellPath is the full path of the 24381590Srgrimes * shell described by commandShell, while shellName is just the 24391590Srgrimes * final component of shellPath. 24401590Srgrimes * 24411590Srgrimes * Notes: 24421590Srgrimes * A shell specification consists of a .SHELL target, with dependency 24431590Srgrimes * operator, followed by a series of blank-separated words. Double 24441590Srgrimes * quotes can be used to use blanks in words. A backslash escapes 24451590Srgrimes * anything (most notably a double-quote and a space) and 24461590Srgrimes * provides the functionality it does in C. Each word consists of 24471590Srgrimes * keyword and value separated by an equal sign. There should be no 24481590Srgrimes * unnecessary spaces in the word. The keywords are as follows: 24491590Srgrimes * name Name of shell. 24501590Srgrimes * path Location of shell. Overrides "name" if given 24511590Srgrimes * quiet Command to turn off echoing. 24521590Srgrimes * echo Command to turn echoing on 24531590Srgrimes * filter Result of turning off echoing that shouldn't be 24541590Srgrimes * printed. 24551590Srgrimes * echoFlag Flag to turn echoing on at the start 24561590Srgrimes * errFlag Flag to turn error checking on at the start 24571590Srgrimes * hasErrCtl True if shell has error checking control 24581590Srgrimes * check Command to turn on error checking if hasErrCtl 24591590Srgrimes * is TRUE or template of command to echo a command 24601590Srgrimes * for which error checking is off if hasErrCtl is 24611590Srgrimes * FALSE. 24621590Srgrimes * ignore Command to turn off error checking if hasErrCtl 24631590Srgrimes * is TRUE or template of command to execute a 24641590Srgrimes * command so as to ignore any errors it returns if 24651590Srgrimes * hasErrCtl is FALSE. 24661590Srgrimes * 24671590Srgrimes *----------------------------------------------------------------------- 24681590Srgrimes */ 24691590SrgrimesReturnStatus 2470104696SjmallettJob_ParseShell(char *line) 24711590Srgrimes{ 24721590Srgrimes char **words; 24731590Srgrimes int wordCount; 247494584Sobrien char **argv; 247594584Sobrien int argc; 24761590Srgrimes char *path; 2477138228Sharti Shell newShell; 2478138228Sharti Shell *sh; 24791590Srgrimes Boolean fullSpec = FALSE; 24801590Srgrimes 2481138232Sharti while (isspace((unsigned char)*line)) { 24821590Srgrimes line++; 24831590Srgrimes } 248418730Ssteve words = brk_string(line, &wordCount, TRUE); 24851590Srgrimes 248669531Swill memset(&newShell, 0, sizeof(newShell)); 24878874Srgrimes 24881590Srgrimes /* 24891590Srgrimes * Parse the specification by keyword 24901590Srgrimes */ 249118730Ssteve for (path = NULL, argc = wordCount - 1, argv = words + 1; 24921590Srgrimes argc != 0; 24931590Srgrimes argc--, argv++) { 249418730Ssteve if (strncmp(*argv, "path=", 5) == 0) { 24951590Srgrimes path = &argv[0][5]; 249618730Ssteve } else if (strncmp(*argv, "name=", 5) == 0) { 24971590Srgrimes newShell.name = &argv[0][5]; 24981590Srgrimes } else { 249918730Ssteve if (strncmp(*argv, "quiet=", 6) == 0) { 25001590Srgrimes newShell.echoOff = &argv[0][6]; 250118730Ssteve } else if (strncmp(*argv, "echo=", 5) == 0) { 25021590Srgrimes newShell.echoOn = &argv[0][5]; 250318730Ssteve } else if (strncmp(*argv, "filter=", 7) == 0) { 25041590Srgrimes newShell.noPrint = &argv[0][7]; 25051590Srgrimes newShell.noPLen = strlen(newShell.noPrint); 250618730Ssteve } else if (strncmp(*argv, "echoFlag=", 9) == 0) { 25071590Srgrimes newShell.echo = &argv[0][9]; 250818730Ssteve } else if (strncmp(*argv, "errFlag=", 8) == 0) { 25091590Srgrimes newShell.exit = &argv[0][8]; 251018730Ssteve } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) { 25111590Srgrimes char c = argv[0][10]; 25121590Srgrimes newShell.hasErrCtl = !((c != 'Y') && (c != 'y') && 251318730Ssteve (c != 'T') && (c != 't')); 251418730Ssteve } else if (strncmp(*argv, "check=", 6) == 0) { 25151590Srgrimes newShell.errCheck = &argv[0][6]; 251618730Ssteve } else if (strncmp(*argv, "ignore=", 7) == 0) { 25171590Srgrimes newShell.ignErr = &argv[0][7]; 25181590Srgrimes } else { 251918730Ssteve Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", 25201590Srgrimes *argv); 2521138232Sharti return (FAILURE); 25221590Srgrimes } 25231590Srgrimes fullSpec = TRUE; 25241590Srgrimes } 25251590Srgrimes } 25261590Srgrimes 2527138079Sharti /* 2528138079Sharti * Some checks (could be more) 2529138079Sharti */ 2530138079Sharti if (fullSpec) { 2531138079Sharti if ((newShell.echoOn != NULL) ^ (newShell.echoOff != NULL)) 2532138079Sharti Parse_Error(PARSE_FATAL, "Shell must have either both echoOff and " 2533138079Sharti "echoOn or none of them"); 2534138079Sharti 2535138079Sharti if (newShell.echoOn != NULL && newShell.echoOff) 2536138079Sharti newShell.hasEchoCtl = TRUE; 2537138079Sharti } 2538138079Sharti 253918730Ssteve if (path == NULL) { 25401590Srgrimes /* 25411590Srgrimes * If no path was given, the user wants one of the pre-defined shells, 25421590Srgrimes * yes? So we find the one s/he wants with the help of JobMatchShell 25431590Srgrimes * and set things up the right way. shellPath will be set up by 25441590Srgrimes * Job_Init. 25451590Srgrimes */ 254618730Ssteve if (newShell.name == NULL) { 254718730Ssteve Parse_Error(PARSE_FATAL, "Neither path nor name specified"); 2548138079Sharti return (FAILURE); 25491590Srgrimes } 2550138079Sharti if ((sh = JobMatchShell(newShell.name)) == NULL) { 2551138079Sharti Parse_Error(PARSE_FATAL, "%s: no matching shell", newShell.name); 2552138079Sharti return (FAILURE); 2553138079Sharti } 2554138079Sharti 25551590Srgrimes } else { 25561590Srgrimes /* 25571590Srgrimes * The user provided a path. If s/he gave nothing else (fullSpec is 25581590Srgrimes * FALSE), try and find a matching shell in the ones we know of. 25591590Srgrimes * Else we just take the specification at its word and copy it 25601590Srgrimes * to a new location. In either case, we need to record the 25611590Srgrimes * path the user gave for the shell. 25621590Srgrimes */ 2563138079Sharti free(shellPath); 2564138079Sharti shellPath = estrdup(path); 2565138079Sharti if (newShell.name == NULL) { 2566138079Sharti /* get the base name as the name */ 2567138079Sharti path = strrchr(path, '/'); 2568138079Sharti if (path == NULL) { 2569138079Sharti path = shellPath; 2570138079Sharti } else { 2571138079Sharti path += 1; 2572138079Sharti } 2573138079Sharti newShell.name = path; 25741590Srgrimes } 2575138079Sharti 25761590Srgrimes if (!fullSpec) { 2577138079Sharti if ((sh = JobMatchShell(newShell.name)) == NULL) { 2578136840Sru Parse_Error(PARSE_FATAL, "%s: no matching shell", 2579138079Sharti newShell.name); 2580138079Sharti return (FAILURE); 2581136840Sru } 25821590Srgrimes } else { 2583138228Sharti sh = JobCopyShell(&newShell); 25841590Srgrimes } 25851590Srgrimes } 25861590Srgrimes 2587138079Sharti /* set the new shell */ 2588138079Sharti JobFreeShell(commandShell); 2589138228Sharti commandShell = sh; 25908874Srgrimes 2591138079Sharti shellName = commandShell->name; 25928874Srgrimes 2593138079Sharti return (SUCCESS); 25941590Srgrimes} 25951590Srgrimes 25961590Srgrimes/*- 25971590Srgrimes *----------------------------------------------------------------------- 25981590Srgrimes * JobInterrupt -- 25991590Srgrimes * Handle the receipt of an interrupt. 26001590Srgrimes * 26011590Srgrimes * Results: 26021590Srgrimes * None 26031590Srgrimes * 26041590Srgrimes * Side Effects: 26051590Srgrimes * All children are killed. Another job will be started if the 26061590Srgrimes * .INTERRUPT target was given. 26071590Srgrimes *----------------------------------------------------------------------- 26081590Srgrimes */ 26091590Srgrimesstatic void 2610104696SjmallettJobInterrupt(int runINTERRUPT, int signo) 26111590Srgrimes{ 2612138512Sharti LstNode *ln; /* element in job table */ 2613138564Sharti Job *job; /* job descriptor in that element */ 26141590Srgrimes GNode *interrupt; /* the node describing the .INTERRUPT target */ 26158874Srgrimes 26161590Srgrimes aborting = ABORT_INTERRUPT; 26171590Srgrimes 2618138916Sharti for (ln = Lst_First(&jobs); ln != NULL; ln = Lst_Succ(ln)) { 2619138264Sharti job = Lst_Datum(ln); 26201590Srgrimes 262118730Ssteve if (!Targ_Precious(job->node)) { 2622138232Sharti char *file = (job->node->path == NULL ? 2623138232Sharti job->node->name : 2624138232Sharti job->node->path); 262518730Ssteve if (!noExecute && eunlink(file) != -1) { 262618730Ssteve Error("*** %s removed", file); 26271590Srgrimes } 26281590Srgrimes } 26291590Srgrimes if (job->pid) { 2630103545Sjmallett DEBUGF(JOB, ("JobInterrupt passing signal to child %d.\n", 2631103545Sjmallett job->pid)); 263218730Ssteve KILL(job->pid, signo); 263318730Ssteve } 263418730Ssteve } 263518730Ssteve 26361590Srgrimes if (runINTERRUPT && !touchFlag) { 2637137605Sharti /* clear the interrupted flag because we would get an 2638137605Sharti * infinite loop otherwise */ 2639137605Sharti interrupted = 0; 2640137605Sharti 264118730Ssteve interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 264269527Swill if (interrupt != NULL) { 26431590Srgrimes ignoreErrors = FALSE; 26441590Srgrimes 2645138264Sharti JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL); 26461590Srgrimes while (nJobs) { 2647137606Sphk Job_CatchOutput(0); 264818730Ssteve Job_CatchChildren(!usePipes); 26491590Srgrimes } 26501590Srgrimes } 26511590Srgrimes } 26521590Srgrimes} 26531590Srgrimes 26541590Srgrimes/* 26551590Srgrimes *----------------------------------------------------------------------- 265694594Sobrien * Job_Finish -- 26571590Srgrimes * Do final processing such as the running of the commands 26588874Srgrimes * attached to the .END target. 26591590Srgrimes * 26601590Srgrimes * Results: 26611590Srgrimes * Number of errors reported. 26621590Srgrimes *----------------------------------------------------------------------- 26631590Srgrimes */ 26641590Srgrimesint 2665104696SjmallettJob_Finish(void) 26661590Srgrimes{ 2667138232Sharti 2668138916Sharti if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { 26691590Srgrimes if (errors) { 267018730Ssteve Error("Errors reported so .END ignored"); 26711590Srgrimes } else { 267218730Ssteve JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); 26731590Srgrimes 26741590Srgrimes while (nJobs) { 2675137606Sphk Job_CatchOutput(0); 267618730Ssteve Job_CatchChildren(!usePipes); 26771590Srgrimes } 26781590Srgrimes } 26791590Srgrimes } 2680137606Sphk if (fifoFd >= 0) { 2681137606Sphk close(fifoFd); 2682137606Sphk fifoFd = -1; 2683137606Sphk if (fifoMaster) 2684137606Sphk unlink(fifoName); 2685137606Sphk } 2686138232Sharti return (errors); 26871590Srgrimes} 26881590Srgrimes 26891590Srgrimes/*- 26901590Srgrimes *----------------------------------------------------------------------- 26911590Srgrimes * Job_Wait -- 26921590Srgrimes * Waits for all running jobs to finish and returns. Sets 'aborting' 26931590Srgrimes * to ABORT_WAIT to prevent other jobs from starting. 26941590Srgrimes * 26951590Srgrimes * Results: 26961590Srgrimes * None. 26971590Srgrimes * 26981590Srgrimes * Side Effects: 26991590Srgrimes * Currently running jobs finish. 27001590Srgrimes * 27011590Srgrimes *----------------------------------------------------------------------- 27021590Srgrimes */ 27031590Srgrimesvoid 2704104696SjmallettJob_Wait(void) 27051590Srgrimes{ 2706138232Sharti 27071590Srgrimes aborting = ABORT_WAIT; 27081590Srgrimes while (nJobs != 0) { 2709137606Sphk Job_CatchOutput(0); 27101590Srgrimes Job_CatchChildren(!usePipes); 27111590Srgrimes } 27121590Srgrimes aborting = 0; 27131590Srgrimes} 27141590Srgrimes 27151590Srgrimes/*- 27161590Srgrimes *----------------------------------------------------------------------- 27171590Srgrimes * Job_AbortAll -- 27181590Srgrimes * Abort all currently running jobs without handling output or anything. 27191590Srgrimes * This function is to be called only in the event of a major 27201590Srgrimes * error. Most definitely NOT to be called from JobInterrupt. 27211590Srgrimes * 27221590Srgrimes * Results: 27231590Srgrimes * None 27241590Srgrimes * 27251590Srgrimes * Side Effects: 27261590Srgrimes * All children are killed, not just the firstborn 27271590Srgrimes *----------------------------------------------------------------------- 27281590Srgrimes */ 27291590Srgrimesvoid 2730104696SjmallettJob_AbortAll(void) 27311590Srgrimes{ 2732138512Sharti LstNode *ln; /* element in job table */ 27331590Srgrimes Job *job; /* the job descriptor in that element */ 27341590Srgrimes int foo; 27358874Srgrimes 27361590Srgrimes aborting = ABORT_ERROR; 27378874Srgrimes 27381590Srgrimes if (nJobs) { 2739138916Sharti for (ln = Lst_First(&jobs); ln != NULL; ln = Lst_Succ(ln)) { 2740138264Sharti job = Lst_Datum(ln); 27411590Srgrimes 27421590Srgrimes /* 27431590Srgrimes * kill the child process with increasingly drastic signals to make 27448874Srgrimes * darn sure it's dead. 27451590Srgrimes */ 27461590Srgrimes KILL(job->pid, SIGINT); 27471590Srgrimes KILL(job->pid, SIGKILL); 27481590Srgrimes } 27491590Srgrimes } 27508874Srgrimes 27511590Srgrimes /* 27521590Srgrimes * Catch as many children as want to report in at first, then give up 27531590Srgrimes */ 2754138232Sharti while (waitpid((pid_t)-1, &foo, WNOHANG) > 0) 27551590Srgrimes continue; 27561590Srgrimes} 275718730Ssteve 275818730Ssteve/*- 275918730Ssteve *----------------------------------------------------------------------- 276018730Ssteve * JobRestartJobs -- 276118730Ssteve * Tries to restart stopped jobs if there are slots available. 276218730Ssteve * Note that this tries to restart them regardless of pending errors. 276318730Ssteve * It's not good to leave stopped jobs lying around! 276418730Ssteve * 276518730Ssteve * Results: 276618730Ssteve * None. 276718730Ssteve * 276818730Ssteve * Side Effects: 276918730Ssteve * Resumes(and possibly migrates) jobs. 277018730Ssteve * 277118730Ssteve *----------------------------------------------------------------------- 277218730Ssteve */ 277318730Sstevestatic void 2774104696SjmallettJobRestartJobs(void) 277518730Ssteve{ 2776138916Sharti while (!jobFull && !Lst_IsEmpty(&stoppedJobs)) { 2777103545Sjmallett DEBUGF(JOB, ("Job queue is not full. Restarting a stopped job.\n")); 2778138916Sharti JobRestart(Lst_DeQueue(&stoppedJobs)); 277918730Ssteve } 278018730Ssteve} 2781