job.c revision 146345
1141104Sharti/*- 294589Sobrien * Copyright (c) 1988, 1989, 1990, 1993 394589Sobrien * The Regents of the University of California. All rights reserved. 45814Sjkh * Copyright (c) 1988, 1989 by Adam de Boor 51590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 61590Srgrimes * All rights reserved. 71590Srgrimes * 81590Srgrimes * This code is derived from software contributed to Berkeley by 91590Srgrimes * Adam de Boor. 101590Srgrimes * 111590Srgrimes * Redistribution and use in source and binary forms, with or without 121590Srgrimes * modification, are permitted provided that the following conditions 131590Srgrimes * are met: 141590Srgrimes * 1. Redistributions of source code must retain the above copyright 151590Srgrimes * notice, this list of conditions and the following disclaimer. 161590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171590Srgrimes * notice, this list of conditions and the following disclaimer in the 181590Srgrimes * documentation and/or other materials provided with the distribution. 191590Srgrimes * 3. All advertising materials mentioning features or use of this software 201590Srgrimes * must display the following acknowledgement: 211590Srgrimes * This product includes software developed by the University of 221590Srgrimes * California, Berkeley and its contributors. 231590Srgrimes * 4. Neither the name of the University nor the names of its contributors 241590Srgrimes * may be used to endorse or promote products derived from this software 251590Srgrimes * without specific prior written permission. 261590Srgrimes * 271590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 281590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 291590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 301590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 311590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 321590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 331590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 341590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 351590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 361590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 371590Srgrimes * SUCH DAMAGE. 3862833Swsanchez * 3962833Swsanchez * @(#)job.c 8.2 (Berkeley) 3/19/94 401590Srgrimes */ 411590Srgrimes 4262833Swsanchez#include <sys/cdefs.h> 4394587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/job.c 146345 2005-05-18 14:50:35Z harti $"); 441590Srgrimes 4535483Simp#ifndef OLD_JOKE 46103503Sjmallett#define OLD_JOKE 0 4735483Simp#endif /* OLD_JOKE */ 4835483Simp 491590Srgrimes/*- 501590Srgrimes * job.c -- 511590Srgrimes * handle the creation etc. of our child processes. 521590Srgrimes * 531590Srgrimes * Interface: 54144467Sharti * Job_Make Start the creation of the given target. 551590Srgrimes * 56144467Sharti * Job_CatchChildren 57144467Sharti * Check for and handle the termination of any children. 58144467Sharti * This must be called reasonably frequently to keep the 59144467Sharti * whole make going at a decent clip, since job table 60144467Sharti * entries aren't removed until their process is caught 61144467Sharti * this way. Its single argument is TRUE if the function 62144467Sharti * should block waiting for a child to terminate. 631590Srgrimes * 64144467Sharti * Job_CatchOutput Print any output our children have produced. Should 65144467Sharti * also be called fairly frequently to keep the user 66144467Sharti * informed of what's going on. If no output is waiting, 67144467Sharti * it will block for a time given by the SEL_* constants, 68144467Sharti * below, or until output is ready. 691590Srgrimes * 70144467Sharti * Job_Init Called to intialize this module. in addition, any 71144467Sharti * commands attached to the .BEGIN target are executed 72144467Sharti * before this function returns. Hence, the makefile must 73144467Sharti * have been parsed before this function is called. 741590Srgrimes * 75144467Sharti * Job_Full Return TRUE if the job table is filled. 761590Srgrimes * 77144467Sharti * Job_Empty Return TRUE if the job table is completely empty. 781590Srgrimes * 79144467Sharti * Job_ParseShell Given the line following a .SHELL target, parse the 80146338Sharti * line as a shell specification. Returns FALSE if the 81144467Sharti * spec was incorrect. 821590Srgrimes * 83144467Sharti * Job_Finish Perform any final processing which needs doing. This 84144467Sharti * includes the execution of any commands which have 85144467Sharti * been/were attached to the .END target. It should only 86144467Sharti * be called when the job table is empty. 871590Srgrimes * 88144467Sharti * Job_AbortAll Abort all currently running jobs. It doesn't handle 89144467Sharti * output or do anything for the jobs, just kills them. 90144467Sharti * It should only be called in an emergency, as it were. 911590Srgrimes * 92144467Sharti * Job_CheckCommands 93144467Sharti * Verify that the commands for a target are ok. Provide 94144467Sharti * them if necessary and possible. 951590Srgrimes * 96144467Sharti * Job_Touch Update a target without really updating it. 971590Srgrimes * 98144467Sharti * Job_Wait Wait for all currently-running jobs to finish. 99146132Sharti * 100146132Sharti * compat.c -- 101146132Sharti * The routines in this file implement the full-compatibility 102146132Sharti * mode of PMake. Most of the special functionality of PMake 103146132Sharti * is available in this mode. Things not supported: 104146132Sharti * - different shells. 105146132Sharti * - friendly variable substitution. 106146132Sharti * 107146132Sharti * Interface: 108146132Sharti * Compat_Run Initialize things for this module and recreate 109146132Sharti * thems as need creatin' 1101590Srgrimes */ 1111590Srgrimes 112144494Sharti#include <sys/queue.h> 1131590Srgrimes#include <sys/types.h> 114141104Sharti#include <sys/select.h> 1151590Srgrimes#include <sys/stat.h> 116107447Sru#ifdef USE_KQUEUE 117104475Sphk#include <sys/event.h> 118107447Sru#endif 1191590Srgrimes#include <sys/wait.h> 120141104Sharti#include <ctype.h> 121146160Sjmallett#include <err.h> 12294506Scharnier#include <errno.h> 1235814Sjkh#include <fcntl.h> 124144665Sharti#include <inttypes.h> 1251590Srgrimes#include <string.h> 1265814Sjkh#include <signal.h> 127141104Sharti#include <stdlib.h> 12880381Ssheldonh#include <unistd.h> 12994506Scharnier#include <utime.h> 130141104Sharti 131141104Sharti#include "arch.h" 132142457Sharti#include "buf.h" 133146056Sharti#include "config.h" 1341590Srgrimes#include "dir.h" 135141104Sharti#include "globals.h" 136141104Sharti#include "GNode.h" 1371590Srgrimes#include "job.h" 138141104Sharti#include "make.h" 139141104Sharti#include "parse.h" 1401590Srgrimes#include "pathnames.h" 141141104Sharti#include "str.h" 142146056Sharti#include "suff.h" 143141104Sharti#include "targ.h" 144141104Sharti#include "util.h" 145141104Sharti#include "var.h" 1461590Srgrimes 147146057Sharti#define TMPPAT "/tmp/makeXXXXXXXXXX" 148146057Sharti 149146057Sharti#ifndef USE_KQUEUE 1501590Srgrimes/* 151146057Sharti * The SEL_ constants determine the maximum amount of time spent in select 152146057Sharti * before coming out to see if a child has finished. SEL_SEC is the number of 153146057Sharti * seconds and SEL_USEC is the number of micro-seconds 154146057Sharti */ 155146057Sharti#define SEL_SEC 2 156146057Sharti#define SEL_USEC 0 157146057Sharti#endif /* !USE_KQUEUE */ 158146057Sharti 159146057Sharti/* 160144483Sharti * Job Table definitions. 161144483Sharti * 162144483Sharti * The job "table" is kept as a linked Lst in 'jobs', with the number of 163144483Sharti * active jobs maintained in the 'nJobs' variable. At no time will this 164144483Sharti * exceed the value of 'maxJobs', initialized by the Job_Init function. 165144483Sharti * 166144483Sharti * When a job is finished, the Make_Update function is called on each of the 167144483Sharti * parents of the node which was just remade. This takes care of the upward 168144483Sharti * traversal of the dependency graph. 169144483Sharti */ 170144483Sharti#define JOB_BUFSIZE 1024 171144483Shartitypedef struct Job { 172144665Sharti pid_t pid; /* The child's process ID */ 173144483Sharti 174144483Sharti struct GNode *node; /* The target the child is making */ 175144483Sharti 176144483Sharti /* 177144483Sharti * A LstNode for the first command to be saved after the job completes. 178144483Sharti * This is NULL if there was no "..." in the job's commands. 179144483Sharti */ 180144483Sharti LstNode *tailCmds; 181144483Sharti 182144483Sharti /* 183144483Sharti * An FILE* for writing out the commands. This is only 184144483Sharti * used before the job is actually started. 185144483Sharti */ 186144483Sharti FILE *cmdFILE; 187144483Sharti 188144483Sharti /* 189144483Sharti * A word of flags which determine how the module handles errors, 190144483Sharti * echoing, etc. for the job 191144483Sharti */ 192144483Sharti short flags; /* Flags to control treatment of job */ 193144483Sharti#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ 194144483Sharti#define JOB_SILENT 0x002 /* no output */ 195144483Sharti#define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally 196144483Sharti * if we can't export it and maxLocal is 0 */ 197146061Sharti#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing 198144483Sharti * commands */ 199144483Sharti#define JOB_FIRST 0x020 /* Job is first job for the node */ 200144483Sharti#define JOB_RESTART 0x080 /* Job needs to be completely restarted */ 201144483Sharti#define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped, 202144483Sharti * for some reason */ 203144483Sharti#define JOB_CONTINUING 0x200 /* We are in the process of resuming this job. 204144483Sharti * Used to avoid infinite recursion between 205144483Sharti * JobFinish and JobRestart */ 206144483Sharti 207144483Sharti /* union for handling shell's output */ 208144483Sharti union { 209144483Sharti /* 210144483Sharti * This part is used when usePipes is true. 211146061Sharti * The output is being caught via a pipe and the descriptors 212144483Sharti * of our pipe, an array in which output is line buffered and 213144483Sharti * the current position in that buffer are all maintained for 214144483Sharti * each job. 215144483Sharti */ 216144483Sharti struct { 217144483Sharti /* 218144483Sharti * Input side of pipe associated with 219144483Sharti * job's output channel 220144483Sharti */ 221144483Sharti int op_inPipe; 222144483Sharti 223144483Sharti /* 224144483Sharti * Output side of pipe associated with job's 225144483Sharti * output channel 226144483Sharti */ 227144483Sharti int op_outPipe; 228144483Sharti 229144483Sharti /* 230144483Sharti * Buffer for storing the output of the 231144483Sharti * job, line by line 232144483Sharti */ 233144483Sharti char op_outBuf[JOB_BUFSIZE + 1]; 234144483Sharti 235144483Sharti /* Current position in op_outBuf */ 236144483Sharti int op_curPos; 237144483Sharti } o_pipe; 238144483Sharti 239144483Sharti /* 240144483Sharti * If usePipes is false the output is routed to a temporary 241144483Sharti * file and all that is kept is the name of the file and the 242144483Sharti * descriptor open to the file. 243144483Sharti */ 244144483Sharti struct { 245144483Sharti /* Name of file to which shell output was rerouted */ 246144483Sharti char of_outFile[sizeof(TMPPAT)]; 247144483Sharti 248144483Sharti /* 249144483Sharti * Stream open to the output file. Used to funnel all 250144483Sharti * from a single job to one file while still allowing 251144483Sharti * multiple shell invocations 252144483Sharti */ 253144483Sharti int of_outFd; 254144483Sharti } o_file; 255144483Sharti 256144483Sharti } output; /* Data for tracking a shell's output */ 257144494Sharti 258144494Sharti TAILQ_ENTRY(Job) link; /* list link */ 259144483Sharti} Job; 260144483Sharti 261146061Sharti#define outPipe output.o_pipe.op_outPipe 262146061Sharti#define inPipe output.o_pipe.op_inPipe 263144483Sharti#define outBuf output.o_pipe.op_outBuf 264144483Sharti#define curPos output.o_pipe.op_curPos 265144483Sharti#define outFile output.o_file.of_outFile 266146061Sharti#define outFd output.o_file.of_outFd 267144483Sharti 268144494ShartiTAILQ_HEAD(JobList, Job); 269144494Sharti 270144483Sharti/* 271144483Sharti * Shell Specifications: 272144483Sharti * 273144483Sharti * Some special stuff goes on if a shell doesn't have error control. In such 274144483Sharti * a case, errCheck becomes a printf template for echoing the command, 275144483Sharti * should echoing be on and ignErr becomes another printf template for 276144483Sharti * executing the command while ignoring the return status. If either of these 277144483Sharti * strings is empty when hasErrCtl is FALSE, the command will be executed 278144483Sharti * anyway as is and if it causes an error, so be it. 279144483Sharti */ 280144483Sharti#define DEF_SHELL_STRUCT(TAG, CONST) \ 281144483Shartistruct TAG { \ 282144483Sharti /* \ 283144483Sharti * the name of the shell. For Bourne and C shells, this is used \ 284144483Sharti * only to find the shell description when used as the single \ 285144483Sharti * source of a .SHELL target. For user-defined shells, this is \ 286144483Sharti * the full path of the shell. \ 287144483Sharti */ \ 288144483Sharti CONST char *name; \ 289144483Sharti \ 290144483Sharti /* True if both echoOff and echoOn defined */ \ 291144483Sharti Boolean hasEchoCtl; \ 292144483Sharti \ 293144483Sharti CONST char *echoOff; /* command to turn off echo */ \ 294144483Sharti CONST char *echoOn; /* command to turn it back on */\ 295144483Sharti \ 296144483Sharti /* \ 297144483Sharti * What the shell prints, and its length, when given the \ 298144483Sharti * echo-off command. This line will not be printed when \ 299144483Sharti * received from the shell. This is usually the command which \ 300144483Sharti * was executed to turn off echoing \ 301144483Sharti */ \ 302144483Sharti CONST char *noPrint; \ 303144483Sharti \ 304144483Sharti /* set if can control error checking for individual commands */ \ 305144483Sharti Boolean hasErrCtl; \ 306144483Sharti \ 307144483Sharti /* string to turn error checking on */ \ 308144483Sharti CONST char *errCheck; \ 309144483Sharti \ 310144483Sharti /* string to turn off error checking */ \ 311144483Sharti CONST char *ignErr; \ 312144483Sharti \ 313144483Sharti CONST char *echo; /* command line flag: echo commands */ \ 314144483Sharti CONST char *exit; /* command line flag: exit on error */ \ 315144483Sharti} 316144483Sharti 317144483ShartiDEF_SHELL_STRUCT(Shell,); 318144483ShartiDEF_SHELL_STRUCT(CShell, const); 319144483Sharti 320144483Sharti/* 3218874Srgrimes * error handling variables 3221590Srgrimes */ 323144467Shartistatic int errors = 0; /* number of errors reported */ 324144467Shartistatic int aborting = 0; /* why is the make aborting? */ 325144467Sharti#define ABORT_ERROR 1 /* Because of an error */ 326144467Sharti#define ABORT_INTERRUPT 2 /* Because it was interrupted */ 327144467Sharti#define ABORT_WAIT 3 /* Waiting for jobs to finish */ 3281590Srgrimes 32918730Ssteve/* 33018730Ssteve * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file 33118730Ssteve * is a char! So when we go above 127 we turn negative! 33218730Ssteve */ 333138232Sharti#define FILENO(a) ((unsigned)fileno(a)) 3341590Srgrimes 3351590Srgrimes/* 3361590Srgrimes * post-make command processing. The node postCommands is really just the 3371590Srgrimes * .END target but we keep it around to avoid having to search for it 3381590Srgrimes * all the time. 3391590Srgrimes */ 340144467Shartistatic GNode *postCommands; 3411590Srgrimes 3421590Srgrimes/* 343144467Sharti * The number of commands actually printed for a target. Should this 344144467Sharti * number be 0, no shell will be executed. 345144467Sharti */ 346144467Shartistatic int numCommands; 347144467Sharti 348144467Sharti/* 3491590Srgrimes * Return values from JobStart. 3501590Srgrimes */ 351144467Sharti#define JOB_RUNNING 0 /* Job is running */ 352146061Sharti#define JOB_ERROR 1 /* Error in starting the job */ 353144467Sharti#define JOB_FINISHED 2 /* The job is already finished */ 354144467Sharti#define JOB_STOPPED 3 /* The job is stopped */ 3551590Srgrimes 3561590Srgrimes/* 3571590Srgrimes * Descriptions for various shells. 3581590Srgrimes */ 359144483Shartistatic const struct CShell shells[] = { 360144467Sharti /* 361144467Sharti * CSH description. The csh can do echo control by playing 362144467Sharti * with the setting of the 'echo' shell variable. Sadly, 363144467Sharti * however, it is unable to do error control nicely. 364144467Sharti */ 365144467Sharti { 366144467Sharti "csh", 367144741Sharti TRUE, "unset verbose", "set verbose", "unset verbose", 368144467Sharti FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", 369144467Sharti "v", "e", 370144467Sharti }, 371144467Sharti /* 372144467Sharti * SH description. Echo control is also possible and, under 373144467Sharti * sun UNIX anyway, one can even control error checking. 374144467Sharti */ 375144467Sharti { 376144467Sharti "sh", 377144741Sharti TRUE, "set -", "set -v", "set -", 378144467Sharti TRUE, "set -e", "set +e", 37918730Ssteve#ifdef OLDBOURNESHELL 380144467Sharti FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", 38118730Ssteve#endif 382144467Sharti "v", "e", 383144467Sharti }, 384144467Sharti /* 385144467Sharti * KSH description. The Korn shell has a superset of 386144467Sharti * the Bourne shell's functionality. 387144467Sharti */ 388144467Sharti { 389144467Sharti "ksh", 390144741Sharti TRUE, "set -", "set -v", "set -", 391144467Sharti TRUE, "set -e", "set +e", 392144467Sharti "v", "e", 393144467Sharti }, 3941590Srgrimes}; 3951590Srgrimes 396144467Sharti/* 397144467Sharti * This is the shell to which we pass all commands in the Makefile. 398144467Sharti * It is set by the Job_ParseShell function. 399144467Sharti */ 400144483Shartistatic struct Shell *commandShell = NULL; 401146059Shartistatic char *shellPath = NULL; /* full pathname of executable image */ 402146059Shartistatic char *shellName = NULL; /* last component of shell */ 4031590Srgrimes 404146140Sharti/* 405146140Sharti * The maximum number of jobs that may run. This is initialize from the 406146140Sharti * -j argument for the leading make and from the FIFO for sub-makes. 407146140Sharti */ 408146140Shartistatic int maxJobs; 409146140Sharti 410144656Shartistatic int nJobs; /* The number of children currently running */ 411138916Sharti 412138916Sharti/* The structures that describe them */ 413144494Shartistatic struct JobList jobs = TAILQ_HEAD_INITIALIZER(jobs); 414138916Sharti 415146061Shartistatic Boolean jobFull; /* Flag to tell when the job table is full. It 4161590Srgrimes * is set TRUE when (1) the total number of 417137572Sphk * running jobs equals the maximum allowed */ 418104475Sphk#ifdef USE_KQUEUE 419104475Sphkstatic int kqfd; /* File descriptor obtained by kqueue() */ 420104475Sphk#else 421146061Shartistatic fd_set outputs; /* Set of descriptors of pipes connected to 4221590Srgrimes * the output channels of children */ 4231590Srgrimes#endif 4241590Srgrimes 425146061Shartistatic GNode *lastNode; /* The node for which output was most recently 4261590Srgrimes * produced. */ 427146061Shartistatic const char *targFmt; /* Format string to use to head output from a 4281590Srgrimes * job when it's not the most-recent job heard 4291590Srgrimes * from */ 4301590Srgrimes 431137202Sharti#define TARG_FMT "--- %s ---\n" /* Default format */ 432137202Sharti#define MESSAGE(fp, gn) \ 433138232Sharti fprintf(fp, targFmt, gn->name); 43418730Ssteve 4351590Srgrimes/* 436137252Sharti * When JobStart attempts to run a job but isn't allowed to 437137252Sharti * or when Job_CatchChildren detects a job that has 438137252Sharti * been stopped somehow, the job is placed on the stoppedJobs queue to be run 4398874Srgrimes * when the next job finishes. 440138916Sharti * 441138916Sharti * Lst of Job structures describing jobs that were stopped due to 442138916Sharti * concurrency limits or externally 4431590Srgrimes */ 444144494Shartistatic struct JobList stoppedJobs = TAILQ_HEAD_INITIALIZER(stoppedJobs); 4451590Srgrimes 446144656Shartistatic int fifoFd; /* Fd of our job fifo */ 447144656Shartistatic char fifoName[] = "/tmp/make_fifo_XXXXXXXXX"; 448144656Shartistatic int fifoMaster; 4491590Srgrimes 450137605Shartistatic sig_atomic_t interrupted; 451137605Sharti 452137605Sharti 4531590Srgrimes#if defined(USE_PGRP) && defined(SYSV) 45418730Ssteve# define KILL(pid, sig) killpg(-(pid), (sig)) 4551590Srgrimes#else 4561590Srgrimes# if defined(USE_PGRP) 45718730Ssteve# define KILL(pid, sig) killpg((pid), (sig)) 4581590Srgrimes# else 45918730Ssteve# define KILL(pid, sig) kill((pid), (sig)) 4601590Srgrimes# endif 4611590Srgrimes#endif 4621590Srgrimes 46318730Ssteve/* 46418730Ssteve * Grmpf... There is no way to set bits of the wait structure 46518730Ssteve * anymore with the stupid W*() macros. I liked the union wait 46618730Ssteve * stuff much more. So, we devise our own macros... This is 46718730Ssteve * really ugly, use dramamine sparingly. You have been warned. 46818730Ssteve */ 469103503Sjmallett#define W_SETMASKED(st, val, fun) \ 47018730Ssteve { \ 471138232Sharti int sh = (int)~0; \ 47218730Ssteve int mask = fun(sh); \ 47318730Ssteve \ 47418730Ssteve for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ 47518730Ssteve continue; \ 47618730Ssteve *(st) = (*(st) & ~mask) | ((val) << sh); \ 47718730Ssteve } 47818730Ssteve 479103503Sjmallett#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) 480103503Sjmallett#define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) 48118730Ssteve 482146129Sharti/** 483146129Sharti * Information used to create a new process. 484146129Sharti */ 485146129Shartitypedef struct ProcStuff { 486146129Sharti int in; /* stdin for new process */ 487146129Sharti int out; /* stdout for new process */ 488146129Sharti int err; /* stderr for new process */ 489146129Sharti 490146129Sharti int merge_errors; /* true if stderr is redirected to stdin */ 491146129Sharti int pgroup; /* true if new process a process leader */ 492146129Sharti int searchpath; /* true if binary should be found via $PATH */ 493146129Sharti 494146129Sharti char **argv; 495146156Sharti int argv_free; /* release argv after use */ 496146156Sharti int errCheck; 497146130Sharti 498146130Sharti pid_t child_pid; 499146129Sharti} ProcStuff; 500146129Sharti 50192921Simpstatic void JobRestart(Job *); 50292921Simpstatic int JobStart(GNode *, int, Job *); 50392921Simpstatic void JobDoOutput(Job *, Boolean); 504144483Shartistatic struct Shell *JobMatchShell(const char *); 50592921Simpstatic void JobInterrupt(int, int); 50692921Simpstatic void JobRestartJobs(void); 507146129Shartistatic void ProcExec(const ProcStuff *) __dead2; 508146142Shartistatic int Compat_RunCommand(char *, struct GNode *); 5091590Srgrimes 510146132Sharti/* 511146132Sharti * The following array is used to make a fast determination of which 512146132Sharti * commands and characters are interpreted specially by the shell. 513146132Sharti * If a command is one of these or contains any of these characters, 514146132Sharti * it is executed by the shell, not directly by us. 515146132Sharti * XXX Both of these arrays should be configurable via .SHELL 516146132Sharti */ 517146132Shartistatic const char const* sh_builtin[] = { 518146132Sharti "alias", "cd", "eval", "exec", 519146132Sharti "exit", "read", "set", "ulimit", 520146132Sharti "unalias", "umask", "unset", "wait", 521146132Sharti ":", NULL 522146132Sharti}; 523146132Shartistatic const char *sh_meta = "#=|^(){};&<>*?[]:$`\\\n"; 524146132Sharti 525146132Shartistatic GNode *curTarg = NULL; 526146132Shartistatic GNode *ENDNode; 527146132Sharti 528146155Sharti/** 529146155Sharti * Create a fifo file with a uniq filename, and returns a file 530146155Sharti * descriptor to that fifo. 531146155Sharti */ 532146155Shartistatic int 533146155Shartimkfifotemp(char *template) 534146155Sharti{ 535146155Sharti char *start; 536146155Sharti char *pathend; 537146155Sharti char *ptr; 538146155Sharti const unsigned char padchar[] = 539146155Sharti "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 540146155Sharti 541146155Sharti if (template[0] == '\0') { 542146155Sharti errno = EINVAL; /* bad input string */ 543146155Sharti return (-1); 544146155Sharti } 545146155Sharti 546146155Sharti /* Find end of template string. */ 547146155Sharti pathend = strchr(template, '\0'); 548146155Sharti ptr = pathend - 1; 549146155Sharti 550146155Sharti /* 551146155Sharti * Starting from the end of the template replace spaces with 'X' in 552146155Sharti * them with random characters until there are no more 'X'. 553146155Sharti */ 554146155Sharti while (ptr >= template && *ptr == 'X') { 555146155Sharti uint32_t rand_num = arc4random() % (sizeof(padchar) - 1); 556146155Sharti *ptr-- = padchar[rand_num]; 557146155Sharti } 558146155Sharti start = ptr + 1; 559146155Sharti 560146155Sharti /* Check the target directory. */ 561146155Sharti for (; ptr > template; --ptr) { 562146155Sharti if (*ptr == '/') { 563146155Sharti struct stat sbuf; 564146155Sharti 565146155Sharti *ptr = '\0'; 566146155Sharti if (stat(template, &sbuf) != 0) 567146155Sharti return (-1); 568146155Sharti 569146155Sharti if (!S_ISDIR(sbuf.st_mode)) { 570146155Sharti errno = ENOTDIR; 571146155Sharti return (-1); 572146155Sharti } 573146155Sharti *ptr = '/'; 574146155Sharti break; 575146155Sharti } 576146155Sharti } 577146155Sharti 578146155Sharti for (;;) { 579146155Sharti if (mkfifo(template, 0600) == 0) { 580146155Sharti int fd; 581146155Sharti 582146155Sharti if ((fd = open(template, O_RDWR, 0600)) < 0) { 583146155Sharti unlink(template); 584146155Sharti return (-1); 585146155Sharti } else { 586146155Sharti return (fd); 587146155Sharti } 588146155Sharti } else { 589146155Sharti if (errno != EEXIST) { 590146155Sharti return (-1); 591146155Sharti } 592146155Sharti } 593146155Sharti 594146155Sharti /* 595146155Sharti * If we have a collision, cycle through the space of 596146155Sharti * filenames. 597146155Sharti */ 598146155Sharti for (ptr = start;;) { 599146155Sharti char *pad; 600146155Sharti 601146155Sharti if (*ptr == '\0' || ptr == pathend) 602146155Sharti return (-1); 603146155Sharti 604146155Sharti pad = strchr(padchar, *ptr); 605146155Sharti if (pad == NULL || *++pad == '\0') { 606146155Sharti *ptr++ = padchar[0]; 607146155Sharti } else { 608146155Sharti *ptr++ = *pad; 609146155Sharti break; 610146155Sharti } 611146155Sharti } 612146155Sharti } 613146155Sharti /*NOTREACHED*/ 614146155Sharti} 615146155Sharti 616146144Shartistatic void 617146144Sharticatch_child(int sig __unused) 618146144Sharti{ 619146144Sharti} 620146144Sharti 621144467Sharti/** 622146144Sharti */ 623146144Shartivoid 624146144ShartiProc_Init() 625146144Sharti{ 626146144Sharti /* 627146144Sharti * Catch SIGCHLD so that we get kicked out of select() when we 628146144Sharti * need to look at a child. This is only known to matter for the 629146144Sharti * -j case (perhaps without -P). 630146144Sharti * 631146144Sharti * XXX this is intentionally misplaced. 632146144Sharti */ 633146144Sharti struct sigaction sa; 634146144Sharti 635146144Sharti sigemptyset(&sa.sa_mask); 636146144Sharti sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; 637146144Sharti sa.sa_handler = catch_child; 638146144Sharti sigaction(SIGCHLD, &sa, NULL); 639146144Sharti 640146144Sharti#if DEFSHELL == 2 641146144Sharti /* 642146144Sharti * Turn off ENV to make ksh happier. 643146144Sharti */ 644146144Sharti unsetenv("ENV"); 645146144Sharti#endif 646146144Sharti} 647146144Sharti 648146144Sharti/** 649146129Sharti * Replace the current process. 650146129Sharti */ 651146129Shartistatic void 652146129ShartiProcExec(const ProcStuff *ps) 653146129Sharti{ 654146129Sharti 655146129Sharti if (ps->in != STDIN_FILENO) { 656146129Sharti /* 657146129Sharti * Redirect the child's stdin to the input fd 658146129Sharti * and reset it to the beginning (again). 659146129Sharti */ 660146129Sharti if (dup2(ps->in, STDIN_FILENO) == -1) 661146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 662146129Sharti lseek(STDIN_FILENO, (off_t)0, SEEK_SET); 663146129Sharti } 664146129Sharti 665146129Sharti if (ps->out != STDOUT_FILENO) { 666146129Sharti /* 667146129Sharti * Redirect the child's stdout to the output fd. 668146129Sharti */ 669146129Sharti if (dup2(ps->out, STDOUT_FILENO) == -1) 670146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 671146129Sharti close(ps->out); 672146129Sharti } 673146129Sharti 674146129Sharti if (ps->err != STDERR_FILENO) { 675146129Sharti /* 676146129Sharti * Redirect the child's stderr to the err fd. 677146129Sharti */ 678146129Sharti if (dup2(ps->err, STDERR_FILENO) == -1) 679146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 680146129Sharti close(ps->err); 681146129Sharti } 682146129Sharti 683146129Sharti if (ps->merge_errors) { 684146129Sharti /* 685146129Sharti * Send stderr to parent process too. 686146129Sharti */ 687146129Sharti if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 688146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 689146129Sharti } 690146129Sharti 691146129Sharti /* 692146129Sharti * The file descriptors for stdin, stdout, or stderr might 693146129Sharti * have been marked close-on-exec. Clear the flag on all 694146129Sharti * of them. 695146129Sharti */ 696146129Sharti fcntl(STDIN_FILENO, F_SETFD, 697146129Sharti fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC)); 698146129Sharti fcntl(STDOUT_FILENO, F_SETFD, 699146129Sharti fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC)); 700146129Sharti fcntl(STDERR_FILENO, F_SETFD, 701146129Sharti fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC)); 702146129Sharti 703146129Sharti if (ps->pgroup) { 704146129Sharti#ifdef USE_PGRP 705146129Sharti /* 706146129Sharti * Become a process group leader, so we can kill it and all 707146129Sharti * its descendants in one fell swoop, by killing its process 708146129Sharti * family, but not commit suicide. 709146129Sharti */ 710146129Sharti#if defined(SYSV) 711146129Sharti setsid(); 712146129Sharti#else 713146129Sharti setpgid(0, getpid()); 714146129Sharti#endif 715146129Sharti#endif /* USE_PGRP */ 716146129Sharti } 717146129Sharti 718146129Sharti if (ps->searchpath) { 719146129Sharti execvp(ps->argv[0], ps->argv); 720146129Sharti 721146129Sharti write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0])); 722146129Sharti write(STDERR_FILENO, ":", 1); 723146129Sharti write(STDERR_FILENO, strerror(errno), strlen(strerror(errno))); 724146129Sharti write(STDERR_FILENO, "\n", 1); 725146129Sharti } else { 726146129Sharti execv(shellPath, ps->argv); 727146129Sharti 728146129Sharti write(STDERR_FILENO, 729146129Sharti "Could not execute shell\n", 730146129Sharti sizeof("Could not execute shell")); 731146129Sharti } 732146129Sharti 733146129Sharti /* 734146129Sharti * Since we are the child process, exit without flushing buffers. 735146129Sharti */ 736146129Sharti _exit(1); 737146129Sharti /* NOTREACHED */ 738146129Sharti} 739146129Sharti 740146129Sharti/** 741146131Sharti * Wait for child process to terminate. 742146130Sharti */ 743146130Shartistatic int 744146130ShartiProcWait(ProcStuff *ps) 745146130Sharti{ 746146130Sharti pid_t pid; 747146130Sharti int status; 748146130Sharti 749146130Sharti /* 750146130Sharti * Wait for the process to exit. 751146130Sharti */ 752146131Sharti for (;;) { 753146131Sharti pid = wait(&status); 754146131Sharti if (pid == -1 && errno != EINTR) { 755146131Sharti Fatal("error in wait: %d", pid); 756146131Sharti /* NOTREACHED */ 757146131Sharti } 758146131Sharti if (pid == ps->child_pid) { 759146131Sharti break; 760146131Sharti } 761146131Sharti if (interrupted) { 762146131Sharti break; 763146131Sharti } 764146130Sharti } 765146130Sharti 766146130Sharti return (status); 767146130Sharti} 768146130Sharti 769146130Sharti/** 770137605Sharti * JobCatchSignal 771144467Sharti * Got a signal. Set global variables and hope that someone will 772144467Sharti * handle it. 773137605Sharti */ 774137605Shartistatic void 775137605ShartiJobCatchSig(int signo) 776137605Sharti{ 777137605Sharti 778137605Sharti interrupted = signo; 779137605Sharti} 780137605Sharti 781144467Sharti/** 7821590Srgrimes * JobPassSig -- 783137252Sharti * Pass a signal on to all local jobs if 7841590Srgrimes * USE_PGRP is defined, then die ourselves. 7851590Srgrimes * 7861590Srgrimes * Side Effects: 7871590Srgrimes * We die by the same signal. 7881590Srgrimes */ 7891590Srgrimesstatic void 790104696SjmallettJobPassSig(int signo) 7911590Srgrimes{ 792144741Sharti Job *job; 793144467Sharti sigset_t nmask, omask; 794144467Sharti struct sigaction act; 7958874Srgrimes 796144467Sharti sigemptyset(&nmask); 797144467Sharti sigaddset(&nmask, signo); 798144467Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 799137605Sharti 800144467Sharti DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo)); 801144741Sharti TAILQ_FOREACH(job, &jobs, link) { 802144741Sharti DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 803144741Sharti signo, (intmax_t)job->pid)); 804144741Sharti KILL(job->pid, signo); 805144741Sharti } 8061590Srgrimes 807144467Sharti /* 808144467Sharti * Deal with proper cleanup based on the signal received. We only run 809144467Sharti * the .INTERRUPT target if the signal was in fact an interrupt. 810144467Sharti * The other three termination signals are more of a "get out *now*" 811144467Sharti * command. 812144467Sharti */ 813144467Sharti if (signo == SIGINT) { 814144467Sharti JobInterrupt(TRUE, signo); 815144657Sharti } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { 816144467Sharti JobInterrupt(FALSE, signo); 817144467Sharti } 8188874Srgrimes 819144467Sharti /* 820144467Sharti * Leave gracefully if SIGQUIT, rather than core dumping. 821144467Sharti */ 822144467Sharti if (signo == SIGQUIT) { 823144467Sharti signo = SIGINT; 824144467Sharti } 8258874Srgrimes 826144467Sharti /* 827144467Sharti * Send ourselves the signal now we've given the message to everyone 828144467Sharti * else. Note we block everything else possible while we're getting 829144467Sharti * the signal. This ensures that all our jobs get continued when we 830144467Sharti * wake up before we take any other signal. 831144467Sharti * XXX this comment seems wrong. 832144467Sharti */ 833144467Sharti act.sa_handler = SIG_DFL; 834144467Sharti sigemptyset(&act.sa_mask); 835144467Sharti act.sa_flags = 0; 836144467Sharti sigaction(signo, &act, NULL); 8371590Srgrimes 838144467Sharti DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n", 839144467Sharti ~0 & ~(1 << (signo - 1)))); 840144467Sharti signal(signo, SIG_DFL); 8411590Srgrimes 842144467Sharti KILL(getpid(), signo); 84318730Ssteve 844144467Sharti signo = SIGCONT; 845144741Sharti TAILQ_FOREACH(job, &jobs, link) { 846144741Sharti DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 847144741Sharti signo, (intmax_t)job->pid)); 848144741Sharti KILL(job->pid, signo); 849144741Sharti } 8501590Srgrimes 851144467Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 852144467Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 853144467Sharti act.sa_handler = JobPassSig; 854144467Sharti sigaction(signo, &act, NULL); 8551590Srgrimes} 8561590Srgrimes 857144467Sharti/** 8581590Srgrimes * JobPrintCommand -- 8591590Srgrimes * Put out another command for the given job. If the command starts 8601590Srgrimes * with an @ or a - we process it specially. In the former case, 8611590Srgrimes * so long as the -s and -n flags weren't given to make, we stick 8621590Srgrimes * a shell-specific echoOff command in the script. In the latter, 8631590Srgrimes * we ignore errors for the entire job, unless the shell has error 8641590Srgrimes * control. 8651590Srgrimes * If the command is just "..." we take all future commands for this 8661590Srgrimes * job to be commands to be executed once the entire graph has been 8671590Srgrimes * made and return non-zero to signal that the end of the commands 8681590Srgrimes * was reached. These commands are later attached to the postCommands 86994594Sobrien * node and executed by Job_Finish when all things are done. 870142993Sharti * This function is called from JobStart via LST_FOREACH. 8711590Srgrimes * 8721590Srgrimes * Results: 8731590Srgrimes * Always 0, unless the command was "..." 8741590Srgrimes * 8751590Srgrimes * Side Effects: 8761590Srgrimes * If the command begins with a '-' and the shell has no error control, 8771590Srgrimes * the JOB_IGNERR flag is set in the job descriptor. 8781590Srgrimes * If the command is "..." and we're not ignoring such things, 8791590Srgrimes * tailCmds is set to the successor node of the cmd. 8801590Srgrimes * numCommands is incremented if the command is actually printed. 8811590Srgrimes */ 8821590Srgrimesstatic int 883144741ShartiJobPrintCommand(char *cmd, Job *job) 8841590Srgrimes{ 885144467Sharti Boolean noSpecials; /* true if we shouldn't worry about 886141258Sharti * inserting special commands into 887141258Sharti * the input stream. */ 888144467Sharti Boolean shutUp = FALSE; /* true if we put a no echo command 889141258Sharti * into the command file */ 890144467Sharti Boolean errOff = FALSE; /* true if we turned error checking 891141258Sharti * off before printing the command 892141258Sharti * and need to turn it back on */ 893144467Sharti const char *cmdTemplate;/* Template to use when printing the command */ 894144467Sharti char *cmdStart; /* Start of expanded command */ 895144467Sharti LstNode *cmdNode; /* Node for replacing the command */ 8961590Srgrimes 897144467Sharti noSpecials = (noExecute && !(job->node->type & OP_MAKE)); 8981590Srgrimes 899144467Sharti if (strcmp(cmd, "...") == 0) { 900144467Sharti job->node->type |= OP_SAVE_CMDS; 901144467Sharti if ((job->flags & JOB_IGNDOTS) == 0) { 902144467Sharti job->tailCmds = 903144467Sharti Lst_Succ(Lst_Member(&job->node->commands, cmd)); 904144467Sharti return (1); 905144467Sharti } 906144467Sharti return (0); 9071590Srgrimes } 9081590Srgrimes 909144467Sharti#define DBPRINTF(fmt, arg) \ 910144467Sharti DEBUGF(JOB, (fmt, arg)); \ 911144467Sharti fprintf(job->cmdFILE, fmt, arg); \ 912144467Sharti fflush(job->cmdFILE); 9131590Srgrimes 914144467Sharti numCommands += 1; 9151590Srgrimes 916144467Sharti /* 917144467Sharti * For debugging, we replace each command with the result of expanding 918144467Sharti * the variables in the command. 919144467Sharti */ 920144467Sharti cmdNode = Lst_Member(&job->node->commands, cmd); 921142457Sharti 922146027Sharti cmd = Buf_Peel(Var_Subst(cmd, job->node, FALSE)); 923144467Sharti cmdStart = cmd; 924142457Sharti 925144467Sharti Lst_Replace(cmdNode, cmdStart); 9261590Srgrimes 927144467Sharti cmdTemplate = "%s\n"; 9281590Srgrimes 929144467Sharti /* 930144467Sharti * Check for leading @', -' or +'s to control echoing, error checking, 931144467Sharti * and execution on -n. 932144467Sharti */ 933144467Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 934144467Sharti switch (*cmd) { 935132839Sharti 936144467Sharti case '@': 937144467Sharti shutUp = DEBUG(LOUD) ? FALSE : TRUE; 938144467Sharti break; 939132839Sharti 940144467Sharti case '-': 941144467Sharti errOff = TRUE; 942144467Sharti break; 943132839Sharti 944144467Sharti case '+': 945144467Sharti if (noSpecials) { 946144467Sharti /* 947144467Sharti * We're not actually exececuting anything... 948144467Sharti * but this one needs to be - use compat mode 949144467Sharti * just for it. 950144467Sharti */ 951144741Sharti Compat_RunCommand(cmd, job->node); 952144467Sharti return (0); 953144467Sharti } 954144467Sharti break; 955144467Sharti } 956144467Sharti cmd++; 9571590Srgrimes } 9581590Srgrimes 959144467Sharti while (isspace((unsigned char)*cmd)) 960144467Sharti cmd++; 9611590Srgrimes 962144467Sharti if (shutUp) { 963144467Sharti if (!(job->flags & JOB_SILENT) && !noSpecials && 9641590Srgrimes commandShell->hasEchoCtl) { 96518730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 9661590Srgrimes } else { 967144467Sharti shutUp = FALSE; 9681590Srgrimes } 969144467Sharti } 970144467Sharti 971144467Sharti if (errOff) { 972144467Sharti if (!(job->flags & JOB_IGNERR) && !noSpecials) { 973144467Sharti if (commandShell->hasErrCtl) { 974144467Sharti /* 975144467Sharti * We don't want the error-control commands 976144467Sharti * showing up either, so we turn off echoing 977144467Sharti * while executing them. We could put another 978144467Sharti * field in the shell structure to tell 979144467Sharti * JobDoOutput to look for this string too, 980144467Sharti * but why make it any more complex than 981144467Sharti * it already is? 982144467Sharti */ 983144467Sharti if (!(job->flags & JOB_SILENT) && !shutUp && 984144467Sharti commandShell->hasEchoCtl) { 985144467Sharti DBPRINTF("%s\n", commandShell->echoOff); 986144467Sharti DBPRINTF("%s\n", commandShell->ignErr); 987144467Sharti DBPRINTF("%s\n", commandShell->echoOn); 988144467Sharti } else { 989144467Sharti DBPRINTF("%s\n", commandShell->ignErr); 990144467Sharti } 991144467Sharti } else if (commandShell->ignErr && 992144657Sharti *commandShell->ignErr != '\0') { 993144467Sharti /* 994144467Sharti * The shell has no error control, so we need to 995144467Sharti * be weird to get it to ignore any errors from 996144467Sharti * the command. If echoing is turned on, we turn 997144467Sharti * it off and use the errCheck template to echo 998144467Sharti * the command. Leave echoing off so the user 999144467Sharti * doesn't see the weirdness we go through to 1000144467Sharti * ignore errors. Set cmdTemplate to use the 1001144467Sharti * weirdness instead of the simple "%s\n" 1002144467Sharti * template. 1003144467Sharti */ 1004144467Sharti if (!(job->flags & JOB_SILENT) && !shutUp && 1005144467Sharti commandShell->hasEchoCtl) { 1006144467Sharti DBPRINTF("%s\n", commandShell->echoOff); 1007144467Sharti DBPRINTF(commandShell->errCheck, cmd); 1008144467Sharti shutUp = TRUE; 1009144467Sharti } 1010144467Sharti cmdTemplate = commandShell->ignErr; 1011144467Sharti /* 1012144467Sharti * The error ignoration (hee hee) is already 1013144467Sharti * taken care of by the ignErr template, so 1014144467Sharti * pretend error checking is still on. 1015144467Sharti */ 1016144467Sharti errOff = FALSE; 1017144467Sharti } else { 1018144467Sharti errOff = FALSE; 1019144467Sharti } 1020144467Sharti } else { 1021144467Sharti errOff = FALSE; 1022144467Sharti } 1023144467Sharti } 1024144467Sharti 1025144467Sharti DBPRINTF(cmdTemplate, cmd); 1026144467Sharti 1027144467Sharti if (errOff) { 10281590Srgrimes /* 1029144467Sharti * If echoing is already off, there's no point in issuing the 1030144467Sharti * echoOff command. Otherwise we issue it and pretend it was on 1031144467Sharti * for the whole command... 10321590Srgrimes */ 1033144467Sharti if (!shutUp && !(job->flags & JOB_SILENT) && 10341590Srgrimes commandShell->hasEchoCtl) { 103518730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 10361590Srgrimes shutUp = TRUE; 10371590Srgrimes } 1038144467Sharti DBPRINTF("%s\n", commandShell->errCheck); 10391590Srgrimes } 1040144467Sharti if (shutUp) { 1041144467Sharti DBPRINTF("%s\n", commandShell->echoOn); 10421590Srgrimes } 1043144467Sharti return (0); 10441590Srgrimes} 10451590Srgrimes 1046144467Sharti/** 104718730Ssteve * JobClose -- 104818730Ssteve * Called to close both input and output pipes when a job is finished. 104918730Ssteve * 105018730Ssteve * Side Effects: 105118730Ssteve * The file descriptors associated with the job are closed. 105218730Ssteve */ 105318730Sstevestatic void 1054104696SjmallettJobClose(Job *job) 105518730Ssteve{ 1056138232Sharti 1057144467Sharti if (usePipes) { 1058137202Sharti#if !defined(USE_KQUEUE) 1059144467Sharti FD_CLR(job->inPipe, &outputs); 106018730Ssteve#endif 1061144467Sharti if (job->outPipe != job->inPipe) { 1062144467Sharti close(job->outPipe); 1063144467Sharti } 1064144467Sharti JobDoOutput(job, TRUE); 1065144467Sharti close(job->inPipe); 1066144467Sharti } else { 1067144467Sharti close(job->outFd); 1068144467Sharti JobDoOutput(job, TRUE); 106918730Ssteve } 107018730Ssteve} 107118730Ssteve 1072144467Sharti/** 10731590Srgrimes * JobFinish -- 10741590Srgrimes * Do final processing for the given job including updating 10751590Srgrimes * parents and starting new jobs as available/necessary. Note 10761590Srgrimes * that we pay no attention to the JOB_IGNERR flag here. 10771590Srgrimes * This is because when we're called because of a noexecute flag 10781590Srgrimes * or something, jstat.w_status is 0 and when called from 10791590Srgrimes * Job_CatchChildren, the status is zeroed if it s/b ignored. 10801590Srgrimes * 10811590Srgrimes * Side Effects: 10821590Srgrimes * Some nodes may be put on the toBeMade queue. 10831590Srgrimes * Final commands for the job are placed on postCommands. 10841590Srgrimes * 10851590Srgrimes * If we got an error and are aborting (aborting == ABORT_ERROR) and 10861590Srgrimes * the job list is now empty, we are done for the day. 10871590Srgrimes * If we recognized an error (errors !=0), we set the aborting flag 10881590Srgrimes * to ABORT_ERROR so no more jobs will be started. 10891590Srgrimes */ 10901590Srgrimesstatic void 1091104696SjmallettJobFinish(Job *job, int *status) 10921590Srgrimes{ 1093144467Sharti Boolean done; 1094144467Sharti LstNode *ln; 10951590Srgrimes 1096146133Sharti if (WIFEXITED(*status)) { 1097146133Sharti int job_status = WEXITSTATUS(*status); 1098146133Sharti 1099144467Sharti JobClose(job); 1100144467Sharti /* 1101146133Sharti * Deal with ignored errors in -B mode. We need to 1102146133Sharti * print a message telling of the ignored error as 1103146133Sharti * well as setting status.w_status to 0 so the next 1104146133Sharti * command gets run. To do this, we set done to be 1105146133Sharti * TRUE if in -B mode and the job exited non-zero. 1106144467Sharti */ 1107146133Sharti if (job_status == 0) { 1108146133Sharti done = FALSE; 1109146133Sharti } else { 1110146133Sharti if (job->flags & JOB_IGNERR) { 1111146133Sharti done = TRUE; 1112146133Sharti } else { 1113146133Sharti /* 1114146133Sharti * If it exited non-zero and either we're 1115146133Sharti * doing things our way or we're not ignoring 1116146133Sharti * errors, the job is finished. Similarly, if 1117146133Sharti * the shell died because of a signal the job 1118146133Sharti * is also finished. In these cases, finish 1119146133Sharti * out the job's output before printing the 1120146133Sharti * exit status... 1121146133Sharti */ 1122146133Sharti done = TRUE; 1123146133Sharti if (job->cmdFILE != NULL && 1124146133Sharti job->cmdFILE != stdout) { 1125146133Sharti fclose(job->cmdFILE); 1126146133Sharti } 11278874Srgrimes 1128146133Sharti } 1129146133Sharti } 1130146133Sharti } else if (WIFSIGNALED(*status)) { 1131146133Sharti if (WTERMSIG(*status) == SIGCONT) { 1132146133Sharti /* 1133146133Sharti * No need to close things down or anything. 1134146133Sharti */ 1135146133Sharti done = FALSE; 1136146133Sharti } else { 1137146133Sharti /* 1138146133Sharti * If it exited non-zero and either we're 1139146133Sharti * doing things our way or we're not ignoring 1140146133Sharti * errors, the job is finished. Similarly, if 1141146133Sharti * the shell died because of a signal the job 1142146133Sharti * is also finished. In these cases, finish 1143146133Sharti * out the job's output before printing the 1144146133Sharti * exit status... 1145146133Sharti */ 1146146133Sharti JobClose(job); 1147146133Sharti if (job->cmdFILE != NULL && 1148146133Sharti job->cmdFILE != stdout) { 1149146133Sharti fclose(job->cmdFILE); 1150146133Sharti } 1151146133Sharti done = TRUE; 1152146133Sharti } 11531590Srgrimes } else { 1154144467Sharti /* 1155144467Sharti * No need to close things down or anything. 1156144467Sharti */ 1157144467Sharti done = FALSE; 11581590Srgrimes } 11591590Srgrimes 1160146133Sharti if (WIFEXITED(*status)) { 1161146133Sharti if (done || DEBUG(JOB)) { 1162146133Sharti FILE *out; 1163144467Sharti 1164146133Sharti if (compatMake && 1165146133Sharti !usePipes && 1166146133Sharti (job->flags & JOB_IGNERR)) { 1167146133Sharti /* 1168146133Sharti * If output is going to a file and this job 1169146133Sharti * is ignoring errors, arrange to have the 1170146133Sharti * exit status sent to the output file as 1171146133Sharti * well. 1172146133Sharti */ 1173146133Sharti out = fdopen(job->outFd, "w"); 1174146133Sharti if (out == NULL) 1175146133Sharti Punt("Cannot fdopen"); 1176146133Sharti } else { 1177146133Sharti out = stdout; 1178146133Sharti } 11791590Srgrimes 1180144665Sharti DEBUGF(JOB, ("Process %jd exited.\n", 1181144665Sharti (intmax_t)job->pid)); 1182146133Sharti 1183146133Sharti if (WEXITSTATUS(*status) == 0) { 1184146133Sharti if (DEBUG(JOB)) { 1185146133Sharti if (usePipes && job->node != lastNode) { 1186146133Sharti MESSAGE(out, job->node); 1187146133Sharti lastNode = job->node; 1188146133Sharti } 1189146133Sharti fprintf(out, 1190146133Sharti "*** Completed successfully\n"); 1191146133Sharti } 1192146133Sharti } else { 1193144467Sharti if (usePipes && job->node != lastNode) { 1194144467Sharti MESSAGE(out, job->node); 1195144467Sharti lastNode = job->node; 1196144467Sharti } 1197144467Sharti fprintf(out, "*** Error code %d%s\n", 1198146133Sharti WEXITSTATUS(*status), 1199146133Sharti (job->flags & JOB_IGNERR) ? 1200146133Sharti "(ignored)" : ""); 1201144467Sharti 1202144467Sharti if (job->flags & JOB_IGNERR) { 1203144467Sharti *status = 0; 1204144467Sharti } 1205144467Sharti } 1206144467Sharti 1207144467Sharti fflush(out); 1208146133Sharti } 1209146133Sharti } else if (WIFSIGNALED(*status)) { 1210146133Sharti if (done || DEBUG(JOB) || (WTERMSIG(*status) == SIGCONT)) { 1211146133Sharti FILE *out; 1212144467Sharti 1213146133Sharti if (compatMake && 1214146133Sharti !usePipes && 1215146133Sharti (job->flags & JOB_IGNERR)) { 1216146133Sharti /* 1217146133Sharti * If output is going to a file and this job 1218146133Sharti * is ignoring errors, arrange to have the 1219146133Sharti * exit status sent to the output file as 1220146133Sharti * well. 1221146133Sharti */ 1222146133Sharti out = fdopen(job->outFd, "w"); 1223146133Sharti if (out == NULL) 1224146133Sharti Punt("Cannot fdopen"); 1225146133Sharti } else { 1226146133Sharti out = stdout; 1227146133Sharti } 1228146133Sharti 1229146133Sharti if (WTERMSIG(*status) == SIGCONT) { 1230146133Sharti /* 1231146133Sharti * If the beastie has continued, shift the 1232146133Sharti * Job from the stopped list to the running 1233146133Sharti * one (or re-stop it if concurrency is 1234146133Sharti * exceeded) and go and get another child. 1235146133Sharti */ 1236146133Sharti if (job->flags & (JOB_RESUME | JOB_RESTART)) { 1237146133Sharti if (usePipes && job->node != lastNode) { 1238146133Sharti MESSAGE(out, job->node); 1239146133Sharti lastNode = job->node; 1240146133Sharti } 1241146133Sharti fprintf(out, "*** Continued\n"); 1242146133Sharti } 1243146133Sharti if (!(job->flags & JOB_CONTINUING)) { 1244146133Sharti DEBUGF(JOB, ("Warning: process %jd was not " 1245146133Sharti "continuing.\n", (intmax_t) job->pid)); 1246146133Sharti#ifdef notdef 1247146133Sharti /* 1248146133Sharti * We don't really want to restart a 1249146133Sharti * job from scratch just because it 1250146133Sharti * continued, especially not without 1251146133Sharti * killing the continuing process! 1252146133Sharti * That's why this is ifdef'ed out. 1253146133Sharti * FD - 9/17/90 1254146133Sharti */ 1255146133Sharti JobRestart(job); 1256146133Sharti#endif 1257146133Sharti } 1258146133Sharti job->flags &= ~JOB_CONTINUING; 1259146133Sharti TAILQ_INSERT_TAIL(&jobs, job, link); 1260146133Sharti nJobs += 1; 1261146133Sharti DEBUGF(JOB, ("Process %jd is continuing locally.\n", 1262146133Sharti (intmax_t) job->pid)); 1263146133Sharti if (nJobs == maxJobs) { 1264146133Sharti jobFull = TRUE; 1265146133Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1266146133Sharti } 1267146133Sharti fflush(out); 1268146133Sharti return; 1269146133Sharti 1270146133Sharti } else { 1271144467Sharti if (usePipes && job->node != lastNode) { 1272144467Sharti MESSAGE(out, job->node); 1273144467Sharti lastNode = job->node; 1274144467Sharti } 1275146133Sharti fprintf(out, 1276146133Sharti "*** Signal %d\n", WTERMSIG(*status)); 1277146133Sharti fflush(out); 1278144467Sharti } 1279146133Sharti } 1280146133Sharti } else { 1281146133Sharti /* STOPPED */ 1282146133Sharti FILE *out; 12831590Srgrimes 1284146133Sharti if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 1285146133Sharti /* 1286146133Sharti * If output is going to a file and this job 1287146133Sharti * is ignoring errors, arrange to have the 1288146133Sharti * exit status sent to the output file as 1289146133Sharti * well. 1290146133Sharti */ 1291146133Sharti out = fdopen(job->outFd, "w"); 1292146133Sharti if (out == NULL) 1293146133Sharti Punt("Cannot fdopen"); 1294144467Sharti } else { 1295146133Sharti out = stdout; 1296144467Sharti } 12971590Srgrimes 1298146133Sharti DEBUGF(JOB, ("Process %jd stopped.\n", (intmax_t) job->pid)); 1299146133Sharti if (usePipes && job->node != lastNode) { 1300146133Sharti MESSAGE(out, job->node); 1301146133Sharti lastNode = job->node; 1302146133Sharti } 1303146133Sharti fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status)); 1304146133Sharti job->flags |= JOB_RESUME; 1305146133Sharti TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 1306144467Sharti fflush(out); 1307146133Sharti return; 13081590Srgrimes } 13091590Srgrimes 13101590Srgrimes /* 1311144467Sharti * Now handle the -B-mode stuff. If the beast still isn't finished, 1312144467Sharti * try and restart the job on the next command. If JobStart says it's 1313144467Sharti * ok, it's ok. If there's an error, this puppy is done. 13141590Srgrimes */ 1315144467Sharti if (compatMake && WIFEXITED(*status) && 1316144467Sharti Lst_Succ(job->node->compat_command) != NULL) { 1317144467Sharti switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { 1318144467Sharti case JOB_RUNNING: 1319144467Sharti done = FALSE; 1320144467Sharti break; 1321144467Sharti case JOB_ERROR: 1322144467Sharti done = TRUE; 1323144467Sharti W_SETEXITSTATUS(status, 1); 1324144467Sharti break; 1325144467Sharti case JOB_FINISHED: 1326144467Sharti /* 1327144467Sharti * If we got back a JOB_FINISHED code, JobStart has 1328144467Sharti * already called Make_Update and freed the job 1329144467Sharti * descriptor. We set done to false here to avoid fake 1330144467Sharti * cycles and double frees. JobStart needs to do the 1331144467Sharti * update so we can proceed up the graph when given 1332144467Sharti * the -n flag.. 1333144467Sharti */ 1334144467Sharti done = FALSE; 1335144467Sharti break; 1336144467Sharti default: 1337144467Sharti break; 1338144467Sharti } 1339144467Sharti } else { 1340144467Sharti done = TRUE; 13411590Srgrimes } 1342143703Sharti 1343144657Sharti if (done && aborting != ABORT_ERROR && 1344144657Sharti aborting != ABORT_INTERRUPT && *status == 0) { 1345144467Sharti /* 1346144467Sharti * As long as we aren't aborting and the job didn't return a 1347144467Sharti * non-zero status that we shouldn't ignore, we call 1348144467Sharti * Make_Update to update the parents. In addition, any saved 1349144467Sharti * commands for the node are placed on the .END target. 1350144467Sharti */ 1351144467Sharti for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { 1352144467Sharti Lst_AtEnd(&postCommands->commands, 1353146027Sharti Buf_Peel( 1354146027Sharti Var_Subst(Lst_Datum(ln), job->node, FALSE))); 1355144467Sharti } 13561590Srgrimes 1357144467Sharti job->node->made = MADE; 1358144467Sharti Make_Update(job->node); 1359144467Sharti free(job); 13601590Srgrimes 1361144467Sharti } else if (*status != 0) { 1362144467Sharti errors += 1; 1363144467Sharti free(job); 1364144467Sharti } 1365144467Sharti 1366144467Sharti JobRestartJobs(); 1367144467Sharti 13681590Srgrimes /* 1369144467Sharti * Set aborting if any error. 13701590Srgrimes */ 1371144657Sharti if (errors && !keepgoing && aborting != ABORT_INTERRUPT) { 1372144467Sharti /* 1373144467Sharti * If we found any errors in this batch of children and the -k 1374144467Sharti * flag wasn't given, we set the aborting flag so no more jobs 1375144467Sharti * get started. 1376144467Sharti */ 1377144467Sharti aborting = ABORT_ERROR; 1378144467Sharti } 13798874Srgrimes 1380144657Sharti if (aborting == ABORT_ERROR && Job_Empty()) { 1381144467Sharti /* 1382144467Sharti * If we are aborting and the job table is now empty, we finish. 1383144467Sharti */ 1384144467Sharti Finish(errors); 1385144467Sharti } 13861590Srgrimes} 13871590Srgrimes 1388144467Sharti/** 1389144467Sharti * Job_Touch 13901590Srgrimes * Touch the given target. Called by JobStart when the -t flag was 1391104696Sjmallett * given. Prints messages unless told to be silent. 13921590Srgrimes * 13931590Srgrimes * Side Effects: 13941590Srgrimes * The data modification of the file is changed. In addition, if the 13951590Srgrimes * file did not exist, it is created. 13961590Srgrimes */ 13971590Srgrimesvoid 1398104696SjmallettJob_Touch(GNode *gn, Boolean silent) 13991590Srgrimes{ 1400144467Sharti int streamID; /* ID of stream opened to do the touch */ 1401144467Sharti struct utimbuf times; /* Times for utime() call */ 14021590Srgrimes 1403144467Sharti if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) { 1404144467Sharti /* 1405144467Sharti * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" 1406144467Sharti * targets and, as such, shouldn't really be created. 1407144467Sharti */ 1408144467Sharti return; 1409144467Sharti } 14108874Srgrimes 1411144467Sharti if (!silent) { 1412144467Sharti fprintf(stdout, "touch %s\n", gn->name); 1413144467Sharti fflush(stdout); 1414144467Sharti } 14151590Srgrimes 1416144467Sharti if (noExecute) { 1417144467Sharti return; 1418144467Sharti } 14191590Srgrimes 1420144467Sharti if (gn->type & OP_ARCHV) { 1421144467Sharti Arch_Touch(gn); 1422144467Sharti } else if (gn->type & OP_LIB) { 1423144467Sharti Arch_TouchLib(gn); 1424144467Sharti } else { 1425144467Sharti char *file = gn->path ? gn->path : gn->name; 14261590Srgrimes 1427144467Sharti times.actime = times.modtime = now; 1428144467Sharti if (utime(file, ×) < 0) { 1429144467Sharti streamID = open(file, O_RDWR | O_CREAT, 0666); 14301590Srgrimes 1431144467Sharti if (streamID >= 0) { 1432144467Sharti char c; 14331590Srgrimes 1434144467Sharti /* 1435144467Sharti * Read and write a byte to the file to change 1436144467Sharti * the modification time, then close the file. 1437144467Sharti */ 1438144467Sharti if (read(streamID, &c, 1) == 1) { 1439144467Sharti lseek(streamID, (off_t)0, SEEK_SET); 1440144467Sharti write(streamID, &c, 1); 1441144467Sharti } 1442144467Sharti 1443144467Sharti close(streamID); 1444144467Sharti } else { 1445144467Sharti fprintf(stdout, "*** couldn't touch %s: %s", 1446144467Sharti file, strerror(errno)); 1447144467Sharti fflush(stdout); 1448144467Sharti } 14491590Srgrimes } 14501590Srgrimes } 14511590Srgrimes} 14521590Srgrimes 1453144467Sharti/** 1454144467Sharti * Job_CheckCommands 14558874Srgrimes * Make sure the given node has all the commands it needs. 14561590Srgrimes * 14571590Srgrimes * Results: 14581590Srgrimes * TRUE if the commands list is/was ok. 14591590Srgrimes * 14601590Srgrimes * Side Effects: 14611590Srgrimes * The node will have commands from the .DEFAULT rule added to it 14621590Srgrimes * if it needs them. 14631590Srgrimes */ 14641590SrgrimesBoolean 1465104696SjmallettJob_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 14661590Srgrimes{ 1467138232Sharti 1468144467Sharti if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && 1469144467Sharti (gn->type & OP_LIB) == 0) { 1470144467Sharti /* 1471144467Sharti * No commands. Look for .DEFAULT rule from which we might infer 1472144467Sharti * commands. 1473144467Sharti */ 1474144657Sharti if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { 1475144467Sharti char *p1; 1476144467Sharti /* 1477144467Sharti * Make only looks for a .DEFAULT if the node was 1478144467Sharti * never the target of an operator, so that's what we 1479144467Sharti * do too. If a .DEFAULT was given, we substitute its 1480144467Sharti * commands for gn's commands and set the IMPSRC 1481144467Sharti * variable to be the target's name The DEFAULT node 1482144467Sharti * acts like a transformation rule, in that gn also 1483144467Sharti * inherits any attributes or sources attached to 1484144467Sharti * .DEFAULT itself. 1485144467Sharti */ 1486144467Sharti Make_HandleUse(DEFAULT, gn); 1487144467Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn); 1488144467Sharti free(p1); 148918730Ssteve 1490144467Sharti } else if (Dir_MTime(gn) == 0) { 1491144467Sharti /* 1492144467Sharti * The node wasn't the target of an operator we have 1493144467Sharti * no .DEFAULT rule to go on and the target doesn't 1494144467Sharti * already exist. There's nothing more we can do for 1495144467Sharti * this branch. If the -k flag wasn't given, we stop 1496144467Sharti * in our tracks, otherwise we just don't update 1497144467Sharti * this node's parents so they never get examined. 1498144467Sharti */ 1499144467Sharti static const char msg[] = 1500144467Sharti "make: don't know how to make"; 1501144467Sharti 1502144467Sharti if (gn->type & OP_OPTIONAL) { 1503144467Sharti fprintf(stdout, "%s %s(ignored)\n", 1504144467Sharti msg, gn->name); 1505144467Sharti fflush(stdout); 1506144467Sharti } else if (keepgoing) { 1507144467Sharti fprintf(stdout, "%s %s(continuing)\n", 1508144467Sharti msg, gn->name); 1509144467Sharti fflush(stdout); 1510144467Sharti return (FALSE); 1511144467Sharti } else { 151235483Simp#if OLD_JOKE 1513144467Sharti if (strcmp(gn->name,"love") == 0) 1514144467Sharti (*abortProc)("Not war."); 1515144467Sharti else 151635483Simp#endif 1517144467Sharti (*abortProc)("%s %s. Stop", 1518144467Sharti msg, gn->name); 1519144467Sharti return (FALSE); 1520144467Sharti } 1521144467Sharti } 15221590Srgrimes } 1523144467Sharti return (TRUE); 15241590Srgrimes} 15251590Srgrimes 1526144467Sharti/** 1527144467Sharti * JobExec 15281590Srgrimes * Execute the shell for the given job. Called from JobStart and 15291590Srgrimes * JobRestart. 15301590Srgrimes * 15311590Srgrimes * Side Effects: 15321590Srgrimes * A shell is executed, outputs is altered and the Job structure added 15331590Srgrimes * to the job table. 15341590Srgrimes */ 15351590Srgrimesstatic void 1536104696SjmallettJobExec(Job *job, char **argv) 15371590Srgrimes{ 1538146129Sharti ProcStuff ps; 15398874Srgrimes 1540144467Sharti if (DEBUG(JOB)) { 1541146061Sharti int i; 15428874Srgrimes 1543144467Sharti DEBUGF(JOB, ("Running %s\n", job->node->name)); 1544144467Sharti DEBUGF(JOB, ("\tCommand: ")); 1545144467Sharti for (i = 0; argv[i] != NULL; i++) { 1546144467Sharti DEBUGF(JOB, ("%s ", argv[i])); 1547144467Sharti } 1548144467Sharti DEBUGF(JOB, ("\n")); 15491590Srgrimes } 15508874Srgrimes 15511590Srgrimes /* 1552144467Sharti * Some jobs produce no output and it's disconcerting to have 1553144467Sharti * no feedback of their running (since they produce no output, the 1554144467Sharti * banner with their name in it never appears). This is an attempt to 1555144467Sharti * provide that feedback, even if nothing follows it. 15561590Srgrimes */ 1557144657Sharti if (lastNode != job->node && (job->flags & JOB_FIRST) && 1558144467Sharti !(job->flags & JOB_SILENT)) { 1559144467Sharti MESSAGE(stdout, job->node); 1560144467Sharti lastNode = job->node; 15611590Srgrimes } 15621590Srgrimes 1563146129Sharti ps.in = FILENO(job->cmdFILE); 1564146129Sharti if (usePipes) { 1565146129Sharti /* 1566146129Sharti * Set up the child's output to be routed through the 1567146129Sharti * pipe we've created for it. 1568146129Sharti */ 1569146129Sharti ps.out = job->outPipe; 1570146129Sharti } else { 1571146129Sharti /* 1572146129Sharti * We're capturing output in a file, so we duplicate 1573146129Sharti * the descriptor to the temporary file into the 1574146129Sharti * standard output. 1575146129Sharti */ 1576146129Sharti ps.out = job->outFd; 1577146129Sharti } 1578146129Sharti ps.err = STDERR_FILENO; 1579146129Sharti 1580146129Sharti ps.merge_errors = 1; 1581146129Sharti ps.pgroup = 1; 1582146129Sharti ps.searchpath = 0; 1583146129Sharti 1584146129Sharti ps.argv = argv; 1585146156Sharti ps.argv_free = 0; 1586146129Sharti 1587146129Sharti /* 1588146129Sharti * Fork. Warning since we are doing vfork() instead of fork(), 1589146129Sharti * do not allocate memory in the child process! 1590146129Sharti */ 1591146130Sharti if ((ps.child_pid = vfork()) == -1) { 1592144467Sharti Punt("Cannot fork"); 1593144467Sharti 1594146130Sharti 1595146130Sharti } else if (ps.child_pid == 0) { 1596144665Sharti /* 1597144665Sharti * Child 1598144665Sharti */ 1599144467Sharti if (fifoFd >= 0) 1600144467Sharti close(fifoFd); 1601144467Sharti 1602146129Sharti ProcExec(&ps); 1603146129Sharti /* NOTREACHED */ 1604144665Sharti } 1605146130Sharti 1606144665Sharti /* 1607144665Sharti * Parent 1608144665Sharti */ 1609146130Sharti job->pid = ps.child_pid; 1610144467Sharti 1611144665Sharti if (usePipes && (job->flags & JOB_FIRST)) { 1612144665Sharti /* 1613144665Sharti * The first time a job is run for a node, we set the 1614144665Sharti * current position in the buffer to the beginning and 1615144665Sharti * mark another stream to watch in the outputs mask. 1616144665Sharti */ 1617104475Sphk#ifdef USE_KQUEUE 1618144665Sharti struct kevent kev[2]; 1619104475Sphk#endif 1620144665Sharti job->curPos = 0; 16218874Srgrimes 1622137202Sharti#if defined(USE_KQUEUE) 1623144665Sharti EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job); 1624144665Sharti EV_SET(&kev[1], job->pid, EVFILT_PROC, 1625144665Sharti EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL); 1626144665Sharti if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) { 1627144665Sharti /* 1628144665Sharti * kevent() will fail if the job is already 1629144665Sharti * finished 1630144665Sharti */ 1631144665Sharti if (errno != EINTR && errno != EBADF && errno != ESRCH) 1632144665Sharti Punt("kevent: %s", strerror(errno)); 1633144665Sharti } 16341590Srgrimes#else 1635144665Sharti FD_SET(job->inPipe, &outputs); 1636137202Sharti#endif /* USE_KQUEUE */ 1637144665Sharti } 1638144467Sharti 1639144665Sharti if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1640144665Sharti fclose(job->cmdFILE); 1641144665Sharti job->cmdFILE = NULL; 16421590Srgrimes } 16431590Srgrimes 1644144467Sharti /* 1645144467Sharti * Now the job is actually running, add it to the table. 1646144467Sharti */ 1647144467Sharti nJobs += 1; 1648144494Sharti TAILQ_INSERT_TAIL(&jobs, job, link); 1649144467Sharti if (nJobs == maxJobs) { 1650144467Sharti jobFull = TRUE; 16511590Srgrimes } 16521590Srgrimes} 16531590Srgrimes 1654144467Sharti/** 1655144467Sharti * JobMakeArgv 16561590Srgrimes * Create the argv needed to execute the shell for a given job. 16571590Srgrimes */ 16581590Srgrimesstatic void 1659104696SjmallettJobMakeArgv(Job *job, char **argv) 16601590Srgrimes{ 1661144467Sharti int argc; 1662144467Sharti static char args[10]; /* For merged arguments */ 16638874Srgrimes 1664144467Sharti argv[0] = shellName; 1665144467Sharti argc = 1; 16661590Srgrimes 1667144657Sharti if ((commandShell->exit && *commandShell->exit != '-') || 1668144657Sharti (commandShell->echo && *commandShell->echo != '-')) { 1669144467Sharti /* 1670144467Sharti * At least one of the flags doesn't have a minus before it, so 1671144467Sharti * merge them together. Have to do this because the *(&(@*#*&#$# 1672144467Sharti * Bourne shell thinks its second argument is a file to source. 1673144467Sharti * Grrrr. Note the ten-character limitation on the combined 1674144467Sharti * arguments. 1675144467Sharti */ 1676144657Sharti sprintf(args, "-%s%s", (job->flags & JOB_IGNERR) ? "" : 1677144657Sharti commandShell->exit ? commandShell->exit : "", 1678144657Sharti (job->flags & JOB_SILENT) ? "" : 1679144657Sharti commandShell->echo ? commandShell->echo : ""); 16801590Srgrimes 1681144467Sharti if (args[1]) { 1682144467Sharti argv[argc] = args; 1683144467Sharti argc++; 1684144467Sharti } 1685144467Sharti } else { 1686144467Sharti if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1687144467Sharti argv[argc] = commandShell->exit; 1688144467Sharti argc++; 1689144467Sharti } 1690144467Sharti if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1691144467Sharti argv[argc] = commandShell->echo; 1692144467Sharti argc++; 1693144467Sharti } 16941590Srgrimes } 1695144467Sharti argv[argc] = NULL; 16961590Srgrimes} 16971590Srgrimes 1698144467Sharti/** 1699144467Sharti * JobRestart 1700144494Sharti * Restart a job that stopped for some reason. The job must be neither 1701144494Sharti * on the jobs nor on the stoppedJobs list. 17021590Srgrimes * 17031590Srgrimes * Side Effects: 17041590Srgrimes * jobFull will be set if the job couldn't be run. 17051590Srgrimes */ 17061590Srgrimesstatic void 1707104696SjmallettJobRestart(Job *job) 17081590Srgrimes{ 170918730Ssteve 1710144467Sharti if (job->flags & JOB_RESTART) { 1711144467Sharti /* 1712144467Sharti * Set up the control arguments to the shell. This is based on 1713144467Sharti * the flags set earlier for this job. If the JOB_IGNERR flag 1714144467Sharti * is clear, the 'exit' flag of the commandShell is used to 1715144467Sharti * cause it to exit upon receiving an error. If the JOB_SILENT 1716144467Sharti * flag is clear, the 'echo' flag of the commandShell is used 1717144467Sharti * to get it to start echoing as soon as it starts 1718144467Sharti * processing commands. 1719144467Sharti */ 1720144467Sharti char *argv[4]; 17218874Srgrimes 1722144467Sharti JobMakeArgv(job, argv); 17238874Srgrimes 1724144467Sharti DEBUGF(JOB, ("Restarting %s...", job->node->name)); 1725144657Sharti if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) { 1726144467Sharti /* 1727144657Sharti * Not allowed to run -- put it back on the hold 1728144657Sharti * queue and mark the table full 1729144467Sharti */ 1730144467Sharti DEBUGF(JOB, ("holding\n")); 1731144494Sharti TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1732144467Sharti jobFull = TRUE; 1733144467Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1734144467Sharti return; 1735144467Sharti } else { 1736144467Sharti /* 1737144467Sharti * Job may be run locally. 1738144467Sharti */ 1739144467Sharti DEBUGF(JOB, ("running locally\n")); 1740144467Sharti } 1741144467Sharti JobExec(job, argv); 1742144467Sharti 1743137202Sharti } else { 17441590Srgrimes /* 1745144467Sharti * The job has stopped and needs to be restarted. 1746144467Sharti * Why it stopped, we don't know... 17471590Srgrimes */ 1748144467Sharti DEBUGF(JOB, ("Resuming %s...", job->node->name)); 1749144657Sharti if ((nJobs < maxJobs || ((job->flags & JOB_SPECIAL) && 1750144657Sharti maxJobs == 0)) && nJobs != maxJobs) { 1751144467Sharti /* 1752144467Sharti * If we haven't reached the concurrency limit already 1753144467Sharti * (or the job must be run and maxJobs is 0), it's ok 1754144467Sharti * to resume it. 1755144467Sharti */ 1756144467Sharti Boolean error; 1757144467Sharti int status; 17588874Srgrimes 1759144467Sharti error = (KILL(job->pid, SIGCONT) != 0); 1760144467Sharti 1761144467Sharti if (!error) { 1762144467Sharti /* 1763144467Sharti * Make sure the user knows we've continued 1764144467Sharti * the beast and actually put the thing in the 1765144467Sharti * job table. 1766144467Sharti */ 1767144467Sharti job->flags |= JOB_CONTINUING; 1768144467Sharti status = 0; 1769144467Sharti W_SETTERMSIG(&status, SIGCONT); 1770144467Sharti JobFinish(job, &status); 1771144467Sharti 1772144467Sharti job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 1773144467Sharti DEBUGF(JOB, ("done\n")); 1774144467Sharti } else { 1775144467Sharti Error("couldn't resume %s: %s", 1776144467Sharti job->node->name, strerror(errno)); 1777144467Sharti status = 0; 1778144467Sharti W_SETEXITSTATUS(&status, 1); 1779144467Sharti JobFinish(job, &status); 1780144467Sharti } 1781144467Sharti } else { 1782144467Sharti /* 1783144467Sharti * Job cannot be restarted. Mark the table as full and 1784144467Sharti * place the job back on the list of stopped jobs. 1785144467Sharti */ 1786144467Sharti DEBUGF(JOB, ("table full\n")); 1787144494Sharti TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1788144467Sharti jobFull = TRUE; 1789144467Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1790144467Sharti } 17911590Srgrimes } 17921590Srgrimes} 17931590Srgrimes 1794144467Sharti/** 1795144467Sharti * JobStart 17961590Srgrimes * Start a target-creation process going for the target described 17978874Srgrimes * by the graph node gn. 17981590Srgrimes * 17991590Srgrimes * Results: 18001590Srgrimes * JOB_ERROR if there was an error in the commands, JOB_FINISHED 18011590Srgrimes * if there isn't actually anything left to do for the job and 18021590Srgrimes * JOB_RUNNING if the job has been started. 18031590Srgrimes * 18041590Srgrimes * Side Effects: 18051590Srgrimes * A new Job node is created and added to the list of running 18061590Srgrimes * jobs. PMake is forked and a child shell created. 18071590Srgrimes */ 18081590Srgrimesstatic int 1809104696SjmallettJobStart(GNode *gn, int flags, Job *previous) 18101590Srgrimes{ 1811144467Sharti Job *job; /* new job descriptor */ 1812144467Sharti char *argv[4]; /* Argument vector to shell */ 1813144467Sharti Boolean cmdsOK; /* true if the nodes commands were all right */ 1814144467Sharti Boolean noExec; /* Set true if we decide not to run the job */ 1815144467Sharti int tfd; /* File descriptor for temp file */ 1816144467Sharti LstNode *ln; 1817144654Sharti char tfile[sizeof(TMPPAT)]; 18181590Srgrimes 1819144467Sharti if (interrupted) { 1820144467Sharti JobPassSig(interrupted); 1821144467Sharti return (JOB_ERROR); 1822144467Sharti } 1823144467Sharti if (previous != NULL) { 1824144467Sharti previous->flags &= ~(JOB_FIRST | JOB_IGNERR | JOB_SILENT); 1825144467Sharti job = previous; 1826144467Sharti } else { 1827144467Sharti job = emalloc(sizeof(Job)); 1828144467Sharti flags |= JOB_FIRST; 1829144467Sharti } 18301590Srgrimes 1831144467Sharti job->node = gn; 1832144467Sharti job->tailCmds = NULL; 18331590Srgrimes 18341590Srgrimes /* 1835144467Sharti * Set the initial value of the flags for this job based on the global 1836144467Sharti * ones and the node's attributes... Any flags supplied by the caller 1837144467Sharti * are also added to the field. 18381590Srgrimes */ 1839144467Sharti job->flags = 0; 1840144467Sharti if (Targ_Ignore(gn)) { 1841144467Sharti job->flags |= JOB_IGNERR; 18421590Srgrimes } 1843144467Sharti if (Targ_Silent(gn)) { 1844144467Sharti job->flags |= JOB_SILENT; 1845144467Sharti } 1846144467Sharti job->flags |= flags; 18478874Srgrimes 18481590Srgrimes /* 1849144467Sharti * Check the commands now so any attributes from .DEFAULT have a chance 1850144658Sharti * to migrate to the node. 18511590Srgrimes */ 1852144658Sharti if (!compatMake && (job->flags & JOB_FIRST)) { 1853144467Sharti cmdsOK = Job_CheckCommands(gn, Error); 1854144467Sharti } else { 1855144467Sharti cmdsOK = TRUE; 1856144467Sharti } 18571590Srgrimes 18581590Srgrimes /* 1859144467Sharti * If the -n flag wasn't given, we open up OUR (not the child's) 1860144467Sharti * temporary file to stuff commands in it. The thing is rd/wr so we 1861144467Sharti * don't need to reopen it to feed it to the shell. If the -n flag 1862144467Sharti * *was* given, we just set the file to be stdout. Cute, huh? 18631590Srgrimes */ 1864144467Sharti if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 1865144467Sharti /* 1866144467Sharti * We're serious here, but if the commands were bogus, we're 1867144467Sharti * also dead... 1868144467Sharti */ 1869144467Sharti if (!cmdsOK) { 1870144467Sharti DieHorribly(); 1871144467Sharti } 18728874Srgrimes 1873144467Sharti strcpy(tfile, TMPPAT); 1874144467Sharti if ((tfd = mkstemp(tfile)) == -1) 1875144467Sharti Punt("Cannot create temp file: %s", strerror(errno)); 1876144467Sharti job->cmdFILE = fdopen(tfd, "w+"); 1877144467Sharti eunlink(tfile); 1878144467Sharti if (job->cmdFILE == NULL) { 1879144467Sharti close(tfd); 1880144467Sharti Punt("Could not open %s", tfile); 1881144467Sharti } 1882144467Sharti fcntl(FILENO(job->cmdFILE), F_SETFD, 1); 1883144467Sharti /* 1884144467Sharti * Send the commands to the command file, flush all its 1885144467Sharti * buffers then rewind and remove the thing. 1886144467Sharti */ 1887144467Sharti noExec = FALSE; 1888138564Sharti 1889138564Sharti /* 1890144467Sharti * Used to be backwards; replace when start doing multiple 1891144467Sharti * commands per shell. 1892138564Sharti */ 1893144467Sharti if (compatMake) { 1894144467Sharti /* 1895144467Sharti * Be compatible: If this is the first time for this 1896144467Sharti * node, verify its commands are ok and open the 1897144467Sharti * commands list for sequential access by later 1898144467Sharti * invocations of JobStart. Once that is done, we take 1899144467Sharti * the next command off the list and print it to the 1900144467Sharti * command file. If the command was an ellipsis, note 1901144467Sharti * that there's nothing more to execute. 1902144467Sharti */ 1903144467Sharti if (job->flags & JOB_FIRST) 1904144467Sharti gn->compat_command = Lst_First(&gn->commands); 1905144467Sharti else 1906144467Sharti gn->compat_command = 1907144467Sharti Lst_Succ(gn->compat_command); 19088874Srgrimes 1909144467Sharti if (gn->compat_command == NULL || 1910144467Sharti JobPrintCommand(Lst_Datum(gn->compat_command), job)) 1911144467Sharti noExec = TRUE; 1912144467Sharti 1913144467Sharti if (noExec && !(job->flags & JOB_FIRST)) { 1914144467Sharti /* 1915144467Sharti * If we're not going to execute anything, the 1916144467Sharti * job is done and we need to close down the 1917144467Sharti * various file descriptors we've opened for 1918144467Sharti * output, then call JobDoOutput to catch the 1919144467Sharti * final characters or send the file to the 1920144467Sharti * screen... Note that the i/o streams are only 1921144467Sharti * open if this isn't the first job. Note also 1922144467Sharti * that this could not be done in 1923144467Sharti * Job_CatchChildren b/c it wasn't clear if 1924144467Sharti * there were more commands to execute or not... 1925144467Sharti */ 1926144467Sharti JobClose(job); 1927144467Sharti } 1928144467Sharti } else { 1929144467Sharti /* 1930144467Sharti * We can do all the commands at once. hooray for sanity 1931144467Sharti */ 1932144467Sharti numCommands = 0; 1933144467Sharti LST_FOREACH(ln, &gn->commands) { 1934144467Sharti if (JobPrintCommand(Lst_Datum(ln), job)) 1935144467Sharti break; 1936144467Sharti } 1937144467Sharti 1938144467Sharti /* 1939144467Sharti * If we didn't print out any commands to the shell 1940144467Sharti * script, there's not much point in executing the 1941144467Sharti * shell, is there? 1942144467Sharti */ 1943144467Sharti if (numCommands == 0) { 1944144467Sharti noExec = TRUE; 1945144467Sharti } 1946144467Sharti } 1947144467Sharti 1948144467Sharti } else if (noExecute) { 1949144467Sharti /* 1950144467Sharti * Not executing anything -- just print all the commands to 1951144467Sharti * stdout in one fell swoop. This will still set up 1952144467Sharti * job->tailCmds correctly. 1953144467Sharti */ 1954144467Sharti if (lastNode != gn) { 1955144467Sharti MESSAGE(stdout, gn); 1956144467Sharti lastNode = gn; 1957144467Sharti } 1958144467Sharti job->cmdFILE = stdout; 1959144467Sharti 1960144467Sharti /* 1961144467Sharti * Only print the commands if they're ok, but don't die if 1962144467Sharti * they're not -- just let the user know they're bad and keep 1963144467Sharti * going. It doesn't do any harm in this case and may do 1964144467Sharti * some good. 1965144467Sharti */ 1966144467Sharti if (cmdsOK) { 1967144467Sharti LST_FOREACH(ln, &gn->commands) { 1968144467Sharti if (JobPrintCommand(Lst_Datum(ln), job)) 1969144467Sharti break; 1970144467Sharti } 1971144467Sharti } 1972144467Sharti /* 1973144467Sharti * Don't execute the shell, thank you. 1974144467Sharti */ 19751590Srgrimes noExec = TRUE; 1976144467Sharti 1977144467Sharti } else { 1978144467Sharti /* 1979144467Sharti * Just touch the target and note that no shell should be 1980144467Sharti * executed. Set cmdFILE to stdout to make life easier. Check 1981144467Sharti * the commands, too, but don't die if they're no good -- it 1982144467Sharti * does no harm to keep working up the graph. 1983144467Sharti */ 1984144467Sharti job->cmdFILE = stdout; 1985144467Sharti Job_Touch(gn, job->flags & JOB_SILENT); 1986144467Sharti noExec = TRUE; 19871590Srgrimes } 1988144467Sharti 19891590Srgrimes /* 1990144467Sharti * If we're not supposed to execute a shell, don't. 19911590Srgrimes */ 1992144467Sharti if (noExec) { 1993144467Sharti /* 1994144467Sharti * Unlink and close the command file if we opened one 1995144467Sharti */ 1996144467Sharti if (job->cmdFILE != stdout) { 1997144467Sharti if (job->cmdFILE != NULL) 1998144467Sharti fclose(job->cmdFILE); 1999144467Sharti } else { 2000144467Sharti fflush(stdout); 2001144467Sharti } 2002144467Sharti 2003144467Sharti /* 2004144467Sharti * We only want to work our way up the graph if we aren't here 2005144467Sharti * because the commands for the job were no good. 2006144467Sharti */ 2007144467Sharti if (cmdsOK) { 2008144467Sharti if (aborting == 0) { 2009144467Sharti for (ln = job->tailCmds; ln != NULL; 2010144467Sharti ln = LST_NEXT(ln)) { 2011144467Sharti Lst_AtEnd(&postCommands->commands, 2012146027Sharti Buf_Peel(Var_Subst(Lst_Datum(ln), 2013146027Sharti job->node, FALSE))); 2014144467Sharti } 2015144467Sharti job->node->made = MADE; 2016144467Sharti Make_Update(job->node); 2017144467Sharti } 2018144467Sharti free(job); 2019144467Sharti return(JOB_FINISHED); 2020144467Sharti } else { 2021144467Sharti free(job); 2022144467Sharti return(JOB_ERROR); 2023144467Sharti } 2024144467Sharti } else { 2025144467Sharti fflush(job->cmdFILE); 20261590Srgrimes } 2027144467Sharti 20281590Srgrimes /* 2029144467Sharti * Set up the control arguments to the shell. This is based on the flags 2030144467Sharti * set earlier for this job. 20311590Srgrimes */ 2032144467Sharti JobMakeArgv(job, argv); 20331590Srgrimes 20341590Srgrimes /* 2035144467Sharti * If we're using pipes to catch output, create the pipe by which we'll 2036144467Sharti * get the shell's output. If we're using files, print out that we're 2037144467Sharti * starting a job and then set up its temporary-file name. 20381590Srgrimes */ 2039144467Sharti if (!compatMake || (job->flags & JOB_FIRST)) { 2040144467Sharti if (usePipes) { 2041144467Sharti int fd[2]; 20421590Srgrimes 2043144467Sharti if (pipe(fd) == -1) 2044144467Sharti Punt("Cannot create pipe: %s", strerror(errno)); 2045144467Sharti job->inPipe = fd[0]; 2046144467Sharti job->outPipe = fd[1]; 2047144467Sharti fcntl(job->inPipe, F_SETFD, 1); 2048144467Sharti fcntl(job->outPipe, F_SETFD, 1); 2049144467Sharti } else { 2050144467Sharti fprintf(stdout, "Remaking `%s'\n", gn->name); 2051144467Sharti fflush(stdout); 2052144467Sharti strcpy(job->outFile, TMPPAT); 2053144467Sharti if ((job->outFd = mkstemp(job->outFile)) == -1) 2054144467Sharti Punt("cannot create temp file: %s", 2055144467Sharti strerror(errno)); 2056144467Sharti fcntl(job->outFd, F_SETFD, 1); 20571590Srgrimes } 20581590Srgrimes } 20591590Srgrimes 2060144657Sharti if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL) && maxJobs != 0) { 2061144467Sharti /* 2062144467Sharti * We've hit the limit of concurrency, so put the job on hold 2063144467Sharti * until some other job finishes. Note that the special jobs 2064144467Sharti * (.BEGIN, .INTERRUPT and .END) may be run even when the 2065144467Sharti * limit has been reached (e.g. when maxJobs == 0). 2066144467Sharti */ 2067144467Sharti jobFull = TRUE; 20681590Srgrimes 2069144467Sharti DEBUGF(JOB, ("Can only run job locally.\n")); 2070144467Sharti job->flags |= JOB_RESTART; 2071144494Sharti TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 20721590Srgrimes } else { 2073144467Sharti if (nJobs >= maxJobs) { 2074144467Sharti /* 2075144657Sharti * If we're running this job as a special case 2076144467Sharti * (see above), at least say the table is full. 2077144467Sharti */ 2078144467Sharti jobFull = TRUE; 2079144467Sharti DEBUGF(JOB, ("Local job queue is full.\n")); 2080144467Sharti } 2081144467Sharti JobExec(job, argv); 20821590Srgrimes } 2083144467Sharti return (JOB_RUNNING); 20841590Srgrimes} 20851590Srgrimes 208618730Sstevestatic char * 2087104696SjmallettJobOutput(Job *job, char *cp, char *endp, int msg) 208818730Ssteve{ 2089144467Sharti char *ecp; 209018730Ssteve 2091144467Sharti if (commandShell->noPrint) { 2092144467Sharti ecp = strstr(cp, commandShell->noPrint); 2093144467Sharti while (ecp != NULL) { 2094144467Sharti if (cp != ecp) { 2095144467Sharti *ecp = '\0'; 2096144467Sharti if (msg && job->node != lastNode) { 2097144467Sharti MESSAGE(stdout, job->node); 2098144467Sharti lastNode = job->node; 2099144467Sharti } 2100144467Sharti /* 2101144467Sharti * The only way there wouldn't be a newline 2102144467Sharti * after this line is if it were the last in 2103144467Sharti * the buffer. However, since the non-printable 2104144467Sharti * comes after it, there must be a newline, so 2105144467Sharti * we don't print one. 2106144467Sharti */ 2107144467Sharti fprintf(stdout, "%s", cp); 2108144467Sharti fflush(stdout); 2109144467Sharti } 2110144741Sharti cp = ecp + strlen(commandShell->noPrint); 2111144467Sharti if (cp != endp) { 2112144467Sharti /* 2113144467Sharti * Still more to print, look again after 2114144467Sharti * skipping the whitespace following the 2115144467Sharti * non-printable command.... 2116144467Sharti */ 2117144467Sharti cp++; 2118144467Sharti while (*cp == ' ' || *cp == '\t' || 2119144467Sharti *cp == '\n') { 2120144467Sharti cp++; 2121144467Sharti } 2122144467Sharti ecp = strstr(cp, commandShell->noPrint); 2123144467Sharti } else { 2124144467Sharti return (cp); 2125144467Sharti } 212618730Ssteve } 212718730Ssteve } 2128144467Sharti return (cp); 212918730Ssteve} 213018730Ssteve 2131144467Sharti/** 2132144467Sharti * JobDoOutput 21331590Srgrimes * This function is called at different times depending on 21341590Srgrimes * whether the user has specified that output is to be collected 21351590Srgrimes * via pipes or temporary files. In the former case, we are called 21361590Srgrimes * whenever there is something to read on the pipe. We collect more 21371590Srgrimes * output from the given job and store it in the job's outBuf. If 21381590Srgrimes * this makes up a line, we print it tagged by the job's identifier, 21391590Srgrimes * as necessary. 21401590Srgrimes * If output has been collected in a temporary file, we open the 21411590Srgrimes * file and read it line by line, transfering it to our own 21421590Srgrimes * output channel until the file is empty. At which point we 21431590Srgrimes * remove the temporary file. 21441590Srgrimes * In both cases, however, we keep our figurative eye out for the 21451590Srgrimes * 'noPrint' line for the shell from which the output came. If 21461590Srgrimes * we recognize a line, we don't print it. If the command is not 21471590Srgrimes * alone on the line (the character after it is not \0 or \n), we 21481590Srgrimes * do print whatever follows it. 21491590Srgrimes * 21501590Srgrimes * Side Effects: 21511590Srgrimes * curPos may be shifted as may the contents of outBuf. 21521590Srgrimes */ 2153144656Shartistatic void 2154104696SjmallettJobDoOutput(Job *job, Boolean finish) 21551590Srgrimes{ 2156144467Sharti Boolean gotNL = FALSE; /* true if got a newline */ 2157144467Sharti Boolean fbuf; /* true if our buffer filled up */ 2158144467Sharti int nr; /* number of bytes read */ 2159144467Sharti int i; /* auxiliary index into outBuf */ 2160144467Sharti int max; /* limit for i (end of current data) */ 2161144467Sharti int nRead; /* (Temporary) number of bytes read */ 2162144467Sharti FILE *oFILE; /* Stream pointer to shell's output file */ 2163144467Sharti char inLine[132]; 21641590Srgrimes 2165144467Sharti if (usePipes) { 21661590Srgrimes /* 2167144467Sharti * Read as many bytes as will fit in the buffer. 21681590Srgrimes */ 2169144467Sharti end_loop: 2170144467Sharti gotNL = FALSE; 2171144467Sharti fbuf = FALSE; 21728874Srgrimes 2173144467Sharti nRead = read(job->inPipe, &job->outBuf[job->curPos], 2174144467Sharti JOB_BUFSIZE - job->curPos); 21751590Srgrimes /* 2176144467Sharti * Check for interrupt here too, because the above read may 2177144467Sharti * block when the child process is stopped. In this case the 2178144467Sharti * interrupt will unblock it (we don't use SA_RESTART). 21791590Srgrimes */ 2180144467Sharti if (interrupted) 2181144467Sharti JobPassSig(interrupted); 21821590Srgrimes 2183144467Sharti if (nRead < 0) { 2184144467Sharti DEBUGF(JOB, ("JobDoOutput(piperead)")); 2185144467Sharti nr = 0; 2186144467Sharti } else { 2187144467Sharti nr = nRead; 2188144467Sharti } 21891590Srgrimes 21901590Srgrimes /* 2191144467Sharti * If we hit the end-of-file (the job is dead), we must flush 2192144467Sharti * its remaining output, so pretend we read a newline if 2193144467Sharti * there's any output remaining in the buffer. 2194144467Sharti * Also clear the 'finish' flag so we stop looping. 21951590Srgrimes */ 2196144657Sharti if (nr == 0 && job->curPos != 0) { 2197144467Sharti job->outBuf[job->curPos] = '\n'; 2198144467Sharti nr = 1; 2199144467Sharti finish = FALSE; 2200144467Sharti } else if (nr == 0) { 2201144467Sharti finish = FALSE; 22021590Srgrimes } 22038874Srgrimes 22041590Srgrimes /* 2205144467Sharti * Look for the last newline in the bytes we just got. If there 2206144467Sharti * is one, break out of the loop with 'i' as its index and 2207144467Sharti * gotNL set TRUE. 2208144467Sharti */ 2209144467Sharti max = job->curPos + nr; 2210144467Sharti for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 2211144467Sharti if (job->outBuf[i] == '\n') { 2212144467Sharti gotNL = TRUE; 2213144467Sharti break; 2214144467Sharti } else if (job->outBuf[i] == '\0') { 2215144467Sharti /* 2216144467Sharti * Why? 2217144467Sharti */ 2218144467Sharti job->outBuf[i] = ' '; 2219144467Sharti } 2220144467Sharti } 22211590Srgrimes 2222144467Sharti if (!gotNL) { 2223144467Sharti job->curPos += nr; 2224144467Sharti if (job->curPos == JOB_BUFSIZE) { 2225144467Sharti /* 2226144467Sharti * If we've run out of buffer space, we have 2227144467Sharti * no choice but to print the stuff. sigh. 2228144467Sharti */ 2229144467Sharti fbuf = TRUE; 2230144467Sharti i = job->curPos; 2231144467Sharti } 22321590Srgrimes } 2233144467Sharti if (gotNL || fbuf) { 2234144467Sharti /* 2235144467Sharti * Need to send the output to the screen. Null terminate 2236144467Sharti * it first, overwriting the newline character if there 2237144467Sharti * was one. So long as the line isn't one we should 2238144467Sharti * filter (according to the shell description), we print 2239144467Sharti * the line, preceded by a target banner if this target 2240144467Sharti * isn't the same as the one for which we last printed 2241144467Sharti * something. The rest of the data in the buffer are 2242144467Sharti * then shifted down to the start of the buffer and 2243144467Sharti * curPos is set accordingly. 2244144467Sharti */ 2245144467Sharti job->outBuf[i] = '\0'; 2246144467Sharti if (i >= job->curPos) { 2247144467Sharti char *cp; 22481590Srgrimes 2249144467Sharti cp = JobOutput(job, job->outBuf, 2250144467Sharti &job->outBuf[i], FALSE); 2251144467Sharti 2252144467Sharti /* 2253144467Sharti * There's still more in that buffer. This time, 2254144467Sharti * though, we know there's no newline at the 2255144467Sharti * end, so we add one of our own free will. 2256144467Sharti */ 2257144467Sharti if (*cp != '\0') { 2258144467Sharti if (job->node != lastNode) { 2259144467Sharti MESSAGE(stdout, job->node); 2260144467Sharti lastNode = job->node; 2261144467Sharti } 2262144467Sharti fprintf(stdout, "%s%s", cp, 2263144467Sharti gotNL ? "\n" : ""); 2264144467Sharti fflush(stdout); 2265144467Sharti } 2266144467Sharti } 2267144467Sharti if (i < max - 1) { 2268144467Sharti /* shift the remaining characters down */ 2269144467Sharti memcpy(job->outBuf, &job->outBuf[i + 1], 2270144467Sharti max - (i + 1)); 2271144467Sharti job->curPos = max - (i + 1); 2272144467Sharti 2273144467Sharti } else { 2274144467Sharti /* 2275144467Sharti * We have written everything out, so we just 2276144467Sharti * start over from the start of the buffer. 2277144467Sharti * No copying. No nothing. 2278144467Sharti */ 2279144467Sharti job->curPos = 0; 2280144467Sharti } 2281144467Sharti } 2282144467Sharti if (finish) { 2283144467Sharti /* 2284144467Sharti * If the finish flag is true, we must loop until we hit 2285144467Sharti * end-of-file on the pipe. This is guaranteed to happen 2286144467Sharti * eventually since the other end of the pipe is now 2287144467Sharti * closed (we closed it explicitly and the child has 2288144467Sharti * exited). When we do get an EOF, finish will be set 2289144467Sharti * FALSE and we'll fall through and out. 2290144467Sharti */ 2291144467Sharti goto end_loop; 2292144467Sharti } 2293144467Sharti 2294144467Sharti } else { 22951590Srgrimes /* 2296144467Sharti * We've been called to retrieve the output of the job from the 2297144467Sharti * temporary file where it's been squirreled away. This consists 2298144467Sharti * of opening the file, reading the output line by line, being 2299144467Sharti * sure not to print the noPrint line for the shell we used, 2300144467Sharti * then close and remove the temporary file. Very simple. 2301144467Sharti * 2302144467Sharti * Change to read in blocks and do FindSubString type things 2303144467Sharti * as for pipes? That would allow for "@echo -n..." 23041590Srgrimes */ 2305144467Sharti oFILE = fopen(job->outFile, "r"); 2306144467Sharti if (oFILE != NULL) { 2307144467Sharti fprintf(stdout, "Results of making %s:\n", 2308144467Sharti job->node->name); 2309144467Sharti fflush(stdout); 2310144467Sharti 2311144467Sharti while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 2312144467Sharti char *cp, *endp, *oendp; 2313144467Sharti 2314144467Sharti cp = inLine; 2315144467Sharti oendp = endp = inLine + strlen(inLine); 2316144467Sharti if (endp[-1] == '\n') { 2317144467Sharti *--endp = '\0'; 2318144467Sharti } 2319144467Sharti cp = JobOutput(job, inLine, endp, FALSE); 2320144467Sharti 2321144467Sharti /* 2322144467Sharti * There's still more in that buffer. This time, 2323144467Sharti * though, we know there's no newline at the 2324144467Sharti * end, so we add one of our own free will. 2325144467Sharti */ 2326144467Sharti fprintf(stdout, "%s", cp); 2327144467Sharti fflush(stdout); 2328144467Sharti if (endp != oendp) { 2329144467Sharti fprintf(stdout, "\n"); 2330144467Sharti fflush(stdout); 2331144467Sharti } 2332144467Sharti } 2333144467Sharti fclose(oFILE); 2334144467Sharti eunlink(job->outFile); 23351590Srgrimes } 23361590Srgrimes } 23371590Srgrimes} 23381590Srgrimes 2339144467Sharti/** 2340144467Sharti * Job_CatchChildren 23411590Srgrimes * Handle the exit of a child. Called from Make_Make. 23421590Srgrimes * 23431590Srgrimes * Side Effects: 23441590Srgrimes * The job descriptor is removed from the list of children. 23451590Srgrimes * 23461590Srgrimes * Notes: 23471590Srgrimes * We do waits, blocking or not, according to the wisdom of our 23481590Srgrimes * caller, until there are no more children to report. For each 23491590Srgrimes * job, call JobFinish to finish things off. This will take care of 23501590Srgrimes * putting jobs on the stoppedJobs queue. 23511590Srgrimes */ 23521590Srgrimesvoid 2353104696SjmallettJob_CatchChildren(Boolean block) 23541590Srgrimes{ 2355144665Sharti pid_t pid; /* pid of dead child */ 2356144467Sharti Job *job; /* job descriptor for dead child */ 2357144467Sharti int status; /* Exit/termination status */ 23581590Srgrimes 2359144467Sharti /* 2360144467Sharti * Don't even bother if we know there's no one around. 2361144467Sharti */ 2362144467Sharti if (nJobs == 0) { 2363144467Sharti return; 2364144467Sharti } 23658874Srgrimes 2366144467Sharti for (;;) { 2367144467Sharti pid = waitpid((pid_t)-1, &status, 2368144467Sharti (block ? 0 : WNOHANG) | WUNTRACED); 2369144467Sharti if (pid <= 0) 2370144467Sharti break; 23711590Srgrimes 2372144665Sharti DEBUGF(JOB, ("Process %jd exited or stopped.\n", 2373144665Sharti (intmax_t)pid)); 23741590Srgrimes 2375144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2376144494Sharti if (job->pid == pid) 2377144467Sharti break; 2378143810Sharti } 2379144467Sharti 2380144494Sharti if (job == NULL) { 2381144467Sharti if (WIFSIGNALED(status) && 2382144467Sharti (WTERMSIG(status) == SIGCONT)) { 2383144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2384144494Sharti if (job->pid == pid) 2385144467Sharti break; 2386144467Sharti } 2387144494Sharti if (job == NULL) { 2388144665Sharti Error("Resumed child (%jd) " 2389144665Sharti "not in table", (intmax_t)pid); 2390144467Sharti continue; 2391144467Sharti } 2392144494Sharti TAILQ_REMOVE(&stoppedJobs, job, link); 2393144467Sharti } else { 2394144665Sharti Error("Child (%jd) not in table?", 2395144665Sharti (intmax_t)pid); 2396144467Sharti continue; 2397144467Sharti } 2398144467Sharti } else { 2399144494Sharti TAILQ_REMOVE(&jobs, job, link); 2400144467Sharti nJobs -= 1; 2401144467Sharti if (fifoFd >= 0 && maxJobs > 1) { 2402144467Sharti write(fifoFd, "+", 1); 2403144467Sharti maxJobs--; 2404144467Sharti if (nJobs >= maxJobs) 2405144467Sharti jobFull = TRUE; 2406144467Sharti else 2407144467Sharti jobFull = FALSE; 2408144467Sharti } else { 2409144467Sharti DEBUGF(JOB, ("Job queue is no longer full.\n")); 2410144467Sharti jobFull = FALSE; 2411144467Sharti } 24121590Srgrimes } 2413144467Sharti 2414144467Sharti JobFinish(job, &status); 24151590Srgrimes } 2416144467Sharti if (interrupted) 2417144467Sharti JobPassSig(interrupted); 24181590Srgrimes} 24191590Srgrimes 2420144467Sharti/** 2421144467Sharti * Job_CatchOutput 24221590Srgrimes * Catch the output from our children, if we're using 24231590Srgrimes * pipes do so. Otherwise just block time until we get a 2424138232Sharti * signal(most likely a SIGCHLD) since there's no point in 24251590Srgrimes * just spinning when there's nothing to do and the reaping 24268874Srgrimes * of a child can wait for a while. 24271590Srgrimes * 24281590Srgrimes * Side Effects: 24291590Srgrimes * Output is read from pipes if we're piping. 24301590Srgrimes * ----------------------------------------------------------------------- 24311590Srgrimes */ 24321590Srgrimesvoid 2433139064Sharti#ifdef USE_KQUEUE 2434139064ShartiJob_CatchOutput(int flag __unused) 2435139064Sharti#else 2436137606SphkJob_CatchOutput(int flag) 2437139064Sharti#endif 24381590Srgrimes{ 2439144467Sharti int nfds; 2440104475Sphk#ifdef USE_KQUEUE 2441104475Sphk#define KEV_SIZE 4 2442144467Sharti struct kevent kev[KEV_SIZE]; 2443144467Sharti int i; 2444104475Sphk#else 2445144467Sharti struct timeval timeout; 2446144467Sharti fd_set readfds; 2447144467Sharti Job *job; 2448104475Sphk#endif 24491590Srgrimes 2450144467Sharti fflush(stdout); 24511590Srgrimes 2452144467Sharti if (usePipes) { 2453104475Sphk#ifdef USE_KQUEUE 2454144467Sharti if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) { 2455144467Sharti if (errno != EINTR) 2456144467Sharti Punt("kevent: %s", strerror(errno)); 2457144467Sharti if (interrupted) 2458144467Sharti JobPassSig(interrupted); 2459144467Sharti } else { 2460144467Sharti for (i = 0; i < nfds; i++) { 2461144467Sharti if (kev[i].flags & EV_ERROR) { 2462144467Sharti warnc(kev[i].data, "kevent"); 2463144467Sharti continue; 2464144467Sharti } 2465144467Sharti switch (kev[i].filter) { 2466144467Sharti case EVFILT_READ: 2467144467Sharti JobDoOutput(kev[i].udata, FALSE); 2468144467Sharti break; 2469144467Sharti case EVFILT_PROC: 2470144467Sharti /* 2471144467Sharti * Just wake up and let 2472144467Sharti * Job_CatchChildren() collect the 2473144467Sharti * terminated job. 2474144467Sharti */ 2475144467Sharti break; 2476144467Sharti } 2477144467Sharti } 2478104475Sphk } 2479104475Sphk#else 2480144467Sharti readfds = outputs; 2481144467Sharti timeout.tv_sec = SEL_SEC; 2482144467Sharti timeout.tv_usec = SEL_USEC; 2483144467Sharti if (flag && jobFull && fifoFd >= 0) 2484144467Sharti FD_SET(fifoFd, &readfds); 24851590Srgrimes 2486144467Sharti nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL, 2487144467Sharti (fd_set *)NULL, &timeout); 2488144467Sharti if (nfds <= 0) { 2489144467Sharti if (interrupted) 2490144467Sharti JobPassSig(interrupted); 2491144467Sharti return; 2492144467Sharti } 2493144467Sharti if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) { 2494144467Sharti if (--nfds <= 0) 2495144467Sharti return; 2496144467Sharti } 2497144494Sharti job = TAILQ_FIRST(&jobs); 2498144494Sharti while (nfds != 0 && job != NULL) { 2499144467Sharti if (FD_ISSET(job->inPipe, &readfds)) { 2500144467Sharti JobDoOutput(job, FALSE); 2501144494Sharti nfds--; 2502144467Sharti } 2503144494Sharti job = TAILQ_NEXT(job, link); 2504144467Sharti } 2505144467Sharti#endif /* !USE_KQUEUE */ 2506137606Sphk } 25071590Srgrimes} 25081590Srgrimes 2509144467Sharti/** 2510144467Sharti * Job_Make 25111590Srgrimes * Start the creation of a target. Basically a front-end for 25121590Srgrimes * JobStart used by the Make module. 25131590Srgrimes * 25141590Srgrimes * Side Effects: 25151590Srgrimes * Another job is started. 25161590Srgrimes */ 25171590Srgrimesvoid 2518104696SjmallettJob_Make(GNode *gn) 25191590Srgrimes{ 2520138232Sharti 2521144467Sharti JobStart(gn, 0, NULL); 25221590Srgrimes} 25231590Srgrimes 2524144467Sharti/** 2525144467Sharti * JobCopyShell 2526144467Sharti * Make a new copy of the shell structure including a copy of the strings 2527144467Sharti * in it. This also defaults some fields in case they are NULL. 2528138079Sharti * 2529144467Sharti * Returns: 2530144467Sharti * The function returns a pointer to the new shell structure. 2531138079Sharti */ 2532144483Shartistatic struct Shell * 2533144483ShartiJobCopyShell(const struct Shell *osh) 2534138079Sharti{ 2535144483Sharti struct Shell *nsh; 2536138079Sharti 2537138079Sharti nsh = emalloc(sizeof(*nsh)); 2538138079Sharti nsh->name = estrdup(osh->name); 2539138079Sharti 2540138079Sharti if (osh->echoOff != NULL) 2541138079Sharti nsh->echoOff = estrdup(osh->echoOff); 2542138079Sharti else 2543138079Sharti nsh->echoOff = NULL; 2544138079Sharti if (osh->echoOn != NULL) 2545138079Sharti nsh->echoOn = estrdup(osh->echoOn); 2546138079Sharti else 2547138079Sharti nsh->echoOn = NULL; 2548138079Sharti nsh->hasEchoCtl = osh->hasEchoCtl; 2549138079Sharti 2550138079Sharti if (osh->noPrint != NULL) 2551138079Sharti nsh->noPrint = estrdup(osh->noPrint); 2552138079Sharti else 2553138079Sharti nsh->noPrint = NULL; 2554138079Sharti 2555138079Sharti nsh->hasErrCtl = osh->hasErrCtl; 2556138079Sharti if (osh->errCheck == NULL) 2557138079Sharti nsh->errCheck = estrdup(""); 2558138079Sharti else 2559138079Sharti nsh->errCheck = estrdup(osh->errCheck); 2560138079Sharti if (osh->ignErr == NULL) 2561138079Sharti nsh->ignErr = estrdup("%s"); 2562138079Sharti else 2563138079Sharti nsh->ignErr = estrdup(osh->ignErr); 2564138079Sharti 2565138079Sharti if (osh->echo == NULL) 2566138079Sharti nsh->echo = estrdup(""); 2567138079Sharti else 2568138079Sharti nsh->echo = estrdup(osh->echo); 2569138079Sharti 2570138079Sharti if (osh->exit == NULL) 2571138079Sharti nsh->exit = estrdup(""); 2572138079Sharti else 2573138079Sharti nsh->exit = estrdup(osh->exit); 2574138079Sharti 2575138079Sharti return (nsh); 2576138079Sharti} 2577138079Sharti 2578144467Sharti/** 2579144467Sharti * JobFreeShell 2580144467Sharti * Free a shell structure and all associated strings. 2581138079Sharti */ 2582138079Shartistatic void 2583144483ShartiJobFreeShell(struct Shell *sh) 2584138079Sharti{ 2585138079Sharti 2586138079Sharti if (sh != NULL) { 2587138079Sharti free(sh->name); 2588138079Sharti free(sh->echoOff); 2589138079Sharti free(sh->echoOn); 2590138079Sharti free(sh->noPrint); 2591138079Sharti free(sh->errCheck); 2592138079Sharti free(sh->ignErr); 2593138079Sharti free(sh->echo); 2594138079Sharti free(sh->exit); 2595138079Sharti free(sh); 2596138079Sharti } 2597138079Sharti} 2598138079Sharti 2599146174Shartistatic void 2600136840SruShell_Init(void) 2601136840Sru{ 2602138079Sharti 2603144467Sharti if (commandShell == NULL) 2604144467Sharti commandShell = JobMatchShell(shells[DEFSHELL].name); 2605138079Sharti 2606144467Sharti if (shellPath == NULL) { 2607144467Sharti /* 2608144467Sharti * The user didn't specify a shell to use, so we are using the 2609144467Sharti * default one... Both the absolute path and the last component 2610144467Sharti * must be set. The last component is taken from the 'name' 2611144467Sharti * field of the default shell description pointed-to by 2612144467Sharti * commandShell. All default shells are located in 2613144467Sharti * PATH_DEFSHELLDIR. 2614144467Sharti */ 2615144467Sharti shellName = commandShell->name; 2616144467Sharti shellPath = str_concat(PATH_DEFSHELLDIR, shellName, 2617144467Sharti STR_ADDSLASH); 2618144467Sharti } 2619136840Sru} 2620136840Sru 2621144467Sharti/** 2622144467Sharti * Job_Init 2623137572Sphk * Initialize the process module, given a maximum number of jobs. 26241590Srgrimes * 26251590Srgrimes * Side Effects: 26261590Srgrimes * lists and counters are initialized 26271590Srgrimes */ 26281590Srgrimesvoid 2629137572SphkJob_Init(int maxproc) 26301590Srgrimes{ 2631144467Sharti GNode *begin; /* node for commands to do at the very start */ 2632144467Sharti const char *env; 2633144467Sharti struct sigaction sa; 26341590Srgrimes 2635144467Sharti fifoFd = -1; 2636144467Sharti env = getenv("MAKE_JOBS_FIFO"); 2637137606Sphk 2638144467Sharti if (env == NULL && maxproc > 1) { 2639144467Sharti /* 2640144467Sharti * We did not find the environment variable so we are the 2641144467Sharti * leader. Create the fifo, open it, write one char per 2642144467Sharti * allowed job into the pipe. 2643144467Sharti */ 2644146155Sharti fifoFd = mkfifotemp(fifoName); 2645146155Sharti if (fifoFd < 0) { 2646146155Sharti env = NULL; 2647146155Sharti } else { 2648146155Sharti fifoMaster = 1; 2649146155Sharti fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2650146155Sharti env = fifoName; 2651146155Sharti setenv("MAKE_JOBS_FIFO", env, 1); 2652146155Sharti while (maxproc-- > 0) { 2653146155Sharti write(fifoFd, "+", 1); 2654144467Sharti } 2655146155Sharti /* The master make does not get a magic token */ 2656146155Sharti jobFull = TRUE; 2657146155Sharti maxJobs = 0; 2658137606Sphk } 2659144467Sharti 2660144467Sharti } else if (env != NULL) { 2661144467Sharti /* 2662144467Sharti * We had the environment variable so we are a slave. 2663144467Sharti * Open fifo and give ourselves a magic token which represents 2664144467Sharti * the token our parent make has grabbed to start his make 2665144467Sharti * process. Otherwise the sub-makes would gobble up tokens and 2666144467Sharti * the proper number of tokens to specify to -j would depend 2667144467Sharti * on the depth of the tree and the order of execution. 2668144467Sharti */ 2669144467Sharti fifoFd = open(env, O_RDWR, 0); 2670144467Sharti if (fifoFd >= 0) { 2671144467Sharti fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2672144467Sharti maxJobs = 1; 2673144467Sharti jobFull = FALSE; 2674144467Sharti } 2675137606Sphk } 2676144467Sharti if (fifoFd <= 0) { 2677144467Sharti maxJobs = maxproc; 2678144467Sharti jobFull = FALSE; 2679144467Sharti } else { 2680137606Sphk } 2681144467Sharti nJobs = 0; 26821590Srgrimes 2683144467Sharti aborting = 0; 2684144467Sharti errors = 0; 26851590Srgrimes 2686144467Sharti lastNode = NULL; 26871590Srgrimes 2688144467Sharti if ((maxJobs == 1 && fifoFd < 0) || beVerbose == 0) { 2689144467Sharti /* 2690144467Sharti * If only one job can run at a time, there's no need for a 2691144467Sharti * banner, no is there? 2692144467Sharti */ 2693144467Sharti targFmt = ""; 2694144467Sharti } else { 2695144467Sharti targFmt = TARG_FMT; 2696144467Sharti } 2697144467Sharti 2698144467Sharti Shell_Init(); 2699144467Sharti 27001590Srgrimes /* 2701144467Sharti * Catch the four signals that POSIX specifies if they aren't ignored. 2702144467Sharti * JobCatchSignal will just set global variables and hope someone 2703144467Sharti * else is going to handle the interrupt. 27041590Srgrimes */ 2705144467Sharti sa.sa_handler = JobCatchSig; 2706144467Sharti sigemptyset(&sa.sa_mask); 2707144467Sharti sa.sa_flags = 0; 27088874Srgrimes 2709144467Sharti if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 2710144467Sharti sigaction(SIGINT, &sa, NULL); 2711144467Sharti } 2712144467Sharti if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 2713144467Sharti sigaction(SIGHUP, &sa, NULL); 2714144467Sharti } 2715144467Sharti if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 2716144467Sharti sigaction(SIGQUIT, &sa, NULL); 2717144467Sharti } 2718144467Sharti if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 2719144467Sharti sigaction(SIGTERM, &sa, NULL); 2720144467Sharti } 2721144467Sharti /* 2722144467Sharti * There are additional signals that need to be caught and passed if 2723144467Sharti * either the export system wants to be told directly of signals or if 2724144467Sharti * we're giving each job its own process group (since then it won't get 2725144467Sharti * signals from the terminal driver as we own the terminal) 2726144467Sharti */ 2727137202Sharti#if defined(USE_PGRP) 2728144467Sharti if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { 2729144467Sharti sigaction(SIGTSTP, &sa, NULL); 2730144467Sharti } 2731144467Sharti if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { 2732144467Sharti sigaction(SIGTTOU, &sa, NULL); 2733144467Sharti } 2734144467Sharti if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { 2735144467Sharti sigaction(SIGTTIN, &sa, NULL); 2736144467Sharti } 2737144467Sharti if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { 2738144467Sharti sigaction(SIGWINCH, &sa, NULL); 2739144467Sharti } 27401590Srgrimes#endif 27418874Srgrimes 2742104475Sphk#ifdef USE_KQUEUE 2743144467Sharti if ((kqfd = kqueue()) == -1) { 2744144467Sharti Punt("kqueue: %s", strerror(errno)); 2745144467Sharti } 2746104475Sphk#endif 2747104475Sphk 2748144467Sharti begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); 27491590Srgrimes 2750144467Sharti if (begin != NULL) { 2751144467Sharti JobStart(begin, JOB_SPECIAL, (Job *)NULL); 2752144467Sharti while (nJobs) { 2753144467Sharti Job_CatchOutput(0); 2754144467Sharti Job_CatchChildren(!usePipes); 2755144467Sharti } 27561590Srgrimes } 2757144467Sharti postCommands = Targ_FindNode(".END", TARG_CREATE); 27581590Srgrimes} 27591590Srgrimes 2760144467Sharti/** 2761144467Sharti * Job_Full 27621590Srgrimes * See if the job table is full. It is considered full if it is OR 27631590Srgrimes * if we are in the process of aborting OR if we have 27641590Srgrimes * reached/exceeded our local quota. This prevents any more jobs 27651590Srgrimes * from starting up. 27661590Srgrimes * 27671590Srgrimes * Results: 27681590Srgrimes * TRUE if the job table is full, FALSE otherwise 27691590Srgrimes */ 27701590SrgrimesBoolean 2771104696SjmallettJob_Full(void) 27721590Srgrimes{ 2773144467Sharti char c; 2774144467Sharti int i; 2775137606Sphk 2776144467Sharti if (aborting) 2777144467Sharti return (aborting); 2778144467Sharti if (fifoFd >= 0 && jobFull) { 2779144467Sharti i = read(fifoFd, &c, 1); 2780144467Sharti if (i > 0) { 2781144467Sharti maxJobs++; 2782144467Sharti jobFull = FALSE; 2783144467Sharti } 2784137606Sphk } 2785144467Sharti return (jobFull); 27861590Srgrimes} 27871590Srgrimes 2788144467Sharti/** 2789144467Sharti * Job_Empty 27901590Srgrimes * See if the job table is empty. Because the local concurrency may 27911590Srgrimes * be set to 0, it is possible for the job table to become empty, 27921590Srgrimes * while the list of stoppedJobs remains non-empty. In such a case, 27931590Srgrimes * we want to restart as many jobs as we can. 27941590Srgrimes * 27951590Srgrimes * Results: 27961590Srgrimes * TRUE if it is. FALSE if it ain't. 27971590Srgrimes */ 27981590SrgrimesBoolean 2799104696SjmallettJob_Empty(void) 28001590Srgrimes{ 2801144467Sharti if (nJobs == 0) { 2802144494Sharti if (!TAILQ_EMPTY(&stoppedJobs) && !aborting) { 2803144467Sharti /* 2804144467Sharti * The job table is obviously not full if it has no 2805144467Sharti * jobs in it...Try and restart the stopped jobs. 2806144467Sharti */ 2807144467Sharti jobFull = FALSE; 2808144467Sharti JobRestartJobs(); 2809144467Sharti return (FALSE); 2810144467Sharti } else { 2811144467Sharti return (TRUE); 2812144467Sharti } 28131590Srgrimes } else { 2814144467Sharti return (FALSE); 28151590Srgrimes } 28161590Srgrimes} 28171590Srgrimes 2818144467Sharti/** 2819144467Sharti * JobMatchShell 28201590Srgrimes * Find a matching shell in 'shells' given its final component. 28211590Srgrimes * 28221590Srgrimes * Results: 2823138334Sharti * A pointer to a freshly allocated Shell structure with a copy 2824138228Sharti * of the static structure or NULL if no shell with the given name 2825138228Sharti * is found. 28261590Srgrimes */ 2827144483Shartistatic struct Shell * 2828138228ShartiJobMatchShell(const char *name) 28291590Srgrimes{ 2830144467Sharti const struct CShell *sh; /* Pointer into shells table */ 2831144483Sharti struct Shell *nsh; 28321590Srgrimes 2833144467Sharti for (sh = shells; sh < shells + sizeof(shells)/sizeof(shells[0]); sh++) 2834144467Sharti if (strcmp(sh->name, name) == 0) 2835144467Sharti break; 28361590Srgrimes 2837144467Sharti if (sh == shells + sizeof(shells)/sizeof(shells[0])) 2838144467Sharti return (NULL); 2839138228Sharti 2840144467Sharti /* make a copy */ 2841144467Sharti nsh = emalloc(sizeof(*nsh)); 2842138228Sharti 2843144467Sharti nsh->name = estrdup(sh->name); 2844144467Sharti nsh->echoOff = estrdup(sh->echoOff); 2845144467Sharti nsh->echoOn = estrdup(sh->echoOn); 2846144467Sharti nsh->hasEchoCtl = sh->hasEchoCtl; 2847144467Sharti nsh->noPrint = estrdup(sh->noPrint); 2848144467Sharti nsh->hasErrCtl = sh->hasErrCtl; 2849144467Sharti nsh->errCheck = estrdup(sh->errCheck); 2850144467Sharti nsh->ignErr = estrdup(sh->ignErr); 2851144467Sharti nsh->echo = estrdup(sh->echo); 2852144467Sharti nsh->exit = estrdup(sh->exit); 2853138228Sharti 2854144467Sharti return (nsh); 28551590Srgrimes} 28561590Srgrimes 2857144467Sharti/** 2858144467Sharti * Job_ParseShell 28591590Srgrimes * Parse a shell specification and set up commandShell, shellPath 28601590Srgrimes * and shellName appropriately. 28611590Srgrimes * 28621590Srgrimes * Results: 2863146338Sharti * TRUE if the specification was correct. FALSE otherwise. 28641590Srgrimes * 28651590Srgrimes * Side Effects: 28661590Srgrimes * commandShell points to a Shell structure (either predefined or 28671590Srgrimes * created from the shell spec), shellPath is the full path of the 28681590Srgrimes * shell described by commandShell, while shellName is just the 28691590Srgrimes * final component of shellPath. 28701590Srgrimes * 28711590Srgrimes * Notes: 28721590Srgrimes * A shell specification consists of a .SHELL target, with dependency 28731590Srgrimes * operator, followed by a series of blank-separated words. Double 28741590Srgrimes * quotes can be used to use blanks in words. A backslash escapes 28751590Srgrimes * anything (most notably a double-quote and a space) and 28761590Srgrimes * provides the functionality it does in C. Each word consists of 28771590Srgrimes * keyword and value separated by an equal sign. There should be no 28781590Srgrimes * unnecessary spaces in the word. The keywords are as follows: 2879146061Sharti * name Name of shell. 2880146061Sharti * path Location of shell. Overrides "name" if given 2881146061Sharti * quiet Command to turn off echoing. 2882146061Sharti * echo Command to turn echoing on 28831590Srgrimes * filter Result of turning off echoing that shouldn't be 2884146061Sharti * printed. 28851590Srgrimes * echoFlag Flag to turn echoing on at the start 28861590Srgrimes * errFlag Flag to turn error checking on at the start 28871590Srgrimes * hasErrCtl True if shell has error checking control 2888146061Sharti * check Command to turn on error checking if hasErrCtl 2889146061Sharti * is TRUE or template of command to echo a command 2890146061Sharti * for which error checking is off if hasErrCtl is 2891146061Sharti * FALSE. 28921590Srgrimes * ignore Command to turn off error checking if hasErrCtl 2893146061Sharti * is TRUE or template of command to execute a 2894146061Sharti * command so as to ignore any errors it returns if 2895146061Sharti * hasErrCtl is FALSE. 28961590Srgrimes */ 2897146338ShartiBoolean 2898146345ShartiJob_ParseShell(const char line[]) 28991590Srgrimes{ 2900146345Sharti ArgArray aa; 2901146345Sharti char **argv; 2902146345Sharti int argc; 2903146345Sharti char *path; 2904146345Sharti char *eq; 2905146345Sharti Boolean fullSpec = FALSE; 2906144483Sharti struct Shell newShell; 2907144483Sharti struct Shell *sh; 29081590Srgrimes 2909144467Sharti memset(&newShell, 0, sizeof(newShell)); 2910144741Sharti path = NULL; 29118874Srgrimes 29121590Srgrimes /* 2913146345Sharti * Parse the specification by keyword but skip the first word 29141590Srgrimes */ 2915146345Sharti brk_string(&aa, line, TRUE); 2916144741Sharti 2917146345Sharti for (argc = aa.argc - 1, argv = aa.argv + 1; argc != 0; 2918146345Sharti argc--, argv++) { 2919144741Sharti /* 2920144741Sharti * Split keyword and value 2921144741Sharti */ 2922144741Sharti if ((eq = strchr(*argv, '=')) == NULL) { 2923144741Sharti Parse_Error(PARSE_FATAL, "missing '=' in shell " 2924144741Sharti "specification keyword '%s'", *argv); 2925146345Sharti ArgArray_Done(&aa); 2926146338Sharti return (FALSE); 2927144741Sharti } 2928144741Sharti *eq++ = '\0'; 2929144741Sharti 2930144741Sharti if (strcmp(*argv, "path") == 0) { 2931144741Sharti path = eq; 2932144741Sharti } else if (strcmp(*argv, "name") == 0) { 2933144741Sharti newShell.name = eq; 2934144741Sharti } else if (strcmp(*argv, "quiet") == 0) { 2935144741Sharti newShell.echoOff = eq; 2936144741Sharti fullSpec = TRUE; 2937144741Sharti } else if (strcmp(*argv, "echo") == 0) { 2938144741Sharti newShell.echoOn = eq; 2939144741Sharti fullSpec = TRUE; 2940144741Sharti } else if (strcmp(*argv, "filter") == 0) { 2941144741Sharti newShell.noPrint = eq; 2942144741Sharti fullSpec = TRUE; 2943144741Sharti } else if (strcmp(*argv, "echoFlag") == 0) { 2944144741Sharti newShell.echo = eq; 2945144741Sharti fullSpec = TRUE; 2946144741Sharti } else if (strcmp(*argv, "errFlag") == 0) { 2947144741Sharti newShell.exit = eq; 2948144741Sharti fullSpec = TRUE; 2949144741Sharti } else if (strcmp(*argv, "hasErrCtl") == 0) { 2950144741Sharti newShell.hasErrCtl = (*eq == 'Y' || *eq == 'y' || 2951144741Sharti *eq == 'T' || *eq == 't'); 2952144741Sharti fullSpec = TRUE; 2953144741Sharti } else if (strcmp(*argv, "check") == 0) { 2954144741Sharti newShell.errCheck = eq; 2955144741Sharti fullSpec = TRUE; 2956144741Sharti } else if (strcmp(*argv, "ignore") == 0) { 2957144741Sharti newShell.ignErr = eq; 2958144741Sharti fullSpec = TRUE; 2959144467Sharti } else { 2960144741Sharti Parse_Error(PARSE_FATAL, "unknown keyword in shell " 2961144741Sharti "specification '%s'", *argv); 2962146345Sharti ArgArray_Done(&aa); 2963146338Sharti return (FALSE); 2964144467Sharti } 29651590Srgrimes } 2966138079Sharti 29671590Srgrimes /* 2968144467Sharti * Some checks (could be more) 29691590Srgrimes */ 2970144467Sharti if (fullSpec) { 2971144467Sharti if ((newShell.echoOn != NULL) ^ (newShell.echoOff != NULL)) 2972144467Sharti Parse_Error(PARSE_FATAL, "Shell must have either both " 2973144467Sharti "echoOff and echoOn or none of them"); 2974144467Sharti 2975144467Sharti if (newShell.echoOn != NULL && newShell.echoOff) 2976144467Sharti newShell.hasEchoCtl = TRUE; 29771590Srgrimes } 2978138079Sharti 2979144467Sharti if (path == NULL) { 2980144467Sharti /* 2981144467Sharti * If no path was given, the user wants one of the pre-defined 2982144467Sharti * shells, yes? So we find the one s/he wants with the help of 2983144467Sharti * JobMatchShell and set things up the right way. shellPath 2984144467Sharti * will be set up by Job_Init. 2985144467Sharti */ 2986144467Sharti if (newShell.name == NULL) { 2987144467Sharti Parse_Error(PARSE_FATAL, 2988144467Sharti "Neither path nor name specified"); 2989146345Sharti ArgArray_Done(&aa); 2990146338Sharti return (FALSE); 2991144467Sharti } 2992144467Sharti if ((sh = JobMatchShell(newShell.name)) == NULL) { 2993144467Sharti Parse_Error(PARSE_FATAL, "%s: no matching shell", 2994144467Sharti newShell.name); 2995146345Sharti ArgArray_Done(&aa); 2996146338Sharti return (FALSE); 2997144467Sharti } 2998144467Sharti 29991590Srgrimes } else { 3000144467Sharti /* 3001144467Sharti * The user provided a path. If s/he gave nothing else 3002144467Sharti * (fullSpec is FALSE), try and find a matching shell in the 3003144467Sharti * ones we know of. Else we just take the specification at its 3004144467Sharti * word and copy it to a new location. In either case, we need 3005144467Sharti * to record the path the user gave for the shell. 3006144467Sharti */ 3007146174Sharti path = estrdup(path); 3008144467Sharti if (newShell.name == NULL) { 3009144467Sharti /* get the base name as the name */ 3010146174Sharti if ((newShell.name = strrchr(path, '/')) == NULL) { 3011146174Sharti newShell.name = path; 3012144467Sharti } else { 3013146174Sharti newShell.name += 1; 3014144467Sharti } 3015144467Sharti } 3016144467Sharti 3017144467Sharti if (!fullSpec) { 3018144467Sharti if ((sh = JobMatchShell(newShell.name)) == NULL) { 3019144467Sharti Parse_Error(PARSE_FATAL, 3020144467Sharti "%s: no matching shell", newShell.name); 3021146174Sharti free(path); 3022146345Sharti ArgArray_Done(&aa); 3023146338Sharti return (FALSE); 3024144467Sharti } 3025144467Sharti } else { 3026144467Sharti sh = JobCopyShell(&newShell); 3027144467Sharti } 3028146174Sharti free(shellPath); 3029146174Sharti shellPath = path; 30301590Srgrimes } 30311590Srgrimes 3032144467Sharti /* set the new shell */ 3033144467Sharti JobFreeShell(commandShell); 3034144467Sharti commandShell = sh; 30358874Srgrimes 3036144467Sharti shellName = commandShell->name; 30378874Srgrimes 3038146345Sharti ArgArray_Done(&aa); 3039146338Sharti return (TRUE); 30401590Srgrimes} 30411590Srgrimes 3042144467Sharti/** 3043144467Sharti * JobInterrupt 30441590Srgrimes * Handle the receipt of an interrupt. 30451590Srgrimes * 30461590Srgrimes * Side Effects: 30471590Srgrimes * All children are killed. Another job will be started if the 30481590Srgrimes * .INTERRUPT target was given. 30491590Srgrimes */ 30501590Srgrimesstatic void 3051104696SjmallettJobInterrupt(int runINTERRUPT, int signo) 30521590Srgrimes{ 3053144467Sharti Job *job; /* job descriptor in that element */ 3054144467Sharti GNode *interrupt; /* the node describing the .INTERRUPT target */ 30558874Srgrimes 3056144467Sharti aborting = ABORT_INTERRUPT; 30571590Srgrimes 3058144494Sharti TAILQ_FOREACH(job, &jobs, link) { 3059144467Sharti if (!Targ_Precious(job->node)) { 3060144467Sharti char *file = (job->node->path == NULL ? 3061144467Sharti job->node->name : job->node->path); 3062144467Sharti 3063144467Sharti if (!noExecute && eunlink(file) != -1) { 3064144467Sharti Error("*** %s removed", file); 3065144467Sharti } 3066144467Sharti } 3067144467Sharti if (job->pid) { 3068144467Sharti DEBUGF(JOB, ("JobInterrupt passing signal to child " 3069144665Sharti "%jd.\n", (intmax_t)job->pid)); 3070144467Sharti KILL(job->pid, signo); 3071144467Sharti } 30721590Srgrimes } 307318730Ssteve 3074144467Sharti if (runINTERRUPT && !touchFlag) { 3075144467Sharti /* 3076144467Sharti * clear the interrupted flag because we would get an 3077144467Sharti * infinite loop otherwise. 3078144467Sharti */ 3079144467Sharti interrupted = 0; 3080137605Sharti 3081144467Sharti interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 3082144467Sharti if (interrupt != NULL) { 3083144467Sharti ignoreErrors = FALSE; 30841590Srgrimes 3085144467Sharti JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL); 3086144467Sharti while (nJobs) { 3087144467Sharti Job_CatchOutput(0); 3088144467Sharti Job_CatchChildren(!usePipes); 3089144467Sharti } 3090144467Sharti } 30911590Srgrimes } 30921590Srgrimes} 30931590Srgrimes 3094144467Sharti/** 3095144467Sharti * Job_Finish 30961590Srgrimes * Do final processing such as the running of the commands 30978874Srgrimes * attached to the .END target. 30981590Srgrimes * 30991590Srgrimes * Results: 31001590Srgrimes * Number of errors reported. 31011590Srgrimes */ 31021590Srgrimesint 3103104696SjmallettJob_Finish(void) 31041590Srgrimes{ 3105138232Sharti 3106144467Sharti if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { 3107144467Sharti if (errors) { 3108144467Sharti Error("Errors reported so .END ignored"); 3109144467Sharti } else { 3110144467Sharti JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); 31111590Srgrimes 3112144467Sharti while (nJobs) { 3113144467Sharti Job_CatchOutput(0); 3114144467Sharti Job_CatchChildren(!usePipes); 3115144467Sharti } 3116144467Sharti } 31171590Srgrimes } 3118144467Sharti if (fifoFd >= 0) { 3119144467Sharti close(fifoFd); 3120144467Sharti fifoFd = -1; 3121144467Sharti if (fifoMaster) 3122144467Sharti unlink(fifoName); 3123144467Sharti } 3124144467Sharti return (errors); 31251590Srgrimes} 31261590Srgrimes 3127144467Sharti/** 3128144467Sharti * Job_Wait 31291590Srgrimes * Waits for all running jobs to finish and returns. Sets 'aborting' 31301590Srgrimes * to ABORT_WAIT to prevent other jobs from starting. 31311590Srgrimes * 31321590Srgrimes * Side Effects: 31331590Srgrimes * Currently running jobs finish. 31341590Srgrimes */ 31351590Srgrimesvoid 3136104696SjmallettJob_Wait(void) 31371590Srgrimes{ 3138138232Sharti 3139144467Sharti aborting = ABORT_WAIT; 3140144467Sharti while (nJobs != 0) { 3141144467Sharti Job_CatchOutput(0); 3142144467Sharti Job_CatchChildren(!usePipes); 3143144467Sharti } 3144144467Sharti aborting = 0; 31451590Srgrimes} 31461590Srgrimes 3147144467Sharti/** 3148144467Sharti * Job_AbortAll 31491590Srgrimes * Abort all currently running jobs without handling output or anything. 31501590Srgrimes * This function is to be called only in the event of a major 31511590Srgrimes * error. Most definitely NOT to be called from JobInterrupt. 31521590Srgrimes * 31531590Srgrimes * Side Effects: 31541590Srgrimes * All children are killed, not just the firstborn 31551590Srgrimes */ 31561590Srgrimesvoid 3157104696SjmallettJob_AbortAll(void) 31581590Srgrimes{ 3159144467Sharti Job *job; /* the job descriptor in that element */ 3160144467Sharti int foo; 31618874Srgrimes 3162144467Sharti aborting = ABORT_ERROR; 31638874Srgrimes 3164144467Sharti if (nJobs) { 3165144494Sharti TAILQ_FOREACH(job, &jobs, link) { 3166144467Sharti /* 3167144467Sharti * kill the child process with increasingly drastic 3168144467Sharti * signals to make darn sure it's dead. 3169144467Sharti */ 3170144467Sharti KILL(job->pid, SIGINT); 3171144467Sharti KILL(job->pid, SIGKILL); 3172144467Sharti } 31731590Srgrimes } 31748874Srgrimes 3175144467Sharti /* 3176144467Sharti * Catch as many children as want to report in at first, then give up 3177144467Sharti */ 3178144467Sharti while (waitpid((pid_t)-1, &foo, WNOHANG) > 0) 3179144665Sharti ; 31801590Srgrimes} 318118730Ssteve 3182144467Sharti/** 3183144467Sharti * JobRestartJobs 318418730Ssteve * Tries to restart stopped jobs if there are slots available. 318518730Ssteve * Note that this tries to restart them regardless of pending errors. 318618730Ssteve * It's not good to leave stopped jobs lying around! 318718730Ssteve * 318818730Ssteve * Side Effects: 318918730Ssteve * Resumes(and possibly migrates) jobs. 319018730Ssteve */ 319118730Sstevestatic void 3192104696SjmallettJobRestartJobs(void) 319318730Ssteve{ 3194144494Sharti Job *job; 3195144494Sharti 3196144494Sharti while (!jobFull && (job = TAILQ_FIRST(&stoppedJobs)) != NULL) { 3197144467Sharti DEBUGF(JOB, ("Job queue is not full. " 3198144467Sharti "Restarting a stopped job.\n")); 3199144494Sharti TAILQ_REMOVE(&stoppedJobs, job, link); 3200144494Sharti JobRestart(job); 3201144467Sharti } 320218730Ssteve} 3203146054Sharti 3204146054Sharti/** 3205146054Sharti * Cmd_Exec 3206146054Sharti * Execute the command in cmd, and return the output of that command 3207146054Sharti * in a string. 3208146054Sharti * 3209146054Sharti * Results: 3210146054Sharti * A string containing the output of the command, or the empty string 3211146054Sharti * If error is not NULL, it contains the reason for the command failure 3212146129Sharti * Any output sent to stderr in the child process is passed to stderr, 3213146129Sharti * and not captured in the string. 3214146054Sharti * 3215146054Sharti * Side Effects: 3216146054Sharti * The string must be freed by the caller. 3217146054Sharti */ 3218146054ShartiBuffer * 3219146054ShartiCmd_Exec(const char *cmd, const char **error) 3220146054Sharti{ 3221146054Sharti int fds[2]; /* Pipe streams */ 3222146054Sharti int status; /* command exit status */ 3223146054Sharti Buffer *buf; /* buffer to store the result */ 3224146054Sharti ssize_t rcnt; 3225146129Sharti ProcStuff ps; 3226146054Sharti 3227146054Sharti *error = NULL; 3228146054Sharti buf = Buf_Init(0); 3229146054Sharti 3230146054Sharti if (shellPath == NULL) 3231146054Sharti Shell_Init(); 3232146054Sharti /* 3233146054Sharti * Open a pipe for fetching its output 3234146054Sharti */ 3235146054Sharti if (pipe(fds) == -1) { 3236146054Sharti *error = "Couldn't create pipe for \"%s\""; 3237146054Sharti return (buf); 3238146054Sharti } 3239146054Sharti 3240146129Sharti /* Set close-on-exec on read side of pipe. */ 3241146129Sharti fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC); 3242146129Sharti 3243146129Sharti ps.in = STDIN_FILENO; 3244146129Sharti ps.out = fds[1]; 3245146129Sharti ps.err = STDERR_FILENO; 3246146129Sharti 3247146129Sharti ps.merge_errors = 0; 3248146129Sharti ps.pgroup = 0; 3249146129Sharti ps.searchpath = 0; 3250146129Sharti 3251146129Sharti /* Set up arguments for shell */ 3252146129Sharti ps.argv = emalloc(4 * sizeof(char *)); 3253146129Sharti ps.argv[0] = strdup(shellName); 3254146129Sharti ps.argv[1] = strdup("-c"); 3255146129Sharti ps.argv[2] = strdup(cmd); 3256146129Sharti ps.argv[3] = NULL; 3257146156Sharti ps.argv_free = 1; 3258146129Sharti 3259146054Sharti /* 3260146129Sharti * Fork. Warning since we are doing vfork() instead of fork(), 3261146129Sharti * do not allocate memory in the child process! 3262146054Sharti */ 3263146130Sharti if ((ps.child_pid = vfork()) == -1) { 3264146058Sharti *error = "Couldn't exec \"%s\""; 3265146058Sharti return (buf); 3266146058Sharti 3267146130Sharti } else if (ps.child_pid == 0) { 3268146129Sharti /* 3269146129Sharti * Child 3270146129Sharti */ 3271146129Sharti ProcExec(&ps); 3272146129Sharti /* NOTREACHED */ 3273146129Sharti } 3274146054Sharti 3275146129Sharti free(ps.argv[2]); 3276146129Sharti free(ps.argv[1]); 3277146129Sharti free(ps.argv[0]); 3278146129Sharti free(ps.argv); 3279146054Sharti 3280146129Sharti close(fds[1]); /* No need for the writing half of the pipe. */ 3281146054Sharti 3282146058Sharti do { 3283146058Sharti char result[BUFSIZ]; 3284146054Sharti 3285146058Sharti rcnt = read(fds[0], result, sizeof(result)); 3286146058Sharti if (rcnt != -1) 3287146058Sharti Buf_AddBytes(buf, (size_t)rcnt, (Byte *)result); 3288146058Sharti } while (rcnt > 0 || (rcnt == -1 && errno == EINTR)); 3289146054Sharti 3290146058Sharti if (rcnt == -1) 3291146058Sharti *error = "Error reading shell's output for \"%s\""; 3292146054Sharti 3293146058Sharti /* 3294146058Sharti * Close the input side of the pipe. 3295146058Sharti */ 3296146058Sharti close(fds[0]); 3297146054Sharti 3298146130Sharti status = ProcWait(&ps); 3299146054Sharti 3300146058Sharti if (status) 3301146058Sharti *error = "\"%s\" returned non-zero status"; 3302146054Sharti 3303146058Sharti Buf_StripNewlines(buf); 3304146054Sharti 3305146054Sharti return (buf); 3306146054Sharti} 3307146054Sharti 3308146056Sharti 3309146056Sharti/* 3310146056Sharti * Interrupt handler - set flag and defer handling to the main code 3311146056Sharti */ 3312146056Shartistatic void 3313146056ShartiCompatCatchSig(int signo) 3314146056Sharti{ 3315146056Sharti 3316146056Sharti interrupted = signo; 3317146056Sharti} 3318146056Sharti 3319146056Sharti/*- 3320146056Sharti *----------------------------------------------------------------------- 3321146056Sharti * CompatInterrupt -- 3322146056Sharti * Interrupt the creation of the current target and remove it if 3323146056Sharti * it ain't precious. 3324146056Sharti * 3325146056Sharti * Results: 3326146056Sharti * None. 3327146056Sharti * 3328146056Sharti * Side Effects: 3329146056Sharti * The target is removed and the process exits. If .INTERRUPT exists, 3330146056Sharti * its commands are run first WITH INTERRUPTS IGNORED.. 3331146056Sharti * 3332146056Sharti *----------------------------------------------------------------------- 3333146056Sharti */ 3334146056Shartistatic void 3335146056ShartiCompatInterrupt(int signo) 3336146056Sharti{ 3337146056Sharti GNode *gn; 3338146056Sharti sigset_t nmask, omask; 3339146056Sharti LstNode *ln; 3340146056Sharti 3341146056Sharti sigemptyset(&nmask); 3342146056Sharti sigaddset(&nmask, SIGINT); 3343146056Sharti sigaddset(&nmask, SIGTERM); 3344146056Sharti sigaddset(&nmask, SIGHUP); 3345146056Sharti sigaddset(&nmask, SIGQUIT); 3346146056Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 3347146056Sharti 3348146056Sharti /* prevent recursion in evaluation of .INTERRUPT */ 3349146056Sharti interrupted = 0; 3350146056Sharti 3351146056Sharti if (curTarg != NULL && !Targ_Precious(curTarg)) { 3352146056Sharti char *p1; 3353146061Sharti char *file = Var_Value(TARGET, curTarg, &p1); 3354146056Sharti 3355146056Sharti if (!noExecute && eunlink(file) != -1) { 3356146056Sharti printf("*** %s removed\n", file); 3357146056Sharti } 3358146056Sharti free(p1); 3359146056Sharti } 3360146056Sharti 3361146056Sharti /* 3362146056Sharti * Run .INTERRUPT only if hit with interrupt signal 3363146056Sharti */ 3364146056Sharti if (signo == SIGINT) { 3365146056Sharti gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 3366146056Sharti if (gn != NULL) { 3367146056Sharti LST_FOREACH(ln, &gn->commands) { 3368146056Sharti if (Compat_RunCommand(Lst_Datum(ln), gn)) 3369146056Sharti break; 3370146056Sharti } 3371146056Sharti } 3372146056Sharti } 3373146056Sharti 3374146056Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 3375146056Sharti 3376146056Sharti if (signo == SIGQUIT) 3377146056Sharti exit(signo); 3378146056Sharti signal(signo, SIG_DFL); 3379146056Sharti kill(getpid(), signo); 3380146056Sharti} 3381146056Sharti 3382146129Sharti/** 3383146129Sharti * shellneed 3384146056Sharti * 3385146056Sharti * Results: 3386146129Sharti * Returns NULL if a specified line must be executed by the shell, 3387146129Sharti * and an argument vector if it can be run via execvp(). 3388146056Sharti * 3389146056Sharti * Side Effects: 3390146056Sharti * Uses brk_string so destroys the contents of argv. 3391146056Sharti */ 3392146129Shartistatic char ** 3393146345Shartishellneed(ArgArray *aa, char *cmd) 3394146056Sharti{ 3395146056Sharti const char **p; 3396146056Sharti 3397146129Sharti if (strpbrk(cmd, sh_meta) != NULL) 3398146129Sharti return (NULL); 3399146129Sharti 3400146147Sharti /* 3401146147Sharti * Break the command into words to form an argument 3402146345Sharti * vector we can execute. 3403146147Sharti */ 3404146345Sharti brk_string(aa, cmd, TRUE); 3405146345Sharti for (p = sh_builtin; *p != 0; p++) { 3406146345Sharti if (strcmp(aa->argv[1], *p) == 0) { 3407146345Sharti ArgArray_Done(aa); 3408146129Sharti return (NULL); 3409146345Sharti } 3410146345Sharti } 3411146345Sharti return (aa->argv + 1); 3412146056Sharti} 3413146056Sharti 3414146056Sharti/*- 3415146056Sharti *----------------------------------------------------------------------- 3416146056Sharti * Compat_RunCommand -- 3417146056Sharti * Execute the next command for a target. If the command returns an 3418146056Sharti * error, the node's made field is set to ERROR and creation stops. 3419146056Sharti * The node from which the command came is also given. 3420146056Sharti * 3421146056Sharti * Results: 3422146056Sharti * 0 if the command succeeded, 1 if an error occurred. 3423146056Sharti * 3424146056Sharti * Side Effects: 3425146056Sharti * The node's 'made' field may be set to ERROR. 3426146056Sharti * 3427146056Sharti *----------------------------------------------------------------------- 3428146056Sharti */ 3429146142Shartistatic int 3430146056ShartiCompat_RunCommand(char *cmd, GNode *gn) 3431146056Sharti{ 3432146345Sharti ArgArray aa; 3433146345Sharti char *cmdStart; /* Start of expanded command */ 3434146345Sharti Boolean silent; /* Don't print command */ 3435146345Sharti Boolean doit; /* Execute even in -n */ 3436146345Sharti Boolean errCheck; /* Check errors */ 3437146345Sharti int reason; /* Reason for child's death */ 3438146345Sharti int status; /* Description of child's death */ 3439146345Sharti LstNode *cmdNode; /* Node where current cmd is located */ 3440146345Sharti char **av; /* Argument vector for thing to exec */ 3441146129Sharti ProcStuff ps; 3442146056Sharti 3443146056Sharti silent = gn->type & OP_SILENT; 3444146056Sharti errCheck = !(gn->type & OP_IGNORE); 3445146056Sharti doit = FALSE; 3446146056Sharti 3447146056Sharti cmdNode = Lst_Member(&gn->commands, cmd); 3448146056Sharti cmdStart = Buf_Peel(Var_Subst(cmd, gn, FALSE)); 3449146056Sharti 3450146056Sharti /* 3451146056Sharti * brk_string will return an argv with a NULL in av[0], thus causing 3452146129Sharti * execvp() to choke and die horribly. Besides, how can we execute a 3453146129Sharti * null command? In any case, we warn the user that the command 3454146129Sharti * expanded to nothing (is this the right thing to do?). 3455146056Sharti */ 3456146056Sharti if (*cmdStart == '\0') { 3457146056Sharti free(cmdStart); 3458146056Sharti Error("%s expands to empty string", cmd); 3459146056Sharti return (0); 3460146056Sharti } else { 3461146056Sharti cmd = cmdStart; 3462146056Sharti } 3463146056Sharti Lst_Replace(cmdNode, cmdStart); 3464146056Sharti 3465146056Sharti if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { 3466146056Sharti Lst_AtEnd(&ENDNode->commands, cmdStart); 3467146056Sharti return (0); 3468146056Sharti } else if (strcmp(cmdStart, "...") == 0) { 3469146056Sharti gn->type |= OP_SAVE_CMDS; 3470146056Sharti return (0); 3471146056Sharti } 3472146056Sharti 3473146056Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 3474146056Sharti switch (*cmd) { 3475146056Sharti 3476146056Sharti case '@': 3477146056Sharti silent = DEBUG(LOUD) ? FALSE : TRUE; 3478146056Sharti break; 3479146056Sharti 3480146056Sharti case '-': 3481146056Sharti errCheck = FALSE; 3482146056Sharti break; 3483146056Sharti 3484146129Sharti case '+': 3485146056Sharti doit = TRUE; 3486146056Sharti break; 3487146056Sharti } 3488146056Sharti cmd++; 3489146056Sharti } 3490146056Sharti 3491146056Sharti while (isspace((unsigned char)*cmd)) 3492146056Sharti cmd++; 3493146056Sharti 3494146056Sharti /* 3495146056Sharti * Print the command before echoing if we're not supposed to be quiet 3496146056Sharti * for this one. We also print the command if -n given, but not if '+'. 3497146056Sharti */ 3498146056Sharti if (!silent || (noExecute && !doit)) { 3499146056Sharti printf("%s\n", cmd); 3500146056Sharti fflush(stdout); 3501146056Sharti } 3502146056Sharti 3503146056Sharti /* 3504146056Sharti * If we're not supposed to execute any commands, this is as far as 3505146056Sharti * we go... 3506146056Sharti */ 3507146056Sharti if (!doit && noExecute) { 3508146056Sharti return (0); 3509146056Sharti } 3510146056Sharti 3511146129Sharti ps.in = STDIN_FILENO; 3512146129Sharti ps.out = STDOUT_FILENO; 3513146129Sharti ps.err = STDERR_FILENO; 3514146056Sharti 3515146129Sharti ps.merge_errors = 0; 3516146129Sharti ps.pgroup = 0; 3517146129Sharti ps.searchpath = 1; 3518146056Sharti 3519146345Sharti if ((av = shellneed(&aa, cmd)) == NULL) { 3520146056Sharti /* 3521146129Sharti * Shell meta character or shell builtin found - pass 3522146129Sharti * command to shell. We give the shell the -e flag as 3523146129Sharti * well as -c if it is supposed to exit when it hits an error. 3524146056Sharti */ 3525146129Sharti ps.argv = emalloc(4 * sizeof(char *)); 3526146174Sharti ps.argv[0] = strdup(shellPath); 3527146129Sharti ps.argv[1] = strdup(errCheck ? "-ec" : "-c"); 3528146129Sharti ps.argv[2] = strdup(cmd); 3529146129Sharti ps.argv[3] = NULL; 3530146156Sharti ps.argv_free = 1; 3531146056Sharti } else { 3532146129Sharti ps.argv = av; 3533146156Sharti ps.argv_free = 0; 3534146056Sharti } 3535146156Sharti ps.errCheck = errCheck; 3536146056Sharti 3537146056Sharti /* 3538146129Sharti * Warning since we are doing vfork() instead of fork(), 3539146129Sharti * do not allocate memory in the child process! 3540146056Sharti */ 3541146130Sharti if ((ps.child_pid = vfork()) == -1) { 3542146056Sharti Fatal("Could not fork"); 3543146058Sharti 3544146130Sharti } else if (ps.child_pid == 0) { 3545146129Sharti /* 3546146129Sharti * Child 3547146129Sharti */ 3548146129Sharti ProcExec(&ps); 3549146129Sharti /* NOTREACHED */ 3550146129Sharti 3551146131Sharti } else { 3552146156Sharti if (ps.argv_free) { 3553146131Sharti free(ps.argv[2]); 3554146131Sharti free(ps.argv[1]); 3555146131Sharti free(ps.argv[0]); 3556146131Sharti free(ps.argv); 3557146345Sharti } else { 3558146345Sharti ArgArray_Done(&aa); 3559146131Sharti } 3560146129Sharti 3561146131Sharti /* 3562146131Sharti * we need to print out the command associated with this 3563146131Sharti * Gnode in Targ_PrintCmd from Targ_PrintGraph when debugging 3564146131Sharti * at level g2, in main(), Fatal() and DieHorribly(), 3565146131Sharti * therefore do not free it when debugging. 3566146131Sharti */ 3567146131Sharti if (!DEBUG(GRAPH2)) { 3568146131Sharti free(cmdStart); 3569146131Sharti } 3570146129Sharti 3571146131Sharti /* 3572146131Sharti * The child is off and running. Now all we can do is wait... 3573146131Sharti */ 3574146131Sharti reason = ProcWait(&ps); 3575146132Sharti 3576146056Sharti if (interrupted) 3577146056Sharti CompatInterrupt(interrupted); 3578146131Sharti 3579146132Sharti /* 3580146132Sharti * Decode and report the reason child exited, then 3581146132Sharti * indicate how we handled it. 3582146132Sharti */ 3583146131Sharti if (WIFEXITED(reason)) { 3584146131Sharti status = WEXITSTATUS(reason); 3585146131Sharti if (status == 0) { 3586146131Sharti return (0); 3587146131Sharti } else { 3588146131Sharti printf("*** Error code %d", status); 3589146131Sharti } 3590146131Sharti } else if (WIFSTOPPED(reason)) { 3591146131Sharti status = WSTOPSIG(reason); 3592146131Sharti } else { 3593146131Sharti status = WTERMSIG(reason); 3594146131Sharti printf("*** Signal %d", status); 3595146131Sharti } 3596146131Sharti 3597146156Sharti if (ps.errCheck) { 3598146131Sharti gn->made = ERROR; 3599146131Sharti if (keepgoing) { 3600146131Sharti /* 3601146131Sharti * Abort the current 3602146131Sharti * target, but let 3603146131Sharti * others continue. 3604146131Sharti */ 3605146131Sharti printf(" (continuing)\n"); 3606146056Sharti } 3607146131Sharti return (status); 3608146056Sharti } else { 3609146131Sharti /* 3610146131Sharti * Continue executing 3611146131Sharti * commands for this target. 3612146131Sharti * If we return 0, this will 3613146131Sharti * happen... 3614146131Sharti */ 3615146131Sharti printf(" (ignored)\n"); 3616146131Sharti return (0); 3617146056Sharti } 3618146056Sharti } 3619146056Sharti} 3620146056Sharti 3621146056Sharti/*- 3622146056Sharti *----------------------------------------------------------------------- 3623146056Sharti * CompatMake -- 3624146056Sharti * Make a target, given the parent, to abort if necessary. 3625146056Sharti * 3626146056Sharti * Side Effects: 3627146056Sharti * If an error is detected and not being ignored, the process exits. 3628146056Sharti * 3629146056Sharti *----------------------------------------------------------------------- 3630146056Sharti */ 3631146056Shartistatic int 3632146056ShartiCompatMake(GNode *gn, GNode *pgn) 3633146056Sharti{ 3634146056Sharti LstNode *ln; 3635146056Sharti 3636146056Sharti if (gn->type & OP_USE) { 3637146056Sharti Make_HandleUse(gn, pgn); 3638146056Sharti 3639146056Sharti } else if (gn->made == UNMADE) { 3640146056Sharti /* 3641146056Sharti * First mark ourselves to be made, then apply whatever 3642146056Sharti * transformations the suffix module thinks are necessary. 3643146056Sharti * Once that's done, we can descend and make all our children. 3644146056Sharti * If any of them has an error but the -k flag was given, our 3645146056Sharti * 'make' field will be set FALSE again. This is our signal to 3646146056Sharti * not attempt to do anything but abort our parent as well. 3647146056Sharti */ 3648146056Sharti gn->make = TRUE; 3649146056Sharti gn->made = BEINGMADE; 3650146056Sharti Suff_FindDeps(gn); 3651146056Sharti LST_FOREACH(ln, &gn->children) 3652146056Sharti CompatMake(Lst_Datum(ln), gn); 3653146056Sharti if (!gn->make) { 3654146056Sharti gn->made = ABORTED; 3655146056Sharti pgn->make = FALSE; 3656146056Sharti return (0); 3657146056Sharti } 3658146056Sharti 3659146056Sharti if (Lst_Member(&gn->iParents, pgn) != NULL) { 3660146056Sharti char *p1; 3661146056Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); 3662146056Sharti free(p1); 3663146056Sharti } 3664146056Sharti 3665146056Sharti /* 3666146056Sharti * All the children were made ok. Now cmtime contains the 3667146056Sharti * modification time of the newest child, we need to find out 3668146056Sharti * if we exist and when we were modified last. The criteria for 3669146056Sharti * datedness are defined by the Make_OODate function. 3670146056Sharti */ 3671146056Sharti DEBUGF(MAKE, ("Examining %s...", gn->name)); 3672146056Sharti if (!Make_OODate(gn)) { 3673146056Sharti gn->made = UPTODATE; 3674146056Sharti DEBUGF(MAKE, ("up-to-date.\n")); 3675146056Sharti return (0); 3676146056Sharti } else { 3677146056Sharti DEBUGF(MAKE, ("out-of-date.\n")); 3678146056Sharti } 3679146056Sharti 3680146056Sharti /* 3681146056Sharti * If the user is just seeing if something is out-of-date, 3682146056Sharti * exit now to tell him/her "yes". 3683146056Sharti */ 3684146056Sharti if (queryFlag) { 3685146056Sharti exit(1); 3686146056Sharti } 3687146056Sharti 3688146056Sharti /* 3689146056Sharti * We need to be re-made. We also have to make sure we've got 3690146056Sharti * a $? variable. To be nice, we also define the $> variable 3691146056Sharti * using Make_DoAllVar(). 3692146056Sharti */ 3693146056Sharti Make_DoAllVar(gn); 3694146056Sharti 3695146056Sharti /* 3696146056Sharti * Alter our type to tell if errors should be ignored or things 3697146056Sharti * should not be printed so Compat_RunCommand knows what to do. 3698146056Sharti */ 3699146056Sharti if (Targ_Ignore(gn)) { 3700146056Sharti gn->type |= OP_IGNORE; 3701146056Sharti } 3702146056Sharti if (Targ_Silent(gn)) { 3703146056Sharti gn->type |= OP_SILENT; 3704146056Sharti } 3705146056Sharti 3706146056Sharti if (Job_CheckCommands(gn, Fatal)) { 3707146056Sharti /* 3708146056Sharti * Our commands are ok, but we still have to worry 3709146056Sharti * about the -t flag... 3710146056Sharti */ 3711146056Sharti if (!touchFlag) { 3712146056Sharti curTarg = gn; 3713146056Sharti LST_FOREACH(ln, &gn->commands) { 3714146056Sharti if (Compat_RunCommand(Lst_Datum(ln), 3715146056Sharti gn)) 3716146056Sharti break; 3717146056Sharti } 3718146056Sharti curTarg = NULL; 3719146056Sharti } else { 3720146056Sharti Job_Touch(gn, gn->type & OP_SILENT); 3721146056Sharti } 3722146056Sharti } else { 3723146056Sharti gn->made = ERROR; 3724146056Sharti } 3725146056Sharti 3726146056Sharti if (gn->made != ERROR) { 3727146056Sharti /* 3728146056Sharti * If the node was made successfully, mark it so, update 3729146056Sharti * its modification time and timestamp all its parents. 3730146056Sharti * Note that for .ZEROTIME targets, the timestamping 3731146056Sharti * isn't done. This is to keep its state from affecting 3732146056Sharti * that of its parent. 3733146056Sharti */ 3734146056Sharti gn->made = MADE; 3735146056Sharti#ifndef RECHECK 3736146056Sharti /* 3737146056Sharti * We can't re-stat the thing, but we can at least take 3738146056Sharti * care of rules where a target depends on a source that 3739146056Sharti * actually creates the target, but only if it has 3740146056Sharti * changed, e.g. 3741146056Sharti * 3742146056Sharti * parse.h : parse.o 3743146056Sharti * 3744146056Sharti * parse.o : parse.y 3745146061Sharti * yacc -d parse.y 3746146061Sharti * cc -c y.tab.c 3747146061Sharti * mv y.tab.o parse.o 3748146061Sharti * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 3749146056Sharti * 3750146056Sharti * In this case, if the definitions produced by yacc 3751146056Sharti * haven't changed from before, parse.h won't have been 3752146056Sharti * updated and gn->mtime will reflect the current 3753146056Sharti * modification time for parse.h. This is something of a 3754146056Sharti * kludge, I admit, but it's a useful one.. 3755146056Sharti * 3756146056Sharti * XXX: People like to use a rule like 3757146056Sharti * 3758146056Sharti * FRC: 3759146056Sharti * 3760146056Sharti * To force things that depend on FRC to be made, so we 3761146056Sharti * have to check for gn->children being empty as well... 3762146056Sharti */ 3763146056Sharti if (!Lst_IsEmpty(&gn->commands) || 3764146056Sharti Lst_IsEmpty(&gn->children)) { 3765146056Sharti gn->mtime = now; 3766146056Sharti } 3767146056Sharti#else 3768146056Sharti /* 3769146056Sharti * This is what Make does and it's actually a good 3770146056Sharti * thing, as it allows rules like 3771146056Sharti * 3772146056Sharti * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 3773146056Sharti * 3774146056Sharti * to function as intended. Unfortunately, thanks to 3775146056Sharti * the stateless nature of NFS (and the speed of this 3776146056Sharti * program), there are times when the modification time 3777146056Sharti * of a file created on a remote machine will not be 3778146056Sharti * modified before the stat() implied by the Dir_MTime 3779146056Sharti * occurs, thus leading us to believe that the file 3780146056Sharti * is unchanged, wreaking havoc with files that depend 3781146056Sharti * on this one. 3782146056Sharti * 3783146056Sharti * I have decided it is better to make too much than to 3784146056Sharti * make too little, so this stuff is commented out 3785146056Sharti * unless you're sure it's ok. 3786146056Sharti * -- ardeb 1/12/88 3787146056Sharti */ 3788146056Sharti if (noExecute || Dir_MTime(gn) == 0) { 3789146056Sharti gn->mtime = now; 3790146056Sharti } 3791146056Sharti if (gn->cmtime > gn->mtime) 3792146056Sharti gn->mtime = gn->cmtime; 3793146056Sharti DEBUGF(MAKE, ("update time: %s\n", 3794146056Sharti Targ_FmtTime(gn->mtime))); 3795146056Sharti#endif 3796146056Sharti if (!(gn->type & OP_EXEC)) { 3797146056Sharti pgn->childMade = TRUE; 3798146056Sharti Make_TimeStamp(pgn, gn); 3799146056Sharti } 3800146056Sharti 3801146056Sharti } else if (keepgoing) { 3802146056Sharti pgn->make = FALSE; 3803146056Sharti 3804146056Sharti } else { 3805146056Sharti char *p1; 3806146056Sharti 3807146056Sharti printf("\n\nStop in %s.\n", 3808146056Sharti Var_Value(".CURDIR", gn, &p1)); 3809146056Sharti free(p1); 3810146056Sharti exit(1); 3811146056Sharti } 3812146056Sharti } else if (gn->made == ERROR) { 3813146056Sharti /* 3814146056Sharti * Already had an error when making this beastie. Tell the 3815146056Sharti * parent to abort. 3816146056Sharti */ 3817146056Sharti pgn->make = FALSE; 3818146056Sharti } else { 3819146056Sharti if (Lst_Member(&gn->iParents, pgn) != NULL) { 3820146056Sharti char *p1; 3821146056Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); 3822146056Sharti free(p1); 3823146056Sharti } 3824146056Sharti switch(gn->made) { 3825146056Sharti case BEINGMADE: 3826146056Sharti Error("Graph cycles through %s\n", gn->name); 3827146056Sharti gn->made = ERROR; 3828146056Sharti pgn->make = FALSE; 3829146056Sharti break; 3830146056Sharti case MADE: 3831146056Sharti if ((gn->type & OP_EXEC) == 0) { 3832146056Sharti pgn->childMade = TRUE; 3833146056Sharti Make_TimeStamp(pgn, gn); 3834146056Sharti } 3835146056Sharti break; 3836146056Sharti case UPTODATE: 3837146056Sharti if ((gn->type & OP_EXEC) == 0) { 3838146056Sharti Make_TimeStamp(pgn, gn); 3839146056Sharti } 3840146056Sharti break; 3841146056Sharti default: 3842146056Sharti break; 3843146056Sharti } 3844146056Sharti } 3845146056Sharti 3846146056Sharti return (0); 3847146056Sharti} 3848146056Sharti 3849146056Sharti/*- 3850146056Sharti *----------------------------------------------------------------------- 3851146056Sharti * Compat_Run -- 3852146056Sharti * Start making again, given a list of target nodes. 3853146056Sharti * 3854146056Sharti * Results: 3855146056Sharti * None. 3856146056Sharti * 3857146056Sharti * Side Effects: 3858146056Sharti * Guess what? 3859146056Sharti * 3860146056Sharti *----------------------------------------------------------------------- 3861146056Sharti */ 3862146056Shartivoid 3863146056ShartiCompat_Run(Lst *targs) 3864146056Sharti{ 3865146056Sharti GNode *gn = NULL; /* Current root target */ 3866146056Sharti int error_cnt; /* Number of targets not remade due to errors */ 3867146056Sharti LstNode *ln; 3868146056Sharti 3869146056Sharti Shell_Init(); /* Set up shell. */ 3870146056Sharti 3871146056Sharti if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 3872146056Sharti signal(SIGINT, CompatCatchSig); 3873146056Sharti } 3874146056Sharti if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 3875146056Sharti signal(SIGTERM, CompatCatchSig); 3876146056Sharti } 3877146056Sharti if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 3878146056Sharti signal(SIGHUP, CompatCatchSig); 3879146056Sharti } 3880146056Sharti if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 3881146056Sharti signal(SIGQUIT, CompatCatchSig); 3882146056Sharti } 3883146056Sharti 3884146056Sharti ENDNode = Targ_FindNode(".END", TARG_CREATE); 3885146056Sharti /* 3886146056Sharti * If the user has defined a .BEGIN target, execute the commands 3887146056Sharti * attached to it. 3888146056Sharti */ 3889146056Sharti if (!queryFlag) { 3890146056Sharti gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); 3891146056Sharti if (gn != NULL) { 3892146056Sharti LST_FOREACH(ln, &gn->commands) { 3893146056Sharti if (Compat_RunCommand(Lst_Datum(ln), gn)) 3894146056Sharti break; 3895146056Sharti } 3896146056Sharti if (gn->made == ERROR) { 3897146056Sharti printf("\n\nStop.\n"); 3898146056Sharti exit(1); 3899146056Sharti } 3900146056Sharti } 3901146056Sharti } 3902146056Sharti 3903146056Sharti /* 3904146056Sharti * For each entry in the list of targets to create, call CompatMake on 3905146056Sharti * it to create the thing. CompatMake will leave the 'made' field of gn 3906146056Sharti * in one of several states: 3907146056Sharti * UPTODATE gn was already up-to-date 3908146056Sharti * MADE gn was recreated successfully 3909146056Sharti * ERROR An error occurred while gn was being created 3910146056Sharti * ABORTED gn was not remade because one of its inferiors 3911146056Sharti * could not be made due to errors. 3912146056Sharti */ 3913146056Sharti error_cnt = 0; 3914146056Sharti while (!Lst_IsEmpty(targs)) { 3915146056Sharti gn = Lst_DeQueue(targs); 3916146056Sharti CompatMake(gn, gn); 3917146056Sharti 3918146056Sharti if (gn->made == UPTODATE) { 3919146056Sharti printf("`%s' is up to date.\n", gn->name); 3920146056Sharti } else if (gn->made == ABORTED) { 3921146056Sharti printf("`%s' not remade because of errors.\n", 3922146056Sharti gn->name); 3923146056Sharti error_cnt += 1; 3924146056Sharti } 3925146056Sharti } 3926146056Sharti 3927146056Sharti /* 3928146056Sharti * If the user has defined a .END target, run its commands. 3929146056Sharti */ 3930146056Sharti if (error_cnt == 0) { 3931146056Sharti LST_FOREACH(ln, &ENDNode->commands) { 3932146056Sharti if (Compat_RunCommand(Lst_Datum(ln), gn)) 3933146056Sharti break; 3934146056Sharti } 3935146056Sharti } 3936146056Sharti} 3937146155Sharti 3938