job.c revision 146147
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 146147 2005-05-12 15:10:45Z 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 80144467Sharti * line as a shell specification. Returns FAILURE 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> 12194506Scharnier#include <errno.h> 1225814Sjkh#include <fcntl.h> 123144665Sharti#include <inttypes.h> 1241590Srgrimes#include <string.h> 1255814Sjkh#include <signal.h> 126141104Sharti#include <stdlib.h> 12780381Ssheldonh#include <unistd.h> 12894506Scharnier#include <utime.h> 129141104Sharti 130141104Sharti#include "arch.h" 131142457Sharti#include "buf.h" 132146056Sharti#include "config.h" 1331590Srgrimes#include "dir.h" 134141104Sharti#include "globals.h" 135141104Sharti#include "GNode.h" 1361590Srgrimes#include "job.h" 137141104Sharti#include "make.h" 138141104Sharti#include "parse.h" 1391590Srgrimes#include "pathnames.h" 140141104Sharti#include "str.h" 141146056Sharti#include "suff.h" 142141104Sharti#include "targ.h" 143141104Sharti#include "util.h" 144141104Sharti#include "var.h" 1451590Srgrimes 146146057Sharti#define TMPPAT "/tmp/makeXXXXXXXXXX" 147146057Sharti 148146057Sharti#ifndef USE_KQUEUE 1491590Srgrimes/* 150146057Sharti * The SEL_ constants determine the maximum amount of time spent in select 151146057Sharti * before coming out to see if a child has finished. SEL_SEC is the number of 152146057Sharti * seconds and SEL_USEC is the number of micro-seconds 153146057Sharti */ 154146057Sharti#define SEL_SEC 2 155146057Sharti#define SEL_USEC 0 156146057Sharti#endif /* !USE_KQUEUE */ 157146057Sharti 158146057Sharti/* 159144483Sharti * Job Table definitions. 160144483Sharti * 161144483Sharti * The job "table" is kept as a linked Lst in 'jobs', with the number of 162144483Sharti * active jobs maintained in the 'nJobs' variable. At no time will this 163144483Sharti * exceed the value of 'maxJobs', initialized by the Job_Init function. 164144483Sharti * 165144483Sharti * When a job is finished, the Make_Update function is called on each of the 166144483Sharti * parents of the node which was just remade. This takes care of the upward 167144483Sharti * traversal of the dependency graph. 168144483Sharti */ 169144483Sharti#define JOB_BUFSIZE 1024 170144483Shartitypedef struct Job { 171144665Sharti pid_t pid; /* The child's process ID */ 172144483Sharti 173144483Sharti struct GNode *node; /* The target the child is making */ 174144483Sharti 175144483Sharti /* 176144483Sharti * A LstNode for the first command to be saved after the job completes. 177144483Sharti * This is NULL if there was no "..." in the job's commands. 178144483Sharti */ 179144483Sharti LstNode *tailCmds; 180144483Sharti 181144483Sharti /* 182144483Sharti * An FILE* for writing out the commands. This is only 183144483Sharti * used before the job is actually started. 184144483Sharti */ 185144483Sharti FILE *cmdFILE; 186144483Sharti 187144483Sharti /* 188144483Sharti * A word of flags which determine how the module handles errors, 189144483Sharti * echoing, etc. for the job 190144483Sharti */ 191144483Sharti short flags; /* Flags to control treatment of job */ 192144483Sharti#define JOB_IGNERR 0x001 /* Ignore non-zero exits */ 193144483Sharti#define JOB_SILENT 0x002 /* no output */ 194144483Sharti#define JOB_SPECIAL 0x004 /* Target is a special one. i.e. run it locally 195144483Sharti * if we can't export it and maxLocal is 0 */ 196146061Sharti#define JOB_IGNDOTS 0x008 /* Ignore "..." lines when processing 197144483Sharti * commands */ 198144483Sharti#define JOB_FIRST 0x020 /* Job is first job for the node */ 199144483Sharti#define JOB_RESTART 0x080 /* Job needs to be completely restarted */ 200144483Sharti#define JOB_RESUME 0x100 /* Job needs to be resumed b/c it stopped, 201144483Sharti * for some reason */ 202144483Sharti#define JOB_CONTINUING 0x200 /* We are in the process of resuming this job. 203144483Sharti * Used to avoid infinite recursion between 204144483Sharti * JobFinish and JobRestart */ 205144483Sharti 206144483Sharti /* union for handling shell's output */ 207144483Sharti union { 208144483Sharti /* 209144483Sharti * This part is used when usePipes is true. 210146061Sharti * The output is being caught via a pipe and the descriptors 211144483Sharti * of our pipe, an array in which output is line buffered and 212144483Sharti * the current position in that buffer are all maintained for 213144483Sharti * each job. 214144483Sharti */ 215144483Sharti struct { 216144483Sharti /* 217144483Sharti * Input side of pipe associated with 218144483Sharti * job's output channel 219144483Sharti */ 220144483Sharti int op_inPipe; 221144483Sharti 222144483Sharti /* 223144483Sharti * Output side of pipe associated with job's 224144483Sharti * output channel 225144483Sharti */ 226144483Sharti int op_outPipe; 227144483Sharti 228144483Sharti /* 229144483Sharti * Buffer for storing the output of the 230144483Sharti * job, line by line 231144483Sharti */ 232144483Sharti char op_outBuf[JOB_BUFSIZE + 1]; 233144483Sharti 234144483Sharti /* Current position in op_outBuf */ 235144483Sharti int op_curPos; 236144483Sharti } o_pipe; 237144483Sharti 238144483Sharti /* 239144483Sharti * If usePipes is false the output is routed to a temporary 240144483Sharti * file and all that is kept is the name of the file and the 241144483Sharti * descriptor open to the file. 242144483Sharti */ 243144483Sharti struct { 244144483Sharti /* Name of file to which shell output was rerouted */ 245144483Sharti char of_outFile[sizeof(TMPPAT)]; 246144483Sharti 247144483Sharti /* 248144483Sharti * Stream open to the output file. Used to funnel all 249144483Sharti * from a single job to one file while still allowing 250144483Sharti * multiple shell invocations 251144483Sharti */ 252144483Sharti int of_outFd; 253144483Sharti } o_file; 254144483Sharti 255144483Sharti } output; /* Data for tracking a shell's output */ 256144494Sharti 257144494Sharti TAILQ_ENTRY(Job) link; /* list link */ 258144483Sharti} Job; 259144483Sharti 260146061Sharti#define outPipe output.o_pipe.op_outPipe 261146061Sharti#define inPipe output.o_pipe.op_inPipe 262144483Sharti#define outBuf output.o_pipe.op_outBuf 263144483Sharti#define curPos output.o_pipe.op_curPos 264144483Sharti#define outFile output.o_file.of_outFile 265146061Sharti#define outFd output.o_file.of_outFd 266144483Sharti 267144494ShartiTAILQ_HEAD(JobList, Job); 268144494Sharti 269144483Sharti/* 270144483Sharti * Shell Specifications: 271144483Sharti * 272144483Sharti * Some special stuff goes on if a shell doesn't have error control. In such 273144483Sharti * a case, errCheck becomes a printf template for echoing the command, 274144483Sharti * should echoing be on and ignErr becomes another printf template for 275144483Sharti * executing the command while ignoring the return status. If either of these 276144483Sharti * strings is empty when hasErrCtl is FALSE, the command will be executed 277144483Sharti * anyway as is and if it causes an error, so be it. 278144483Sharti */ 279144483Sharti#define DEF_SHELL_STRUCT(TAG, CONST) \ 280144483Shartistruct TAG { \ 281144483Sharti /* \ 282144483Sharti * the name of the shell. For Bourne and C shells, this is used \ 283144483Sharti * only to find the shell description when used as the single \ 284144483Sharti * source of a .SHELL target. For user-defined shells, this is \ 285144483Sharti * the full path of the shell. \ 286144483Sharti */ \ 287144483Sharti CONST char *name; \ 288144483Sharti \ 289144483Sharti /* True if both echoOff and echoOn defined */ \ 290144483Sharti Boolean hasEchoCtl; \ 291144483Sharti \ 292144483Sharti CONST char *echoOff; /* command to turn off echo */ \ 293144483Sharti CONST char *echoOn; /* command to turn it back on */\ 294144483Sharti \ 295144483Sharti /* \ 296144483Sharti * What the shell prints, and its length, when given the \ 297144483Sharti * echo-off command. This line will not be printed when \ 298144483Sharti * received from the shell. This is usually the command which \ 299144483Sharti * was executed to turn off echoing \ 300144483Sharti */ \ 301144483Sharti CONST char *noPrint; \ 302144483Sharti \ 303144483Sharti /* set if can control error checking for individual commands */ \ 304144483Sharti Boolean hasErrCtl; \ 305144483Sharti \ 306144483Sharti /* string to turn error checking on */ \ 307144483Sharti CONST char *errCheck; \ 308144483Sharti \ 309144483Sharti /* string to turn off error checking */ \ 310144483Sharti CONST char *ignErr; \ 311144483Sharti \ 312144483Sharti CONST char *echo; /* command line flag: echo commands */ \ 313144483Sharti CONST char *exit; /* command line flag: exit on error */ \ 314144483Sharti} 315144483Sharti 316144483ShartiDEF_SHELL_STRUCT(Shell,); 317144483ShartiDEF_SHELL_STRUCT(CShell, const); 318144483Sharti 319144483Sharti/* 3208874Srgrimes * error handling variables 3211590Srgrimes */ 322144467Shartistatic int errors = 0; /* number of errors reported */ 323144467Shartistatic int aborting = 0; /* why is the make aborting? */ 324144467Sharti#define ABORT_ERROR 1 /* Because of an error */ 325144467Sharti#define ABORT_INTERRUPT 2 /* Because it was interrupted */ 326144467Sharti#define ABORT_WAIT 3 /* Waiting for jobs to finish */ 3271590Srgrimes 32818730Ssteve/* 32918730Ssteve * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file 33018730Ssteve * is a char! So when we go above 127 we turn negative! 33118730Ssteve */ 332138232Sharti#define FILENO(a) ((unsigned)fileno(a)) 3331590Srgrimes 3341590Srgrimes/* 3351590Srgrimes * post-make command processing. The node postCommands is really just the 3361590Srgrimes * .END target but we keep it around to avoid having to search for it 3371590Srgrimes * all the time. 3381590Srgrimes */ 339144467Shartistatic GNode *postCommands; 3401590Srgrimes 3411590Srgrimes/* 342144467Sharti * The number of commands actually printed for a target. Should this 343144467Sharti * number be 0, no shell will be executed. 344144467Sharti */ 345144467Shartistatic int numCommands; 346144467Sharti 347144467Sharti/* 3481590Srgrimes * Return values from JobStart. 3491590Srgrimes */ 350144467Sharti#define JOB_RUNNING 0 /* Job is running */ 351146061Sharti#define JOB_ERROR 1 /* Error in starting the job */ 352144467Sharti#define JOB_FINISHED 2 /* The job is already finished */ 353144467Sharti#define JOB_STOPPED 3 /* The job is stopped */ 3541590Srgrimes 3551590Srgrimes/* 3561590Srgrimes * Descriptions for various shells. 3571590Srgrimes */ 358144483Shartistatic const struct CShell shells[] = { 359144467Sharti /* 360144467Sharti * CSH description. The csh can do echo control by playing 361144467Sharti * with the setting of the 'echo' shell variable. Sadly, 362144467Sharti * however, it is unable to do error control nicely. 363144467Sharti */ 364144467Sharti { 365144467Sharti "csh", 366144741Sharti TRUE, "unset verbose", "set verbose", "unset verbose", 367144467Sharti FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", 368144467Sharti "v", "e", 369144467Sharti }, 370144467Sharti /* 371144467Sharti * SH description. Echo control is also possible and, under 372144467Sharti * sun UNIX anyway, one can even control error checking. 373144467Sharti */ 374144467Sharti { 375144467Sharti "sh", 376144741Sharti TRUE, "set -", "set -v", "set -", 377144467Sharti TRUE, "set -e", "set +e", 37818730Ssteve#ifdef OLDBOURNESHELL 379144467Sharti FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", 38018730Ssteve#endif 381144467Sharti "v", "e", 382144467Sharti }, 383144467Sharti /* 384144467Sharti * KSH description. The Korn shell has a superset of 385144467Sharti * the Bourne shell's functionality. 386144467Sharti */ 387144467Sharti { 388144467Sharti "ksh", 389144741Sharti TRUE, "set -", "set -v", "set -", 390144467Sharti TRUE, "set -e", "set +e", 391144467Sharti "v", "e", 392144467Sharti }, 3931590Srgrimes}; 3941590Srgrimes 395144467Sharti/* 396144467Sharti * This is the shell to which we pass all commands in the Makefile. 397144467Sharti * It is set by the Job_ParseShell function. 398144467Sharti */ 399144483Shartistatic struct Shell *commandShell = NULL; 400146059Shartistatic char *shellPath = NULL; /* full pathname of executable image */ 401146059Shartistatic char *shellName = NULL; /* last component of shell */ 4021590Srgrimes 403146140Sharti/* 404146140Sharti * The maximum number of jobs that may run. This is initialize from the 405146140Sharti * -j argument for the leading make and from the FIFO for sub-makes. 406146140Sharti */ 407146140Shartistatic int maxJobs; 408146140Sharti 409144656Shartistatic int nJobs; /* The number of children currently running */ 410138916Sharti 411138916Sharti/* The structures that describe them */ 412144494Shartistatic struct JobList jobs = TAILQ_HEAD_INITIALIZER(jobs); 413138916Sharti 414146061Shartistatic Boolean jobFull; /* Flag to tell when the job table is full. It 4151590Srgrimes * is set TRUE when (1) the total number of 416137572Sphk * running jobs equals the maximum allowed */ 417104475Sphk#ifdef USE_KQUEUE 418104475Sphkstatic int kqfd; /* File descriptor obtained by kqueue() */ 419104475Sphk#else 420146061Shartistatic fd_set outputs; /* Set of descriptors of pipes connected to 4211590Srgrimes * the output channels of children */ 4221590Srgrimes#endif 4231590Srgrimes 424146061Shartistatic GNode *lastNode; /* The node for which output was most recently 4251590Srgrimes * produced. */ 426146061Shartistatic const char *targFmt; /* Format string to use to head output from a 4271590Srgrimes * job when it's not the most-recent job heard 4281590Srgrimes * from */ 4291590Srgrimes 430137202Sharti#define TARG_FMT "--- %s ---\n" /* Default format */ 431137202Sharti#define MESSAGE(fp, gn) \ 432138232Sharti fprintf(fp, targFmt, gn->name); 43318730Ssteve 4341590Srgrimes/* 435137252Sharti * When JobStart attempts to run a job but isn't allowed to 436137252Sharti * or when Job_CatchChildren detects a job that has 437137252Sharti * been stopped somehow, the job is placed on the stoppedJobs queue to be run 4388874Srgrimes * when the next job finishes. 439138916Sharti * 440138916Sharti * Lst of Job structures describing jobs that were stopped due to 441138916Sharti * concurrency limits or externally 4421590Srgrimes */ 443144494Shartistatic struct JobList stoppedJobs = TAILQ_HEAD_INITIALIZER(stoppedJobs); 4441590Srgrimes 445144656Shartistatic int fifoFd; /* Fd of our job fifo */ 446144656Shartistatic char fifoName[] = "/tmp/make_fifo_XXXXXXXXX"; 447144656Shartistatic int fifoMaster; 4481590Srgrimes 449137605Shartistatic sig_atomic_t interrupted; 450137605Sharti 451137605Sharti 4521590Srgrimes#if defined(USE_PGRP) && defined(SYSV) 45318730Ssteve# define KILL(pid, sig) killpg(-(pid), (sig)) 4541590Srgrimes#else 4551590Srgrimes# if defined(USE_PGRP) 45618730Ssteve# define KILL(pid, sig) killpg((pid), (sig)) 4571590Srgrimes# else 45818730Ssteve# define KILL(pid, sig) kill((pid), (sig)) 4591590Srgrimes# endif 4601590Srgrimes#endif 4611590Srgrimes 46218730Ssteve/* 46318730Ssteve * Grmpf... There is no way to set bits of the wait structure 46418730Ssteve * anymore with the stupid W*() macros. I liked the union wait 46518730Ssteve * stuff much more. So, we devise our own macros... This is 46618730Ssteve * really ugly, use dramamine sparingly. You have been warned. 46718730Ssteve */ 468103503Sjmallett#define W_SETMASKED(st, val, fun) \ 46918730Ssteve { \ 470138232Sharti int sh = (int)~0; \ 47118730Ssteve int mask = fun(sh); \ 47218730Ssteve \ 47318730Ssteve for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ 47418730Ssteve continue; \ 47518730Ssteve *(st) = (*(st) & ~mask) | ((val) << sh); \ 47618730Ssteve } 47718730Ssteve 478103503Sjmallett#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) 479103503Sjmallett#define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS) 48018730Ssteve 481146129Sharti/** 482146129Sharti * Information used to create a new process. 483146129Sharti */ 484146129Shartitypedef struct ProcStuff { 485146129Sharti int in; /* stdin for new process */ 486146129Sharti int out; /* stdout for new process */ 487146129Sharti int err; /* stderr for new process */ 488146129Sharti 489146129Sharti int merge_errors; /* true if stderr is redirected to stdin */ 490146129Sharti int pgroup; /* true if new process a process leader */ 491146129Sharti int searchpath; /* true if binary should be found via $PATH */ 492146129Sharti 493146129Sharti char **argv; 494146130Sharti 495146130Sharti pid_t child_pid; 496146129Sharti} ProcStuff; 497146129Sharti 49892921Simpstatic void JobRestart(Job *); 49992921Simpstatic int JobStart(GNode *, int, Job *); 50092921Simpstatic void JobDoOutput(Job *, Boolean); 501144483Shartistatic struct Shell *JobMatchShell(const char *); 50292921Simpstatic void JobInterrupt(int, int); 50392921Simpstatic void JobRestartJobs(void); 504146129Shartistatic void ProcExec(const ProcStuff *) __dead2; 505146142Shartistatic int Compat_RunCommand(char *, struct GNode *); 5061590Srgrimes 507146132Sharti/* 508146132Sharti * The following array is used to make a fast determination of which 509146132Sharti * commands and characters are interpreted specially by the shell. 510146132Sharti * If a command is one of these or contains any of these characters, 511146132Sharti * it is executed by the shell, not directly by us. 512146132Sharti * XXX Both of these arrays should be configurable via .SHELL 513146132Sharti */ 514146132Shartistatic const char const* sh_builtin[] = { 515146132Sharti "alias", "cd", "eval", "exec", 516146132Sharti "exit", "read", "set", "ulimit", 517146132Sharti "unalias", "umask", "unset", "wait", 518146132Sharti ":", NULL 519146132Sharti}; 520146132Shartistatic const char *sh_meta = "#=|^(){};&<>*?[]:$`\\\n"; 521146132Sharti 522146132Shartistatic GNode *curTarg = NULL; 523146132Shartistatic GNode *ENDNode; 524146132Sharti 525146144Shartistatic void 526146144Sharticatch_child(int sig __unused) 527146144Sharti{ 528146144Sharti} 529146144Sharti 530144467Sharti/** 531146144Sharti */ 532146144Shartivoid 533146144ShartiProc_Init() 534146144Sharti{ 535146144Sharti /* 536146144Sharti * Catch SIGCHLD so that we get kicked out of select() when we 537146144Sharti * need to look at a child. This is only known to matter for the 538146144Sharti * -j case (perhaps without -P). 539146144Sharti * 540146144Sharti * XXX this is intentionally misplaced. 541146144Sharti */ 542146144Sharti struct sigaction sa; 543146144Sharti 544146144Sharti sigemptyset(&sa.sa_mask); 545146144Sharti sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; 546146144Sharti sa.sa_handler = catch_child; 547146144Sharti sigaction(SIGCHLD, &sa, NULL); 548146144Sharti 549146144Sharti#if DEFSHELL == 2 550146144Sharti /* 551146144Sharti * Turn off ENV to make ksh happier. 552146144Sharti */ 553146144Sharti unsetenv("ENV"); 554146144Sharti#endif 555146144Sharti} 556146144Sharti 557146144Sharti/** 558146129Sharti * Replace the current process. 559146129Sharti */ 560146129Shartistatic void 561146129ShartiProcExec(const ProcStuff *ps) 562146129Sharti{ 563146129Sharti 564146129Sharti if (ps->in != STDIN_FILENO) { 565146129Sharti /* 566146129Sharti * Redirect the child's stdin to the input fd 567146129Sharti * and reset it to the beginning (again). 568146129Sharti */ 569146129Sharti if (dup2(ps->in, STDIN_FILENO) == -1) 570146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 571146129Sharti lseek(STDIN_FILENO, (off_t)0, SEEK_SET); 572146129Sharti } 573146129Sharti 574146129Sharti if (ps->out != STDOUT_FILENO) { 575146129Sharti /* 576146129Sharti * Redirect the child's stdout to the output fd. 577146129Sharti */ 578146129Sharti if (dup2(ps->out, STDOUT_FILENO) == -1) 579146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 580146129Sharti close(ps->out); 581146129Sharti } 582146129Sharti 583146129Sharti if (ps->err != STDERR_FILENO) { 584146129Sharti /* 585146129Sharti * Redirect the child's stderr to the err fd. 586146129Sharti */ 587146129Sharti if (dup2(ps->err, STDERR_FILENO) == -1) 588146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 589146129Sharti close(ps->err); 590146129Sharti } 591146129Sharti 592146129Sharti if (ps->merge_errors) { 593146129Sharti /* 594146129Sharti * Send stderr to parent process too. 595146129Sharti */ 596146129Sharti if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 597146129Sharti Punt("Cannot dup2: %s", strerror(errno)); 598146129Sharti } 599146129Sharti 600146129Sharti /* 601146129Sharti * The file descriptors for stdin, stdout, or stderr might 602146129Sharti * have been marked close-on-exec. Clear the flag on all 603146129Sharti * of them. 604146129Sharti */ 605146129Sharti fcntl(STDIN_FILENO, F_SETFD, 606146129Sharti fcntl(STDIN_FILENO, F_GETFD) & (~FD_CLOEXEC)); 607146129Sharti fcntl(STDOUT_FILENO, F_SETFD, 608146129Sharti fcntl(STDOUT_FILENO, F_GETFD) & (~FD_CLOEXEC)); 609146129Sharti fcntl(STDERR_FILENO, F_SETFD, 610146129Sharti fcntl(STDERR_FILENO, F_GETFD) & (~FD_CLOEXEC)); 611146129Sharti 612146129Sharti if (ps->pgroup) { 613146129Sharti#ifdef USE_PGRP 614146129Sharti /* 615146129Sharti * Become a process group leader, so we can kill it and all 616146129Sharti * its descendants in one fell swoop, by killing its process 617146129Sharti * family, but not commit suicide. 618146129Sharti */ 619146129Sharti#if defined(SYSV) 620146129Sharti setsid(); 621146129Sharti#else 622146129Sharti setpgid(0, getpid()); 623146129Sharti#endif 624146129Sharti#endif /* USE_PGRP */ 625146129Sharti } 626146129Sharti 627146129Sharti if (ps->searchpath) { 628146129Sharti execvp(ps->argv[0], ps->argv); 629146129Sharti 630146129Sharti write(STDERR_FILENO, ps->argv[0], strlen(ps->argv[0])); 631146129Sharti write(STDERR_FILENO, ":", 1); 632146129Sharti write(STDERR_FILENO, strerror(errno), strlen(strerror(errno))); 633146129Sharti write(STDERR_FILENO, "\n", 1); 634146129Sharti } else { 635146129Sharti execv(shellPath, ps->argv); 636146129Sharti 637146129Sharti write(STDERR_FILENO, 638146129Sharti "Could not execute shell\n", 639146129Sharti sizeof("Could not execute shell")); 640146129Sharti } 641146129Sharti 642146129Sharti /* 643146129Sharti * Since we are the child process, exit without flushing buffers. 644146129Sharti */ 645146129Sharti _exit(1); 646146129Sharti /* NOTREACHED */ 647146129Sharti} 648146129Sharti 649146129Sharti/** 650146131Sharti * Wait for child process to terminate. 651146130Sharti */ 652146130Shartistatic int 653146130ShartiProcWait(ProcStuff *ps) 654146130Sharti{ 655146130Sharti pid_t pid; 656146130Sharti int status; 657146130Sharti 658146130Sharti /* 659146130Sharti * Wait for the process to exit. 660146130Sharti */ 661146131Sharti for (;;) { 662146131Sharti pid = wait(&status); 663146131Sharti if (pid == -1 && errno != EINTR) { 664146131Sharti Fatal("error in wait: %d", pid); 665146131Sharti /* NOTREACHED */ 666146131Sharti } 667146131Sharti if (pid == ps->child_pid) { 668146131Sharti break; 669146131Sharti } 670146131Sharti if (interrupted) { 671146131Sharti break; 672146131Sharti } 673146130Sharti } 674146130Sharti 675146130Sharti return (status); 676146130Sharti} 677146130Sharti 678146130Sharti/** 679137605Sharti * JobCatchSignal 680144467Sharti * Got a signal. Set global variables and hope that someone will 681144467Sharti * handle it. 682137605Sharti */ 683137605Shartistatic void 684137605ShartiJobCatchSig(int signo) 685137605Sharti{ 686137605Sharti 687137605Sharti interrupted = signo; 688137605Sharti} 689137605Sharti 690144467Sharti/** 6911590Srgrimes * JobPassSig -- 692137252Sharti * Pass a signal on to all local jobs if 6931590Srgrimes * USE_PGRP is defined, then die ourselves. 6941590Srgrimes * 6951590Srgrimes * Side Effects: 6961590Srgrimes * We die by the same signal. 6971590Srgrimes */ 6981590Srgrimesstatic void 699104696SjmallettJobPassSig(int signo) 7001590Srgrimes{ 701144741Sharti Job *job; 702144467Sharti sigset_t nmask, omask; 703144467Sharti struct sigaction act; 7048874Srgrimes 705144467Sharti sigemptyset(&nmask); 706144467Sharti sigaddset(&nmask, signo); 707144467Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 708137605Sharti 709144467Sharti DEBUGF(JOB, ("JobPassSig(%d) called.\n", signo)); 710144741Sharti TAILQ_FOREACH(job, &jobs, link) { 711144741Sharti DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 712144741Sharti signo, (intmax_t)job->pid)); 713144741Sharti KILL(job->pid, signo); 714144741Sharti } 7151590Srgrimes 716144467Sharti /* 717144467Sharti * Deal with proper cleanup based on the signal received. We only run 718144467Sharti * the .INTERRUPT target if the signal was in fact an interrupt. 719144467Sharti * The other three termination signals are more of a "get out *now*" 720144467Sharti * command. 721144467Sharti */ 722144467Sharti if (signo == SIGINT) { 723144467Sharti JobInterrupt(TRUE, signo); 724144657Sharti } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) { 725144467Sharti JobInterrupt(FALSE, signo); 726144467Sharti } 7278874Srgrimes 728144467Sharti /* 729144467Sharti * Leave gracefully if SIGQUIT, rather than core dumping. 730144467Sharti */ 731144467Sharti if (signo == SIGQUIT) { 732144467Sharti signo = SIGINT; 733144467Sharti } 7348874Srgrimes 735144467Sharti /* 736144467Sharti * Send ourselves the signal now we've given the message to everyone 737144467Sharti * else. Note we block everything else possible while we're getting 738144467Sharti * the signal. This ensures that all our jobs get continued when we 739144467Sharti * wake up before we take any other signal. 740144467Sharti * XXX this comment seems wrong. 741144467Sharti */ 742144467Sharti act.sa_handler = SIG_DFL; 743144467Sharti sigemptyset(&act.sa_mask); 744144467Sharti act.sa_flags = 0; 745144467Sharti sigaction(signo, &act, NULL); 7461590Srgrimes 747144467Sharti DEBUGF(JOB, ("JobPassSig passing signal to self, mask = %x.\n", 748144467Sharti ~0 & ~(1 << (signo - 1)))); 749144467Sharti signal(signo, SIG_DFL); 7501590Srgrimes 751144467Sharti KILL(getpid(), signo); 75218730Ssteve 753144467Sharti signo = SIGCONT; 754144741Sharti TAILQ_FOREACH(job, &jobs, link) { 755144741Sharti DEBUGF(JOB, ("JobPassSig passing signal %d to child %jd.\n", 756144741Sharti signo, (intmax_t)job->pid)); 757144741Sharti KILL(job->pid, signo); 758144741Sharti } 7591590Srgrimes 760144467Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 761144467Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 762144467Sharti act.sa_handler = JobPassSig; 763144467Sharti sigaction(signo, &act, NULL); 7641590Srgrimes} 7651590Srgrimes 766144467Sharti/** 7671590Srgrimes * JobPrintCommand -- 7681590Srgrimes * Put out another command for the given job. If the command starts 7691590Srgrimes * with an @ or a - we process it specially. In the former case, 7701590Srgrimes * so long as the -s and -n flags weren't given to make, we stick 7711590Srgrimes * a shell-specific echoOff command in the script. In the latter, 7721590Srgrimes * we ignore errors for the entire job, unless the shell has error 7731590Srgrimes * control. 7741590Srgrimes * If the command is just "..." we take all future commands for this 7751590Srgrimes * job to be commands to be executed once the entire graph has been 7761590Srgrimes * made and return non-zero to signal that the end of the commands 7771590Srgrimes * was reached. These commands are later attached to the postCommands 77894594Sobrien * node and executed by Job_Finish when all things are done. 779142993Sharti * This function is called from JobStart via LST_FOREACH. 7801590Srgrimes * 7811590Srgrimes * Results: 7821590Srgrimes * Always 0, unless the command was "..." 7831590Srgrimes * 7841590Srgrimes * Side Effects: 7851590Srgrimes * If the command begins with a '-' and the shell has no error control, 7861590Srgrimes * the JOB_IGNERR flag is set in the job descriptor. 7871590Srgrimes * If the command is "..." and we're not ignoring such things, 7881590Srgrimes * tailCmds is set to the successor node of the cmd. 7891590Srgrimes * numCommands is incremented if the command is actually printed. 7901590Srgrimes */ 7911590Srgrimesstatic int 792144741ShartiJobPrintCommand(char *cmd, Job *job) 7931590Srgrimes{ 794144467Sharti Boolean noSpecials; /* true if we shouldn't worry about 795141258Sharti * inserting special commands into 796141258Sharti * the input stream. */ 797144467Sharti Boolean shutUp = FALSE; /* true if we put a no echo command 798141258Sharti * into the command file */ 799144467Sharti Boolean errOff = FALSE; /* true if we turned error checking 800141258Sharti * off before printing the command 801141258Sharti * and need to turn it back on */ 802144467Sharti const char *cmdTemplate;/* Template to use when printing the command */ 803144467Sharti char *cmdStart; /* Start of expanded command */ 804144467Sharti LstNode *cmdNode; /* Node for replacing the command */ 8051590Srgrimes 806144467Sharti noSpecials = (noExecute && !(job->node->type & OP_MAKE)); 8071590Srgrimes 808144467Sharti if (strcmp(cmd, "...") == 0) { 809144467Sharti job->node->type |= OP_SAVE_CMDS; 810144467Sharti if ((job->flags & JOB_IGNDOTS) == 0) { 811144467Sharti job->tailCmds = 812144467Sharti Lst_Succ(Lst_Member(&job->node->commands, cmd)); 813144467Sharti return (1); 814144467Sharti } 815144467Sharti return (0); 8161590Srgrimes } 8171590Srgrimes 818144467Sharti#define DBPRINTF(fmt, arg) \ 819144467Sharti DEBUGF(JOB, (fmt, arg)); \ 820144467Sharti fprintf(job->cmdFILE, fmt, arg); \ 821144467Sharti fflush(job->cmdFILE); 8221590Srgrimes 823144467Sharti numCommands += 1; 8241590Srgrimes 825144467Sharti /* 826144467Sharti * For debugging, we replace each command with the result of expanding 827144467Sharti * the variables in the command. 828144467Sharti */ 829144467Sharti cmdNode = Lst_Member(&job->node->commands, cmd); 830142457Sharti 831146027Sharti cmd = Buf_Peel(Var_Subst(cmd, job->node, FALSE)); 832144467Sharti cmdStart = cmd; 833142457Sharti 834144467Sharti Lst_Replace(cmdNode, cmdStart); 8351590Srgrimes 836144467Sharti cmdTemplate = "%s\n"; 8371590Srgrimes 838144467Sharti /* 839144467Sharti * Check for leading @', -' or +'s to control echoing, error checking, 840144467Sharti * and execution on -n. 841144467Sharti */ 842144467Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 843144467Sharti switch (*cmd) { 844132839Sharti 845144467Sharti case '@': 846144467Sharti shutUp = DEBUG(LOUD) ? FALSE : TRUE; 847144467Sharti break; 848132839Sharti 849144467Sharti case '-': 850144467Sharti errOff = TRUE; 851144467Sharti break; 852132839Sharti 853144467Sharti case '+': 854144467Sharti if (noSpecials) { 855144467Sharti /* 856144467Sharti * We're not actually exececuting anything... 857144467Sharti * but this one needs to be - use compat mode 858144467Sharti * just for it. 859144467Sharti */ 860144741Sharti Compat_RunCommand(cmd, job->node); 861144467Sharti return (0); 862144467Sharti } 863144467Sharti break; 864144467Sharti } 865144467Sharti cmd++; 8661590Srgrimes } 8671590Srgrimes 868144467Sharti while (isspace((unsigned char)*cmd)) 869144467Sharti cmd++; 8701590Srgrimes 871144467Sharti if (shutUp) { 872144467Sharti if (!(job->flags & JOB_SILENT) && !noSpecials && 8731590Srgrimes commandShell->hasEchoCtl) { 87418730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 8751590Srgrimes } else { 876144467Sharti shutUp = FALSE; 8771590Srgrimes } 878144467Sharti } 879144467Sharti 880144467Sharti if (errOff) { 881144467Sharti if (!(job->flags & JOB_IGNERR) && !noSpecials) { 882144467Sharti if (commandShell->hasErrCtl) { 883144467Sharti /* 884144467Sharti * We don't want the error-control commands 885144467Sharti * showing up either, so we turn off echoing 886144467Sharti * while executing them. We could put another 887144467Sharti * field in the shell structure to tell 888144467Sharti * JobDoOutput to look for this string too, 889144467Sharti * but why make it any more complex than 890144467Sharti * it already is? 891144467Sharti */ 892144467Sharti if (!(job->flags & JOB_SILENT) && !shutUp && 893144467Sharti commandShell->hasEchoCtl) { 894144467Sharti DBPRINTF("%s\n", commandShell->echoOff); 895144467Sharti DBPRINTF("%s\n", commandShell->ignErr); 896144467Sharti DBPRINTF("%s\n", commandShell->echoOn); 897144467Sharti } else { 898144467Sharti DBPRINTF("%s\n", commandShell->ignErr); 899144467Sharti } 900144467Sharti } else if (commandShell->ignErr && 901144657Sharti *commandShell->ignErr != '\0') { 902144467Sharti /* 903144467Sharti * The shell has no error control, so we need to 904144467Sharti * be weird to get it to ignore any errors from 905144467Sharti * the command. If echoing is turned on, we turn 906144467Sharti * it off and use the errCheck template to echo 907144467Sharti * the command. Leave echoing off so the user 908144467Sharti * doesn't see the weirdness we go through to 909144467Sharti * ignore errors. Set cmdTemplate to use the 910144467Sharti * weirdness instead of the simple "%s\n" 911144467Sharti * template. 912144467Sharti */ 913144467Sharti if (!(job->flags & JOB_SILENT) && !shutUp && 914144467Sharti commandShell->hasEchoCtl) { 915144467Sharti DBPRINTF("%s\n", commandShell->echoOff); 916144467Sharti DBPRINTF(commandShell->errCheck, cmd); 917144467Sharti shutUp = TRUE; 918144467Sharti } 919144467Sharti cmdTemplate = commandShell->ignErr; 920144467Sharti /* 921144467Sharti * The error ignoration (hee hee) is already 922144467Sharti * taken care of by the ignErr template, so 923144467Sharti * pretend error checking is still on. 924144467Sharti */ 925144467Sharti errOff = FALSE; 926144467Sharti } else { 927144467Sharti errOff = FALSE; 928144467Sharti } 929144467Sharti } else { 930144467Sharti errOff = FALSE; 931144467Sharti } 932144467Sharti } 933144467Sharti 934144467Sharti DBPRINTF(cmdTemplate, cmd); 935144467Sharti 936144467Sharti if (errOff) { 9371590Srgrimes /* 938144467Sharti * If echoing is already off, there's no point in issuing the 939144467Sharti * echoOff command. Otherwise we issue it and pretend it was on 940144467Sharti * for the whole command... 9411590Srgrimes */ 942144467Sharti if (!shutUp && !(job->flags & JOB_SILENT) && 9431590Srgrimes commandShell->hasEchoCtl) { 94418730Ssteve DBPRINTF("%s\n", commandShell->echoOff); 9451590Srgrimes shutUp = TRUE; 9461590Srgrimes } 947144467Sharti DBPRINTF("%s\n", commandShell->errCheck); 9481590Srgrimes } 949144467Sharti if (shutUp) { 950144467Sharti DBPRINTF("%s\n", commandShell->echoOn); 9511590Srgrimes } 952144467Sharti return (0); 9531590Srgrimes} 9541590Srgrimes 955144467Sharti/** 95618730Ssteve * JobClose -- 95718730Ssteve * Called to close both input and output pipes when a job is finished. 95818730Ssteve * 95918730Ssteve * Side Effects: 96018730Ssteve * The file descriptors associated with the job are closed. 96118730Ssteve */ 96218730Sstevestatic void 963104696SjmallettJobClose(Job *job) 96418730Ssteve{ 965138232Sharti 966144467Sharti if (usePipes) { 967137202Sharti#if !defined(USE_KQUEUE) 968144467Sharti FD_CLR(job->inPipe, &outputs); 96918730Ssteve#endif 970144467Sharti if (job->outPipe != job->inPipe) { 971144467Sharti close(job->outPipe); 972144467Sharti } 973144467Sharti JobDoOutput(job, TRUE); 974144467Sharti close(job->inPipe); 975144467Sharti } else { 976144467Sharti close(job->outFd); 977144467Sharti JobDoOutput(job, TRUE); 97818730Ssteve } 97918730Ssteve} 98018730Ssteve 981144467Sharti/** 9821590Srgrimes * JobFinish -- 9831590Srgrimes * Do final processing for the given job including updating 9841590Srgrimes * parents and starting new jobs as available/necessary. Note 9851590Srgrimes * that we pay no attention to the JOB_IGNERR flag here. 9861590Srgrimes * This is because when we're called because of a noexecute flag 9871590Srgrimes * or something, jstat.w_status is 0 and when called from 9881590Srgrimes * Job_CatchChildren, the status is zeroed if it s/b ignored. 9891590Srgrimes * 9901590Srgrimes * Side Effects: 9911590Srgrimes * Some nodes may be put on the toBeMade queue. 9921590Srgrimes * Final commands for the job are placed on postCommands. 9931590Srgrimes * 9941590Srgrimes * If we got an error and are aborting (aborting == ABORT_ERROR) and 9951590Srgrimes * the job list is now empty, we are done for the day. 9961590Srgrimes * If we recognized an error (errors !=0), we set the aborting flag 9971590Srgrimes * to ABORT_ERROR so no more jobs will be started. 9981590Srgrimes */ 9991590Srgrimesstatic void 1000104696SjmallettJobFinish(Job *job, int *status) 10011590Srgrimes{ 1002144467Sharti Boolean done; 1003144467Sharti LstNode *ln; 10041590Srgrimes 1005146133Sharti if (WIFEXITED(*status)) { 1006146133Sharti int job_status = WEXITSTATUS(*status); 1007146133Sharti 1008144467Sharti JobClose(job); 1009144467Sharti /* 1010146133Sharti * Deal with ignored errors in -B mode. We need to 1011146133Sharti * print a message telling of the ignored error as 1012146133Sharti * well as setting status.w_status to 0 so the next 1013146133Sharti * command gets run. To do this, we set done to be 1014146133Sharti * TRUE if in -B mode and the job exited non-zero. 1015144467Sharti */ 1016146133Sharti if (job_status == 0) { 1017146133Sharti done = FALSE; 1018146133Sharti } else { 1019146133Sharti if (job->flags & JOB_IGNERR) { 1020146133Sharti done = TRUE; 1021146133Sharti } else { 1022146133Sharti /* 1023146133Sharti * If it exited non-zero and either we're 1024146133Sharti * doing things our way or we're not ignoring 1025146133Sharti * errors, the job is finished. Similarly, if 1026146133Sharti * the shell died because of a signal the job 1027146133Sharti * is also finished. In these cases, finish 1028146133Sharti * out the job's output before printing the 1029146133Sharti * exit status... 1030146133Sharti */ 1031146133Sharti done = TRUE; 1032146133Sharti if (job->cmdFILE != NULL && 1033146133Sharti job->cmdFILE != stdout) { 1034146133Sharti fclose(job->cmdFILE); 1035146133Sharti } 10368874Srgrimes 1037146133Sharti } 1038146133Sharti } 1039146133Sharti } else if (WIFSIGNALED(*status)) { 1040146133Sharti if (WTERMSIG(*status) == SIGCONT) { 1041146133Sharti /* 1042146133Sharti * No need to close things down or anything. 1043146133Sharti */ 1044146133Sharti done = FALSE; 1045146133Sharti } else { 1046146133Sharti /* 1047146133Sharti * If it exited non-zero and either we're 1048146133Sharti * doing things our way or we're not ignoring 1049146133Sharti * errors, the job is finished. Similarly, if 1050146133Sharti * the shell died because of a signal the job 1051146133Sharti * is also finished. In these cases, finish 1052146133Sharti * out the job's output before printing the 1053146133Sharti * exit status... 1054146133Sharti */ 1055146133Sharti JobClose(job); 1056146133Sharti if (job->cmdFILE != NULL && 1057146133Sharti job->cmdFILE != stdout) { 1058146133Sharti fclose(job->cmdFILE); 1059146133Sharti } 1060146133Sharti done = TRUE; 1061146133Sharti } 10621590Srgrimes } else { 1063144467Sharti /* 1064144467Sharti * No need to close things down or anything. 1065144467Sharti */ 1066144467Sharti done = FALSE; 10671590Srgrimes } 10681590Srgrimes 1069146133Sharti if (WIFEXITED(*status)) { 1070146133Sharti if (done || DEBUG(JOB)) { 1071146133Sharti FILE *out; 1072144467Sharti 1073146133Sharti if (compatMake && 1074146133Sharti !usePipes && 1075146133Sharti (job->flags & JOB_IGNERR)) { 1076146133Sharti /* 1077146133Sharti * If output is going to a file and this job 1078146133Sharti * is ignoring errors, arrange to have the 1079146133Sharti * exit status sent to the output file as 1080146133Sharti * well. 1081146133Sharti */ 1082146133Sharti out = fdopen(job->outFd, "w"); 1083146133Sharti if (out == NULL) 1084146133Sharti Punt("Cannot fdopen"); 1085146133Sharti } else { 1086146133Sharti out = stdout; 1087146133Sharti } 10881590Srgrimes 1089144665Sharti DEBUGF(JOB, ("Process %jd exited.\n", 1090144665Sharti (intmax_t)job->pid)); 1091146133Sharti 1092146133Sharti if (WEXITSTATUS(*status) == 0) { 1093146133Sharti if (DEBUG(JOB)) { 1094146133Sharti if (usePipes && job->node != lastNode) { 1095146133Sharti MESSAGE(out, job->node); 1096146133Sharti lastNode = job->node; 1097146133Sharti } 1098146133Sharti fprintf(out, 1099146133Sharti "*** Completed successfully\n"); 1100146133Sharti } 1101146133Sharti } else { 1102144467Sharti if (usePipes && job->node != lastNode) { 1103144467Sharti MESSAGE(out, job->node); 1104144467Sharti lastNode = job->node; 1105144467Sharti } 1106144467Sharti fprintf(out, "*** Error code %d%s\n", 1107146133Sharti WEXITSTATUS(*status), 1108146133Sharti (job->flags & JOB_IGNERR) ? 1109146133Sharti "(ignored)" : ""); 1110144467Sharti 1111144467Sharti if (job->flags & JOB_IGNERR) { 1112144467Sharti *status = 0; 1113144467Sharti } 1114144467Sharti } 1115144467Sharti 1116144467Sharti fflush(out); 1117146133Sharti } 1118146133Sharti } else if (WIFSIGNALED(*status)) { 1119146133Sharti if (done || DEBUG(JOB) || (WTERMSIG(*status) == SIGCONT)) { 1120146133Sharti FILE *out; 1121144467Sharti 1122146133Sharti if (compatMake && 1123146133Sharti !usePipes && 1124146133Sharti (job->flags & JOB_IGNERR)) { 1125146133Sharti /* 1126146133Sharti * If output is going to a file and this job 1127146133Sharti * is ignoring errors, arrange to have the 1128146133Sharti * exit status sent to the output file as 1129146133Sharti * well. 1130146133Sharti */ 1131146133Sharti out = fdopen(job->outFd, "w"); 1132146133Sharti if (out == NULL) 1133146133Sharti Punt("Cannot fdopen"); 1134146133Sharti } else { 1135146133Sharti out = stdout; 1136146133Sharti } 1137146133Sharti 1138146133Sharti if (WTERMSIG(*status) == SIGCONT) { 1139146133Sharti /* 1140146133Sharti * If the beastie has continued, shift the 1141146133Sharti * Job from the stopped list to the running 1142146133Sharti * one (or re-stop it if concurrency is 1143146133Sharti * exceeded) and go and get another child. 1144146133Sharti */ 1145146133Sharti if (job->flags & (JOB_RESUME | JOB_RESTART)) { 1146146133Sharti if (usePipes && job->node != lastNode) { 1147146133Sharti MESSAGE(out, job->node); 1148146133Sharti lastNode = job->node; 1149146133Sharti } 1150146133Sharti fprintf(out, "*** Continued\n"); 1151146133Sharti } 1152146133Sharti if (!(job->flags & JOB_CONTINUING)) { 1153146133Sharti DEBUGF(JOB, ("Warning: process %jd was not " 1154146133Sharti "continuing.\n", (intmax_t) job->pid)); 1155146133Sharti#ifdef notdef 1156146133Sharti /* 1157146133Sharti * We don't really want to restart a 1158146133Sharti * job from scratch just because it 1159146133Sharti * continued, especially not without 1160146133Sharti * killing the continuing process! 1161146133Sharti * That's why this is ifdef'ed out. 1162146133Sharti * FD - 9/17/90 1163146133Sharti */ 1164146133Sharti JobRestart(job); 1165146133Sharti#endif 1166146133Sharti } 1167146133Sharti job->flags &= ~JOB_CONTINUING; 1168146133Sharti TAILQ_INSERT_TAIL(&jobs, job, link); 1169146133Sharti nJobs += 1; 1170146133Sharti DEBUGF(JOB, ("Process %jd is continuing locally.\n", 1171146133Sharti (intmax_t) job->pid)); 1172146133Sharti if (nJobs == maxJobs) { 1173146133Sharti jobFull = TRUE; 1174146133Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1175146133Sharti } 1176146133Sharti fflush(out); 1177146133Sharti return; 1178146133Sharti 1179146133Sharti } else { 1180144467Sharti if (usePipes && job->node != lastNode) { 1181144467Sharti MESSAGE(out, job->node); 1182144467Sharti lastNode = job->node; 1183144467Sharti } 1184146133Sharti fprintf(out, 1185146133Sharti "*** Signal %d\n", WTERMSIG(*status)); 1186146133Sharti fflush(out); 1187144467Sharti } 1188146133Sharti } 1189146133Sharti } else { 1190146133Sharti /* STOPPED */ 1191146133Sharti FILE *out; 11921590Srgrimes 1193146133Sharti if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 1194146133Sharti /* 1195146133Sharti * If output is going to a file and this job 1196146133Sharti * is ignoring errors, arrange to have the 1197146133Sharti * exit status sent to the output file as 1198146133Sharti * well. 1199146133Sharti */ 1200146133Sharti out = fdopen(job->outFd, "w"); 1201146133Sharti if (out == NULL) 1202146133Sharti Punt("Cannot fdopen"); 1203144467Sharti } else { 1204146133Sharti out = stdout; 1205144467Sharti } 12061590Srgrimes 1207146133Sharti DEBUGF(JOB, ("Process %jd stopped.\n", (intmax_t) job->pid)); 1208146133Sharti if (usePipes && job->node != lastNode) { 1209146133Sharti MESSAGE(out, job->node); 1210146133Sharti lastNode = job->node; 1211146133Sharti } 1212146133Sharti fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status)); 1213146133Sharti job->flags |= JOB_RESUME; 1214146133Sharti TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 1215144467Sharti fflush(out); 1216146133Sharti return; 12171590Srgrimes } 12181590Srgrimes 12191590Srgrimes /* 1220144467Sharti * Now handle the -B-mode stuff. If the beast still isn't finished, 1221144467Sharti * try and restart the job on the next command. If JobStart says it's 1222144467Sharti * ok, it's ok. If there's an error, this puppy is done. 12231590Srgrimes */ 1224144467Sharti if (compatMake && WIFEXITED(*status) && 1225144467Sharti Lst_Succ(job->node->compat_command) != NULL) { 1226144467Sharti switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { 1227144467Sharti case JOB_RUNNING: 1228144467Sharti done = FALSE; 1229144467Sharti break; 1230144467Sharti case JOB_ERROR: 1231144467Sharti done = TRUE; 1232144467Sharti W_SETEXITSTATUS(status, 1); 1233144467Sharti break; 1234144467Sharti case JOB_FINISHED: 1235144467Sharti /* 1236144467Sharti * If we got back a JOB_FINISHED code, JobStart has 1237144467Sharti * already called Make_Update and freed the job 1238144467Sharti * descriptor. We set done to false here to avoid fake 1239144467Sharti * cycles and double frees. JobStart needs to do the 1240144467Sharti * update so we can proceed up the graph when given 1241144467Sharti * the -n flag.. 1242144467Sharti */ 1243144467Sharti done = FALSE; 1244144467Sharti break; 1245144467Sharti default: 1246144467Sharti break; 1247144467Sharti } 1248144467Sharti } else { 1249144467Sharti done = TRUE; 12501590Srgrimes } 1251143703Sharti 1252144657Sharti if (done && aborting != ABORT_ERROR && 1253144657Sharti aborting != ABORT_INTERRUPT && *status == 0) { 1254144467Sharti /* 1255144467Sharti * As long as we aren't aborting and the job didn't return a 1256144467Sharti * non-zero status that we shouldn't ignore, we call 1257144467Sharti * Make_Update to update the parents. In addition, any saved 1258144467Sharti * commands for the node are placed on the .END target. 1259144467Sharti */ 1260144467Sharti for (ln = job->tailCmds; ln != NULL; ln = LST_NEXT(ln)) { 1261144467Sharti Lst_AtEnd(&postCommands->commands, 1262146027Sharti Buf_Peel( 1263146027Sharti Var_Subst(Lst_Datum(ln), job->node, FALSE))); 1264144467Sharti } 12651590Srgrimes 1266144467Sharti job->node->made = MADE; 1267144467Sharti Make_Update(job->node); 1268144467Sharti free(job); 12691590Srgrimes 1270144467Sharti } else if (*status != 0) { 1271144467Sharti errors += 1; 1272144467Sharti free(job); 1273144467Sharti } 1274144467Sharti 1275144467Sharti JobRestartJobs(); 1276144467Sharti 12771590Srgrimes /* 1278144467Sharti * Set aborting if any error. 12791590Srgrimes */ 1280144657Sharti if (errors && !keepgoing && aborting != ABORT_INTERRUPT) { 1281144467Sharti /* 1282144467Sharti * If we found any errors in this batch of children and the -k 1283144467Sharti * flag wasn't given, we set the aborting flag so no more jobs 1284144467Sharti * get started. 1285144467Sharti */ 1286144467Sharti aborting = ABORT_ERROR; 1287144467Sharti } 12888874Srgrimes 1289144657Sharti if (aborting == ABORT_ERROR && Job_Empty()) { 1290144467Sharti /* 1291144467Sharti * If we are aborting and the job table is now empty, we finish. 1292144467Sharti */ 1293144467Sharti Finish(errors); 1294144467Sharti } 12951590Srgrimes} 12961590Srgrimes 1297144467Sharti/** 1298144467Sharti * Job_Touch 12991590Srgrimes * Touch the given target. Called by JobStart when the -t flag was 1300104696Sjmallett * given. Prints messages unless told to be silent. 13011590Srgrimes * 13021590Srgrimes * Side Effects: 13031590Srgrimes * The data modification of the file is changed. In addition, if the 13041590Srgrimes * file did not exist, it is created. 13051590Srgrimes */ 13061590Srgrimesvoid 1307104696SjmallettJob_Touch(GNode *gn, Boolean silent) 13081590Srgrimes{ 1309144467Sharti int streamID; /* ID of stream opened to do the touch */ 1310144467Sharti struct utimbuf times; /* Times for utime() call */ 13111590Srgrimes 1312144467Sharti if (gn->type & (OP_JOIN | OP_USE | OP_EXEC | OP_OPTIONAL)) { 1313144467Sharti /* 1314144467Sharti * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" 1315144467Sharti * targets and, as such, shouldn't really be created. 1316144467Sharti */ 1317144467Sharti return; 1318144467Sharti } 13198874Srgrimes 1320144467Sharti if (!silent) { 1321144467Sharti fprintf(stdout, "touch %s\n", gn->name); 1322144467Sharti fflush(stdout); 1323144467Sharti } 13241590Srgrimes 1325144467Sharti if (noExecute) { 1326144467Sharti return; 1327144467Sharti } 13281590Srgrimes 1329144467Sharti if (gn->type & OP_ARCHV) { 1330144467Sharti Arch_Touch(gn); 1331144467Sharti } else if (gn->type & OP_LIB) { 1332144467Sharti Arch_TouchLib(gn); 1333144467Sharti } else { 1334144467Sharti char *file = gn->path ? gn->path : gn->name; 13351590Srgrimes 1336144467Sharti times.actime = times.modtime = now; 1337144467Sharti if (utime(file, ×) < 0) { 1338144467Sharti streamID = open(file, O_RDWR | O_CREAT, 0666); 13391590Srgrimes 1340144467Sharti if (streamID >= 0) { 1341144467Sharti char c; 13421590Srgrimes 1343144467Sharti /* 1344144467Sharti * Read and write a byte to the file to change 1345144467Sharti * the modification time, then close the file. 1346144467Sharti */ 1347144467Sharti if (read(streamID, &c, 1) == 1) { 1348144467Sharti lseek(streamID, (off_t)0, SEEK_SET); 1349144467Sharti write(streamID, &c, 1); 1350144467Sharti } 1351144467Sharti 1352144467Sharti close(streamID); 1353144467Sharti } else { 1354144467Sharti fprintf(stdout, "*** couldn't touch %s: %s", 1355144467Sharti file, strerror(errno)); 1356144467Sharti fflush(stdout); 1357144467Sharti } 13581590Srgrimes } 13591590Srgrimes } 13601590Srgrimes} 13611590Srgrimes 1362144467Sharti/** 1363144467Sharti * Job_CheckCommands 13648874Srgrimes * Make sure the given node has all the commands it needs. 13651590Srgrimes * 13661590Srgrimes * Results: 13671590Srgrimes * TRUE if the commands list is/was ok. 13681590Srgrimes * 13691590Srgrimes * Side Effects: 13701590Srgrimes * The node will have commands from the .DEFAULT rule added to it 13711590Srgrimes * if it needs them. 13721590Srgrimes */ 13731590SrgrimesBoolean 1374104696SjmallettJob_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 13751590Srgrimes{ 1376138232Sharti 1377144467Sharti if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) && 1378144467Sharti (gn->type & OP_LIB) == 0) { 1379144467Sharti /* 1380144467Sharti * No commands. Look for .DEFAULT rule from which we might infer 1381144467Sharti * commands. 1382144467Sharti */ 1383144657Sharti if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) { 1384144467Sharti char *p1; 1385144467Sharti /* 1386144467Sharti * Make only looks for a .DEFAULT if the node was 1387144467Sharti * never the target of an operator, so that's what we 1388144467Sharti * do too. If a .DEFAULT was given, we substitute its 1389144467Sharti * commands for gn's commands and set the IMPSRC 1390144467Sharti * variable to be the target's name The DEFAULT node 1391144467Sharti * acts like a transformation rule, in that gn also 1392144467Sharti * inherits any attributes or sources attached to 1393144467Sharti * .DEFAULT itself. 1394144467Sharti */ 1395144467Sharti Make_HandleUse(DEFAULT, gn); 1396144467Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn); 1397144467Sharti free(p1); 139818730Ssteve 1399144467Sharti } else if (Dir_MTime(gn) == 0) { 1400144467Sharti /* 1401144467Sharti * The node wasn't the target of an operator we have 1402144467Sharti * no .DEFAULT rule to go on and the target doesn't 1403144467Sharti * already exist. There's nothing more we can do for 1404144467Sharti * this branch. If the -k flag wasn't given, we stop 1405144467Sharti * in our tracks, otherwise we just don't update 1406144467Sharti * this node's parents so they never get examined. 1407144467Sharti */ 1408144467Sharti static const char msg[] = 1409144467Sharti "make: don't know how to make"; 1410144467Sharti 1411144467Sharti if (gn->type & OP_OPTIONAL) { 1412144467Sharti fprintf(stdout, "%s %s(ignored)\n", 1413144467Sharti msg, gn->name); 1414144467Sharti fflush(stdout); 1415144467Sharti } else if (keepgoing) { 1416144467Sharti fprintf(stdout, "%s %s(continuing)\n", 1417144467Sharti msg, gn->name); 1418144467Sharti fflush(stdout); 1419144467Sharti return (FALSE); 1420144467Sharti } else { 142135483Simp#if OLD_JOKE 1422144467Sharti if (strcmp(gn->name,"love") == 0) 1423144467Sharti (*abortProc)("Not war."); 1424144467Sharti else 142535483Simp#endif 1426144467Sharti (*abortProc)("%s %s. Stop", 1427144467Sharti msg, gn->name); 1428144467Sharti return (FALSE); 1429144467Sharti } 1430144467Sharti } 14311590Srgrimes } 1432144467Sharti return (TRUE); 14331590Srgrimes} 14341590Srgrimes 1435144467Sharti/** 1436144467Sharti * JobExec 14371590Srgrimes * Execute the shell for the given job. Called from JobStart and 14381590Srgrimes * JobRestart. 14391590Srgrimes * 14401590Srgrimes * Side Effects: 14411590Srgrimes * A shell is executed, outputs is altered and the Job structure added 14421590Srgrimes * to the job table. 14431590Srgrimes */ 14441590Srgrimesstatic void 1445104696SjmallettJobExec(Job *job, char **argv) 14461590Srgrimes{ 1447146129Sharti ProcStuff ps; 14488874Srgrimes 1449144467Sharti if (DEBUG(JOB)) { 1450146061Sharti int i; 14518874Srgrimes 1452144467Sharti DEBUGF(JOB, ("Running %s\n", job->node->name)); 1453144467Sharti DEBUGF(JOB, ("\tCommand: ")); 1454144467Sharti for (i = 0; argv[i] != NULL; i++) { 1455144467Sharti DEBUGF(JOB, ("%s ", argv[i])); 1456144467Sharti } 1457144467Sharti DEBUGF(JOB, ("\n")); 14581590Srgrimes } 14598874Srgrimes 14601590Srgrimes /* 1461144467Sharti * Some jobs produce no output and it's disconcerting to have 1462144467Sharti * no feedback of their running (since they produce no output, the 1463144467Sharti * banner with their name in it never appears). This is an attempt to 1464144467Sharti * provide that feedback, even if nothing follows it. 14651590Srgrimes */ 1466144657Sharti if (lastNode != job->node && (job->flags & JOB_FIRST) && 1467144467Sharti !(job->flags & JOB_SILENT)) { 1468144467Sharti MESSAGE(stdout, job->node); 1469144467Sharti lastNode = job->node; 14701590Srgrimes } 14711590Srgrimes 1472146129Sharti ps.in = FILENO(job->cmdFILE); 1473146129Sharti if (usePipes) { 1474146129Sharti /* 1475146129Sharti * Set up the child's output to be routed through the 1476146129Sharti * pipe we've created for it. 1477146129Sharti */ 1478146129Sharti ps.out = job->outPipe; 1479146129Sharti } else { 1480146129Sharti /* 1481146129Sharti * We're capturing output in a file, so we duplicate 1482146129Sharti * the descriptor to the temporary file into the 1483146129Sharti * standard output. 1484146129Sharti */ 1485146129Sharti ps.out = job->outFd; 1486146129Sharti } 1487146129Sharti ps.err = STDERR_FILENO; 1488146129Sharti 1489146129Sharti ps.merge_errors = 1; 1490146129Sharti ps.pgroup = 1; 1491146129Sharti ps.searchpath = 0; 1492146129Sharti 1493146129Sharti ps.argv = argv; 1494146129Sharti 1495146129Sharti /* 1496146129Sharti * Fork. Warning since we are doing vfork() instead of fork(), 1497146129Sharti * do not allocate memory in the child process! 1498146129Sharti */ 1499146130Sharti if ((ps.child_pid = vfork()) == -1) { 1500144467Sharti Punt("Cannot fork"); 1501144467Sharti 1502146130Sharti 1503146130Sharti } else if (ps.child_pid == 0) { 1504144665Sharti /* 1505144665Sharti * Child 1506144665Sharti */ 1507144467Sharti if (fifoFd >= 0) 1508144467Sharti close(fifoFd); 1509144467Sharti 1510146129Sharti ProcExec(&ps); 1511146129Sharti /* NOTREACHED */ 1512144665Sharti } 1513146130Sharti 1514144665Sharti /* 1515144665Sharti * Parent 1516144665Sharti */ 1517146130Sharti job->pid = ps.child_pid; 1518144467Sharti 1519144665Sharti if (usePipes && (job->flags & JOB_FIRST)) { 1520144665Sharti /* 1521144665Sharti * The first time a job is run for a node, we set the 1522144665Sharti * current position in the buffer to the beginning and 1523144665Sharti * mark another stream to watch in the outputs mask. 1524144665Sharti */ 1525104475Sphk#ifdef USE_KQUEUE 1526144665Sharti struct kevent kev[2]; 1527104475Sphk#endif 1528144665Sharti job->curPos = 0; 15298874Srgrimes 1530137202Sharti#if defined(USE_KQUEUE) 1531144665Sharti EV_SET(&kev[0], job->inPipe, EVFILT_READ, EV_ADD, 0, 0, job); 1532144665Sharti EV_SET(&kev[1], job->pid, EVFILT_PROC, 1533144665Sharti EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, NULL); 1534144665Sharti if (kevent(kqfd, kev, 2, NULL, 0, NULL) != 0) { 1535144665Sharti /* 1536144665Sharti * kevent() will fail if the job is already 1537144665Sharti * finished 1538144665Sharti */ 1539144665Sharti if (errno != EINTR && errno != EBADF && errno != ESRCH) 1540144665Sharti Punt("kevent: %s", strerror(errno)); 1541144665Sharti } 15421590Srgrimes#else 1543144665Sharti FD_SET(job->inPipe, &outputs); 1544137202Sharti#endif /* USE_KQUEUE */ 1545144665Sharti } 1546144467Sharti 1547144665Sharti if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1548144665Sharti fclose(job->cmdFILE); 1549144665Sharti job->cmdFILE = NULL; 15501590Srgrimes } 15511590Srgrimes 1552144467Sharti /* 1553144467Sharti * Now the job is actually running, add it to the table. 1554144467Sharti */ 1555144467Sharti nJobs += 1; 1556144494Sharti TAILQ_INSERT_TAIL(&jobs, job, link); 1557144467Sharti if (nJobs == maxJobs) { 1558144467Sharti jobFull = TRUE; 15591590Srgrimes } 15601590Srgrimes} 15611590Srgrimes 1562144467Sharti/** 1563144467Sharti * JobMakeArgv 15641590Srgrimes * Create the argv needed to execute the shell for a given job. 15651590Srgrimes */ 15661590Srgrimesstatic void 1567104696SjmallettJobMakeArgv(Job *job, char **argv) 15681590Srgrimes{ 1569144467Sharti int argc; 1570144467Sharti static char args[10]; /* For merged arguments */ 15718874Srgrimes 1572144467Sharti argv[0] = shellName; 1573144467Sharti argc = 1; 15741590Srgrimes 1575144657Sharti if ((commandShell->exit && *commandShell->exit != '-') || 1576144657Sharti (commandShell->echo && *commandShell->echo != '-')) { 1577144467Sharti /* 1578144467Sharti * At least one of the flags doesn't have a minus before it, so 1579144467Sharti * merge them together. Have to do this because the *(&(@*#*&#$# 1580144467Sharti * Bourne shell thinks its second argument is a file to source. 1581144467Sharti * Grrrr. Note the ten-character limitation on the combined 1582144467Sharti * arguments. 1583144467Sharti */ 1584144657Sharti sprintf(args, "-%s%s", (job->flags & JOB_IGNERR) ? "" : 1585144657Sharti commandShell->exit ? commandShell->exit : "", 1586144657Sharti (job->flags & JOB_SILENT) ? "" : 1587144657Sharti commandShell->echo ? commandShell->echo : ""); 15881590Srgrimes 1589144467Sharti if (args[1]) { 1590144467Sharti argv[argc] = args; 1591144467Sharti argc++; 1592144467Sharti } 1593144467Sharti } else { 1594144467Sharti if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1595144467Sharti argv[argc] = commandShell->exit; 1596144467Sharti argc++; 1597144467Sharti } 1598144467Sharti if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1599144467Sharti argv[argc] = commandShell->echo; 1600144467Sharti argc++; 1601144467Sharti } 16021590Srgrimes } 1603144467Sharti argv[argc] = NULL; 16041590Srgrimes} 16051590Srgrimes 1606144467Sharti/** 1607144467Sharti * JobRestart 1608144494Sharti * Restart a job that stopped for some reason. The job must be neither 1609144494Sharti * on the jobs nor on the stoppedJobs list. 16101590Srgrimes * 16111590Srgrimes * Side Effects: 16121590Srgrimes * jobFull will be set if the job couldn't be run. 16131590Srgrimes */ 16141590Srgrimesstatic void 1615104696SjmallettJobRestart(Job *job) 16161590Srgrimes{ 161718730Ssteve 1618144467Sharti if (job->flags & JOB_RESTART) { 1619144467Sharti /* 1620144467Sharti * Set up the control arguments to the shell. This is based on 1621144467Sharti * the flags set earlier for this job. If the JOB_IGNERR flag 1622144467Sharti * is clear, the 'exit' flag of the commandShell is used to 1623144467Sharti * cause it to exit upon receiving an error. If the JOB_SILENT 1624144467Sharti * flag is clear, the 'echo' flag of the commandShell is used 1625144467Sharti * to get it to start echoing as soon as it starts 1626144467Sharti * processing commands. 1627144467Sharti */ 1628144467Sharti char *argv[4]; 16298874Srgrimes 1630144467Sharti JobMakeArgv(job, argv); 16318874Srgrimes 1632144467Sharti DEBUGF(JOB, ("Restarting %s...", job->node->name)); 1633144657Sharti if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL)) { 1634144467Sharti /* 1635144657Sharti * Not allowed to run -- put it back on the hold 1636144657Sharti * queue and mark the table full 1637144467Sharti */ 1638144467Sharti DEBUGF(JOB, ("holding\n")); 1639144494Sharti TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1640144467Sharti jobFull = TRUE; 1641144467Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1642144467Sharti return; 1643144467Sharti } else { 1644144467Sharti /* 1645144467Sharti * Job may be run locally. 1646144467Sharti */ 1647144467Sharti DEBUGF(JOB, ("running locally\n")); 1648144467Sharti } 1649144467Sharti JobExec(job, argv); 1650144467Sharti 1651137202Sharti } else { 16521590Srgrimes /* 1653144467Sharti * The job has stopped and needs to be restarted. 1654144467Sharti * Why it stopped, we don't know... 16551590Srgrimes */ 1656144467Sharti DEBUGF(JOB, ("Resuming %s...", job->node->name)); 1657144657Sharti if ((nJobs < maxJobs || ((job->flags & JOB_SPECIAL) && 1658144657Sharti maxJobs == 0)) && nJobs != maxJobs) { 1659144467Sharti /* 1660144467Sharti * If we haven't reached the concurrency limit already 1661144467Sharti * (or the job must be run and maxJobs is 0), it's ok 1662144467Sharti * to resume it. 1663144467Sharti */ 1664144467Sharti Boolean error; 1665144467Sharti int status; 16668874Srgrimes 1667144467Sharti error = (KILL(job->pid, SIGCONT) != 0); 1668144467Sharti 1669144467Sharti if (!error) { 1670144467Sharti /* 1671144467Sharti * Make sure the user knows we've continued 1672144467Sharti * the beast and actually put the thing in the 1673144467Sharti * job table. 1674144467Sharti */ 1675144467Sharti job->flags |= JOB_CONTINUING; 1676144467Sharti status = 0; 1677144467Sharti W_SETTERMSIG(&status, SIGCONT); 1678144467Sharti JobFinish(job, &status); 1679144467Sharti 1680144467Sharti job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 1681144467Sharti DEBUGF(JOB, ("done\n")); 1682144467Sharti } else { 1683144467Sharti Error("couldn't resume %s: %s", 1684144467Sharti job->node->name, strerror(errno)); 1685144467Sharti status = 0; 1686144467Sharti W_SETEXITSTATUS(&status, 1); 1687144467Sharti JobFinish(job, &status); 1688144467Sharti } 1689144467Sharti } else { 1690144467Sharti /* 1691144467Sharti * Job cannot be restarted. Mark the table as full and 1692144467Sharti * place the job back on the list of stopped jobs. 1693144467Sharti */ 1694144467Sharti DEBUGF(JOB, ("table full\n")); 1695144494Sharti TAILQ_INSERT_HEAD(&stoppedJobs, job, link); 1696144467Sharti jobFull = TRUE; 1697144467Sharti DEBUGF(JOB, ("Job queue is full.\n")); 1698144467Sharti } 16991590Srgrimes } 17001590Srgrimes} 17011590Srgrimes 1702144467Sharti/** 1703144467Sharti * JobStart 17041590Srgrimes * Start a target-creation process going for the target described 17058874Srgrimes * by the graph node gn. 17061590Srgrimes * 17071590Srgrimes * Results: 17081590Srgrimes * JOB_ERROR if there was an error in the commands, JOB_FINISHED 17091590Srgrimes * if there isn't actually anything left to do for the job and 17101590Srgrimes * JOB_RUNNING if the job has been started. 17111590Srgrimes * 17121590Srgrimes * Side Effects: 17131590Srgrimes * A new Job node is created and added to the list of running 17141590Srgrimes * jobs. PMake is forked and a child shell created. 17151590Srgrimes */ 17161590Srgrimesstatic int 1717104696SjmallettJobStart(GNode *gn, int flags, Job *previous) 17181590Srgrimes{ 1719144467Sharti Job *job; /* new job descriptor */ 1720144467Sharti char *argv[4]; /* Argument vector to shell */ 1721144467Sharti Boolean cmdsOK; /* true if the nodes commands were all right */ 1722144467Sharti Boolean noExec; /* Set true if we decide not to run the job */ 1723144467Sharti int tfd; /* File descriptor for temp file */ 1724144467Sharti LstNode *ln; 1725144654Sharti char tfile[sizeof(TMPPAT)]; 17261590Srgrimes 1727144467Sharti if (interrupted) { 1728144467Sharti JobPassSig(interrupted); 1729144467Sharti return (JOB_ERROR); 1730144467Sharti } 1731144467Sharti if (previous != NULL) { 1732144467Sharti previous->flags &= ~(JOB_FIRST | JOB_IGNERR | JOB_SILENT); 1733144467Sharti job = previous; 1734144467Sharti } else { 1735144467Sharti job = emalloc(sizeof(Job)); 1736144467Sharti flags |= JOB_FIRST; 1737144467Sharti } 17381590Srgrimes 1739144467Sharti job->node = gn; 1740144467Sharti job->tailCmds = NULL; 17411590Srgrimes 17421590Srgrimes /* 1743144467Sharti * Set the initial value of the flags for this job based on the global 1744144467Sharti * ones and the node's attributes... Any flags supplied by the caller 1745144467Sharti * are also added to the field. 17461590Srgrimes */ 1747144467Sharti job->flags = 0; 1748144467Sharti if (Targ_Ignore(gn)) { 1749144467Sharti job->flags |= JOB_IGNERR; 17501590Srgrimes } 1751144467Sharti if (Targ_Silent(gn)) { 1752144467Sharti job->flags |= JOB_SILENT; 1753144467Sharti } 1754144467Sharti job->flags |= flags; 17558874Srgrimes 17561590Srgrimes /* 1757144467Sharti * Check the commands now so any attributes from .DEFAULT have a chance 1758144658Sharti * to migrate to the node. 17591590Srgrimes */ 1760144658Sharti if (!compatMake && (job->flags & JOB_FIRST)) { 1761144467Sharti cmdsOK = Job_CheckCommands(gn, Error); 1762144467Sharti } else { 1763144467Sharti cmdsOK = TRUE; 1764144467Sharti } 17651590Srgrimes 17661590Srgrimes /* 1767144467Sharti * If the -n flag wasn't given, we open up OUR (not the child's) 1768144467Sharti * temporary file to stuff commands in it. The thing is rd/wr so we 1769144467Sharti * don't need to reopen it to feed it to the shell. If the -n flag 1770144467Sharti * *was* given, we just set the file to be stdout. Cute, huh? 17711590Srgrimes */ 1772144467Sharti if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 1773144467Sharti /* 1774144467Sharti * We're serious here, but if the commands were bogus, we're 1775144467Sharti * also dead... 1776144467Sharti */ 1777144467Sharti if (!cmdsOK) { 1778144467Sharti DieHorribly(); 1779144467Sharti } 17808874Srgrimes 1781144467Sharti strcpy(tfile, TMPPAT); 1782144467Sharti if ((tfd = mkstemp(tfile)) == -1) 1783144467Sharti Punt("Cannot create temp file: %s", strerror(errno)); 1784144467Sharti job->cmdFILE = fdopen(tfd, "w+"); 1785144467Sharti eunlink(tfile); 1786144467Sharti if (job->cmdFILE == NULL) { 1787144467Sharti close(tfd); 1788144467Sharti Punt("Could not open %s", tfile); 1789144467Sharti } 1790144467Sharti fcntl(FILENO(job->cmdFILE), F_SETFD, 1); 1791144467Sharti /* 1792144467Sharti * Send the commands to the command file, flush all its 1793144467Sharti * buffers then rewind and remove the thing. 1794144467Sharti */ 1795144467Sharti noExec = FALSE; 1796138564Sharti 1797138564Sharti /* 1798144467Sharti * Used to be backwards; replace when start doing multiple 1799144467Sharti * commands per shell. 1800138564Sharti */ 1801144467Sharti if (compatMake) { 1802144467Sharti /* 1803144467Sharti * Be compatible: If this is the first time for this 1804144467Sharti * node, verify its commands are ok and open the 1805144467Sharti * commands list for sequential access by later 1806144467Sharti * invocations of JobStart. Once that is done, we take 1807144467Sharti * the next command off the list and print it to the 1808144467Sharti * command file. If the command was an ellipsis, note 1809144467Sharti * that there's nothing more to execute. 1810144467Sharti */ 1811144467Sharti if (job->flags & JOB_FIRST) 1812144467Sharti gn->compat_command = Lst_First(&gn->commands); 1813144467Sharti else 1814144467Sharti gn->compat_command = 1815144467Sharti Lst_Succ(gn->compat_command); 18168874Srgrimes 1817144467Sharti if (gn->compat_command == NULL || 1818144467Sharti JobPrintCommand(Lst_Datum(gn->compat_command), job)) 1819144467Sharti noExec = TRUE; 1820144467Sharti 1821144467Sharti if (noExec && !(job->flags & JOB_FIRST)) { 1822144467Sharti /* 1823144467Sharti * If we're not going to execute anything, the 1824144467Sharti * job is done and we need to close down the 1825144467Sharti * various file descriptors we've opened for 1826144467Sharti * output, then call JobDoOutput to catch the 1827144467Sharti * final characters or send the file to the 1828144467Sharti * screen... Note that the i/o streams are only 1829144467Sharti * open if this isn't the first job. Note also 1830144467Sharti * that this could not be done in 1831144467Sharti * Job_CatchChildren b/c it wasn't clear if 1832144467Sharti * there were more commands to execute or not... 1833144467Sharti */ 1834144467Sharti JobClose(job); 1835144467Sharti } 1836144467Sharti } else { 1837144467Sharti /* 1838144467Sharti * We can do all the commands at once. hooray for sanity 1839144467Sharti */ 1840144467Sharti numCommands = 0; 1841144467Sharti LST_FOREACH(ln, &gn->commands) { 1842144467Sharti if (JobPrintCommand(Lst_Datum(ln), job)) 1843144467Sharti break; 1844144467Sharti } 1845144467Sharti 1846144467Sharti /* 1847144467Sharti * If we didn't print out any commands to the shell 1848144467Sharti * script, there's not much point in executing the 1849144467Sharti * shell, is there? 1850144467Sharti */ 1851144467Sharti if (numCommands == 0) { 1852144467Sharti noExec = TRUE; 1853144467Sharti } 1854144467Sharti } 1855144467Sharti 1856144467Sharti } else if (noExecute) { 1857144467Sharti /* 1858144467Sharti * Not executing anything -- just print all the commands to 1859144467Sharti * stdout in one fell swoop. This will still set up 1860144467Sharti * job->tailCmds correctly. 1861144467Sharti */ 1862144467Sharti if (lastNode != gn) { 1863144467Sharti MESSAGE(stdout, gn); 1864144467Sharti lastNode = gn; 1865144467Sharti } 1866144467Sharti job->cmdFILE = stdout; 1867144467Sharti 1868144467Sharti /* 1869144467Sharti * Only print the commands if they're ok, but don't die if 1870144467Sharti * they're not -- just let the user know they're bad and keep 1871144467Sharti * going. It doesn't do any harm in this case and may do 1872144467Sharti * some good. 1873144467Sharti */ 1874144467Sharti if (cmdsOK) { 1875144467Sharti LST_FOREACH(ln, &gn->commands) { 1876144467Sharti if (JobPrintCommand(Lst_Datum(ln), job)) 1877144467Sharti break; 1878144467Sharti } 1879144467Sharti } 1880144467Sharti /* 1881144467Sharti * Don't execute the shell, thank you. 1882144467Sharti */ 18831590Srgrimes noExec = TRUE; 1884144467Sharti 1885144467Sharti } else { 1886144467Sharti /* 1887144467Sharti * Just touch the target and note that no shell should be 1888144467Sharti * executed. Set cmdFILE to stdout to make life easier. Check 1889144467Sharti * the commands, too, but don't die if they're no good -- it 1890144467Sharti * does no harm to keep working up the graph. 1891144467Sharti */ 1892144467Sharti job->cmdFILE = stdout; 1893144467Sharti Job_Touch(gn, job->flags & JOB_SILENT); 1894144467Sharti noExec = TRUE; 18951590Srgrimes } 1896144467Sharti 18971590Srgrimes /* 1898144467Sharti * If we're not supposed to execute a shell, don't. 18991590Srgrimes */ 1900144467Sharti if (noExec) { 1901144467Sharti /* 1902144467Sharti * Unlink and close the command file if we opened one 1903144467Sharti */ 1904144467Sharti if (job->cmdFILE != stdout) { 1905144467Sharti if (job->cmdFILE != NULL) 1906144467Sharti fclose(job->cmdFILE); 1907144467Sharti } else { 1908144467Sharti fflush(stdout); 1909144467Sharti } 1910144467Sharti 1911144467Sharti /* 1912144467Sharti * We only want to work our way up the graph if we aren't here 1913144467Sharti * because the commands for the job were no good. 1914144467Sharti */ 1915144467Sharti if (cmdsOK) { 1916144467Sharti if (aborting == 0) { 1917144467Sharti for (ln = job->tailCmds; ln != NULL; 1918144467Sharti ln = LST_NEXT(ln)) { 1919144467Sharti Lst_AtEnd(&postCommands->commands, 1920146027Sharti Buf_Peel(Var_Subst(Lst_Datum(ln), 1921146027Sharti job->node, FALSE))); 1922144467Sharti } 1923144467Sharti job->node->made = MADE; 1924144467Sharti Make_Update(job->node); 1925144467Sharti } 1926144467Sharti free(job); 1927144467Sharti return(JOB_FINISHED); 1928144467Sharti } else { 1929144467Sharti free(job); 1930144467Sharti return(JOB_ERROR); 1931144467Sharti } 1932144467Sharti } else { 1933144467Sharti fflush(job->cmdFILE); 19341590Srgrimes } 1935144467Sharti 19361590Srgrimes /* 1937144467Sharti * Set up the control arguments to the shell. This is based on the flags 1938144467Sharti * set earlier for this job. 19391590Srgrimes */ 1940144467Sharti JobMakeArgv(job, argv); 19411590Srgrimes 19421590Srgrimes /* 1943144467Sharti * If we're using pipes to catch output, create the pipe by which we'll 1944144467Sharti * get the shell's output. If we're using files, print out that we're 1945144467Sharti * starting a job and then set up its temporary-file name. 19461590Srgrimes */ 1947144467Sharti if (!compatMake || (job->flags & JOB_FIRST)) { 1948144467Sharti if (usePipes) { 1949144467Sharti int fd[2]; 19501590Srgrimes 1951144467Sharti if (pipe(fd) == -1) 1952144467Sharti Punt("Cannot create pipe: %s", strerror(errno)); 1953144467Sharti job->inPipe = fd[0]; 1954144467Sharti job->outPipe = fd[1]; 1955144467Sharti fcntl(job->inPipe, F_SETFD, 1); 1956144467Sharti fcntl(job->outPipe, F_SETFD, 1); 1957144467Sharti } else { 1958144467Sharti fprintf(stdout, "Remaking `%s'\n", gn->name); 1959144467Sharti fflush(stdout); 1960144467Sharti strcpy(job->outFile, TMPPAT); 1961144467Sharti if ((job->outFd = mkstemp(job->outFile)) == -1) 1962144467Sharti Punt("cannot create temp file: %s", 1963144467Sharti strerror(errno)); 1964144467Sharti fcntl(job->outFd, F_SETFD, 1); 19651590Srgrimes } 19661590Srgrimes } 19671590Srgrimes 1968144657Sharti if (nJobs >= maxJobs && !(job->flags & JOB_SPECIAL) && maxJobs != 0) { 1969144467Sharti /* 1970144467Sharti * We've hit the limit of concurrency, so put the job on hold 1971144467Sharti * until some other job finishes. Note that the special jobs 1972144467Sharti * (.BEGIN, .INTERRUPT and .END) may be run even when the 1973144467Sharti * limit has been reached (e.g. when maxJobs == 0). 1974144467Sharti */ 1975144467Sharti jobFull = TRUE; 19761590Srgrimes 1977144467Sharti DEBUGF(JOB, ("Can only run job locally.\n")); 1978144467Sharti job->flags |= JOB_RESTART; 1979144494Sharti TAILQ_INSERT_TAIL(&stoppedJobs, job, link); 19801590Srgrimes } else { 1981144467Sharti if (nJobs >= maxJobs) { 1982144467Sharti /* 1983144657Sharti * If we're running this job as a special case 1984144467Sharti * (see above), at least say the table is full. 1985144467Sharti */ 1986144467Sharti jobFull = TRUE; 1987144467Sharti DEBUGF(JOB, ("Local job queue is full.\n")); 1988144467Sharti } 1989144467Sharti JobExec(job, argv); 19901590Srgrimes } 1991144467Sharti return (JOB_RUNNING); 19921590Srgrimes} 19931590Srgrimes 199418730Sstevestatic char * 1995104696SjmallettJobOutput(Job *job, char *cp, char *endp, int msg) 199618730Ssteve{ 1997144467Sharti char *ecp; 199818730Ssteve 1999144467Sharti if (commandShell->noPrint) { 2000144467Sharti ecp = strstr(cp, commandShell->noPrint); 2001144467Sharti while (ecp != NULL) { 2002144467Sharti if (cp != ecp) { 2003144467Sharti *ecp = '\0'; 2004144467Sharti if (msg && job->node != lastNode) { 2005144467Sharti MESSAGE(stdout, job->node); 2006144467Sharti lastNode = job->node; 2007144467Sharti } 2008144467Sharti /* 2009144467Sharti * The only way there wouldn't be a newline 2010144467Sharti * after this line is if it were the last in 2011144467Sharti * the buffer. However, since the non-printable 2012144467Sharti * comes after it, there must be a newline, so 2013144467Sharti * we don't print one. 2014144467Sharti */ 2015144467Sharti fprintf(stdout, "%s", cp); 2016144467Sharti fflush(stdout); 2017144467Sharti } 2018144741Sharti cp = ecp + strlen(commandShell->noPrint); 2019144467Sharti if (cp != endp) { 2020144467Sharti /* 2021144467Sharti * Still more to print, look again after 2022144467Sharti * skipping the whitespace following the 2023144467Sharti * non-printable command.... 2024144467Sharti */ 2025144467Sharti cp++; 2026144467Sharti while (*cp == ' ' || *cp == '\t' || 2027144467Sharti *cp == '\n') { 2028144467Sharti cp++; 2029144467Sharti } 2030144467Sharti ecp = strstr(cp, commandShell->noPrint); 2031144467Sharti } else { 2032144467Sharti return (cp); 2033144467Sharti } 203418730Ssteve } 203518730Ssteve } 2036144467Sharti return (cp); 203718730Ssteve} 203818730Ssteve 2039144467Sharti/** 2040144467Sharti * JobDoOutput 20411590Srgrimes * This function is called at different times depending on 20421590Srgrimes * whether the user has specified that output is to be collected 20431590Srgrimes * via pipes or temporary files. In the former case, we are called 20441590Srgrimes * whenever there is something to read on the pipe. We collect more 20451590Srgrimes * output from the given job and store it in the job's outBuf. If 20461590Srgrimes * this makes up a line, we print it tagged by the job's identifier, 20471590Srgrimes * as necessary. 20481590Srgrimes * If output has been collected in a temporary file, we open the 20491590Srgrimes * file and read it line by line, transfering it to our own 20501590Srgrimes * output channel until the file is empty. At which point we 20511590Srgrimes * remove the temporary file. 20521590Srgrimes * In both cases, however, we keep our figurative eye out for the 20531590Srgrimes * 'noPrint' line for the shell from which the output came. If 20541590Srgrimes * we recognize a line, we don't print it. If the command is not 20551590Srgrimes * alone on the line (the character after it is not \0 or \n), we 20561590Srgrimes * do print whatever follows it. 20571590Srgrimes * 20581590Srgrimes * Side Effects: 20591590Srgrimes * curPos may be shifted as may the contents of outBuf. 20601590Srgrimes */ 2061144656Shartistatic void 2062104696SjmallettJobDoOutput(Job *job, Boolean finish) 20631590Srgrimes{ 2064144467Sharti Boolean gotNL = FALSE; /* true if got a newline */ 2065144467Sharti Boolean fbuf; /* true if our buffer filled up */ 2066144467Sharti int nr; /* number of bytes read */ 2067144467Sharti int i; /* auxiliary index into outBuf */ 2068144467Sharti int max; /* limit for i (end of current data) */ 2069144467Sharti int nRead; /* (Temporary) number of bytes read */ 2070144467Sharti FILE *oFILE; /* Stream pointer to shell's output file */ 2071144467Sharti char inLine[132]; 20721590Srgrimes 2073144467Sharti if (usePipes) { 20741590Srgrimes /* 2075144467Sharti * Read as many bytes as will fit in the buffer. 20761590Srgrimes */ 2077144467Sharti end_loop: 2078144467Sharti gotNL = FALSE; 2079144467Sharti fbuf = FALSE; 20808874Srgrimes 2081144467Sharti nRead = read(job->inPipe, &job->outBuf[job->curPos], 2082144467Sharti JOB_BUFSIZE - job->curPos); 20831590Srgrimes /* 2084144467Sharti * Check for interrupt here too, because the above read may 2085144467Sharti * block when the child process is stopped. In this case the 2086144467Sharti * interrupt will unblock it (we don't use SA_RESTART). 20871590Srgrimes */ 2088144467Sharti if (interrupted) 2089144467Sharti JobPassSig(interrupted); 20901590Srgrimes 2091144467Sharti if (nRead < 0) { 2092144467Sharti DEBUGF(JOB, ("JobDoOutput(piperead)")); 2093144467Sharti nr = 0; 2094144467Sharti } else { 2095144467Sharti nr = nRead; 2096144467Sharti } 20971590Srgrimes 20981590Srgrimes /* 2099144467Sharti * If we hit the end-of-file (the job is dead), we must flush 2100144467Sharti * its remaining output, so pretend we read a newline if 2101144467Sharti * there's any output remaining in the buffer. 2102144467Sharti * Also clear the 'finish' flag so we stop looping. 21031590Srgrimes */ 2104144657Sharti if (nr == 0 && job->curPos != 0) { 2105144467Sharti job->outBuf[job->curPos] = '\n'; 2106144467Sharti nr = 1; 2107144467Sharti finish = FALSE; 2108144467Sharti } else if (nr == 0) { 2109144467Sharti finish = FALSE; 21101590Srgrimes } 21118874Srgrimes 21121590Srgrimes /* 2113144467Sharti * Look for the last newline in the bytes we just got. If there 2114144467Sharti * is one, break out of the loop with 'i' as its index and 2115144467Sharti * gotNL set TRUE. 2116144467Sharti */ 2117144467Sharti max = job->curPos + nr; 2118144467Sharti for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 2119144467Sharti if (job->outBuf[i] == '\n') { 2120144467Sharti gotNL = TRUE; 2121144467Sharti break; 2122144467Sharti } else if (job->outBuf[i] == '\0') { 2123144467Sharti /* 2124144467Sharti * Why? 2125144467Sharti */ 2126144467Sharti job->outBuf[i] = ' '; 2127144467Sharti } 2128144467Sharti } 21291590Srgrimes 2130144467Sharti if (!gotNL) { 2131144467Sharti job->curPos += nr; 2132144467Sharti if (job->curPos == JOB_BUFSIZE) { 2133144467Sharti /* 2134144467Sharti * If we've run out of buffer space, we have 2135144467Sharti * no choice but to print the stuff. sigh. 2136144467Sharti */ 2137144467Sharti fbuf = TRUE; 2138144467Sharti i = job->curPos; 2139144467Sharti } 21401590Srgrimes } 2141144467Sharti if (gotNL || fbuf) { 2142144467Sharti /* 2143144467Sharti * Need to send the output to the screen. Null terminate 2144144467Sharti * it first, overwriting the newline character if there 2145144467Sharti * was one. So long as the line isn't one we should 2146144467Sharti * filter (according to the shell description), we print 2147144467Sharti * the line, preceded by a target banner if this target 2148144467Sharti * isn't the same as the one for which we last printed 2149144467Sharti * something. The rest of the data in the buffer are 2150144467Sharti * then shifted down to the start of the buffer and 2151144467Sharti * curPos is set accordingly. 2152144467Sharti */ 2153144467Sharti job->outBuf[i] = '\0'; 2154144467Sharti if (i >= job->curPos) { 2155144467Sharti char *cp; 21561590Srgrimes 2157144467Sharti cp = JobOutput(job, job->outBuf, 2158144467Sharti &job->outBuf[i], FALSE); 2159144467Sharti 2160144467Sharti /* 2161144467Sharti * There's still more in that buffer. This time, 2162144467Sharti * though, we know there's no newline at the 2163144467Sharti * end, so we add one of our own free will. 2164144467Sharti */ 2165144467Sharti if (*cp != '\0') { 2166144467Sharti if (job->node != lastNode) { 2167144467Sharti MESSAGE(stdout, job->node); 2168144467Sharti lastNode = job->node; 2169144467Sharti } 2170144467Sharti fprintf(stdout, "%s%s", cp, 2171144467Sharti gotNL ? "\n" : ""); 2172144467Sharti fflush(stdout); 2173144467Sharti } 2174144467Sharti } 2175144467Sharti if (i < max - 1) { 2176144467Sharti /* shift the remaining characters down */ 2177144467Sharti memcpy(job->outBuf, &job->outBuf[i + 1], 2178144467Sharti max - (i + 1)); 2179144467Sharti job->curPos = max - (i + 1); 2180144467Sharti 2181144467Sharti } else { 2182144467Sharti /* 2183144467Sharti * We have written everything out, so we just 2184144467Sharti * start over from the start of the buffer. 2185144467Sharti * No copying. No nothing. 2186144467Sharti */ 2187144467Sharti job->curPos = 0; 2188144467Sharti } 2189144467Sharti } 2190144467Sharti if (finish) { 2191144467Sharti /* 2192144467Sharti * If the finish flag is true, we must loop until we hit 2193144467Sharti * end-of-file on the pipe. This is guaranteed to happen 2194144467Sharti * eventually since the other end of the pipe is now 2195144467Sharti * closed (we closed it explicitly and the child has 2196144467Sharti * exited). When we do get an EOF, finish will be set 2197144467Sharti * FALSE and we'll fall through and out. 2198144467Sharti */ 2199144467Sharti goto end_loop; 2200144467Sharti } 2201144467Sharti 2202144467Sharti } else { 22031590Srgrimes /* 2204144467Sharti * We've been called to retrieve the output of the job from the 2205144467Sharti * temporary file where it's been squirreled away. This consists 2206144467Sharti * of opening the file, reading the output line by line, being 2207144467Sharti * sure not to print the noPrint line for the shell we used, 2208144467Sharti * then close and remove the temporary file. Very simple. 2209144467Sharti * 2210144467Sharti * Change to read in blocks and do FindSubString type things 2211144467Sharti * as for pipes? That would allow for "@echo -n..." 22121590Srgrimes */ 2213144467Sharti oFILE = fopen(job->outFile, "r"); 2214144467Sharti if (oFILE != NULL) { 2215144467Sharti fprintf(stdout, "Results of making %s:\n", 2216144467Sharti job->node->name); 2217144467Sharti fflush(stdout); 2218144467Sharti 2219144467Sharti while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 2220144467Sharti char *cp, *endp, *oendp; 2221144467Sharti 2222144467Sharti cp = inLine; 2223144467Sharti oendp = endp = inLine + strlen(inLine); 2224144467Sharti if (endp[-1] == '\n') { 2225144467Sharti *--endp = '\0'; 2226144467Sharti } 2227144467Sharti cp = JobOutput(job, inLine, endp, FALSE); 2228144467Sharti 2229144467Sharti /* 2230144467Sharti * There's still more in that buffer. This time, 2231144467Sharti * though, we know there's no newline at the 2232144467Sharti * end, so we add one of our own free will. 2233144467Sharti */ 2234144467Sharti fprintf(stdout, "%s", cp); 2235144467Sharti fflush(stdout); 2236144467Sharti if (endp != oendp) { 2237144467Sharti fprintf(stdout, "\n"); 2238144467Sharti fflush(stdout); 2239144467Sharti } 2240144467Sharti } 2241144467Sharti fclose(oFILE); 2242144467Sharti eunlink(job->outFile); 22431590Srgrimes } 22441590Srgrimes } 22451590Srgrimes} 22461590Srgrimes 2247144467Sharti/** 2248144467Sharti * Job_CatchChildren 22491590Srgrimes * Handle the exit of a child. Called from Make_Make. 22501590Srgrimes * 22511590Srgrimes * Side Effects: 22521590Srgrimes * The job descriptor is removed from the list of children. 22531590Srgrimes * 22541590Srgrimes * Notes: 22551590Srgrimes * We do waits, blocking or not, according to the wisdom of our 22561590Srgrimes * caller, until there are no more children to report. For each 22571590Srgrimes * job, call JobFinish to finish things off. This will take care of 22581590Srgrimes * putting jobs on the stoppedJobs queue. 22591590Srgrimes */ 22601590Srgrimesvoid 2261104696SjmallettJob_CatchChildren(Boolean block) 22621590Srgrimes{ 2263144665Sharti pid_t pid; /* pid of dead child */ 2264144467Sharti Job *job; /* job descriptor for dead child */ 2265144467Sharti int status; /* Exit/termination status */ 22661590Srgrimes 2267144467Sharti /* 2268144467Sharti * Don't even bother if we know there's no one around. 2269144467Sharti */ 2270144467Sharti if (nJobs == 0) { 2271144467Sharti return; 2272144467Sharti } 22738874Srgrimes 2274144467Sharti for (;;) { 2275144467Sharti pid = waitpid((pid_t)-1, &status, 2276144467Sharti (block ? 0 : WNOHANG) | WUNTRACED); 2277144467Sharti if (pid <= 0) 2278144467Sharti break; 22791590Srgrimes 2280144665Sharti DEBUGF(JOB, ("Process %jd exited or stopped.\n", 2281144665Sharti (intmax_t)pid)); 22821590Srgrimes 2283144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2284144494Sharti if (job->pid == pid) 2285144467Sharti break; 2286143810Sharti } 2287144467Sharti 2288144494Sharti if (job == NULL) { 2289144467Sharti if (WIFSIGNALED(status) && 2290144467Sharti (WTERMSIG(status) == SIGCONT)) { 2291144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2292144494Sharti if (job->pid == pid) 2293144467Sharti break; 2294144467Sharti } 2295144494Sharti if (job == NULL) { 2296144665Sharti Error("Resumed child (%jd) " 2297144665Sharti "not in table", (intmax_t)pid); 2298144467Sharti continue; 2299144467Sharti } 2300144494Sharti TAILQ_REMOVE(&stoppedJobs, job, link); 2301144467Sharti } else { 2302144665Sharti Error("Child (%jd) not in table?", 2303144665Sharti (intmax_t)pid); 2304144467Sharti continue; 2305144467Sharti } 2306144467Sharti } else { 2307144494Sharti TAILQ_REMOVE(&jobs, job, link); 2308144467Sharti nJobs -= 1; 2309144467Sharti if (fifoFd >= 0 && maxJobs > 1) { 2310144467Sharti write(fifoFd, "+", 1); 2311144467Sharti maxJobs--; 2312144467Sharti if (nJobs >= maxJobs) 2313144467Sharti jobFull = TRUE; 2314144467Sharti else 2315144467Sharti jobFull = FALSE; 2316144467Sharti } else { 2317144467Sharti DEBUGF(JOB, ("Job queue is no longer full.\n")); 2318144467Sharti jobFull = FALSE; 2319144467Sharti } 23201590Srgrimes } 2321144467Sharti 2322144467Sharti JobFinish(job, &status); 23231590Srgrimes } 2324144467Sharti if (interrupted) 2325144467Sharti JobPassSig(interrupted); 23261590Srgrimes} 23271590Srgrimes 2328144467Sharti/** 2329144467Sharti * Job_CatchOutput 23301590Srgrimes * Catch the output from our children, if we're using 23311590Srgrimes * pipes do so. Otherwise just block time until we get a 2332138232Sharti * signal(most likely a SIGCHLD) since there's no point in 23331590Srgrimes * just spinning when there's nothing to do and the reaping 23348874Srgrimes * of a child can wait for a while. 23351590Srgrimes * 23361590Srgrimes * Side Effects: 23371590Srgrimes * Output is read from pipes if we're piping. 23381590Srgrimes * ----------------------------------------------------------------------- 23391590Srgrimes */ 23401590Srgrimesvoid 2341139064Sharti#ifdef USE_KQUEUE 2342139064ShartiJob_CatchOutput(int flag __unused) 2343139064Sharti#else 2344137606SphkJob_CatchOutput(int flag) 2345139064Sharti#endif 23461590Srgrimes{ 2347144467Sharti int nfds; 2348104475Sphk#ifdef USE_KQUEUE 2349104475Sphk#define KEV_SIZE 4 2350144467Sharti struct kevent kev[KEV_SIZE]; 2351144467Sharti int i; 2352104475Sphk#else 2353144467Sharti struct timeval timeout; 2354144467Sharti fd_set readfds; 2355144467Sharti Job *job; 2356104475Sphk#endif 23571590Srgrimes 2358144467Sharti fflush(stdout); 23591590Srgrimes 2360144467Sharti if (usePipes) { 2361104475Sphk#ifdef USE_KQUEUE 2362144467Sharti if ((nfds = kevent(kqfd, NULL, 0, kev, KEV_SIZE, NULL)) == -1) { 2363144467Sharti if (errno != EINTR) 2364144467Sharti Punt("kevent: %s", strerror(errno)); 2365144467Sharti if (interrupted) 2366144467Sharti JobPassSig(interrupted); 2367144467Sharti } else { 2368144467Sharti for (i = 0; i < nfds; i++) { 2369144467Sharti if (kev[i].flags & EV_ERROR) { 2370144467Sharti warnc(kev[i].data, "kevent"); 2371144467Sharti continue; 2372144467Sharti } 2373144467Sharti switch (kev[i].filter) { 2374144467Sharti case EVFILT_READ: 2375144467Sharti JobDoOutput(kev[i].udata, FALSE); 2376144467Sharti break; 2377144467Sharti case EVFILT_PROC: 2378144467Sharti /* 2379144467Sharti * Just wake up and let 2380144467Sharti * Job_CatchChildren() collect the 2381144467Sharti * terminated job. 2382144467Sharti */ 2383144467Sharti break; 2384144467Sharti } 2385144467Sharti } 2386104475Sphk } 2387104475Sphk#else 2388144467Sharti readfds = outputs; 2389144467Sharti timeout.tv_sec = SEL_SEC; 2390144467Sharti timeout.tv_usec = SEL_USEC; 2391144467Sharti if (flag && jobFull && fifoFd >= 0) 2392144467Sharti FD_SET(fifoFd, &readfds); 23931590Srgrimes 2394144467Sharti nfds = select(FD_SETSIZE, &readfds, (fd_set *)NULL, 2395144467Sharti (fd_set *)NULL, &timeout); 2396144467Sharti if (nfds <= 0) { 2397144467Sharti if (interrupted) 2398144467Sharti JobPassSig(interrupted); 2399144467Sharti return; 2400144467Sharti } 2401144467Sharti if (fifoFd >= 0 && FD_ISSET(fifoFd, &readfds)) { 2402144467Sharti if (--nfds <= 0) 2403144467Sharti return; 2404144467Sharti } 2405144494Sharti job = TAILQ_FIRST(&jobs); 2406144494Sharti while (nfds != 0 && job != NULL) { 2407144467Sharti if (FD_ISSET(job->inPipe, &readfds)) { 2408144467Sharti JobDoOutput(job, FALSE); 2409144494Sharti nfds--; 2410144467Sharti } 2411144494Sharti job = TAILQ_NEXT(job, link); 2412144467Sharti } 2413144467Sharti#endif /* !USE_KQUEUE */ 2414137606Sphk } 24151590Srgrimes} 24161590Srgrimes 2417144467Sharti/** 2418144467Sharti * Job_Make 24191590Srgrimes * Start the creation of a target. Basically a front-end for 24201590Srgrimes * JobStart used by the Make module. 24211590Srgrimes * 24221590Srgrimes * Side Effects: 24231590Srgrimes * Another job is started. 24241590Srgrimes */ 24251590Srgrimesvoid 2426104696SjmallettJob_Make(GNode *gn) 24271590Srgrimes{ 2428138232Sharti 2429144467Sharti JobStart(gn, 0, NULL); 24301590Srgrimes} 24311590Srgrimes 2432144467Sharti/** 2433144467Sharti * JobCopyShell 2434144467Sharti * Make a new copy of the shell structure including a copy of the strings 2435144467Sharti * in it. This also defaults some fields in case they are NULL. 2436138079Sharti * 2437144467Sharti * Returns: 2438144467Sharti * The function returns a pointer to the new shell structure. 2439138079Sharti */ 2440144483Shartistatic struct Shell * 2441144483ShartiJobCopyShell(const struct Shell *osh) 2442138079Sharti{ 2443144483Sharti struct Shell *nsh; 2444138079Sharti 2445138079Sharti nsh = emalloc(sizeof(*nsh)); 2446138079Sharti nsh->name = estrdup(osh->name); 2447138079Sharti 2448138079Sharti if (osh->echoOff != NULL) 2449138079Sharti nsh->echoOff = estrdup(osh->echoOff); 2450138079Sharti else 2451138079Sharti nsh->echoOff = NULL; 2452138079Sharti if (osh->echoOn != NULL) 2453138079Sharti nsh->echoOn = estrdup(osh->echoOn); 2454138079Sharti else 2455138079Sharti nsh->echoOn = NULL; 2456138079Sharti nsh->hasEchoCtl = osh->hasEchoCtl; 2457138079Sharti 2458138079Sharti if (osh->noPrint != NULL) 2459138079Sharti nsh->noPrint = estrdup(osh->noPrint); 2460138079Sharti else 2461138079Sharti nsh->noPrint = NULL; 2462138079Sharti 2463138079Sharti nsh->hasErrCtl = osh->hasErrCtl; 2464138079Sharti if (osh->errCheck == NULL) 2465138079Sharti nsh->errCheck = estrdup(""); 2466138079Sharti else 2467138079Sharti nsh->errCheck = estrdup(osh->errCheck); 2468138079Sharti if (osh->ignErr == NULL) 2469138079Sharti nsh->ignErr = estrdup("%s"); 2470138079Sharti else 2471138079Sharti nsh->ignErr = estrdup(osh->ignErr); 2472138079Sharti 2473138079Sharti if (osh->echo == NULL) 2474138079Sharti nsh->echo = estrdup(""); 2475138079Sharti else 2476138079Sharti nsh->echo = estrdup(osh->echo); 2477138079Sharti 2478138079Sharti if (osh->exit == NULL) 2479138079Sharti nsh->exit = estrdup(""); 2480138079Sharti else 2481138079Sharti nsh->exit = estrdup(osh->exit); 2482138079Sharti 2483138079Sharti return (nsh); 2484138079Sharti} 2485138079Sharti 2486144467Sharti/** 2487144467Sharti * JobFreeShell 2488144467Sharti * Free a shell structure and all associated strings. 2489138079Sharti */ 2490138079Shartistatic void 2491144483ShartiJobFreeShell(struct Shell *sh) 2492138079Sharti{ 2493138079Sharti 2494138079Sharti if (sh != NULL) { 2495138079Sharti free(sh->name); 2496138079Sharti free(sh->echoOff); 2497138079Sharti free(sh->echoOn); 2498138079Sharti free(sh->noPrint); 2499138079Sharti free(sh->errCheck); 2500138079Sharti free(sh->ignErr); 2501138079Sharti free(sh->echo); 2502138079Sharti free(sh->exit); 2503138079Sharti free(sh); 2504138079Sharti } 2505138079Sharti} 2506138079Sharti 2507136840Sruvoid 2508136840SruShell_Init(void) 2509136840Sru{ 2510138079Sharti 2511144467Sharti if (commandShell == NULL) 2512144467Sharti commandShell = JobMatchShell(shells[DEFSHELL].name); 2513138079Sharti 2514144467Sharti if (shellPath == NULL) { 2515144467Sharti /* 2516144467Sharti * The user didn't specify a shell to use, so we are using the 2517144467Sharti * default one... Both the absolute path and the last component 2518144467Sharti * must be set. The last component is taken from the 'name' 2519144467Sharti * field of the default shell description pointed-to by 2520144467Sharti * commandShell. All default shells are located in 2521144467Sharti * PATH_DEFSHELLDIR. 2522144467Sharti */ 2523144467Sharti shellName = commandShell->name; 2524144467Sharti shellPath = str_concat(PATH_DEFSHELLDIR, shellName, 2525144467Sharti STR_ADDSLASH); 2526144467Sharti } 2527136840Sru} 2528136840Sru 2529144467Sharti/** 2530144467Sharti * Job_Init 2531137572Sphk * Initialize the process module, given a maximum number of jobs. 25321590Srgrimes * 25331590Srgrimes * Side Effects: 25341590Srgrimes * lists and counters are initialized 25351590Srgrimes */ 25361590Srgrimesvoid 2537137572SphkJob_Init(int maxproc) 25381590Srgrimes{ 2539144467Sharti GNode *begin; /* node for commands to do at the very start */ 2540144467Sharti const char *env; 2541144467Sharti struct sigaction sa; 25421590Srgrimes 2543144467Sharti fifoFd = -1; 2544144467Sharti env = getenv("MAKE_JOBS_FIFO"); 2545137606Sphk 2546144467Sharti if (env == NULL && maxproc > 1) { 2547144467Sharti /* 2548144467Sharti * We did not find the environment variable so we are the 2549144467Sharti * leader. Create the fifo, open it, write one char per 2550144467Sharti * allowed job into the pipe. 2551144467Sharti */ 2552144467Sharti mktemp(fifoName); 2553144467Sharti if (!mkfifo(fifoName, 0600)) { 2554144467Sharti fifoFd = open(fifoName, O_RDWR | O_NONBLOCK, 0); 2555144467Sharti if (fifoFd >= 0) { 2556144467Sharti fifoMaster = 1; 2557144467Sharti fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2558144467Sharti env = fifoName; 2559144467Sharti setenv("MAKE_JOBS_FIFO", env, 1); 2560144467Sharti while (maxproc-- > 0) { 2561144467Sharti write(fifoFd, "+", 1); 2562144467Sharti } 2563144467Sharti /* The master make does not get a magic token */ 2564144467Sharti jobFull = TRUE; 2565144467Sharti maxJobs = 0; 2566144467Sharti } else { 2567144467Sharti unlink(fifoName); 2568144467Sharti env = NULL; 2569144467Sharti } 2570137606Sphk } 2571144467Sharti 2572144467Sharti } else if (env != NULL) { 2573144467Sharti /* 2574144467Sharti * We had the environment variable so we are a slave. 2575144467Sharti * Open fifo and give ourselves a magic token which represents 2576144467Sharti * the token our parent make has grabbed to start his make 2577144467Sharti * process. Otherwise the sub-makes would gobble up tokens and 2578144467Sharti * the proper number of tokens to specify to -j would depend 2579144467Sharti * on the depth of the tree and the order of execution. 2580144467Sharti */ 2581144467Sharti fifoFd = open(env, O_RDWR, 0); 2582144467Sharti if (fifoFd >= 0) { 2583144467Sharti fcntl(fifoFd, F_SETFL, O_NONBLOCK); 2584144467Sharti maxJobs = 1; 2585144467Sharti jobFull = FALSE; 2586144467Sharti } 2587137606Sphk } 2588144467Sharti if (fifoFd <= 0) { 2589144467Sharti maxJobs = maxproc; 2590144467Sharti jobFull = FALSE; 2591144467Sharti } else { 2592137606Sphk } 2593144467Sharti nJobs = 0; 25941590Srgrimes 2595144467Sharti aborting = 0; 2596144467Sharti errors = 0; 25971590Srgrimes 2598144467Sharti lastNode = NULL; 25991590Srgrimes 2600144467Sharti if ((maxJobs == 1 && fifoFd < 0) || beVerbose == 0) { 2601144467Sharti /* 2602144467Sharti * If only one job can run at a time, there's no need for a 2603144467Sharti * banner, no is there? 2604144467Sharti */ 2605144467Sharti targFmt = ""; 2606144467Sharti } else { 2607144467Sharti targFmt = TARG_FMT; 2608144467Sharti } 2609144467Sharti 2610144467Sharti Shell_Init(); 2611144467Sharti 26121590Srgrimes /* 2613144467Sharti * Catch the four signals that POSIX specifies if they aren't ignored. 2614144467Sharti * JobCatchSignal will just set global variables and hope someone 2615144467Sharti * else is going to handle the interrupt. 26161590Srgrimes */ 2617144467Sharti sa.sa_handler = JobCatchSig; 2618144467Sharti sigemptyset(&sa.sa_mask); 2619144467Sharti sa.sa_flags = 0; 26208874Srgrimes 2621144467Sharti if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 2622144467Sharti sigaction(SIGINT, &sa, NULL); 2623144467Sharti } 2624144467Sharti if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 2625144467Sharti sigaction(SIGHUP, &sa, NULL); 2626144467Sharti } 2627144467Sharti if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 2628144467Sharti sigaction(SIGQUIT, &sa, NULL); 2629144467Sharti } 2630144467Sharti if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 2631144467Sharti sigaction(SIGTERM, &sa, NULL); 2632144467Sharti } 2633144467Sharti /* 2634144467Sharti * There are additional signals that need to be caught and passed if 2635144467Sharti * either the export system wants to be told directly of signals or if 2636144467Sharti * we're giving each job its own process group (since then it won't get 2637144467Sharti * signals from the terminal driver as we own the terminal) 2638144467Sharti */ 2639137202Sharti#if defined(USE_PGRP) 2640144467Sharti if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { 2641144467Sharti sigaction(SIGTSTP, &sa, NULL); 2642144467Sharti } 2643144467Sharti if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { 2644144467Sharti sigaction(SIGTTOU, &sa, NULL); 2645144467Sharti } 2646144467Sharti if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { 2647144467Sharti sigaction(SIGTTIN, &sa, NULL); 2648144467Sharti } 2649144467Sharti if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { 2650144467Sharti sigaction(SIGWINCH, &sa, NULL); 2651144467Sharti } 26521590Srgrimes#endif 26538874Srgrimes 2654104475Sphk#ifdef USE_KQUEUE 2655144467Sharti if ((kqfd = kqueue()) == -1) { 2656144467Sharti Punt("kqueue: %s", strerror(errno)); 2657144467Sharti } 2658104475Sphk#endif 2659104475Sphk 2660144467Sharti begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); 26611590Srgrimes 2662144467Sharti if (begin != NULL) { 2663144467Sharti JobStart(begin, JOB_SPECIAL, (Job *)NULL); 2664144467Sharti while (nJobs) { 2665144467Sharti Job_CatchOutput(0); 2666144467Sharti Job_CatchChildren(!usePipes); 2667144467Sharti } 26681590Srgrimes } 2669144467Sharti postCommands = Targ_FindNode(".END", TARG_CREATE); 26701590Srgrimes} 26711590Srgrimes 2672144467Sharti/** 2673144467Sharti * Job_Full 26741590Srgrimes * See if the job table is full. It is considered full if it is OR 26751590Srgrimes * if we are in the process of aborting OR if we have 26761590Srgrimes * reached/exceeded our local quota. This prevents any more jobs 26771590Srgrimes * from starting up. 26781590Srgrimes * 26791590Srgrimes * Results: 26801590Srgrimes * TRUE if the job table is full, FALSE otherwise 26811590Srgrimes */ 26821590SrgrimesBoolean 2683104696SjmallettJob_Full(void) 26841590Srgrimes{ 2685144467Sharti char c; 2686144467Sharti int i; 2687137606Sphk 2688144467Sharti if (aborting) 2689144467Sharti return (aborting); 2690144467Sharti if (fifoFd >= 0 && jobFull) { 2691144467Sharti i = read(fifoFd, &c, 1); 2692144467Sharti if (i > 0) { 2693144467Sharti maxJobs++; 2694144467Sharti jobFull = FALSE; 2695144467Sharti } 2696137606Sphk } 2697144467Sharti return (jobFull); 26981590Srgrimes} 26991590Srgrimes 2700144467Sharti/** 2701144467Sharti * Job_Empty 27021590Srgrimes * See if the job table is empty. Because the local concurrency may 27031590Srgrimes * be set to 0, it is possible for the job table to become empty, 27041590Srgrimes * while the list of stoppedJobs remains non-empty. In such a case, 27051590Srgrimes * we want to restart as many jobs as we can. 27061590Srgrimes * 27071590Srgrimes * Results: 27081590Srgrimes * TRUE if it is. FALSE if it ain't. 27091590Srgrimes */ 27101590SrgrimesBoolean 2711104696SjmallettJob_Empty(void) 27121590Srgrimes{ 2713144467Sharti if (nJobs == 0) { 2714144494Sharti if (!TAILQ_EMPTY(&stoppedJobs) && !aborting) { 2715144467Sharti /* 2716144467Sharti * The job table is obviously not full if it has no 2717144467Sharti * jobs in it...Try and restart the stopped jobs. 2718144467Sharti */ 2719144467Sharti jobFull = FALSE; 2720144467Sharti JobRestartJobs(); 2721144467Sharti return (FALSE); 2722144467Sharti } else { 2723144467Sharti return (TRUE); 2724144467Sharti } 27251590Srgrimes } else { 2726144467Sharti return (FALSE); 27271590Srgrimes } 27281590Srgrimes} 27291590Srgrimes 2730144467Sharti/** 2731144467Sharti * JobMatchShell 27321590Srgrimes * Find a matching shell in 'shells' given its final component. 27331590Srgrimes * 27341590Srgrimes * Results: 2735138334Sharti * A pointer to a freshly allocated Shell structure with a copy 2736138228Sharti * of the static structure or NULL if no shell with the given name 2737138228Sharti * is found. 27381590Srgrimes */ 2739144483Shartistatic struct Shell * 2740138228ShartiJobMatchShell(const char *name) 27411590Srgrimes{ 2742144467Sharti const struct CShell *sh; /* Pointer into shells table */ 2743144483Sharti struct Shell *nsh; 27441590Srgrimes 2745144467Sharti for (sh = shells; sh < shells + sizeof(shells)/sizeof(shells[0]); sh++) 2746144467Sharti if (strcmp(sh->name, name) == 0) 2747144467Sharti break; 27481590Srgrimes 2749144467Sharti if (sh == shells + sizeof(shells)/sizeof(shells[0])) 2750144467Sharti return (NULL); 2751138228Sharti 2752144467Sharti /* make a copy */ 2753144467Sharti nsh = emalloc(sizeof(*nsh)); 2754138228Sharti 2755144467Sharti nsh->name = estrdup(sh->name); 2756144467Sharti nsh->echoOff = estrdup(sh->echoOff); 2757144467Sharti nsh->echoOn = estrdup(sh->echoOn); 2758144467Sharti nsh->hasEchoCtl = sh->hasEchoCtl; 2759144467Sharti nsh->noPrint = estrdup(sh->noPrint); 2760144467Sharti nsh->hasErrCtl = sh->hasErrCtl; 2761144467Sharti nsh->errCheck = estrdup(sh->errCheck); 2762144467Sharti nsh->ignErr = estrdup(sh->ignErr); 2763144467Sharti nsh->echo = estrdup(sh->echo); 2764144467Sharti nsh->exit = estrdup(sh->exit); 2765138228Sharti 2766144467Sharti return (nsh); 27671590Srgrimes} 27681590Srgrimes 2769144467Sharti/** 2770144467Sharti * Job_ParseShell 27711590Srgrimes * Parse a shell specification and set up commandShell, shellPath 27721590Srgrimes * and shellName appropriately. 27731590Srgrimes * 27741590Srgrimes * Results: 27751590Srgrimes * FAILURE if the specification was incorrect. 27761590Srgrimes * 27771590Srgrimes * Side Effects: 27781590Srgrimes * commandShell points to a Shell structure (either predefined or 27791590Srgrimes * created from the shell spec), shellPath is the full path of the 27801590Srgrimes * shell described by commandShell, while shellName is just the 27811590Srgrimes * final component of shellPath. 27821590Srgrimes * 27831590Srgrimes * Notes: 27841590Srgrimes * A shell specification consists of a .SHELL target, with dependency 27851590Srgrimes * operator, followed by a series of blank-separated words. Double 27861590Srgrimes * quotes can be used to use blanks in words. A backslash escapes 27871590Srgrimes * anything (most notably a double-quote and a space) and 27881590Srgrimes * provides the functionality it does in C. Each word consists of 27891590Srgrimes * keyword and value separated by an equal sign. There should be no 27901590Srgrimes * unnecessary spaces in the word. The keywords are as follows: 2791146061Sharti * name Name of shell. 2792146061Sharti * path Location of shell. Overrides "name" if given 2793146061Sharti * quiet Command to turn off echoing. 2794146061Sharti * echo Command to turn echoing on 27951590Srgrimes * filter Result of turning off echoing that shouldn't be 2796146061Sharti * printed. 27971590Srgrimes * echoFlag Flag to turn echoing on at the start 27981590Srgrimes * errFlag Flag to turn error checking on at the start 27991590Srgrimes * hasErrCtl True if shell has error checking control 2800146061Sharti * check Command to turn on error checking if hasErrCtl 2801146061Sharti * is TRUE or template of command to echo a command 2802146061Sharti * for which error checking is off if hasErrCtl is 2803146061Sharti * FALSE. 28041590Srgrimes * ignore Command to turn off error checking if hasErrCtl 2805146061Sharti * is TRUE or template of command to execute a 2806146061Sharti * command so as to ignore any errors it returns if 2807146061Sharti * hasErrCtl is FALSE. 28081590Srgrimes */ 28091590SrgrimesReturnStatus 2810104696SjmallettJob_ParseShell(char *line) 28111590Srgrimes{ 2812144467Sharti char **words; 2813144467Sharti int wordCount; 2814144467Sharti char **argv; 2815144467Sharti int argc; 2816144467Sharti char *path; 2817144741Sharti char *eq; 2818144467Sharti Boolean fullSpec = FALSE; 2819144483Sharti struct Shell newShell; 2820144483Sharti struct Shell *sh; 28211590Srgrimes 2822144467Sharti while (isspace((unsigned char)*line)) { 2823144467Sharti line++; 2824144467Sharti } 28251590Srgrimes 2826144467Sharti memset(&newShell, 0, sizeof(newShell)); 2827144741Sharti path = NULL; 28288874Srgrimes 28291590Srgrimes /* 2830144741Sharti * Parse the specification by keyword but skip the first word - it 2831144741Sharti * is not set by brk_string. 28321590Srgrimes */ 2833146147Sharti words = brk_string(line, &wordCount, TRUE); 2834146147Sharti words++; 2835144741Sharti wordCount--; 2836144741Sharti 2837144741Sharti for (argc = wordCount, argv = words; argc != 0; argc--, argv++) { 2838144741Sharti /* 2839144741Sharti * Split keyword and value 2840144741Sharti */ 2841144741Sharti if ((eq = strchr(*argv, '=')) == NULL) { 2842144741Sharti Parse_Error(PARSE_FATAL, "missing '=' in shell " 2843144741Sharti "specification keyword '%s'", *argv); 2844144741Sharti return (FAILURE); 2845144741Sharti } 2846144741Sharti *eq++ = '\0'; 2847144741Sharti 2848144741Sharti if (strcmp(*argv, "path") == 0) { 2849144741Sharti path = eq; 2850144741Sharti } else if (strcmp(*argv, "name") == 0) { 2851144741Sharti newShell.name = eq; 2852144741Sharti } else if (strcmp(*argv, "quiet") == 0) { 2853144741Sharti newShell.echoOff = eq; 2854144741Sharti fullSpec = TRUE; 2855144741Sharti } else if (strcmp(*argv, "echo") == 0) { 2856144741Sharti newShell.echoOn = eq; 2857144741Sharti fullSpec = TRUE; 2858144741Sharti } else if (strcmp(*argv, "filter") == 0) { 2859144741Sharti newShell.noPrint = eq; 2860144741Sharti fullSpec = TRUE; 2861144741Sharti } else if (strcmp(*argv, "echoFlag") == 0) { 2862144741Sharti newShell.echo = eq; 2863144741Sharti fullSpec = TRUE; 2864144741Sharti } else if (strcmp(*argv, "errFlag") == 0) { 2865144741Sharti newShell.exit = eq; 2866144741Sharti fullSpec = TRUE; 2867144741Sharti } else if (strcmp(*argv, "hasErrCtl") == 0) { 2868144741Sharti newShell.hasErrCtl = (*eq == 'Y' || *eq == 'y' || 2869144741Sharti *eq == 'T' || *eq == 't'); 2870144741Sharti fullSpec = TRUE; 2871144741Sharti } else if (strcmp(*argv, "check") == 0) { 2872144741Sharti newShell.errCheck = eq; 2873144741Sharti fullSpec = TRUE; 2874144741Sharti } else if (strcmp(*argv, "ignore") == 0) { 2875144741Sharti newShell.ignErr = eq; 2876144741Sharti fullSpec = TRUE; 2877144467Sharti } else { 2878144741Sharti Parse_Error(PARSE_FATAL, "unknown keyword in shell " 2879144741Sharti "specification '%s'", *argv); 2880144741Sharti return (FAILURE); 2881144467Sharti } 28821590Srgrimes } 2883138079Sharti 28841590Srgrimes /* 2885144467Sharti * Some checks (could be more) 28861590Srgrimes */ 2887144467Sharti if (fullSpec) { 2888144467Sharti if ((newShell.echoOn != NULL) ^ (newShell.echoOff != NULL)) 2889144467Sharti Parse_Error(PARSE_FATAL, "Shell must have either both " 2890144467Sharti "echoOff and echoOn or none of them"); 2891144467Sharti 2892144467Sharti if (newShell.echoOn != NULL && newShell.echoOff) 2893144467Sharti newShell.hasEchoCtl = TRUE; 28941590Srgrimes } 2895138079Sharti 2896144467Sharti if (path == NULL) { 2897144467Sharti /* 2898144467Sharti * If no path was given, the user wants one of the pre-defined 2899144467Sharti * shells, yes? So we find the one s/he wants with the help of 2900144467Sharti * JobMatchShell and set things up the right way. shellPath 2901144467Sharti * will be set up by Job_Init. 2902144467Sharti */ 2903144467Sharti if (newShell.name == NULL) { 2904144467Sharti Parse_Error(PARSE_FATAL, 2905144467Sharti "Neither path nor name specified"); 2906144467Sharti return (FAILURE); 2907144467Sharti } 2908144467Sharti if ((sh = JobMatchShell(newShell.name)) == NULL) { 2909144467Sharti Parse_Error(PARSE_FATAL, "%s: no matching shell", 2910144467Sharti newShell.name); 2911144467Sharti return (FAILURE); 2912144467Sharti } 2913144467Sharti 29141590Srgrimes } else { 2915144467Sharti /* 2916144467Sharti * The user provided a path. If s/he gave nothing else 2917144467Sharti * (fullSpec is FALSE), try and find a matching shell in the 2918144467Sharti * ones we know of. Else we just take the specification at its 2919144467Sharti * word and copy it to a new location. In either case, we need 2920144467Sharti * to record the path the user gave for the shell. 2921144467Sharti */ 2922144467Sharti free(shellPath); 2923144467Sharti shellPath = estrdup(path); 2924144467Sharti if (newShell.name == NULL) { 2925144467Sharti /* get the base name as the name */ 2926144467Sharti path = strrchr(path, '/'); 2927144467Sharti if (path == NULL) { 2928144467Sharti path = shellPath; 2929144467Sharti } else { 2930144467Sharti path += 1; 2931144467Sharti } 2932144467Sharti newShell.name = path; 2933144467Sharti } 2934144467Sharti 2935144467Sharti if (!fullSpec) { 2936144467Sharti if ((sh = JobMatchShell(newShell.name)) == NULL) { 2937144467Sharti Parse_Error(PARSE_FATAL, 2938144467Sharti "%s: no matching shell", newShell.name); 2939144467Sharti return (FAILURE); 2940144467Sharti } 2941144467Sharti } else { 2942144467Sharti sh = JobCopyShell(&newShell); 2943144467Sharti } 29441590Srgrimes } 29451590Srgrimes 2946144467Sharti /* set the new shell */ 2947144467Sharti JobFreeShell(commandShell); 2948144467Sharti commandShell = sh; 29498874Srgrimes 2950144467Sharti shellName = commandShell->name; 29518874Srgrimes 2952144467Sharti return (SUCCESS); 29531590Srgrimes} 29541590Srgrimes 2955144467Sharti/** 2956144467Sharti * JobInterrupt 29571590Srgrimes * Handle the receipt of an interrupt. 29581590Srgrimes * 29591590Srgrimes * Side Effects: 29601590Srgrimes * All children are killed. Another job will be started if the 29611590Srgrimes * .INTERRUPT target was given. 29621590Srgrimes */ 29631590Srgrimesstatic void 2964104696SjmallettJobInterrupt(int runINTERRUPT, int signo) 29651590Srgrimes{ 2966144467Sharti Job *job; /* job descriptor in that element */ 2967144467Sharti GNode *interrupt; /* the node describing the .INTERRUPT target */ 29688874Srgrimes 2969144467Sharti aborting = ABORT_INTERRUPT; 29701590Srgrimes 2971144494Sharti TAILQ_FOREACH(job, &jobs, link) { 2972144467Sharti if (!Targ_Precious(job->node)) { 2973144467Sharti char *file = (job->node->path == NULL ? 2974144467Sharti job->node->name : job->node->path); 2975144467Sharti 2976144467Sharti if (!noExecute && eunlink(file) != -1) { 2977144467Sharti Error("*** %s removed", file); 2978144467Sharti } 2979144467Sharti } 2980144467Sharti if (job->pid) { 2981144467Sharti DEBUGF(JOB, ("JobInterrupt passing signal to child " 2982144665Sharti "%jd.\n", (intmax_t)job->pid)); 2983144467Sharti KILL(job->pid, signo); 2984144467Sharti } 29851590Srgrimes } 298618730Ssteve 2987144467Sharti if (runINTERRUPT && !touchFlag) { 2988144467Sharti /* 2989144467Sharti * clear the interrupted flag because we would get an 2990144467Sharti * infinite loop otherwise. 2991144467Sharti */ 2992144467Sharti interrupted = 0; 2993137605Sharti 2994144467Sharti interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 2995144467Sharti if (interrupt != NULL) { 2996144467Sharti ignoreErrors = FALSE; 29971590Srgrimes 2998144467Sharti JobStart(interrupt, JOB_IGNDOTS, (Job *)NULL); 2999144467Sharti while (nJobs) { 3000144467Sharti Job_CatchOutput(0); 3001144467Sharti Job_CatchChildren(!usePipes); 3002144467Sharti } 3003144467Sharti } 30041590Srgrimes } 30051590Srgrimes} 30061590Srgrimes 3007144467Sharti/** 3008144467Sharti * Job_Finish 30091590Srgrimes * Do final processing such as the running of the commands 30108874Srgrimes * attached to the .END target. 30111590Srgrimes * 30121590Srgrimes * Results: 30131590Srgrimes * Number of errors reported. 30141590Srgrimes */ 30151590Srgrimesint 3016104696SjmallettJob_Finish(void) 30171590Srgrimes{ 3018138232Sharti 3019144467Sharti if (postCommands != NULL && !Lst_IsEmpty(&postCommands->commands)) { 3020144467Sharti if (errors) { 3021144467Sharti Error("Errors reported so .END ignored"); 3022144467Sharti } else { 3023144467Sharti JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); 30241590Srgrimes 3025144467Sharti while (nJobs) { 3026144467Sharti Job_CatchOutput(0); 3027144467Sharti Job_CatchChildren(!usePipes); 3028144467Sharti } 3029144467Sharti } 30301590Srgrimes } 3031144467Sharti if (fifoFd >= 0) { 3032144467Sharti close(fifoFd); 3033144467Sharti fifoFd = -1; 3034144467Sharti if (fifoMaster) 3035144467Sharti unlink(fifoName); 3036144467Sharti } 3037144467Sharti return (errors); 30381590Srgrimes} 30391590Srgrimes 3040144467Sharti/** 3041144467Sharti * Job_Wait 30421590Srgrimes * Waits for all running jobs to finish and returns. Sets 'aborting' 30431590Srgrimes * to ABORT_WAIT to prevent other jobs from starting. 30441590Srgrimes * 30451590Srgrimes * Side Effects: 30461590Srgrimes * Currently running jobs finish. 30471590Srgrimes */ 30481590Srgrimesvoid 3049104696SjmallettJob_Wait(void) 30501590Srgrimes{ 3051138232Sharti 3052144467Sharti aborting = ABORT_WAIT; 3053144467Sharti while (nJobs != 0) { 3054144467Sharti Job_CatchOutput(0); 3055144467Sharti Job_CatchChildren(!usePipes); 3056144467Sharti } 3057144467Sharti aborting = 0; 30581590Srgrimes} 30591590Srgrimes 3060144467Sharti/** 3061144467Sharti * Job_AbortAll 30621590Srgrimes * Abort all currently running jobs without handling output or anything. 30631590Srgrimes * This function is to be called only in the event of a major 30641590Srgrimes * error. Most definitely NOT to be called from JobInterrupt. 30651590Srgrimes * 30661590Srgrimes * Side Effects: 30671590Srgrimes * All children are killed, not just the firstborn 30681590Srgrimes */ 30691590Srgrimesvoid 3070104696SjmallettJob_AbortAll(void) 30711590Srgrimes{ 3072144467Sharti Job *job; /* the job descriptor in that element */ 3073144467Sharti int foo; 30748874Srgrimes 3075144467Sharti aborting = ABORT_ERROR; 30768874Srgrimes 3077144467Sharti if (nJobs) { 3078144494Sharti TAILQ_FOREACH(job, &jobs, link) { 3079144467Sharti /* 3080144467Sharti * kill the child process with increasingly drastic 3081144467Sharti * signals to make darn sure it's dead. 3082144467Sharti */ 3083144467Sharti KILL(job->pid, SIGINT); 3084144467Sharti KILL(job->pid, SIGKILL); 3085144467Sharti } 30861590Srgrimes } 30878874Srgrimes 3088144467Sharti /* 3089144467Sharti * Catch as many children as want to report in at first, then give up 3090144467Sharti */ 3091144467Sharti while (waitpid((pid_t)-1, &foo, WNOHANG) > 0) 3092144665Sharti ; 30931590Srgrimes} 309418730Ssteve 3095144467Sharti/** 3096144467Sharti * JobRestartJobs 309718730Ssteve * Tries to restart stopped jobs if there are slots available. 309818730Ssteve * Note that this tries to restart them regardless of pending errors. 309918730Ssteve * It's not good to leave stopped jobs lying around! 310018730Ssteve * 310118730Ssteve * Side Effects: 310218730Ssteve * Resumes(and possibly migrates) jobs. 310318730Ssteve */ 310418730Sstevestatic void 3105104696SjmallettJobRestartJobs(void) 310618730Ssteve{ 3107144494Sharti Job *job; 3108144494Sharti 3109144494Sharti while (!jobFull && (job = TAILQ_FIRST(&stoppedJobs)) != NULL) { 3110144467Sharti DEBUGF(JOB, ("Job queue is not full. " 3111144467Sharti "Restarting a stopped job.\n")); 3112144494Sharti TAILQ_REMOVE(&stoppedJobs, job, link); 3113144494Sharti JobRestart(job); 3114144467Sharti } 311518730Ssteve} 3116146054Sharti 3117146054Sharti/** 3118146054Sharti * Cmd_Exec 3119146054Sharti * Execute the command in cmd, and return the output of that command 3120146054Sharti * in a string. 3121146054Sharti * 3122146054Sharti * Results: 3123146054Sharti * A string containing the output of the command, or the empty string 3124146054Sharti * If error is not NULL, it contains the reason for the command failure 3125146129Sharti * Any output sent to stderr in the child process is passed to stderr, 3126146129Sharti * and not captured in the string. 3127146054Sharti * 3128146054Sharti * Side Effects: 3129146054Sharti * The string must be freed by the caller. 3130146054Sharti */ 3131146054ShartiBuffer * 3132146054ShartiCmd_Exec(const char *cmd, const char **error) 3133146054Sharti{ 3134146054Sharti int fds[2]; /* Pipe streams */ 3135146054Sharti int status; /* command exit status */ 3136146054Sharti Buffer *buf; /* buffer to store the result */ 3137146054Sharti ssize_t rcnt; 3138146129Sharti ProcStuff ps; 3139146054Sharti 3140146054Sharti *error = NULL; 3141146054Sharti buf = Buf_Init(0); 3142146054Sharti 3143146054Sharti if (shellPath == NULL) 3144146054Sharti Shell_Init(); 3145146054Sharti /* 3146146054Sharti * Open a pipe for fetching its output 3147146054Sharti */ 3148146054Sharti if (pipe(fds) == -1) { 3149146054Sharti *error = "Couldn't create pipe for \"%s\""; 3150146054Sharti return (buf); 3151146054Sharti } 3152146054Sharti 3153146129Sharti /* Set close-on-exec on read side of pipe. */ 3154146129Sharti fcntl(fds[0], F_SETFD, fcntl(fds[0], F_GETFD) | FD_CLOEXEC); 3155146129Sharti 3156146129Sharti ps.in = STDIN_FILENO; 3157146129Sharti ps.out = fds[1]; 3158146129Sharti ps.err = STDERR_FILENO; 3159146129Sharti 3160146129Sharti ps.merge_errors = 0; 3161146129Sharti ps.pgroup = 0; 3162146129Sharti ps.searchpath = 0; 3163146129Sharti 3164146129Sharti /* Set up arguments for shell */ 3165146129Sharti ps.argv = emalloc(4 * sizeof(char *)); 3166146129Sharti ps.argv[0] = strdup(shellName); 3167146129Sharti ps.argv[1] = strdup("-c"); 3168146129Sharti ps.argv[2] = strdup(cmd); 3169146129Sharti ps.argv[3] = NULL; 3170146129Sharti 3171146054Sharti /* 3172146129Sharti * Fork. Warning since we are doing vfork() instead of fork(), 3173146129Sharti * do not allocate memory in the child process! 3174146054Sharti */ 3175146130Sharti if ((ps.child_pid = vfork()) == -1) { 3176146058Sharti *error = "Couldn't exec \"%s\""; 3177146058Sharti return (buf); 3178146058Sharti 3179146130Sharti } else if (ps.child_pid == 0) { 3180146129Sharti /* 3181146129Sharti * Child 3182146129Sharti */ 3183146129Sharti ProcExec(&ps); 3184146129Sharti /* NOTREACHED */ 3185146129Sharti } 3186146054Sharti 3187146129Sharti free(ps.argv[2]); 3188146129Sharti free(ps.argv[1]); 3189146129Sharti free(ps.argv[0]); 3190146129Sharti free(ps.argv); 3191146054Sharti 3192146129Sharti close(fds[1]); /* No need for the writing half of the pipe. */ 3193146054Sharti 3194146058Sharti do { 3195146058Sharti char result[BUFSIZ]; 3196146054Sharti 3197146058Sharti rcnt = read(fds[0], result, sizeof(result)); 3198146058Sharti if (rcnt != -1) 3199146058Sharti Buf_AddBytes(buf, (size_t)rcnt, (Byte *)result); 3200146058Sharti } while (rcnt > 0 || (rcnt == -1 && errno == EINTR)); 3201146054Sharti 3202146058Sharti if (rcnt == -1) 3203146058Sharti *error = "Error reading shell's output for \"%s\""; 3204146054Sharti 3205146058Sharti /* 3206146058Sharti * Close the input side of the pipe. 3207146058Sharti */ 3208146058Sharti close(fds[0]); 3209146054Sharti 3210146130Sharti status = ProcWait(&ps); 3211146054Sharti 3212146058Sharti if (status) 3213146058Sharti *error = "\"%s\" returned non-zero status"; 3214146054Sharti 3215146058Sharti Buf_StripNewlines(buf); 3216146054Sharti 3217146054Sharti return (buf); 3218146054Sharti} 3219146054Sharti 3220146056Sharti 3221146056Sharti/* 3222146056Sharti * Interrupt handler - set flag and defer handling to the main code 3223146056Sharti */ 3224146056Shartistatic void 3225146056ShartiCompatCatchSig(int signo) 3226146056Sharti{ 3227146056Sharti 3228146056Sharti interrupted = signo; 3229146056Sharti} 3230146056Sharti 3231146056Sharti/*- 3232146056Sharti *----------------------------------------------------------------------- 3233146056Sharti * CompatInterrupt -- 3234146056Sharti * Interrupt the creation of the current target and remove it if 3235146056Sharti * it ain't precious. 3236146056Sharti * 3237146056Sharti * Results: 3238146056Sharti * None. 3239146056Sharti * 3240146056Sharti * Side Effects: 3241146056Sharti * The target is removed and the process exits. If .INTERRUPT exists, 3242146056Sharti * its commands are run first WITH INTERRUPTS IGNORED.. 3243146056Sharti * 3244146056Sharti *----------------------------------------------------------------------- 3245146056Sharti */ 3246146056Shartistatic void 3247146056ShartiCompatInterrupt(int signo) 3248146056Sharti{ 3249146056Sharti GNode *gn; 3250146056Sharti sigset_t nmask, omask; 3251146056Sharti LstNode *ln; 3252146056Sharti 3253146056Sharti sigemptyset(&nmask); 3254146056Sharti sigaddset(&nmask, SIGINT); 3255146056Sharti sigaddset(&nmask, SIGTERM); 3256146056Sharti sigaddset(&nmask, SIGHUP); 3257146056Sharti sigaddset(&nmask, SIGQUIT); 3258146056Sharti sigprocmask(SIG_SETMASK, &nmask, &omask); 3259146056Sharti 3260146056Sharti /* prevent recursion in evaluation of .INTERRUPT */ 3261146056Sharti interrupted = 0; 3262146056Sharti 3263146056Sharti if (curTarg != NULL && !Targ_Precious(curTarg)) { 3264146056Sharti char *p1; 3265146061Sharti char *file = Var_Value(TARGET, curTarg, &p1); 3266146056Sharti 3267146056Sharti if (!noExecute && eunlink(file) != -1) { 3268146056Sharti printf("*** %s removed\n", file); 3269146056Sharti } 3270146056Sharti free(p1); 3271146056Sharti } 3272146056Sharti 3273146056Sharti /* 3274146056Sharti * Run .INTERRUPT only if hit with interrupt signal 3275146056Sharti */ 3276146056Sharti if (signo == SIGINT) { 3277146056Sharti gn = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 3278146056Sharti if (gn != NULL) { 3279146056Sharti LST_FOREACH(ln, &gn->commands) { 3280146056Sharti if (Compat_RunCommand(Lst_Datum(ln), gn)) 3281146056Sharti break; 3282146056Sharti } 3283146056Sharti } 3284146056Sharti } 3285146056Sharti 3286146056Sharti sigprocmask(SIG_SETMASK, &omask, NULL); 3287146056Sharti 3288146056Sharti if (signo == SIGQUIT) 3289146056Sharti exit(signo); 3290146056Sharti signal(signo, SIG_DFL); 3291146056Sharti kill(getpid(), signo); 3292146056Sharti} 3293146056Sharti 3294146129Sharti/** 3295146129Sharti * shellneed 3296146056Sharti * 3297146056Sharti * Results: 3298146129Sharti * Returns NULL if a specified line must be executed by the shell, 3299146129Sharti * and an argument vector if it can be run via execvp(). 3300146056Sharti * 3301146056Sharti * Side Effects: 3302146056Sharti * Uses brk_string so destroys the contents of argv. 3303146056Sharti */ 3304146129Shartistatic char ** 3305146056Shartishellneed(char *cmd) 3306146056Sharti{ 3307146056Sharti char **av; 3308146056Sharti const char **p; 3309146056Sharti 3310146129Sharti if (strpbrk(cmd, sh_meta) != NULL) 3311146129Sharti return (NULL); 3312146129Sharti 3313146147Sharti /* 3314146147Sharti * Break the command into words to form an argument 3315146147Sharti * vector we can execute. brk_string sticks NULL 3316146147Sharti * in av[0], so we have to skip over it... 3317146147Sharti */ 3318146056Sharti av = brk_string(cmd, NULL, TRUE); 3319146056Sharti for (p = sh_builtin; *p != 0; p++) 3320146056Sharti if (strcmp(av[1], *p) == 0) 3321146129Sharti return (NULL); 3322146129Sharti return (av + 1); 3323146056Sharti} 3324146056Sharti 3325146056Sharti/*- 3326146056Sharti *----------------------------------------------------------------------- 3327146056Sharti * Compat_RunCommand -- 3328146056Sharti * Execute the next command for a target. If the command returns an 3329146056Sharti * error, the node's made field is set to ERROR and creation stops. 3330146056Sharti * The node from which the command came is also given. 3331146056Sharti * 3332146056Sharti * Results: 3333146056Sharti * 0 if the command succeeded, 1 if an error occurred. 3334146056Sharti * 3335146056Sharti * Side Effects: 3336146056Sharti * The node's 'made' field may be set to ERROR. 3337146056Sharti * 3338146056Sharti *----------------------------------------------------------------------- 3339146056Sharti */ 3340146142Shartistatic int 3341146056ShartiCompat_RunCommand(char *cmd, GNode *gn) 3342146056Sharti{ 3343146056Sharti char *cmdStart; /* Start of expanded command */ 3344146056Sharti Boolean silent; /* Don't print command */ 3345146056Sharti Boolean doit; /* Execute even in -n */ 3346146056Sharti Boolean errCheck; /* Check errors */ 3347146056Sharti int reason; /* Reason for child's death */ 3348146056Sharti int status; /* Description of child's death */ 3349146056Sharti LstNode *cmdNode; /* Node where current command is located */ 3350146056Sharti char **av; /* Argument vector for thing to exec */ 3351146056Sharti char *cmd_save; /* saved cmd */ 3352146129Sharti ProcStuff ps; 3353146056Sharti 3354146056Sharti silent = gn->type & OP_SILENT; 3355146056Sharti errCheck = !(gn->type & OP_IGNORE); 3356146056Sharti doit = FALSE; 3357146056Sharti 3358146056Sharti cmdNode = Lst_Member(&gn->commands, cmd); 3359146056Sharti cmdStart = Buf_Peel(Var_Subst(cmd, gn, FALSE)); 3360146056Sharti 3361146056Sharti /* 3362146056Sharti * brk_string will return an argv with a NULL in av[0], thus causing 3363146129Sharti * execvp() to choke and die horribly. Besides, how can we execute a 3364146129Sharti * null command? In any case, we warn the user that the command 3365146129Sharti * expanded to nothing (is this the right thing to do?). 3366146056Sharti */ 3367146056Sharti if (*cmdStart == '\0') { 3368146056Sharti free(cmdStart); 3369146056Sharti Error("%s expands to empty string", cmd); 3370146056Sharti return (0); 3371146056Sharti } else { 3372146056Sharti cmd = cmdStart; 3373146056Sharti } 3374146056Sharti Lst_Replace(cmdNode, cmdStart); 3375146056Sharti 3376146056Sharti if ((gn->type & OP_SAVE_CMDS) && (gn != ENDNode)) { 3377146056Sharti Lst_AtEnd(&ENDNode->commands, cmdStart); 3378146056Sharti return (0); 3379146056Sharti } else if (strcmp(cmdStart, "...") == 0) { 3380146056Sharti gn->type |= OP_SAVE_CMDS; 3381146056Sharti return (0); 3382146056Sharti } 3383146056Sharti 3384146056Sharti while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 3385146056Sharti switch (*cmd) { 3386146056Sharti 3387146056Sharti case '@': 3388146056Sharti silent = DEBUG(LOUD) ? FALSE : TRUE; 3389146056Sharti break; 3390146056Sharti 3391146056Sharti case '-': 3392146056Sharti errCheck = FALSE; 3393146056Sharti break; 3394146056Sharti 3395146129Sharti case '+': 3396146056Sharti doit = TRUE; 3397146056Sharti break; 3398146056Sharti } 3399146056Sharti cmd++; 3400146056Sharti } 3401146056Sharti 3402146056Sharti while (isspace((unsigned char)*cmd)) 3403146056Sharti cmd++; 3404146056Sharti 3405146056Sharti /* 3406146056Sharti * Print the command before echoing if we're not supposed to be quiet 3407146056Sharti * for this one. We also print the command if -n given, but not if '+'. 3408146056Sharti */ 3409146056Sharti if (!silent || (noExecute && !doit)) { 3410146056Sharti printf("%s\n", cmd); 3411146056Sharti fflush(stdout); 3412146056Sharti } 3413146056Sharti 3414146056Sharti /* 3415146056Sharti * If we're not supposed to execute any commands, this is as far as 3416146056Sharti * we go... 3417146056Sharti */ 3418146056Sharti if (!doit && noExecute) { 3419146056Sharti return (0); 3420146056Sharti } 3421146056Sharti 3422146129Sharti ps.in = STDIN_FILENO; 3423146129Sharti ps.out = STDOUT_FILENO; 3424146129Sharti ps.err = STDERR_FILENO; 3425146056Sharti 3426146129Sharti ps.merge_errors = 0; 3427146129Sharti ps.pgroup = 0; 3428146129Sharti ps.searchpath = 1; 3429146056Sharti 3430146129Sharti if ((av = shellneed(cmd)) == NULL) { 3431146056Sharti /* 3432146129Sharti * Shell meta character or shell builtin found - pass 3433146129Sharti * command to shell. We give the shell the -e flag as 3434146129Sharti * well as -c if it is supposed to exit when it hits an error. 3435146056Sharti */ 3436146129Sharti ps.argv = emalloc(4 * sizeof(char *)); 3437146129Sharti ps.argv[0] = strdup(shellName); 3438146129Sharti ps.argv[1] = strdup(errCheck ? "-ec" : "-c"); 3439146129Sharti ps.argv[2] = strdup(cmd); 3440146129Sharti ps.argv[3] = NULL; 3441146056Sharti } else { 3442146129Sharti ps.argv = av; 3443146056Sharti } 3444146056Sharti 3445146056Sharti /* 3446146129Sharti * Warning since we are doing vfork() instead of fork(), 3447146129Sharti * do not allocate memory in the child process! 3448146056Sharti */ 3449146130Sharti if ((ps.child_pid = vfork()) == -1) { 3450146056Sharti Fatal("Could not fork"); 3451146058Sharti 3452146130Sharti } else if (ps.child_pid == 0) { 3453146129Sharti /* 3454146129Sharti * Child 3455146129Sharti */ 3456146129Sharti ProcExec(&ps); 3457146129Sharti /* NOTREACHED */ 3458146129Sharti 3459146131Sharti } else { 3460146131Sharti if (av == NULL) { 3461146131Sharti free(ps.argv[2]); 3462146131Sharti free(ps.argv[1]); 3463146131Sharti free(ps.argv[0]); 3464146131Sharti free(ps.argv); 3465146131Sharti } 3466146129Sharti 3467146131Sharti /* 3468146131Sharti * we need to print out the command associated with this 3469146131Sharti * Gnode in Targ_PrintCmd from Targ_PrintGraph when debugging 3470146131Sharti * at level g2, in main(), Fatal() and DieHorribly(), 3471146131Sharti * therefore do not free it when debugging. 3472146131Sharti */ 3473146131Sharti if (!DEBUG(GRAPH2)) { 3474146131Sharti free(cmdStart); 3475146131Sharti Lst_Replace(cmdNode, cmd_save); 3476146131Sharti } 3477146129Sharti 3478146131Sharti /* 3479146131Sharti * The child is off and running. Now all we can do is wait... 3480146131Sharti */ 3481146131Sharti reason = ProcWait(&ps); 3482146132Sharti 3483146056Sharti if (interrupted) 3484146056Sharti CompatInterrupt(interrupted); 3485146131Sharti 3486146132Sharti /* 3487146132Sharti * Decode and report the reason child exited, then 3488146132Sharti * indicate how we handled it. 3489146132Sharti */ 3490146131Sharti if (WIFEXITED(reason)) { 3491146131Sharti status = WEXITSTATUS(reason); 3492146131Sharti if (status == 0) { 3493146131Sharti return (0); 3494146131Sharti } else { 3495146131Sharti printf("*** Error code %d", status); 3496146131Sharti } 3497146131Sharti } else if (WIFSTOPPED(reason)) { 3498146131Sharti status = WSTOPSIG(reason); 3499146131Sharti } else { 3500146131Sharti status = WTERMSIG(reason); 3501146131Sharti printf("*** Signal %d", status); 3502146131Sharti } 3503146131Sharti 3504146131Sharti if (errCheck) { 3505146131Sharti gn->made = ERROR; 3506146131Sharti if (keepgoing) { 3507146131Sharti /* 3508146131Sharti * Abort the current 3509146131Sharti * target, but let 3510146131Sharti * others continue. 3511146131Sharti */ 3512146131Sharti printf(" (continuing)\n"); 3513146056Sharti } 3514146131Sharti return (status); 3515146056Sharti } else { 3516146131Sharti /* 3517146131Sharti * Continue executing 3518146131Sharti * commands for this target. 3519146131Sharti * If we return 0, this will 3520146131Sharti * happen... 3521146131Sharti */ 3522146131Sharti printf(" (ignored)\n"); 3523146131Sharti return (0); 3524146056Sharti } 3525146056Sharti } 3526146056Sharti} 3527146056Sharti 3528146056Sharti/*- 3529146056Sharti *----------------------------------------------------------------------- 3530146056Sharti * CompatMake -- 3531146056Sharti * Make a target, given the parent, to abort if necessary. 3532146056Sharti * 3533146056Sharti * Side Effects: 3534146056Sharti * If an error is detected and not being ignored, the process exits. 3535146056Sharti * 3536146056Sharti *----------------------------------------------------------------------- 3537146056Sharti */ 3538146056Shartistatic int 3539146056ShartiCompatMake(GNode *gn, GNode *pgn) 3540146056Sharti{ 3541146056Sharti LstNode *ln; 3542146056Sharti 3543146056Sharti if (gn->type & OP_USE) { 3544146056Sharti Make_HandleUse(gn, pgn); 3545146056Sharti 3546146056Sharti } else if (gn->made == UNMADE) { 3547146056Sharti /* 3548146056Sharti * First mark ourselves to be made, then apply whatever 3549146056Sharti * transformations the suffix module thinks are necessary. 3550146056Sharti * Once that's done, we can descend and make all our children. 3551146056Sharti * If any of them has an error but the -k flag was given, our 3552146056Sharti * 'make' field will be set FALSE again. This is our signal to 3553146056Sharti * not attempt to do anything but abort our parent as well. 3554146056Sharti */ 3555146056Sharti gn->make = TRUE; 3556146056Sharti gn->made = BEINGMADE; 3557146056Sharti Suff_FindDeps(gn); 3558146056Sharti LST_FOREACH(ln, &gn->children) 3559146056Sharti CompatMake(Lst_Datum(ln), gn); 3560146056Sharti if (!gn->make) { 3561146056Sharti gn->made = ABORTED; 3562146056Sharti pgn->make = FALSE; 3563146056Sharti return (0); 3564146056Sharti } 3565146056Sharti 3566146056Sharti if (Lst_Member(&gn->iParents, pgn) != NULL) { 3567146056Sharti char *p1; 3568146056Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); 3569146056Sharti free(p1); 3570146056Sharti } 3571146056Sharti 3572146056Sharti /* 3573146056Sharti * All the children were made ok. Now cmtime contains the 3574146056Sharti * modification time of the newest child, we need to find out 3575146056Sharti * if we exist and when we were modified last. The criteria for 3576146056Sharti * datedness are defined by the Make_OODate function. 3577146056Sharti */ 3578146056Sharti DEBUGF(MAKE, ("Examining %s...", gn->name)); 3579146056Sharti if (!Make_OODate(gn)) { 3580146056Sharti gn->made = UPTODATE; 3581146056Sharti DEBUGF(MAKE, ("up-to-date.\n")); 3582146056Sharti return (0); 3583146056Sharti } else { 3584146056Sharti DEBUGF(MAKE, ("out-of-date.\n")); 3585146056Sharti } 3586146056Sharti 3587146056Sharti /* 3588146056Sharti * If the user is just seeing if something is out-of-date, 3589146056Sharti * exit now to tell him/her "yes". 3590146056Sharti */ 3591146056Sharti if (queryFlag) { 3592146056Sharti exit(1); 3593146056Sharti } 3594146056Sharti 3595146056Sharti /* 3596146056Sharti * We need to be re-made. We also have to make sure we've got 3597146056Sharti * a $? variable. To be nice, we also define the $> variable 3598146056Sharti * using Make_DoAllVar(). 3599146056Sharti */ 3600146056Sharti Make_DoAllVar(gn); 3601146056Sharti 3602146056Sharti /* 3603146056Sharti * Alter our type to tell if errors should be ignored or things 3604146056Sharti * should not be printed so Compat_RunCommand knows what to do. 3605146056Sharti */ 3606146056Sharti if (Targ_Ignore(gn)) { 3607146056Sharti gn->type |= OP_IGNORE; 3608146056Sharti } 3609146056Sharti if (Targ_Silent(gn)) { 3610146056Sharti gn->type |= OP_SILENT; 3611146056Sharti } 3612146056Sharti 3613146056Sharti if (Job_CheckCommands(gn, Fatal)) { 3614146056Sharti /* 3615146056Sharti * Our commands are ok, but we still have to worry 3616146056Sharti * about the -t flag... 3617146056Sharti */ 3618146056Sharti if (!touchFlag) { 3619146056Sharti curTarg = gn; 3620146056Sharti LST_FOREACH(ln, &gn->commands) { 3621146056Sharti if (Compat_RunCommand(Lst_Datum(ln), 3622146056Sharti gn)) 3623146056Sharti break; 3624146056Sharti } 3625146056Sharti curTarg = NULL; 3626146056Sharti } else { 3627146056Sharti Job_Touch(gn, gn->type & OP_SILENT); 3628146056Sharti } 3629146056Sharti } else { 3630146056Sharti gn->made = ERROR; 3631146056Sharti } 3632146056Sharti 3633146056Sharti if (gn->made != ERROR) { 3634146056Sharti /* 3635146056Sharti * If the node was made successfully, mark it so, update 3636146056Sharti * its modification time and timestamp all its parents. 3637146056Sharti * Note that for .ZEROTIME targets, the timestamping 3638146056Sharti * isn't done. This is to keep its state from affecting 3639146056Sharti * that of its parent. 3640146056Sharti */ 3641146056Sharti gn->made = MADE; 3642146056Sharti#ifndef RECHECK 3643146056Sharti /* 3644146056Sharti * We can't re-stat the thing, but we can at least take 3645146056Sharti * care of rules where a target depends on a source that 3646146056Sharti * actually creates the target, but only if it has 3647146056Sharti * changed, e.g. 3648146056Sharti * 3649146056Sharti * parse.h : parse.o 3650146056Sharti * 3651146056Sharti * parse.o : parse.y 3652146061Sharti * yacc -d parse.y 3653146061Sharti * cc -c y.tab.c 3654146061Sharti * mv y.tab.o parse.o 3655146061Sharti * cmp -s y.tab.h parse.h || mv y.tab.h parse.h 3656146056Sharti * 3657146056Sharti * In this case, if the definitions produced by yacc 3658146056Sharti * haven't changed from before, parse.h won't have been 3659146056Sharti * updated and gn->mtime will reflect the current 3660146056Sharti * modification time for parse.h. This is something of a 3661146056Sharti * kludge, I admit, but it's a useful one.. 3662146056Sharti * 3663146056Sharti * XXX: People like to use a rule like 3664146056Sharti * 3665146056Sharti * FRC: 3666146056Sharti * 3667146056Sharti * To force things that depend on FRC to be made, so we 3668146056Sharti * have to check for gn->children being empty as well... 3669146056Sharti */ 3670146056Sharti if (!Lst_IsEmpty(&gn->commands) || 3671146056Sharti Lst_IsEmpty(&gn->children)) { 3672146056Sharti gn->mtime = now; 3673146056Sharti } 3674146056Sharti#else 3675146056Sharti /* 3676146056Sharti * This is what Make does and it's actually a good 3677146056Sharti * thing, as it allows rules like 3678146056Sharti * 3679146056Sharti * cmp -s y.tab.h parse.h || cp y.tab.h parse.h 3680146056Sharti * 3681146056Sharti * to function as intended. Unfortunately, thanks to 3682146056Sharti * the stateless nature of NFS (and the speed of this 3683146056Sharti * program), there are times when the modification time 3684146056Sharti * of a file created on a remote machine will not be 3685146056Sharti * modified before the stat() implied by the Dir_MTime 3686146056Sharti * occurs, thus leading us to believe that the file 3687146056Sharti * is unchanged, wreaking havoc with files that depend 3688146056Sharti * on this one. 3689146056Sharti * 3690146056Sharti * I have decided it is better to make too much than to 3691146056Sharti * make too little, so this stuff is commented out 3692146056Sharti * unless you're sure it's ok. 3693146056Sharti * -- ardeb 1/12/88 3694146056Sharti */ 3695146056Sharti if (noExecute || Dir_MTime(gn) == 0) { 3696146056Sharti gn->mtime = now; 3697146056Sharti } 3698146056Sharti if (gn->cmtime > gn->mtime) 3699146056Sharti gn->mtime = gn->cmtime; 3700146056Sharti DEBUGF(MAKE, ("update time: %s\n", 3701146056Sharti Targ_FmtTime(gn->mtime))); 3702146056Sharti#endif 3703146056Sharti if (!(gn->type & OP_EXEC)) { 3704146056Sharti pgn->childMade = TRUE; 3705146056Sharti Make_TimeStamp(pgn, gn); 3706146056Sharti } 3707146056Sharti 3708146056Sharti } else if (keepgoing) { 3709146056Sharti pgn->make = FALSE; 3710146056Sharti 3711146056Sharti } else { 3712146056Sharti char *p1; 3713146056Sharti 3714146056Sharti printf("\n\nStop in %s.\n", 3715146056Sharti Var_Value(".CURDIR", gn, &p1)); 3716146056Sharti free(p1); 3717146056Sharti exit(1); 3718146056Sharti } 3719146056Sharti } else if (gn->made == ERROR) { 3720146056Sharti /* 3721146056Sharti * Already had an error when making this beastie. Tell the 3722146056Sharti * parent to abort. 3723146056Sharti */ 3724146056Sharti pgn->make = FALSE; 3725146056Sharti } else { 3726146056Sharti if (Lst_Member(&gn->iParents, pgn) != NULL) { 3727146056Sharti char *p1; 3728146056Sharti Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), pgn); 3729146056Sharti free(p1); 3730146056Sharti } 3731146056Sharti switch(gn->made) { 3732146056Sharti case BEINGMADE: 3733146056Sharti Error("Graph cycles through %s\n", gn->name); 3734146056Sharti gn->made = ERROR; 3735146056Sharti pgn->make = FALSE; 3736146056Sharti break; 3737146056Sharti case MADE: 3738146056Sharti if ((gn->type & OP_EXEC) == 0) { 3739146056Sharti pgn->childMade = TRUE; 3740146056Sharti Make_TimeStamp(pgn, gn); 3741146056Sharti } 3742146056Sharti break; 3743146056Sharti case UPTODATE: 3744146056Sharti if ((gn->type & OP_EXEC) == 0) { 3745146056Sharti Make_TimeStamp(pgn, gn); 3746146056Sharti } 3747146056Sharti break; 3748146056Sharti default: 3749146056Sharti break; 3750146056Sharti } 3751146056Sharti } 3752146056Sharti 3753146056Sharti return (0); 3754146056Sharti} 3755146056Sharti 3756146056Sharti/*- 3757146056Sharti *----------------------------------------------------------------------- 3758146056Sharti * Compat_Run -- 3759146056Sharti * Start making again, given a list of target nodes. 3760146056Sharti * 3761146056Sharti * Results: 3762146056Sharti * None. 3763146056Sharti * 3764146056Sharti * Side Effects: 3765146056Sharti * Guess what? 3766146056Sharti * 3767146056Sharti *----------------------------------------------------------------------- 3768146056Sharti */ 3769146056Shartivoid 3770146056ShartiCompat_Run(Lst *targs) 3771146056Sharti{ 3772146056Sharti GNode *gn = NULL; /* Current root target */ 3773146056Sharti int error_cnt; /* Number of targets not remade due to errors */ 3774146056Sharti LstNode *ln; 3775146056Sharti 3776146056Sharti Shell_Init(); /* Set up shell. */ 3777146056Sharti 3778146056Sharti if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 3779146056Sharti signal(SIGINT, CompatCatchSig); 3780146056Sharti } 3781146056Sharti if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 3782146056Sharti signal(SIGTERM, CompatCatchSig); 3783146056Sharti } 3784146056Sharti if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 3785146056Sharti signal(SIGHUP, CompatCatchSig); 3786146056Sharti } 3787146056Sharti if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 3788146056Sharti signal(SIGQUIT, CompatCatchSig); 3789146056Sharti } 3790146056Sharti 3791146056Sharti ENDNode = Targ_FindNode(".END", TARG_CREATE); 3792146056Sharti /* 3793146056Sharti * If the user has defined a .BEGIN target, execute the commands 3794146056Sharti * attached to it. 3795146056Sharti */ 3796146056Sharti if (!queryFlag) { 3797146056Sharti gn = Targ_FindNode(".BEGIN", TARG_NOCREATE); 3798146056Sharti if (gn != NULL) { 3799146056Sharti LST_FOREACH(ln, &gn->commands) { 3800146056Sharti if (Compat_RunCommand(Lst_Datum(ln), gn)) 3801146056Sharti break; 3802146056Sharti } 3803146056Sharti if (gn->made == ERROR) { 3804146056Sharti printf("\n\nStop.\n"); 3805146056Sharti exit(1); 3806146056Sharti } 3807146056Sharti } 3808146056Sharti } 3809146056Sharti 3810146056Sharti /* 3811146056Sharti * For each entry in the list of targets to create, call CompatMake on 3812146056Sharti * it to create the thing. CompatMake will leave the 'made' field of gn 3813146056Sharti * in one of several states: 3814146056Sharti * UPTODATE gn was already up-to-date 3815146056Sharti * MADE gn was recreated successfully 3816146056Sharti * ERROR An error occurred while gn was being created 3817146056Sharti * ABORTED gn was not remade because one of its inferiors 3818146056Sharti * could not be made due to errors. 3819146056Sharti */ 3820146056Sharti error_cnt = 0; 3821146056Sharti while (!Lst_IsEmpty(targs)) { 3822146056Sharti gn = Lst_DeQueue(targs); 3823146056Sharti CompatMake(gn, gn); 3824146056Sharti 3825146056Sharti if (gn->made == UPTODATE) { 3826146056Sharti printf("`%s' is up to date.\n", gn->name); 3827146056Sharti } else if (gn->made == ABORTED) { 3828146056Sharti printf("`%s' not remade because of errors.\n", 3829146056Sharti gn->name); 3830146056Sharti error_cnt += 1; 3831146056Sharti } 3832146056Sharti } 3833146056Sharti 3834146056Sharti /* 3835146056Sharti * If the user has defined a .END target, run its commands. 3836146056Sharti */ 3837146056Sharti if (error_cnt == 0) { 3838146056Sharti LST_FOREACH(ln, &ENDNode->commands) { 3839146056Sharti if (Compat_RunCommand(Lst_Datum(ln), gn)) 3840146056Sharti break; 3841146056Sharti } 3842146056Sharti } 3843146056Sharti} 3844