Changeset 51 for trunk/src/kmk/job.c
- Timestamp:
- Apr 7, 2003, 3:30:32 AM (22 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kmk/job.c
r46 r51 18 18 * 3. All advertising materials mentioning features or use of this software 19 19 * must display the following acknowledgement: 20 * 21 * 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 22 * 4. Neither the name of the University nor the names of its contributors 23 23 * may be used to endorse or promote products derived from this software … … 39 39 #ifndef lint 40 40 #if 0 41 static char sccsid[] = "@(#)job.c 41 static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; 42 42 #else 43 43 static const char rcsid[] = 44 44 "$FreeBSD: src/usr.bin/make/job.c,v 1.17.2.2 2001/02/13 03:13:57 will Exp $"; 45 45 #endif 46 #define KLIBFILEDEF rcsid 46 47 #endif /* not lint */ 47 48 … … 56 57 /*- 57 58 * job.c -- 58 * 59 * handle the creation etc. of our child processes. 59 60 * 60 61 * Interface: 61 * Job_MakeStart the creation of the given target.62 * 63 * Job_CatchChildrenCheck for and handle the termination of any64 * 65 * 66 * 67 * 68 * 69 * 70 * 71 * Job_CatchOutputPrint any output our children have produced.72 * 73 * 74 * 75 * 76 * 77 * 78 * Job_InitCalled to intialize this module. in addition,79 * 80 * 81 * 82 * 83 * 84 * Job_FullReturn TRUE if the job table is filled.85 * 86 * Job_EmptyReturn TRUE if the job table is completely87 * 88 * 89 * Job_ParseShellGiven the line following a .SHELL target, parse90 * 91 * 92 * 93 * Job_EndPerform any final processing which needs doing.94 * 95 * 96 * 97 * 98 * 99 * Job_AbortAllAbort all currently running jobs. It doesn't100 * 101 * 102 * 103 * 104 * Job_CheckCommandsVerify that the commands for a target are105 * 106 * 107 * Job_TouchUpdate a target without really updating it.108 * 109 * Job_WaitWait for all currently-running jobs to finish.62 * Job_Make Start the creation of the given target. 63 * 64 * Job_CatchChildren Check for and handle the termination of any 65 * children. This must be called reasonably 66 * frequently to keep the whole make going at 67 * a decent clip, since job table entries aren't 68 * removed until their process is caught this way. 69 * Its single argument is TRUE if the function 70 * should block waiting for a child to terminate. 71 * 72 * Job_CatchOutput Print any output our children have produced. 73 * Should also be called fairly frequently to 74 * keep the user informed of what's going on. 75 * If no output is waiting, it will block for 76 * a time given by the SEL_* constants, below, 77 * or until output is ready. 78 * 79 * Job_Init Called to intialize this module. in addition, 80 * any commands attached to the .BEGIN target 81 * are executed before this function returns. 82 * Hence, the makefile must have been parsed 83 * before this function is called. 84 * 85 * Job_Full Return TRUE if the job table is filled. 86 * 87 * Job_Empty Return TRUE if the job table is completely 88 * empty. 89 * 90 * Job_ParseShell Given the line following a .SHELL target, parse 91 * the line as a shell specification. Returns 92 * FAILURE if the spec was incorrect. 93 * 94 * Job_End Perform any final processing which needs doing. 95 * This includes the execution of any commands 96 * which have been/were attached to the .END 97 * target. It should only be called when the 98 * job table is empty. 99 * 100 * Job_AbortAll Abort all currently running jobs. It doesn't 101 * handle output or do anything for the jobs, 102 * just kills them. It should only be called in 103 * an emergency, as it were. 104 * 105 * Job_CheckCommands Verify that the commands for a target are 106 * ok. Provide them if necessary and possible. 107 * 108 * Job_Touch Update a target without really updating it. 109 * 110 * Job_Wait Wait for all currently-running jobs to finish. 110 111 */ 111 112 … … 153 154 * error handling variables 154 155 */ 155 static int errors = 0;/* number of errors reported */156 static int aborting = 0;/* why is the make aborting? */157 #define ABORT_ERROR 1/* Because of an error */158 #define ABORT_INTERRUPT 2/* Because it was interrupted */159 #define ABORT_WAIT 3/* Waiting for jobs to finish */156 static int errors = 0; /* number of errors reported */ 157 static int aborting = 0; /* why is the make aborting? */ 158 #define ABORT_ERROR 1 /* Because of an error */ 159 #define ABORT_INTERRUPT 2 /* Because it was interrupted */ 160 #define ABORT_WAIT 3 /* Waiting for jobs to finish */ 160 161 161 162 /* … … 170 171 * all the time. 171 172 */ 172 static GNode 173 174 static int numCommands;/* The number of commands actually printed175 176 173 static GNode *postCommands; /* node containing commands to execute when 174 * everything else is done */ 175 static int numCommands; /* The number of commands actually printed 176 * for a target. Should this number be 177 * 0, no shell will be executed. */ 177 178 178 179 /* 179 180 * Return values from JobStart. 180 181 */ 181 #define JOB_RUNNING 0/* Job is running */182 #define JOB_ERROR 1/* Error in starting the job */183 #define JOB_FINISHED 2/* The job is already finished */184 #define JOB_STOPPED 3/* The job is stopped */182 #define JOB_RUNNING 0 /* Job is running */ 183 #define JOB_ERROR 1 /* Error in starting the job */ 184 #define JOB_FINISHED 2 /* The job is already finished */ 185 #define JOB_STOPPED 3 /* The job is stopped */ 185 186 186 187 /* … … 229 230 } 230 231 }; 231 static Shell 232 233 234 235 236 static char *shellPath = NULL,/* full pathname of237 238 *shellName;/* last component of shell */232 static Shell *commandShell = &shells[DEFSHELL];/* this is the shell to 233 * which we pass all 234 * commands in the Makefile. 235 * It is set by the 236 * Job_ParseShell function */ 237 static char *shellPath = NULL, /* full pathname of 238 * executable image */ 239 *shellName; /* last component of shell */ 239 240 #endif /*!KMK*/ 240 241 241 242 242 static int maxJobs;/* The most children we can run at once */243 static int maxLocal;/* The most local ones we can have */244 STATIC int nJobs;/* The number of children currently running */245 STATIC int nLocal;/* The number of local children */246 STATIC Lst jobs;/* The structures that describe them */247 STATIC Boolean jobFull;/* Flag to tell when the job table is full. It248 249 250 251 243 static int maxJobs; /* The most children we can run at once */ 244 static int maxLocal; /* The most local ones we can have */ 245 STATIC int nJobs; /* The number of children currently running */ 246 STATIC int nLocal; /* The number of local children */ 247 STATIC Lst jobs; /* The structures that describe them */ 248 STATIC Boolean jobFull; /* Flag to tell when the job table is full. It 249 * is set TRUE when (1) the total number of 250 * running jobs equals the maximum allowed or 251 * (2) a job can only be run locally, but 252 * nLocal equals maxLocal */ 252 253 #ifndef RMT_WILL_WATCH 253 static fd_set outputs;/* Set of descriptors of pipes connected to254 255 #endif 256 257 STATIC GNode *lastNode;/* The node for which output was most recently258 259 STATIC char *targFmt;/* Format string to use to head output from a260 261 254 static fd_set outputs; /* Set of descriptors of pipes connected to 255 * the output channels of children */ 256 #endif 257 258 STATIC GNode *lastNode; /* The node for which output was most recently 259 * produced. */ 260 STATIC char *targFmt; /* Format string to use to head output from a 261 * job when it's not the most-recent job heard 262 * from */ 262 263 263 264 #ifdef REMOTE 264 265 # define TARG_FMT "--- %s at %s ---\n" /* Default format */ 265 266 # define MESSAGE(fp, gn) \ 266 267 (void) fprintf(fp, targFmt, gn->name, gn->rem.hname); 267 268 #else 268 269 # define TARG_FMT "--- %s ---\n" /* Default format */ 269 270 # define MESSAGE(fp, gn) \ 270 (void) fprintf(fp, targFmt, gn->name); 271 #endif 272 271 (void) fprintf(fp, targFmt, gn->name); 272 #endif 273 274 #ifdef SIGCONT 273 275 /* 274 276 * When JobStart attempts to run a job remotely but can't, and isn't allowed … … 277 279 * when the next job finishes. 278 280 */ 279 STATIC Lst stoppedJobs;/* Lst of Job structures describing280 281 282 281 STATIC Lst stoppedJobs; /* Lst of Job structures describing 282 * jobs that were stopped due to concurrency 283 * limits or migration home */ 284 #endif /*SIGCONT*/ 283 285 284 286 #if defined(USE_PGRP) && defined(SYSV) 285 # define KILL(pid, sig) 287 # define KILL(pid, sig) killpg(-(pid), (sig)) 286 288 #else 287 289 # if defined(USE_PGRP) 288 # define KILL(pid, sig) 290 # define KILL(pid, sig) killpg((pid), (sig)) 289 291 # else 290 # define KILL(pid, sig) 292 # define KILL(pid, sig) kill((pid), (sig)) 291 293 # endif 292 294 #endif … … 298 300 * really ugly, use dramamine sparingly. You have been warned. 299 301 */ 300 #define W_SETMASKED(st, val, fun) 301 {\302 int sh = (int) ~0;\303 int mask = fun(sh);\304 305 for (sh = 0; ((mask >> sh) & 1) == 0; sh++)\306 continue;\307 *(st) = (*(st) & ~mask) | ((val) << sh);\308 302 #define W_SETMASKED(st, val, fun) \ 303 { \ 304 int sh = (int) ~0; \ 305 int mask = fun(sh); \ 306 \ 307 for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \ 308 continue; \ 309 *(st) = (*(st) & ~mask) | ((val) << sh); \ 310 } 309 311 310 312 #define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG) … … 324 326 # endif 325 327 #else 328 #ifdef USE_KLIB 329 static void JobFinish __P((Job *, KPROCRES *)); 330 #else 326 331 static void JobFinish __P((Job *, int *)); 332 #endif 327 333 static void JobExec __P((Job *, char **)); 328 334 #endif 329 #ifndef KMK330 335 static void JobMakeArgv __P((Job *, char **)); 331 # endif336 #ifdef SIGCONT 332 337 static void JobRestart __P((Job *)); 338 #endif 333 339 static int JobStart __P((GNode *, int, Job *)); 334 340 static char *JobOutput __P((Job *, char *, char *, int)); … … 336 342 static Shell *JobMatchShell __P((char *)); 337 343 static void JobInterrupt __P((int, int)); 344 #ifdef SIGCONT 338 345 static void JobRestartJobs __P((void)); 346 #endif 339 347 340 348 /*- 341 349 *----------------------------------------------------------------------- 342 350 * JobCondPassSig -- 343 * 344 * 351 * Pass a signal to a job if the job is remote or if USE_PGRP 352 * is defined. 345 353 * 346 354 * Results: 347 * 355 * === 0 348 356 * 349 357 * Side Effects: 350 * 358 * None, except the job may bite it. 351 359 * 352 360 *----------------------------------------------------------------------- … … 354 362 static int 355 363 JobCondPassSig(jobp, signop) 356 ClientData jobp;/* Job to biff */357 ClientData signop;/* Signal to send it */364 ClientData jobp; /* Job to biff */ 365 ClientData signop; /* Signal to send it */ 358 366 { 359 Job 360 int 367 Job *job = (Job *) jobp; 368 int signo = *(int *) signop; 361 369 #ifdef RMT_WANTS_SIGNALS 362 370 if (job->flags & JOB_REMOTE) { 363 371 (void) Rmt_Signal(job, signo); 364 372 } else { 365 373 KILL(job->pid, signo); 366 374 } 367 375 #else … … 371 379 */ 372 380 if (DEBUG(JOB)) { 373 (void) fprintf(stdout, 374 "JobCondPassSig passing signal %d to child %d.\n", 375 signo, job->pid); 376 (void) fflush(stdout); 377 } 381 (void) fprintf(stdout, 382 "JobCondPassSig passing signal %d to child %d.\n", 383 signo, job->pid); 384 (void) fflush(stdout); 385 } 386 #if defined(USE_KLIB) && (defined(OS2) || defined(WIN32)) 387 switch (signo) 388 { 389 case SIGINT: 390 kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_INT); 391 break; 392 #ifdef SIGKILL 393 case SIGKILL: 394 #endif 395 case SIGTERM: 396 kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_KILL); 397 break; 398 /* default: ignore signal as we don't really support it */ 399 } 400 #else 378 401 KILL(job->pid, signo); 402 #endif 379 403 #endif 380 404 return 0; … … 384 408 *----------------------------------------------------------------------- 385 409 * JobPassSig -- 386 * 387 * 410 * Pass a signal on to all remote jobs and to all local jobs if 411 * USE_PGRP is defined, then die ourselves. 388 412 * 389 413 * Results: 390 * 414 * None. 391 415 * 392 416 * Side Effects: 393 * 417 * We die by the same signal. 394 418 * 395 419 *----------------------------------------------------------------------- … … 397 421 static void 398 422 JobPassSig(signo) 399 int signo;/* The signal number we've received */423 int signo; /* The signal number we've received */ 400 424 { 401 sigset_t nmask, omask; 402 struct sigaction act; 425 #if defined(USE_KLIB) && (defined(OS2) || defined(WIN32)) 403 426 404 427 if (DEBUG(JOB)) { 405 (void)fprintf(stdout, "JobPassSig(%d) called.\n", signo);406 (void)fflush(stdout);428 fprintf(stdout, "JobPassSig(%d) called.\n", signo); 429 fflush(stdout); 407 430 } 408 431 Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo); … … 414 437 */ 415 438 if (signo == SIGINT) { 416 JobInterrupt(TRUE, signo); 417 } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) { 418 JobInterrupt(FALSE, signo); 419 } 420 439 JobInterrupt(TRUE, signo); 440 } else if (signo == SIGTERM) { 441 JobInterrupt(FALSE, signo); 442 } 443 444 445 if (DEBUG(JOB)) { 446 fprintf(stdout, 447 "JobPassSig passing signal to self, mask = %x.\n", 448 ~0 & ~(1 << (signo-1))); 449 fflush(stdout); 450 } 451 signal(signo, SIG_DFL); 452 raise(signo); 453 454 #ifdef SIGCONT 455 signo = SIGCONT; 456 Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo); 457 #endif 458 459 460 #else /* Not KLIB + OS2/Win32 */ 461 sigset_t nmask, omask; 462 struct sigaction act; 463 464 465 if (DEBUG(JOB)) { 466 (void) fprintf(stdout, "JobPassSig(%d) called.\n", signo); 467 (void) fflush(stdout); 468 } 469 Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo); 470 471 /* 472 * Deal with proper cleanup based on the signal received. We only run 473 * the .INTERRUPT target if the signal was in fact an interrupt. The other 474 * three termination signals are more of a "get out *now*" command. 475 */ 476 if (signo == SIGINT) { 477 JobInterrupt(TRUE, signo); 478 } else if ( 0 479 #ifdef SIGHUP /* not all systems supports this signal */ 480 || (signo == SIGHUP) 481 #endif 482 || (signo == SIGTERM) 483 #ifdef SIGQUIT /* not all systems supports this signal */ 484 || (signo == SIGQUIT) 485 #endif 486 ) { 487 JobInterrupt(FALSE, signo); 488 } 489 490 #ifdef SIGQUIT /* not all systems supports this signal */ 421 491 /* 422 492 * Leave gracefully if SIGQUIT, rather than core dumping. 423 493 */ 424 494 if (signo == SIGQUIT) { 425 signo = SIGINT; 426 } 427 495 signo = SIGINT; 496 } 497 #endif 498 499 #if !defined(USE_KLIB) || !(defined(OS2) || defined(WIN32)) 428 500 /* 429 501 * Send ourselves the signal now we've given the message to everyone else. … … 439 511 act.sa_flags = 0; 440 512 sigaction(signo, &act, NULL); 513 #endif 441 514 442 515 if (DEBUG(JOB)) { 443 444 445 446 516 (void) fprintf(stdout, 517 "JobPassSig passing signal to self, mask = %x.\n", 518 ~0 & ~(1 << (signo-1))); 519 (void) fflush(stdout); 447 520 } 448 521 (void) signal(signo, SIG_DFL); … … 453 526 Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo); 454 527 528 #if !defined(USE_KLIB) || !(defined(OS2) || defined(WIN32)) 455 529 (void) sigprocmask(SIG_SETMASK, &omask, NULL); 456 530 sigprocmask(SIG_SETMASK, &omask, NULL); 457 531 act.sa_handler = JobPassSig; 458 532 sigaction(signo, &act, NULL); 533 #endif 534 #endif /* KLIB + OS2/Win32 */ 459 535 } 460 536 … … 462 538 *----------------------------------------------------------------------- 463 539 * JobCmpPid -- 464 * 465 * 466 * 540 * Compare the pid of the job with the given pid and return 0 if they 541 * are equal. This function is called from Job_CatchChildren via 542 * Lst_Find to find the job descriptor of the finished job. 467 543 * 468 544 * Results: 469 * 545 * 0 if the pid's match 470 546 * 471 547 * Side Effects: 472 * 548 * None 473 549 *----------------------------------------------------------------------- 474 550 */ 475 551 static int 476 552 JobCmpPid(job, pid) 477 ClientData job; 478 ClientData pid; 553 ClientData job; /* job to examine */ 554 ClientData pid; /* process id desired */ 479 555 { 480 556 return *(int *) pid - ((Job *) job)->pid; … … 485 561 *----------------------------------------------------------------------- 486 562 * JobCmpRmtID -- 487 * 488 * 563 * Compare the rmtID of the job with the given rmtID and return 0 if they 564 * are equal. 489 565 * 490 566 * Results: 491 * 567 * 0 if the rmtID's match 492 568 * 493 569 * Side Effects: 494 * 570 * None. 495 571 *----------------------------------------------------------------------- 496 572 */ 497 573 static int 498 574 JobCmpRmtID(job, rmtID) 499 ClientData job; 500 ClientData rmtID; 575 ClientData job; /* job to examine */ 576 ClientData rmtID; /* remote id desired */ 501 577 { 502 578 return(*(int *) rmtID - *(int *) job->rmtID); … … 507 583 *----------------------------------------------------------------------- 508 584 * JobPrintCommand -- 509 * 510 * 511 * 512 * 513 * 514 * 515 * 516 * 517 * 518 * 519 * 520 * 585 * Put out another command for the given job. If the command starts 586 * with an @ or a - we process it specially. In the former case, 587 * so long as the -s and -n flags weren't given to make, we stick 588 * a shell-specific echoOff command in the script. In the latter, 589 * we ignore errors for the entire job, unless the shell has error 590 * control. 591 * If the command is just "..." we take all future commands for this 592 * job to be commands to be executed once the entire graph has been 593 * made and return non-zero to signal that the end of the commands 594 * was reached. These commands are later attached to the postCommands 595 * node and executed by Job_End when all things are done. 596 * This function is called from JobStart via Lst_ForEach. 521 597 * 522 598 * Results: 523 * 599 * Always 0, unless the command was "..." 524 600 * 525 601 * Side Effects: 526 * 527 * 528 * 529 * 530 * 602 * If the command begins with a '-' and the shell has no error control, 603 * the JOB_IGNERR flag is set in the job descriptor. 604 * If the command is "..." and we're not ignoring such things, 605 * tailCmds is set to the successor node of the cmd. 606 * numCommands is incremented if the command is actually printed. 531 607 *----------------------------------------------------------------------- 532 608 */ 533 609 static int 534 610 JobPrintCommand(cmdp, jobp) 535 ClientData cmdp; 536 ClientData jobp; 611 ClientData cmdp; /* command string to print */ 612 ClientData jobp; /* job for which to print it */ 537 613 { 538 Boolean noSpecials;/* true if we shouldn't worry about539 540 614 Boolean noSpecials; /* true if we shouldn't worry about 615 * inserting special commands into 616 * the input stream. */ 541 617 Boolean shutUp = FALSE; /* true if we put a no echo command 542 543 Boolean 544 545 546 char *cmdTemplate;/* Template to use when printing the547 548 char *cmdStart;/* Start of expanded command */549 LstNode cmdNode;/* Node for replacing the command */550 char 618 * into the command file */ 619 Boolean errOff = FALSE; /* true if we turned error checking 620 * off before printing the command 621 * and need to turn it back on */ 622 char *cmdTemplate; /* Template to use when printing the 623 * command */ 624 char *cmdStart; /* Start of expanded command */ 625 LstNode cmdNode; /* Node for replacing the command */ 626 char *cmd = (char *) cmdp; 551 627 Job *job = (Job *) jobp; 552 628 … … 554 630 555 631 if (strcmp(cmd, "...") == 0) { 556 557 558 559 560 561 562 563 } 564 565 #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { 566 (void) fprintf(stdout, fmt, arg);\567 (void) fflush(stdout);\568 } 569 (void) fprintf(job->cmdFILE, fmt, arg); 632 job->node->type |= OP_SAVE_CMDS; 633 if ((job->flags & JOB_IGNDOTS) == 0) { 634 job->tailCmds = Lst_Succ(Lst_Member(job->node->commands, 635 (ClientData)cmd)); 636 return 1; 637 } 638 return 0; 639 } 640 641 #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ 642 (void) fprintf(stdout, fmt, arg); \ 643 (void) fflush(stdout); \ 644 } \ 645 (void) fprintf(job->cmdFILE, fmt, arg); \ 570 646 (void) fflush(job->cmdFILE); 571 647 … … 586 662 */ 587 663 while (*cmd == '@' || *cmd == '-') { 588 589 590 591 592 593 664 if (*cmd == '@') { 665 shutUp = DEBUG(LOUD) ? FALSE : TRUE; 666 } else { 667 errOff = TRUE; 668 } 669 cmd++; 594 670 } 595 671 596 672 while (isspace((unsigned char) *cmd)) 597 673 cmd++; 598 674 599 675 #ifndef KMK 600 676 if (shutUp) { 601 602 603 604 605 606 677 if (!(job->flags & JOB_SILENT) && !noSpecials && 678 commandShell->hasEchoCtl) { 679 DBPRINTF("%s\n", commandShell->echoOff); 680 } else { 681 shutUp = FALSE; 682 } 607 683 } 608 684 #endif 609 685 610 686 if (errOff) { 611 687 if ( !(job->flags & JOB_IGNERR) && !noSpecials) { 612 688 #ifdef KMK 613 689 errOff = FALSE; 614 690 #else 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 691 if (commandShell->hasErrCtl) { 692 /* 693 * we don't want the error-control commands showing 694 * up either, so we turn off echoing while executing 695 * them. We could put another field in the shell 696 * structure to tell JobDoOutput to look for this 697 * string too, but why make it any more complex than 698 * it already is? 699 */ 700 if (!(job->flags & JOB_SILENT) && !shutUp && 701 commandShell->hasEchoCtl) { 702 DBPRINTF("%s\n", commandShell->echoOff); 703 DBPRINTF("%s\n", commandShell->ignErr); 704 DBPRINTF("%s\n", commandShell->echoOn); 705 } else { 706 DBPRINTF("%s\n", commandShell->ignErr); 707 } 708 } else if (commandShell->ignErr && 709 (*commandShell->ignErr != '\0')) 710 { 711 /* 712 * The shell has no error control, so we need to be 713 * weird to get it to ignore any errors from the command. 714 * If echoing is turned on, we turn it off and use the 715 * errCheck template to echo the command. Leave echoing 716 * off so the user doesn't see the weirdness we go through 717 * to ignore errors. Set cmdTemplate to use the weirdness 718 * instead of the simple "%s\n" template. 719 */ 720 if (!(job->flags & JOB_SILENT) && !shutUp && 721 commandShell->hasEchoCtl) { 722 DBPRINTF("%s\n", commandShell->echoOff); 723 DBPRINTF(commandShell->errCheck, cmd); 724 shutUp = TRUE; 725 } 726 cmdTemplate = commandShell->ignErr; 727 /* 728 * The error ignoration (hee hee) is already taken care 729 * of by the ignErr template, so pretend error checking 730 * is still on. 731 */ 732 errOff = FALSE; 733 } else { 734 errOff = FALSE; 735 } 660 736 #endif 661 662 663 737 } else { 738 errOff = FALSE; 739 } 664 740 } 665 741 … … 668 744 #ifndef KMK /*todo*/ 669 745 if (errOff) { 670 671 672 673 674 675 676 677 678 679 746 /* 747 * If echoing is already off, there's no point in issuing the 748 * echoOff command. Otherwise we issue it and pretend it was on 749 * for the whole command... 750 */ 751 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ 752 DBPRINTF("%s\n", commandShell->echoOff); 753 shutUp = TRUE; 754 } 755 DBPRINTF("%s\n", commandShell->errCheck); 680 756 } 681 757 if (shutUp) { 682 758 DBPRINTF("%s\n", commandShell->echoOn); 683 759 } 684 760 #endif … … 689 765 *----------------------------------------------------------------------- 690 766 * JobSaveCommand -- 691 * 692 * 767 * Save a command to be executed when everything else is done. 768 * Callback function for JobFinish... 693 769 * 694 770 * Results: 695 * 771 * Always returns 0 696 772 * 697 773 * Side Effects: 698 * 774 * The command is tacked onto the end of postCommands's commands list. 699 775 * 700 776 *----------------------------------------------------------------------- … … 714 790 *----------------------------------------------------------------------- 715 791 * JobClose -- 716 * 792 * Called to close both input and output pipes when a job is finished. 717 793 * 718 794 * Results: 719 * 795 * Nada 720 796 * 721 797 * Side Effects: 722 * 798 * The file descriptors associated with the job are closed. 723 799 * 724 800 *----------------------------------------------------------------------- … … 728 804 Job *job; 729 805 { 806 #ifdef USE_PIPES 730 807 if (usePipes) { 731 808 #ifdef RMT_WILL_WATCH 732 809 Rmt_Ignore(job->inPipe); 733 810 #else 734 735 #endif 736 737 738 739 740 811 FD_CLR(job->inPipe, &outputs); 812 #endif 813 if (job->outPipe != job->inPipe) { 814 (void) close(job->outPipe); 815 } 816 JobDoOutput(job, TRUE); 817 (void) close(job->inPipe); 741 818 } else { 742 (void) close(job->outFd); 743 JobDoOutput(job, TRUE); 744 } 819 (void) close(job->outFd); 820 JobDoOutput(job, TRUE); 821 } 822 823 #else /* Don't use Pipes */ 824 close(job->outFd); 825 JobDoOutput(job, TRUE); 826 #endif /* USE_PIPES */ 745 827 } 746 828 … … 748 830 *----------------------------------------------------------------------- 749 831 * JobFinish -- 750 * 751 * 752 * 753 * 754 * 755 * 832 * Do final processing for the given job including updating 833 * parents and starting new jobs as available/necessary. Note 834 * that we pay no attention to the JOB_IGNERR flag here. 835 * This is because when we're called because of a noexecute flag 836 * or something, jstat.w_status is 0 and when called from 837 * Job_CatchChildren, the status is zeroed if it s/b ignored. 756 838 * 757 839 * Results: 758 * 840 * None 759 841 * 760 842 * Side Effects: 761 * 762 * 763 * 764 * 765 * 766 * 767 * 843 * Some nodes may be put on the toBeMade queue. 844 * Final commands for the job are placed on postCommands. 845 * 846 * If we got an error and are aborting (aborting == ABORT_ERROR) and 847 * the job list is now empty, we are done for the day. 848 * If we recognized an error (errors !=0), we set the aborting flag 849 * to ABORT_ERROR so no more jobs will be started. 768 850 *----------------------------------------------------------------------- 769 851 */ … … 771 853 static void 772 854 JobFinish(job, status) 773 Job *job; /* job to finish */ 774 int *status; /* sub-why job went away */ 855 Job *job; /* job to finish */ 856 #ifdef USE_KLIB 857 KPROCRES *status; /* sub-why job went away */ 858 #else 859 int *status; /* sub-why job went away */ 860 #endif 775 861 { 776 Boolean done; 862 #ifdef USE_KLIB 863 Boolean done; 864 865 if ( ( (status->fFlags & KPROCRES_FLAGS_NORMAL) && status->uExitCode != 0 && !(job->flags & JOB_IGNERR) ) 866 || !(status->fFlags & KPROCRES_FLAGS_NORMAL) 867 ) 868 { 869 /* 870 * If it exited non-zero and either we're doing things our 871 * way or we're not ignoring errors, the job is finished. 872 * Similarly, if the shell died because of a signal 873 * the job is also finished. In these 874 * cases, finish out the job's output before printing the exit 875 * status... 876 */ 877 JobClose(job); 878 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 879 (void) fclose(job->cmdFILE); 880 job->cmdFILE = NULL; 881 } 882 done = TRUE; 883 } else if (status->fFlags & KPROCRES_FLAGS_NORMAL) { 884 /* 885 * Deal with ignored errors in -B mode. We need to print a message 886 * telling of the ignored error as well as setting status.w_status 887 * to 0 so the next command gets run. To do this, we set done to be 888 * TRUE if in -B mode and the job exited non-zero. 889 */ 890 done = status->uExitCode != 0; 891 /* 892 * Old comment said: "Note we don't 893 * want to close down any of the streams until we know we're at the 894 * end." 895 * But we do. Otherwise when are we going to print the rest of the 896 * stuff? 897 */ 898 JobClose(job); 899 } else { 900 /* 901 * No need to close things down or anything. 902 */ 903 done = FALSE; 904 } 905 906 if ( done 907 || DEBUG(JOB)) 908 { 909 FILE *out = stdout; 910 if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) 911 { 912 /* 913 * If output is going to a file and this job is ignoring 914 * errors, arrange to have the exit status sent to the 915 * output file as well. 916 */ 917 out = fdopen(job->outFd, "w"); 918 } 919 920 if (status->fFlags & KPROCRES_FLAGS_NORMAL) 921 { 922 if (DEBUG(JOB)) 923 { 924 fprintf(stdout, "Process %d exited.\n", job->pid); 925 fflush(stdout); 926 } 927 if (status->uExitCode != 0) 928 { 929 #ifdef USE_PIPES 930 if (usePipes && job->node != lastNode) 931 { 932 MESSAGE(out, job->node); 933 lastNode = job->node; 934 } 935 #endif 936 fprintf(out, "*** Error code %d%s\n", 937 status->uExitCode, 938 (job->flags & JOB_IGNERR) ? "(ignored)" : ""); 939 940 if (job->flags & JOB_IGNERR) 941 status->uExitCode = 0; 942 } 943 else if (DEBUG(JOB)) 944 { 945 #ifdef USE_PIPES 946 if (usePipes && job->node != lastNode) 947 { 948 MESSAGE(out, job->node); 949 lastNode = job->node; 950 } 951 #endif 952 fprintf(out, "*** Completed successfully\n"); 953 } 954 } 955 else 956 { 957 #ifdef USE_PIPES 958 if (usePipes && job->node != lastNode) 959 { 960 MESSAGE(out, job->node); 961 lastNode = job->node; 962 } 963 #endif 964 fprintf(out, "*** Abnormal End\n"); 965 } 966 967 fflush(out); 968 } 969 970 /* 971 * Now handle the -B-mode stuff. If the beast still isn't finished, 972 * try and restart the job on the next command. If JobStart says it's 973 * ok, it's ok. If there's an error, this puppy is done. 974 */ 975 if ( compatMake 976 && (status->fFlags & KPROCRES_FLAGS_NORMAL) 977 && !Lst_IsAtEnd(job->node->commands) 978 ) 979 { 980 switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) 981 { 982 case JOB_RUNNING: 983 done = FALSE; 984 break; 985 case JOB_ERROR: 986 done = TRUE; 987 status->uExitCode = EXIT_FAILURE; 988 break; 989 case JOB_FINISHED: 990 /* 991 * If we got back a JOB_FINISHED code, JobStart has already 992 * called Make_Update and freed the job descriptor. We set 993 * done to false here to avoid fake cycles and double frees. 994 * JobStart needs to do the update so we can proceed up the 995 * graph when given the -n flag.. 996 */ 997 done = FALSE; 998 break; 999 } 1000 } else { 1001 done = TRUE; 1002 } 1003 1004 1005 if ( done 1006 && aborting != ABORT_ERROR 1007 && aborting != ABORT_INTERRUPT 1008 && (status->fFlags & KPROCRES_FLAGS_NORMAL) 1009 && status->uExitCode == 0 1010 ) 1011 { 1012 /* 1013 * As long as we aren't aborting and the job didn't return a non-zero 1014 * status that we shouldn't ignore, we call Make_Update to update 1015 * the parents. In addition, any saved commands for the node are placed 1016 * on the .END target. 1017 */ 1018 if (job->tailCmds != NILLNODE) { 1019 Lst_ForEachFrom(job->node->commands, job->tailCmds, 1020 JobSaveCommand, 1021 (ClientData)job->node); 1022 } 1023 job->node->made = MADE; 1024 Make_Update(job->node); 1025 efree((Address)job); 1026 } 1027 else if (!(status->fFlags & KPROCRES_FLAGS_NORMAL) || status->uExitCode != 0) 1028 { 1029 errors += 1; 1030 efree((Address)job); 1031 } 1032 1033 /* 1034 * Set aborting if any error. 1035 */ 1036 if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) 1037 { 1038 /* 1039 * If we found any errors in this batch of children and the -k flag 1040 * wasn't given, we set the aborting flag so no more jobs get 1041 * started. 1042 */ 1043 aborting = ABORT_ERROR; 1044 } 1045 1046 if ((aborting == ABORT_ERROR) && Job_Empty()) 1047 { 1048 /* 1049 * If we are aborting and the job table is now empty, we finish. 1050 */ 1051 Finish(errors); 1052 } 1053 1054 1055 #else /* Don't use kLib */ 1056 Boolean done; 777 1057 778 1058 if ((WIFEXITED(*status) && 779 780 1059 (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) || 1060 (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT))) 781 1061 { 782 783 784 785 786 787 788 789 1062 /* 1063 * If it exited non-zero and either we're doing things our 1064 * way or we're not ignoring errors, the job is finished. 1065 * Similarly, if the shell died because of a signal 1066 * the job is also finished. In these 1067 * cases, finish out the job's output before printing the exit 1068 * status... 1069 */ 790 1070 #ifdef REMOTE 791 792 #endif 793 794 795 796 797 1071 KILL(job->pid, SIGCONT); 1072 #endif 1073 JobClose(job); 1074 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1075 (void) fclose(job->cmdFILE); 1076 } 1077 done = TRUE; 798 1078 #ifdef REMOTE 799 800 1079 if (job->flags & JOB_REMOTE) 1080 Rmt_Done(job->rmtID, job->node); 801 1081 #endif 802 1082 } else if (WIFEXITED(*status)) { 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 1083 /* 1084 * Deal with ignored errors in -B mode. We need to print a message 1085 * telling of the ignored error as well as setting status.w_status 1086 * to 0 so the next command gets run. To do this, we set done to be 1087 * TRUE if in -B mode and the job exited non-zero. 1088 */ 1089 done = WEXITSTATUS(*status) != 0; 1090 /* 1091 * Old comment said: "Note we don't 1092 * want to close down any of the streams until we know we're at the 1093 * end." 1094 * But we do. Otherwise when are we going to print the rest of the 1095 * stuff? 1096 */ 1097 JobClose(job); 818 1098 #ifdef REMOTE 819 820 1099 if (job->flags & JOB_REMOTE) 1100 Rmt_Done(job->rmtID, job->node); 821 1101 #endif /* REMOTE */ 822 1102 } else { 823 824 825 826 1103 /* 1104 * No need to close things down or anything. 1105 */ 1106 done = FALSE; 827 1107 } 828 1108 829 1109 if (done || 830 831 832 1110 WIFSTOPPED(*status) || 1111 (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) || 1112 DEBUG(JOB)) 833 1113 { 834 FILE *out; 835 836 if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 837 /* 838 * If output is going to a file and this job is ignoring 839 * errors, arrange to have the exit status sent to the 840 * output file as well. 841 */ 842 out = fdopen(job->outFd, "w"); 843 } else { 844 out = stdout; 845 } 846 847 if (WIFEXITED(*status)) { 848 if (DEBUG(JOB)) { 849 (void) fprintf(stdout, "Process %d exited.\n", job->pid); 850 (void) fflush(stdout); 851 } 852 if (WEXITSTATUS(*status) != 0) { 853 if (usePipes && job->node != lastNode) { 854 MESSAGE(out, job->node); 855 lastNode = job->node; 856 } 857 (void) fprintf(out, "*** Error code %d%s\n", 858 WEXITSTATUS(*status), 859 (job->flags & JOB_IGNERR) ? "(ignored)" : ""); 860 861 if (job->flags & JOB_IGNERR) { 862 *status = 0; 863 } 864 } else if (DEBUG(JOB)) { 865 if (usePipes && job->node != lastNode) { 866 MESSAGE(out, job->node); 867 lastNode = job->node; 868 } 869 (void) fprintf(out, "*** Completed successfully\n"); 870 } 871 } else if (WIFSTOPPED(*status)) { 872 if (DEBUG(JOB)) { 873 (void) fprintf(stdout, "Process %d stopped.\n", job->pid); 874 (void) fflush(stdout); 875 } 876 if (usePipes && job->node != lastNode) { 877 MESSAGE(out, job->node); 878 lastNode = job->node; 879 } 880 if (!(job->flags & JOB_REMIGRATE)) { 881 (void) fprintf(out, "*** Stopped -- signal %d\n", 882 WSTOPSIG(*status)); 883 } 884 job->flags |= JOB_RESUME; 885 (void)Lst_AtEnd(stoppedJobs, (ClientData)job); 886 #ifdef REMOTE 887 if (job->flags & JOB_REMIGRATE) 888 JobRestart(job); 889 #endif 890 (void) fflush(out); 891 return; 892 } else if (WTERMSIG(*status) == SIGCONT) { 893 /* 894 * If the beastie has continued, shift the Job from the stopped 895 * list to the running one (or re-stop it if concurrency is 896 * exceeded) and go and get another child. 897 */ 898 if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) { 899 if (usePipes && job->node != lastNode) { 900 MESSAGE(out, job->node); 901 lastNode = job->node; 902 } 903 (void) fprintf(out, "*** Continued\n"); 904 } 905 if (!(job->flags & JOB_CONTINUING)) { 906 if (DEBUG(JOB)) { 907 (void) fprintf(stdout, 908 "Warning: process %d was not continuing.\n", 909 job->pid); 910 (void) fflush(stdout); 911 } 1114 FILE *out; 1115 1116 if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { 1117 /* 1118 * If output is going to a file and this job is ignoring 1119 * errors, arrange to have the exit status sent to the 1120 * output file as well. 1121 */ 1122 out = fdopen(job->outFd, "w"); 1123 } else { 1124 out = stdout; 1125 } 1126 1127 if (WIFEXITED(*status)) { 1128 if (DEBUG(JOB)) { 1129 (void) fprintf(stdout, "Process %d exited.\n", job->pid); 1130 (void) fflush(stdout); 1131 } 1132 if (WEXITSTATUS(*status) != 0) { 1133 #ifdef USE_PIPES 1134 if (usePipes && job->node != lastNode) { 1135 MESSAGE(out, job->node); 1136 lastNode = job->node; 1137 } 1138 #endif 1139 (void) fprintf(out, "*** Error code %d%s\n", 1140 WEXITSTATUS(*status), 1141 (job->flags & JOB_IGNERR) ? "(ignored)" : ""); 1142 1143 if (job->flags & JOB_IGNERR) { 1144 *status = 0; 1145 } 1146 } else if (DEBUG(JOB)) { 1147 #ifdef USE_PIPES 1148 if (usePipes && job->node != lastNode) { 1149 MESSAGE(out, job->node); 1150 lastNode = job->node; 1151 } 1152 #endif 1153 (void) fprintf(out, "*** Completed successfully\n"); 1154 } 1155 } else if (WIFSTOPPED(*status)) { 1156 if (DEBUG(JOB)) { 1157 (void) fprintf(stdout, "Process %d stopped.\n", job->pid); 1158 (void) fflush(stdout); 1159 } 1160 #ifdef USE_PIPES 1161 if (usePipes && job->node != lastNode) { 1162 MESSAGE(out, job->node); 1163 lastNode = job->node; 1164 } 1165 #endif 1166 if (!(job->flags & JOB_REMIGRATE)) { 1167 (void) fprintf(out, "*** Stopped -- signal %d\n", 1168 WSTOPSIG(*status)); 1169 } 1170 job->flags |= JOB_RESUME; 1171 (void)Lst_AtEnd(stoppedJobs, (ClientData)job); 1172 #if defined(REMOTE) && defined(SIGCONT) 1173 if (job->flags & JOB_REMIGRATE) 1174 JobRestart(job); 1175 #endif 1176 (void) fflush(out); 1177 return; 1178 } else if (WTERMSIG(*status) == SIGCONT) { 1179 /* 1180 * If the beastie has continued, shift the Job from the stopped 1181 * list to the running one (or re-stop it if concurrency is 1182 * exceeded) and go and get another child. 1183 */ 1184 if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) { 1185 #ifdef USE_PIPES 1186 if (usePipes && job->node != lastNode) { 1187 MESSAGE(out, job->node); 1188 lastNode = job->node; 1189 } 1190 #endif 1191 (void) fprintf(out, "*** Continued\n"); 1192 } 1193 if (!(job->flags & JOB_CONTINUING)) { 1194 if (DEBUG(JOB)) { 1195 (void) fprintf(stdout, 1196 "Warning: process %d was not continuing.\n", 1197 job->pid); 1198 (void) fflush(stdout); 1199 } 1200 #ifdef SIGCONT 912 1201 #ifdef notdef 913 /* 914 * We don't really want to restart a job from scratch just 915 * because it continued, especially not without killing the 916 * continuing process! That's why this is ifdef'ed out. 917 * FD - 9/17/90 918 */ 919 JobRestart(job); 920 #endif 921 } 922 job->flags &= ~JOB_CONTINUING; 923 Lst_AtEnd(jobs, (ClientData)job); 924 nJobs += 1; 925 if (!(job->flags & JOB_REMOTE)) { 926 if (DEBUG(JOB)) { 927 (void) fprintf(stdout, 928 "Process %d is continuing locally.\n", 929 job->pid); 930 (void) fflush(stdout); 931 } 932 nLocal += 1; 933 } 934 if (nJobs == maxJobs) { 935 jobFull = TRUE; 936 if (DEBUG(JOB)) { 937 (void) fprintf(stdout, "Job queue is full.\n"); 938 (void) fflush(stdout); 939 } 940 } 941 (void) fflush(out); 942 return; 943 } else { 944 if (usePipes && job->node != lastNode) { 945 MESSAGE(out, job->node); 946 lastNode = job->node; 947 } 948 (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status)); 949 } 950 951 (void) fflush(out); 1202 /* 1203 * We don't really want to restart a job from scratch just 1204 * because it continued, especially not without killing the 1205 * continuing process! That's why this is ifdef'ed out. 1206 * FD - 9/17/90 1207 */ 1208 JobRestart(job); 1209 #endif 1210 #endif 1211 } 1212 job->flags &= ~JOB_CONTINUING; 1213 Lst_AtEnd(jobs, (ClientData)job); 1214 nJobs += 1; 1215 if (!(job->flags & JOB_REMOTE)) { 1216 if (DEBUG(JOB)) { 1217 (void) fprintf(stdout, 1218 "Process %d is continuing locally.\n", 1219 job->pid); 1220 (void) fflush(stdout); 1221 } 1222 nLocal += 1; 1223 } 1224 if (nJobs == maxJobs) { 1225 jobFull = TRUE; 1226 if (DEBUG(JOB)) { 1227 (void) fprintf(stdout, "Job queue is full.\n"); 1228 (void) fflush(stdout); 1229 } 1230 } 1231 (void) fflush(out); 1232 return; 1233 } else { 1234 #ifdef USE_PIPES 1235 if (usePipes && job->node != lastNode) { 1236 MESSAGE(out, job->node); 1237 lastNode = job->node; 1238 } 1239 #endif 1240 (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status)); 1241 } 1242 1243 (void) fflush(out); 952 1244 } 953 1245 … … 958 1250 */ 959 1251 if (compatMake && (WIFEXITED(*status) && 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 1252 !Lst_IsAtEnd(job->node->commands))) { 1253 switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) { 1254 case JOB_RUNNING: 1255 done = FALSE; 1256 break; 1257 case JOB_ERROR: 1258 done = TRUE; 1259 W_SETEXITSTATUS(status, 1); 1260 break; 1261 case JOB_FINISHED: 1262 /* 1263 * If we got back a JOB_FINISHED code, JobStart has already 1264 * called Make_Update and freed the job descriptor. We set 1265 * done to false here to avoid fake cycles and double frees. 1266 * JobStart needs to do the update so we can proceed up the 1267 * graph when given the -n flag.. 1268 */ 1269 done = FALSE; 1270 break; 1271 } 980 1272 } else { 981 1273 done = TRUE; 982 1274 } 983 1275 984 1276 985 1277 if (done && 986 987 988 1278 (aborting != ABORT_ERROR) && 1279 (aborting != ABORT_INTERRUPT) && 1280 (*status == 0)) 989 1281 { 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1282 /* 1283 * As long as we aren't aborting and the job didn't return a non-zero 1284 * status that we shouldn't ignore, we call Make_Update to update 1285 * the parents. In addition, any saved commands for the node are placed 1286 * on the .END target. 1287 */ 1288 if (job->tailCmds != NILLNODE) { 1289 Lst_ForEachFrom(job->node->commands, job->tailCmds, 1290 JobSaveCommand, 1291 (ClientData)job->node); 1292 } 1293 job->node->made = MADE; 1294 Make_Update(job->node); 1295 efree((Address)job); 1004 1296 } else if (*status != 0) { 1005 errors += 1; 1006 efree((Address)job); 1007 } 1008 1297 errors += 1; 1298 efree((Address)job); 1299 } 1300 1301 #ifdef SIGCONT 1009 1302 JobRestartJobs(); 1303 #endif 1010 1304 1011 1305 /* … … 1013 1307 */ 1014 1308 if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) { 1015 1016 1017 1018 1019 1020 1309 /* 1310 * If we found any errors in this batch of children and the -k flag 1311 * wasn't given, we set the aborting flag so no more jobs get 1312 * started. 1313 */ 1314 aborting = ABORT_ERROR; 1021 1315 } 1022 1316 1023 1317 if ((aborting == ABORT_ERROR) && Job_Empty()) 1024 /* 1025 * If we are aborting and the job table is now empty, we finish. 1026 */ 1027 Finish(errors); 1318 /* 1319 * If we are aborting and the job table is now empty, we finish. 1320 */ 1321 Finish(errors); 1322 #endif /* USE_KLIB */ 1028 1323 } 1029 1324 … … 1031 1326 *----------------------------------------------------------------------- 1032 1327 * Job_Touch -- 1033 * 1034 * 1328 * Touch the given target. Called by JobStart when the -t flag was 1329 * given 1035 1330 * 1036 1331 * Results: 1037 * 1332 * None 1038 1333 * 1039 1334 * Side Effects: 1040 * 1041 * 1335 * The data modification of the file is changed. In addition, if the 1336 * file did not exist, it is created. 1042 1337 *----------------------------------------------------------------------- 1043 1338 */ 1044 1339 void 1045 1340 Job_Touch(gn, silent) 1046 GNode *gn; 1047 Boolean silent;/* TRUE if should not print messages */1341 GNode *gn; /* the node of the file to touch */ 1342 Boolean silent; /* TRUE if should not print messages */ 1048 1343 { 1049 int streamID;/* ID of stream opened to do the touch */1050 struct utimbuf times; 1344 int streamID; /* ID of stream opened to do the touch */ 1345 struct utimbuf times; /* Times for utime() call */ 1051 1346 1052 1347 if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) { 1053 1054 1055 1056 1057 1348 /* 1349 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets 1350 * and, as such, shouldn't really be created. 1351 */ 1352 return; 1058 1353 } 1059 1354 1060 1355 if (!silent) { 1061 1062 1356 (void) fprintf(stdout, "touch %s\n", gn->name); 1357 (void) fflush(stdout); 1063 1358 } 1064 1359 1065 1360 if (noExecute) { 1066 1361 return; 1067 1362 } 1068 1363 1069 1364 #ifdef USE_ARCHIVES 1070 1365 if (gn->type & OP_ARCHV) { 1071 1366 Arch_Touch(gn); 1072 1367 } else if (gn->type & OP_LIB) { 1073 1368 Arch_TouchLib(gn); 1074 1369 } else { 1075 1370 #else … … 1077 1372 #endif 1078 1373 1079 char*file = gn->path ? gn->path : gn->name;1080 1081 1082 1083 1084 1085 1086 charc;1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1374 char *file = gn->path ? gn->path : gn->name; 1375 1376 times.actime = times.modtime = now; 1377 if (utime(file, ×) < 0){ 1378 streamID = open(file, O_RDWR | O_CREAT, 0666); 1379 1380 if (streamID >= 0) { 1381 char c; 1382 1383 /* 1384 * Read and write a byte to the file to change the 1385 * modification time, then close the file. 1386 */ 1387 if (read(streamID, &c, 1) == 1) { 1388 (void) lseek(streamID, 0L, SEEK_SET); 1389 (void) write(streamID, &c, 1); 1390 } 1391 1392 (void) close(streamID); 1393 } else { 1394 (void) fprintf(stdout, "*** couldn't touch %s: %s", 1395 file, strerror(errno)); 1396 (void) fflush(stdout); 1397 } 1398 } 1104 1399 } 1105 1400 } … … 1108 1403 *----------------------------------------------------------------------- 1109 1404 * Job_CheckCommands -- 1110 * 1405 * Make sure the given node has all the commands it needs. 1111 1406 * 1112 1407 * Results: 1113 * 1408 * TRUE if the commands list is/was ok. 1114 1409 * 1115 1410 * Side Effects: 1116 * 1117 * 1411 * The node will have commands from the .DEFAULT rule added to it 1412 * if it needs them. 1118 1413 *----------------------------------------------------------------------- 1119 1414 */ 1120 1415 Boolean 1121 1416 Job_CheckCommands(gn, abortProc) 1122 GNode *gn; 1123 1124 void 1125 1417 GNode *gn; /* The target whose commands need 1418 * verifying */ 1419 void (*abortProc) __P((char *, ...)); 1420 /* Function to abort with message */ 1126 1421 { 1127 1422 if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) … … 1131 1426 ) 1132 1427 { 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1428 /* 1429 * No commands. Look for .DEFAULT rule from which we might infer 1430 * commands 1431 */ 1432 if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) { 1433 char *p1; 1434 /* 1435 * Make only looks for a .DEFAULT if the node was never the 1436 * target of an operator, so that's what we do too. If 1437 * a .DEFAULT was given, we substitute its commands for gn's 1438 * commands and set the IMPSRC variable to be the target's name 1439 * The DEFAULT node acts like a transformation rule, in that 1440 * gn also inherits any attributes or sources attached to 1441 * .DEFAULT itself. 1442 */ 1443 Make_HandleUse(DEFAULT, gn); 1444 Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn); 1445 efree(p1); 1446 } else if (Dir_MTime(gn) == 0) { 1447 /* 1448 * The node wasn't the target of an operator we have no .DEFAULT 1449 * rule to go on and the target doesn't already exist. There's 1450 * nothing more we can do for this branch. If the -k flag wasn't 1451 * given, we stop in our tracks, otherwise we just don't update 1452 * this node's parents so they never get examined. 1453 */ 1454 static const char msg[] = MAKE_NAME ": don't know how to make"; 1455 1456 if (gn->type & OP_OPTIONAL) { 1457 (void) fprintf(stdout, "%s %s(ignored)\n", msg, gn->name); 1458 (void) fflush(stdout); 1459 } else if (keepgoing) { 1460 (void) fprintf(stdout, "%s %s(continuing)\n", msg, gn->name); 1461 (void) fflush(stdout); 1462 return FALSE; 1463 } else { 1169 1464 #if OLD_JOKE 1170 1171 1465 if (strcmp(gn->name,"love") == 0) 1466 (*abortProc)("Not war."); 1172 1467 #if defined(NMAKE) || defined(KMK) 1173 1468 else if (strcmp(gn->name,"fire") == 0) 1174 1469 (*abortProc)("No match."); 1175 1470 #endif 1176 1471 else 1177 1472 #endif 1178 1179 1180 1181 1473 (*abortProc)("%s %s. Stop", msg, gn->name); 1474 return FALSE; 1475 } 1476 } 1182 1477 } 1183 1478 return TRUE; … … 1187 1482 *----------------------------------------------------------------------- 1188 1483 * JobLocalInput -- 1189 * 1484 * Handle a pipe becoming readable. Callback function for Rmt_Watch 1190 1485 * 1191 1486 * Results: 1192 * 1487 * None 1193 1488 * 1194 1489 * Side Effects: 1195 * 1490 * JobDoOutput is called. 1196 1491 * 1197 1492 *----------------------------------------------------------------------- … … 1200 1495 static void 1201 1496 JobLocalInput(stream, job) 1202 int stream;/* Stream that's ready (ignored) */1203 Job *job;/* Job to which the stream belongs */1497 int stream; /* Stream that's ready (ignored) */ 1498 Job *job; /* Job to which the stream belongs */ 1204 1499 { 1205 1500 JobDoOutput(job, FALSE); … … 1210 1505 *----------------------------------------------------------------------- 1211 1506 * JobExec -- 1212 * 1213 * 1507 * Execute the shell for the given job. Called from JobStart and 1508 * JobRestart. 1214 1509 * 1215 1510 * Results: 1216 * 1511 * None. 1217 1512 * 1218 1513 * Side Effects: 1219 * 1220 * 1514 * A shell is executed, outputs is altered and the Job structure added 1515 * to the job table. 1221 1516 * 1222 1517 *----------------------------------------------------------------------- … … 1224 1519 static void 1225 1520 JobExec(job, argv) 1226 Job *job;/* Job to execute */1227 char 1521 Job *job; /* Job to execute */ 1522 char **argv; 1228 1523 { 1229 int cpid; /* ID of new child */ 1524 #ifdef USE_KLIB 1525 int cpid; /* ID of new child */ 1526 int rc; 1527 1528 if (DEBUG(JOB)) 1529 { 1530 int i; 1531 fprintf(stdout, "Running %s %sly\n", job->node->name, 1532 job->flags&JOB_REMOTE?"remote":"local"); 1533 fprintf(stdout, "\tCommand: "); 1534 for (i = 0; argv[i] != NULL; i++) 1535 fprintf(stdout, "%s ", argv[i]); 1536 fprintf(stdout, "\n"); 1537 fflush(stdout); 1538 } 1539 1540 /* 1541 * Some jobs produce no output and it's disconcerting to have 1542 * no feedback of their running (since they produce no output, the 1543 * banner with their name in it never appears). This is an attempt to 1544 * provide that feedback, even if nothing follows it. 1545 */ 1546 if ( lastNode != job->node 1547 && (job->flags & JOB_FIRST) 1548 && !(job->flags & JOB_SILENT) 1549 ) 1550 { 1551 MESSAGE(stdout, job->node); 1552 lastNode = job->node; 1553 } 1554 1555 /* 1556 * Create process with assigned output+stderr pipe. 1557 */ 1558 if (job->cmdFILE) 1559 fseek(job->cmdFILE, 0, SEEK_SET); 1560 rc = kProcCreate(argv, 1561 NULL, 1562 NULL, 1563 NULL, 1564 KPROCCREATE_FLAGS_SPAWN, 1565 job->cmdFILE ? FILENO(job->cmdFILE) : KFILE_NULL, 1566 usePipes ? job->outPipe : job->outFd, /* stdout */ 1567 usePipes ? job->outPipe : job->outFd, /* stderr */ 1568 &cpid, 1569 NULL); 1570 if (!rc) 1571 { 1572 job->pid = cpid; 1573 1574 #ifdef USE_PIPES 1575 if (usePipes && (job->flags & JOB_FIRST) ) 1576 { 1577 /* 1578 * The first time a job is run for a node, we set the current 1579 * position in the buffer to the beginning and mark another 1580 * stream to watch in the outputs mask 1581 */ 1582 job->curPos = 0; 1583 FD_SET(job->inPipe, &outputs); 1584 } 1585 #endif /* USE_PIPES */ 1586 1587 if (job->flags & JOB_REMOTE) { 1588 job->rmtID = 0; 1589 } else { 1590 nLocal += 1; 1591 /* 1592 * XXX: Used to not happen if REMOTE. Why? 1593 */ 1594 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1595 fclose(job->cmdFILE); 1596 job->cmdFILE = NULL; 1597 } 1598 } 1599 1600 /* 1601 * Now the job is actually running, add it to the table. 1602 */ 1603 nJobs += 1; 1604 (void) Lst_AtEnd(jobs, (ClientData)job); 1605 if (nJobs == maxJobs) 1606 { 1607 jobFull = TRUE; 1608 } 1609 } 1610 else 1611 Punt("Cannot start child (%d)", rc); 1612 1613 1614 1615 #else /* Don't use kLib */ 1616 int cpid; /* ID of new child */ 1230 1617 1231 1618 if (DEBUG(JOB)) { 1232 inti;1233 1234 1235 1236 1237 1238 1239 1240 1241 1619 int i; 1620 1621 (void) fprintf(stdout, "Running %s %sly\n", job->node->name, 1622 job->flags&JOB_REMOTE?"remote":"local"); 1623 (void) fprintf(stdout, "\tCommand: "); 1624 for (i = 0; argv[i] != NULL; i++) { 1625 (void) fprintf(stdout, "%s ", argv[i]); 1626 } 1627 (void) fprintf(stdout, "\n"); 1628 (void) fflush(stdout); 1242 1629 } 1243 1630 … … 1249 1636 */ 1250 1637 if ((lastNode != job->node) && (job->flags & JOB_FIRST) && 1251 1252 1253 1638 !(job->flags & JOB_SILENT)) { 1639 MESSAGE(stdout, job->node); 1640 lastNode = job->node; 1254 1641 } 1255 1642 1256 1643 #ifdef RMT_NO_EXEC 1257 1644 if (job->flags & JOB_REMOTE) { 1258 1645 goto jobExecFinish; 1259 1646 } 1260 1647 #endif /* RMT_NO_EXEC */ … … 1265 1652 if ((cpid = vfork()) == -1) { 1266 1653 #endif 1267 1654 Punt("Cannot fork"); 1268 1655 } else if (cpid == 0) { 1269 1656 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 if (dup2(job->outPipe, 1) == -1)1286 1287 1288 1289 1290 1291 1292 1293 if (dup2(job->outFd, 1) == -1)1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 if (dup2(1, 2) == -1)1304 1657 /* 1658 * Must duplicate the input stream down to the child's input and 1659 * reset it to the beginning (again). Since the stream was marked 1660 * close-on-exec, we must clear that bit in the new input. 1661 */ 1662 if (dup2(FILENO(job->cmdFILE), 0) == -1) 1663 Punt("Cannot dup2: %s", strerror(errno)); 1664 (void) fcntl(0, F_SETFD, 0); 1665 (void) lseek(0, 0, SEEK_SET); 1666 1667 if (usePipes) { 1668 /* 1669 * Set up the child's output to be routed through the pipe 1670 * we've created for it. 1671 */ 1672 if (dup2(job->outPipe, STDOUT_FILENO) == -1) 1673 Punt("Cannot dup2: %s", strerror(errno)); 1674 } else { 1675 /* 1676 * We're capturing output in a file, so we duplicate the 1677 * descriptor to the temporary file into the standard 1678 * output. 1679 */ 1680 if (dup2(job->outFd, STDOUT_FILENO) == -1) 1681 Punt("Cannot dup2: %s", strerror(errno)); 1682 } 1683 /* 1684 * The output channels are marked close on exec. This bit was 1685 * duplicated by the dup2 (on some systems), so we have to clear 1686 * it before routing the shell's error output to the same place as 1687 * its standard output. 1688 */ 1689 (void) fcntl(1, F_SETFD, 0); 1690 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1) 1691 Punt("Cannot dup2: %s", strerror(errno)); 1305 1692 1306 1693 #ifdef USE_PGRP 1307 1308 1309 1310 1311 1694 /* 1695 * We want to switch the child into a different process family so 1696 * we can kill it and all its descendants in one fell swoop, 1697 * by killing its process family, but not commit suicide. 1698 */ 1312 1699 # if defined(SYSV) 1313 1700 (void) setsid(); 1314 1701 # else 1315 1702 (void) setpgid(0, getpid()); 1316 1703 # endif 1317 1704 #endif /* USE_PGRP */ 1318 1705 1319 1706 #ifdef REMOTE 1320 1321 1322 1707 if (job->flags & JOB_REMOTE) { 1708 Rmt_Exec(shellPath, argv, FALSE); 1709 } else 1323 1710 #endif /* REMOTE */ 1324 1711 #ifdef KMK 1325 1712 (void) execv(argv[0], argv); 1326 1713 #else 1327 1328 #endif 1329 1330 1331 1332 1714 (void) execv(shellPath, argv); 1715 #endif 1716 1717 (void) write(2, "Could not execute shell\n", 1718 sizeof("Could not execute shell")); 1719 _exit(1); 1333 1720 } else { 1334 1721 #ifdef REMOTE 1335 long omask = sigblock(sigmask(SIGCHLD)); 1336 #endif 1337 job->pid = cpid; 1338 1339 if (usePipes && (job->flags & JOB_FIRST) ) { 1340 /* 1341 * The first time a job is run for a node, we set the current 1342 * position in the buffer to the beginning and mark another 1343 * stream to watch in the outputs mask 1344 */ 1345 job->curPos = 0; 1722 long omask = sigblock(sigmask(SIGCHLD)); 1723 #endif 1724 job->pid = cpid; 1725 1726 #ifdef USE_PIPES 1727 if (usePipes && (job->flags & JOB_FIRST) ) { 1728 /* 1729 * The first time a job is run for a node, we set the current 1730 * position in the buffer to the beginning and mark another 1731 * stream to watch in the outputs mask 1732 */ 1733 job->curPos = 0; 1346 1734 1347 1735 #ifdef RMT_WILL_WATCH 1348 1736 Rmt_Watch(job->inPipe, JobLocalInput, job); 1349 1737 #else 1350 1738 FD_SET(job->inPipe, &outputs); 1351 1739 #endif /* RMT_WILL_WATCH */ 1352 } 1353 1354 if (job->flags & JOB_REMOTE) { 1740 } 1741 #endif /* USE_PIPES */ 1742 1743 if (job->flags & JOB_REMOTE) { 1355 1744 #ifndef REMOTE 1356 1745 job->rmtID = 0; 1357 1746 #else 1358 1747 job->rmtID = Rmt_LastID(job->pid); 1359 1748 #endif /* REMOTE */ 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1749 } else { 1750 nLocal += 1; 1751 /* 1752 * XXX: Used to not happen if REMOTE. Why? 1753 */ 1754 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1755 (void) fclose(job->cmdFILE); 1756 job->cmdFILE = NULL; 1757 } 1758 } 1370 1759 #ifdef REMOTE 1371 1760 (void) sigsetmask(omask); 1372 1761 #endif 1373 1762 } … … 1382 1771 (void) Lst_AtEnd(jobs, (ClientData)job); 1383 1772 if (nJobs == maxJobs) { 1384 jobFull = TRUE; 1385 } 1773 jobFull = TRUE; 1774 } 1775 #endif /* USE_KLIB */ 1386 1776 } 1387 1777 … … 1390 1780 *----------------------------------------------------------------------- 1391 1781 * JobMakeArgv -- 1392 * 1782 * Create the argv needed to execute the shell for a given job. 1393 1783 * 1394 1784 * … … 1401 1791 static void 1402 1792 JobMakeArgv(job, argv) 1403 Job 1404 char 1793 Job *job; 1794 char **argv; 1405 1795 { 1406 int argc; 1407 static char args[10]; /* For merged arguments */ 1408 1409 #ifndef _PATH_DEFSHELLDIR 1410 /* @todo! */ 1411 argv[0] = "c:\\os2\\cmd.exe"; 1412 argc = 1; 1413 #else 1796 #ifdef KMK 1797 int argc; 1798 1799 argv[0] = argv0; 1800 argv[1] = "--kShell"; 1801 argc = 2; 1802 if (!(job->flags & JOB_IGNERR)) 1803 argv[argc++] = "-e"; 1804 if (!(job->flags & JOB_SILENT)) 1805 argv[argc++] = "-v"; 1806 argv[argc] = NULL; 1807 1808 #else /* not kMk */ 1809 int argc; 1810 static char args[10]; /* For merged arguments */ 1811 1414 1812 argv[0] = shellName; 1415 1813 argc = 1; 1416 1814 1417 1815 if ((commandShell->exit && (*commandShell->exit != '-')) || 1418 1816 (commandShell->echo && (*commandShell->echo != '-'))) 1419 1817 { 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1818 /* 1819 * At least one of the flags doesn't have a minus before it, so 1820 * merge them together. Have to do this because the *(&(@*#*&#$# 1821 * Bourne shell thinks its second argument is a file to source. 1822 * Grrrr. Note the ten-character limitation on the combined arguments. 1823 */ 1824 (void)sprintf(args, "-%s%s", 1825 ((job->flags & JOB_IGNERR) ? "" : 1826 (commandShell->exit ? commandShell->exit : "")), 1827 ((job->flags & JOB_SILENT) ? "" : 1828 (commandShell->echo ? commandShell->echo : ""))); 1829 1830 if (args[1]) { 1831 argv[argc] = args; 1832 argc++; 1833 } 1436 1834 } else { 1437 1438 1439 1440 1441 1442 1443 1444 1835 if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1836 argv[argc] = commandShell->exit; 1837 argc++; 1838 } 1839 if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1840 argv[argc] = commandShell->echo; 1841 argc++; 1842 } 1445 1843 } 1446 1844 argv[argc] = NULL; 1447 #endif 1845 #endif /* KMK */ 1448 1846 } 1449 1847 1450 1848 1849 #ifdef SIGCONT 1451 1850 /*- 1452 1851 *----------------------------------------------------------------------- 1453 1852 * JobRestart -- 1454 * 1853 * Restart a job that stopped for some reason. 1455 1854 * 1456 1855 * Results: 1457 * 1856 * None. 1458 1857 * 1459 1858 * Side Effects: 1460 * 1859 * jobFull will be set if the job couldn't be run. 1461 1860 * 1462 1861 *----------------------------------------------------------------------- … … 1464 1863 static void 1465 1864 JobRestart(job) 1466 Job *job;/* Job to restart */1865 Job *job; /* Job to restart */ 1467 1866 { 1468 1867 #ifdef REMOTE … … 1471 1870 1472 1871 if (job->flags & JOB_REMIGRATE) { 1473 1872 if ( 1474 1873 #ifdef REMOTE 1475 1476 #endif 1477 1478 1479 1480 1481 1874 verboseRemigrates || 1875 #endif 1876 DEBUG(JOB)) { 1877 (void) fprintf(stdout, "*** remigrating %x(%s)\n", 1878 job->pid, job->node->name); 1879 (void) fflush(stdout); 1880 } 1482 1881 1483 1882 #ifdef REMOTE 1484 1485 1486 1487 1488 1489 #endif 1490 1491 1492 1493 1494 1495 1496 1883 if (!Rmt_ReExport(job->pid, job->node, &host)) { 1884 if (verboseRemigrates || DEBUG(JOB)) { 1885 (void) fprintf(stdout, "*** couldn't migrate...\n"); 1886 (void) fflush(stdout); 1887 } 1888 #endif 1889 if (nLocal != maxLocal) { 1890 /* 1891 * Job cannot be remigrated, but there's room on the local 1892 * machine, so resume the job and note that another 1893 * local job has started. 1894 */ 1895 if ( 1497 1896 #ifdef REMOTE 1498 1499 #endif 1500 1501 1502 1503 1504 1505 1897 verboseRemigrates || 1898 #endif 1899 DEBUG(JOB)) { 1900 (void) fprintf(stdout, "*** resuming on local machine\n"); 1901 (void) fflush(stdout); 1902 } 1903 KILL(job->pid, SIGCONT); 1904 nLocal +=1; 1506 1905 #ifdef REMOTE 1507 1508 1906 job->flags &= ~(JOB_REMIGRATE|JOB_RESUME|JOB_REMOTE); 1907 job->flags |= JOB_CONTINUING; 1509 1908 #else 1510 1511 #endif 1512 1513 1514 1515 1516 1517 1909 job->flags &= ~(JOB_REMIGRATE|JOB_RESUME); 1910 #endif 1911 } else { 1912 /* 1913 * Job cannot be restarted. Mark the table as full and 1914 * place the job back on the list of stopped jobs. 1915 */ 1916 if ( 1518 1917 #ifdef REMOTE 1519 1520 #endif 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1918 verboseRemigrates || 1919 #endif 1920 DEBUG(JOB)) { 1921 (void) fprintf(stdout, "*** holding\n"); 1922 (void) fflush(stdout); 1923 } 1924 (void)Lst_AtFront(stoppedJobs, (ClientData)job); 1925 jobFull = TRUE; 1926 if (DEBUG(JOB)) { 1927 (void) fprintf(stdout, "Job queue is full.\n"); 1928 (void) fflush(stdout); 1929 } 1930 return; 1931 } 1533 1932 #ifdef REMOTE 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 #endif 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1933 } else { 1934 /* 1935 * Clear out the remigrate and resume flags. Set the continuing 1936 * flag so we know later on that the process isn't exiting just 1937 * because of a signal. 1938 */ 1939 job->flags &= ~(JOB_REMIGRATE|JOB_RESUME); 1940 job->flags |= JOB_CONTINUING; 1941 job->rmtID = host; 1942 } 1943 #endif 1944 1945 (void)Lst_AtEnd(jobs, (ClientData)job); 1946 nJobs += 1; 1947 if (nJobs == maxJobs) { 1948 jobFull = TRUE; 1949 if (DEBUG(JOB)) { 1950 (void) fprintf(stdout, "Job queue is full.\n"); 1951 (void) fflush(stdout); 1952 } 1953 } 1555 1954 } else if (job->flags & JOB_RESTART) { 1556 1557 1558 1559 1560 1561 1562 1563 1564 char*argv[4];1565 1566 1567 1568 1569 1570 1571 1955 /* 1956 * Set up the control arguments to the shell. This is based on the 1957 * flags set earlier for this job. If the JOB_IGNERR flag is clear, 1958 * the 'exit' flag of the commandShell is used to cause it to exit 1959 * upon receiving an error. If the JOB_SILENT flag is clear, the 1960 * 'echo' flag of the commandShell is used to get it to start echoing 1961 * as soon as it starts processing commands. 1962 */ 1963 char *argv[4]; 1964 1965 JobMakeArgv(job, argv); 1966 1967 if (DEBUG(JOB)) { 1968 (void) fprintf(stdout, "Restarting %s...", job->node->name); 1969 (void) fflush(stdout); 1970 } 1572 1971 #ifdef REMOTE 1573 1574 1972 if ((job->node->type&OP_NOEXPORT) || 1973 (nLocal < maxLocal && runLocalFirst) 1575 1974 # ifdef RMT_NO_EXEC 1576 1975 || !Rmt_Export(shellPath, argv, job) 1577 1976 # else 1578 1977 || !Rmt_Begin(shellPath, argv, job->node) 1579 1978 # endif 1580 1979 #endif 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1980 { 1981 if (((nLocal >= maxLocal) && !(job->flags & JOB_SPECIAL))) { 1982 /* 1983 * Can't be exported and not allowed to run locally -- put it 1984 * back on the hold queue and mark the table full 1985 */ 1986 if (DEBUG(JOB)) { 1987 (void) fprintf(stdout, "holding\n"); 1988 (void) fflush(stdout); 1989 } 1990 (void)Lst_AtFront(stoppedJobs, (ClientData)job); 1991 jobFull = TRUE; 1992 if (DEBUG(JOB)) { 1993 (void) fprintf(stdout, "Job queue is full.\n"); 1994 (void) fflush(stdout); 1995 } 1996 return; 1997 } else { 1998 /* 1999 * Job may be run locally. 2000 */ 2001 if (DEBUG(JOB)) { 2002 (void) fprintf(stdout, "running locally\n"); 2003 (void) fflush(stdout); 2004 } 2005 job->flags &= ~JOB_REMOTE; 2006 } 2007 } 1609 2008 #ifdef REMOTE 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 #endif 1621 2009 else { 2010 /* 2011 * Can be exported. Hooray! 2012 */ 2013 if (DEBUG(JOB)) { 2014 (void) fprintf(stdout, "exporting\n"); 2015 (void) fflush(stdout); 2016 } 2017 job->flags |= JOB_REMOTE; 2018 } 2019 #endif 2020 JobExec(job, argv); 1622 2021 } else { 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 2022 /* 2023 * The job has stopped and needs to be restarted. Why it stopped, 2024 * we don't know... 2025 */ 2026 if (DEBUG(JOB)) { 2027 (void) fprintf(stdout, "Resuming %s...", job->node->name); 2028 (void) fflush(stdout); 2029 } 2030 if (((job->flags & JOB_REMOTE) || 2031 (nLocal < maxLocal) || 1633 2032 #ifdef REMOTE 1634 1635 1636 2033 (((job->flags & JOB_SPECIAL) && 2034 (job->node->type & OP_NOEXPORT)) && 2035 (maxLocal == 0))) && 1637 2036 #else 1638 1639 1640 #endif 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 2037 ((job->flags & JOB_SPECIAL) && 2038 (maxLocal == 0))) && 2039 #endif 2040 (nJobs != maxJobs)) 2041 { 2042 /* 2043 * If the job is remote, it's ok to resume it as long as the 2044 * maximum concurrency won't be exceeded. If it's local and 2045 * we haven't reached the local concurrency limit already (or the 2046 * job must be run locally and maxLocal is 0), it's also ok to 2047 * resume it. 2048 */ 2049 Boolean error; 2050 int status; 1652 2051 1653 2052 #ifdef RMT_WANTS_SIGNALS 1654 1655 1656 1657 #endif 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 2053 if (job->flags & JOB_REMOTE) { 2054 error = !Rmt_Signal(job, SIGCONT); 2055 } else 2056 #endif /* RMT_WANTS_SIGNALS */ 2057 error = (KILL(job->pid, SIGCONT) != 0); 2058 2059 if (!error) { 2060 /* 2061 * Make sure the user knows we've continued the beast and 2062 * actually put the thing in the job table. 2063 */ 2064 job->flags |= JOB_CONTINUING; 2065 W_SETTERMSIG(&status, SIGCONT); 2066 JobFinish(job, &status); 2067 2068 job->flags &= ~(JOB_RESUME|JOB_CONTINUING); 2069 if (DEBUG(JOB)) { 2070 (void) fprintf(stdout, "done\n"); 2071 (void) fflush(stdout); 2072 } 2073 } else { 2074 Error("couldn't resume %s: %s", 2075 job->node->name, strerror(errno)); 2076 status = 0; 2077 W_SETEXITSTATUS(&status, 1); 2078 JobFinish(job, &status); 2079 } 2080 } else { 2081 /* 2082 * Job cannot be restarted. Mark the table as full and 2083 * place the job back on the list of stopped jobs. 2084 */ 2085 if (DEBUG(JOB)) { 2086 (void) fprintf(stdout, "table full\n"); 2087 (void) fflush(stdout); 2088 } 2089 (void) Lst_AtFront(stoppedJobs, (ClientData)job); 2090 jobFull = TRUE; 2091 if (DEBUG(JOB)) { 2092 (void) fprintf(stdout, "Job queue is full.\n"); 2093 (void) fflush(stdout); 2094 } 2095 } 1697 2096 } 1698 2097 } 2098 #endif 1699 2099 1700 2100 /*- 1701 2101 *----------------------------------------------------------------------- 1702 2102 * JobStart -- 1703 * 1704 * 2103 * Start a target-creation process going for the target described 2104 * by the graph node gn. 1705 2105 * 1706 2106 * Results: 1707 * 1708 * 1709 * 2107 * JOB_ERROR if there was an error in the commands, JOB_FINISHED 2108 * if there isn't actually anything left to do for the job and 2109 * JOB_RUNNING if the job has been started. 1710 2110 * 1711 2111 * Side Effects: 1712 * 1713 * 2112 * A new Job node is created and added to the list of running 2113 * jobs. PMake is forked and a child shell created. 1714 2114 *----------------------------------------------------------------------- 1715 2115 */ 1716 2116 static int 1717 2117 JobStart(gn, flags, previous) 1718 GNode *gn; 1719 int 1720 1721 Job 1722 2118 GNode *gn; /* target to create */ 2119 int flags; /* flags for the job to override normal ones. 2120 * e.g. JOB_SPECIAL or JOB_IGNDOTS */ 2121 Job *previous; /* The previous Job structure for this node, 2122 * if any. */ 1723 2123 { 1724 2124 register Job *job; /* new job descriptor */ 1725 char 1726 Boolean 1727 Boolean 1728 Boolean 1729 int tfd;/* File descriptor for temp file */2125 char *argv[4]; /* Argument vector to shell */ 2126 Boolean cmdsOK; /* true if the nodes commands were all right */ 2127 Boolean local; /* Set true if the job was run locally */ 2128 Boolean noExec; /* Set true if we decide not to run the job */ 2129 int tfd; /* File descriptor for temp file */ 1730 2130 1731 2131 if (previous != NULL) { 1732 1733 2132 previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE); 2133 job = previous; 1734 2134 } else { 1735 1736 1737 1738 1739 2135 job = (Job *) emalloc(sizeof(Job)); 2136 if (job == NULL) { 2137 Punt("JobStart out of memory"); 2138 } 2139 flags |= JOB_FIRST; 1740 2140 } 1741 2141 … … 1750 2150 job->flags = 0; 1751 2151 if (Targ_Ignore(gn)) { 1752 2152 job->flags |= JOB_IGNERR; 1753 2153 } 1754 2154 if (Targ_Silent(gn)) { 1755 2155 job->flags |= JOB_SILENT; 1756 2156 } 1757 2157 job->flags |= flags; … … 1762 2162 */ 1763 2163 if (!compatMake && job->flags & JOB_FIRST) { 1764 2164 cmdsOK = Job_CheckCommands(gn, Error); 1765 2165 } else { 1766 2166 cmdsOK = TRUE; 1767 2167 } 1768 2168 … … 1774 2174 */ 1775 2175 if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) { 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 LstNodeln = Lst_Next(gn->commands);1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 2176 /* 2177 * We're serious here, but if the commands were bogus, we're 2178 * also dead... 2179 */ 2180 if (!cmdsOK) { 2181 DieHorribly(); 2182 } 2183 2184 (void) strcpy(tfile, TMPPAT); 2185 if ((tfd = mkstemp(tfile)) == -1) 2186 Punt("Cannot create temp file: %s", strerror(errno)); 2187 job->cmdFILE = fdopen(tfd, "w+"); 2188 eunlink(tfile); 2189 if (job->cmdFILE == NULL) { 2190 close(tfd); 2191 Punt("Could not open %s", tfile); 2192 } 2193 (void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1); 2194 /* 2195 * Send the commands to the command file, flush all its buffers then 2196 * rewind and remove the thing. 2197 */ 2198 noExec = FALSE; 2199 2200 /* 2201 * used to be backwards; replace when start doing multiple commands 2202 * per shell. 2203 */ 2204 if (compatMake) { 2205 /* 2206 * Be compatible: If this is the first time for this node, 2207 * verify its commands are ok and open the commands list for 2208 * sequential access by later invocations of JobStart. 2209 * Once that is done, we take the next command off the list 2210 * and print it to the command file. If the command was an 2211 * ellipsis, note that there's nothing more to execute. 2212 */ 2213 if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){ 2214 cmdsOK = FALSE; 2215 } else { 2216 LstNode ln = Lst_Next(gn->commands); 2217 2218 if ((ln == NILLNODE) || 2219 JobPrintCommand((ClientData) Lst_Datum(ln), 2220 (ClientData) job)) 2221 { 2222 noExec = TRUE; 2223 Lst_Close(gn->commands); 2224 } 2225 if (noExec && !(job->flags & JOB_FIRST)) { 2226 /* 2227 * If we're not going to execute anything, the job 2228 * is done and we need to close down the various 2229 * file descriptors we've opened for output, then 2230 * call JobDoOutput to catch the final characters or 2231 * send the file to the screen... Note that the i/o streams 2232 * are only open if this isn't the first job. 2233 * Note also that this could not be done in 2234 * Job_CatchChildren b/c it wasn't clear if there were 2235 * more commands to execute or not... 2236 */ 2237 JobClose(job); 2238 } 2239 } 2240 } else { 2241 /* 2242 * We can do all the commands at once. hooray for sanity 2243 */ 2244 numCommands = 0; 2245 Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job); 2246 2247 /* 2248 * If we didn't print out any commands to the shell script, 2249 * there's not much point in executing the shell, is there? 2250 */ 2251 if (numCommands == 0) { 2252 noExec = TRUE; 2253 } 2254 } 1855 2255 } else if (noExecute) { 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 2256 /* 2257 * Not executing anything -- just print all the commands to stdout 2258 * in one fell swoop. This will still set up job->tailCmds correctly. 2259 */ 2260 if (lastNode != gn) { 2261 MESSAGE(stdout, gn); 2262 lastNode = gn; 2263 } 2264 job->cmdFILE = stdout; 2265 /* 2266 * Only print the commands if they're ok, but don't die if they're 2267 * not -- just let the user know they're bad and keep going. It 2268 * doesn't do any harm in this case and may do some good. 2269 */ 2270 if (cmdsOK) { 2271 Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job); 2272 } 2273 /* 2274 * Don't execute the shell, thank you. 2275 */ 2276 noExec = TRUE; 1877 2277 } else { 1878 1879 1880 1881 1882 1883 1884 1885 1886 2278 /* 2279 * Just touch the target and note that no shell should be executed. 2280 * Set cmdFILE to stdout to make life easier. Check the commands, too, 2281 * but don't die if they're no good -- it does no harm to keep working 2282 * up the graph. 2283 */ 2284 job->cmdFILE = stdout; 2285 Job_Touch(gn, job->flags&JOB_SILENT); 2286 noExec = TRUE; 1887 2287 } 1888 2288 … … 1891 2291 */ 1892 2292 if (noExec) { 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 2293 /* 2294 * Unlink and close the command file if we opened one 2295 */ 2296 if (job->cmdFILE != stdout) { 2297 if (job->cmdFILE != NULL) 2298 (void) fclose(job->cmdFILE); 2299 } else { 2300 (void) fflush(stdout); 2301 } 2302 2303 /* 2304 * We only want to work our way up the graph if we aren't here because 2305 * the commands for the job were no good. 2306 */ 2307 if (cmdsOK) { 2308 if (aborting == 0) { 2309 if (job->tailCmds != NILLNODE) { 2310 Lst_ForEachFrom(job->node->commands, job->tailCmds, 2311 JobSaveCommand, 2312 (ClientData)job->node); 2313 } 2314 job->node->made = MADE; 2315 Make_Update(job->node); 2316 } 2317 efree((Address)job); 2318 return(JOB_FINISHED); 2319 } else { 2320 efree((Address)job); 2321 return(JOB_ERROR); 2322 } 1923 2323 } else { 1924 2324 (void) fflush(job->cmdFILE); 1925 2325 } 1926 2326 … … 1937 2337 */ 1938 2338 if (!compatMake || (job->flags & JOB_FIRST)) { 1939 if (usePipes) { 1940 int fd[2]; 1941 if (pipe(fd) == -1) 1942 Punt("Cannot create pipe: %s", strerror(errno)); 1943 job->inPipe = fd[0]; 1944 job->outPipe = fd[1]; 1945 (void) fcntl(job->inPipe, F_SETFD, 1); 1946 (void) fcntl(job->outPipe, F_SETFD, 1); 1947 } else { 1948 (void) fprintf(stdout, "Remaking `%s'\n", gn->name); 1949 (void) fflush(stdout); 1950 (void) strcpy(job->outFile, TMPPAT); 1951 if ((job->outFd = mkstemp(job->outFile)) == -1) 1952 Punt("cannot create temp file: %s", strerror(errno)); 1953 (void) fcntl(job->outFd, F_SETFD, 1); 1954 } 2339 #ifdef USE_PIPES 2340 if (usePipes) { 2341 int fd[2]; 2342 if (pipe(fd) == -1) 2343 Punt("Cannot create pipe: %s", strerror(errno)); 2344 job->inPipe = fd[0]; 2345 job->outPipe = fd[1]; 2346 (void) fcntl(job->inPipe, F_SETFD, 1); 2347 (void) fcntl(job->outPipe, F_SETFD, 1); 2348 } 2349 else 2350 #endif /* USE_PIPES */ 2351 { 2352 (void) fprintf(stdout, "Remaking `%s'\n", gn->name); 2353 (void) fflush(stdout); 2354 (void) strcpy(job->outFile, TMPPAT); 2355 if ((job->outFd = mkstemp(job->outFile)) == -1) 2356 Punt("cannot create temp file: %s", strerror(errno)); 2357 (void) fcntl(job->outFd, F_SETFD, 1); 2358 } 1955 2359 } 1956 2360 … … 1958 2362 if (!(gn->type & OP_NOEXPORT) && !(runLocalFirst && nLocal < maxLocal)) { 1959 2363 #ifdef RMT_NO_EXEC 1960 2364 local = !Rmt_Export(shellPath, argv, job); 1961 2365 #else 1962 2366 local = !Rmt_Begin(shellPath, argv, job->node); 1963 2367 #endif /* RMT_NO_EXEC */ 1964 1965 1966 2368 if (!local) { 2369 job->flags |= JOB_REMOTE; 2370 } 1967 2371 } else 1968 2372 #endif 1969 2373 local = TRUE; 1970 2374 1971 2375 if (local && (((nLocal >= maxLocal) && 1972 2376 !(job->flags & JOB_SPECIAL) && 1973 2377 #ifdef REMOTE 1974 2378 (!(gn->type & OP_NOEXPORT) || (maxLocal != 0)) 1975 2379 #else 1976 1977 #endif 1978 2380 (maxLocal != 0) 2381 #endif 2382 ))) 1979 2383 { 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 2384 /* 2385 * The job can only be run locally, but we've hit the limit of 2386 * local concurrency, so put the job on hold until some other job 2387 * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END) 2388 * may be run locally even when the local limit has been reached 2389 * (e.g. when maxLocal == 0), though they will be exported if at 2390 * all possible. In addition, any target marked with .NOEXPORT will 2391 * be run locally if maxLocal is 0. 2392 */ 2393 jobFull = TRUE; 2394 2395 if (DEBUG(JOB)) { 2396 (void) fprintf(stdout, "Can only run job locally.\n"); 2397 (void) fflush(stdout); 2398 } 2399 job->flags |= JOB_RESTART; 2400 (void) Lst_AtEnd(stoppedJobs, (ClientData)job); 1997 2401 } else { 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2402 if ((nLocal >= maxLocal) && local) { 2403 /* 2404 * If we're running this job locally as a special case (see above), 2405 * at least say the table is full. 2406 */ 2407 jobFull = TRUE; 2408 if (DEBUG(JOB)) { 2409 (void) fprintf(stdout, "Local job queue is full.\n"); 2410 (void) fflush(stdout); 2411 } 2412 } 2413 JobExec(job, argv); 2010 2414 } 2011 2415 return(JOB_RUNNING); … … 2022 2426 #ifndef KMK /* @Todo */ 2023 2427 if (commandShell->noPrint) { 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2428 ecp = Str_FindSubstring(cp, commandShell->noPrint); 2429 while (ecp != NULL) { 2430 if (cp != ecp) { 2431 *ecp = '\0'; 2432 if (msg && job->node != lastNode) { 2433 MESSAGE(stdout, job->node); 2434 lastNode = job->node; 2435 } 2436 /* 2437 * The only way there wouldn't be a newline after 2438 * this line is if it were the last in the buffer. 2439 * however, since the non-printable comes after it, 2440 * there must be a newline, so we don't print one. 2441 */ 2442 (void) fprintf(stdout, "%s", cp); 2443 (void) fflush(stdout); 2444 } 2445 cp = ecp + commandShell->noPLen; 2446 if (cp != endp) { 2447 /* 2448 * Still more to print, look again after skipping 2449 * the whitespace following the non-printable 2450 * command.... 2451 */ 2452 cp++; 2453 while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 2454 cp++; 2455 } 2456 ecp = Str_FindSubstring(cp, commandShell->noPrint); 2457 } else { 2458 return cp; 2459 } 2460 } 2057 2461 } 2058 2462 #endif /*!KMK*/ … … 2063 2467 *----------------------------------------------------------------------- 2064 2468 * JobDoOutput -- 2065 * 2066 * 2067 * 2068 * 2069 * 2070 * 2071 * 2072 * 2073 * 2074 * 2075 * 2076 * 2077 * 2078 * 2079 * 2080 * 2469 * This function is called at different times depending on 2470 * whether the user has specified that output is to be collected 2471 * via pipes or temporary files. In the former case, we are called 2472 * whenever there is something to read on the pipe. We collect more 2473 * output from the given job and store it in the job's outBuf. If 2474 * this makes up a line, we print it tagged by the job's identifier, 2475 * as necessary. 2476 * If output has been collected in a temporary file, we open the 2477 * file and read it line by line, transfering it to our own 2478 * output channel until the file is empty. At which point we 2479 * remove the temporary file. 2480 * In both cases, however, we keep our figurative eye out for the 2481 * 'noPrint' line for the shell from which the output came. If 2482 * we recognize a line, we don't print it. If the command is not 2483 * alone on the line (the character after it is not \0 or \n), we 2484 * do print whatever follows it. 2081 2485 * 2082 2486 * Results: 2083 * 2487 * None 2084 2488 * 2085 2489 * Side Effects: 2086 * 2490 * curPos may be shifted as may the contents of outBuf. 2087 2491 *----------------------------------------------------------------------- 2088 2492 */ 2089 2493 STATIC void 2090 2494 JobDoOutput(job, finish) 2091 register Job *job; 2092 Boolean finish;/* TRUE if this is the last time we'll be2093 2495 register Job *job; /* the job whose output needs printing */ 2496 Boolean finish; /* TRUE if this is the last time we'll be 2497 * called for this job */ 2094 2498 { 2095 2499 Boolean gotNL = FALSE; /* true if got a newline */ 2096 Boolean fbuf; 2097 register int nr; 2098 register int i; 2099 register int max; 2100 int nRead;/* (Temporary) number of bytes read */2101 2102 FILE *oFILE;/* Stream pointer to shell's output file */2500 Boolean fbuf; /* true if our buffer filled up */ 2501 register int nr; /* number of bytes read */ 2502 register int i; /* auxiliary index into outBuf */ 2503 register int max; /* limit for i (end of current data) */ 2504 int nRead; /* (Temporary) number of bytes read */ 2505 2506 FILE *oFILE; /* Stream pointer to shell's output file */ 2103 2507 char inLine[132]; 2104 2508 2105 2509 2510 #ifdef USE_PIPES 2106 2511 if (usePipes) { 2107 2108 2109 2512 /* 2513 * Read as many bytes as will fit in the buffer. 2514 */ 2110 2515 end_loop: 2111 gotNL = FALSE; 2112 fbuf = FALSE; 2113 2114 nRead = read(job->inPipe, &job->outBuf[job->curPos], 2115 JOB_BUFSIZE - job->curPos); 2116 if (nRead < 0) { 2117 if (DEBUG(JOB)) { 2118 perror("JobDoOutput(piperead)"); 2119 } 2120 nr = 0; 2121 } else { 2122 nr = nRead; 2123 } 2124 2125 /* 2126 * If we hit the end-of-file (the job is dead), we must flush its 2127 * remaining output, so pretend we read a newline if there's any 2128 * output remaining in the buffer. 2129 * Also clear the 'finish' flag so we stop looping. 2130 */ 2131 if ((nr == 0) && (job->curPos != 0)) { 2132 job->outBuf[job->curPos] = '\n'; 2133 nr = 1; 2134 finish = FALSE; 2135 } else if (nr == 0) { 2136 finish = FALSE; 2137 } 2138 2139 /* 2140 * Look for the last newline in the bytes we just got. If there is 2141 * one, break out of the loop with 'i' as its index and gotNL set 2142 * TRUE. 2143 */ 2144 max = job->curPos + nr; 2145 for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 2146 if (job->outBuf[i] == '\n') { 2147 gotNL = TRUE; 2148 break; 2149 } else if (job->outBuf[i] == '\0') { 2150 /* 2151 * Why? 2152 */ 2153 job->outBuf[i] = ' '; 2154 } 2155 } 2156 2157 if (!gotNL) { 2158 job->curPos += nr; 2159 if (job->curPos == JOB_BUFSIZE) { 2160 /* 2161 * If we've run out of buffer space, we have no choice 2162 * but to print the stuff. sigh. 2163 */ 2164 fbuf = TRUE; 2165 i = job->curPos; 2166 } 2167 } 2168 if (gotNL || fbuf) { 2169 /* 2170 * Need to send the output to the screen. Null terminate it 2171 * first, overwriting the newline character if there was one. 2172 * So long as the line isn't one we should filter (according 2173 * to the shell description), we print the line, preceeded 2174 * by a target banner if this target isn't the same as the 2175 * one for which we last printed something. 2176 * The rest of the data in the buffer are then shifted down 2177 * to the start of the buffer and curPos is set accordingly. 2178 */ 2179 job->outBuf[i] = '\0'; 2180 if (i >= job->curPos) { 2181 char *cp; 2182 2183 cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE); 2184 2185 /* 2186 * There's still more in that thar buffer. This time, though, 2187 * we know there's no newline at the end, so we add one of 2188 * our own efree will. 2189 */ 2190 if (*cp != '\0') { 2191 if (job->node != lastNode) { 2192 MESSAGE(stdout, job->node); 2193 lastNode = job->node; 2194 } 2195 (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); 2196 (void) fflush(stdout); 2197 } 2198 } 2199 if (i < max - 1) { 2200 /* shift the remaining characters down */ 2201 (void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); 2202 job->curPos = max - (i + 1); 2203 2204 } else { 2205 /* 2206 * We have written everything out, so we just start over 2207 * from the start of the buffer. No copying. No nothing. 2208 */ 2209 job->curPos = 0; 2210 } 2211 } 2212 if (finish) { 2213 /* 2214 * If the finish flag is true, we must loop until we hit 2215 * end-of-file on the pipe. This is guaranteed to happen 2216 * eventually since the other end of the pipe is now closed 2217 * (we closed it explicitly and the child has exited). When 2218 * we do get an EOF, finish will be set FALSE and we'll fall 2219 * through and out. 2220 */ 2221 goto end_loop; 2222 } 2223 } else { 2224 /* 2225 * We've been called to retrieve the output of the job from the 2226 * temporary file where it's been squirreled away. This consists of 2227 * opening the file, reading the output line by line, being sure not 2228 * to print the noPrint line for the shell we used, then close and 2229 * remove the temporary file. Very simple. 2230 * 2231 * Change to read in blocks and do FindSubString type things as for 2232 * pipes? That would allow for "@echo -n..." 2233 */ 2234 oFILE = fopen(job->outFile, "r"); 2235 if (oFILE != NULL) { 2236 (void) fprintf(stdout, "Results of making %s:\n", job->node->name); 2237 (void) fflush(stdout); 2238 while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 2239 register char *cp, *endp, *oendp; 2240 2241 cp = inLine; 2242 oendp = endp = inLine + strlen(inLine); 2243 if (endp[-1] == '\n') { 2244 *--endp = '\0'; 2245 } 2246 cp = JobOutput(job, inLine, endp, FALSE); 2247 2248 /* 2249 * There's still more in that thar buffer. This time, though, 2250 * we know there's no newline at the end, so we add one of 2251 * our own efree will. 2252 */ 2253 (void) fprintf(stdout, "%s", cp); 2254 (void) fflush(stdout); 2255 if (endp != oendp) { 2256 (void) fprintf(stdout, "\n"); 2257 (void) fflush(stdout); 2258 } 2259 } 2260 (void) fclose(oFILE); 2261 (void) eunlink(job->outFile); 2262 } 2516 gotNL = FALSE; 2517 fbuf = FALSE; 2518 2519 nRead = read(job->inPipe, &job->outBuf[job->curPos], 2520 JOB_BUFSIZE - job->curPos); 2521 if (nRead < 0) { 2522 if (DEBUG(JOB)) { 2523 perror("JobDoOutput(piperead)"); 2524 } 2525 nr = 0; 2526 } else { 2527 nr = nRead; 2528 } 2529 2530 /* 2531 * If we hit the end-of-file (the job is dead), we must flush its 2532 * remaining output, so pretend we read a newline if there's any 2533 * output remaining in the buffer. 2534 * Also clear the 'finish' flag so we stop looping. 2535 */ 2536 if ((nr == 0) && (job->curPos != 0)) { 2537 job->outBuf[job->curPos] = '\n'; 2538 nr = 1; 2539 finish = FALSE; 2540 } else if (nr == 0) { 2541 finish = FALSE; 2542 } 2543 2544 /* 2545 * Look for the last newline in the bytes we just got. If there is 2546 * one, break out of the loop with 'i' as its index and gotNL set 2547 * TRUE. 2548 */ 2549 max = job->curPos + nr; 2550 for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 2551 if (job->outBuf[i] == '\n') { 2552 gotNL = TRUE; 2553 break; 2554 } else if (job->outBuf[i] == '\0') { 2555 /* 2556 * Why? 2557 */ 2558 job->outBuf[i] = ' '; 2559 } 2560 } 2561 2562 if (!gotNL) { 2563 job->curPos += nr; 2564 if (job->curPos == JOB_BUFSIZE) { 2565 /* 2566 * If we've run out of buffer space, we have no choice 2567 * but to print the stuff. sigh. 2568 */ 2569 fbuf = TRUE; 2570 i = job->curPos; 2571 } 2572 } 2573 if (gotNL || fbuf) { 2574 /* 2575 * Need to send the output to the screen. Null terminate it 2576 * first, overwriting the newline character if there was one. 2577 * So long as the line isn't one we should filter (according 2578 * to the shell description), we print the line, preceeded 2579 * by a target banner if this target isn't the same as the 2580 * one for which we last printed something. 2581 * The rest of the data in the buffer are then shifted down 2582 * to the start of the buffer and curPos is set accordingly. 2583 */ 2584 job->outBuf[i] = '\0'; 2585 if (i >= job->curPos) { 2586 char *cp; 2587 2588 cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE); 2589 2590 /* 2591 * There's still more in that thar buffer. This time, though, 2592 * we know there's no newline at the end, so we add one of 2593 * our own efree will. 2594 */ 2595 if (*cp != '\0') { 2596 if (job->node != lastNode) { 2597 MESSAGE(stdout, job->node); 2598 lastNode = job->node; 2599 } 2600 (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); 2601 (void) fflush(stdout); 2602 } 2603 } 2604 if (i < max - 1) { 2605 /* shift the remaining characters down */ 2606 (void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); 2607 job->curPos = max - (i + 1); 2608 2609 } else { 2610 /* 2611 * We have written everything out, so we just start over 2612 * from the start of the buffer. No copying. No nothing. 2613 */ 2614 job->curPos = 0; 2615 } 2616 } 2617 if (finish) { 2618 /* 2619 * If the finish flag is true, we must loop until we hit 2620 * end-of-file on the pipe. This is guaranteed to happen 2621 * eventually since the other end of the pipe is now closed 2622 * (we closed it explicitly and the child has exited). When 2623 * we do get an EOF, finish will be set FALSE and we'll fall 2624 * through and out. 2625 */ 2626 goto end_loop; 2627 } 2628 } 2629 else 2630 #endif /* USE_PIPES */ 2631 { 2632 /* 2633 * We've been called to retrieve the output of the job from the 2634 * temporary file where it's been squirreled away. This consists of 2635 * opening the file, reading the output line by line, being sure not 2636 * to print the noPrint line for the shell we used, then close and 2637 * remove the temporary file. Very simple. 2638 * 2639 * Change to read in blocks and do FindSubString type things as for 2640 * pipes? That would allow for "@echo -n..." 2641 */ 2642 oFILE = fopen(job->outFile, "r"); 2643 if (oFILE != NULL) { 2644 (void) fprintf(stdout, "Results of making %s:\n", job->node->name); 2645 (void) fflush(stdout); 2646 while (fgets(inLine, sizeof(inLine), oFILE) != NULL) { 2647 register char *cp, *endp, *oendp; 2648 2649 cp = inLine; 2650 oendp = endp = inLine + strlen(inLine); 2651 if (endp[-1] == '\n') { 2652 *--endp = '\0'; 2653 } 2654 cp = JobOutput(job, inLine, endp, FALSE); 2655 2656 /* 2657 * There's still more in that thar buffer. This time, though, 2658 * we know there's no newline at the end, so we add one of 2659 * our own efree will. 2660 */ 2661 (void) fprintf(stdout, "%s", cp); 2662 (void) fflush(stdout); 2663 if (endp != oendp) { 2664 (void) fprintf(stdout, "\n"); 2665 (void) fflush(stdout); 2666 } 2667 } 2668 (void) fclose(oFILE); 2669 (void) eunlink(job->outFile); 2670 } 2263 2671 } 2264 2672 } … … 2267 2675 *----------------------------------------------------------------------- 2268 2676 * Job_CatchChildren -- 2269 * 2677 * Handle the exit of a child. Called from Make_Make. 2270 2678 * 2271 2679 * Results: 2272 * 2680 * none. 2273 2681 * 2274 2682 * Side Effects: 2275 * 2683 * The job descriptor is removed from the list of children. 2276 2684 * 2277 2685 * Notes: 2278 * 2279 * 2280 * 2281 * 2686 * We do waits, blocking or not, according to the wisdom of our 2687 * caller, until there are no more children to report. For each 2688 * job, call JobFinish to finish things off. This will take care of 2689 * putting jobs on the stoppedJobs queue. 2282 2690 * 2283 2691 *----------------------------------------------------------------------- … … 2285 2693 void 2286 2694 Job_CatchChildren(block) 2287 Boolean block;/* TRUE if should block on the wait. */2695 Boolean block; /* TRUE if should block on the wait. */ 2288 2696 { 2289 int pid; /* pid of dead child */ 2290 register Job *job; /* job descriptor for dead child */ 2291 LstNode jnode; /* list element for finding job */ 2292 int status; /* Exit/termination status */ 2697 #ifdef USE_KLIB 2698 int pid; /* pid of dead child */ 2699 register Job *job; /* job descriptor for dead child */ 2700 LstNode jnode; /* list element for finding job */ 2701 KPROCRES status; /* Exit/termination status */ 2293 2702 2294 2703 /* … … 2296 2705 */ 2297 2706 if (nLocal == 0) { 2298 return; 2707 return; 2708 } 2709 2710 while (!kProcWait(KPID_NULL, KPROCWAIT_FLAGS_NOWAIT, &status, &pid)) 2711 { 2712 if (DEBUG(JOB)) { 2713 (void) fprintf(stdout, "Process %d exited or stopped.\n", pid); 2714 (void) fflush(stdout); 2715 } 2716 2717 jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid); 2718 if (jnode == NILLNODE) { 2719 Error("Child (%d) not in table?", pid); 2720 continue; 2721 } else { 2722 job = (Job *) Lst_Datum(jnode); 2723 (void) Lst_Remove(jobs, jnode); 2724 nJobs -= 1; 2725 if (jobFull && DEBUG(JOB)) { 2726 (void) fprintf(stdout, "Job queue is no longer full.\n"); 2727 (void) fflush(stdout); 2728 } 2729 jobFull = FALSE; 2730 nLocal -= 1; 2731 } 2732 JobFinish(job, &status); 2733 } 2734 2735 #else /* Don't Use kLib */ 2736 int pid; /* pid of dead child */ 2737 register Job *job; /* job descriptor for dead child */ 2738 LstNode jnode; /* list element for finding job */ 2739 int status; /* Exit/termination status */ 2740 2741 /* 2742 * Don't even bother if we know there's no one around. 2743 */ 2744 if (nLocal == 0) { 2745 return; 2299 2746 } 2300 2747 2301 2748 while ((pid = waitpid((pid_t) -1, &status, 2302 2749 (block?0:WNOHANG)|WUNTRACED)) > 0) 2303 2750 { 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2751 if (DEBUG(JOB)) { 2752 (void) fprintf(stdout, "Process %d exited or stopped.\n", pid); 2753 (void) fflush(stdout); 2754 } 2755 2756 2757 jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid); 2758 2759 if (jnode == NILLNODE) { 2760 if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { 2761 jnode = Lst_Find(stoppedJobs, (ClientData) &pid, JobCmpPid); 2762 if (jnode == NILLNODE) { 2763 Error("Resumed child (%d) not in table", pid); 2764 continue; 2765 } 2766 job = (Job *)Lst_Datum(jnode); 2767 (void) Lst_Remove(stoppedJobs, jnode); 2768 } else { 2769 Error("Child (%d) not in table?", pid); 2770 continue; 2771 } 2772 } else { 2773 job = (Job *) Lst_Datum(jnode); 2774 (void) Lst_Remove(jobs, jnode); 2775 nJobs -= 1; 2776 if (jobFull && DEBUG(JOB)) { 2777 (void) fprintf(stdout, "Job queue is no longer full.\n"); 2778 (void) fflush(stdout); 2779 } 2780 jobFull = FALSE; 2334 2781 #ifdef REMOTE 2335 2336 2337 2338 2339 2340 2341 2342 2782 if (!(job->flags & JOB_REMOTE)) { 2783 if (DEBUG(JOB)) { 2784 (void) fprintf(stdout, 2785 "Job queue has one fewer local process.\n"); 2786 (void) fflush(stdout); 2787 } 2788 nLocal -= 1; 2789 } 2343 2790 #else 2344 nLocal -= 1; 2345 #endif 2346 } 2347 2348 JobFinish(job, &status); 2349 } 2791 nLocal -= 1; 2792 #endif 2793 } 2794 2795 JobFinish(job, &status); 2796 } 2797 #endif /* USE_KLIB */ 2350 2798 } 2351 2799 … … 2353 2801 *----------------------------------------------------------------------- 2354 2802 * Job_CatchOutput -- 2355 * 2356 * 2357 * 2358 * 2359 * 2803 * Catch the output from our children, if we're using 2804 * pipes do so. Otherwise just block time until we get a 2805 * signal (most likely a SIGCHLD) since there's no point in 2806 * just spinning when there's nothing to do and the reaping 2807 * of a child can wait for a while. 2360 2808 * 2361 2809 * Results: 2362 * 2810 * None 2363 2811 * 2364 2812 * Side Effects: 2365 * 2813 * Output is read from pipes if we're piping. 2366 2814 * ----------------------------------------------------------------------- 2367 2815 */ … … 2369 2817 Job_CatchOutput() 2370 2818 { 2371 int 2372 struct timeval 2373 fd_set 2374 register LstNode 2375 register Job 2819 int nfds; 2820 struct timeval timeout; 2821 fd_set readfds; 2822 register LstNode ln; 2823 register Job *job; 2376 2824 #ifdef RMT_WILL_WATCH 2377 int pnJobs;/* Previous nJobs */2825 int pnJobs; /* Previous nJobs */ 2378 2826 #endif 2379 2827 … … 2399 2847 */ 2400 2848 while (nJobs != 0 && pnJobs == nJobs) { 2401 2849 Rmt_Wait(); 2402 2850 } 2403 2851 #else 2852 #ifdef USE_PIPES 2404 2853 if (usePipes) { 2405 readfds = outputs; 2406 timeout.tv_sec = SEL_SEC; 2407 timeout.tv_usec = SEL_USEC; 2408 2409 if ((nfds = select(FD_SETSIZE, &readfds, (fd_set *) 0, 2410 (fd_set *) 0, &timeout)) <= 0) 2411 return; 2412 else { 2413 if (Lst_Open(jobs) == FAILURE) { 2414 Punt("Cannot open job table"); 2415 } 2416 while (nfds && (ln = Lst_Next(jobs)) != NILLNODE) { 2417 job = (Job *) Lst_Datum(ln); 2418 if (FD_ISSET(job->inPipe, &readfds)) { 2419 JobDoOutput(job, FALSE); 2420 nfds -= 1; 2421 } 2422 } 2423 Lst_Close(jobs); 2424 } 2425 } 2854 readfds = outputs; 2855 timeout.tv_sec = SEL_SEC; 2856 timeout.tv_usec = SEL_USEC; 2857 2858 if ((nfds = select(FD_SETSIZE, &readfds, (fd_set *) 0, 2859 (fd_set *) 0, &timeout)) <= 0) 2860 return; 2861 else { 2862 if (Lst_Open(jobs) == FAILURE) { 2863 Punt("Cannot open job table"); 2864 } 2865 while (nfds && (ln = Lst_Next(jobs)) != NILLNODE) { 2866 job = (Job *) Lst_Datum(ln); 2867 if (FD_ISSET(job->inPipe, &readfds)) { 2868 JobDoOutput(job, FALSE); 2869 nfds -= 1; 2870 } 2871 } 2872 Lst_Close(jobs); 2873 } 2874 } 2875 #endif /* USE_PIPES */ 2426 2876 #endif /* RMT_WILL_WATCH */ 2427 2877 } … … 2430 2880 *----------------------------------------------------------------------- 2431 2881 * Job_Make -- 2432 * 2433 * 2882 * Start the creation of a target. Basically a front-end for 2883 * JobStart used by the Make module. 2434 2884 * 2435 2885 * Results: 2436 * 2886 * None. 2437 2887 * 2438 2888 * Side Effects: 2439 * 2889 * Another job is started. 2440 2890 * 2441 2891 *----------------------------------------------------------------------- … … 2451 2901 *----------------------------------------------------------------------- 2452 2902 * Job_Init -- 2453 * 2903 * Initialize the process module 2454 2904 * 2455 2905 * Results: 2456 * 2906 * none 2457 2907 * 2458 2908 * Side Effects: 2459 * 2909 * lists and counters are initialized 2460 2910 *----------------------------------------------------------------------- 2461 2911 */ … … 2463 2913 Job_Init(maxproc, maxlocal) 2464 2914 int maxproc; /* the greatest number of jobs which may be 2465 2466 int 2467 2915 * running at one time */ 2916 int maxlocal; /* the greatest number of local jobs which may 2917 * be running at once. */ 2468 2918 { 2469 2919 GNode *begin; /* node for commands to do at the very start */ 2470 2920 2471 jobs = Lst_Init(FALSE); 2921 jobs = Lst_Init(FALSE); 2922 #ifdef SIGCONT 2472 2923 stoppedJobs = Lst_Init(FALSE); 2473 maxJobs = maxproc; 2474 maxLocal = maxlocal; 2475 nJobs = 0; 2476 nLocal = 0; 2477 jobFull = FALSE; 2478 2479 aborting = 0; 2480 errors = 0; 2481 2482 lastNode = NILGNODE; 2924 #endif 2925 maxJobs = maxproc; 2926 maxLocal = maxlocal; 2927 nJobs = 0; 2928 nLocal = 0; 2929 jobFull = FALSE; 2930 2931 aborting = 0; 2932 errors = 0; 2933 2934 lastNode = NILGNODE; 2483 2935 2484 2936 if (maxJobs == 1 || beVerbose == 0 2485 2937 #ifdef REMOTE 2486 2487 #endif 2488 2489 2490 2491 2492 2493 2938 || noMessages 2939 #endif 2940 ) { 2941 /* 2942 * If only one job can run at a time, there's no need for a banner, 2943 * no is there? 2944 */ 2945 targFmt = ""; 2494 2946 } else { 2495 2947 targFmt = TARG_FMT; 2496 2948 } 2497 2949 2498 2950 #ifndef KMK 2499 2951 if (shellPath == NULL) { 2500 2501 2502 2503 2504 2505 2506 2507 2508 2952 /* 2953 * The user didn't specify a shell to use, so we are using the 2954 * default one... Both the absolute path and the last component 2955 * must be set. The last component is taken from the 'name' field 2956 * of the default shell description pointed-to by commandShell. 2957 * All default shells are located in _PATH_DEFSHELLDIR. 2958 */ 2959 shellName = commandShell->name; 2960 shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH); 2509 2961 } 2510 2962 2511 2963 if (commandShell->exit == NULL) { 2512 2964 commandShell->exit = ""; 2513 2965 } 2514 2966 if (commandShell->echo == NULL) { 2515 2967 commandShell->echo = ""; 2516 2968 } 2517 2969 #endif … … 2522 2974 */ 2523 2975 if (signal(SIGINT, SIG_IGN) != SIG_IGN) { 2524 (void) signal(SIGINT, JobPassSig); 2525 } 2976 (void) signal(SIGINT, JobPassSig); 2977 } 2978 #ifdef SIGHUP /* not all systems supports this signal */ 2526 2979 if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { 2527 (void) signal(SIGHUP, JobPassSig); 2528 } 2980 (void) signal(SIGHUP, JobPassSig); 2981 } 2982 #endif 2983 #ifdef SIGQUIT /* not all systems supports this signal */ 2529 2984 if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) { 2530 (void) signal(SIGQUIT, JobPassSig); 2531 } 2985 (void) signal(SIGQUIT, JobPassSig); 2986 } 2987 #endif 2532 2988 if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { 2533 2989 (void) signal(SIGTERM, JobPassSig); 2534 2990 } 2535 2991 /* … … 2541 2997 #if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP) 2542 2998 if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) { 2543 2999 (void) signal(SIGTSTP, JobPassSig); 2544 3000 } 2545 3001 if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) { 2546 3002 (void) signal(SIGTTOU, JobPassSig); 2547 3003 } 2548 3004 if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) { 2549 3005 (void) signal(SIGTTIN, JobPassSig); 2550 3006 } 2551 3007 if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) { 2552 3008 (void) signal(SIGWINCH, JobPassSig); 2553 3009 } 2554 3010 #endif … … 2557 3013 2558 3014 if (begin != NILGNODE) { 2559 2560 2561 3015 JobStart(begin, JOB_SPECIAL, (Job *)0); 3016 while (nJobs) { 3017 Job_CatchOutput(); 2562 3018 #ifndef RMT_WILL_WATCH 2563 3019 Job_CatchChildren(!usePipes); 2564 3020 #endif /* RMT_WILL_WATCH */ 2565 3021 } 2566 3022 } 2567 3023 postCommands = Targ_FindNode(".END", TARG_CREATE); … … 2571 3027 *----------------------------------------------------------------------- 2572 3028 * Job_Full -- 2573 * 2574 * 2575 * 2576 * 3029 * See if the job table is full. It is considered full if it is OR 3030 * if we are in the process of aborting OR if we have 3031 * reached/exceeded our local quota. This prevents any more jobs 3032 * from starting up. 2577 3033 * 2578 3034 * Results: 2579 * 3035 * TRUE if the job table is full, FALSE otherwise 2580 3036 * Side Effects: 2581 * 3037 * None. 2582 3038 *----------------------------------------------------------------------- 2583 3039 */ … … 2591 3047 *----------------------------------------------------------------------- 2592 3048 * Job_Empty -- 2593 * 2594 * 2595 * 2596 * 3049 * See if the job table is empty. Because the local concurrency may 3050 * be set to 0, it is possible for the job table to become empty, 3051 * while the list of stoppedJobs remains non-empty. In such a case, 3052 * we want to restart as many jobs as we can. 2597 3053 * 2598 3054 * Results: 2599 * 3055 * TRUE if it is. FALSE if it ain't. 2600 3056 * 2601 3057 * Side Effects: 2602 * 3058 * None. 2603 3059 * 2604 3060 * ----------------------------------------------------------------------- … … 2608 3064 { 2609 3065 if (nJobs == 0) { 2610 if (!Lst_IsEmpty(stoppedJobs) && !aborting) { 2611 /* 2612 * The job table is obviously not full if it has no jobs in 2613 * it...Try and restart the stopped jobs. 2614 */ 2615 jobFull = FALSE; 2616 JobRestartJobs(); 2617 return(FALSE); 2618 } else { 2619 return(TRUE); 2620 } 3066 #ifdef SIGCONT 3067 if (!Lst_IsEmpty(stoppedJobs) && !aborting) { 3068 /* 3069 * The job table is obviously not full if it has no jobs in 3070 * it...Try and restart the stopped jobs. 3071 */ 3072 jobFull = FALSE; 3073 JobRestartJobs(); 3074 return(FALSE); 3075 } 3076 #else 3077 return(TRUE); 3078 #endif 2621 3079 } else { 2622 3080 return(FALSE); 2623 3081 } 2624 3082 } … … 2628 3086 *----------------------------------------------------------------------- 2629 3087 * JobMatchShell -- 2630 * 3088 * Find a matching shell in 'shells' given its final component. 2631 3089 * 2632 3090 * Results: 2633 * 3091 * A pointer to the Shell structure. 2634 3092 * 2635 3093 * Side Effects: 2636 * 3094 * None. 2637 3095 * 2638 3096 *----------------------------------------------------------------------- … … 2640 3098 static Shell * 2641 3099 JobMatchShell(name) 2642 char 3100 char *name; /* Final component of shell path */ 2643 3101 { 2644 register Shell *sh; 2645 Shell 3102 register Shell *sh; /* Pointer into shells table */ 3103 Shell *match; /* Longest-matching shell */ 2646 3104 register char *cp1, 2647 2648 char 3105 *cp2; 3106 char *eoname; 2649 3107 2650 3108 eoname = name + strlen(name); … … 2653 3111 2654 3112 for (sh = shells; sh->name != NULL; sh++) { 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 3113 for (cp1 = eoname - strlen(sh->name), cp2 = sh->name; 3114 *cp1 != '\0' && *cp1 == *cp2; 3115 cp1++, cp2++) { 3116 continue; 3117 } 3118 if (*cp1 != *cp2) { 3119 continue; 3120 } else if (match == NULL || strlen(match->name) < strlen(sh->name)) { 3121 match = sh; 3122 } 2665 3123 } 2666 3124 return(match == NULL ? sh : match); … … 2672 3130 *----------------------------------------------------------------------- 2673 3131 * Job_ParseShell -- 2674 * 2675 * 3132 * Parse a shell specification and set up commandShell, shellPath 3133 * and shellName appropriately. 2676 3134 * 2677 3135 * Results: 2678 * 3136 * FAILURE if the specification was incorrect. 2679 3137 * 2680 3138 * Side Effects: 2681 * 2682 * 2683 * 2684 * 3139 * commandShell points to a Shell structure (either predefined or 3140 * created from the shell spec), shellPath is the full path of the 3141 * shell described by commandShell, while shellName is just the 3142 * final component of shellPath. 2685 3143 * 2686 3144 * Notes: 2687 * 2688 * 2689 * 2690 * 2691 * 2692 * 2693 * 2694 * nameName of shell.2695 * pathLocation of shell. Overrides "name" if given2696 * quietCommand to turn off echoing.2697 * echoCommand to turn echoing on2698 * filterResult of turning off echoing that shouldn't be2699 * 2700 * echoFlagFlag to turn echoing on at the start2701 * errFlagFlag to turn error checking on at the start2702 * hasErrCtlTrue if shell has error checking control2703 * checkCommand to turn on error checking if hasErrCtl2704 * 2705 * 2706 * 2707 * ignoreCommand to turn off error checking if hasErrCtl2708 * 2709 * 2710 * 3145 * A shell specification consists of a .SHELL target, with dependency 3146 * operator, followed by a series of blank-separated words. Double 3147 * quotes can be used to use blanks in words. A backslash escapes 3148 * anything (most notably a double-quote and a space) and 3149 * provides the functionality it does in C. Each word consists of 3150 * keyword and value separated by an equal sign. There should be no 3151 * unnecessary spaces in the word. The keywords are as follows: 3152 * name Name of shell. 3153 * path Location of shell. Overrides "name" if given 3154 * quiet Command to turn off echoing. 3155 * echo Command to turn echoing on 3156 * filter Result of turning off echoing that shouldn't be 3157 * printed. 3158 * echoFlag Flag to turn echoing on at the start 3159 * errFlag Flag to turn error checking on at the start 3160 * hasErrCtl True if shell has error checking control 3161 * check Command to turn on error checking if hasErrCtl 3162 * is TRUE or template of command to echo a command 3163 * for which error checking is off if hasErrCtl is 3164 * FALSE. 3165 * ignore Command to turn off error checking if hasErrCtl 3166 * is TRUE or template of command to execute a 3167 * command so as to ignore any errors it returns if 3168 * hasErrCtl is FALSE. 2711 3169 * 2712 3170 *----------------------------------------------------------------------- … … 2714 3172 ReturnStatus 2715 3173 Job_ParseShell(line) 2716 char 3174 char *line; /* The shell spec */ 2717 3175 { 2718 char 2719 int 3176 char **words; 3177 int wordCount; 2720 3178 register char **argv; 2721 3179 register int argc; 2722 char 2723 Shell 2724 Boolean 3180 char *path; 3181 Shell newShell; 3182 Boolean fullSpec = FALSE; 2725 3183 2726 3184 while (isspace(*line)) { 2727 3185 line++; 2728 3186 } 2729 3187 words = brk_string(line, &wordCount, TRUE); … … 2735 3193 */ 2736 3194 for (path = NULL, argc = wordCount - 1, argv = words + 1; 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 3195 argc != 0; 3196 argc--, argv++) { 3197 if (strncmp(*argv, "path=", 5) == 0) { 3198 path = &argv[0][5]; 3199 } else if (strncmp(*argv, "name=", 5) == 0) { 3200 newShell.name = &argv[0][5]; 3201 } else { 3202 if (strncmp(*argv, "quiet=", 6) == 0) { 3203 newShell.echoOff = &argv[0][6]; 3204 } else if (strncmp(*argv, "echo=", 5) == 0) { 3205 newShell.echoOn = &argv[0][5]; 3206 } else if (strncmp(*argv, "filter=", 7) == 0) { 3207 newShell.noPrint = &argv[0][7]; 3208 newShell.noPLen = strlen(newShell.noPrint); 3209 } else if (strncmp(*argv, "echoFlag=", 9) == 0) { 3210 newShell.echo = &argv[0][9]; 3211 } else if (strncmp(*argv, "errFlag=", 8) == 0) { 3212 newShell.exit = &argv[0][8]; 3213 } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) { 3214 char c = argv[0][10]; 3215 newShell.hasErrCtl = !((c != 'Y') && (c != 'y') && 3216 (c != 'T') && (c != 't')); 3217 } else if (strncmp(*argv, "check=", 6) == 0) { 3218 newShell.errCheck = &argv[0][6]; 3219 } else if (strncmp(*argv, "ignore=", 7) == 0) { 3220 newShell.ignErr = &argv[0][7]; 3221 } else { 3222 Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", 3223 *argv); 3224 return(FAILURE); 3225 } 3226 fullSpec = TRUE; 3227 } 2770 3228 } 2771 3229 2772 3230 if (path == NULL) { 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 3231 /* 3232 * If no path was given, the user wants one of the pre-defined shells, 3233 * yes? So we find the one s/he wants with the help of JobMatchShell 3234 * and set things up the right way. shellPath will be set up by 3235 * Job_Init. 3236 */ 3237 if (newShell.name == NULL) { 3238 Parse_Error(PARSE_FATAL, "Neither path nor name specified"); 3239 return(FAILURE); 3240 } else { 3241 commandShell = JobMatchShell(newShell.name); 3242 shellName = newShell.name; 3243 } 2786 3244 } else { 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 3245 /* 3246 * The user provided a path. If s/he gave nothing else (fullSpec is 3247 * FALSE), try and find a matching shell in the ones we know of. 3248 * Else we just take the specification at its word and copy it 3249 * to a new location. In either case, we need to record the 3250 * path the user gave for the shell. 3251 */ 3252 shellPath = path; 3253 path = strrchr(path, '/'); 3254 if (path == NULL) { 3255 path = shellPath; 3256 } else { 3257 path += 1; 3258 } 3259 if (newShell.name != NULL) { 3260 shellName = newShell.name; 3261 } else { 3262 shellName = path; 3263 } 3264 if (!fullSpec) { 3265 commandShell = JobMatchShell(shellName); 3266 } else { 3267 commandShell = (Shell *) emalloc(sizeof(Shell)); 3268 *commandShell = newShell; 3269 } 2812 3270 } 2813 3271 2814 3272 if (commandShell->echoOn && commandShell->echoOff) { 2815 3273 commandShell->hasEchoCtl = TRUE; 2816 3274 } 2817 3275 2818 3276 if (!commandShell->hasErrCtl) { 2819 2820 2821 2822 2823 2824 3277 if (commandShell->errCheck == NULL) { 3278 commandShell->errCheck = ""; 3279 } 3280 if (commandShell->ignErr == NULL) { 3281 commandShell->ignErr = "%s\n"; 3282 } 2825 3283 } 2826 3284 … … 2837 3295 *----------------------------------------------------------------------- 2838 3296 * JobInterrupt -- 2839 * 3297 * Handle the receipt of an interrupt. 2840 3298 * 2841 3299 * Results: 2842 * 3300 * None 2843 3301 * 2844 3302 * Side Effects: 2845 * 2846 * 3303 * All children are killed. Another job will be started if the 3304 * .INTERRUPT target was given. 2847 3305 *----------------------------------------------------------------------- 2848 3306 */ 2849 3307 static void 2850 3308 JobInterrupt(runINTERRUPT, signo) 2851 int runINTERRUPT;/* Non-zero if commands for the .INTERRUPT2852 2853 int signo;/* signal received */3309 int runINTERRUPT; /* Non-zero if commands for the .INTERRUPT 3310 * target should be executed */ 3311 int signo; /* signal received */ 2854 3312 { 2855 LstNode ln;/* element in job table */2856 Job *job = NULL; 2857 GNode *interrupt; 3313 LstNode ln; /* element in job table */ 3314 Job *job = NULL; /* job descriptor in that element */ 3315 GNode *interrupt; /* the node describing the .INTERRUPT target */ 2858 3316 2859 3317 aborting = ABORT_INTERRUPT; … … 2861 3319 (void) Lst_Open(jobs); 2862 3320 while ((ln = Lst_Next(jobs)) != NILLNODE) { 2863 2864 2865 2866 char*file = (job->node->path == NULL ?2867 2868 2869 2870 2871 2872 3321 job = (Job *) Lst_Datum(ln); 3322 3323 if (!Targ_Precious(job->node)) { 3324 char *file = (job->node->path == NULL ? 3325 job->node->name : 3326 job->node->path); 3327 if (!noExecute && eunlink(file) != -1) { 3328 Error("*** %s removed", file); 3329 } 3330 } 2873 3331 #ifdef RMT_WANTS_SIGNALS 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 3332 if (job->flags & JOB_REMOTE) { 3333 /* 3334 * If job is remote, let the Rmt module do the killing. 3335 */ 3336 if (!Rmt_Signal(job, signo)) { 3337 /* 3338 * If couldn't kill the thing, finish it out now with an 3339 * error code, since no exit report will come in likely. 3340 */ 3341 int status; 3342 3343 status.w_status = 0; 3344 status.w_retcode = 1; 3345 JobFinish(job, &status); 3346 } 3347 } else if (job->pid) { 3348 KILL(job->pid, signo); 3349 } 2892 3350 #else 2893 2894 2895 2896 2897 2898 2899 2900 2901 3351 if (job->pid) { 3352 if (DEBUG(JOB)) { 3353 (void) fprintf(stdout, 3354 "JobInterrupt passing signal to child %d.\n", 3355 job->pid); 3356 (void) fflush(stdout); 3357 } 3358 KILL(job->pid, signo); 3359 } 2902 3360 #endif /* RMT_WANTS_SIGNALS */ 2903 3361 } … … 2906 3364 (void)Lst_Open(stoppedJobs); 2907 3365 while ((ln = Lst_Next(stoppedJobs)) != NILLNODE) { 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 char*file = (job->node->path == NULL ?2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 3366 job = (Job *) Lst_Datum(ln); 3367 3368 if (job->flags & JOB_RESTART) { 3369 if (DEBUG(JOB)) { 3370 (void) fprintf(stdout, "%s%s", 3371 "JobInterrupt skipping job on stopped queue", 3372 "-- it was waiting to be restarted.\n"); 3373 (void) fflush(stdout); 3374 } 3375 continue; 3376 } 3377 if (!Targ_Precious(job->node)) { 3378 char *file = (job->node->path == NULL ? 3379 job->node->name : 3380 job->node->path); 3381 if (eunlink(file) == 0) { 3382 Error("*** %s removed", file); 3383 } 3384 } 3385 /* 3386 * Resume the thing so it will take the signal. 3387 */ 3388 if (DEBUG(JOB)) { 3389 (void) fprintf(stdout, 3390 "JobInterrupt passing CONT to stopped child %d.\n", 3391 job->pid); 3392 (void) fflush(stdout); 3393 } 3394 KILL(job->pid, SIGCONT); 2937 3395 #ifdef RMT_WANTS_SIGNALS 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 3396 if (job->flags & JOB_REMOTE) { 3397 /* 3398 * If job is remote, let the Rmt module do the killing. 3399 */ 3400 if (!Rmt_Signal(job, SIGINT)) { 3401 /* 3402 * If couldn't kill the thing, finish it out now with an 3403 * error code, since no exit report will come in likely. 3404 */ 3405 int status; 3406 status.w_status = 0; 3407 status.w_retcode = 1; 3408 JobFinish(job, &status); 3409 } 3410 } else if (job->pid) { 3411 if (DEBUG(JOB)) { 3412 (void) fprintf(stdout, 3413 "JobInterrupt passing interrupt to stopped child %d.\n", 3414 job->pid); 3415 (void) fflush(stdout); 3416 } 3417 KILL(job->pid, SIGINT); 3418 } 2961 3419 #endif /* RMT_WANTS_SIGNALS */ 2962 3420 } 2963 #endif2964 3421 Lst_Close(stoppedJobs); 3422 #endif 2965 3423 2966 3424 if (runINTERRUPT && !touchFlag) { 2967 2968 2969 2970 2971 2972 2973 3425 interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE); 3426 if (interrupt != NILGNODE) { 3427 ignoreErrors = FALSE; 3428 3429 JobStart(interrupt, JOB_IGNDOTS, (Job *)0); 3430 while (nJobs) { 3431 Job_CatchOutput(); 2974 3432 #ifndef RMT_WILL_WATCH 2975 3433 Job_CatchChildren(!usePipes); 2976 3434 #endif /* RMT_WILL_WATCH */ 2977 2978 3435 } 3436 } 2979 3437 } 2980 3438 } … … 2983 3441 *----------------------------------------------------------------------- 2984 3442 * Job_End -- 2985 * 2986 * 3443 * Do final processing such as the running of the commands 3444 * attached to the .END target. 2987 3445 * 2988 3446 * Results: 2989 * 3447 * Number of errors reported. 2990 3448 *----------------------------------------------------------------------- 2991 3449 */ … … 2994 3452 { 2995 3453 if (postCommands != NILGNODE && !Lst_IsEmpty(postCommands->commands)) { 2996 2997 2998 2999 3000 3001 3002 3454 if (errors) { 3455 Error("Errors reported so .END ignored"); 3456 } else { 3457 JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL); 3458 3459 while (nJobs) { 3460 Job_CatchOutput(); 3003 3461 #ifndef RMT_WILL_WATCH 3004 3462 Job_CatchChildren(!usePipes); 3005 3463 #endif /* RMT_WILL_WATCH */ 3006 3007 3464 } 3465 } 3008 3466 } 3009 3467 return(errors); … … 3013 3471 *----------------------------------------------------------------------- 3014 3472 * Job_Wait -- 3015 * 3016 * 3473 * Waits for all running jobs to finish and returns. Sets 'aborting' 3474 * to ABORT_WAIT to prevent other jobs from starting. 3017 3475 * 3018 3476 * Results: 3019 * 3477 * None. 3020 3478 * 3021 3479 * Side Effects: 3022 * 3480 * Currently running jobs finish. 3023 3481 * 3024 3482 *----------------------------------------------------------------------- … … 3029 3487 aborting = ABORT_WAIT; 3030 3488 while (nJobs != 0) { 3031 3489 Job_CatchOutput(); 3032 3490 #ifndef RMT_WILL_WATCH 3033 3491 Job_CatchChildren(!usePipes); 3034 3492 #endif /* RMT_WILL_WATCH */ 3035 3493 } … … 3040 3498 *----------------------------------------------------------------------- 3041 3499 * Job_AbortAll -- 3042 * 3043 * 3044 * 3500 * Abort all currently running jobs without handling output or anything. 3501 * This function is to be called only in the event of a major 3502 * error. Most definitely NOT to be called from JobInterrupt. 3045 3503 * 3046 3504 * Results: 3047 * 3505 * None 3048 3506 * 3049 3507 * Side Effects: 3050 * 3508 * All children are killed, not just the firstborn 3051 3509 *----------------------------------------------------------------------- 3052 3510 */ … … 3054 3512 Job_AbortAll() 3055 3513 { 3056 LstNode ln; /* element in job table */ 3057 Job *job; /* the job descriptor in that element */ 3058 int foo; 3514 #ifdef USE_KLIB 3515 LstNode ln; /* element in job table */ 3516 Job *job; /* the job descriptor in that element */ 3517 KPROCRES res; 3059 3518 3060 3519 aborting = ABORT_ERROR; 3061 3520 3521 if (nJobs) 3522 { 3523 Lst_Open(jobs); 3524 while ((ln = Lst_Next(jobs)) != NILLNODE) 3525 { 3526 job = (Job *) Lst_Datum(ln); 3527 3528 /* 3529 * kill the child process with increasingly drastic signals to make 3530 * darn sure it's dead. 3531 */ 3532 kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_INT); 3533 kProcKill(job->pid, KPROCKILL_FLAGS_TREE | KPROCKILL_FLAGS_TYPE_KILL); 3534 } 3535 } 3536 3537 /* 3538 * Catch as many children as want to report in at first, then give up 3539 */ 3540 do 3541 { 3542 kThrdYield(); 3543 } while (!kProcWait(KPID_NULL, KPROCWAIT_FLAGS_NOWAIT, &res, NULL)); /** @todo checkout this call */ 3544 3545 #else /* Don't use kLib */ 3546 LstNode ln; /* element in job table */ 3547 Job *job; /* the job descriptor in that element */ 3548 int foo; 3549 3550 aborting = ABORT_ERROR; 3551 3062 3552 if (nJobs) { 3063 3553 3064 3065 3066 3067 3068 3069 3070 3071 3554 (void) Lst_Open(jobs); 3555 while ((ln = Lst_Next(jobs)) != NILLNODE) { 3556 job = (Job *) Lst_Datum(ln); 3557 3558 /* 3559 * kill the child process with increasingly drastic signals to make 3560 * darn sure it's dead. 3561 */ 3072 3562 #ifdef RMT_WANTS_SIGNALS 3073 3074 3075 3076 3077 3078 3079 3563 if (job->flags & JOB_REMOTE) { 3564 Rmt_Signal(job, SIGINT); 3565 Rmt_Signal(job, SIGKILL); 3566 } else { 3567 KILL(job->pid, SIGINT); 3568 KILL(job->pid, SIGKILL); 3569 } 3080 3570 #else 3081 3082 3571 KILL(job->pid, SIGINT); 3572 KILL(job->pid, SIGKILL); 3083 3573 #endif /* RMT_WANTS_SIGNALS */ 3084 3574 } 3085 3575 } 3086 3576 … … 3089 3579 */ 3090 3580 while (waitpid((pid_t) -1, &foo, WNOHANG) > 0) 3091 continue; 3581 continue; 3582 #endif /* USE_KLIB */ 3092 3583 } 3093 3584 … … 3096 3587 *----------------------------------------------------------------------- 3097 3588 * JobFlagForMigration -- 3098 * 3099 * 3589 * Handle the eviction of a child. Called from RmtStatusChange. 3590 * Flags the child as remigratable and then suspends it. 3100 3591 * 3101 3592 * Results: 3102 * 3593 * none. 3103 3594 * 3104 3595 * Side Effects: 3105 * 3596 * The job descriptor is flagged for remigration. 3106 3597 * 3107 3598 *----------------------------------------------------------------------- … … 3109 3600 void 3110 3601 JobFlagForMigration(hostID) 3111 int hostID;/* ID of host we used, for matching children. */3602 int hostID; /* ID of host we used, for matching children. */ 3112 3603 { 3113 register Job *job; 3114 LstNode jnode; 3604 register Job *job; /* job descriptor for dead child */ 3605 LstNode jnode; /* list element for finding job */ 3115 3606 3116 3607 if (DEBUG(JOB)) { 3117 3118 3608 (void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID); 3609 (void) fflush(stdout); 3119 3610 } 3120 3611 jnode = Lst_Find(jobs, (ClientData)hostID, JobCmpRmtID); 3121 3612 3122 3613 if (jnode == NILLNODE) { 3123 3124 3125 3126 3127 3128 3129 3614 jnode = Lst_Find(stoppedJobs, (ClientData)hostID, JobCmpRmtID); 3615 if (jnode == NILLNODE) { 3616 if (DEBUG(JOB)) { 3617 Error("Evicting host(%d) not in table", hostID); 3618 } 3619 return; 3620 } 3130 3621 } 3131 3622 job = (Job *) Lst_Datum(jnode); 3132 3623 3133 3624 if (DEBUG(JOB)) { 3134 3135 3136 3137 3625 (void) fprintf(stdout, 3626 "JobFlagForMigration(%d) found job '%s'.\n", hostID, 3627 job->node->name); 3628 (void) fflush(stdout); 3138 3629 } 3139 3630 … … 3146 3637 3147 3638 3639 #ifdef SIGCONT 3148 3640 /*- 3149 3641 *----------------------------------------------------------------------- 3150 3642 * JobRestartJobs -- 3151 * 3152 * 3153 * 3643 * Tries to restart stopped jobs if there are slots available. 3644 * Note that this tries to restart them regardless of pending errors. 3645 * It's not good to leave stopped jobs lying around! 3154 3646 * 3155 3647 * Results: 3156 * 3648 * None. 3157 3649 * 3158 3650 * Side Effects: 3159 * 3651 * Resumes(and possibly migrates) jobs. 3160 3652 * 3161 3653 *----------------------------------------------------------------------- … … 3165 3657 { 3166 3658 while (!jobFull && !Lst_IsEmpty(stoppedJobs)) { 3167 3168 3169 3170 3171 3172 3659 if (DEBUG(JOB)) { 3660 (void) fprintf(stdout, 3661 "Job queue is not full. Restarting a stopped job.\n"); 3662 (void) fflush(stdout); 3663 } 3664 JobRestart((Job *)Lst_DeQueue(stoppedJobs)); 3173 3665 } 3174 3666 } 3667 #endif
Note:
See TracChangeset
for help on using the changeset viewer.