1141104Sharti/*- 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$"); 441590Srgrimes 451590Srgrimes/*- 461590Srgrimes * job.c -- 471590Srgrimes * handle the creation etc. of our child processes. 481590Srgrimes * 491590Srgrimes * Interface: 50144467Sharti * Job_Make Start the creation of the given target. 511590Srgrimes * 52144467Sharti * Job_CatchChildren 53144467Sharti * Check for and handle the termination of any children. 54144467Sharti * This must be called reasonably frequently to keep the 55144467Sharti * whole make going at a decent clip, since job table 56144467Sharti * entries aren't removed until their process is caught 57144467Sharti * this way. Its single argument is TRUE if the function 58144467Sharti * should block waiting for a child to terminate. 591590Srgrimes * 60144467Sharti * Job_CatchOutput Print any output our children have produced. Should 61144467Sharti * also be called fairly frequently to keep the user 62144467Sharti * informed of what's going on. If no output is waiting, 63144467Sharti * it will block for a time given by the SEL_* constants, 64144467Sharti * below, or until output is ready. 651590Srgrimes * 66144467Sharti * Job_Init Called to intialize this module. in addition, any 67144467Sharti * commands attached to the .BEGIN target are executed 68144467Sharti * before this function returns. Hence, the makefile must 69144467Sharti * have been parsed before this function is called. 701590Srgrimes * 71144467Sharti * Job_Full Return TRUE if the job table is filled. 721590Srgrimes * 73144467Sharti * Job_Empty Return TRUE if the job table is completely empty. 741590Srgrimes * 75144467Sharti * Job_Finish Perform any final processing which needs doing. This 76144467Sharti * includes the execution of any commands which have 77144467Sharti * been/were attached to the .END target. It should only 78144467Sharti * be called when the job table is empty. 791590Srgrimes * 80144467Sharti * Job_AbortAll Abort all currently running jobs. It doesn't handle 81144467Sharti * output or do anything for the jobs, just kills them. 82144467Sharti * It should only be called in an emergency, as it were. 831590Srgrimes * 84144467Sharti * Job_CheckCommands 85144467Sharti * Verify that the commands for a target are ok. Provide 86144467Sharti * them if necessary and possible. 871590Srgrimes * 88144467Sharti * Job_Touch Update a target without really updating it. 891590Srgrimes * 90144467Sharti * Job_Wait Wait for all currently-running jobs to finish. 91146132Sharti * 92146132Sharti * compat.c -- 93146132Sharti * The routines in this file implement the full-compatibility 94146132Sharti * mode of PMake. Most of the special functionality of PMake 95146132Sharti * is available in this mode. Things not supported: 96146132Sharti * - different shells. 97146132Sharti * - friendly variable substitution. 98146132Sharti * 99146132Sharti * Interface: 100146132Sharti * Compat_Run Initialize things for this module and recreate 101146132Sharti * thems as need creatin' 1021590Srgrimes */ 1031590Srgrimes 104144494Sharti#include <sys/queue.h> 1051590Srgrimes#include <sys/types.h> 106141104Sharti#include <sys/select.h> 1071590Srgrimes#include <sys/stat.h> 108107447Sru#ifdef USE_KQUEUE 109104475Sphk#include <sys/event.h> 110107447Sru#endif 1111590Srgrimes#include <sys/wait.h> 112141104Sharti#include <ctype.h> 113146160Sjmallett#include <err.h> 11494506Scharnier#include <errno.h> 1155814Sjkh#include <fcntl.h> 116144665Sharti#include <inttypes.h> 117202045Sharti#include <limits.h> 118202070Sharti#include <paths.h> 1191590Srgrimes#include <string.h> 1205814Sjkh#include <signal.h> 121141104Sharti#include <stdlib.h> 12280381Ssheldonh#include <unistd.h> 12394506Scharnier#include <utime.h> 124141104Sharti 125141104Sharti#include "arch.h" 126142457Sharti#include "buf.h" 127146056Sharti#include "config.h" 1281590Srgrimes#include "dir.h" 129141104Sharti#include "globals.h" 130141104Sharti#include "GNode.h" 1311590Srgrimes#include "job.h" 132141104Sharti#include "make.h" 133141104Sharti#include "parse.h" 134146574Sharti#include "proc.h" 135146572Sharti#include "shell.h" 136141104Sharti#include "str.h" 137146056Sharti#include "suff.h" 138141104Sharti#include "targ.h" 139141104Sharti#include "util.h" 140141104Sharti#include "var.h" 1411590Srgrimes 142202045Sharti#define TMPPAT "makeXXXXXXXXXX" 143146057Sharti 144146057Sharti#ifndef USE_KQUEUE 1451590Srgrimes/* 146146057Sharti * The SEL_ constants determine the maximum amount of time spent in select 147146057Sharti * before coming out to see if a child has finished. SEL_SEC is the number of 148146057Sharti * seconds and SEL_USEC is the number of micro-seconds 149146057Sharti */ 150146057Sharti#define SEL_SEC 2 151146057Sharti#define SEL_USEC 0 152146057Sharti#endif /* !USE_KQUEUE */ 153146057Sharti 154146057Sharti/* 155144483Sharti * Job Table definitions. 156144483Sharti * 157144483Sharti * The job "table" is kept as a linked Lst in 'jobs', with the number of 158144483Sharti * active jobs maintained in the 'nJobs' variable. At no time will this 159144483Sharti * exceed the value of 'maxJobs', initialized by the Job_Init function. 160144483Sharti * 161144483Sharti * When a job is finished, the Make_Update function is called on each of the 162144483Sharti * parents of the node which was just remade. This takes care of the upward 163144483Sharti * traversal of the dependency graph. 164144483Sharti */ 165144483Sharti#define JOB_BUFSIZE 1024 166144483Shartitypedef struct Job { 167144665Sharti pid_t pid; /* The child's process ID */ 168144483Sharti 169144483Sharti struct GNode *node; /* The target the child is making */ 170144483Sharti 171144483Sharti /* 172144483Sharti * A LstNode for the first command to be saved after the job completes. 173144483Sharti * This is NULL if there was no "..." in the job's commands. 174144483Sharti */ 175144483Sharti LstNode *tailCmds; 176144483Sharti 177144483Sharti /* 178144483Sharti * An FILE* for writing out the commands. This is only 179144483Sharti * used before the job is actually started. 180144483Sharti */ 181144483Sharti FILE *cmdFILE; 182144483Sharti 183144483Sharti /* 184144483Sharti * A word of flags which determine how the module handles errors, 185144483Sharti * echoing, etc. for the job 186144483Sharti */ 187144483Sharti short flags; /* Flags to control treatment of job */ 188144483Sharti#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ 189144483Sharti#define JOB_SILENT 0x002 /* no output */ 190144483Sharti#define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally 191144483Sharti * if we can't export it and maxLocal is 0 */ 192146061Sharti#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing 193144483Sharti * commands */ 194144483Sharti#define JOB_FIRST 0x020 /* Job is first job for the node */ 195144483Sharti#define JOB_RESTART 0x080 /* Job needs to be completely restarted */ 196144483Sharti#define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped, 197144483Sharti * for some reason */ 198144483Sharti#define JOB_CONTINUING 0x200 /* We are in the process of resuming this job. 199144483Sharti * Used to avoid infinite recursion between 200144483Sharti * JobFinish and JobRestart */ 201144483Sharti 202144483Sharti /* union for handling shell's output */ 203144483Sharti union { 204144483Sharti /* 205144483Sharti * This part is used when usePipes is true. 206146061Sharti * The output is being caught via a pipe and the descriptors 207144483Sharti * of our pipe, an array in which output is line buffered and 208144483Sharti * the current position in that buffer are all maintained for 209144483Sharti * each job. 210144483Sharti */ 211144483Sharti struct { 212144483Sharti /* 213144483Sharti * Input side of pipe associated with 214144483Sharti * job's output channel 215144483Sharti */ 216144483Sharti int op_inPipe; 217144483Sharti 218144483Sharti /* 219144483Sharti * Output side of pipe associated with job's 220144483Sharti * output channel 221144483Sharti */ 222144483Sharti int op_outPipe; 223144483Sharti 224144483Sharti /* 225144483Sharti * Buffer for storing the output of the 226144483Sharti * job, line by line 227144483Sharti */ 228144483Sharti char op_outBuf[JOB_BUFSIZE + 1]; 229144483Sharti 230144483Sharti /* Current position in op_outBuf */ 231144483Sharti int op_curPos; 232144483Sharti } o_pipe; 233144483Sharti 234144483Sharti /* 235144483Sharti * If usePipes is false the output is routed to a temporary 236144483Sharti * file and all that is kept is the name of the file and the 237144483Sharti * descriptor open to the file. 238144483Sharti */ 239144483Sharti struct { 240144483Sharti /* Name of file to which shell output was rerouted */ 241202045Sharti char of_outFile[PATH_MAX]; 242144483Sharti 243144483Sharti /* 244144483Sharti * Stream open to the output file. Used to funnel all 245144483Sharti * from a single job to one file while still allowing 246144483Sharti * multiple shell invocations 247144483Sharti */ 248144483Sharti int of_outFd; 249144483Sharti } o_file; 250144483Sharti 251144483Sharti } output; /* Data for tracking a shell's output */ 252144494Sharti 253144494Sharti TAILQ_ENTRY(Job) link; /* list link */ 254144483Sharti} Job; 255144483Sharti 256146061Sharti#define outPipe output.o_pipe.op_outPipe 257146061Sharti#define inPipe output.o_pipe.op_inPipe 258144483Sharti#define outBuf output.o_pipe.op_outBuf 259144483Sharti#define curPos output.o_pipe.op_curPos 260144483Sharti#define outFile output.o_file.of_outFile 261146061Sharti#define outFd output.o_file.of_outFd 262144483Sharti 263144494ShartiTAILQ_HEAD(JobList, Job); 264144494Sharti 265144483Sharti/* 2668874Srgrimes * error handling variables 2671590Srgrimes */ 268144467Shartistatic int aborting = 0; /* why is the make aborting? */ 269144467Sharti#define ABORT_ERROR 1 /* Because of an error */ 270144467Sharti#define ABORT_INTERRUPT 2 /* Because it was interrupted */ 271144467Sharti#define ABORT_WAIT 3 /* Waiting for jobs to finish */ 2721590Srgrimes 27318730Ssteve/* 27418730Ssteve * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file 27518730Ssteve * is a char! So when we go above 127 we turn negative! 27618730Ssteve */ 277138232Sharti#define FILENO(a) ((unsigned)fileno(a)) 2781590Srgrimes 2791590Srgrimes/* 2801590Srgrimes * post-make command processing. The node postCommands is really just the 2811590Srgrimes * .END target but we keep it around to avoid having to search for it 2821590Srgrimes * all the time. 2831590Srgrimes */ 284144467Shartistatic GNode *postCommands; 2851590Srgrimes 2861590Srgrimes/* 287144467Sharti * The number of commands actually printed for a target. Should this 288144467Sharti * number be 0, no shell will be executed. 289144467Sharti */ 290144467Shartistatic int numCommands; 291144467Sharti 292144467Sharti/* 2931590Srgrimes * Return values from JobStart. 2941590Srgrimes */ 295144467Sharti#define JOB_RUNNING 0 /* Job is running */ 296146061Sharti#define JOB_ERROR 1 /* Error in starting the job */ 297144467Sharti#define JOB_FINISHED 2 /* The job is already finished */ 298144467Sharti#define JOB_STOPPED 3 /* The job is stopped */ 2991590Srgrimes 3001590Srgrimes/* 301146140Sharti * The maximum number of jobs that may run. This is initialize from the 302146140Sharti * -j argument for the leading make and from the FIFO for sub-makes. 303146140Sharti */ 304146140Shartistatic int maxJobs; 305146140Sharti 306144656Shartistatic int nJobs; /* The number of children currently running */ 307138916Sharti 308138916Sharti/* The structures that describe them */ 309144494Shartistatic struct JobList jobs = TAILQ_HEAD_INITIALIZER(jobs); 310138916Sharti 311146061Shartistatic Boolean jobFull; /* Flag to tell when the job table is full. It 3121590Srgrimes * is set TRUE when (1) the total number of 313137572Sphk * running jobs equals the maximum allowed */ 314104475Sphk#ifdef USE_KQUEUE 315104475Sphkstatic int kqfd; /* File descriptor obtained by kqueue() */ 316104475Sphk#else 317146061Shartistatic fd_set outputs; /* Set of descriptors of pipes connected to 3181590Srgrimes * the output channels of children */ 3191590Srgrimes#endif 3201590Srgrimes 321146061Shartistatic GNode *lastNode; /* The node for which output was most recently 3221590Srgrimes * produced. */ 323146061Shartistatic const char *targFmt; /* Format string to use to head output from a 3241590Srgrimes * job when it's not the most-recent job heard 3251590Srgrimes * from */ 326186559Sobrienstatic char *targPrefix = NULL; /* What we print at the start of targFmt */ 3271590Srgrimes 328186559Sobrien#define TARG_FMT "%s %s ---\n" /* Default format */ 329137202Sharti#define MESSAGE(fp, gn) \ 330186559Sobrien fprintf(fp, targFmt, targPrefix, gn->name); 33118730Ssteve 3321590Srgrimes/* 333137252Sharti * When JobStart attempts to run a job but isn't allowed to 334137252Sharti * or when Job_CatchChildren detects a job that has 335137252Sharti * been stopped somehow, the job is placed on the stoppedJobs queue to be run 3368874Srgrimes * when the next job finishes. 337138916Sharti * 338138916Sharti * Lst of Job structures describing jobs that were stopped due to 339138916Sharti * concurrency limits or externally 3401590Srgrimes */ 341144494Shartistatic struct JobList stoppedJobs = TAILQ_HEAD_INITIALIZER(stoppedJobs); 3421590Srgrimes 343144656Shartistatic int fifoFd; /* Fd of our job fifo */ 344144656Shartistatic char fifoName[] = "/tmp/make_fifo_XXXXXXXXX"; 345144656Shartistatic int fifoMaster; 3461590Srgrimes 347194217Sdesstatic volatile sig_atomic_t interrupted; 348137605Sharti 349137605Sharti 3501590Srgrimes#if defined(USE_PGRP) && defined(SYSV) 35118730Ssteve# define KILL(pid, sig) killpg(-(pid), (sig)) 3521590Srgrimes#else 3531590Srgrimes# if defined(USE_PGRP) 35418730Ssteve# define KILL(pid, sig) killpg((pid), (sig)) 3551590Srgrimes# else 35618730Ssteve# define KILL(pid, sig) kill((pid), (sig)) 3571590Srgrimes# endif 3581590Srgrimes#endif 3591590Srgrimes 36018730Ssteve/* 36118730Ssteve * Grmpf... There is no way to set bits of the wait structure 36218730Ssteve * anymore with the stupid W*() macros. I liked the union wait 36318730Ssteve * stuff much more. So, we devise our own macros... This is 36418730Ssteve * really ugly, use dramamine sparingly. You have been warned. 36518730Ssteve */ 366103503Sjmallett#define W_SETMASKED(st, val, fun) \ 36718730Ssteve { \ 368138232Sharti int sh = (int)~0; \ 36918730Ssteve int mask = fun(sh); \ 37018730Ssteve \ 37118730Ssteve for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ 37218730Ssteve continue; \ 37318730Ssteve *(st) = (*(st) & ~mask) | ((val) << sh); \ 37418730Ssteve } 37518730Ssteve 376103503Sjmallett#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) 377103503Sjmallett#define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) 37818730Ssteve 37992921Simpstatic void JobRestart(Job *); 38092921Simpstatic int JobStart(GNode *, int, Job *); 38192921Simpstatic void JobDoOutput(Job *, Boolean); 38292921Simpstatic void JobInterrupt(int, int); 38392921Simpstatic void JobRestartJobs(void); 384228157Sfjoestatic int Compat_RunCommand(LstNode *, struct GNode *); 3851590Srgrimes 386146132Shartistatic GNode *curTarg = NULL; 387146132Shartistatic GNode *ENDNode; 388146132Sharti 389146155Sharti/** 390146155Sharti * Create a fifo file with a uniq filename, and returns a file 391146155Sharti * descriptor to that fifo. 392146155Sharti */ 393146155Shartistatic int 394146155Shartimkfifotemp(char *template) 395146155Sharti{ 396146155Sharti char *start; 397146155Sharti char *pathend; 398146155Sharti char *ptr; 399146155Sharti const unsigned char padchar[] = 400146155Sharti "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 401146155Sharti 402146155Sharti if (template[0] == '\0') { 403146155Sharti errno = EINVAL; /* bad input string */ 404146155Sharti return (-1); 405146155Sharti } 406146155Sharti 407146155Sharti /* Find end of template string. */ 408146155Sharti pathend = strchr(template, '\0'); 409146155Sharti ptr = pathend - 1; 410146155Sharti 411146155Sharti /* 412146155Sharti * Starting from the end of the template replace spaces with 'X' in 413146155Sharti * them with random characters until there are no more 'X'. 414146155Sharti */ 415146155Sharti while (ptr >= template && *ptr == 'X') { 416183465Sache uint32_t rand_num = 417183465Sache#if __FreeBSD_version < 800041 418183465Sache arc4random() % (sizeof(padchar) - 1); 419183465Sache#else 420183465Sache arc4random_uniform(sizeof(padchar) - 1); 421183465Sache#endif 422146155Sharti *ptr-- = padchar[rand_num]; 423146155Sharti } 424146155Sharti start = ptr + 1; 425146155Sharti 426146155Sharti /* Check the target directory. */ 427146155Sharti for (; ptr > template; --ptr) { 428146155Sharti if (*ptr == '/') { 429146155Sharti struct stat sbuf; 430146155Sharti 431146155Sharti *ptr = '\0'; 432146155Sharti if (stat(template, &sbuf) != 0) 433146155Sharti return (-1); 434146155Sharti 435146155Sharti if (!S_ISDIR(sbuf.st_mode)) { 436146155Sharti errno = ENOTDIR; 437146155Sharti return (-1); 438146155Sharti } 439146155Sharti *ptr = '/'; 440146155Sharti break; 441146155Sharti } 442146155Sharti } 443146155Sharti 444146155Sharti for (;;) { 445146155Sharti if (mkfifo(template, 0600) == 0) { 446146155Sharti int fd; 447146155Sharti 448146155Sharti if ((fd = open(template, O_RDWR, 0600)) < 0) { 449146155Sharti unlink(template); 450146155Sharti return (-1); 451146155Sharti } else { 452146155Sharti return (fd); 453146155Sharti } 454146155Sharti } else { 455146155Sharti if (errno != EEXIST) { 456146155Sharti return (-1); 457146155Sharti } 458146155Sharti } 459146155Sharti 460146155Sharti /* 461146155Sharti * If we have a collision, cycle through the space of 462146155Sharti * filenames. 463146155Sharti */ 464146155Sharti for (ptr = start;;) { 465146155Sharti char *pad; 466146155Sharti 467146155Sharti if (*ptr == '\0' || ptr == pathend) 468146155Sharti return (-1); 469146155Sharti 470146155Sharti pad = strchr(padchar, *ptr); 471146155Sharti if (pad == NULL || *++pad == '\0') { 472146155Sharti *ptr++ = padchar[0]; 473146155Sharti } else { 474146155Sharti *ptr++ = *pad; 475146155Sharti break; 476146155Sharti } 477146155Sharti } 478146155Sharti } 479146155Sharti /*NOTREACHED*/ 480146155Sharti} 481146155Sharti 482146144Shartistatic void 483146144Sharticatch_child(int sig __unused) 484146144Sharti{ 485146144Sharti} 486146144Sharti 487144467Sharti/** 488146144Sharti */ 489146144Shartivoid 490201225SedProc_Init(void) 491146144Sharti{ 492146144Sharti /* 493146144Sharti * Catch SIGCHLD so that we get kicked out of select() when we 494146144Sharti * need to look at a child. This is only known to matter for the 495146144Sharti * -j case (perhaps without -P). 496146144Sharti * 497146144Sharti * XXX this is intentionally misplaced. 498146144Sharti */ 499146144Sharti struct sigaction sa; 500146144Sharti 501146144Sharti sigemptyset(&sa.sa_mask); 502146144Sharti sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; 503146144Sharti sa.sa_handler = catch_child; 504146144Sharti sigaction(SIGCHLD, &sa, NULL); 505146144Sharti} 506146144Sharti 507146144Sharti/** 508146131Sharti * Wait for child process to terminate. 509146130Sharti */ 510146130Shartistatic int 511146130ShartiProcWait(ProcStuff *ps) 512146130Sharti{ 513146130Sharti pid_t pid; 514146130Sharti int status; 515146130Sharti 516146130Sharti /* 517146130Sharti * Wait for the process to exit. 518146130Sharti */ 519146131Sharti for (;;) { 520146131Sharti pid = wait(&status); 521146131Sharti if (pid == -1 && errno != EINTR) { 522146131Sharti Fatal("error in wait: %d", pid); 523146131Sharti /* NOTREACHED */ 524146131Sharti } 525146131Sharti if (pid == ps->child_pid) { 526146131Sharti break; 527146131Sharti } 528146131Sharti if (interrupted) { 529146131Sharti break; 530146131Sharti } 531146130Sharti } 532146130Sharti 533146130Sharti return (status); 534146130Sharti} 535146130Sharti 536146130Sharti/** 537137605Sharti * JobCatchSignal 538144467Sharti * Got a signal. Set global variables and hope that someone will 539144467Sharti * handle it. 540137605Sharti */ 541137605Shartistatic void 542137605ShartiJobCatchSig(int signo) 543137605Sharti{ 544137605Sharti 545137605Sharti interrupted = signo; 546137605Sharti} 547137605Sharti 548144467Sharti/** 5491590Srgrimes * JobPassSig -- 550137252Sharti * Pass a signal on to all local jobs if 5511590Srgrimes * USE_PGRP is defined, then die ourselves. 5521590Srgrimes * 5531590Srgrimes * Side Effects: 5541590Srgrimes * We die by the same signal. 5551590Srgrimes */ 5561590Srgrimesstatic void 557104696SjmallettJobPassSig(int signo) 5581590Srgrimes{ 559144741Sharti Job *job; 560144467Sharti sigset_t nmask, omask; 561144467Sharti struct sigaction act; 5628874Srgrimes 563144467Sharti sigemptyset(&nmask); 564144467Sharti sigaddset(&nmask, signo); 565144467Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 566137605Sharti 567144467Sharti DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo)); 568144741Sharti TAILQ_FOREACH(job, &jobs, link) { 569144741Sharti DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 570144741Sharti signo, (intmax_t)job->pid)); 571144741Sharti KILL(job->pid, signo); 572144741Sharti } 5731590Srgrimes 574144467Sharti /* 575144467Sharti * Deal with proper cleanup based on the signal received. We only run 576144467Sharti * the .INTERRUPT target if the signal was in fact an interrupt. 577144467Sharti * The other three termination signals are more of a "get out *now*" 578144467Sharti * command. 579144467Sharti */ 580144467Sharti if (signo == SIGINT) { 581144467Sharti JobInterrupt(TRUE, signo); 582144657Sharti } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { 583144467Sharti JobInterrupt(FALSE, signo); 584144467Sharti } 5858874Srgrimes 586144467Sharti /* 587144467Sharti * Leave gracefully if SIGQUIT, rather than core dumping. 588144467Sharti */ 589144467Sharti if (signo == SIGQUIT) { 590144467Sharti signo = SIGINT; 591144467Sharti } 5928874Srgrimes 593144467Sharti /* 594144467Sharti * Send ourselves the signal now we've given the message to everyone 595144467Sharti * else. Note we block everything else possible while we're getting 596144467Sharti * the signal. This ensures that all our jobs get continued when we 597144467Sharti * wake up before we take any other signal. 598144467Sharti * XXX this comment seems wrong. 599144467Sharti */ 600144467Sharti act.sa_handler = SIG_DFL; 601144467Sharti sigemptyset(&act.sa_mask); 602144467Sharti act.sa_flags = 0; 603144467Sharti sigaction(signo, &act, NULL); 6041590Srgrimes 605144467Sharti DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n", 606144467Sharti ~0 & ~(1 << (signo - 1)))); 607144467Sharti signal(signo, SIG_DFL); 6081590Srgrimes 609144467Sharti KILL(getpid(), signo); 61018730Ssteve 611144467Sharti signo = SIGCONT; 612144741Sharti TAILQ_FOREACH(job, &jobs, link) { 613144741Sharti DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 614144741Sharti signo, (intmax_t)job->pid)); 615144741Sharti KILL(job->pid, signo); 616144741Sharti } 6171590Srgrimes 618144467Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 619144467Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 620144467Sharti act.sa_handler = JobPassSig; 621144467Sharti sigaction(signo, &act, NULL); 6221590Srgrimes} 6231590Srgrimes 624144467Sharti/** 6251590Srgrimes * JobPrintCommand -- 6261590Srgrimes * Put out another command for the given job. If the command starts 6271590Srgrimes * with an @ or a - we process it specially. In the former case, 6281590Srgrimes * so long as the -s and -n flags weren't given to make, we stick 6291590Srgrimes * a shell-specific echoOff command in the script. In the latter, 6301590Srgrimes * we ignore errors for the entire job, unless the shell has error 6311590Srgrimes * control. 6321590Srgrimes * If the command is just "..." we take all future commands for this 6331590Srgrimes * job to be commands to be executed once the entire graph has been 6341590Srgrimes * made and return non-zero to signal that the end of the commands 6351590Srgrimes * was reached. These commands are later attached to the postCommands 63694594Sobrien * node and executed by Job_Finish when all things are done. 637142993Sharti * This function is called from JobStart via LST_FOREACH. 6381590Srgrimes * 6391590Srgrimes * Results: 6401590Srgrimes * Always 0, unless the command was "..." 6411590Srgrimes * 6421590Srgrimes * Side Effects: 6431590Srgrimes * If the command begins with a '-' and the shell has no error control, 6441590Srgrimes * the JOB_IGNERR flag is set in the job descriptor. 6451590Srgrimes * If the command is "..." and we're not ignoring such things, 6461590Srgrimes * tailCmds is set to the successor node of the cmd. 6471590Srgrimes * numCommands is incremented if the command is actually printed. 6481590Srgrimes */ 6491590Srgrimesstatic int 650228157SfjoeJobPrintCommand(LstNode *cmdNode, Job *job) 6511590Srgrimes{ 652144467Sharti Boolean noSpecials; /* true if we shouldn't worry about 653141258Sharti * inserting special commands into 654141258Sharti * the input stream. */ 655144467Sharti Boolean shutUp = FALSE; /* true if we put a no echo command 656141258Sharti * into the command file */ 657144467Sharti Boolean errOff = FALSE; /* true if we turned error checking 658141258Sharti * off before printing the command 659141258Sharti * and need to turn it back on */ 660144467Sharti const char *cmdTemplate;/* Template to use when printing the command */ 661228157Sfjoe char *cmd; /* Expanded command */ 6621590Srgrimes 663144467Sharti noSpecials = (noExecute && !(job->node->type & OP_MAKE)); 6641590Srgrimes 665144467Sharti#define DBPRINTF(fmt, arg) \ 666144467Sharti DEBUGF(JOB, (fmt, arg)); \ 667144467Sharti fprintf(job->cmdFILE, fmt, arg); \ 668144467Sharti fflush(job->cmdFILE); 6691590Srgrimes 670144467Sharti /* 671144467Sharti * For debugging, we replace each command with the result of expanding 672144467Sharti * the variables in the command. 673144467Sharti */ 674228157Sfjoe cmd = Buf_Peel(Var_Subst(Lst_Datum(cmdNode), job->node, FALSE)); 675228157Sfjoe if (strcmp(cmd, "...") == 0) { 676228157Sfjoe free(cmd); 677228157Sfjoe job->node->type |= OP_SAVE_CMDS; 678228157Sfjoe if ((job->flags & JOB_IGNDOTS) == 0) { 679228157Sfjoe job->tailCmds = Lst_Succ(cmdNode); 680228157Sfjoe return (1); 681228157Sfjoe } 682228157Sfjoe return (0); 683228157Sfjoe } 684228157Sfjoe Lst_Replace(cmdNode, cmd); 685142457Sharti 686144467Sharti /* 687144467Sharti * Check for leading @', -' or +'s to control echoing, error checking, 688144467Sharti * and execution on -n. 689144467Sharti */ 690144467Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 691144467Sharti switch (*cmd) { 692132839Sharti 693144467Sharti case '@': 694144467Sharti shutUp = DEBUG(LOUD) ? FALSE : TRUE; 695144467Sharti break; 696132839Sharti 697144467Sharti case '-': 698144467Sharti errOff = TRUE; 699144467Sharti break; 700132839Sharti 701144467Sharti case '+': 702144467Sharti if (noSpecials) { 703144467Sharti /* 704144467Sharti * We're not actually exececuting anything... 705144467Sharti * but this one needs to be - use compat mode 706144467Sharti * just for it. 707144467Sharti */ 708228157Sfjoe Compat_RunCommand(cmdNode, job->node); 709144467Sharti return (0); 710144467Sharti } 711144467Sharti break; 712144467Sharti } 713144467Sharti cmd++; 7141590Srgrimes } 7151590Srgrimes 716144467Sharti while (isspace((unsigned char)*cmd)) 717144467Sharti cmd++; 7181590Srgrimes 719228157Sfjoe /* 720228157Sfjoe * Ignore empty commands 721228157Sfjoe */ 722228157Sfjoe if (*cmd == '\0') { 723228157Sfjoe return (0); 724228157Sfjoe } 725228157Sfjoe 726228157Sfjoe cmdTemplate = "%s\n"; 727228157Sfjoe numCommands += 1; 728228157Sfjoe 729144467Sharti if (shutUp) { 730144467Sharti if (!(job->flags & JOB_SILENT) && !noSpecials && 7311590Srgrimes commandShell->hasEchoCtl) { 73218730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 7331590Srgrimes } else { 734144467Sharti shutUp = FALSE; 7351590Srgrimes } 736144467Sharti } 737144467Sharti 738144467Sharti if (errOff) { 739144467Sharti if (!(job->flags & JOB_IGNERR) && !noSpecials) { 740144467Sharti if (commandShell->hasErrCtl) { 741144467Sharti /* 742144467Sharti * We don't want the error-control commands 743144467Sharti * showing up either, so we turn off echoing 744144467Sharti * while executing them. We could put another 745144467Sharti * field in the shell structure to tell 746144467Sharti * JobDoOutput to look for this string too, 747144467Sharti * but why make it any more complex than 748144467Sharti * it already is? 749144467Sharti */ 750144467Sharti if (!(job->flags & JOB_SILENT) && !shutUp && 751144467Sharti commandShell->hasEchoCtl) { 752144467Sharti DBPRINTF("%s\n", commandShell->echoOff); 753144467Sharti DBPRINTF("%s\n", commandShell->ignErr); 754144467Sharti DBPRINTF("%s\n", commandShell->echoOn); 755144467Sharti } else { 756144467Sharti DBPRINTF("%s\n", commandShell->ignErr); 757144467Sharti } 758144467Sharti } else if (commandShell->ignErr && 759144657Sharti *commandShell->ignErr != '\0') { 760144467Sharti /* 761144467Sharti * The shell has no error control, so we need to 762144467Sharti * be weird to get it to ignore any errors from 763144467Sharti * the command. If echoing is turned on, we turn 764144467Sharti * it off and use the errCheck template to echo 765144467Sharti * the command. Leave echoing off so the user 766144467Sharti * doesn't see the weirdness we go through to 767144467Sharti * ignore errors. Set cmdTemplate to use the 768144467Sharti * weirdness instead of the simple "%s\n" 769144467Sharti * template. 770144467Sharti */ 771144467Sharti if (!(job->flags & JOB_SILENT) && !shutUp && 772144467Sharti commandShell->hasEchoCtl) { 773144467Sharti DBPRINTF("%s\n", commandShell->echoOff); 774144467Sharti DBPRINTF(commandShell->errCheck, cmd); 775144467Sharti shutUp = TRUE; 776144467Sharti } 777144467Sharti cmdTemplate = commandShell->ignErr; 778144467Sharti /* 779144467Sharti * The error ignoration (hee hee) is already 780144467Sharti * taken care of by the ignErr template, so 781144467Sharti * pretend error checking is still on. 782144467Sharti */ 783144467Sharti errOff = FALSE; 784144467Sharti } else { 785144467Sharti errOff = FALSE; 786144467Sharti } 787144467Sharti } else { 788144467Sharti errOff = FALSE; 789144467Sharti } 790144467Sharti } 791144467Sharti 792144467Sharti DBPRINTF(cmdTemplate, cmd); 793144467Sharti 794144467Sharti if (errOff) { 7951590Srgrimes /* 796144467Sharti * If echoing is already off, there's no point in issuing the 797144467Sharti * echoOff command. Otherwise we issue it and pretend it was on 798144467Sharti * for the whole command... 7991590Srgrimes */ 800144467Sharti if (!shutUp && !(job->flags & JOB_SILENT) && 8011590Srgrimes commandShell->hasEchoCtl) { 80218730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 8031590Srgrimes shutUp = TRUE; 8041590Srgrimes } 805144467Sharti DBPRINTF("%s\n", commandShell->errCheck); 8061590Srgrimes } 807144467Sharti if (shutUp) { 808144467Sharti DBPRINTF("%s\n", commandShell->echoOn); 8091590Srgrimes } 810144467Sharti return (0); 8111590Srgrimes} 8121590Srgrimes 813144467Sharti/** 81418730Ssteve * JobClose -- 81518730Ssteve * Called to close both input and output pipes when a job is finished. 81618730Ssteve * 81718730Ssteve * Side Effects: 81818730Ssteve * The file descriptors associated with the job are closed. 81918730Ssteve */ 82018730Sstevestatic void 821104696SjmallettJobClose(Job *job) 82218730Ssteve{ 823138232Sharti 824144467Sharti if (usePipes) { 825137202Sharti#if !defined(USE_KQUEUE) 826144467Sharti FD_CLR(job->inPipe, &outputs); 82718730Ssteve#endif 828144467Sharti if (job->outPipe != job->inPipe) { 829144467Sharti close(job->outPipe); 830144467Sharti } 831144467Sharti JobDoOutput(job, TRUE); 832144467Sharti close(job->inPipe); 833144467Sharti } else { 834144467Sharti close(job->outFd); 835144467Sharti JobDoOutput(job, TRUE); 83618730Ssteve } 83718730Ssteve} 83818730Ssteve 839144467Sharti/** 8401590Srgrimes * JobFinish -- 8411590Srgrimes * Do final processing for the given job including updating 8421590Srgrimes * parents and starting new jobs as available/necessary. Note 8431590Srgrimes * that we pay no attention to the JOB_IGNERR flag here. 8441590Srgrimes * This is because when we're called because of a noexecute flag 8451590Srgrimes * or something, jstat.w_status is 0 and when called from 8461590Srgrimes * Job_CatchChildren, the status is zeroed if it s/b ignored. 8471590Srgrimes * 8481590Srgrimes * Side Effects: 8491590Srgrimes * Some nodes may be put on the toBeMade queue. 8501590Srgrimes * Final commands for the job are placed on postCommands. 8511590Srgrimes * 8521590Srgrimes * If we got an error and are aborting (aborting == ABORT_ERROR) and 8531590Srgrimes * the job list is now empty, we are done for the day. 854186279Sfjoe * If we recognized an error (makeErrors !=0), we set the aborting flag 8551590Srgrimes * to ABORT_ERROR so no more jobs will be started. 8561590Srgrimes */ 8571590Srgrimesstatic void 858104696SjmallettJobFinish(Job *job, int *status) 8591590Srgrimes{ 860144467Sharti Boolean done; 861144467Sharti LstNode *ln; 8621590Srgrimes 863146133Sharti if (WIFEXITED(*status)) { 864146133Sharti int job_status = WEXITSTATUS(*status); 865146133Sharti 866144467Sharti JobClose(job); 867144467Sharti /* 868146133Sharti * Deal with ignored errors in -B mode. We need to 869146133Sharti * print a message telling of the ignored error as 870146133Sharti * well as setting status.w_status to 0 so the next 871146133Sharti * command gets run. To do this, we set done to be 872146133Sharti * TRUE if in -B mode and the job exited non-zero. 873144467Sharti */ 874146133Sharti if (job_status == 0) { 875146133Sharti done = FALSE; 876146133Sharti } else { 877146133Sharti if (job->flags & JOB_IGNERR) { 878146133Sharti done = TRUE; 879146133Sharti } else { 880146133Sharti /* 881146133Sharti * If it exited non-zero and either we're 882146133Sharti * doing things our way or we're not ignoring 883146133Sharti * errors, the job is finished. Similarly, if 884146133Sharti * the shell died because of a signal the job 885146133Sharti * is also finished. In these cases, finish 886146133Sharti * out the job's output before printing the 887146133Sharti * exit status... 888146133Sharti */ 889146133Sharti done = TRUE; 890146133Sharti if (job->cmdFILE != NULL && 891146133Sharti job->cmdFILE != stdout) { 892146133Sharti fclose(job->cmdFILE); 893146133Sharti } 8948874Srgrimes 895146133Sharti } 896146133Sharti } 897146133Sharti } else if (WIFSIGNALED(*status)) { 898146133Sharti if (WTERMSIG(*status) == SIGCONT) { 899146133Sharti /* 900146133Sharti * No need to close things down or anything. 901146133Sharti */ 902146133Sharti done = FALSE; 903146133Sharti } else { 904146133Sharti /* 905146133Sharti * If it exited non-zero and either we're 906146133Sharti * doing things our way or we're not ignoring 907146133Sharti * errors, the job is finished. Similarly, if 908146133Sharti * the shell died because of a signal the job 909146133Sharti * is also finished. In these cases, finish 910146133Sharti * out the job's output before printing the 911146133Sharti * exit status... 912146133Sharti */ 913146133Sharti JobClose(job); 914146133Sharti if (job->cmdFILE != NULL && 915146133Sharti job->cmdFILE != stdout) { 916146133Sharti fclose(job->cmdFILE); 917146133Sharti } 918146133Sharti done = TRUE; 919146133Sharti } 9201590Srgrimes } else { 921144467Sharti /* 922144467Sharti * No need to close things down or anything. 923144467Sharti */ 924144467Sharti done = FALSE; 9251590Srgrimes } 9261590Srgrimes 927146133Sharti if (WIFEXITED(*status)) { 928146133Sharti if (done || DEBUG(JOB)) { 929146133Sharti FILE *out; 930144467Sharti 931146133Sharti if (compatMake && 932146133Sharti !usePipes && 933146133Sharti (job->flags & JOB_IGNERR)) { 934146133Sharti /* 935146133Sharti * If output is going to a file and this job 936146133Sharti * is ignoring errors, arrange to have the 937146133Sharti * exit status sent to the output file as 938146133Sharti * well. 939146133Sharti */ 940146133Sharti out = fdopen(job->outFd, "w"); 941146133Sharti if (out == NULL) 942146133Sharti Punt("Cannot fdopen"); 943146133Sharti } else { 944146133Sharti out = stdout; 945146133Sharti } 9461590Srgrimes 947144665Sharti DEBUGF(JOB, ("Process %jd exited.\n", 948144665Sharti (intmax_t)job->pid)); 949146133Sharti 950146133Sharti if (WEXITSTATUS(*status) == 0) { 951146133Sharti if (DEBUG(JOB)) { 952146133Sharti if (usePipes && job->node != lastNode) { 953146133Sharti MESSAGE(out, job->node); 954146133Sharti lastNode = job->node; 955146133Sharti } 956146133Sharti fprintf(out, 957231544Sfjoe "*** [%s] Completed successfully\n", 958231544Sfjoe job->node->name); 959146133Sharti } 960146133Sharti } else { 961144467Sharti if (usePipes && job->node != lastNode) { 962144467Sharti MESSAGE(out, job->node); 963144467Sharti lastNode = job->node; 964144467Sharti } 965231544Sfjoe fprintf(out, "*** [%s] Error code %d%s\n", 966231544Sfjoe job->node->name, 967146133Sharti WEXITSTATUS(*status), 968146133Sharti (job->flags & JOB_IGNERR) ? 969231544Sfjoe " (ignored)" : ""); 970144467Sharti 971144467Sharti if (job->flags & JOB_IGNERR) { 972144467Sharti *status = 0; 973144467Sharti } 974144467Sharti } 975144467Sharti 976144467Sharti fflush(out); 977146133Sharti } 978146133Sharti } else if (WIFSIGNALED(*status)) { 979146133Sharti if (done || DEBUG(JOB) || (WTERMSIG(*status) == SIGCONT)) { 980146133Sharti FILE *out; 981144467Sharti 982146133Sharti if (compatMake && 983146133Sharti !usePipes && 984146133Sharti (job->flags & JOB_IGNERR)) { 985146133Sharti /* 986146133Sharti * If output is going to a file and this job 987146133Sharti * is ignoring errors, arrange to have the 988146133Sharti * exit status sent to the output file as 989146133Sharti * well. 990146133Sharti */ 991146133Sharti out = fdopen(job->outFd, "w"); 992146133Sharti if (out == NULL) 993146133Sharti Punt("Cannot fdopen"); 994146133Sharti } else { 995146133Sharti out = stdout; 996146133Sharti } 997146133Sharti 998146133Sharti if (WTERMSIG(*status) == SIGCONT) { 999146133Sharti /* 1000146133Sharti * If the beastie has continued, shift the 1001146133Sharti * Job from the stopped list to the running 1002146133Sharti * one (or re-stop it if concurrency is 1003146133Sharti * exceeded) and go and get another child. 1004146133Sharti */ 1005146133Sharti if (job->flags & (JOB_RESUME | JOB_RESTART)) { 1006146133Sharti if (usePipes && job->node != lastNode) { 1007146133Sharti MESSAGE(out, job->node); 1008146133Sharti lastNode = job->node; 1009146133Sharti } 1010231544Sfjoe fprintf(out, "*** [%s] Continued\n", 1011231544Sfjoe job->node->name); 1012146133Sharti } 1013146133Sharti if (!(job->flags & JOB_CONTINUING)) { 1014146133Sharti DEBUGF(JOB, ("Warning: process %jd was not " 1015146133Sharti "continuing.\n", (intmax_t) job->pid)); 1016146133Sharti } 1017146133Sharti job->flags &= ~JOB_CONTINUING; 1018146133Sharti TAILQ_INSERT_TAIL(&jobs, job, link); 1019146133Sharti nJobs += 1; 1020146133Sharti DEBUGF(JOB, ("Process %jd is continuing locally.\n", 1021146133Sharti (intmax_t) job->pid)); 1022146133Sharti if (nJobs == maxJobs) { 1023146133Sharti jobFull = TRUE; 1024146133Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1025146133Sharti } 1026146133Sharti fflush(out); 1027146133Sharti return; 1028146133Sharti 1029146133Sharti } else { 1030144467Sharti if (usePipes && job->node != lastNode) { 1031144467Sharti MESSAGE(out, job->node); 1032144467Sharti lastNode = job->node; 1033144467Sharti } 1034146133Sharti fprintf(out, 1035231544Sfjoe "*** [%s] Signal %d\n", job->node->name, 1036231544Sfjoe WTERMSIG(*status)); 1037146133Sharti fflush(out); 1038144467Sharti } 1039146133Sharti } 1040146133Sharti } else { 1041146133Sharti /* STOPPED */ 1042146133Sharti FILE *out; 10431590Srgrimes 1044146133Sharti if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 1045146133Sharti /* 1046146133Sharti * If output is going to a file and this job 1047146133Sharti * is ignoring errors, arrange to have the 1048146133Sharti * exit status sent to the output file as 1049146133Sharti * well. 1050146133Sharti */ 1051146133Sharti out = fdopen(job->outFd, "w"); 1052146133Sharti if (out == NULL) 1053146133Sharti Punt("Cannot fdopen"); 1054144467Sharti } else { 1055146133Sharti out = stdout; 1056144467Sharti } 10571590Srgrimes 1058146133Sharti DEBUGF(JOB, ("Process %jd stopped.\n", (intmax_t) job->pid)); 1059146133Sharti if (usePipes && job->node != lastNode) { 1060146133Sharti MESSAGE(out, job->node); 1061146133Sharti lastNode = job->node; 1062146133Sharti } 1063231544Sfjoe fprintf(out, "*** [%s] Stopped -- signal %d\n", 1064231544Sfjoe job->node->name, WSTOPSIG(*status)); 1065146133Sharti job->flags |= JOB_RESUME; 1066146133Sharti TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 1067144467Sharti fflush(out); 1068146133Sharti return; 10691590Srgrimes } 10701590Srgrimes 10711590Srgrimes /* 1072144467Sharti * Now handle the -B-mode stuff. If the beast still isn't finished, 1073144467Sharti * try and restart the job on the next command. If JobStart says it's 1074144467Sharti * ok, it's ok. If there's an error, this puppy is done. 10751590Srgrimes */ 1076144467Sharti if (compatMake && WIFEXITED(*status) && 1077144467Sharti Lst_Succ(job->node->compat_command) != NULL) { 1078144467Sharti switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { 1079144467Sharti case JOB_RUNNING: 1080144467Sharti done = FALSE; 1081144467Sharti break; 1082144467Sharti case JOB_ERROR: 1083144467Sharti done = TRUE; 1084144467Sharti W_SETEXITSTATUS(status, 1); 1085144467Sharti break; 1086144467Sharti case JOB_FINISHED: 1087144467Sharti /* 1088144467Sharti * If we got back a JOB_FINISHED code, JobStart has 1089144467Sharti * already called Make_Update and freed the job 1090144467Sharti * descriptor. We set done to false here to avoid fake 1091144467Sharti * cycles and double frees. JobStart needs to do the 1092144467Sharti * update so we can proceed up the graph when given 1093144467Sharti * the -n flag.. 1094144467Sharti */ 1095144467Sharti done = FALSE; 1096144467Sharti break; 1097144467Sharti default: 1098144467Sharti break; 1099144467Sharti } 1100144467Sharti } else { 1101144467Sharti done = TRUE; 11021590Srgrimes } 1103143703Sharti 1104144657Sharti if (done && aborting != ABORT_ERROR && 1105144657Sharti aborting != ABORT_INTERRUPT && *status == 0) { 1106144467Sharti /* 1107144467Sharti * As long as we aren't aborting and the job didn't return a 1108144467Sharti * non-zero status that we shouldn't ignore, we call 1109144467Sharti * Make_Update to update the parents. In addition, any saved 1110144467Sharti * commands for the node are placed on the .END target. 1111144467Sharti */ 1112144467Sharti for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { 1113144467Sharti Lst_AtEnd(&postCommands->commands, 1114146027Sharti Buf_Peel( 1115146027Sharti Var_Subst(Lst_Datum(ln), job->node, FALSE))); 1116144467Sharti } 11171590Srgrimes 1118144467Sharti job->node->made = MADE; 1119144467Sharti Make_Update(job->node); 1120144467Sharti free(job); 11211590Srgrimes 1122144467Sharti } else if (*status != 0) { 1123186279Sfjoe makeErrors++; 1124144467Sharti free(job); 1125144467Sharti } 1126144467Sharti 1127144467Sharti JobRestartJobs(); 1128144467Sharti 11291590Srgrimes /* 1130144467Sharti * Set aborting if any error. 11311590Srgrimes */ 1132186279Sfjoe if (makeErrors && !keepgoing && aborting != ABORT_INTERRUPT) { 1133144467Sharti /* 1134144467Sharti * If we found any errors in this batch of children and the -k 1135144467Sharti * flag wasn't given, we set the aborting flag so no more jobs 1136144467Sharti * get started. 1137144467Sharti */ 1138144467Sharti aborting = ABORT_ERROR; 1139144467Sharti } 11408874Srgrimes 1141144657Sharti if (aborting == ABORT_ERROR && Job_Empty()) { 1142144467Sharti /* 1143144467Sharti * If we are aborting and the job table is now empty, we finish. 1144144467Sharti */ 1145186279Sfjoe Finish(makeErrors); 1146144467Sharti } 11471590Srgrimes} 11481590Srgrimes 1149144467Sharti/** 1150144467Sharti * Job_Touch 11511590Srgrimes * Touch the given target. Called by JobStart when the -t flag was 1152104696Sjmallett * given. Prints messages unless told to be silent. 11531590Srgrimes * 11541590Srgrimes * Side Effects: 11551590Srgrimes * The data modification of the file is changed. In addition, if the 11561590Srgrimes * file did not exist, it is created. 11571590Srgrimes */ 11581590Srgrimesvoid 1159104696SjmallettJob_Touch(GNode *gn, Boolean silent) 11601590Srgrimes{ 1161144467Sharti int streamID; /* ID of stream opened to do the touch */ 1162144467Sharti struct utimbuf times; /* Times for utime() call */ 11631590Srgrimes 1164144467Sharti if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) { 1165144467Sharti /* 1166144467Sharti * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" 1167144467Sharti * targets and, as such, shouldn't really be created. 1168144467Sharti */ 1169144467Sharti return; 1170144467Sharti } 11718874Srgrimes 1172144467Sharti if (!silent) { 1173144467Sharti fprintf(stdout, "touch %s\n", gn->name); 1174144467Sharti fflush(stdout); 1175144467Sharti } 11761590Srgrimes 1177144467Sharti if (noExecute) { 1178144467Sharti return; 1179144467Sharti } 11801590Srgrimes 1181144467Sharti if (gn->type & OP_ARCHV) { 1182144467Sharti Arch_Touch(gn); 1183144467Sharti } else if (gn->type & OP_LIB) { 1184144467Sharti Arch_TouchLib(gn); 1185144467Sharti } else { 1186144467Sharti char *file = gn->path ? gn->path : gn->name; 11871590Srgrimes 1188144467Sharti times.actime = times.modtime = now; 1189144467Sharti if (utime(file, ×) < 0) { 1190144467Sharti streamID = open(file, O_RDWR | O_CREAT, 0666); 11911590Srgrimes 1192144467Sharti if (streamID >= 0) { 1193144467Sharti char c; 11941590Srgrimes 1195144467Sharti /* 1196144467Sharti * Read and write a byte to the file to change 1197144467Sharti * the modification time, then close the file. 1198144467Sharti */ 1199144467Sharti if (read(streamID, &c, 1) == 1) { 1200144467Sharti lseek(streamID, (off_t)0, SEEK_SET); 1201144467Sharti write(streamID, &c, 1); 1202144467Sharti } 1203144467Sharti 1204144467Sharti close(streamID); 1205144467Sharti } else { 1206144467Sharti fprintf(stdout, "*** couldn't touch %s: %s", 1207144467Sharti file, strerror(errno)); 1208144467Sharti fflush(stdout); 1209144467Sharti } 12101590Srgrimes } 12111590Srgrimes } 12121590Srgrimes} 12131590Srgrimes 1214144467Sharti/** 1215144467Sharti * Job_CheckCommands 12168874Srgrimes * Make sure the given node has all the commands it needs. 12171590Srgrimes * 12181590Srgrimes * Results: 12191590Srgrimes * TRUE if the commands list is/was ok. 12201590Srgrimes * 12211590Srgrimes * Side Effects: 12221590Srgrimes * The node will have commands from the .DEFAULT rule added to it 12231590Srgrimes * if it needs them. 12241590Srgrimes */ 12251590SrgrimesBoolean 1226104696SjmallettJob_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 12271590Srgrimes{ 1228138232Sharti 1229144467Sharti if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && 1230144467Sharti (gn->type & OP_LIB) == 0) { 1231144467Sharti /* 1232144467Sharti * No commands. Look for .DEFAULT rule from which we might infer 1233144467Sharti * commands. 1234144467Sharti */ 1235144657Sharti if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { 1236144467Sharti /* 1237144467Sharti * Make only looks for a .DEFAULT if the node was 1238144467Sharti * never the target of an operator, so that's what we 1239144467Sharti * do too. If a .DEFAULT was given, we substitute its 1240144467Sharti * commands for gn's commands and set the IMPSRC 1241144467Sharti * variable to be the target's name The DEFAULT node 1242144467Sharti * acts like a transformation rule, in that gn also 1243144467Sharti * inherits any attributes or sources attached to 1244144467Sharti * .DEFAULT itself. 1245144467Sharti */ 1246144467Sharti Make_HandleUse(DEFAULT, gn); 1247146580Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn), gn); 124818730Ssteve 1249144467Sharti } else if (Dir_MTime(gn) == 0) { 1250144467Sharti /* 1251144467Sharti * The node wasn't the target of an operator we have 1252144467Sharti * no .DEFAULT rule to go on and the target doesn't 1253144467Sharti * already exist. There's nothing more we can do for 1254144467Sharti * this branch. If the -k flag wasn't given, we stop 1255144467Sharti * in our tracks, otherwise we just don't update 1256144467Sharti * this node's parents so they never get examined. 1257144467Sharti */ 1258144467Sharti static const char msg[] = 1259144467Sharti "make: don't know how to make"; 1260144467Sharti 1261144467Sharti if (gn->type & OP_OPTIONAL) { 1262144467Sharti fprintf(stdout, "%s %s(ignored)\n", 1263144467Sharti msg, gn->name); 1264144467Sharti fflush(stdout); 1265144467Sharti } else if (keepgoing) { 1266144467Sharti fprintf(stdout, "%s %s(continuing)\n", 1267144467Sharti msg, gn->name); 1268144467Sharti fflush(stdout); 1269144467Sharti return (FALSE); 1270144467Sharti } else { 1271176808Sobrien#ifndef WITHOUT_OLD_JOKE 1272144467Sharti if (strcmp(gn->name,"love") == 0) 1273144467Sharti (*abortProc)("Not war."); 1274144467Sharti else 1275176808Sobrien#endif 1276144467Sharti (*abortProc)("%s %s. Stop", 1277144467Sharti msg, gn->name); 1278144467Sharti return (FALSE); 1279144467Sharti } 1280144467Sharti } 12811590Srgrimes } 1282144467Sharti return (TRUE); 12831590Srgrimes} 12841590Srgrimes 1285144467Sharti/** 1286144467Sharti * JobExec 12871590Srgrimes * Execute the shell for the given job. Called from JobStart and 12881590Srgrimes * JobRestart. 12891590Srgrimes * 12901590Srgrimes * Side Effects: 12911590Srgrimes * A shell is executed, outputs is altered and the Job structure added 12921590Srgrimes * to the job table. 12931590Srgrimes */ 12941590Srgrimesstatic void 1295104696SjmallettJobExec(Job *job, char **argv) 12961590Srgrimes{ 1297146129Sharti ProcStuff ps; 12988874Srgrimes 1299144467Sharti if (DEBUG(JOB)) { 1300146061Sharti int i; 13018874Srgrimes 1302144467Sharti DEBUGF(JOB, ("Running %s\n", job->node->name)); 1303144467Sharti DEBUGF(JOB, ("\tCommand: ")); 1304144467Sharti for (i = 0; argv[i] != NULL; i++) { 1305144467Sharti DEBUGF(JOB, ("%s ", argv[i])); 1306144467Sharti } 1307144467Sharti DEBUGF(JOB, ("\n")); 13081590Srgrimes } 13098874Srgrimes 13101590Srgrimes /* 1311144467Sharti * Some jobs produce no output and it's disconcerting to have 1312144467Sharti * no feedback of their running (since they produce no output, the 1313144467Sharti * banner with their name in it never appears). This is an attempt to 1314144467Sharti * provide that feedback, even if nothing follows it. 13151590Srgrimes */ 1316144657Sharti if (lastNode != job->node && (job->flags & JOB_FIRST) && 1317144467Sharti !(job->flags & JOB_SILENT)) { 1318144467Sharti MESSAGE(stdout, job->node); 1319144467Sharti lastNode = job->node; 13201590Srgrimes } 13211590Srgrimes 1322146129Sharti ps.in = FILENO(job->cmdFILE); 1323146129Sharti if (usePipes) { 1324146129Sharti /* 1325146129Sharti * Set up the child's output to be routed through the 1326146129Sharti * pipe we've created for it. 1327146129Sharti */ 1328146129Sharti ps.out = job->outPipe; 1329146129Sharti } else { 1330146129Sharti /* 1331146129Sharti * We're capturing output in a file, so we duplicate 1332146129Sharti * the descriptor to the temporary file into the 1333146129Sharti * standard output. 1334146129Sharti */ 1335146129Sharti ps.out = job->outFd; 1336146129Sharti } 1337146129Sharti ps.err = STDERR_FILENO; 1338146129Sharti 1339146129Sharti ps.merge_errors = 1; 1340146129Sharti ps.pgroup = 1; 1341146129Sharti ps.searchpath = 0; 1342146129Sharti 1343146129Sharti ps.argv = argv; 1344146156Sharti ps.argv_free = 0; 1345146129Sharti 1346146129Sharti /* 1347146129Sharti * Fork. Warning since we are doing vfork() instead of fork(), 1348146129Sharti * do not allocate memory in the child process! 1349146129Sharti */ 1350146130Sharti if ((ps.child_pid = vfork()) == -1) { 1351144467Sharti Punt("Cannot fork"); 1352144467Sharti 1353146130Sharti 1354146130Sharti } else if (ps.child_pid == 0) { 1355144665Sharti /* 1356144665Sharti * Child 1357144665Sharti */ 1358144467Sharti if (fifoFd >= 0) 1359144467Sharti close(fifoFd); 1360144467Sharti 1361146574Sharti Proc_Exec(&ps); 1362146129Sharti /* NOTREACHED */ 1363144665Sharti } 1364146130Sharti 1365144665Sharti /* 1366144665Sharti * Parent 1367144665Sharti */ 1368146130Sharti job->pid = ps.child_pid; 1369144467Sharti 1370144665Sharti if (usePipes && (job->flags & JOB_FIRST)) { 1371144665Sharti /* 1372144665Sharti * The first time a job is run for a node, we set the 1373144665Sharti * current position in the buffer to the beginning and 1374144665Sharti * mark another stream to watch in the outputs mask. 1375144665Sharti */ 1376104475Sphk#ifdef USE_KQUEUE 1377144665Sharti struct kevent kev[2]; 1378104475Sphk#endif 1379144665Sharti job->curPos = 0; 13808874Srgrimes 1381137202Sharti#if defined(USE_KQUEUE) 1382144665Sharti EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job); 1383144665Sharti EV_SET(&kev[1], job->pid, EVFILT_PROC, 1384144665Sharti EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL); 1385144665Sharti if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) { 1386144665Sharti /* 1387144665Sharti * kevent() will fail if the job is already 1388144665Sharti * finished 1389144665Sharti */ 1390144665Sharti if (errno != EINTR && errno != EBADF && errno != ESRCH) 1391144665Sharti Punt("kevent: %s", strerror(errno)); 1392144665Sharti } 13931590Srgrimes#else 1394144665Sharti FD_SET(job->inPipe, &outputs); 1395137202Sharti#endif /* USE_KQUEUE */ 1396144665Sharti } 1397144467Sharti 1398144665Sharti if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1399144665Sharti fclose(job->cmdFILE); 1400144665Sharti job->cmdFILE = NULL; 14011590Srgrimes } 14021590Srgrimes 1403144467Sharti /* 1404144467Sharti * Now the job is actually running, add it to the table. 1405144467Sharti */ 1406144467Sharti nJobs += 1; 1407144494Sharti TAILQ_INSERT_TAIL(&jobs, job, link); 1408144467Sharti if (nJobs == maxJobs) { 1409144467Sharti jobFull = TRUE; 14101590Srgrimes } 14111590Srgrimes} 14121590Srgrimes 1413144467Sharti/** 1414144467Sharti * JobMakeArgv 14151590Srgrimes * Create the argv needed to execute the shell for a given job. 14161590Srgrimes */ 14171590Srgrimesstatic void 1418104696SjmallettJobMakeArgv(Job *job, char **argv) 14191590Srgrimes{ 1420144467Sharti int argc; 1421144467Sharti static char args[10]; /* For merged arguments */ 14228874Srgrimes 1423146557Sharti argv[0] = commandShell->name; 1424144467Sharti argc = 1; 14251590Srgrimes 1426144657Sharti if ((commandShell->exit && *commandShell->exit != '-') || 1427144657Sharti (commandShell->echo && *commandShell->echo != '-')) { 1428144467Sharti /* 1429144467Sharti * At least one of the flags doesn't have a minus before it, so 1430144467Sharti * merge them together. Have to do this because the *(&(@*#*&#$# 1431144467Sharti * Bourne shell thinks its second argument is a file to source. 1432144467Sharti * Grrrr. Note the ten-character limitation on the combined 1433144467Sharti * arguments. 1434144467Sharti */ 1435144657Sharti sprintf(args, "-%s%s", (job->flags & JOB_IGNERR) ? "" : 1436144657Sharti commandShell->exit ? commandShell->exit : "", 1437144657Sharti (job->flags & JOB_SILENT) ? "" : 1438144657Sharti commandShell->echo ? commandShell->echo : ""); 14391590Srgrimes 1440144467Sharti if (args[1]) { 1441144467Sharti argv[argc] = args; 1442144467Sharti argc++; 1443144467Sharti } 1444144467Sharti } else { 1445144467Sharti if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1446144467Sharti argv[argc] = commandShell->exit; 1447144467Sharti argc++; 1448144467Sharti } 1449144467Sharti if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1450144467Sharti argv[argc] = commandShell->echo; 1451144467Sharti argc++; 1452144467Sharti } 14531590Srgrimes } 1454144467Sharti argv[argc] = NULL; 14551590Srgrimes} 14561590Srgrimes 1457144467Sharti/** 1458144467Sharti * JobRestart 1459144494Sharti * Restart a job that stopped for some reason. The job must be neither 1460144494Sharti * on the jobs nor on the stoppedJobs list. 14611590Srgrimes * 14621590Srgrimes * Side Effects: 14631590Srgrimes * jobFull will be set if the job couldn't be run. 14641590Srgrimes */ 14651590Srgrimesstatic void 1466104696SjmallettJobRestart(Job *job) 14671590Srgrimes{ 146818730Ssteve 1469144467Sharti if (job->flags & JOB_RESTART) { 1470144467Sharti /* 1471144467Sharti * Set up the control arguments to the shell. This is based on 1472144467Sharti * the flags set earlier for this job. If the JOB_IGNERR flag 1473144467Sharti * is clear, the 'exit' flag of the commandShell is used to 1474144467Sharti * cause it to exit upon receiving an error. If the JOB_SILENT 1475144467Sharti * flag is clear, the 'echo' flag of the commandShell is used 1476144467Sharti * to get it to start echoing as soon as it starts 1477144467Sharti * processing commands. 1478144467Sharti */ 1479144467Sharti char *argv[4]; 14808874Srgrimes 1481144467Sharti JobMakeArgv(job, argv); 14828874Srgrimes 1483144467Sharti DEBUGF(JOB, ("Restarting %s...", job->node->name)); 1484144657Sharti if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) { 1485144467Sharti /* 1486144657Sharti * Not allowed to run -- put it back on the hold 1487144657Sharti * queue and mark the table full 1488144467Sharti */ 1489144467Sharti DEBUGF(JOB, ("holding\n")); 1490144494Sharti TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1491144467Sharti jobFull = TRUE; 1492144467Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1493144467Sharti return; 1494144467Sharti } else { 1495144467Sharti /* 1496144467Sharti * Job may be run locally. 1497144467Sharti */ 1498144467Sharti DEBUGF(JOB, ("running locally\n")); 1499144467Sharti } 1500144467Sharti JobExec(job, argv); 1501144467Sharti 1502137202Sharti } else { 15031590Srgrimes /* 1504144467Sharti * The job has stopped and needs to be restarted. 1505144467Sharti * Why it stopped, we don't know... 15061590Srgrimes */ 1507144467Sharti DEBUGF(JOB, ("Resuming %s...", job->node->name)); 1508144657Sharti if ((nJobs < maxJobs || ((job->flags & JOB_SPECIAL) && 1509144657Sharti maxJobs == 0)) && nJobs != maxJobs) { 1510144467Sharti /* 1511144467Sharti * If we haven't reached the concurrency limit already 1512144467Sharti * (or the job must be run and maxJobs is 0), it's ok 1513144467Sharti * to resume it. 1514144467Sharti */ 1515144467Sharti Boolean error; 1516144467Sharti int status; 15178874Srgrimes 1518144467Sharti error = (KILL(job->pid, SIGCONT) != 0); 1519144467Sharti 1520144467Sharti if (!error) { 1521144467Sharti /* 1522144467Sharti * Make sure the user knows we've continued 1523144467Sharti * the beast and actually put the thing in the 1524144467Sharti * job table. 1525144467Sharti */ 1526144467Sharti job->flags |= JOB_CONTINUING; 1527144467Sharti status = 0; 1528144467Sharti W_SETTERMSIG(&status, SIGCONT); 1529144467Sharti JobFinish(job, &status); 1530144467Sharti 1531144467Sharti job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 1532144467Sharti DEBUGF(JOB, ("done\n")); 1533144467Sharti } else { 1534144467Sharti Error("couldn't resume %s: %s", 1535144467Sharti job->node->name, strerror(errno)); 1536144467Sharti status = 0; 1537144467Sharti W_SETEXITSTATUS(&status, 1); 1538144467Sharti JobFinish(job, &status); 1539144467Sharti } 1540144467Sharti } else { 1541144467Sharti /* 1542144467Sharti * Job cannot be restarted. Mark the table as full and 1543144467Sharti * place the job back on the list of stopped jobs. 1544144467Sharti */ 1545144467Sharti DEBUGF(JOB, ("table full\n")); 1546144494Sharti TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1547144467Sharti jobFull = TRUE; 1548144467Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1549144467Sharti } 15501590Srgrimes } 15511590Srgrimes} 15521590Srgrimes 1553144467Sharti/** 1554144467Sharti * JobStart 15551590Srgrimes * Start a target-creation process going for the target described 15568874Srgrimes * by the graph node gn. 15571590Srgrimes * 15581590Srgrimes * Results: 15591590Srgrimes * JOB_ERROR if there was an error in the commands, JOB_FINISHED 15601590Srgrimes * if there isn't actually anything left to do for the job and 15611590Srgrimes * JOB_RUNNING if the job has been started. 15621590Srgrimes * 15631590Srgrimes * Side Effects: 15641590Srgrimes * A new Job node is created and added to the list of running 15651590Srgrimes * jobs. PMake is forked and a child shell created. 15661590Srgrimes */ 15671590Srgrimesstatic int 1568104696SjmallettJobStart(GNode *gn, int flags, Job *previous) 15691590Srgrimes{ 1570144467Sharti Job *job; /* new job descriptor */ 1571144467Sharti char *argv[4]; /* Argument vector to shell */ 1572144467Sharti Boolean cmdsOK; /* true if the nodes commands were all right */ 1573144467Sharti Boolean noExec; /* Set true if we decide not to run the job */ 1574144467Sharti int tfd; /* File descriptor for temp file */ 1575144467Sharti LstNode *ln; 1576202045Sharti char tfile[PATH_MAX]; 1577202045Sharti const char *tdir; 15781590Srgrimes 1579144467Sharti if (interrupted) { 1580144467Sharti JobPassSig(interrupted); 1581144467Sharti return (JOB_ERROR); 1582144467Sharti } 1583144467Sharti if (previous != NULL) { 1584144467Sharti previous->flags &= ~(JOB_FIRST | JOB_IGNERR | JOB_SILENT); 1585144467Sharti job = previous; 1586144467Sharti } else { 1587144467Sharti job = emalloc(sizeof(Job)); 1588144467Sharti flags |= JOB_FIRST; 1589144467Sharti } 15901590Srgrimes 1591144467Sharti job->node = gn; 1592144467Sharti job->tailCmds = NULL; 15931590Srgrimes 15941590Srgrimes /* 1595144467Sharti * Set the initial value of the flags for this job based on the global 1596144467Sharti * ones and the node's attributes... Any flags supplied by the caller 1597144467Sharti * are also added to the field. 15981590Srgrimes */ 1599144467Sharti job->flags = 0; 1600144467Sharti if (Targ_Ignore(gn)) { 1601144467Sharti job->flags |= JOB_IGNERR; 16021590Srgrimes } 1603144467Sharti if (Targ_Silent(gn)) { 1604144467Sharti job->flags |= JOB_SILENT; 1605144467Sharti } 1606144467Sharti job->flags |= flags; 16078874Srgrimes 16081590Srgrimes /* 1609144467Sharti * Check the commands now so any attributes from .DEFAULT have a chance 1610144658Sharti * to migrate to the node. 16111590Srgrimes */ 1612144658Sharti if (!compatMake && (job->flags & JOB_FIRST)) { 1613144467Sharti cmdsOK = Job_CheckCommands(gn, Error); 1614144467Sharti } else { 1615144467Sharti cmdsOK = TRUE; 1616144467Sharti } 16171590Srgrimes 1618202045Sharti if ((tdir = getenv("TMPDIR")) == NULL) 1619202070Sharti tdir = _PATH_TMP; 1620202045Sharti 16211590Srgrimes /* 1622144467Sharti * If the -n flag wasn't given, we open up OUR (not the child's) 1623144467Sharti * temporary file to stuff commands in it. The thing is rd/wr so we 1624144467Sharti * don't need to reopen it to feed it to the shell. If the -n flag 1625144467Sharti * *was* given, we just set the file to be stdout. Cute, huh? 16261590Srgrimes */ 1627144467Sharti if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 1628144467Sharti /* 1629144467Sharti * We're serious here, but if the commands were bogus, we're 1630144467Sharti * also dead... 1631144467Sharti */ 1632144467Sharti if (!cmdsOK) { 1633144467Sharti DieHorribly(); 1634144467Sharti } 16358874Srgrimes 1636202045Sharti snprintf(tfile, sizeof(tfile), "%s/%s", tdir, TMPPAT); 1637144467Sharti if ((tfd = mkstemp(tfile)) == -1) 1638144467Sharti Punt("Cannot create temp file: %s", strerror(errno)); 1639144467Sharti job->cmdFILE = fdopen(tfd, "w+"); 1640144467Sharti eunlink(tfile); 1641144467Sharti if (job->cmdFILE == NULL) { 1642144467Sharti close(tfd); 1643144467Sharti Punt("Could not open %s", tfile); 1644144467Sharti } 1645144467Sharti fcntl(FILENO(job->cmdFILE), F_SETFD, 1); 1646144467Sharti /* 1647144467Sharti * Send the commands to the command file, flush all its 1648144467Sharti * buffers then rewind and remove the thing. 1649144467Sharti */ 1650144467Sharti noExec = FALSE; 1651138564Sharti 1652138564Sharti /* 1653144467Sharti * Used to be backwards; replace when start doing multiple 1654144467Sharti * commands per shell. 1655138564Sharti */ 1656144467Sharti if (compatMake) { 1657144467Sharti /* 1658144467Sharti * Be compatible: If this is the first time for this 1659144467Sharti * node, verify its commands are ok and open the 1660144467Sharti * commands list for sequential access by later 1661144467Sharti * invocations of JobStart. Once that is done, we take 1662144467Sharti * the next command off the list and print it to the 1663144467Sharti * command file. If the command was an ellipsis, note 1664144467Sharti * that there's nothing more to execute. 1665144467Sharti */ 1666144467Sharti if (job->flags & JOB_FIRST) 1667144467Sharti gn->compat_command = Lst_First(&gn->commands); 1668144467Sharti else 1669144467Sharti gn->compat_command = 1670144467Sharti Lst_Succ(gn->compat_command); 16718874Srgrimes 1672144467Sharti if (gn->compat_command == NULL || 1673228157Sfjoe JobPrintCommand(gn->compat_command, job)) 1674144467Sharti noExec = TRUE; 1675144467Sharti 1676144467Sharti if (noExec && !(job->flags & JOB_FIRST)) { 1677144467Sharti /* 1678144467Sharti * If we're not going to execute anything, the 1679144467Sharti * job is done and we need to close down the 1680144467Sharti * various file descriptors we've opened for 1681144467Sharti * output, then call JobDoOutput to catch the 1682144467Sharti * final characters or send the file to the 1683144467Sharti * screen... Note that the i/o streams are only 1684144467Sharti * open if this isn't the first job. Note also 1685144467Sharti * that this could not be done in 1686144467Sharti * Job_CatchChildren b/c it wasn't clear if 1687144467Sharti * there were more commands to execute or not... 1688144467Sharti */ 1689144467Sharti JobClose(job); 1690144467Sharti } 1691144467Sharti } else { 1692144467Sharti /* 1693144467Sharti * We can do all the commands at once. hooray for sanity 1694144467Sharti */ 1695144467Sharti numCommands = 0; 1696144467Sharti LST_FOREACH(ln, &gn->commands) { 1697228157Sfjoe if (JobPrintCommand(ln, job)) 1698144467Sharti break; 1699144467Sharti } 1700144467Sharti 1701144467Sharti /* 1702144467Sharti * If we didn't print out any commands to the shell 1703144467Sharti * script, there's not much point in executing the 1704144467Sharti * shell, is there? 1705144467Sharti */ 1706144467Sharti if (numCommands == 0) { 1707144467Sharti noExec = TRUE; 1708144467Sharti } 1709144467Sharti } 1710144467Sharti 1711144467Sharti } else if (noExecute) { 1712144467Sharti /* 1713144467Sharti * Not executing anything -- just print all the commands to 1714144467Sharti * stdout in one fell swoop. This will still set up 1715144467Sharti * job->tailCmds correctly. 1716144467Sharti */ 1717144467Sharti if (lastNode != gn) { 1718144467Sharti MESSAGE(stdout, gn); 1719144467Sharti lastNode = gn; 1720144467Sharti } 1721144467Sharti job->cmdFILE = stdout; 1722144467Sharti 1723144467Sharti /* 1724144467Sharti * Only print the commands if they're ok, but don't die if 1725144467Sharti * they're not -- just let the user know they're bad and keep 1726144467Sharti * going. It doesn't do any harm in this case and may do 1727144467Sharti * some good. 1728144467Sharti */ 1729144467Sharti if (cmdsOK) { 1730144467Sharti LST_FOREACH(ln, &gn->commands) { 1731228157Sfjoe if (JobPrintCommand(ln, job)) 1732144467Sharti break; 1733144467Sharti } 1734144467Sharti } 1735144467Sharti /* 1736144467Sharti * Don't execute the shell, thank you. 1737144467Sharti */ 17381590Srgrimes noExec = TRUE; 1739144467Sharti 1740144467Sharti } else { 1741144467Sharti /* 1742144467Sharti * Just touch the target and note that no shell should be 1743144467Sharti * executed. Set cmdFILE to stdout to make life easier. Check 1744144467Sharti * the commands, too, but don't die if they're no good -- it 1745144467Sharti * does no harm to keep working up the graph. 1746144467Sharti */ 1747144467Sharti job->cmdFILE = stdout; 1748144467Sharti Job_Touch(gn, job->flags & JOB_SILENT); 1749144467Sharti noExec = TRUE; 17501590Srgrimes } 1751144467Sharti 17521590Srgrimes /* 1753144467Sharti * If we're not supposed to execute a shell, don't. 17541590Srgrimes */ 1755144467Sharti if (noExec) { 1756144467Sharti /* 1757144467Sharti * Unlink and close the command file if we opened one 1758144467Sharti */ 1759144467Sharti if (job->cmdFILE != stdout) { 1760144467Sharti if (job->cmdFILE != NULL) 1761144467Sharti fclose(job->cmdFILE); 1762144467Sharti } else { 1763144467Sharti fflush(stdout); 1764144467Sharti } 1765144467Sharti 1766144467Sharti /* 1767144467Sharti * We only want to work our way up the graph if we aren't here 1768144467Sharti * because the commands for the job were no good. 1769144467Sharti */ 1770144467Sharti if (cmdsOK) { 1771144467Sharti if (aborting == 0) { 1772144467Sharti for (ln = job->tailCmds; ln != NULL; 1773144467Sharti ln = LST_NEXT(ln)) { 1774144467Sharti Lst_AtEnd(&postCommands->commands, 1775146027Sharti Buf_Peel(Var_Subst(Lst_Datum(ln), 1776146027Sharti job->node, FALSE))); 1777144467Sharti } 1778144467Sharti job->node->made = MADE; 1779144467Sharti Make_Update(job->node); 1780144467Sharti } 1781144467Sharti free(job); 1782144467Sharti return(JOB_FINISHED); 1783144467Sharti } else { 1784144467Sharti free(job); 1785144467Sharti return(JOB_ERROR); 1786144467Sharti } 1787144467Sharti } else { 1788144467Sharti fflush(job->cmdFILE); 17891590Srgrimes } 1790144467Sharti 17911590Srgrimes /* 1792144467Sharti * Set up the control arguments to the shell. This is based on the flags 1793144467Sharti * set earlier for this job. 17941590Srgrimes */ 1795144467Sharti JobMakeArgv(job, argv); 17961590Srgrimes 17971590Srgrimes /* 1798144467Sharti * If we're using pipes to catch output, create the pipe by which we'll 1799144467Sharti * get the shell's output. If we're using files, print out that we're 1800144467Sharti * starting a job and then set up its temporary-file name. 18011590Srgrimes */ 1802144467Sharti if (!compatMake || (job->flags & JOB_FIRST)) { 1803144467Sharti if (usePipes) { 1804144467Sharti int fd[2]; 18051590Srgrimes 1806228525Sfjoe if (pipe(fd) == -1) 1807228525Sfjoe Punt("Cannot create pipe: %s", strerror(errno)); 1808144467Sharti job->inPipe = fd[0]; 1809144467Sharti job->outPipe = fd[1]; 1810144467Sharti fcntl(job->inPipe, F_SETFD, 1); 1811144467Sharti fcntl(job->outPipe, F_SETFD, 1); 1812144467Sharti } else { 1813144467Sharti fprintf(stdout, "Remaking `%s'\n", gn->name); 1814144467Sharti fflush(stdout); 1815202045Sharti snprintf(job->outFile, sizeof(job->outFile), "%s/%s", 1816202045Sharti tdir, TMPPAT); 1817144467Sharti if ((job->outFd = mkstemp(job->outFile)) == -1) 1818144467Sharti Punt("cannot create temp file: %s", 1819144467Sharti strerror(errno)); 1820144467Sharti fcntl(job->outFd, F_SETFD, 1); 18211590Srgrimes } 18221590Srgrimes } 18231590Srgrimes 1824144657Sharti if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL) && maxJobs != 0) { 1825144467Sharti /* 1826144467Sharti * We've hit the limit of concurrency, so put the job on hold 1827144467Sharti * until some other job finishes. Note that the special jobs 1828144467Sharti * (.BEGIN, .INTERRUPT and .END) may be run even when the 1829144467Sharti * limit has been reached (e.g. when maxJobs == 0). 1830144467Sharti */ 1831144467Sharti jobFull = TRUE; 18321590Srgrimes 1833144467Sharti DEBUGF(JOB, ("Can only run job locally.\n")); 1834144467Sharti job->flags |= JOB_RESTART; 1835144494Sharti TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 18361590Srgrimes } else { 1837144467Sharti if (nJobs >= maxJobs) { 1838144467Sharti /* 1839144657Sharti * If we're running this job as a special case 1840144467Sharti * (see above), at least say the table is full. 1841144467Sharti */ 1842144467Sharti jobFull = TRUE; 1843144467Sharti DEBUGF(JOB, ("Local job queue is full.\n")); 1844144467Sharti } 1845144467Sharti JobExec(job, argv); 18461590Srgrimes } 1847144467Sharti return (JOB_RUNNING); 18481590Srgrimes} 18491590Srgrimes 185018730Sstevestatic char * 1851104696SjmallettJobOutput(Job *job, char *cp, char *endp, int msg) 185218730Ssteve{ 1853144467Sharti char *ecp; 185418730Ssteve 1855144467Sharti if (commandShell->noPrint) { 1856144467Sharti ecp = strstr(cp, commandShell->noPrint); 1857144467Sharti while (ecp != NULL) { 1858144467Sharti if (cp != ecp) { 1859144467Sharti *ecp = '\0'; 1860144467Sharti if (msg && job->node != lastNode) { 1861144467Sharti MESSAGE(stdout, job->node); 1862144467Sharti lastNode = job->node; 1863144467Sharti } 1864144467Sharti /* 1865144467Sharti * The only way there wouldn't be a newline 1866144467Sharti * after this line is if it were the last in 1867144467Sharti * the buffer. However, since the non-printable 1868144467Sharti * comes after it, there must be a newline, so 1869144467Sharti * we don't print one. 1870144467Sharti */ 1871144467Sharti fprintf(stdout, "%s", cp); 1872144467Sharti fflush(stdout); 1873144467Sharti } 1874144741Sharti cp = ecp + strlen(commandShell->noPrint); 1875144467Sharti if (cp != endp) { 1876144467Sharti /* 1877144467Sharti * Still more to print, look again after 1878144467Sharti * skipping the whitespace following the 1879144467Sharti * non-printable command.... 1880144467Sharti */ 1881144467Sharti cp++; 1882144467Sharti while (*cp == ' ' || *cp == '\t' || 1883144467Sharti *cp == '\n') { 1884144467Sharti cp++; 1885144467Sharti } 1886144467Sharti ecp = strstr(cp, commandShell->noPrint); 1887144467Sharti } else { 1888144467Sharti return (cp); 1889144467Sharti } 189018730Ssteve } 189118730Ssteve } 1892144467Sharti return (cp); 189318730Ssteve} 189418730Ssteve 1895144467Sharti/** 1896144467Sharti * JobDoOutput 18971590Srgrimes * This function is called at different times depending on 18981590Srgrimes * whether the user has specified that output is to be collected 18991590Srgrimes * via pipes or temporary files. In the former case, we are called 19001590Srgrimes * whenever there is something to read on the pipe. We collect more 19011590Srgrimes * output from the given job and store it in the job's outBuf. If 19021590Srgrimes * this makes up a line, we print it tagged by the job's identifier, 19031590Srgrimes * as necessary. 19041590Srgrimes * If output has been collected in a temporary file, we open the 1905228992Suqs * file and read it line by line, transferring it to our own 19061590Srgrimes * output channel until the file is empty. At which point we 19071590Srgrimes * remove the temporary file. 19081590Srgrimes * In both cases, however, we keep our figurative eye out for the 19091590Srgrimes * 'noPrint' line for the shell from which the output came. If 19101590Srgrimes * we recognize a line, we don't print it. If the command is not 19111590Srgrimes * alone on the line (the character after it is not \0 or \n), we 19121590Srgrimes * do print whatever follows it. 19131590Srgrimes * 19141590Srgrimes * Side Effects: 19151590Srgrimes * curPos may be shifted as may the contents of outBuf. 19161590Srgrimes */ 1917144656Shartistatic void 1918104696SjmallettJobDoOutput(Job *job, Boolean finish) 19191590Srgrimes{ 1920144467Sharti Boolean gotNL = FALSE; /* true if got a newline */ 1921144467Sharti Boolean fbuf; /* true if our buffer filled up */ 1922144467Sharti int nr; /* number of bytes read */ 1923144467Sharti int i; /* auxiliary index into outBuf */ 1924144467Sharti int max; /* limit for i (end of current data) */ 1925144467Sharti int nRead; /* (Temporary) number of bytes read */ 1926144467Sharti FILE *oFILE; /* Stream pointer to shell's output file */ 1927144467Sharti char inLine[132]; 19281590Srgrimes 1929144467Sharti if (usePipes) { 19301590Srgrimes /* 1931144467Sharti * Read as many bytes as will fit in the buffer. 19321590Srgrimes */ 1933144467Sharti end_loop: 1934144467Sharti gotNL = FALSE; 1935144467Sharti fbuf = FALSE; 19368874Srgrimes 1937144467Sharti nRead = read(job->inPipe, &job->outBuf[job->curPos], 1938144467Sharti JOB_BUFSIZE - job->curPos); 19391590Srgrimes /* 1940144467Sharti * Check for interrupt here too, because the above read may 1941144467Sharti * block when the child process is stopped. In this case the 1942144467Sharti * interrupt will unblock it (we don't use SA_RESTART). 19431590Srgrimes */ 1944144467Sharti if (interrupted) 1945144467Sharti JobPassSig(interrupted); 19461590Srgrimes 1947144467Sharti if (nRead < 0) { 1948144467Sharti DEBUGF(JOB, ("JobDoOutput(piperead)")); 1949144467Sharti nr = 0; 1950144467Sharti } else { 1951144467Sharti nr = nRead; 1952144467Sharti } 19531590Srgrimes 19541590Srgrimes /* 1955144467Sharti * If we hit the end-of-file (the job is dead), we must flush 1956144467Sharti * its remaining output, so pretend we read a newline if 1957144467Sharti * there's any output remaining in the buffer. 1958144467Sharti * Also clear the 'finish' flag so we stop looping. 19591590Srgrimes */ 1960144657Sharti if (nr == 0 && job->curPos != 0) { 1961144467Sharti job->outBuf[job->curPos] = '\n'; 1962144467Sharti nr = 1; 1963144467Sharti finish = FALSE; 1964144467Sharti } else if (nr == 0) { 1965144467Sharti finish = FALSE; 19661590Srgrimes } 19678874Srgrimes 19681590Srgrimes /* 1969144467Sharti * Look for the last newline in the bytes we just got. If there 1970144467Sharti * is one, break out of the loop with 'i' as its index and 1971144467Sharti * gotNL set TRUE. 1972144467Sharti */ 1973144467Sharti max = job->curPos + nr; 1974144467Sharti for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 1975144467Sharti if (job->outBuf[i] == '\n') { 1976144467Sharti gotNL = TRUE; 1977144467Sharti break; 1978144467Sharti } else if (job->outBuf[i] == '\0') { 1979144467Sharti /* 1980144467Sharti * Why? 1981144467Sharti */ 1982144467Sharti job->outBuf[i] = ' '; 1983144467Sharti } 1984144467Sharti } 19851590Srgrimes 1986144467Sharti if (!gotNL) { 1987144467Sharti job->curPos += nr; 1988144467Sharti if (job->curPos == JOB_BUFSIZE) { 1989144467Sharti /* 1990144467Sharti * If we've run out of buffer space, we have 1991144467Sharti * no choice but to print the stuff. sigh. 1992144467Sharti */ 1993144467Sharti fbuf = TRUE; 1994144467Sharti i = job->curPos; 1995144467Sharti } 19961590Srgrimes } 1997144467Sharti if (gotNL || fbuf) { 1998144467Sharti /* 1999144467Sharti * Need to send the output to the screen. Null terminate 2000144467Sharti * it first, overwriting the newline character if there 2001144467Sharti * was one. So long as the line isn't one we should 2002144467Sharti * filter (according to the shell description), we print 2003144467Sharti * the line, preceded by a target banner if this target 2004144467Sharti * isn't the same as the one for which we last printed 2005144467Sharti * something. The rest of the data in the buffer are 2006144467Sharti * then shifted down to the start of the buffer and 2007144467Sharti * curPos is set accordingly. 2008144467Sharti */ 2009144467Sharti job->outBuf[i] = '\0'; 2010144467Sharti if (i >= job->curPos) { 2011144467Sharti char *cp; 20121590Srgrimes 2013144467Sharti cp = JobOutput(job, job->outBuf, 2014144467Sharti &job->outBuf[i], FALSE); 2015144467Sharti 2016144467Sharti /* 2017144467Sharti * There's still more in that buffer. This time, 2018144467Sharti * though, we know there's no newline at the 2019144467Sharti * end, so we add one of our own free will. 2020144467Sharti */ 2021144467Sharti if (*cp != '\0') { 2022144467Sharti if (job->node != lastNode) { 2023144467Sharti MESSAGE(stdout, job->node); 2024144467Sharti lastNode = job->node; 2025144467Sharti } 2026144467Sharti fprintf(stdout, "%s%s", cp, 2027144467Sharti gotNL ? "\n" : ""); 2028144467Sharti fflush(stdout); 2029144467Sharti } 2030144467Sharti } 2031144467Sharti if (i < max - 1) { 2032144467Sharti /* shift the remaining characters down */ 2033144467Sharti memcpy(job->outBuf, &job->outBuf[i + 1], 2034144467Sharti max - (i + 1)); 2035144467Sharti job->curPos = max - (i + 1); 2036144467Sharti 2037144467Sharti } else { 2038144467Sharti /* 2039144467Sharti * We have written everything out, so we just 2040144467Sharti * start over from the start of the buffer. 2041144467Sharti * No copying. No nothing. 2042144467Sharti */ 2043144467Sharti job->curPos = 0; 2044144467Sharti } 2045144467Sharti } 2046144467Sharti if (finish) { 2047144467Sharti /* 2048144467Sharti * If the finish flag is true, we must loop until we hit 2049144467Sharti * end-of-file on the pipe. This is guaranteed to happen 2050144467Sharti * eventually since the other end of the pipe is now 2051144467Sharti * closed (we closed it explicitly and the child has 2052144467Sharti * exited). When we do get an EOF, finish will be set 2053144467Sharti * FALSE and we'll fall through and out. 2054144467Sharti */ 2055144467Sharti goto end_loop; 2056144467Sharti } 2057144467Sharti 2058144467Sharti } else { 20591590Srgrimes /* 2060144467Sharti * We've been called to retrieve the output of the job from the 2061144467Sharti * temporary file where it's been squirreled away. This consists 2062144467Sharti * of opening the file, reading the output line by line, being 2063144467Sharti * sure not to print the noPrint line for the shell we used, 2064144467Sharti * then close and remove the temporary file. Very simple. 2065144467Sharti * 2066144467Sharti * Change to read in blocks and do FindSubString type things 2067144467Sharti * as for pipes? That would allow for "@echo -n..." 20681590Srgrimes */ 2069144467Sharti oFILE = fopen(job->outFile, "r"); 2070144467Sharti if (oFILE != NULL) { 2071144467Sharti fprintf(stdout, "Results of making %s:\n", 2072144467Sharti job->node->name); 2073144467Sharti fflush(stdout); 2074144467Sharti 2075144467Sharti while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 2076144467Sharti char *cp, *endp, *oendp; 2077144467Sharti 2078144467Sharti cp = inLine; 2079144467Sharti oendp = endp = inLine + strlen(inLine); 2080144467Sharti if (endp[-1] == '\n') { 2081144467Sharti *--endp = '\0'; 2082144467Sharti } 2083144467Sharti cp = JobOutput(job, inLine, endp, FALSE); 2084144467Sharti 2085144467Sharti /* 2086144467Sharti * There's still more in that buffer. This time, 2087144467Sharti * though, we know there's no newline at the 2088144467Sharti * end, so we add one of our own free will. 2089144467Sharti */ 2090144467Sharti fprintf(stdout, "%s", cp); 2091144467Sharti fflush(stdout); 2092144467Sharti if (endp != oendp) { 2093144467Sharti fprintf(stdout, "\n"); 2094144467Sharti fflush(stdout); 2095144467Sharti } 2096144467Sharti } 2097144467Sharti fclose(oFILE); 2098144467Sharti eunlink(job->outFile); 20991590Srgrimes } 21001590Srgrimes } 21011590Srgrimes} 21021590Srgrimes 2103144467Sharti/** 2104144467Sharti * Job_CatchChildren 21051590Srgrimes * Handle the exit of a child. Called from Make_Make. 21061590Srgrimes * 21071590Srgrimes * Side Effects: 21081590Srgrimes * The job descriptor is removed from the list of children. 21091590Srgrimes * 21101590Srgrimes * Notes: 21111590Srgrimes * We do waits, blocking or not, according to the wisdom of our 21121590Srgrimes * caller, until there are no more children to report. For each 21131590Srgrimes * job, call JobFinish to finish things off. This will take care of 21141590Srgrimes * putting jobs on the stoppedJobs queue. 21151590Srgrimes */ 21161590Srgrimesvoid 2117104696SjmallettJob_CatchChildren(Boolean block) 21181590Srgrimes{ 2119144665Sharti pid_t pid; /* pid of dead child */ 2120144467Sharti Job *job; /* job descriptor for dead child */ 2121144467Sharti int status; /* Exit/termination status */ 21221590Srgrimes 2123144467Sharti /* 2124144467Sharti * Don't even bother if we know there's no one around. 2125144467Sharti */ 2126144467Sharti if (nJobs == 0) { 2127144467Sharti return; 2128144467Sharti } 21298874Srgrimes 2130144467Sharti for (;;) { 2131252679Skevlo pid = waitpid(-1, &status, 2132144467Sharti (block ? 0 : WNOHANG) | WUNTRACED); 2133144467Sharti if (pid <= 0) 2134144467Sharti break; 21351590Srgrimes 2136144665Sharti DEBUGF(JOB, ("Process %jd exited or stopped.\n", 2137144665Sharti (intmax_t)pid)); 21381590Srgrimes 2139144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2140144494Sharti if (job->pid == pid) 2141144467Sharti break; 2142143810Sharti } 2143144467Sharti 2144144494Sharti if (job == NULL) { 2145144467Sharti if (WIFSIGNALED(status) && 2146144467Sharti (WTERMSIG(status) == SIGCONT)) { 2147144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2148144494Sharti if (job->pid == pid) 2149144467Sharti break; 2150144467Sharti } 2151144494Sharti if (job == NULL) { 2152144665Sharti Error("Resumed child (%jd) " 2153144665Sharti "not in table", (intmax_t)pid); 2154144467Sharti continue; 2155144467Sharti } 2156144494Sharti TAILQ_REMOVE(&stoppedJobs, job, link); 2157144467Sharti } else { 2158144665Sharti Error("Child (%jd) not in table?", 2159144665Sharti (intmax_t)pid); 2160144467Sharti continue; 2161144467Sharti } 2162144467Sharti } else { 2163144494Sharti TAILQ_REMOVE(&jobs, job, link); 2164144467Sharti nJobs -= 1; 2165144467Sharti if (fifoFd >= 0 && maxJobs > 1) { 2166144467Sharti write(fifoFd, "+", 1); 2167144467Sharti maxJobs--; 2168144467Sharti if (nJobs >= maxJobs) 2169144467Sharti jobFull = TRUE; 2170144467Sharti else 2171144467Sharti jobFull = FALSE; 2172144467Sharti } else { 2173144467Sharti DEBUGF(JOB, ("Job queue is no longer full.\n")); 2174144467Sharti jobFull = FALSE; 2175144467Sharti } 21761590Srgrimes } 2177144467Sharti 2178144467Sharti JobFinish(job, &status); 21791590Srgrimes } 2180144467Sharti if (interrupted) 2181144467Sharti JobPassSig(interrupted); 21821590Srgrimes} 21831590Srgrimes 2184144467Sharti/** 2185144467Sharti * Job_CatchOutput 21861590Srgrimes * Catch the output from our children, if we're using 21871590Srgrimes * pipes do so. Otherwise just block time until we get a 2188138232Sharti * signal(most likely a SIGCHLD) since there's no point in 21891590Srgrimes * just spinning when there's nothing to do and the reaping 21908874Srgrimes * of a child can wait for a while. 21911590Srgrimes * 21921590Srgrimes * Side Effects: 21931590Srgrimes * Output is read from pipes if we're piping. 21941590Srgrimes * ----------------------------------------------------------------------- 21951590Srgrimes */ 21961590Srgrimesvoid 2197139064Sharti#ifdef USE_KQUEUE 2198139064ShartiJob_CatchOutput(int flag __unused) 2199139064Sharti#else 2200137606SphkJob_CatchOutput(int flag) 2201139064Sharti#endif 22021590Srgrimes{ 2203144467Sharti int nfds; 2204104475Sphk#ifdef USE_KQUEUE 2205104475Sphk#define KEV_SIZE 4 2206144467Sharti struct kevent kev[KEV_SIZE]; 2207144467Sharti int i; 2208104475Sphk#else 2209144467Sharti struct timeval timeout; 2210144467Sharti fd_set readfds; 2211144467Sharti Job *job; 2212104475Sphk#endif 22131590Srgrimes 2214144467Sharti fflush(stdout); 22151590Srgrimes 2216144467Sharti if (usePipes) { 2217104475Sphk#ifdef USE_KQUEUE 2218144467Sharti if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) { 2219144467Sharti if (errno != EINTR) 2220144467Sharti Punt("kevent: %s", strerror(errno)); 2221144467Sharti if (interrupted) 2222144467Sharti JobPassSig(interrupted); 2223144467Sharti } else { 2224144467Sharti for (i = 0; i < nfds; i++) { 2225144467Sharti if (kev[i].flags & EV_ERROR) { 2226144467Sharti warnc(kev[i].data, "kevent"); 2227144467Sharti continue; 2228144467Sharti } 2229144467Sharti switch (kev[i].filter) { 2230144467Sharti case EVFILT_READ: 2231144467Sharti JobDoOutput(kev[i].udata, FALSE); 2232144467Sharti break; 2233144467Sharti case EVFILT_PROC: 2234144467Sharti /* 2235144467Sharti * Just wake up and let 2236144467Sharti * Job_CatchChildren() collect the 2237144467Sharti * terminated job. 2238144467Sharti */ 2239144467Sharti break; 2240144467Sharti } 2241144467Sharti } 2242104475Sphk } 2243104475Sphk#else 2244144467Sharti readfds = outputs; 2245144467Sharti timeout.tv_sec = SEL_SEC; 2246144467Sharti timeout.tv_usec = SEL_USEC; 2247144467Sharti if (flag && jobFull && fifoFd >= 0) 2248144467Sharti FD_SET(fifoFd, &readfds); 22491590Srgrimes 2250144467Sharti nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL, 2251144467Sharti (fd_set *)NULL, &timeout); 2252144467Sharti if (nfds <= 0) { 2253144467Sharti if (interrupted) 2254144467Sharti JobPassSig(interrupted); 2255144467Sharti return; 2256144467Sharti } 2257144467Sharti if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) { 2258144467Sharti if (--nfds <= 0) 2259144467Sharti return; 2260144467Sharti } 2261144494Sharti job = TAILQ_FIRST(&jobs); 2262144494Sharti while (nfds != 0 && job != NULL) { 2263144467Sharti if (FD_ISSET(job->inPipe, &readfds)) { 2264144467Sharti JobDoOutput(job, FALSE); 2265144494Sharti nfds--; 2266144467Sharti } 2267144494Sharti job = TAILQ_NEXT(job, link); 2268144467Sharti } 2269144467Sharti#endif /* !USE_KQUEUE */ 2270137606Sphk } 22711590Srgrimes} 22721590Srgrimes 2273144467Sharti/** 2274144467Sharti * Job_Make 22751590Srgrimes * Start the creation of a target. Basically a front-end for 22761590Srgrimes * JobStart used by the Make module. 22771590Srgrimes * 22781590Srgrimes * Side Effects: 22791590Srgrimes * Another job is started. 22801590Srgrimes */ 22811590Srgrimesvoid 2282104696SjmallettJob_Make(GNode *gn) 22831590Srgrimes{ 2284138232Sharti 2285144467Sharti JobStart(gn, 0, NULL); 22861590Srgrimes} 22871590Srgrimes 2288186559Sobrienvoid 2289186559SobrienJob_SetPrefix(void) 2290186559Sobrien{ 2291186559Sobrien 2292186559Sobrien if (targPrefix) { 2293186559Sobrien free(targPrefix); 2294186559Sobrien } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) { 2295186559Sobrien Var_SetGlobal(MAKE_JOB_PREFIX, "---"); 2296186559Sobrien } 2297186559Sobrien targPrefix = Var_Subst("${" MAKE_JOB_PREFIX "}", VAR_GLOBAL, 0)->buf; 2298186559Sobrien} 2299186559Sobrien 2300144467Sharti/** 2301144467Sharti * Job_Init 2302137572Sphk * Initialize the process module, given a maximum number of jobs. 23031590Srgrimes * 23041590Srgrimes * Side Effects: 23051590Srgrimes * lists and counters are initialized 23061590Srgrimes */ 23071590Srgrimesvoid 2308137572SphkJob_Init(int maxproc) 23091590Srgrimes{ 2310144467Sharti GNode *begin; /* node for commands to do at the very start */ 2311144467Sharti const char *env; 2312144467Sharti struct sigaction sa; 23131590Srgrimes 2314144467Sharti fifoFd = -1; 2315144467Sharti env = getenv("MAKE_JOBS_FIFO"); 2316137606Sphk 2317144467Sharti if (env == NULL && maxproc > 1) { 2318144467Sharti /* 2319144467Sharti * We did not find the environment variable so we are the 2320144467Sharti * leader. Create the fifo, open it, write one char per 2321144467Sharti * allowed job into the pipe. 2322144467Sharti */ 2323146155Sharti fifoFd = mkfifotemp(fifoName); 2324146155Sharti if (fifoFd < 0) { 2325146155Sharti env = NULL; 2326146155Sharti } else { 2327146155Sharti fifoMaster = 1; 2328146155Sharti fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2329146155Sharti env = fifoName; 2330146155Sharti setenv("MAKE_JOBS_FIFO", env, 1); 2331146155Sharti while (maxproc-- > 0) { 2332146155Sharti write(fifoFd, "+", 1); 2333144467Sharti } 2334146155Sharti /* The master make does not get a magic token */ 2335146155Sharti jobFull = TRUE; 2336146155Sharti maxJobs = 0; 2337137606Sphk } 2338144467Sharti 2339144467Sharti } else if (env != NULL) { 2340144467Sharti /* 2341144467Sharti * We had the environment variable so we are a slave. 2342144467Sharti * Open fifo and give ourselves a magic token which represents 2343144467Sharti * the token our parent make has grabbed to start his make 2344144467Sharti * process. Otherwise the sub-makes would gobble up tokens and 2345144467Sharti * the proper number of tokens to specify to -j would depend 2346144467Sharti * on the depth of the tree and the order of execution. 2347144467Sharti */ 2348144467Sharti fifoFd = open(env, O_RDWR, 0); 2349144467Sharti if (fifoFd >= 0) { 2350144467Sharti fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2351144467Sharti maxJobs = 1; 2352144467Sharti jobFull = FALSE; 2353144467Sharti } 2354137606Sphk } 2355167329Swill if (fifoFd < 0) { 2356144467Sharti maxJobs = maxproc; 2357144467Sharti jobFull = FALSE; 2358144467Sharti } else { 2359137606Sphk } 2360144467Sharti nJobs = 0; 23611590Srgrimes 2362144467Sharti aborting = 0; 2363186279Sfjoe makeErrors = 0; 23641590Srgrimes 2365144467Sharti lastNode = NULL; 2366188075Sobrien if ((maxJobs == 1 && fifoFd < 0) || !beVerbose || is_posix || beQuiet) { 2367144467Sharti /* 2368144467Sharti * If only one job can run at a time, there's no need for a 2369144467Sharti * banner, no is there? 2370144467Sharti */ 2371144467Sharti targFmt = ""; 2372144467Sharti } else { 2373144467Sharti targFmt = TARG_FMT; 2374144467Sharti } 2375144467Sharti 23761590Srgrimes /* 2377144467Sharti * Catch the four signals that POSIX specifies if they aren't ignored. 2378144467Sharti * JobCatchSignal will just set global variables and hope someone 2379144467Sharti * else is going to handle the interrupt. 23801590Srgrimes */ 2381144467Sharti sa.sa_handler = JobCatchSig; 2382144467Sharti sigemptyset(&sa.sa_mask); 2383144467Sharti sa.sa_flags = 0; 23848874Srgrimes 2385144467Sharti if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 2386144467Sharti sigaction(SIGINT, &sa, NULL); 2387144467Sharti } 2388144467Sharti if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 2389144467Sharti sigaction(SIGHUP, &sa, NULL); 2390144467Sharti } 2391144467Sharti if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 2392144467Sharti sigaction(SIGQUIT, &sa, NULL); 2393144467Sharti } 2394144467Sharti if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 2395144467Sharti sigaction(SIGTERM, &sa, NULL); 2396144467Sharti } 2397144467Sharti /* 2398144467Sharti * There are additional signals that need to be caught and passed if 2399144467Sharti * either the export system wants to be told directly of signals or if 2400144467Sharti * we're giving each job its own process group (since then it won't get 2401144467Sharti * signals from the terminal driver as we own the terminal) 2402144467Sharti */ 2403137202Sharti#if defined(USE_PGRP) 2404144467Sharti if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { 2405144467Sharti sigaction(SIGTSTP, &sa, NULL); 2406144467Sharti } 2407144467Sharti if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { 2408144467Sharti sigaction(SIGTTOU, &sa, NULL); 2409144467Sharti } 2410144467Sharti if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { 2411144467Sharti sigaction(SIGTTIN, &sa, NULL); 2412144467Sharti } 2413144467Sharti if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { 2414144467Sharti sigaction(SIGWINCH, &sa, NULL); 2415144467Sharti } 24161590Srgrimes#endif 24178874Srgrimes 2418104475Sphk#ifdef USE_KQUEUE 2419144467Sharti if ((kqfd = kqueue()) == -1) { 2420144467Sharti Punt("kqueue: %s", strerror(errno)); 2421144467Sharti } 2422104475Sphk#endif 2423104475Sphk 2424144467Sharti begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); 24251590Srgrimes 2426144467Sharti if (begin != NULL) { 2427144467Sharti JobStart(begin, JOB_SPECIAL, (Job *)NULL); 2428144467Sharti while (nJobs) { 2429144467Sharti Job_CatchOutput(0); 2430144467Sharti Job_CatchChildren(!usePipes); 2431144467Sharti } 24321590Srgrimes } 2433144467Sharti postCommands = Targ_FindNode(".END", TARG_CREATE); 24341590Srgrimes} 24351590Srgrimes 2436144467Sharti/** 2437144467Sharti * Job_Full 24381590Srgrimes * See if the job table is full. It is considered full if it is OR 24391590Srgrimes * if we are in the process of aborting OR if we have 24401590Srgrimes * reached/exceeded our local quota. This prevents any more jobs 24411590Srgrimes * from starting up. 24421590Srgrimes * 24431590Srgrimes * Results: 24441590Srgrimes * TRUE if the job table is full, FALSE otherwise 24451590Srgrimes */ 24461590SrgrimesBoolean 2447104696SjmallettJob_Full(void) 24481590Srgrimes{ 2449144467Sharti char c; 2450144467Sharti int i; 2451137606Sphk 2452144467Sharti if (aborting) 2453144467Sharti return (aborting); 2454144467Sharti if (fifoFd >= 0 && jobFull) { 2455144467Sharti i = read(fifoFd, &c, 1); 2456144467Sharti if (i > 0) { 2457144467Sharti maxJobs++; 2458144467Sharti jobFull = FALSE; 2459144467Sharti } 2460137606Sphk } 2461144467Sharti return (jobFull); 24621590Srgrimes} 24631590Srgrimes 2464144467Sharti/** 2465144467Sharti * Job_Empty 24661590Srgrimes * See if the job table is empty. Because the local concurrency may 24671590Srgrimes * be set to 0, it is possible for the job table to become empty, 24681590Srgrimes * while the list of stoppedJobs remains non-empty. In such a case, 24691590Srgrimes * we want to restart as many jobs as we can. 24701590Srgrimes * 24711590Srgrimes * Results: 24721590Srgrimes * TRUE if it is. FALSE if it ain't. 24731590Srgrimes */ 24741590SrgrimesBoolean 2475104696SjmallettJob_Empty(void) 24761590Srgrimes{ 2477144467Sharti if (nJobs == 0) { 2478144494Sharti if (!TAILQ_EMPTY(&stoppedJobs) && !aborting) { 2479144467Sharti /* 2480144467Sharti * The job table is obviously not full if it has no 2481144467Sharti * jobs in it...Try and restart the stopped jobs. 2482144467Sharti */ 2483144467Sharti jobFull = FALSE; 2484144467Sharti JobRestartJobs(); 2485144467Sharti return (FALSE); 2486144467Sharti } else { 2487144467Sharti return (TRUE); 2488144467Sharti } 24891590Srgrimes } else { 2490144467Sharti return (FALSE); 24911590Srgrimes } 24921590Srgrimes} 24931590Srgrimes 2494144467Sharti/** 2495144467Sharti * JobInterrupt 24961590Srgrimes * Handle the receipt of an interrupt. 24971590Srgrimes * 24981590Srgrimes * Side Effects: 24991590Srgrimes * All children are killed. Another job will be started if the 25001590Srgrimes * .INTERRUPT target was given. 25011590Srgrimes */ 25021590Srgrimesstatic void 2503104696SjmallettJobInterrupt(int runINTERRUPT, int signo) 25041590Srgrimes{ 2505144467Sharti Job *job; /* job descriptor in that element */ 2506144467Sharti GNode *interrupt; /* the node describing the .INTERRUPT target */ 25078874Srgrimes 2508144467Sharti aborting = ABORT_INTERRUPT; 25091590Srgrimes 2510144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2511144467Sharti if (!Targ_Precious(job->node)) { 2512144467Sharti char *file = (job->node->path == NULL ? 2513144467Sharti job->node->name : job->node->path); 2514144467Sharti 2515144467Sharti if (!noExecute && eunlink(file) != -1) { 2516144467Sharti Error("*** %s removed", file); 2517144467Sharti } 2518144467Sharti } 2519144467Sharti if (job->pid) { 2520144467Sharti DEBUGF(JOB, ("JobInterrupt passing signal to child " 2521144665Sharti "%jd.\n", (intmax_t)job->pid)); 2522144467Sharti KILL(job->pid, signo); 2523144467Sharti } 25241590Srgrimes } 252518730Ssteve 2526144467Sharti if (runINTERRUPT && !touchFlag) { 2527144467Sharti /* 2528144467Sharti * clear the interrupted flag because we would get an 2529144467Sharti * infinite loop otherwise. 2530144467Sharti */ 2531144467Sharti interrupted = 0; 2532137605Sharti 2533144467Sharti interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 2534144467Sharti if (interrupt != NULL) { 2535144467Sharti ignoreErrors = FALSE; 25361590Srgrimes 2537144467Sharti JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL); 2538144467Sharti while (nJobs) { 2539144467Sharti Job_CatchOutput(0); 2540144467Sharti Job_CatchChildren(!usePipes); 2541144467Sharti } 2542144467Sharti } 25431590Srgrimes } 2544151162Sscottl if (fifoMaster) 2545151162Sscottl unlink(fifoName); 25461590Srgrimes} 25471590Srgrimes 2548144467Sharti/** 2549144467Sharti * Job_Finish 25501590Srgrimes * Do final processing such as the running of the commands 25518874Srgrimes * attached to the .END target. 25521590Srgrimes * 25531590Srgrimes * Results: 2554186279Sfjoe * None. 25551590Srgrimes */ 2556186279Sfjoevoid 2557104696SjmallettJob_Finish(void) 25581590Srgrimes{ 2559138232Sharti 2560144467Sharti if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { 2561186279Sfjoe if (makeErrors) { 2562144467Sharti Error("Errors reported so .END ignored"); 2563144467Sharti } else { 2564144467Sharti JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); 25651590Srgrimes 2566144467Sharti while (nJobs) { 2567144467Sharti Job_CatchOutput(0); 2568144467Sharti Job_CatchChildren(!usePipes); 2569144467Sharti } 2570144467Sharti } 25711590Srgrimes } 2572144467Sharti if (fifoFd >= 0) { 2573144467Sharti close(fifoFd); 2574144467Sharti fifoFd = -1; 2575144467Sharti if (fifoMaster) 2576144467Sharti unlink(fifoName); 2577144467Sharti } 25781590Srgrimes} 25791590Srgrimes 2580144467Sharti/** 2581144467Sharti * Job_Wait 25821590Srgrimes * Waits for all running jobs to finish and returns. Sets 'aborting' 25831590Srgrimes * to ABORT_WAIT to prevent other jobs from starting. 25841590Srgrimes * 25851590Srgrimes * Side Effects: 25861590Srgrimes * Currently running jobs finish. 25871590Srgrimes */ 25881590Srgrimesvoid 2589104696SjmallettJob_Wait(void) 25901590Srgrimes{ 2591138232Sharti 2592144467Sharti aborting = ABORT_WAIT; 2593144467Sharti while (nJobs != 0) { 2594144467Sharti Job_CatchOutput(0); 2595144467Sharti Job_CatchChildren(!usePipes); 2596144467Sharti } 2597144467Sharti aborting = 0; 25981590Srgrimes} 25991590Srgrimes 2600144467Sharti/** 2601144467Sharti * Job_AbortAll 26021590Srgrimes * Abort all currently running jobs without handling output or anything. 26031590Srgrimes * This function is to be called only in the event of a major 26041590Srgrimes * error. Most definitely NOT to be called from JobInterrupt. 26051590Srgrimes * 26061590Srgrimes * Side Effects: 26071590Srgrimes * All children are killed, not just the firstborn 26081590Srgrimes */ 26091590Srgrimesvoid 2610104696SjmallettJob_AbortAll(void) 26111590Srgrimes{ 2612144467Sharti Job *job; /* the job descriptor in that element */ 2613144467Sharti int foo; 26148874Srgrimes 2615144467Sharti aborting = ABORT_ERROR; 26168874Srgrimes 2617144467Sharti if (nJobs) { 2618144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2619144467Sharti /* 2620144467Sharti * kill the child process with increasingly drastic 2621144467Sharti * signals to make darn sure it's dead. 2622144467Sharti */ 2623144467Sharti KILL(job->pid, SIGINT); 2624144467Sharti KILL(job->pid, SIGKILL); 2625144467Sharti } 26261590Srgrimes } 26278874Srgrimes 2628144467Sharti /* 2629144467Sharti * Catch as many children as want to report in at first, then give up 2630144467Sharti */ 2631252679Skevlo while (waitpid(-1, &foo, WNOHANG) > 0) 2632144665Sharti ; 26331590Srgrimes} 263418730Ssteve 2635144467Sharti/** 2636144467Sharti * JobRestartJobs 263718730Ssteve * Tries to restart stopped jobs if there are slots available. 263818730Ssteve * Note that this tries to restart them regardless of pending errors. 263918730Ssteve * It's not good to leave stopped jobs lying around! 264018730Ssteve * 264118730Ssteve * Side Effects: 264218730Ssteve * Resumes(and possibly migrates) jobs. 264318730Ssteve */ 264418730Sstevestatic void 2645104696SjmallettJobRestartJobs(void) 264618730Ssteve{ 2647144494Sharti Job *job; 2648144494Sharti 2649144494Sharti while (!jobFull && (job = TAILQ_FIRST(&stoppedJobs)) != NULL) { 2650144467Sharti DEBUGF(JOB, ("Job queue is not full. " 2651144467Sharti "Restarting a stopped job.\n")); 2652144494Sharti TAILQ_REMOVE(&stoppedJobs, job, link); 2653144494Sharti JobRestart(job); 2654144467Sharti } 265518730Ssteve} 2656146054Sharti 2657146054Sharti/** 2658146054Sharti * Cmd_Exec 2659146054Sharti * Execute the command in cmd, and return the output of that command 2660146054Sharti * in a string. 2661146054Sharti * 2662146054Sharti * Results: 2663146054Sharti * A string containing the output of the command, or the empty string 2664146054Sharti * If error is not NULL, it contains the reason for the command failure 2665146129Sharti * Any output sent to stderr in the child process is passed to stderr, 2666146129Sharti * and not captured in the string. 2667146054Sharti * 2668146054Sharti * Side Effects: 2669146054Sharti * The string must be freed by the caller. 2670146054Sharti */ 2671146054ShartiBuffer * 2672146054ShartiCmd_Exec(const char *cmd, const char **error) 2673146054Sharti{ 2674146054Sharti int fds[2]; /* Pipe streams */ 2675146054Sharti int status; /* command exit status */ 2676146054Sharti Buffer *buf; /* buffer to store the result */ 2677146054Sharti ssize_t rcnt; 2678146129Sharti ProcStuff ps; 2679146054Sharti 2680146054Sharti *error = NULL; 2681146054Sharti buf = Buf_Init(0); 2682146054Sharti 2683146054Sharti /* 2684146054Sharti * Open a pipe for fetching its output 2685146054Sharti */ 2686146054Sharti if (pipe(fds) == -1) { 2687146054Sharti *error = "Couldn't create pipe for \"%s\""; 2688146054Sharti return (buf); 2689146054Sharti } 2690146054Sharti 2691146129Sharti /* Set close-on-exec on read side of pipe. */ 2692146129Sharti fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC); 2693146129Sharti 2694146129Sharti ps.in = STDIN_FILENO; 2695146129Sharti ps.out = fds[1]; 2696146129Sharti ps.err = STDERR_FILENO; 2697146129Sharti 2698146129Sharti ps.merge_errors = 0; 2699146129Sharti ps.pgroup = 0; 2700146129Sharti ps.searchpath = 0; 2701146129Sharti 2702146129Sharti /* Set up arguments for shell */ 2703146129Sharti ps.argv = emalloc(4 * sizeof(char *)); 2704146557Sharti ps.argv[0] = strdup(commandShell->name); 2705146129Sharti ps.argv[1] = strdup("-c"); 2706146129Sharti ps.argv[2] = strdup(cmd); 2707146129Sharti ps.argv[3] = NULL; 2708146156Sharti ps.argv_free = 1; 2709146129Sharti 2710146054Sharti /* 2711146129Sharti * Fork. Warning since we are doing vfork() instead of fork(), 2712146129Sharti * do not allocate memory in the child process! 2713146054Sharti */ 2714146130Sharti if ((ps.child_pid = vfork()) == -1) { 2715146058Sharti *error = "Couldn't exec \"%s\""; 2716146058Sharti return (buf); 2717146058Sharti 2718146130Sharti } else if (ps.child_pid == 0) { 2719146129Sharti /* 2720146129Sharti * Child 2721146129Sharti */ 2722146574Sharti Proc_Exec(&ps); 2723146129Sharti /* NOTREACHED */ 2724146129Sharti } 2725146054Sharti 2726146129Sharti free(ps.argv[2]); 2727146129Sharti free(ps.argv[1]); 2728146129Sharti free(ps.argv[0]); 2729146129Sharti free(ps.argv); 2730146054Sharti 2731146129Sharti close(fds[1]); /* No need for the writing half of the pipe. */ 2732146054Sharti 2733146058Sharti do { 2734146058Sharti char result[BUFSIZ]; 2735146054Sharti 2736146058Sharti rcnt = read(fds[0], result, sizeof(result)); 2737146058Sharti if (rcnt != -1) 2738146058Sharti Buf_AddBytes(buf, (size_t)rcnt, (Byte *)result); 2739146058Sharti } while (rcnt > 0 || (rcnt == -1 && errno == EINTR)); 2740146054Sharti 2741146058Sharti if (rcnt == -1) 2742146058Sharti *error = "Error reading shell's output for \"%s\""; 2743146054Sharti 2744146058Sharti /* 2745146058Sharti * Close the input side of the pipe. 2746146058Sharti */ 2747146058Sharti close(fds[0]); 2748146054Sharti 2749146130Sharti status = ProcWait(&ps); 2750146054Sharti 2751146058Sharti if (status) 2752146058Sharti *error = "\"%s\" returned non-zero status"; 2753146054Sharti 2754146058Sharti Buf_StripNewlines(buf); 2755146054Sharti 2756146054Sharti return (buf); 2757146054Sharti} 2758146054Sharti 2759146056Sharti 2760146056Sharti/* 2761146056Sharti * Interrupt handler - set flag and defer handling to the main code 2762146056Sharti */ 2763146056Shartistatic void 2764146056ShartiCompatCatchSig(int signo) 2765146056Sharti{ 2766146056Sharti 2767146056Sharti interrupted = signo; 2768146056Sharti} 2769146056Sharti 2770146056Sharti/*- 2771146056Sharti *----------------------------------------------------------------------- 2772146056Sharti * CompatInterrupt -- 2773146056Sharti * Interrupt the creation of the current target and remove it if 2774146056Sharti * it ain't precious. 2775146056Sharti * 2776146056Sharti * Results: 2777146056Sharti * None. 2778146056Sharti * 2779146056Sharti * Side Effects: 2780146056Sharti * The target is removed and the process exits. If .INTERRUPT exists, 2781146056Sharti * its commands are run first WITH INTERRUPTS IGNORED.. 2782146056Sharti * 2783146056Sharti *----------------------------------------------------------------------- 2784146056Sharti */ 2785146056Shartistatic void 2786146056ShartiCompatInterrupt(int signo) 2787146056Sharti{ 2788146056Sharti GNode *gn; 2789146056Sharti sigset_t nmask, omask; 2790146056Sharti LstNode *ln; 2791146056Sharti 2792146056Sharti sigemptyset(&nmask); 2793146056Sharti sigaddset(&nmask, SIGINT); 2794146056Sharti sigaddset(&nmask, SIGTERM); 2795146056Sharti sigaddset(&nmask, SIGHUP); 2796146056Sharti sigaddset(&nmask, SIGQUIT); 2797146056Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 2798146056Sharti 2799146056Sharti /* prevent recursion in evaluation of .INTERRUPT */ 2800146056Sharti interrupted = 0; 2801146056Sharti 2802146056Sharti if (curTarg != NULL && !Targ_Precious(curTarg)) { 2803146581Sharti const char *file = Var_Value(TARGET, curTarg); 2804146056Sharti 2805146056Sharti if (!noExecute && eunlink(file) != -1) { 2806146056Sharti printf("*** %s removed\n", file); 2807146056Sharti } 2808146056Sharti } 2809146056Sharti 2810146056Sharti /* 2811146056Sharti * Run .INTERRUPT only if hit with interrupt signal 2812146056Sharti */ 2813146056Sharti if (signo == SIGINT) { 2814146056Sharti gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 2815146056Sharti if (gn != NULL) { 2816146056Sharti LST_FOREACH(ln, &gn->commands) { 2817228157Sfjoe if (Compat_RunCommand(ln, gn)) 2818146056Sharti break; 2819146056Sharti } 2820146056Sharti } 2821146056Sharti } 2822146056Sharti 2823146056Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 2824146056Sharti 2825146056Sharti if (signo == SIGQUIT) 2826146056Sharti exit(signo); 2827146056Sharti signal(signo, SIG_DFL); 2828146056Sharti kill(getpid(), signo); 2829146056Sharti} 2830146056Sharti 2831146129Sharti/** 2832146129Sharti * shellneed 2833146056Sharti * 2834146056Sharti * Results: 2835146129Sharti * Returns NULL if a specified line must be executed by the shell, 2836146129Sharti * and an argument vector if it can be run via execvp(). 2837146056Sharti * 2838146056Sharti * Side Effects: 2839146056Sharti * Uses brk_string so destroys the contents of argv. 2840146056Sharti */ 2841146129Shartistatic char ** 2842146345Shartishellneed(ArgArray *aa, char *cmd) 2843146056Sharti{ 2844146557Sharti char **p; 2845146557Sharti int ret; 2846146056Sharti 2847146557Sharti if (commandShell->meta == NULL || commandShell->builtins.argc <= 1) 2848146557Sharti /* use shell */ 2849146129Sharti return (NULL); 2850146129Sharti 2851146557Sharti if (strpbrk(cmd, commandShell->meta) != NULL) 2852146557Sharti return (NULL); 2853146557Sharti 2854146147Sharti /* 2855146147Sharti * Break the command into words to form an argument 2856146345Sharti * vector we can execute. 2857146147Sharti */ 2858146345Sharti brk_string(aa, cmd, TRUE); 2859146557Sharti for (p = commandShell->builtins.argv + 1; *p != 0; p++) { 2860146557Sharti if ((ret = strcmp(aa->argv[1], *p)) == 0) { 2861146557Sharti /* found - use shell */ 2862146345Sharti ArgArray_Done(aa); 2863146129Sharti return (NULL); 2864146345Sharti } 2865146557Sharti if (ret < 0) { 2866146557Sharti /* not found */ 2867146557Sharti break; 2868146557Sharti } 2869146345Sharti } 2870146345Sharti return (aa->argv + 1); 2871146056Sharti} 2872146056Sharti 2873146557Sharti/** 2874146557Sharti * Execute the next command for a target. If the command returns an 2875146557Sharti * error, the node's made field is set to ERROR and creation stops. 2876146557Sharti * The node from which the command came is also given. This is used 2877146557Sharti * to execute the commands in compat mode and when executing commands 2878146557Sharti * with the '+' flag in non-compat mode. In these modes each command 2879146557Sharti * line should be executed by its own shell. We do some optimisation here: 2880146557Sharti * if the shell description defines both a string of meta characters and 2881146557Sharti * a list of builtins and the command line neither contains a meta character 2882146557Sharti * nor starts with one of the builtins then we execute the command directly 2883146557Sharti * without invoking a shell. 2884146056Sharti * 2885146056Sharti * Results: 2886146056Sharti * 0 if the command succeeded, 1 if an error occurred. 2887146056Sharti * 2888146056Sharti * Side Effects: 2889146056Sharti * The node's 'made' field may be set to ERROR. 2890146056Sharti */ 2891146142Shartistatic int 2892228157SfjoeCompat_RunCommand(LstNode *cmdNode, GNode *gn) 2893146056Sharti{ 2894146345Sharti ArgArray aa; 2895228157Sfjoe char *cmd; /* Expanded command */ 2896146345Sharti Boolean silent; /* Don't print command */ 2897146345Sharti Boolean doit; /* Execute even in -n */ 2898146345Sharti Boolean errCheck; /* Check errors */ 2899146345Sharti int reason; /* Reason for child's death */ 2900146345Sharti int status; /* Description of child's death */ 2901146345Sharti char **av; /* Argument vector for thing to exec */ 2902146129Sharti ProcStuff ps; 2903146056Sharti 2904146056Sharti silent = gn->type & OP_SILENT; 2905146056Sharti errCheck = !(gn->type & OP_IGNORE); 2906146056Sharti doit = FALSE; 2907146056Sharti 2908228157Sfjoe cmd = Buf_Peel(Var_Subst(Lst_Datum(cmdNode), gn, FALSE)); 2909146056Sharti if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { 2910228157Sfjoe Lst_AtEnd(&ENDNode->commands, cmd); 2911146056Sharti return (0); 2912228157Sfjoe } else if (strcmp(cmd, "...") == 0) { 2913228157Sfjoe free(cmd); 2914146056Sharti gn->type |= OP_SAVE_CMDS; 2915146056Sharti return (0); 2916146056Sharti } 2917228157Sfjoe Lst_Replace(cmdNode, cmd); 2918146056Sharti 2919146056Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 2920146056Sharti switch (*cmd) { 2921146056Sharti 2922146056Sharti case '@': 2923146056Sharti silent = DEBUG(LOUD) ? FALSE : TRUE; 2924146056Sharti break; 2925146056Sharti 2926146056Sharti case '-': 2927146056Sharti errCheck = FALSE; 2928146056Sharti break; 2929146056Sharti 2930146129Sharti case '+': 2931146056Sharti doit = TRUE; 2932146056Sharti break; 2933146056Sharti } 2934146056Sharti cmd++; 2935146056Sharti } 2936146056Sharti 2937146056Sharti while (isspace((unsigned char)*cmd)) 2938146056Sharti cmd++; 2939146056Sharti 2940146056Sharti /* 2941228157Sfjoe * Ignore empty commands 2942228157Sfjoe */ 2943228157Sfjoe if (*cmd == '\0') { 2944228157Sfjoe return (0); 2945228157Sfjoe } 2946228157Sfjoe 2947228157Sfjoe /* 2948146056Sharti * Print the command before echoing if we're not supposed to be quiet 2949146056Sharti * for this one. We also print the command if -n given, but not if '+'. 2950146056Sharti */ 2951146056Sharti if (!silent || (noExecute && !doit)) { 2952146056Sharti printf("%s\n", cmd); 2953146056Sharti fflush(stdout); 2954146056Sharti } 2955146056Sharti 2956146056Sharti /* 2957146056Sharti * If we're not supposed to execute any commands, this is as far as 2958146056Sharti * we go... 2959146056Sharti */ 2960146056Sharti if (!doit && noExecute) { 2961146056Sharti return (0); 2962146056Sharti } 2963146056Sharti 2964146129Sharti ps.in = STDIN_FILENO; 2965146129Sharti ps.out = STDOUT_FILENO; 2966146129Sharti ps.err = STDERR_FILENO; 2967146056Sharti 2968146129Sharti ps.merge_errors = 0; 2969146129Sharti ps.pgroup = 0; 2970146129Sharti ps.searchpath = 1; 2971146056Sharti 2972146345Sharti if ((av = shellneed(&aa, cmd)) == NULL) { 2973146056Sharti /* 2974146129Sharti * Shell meta character or shell builtin found - pass 2975146129Sharti * command to shell. We give the shell the -e flag as 2976146129Sharti * well as -c if it is supposed to exit when it hits an error. 2977146056Sharti */ 2978146129Sharti ps.argv = emalloc(4 * sizeof(char *)); 2979146557Sharti ps.argv[0] = strdup(commandShell->path); 2980146129Sharti ps.argv[1] = strdup(errCheck ? "-ec" : "-c"); 2981146129Sharti ps.argv[2] = strdup(cmd); 2982146129Sharti ps.argv[3] = NULL; 2983146156Sharti ps.argv_free = 1; 2984146056Sharti } else { 2985146129Sharti ps.argv = av; 2986146156Sharti ps.argv_free = 0; 2987146056Sharti } 2988146156Sharti ps.errCheck = errCheck; 2989146056Sharti 2990146056Sharti /* 2991146129Sharti * Warning since we are doing vfork() instead of fork(), 2992146129Sharti * do not allocate memory in the child process! 2993146056Sharti */ 2994146130Sharti if ((ps.child_pid = vfork()) == -1) { 2995146056Sharti Fatal("Could not fork"); 2996146058Sharti 2997146130Sharti } else if (ps.child_pid == 0) { 2998146129Sharti /* 2999146129Sharti * Child 3000146129Sharti */ 3001146574Sharti Proc_Exec(&ps); 3002146129Sharti /* NOTREACHED */ 3003146129Sharti 3004146131Sharti } else { 3005146156Sharti if (ps.argv_free) { 3006146131Sharti free(ps.argv[2]); 3007146131Sharti free(ps.argv[1]); 3008146131Sharti free(ps.argv[0]); 3009146131Sharti free(ps.argv); 3010146345Sharti } else { 3011146345Sharti ArgArray_Done(&aa); 3012146131Sharti } 3013146129Sharti 3014146131Sharti /* 3015146131Sharti * we need to print out the command associated with this 3016146131Sharti * Gnode in Targ_PrintCmd from Targ_PrintGraph when debugging 3017146131Sharti * at level g2, in main(), Fatal() and DieHorribly(), 3018146131Sharti * therefore do not free it when debugging. 3019146131Sharti */ 3020146131Sharti if (!DEBUG(GRAPH2)) { 3021228157Sfjoe free(Lst_Datum(cmdNode)); 3022228157Sfjoe Lst_Replace(cmdNode, NULL); 3023146131Sharti } 3024146129Sharti 3025146131Sharti /* 3026146131Sharti * The child is off and running. Now all we can do is wait... 3027146131Sharti */ 3028146131Sharti reason = ProcWait(&ps); 3029146132Sharti 3030146056Sharti if (interrupted) 3031146056Sharti CompatInterrupt(interrupted); 3032146131Sharti 3033146132Sharti /* 3034146132Sharti * Decode and report the reason child exited, then 3035146132Sharti * indicate how we handled it. 3036146132Sharti */ 3037146131Sharti if (WIFEXITED(reason)) { 3038146131Sharti status = WEXITSTATUS(reason); 3039146131Sharti if (status == 0) { 3040146131Sharti return (0); 3041146131Sharti } else { 3042231544Sfjoe printf("*** [%s] Error code %d", 3043231544Sfjoe gn->name, status); 3044146131Sharti } 3045146131Sharti } else if (WIFSTOPPED(reason)) { 3046146131Sharti status = WSTOPSIG(reason); 3047146131Sharti } else { 3048146131Sharti status = WTERMSIG(reason); 3049231544Sfjoe printf("*** [%s] Signal %d", 3050231544Sfjoe gn->name, status); 3051146131Sharti } 3052146131Sharti 3053146156Sharti if (ps.errCheck) { 3054146131Sharti gn->made = ERROR; 3055146131Sharti if (keepgoing) { 3056146131Sharti /* 3057146131Sharti * Abort the current 3058146131Sharti * target, but let 3059146131Sharti * others continue. 3060146131Sharti */ 3061146131Sharti printf(" (continuing)\n"); 3062146056Sharti } 3063146131Sharti return (status); 3064146056Sharti } else { 3065146131Sharti /* 3066146131Sharti * Continue executing 3067146131Sharti * commands for this target. 3068146131Sharti * If we return 0, this will 3069146131Sharti * happen... 3070146131Sharti */ 3071146131Sharti printf(" (ignored)\n"); 3072146131Sharti return (0); 3073146056Sharti } 3074146056Sharti } 3075146056Sharti} 3076146056Sharti 3077146056Sharti/*- 3078146056Sharti *----------------------------------------------------------------------- 3079167330Sfjoe * Compat_Make -- 3080146056Sharti * Make a target, given the parent, to abort if necessary. 3081146056Sharti * 3082146056Sharti * Side Effects: 3083146056Sharti * If an error is detected and not being ignored, the process exits. 3084146056Sharti * 3085146056Sharti *----------------------------------------------------------------------- 3086146056Sharti */ 3087167330Sfjoeint 3088167330SfjoeCompat_Make(GNode *gn, GNode *pgn) 3089146056Sharti{ 3090146056Sharti LstNode *ln; 3091146056Sharti 3092146056Sharti if (gn->type & OP_USE) { 3093146056Sharti Make_HandleUse(gn, pgn); 3094146056Sharti 3095146056Sharti } else if (gn->made == UNMADE) { 3096146056Sharti /* 3097146056Sharti * First mark ourselves to be made, then apply whatever 3098146056Sharti * transformations the suffix module thinks are necessary. 3099146056Sharti * Once that's done, we can descend and make all our children. 3100146056Sharti * If any of them has an error but the -k flag was given, our 3101146056Sharti * 'make' field will be set FALSE again. This is our signal to 3102146056Sharti * not attempt to do anything but abort our parent as well. 3103146056Sharti */ 3104146056Sharti gn->make = TRUE; 3105146056Sharti gn->made = BEINGMADE; 3106146056Sharti Suff_FindDeps(gn); 3107146056Sharti LST_FOREACH(ln, &gn->children) 3108167330Sfjoe Compat_Make(Lst_Datum(ln), gn); 3109146056Sharti if (!gn->make) { 3110146056Sharti gn->made = ABORTED; 3111146056Sharti pgn->make = FALSE; 3112146056Sharti return (0); 3113146056Sharti } 3114146056Sharti 3115146056Sharti if (Lst_Member(&gn->iParents, pgn) != NULL) { 3116146580Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn), pgn); 3117146056Sharti } 3118146056Sharti 3119146056Sharti /* 3120146056Sharti * All the children were made ok. Now cmtime contains the 3121146056Sharti * modification time of the newest child, we need to find out 3122146056Sharti * if we exist and when we were modified last. The criteria for 3123146056Sharti * datedness are defined by the Make_OODate function. 3124146056Sharti */ 3125146056Sharti DEBUGF(MAKE, ("Examining %s...", gn->name)); 3126146056Sharti if (!Make_OODate(gn)) { 3127146056Sharti gn->made = UPTODATE; 3128146056Sharti DEBUGF(MAKE, ("up-to-date.\n")); 3129146056Sharti return (0); 3130146056Sharti } else { 3131146056Sharti DEBUGF(MAKE, ("out-of-date.\n")); 3132146056Sharti } 3133146056Sharti 3134146056Sharti /* 3135146056Sharti * If the user is just seeing if something is out-of-date, 3136146056Sharti * exit now to tell him/her "yes". 3137146056Sharti */ 3138146056Sharti if (queryFlag) { 3139146056Sharti exit(1); 3140146056Sharti } 3141146056Sharti 3142146056Sharti /* 3143146056Sharti * We need to be re-made. We also have to make sure we've got 3144146056Sharti * a $? variable. To be nice, we also define the $> variable 3145146056Sharti * using Make_DoAllVar(). 3146146056Sharti */ 3147146056Sharti Make_DoAllVar(gn); 3148146056Sharti 3149146056Sharti /* 3150146056Sharti * Alter our type to tell if errors should be ignored or things 3151146056Sharti * should not be printed so Compat_RunCommand knows what to do. 3152146056Sharti */ 3153146056Sharti if (Targ_Ignore(gn)) { 3154146056Sharti gn->type |= OP_IGNORE; 3155146056Sharti } 3156146056Sharti if (Targ_Silent(gn)) { 3157146056Sharti gn->type |= OP_SILENT; 3158146056Sharti } 3159146056Sharti 3160146056Sharti if (Job_CheckCommands(gn, Fatal)) { 3161146056Sharti /* 3162146056Sharti * Our commands are ok, but we still have to worry 3163146056Sharti * about the -t flag... 3164146056Sharti */ 3165146056Sharti if (!touchFlag) { 3166146056Sharti curTarg = gn; 3167146056Sharti LST_FOREACH(ln, &gn->commands) { 3168228157Sfjoe if (Compat_RunCommand(ln, gn)) 3169146056Sharti break; 3170146056Sharti } 3171146056Sharti curTarg = NULL; 3172146056Sharti } else { 3173146056Sharti Job_Touch(gn, gn->type & OP_SILENT); 3174146056Sharti } 3175146056Sharti } else { 3176146056Sharti gn->made = ERROR; 3177146056Sharti } 3178146056Sharti 3179146056Sharti if (gn->made != ERROR) { 3180146056Sharti /* 3181146056Sharti * If the node was made successfully, mark it so, update 3182146056Sharti * its modification time and timestamp all its parents. 3183146056Sharti * Note that for .ZEROTIME targets, the timestamping 3184146056Sharti * isn't done. This is to keep its state from affecting 3185146056Sharti * that of its parent. 3186146056Sharti */ 3187146056Sharti gn->made = MADE; 3188146056Sharti#ifndef RECHECK 3189146056Sharti /* 3190146056Sharti * We can't re-stat the thing, but we can at least take 3191146056Sharti * care of rules where a target depends on a source that 3192146056Sharti * actually creates the target, but only if it has 3193146056Sharti * changed, e.g. 3194146056Sharti * 3195146056Sharti * parse.h : parse.o 3196146056Sharti * 3197146056Sharti * parse.o : parse.y 3198146061Sharti * yacc -d parse.y 3199146061Sharti * cc -c y.tab.c 3200146061Sharti * mv y.tab.o parse.o 3201146061Sharti * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 3202146056Sharti * 3203146056Sharti * In this case, if the definitions produced by yacc 3204146056Sharti * haven't changed from before, parse.h won't have been 3205146056Sharti * updated and gn->mtime will reflect the current 3206146056Sharti * modification time for parse.h. This is something of a 3207146056Sharti * kludge, I admit, but it's a useful one.. 3208146056Sharti * 3209146056Sharti * XXX: People like to use a rule like 3210146056Sharti * 3211146056Sharti * FRC: 3212146056Sharti * 3213146056Sharti * To force things that depend on FRC to be made, so we 3214146056Sharti * have to check for gn->children being empty as well... 3215146056Sharti */ 3216146056Sharti if (!Lst_IsEmpty(&gn->commands) || 3217146056Sharti Lst_IsEmpty(&gn->children)) { 3218146056Sharti gn->mtime = now; 3219146056Sharti } 3220146056Sharti#else 3221146056Sharti /* 3222146056Sharti * This is what Make does and it's actually a good 3223146056Sharti * thing, as it allows rules like 3224146056Sharti * 3225146056Sharti * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 3226146056Sharti * 3227146056Sharti * to function as intended. Unfortunately, thanks to 3228146056Sharti * the stateless nature of NFS (and the speed of this 3229146056Sharti * program), there are times when the modification time 3230146056Sharti * of a file created on a remote machine will not be 3231146056Sharti * modified before the stat() implied by the Dir_MTime 3232146056Sharti * occurs, thus leading us to believe that the file 3233146056Sharti * is unchanged, wreaking havoc with files that depend 3234146056Sharti * on this one. 3235146056Sharti * 3236146056Sharti * I have decided it is better to make too much than to 3237146056Sharti * make too little, so this stuff is commented out 3238146056Sharti * unless you're sure it's ok. 3239146056Sharti * -- ardeb 1/12/88 3240146056Sharti */ 3241146056Sharti if (noExecute || Dir_MTime(gn) == 0) { 3242146056Sharti gn->mtime = now; 3243146056Sharti } 3244146056Sharti if (gn->cmtime > gn->mtime) 3245146056Sharti gn->mtime = gn->cmtime; 3246146056Sharti DEBUGF(MAKE, ("update time: %s\n", 3247146056Sharti Targ_FmtTime(gn->mtime))); 3248146056Sharti#endif 3249146056Sharti if (!(gn->type & OP_EXEC)) { 3250146056Sharti pgn->childMade = TRUE; 3251146056Sharti Make_TimeStamp(pgn, gn); 3252146056Sharti } 3253146056Sharti 3254146056Sharti } else if (keepgoing) { 3255146056Sharti pgn->make = FALSE; 3256146056Sharti 3257146056Sharti } else { 3258146580Sharti printf("\n\nStop in %s.\n", Var_Value(".CURDIR", gn)); 3259146056Sharti exit(1); 3260146056Sharti } 3261146056Sharti } else if (gn->made == ERROR) { 3262146056Sharti /* 3263146056Sharti * Already had an error when making this beastie. Tell the 3264146056Sharti * parent to abort. 3265146056Sharti */ 3266146056Sharti pgn->make = FALSE; 3267146056Sharti } else { 3268146056Sharti if (Lst_Member(&gn->iParents, pgn) != NULL) { 3269146580Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn), pgn); 3270146056Sharti } 3271146056Sharti switch(gn->made) { 3272146056Sharti case BEINGMADE: 3273146056Sharti Error("Graph cycles through %s\n", gn->name); 3274146056Sharti gn->made = ERROR; 3275146056Sharti pgn->make = FALSE; 3276146056Sharti break; 3277146056Sharti case MADE: 3278146056Sharti if ((gn->type & OP_EXEC) == 0) { 3279146056Sharti pgn->childMade = TRUE; 3280146056Sharti Make_TimeStamp(pgn, gn); 3281146056Sharti } 3282146056Sharti break; 3283146056Sharti case UPTODATE: 3284146056Sharti if ((gn->type & OP_EXEC) == 0) { 3285146056Sharti Make_TimeStamp(pgn, gn); 3286146056Sharti } 3287146056Sharti break; 3288146056Sharti default: 3289146056Sharti break; 3290146056Sharti } 3291146056Sharti } 3292146056Sharti 3293146056Sharti return (0); 3294146056Sharti} 3295146056Sharti 3296146056Sharti/*- 3297167330Sfjoe * Install signal handlers for Compat_Run 3298167330Sfjoe */ 3299167330Sfjoevoid 3300167330SfjoeCompat_InstallSignalHandlers(void) 3301167330Sfjoe{ 3302167330Sfjoe 3303167330Sfjoe if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 3304167330Sfjoe signal(SIGINT, CompatCatchSig); 3305167330Sfjoe } 3306167330Sfjoe if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 3307167330Sfjoe signal(SIGTERM, CompatCatchSig); 3308167330Sfjoe } 3309167330Sfjoe if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 3310167330Sfjoe signal(SIGHUP, CompatCatchSig); 3311167330Sfjoe } 3312167330Sfjoe if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 3313167330Sfjoe signal(SIGQUIT, CompatCatchSig); 3314167330Sfjoe } 3315167330Sfjoe} 3316167330Sfjoe 3317167330Sfjoe/*- 3318146056Sharti *----------------------------------------------------------------------- 3319146056Sharti * Compat_Run -- 3320146056Sharti * Start making again, given a list of target nodes. 3321146056Sharti * 3322146056Sharti * Results: 3323146056Sharti * None. 3324146056Sharti * 3325146056Sharti * Side Effects: 3326146056Sharti * Guess what? 3327146056Sharti * 3328146056Sharti *----------------------------------------------------------------------- 3329146056Sharti */ 3330146056Shartivoid 3331146056ShartiCompat_Run(Lst *targs) 3332146056Sharti{ 3333146056Sharti GNode *gn = NULL; /* Current root target */ 3334146056Sharti LstNode *ln; 3335146056Sharti 3336167330Sfjoe Compat_InstallSignalHandlers(); 3337146056Sharti ENDNode = Targ_FindNode(".END", TARG_CREATE); 3338146056Sharti /* 3339146056Sharti * If the user has defined a .BEGIN target, execute the commands 3340146056Sharti * attached to it. 3341146056Sharti */ 3342146056Sharti if (!queryFlag) { 3343146056Sharti gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); 3344146056Sharti if (gn != NULL) { 3345146056Sharti LST_FOREACH(ln, &gn->commands) { 3346228157Sfjoe if (Compat_RunCommand(ln, gn)) 3347146056Sharti break; 3348146056Sharti } 3349146056Sharti if (gn->made == ERROR) { 3350146056Sharti printf("\n\nStop.\n"); 3351146056Sharti exit(1); 3352146056Sharti } 3353146056Sharti } 3354146056Sharti } 3355146056Sharti 3356146056Sharti /* 3357167330Sfjoe * For each entry in the list of targets to create, call Compat_Make on 3358167330Sfjoe * it to create the thing. Compat_Make will leave the 'made' field of gn 3359146056Sharti * in one of several states: 3360146056Sharti * UPTODATE gn was already up-to-date 3361146056Sharti * MADE gn was recreated successfully 3362146056Sharti * ERROR An error occurred while gn was being created 3363146056Sharti * ABORTED gn was not remade because one of its inferiors 3364146056Sharti * could not be made due to errors. 3365146056Sharti */ 3366186279Sfjoe makeErrors = 0; 3367146056Sharti while (!Lst_IsEmpty(targs)) { 3368146056Sharti gn = Lst_DeQueue(targs); 3369167330Sfjoe Compat_Make(gn, gn); 3370146056Sharti 3371146056Sharti if (gn->made == UPTODATE) { 3372146056Sharti printf("`%s' is up to date.\n", gn->name); 3373146056Sharti } else if (gn->made == ABORTED) { 3374146056Sharti printf("`%s' not remade because of errors.\n", 3375146056Sharti gn->name); 3376186279Sfjoe makeErrors++; 3377198197Sfjoe } else if (gn->made == ERROR) { 3378198197Sfjoe makeErrors++; 3379146056Sharti } 3380146056Sharti } 3381146056Sharti 3382146056Sharti /* 3383146056Sharti * If the user has defined a .END target, run its commands. 3384146056Sharti */ 3385186279Sfjoe if (makeErrors == 0) { 3386146056Sharti LST_FOREACH(ln, &ENDNode->commands) { 3387228157Sfjoe if (Compat_RunCommand(ln, ENDNode)) 3388146056Sharti break; 3389146056Sharti } 3390146056Sharti } 3391146056Sharti} 3392