1 /* 2 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 3 * Copyright (c) 1988, 1989 by Adam de Boor 4 * Copyright (c) 1989 by Berkeley Softworks 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #ifndef lint 40 /*static char sccsid[] = "from: @(#)job.c 5.15 (Berkeley) 3/1/91";*/ 41 static char rcsid[] = "$Id: job.c,v 1.3 1993/08/01 18:11:48 mycroft Exp $"; 42 #endif /* not lint */ 43 44 /*- 45 * job.c -- 46 * handle the creation etc. of our child processes. 47 * 48 * Interface: 49 * Job_Make Start the creation of the given target. 50 * 51 * Job_CatchChildren Check for and handle the termination of any 52 * children. This must be called reasonably 53 * frequently to keep the whole make going at 54 * a decent clip, since job table entries aren't 55 * removed until their process is caught this way. 56 * Its single argument is TRUE if the function 57 * should block waiting for a child to terminate. 58 * 59 * Job_CatchOutput Print any output our children have produced. 60 * Should also be called fairly frequently to 61 * keep the user informed of what's going on. 62 * If no output is waiting, it will block for 63 * a time given by the SEL_* constants, below, 64 * or until output is ready. 65 * 66 * Job_Init Called to intialize this module. in addition, 67 * any commands attached to the .BEGIN target 68 * are executed before this function returns. 69 * Hence, the makefile must have been parsed 70 * before this function is called. 71 * 72 * Job_Full Return TRUE if the job table is filled. 73 * 74 * Job_Empty Return TRUE if the job table is completely 75 * empty. 76 * 77 * Job_ParseShell Given the line following a .SHELL target, parse 78 * the line as a shell specification. Returns 79 * FAILURE if the spec was incorrect. 80 * 81 * Job_End Perform any final processing which needs doing. 82 * This includes the execution of any commands 83 * which have been/were attached to the .END 84 * target. It should only be called when the 85 * job table is empty. 86 * 87 * Job_AbortAll Abort all currently running jobs. It doesn't 88 * handle output or do anything for the jobs, 89 * just kills them. It should only be called in 90 * an emergency, as it were. 91 * 92 * Job_CheckCommands Verify that the commands for a target are 93 * ok. Provide them if necessary and possible. 94 * 95 * Job_Touch Update a target without really updating it. 96 * 97 * Job_Wait Wait for all currently-running jobs to finish. 98 */ 99 100 #include "make.h" 101 #include <sys/signal.h> 102 #include <sys/stat.h> 103 #include <sys/file.h> 104 #include <sys/time.h> 105 #include <sys/wait.h> 106 #include <fcntl.h> 107 #include <errno.h> 108 #include <stdio.h> 109 #include <string.h> 110 #include <ctype.h> 111 #include "job.h" 112 #include "pathnames.h" 113 114 extern int errno; 115 116 /* 117 * error handling variables 118 */ 119 int errors = 0; /* number of errors reported */ 120 int aborting = 0; /* why is the make aborting? */ 121 #define ABORT_ERROR 1 /* Because of an error */ 122 #define ABORT_INTERRUPT 2 /* Because it was interrupted */ 123 #define ABORT_WAIT 3 /* Waiting for jobs to finish */ 124 125 126 /* 127 * post-make command processing. The node postCommands is really just the 128 * .END target but we keep it around to avoid having to search for it 129 * all the time. 130 */ 131 static GNode *postCommands; /* node containing commands to execute when 132 * everything else is done */ 133 static int numCommands; /* The number of commands actually printed 134 * for a target. Should this number be 135 * 0, no shell will be executed. */ 136 137 138 /* 139 * Return values from JobStart. 140 */ 141 #define JOB_RUNNING 0 /* Job is running */ 142 #define JOB_ERROR 1 /* Error in starting the job */ 143 #define JOB_FINISHED 2 /* The job is already finished */ 144 #define JOB_STOPPED 3 /* The job is stopped */ 145 146 /* 147 * tfile is the name of a file into which all shell commands are put. It is 148 * used over by removing it before the child shell is executed. The XXXXX in 149 * the string are replaced by the pid of the make process in a 5-character 150 * field with leading zeroes. 151 */ 152 static char tfile[] = TMPPAT; 153 154 155 /* 156 * Descriptions for various shells. 157 */ 158 static Shell shells[] = { 159 /* 160 * CSH description. The csh can do echo control by playing 161 * with the setting of the 'echo' shell variable. Sadly, 162 * however, it is unable to do error control nicely. 163 */ 164 { 165 "csh", 166 TRUE, "unset verbose", "set verbose", "unset verbose", 10, 167 FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"", 168 "v", "e", 169 }, 170 /* 171 * SH description. Echo control is also possible and, under 172 * sun UNIX anyway, one can even control error checking. 173 */ 174 { 175 "sh", 176 TRUE, "set -", "set -v", "set -", 5, 177 FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n", 178 "v", "e", 179 }, 180 /* 181 * UNKNOWN. 182 */ 183 { 184 (char *)0, 185 FALSE, (char *)0, (char *)0, (char *)0, 0, 186 FALSE, (char *)0, (char *)0, 187 (char *)0, (char *)0, 188 } 189 }; 190 Shell *commandShell = &shells[DEFSHELL]; /* this is the shell to 191 * which we pass all 192 * commands in the Makefile. 193 * It is set by the 194 * Job_ParseShell function */ 195 char *shellPath = (char *) NULL, /* full pathname of 196 * executable image */ 197 *shellName; /* last component of shell */ 198 199 200 static int maxJobs; /* The most children we can run at once */ 201 static int maxLocal; /* The most local ones we can have */ 202 int nJobs; /* The number of children currently running */ 203 int nLocal; /* The number of local children */ 204 Lst jobs; /* The structures that describe them */ 205 Boolean jobFull; /* Flag to tell when the job table is full. It 206 * is set TRUE when (1) the total number of 207 * running jobs equals the maximum allowed or 208 * (2) a job can only be run locally, but 209 * nLocal equals maxLocal */ 210 #ifndef RMT_WILL_WATCH 211 static fd_set outputs; /* Set of descriptors of pipes connected to 212 * the output channels of children */ 213 #endif 214 215 GNode *lastNode; /* The node for which output was most recently 216 * produced. */ 217 char *targFmt; /* Format string to use to head output from a 218 * job when it's not the most-recent job heard 219 * from */ 220 #define TARG_FMT "--- %s ---\n" /* Default format */ 221 222 /* 223 * When JobStart attempts to run a job remotely but can't, and isn't allowed 224 * to run the job locally, or when Job_CatchChildren detects a job that has 225 * been migrated home, the job is placed on the stoppedJobs queue to be run 226 * when the next job finishes. 227 */ 228 Lst stoppedJobs; /* Lst of Job structures describing 229 * jobs that were stopped due to concurrency 230 * limits or migration home */ 231 232 233 # if defined(USE_PGRP) 234 #define KILL(pid,sig) killpg((pid),(sig)) 235 # else 236 #define KILL(pid,sig) kill((pid),(sig)) 237 # endif 238 239 static void JobRestart(); 240 static int JobStart(); 241 static void JobInterrupt(); 242 243 /*- 244 *----------------------------------------------------------------------- 245 * JobCondPassSig -- 246 * Pass a signal to a job if the job is remote or if USE_PGRP 247 * is defined. 248 * 249 * Results: 250 * === 0 251 * 252 * Side Effects: 253 * None, except the job may bite it. 254 * 255 *----------------------------------------------------------------------- 256 */ 257 static int 258 JobCondPassSig(job, signo) 259 Job *job; /* Job to biff */ 260 int signo; /* Signal to send it */ 261 { 262 #ifdef RMT_WANTS_SIGNALS 263 if (job->flags & JOB_REMOTE) { 264 (void)Rmt_Signal(job, signo); 265 } else { 266 KILL(job->pid, signo); 267 } 268 #else 269 /* 270 * Assume that sending the signal to job->pid will signal any remote 271 * job as well. 272 */ 273 KILL(job->pid, signo); 274 #endif 275 return(0); 276 } 277 278 /*- 279 *----------------------------------------------------------------------- 280 * JobPassSig -- 281 * Pass a signal on to all remote jobs and to all local jobs if 282 * USE_PGRP is defined, then die ourselves. 283 * 284 * Results: 285 * None. 286 * 287 * Side Effects: 288 * We die by the same signal. 289 * 290 *----------------------------------------------------------------------- 291 */ 292 static void 293 JobPassSig(signo) 294 int signo; /* The signal number we've received */ 295 { 296 int mask; 297 298 Lst_ForEach(jobs, JobCondPassSig, (ClientData)signo); 299 300 /* 301 * Deal with proper cleanup based on the signal received. We only run 302 * the .INTERRUPT target if the signal was in fact an interrupt. The other 303 * three termination signals are more of a "get out *now*" command. 304 */ 305 if (signo == SIGINT) { 306 JobInterrupt(TRUE); 307 } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) { 308 JobInterrupt(FALSE); 309 } 310 311 /* 312 * Leave gracefully if SIGQUIT, rather than core dumping. 313 */ 314 if (signo == SIGQUIT) { 315 Finish(); 316 } 317 318 /* 319 * Send ourselves the signal now we've given the message to everyone else. 320 * Note we block everything else possible while we're getting the signal. 321 * This ensures that all our jobs get continued when we wake up before 322 * we take any other signal. 323 */ 324 mask = sigblock(0); 325 (void) sigsetmask(~0 & ~(1 << (signo-1))); 326 signal(signo, SIG_DFL); 327 328 kill(getpid(), signo); 329 330 Lst_ForEach(jobs, JobCondPassSig, (ClientData)SIGCONT); 331 332 sigsetmask(mask); 333 signal(signo, JobPassSig); 334 335 } 336 337 /*- 338 *----------------------------------------------------------------------- 339 * JobCmpPid -- 340 * Compare the pid of the job with the given pid and return 0 if they 341 * are equal. This function is called from Job_CatchChildren via 342 * Lst_Find to find the job descriptor of the finished job. 343 * 344 * Results: 345 * 0 if the pid's match 346 * 347 * Side Effects: 348 * None 349 *----------------------------------------------------------------------- 350 */ 351 static int 352 JobCmpPid (job, pid) 353 int pid; /* process id desired */ 354 Job *job; /* job to examine */ 355 { 356 return (pid - job->pid); 357 } 358 359 /*- 360 *----------------------------------------------------------------------- 361 * JobPrintCommand -- 362 * Put out another command for the given job. If the command starts 363 * with an @ or a - we process it specially. In the former case, 364 * so long as the -s and -n flags weren't given to make, we stick 365 * a shell-specific echoOff command in the script. In the latter, 366 * we ignore errors for the entire job, unless the shell has error 367 * control. 368 * If the command is just "..." we take all future commands for this 369 * job to be commands to be executed once the entire graph has been 370 * made and return non-zero to signal that the end of the commands 371 * was reached. These commands are later attached to the postCommands 372 * node and executed by Job_End when all things are done. 373 * This function is called from JobStart via Lst_ForEach. 374 * 375 * Results: 376 * Always 0, unless the command was "..." 377 * 378 * Side Effects: 379 * If the command begins with a '-' and the shell has no error control, 380 * the JOB_IGNERR flag is set in the job descriptor. 381 * If the command is "..." and we're not ignoring such things, 382 * tailCmds is set to the successor node of the cmd. 383 * numCommands is incremented if the command is actually printed. 384 *----------------------------------------------------------------------- 385 */ 386 static int 387 JobPrintCommand (cmd, job) 388 char *cmd; /* command string to print */ 389 Job *job; /* job for which to print it */ 390 { 391 Boolean noSpecials; /* true if we shouldn't worry about 392 * inserting special commands into 393 * the input stream. */ 394 Boolean shutUp = FALSE; /* true if we put a no echo command 395 * into the command file */ 396 Boolean errOff = FALSE; /* true if we turned error checking 397 * off before printing the command 398 * and need to turn it back on */ 399 char *cmdTemplate; /* Template to use when printing the 400 * command */ 401 char *cmdStart; /* Start of expanded command */ 402 LstNode cmdNode; /* Node for replacing the command */ 403 404 noSpecials = (noExecute && ! (job->node->type & OP_MAKE)); 405 406 if (strcmp (cmd, "...") == 0) { 407 if ((job->flags & JOB_IGNDOTS) == 0) { 408 job->tailCmds = Lst_Succ (Lst_Member (job->node->commands, 409 (ClientData)cmd)); 410 return (1); 411 } 412 return (0); 413 } 414 415 #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) printf (fmt, arg); fprintf (job->cmdFILE, fmt, arg) 416 417 numCommands += 1; 418 419 /* 420 * For debugging, we replace each command with the result of expanding 421 * the variables in the command. 422 */ 423 cmdNode = Lst_Member (job->node->commands, (ClientData)cmd); 424 cmdStart = cmd = Var_Subst (cmd, job->node, FALSE); 425 Lst_Replace (cmdNode, (ClientData)cmdStart); 426 427 cmdTemplate = "%s\n"; 428 429 /* 430 * Check for leading @' and -'s to control echoing and error checking. 431 */ 432 while (*cmd == '@' || *cmd == '-') { 433 if (*cmd == '@') { 434 shutUp = TRUE; 435 } else { 436 errOff = TRUE; 437 } 438 cmd++; 439 } 440 441 while (isspace(*cmd)) cmd++; 442 443 if (shutUp) { 444 if (! (job->flags & JOB_SILENT) && !noSpecials && 445 commandShell->hasEchoCtl) { 446 DBPRINTF ("%s\n", commandShell->echoOff); 447 } else { 448 shutUp = FALSE; 449 } 450 } 451 452 if (errOff) { 453 if ( ! (job->flags & JOB_IGNERR) && !noSpecials) { 454 if (commandShell->hasErrCtl) { 455 /* 456 * we don't want the error-control commands showing 457 * up either, so we turn off echoing while executing 458 * them. We could put another field in the shell 459 * structure to tell JobDoOutput to look for this 460 * string too, but why make it any more complex than 461 * it already is? 462 */ 463 if (! (job->flags & JOB_SILENT) && !shutUp && 464 commandShell->hasEchoCtl) { 465 DBPRINTF ("%s\n", commandShell->echoOff); 466 DBPRINTF ("%s\n", commandShell->ignErr); 467 DBPRINTF ("%s\n", commandShell->echoOn); 468 } else { 469 DBPRINTF ("%s\n", commandShell->ignErr); 470 } 471 } else if (commandShell->ignErr && 472 (*commandShell->ignErr != '\0')) 473 { 474 /* 475 * The shell has no error control, so we need to be 476 * weird to get it to ignore any errors from the command. 477 * If echoing is turned on, we turn it off and use the 478 * errCheck template to echo the command. Leave echoing 479 * off so the user doesn't see the weirdness we go through 480 * to ignore errors. Set cmdTemplate to use the weirdness 481 * instead of the simple "%s\n" template. 482 */ 483 if (! (job->flags & JOB_SILENT) && !shutUp && 484 commandShell->hasEchoCtl) { 485 DBPRINTF ("%s\n", commandShell->echoOff); 486 DBPRINTF (commandShell->errCheck, cmd); 487 shutUp = TRUE; 488 } 489 cmdTemplate = commandShell->ignErr; 490 /* 491 * The error ignoration (hee hee) is already taken care 492 * of by the ignErr template, so pretend error checking 493 * is still on. 494 */ 495 errOff = FALSE; 496 } else { 497 errOff = FALSE; 498 } 499 } else { 500 errOff = FALSE; 501 } 502 } 503 504 DBPRINTF (cmdTemplate, cmd); 505 506 if (errOff) { 507 /* 508 * If echoing is already off, there's no point in issuing the 509 * echoOff command. Otherwise we issue it and pretend it was on 510 * for the whole command... 511 */ 512 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ 513 DBPRINTF ("%s\n", commandShell->echoOff); 514 shutUp = TRUE; 515 } 516 DBPRINTF ("%s\n", commandShell->errCheck); 517 } 518 if (shutUp) { 519 DBPRINTF ("%s\n", commandShell->echoOn); 520 } 521 return (0); 522 } 523 524 /*- 525 *----------------------------------------------------------------------- 526 * JobSaveCommand -- 527 * Save a command to be executed when everything else is done. 528 * Callback function for JobFinish... 529 * 530 * Results: 531 * Always returns 0 532 * 533 * Side Effects: 534 * The command is tacked onto the end of postCommands's commands list. 535 * 536 *----------------------------------------------------------------------- 537 */ 538 static int 539 JobSaveCommand (cmd, gn) 540 char *cmd; 541 GNode *gn; 542 { 543 cmd = Var_Subst (cmd, gn, FALSE); 544 (void)Lst_AtEnd (postCommands->commands, (ClientData)cmd); 545 return (0); 546 } 547 548 /*- 549 *----------------------------------------------------------------------- 550 * JobFinish -- 551 * Do final processing for the given job including updating 552 * parents and starting new jobs as available/necessary. Note 553 * that we pay no attention to the JOB_IGNERR flag here. 554 * This is because when we're called because of a noexecute flag 555 * or something, jstat.w_status is 0 and when called from 556 * Job_CatchChildren, the status is zeroed if it s/b ignored. 557 * 558 * Results: 559 * None 560 * 561 * Side Effects: 562 * Some nodes may be put on the toBeMade queue. 563 * Final commands for the job are placed on postCommands. 564 * 565 * If we got an error and are aborting (aborting == ABORT_ERROR) and 566 * the job list is now empty, we are done for the day. 567 * If we recognized an error (errors !=0), we set the aborting flag 568 * to ABORT_ERROR so no more jobs will be started. 569 *----------------------------------------------------------------------- 570 */ 571 /*ARGSUSED*/ 572 void 573 JobFinish (job, status) 574 Job *job; /* job to finish */ 575 union wait status; /* sub-why job went away */ 576 { 577 Boolean done; 578 579 if ((WIFEXITED(status) && 580 (((status.w_retcode != 0) && !(job->flags & JOB_IGNERR)))) || 581 (WIFSIGNALED(status) && (status.w_termsig != SIGCONT))) 582 { 583 /* 584 * If it exited non-zero and either we're doing things our 585 * way or we're not ignoring errors, the job is finished. 586 * Similarly, if the shell died because of a signal 587 * the job is also finished. In these 588 * cases, finish out the job's output before printing the exit 589 * status... 590 */ 591 if (usePipes) { 592 #ifdef RMT_WILL_WATCH 593 Rmt_Ignore(job->inPipe); 594 #else 595 FD_CLR(job->inPipe, &outputs); 596 #endif /* RMT_WILL_WATCH */ 597 if (job->outPipe != job->inPipe) { 598 (void)close (job->outPipe); 599 } 600 JobDoOutput (job, TRUE); 601 (void)close (job->inPipe); 602 } else { 603 (void)close (job->outFd); 604 JobDoOutput (job, TRUE); 605 } 606 607 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 608 fclose(job->cmdFILE); 609 } 610 done = TRUE; 611 } else if (WIFEXITED(status) && status.w_retcode != 0) { 612 /* 613 * Deal with ignored errors in -B mode. We need to print a message 614 * telling of the ignored error as well as setting status.w_status 615 * to 0 so the next command gets run. To do this, we set done to be 616 * TRUE if in -B mode and the job exited non-zero. Note we don't 617 * want to close down any of the streams until we know we're at the 618 * end. 619 */ 620 done = TRUE; 621 } else { 622 /* 623 * No need to close things down or anything. 624 */ 625 done = FALSE; 626 } 627 628 if (done || 629 WIFSTOPPED(status) || 630 (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) || 631 DEBUG(JOB)) 632 { 633 FILE *out; 634 635 if (!usePipes && (job->flags & JOB_IGNERR)) { 636 /* 637 * If output is going to a file and this job is ignoring 638 * errors, arrange to have the exit status sent to the 639 * output file as well. 640 */ 641 out = fdopen (job->outFd, "w"); 642 } else { 643 out = stdout; 644 } 645 646 if (WIFEXITED(status)) { 647 if (status.w_retcode != 0) { 648 if (usePipes && job->node != lastNode) { 649 fprintf (out, targFmt, job->node->name); 650 lastNode = job->node; 651 } 652 fprintf (out, "*** Error code %d%s\n", status.w_retcode, 653 (job->flags & JOB_IGNERR) ? " (ignored)" : ""); 654 655 if (job->flags & JOB_IGNERR) { 656 status.w_status = 0; 657 } 658 } else if (DEBUG(JOB)) { 659 if (usePipes && job->node != lastNode) { 660 fprintf (out, targFmt, job->node->name); 661 lastNode = job->node; 662 } 663 fprintf (out, "*** Completed successfully\n"); 664 } 665 } else if (WIFSTOPPED(status)) { 666 if (usePipes && job->node != lastNode) { 667 fprintf (out, targFmt, job->node->name); 668 lastNode = job->node; 669 } 670 if (! (job->flags & JOB_REMIGRATE)) { 671 fprintf (out, "*** Stopped -- signal %d\n", status.w_stopsig); 672 } 673 job->flags |= JOB_RESUME; 674 (void)Lst_AtEnd(stoppedJobs, (ClientData)job); 675 fflush(out); 676 return; 677 } else if (status.w_termsig == SIGCONT) { 678 /* 679 * If the beastie has continued, shift the Job from the stopped 680 * list to the running one (or re-stop it if concurrency is 681 * exceeded) and go and get another child. 682 */ 683 if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) { 684 if (usePipes && job->node != lastNode) { 685 fprintf (out, targFmt, job->node->name); 686 lastNode = job->node; 687 } 688 fprintf (out, "*** Continued\n"); 689 } 690 if (! (job->flags & JOB_CONTINUING)) { 691 JobRestart(job); 692 } else { 693 Lst_AtEnd(jobs, (ClientData)job); 694 nJobs += 1; 695 if (! (job->flags & JOB_REMOTE)) { 696 nLocal += 1; 697 } 698 if (nJobs == maxJobs) { 699 jobFull = TRUE; 700 if (DEBUG(JOB)) { 701 printf("Job queue is full.\n"); 702 } 703 } 704 } 705 fflush(out); 706 return; 707 } else { 708 if (usePipes && job->node != lastNode) { 709 fprintf (out, targFmt, job->node->name); 710 lastNode = job->node; 711 } 712 fprintf (out, "*** Signal %d\n", status.w_termsig); 713 } 714 715 fflush (out); 716 } 717 718 /* 719 * Now handle the -B-mode stuff. If the beast still isn't finished, 720 * try and restart the job on the next command. If JobStart says it's 721 * ok, it's ok. If there's an error, this puppy is done. 722 */ 723 if ((status.w_status == 0) && 724 !Lst_IsAtEnd (job->node->commands)) 725 { 726 switch (JobStart (job->node, 727 job->flags & JOB_IGNDOTS, 728 job)) 729 { 730 case JOB_RUNNING: 731 done = FALSE; 732 break; 733 case JOB_ERROR: 734 done = TRUE; 735 status.w_retcode = 1; 736 break; 737 case JOB_FINISHED: 738 /* 739 * If we got back a JOB_FINISHED code, JobStart has already 740 * called Make_Update and freed the job descriptor. We set 741 * done to false here to avoid fake cycles and double frees. 742 * JobStart needs to do the update so we can proceed up the 743 * graph when given the -n flag.. 744 */ 745 done = FALSE; 746 break; 747 } 748 } else { 749 done = TRUE; 750 } 751 752 753 if (done && 754 (aborting != ABORT_ERROR) && 755 (aborting != ABORT_INTERRUPT) && 756 (status.w_status == 0)) 757 { 758 /* 759 * As long as we aren't aborting and the job didn't return a non-zero 760 * status that we shouldn't ignore, we call Make_Update to update 761 * the parents. In addition, any saved commands for the node are placed 762 * on the .END target. 763 */ 764 if (job->tailCmds != NILLNODE) { 765 Lst_ForEachFrom (job->node->commands, job->tailCmds, 766 JobSaveCommand, 767 (ClientData)job->node); 768 } 769 job->node->made = MADE; 770 Make_Update (job->node); 771 free((Address)job); 772 } else if (status.w_status) { 773 errors += 1; 774 free((Address)job); 775 } 776 777 while (!errors && !jobFull && !Lst_IsEmpty(stoppedJobs)) { 778 JobRestart((Job *)Lst_DeQueue(stoppedJobs)); 779 } 780 781 /* 782 * Set aborting if any error. 783 */ 784 if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) { 785 /* 786 * If we found any errors in this batch of children and the -k flag 787 * wasn't given, we set the aborting flag so no more jobs get 788 * started. 789 */ 790 aborting = ABORT_ERROR; 791 } 792 793 if ((aborting == ABORT_ERROR) && Job_Empty()) { 794 /* 795 * If we are aborting and the job table is now empty, we finish. 796 */ 797 (void) unlink (tfile); 798 Finish (errors); 799 } 800 } 801 802 /*- 803 *----------------------------------------------------------------------- 804 * Job_Touch -- 805 * Touch the given target. Called by JobStart when the -t flag was 806 * given 807 * 808 * Results: 809 * None 810 * 811 * Side Effects: 812 * The data modification of the file is changed. In addition, if the 813 * file did not exist, it is created. 814 *----------------------------------------------------------------------- 815 */ 816 void 817 Job_Touch (gn, silent) 818 GNode *gn; /* the node of the file to touch */ 819 Boolean silent; /* TRUE if should not print messages */ 820 { 821 int streamID; /* ID of stream opened to do the touch */ 822 struct timeval times[2]; /* Times for utimes() call */ 823 struct stat attr; /* Attributes of the file */ 824 825 if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) { 826 /* 827 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets 828 * and, as such, shouldn't really be created. 829 */ 830 return; 831 } 832 833 if (!silent) { 834 printf ("touch %s\n", gn->name); 835 } 836 837 if (noExecute) { 838 return; 839 } 840 841 if (gn->type & OP_ARCHV) { 842 Arch_Touch (gn); 843 } else if (gn->type & OP_LIB) { 844 Arch_TouchLib (gn); 845 } else { 846 char *file = gn->path ? gn->path : gn->name; 847 848 times[0].tv_sec = times[1].tv_sec = now; 849 times[0].tv_usec = times[1].tv_usec = 0; 850 if (utimes(file, times) < 0){ 851 streamID = open (file, O_RDWR | O_CREAT, 0666); 852 853 if (streamID >= 0) { 854 char c; 855 856 /* 857 * Read and write a byte to the file to change the 858 * modification time, then close the file. 859 */ 860 if (read(streamID, &c, 1) == 1) { 861 lseek(streamID, 0L, L_SET); 862 write(streamID, &c, 1); 863 } 864 865 (void)close (streamID); 866 } else 867 printf("*** couldn't touch %s: %s", file, strerror(errno)); 868 } 869 } 870 } 871 872 /*- 873 *----------------------------------------------------------------------- 874 * Job_CheckCommands -- 875 * Make sure the given node has all the commands it needs. 876 * 877 * Results: 878 * TRUE if the commands list is/was ok. 879 * 880 * Side Effects: 881 * The node will have commands from the .DEFAULT rule added to it 882 * if it needs them. 883 *----------------------------------------------------------------------- 884 */ 885 Boolean 886 Job_CheckCommands (gn, abortProc) 887 GNode *gn; /* The target whose commands need 888 * verifying */ 889 void (*abortProc)(); /* Function to abort with message */ 890 { 891 if (OP_NOP(gn->type) && Lst_IsEmpty (gn->commands) && 892 (gn->type & OP_LIB) == 0) { 893 /* 894 * No commands. Look for .DEFAULT rule from which we might infer 895 * commands 896 */ 897 if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) { 898 /* 899 * Make only looks for a .DEFAULT if the node was never the 900 * target of an operator, so that's what we do too. If 901 * a .DEFAULT was given, we substitute its commands for gn's 902 * commands and set the IMPSRC variable to be the target's name 903 * The DEFAULT node acts like a transformation rule, in that 904 * gn also inherits any attributes or sources attached to 905 * .DEFAULT itself. 906 */ 907 Make_HandleUse(DEFAULT, gn); 908 Var_Set (IMPSRC, Var_Value (TARGET, gn), gn); 909 } else if (Dir_MTime (gn) == 0) { 910 /* 911 * The node wasn't the target of an operator we have no .DEFAULT 912 * rule to go on and the target doesn't already exist. There's 913 * nothing more we can do for this branch. If the -k flag wasn't 914 * given, we stop in our tracks, otherwise we just don't update 915 * this node's parents so they never get examined. 916 */ 917 if (gn->type & OP_OPTIONAL) { 918 printf ("make: don't know how to make %s (ignored)\n", 919 gn->name); 920 } else if (keepgoing) { 921 printf ("make: don't know how to make %s (continuing)\n", 922 gn->name); 923 return (FALSE); 924 } else { 925 (*abortProc) ("make: don't know how to make %s. Stop", 926 gn->name); 927 return(FALSE); 928 } 929 } 930 } 931 return (TRUE); 932 } 933 #ifdef RMT_WILL_WATCH 934 /*- 935 *----------------------------------------------------------------------- 936 * JobLocalInput -- 937 * Handle a pipe becoming readable. Callback function for Rmt_Watch 938 * 939 * Results: 940 * None 941 * 942 * Side Effects: 943 * JobDoOutput is called. 944 * 945 *----------------------------------------------------------------------- 946 */ 947 /*ARGSUSED*/ 948 static void 949 JobLocalInput(stream, job) 950 int stream; /* Stream that's ready (ignored) */ 951 Job *job; /* Job to which the stream belongs */ 952 { 953 JobDoOutput(job, FALSE); 954 } 955 #endif /* RMT_WILL_WATCH */ 956 957 /*- 958 *----------------------------------------------------------------------- 959 * JobExec -- 960 * Execute the shell for the given job. Called from JobStart and 961 * JobRestart. 962 * 963 * Results: 964 * None. 965 * 966 * Side Effects: 967 * A shell is executed, outputs is altered and the Job structure added 968 * to the job table. 969 * 970 *----------------------------------------------------------------------- 971 */ 972 static void 973 JobExec(job, argv) 974 Job *job; /* Job to execute */ 975 char **argv; 976 { 977 int cpid; /* ID of new child */ 978 979 if (DEBUG(JOB)) { 980 int i; 981 982 printf("Running %s %sly\n", job->node->name, 983 job->flags&JOB_REMOTE?"remote":"local"); 984 printf("\tCommand: "); 985 for (i = 0; argv[i] != (char *)NULL; i++) { 986 printf("%s ", argv[i]); 987 } 988 printf("\n"); 989 } 990 991 /* 992 * Some jobs produce no output and it's disconcerting to have 993 * no feedback of their running (since they produce no output, the 994 * banner with their name in it never appears). This is an attempt to 995 * provide that feedback, even if nothing follows it. 996 */ 997 if ((lastNode != job->node) && (job->flags & JOB_FIRST) && 998 !(job->flags & JOB_SILENT)) 999 { 1000 printf(targFmt, job->node->name); 1001 lastNode = job->node; 1002 } 1003 1004 #ifdef RMT_NO_EXEC 1005 if (job->flags & JOB_REMOTE) { 1006 goto jobExecFinish; 1007 } 1008 #endif /* RMT_NO_EXEC */ 1009 1010 if ((cpid = vfork()) == -1) { 1011 Punt ("Cannot fork"); 1012 } else if (cpid == 0) { 1013 1014 /* 1015 * Must duplicate the input stream down to the child's input and 1016 * reset it to the beginning (again). Since the stream was marked 1017 * close-on-exec, we must clear that bit in the new input. 1018 */ 1019 (void) dup2(fileno(job->cmdFILE), 0); 1020 fcntl(0, F_SETFD, 0); 1021 lseek(0, 0, L_SET); 1022 1023 if (usePipes) { 1024 /* 1025 * Set up the child's output to be routed through the pipe 1026 * we've created for it. 1027 */ 1028 (void) dup2 (job->outPipe, 1); 1029 } else { 1030 /* 1031 * We're capturing output in a file, so we duplicate the 1032 * descriptor to the temporary file into the standard 1033 * output. 1034 */ 1035 (void) dup2 (job->outFd, 1); 1036 } 1037 /* 1038 * The output channels are marked close on exec. This bit was 1039 * duplicated by the dup2 (on some systems), so we have to clear 1040 * it before routing the shell's error output to the same place as 1041 * its standard output. 1042 */ 1043 fcntl(1, F_SETFD, 0); 1044 (void) dup2 (1, 2); 1045 1046 #ifdef USE_PGRP 1047 /* 1048 * We want to switch the child into a different process family so 1049 * we can kill it and all its descendants in one fell swoop, 1050 * by killing its process family, but not commit suicide. 1051 */ 1052 1053 (void) setpgrp(0, getpid()); 1054 #endif USE_PGRP 1055 1056 (void) execv (shellPath, argv); 1057 (void) write (2, "Could not execute shell\n", 1058 sizeof ("Could not execute shell")); 1059 _exit (1); 1060 } else { 1061 job->pid = cpid; 1062 1063 if (usePipes && (job->flags & JOB_FIRST) ) { 1064 /* 1065 * The first time a job is run for a node, we set the current 1066 * position in the buffer to the beginning and mark another 1067 * stream to watch in the outputs mask 1068 */ 1069 job->curPos = 0; 1070 1071 #ifdef RMT_WILL_WATCH 1072 Rmt_Watch(job->inPipe, JobLocalInput, job); 1073 #else 1074 FD_SET(job->inPipe, &outputs); 1075 #endif /* RMT_WILL_WATCH */ 1076 } 1077 1078 if (job->flags & JOB_REMOTE) { 1079 job->rmtID = (char *)0; 1080 } else { 1081 nLocal += 1; 1082 /* 1083 * XXX: Used to not happen if CUSTOMS. Why? 1084 */ 1085 if (job->cmdFILE != stdout) { 1086 fclose(job->cmdFILE); 1087 job->cmdFILE = NULL; 1088 } 1089 } 1090 } 1091 1092 jobExecFinish: 1093 /* 1094 * Now the job is actually running, add it to the table. 1095 */ 1096 nJobs += 1; 1097 (void)Lst_AtEnd (jobs, (ClientData)job); 1098 if (nJobs == maxJobs) { 1099 jobFull = TRUE; 1100 } 1101 } 1102 1103 /*- 1104 *----------------------------------------------------------------------- 1105 * JobMakeArgv -- 1106 * Create the argv needed to execute the shell for a given job. 1107 * 1108 * 1109 * Results: 1110 * 1111 * Side Effects: 1112 * 1113 *----------------------------------------------------------------------- 1114 */ 1115 static void 1116 JobMakeArgv(job, argv) 1117 Job *job; 1118 char **argv; 1119 { 1120 int argc; 1121 static char args[10]; /* For merged arguments */ 1122 1123 argv[0] = shellName; 1124 argc = 1; 1125 1126 if ((commandShell->exit && (*commandShell->exit != '-')) || 1127 (commandShell->echo && (*commandShell->echo != '-'))) 1128 { 1129 /* 1130 * At least one of the flags doesn't have a minus before it, so 1131 * merge them together. Have to do this because the *(&(@*#*&#$# 1132 * Bourne shell thinks its second argument is a file to source. 1133 * Grrrr. Note the ten-character limitation on the combined arguments. 1134 */ 1135 (void)sprintf(args, "-%s%s", 1136 ((job->flags & JOB_IGNERR) ? "" : 1137 (commandShell->exit ? commandShell->exit : "")), 1138 ((job->flags & JOB_SILENT) ? "" : 1139 (commandShell->echo ? commandShell->echo : ""))); 1140 1141 if (args[1]) { 1142 argv[argc] = args; 1143 argc++; 1144 } 1145 } else { 1146 if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1147 argv[argc] = commandShell->exit; 1148 argc++; 1149 } 1150 if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1151 argv[argc] = commandShell->echo; 1152 argc++; 1153 } 1154 } 1155 argv[argc] = (char *)NULL; 1156 } 1157 1158 /*- 1159 *----------------------------------------------------------------------- 1160 * JobRestart -- 1161 * Restart a job that stopped for some reason. 1162 * 1163 * Results: 1164 * None. 1165 * 1166 * Side Effects: 1167 * jobFull will be set if the job couldn't be run. 1168 * 1169 *----------------------------------------------------------------------- 1170 */ 1171 static void 1172 JobRestart(job) 1173 Job *job; /* Job to restart */ 1174 { 1175 if (job->flags & JOB_REMIGRATE) { 1176 if (DEBUG(JOB)) { 1177 printf("Remigrating %x\n", job->pid); 1178 } 1179 if (nLocal != maxLocal) { 1180 /* 1181 * Job cannot be remigrated, but there's room on the local 1182 * machine, so resume the job and note that another 1183 * local job has started. 1184 */ 1185 if (DEBUG(JOB)) { 1186 printf("resuming on local machine\n"); 1187 } 1188 KILL(job->pid, SIGCONT); 1189 nLocal +=1; 1190 job->flags &= ~(JOB_REMIGRATE|JOB_RESUME); 1191 } else { 1192 /* 1193 * Job cannot be restarted. Mark the table as full and 1194 * place the job back on the list of stopped jobs. 1195 */ 1196 if (DEBUG(JOB)) { 1197 printf("holding\n"); 1198 } 1199 (void)Lst_AtFront(stoppedJobs, (ClientData)job); 1200 jobFull = TRUE; 1201 if (DEBUG(JOB)) { 1202 printf("Job queue is full.\n"); 1203 } 1204 return; 1205 } 1206 1207 (void)Lst_AtEnd(jobs, (ClientData)job); 1208 nJobs += 1; 1209 if (nJobs == maxJobs) { 1210 jobFull = TRUE; 1211 if (DEBUG(JOB)) { 1212 printf("Job queue is full.\n"); 1213 } 1214 } 1215 } else if (job->flags & JOB_RESTART) { 1216 /* 1217 * Set up the control arguments to the shell. This is based on the 1218 * flags set earlier for this job. If the JOB_IGNERR flag is clear, 1219 * the 'exit' flag of the commandShell is used to cause it to exit 1220 * upon receiving an error. If the JOB_SILENT flag is clear, the 1221 * 'echo' flag of the commandShell is used to get it to start echoing 1222 * as soon as it starts processing commands. 1223 */ 1224 char *argv[4]; 1225 1226 JobMakeArgv(job, argv); 1227 1228 if (DEBUG(JOB)) { 1229 printf("Restarting %s...", job->node->name); 1230 } 1231 if (((nLocal >= maxLocal) && ! (job->flags & JOB_SPECIAL))) { 1232 /* 1233 * Can't be exported and not allowed to run locally -- put it 1234 * back on the hold queue and mark the table full 1235 */ 1236 if (DEBUG(JOB)) { 1237 printf("holding\n"); 1238 } 1239 (void)Lst_AtFront(stoppedJobs, (ClientData)job); 1240 jobFull = TRUE; 1241 if (DEBUG(JOB)) { 1242 printf("Job queue is full.\n"); 1243 } 1244 return; 1245 } else { 1246 /* 1247 * Job may be run locally. 1248 */ 1249 if (DEBUG(JOB)) { 1250 printf("running locally\n"); 1251 } 1252 job->flags &= ~JOB_REMOTE; 1253 } 1254 JobExec(job, argv); 1255 } else { 1256 /* 1257 * The job has stopped and needs to be restarted. Why it stopped, 1258 * we don't know... 1259 */ 1260 if (DEBUG(JOB)) { 1261 printf("Resuming %s...", job->node->name); 1262 } 1263 if (((job->flags & JOB_REMOTE) || 1264 (nLocal < maxLocal) || 1265 (((job->flags & JOB_SPECIAL)) && 1266 (maxLocal == 0))) && 1267 (nJobs != maxJobs)) 1268 { 1269 /* 1270 * If the job is remote, it's ok to resume it as long as the 1271 * maximum concurrency won't be exceeded. If it's local and 1272 * we haven't reached the local concurrency limit already (or the 1273 * job must be run locally and maxLocal is 0), it's also ok to 1274 * resume it. 1275 */ 1276 Boolean error; 1277 extern int errno; 1278 union wait status; 1279 1280 #ifdef RMT_WANTS_SIGNALS 1281 if (job->flags & JOB_REMOTE) { 1282 error = !Rmt_Signal(job, SIGCONT); 1283 } else 1284 #endif /* RMT_WANTS_SIGNALS */ 1285 error = (KILL(job->pid, SIGCONT) != 0); 1286 1287 if (!error) { 1288 /* 1289 * Make sure the user knows we've continued the beast and 1290 * actually put the thing in the job table. 1291 */ 1292 job->flags |= JOB_CONTINUING; 1293 status.w_termsig = SIGCONT; 1294 JobFinish(job, status); 1295 1296 job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 1297 if (DEBUG(JOB)) { 1298 printf("done\n"); 1299 } 1300 } else { 1301 Error("couldn't resume %s: %s", 1302 job->node->name, strerror(errno)); 1303 status.w_status = 0; 1304 status.w_retcode = 1; 1305 JobFinish(job, status); 1306 } 1307 } else { 1308 /* 1309 * Job cannot be restarted. Mark the table as full and 1310 * place the job back on the list of stopped jobs. 1311 */ 1312 if (DEBUG(JOB)) { 1313 printf("table full\n"); 1314 } 1315 (void)Lst_AtFront(stoppedJobs, (ClientData)job); 1316 jobFull = TRUE; 1317 if (DEBUG(JOB)) { 1318 printf("Job queue is full.\n"); 1319 } 1320 } 1321 } 1322 } 1323 1324 /*- 1325 *----------------------------------------------------------------------- 1326 * JobStart -- 1327 * Start a target-creation process going for the target described 1328 * by the graph node gn. 1329 * 1330 * Results: 1331 * JOB_ERROR if there was an error in the commands, JOB_FINISHED 1332 * if there isn't actually anything left to do for the job and 1333 * JOB_RUNNING if the job has been started. 1334 * 1335 * Side Effects: 1336 * A new Job node is created and added to the list of running 1337 * jobs. PMake is forked and a child shell created. 1338 *----------------------------------------------------------------------- 1339 */ 1340 static int 1341 JobStart (gn, flags, previous) 1342 GNode *gn; /* target to create */ 1343 short flags; /* flags for the job to override normal ones. 1344 * e.g. JOB_SPECIAL or JOB_IGNDOTS */ 1345 Job *previous; /* The previous Job structure for this node, 1346 * if any. */ 1347 { 1348 register Job *job; /* new job descriptor */ 1349 char *argv[4]; /* Argument vector to shell */ 1350 char args[5]; /* arguments to shell */ 1351 static int jobno = 0; /* job number of catching output in a file */ 1352 Boolean cmdsOK; /* true if the nodes commands were all right */ 1353 Boolean local; /* Set true if the job was run locally */ 1354 Boolean noExec; /* Set true if we decide not to run the job */ 1355 1356 if (previous != (Job *)NULL) { 1357 previous->flags &= ~ (JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE); 1358 job = previous; 1359 } else { 1360 job = (Job *) emalloc (sizeof (Job)); 1361 if (job == (Job *)NULL) { 1362 Punt("JobStart out of memory"); 1363 } 1364 flags |= JOB_FIRST; 1365 } 1366 1367 job->node = gn; 1368 job->tailCmds = NILLNODE; 1369 1370 /* 1371 * Set the initial value of the flags for this job based on the global 1372 * ones and the node's attributes... Any flags supplied by the caller 1373 * are also added to the field. 1374 */ 1375 job->flags = 0; 1376 if (Targ_Ignore (gn)) { 1377 job->flags |= JOB_IGNERR; 1378 } 1379 if (Targ_Silent (gn)) { 1380 job->flags |= JOB_SILENT; 1381 } 1382 job->flags |= flags; 1383 1384 /* 1385 * Check the commands now so any attributes from .DEFAULT have a chance 1386 * to migrate to the node 1387 */ 1388 if (job->flags & JOB_FIRST) { 1389 cmdsOK = Job_CheckCommands(gn, Error); 1390 } else { 1391 cmdsOK = TRUE; 1392 } 1393 1394 /* 1395 * If the -n flag wasn't given, we open up OUR (not the child's) 1396 * temporary file to stuff commands in it. The thing is rd/wr so we don't 1397 * need to reopen it to feed it to the shell. If the -n flag *was* given, 1398 * we just set the file to be stdout. Cute, huh? 1399 */ 1400 if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 1401 /* 1402 * We're serious here, but if the commands were bogus, we're 1403 * also dead... 1404 */ 1405 if (!cmdsOK) { 1406 DieHorribly(); 1407 } 1408 1409 job->cmdFILE = fopen (tfile, "w+"); 1410 if (job->cmdFILE == (FILE *) NULL) { 1411 Punt ("Could not open %s", tfile); 1412 } 1413 fcntl(fileno(job->cmdFILE), F_SETFD, 1); 1414 /* 1415 * Send the commands to the command file, flush all its buffers then 1416 * rewind and remove the thing. 1417 */ 1418 noExec = FALSE; 1419 1420 /* 1421 * used to be backwards; replace when start doing multiple commands 1422 * per shell. 1423 */ 1424 if (1) { 1425 /* 1426 * Be compatible: If this is the first time for this node, 1427 * verify its commands are ok and open the commands list for 1428 * sequential access by later invocations of JobStart. 1429 * Once that is done, we take the next command off the list 1430 * and print it to the command file. If the command was an 1431 * ellipsis, note that there's nothing more to execute. 1432 */ 1433 if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){ 1434 cmdsOK = FALSE; 1435 } else { 1436 LstNode ln = Lst_Next (gn->commands); 1437 1438 if ((ln == NILLNODE) || 1439 JobPrintCommand ((char *)Lst_Datum (ln), job)) 1440 { 1441 noExec = TRUE; 1442 Lst_Close (gn->commands); 1443 } 1444 if (noExec && !(job->flags & JOB_FIRST)) { 1445 /* 1446 * If we're not going to execute anything, the job 1447 * is done and we need to close down the various 1448 * file descriptors we've opened for output, then 1449 * call JobDoOutput to catch the final characters or 1450 * send the file to the screen... Note that the i/o streams 1451 * are only open if this isn't the first job. 1452 * Note also that this could not be done in 1453 * Job_CatchChildren b/c it wasn't clear if there were 1454 * more commands to execute or not... 1455 */ 1456 if (usePipes) { 1457 #ifdef RMT_WILL_WATCH 1458 Rmt_Ignore(job->inPipe); 1459 #else 1460 FD_CLR(job->inPipe, &outputs); 1461 #endif 1462 if (job->outPipe != job->inPipe) { 1463 (void)close (job->outPipe); 1464 } 1465 JobDoOutput (job, TRUE); 1466 (void)close (job->inPipe); 1467 } else { 1468 (void)close (job->outFd); 1469 JobDoOutput (job, TRUE); 1470 } 1471 } 1472 } 1473 } else { 1474 /* 1475 * We can do all the commands at once. hooray for sanity 1476 */ 1477 numCommands = 0; 1478 Lst_ForEach (gn->commands, JobPrintCommand, (ClientData)job); 1479 1480 /* 1481 * If we didn't print out any commands to the shell script, 1482 * there's not much point in executing the shell, is there? 1483 */ 1484 if (numCommands == 0) { 1485 noExec = TRUE; 1486 } 1487 } 1488 } else if (noExecute) { 1489 /* 1490 * Not executing anything -- just print all the commands to stdout 1491 * in one fell swoop. This will still set up job->tailCmds correctly. 1492 */ 1493 if (lastNode != gn) { 1494 printf (targFmt, gn->name); 1495 lastNode = gn; 1496 } 1497 job->cmdFILE = stdout; 1498 /* 1499 * Only print the commands if they're ok, but don't die if they're 1500 * not -- just let the user know they're bad and keep going. It 1501 * doesn't do any harm in this case and may do some good. 1502 */ 1503 if (cmdsOK) { 1504 Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job); 1505 } 1506 /* 1507 * Don't execute the shell, thank you. 1508 */ 1509 noExec = TRUE; 1510 } else { 1511 /* 1512 * Just touch the target and note that no shell should be executed. 1513 * Set cmdFILE to stdout to make life easier. Check the commands, too, 1514 * but don't die if they're no good -- it does no harm to keep working 1515 * up the graph. 1516 */ 1517 job->cmdFILE = stdout; 1518 Job_Touch (gn, job->flags&JOB_SILENT); 1519 noExec = TRUE; 1520 } 1521 1522 /* 1523 * If we're not supposed to execute a shell, don't. 1524 */ 1525 if (noExec) { 1526 /* 1527 * Unlink and close the command file if we opened one 1528 */ 1529 if (job->cmdFILE != stdout) { 1530 (void) unlink (tfile); 1531 fclose(job->cmdFILE); 1532 } else { 1533 fflush (stdout); 1534 } 1535 1536 /* 1537 * We only want to work our way up the graph if we aren't here because 1538 * the commands for the job were no good. 1539 */ 1540 if (cmdsOK) { 1541 if (aborting == 0) { 1542 if (job->tailCmds != NILLNODE) { 1543 Lst_ForEachFrom(job->node->commands, job->tailCmds, 1544 JobSaveCommand, 1545 (ClientData)job->node); 1546 } 1547 Make_Update(job->node); 1548 } 1549 free((Address)job); 1550 return(JOB_FINISHED); 1551 } else { 1552 free((Address)job); 1553 return(JOB_ERROR); 1554 } 1555 } else { 1556 fflush (job->cmdFILE); 1557 (void) unlink (tfile); 1558 } 1559 1560 /* 1561 * Set up the control arguments to the shell. This is based on the flags 1562 * set earlier for this job. 1563 */ 1564 JobMakeArgv(job, argv); 1565 1566 /* 1567 * If we're using pipes to catch output, create the pipe by which we'll 1568 * get the shell's output. If we're using files, print out that we're 1569 * starting a job and then set up its temporary-file name. This is just 1570 * tfile with two extra digits tacked on -- jobno. 1571 */ 1572 if (job->flags & JOB_FIRST) { 1573 if (usePipes) { 1574 int fd[2]; 1575 (void) pipe(fd); 1576 job->inPipe = fd[0]; 1577 job->outPipe = fd[1]; 1578 (void)fcntl (job->inPipe, F_SETFD, 1); 1579 (void)fcntl (job->outPipe, F_SETFD, 1); 1580 } else { 1581 printf ("Remaking `%s'\n", gn->name); 1582 fflush (stdout); 1583 sprintf (job->outFile, "%s%02d", tfile, jobno); 1584 jobno = (jobno + 1) % 100; 1585 job->outFd = open(job->outFile,O_WRONLY|O_CREAT|O_APPEND,0600); 1586 (void)fcntl (job->outFd, F_SETFD, 1); 1587 } 1588 } 1589 1590 local = TRUE; 1591 1592 if (local && (((nLocal >= maxLocal) && 1593 !(job->flags & JOB_SPECIAL) && 1594 (maxLocal != 0)))) 1595 { 1596 /* 1597 * The job can only be run locally, but we've hit the limit of 1598 * local concurrency, so put the job on hold until some other job 1599 * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END) 1600 * may be run locally even when the local limit has been reached 1601 * (e.g. when maxLocal == 0), though they will be exported if at 1602 * all possible. 1603 */ 1604 jobFull = TRUE; 1605 1606 if (DEBUG(JOB)) { 1607 printf("Can only run job locally.\n"); 1608 } 1609 job->flags |= JOB_RESTART; 1610 (void)Lst_AtEnd(stoppedJobs, (ClientData)job); 1611 } else { 1612 if ((nLocal >= maxLocal) && local) { 1613 /* 1614 * If we're running this job locally as a special case (see above), 1615 * at least say the table is full. 1616 */ 1617 jobFull = TRUE; 1618 if (DEBUG(JOB)) { 1619 printf("Local job queue is full.\n"); 1620 } 1621 } 1622 JobExec(job, argv); 1623 } 1624 return(JOB_RUNNING); 1625 } 1626 1627 /*- 1628 *----------------------------------------------------------------------- 1629 * JobDoOutput -- 1630 * This function is called at different times depending on 1631 * whether the user has specified that output is to be collected 1632 * via pipes or temporary files. In the former case, we are called 1633 * whenever there is something to read on the pipe. We collect more 1634 * output from the given job and store it in the job's outBuf. If 1635 * this makes up a line, we print it tagged by the job's identifier, 1636 * as necessary. 1637 * If output has been collected in a temporary file, we open the 1638 * file and read it line by line, transfering it to our own 1639 * output channel until the file is empty. At which point we 1640 * remove the temporary file. 1641 * In both cases, however, we keep our figurative eye out for the 1642 * 'noPrint' line for the shell from which the output came. If 1643 * we recognize a line, we don't print it. If the command is not 1644 * alone on the line (the character after it is not \0 or \n), we 1645 * do print whatever follows it. 1646 * 1647 * Results: 1648 * None 1649 * 1650 * Side Effects: 1651 * curPos may be shifted as may the contents of outBuf. 1652 *----------------------------------------------------------------------- 1653 */ 1654 void 1655 JobDoOutput (job, finish) 1656 register Job *job; /* the job whose output needs printing */ 1657 Boolean finish; /* TRUE if this is the last time we'll be 1658 * called for this job */ 1659 { 1660 Boolean gotNL = FALSE; /* true if got a newline */ 1661 register int nr; /* number of bytes read */ 1662 register int i; /* auxiliary index into outBuf */ 1663 register int max; /* limit for i (end of current data) */ 1664 int nRead; /* (Temporary) number of bytes read */ 1665 1666 char c; /* character after noPrint string */ 1667 FILE *oFILE; /* Stream pointer to shell's output file */ 1668 char inLine[132]; 1669 1670 1671 if (usePipes) { 1672 /* 1673 * Read as many bytes as will fit in the buffer. 1674 */ 1675 end_loop: 1676 1677 nRead = read (job->inPipe, &job->outBuf[job->curPos], 1678 JOB_BUFSIZE - job->curPos); 1679 if (nRead < 0) { 1680 if (DEBUG(JOB)) { 1681 perror("JobDoOutput(piperead)"); 1682 } 1683 nr = 0; 1684 } else { 1685 nr = nRead; 1686 } 1687 1688 /* 1689 * If we hit the end-of-file (the job is dead), we must flush its 1690 * remaining output, so pretend we read a newline if there's any 1691 * output remaining in the buffer. 1692 * Also clear the 'finish' flag so we stop looping. 1693 */ 1694 if ((nr == 0) && (job->curPos != 0)) { 1695 job->outBuf[job->curPos] = '\n'; 1696 nr = 1; 1697 finish = FALSE; 1698 } else if (nr == 0) { 1699 finish = FALSE; 1700 } 1701 1702 /* 1703 * Look for the last newline in the bytes we just got. If there is 1704 * one, break out of the loop with 'i' as its index and gotNL set 1705 * TRUE. 1706 */ 1707 max = job->curPos + nr; 1708 for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 1709 if (job->outBuf[i] == '\n') { 1710 gotNL = TRUE; 1711 break; 1712 } else if (job->outBuf[i] == '\0') { 1713 /* 1714 * Why? 1715 */ 1716 job->outBuf[i] = ' '; 1717 } 1718 } 1719 1720 if (!gotNL) { 1721 job->curPos += nr; 1722 if (job->curPos == JOB_BUFSIZE) { 1723 /* 1724 * If we've run out of buffer space, we have no choice 1725 * but to print the stuff. sigh. 1726 */ 1727 gotNL = TRUE; 1728 i = job->curPos; 1729 } 1730 } 1731 if (gotNL) { 1732 /* 1733 * Need to send the output to the screen. Null terminate it 1734 * first, overwriting the newline character if there was one. 1735 * So long as the line isn't one we should filter (according 1736 * to the shell description), we print the line, preceeded 1737 * by a target banner if this target isn't the same as the 1738 * one for which we last printed something. 1739 * The rest of the data in the buffer are then shifted down 1740 * to the start of the buffer and curPos is set accordingly. 1741 */ 1742 job->outBuf[i] = '\0'; 1743 if (i >= job->curPos) { 1744 register char *cp, *ecp; 1745 1746 cp = job->outBuf; 1747 if (commandShell->noPrint) { 1748 ecp = Str_FindSubstring(job->outBuf, 1749 commandShell->noPrint); 1750 while (ecp != (char *)NULL) { 1751 if (cp != ecp) { 1752 *ecp = '\0'; 1753 if (job->node != lastNode) { 1754 printf (targFmt, job->node->name); 1755 lastNode = job->node; 1756 } 1757 /* 1758 * The only way there wouldn't be a newline after 1759 * this line is if it were the last in the buffer. 1760 * however, since the non-printable comes after it, 1761 * there must be a newline, so we don't print one. 1762 */ 1763 printf ("%s", cp); 1764 } 1765 cp = ecp + commandShell->noPLen; 1766 if (cp != &job->outBuf[i]) { 1767 /* 1768 * Still more to print, look again after skipping 1769 * the whitespace following the non-printable 1770 * command.... 1771 */ 1772 cp++; 1773 while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 1774 cp++; 1775 } 1776 ecp = Str_FindSubstring (cp, 1777 commandShell->noPrint); 1778 } else { 1779 break; 1780 } 1781 } 1782 } 1783 1784 /* 1785 * There's still more in that thar buffer. This time, though, 1786 * we know there's no newline at the end, so we add one of 1787 * our own free will. 1788 */ 1789 if (*cp != '\0') { 1790 if (job->node != lastNode) { 1791 printf (targFmt, job->node->name); 1792 lastNode = job->node; 1793 } 1794 printf ("%s\n", cp); 1795 } 1796 1797 fflush (stdout); 1798 } 1799 if (i < max - 1) { 1800 bcopy (&job->outBuf[i + 1], /* shift the remaining */ 1801 job->outBuf, /* characters down */ 1802 max - (i + 1)); 1803 job->curPos = max - (i + 1); 1804 1805 } else { 1806 /* 1807 * We have written everything out, so we just start over 1808 * from the start of the buffer. No copying. No nothing. 1809 */ 1810 job->curPos = 0; 1811 } 1812 } 1813 if (finish) { 1814 /* 1815 * If the finish flag is true, we must loop until we hit 1816 * end-of-file on the pipe. This is guaranteed to happen eventually 1817 * since the other end of the pipe is now closed (we closed it 1818 * explicitly and the child has exited). When we do get an EOF, 1819 * finish will be set FALSE and we'll fall through and out. 1820 */ 1821 goto end_loop; 1822 } 1823 } else { 1824 /* 1825 * We've been called to retrieve the output of the job from the 1826 * temporary file where it's been squirreled away. This consists of 1827 * opening the file, reading the output line by line, being sure not 1828 * to print the noPrint line for the shell we used, then close and 1829 * remove the temporary file. Very simple. 1830 * 1831 * Change to read in blocks and do FindSubString type things as for 1832 * pipes? That would allow for "@echo -n..." 1833 */ 1834 oFILE = fopen (job->outFile, "r"); 1835 if (oFILE != (FILE *) NULL) { 1836 printf ("Results of making %s:\n", job->node->name); 1837 while (fgets (inLine, sizeof(inLine), oFILE) != NULL) { 1838 register char *cp, *ecp, *endp; 1839 1840 cp = inLine; 1841 endp = inLine + strlen(inLine); 1842 if (endp[-1] == '\n') { 1843 *--endp = '\0'; 1844 } 1845 if (commandShell->noPrint) { 1846 ecp = Str_FindSubstring(cp, commandShell->noPrint); 1847 while (ecp != (char *)NULL) { 1848 if (cp != ecp) { 1849 *ecp = '\0'; 1850 /* 1851 * The only way there wouldn't be a newline after 1852 * this line is if it were the last in the buffer. 1853 * however, since the non-printable comes after it, 1854 * there must be a newline, so we don't print one. 1855 */ 1856 printf ("%s", cp); 1857 } 1858 cp = ecp + commandShell->noPLen; 1859 if (cp != endp) { 1860 /* 1861 * Still more to print, look again after skipping 1862 * the whitespace following the non-printable 1863 * command.... 1864 */ 1865 cp++; 1866 while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 1867 cp++; 1868 } 1869 ecp = Str_FindSubstring(cp, commandShell->noPrint); 1870 } else { 1871 break; 1872 } 1873 } 1874 } 1875 1876 /* 1877 * There's still more in that thar buffer. This time, though, 1878 * we know there's no newline at the end, so we add one of 1879 * our own free will. 1880 */ 1881 if (*cp != '\0') { 1882 printf ("%s\n", cp); 1883 } 1884 } 1885 fclose (oFILE); 1886 (void) unlink (job->outFile); 1887 } 1888 } 1889 fflush(stdout); 1890 } 1891 1892 /*- 1893 *----------------------------------------------------------------------- 1894 * Job_CatchChildren -- 1895 * Handle the exit of a child. Called from Make_Make. 1896 * 1897 * Results: 1898 * none. 1899 * 1900 * Side Effects: 1901 * The job descriptor is removed from the list of children. 1902 * 1903 * Notes: 1904 * We do waits, blocking or not, according to the wisdom of our 1905 * caller, until there are no more children to report. For each 1906 * job, call JobFinish to finish things off. This will take care of 1907 * putting jobs on the stoppedJobs queue. 1908 * 1909 *----------------------------------------------------------------------- 1910 */ 1911 void 1912 Job_CatchChildren (block) 1913 Boolean block; /* TRUE if should block on the wait. */ 1914 { 1915 int pid; /* pid of dead child */ 1916 register Job *job; /* job descriptor for dead child */ 1917 LstNode jnode; /* list element for finding job */ 1918 union wait status; /* Exit/termination status */ 1919 1920 /* 1921 * Don't even bother if we know there's no one around. 1922 */ 1923 if (nLocal == 0) { 1924 return; 1925 } 1926 1927 while ((pid = wait3((int *)&status, (block?0:WNOHANG)|WUNTRACED, 1928 (struct rusage *)0)) > 0) 1929 { 1930 if (DEBUG(JOB)) 1931 printf("Process %d exited or stopped.\n", pid); 1932 1933 1934 jnode = Lst_Find (jobs, (ClientData)pid, JobCmpPid); 1935 1936 if (jnode == NILLNODE) { 1937 if (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) { 1938 jnode = Lst_Find(stoppedJobs, (ClientData)pid, JobCmpPid); 1939 if (jnode == NILLNODE) { 1940 Error("Resumed child (%d) not in table", pid); 1941 continue; 1942 } 1943 job = (Job *)Lst_Datum(jnode); 1944 (void)Lst_Remove(stoppedJobs, jnode); 1945 } else { 1946 Error ("Child (%d) not in table?", pid); 1947 continue; 1948 } 1949 } else { 1950 job = (Job *) Lst_Datum (jnode); 1951 (void)Lst_Remove (jobs, jnode); 1952 nJobs -= 1; 1953 if (jobFull && DEBUG(JOB)) { 1954 printf("Job queue is no longer full.\n"); 1955 } 1956 jobFull = FALSE; 1957 nLocal -= 1; 1958 } 1959 1960 JobFinish (job, status); 1961 } 1962 } 1963 1964 /*- 1965 *----------------------------------------------------------------------- 1966 * Job_CatchOutput -- 1967 * Catch the output from our children, if we're using 1968 * pipes do so. Otherwise just block time until we get a 1969 * signal (most likely a SIGCHLD) since there's no point in 1970 * just spinning when there's nothing to do and the reaping 1971 * of a child can wait for a while. 1972 * 1973 * Results: 1974 * None 1975 * 1976 * Side Effects: 1977 * Output is read from pipes if we're piping. 1978 * ----------------------------------------------------------------------- 1979 */ 1980 void 1981 Job_CatchOutput () 1982 { 1983 int nfds; 1984 struct timeval timeout; 1985 fd_set readfds; 1986 register LstNode ln; 1987 register Job *job; 1988 int pnJobs; /* Previous nJobs */ 1989 1990 fflush(stdout); 1991 #ifdef RMT_WILL_WATCH 1992 pnJobs = nJobs; 1993 1994 /* 1995 * It is possible for us to be called with nJobs equal to 0. This happens 1996 * if all the jobs finish and a job that is stopped cannot be run 1997 * locally (eg if maxLocal is 0) and cannot be exported. The job will 1998 * be placed back on the stoppedJobs queue, Job_Empty() will return false, 1999 * Make_Run will call us again when there's nothing for which to wait. 2000 * nJobs never changes, so we loop forever. Hence the check. It could 2001 * be argued that we should sleep for a bit so as not to swamp the 2002 * exportation system with requests. Perhaps we should. 2003 * 2004 * NOTE: IT IS THE RESPONSIBILITY OF Rmt_Wait TO CALL Job_CatchChildren 2005 * IN A TIMELY FASHION TO CATCH ANY LOCALLY RUNNING JOBS THAT EXIT. 2006 * It may use the variable nLocal to determine if it needs to call 2007 * Job_CatchChildren (if nLocal is 0, there's nothing for which to 2008 * wait...) 2009 */ 2010 while (nJobs != 0 && pnJobs == nJobs) { 2011 Rmt_Wait(); 2012 } 2013 #else 2014 if (usePipes) { 2015 readfds = outputs; 2016 timeout.tv_sec = SEL_SEC; 2017 timeout.tv_usec = SEL_USEC; 2018 2019 if ((nfds = select (FD_SETSIZE, &readfds, (int *) 0, (int *) 0, &timeout)) < 0) 2020 { 2021 return; 2022 } else { 2023 if (Lst_Open (jobs) == FAILURE) { 2024 Punt ("Cannot open job table"); 2025 } 2026 while (nfds && (ln = Lst_Next (jobs)) != NILLNODE) { 2027 job = (Job *) Lst_Datum (ln); 2028 if (FD_ISSET(job->inPipe, &readfds)) { 2029 JobDoOutput (job, FALSE); 2030 nfds -= 1; 2031 } 2032 } 2033 Lst_Close (jobs); 2034 } 2035 } 2036 #endif /* RMT_WILL_WATCH */ 2037 } 2038 2039 /*- 2040 *----------------------------------------------------------------------- 2041 * Job_Make -- 2042 * Start the creation of a target. Basically a front-end for 2043 * JobStart used by the Make module. 2044 * 2045 * Results: 2046 * None. 2047 * 2048 * Side Effects: 2049 * Another job is started. 2050 * 2051 *----------------------------------------------------------------------- 2052 */ 2053 void 2054 Job_Make (gn) 2055 GNode *gn; 2056 { 2057 (void)JobStart (gn, 0, (Job *)NULL); 2058 } 2059 2060 /*- 2061 *----------------------------------------------------------------------- 2062 * Job_Init -- 2063 * Initialize the process module 2064 * 2065 * Results: 2066 * none 2067 * 2068 * Side Effects: 2069 * lists and counters are initialized 2070 *----------------------------------------------------------------------- 2071 */ 2072 void 2073 Job_Init (maxproc, maxlocal) 2074 int maxproc; /* the greatest number of jobs which may be 2075 * running at one time */ 2076 int maxlocal; /* the greatest number of local jobs which may 2077 * be running at once. */ 2078 { 2079 GNode *begin; /* node for commands to do at the very start */ 2080 2081 sprintf (tfile, "/tmp/make%05d", getpid()); 2082 2083 jobs = Lst_Init (FALSE); 2084 stoppedJobs = Lst_Init(FALSE); 2085 maxJobs = maxproc; 2086 maxLocal = maxlocal; 2087 nJobs = 0; 2088 nLocal = 0; 2089 jobFull = FALSE; 2090 2091 aborting = 0; 2092 errors = 0; 2093 2094 lastNode = NILGNODE; 2095 2096 if (maxJobs == 1) { 2097 /* 2098 * If only one job can run at a time, there's no need for a banner, 2099 * no is there? 2100 */ 2101 targFmt = ""; 2102 } else { 2103 targFmt = TARG_FMT; 2104 } 2105 2106 if (shellPath == (char *) NULL) { 2107 /* 2108 * The user didn't specify a shell to use, so we are using the 2109 * default one... Both the absolute path and the last component 2110 * must be set. The last component is taken from the 'name' field 2111 * of the default shell description pointed-to by commandShell. 2112 * All default shells are located in _PATH_DEFSHELLDIR. 2113 */ 2114 shellName = commandShell->name; 2115 shellPath = str_concat (_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH); 2116 } 2117 2118 if (commandShell->exit == (char *)NULL) { 2119 commandShell->exit = ""; 2120 } 2121 if (commandShell->echo == (char *)NULL) { 2122 commandShell->echo = ""; 2123 } 2124 2125 /* 2126 * Catch the four signals that POSIX specifies if they aren't ignored. 2127 * JobPassSig will take care of calling JobInterrupt if appropriate. 2128 */ 2129 if (signal (SIGINT, SIG_IGN) != SIG_IGN) { 2130 signal (SIGINT, JobPassSig); 2131 } 2132 if (signal (SIGHUP, SIG_IGN) != SIG_IGN) { 2133 signal (SIGHUP, JobPassSig); 2134 } 2135 if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) { 2136 signal (SIGQUIT, JobPassSig); 2137 } 2138 if (signal (SIGTERM, SIG_IGN) != SIG_IGN) { 2139 signal (SIGTERM, JobPassSig); 2140 } 2141 /* 2142 * There are additional signals that need to be caught and passed if 2143 * either the export system wants to be told directly of signals or if 2144 * we're giving each job its own process group (since then it won't get 2145 * signals from the terminal driver as we own the terminal) 2146 */ 2147 #if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP) 2148 if (signal (SIGTSTP, SIG_IGN) != SIG_IGN) { 2149 signal (SIGTSTP, JobPassSig); 2150 } 2151 if (signal (SIGTTOU, SIG_IGN) != SIG_IGN) { 2152 signal (SIGTTOU, JobPassSig); 2153 } 2154 if (signal (SIGTTIN, SIG_IGN) != SIG_IGN) { 2155 signal (SIGTTIN, JobPassSig); 2156 } 2157 if (signal (SIGWINCH, SIG_IGN) != SIG_IGN) { 2158 signal (SIGWINCH, JobPassSig); 2159 } 2160 #endif 2161 2162 begin = Targ_FindNode (".BEGIN", TARG_NOCREATE); 2163 2164 if (begin != NILGNODE) { 2165 JobStart (begin, JOB_SPECIAL, (Job *)0); 2166 while (nJobs) { 2167 Job_CatchOutput(); 2168 #ifndef RMT_WILL_WATCH 2169 Job_CatchChildren (!usePipes); 2170 #endif /* RMT_WILL_WATCH */ 2171 } 2172 } 2173 postCommands = Targ_FindNode (".END", TARG_CREATE); 2174 } 2175 2176 /*- 2177 *----------------------------------------------------------------------- 2178 * Job_Full -- 2179 * See if the job table is full. It is considered full if it is OR 2180 * if we are in the process of aborting OR if we have 2181 * reached/exceeded our local quota. This prevents any more jobs 2182 * from starting up. 2183 * 2184 * Results: 2185 * TRUE if the job table is full, FALSE otherwise 2186 * Side Effects: 2187 * None. 2188 *----------------------------------------------------------------------- 2189 */ 2190 Boolean 2191 Job_Full () 2192 { 2193 return (aborting || jobFull); 2194 } 2195 2196 /*- 2197 *----------------------------------------------------------------------- 2198 * Job_Empty -- 2199 * See if the job table is empty. Because the local concurrency may 2200 * be set to 0, it is possible for the job table to become empty, 2201 * while the list of stoppedJobs remains non-empty. In such a case, 2202 * we want to restart as many jobs as we can. 2203 * 2204 * Results: 2205 * TRUE if it is. FALSE if it ain't. 2206 * 2207 * Side Effects: 2208 * None. 2209 * 2210 * ----------------------------------------------------------------------- 2211 */ 2212 Boolean 2213 Job_Empty () 2214 { 2215 if (nJobs == 0) { 2216 if (!Lst_IsEmpty(stoppedJobs) && !aborting) { 2217 /* 2218 * The job table is obviously not full if it has no jobs in 2219 * it...Try and restart the stopped jobs. 2220 */ 2221 jobFull = FALSE; 2222 while (!jobFull && !Lst_IsEmpty(stoppedJobs)) { 2223 JobRestart((Job *)Lst_DeQueue(stoppedJobs)); 2224 } 2225 return(FALSE); 2226 } else { 2227 return(TRUE); 2228 } 2229 } else { 2230 return(FALSE); 2231 } 2232 } 2233 2234 /*- 2235 *----------------------------------------------------------------------- 2236 * JobMatchShell -- 2237 * Find a matching shell in 'shells' given its final component. 2238 * 2239 * Results: 2240 * A pointer to the Shell structure. 2241 * 2242 * Side Effects: 2243 * None. 2244 * 2245 *----------------------------------------------------------------------- 2246 */ 2247 static Shell * 2248 JobMatchShell (name) 2249 char *name; /* Final component of shell path */ 2250 { 2251 register Shell *sh; /* Pointer into shells table */ 2252 Shell *match; /* Longest-matching shell */ 2253 register char *cp1, 2254 *cp2; 2255 char *eoname; 2256 2257 eoname = name + strlen (name); 2258 2259 match = (Shell *) NULL; 2260 2261 for (sh = shells; sh->name != NULL; sh++) { 2262 for (cp1 = eoname - strlen (sh->name), cp2 = sh->name; 2263 *cp1 != '\0' && *cp1 == *cp2; 2264 cp1++, cp2++) { 2265 continue; 2266 } 2267 if (*cp1 != *cp2) { 2268 continue; 2269 } else if (match == (Shell *) NULL || 2270 strlen (match->name) < strlen (sh->name)) { 2271 match = sh; 2272 } 2273 } 2274 return (match == (Shell *) NULL ? sh : match); 2275 } 2276 2277 /*- 2278 *----------------------------------------------------------------------- 2279 * Job_ParseShell -- 2280 * Parse a shell specification and set up commandShell, shellPath 2281 * and shellName appropriately. 2282 * 2283 * Results: 2284 * FAILURE if the specification was incorrect. 2285 * 2286 * Side Effects: 2287 * commandShell points to a Shell structure (either predefined or 2288 * created from the shell spec), shellPath is the full path of the 2289 * shell described by commandShell, while shellName is just the 2290 * final component of shellPath. 2291 * 2292 * Notes: 2293 * A shell specification consists of a .SHELL target, with dependency 2294 * operator, followed by a series of blank-separated words. Double 2295 * quotes can be used to use blanks in words. A backslash escapes 2296 * anything (most notably a double-quote and a space) and 2297 * provides the functionality it does in C. Each word consists of 2298 * keyword and value separated by an equal sign. There should be no 2299 * unnecessary spaces in the word. The keywords are as follows: 2300 * name Name of shell. 2301 * path Location of shell. Overrides "name" if given 2302 * quiet Command to turn off echoing. 2303 * echo Command to turn echoing on 2304 * filter Result of turning off echoing that shouldn't be 2305 * printed. 2306 * echoFlag Flag to turn echoing on at the start 2307 * errFlag Flag to turn error checking on at the start 2308 * hasErrCtl True if shell has error checking control 2309 * check Command to turn on error checking if hasErrCtl 2310 * is TRUE or template of command to echo a command 2311 * for which error checking is off if hasErrCtl is 2312 * FALSE. 2313 * ignore Command to turn off error checking if hasErrCtl 2314 * is TRUE or template of command to execute a 2315 * command so as to ignore any errors it returns if 2316 * hasErrCtl is FALSE. 2317 * 2318 *----------------------------------------------------------------------- 2319 */ 2320 ReturnStatus 2321 Job_ParseShell (line) 2322 char *line; /* The shell spec */ 2323 { 2324 char **words; 2325 int wordCount; 2326 register char **argv; 2327 register int argc; 2328 char *path; 2329 Shell newShell; 2330 Boolean fullSpec = FALSE; 2331 2332 while (isspace (*line)) { 2333 line++; 2334 } 2335 words = brk_string (line, &wordCount); 2336 2337 bzero ((Address)&newShell, sizeof(newShell)); 2338 2339 /* 2340 * Parse the specification by keyword 2341 */ 2342 for (path = (char *)NULL, argc = wordCount - 1, argv = words + 1; 2343 argc != 0; 2344 argc--, argv++) { 2345 if (strncmp (*argv, "path=", 5) == 0) { 2346 path = &argv[0][5]; 2347 } else if (strncmp (*argv, "name=", 5) == 0) { 2348 newShell.name = &argv[0][5]; 2349 } else { 2350 if (strncmp (*argv, "quiet=", 6) == 0) { 2351 newShell.echoOff = &argv[0][6]; 2352 } else if (strncmp (*argv, "echo=", 5) == 0) { 2353 newShell.echoOn = &argv[0][5]; 2354 } else if (strncmp (*argv, "filter=", 7) == 0) { 2355 newShell.noPrint = &argv[0][7]; 2356 newShell.noPLen = strlen(newShell.noPrint); 2357 } else if (strncmp (*argv, "echoFlag=", 9) == 0) { 2358 newShell.echo = &argv[0][9]; 2359 } else if (strncmp (*argv, "errFlag=", 8) == 0) { 2360 newShell.exit = &argv[0][8]; 2361 } else if (strncmp (*argv, "hasErrCtl=", 10) == 0) { 2362 char c = argv[0][10]; 2363 newShell.hasErrCtl = !((c != 'Y') && (c != 'y') && 2364 (c != 'T') && (c != 't')); 2365 } else if (strncmp (*argv, "check=", 6) == 0) { 2366 newShell.errCheck = &argv[0][6]; 2367 } else if (strncmp (*argv, "ignore=", 7) == 0) { 2368 newShell.ignErr = &argv[0][7]; 2369 } else { 2370 Parse_Error (PARSE_FATAL, "Unknown keyword \"%s\"", 2371 *argv); 2372 return (FAILURE); 2373 } 2374 fullSpec = TRUE; 2375 } 2376 } 2377 2378 if (path == (char *)NULL) { 2379 /* 2380 * If no path was given, the user wants one of the pre-defined shells, 2381 * yes? So we find the one s/he wants with the help of JobMatchShell 2382 * and set things up the right way. shellPath will be set up by 2383 * Job_Init. 2384 */ 2385 if (newShell.name == (char *)NULL) { 2386 Parse_Error (PARSE_FATAL, "Neither path nor name specified"); 2387 return (FAILURE); 2388 } else { 2389 commandShell = JobMatchShell (newShell.name); 2390 shellName = newShell.name; 2391 } 2392 } else { 2393 /* 2394 * The user provided a path. If s/he gave nothing else (fullSpec is 2395 * FALSE), try and find a matching shell in the ones we know of. 2396 * Else we just take the specification at its word and copy it 2397 * to a new location. In either case, we need to record the 2398 * path the user gave for the shell. 2399 */ 2400 shellPath = path; 2401 path = rindex (path, '/'); 2402 if (path == (char *)NULL) { 2403 path = shellPath; 2404 } else { 2405 path += 1; 2406 } 2407 if (newShell.name != (char *)NULL) { 2408 shellName = newShell.name; 2409 } else { 2410 shellName = path; 2411 } 2412 if (!fullSpec) { 2413 commandShell = JobMatchShell (shellName); 2414 } else { 2415 commandShell = (Shell *) emalloc(sizeof(Shell)); 2416 *commandShell = newShell; 2417 } 2418 } 2419 2420 if (commandShell->echoOn && commandShell->echoOff) { 2421 commandShell->hasEchoCtl = TRUE; 2422 } 2423 2424 if (!commandShell->hasErrCtl) { 2425 if (commandShell->errCheck == (char *)NULL) { 2426 commandShell->errCheck = ""; 2427 } 2428 if (commandShell->ignErr == (char *)NULL) { 2429 commandShell->ignErr = "%s\n"; 2430 } 2431 } 2432 2433 /* 2434 * Do not free up the words themselves, since they might be in use by the 2435 * shell specification... 2436 */ 2437 free (words); 2438 return SUCCESS; 2439 } 2440 2441 /*- 2442 *----------------------------------------------------------------------- 2443 * JobInterrupt -- 2444 * Handle the receipt of an interrupt. 2445 * 2446 * Results: 2447 * None 2448 * 2449 * Side Effects: 2450 * All children are killed. Another job will be started if the 2451 * .INTERRUPT target was given. 2452 *----------------------------------------------------------------------- 2453 */ 2454 static void 2455 JobInterrupt (runINTERRUPT) 2456 int runINTERRUPT; /* Non-zero if commands for the .INTERRUPT 2457 * target should be executed */ 2458 { 2459 LstNode ln; /* element in job table */ 2460 Job *job; /* job descriptor in that element */ 2461 GNode *interrupt; /* the node describing the .INTERRUPT target */ 2462 2463 aborting = ABORT_INTERRUPT; 2464 2465 (void)Lst_Open (jobs); 2466 while ((ln = Lst_Next (jobs)) != NILLNODE) { 2467 job = (Job *) Lst_Datum (ln); 2468 2469 if (!Targ_Precious (job->node)) { 2470 char *file = (job->node->path == (char *)NULL ? 2471 job->node->name : 2472 job->node->path); 2473 /* Don't unlink directories */ /* 10 Aug 92*/ 2474 struct stat sbuf; 2475 stat (file, &sbuf); 2476 if (!(sbuf.st_mode & S_IFDIR)) { 2477 if (unlink (file) == 0) { 2478 Error ("*** %s removed", file); 2479 } 2480 } 2481 } 2482 #ifdef RMT_WANTS_SIGNALS 2483 if (job->flags & JOB_REMOTE) { 2484 /* 2485 * If job is remote, let the Rmt module do the killing. 2486 */ 2487 if (!Rmt_Signal(job, SIGINT)) { 2488 /* 2489 * If couldn't kill the thing, finish it out now with an 2490 * error code, since no exit report will come in likely. 2491 */ 2492 union wait status; 2493 2494 status.w_status = 0; 2495 status.w_retcode = 1; 2496 JobFinish(job, status); 2497 } 2498 } else if (job->pid) { 2499 KILL(job->pid, SIGINT); 2500 } 2501 #else 2502 if (job->pid) { 2503 KILL(job->pid, SIGINT); 2504 } 2505 #endif /* RMT_WANTS_SIGNALS */ 2506 } 2507 Lst_Close (jobs); 2508 2509 if (runINTERRUPT && !touchFlag) { 2510 interrupt = Targ_FindNode (".INTERRUPT", TARG_NOCREATE); 2511 if (interrupt != NILGNODE) { 2512 ignoreErrors = FALSE; 2513 2514 JobStart (interrupt, JOB_IGNDOTS, (Job *)0); 2515 while (nJobs) { 2516 Job_CatchOutput(); 2517 #ifndef RMT_WILL_WATCH 2518 Job_CatchChildren (!usePipes); 2519 #endif /* RMT_WILL_WATCH */ 2520 } 2521 } 2522 } 2523 (void) unlink (tfile); 2524 exit (0); 2525 } 2526 2527 /* 2528 *----------------------------------------------------------------------- 2529 * Job_End -- 2530 * Do final processing such as the running of the commands 2531 * attached to the .END target. 2532 * 2533 * Results: 2534 * Number of errors reported. 2535 * 2536 * Side Effects: 2537 * The process' temporary file (tfile) is removed if it still 2538 * existed. 2539 *----------------------------------------------------------------------- 2540 */ 2541 int 2542 Job_End () 2543 { 2544 if (postCommands != NILGNODE && !Lst_IsEmpty (postCommands->commands)) { 2545 if (errors) { 2546 Error ("Errors reported so .END ignored"); 2547 } else { 2548 JobStart (postCommands, JOB_SPECIAL | JOB_IGNDOTS, 2549 (Job *)0); 2550 2551 while (nJobs) { 2552 Job_CatchOutput(); 2553 #ifndef RMT_WILL_WATCH 2554 Job_CatchChildren (!usePipes); 2555 #endif /* RMT_WILL_WATCH */ 2556 } 2557 } 2558 } 2559 (void) unlink (tfile); 2560 return(errors); 2561 } 2562 2563 /*- 2564 *----------------------------------------------------------------------- 2565 * Job_Wait -- 2566 * Waits for all running jobs to finish and returns. Sets 'aborting' 2567 * to ABORT_WAIT to prevent other jobs from starting. 2568 * 2569 * Results: 2570 * None. 2571 * 2572 * Side Effects: 2573 * Currently running jobs finish. 2574 * 2575 *----------------------------------------------------------------------- 2576 */ 2577 void 2578 Job_Wait() 2579 { 2580 aborting = ABORT_WAIT; 2581 while (nJobs != 0) { 2582 Job_CatchOutput(); 2583 #ifndef RMT_WILL_WATCH 2584 Job_CatchChildren(!usePipes); 2585 #endif /* RMT_WILL_WATCH */ 2586 } 2587 aborting = 0; 2588 } 2589 2590 /*- 2591 *----------------------------------------------------------------------- 2592 * Job_AbortAll -- 2593 * Abort all currently running jobs without handling output or anything. 2594 * This function is to be called only in the event of a major 2595 * error. Most definitely NOT to be called from JobInterrupt. 2596 * 2597 * Results: 2598 * None 2599 * 2600 * Side Effects: 2601 * All children are killed, not just the firstborn 2602 *----------------------------------------------------------------------- 2603 */ 2604 void 2605 Job_AbortAll () 2606 { 2607 LstNode ln; /* element in job table */ 2608 Job *job; /* the job descriptor in that element */ 2609 int foo; 2610 2611 aborting = ABORT_ERROR; 2612 2613 if (nJobs) { 2614 2615 (void)Lst_Open (jobs); 2616 while ((ln = Lst_Next (jobs)) != NILLNODE) { 2617 job = (Job *) Lst_Datum (ln); 2618 2619 /* 2620 * kill the child process with increasingly drastic signals to make 2621 * darn sure it's dead. 2622 */ 2623 #ifdef RMT_WANTS_SIGNALS 2624 if (job->flags & JOB_REMOTE) { 2625 Rmt_Signal(job, SIGINT); 2626 Rmt_Signal(job, SIGKILL); 2627 } else { 2628 KILL(job->pid, SIGINT); 2629 KILL(job->pid, SIGKILL); 2630 } 2631 #else 2632 KILL(job->pid, SIGINT); 2633 KILL(job->pid, SIGKILL); 2634 #endif /* RMT_WANTS_SIGNALS */ 2635 } 2636 } 2637 2638 /* 2639 * Catch as many children as want to report in at first, then give up 2640 */ 2641 while (wait3(&foo, WNOHANG, (struct rusage *)0) > 0) { 2642 ; 2643 } 2644 (void) unlink (tfile); 2645 } 2646