1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 
  27 /*
  28  *      parallel.cc
  29  *
  30  *      Deal with the parallel processing
  31  */
  32 
  33 /*
  34  * Included files
  35  */
  36 #include <errno.h>                /* errno */
  37 #include <fcntl.h>
  38 #include <mk/defs.h>
  39 #include <mksh/dosys.h>           /* redirect_io() */
  40 #include <mksh/macro.h>           /* expand_value() */
  41 #include <mksh/misc.h>            /* getmem() */
  42 #include <sys/signal.h>
  43 #include <sys/stat.h>
  44 #include <sys/types.h>
  45 #include <sys/utsname.h>
  46 #include <sys/wait.h>
  47 #include <unistd.h>
  48 #include <netdb.h>
  49 #include <libintl.h>
  50 
  51 
  52 
  53 /*
  54  * Defined macros
  55  */
  56 #define MAXRULES                100
  57 
  58 /*
  59  * This const should be in avo_dms/include/AvoDmakeCommand.h
  60  */
  61 const int local_host_mask = 0x20;
  62 
  63 
  64 /*
  65  * typedefs & structs
  66  */
  67 
  68 
  69 /*
  70  * Static variables
  71  */
  72 static  Boolean         just_did_subtree = false;
  73 static  char            local_host[MAXNAMELEN] = "";
  74 static  char            user_name[MAXNAMELEN] = "";
  75 static  int             pmake_max_jobs = 0;
  76 static  pid_t           process_running = -1;
  77 static  Running         *running_tail = &running_list;
  78 static  Name            subtree_conflict;
  79 static  Name            subtree_conflict2;
  80 
  81 
  82 /*
  83  * File table of contents
  84  */
  85 static  void            delete_running_struct(Running rp);
  86 static  Boolean         dependency_conflict(Name target);
  87 static  Doname          distribute_process(char **commands, Property line);
  88 static  void            doname_subtree(Name target, Boolean do_get, Boolean implicit);
  89 static  void            dump_out_file(char *filename, Boolean err);
  90 static  void            finish_doname(Running rp);
  91 static  void            maybe_reread_make_state(void);
  92 static  void            process_next(void);
  93 static  void            reset_conditionals(int cnt, Name *targets, Property *locals);
  94 static  pid_t           run_rule_commands(char *host, char **commands);
  95 static  Property        *set_conditionals(int cnt, Name *targets);
  96 static  void            store_conditionals(Running rp);
  97 
  98 
  99 /*
 100  *      execute_parallel(line, waitflg)
 101  *
 102  *      DMake 2.x:
 103  *      parallel mode: spawns a parallel process to execute the command group.
 104  *
 105  *      Return value:
 106  *                              The result of the execution
 107  *
 108  *      Parameters:
 109  *              line            The command group to execute
 110  */
 111 Doname
 112 execute_parallel(Property line, Boolean waitflg, Boolean local)
 113 {
 114         int                     argcnt;
 115         int                     cmd_options = 0;
 116         char                    *commands[MAXRULES + 5];
 117         char                    *cp;
 118         Name                    dmake_name;
 119         Name                    dmake_value;
 120         int                     ignore;
 121         Name                    make_machines_name;
 122         char                    **p;
 123         Property                prop;
 124         Doname                  result = build_ok;
 125         Cmd_line                rule;
 126         Boolean                 silent_flag;
 127         Name                    target = line->body.line.target;
 128         Boolean                 wrote_state_file = false;
 129 
 130         if ((pmake_max_jobs == 0) &&
 131             (dmake_mode_type == parallel_mode)) {
 132                 if (local_host[0] == '\0') {
 133                         (void) gethostname(local_host, MAXNAMELEN);
 134                 }
 135                 MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS");
 136                 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
 137                 if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
 138                     ((dmake_value = prop->body.macro.value) != NULL)) {
 139                         pmake_max_jobs = atoi(dmake_value->string_mb);
 140                         if (pmake_max_jobs <= 0) {
 141                                 warning(gettext("DMAKE_MAX_JOBS cannot be less than or equal to zero."));
 142                                 warning(gettext("setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS);
 143                                 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
 144                         }
 145                 } else {
 146                         /*
 147                          * For backwards compatibility w/ PMake 1.x, when
 148                          * DMake 2.x is being run in parallel mode, DMake
 149                          * should parse the PMake startup file
 150                          * $(HOME)/.make.machines to get the pmake_max_jobs.
 151                          */
 152                         MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE");
 153                         dmake_name = GETNAME(wcs_buffer, FIND_LENGTH);
 154                         if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) &&
 155                             ((dmake_value = prop->body.macro.value) != NULL)) {
 156                                 make_machines_name = dmake_value;
 157                         } else {
 158                                 make_machines_name = NULL;
 159                         }
 160                         if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) {
 161                                 pmake_max_jobs = PMAKE_DEF_MAX_JOBS;
 162                         }
 163                 }
 164         }
 165 
 166         if ((dmake_mode_type == serial_mode) ||
 167             ((dmake_mode_type == parallel_mode) && (waitflg))) {
 168                 return (execute_serial(line));
 169         }
 170 
 171         {
 172                 p = commands;
 173         }
 174 
 175         argcnt = 0;
 176         for (rule = line->body.line.command_used;
 177              rule != NULL;
 178              rule = rule->next) {
 179                 if (posix && (touch || quest) && !rule->always_exec) {
 180                         continue;
 181                 }
 182                 if (vpath_defined) {
 183                         rule->command_line =
 184                           vpath_translation(rule->command_line);
 185                 }
 186                 
 187                 silent_flag = false;
 188                 ignore = 0;
 189 
 190                 if (rule->command_line->hash.length > 0) {
 191                         if (++argcnt == MAXRULES) {
 192                                 return build_serial;
 193                         }
 194                         {
 195                                 if (rule->silent && !silent) {
 196                                         silent_flag = true;
 197                                 }
 198                                 if (rule->ignore_error) {
 199                                         ignore++;
 200                                 }
 201                                 /* XXX - need to add support for + prefix */
 202                                 if (silent_flag || ignore) {
 203                                         *p = getmem((silent_flag ? 1 : 0) +
 204                                                     ignore +
 205                                                     (strlen(rule->
 206                                                            command_line->
 207                                                            string_mb)) +
 208                                                     1);
 209                                         cp = *p++;
 210                                         if (silent_flag) {
 211                                                 *cp++ = (int) at_char;
 212                                         }
 213                                         if (ignore) {
 214                                                 *cp++ = (int) hyphen_char;
 215                                         }
 216                                         (void) strcpy(cp, rule->command_line->string_mb);
 217                                 } else {
 218                                         *p++ = rule->command_line->string_mb;
 219                                 }
 220                         }
 221                 }
 222         }
 223         if ((argcnt == 0) ||
 224             (report_dependencies_level > 0)) {
 225                 return build_ok;
 226         }
 227         {
 228                 *p = NULL;
 229 
 230                 Doname res = distribute_process(commands, line);
 231                 if (res == build_running) {
 232                         parallel_process_cnt++;
 233                 }
 234 
 235                 /*
 236                  * Return only those memory that were specially allocated
 237                  * for part of commands.
 238                  */
 239                 for (int i = 0; commands[i] != NULL; i++) {
 240                         if ((commands[i][0] == (int) at_char) ||
 241                             (commands[i][0] == (int) hyphen_char)) {
 242                                 retmem_mb(commands[i]);
 243                         }
 244                 }
 245                 return res;
 246         }
 247 }
 248 
 249 
 250 
 251 #include <unistd.h>       /* sysconf(_SC_NPROCESSORS_ONLN) */
 252 #include <sys/ipc.h>              /* ftok() */
 253 #include <sys/shm.h>              /* shmget(), shmat(), shmdt(), shmctl() */
 254 #include <semaphore.h>            /* sem_init(), sem_trywait(), sem_post(), sem_destroy() */
 255 #include <sys/loadavg.h>  /* getloadavg() */
 256 
 257 /*
 258  *      adjust_pmake_max_jobs (int pmake_max_jobs)
 259  *
 260  *      Parameters:
 261  *              pmake_max_jobs  - max jobs limit set by user
 262  *
 263  *      External functions used:
 264  *              sysconf()
 265  *              getloadavg()
 266  */
 267 static int
 268 adjust_pmake_max_jobs (int pmake_max_jobs)
 269 {
 270         static int      ncpu = 0;
 271         double          loadavg[3];
 272         int             adjustment;
 273         int             adjusted_max_jobs;
 274 
 275         if (ncpu <= 0) {
 276                 if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) {
 277                         ncpu = 1;
 278                 }
 279         }
 280         if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs);
 281         adjustment = ((int)loadavg[LOADAVG_1MIN]);
 282         if (adjustment < 2) return(pmake_max_jobs);
 283         if (ncpu > 1) {
 284                 adjustment = adjustment / ncpu;
 285         }
 286         adjusted_max_jobs = pmake_max_jobs - adjustment;
 287         if (adjusted_max_jobs < 1) adjusted_max_jobs = 1;
 288         return(adjusted_max_jobs);
 289 }
 290 
 291 /*
 292  *  M2 adjust mode data and functions
 293  *
 294  *  m2_init()           - initializes M2 shared semaphore
 295  *  m2_acquire_job()    - decrements M2 semaphore counter
 296  *  m2_release_job()    - increments M2 semaphore counter
 297  *  m2_fini()           - destroys M2 semaphore and shared memory*
 298  *
 299  *  Environment variables:
 300  *      __DMAKE_M2_FILE__
 301  *
 302  *  External functions:
 303  *      ftok(), shmget(), shmat(), shmdt(), shmctl()
 304  *      sem_init(), sem_trywait(), sem_post(), sem_destroy()
 305  *      creat(), close(), unlink()
 306  *      getenv(), putenv()
 307  *
 308  *  Static variables:
 309  *      m2_file         - tmp file name to create ipc key for shared memory
 310  *      m2_shm_id       - shared memory id
 311  *      m2_shm_sem      - shared memory semaphore
 312  */
 313 
 314 static char     m2_file[MAXPATHLEN];
 315 static int      m2_shm_id = -1;
 316 static sem_t*   m2_shm_sem = 0;
 317 
 318 static int
 319 m2_init() {
 320         char    *var;
 321         key_t   key;
 322 
 323         if ((var = getenv("__DMAKE_M2_FILE__")) == 0) {
 324                 /* compose tmp file name */
 325                 sprintf(m2_file, "%s/dmake.m2.%d.XXXXXX", tmpdir, getpid());
 326 
 327                 /* create tmp file */
 328                 int fd = mkstemp(m2_file);
 329                 if (fd < 0) {
 330                         return -1;
 331                 } else {
 332                         close(fd);
 333                 }
 334         } else {
 335                 /* using existing semaphore */
 336                 strcpy(m2_file, var);
 337         }
 338 
 339         /* combine IPC key */
 340         if ((key = ftok(m2_file, 38)) == (key_t) -1) {
 341                 return -1;
 342         }
 343 
 344         /* create shared memory */
 345         if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) {
 346                 return -1;
 347         }
 348 
 349         /* attach shared memory */
 350         if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) {
 351                 return -1;
 352         }
 353 
 354         /* root process */
 355         if (var == 0) {
 356                 /* initialize semaphore */
 357                 if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) {
 358                         return -1;
 359                 }
 360 
 361                 /* alloc memory for env variable */
 362                 if ((var = (char*) malloc(MAXPATHLEN)) == 0) {
 363                         return -1;
 364                 }
 365 
 366                 /* put key to env */
 367                 sprintf(var, "__DMAKE_M2_FILE__=%s", m2_file);
 368                 if (putenv(var)) {
 369                         return -1;
 370                 }
 371         }
 372         return 0;
 373 }
 374 
 375 static void
 376 m2_fini() {
 377         if (m2_shm_id >= 0) {
 378                 struct shmid_ds stat;
 379 
 380                 /* determine the number of attached processes */
 381                 if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) {
 382                         if (stat.shm_nattch <= 1) {
 383                                 /* destroy semaphore */
 384                                 if (m2_shm_sem != 0) {
 385                                         (void) sem_destroy(m2_shm_sem);
 386                                 }
 387 
 388                                 /* destroy shared memory */
 389                                 (void) shmctl(m2_shm_id, IPC_RMID, &stat);
 390 
 391                                 /* remove tmp file created for the key */
 392                                 (void) unlink(m2_file);
 393                         } else {
 394                                 /* detach shared memory */
 395                                 if (m2_shm_sem != 0) {
 396                                         (void) shmdt((char*) m2_shm_sem);
 397                                 }
 398                         }
 399                 }
 400 
 401                 m2_shm_id = -1;
 402                 m2_shm_sem = 0;
 403         }
 404 }
 405 
 406 static int
 407 m2_acquire_job() {
 408         if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
 409                 if (sem_trywait(m2_shm_sem) == 0) {
 410                         return 1;
 411                 }
 412                 if (errno == EAGAIN) {
 413                         return 0;
 414                 }
 415         }
 416         return -1;
 417 }
 418 
 419 static int
 420 m2_release_job() {
 421         if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) {
 422                 if (sem_post(m2_shm_sem) == 0) {
 423                         return 0;
 424                 }
 425         }
 426         return -1;
 427 }
 428 
 429 /*
 430  *  job adjust mode
 431  *
 432  *  Possible values:
 433  *    ADJUST_M1         - adjustment by system load (default)
 434  *    ADJUST_M2         - fixed limit of jobs for the group of nested dmakes
 435  *    ADJUST_NONE       - no adjustment - fixed limit of jobs for the current dmake
 436  */
 437 static enum {
 438         ADJUST_UNKNOWN,
 439         ADJUST_M1,
 440         ADJUST_M2,
 441         ADJUST_NONE
 442 } job_adjust_mode = ADJUST_UNKNOWN;
 443 
 444 /*
 445  *  void job_adjust_fini()
 446  *
 447  *  Description:
 448  *      Cleans up job adjust data.
 449  *
 450  *  Static variables:
 451  *      job_adjust_mode Current job adjust mode
 452  */
 453 void
 454 job_adjust_fini() {
 455         if (job_adjust_mode == ADJUST_M2) {
 456                 m2_fini();
 457         }
 458 }
 459 
 460 /*
 461  *  void job_adjust_error()
 462  *
 463  *  Description:
 464  *      Prints warning message, cleans up job adjust data, and disables job adjustment
 465  *
 466  *  Environment:
 467  *      DMAKE_ADJUST_MAX_JOBS
 468  *
 469  *  External functions:
 470  *      putenv()
 471  *
 472  *  Static variables:
 473  *      job_adjust_mode Current job adjust mode
 474  */
 475 static void
 476 job_adjust_error() {
 477         if (job_adjust_mode != ADJUST_NONE) {
 478                 /* cleanup internals */
 479                 job_adjust_fini();
 480 
 481                 /* warning message for the user */
 482                 warning(gettext("Encountered max jobs auto adjustment error - disabling auto adjustment."));
 483 
 484                 /* switch off job adjustment for the children */
 485                 putenv(strdup("DMAKE_ADJUST_MAX_JOBS=NO"));
 486 
 487                 /* and for this dmake */
 488                 job_adjust_mode = ADJUST_NONE;
 489         }
 490 }
 491 
 492 /*
 493  *  void job_adjust_init()
 494  *
 495  *  Description:
 496  *      Parses DMAKE_ADJUST_MAX_JOBS env variable
 497  *      and performs appropriate initializations.
 498  *
 499  *  Environment:
 500  *      DMAKE_ADJUST_MAX_JOBS
 501  *        DMAKE_ADJUST_MAX_JOBS == "NO" - no adjustment
 502  *        DMAKE_ADJUST_MAX_JOBS == "M2" - M2 adjust mode
 503  *        other                         - M1 adjust mode
 504  *
 505  *  External functions:
 506  *      getenv()
 507  *
 508  *  Static variables:
 509  *      job_adjust_mode Current job adjust mode
 510  */
 511 static void
 512 job_adjust_init() {
 513         if (job_adjust_mode == ADJUST_UNKNOWN) {
 514                 /* default mode */
 515                 job_adjust_mode = ADJUST_M1;
 516 
 517                 /* determine adjust mode */
 518                 if (char *var = getenv("DMAKE_ADJUST_MAX_JOBS")) {
 519                         if (strcasecmp(var, "NO") == 0) {
 520                                 job_adjust_mode = ADJUST_NONE;
 521                         } else if (strcasecmp(var, "M2") == 0) {
 522                                 job_adjust_mode = ADJUST_M2;
 523                         }
 524                 }
 525 
 526                 /* M2 specific initialization */
 527                 if (job_adjust_mode == ADJUST_M2) {
 528                         if (m2_init()) {
 529                                 job_adjust_error();
 530                         }
 531                 }
 532         }
 533 }
 534 
 535 
 536 /*
 537  *      distribute_process(char **commands, Property line)
 538  *
 539  *      Parameters:
 540  *              commands        argv vector of commands to execute
 541  *
 542  *      Return value:
 543  *                              The result of the execution
 544  *
 545  *      Static variables used:
 546  *              process_running Set to the pid of the process set running
 547  *              job_adjust_mode Current job adjust mode
 548  */
 549 static Doname
 550 distribute_process(char **commands, Property line)
 551 {
 552         static unsigned file_number = 0;
 553         wchar_t         string[MAXPATHLEN];
 554         char            mbstring[MAXPATHLEN];
 555         int             filed;
 556         int             res;
 557         int             tmp_index;
 558         char            *tmp_index_str_ptr;
 559 
 560         /* initialize adjust mode, if not initialized */
 561         if (job_adjust_mode == ADJUST_UNKNOWN) {
 562                 job_adjust_init();
 563         }
 564 
 565         /* actions depend on adjust mode */
 566         switch (job_adjust_mode) {
 567         case ADJUST_M1:
 568                 while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) {
 569                         await_parallel(false);
 570                         finish_children(true);
 571                 }
 572                 break;
 573         case ADJUST_M2:
 574                 if ((res = m2_acquire_job()) == 0) {
 575                         if (parallel_process_cnt > 0) {
 576                                 await_parallel(false);
 577                                 finish_children(true);
 578 
 579                                 if ((res = m2_acquire_job()) == 0) {
 580                                         return build_serial;
 581                                 }
 582                         } else {
 583                                 return build_serial;
 584                         }
 585                 }
 586                 if (res < 0) {
 587                         /* job adjustment error */
 588                         job_adjust_error();
 589 
 590                         /* no adjustment */
 591                         while (parallel_process_cnt >= pmake_max_jobs) {
 592                                 await_parallel(false);
 593                                 finish_children(true);
 594                         }
 595                 }
 596                 break;
 597         default:
 598                 while (parallel_process_cnt >= pmake_max_jobs) {
 599                         await_parallel(false);
 600                         finish_children(true);
 601                 }
 602         }
 603 
 604         setvar_envvar();
 605         /*
 606          * Tell the user what DMake is doing.
 607          */
 608         if (!silent && output_mode != txt2_mode) {
 609                 /*
 610                  * Print local_host --> x job(s).
 611                  */
 612                 (void) fprintf(stdout,
 613                                gettext("%s --> %d %s\n"),
 614                                local_host,
 615                                parallel_process_cnt + 1,
 616                                (parallel_process_cnt == 0) ? gettext("job") : gettext("jobs"));
 617 
 618                 /* Print command line(s). */
 619                 tmp_index = 0;
 620                 while (commands[tmp_index] != NULL) {
 621                     /* No @ char. */
 622                     /* XXX - need to add [2] when + prefix is added */
 623                     if ((commands[tmp_index][0] != (int) at_char) &&
 624                         (commands[tmp_index][1] != (int) at_char)) {
 625                         tmp_index_str_ptr = commands[tmp_index];
 626                         if (*tmp_index_str_ptr == (int) hyphen_char) {
 627                                 tmp_index_str_ptr++;
 628                         }
 629                         (void) fprintf(stdout, "%s\n", tmp_index_str_ptr);
 630                     }
 631                     tmp_index++;
 632                 }
 633                 (void) fflush(stdout);
 634         }
 635 
 636         (void) sprintf(mbstring,
 637                         "%s/dmake.stdout.%d.%d.XXXXXX",
 638                         tmpdir,
 639                         getpid(),
 640                         file_number++);
 641 
 642         mktemp(mbstring);
 643 
 644         stdout_file = strdup(mbstring);
 645         stderr_file = NULL;
 646 
 647         if (!out_err_same) {
 648                 (void) sprintf(mbstring,
 649                                 "%s/dmake.stderr.%d.%d.XXXXXX",
 650                                 tmpdir,
 651                                 getpid(),
 652                                 file_number++);
 653 
 654                 mktemp(mbstring);
 655 
 656                 stderr_file = strdup(mbstring);
 657         }
 658 
 659         process_running = run_rule_commands(local_host, commands);
 660 
 661         return build_running;
 662 }
 663 
 664 /*
 665  *      doname_parallel(target, do_get, implicit)
 666  *
 667  *      Processes the given target and finishes up any parallel
 668  *      processes left running.
 669  *
 670  *      Return value:
 671  *                              Result of target build
 672  *
 673  *      Parameters:
 674  *              target          Target to build
 675  *              do_get          True if sccs get to be done
 676  *              implicit        True if this is an implicit target
 677  */
 678 Doname
 679 doname_parallel(Name target, Boolean do_get, Boolean implicit)
 680 {
 681         Doname          result;
 682 
 683         result = doname_check(target, do_get, implicit, false);
 684         if (result == build_ok || result == build_failed) {
 685                 return result;
 686         }
 687         finish_running();
 688         return (Doname) target->state;
 689 }
 690 
 691 /*
 692  *      doname_subtree(target, do_get, implicit)
 693  *
 694  *      Completely computes an object and its dependents for a
 695  *      serial subtree build.
 696  *
 697  *      Parameters:
 698  *              target          Target to build
 699  *              do_get          True if sccs get to be done
 700  *              implicit        True if this is an implicit target
 701  *
 702  *      Static variables used:
 703  *              running_tail    Tail of the list of running processes
 704  *
 705  *      Global variables used:
 706  *              running_list    The list of running processes
 707  */
 708 static void
 709 doname_subtree(Name target, Boolean do_get, Boolean implicit)
 710 {
 711         Running         save_running_list;
 712         Running         *save_running_tail;
 713 
 714         save_running_list = running_list;
 715         save_running_tail = running_tail;
 716         running_list = NULL;
 717         running_tail = &running_list;
 718         target->state = build_subtree;
 719         target->checking_subtree = true;
 720         while(doname_check(target, do_get, implicit, false) == build_running) {
 721                 target->checking_subtree = false;
 722                 finish_running();
 723                 target->state = build_subtree;
 724         }
 725         target->checking_subtree = false;
 726         running_list = save_running_list;
 727         running_tail = save_running_tail;
 728 }
 729 
 730 /*
 731  *      finish_running()
 732  *
 733  *      Keeps processing until the running_list is emptied out.
 734  *
 735  *      Parameters:
 736  *
 737  *      Global variables used:
 738  *              running_list    The list of running processes
 739  */
 740 void
 741 finish_running(void)
 742 {
 743         while (running_list != NULL) {
 744                 {
 745                         await_parallel(false);
 746                         finish_children(true);
 747                 }
 748                 if (running_list != NULL) {
 749                         process_next();
 750                 }
 751         }
 752 }
 753 
 754 /*
 755  *      process_next()
 756  *
 757  *      Searches the running list for any targets which can start processing.
 758  *      This can be a pending target, a serial target, or a subtree target.
 759  *
 760  *      Parameters:
 761  *
 762  *      Static variables used:
 763  *              running_tail            The end of the list of running procs
 764  *              subtree_conflict        A target which conflicts with a subtree
 765  *              subtree_conflict2       The other target which conflicts
 766  *
 767  *      Global variables used:
 768  *              commands_done           True if commands executed
 769  *              debug_level             Controls debug output
 770  *              parallel_process_cnt    Number of parallel process running
 771  *              recursion_level         Indentation for debug output
 772  *              running_list            List of running processes
 773  */
 774 static void
 775 process_next(void)
 776 {
 777         Running         rp;
 778         Running         *rp_prev;
 779         Property        line;
 780         Chain           target_group;
 781         Dependency      dep;
 782         Boolean         quiescent = true;
 783         Running         *subtree_target;
 784         Boolean         saved_commands_done;
 785         Property        *conditionals;
 786 
 787         subtree_target = NULL;
 788         subtree_conflict = NULL;
 789         subtree_conflict2 = NULL;
 790         /*
 791          * If nothing currently running, build a serial target, if any.
 792          */
 793 start_loop_1:
 794         for (rp_prev = &running_list, rp = running_list;
 795              rp != NULL && parallel_process_cnt == 0;
 796              rp = rp->next) {
 797                 if (rp->state == build_serial) {
 798                         *rp_prev = rp->next;
 799                         if (rp->next == NULL) {
 800                                 running_tail = rp_prev;
 801                         }
 802                         recursion_level = rp->recursion_level;
 803                         rp->target->state = build_pending;
 804                         (void) doname_check(rp->target,
 805                                             rp->do_get,
 806                                             rp->implicit,
 807                                             false);
 808                         quiescent = false;
 809                         delete_running_struct(rp);
 810                         goto start_loop_1;
 811                 } else {
 812                         rp_prev = &rp->next;
 813                 }
 814         }
 815         /*
 816          * Find a target to build.  The target must be pending, have all
 817          * its dependencies built, and not be in a target group with a target
 818          * currently building.
 819          */
 820 start_loop_2:
 821         for (rp_prev = &running_list, rp = running_list;
 822              rp != NULL;
 823              rp = rp->next) {
 824                 if (!(rp->state == build_pending ||
 825                       rp->state == build_subtree)) {
 826                         quiescent = false;
 827                         rp_prev = &rp->next;
 828                 } else if (rp->state == build_pending) {
 829                         line = get_prop(rp->target->prop, line_prop);
 830                         for (dep = line->body.line.dependencies;
 831                              dep != NULL;
 832                              dep = dep->next) {
 833                                 if (dep->name->state == build_running ||
 834                                     dep->name->state == build_pending ||
 835                                     dep->name->state == build_serial) {
 836                                         break;
 837                                 }
 838                         }
 839                         if (dep == NULL) {
 840                                 for (target_group = line->body.line.target_group;
 841                                      target_group != NULL;
 842                                      target_group = target_group->next) {
 843                                         if (is_running(target_group->name)) {
 844                                                 break;
 845                                         }
 846                                 }
 847                                 if (target_group == NULL) {
 848                                         *rp_prev = rp->next;
 849                                         if (rp->next == NULL) {
 850                                                 running_tail = rp_prev;
 851                                         }
 852                                         recursion_level = rp->recursion_level;
 853                                         rp->target->state = rp->redo ?
 854                                           build_dont_know : build_pending;
 855                                         saved_commands_done = commands_done;
 856                                         conditionals =
 857                                                 set_conditionals
 858                                                     (rp->conditional_cnt,
 859                                                      rp->conditional_targets);
 860                                         rp->target->dont_activate_cond_values = true;
 861                                         if ((doname_check(rp->target,
 862                                                           rp->do_get,
 863                                                           rp->implicit,
 864                                                           rp->target->has_target_prop ? true : false) !=
 865                                              build_running) &&
 866                                             !commands_done) {
 867                                                 commands_done =
 868                                                   saved_commands_done;
 869                                         }
 870                                         rp->target->dont_activate_cond_values = false;
 871                                         reset_conditionals
 872                                                 (rp->conditional_cnt,
 873                                                  rp->conditional_targets,
 874                                                  conditionals);
 875                                         quiescent = false;
 876                                         delete_running_struct(rp);
 877                                         goto start_loop_2;
 878                                 } else {
 879                                         rp_prev = &rp->next;
 880                                 }
 881                         } else {
 882                                 rp_prev = &rp->next;
 883                         }
 884                 } else {
 885                         rp_prev = &rp->next;
 886                 }
 887         }
 888         /*
 889          * If nothing has been found to build and there exists a subtree
 890          * target with no dependency conflicts, build it.
 891          */
 892         if (quiescent) {
 893 start_loop_3:
 894                 for (rp_prev = &running_list, rp = running_list;
 895                      rp != NULL;
 896                      rp = rp->next) {
 897                         if (rp->state == build_subtree) {
 898                                 if (!dependency_conflict(rp->target)) {
 899                                         *rp_prev = rp->next;
 900                                         if (rp->next == NULL) {
 901                                                 running_tail = rp_prev;
 902                                         }
 903                                         recursion_level = rp->recursion_level;
 904                                         doname_subtree(rp->target,
 905                                                        rp->do_get,
 906                                                        rp->implicit);
 907                                         quiescent = false;
 908                                         delete_running_struct(rp);
 909                                         goto start_loop_3;
 910                                 } else {
 911                                         subtree_target = rp_prev;
 912                                         rp_prev = &rp->next;
 913                                 }
 914                         } else {
 915                                 rp_prev = &rp->next;
 916                         }
 917                 }
 918         }
 919         /*
 920          * If still nothing found to build, we either have a deadlock
 921          * or a subtree with a dependency conflict with something waiting
 922          * to build.
 923          */
 924         if (quiescent) {
 925                 if (subtree_target == NULL) {
 926                         fatal(gettext("Internal error: deadlock detected in process_next"));
 927                 } else {
 928                         rp = *subtree_target;
 929                         if (debug_level > 0) {
 930                                 warning(gettext("Conditional macro conflict encountered for %s between %s and %s"),
 931                                         subtree_conflict2->string_mb,
 932                                         rp->target->string_mb,
 933                                         subtree_conflict->string_mb);
 934                         }
 935                         *subtree_target = (*subtree_target)->next;
 936                         if (rp->next == NULL) {
 937                                 running_tail = subtree_target;
 938                         }
 939                         recursion_level = rp->recursion_level;
 940                         doname_subtree(rp->target, rp->do_get, rp->implicit);
 941                         delete_running_struct(rp);
 942                 }
 943         }
 944 }
 945 
 946 /*
 947  *      set_conditionals(cnt, targets)
 948  *
 949  *      Sets the conditional macros for the targets given in the array of
 950  *      targets.  The old macro values are returned in an array of
 951  *      Properties for later resetting.
 952  *
 953  *      Return value:
 954  *                                      Array of conditional macro settings
 955  *
 956  *      Parameters:
 957  *              cnt                     Number of targets
 958  *              targets                 Array of targets
 959  */
 960 static Property *
 961 set_conditionals(int cnt, Name *targets)
 962 {
 963         Property        *locals, *lp;
 964         Name            *tp;
 965 
 966         locals = (Property *) getmem(cnt * sizeof(Property));
 967         for (lp = locals, tp = targets;
 968              cnt > 0;
 969              cnt--, lp++, tp++) {
 970                 *lp = (Property) getmem((*tp)->conditional_cnt *
 971                                         sizeof(struct _Property));
 972                 set_locals(*tp, *lp);
 973         }
 974         return locals;
 975 }
 976 
 977 /*
 978  *      reset_conditionals(cnt, targets, locals)
 979  *
 980  *      Resets the conditional macros as saved in the given array of
 981  *      Properties.  The resets are done in reverse order.  Afterwards the
 982  *      data structures are freed.
 983  *
 984  *      Parameters:
 985  *              cnt                     Number of targets
 986  *              targets                 Array of targets
 987  *              locals                  Array of dependency macro settings
 988  */
 989 static void
 990 reset_conditionals(int cnt, Name *targets, Property *locals)
 991 {
 992         Name            *tp;
 993         Property        *lp;
 994 
 995         for (tp = targets + (cnt - 1), lp = locals + (cnt - 1);
 996              cnt > 0;
 997              cnt--, tp--, lp--) {
 998                 reset_locals(*tp,
 999                              *lp,
1000                              get_prop((*tp)->prop, conditional_prop),
1001                              0);
1002                 retmem_mb((caddr_t) *lp);
1003         }
1004         retmem_mb((caddr_t) locals);
1005 }
1006 
1007 /*
1008  *      dependency_conflict(target)
1009  *
1010  *      Returns true if there is an intersection between
1011  *      the subtree of the target and any dependents of the pending targets.
1012  *
1013  *      Return value:
1014  *                                      True if conflict found
1015  *
1016  *      Parameters:
1017  *              target                  Subtree target to check
1018  *
1019  *      Static variables used:
1020  *              subtree_conflict        Target conflict found
1021  *              subtree_conflict2       Second conflict found
1022  *
1023  *      Global variables used:
1024  *              running_list            List of running processes
1025  *              wait_name               .WAIT, not a real dependency
1026  */
1027 static Boolean
1028 dependency_conflict(Name target)
1029 {
1030         Property        line;
1031         Property        pending_line;
1032         Dependency      dp;
1033         Dependency      pending_dp;
1034         Running         rp;
1035 
1036         /* Return if we are already checking this target */
1037         if (target->checking_subtree) {
1038                 return false;
1039         }
1040         target->checking_subtree = true;
1041         line = get_prop(target->prop, line_prop);
1042         if (line == NULL) {
1043                 target->checking_subtree = false;
1044                 return false;
1045         }
1046         /* Check each dependency of the target for conflicts */
1047         for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) {
1048                 /* Ignore .WAIT dependency */
1049                 if (dp->name == wait_name) {
1050                         continue;
1051                 }
1052                 /*
1053                  * For each pending target, look for a dependency which
1054                  * is the same as a dependency of the subtree target.  Since
1055                  * we can't build the subtree until all pending targets have
1056                  * finished which depend on the same dependency, this is
1057                  * a conflict.
1058                  */
1059                 for (rp = running_list; rp != NULL; rp = rp->next) {
1060                         if (rp->state == build_pending) {
1061                                 pending_line = get_prop(rp->target->prop,
1062                                                         line_prop);
1063                                 if (pending_line == NULL) {
1064                                         continue;
1065                                 }
1066                                 for(pending_dp = pending_line->
1067                                                         body.line.dependencies;
1068                                     pending_dp != NULL;
1069                                     pending_dp = pending_dp->next) {
1070                                         if (dp->name == pending_dp->name) {
1071                                                 target->checking_subtree
1072                                                                 = false;
1073                                                 subtree_conflict = rp->target;
1074                                                 subtree_conflict2 = dp->name;
1075                                                 return true;
1076                                         }
1077                                 }
1078                         }
1079                 }
1080                 if (dependency_conflict(dp->name)) {
1081                         target->checking_subtree = false;
1082                         return true;
1083                 }
1084         }
1085         target->checking_subtree = false;
1086         return false;
1087 }
1088 
1089 /*
1090  *      await_parallel(waitflg)
1091  *
1092  *      Waits for parallel children to exit and finishes their processing.
1093  *      If waitflg is false, the function returns after update_delay.
1094  *
1095  *      Parameters:
1096  *              waitflg         dwight
1097  */
1098 void
1099 await_parallel(Boolean waitflg)
1100 {
1101         Boolean         nohang;
1102         pid_t           pid;
1103         int             status;
1104         Running         rp;
1105         int             waiterr;
1106 
1107         nohang = false;
1108         for ( ; ; ) {
1109                 if (!nohang) {
1110                         (void) alarm((int) update_delay);
1111                 }
1112                 pid = waitpid((pid_t)-1,
1113                               &status,
1114                               nohang ? WNOHANG : 0);
1115                 waiterr = errno;
1116                 if (!nohang) {
1117                         (void) alarm(0);
1118                 }
1119                 if (pid <= 0) {
1120                         if (waiterr == EINTR) {
1121                                 if (waitflg) {
1122                                         continue;
1123                                 } else {
1124                                         return;
1125                                 }
1126                         } else {
1127                                 return;
1128                         }
1129                 }
1130                 for (rp = running_list;
1131                      (rp != NULL) && (rp->pid != pid);
1132                      rp = rp->next) {
1133                         ;
1134                 }
1135                 if (rp == NULL) {
1136                         fatal(gettext("Internal error: returned child pid not in running_list"));
1137                 } else {
1138                         rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed;
1139                 }
1140                 nohang = true;
1141                 parallel_process_cnt--;
1142 
1143                 if (job_adjust_mode == ADJUST_M2) {
1144                         if (m2_release_job()) {
1145                                 job_adjust_error();
1146                         }
1147                 }
1148         }
1149 }
1150 
1151 /*
1152  *      finish_children(docheck)
1153  *
1154  *      Finishes the processing for all targets which were running
1155  *      and have now completed.
1156  *
1157  *      Parameters:
1158  *              docheck         Completely check the finished target
1159  *
1160  *      Static variables used:
1161  *              running_tail    The tail of the running list
1162  *
1163  *      Global variables used:
1164  *              continue_after_error  -k flag
1165  *              fatal_in_progress  True if we are finishing up after fatal err
1166  *              running_list    List of running processes
1167  */
1168 void
1169 finish_children(Boolean docheck)
1170 {
1171         int             cmds_length;
1172         Property        line;
1173         Property        line2;
1174         struct stat     out_buf;
1175         Running         rp;
1176         Running         *rp_prev;
1177         Cmd_line        rule;
1178         Boolean         silent_flag;
1179 
1180         for (rp_prev = &running_list, rp = running_list;
1181              rp != NULL;
1182              rp = rp->next) {
1183 bypass_for_loop_inc_4:
1184                 /*
1185                  * If the state is ok or failed, then this target has
1186                  * finished building.
1187                  * In parallel_mode, output the accumulated stdout/stderr.
1188                  * Read the auto dependency stuff, handle a failed build,
1189                  * update the target, then finish the doname process for
1190                  * that target.
1191                  */
1192                 if (rp->state == build_ok || rp->state == build_failed) {
1193                         *rp_prev = rp->next;
1194                         if (rp->next == NULL) {
1195                                 running_tail = rp_prev;
1196                         }
1197                         if ((line2 = rp->command) == NULL) {
1198                                 line2 = get_prop(rp->target->prop, line_prop);
1199                         }
1200 
1201 
1202                         /*
1203                          * Check if there were any job output
1204                          * from the parallel build.
1205                          */
1206                         if (rp->stdout_file != NULL) {
1207                                 if (stat(rp->stdout_file, &out_buf) < 0) {
1208                                         fatal(gettext("stat of %s failed: %s"),
1209                                             rp->stdout_file,
1210                                             errmsg(errno));
1211                                 }
1212 
1213                                 if ((line2 != NULL) &&
1214                                     (out_buf.st_size > 0)) {
1215                                         cmds_length = 0;
1216                                         for (rule = line2->body.line.command_used,
1217                                                  silent_flag = silent;
1218                                              rule != NULL;
1219                                              rule = rule->next) {
1220                                                 cmds_length += rule->command_line->hash.length + 1;
1221                                                 silent_flag = BOOLEAN(silent_flag || rule->silent);
1222                                         }
1223                                         if (out_buf.st_size != cmds_length || silent_flag ||
1224                                             output_mode == txt2_mode) {
1225                                                 dump_out_file(rp->stdout_file, false);
1226                                         }
1227                                 }
1228                                 (void) unlink(rp->stdout_file);
1229                                 retmem_mb(rp->stdout_file);
1230                                 rp->stdout_file = NULL;
1231                         }
1232 
1233                         if (!out_err_same && (rp->stderr_file != NULL)) {
1234                                 if (stat(rp->stderr_file, &out_buf) < 0) {
1235                                         fatal(gettext("stat of %s failed: %s"),
1236                                             rp->stderr_file,
1237                                             errmsg(errno));
1238                                 }
1239                                 if ((line2 != NULL) &&
1240                                     (out_buf.st_size > 0)) {
1241                                         dump_out_file(rp->stderr_file, true);
1242                                 }
1243                                 (void) unlink(rp->stderr_file);
1244                                 retmem_mb(rp->stderr_file);
1245                                 rp->stderr_file = NULL;
1246                         }
1247                         
1248                         check_state(rp->temp_file);
1249                         if (rp->temp_file != NULL) {
1250                                 free_name(rp->temp_file);
1251                         }
1252                         rp->temp_file = NULL;
1253                         if (rp->state == build_failed) {
1254                                 line = get_prop(rp->target->prop, line_prop);
1255                                 if (line != NULL) {
1256                                         line->body.line.command_used = NULL;
1257                                 }
1258                                 if (continue_after_error ||
1259                                     fatal_in_progress ||
1260                                     !docheck) {
1261                                         warning(gettext("Command failed for target `%s'"),
1262                                                 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1263                                         build_failed_seen = true;
1264                                 } else {
1265                                         /*
1266                                          * XXX??? - DMake needs to exit(),
1267                                          * but shouldn't call fatal().
1268                                          */
1269 #ifdef PRINT_EXIT_STATUS
1270                                         warning("I'm in finish_children. rp->state == build_failed.");
1271 #endif
1272 
1273                                         fatal(gettext("Command failed for target `%s'"),
1274                                                 rp->command ? line2->body.line.target->string_mb : rp->target->string_mb);
1275                                 }
1276                         }
1277                         if (!docheck) {
1278                                 delete_running_struct(rp);
1279                                 rp = *rp_prev;
1280                                 if (rp == NULL) {
1281                                         break;
1282                                 } else {
1283                                         goto bypass_for_loop_inc_4;
1284                                 }
1285                         }
1286                         update_target(get_prop(rp->target->prop, line_prop),
1287                                       rp->state);
1288                         finish_doname(rp);
1289                         delete_running_struct(rp);
1290                         rp = *rp_prev;
1291                         if (rp == NULL) {
1292                                 break;
1293                         } else {
1294                                 goto bypass_for_loop_inc_4;
1295                         }
1296                 } else {
1297                         rp_prev = &rp->next;
1298                 }
1299         }
1300 }
1301 
1302 /*
1303  *      dump_out_file(filename, err)
1304  *
1305  *      Write the contents of the file to stdout, then unlink the file.
1306  *
1307  *      Parameters:
1308  *              filename        Name of temp file containing output
1309  *
1310  *      Global variables used:
1311  */
1312 static void
1313 dump_out_file(char *filename, Boolean err)
1314 {
1315         int             chars_read;
1316         char            copybuf[BUFSIZ];
1317         int             fd;
1318         int             out_fd = (err ? 2 : 1);
1319 
1320         if ((fd = open(filename, O_RDONLY)) < 0) {
1321                 fatal(gettext("open failed for output file %s: %s"),
1322                       filename,
1323                       errmsg(errno));
1324         }
1325         if (!silent && output_mode != txt2_mode) {
1326                 (void) fprintf(err ? stderr : stdout,
1327                                err ?
1328                                 gettext("%s --> Job errors\n") :
1329                                 gettext("%s --> Job output\n"),
1330                                local_host);
1331                 (void) fflush(err ? stderr : stdout);
1332         }
1333         for (chars_read = read(fd, copybuf, BUFSIZ);
1334              chars_read > 0;
1335              chars_read = read(fd, copybuf, BUFSIZ)) {
1336                 /*
1337                  * Read buffers from the source file until end or error.
1338                  */
1339                 if (write(out_fd, copybuf, chars_read) < 0) {
1340                         fatal(gettext("write failed for output file %s: %s"),
1341                               filename,
1342                               errmsg(errno));
1343                 }
1344         }
1345         (void) close(fd);
1346         (void) unlink(filename);
1347 }
1348 
1349 /*
1350  *      finish_doname(rp)
1351  *
1352  *      Completes the processing for a target which was left running.
1353  *
1354  *      Parameters:
1355  *              rp              Running list entry for target
1356  *
1357  *      Global variables used:
1358  *              debug_level     Debug flag
1359  *              recursion_level Indentation for debug output
1360  */
1361 static void
1362 finish_doname(Running rp)
1363 {
1364         int             auto_count = rp->auto_count;
1365         Name            *automatics = rp->automatics;
1366         Doname          result = rp->state;
1367         Name            target = rp->target;
1368         Name            true_target = rp->true_target;
1369         Property        *conditionals;
1370 
1371         recursion_level = rp->recursion_level;
1372         if (result == build_ok) {
1373                 if (true_target == NULL) {
1374                         (void) printf("Target = %s\n", target->string_mb);
1375                         (void) printf(" State = %d\n", result);
1376                         fatal("Internal error: NULL true_target in finish_doname");
1377                 }
1378                 /* If all went OK, set a nice timestamp */
1379                 if (true_target->stat.time == file_doesnt_exist) {
1380                         true_target->stat.time = file_max_time;
1381                 }
1382         }
1383         target->state = result;
1384         if (target->is_member) {
1385                 Property member;
1386 
1387                 /* Propagate the timestamp from the member file to the member */
1388                 if ((target->stat.time != file_max_time) &&
1389                     ((member = get_prop(target->prop, member_prop)) != NULL) &&
1390                     (exists(member->body.member.member) > file_doesnt_exist)) {
1391                         target->stat.time =
1392 /*
1393                           exists(member->body.member.member);
1394  */
1395                           member->body.member.member->stat.time;
1396                 }
1397         }
1398         /*
1399          * Check if we found any new auto dependencies when we
1400          * built the target.
1401          */
1402         if ((result == build_ok) && check_auto_dependencies(target,
1403                                                             auto_count,
1404                                                             automatics)) {
1405                 if (debug_level > 0) {
1406                         (void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"),
1407                                       recursion_level,
1408                                       "",
1409                                       true_target->string_mb);
1410                 }
1411                 target->rechecking_target = true;
1412                 target->state = build_running;
1413 
1414                 /* [tolik, Tue Mar 25 1997]
1415                  * Fix for bug 4038824:
1416                  *       command line options set by conditional macros get dropped
1417                  * rp->conditional_cnt and rp->conditional_targets must be copied
1418                  * to new 'rp' during add_pending(). Set_conditionals() stores
1419                  * rp->conditional_targets to the global variable 'conditional_targets'
1420                  * Add_pending() will use this variable to set up 'rp'.
1421                  */
1422                 conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets);
1423                 add_pending(target,
1424                             recursion_level,
1425                             rp->do_get,
1426                             rp->implicit,
1427                             true);
1428                 reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals);
1429         }
1430 }
1431 
1432 /*
1433  *      new_running_struct()
1434  *
1435  *      Constructor for Running struct. Creates a structure and initializes
1436  *      its fields.
1437  *
1438  */
1439 static Running new_running_struct()
1440 {
1441         Running         rp;
1442 
1443         rp = ALLOC(Running);
1444         rp->target = NULL;
1445         rp->true_target = NULL;
1446         rp->command = NULL;
1447         rp->sprodep_value = NULL;
1448         rp->sprodep_env = NULL;
1449         rp->auto_count = 0;
1450         rp->automatics = NULL;
1451         rp->pid = -1;
1452         rp->job_msg_id = -1;
1453         rp->stdout_file = NULL;
1454         rp->stderr_file = NULL;
1455         rp->temp_file = NULL;
1456         rp->next = NULL;
1457         return rp;
1458 }
1459 
1460 /*
1461  *      add_running(target, true_target, command, recursion_level, auto_count,
1462  *                                      automatics, do_get, implicit)
1463  *
1464  *      Adds a record on the running list for this target, which
1465  *      was just spawned and is running.
1466  *
1467  *      Parameters:
1468  *              target          Target being built
1469  *              true_target     True target for target
1470  *              command         Running command.
1471  *              recursion_level Debug indentation level
1472  *              auto_count      Count of automatic dependencies
1473  *              automatics      List of automatic dependencies
1474  *              do_get          Sccs get flag
1475  *              implicit        Implicit flag
1476  *
1477  *      Static variables used:
1478  *              running_tail    Tail of running list
1479  *              process_running PID of process
1480  *
1481  *      Global variables used:
1482  *              current_line    Current line for target
1483  *              current_target  Current target being built
1484  *              stderr_file     Temporary file for stdout
1485  *              stdout_file     Temporary file for stdout
1486  *              temp_file_name  Temporary file for auto dependencies
1487  */
1488 void
1489 add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit)
1490 {
1491         Running         rp;
1492         Name            *p;
1493 
1494         rp = new_running_struct();
1495         rp->state = build_running;
1496         rp->target = target;
1497         rp->true_target = true_target;
1498         rp->command = command;
1499         rp->recursion_level = recursion_level;
1500         rp->do_get = do_get;
1501         rp->implicit = implicit;
1502         rp->auto_count = auto_count;
1503         if (auto_count > 0) {
1504                 rp->automatics = (Name *) getmem(auto_count * sizeof (Name));
1505                 for (p = rp->automatics; auto_count > 0; auto_count--) {
1506                         *p++ = *automatics++;
1507                 }
1508         } else {
1509                 rp->automatics = NULL;
1510         }
1511         {
1512                 rp->pid = process_running;
1513                 process_running = -1;
1514                 childPid = -1;
1515         }
1516         rp->job_msg_id = job_msg_id;
1517         rp->stdout_file = stdout_file;
1518         rp->stderr_file = stderr_file;
1519         rp->temp_file = temp_file_name;
1520         rp->redo = false;
1521         rp->next = NULL;
1522         store_conditionals(rp);
1523         stdout_file = NULL;
1524         stderr_file = NULL;
1525         temp_file_name = NULL;
1526         current_target = NULL;
1527         current_line = NULL;
1528         *running_tail = rp;
1529         running_tail = &rp->next;
1530 }
1531 
1532 /*
1533  *      add_pending(target, recursion_level, do_get, implicit, redo)
1534  *
1535  *      Adds a record on the running list for a pending target
1536  *      (waiting for its dependents to finish running).
1537  *
1538  *      Parameters:
1539  *              target          Target being built
1540  *              recursion_level Debug indentation level
1541  *              do_get          Sccs get flag
1542  *              implicit        Implicit flag
1543  *              redo            True if this target is being redone
1544  *
1545  *      Static variables used:
1546  *              running_tail    Tail of running list
1547  */
1548 void
1549 add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo)
1550 {
1551         Running         rp;
1552         rp = new_running_struct();
1553         rp->state = build_pending;
1554         rp->target = target;
1555         rp->recursion_level = recursion_level;
1556         rp->do_get = do_get;
1557         rp->implicit = implicit;
1558         rp->redo = redo;
1559         store_conditionals(rp);
1560         *running_tail = rp;
1561         running_tail = &rp->next;
1562 }
1563 
1564 /*
1565  *      add_serial(target, recursion_level, do_get, implicit)
1566  *
1567  *      Adds a record on the running list for a target which must be
1568  *      executed in serial after others have finished.
1569  *
1570  *      Parameters:
1571  *              target          Target being built
1572  *              recursion_level Debug indentation level
1573  *              do_get          Sccs get flag
1574  *              implicit        Implicit flag
1575  *
1576  *      Static variables used:
1577  *              running_tail    Tail of running list
1578  */
1579 void
1580 add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1581 {
1582         Running         rp;
1583 
1584         rp = new_running_struct();
1585         rp->target = target;
1586         rp->recursion_level = recursion_level;
1587         rp->do_get = do_get;
1588         rp->implicit = implicit;
1589         rp->state = build_serial;
1590         rp->redo = false;
1591         store_conditionals(rp);
1592         *running_tail = rp;
1593         running_tail = &rp->next;
1594 }
1595 
1596 /*
1597  *      add_subtree(target, recursion_level, do_get, implicit)
1598  *
1599  *      Adds a record on the running list for a target which must be
1600  *      executed in isolation after others have finished.
1601  *
1602  *      Parameters:
1603  *              target          Target being built
1604  *              recursion_level Debug indentation level
1605  *              do_get          Sccs get flag
1606  *              implicit        Implicit flag
1607  *
1608  *      Static variables used:
1609  *              running_tail    Tail of running list
1610  */
1611 void
1612 add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit)
1613 {
1614         Running         rp;
1615 
1616         rp = new_running_struct();
1617         rp->target = target;
1618         rp->recursion_level = recursion_level;
1619         rp->do_get = do_get;
1620         rp->implicit = implicit;
1621         rp->state = build_subtree;
1622         rp->redo = false;
1623         store_conditionals(rp);
1624         *running_tail = rp;
1625         running_tail = &rp->next;
1626 }
1627 
1628 /*
1629  *      store_conditionals(rp)
1630  *
1631  *      Creates an array of the currently active targets with conditional
1632  *      macros (found in the chain conditional_targets) and puts that
1633  *      array in the Running struct.
1634  *
1635  *      Parameters:
1636  *              rp              Running struct for storing chain
1637  *
1638  *      Global variables used:
1639  *              conditional_targets  Chain of current dynamic conditionals
1640  */
1641 static void
1642 store_conditionals(Running rp)
1643 {
1644         int             cnt;
1645         Chain           cond_name;
1646 
1647         if (conditional_targets == NULL) {
1648                 rp->conditional_cnt = 0;
1649                 rp->conditional_targets = NULL;
1650                 return;
1651         }
1652         cnt = 0;
1653         for (cond_name = conditional_targets;
1654              cond_name != NULL;
1655              cond_name = cond_name->next) {
1656                 cnt++;
1657         }
1658         rp->conditional_cnt = cnt;
1659         rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name));
1660         for (cond_name = conditional_targets;
1661              cond_name != NULL;
1662              cond_name = cond_name->next) {
1663                 rp->conditional_targets[--cnt] = cond_name->name;
1664         }
1665 }
1666 
1667 /*
1668  *      parallel_ok(target, line_prop_must_exists)
1669  *
1670  *      Returns true if the target can be run in parallel
1671  *
1672  *      Return value:
1673  *                              True if can run in parallel
1674  *
1675  *      Parameters:
1676  *              target          Target being tested
1677  *
1678  *      Global variables used:
1679  *              all_parallel    True if all targets default to parallel
1680  *              only_parallel   True if no targets default to parallel
1681  */
1682 Boolean
1683 parallel_ok(Name target, Boolean line_prop_must_exists)
1684 {
1685         Boolean         assign;
1686         Boolean         make_refd;
1687         Property        line;
1688         Cmd_line        rule;
1689 
1690         assign = make_refd = false;
1691         if (((line = get_prop(target->prop, line_prop)) == NULL) &&
1692             line_prop_must_exists) {
1693                 return false;
1694         }
1695         if (line != NULL) {
1696                 for (rule = line->body.line.command_used;
1697                      rule != NULL;
1698                      rule = rule->next) {
1699                         if (rule->assign) {
1700                                 assign = true;
1701                         } else if (rule->make_refd) {
1702                                 make_refd = true;
1703                         }
1704                 }
1705         }
1706         if (assign) {
1707                 return false;
1708         } else if (target->parallel) {
1709                 return true;
1710         } else if (target->no_parallel) {
1711                 return false;
1712         } else if (all_parallel) {
1713                 return true;
1714         } else if (only_parallel) {
1715                 return false;
1716         } else if (make_refd) {
1717                 return false;
1718         } else {
1719                 return true;
1720         }
1721 }
1722 
1723 /*
1724  *      is_running(target)
1725  *
1726  *      Returns true if the target is running.
1727  *
1728  *      Return value:
1729  *                              True if target is running
1730  *
1731  *      Parameters:
1732  *              target          Target to check
1733  *
1734  *      Global variables used:
1735  *              running_list    List of running processes
1736  */
1737 Boolean
1738 is_running(Name target)
1739 {
1740         Running         rp;
1741 
1742         if (target->state != build_running) {
1743                 return false;
1744         }
1745         for (rp = running_list;
1746              rp != NULL && target != rp->target;
1747              rp = rp->next);
1748         if (rp == NULL) {
1749                 return false;
1750         } else {
1751                 return (rp->state == build_running) ? true : false;
1752         }
1753 }
1754 
1755 /*
1756  * This function replaces the makesh binary.
1757  */
1758  
1759 
1760 static pid_t
1761 run_rule_commands(char *host, char **commands)
1762 {
1763         Boolean         always_exec;
1764         Name            command;
1765         Boolean         ignore;
1766         int             length;
1767         Doname          result;
1768         Boolean         silent_flag;
1769         wchar_t         *tmp_wcs_buffer;
1770 
1771         childPid = fork();
1772         switch (childPid) {
1773         case -1:        /* Error */
1774                 fatal(gettext("Could not fork child process for dmake job: %s"),
1775                       errmsg(errno));
1776                 break;
1777         case 0:         /* Child */
1778                 /* To control the processed targets list is not the child's business */
1779                 running_list = NULL;
1780                 if(out_err_same) {
1781                         redirect_io(stdout_file, (char*)NULL);
1782                 } else {
1783                         redirect_io(stdout_file, stderr_file);
1784                 }
1785                 for (commands = commands;
1786                      (*commands != (char *)NULL);
1787                      commands++) {
1788                         silent_flag = silent;
1789                         ignore = false;
1790                         always_exec = false;
1791                         while ((**commands == (int) at_char) ||
1792                                (**commands == (int) hyphen_char) ||
1793                                (**commands == (int) plus_char)) {
1794                                 if (**commands == (int) at_char) {
1795                                         silent_flag = true;
1796                                 }
1797                                 if (**commands == (int) hyphen_char) {
1798                                         ignore = true;
1799                                 }
1800                                 if (**commands == (int) plus_char) {
1801                                         always_exec = true;
1802                                 }
1803                                 (*commands)++;
1804                         }
1805                         if ((length = strlen(*commands)) >= MAXPATHLEN) {
1806                                 tmp_wcs_buffer = ALLOC_WC(length + 1);
1807                                 (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1);
1808                                 command = GETNAME(tmp_wcs_buffer, FIND_LENGTH);
1809                                 retmem(tmp_wcs_buffer);
1810                         } else {
1811                                 MBSTOWCS(wcs_buffer, *commands);
1812                                 command = GETNAME(wcs_buffer, FIND_LENGTH);
1813                         }
1814                         if ((command->hash.length > 0) &&
1815                             !silent_flag) {
1816                                 (void) printf("%s\n", command->string_mb);
1817                         }
1818                         result = dosys(command,
1819                                        ignore,
1820                                        false,
1821                                        false, /* bugs #4085164 & #4990057 */
1822                                        /* BOOLEAN(silent_flag && ignore), */
1823                                        always_exec, 
1824                                        (Name) NULL);
1825                         if (result == build_failed) {
1826                                 if (silent_flag) {
1827                                         (void) printf(gettext("The following command caused the error:\n%s\n"), command->string_mb);
1828                                 }
1829                                 if (!ignore) {
1830                                         _exit(1);
1831                                 }
1832                         }
1833                 }
1834                 _exit(0);
1835                 break;
1836         default:
1837                 break;
1838         }
1839         return childPid;
1840 }
1841 
1842 static void
1843 maybe_reread_make_state(void)
1844 {
1845         /* Copying dosys()... */
1846         if (report_dependencies_level == 0) {
1847                 make_state->stat.time = file_no_time;
1848                 (void) exists(make_state);
1849                 if (make_state_before == make_state->stat.time) {
1850                         return;
1851                 }
1852                 makefile_type = reading_statefile;
1853                 if (read_trace_level > 1) {
1854                         trace_reader = true;
1855                 }
1856                 temp_file_number++;
1857                 (void) read_simple_file(make_state,
1858                                         false,
1859                                         false,
1860                                         false,
1861                                         false,
1862                                         false,
1863                                         true);
1864                 trace_reader = false;
1865         }
1866 }
1867 
1868 
1869 static void
1870 delete_running_struct(Running rp)
1871 {
1872         if ((rp->conditional_cnt > 0) &&
1873             (rp->conditional_targets != NULL)) {
1874                 retmem_mb((char *) rp->conditional_targets);
1875         }
1876 /**/
1877         if ((rp->auto_count > 0) &&
1878             (rp->automatics != NULL)) {
1879                 retmem_mb((char *) rp->automatics);
1880         }
1881 /**/
1882         if(rp->sprodep_value) {
1883                 free_name(rp->sprodep_value);
1884         }
1885         if(rp->sprodep_env) {
1886                 retmem_mb(rp->sprodep_env);
1887         }
1888         retmem_mb((char *) rp);
1889 
1890 }
1891 
1892