job.c revision 146133
1179055Sjfv/*- 2171384Sjfv * Copyright (c) 1988, 1989, 1990, 1993 3247822Sjfv * The Regents of the University of California. All rights reserved. 4171384Sjfv * Copyright (c) 1988, 1989 by Adam de Boor 5171384Sjfv * Copyright (c) 1989 by Berkeley Softworks 6171384Sjfv * All rights reserved. 7171384Sjfv * 8171384Sjfv * This code is derived from software contributed to Berkeley by 9171384Sjfv * Adam de Boor. 10171384Sjfv * 11171384Sjfv * Redistribution and use in source and binary forms, with or without 12171384Sjfv * modification, are permitted provided that the following conditions 13171384Sjfv * are met: 14171384Sjfv * 1. Redistributions of source code must retain the above copyright 15171384Sjfv * notice, this list of conditions and the following disclaimer. 16171384Sjfv * 2. Redistributions in binary form must reproduce the above copyright 17171384Sjfv * notice, this list of conditions and the following disclaimer in the 18171384Sjfv * documentation and/or other materials provided with the distribution. 19171384Sjfv * 3. All advertising materials mentioning features or use of this software 20171384Sjfv * must display the following acknowledgement: 21171384Sjfv * This product includes software developed by the University of 22171384Sjfv * California, Berkeley and its contributors. 23171384Sjfv * 4. Neither the name of the University nor the names of its contributors 24171384Sjfv * may be used to endorse or promote products derived from this software 25171384Sjfv * without specific prior written permission. 26171384Sjfv * 27171384Sjfv * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28171384Sjfv * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29171384Sjfv * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30171384Sjfv * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31171384Sjfv * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32179055Sjfv * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33179055Sjfv * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34171384Sjfv * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35171384Sjfv * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36171384Sjfv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37171384Sjfv * SUCH DAMAGE. 38251964Sjfv * 39251964Sjfv * @(#)job.c 8.2 (Berkeley) 3/19/94 40251964Sjfv */ 41251964Sjfv 42251964Sjfv#include <sys/cdefs.h> 43251964Sjfv__FBSDID("$FreeBSD: head/usr.bin/make/job.c 146133 2005-05-12 11:47:17Z harti $"); 44251964Sjfv 45251964Sjfv#ifndef OLD_JOKE 46251964Sjfv#define OLD_JOKE 0 47251964Sjfv#endif /* OLD_JOKE */ 48251964Sjfv 49251964Sjfv/*- 50251964Sjfv * job.c -- 51251964Sjfv * handle the creation etc. of our child processes. 52251964Sjfv * 53251964Sjfv * Interface: 54251964Sjfv * Job_Make Start the creation of the given target. 55251964Sjfv * 56251964Sjfv * Job_CatchChildren 57251964Sjfv * Check for and handle the termination of any children. 58251964Sjfv * This must be called reasonably frequently to keep the 59251964Sjfv * whole make going at a decent clip, since job table 60251964Sjfv * entries aren't removed until their process is caught 61251964Sjfv * this way. Its single argument is TRUE if the function 62251964Sjfv * should block waiting for a child to terminate. 63251964Sjfv * 64251964Sjfv * Job_CatchOutput Print any output our children have produced. Should 65251964Sjfv * also be called fairly frequently to keep the user 66251964Sjfv * informed of what's going on. If no output is waiting, 67251964Sjfv * it will block for a time given by the SEL_* constants, 68251964Sjfv * below, or until output is ready. 69251964Sjfv * 70251964Sjfv * Job_Init Called to intialize this module. in addition, any 71251964Sjfv * commands attached to the .BEGIN target are executed 72251964Sjfv * before this function returns. Hence, the makefile must 73251964Sjfv * have been parsed before this function is called. 74251964Sjfv * 75251964Sjfv * Job_Full Return TRUE if the job table is filled. 76171384Sjfv * 77171384Sjfv * Job_Empty Return TRUE if the job table is completely empty. 78194875Sjfv * 79251964Sjfv * Job_ParseShell Given the line following a .SHELL target, parse the 80251964Sjfv * line as a shell specification. Returns FAILURE if the 81251964Sjfv * spec was incorrect. 82171384Sjfv * 83230775Sjfv * Job_Finish Perform any final processing which needs doing. This 84230775Sjfv * includes the execution of any commands which have 85230775Sjfv * been/were attached to the .END target. It should only 86230775Sjfv * be called when the job table is empty. 87230775Sjfv * 88230775Sjfv * Job_AbortAll Abort all currently running jobs. It doesn't handle 89230775Sjfv * output or do anything for the jobs, just kills them. 90230775Sjfv * It should only be called in an emergency, as it were. 91230775Sjfv * 92230775Sjfv * Job_CheckCommands 93230775Sjfv * Verify that the commands for a target are ok. Provide 94230775Sjfv * them if necessary and possible. 95230775Sjfv * 96230775Sjfv * Job_Touch Update a target without really updating it. 97230775Sjfv * 98230775Sjfv * Job_Wait Wait for all currently-running jobs to finish. 99230775Sjfv * 100230775Sjfv * compat.c -- 101230775Sjfv * The routines in this file implement the full-compatibility 102230775Sjfv * mode of PMake. Most of the special functionality of PMake 103247822Sjfv * is available in this mode. Things not supported: 104230775Sjfv * - different shells. 105247822Sjfv * - friendly variable substitution. 106251964Sjfv * 107251964Sjfv * Interface: 108230775Sjfv * Compat_Run Initialize things for this module and recreate 109230775Sjfv * thems as need creatin' 110230775Sjfv */ 111238149Sjfv 112247822Sjfv#include <sys/queue.h> 113230775Sjfv#include <sys/types.h> 114251964Sjfv#include <sys/select.h> 115230775Sjfv#include <sys/stat.h> 116230775Sjfv#ifdef USE_KQUEUE 117230775Sjfv#include <sys/event.h> 118247822Sjfv#endif 119247822Sjfv#include <sys/wait.h> 120247822Sjfv#include <ctype.h> 121230775Sjfv#include <errno.h> 122247822Sjfv#include <fcntl.h> 123247822Sjfv#include <inttypes.h> 124171384Sjfv#include <string.h> 125171384Sjfv#include <signal.h> 126230775Sjfv#include <stdlib.h> 127230775Sjfv#include <unistd.h> 128230775Sjfv#include <utime.h> 129230775Sjfv 130230775Sjfv#include "arch.h" 131230775Sjfv#include "buf.h" 132230775Sjfv#include "config.h" 133230775Sjfv#include "dir.h" 134230775Sjfv#include "globals.h" 135230775Sjfv#include "GNode.h" 136230775Sjfv#include "job.h" 137230775Sjfv#include "make.h" 138230775Sjfv#include "parse.h" 139230775Sjfv#include "pathnames.h" 140230775Sjfv#include "str.h" 141230775Sjfv#include "suff.h" 142171384Sjfv#include "targ.h" 143171384Sjfv#include "util.h" 144230775Sjfv#include "var.h" 145230775Sjfv 146230775Sjfv#define TMPPAT "/tmp/makeXXXXXXXXXX" 147230775Sjfv 148230775Sjfv#ifndef USE_KQUEUE 149230775Sjfv/* 150230775Sjfv * The SEL_ constants determine the maximum amount of time spent in select 151230775Sjfv * before coming out to see if a child has finished. SEL_SEC is the number of 152230775Sjfv * seconds and SEL_USEC is the number of micro-seconds 153230775Sjfv */ 154230775Sjfv#define SEL_SEC 2 155230775Sjfv#define SEL_USEC 0 156230775Sjfv#endif /* !USE_KQUEUE */ 157171384Sjfv 158190873Sjfv/* 159230775Sjfv * Job Table definitions. 160230775Sjfv * 161190873Sjfv * The job "table" is kept as a linked Lst in 'jobs', with the number of 162230775Sjfv * active jobs maintained in the 'nJobs' variable. At no time will this 163230775Sjfv * exceed the value of 'maxJobs', initialized by the Job_Init function. 164190873Sjfv * 165190873Sjfv * When a job is finished, the Make_Update function is called on each of the 166230775Sjfv * parents of the node which was just remade. This takes care of the upward 167230775Sjfv * traversal of the dependency graph. 168230775Sjfv */ 169230775Sjfv#define JOB_BUFSIZE 1024 170238149Sjfvtypedef struct Job { 171190873Sjfv pid_t pid; /* The child's process ID */ 172238149Sjfv 173171384Sjfv struct GNode *node; /* The target the child is making */ 174230775Sjfv 175230775Sjfv /* 176230775Sjfv * A LstNode for the first command to be saved after the job completes. 177230775Sjfv * This is NULL if there was no "..." in the job's commands. 178230775Sjfv */ 179230775Sjfv LstNode *tailCmds; 180230775Sjfv 181230775Sjfv /* 182230775Sjfv * An FILE* for writing out the commands. This is only 183230775Sjfv * used before the job is actually started. 184190873Sjfv */ 185190873Sjfv FILE *cmdFILE; 186190873Sjfv 187190873Sjfv /* 188190873Sjfv * A word of flags which determine how the module handles errors, 189230775Sjfv * echoing, etc. for the job 190230775Sjfv */ 191230775Sjfv short flags; /* Flags to control treatment of job */ 192230775Sjfv#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ 193230775Sjfv#define JOB_SILENT 0x002 /* no output */ 194230775Sjfv#define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally 195230775Sjfv * if we can't export it and maxLocal is 0 */ 196230775Sjfv#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing 197230775Sjfv * commands */ 198230775Sjfv#define JOB_FIRST 0x020 /* Job is first job for the node */ 199230775Sjfv#define JOB_RESTART 0x080 /* Job needs to be completely restarted */ 200230775Sjfv#define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped, 201230775Sjfv * for some reason */ 202230775Sjfv#define JOB_CONTINUING 0x200 /* We are in the process of resuming this job. 203230775Sjfv * Used to avoid infinite recursion between 204230775Sjfv * JobFinish and JobRestart */ 205171384Sjfv 206171384Sjfv /* union for handling shell's output */ 207230775Sjfv union { 208230775Sjfv /* 209230775Sjfv * This part is used when usePipes is true. 210230775Sjfv * The output is being caught via a pipe and the descriptors 211230775Sjfv * of our pipe, an array in which output is line buffered and 212230775Sjfv * the current position in that buffer are all maintained for 213230775Sjfv * each job. 214230775Sjfv */ 215230775Sjfv struct { 216230775Sjfv /* 217230775Sjfv * Input side of pipe associated with 218230775Sjfv * job's output channel 219230775Sjfv */ 220171384Sjfv int op_inPipe; 221171384Sjfv 222230775Sjfv /* 223230775Sjfv * Output side of pipe associated with job's 224230775Sjfv * output channel 225230775Sjfv */ 226230775Sjfv int op_outPipe; 227230775Sjfv 228230775Sjfv /* 229230775Sjfv * Buffer for storing the output of the 230230775Sjfv * job, line by line 231230775Sjfv */ 232230775Sjfv char op_outBuf[JOB_BUFSIZE + 1]; 233230775Sjfv 234230775Sjfv /* Current position in op_outBuf */ 235230775Sjfv int op_curPos; 236230775Sjfv } o_pipe; 237230775Sjfv 238230775Sjfv /* 239230775Sjfv * If usePipes is false the output is routed to a temporary 240179055Sjfv * file and all that is kept is the name of the file and the 241179055Sjfv * descriptor open to the file. 242179055Sjfv */ 243179055Sjfv struct { 244179055Sjfv /* Name of file to which shell output was rerouted */ 245179055Sjfv char of_outFile[sizeof(TMPPAT)]; 246230775Sjfv 247230775Sjfv /* 248230775Sjfv * Stream open to the output file. Used to funnel all 249179055Sjfv * from a single job to one file while still allowing 250179055Sjfv * multiple shell invocations 251179055Sjfv */ 252179055Sjfv int of_outFd; 253179055Sjfv } o_file; 254179055Sjfv 255230775Sjfv } output; /* Data for tracking a shell's output */ 256230775Sjfv 257230775Sjfv TAILQ_ENTRY(Job) link; /* list link */ 258230775Sjfv} Job; 259230775Sjfv 260230775Sjfv#define outPipe output.o_pipe.op_outPipe 261230775Sjfv#define inPipe output.o_pipe.op_inPipe 262230775Sjfv#define outBuf output.o_pipe.op_outBuf 263230775Sjfv#define curPos output.o_pipe.op_curPos 264251964Sjfv#define outFile output.o_file.of_outFile 265171384Sjfv#define outFd output.o_file.of_outFd 266171384Sjfv 267230775SjfvTAILQ_HEAD(JobList, Job); 268230775Sjfv 269230775Sjfv/* 270230775Sjfv * Shell Specifications: 271230775Sjfv * 272205720Sjfv * Some special stuff goes on if a shell doesn't have error control. In such 273179055Sjfv * a case, errCheck becomes a printf template for echoing the command, 274230775Sjfv * should echoing be on and ignErr becomes another printf template for 275230775Sjfv * executing the command while ignoring the return status. If either of these 276230775Sjfv * strings is empty when hasErrCtl is FALSE, the command will be executed 277230775Sjfv * anyway as is and if it causes an error, so be it. 278230775Sjfv */ 279230775Sjfv#define DEF_SHELL_STRUCT(TAG, CONST) \ 280230775Sjfvstruct TAG { \ 281179055Sjfv /* \ 282230775Sjfv * the name of the shell. For Bourne and C shells, this is used \ 283230775Sjfv * only to find the shell description when used as the single \ 284179055Sjfv * source of a .SHELL target. For user-defined shells, this is \ 285230775Sjfv * the full path of the shell. \ 286179055Sjfv */ \ 287230775Sjfv CONST char *name; \ 288230775Sjfv \ 289230775Sjfv /* True if both echoOff and echoOn defined */ \ 290230775Sjfv Boolean hasEchoCtl; \ 291230775Sjfv \ 292230775Sjfv CONST char *echoOff; /* command to turn off echo */ \ 293230775Sjfv CONST char *echoOn; /* command to turn it back on */\ 294230775Sjfv \ 295230775Sjfv /* \ 296230775Sjfv * What the shell prints, and its length, when given the \ 297230775Sjfv * echo-off command. This line will not be printed when \ 298230775Sjfv * received from the shell. This is usually the command which \ 299230775Sjfv * was executed to turn off echoing \ 300230775Sjfv */ \ 301230775Sjfv CONST char *noPrint; \ 302230775Sjfv \ 303230775Sjfv /* set if can control error checking for individual commands */ \ 304230775Sjfv Boolean hasErrCtl; \ 305230775Sjfv \ 306230775Sjfv /* string to turn error checking on */ \ 307230775Sjfv CONST char *errCheck; \ 308230775Sjfv \ 309230775Sjfv /* string to turn off error checking */ \ 310230775Sjfv CONST char *ignErr; \ 311230775Sjfv \ 312230775Sjfv CONST char *echo; /* command line flag: echo commands */ \ 313230775Sjfv CONST char *exit; /* command line flag: exit on error */ \ 314230775Sjfv} 315230775Sjfv 316230775SjfvDEF_SHELL_STRUCT(Shell,); 317230775SjfvDEF_SHELL_STRUCT(CShell, const); 318230775Sjfv 319230775Sjfv/* 320230775Sjfv * error handling variables 321230775Sjfv */ 322230775Sjfvstatic int errors = 0; /* number of errors reported */ 323230775Sjfvstatic int aborting = 0; /* why is the make aborting? */ 324230775Sjfv#define ABORT_ERROR 1 /* Because of an error */ 325230775Sjfv#define ABORT_INTERRUPT 2 /* Because it was interrupted */ 326230775Sjfv#define ABORT_WAIT 3 /* Waiting for jobs to finish */ 327230775Sjfv 328230775Sjfv/* 329171384Sjfv * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file 330247822Sjfv * is a char! So when we go above 127 we turn negative! 331190873Sjfv */ 332230775Sjfv#define FILENO(a) ((unsigned)fileno(a)) 333230775Sjfv 334230775Sjfv/* 335230775Sjfv * post-make command processing. The node postCommands is really just the 336230775Sjfv * .END target but we keep it around to avoid having to search for it 337230775Sjfv * all the time. 338230775Sjfv */ 339230775Sjfvstatic GNode *postCommands; 340230775Sjfv 341179055Sjfv/* 342190873Sjfv * The number of commands actually printed for a target. Should this 343230775Sjfv * number be 0, no shell will be executed. 344230775Sjfv */ 345230775Sjfvstatic int numCommands; 346230775Sjfv 347230775Sjfv/* 348230775Sjfv * Return values from JobStart. 349190873Sjfv */ 350190873Sjfv#define JOB_RUNNING 0 /* Job is running */ 351190873Sjfv#define JOB_ERROR 1 /* Error in starting the job */ 352230775Sjfv#define JOB_FINISHED 2 /* The job is already finished */ 353230775Sjfv#define JOB_STOPPED 3 /* The job is stopped */ 354230775Sjfv 355230775Sjfv/* 356230775Sjfv * Descriptions for various shells. 357230775Sjfv */ 358190873Sjfvstatic const struct CShell shells[] = { 359171384Sjfv /* 360230775Sjfv * CSH description. The csh can do echo control by playing 361230775Sjfv * with the setting of the 'echo' shell variable. Sadly, 362230775Sjfv * however, it is unable to do error control nicely. 363230775Sjfv */ 364230775Sjfv { 365230775Sjfv "csh", 366230775Sjfv TRUE, "unset verbose", "set verbose", "unset verbose", 367230775Sjfv FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", 368230775Sjfv "v", "e", 369179055Sjfv }, 370230775Sjfv /* 371230775Sjfv * SH description. Echo control is also possible and, under 372230775Sjfv * sun UNIX anyway, one can even control error checking. 373230775Sjfv */ 374230775Sjfv { 375230775Sjfv "sh", 376230775Sjfv TRUE, "set -", "set -v", "set -", 377230775Sjfv TRUE, "set -e", "set +e", 378190873Sjfv#ifdef OLDBOURNESHELL 379230775Sjfv FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", 380230775Sjfv#endif 381230775Sjfv "v", "e", 382230775Sjfv }, 383194875Sjfv /* 384230775Sjfv * KSH description. The Korn shell has a superset of 385215911Sjfv * the Bourne shell's functionality. 386215911Sjfv */ 387230775Sjfv { 388230775Sjfv "ksh", 389230775Sjfv TRUE, "set -", "set -v", "set -", 390230775Sjfv TRUE, "set -e", "set +e", 391230775Sjfv "v", "e", 392230775Sjfv }, 393190873Sjfv}; 394230775Sjfv 395230775Sjfv/* 396230775Sjfv * This is the shell to which we pass all commands in the Makefile. 397230775Sjfv * It is set by the Job_ParseShell function. 398230775Sjfv */ 399230775Sjfvstatic struct Shell *commandShell = NULL; 400171384Sjfvstatic char *shellPath = NULL; /* full pathname of executable image */ 401171384Sjfvstatic char *shellName = NULL; /* last component of shell */ 402230775Sjfv 403230775Sjfvint maxJobs; /* The most children we can run at once */ 404230775Sjfvstatic int nJobs; /* The number of children currently running */ 405230775Sjfv 406230775Sjfv/* The structures that describe them */ 407230775Sjfvstatic struct JobList jobs = TAILQ_HEAD_INITIALIZER(jobs); 408185352Sjfv 409230775Sjfvstatic Boolean jobFull; /* Flag to tell when the job table is full. It 410230775Sjfv * is set TRUE when (1) the total number of 411247822Sjfv * running jobs equals the maximum allowed */ 412230775Sjfv#ifdef USE_KQUEUE 413230775Sjfvstatic int kqfd; /* File descriptor obtained by kqueue() */ 414230775Sjfv#else 415171384Sjfvstatic fd_set outputs; /* Set of descriptors of pipes connected to 416247822Sjfv * the output channels of children */ 417230775Sjfv#endif 418247822Sjfv 419247822Sjfvstatic GNode *lastNode; /* The node for which output was most recently 420247822Sjfv * produced. */ 421230775Sjfvstatic const char *targFmt; /* Format string to use to head output from a 422185352Sjfv * job when it's not the most-recent job heard 423185352Sjfv * from */ 424230775Sjfv 425230775Sjfv#define TARG_FMT "--- %s ---\n" /* Default format */ 426230775Sjfv#define MESSAGE(fp, gn) \ 427185352Sjfv fprintf(fp, targFmt, gn->name); 428185352Sjfv 429185352Sjfv/* 430230775Sjfv * When JobStart attempts to run a job but isn't allowed to 431230775Sjfv * or when Job_CatchChildren detects a job that has 432230775Sjfv * been stopped somehow, the job is placed on the stoppedJobs queue to be run 433185352Sjfv * when the next job finishes. 434185352Sjfv * 435230775Sjfv * Lst of Job structures describing jobs that were stopped due to 436230775Sjfv * concurrency limits or externally 437230775Sjfv */ 438230775Sjfvstatic struct JobList stoppedJobs = TAILQ_HEAD_INITIALIZER(stoppedJobs); 439230775Sjfv 440230775Sjfvstatic int fifoFd; /* Fd of our job fifo */ 441230775Sjfvstatic char fifoName[] = "/tmp/make_fifo_XXXXXXXXX"; 442230775Sjfvstatic int fifoMaster; 443230775Sjfv 444185352Sjfvstatic sig_atomic_t interrupted; 445230775Sjfv 446230775Sjfv 447230775Sjfv#if defined(USE_PGRP) && defined(SYSV) 448230775Sjfv# define KILL(pid, sig) killpg(-(pid), (sig)) 449230775Sjfv#else 450230775Sjfv# if defined(USE_PGRP) 451230775Sjfv# define KILL(pid, sig) killpg((pid), (sig)) 452247822Sjfv# else 453230775Sjfv# define KILL(pid, sig) kill((pid), (sig)) 454230775Sjfv# endif 455247822Sjfv#endif 456247822Sjfv 457230775Sjfv/* 458185352Sjfv * Grmpf... There is no way to set bits of the wait structure 459185352Sjfv * anymore with the stupid W*() macros. I liked the union wait 460230775Sjfv * stuff much more. So, we devise our own macros... This is 461230775Sjfv * really ugly, use dramamine sparingly. You have been warned. 462230775Sjfv */ 463230775Sjfv#define W_SETMASKED(st, val, fun) \ 464230775Sjfv { \ 465230775Sjfv int sh = (int)~0; \ 466230775Sjfv int mask = fun(sh); \ 467230775Sjfv \ 468230775Sjfv for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ 469230775Sjfv continue; \ 470230775Sjfv *(st) = (*(st) & ~mask) | ((val) << sh); \ 471230775Sjfv } 472230775Sjfv 473230775Sjfv#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) 474230775Sjfv#define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) 475230775Sjfv 476185352Sjfv/** 477230775Sjfv * Information used to create a new process. 478185352Sjfv */ 479185352Sjfvtypedef struct ProcStuff { 480230775Sjfv int in; /* stdin for new process */ 481230775Sjfv int out; /* stdout for new process */ 482230775Sjfv int err; /* stderr for new process */ 483230775Sjfv 484230775Sjfv int merge_errors; /* true if stderr is redirected to stdin */ 485230775Sjfv int pgroup; /* true if new process a process leader */ 486230775Sjfv int searchpath; /* true if binary should be found via $PATH */ 487230775Sjfv 488230775Sjfv char **argv; 489230775Sjfv 490230775Sjfv pid_t child_pid; 491171384Sjfv} ProcStuff; 492179055Sjfv 493251964Sjfvstatic void JobRestart(Job *); 494190873Sjfvstatic int JobStart(GNode *, int, Job *); 495230775Sjfvstatic void JobDoOutput(Job *, Boolean); 496230775Sjfvstatic struct Shell *JobMatchShell(const char *); 497230775Sjfvstatic void JobInterrupt(int, int); 498230775Sjfvstatic void JobRestartJobs(void); 499230775Sjfvstatic void ProcExec(const ProcStuff *) __dead2; 500230775Sjfv 501179055Sjfv/* 502190873Sjfv * The following array is used to make a fast determination of which 503230775Sjfv * commands and characters are interpreted specially by the shell. 504230775Sjfv * If a command is one of these or contains any of these characters, 505230775Sjfv * it is executed by the shell, not directly by us. 506190873Sjfv * XXX Both of these arrays should be configurable via .SHELL 507230775Sjfv */ 508230775Sjfvstatic const char const* sh_builtin[] = { 509190873Sjfv "alias", "cd", "eval", "exec", 510230775Sjfv "exit", "read", "set", "ulimit", 511230775Sjfv "unalias", "umask", "unset", "wait", 512190873Sjfv ":", NULL 513230775Sjfv}; 514230775Sjfvstatic const char *sh_meta = "#=|^(){};&<>*?[]:$`\\\n"; 515190873Sjfv 516190873Sjfvstatic GNode *curTarg = NULL; 517230775Sjfvstatic GNode *ENDNode; 518230775Sjfv 519230775Sjfv/** 520230775Sjfv * Replace the current process. 521230775Sjfv */ 522230775Sjfvstatic void 523230775SjfvProcExec(const ProcStuff *ps) 524230775Sjfv{ 525230775Sjfv 526230775Sjfv if (ps->in != STDIN_FILENO) { 527230775Sjfv /* 528230775Sjfv * Redirect the child's stdin to the input fd 529230775Sjfv * and reset it to the beginning (again). 530230775Sjfv */ 531230775Sjfv if (dup2(ps->in, STDIN_FILENO) == -1) 532230775Sjfv Punt("Cannot dup2: %s", strerror(errno)); 533230775Sjfv lseek(STDIN_FILENO, (off_t)0, SEEK_SET); 534230775Sjfv } 535230775Sjfv 536230775Sjfv if (ps->out != STDOUT_FILENO) { 537230775Sjfv /* 538230775Sjfv * Redirect the child's stdout to the output fd. 539230775Sjfv */ 540230775Sjfv if (dup2(ps->out, STDOUT_FILENO) == -1) 541230775Sjfv Punt("Cannot dup2: %s", strerror(errno)); 542230775Sjfv close(ps->out); 543230775Sjfv } 544230775Sjfv 545230775Sjfv if (ps->err != STDERR_FILENO) { 546230775Sjfv /* 547230775Sjfv * Redirect the child's stderr to the err fd. 548230775Sjfv */ 549230775Sjfv if (dup2(ps->err, STDERR_FILENO) == -1) 550230775Sjfv Punt("Cannot dup2: %s", strerror(errno)); 551230775Sjfv close(ps->err); 552190873Sjfv } 553190873Sjfv 554230775Sjfv if (ps->merge_errors) { 555230775Sjfv /* 556230775Sjfv * Send stderr to parent process too. 557230775Sjfv */ 558190873Sjfv if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 559230775Sjfv Punt("Cannot dup2: %s", strerror(errno)); 560230775Sjfv } 561230775Sjfv 562230775Sjfv /* 563230775Sjfv * The file descriptors for stdin, stdout, or stderr might 564230775Sjfv * have been marked close-on-exec. Clear the flag on all 565230775Sjfv * of them. 566190873Sjfv */ 567230775Sjfv fcntl(STDIN_FILENO, F_SETFD, 568230775Sjfv fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC)); 569230775Sjfv fcntl(STDOUT_FILENO, F_SETFD, 570230775Sjfv fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC)); 571230775Sjfv fcntl(STDERR_FILENO, F_SETFD, 572230775Sjfv fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC)); 573230775Sjfv 574230775Sjfv if (ps->pgroup) { 575230775Sjfv#ifdef USE_PGRP 576190873Sjfv /* 577190873Sjfv * Become a process group leader, so we can kill it and all 578230775Sjfv * its descendants in one fell swoop, by killing its process 579230775Sjfv * family, but not commit suicide. 580230775Sjfv */ 581230775Sjfv#if defined(SYSV) 582230775Sjfv setsid(); 583230775Sjfv#else 584230775Sjfv setpgid(0, getpid()); 585230775Sjfv#endif 586230775Sjfv#endif /* USE_PGRP */ 587230775Sjfv } 588190873Sjfv 589230775Sjfv if (ps->searchpath) { 590190873Sjfv execvp(ps->argv[0], ps->argv); 591190873Sjfv 592230775Sjfv write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0])); 593230775Sjfv write(STDERR_FILENO, ":", 1); 594230775Sjfv write(STDERR_FILENO, strerror(errno), strlen(strerror(errno))); 595230775Sjfv write(STDERR_FILENO, "\n", 1); 596230775Sjfv } else { 597230775Sjfv execv(shellPath, ps->argv); 598230775Sjfv 599230775Sjfv write(STDERR_FILENO, 600230775Sjfv "Could not execute shell\n", 601230775Sjfv sizeof("Could not execute shell")); 602230775Sjfv } 603230775Sjfv 604230775Sjfv /* 605230775Sjfv * Since we are the child process, exit without flushing buffers. 606230775Sjfv */ 607230775Sjfv _exit(1); 608230775Sjfv /* NOTREACHED */ 609230775Sjfv} 610190873Sjfv 611230775Sjfv/** 612230775Sjfv * Wait for child process to terminate. 613230775Sjfv */ 614230775Sjfvstatic int 615217593SjfvProcWait(ProcStuff *ps) 616217593Sjfv{ 617230775Sjfv pid_t pid; 618190873Sjfv int status; 619190873Sjfv 620230775Sjfv /* 621230775Sjfv * Wait for the process to exit. 622230775Sjfv */ 623230775Sjfv for (;;) { 624230775Sjfv pid = wait(&status); 625230775Sjfv if (pid == -1 && errno != EINTR) { 626230775Sjfv Fatal("error in wait: %d", pid); 627230775Sjfv /* NOTREACHED */ 628230775Sjfv } 629230775Sjfv if (pid == ps->child_pid) { 630190873Sjfv break; 631247822Sjfv } 632190873Sjfv if (interrupted) { 633230775Sjfv break; 634230775Sjfv } 635230775Sjfv } 636230775Sjfv 637230775Sjfv return (status); 638230775Sjfv} 639230775Sjfv 640230775Sjfv/** 641230775Sjfv * JobCatchSignal 642230775Sjfv * Got a signal. Set global variables and hope that someone will 643230775Sjfv * handle it. 644230775Sjfv */ 645230775Sjfvstatic void 646230775SjfvJobCatchSig(int signo) 647230775Sjfv{ 648230775Sjfv 649230775Sjfv interrupted = signo; 650190873Sjfv} 651230775Sjfv 652230775Sjfv/** 653230775Sjfv * JobPassSig -- 654230775Sjfv * Pass a signal on to all local jobs if 655190873Sjfv * USE_PGRP is defined, then die ourselves. 656230775Sjfv * 657230775Sjfv * Side Effects: 658230775Sjfv * We die by the same signal. 659230775Sjfv */ 660230775Sjfvstatic void 661230775SjfvJobPassSig(int signo) 662230775Sjfv{ 663230775Sjfv Job *job; 664230775Sjfv sigset_t nmask, omask; 665230775Sjfv struct sigaction act; 666190873Sjfv 667230775Sjfv sigemptyset(&nmask); 668230775Sjfv sigaddset(&nmask, signo); 669230775Sjfv sigprocmask(SIG_SETMASK, &nmask, &omask); 670230775Sjfv 671230775Sjfv DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo)); 672230775Sjfv TAILQ_FOREACH(job, &jobs, link) { 673230775Sjfv DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 674230775Sjfv signo, (intmax_t)job->pid)); 675230775Sjfv KILL(job->pid, signo); 676230775Sjfv } 677230775Sjfv 678190873Sjfv /* 679230775Sjfv * Deal with proper cleanup based on the signal received. We only run 680230775Sjfv * the .INTERRUPT target if the signal was in fact an interrupt. 681230775Sjfv * The other three termination signals are more of a "get out *now*" 682230775Sjfv * command. 683230775Sjfv */ 684230775Sjfv if (signo == SIGINT) { 685230775Sjfv JobInterrupt(TRUE, signo); 686190873Sjfv } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { 687171384Sjfv JobInterrupt(FALSE, signo); 688230775Sjfv } 689230775Sjfv 690230775Sjfv /* 691230775Sjfv * Leave gracefully if SIGQUIT, rather than core dumping. 692230775Sjfv */ 693230775Sjfv if (signo == SIGQUIT) { 694230775Sjfv signo = SIGINT; 695230775Sjfv } 696230775Sjfv 697230775Sjfv /* 698230775Sjfv * Send ourselves the signal now we've given the message to everyone 699230775Sjfv * else. Note we block everything else possible while we're getting 700230775Sjfv * the signal. This ensures that all our jobs get continued when we 701230775Sjfv * wake up before we take any other signal. 702230775Sjfv * XXX this comment seems wrong. 703230775Sjfv */ 704230775Sjfv act.sa_handler = SIG_DFL; 705230775Sjfv sigemptyset(&act.sa_mask); 706230775Sjfv act.sa_flags = 0; 707230775Sjfv sigaction(signo, &act, NULL); 708230775Sjfv 709230775Sjfv DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n", 710230775Sjfv ~0 & ~(1 << (signo - 1)))); 711230775Sjfv signal(signo, SIG_DFL); 712230775Sjfv 713230775Sjfv KILL(getpid(), signo); 714230775Sjfv 715230775Sjfv signo = SIGCONT; 716230775Sjfv TAILQ_FOREACH(job, &jobs, link) { 717230775Sjfv DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 718230775Sjfv signo, (intmax_t)job->pid)); 719230775Sjfv KILL(job->pid, signo); 720230775Sjfv } 721230775Sjfv 722230775Sjfv sigprocmask(SIG_SETMASK, &omask, NULL); 723230775Sjfv sigprocmask(SIG_SETMASK, &omask, NULL); 724230775Sjfv act.sa_handler = JobPassSig; 725230775Sjfv sigaction(signo, &act, NULL); 726230775Sjfv} 727230775Sjfv 728230775Sjfv/** 729230775Sjfv * JobPrintCommand -- 730230775Sjfv * Put out another command for the given job. If the command starts 731230775Sjfv * with an @ or a - we process it specially. In the former case, 732230775Sjfv * so long as the -s and -n flags weren't given to make, we stick 733230775Sjfv * a shell-specific echoOff command in the script. In the latter, 734230775Sjfv * we ignore errors for the entire job, unless the shell has error 735230775Sjfv * control. 736230775Sjfv * If the command is just "..." we take all future commands for this 737230775Sjfv * job to be commands to be executed once the entire graph has been 738230775Sjfv * made and return non-zero to signal that the end of the commands 739230775Sjfv * was reached. These commands are later attached to the postCommands 740230775Sjfv * node and executed by Job_Finish when all things are done. 741230775Sjfv * This function is called from JobStart via LST_FOREACH. 742230775Sjfv * 743230775Sjfv * Results: 744230775Sjfv * Always 0, unless the command was "..." 745171384Sjfv * 746230775Sjfv * Side Effects: 747230775Sjfv * If the command begins with a '-' and the shell has no error control, 748230775Sjfv * the JOB_IGNERR flag is set in the job descriptor. 749230775Sjfv * If the command is "..." and we're not ignoring such things, 750171384Sjfv * tailCmds is set to the successor node of the cmd. 751230775Sjfv * numCommands is incremented if the command is actually printed. 752230775Sjfv */ 753230775Sjfvstatic int 754230775SjfvJobPrintCommand(char *cmd, Job *job) 755230775Sjfv{ 756230775Sjfv Boolean noSpecials; /* true if we shouldn't worry about 757230775Sjfv * inserting special commands into 758230775Sjfv * the input stream. */ 759230775Sjfv Boolean shutUp = FALSE; /* true if we put a no echo command 760230775Sjfv * into the command file */ 761230775Sjfv Boolean errOff = FALSE; /* true if we turned error checking 762230775Sjfv * off before printing the command 763230775Sjfv * and need to turn it back on */ 764230775Sjfv const char *cmdTemplate;/* Template to use when printing the command */ 765230775Sjfv char *cmdStart; /* Start of expanded command */ 766230775Sjfv LstNode *cmdNode; /* Node for replacing the command */ 767230775Sjfv 768230775Sjfv noSpecials = (noExecute && !(job->node->type & OP_MAKE)); 769230775Sjfv 770230775Sjfv if (strcmp(cmd, "...") == 0) { 771230775Sjfv job->node->type |= OP_SAVE_CMDS; 772230775Sjfv if ((job->flags & JOB_IGNDOTS) == 0) { 773230775Sjfv job->tailCmds = 774230775Sjfv Lst_Succ(Lst_Member(&job->node->commands, cmd)); 775230775Sjfv return (1); 776230775Sjfv } 777230775Sjfv return (0); 778230775Sjfv } 779230775Sjfv 780230775Sjfv#define DBPRINTF(fmt, arg) \ 781230775Sjfv DEBUGF(JOB, (fmt, arg)); \ 782230775Sjfv fprintf(job->cmdFILE, fmt, arg); \ 783230775Sjfv fflush(job->cmdFILE); 784230775Sjfv 785230775Sjfv numCommands += 1; 786230775Sjfv 787230775Sjfv /* 788230775Sjfv * For debugging, we replace each command with the result of expanding 789171384Sjfv * the variables in the command. 790171384Sjfv */ 791230775Sjfv cmdNode = Lst_Member(&job->node->commands, cmd); 792230775Sjfv 793230775Sjfv cmd = Buf_Peel(Var_Subst(cmd, job->node, FALSE)); 794230775Sjfv cmdStart = cmd; 795230775Sjfv 796230775Sjfv Lst_Replace(cmdNode, cmdStart); 797230775Sjfv 798230775Sjfv cmdTemplate = "%s\n"; 799230775Sjfv 800230775Sjfv /* 801230775Sjfv * Check for leading @', -' or +'s to control echoing, error checking, 802230775Sjfv * and execution on -n. 803230775Sjfv */ 804230775Sjfv while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 805230775Sjfv switch (*cmd) { 806230775Sjfv 807230775Sjfv case '@': 808171384Sjfv shutUp = DEBUG(LOUD) ? FALSE : TRUE; 809230775Sjfv break; 810247822Sjfv 811230775Sjfv case '-': 812230775Sjfv errOff = TRUE; 813230775Sjfv break; 814230775Sjfv 815230775Sjfv case '+': 816247822Sjfv if (noSpecials) { 817247822Sjfv /* 818230775Sjfv * We're not actually exececuting anything... 819171384Sjfv * but this one needs to be - use compat mode 820230775Sjfv * just for it. 821230775Sjfv */ 822230775Sjfv Compat_RunCommand(cmd, job->node); 823230775Sjfv return (0); 824230775Sjfv } 825230775Sjfv break; 826230775Sjfv } 827171384Sjfv cmd++; 828230775Sjfv } 829230775Sjfv 830230775Sjfv while (isspace((unsigned char)*cmd)) 831230775Sjfv cmd++; 832230775Sjfv 833230775Sjfv if (shutUp) { 834230775Sjfv if (!(job->flags & JOB_SILENT) && !noSpecials && 835171384Sjfv commandShell->hasEchoCtl) { 836230775Sjfv DBPRINTF("%s\n", commandShell->echoOff); 837230775Sjfv } else { 838230775Sjfv shutUp = FALSE; 839230775Sjfv } 840230775Sjfv } 841230775Sjfv 842230775Sjfv if (errOff) { 843230775Sjfv if (!(job->flags & JOB_IGNERR) && !noSpecials) { 844230775Sjfv if (commandShell->hasErrCtl) { 845230775Sjfv /* 846230775Sjfv * We don't want the error-control commands 847230775Sjfv * showing up either, so we turn off echoing 848230775Sjfv * while executing them. We could put another 849230775Sjfv * field in the shell structure to tell 850230775Sjfv * JobDoOutput to look for this string too, 851230775Sjfv * but why make it any more complex than 852230775Sjfv * it already is? 853230775Sjfv */ 854230775Sjfv if (!(job->flags & JOB_SILENT) && !shutUp && 855230775Sjfv commandShell->hasEchoCtl) { 856230775Sjfv DBPRINTF("%s\n", commandShell->echoOff); 857230775Sjfv DBPRINTF("%s\n", commandShell->ignErr); 858230775Sjfv DBPRINTF("%s\n", commandShell->echoOn); 859171384Sjfv } else { 860190873Sjfv DBPRINTF("%s\n", commandShell->ignErr); 861230775Sjfv } 862230775Sjfv } else if (commandShell->ignErr && 863230775Sjfv *commandShell->ignErr != '\0') { 864230775Sjfv /* 865230775Sjfv * The shell has no error control, so we need to 866230775Sjfv * be weird to get it to ignore any errors from 867230775Sjfv * the command. If echoing is turned on, we turn 868230775Sjfv * it off and use the errCheck template to echo 869230775Sjfv * the command. Leave echoing off so the user 870230775Sjfv * doesn't see the weirdness we go through to 871230775Sjfv * ignore errors. Set cmdTemplate to use the 872230775Sjfv * weirdness instead of the simple "%s\n" 873230775Sjfv * template. 874230775Sjfv */ 875230775Sjfv if (!(job->flags & JOB_SILENT) && !shutUp && 876230775Sjfv commandShell->hasEchoCtl) { 877230775Sjfv DBPRINTF("%s\n", commandShell->echoOff); 878230775Sjfv DBPRINTF(commandShell->errCheck, cmd); 879230775Sjfv shutUp = TRUE; 880230775Sjfv } 881190873Sjfv cmdTemplate = commandShell->ignErr; 882200239Sjfv /* 883230775Sjfv * The error ignoration (hee hee) is already 884230775Sjfv * taken care of by the ignErr template, so 885230775Sjfv * pretend error checking is still on. 886230775Sjfv */ 887200239Sjfv errOff = FALSE; 888230775Sjfv } else { 889230775Sjfv errOff = FALSE; 890230775Sjfv } 891230775Sjfv } else { 892230775Sjfv errOff = FALSE; 893230775Sjfv } 894230775Sjfv } 895238149Sjfv 896190873Sjfv DBPRINTF(cmdTemplate, cmd); 897230775Sjfv 898230775Sjfv if (errOff) { 899230775Sjfv /* 900230775Sjfv * If echoing is already off, there's no point in issuing the 901230775Sjfv * echoOff command. Otherwise we issue it and pretend it was on 902230775Sjfv * for the whole command... 903230775Sjfv */ 904230775Sjfv if (!shutUp && !(job->flags & JOB_SILENT) && 905230775Sjfv commandShell->hasEchoCtl) { 906230775Sjfv DBPRINTF("%s\n", commandShell->echoOff); 907230775Sjfv shutUp = TRUE; 908230775Sjfv } 909230775Sjfv DBPRINTF("%s\n", commandShell->errCheck); 910230775Sjfv } 911230775Sjfv if (shutUp) { 912230775Sjfv DBPRINTF("%s\n", commandShell->echoOn); 913230775Sjfv } 914230775Sjfv return (0); 915230775Sjfv} 916238149Sjfv 917238149Sjfv/** 918230775Sjfv * JobClose -- 919230775Sjfv * Called to close both input and output pipes when a job is finished. 920230775Sjfv * 921230775Sjfv * Side Effects: 922230775Sjfv * The file descriptors associated with the job are closed. 923230775Sjfv */ 924190873Sjfvstatic void 925171384SjfvJobClose(Job *job) 926230775Sjfv{ 927230775Sjfv 928230775Sjfv if (usePipes) { 929230775Sjfv#if !defined(USE_KQUEUE) 930230775Sjfv FD_CLR(job->inPipe, &outputs); 931230775Sjfv#endif 932230775Sjfv if (job->outPipe != job->inPipe) { 933230775Sjfv close(job->outPipe); 934230775Sjfv } 935230775Sjfv JobDoOutput(job, TRUE); 936230775Sjfv close(job->inPipe); 937230775Sjfv } else { 938230775Sjfv close(job->outFd); 939230775Sjfv JobDoOutput(job, TRUE); 940230775Sjfv } 941230775Sjfv} 942230775Sjfv 943230775Sjfv/** 944230775Sjfv * JobFinish -- 945230775Sjfv * Do final processing for the given job including updating 946230775Sjfv * parents and starting new jobs as available/necessary. Note 947230775Sjfv * that we pay no attention to the JOB_IGNERR flag here. 948230775Sjfv * This is because when we're called because of a noexecute flag 949230775Sjfv * or something, jstat.w_status is 0 and when called from 950230775Sjfv * Job_CatchChildren, the status is zeroed if it s/b ignored. 951230775Sjfv * 952230775Sjfv * Side Effects: 953230775Sjfv * Some nodes may be put on the toBeMade queue. 954230775Sjfv * Final commands for the job are placed on postCommands. 955230775Sjfv * 956230775Sjfv * If we got an error and are aborting (aborting == ABORT_ERROR) and 957230775Sjfv * the job list is now empty, we are done for the day. 958230775Sjfv * If we recognized an error (errors !=0), we set the aborting flag 959230775Sjfv * to ABORT_ERROR so no more jobs will be started. 960230775Sjfv */ 961230775Sjfvstatic void 962230775SjfvJobFinish(Job *job, int *status) 963230775Sjfv{ 964230775Sjfv Boolean done; 965230775Sjfv LstNode *ln; 966230775Sjfv 967230775Sjfv if (WIFEXITED(*status)) { 968230775Sjfv int job_status = WEXITSTATUS(*status); 969230775Sjfv 970230775Sjfv JobClose(job); 971230775Sjfv /* 972230775Sjfv * Deal with ignored errors in -B mode. We need to 973230775Sjfv * print a message telling of the ignored error as 974230775Sjfv * well as setting status.w_status to 0 so the next 975230775Sjfv * command gets run. To do this, we set done to be 976230775Sjfv * TRUE if in -B mode and the job exited non-zero. 977230775Sjfv */ 978230775Sjfv if (job_status == 0) { 979230775Sjfv done = FALSE; 980230775Sjfv } else { 981230775Sjfv if (job->flags & JOB_IGNERR) { 982171384Sjfv done = TRUE; 983171384Sjfv } else { 984230775Sjfv /* 985230775Sjfv * If it exited non-zero and either we're 986230775Sjfv * doing things our way or we're not ignoring 987230775Sjfv * errors, the job is finished. Similarly, if 988230775Sjfv * the shell died because of a signal the job 989230775Sjfv * is also finished. In these cases, finish 990230775Sjfv * out the job's output before printing the 991230775Sjfv * exit status... 992230775Sjfv */ 993230775Sjfv done = TRUE; 994230775Sjfv if (job->cmdFILE != NULL && 995230775Sjfv job->cmdFILE != stdout) { 996230775Sjfv fclose(job->cmdFILE); 997230775Sjfv } 998230775Sjfv 999230775Sjfv } 1000230775Sjfv } 1001230775Sjfv } else if (WIFSIGNALED(*status)) { 1002230775Sjfv if (WTERMSIG(*status) == SIGCONT) { 1003230775Sjfv /* 1004230775Sjfv * No need to close things down or anything. 1005230775Sjfv */ 1006230775Sjfv done = FALSE; 1007230775Sjfv } else { 1008230775Sjfv /* 1009230775Sjfv * If it exited non-zero and either we're 1010230775Sjfv * doing things our way or we're not ignoring 1011230775Sjfv * errors, the job is finished. Similarly, if 1012230775Sjfv * the shell died because of a signal the job 1013230775Sjfv * is also finished. In these cases, finish 1014230775Sjfv * out the job's output before printing the 1015230775Sjfv * exit status... 1016230775Sjfv */ 1017230775Sjfv JobClose(job); 1018230775Sjfv if (job->cmdFILE != NULL && 1019230775Sjfv job->cmdFILE != stdout) { 1020230775Sjfv fclose(job->cmdFILE); 1021230775Sjfv } 1022230775Sjfv done = TRUE; 1023230775Sjfv } 1024230775Sjfv } else { 1025230775Sjfv /* 1026230775Sjfv * No need to close things down or anything. 1027230775Sjfv */ 1028230775Sjfv done = FALSE; 1029230775Sjfv } 1030230775Sjfv 1031171384Sjfv if (WIFEXITED(*status)) { 1032230775Sjfv if (done || DEBUG(JOB)) { 1033230775Sjfv FILE *out; 1034230775Sjfv 1035230775Sjfv if (compatMake && 1036230775Sjfv !usePipes && 1037230775Sjfv (job->flags & JOB_IGNERR)) { 1038230775Sjfv /* 1039230775Sjfv * If output is going to a file and this job 1040230775Sjfv * is ignoring errors, arrange to have the 1041230775Sjfv * exit status sent to the output file as 1042230775Sjfv * well. 1043230775Sjfv */ 1044230775Sjfv out = fdopen(job->outFd, "w"); 1045230775Sjfv if (out == NULL) 1046230775Sjfv Punt("Cannot fdopen"); 1047230775Sjfv } else { 1048230775Sjfv out = stdout; 1049230775Sjfv } 1050230775Sjfv 1051230775Sjfv DEBUGF(JOB, ("Process %jd exited.\n", 1052230775Sjfv (intmax_t)job->pid)); 1053230775Sjfv 1054200239Sjfv if (WEXITSTATUS(*status) == 0) { 1055200239Sjfv if (DEBUG(JOB)) { 1056200239Sjfv if (usePipes && job->node != lastNode) { 1057190873Sjfv MESSAGE(out, job->node); 1058230775Sjfv lastNode = job->node; 1059190873Sjfv } 1060230775Sjfv fprintf(out, 1061230775Sjfv "*** Completed successfully\n"); 1062230775Sjfv } 1063230775Sjfv } else { 1064190873Sjfv if (usePipes && job->node != lastNode) { 1065190873Sjfv MESSAGE(out, job->node); 1066230775Sjfv lastNode = job->node; 1067230775Sjfv } 1068230775Sjfv fprintf(out, "*** Error code %d%s\n", 1069230775Sjfv WEXITSTATUS(*status), 1070230775Sjfv (job->flags & JOB_IGNERR) ? 1071247822Sjfv "(ignored)" : ""); 1072190873Sjfv 1073190873Sjfv if (job->flags & JOB_IGNERR) { 1074230775Sjfv *status = 0; 1075230775Sjfv } 1076190873Sjfv } 1077181003Sjfv 1078230775Sjfv fflush(out); 1079230775Sjfv } 1080230775Sjfv } else if (WIFSIGNALED(*status)) { 1081251964Sjfv if (done || DEBUG(JOB) || (WTERMSIG(*status) == SIGCONT)) { 1082230775Sjfv FILE *out; 1083251964Sjfv 1084230775Sjfv if (compatMake && 1085230775Sjfv !usePipes && 1086247822Sjfv (job->flags & JOB_IGNERR)) { 1087230775Sjfv /* 1088230775Sjfv * If output is going to a file and this job 1089171384Sjfv * is ignoring errors, arrange to have the 1090190873Sjfv * exit status sent to the output file as 1091230775Sjfv * well. 1092230775Sjfv */ 1093230775Sjfv out = fdopen(job->outFd, "w"); 1094230775Sjfv if (out == NULL) 1095230775Sjfv Punt("Cannot fdopen"); 1096230775Sjfv } else { 1097230775Sjfv out = stdout; 1098230775Sjfv } 1099230775Sjfv 1100190873Sjfv if (WTERMSIG(*status) == SIGCONT) { 1101190873Sjfv /* 1102230775Sjfv * If the beastie has continued, shift the 1103230775Sjfv * Job from the stopped list to the running 1104190873Sjfv * one (or re-stop it if concurrency is 1105171384Sjfv * exceeded) and go and get another child. 1106230775Sjfv */ 1107230775Sjfv if (job->flags & (JOB_RESUME | JOB_RESTART)) { 1108230775Sjfv if (usePipes && job->node != lastNode) { 1109230775Sjfv MESSAGE(out, job->node); 1110171384Sjfv lastNode = job->node; 1111171384Sjfv } 1112247822Sjfv fprintf(out, "*** Continued\n"); 1113230775Sjfv } 1114171384Sjfv if (!(job->flags & JOB_CONTINUING)) { 1115171384Sjfv DEBUGF(JOB, ("Warning: process %jd was not " 1116230775Sjfv "continuing.\n", (intmax_t) job->pid)); 1117230775Sjfv#ifdef notdef 1118171384Sjfv /* 1119171384Sjfv * We don't really want to restart a 1120230775Sjfv * job from scratch just because it 1121230775Sjfv * continued, especially not without 1122230775Sjfv * killing the continuing process! 1123230775Sjfv * That's why this is ifdef'ed out. 1124171384Sjfv * FD - 9/17/90 1125171384Sjfv */ 1126230775Sjfv JobRestart(job); 1127230775Sjfv#endif 1128171384Sjfv } 1129230775Sjfv job->flags &= ~JOB_CONTINUING; 1130230775Sjfv TAILQ_INSERT_TAIL(&jobs, job, link); 1131171384Sjfv nJobs += 1; 1132230775Sjfv DEBUGF(JOB, ("Process %jd is continuing locally.\n", 1133230775Sjfv (intmax_t) job->pid)); 1134230775Sjfv if (nJobs == maxJobs) { 1135230775Sjfv jobFull = TRUE; 1136230775Sjfv DEBUGF(JOB, ("Job queue is full.\n")); 1137230775Sjfv } 1138230775Sjfv fflush(out); 1139238149Sjfv return; 1140238149Sjfv 1141171384Sjfv } else { 1142230775Sjfv if (usePipes && job->node != lastNode) { 1143230775Sjfv MESSAGE(out, job->node); 1144230775Sjfv lastNode = job->node; 1145230775Sjfv } 1146238149Sjfv fprintf(out, 1147238149Sjfv "*** Signal %d\n", WTERMSIG(*status)); 1148238149Sjfv fflush(out); 1149230775Sjfv } 1150171384Sjfv } 1151171384Sjfv } else { 1152230775Sjfv /* STOPPED */ 1153230775Sjfv FILE *out; 1154230775Sjfv 1155230775Sjfv if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 1156230775Sjfv /* 1157230775Sjfv * If output is going to a file and this job 1158230775Sjfv * is ignoring errors, arrange to have the 1159230775Sjfv * exit status sent to the output file as 1160230775Sjfv * well. 1161230775Sjfv */ 1162230775Sjfv out = fdopen(job->outFd, "w"); 1163230775Sjfv if (out == NULL) 1164230775Sjfv Punt("Cannot fdopen"); 1165230775Sjfv } else { 1166230775Sjfv out = stdout; 1167230775Sjfv } 1168230775Sjfv 1169230775Sjfv DEBUGF(JOB, ("Process %jd stopped.\n", (intmax_t) job->pid)); 1170171384Sjfv if (usePipes && job->node != lastNode) { 1171171384Sjfv MESSAGE(out, job->node); 1172230775Sjfv lastNode = job->node; 1173230775Sjfv } 1174230775Sjfv fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status)); 1175230775Sjfv job->flags |= JOB_RESUME; 1176171384Sjfv TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 1177172043Sjfv fflush(out); 1178230775Sjfv return; 1179230775Sjfv } 1180230775Sjfv 1181230775Sjfv /* 1182172043Sjfv * Now handle the -B-mode stuff. If the beast still isn't finished, 1183172043Sjfv * try and restart the job on the next command. If JobStart says it's 1184230775Sjfv * ok, it's ok. If there's an error, this puppy is done. 1185230775Sjfv */ 1186230775Sjfv if (compatMake && WIFEXITED(*status) && 1187230775Sjfv Lst_Succ(job->node->compat_command) != NULL) { 1188230775Sjfv switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { 1189172043Sjfv case JOB_RUNNING: 1190190873Sjfv done = FALSE; 1191230775Sjfv break; 1192185352Sjfv case JOB_ERROR: 1193171384Sjfv done = TRUE; 1194230775Sjfv W_SETEXITSTATUS(status, 1); 1195230775Sjfv break; 1196230775Sjfv case JOB_FINISHED: 1197230775Sjfv /* 1198230775Sjfv * If we got back a JOB_FINISHED code, JobStart has 1199230775Sjfv * already called Make_Update and freed the job 1200171384Sjfv * descriptor. We set done to false here to avoid fake 1201230775Sjfv * cycles and double frees. JobStart needs to do the 1202172043Sjfv * update so we can proceed up the graph when given 1203230775Sjfv * the -n flag.. 1204230775Sjfv */ 1205230775Sjfv done = FALSE; 1206230775Sjfv break; 1207230775Sjfv default: 1208230775Sjfv break; 1209171384Sjfv } 1210230775Sjfv } else { 1211230775Sjfv done = TRUE; 1212230775Sjfv } 1213230775Sjfv 1214230775Sjfv if (done && aborting != ABORT_ERROR && 1215230775Sjfv aborting != ABORT_INTERRUPT && *status == 0) { 1216230775Sjfv /* 1217230775Sjfv * As long as we aren't aborting and the job didn't return a 1218230775Sjfv * non-zero status that we shouldn't ignore, we call 1219230775Sjfv * Make_Update to update the parents. In addition, any saved 1220230775Sjfv * commands for the node are placed on the .END target. 1221230775Sjfv */ 1222230775Sjfv for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { 1223230775Sjfv Lst_AtEnd(&postCommands->commands, 1224230775Sjfv Buf_Peel( 1225230775Sjfv Var_Subst(Lst_Datum(ln), job->node, FALSE))); 1226230775Sjfv } 1227171384Sjfv 1228230775Sjfv job->node->made = MADE; 1229230775Sjfv Make_Update(job->node); 1230230775Sjfv free(job); 1231230775Sjfv 1232185352Sjfv } else if (*status != 0) { 1233179055Sjfv errors += 1; 1234230775Sjfv free(job); 1235179055Sjfv } 1236230775Sjfv 1237200239Sjfv JobRestartJobs(); 1238230775Sjfv 1239230775Sjfv /* 1240230775Sjfv * Set aborting if any error. 1241230775Sjfv */ 1242230775Sjfv if (errors && !keepgoing && aborting != ABORT_INTERRUPT) { 1243230775Sjfv /* 1244230775Sjfv * If we found any errors in this batch of children and the -k 1245230775Sjfv * flag wasn't given, we set the aborting flag so no more jobs 1246230775Sjfv * get started. 1247230775Sjfv */ 1248230775Sjfv aborting = ABORT_ERROR; 1249179055Sjfv } 1250230775Sjfv 1251230775Sjfv if (aborting == ABORT_ERROR && Job_Empty()) { 1252171384Sjfv /* 1253171384Sjfv * If we are aborting and the job table is now empty, we finish. 1254230775Sjfv */ 1255230775Sjfv Finish(errors); 1256230775Sjfv } 1257230775Sjfv} 1258230775Sjfv 1259230775Sjfv/** 1260171384Sjfv * Job_Touch 1261179055Sjfv * Touch the given target. Called by JobStart when the -t flag was 1262230775Sjfv * given. Prints messages unless told to be silent. 1263179055Sjfv * 1264185352Sjfv * Side Effects: 1265230775Sjfv * The data modification of the file is changed. In addition, if the 1266230775Sjfv * file did not exist, it is created. 1267230775Sjfv */ 1268230775Sjfvvoid 1269230775SjfvJob_Touch(GNode *gn, Boolean silent) 1270230775Sjfv{ 1271230775Sjfv int streamID; /* ID of stream opened to do the touch */ 1272230775Sjfv struct utimbuf times; /* Times for utime() call */ 1273230775Sjfv 1274230775Sjfv if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) { 1275185352Sjfv /* 1276171384Sjfv * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" 1277230775Sjfv * targets and, as such, shouldn't really be created. 1278230775Sjfv */ 1279230775Sjfv return; 1280230775Sjfv } 1281230775Sjfv 1282230775Sjfv if (!silent) { 1283230775Sjfv fprintf(stdout, "touch %s\n", gn->name); 1284230775Sjfv fflush(stdout); 1285230775Sjfv } 1286230775Sjfv 1287230775Sjfv if (noExecute) { 1288230775Sjfv return; 1289230775Sjfv } 1290171384Sjfv 1291230775Sjfv if (gn->type & OP_ARCHV) { 1292230775Sjfv Arch_Touch(gn); 1293230775Sjfv } else if (gn->type & OP_LIB) { 1294230775Sjfv Arch_TouchLib(gn); 1295230775Sjfv } else { 1296230775Sjfv char *file = gn->path ? gn->path : gn->name; 1297230775Sjfv 1298230775Sjfv times.actime = times.modtime = now; 1299230775Sjfv if (utime(file, ×) < 0) { 1300230775Sjfv streamID = open(file, O_RDWR | O_CREAT, 0666); 1301230775Sjfv 1302230775Sjfv if (streamID >= 0) { 1303230775Sjfv char c; 1304230775Sjfv 1305230775Sjfv /* 1306230775Sjfv * Read and write a byte to the file to change 1307230775Sjfv * the modification time, then close the file. 1308230775Sjfv */ 1309230775Sjfv if (read(streamID, &c, 1) == 1) { 1310230775Sjfv lseek(streamID, (off_t)0, SEEK_SET); 1311230775Sjfv write(streamID, &c, 1); 1312230775Sjfv } 1313230775Sjfv 1314171384Sjfv close(streamID); 1315230775Sjfv } else { 1316230775Sjfv fprintf(stdout, "*** couldn't touch %s: %s", 1317230775Sjfv file, strerror(errno)); 1318230775Sjfv fflush(stdout); 1319230775Sjfv } 1320230775Sjfv } 1321230775Sjfv } 1322230775Sjfv} 1323230775Sjfv 1324171384Sjfv/** 1325171384Sjfv * Job_CheckCommands 1326230775Sjfv * Make sure the given node has all the commands it needs. 1327230775Sjfv * 1328230775Sjfv * Results: 1329230775Sjfv * TRUE if the commands list is/was ok. 1330230775Sjfv * 1331171384Sjfv * Side Effects: 1332171384Sjfv * The node will have commands from the .DEFAULT rule added to it 1333230775Sjfv * if it needs them. 1334230775Sjfv */ 1335230775SjfvBoolean 1336230775SjfvJob_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 1337230775Sjfv{ 1338230775Sjfv 1339230775Sjfv if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && 1340230775Sjfv (gn->type & OP_LIB) == 0) { 1341230775Sjfv /* 1342230775Sjfv * No commands. Look for .DEFAULT rule from which we might infer 1343230775Sjfv * commands. 1344230775Sjfv */ 1345230775Sjfv if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { 1346230775Sjfv char *p1; 1347230775Sjfv /* 1348171384Sjfv * Make only looks for a .DEFAULT if the node was 1349171384Sjfv * never the target of an operator, so that's what we 1350230775Sjfv * do too. If a .DEFAULT was given, we substitute its 1351230775Sjfv * commands for gn's commands and set the IMPSRC 1352171384Sjfv * variable to be the target's name The DEFAULT node 1353190873Sjfv * acts like a transformation rule, in that gn also 1354230775Sjfv * inherits any attributes or sources attached to 1355230775Sjfv * .DEFAULT itself. 1356230775Sjfv */ 1357230775Sjfv Make_HandleUse(DEFAULT, gn); 1358230775Sjfv Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn); 1359190873Sjfv free(p1); 1360190873Sjfv 1361230775Sjfv } else if (Dir_MTime(gn) == 0) { 1362230775Sjfv /* 1363230775Sjfv * The node wasn't the target of an operator we have 1364230775Sjfv * no .DEFAULT rule to go on and the target doesn't 1365230775Sjfv * already exist. There's nothing more we can do for 1366190873Sjfv * this branch. If the -k flag wasn't given, we stop 1367190873Sjfv * in our tracks, otherwise we just don't update 1368230775Sjfv * this node's parents so they never get examined. 1369190873Sjfv */ 1370230775Sjfv static const char msg[] = 1371194875Sjfv "make: don't know how to make"; 1372171384Sjfv 1373230775Sjfv if (gn->type & OP_OPTIONAL) { 1374230775Sjfv fprintf(stdout, "%s %s(ignored)\n", 1375230775Sjfv msg, gn->name); 1376230775Sjfv fflush(stdout); 1377230775Sjfv } else if (keepgoing) { 1378230775Sjfv fprintf(stdout, "%s %s(continuing)\n", 1379171384Sjfv msg, gn->name); 1380230775Sjfv fflush(stdout); 1381230775Sjfv return (FALSE); 1382230775Sjfv } else { 1383230775Sjfv#if OLD_JOKE 1384230775Sjfv if (strcmp(gn->name,"love") == 0) 1385230775Sjfv (*abortProc)("Not war."); 1386230775Sjfv else 1387230775Sjfv#endif 1388230775Sjfv (*abortProc)("%s %s. Stop", 1389230775Sjfv msg, gn->name); 1390230775Sjfv return (FALSE); 1391230775Sjfv } 1392230775Sjfv } 1393230775Sjfv } 1394230775Sjfv return (TRUE); 1395230775Sjfv} 1396230775Sjfv 1397230775Sjfv/** 1398230775Sjfv * JobExec 1399230775Sjfv * Execute the shell for the given job. Called from JobStart and 1400230775Sjfv * JobRestart. 1401230775Sjfv * 1402230775Sjfv * Side Effects: 1403230775Sjfv * A shell is executed, outputs is altered and the Job structure added 1404230775Sjfv * to the job table. 1405230775Sjfv */ 1406230775Sjfvstatic void 1407230775SjfvJobExec(Job *job, char **argv) 1408230775Sjfv{ 1409230775Sjfv ProcStuff ps; 1410230775Sjfv 1411230775Sjfv if (DEBUG(JOB)) { 1412190873Sjfv int i; 1413230775Sjfv 1414190873Sjfv DEBUGF(JOB, ("Running %s\n", job->node->name)); 1415171384Sjfv DEBUGF(JOB, ("\tCommand: ")); 1416230775Sjfv for (i = 0; argv[i] != NULL; i++) { 1417230775Sjfv DEBUGF(JOB, ("%s ", argv[i])); 1418171384Sjfv } 1419171384Sjfv DEBUGF(JOB, ("\n")); 1420230775Sjfv } 1421230775Sjfv 1422171384Sjfv /* 1423171384Sjfv * Some jobs produce no output and it's disconcerting to have 1424230775Sjfv * no feedback of their running (since they produce no output, the 1425171384Sjfv * banner with their name in it never appears). This is an attempt to 1426171384Sjfv * provide that feedback, even if nothing follows it. 1427230775Sjfv */ 1428171384Sjfv if (lastNode != job->node && (job->flags & JOB_FIRST) && 1429230775Sjfv !(job->flags & JOB_SILENT)) { 1430230775Sjfv MESSAGE(stdout, job->node); 1431230775Sjfv lastNode = job->node; 1432230775Sjfv } 1433230775Sjfv 1434230775Sjfv ps.in = FILENO(job->cmdFILE); 1435171384Sjfv if (usePipes) { 1436190873Sjfv /* 1437230775Sjfv * Set up the child's output to be routed through the 1438230775Sjfv * pipe we've created for it. 1439179055Sjfv */ 1440171384Sjfv ps.out = job->outPipe; 1441171384Sjfv } else { 1442171384Sjfv /* 1443230775Sjfv * We're capturing output in a file, so we duplicate 1444230775Sjfv * the descriptor to the temporary file into the 1445230775Sjfv * standard output. 1446230775Sjfv */ 1447230775Sjfv ps.out = job->outFd; 1448230775Sjfv } 1449230775Sjfv ps.err = STDERR_FILENO; 1450230775Sjfv 1451230775Sjfv ps.merge_errors = 1; 1452238149Sjfv ps.pgroup = 1; 1453230775Sjfv ps.searchpath = 0; 1454230775Sjfv 1455230775Sjfv ps.argv = argv; 1456230775Sjfv 1457230775Sjfv /* 1458230775Sjfv * Fork. Warning since we are doing vfork() instead of fork(), 1459230775Sjfv * do not allocate memory in the child process! 1460230775Sjfv */ 1461171384Sjfv if ((ps.child_pid = vfork()) == -1) { 1462171384Sjfv Punt("Cannot fork"); 1463230775Sjfv 1464230775Sjfv 1465230775Sjfv } else if (ps.child_pid == 0) { 1466230775Sjfv /* 1467230775Sjfv * Child 1468230775Sjfv */ 1469230775Sjfv if (fifoFd >= 0) 1470238149Sjfv close(fifoFd); 1471230775Sjfv 1472230775Sjfv ProcExec(&ps); 1473230775Sjfv /* NOTREACHED */ 1474230775Sjfv } 1475230775Sjfv 1476230775Sjfv /* 1477230775Sjfv * Parent 1478230775Sjfv */ 1479171384Sjfv job->pid = ps.child_pid; 1480171384Sjfv 1481230775Sjfv if (usePipes && (job->flags & JOB_FIRST)) { 1482230775Sjfv /* 1483230775Sjfv * The first time a job is run for a node, we set the 1484230775Sjfv * current position in the buffer to the beginning and 1485230775Sjfv * mark another stream to watch in the outputs mask. 1486230775Sjfv */ 1487230775Sjfv#ifdef USE_KQUEUE 1488230775Sjfv struct kevent kev[2]; 1489238149Sjfv#endif 1490230775Sjfv job->curPos = 0; 1491230775Sjfv 1492230775Sjfv#if defined(USE_KQUEUE) 1493230775Sjfv EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job); 1494230775Sjfv EV_SET(&kev[1], job->pid, EVFILT_PROC, 1495230775Sjfv EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL); 1496230775Sjfv if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) { 1497230775Sjfv /* 1498171384Sjfv * kevent() will fail if the job is already 1499171384Sjfv * finished 1500230775Sjfv */ 1501230775Sjfv if (errno != EINTR && errno != EBADF && errno != ESRCH) 1502230775Sjfv Punt("kevent: %s", strerror(errno)); 1503230775Sjfv } 1504230775Sjfv#else 1505230775Sjfv FD_SET(job->inPipe, &outputs); 1506230775Sjfv#endif /* USE_KQUEUE */ 1507238149Sjfv } 1508230775Sjfv 1509230775Sjfv if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1510230775Sjfv fclose(job->cmdFILE); 1511230775Sjfv job->cmdFILE = NULL; 1512230775Sjfv } 1513230775Sjfv 1514230775Sjfv /* 1515230775Sjfv * Now the job is actually running, add it to the table. 1516171384Sjfv */ 1517171384Sjfv nJobs += 1; 1518230775Sjfv TAILQ_INSERT_TAIL(&jobs, job, link); 1519230775Sjfv if (nJobs == maxJobs) { 1520230775Sjfv jobFull = TRUE; 1521230775Sjfv } 1522171384Sjfv} 1523179055Sjfv 1524230775Sjfv/** 1525230775Sjfv * JobMakeArgv 1526230775Sjfv * Create the argv needed to execute the shell for a given job. 1527230775Sjfv */ 1528230775Sjfvstatic void 1529230775SjfvJobMakeArgv(Job *job, char **argv) 1530230775Sjfv{ 1531230775Sjfv int argc; 1532230775Sjfv static char args[10]; /* For merged arguments */ 1533230775Sjfv 1534230775Sjfv argv[0] = shellName; 1535230775Sjfv argc = 1; 1536230775Sjfv 1537230775Sjfv if ((commandShell->exit && *commandShell->exit != '-') || 1538230775Sjfv (commandShell->echo && *commandShell->echo != '-')) { 1539230775Sjfv /* 1540230775Sjfv * At least one of the flags doesn't have a minus before it, so 1541230775Sjfv * merge them together. Have to do this because the *(&(@*#*&#$# 1542230775Sjfv * Bourne shell thinks its second argument is a file to source. 1543230775Sjfv * Grrrr. Note the ten-character limitation on the combined 1544230775Sjfv * arguments. 1545230775Sjfv */ 1546230775Sjfv sprintf(args, "-%s%s", (job->flags & JOB_IGNERR) ? "" : 1547171384Sjfv commandShell->exit ? commandShell->exit : "", 1548230775Sjfv (job->flags & JOB_SILENT) ? "" : 1549230775Sjfv commandShell->echo ? commandShell->echo : ""); 1550230775Sjfv 1551230775Sjfv if (args[1]) { 1552230775Sjfv argv[argc] = args; 1553230775Sjfv argc++; 1554230775Sjfv } 1555230775Sjfv } else { 1556230775Sjfv if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1557230775Sjfv argv[argc] = commandShell->exit; 1558230775Sjfv argc++; 1559230775Sjfv } 1560230775Sjfv if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1561230775Sjfv argv[argc] = commandShell->echo; 1562230775Sjfv argc++; 1563230775Sjfv } 1564230775Sjfv } 1565230775Sjfv argv[argc] = NULL; 1566190873Sjfv} 1567171384Sjfv 1568230775Sjfv/** 1569171384Sjfv * JobRestart 1570171384Sjfv * Restart a job that stopped for some reason. The job must be neither 1571230775Sjfv * on the jobs nor on the stoppedJobs list. 1572230775Sjfv * 1573230775Sjfv * Side Effects: 1574230775Sjfv * jobFull will be set if the job couldn't be run. 1575230775Sjfv */ 1576230775Sjfvstatic void 1577230775SjfvJobRestart(Job *job) 1578171384Sjfv{ 1579230775Sjfv 1580230775Sjfv if (job->flags & JOB_RESTART) { 1581171384Sjfv /* 1582230775Sjfv * Set up the control arguments to the shell. This is based on 1583171384Sjfv * the flags set earlier for this job. If the JOB_IGNERR flag 1584230775Sjfv * is clear, the 'exit' flag of the commandShell is used to 1585171384Sjfv * cause it to exit upon receiving an error. If the JOB_SILENT 1586190873Sjfv * flag is clear, the 'echo' flag of the commandShell is used 1587230775Sjfv * to get it to start echoing as soon as it starts 1588230775Sjfv * processing commands. 1589230775Sjfv */ 1590230775Sjfv char *argv[4]; 1591230775Sjfv 1592230775Sjfv JobMakeArgv(job, argv); 1593238149Sjfv 1594190873Sjfv DEBUGF(JOB, ("Restarting %s...", job->node->name)); 1595230775Sjfv if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) { 1596230775Sjfv /* 1597230775Sjfv * Not allowed to run -- put it back on the hold 1598230775Sjfv * queue and mark the table full 1599190873Sjfv */ 1600190873Sjfv DEBUGF(JOB, ("holding\n")); 1601190873Sjfv TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1602230775Sjfv jobFull = TRUE; 1603230775Sjfv DEBUGF(JOB, ("Job queue is full.\n")); 1604190873Sjfv return; 1605190873Sjfv } else { 1606230775Sjfv /* 1607230775Sjfv * Job may be run locally. 1608230775Sjfv */ 1609230775Sjfv DEBUGF(JOB, ("running locally\n")); 1610190873Sjfv } 1611230775Sjfv JobExec(job, argv); 1612230775Sjfv 1613230775Sjfv } else { 1614230775Sjfv /* 1615171384Sjfv * The job has stopped and needs to be restarted. 1616230775Sjfv * Why it stopped, we don't know... 1617230775Sjfv */ 1618230775Sjfv DEBUGF(JOB, ("Resuming %s...", job->node->name)); 1619230775Sjfv if ((nJobs < maxJobs || ((job->flags & JOB_SPECIAL) && 1620230775Sjfv maxJobs == 0)) && nJobs != maxJobs) { 1621171384Sjfv /* 1622190873Sjfv * If we haven't reached the concurrency limit already 1623230775Sjfv * (or the job must be run and maxJobs is 0), it's ok 1624230775Sjfv * to resume it. 1625230775Sjfv */ 1626215911Sjfv Boolean error; 1627230775Sjfv int status; 1628230775Sjfv 1629179055Sjfv error = (KILL(job->pid, SIGCONT) != 0); 1630230775Sjfv 1631171384Sjfv if (!error) { 1632171384Sjfv /* 1633230775Sjfv * Make sure the user knows we've continued 1634230775Sjfv * the beast and actually put the thing in the 1635230775Sjfv * job table. 1636171384Sjfv */ 1637230775Sjfv job->flags |= JOB_CONTINUING; 1638230775Sjfv status = 0; 1639171384Sjfv W_SETTERMSIG(&status, SIGCONT); 1640171384Sjfv JobFinish(job, &status); 1641230775Sjfv 1642230775Sjfv job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 1643230775Sjfv DEBUGF(JOB, ("done\n")); 1644230775Sjfv } else { 1645230775Sjfv Error("couldn't resume %s: %s", 1646230775Sjfv job->node->name, strerror(errno)); 1647230775Sjfv status = 0; 1648238149Sjfv W_SETEXITSTATUS(&status, 1); 1649238149Sjfv JobFinish(job, &status); 1650238149Sjfv } 1651247822Sjfv } else { 1652238149Sjfv /* 1653238149Sjfv * Job cannot be restarted. Mark the table as full and 1654230775Sjfv * place the job back on the list of stopped jobs. 1655238149Sjfv */ 1656238149Sjfv DEBUGF(JOB, ("table full\n")); 1657238149Sjfv TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1658238149Sjfv jobFull = TRUE; 1659171384Sjfv DEBUGF(JOB, ("Job queue is full.\n")); 1660238149Sjfv } 1661171384Sjfv } 1662230775Sjfv} 1663230775Sjfv 1664230775Sjfv/** 1665230775Sjfv * JobStart 1666230775Sjfv * Start a target-creation process going for the target described 1667230775Sjfv * by the graph node gn. 1668230775Sjfv * 1669230775Sjfv * Results: 1670171384Sjfv * JOB_ERROR if there was an error in the commands, JOB_FINISHED 1671171384Sjfv * if there isn't actually anything left to do for the job and 1672230775Sjfv * JOB_RUNNING if the job has been started. 1673230775Sjfv * 1674230775Sjfv * Side Effects: 1675230775Sjfv * A new Job node is created and added to the list of running 1676230775Sjfv * jobs. PMake is forked and a child shell created. 1677230775Sjfv */ 1678230775Sjfvstatic int 1679230775SjfvJobStart(GNode *gn, int flags, Job *previous) 1680171384Sjfv{ 1681171384Sjfv Job *job; /* new job descriptor */ 1682190873Sjfv char *argv[4]; /* Argument vector to shell */ 1683230775Sjfv Boolean cmdsOK; /* true if the nodes commands were all right */ 1684230775Sjfv Boolean noExec; /* Set true if we decide not to run the job */ 1685230775Sjfv int tfd; /* File descriptor for temp file */ 1686230775Sjfv LstNode *ln; 1687230775Sjfv char tfile[sizeof(TMPPAT)]; 1688230775Sjfv 1689230775Sjfv if (interrupted) { 1690230775Sjfv JobPassSig(interrupted); 1691230775Sjfv return (JOB_ERROR); 1692230775Sjfv } 1693230775Sjfv if (previous != NULL) { 1694230775Sjfv previous->flags &= ~(JOB_FIRST | JOB_IGNERR | JOB_SILENT); 1695230775Sjfv job = previous; 1696230775Sjfv } else { 1697230775Sjfv job = emalloc(sizeof(Job)); 1698230775Sjfv flags |= JOB_FIRST; 1699230775Sjfv } 1700230775Sjfv 1701230775Sjfv job->node = gn; 1702230775Sjfv job->tailCmds = NULL; 1703230775Sjfv 1704230775Sjfv /* 1705230775Sjfv * Set the initial value of the flags for this job based on the global 1706230775Sjfv * ones and the node's attributes... Any flags supplied by the caller 1707230775Sjfv * are also added to the field. 1708230775Sjfv */ 1709230775Sjfv job->flags = 0; 1710230775Sjfv if (Targ_Ignore(gn)) { 1711171384Sjfv job->flags |= JOB_IGNERR; 1712230775Sjfv } 1713230775Sjfv if (Targ_Silent(gn)) { 1714230775Sjfv job->flags |= JOB_SILENT; 1715230775Sjfv } 1716230775Sjfv job->flags |= flags; 1717230775Sjfv 1718230775Sjfv /* 1719230775Sjfv * Check the commands now so any attributes from .DEFAULT have a chance 1720230775Sjfv * to migrate to the node. 1721230775Sjfv */ 1722230775Sjfv if (!compatMake && (job->flags & JOB_FIRST)) { 1723171384Sjfv cmdsOK = Job_CheckCommands(gn, Error); 1724230775Sjfv } else { 1725230775Sjfv cmdsOK = TRUE; 1726230775Sjfv } 1727230775Sjfv 1728230775Sjfv /* 1729230775Sjfv * If the -n flag wasn't given, we open up OUR (not the child's) 1730251964Sjfv * temporary file to stuff commands in it. The thing is rd/wr so we 1731251964Sjfv * don't need to reopen it to feed it to the shell. If the -n flag 1732190873Sjfv * *was* given, we just set the file to be stdout. Cute, huh? 1733230775Sjfv */ 1734230775Sjfv if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 1735230775Sjfv /* 1736230775Sjfv * We're serious here, but if the commands were bogus, we're 1737205720Sjfv * also dead... 1738171384Sjfv */ 1739230775Sjfv if (!cmdsOK) { 1740230775Sjfv DieHorribly(); 1741230775Sjfv } 1742230775Sjfv 1743230775Sjfv strcpy(tfile, TMPPAT); 1744230775Sjfv if ((tfd = mkstemp(tfile)) == -1) 1745230775Sjfv Punt("Cannot create temp file: %s", strerror(errno)); 1746230775Sjfv job->cmdFILE = fdopen(tfd, "w+"); 1747230775Sjfv eunlink(tfile); 1748230775Sjfv if (job->cmdFILE == NULL) { 1749230775Sjfv close(tfd); 1750230775Sjfv Punt("Could not open %s", tfile); 1751230775Sjfv } 1752230775Sjfv fcntl(FILENO(job->cmdFILE), F_SETFD, 1); 1753230775Sjfv /* 1754230775Sjfv * Send the commands to the command file, flush all its 1755171384Sjfv * buffers then rewind and remove the thing. 1756230775Sjfv */ 1757230775Sjfv noExec = FALSE; 1758230775Sjfv 1759230775Sjfv /* 1760230775Sjfv * Used to be backwards; replace when start doing multiple 1761230775Sjfv * commands per shell. 1762171384Sjfv */ 1763230775Sjfv if (compatMake) { 1764200239Sjfv /* 1765172043Sjfv * Be compatible: If this is the first time for this 1766230775Sjfv * node, verify its commands are ok and open the 1767230775Sjfv * commands list for sequential access by later 1768230775Sjfv * invocations of JobStart. Once that is done, we take 1769230775Sjfv * the next command off the list and print it to the 1770230775Sjfv * command file. If the command was an ellipsis, note 1771230775Sjfv * that there's nothing more to execute. 1772230775Sjfv */ 1773172043Sjfv if (job->flags & JOB_FIRST) 1774230775Sjfv gn->compat_command = Lst_First(&gn->commands); 1775230775Sjfv else 1776172043Sjfv gn->compat_command = 1777172043Sjfv Lst_Succ(gn->compat_command); 1778230775Sjfv 1779230775Sjfv if (gn->compat_command == NULL || 1780230775Sjfv JobPrintCommand(Lst_Datum(gn->compat_command), job)) 1781230775Sjfv noExec = TRUE; 1782230775Sjfv 1783230775Sjfv if (noExec && !(job->flags & JOB_FIRST)) { 1784172043Sjfv /* 1785200239Sjfv * If we're not going to execute anything, the 1786230775Sjfv * job is done and we need to close down the 1787230775Sjfv * various file descriptors we've opened for 1788230775Sjfv * output, then call JobDoOutput to catch the 1789230775Sjfv * final characters or send the file to the 1790200239Sjfv * screen... Note that the i/o streams are only 1791171384Sjfv * open if this isn't the first job. Note also 1792230775Sjfv * that this could not be done in 1793230775Sjfv * Job_CatchChildren b/c it wasn't clear if 1794230775Sjfv * there were more commands to execute or not... 1795230775Sjfv */ 1796171384Sjfv JobClose(job); 1797200239Sjfv } 1798230775Sjfv } else { 1799230775Sjfv /* 1800230775Sjfv * We can do all the commands at once. hooray for sanity 1801230775Sjfv */ 1802230775Sjfv numCommands = 0; 1803230775Sjfv LST_FOREACH(ln, &gn->commands) { 1804171384Sjfv if (JobPrintCommand(Lst_Datum(ln), job)) 1805230775Sjfv break; 1806230775Sjfv } 1807230775Sjfv 1808171384Sjfv /* 1809230775Sjfv * If we didn't print out any commands to the shell 1810230775Sjfv * script, there's not much point in executing the 1811230775Sjfv * shell, is there? 1812230775Sjfv */ 1813230775Sjfv if (numCommands == 0) { 1814230775Sjfv noExec = TRUE; 1815230775Sjfv } 1816230775Sjfv } 1817230775Sjfv 1818230775Sjfv } else if (noExecute) { 1819230775Sjfv /* 1820230775Sjfv * Not executing anything -- just print all the commands to 1821230775Sjfv * stdout in one fell swoop. This will still set up 1822230775Sjfv * job->tailCmds correctly. 1823230775Sjfv */ 1824171384Sjfv if (lastNode != gn) { 1825230775Sjfv MESSAGE(stdout, gn); 1826230775Sjfv lastNode = gn; 1827230775Sjfv } 1828171384Sjfv job->cmdFILE = stdout; 1829230775Sjfv 1830230775Sjfv /* 1831230775Sjfv * Only print the commands if they're ok, but don't die if 1832171384Sjfv * they're not -- just let the user know they're bad and keep 1833215911Sjfv * going. It doesn't do any harm in this case and may do 1834230775Sjfv * some good. 1835215911Sjfv */ 1836171384Sjfv if (cmdsOK) { 1837230775Sjfv LST_FOREACH(ln, &gn->commands) { 1838230775Sjfv if (JobPrintCommand(Lst_Datum(ln), job)) 1839230775Sjfv break; 1840230775Sjfv } 1841230775Sjfv } 1842230775Sjfv /* 1843230775Sjfv * Don't execute the shell, thank you. 1844230775Sjfv */ 1845230775Sjfv noExec = TRUE; 1846230775Sjfv 1847230775Sjfv } else { 1848230775Sjfv /* 1849230775Sjfv * Just touch the target and note that no shell should be 1850230775Sjfv * executed. Set cmdFILE to stdout to make life easier. Check 1851230775Sjfv * the commands, too, but don't die if they're no good -- it 1852230775Sjfv * does no harm to keep working up the graph. 1853230775Sjfv */ 1854230775Sjfv job->cmdFILE = stdout; 1855230775Sjfv Job_Touch(gn, job->flags & JOB_SILENT); 1856230775Sjfv noExec = TRUE; 1857230775Sjfv } 1858230775Sjfv 1859171384Sjfv /* 1860230775Sjfv * If we're not supposed to execute a shell, don't. 1861230775Sjfv */ 1862230775Sjfv if (noExec) { 1863230775Sjfv /* 1864238149Sjfv * Unlink and close the command file if we opened one 1865230775Sjfv */ 1866238149Sjfv if (job->cmdFILE != stdout) { 1867230775Sjfv if (job->cmdFILE != NULL) 1868190873Sjfv fclose(job->cmdFILE); 1869230775Sjfv } else { 1870190873Sjfv fflush(stdout); 1871172043Sjfv } 1872230775Sjfv 1873230775Sjfv /* 1874230775Sjfv * We only want to work our way up the graph if we aren't here 1875172043Sjfv * because the commands for the job were no good. 1876171384Sjfv */ 1877230775Sjfv if (cmdsOK) { 1878230775Sjfv if (aborting == 0) { 1879230775Sjfv for (ln = job->tailCmds; ln != NULL; 1880230775Sjfv ln = LST_NEXT(ln)) { 1881230775Sjfv Lst_AtEnd(&postCommands->commands, 1882230775Sjfv Buf_Peel(Var_Subst(Lst_Datum(ln), 1883179055Sjfv job->node, FALSE))); 1884230775Sjfv } 1885230775Sjfv job->node->made = MADE; 1886230775Sjfv Make_Update(job->node); 1887230775Sjfv } 1888230775Sjfv free(job); 1889230775Sjfv return(JOB_FINISHED); 1890171384Sjfv } else { 1891171384Sjfv free(job); 1892230775Sjfv return(JOB_ERROR); 1893230775Sjfv } 1894230775Sjfv } else { 1895230775Sjfv fflush(job->cmdFILE); 1896230775Sjfv } 1897230775Sjfv 1898171384Sjfv /* 1899230775Sjfv * Set up the control arguments to the shell. This is based on the flags 1900171384Sjfv * set earlier for this job. 1901230775Sjfv */ 1902247822Sjfv JobMakeArgv(job, argv); 1903230775Sjfv 1904251964Sjfv /* 1905251964Sjfv * If we're using pipes to catch output, create the pipe by which we'll 1906230775Sjfv * get the shell's output. If we're using files, print out that we're 1907171384Sjfv * starting a job and then set up its temporary-file name. 1908230775Sjfv */ 1909171384Sjfv if (!compatMake || (job->flags & JOB_FIRST)) { 1910171384Sjfv if (usePipes) { 1911200239Sjfv int fd[2]; 1912200239Sjfv 1913230775Sjfv if (pipe(fd) == -1) 1914171384Sjfv Punt("Cannot create pipe: %s", strerror(errno)); 1915200239Sjfv job->inPipe = fd[0]; 1916230775Sjfv job->outPipe = fd[1]; 1917200239Sjfv fcntl(job->inPipe, F_SETFD, 1); 1918230775Sjfv fcntl(job->outPipe, F_SETFD, 1); 1919230775Sjfv } else { 1920230775Sjfv fprintf(stdout, "Remaking `%s'\n", gn->name); 1921230775Sjfv fflush(stdout); 1922194875Sjfv strcpy(job->outFile, TMPPAT); 1923230775Sjfv if ((job->outFd = mkstemp(job->outFile)) == -1) 1924230775Sjfv Punt("cannot create temp file: %s", 1925230775Sjfv strerror(errno)); 1926230775Sjfv fcntl(job->outFd, F_SETFD, 1); 1927230775Sjfv } 1928230775Sjfv } 1929230775Sjfv 1930230775Sjfv if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL) && maxJobs != 0) { 1931230775Sjfv /* 1932230775Sjfv * We've hit the limit of concurrency, so put the job on hold 1933230775Sjfv * until some other job finishes. Note that the special jobs 1934230775Sjfv * (.BEGIN, .INTERRUPT and .END) may be run even when the 1935230775Sjfv * limit has been reached (e.g. when maxJobs == 0). 1936230775Sjfv */ 1937230775Sjfv jobFull = TRUE; 1938230775Sjfv 1939230775Sjfv DEBUGF(JOB, ("Can only run job locally.\n")); 1940230775Sjfv job->flags |= JOB_RESTART; 1941230775Sjfv TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 1942230775Sjfv } else { 1943230775Sjfv if (nJobs >= maxJobs) { 1944230775Sjfv /* 1945190873Sjfv * If we're running this job as a special case 1946251964Sjfv * (see above), at least say the table is full. 1947251964Sjfv */ 1948251964Sjfv jobFull = TRUE; 1949251964Sjfv DEBUGF(JOB, ("Local job queue is full.\n")); 1950251964Sjfv } 1951251964Sjfv JobExec(job, argv); 1952251964Sjfv } 1953251964Sjfv return (JOB_RUNNING); 1954251964Sjfv} 1955251964Sjfv 1956251964Sjfvstatic char * 1957251964SjfvJobOutput(Job *job, char *cp, char *endp, int msg) 1958230775Sjfv{ 1959230775Sjfv char *ecp; 1960230775Sjfv 1961230775Sjfv if (commandShell->noPrint) { 1962171384Sjfv ecp = strstr(cp, commandShell->noPrint); 1963230775Sjfv while (ecp != NULL) { 1964230775Sjfv if (cp != ecp) { 1965230775Sjfv *ecp = '\0'; 1966230775Sjfv if (msg && job->node != lastNode) { 1967230775Sjfv MESSAGE(stdout, job->node); 1968230775Sjfv lastNode = job->node; 1969230775Sjfv } 1970230775Sjfv /* 1971230775Sjfv * The only way there wouldn't be a newline 1972230775Sjfv * after this line is if it were the last in 1973230775Sjfv * the buffer. However, since the non-printable 1974230775Sjfv * comes after it, there must be a newline, so 1975238149Sjfv * we don't print one. 1976230775Sjfv */ 1977230775Sjfv fprintf(stdout, "%s", cp); 1978230775Sjfv fflush(stdout); 1979171384Sjfv } 1980251964Sjfv cp = ecp + strlen(commandShell->noPrint); 1981251964Sjfv if (cp != endp) { 1982251964Sjfv /* 1983251964Sjfv * Still more to print, look again after 1984251964Sjfv * skipping the whitespace following the 1985251964Sjfv * non-printable command.... 1986251964Sjfv */ 1987251964Sjfv cp++; 1988251964Sjfv while (*cp == ' ' || *cp == '\t' || 1989251964Sjfv *cp == '\n') { 1990251964Sjfv cp++; 1991171384Sjfv } 1992230775Sjfv ecp = strstr(cp, commandShell->noPrint); 1993171384Sjfv } else { 1994230775Sjfv return (cp); 1995171384Sjfv } 1996230775Sjfv } 1997171384Sjfv } 1998171384Sjfv return (cp); 1999230775Sjfv} 2000230775Sjfv 2001230775Sjfv/** 2002171384Sjfv * JobDoOutput 2003171384Sjfv * This function is called at different times depending on 2004230775Sjfv * whether the user has specified that output is to be collected 2005230775Sjfv * via pipes or temporary files. In the former case, we are called 2006230775Sjfv * whenever there is something to read on the pipe. We collect more 2007230775Sjfv * output from the given job and store it in the job's outBuf. If 2008171384Sjfv * this makes up a line, we print it tagged by the job's identifier, 2009171384Sjfv * as necessary. 2010230775Sjfv * If output has been collected in a temporary file, we open the 2011230775Sjfv * file and read it line by line, transfering it to our own 2012230775Sjfv * output channel until the file is empty. At which point we 2013230775Sjfv * remove the temporary file. 2014230775Sjfv * In both cases, however, we keep our figurative eye out for the 2015230775Sjfv * 'noPrint' line for the shell from which the output came. If 2016230775Sjfv * we recognize a line, we don't print it. If the command is not 2017230775Sjfv * alone on the line (the character after it is not \0 or \n), we 2018230775Sjfv * do print whatever follows it. 2019230775Sjfv * 2020230775Sjfv * Side Effects: 2021230775Sjfv * curPos may be shifted as may the contents of outBuf. 2022230775Sjfv */ 2023230775Sjfvstatic void 2024230775SjfvJobDoOutput(Job *job, Boolean finish) 2025230775Sjfv{ 2026171384Sjfv Boolean gotNL = FALSE; /* true if got a newline */ 2027171384Sjfv Boolean fbuf; /* true if our buffer filled up */ 2028230775Sjfv int nr; /* number of bytes read */ 2029230775Sjfv int i; /* auxiliary index into outBuf */ 2030230775Sjfv int max; /* limit for i (end of current data) */ 2031171384Sjfv int nRead; /* (Temporary) number of bytes read */ 2032230775Sjfv FILE *oFILE; /* Stream pointer to shell's output file */ 2033230775Sjfv char inLine[132]; 2034171384Sjfv 2035230775Sjfv if (usePipes) { 2036171384Sjfv /* 2037230775Sjfv * Read as many bytes as will fit in the buffer. 2038230775Sjfv */ 2039171384Sjfv end_loop: 2040171384Sjfv gotNL = FALSE; 2041230775Sjfv fbuf = FALSE; 2042230775Sjfv 2043230775Sjfv nRead = read(job->inPipe, &job->outBuf[job->curPos], 2044230775Sjfv JOB_BUFSIZE - job->curPos); 2045230775Sjfv /* 2046230775Sjfv * Check for interrupt here too, because the above read may 2047230775Sjfv * block when the child process is stopped. In this case the 2048171384Sjfv * interrupt will unblock it (we don't use SA_RESTART). 2049238149Sjfv */ 2050238149Sjfv if (interrupted) 2051238149Sjfv JobPassSig(interrupted); 2052238149Sjfv 2053230775Sjfv if (nRead < 0) { 2054230775Sjfv DEBUGF(JOB, ("JobDoOutput(piperead)")); 2055230775Sjfv nr = 0; 2056230775Sjfv } else { 2057230775Sjfv nr = nRead; 2058230775Sjfv } 2059230775Sjfv 2060230775Sjfv /* 2061230775Sjfv * If we hit the end-of-file (the job is dead), we must flush 2062230775Sjfv * its remaining output, so pretend we read a newline if 2063230775Sjfv * there's any output remaining in the buffer. 2064230775Sjfv * Also clear the 'finish' flag so we stop looping. 2065230775Sjfv */ 2066230775Sjfv if (nr == 0 && job->curPos != 0) { 2067230775Sjfv job->outBuf[job->curPos] = '\n'; 2068230775Sjfv nr = 1; 2069230775Sjfv finish = FALSE; 2070230775Sjfv } else if (nr == 0) { 2071230775Sjfv finish = FALSE; 2072230775Sjfv } 2073230775Sjfv 2074230775Sjfv /* 2075230775Sjfv * Look for the last newline in the bytes we just got. If there 2076230775Sjfv * is one, break out of the loop with 'i' as its index and 2077230775Sjfv * gotNL set TRUE. 2078230775Sjfv */ 2079230775Sjfv max = job->curPos + nr; 2080230775Sjfv for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 2081230775Sjfv if (job->outBuf[i] == '\n') { 2082230775Sjfv gotNL = TRUE; 2083230775Sjfv break; 2084230775Sjfv } else if (job->outBuf[i] == '\0') { 2085230775Sjfv /* 2086230775Sjfv * Why? 2087230775Sjfv */ 2088230775Sjfv job->outBuf[i] = ' '; 2089179055Sjfv } 2090230775Sjfv } 2091230775Sjfv 2092230775Sjfv if (!gotNL) { 2093230775Sjfv job->curPos += nr; 2094230775Sjfv if (job->curPos == JOB_BUFSIZE) { 2095230775Sjfv /* 2096238149Sjfv * If we've run out of buffer space, we have 2097230775Sjfv * no choice but to print the stuff. sigh. 2098171384Sjfv */ 2099171384Sjfv fbuf = TRUE; 2100230775Sjfv i = job->curPos; 2101230775Sjfv } 2102230775Sjfv } 2103230775Sjfv if (gotNL || fbuf) { 2104230775Sjfv /* 2105230775Sjfv * Need to send the output to the screen. Null terminate 2106230775Sjfv * it first, overwriting the newline character if there 2107230775Sjfv * was one. So long as the line isn't one we should 2108230775Sjfv * filter (according to the shell description), we print 2109230775Sjfv * the line, preceded by a target banner if this target 2110230775Sjfv * isn't the same as the one for which we last printed 2111230775Sjfv * something. The rest of the data in the buffer are 2112230775Sjfv * then shifted down to the start of the buffer and 2113230775Sjfv * curPos is set accordingly. 2114171384Sjfv */ 2115230775Sjfv job->outBuf[i] = '\0'; 2116230775Sjfv if (i >= job->curPos) { 2117230775Sjfv char *cp; 2118230775Sjfv 2119230775Sjfv cp = JobOutput(job, job->outBuf, 2120171384Sjfv &job->outBuf[i], FALSE); 2121230775Sjfv 2122171384Sjfv /* 2123190873Sjfv * There's still more in that buffer. This time, 2124230775Sjfv * though, we know there's no newline at the 2125230775Sjfv * end, so we add one of our own free will. 2126230775Sjfv */ 2127230775Sjfv if (*cp != '\0') { 2128230775Sjfv if (job->node != lastNode) { 2129190873Sjfv MESSAGE(stdout, job->node); 2130230775Sjfv lastNode = job->node; 2131230775Sjfv } 2132230775Sjfv fprintf(stdout, "%s%s", cp, 2133230775Sjfv gotNL ? "\n" : ""); 2134230775Sjfv fflush(stdout); 2135230775Sjfv } 2136230775Sjfv } 2137230775Sjfv if (i < max - 1) { 2138230775Sjfv /* shift the remaining characters down */ 2139171384Sjfv memcpy(job->outBuf, &job->outBuf[i + 1], 2140230775Sjfv max - (i + 1)); 2141230775Sjfv job->curPos = max - (i + 1); 2142230775Sjfv 2143230775Sjfv } else { 2144230775Sjfv /* 2145190873Sjfv * We have written everything out, so we just 2146230775Sjfv * start over from the start of the buffer. 2147230775Sjfv * No copying. No nothing. 2148230775Sjfv */ 2149230775Sjfv job->curPos = 0; 2150230775Sjfv } 2151230775Sjfv } 2152230775Sjfv if (finish) { 2153190873Sjfv /* 2154171384Sjfv * If the finish flag is true, we must loop until we hit 2155230775Sjfv * end-of-file on the pipe. This is guaranteed to happen 2156230775Sjfv * eventually since the other end of the pipe is now 2157230775Sjfv * closed (we closed it explicitly and the child has 2158230775Sjfv * exited). When we do get an EOF, finish will be set 2159230775Sjfv * FALSE and we'll fall through and out. 2160230775Sjfv */ 2161230775Sjfv goto end_loop; 2162230775Sjfv } 2163230775Sjfv 2164230775Sjfv } else { 2165230775Sjfv /* 2166230775Sjfv * We've been called to retrieve the output of the job from the 2167230775Sjfv * temporary file where it's been squirreled away. This consists 2168230775Sjfv * of opening the file, reading the output line by line, being 2169230775Sjfv * sure not to print the noPrint line for the shell we used, 2170230775Sjfv * then close and remove the temporary file. Very simple. 2171230775Sjfv * 2172230775Sjfv * Change to read in blocks and do FindSubString type things 2173230775Sjfv * as for pipes? That would allow for "@echo -n..." 2174230775Sjfv */ 2175230775Sjfv oFILE = fopen(job->outFile, "r"); 2176230775Sjfv if (oFILE != NULL) { 2177230775Sjfv fprintf(stdout, "Results of making %s:\n", 2178230775Sjfv job->node->name); 2179230775Sjfv fflush(stdout); 2180230775Sjfv 2181230775Sjfv while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 2182230775Sjfv char *cp, *endp, *oendp; 2183230775Sjfv 2184230775Sjfv cp = inLine; 2185230775Sjfv oendp = endp = inLine + strlen(inLine); 2186230775Sjfv if (endp[-1] == '\n') { 2187230775Sjfv *--endp = '\0'; 2188230775Sjfv } 2189230775Sjfv cp = JobOutput(job, inLine, endp, FALSE); 2190230775Sjfv 2191230775Sjfv /* 2192230775Sjfv * There's still more in that buffer. This time, 2193230775Sjfv * though, we know there's no newline at the 2194230775Sjfv * end, so we add one of our own free will. 2195230775Sjfv */ 2196230775Sjfv fprintf(stdout, "%s", cp); 2197230775Sjfv fflush(stdout); 2198230775Sjfv if (endp != oendp) { 2199230775Sjfv fprintf(stdout, "\n"); 2200230775Sjfv fflush(stdout); 2201230775Sjfv } 2202171384Sjfv } 2203230775Sjfv fclose(oFILE); 2204230775Sjfv eunlink(job->outFile); 2205230775Sjfv } 2206230775Sjfv } 2207230775Sjfv} 2208230775Sjfv 2209230775Sjfv/** 2210230775Sjfv * Job_CatchChildren 2211230775Sjfv * Handle the exit of a child. Called from Make_Make. 2212230775Sjfv * 2213230775Sjfv * Side Effects: 2214230775Sjfv * The job descriptor is removed from the list of children. 2215185352Sjfv * 2216190873Sjfv * Notes: 2217230775Sjfv * We do waits, blocking or not, according to the wisdom of our 2218230775Sjfv * caller, until there are no more children to report. For each 2219230775Sjfv * job, call JobFinish to finish things off. This will take care of 2220230775Sjfv * putting jobs on the stoppedJobs queue. 2221230775Sjfv */ 2222190873Sjfvvoid 2223171384SjfvJob_CatchChildren(Boolean block) 2224230775Sjfv{ 2225230775Sjfv pid_t pid; /* pid of dead child */ 2226230775Sjfv Job *job; /* job descriptor for dead child */ 2227230775Sjfv int status; /* Exit/termination status */ 2228230775Sjfv 2229230775Sjfv /* 2230230775Sjfv * Don't even bother if we know there's no one around. 2231171384Sjfv */ 2232230775Sjfv if (nJobs == 0) { 2233171384Sjfv return; 2234171384Sjfv } 2235230775Sjfv 2236171384Sjfv for (;;) { 2237230775Sjfv pid = waitpid((pid_t)-1, &status, 2238230775Sjfv (block ? 0 : WNOHANG) | WUNTRACED); 2239171384Sjfv if (pid <= 0) 2240230775Sjfv break; 2241230775Sjfv 2242230775Sjfv DEBUGF(JOB, ("Process %jd exited or stopped.\n", 2243230775Sjfv (intmax_t)pid)); 2244230775Sjfv 2245230775Sjfv TAILQ_FOREACH(job, &jobs, link) { 2246230775Sjfv if (job->pid == pid) 2247230775Sjfv break; 2248230775Sjfv } 2249171384Sjfv 2250171384Sjfv if (job == NULL) { 2251230775Sjfv if (WIFSIGNALED(status) && 2252230775Sjfv (WTERMSIG(status) == SIGCONT)) { 2253230775Sjfv TAILQ_FOREACH(job, &jobs, link) { 2254230775Sjfv if (job->pid == pid) 2255230775Sjfv break; 2256230775Sjfv } 2257171384Sjfv if (job == NULL) { 2258230775Sjfv Error("Resumed child (%jd) " 2259230775Sjfv "not in table", (intmax_t)pid); 2260171384Sjfv continue; 2261171384Sjfv } 2262171384Sjfv TAILQ_REMOVE(&stoppedJobs, job, link); 2263230775Sjfv } else { 2264230775Sjfv Error("Child (%jd) not in table?", 2265230775Sjfv (intmax_t)pid); 2266230775Sjfv continue; 2267230775Sjfv } 2268230775Sjfv } else { 2269230775Sjfv TAILQ_REMOVE(&jobs, job, link); 2270230775Sjfv nJobs -= 1; 2271230775Sjfv if (fifoFd >= 0 && maxJobs > 1) { 2272230775Sjfv write(fifoFd, "+", 1); 2273230775Sjfv maxJobs--; 2274230775Sjfv if (nJobs >= maxJobs) 2275230775Sjfv jobFull = TRUE; 2276230775Sjfv else 2277230775Sjfv jobFull = FALSE; 2278190873Sjfv } else { 2279190873Sjfv DEBUGF(JOB, ("Job queue is no longer full.\n")); 2280230775Sjfv jobFull = FALSE; 2281230775Sjfv } 2282230775Sjfv } 2283230775Sjfv 2284230775Sjfv JobFinish(job, &status); 2285190873Sjfv } 2286171384Sjfv if (interrupted) 2287171384Sjfv JobPassSig(interrupted); 2288230775Sjfv} 2289230775Sjfv 2290230775Sjfv/** 2291230775Sjfv * Job_CatchOutput 2292230775Sjfv * Catch the output from our children, if we're using 2293171384Sjfv * pipes do so. Otherwise just block time until we get a 2294171384Sjfv * signal(most likely a SIGCHLD) since there's no point in 2295230775Sjfv * just spinning when there's nothing to do and the reaping 2296230775Sjfv * of a child can wait for a while. 2297230775Sjfv * 2298230775Sjfv * Side Effects: 2299230775Sjfv * Output is read from pipes if we're piping. 2300171384Sjfv * ----------------------------------------------------------------------- 2301230775Sjfv */ 2302230775Sjfvvoid 2303171384Sjfv#ifdef USE_KQUEUE 2304230775SjfvJob_CatchOutput(int flag __unused) 2305171384Sjfv#else 2306171384SjfvJob_CatchOutput(int flag) 2307230775Sjfv#endif 2308230775Sjfv{ 2309230775Sjfv int nfds; 2310171384Sjfv#ifdef USE_KQUEUE 2311171384Sjfv#define KEV_SIZE 4 2312230775Sjfv struct kevent kev[KEV_SIZE]; 2313230775Sjfv int i; 2314230775Sjfv#else 2315230775Sjfv struct timeval timeout; 2316171384Sjfv fd_set readfds; 2317194875Sjfv Job *job; 2318230775Sjfv#endif 2319230775Sjfv 2320230775Sjfv fflush(stdout); 2321230775Sjfv 2322194875Sjfv if (usePipes) { 2323190873Sjfv#ifdef USE_KQUEUE 2324179055Sjfv if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) { 2325179055Sjfv if (errno != EINTR) 2326190873Sjfv Punt("kevent: %s", strerror(errno)); 2327190873Sjfv if (interrupted) 2328179055Sjfv JobPassSig(interrupted); 2329190873Sjfv } else { 2330190873Sjfv for (i = 0; i < nfds; i++) { 2331179055Sjfv if (kev[i].flags & EV_ERROR) { 2332179055Sjfv warnc(kev[i].data, "kevent"); 2333179055Sjfv continue; 2334185352Sjfv } 2335185352Sjfv switch (kev[i].filter) { 2336185352Sjfv case EVFILT_READ: 2337185352Sjfv JobDoOutput(kev[i].udata, FALSE); 2338185352Sjfv break; 2339179055Sjfv case EVFILT_PROC: 2340185352Sjfv /* 2341190873Sjfv * Just wake up and let 2342230775Sjfv * Job_CatchChildren() collect the 2343230775Sjfv * terminated job. 2344230775Sjfv */ 2345230775Sjfv break; 2346190873Sjfv } 2347179055Sjfv } 2348190873Sjfv } 2349230775Sjfv#else 2350230775Sjfv readfds = outputs; 2351230775Sjfv timeout.tv_sec = SEL_SEC; 2352230775Sjfv timeout.tv_usec = SEL_USEC; 2353230775Sjfv if (flag && jobFull && fifoFd >= 0) 2354230775Sjfv FD_SET(fifoFd, &readfds); 2355230775Sjfv 2356230775Sjfv nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL, 2357230775Sjfv (fd_set *)NULL, &timeout); 2358230775Sjfv if (nfds <= 0) { 2359230775Sjfv if (interrupted) 2360230775Sjfv JobPassSig(interrupted); 2361230775Sjfv return; 2362190873Sjfv } 2363230775Sjfv if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) { 2364230775Sjfv if (--nfds <= 0) 2365230775Sjfv return; 2366230775Sjfv } 2367230775Sjfv job = TAILQ_FIRST(&jobs); 2368230775Sjfv while (nfds != 0 && job != NULL) { 2369230775Sjfv if (FD_ISSET(job->inPipe, &readfds)) { 2370230775Sjfv JobDoOutput(job, FALSE); 2371230775Sjfv nfds--; 2372190873Sjfv } 2373230775Sjfv job = TAILQ_NEXT(job, link); 2374230775Sjfv } 2375230775Sjfv#endif /* !USE_KQUEUE */ 2376230775Sjfv } 2377230775Sjfv} 2378230775Sjfv 2379230775Sjfv/** 2380230775Sjfv * Job_Make 2381230775Sjfv * Start the creation of a target. Basically a front-end for 2382230775Sjfv * JobStart used by the Make module. 2383230775Sjfv * 2384230775Sjfv * Side Effects: 2385230775Sjfv * Another job is started. 2386230775Sjfv */ 2387230775Sjfvvoid 2388230775SjfvJob_Make(GNode *gn) 2389230775Sjfv{ 2390230775Sjfv 2391230775Sjfv JobStart(gn, 0, NULL); 2392230775Sjfv} 2393190873Sjfv 2394230775Sjfv/** 2395230775Sjfv * JobCopyShell 2396230775Sjfv * Make a new copy of the shell structure including a copy of the strings 2397230775Sjfv * in it. This also defaults some fields in case they are NULL. 2398230775Sjfv * 2399230775Sjfv * Returns: 2400230775Sjfv * The function returns a pointer to the new shell structure. 2401230775Sjfv */ 2402230775Sjfvstatic struct Shell * 2403230775SjfvJobCopyShell(const struct Shell *osh) 2404230775Sjfv{ 2405230775Sjfv struct Shell *nsh; 2406230775Sjfv 2407230775Sjfv nsh = emalloc(sizeof(*nsh)); 2408230775Sjfv nsh->name = estrdup(osh->name); 2409230775Sjfv 2410230775Sjfv if (osh->echoOff != NULL) 2411230775Sjfv nsh->echoOff = estrdup(osh->echoOff); 2412230775Sjfv else 2413230775Sjfv nsh->echoOff = NULL; 2414230775Sjfv if (osh->echoOn != NULL) 2415230775Sjfv nsh->echoOn = estrdup(osh->echoOn); 2416190873Sjfv else 2417230775Sjfv nsh->echoOn = NULL; 2418230775Sjfv nsh->hasEchoCtl = osh->hasEchoCtl; 2419230775Sjfv 2420251964Sjfv if (osh->noPrint != NULL) 2421251964Sjfv nsh->noPrint = estrdup(osh->noPrint); 2422251964Sjfv else 2423251964Sjfv nsh->noPrint = NULL; 2424251964Sjfv 2425251964Sjfv nsh->hasErrCtl = osh->hasErrCtl; 2426251964Sjfv if (osh->errCheck == NULL) 2427251964Sjfv nsh->errCheck = estrdup(""); 2428230775Sjfv else 2429230775Sjfv nsh->errCheck = estrdup(osh->errCheck); 2430230775Sjfv if (osh->ignErr == NULL) 2431230775Sjfv nsh->ignErr = estrdup("%s"); 2432230775Sjfv else 2433230775Sjfv nsh->ignErr = estrdup(osh->ignErr); 2434230775Sjfv 2435230775Sjfv if (osh->echo == NULL) 2436230775Sjfv nsh->echo = estrdup(""); 2437230775Sjfv else 2438230775Sjfv nsh->echo = estrdup(osh->echo); 2439230775Sjfv 2440230775Sjfv if (osh->exit == NULL) 2441230775Sjfv nsh->exit = estrdup(""); 2442230775Sjfv else 2443230775Sjfv nsh->exit = estrdup(osh->exit); 2444230775Sjfv 2445230775Sjfv return (nsh); 2446230775Sjfv} 2447230775Sjfv 2448230775Sjfv/** 2449230775Sjfv * JobFreeShell 2450230775Sjfv * Free a shell structure and all associated strings. 2451230775Sjfv */ 2452230775Sjfvstatic void 2453230775SjfvJobFreeShell(struct Shell *sh) 2454230775Sjfv{ 2455230775Sjfv 2456230775Sjfv if (sh != NULL) { 2457230775Sjfv free(sh->name); 2458230775Sjfv free(sh->echoOff); 2459230775Sjfv free(sh->echoOn); 2460230775Sjfv free(sh->noPrint); 2461230775Sjfv free(sh->errCheck); 2462230775Sjfv free(sh->ignErr); 2463230775Sjfv free(sh->echo); 2464230775Sjfv free(sh->exit); 2465230775Sjfv free(sh); 2466171384Sjfv } 2467171384Sjfv} 2468230775Sjfv 2469171384Sjfvvoid 2470179055SjfvShell_Init(void) 2471171384Sjfv{ 2472230775Sjfv 2473230775Sjfv if (commandShell == NULL) 2474230775Sjfv commandShell = JobMatchShell(shells[DEFSHELL].name); 2475171384Sjfv 2476171384Sjfv if (shellPath == NULL) { 2477171384Sjfv /* 2478179055Sjfv * The user didn't specify a shell to use, so we are using the 2479171384Sjfv * default one... Both the absolute path and the last component 2480230775Sjfv * must be set. The last component is taken from the 'name' 2481230775Sjfv * field of the default shell description pointed-to by 2482179055Sjfv * commandShell. All default shells are located in 2483171384Sjfv * PATH_DEFSHELLDIR. 2484171384Sjfv */ 2485171384Sjfv shellName = commandShell->name; 2486171384Sjfv shellPath = str_concat(PATH_DEFSHELLDIR, shellName, 2487171384Sjfv STR_ADDSLASH); 2488171384Sjfv } 2489171384Sjfv} 2490230775Sjfv 2491179055Sjfv/** 2492179055Sjfv * Job_Init 2493171384Sjfv * Initialize the process module, given a maximum number of jobs. 2494171384Sjfv * 2495230775Sjfv * Side Effects: 2496179055Sjfv * lists and counters are initialized 2497179055Sjfv */ 2498171384Sjfvvoid 2499171384SjfvJob_Init(int maxproc) 2500171384Sjfv{ 2501171384Sjfv GNode *begin; /* node for commands to do at the very start */ 2502171384Sjfv const char *env; 2503179055Sjfv struct sigaction sa; 2504230775Sjfv 2505230775Sjfv fifoFd = -1; 2506230775Sjfv env = getenv("MAKE_JOBS_FIFO"); 2507230775Sjfv 2508179055Sjfv if (env == NULL && maxproc > 1) { 2509171384Sjfv /* 2510171384Sjfv * We did not find the environment variable so we are the 2511171384Sjfv * leader. Create the fifo, open it, write one char per 2512171384Sjfv * allowed job into the pipe. 2513171384Sjfv */ 2514179055Sjfv mktemp(fifoName); 2515179055Sjfv if (!mkfifo(fifoName, 0600)) { 2516171384Sjfv fifoFd = open(fifoName, O_RDWR | O_NONBLOCK, 0); 2517171384Sjfv if (fifoFd >= 0) { 2518171384Sjfv fifoMaster = 1; 2519179055Sjfv fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2520179055Sjfv env = fifoName; 2521179055Sjfv setenv("MAKE_JOBS_FIFO", env, 1); 2522181003Sjfv while (maxproc-- > 0) { 2523181003Sjfv write(fifoFd, "+", 1); 2524179055Sjfv } 2525171384Sjfv /* The master make does not get a magic token */ 2526171384Sjfv jobFull = TRUE; 2527179055Sjfv maxJobs = 0; 2528171384Sjfv } else { 2529179055Sjfv unlink(fifoName); 2530179055Sjfv env = NULL; 2531171384Sjfv } 2532171384Sjfv } 2533171384Sjfv 2534171384Sjfv } else if (env != NULL) { 2535179055Sjfv /* 2536179055Sjfv * We had the environment variable so we are a slave. 2537179055Sjfv * Open fifo and give ourselves a magic token which represents 2538171384Sjfv * the token our parent make has grabbed to start his make 2539171384Sjfv * process. Otherwise the sub-makes would gobble up tokens and 2540171384Sjfv * the proper number of tokens to specify to -j would depend 2541171384Sjfv * on the depth of the tree and the order of execution. 2542171384Sjfv */ 2543171384Sjfv fifoFd = open(env, O_RDWR, 0); 2544179055Sjfv if (fifoFd >= 0) { 2545179055Sjfv fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2546179055Sjfv maxJobs = 1; 2547179055Sjfv jobFull = FALSE; 2548171384Sjfv } 2549171384Sjfv } 2550171384Sjfv if (fifoFd <= 0) { 2551230775Sjfv maxJobs = maxproc; 2552230775Sjfv jobFull = FALSE; 2553230775Sjfv } else { 2554230775Sjfv } 2555230775Sjfv nJobs = 0; 2556230775Sjfv 2557230775Sjfv aborting = 0; 2558230775Sjfv errors = 0; 2559230775Sjfv 2560230775Sjfv lastNode = NULL; 2561230775Sjfv 2562230775Sjfv if ((maxJobs == 1 && fifoFd < 0) || beVerbose == 0) { 2563230775Sjfv /* 2564230775Sjfv * If only one job can run at a time, there's no need for a 2565230775Sjfv * banner, no is there? 2566230775Sjfv */ 2567230775Sjfv targFmt = ""; 2568230775Sjfv } else { 2569230775Sjfv targFmt = TARG_FMT; 2570230775Sjfv } 2571230775Sjfv 2572230775Sjfv Shell_Init(); 2573230775Sjfv 2574230775Sjfv /* 2575230775Sjfv * Catch the four signals that POSIX specifies if they aren't ignored. 2576230775Sjfv * JobCatchSignal will just set global variables and hope someone 2577230775Sjfv * else is going to handle the interrupt. 2578230775Sjfv */ 2579230775Sjfv sa.sa_handler = JobCatchSig; 2580230775Sjfv sigemptyset(&sa.sa_mask); 2581230775Sjfv sa.sa_flags = 0; 2582230775Sjfv 2583230775Sjfv if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 2584230775Sjfv sigaction(SIGINT, &sa, NULL); 2585230775Sjfv } 2586230775Sjfv if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 2587230775Sjfv sigaction(SIGHUP, &sa, NULL); 2588230775Sjfv } 2589230775Sjfv if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 2590230775Sjfv sigaction(SIGQUIT, &sa, NULL); 2591230775Sjfv } 2592190873Sjfv if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 2593190873Sjfv sigaction(SIGTERM, &sa, NULL); 2594230775Sjfv } 2595230775Sjfv /* 2596230775Sjfv * There are additional signals that need to be caught and passed if 2597230775Sjfv * either the export system wants to be told directly of signals or if 2598230775Sjfv * we're giving each job its own process group (since then it won't get 2599230775Sjfv * signals from the terminal driver as we own the terminal) 2600230775Sjfv */ 2601230775Sjfv#if defined(USE_PGRP) 2602230775Sjfv if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { 2603230775Sjfv sigaction(SIGTSTP, &sa, NULL); 2604230775Sjfv } 2605230775Sjfv if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { 2606171384Sjfv sigaction(SIGTTOU, &sa, NULL); 2607171384Sjfv } 2608171384Sjfv if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { 2609171384Sjfv sigaction(SIGTTIN, &sa, NULL); 2610171384Sjfv } 2611230775Sjfv if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { 2612230775Sjfv sigaction(SIGWINCH, &sa, NULL); 2613230775Sjfv } 2614230775Sjfv#endif 2615230775Sjfv 2616230775Sjfv#ifdef USE_KQUEUE 2617230775Sjfv if ((kqfd = kqueue()) == -1) { 2618230775Sjfv Punt("kqueue: %s", strerror(errno)); 2619230775Sjfv } 2620171384Sjfv#endif 2621185352Sjfv 2622185352Sjfv begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); 2623230775Sjfv 2624230775Sjfv if (begin != NULL) { 2625230775Sjfv JobStart(begin, JOB_SPECIAL, (Job *)NULL); 2626230775Sjfv while (nJobs) { 2627230775Sjfv Job_CatchOutput(0); 2628230775Sjfv Job_CatchChildren(!usePipes); 2629230775Sjfv } 2630230775Sjfv } 2631230775Sjfv postCommands = Targ_FindNode(".END", TARG_CREATE); 2632230775Sjfv} 2633230775Sjfv 2634230775Sjfv/** 2635230775Sjfv * Job_Full 2636230775Sjfv * See if the job table is full. It is considered full if it is OR 2637230775Sjfv * if we are in the process of aborting OR if we have 2638238149Sjfv * reached/exceeded our local quota. This prevents any more jobs 2639185352Sjfv * from starting up. 2640230775Sjfv * 2641230775Sjfv * Results: 2642230775Sjfv * TRUE if the job table is full, FALSE otherwise 2643205720Sjfv */ 2644230775SjfvBoolean 2645238149SjfvJob_Full(void) 2646230775Sjfv{ 2647215911Sjfv char c; 2648230775Sjfv int i; 2649230775Sjfv 2650230775Sjfv if (aborting) 2651230775Sjfv return (aborting); 2652230775Sjfv if (fifoFd >= 0 && jobFull) { 2653230775Sjfv i = read(fifoFd, &c, 1); 2654230775Sjfv if (i > 0) { 2655230775Sjfv maxJobs++; 2656230775Sjfv jobFull = FALSE; 2657230775Sjfv } 2658230775Sjfv } 2659230775Sjfv return (jobFull); 2660230775Sjfv} 2661230775Sjfv 2662230775Sjfv/** 2663230775Sjfv * Job_Empty 2664230775Sjfv * See if the job table is empty. Because the local concurrency may 2665230775Sjfv * be set to 0, it is possible for the job table to become empty, 2666230775Sjfv * while the list of stoppedJobs remains non-empty. In such a case, 2667230775Sjfv * we want to restart as many jobs as we can. 2668230775Sjfv * 2669230775Sjfv * Results: 2670230775Sjfv * TRUE if it is. FALSE if it ain't. 2671230775Sjfv */ 2672230775SjfvBoolean 2673230775SjfvJob_Empty(void) 2674230775Sjfv{ 2675230775Sjfv if (nJobs == 0) { 2676238149Sjfv if (!TAILQ_EMPTY(&stoppedJobs) && !aborting) { 2677238149Sjfv /* 2678238149Sjfv * The job table is obviously not full if it has no 2679238149Sjfv * jobs in it...Try and restart the stopped jobs. 2680238149Sjfv */ 2681238149Sjfv jobFull = FALSE; 2682238149Sjfv JobRestartJobs(); 2683238149Sjfv return (FALSE); 2684230775Sjfv } else { 2685230775Sjfv return (TRUE); 2686238149Sjfv } 2687238149Sjfv } else { 2688238149Sjfv return (FALSE); 2689238149Sjfv } 2690238149Sjfv} 2691238149Sjfv 2692238149Sjfv/** 2693238149Sjfv * JobMatchShell 2694230775Sjfv * Find a matching shell in 'shells' given its final component. 2695230775Sjfv * 2696238149Sjfv * Results: 2697238149Sjfv * A pointer to a freshly allocated Shell structure with a copy 2698238149Sjfv * of the static structure or NULL if no shell with the given name 2699238149Sjfv * is found. 2700238149Sjfv */ 2701230775Sjfvstatic struct Shell * 2702190873SjfvJobMatchShell(const char *name) 2703230775Sjfv{ 2704230775Sjfv const struct CShell *sh; /* Pointer into shells table */ 2705185352Sjfv struct Shell *nsh; 2706215911Sjfv 2707230775Sjfv for (sh = shells; sh < shells + sizeof(shells)/sizeof(shells[0]); sh++) 2708230775Sjfv if (strcmp(sh->name, name) == 0) 2709230775Sjfv break; 2710230775Sjfv 2711230775Sjfv if (sh == shells + sizeof(shells)/sizeof(shells[0])) 2712230775Sjfv return (NULL); 2713215911Sjfv 2714230775Sjfv /* make a copy */ 2715230775Sjfv nsh = emalloc(sizeof(*nsh)); 2716230775Sjfv 2717230775Sjfv nsh->name = estrdup(sh->name); 2718230775Sjfv nsh->echoOff = estrdup(sh->echoOff); 2719230775Sjfv nsh->echoOn = estrdup(sh->echoOn); 2720230775Sjfv nsh->hasEchoCtl = sh->hasEchoCtl; 2721230775Sjfv nsh->noPrint = estrdup(sh->noPrint); 2722215911Sjfv nsh->hasErrCtl = sh->hasErrCtl; 2723190873Sjfv nsh->errCheck = estrdup(sh->errCheck); 2724190873Sjfv nsh->ignErr = estrdup(sh->ignErr); 2725215911Sjfv nsh->echo = estrdup(sh->echo); 2726217593Sjfv nsh->exit = estrdup(sh->exit); 2727217593Sjfv 2728190873Sjfv return (nsh); 2729230775Sjfv} 2730230775Sjfv 2731230775Sjfv/** 2732230775Sjfv * Job_ParseShell 2733230775Sjfv * Parse a shell specification and set up commandShell, shellPath 2734230775Sjfv * and shellName appropriately. 2735230775Sjfv * 2736230775Sjfv * Results: 2737230775Sjfv * FAILURE if the specification was incorrect. 2738190873Sjfv * 2739215911Sjfv * Side Effects: 2740230775Sjfv * commandShell points to a Shell structure (either predefined or 2741230775Sjfv * created from the shell spec), shellPath is the full path of the 2742215911Sjfv * shell described by commandShell, while shellName is just the 2743215911Sjfv * final component of shellPath. 2744215911Sjfv * 2745215911Sjfv * Notes: 2746215911Sjfv * A shell specification consists of a .SHELL target, with dependency 2747215911Sjfv * operator, followed by a series of blank-separated words. Double 2748230775Sjfv * quotes can be used to use blanks in words. A backslash escapes 2749215911Sjfv * anything (most notably a double-quote and a space) and 2750215911Sjfv * provides the functionality it does in C. Each word consists of 2751190873Sjfv * keyword and value separated by an equal sign. There should be no 2752190873Sjfv * unnecessary spaces in the word. The keywords are as follows: 2753217593Sjfv * name Name of shell. 2754217593Sjfv * path Location of shell. Overrides "name" if given 2755217593Sjfv * quiet Command to turn off echoing. 2756217593Sjfv * echo Command to turn echoing on 2757217593Sjfv * filter Result of turning off echoing that shouldn't be 2758217593Sjfv * printed. 2759217593Sjfv * echoFlag Flag to turn echoing on at the start 2760217593Sjfv * errFlag Flag to turn error checking on at the start 2761217593Sjfv * hasErrCtl True if shell has error checking control 2762217593Sjfv * check Command to turn on error checking if hasErrCtl 2763217593Sjfv * is TRUE or template of command to echo a command 2764217593Sjfv * for which error checking is off if hasErrCtl is 2765217593Sjfv * FALSE. 2766217593Sjfv * ignore Command to turn off error checking if hasErrCtl 2767217593Sjfv * is TRUE or template of command to execute a 2768217593Sjfv * command so as to ignore any errors it returns if 2769217593Sjfv * hasErrCtl is FALSE. 2770215911Sjfv */ 2771215911SjfvReturnStatus 2772215911SjfvJob_ParseShell(char *line) 2773215911Sjfv{ 2774215911Sjfv char **words; 2775215911Sjfv int wordCount; 2776230775Sjfv char **argv; 2777230775Sjfv int argc; 2778230775Sjfv char *path; 2779215911Sjfv char *eq; 2780215911Sjfv Boolean fullSpec = FALSE; 2781171384Sjfv struct Shell newShell; 2782171384Sjfv struct Shell *sh; 2783171384Sjfv 2784200239Sjfv while (isspace((unsigned char)*line)) { 2785171384Sjfv line++; 2786171384Sjfv } 2787171384Sjfv words = brk_string(line, &wordCount, TRUE); 2788171384Sjfv 2789171384Sjfv memset(&newShell, 0, sizeof(newShell)); 2790171384Sjfv path = NULL; 2791190873Sjfv 2792215911Sjfv /* 2793230775Sjfv * Parse the specification by keyword but skip the first word - it 2794230775Sjfv * is not set by brk_string. 2795171384Sjfv */ 2796171384Sjfv wordCount--; 2797171384Sjfv words++; 2798171384Sjfv 2799171384Sjfv for (argc = wordCount, argv = words; argc != 0; argc--, argv++) { 2800190873Sjfv /* 2801179055Sjfv * Split keyword and value 2802190873Sjfv */ 2803190873Sjfv if ((eq = strchr(*argv, '=')) == NULL) { 2804171384Sjfv Parse_Error(PARSE_FATAL, "missing '=' in shell " 2805179055Sjfv "specification keyword '%s'", *argv); 2806185352Sjfv return (FAILURE); 2807205720Sjfv } 2808205720Sjfv *eq++ = '\0'; 2809205720Sjfv 2810185352Sjfv if (strcmp(*argv, "path") == 0) { 2811185352Sjfv path = eq; 2812205720Sjfv } else if (strcmp(*argv, "name") == 0) { 2813185352Sjfv newShell.name = eq; 2814190873Sjfv } else if (strcmp(*argv, "quiet") == 0) { 2815190873Sjfv newShell.echoOff = eq; 2816179055Sjfv fullSpec = TRUE; 2817171384Sjfv } else if (strcmp(*argv, "echo") == 0) { 2818171384Sjfv newShell.echoOn = eq; 2819185352Sjfv fullSpec = TRUE; 2820185352Sjfv } else if (strcmp(*argv, "filter") == 0) { 2821185352Sjfv newShell.noPrint = eq; 2822185352Sjfv fullSpec = TRUE; 2823185352Sjfv } else if (strcmp(*argv, "echoFlag") == 0) { 2824185352Sjfv newShell.echo = eq; 2825185352Sjfv fullSpec = TRUE; 2826185352Sjfv } else if (strcmp(*argv, "errFlag") == 0) { 2827230775Sjfv newShell.exit = eq; 2828230775Sjfv fullSpec = TRUE; 2829230775Sjfv } else if (strcmp(*argv, "hasErrCtl") == 0) { 2830230775Sjfv newShell.hasErrCtl = (*eq == 'Y' || *eq == 'y' || 2831185352Sjfv *eq == 'T' || *eq == 't'); 2832185352Sjfv fullSpec = TRUE; 2833185352Sjfv } else if (strcmp(*argv, "check") == 0) { 2834185352Sjfv newShell.errCheck = eq; 2835185352Sjfv fullSpec = TRUE; 2836190873Sjfv } else if (strcmp(*argv, "ignore") == 0) { 2837190873Sjfv newShell.ignErr = eq; 2838190873Sjfv fullSpec = TRUE; 2839190873Sjfv } else { 2840205720Sjfv Parse_Error(PARSE_FATAL, "unknown keyword in shell " 2841205720Sjfv "specification '%s'", *argv); 2842215911Sjfv return (FAILURE); 2843215911Sjfv } 2844238149Sjfv } 2845238149Sjfv 2846185352Sjfv /* 2847185352Sjfv * Some checks (could be more) 2848185352Sjfv */ 2849185352Sjfv if (fullSpec) { 2850171384Sjfv if ((newShell.echoOn != NULL) ^ (newShell.echoOff != NULL)) 2851171384Sjfv Parse_Error(PARSE_FATAL, "Shell must have either both " 2852171384Sjfv "echoOff and echoOn or none of them"); 2853247822Sjfv 2854171384Sjfv if (newShell.echoOn != NULL && newShell.echoOff) 2855179055Sjfv newShell.hasEchoCtl = TRUE; 2856200239Sjfv } 2857179055Sjfv 2858171384Sjfv if (path == NULL) { 2859171384Sjfv /* 2860171384Sjfv * If no path was given, the user wants one of the pre-defined 2861185352Sjfv * shells, yes? So we find the one s/he wants with the help of 2862171384Sjfv * JobMatchShell and set things up the right way. shellPath 2863171384Sjfv * will be set up by Job_Init. 2864171384Sjfv */ 2865171384Sjfv if (newShell.name == NULL) { 2866171384Sjfv Parse_Error(PARSE_FATAL, 2867171384Sjfv "Neither path nor name specified"); 2868171384Sjfv return (FAILURE); 2869200239Sjfv } 2870200239Sjfv if ((sh = JobMatchShell(newShell.name)) == NULL) { 2871200239Sjfv Parse_Error(PARSE_FATAL, "%s: no matching shell", 2872200239Sjfv newShell.name); 2873200239Sjfv return (FAILURE); 2874200239Sjfv } 2875200239Sjfv 2876200239Sjfv } else { 2877171384Sjfv /* 2878171384Sjfv * The user provided a path. If s/he gave nothing else 2879171384Sjfv * (fullSpec is FALSE), try and find a matching shell in the 2880171384Sjfv * ones we know of. Else we just take the specification at its 2881171384Sjfv * word and copy it to a new location. In either case, we need 2882171384Sjfv * to record the path the user gave for the shell. 2883171384Sjfv */ 2884171384Sjfv free(shellPath); 2885171384Sjfv shellPath = estrdup(path); 2886171384Sjfv if (newShell.name == NULL) { 2887171384Sjfv /* get the base name as the name */ 2888230775Sjfv path = strrchr(path, '/'); 2889230775Sjfv if (path == NULL) { 2890230775Sjfv path = shellPath; 2891230775Sjfv } else { 2892230775Sjfv path += 1; 2893230775Sjfv } 2894230775Sjfv newShell.name = path; 2895230775Sjfv } 2896238149Sjfv 2897171384Sjfv if (!fullSpec) { 2898171384Sjfv if ((sh = JobMatchShell(newShell.name)) == NULL) { 2899171384Sjfv Parse_Error(PARSE_FATAL, 2900171384Sjfv "%s: no matching shell", newShell.name); 2901171384Sjfv return (FAILURE); 2902230775Sjfv } 2903230775Sjfv } else { 2904230775Sjfv sh = JobCopyShell(&newShell); 2905230775Sjfv } 2906230775Sjfv } 2907230775Sjfv 2908230775Sjfv /* set the new shell */ 2909171384Sjfv JobFreeShell(commandShell); 2910171384Sjfv commandShell = sh; 2911171384Sjfv 2912171384Sjfv shellName = commandShell->name; 2913171384Sjfv 2914171384Sjfv return (SUCCESS); 2915171384Sjfv} 2916179055Sjfv 2917179055Sjfv/** 2918171384Sjfv * JobInterrupt 2919171384Sjfv * Handle the receipt of an interrupt. 2920171384Sjfv * 2921171384Sjfv * Side Effects: 2922171384Sjfv * All children are killed. Another job will be started if the 2923171384Sjfv * .INTERRUPT target was given. 2924171384Sjfv */ 2925185352Sjfvstatic void 2926185352SjfvJobInterrupt(int runINTERRUPT, int signo) 2927190873Sjfv{ 2928171384Sjfv Job *job; /* job descriptor in that element */ 2929171384Sjfv GNode *interrupt; /* the node describing the .INTERRUPT target */ 2930171384Sjfv 2931171384Sjfv aborting = ABORT_INTERRUPT; 2932230775Sjfv 2933238149Sjfv TAILQ_FOREACH(job, &jobs, link) { 2934171384Sjfv if (!Targ_Precious(job->node)) { 2935171384Sjfv char *file = (job->node->path == NULL ? 2936171384Sjfv job->node->name : job->node->path); 2937190873Sjfv 2938190873Sjfv if (!noExecute && eunlink(file) != -1) { 2939185352Sjfv Error("*** %s removed", file); 2940185352Sjfv } 2941171384Sjfv } 2942171384Sjfv if (job->pid) { 2943171384Sjfv DEBUGF(JOB, ("JobInterrupt passing signal to child " 2944171384Sjfv "%jd.\n", (intmax_t)job->pid)); 2945171384Sjfv KILL(job->pid, signo); 2946171384Sjfv } 2947171384Sjfv } 2948171384Sjfv 2949171384Sjfv if (runINTERRUPT && !touchFlag) { 2950171384Sjfv /* 2951171384Sjfv * clear the interrupted flag because we would get an 2952171384Sjfv * infinite loop otherwise. 2953171384Sjfv */ 2954171384Sjfv interrupted = 0; 2955171384Sjfv 2956171384Sjfv interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 2957171384Sjfv if (interrupt != NULL) { 2958171384Sjfv ignoreErrors = FALSE; 2959171384Sjfv 2960171384Sjfv JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL); 2961171384Sjfv while (nJobs) { 2962171384Sjfv Job_CatchOutput(0); 2963171384Sjfv Job_CatchChildren(!usePipes); 2964171384Sjfv } 2965171384Sjfv } 2966171384Sjfv } 2967171384Sjfv} 2968171384Sjfv 2969171384Sjfv/** 2970171384Sjfv * Job_Finish 2971171384Sjfv * Do final processing such as the running of the commands 2972171384Sjfv * attached to the .END target. 2973171384Sjfv * 2974171384Sjfv * Results: 2975171384Sjfv * Number of errors reported. 2976171384Sjfv */ 2977171384Sjfvint 2978171384SjfvJob_Finish(void) 2979171384Sjfv{ 2980171384Sjfv 2981171384Sjfv if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { 2982171384Sjfv if (errors) { 2983171384Sjfv Error("Errors reported so .END ignored"); 2984171384Sjfv } else { 2985171384Sjfv JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); 2986171384Sjfv 2987171384Sjfv while (nJobs) { 2988171384Sjfv Job_CatchOutput(0); 2989171384Sjfv Job_CatchChildren(!usePipes); 2990171384Sjfv } 2991171384Sjfv } 2992171384Sjfv } 2993171384Sjfv if (fifoFd >= 0) { 2994171384Sjfv close(fifoFd); 2995171384Sjfv fifoFd = -1; 2996171384Sjfv if (fifoMaster) 2997171384Sjfv unlink(fifoName); 2998190873Sjfv } 2999190873Sjfv return (errors); 3000190873Sjfv} 3001190873Sjfv 3002190873Sjfv/** 3003190873Sjfv * Job_Wait 3004190873Sjfv * Waits for all running jobs to finish and returns. Sets 'aborting' 3005190873Sjfv * to ABORT_WAIT to prevent other jobs from starting. 3006190873Sjfv * 3007190873Sjfv * Side Effects: 3008190873Sjfv * Currently running jobs finish. 3009190873Sjfv */ 3010190873Sjfvvoid 3011190873SjfvJob_Wait(void) 3012190873Sjfv{ 3013230775Sjfv 3014230775Sjfv aborting = ABORT_WAIT; 3015230775Sjfv while (nJobs != 0) { 3016230775Sjfv Job_CatchOutput(0); 3017230775Sjfv Job_CatchChildren(!usePipes); 3018230775Sjfv } 3019230775Sjfv aborting = 0; 3020230775Sjfv} 3021171384Sjfv 3022171384Sjfv/** 3023171384Sjfv * Job_AbortAll 3024171384Sjfv * Abort all currently running jobs without handling output or anything. 3025171384Sjfv * This function is to be called only in the event of a major 3026179055Sjfv * error. Most definitely NOT to be called from JobInterrupt. 3027179055Sjfv * 3028230775Sjfv * Side Effects: 3029179055Sjfv * All children are killed, not just the firstborn 3030171384Sjfv */ 3031179055Sjfvvoid 3032179055SjfvJob_AbortAll(void) 3033179055Sjfv{ 3034230775Sjfv Job *job; /* the job descriptor in that element */ 3035179055Sjfv int foo; 3036230775Sjfv 3037179055Sjfv aborting = ABORT_ERROR; 3038179055Sjfv 3039200239Sjfv if (nJobs) { 3040179055Sjfv TAILQ_FOREACH(job, &jobs, link) { 3041171384Sjfv /* 3042179055Sjfv * kill the child process with increasingly drastic 3043179055Sjfv * signals to make darn sure it's dead. 3044179055Sjfv */ 3045179055Sjfv KILL(job->pid, SIGINT); 3046179055Sjfv KILL(job->pid, SIGKILL); 3047205720Sjfv } 3048179055Sjfv } 3049185352Sjfv 3050179055Sjfv /* 3051190873Sjfv * Catch as many children as want to report in at first, then give up 3052190873Sjfv */ 3053190873Sjfv while (waitpid((pid_t)-1, &foo, WNOHANG) > 0) 3054200239Sjfv ; 3055215911Sjfv} 3056179055Sjfv 3057179055Sjfv/** 3058185352Sjfv * JobRestartJobs 3059179055Sjfv * Tries to restart stopped jobs if there are slots available. 3060179055Sjfv * Note that this tries to restart them regardless of pending errors. 3061190873Sjfv * It's not good to leave stopped jobs lying around! 3062190873Sjfv * 3063230775Sjfv * Side Effects: 3064230775Sjfv * Resumes(and possibly migrates) jobs. 3065194875Sjfv */ 3066194875Sjfvstatic void 3067179055SjfvJobRestartJobs(void) 3068171384Sjfv{ 3069215911Sjfv Job *job; 3070215911Sjfv 3071215911Sjfv while (!jobFull && (job = TAILQ_FIRST(&stoppedJobs)) != NULL) { 3072247822Sjfv DEBUGF(JOB, ("Job queue is not full. " 3073179055Sjfv "Restarting a stopped job.\n")); 3074179055Sjfv TAILQ_REMOVE(&stoppedJobs, job, link); 3075230775Sjfv JobRestart(job); 3076171384Sjfv } 3077230775Sjfv} 3078230775Sjfv 3079230775Sjfv/** 3080171384Sjfv * Cmd_Exec 3081179055Sjfv * Execute the command in cmd, and return the output of that command 3082179055Sjfv * in a string. 3083179055Sjfv * 3084179055Sjfv * Results: 3085171384Sjfv * A string containing the output of the command, or the empty string 3086171384Sjfv * If error is not NULL, it contains the reason for the command failure 3087179055Sjfv * Any output sent to stderr in the child process is passed to stderr, 3088230775Sjfv * and not captured in the string. 3089181003Sjfv * 3090190873Sjfv * Side Effects: 3091179055Sjfv * The string must be freed by the caller. 3092238149Sjfv */ 3093181003SjfvBuffer * 3094179055SjfvCmd_Exec(const char *cmd, const char **error) 3095179055Sjfv{ 3096230775Sjfv int fds[2]; /* Pipe streams */ 3097179055Sjfv int status; /* command exit status */ 3098230775Sjfv Buffer *buf; /* buffer to store the result */ 3099179055Sjfv ssize_t rcnt; 3100179055Sjfv ProcStuff ps; 3101179055Sjfv 3102179055Sjfv *error = NULL; 3103230775Sjfv buf = Buf_Init(0); 3104181003Sjfv 3105215911Sjfv if (shellPath == NULL) 3106215911Sjfv Shell_Init(); 3107171384Sjfv /* 3108171384Sjfv * Open a pipe for fetching its output 3109238149Sjfv */ 3110230775Sjfv if (pipe(fds) == -1) { 3111230775Sjfv *error = "Couldn't create pipe for \"%s\""; 3112230775Sjfv return (buf); 3113251964Sjfv } 3114251964Sjfv 3115251964Sjfv /* Set close-on-exec on read side of pipe. */ 3116251964Sjfv fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC); 3117171384Sjfv 3118171384Sjfv ps.in = STDIN_FILENO; 3119179055Sjfv ps.out = fds[1]; 3120179055Sjfv ps.err = STDERR_FILENO; 3121185352Sjfv 3122190873Sjfv ps.merge_errors = 0; 3123179055Sjfv ps.pgroup = 0; 3124179055Sjfv ps.searchpath = 0; 3125179055Sjfv 3126251964Sjfv /* Set up arguments for shell */ 3127251964Sjfv ps.argv = emalloc(4 * sizeof(char *)); 3128179055Sjfv ps.argv[0] = strdup(shellName); 3129247822Sjfv ps.argv[1] = strdup("-c"); 3130179055Sjfv ps.argv[2] = strdup(cmd); 3131179055Sjfv ps.argv[3] = NULL; 3132185352Sjfv 3133185352Sjfv /* 3134247822Sjfv * Fork. Warning since we are doing vfork() instead of fork(), 3135185352Sjfv * do not allocate memory in the child process! 3136185352Sjfv */ 3137190873Sjfv if ((ps.child_pid = vfork()) == -1) { 3138205720Sjfv *error = "Couldn't exec \"%s\""; 3139179055Sjfv return (buf); 3140179055Sjfv 3141179055Sjfv } else if (ps.child_pid == 0) { 3142230775Sjfv /* 3143230775Sjfv * Child 3144230775Sjfv */ 3145230775Sjfv ProcExec(&ps); 3146230775Sjfv /* NOTREACHED */ 3147230775Sjfv } 3148179055Sjfv 3149179055Sjfv free(ps.argv[2]); 3150205720Sjfv free(ps.argv[1]); 3151171384Sjfv free(ps.argv[0]); 3152230775Sjfv free(ps.argv); 3153230775Sjfv 3154230775Sjfv close(fds[1]); /* No need for the writing half of the pipe. */ 3155230775Sjfv 3156230775Sjfv do { 3157200239Sjfv char result[BUFSIZ]; 3158230775Sjfv 3159200239Sjfv rcnt = read(fds[0], result, sizeof(result)); 3160230775Sjfv if (rcnt != -1) 3161215911Sjfv Buf_AddBytes(buf, (size_t)rcnt, (Byte *)result); 3162230775Sjfv } while (rcnt > 0 || (rcnt == -1 && errno == EINTR)); 3163230775Sjfv 3164230775Sjfv if (rcnt == -1) 3165230775Sjfv *error = "Error reading shell's output for \"%s\""; 3166230775Sjfv 3167230775Sjfv /* 3168230775Sjfv * Close the input side of the pipe. 3169230775Sjfv */ 3170230775Sjfv close(fds[0]); 3171230775Sjfv 3172247822Sjfv status = ProcWait(&ps); 3173238149Sjfv 3174247822Sjfv if (status) 3175238149Sjfv *error = "\"%s\" returned non-zero status"; 3176238149Sjfv 3177230775Sjfv Buf_StripNewlines(buf); 3178230775Sjfv 3179230775Sjfv return (buf); 3180230775Sjfv} 3181171384Sjfv 3182171384Sjfv 3183171384Sjfv/* 3184230775Sjfv * Interrupt handler - set flag and defer handling to the main code 3185230775Sjfv */ 3186230775Sjfvstatic void 3187230775SjfvCompatCatchSig(int signo) 3188230775Sjfv{ 3189230775Sjfv 3190230775Sjfv interrupted = signo; 3191230775Sjfv} 3192230775Sjfv 3193230775Sjfv/*- 3194230775Sjfv *----------------------------------------------------------------------- 3195230775Sjfv * CompatInterrupt -- 3196230775Sjfv * Interrupt the creation of the current target and remove it if 3197230775Sjfv * it ain't precious. 3198171384Sjfv * 3199171384Sjfv * Results: 3200215911Sjfv * None. 3201215911Sjfv * 3202215911Sjfv * Side Effects: 3203215911Sjfv * The target is removed and the process exits. If .INTERRUPT exists, 3204215911Sjfv * its commands are run first WITH INTERRUPTS IGNORED.. 3205215911Sjfv * 3206215911Sjfv *----------------------------------------------------------------------- 3207215911Sjfv */ 3208215911Sjfvstatic void 3209215911SjfvCompatInterrupt(int signo) 3210215911Sjfv{ 3211215911Sjfv GNode *gn; 3212215911Sjfv sigset_t nmask, omask; 3213215911Sjfv LstNode *ln; 3214215911Sjfv 3215215911Sjfv sigemptyset(&nmask); 3216215911Sjfv sigaddset(&nmask, SIGINT); 3217215911Sjfv sigaddset(&nmask, SIGTERM); 3218215911Sjfv sigaddset(&nmask, SIGHUP); 3219215911Sjfv sigaddset(&nmask, SIGQUIT); 3220215911Sjfv sigprocmask(SIG_SETMASK, &nmask, &omask); 3221215911Sjfv 3222215911Sjfv /* prevent recursion in evaluation of .INTERRUPT */ 3223215911Sjfv interrupted = 0; 3224215911Sjfv 3225215911Sjfv if (curTarg != NULL && !Targ_Precious(curTarg)) { 3226215911Sjfv char *p1; 3227215911Sjfv char *file = Var_Value(TARGET, curTarg, &p1); 3228215911Sjfv 3229215911Sjfv if (!noExecute && eunlink(file) != -1) { 3230215911Sjfv printf("*** %s removed\n", file); 3231171384Sjfv } 3232230775Sjfv free(p1); 3233230775Sjfv } 3234230775Sjfv 3235230775Sjfv /* 3236230775Sjfv * Run .INTERRUPT only if hit with interrupt signal 3237230775Sjfv */ 3238230775Sjfv if (signo == SIGINT) { 3239230775Sjfv gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 3240230775Sjfv if (gn != NULL) { 3241230775Sjfv LST_FOREACH(ln, &gn->commands) { 3242230775Sjfv if (Compat_RunCommand(Lst_Datum(ln), gn)) 3243230775Sjfv break; 3244230775Sjfv } 3245230775Sjfv } 3246230775Sjfv } 3247247822Sjfv 3248230775Sjfv sigprocmask(SIG_SETMASK, &omask, NULL); 3249238149Sjfv 3250251964Sjfv if (signo == SIGQUIT) 3251251964Sjfv exit(signo); 3252171384Sjfv signal(signo, SIG_DFL); 3253171384Sjfv kill(getpid(), signo); 3254171384Sjfv} 3255230775Sjfv 3256171384Sjfv/** 3257194875Sjfv * shellneed 3258171384Sjfv * 3259230775Sjfv * Results: 3260230775Sjfv * Returns NULL if a specified line must be executed by the shell, 3261230775Sjfv * and an argument vector if it can be run via execvp(). 3262230775Sjfv * 3263230775Sjfv * Side Effects: 3264230775Sjfv * Uses brk_string so destroys the contents of argv. 3265230775Sjfv */ 3266230775Sjfvstatic char ** 3267230775Sjfvshellneed(char *cmd) 3268230775Sjfv{ 3269230775Sjfv char **av; 3270230775Sjfv const char **p; 3271230775Sjfv 3272230775Sjfv if (strpbrk(cmd, sh_meta) != NULL) 3273230775Sjfv return (NULL); 3274230775Sjfv 3275230775Sjfv av = brk_string(cmd, NULL, TRUE); 3276230775Sjfv for (p = sh_builtin; *p != 0; p++) 3277230775Sjfv if (strcmp(av[1], *p) == 0) 3278230775Sjfv return (NULL); 3279230775Sjfv return (av + 1); 3280230775Sjfv} 3281230775Sjfv 3282230775Sjfv/*- 3283230775Sjfv *----------------------------------------------------------------------- 3284230775Sjfv * Compat_RunCommand -- 3285230775Sjfv * Execute the next command for a target. If the command returns an 3286230775Sjfv * error, the node's made field is set to ERROR and creation stops. 3287230775Sjfv * The node from which the command came is also given. 3288230775Sjfv * 3289230775Sjfv * Results: 3290230775Sjfv * 0 if the command succeeded, 1 if an error occurred. 3291230775Sjfv * 3292230775Sjfv * Side Effects: 3293247822Sjfv * The node's 'made' field may be set to ERROR. 3294251964Sjfv * 3295171384Sjfv *----------------------------------------------------------------------- 3296230775Sjfv */ 3297171384Sjfvint 3298171384SjfvCompat_RunCommand(char *cmd, GNode *gn) 3299{ 3300 char *cmdStart; /* Start of expanded command */ 3301 Boolean silent; /* Don't print command */ 3302 Boolean doit; /* Execute even in -n */ 3303 Boolean errCheck; /* Check errors */ 3304 int reason; /* Reason for child's death */ 3305 int status; /* Description of child's death */ 3306 LstNode *cmdNode; /* Node where current command is located */ 3307 char **av; /* Argument vector for thing to exec */ 3308 char *cmd_save; /* saved cmd */ 3309 ProcStuff ps; 3310 3311 silent = gn->type & OP_SILENT; 3312 errCheck = !(gn->type & OP_IGNORE); 3313 doit = FALSE; 3314 3315 cmdNode = Lst_Member(&gn->commands, cmd); 3316 cmdStart = Buf_Peel(Var_Subst(cmd, gn, FALSE)); 3317 3318 /* 3319 * brk_string will return an argv with a NULL in av[0], thus causing 3320 * execvp() to choke and die horribly. Besides, how can we execute a 3321 * null command? In any case, we warn the user that the command 3322 * expanded to nothing (is this the right thing to do?). 3323 */ 3324 if (*cmdStart == '\0') { 3325 free(cmdStart); 3326 Error("%s expands to empty string", cmd); 3327 return (0); 3328 } else { 3329 cmd = cmdStart; 3330 } 3331 Lst_Replace(cmdNode, cmdStart); 3332 3333 if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { 3334 Lst_AtEnd(&ENDNode->commands, cmdStart); 3335 return (0); 3336 } else if (strcmp(cmdStart, "...") == 0) { 3337 gn->type |= OP_SAVE_CMDS; 3338 return (0); 3339 } 3340 3341 while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 3342 switch (*cmd) { 3343 3344 case '@': 3345 silent = DEBUG(LOUD) ? FALSE : TRUE; 3346 break; 3347 3348 case '-': 3349 errCheck = FALSE; 3350 break; 3351 3352 case '+': 3353 doit = TRUE; 3354 break; 3355 } 3356 cmd++; 3357 } 3358 3359 while (isspace((unsigned char)*cmd)) 3360 cmd++; 3361 3362 /* 3363 * Print the command before echoing if we're not supposed to be quiet 3364 * for this one. We also print the command if -n given, but not if '+'. 3365 */ 3366 if (!silent || (noExecute && !doit)) { 3367 printf("%s\n", cmd); 3368 fflush(stdout); 3369 } 3370 3371 /* 3372 * If we're not supposed to execute any commands, this is as far as 3373 * we go... 3374 */ 3375 if (!doit && noExecute) { 3376 return (0); 3377 } 3378 3379 ps.in = STDIN_FILENO; 3380 ps.out = STDOUT_FILENO; 3381 ps.err = STDERR_FILENO; 3382 3383 ps.merge_errors = 0; 3384 ps.pgroup = 0; 3385 ps.searchpath = 1; 3386 3387 if ((av = shellneed(cmd)) == NULL) { 3388 /* 3389 * Shell meta character or shell builtin found - pass 3390 * command to shell. We give the shell the -e flag as 3391 * well as -c if it is supposed to exit when it hits an error. 3392 */ 3393 ps.argv = emalloc(4 * sizeof(char *)); 3394 ps.argv[0] = strdup(shellName); 3395 ps.argv[1] = strdup(errCheck ? "-ec" : "-c"); 3396 ps.argv[2] = strdup(cmd); 3397 ps.argv[3] = NULL; 3398 } else { 3399 ps.argv = av; 3400 } 3401 3402 /* 3403 * Warning since we are doing vfork() instead of fork(), 3404 * do not allocate memory in the child process! 3405 */ 3406 if ((ps.child_pid = vfork()) == -1) { 3407 Fatal("Could not fork"); 3408 3409 } else if (ps.child_pid == 0) { 3410 /* 3411 * Child 3412 */ 3413 ProcExec(&ps); 3414 /* NOTREACHED */ 3415 3416 } else { 3417 if (av == NULL) { 3418 free(ps.argv[2]); 3419 free(ps.argv[1]); 3420 free(ps.argv[0]); 3421 free(ps.argv); 3422 } 3423 3424 /* 3425 * we need to print out the command associated with this 3426 * Gnode in Targ_PrintCmd from Targ_PrintGraph when debugging 3427 * at level g2, in main(), Fatal() and DieHorribly(), 3428 * therefore do not free it when debugging. 3429 */ 3430 if (!DEBUG(GRAPH2)) { 3431 free(cmdStart); 3432 Lst_Replace(cmdNode, cmd_save); 3433 } 3434 3435 /* 3436 * The child is off and running. Now all we can do is wait... 3437 */ 3438 reason = ProcWait(&ps); 3439 3440 if (interrupted) 3441 CompatInterrupt(interrupted); 3442 3443 /* 3444 * Decode and report the reason child exited, then 3445 * indicate how we handled it. 3446 */ 3447 if (WIFEXITED(reason)) { 3448 status = WEXITSTATUS(reason); 3449 if (status == 0) { 3450 return (0); 3451 } else { 3452 printf("*** Error code %d", status); 3453 } 3454 } else if (WIFSTOPPED(reason)) { 3455 status = WSTOPSIG(reason); 3456 } else { 3457 status = WTERMSIG(reason); 3458 printf("*** Signal %d", status); 3459 } 3460 3461 if (errCheck) { 3462 gn->made = ERROR; 3463 if (keepgoing) { 3464 /* 3465 * Abort the current 3466 * target, but let 3467 * others continue. 3468 */ 3469 printf(" (continuing)\n"); 3470 } 3471 return (status); 3472 } else { 3473 /* 3474 * Continue executing 3475 * commands for this target. 3476 * If we return 0, this will 3477 * happen... 3478 */ 3479 printf(" (ignored)\n"); 3480 return (0); 3481 } 3482 } 3483} 3484 3485/*- 3486 *----------------------------------------------------------------------- 3487 * CompatMake -- 3488 * Make a target, given the parent, to abort if necessary. 3489 * 3490 * Side Effects: 3491 * If an error is detected and not being ignored, the process exits. 3492 * 3493 *----------------------------------------------------------------------- 3494 */ 3495static int 3496CompatMake(GNode *gn, GNode *pgn) 3497{ 3498 LstNode *ln; 3499 3500 if (gn->type & OP_USE) { 3501 Make_HandleUse(gn, pgn); 3502 3503 } else if (gn->made == UNMADE) { 3504 /* 3505 * First mark ourselves to be made, then apply whatever 3506 * transformations the suffix module thinks are necessary. 3507 * Once that's done, we can descend and make all our children. 3508 * If any of them has an error but the -k flag was given, our 3509 * 'make' field will be set FALSE again. This is our signal to 3510 * not attempt to do anything but abort our parent as well. 3511 */ 3512 gn->make = TRUE; 3513 gn->made = BEINGMADE; 3514 Suff_FindDeps(gn); 3515 LST_FOREACH(ln, &gn->children) 3516 CompatMake(Lst_Datum(ln), gn); 3517 if (!gn->make) { 3518 gn->made = ABORTED; 3519 pgn->make = FALSE; 3520 return (0); 3521 } 3522 3523 if (Lst_Member(&gn->iParents, pgn) != NULL) { 3524 char *p1; 3525 Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); 3526 free(p1); 3527 } 3528 3529 /* 3530 * All the children were made ok. Now cmtime contains the 3531 * modification time of the newest child, we need to find out 3532 * if we exist and when we were modified last. The criteria for 3533 * datedness are defined by the Make_OODate function. 3534 */ 3535 DEBUGF(MAKE, ("Examining %s...", gn->name)); 3536 if (!Make_OODate(gn)) { 3537 gn->made = UPTODATE; 3538 DEBUGF(MAKE, ("up-to-date.\n")); 3539 return (0); 3540 } else { 3541 DEBUGF(MAKE, ("out-of-date.\n")); 3542 } 3543 3544 /* 3545 * If the user is just seeing if something is out-of-date, 3546 * exit now to tell him/her "yes". 3547 */ 3548 if (queryFlag) { 3549 exit(1); 3550 } 3551 3552 /* 3553 * We need to be re-made. We also have to make sure we've got 3554 * a $? variable. To be nice, we also define the $> variable 3555 * using Make_DoAllVar(). 3556 */ 3557 Make_DoAllVar(gn); 3558 3559 /* 3560 * Alter our type to tell if errors should be ignored or things 3561 * should not be printed so Compat_RunCommand knows what to do. 3562 */ 3563 if (Targ_Ignore(gn)) { 3564 gn->type |= OP_IGNORE; 3565 } 3566 if (Targ_Silent(gn)) { 3567 gn->type |= OP_SILENT; 3568 } 3569 3570 if (Job_CheckCommands(gn, Fatal)) { 3571 /* 3572 * Our commands are ok, but we still have to worry 3573 * about the -t flag... 3574 */ 3575 if (!touchFlag) { 3576 curTarg = gn; 3577 LST_FOREACH(ln, &gn->commands) { 3578 if (Compat_RunCommand(Lst_Datum(ln), 3579 gn)) 3580 break; 3581 } 3582 curTarg = NULL; 3583 } else { 3584 Job_Touch(gn, gn->type & OP_SILENT); 3585 } 3586 } else { 3587 gn->made = ERROR; 3588 } 3589 3590 if (gn->made != ERROR) { 3591 /* 3592 * If the node was made successfully, mark it so, update 3593 * its modification time and timestamp all its parents. 3594 * Note that for .ZEROTIME targets, the timestamping 3595 * isn't done. This is to keep its state from affecting 3596 * that of its parent. 3597 */ 3598 gn->made = MADE; 3599#ifndef RECHECK 3600 /* 3601 * We can't re-stat the thing, but we can at least take 3602 * care of rules where a target depends on a source that 3603 * actually creates the target, but only if it has 3604 * changed, e.g. 3605 * 3606 * parse.h : parse.o 3607 * 3608 * parse.o : parse.y 3609 * yacc -d parse.y 3610 * cc -c y.tab.c 3611 * mv y.tab.o parse.o 3612 * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 3613 * 3614 * In this case, if the definitions produced by yacc 3615 * haven't changed from before, parse.h won't have been 3616 * updated and gn->mtime will reflect the current 3617 * modification time for parse.h. This is something of a 3618 * kludge, I admit, but it's a useful one.. 3619 * 3620 * XXX: People like to use a rule like 3621 * 3622 * FRC: 3623 * 3624 * To force things that depend on FRC to be made, so we 3625 * have to check for gn->children being empty as well... 3626 */ 3627 if (!Lst_IsEmpty(&gn->commands) || 3628 Lst_IsEmpty(&gn->children)) { 3629 gn->mtime = now; 3630 } 3631#else 3632 /* 3633 * This is what Make does and it's actually a good 3634 * thing, as it allows rules like 3635 * 3636 * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 3637 * 3638 * to function as intended. Unfortunately, thanks to 3639 * the stateless nature of NFS (and the speed of this 3640 * program), there are times when the modification time 3641 * of a file created on a remote machine will not be 3642 * modified before the stat() implied by the Dir_MTime 3643 * occurs, thus leading us to believe that the file 3644 * is unchanged, wreaking havoc with files that depend 3645 * on this one. 3646 * 3647 * I have decided it is better to make too much than to 3648 * make too little, so this stuff is commented out 3649 * unless you're sure it's ok. 3650 * -- ardeb 1/12/88 3651 */ 3652 if (noExecute || Dir_MTime(gn) == 0) { 3653 gn->mtime = now; 3654 } 3655 if (gn->cmtime > gn->mtime) 3656 gn->mtime = gn->cmtime; 3657 DEBUGF(MAKE, ("update time: %s\n", 3658 Targ_FmtTime(gn->mtime))); 3659#endif 3660 if (!(gn->type & OP_EXEC)) { 3661 pgn->childMade = TRUE; 3662 Make_TimeStamp(pgn, gn); 3663 } 3664 3665 } else if (keepgoing) { 3666 pgn->make = FALSE; 3667 3668 } else { 3669 char *p1; 3670 3671 printf("\n\nStop in %s.\n", 3672 Var_Value(".CURDIR", gn, &p1)); 3673 free(p1); 3674 exit(1); 3675 } 3676 } else if (gn->made == ERROR) { 3677 /* 3678 * Already had an error when making this beastie. Tell the 3679 * parent to abort. 3680 */ 3681 pgn->make = FALSE; 3682 } else { 3683 if (Lst_Member(&gn->iParents, pgn) != NULL) { 3684 char *p1; 3685 Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); 3686 free(p1); 3687 } 3688 switch(gn->made) { 3689 case BEINGMADE: 3690 Error("Graph cycles through %s\n", gn->name); 3691 gn->made = ERROR; 3692 pgn->make = FALSE; 3693 break; 3694 case MADE: 3695 if ((gn->type & OP_EXEC) == 0) { 3696 pgn->childMade = TRUE; 3697 Make_TimeStamp(pgn, gn); 3698 } 3699 break; 3700 case UPTODATE: 3701 if ((gn->type & OP_EXEC) == 0) { 3702 Make_TimeStamp(pgn, gn); 3703 } 3704 break; 3705 default: 3706 break; 3707 } 3708 } 3709 3710 return (0); 3711} 3712 3713/*- 3714 *----------------------------------------------------------------------- 3715 * Compat_Run -- 3716 * Start making again, given a list of target nodes. 3717 * 3718 * Results: 3719 * None. 3720 * 3721 * Side Effects: 3722 * Guess what? 3723 * 3724 *----------------------------------------------------------------------- 3725 */ 3726void 3727Compat_Run(Lst *targs) 3728{ 3729 GNode *gn = NULL; /* Current root target */ 3730 int error_cnt; /* Number of targets not remade due to errors */ 3731 LstNode *ln; 3732 3733 Shell_Init(); /* Set up shell. */ 3734 3735 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 3736 signal(SIGINT, CompatCatchSig); 3737 } 3738 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 3739 signal(SIGTERM, CompatCatchSig); 3740 } 3741 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 3742 signal(SIGHUP, CompatCatchSig); 3743 } 3744 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 3745 signal(SIGQUIT, CompatCatchSig); 3746 } 3747 3748 ENDNode = Targ_FindNode(".END", TARG_CREATE); 3749 /* 3750 * If the user has defined a .BEGIN target, execute the commands 3751 * attached to it. 3752 */ 3753 if (!queryFlag) { 3754 gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); 3755 if (gn != NULL) { 3756 LST_FOREACH(ln, &gn->commands) { 3757 if (Compat_RunCommand(Lst_Datum(ln), gn)) 3758 break; 3759 } 3760 if (gn->made == ERROR) { 3761 printf("\n\nStop.\n"); 3762 exit(1); 3763 } 3764 } 3765 } 3766 3767 /* 3768 * For each entry in the list of targets to create, call CompatMake on 3769 * it to create the thing. CompatMake will leave the 'made' field of gn 3770 * in one of several states: 3771 * UPTODATE gn was already up-to-date 3772 * MADE gn was recreated successfully 3773 * ERROR An error occurred while gn was being created 3774 * ABORTED gn was not remade because one of its inferiors 3775 * could not be made due to errors. 3776 */ 3777 error_cnt = 0; 3778 while (!Lst_IsEmpty(targs)) { 3779 gn = Lst_DeQueue(targs); 3780 CompatMake(gn, gn); 3781 3782 if (gn->made == UPTODATE) { 3783 printf("`%s' is up to date.\n", gn->name); 3784 } else if (gn->made == ABORTED) { 3785 printf("`%s' not remade because of errors.\n", 3786 gn->name); 3787 error_cnt += 1; 3788 } 3789 } 3790 3791 /* 3792 * If the user has defined a .END target, run its commands. 3793 */ 3794 if (error_cnt == 0) { 3795 LST_FOREACH(ln, &ENDNode->commands) { 3796 if (Compat_RunCommand(Lst_Datum(ln), gn)) 3797 break; 3798 } 3799 } 3800} 3801